We save positional information in the main utility table. Not only
+can we store much more information in but it's also
+more efficient.
+--ldx]]--
+
+local concat, format = table.concat, string.format
+local texprint, ctxcatcodes = tex.print, tex.ctxcatcodes
+local lpegmatch = lpeg.match
+
+jobpositions = jobpositions or { }
+jobpositions.collected = jobpositions.collected or { }
+jobpositions.tobesaved = jobpositions.tobesaved or { }
+
+-- these are global since they are used often at the tex end
+
+-- \the\dimexpr #2\ifnum\positionanchormode=\plusone-\MPx\pageanchor\fi\relax
+-- \the\dimexpr #3\ifnum\positionanchormode=\plusone-\MPy\pageanchor\fi\relax
+
+ptbs, pcol = jobpositions.tobesaved, jobpositions.collected -- global
+
+local dx, dy = "0pt", "0pt"
+
+local function initializer()
+ ptbs, pcol = jobpositions.tobesaved, jobpositions.collected
+ local p = pcol["page:0"] -- page:1
+ if p then
+-- to be checked !
+--~ dx, dy = p[2] or "0pt", p[3] or "0pt"
+ end
+end
+
+job.register('jobpositions.collected', jobpositions.tobesaved, initializer)
+
+function jobpositions.copy(target,source)
+ jobpositions.collected[target] = jobpositions.collected[source] or ptbs[source]
+end
+
+function jobpositions.replace(name,...)
+ jobpositions.collected[name] = {...}
+end
+
+function jobpositions.doifelse(name)
+ commands.testcase(jobpositions.collected[name] or ptbs[name])
+end
+
+function jobpositions.MPp(id) local jpi = pcol[id] or ptbs[id] texprint(ctxcatcodes,(jpi and jpi[1]) or '0' ) end
+function jobpositions.MPx(id) local jpi = pcol[id] or ptbs[id] texprint(ctxcatcodes,(jpi and jpi[2]) or '0pt') end
+function jobpositions.MPy(id) local jpi = pcol[id] or ptbs[id] texprint(ctxcatcodes,(jpi and jpi[3]) or '0pt') end
+function jobpositions.MPw(id) local jpi = pcol[id] or ptbs[id] texprint(ctxcatcodes,(jpi and jpi[4]) or '0pt') end
+function jobpositions.MPh(id) local jpi = pcol[id] or ptbs[id] texprint(ctxcatcodes,(jpi and jpi[5]) or '0pt') end
+function jobpositions.MPd(id) local jpi = pcol[id] or ptbs[id] texprint(ctxcatcodes,(jpi and jpi[6]) or '0pt') end
+
+
+function jobpositions.MPx(id)
+ local jpi = pcol[id] or ptbs[id]
+ local x = jpi and jpi[2]
+ if x then
+ texprint(ctxcatcodes,format('\\the\\dimexpr%s-%s\\relax',x,dx)) -- no space after dimexpr !
+ else
+ texprint(ctxcatcodes,'0pt')
+ end
+end
+
+function jobpositions.MPy(id)
+ local jpi = pcol[id] or ptbs[id]
+ local y = jpi and jpi[3]
+ if y then
+ texprint(ctxcatcodes,format('\\the\\dimexpr%s-%s\\relax',y,dy)) -- no space after dimexpr !
+ else
+ texprint(ctxcatcodes,'0pt')
+ end
+end
+
+-- the following are only for MP so there we can leave out the pt
+
+-- can be writes and no format needed any more
+
+function jobpositions.MPxy(id)
+ local jpi = pcol[id] or ptbs[id]
+ if jpi then
+ texprint(ctxcatcodes,format('(%s-%s,%s-%s)',jpi[2],dx,jpi[3],dy))
+--~ texprint(ctxcatcodes,'(',jpi[2],'-',dx,',',jpi[3],'-',dy,')')
+ else
+ texprint(ctxcatcodes,'(0,0)')
+ end
+end
+
+function jobpositions.MPll(id)
+ local jpi = pcol[id] or ptbs[id]
+ if jpi then
+ texprint(ctxcatcodes,format('(%s-%s,%s-%s-%s)',jpi[2],dx,jpi[3],jpi[6],dy))
+--~ texprint(ctxcatcodes,'(',jpi[2],'-',dx,',',jpi[3],'-',jpi[6],'-',dy,')')
+ else
+ texprint(ctxcatcodes,'(0,0)')
+ end
+end
+
+function jobpositions.MPlr(id)
+ local jpi = pcol[id] or ptbs[id]
+ if jpi then
+ texprint(ctxcatcodes,format('(%s+%s-%s,%s-%s-%s)',jpi[2],jpi[4],dx,jpi[3],jpi[6],dy))
+--~ texprint(ctxcatcodes,'(',jpi[2],'+',jpi[4],'-',dx,',',jpi[3],'-',jpi[6],'-',dy,')')
+ else
+ texprint(ctxcatcodes,'(0,0)')
+ end
+end
+
+function jobpositions.MPur(id)
+ local jpi = pcol[id] or ptbs[id]
+ if jpi then
+ texprint(ctxcatcodes,format('(%s+%s-%s,%s+%s-%s)',jpi[2],jpi[4],dx,jpi[3],jpi[5],dy))
+--~ texprint(ctxcatcodes,'(',jpi[2],'+',jpi[4],'-',dx,',',jpi[3],'+',jpi[5],'-',dy,')')
+ else
+ texprint(ctxcatcodes,'(0,0)')
+ end
+end
+
+function jobpositions.MPul(id)
+ local jpi = pcol[id] or ptbs[id]
+ if jpi then
+ texprint(ctxcatcodes,format('(%s-%s,%s+%s-%s)',jpi[2],dx,jpi[3],jpi[5],dy))
+--~ texprint(ctxcatcodes,'(',jpi[2],'-',dx,',',jpi[3],'+',jpi[5],'-',dy,')')
+ else
+ texprint(ctxcatcodes,'(0,0)')
+ end
+end
+
+function jobpositions.MPpos(id)
+ local jpi = pcol[id] or ptbs[id]
+ if jpi then
+ texprint(ctxcatcodes,concat(jpi,',',1,6))
+ else
+ texprint(ctxcatcodes,'0,0,0,0,0,0')
+ end
+end
+
+local splitter = lpeg.Ct(lpeg.splitat(","))
+
+function jobpositions.MPplus(id,n,default)
+ local jpi = pcol[id] or ptbs[id]
+ if not jpi then
+ texprint(ctxcatcodes,default)
+ else
+ local split = jpi[0]
+ if not split then
+ split = lpegmatch(splitter,jpi[7])
+ jpi[0] = split
+ end
+ texprint(ctxcatcodes,split[n] or default)
+ end
+end
+
+function jobpositions.MPrest(id,default)
+ local jpi = pcol[id] or ptbs[id]
+ -- texprint(ctxcatcodes,(jpi and jpi[7] and concat(jpi,",",7,#jpi)) or default)
+ texprint(ctxcatcodes,(jpi and jpi[7]) or default)
+end
diff --git a/tex/context/base/anch-pos.mkii b/tex/context/base/anch-pos.mkii
new file mode 100644
index 000000000..589c4aa26
--- /dev/null
+++ b/tex/context/base/anch-pos.mkii
@@ -0,0 +1,877 @@
+%D \module
+%D [ file=anch-pos,
+%D version=1999.08.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Positioning Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% needs a cleanup, things may change; we also need to move the mp
+% related code to meta-pos
+
+% shorter tags, ..:achtergrond:.. etc in pos actions
+
+% dubbele text- * pos's eruit
+
+% class pos -> als gelijk aan vorige, dan niet niet definieren
+% en erven, maw:
+%
+% 1 -> opslaan
+% 2 -> undef, dus == prev
+% 3 -> undef, dus == prev
+% 4 -> opslaan
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Positioning}
+
+% todo: topskip als optie voor eerste regel achtergrond
+% todo: build pos layers on top of layers
+% todo: positionlayer pos van text-1 etc delen
+
+%D Although \TEX\ has a rather powerful channel to the outside
+%D world, called \type {\special}, real communication with
+%D other programs is complicated by the fact that no positional
+%D information is available. Mid 1999, I discussed this with
+%D \THANH, the author of \PDFTEX, and after some experiments,
+%D \PDFTEX\ was extended with a simple but effective mechanism,
+%D that provided positional information. The interesting
+%D thought is that, although \TEX\ is frozen, similar
+%D functionality could have been achieved with \type
+%D {\specials} and an additional \DVI\ postprocessor.
+%D
+%D Since we want to be as compatible as can be, \CONTEXT\ will
+%D support both methods, although the development is primarily
+%D driven by the \PDFTEX\ way of doing things. Since the
+%D mechanism is basically not limited to one application, for
+%D the moment we stick to building the functionality around one
+%D \CONTEXT\ special command, but at the same time we keep our
+%D eyes open for extensions in other directions.
+%D
+%D A question that may arise when one reads this module, is to
+%D what extend these macros are generic, in the sense that they
+%D could be collected in a support module instead of a core
+%D module. Since the mechanism described here will closely
+%D cooperate with the \METAPOST\ support built in \CONTEXT,
+%D which in turn will be tightly integrated with the \CONTEXT\
+%D overlay mechanisms, I decided to write a core module instead
+%D of a support one. This makes even more sense, when one takes
+%D into account that this kind of support depends on special
+%D drivers.
+
+\unprotect
+
+%D The first application of positional information was embedded
+%D graphics. Since we are interacting with text, it made sense
+%D to take the current line height and depth into account too.
+%D This is why we have two basic position macros: one for
+%D simple positions, and one for boxes.
+%D
+%D We could have sticked to one special, and actually did so in
+%D earlier experiments, but for convenience, as well for
+%D clearness, we now have two alternatives. This approach will
+%D save us quite some bytes when storing large quantities of
+%D positional information. We save as less information as
+%D needed, that is, we save no dimensions, in a \METAPOST\
+%D friendly way.
+%D
+%D The three specials involved are:
+%D
+%D \starttyping
+%D \dosetposition {identifier}
+%D \dosetpositionwhd {identifier} {width} {height} {depth}
+%D \dosetpositionplus {identifier} {width} {height} {depth} {list}
+%D \dosetpositionpapersize {width} {height}
+%D \stoptyping
+
+\newbox\positionbox
+\newif \ifpositioning
+
+\def\POSprefix{POS::}
+
+\def\setpospxy#1#2#3#4%
+ {\@EA\xdef\csname\POSprefix#1\endcsname
+ {\number#2,%
+ \the\dimexpr#3\ifnum\positionanchormode=\plusone-\MPx\pageanchor\fi\relax,%
+ \the\dimexpr#4\ifnum\positionanchormode=\plusone-\MPy\pageanchor\fi\relax}}
+
+\def\setpospxywhd#1#2#3#4#5#6#7%
+ {\@EA\xdef\csname\POSprefix#1\endcsname
+ {\number#2,%
+ \the\dimexpr#3\ifnum\positionanchormode=\plusone-\MPx\pageanchor\fi\relax,%
+ \the\dimexpr#4\ifnum\positionanchormode=\plusone-\MPy\pageanchor\fi\relax,%
+ \the\dimexpr#5\relax,%
+ \the\dimexpr#6\relax,%
+ \the\dimexpr#7\relax}}
+
+\def\setpospxyplus#1#2#3#4#5#6#7#8%
+ {\@EA\xdef\csname\POSprefix#1\endcsname
+ {\number#2,%
+ \the\dimexpr#3\ifnum\positionanchormode=\plusone-\MPx\pageanchor\fi\relax,%
+ \the\dimexpr#4\ifnum\positionanchormode=\plusone-\MPy\pageanchor\fi\relax,%
+ \the\dimexpr#5\relax,%
+ \the\dimexpr#6\relax,%
+ \the\dimexpr#7\relax,%
+ #8}}
+
+%D This is real tricky! The page anchor is applied to the
+%D page box and therefore flushed first. So, when present, it
+%D is applied to all positions except itself.
+
+\chardef\positionanchormode=0 % don't relocate page origin
+\chardef\positionanchormode=1 % relocate page origin once
+
+%D The core set macros.
+
+\def\pxypos {\pospxy} % obsolete
+\def\pxyposwhd {\pospxywhd} % obsolete
+\def\pxyposplus{\pospxyplus} % obsolete
+
+\def\resetpositions
+ {\let\pospxy \gobblefourarguments
+ \let\pospxywhd \gobblesevenarguments
+ \let\pospxyplus\gobbleeightarguments}
+
+\def\setpositions
+ {\let\pospxy \setpospxy
+ \let\pospxywhd \setpospxywhd
+ \let\pospxyplus\setpospxyplus}
+
+%D We need to initialize.
+
+\resetpositions
+
+\addutilityreset{positions}
+
+%D Sometimes we want to trick the position handler a bit:
+
+\def\replacepospxywhd#1#2#3#4#5#6#7%
+ {\@EA\xdef\csname\POSprefix#1\endcsname
+ {\number#2,%
+ \the\dimexpr#3\relax,%
+ \the\dimexpr#4\relax,%
+ \the\dimexpr#5\relax,%
+ \the\dimexpr#6\relax,%
+ \the\dimexpr#7\relax}}
+
+%D For postprocessing purposes, we save the number of
+%D positions.
+
+\newcount\currentpositions % current number of positions
+\newcounter\totalnofpositions % total from previous run
+
+\appendtoks
+ \expanded{\savecurrentvalue\noexpand\totalnofpositions{\the\currentpositions}}%
+\to \everybye
+
+%D The next switch can be used to communicate a special
+%D situation. Positioning and associated actions can be
+%D executed any time. However, in for instance backgrounds
+%D they can be collected in a layer, for instance the text
+%D layer (especially the hidden text layer). In the case of
+%D floats, we run into problems, since the page information is
+%D not applicable when the content floats indeed. In such
+%D situations one can treat positions and graphics local.
+
+\newif\iflocalpositioning
+
+%D Watch out: sometimes a pagebreak occurs inside a float
+%D placement, so there we need to disable local mode.
+
+\appendtoks
+ \localpositioningtrue
+\to \everyinsidefloat
+
+\appendtoks
+ \localpositioningfalse
+\to \everypagebody
+
+\def\checkpositions
+ {\startnointerference
+ \protectlabels
+ \doutilities{positions}\jobname\empty\relax\relax
+ \global\let\checkpositions\relax
+ \stopnointerference}
+
+%D Since the positional values are to be fully expandable, we
+%D need to preload them as soon as possible, which is why we
+%D load the data when we start a text.
+
+\appendtoks \checkpositions \to \everystarttext
+
+%D Positions are either generated at a delayed write time
+%D (in \PDFTEX), or derived from the dvi file. The actual
+%D method is implemented in a special driver. If needed, the
+%D driver can fall back on the following macros.
+
+\def\dolazysaveposition#1#2#3#4% tag page x y
+ {\expanded{\writeutilitycommand{\noexpand\pospxy
+ {#1}{#2}{#3}{#4}}}}
+
+\def\dolazysavepositionwhd#1#2#3#4#5#6#7% tag page x y w h d
+ {\expanded{\writeutilitycommand{\noexpand\pospxywhd
+ {#1}{#2}{#3}{#4}{#5}{#6}{#7}}}}
+
+\def\dolazysavepositionplus#1#2#3#4#5#6#7#8% tag page x y w h d list
+ {\expanded{\writeutilitycommand{\noexpand\pospxyplus
+ {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}}}
+
+\def\dosaveposition#1#2#3#4% tag page x y
+ {\expanded{\immediatewriteutilitycommand{\noexpand\pospxy
+ {#1}{#2}{#3}{#4}}}}
+
+\def\dosavepositionwhd#1#2#3#4#5#6#7% tag page x y w h d
+ {\expanded{\immediatewriteutilitycommand{\noexpand\pospxywhd
+ {#1}{#2}{#3}{#4}{#5}{#6}{#7}}}}
+
+\def\dosavepositionplus#1#2#3#4#5#6#7#8% tag page x y w h d list
+ {\expanded{\immediatewriteutilitycommand{\noexpand\pospxyplus
+ {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}}}
+
+%D \macros
+%D {MPp, MPx, MPy, MPw, MPh, MPd,
+%D MPxy, MPll, MPlr, MPur, MPul, MPpos}
+%D
+%D Access to the positional information is provided by macros
+%D with short names that are clearly meant for \METAPOST.
+
+\def\MPp {\doMPxyhdwlr\doMPp }
+\def\MPx {\doMPxyhdwlr\doMPx }
+\def\MPy {\doMPxyhdwlr\doMPy }
+\def\MPw {\doMPxyhdwlr\doMPw }
+\def\MPh {\doMPxyhdwlr\doMPh }
+\def\MPd {\doMPxyhdwlr\doMPd }
+\def\MPxy {\doMPxyhdwlr\doMPxy }
+\def\MPll {\doMPxyhdwlr\doMPll }
+\def\MPlr {\doMPxyhdwlr\doMPlr }
+\def\MPur {\doMPxyhdwlr\doMPur }
+\def\MPul {\doMPxyhdwlr\doMPul }
+\def\MPpos{\doMPxyhdwlr\doMPpos}
+
+\def\doMPp #1,#2,#3,#4,#5,#6,#7\relax{#1}
+\def\doMPx #1,#2,#3,#4,#5,#6,#7\relax{#2}
+\def\doMPy #1,#2,#3,#4,#5,#6,#7\relax{#3}
+\def\doMPw #1,#2,#3,#4,#5,#6,#7\relax{#4}
+\def\doMPh #1,#2,#3,#4,#5,#6,#7\relax{#5}
+\def\doMPd #1,#2,#3,#4,#5,#6,#7\relax{#6}
+\def\doMPxy #1,#2,#3,#4,#5,#6,#7\relax{(#2,#3)}
+\def\doMPll #1,#2,#3,#4,#5,#6,#7\relax{(#2,#3-#6)}
+\def\doMPlr #1,#2,#3,#4,#5,#6,#7\relax{(#2+#4,#3-#6)}
+\def\doMPur #1,#2,#3,#4,#5,#6,#7\relax{(#2+#4,#3+#5)}
+\def\doMPul #1,#2,#3,#4,#5,#6,#7\relax{(#2,#3+#5)}
+\def\doMPpos#1,#2,#3,#4,#5,#6,#7\relax{#1,#2,#3,#4,#5,#6}
+
+\def\doMPxyhdwlr#1#2%
+ {\ifcsname\POSprefix#2\endcsname
+ \@EA\@EA\@EA#1\csname\POSprefix#2\endcsname,0pt,0pt,0pt,0pt\relax
+ \else
+ #10,0pt,0pt,0pt,0pt,0pt,0pt\relax
+ \fi}
+
+%D \macros
+%D {MPplus, MPrest, MPv, MPvv}
+%D
+%D Since we will probably keep on extending, we provide a
+%D general extension macro. The plus alternative takes an
+%D extra argument, denoting what additional parameter to pick
+%D up. So, the third extra is fetched with,
+%D
+%D \starttyping
+%D \MPplus{identifier}{3}{default}
+%D \stoptyping
+%D
+%D All extras (comma separated) are fetched with:
+%D
+%D \starttyping
+%D \MPrest{identifier}
+%D \stoptyping
+%D
+%D The extra parameters are not treated.
+
+\def\MPplus {\MPdoplus\doMPplus}
+\def\MPrest#1{\MPdoplus\doMPrest{#1}{}}
+
+\def\MPdoplus#1#2#3#4%
+ {\ifcsname\POSprefix#2\endcsname
+ \@EA\@EA\@EA#1\csname\POSprefix#2\endcsname,,,,,,,,,\relax{#3}%
+ \else
+ #4%
+ \fi}
+
+\def\doMPplus#1,#2,#3,#4,#5,#6,%
+ {\dodoMPplus}
+
+\def\dodoMPplus#1,#2,#3,#4,#5,#6,#7,#8\relax#9%
+ {\ifcase#9\or#1\or#2\or#3\or#4\or#5\or#6\or#7\else\dododoMPplus#8\relax{#9}\fi}
+
+\def\dododoMPplus#1,#2,#3,#4,#5,#6,#7,#8\relax#9%
+ {\ifcase#9\or\or\or\or\or\or\or\or#1\or#2\or#3\or#4\or#5\or#6\or#7\fi}
+
+\def\doMPrest#1,#2,#3,#4,#5,#6,#7,,#8\relax#9%
+ {#7}
+
+%D \macros
+%D {MPanchor}
+%D
+%D For readability we define a few synonyms:
+
+\def\MPanchor{\MPpos}
+
+%D \macros
+%D {POSp, POSx, POSy, POSh, POSd, POSw}
+%D
+%D and:
+
+\def\POSp{\MPp} \def\POSx{\MPx} \def\POSy{\MPy}
+\def\POSh{\MPh} \def\POSd{\MPd} \def\POSw{\MPw}
+
+%D There are two low level positioning macros. Both store the
+%D position as well as execute an action associated with that
+%D position.
+
+\def\initializenextposition
+ {\ifpositioning \else
+ \global\positioningtrue
+ \dosetpositionpapersize
+ {\printpaperwidth }%
+ {\printpaperheight}%
+ \fi
+ \global\advance\currentpositions\plusone}
+
+\def\setpositiononly#1%
+ {\iftrialtypesetting
+ % nothing
+ \else
+ \initializenextposition
+ \def\currentposition{#1}%
+ \dosetposition\currentposition
+ \fi}
+
+\def\setposition#1%
+ {\iftrialtypesetting
+ % nothing
+ \else
+ \initializenextposition
+ \def\currentposition{#1}%
+ \dosetposition\currentposition
+ \traceposstring\llap\green{\currentposition>}%
+ \dopositionaction\currentposition
+ \fi}
+
+\def\setpositiondata#1#2#3#4%
+ {\iftrialtypesetting \else
+ \initializenextposition
+ \hbox
+ {\def\currentposition{#1}%
+ \dosetpositionwhd\currentposition
+ {\the\dimexpr#2\relax}%
+ {\the\dimexpr#3\relax}%
+ {\the\dimexpr#4\relax}%
+ \traceposstring\llap\green{\currentposition>}%
+ \dopositionaction\currentposition
+ \hss}%
+ \fi}
+
+\def\setpositionbox#1%
+ {\dowithnextbox
+ {\iftrialtypesetting
+ \flushnextbox
+ \else
+ \initializenextposition
+ \hbox to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionwhd\currentposition
+ {\the\nextboxwd}%
+ {\the\nextboxht}%
+ {\the\nextboxdp}%
+ \traceposstring\llap\green{\currentposition>}%
+ \setbox\positionbox\flushnextbox
+ \dopositionaction\currentposition
+ \box\positionbox
+ \hss}%
+ \fi}}
+
+\def\setpositiondataplus#1#2#3#4#5%
+ {\iftrialtypesetting \else
+ \initializenextposition
+ \hbox % bug: to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition
+ {\the\dimexpr#2\relax}%
+ {\the\dimexpr#3\relax}%
+ {\the\dimexpr#4\relax}%
+ {#5}%
+ \traceposstring\rlap\magenta{<\currentposition}%
+ \dopositionaction\currentposition
+ \hss}%
+ \fi}
+
+\def\setpositionplus#1#2%
+ {\dowithnextbox
+ {\iftrialtypesetting
+ \flushnextbox
+ \else
+ \initializenextposition
+ \hbox to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition
+ {\the\nextboxwd}%
+ {\the\nextboxht}%
+ {\the\nextboxdp}%
+ {#2}%
+ \traceposstring\rlap\magenta{<\currentposition}%
+ \setbox\positionbox\flushnextbox
+ \dopositionaction\currentposition
+ \box\positionbox
+ \hss}%
+ \fi}}
+
+\let\currentposition\s!unknown
+
+%D A few more low level macros take care of defining and
+%D recalling actions. We could save this information in the
+%D position containers themselves, this would save hash
+%D entries, but at the cost of much more time consuming
+%D expansion. Actions are saved globally!
+
+\newtoks\everypositionaction
+
+\let\POSactionprefix\POSprefix
+
+\def\dosetpositionaction#1%
+ {\setgvalue{\POSactionprefix#1::}}
+
+%D The lists can become quite long (also because there can
+%D be lots of parameters passed on) so we provide a hook
+%D to clean up the list afterwards.
+
+\let\cleanuppositionaction\gobbleoneargument
+
+\def\doifpositionaction#1%
+ {\ifcsname\POSactionprefix#1::\endcsname
+ \@EA\firstofoneargument
+ \else
+ \@EA\gobbleoneargument
+ \fi}
+
+\def\doifpositionactionelse#1%
+ {\ifcsname\POSactionprefix#1::\endcsname
+ \@EA\firstoftwoarguments
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+%D We can copy a position with:
+%D
+%D \starttyping
+%D \copyposition {to} {from}
+%D \stoptyping
+%D
+%D Again, this is a global action.
+
+\def\copyposition#1#2%
+ {\ifcsname\POSprefix#2\endcsname
+ \global\@EA\let\csname\POSprefix#1\@EA\endcsname\csname\POSprefix#2\endcsname
+ \fi}
+
+%D The fact that handling positions is a two pass operation, is
+%D one of the reasons why we need to be able to test for
+%D existence, using:
+%D
+%D \starttyping
+%D \doifpositionelse {identifier} {found action} {not found action}
+%D \stoptyping
+
+\def\doifpositionelse#1%
+ {\ifcsname\POSprefix#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+%D We have now arrived at a few macros that would make sense as
+%D support macros, but ended up in the core.
+
+%D \macros
+%D {xypos}
+%D
+%D We have several macros available to save positions. Later
+%D we will see applications.
+%D
+%D \starttabulate[|l|l||]
+%D \NC \type {\xypos} \NC \NC simple position with no dimensions \NC \NR
+%D \NC \type {\hpos} \NC \NC position and characteristics of a \type {\hbox} \NC \NR
+%D \NC \type {\vpos} \NC \NC position and characteristics of a \type {\vbox} \NC \NR
+%D \NC \type {\bpos} \NC b: \NC begin point in a line \NC \NR
+%D \NC \type {\epos} \NC e: \NC end point in a line \NC \NR
+%D \NC \type {\fpos} \NC f: \NC begin point in a paragraph \NC \NR
+%D \NC \type {\tpos} \NC t: \NC end point in a paragraph \NC \NR
+%D \stoptabulate
+%D
+%D Each macro takes an identifier as argument, and the \type
+%D {\hpos} and \type {\vpos} also expect box content.
+
+% \def\xypos{\initializenextposition\dosetposition}
+
+\let\xypos\setpositiononly
+
+\def\hpos#1{\dontleavehmode\setpositionbox{#1}\hbox}
+\def\vpos#1{\setpositionbox{#1}\vbox}
+
+\def\bpos#1{\hpos{b:#1}{\strut}\ignorespaces}
+\def\epos#1{\removelastspace\hpos{e:#1}{\strut}}
+
+\def\fpos#1%
+ {\setpositionplus{b:#1}{\number\parposcounter}\horizontalstrut
+ \ignorespaces}
+
+\def\tpos#1%
+ {\removelastspace
+ \setpositionplus{e:#1}{\number\parposcounter}\horizontalstrut}
+
+\def\ffpos#1%
+ {\setpositionplus{b:#1}{\number\parposcounter}\horizontalstrut\wpos{#1}%
+ \ignorespaces}
+
+\def\ttpos#1%
+ {\removelastspace
+ \setpositionplus{e:#1}{\number\parposcounter}\horizontalstrut}
+
+\def\wpos#1%
+ {\dontleavehmode\vadjust % may disappear if buried
+ {\setbox0\hbox{\raise\strutdp\hbox{\rawwpos{#1}}}%
+ \rlap{\smashedbox0}}}
+
+\def\wwpos#1% \hsmashed{\llap{\rawwpos{#1}}}
+ {\rlap
+ {\setbox0\hbox{\rawwpos{#1}}%
+ \smashedbox0}}
+
+\def\rawwpos#1%
+ {\hpos{w:#1}
+ {\strut
+ \hskip-\leftskip
+ \hskip\hsize
+ \hskip-\rightskip}}
+
+% the next macro disables par positions (in inner boxes) and
+% only registers the width
+
+\def\setinnerparpositions
+ {\let\fpos\ffpos
+ \let\tpos\ttpos
+ \let\wpos\wwpos}
+
+% example of usage: (see for application "techniek")
+%
+% \appendtoks
+% \setinnerparpositions
+% \to \everytabulate
+
+%D When we want to calculate more complex backgrounds, we
+%D need to know what the current indentation scheme is. At
+%D the cost of many positions and memory, we can keep track
+%D of them. This mechanism is activated automatically
+%D based on information collected in the previous pass.
+
+\newcount\parposcounter
+
+\newif\ifpositioningpar
+
+% we can check for used entries, and if not, then not add one
+
+\def\enableparpositions % global
+ {\global\positioningtrue
+ \global\positioningpartrue}
+
+\def\disableparpositions % local
+ {\positioningparfalse}
+
+\def\registerparoptions
+ {\ifpositioningpar \ifpositioning \iftrialtypesetting \else
+ \ifinpagebody \else \ifmmode \else \ifinformula \else
+ \ifprocessingverbatim
+ \iflinepar \doregisterparoptions \fi
+ \else
+ \doregisterparoptions
+ \fi
+ \fi \fi \fi
+ \fi \fi \fi}
+
+\chardef\parposstrut=1 % 0 => no strut data, so fall backs used
+
+\newif\iftracepositions
+
+% \def\doregisterparoptions
+% {\global\advance\parposcounter\plusone
+% \begingroup
+% \leftskip 1\leftskip
+% \rightskip1\rightskip
+% \setpositiondataplus
+% {p:\number\parposcounter}% identifier
+% {\the\zeropoint}%
+% {\the\strutht}%
+% {\the\strutdp}%
+% {\the\hsize ,% 1
+% \the\leftskip ,% 2
+% \the\rightskip ,% 3
+% \the\hangindent,% 4
+% \the\hangafter ,% 5 (num)
+% \the\parindent }% 6
+% %\normalhbox{\registerparsymbol}%
+% \registerparsymbol
+% \endgroup}
+
+\def\doregisterparoptions
+ {\global\advance\parposcounter\plusone
+ \setpositiondataplus
+ {p:\number\parposcounter}% identifier
+ {\the\zeropoint}%
+ {\the\strutht}%
+ {\the\strutdp}%
+ {\the\hsize,\the\dimexpr\leftskip\relax,\the\dimexpr\rightskip\relax,\the\hangindent,\the\hangafter,\the\parindent}%
+ %\normalhbox{\registerparsymbol}%
+ \iftracepositions\registerparsymbol\fi}
+
+\def\traceposstring#1#2#3%
+ {\iftracepositions\smashedhbox{#1{\infofont#2#3}}\fi}
+
+\def\registerparsymbol
+ {\iftracepositions
+ \smashedhbox to \zeropoint
+ {\hss
+ \startcolor[blue]%
+ \llap{\infofont\number\parposcounter}%
+ \scratchdimen\onepoint
+ \vrule
+ \!!width 4\scratchdimen
+ \!!height2\scratchdimen
+ \!!depth 2\scratchdimen
+ \stopcolor
+ \hss}%
+ \fi}
+
+% \appendtoks \registerparoptions \to \everypar
+
+%D Eperimental code, don't use this yet: (must be sped up anyway)
+
+\def\@@noden{node:n:}
+\def\@@nodeo{node:o:}
+\def\@@nodep{node:p:}
+
+\def\doifelsenodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\nextnodelocation#1%
+ {\ifcsname\@@noden#1\endcsname\pluscounter{\@@noden#1}\fi}
+
+\def\newnodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \setcounter{\@@noden#1}\zerocount
+ \letgvalue {\@@nodeo#1}\!!zerocount
+ \fi}
+
+\def\tagnodelocation#1%
+ {\ifcsname\@@noden#1\endcsname\xypos{\@@nodep#1:\countervalue{\@@noden#1}}\fi}
+
+\def\getnodelocationp#1{\MPp{\@@nodep#1:\countervalue{\@@noden#1}}}
+\def\getnodelocationx#1{\MPx{\@@nodep#1:\countervalue{\@@noden#1}}}
+\def\getnodelocationy#1{\MPy{\@@nodep#1:\countervalue{\@@noden#1}}}
+
+\def\numnodelocationp#1#2{\MPp{\@@nodep#1:\number#2}}
+\def\numnodelocationx#1#2{\MPx{\@@nodep#1:\number#2}}
+\def\numnodelocationy#1#2{\MPy{\@@nodep#1:\number#2}}
+
+\def\getnodelocationn#1{\countervalue{\@@noden#1}}
+\def\getnodelocationo#1{\getvalue {\@@nodeo#1}}
+
+\chardef\nodelocationmode\plusone
+
+\def\analyzenodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \doanalyzenodelocation{#1}{\getnodelocationn{#1}}\zerocount
+ \fi}
+
+\def\doanalyzenodelocation#1#2#3% class n default
+ {\begingroup
+ \donefalse
+ \ifcase\nodelocationmode
+ % do nothing
+ \else
+ \edef\nodelocationselfn{#2}%
+ \edef\nodelocationselfp{\numnodelocationp{#1}\nodelocationselfn}%
+ \edef\nodelocationselfx{\numnodelocationx{#1}\nodelocationselfn}%
+ \edef\nodelocationselfy{\numnodelocationy{#1}\nodelocationselfn}%
+ \scratchcounter\plusone
+ \doloop
+ {\ifnum\recurselevel=\nodelocationselfn\relax
+ \donetrue
+ \else
+ \edef\nodelocationotherp{\numnodelocationp{#1}\recurselevel}%
+ \edef\nodelocationotherx{\numnodelocationx{#1}\recurselevel}%
+ \edef\nodelocationothery{\numnodelocationy{#1}\recurselevel}%
+ \ifcase\nodelocationmode
+ \or
+ % ok for single column
+ \ifcase\nodelocationotherp\relax
+ \exitloop
+ \else\ifnum\nodelocationotherp<\nodelocationselfp\relax
+ \donetrue \advance\scratchcounter\plusone
+ \else\ifnum\nodelocationotherp>\nodelocationselfp\relax
+ % skip
+ \else\ifdim\nodelocationothery>\nodelocationselfy\relax
+ \donetrue \advance\scratchcounter\plusone
+ \else\ifdim\nodelocationothery<\nodelocationselfy\relax
+ % skip
+ \else\ifdim\nodelocationotherx<\nodelocationselfx\relax
+ \donetrue \advance\scratchcounter\plusone
+ \fi\fi\fi\fi\fi\fi
+ \or
+ % acceptable for double column
+ \ifcase\nodelocationotherp\relax
+ \exitloop
+ \else\ifnum\nodelocationotherp<\nodelocationselfp\relax
+ \donetrue \advance\scratchcounter\plusone
+ \else\ifnum\nodelocationotherp>\nodelocationselfp\relax
+ % skip
+ \else\ifnum\recurselevel>\nodelocationselfn\relax
+ \donetrue \exitloop
+ \else
+ \donetrue \advance\scratchcounter\plusone
+ \fi\fi\fi\fi
+ \else
+ \exitloop
+ \fi
+ \fi}%
+ \fi
+ \ifdone \else
+ \scratchcounter#3\relax
+ \fi
+ \setxvalue{\@@nodeo#1}{\the\scratchcounter}%
+ \endgroup}
+
+\unexpanded\def\shownodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \analyzenodelocation{#1}%
+ (#1,%
+ n:\getnodelocationn{#1},%
+ p:\getnodelocationp{#1},%
+ x:\getnodelocationx{#1},%
+ y:\getnodelocationy{#1},%
+ o:\getnodelocationo{#1})%
+ \fi}
+
+%D \macros
+%D {doifoverlappingelse}
+%D
+%D A first application of positional information, is to
+%D determine if two boxes do overlap:
+%D
+%D \starttyping
+%D \doifoverlappingelse{point a}{point b}
+%D {action when overlapping}
+%D {action when not overlapping}
+%D \stoptyping
+
+\def\overlappingmargin{-2\scaledpoint}
+
+\def\doifoverlappingelse#1#2%
+ {\begingroup
+ \donefalse
+ \edef\!!stringa{#1}\edef\!!stringb{#2}%
+ \ifnum\MPp\!!stringa=\MPp\!!stringb\relax
+ \!!dimena\MPx\!!stringa
+ \!!dimenb\dimexpr\MPx\!!stringa+\MPw\!!stringa\relax
+ \!!dimenc\dimexpr\MPy\!!stringa-\MPd\!!stringa\relax
+ \!!dimend\dimexpr\MPy\!!stringa+\MPh\!!stringa\relax
+ \!!dimene\MPx\!!stringb
+ \!!dimenf\dimexpr\MPx\!!stringb+\MPw\!!stringb\relax
+ \!!dimeng\dimexpr\MPy\!!stringb-\MPd\!!stringb\relax
+ \!!dimenh\dimexpr\MPy\!!stringb+\MPh\!!stringb\relax
+ \ifdim\overlappingmargin=\zeropoint\else
+ \advance\!!dimena-\overlappingmargin
+ \advance\!!dimenb+\overlappingmargin
+ \advance\!!dimenc-\overlappingmargin
+ \advance\!!dimend+\overlappingmargin
+ \advance\!!dimene-\overlappingmargin
+ \advance\!!dimenf+\overlappingmargin
+ \advance\!!dimeng-\overlappingmargin
+ \advance\!!dimenh+\overlappingmargin
+ \fi
+ % more often eh fb eg fg
+ \def\checkone##1##2%
+ {\ifdim##1<\!!dimena \else \ifdim##1>\!!dimenb \else
+ \ifdim##2<\!!dimenc \else \ifdim##2>\!!dimend \else
+ \donetrue
+ \fi\fi
+ \fi\fi}%
+ \def\checktwo##1##2%
+ {\ifdim##1<\!!dimene \else \ifdim##1>\!!dimenf \else
+ \ifdim##2<\!!dimeng \else \ifdim##2>\!!dimenh \else
+ \donetrue
+ \fi\fi
+ \fi\fi}%
+ \checkone\!!dimene\!!dimeng \ifdone \else
+ \checkone\!!dimene\!!dimenh \ifdone \else
+ \checkone\!!dimenf\!!dimeng \ifdone \else
+ \checkone\!!dimenf\!!dimenh \ifdone \else
+ \checktwo\!!dimena\!!dimenc \ifdone \else
+ \checktwo\!!dimena\!!dimend \ifdone \else
+ \checktwo\!!dimenb\!!dimene \ifdone \else
+ \checktwo\!!dimenb\!!dimenc \fi \fi \fi \fi \fi \fi \fi
+ \fi
+ \ifdone
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+%D \macros
+%D {doifpositionsonsamepageelse,
+%D doifpositionsonthispageelse}
+%D
+%D Instead of letting the user handle fuzzy expansion, we
+%D provide a simple test on positione being on the same page.
+%D
+%D \starttyping
+%D \doifpositionsonsamepageelse{point a}{point b}
+%D {action when on same page}
+%D {action when not on same page}
+%D \doifpositionsonthispageelse{point a}{point b}
+%D {action when on this page}
+%D {action when not on this page}
+%D \stoptyping
+
+\def\dodoifpositionsonsamepageelse#1#2#3#4%
+ {\bgroup
+ \scratchcounter#1\donefalse
+ \def\docommand##1%
+ {\ifcase\scratchcounter
+ \scratchcounter\MPp{##1}\donetrue
+ \else
+ \ifnum\scratchcounter=\MPp{##1}\relax\else\donefalse\fi
+ \fi}%
+ \rawprocesscommalist[#2]\docommand
+ \ifdone\egroup#3\else\egroup#4\fi}
+
+\def\doifpositionsonsamepageelse{\dodoifpositionsonsamepageelse\!!zerocount}
+\def\doifpositionsonthispageelse{\dodoifpositionsonsamepageelse\realfolio }
+
+%D Plugins:
+
+\let\MPv \MPplus
+\let\MPvv\MPrest
+
+\let\MPanchor\MPpos
+
+\let\POSp\MPp \let\POSx\MPx \let\POSy\MPy
+\let\POSh\MPh \let\POSd\MPd \let\POSw\MPw
+
+\protect \endinput
diff --git a/tex/context/base/anch-pos.mkiv b/tex/context/base/anch-pos.mkiv
new file mode 100644
index 000000000..e454747da
--- /dev/null
+++ b/tex/context/base/anch-pos.mkiv
@@ -0,0 +1,784 @@
+%D \module
+%D [ file=anch-pos, % was core-pos
+%D version=1999.08.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Positioning Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% needs a cleanup, things may change; we also need to move the mp
+% related code to meta-pos
+
+% shorter tags, ..:achtergrond:.. etc in pos actions
+
+% dubbele text- * pos's eruit
+
+% class pos -> als gelijk aan vorige, dan niet niet definieren
+% en erven, maw:
+%
+% 1 -> opslaan
+% 2 -> undef, dus == prev
+% 3 -> undef, dus == prev
+% 4 -> opslaan
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Positioning}
+
+% saveposition : tag page x y
+% savepositionwhd : tag page x y w h d
+% savepositionplus : tag page x y w h d list
+%
+% at some point (when we no longer share code) we will move to numbers
+% do that we have less garbage collection and hashing
+%
+% the global table ptbs is equivalent to jobpositions.tobesaved
+%
+% btw, using a function is more efficient than passing longer code
+% snippets to ctxlua
+
+\registerctxluafile{anch-pos}{1.001}
+
+% todo: topskip als optie voor eerste regel achtergrond
+% todo: build pos layers on top of layers
+% todo: positionlayer pos van text-1 etc delen
+
+%D Although \TEX\ has a rather powerful channel to the outside
+%D world, called \type {\special}, real communication with
+%D other programs is complicated by the fact that no positional
+%D information is available. Mid 1999, I discussed this with
+%D \THANH, the author of \PDFTEX, and after some experiments,
+%D \PDFTEX\ was extended with a simple but effective mechanism,
+%D that provided positional information. The interesting
+%D thought is that, although \TEX\ is frozen, similar
+%D functionality could have been achieved with \type
+%D {\specials} and an additional \DVI\ postprocessor.
+%D
+%D Since we want to be as compatible as can be, \CONTEXT\ will
+%D support both methods, although the development is primarily
+%D driven by the \PDFTEX\ way of doing things. Since the
+%D mechanism is basically not limited to one application, for
+%D the moment we stick to building the functionality around one
+%D \CONTEXT\ special command, but at the same time we keep our
+%D eyes open for extensions in other directions.
+%D
+%D A question that may arise when one reads this module, is to
+%D what extend these macros are generic, in the sense that they
+%D could be collected in a support module instead of a core
+%D module. Since the mechanism described here will closely
+%D cooperate with the \METAPOST\ support built in \CONTEXT,
+%D which in turn will be tightly integrated with the \CONTEXT\
+%D overlay mechanisms, I decided to write a core module instead
+%D of a support one. This makes even more sense, when one takes
+%D into account that this kind of support depends on special
+%D drivers.
+
+\unprotect
+
+%D The first application of positional information was embedded
+%D graphics. Since we are interacting with text, it made sense
+%D to take the current line height and depth into account too.
+%D This is why we have two basic position macros: one for
+%D simple positions, and one for boxes.
+%D
+%D We could have sticked to one special, and actually did so in
+%D earlier experiments, but for convenience, as well for
+%D clearness, we now have two alternatives. This approach will
+%D save us quite some bytes when storing large quantities of
+%D positional information. We save as less information as
+%D needed, that is, we save no dimensions, in a \METAPOST\
+%D friendly way.
+%D
+%D The three specials involved are:
+%D
+%D \starttyping
+%D \dosetposition {identifier}
+%D \dosetpositionwhd {identifier} {width} {height} {depth}
+%D \dosetpositionplus {identifier} {width} {height} {depth} {list}
+%D \dosetpositionpapersize {width} {height}
+%D \stoptyping
+%D
+%D Positions are either generated at a delayed write time
+%D (in \PDFTEX), or derived from the dvi file. The actual
+%D method is implemented in a special driver. If needed, the
+%D driver can fall back on the following macros.
+
+% are the next 6 still used?
+
+\def\dolazysaveposition #1#2#3#4{\normalexpanded{\ctxlatelua{ptbs['#1']={#2,"#3","#4"}}}}
+\def\dolazysavepositionwhd #1#2#3#4#5#6#7{\normalexpanded{\ctxlatelua{ptbs['#1']={#2,"#3","#4","#5","#6","#7"}}}}
+\def\dolazysavepositionplus#1#2#3#4#5#6#7#8{\normalexpanded{\ctxlatelua{ptbs['#1']={#2,"#3","#4","#5","#6","#7","#8"}}}}
+\def\dosaveposition #1#2#3#4{\normalexpanded{\ctxlua {ptbs['#1']={#2,"#3","#4"}}}}
+\def\dosavepositionwhd #1#2#3#4#5#6#7{\normalexpanded{\ctxlua {ptbs['#1']={#2,"#3","#4","#5","#6","#7"}}}}
+\def\dosavepositionplus #1#2#3#4#5#6#7#8{\normalexpanded{\ctxlua {ptbs['#1']={#2,"#3","#4","#5","#6","#7","#8"}}}}
+
+\def\lastsavedpositionx {\the\dimexpr\pdflastxpos\scaledpoint\relax}
+\def\lastsavedpositiony {\the\dimexpr\pdflastypos\scaledpoint\relax}
+\let\savecurrentposition\pdfsavepos
+
+\def\dosetposition#1%
+ {\savecurrentposition
+ \normalexpanded{\ctxlatelua{ptbs['#1']={%
+ \noexpand\realfolio,"\noexpand\lastsavedpositionx","\noexpand\lastsavedpositiony"}}}}
+
+\def\dosetpositionwhd#1#2#3#4%
+ {\savecurrentposition
+ \normalexpanded{\ctxlatelua{ptbs['#1']={%
+ \noexpand\realfolio,"\noexpand\lastsavedpositionx","\noexpand\lastsavedpositiony","#2","#3","#4"}}}}
+
+\def\dosetpositionplus#1#2#3#4#5%
+ {\savecurrentposition
+ \normalexpanded{\ctxlatelua{ptbs['#1']={%
+ \noexpand\realfolio,"\noexpand\lastsavedpositionx","\noexpand\lastsavedpositiony","#2","#3","#4","#5"}}}}
+
+\let\dosetpositionpapersize\gobbletwoarguments
+
+\newbox\positionbox
+\newif \ifpositioning
+
+\def\POSprefix{POS::}
+
+\let\setpospx \gobblefourarguments % suppress errors with mkii tuo file
+\let\setpospxywhd \gobblesevenarguments % suppress errors with mkii tuo file
+\let\setpospxyplus\gobbleeightarguments % suppress errors with mkii tuo file
+
+%D This is real tricky! The page anchor is applied to the
+%D page box and therefore flushed first. So, when present, it
+%D is applied to all positions except itself.
+
+\chardef\positionanchormode=0 % don't relocate page origin
+\chardef\positionanchormode=1 % relocate page origin once
+
+%D The core set macros.
+
+\let\pospxy \gobblefourarguments
+\let\pospxywhd \gobblesevenarguments
+\let\pospxyplus\gobbleeightarguments
+
+%D Sometimes we want to trick the position handler a bit:
+
+\def\replacepospxywhd#1#2#3#4#5#6#7{\ctxlua{jobpositions.replace('#1',\number#2,"\the\dimexpr#3\relax","\the\dimexpr#4\relax","\the\dimexpr#5\relax","\the\dimexpr#6\relax","\the\dimexpr#7\relax")}}
+
+%D For postprocessing purposes, we save the number of
+%D positions.
+
+\newcount\currentpositions % current number of positions
+
+%D The next switch can be used to communicate a special
+%D situation. Positioning and associated actions can be
+%D executed any time. However, in for instance backgrounds
+%D they can be collected in a layer, for instance the text
+%D layer (especially the hidden text layer). In the case of
+%D floats, we run into problems, since the page information is
+%D not applicable when the content floats indeed. In such
+%D situations one can treat positions and graphics local.
+
+\newif\iflocalpositioning
+
+%D Watch out: sometimes a pagebreak occurs inside a float
+%D placement, so there we need to disable local mode.
+
+\appendtoks
+ \localpositioningtrue
+\to \everyinsidefloat
+
+\appendtoks
+ \localpositioningfalse
+\to \everypagebody
+
+%D Since the positional values are to be fully expandable, we
+%D need to preload them as soon as possible, which is why we
+%D load the data when we start a text.
+
+% \appendtoks \checkpositions \to \everystarttext
+
+%D \macros
+%D {MPp, MPx, MPy, MPw, MPh, MPd,
+%D MPxy, MPll, MPlr, MPur, MPul, MPpos}
+%D
+%D Access to the positional information is provided by macros
+%D with short names that are clearly meant for \METAPOST.
+
+% \the\dimexpr\noexpand\lastsavedpositionx\ifnum\positionanchormode=\plusone-\MPx\pageanchor\fi\relax
+% \the\dimexpr\noexpand\lastsavedpositiony\ifnum\positionanchormode=\plusone-\MPx\pageanchor\fi\relax
+
+\def\MPp #1{\ctxlua{jobpositions.MPp("#1")}}
+\def\MPx #1{\ctxlua{jobpositions.MPx("#1")}}
+\def\MPy #1{\ctxlua{jobpositions.MPy("#1")}}
+\def\MPw #1{\ctxlua{jobpositions.MPw("#1")}}
+\def\MPh #1{\ctxlua{jobpositions.MPh("#1")}}
+\def\MPd #1{\ctxlua{jobpositions.MPd("#1")}}
+\def\MPxy #1{\ctxlua{jobpositions.MPxy("#1")}}
+\def\MPll #1{\ctxlua{jobpositions.MPll("#1")}}
+\def\MPlr #1{\ctxlua{jobpositions.MPlr("#1")}}
+\def\MPur #1{\ctxlua{jobpositions.MPur("#1")}}
+\def\MPul #1{\ctxlua{jobpositions.MPul("#1")}}
+\def\MPpos#1{\ctxlua{jobpositions.MPpos("#1")}}
+
+%D \macros
+%D {MPplus, MPrest, MPv, MPvv}
+%D
+%D Since we will probably keep on extending, we provide a
+%D general extension macro. The plus alternative takes an
+%D extra argument, denoting what additional parameter to pick
+%D up. So, the third extra is fetched with,
+%D
+%D \starttyping
+%D \MPplus{identifier}{3}{default}
+%D \stoptyping
+%D
+%D All extras (comma separated) are fetched with:
+%D
+%D \starttyping
+%D \MPrest{identifier}
+%D \stoptyping
+%D
+%D The extra parameters are not treated.
+
+\def\MPplus#1#2#3{\ctxlua{jobpositions.MPplus("#1",#2,"#3")}} \let\MPv \MPplus
+\def\MPrest #1#2{\ctxlua{jobpositions.MPrest("#1","#2")}} \let\MPvv\MPrest
+
+%D \macros
+%D {MPanchor}
+%D
+%D For readability we define a few synonyms:
+
+\def\MPanchor{\MPpos}
+
+%D \macros
+%D {POSp, POSx, POSy, POSh, POSd, POSw}
+%D
+%D and:
+
+\def\POSp{\MPp} \def\POSx{\MPx} \def\POSy{\MPy}
+\def\POSh{\MPh} \def\POSd{\MPd} \def\POSw{\MPw}
+
+%D There are two low level positioning macros. Both store the
+%D position as well as execute an action associated with that
+%D position.
+
+\def\initializenextposition
+ {\ifpositioning \else
+ \global\positioningtrue
+ \dosetpositionpapersize
+ {\printpaperwidth }%
+ {\printpaperheight}%
+ \fi
+ \global\advance\currentpositions\plusone}
+
+\def\setpositiononly#1%
+ {\iftrialtypesetting
+ % nothing
+ \else
+ \initializenextposition
+ \def\currentposition{#1}%
+ \dosetposition\currentposition
+ \fi}
+
+\def\setposition#1%
+ {\iftrialtypesetting
+ % nothing
+ \else
+ \initializenextposition
+ \def\currentposition{#1}%
+ \dosetposition\currentposition
+ \traceposstring\llap\green{\currentposition>}%
+ \dopositionaction\currentposition
+ \fi}
+
+\def\setpositiondata#1#2#3#4%
+ {\iftrialtypesetting \else
+ \initializenextposition
+ \hbox
+ {\def\currentposition{#1}%
+ \dosetpositionwhd\currentposition
+ {\the\dimexpr#2\relax}%
+ {\the\dimexpr#3\relax}%
+ {\the\dimexpr#4\relax}%
+ \traceposstring\llap\green{\currentposition>}%
+ \dopositionaction\currentposition
+ \hss}%
+ \fi}
+
+\def\setpositionbox#1%
+ {\dowithnextbox
+ {\iftrialtypesetting
+ \flushnextbox
+ \else
+ \initializenextposition
+ \hbox to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionwhd\currentposition
+ {\the\nextboxwd}%
+ {\the\nextboxht}%
+ {\the\nextboxdp}%
+ \traceposstring\llap\green{\currentposition>}%
+ \setbox\positionbox\flushnextbox
+ \dopositionaction\currentposition
+ \box\positionbox
+ \hss}%
+ \fi}}
+
+\def\setpositiondataplus#1#2#3#4#5%
+ {\iftrialtypesetting \else
+ \initializenextposition
+ \hbox % bug: to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition
+ {\the\dimexpr#2\relax}%
+ {\the\dimexpr#3\relax}%
+ {\the\dimexpr#4\relax}%
+ {#5}%
+ \traceposstring\rlap\magenta{<\currentposition}%
+ \dopositionaction\currentposition
+ \hss}%
+ \fi}
+
+\def\setpositionplus#1#2%
+ {\dowithnextbox
+ {\iftrialtypesetting
+ \flushnextbox
+ \else
+ \initializenextposition
+ \hbox to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition
+ {\the\nextboxwd}%
+ {\the\nextboxht}%
+ {\the\nextboxdp}%
+ {#2}%
+ \traceposstring\rlap\magenta{<\currentposition}%
+ \setbox\positionbox\flushnextbox
+ \dopositionaction\currentposition
+ \box\positionbox
+ \hss}%
+ \fi}}
+
+\let\currentposition\s!unknown
+
+%D A few more low level macros take care of defining and
+%D recalling actions. We could save this information in the
+%D position containers themselves, this would save hash
+%D entries, but at the cost of much more time consuming
+%D expansion. Actions are saved globally!
+
+\newtoks\everypositionaction
+
+\let\POSactionprefix\POSprefix
+
+\def\dosetpositionaction#1%
+ {\setgvalue{\POSactionprefix#1::}}
+
+%D The lists can become quite long (also because there can
+%D be lots of parameters passed on) so we provide a hook
+%D to clean up the list afterwards.
+
+\let\cleanuppositionaction\gobbleoneargument
+
+\def\doifpositionaction#1%
+ {\ifcsname\POSactionprefix#1::\endcsname
+ \@EA\firstofoneargument
+ \else
+ \@EA\gobbleoneargument
+ \fi}
+
+\def\doifpositionactionelse#1%
+ {\ifcsname\POSactionprefix#1::\endcsname
+ \@EA\firstoftwoarguments
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+%D We can copy a position with:
+%D
+%D \starttyping
+%D \copyposition {to} {from}
+%D \stoptyping
+%D
+%D Again, this is a global action.
+
+\def\copyposition#1#2{\ctxlua{jobpositions.copy('#1','#2')}}
+
+%D The fact that handling positions is a two pass operation, is
+%D one of the reasons why we need to be able to test for
+%D existence, using:
+%D
+%D \starttyping
+%D \doifpositionelse {identifier} {found action} {not found action}
+%D \stoptyping
+
+\def\doifpositionelse#1{\ctxlua{jobpositions.doifelse('#1')}}
+
+%D We have now arrived at a few macros that would make sense as
+%D support macros, but ended up in the core.
+
+%D \macros
+%D {xypos}
+%D
+%D We have several macros available to save positions. Later
+%D we will see applications.
+%D
+%D \starttabulate[|l|l||]
+%D \NC \type {\xypos} \NC \NC simple position with no dimensions \NC \NR
+%D \NC \type {\hpos} \NC \NC position and characteristics of a \type {\hbox} \NC \NR
+%D \NC \type {\vpos} \NC \NC position and characteristics of a \type {\vbox} \NC \NR
+%D \NC \type {\bpos} \NC b: \NC begin point in a line \NC \NR
+%D \NC \type {\epos} \NC e: \NC end point in a line \NC \NR
+%D \NC \type {\fpos} \NC f: \NC begin point in a paragraph \NC \NR
+%D \NC \type {\tpos} \NC t: \NC end point in a paragraph \NC \NR
+%D \stoptabulate
+%D
+%D Each macro takes an identifier as argument, and the \type
+%D {\hpos} and \type {\vpos} also expect box content.
+
+% \def\xypos{\initializenextposition\dosetposition}
+
+\let\xypos\setpositiononly
+
+\def\hpos#1{\dontleavehmode\setpositionbox{#1}\hbox}
+\def\vpos#1{\setpositionbox{#1}\vbox}
+
+\def\bpos#1{\hpos{b:#1}{\strut}\ignorespaces}
+\def\epos#1{\removelastspace\hpos{e:#1}{\strut}}
+
+\def\fpos#1%
+ {\setpositionplus{b:#1}{\number\parposcounter}\horizontalstrut
+ \ignorespaces}
+
+\def\tpos#1%
+ {\removelastspace
+ \setpositionplus{e:#1}{\number\parposcounter}\horizontalstrut}
+
+\def\ffpos#1%
+ {\setpositionplus{b:#1}{\number\parposcounter}\horizontalstrut\wpos{#1}%
+ \ignorespaces}
+
+\def\ttpos#1%
+ {\removelastspace
+ \setpositionplus{e:#1}{\number\parposcounter}\horizontalstrut}
+
+\def\wpos#1%
+ {\dontleavehmode\vadjust % may disappear if buried
+ {\setbox0\hbox{\raise\strutdp\hbox{\rawwpos{#1}}}%
+ \rlap{\smashedbox0}}}
+
+\def\wwpos#1% \hsmashed{\llap{\rawwpos{#1}}}
+ {\rlap
+ {\setbox0\hbox{\rawwpos{#1}}%
+ \smashedbox0}}
+
+\def\rawwpos#1%
+ {\hpos{w:#1}
+ {\strut
+ \hskip-\leftskip
+ \hskip\hsize
+ \hskip-\rightskip}}
+
+% the next macro disables par positions (in inner boxes) and
+% only registers the width
+
+\def\setinnerparpositions
+ {\let\fpos\ffpos
+ \let\tpos\ttpos
+ \let\wpos\wwpos}
+
+% example of usage: (see for application "techniek")
+%
+% \appendtoks
+% \setinnerparpositions
+% \to \everytabulate
+
+%D When we want to calculate more complex backgrounds, we
+%D need to know what the current indentation scheme is. At
+%D the cost of many positions and memory, we can keep track
+%D of them. This mechanism is activated automatically
+%D based on information collected in the previous pass.
+
+\newcount\parposcounter
+\newif \ifpositioningpar
+\chardef \parposstrut = 1 % 0 => no strut data, so fall backs used
+\newif \iftracepositions
+
+% we can check for used entries, and if not, then not add one
+
+\def\enableparpositions % global
+ {\global\let\registerparoptions\doregisterparoptions
+ \global\positioningtrue
+ \global\positioningpartrue}
+
+\def\disableparpositions % local
+ {\positioningparfalse}
+
+\let\registerparoptions\relax
+
+\def\doregisterparoptions
+ {\ifpositioningpar \ifpositioning \iftrialtypesetting \else
+ \ifinpagebody \else \ifmmode \else \ifinformula \else
+ \ifprocessingverbatim
+ \iflinepar \dodoregisterparoptions \fi
+ \else
+ \dodoregisterparoptions
+ \fi
+ \fi \fi \fi
+ \fi \fi \fi}
+
+\def\dodoregisterparoptions
+ {\global\advance\parposcounter\plusone
+ \setpositiondataplus
+ {p:\number\parposcounter}% identifier
+ {\the\zeropoint}%
+ {\the\strutht}%
+ {\the\strutdp}%
+ {\the\hsize,\the\dimexpr\leftskip\relax,\the\dimexpr\rightskip\relax,\the\hangindent,\the\hangafter,\the\parindent}%
+ %\normalhbox{\registerparsymbol}%
+ \iftracepositions\registerparsymbol\fi}
+
+\def\traceposstring#1#2#3%
+ {\iftracepositions\smashedhbox{#1{\infofont#2#3}}\fi}
+
+\def\registerparsymbol
+ {\iftracepositions
+ \smashedhbox to \zeropoint
+ {\hss
+ \startcolor[blue]%
+ \llap{\infofont\number\parposcounter}%
+ \scratchdimen\onepoint
+ \vrule
+ \!!width 4\scratchdimen
+ \!!height2\scratchdimen
+ \!!depth 2\scratchdimen
+ \stopcolor
+ \hss}%
+ \fi}
+
+% \appendtoks \registerparoptions \to \everypar
+
+%D Eperimental code, don't use this yet: (must be sped up anyway)
+
+\def\@@noden{node:n:}
+\def\@@nodeo{node:o:}
+\def\@@nodep{node:p:}
+
+\def\doifelsenodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\nextnodelocation#1%
+ {\ifcsname\@@noden#1\endcsname\pluscounter{\@@noden#1}\fi}
+
+\def\newnodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \setcounter{\@@noden#1}\zerocount
+ \letgvalue {\@@nodeo#1}\!!zerocount
+ \fi}
+
+\def\tagnodelocation#1%
+ {\ifcsname\@@noden#1\endcsname\xypos{\@@nodep#1:\countervalue{\@@noden#1}}\fi}
+
+\def\getnodelocationp#1{\MPp{\@@nodep#1:\countervalue{\@@noden#1}}}
+\def\getnodelocationx#1{\MPx{\@@nodep#1:\countervalue{\@@noden#1}}}
+\def\getnodelocationy#1{\MPy{\@@nodep#1:\countervalue{\@@noden#1}}}
+
+\def\numnodelocationp#1#2{\MPp{\@@nodep#1:\number#2}}
+\def\numnodelocationx#1#2{\MPx{\@@nodep#1:\number#2}}
+\def\numnodelocationy#1#2{\MPy{\@@nodep#1:\number#2}}
+
+\def\getnodelocationn#1{\countervalue{\@@noden#1}}
+\def\getnodelocationo#1{\getvalue {\@@nodeo#1}}
+
+\chardef\nodelocationmode\plusone
+
+\def\analyzenodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \doanalyzenodelocation{#1}{\getnodelocationn{#1}}\zerocount
+ \fi}
+
+\def\doanalyzenodelocation#1#2#3% class n default
+ {\begingroup
+ \donefalse
+ \ifcase\nodelocationmode
+ % do nothing
+ \else
+ \edef\nodelocationselfn{#2}%
+ \edef\nodelocationselfp{\numnodelocationp{#1}\nodelocationselfn}%
+ \edef\nodelocationselfx{\numnodelocationx{#1}\nodelocationselfn}%
+ \edef\nodelocationselfy{\numnodelocationy{#1}\nodelocationselfn}%
+ \scratchcounter\plusone
+ \doloop
+ {\ifnum\recurselevel=\nodelocationselfn\relax
+ \donetrue
+ \else
+ \edef\nodelocationotherp{\numnodelocationp{#1}\recurselevel}%
+ \edef\nodelocationotherx{\numnodelocationx{#1}\recurselevel}%
+ \edef\nodelocationothery{\numnodelocationy{#1}\recurselevel}%
+ \ifcase\nodelocationmode
+ \or
+ % ok for single column
+ \ifcase\nodelocationotherp\relax
+ \exitloop
+ \else\ifnum\nodelocationotherp<\nodelocationselfp\relax
+ \donetrue \advance\scratchcounter\plusone
+ \else\ifnum\nodelocationotherp>\nodelocationselfp\relax
+ % skip
+ \else\ifdim\nodelocationothery>\nodelocationselfy\relax
+ \donetrue \advance\scratchcounter\plusone
+ \else\ifdim\nodelocationothery<\nodelocationselfy\relax
+ % skip
+ \else\ifdim\nodelocationotherx<\nodelocationselfx\relax
+ \donetrue \advance\scratchcounter\plusone
+ \fi\fi\fi\fi\fi\fi
+ \or
+ % acceptable for double column
+ \ifcase\nodelocationotherp\relax
+ \exitloop
+ \else\ifnum\nodelocationotherp<\nodelocationselfp\relax
+ \donetrue \advance\scratchcounter\plusone
+ \else\ifnum\nodelocationotherp>\nodelocationselfp\relax
+ % skip
+ \else\ifnum\recurselevel>\nodelocationselfn\relax
+ \donetrue \exitloop
+ \else
+ \donetrue \advance\scratchcounter\plusone
+ \fi\fi\fi\fi
+ \else
+ \exitloop
+ \fi
+ \fi}%
+ \fi
+ \ifdone \else
+ \scratchcounter#3\relax
+ \fi
+ \setxvalue{\@@nodeo#1}{\the\scratchcounter}%
+ \endgroup}
+
+\unexpanded\def\shownodelocation#1%
+ {\ifcsname\@@noden#1\endcsname
+ \analyzenodelocation{#1}%
+ (#1,%
+ n:\getnodelocationn{#1},%
+ p:\getnodelocationp{#1},%
+ x:\getnodelocationx{#1},%
+ y:\getnodelocationy{#1},%
+ o:\getnodelocationo{#1})%
+ \fi}
+
+%D \macros
+%D {doifoverlappingelse}
+%D
+%D A first application of positional information, is to
+%D determine if two boxes do overlap:
+%D
+%D \starttyping
+%D \doifoverlappingelse{point a}{point b}
+%D {action when overlapping}
+%D {action when not overlapping}
+%D \stoptyping
+
+\def\overlappingmargin{-2\scaledpoint}
+
+\def\overlappingcheckone#1#2%
+ {\ifdim#1<\!!dimena \else \ifdim#1>\!!dimenb \else
+ \ifdim#2<\!!dimenc \else \ifdim#2>\!!dimend \else
+ \donetrue
+ \fi\fi
+ \fi\fi}
+
+\def\overlappingchecktwo#1#2%
+ {\ifdim#1<\!!dimene \else \ifdim#1>\!!dimenf \else
+ \ifdim#2<\!!dimeng \else \ifdim#2>\!!dimenh \else
+ \donetrue
+ \fi\fi
+ \fi\fi}
+
+\def\doifoverlappingelse#1#2% maybe do this in lua
+ {\begingroup
+ \donefalse
+ \edef\!!stringa{#1}\edef\!!stringb{#2}%
+ \ifnum\MPp\!!stringa=\MPp\!!stringb\relax
+ \!!dimena\MPx\!!stringa
+ \!!dimenb\dimexpr\MPx\!!stringa+\MPw\!!stringa\relax
+ \!!dimenc\dimexpr\MPy\!!stringa-\MPd\!!stringa\relax
+ \!!dimend\dimexpr\MPy\!!stringa+\MPh\!!stringa\relax
+ \!!dimene\MPx\!!stringb
+ \!!dimenf\dimexpr\MPx\!!stringb+\MPw\!!stringb\relax
+ \!!dimeng\dimexpr\MPy\!!stringb-\MPd\!!stringb\relax
+ \!!dimenh\dimexpr\MPy\!!stringb+\MPh\!!stringb\relax
+ \ifdim\overlappingmargin=\zeropoint\else
+ \advance\!!dimena-\overlappingmargin
+ \advance\!!dimenb+\overlappingmargin
+ \advance\!!dimenc-\overlappingmargin
+ \advance\!!dimend+\overlappingmargin
+ \advance\!!dimene-\overlappingmargin
+ \advance\!!dimenf+\overlappingmargin
+ \advance\!!dimeng-\overlappingmargin
+ \advance\!!dimenh+\overlappingmargin
+ \fi
+ % more often eh fb eg fg
+ \overlappingcheckone\!!dimene\!!dimeng \ifdone \else
+ \overlappingcheckone\!!dimene\!!dimenh \ifdone \else
+ \overlappingcheckone\!!dimenf\!!dimeng \ifdone \else
+ \overlappingcheckone\!!dimenf\!!dimenh \ifdone \else
+ \overlappingchecktwo\!!dimena\!!dimenc \ifdone \else
+ \overlappingchecktwo\!!dimena\!!dimend \ifdone \else
+ \overlappingchecktwo\!!dimenb\!!dimene \ifdone \else
+ \overlappingchecktwo\!!dimenb\!!dimenc \fi \fi \fi \fi \fi \fi \fi
+ \fi
+ \ifdone
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+%D \macros
+%D {doifpositionsonsamepageelse,
+%D doifpositionsonthispageelse}
+%D
+%D Instead of letting the user handle fuzzy expansion, we
+%D provide a simple test on positione being on the same page.
+%D
+%D \starttyping
+%D \doifpositionsonsamepageelse{point a}{point b}
+%D {action when on same page}
+%D {action when not on same page}
+%D \doifpositionsonthispageelse{point a}{point b}
+%D {action when on this page}
+%D {action when not on this page}
+%D \stoptyping
+
+\def\dododoifpositionsonsamepageelse#1%
+ {\ifcase\scratchcounter
+ \scratchcounter\MPp{##}\donetrue
+ \else
+ \ifnum\scratchcounter=\MPp{#1}\relax\else\donefalse\fi
+ \fi}%
+
+\def\dodoifpositionsonsamepageelse#1#2%
+ {\begingroup
+ \scratchcounter#1\donefalse
+ \rawprocesscommalist[#2]\dododoifpositionsonsamepageelse
+ \ifdone
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifpositionsonsamepageelse{\dodoifpositionsonsamepageelse\!!zerocount}
+\def\doifpositionsonthispageelse{\dodoifpositionsonsamepageelse\realfolio }
+
+%D Plugins:
+
+\let\MPv \MPplus
+\let\MPvv\MPrest
+
+\let\MPanchor\MPpos
+
+\let\POSp\MPp \let\POSx\MPx \let\POSy\MPy
+\let\POSh\MPh \let\POSd\MPd \let\POSw\MPw
+
+\protect \endinput
diff --git a/tex/context/base/anch-snc.mkii b/tex/context/base/anch-snc.mkii
new file mode 100644
index 000000000..cf5b35d69
--- /dev/null
+++ b/tex/context/base/anch-snc.mkii
@@ -0,0 +1,177 @@
+%D \module
+%D [ file=anch-snc,
+%D version=2003.12.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Synchronization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Anchoring Macros / Synchronization}
+
+\unprotect
+
+\ifx\s!set \undefined \def\s!set {set} \fi
+\ifx\s!reset \undefined \def\s!reset {reset} \fi
+\ifx\s!preset \undefined \def\s!preset {preset} \fi
+\ifx\s!syncpos\undefined \def\s!syncpos{syncpos} \fi
+
+\def\definesyncpositions[#1]%
+ {\setcounter{\s!num:\s!syncpos:#1}{0}%
+ \doglobal\appendtoksonce\getvalue {\s!reset:\s!syncpos:#1}\to\resetsyncpositions
+ \doglobal\appendtoksonce\getvalue{\s!preset:\s!syncpos:#1}\to\presetsyncpositions
+ \setgvalue{\s!syncpos:#1}{sync_n[#1] := 0 ;}%
+ \setgvalue{\s!set:\s!syncpos:#1}{\dosetsyncpositions{#1}}}
+
+\def\syncposition
+ {\dodoubleempty\dosyncposition}
+
+\def\dosyncposition[#1][#2]%
+ {\letgvalue{\s!reset:\s!syncpos:#1}\relax
+ \letgvalue{\s!preset:\s!syncpos:#1}\relax
+ \dontleavehmode
+ \dodosyncposition{#1}{#2}\s!set
+ \ignorespaces}
+
+\def\doifelselastsyncposition#1#2%
+ {\doifelse{\lastsyncclass\lastsyncposition}{#1#2}}
+
+\def\dodosyncposition#1#2#3%
+ {\letgvalue{\s!reset:\s!syncpos:#1}\relax
+ \letgvalue{\s!preset:\s!syncpos:#1}\relax
+ \ifundefined{\s!syncpos:#1}%
+ \strut
+ \else
+ \pluscounter{\s!num:\s!syncpos:#1}%
+ \setsyncpositions{#1}%
+ % option: geen w/h, alleen p 0 0 0 data
+ \setpositionplus
+ {\s!syncpos:#1:\countervalue{\s!num:\s!syncpos:#1}}%
+ {#2}%
+ \hbox{\strut\traceposstring\llap\green{#3/\countervalue{\s!num:\s!syncpos:#1}/#1/#2>>}}%
+ \fi}
+
+\def\setsyncpositions#1%
+ {\enabletextarearegistration
+ \getvalue {\s!set:\s!syncpos:#1}%
+ \letgvalue{\s!set:\s!syncpos:#1}\relax}
+
+\def\dosetsyncpositions#1%
+ {\startnointerference % removing out of sync can best be done in mp
+ \!!dimena\maxdimen
+ \!!counta\zerocount
+ \!!countc\zerocount
+ \doloop
+ {\doifpositionelse{\s!syncpos:#1:\recurselevel}
+ {\!!dimenb\MPy{\s!syncpos:#1:\recurselevel}\relax
+ \!!countb\MPp{\s!syncpos:#1:\recurselevel}\relax
+ \ifnum\!!countb=\!!counta % same page
+ \ifdim\!!dimenb>\!!dimena
+ \donefalse % out of order nodes
+ \else
+ \donetrue % nodes in order
+ \fi
+ \else
+ \donetrue % different page
+ \fi
+ \ifdone
+ \!!counta\!!countb
+ \!!dimena\!!dimenb
+ \advance\!!countc\plusone
+ \edef\!!stringa{[#1][\the\!!countc]:=}%
+ \edef\!!stringc{\s!syncpos:#1:\the\!!countc}%
+ \edef\!!stringd{\MPplus\!!stringc{1}{0}}%
+ \setxvalue{\s!syncpos:#1}%
+ {\getsyncpositions{#1}%
+ sync_p \!!stringa \MPp \!!stringc ;
+ sync_xy\!!stringa \MPxy\!!stringc ;
+ sync_w \!!stringa \MPw \!!stringc ;
+ sync_h \!!stringa \MPh \!!stringc ;
+ sync_d \!!stringa \MPd \!!stringc ;
+ \ifx\!!stringd\empty \else sync_t \!!stringa \MPplus\!!stringc{1}{0} ; \fi}%
+ \fi}
+ {\setxvalue{\s!syncpos:#1}%
+ {\getsyncpositions{#1}%
+ sync_n[#1] := \the\!!countc ;}
+ \exitloop}}%
+ \stopnointerference}
+
+\def\getsyncpositions#1%
+ {\getvalue{\s!syncpos:#1}}
+
+\newtoks\resetsyncpositions
+\newtoks\presetsyncpositions
+
+\def\resyncposition {\dodoubleargument\doresyncposition}
+\def\presyncposition{\dodoubleargument\dopresyncposition}
+
+\def\dodoresyncposition #1#2{\dodosyncposition{#1}{#2}\s!reset}
+\def\dodopresyncposition#1#2{\dodosyncposition{#1}{#2}\s!preset}
+
+\def\doresyncposition [#1][#2]{\setxvalue{\s!reset :\s!syncpos:#1}{\noexpand\dodoresyncposition{#1}{#2}}}
+\def\dopresyncposition[#1][#2]{\setxvalue{\s!preset:\s!syncpos:#1}{\noexpand\dodopresyncposition{#1}{#2}}}
+
+\def\flushsyncpositions % this order !
+ {\begingroup
+ \the\presetsyncpositions
+ \the\resetsyncpositions
+ \endgroup}
+
+\def\flushsyncxxsets#1%
+ {\setbox\scratchbox\hbox{\the#1}%
+ \ifvoid\scratchbox\else
+ \prewordbreak \let\prewordbreak\relax % only once
+ \smashbox\scratchbox
+ \box\scratchbox
+ \fi}
+
+\def\flushsyncresets {\flushsyncxxsets\resetsyncpositions }
+\def\flushsyncpresets{\flushsyncxxsets\presetsyncpositions}
+
+% \appendtoks \flushsyncpositions \to \everypar
+% \appendtoks \flushsyncpositions \to \everyheadstart
+
+% \explicitneverypar -> in grid snapper, eerst testen
+%
+% \appendtoks \flushsyncpositions \to \neverypar
+
+\protect \endinput
+
+\starttext
+
+\definesyncpositions[1]
+
+\startuseMPgraphic{sync}
+ StartPage ;
+ \getsyncpositions{1} ;
+ SyncThreshold := 2LineHeight ;
+ SyncLeftOffset := -.5LeftMarginDistance ;
+ % SetSyncThreshold(1,3,3LineHeight) ;
+ SyncWidth := - (BackSpace + SyncLeftOffset) ;
+ SetSyncColor(1,1,\MPcolor{red}) ;
+ SetSyncColor(1,2,\MPcolor{green}) ;
+ SetSyncColor(1,3,\MPcolor{blue}) ;
+ SetSyncColor(1,4,\MPcolor{yellow}) ;
+ PrepareSyncTasks(1,true,true,false) ;
+ for i = 1 upto NOfSyncPaths :
+ fill SyncPaths[i]
+ withcolor TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]]) ;
+ endfor ;
+ setbounds currentpicture to Page ;
+ StopPage ;
+\stopuseMPgraphic
+
+\defineoverlay[tempoverlay][\useMPgraphic{sync}]
+
+\setupbackgrounds[page][background=tempoverlay]
+
+\syncposition[1][1] \input ward \endgraf
+\syncposition[1][2] \input ward \endgraf
+\syncposition[1][3] \input ward \endgraf
+\syncposition[1][4] \input ward \endgraf
+
+\stoptext
diff --git a/tex/context/base/anch-snc.mkiv b/tex/context/base/anch-snc.mkiv
new file mode 100644
index 000000000..f976047c9
--- /dev/null
+++ b/tex/context/base/anch-snc.mkiv
@@ -0,0 +1,185 @@
+%D \module
+%D [ file=anch-snc,
+%D version=2003.12.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Synchronization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% this can be optimized (will do when used again)
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Synchronization}
+
+\unprotect
+
+\ifx\s!set \undefined \def\s!set {set} \fi
+\ifx\s!reset \undefined \def\s!reset {reset} \fi
+\ifx\s!preset \undefined \def\s!preset {preset} \fi
+\ifx\s!syncpos\undefined \def\s!syncpos{syncpos} \fi
+
+\unexpanded\def\definesyncpositions[#1]%
+ {\global\let\flushsyncpositions\doflushsyncpositions % only when used
+ \setcounter{\s!num:\s!syncpos:#1}{0}%
+ \doglobal\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions
+ \doglobal\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions
+% to be tested:
+% \doglobal\expandafter\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions
+% \doglobal\expandafter\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions
+ \setgvalue{\s!syncpos:#1}{sync_n[#1] := 0 ;}%
+ \setgvalue{\s!set:\s!syncpos:#1}{\dosetsyncpositions{#1}}}
+
+\def\syncposition
+ {\dodoubleempty\dosyncposition}
+
+\def\dosyncposition[#1][#2]%
+ {\letgvalue{\s!reset :\s!syncpos:#1}\relax
+ \letgvalue{\s!preset:\s!syncpos:#1}\relax
+ \dontleavehmode
+ \dodosyncposition{#1}{#2}\s!set
+ \ignorespaces}
+
+\def\doifelselastsyncposition#1#2%
+ {\doifelse{\lastsyncclass\lastsyncposition}{#1#2}}
+
+\def\dodosyncposition#1#2#3%
+ {\letgvalue{\s!reset:\s!syncpos:#1}\relax
+ \letgvalue{\s!preset:\s!syncpos:#1}\relax
+ \ifcsname\s!syncpos:#1\endcsname
+ \pluscounter{\s!num:\s!syncpos:#1}%
+ \setsyncpositions{#1}%
+ % option: geen w/h, alleen p 0 0 0 data
+ \setpositionplus
+ {\s!syncpos:#1:\countervalue{\s!num:\s!syncpos:#1}}%
+ {#2}%
+ \hbox{\strut\traceposstring\llap\green{#3/\countervalue{\s!num:\s!syncpos:#1}/#1/#2>>}}%
+ \else
+ \strut
+ \fi}
+
+\def\setsyncpositions#1%
+ {\enabletextarearegistration
+ \getvalue {\s!set:\s!syncpos:#1}%
+ \letgvalue{\s!set:\s!syncpos:#1}\relax}
+
+\def\dosetsyncpositions#1%
+ {\startnointerference % removing out of sync can best be done in mp
+ \!!dimena\maxdimen
+ \!!counta\zerocount
+ \!!countc\zerocount
+ \doloop
+ {\doifpositionelse{\s!syncpos:#1:\recurselevel}
+ {\!!dimenb\MPy{\s!syncpos:#1:\recurselevel}\relax
+ \!!countb\MPp{\s!syncpos:#1:\recurselevel}\relax
+ \ifnum\!!countb=\!!counta % same page
+ \ifdim\!!dimenb>\!!dimena
+ \donefalse % out of order nodes
+ \else
+ \donetrue % nodes in order
+ \fi
+ \else
+ \donetrue % different page
+ \fi
+ \ifdone
+ \!!counta\!!countb
+ \!!dimena\!!dimenb
+ \advance\!!countc\plusone
+ \edef\!!stringa{[#1][\the\!!countc]:=}%
+ \edef\!!stringc{\s!syncpos:#1:\the\!!countc}%
+ \edef\!!stringd{\MPplus\!!stringc{1}{0}}%
+ \setxvalue{\s!syncpos:#1}%
+ {\getsyncpositions{#1}%
+ sync_p \!!stringa \MPp \!!stringc ;
+ sync_xy\!!stringa \MPxy\!!stringc ;
+ sync_w \!!stringa \MPw \!!stringc ;
+ sync_h \!!stringa \MPh \!!stringc ;
+ sync_d \!!stringa \MPd \!!stringc ;
+ \ifx\!!stringd\empty \else sync_t \!!stringa \MPplus\!!stringc{1}{0} ; \fi}%
+ \fi}
+ {\setxvalue{\s!syncpos:#1}%
+ {\getsyncpositions{#1}%
+ sync_n[#1] := \the\!!countc ;}
+ \exitloop}}%
+ \stopnointerference}
+
+\def\getsyncpositions#1%
+ {\getvalue{\s!syncpos:#1}}
+
+\newtoks\resetsyncpositions
+\newtoks\presetsyncpositions
+
+\def\resyncposition {\dodoubleargument\doresyncposition}
+\def\presyncposition{\dodoubleargument\dopresyncposition}
+
+\def\dodoresyncposition #1#2{\dodosyncposition{#1}{#2}\s!reset}
+\def\dodopresyncposition#1#2{\dodosyncposition{#1}{#2}\s!preset}
+
+\def\doresyncposition [#1][#2]{\setxvalue{\s!reset :\s!syncpos:#1}{\noexpand\dodoresyncposition{#1}{#2}}}
+\def\dopresyncposition[#1][#2]{\setxvalue{\s!preset:\s!syncpos:#1}{\noexpand\dodopresyncposition{#1}{#2}}}
+
+\let\flushsyncpositions\relax
+
+\def\doflushsyncpositions % this order !
+ {\begingroup
+ \the\presetsyncpositions
+ \the\resetsyncpositions
+ \endgroup}
+
+\def\flushsyncxxsets#1%
+ {\setbox\scratchbox\hbox{\the#1}%
+ \ifvoid\scratchbox\else
+ \prewordbreak \let\prewordbreak\relax % only once
+ \smashbox\scratchbox
+ \box\scratchbox
+ \fi}
+
+\def\flushsyncresets {\flushsyncxxsets\resetsyncpositions }
+\def\flushsyncpresets{\flushsyncxxsets\presetsyncpositions}
+
+% \appendtoks \flushsyncpositions \to \everypar
+% \appendtoks \flushsyncpositions \to \everyheadstart
+
+% \explicitneverypar -> in grid snapper, eerst testen
+%
+% \appendtoks \flushsyncpositions \to \neverypar
+
+\protect \endinput
+
+\starttext
+
+\definesyncpositions[1]
+
+\startuseMPgraphic{sync}
+ StartPage ;
+ \getsyncpositions{1} ;
+ SyncThreshold := 2LineHeight ;
+ SyncLeftOffset := -.5LeftMarginDistance ;
+ % SetSyncThreshold(1,3,3LineHeight) ;
+ SyncWidth := - (BackSpace + SyncLeftOffset) ;
+ SetSyncColor(1,1,\MPcolor{red}) ;
+ SetSyncColor(1,2,\MPcolor{green}) ;
+ SetSyncColor(1,3,\MPcolor{blue}) ;
+ SetSyncColor(1,4,\MPcolor{yellow}) ;
+ PrepareSyncTasks(1,true,true,false) ;
+ for i = 1 upto NOfSyncPaths :
+ fill SyncPaths[i]
+ withcolor TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]]) ;
+ endfor ;
+ setbounds currentpicture to Page ;
+ StopPage ;
+\stopuseMPgraphic
+
+\defineoverlay[tempoverlay][\useMPgraphic{sync}]
+
+\setupbackgrounds[page][background=tempoverlay]
+
+\syncposition[1][1] \input ward \endgraf
+\syncposition[1][2] \input ward \endgraf
+\syncposition[1][3] \input ward \endgraf
+\syncposition[1][4] \input ward \endgraf
+
+\stoptext
diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua
new file mode 100644
index 000000000..81c2f4744
--- /dev/null
+++ b/tex/context/base/attr-ini.lua
@@ -0,0 +1,648 @@
+if not modules then modules = { } end modules ['attr-ini'] = {
+ version = 1.001,
+ comment = "companion to attr-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this module is being reconstructed
+-- we can also do the nsnone via a metatable and then also se index 0
+
+local type = type
+local format, gmatch = string.format, string.gmatch
+local concat = table.concat
+local texsprint = tex.sprint
+
+local ctxcatcodes = tex.ctxcatcodes
+local unsetvalue = attributes.unsetvalue
+
+-- todo: document this but first reimplement this as it reflects the early
+-- days of luatex / mkiv and we have better ways now
+
+-- nb: attributes: color etc is much slower than normal (marks + literals) but ...
+-- nb. too many "0 g"s
+
+nodes = nodes or { }
+states = states or { }
+shipouts = shipouts or { }
+
+-- We can distinguish between rules and glyphs but it's not worth the trouble. A
+-- first implementation did that and while it saves a bit for glyphs and rules, it
+-- costs more resourses for transparencies. So why bother.
+
+--
+-- colors
+--
+
+-- we can also collapse the two attributes: n, n+1, n+2 and then
+-- at the tex end add 0, 1, 2, but this is not faster and less
+-- flexible (since sometimes we freeze color attribute values at
+-- the lua end of the game
+--
+-- we also need to store the colorvalues because we need then in mp
+--
+-- This is a compromis between speed and simplicity. We used to store the
+-- values and data in one array, which made in neccessary to store the
+-- converters that need node constructor into strings and evaluate them
+-- at runtime (after reading from storage). Think of:
+--
+-- colors.strings = colors.strings or { }
+--
+-- if environment.initex then
+-- colors.strings[color] = "return colors." .. colorspace .. "(" .. concat({...},",") .. ")"
+-- end
+--
+-- storage.register("colors/data", colors.strings, "colors.data") -- evaluated
+--
+-- We assume that only processcolors are defined in the format.
+
+colors = colors or { }
+colors.data = colors.data or { }
+colors.values = colors.values or { }
+colors.registered = colors.registered or { }
+
+colors.weightgray = true
+colors.attribute = attributes.private('color')
+colors.selector = attributes.private('colormodel')
+colors.default = 1
+colors.main = nil
+colors.triggering = true
+
+storage.register("colors/values", colors.values, "colors.values")
+storage.register("colors/registered", colors.registered, "colors.registered")
+
+local templates = {
+ rgb = "r:%s:%s:%s",
+ cmyk = "c:%s:%s:%s:%s",
+ gray = "s:%s",
+ spot = "p:%s:%s:%s:%s"
+}
+
+local models = {
+ [interfaces.variables.none] = unsetvalue,
+ black = unsetvalue,
+ bw = unsetvalue,
+ all = 1,
+ gray = 2,
+ rgb = 3,
+ cmyk = 4,
+}
+
+colors.model = "all"
+
+local data = colors.data
+local values = colors.values
+local registered = colors.registered
+
+local numbers = attributes.numbers
+local list = attributes.list
+
+local min, max, floor = math.min, math.max, math.floor
+
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
+local registrations = backends.registrations
+
+local function rgbtocmyk(r,g,b) -- we could reduce
+ return 1-r, 1-g, 1-b, 0
+end
+
+local function cmyktorgb(c,m,y,k)
+ return 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k)
+end
+
+local function rgbtogray(r,g,b)
+ if colors.weightgray then
+ return .30*r+.59*g+.11*b
+ else
+ return r/3+g/3+b/3
+ end
+end
+
+local function cmyktogray(c,m,y,k)
+ return rgbtogray(cmyktorgb(c,m,y,k))
+end
+
+-- http://en.wikipedia.org/wiki/HSI_color_space
+-- http://nl.wikipedia.org/wiki/HSV_(kleurruimte)
+
+
+local function hsvtorgb(h,s,v)
+ -- h = h % 360
+ local hd = h/60
+ local hf = floor(hd)
+ local hi = hf % 6
+ -- local f = hd - hi
+ local f = hd - hf
+ local p = v * (1 - s)
+ local q = v * (1 - f * s)
+ local t = v * (1 - (1 - f) * s)
+ if hi == 0 then
+ return v, t, p
+ elseif hi == 1 then
+ return q, v, p
+ elseif hi == 2 then
+ return p, v, t
+ elseif hi == 3 then
+ return p, q, v
+ elseif hi == 4 then
+ return t, p, v
+ elseif hi == 5 then
+ return v, p, q
+ else
+ print("error in hsv -> rgb",hi,h,s,v)
+ end
+end
+
+function rgbtohsv(r,g,b)
+ local offset, maximum, other_1, other_2
+ if r >= g and r >= b then
+ offset, maximum, other_1, other_2 = 0, r, g, b
+ elseif g >= r and g >= b then
+ offset, maximum, other_1, other_2 = 2, g, b, r
+ else
+ offset, maximum, other_1, other_2 = 4, b, r, g
+ end
+ if maximum == 0 then
+ return 0, 0, 0
+ end
+ local minimum = other_1 < other_2 and other_1 or other_2
+ if maximum == minimum then
+ return 0, 0, maximum
+ end
+ local delta = maximum - minimum
+ return (offset + (other_1-other_2)/delta)*60, delta/maximum, maximum
+end
+
+function graytorgb(s) -- unweighted
+ return 1-s, 1-s, 1-s
+end
+
+function hsvtogray(h,s,v)
+ return rgb_to_gray(hsv_to_rgb(h,s,v))
+end
+
+function grayto_hsv(s)
+ return 0, 0, s
+end
+
+colors.rgbtocmyk = rgbtocmyk
+colors.rgbtogray = rgbtogray
+colors.cmyktorgb = cmyktorgb
+colors.cmyktogray = cmyktogray
+colors.rgbtohsv = rgbtohsv
+colors.hsvtorgb = hsvtorgb
+colors.hsvtogray = hsvtogray
+colors.graytohsv = graytohsv
+
+-- we can share some *data by using s, rgb and cmyk hashes, but
+-- normally the amount of colors is not that large; storing the
+-- components costs a bit of extra runtime, but we expect to gain
+-- some back because we have them at hand; the number indicates the
+-- default color space
+
+function colors.gray(s)
+ return { 2, s, s, s, s, 0, 0, 0, 1-s }
+end
+
+function colors.rgb(r,g,b)
+ local s = rgbtogray(r,g,b)
+ local c, m, y, k = rgbtocmyk(r,g,b)
+ return { 3, s, r, g, b, c, m, y, k }
+end
+
+function colors.cmyk(c,m,y,k)
+ local s = cmyktogray(c,m,y,k)
+ local r, g, b = cmyktorgb(c,m,y,k)
+ return { 4, s, r, g, b, c, m, y, k }
+end
+
+--~ function colors.spot(parent,f,d,p)
+--~ return { 5, .5, .5, .5, .5, 0, 0, 0, .5, parent, f, d, p }
+--~ end
+
+function colors.spot(parent,f,d,p)
+ if type(p) == "number" then
+ local n = list[numbers.color][parent] -- hard coded ref to color number
+ if n then
+ local v = values[n]
+ if v then
+ -- the via cmyk hack is dirty, but it scales better
+ local c, m, y, k = p*v[6], p*v[7], p*v[8], p*v[8]
+ local r, g, b = cmyktorgb(c,m,y,k)
+ local s = cmyktogray(c,m,y,k)
+ return { 5, s, r, g, b, c, m, y, k, parent, f, d, p }
+ end
+ end
+ else
+ -- todo, multitone (maybe p should be a table)
+ end
+ return { 5, .5, .5, .5, .5, 0, 0, 0, .5, parent, f, d, p }
+end
+
+local function graycolor(...) graycolor = nodeinjections.graycolor return graycolor(...) end
+local function rgbcolor (...) rgbcolor = nodeinjections.rgbcolor return rgbcolor (...) end
+local function cmykcolor(...) cmykcolor = nodeinjections.cmykcolor return cmykcolor(...) end
+local function spotcolor(...) spotcolor = nodeinjections.spotcolor return spotcolor(...) end
+
+local function extender(colors,key)
+ if key == "none" then
+ local d = graycolor(0)
+ colors.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ local v = values[n]
+ local d
+ if not v then
+ local gray = graycolor(0)
+ d = { gray, gray, gray, gray }
+ logs.report("attributes","unable to revive color %s",n or "?")
+ else
+ local kind = v[1]
+ if kind == 2 then
+ local gray= graycolor(v[2])
+ d = { gray, gray, gray, gray }
+ elseif kind == 3 then
+ local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9])
+ d = { rgb, gray, rgb, cmyk }
+ elseif kind == 4 then
+ local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9])
+ d = { cmyk, gray, rgb, cmyk }
+ elseif kind == 5 then
+ local spot = spotcolor(v[10],v[11],v[12],v[13])
+ -- d = { spot, gray, rgb, cmyk }
+ d = { spot, spot, spot, spot }
+ end
+ end
+ data[n] = d
+ return d
+end
+
+setmetatable(colors, { __index = extender })
+setmetatable(colors.data, { __index = reviver })
+
+function colors.filter(n)
+ return concat(data[n],":",5)
+end
+
+function colors.setmodel(name,weightgray)
+ colors.model = name
+ colors.default = models[name] or 1
+ colors.weightgray = weightgray ~= false
+ return colors.default
+end
+
+function colors.register(name, colorspace, ...) -- passing 9 vars is faster (but not called that often)
+ local stamp = format(templates[colorspace],...)
+ local color = registered[stamp]
+ if not color then
+ color = #values + 1
+ values[color] = colors[colorspace](...)
+ registered[stamp] = color
+ -- colors.reviver(color)
+ end
+ if name then
+ list[colors.attribute][name] = color -- not grouped, so only global colors
+ end
+ return registered[stamp]
+end
+
+function colors.value(id)
+ return values[id]
+end
+
+shipouts.handle_color = nodes.install_attribute_handler {
+ name = "color",
+ namespace = colors,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.selective,
+ resolver = function() return colors.main end,
+}
+
+function colors.enable()
+ tasks.enableaction("shipouts","shipouts.handle_color")
+end
+
+-- transparencies
+
+transparencies = transparencies or { }
+transparencies.registered = transparencies.registered or { }
+transparencies.data = transparencies.data or { }
+transparencies.values = transparencies.values or { }
+transparencies.triggering = true
+transparencies.attribute = attributes.private('transparency')
+
+storage.register("transparencies/registered", transparencies.registered, "transparencies.registered")
+storage.register("transparencies/values", transparencies.values, "transparencies.values")
+
+local registered = transparencies.registered -- we could use a 2 dimensional table instead
+local data = transparencies.data
+local values = transparencies.values
+local template = "%s:%s"
+
+local function inject_transparency (...)
+ inject_transparency = nodeinjections.transparency
+ return inject_transparency(...)
+end
+
+local function register_transparency(...)
+ register_transparency = registrations.transparency
+ return register_transparency(...)
+end
+
+function transparencies.register(name,a,t,force) -- name is irrelevant here (can even be nil)
+ -- Force needed here for metapost converter. We could always force
+ -- but then we'd end up with transparencies resources even if we
+ -- would not use transparencies (but define them only). This is
+ -- somewhat messy.
+ local stamp = format(template,a,t)
+ local n = registered[stamp]
+ if not n then
+ n = #values + 1
+ values[n] = { a, t }
+ registered[stamp] = n
+ if force then
+ register_transparency(n,a,t)
+ end
+ elseif force and not data[n] then
+ register_transparency(n,a,t)
+ end
+ return registered[stamp]
+end
+
+local function extender(transparencies,key)
+ if key == "none" then
+ local d = inject_transparency(0)
+ transparencies.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ local v = values[n]
+ local d
+ if not v then
+ d = inject_transparency(0)
+ else
+ d = inject_transparency(n)
+ register_transparency(n,v[1],v[2])
+ end
+ data[n] = d
+ return d
+end
+
+setmetatable(transparencies, { __index = extender })
+setmetatable(transparencies.data, { __index = reviver }) -- register if used
+
+-- check if there is an identity
+
+function transparencies.value(id)
+ return values[id]
+end
+
+shipouts.handle_transparency = nodes.install_attribute_handler {
+ name = "transparency",
+ namespace = transparencies,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+function transparencies.enable()
+ tasks.enableaction("shipouts","shipouts.handle_transparency")
+end
+
+--- colorintents: overprint / knockout
+
+colorintents = colorintents or { }
+colorintents.data = colorintents.data or { }
+colorintents.attribute = attributes.private('colorintent')
+
+colorintents.registered = {
+ overprint = 1,
+ knockout = 2,
+}
+
+local data, registered = colorintents.data, colorintents.registered
+
+local function extender(colorintents,key)
+ if key == "none" then
+ local d = data[2]
+ colorintents.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ if n == 1 then
+ local d = nodeinjections.overprint() -- called once
+ data[1] = d
+ return d
+ elseif n == 2 then
+ local d = nodeinjections.knockout() -- called once
+ data[2] = d
+ return d
+ end
+end
+
+setmetatable(colorintents, { __index = extender })
+setmetatable(colorintents.data, { __index = reviver })
+
+function colorintents.register(stamp)
+ return registered[stamp] or registered.overprint
+end
+
+shipouts.handle_colorintent = nodes.install_attribute_handler {
+ name = "colorintent",
+ namespace = colorintents,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+function colorintents.enable()
+ tasks.enableaction("shipouts","shipouts.handle_colorintent")
+end
+
+--- negative / positive
+
+negatives = negatives or { }
+negatives.data = negatives.data or { }
+negatives.attribute = attributes.private("negative")
+
+negatives.registered = {
+ positive = 1,
+ negative = 2,
+}
+
+local data, registered = negatives.data, negatives.registered
+
+local function extender(negatives,key)
+ if key == "none" then
+ local d = data[1]
+ negatives.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ if n == 1 then
+ local d = nodeinjections.positive() -- called once
+ data[1] = d
+ return d
+ elseif n == 2 then
+ local d = nodeinjections.negative() -- called once
+ data[2] = d
+ return d
+ end
+end
+
+setmetatable(negatives, { __index = extender })
+setmetatable(negatives.data, { __index = reviver })
+
+function negatives.register(stamp)
+ return registered[stamp] or registered.positive
+end
+
+shipouts.handle_negative = nodes.install_attribute_handler {
+ name = "negative",
+ namespace = negatives,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+function negatives.enable()
+ tasks.enableaction("shipouts","shipouts.handle_negative")
+end
+
+-- effects -- can be optimized (todo: metatables)
+
+effects = effects or { }
+effects.data = effects.data or { }
+effects.values = effects.values or { }
+effects.registered = effects.registered or { }
+effects.stamp = "%s:%s:%s"
+effects.attribute = attributes.private("effect")
+
+storage.register("effects/registered", effects.registered, "effects.registered")
+storage.register("effects/values", effects.values, "effects.values")
+
+local data, registered, values = effects.data, effects.registered, effects.values
+
+-- valid effects: normal inner outer both hidden (stretch,rulethickness,effect)
+
+local function effect(...) effect = nodeinjections.effect return effect(...) end
+
+local function extender(effects,key)
+ if key == "none" then
+ local d = effect(0,0,0)
+ effects.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ local e = values[n] -- we could nil values[n] now but hardly needed
+ local d = effect(e[1],e[2],e[3])
+ data[n] = d
+ return d
+end
+
+setmetatable(effects, { __index = extender })
+setmetatable(effects.data, { __index = reviver })
+
+function effects.register(effect,stretch,rulethickness)
+ local stamp = format(effects.stamp,effect,stretch,rulethickness)
+ local n = registered[stamp]
+ if not n then
+ n = #values + 1
+ values[n] = { effect, stretch, rulethickness }
+ registered[stamp] = n
+ end
+ return n
+end
+
+shipouts.handle_effect = nodes.install_attribute_handler {
+ name = "effect",
+ namespace = effects,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
+}
+
+function effects.enable()
+ tasks.enableaction("shipouts","shipouts.handle_effect")
+end
+
+-- layers (ugly code, due to no grouping and such); currently we use exclusive layers
+-- but when we need it stacked layers might show up too; the next function based
+-- approach can be replaced by static (metatable driven) resolvers
+
+viewerlayers = viewerlayers or { }
+viewerlayers.data = viewerlayers.data or { }
+viewerlayers.registered = viewerlayers.registered or { }
+viewerlayers.values = viewerlayers.values or { }
+viewerlayers.listwise = viewerlayers.listwise or { }
+viewerlayers.attribute = attributes.private("viewerlayer")
+
+storage.register("viewerlayers/registered", viewerlayers.registered, "viewerlayers.registered")
+storage.register("viewerlayers/values", viewerlayers.values, "viewerlayers.values")
+
+local data = viewerlayers.data
+local values = viewerlayers.values
+local listwise = viewerlayers.listwise
+local registered = viewerlayers.registered
+local template = "%s"
+
+-- stacked
+
+local function extender(viewerlayers,key)
+ if key == "none" then
+ local d = nodeinjections.stoplayer()
+ viewerlayers.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ local d = nodeinjections.startlayer(values[n])
+ data[n] = d
+ return d
+end
+
+setmetatable(viewerlayers, { __index = extender })
+setmetatable(viewerlayers.data, { __index = reviver })
+
+local function initializer(...)
+ return states.initialize(...)
+end
+
+viewerlayers.register = function(name,lw) -- if not inimode redefine data[n] in first call
+ local stamp = format(template,name)
+ local n = registered[stamp]
+ if not n then
+ n = #values + 1
+ values[n] = name
+ registered[stamp] = n
+ listwise[n] = lw or false
+ end
+ return registered[stamp] -- == n
+end
+
+shipouts.handle_viewerlayer = nodes.install_attribute_handler {
+ name = "viewerlayer",
+ namespace = viewerlayers,
+ initializer = initializer,
+ finalizer = states.finalize,
+ processor = states.stacked,
+}
+
+function viewerlayers.enable()
+ tasks.enableaction("shipouts","shipouts.handle_viewerlayer")
+end
diff --git a/tex/context/base/attr-ini.mkiv b/tex/context/base/attr-ini.mkiv
new file mode 100644
index 000000000..87d06c48a
--- /dev/null
+++ b/tex/context/base/attr-ini.mkiv
@@ -0,0 +1,170 @@
+%D \module
+%D [ file=attr-ini,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 Attribute Macros / Initialization}
+
+%D Although it's still somewhat experimental, here we introduce code
+%D related to attributes.
+
+\unprotect
+
+\registerctxluafile{attr-ini}{1.001}
+
+%D This might move:
+
+\def\pushattribute#1%
+ {\global\advance\csname\??ae:\string#1\endcsname\plusone
+ \global\expandafter\mathchardef\csname\??ae:\string#1:\number\csname\??ae:\string#1\endcsname\endcsname\attribute#1}
+
+\def\popattribute#1%
+ {\attribute#1\csname\??ae:\string#1:\number\csname\??ae:\string#1\endcsname\endcsname
+ \global\advance\csname\??ae:\string#1\endcsname\minusone}
+
+\def\installattributestack#1%
+ {\expandafter\newcount\csname\??ae:\string#1\endcsname}
+
+%D For the moment we put this here (later it will move to where it's used):
+
+\definesystemattribute[state]
+\definesystemattribute[skip]
+\definesystemattribute[penalty]
+\definesystemattribute[colormodel][global] \chardef\colormodelattribute \dogetattributeid{colormodel}
+\definesystemattribute[color] \chardef\colorattribute \dogetattributeid{color}
+\definesystemattribute[transparency] \chardef\transparencyattribute \dogetattributeid{transparency}
+\definesystemattribute[background] \chardef\backgroundattribute \dogetattributeid{background}
+\definesystemattribute[colorintent] \chardef\colorintentattribute \dogetattributeid{colorintent}
+\definesystemattribute[negative] \chardef\negativeattribute \dogetattributeid{negative}
+\definesystemattribute[effect] \chardef\effectattribute \dogetattributeid{effect}
+\definesystemattribute[viewerlayer] \chardef\viewerlayerattribute \dogetattributeid{viewerlayer}
+\definesystemattribute[layoutcomponent] \chardef\layoutcomponentattribute\dogetattributeid{layoutcomponent}
+\definesystemattribute[reference] \chardef\referenceattribute \dogetattributeid{reference}
+\definesystemattribute[destination] \chardef\destinationattribute \dogetattributeid{destination}
+\definesystemattribute[graphicvadjust] \chardef\graphicvadjustattribute \dogetattributeid{graphicvadjust}
+\definesystemattribute[ruled] \chardef\ruledattribute \dogetattributeid{ruled}
+\definesystemattribute[shifted] \chardef\shiftedattribute \dogetattributeid{shifted}
+
+% \definesystemattribute[ignore]
+%
+% \edef\startignorecontent{\dosetattribute{ignore}\plusone}
+% \edef\stopignorecontent {\doresetattribute{ignore}}
+
+% todo: no need for 'color' argument, we can set that once at startup; currently
+% a bit inconsistent
+
+% 1=off 2=gray 3=spot 4=rgb 5=cmyk 6=cmy % only 1/2/4/5 are supported
+%
+% We could combine this in one attribute but this is not faster and also
+% less flexible because sometimes we want to freeze the attribute bit.
+%
+% Watch out: real color support will be implemented later.
+
+\newcount\currentcolormodel
+
+\def\dosetcolormodel#1%
+ {\currentcolormodel\ctxlua{tex.print(colors.setmodel('#1'))}%
+ \attribute\colormodelattribute\currentcolormodel}
+
+\dosetcolormodel{all}
+
+\appendtoks
+ \dosetcolormodel{all}% redundant?
+\to \everyjob
+
+\def\registerrgbcolor #1#2#3#4{\ctxlua{colors.register('#1','rgb' ,#2,#3,#4)}}
+\def\registercmykcolor#1#2#3#4#5{\ctxlua{colors.register('#1','cmyk',#2,#3,#4,#5)}}
+\def\registergraycolor #1#2{\ctxlua{colors.register('#1','gray',#2)}}
+
+% transparency
+
+\def\registertransparency#1#2#3%
+ {\setevalue{(ts:#1)}{\attribute\transparencyattribute\ctxlua{tex.write(transparencies.register(#2,#3))} }}
+
+\def\sometransparencyswitch#1{\csname(ts:#1)\endcsname}
+
+\def\sometransparencyswitch
+ {\ctxlua{transparencies.enable()}%
+ \gdef\sometransparencyswitch##1{\csname(ts:##1)\endcsname}%
+ \sometransparencyswitch}
+
+% \registertransparency {one} {1} {.5}
+% \registertransparency {two} {1} {.6}
+
+% overprint
+
+\def\registercolorintent#1#2%
+ {\setevalue{(os:#1)}{\attribute\colorintentattribute\ctxlua{tex.write(colorintents.register('#2'))} }}
+
+\def\dotriggercolorintent
+ {\ctxlua{colorintents.enable()}%
+ \gdef\dotriggercolorintent##1{\csname(os:##1)\endcsname}%
+ \dotriggercolorintent}
+
+\registercolorintent{knockout} {knockout}
+\registercolorintent{overprint}{overprint}
+
+\installattributestack\colorintentattribute
+
+\setevalue{(os:#\v!none}{\attribute\colorintentattribute\attributeunsetvalue} % does this work out ok?
+
+% negative
+
+\def\registernegative#1#2%
+ {\setevalue{(ns:#1)}{\attribute\negativeattribute\ctxlua{tex.write(negatives.register('#2'))} }}
+
+\def\dotriggernegative
+ {\ctxlua{negatives.enable()}%
+ \gdef\dotriggernegative##1{\csname(ns:##1)\endcsname}%
+ \dotriggernegative}
+
+\registernegative{positive}{positive}
+\registernegative{negative}{negative}
+
+% effect
+
+\def\registereffect#1#2#3% #2=stretch #3=rulethickness
+ {\setxvalue{(es:#1:#2:\number\dimexpr#3\relax)}%
+ {\attribute\effectattribute\ctxlua{tex.write(effects.register('#1',#2,\number\dimexpr#3\relax))} }}
+
+\def\dotriggereffect
+ {\ctxlua{effects.enable()}%
+ \gdef\dotriggereffect##1##2##3%
+ {\ifcsname(es:##1:##2:\number\dimexpr##3\relax)\endcsname\else\registereffect{##1}{##2}{##3}\fi
+ \csname(es:##1:##2:\number\dimexpr##3\relax)\endcsname}%
+ \dotriggereffect}
+
+% \registereffect{normal}
+% \registereffect{inner}
+% \registereffect{outer}
+% \registereffect{both}
+% \registereffect{hidden}
+
+% viewerlayers (will probably change a bit)
+
+% needs to work over stopitemize grouping etc
+
+\def\registerviewerlayer#1#2% global !
+ {\setxvalue{(vl:#1)}{\global\attribute\viewerlayerattribute\ctxlua{tex.write(viewerlayers.register('#2'))} }}
+
+\setevalue{(vl:)}{\global\attribute\viewerlayerattribute\attributeunsetvalue}
+
+\def\dotriggerviewerlayer
+ {\ctxlua{viewerlayers.enable()}%
+ \gdef\dotriggerviewerlayer##1{\csname(vl:##1)\endcsname}%
+ \dotriggerviewerlayer}
+
+\protect \endinput
+
+% test case
+%
+% {\green \hbox to \hsize{\leaders\hrule \hfill a}\par}
+% {\red \hbox to \hsize{\leaders\hbox{x}\hfill a}\par}
diff --git a/tex/context/base/back-ini.lua b/tex/context/base/back-ini.lua
new file mode 100644
index 000000000..12a487dd4
--- /dev/null
+++ b/tex/context/base/back-ini.lua
@@ -0,0 +1,143 @@
+if not modules then modules = { } end modules ['back-ini'] = {
+ version = 1.001,
+ comment = "companion to back-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+backends = backends or { }
+
+local trace_backend = false
+
+local function nothing() return nil end
+
+backends.nothing = nothing
+
+backends.nodeinjections = {
+ rgbcolor = nothing,
+ cmykcolor = nothing,
+ graycolor = nothing,
+ spotcolor = nothing,
+ transparency = nothing,
+ overprint = nothing,
+ knockout = nothing,
+ positive = nothing,
+ negative = nothing,
+ effect = nothing,
+ startlayer = nothing,
+ stoplayer = nothing,
+ switchlayer = nothing,
+
+ reference = nothing,
+ destination = nothing,
+
+}
+
+backends.codeinjections = {
+
+ prerollreference = nothing,
+
+ insertmovie = nothing,
+ insertsound = nothing,
+
+ presetsymbollist = nothing,
+ registersymbol = nothing,
+ registeredsymbol = nothing,
+
+ registercomment = nothing,
+ embedfile = nothing,
+ attachfile = nothing,
+ adddocumentinfo = nothing,
+ setupidentity = nothing,
+ setpagetransition = nothing,
+ defineviewerlayer = nothing,
+ addbookmarks = nothing,
+ addtransparencygroup = nothing,
+
+ typesetfield = nothing,
+ doiffieldelse = nothing,
+ doiffieldgroupelse = nothing,
+ definefield = nothing,
+ clonefield = nothing,
+ definefieldset = nothing,
+ getfieldgroup = nothing,
+ setformsmethod = nothing,
+ getdefaultfieldvalue = nothing,
+
+ setupcanvas = nothing,
+
+ initializepage = nothing,
+ initializedocument = nothing,
+ finalizepage = nothing,
+ finalizedocument = nothing,
+
+ flushpageactions = nothing,
+ flushdocumentactions = nothing,
+
+ insertrenderingwindow = nothing,
+ processrendering = nothing,
+ kindofrendering = nothing,
+ flushrenderingwindow = nothing,
+
+ setfigurecolorspace = nothing,
+ setfigurealternative = nothing,
+
+}
+
+backends.registrations = {
+ grayspotcolor = nothing,
+ rgbspotcolor = nothing,
+ cmykspotcolor = nothing,
+ grayindexcolor = nothing,
+ rgbindexcolor = nothing,
+ cmykindexcolor = nothing,
+ spotcolorname = nothing,
+ transparency = nothing,
+}
+
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
+local registrations = backends.registrations
+
+backends.current = "unknown"
+
+function backends.install(what)
+ if type(what) == "string" then
+ local backend = backends[what]
+ if backend then
+ if trace_backend then
+ logs.report("backend", "initializing backend %s (%s)",what,backend.comment or "no comment")
+ end
+ backends.current = what
+ for _, category in next, { "nodeinjections", "codeinjections", "registrations"} do
+ local plugin = backend[category]
+ if plugin then
+ local whereto = backends[category]
+ for name, meaning in next, whereto do
+ if plugin[name] then
+ whereto[name] = plugin[name]
+ -- logs.report("backend", "installing function %s in category %s of %s",name,category,what)
+ elseif trace_backend then
+ logs.report("backend", "no function %s in category %s of %s",name,category,what)
+ end
+ end
+ elseif trace_backend then
+ logs.report("backend", "no category %s in %s",category,what)
+ end
+ end
+ backends.helpers = backend.helpers
+ elseif trace_backend then
+ logs.report("backend", "no backend named %s",what)
+ end
+ end
+end
+
+statistics.register("used backend", function()
+ local bc = backends.current
+ if bc ~= "unknown" then
+ return string.format("%s (%s)",bc,backends[bc].comment or "no comment")
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/back-ini.mkiv b/tex/context/base/back-ini.mkiv
new file mode 100644
index 000000000..b7bbdb56f
--- /dev/null
+++ b/tex/context/base/back-ini.mkiv
@@ -0,0 +1,168 @@
+%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]
+%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 Most will go away here as it is replaced by \LUA\ calls to
+%D backend functions.
+
+\writestatus{loading}{ConTeXt Backend Macros / Initialization}
+
+\registerctxluafile{back-ini}{1.001}
+
+%D We currently have a curious mix between tex and lua backend
+%D handling but eventually most will move to lua.
+
+\unprotect
+
+\ifdefined\everybackendshipout \else \newtoks\everybackendshipout \fi
+\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi
+
+%D Right from the start \CONTEXT\ had a backend system based on
+%D runtime pluggable code. As most backend issues involved specials
+%D and since postprocessors had not that much in common, we ended up
+%D with a system where we could switch backend as well as output code
+%D for multiple backends at the same time.
+%D
+%D Because \LUATEX\ has the backend built in, and since some backend
+%D issues have been moved to the frontend I decided to provide new
+%D backend code for \MKIV, starting with what was actually used.
+%D
+%D At this moment \DVI\ is no longer used for advanced document
+%D output and we therefore dropped support for this format. Future
+%D versions might support more backends again, but this has a low
+%D priority.
+%D
+%D The big question is: what is to be considered a backend issue and
+%D what not. For the moment we treat image inclusion, object reuse,
+%D position tracking and color as frontend issues, if only because we
+%D deal with them via \LUA\ code and as such we don't depend too much
+%D on macro calls that need to inject code for the backend.
+%D
+%D Not everything here makes sense and the content of this file will
+%D definitely change.
+
+\let \dostartrotation \gobbleoneargument
+\let \dostoprotation \donothing
+\let \dostartscaling \gobbletwoarguments
+\let \dostopscaling \donothing
+\let \dostartmirroring \donothing
+\let \dostopmirroring \donothing
+
+%D \macros
+%D {doovalbox}
+%D
+%D When we look at the implementation, this is a complicated
+%D one. There are seven arguments.
+%D
+%D \starttyping
+%D \doovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant}
+%D \stoptyping
+%D
+%D This command has to return a \type{\vbox} which can be used
+%D to lay over another one (with text). The radius is in
+%D degrees, the stroke and fill are~\type{1} (true) of~\type{0}
+%D (false).
+
+\let \doovalbox \gobbleeightarguments
+
+%D \macros
+%D {dostartclipping,dostopclipping}
+%D
+%D Clipping is implemented in such a way that an arbitrary code
+%D can be fed.
+%D
+%D \starttyping
+%D \dostartclipping {pathname} {width} {height}
+%D \dostopclipping
+%D \stoptyping
+
+\let \dostartclipping \gobblethreearguments
+\let \dostopclipping \donothing
+
+%D \macros
+%D {dostartobject,
+%D dostopobject,
+%D doresetobjects,
+%D doinsertobject}
+%D
+%D Reuse of object can reduce the output filesize
+%D considerably. Reusable objects are implemented with:
+%D
+%D \starttyping
+%D \dostartobject{class}{name}{width}{height}{depth}
+%D some typeset material
+%D \dostopobject
+%D \stoptyping
+%D
+%D \starttyping
+%D \doinsertobject{class}{name}
+%D \stoptyping
+%D
+%D The savings can be huge in interactive texts. The next macro needs
+%D to be called after a graphic is inserted (in order to clean up
+%D global references).
+%D
+%D \starttyping
+%D \doresetobjects
+%D \stoptyping
+
+\let \dostartobject \gobblefourarguments
+\let \dostopobject \donothing
+\let \doinsertobject \gobbletwoarguments
+\let \doresetobjects \donothing
+
+%D From now on, mapfile loading is also a special; we assume the
+%D more or less standard dvips syntax.
+
+\let \doresetmapfilelist \donothing
+\let \doloadmapfile \gobbletwoarguments % + - = | filename
+\let \doloadmapline \gobbletwoarguments % + - = | fileline
+
+%D \macros
+%D {ifusepagedestinations}
+%D
+%D In \PDF\ version 1.0 only page references were supported,
+%D while in \DVIWINDO\ 1.N only named references were accepted.
+%D Therefore \CONTEXT\ supports both methods of referencing. In
+%D \PDF\ version 1.1 named destinations arrived. Lack of
+%D continuous support of version 1.1 viewers for \MSDOS\
+%D therefore sometimes forces us to prefer page references. As
+%D a bonus, they are faster too and have no limitations. How
+%D fortunate we were having both mechanisms available when the
+%D version 3.0 (\PDF\ version 1.2) viewers proved to be too
+%D bugged to support named destinations.
+
+\newif\ifusepagedestinations % not yet interfaced in mkiv
+
+%D \macros
+%D {jobsuffix}
+%D
+%D By default, \TEX\ produces \DVI\ files which can be
+%D converted to other filetypes. Sometimes it is handy to
+%D know what the target file will be. In other driver
+%D modules we wil set \type {\jobsuffix} to \type {pdf}.
+
+\def\jobsuffix{pdf}
+
+\ifdefined\resetsystemmode \else
+ \let\setsystemmode \gobbleoneargument
+ \let\resetsystemmode\gobbleoneargument
+\fi
+
+\def\setjobsuffix#1%
+ {\resetsystemmode\jobsuffix
+ \edef\jobsuffix{#1}%
+ \setsystemmode\jobsuffix}
+
+\unexpanded\def\setupoutput[#1]{} % will be command line switch
+
+\protect \endinput
diff --git a/tex/context/base/back-pdf.lua b/tex/context/base/back-pdf.lua
new file mode 100644
index 000000000..54e22f1a2
--- /dev/null
+++ b/tex/context/base/back-pdf.lua
@@ -0,0 +1,469 @@
+if not modules then modules = { } end modules ['back-pdf'] = {
+ version = 1.001,
+ comment = "companion to back-pdf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we will move code to lpdf-* files (second cleanup stage)
+
+--[[ldx--
+
This module implements a couple of cleanup methods. We need these
+in order to meet the specification. Watch the double
+parenthesis; they are needed because otherwise we would pass more
+than one argument to .
+--ldx]]--
+
+local type, next, tostring = type, next, tostring
+local char, byte, format, gsub, rep, gmatch = string.char, string.byte, string.format, string.gsub, string.rep, string.gmatch
+local concat = table.concat
+local round = math.round
+local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
+local texsprint, texwrite = tex.sprint, tex.write
+local ctxcatcodes = tex.ctxcatcodes
+
+local copy_node = node.copy
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local pdfliteral, register = nodes.pdfliteral, nodes.register
+
+local pdfconstant = lpdf.constant
+local pdfstring = lpdf.string
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfverbose = lpdf.verbose
+local pdfflushobject = lpdf.flushobject
+local pdfreserveobject = lpdf.reserveobject
+local pdfannotation = nodes.pdfannotation
+
+local pdfreserveobj = pdf.reserveobj
+local pdfimmediateobj = pdf.immediateobj
+
+function nodeinjections.rgbcolor(r,g,b)
+ return register(pdfliteral(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)))
+end
+
+function nodeinjections.cmykcolor(c,m,y,k)
+ return register(pdfliteral(format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)))
+end
+
+function nodeinjections.graycolor(s) -- caching 0/1 does not pay off
+ return register(pdfliteral(format("%s g %s G",s,s)))
+end
+
+function nodeinjections.spotcolor(n,f,d,p)
+ if type(p) == "string" then
+ p = gsub(p,","," ") -- brr misuse of spot
+ end
+ return register(pdfliteral(format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)))
+end
+
+function nodeinjections.transparency(n)
+ return register(pdfliteral(format("/Tr%s gs",n)))
+end
+
+local effects = {
+ normal = 0,
+ inner = 0,
+ outer = 1,
+ both = 2,
+ hidden = 3,
+}
+
+function nodeinjections.effect(effect,stretch,rulethickness)
+ -- always, no zero test (removed)
+ rulethickness = number.dimenfactors["bp"] * rulethickness
+ effect = effects[effect] or effects['normal']
+ return register(pdfliteral(format("%s Tc %s w %s Tr",stretch,rulethickness,effect))) -- watch order
+end
+
+-- cached ..
+
+local cache = { }
+
+function nodeinjections.startlayer(name)
+ local c = cache[name]
+ if not c then
+ c = register(pdfliteral(format("/OC /%s BDC",name)))
+ cache[name] = c
+ end
+ return copy_node(c)
+end
+
+local stop = register(pdfliteral("EMC"))
+
+function nodeinjections.stoplayer()
+ return copy_node(stop)
+end
+
+local cache = { }
+
+function nodeinjections.switchlayer(name)
+ local c = cache[name]
+ if not c then
+ c = register(pdfliteral(format("EMC /OC /%s BDC",name)))
+ end
+ return copy_node(c)
+end
+
+-- code
+
+function codeinjections.insertmovie(specification)
+ -- managed in figure inclusion: width, height, factor, repeat, controls, preview, label, foundname
+ local width = specification.width
+ local height = specification.height
+ local factor = specification.factor or number.dimenfactors.bp
+ local moviedict = pdfdictionary {
+ F = specification.foundname,
+ Aspect = pdfarray { factor * width, factor * height },
+ Poster = (specification.preview and true) or false,
+ }
+ local controldict = pdfdictionary {
+ ShowControls = (specification.controls and true) or false,
+ Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil,
+ }
+ local action = pdfdictionary {
+ Subtype = pdfconstant("Movie"),
+ Border = pdfarray { 0, 0, 0 },
+ T = format("movie %s",specification.label),
+ Movie = moviedict,
+ A = controldict,
+ }
+ node.write(pdfannotation(width,height,0,action()))
+end
+
+function codeinjections.insertsound(specification)
+ -- rmanaged in interaction: repeat, label, foundname
+ local soundclip = interactions.soundclip(specification.label)
+ if soundclip then
+ local controldict = pdfdictionary {
+ Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil
+ }
+ local sounddict = pdfdictionary {
+ F = soundclip.filename
+ }
+ local action = pdfdictionary {
+ Subtype = pdfconstant("Movie"),
+ Border = pdfarray { 0, 0, 0 },
+ T = format("sound %s",specification.label),
+ Movie = sounddict,
+ A = controldict,
+ }
+ node.write(pdfannotation(0,0,0,action()))
+ end
+end
+
+-- spot- and indexcolors
+
+local pdf_separation = pdfconstant("Separation")
+local pdf_indexed = pdfconstant("Indexed")
+local pdf_device_n = pdfconstant("DeviceN")
+local pdf_device_rgb = pdfconstant("DeviceRGB")
+local pdf_device_cmyk = pdfconstant("DeviceCMYK")
+local pdf_device_gray = pdfconstant("DeviceGray")
+local pdf_extgstate = pdfconstant("ExtGState")
+
+local pdf_rbg_range = pdfarray { 0, 1, 0, 1, 0, 1 }
+local pdf_cmyk_range = pdfarray { 0, 1, 0, 1, 0, 1, 0, 1 }
+local pdf_gray_range = pdfarray { 0, 1 }
+
+local rgb_function = "dup %s mul exch dup %s mul exch %s mul"
+local cmyk_function = "dup %s mul exch dup %s mul exch dup %s mul exch %s mul"
+local gray_function = "%s mul"
+
+local documentcolorspaces = pdfdictionary()
+
+local spotcolorhash = { } -- not needed
+local spotcolornames = { }
+local indexcolorhash = { }
+local delayedindexcolors = { }
+
+function registrations.spotcolorname(name,e)
+ spotcolornames[name] = e or name
+end
+
+local function registersomespotcolor(name,noffractions,names,p,colorspace,range,funct)
+ noffractions = tonumber(noffractions) or 1 -- to be checked
+ if noffractions == 0 then
+ -- can't happen
+ elseif noffractions == 1 then
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = { 0, 1 },
+ Range = range,
+ }
+ local n = pdfimmediateobj("stream",format("{ %s }",funct),dictionary())
+ local array = pdfarray {
+ pdf_separation,
+ pdfconstant(spotcolornames[name] or name),
+ colorspace,
+ pdfreference(n),
+ }
+ local m = pdfimmediateobj(tostring(array))
+ local mr = pdfreference(m)
+ spotcolorhash[name] = m
+ documentcolorspaces[name] = mr
+ lpdf.adddocumentcolorspace(name,mr)
+ else
+ local cnames = pdfarray()
+ local domain = pdfarray()
+ for n in gmatch(names,"[^,]+") do
+ cnames[#cnames+1] = pdfconstant(spotcolornames[n] or n)
+ domain[#domain+1] = 0
+ domain[#domain+1] = 1
+ end
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = domain,
+ Range = range,
+ }
+ local n = pdfimmediateobj("stream",format("{ %s %s }",rep("pop ",noffractions),funct),dictionary())
+ local array = pdfarray {
+ pdf_device_n,
+ cnames,
+ colorspace,
+ pdfreference(n),
+ }
+ local m = pdfimmediateobj(tostring(array))
+ local mr = pdfreference(m)
+ spotcolorhash[name] = m
+ documentcolorspaces[name] = mr
+ lpdf.adddocumentcolorspace(name,mr)
+ end
+end
+
+function registersomeindexcolor(name,noffractions,names,p,colorspace,range,funct)
+ noffractions = tonumber(noffractions) or 1 -- to be checked
+ local cnames = pdfarray()
+ local domain = pdfarray()
+ if names == "" then
+ names = name .. ",None"
+ else
+ names = names .. ",None"
+ end
+ for n in gmatch(names,"[^,]+") do
+ cnames[#cnames+1] = pdfconstant(spotcolornames[n] or n)
+ domain[#domain+1] = 0
+ domain[#domain+1] = 1
+ end
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = domain,
+ Range = range,
+ }
+ local n = pdfimmediateobj("stream",format("{ %s %s }",rep("exch pop ",noffractions),funct),dictionary()) -- exch pop
+ local a = pdfarray {
+ pdf_device_n,
+ cnames,
+ colorspace,
+ pdfreference(n),
+ }
+ if p == "" then
+ p = "1"
+ else
+ p = p .. ",1"
+ end
+ local pi = { }
+ for pp in gmatch(p,"[^,]+") do
+ pi[#pi+1] = tonumber(pp)
+ end
+ local vector, set, n = { }, { }, #pi
+ for i=255,0,-1 do
+ for j=1,n do
+ set[j] = format("%02X",round(pi[j]*i))
+ end
+ vector[#vector+1] = concat(set)
+ end
+ vector = pdfverbose { "<", concat(vector, " "), ">" }
+ local n = pdfimmediateobj(tostring(pdfarray{ pdf_indexed, a, 255, vector }))
+ lpdf.adddocumentcolorspace(format("%s_indexed",name),pdfreference(n))
+ return n
+end
+
+-- actually, names (parent) is the hash
+
+local function delayindexcolor(name,names,func)
+ local hash = (names ~= "" and names) or name
+ -- logs.report("index colors","delaying '%s'",name)
+ delayedindexcolors[hash] = func
+end
+
+local function indexcolorref(name) -- actually, names (parent) is the hash
+ if not indexcolorhash[name] then
+ -- logs.report("index colors","registering '%s'",name)
+ local delayedindexcolor = delayedindexcolors[name]
+ if type(delayedindexcolor) == "function" then
+ indexcolorhash[name] = delayedindexcolor()
+ delayedindexcolors[name] = true
+ end
+ end
+ return indexcolorhash[name]
+end
+
+function registrations.rgbspotcolor(name,noffractions,names,p,r,g,b)
+--~ print(name,noffractions,names,p,r,g,b)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,format(rgb_function,r,g,b))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,format("%s %s %s",r,g,b))
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,format(rgb_function,r,g,b))
+ end)
+end
+
+function registrations.cmykspotcolor(name,noffractions,names,p,c,m,y,k)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format("%s %s %s %s",c,m,y,k))
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
+ end)
+end
+
+function registrations.grayspotcolor(name,noffractions,names,p,s)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,format(gray_function,s))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,s)
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,format(gray_function,s))
+ end)
+end
+
+function registrations.rgbindexcolor(name,noffractions,names,p,r,g,b)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,format(rgb_function,r,g,b))
+end
+
+function registrations.cmykindexcolor(name,noffractions,names,p,c,m,y,k)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
+end
+
+function registrations.grayindexcolor(name,noffractions,names,p,s)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,gray_function)
+end
+
+function codeinjections.setfigurecolorspace(data,figure)
+ local color = data.request.color
+ if color then
+ local ref = indexcolorref(color)
+ if ref then
+ figure.colorspace = ref
+ data.used.color = color
+ end
+ end
+end
+
+-- transparency
+
+local transparencies = { [0] =
+ pdfconstant("Normal"),
+ pdfconstant("Normal"),
+ pdfconstant("Multiply"),
+ pdfconstant("Screen"),
+ pdfconstant("Overlay"),
+ pdfconstant("SoftLight"),
+ pdfconstant("HardLight"),
+ pdfconstant("ColorDodge"),
+ pdfconstant("ColorBurn"),
+ pdfconstant("Darken"),
+ pdfconstant("Lighten"),
+ pdfconstant("Difference"),
+ pdfconstant("Exclusion"),
+ pdfconstant("Compatible"),
+}
+
+local documenttransparencies = { }
+local transparencyhash = { } -- share objects
+
+local done = false
+
+function registrations.transparency(n,a,t)
+ if not done then
+ local d = pdfdictionary {
+ Type = pdf_extgstate,
+ ca = 1,
+ CA = 1,
+ BM = transparencies[1],
+ AIS = false,
+ }
+ local m = pdfimmediateobj(tostring(d))
+ local mr = pdfreference(m)
+ transparencyhash[0] = m
+ documenttransparencies[0] = mr
+ lpdf.adddocumentextgstate("Tr0",mr)
+ done = true
+ end
+ if n > 0 and not transparencyhash[n] then
+ local d = pdfdictionary {
+ Type = pdf_extgstate,
+ ca = tonumber(t),
+ CA = tonumber(t),
+ BM = transparencies[a] or transparencies[0],
+ AIS = false,
+ }
+ local m = pdfimmediateobj(tostring(d))
+ local mr = pdfreference(m)
+ transparencyhash[n] = m
+ documenttransparencies[n] = mr
+ lpdf.adddocumentextgstate(format("Tr%s",n),mr)
+ end
+end
+
+function codeinjections.adddocumentinfo(key,value)
+ lpdf.addtoinfo(key,lpdf.tosixteen(value))
+end
+
+-- graphics
+
+function codeinjections.setfigurealternative(data,figure)
+ local display = data.request.display
+ if display and display ~= "" then
+ local request = data.request
+ figures.push {
+ name = request.display,
+ page = request.page,
+ size = request.size,
+ prefix = request.prefix,
+ cache = request.cache,
+ width = request.width,
+ height = request.height,
+ }
+ figures.identify()
+ local displayfigure = figures.check()
+ if displayfigure then
+ -- figure.aform = true
+ img.immediatewrite(figure)
+ local a = lpdf.array {
+ lpdf.dictionary {
+ Image = lpdf.reference(figure.objnum),
+ DefaultForPrinting = true,
+ }
+ }
+ local d = lpdf.dictionary {
+ Alternates = lpdf.reference(pdf.immediateobj(tostring(a))),
+ }
+ displayfigure.attr = d()
+ return displayfigure, figures.current()
+ end
+ end
+end
+
+-- eventually we need to load this runtime
+--
+-- backends.install((environment and environment.arguments and environment.arguments.backend) or "pdf")
+--
+-- but now we need to force this as we also load the pdf tex part which hooks into all kind of places
+
+codeinjections.finalizepage = lpdf.finalizepage
+codeinjections.finalizedocument = lpdf.finalizedocument
+
+backends.install("pdf")
diff --git a/tex/context/base/back-pdf.mkiv b/tex/context/base/back-pdf.mkiv
new file mode 100644
index 000000000..a10afd5b9
--- /dev/null
+++ b/tex/context/base/back-pdf.mkiv
@@ -0,0 +1,178 @@
+%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]
+%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 / PDF}
+
+\registerctxluafile{back-pdf}{1.001} % this will change
+
+\unprotect
+
+%D We will minimize the number of calls to \PDF\ specific primitives
+%D and delegate all management and injection of code to the backend.
+%D
+%D Here we initialize some internal quantities.
+
+\pdfoutput = 1
+\pdfhorigin = 1 true in
+\pdfvorigin = 1 true in
+\pdfimageresolution = 300
+\pdfpkresolution = 600
+\pdfdecimaldigits = 10
+\pdfinclusionerrorlevel = 0
+\pdfminorversion = 6 % maybe even 7
+%pdfuniqueresname = 1
+
+%D This one can be consulted by users although the suffix is also
+%D a system mode.
+
+\setjobsuffix{pdf}
+
+%D For the moment we keep these.
+
+\newtoks \pdfbackendeveryximage
+\newtoks \pdfbackendeveryxform
+
+%D These are the only official methods to add stuff to the resources.
+
+\def\pdfbackendsetcatalog #1#2{\ctxlua{lpdf.addtocatalog ("#1",\!!bs#2\!!es)}}
+\def\pdfbackendsetinfo #1#2{\ctxlua{lpdf.addtoinfo ("#1",\!!bs#2\!!es)}}
+\def\pdfbackendsetname #1#2{\ctxlua{lpdf.addtonames ("#1",\!!bs#2\!!es)}}
+
+\def\pdfbackendsetpageattribute #1#2{\ctxlua{lpdf.addtopageattributes ("#1",\!!bs#2\!!es)}}
+\def\pdfbackendsetpagesattribute#1#2{\ctxlua{lpdf.addtopagesattributes("#1",\!!bs#2\!!es)}}
+\def\pdfbackendsetpageresource #1#2{\ctxlua{lpdf.addtopageresources ("#1",\!!bs#2\!!es)}}
+
+\def\pdfbackendsetextgstate #1#2{\ctxlua{lpdf.adddocumentextgstate ("#1",lpdf.verbose(\!!bs#2\!!es))}}
+\def\pdfbackendsetcolorspace #1#2{\ctxlua{lpdf.adddocumentcolorspace("#1",lpdf.verbose(\!!bs#2\!!es))}}
+\def\pdfbackendsetpattern #1#2{\ctxlua{lpdf.adddocumentpattern ("#1",lpdf.verbose(\!!bs#2\!!es))}}
+\def\pdfbackendsetshade #1#2{\ctxlua{lpdf.adddocumentshade ("#1",lpdf.verbose(\!!bs#2\!!es))}}
+
+\def\pdfbackendcurrentresources {\ctxlua{lpdf.collectedresources()}}
+
+%D Let's block these:
+
+\let\pdfcatalog \relax \newtoks\pdfcatalog
+\let\pdfinfo \relax \newtoks\pdfinfo
+\let\pdfnames \relax \newtoks\pdfnames
+\let\pdfpageresources\relax \newtoks\pdfpageresources
+\let\pdfpageattr \relax \newtoks\pdfpageattr
+\let\pdfpagesattr \relax \newtoks\pdfpagesattr
+
+%D An example of usage is:
+
+\appendtoks
+ \pdfbackendsetinfo{ConTeXt.Version}{\contextversion}%
+ \pdfbackendsetinfo{ConTeXt.Time} {\number\normalyear.\twodigits\normalmonth.\twodigits\normalday\space \twodigits\currenthour:\twodigits\currentminute}%
+ \pdfbackendsetinfo{ConTeXt.Jobname}{\jobname}%
+ \pdfbackendsetinfo{ConTeXt.Url} {www.pragma-ade.com}%
+\to \everylastbackendshipout
+
+%D Unfortunately this is still needed (also for \METAPOST\ to
+%D \PDF\ converter):
+
+% \def\doresetmapfilelist
+% {\global\let\doresetmapfilelist\relax
+% \pdfmapfile{original-empty.map}}
+%
+% \appendtoksonce \loadallfontmapfiles \to \pdfbackendeveryxform
+% \appendtoksonce \loadallfontmapfiles \to \pdfbackendeveryximage
+
+%D Transformations. Some day we will use primitives (once they're fixed).
+
+\def\dostartrotation#1% grouped
+ {\forcecolorhack
+ \pdfliteral{q \ctxlua{lpdf.rotationcm(#1)}}}
+
+\def\dostoprotation
+ {\pdfliteral{Q}}
+
+\def\dostartscaling#1#2% the test is needed because acrobat is bugged!
+ {\forcecolorhack
+ \pdfliteral{q \ifdim#1\points=\zeropoint.0001\else#1\fi\space 0 0
+ \ifdim#2\points=\zeropoint.0001\else#2\fi\space 0 0 cm}}
+
+\def\dostopscaling
+ {\pdfliteral{Q}}
+
+\def\dostartmirroring{\pdfliteral{-1 0 0 1 0 0 cm}}
+\def\dostopmirroring {\pdfliteral{-1 0 0 1 0 0 cm}}
+
+\def\dostartclipping#1#2#3% todo (still needed?)
+ {\PointsToBigPoints{#2}\width
+ \PointsToBigPoints{#3}\height
+ \grabMPclippath{#1}{1}\width\height{0 0 m \width\space 0 l \width \height l 0 \height l}%
+ \pdfliteral{q 0 w \MPclippath\space W n}}
+
+\def\dostopclipping
+ {\pdfliteral{Q n}}
+
+%D The following will move to the backend \LUA\ code:
+
+\appendtoks \ctxlua{backends.codeinjections.finalizepage ()}\to \everybackendshipout % is immediate
+\appendtoks \ctxlua{backends.codeinjections.finalizedocument()}\to \everylastbackendshipout % is immediate
+
+%D Temporary hack, will be removed or improved or default.
+
+\def\TransparencyHack{\ctxlua{backends.codeinjections.addtransparencygroup()}}
+
+%D \macros
+%D {dostartobject,dostopobject,doinsertobject}
+
+%D This will change:
+
+\newbox\objectbox
+
+\def\dostartobject#1#2#3#4#5%
+ {\bgroup
+ \setbox\objectbox\vbox\bgroup
+ \def\dodostopobject{\egroup\doregisterobject{#1}{#2}}}
+
+\def\dostopobject
+ {\dodostopobject
+ \egroup}
+
+\def\doregisterobject#1#2%
+ {\the\pdfbackendeveryxform
+ \finalizeobjectbox\objectbox
+ \immediate\pdfxform resources {\pdfbackendcurrentresources}\objectbox
+ \dosetobjectreference{#1}{#2}{\the\pdflastxform}}
+
+\def\doresetobjects
+ {}
+
+\def\doinsertobject#1#2%
+ {\begingroup
+ \doifobjectreferencefoundelse{#1}{#2}
+ {\dogetobjectreference{#1}{#2}\PDFobjectreference\pdfrefxform\PDFobjectreference}%
+ \donothing
+ \endgroup}
+
+\def\doPDFgetobjectpage#1#2#3%
+ {\dogetobjectreferencepage{#1}{#2}#3%
+ \ifx#3\empty\def#3{\realfolio}\fi}
+
+\def\doPDFgetobjectpagereference#1#2#3%
+ {\dogetobjectreferencepage{#1}{#2}#3%
+ \doPDFgetpagereference{\ifx#3\empty\realfolio\else#3\fi}#3}
+
+\let\lastpredefinedsymbol\empty % some day we can do more at the lua end
+
+\def\predefinesymbol[#1]%
+ {\begingroup
+ \xdef\lastpredefinedsymbol{#1}%
+ \settightobject{SYM}{#1}\hbox{\symbol[#1]}% to be checked ... maybe only fitting
+ \dogetobjectreference{SYM}{#1}\lastref
+ \ctxlua{backends.codeinjections.registersymbol("#1",\lastref)}%
+ \endgroup}
+
+\protect \endinput
diff --git a/tex/context/base/back-u3d.mkiv b/tex/context/base/back-u3d.mkiv
new file mode 100644
index 000000000..398159feb
--- /dev/null
+++ b/tex/context/base/back-u3d.mkiv
@@ -0,0 +1,156 @@
+%D \module
+%D [ file=back-u3d,
+%D version=2009.04.15,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=U3D Experiment,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% This is only a placeholder that demonstrates the usage of u3d
+% resources. The user interface is rather messy an might be
+% improved. The files and setup is derived from an example by
+% Michael Vidiassov.
+
+\endinput
+
+\starttext
+
+\startluaparameterset [u3d:myset:controls:1]
+ view = {
+ name = 'default',
+ bg = {1,1,1},
+ mag = 100,
+ coo = {0,0,0},
+ c2c = {0,0,1},
+ rot = {40,0,60},
+ roo = 6,
+ lights = 'CAD'
+ },
+ js = 'cloudq.js'
+\stopluaparameterset
+
+\startluaparameterset [u3d:myset:controls:2]
+ views = {
+ {
+ name = 'AnglePositioning',
+ bg = {1,1,1},
+ azimuth = 45,
+ altitude = 45,
+ roo = 50,
+ aac = 2.5,
+ lights = 'Artwork'
+ },
+ {
+ name = 'RotationPositioning',
+ bg = {1,1,1},
+ rot = {0,45,45},
+ roo = 50,
+ aac = 2.5,
+ lights = 'Artwork'
+ },
+ {
+ name = 'VectorPositioning',
+ bg = {1,0,0},
+ c2c = {1,1,math.sqrt(2)},
+ roo = 50,
+ aac = 2.5,
+ lights = 'CAD'
+ },
+ {
+ name = 'PositionPositioning',
+ bg = {1,0,0},
+ pos = {1+25,1+25,1+50/math.sqrt(2)},
+ aac = 2.5,
+ lights = 'CAD'
+ },
+ {
+ name = 'ortho',
+ bg = {1,1,1},
+ mag = 300,
+ lights = 'CAD',
+ crossection = {}
+ }
+ },
+ view = {
+ name = 'default',
+ bg = {1,1,1},
+ c2c = {-1,-1,0},
+ roo = 50,
+ aac = 2.5,
+ roll = 45,
+ lights = 'CAD',
+ crossection = {
+ normal = {-1,-1,-1},
+ transparent = true
+ },
+ nodes = {
+ {
+ name = 'xlabel',
+ visible = false
+ },
+ {
+ name = 'ylabel',
+ opacity = 0.5
+ },
+ {
+ name = 'zlabel',
+ rendermode = 'Wireframe'
+ }
+ }
+ }
+\stopluaparameterset
+
+\useexternalfigure
+ [cloudq]
+ [cloudq.u3d]
+ [width=0.7\textwidth,
+ height=.7\textwidth,
+ display=u3d:myset:display:1,
+ controls=u3d:myset:controls:1]
+
+\useexternalfigure
+ [axes]
+ [axes.u3d]
+ [width=0.7\textwidth,
+ height=.7\textwidth,
+ controls=u3d:myset:controls:1]
+
+\startluaparameterset[u3d:myset:display:2]
+ toolbar = true,
+ preview = 'cloudq.png'
+\stopluaparameterset
+\startluaparameterset[u3d:myset:display:3]
+ toolbar = true,
+ tree = false,
+ preview = 'area.png'
+\stopluaparameterset
+\startluaparameterset[u3d:myset:display:4]
+ toolbar = true,
+ tree = false,
+ view = {
+ name = 'view',
+ bg = {0.1,0.1,0.1},
+ c2c = {-1,-1,0},
+ roo = 50,
+ aac = 2.5,
+ roll = 45,
+ lights = 'Red'
+ }
+\stopluaparameterset
+\startluaparameterset[u3d:myset:display:5]
+ toolbar = true,
+ tree = false,
+ view = 'ortho'
+\stopluaparameterset
+
+\placefigure[here]{none}{\externalfigure[cloudq][display=u3d:myset:display:2]}
+\placefigure[here]{none}{\externalfigure[axes] [display=u3d:myset:display:3]}
+\placefigure[here]{none}{\externalfigure[axes] [display=u3d:myset:display:4]}
+\placefigure[here]{none}{\externalfigure[axes] [display=u3d:myset:display:5,width=0.5\textwidth,height=.5\textwidth]}
+
+\stoptext
diff --git a/tex/context/base/bibl-bib.lua b/tex/context/base/bibl-bib.lua
new file mode 100644
index 000000000..3c0dad2fa
--- /dev/null
+++ b/tex/context/base/bibl-bib.lua
@@ -0,0 +1,762 @@
+if not modules then modules = { } end modules ['bibl-bib'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
This is a prelude to integrated bibliography support. This file just loads
+bibtex files and converts them to xml so that the we access the content
+in a convenient way. Actually handling the data takes place elsewhere.
+--ldx]]--
+
+local utf = unicode.utf8
+local lower, format, gsub, concat = string.lower, string.format, string.gsub, table.concat
+local next = next
+local utfchar = utf.char
+local lpegmatch = lpeg.match
+local textoutf = characters and characters.tex.toutf
+local variables = interfaces and interfaces.variables
+
+local finalizers = xml.finalizers.tex
+local xmlfilter, xmltext = xml.filter, xml.text
+
+local trace_bibxml = false trackers.register("publications.bibxml", function(v) trace_bibtex = v end)
+
+bibtex = bibtex or { }
+
+bibtex.size = 0
+bibtex.definitions = 0
+bibtex.shortcuts = 0
+
+local defaultshortcuts = {
+ jan = "1",
+ feb = "2",
+ mar = "3",
+ apr = "4",
+ may = "5",
+ jun = "6",
+ jul = "7",
+ aug = "8",
+ sep = "9",
+ oct = "10",
+ nov = "11",
+ dec = "12",
+}
+
+local shortcuts = { }
+local data = { }
+local entries
+
+-- Currently we expand shortcuts and for large ones (like the acknowledgements
+-- in tugboat.bib this is not that efficient. However, eventually strings get
+-- hashed again.
+
+local function do_shortcut(tag,key,value)
+ bibtex.shortcuts = bibtex.shortcuts + 1
+ if lower(tag) == "@string" then
+ shortcuts[key] = value
+ end
+end
+
+local function do_definition(tag,key,tab) -- maybe check entries here (saves memory)
+ if not entries or entries[key] then
+ bibtex.definitions = bibtex.definitions + 1
+ local t = { }
+ for i=1,#tab,2 do
+ t[tab[i]] = tab[i+1]
+ end
+ local p = data[tag]
+ if not p then
+ data[tag] = { [key] = t }
+ else
+ p[key] = t
+ end
+ end
+end
+
+local function resolve(s)
+ return shortcuts[s] or defaultshortcuts[s] or s -- can be number
+end
+
+local P, R, S, C, Cc, Cs, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct
+
+local percent = P("%")
+local start = P("@")
+local comma = P(",")
+local hash = P("#")
+local escape = P("\\")
+local single = P("'")
+local double = P('"')
+local left = P('{')
+local right = P('}')
+local both = left + right
+local lineending = S("\n\r")
+local space = S(" \t\n\r\f")
+local spacing = space^0
+local equal = P("=")
+local collapsed = (space^1)/ " "
+
+local function add(a,b) if b then return a..b else return a end end
+
+local keyword = C((lpeg.R("az","AZ","09") + S("@_:-"))^1) -- lpeg.C((1-space)^1)
+local s_quoted = ((escape*single) + collapsed + (1-single))^0
+local d_quoted = ((escape*double) + collapsed + (1-double))^0
+local balanced = lpeg.patterns.balanced
+
+local s_value = (single/"") * s_quoted * (single/"")
+local d_value = (double/"") * d_quoted * (double/"")
+local b_value = (left /"") * balanced * (right /"")
+local r_value = keyword/resolve
+
+local somevalue = s_value + d_value + b_value + r_value
+local value = Cs((somevalue * ((spacing * hash * spacing)/"" * somevalue)^0))
+
+local assignment = spacing * keyword * spacing * equal * spacing * value * spacing
+local shortcut = keyword * spacing * left * spacing * (assignment * comma^0)^0 * spacing * right
+local definition = keyword * spacing * left * spacing * keyword * comma * lpeg.Ct((assignment * comma^0)^0) * spacing * right
+local comment = keyword * spacing * left * (1-right)^0 * spacing * right
+local forget = percent^1 * (1-lineending)^0
+
+-- todo \%
+
+local grammar = (space + forget + shortcut/do_shortcut + definition/do_definition + comment + 1)^0
+
+function bibtex.convert(session,content)
+ statistics.starttiming(bibtex)
+ data, shortcuts, entries = session.data, session.shortcuts, session.entries
+ -- session.size = session.size + #content
+ bibtex.size = bibtex.size + #content
+ session.size = session.size + #content
+ lpegmatch(grammar,content or "")
+ statistics.stoptiming(bibtex)
+end
+
+function bibtex.load(session,filename)
+ local filename = resolvers.find_file(filename,"bib")
+ if filename ~= "" then
+ local data = io.loaddata(filename) or ""
+ if data == "" then
+ logs.report("publications","empty file '%s', no conversion to xml",filename)
+ elseif trace_bibxml then
+ logs.report("publications","converting file '%s' to xml",filename)
+ end
+ bibtex.convert(session,data)
+ end
+end
+
+function bibtex.new()
+ return {
+ data = { },
+ shortcuts = { },
+ xml = xml.convert("\n"),
+ size = 0,
+ entries = nil,
+ loaded = false,
+ }
+end
+
+local escaped_pattern = xml.escaped_pattern
+
+local ihatethis = {
+ f = "\\f",
+ n = "\\n",
+ r = "\\r",
+ s = "\\s",
+ t = "\\t",
+ v = "\\v",
+ z = "\\z",
+}
+
+local command = P("\\")/"" * Cc("\\bibtexcommand{") * (R("az","AZ")^1) * Cc("}")
+local any = P(1)
+local done = P(-1)
+local one_l = P("{") / ""
+local one_r = P("}") / ""
+local two_l = P("{{") / ""
+local two_r = P("}}") / ""
+
+local filter = Cs(
+ two_l * (command + any - two_r - done)^0 * two_r * done +
+ one_l * (command + any - one_r - done)^0 * one_r * done +
+ (command + any )^0
+)
+
+function bibtex.toxml(session,options)
+ if session.loaded then
+ return
+ else
+ session.loaded = true
+ end
+ -- we can always speed this up if needed
+ -- format slows down things a bit but who cares
+ statistics.starttiming(bibtex)
+ local result = { }
+ local options = aux.settings_to_hash(options)
+ local convert = options.convert -- todo: interface
+ local strip = options.strip -- todo: interface
+ local entries = session.entries
+ result[#result+1] = format("")
+ result[#result+1] = format("")
+ for id, categories in next, session.data do
+ id = lower(gsub(id,"^@",""))
+ for name, entry in next, categories do
+ if not entries or entries[name] then
+ result[#result+1] = format("",lower(name),id)
+ for key, value in next, entry do
+ value = gsub(value,"\\(.)",ihatethis)
+ value = lpegmatch(escaped_pattern,value)
+
+ if value ~= "" then
+ if convert then
+ value = textoutf(value,true)
+ end
+ if strip then
+ -- as there is no proper namespace in bibtex we need this
+ -- kind of hackery ... bibtex databases are quite unportable
+ value = lpegmatch(filter,value) or value
+ end
+ result[#result+1] = format(" %s",key,value)
+ end
+ end
+ result[#result+1] = format("")
+ end
+ end
+ end
+ result[#result+1] = format("")
+ result = concat(result,"\n")
+ -- alternatively we could use lxml.convert
+ session.xml = xml.convert(result, {
+ resolve_entities = true,
+ resolve_predefined_entities = true, -- in case we have escaped entities
+ -- unify_predefined_entities = true, -- & -> &
+ utfize_entities = true,
+ } )
+ session.data = nil
+ session.shortcuts = nil
+ statistics.stoptiming(bibtex)
+end
+
+statistics.register("bibtex load time", function()
+ local size = bibtex.size
+ if size > 0 then
+ return format("%s seconds (%s bytes, %s definitions, %s shortcuts)",
+ statistics.elapsedtime(bibtex),size,bibtex.definitions,bibtex.shortcuts)
+ else
+ return nil
+ end
+end)
+
+--~ str = [[
+--~ @COMMENT { CRAP }
+--~ @STRING{ hans = "h a n s" }
+--~ @STRING{ taco = "t a c o" }
+--~ @SOMETHING{ key1, abc = "t a c o" , def = "h a n s" }
+--~ @SOMETHING{ key2, abc = hans # taco }
+--~ @SOMETHING{ key3, abc = "hans" # taco }
+--~ @SOMETHING{ key4, abc = hans # "taco" }
+--~ @SOMETHING{ key5, abc = hans # taco # "hans" # "taco"}
+--~ @SOMETHING{ key6, abc = {oeps {oeps} oeps} }
+--~ ]]
+
+--~ local session = bibtex.new()
+--~ bibtex.convert(session,str)
+--~ bibtex.toxml(session)
+--~ print(session.size,statistics.elapsedtime(bibtex))
+
+--~ local session = bibtex.new()
+--~ bibtex.load(session,"IEEEabrv.bib")
+--~ bibtex.load(session,"IEEEfull.bib")
+--~ bibtex.load(session,"IEEEexample.bib")
+--~ bibtex.toxml(session)
+--~ print(session.size,statistics.elapsedtime(bibtex))
+
+--~ local session = bibtex.new()
+--~ bibtex.load(session,"gut.bib")
+--~ bibtex.load(session,"komoedie.bib")
+--~ bibtex.load(session,"texbook1.bib")
+--~ bibtex.load(session,"texbook2.bib")
+--~ bibtex.load(session,"texbook3.bib")
+--~ bibtex.load(session,"texgraph.bib")
+--~ bibtex.load(session,"texjourn.bib")
+--~ bibtex.load(session,"texnique.bib")
+--~ bibtex.load(session,"tugboat.bib")
+--~ bibtex.toxml(session)
+--~ print(session.size,statistics.elapsedtime(bibtex))
+
+--~ print(table.serialize(session.data))
+--~ print(table.serialize(session.shortcuts))
+--~ print(xml.serialize(session.xml))
+
+if not characters then dofile(resolvers.find_file("char-def.lua")) end
+
+local chardata = characters.data
+local concat = table.concat
+
+local P, Ct, lpegmatch = lpeg.P, lpeg.Ct, lpeg.match
+
+local space, comma = P(" "), P(",")
+
+local andsplitter = Ct(lpeg.splitat(space^1 * "and" * space^1))
+local commasplitter = Ct(lpeg.splitat(space^0 * comma * space^0))
+local spacesplitter = Ct(lpeg.splitat(space^1))
+local firstcharacter = lpeg.patterns.utf8byte
+
+function is_upper(str)
+ local first = lpegmatch(firstcharacter,str)
+ local okay = chardata[first]
+ return okay and okay.category == "lu"
+end
+
+local function splitauthors(str)
+ local authors = lpegmatch(andsplitter,str)
+ for i=1,#authors do
+ local firstnames, vons, surnames, initials, juniors, words
+ local author = authors[i]
+ local split = lpegmatch(commasplitter,author)
+ local n = #split
+ if n == 1 then
+ --~ First von Last
+ words = lpegmatch(spacesplitter,author)
+ firstnames, vons, surnames = { }, { }, { }
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ break
+ else
+ vons[#vons+1], i = w, i + 1
+ end
+ end
+ while i <= n do
+ surnames[#surnames+1], i = words[i], i + 1
+ end
+ elseif n == 2 then
+ --~ von Last, First
+ words = lpegmatch(spacesplitter,split[2])
+ surnames = lpegmatch(spacesplitter,split[1])
+ firstnames, vons = { }, { }
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ vons[#vons+1], i = words[i], i + 1
+ end
+ else
+ --~ von Last, Jr ,First
+ firstnames = lpegmatch(spacesplitter,split[1])
+ juniors = lpegmatch(spacesplitter,split[2])
+ surnames = lpegmatch(spacesplitter,split[3])
+ if n > 3 then
+ -- error
+ end
+ end
+ if #surnames == 0 then
+ surnames[1] = firstnames[#firstnames]
+ firstnames[#firstnames] = nil
+ end
+ if firstnames then
+ initials = { }
+ for i=1,#firstnames do
+ initials[i] = utfchar(lpegmatch(firstcharacter,firstnames[i]))
+ end
+ end
+ authors[i] = {
+ original = author,
+ firstnames = firstnames,
+ vons = vons,
+ surnames = surnames,
+ initials = initials,
+ juniors = juniors,
+ }
+ end
+ authors.original = str
+ return authors
+end
+
+local function the_initials(initials,symbol)
+ local t, symbol = { }, symbol or "."
+ for i=1,#initials do
+ t[i] = initials[i] .. symbol
+ end
+ return t
+end
+
+-- authors
+
+bibtex.authors = bibtex.authors or { }
+
+local authors = bibtex.authors
+
+local defaultsettings = {
+ firstnamesep = " ",
+ vonsep = " ",
+ surnamesep = " ",
+ juniorsep = " ",
+ surnamejuniorsep = ", ",
+ juniorjuniorsep = ", ",
+ surnamefirstnamesep = ", ",
+ surnameinitialsep = ", ",
+ namesep = ", ",
+ lastnamesep = " and ",
+ finalnamesep = " and ",
+}
+
+function authors.normal(author,settings)
+ local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if firstnames and #firstnames > 0 then
+ result[#result+1] = concat(firstnames," ")
+ result[#result+1] = settings.firstnamesep or defaultsettings.firstnamesep
+ end
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = concat(juniors," ")
+ result[#result+1] = settings.surnamesep or defaultsettings.surnamesep
+ end
+ return concat(result)
+end
+
+function authors.normalshort(author,settings)
+ local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if firstnames and #firstnames > 0 then
+ result[#result+1] = concat(firstnames," ")
+ result[#result+1] = settings.firstnamesep or defaultsettings.firstnamesep
+ end
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = concat(juniors," ")
+ result[#result+1] = settings.surnamejuniorsep or defaultsettings.surnamejuniorsep
+ end
+ return concat(result)
+end
+
+function authors.inverted(author,settings)
+ local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = settings.juniorjuniorsep or defaultsettings.juniorjuniorsep
+ result[#result+1] = concat(juniors," ")
+ end
+ if firstnames and #firstnames > 0 then
+ result[#result+1] = settings.surnamefirstnamesep or defaultsettings.surnamefirstnamesep
+ result[#result+1] = concat(firstnames," ")
+ end
+ return concat(result)
+end
+
+function authors.invertedshort(author,settings)
+ local vons, surnames, initials, juniors = author.vons, author.surnames, author.initials, author.juniors
+ local result, settings = { }, settings or defaultsettings
+ if vons and #vons > 0 then
+ result[#result+1] = concat(vons," ")
+ result[#result+1] = settings.vonsep or defaultsettings.vonsep
+ end
+ if surnames then
+ result[#result+1] = concat(surnames," ")
+ end
+ if juniors and #juniors > 0 then
+ result[#result+1] = settings.juniorjuniorsep or defaultsettings.juniorjuniorsep
+ result[#result+1] = concat(juniors," ")
+ end
+ if initials and #initials > 0 then
+ result[#result+1] = settings.surnameinitialsep or defaultsettings.surnameinitialsep
+ result[#result+1] = concat(the_initials(initials)," ")
+ end
+ return concat(result)
+end
+
+local lastconcatsize = 1
+
+local function bibtexconcat(t,settings)
+ local namesep = settings.namesep or defaultsettings.namesep or ", "
+ local lastnamesep = settings.lastnamesep or defaultsettings.lastnamesep or namesep
+ local finalnamesep = settings.finalnamesep or defaultsettings.finalnamesep or lastnamesep
+ local lastconcatsize = #t
+ if lastconcatsize > 2 then
+ local s = { }
+ for i=1,lastconcatsize-2 do
+ s[i] = t[i] .. namesep
+ end
+ s[lastconcatsize-1], s[lastconcatsize] = t[lastconcatsize-1] .. finalnamesep, t[lastconcatsize]
+ return concat(s)
+ elseif lastconcatsize > 1 then
+ return concat(t,lastnamesep)
+ elseif lastconcatsize > 0 then
+ return t[1]
+ else
+ return ""
+ end
+end
+
+function authors.concat(author,combiner,what,settings)
+ if type(combiner) == "string" then
+ combiner = authors[combiner or "normal"] or authors.normal
+ end
+ local split = splitauthors(author)
+ local setting = settings[what]
+ local etallimit, etaldisplay, etaltext = 1000, 1000, ""
+ if setting then
+ etallimit = settings.etallimit or 1000
+ etaldisplay = settings.etaldisplay or etallimit
+ etalltext = settings.etaltext or ""
+ end
+ local max = #split
+ if max > etallimit and etaldisplay < max then
+ max = etaldisplay
+ end
+ for i=1,max do
+ split[i] = combiner(split[i],settings)
+ end
+ local result = bibtexconcat(split,settings)
+ if max < #split then
+ return result
+ else
+ return result .. etaltext
+ end
+end
+
+function authors.short(author,year)
+ local result = { }
+ if author then
+ local authors = splitauthors(author)
+ for a=1,#authors do
+ local aa = authors[a]
+ local initials = aa.initials
+ for i=1,#initials do
+ result[#result+1] = initials[i]
+ end
+ local surnames = aa.surnames
+ for s=1,#surnames do
+ result[#result+1] = utfchar(lpegmatch(firstcharacter,surnames[s]))
+ end
+ end
+ end
+ if year then
+ result[#result+1] = year
+ end
+ return concat(result)
+end
+
+-- We can consider creating a hashtable key -> entry but I wonder if
+-- pays off.
+
+local function collectauthoryears(id,list)
+ list = aux.settings_to_hash(list)
+ id = lxml.get_id(id)
+ local found = { }
+ for e in xml.collected(id,"/bibtex/entry") do
+ if list[e.at.tag] then
+ local year = xmlfilter(e,"xml:///field[@name='year']/text()")
+ local author = xmlfilter(e,"xml:///field[@name='author']/text()")
+ if author and year then
+ local a = found[author]
+ if not a then
+ a = { }
+ found[author] = a
+ end
+ local y = a[year]
+ if not y then
+ y = { }
+ a[year] = y
+ end
+ y[#y+1] = e
+ end
+ end
+ end
+ -- found = { author = { year_1 = { e1, e2, e3 } } }
+ local done = { }
+ for author, years in next, found do
+ local yrs = { }
+ for year, entries in next, years do
+ if subyears then
+ -- -- add letters to all entries of an author and if so shouldn't
+ -- -- we tag all years of an author as soon as we do this?
+ -- if #entries > 1 then
+ -- for i=1,#years do
+ -- local entry = years[i]
+ -- -- years[i] = year .. string.char(i + string.byte("0") - 1)
+ -- end
+ -- end
+ else
+ yrs[#yrs+1] = year
+ end
+ end
+ done[author] = yrs
+ end
+ return done
+end
+
+local method, settings = "normal", { }
+
+function authors.setsettings(s)
+ settings = s or settings
+end
+
+if commands then
+
+ local texsprint = tex and tex.sprint
+ local ctxcatcodes = tex and tex.ctxcatcodes
+
+ local sessions = { }
+
+ function commands.definebibtexsession(name)
+ sessions[name] = bibtex.new()
+ end
+
+ function commands.preparebibtexsession(name,xmlname,options)
+ bibtex.toxml(sessions[name],options)
+ lxml.register(xmlname,sessions[name].xml)
+ end
+
+ function commands.registerbibtexfile(name,filename)
+ bibtex.load(sessions[name],filename)
+ end
+
+ function commands.registerbibtexentry(name,entry)
+ local session = sessions[name]
+ local entries = session.entries
+ if not entries then
+ session.entries = { [entry] = true } -- here we can keep more info
+ else
+ entries[entry] = true
+ end
+ end
+
+ -- commands.bibtexconcat = bibtexconcat
+
+ -- finalizers can be rather dumb as we have just text and no embedded xml
+
+ function finalizers.bibtexconcat(collected,method,what)
+ if collected then
+ local author = collected[1].dt[1] or ""
+ if author ~= "" then
+ texsprint(ctxcatcodes,authors.concat(author,method,what,settings))
+ end
+ end
+ end
+
+ function finalizers.bibtexshort(collected)
+ if collected then
+ local c = collected[1]
+ local year = xmlfilter(c,"xml://field[@name='year']/text()")
+ local author = xmlfilter(c,"xml://field[@name='author']/text()")
+ texsprint(ctxcatcodes,authors.short(author,year))
+ end
+ end
+
+ -- experiment:
+
+ --~ -- alternative approach: keep data at the tex end
+
+ --~ local function xbibtexconcat(t,sep,finalsep,lastsep)
+ --~ local n = #t
+ --~ if n > 0 then
+ --~ context(t[1])
+ --~ if n > 1 then
+ --~ if n > 2 then
+ --~ for i=2,n-1 do
+ --~ context.bibtexpublicationsparameter("sep")
+ --~ context(t[i])
+ --~ end
+ --~ context.bibtexpublicationsparameter("finalsep")
+ --~ else
+ --~ context.bibtexpublicationsparameter("lastsep")
+ --~ end
+ --~ context(t[n])
+ --~ end
+ --~ end
+ --~ end
+
+ -- todo : sort
+
+ -- todo: choose between bibtex or commands namespace
+
+ function bibtex.authorref(id,list)
+ local result = collectauthoryears(id,list,method,what)
+ for author, years in next, result do
+ texsprint(ctxcatcodes,authors.concat(author,method,what,settings))
+ end
+ end
+
+ function bibtex.authoryearref(id,list)
+ local result = collectauthoryears(id,list,method,what)
+ for author, years in next, result do
+ texsprint(ctxcatcodes,authors.concat(author,method,what,settings)," (",concat(years,", "),")")
+ end
+ end
+
+ function bibtex.authoryearsref(id,list)
+ local result = collectauthoryears(id,list,method,what)
+ for author, years in next, result do
+ texsprint(ctxcatcodes,"(",authors.concat(author,method,what,settings),", ",concat(years,", "),")")
+ end
+ end
+
+ function bibtex.singular_or_plural(singular,plural)
+ if lastconcatsize and lastconcatsize > 1 then
+ texsprint(ctxcatcodes,plural)
+ else
+ texsprint(ctxcatcodes,singular)
+ end
+ end
+end
+
+
+--~ local function test(sample)
+--~ local authors = splitauthors(sample)
+--~ print(table.serialize(authors))
+--~ for i=1,#authors do
+--~ local author = authors[i]
+--~ print(normalauthor (author,settings))
+--~ print(normalshortauthor (author,settings))
+--~ print(invertedauthor (author,settings))
+--~ print(invertedshortauthor(author,settings))
+--~ end
+--~ print(concatauthors(sample,settings,normalauthor))
+--~ print(concatauthors(sample,settings,normalshortauthor))
+--~ print(concatauthors(sample,settings,invertedauthor))
+--~ print(concatauthors(sample,settings,invertedshortauthor))
+--~ end
+
+--~ local sample_a = "Hagen, Hans and Hoekwater, Taco Whoever T. Ex. and Henkel Hut, Hartmut Harald von der"
+--~ local sample_b = "Hans Hagen and Taco Whoever T. Ex. Hoekwater and Hartmut Harald von der Henkel Hut"
+
+--~ test(sample_a)
+--~ test(sample_b)
diff --git a/tex/context/base/bibl-bib.mkiv b/tex/context/base/bibl-bib.mkiv
new file mode 100644
index 000000000..10abe5cb8
--- /dev/null
+++ b/tex/context/base/bibl-bib.mkiv
@@ -0,0 +1,962 @@
+%D \module
+%D [ file=bibl-bib,
+%D version=2007.08.17,
+%D title=\CONTEXT\ Bibliography Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen \& Taco Hoekwater,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Bibliography Support / Experimental BibTeX}
+
+\registerctxluafile{bibl-bib}{1.001}
+
+\unprotect
+
+% todo: et al limiters
+% todo: split: citationvariant and publicationvariant
+
+%D This interface is under development. As I don't use \BIBTEX\ myself I need
+%D some motivation to spend time on it, and an occasional question on the
+%D list can be a reason. A few examples. As \BIBTEX\ databases can be poluted
+%D by local commands, we need to catch:
+%D
+%D \startbuffer
+%D \defbibtexcommand\MF {MF}
+%D \defbibtexcommand\MP {MP}
+%D \defbibtexcommand\TUB {TUGboat}
+%D \defbibtexcommand\Mc {Mac}
+%D \defbibtexcommand\sltt{\tt}
+%D \defbibtexcommand\<#1>{\type{#1}}
+%D \defbibtexcommand\acro#1{#1}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Let's define a session and load a few databases. We convert to \UTF\ and
+%D strip commands.
+%D
+%D \startbuffer
+%D \definebibtexsession [somebibtex]
+%D \registerbibtexfile [somebibtex] [tugboat.bib]
+%D \registerbibtexfile [somebibtex] [komoedie.bib]
+%D \preparebibtexsession [somebibtex] [convert,strip]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This loads an mapping (work in progress):
+%D
+%D \startbuffer
+%D \def\currentbibtexformat{apa} \input bxml-\currentbibtexformat.mkiv
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D There are several ways to handle the \XML. It helps if you're a bit
+%D familiar with \XML\ processing in \MKIV.
+%D
+%D Here we regular setups. Three elements are mapped but only one
+%D is actually used and applied to root element \type {/bibtex}.
+%D
+%D \startbuffer
+%D \startxmlsetups bibtex
+%D \xmlregistereddocumentsetups{#1}{}
+%D \xmlsetsetup{#1}{bibtex|entry|field}{bibtex:*}
+%D \xmlmain{#1}
+%D \stopxmlsetups
+%D
+%D \startxmlsetups bibtex:bibtex
+%D \xmlfilter{#1}{
+%D /entry[@category='article']
+%D /field[@name='author' and (find(text(),'Hagen') or find(text(),'Hoekwater'))]
+%D /../command(bibtex:format)
+%D }
+%D \stopxmlsetups
+%D
+%D \applytobibtexsession[somebibtex][bibtex]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D A simpler setup is given next. Here we just apply a setup to the root
+%D element directly:
+%D
+%D \startbuffer
+%D \startxmlsetups bibtex:list
+%D \xmlfilter{#1}{/bibtex/entry/command(bibtex:format)}
+%D \stopxmlsetups
+%D
+%D \applytobibtexsession[somebibtex][bibtex:list]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D A slightly more complex expression:
+%D
+%D \startbuffer
+%D \startxmlsetups bibtex:filter
+%D \xmlfilter{#1}{
+%D /bibtex
+%D /entry[@category='article']
+%D /field[@name='author' and (find(text(),'Hagen') or find(text(),'Hoekwater'))]
+%D /../command(bibtex:format)
+%D }
+%D \stopxmlsetups
+%D
+%D \applytobibtexsession[somebibtex][bibtex:filter]
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\newtoks \everydefinebibtexsession
+\newtoks \everypreparebibtexsession
+\newtoks \everysetupbibtexsession
+\setfalse \tracebibtexformat
+
+\unexpanded\def\definebibtexsession {\dosingleargument\dodefinebibtexsession}
+\def\preparebibtexsession {\dodoubleempty \dopreparebibtexsession}
+\unexpanded\def\setupbibtexsession {\dodoubleargument\dosetupbibtexsession}
+
+\def\dodefinebibtexsession [#1]{\edef\currentbibtexsession{#1}%
+ \ctxlua{commands.definebibtexsession("#1")}%
+ \the\everydefinebibtexsession}
+
+\def\dopreparebibtexsession[#1][#2]{\edef\currentbibtexsession{#1}%
+ \ctxlua{commands.preparebibtexsession("#1","bibtex:#1","#2")}%
+ \the\everypreparebibtexsession}
+
+\def\dosetupbibtexsession [#1][#2]{\edef\currentbibtexsession{#1}%
+ \getparameters[\??pb#1][#2]%
+ \the\everysetupbibtexsession}
+
+\def\registerbibtexfile {\dodoubleargument\doregisterbibtexfile}
+\def\registerbibtexentry {\dodoubleargument\doregisterbibtexentry}
+\def\applytobibtexsession {\dodoubleargument\doapplytobibtexsession}
+
+\def\doregisterbibtexfile [#1][#2]{\ctxlua{commands.registerbibtexfile("#1","#2")}}
+\def\doregisterbibtexentry [#1][#2]{\ctxlua{commands.registerbibtexentry("#1","#2")}}
+\def\doapplytobibtexsession[#1][#2]{\xmlprocessregistered{bibtex:#1}{#2}{#2}}
+
+\unexpanded\def\bibtexcommand#1%
+ {\ifcsname\??pb:c:#1\endcsname \else
+ \fakebibtexcommand{#1}%
+ \fi
+ \csname\??pb:c:#1\endcsname}
+
+\def\fakebibtexcommand#1%
+ {\ifcsname#1\endcsname
+ \writestatus{bibtex}{unknown command: #1, using built-in context variant}%
+ \setugvalue{\??pb:c:#1}{\dosomebibtexcommand{#1}}%
+ \else
+ \writestatus{bibtex}{unknown command: #1}%
+ \setugvalue{\??pb:c:#1}{\dofakebibtexcommand{#1}}%
+ \fi}
+
+\let\dosomebibtexcommand \getvalue
+\def\dofakebibtexcommand#1{{\tttf#1}}
+
+\def\defbibtexcommand#1%
+ {\setuvalue{\strippedcsname#1}}
+
+\def\bibxmldoifelse#1{\xmldoifelse\currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmldoif #1{\xmldoif \currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmldoifnot #1{\xmldoifnot \currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmlflush #1{\xmlcontext \currentbibxmlnode{/field[@name='#1']}}
+\def\bibxmlsetup {\xmlsetup \currentbibxmlnode} % {#1}
+
+\def\currentbibtexformat{apa} % ho wto interface this, maybe split loading and key
+\def\currentbibxmlnode {unset}
+\def\currentbibxmltag {unset}
+
+\startxmlsetups bibtex
+ \xmlregistereddocumentsetups{#1}{}
+ \xmlsetsetup{#1}{bibtex|entry|field}{bibtex:*}
+ \xmlmain{#1}
+\stopxmlsetups
+
+\startxmlsetups bibtex:format
+ \bibtexpublicationsparameter\c!before\relax % prevents lookahead
+ \edef\currentbibxmlnode {#1}
+ \edef\currentbibxmltag {\xmlatt{#1}{tag}}
+ \edef\currentbibxmlcategory{\xmlatt{#1}{category}}
+ \ifconditional\tracebibtexformat
+ \tracedbibxmlintro\currentbibxmltag
+ \tracedbibxmlintro\currentbibxmlcategory
+ \fi
+ \ignorespaces
+ \xmlcommand{#1}{.}{bibtex:\currentbibtexformat:\currentbibxmlcategory}
+ \removeunwantedspaces
+ \bibtexpublicationsparameter\c!after\relax % prevents lookahead
+\stopxmlsetups
+
+\startxmlsetups bibtex:list
+ \xmlfilter{#1}{/bibtex/entry/command(bibtex:format)}
+\stopxmlsetups
+
+\startxmlsetups bibtex:bibtex
+ \xmlfilter{#1}{/entry/command(bibtex:format)}
+\stopxmlsetups
+
+% formatters
+
+\let\normalbibxmlflush\bibxmlflush
+
+\definecolor[bibtextracecolor:field] [darkred]
+\definecolor[bibtextracecolor:crossref][darkblue]
+\definecolor[bibtextracecolor:key] [darkgreen]
+
+\def\tracedbibxmlintro #1{{\tttf#1 -> }}
+\def\tracedbibxmlflush #1{\color[bibtextracecolor:field] {\tttf[#1]}}
+\def\tracedbibxmltexts #1{\color[bibtextracecolor:field] {\tttf<#1>}}
+\def\tracedbibxmlcrossref#1{\color[bibtextracecolor:crossref]{\tttf#1}}
+\def\tracedbibxmlkey #1{\color[bibtextracecolor:key] {\tttf#1}}
+
+\def\tracedbibxmltext
+ {\ifconditional\tracebibtexformat
+ \expandafter\tracedbibxmltexts % plural
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\bibxmlflush
+ {\ifconditional\tracebibtexformat
+ \expandafter\tracedbibxmlflush
+ \else
+ \expandafter\normalbibxmlflush
+ \fi}
+
+\startxmlsetups bibtex:format:crossref
+ \ifconditional\tracebibtexformat
+ \tracedbibxmlcrossref{\xmlfirst\currentbibxmlnode{/field[@name='crossref']/lower()}}
+ \else
+ \cite[\xmlfirst\currentbibxmlnode{/field[@name='crossref']/lower()}]
+ \fi
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:key
+ \ifconditional\tracebibtexformat
+ \tracedbibxmlkey{\normalbibxmlflush{key}}
+ \else
+ \bibxmlflush{key}
+ \fi
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:common:author
+ \ifconditional\tracebibtexformat
+ \bibxmlflush\currentbibtexvariant
+ \else
+ \xmlfilter{#1}{/field[@name='\currentbibtexvariant']/bibtexconcat('\currentbibtexvariant')}
+ \fi
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:author
+ \begingroup
+ \def\currentbibtexvariant{author}
+ \xmlsetup{#1}{bibtex:format:common:author}
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:artauthor
+ \begingroup
+ \def\currentbibtexvariant{artauthor}
+ \xmlsetup{#1}{bibtex:format:common:author}
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:editor
+ \begingroup
+ \def\currentbibtexvariant{editor}
+ \xmlsetup{#1}{bibtex:format:common:author}
+ \endgroup
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:doi
+% \bibdoifelse{\@@pb@doi}{#1\expanded{\bibgotoDOI{\@@pb@thekey}{\@@pb@doi}}#2}{#3}
+ *doi*
+\stopxmlsetups
+
+
+\startxmlsetups bibtex:format:doi
+% \bibdoifelse{\@@pb@biburl}{#1\expanded{\bibgotoURL{\@@pb@thekey}{\@@pb@biburl}}#2}{#3}
+ *url*
+\stopxmlsetups
+
+\startxmlsetups bibtex:format:month
+% {\bibdoifelse\@@pb@month
+% {#1\doifnumberelse\@@pb@month
+% {\doifconversiondefinedelse\@@pbmonthconversion
+% {\convertnumber\@@pbmonthconversion\@@pb@month}{\@@pb@month}}%
+% {\@@pb@month}#2}%
+% {#3}
+ *month*
+\stopxmlsetups
+
+% lists
+
+\def\bibtexlistprocessor
+ {\ctxlua{bibtex.hacks.add(structure.lists.uservalue("\currentlist",\currentlistindex,"bibref"),\currentlistindex)}}
+
+\appendtoks
+ \definelist[\currentbibtexsession]%
+ \setuplist[\currentbibtexsession][\c!state=\v!start,\c!width=]%
+ \installstructurelistprocessor{\currentbibtexsession:userdata}{\bibtexlistprocessor}%
+\to \everydefinebibtexsession
+
+% \def\installbibtexsorter#1#2%
+% {\setvalue{\??pb:\c!sort:#1}{#2}}
+
+% \installbibtexsorter\v!no {no}
+% \installbibtexsorter\v!author {au}
+% \installbibtexsorter\v!title {ti}
+% \installbibtexsorter\v!short {ab}
+% \installbibtexsorter\empty {no}
+% \installbibtexsorter\s!default{no}
+
+% \setupbibtex
+% [\c!sorttype=\v!cite,
+% \c!sort=no]
+
+% \long\unexpanded\def\startpublication#1\stoppublication
+% {\blank
+% todo
+% \blank}
+
+% \let\stoppublication\relax
+
+\unexpanded\def\bibtexspace {\removeunwantedspaces\space}
+\unexpanded\def\bibtexperiod {\removeunwantedspaces.\space}
+\unexpanded\def\bibtexcomma {\removeunwantedspaces,\space}
+\unexpanded\def\bibtexlparent {\removeunwantedspaces\space(}
+\unexpanded\def\bibtexrparent {\removeunwantedspaces)\space}
+\unexpanded\def\bibtexlbracket{\removeunwantedspaces\space[}
+\unexpanded\def\bibtexrbracket{\removeunwantedspaces]\space}
+
+% interfacing
+
+% todo : lang en language
+% todo : directions
+
+
+% variables
+
+\newcount\bibtexblock \bibtexblock\plusone
+
+\newtoks \everysetupbibtexpublications
+\newtoks \everysetupbibtexcitations
+\newcount\bibtexcounter
+
+\def\bibtexrefprefix{\number\bibtexblock:}
+
+\let\currentbibtexsession\s!default
+\let\currentbibtexvariant\s!default
+
+% parameters: session+variant variant session shared
+
+\def\bibtexpublicationsparameter#1%
+ {\csname
+ \ifcsname\??pb\currentbibtexsession:\currentbibtexvariant#1\endcsname
+ \??pb\currentbibtexsession:\currentbibtexvariant#1%
+ \else\ifcsname\??pb:\currentbibtexvariant#1\endcsname
+ \??pb:\currentbibtexvariant#1%
+ \else\ifcsname\??pb\currentbibtexsession#1\endcsname
+ \??pb\currentbibtexsession#1%
+ \else\ifcsname\??pb#1\endcsname
+ \??pb#1%
+ \else
+ \s!empty
+ \fi\fi\fi\fi
+ \endcsname}
+
+\def\bibtexcitationparameter#1%
+ {\csname
+ \ifcsname\??pv\currentbibtexsession:\currentbibtexvariant#1\endcsname
+ \??pv\currentbibtexsession:\currentbibtexvariant#1%
+ \else\ifcsname\??pv:\currentbibtexvariant#1\endcsname
+ \??pv:\currentbibtexvariant#1%
+ \else\ifcsname\??pv\currentbibtexsession#1\endcsname
+ \??pv\currentbibtexsession#1%
+ \else\ifcsname\??pv#1\endcsname
+ \??pv#1%
+ \else
+ \s!empty
+ \fi\fi\fi\fi
+ \endcsname}
+
+% setup commands
+
+\unexpanded\def\setupbibtexpublications
+ {\let\currentpublicationclass\??pb
+ \let\everysetupbibtexwhatever\everysetupbibtexpublications
+ \dodoubleargument\dosetupbibtexwhatever}
+
+\unexpanded\def\setupbibtexcitations
+ {\let\currentpublicationclass\??pv
+ \let\everysetupbibtexwhatever\everysetupbibtexcitations
+ \dodoubleargument\dosetupbibtexwhatever}
+
+\unexpanded\def\setupbibtexpublicationvariants
+ {\let\currentpublicationclass\??pb
+ \let\everysetupbibtexwhatever\everysetupbibtexpublications
+ \dotripleargument\dosetupbibtexwhatevervariant}
+
+\unexpanded\def\setupbibtexcitationvariants
+ {\let\currentpublicationclass\??pv
+ \let\everysetupbibtexwhatever\everysetupbibtexcitations
+ \dotripleargument\dosetupbibtexwhatevervariant}
+
+\def\dosetupbibtexwhatever[#1][#2]% [sessionlist] [setup]
+ {\ifsecondargument
+ % sessions setups
+ \def\dobtxcommand##1{\getparameters[\currentpublicationclass##1][#2]}%
+ \processcommalist[#1]\dobtxcommand
+ \else
+ % setups
+ \getparameters[\currentpublicationclass][#1]%
+ \the\everysetupbibtexwhatever
+ \fi}
+
+\def\dosetupbibtexwhatevervariant[#1][#2][#3]% [sessionlist] [variantlist] [setup]
+ {\ifthirdargument
+ % sessions variants setups
+ \def\dobtxcommand##1%
+ {\def\dodobtxcommand####1{\getparameters[\currentpublicationclass##1:####1][#3]}%
+ \processcommalist[#2]\dodobtxcommand}%
+ \processcommalist[#1]\docbtxommand
+ \else\ifsecondargument
+ % variants setups
+ \def\dobtxcommand##1{\getparameters[\currentpublicationclass:##1][#2]}%
+ \processcommalist[#1]\dobtxcommand
+ \else
+ % setups
+ \getparameters[\currentpublicationclass][#1]%
+ \the\everysetupbibtexwhatever
+ \fi\fi}
+
+% some initializations
+
+\setupbibtexcitationvariants
+ [author,authoryear,authoryears]
+ [\c!namesep={, }]
+
+% loading alternatives (apa etc)
+
+\def\doloadbibtexpublicationalternative
+ {\ifproductionrun
+ \edef\bibtexpublicationsalternative{\@@pbalternative}% parent
+ \ifx\bibtexpublicationsalternative\empty \else
+ \processcommacommand[\bibtexpublicationsalternative]\dodoloadbibtexpublicationalternative
+ \let\@@pbalternative\empty
+ \fi
+ \fi}
+
+\def\dodoloadbibtexpublicationalternative#1%
+ {\doonlyonce{#1}
+ {\readsysfile{bxml-#1.mkiv}
+ {\showmessage\m!publications{6}{bxml-#1}}
+ {\showmessage\m!publications{1}{bxml-#1}}}}
+
+\appendtoks
+ \doloadbibtexpublicationalternative
+\to \everysetupbibtexpublications
+
+\appendtoks
+ \doloadbibtexpublicationalternative
+\to \everyjob
+
+% whatever, should be key
+
+\def\bibtexleftnumber#1{#1\hfill~}
+
+% testing
+
+% \showmessage\m!publications{5}{#1 is unknown}\secondoftwoarguments}
+
+\let\doifbibreferencefoundelse\secondofthreearguments
+
+% lists
+
+\newtoks\everysetupbibtexlistplacement
+
+% this will change as we need it too often .. we will use context.thebibtexnamesep
+
+\appendtoks
+ \ctxlua {bibtex.authors.setsettings {
+ namesep = \!!bs\bibtexpublicationsparameter\c!namesep\!!es,
+ lastnamesep = \!!bs\bibtexpublicationsparameter\c!lastnamesep\!!es,
+ finalnamesep = \!!bs\bibtexpublicationsparameter\c!finalnamesep\!!es,
+ firstnamesep = \!!bs\bibtexpublicationsparameter\c!firstnamesep\!!es,
+ juniorsep = \!!bs\bibtexpublicationsparameter\c!juniorsep\!!es,
+ vonsep = \!!bs\bibtexpublicationsparameter\c!vonsep\!!es,
+ surnamesep = \!!bs\bibtexpublicationsparameter\c!surnamesep\!!es,
+ namesep = \!!bs\bibtexpublicationsparameter\c!namesep\!!es,
+ lastnamesep = \!!bs\bibtexpublicationsparameter\c!lastnamesep\!!es,
+ finalnamesep = \!!bs\bibtexpublicationsparameter\c!finalnamesep\!!es,
+ author = {
+ etallimit = \!!bs\bibtexpublicationsparameter\c!authoretallimit\!!es,
+ etaldisplay = \!!bs\bibtexpublicationsparameter\c!authoretaldisplay\!!es,
+ etaltext = \!!bs\bibtexpublicationsparameter\c!authoretaltext\!!es,
+ },
+ editor = {
+ etallimit = \!!bs\bibtexpublicationsparameter\c!editoretallimit\!!es,
+ etaldisplay = \!!bs\bibtexpublicationsparameter\c!editoretaldisplay\!!es,
+ etaltext = \!!bs\bibtexpublicationsparameter\c!editoretaltext\!!es,
+ },
+ artauthor = {
+ etallimit = \!!bs\bibtexpublicationsparameter\c!artauthoretallimit\!!es,
+ etaldisplay = \!!bs\bibtexpublicationsparameter\c!artauthoretaldisplay\!!es,
+ etaltext = \!!bs\bibtexpublicationsparameter\c!artauthoretaltext\!!es,
+ },
+ } }%
+\to \everysetupbibtexlistplacement
+
+\def\completebibtexpublications{\dodoubleempty\docompletebibtexpublications}
+\unexpanded\def\placebibtexpublications {\dodoubleempty\doplacebibtexpublications}
+
+\def\docompletebibtexpublications[#1][#2]% title might become obsolete, just headtext
+ {\begingroup
+ \edef\currentbibtexsession{#1}%
+ \let\currentlist\currentbibtexsession
+ \setuplist[\currentbibtexsession][\c!criterium=\v!previous,#2]
+ \doifelsenothing{\namedlistparameter\currentbibtexsession\c!title}
+ {\systemsuppliedchapter[\currentbibtexsession]{\headtext{\currentbibtexsession}}}
+ {\normalexpanded{\systemsuppliedchapter[\currentbibtexsession]{\namedlistparameter\currentbibtexsession\c!title}}}%
+ \dodoplacebibtexpublications}
+
+\def\doplacebibtexpublications[#1][#2]%
+ {\begingroup
+ \edef\currentbibtexsession{#1}%
+ \let\currentlist\currentbibtexsession
+ \setuplist[\currentbibtexsession][\c!criterium=\v!previous,#2]%
+ \dodoplacebibtexpublications}
+
+\def\dodoplacebibtexpublications
+ {\determinelistcharacteristics[\currentbibtexsession]%
+ \the\everysetupbibtexlistplacement
+ \forgetall
+ \typesetbibtexlist
+ \endgroup
+ \global\advance\bibtexblock\plusone}
+
+\setvalue{\??pb:\c!numbering:\v!short}#1% todo var s -> short tag
+ {\bibtexlistnumberbox{\bibtexpublicationsparameter\c!numbercommand{\bibtexgetshort\currentpublicationtag}}}
+
+\setvalue{\??pb:\c!numbering:\v!bib}#1% todo var n -> number
+ {\bibtexlistnumberbox{\bibtexpublicationsparameter\c!numbercommand{\bibtexgetnumber\currentpublicationtag}}}
+
+\setvalue{\??pb:\c!numbering:\s!unknown}#1%
+ {\bibtexlistnumberbox{\bibtexpublicationsparameter\c!numbercommand{#1}}}
+
+\def\@@pblimitednumber % name
+ {\csname\??pb:\c!numbering:%
+ \ifcsname\??pb:\c!numbering:\currentbibtexnumbering\endcsname
+ \currentbibtexnumbering
+ \else
+ \s!unknown
+ \fi
+ \endcsname}
+
+\appendtoks
+ \edef\currentbibtexnumbering{\bibtexpublicationsparameter\c!numbering}%
+ \ifx\currentbibtexnumbering\v!no
+ \setuplist[\currentbibtexsession][\c!numbercommand=,\c!symbol=\v!none,\c!textcommand=\outdented]%
+ \else
+ \setuplist[\currentbibtexsession][\c!numbercommand=\@@pblimitednumber]%
+ \fi
+\to \everysetupbibtexlistplacement
+
+\newdimen\bibtexnumberwidth
+
+\def\bibtexlistnumberbox{\hbox \ifcase\bibtexnumberwidth\else to \bibtexnumberwidth\fi}
+
+\appendtoks
+ \doifelse{\bibtexpublicationsparameter\c!autohang}\v!yes
+ {\ifx\currentbibtexnumbering\v!short
+ \setbox\scratchbox\hbox{\bibtexpublicationsparameter\c!numbercommand{\bibtexpublicationsparameter\c!samplesize}}%
+ \else
+ \setbox\scratchbox\hbox{\bibtexpublicationsparameter\c!numbercommand{\ctxlua{tex.write(structure.lists.size())}}}%
+ \fi
+ \bibtexnumberwidth\wd\scratchbox
+ \setuplist[\currentbibtexsession][\c!distance=\zeropoint]}
+ {\doifelsenothing{\bibtexpublicationsparameter\c!width}
+ {\bibtexnumberwidth\zeropoint}
+ {\bibtexnumberwidth\bibtexpublicationsparameter\c!width}}%
+ \setuplist[\currentbibtexsession][\c!width=\bibtexnumberwidth]%
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \let\maybeyear\gobbleoneargument
+ \let\noopsort \gobbleoneargument
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \doifelse{\bibtexpublicationsparameter\c!maybeyear}\v!off
+ {\let\maybeyear\gobbleoneargument}
+ {\let\maybeyear\firstofoneargument}%
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \doifnot{\bibtexpublicationsparameter\c!option}\v!continue
+ {\global\bibtexcounter\zerocount}%
+\to \everysetupbibtexlistplacement
+
+\appendtoks
+ \edef\currentbibtexcriterium{\namedlistparameter\currentbibtexsession\c!criterium}%
+\to \everysetupbibtexlistplacement
+
+\def\typesetbibtexlist
+ {\dobeginoflist
+ \doif{\namedlistparameter\currentbibtexsession\c!criterium}\v!cite
+ {\setuplist[\currentbibtexsession][\c!criterium=\v!here]}%
+ \doifelse{\bibtexpublicationsparameter\c!method}\v!local
+ {\ctxlua{bibtex.hacks.reset(1)}}% function can take method
+ {\ctxlua{bibtex.hacks.reset(2)}}%
+ \placestructurelist
+ {\currentbibtexsession}
+ {\currentbibtexcriterium}
+ {\namedlistparameter\currentbibtexsession\c!number}%
+ \ctxlua{bibtex.hacks.flush("\bibtexpublicationsparameter\c!sorttype")}%
+ \doendoflist}
+
+\unexpanded\def\typesetbibtexpublication#1%
+ {\edef\currentbibtexsessiontag{#1}%
+ \ifx\currentbibtexsessiontag\empty
+ % can't really happen
+ \else\ifx\currentbibtexcriterium\v!all
+ \doplacepublicationindeed
+ \else
+ \ctxlua{bibtex.hacks.doifalreadyplaced("\currentbibtexsessiontag")}
+ \donothing
+ \dotypesetbibtexpublication
+ \fi\fi}
+
+\def\dotypesetbibtexpublication
+ {\doifbibreferencefoundelse\currentbibtexsessiontag
+ {\global\advance\bibtexcounter\plusone
+ \ctxlua{bibtex.hacks.registerplaced("\currentbibtexsessiontag")}%
+ \dodolistelement{\currentbibtexsession}{}{\number\bibtexcounter}{\thebibtexpublicationlistelement}{}{}}
+ {}} % invalid
+
+\def\thebibtexpublicationlistelement
+ {\strut
+ \expanded{\reference[\bibtexrefprefix\currentbibtexsessiontag]{\number\bibtexcounter}}%
+ \dotypesetabibtexpublication\currentbibtexsessiontag
+ \strut}
+
+\def\dotypesetabibtexpublication#1%
+ {\begingroup
+ \ignorespaces
+ \xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/command(bibtex:format)}%
+ \removeunwantedspaces
+% \ignorespaces
+% \bibalternative{\bibgetvart{#1}}%
+% \removeunwantedspaces
+ \endgroup}
+
+\def\doprocessbibtexentry#1{\typesetbibtexpublication{#1}}
+
+% citations
+
+\unexpanded\def\bibtexcitation[#1]%
+ {\edef\currentbibtexsession{#1}%
+ \strictdoifnextoptionalelse\dobibtexcitation\dobibtexref}
+
+\def\dobibtexref#1%
+ {\dodobibtexcitation[#1][]}
+
+\def\dobibtexcitation[#1]%
+ {\strictdoifnextoptionalelse{\dodobibtexcitation[#1]}{\dodobibtexcitation[#1][]}}
+
+\def\dodobibtexcitation[#1][#2]%
+ {\dontleavehmode
+ \begingroup
+ \doifelsenothing{#2}\secondargumentfalse\secondargumenttrue
+ \ifsecondargument
+ \dowhateverbibtexcitation{#1}{#2}%
+ \else
+ \donumberedbibtexcitation{#1}%
+ \fi
+ \endgroup}
+
+\def\dowhatevercitation#1#2%
+ {\processcommalist[#2]\dobibtexcitationindeed
+ \setupinteraction[\c!style=]% use flag instead
+ \doifassignmentelse{#1}
+ {\getparameters[\??pb\??pb][\c!alternative=,\c!extras=,#1]%
+ \edef\currentbibtexvariant{\@@pb@@pbalternative}%
+ \ifx\currentbibtexvariant\empty
+ \edef\currentbibtexvariant{\bibtexpublicationparameter\c!refcommand}%
+ \fi
+ \ifx\@@pb@@pbextras\empty
+ \setupcite[\currentbibtexvariant][#1]%
+ \else
+ \edef\@@pb@@pbextras{{\@@pb@@pbextras\ifdefined\@@pb@@pbright\@@pb@@pbright\else\bibtexpublicationparameter\c!right\fi}}%
+ \expanded{\setupcite[\currentbibtexvariant][#1,\c!right=\@@pb@@pbextras]}%
+ \fi}%
+ {\def\currentbibtexvariant{#1}}%
+ \getvalue{bibtex\currentbibtexvariant ref}[#2]}
+
+\def\donumberedbibtexcitation#1%
+ {\processcommalist[#1]\dobibtexcitationindeed
+ \setupinteraction[\c!style=]%
+ \edef\currentbibtexvariant{\bibtexcitationparameter\c!refcommand}%
+ \getvalue{bibtex\currentbibtexvariant ref}[#1]}
+
+\def\dobibtexcitationindeed#1%
+ {\iftrialtypesetting \else
+ \expanded{\writedatatolist[\currentbibtexsession][bibref=#1]}%
+ \fi}
+
+\def\nobibtexcitation[#1]%
+ {\processcommalist[#1]\dobibtexcitationindeed}
+
+\def\bibtexnumref[#1]%
+ {\dontleavehmode
+ \begingroup
+ \bibtexcitationparameter\v!left
+ \penalty\!!tenthousand
+ \ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}%
+ \bibtexcitationparameter\v!right
+ \endgroup}
+
+\def\dowithbibtexnumrefconnector#1#2%
+ {\ifnum#1>\plusone
+ \ifnum#2>\plusone
+ \ifnum#2=#1\relax
+ \bibtexpublicationsparameter\c!lastpubsep
+ \else
+ \bibtexpublicationsparameter\c!pubsep
+ \fi
+ \fi
+ \fi}
+
+\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibtexrefprefix{#4:}%
+ \inbiblink[#5]}
+
+\def\dowithbibtexnumrefrange#1#2#3#4#5#6#7% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibtexrefprefix{#4:}%
+ \inbiblink[#5]%
+ \endash
+ \def\bibtexrefprefix{#6:}%
+ \inbiblink[#7]}
+
+\def\nobibtexnumref#1%
+ {[#1]}
+
+% hm
+
+% \def\@@pbinumbercommand{\executeifdefined{\??pb:\c!numbercommand:\@@pbnumbering}\firstofoneargument}
+
+% \letvalue{\??pb:\c!numbercommand:\v!yes }\firstofoneargument
+% \letvalue{\??pb:\c!numbercommand:\v!no }\gobbleoneargument
+% \setvalue{\??pb:\c!numbercommand:\v!short}{\bibtexgetshort\currentpublicationtag\gobbleoneargument}
+% \setvalue{\??pb:\c!numbercommand:\v!bib }{\bibtexgetnumber\currentpublicationtag\gobbleoneargument}
+
+% \def\bibalternative#1{\csname\??pv\@@currentalternative#1\endcsname}
+
+% basic setup
+
+% parent -> publicationlist
+%
+% \setuplist
+% [\currentbibtexsession]
+% [\c!samplesize={AA99},
+% \c!alternative=a,
+% \c!interaction=,
+% \c!pagenumber=\v!no,
+% #1,
+% \c!command=]
+
+% \setuppublicationlist
+% [\c!title=,
+% \c!command=\dospecialbibinsert,
+% \c!maybeyear=\v!on]
+
+\setupbibtexpublications
+ [\c!monthconversion=,
+ \c!alternative=apa,
+ \c!method=\v!global,
+ \c!refcommand=num,
+ \c!numbercommand=\bibtexleftnumber]
+
+\setupbibtexcitations % command ?
+ [\c!refcommand=num]
+
+% helpers
+
+\def\doifbibtexinteractionelse
+ {\iflocation
+ \edef\temp{\bibtexcitationparameter\c!interaction}%
+ \ifx\temp\v!stop
+ \@EA@EA@EA\secondoftwoarguments
+ \else
+ \@EA@EA@EA\firstoftwoarguments
+ \fi
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+% variants
+
+% todo: lastsep here
+
+\newconditional\firstbibtexrefsep
+
+\def\bibtexresetrefsep
+ {\settrue\firstbibtexrefsep}
+
+\def\bibtexinsertrefsep
+ {\ifconditional\firstbibtexrefsep
+ \setfalse\firstbibtexrefsep
+ \else
+ \bibtexcitationparameter\c!pubsep
+ \fi}
+
+\def\inbibtexlink#1#2%
+ {\doifreferencefoundelse{\bibtexrefprefix#1}
+ {\goto{#2}[\bibtexrefprefix#1]}
+ {!#1!\unknownreference{#1}}}
+
+\def\dobibtexgotolink#1#2%
+ {\doifreferencefoundelse{\bibtexrefprefix#1}
+ {\goto{#2}[\bibtexrefprefix#1]}
+ {!#1!\unknownreference{#1}}}
+
+\def\dobibattexlink#1#2%
+ {\doifreferencefoundelse{\bibtexrefprefix#1}
+ {\at{#2}[\bibtexrefprefix#1]}
+ {!#1!\unknownreference{#1}}}
+
+\def\dobibtexurllink#1#2%
+ {\expanded{\useURL[bibtex:url:#1][#2]}%
+ \doifbibtexinteractionelse
+ {\goto{\url[bibtex:url:#1]}[url(bibtex:url:#1)]}
+ {\url[bibtex:url:#1]}}
+
+% todo: style, color
+
+\unexpanded\def\bibtexdataref {\dodoubleargument\dobibtexdataref}
+\unexpanded\def\bibtextyperef {\dodoubleargument\dobibtextyperef}
+\unexpanded\def\bibtexkeyref {\dodoubleargument\dobibtexkeyref}
+\unexpanded\def\bibtexserialref {\dodoubleargument\dobibtexserialref}
+\unexpanded\def\bibtexurlref {\dodoubleargument\dobibtexurlref}
+\unexpanded\def\bibtexdoiref {\dodoubleargument\dobibtexdoiref}
+\unexpanded\def\bibtexpageref {\dodoubleargument\dobibtexpageref}
+\unexpanded\def\bibtexnoneref {\dodoubleargument\dobibtexnoneref}
+\unexpanded\def\bibtexshortref {\dodoubleargument\dobibtexshortref}
+\unexpanded\def\bibtexyearref {\dodoubleargument\dobibtexyearref}
+\unexpanded\def\bibtexauthorref {\dodoubleargument\dobibtexauthorref}
+\unexpanded\def\bibtexauthoryearref {\dodoubleargument\dobibtexauthoryearref}
+\unexpanded\def\bibtexauthoryearsref{\dodoubleargument\dobibtexauthoryearsref}
+
+\def\dobibtexdataref {\doprocessbibtexref\dodobibtexdataref {ref}} % [#1][#2]
+\def\dobibtextyperef {\doprocessbibtexref\dodobibtextyperef {type}} % [#1][#2]
+\def\dobibtexkeyref {\doprocessbibtexref\dodobibtexkeyref {key}} % [#1][#2]
+\def\dobibtexserialref {\doprocessbibtexref\dodobibtexserialref {serial}} % [#1][#2]
+\def\dobibtexurlref {\doprocessbibtexref\dodobibtexurlref {url}} % [#1][#2]
+\def\dobibtexdoiref {\doprocessbibtexref\dodobibtexdoiref {doi}} % [#1][#2]
+\def\dobibtexpageref {\doprocessbibtexref\dodobibtexpageref {page}} % [#1][#2]
+\def\dobibtexnoneref {\doprocessbibtexref\dodobibtexnoneref {none}} % [#1][#2]
+\def\dobibtexshortref {\doprocessbibtexref\dodobibtexshortref {short}} % [#1][#2]
+\def\dobibtexyearref {\doprocessbibtexref\dodobibtexyearref {year}} % [#1][#2]
+\def\dobibtexauthorref {\doprocessbibtexref\dodobibtexauthorref {author}} % [#1][#2]
+\def\dobibtexauthoryearref {\doprocessbibtexref\dodobibtexauthoryearref {authoryear}} % [#1][#2]
+\def\dobibtexauthoryearsref{\doprocessbibtexref\dodobibtexauthoryearsref{authoryears}} % [#1][#2]
+
+\def\doprocessbibtexref#1#2[#3][#4]%
+ {\edef\currentbibtexsession{#3}%
+ \edef\currentbibtexvariant{#2}%
+ \def\dodoprocessbibtexref##1%
+ {% test for existence
+ \edef\currentbibtextag{##1}%
+ \bibtexinsertrefsep
+ #1{##1}}%
+ \bibtexresetrefsep
+ \bibtexcitationparameter\v!left
+ \processcommalist[#4]\dodoprocessbibtexref\relax
+ \bibtexcitationparameter\v!right}
+
+\def\dodobibtexdataref#1%
+ {\dotypesetabibtexpublication{#1}}
+
+\def\dodobibtextyperef#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/attribute('category')}}%
+ \bibtexrefcontent}
+
+\def\dodobibtexkeyref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='key']/context()}}%
+ \dobibtexgotolink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexserialref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/match()}}%
+ \dobibtexgotolink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexurlref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/field[@name='url']/context()}}%
+ \dobibtexurllink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexdoiref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/field[@name='doi']/context()}}%
+ \dobibtexurllink{#1}{http://dx.doi.org/\bibtexrefcontent}}
+
+\def\dodobibtexpageref#1%
+ {\dobibtexatlink{#1}{}} % second argument can become 'page'
+
+\def\dodobibtexnoneref#1%
+ {}
+
+\def\dodobibtexshortref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/bibtexshort()}}%
+ \dobibtexgotolink{#1}{\bibtexrefcontent}}
+
+\def\dodobibtexyearref#1%
+ {\edef\bibtexrefcontent{\xmlfilter{bibtex:\currentbibtexsession}{/bibtex/entry[@tag='#1']/field[@name='year']/context()}}%
+ \bibtexrefcontent}
+
+% \def\bibmaybeinteractive#1#2%
+% {\doifelsevalue{@@pv\@@currentalternative\c!compress}
+% {\ifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}}
+% {#2}}
+
+% \def\bibauthornumref[#1]%
+% {\getcommalistsize[#1]%
+% \global\bibitemcounter\commalistsize
+% \bibresetrefsep
+% \processcommalist[#1]\dobibauthornumref }
+%
+% \def\dobibauthornumref#1%
+% {\bibinsertrefsep
+% \doifbibreferencefoundelse{#1}
+% {\begingroup
+% \bibgetvara{#1}%
+% \bibalternative\c!inbetween
+% \setuppublications[\c!refcommand=num]%
+% \cite[#1]%
+% \endgroup}
+% {\unknownreference{#1}}}
+
+% compress years
+% andtext namesep
+% otherstext authoretallimit
+
+% we will use context.* instead at the lua end because it saves us passing settings
+
+% \def\thebibtexpubsep {\bibtexpublicationsparameter\c!pubsep}
+% \def\thebibtexlastpubsep {\bibtexpublicationsparameter\c!lastpubsep}
+% \def\thebibtexfinalpubseparator{\bibtexpublicationsparameter\c!lastpubsep}
+
+\def\dodobibtexauthorref #1{\ctxlua{bibtex.authorref ("bibtex:\currentbibtexsession","#1","normal","author")}}
+\def\dodobibtexauthoryearref #1{\ctxlua{bibtex.authoryearref ("bibtex:\currentbibtexsession","#1","normal","author")}}
+\def\dodobibtexauthoryearsref#1{\ctxlua{bibtex.authoryearsref("bibtex:\currentbibtexsession","#1","normal","author")}}
+
+\unexpanded\def\bibtexsingularplural#1#2{\ctxlua{bibtex.singular_or_plural(\!!bs#1\!!es,\!!bs#2\!!es)}}
+
+\protect \endinput
+
diff --git a/tex/context/base/bibl-tra.lua b/tex/context/base/bibl-tra.lua
new file mode 100644
index 000000000..442231028
--- /dev/null
+++ b/tex/context/base/bibl-tra.lua
@@ -0,0 +1,194 @@
+if not modules then modules = { } end modules ['bibl-bib'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+bibtex = bibtex or { }
+bibtex.hacks = bibtex.hacks or { }
+
+local match, gmatch, format, concat, sort = string.match, string.gmatch, string.format, table.concat, table.sort
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+local variables, constants = interfaces.variables, interfaces.constants
+
+local trace_bibtex = false trackers.register("publications.bibtex", function(v) trace_bibtex = v end)
+
+local hacks = bibtex.hacks
+
+local list, done, alldone, used, registered, ordered = { }, { }, { }, { }, { }, { }
+local mode = 0
+
+local template = string.striplong([[
+ \citation{*}
+ \bibstyle{cont-%s}
+ \bibdata{%s}
+]])
+
+function hacks.process(settings)
+ local style = settings.style or ""
+ local database = settings.database or ""
+ local jobname = tex.jobname
+ if database ~= "" then
+ interfaces.showmessage("publications",3)
+ io.savedata(file.addsuffix(jobname,"aux"),format(template,style,database))
+ if trace_bibtex then
+ logs.report("publications","processing bibtex file '%s'",jobname)
+ end
+ os.execute(format("bibtex %s",jobname))
+ -- purge 'm
+ end
+end
+
+function hacks.register(str)
+ if trace_bibtex then
+ logs.report("publications","registering bibtex entry '%s'",str)
+ end
+ registered[#registered+1] = str
+ ordered[str] = #registered
+end
+
+function hacks.reset(m)
+ mode, list, done = m, { }, { }
+end
+
+function hacks.add(str,listindex)
+ if not str or mode == 0 then
+ -- skip
+ elseif mode == 1 then
+ -- all locals but no duplicates
+ local sc = structure.sections.currentid()
+ if done[str] ~= sc then
+ done[str], alldone[str] = sc, true
+ list[#list+1] = { str, listindex }
+ end
+ elseif mode == 2 then
+ -- all locals but no preceding
+ local sc = structure.sections.currentid()
+ if not alldone[str] and done[str] ~= sc then
+ done[str], alldone[str] = sc, true
+ list[#list+1] = { str, listindex }
+ end
+ end
+end
+
+local function compare(a,b)
+ local aa, bb = a[1], b[1]
+ if aa and bb then
+ return ordered[aa] < ordered[bb]
+ else
+ return true
+ end
+end
+
+function hacks.flush(sortvariant)
+ if sortvariant == "" or sortvariant == variables.cite or sortvariant == "default" then
+ -- order is cite order i.e. same as list
+ else
+ sort(list,compare)
+ end
+ for i=1,#list do
+ context.doprocessbibtexentry(list[i][1])
+ end
+end
+
+function hacks.registerplaced(str)
+ used[str] = true
+end
+
+function hacks.doifalreadyplaced(str)
+ commands.testcase(used[str])
+end
+
+-- we ask for :tag but when we can't find it we go back
+-- to look for previous definitions, and when not found again
+-- we look forward
+
+local function compare(a,b)
+ return a[3] < b[3]
+end
+
+function hacks.resolve(prefix,block,reference) -- maybe already feed it split
+ local subset = jobreferences.collected[prefix or ""] or jobreferences.collected[""]
+ if subset then
+ local result, done = { }, { }
+ block = tonumber(block)
+ for rest in gmatch(reference,"([^,%s]+)") do
+ local blk, tag, found = block, nil, nil
+ if block then
+ tag = blk .. ":" .. rest
+ found = subset[tag]
+ if not found then
+ for i=block-1,1,-1 do
+ tag = i .. ":" .. rest
+ found = subset[tag]
+ if found then
+ blk = i
+ break
+ end
+ end
+ end
+ end
+ if not found then
+ blk = "*"
+ tag = blk .. ":" .. rest
+ found = subset[tag]
+ end
+ if found then
+ local current = found.entries and found.entries.text
+ if current and not done[current] then
+ result[#result+1] = { blk, rest, current }
+ done[current] = true
+ end
+ end
+ end
+ -- todo: ranges so the interface will change
+ sort(result,compare)
+ local first, last, firsti, lasti, firstr, lastr
+ local collected = { }
+ for i=1,#result do
+ local r = result[i]
+ local current = r[3]
+ if not first then
+ first, last, firsti, lasti, firstr, lastr = current, current, i, i, r, r
+ elseif current == last + 1 then
+ last, lasti, lastr = current, i, r
+ else
+ if last > first + 1 then
+ collected[#collected+1] = { firstr[1], firstr[2], lastr[1], lastr[2] }
+ else
+ collected[#collected+1] = { firstr[1], firstr[2] }
+ if last > first then
+ collected[#collected+1] = { lastr[1], lastr[2] }
+ end
+ end
+ first, last, firsti, lasti, firstr, lastr = current, current, i, i, r, r
+ end
+ end
+ if first then
+ if last > first + 1 then
+ collected[#collected+1] = { firstr[1], firstr[2], lastr[1], lastr[2] }
+ else
+ collected[#collected+1] = { firstr[1], firstr[2] }
+ if last > first then
+ collected[#collected+1] = { lastr[1], lastr[2] }
+ end
+ end
+ end
+ if #collected > 0 then
+ for i=1,#collected do
+ local c = collected[i]
+ if c[3] then
+ context.dowithbibtexnumrefrange(#collected,i,prefix,c[1],c[2],c[3],c[4])
+ else
+ context.dowithbibtexnumref(#collected,i,prefix,c[1],c[2])
+ end
+ end
+ else
+ context.nobibtexnumref("error 1")
+ end
+ else
+ context.nobibtexnumref("error 2")
+ end
+end
diff --git a/tex/context/base/bibl-tra.mkii b/tex/context/base/bibl-tra.mkii
new file mode 100644
index 000000000..087781db9
--- /dev/null
+++ b/tex/context/base/bibl-tra.mkii
@@ -0,0 +1,1778 @@
+%D \module
+%D [ file=bibl-tra,
+%D version=2009.08.13,
+%D title=\CONTEXT\ Publication Module,
+%D subtitle=Publications,
+%D author=Taco Hoekwater,
+%D date=\currentdate,
+%D copyright=Public Domain]
+%C
+%C Donated to the public domain.
+
+%D This used to be module \type {t-bib} but due to the number of differences
+%D in handling structure between \MKII\ and \MKIV\ we now have \BIBTEX\ support
+%D in the kernel. The only patches concerns some namespace issues. Also,
+%D constants and variables are now predefined. When the \MKIV\ code is well
+%D tested I might backport a couple of adaptions to this \MKII\ variant.
+
+\writestatus{loading}{ConTeXt Bibliography Support / BibTeX}
+
+\definefilesynonym[bib][obsolete]
+
+% here starts t-bib.tex
+
+%D The original was developed independantly by Taco Hoekwater while still working for Kluwer
+%D Academic publishers (it still used the dutch interface then). Development continued after
+%D he left Kluwer, and in Januari 2005, the then already internationalized file was merged
+%D with the core distribution by Hans Hagen. The current version is once again by Taco.
+%D
+%D More documentation and additional resources can be found on the contextgarden:
+%D \hyphenatedurl{http://wiki.contextgarden.net//Bibliography}.
+
+%D \subject{DONE (dd/mm/yyyy)}
+%D
+%D \startitemize
+%D \item add author definition (and associated system variable) (26/05/2005)
+%D \item add finalnamesep support for Oxford comma (17/09/2005)
+%D \item add \type{\insert...} for: doi, eprint, howpublished (19/09/2005)
+%D \item allow a defaulted \type{\setupcite} (19/11/2005)
+%D \item renamed citation type 'number' to 'serial' (19/11/2005)
+%D \item better definition of \type{\inverted...author} (19/11/2005)
+%D \item don't reset [numbercommand] in \type {\setuppublication} by default (20/11/2005)
+%D \item don't disable other \type {\setuppublication} keys if alternative is present (20/11/2005)
+%D \item drop \type{\sanitizeaccents} (20/11/2005)
+%D \item added \type{\nocite} and \type{\cite[none]} (21/11/2005)
+%D \item added headtext for it (23/11/2005)
+%D \item make \type{\cite[url]} and \type{\cite[doi]} interactive (23/11/2005)
+%D \item make right-aligned labels in the list work even when autohang=no
+%D \item use 'et al.' instead of 'et.al.'. Pointed out by Peter M�nster (30/12/2005)
+%D \item added headtext for cz (31/12/2005)
+%D \item Keep whitespace after \type{\cite} with single argument (31/12/2005)
+%D \item Fix broken \type{\cite{}} support (31/12/2005)
+%D \item Use \type{\readfile} inside \type{\usepublications} instead of \type{\readsysfile} (12/01/2006)
+%D \item Use \type{\currentbibyear} and \type{\currentbibauthor} instead of \type{\YR} and \type{\AU} (05/02/2006)
+%D \item Fix compressed version of authoryear style (05/02/2006)
+%D \item Rename the clashing data fields \type{\url} and \type{\type} to \type{\biburl} and \type{\bibtype} (05/02/2006)
+%D \item Added two french bibl files from Renaud Aubin (06/02/2006)
+%D \item Five new bib class and eight extra bib fields, for IEEEtran (07/02/2006)
+%D \item French keyword translation, provided by Renaud (08/02/2006)
+%D \item fix underscores in undefined keys (22/02/2006)
+%D \item Destroy interactivity in labels of the publication list (13/03/2006)
+%D \item fix multi-cite list compression (11/4/2006)
+%D \item fix \type{\getcitedata} (11/4/2006)
+%D \item magic for chapter bibs (18-25/4/2006)
+%D \item language setting (25/4/2006)
+%D \item use \type{\hyphenatedurl} for \type{\inserturl} (25/4/2006)
+%D \item Add \type{\docitation} to \type{\nocite}(26/4/2006)
+%D \item patents can have numbers, added to bst files (26/4/2006)
+%D \item \type{\docitation} needs a \type{\iftrialtypesetting} (27/4/2006)
+%D \item \type{\filllocalpublist}'s loop is bound by definedness, not resolvedness (27/4/2006)
+%D \item \type{\setuppublications[monthconversion=]} added (15/5/2006)
+%D \item use \type{\undefinedreference} instead of bare question marks (15/5/2006)
+%D \item add grouping around \type{\placepublications} commands (16/5/2006)
+%D \item fix a bug in \type{\cite{}} (17/5/2006)
+%D \item support \type{\cite[authornum]} (18/5/2006)
+%D \item make \type{\cite} unexpandable (20/6/2006)
+%D \item allow hyperlinks in author\&year combo's
+%D (cite list compression has to be off) (20/6/2006)
+%D \item fix duplicate labels for per-chapter style (20/6/2006)
+%D \item allow \type{\setupcite[interaction=(start|stop)]}
+%D \item fix the item number in the publication list with 'numbering=yes' (22/6/2006)
+%D \item make the default criterium for \type{\placepublications} be \type{previous} (23/6/2006)
+%D \item fix \type{\normalauthor} and \type{\normalshortauthor} spacing (29/6/2006)
+%D \item do not typeset empty arguments to \type{\typesetapublication} (29/6/2006)
+%D \item add \type{symbol=none} to \type{\setuplist} in unnumbered
+%D mode to prevent typesetting of bare numbers (29/6/2006)
+%D \item remove two incorrect spaces from bibl-num.tex (1/7/2006)
+%D \item reset font styles within \type{\cite}, so that font switches
+%D in \type{left} stay in effect (12/7/2006)
+%D \item guard added against loading bbl files multiple times (13/7/2006)
+%D \item fix \type{\cite[num]} with compression is on. (14/7/2006)
+%D \item test \type{\iflocation} before deciding to use the
+%D interactive version of cite (18/7/2006)
+%D \item support \type{\setupcite[authoretallimit=1]} (18/7/2006)
+%D \item support use of \type{\cite} within titles and captions by
+%D saveguarding the list item extraction and reference placement
+%D code (19/7/2006)
+%D \item support \type{\setuppublicationlist[title=\chapter]} (4/8/2006)
+%D \item use the expansion of \type{\headtext{pubs}} (4/8/2006)
+%D \item hook added for repeated authors in publication list
+%D \type{\setuppublicationlist[artauthorcommand=\mythreeargscommand]}
+%D (4/8/2006)
+%D \item make the bracketed arguments of \type{\artauthor}, \type{\author}
+%D and \type{\editor} (bbl commands) optional (4/8/2006)
+%D \item the constants \type{sorttype}, \type{compress} and
+%D \type{autohang} have moved to the core (8/8/2006)
+%D \item bibtex is now registered as a program to be run by texexec (8/8/2006)
+%D \item fix a bug in \type{\setupcite[authoretallimit=1]} (9/8/2006)
+%D \item fix a bug inside citations that prevented lastpubsep from ever being
+%D used due to a volatile \type{\commalistsize} (25/8/2006).
+%D \item added the possibility of \type{\placepublications[option=continue]}
+%D (6/9/2006)
+%D \item Mojca translated Master's Thesis to Masterarbeit (bibl-apa-de.tex)
+%D (12/9/2006)
+%D \item Added \type{\setuppublicationlist[maybeyear=off]} by request from
+%D Thomas Schmitz (15/9/2006)
+%D \item Removed some spurious spaces pointed out by willi egger (19/9/2006)
+%D \item Add configuration of bibtex executable name (4/11/2006)
+%D \item Fix numbering=short and numbering=bib (spotted by Matthias W�chter) (4/11/2006)
+%D \item third attempt to get a correct release (5/11/2006)
+%D \item fix a few missing dots in bibl-num.tex (7/12/2006)
+%D \item Patch for DOI's by Tobias Burnus (17/4/2007)
+%D \item Patch for \type{\insertbiburl} and \type{\insertdoi} for Tobias Burnus (18/4/2007)
+%D \item Added a missing \type{\relax} in \type{\dospecialbibinsert},
+%D that made the space before the {\it et al.} text disappear. (18/4/2007)
+%D \item Attempt to fix percent signs in bbl files. As a side-effect,
+%D this prohibits comments in \tex{startpublication} blocks! (17/4/2008)
+%D \item Patch from Matthias W\"achter that allows arbitrary .bst
+%D files to be used with \tex{setupbibtex} (25/9/2008)
+%D \item Extended for the new multilingual setups for the Oct 2008 current of ConTeXt (23/10/2008)
+%D \item Multilingual setups needed another fix (27/10/2008)
+%D \item Two fixes for bibl-apa by Michael Green (27/10/2008)
+%D \item Catalan translation of 'References' (10/11/2008)
+%D \item 'chapter' -> 'chapitre' in bibl-apa-fr (27/11/2008)
+%D \item Run bibtex via os.execute in mkiv modee (01/12/2008)
+%D \item Small correction in bibl-apa's placement of volume
+%D information in articles (05/01/2009)
+%D \item Handle multi-author (more than two) cases in \type{\cite}
+%D (02/03/2009)
+%D \item Suppress a syntax error in \type{cont-xp} mode. The output is
+%D probably not right, though (02/03/2009)
+%D \item Added a \tex{loadmarkfile} at the end, and two new files
+%D from Hans. The \type{t-bib.mkiv} is needed to make the module
+%D work with the new structure code (17/04/2009)
+%D \item Added a patch to \type{t-bib.mkiv} from Hans to make the
+%D cross referencing between multiple citations an
+%D bibliographies work (27/04/2009)
+%D \item Remove a superfluous \type{\unprotect} in t-bib.mkiv (11/05/2009).
+%D \item Patch of incollection in bibl-ams.tex from Xan (08/06/2009).
+%D \item Patch of unpublished in bibl-ams.tex from Xan (22/07/2009).
+%D \item Modified \type{\bibdogetupsometextprefix} so it works for undefined
+%D language labels, from Hans (13/08/2009).
+%D \item Removed some \MKIV\ hacks as well as some things that are in the
+%D core like variables, constants and messages (HH:22/08/2009).
+%D \item Added \type{bib} in front of \type {insert} macros and initialize
+%D then later on (HH:22/08/2009).
+%D \item Removed test for type {\currentlocationreference} plus associated
+%D code (HH:22/08/2009).
+%D \stopitemize
+%D
+%D \subject{WISHLIST}
+%D
+%D \startitemize
+%D \item link back from publication list to citation
+%D \item export \type {\citation{}}
+%D \item support mlbibtex
+%D \item don't load the whole lot, but filter entries instead
+%D \stopitemize
+
+\unprotect
+
+%D Variables, constants and messages are removed as they are now in the
+%D multilingual interface modules.
+
+\def\biblistname{pubs} % for compatibility
+
+%D how to load the references. There is some new stuff here
+%D to support Idris' (incorrect :-)) use of projects
+
+% \let\preloadbiblist\relax
+%
+% \ifx\currentcomponent\v!text
+% % single file
+% \edef\temp{\the\everystarttext}%
+% \ifx\temp\empty
+% % post-starttext
+% \def\preloadbiblist{\dousepublications\jobname }%
+% \else
+% % pre-starttext
+% \appendtoks \dousepublications\jobname \to \everystarttext
+% \fi
+% %
+% \else \ifx\currentcomponent\v!project
+% % a project file, have to set up the partial products!
+% \def\startproduct #1 %
+% {\doateverystarttext
+% \dousepublications{#1}%
+% \donextlevel\v!product\currentproduct
+% \doexecutefileonce\doexecutefileonce
+% \donotexecutefile\doexecutefile#1\\}%
+% %
+% \else \ifx\currentcomponent\v!product
+% % a product file
+% \def\preloadbiblist{\dousepublications\jobname }%
+% %
+% \else
+% % a component? not sure what to do
+% \def\preloadbiblist{\dousepublications\jobname }%
+% %
+% \fi \fi \fi
+
+\def\preloadbiblist
+ {\globallet\preloadbiblist\relax
+ \dousepublications\jobname}
+
+\definelist[pubs]
+\setuplist[pubs][\c!width=]
+
+%D \macros{bibdoif,bibdoifnot,bibdoifelse}
+%D
+%D Here are a few small helpers that are used a lot
+%D in all the typesetting commands
+%D (\type{\insert...}) we will encounter later.
+
+\long\def\bibdoifelse#1%
+ {\@EA\def\@EA\!!stringa\@EA{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\long\def\bibdoifnot#1%
+ {\@EA\def\@EA\!!stringa\@EA{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\long\def\bibdoif#1%
+ {\@EA\def\@EA\!!stringa\@EA{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D Bibtex settings separated out
+
+%D No point in writing the aux file if there is no database...
+
+\def\setupbibtex{\dosingleempty\dosetupbibtex}
+
+\def\dosetupbibtex[#1]%
+ {\let\@@pbdatabase\empty
+ \getparameters[\??pb][\c!sort=\s!default,#1]%
+ \expanded{\processaction[\@@pbsort]}
+ [ \v!no=>\def\bibstyle{cont-no},
+ \v!author=>\def\bibstyle{cont-au},
+ \v!title=>\def\bibstyle{cont-ti},
+ \v!short=>\def\bibstyle{cont-ab},
+ \s!default=>\def\bibstyle{cont-no},
+ \s!unknown=>\def\bibstyle{\@@pbsort}]%
+ \ifx\@@pbdatabase\empty\else \writeauxfile \fi}
+
+\dosetupbibtex[bibtex=bibtex]
+
+%D \macros{writeauxfile}
+%D
+%D Unfortunately, \BIBTEX\ is not the best configurable program
+%D around. The names of the commands it parses as well as the \type{.aux}
+%D extension to the file name are both hardwired.
+%D
+%D This means \CONTEXT\ has to write a \LATEX-style auxiliary file, yuk!
+%D The good news is that it can be rather short. We'll just ask
+%D \BIBTEX\ to output the entire database(s) into the \type{bbl} file.
+%D
+%D The \type{\bibstyle} command controls how the \type{bbl} file will
+%D be sorted. The possibilities are:
+%D
+%D \startitemize[packed]
+%D \item by author (+year, title): cont-au.bst
+%D \item by title (+author, year): cont-ti.bst
+%D \item by short key as in abbrev.bst: cont-ab.bst
+%D \item not sorted at all: cont-no.bst
+%D \stopitemize
+
+\def\writeauxfile
+ {\doifmode{*\v!first}
+ {\openout \scratchwrite \jobname.aux
+ \write \scratchwrite {\string\citation{*}}%
+ \write \scratchwrite {\string\bibstyle{\bibstyle}}%
+ \write \scratchwrite {\string\bibdata{\@@pbdatabase}}%
+ \closeout\scratchwrite
+ \showmessage\m!publications{3}{}%
+ \expanded{\installprogram{\@@pbbibtex\space\jobname}}}}
+
+%D \macros{ifsortbycite,iftypesetall,ifautohang,ifbibcitecompress}
+%D
+%D The module needs some new \type{\if} statements.
+
+%D Default sort order of the reference list is by citation.
+
+\newif\ifsortbycite \sortbycitetrue
+
+%D By default, only referenced publications are typeset
+
+\newif\iftypesetall \typesetallfalse
+
+%D Hanging indentation of the publication list
+%D will not adjust itself according to the width of the label.
+
+\newif\ifautohang \autohangfalse
+
+%D Cite lists are compressed, if possible.
+
+\newif\ifbibcitecompress \bibcitecompresstrue
+
+\def\setuppublications
+ {\dosingleargument\dosetuppublications}
+
+\def\bibleftnumber#1%
+ {#1\hfill~}
+
+\def\dosetuppublications[#1]%
+ {\getparameters
+ [\??pb]
+ [\c!alternative=,#1]%
+ \doifsomething\@@pbalternative
+ {\readsysfile
+ {bibl-\@@pbalternative.tex}
+ {\showmessage\m!publications{6}{bibl-\@@pbalternative}\let\@@pbalternative\empty}
+ {\showmessage\m!publications{1}{bibl-\@@pbalternative}\let\@@pbalternative\empty}}%
+ \getparameters
+ [\??pb]
+ [#1]%
+ \processaction
+ [\@@pbcriterium]
+ [ \v!all=>\typesetalltrue,
+ \s!unknown=>\typesetallfalse]%
+ \processaction
+ [\@@pbautohang]
+ [ \v!yes=>\autohangtrue,
+ \s!unknown=>\autohangfalse]%
+ \processaction
+ [\@@pbsorttype]
+ [ \v!cite=>\sortbycitetrue,
+ \v!bbl=>\sortbycitefalse,
+ \s!default=>\sortbycitetrue,
+ \s!unknown=>\sortbycitefalse]%
+ \processaction
+ [\@@pbnumbering]
+ [ \v!yes=>\let\@@pbinumbercommand\firstofoneargument,
+ \v!no=>\let\@@pbinumbercommand\gobbleoneargument,
+ \v!short=>\def\@@pbinumbercommand##1{\getvalue{pbds-\@@pbk}},
+ \v!bib=>\def\@@pbinumbercommand##1{\getvalue{pbdn-\@@pbk}},
+ \s!unknown=>\let\@@pbinumbercommand\firstofoneargument]%
+ \processaction
+ [\@@pbrefcommand]
+ [\s!default=>\edef\@@citedefault{\@@pbrefcommand},
+ \s!unknown=>\edef\@@citedefault{\@@pbrefcommand}]}
+
+% initialize
+
+\def\@@pbrefcommand{num}
+\def\@@pbnumbercommand{\bibleftnumber}
+
+%D \macros{usepublications}
+%D
+%D We need \type{\usereferences} so that it is possible to
+%D refer to page and/or appearance number for publications
+%D in the other document.
+
+\def\usepublications[#1]%
+ {\usereferences[#1]\processcommalist[#1]\dousepublications}
+
+\def\dousepublications#1%
+ {\doonlyonce
+ {#1.\f!bibextension}
+ {\readfile{#1.\f!bibextension}
+ {\showmessage\m!publications{4}{#1.\f!bibextension}}
+ {\showmessage\m!publications{2}{#1.\f!bibextension}}}}
+
+%D \macros{setuppublicationlist}
+%D
+%D This will be the first command in (\BIBTEX-generated) \type{bbl}
+%D files. `samplesize' is a sample value (in case of \BIBTEX-generated
+%D files, this will be the longest `short' key). `totalnumber'
+%D is the total number of entries that will follow in this
+%D file.
+
+%D Both values are only needed for the label calculation
+%D if `autohang' is `true', so by default the command is
+%D not even needed, and therefore I saw no need to give
+%D it it's own system variable and it just re-uses \type{pb}.
+
+\def\setuppublicationlist
+ {\dosingleempty\dosetuppublicationlist}
+
+\def\dosetuppublicationlist[#1]%
+ {\getparameters[\??pv data][#1]%
+ \setuplist
+ [pubs]
+ [\c!samplesize={AA99},\c!totalnumber={99},
+ \c!alternative=a,\c!interaction=,\c!pagenumber=\v!no,#1]}
+
+\def\setuppublicationlayout[#1]#2%
+ {\setvalue{\??pv data#1}{#2\unskip}}
+
+%D \macros{bibalternative}
+%D
+%D A nice little shorthand that will be used so we don't have to
+%D key in the weird \type{\@@pv} parameter names all the time.
+
+\def\bibalternative#1%
+ {\getvalue{\??pv\@@currentalternative#1}}
+
+%D \macros{simplebibdef,bibcommandlist}
+%D
+%D \type{\simplebibdef} defines \type{bib@#1}, which in turn will
+%D use one argument that is stored in \type{@@pb@#1}.
+%D
+%D \type{\simplebibdef} also defines \type{insert#1}, which can be
+%D used in the argument of \type{\setuppublicationlayout} to fetch
+%D one of the \type{@@pb@} data entries. \type{insert#1} then has
+%D three arguments: \type{#1} are commands to be executed before the
+%D data, \type{#2} are commands to be executed after the data, and
+%D \type{#3} are commands to be executed if the data is not found.
+
+%D \type{\bibcommandlist} is the list of commands that is affected
+%D by this approach. Later on, it will be used to do a series
+%D of assignments from \type{#1} to \type{bib@#1}: e.g
+%D \type{\title} becomes \type{\bib@title} when used within
+%D a publication.
+
+\newtoks\initializebibdefinitions % we need to prevent clashes (HH)
+
+% \def\simplebibdef#1% hh: funny expansion ?
+% {\@EA\long\@EA\def\csname bib@#1\endcsname##1%
+% {\setvalue{\??pb @#1}{##1}%
+% \ignorespaces}%
+% \@EA\def\csname insert#1\endcsname##1##2##3%
+% {\@EA\bibdoifelse
+% \@EA{\csname @@pb@#1\endcsname}%
+% {##1\csname @@pb@#1\endcsname##2}%
+% {##3}%
+% }}
+
+\def\simplebibdef#1% hh: funny expansion ?
+ {\@EA\long\@EA\def\csname bib@#1\endcsname##1%
+ {\setvalue{\??pb @#1}{##1}\ignorespaces}%
+ \expandafter \appendtoks
+ \expandafter\let\csname insert#1\expandafter\endcsname\csname bibinsert#1\endcsname
+ \to \initializebibdefinitions
+ \@EA\unexpanded\@EA\def\csname bibinsert#1\endcsname##1##2##3%
+ {\@EA\bibdoifelse\@EA{\csname\??pb @#1\endcsname}{##1\csname\??pb @#1\endcsname##2}{##3}}}
+
+\def\bibcommandlist
+ {abstract, annotate, arttitle, assignee, bibnumber, bibtype, biburl, chapter, city,
+ comment, country, day, dayfiled, doi, edition, eprint, howpublished, isbn, issn,
+ issue, journal, keyword, keywords, lastchecked, month, monthfiled, names, nationality,
+ note, notes, organization, pages, pubname, pubyear, revision, series, size, thekey,
+ title, volume, yearfiled}
+
+\processcommacommand[\bibcommandlist]\simplebibdef
+
+\def\bibinsertdoi#1#2#3%
+ {{\bibdoifelse{\@@pb@doi}%
+ {\edef\ascii{\@EA\detokenize\@EA{\@@pb@doi}}%
+ #1\expanded{\gotoDOI{\@@pb@thekey}{\ascii}}#2}{#3}}}
+
+\def\bibinsertbiburl#1#2#3%
+ {{\bibdoifelse{\@@pb@biburl}%
+ {\edef\ascii{\@EA\detokenize\@EA{\@@pb@biburl}}%
+ #1\expanded{\gotoURL{\@@pb@thekey}{\ascii}}#2}{#3}}}
+
+\def\bibinsertmonth#1#2#3%
+ {\bibdoifelse{\@@pb@month}%
+ {#1\doifnumberelse{\@@pb@month}%
+ {\doifconversiondefinedelse\@@pbmonthconversion
+ {\convertnumber\@@pbmonthconversion{\@@pb@month}}{\@@pb@month}}%
+ {\@@pb@month}#2}{#3}}
+
+\appendtoks
+ \let\inserturl \bibinsertbiburl % for backward compat.
+ \let\inserttype\bibinsertbibtype % for backward compat.
+\to\initializebibdefinitions
+
+\def\newbibfield[#1]%
+ {\simplebibdef{#1}%
+ \edef\bibcommandlist{\bibcommandlist,#1}}
+
+%D \macros{bib@crossref}
+%D
+%D \type{\crossref} is used in database files to point to another
+%D entry. Because of this special situation, it has to be defined
+%D separately. Since this command will not be seen until at
+%D \type{\placepublications}, it may force extra runs. The same is
+%D true for \type{\cite} commands inside of publications.
+
+\def\bib@crossref#1%
+ {\setvalue{\??pb @crossref}{#1}\ignorespaces}
+
+\def\bibinsertcrossref#1#2#3%
+ {\bibdoifelse{\@@pb@crossref}
+ {#1\@EA\cite\@EA[\@@pb@crossref]#2}
+ {#3}}
+
+\appendtoks\let\insertcrossref\bibinsertcrossref\to\initializebibdefinitions
+
+%D \macros{complexbibdef,specialbibinsert}
+%D
+%D The commands \type{\artauthor}, \type{\author} and
+%D \type{\editor} are more complex than the other commands.
+%D Their argument lists have this form:
+%D
+%D \type{\author[junior]{firstnames}[inits]{von}{surname}}
+%D
+%D (bracketed stuff is optional)
+%D
+%D And not only that, but there also might be more than one of each of
+%D these commands. This is why a special command is needed to insert
+%D them, as well as one extra counter for each command.
+
+%D All of these \type{\@EA}'s and \type{\csnames} make this code
+%D look far more complex than it really is. For example, the argument
+%D \type{author} defines the macro \type{\bib@author} to do two
+%D things: increment the counter \type{\author@num} (let's say to 2)
+%D and next store it's arguments in the macro \type{\@@pb@author2}.
+%D And it defines \type{\insertauthors} to expand into
+%D \starttyping
+%D \specialbibinsert{author}{\author@num}{}{}{}
+%D \stoptyping
+
+\def\docomplexbibdef#1%
+ {\def\currentype{#1}%
+ \dosingleempty\dodocomplexbibdef}
+
+\def\dodocomplexbibdef[#1]#2%
+ {\def\firstarg{#1}\def\secondarg{#2}%
+ \dosingleempty\dododocomplexbibdef}
+
+\def\dododocomplexbibdef[#1]#2#3%
+ {\@EA\increment\csname \currentype @num\endcsname
+ \setevalue{\??pb @\currentype\csname \currentype @num\endcsname}%
+ {{\secondarg}{#2}{#3}{#1}{\firstarg}}\ignorespaces}%
+
+% \def\complexbibdef#1%
+% {\@EA\newcounter\csname #1@num\endcsname
+% \@EA\def\csname bib@#1\endcsname{\docomplexbibdef{#1}}%
+% \@EA\def\csname insert#1s\endcsname##1##2##3%
+% {\specialbibinsert{#1}{\csname #1@num\endcsname}{##1}{\unskip ##2}{##3}}}
+
+\def\complexbibdef#1%
+ {\@EA\newcounter\csname #1@num\endcsname
+ \@EA\def\csname bib@#1\endcsname{\docomplexbibdef{#1}}%
+ \expandafter \appendtoks
+ \expandafter\let\csname insert#1s\expandafter\endcsname\csname bibinsert#1s\endcsname
+ \to \initializebibdefinitions
+ \@EA\def\csname bibinsert#1s\endcsname##1##2##3{\specialbibinsert{#1}{\csname #1@num\endcsname}{##1}{\unskip ##2}{##3}}}
+
+\processcommalist[author,artauthor,editor]\complexbibdef
+
+%D Another level of indirection is needed to control the
+%D typesetting of all of these arguments.
+
+%D Btw, there is a conflict between `author' and the predefined interface
+%D variable `auteur'. The old version is overruled `auteur' is
+%D overruled by the systemconstant definition at the top of this file!
+
+\newcount\etallimitcounter
+\newcount\etaldisplaycounter
+\newcount\todocounter
+
+\def\specialbibinsert#1#2#3#4#5%
+ {\bgroup
+ \ifnum#2>\zerocount
+ \etallimitcounter =0\bibalternative{#1etallimit}\relax
+ \etaldisplaycounter=0\bibalternative{#1etaldisplay}\relax
+ \ifnum #2>\etallimitcounter
+ \todocounter\etaldisplaycounter
+ % just in case ...
+ \ifnum\todocounter>\etallimitcounter
+ \todocounter\etallimitcounter
+ \fi
+ \else
+ \todocounter#2\relax
+ \fi
+ \ifnum\todocounter>\zerocount
+ % find the current author list
+ \let\templist\empty
+ \dorecurse{#2}
+ {\toks0=\@EA\@EA\@EA{\csname @@pb@#1\recurselevel\endcsname}%
+ \ifx\templist\empty \edef\templist{\the\toks0}%
+ \else \edef\templist{\templist,\the\toks0}\fi }%
+ \doifdefinedelse
+ {\??pv data#1\c!command}
+ {\doifemptyelsevalue
+ {\??pv data#1\c!command}
+ {#3\dospecialbibinsert{#1}{\todocounter}{\templist}#4}%
+ {#3\getvalue{\??pv data#1\c!command}{#1}{\todocounter}{\templist}#4}}%
+ {#3\dospecialbibinsert{#1}{\todocounter}{\templist}#4}%
+ \else
+ #5%
+ \fi
+ \else
+ #5%
+ \fi
+ \egroup}
+
+%D This macro does the hard work of inserting a list of people in the
+%D output, with proper regard of all the inbetween strings that can
+%D arise depending on length of the list of people.
+
+%D \#1 = type
+%D \#2 = number of items to be typeset
+%D \#3 = commacommand containing authors
+
+\def\dospecialbibinsert#1#2#3%
+ {\getcommacommandsize[#3]%
+ \scratchcounter 0
+ \def\processauthoritem##1%
+ {\advance\scratchcounter1
+ \ifnum \numexpr\scratchcounter-1\relax<#2\relax
+ \getvalue{\??pv data#1}##1%
+ \ifnum \scratchcounter=#2\relax
+ \ifnum\etallimitcounter<\commalistsize\relax \bibalternative{#1etaltext}\fi
+ \else \ifnum\numexpr\scratchcounter+1 = #2\relax
+ \ifnum \commalistsize > \plustwo \bibalternative\c!finalnamesep
+ \else \bibalternative\c!lastnamesep \fi
+ \else
+ \bibalternative\c!namesep
+ \fi \fi
+ \fi}%
+ \processcommacommand[#3]\processauthoritem }
+
+%D \macros{invertedauthor,normalauthor,invertedshortauthor,normalshortauthor}
+%D
+%D Just some commands that can be used in \type{\setuppublicationparameters}
+%D If you want to write an extension to the styles, you might
+%D as well define some of these commands yourself.
+%D
+%D The argument liust has been reordered here, and the meanings
+%D are:
+%D
+%D {\obeylines\parskip0pt
+%D \type{#1} firstnames
+%D \type{#2} von
+%D \type{#3} surname
+%D \type{#4} inits
+%D \type{#5} junior
+%D }
+%D
+
+\def\normalauthor#1#2#3#4#5%
+ {\bibdoif{#1}{#1\bibalternative\c!firstnamesep}%
+ \bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
+
+\def\normalshortauthor#1#2#3#4#5%
+ {\bibdoif{#4}{#4\bibalternative\c!firstnamesep}%
+ \bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
+
+\def\invertedauthor#1#2#3#4#5%
+ {\bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!juniorsep #5}%
+ \bibdoif{#1}{\bibalternative\c!surnamesep #1\unskip}}
+
+\def\invertedshortauthor#1#2#3#4#5%
+ {\bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!juniorsep #5}%
+ \bibdoif{#4}{\bibalternative\c!surnamesep #4\unskip}}
+
+%D \macros{clearbibitem,clearbibitemtwo,bibitemdefs}
+%D
+%D These are used in \type{\typesetapublication} to do
+%D initializations and cleanups.
+
+\def\clearbibitem#1{\setvalue{\??pb @#1}{}}%
+
+\def\clearbibitemtwo#1%
+ {\letvalue{#1@num}\!!zerocount
+ \scratchcounter\plusone
+ \doloop
+ {\doifdefinedelse{\??pb @#1\the\scratchcounter}
+ {\letvalue{\??pb @#1\the\scratchcounter}\empty
+ \advance\scratchcounter\plusone}%
+ {\exitloop}}}
+
+\def\bibitemdefs#1%
+ {\@EA\let\@EA\tempa \csname bib@#1\endcsname
+ \@EA\let\csname #1\endcsname \tempa }
+
+%D \macros{startpublication}
+%D
+%D We are coming to the end of this module, to the macros that
+%D do typesetting and read the \type{bbl} file.
+
+\newcounter\bibcounter
+
+%D Just a \type{\dosingleempty} is the most friendly
+%D of doing this: there need not even be an argument
+%D to \type{\startpublication}. Of course, then there
+%D is no key either, and it had better be an
+%D article (otherwise the layout will be all screwed up).
+%D
+%D Now prohibits comments, so % can be used for urls
+
+\def\startpublication
+ {\edef\bibmodsavedpercent{\the\catcode`\%}%
+ \catcode`\%=12
+ \dosingleempty\dostartpublication}
+
+\def\stoppublication
+ {} % the \catcode of % is reset below
+
+%D Only specifying the key in the argument is also
+%D legal. In storing this stuff into macros, some trickery with
+%D token registers is needed to fix the expansion problems. Even so,
+%D this appears to not always be 100\% safe, so people are
+%D urgently advised to use \ETEX\ instead of traditional \TEX.
+%D
+%D In \ETEX, all expansion problems are conviniently solved by
+%D the primitive \type{\protected}. To put that another way:
+%D
+%D It's not a bug in this module if it does not appear in \ETEX!
+
+\long\def\dostartpublication[#1]#2\stoppublication%
+ {\increment\bibcounter
+ \bgroup
+ \doifassignmentelse{#1}%
+ {\getparameters[\??pb][k=,t=article,n=,s=,a=,y=,o=,u=,#1]}%
+ {\getparameters[\??pb][k=#1,t=article,n=,s=,a=,y=,o=,u=]}%
+ \@EA\toks\@EA2\@EA{\@@pba}%
+ \@EA\toks\@EA4\@EA{\@@pbs}%
+ \toks0={\ignorespaces #2}%
+ \setxvalue{pbdk-\@@pbk}{\@@pbk}
+ \setxvalue{pbda-\@@pbk}{\the\toks2}
+ \setxvalue{pbdy-\@@pbk}{\@@pby}
+ \setxvalue{pbds-\@@pbk}{\the\toks4}
+ \setxvalue{pbdn-\@@pbk}{\@@pbn}
+ \setxvalue{pbdt-\@@pbk}{\@@pbt}
+ \setxvalue{pbdo-\@@pbk}{\@@pbo}
+ \setxvalue{pbdu-\@@pbk}{\@@pbu}
+ \setxvalue{pbdd-\@@pbk}{\the\toks0}
+ \xdef\allrefs{\allrefs,\@@pbk}%
+ \egroup
+ \catcode`\%=\bibmodsavedpercent\relax }
+
+% intialization of the order-list:
+
+\let\allrefs\empty
+
+%D The next macro is needed because the number command of the
+%D publist sometimes needs to fetch something from the current
+%D item (like the 'short' key). For this, the ID of the current
+%D item is passed in the implict parameter \type{\@@pbk}
+
+\def\makepbkvalue#1{\def\@@pbk{#1}}
+
+\newif\ifinpublist
+
+% from Hans
+
+\def\ignoresectionconversion
+ {\let\@@sectionconversion\secondoftwoarguments}
+
+\let\normaldosetfilterlevel\dosetfilterlevel
+
+\def\patcheddosetfilterlevel#1#2% beware: this one is \let
+ {\bgroup
+ \ignoresectionconversion
+ \edef\askedlevel{#1}%
+ \edef\askedfilter{#2}%
+% \message{ASKD: \meaning\askedlevel}%
+% \message{PREV: \meaning\v!previous}%
+ \ifx\askedlevel\v!current
+ \dosetcurrentlevel\askedlevel
+ \else\ifx\askedlevel\v!previous
+ \dosetpreviouslevel\askedlevel
+ \else\ifx\askedlevel\v!all
+ \global\chardef\alltoclevels\plusone
+ \else\ifx\askedlevel\v!text
+ \global\chardef\alltoclevels\plusone
+ \else
+ \edef\byaskedlevel{\csname\??by\askedlevel\endcsname}%
+ \ifx\byaskedlevel\v!text
+ \dosettextlevel\askedlevel
+ \else
+ \dosetotherlevel\askedlevel
+ \fi
+ \fi\fi\fi\fi
+ % experiment
+ \ifx\askedfilter\empty \else
+ \xdef\currentlevel{\currentlevel\sectionseparator\askedfilter}%
+ \fi
+ \egroup}
+
+\def\filllocalpublist%
+ {\doifdefinedelse{\alltoclevels}
+ {\let\dosetfilterlevel\patcheddosetfilterlevel
+ \dosettoclevel\??li{pubs}%
+ \let\dosetfilterlevel\normaldosetfilterlevel }%
+ {\dosettoclevel\??li{pubs}}%
+ \global\let\glocalpublist\empty
+ \doloop
+ {\doifdefinedelse
+ {\r!cross cite-\jobname-\recurselevel}
+ {\doifreferencefoundelse
+ {cite-\jobname-\recurselevel}
+ {\@EA\doifreglevelelse\@EA[\currentlocationreference]
+ {\@EA\doglobal\@EA\addtocommalist\@EA
+ {\currenttextreference}\glocalpublist}{}}
+ {}}%
+ {\exitloop}}%
+ \let\localpublist\glocalpublist}
+
+\def\typesetpubslist
+ {\dobeginoflist
+% \the\initializebibdefinitions
+ \edef\askedlevel{\csname \??li pubs\c!criterium\endcsname}%
+ \ifx\askedlevel\v!all
+ \def\bibrefprefix{}%
+ \else %
+ \preparebibrefprefix
+ \fi
+ \ifsortbycite
+ \filllocalpublist
+ \iftypesetall
+ \let\localallrefs\allrefs
+ \processcommacommand[\localpublist]\typesetapublication
+ \def\removefromallrefs##1%
+ {\removefromcommalist{##1}\localallrefs }%
+ \processcommacommand[\localpublist]\removefromallrefs
+ \processcommacommand[\localallrefs]\typesetapublication
+ \else
+ \processcommacommand[\localpublist]\typesetapublication
+ \fi
+ \else
+ \iftypesetall
+ \processcommacommand[\allrefs]\typesetapublication
+ \else
+ %
+ \filllocalpublist
+ \processcommacommand[\allrefs]\maybetypesetapublication
+ \fi
+ \fi
+ \doendoflist}
+
+\newif\ifinpublist
+
+\def\maybetypesetapublication#1%
+ {\global\inpublistfalse
+ \def\test{#1}%
+ \def\runtest##1%
+ {\def\tempa{##1}\ifx \test\tempa \global\inpublisttrue \fi}%
+ \processcommacommand[\localpublist]\runtest
+ \ifinpublist \typesetapublication{#1}\fi}
+
+\def\initializepubslist
+ {\edef\@@pbnumbering{\@@pbnumbering}%
+ \ifautohang
+ \ifx\@@pbnumbering\v!short
+ \setbox\scratchbox\hbox{\@@pbnumbercommand{\getvalue{\??li pubs\c!samplesize}}}%
+ \else\iftypesetall
+ \setbox\scratchbox\hbox{\@@pbnumbercommand{\getvalue{\??li pubs\c!totalnumber}}}%
+ \else
+ \setbox\scratchbox\hbox{\@@pbnumbercommand{\numreferred}}%
+ \fi\fi
+ \edef\samplewidth{\the\wd\scratchbox}%
+ \setuplist[pubs][\c!width=\samplewidth,\c!distance=0pt]%
+ \ifx\@@pbnumbering\v!short
+ \def\@@pblimitednumber##1{\hbox to \samplewidth
+ {\@@pbnumbercommand{\getvalue{pbds-\@@pbk}}}}%
+ \else \ifx \@@pbnumbering\v!bib
+ \def\@@pblimitednumber##1{\hbox to \samplewidth
+ {\@@pbnumbercommand{\getvalue{pbdn-\@@pbk}}}}%
+ \else
+ \def\@@pblimitednumber##1{\hbox to \samplewidth{\@@pbnumbercommand{##1}}}%
+ \fi \fi
+ \else
+ \ifx\@@pbnumbering\v!short
+ \doifemptyelse
+ {\getvalue{\??li pubs\c!width}}
+ {\def\@@pblimitednumber##1{\hbox
+ {\@@pbnumbercommand{\getvalue{pbds-\@@pbk}}}}}%
+ {\def\@@pblimitednumber##1{\hbox to \getvalue{\??li pubs\c!width}%
+ {\@@pbnumbercommand{\getvalue{pbds-\@@pbk}}}}}%
+ \else \ifx \@@pbnumbering\v!bib
+ \doifemptyelse
+ {\getvalue{\??li pubs\c!width}}
+ {\def\@@pblimitednumber##1{\hbox
+ {\@@pbnumbercommand{\getvalue{pbdn-\@@pbk}}}}}%
+ {\def\@@pblimitednumber##1{\hbox to \getvalue{\??li pubs\c!width}%
+ {\@@pbnumbercommand{\getvalue{pbdn-\@@pbk}}}}}%
+ \else
+ \doifemptyelse
+ {\getvalue{\??li pubs\c!width}}
+ {\def\@@pblimitednumber##1{\hbox{\@@pbnumbercommand{##1}}}}%
+ {\def\@@pblimitednumber##1{\hbox to \getvalue{\??li pubs\c!width}{\@@pbnumbercommand{##1}}}}%
+ \fi
+ \fi
+ \fi
+ \ifx\@@pbnumbering\v!no
+ \setuplist[pubs][\c!numbercommand=,\c!symbol=\v!none,\c!textcommand=\outdented]%
+ \else
+ \setuplist[pubs][\c!numbercommand=\@@pblimitednumber]%
+ \fi
+ \doifelsevalue
+ {\??pv data\c!maybeyear}{\v!off}{\def\maybeyear##1{}}{\def\maybeyear##1{##1}}%
+ \forgetall} % bugfix 2005/03/18
+
+\def\outdented#1% move to supp-box ?
+ {\hskip -\hangindent #1}
+
+%D The full list of publications
+
+\def\completepublications
+ {\dosingleempty\docompletepublications}
+
+\def\bibdogetupsometextprefix#1#2#3%
+ {\ifcsname#2#1#3\endcsname
+ \csname#2#1#3\endcsname
+ \else\ifcsname\??la#1\c!default\endcsname
+ \@EA\ifx\csname\??la#1\c!default\endcsname\empty
+ \ifcsname#2#3\endcsname
+ \csname#2#3\endcsname
+ \else\ifcsname#2\s!en#3\endcsname
+ \csname#2\s!en#3\endcsname
+ \fi\fi
+ \else
+ \expandafter\bibdogetupsometextprefix
+ \csname\??la#1\c!default\endcsname{#2}{#3}%
+ \fi
+ \else
+ \ifcsname#2#3\endcsname
+ \csname#2#3\endcsname
+ \else\ifcsname#2\s!en#3\endcsname
+ \csname#2\s!en#3\endcsname
+ \fi\fi
+ \fi\fi}
+
+\def\docompletepublications[#1]%
+ {\begingroup
+ \setuplist[pubs][\c!criterium=\v!previous,#1]
+ \begingroup
+ \let\handletextprefix\firstoftwoarguments
+ \edef\headtextpubs{\bibdogetupsometextprefix\headlanguage\c!title{pubs}}%
+ \doifdefinedelse
+ {\??pv data\v!title}
+ {\doifemptyelsevalue
+ {\??pv data\v!title}
+ {\expanded{\systemsuppliedtitle[pubs]{\headtextpubs}}}%
+ {\expanded{\getvalue{\??pv data\v!title}{\headtextpubs}}}%
+ }%
+ {\expanded{\systemsuppliedtitle[pubs]{\headtextpubs}}}%
+ \endgroup
+ \dodoplacepublications }
+
+%D And the portion with the entries only.
+
+\def\placepublications
+ {\dosingleempty\doplacepublications}
+
+\def\doplacepublications[#1]%
+ {%\getparameters[\??pv data][#1]
+ \begingroup
+ \setuplist[pubs][\c!criterium=\v!previous,#1]%
+ \dodoplacepublications }%
+
+\def\dodoplacepublications%
+ {\initializepubslist
+ \doifelsevalue
+ {\??li pubs\c!option}{\v!continue}%
+ {}%
+ {\global\let\bibcounter\!!zerocount }%
+ \inpublisttrue
+ \typesetpubslist
+ \inpublistfalse
+ \endgroup}
+
+%D \subsubject{What's in a publication}
+
+\unexpanded\def\typesetapublication#1%
+ {\doifsomething{#1}
+ {\doglobal\increment\bibcounter
+ \bgroup
+ \the\initializebibdefinitions
+ \makepbkvalue{#1}%
+ \ifgridsnapping
+ \snaptogrid\vbox{\dodolistelement{pubs}{}{\bibcounter}%
+ {\expanded{\reference[\bibrefprefix#1]{\bibcounter}}%
+ \strut \dotypesetapublication{#1}\strut }{}{}}%
+ \else
+ \dodolistelement{pubs}{}{\bibcounter}%
+ {\expanded{\reference[\bibrefprefix#1]{\bibcounter}}%
+ \strut \dotypesetapublication{#1}\strut }{}{}%
+ \fi
+ \egroup}}
+
+\def\dotypesetapublication#1%
+ {\bgroup
+ \def\@@currentalternative{data}%
+ \processcommacommand[\bibcommandlist,crossref]\clearbibitem
+ \processcommalist [artauthor,author,editor]\clearbibitemtwo
+ \processcommacommand[\bibcommandlist]\bibitemdefs
+ \processcommalist [artauthor,author,editor,crossref]\bibitemdefs
+ \let\biblanguage\empty
+ \getvalue{pbdd-#1}%
+ \ifcsname pbdt-#1\endcsname \bibalternative{\getvalue{pbdt-#1}}\fi
+ \egroup }
+
+%D An afterthought:
+
+\def\maybeyear#1{}
+
+%D An another:
+
+\def\noopsort#1{}
+
+%D This is the result of bibtex's `language' field.
+
+\def\setbiblanguage#1#2{\setvalue{\??pb @lang@#1}{#2}}
+
+\def\lang#1%
+ {\def\biblanguage{#1}%
+ \ifcsname \??pb @lang@#1\endcsname
+ \expanded{\language[\getvalue{\??pb @lang@#1}]}%
+ \fi \ignorespaces}
+
+%D \subject{Citations}
+%D
+%D \macros{cite,bibref}
+%D
+%D The indirection with \type{\dobibref} allows \LATEX\ style
+%D \type{\cite} commands with a braced argument (these might appear
+%D in included data from the \type{.bib} file).
+
+% \unexpanded\def\cite
+% {\doifnextcharelse{[}
+% {\dodocite}
+% {\dobibref}}
+% \def\dobibref#1%
+% {\docite[#1][]}
+% \def\dodocite[#1]%
+% {\startstrictinspectnextcharacter
+% \dodoubleempty\dododocite[#1]}
+% \def\dododocite[#1][#2]{%
+% \stopstrictinspectnextcharacter
+% \docite[#1][#2]}
+
+\unexpanded\def\cite
+ {\strictdoifnextoptionalelse\dodocite\dobibref}
+
+\def\dobibref#1%
+ {\docite[#1][]}
+
+\def\dodocite[#1]%
+ {\strictdoifnextoptionalelse{\docite[#1]}{\docite[#1][]}}
+
+\def\docite[#1][#2]%
+ {\begingroup
+ \setupinteraction[\c!style=]%
+ \edef\temp{#2}%
+ \ifx\empty\temp \secondargumentfalse
+ \else \secondargumenttrue \fi
+ \ifsecondargument
+ \processcommalist[#2]\docitation
+ \doifassignmentelse
+ {#1}%
+ {\getparameters[LO][\c!alternative=,\c!extras=,#1]%
+ \edef\@@currentalternative{\LOalternative}%
+ \ifx\@@currentalternative\empty
+ \edef\@@currentalternative{\@@citedefault}%
+ \fi
+ \ifx\LOextras\empty
+ \setupcite[\@@currentalternative][#1]%
+ \else
+ \expandafter\ifx\csname LOright\endcsname \relax
+ \edef\LOextras{{\LOextras\bibalternative\c!right}}%
+ \else
+ \edef\LOextras{{\LOextras\LOright}}%
+ \fi
+ \expanded{\setupcite[\@@currentalternative][#1,\c!right=\LOextras]}%
+ \fi
+ }%
+ {\def\@@currentalternative{#1}}%
+ \expanded{%
+ \processaction[\csname @@pv\@@currentalternative \c!compress\endcsname]}
+ [ \v!yes=>\bibcitecompresstrue,
+ \v!no=>\bibcitecompressfalse,
+ \s!default=>\bibcitecompresstrue,
+ \s!unknown=>\bibcitecompresstrue]%
+ \getvalue{bib\@@currentalternative ref}[#2]%
+ \else
+ \processcommalist[#1]\docitation
+ \expanded{\processaction[\csname @@pv\@@citedefault \c!compress\endcsname]}
+ [ \v!yes=>\bibcitecompresstrue,
+ \v!no=>\bibcitecompressfalse,
+ \s!default=>\bibcitecompresstrue,
+ \s!unknown=>\bibcitecompresstrue]%
+ \edef\@@currentalternative{\@@citedefault}%
+ \getvalue{bib\@@citedefault ref}[#1]%
+ \fi
+ \endgroup}
+
+%D \macros{nocite}
+
+\def\nocite[#1]%
+ {\processcommalist[#1]\addthisref
+ \processcommalist[#1]\docitation }
+
+%D \macros{setupcite}
+
+\def\setupcite{\dodoubleempty\dosetupcite}
+
+\def\dosetupcite[#1][#2]%
+ {\ifsecondargument
+ \def\dodosetupcite##1{\getparameters[\??pv##1][#2]}%
+ \processcommalist[#1]\dodosetupcite
+ \else % default case
+ \getparameters[\??pv\@@citedefault][#1]%
+ \fi }
+
+%D Low-level stuff
+
+\def\getcitedata#1[#2]#3[#4]#5to#6%
+ {\bgroup
+ \addthisref{#4}%
+ \dofetchapublication{#4}%
+ \doifdefinedelse{@@pb@bib#2}%
+ {\xdef#6{\getvalue{@@pb@bib#2}}}%
+ {\xdef#6{\getvalue{@@pb@#2}}}%
+ \egroup}
+
+\def\dofetchapublication#1%
+ {\makepbkvalue{#1}%
+ \processcommacommand[\bibcommandlist,crossref]\clearbibitem
+ \processcommalist [artauthor,author,editor]\clearbibitemtwo
+ \processcommacommand[\bibcommandlist]\bibitemdefs
+ \processcommalist [artauthor,author,editor,crossref]\bibitemdefs
+ \getvalue{pbdd-#1}}
+
+%D This new version writes a reference out to the tui file for every
+%D \type{\cite}. This will allow backlinking.
+%D
+%D Some special care is needed so that references are not added from
+%D weird locations like in the TOC or within a \type{\setbox} command.
+
+\newcounter\citationnumber
+
+\def\docitation#1{%
+ \iftrialtypesetting \else
+ \ifdoinpututilities\else
+ \doglobal\increment\citationnumber
+ \expanded{\rawreference{}{cite-\jobname-\citationnumber}{#1}}%
+ \fi \fi }
+
+%D \macros{numreferred,doifreferredelse,addthisref,publist}
+%D
+%D The interesting command here is \type{\addthisref}, which maintains
+%D the global list of references.
+%D
+%D \type{\numreferred} is needed to do automatic calculations on
+%D the label width, and \type{\doifreferredelse} will be used
+%D to implement \type{criterium=cite}.
+
+\newcounter\numreferred
+
+\long\def\doifreferredelse#1{\doifdefinedelse{pbr-#1}}
+
+\def\addthisref#1%
+ {\doifundefinedelse{pbr-#1}
+ {\setxvalue{pbr-#1}{\citationnumber}%
+ \doglobal\increment\numreferred
+ \ifx\publist\empty \gdef\publist{#1}\else\appended\gdef\publist{,#1}\fi}
+ {\setxvalue{pbr-#1}{\getvalue{pbr-#1},\citationnumber}}}
+
+\let\publist\empty
+
+%D \macros{doifbibreferencefoundelse}
+%D
+%D Some macros to fetch the information provided by
+%D \type{\startpublication}.
+
+\def\doifbibreferencefoundelse#1%
+ {\preloadbiblist
+ \doifdefinedelse{pbdk-#1}
+ {\firstoftwoarguments}
+ {\showmessage\m!publications{5}{#1 is unknown}%
+ \secondoftwoarguments}}
+
+%D \macros{ixbibauthoryear,thebibauthors,thebibyears}
+%D
+%D If compression of \type{\cite}'s argument expansion is on,
+%D the macros that deal with authors and years call this internal
+%D command to do the actual typesetting.
+%D
+%D Two entries with same author but with different years may
+%D be condensed into ``Author (year1,year2)''. This is about the
+%D only optimization that makes sense for the (author,year)
+%D style of citations (years within one author have to be unique
+%D anyway so no need to test for that, and ``Author1, Author2 (year)''
+%D creates more confusion than it does good).
+%D
+%D In the code below,
+%D the macro \type{\thebibauthors} holds the names of the alternative
+%D author info fields for the current list. This is a commalist,
+%D and \type{\thebibyears} holds the (collection of) year(s) that go with
+%D this author (possibly as a nested commalist).
+%D
+%D There had better be an author for all cases, but there
+%D does not have to be year info always. \type{\thebibyears} is
+%D pre-initialized because this makes the insertion macros simpler.
+%D
+%D In `normal' \TeX, of course there are expansion problems again.
+
+\def\ixbibauthoryear#1#2#3#4%
+ {\bgroup
+ \gdef\ixlastcommand {#4}%
+ \gdef\ixsecondcommand{#3}%
+ \gdef\ixfirstcommand {#2}%
+ \glet\thebibauthors \empty
+ \glet\thebibyears \empty
+ \getcommalistsize[#1]%
+ \ifbibcitecompress
+ \dorecurse\commalistsize{\xdef\thebibyears{\thebibyears,}}%
+ \processcommalist[#1]\docompressbibauthoryear
+ \else
+ \processcommalist[#1]\donormalbibauthoryear
+ \fi
+ \egroup
+ \dobibauthoryear}
+
+%D \macros{dodobibauthoryear}
+%D
+%D This macro only has to make sure that the lists
+%D \type{\thebibauthors} and \type{\thebibyears} are printed.
+
+\def\dobibauthoryear
+ {\scratchcounter\zerocount
+ \getcommacommandsize[\thebibauthors]%
+ \edef\authorcount{\commalistsize}%
+ \@EA\processcommalist\@EA[\thebibauthors]\dodobibauthoryear}
+
+\def\dodobibauthoryear#1%
+ {\advance\scratchcounter\plusone
+ \edef\wantednumber{\the\scratchcounter}%
+ \getfromcommacommand[\thebibyears][\wantednumber]%
+ \@EA\def\@EA\currentbibyear\@EA{\commalistelement}%
+ \setcurrentbibauthor{#1}%
+ \ifnum\scratchcounter=\plusone
+ \ixfirstcommand
+ \else\ifnum \scratchcounter=\authorcount\relax
+ \ixlastcommand
+ \else
+ \ixsecondcommand
+ \fi\fi}
+
+\def\setcurrentbibauthor#1%
+ {\getcommacommandsize[#1]%
+ \ifcase\commalistsize
+ % anonymous?
+ \def\currentbibauthor{}%
+ \or
+ \def\currentbibauthor{#1}%
+ \or
+ \expanded{\docurrentbibauthor#1}%
+ \else
+ \handlemultiplebibauthors{\commalistsize}{#1}%
+ \fi }
+
+\newcount\citescratchcounter
+
+\def\handlemultiplebibauthors#1#2%
+ {\citescratchcounter 0
+ \def\currentbibauthor{}%
+ \def\bibprocessauthoritem##1%
+ {\advance\citescratchcounter1
+ \ifnum \citescratchcounter=#1\relax
+ \edef\currentbibauthor{\currentbibauthor##1}%
+ \else \ifnum\numexpr\citescratchcounter+1 = #1\relax
+ \edef\currentbibauthor{\currentbibauthor ##1\bibalternative{andtext}}%
+ \else
+ \edef\currentbibauthor{\currentbibauthor ##1\bibalternative{namesep}}%
+ \fi
+ \fi }%
+ \processcommalist[#2]\bibprocessauthoritem }
+
+\setupcite
+ [author,authoryear,authoryears]
+ [\c!namesep={, }]
+
+%D This discovery of authoretallimit is not the best one,
+%D but it will do for now.
+
+\def\docurrentbibauthor#1,#2%
+ {\doifemptyelse{#2}
+ {\def\currentbibauthor{#1\bibalternative{otherstext}}}
+ {\@EA
+ \ifx\csname \??pv\@@currentalternative authoretallimit\endcsname\relax
+ \edef\currentbibauthor{#1\bibalternative{andtext}#2}%
+ \else
+ \edef\currentbibauthor{#1%
+ \ifcase0\bibalternative{authoretallimit}\relax\or
+ \bibalternative{otherstext}\else\bibalternative{andtext}#2\fi}%
+ \fi}}
+
+%D This is not the one Hans made for me, because I need a global
+%D edef, and the \type{\robustdoifinsetelse} doesn't listen to
+%D \type{\doglobal }
+
+\def\robustaddtocommalist#1#2% {item} \cs
+ {\robustdoifinsetelse{#1}#2\resetglobal
+ {\dodoglobal\xdef#2{\ifx#2\empty\else#2,\fi#1}}}
+
+%D \macros{donormalbibauthoryear}
+%D
+%D Now we get to the macros that fill the two lists.
+%D The `simple' one really is quite simple.
+
+\def\donormalbibauthoryear#1%
+ {\addthisref{#1}%
+ \def\myauthor{Xxxxxxxxxx}%
+ \def\myyear{0000}%
+ \doifbibreferencefoundelse{#1}
+ {\def\myauthor{{\getvalue{pbda-#1}}}%
+ \def\myyear {\getvalue{pbdy-#1}}}%
+ {}%
+ \@EA\doglobal\@EA\appendtocommalist\@EA{\myauthor}\thebibauthors
+ \@EA\doglobal\@EA\appendtocommalist\@EA{\myyear }\thebibyears}
+
+%D \macros{docompressbibauthoryear}
+%D
+%D So much for the easy parts. Nothing at all will be done if
+%D the reference is not found or the reference does not contain
+%D author data. No questions marks o.s.s. (to be fixed later)
+
+\def\docompressbibauthoryear#1%
+ {\addthisref{#1}%
+ \def\myauthor{Xxxxxxxxxx}%
+ \def\myyear {0000}%
+ \doifbibreferencefoundelse{#1}
+ {\xdef\myauthor{\csname pbda-#1\endcsname }%
+ \xdef\myyear {\csname pbdy-#1\endcsname }}
+ {}%
+ \ifx\myauthor\empty\else
+ \checkifmyauthoralreadyexists
+ \findmatchingyear
+ \fi}
+
+%D two temporary counters. One of these two can possibly be replaced
+%D by \type{\scratchcounter}.
+
+\newcount\bibitemcounter
+\newcount\bibitemwanted
+
+%D The first portion is simple enough: if this is the very first author
+%D it is quite straightforward to add it. \type{\bibitemcounter} and
+%D \type{\bibitemwanted} are needed later to insert the year
+%D information in the correct item of \type{\thebibyears}
+
+\def\checkifmyauthoralreadyexists
+ {\doifemptyelsevalue{thebibauthors}
+ {\global\bibitemwanted \plusone
+ \global\bibitemcounter \plusone
+ \xdef\thebibauthors{{\myauthor}}}
+ {% the next weirdness is because according to \getcommalistsize,
+ % the length of \type{[{{},{}}]} is 2.
+ \@EA\getcommalistsize\@EA[\thebibauthors,]%
+ \global\bibitemcounter\commalistsize
+ \global\advance\bibitemcounter\minusone
+ \global\bibitemwanted \zerocount
+ \processcommacommand[\thebibauthors]\docomparemyauthor}}
+
+%D The outer \type{\ifnum} accomplishes the addition of
+%D a new author to \type{\thebibauthors}. The messing about with
+%D the two counters is again to make sure that \type{\thebibyears}
+%D will be updated correctly.If the author {\it was} found,
+%D the counters will stay at their present values and everything
+%D will be setup properly to insert the year info.
+
+\def\docomparemyauthor#1%
+ {\global\advance\bibitemwanted \plusone
+ \def\mytempc{#1}%
+% \message{authors: \myauthor <=>\mytempc \ifx\mytempc\myauthor :Y \else :N
+% \meaning \myauthor, \meaning\mytempc\fi (\the\bibitemwanted = \the\bibitemcounter)}%
+ \ifx\mytempc\myauthor
+ \quitcommalist
+ \else
+ \ifnum\bibitemwanted = \bibitemcounter\relax
+ \global\advance\bibitemwanted \plusone
+ \global\bibitemcounter\bibitemwanted\relax
+ \@EA\doglobal\@EA\robustaddtocommalist\@EA{{\myauthor}}\thebibauthors
+ \fi
+ \fi}
+
+%D This macro should be clear now.
+
+\def\findmatchingyear
+ {\edef\wantednumber{\the\bibitemwanted}%
+ \getfromcommacommand[\thebibyears][\wantednumber]%
+ \ifx\commalistelement\empty
+ \edef\myyear{{\myyear}}%
+ \else
+ \edef\myyear{{\commalistelement, \myyear}}%
+ \fi
+ \edef\newcommalistelement{\myyear}%
+ \doglobal\replaceincommalist \thebibyears \wantednumber}
+
+%D \macros{preparebibrefprefix}
+%D
+%D The reference list only writes bare references when the criterium
+%D is `all'. Otherwise, a prefix is added to make sure that pdfTeX
+%D does not encounter duplicate named references. On the generation
+%D side, this is not a big problem. \type{\preparebibrefprefix}
+%D creates a suitable string to prepend if a prefix is needed.
+%D
+%D Because this macro is used within \type{\cite } that itself
+%D can be used within lists like the table of contents, it needs
+%D to save and restore \type{\savedalltoclevels} and
+%D \type{\currentlevel} (\type{\dosetfilterlevel} needs to change
+%D their values globally).
+
+\def\preparebibrefprefix
+ {\chardef\savedalltoclevels \alltoclevels
+ \let\savedcurrentlevel\currentlevel
+ \let\dosetfilterlevel\patcheddosetfilterlevel
+ \dosettoclevel\??li{pubs}%
+ \edef\bibrefprefix{\@@sectiontype\currentlevel\sectionseparator}%
+ \let\dosetfilterlevel\normaldosetfilterlevel
+ \global\let\currentlevel\savedcurrentlevel
+ \global\chardef\alltoclevels \savedalltoclevels }
+
+%D \macros{preparebibreflist}
+%D
+%D But this optional prefixing is a bit of a problem on the
+%D other side. We would like to do \type{\goto{}[article-full]}
+%D but can't do it like that, because the actual label may be
+%D \type{1:2:0:3:4:article-full]} or so. The problem is solved
+%D by building a commalist that looks like this:
+%D \starttyping
+%D \def\bibreflist%
+%D {1:2:0:3:4:article-full,
+%D 1:2:0:3:article-full,
+%D 1:2:0:article-full,
+%D 1:2:article-full,
+%D 1:article-full,
+%D article-full}
+%D \stoptyping
+
+\def\preparebibreflist#1%
+ {\let\bibreflist\empty
+ \def\storeitem##1%
+ {\ifx\bibreflist\empty
+ \edef\prefix{##1\sectionseparator}%
+ \edef\bibreflist{\prefix#1,#1}%
+ \else
+ \edef\prefix{\prefix##1\sectionseparator}%
+ \edef\bibreflist{\prefix#1,\bibreflist}%
+ \fi}%
+ \expanded{\processseparatedlist[\bibrefprefix][\sectionseparator]}\storeitem }
+
+%D \macros{gotobiblink,inbiblink,atbiblink}
+%D
+%D The final task is looping over that list until a match is found.
+
+\newif\ifbibreffound
+
+\def\gotobiblink#1[#2]%
+ {\bgroup
+ \preparebibrefprefix
+ \preparebibreflist{#2}%
+ \global\bibreffoundfalse
+ \def\setuplink##1%
+ {\ifbibreffound\else
+ \doifreferencefoundelse
+ {##1}
+ {\global\bibreffoundtrue \goto{#1}[##1]}%
+ {}\fi}%
+ \processcommacommand[\bibreflist]\setuplink
+ \ifbibreffound \else \unknownreference{#2}\fi
+ \egroup }
+
+\def\atbiblink[#1]%
+ {\bgroup
+ \preparebibrefprefix
+ \preparebibreflist{#1}%
+ \global\bibreffoundfalse
+ \def\setuplink##1%
+ {\ifbibreffound\else
+ \doifreferencefoundelse
+ {##1}
+ {\global\bibreffoundtrue \at[##1]}%
+ {}\fi}%
+ \processcommacommand[\bibreflist]\setuplink
+ \ifbibreffound \else \unknownreference{#1}\fi
+ \egroup }
+
+\def\inbiblink[#1]%
+ {\bgroup
+ \preparebibrefprefix
+ \preparebibreflist{#1}%
+ \global\bibreffoundfalse
+ \def\setuplink##1%
+ {\ifbibreffound\else
+ \doifreferencefoundelse
+ {##1}
+ {\global\bibreffoundtrue \in[##1]}%
+ {}\fi}%
+ \processcommacommand[\bibreflist]\setuplink
+ \ifbibreffound \else \unknownreference{#1}\fi
+ \egroup }
+
+%D \macros{bibauthoryearref,bibauthoryearsref,bibauthorref,bibyearref}
+%D
+%D Now that all the hard work has been done, these are simple.
+%D \type{\ixbibauthoryearref} stores the data in the macros
+%D \type{\currentbibauthor} and \type{\currentbibyear}.
+
+\def\ifbibinteractionelse%
+ {\iflocation
+ \edef\test{\bibalternative\c!interaction}%
+ \ifx\test\v!stop
+ \@EA\@EA\@EA\secondoftwoarguments
+ \else
+ \@EA\@EA\@EA\firstoftwoarguments
+ \fi
+ \else
+ \@EA\secondoftwoarguments
+ \fi
+ }
+
+\def\bibmaybeinteractive#1#2%
+ {\ifbibcitecompress #2\else
+ \ifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}\fi }
+
+\def\bibauthoryearref[#1]%
+ {\ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left{\currentbibyear}\bibalternative\v!right}}
+ {\bibalternative\c!pubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left {\currentbibyear}\bibalternative\v!right}}
+ {\bibalternative\c!lastpubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left {\currentbibyear}\bibalternative\v!right}}}
+
+\def\bibauthoryearsref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}
+ {\bibalternative\c!pubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}
+ {\bibalternative\c!lastpubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}%
+ \bibalternative\v!right}
+
+\def\bibauthorref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}}}
+ {\bibalternative\c!pubsep \bibmaybeinteractive{#1}{{\currentbibauthor}}}
+ {\bibalternative\c!lastpubsep\bibmaybeinteractive{#1}{{\currentbibauthor}}}%
+ \bibalternative\v!right}
+
+\def\bibyearref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibyear}}}
+ {\bibalternative\c!pubsep \bibmaybeinteractive{#1}{{\currentbibyear}}}
+ {\bibalternative\c!lastpubsep\bibmaybeinteractive{#1}{{\currentbibyear}}}%
+ \bibalternative\v!right}
+
+%D ML problems:
+
+%D \macros{bibshortref,bibkeyref,bibpageref,bibtyperef,bibserialref}
+%D
+%D There is hardly any point in trying to compress these. The only
+%D thing that needs to be done is making sure that
+%D the separations are inserted correctly. And that is
+%D what \type{\refsep} does.
+
+\newif\iffirstref
+
+\def\refsep{\iffirstref\firstreffalse\else\bibalternative\c!pubsep\fi}
+
+\def\bibshortref[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobibshortref
+ \bibalternative\v!right}
+
+\def\dobibshortref#1%
+ {\addthisref{#1}\refsep
+ \doifbibreferencefoundelse{#1}{\gotobiblink{\getvalue{pbds-#1}}[#1]}
+ {\unknownreference{#1}}}
+
+
+\def\bibserialref[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobibserialref
+ \bibalternative\v!right}
+
+\def\dobibserialref#1%
+ {\addthisref{#1}\refsep
+ \doifbibreferencefoundelse{#1}{\gotobiblink{\getvalue{pbdn-#1}}[#1]}
+ {\unknownreference{#1}}}
+
+\def\bibkeyref[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobibkeyref
+ \bibalternative\v!right}
+
+\def\dobibkeyref#1%
+ {\addthisref{#1}\refsep\gotobiblink{#1}[#1]}
+
+\def\gotoDOI#1#2%
+ {\ifbibinteractionelse
+ {\useURL[bibfooDoi#1][#2]%
+ \useURL[bibfoo#1][http://dx.doi.org/#2]%
+ \goto{\url[bibfooDoi#1]}[url(bibfoo#1)]}
+ {\hyphenatedurl{#2}}}
+
+\def\bibdoiref[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobibdoiref
+ \bibalternative\v!right}
+
+\def\dobibdoiref#1%
+ {\addthisref{#1}\refsep
+ \doifbibreferencefoundelse{#1}{\expanded{\gotoDOI{#1}{\getvalue{pbdo-#1}}}}
+ {\unknownreference{#1}}}
+
+\def\biburlref[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobiburlref
+ \bibalternative\v!right}
+
+\def\gotoURL#1#2%
+ {\ifbibinteractionelse
+ {\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]}
+ {\hyphenatedurl{#2}}}
+
+\def\dobiburlref#1%
+ {\addthisref{#1}\refsep
+ \doifbibreferencefoundelse{#1}{\expanded{\gotoURL{#1}{\getvalue{pbdu-#1}}}}
+ {\unknownreference{#1}}}
+
+\def\bibtyperef[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobibtyperef
+ \bibalternative\v!right}
+
+\def\dobibtyperef#1%
+ {\addthisref{#1}\refsep
+ \doifbibreferencefoundelse{#1}{\gotobiblink{\getvalue{pbdt-#1}}[#1]}
+ {\unknownreference{#1}}}
+
+\def\bibpageref[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobibpageref
+ \bibalternative\v!right}
+
+\def\dobibpageref#1%
+ {\addthisref{#1}\refsep
+ \ifbibinteractionelse{\atbiblink[#1]}{{\referencingfalse\at[#1]}}}
+
+\def\bibdataref[#1]%
+ {\bibalternative\v!left
+ \firstreftrue\processcommalist[#1]\dobibdata
+ \bibalternative\v!right}
+
+\def\dobibdata#1%
+ {\addthisref{#1}\refsep
+ \doifbibreferencefoundelse{#1}{\dotypesetapublication{#1}}
+ {\unknownreference{#1}}}
+
+\let\bibnoneref\nocite
+
+%D \macros{bibnumref}
+%D
+%D It makes sense to try and compress the argument list of
+%D \type{\bibnumref}. There are two things involved: the actual
+%D compression, and a sort routine. The idea is to store the
+%D found values in a new commalist called \type{\therefs}.
+
+%D But that is not too straight-forward, because \type{\in} is
+%D not expandable,
+%D so that the macro \type{\expandrefs} is needed.
+
+\def\expandrefs#1%
+ {\bgroup
+ \preparebibrefprefix
+ \preparebibreflist{#1}%
+ \global\bibreffoundfalse
+ \def\setuplink##1%
+ {\ifbibreffound\else
+ \doifreferencefoundelse
+ {##1}
+ {\global\bibreffoundtrue
+ \@EA\doglobal\@EA\addtocommalist\@EA{\reftypet}\therefs }%
+ {}\fi}%
+ \processcommacommand[\bibreflist]\setuplink
+ \ifbibreffound \else \showmessage\m!publications{5}{#1 unknown}%
+ \doglobal\addtocommalist{0}\therefs\fi
+ \egroup }
+
+%D But at least the actual sorting code is simple (note that sorting
+%D a list with exactly one entry fails to return anything, which
+%D is why the \type{\ifx} is needed).
+
+\def\bibnumref[#1]%
+ {\bibalternative\v!left
+ \penalty\!!tenthousand
+ \processcommalist[#1]\addthisref
+ \firstreftrue
+ \ifbibcitecompress
+ \glet\therefs\empty
+ \processcommalist[#1]\expandrefs
+ \sortcommacommand[\therefs]\donumericcompare
+ \ifx\empty\sortedcommalist\else
+ \let\therefs\sortedcommalist
+ \fi
+ \compresscommacommandnrs[\therefs]%
+ \processcommacommand[\compressedlist]\verysimplebibnumref
+ \else
+ \processcommalist[#1]\dosimplebibnumref
+ \fi
+ \bibalternative\v!right}
+
+\def\dosimplebibnumref #1%
+ {\refsep\ifbibinteractionelse
+ {\inbiblink[#1]}{{\referencingfalse\inbiblink[#1]}}}
+
+\def\verysimplebibnumref#1{\doverysimplebibnumref#1}
+
+\def\doverysimplebibnumref#1#2%
+ {\refsep
+ \ifcase#1\relax \unknownreference{#1}\else
+ \def\tempa{#2}\ifx\empty\tempa#1\else#1\bibalternative\c!inbetween#2\fi
+ \fi}
+
+%D By request from Sanjoy. This makes it easier to implement
+%D \type{\citeasnoun}.
+
+\def\bibauthornumref[#1]%
+ {\getcommalistsize[#1]%
+ \global\bibitemcounter\commalistsize
+ \firstreftrue
+ \processcommalist[#1]\dobibauthornumref }
+
+\def\dobibauthornumref#1%
+ {\addthisref{#1}\refsep
+ \doifbibreferencefoundelse{#1}
+ {\getvalue{pbda-#1}%
+ \bibalternative\c!inbetween
+ \bibalternative\v!left
+ \ifbibinteractionelse{\inbiblink[#1]}
+ {{\referencingfalse\inbiblink[#1]}}%
+ \bibalternative\v!right}
+ {\unknownreference{#1}}}
+
+%D And some defaults are loaded from bibl-apa:
+
+\setuppublications
+ [\v!month\v!conversion=,
+ \c!alternative=apa]
+
+\appendtoks
+ \preloadbiblist
+\to \everystarttext
+
+\protect \endinput
diff --git a/tex/context/base/bibl-tra.mkiv b/tex/context/base/bibl-tra.mkiv
new file mode 100644
index 000000000..519af0c6f
--- /dev/null
+++ b/tex/context/base/bibl-tra.mkiv
@@ -0,0 +1,1552 @@
+%D \module
+%D [ file=bibl-tra,
+%D version=2009.08.22,
+%D title=\CONTEXT\ Publication Module,
+%D subtitle=Publications,
+%D author=Taco Hoekwater,
+%D date=\currentdate,
+%D copyright=Public Domain]
+%C
+%C Donated to the public domain.
+
+%D This module has been adapted to \MKIV\ by Hans Hagen so if things go wrong,
+%D he is to blame. The changes concern references and lists but teh rendering
+%D itself is unchanged. Future versions might provide variants as we have plans
+%D for an upgrade.
+%D
+%D We use a still somewhat experimental extension to the list
+%D mechanism. Eventually the bibtex module will use the bibl loader
+%D and access the data by means of lpath expressions. In that case we
+%D don't need to process the bibliography but still need to track
+%D usage as done here.
+%D
+%D A bit ongoing: make more local macros prefixed with bib, i.e. the bib
+%D namespace is reserved.
+
+\writestatus{loading}{ConTeXt Bibliography Support / BibTeX}
+
+\definefilesynonym[bib][obsolete]
+
+\registerctxluafile{bibl-tra}{1.001}
+
+%D The original was developed independantly by Taco Hoekwater while still working for Kluwer
+%D Academic publishers (it still used the dutch interface then). Development continued after
+%D he left Kluwer, and in Januari 2005, the then already internationalized file was merged
+%D with the core distribution by Hans Hagen. The current version is once again by Taco.
+%D
+%D More documentation and additional resources can be found on the contextgarden:
+%D \hyphenatedurl{http://wiki.contextgarden.net//Bibliography}.
+
+%D \subject{DONE (dd/mm/yyyy)}
+%D
+%D \startitemize
+%D \item add author definition (and associated system variable) (26/05/2005)
+%D \item add finalnamesep support for Oxford comma (17/09/2005)
+%D \item add \type{\insert...} for: doi, eprint, howpublished (19/09/2005)
+%D \item allow a defaulted \type{\setupcite} (19/11/2005)
+%D \item renamed citation type 'number' to 'serial' (19/11/2005)
+%D \item better definition of \type{\inverted...author} (19/11/2005)
+%D \item don't reset [numbercommand] in \type {\setuppublication} by default (20/11/2005)
+%D \item don't disable other \type {\setuppublication} keys if alternative is present (20/11/2005)
+%D \item drop \type{\sanitizeaccents} (20/11/2005)
+%D \item added \type{\nocite} and \type{\cite[none]} (21/11/2005)
+%D \item added headtext for it (23/11/2005)
+%D \item make \type{\cite[url]} and \type{\cite[doi]} interactive (23/11/2005)
+%D \item make right-aligned labels in the list work even when autohang=no
+%D \item use 'et al.' instead of 'et.al.'. Pointed out by Peter M\"unster (30/12/2005)
+%D \item added headtext for cz (31/12/2005)
+%D \item Keep whitespace after \type{\cite} with single argument (31/12/2005)
+%D \item Fix broken \type{\cite{}} support (31/12/2005)
+%D \item Use \type{\readfile} inside \type{\usepublications} instead of \type{\readsysfile} (12/01/2006)
+%D \item Use \type{\currentbibyear} and \type{\currentbibauthor} instead of \type{\YR} and \type{\AU} (05/02/2006)
+%D \item Fix compressed version of authoryear style (05/02/2006)
+%D \item Rename the clashing data fields \type{\url} and \type{\type} to \type{\biburl} and \type{\bibtype} (05/02/2006)
+%D \item Added two french bibl files from Renaud Aubin (06/02/2006)
+%D \item Five new bib class and eight extra bib fields, for IEEEtran (07/02/2006)
+%D \item French keyword translation, provided by Renaud (08/02/2006)
+%D \item fix underscores in undefined keys (22/02/2006)
+%D \item Destroy interactivity in labels of the publication list (13/03/2006)
+%D \item fix multi-cite list compression (11/4/2006)
+%D \item fix \type{\getcitedata} (11/4/2006)
+%D \item magic for chapter bibs (18-25/4/2006)
+%D \item language setting (25/4/2006)
+%D \item use \type{\hyphenatedurl} for \type{\inserturl} (25/4/2006)
+%D \item Add \type{\docitation} to \type{\nocite}(26/4/2006)
+%D \item patents can have numbers, added to bst files (26/4/2006)
+%D \item \type{\docitation} needs a \type{\iftrialtypesetting} (27/4/2006)
+%D \item \type{\filllocalpublist}'s loop is bound by definedness, not resolvedness (27/4/2006)
+%D \item \type{\setuppublications[monthconversion=]} added (15/5/2006)
+%D \item use \type{\undefinedreference} instead of bare question marks (15/5/2006)
+%D \item add grouping around \type{\placepublications} commands (16/5/2006)
+%D \item fix a bug in \type{\cite{}} (17/5/2006)
+%D \item support \type{\cite[authornum]} (18/5/2006)
+%D \item make \type{\cite} unexpandable (20/6/2006)
+%D \item allow hyperlinks in author\&year combo's
+%D (cite list compression has to be off) (20/6/2006)
+%D \item fix duplicate labels for per-chapter style (20/6/2006)
+%D \item allow \type{\setupcite[interaction=(start|stop)]}
+%D \item fix the item number in the publication list with 'numbering=yes' (22/6/2006)
+%D \item make the default criterium for \type{\placepublications} be \type{previous} (23/6/2006)
+%D \item fix \type{\normalauthor} and \type{\normalshortauthor} spacing (29/6/2006)
+%D \item do not typeset empty arguments to \type{\typesetapublication} (29/6/2006)
+%D \item add \type{symbol=none} to \type{\setuplist} in unnumbered
+%D mode to prevent typesetting of bare numbers (29/6/2006)
+%D \item remove two incorrect spaces from bibl-num.tex (1/7/2006)
+%D \item reset font styles within \type{\cite}, so that font switches
+%D in \type{left} stay in effect (12/7/2006)
+%D \item guard added against loading bbl files multiple times (13/7/2006)
+%D \item fix \type{\cite[num]} with compression is on. (14/7/2006)
+%D \item test \type{\iflocation} before deciding to use the
+%D interactive version of cite (18/7/2006)
+%D \item support \type{\setupcite[authoretallimit=1]} (18/7/2006)
+%D \item support use of \type{\cite} within titles and captions by
+%D saveguarding the list item extraction and reference placement
+%D code (19/7/2006)
+%D \item support \type{\setuppublicationlist[title=\chapter]} (4/8/2006)
+%D \item use the expansion of \type{\headtext{pubs}} (4/8/2006)
+%D \item hook added for repeated authors in publication list
+%D \type{\setuppublicationlist[artauthorcommand=\mythreeargscommand]}
+%D (4/8/2006)
+%D \item make the bracketed arguments of \type{\artauthor}, \type{\author}
+%D and \type{\editor} (bbl commands) optional (4/8/2006)
+%D \item the constants \type{sorttype}, \type{compress} and
+%D \type{autohang} have moved to the core (8/8/2006)
+%D \item bibtex is now registered as a program to be run by texexec (8/8/2006)
+%D \item fix a bug in \type{\setupcite[authoretallimit=1]} (9/8/2006)
+%D \item fix a bug inside citations that prevented lastpubsep from ever being
+%D used due to a volatile \type{\commalistsize} (25/8/2006).
+%D \item added the possibility of \type{\placepublications[option=continue]}
+%D (6/9/2006)
+%D \item Mojca translated Master's Thesis to Masterarbeit (bibl-apa-de.tex)
+%D (12/9/2006)
+%D \item Added \type{\setuppublicationlist[maybeyear=off]} by request from
+%D Thomas Schmitz (15/9/2006)
+%D \item Removed some spurious spaces pointed out by willi egger (19/9/2006)
+%D \item Add configuration of bibtex executable name (4/11/2006)
+%D \item Fix numbering=short and numbering=bib (spotted by Matthias W\"achter) (4/11/2006)
+%D \item third attempt to get a correct release (5/11/2006)
+%D \item fix a few missing dots in bibl-num.tex (7/12/2006)
+%D \item Patch for DOI's by Tobias Burnus (17/4/2007)
+%D \item Patch for \type{\insertbiburl} and \type{\insertdoi} for Tobias Burnus (18/4/2007)
+%D \item Added a missing \type{\relax} in \type{\dospecialbibinsert},
+%D that made the space before the {\it et al.} text disappear. (18/4/2007)
+%D \item Attempt to fix percent signs in bbl files. As a side-effect,
+%D this prohibits comments in \tex{startpublication} blocks! (17/4/2008)
+%D \item Patch from Matthias W\"achter that allows arbitrary .bst
+%D files to be used with \tex{setupbibtex} (25/9/2008)
+%D \item Extended for the new multilingual setups for the Oct 2008 current of ConTeXt (23/10/2008)
+%D \item Multilingual setups needed another fix (27/10/2008)
+%D \item Two fixes for bibl-apa by Michael Green (27/10/2008)
+%D \item Catalan translation of 'References' (10/11/2008)
+%D \item 'chapter' -> 'chapitre' in bibl-apa-fr (27/11/2008)
+%D \item Run bibtex via os.execute in mkiv modee (01/12/2008)
+%D \item Small correction in bibl-apa's placement of volume
+%D information in articles (05/01/2009)
+%D \item Handle multi-author (more than two) cases in \type{\cite}
+%D (02/03/2009)
+%D \item Suppress a syntax error in \type{cont-xp} mode. The output is
+%D probably not right, though (02/03/2009)
+%D \item Added a \tex{loadmarkfile} at the end, and two new files
+%D from Hans. The \type{t-bib.mkiv} is needed to make the module
+%D work with the new structure code (17/04/2009)
+%D \item Added a patch to \type{t-bib.mkiv} from Hans to make the
+%D cross referencing between multiple citations an
+%D bibliographies work (27/04/2009)
+%D \item Remove a superfluous \type{\unprotect} in t-bib.mkiv (11/05/2009).
+%D \item Patch of incollection in bibl-ams.tex from Xan (08/06/2009).
+%D \item Patch of unpublished in bibl-ams.tex from Xan (22/07/2009).
+%D \item Modified \type{\bibdogetupsometextprefix} so it works for undefined
+%D language labels, from Hans (13/08/2009).
+%D \item Adapt referencing and list insertion to \MKIV. Update some code
+%D to the latest \CONTEXT. Change some names in order to avoid conflicts
+%D with existing core names (like \type {\insertpages}).
+%D \item All constants, variables, message etc.\ are now in the core.
+%D \item Added key: \type {method} (when \type {global}, previous shown entries are
+%D not shown again, when \type {local} they are repeated).
+%D \stopitemize
+%D
+%D \subject{WISHLIST}
+%D
+%D \startitemize
+%D \item link back from publication list to citation
+%D \item export \type {\citation{}}
+%D \item support mlbibtex
+%D \item don't load the whole lot, but filter entries instead
+%D \item 9 vs 10, 19 vs 20 ... prevent extra runs when only subtle changes in wd of reference
+%D \stopitemize
+
+\unprotect
+
+\def\biblistname{pubs} % for compatibility
+
+\definelist
+ [pubs]
+
+\setuplist
+ [pubs]
+ [\c!state=\v!start,
+ \c!width=]
+
+\installstructurelistprocessor{pubs:userdata}%
+ {\ctxlua{bibtex.hacks.add(structure.lists.uservalue("\currentlist",\currentlistindex,"bibref"),\currentlistindex)}}
+
+\newcount\bibtexblock \bibtexblock\plusone
+
+%D \macros{bibdoif,bibdoifnot,bibdoifelse}
+%D
+%D Here are a few small helpers that are used a lot in all the typesetting commands
+%D (\type{\bibinsert...}) we will encounter later.
+
+\long\def\bibdoifelse#1%
+ {\@EA\def\@EA\!!stringa\@EA{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\long\def\bibdoifnot#1%
+ {\@EA\def\@EA\!!stringa\@EA{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\long\def\bibdoif#1%
+ {\@EA\def\@EA\!!stringa\@EA{#1}%
+ \ifx\!!stringa\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D Unfortunately, \BIBTEX\ is not the best configurable program
+%D around. The names of the commands it parses as well as the \type{.aux}
+%D extension to the file name are both hardwired.
+%D
+%D This means \CONTEXT\ has to write a \LATEX-style auxiliary file, yuk!
+%D The good news is that it can be rather short. We'll just ask
+%D \BIBTEX\ to output the entire database(s) into the \type{bbl} file.
+%D
+%D The \type{\bibstyle} command controls how the \type{bbl} file will
+%D be sorted. The possibilities are:
+%D
+%D \startitemize[packed]
+%D \item by author (+year, title): cont-au.bst
+%D \item by title (+author, year): cont-ti.bst
+%D \item by short key as in abbrev.bst: cont-ab.bst
+%D \item not sorted at all: cont-no.bst
+%D \stopitemize
+
+\newtoks\everysetupbibtex
+
+\unexpanded\def\setupbibtex
+ {\dosingleempty\dosetupbibtex}
+
+\def\dosetupbibtex[#1]%
+ {\let\@@pbdatabase\empty
+ \getparameters[\??pb][#1]%
+ \the\everysetupbibtex}
+
+\def\installbibtexsorter#1#2%
+ {\setvalue{\??pb:\c!sort:#1}{#2}}
+
+\installbibtexsorter\v!no {no}
+\installbibtexsorter\v!author {au}
+\installbibtexsorter\v!title {ti}
+\installbibtexsorter\v!short {ab}
+\installbibtexsorter\empty {no}
+\installbibtexsorter\s!default{no}
+
+\def\thebibtexsorter{\executeifdefined{\??pb:\c!sort:\@@pbsort}\@@pbsort}
+
+\appendtoks
+ \ifx\@@pbdatabase\empty\else
+ \doifmode{*\v!first}{\ctxlua{bibtex.hacks.process { style="\thebibtexsorter", database="\@@pbdatabase" }}}%
+ \fi
+\to \everysetupbibtex
+
+\setupbibtex
+ [\c!sorttype=\v!cite,
+ \c!sort=no]
+
+%D \macros{iftypesetall,ifbibcitecompress}
+%D
+%D The module needs some new \type{\if} statements.
+
+\newtoks\everysetuppublications
+
+\unexpanded\def\setuppublications
+ {\dosingleargument\dosetuppublications}
+
+\def\dosetuppublications[#1]%
+ {\getparameters[\??pb][\c!alternative=,#1]%
+ \doifsomething\@@pbalternative
+ {\readsysfile{bibl-\@@pbalternative.tex}
+ {\showmessage\m!publications{6}{bibl-\@@pbalternative}}
+ {\showmessage\m!publications{1}{bibl-\@@pbalternative}}%
+ \let\@@pbalternative\empty}%
+ \let\setuppublicationlayout\normalsetuppublicationlayout % overloaded in bibl-num ... vadjust needs to be done with option
+ \getparameters[\??pb][#1]% as bibl-* can have set things back
+ \the\everysetuppublications
+ \ignorespaces}
+
+%D We can omit already shown references (\v!global) or use fresh
+%D lists each time (\v!local).
+
+\chardef\bibtexoncemode\plusone % 0=disable, 1=local, 2=global
+
+\appendtoks
+ \doifelse\@@pbmethod\v!local
+ {\chardef\bibtexoncemode\plusone}%
+ {\chardef\bibtexoncemode\plustwo}%
+\to \everysetuppublications
+
+%D Cite lists are compressed, if possible. This is set later on.
+
+\newif\ifbibcitecompress\bibcitecompresstrue
+
+% \appendtoks
+% \processaction
+% [\@@pbnumbering]
+% [ \v!yes=>\let\@@pbinumbercommand\firstofoneargument,
+% \v!no=>\let\@@pbinumbercommand\gobbleoneargument,
+% \v!short=>\def\@@pbinumbercommand##1{\bibgetvars\currentpublicationkey},
+% \v!bib=>\def\@@pbinumbercommand##1{\bibgetvarn\currentpublicationkey},
+% \s!unknown=>\let\@@pbinumbercommand\firstofoneargument]%
+% \to \everysetuppublications
+
+\def\@@pbinumbercommand{\executeifdefined{\??pb:\c!numbercommand:\@@pbnumbering}\firstofoneargument}
+
+\letvalue{\??pb:\c!numbercommand:\v!yes }\firstofoneargument
+\letvalue{\??pb:\c!numbercommand:\v!no }\gobbleoneargument
+\setvalue{\??pb:\c!numbercommand:\v!short}#1{\bibgetvars\currentpublicationkey}
+\setvalue{\??pb:\c!numbercommand:\v!bib }#1{\bibgetvarn\currentpublicationkey}
+
+% to be tested
+%
+% \setvalue{\??pb:\c!numbercommand:\v!short}{\bibgetvars\currentpublicationkey\firstofoneargument}
+% \setvalue{\??pb:\c!numbercommand:\v!bib }{\bibgetvarn\currentpublicationkey\firstofoneargument}
+
+\appendtoks
+ \processaction
+ [\@@pbrefcommand]
+ [\s!default=>\edef\@@citedefault{\@@pbrefcommand},
+ \s!unknown=>\edef\@@citedefault{\@@pbrefcommand}]%
+\to \everysetuppublications
+
+\def\bibleftnumber#1{#1\hfill~}
+
+%D \macros{usepublications}
+%D
+%D After discussing it with Thomas Schmitz it became clear that using external
+%D references makes no sense as one needs to refer to it in special ways and
+%D because similar numbers can be confusing. So, for the moment this is not
+%D supported in \MKIV. (So no: see reference [3-5,9] in "some other document")
+
+\def\usepublications[#1]%
+ {\processcommalist[#1]\dousepublications}
+
+% \def\dousepublications#1%
+% {\doonlyonce{#1.\f!bibextension}
+% {\readfile{#1.\f!bibextension}
+% {\showmessage\m!publications{4}{#1.\f!bibextension}}
+% {\showmessage\m!publications{2}{#1.\f!bibextension}}}}
+
+\def\dousepublications#1%
+ {\doonlyonce{#1.\f!bibextension}{\dodousepublications{#1}}}
+
+\def\dodousepublications#1%
+ {\let\@@savedpar\par
+ \let\par\ignorespaces
+ \ifhmode\kern\zeropoint\fi
+ \readfile{#1.\f!bibextension}
+ {\showmessage\m!publications{4}{#1.\f!bibextension}}
+ {\showmessage\m!publications{2}{#1.\f!bibextension}}%
+ \ifhmode\removeunwantedspaces\fi
+ \let\par\@@savedpar}
+
+%D \macros{setuppublicationlist}
+%D
+%D This will be the first command in (\BIBTEX-generated) \type{bbl}
+%D files. `samplesize' is a sample value (in case of \BIBTEX-generated
+%D files, this will be the longest `short' key). `totalnumber'
+%D is the total number of entries that will follow in this
+%D file.
+%D
+%D Both values are only needed for the label calculation
+%D if `autohang' is `true', so by default the command is
+%D not even needed, and therefore I saw no need to give
+%D it it's own system variable and it just re-uses \type{pb}.
+
+\def\publicationlistparameter#1{\csname\??pv:l:#1\endcsname}
+
+\unexpanded\def\setuppublicationlist
+ {\dosingleempty\dosetuppublicationlist}
+
+\def\dosetuppublicationlist[#1]%
+ {\getparameters[\??pv:l:][#1]%
+ \setuplist[pubs][\c!samplesize={AA99},\c!alternative=a,\c!interaction=,\c!pagenumber=\v!no,#1,\c!command=]}
+
+\unexpanded\def\setuppublicationlayout[#1]#2%
+ {\setvalue{\??pv:l:#1}{#2}}
+
+\let\normalsetuppublicationlayout\setuppublicationlayout
+
+\setuppublicationlist[\c!title=,\c!command=\dospecialbibinsert,\c!maybeyear=\v!on]
+
+%D \macros{bibalternative}
+%D
+%D A nice little shorthand that will be used so we don't have to
+%D key in the weird \type{\@@pv} parameter names all the time.
+
+\def\bibalternative#1%
+ {\csname\??pv\@@currentalternative#1\endcsname}
+
+%D \macros{simplebibdef,bibcommandlist}
+%D
+%D \type{\simplebibdef} defines \type{bib@#1}, which in turn will
+%D use one argument that is stored in \type{@@pb@#1}.
+%D
+%D \type{\simplebibdef} also defines \type{bibinsert#1}, which can be
+%D used in the argument of \type{\setuppublicationlayout} to fetch
+%D one of the \type{@@pb@} data entries. \type{bibinsert#1} then has
+%D three arguments: \type{#1} are commands to be executed before the
+%D data, \type{#2} are commands to be executed after the data, and
+%D \type{#3} are commands to be executed if the data is not found.
+%D
+%D \type{\bibcommandlist} is the list of commands that is affected
+%D by this approach. Later on, it will be used to do a series
+%D of assignments from \type{#1} to \type{bib@#1}: e.g
+%D \type{\title} becomes \type{\bib@title} when used within
+%D a publication.
+
+\newtoks\initializebibdefinitions % we need to prevent clashes
+
+\def\simplebibdef#1% hh: funny expansion ?
+ {\@EA\long\@EA\def\csname bib@#1\endcsname##1%
+ {\setvalue{\??pb @#1}{##1}\ignorespaces}%
+ \expandafter \appendtoks
+ \expandafter\let\csname insert#1\expandafter\endcsname\csname bibinsert#1\endcsname
+ \to \initializebibdefinitions
+ \@EA\unexpanded\@EA\def\csname bibinsert#1\endcsname##1##2##3%
+ {\@EA\bibdoifelse\@EA{\csname\??pb @#1\endcsname}{##1\csname\??pb @#1\endcsname##2}{##3}}}
+
+\def\bibcommandlist
+ {abstract, annotate, arttitle, assignee, bibnumber, bibtype, biburl, chapter, city,
+ comment, country, day, dayfiled, doi, edition, eprint, howpublished, isbn, issn,
+ issue, journal, keyword, keywords, lastchecked, month, monthfiled, names, nationality,
+ note, notes, organization, pages, pubname, pubyear, revision, series, size, thekey,
+ title, volume, yearfiled}
+
+\processcommacommand[\bibcommandlist]\simplebibdef
+
+% \def\bibinsertdoi#1#2#3%
+% {\begingroup
+% \bibdoifelse{\@@pb@doi}%
+% {\edef\ascii{\detokenize\expandafter{\@@pb@doi}}% probably not ok, to less expansion
+% #1\expanded{\bibgotoDOI{\@@pb@thekey}{\ascii}}#2}{#3}%
+% \endgroup}
+%
+% \def\bibinsertbiburl#1#2#3%
+% {\begingroup
+% \bibdoifelse{\@@pb@biburl}%
+% {\edef\ascii{\detokenize\expandafter{\@@pb@biburl}}% probably not ok, to less expansion
+% #1\expanded{\bibgotoURL{\@@pb@thekey}{\ascii}}#2}{#3}%
+% \endgroup}
+
+\def\bibinsertdoi#1#2#3% let's see how this fails
+ {\bibdoifelse{\@@pb@doi}{#1\expanded{\bibgotoDOI{\@@pb@thekey}{\@@pb@doi}}#2}{#3}}
+
+\def\bibinsertbiburl#1#2#3% let's see how this fails
+ {\bibdoifelse{\@@pb@biburl}{#1\expanded{\bibgotoURL{\@@pb@thekey}{\@@pb@biburl}}#2}{#3}}
+
+\def\bibinsertmonth#1#2#3%
+ {\bibdoifelse\@@pb@month
+ {#1\doifnumberelse\@@pb@month
+ {\doifconversiondefinedelse\@@pbmonthconversion
+ {\convertnumber\@@pbmonthconversion\@@pb@month}{\@@pb@month}}%
+ {\@@pb@month}#2}%
+ {#3}}
+
+\appendtoks
+ \let\inserturl \bibinsertbiburl % for backward compat.
+ \let\inserttype\bibinsertbibtype % for backward compat.
+\to\initializebibdefinitions
+
+\def\newbibfield[#1]%
+ {\simplebibdef{#1}%
+ \edef\bibcommandlist{\bibcommandlist,#1}}
+
+%D \macros{complexbibdef,specialbibinsert}
+%D
+%D The commands \type{\artauthor}, \type{\author} and
+%D \type{\editor} are more complex than the other commands.
+%D Their argument lists have this form:
+%D
+%D \type{\author[junior]{firstnames}[inits]{von}{surname}}
+%D
+%D (bracketed stuff is optional)
+%D
+%D And not only that, but there also might be more than one of each of
+%D these commands. This is why a special command is needed to insert
+%D them, as well as one extra counter for each command.
+
+% todo: instead of \getvalue{bla@num} in specs we should do
+% \bibentrynum{bla} so that we can create a better namespace
+
+%D All of these \type{\@EA}'s and \type{\csnames} make this code
+%D look far more complex than it really is. For example, the argument
+%D \type{author} defines the macro \type{\bib@author} to do two
+%D things: increment the counter \type{\author@num} (let's say to 2)
+%D and next store it's arguments in the macro \type{\@@pb@author2}.
+%D And it defines \type{\bibinsertauthors} to expand into
+%D \starttyping
+%D \specialbibinsert{author}{\author@num}{}{}{}
+%D \stoptyping
+
+% \def\docomplexbibdef#1%
+% {\def\currentype{#1}%
+% \dosingleempty\dodocomplexbibdef}
+
+% \def\dodocomplexbibdef[#1]#2%
+% {\def\firstarg{#1}\def\secondarg{#2}%
+% \dosingleempty\dododocomplexbibdef}
+
+% \def\dododocomplexbibdef[#1]#2#3%
+% {\@EA\increment\csname\currentype @num\endcsname
+% \setevalue{\??pb @\currentype\csname \currentype @num\endcsname}%
+% {{\secondarg}{#2}{#3}{#1}{\firstarg}}\ignorespaces}
+
+\def\docomplexbibdef#1%
+ {\dodoubleempty\dodocomplexbibdef[#1]}
+
+\def\dodocomplexbibdef[#1][#2]#3%
+ {\doquadrupleempty\dododocomplexbibdef[#1][#2][#3]}
+
+\def\dododocomplexbibdef[#1][#2][#3][#4]#5#6%
+ {\@EA\increment\csname#1@num\endcsname % todo: bib in name
+ \setevalue{\??pb @#1\csname#1@num\endcsname}{{#3}{#5}{#6}{#4}{#2}}\ignorespaces}
+
+\def\complexbibdef#1%
+ {\@EA\newcounter\csname #1@num\endcsname
+ \@EA\def\csname bib@#1\endcsname{\docomplexbibdef{#1}}%
+ \expandafter \appendtoks
+ \expandafter\let\csname insert#1s\expandafter\endcsname\csname bibinsert#1s\endcsname
+ \to \initializebibdefinitions
+ \@EA\def\csname bibinsert#1s\endcsname##1##2##3{\specialbibinsert{#1}{\csname #1@num\endcsname}{##1}{\unskip ##2}{##3}}}
+
+\processcommalist[author,artauthor,editor]\complexbibdef
+
+%D Another level of indirection is needed to control the
+%D typesetting of all of these arguments.
+
+\newcount\etallimitcounter
+\newcount\etaldisplaycounter
+\newcount\todocounter
+
+\def\specialbibinsert#1#2#3#4#5%
+ {\bgroup
+ \ifnum#2>\zerocount
+ \etallimitcounter =0\bibalternative{#1etallimit}\relax
+ \etaldisplaycounter=0\bibalternative{#1etaldisplay}\relax
+ \ifnum #2>\etallimitcounter
+ \todocounter\etaldisplaycounter
+ % just in case ...
+ \ifnum\todocounter>\etallimitcounter
+ \todocounter\etallimitcounter
+ \fi
+ \else
+ \todocounter#2\relax
+ \fi
+ \ifnum\todocounter>\zerocount
+ % find the current author list
+ \let\templist\empty
+ \dorecurse{#2}
+ {\scratchtoks\@EA\@EA\@EA{\csname\??pb @#1\recurselevel\endcsname}%
+ \edef\templist{\ifx\templist\empty\else\templist,\fi\the\scratchtoks}}%
+ #3\publicationlistparameter\c!command{#1}{\todocounter}{\templist}#4\relax
+ \else
+ #5%
+ \fi
+ \else
+ #5%
+ \fi
+ \egroup}
+
+%D This macro does the hard work of inserting a list of people in the
+%D output, with proper regard of all the inbetween strings that can
+%D arise depending on length of the list of people.
+
+%D \#1 = type
+%D \#2 = number of items to be typeset
+%D \#3 = commacommand containing authors
+
+% \def\dospecialbibinsert#1#2#3%
+% {\getcommacommandsize[#3]%
+% \scratchcounter\zerocount
+% \def\processauthoritem##1%
+% {\advance\scratchcounter\plusone
+% \ifnum\numexpr\scratchcounter-\plusone\relax<#2\relax
+% \publicationlistparameter{#1}##1%
+% \ifnum\scratchcounter=#2\relax
+% \ifnum\etallimitcounter<\commalistsize\relax
+% \bibalternative{#1etaltext}%
+% \fi
+% \else\ifnum\numexpr\scratchcounter+\plusone\relax=#2\relax
+% \ifnum\commalistsize>\plustwo
+% \bibalternative\c!finalnamesep
+% \else
+% \bibalternative\c!lastnamesep
+% \fi
+% \else
+% \bibalternative\c!namesep
+% \fi\fi
+% \fi}%
+% \processcommacommand[#3]\processauthoritem}
+
+\def\doprocessauthoritem#1#2#3%
+ {\advance\scratchcounter\plusone
+ \ifnum\numexpr\scratchcounter-\plusone\relax<#2\relax
+ \publicationlistparameter{#1}#3%
+ \ifnum\scratchcounter=#2\relax
+ \ifnum\etallimitcounter<\commalistsize\relax
+ \bibalternative{#1etaltext}%
+ \fi
+ \else\ifnum\numexpr\scratchcounter+\plusone\relax=#2\relax
+ \ifnum\commalistsize>\plustwo
+ \bibalternative\c!finalnamesep
+ \else
+ \bibalternative\c!lastnamesep
+ \fi
+ \else
+ \bibalternative\c!namesep
+ \fi\fi
+ \fi}
+
+\def\dospecialbibinsert#1#2#3%
+ {\getcommacommandsize[#3]%
+ \scratchcounter\zerocount
+ \processcommacommand[#3]{\doprocessauthoritem{#1}{#2}}}
+
+%D \macros{invertedauthor,normalauthor,invertedshortauthor,normalshortauthor}
+%D
+%D Just some commands that can be used in \type{\setuppublicationparameters}
+%D If you want to write an extension to the styles, you might
+%D as well define some of these commands yourself.
+%D
+%D The argument list has been reordered here, and the meanings
+%D are:
+%D
+%D \startlines
+%D \type{#1} firstnames
+%D \type{#2} von
+%D \type{#3} surname
+%D \type{#4} inits
+%D \type{#5} junior
+%D \stoplines
+
+\def\normalauthor#1#2#3#4#5%
+ {\bibdoif{#1}{#1\bibalternative\c!firstnamesep}%
+ \bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
+
+\def\normalshortauthor#1#2#3#4#5%
+ {\bibdoif{#4}{#4\bibalternative\c!firstnamesep}%
+ \bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
+
+\def\invertedauthor#1#2#3#4#5%
+ {\bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!juniorsep#5}%
+ \bibdoif{#1}{\bibalternative\c!surnamesep#1\unskip}}
+
+\def\invertedshortauthor#1#2#3#4#5%
+ {\bibdoif{#2}{#2\bibalternative\c!vonsep}%
+ #3%
+ \bibdoif{#5}{\bibalternative\c!juniorsep#5}%
+ \bibdoif{#4}{\bibalternative\c!surnamesep#4\unskip}}
+
+%D \macros{clearbibitem,clearbibitemtwo,bibitemdefs}
+%D
+%D These are used in \type{\typesetapublication} to do
+%D initializations and cleanups.
+
+\def\clearbibitem#1{\setvalue{\??pb @#1}{}}%
+
+% \def\clearbibitemtwo#1%
+% {\letvalue{#1@num}\!!zerocount
+% \doloop
+% {\doifdefinedelse{\??pb @#1\recurselevel}
+% {\letvalue{\??pb @#1\recurselevel}\empty} % why not undefined?
+% {\exitloop}}}
+
+% \def\clearbibitemtwo#1%
+% {\letvalue{#1@num}\!!zerocount
+% \doloop
+% {\ifcsname\??pb @#1\recurselevel\endcsname
+% \expandafter\let\csname\??pb @#1\recurselevel\undefined
+% \else
+% \exitloop
+% \fi}}
+
+\def\clearbibitemtwo#1% is this reset really needed? after all we reset the counter and we are local
+ {%\dofastrecurse\plusone{\csname#1@num\endcsname}\plusone{\expandafter\let\csname\??pb @#1\recurselevel\undefined}%
+ \letvalue{#1@num}\!!zerocount}
+
+\def\bibitemdefs#1%
+ {\@EA\let\csname#1\expandafter\endcsname\csname bib@#1\endcsname}
+
+\def\presetbibvariables % make a fast resetter (toks)
+ {\processcommacommand[\bibcommandlist,crossref]\clearbibitem
+ \processcommalist [artauthor,author,editor]\clearbibitemtwo
+ \processcommacommand[\bibcommandlist]\bibitemdefs
+ \processcommalist [artauthor,author,editor,crossref]\bibitemdefs}
+
+%D \macros{startpublication}
+%D
+%D We are coming to the end of this module, to the macros that
+%D do typesetting and read the \type{bbl} file.
+
+\newcount\bibtexcounter
+
+%D Just a \type{\dosingleempty} is the most friendly
+%D of doing this: there need not even be an argument
+%D to \type{\startpublication}. Of course, then there
+%D is no key either, and it had better be an
+%D article (otherwise the layout will be all screwed up).
+%D
+%D Only specifying the key in the argument is also
+%D legal. In storing this stuff into macros, some trickery with
+%D token registers is needed to fix the expansion problems. Even so,
+%D this appears to not always be 100\% safe, so people are
+%D urgently advised to use \ETEX\ instead of traditional \TEX.
+%D
+%D In \ETEX, all expansion problems are conveniently solved by
+%D the primitive \type{\protected}. To put that another way:
+%D
+%D It's not a bug in this module if it does not appear in \ETEX!
+%D
+%D Now prohibits comments, so % can be used for urls
+
+\unexpanded\def\startpublication
+ {\begingroup
+ \catcode`\%=\othercatcode
+ \dosingleempty\dostartpublication}
+
+\let\stoppublication\relax
+
+% this is rather memory hungry; some day i will rewrite this so that
+% we use the database instead
+
+%D \macros{doifbibreferencefoundelse}
+%D
+%D Some macros to fetch the information provided by
+%D \type{\startpublication}.
+
+% we can consider a faster variant in the bbl file; we can also consider
+% storing the keys in lua (and then do more in lua) and use calls to
+% fetch the variables
+
+% hm, we can store at the lua end ...
+
+\long\def\dostartpublication[#1]#2\stoppublication
+ {\doifassignmentelse{#1}%
+ {\getparameters[\??pb][k=\s!unknown,t=article,n=,s=,a=,y=,o=,u=,#1]}%
+ {\getparameters[\??pb][k=#1,t=article,n=,s=,a=,y=,o=,u=]}%
+ \ctxlua{bibtex.hacks.register("\@@pbk")}%
+ \setxvalue{pbd:\@@pbk}##1{\noexpand\ifcase##1\noexpand\or
+ \@@pbk\noexpand\or
+ \@@pba\noexpand\or
+ \@@pby\noexpand\or
+ \@@pbs\noexpand\or
+ \@@pbn\noexpand\or
+ \@@pbt\noexpand\or
+ \@@pbo\noexpand\or
+ \@@pbu\noexpand\or
+ \normalunexpanded{#2}\noexpand\fi}%
+ \endgroup
+ \ignorespaces}
+
+\def\bibgetvark#1{\csname pbd:#1\endcsname\plusone }
+\def\bibgetvara#1{\csname pbd:#1\endcsname\plustwo }
+\def\bibgetvary#1{\csname pbd:#1\endcsname\plusthree}
+\def\bibgetvars#1{\csname pbd:#1\endcsname\plusfour }
+\def\bibgetvarn#1{\csname pbd:#1\endcsname\plusfive }
+\def\bibgetvart#1{\csname pbd:#1\endcsname\plussix }
+\def\bibgetvaro#1{\csname pbd:#1\endcsname\plusseven}
+\def\bibgetvaru#1{\csname pbd:#1\endcsname\pluseight}
+\def\bibgetvard#1{\csname pbd:#1\endcsname\plusnine }
+
+\def\doifbibreferencefoundelse#1%
+ {\preloadbiblist
+ \doifdefinedelse{pbd:#1}
+ \firstoftwoarguments
+ {\showmessage\m!publications{5}{#1 is unknown}\secondoftwoarguments}}
+
+%D \macros{bib@crossref}
+%D
+%D \type{\crossref} is used in database files to point to another
+%D entry. Because of this special situation, it has to be defined
+%D separately. Since this command will not be seen until at
+%D \type{\placepublications}, it may force extra runs. The same is
+%D true for \type{\cite} commands inside of publications.
+
+% used in bib self
+
+\def\bib@crossref#1% called via \csname \endcsname
+ {\setvalue{\??pb @crossref}{#1}\ignorespaces}
+
+\def\bibinsertcrossref#1#2#3%
+ {\bibdoifelse\@@pb@crossref{#1\cite[\@@pb@crossref]#2}{#3}}
+
+\appendtoks\let\insertcrossref\bibinsertcrossref\to\initializebibdefinitions
+
+%D The next macro is needed because the number command of the
+%D publist sometimes needs to fetch something from the current
+%D item (like the 'short' key). For this, the ID of the current
+%D item is passed in the implict parameter \type{\currentpublicationkey}
+
+\def\doprocessbibtexentry#1{\typesetapublication{#1}}
+
+\def\typesetpubslist
+ {\dobeginoflist
+ % \the\initializebibdefinitions % COMMENTED
+ \edef\currentlist{pubs}%
+ \doif{\listparameter\c!criterium}\v!cite{\setuplist[pubs][\c!criterium=\v!here]}%
+ \ctxlua{bibtex.hacks.reset(\number\bibtexoncemode)}%
+ \placestructurelist{pubs}{\listparameter\c!criterium}{\listparameter\c!number}%
+ \ctxlua{bibtex.hacks.flush("\@@pbsorttype")}%
+ \doendoflist}
+
+\newif\ifinpublist
+
+\def\initializepubslist
+ {\def\currentlist{pubs}%
+ \edef\@@pbnumbering{\@@pbnumbering}%
+ \doifelse\@@pbautohang\v!yes
+ {\ifx\@@pbnumbering\v!short
+ \setbox\scratchbox\hbox{\@@pbnumbercommand{\listparameter\c!samplesize}}%
+ \else
+ \setbox\scratchbox\hbox{\@@pbnumbercommand{\ctxlua{tex.write(structure.lists.size())}}}%
+ \fi
+ \edef\publistnumberbox{\hbox to \the\wd\scratchbox}%
+ \expanded{\setuplist[pubs][\c!width=\the\wd\scratchbox,\c!distance=\zeropoint]}%
+ \ifx\@@pbnumbering\v!short
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvars\currentpublicationkey}}}%
+ \else\ifx\@@pbnumbering\v!bib
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvarn\currentpublicationkey}}}%
+ \else
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{##1}}}%
+ \fi\fi}
+ {\doifelsenothing{\listparameter\c!width}
+ {\let \publistnumberbox \hbox}
+ {\edef\publistnumberbox{\hbox to \listparameter\c!width}}%
+ \ifx\@@pbnumbering\v!short
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvars\currentpublicationkey}}}%
+ \else\ifx\@@pbnumbering\v!bib
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{\bibgetvarn\currentpublicationkey}}}%
+ \else
+ \def\@@pblimitednumber##1{\publistnumberbox{\@@pbnumbercommand{##1}}}%
+ \fi\fi}%
+ \ifx\@@pbnumbering\v!no
+ \setuplist[pubs][\c!numbercommand=,\c!symbol=\v!none,\c!textcommand=\outdented]%
+ \else
+ \setuplist[pubs][\c!numbercommand=\@@pblimitednumber]%
+ \fi
+ \doifelse{\publicationlistparameter\c!maybeyear}{\v!off}{\def\maybeyear##1{}}{\def\maybeyear##1{##1}}%
+ \forgetall}
+
+\def\outdented#1% move to supp-box ?
+ {\hskip-\hangindent#1\relax}
+
+%D The full list of publications
+
+\def\completepublications
+ {\dosingleempty\docompletepublications}
+
+\def\docompletepublications[#1]%
+ {\begingroup
+ \setuplist[pubs][\c!criterium=\v!previous,#1]
+ \doifelsenothing{\publicationlistparameter\c!title}
+ {\systemsuppliedchapter[pubs]{\headtext{pubs}}}
+ {\normalexpanded{\systemsuppliedchapter[pubs]{\publicationlistparameter\c!title}}}%
+ \dodoplacepublications}
+
+%D And the portion with the entries only.
+
+\def\bibrefprefix{\number\bibtexblock:}
+
+\unexpanded\def\placepublications
+ {\dosingleempty\doplacepublications}
+
+\def\doplacepublications[#1]%
+ {\begingroup
+ \setuplist[pubs][\c!criterium=\v!previous,#1]%
+ \dodoplacepublications}
+
+\def\dodoplacepublications
+ {\determinelistcharacteristics[pubs]%
+ \initializepubslist
+ \doifnot{\namedlistparameter{pubs}\c!option}\v!continue
+ {\global\bibtexcounter\zerocount}%
+ \inpublisttrue
+ \typesetpubslist
+ \inpublistfalse
+ \endgroup
+ \global\advance\bibtexblock\plusone}
+
+%D \subsubject{What's in a publication}
+
+\unexpanded\def\typesetapublication#1%
+ {\doifsomething{#1}
+ {\doifelse{\namedlistparameter{pubs}\c!criterium}\v!all
+ {\doplacepublicationindeed{#1}}%
+ {\ctxlua{bibtex.hacks.doifalreadyplaced("#1")}
+ {}
+ {\doplacepublicationindeed{#1}}}%
+ }}
+
+% for the moment we don't access the data directly but we will do that
+% later when we get away from storing the data and only deal with
+% references
+
+% we'll define proper handlers later
+
+\def\doplacepublicationindeed#1%
+ {\doifbibreferencefoundelse{#1}
+ {\global\advance\bibtexcounter\plusone
+ \def\currentpublicationkey{#1}%
+ \ctxlua{bibtex.hacks.registerplaced("#1")}%
+ \dodolistelement
+ {pubs}%
+ {}%
+ {\number\bibtexcounter}%
+ {\expanded{\reference[\bibrefprefix#1]{\number\bibtexcounter}}%
+ \strut\dotypesetapublication{#1}\strut}%
+ {}%
+ {}}
+ {}} % invalid
+
+\def\dotypesetapublication#1%
+ {\bgroup
+ \the\initializebibdefinitions % NEW
+ \def\@@currentalternative{:l:}%
+ \presetbibvariables
+ \let\biblanguage\empty
+ \ignorespaces
+ \bibgetvard{#1}%
+ \removeunwantedspaces
+ \ignorespaces
+ \bibalternative{\bibgetvart{#1}}%
+ \removeunwantedspaces
+ \egroup}
+
+%D An few afterthoughts:
+
+\let\maybeyear\gobbleoneargument
+\let\noopsort \gobbleoneargument
+
+%D This is the result of bibtex's `language' field.
+
+\def\setbiblanguage#1#2{\setvalue{\??pb\s!language#1}{#2}}
+
+\def\lang#1%
+ {\edef\biblanguage{#1}%
+ \ifcsname\??pb\s!language#1\endcsname
+ \language[\getvalue{\??pb\s!language#1}]%
+ \fi
+ \ignorespaces}
+
+%D \subject{Citations}
+
+%D \macros{cite,bibref}
+%D
+%D The indirection with \type{\dobibref} allows \LATEX\ style
+%D \type{\cite} commands with a braced argument (these might appear
+%D in included data from the \type{.bib} file).
+
+% \unexpanded\def\cite
+% {\doifnextoptionalelse\dodocite\dobibref}
+% \def\dobibref#1%
+% {\docite[#1][]}
+% \def\dodocite[#1]%
+% {\startstrictinspectnextcharacter
+% \dodoubleempty\dododocite[#1]}
+% \def\dododocite % [#1][#2]
+% {\stopstrictinspectnextcharacter
+% \docite}
+
+\unexpanded\def\cite
+ {\strictdoifnextoptionalelse\dodocite\dobibref}
+
+\def\dobibref#1%
+ {\docite[#1][]}
+
+\def\dodocite[#1]%
+ {\strictdoifnextoptionalelse{\docite[#1]}{\docite[#1][]}}
+
+\def\docite[#1][#2]%
+ {\begingroup
+ \doifelsenothing{#2}\secondargumentfalse\secondargumenttrue
+ \ifsecondargument
+ \dowhatevercite{#1}{#2}%
+ \else
+ \donumberedcite{#1}%
+ \fi
+ \endgroup}
+
+\def\dowhatevercite#1#2%
+ {\processcommalist[#2]\docitation
+ \setupinteraction[\c!style=]%
+ \doifassignmentelse
+ {#1}%
+ {\getparameters[LO][\c!alternative=,\c!extras=,#1]%
+ \edef\@@currentalternative{\LOalternative}%
+ \ifx\@@currentalternative\empty
+ \edef\@@currentalternative{\@@citedefault}%
+ \fi
+ \ifx\LOextras\empty
+ \setupcite[\@@currentalternative][#1]%
+ \else
+ \expandafter\ifx\csname LOright\endcsname \relax
+ \edef\LOextras{{\LOextras\bibalternative\c!right}}%
+ \else
+ \edef\LOextras{{\LOextras\LOright}}%
+ \fi
+ \expanded{\setupcite[\@@currentalternative][#1,\c!right=\LOextras]}%
+ \fi}%
+ {\def\@@currentalternative{#1}}%
+ \doifelsevalue{@@pv\@@currentalternative\c!compress}\v!no\bibcitecompressfalse\bibcitecompresstrue
+ \getvalue{bib\@@currentalternative ref}[#2]}
+
+\def\donumberedcite#1%
+ {\processcommalist[#1]\docitation
+ \setupinteraction[\c!style=]%
+ \edef\@@currentalternative{\@@citedefault}%
+ \doifelsevalue{@@pv\@@currentalternative\c!compress}\v!no\bibcitecompressfalse\bibcitecompresstrue
+ \getvalue{bib\@@citedefault ref}[#1]}
+
+%D \macros{nocite}
+
+\def\nocite[#1]%
+ {\processcommalist[#1]\docitation}
+
+%D \macros{setupcite}
+
+\unexpanded\def\setupcite{\dodoubleempty\dosetupcite}
+
+\def\dosetupcite[#1][#2]%
+ {\ifsecondargument
+ \def\dodosetupcite##1{\getparameters[\??pv##1][#2]}%
+ \processcommalist[#1]\dodosetupcite
+ \else % default case
+ \getparameters[\??pv\@@citedefault][#1]%
+ \fi}
+
+%D Low-level stuff
+
+\def\getcitedata#1[#2]#3[#4]#5to#6%
+ {\bgroup
+ \dofetchapublication{#4}%
+ \doifdefinedelse{\??pb @bib#2}%
+ {\xdef#6{\getvalue{\??pb @bib#2}}}%
+ {\xdef#6{\getvalue{\??pb @#2}}}%
+ \egroup}
+
+\def\dofetchapublication#1%
+ {\def\currentpublicationkey{#1}%
+ \presetbibvariables
+ \ignorespaces\bibgetvard{#1}}
+
+\def\docitation#1%
+ {\iftrialtypesetting \else
+ \expanded{\writedatatolist[pubs][bibref=#1]}%
+ \fi}
+
+\let\addthisref\gobbleoneargument % keep this for compatibility
+
+%D \macros{ixbibauthoryear,thebibauthors,thebibyears}
+%D
+%D If compression of \type{\cite}'s argument expansion is on,
+%D the macros that deal with authors and years call this internal
+%D command to do the actual typesetting.
+%D
+%D Two entries with same author but with different years may
+%D be condensed into ``Author (year1,year2)''. This is about the
+%D only optimization that makes sense for the (author,year)
+%D style of citations (years within one author have to be unique
+%D anyway so no need to test for that, and ``Author1, Author2 (year)''
+%D creates more confusion than it does good).
+%D
+%D In the code below,
+%D the macro \type{\thebibauthors} holds the names of the alternative
+%D author info fields for the current list. This is a commalist,
+%D and \type{\thebibyears} holds the (collection of) year(s) that go with
+%D this author (possibly as a nested commalist).
+%D
+%D There had better be an author for all cases, but there
+%D does not have to be year info always. \type{\thebibyears} is
+%D pre-initialized because this makes the insertion macros simpler.
+%D
+%D In `normal' \TeX, of course there are expansion problems again.
+
+\def\ixbibauthoryear#1#2#3#4%
+ {\bgroup
+ \gdef\ixlastcommand {#4}%
+ \gdef\ixsecondcommand{#3}%
+ \gdef\ixfirstcommand {#2}%
+ \glet\thebibauthors \empty
+ \glet\thebibyears \empty
+ \getcommalistsize[#1]%
+ \ifbibcitecompress
+ \dorecurse\commalistsize{\xdef\thebibyears{\thebibyears,}}%
+ \processcommalist[#1]\docompressbibauthoryear
+ \else
+ \processcommalist[#1]\donormalbibauthoryear
+ \fi
+ \egroup
+ \dobibauthoryear}
+
+%D \macros{dodobibauthoryear}
+%D
+%D This macro only has to make sure that the lists
+%D \type{\thebibauthors} and \type{\thebibyears} are printed.
+
+\def\dobibauthoryear
+ {\scratchcounter\zerocount
+ \getcommacommandsize[\thebibauthors]%
+ \edef\authorcount{\commalistsize}%
+ \@EA\processcommalist\@EA[\thebibauthors]\dodobibauthoryear}
+
+\def\dodobibauthoryear#1%
+ {\advance\scratchcounter\plusone
+ \edef\wantednumber{\the\scratchcounter}%
+ \getfromcommacommand[\thebibyears][\wantednumber]%
+ \@EA\def\@EA\currentbibyear\@EA{\commalistelement}%
+ \setcurrentbibauthor{#1}%
+ \ifnum\scratchcounter=\plusone
+ \ixfirstcommand
+ \else\ifnum \scratchcounter=\authorcount\relax
+ \ixlastcommand
+ \else
+ \ixsecondcommand
+ \fi\fi}
+
+\def\setcurrentbibauthor#1%
+ {\getcommacommandsize[#1]%
+ \ifcase\commalistsize
+ % anonymous?
+ \let\currentbibauthor\empty
+ \or
+ \def\currentbibauthor{#1}%
+ \or
+ \expanded{\docurrentbibauthor#1}%
+ \else
+ \handlemultiplebibauthors{\commalistsize}{#1}%
+ \fi}
+
+\newcount\citescratchcounter
+
+\def\handlemultiplebibauthors#1#2%
+ {\citescratchcounter\zerocount
+ \let\currentbibauthor\empty
+ \def\bibprocessauthoritem##1%
+ {\advance\citescratchcounter\plusone
+ \ifnum \citescratchcounter=#1\relax
+ \edef\currentbibauthor{\currentbibauthor##1}%
+ \else\ifnum\numexpr\citescratchcounter+\plusone\relax=#1\relax
+ \edef\currentbibauthor{\currentbibauthor##1\bibalternative{andtext}}%
+ \else
+ \edef\currentbibauthor{\currentbibauthor##1\bibalternative{namesep}}%
+ \fi\fi}%
+ \processcommalist[#2]\bibprocessauthoritem}
+
+\setupcite
+ [author,authoryear,authoryears]
+ [\c!namesep={, }]
+
+%D This discovery of authoretallimit is not the best one,
+%D but it will do for now.
+
+\def\docurrentbibauthor#1,#2%
+ {\doifemptyelse{#2}
+ {\def\currentbibauthor{#1\bibalternative{otherstext}}}
+ {\@EA\ifx\csname\??pv\@@currentalternative authoretallimit\endcsname\relax
+ \edef\currentbibauthor{#1\bibalternative{andtext}#2}%
+ \else
+ \edef\currentbibauthor{#1%
+ \ifcase0\bibalternative{authoretallimit}\relax\or
+ \bibalternative{otherstext}\else\bibalternative{andtext}#2\fi}%
+ \fi}}
+
+%D This is not the one Hans made for me, because I need a global
+%D edef, and the \type{\robustdoifinsetelse} doesn't listen to
+%D \type{\doglobal }
+
+\def\robustaddtocommalist#1#2% {item} \cs
+ {\robustdoifinsetelse{#1}#2\resetglobal
+ {\dodoglobal\xdef#2{\ifx#2\empty\else#2,\fi#1}}}
+
+%D \macros{donormalbibauthoryear}
+%D
+%D Now we get to the macros that fill the two lists.
+%D The `simple' one really is quite simple.
+
+\def\donormalbibauthoryear#1%
+ {\def\myauthor{Xxxxxxxxxx}%
+ \def\myyear{0000}%
+ \doifbibreferencefoundelse{#1}
+ {\def\myauthor{{\bibgetvara{#1}}}%
+ \def\myyear {\bibgetvary{#1}}}%
+ {}%
+ \@EA\doglobal\@EA\appendtocommalist\@EA{\myauthor}\thebibauthors
+ \@EA\doglobal\@EA\appendtocommalist\@EA{\myyear }\thebibyears}
+
+%D \macros{docompressbibauthoryear}
+%D
+%D So much for the easy parts. Nothing at all will be done if
+%D the reference is not found or the reference does not contain
+%D author data. No questions marks o.s.s. (to be fixed later)
+
+\def\docompressbibauthoryear#1%
+ {\def\myauthor{Xxxxxxxxxx}%
+ \def\myyear {0000}%
+ \doifbibreferencefoundelse{#1}
+ {\xdef\myauthor{\bibgetvara{#1}}%
+ \xdef\myyear {\bibgetvary{#1}}}
+ {}%
+ \ifx\myauthor\empty\else
+ \checkifmyauthoralreadyexists
+ \findmatchingyear
+ \fi}
+
+%D two temporary counters. One of these two can possibly be replaced
+%D by \type{\scratchcounter}.
+
+\newcount\bibitemcounter
+\newcount\bibitemwanted
+
+%D The first portion is simple enough: if this is the very first author
+%D it is quite straightforward to add it. \type{\bibitemcounter} and
+%D \type{\bibitemwanted} are needed later to insert the year
+%D information in the correct item of \type{\thebibyears}
+
+\def\checkifmyauthoralreadyexists
+ {\doifemptyelsevalue{thebibauthors}
+ {\global\bibitemwanted \plusone
+ \global\bibitemcounter\plusone
+ \xdef\thebibauthors{{\myauthor}}}
+ {% the next weirdness is because according to \getcommalistsize,
+ % the length of \type{[{{},{}}]} is 2.
+ \@EA\getcommalistsize\@EA[\thebibauthors,]%
+ \global\bibitemcounter\numexpr\commalistsize+\minusone\relax
+ \global\bibitemwanted \zerocount
+ \processcommacommand[\thebibauthors]\docomparemyauthor}}
+
+%D The outer \type{\ifnum} accomplishes the addition of
+%D a new author to \type{\thebibauthors}. The messing about with
+%D the two counters is again to make sure that \type{\thebibyears}
+%D will be updated correctly.If the author {\it was} found,
+%D the counters will stay at their present values and everything
+%D will be setup properly to insert the year info.
+
+\def\docomparemyauthor#1%
+ {\global\advance\bibitemwanted \plusone
+ \def\mytempc{#1}%
+ \ifx\mytempc\myauthor
+ \quitcommalist
+ \else\ifnum\bibitemwanted=\bibitemcounter\relax
+ \global\advance\bibitemwanted \plusone
+ \global\bibitemcounter\bibitemwanted\relax
+ \@EA\doglobal\@EA\robustaddtocommalist\@EA{{\myauthor}}\thebibauthors
+ \fi\fi}
+
+%D This macro should be clear now.
+
+\def\findmatchingyear
+ {\edef\wantednumber{\the\bibitemwanted}%
+ \getfromcommacommand[\thebibyears][\wantednumber]%
+ \ifx\commalistelement\empty
+ \edef\myyear{{\myyear}}%
+ \else
+ \edef\myyear{{\commalistelement,\myyear}}%
+ \fi
+ \edef\newcommalistelement{\myyear}%
+ \doglobal\replaceincommalist \thebibyears \wantednumber}
+
+%D \macros{gotobiblink,inbiblink,atbiblink}
+%D
+%D The final task is looping over that list until a match is found.
+
+\def\gotobiblink#1[#2]{\doifreferencefoundelse{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{\unknownreference{#2}}}
+\def\atbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\at [\bibrefprefix#1]}{\unknownreference{#1}}}
+\def\inbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\expanded{\goto{\currentreferencetext}}[\bibrefprefix#1]}{\unknownreference{#1}}}
+
+%D \macros{bibauthoryearref,bibauthoryearsref,bibauthorref,bibyearref}
+%D
+%D Now that all the hard work has been done, these are simple.
+%D \type{\ixbibauthoryearref} stores the data in the macros
+%D \type{\currentbibauthor} and \type{\currentbibyear}.
+
+\def\ifbibinteractionelse
+ {\iflocation
+ \edef\test{\bibalternative\c!interaction}%
+ \ifx\test\v!stop
+ \@EA\@EA\@EA\secondoftwoarguments
+ \else
+ \@EA\@EA\@EA\firstoftwoarguments
+ \fi
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+\def\ifbibinteractionelse
+ {\iflocation
+ \doifelse{\bibalternative\c!interaction}\v!stop
+ {\@EA\secondoftwoarguments}
+ {\@EA\firstoftwoarguments}%
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+\def\bibmaybeinteractive#1#2%
+ {\ifbibcitecompress
+ #2%
+ \else
+ \ifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}%
+ \fi}
+
+\def\bibauthoryearref[#1]%
+ {\ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left{\currentbibyear}\bibalternative\v!right}}
+ {\bibalternative\c!pubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left {\currentbibyear}\bibalternative\v!right}}
+ {\bibalternative\c!lastpubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
+ \bibalternative\v!left {\currentbibyear}\bibalternative\v!right}}}
+
+\def\bibauthoryearsref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}
+ {\bibalternative\c!pubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}
+ {\bibalternative\c!lastpubsep
+ \bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}%
+ \bibalternative\v!right}
+
+\def\bibauthorref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibauthor}}}
+ {\bibalternative\c!pubsep \bibmaybeinteractive{#1}{{\currentbibauthor}}}
+ {\bibalternative\c!lastpubsep\bibmaybeinteractive{#1}{{\currentbibauthor}}}%
+ \bibalternative\v!right}
+
+\def\bibyearref[#1]%
+ {\bibalternative\v!left
+ \ixbibauthoryear{#1}%
+ {\bibmaybeinteractive{#1}{{\currentbibyear}}}
+ {\bibalternative\c!pubsep \bibmaybeinteractive{#1}{{\currentbibyear}}}
+ {\bibalternative\c!lastpubsep\bibmaybeinteractive{#1}{{\currentbibyear}}}%
+ \bibalternative\v!right}
+
+%D \macros{bibshortref,bibkeyref,bibpageref,bibtyperef,bibserialref}
+%D
+%D There is hardly any point in trying to compress these. The only
+%D thing that needs to be done is making sure that
+%D the separations are inserted correctly. And that is
+%D what \type{\bibinsertrefsep} does.
+
+\newconditional\firstbibrefsep
+
+\def\bibresetrefsep
+ {\settrue\firstbibrefsep}
+
+\def\bibinsertrefsep
+ {\ifconditional\firstbibrefsep
+ \setfalse\firstbibrefsep
+ \else
+ \bibalternative\c!pubsep
+ \fi}
+
+\def\bibshortref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibshortref
+ \bibalternative\v!right}
+
+\def\dobibshortref#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\gotobiblink{\bibgetvars{#1}}[#1]}
+ {\unknownreference{#1}}}
+
+\def\bibserialref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibserialref
+ \bibalternative\v!right}
+
+\def\dobibserialref#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\gotobiblink{\bibgetvarn{#1}}[#1]}
+ {\unknownreference{#1}}}
+
+\def\bibkeyref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibkeyref
+ \bibalternative\v!right}
+
+\def\dobibkeyref#1%
+ {\bibinsertrefsep
+ \gotobiblink{#1}[#1]}
+
+\def\bibgotoDOI#1#2%
+ {\ifbibinteractionelse
+ {\useURL[bibfooDoi#1][#2]%
+ \useURL[bibfoo#1][http://dx.doi.org/#2]%
+ \goto{\url[bibfooDoi#1]}[url(bibfoo#1)]}
+ {\hyphenatedurl{#2}}}
+
+\def\bibdoiref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibdoiref
+ \bibalternative\v!right}
+
+\def\dobibdoiref#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\expanded{\bibgotoDOI{#1}{\bibgetvaro{#1}}}}
+ {\unknownreference{#1}}}
+
+\def\biburlref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobiburlref
+ \bibalternative\v!right}
+
+\def\bibgotoURL#1#2%
+ {\ifbibinteractionelse
+ {\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]}
+ {\hyphenatedurl{#2}}}
+
+\def\dobiburlref#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\expanded{\bibgotoURL{#1}{\bibgetvaru{#1}}}}
+ {\unknownreference{#1}}}
+
+\def\bibtyperef[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibtyperef
+ \bibalternative\v!right}
+
+\def\dobibtyperef#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\gotobiblink{\bibgetvart{#1}}[#1]}
+ {\unknownreference{#1}}}
+
+\def\bibpageref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibpageref
+ \bibalternative\v!right}
+
+\def\dobibpageref#1%
+ {\bibinsertrefsep
+ \ifbibinteractionelse
+ {\atbiblink[#1]}
+ {{\referencingfalse\at[#1]}}}
+
+\def\bibdataref[#1]%
+ {\bibalternative\v!left
+ \bibresetrefsep\processcommalist[#1]\dobibdata
+ \bibalternative\v!right}
+
+\def\dobibdata#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\dotypesetapublication{#1}}
+ {\unknownreference{#1}}}
+
+\let\bibnoneref\nocite
+
+%D \macros{bibnumref}
+
+\def\bibnumref[#1]%
+ {\begingroup
+ \bibalternative\v!left
+ \penalty\!!tenthousand
+ \ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}%
+ \bibalternative\v!right
+ \endgroup}
+
+\def\dowithbibtexnumrefconnector#1#2%
+ {\ifnum#1>\plusone
+ \ifnum#2>\plusone
+ \ifnum#2=#1\relax
+ \bibalternative{lastpubsep}%
+ \else
+ \bibalternative{pubsep}%
+ \fi
+ \fi
+ \fi}
+
+\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibrefprefix{#4:}%
+ \inbiblink[#5]}
+
+\def\dowithbibtexnumrefrange#1#2#3#4#5#6#7% n, i, prefix block ref
+ {\dowithbibtexnumrefconnector{#1}{#2}%
+ \def\bibrefprefix{#4:}%
+ \inbiblink[#5]%
+ \endash
+ \def\bibrefprefix{#6:}%
+ \inbiblink[#7]}
+
+%D By request from Sanjoy. This makes it easier to implement
+%D \type{\citeasnoun}.
+
+\def\bibauthornumref[#1]%
+ {\getcommalistsize[#1]%
+ \global\bibitemcounter\commalistsize
+ \bibresetrefsep
+ \processcommalist[#1]\dobibauthornumref }
+
+\def\dobibauthornumref#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\begingroup
+ \bibgetvara{#1}%
+ \bibalternative\c!inbetween
+ \setuppublications[\c!refcommand=num]%
+ \cite[#1]%
+ \endgroup}
+ {\unknownreference{#1}}}
+
+%D And some defaults are loaded from bibl-apa:
+
+\def\c!monthconversion{monthconversion} % todo
+
+\setuppublications
+ [\c!monthconversion=,
+ \c!alternative=apa,
+ \c!method=\v!global,
+ \c!refcommand=num,
+ \c!numbercommand=\bibleftnumber]
+
+\def\preloadbiblist
+ {\globallet\preloadbiblist\relax
+ \dousepublications\jobname}
+
+% \appendtoks \preloadbiblist \to \everysetuppublications
+% \appendtoks \preloadbiblist \to \everystarttext
+
+\protect \endinput
diff --git a/tex/context/base/bibl-tst.lua b/tex/context/base/bibl-tst.lua
new file mode 100644
index 000000000..5ff8f4570
--- /dev/null
+++ b/tex/context/base/bibl-tst.lua
@@ -0,0 +1,21 @@
+dofile("bibl-bib.lua")
+
+local session = bibtex.new()
+
+bibtex.load(session,"gut.bib")
+bibtex.load(session,"komoedie.bib")
+bibtex.load(session,"texbook1.bib")
+bibtex.load(session,"texbook2.bib")
+bibtex.load(session,"texbook3.bib")
+bibtex.load(session,"texgraph.bib")
+bibtex.load(session,"texjourn.bib")
+bibtex.load(session,"texnique.bib")
+bibtex.load(session,"tugboat.bib")
+print(bibtex.size,statistics.elapsedtime(bibtex))
+bibtex.toxml(session)
+print(bibtex.size,statistics.elapsedtime(bibtex))
+
+--~ print(table.serialize(session.data))
+--~ print(table.serialize(session.shortcuts))
+--~ print(xml.serialize(session.xml))
+
diff --git a/tex/context/base/blob-ini.lua b/tex/context/base/blob-ini.lua
new file mode 100644
index 000000000..0f7ccee26
--- /dev/null
+++ b/tex/context/base/blob-ini.lua
@@ -0,0 +1,165 @@
+if not modules then modules = { } end modules ['blob-ini'] = {
+ version = 1.001,
+ comment = "companion to blob-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- later we will consider an OO variant.
+
+-- This module is just a playground. Occasionally we need to typeset
+-- at the lua and and this is one method. In principle we can construct
+-- pages this way too which sometimes makes sense in dumb cases. Actually,
+-- if one only needs this, one does not really need tex, okay maybe the
+-- parbuilder but that one can be simplified as well then.
+
+-- set fonts, attributes
+-- rest already done in packers etc
+-- add local par whatsit (or wait till cleaned up)
+-- collapse or new pars
+-- interline spacing etc
+
+-- DON'T USE THESE FUNCTIONS AS THEY WILL CHANGE!
+
+local type = type
+
+local utfvalues = string.utfvalues
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+
+local fontdata = fonts.identifiers
+
+local new_glyph_node = nodes.glyph
+local new_glue_node = nodes.glyph
+
+local copy_node = node.copy
+local copy_node_list = node.copy_list
+local insert_node_after = node.insert_after
+local flush_node_list = node.flush_list
+local hpack_node_list = node.hpack
+local vpack_node_list = node.vpack
+local write_node = node.write
+
+local current_font = font.current
+
+blobs = blobs or { }
+
+local newline = lpegpatterns.newline
+local space = lpegpatterns.spacer
+local spacing = newline * space^0
+local content = (space^1)/" " + (1-spacing)
+
+local ctxtextcapture = lpeg.Ct ( (
+ space^0 * (
+ newline^2 * space^0 * lpeg.Cc("")
+ + newline * space^0 * lpeg.Cc(" ")
+ + lpeg.Cs(content^1)
+ )
+)^0)
+
+local function tonodes(str,fnt,attr) -- (str,template_glyph)
+ if not str or str == "" then
+ return
+ end
+ local head, tail, space, fnt, template = nil, nil, nil, nil, nil
+ if not fnt then
+ fnt = current_font()
+ elseif type(fnt) ~= "number" and fnt.id == "glyph" then
+ fnt, template = nil, fnt
+ -- else
+ -- already a number
+ end
+ for s in utfvalues(str) do
+ local n
+ if s == 32 then
+ if not space then
+ local parameters = fontdata[fnt].parameters
+ space = new_glue_node(parameters.space,parameters.space_stretch,parameters.space_shrink)
+ n = space
+ else
+ n = copy_node(space)
+ end
+ elseif template then
+ n = copy_node(template)
+ n.char = s
+ else
+ n = new_glyph_node(fnt,s)
+ end
+ if attr then -- normall false when template
+ n.attr = copy_node_list(attr)
+ end
+ if head then
+ insert_node_after(head,tail,n)
+ else
+ head = n
+ end
+ tail = n
+ end
+ return head, tail
+end
+
+blobs.tonodes = tonodes
+
+function blobs.new()
+ return {
+ list = { },
+ }
+end
+
+function blobs.append(t,str)
+ local kind = type(str)
+ local dummy = nil
+ if kind == "string" then
+ local pars = lpegmatch(ctxtextcapture,str)
+ local list = t.list
+ for p=1,#pars do
+ local str = pars[p]
+ if #str == 0 then
+ list[#list+1 ] = { head = nil, tail = nil }
+ else
+ local l = list[#list]
+ if not l then
+ l = { head = nil, tail = nil }
+ list[#list+1 ] = l
+ end
+ local head, tail = tonodes(str,nil,nil)
+ if head then
+ if l.head then
+ l.tail.next = head
+ head.prev = l.tail
+ l.tail = tail
+ else
+ l.head, l.tail = head, tail
+ end
+ end
+ end
+ end
+ end
+end
+
+function blobs.pack(t,how)
+ local list = t.list
+ for i=1,#list do
+ local pack = list[i].pack
+ if pack then
+ flush_node_list(node.pack)
+ end
+ if how == "vertical" then
+ -- we need to prepend a local par node
+ -- list[i].pack = node.vpack(list[i].head,"exactly")
+ logs.report("blobs","vpack not yet supported")
+ else
+ list[i].pack = hpack_node_list(list[i].head,"exactly")
+ end
+ end
+end
+
+function blobs.write(t)
+ local list = t.list
+ for i=1,#list do
+ local pack = list[i].pack
+ if pack then
+ write_node(pack)
+ end
+ end
+end
diff --git a/tex/context/base/blob-ini.mkiv b/tex/context/base/blob-ini.mkiv
new file mode 100644
index 000000000..7f63ec73d
--- /dev/null
+++ b/tex/context/base/blob-ini.mkiv
@@ -0,0 +1,34 @@
+%D \module
+%D [ file=blob-ini,
+%D version=2010.04.06,
+%D title=\CONTEXT\ \LUA\ Typesetting,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Lua Typesetting / Initialization}
+
+%D This is a prelude to typesetting at the \LUA\ end. The code
+%D is already quite old but will only get nice when we are further
+%D down the road (close to version 1.00 of \LUATEX). Typesetting in
+%D pure \LUA\ sometimes makes sense.
+
+\registerctxluafile{blob-ini}{1.001}
+
+\endinput
+
+% \starttext
+%
+% \startluacode
+% local b = blobs.new()
+% blobs.append(b,"Hello world.\n Here we are.\n\n And Again!")
+% blobs.pack(b)
+% blobs.write(b)
+% \stopluacode
+%
+% \stoptext
diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua
new file mode 100644
index 000000000..6b1af8f96
--- /dev/null
+++ b/tex/context/base/buff-ini.lua
@@ -0,0 +1,838 @@
+if not modules then modules = { } end modules ['buff-ini'] = {
+ version = 1.001,
+ comment = "companion to core-buf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- ctx lua reference model / hooks and such
+-- to be optimized
+
+-- redefine buffers.get
+
+buffers = { }
+buffers.data = { }
+buffers.hooks = { }
+buffers.flags = { }
+buffers.commands = { }
+buffers.visualizers = { }
+
+-- if needed we can make 'm local
+
+local trace_run = false trackers.register("buffers.run", function(v) trace_run = v end)
+local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
+
+local utf = unicode.utf8
+
+local concat, texsprint, texprint, texwrite = table.concat, tex.sprint, tex.print, tex.write
+local utfbyte, utffind, utfgsub = utf.byte, utf.find, utf.gsub
+local type, next = type, next
+local huge = math.huge
+local byte, sub, find, char, gsub, rep, lower, format, gmatch, match = string.byte, string.sub, string.find, string.char, string.gsub, string.rep, string.lower, string.format, string.gmatch, string.match
+local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
+local ctxcatcodes = tex.ctxcatcodes
+local variables = interfaces.variables
+local lpegmatch = lpeg.match
+
+local data, flags, hooks, visualizers = buffers.data, buffers.flags, buffers.hooks, buffers.visualizers
+
+visualizers.defaultname = variables.typing
+
+function buffers.raw(name)
+ return data[name] or { }
+end
+
+function buffers.erase(name)
+ data[name] = nil
+end
+
+function buffers.set(name, str)
+ data[name] = { str } -- CHECK THIS
+end
+
+function buffers.append(name, str)
+ data[name] = (data[name] or "") .. str
+end
+
+
+buffers.flags.store_as_table = true
+
+-- to be sorted out: crlf + \ ; slow now
+
+local n = 0
+
+function buffers.grab(name,begintag,endtag,bufferdata)
+ local dn = data[name] or ""
+ if dn == "" then
+ buffers.level = 0
+ end
+ buffers.level = buffers.level + bufferdata:count("\\"..begintag) - bufferdata:count("\\"..endtag)
+ local more = buffers.level > 0
+ if more then
+ dn = dn .. bufferdata .. endtag
+ buffers.level = buffers.level - 1
+ else
+ if dn == "" then
+ dn = sub(bufferdata,1,#bufferdata-1)
+ else
+ dn = dn .. "\n" .. sub(bufferdata,1,#bufferdata-1)
+ end
+ dn = gsub(dn,"[\010\013]$","")
+ if flags.store_as_table then
+ dn = dn:splitlines()
+ end
+ end
+ data[name] = dn
+ cs.testcase(more)
+end
+
+function buffers.exists(name)
+ return data[name] ~= nil
+end
+
+function buffers.doifelsebuffer(name)
+ cs.testcase(data[name] ~= nil)
+end
+
+flags.optimize_verbatim = true
+flags.count_empty_lines = false
+
+local no_break_command = "\\doverbatimnobreak"
+local do_break_command = "\\doverbatimgoodbreak"
+local begin_of_line_command = "\\doverbatimbeginofline"
+local end_of_line_command = "\\doverbatimendofline"
+local empty_line_command = "\\doverbatimemptyline"
+
+local begin_of_display_command = "\\doverbatimbeginofdisplay"
+local end_of_display_command = "\\doverbatimendofdisplay"
+local begin_of_inline_command = "\\doverbatimbeginofinline"
+local end_of_inline_command = "\\doverbatimendofinline"
+
+function buffers.verbatimbreak(n,m)
+ if flags.optimize_verbatim then
+ if n == 2 or n == m then
+ texsprint(no_break_command)
+ elseif n > 1 then
+ texsprint(do_break_command)
+ end
+ end
+end
+
+function buffers.strip(lines,first,last)
+ local first, last = first or 1, last or #lines
+ for i=first,last do
+ local li = lines[i]
+ if #li == 0 or find(li,"^%s*$") then
+ first = first + 1
+ else
+ break
+ end
+ end
+ for i=last,first,-1 do
+ local li = lines[i]
+ if #li == 0 or find(li,"^%s*$") then
+ last = last - 1
+ else
+ break
+ end
+ end
+ return first, last, last - first + 1
+end
+
+function buffers.range(lines,first,last,range) -- 1,3 1,+3 fromhere,tothere
+ local first, last = first or 1, last or #lines
+ local what = aux.settings_to_array(range)
+ local r_first, r_last = what[1], what[2]
+ local f, l = tonumber(r_first), tonumber(r_last)
+ if r_first then
+ if f then
+ if f > first then
+ first = f
+ end
+ else
+ for i=first,last do
+ if find(lines[i],r_first) then
+ first, strip = i + 1
+ break
+ end
+ end
+ end
+ end
+ if r_last then
+ if l then
+ if find(r_last,"^[%+]") then -- 1,+3
+ l = first + l
+ end
+ if l < last then
+ last = l
+ end
+ else
+ for i=first,last do
+ if find(lines[i],r_last) then
+ last = i - 1
+ break
+ end
+ end
+ end
+ end
+ return first, last
+end
+
+function buffers.type(name,realign,range)
+ local lines = data[name]
+ local action = buffers.typeline
+ if lines then
+ if type(lines) == "string" then
+ lines = lines:splitlines()
+ data[name] = lines
+ end
+ if realign then
+ lines = buffers.realign(lines,realign)
+ end
+ local line, n = 0, 0
+ local first, last, m = buffers.strip(lines)
+ if range then
+ first, last = buffers.range(lines,first,last,range)
+ first, last = buffers.strip(lines,first,last)
+ end
+ hooks.begin_of_display()
+ for i=first,last do
+ n, line = action(lines[i], n, m, line)
+ end
+ hooks.end_of_display()
+ end
+end
+
+function buffers.loaddata(filename) -- this one might go away
+ -- this will be cleaned up when we have split supp-fil completely
+ -- instead of half-half
+ local ok, str, n = resolvers.loaders.tex(filename)
+ if not str then
+ ok, str, n = resolvers.loaders.tex(file.addsuffix(filename,'tex'))
+ end
+end
+
+function buffers.loaddata(filename) -- this one might go away
+ local foundname = resolvers.findtexfile(filename) or ""
+ if foundname == "" then
+ foundname = resolvers.findtexfile(file.addsuffix(filename,'tex')) or ""
+ end
+ if foundname == "" then
+ return ""
+ else
+ return resolvers.loadtexfile(foundname)
+ end
+end
+
+function buffers.typefile(name,realign,range) -- still somewhat messy, since name can be be suffixless
+ local str = buffers.loaddata(name)
+ if str and str~= "" then
+ local lines = str:splitlines()
+ if realign then
+ lines = buffers.realign(lines,realign)
+ end
+ local line, n, action = 0, 0, buffers.typeline
+ local first, last, m = buffers.strip(lines)
+ hooks.begin_of_display()
+ if range then
+ first, last = buffers.range(lines,first,last,range)
+ first, last = buffers.strip(lines,first,last)
+ end
+ for i=first,last do
+ n, line = action(lines[i], n, m, line)
+ end
+ hooks.end_of_display()
+ end
+end
+
+function buffers.typeline(str,n,m,line)
+ n = n + 1
+ buffers.verbatimbreak(n,m)
+ if find(str,"%S") then
+ line = line + 1
+ hooks.begin_of_line(line)
+ hooks.flush_line(hooks.line(str))
+ hooks.end_of_line()
+ else
+ if flags.count_empty_lines then
+ line = line + 1
+ end
+ hooks.empty_line(line)
+ end
+ return n, line
+end
+
+-- The optional prefix hack is there for the typesetbuffer feature and
+-- in mkii we needed that (this hidden feature is used in a manual).
+
+local function prepared(name,list) -- list is optional
+ if not list or list == "" then
+ list = name
+ end
+ if not name or name == "" then
+ name = tex.jobname .. "-" .. list .. ".tmp"
+ end
+ local content = buffers.collect(list,nil) or ""
+ if content == "" then
+ content = "empty buffer"
+ end
+ return name, content
+end
+
+local capsule = "\\starttext\n%s\n\\stoptext\n"
+local command = "context %s"
+
+function buffers.save(name,list,encapsulate) -- list is optional
+ local name, content = prepared(name,list)
+ io.savedata(name, (encapsulate and format(capsule,content)) or content)
+end
+
+function commands.savebuffer(list,name) -- name is optional
+ buffers.save(name,list)
+end
+
+function buffers.run(name,list,encapsulate)
+ local name, content = prepared(name,list)
+ local data = io.loaddata(name)
+ content = (encapsulate and format(capsule,content)) or content
+ if data ~= content then
+ if trace_run then
+ commands.writestatus("buffers","changes in '%s', processing forced",name)
+ end
+ io.savedata(name,content)
+ os.execute(format(command,name))
+ elseif trace_run then
+ commands.writestatus("buffers","no changes in '%s', not processed",name)
+ end
+end
+
+local printer = (lpeg.patterns.textline/texprint)^0
+
+function buffers.get(name)
+ local b = buffers.data[name]
+ if b then
+ if type(b) == "table" then
+ for i=1,#b do
+ texprint(b[i])
+ end
+ else
+ lpegmatch(printer,b)
+ end
+ end
+end
+
+local function content(name,separator) -- no print
+ local b = data[name]
+ if b then
+ if type(b) == "table" then
+ return concat(b,separator or "\n")
+ else
+ return b
+ end
+ else
+ return ""
+ end
+end
+
+buffers.content = content
+
+function buffers.collect(names,separator) -- no print
+ -- maybe we should always store a buffer as table so
+ -- that we can pass it directly
+ if type(names) == "string" then
+ names = aux.settings_to_array(names)
+ end
+ local t = { }
+ for i=1,#names do
+ local c = content(names[i],separator)
+ if c ~= "" then
+ t[#t+1] = c
+ end
+ end
+ return concat(t,separator or "\r") -- "\n" is safer due to comments and such
+end
+
+function buffers.feedback(names,separator)
+ -- don't change the texprint into texsprint as it fails on mp buffers
+ -- because (penddef) becomes penddef then
+ texprint(ctxcatcodes,string.splitlines(buffers.collect(names,separator)))
+end
+
+local function tobyte(c)
+ return " [" .. utfbyte(c) .. "] "
+end
+
+function buffers.inspect(name)
+ local b = data[name]
+ if b then
+ if type(b) == "table" then
+ for k=1,#b do
+ local v = b[k]
+ if v == "" then
+ texsprint(ctxcatcodes,"[crlf]\\par ") -- space ?
+ else
+ texsprint(ctxcatcodes,(gsub(v,"(.)",tobyte)),"\\par")
+ end
+ end
+ else
+ texsprint(ctxcatcodes,(gsub(b,"(.)",tobyte)))
+ end
+ end
+end
+
+-- maybe just line(n,str) empty(n,str)
+
+visualizers.tablength = 7
+visualizers.enabletab = true -- false
+visualizers.obeyspace = true
+
+function buffers.settablength(tablength)
+ visualizers.tablength = tablength and tonumber(tablength) or 7
+end
+
+visualizers.handlers = visualizers.handlers or { }
+
+local handlers = visualizers.handlers
+
+function buffers.newvisualizer(name)
+ name = lower(name)
+ local handler = { }
+ handlers[name] = handler
+ return handler
+end
+
+function buffers.getvisualizer(name)
+ name = lower(name)
+ return handlers[name] or buffers.loadvisualizer(name)
+end
+
+function buffers.loadvisualizer(name)
+ name = lower(name)
+ local hn = handlers[name]
+ if hn then
+ return hn
+ else
+ environment.loadluafile("pret-" .. name)
+ local hn = handlers[name]
+ if not hn then
+ -- hn = buffers.newvisualizer(name)
+ hn = handlers[visualizers.defaultname]
+ handlers[name] = hn
+ if trace_visualize then
+ logs.report("buffers","mapping '%s' visualizer onto '%s'",name,visualizers.defaultname)
+ end
+ elseif trace_visualize then
+ logs.report("buffers","loading '%s' visualizer",name)
+ end
+ return hn
+ end
+end
+
+-- was "default", should be set at tex end (todo)
+
+local default = buffers.newvisualizer(visualizers.defaultname)
+
+--~ print(variables.typing) os.exit()
+
+-- will become cleaner
+
+local currentvisualizer, currenthandler
+
+function buffers.setvisualizer(str)
+ currentvisualizer = lower(str)
+ currenthandler = handlers[currentvisualizer]
+ if currenthandler then
+ -- if trace_visualize then
+ -- logs.report("buffers","enabling specific '%s' visualizer",currentvisualizer)
+ -- end
+ else
+ currentvisualizer = visualizers.defaultname
+ currenthandler = handlers.default
+ -- if trace_visualize then
+ -- logs.report("buffers","enabling default visualizer '%s'",currentvisualizer)
+ -- end
+ end
+ if currenthandler.reset then
+ currenthandler.reset()
+ end
+end
+
+function buffers.resetvisualizer()
+ currentvisualizer = visualizers.defaultname
+ currenthandler = handlers.default
+ if currenthandler.reset then
+ currenthandler.reset()
+ end
+end
+
+buffers.setvisualizer(visualizers.defaultname)
+
+function visualizers.reset()
+end
+
+function buffers.doifelsevisualizer(str)
+ cs.testcase((str ~= "") and (handlers[lower(str)] ~= nil))
+end
+
+-- calling routines, don't change
+
+function hooks.begin_of_display()
+ (currenthandler.begin_of_display or default.begin_of_display)(currentvisualizer)
+end
+
+function hooks.end_of_display()
+ (currenthandler.end_of_display or default.end_of_display)()
+end
+
+function hooks.begin_of_inline()
+ (currenthandler.begin_of_inline or default.begin_of_inline)(currentvisualizer)
+end
+
+function hooks.end_of_inline()
+ (currenthandler.end_of_inline or default.end_of_inline)()
+end
+
+function hooks.flush_line(str,nesting)
+ local fl = currenthandler.flush_line
+ if fl then
+ str = gsub(str," *[\n\r]+ *"," ") ; -- semi colon needed
+ fl(str,nesting)
+ else
+ -- gsub done later
+ default.flush_line(str,nesting)
+ end
+end
+
+function hooks.flush_inline(str,nesting)
+ hooks.begin_of_inline()
+ hooks.flush_line(str,nesting)
+ hooks.end_of_inline()
+end
+
+function hooks.begin_of_line(n)
+ (currenthandler.begin_of_line or default.begin_of_line)(n)
+end
+
+function hooks.end_of_line()
+ (currenthandler.end_of_line or default.end_of_line)()
+end
+
+function hooks.empty_line()
+ (currenthandler.empty_line or default.empty_line)()
+end
+
+function hooks.line(str)
+ if visualizers.enabletab then
+ str = string.tabtospace(str,visualizers.tablength)
+ else
+ str = gsub(str,"\t"," ")
+ end
+ return (currenthandler.line or default.line)(str)
+end
+
+-- defaults
+
+function default.begin_of_display(currentvisualizer)
+ texsprint(ctxcatcodes,begin_of_display_command,"{",currentvisualizer,"}")
+end
+
+function default.end_of_display()
+ texsprint(ctxcatcodes,end_of_display_command)
+end
+
+function default.begin_of_inline(currentvisualizer)
+ texsprint(ctxcatcodes,begin_of_inline_command,"{",currentvisualizer,"}")
+end
+
+function default.end_of_inline()
+ texsprint(ctxcatcodes,end_of_inline_command)
+end
+
+function default.begin_of_line(n)
+ texsprint(ctxcatcodes, begin_of_line_command,"{",n,"}")
+end
+
+function default.end_of_line()
+ texsprint(ctxcatcodes,end_of_line_command)
+end
+
+function default.empty_line()
+ texsprint(ctxcatcodes,empty_line_command)
+end
+
+function default.line(str)
+ return str
+end
+
+function default.flush_line(str)
+ str = gsub(str," *[\n\r]+ *"," ")
+ if visualizers.obeyspace then
+ for c in utfcharacters(str) do
+ if c == " " then
+ texsprint(ctxcatcodes,"\\obs")
+ else
+ texwrite(c)
+ end
+ end
+ else
+ texwrite(str)
+ end
+end
+
+-- not needed any more
+
+local function escaped_token(c)
+ if utffind(c,"^(%a%d)$") then
+ return c
+ elseif c == " " then
+ return "\\obs "
+ else
+ return "\\char" .. utfbyte(c) .. " "
+ end
+end
+
+buffers.escaped_token = escaped_token
+
+function buffers.escaped(str)
+ -- use the utfcharacters loop
+ return (utfgsub(str,"(.)", escaped_token))
+end
+
+-- special one
+
+buffers.commands.nested = "\\switchslantedtype "
+
+-- todo : utf + faster, direct print and such. no \\char, vrb catcodes, see end
+
+function visualizers.flush_nested(str, enable) -- no utf, kind of obsolete mess
+ str = gsub(str," *[\n\r]+ *"," ")
+ local result, c, nested, i = "", "", 0, 1
+ local commands = buffers.commands -- otherwise wrong commands
+ while i < #str do -- slow
+ c = sub(str,i,i+1)
+ if c == "<<" then
+ nested = nested + 1
+ if enable then
+ result = result .. "{" .. commands.nested
+ else
+ result = result .. "{"
+ end
+ i = i + 2
+ elseif c == ">>" then
+ if nested > 0 then
+ nested = nested - 1
+ result = result .. "}"
+ end
+ i = i + 2
+ else
+ c = sub(str,i,i)
+ if c == " " then
+ result = result .. "\\obs "
+ elseif find(c,"%a") then
+ result = result .. c
+ else
+ result = result .. "\\char" .. byte(c) .. " "
+ end
+ i = i + 1
+ end
+ end
+ result = result .. "\\char" .. byte(sub(str,i,i)) .. " " .. rep("}",nested)
+ texsprint(ctxcatcodes,result)
+end
+
+-- handy helpers
+--
+-- \sop[color] switch_of_pretty
+-- \bop[color] begin_of_pretty
+-- \eop end_of_pretty
+-- \obs obeyedspace
+-- \char special characters
+
+buffers.currentcolors = { }
+
+function buffers.change_state(n, state)
+ if n then
+ if state ~= n then
+ if state > 0 then
+ texsprint(ctxcatcodes,"\\sop[",buffers.currentcolors[n],"]")
+ else
+ texsprint(ctxcatcodes,"\\bop[",buffers.currentcolors[n],"]")
+ end
+ return n
+ end
+ elseif state > 0 then
+ texsprint(ctxcatcodes,"\\eop")
+ return 0
+ end
+ return state
+end
+
+function buffers.finish_state(state)
+ if state > 0 then
+ texsprint(ctxcatcodes,"\\eop")
+ return 0
+ else
+ return state
+ end
+end
+
+buffers.open_nested = rep("\\char"..byte('<').." ",2)
+buffers.close_nested = rep("\\char"..byte('>').." ",2)
+
+function buffers.replace_nested(result)
+ result = gsub(result,buffers.open_nested, "{")
+ result = gsub(result,buffers.close_nested,"}")
+ return result
+end
+
+function buffers.flush_result(result,nested)
+ if nested then
+ texsprint(ctxcatcodes,buffers.replace_nested(concat(result,"")))
+ else
+ texsprint(ctxcatcodes,concat(result,""))
+ end
+end
+
+-- new
+
+function buffers.realign(name,forced_n) -- no, auto,
+ local n, d
+ if type(name) == "string" then
+ d = data[name]
+ if type(d) == "string" then
+ d = d:splitlines()
+ end
+ else
+ d = name -- already a buffer
+ end
+ forced_n = (forced_n == variables.auto and huge) or tonumber(forced_n)
+ if forced_n then
+ for i=1, #d do
+ local spaces = find(d[i],"%S")
+ if not spaces then
+ -- empty line
+ elseif not n then
+ n = spaces
+ elseif spaces == 0 then
+ n = 0
+ break
+ elseif n > spaces then
+ n = spaces
+ end
+ end
+ if n > 0 then
+ if n > forced_n then
+ n = forced_n
+ end
+ for i=1,#d do
+ d[i] = sub(d[i],n)
+ end
+ end
+ end
+ return d
+end
+
+-- escapes: buffers.set_escape("tex","/BTEX","/ETEX")
+
+local function flush_escaped_line(str,pattern,flushline)
+ while true do
+ local a, b, c = match(str,pattern)
+ if a and a ~= "" then
+ flushline(a)
+ end
+ if b and b ~= "" then
+ texsprint(ctxcatcodes,"{",b,"}")
+ end
+ if c then
+ if c == "" then
+ break
+ else
+ str = c
+ end
+ else
+ flushline(str)
+ break
+ end
+ end
+end
+
+function buffers.set_escape(name,pair)
+ if pair and pair ~= "" then
+ local visualizer = buffers.getvisualizer(name)
+ visualizer.normal_flush_line = visualizer.normal_flush_line or visualizer.flush_line
+ if pair == variables.no then
+ visualizer.flush_line = visualizer.normal_flush_line or visualizer.flush_line
+ if trace_visualize then
+ logs.report("buffers","resetting escape range for visualizer '%s'",name)
+ end
+ else
+ local start, stop
+ if pair == variables.yes then
+ start, stop = "/BTEX", "/ETEX"
+ else
+ pair = string.split(pair,",")
+ start, stop = string.esc(pair[1] or ""), string.esc(pair[2] or "")
+ end
+ if start ~= "" then
+ local pattern
+ if stop == "" then
+ pattern = "^(.-)" .. start .. "(.*)(.*)$"
+ else
+ pattern = "^(.-)" .. start .. "(.-)" .. stop .. "(.*)$"
+ end
+ function visualizer.flush_line(str)
+ flush_escaped_line(str,pattern,visualizer.normal_flush_line)
+ end
+ if trace_visualize then
+ logs.report("buffers","setting escape range for visualizer '%s' to %s -> %s",name,start,stop)
+ end
+ elseif trace_visualize then
+ logs.report("buffers","problematic escape specification '%s' for visualizer '%s'",pair,name)
+ end
+ end
+ end
+end
+
+-- THIS WILL BECOME A FRAMEWORK: the problem with prety printing is that
+-- we deal with snippets and therefore we need tolerant parsing
+
+--~ local type = type
+
+--~ visualizers = visualizers or { }
+
+--~ local function fallback(s) return s end
+
+--~ function visualizers.visualize(visualizer,kind,pattern)
+--~ if type(visualizer) == "table" and type(kind) == "string" then
+--~ kind = visualizer[kind] or visualizer.default or fallback
+--~ else
+--~ kind = fallback
+--~ end
+--~ return (lpeg.C(pattern))/kind
+--~ end
+
+--~ local flusher = texio.write
+--~ local format = string.format
+
+--~ local visualizer = {
+--~ word = function(s) return flusher(format("\\bold{%s}",s)) end,
+--~ number = function(s) return flusher(format("\\slanted{%s}",s)) end,
+--~ default = function(s) return flusher(s) end,
+--~ }
+
+--~ local word = lpeg.R("AZ","az")^1
+--~ local number = lpeg.R("09")^1
+--~ local any = lpeg.P(1)
+
+--~ local pattern = lpeg.P { "start",
+--~ start = (
+--~ visualizers.visualize(visualizer,"word",word) +
+--~ visualizers.visualize(visualizer,"number",number) +
+--~ visualizers.visualize(visualizer,"default",any)
+--~ )^1
+--~ }
+
+--~ str = [[test 123 test $oeps$]]
+
+--~ lpegmatch(pattern,str)
diff --git a/tex/context/base/buff-ini.mkii b/tex/context/base/buff-ini.mkii
new file mode 100644
index 000000000..fc147d090
--- /dev/null
+++ b/tex/context/base/buff-ini.mkii
@@ -0,0 +1,348 @@
+%D \module
+%D [ file=buff-ini, % was core-buf % blocks are moved to core-blk
+%D version=2000.01.05,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Buffers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Buffer Macros / Buffers}
+
+\unprotect
+
+% Helpers:
+
+\chardef\buffernestmode\plusone % 0: not nested, 1: startbuffer nested, 2: all buffers nested
+
+\edefconvertedargument\emptybufferline{ }
+
+\ifx\tmpblocks\undefined \newwrite\tmpblocks \fi
+
+\newif\iftmpblockstarted
+
+\long\def\flushbufferline#1%
+ {\iftmpblockstarted
+ \ifsegmentatebuffer
+ \ifemptybufferline
+ \immediate\write\tmpblocks{\string\stopbufferparagraph }%
+ \immediate\write\tmpblocks{\string\startbufferparagraph}%
+ \else
+ \immediate\write\tmpblocks{#1}%
+ \fi
+ \else
+ \immediate\write\tmpblocks{#1}%
+ \fi
+ \else
+ \doifsomething{#1}
+ {\tmpblockstartedtrue
+ \immediate\write\tmpblocks{\string#1}}%
+ \fi}
+
+\long\def\processnextbufferlineA#1%
+ {\relax % checken waarom eerdere macro dit nodig heeft / supp-mps run
+ \defconvertedargument\next{#1 }%
+ \doifinstringelse{\delcharacter\letterpercent}{\delcharacter\next}
+ {\secondoftwoarguments}
+ {\doifincsnameelse\endofblock\next
+ {\ifnum\nestedbufferlevel=\zerocount
+ \expandafter\firstoftwoarguments
+ \else
+ \decrement\nestedbufferlevel\relax
+ \expandafter\secondoftwoarguments
+ \fi}
+ {\doifincsnameelse\beginofblock\next
+ {\increment\nestedbufferlevel\relax
+ \secondoftwoarguments}
+ {\secondoftwoarguments}}}}
+
+\long\def\processnextbufferlineB#1% #2#3%
+ {\defconvertedargument\next{#1 }%
+ \ifx\next\emptybufferline
+ \ifsegmentatebuffer \emptybufferlinetrue \fi
+ \expandafter\secondoftwoarguments% #3%
+ \else
+ \emptybufferlinefalse
+ \doifinstringelse\endofblock\next
+ {\expandafter\firstoftwoarguments }% #2}
+ {\expandafter\secondoftwoarguments}% #3}%
+ \fi}
+
+\bgroup
+\obeylines
+\long\gdef\copybufferline#1
+ {\processnextbufferline{#1}\closebufferfile{\flushbufferline{#1}\copybufferline}}
+\egroup
+
+\newif\ifsegmentatebuffer
+\newif\ifemptybufferline
+
+\def\currentbuffer{\jobname}
+
+\def\setcurrentbuffer#1%
+ {\doifelsenothing{#1}{\edef\currentbuffer{\jobname}}{\edef\currentbuffer{#1}}}
+
+\def\resetbuffer
+ {\dosingleempty\doresetbuffer}
+
+\def\doresetbuffer[#1]%
+ {\begingroup
+ \setcurrentbuffer{#1}%
+ \unlinkfile{\TEXbufferfile\currentbuffer}%
+ \endgroup}
+
+\def\dostartbuffer
+ {\bgroup
+ \obeylines % nodig, anders gaat 't fout als direct \starttable (bv)
+ \doquadrupleempty\dodostartbuffer}
+
+\def\dodostartbuffer[#1][#2][#3][#4]% upward compatible
+ {\iffourthargument
+ \def\next{\dododostartbuffer{#1}{#2}{#3}{#4}}%
+ \else
+ \def\next{\dododostartbuffer {}{#1}{#2}{#3}}%
+ \fi
+ \next}
+
+\def\dododostartbuffer#1#2#3#4%
+ {%\showmessage\m!systems{15}{#2}%
+ \doifelsevalue{\??bu#1\c!paragraph}\v!yes
+ {\segmentatebuffertrue} % todo in mkiv
+ {\doifnumberelse{\getvalue{\??bu#1\c!paragraph}}\segmentatebuffertrue\segmentatebufferfalse}%
+ \doifvalue{\??bu#1\c!local}\v!yes
+ {\chardef\buffernestmode\plustwo}% permit nesting
+ \setcurrentbuffer{#2}%
+ \doifelsenothing{#4}
+ {\letbeundefined{\e!stop\v!buffer}% % \let\stopbuffer=\relax % \undefined
+ \edefconvertedargument\beginofblock{\e!start\v!buffer}%
+ \edefconvertedargument\endofblock {\e!stop \v!buffer}%
+ \ifcase\buffernestmode
+ \let\processnextbufferline\processnextbufferlineB
+ \else
+ \let\processnextbufferline\processnextbufferlineA
+ \fi}
+ {\letbeundefined{#4}% \letvalue{#4}=\relax % \undefined
+ \@EA\defconvertedargument\@EA\beginofblock\@EA{\csname#3\endcsname}% we could use defconvertedcommand here (no \@EA)
+ \@EA\defconvertedargument\@EA\endofblock \@EA{\csname#4\endcsname}% we could use defconvertedcommand here (no \@EA)
+ \ifcase\buffernestmode
+ \let\processnextbufferline\processnextbufferlineB
+ \or
+ \let\processnextbufferline\processnextbufferlineB
+ \else
+ \let\processnextbufferline\processnextbufferlineA
+ \fi}%
+ \def\closebufferfile
+ {\ifsegmentatebuffer
+ \immediate\write\tmpblocks{\string\stopbufferparagraph}%
+ \fi
+ \immediate\closeout\tmpblocks
+ \egroup
+ \getvalue{#4}}%
+ \doifelsenothing{#2}
+ {\edef\bufferfilename{\TEXbufferfile\jobname}}%
+ {\edef\bufferfilename{\TEXbufferfile{#2}}}%
+ \immediate\openout\tmpblocks\bufferfilename
+ \ifsegmentatebuffer
+ \immediate\write\tmpblocks{\string\startbufferparagraph}%
+ \fi
+ \newcounter\nestedbufferlevel
+ \recatcodeuppercharacterstrue
+ \setcatcodetable\vrbcatcodes
+ \obeylines
+ \copybufferline}
+
+\letvalue{\e!start\v!buffer}\dostartbuffer
+
+\let\endbuffer\undefined % to please the dep parser
+
+\def\setbuffer
+ {\dosingleempty\dosetbuffer}
+
+\long\def\dosetbuffer[#1]#2\endbuffer % seldom used so we just pass #2
+ {\begingroup
+ \setcurrentbuffer{#1}%
+ \edef\bufferfilename{\TEXbufferfile{\currentbuffer}}%
+ \immediate\openout\tmpblocks\bufferfilename
+ \defconvertedargument\ascii{#2}%
+ \immediate\write\tmpblocks{\ascii}%
+ \immediate\closeout\tmpblocks
+ \endgroup}
+
+\def\setupbuffer
+ {\dodoubleempty\dosetupbuffer}
+
+\def\dosetupbuffer[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??bu#1][#2]%
+ \else
+ \getparameters[\??bu][#1]%
+ \fi}
+
+\def\dodefinebuffer[#1][#2]%
+ {\iffirstargument % else problems
+ \doglobal\increment\nofdefinedbuffers
+ \letvalue{\??bu#1\c!number }\nofdefinedbuffers
+ \letvalue{\??bu#1\c!paragraph}\v!no
+ \setevalue{\e!start#1}{\noexpand\dostartbuffer[#1][def-\nofdefinedbuffers][\e!start#1][\e!stop#1]}%
+ \unexpanded\setevalue{\e!get #1}{\noexpand\dogetbuffer [#1][def-\nofdefinedbuffers]}%
+ \unexpanded\setevalue{\e!type #1}{\noexpand\dotypebuffer [#1][def-\nofdefinedbuffers]}%
+ \getparameters[\??bu#1][#2]%
+ \fi}
+
+\def\definebuffer
+ {\dodoubleempty\dodefinebuffer}
+
+\unexpanded\def\getbuffer
+ {\dodoubleempty\dogetbuffer}
+
+\def\dogetbuffer[#1][#2]%
+ {\ifsecondargument
+ \dodogetbuffer[#1][#2]%
+ \else
+ \dodogetbuffer[][#1]%
+ \fi}
+
+\def\dogetbufferasis{\readjobfile{\TEXbufferfile{\currentbuffer}}\donothing\donothing}%
+
+\def\dodogetbuffer[#1][#2]%
+ {\getvalue{\??bu#1\c!before}%
+ \dobuffer{16}{#2}\dogetbufferasis
+ \getvalue{\??bu#1\c!after}}
+
+\unexpanded\def\typebuffer
+ {\dodoubleempty\dotypebuffer}
+
+\def\dogetfilebuffer{\typefile{\TEXbufferfile{\currentbuffer}}}
+
+\def\dotypebuffer[#1][#2]%
+ {\iffirstargument
+ \dobuffer{17}{#1}\dogetfilebuffer
+ \else
+ \dobuffer{17}{#2}\dogetfilebuffer
+ \fi}
+
+\def\dobuffer#1#2#3%
+ {\doifelsenothing{#2}
+ {\dodobuffer#3\jobname}
+ {\processcommalist[#2]{\dodobuffer#3}}}
+
+\def\dodobuffer#1#2% command name
+ {\pushmacro\currentbuffer
+ \edef\currentbuffer{\ifcsname\??bu#2\c!number\endcsname def-\csname\??bu#2\c!number\endcsname\else#2\fi}%
+ \beginrestorecatcodes
+ #1%
+ \endrestorecatcodes
+ \popmacro\currentbuffer}
+
+\def\processTEXbuffer{\getbuffer} % handy
+
+% seldom used, only in a few projects that demanded more speed
+
+\def\dostartmemorybuffer
+ {\dosingleempty\dostartmemorybuffer}
+
+\long\def\dostartmemorybuffer[#1]#2\stopbuffer
+ {\setbuffer[#1]#2\endbuffer}
+
+\let\dostartfilebuffer\startbuffer
+
+\def\usememorybuffers{\let\startbuffer\dostartmemorybuffer}
+\def\usefilebuffers {\let\startbuffer\dostartfilebuffer}
+
+% this features is soldom used (complex examns where we need to fetch
+% special parts of a text
+%
+% this is not yet supported in mkiv (relatively easy to do but there
+% we don't have the par tags but need to grab 'm
+
+\def\skippedbufferparagraphs{0}
+
+\let\startbufferparagraph\relax
+\let\stopbufferparagraph \par % \relax
+
+\newcount\currentbufferparagraph
+
+\def\getbufferparagraphs
+ {\dodoubleempty\dogetbufferparagraphs}
+
+\def\dosetbufferoffset#1%
+ {\doifnumberelse{\getvalue{\??bu#1\c!paragraph}}
+ {\currentbufferparagraph-\getvalue{\??bu#1\c!paragraph}}
+ {\currentbufferparagraph \zerocount}%
+ \relax}
+
+\def\dogetbufferparagraphs[#1][#2]%
+ {\iffirstargument
+ \ifsecondargument
+ \dosetbufferoffset{#1}%
+ \doifelse{#2}\v!all
+ {\def\startbufferparagraph{\normalbufferparagraph{#1}}}
+ {\def\startbufferparagraph{\filterbufferparagraph{#1}{#2}}}%
+ \def\stopbufferparagraph{\dostopbufferparagraph{#1}}%
+ \def\next{\getparagraphedbuffer[#1]}%
+ \else
+ \dosetbufferoffset\empty
+ \def\startbufferparagraph{\filterbufferparagraph{}{#1}}%
+ \def\stopbufferparagraph{\dostopbufferparagraph{}}%
+ \def\next{\getparagraphedbuffer[]}%
+ \fi
+ \else
+ \dosetbufferoffset\empty
+ \def\startbufferparagraph{\normalbufferparagraph{}}%
+ \def\stopbufferparagraph{\dostopbufferparagraph{}}%
+ \def\next{\getparagraphedbuffer[]}%
+ \fi
+ \next}
+
+\def\dogetparagraphbuffer{\readjobfile{\TEXbufferfile{\currentbuffer}}\donothing\donothing}
+
+\def\getparagraphedbuffer[#1]%
+ {\dobuffer{16}{#1}\dogetparagraphbuffer}
+
+\def\dostopbufferparagraph#1%
+ {\getvalue{\??bu#1\c!after}\par}
+
+\def\dostartbufferparagraph#1%
+ {\par\getvalue{\??bu#1\c!before}}
+
+\def\normalbufferparagraph
+ {\advance\currentbufferparagraph \plusone
+ \ifnum\currentbufferparagraph>\zerocount
+ \expandafter\dostartbufferparagraph
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\filterbufferparagraph#1#2%
+ {\advance\currentbufferparagraph \plusone
+ \ifcase\currentbufferparagraph
+ \@EA\gobblebufferparagraph
+ \else
+ \doifinsetelse{\the\currentbufferparagraph}{#2}
+ {\@EA\dostartbufferparagraph}
+ {\@EA\fakebufferparagraph}%
+ \fi
+ {#1}}
+
+\long\def\gobblebufferparagraph#1#2\stopbufferparagraph
+ {}
+
+\def\fakebufferparagraph#1%
+ {\bgroup
+ \def\stopbufferparagraph{\dostopbufferparagraph{#1}\egroup\egroup}%
+ \setbox\scratchbox\vbox\bgroup\dostartbufferparagraph{#1}}
+
+% definitions
+
+\definebuffer[\v!hiding] \setupbuffer[\v!hiding][\c!local=\v!yes]
+
+\setupbuffer
+ [\c!paragraph=\v!no,
+ \c!before=,
+ \c!after=]
+
+\protect \endinput
diff --git a/tex/context/base/buff-ini.mkiv b/tex/context/base/buff-ini.mkiv
new file mode 100644
index 000000000..86b0fa3c5
--- /dev/null
+++ b/tex/context/base/buff-ini.mkiv
@@ -0,0 +1,355 @@
+%D \module
+%D [ file=buff-ini, % was core-buf, % blocks are moved to core-blk
+%D version=2000.01.05,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Buffers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Buffer Macros / Buffers}
+
+\registerctxluafile{buff-ini}{1.001}
+
+% todo:
+%
+% \startluacode
+% local locations = { }
+% function document.set_number(name)
+% locations[name] = {
+% line = status.linenumber,
+% file = status.filename
+% }
+% end
+% function document.add_number(name)
+% local b, l = buffers.raw(name), locations[name]
+% if b and l then
+% for i=1,#b do
+% b[i] = string.gsub(b[i],"# line: ","# line: " .. l.line + 2)
+% end
+% end
+% end
+% \stopluacode
+%
+% \starttext
+%
+% \ctxlua{document.set_number("oeps")}
+% \startbuffer[oeps]
+% # line:
+%
+% test
+% test
+% \stopbuffer
+% \ctxlua{document.add_number("oeps")}
+%
+% \typebuffer[oeps]
+%
+% \stoptext
+
+\ifdefined\doinitializeverbatim \else% temp hack
+ \def\doinitializeverbatim{\tttf}
+\fi
+
+\unprotect
+
+\chardef\buffernestmode\plusone % 0: not nested, 1: startbuffer nested, 2: all buffers nested
+
+\newif\ifsegmentatebuffer
+\newif\ifemptybufferline
+
+\def\currentbuffer{\jobname}
+
+\def\setcurrentbuffer#1%
+ {\doifelsenothing{#1}{\edef\currentbuffer{\jobname}}{\edef\currentbuffer{#1}}}
+
+\def\resetbuffer
+ {\dosingleempty\doresetbuffer}
+
+\def\doresetbuffer[#1]%
+ {\begingroup
+ \setcurrentbuffer{#1}%
+ \ctxlua{buffers.erase("\currentbuffer")}%
+ \endgroup}
+
+\def\dostartbuffer
+ {\bgroup
+ \obeylines % nodig, anders gaat 't fout als direct \starttable (bv)
+ \doquadrupleempty\dodostartbuffer}
+
+\def\dodostartbuffer[#1][#2][#3][#4]% upward compatible
+ {\iffourthargument
+ \def\next{\dododostartbuffer{#1}{#2}{#3}{#4}}%
+ \else
+ \def\next{\dododostartbuffer {}{#1}{#2}{#3}}%
+ \fi
+ \next}
+
+\def\dododostartbuffer#1#2#3#4%
+ {%\showmessage\m!systems{15}{#2}%
+ \doifelsevalue{\??bu#1\c!paragraph}\v!yes
+ {\segmentatebuffertrue} % todo in mkiv
+ {\doifnumberelse{\getvalue{\??bu#1\c!paragraph}}\segmentatebuffertrue\segmentatebufferfalse}%
+ \doifvalue{\??bu#1\c!local}\v!yes
+ {\chardef\buffernestmode\plustwo}% permit nesting
+ \setcurrentbuffer{#2}%
+ \doifelsenothing{#4}
+ {\normalexpanded{\noexpand\setbuffercapsules{\e!start\v!buffer}{\e!stop\v!buffer}}%
+ \letvalue\bufferstop\relax}
+ %{\@EA\setbuffercapsules\@EA{\csname#3\@EA\endcsname\@EA}\@EA{\csname#4\endcsname}}% if we strip later
+ {\setbuffercapsules{#3}{#4}}%
+ \normalexpanded{\noexpand\dodowithbuffer
+ {\currentbuffer}
+ {\bufferstart}
+ {\bufferstop}
+ {\donothing}
+ {\egroup
+ \noexpand\getvalue{\bufferstop}}}}
+
+\letvalue{\e!start\v!buffer}\dostartbuffer
+
+\let\endbuffer\undefined % to please the dep parser
+
+\def\dowithbuffer#1#2#3% name, startsequence, stopsequence, before, after
+ {\setbuffercapsules{#2}{#3}%
+ \normalexpanded{\noexpand\dodowithbuffer{#1}{\bufferstart}{\bufferstop}}}
+
+\long\def\dodowithbuffer#1#2#3#4#5% name, startsequence, stopsequence, before, after
+ {#4%
+ \bgroup
+ \setcatcodetable \vrbcatcodes
+ \catcode`\\=12
+ \ctxlua{buffers.erase("#1")}%
+ \long\def\nododowithbuffer
+ {\egroup
+ #5}%
+ \long\def\dododowithbuffer##1#3% is detokenize needed? TEST
+ {\ctxlua
+ {buffers.grab("#1","#2","#3",\!!bs\detokenize{##1}\!!es)}
+ \dododowithbuffer
+ \nododowithbuffer}%
+ \dododowithbuffer}
+
+\def\setbuffercapsules#1#2% \scantextokens not needed (had a reason at some point)
+ {\edef\bufferstart{#1}\edef\bufferstart{\scantextokens\expandafter{\bufferstart}}%
+ \edef\bufferstop {#2}\edef\bufferstop {\scantextokens\expandafter{\bufferstop }}}
+
+\def\setbuffer
+ {\dosingleempty\dosetbuffer}
+
+\long\def\dosetbuffer[#1]#2\endbuffer % seldom used so we just pass #2
+ {\begingroup
+ \setcurrentbuffer{#1}%
+ \ctxlua{buffers.set("\currentbuffer", \!!bs\detokenize{#2}\!!es)}%
+ \endgroup}
+
+\unexpanded\def\setupbuffer
+ {\dodoubleempty\dosetupbuffer}
+
+\def\dosetupbuffer[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??bu#1][#2]%
+ \else
+ \getparameters[\??bu][#1]%
+ \fi}
+
+\def\dodefinebuffer[#1][#2]%
+ {\iffirstargument % else problems
+ \doglobal\increment\nofdefinedbuffers
+ \letvalue{\??bu#1\c!number }\nofdefinedbuffers
+ \letvalue{\??bu#1\c!paragraph}\v!no
+ \setuevalue{\e!start#1}{\noexpand\dostartbuffer[#1][def-\nofdefinedbuffers][\e!start#1][\e!stop#1]}% maybe also relax stop
+ \setuevalue{\e!get #1}{\noexpand\dogetbuffer [#1][def-\nofdefinedbuffers]}%
+ \setuevalue{\e!type #1}{\noexpand\dotypebuffer [#1][def-\nofdefinedbuffers]}%
+ \getparameters[\??bu#1][#2]%
+ \fi}
+
+\unexpanded\def\definebuffer
+ {\dodoubleempty\dodefinebuffer}
+
+\def\thebuffernumber#1%
+ {\csname\??bu#1\c!number\endcsname}
+
+\unexpanded\def\getbuffer
+ {\dodoubleempty\dogetbuffer}
+
+\def\dogetbuffer[#1][#2]%
+ {\ifsecondargument
+ \dodogetbuffer[#1][#2]%
+ \else
+ \dodogetbuffer[][#1]%
+ \fi}
+
+\def\dogetbufferasis{\ctxlua{buffers.get("\currentbuffer")}}
+
+\def\dodogetbuffer[#1][#2]%
+ {\getvalue{\??bu#1\c!before}%
+ \dobuffer{16}{#2}\dogetbufferasis
+ \getvalue{\??bu#1\c!after}}
+
+\unexpanded\def\typebuffer
+ {\dodoubleempty\dotypebuffer}
+
+\def\doprocessbufferverbatim
+ {\doinitializeverbatim
+ \ctxlua{buffers.type("\currentbuffer","\typingparameter\c!strip")}}
+
+\def\doprocessbufferlinesverbatim#1#2#3%
+ {#2%
+ % todo, set up numbers
+ \doinitializeverbatim
+ \ctxlua{buffers.type("\currentbuffer","\typingparameter\c!strip")}
+ #3}
+
+\def\doifelsebuffer#1%
+ {\ctxlua{buffers.doifelsebuffer("#1")}}
+
+\def\dodotypebuffer#1#2#3% see dodotypefile
+ {\doifelsebuffer{#3}
+ {\dosometyping{#1}{#2}{#3}\doprocessbufferverbatim\doprocessbufferlinesverbatim}
+ {\reporttypingerror{#3}}}
+
+\def\dotypefilebuffer{\dodotypebuffer{\v!file}{}{\currentbuffer}}%
+
+\def\dotypebuffer[#1][#2]%
+ {\iffirstargument
+ \dobuffer{17}{#1}\dotypefilebuffer
+ \else
+ \dobuffer{17}{#2}\dotypefilebuffer
+ \fi}
+
+\def\dobuffer#1#2#3%
+ {\doifelsenothing{#2}
+ {\dodobuffer#3\jobname}
+ {\processcommalist[#2]{\dodobuffer#3}}}
+
+\def\dodobuffer#1#2% command name
+ {\pushmacro\currentbuffer
+ \edef\currentbuffer{\ifcsname\??bu#2\c!number\endcsname def-\csname\??bu#2\c!number\endcsname\else#2\fi}%
+ #1%
+ \popmacro\currentbuffer}
+
+\def\processTEXbuffer{\getbuffer} % handy
+
+% extras:
+
+\def\inspectbuffer
+ {\dosingleempty\doinspectbuffer}
+
+\def\doinspectbuffer[#1]%
+ {\setcurrentbuffer{#1}%
+ \ctxlua{buffers.inspect("\currentbuffer")}}
+
+% seldom used, only in a few projects that demanded more speed
+
+\let\usememorybuffers\relax
+\let\usefilebuffers \relax
+
+% this features is soldom used (complex examns where we need to fetch
+% special parts of a text
+%
+% this is not yet supported in mkiv (relatively easy to do but there
+% we don't have the par tags but need to grab 'm
+
+\def\skippedbufferparagraphs{0}
+
+\let\startbufferparagraph\relax
+\let\stopbufferparagraph \par % \relax
+
+\newcount\currentbufferparagraph
+
+\def\getbufferparagraphs
+ {\dodoubleempty\dogetbufferparagraphs}
+
+\def\dosetbufferoffset#1%
+ {\doifnumberelse{\getvalue{\??bu#1\c!paragraph}}
+ {\currentbufferparagraph-\getvalue{\??bu#1\c!paragraph}}
+ {\currentbufferparagraph \zerocount}%
+ \relax}
+
+\def\dogetbufferparagraphs[#1][#2]%
+ {\iffirstargument
+ \ifsecondargument
+ \dosetbufferoffset{#1}%
+ \doifelse{#2}\v!all
+ {\unexpanded\def\startbufferparagraph{\normalbufferparagraph{#1}}}
+ {\unexpanded\def\startbufferparagraph{\filterbufferparagraph{#1}{#2}}}%
+ \unexpanded\def\stopbufferparagraph{\dostopbufferparagraph{#1}}%
+ \def\next{\getparagraphedbuffer[#1]}%
+ \else
+ \dosetbufferoffset\empty
+ \unexpanded\def\startbufferparagraph{\filterbufferparagraph{}{#1}}%
+ \unexpanded\def\stopbufferparagraph{\dostopbufferparagraph{}}%
+ \def\next{\getparagraphedbuffer[]}%
+ \fi
+ \else
+ \dosetbufferoffset\empty
+ \unexpanded\def\startbufferparagraph{\normalbufferparagraph{}}%
+ \unexpanded\def\stopbufferparagraph{\dostopbufferparagraph{}}%
+ \def\next{\getparagraphedbuffer[]}%
+ \fi
+ \next}
+
+\def\dotypeparagraphbuffer{\ctxlua{buffers.get("\currentbuffer")}}
+
+\def\getparagraphedbuffer[#1]%
+ {\dobuffer{16}{#1}\dotypeparagraphbuffer}
+
+\def\dostopbufferparagraph#1%
+ {\getvalue{\??bu#1\c!after}\par}
+
+\def\dostartbufferparagraph#1%
+ {\par\getvalue{\??bu#1\c!before}}
+
+\def\normalbufferparagraph
+ {\advance\currentbufferparagraph \plusone
+ \ifnum\currentbufferparagraph>\zerocount
+ \expandafter\dostartbufferparagraph
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\filterbufferparagraph#1#2%
+ {\advance\currentbufferparagraph \plusone
+ \ifcase\currentbufferparagraph
+ \@EA\gobblebufferparagraph
+ \else
+ \doifinsetelse{\the\currentbufferparagraph}{#2}
+ {\@EA\dostartbufferparagraph}
+ {\@EA\fakebufferparagraph}%
+ \fi
+ {#1}}
+
+\long\def\gobblebufferparagraph#1#2\stopbufferparagraph
+ {}
+
+\def\fakebufferparagraph#1%
+ {\bgroup
+ \unexpanded\def\stopbufferparagraph{\dostopbufferparagraph{#1}\egroup\egroup}%
+ \setbox\scratchbox\vbox\bgroup\dostartbufferparagraph{#1}}
+
+% definitions
+
+\definebuffer[\v!hiding] \setupbuffer[\v!hiding][\c!local=\v!yes]
+
+\setupbuffer
+ [\c!paragraph=\v!no,
+ \c!before=,
+ \c!after=]
+
+% only mkiv:
+%
+% \startbuffer[x]
+% x
+% \stopbuffer
+%
+% \savebuffer[x][temp.log]
+
+\unexpanded\def\savebuffer{\dodoubleempty\dosavebuffer}
+
+\def\dosavebuffer[#1][#2]{\ctxlua{commands.savebuffer("#1","#2")}}
+
+\protect \endinput
diff --git a/tex/context/base/buff-ver.mkii b/tex/context/base/buff-ver.mkii
new file mode 100644
index 000000000..e7ad5474f
--- /dev/null
+++ b/tex/context/base/buff-ver.mkii
@@ -0,0 +1,1340 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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 Buffer Macros / Verbatim}
+
+\unprotect
+
+\ifx\startlinenumbering\undefined \let\startlinenumbering\relax \fi
+\ifx\stoplinenumbering \undefined \let\stoplinenumbering\relax \fi
+\ifx\setuplinenumbering\undefined \def\setuplinenumbering[#1]{} \fi
+
+% \type{ char} geeft bagger
+
+%D We are going to embed the general verbatim support macros in
+%D a proper environment. First we show the common setup
+%D macro, so we know what features are supported. The options
+%D are hooked into the support macros via the \type{\obey}
+%D macros.
+
+\newif\ifslantedtypeactivated
+\newif\ifslantedtypepermitted
+
+\def\switchslantedtype
+ {\ifslantedtypepermitted
+ \ifslantedtypeactivated
+ \slantedtypeactivatedfalse\tttf
+ \else
+ \slantedtypeactivatedtrue\ttsl
+ \fi
+ \fi}
+
+\newprettytrue % movet to here from cont-sys.tex
+
+\def\prettyidentifier {TEX}
+\def\prettypalet {}
+
+\def\installprettytype
+ {\dodoubleargument\doinstallprettytype}
+
+\def\doinstallprettytype[#1][#2]% map #1 onto #2
+ {\uppercasestring#1\to\asciia
+ \uppercasestring#2\to\asciib
+ \setevalue{\??ty\??ty\asciia}{\asciib}}
+
+\def\setupprettiesintype#1%
+ {\uppercasestring#1\to\ascii
+ \edef\prettyidentifier{\executeifdefined{\??ty\??ty\ascii}{TEX}}%
+ \doifundefined{setuppretty\prettyidentifier type}%
+ {\startnointerference
+ \restorecatcodes % also needed when loading during \newpretty
+ \startreadingfile % restore < and > if needed
+ \lowercasestring verb-\prettyidentifier\to\filename
+ \readsysfile{\filename.mkii}\donothing\donothing
+ \stopreadingfile
+ \stopnointerference}%
+ \doifdefinedelse{setuppretty\prettyidentifier type}%
+ {\let\uncatcodecharacters\uncatcodeallcharacters % ugly, should be switch / todo
+ \def\dosetupprettytype{\getvalue{setuppretty\prettyidentifier type}}}
+ {\let\dosetupprettytype\relax}}
+
+\def\setupprettytype{\dosetupprettytype}
+
+% \def\setupcommonverbatim
+% {\recatcodeuppercharactersfalse % obey regime / encoding
+% %
+% \let\prettyidentifier\s!default
+% %
+% \doifelse{\typingparameter\c!text}\v!yes
+% \naturaltextexttrue
+% \naturaltextextfalse
+% \def\prettyidentifierfont{\typingparameter\c!icommand}%
+% \def\prettyvariablefont {\typingparameter\c!vcommand}%
+% \def\prettynaturalfont {\typingparameter\c!ccommand}%
+% %
+% \doif{\typingparameter\c!space}\v!on
+% {\def\obeyspaces{\setcontrolspaces}}%
+% \doif{\typingparameter\c!page }\v!no
+% {\def\obeypages {\ignorepages}}%
+% %
+% \doifelse{\typingparameter\c!tab}\v!yes
+% {\def\obeytabs{\settabskips}}%
+% {\doif{\typingparameter\c!tab}\s!ascii
+% {\chardef\tabskipmode\plustwo % quit on >127
+% \def\obeytabs{\settabskips}}}%
+% %
+% \ignorehyphens % default
+% \ExpandFirstAfter\processaction
+% [\typingparameter\c!lines]
+% [ \v!yes=>\obeybreakpoints,
+% \v!hyphenated=>\obeyhyphens]%
+% \processaction
+% [\typingparameter\c!empty]
+% [\v!yes=>\obeyemptylines,
+% \v!all=>\obeyallemptylines]%
+% %
+% \ExpandFirstAfter\processaction
+% [\typingparameter\c!option]
+% [ \v!none=>\let\obeycharacters\relax,
+% \v!color=>\setupprettiesintype{TEX}%
+% \let\obeycharacters\setupprettytype
+% \let\obeytabs\ignoretabs,
+% \v!normal=>\let\obeycharacters\setupgroupedtype,
+% \v!commands=>\def\obeycharacters{\setupcommandsintype}% \let
+% \let\obeytabs\ignoretabs,
+% \v!slanted=>\let\obeycharacters\setupslantedtype
+% \let\obeytabs\ignoretabs,
+% \s!unknown=>\setupprettiesintype{\typingparameter\c!option}%
+% \let\obeycharacters\setupprettytype
+% \let\obeytabs\ignoretabs]%
+% \doifnumberelse{\typingparameter\c!tab}
+% {\def\obeytabs{\setfixedtabskips{\typingparameter\c!tab}}}%
+% \donothing
+% %\def\verbatimfont{\typingparameter\c!style\normalnoligatures\font}%
+% % more generic, but beware of the \redoconvertfont (else no typing in titles and such)
+% \def\verbatimfont{\redoconvertfont\dosetfontattribute{\currenttypingclass\currenttyping}\c!style\normalnoligatures\font}%
+% \setupverbatimcolor}
+
+\setvalue{\??tp:\c!lines:\v!yes }{\obeybreakpoints}
+\setvalue{\??tp:\c!lines:\v!hyphenated}{\obeyhyphens}
+
+\setvalue{\??tp:\c!empty:\v!yes }{\obeyemptylines}
+\setvalue{\??tp:\c!empty:\v!all }{\obeyallemptylines}
+
+\setvalue{\??tp:\c!option:\v!none }{\let\obeycharacters\relax}
+\setvalue{\??tp:\c!option:\v!color }{\setupprettiesintype{TEX}%
+ \let\obeycharacters\setupprettytype
+ \let\obeytabs\ignoretabs}
+\setvalue{\??tp:\c!option:\v!normal }{\let\obeycharacters\setupgroupedtype}
+\setvalue{\??tp:\c!option:\v!commands }{\def\obeycharacters{\setupcommandsintype}%
+ \let\obeytabs\ignoretabs}
+\setvalue{\??tp:\c!option:\v!slanted }{\let\obeycharacters\setupslantedtype
+ \let\obeytabs\ignoretabs}
+\setvalue{\??tp:\c!option:\s!unknown }{\setupprettiesintype{\typingparameter\c!option}%
+ \let\obeycharacters\setupprettytype
+ \let\obeytabs\ignoretabs}
+
+\def\setupcommonverbatim
+ {\recatcodeuppercharactersfalse % obey regime / encoding
+ %
+ \let\prettyidentifier\s!default
+ %
+ \doifelse{\typingparameter\c!text}\v!yes
+ \naturaltextexttrue
+ \naturaltextextfalse
+ \def\prettyidentifierfont{\typingparameter\c!icommand}%
+ \def\prettyvariablefont {\typingparameter\c!vcommand}%
+ \def\prettynaturalfont {\typingparameter\c!ccommand}%
+ %
+ \doif{\typingparameter\c!space}\v!on
+ {\def\obeyspaces{\setcontrolspaces}}%
+ \doif{\typingparameter\c!page }\v!no
+ {\def\obeypages {\ignorepages}}%
+ %
+ \doifelse{\typingparameter\c!tab}\v!yes
+ {\def\obeytabs{\settabskips}}%
+ {\doif{\typingparameter\c!tab}\s!ascii % not needed in mkiv
+ {\chardef\tabskipmode\plustwo % quit on >127
+ \def\obeytabs{\settabskips}}}%
+ %
+ \ignorehyphens % default
+ \getvalue{\??tp:\c!lines:\typingparameter\c!lines}%
+ \getvalue{\??tp:\c!empty:\typingparameter\c!empty}%
+ \getvalue{\??tp:\c!option:\ifcsname\??tp:\c!option:\typingparameter\c!option\endcsname\typingparameter\c!option\else\s!unknown\fi}%
+ \doifnumberelse{\typingparameter\c!tab}
+ {\def\obeytabs{\setfixedtabskips{\typingparameter\c!tab}}}%
+ \donothing
+ %\def\verbatimfont{\typingparameter\c!style\normalnoligatures\font}%
+ % more generic, but beware of the \redoconvertfont (else no typing in titles and such)
+ \def\verbatimfont{\redoconvertfont\dosetfontattribute{\currenttypingclass\currenttyping}\c!style\normalnoligatures\font}%
+ \setupverbatimcolor}
+
+% BEWARE: the noligatures will globally change the verbatim font's behaviour
+
+% test case:
+%
+% \definetype[typeTEX][option=tex]
+%
+% \typeTEX|\example---oeps|. this---ligates---again.
+% \typeTEX{\example---oeps}. this---ligates---again.
+% \type {\example---oeps}. this---ligates---again.
+
+\def\setupcommandsintype % can also be \string\
+ {\setupgroupedtype
+ \edef\\{\typingparameter\c!escape}%
+ \letvalue{\\}=\\% for instance \/=/
+ \@EA\catcode\@EA`\\=\@@escape
+ \def\BTEX##1\ETEX##2% ##2 gobbles active space
+ {\naturaltextext##1\unskip\relax}}
+
+\def\setupslantedtype
+ {\slantedtypepermittedtrue\setupgroupedtype}
+
+\ifx\setupprettytype \undefined \let\setupprettytype \relax \fi
+\ifx\setupslantedtype \undefined \let\setupslantedtype \relax \fi
+\ifx\setupgroupedtype \undefined \let\setupgroupedtype \relax \fi
+\ifx\normalnoligatures\undefined \let\normalnoligatures\gobbleoneargument \fi
+
+%D The verbatim commands have a rather long and turbulent
+%D history. Most users of \CONTEXT\ probably will never use
+%D some of the features, but I've kept in mind that when one is
+%D writing a users manual, about everything can and undoubtly
+%D will be subject to a verbatim treatment.
+%D
+%D Verbatim command are very sensitive to argument processing,
+%D which is a direct result of the \CATCODES\ being fixed at
+%D reading time. With our growing understanding of \TEX,
+%D especially of the mechanism that can be used for looking
+%D ahead and manipulating \CATCODES, the verbatim support
+%D became more and more advanced and natural.
+%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
+%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
+%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.
+
+% todo: we can use \letter... here:
+
+\def\lesscharacter {<}
+\def\morecharacter {>}
+
+\chardef\texescape = `\\
+\chardef\leftargument = `\{
+\chardef\rightargument = `\}
+
+%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.
+
+% \starttyping
+% normal: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par
+% normal: \par \type{xx<..xx.. >..>xx} \par \type{<....>} \par \type{<....>}
+% \setuptype[option=slanted]
+% slanted: \par \type{xx<<..sl..<> xx>>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<>..>> \par
+% slanted: \par \type{xx<<..sl.. xx>..sl..>>xx} \par \type<<..xx..>> \par \type<<....>> \par
+% \setuptype[option=none]
+% none: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par
+% \stoptyping
+
+%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 The following lines show what happens when we set
+%D \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
+
+\unexpanded\def\type{\dotype\empty}
+
+% not that fast but catches \type{\command} % nothing more after \command
+%
+% \setupcolors[state=start]
+% \setuptype[option=TEX]
+% \setupcolors[textcolor=red]
+%
+% The options \type{before=\startsolutionbackground } and
+% \type{after=\stopsolutionbackground} take care of putting a frame,
+% which can
+%
+% {\blue The options \type{before=\startsolutionbackground } and
+% \type{after=\stopsolutionbackground} take care of putting a frame,
+% which} can
+
+\def\resumecoloraftergroup
+ {\localstartcolor[\s!black]%
+ \localstartcolor[\maintextcolor]%
+ \aftergroup\localstopcolor
+ \aftergroup\localstopcolor}
+
+% the rather messy \type command
+
+\def\dotype#1% was \dotype
+ {\bgroup
+ \resumecoloraftergroup % a problem is that we can still be in color mode, tricky hack
+ \begstrut % new, enables leading space in \type { abc } at par start / begstrut else no hyphenation
+ \let\currenttypingclass\??ty
+ \edef\currenttyping{#1}%
+ \catcode`\<=\@@other
+ \catcode`\>=\@@other
+ \futurelet\next\dodotype}
+
+\def\dodotypeA
+ {\initializetype
+ \initializetypegrouping
+ \verbatimfont
+ \verbatimcolor
+ \afterassignment\protectfirsttype\let\next=}
+
+\def\dodotypeB
+ {\initializetype
+ \setupnotypegrouping
+ \verbatimfont
+ \verbatimcolor
+ \let\next=}
+
+\def\dodotypeC<#1%
+ {\initializetype
+ \verbatimfont
+ \verbatimcolor
+ \if#1<%
+ \@EA\setupalternativetypegrouping
+ \else
+ \@EA#1%
+ \fi}
+
+\def\dodotypeD#1%
+ {\initializetype
+ \verbatimfont
+ \verbatimcolor
+ \catcode`#1=\@@endgroup}
+
+\def\dodotype
+ {\ifx\next\bgroup
+ \@EA\dodotypeA
+ \else\if\next<%
+ \doifelse{\typingparameter\c!option}\v!none
+ {\@EAEAEA\dodotypeB}{\@EAEAEA\dodotypeC}%
+ \else
+ \@EAEAEA\dodotypeD
+ \fi\fi}
+
+% The next one is safe for: \def\xx#1{\type{#1}} \xx{\ifx}
+
+\let\protectedfirsttype\string % \relax for special cases
+
+\bgroup
+\catcode`\<=\active
+\catcode`\>=\active
+\gdef\doprotectfirsttype
+ {\normalifx\next<%
+ \endrobusttest \let\next\relax
+ \normalelse\normalifx\next\bgroup
+ \endrobusttest \let\next\relax
+ \normalelse\normalifx\next\egroup % takes care of \type{}
+ \endrobusttest \let\next\relax
+ \normalelse\normalifx\next\activeleftargument
+ \endrobusttest \let\next\relax
+ \normalelse
+ \endrobusttest \let\next\protectedfirsttype
+ \normalfi\normalfi\normalfi\normalfi
+ \next}
+\egroup
+
+\def\protectfirsttype
+ {\beginrobusttest
+ \futurelet\next\doprotectfirsttype}
+
+% Verbatim does not work when passed as an argument, so here is a
+% workaround. Beware, spaces are introduced after a \type {\csname}.
+
+\chardef\recodeverbatimmode\zerocount % 0=nothing 1=rescan 2=autorescan
+
+% \appendtoks \chardef\recodeverbatimmode\plustwo \to \everytabulate
+% \appendtoks \chardef\recodeverbatimmode\plustwo \to \everytable
+
+\def\dodotypeA
+ {\initializetype
+ \initializetypegrouping
+ \verbatimfont
+ \verbatimcolor
+ \ifcase\recodeverbatimmode
+ \@EA\dodotypeAA
+ \or
+ \@EA\dodotypeAB
+ \or
+ \ifnum\catcode`\{=\@@active
+ \@EAEAEA\dodotypeAB
+ \else
+ \@EAEAEA\dodotypeAA
+ \fi
+ \else
+ \@EA\dodotypeAA
+ \fi}
+
+\def\dodotypeAA
+ {\afterassignment\protectfirsttype\let\next=}
+
+\def\dodotypeAB
+ {\bgroup
+ \catcode`\}=\@@endgroup
+ \catcode`\{=\@@begingroup
+ \afterassignment\redotypeAB\global\globalscratchtoks}
+
+\def\redotypeAB
+ {\egroup
+ \expandafter\defconvertedargument\expandafter\ascii\expandafter{\the\globalscratchtoks}% == \edefconvertedargument\ascii{\the\globalscratchtoks}%
+ \ifx\scantokens\undefined\ascii\else\everyeof{\hskip-\spaceskip}\scantokens\expandafter{\ascii}\fi
+ \egroup}
+
+\bgroup
+\catcode`\[=\@@begingroup
+\catcode`\]=\@@endgroup
+\catcode`\{=\@@active
+\catcode`\}=\@@active
+\gdef\initializetypegrouping
+ [\ifnum\catcode`\{=\@@active
+ \let\normalactivebgroup{%
+ \let\normalactiveegroup}%
+ \else
+ \catcode`\{=\@@active
+ \catcode`\}=\@@active
+ \let\normalactivebgroup\leftargument
+ \let\normalactiveegroup\rightargument
+ \fi
+ \def\activeleftargument
+ [\bgroup
+ \catcode`\}=\@@active
+ \let}\activerightargument
+ \normalactivebgroup]%
+ \def\activerightargument
+ [\normalactiveegroup
+ \egroup]%
+ \let{=\activeleftargument
+ % not \let}=\egroup, otherwise things go wrong in alignments (???)
+ \catcode`\}=\@@endgroup]
+\egroup
+
+\bgroup
+\catcode`\<=\@@active
+\catcode`\>=\@@active
+\gdef\setupalternativetypegrouping
+ {\catcode`\<=\@@active
+ \catcode`\>=\@@active
+ \def\doless
+ {\ifx<\next
+ \def\next
+ {\bgroup\switchslantedtype
+ \let\next=}%
+ \else
+ \let\next\lesscharacter
+ \fi
+ \next}%
+ \def\domore
+ {\ifx>\next
+ \def\next
+ {\egroup
+ \let\next=}%
+ \else
+ \let\next\morecharacter
+ \fi
+ \next}%
+ \def<{\futurelet\next\doless}%
+ \def>{\futurelet\next\domore}}
+\egroup
+
+\def\setupnotypegrouping
+ {\catcode`\<=\@@begingroup
+ \catcode`\>=\@@endgroup}
+
+\def\doenterdoublelesstype
+ {\ifx\next\egroup
+ \lesscharacter\null\lesscharacter
+ \else
+ \bgroup\switchslantedtype
+ \let\doenterdoublemoretype\egroup
+ \fi}
+
+\def\doenterdoublemoretype
+ {\def\doenterdoubletype
+ {\ifx\next\egroup
+ \morecharacter\null\morecharacter
+ \fi}}
+
+\bgroup
+\catcode`\<=\@@active
+\catcode`\>=\@@active
+\gdef\setupgroupedtype
+ {\catcode`\<=\@@active
+ \catcode`\>=\@@active
+ \def\doless
+ {\ifx<\next
+ \def\next
+ {\def\enterdoubletype{\futurelet\next\doenterdoublelesstype}%
+ \afterassignment\enterdoubletype
+ \let\next=}%
+ \else
+ \let\next\lesscharacter
+ \fi
+ \next}%
+ \def\domore
+ {\ifx>\next
+ \def\next
+ {\def\enterdoubletype{\futurelet\next\doenterdoublemoretype}%
+ \afterassignment\enterdoubletype
+ \let\next=}%
+ \else
+ \let\next\morecharacter
+ \fi
+ \next}%
+ \def<{\futurelet\next\doless}%
+ \def>{\futurelet\next\domore}}
+\egroup
+
+%D The neccessary initializations are done by calling
+%D \type{\initializetype} which in return calls for the support
+%D macro \type{\setupinlineverbatim}.
+
+\def\initializetype
+ {\let\obeylines\ignorelines
+ \setupcommonverbatim
+ \setupinlineverbatim}
+
+%D \macros
+%D {setuptype}
+%D
+%D Some characteristics of \type{\type} can be set up by:
+
+\def\setuptype
+ {\dodoubleempty\dosetuptype}
+
+\def\dosetuptype[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??ty#1][#2]%
+ \else
+ \getparameters[\??ty][#1]%
+ \fi}
+
+%D \macros
+%D {typ,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.
+
+\def\obeyhyphens
+ {\def\obeyedspace {\hskip\interwordspace\relax}% better than spaceskip
+ \def\controlspace{\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax}%
+ \spaceskip.25em\relax} % hm a bit of stretch !
+
+\def\obeybreakpoints
+ {\ignorehyphens
+ \veryraggedright}
+
+\def\ignorehyphens
+ {% \nohyphens % forgotten when no \par
+ \normallanguage\minusone % fails as the font redoes the language
+ \def\obeyedspace {\hskip\interwordspace\relax}% better than spaceskip
+ \def\controlspace{\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax}%
+ \spaceskip.5em\relax}
+
+
+\unexpanded\def\typ
+ {\bgroup
+ \let\@@tylines\v!hyphenated
+ \futurelet\next\dodotype}
+
+%D \macros
+%D {tex,arg,mat,dis}
+%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
+%D The next implementation is more clear but less versatile,
+%D so we treated it for a beter one.
+%D
+%D \starttyping
+%D \def\dospecialtype#1#2%
+%D {\bgroup
+%D \initializetype
+%D \catcode`\{=\@@begingroup
+%D \catcode`\}=\@@endgroup
+%D \def\dospecialtype%
+%D {\def\dospecialtype{#2\egroup}%
+%D \bgroup
+%D \aftergroup\dospecialtype
+%D #1}%
+%D \afterassignment\dospecialtype
+%D \let\next=}
+%D
+%D \unexpanded\def\tex{\dospecialtype\texescape\relax}
+%D \unexpanded\def\arg{\dospecialtype\leftargument\rightargument}
+%D \unexpanded\def\mat{\dospecialtype\$\$}
+%D \unexpanded\def\dis{\dospecialtype{\$\$}{\$\$}}
+%D \stoptyping
+
+\def\setgroupedtype
+ {\let\currenttypingclass\??ty
+ \initializetype
+ \verbatimcolor
+ %\setcatcodetable \typcatcodesa
+ \catcode`\{=\@@begingroup
+ \catcode`\}=\@@endgroup}
+
+\unexpanded\def\tex{\groupedcommand{\setgroupedtype\texescape}{\relax}}
+\unexpanded\def\arg{\groupedcommand{\setgroupedtype\leftargument}{\rightargument}}
+\unexpanded\def\mat{\groupedcommand{\setgroupedtype\$}{\$}}
+\unexpanded\def\dis{\groupedcommand{\setgroupedtype\$\$}{\$\$}}
+
+\let\normaltexttex\tex
+\let\normaltextarg\arg
+\let\normaltextmat\mat
+\let\normaltextdis\dis
+
+%D \macros
+%D {starttyping}
+%D
+%D Display verbatim is realized far more easy, which is mostly
+%D due to the fact that we use \type{\stop...} as delimiter.
+%D The implementation inherits some features, for instance the
+%D support of linenumbering, which can best be studied in the
+%D documented support module.
+
+\let\currenttyping \empty
+\let\currenttypingclass\??ty % saveguard
+
+% \def\typingparameter#1%
+% {\executeifdefined
+% {\currenttypingclass\currenttyping#1}%
+% {\executeifdefined{\currenttypingclass#1}\empty}}
+
+\def\typingparameter#1%
+ {\ifcsname\currenttypingclass\currenttyping#1\endcsname
+ \csname\currenttypingclass\currenttyping#1\endcsname
+ \else\ifcsname\currenttypingclass#1\endcsname
+ \csname\currenttypingclass#1\endcsname
+ \fi\fi}
+
+\def\settypingparameter#1#2%
+ {\setvalue{\currenttypingclass\currenttyping#1}{#2}}
+
+\def\setxtypingparameter#1#2%
+ {\setxvalue{\currenttypingclass\currenttyping#1}{#2}}
+
+% \def\initializetyping
+% {%\donefalse
+% \switchtobodyfont[\typingparameter\c!bodyfont]%
+% \donefalse
+% \scratchskip\typingparameter\c!oddmargin\relax
+% \ifzeropt\scratchskip\else\donetrue\fi
+% \scratchskip\typingparameter\c!evenmargin\relax
+% \ifzeropt\scratchskip\else\donetrue\fi
+% \ifdone
+% \def\doopenupverbatimline
+% {\getpagestatus
+% \ifrightpage
+% \hskip\typingparameter\c!oddmargin\relax
+% \else
+% \hskip\typingparameter\c!evenmargin\relax
+% \fi}%
+% \else
+% \doadaptleftskip{\typingparameter\c!margin}%
+% \fi
+% \doifdefinedelse{\??bo\typingparameter\c!blank}
+% {\edef\!!stringa{\csname\??bo\typingparameter\c!blank\endcsname}}
+% {\edef\!!stringa{\typingparameter\c!blank}}%
+% \processaction
+% [\!!stringa]
+% [ \v!standard=>\scratchskip\ctxparskip,
+% \v!small=>\scratchskip\blankokleinmaat,
+% \v!medium=>\scratchskip\blankomiddelmaat,
+% \v!big=>\scratchskip\blankogrootmaat,
+% \v!halfline=>\scratchskip.5\baselineskip,
+% \v!line=>\scratchskip\baselineskip,
+% \v!none=>\scratchskip\zeropoint,
+% \s!unknown=>\scratchskip\commalistelement]%
+% \ifgridsnapping
+% \ifdim\scratchskip=.5\baselineskip\relax
+% \edef\verbatimbaselineskip{\the\scratchskip}% new
+% \else
+% \edef\verbatimbaselineskip{\the\baselineskip}%
+% \fi
+% \else
+% \edef\verbatimbaselineskip{\the\scratchskip}%
+% \fi
+% \setupcommonverbatim}
+
+\setvalue{\??tp:\c!blank:\v!standard}{\ctxparskip}
+\setvalue{\??tp:\c!blank:\v!small }{\blankokleinmaat}
+\setvalue{\??tp:\c!blank:\v!medium }{\blankomiddelmaat}
+\setvalue{\??tp:\c!blank:\v!big }{\blankogrootmaat}
+\setvalue{\??tp:\c!blank:\v!halfline}{.5\baselineskip}
+\setvalue{\??tp:\c!blank:\v!line }{\baselineskip}
+\setvalue{\??tp:\c!blank:\v!none }{\zeropoint}
+
+\def\initializetyping
+ {%\donefalse
+ \switchtobodyfont[\typingparameter\c!bodyfont]%
+ \donefalse
+ \scratchskip\typingparameter\c!oddmargin\relax
+ \ifzeropt\scratchskip\else\donetrue\fi
+ \scratchskip\typingparameter\c!evenmargin\relax
+ \ifzeropt\scratchskip\else\donetrue\fi
+ \ifdone
+ \def\doopenupverbatimline
+ {\getpagestatus
+ \ifrightpage
+ \hskip\typingparameter\c!oddmargin\relax
+ \else
+ \hskip\typingparameter\c!evenmargin\relax
+ \fi}%
+ \else
+ \doadaptleftskip{\typingparameter\c!margin}%
+ \fi
+ \edef\!!stringa{\executeifdefined{\??bo\typingparameter\c!blank}{\typingparameter\c!blank}}%
+ \scratchskip\executeifdefined{\??tp:\c!blank:\!!stringa}\!!stringa\relax
+ \ifgridsnapping
+ \ifdim\scratchskip=.5\baselineskip\relax
+ \edef\verbatimbaselineskip{\the\scratchskip}% new
+ \else
+ \edef\verbatimbaselineskip{\the\baselineskip}%
+ \fi
+ \else
+ \edef\verbatimbaselineskip{\the\scratchskip}%
+ \fi
+ \setupcommonverbatim}
+
+%D The basic display verbatim commands are defined in an
+%D indirect way. As we will see, they are a specific case of a
+%D more general mechanism.
+
+% we need this hack because otherwise verbatim skips
+% the first line (everything after the initial command)
+
+\def\dostarttyping#1% tricky non standard lookahead
+ {\bgroup
+ \let\currenttypingclass\??tp
+ \edef\currenttyping{#1}%
+ \obeylines
+ \futurelet\nexttoken\dodostarttyping}
+
+\def\dodostarttyping
+ {\ifx\nexttoken[%
+ \expandafter\dododostarttyping
+ \else
+ \expandafter\nododostarttyping
+ \fi}
+
+\def\nododostarttyping
+ {\dododostarttyping[]}
+
+\def\dododostarttyping[#1]%
+ {\typingparameter\c!before
+ \startpacked % includes \bgroup
+ \dosetuptypelinenumbering{#1}%
+ \initializetyping
+ \startverbatimcolor
+ \expanded{\processdisplayverbatim{\s!stop\currenttyping}}}
+
+\def\dostoptyping#1% hm, currenttyping
+ {\stopverbatimcolor
+ \stoppacked % includes \egroup
+ \typingparameter\c!after
+ \egroup
+ \dochecknextindentation{\??tp#1}%
+ \dorechecknextindentation}
+
+%D Line numbering for files is combined with filtering, while
+%D display verbatim has 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[continue]
+%D ...
+%D ...
+%D \stopcode
+%D
+%D \startcode[start=10]
+%D ...
+%D \stopcode
+%D \stoptyping
+
+%D \macros
+%D {setuptyping}
+%D
+%D The setup of typing accepts two arguments. The optional
+%D first one identifies the user defined ones. If only one
+%D argument is given, the values apply to both the standard
+%D command \type{\starttyping} and \type{\typefile}.
+
+\def\dosetuptyping[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??tp#1][#2]%
+ \else
+ \getparameters[\??tp][#1]%
+ \fi}
+
+\def\setuptyping
+ {\dodoubleempty\dosetuptyping}
+
+%D \macros
+%D {definetype}
+%D
+%D Specific inline verbatim commands can be defined with the
+%D following command.
+
+\def\definetype
+ {\dodoubleempty\dodefinetype}
+
+\def\dodefinetype[#1][#2]%
+ {\unexpanded\setvalue{#1}{\dotype{#1}}%
+ \getparameters[\??ty#1][#2]}
+
+%D \macros
+%D {definetyping}
+%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
+%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.
+
+\def\presettyping[#1][#2]%
+ {\copyparameters[\??tp#1][\??tp][\c!color,\c!style]%
+ \getparameters [\??tp#1][#2]}
+
+\def\dodefinetyping[#1][#2]%
+ {\setvalue{\e!start#1}{\dostarttyping{#1}}%
+ \setvalue{\e!stop #1}{\dostoptyping {#1}}%
+ \presettyping[#1][#2]}
+
+\def\definetyping
+ {\dodoubleempty\dodefinetyping}
+
+%D We can use some core color commands. These are faster than
+%D the standard color switching ones and work ok on a line by
+%D line basis.
+%D
+%D \starttyping
+%D \def\setupverbatimcolor%
+%D {\edef\prettypalet{\prettyidentifier\typingparameter\c!palet}%
+%D \def\beginofpretty[##1]{\startcolormode{\prettypalet:##1}}%
+%D \def\endofpretty {\stopcolormode}}
+%D \stoptyping
+%D
+%D Since we support a global color too, the folowing
+%D definition is better:
+
+% \def\setupverbatimcolor% fast and local versus slow and global
+% {\doifelsenothing{\typingparameter\c!color}
+% {\def\beginofpretty[##1]{\startcolormode{\prettypalet:##1}}%
+% \let\endofpretty \restorecolormode % \stopcolormode
+% \let\startverbatimcolor \relax
+% \let\stopverbatimcolor \relax
+% \let\verbatimcolor \relax}
+% {\def\beginofpretty[##1]{\startcolor[\prettypalet:##1]}%
+% \let\endofpretty \stopcolor
+% \def\startverbatimcolor{\startcolor[\typingparameter\c!color]}%
+% \let\stopverbatimcolor \stopcolor
+% \def\verbatimcolor {\getvalue{\typingparameter\c!color}}}% command !
+% \doifelsenothing{\typingparameter\c!palet}
+% {\let\prettypalet\empty
+% \let\endofpretty\relax
+% \def\beginofpretty[##1]{}}
+% {\edef\prettypalet{\prettyidentifier\typingparameter\c!palet}}}
+%
+% let's forget about this optimization not that we have mkiv
+
+\def\setupverbatimcolor
+ {\def\beginofpretty[##1]{\startcolor[\prettypalet:##1]}%
+ \let\endofpretty \stopcolor
+ \def\startverbatimcolor{\startcolor[\typingparameter\c!color]}%
+ \let\stopverbatimcolor \stopcolor
+ \def\verbatimcolor {\getvalue{\typingparameter\c!color}}% command !
+ \doifelsenothing{\typingparameter\c!palet}
+ {\let\prettypalet\empty
+ \let\endofpretty\relax
+ \def\beginofpretty[##1]{}}
+ {\edef\prettypalet{\prettyidentifier\typingparameter\c!palet}}}
+
+\let\prettypalet \empty
+\let\startverbatimcolor\relax
+\let\stopverbatimcolor \relax
+\let\verbatimcolor \relax
+
+%D In the verbatim module, there are some examples given of
+%D the more obscure features of the verbatim environments.
+%D
+%D \startbuffer
+%D \startTEX
+%D \def\mathematics#1% % usage: \type {\mathematics{x^2}}
+%D {\ifmmode#1\else$#1$\fi} % becomes: \mathematics{x^2}
+%D \stopTEX
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This gives, as can be expected:
+%D
+%D \getbuffer
+%D
+%D When we want to see some typeset \TEX\ too, we can say:
+%D
+%D \startbuffer
+%D \startTEX
+%D \def\mathematics#1% %%\ N usage: \type {\mathematics{x^2}}
+%D {\ifmmode#1\else$#1$\fi} %%\ N becomes: \mathematics{x^2}
+%D \stopTEX
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or:
+%D
+%D \getbuffer
+%D
+%D In a similar way:
+%D
+%D \startbuffer
+%D \startSQL
+%D select * -- indeed, here we {\em do} select
+%D from tableA
+%D where 1 = 2
+%D \stopSQL
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D gives:
+%D
+%D \getbuffer
+%D
+%D The next examples sow how we can directly call for natural
+%D \TEX\ comments:
+%D
+%D \startbuffer
+%D \setuptyping
+%D [TEX]
+%D [text=yes]
+%D
+%D \startTEX
+%D \def\mathematics#1% % usage: \type {\mathematics{x^2}}
+%D {\ifmmode#1\else$#1$\fi} % becomes: \mathematics{x^2}
+%D \stopTEX
+%D
+%D \setuptyping
+%D [SQL]
+%D [text=yes,palet=,icommand=\bf,vcommand=,ccommand=\it]
+%D
+%D \startSQL
+%D select * -- indeed, here we {\em do} select
+%D from tableA
+%D where 1 = 2
+%D \stopSQL
+%D
+%D \setuptyping
+%D [SQL]
+%D [ccommand=\tf\underbar]
+%D
+%D \startSQL
+%D select * -- indeed, here we {\em do} select
+%D from tableA
+%D where 1 = 2
+%D \stopSQL
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Now watch:
+%D
+%D \getbuffer
+%D
+%D The natural \TEX\ typesetting was introduced when Tobias
+%D and Berend started using verbatim \JAVASCRIPT\ and \SQL.
+
+%D \macros
+%D {EveryPar, EveryLine, iflinepar}
+%D
+%D One of the features of these commands is the support of
+%D \type{\EveryPar}, \type{\EveryLine} and \type{\iflinepar}.
+%D In the documentation of the verbatim support module we give
+%D some examples of line- and paragraph numbering using these
+%D macros.
+
+%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:
+
+% new feature (not yet 100\% ok)
+%
+% \setuptyping[file][numbering=file]
+%
+% \typefile[start=2,nlines=3]{zapf}
+% \typefile[start=continue,nlines=13]{zapf}
+% \typefile{zapf}
+%
+% \setuptyping[file][numbering=line]
+%
+% \typefile[start=4,step=3]{zapf}
+% \typefile{zapf}
+
+\def\typefile
+ {\dodoubleempty\dotypefile}
+
+\def\dotypefile[#1][#2]#3%
+ {\ifsecondargument
+ \dodotypefile[#1][#2]{#3}%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\dodotypefile[\v!file][#1]{#3}}
+ {\dodotypefile[#1][]{#3}}%
+ \else
+ \dodotypefile[\v!file][]{#3}%
+ \fi\fi}
+
+\def\dosetuptypelinenumbering#1% fuzzy
+ {\doifundefined{\currenttypingclass\currenttyping\c!start}
+ {\setuptyping[\currenttyping][\c!start=1,\c!stop=,\c!step=1,\c!nlines=]}%
+ \setuptyping[\currenttyping][#1]%
+ \doifelse{\typingparameter\c!numbering}\v!file
+ {% kind of special: filters lines !
+ \setuplinenumbering[\c!method=\v!file]%
+ \donetrue}
+ {\doifelse{\typingparameter\c!numbering}\v!line
+ {% \setuplinenumbering defaults start/step to 1/1, so we need
+ \doifinsetelse\v!continue{#1,\typingparameter\c!start}
+ {\scratchcounter0\typingparameter\c!n
+ \setxtypingparameter\c!start{\ifnum\scratchcounter=0 1\else\number\scratchcounter\fi}}%
+ {\doifnothing{\typingparameter\c!start}{\settypingparameter\c!start{1}}}%
+ \doifnothing{\typingparameter\c!step}{\settypingparameter\c!step{1}}%
+ \setuplinenumbering
+ [\c!method=\v!type,
+ \c!start=\typingparameter\c!start,
+ \c!stop=\typingparameter\c!stop,
+ \c!step=\typingparameter\c!step]%
+ \donetrue}
+ {\donefalse}}%
+ \ifdone
+ \ifx\startlinenumbering\undefined \let\startlinenumbering\relax \fi
+ \ifx\stoplinenumbering \undefined \let\stoplinenumbering \relax \fi
+ \def\beginofverbatimlines{\startlinenumbering}%
+ \def\endofverbatimlines {\stoplinenumbering\setxtypingparameter\c!n{\number\linenumber}}%
+ \fi}
+
+\def\reporttypingerror#1% temp hack
+ {\blank
+ \dontleavehmode\hbox\bgroup
+ \expanded{\defconvertedargument\noexpand\ascii{#1}}%
+ \tttf[\makemessage\m!verbatims1\ascii]%
+ \showmessage\m!verbatims1\ascii
+ \egroup
+ \blank}
+
+\def\dosometyping#1#2#3#4#5%
+ {\bgroup
+ \let\currenttypingclass\??tp
+ \edef\currenttyping{#1}%
+ \typingparameter\c!before
+ \startpacked % includes \bgroup
+ \dosetuptypelinenumbering{#2}%
+ \doifinset{\typingparameter\c!option}{\v!commands,\v!slanted,\v!normal}
+ {\setuptyping[#1][\c!option=\v!none]}%
+ \doif{\typingparameter\c!option}\v!color
+ {\expandafter\aftersplitstring#3\at.\to\prettyidentifier
+ \settypingparameter\c!option{\prettyidentifier}}%
+ \initializetyping
+ \startverbatimcolor
+ \doifundefinedelse{\currenttypingclass#3\v!global\c!start}
+ {\scratchcounter\zerocount}
+ {\scratchcounter\getvalue{\currenttypingclass#3\v!global\c!start}}%
+ \advance\scratchcounter\plusone
+ \setxvalue{\currenttypingclass#3\v!global\c!start}{\the\scratchcounter}%
+ \doifelsenothing{\typingparameter\c!start}
+ {#4}
+ {\doif{\typingparameter\c!start}\v!continue
+ {\setevalue{\currenttypingclass#1\c!start}%
+ {\getvalue{\currenttypingclass#3\v!global\c!start}}}%
+ \doifelsenothing{\typingparameter\c!stop}
+ {\doifelsenothing{\typingparameter\c!nlines}
+ {#4}
+ {\setxvalue{\currenttypingclass#3\v!global\c!start}%
+ {\the\numexpr\typingparameter\c!start+\typingparameter\c!nlines+\minusone\relax}%
+ #5{\typingparameter\c!start}{\getvalue{\currenttypingclass#3\v!global\c!start}}}}%
+ {#5{\typingparameter\c!start}{\typingparameter\c!stop}}}%
+ \stopverbatimcolor
+ \stoppacked
+ \typingparameter\c!after
+ \egroup}
+
+\def\doifelsetypingfile#1% sets \readfilename (we will make this proper mkiv i.e. less messy)
+ {\doiflocfileelse{#1}
+ {\firstoftwoarguments}
+ {\doifinputfileelse{#1}
+ {\def\readfilename{\pathplusfile\filepath{#1}}\firstoftwoarguments} % messy, looks wrong too
+ {\secondoftwoarguments}}}
+
+\def\dodotypefile[#1][#2]#3%
+ {\doifelsetypingfile{#3}
+ {\dosometyping{#1}{#2}{#3}{\processfileverbatim\readfilename}{\processfilelinesverbatim\readfilename}}
+ {\reporttypingerror{#3}}}
+
+%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 This leaves some settings:
+
+\permitshiftedendofverbatim
+\optimizeverbatimtrue
+
+%D And a bonus macro:
+
+\def\verbatim#1{\defconvertedargument\ascii{#1}\ascii}
+
+%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.
+
+\setuptyping
+ [ \c!before=\blank,
+ \c!after=\blank,
+ \c!bodyfont=,
+ \c!color=,
+ \c!space=\v!off,
+ \c!page=\v!no,
+ \c!tab=\s!ascii,
+ \c!option=\v!none,
+ \c!palet=colorpretty,
+ \c!text=\v!no,
+ \c!style=\tttf,
+ \c!icommand=\ttsl,
+ \c!vcommand=,
+ \c!ccommand=\tttf,
+ \c!indentnext=\v!yes,
+ \c!margin=\!!zeropoint,
+ \c!evenmargin=\!!zeropoint,
+ \c!oddmargin=\!!zeropoint,
+ \c!blank=\v!line,
+ \c!escape=/, % beware \string\ , should also be accepted
+ \c!numbering=\v!no,
+ \c!lines=,
+ \c!empty=,
+ \c!start=1,
+ \c!stop=,
+ \c!step=1,
+ \c!continue=,
+ \c!nlines=]
+
+\definetyping[\v!typing]
+
+\presettyping[\v!file][]
+
+% \setuptyping % not needed
+% [\v!file]
+% [\c!start=1,
+% \c!stop=,
+% \c!step=1,
+% \c!continue=,
+% \c!nlines=]
+
+%D The setups for inline verbatim default to:
+
+\setuptype
+ [ \c!space=\v!off,
+ \c!color=,
+ \c!style=\tt\tf, % \tttf gives problems with {\tx \type...}
+ \c!page=\v!no,
+ \c!tab=\v!yes,
+ \c!palet=colorpretty,
+ \c!option=\v!normal]
+
+\definetyping[RAW] [\c!option=RAW]
+\definetyping[MP] [\c!option=MP]
+\definetyping[PL] [\c!option=PL]
+\definetyping[PM] [\c!option=PL]
+\definetyping[JS] [\c!option=JS]
+\definetyping[JV] [\c!option=JV]
+\definetyping[SQL] [\c!option=SQL]
+\definetyping[TEX] [\c!option=TEX]
+\definetyping[PAS] [\c!option=PAS]
+\definetyping[PASCAL][\c!option=PAS]
+\definetyping[MOD] [\c!option=PAS]
+\definetyping[MODULA][\c!option=PAS]
+\definetyping[DELPHI][\c!option=PAS]
+\definetyping[EIFFEL][\c!option=EIF]
+\definetyping[XML] [\c!option=XML]
+\definetyping[LUA] [\c!option=LUA]
+
+\installprettytype [RAW] [RAW]
+
+\installprettytype [TEX] [TEX]
+
+\installprettytype [PERL] [PL]
+\installprettytype [PL] [PL]
+\installprettytype [PM] [PL]
+
+\installprettytype [METAPOST] [MP]
+\installprettytype [METAFONT] [MP]
+\installprettytype [MP] [MP]
+\installprettytype [MF] [MP]
+
+\installprettytype [JAVASCRIPT] [JS]
+\installprettytype [JAVA] [JV]
+\installprettytype [JS] [JS]
+\installprettytype [JV] [JV]
+
+\installprettytype [SQL] [SQL]
+
+\installprettytype [PASCAL] [PAS]
+\installprettytype [PAS] [PAS]
+\installprettytype [MODULA] [PAS]
+\installprettytype [MOD] [PAS]
+
+\installprettytype [EIFFEL] [EIF]
+\installprettytype [EIF] [EIF]
+\installprettytype [E] [EIF]
+
+\installprettytype [XML] [XML]
+
+\installprettytype [LUA] [LUA]
+
+\installnewpretty M {\setupprettiesintype {MP}\setupprettytype}
+\installnewpretty P {\setupprettiesintype {PL}\setupprettytype}
+\installnewpretty T {\setupprettiesintype{TEX}\setupprettytype}
+\installnewpretty J {\setupprettiesintype {JV}\setupprettytype}
+\installnewpretty S {\setupprettiesintype{SQL}\setupprettytype}
+\installnewpretty W {\setupprettiesintype{PAS}\setupprettytype} % Wirth
+\installnewpretty I {\setupprettiesintype{EIF}\setupprettytype} % E taken
+\installnewpretty X {\setupprettiesintype{XML}\setupprettytype}
+
+%D We use the \CONTEXT\ color system for switching to and from
+%D color mode. We can always redefine these colors afterwards.
+
+\definecolor [colorprettyone] [r=.9, g=.0, b=.0] % red
+\definecolor [colorprettytwo] [r=.0, g=.8, b=.0] % green
+\definecolor [colorprettythree] [r=.0, g=.0, b=.9] % blue
+\definecolor [colorprettyfour] [r=.8, g=.8, b=.6] % yellow
+
+\definecolor [grayprettyone] [s=.30]
+\definecolor [grayprettytwo] [s=.45]
+\definecolor [grayprettythree] [s=.60]
+\definecolor [grayprettyfour] [s=.75]
+
+\definepalet
+ [colorpretty]
+ [ prettyone=colorprettyone,
+ prettytwo=colorprettytwo,
+ prettythree=colorprettythree,
+ prettyfour=colorprettyfour]
+
+\definepalet
+ [graypretty]
+ [ prettyone=grayprettyone,
+ prettytwo=grayprettytwo,
+ prettythree=grayprettythree,
+ prettyfour=grayprettyfour]
+
+\definepalet [TEXcolorpretty] [colorpretty]
+\definepalet [TEXgraypretty] [graypretty]
+\definepalet [PLcolorpretty] [colorpretty]
+\definepalet [PLgraypretty] [graypretty]
+\definepalet [PMcolorpretty] [colorpretty]
+\definepalet [PMgraypretty] [graypretty]
+\definepalet [MPcolorpretty] [colorpretty]
+\definepalet [MPgraypretty] [graypretty]
+\definepalet [JVcolorpretty] [colorpretty]
+\definepalet [JVgraypretty] [graypretty]
+\definepalet [JScolorpretty] [colorpretty]
+\definepalet [JSgraypretty] [graypretty]
+\definepalet [SQLcolorpretty] [colorpretty]
+\definepalet [SQLgraypretty] [graypretty]
+\definepalet [PAScolorpretty] [colorpretty]
+\definepalet [PASgraypretty] [graypretty]
+\definepalet [EIFcolorpretty] [colorpretty]
+\definepalet [EIFgraypretty] [graypretty]
+\definepalet [XMLcolorpretty] [colorpretty]
+\definepalet [XMLgraypretty] [graypretty]
+\definepalet [LUAcolorpretty] [colorpretty]
+\definepalet [LUAgraypretty] [graypretty]
+
+\protect \endinput
diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv
new file mode 100644
index 000000000..dacbdb7ac
--- /dev/null
+++ b/tex/context/base/buff-ver.mkiv
@@ -0,0 +1,1193 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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 Buffer Macros / Verbatim}
+
+%D We can optimize esp the initializations a bit.
+
+\unprotect
+
+\ifdefined\startlinenumbering\else \let\startlinenumbering \relax \fi
+\ifdefined\stoplinenumbering \else \let\stoplinenumbering \relax \fi
+\ifdefined\setuplinenumbering\else \unexpanded\def\setuplinenumbering[#1]{} \fi
+
+% D \macros
+% D {iflinepar}
+% D
+% D A careful reader will see that \type{\linepar} is reset.
+% D This boolean can be used to determine if the current line is
+% D the first line in a pseudo paragraph and this boolean is set
+% D after each empty line. The \type{\relax} can be used to
+% D determine the end of the line when one implements a scanner
+% D routine.
+%
+% will become obsolete
+
+\newif\iflinepar
+
+% \type{ char} geeft bagger
+
+%D We are going to embed the general verbatim support macros in
+%D a proper environment. First we show the common setup
+%D macro, so we know what features are supported. The options
+%D are hooked into the support macros via the \type{\obey}
+%D macros.
+
+\newif\ifslantedtypeactivated
+\newif\ifslantedtypepermitted
+
+\def\switchslantedtype
+ {\ifslantedtypepermitted
+ \ifslantedtypeactivated
+ \slantedtypeactivatedfalse\tttf
+ \else
+ \slantedtypeactivatedtrue\ttsl
+ \fi
+ \fi}
+
+\def\prettyidentifier {TEX}
+\def\prettypalet {}
+
+\def\installprettytype
+ {\dodoubleargument\doinstallprettytype}
+
+\def\doinstallprettytype[#1][#2]% map #1 onto #2
+ {\uppercasestring#1\to\asciia
+ \uppercasestring#2\to\asciib
+ \setevalue{\??ty\??ty\asciia}{\asciib}}
+
+\unexpanded\def\setupprettiesintype#1%
+ {\uppercasestring#1\to\ascii
+ \edef\prettyidentifier{\executeifdefined{\??ty\??ty\ascii}{TEX}}%
+ \begingroup
+ % we can move this to lua
+ % \lowercasestring \f!prettyprefix\prettyidentifier\to\filename
+ % \doonlyonce\filename{\ctxloadluafile\filename\empty}%
+ \ctxlua{buffers.loadvisualizer("\ascii")}%
+ \endgroup}
+
+\unexpanded\def\setupprettytype
+ {\processingverbatimtrue % will move
+ \ctxlua{buffers.visualizers.reset()}}
+
+\def\setverbatimspaceskip
+ {\setbox\scratchbox\hbox{x}%
+ \spaceskip\wd\scratchbox
+ \xspaceskip\spaceskip}
+
+\let\obeycharacters\relax % tab mess can go
+
+\setvalue{\??tp:\c!lines:\v!yes }{\obeybreakpoints}
+\setvalue{\??tp:\c!lines:\v!hyphenated}{\obeyhyphens}
+
+%setvalue{\??tp:\c!empty:\v!yes }{\obeyemptylines}
+%setvalue{\??tp:\c!empty:\v!all }{\obeyallemptylines}
+
+\setvalue{\??tp:\c!option:\v!none }{\let\obeycharacters\relax}
+\setvalue{\??tp:\c!option:\empty }{\let\obeycharacters\relax}
+\setvalue{\??tp:\c!option:\v!color }{\setupprettiesintype{\typingparameter\c!option}%
+ \let\obeycharacters\setupprettytype}
+\setvalue{\??tp:\c!option:\v!normal }{\let\obeycharacters\setupgroupedtype}
+\setvalue{\??tp:\c!option:\v!slanted }{\let\obeycharacters\setupslantedtype}
+\setvalue{\??tp:\c!option:\s!unknown }{\setupprettiesintype{\typingparameter\c!option}%
+ \let\obeycharacters\setupprettytype}
+%setvalue{\??tp:\c!option:\v!commands }{\def\obeycharacters{\setupcommandsintype}}
+
+\def\dosetverbatimfont
+ {\redoconvertfont\dosetfontattribute{\currenttypingclass\currenttyping}\c!style
+ \normalnoligatures\font}
+
+\unexpanded\def\setupcommonverbatim
+ {\let\prettyidentifier\s!default
+ %
+ \def\prettyidentifierfont{\typingparameter\c!icommand}%
+ \def\prettyvariablefont {\typingparameter\c!vcommand}%
+ \def\prettynaturalfont {\typingparameter\c!ccommand}%
+ %
+ \ignorehyphens % default
+ \getvalue{\??tp:\c!lines:\typingparameter\c!lines}%
+ \getvalue{\??tp:\c!empty:\typingparameter\c!empty}%
+ \getvalue{\??tp:\c!option:\ifcsname\??tp:\c!option:\typingparameter\c!option\endcsname\typingparameter\c!option\else\s!unknown\fi}%
+ \setupverbatimcolor}
+
+\newtoks \everyinitializeverbatim
+
+\def\ignorebeginofpretty [#1]{}
+\def\ignoreendofpretty {}
+
+\def\doverbatimbop{\bgroup\beginofpretty}
+\def\doverbatimeop{\endofpretty\egroup}
+\def\doverbatimsop{\endofpretty\egroup\bgroup\beginofpretty}
+
+\let\noverbatimbop\ignorebeginofpretty
+\let\noverbatimeop\ignoreendofpretty
+\let\noverbatimsop\ignorebeginofpretty
+
+\def\doinitializeverbatim % todo: combine all in one call is faster
+ {\ctxlua{buffers.visualizers.reset()}%
+ \doifelse{\typingparameter\c!space}\v!on
+ {\let\obs\fastcontrolspace}%
+ {\let\obs\specialobeyedspace}%
+ \edef\askedverbatimtab{\typingparameter\c!tab}%
+ \doifelse\askedverbatimtab\v!no
+ {\ctxlua{buffers.settablength(1)}}
+ {\doifnumberelse{\askedverbatimtab}
+ {\ctxlua{buffers.settablength(\askedverbatimtab)}}
+ {\ctxlua{buffers.settablength()}}}%
+ \ctxlua{buffers.doifelsevisualizer("\prettyidentifier")}
+ {\ctxlua{buffers.setvisualizer("\prettyidentifier")}%
+ \let\bop\doverbatimbop
+ \let\eop\doverbatimeop
+ \let\sop\doverbatimsop}%
+ {\ctxlua{buffers.setvisualizer("\v!typing")}% or resetdefaultvisualizer
+ \let\bop\noverbatimbop
+ \let\eop\noverbatimeop
+ \let\sop\noverbatimsop}%
+ \relax\the\everyinitializeverbatim\relax}
+
+\appendtoks
+ \resetfontfeature
+ \resetcharacterspacing
+\to \everyinitializeverbatim
+
+% BEWARE: the noligatures will globally change the verbatim font's behaviour
+
+% test case:
+%
+% \definetype[typeTEX][option=tex]
+%
+% \typeTEX|\example---oeps|. this---ligates---again.
+% \typeTEX{\example---oeps}. this---ligates---again.
+% \type {\example---oeps}. this---ligates---again.
+
+%D \startbuffer
+%D \setuptyping[TEX][escape=yes]
+%D
+%D \startTEX
+%D /BTEX\em sometex/ETEX
+%D /BTEX\em sometex/ETEX \after
+%D \before /BTEX\em sometex/ETEX
+%D \before /BTEX\em sometex/ETEX \after
+%D \before /BTEX\em sometex/ETEX \inbetween /BTEX\em sometex/ETEX \after
+%D \before \after
+%D \stopTEX
+%D \stopbuffer
+%D
+%D \typebuffer \start \getbuffer \stop
+%D
+%D \startbuffer
+%D \setuptyping[TEX][escape={[[,]]}]
+%D
+%D \startTEX
+%D [[\em sometex]]
+%D [[\em sometex]] \after
+%D \before [[\em sometex]]
+%D \before [[\em sometex]] \after
+%D \before [[\em sometex]] \inbetween [[\em sometex]] \after
+%D \before \after
+%D \stopTEX
+%D \stopbuffer
+%D
+%D \typebuffer \start \getbuffer \stop
+%D
+%D \startbuffer
+%D \setuptyping[TEX][escape=//]
+%D
+%D \startTEX
+%D //\em sometex
+%D \before //\em sometex
+%D \stopTEX
+%D
+%D \typebuffer \start \getbuffer \stop
+
+\unexpanded\def\setupcommandsintype
+ {\ctxlua{buffers.set_escape("\currenttyping",\!!bs\typingparameter\c!escape\!!es)}}
+
+\appendtoks
+ \setupcommandsintype
+\to \everyinitializeverbatim
+
+\unexpanded\def\setupslantedtype
+ {\slantedtypepermittedtrue}
+
+\ifx\setupprettytype \undefined \let\setupprettytype \relax \fi
+\ifx\setupslantedtype \undefined \let\setupslantedtype \relax \fi
+\ifx\setupgroupedtype \undefined \let\setupgroupedtype \relax \fi
+\ifx\normalnoligatures\undefined \let\normalnoligatures\gobbleoneargument \fi
+
+%D The verbatim commands have a rather long and turbulent
+%D history. Most users of \CONTEXT\ probably will never use
+%D some of the features, but I've kept in mind that when one is
+%D writing a users manual, about everything can and undoubtly
+%D will be subject to a verbatim treatment.
+%D
+%D Verbatim command are very sensitive to argument processing,
+%D which is a direct result of the \CATCODES\ being fixed at
+%D reading time. With our growing understanding of \TEX,
+%D especially of the mechanism that can be used for looking
+%D ahead and manipulating \CATCODES, the verbatim support
+%D became more and more advanced and natural.
+%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
+%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
+%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.
+
+% todo: we can use \letter... here:
+
+\def\lesscharacter {<}
+\def\morecharacter {>}
+
+\chardef\texescape = `\\
+\chardef\leftargument = `\{
+\chardef\rightargument = `\}
+
+%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.
+
+% \starttyping
+% normal: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par
+% normal: \par \type{xx<..xx.. >..>xx} \par \type{<....>} \par \type{<....>}
+% \setuptype[option=slanted]
+% slanted: \par \type{xx<<..sl..<> xx>>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<>..>> \par
+% slanted: \par \type{xx<<..sl.. xx>..sl..>>xx} \par \type<<..xx..>> \par \type<<....>> \par
+% \setuptype[option=none]
+% none: \par \type{xx<<..xx..<> >>..>>xx} \par \type<<....>> \par \type<<..<>..>> \par
+% \stoptyping
+
+%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 The following lines show what happens when we set
+%D \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
+
+\unexpanded\def\type{\dotype\empty}
+
+\def\dotype#1% was \dotype
+ {\dontleavehmode \bgroup
+ % new, \strut enables leading space in \type { abc } at par start / begstrut
+ % else no hyphenation (replaced by \dontleavehmode which saves unboxing)
+ % \begstrut
+ \let\currenttypingclass\??ty
+ \edef\currenttyping{#1}%
+ \catcode`\<=\@@other
+ \catcode`\>=\@@other
+ \futurelet\next\dodotype}
+
+\def\dodotype
+ {\ifx\next\bgroup
+ \@EA\dodotypeA
+ \else
+ \@EA\dodotypeAD
+ \fi}
+
+\def\dodotypeAD
+ {\if\next<%
+ \doifelse{\typingparameter\c!option}\v!none{\@EA\dodotypeB}{\@EA\dodotypeC}%
+ \else
+ \@EA\dodotypeD
+ \fi}
+
+\def\dodotypeA
+ {\initializetype % probably too much
+ \verbatimcolor
+ \dosetverbatimfont
+ \setcatcodetable \typcatcodesa
+ \dodotypeAA}
+
+\def\dodotypeAA#1%
+ {\doinitializeverbatim
+ \def\obs{\obeyedspace}%
+ \ctxlua{buffers.hooks.flush_inline(\!!bs\detokenize{#1}\!!es)}%
+ \egroup}
+
+\def\dodotypeB#1%
+ {\initializetype
+ \verbatimcolor
+ \dosetverbatimfont
+ \setcatcodetable \typcatcodesb
+ \dodotypeBB}
+
+\def\dodotypeBB#1%
+ {\doinitializeverbatim
+ \ctxlua{buffers.visualizers.flush_nested(\!!bs\detokenize{#1}\!!es,false)}%
+ \egroup
+ \gobbleoneargument} % grab last >
+
+\def\dodotypeC#1%
+ {\initializetype
+ \verbatimcolor
+ \dosetverbatimfont
+ \setcatcodetable \typcatcodesb
+ \dodotypeCC}
+
+\def\dodotypeCC#1%
+ {\doinitializeverbatim
+ \ifx\obeycharacters\setupprettytype % temp hack, we need a proper signal
+ \ctxlua{buffers.hooks.flush_inline([\!!bs\detokenize{#1}\!!es,true)}%
+ \else
+ \def\obs{\obeyedspace}%
+ \ctxlua{buffers.visualizers.flush_nested(\!!bs\detokenize{#1}\!!es,true)}%
+ \fi
+ \egroup
+ \gobbleoneargument} % grab last >
+
+\def\dodotypeD#1%
+ {\initializetype
+ \verbatimcolor
+ \dosetverbatimfont
+ \setcatcodetable \typcatcodesa
+ \def\dodotypeDD##1#1{\dodotypeAA{##1}}%
+ \dodotypeDD}
+
+\def\dodotypeDD#1%
+ {\doinitializeverbatim
+ \ctxlua{buffers.hooks.flush_inline(\!!bs\detokenize{#1}\!!es,true)}%
+ \egroup
+ \gobbleoneargument} % grab last >
+
+%D The neccessary initializations are done by calling
+%D \type{\initializetype} which in return calls for the support
+%D macro \type{\setupinlineverbatim}.
+
+\def\initializetype
+ {\let\obeylines\ignorelines
+ \setupcommonverbatim
+ %\dosetverbatimfont
+ %\setverbatimspaceskip
+ %\setupcopyverbatim % not needed
+ \setcatcodetable\vrbcatcodes}
+
+%D \macros
+%D {setuptype}
+%D
+%D Some characteristics of \type{\type} can be set up by:
+
+\unexpanded\def\setuptype
+ {\dodoubleempty\dosetuptype}
+
+\def\dosetuptype[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??ty#1][#2]%
+ \else
+ \getparameters[\??ty][#1]%
+ \fi}
+
+%D \macros
+%D {typ,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.
+
+\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
+\def\specialcontrolspace{\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax}
+
+\def\obeyhyphens
+ {\let\obeyedspace \specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \spaceskip.25em\relax} % hm a bit of stretch !
+
+\def\obeybreakpoints
+ {\ignorehyphens
+ \veryraggedright}
+
+\def\ignorehyphens
+ {\language\minusone % extra bonus, the \null should do the job too
+ \let\obeyedspace \specialobeyedspace
+ \let\controlspace\specialcontrolspace
+ \spaceskip.5em\relax}
+
+\unexpanded\def\typ
+ {\bgroup
+ \let\@@tylines\v!hyphenated
+ \futurelet\next\dodotype}
+
+%D \macros
+%D {tex,arg,mat,dis}
+%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
+%D The next implementation is more clear but less versatile,
+%D so we treated it for a beter one.
+%D
+%D \starttyping
+%D \def\dospecialtype#1#2%
+%D {\bgroup
+%D \initializetype
+%D \catcode`\{=\@@begingroup
+%D \catcode`\}=\@@endgroup
+%D \def\dospecialtype%
+%D {\def\dospecialtype{#2\egroup}%
+%D \bgroup
+%D \aftergroup\dospecialtype
+%D #1}%
+%D \afterassignment\dospecialtype
+%D \let\next=}
+%D
+%D \unexpanded\def\tex{\dospecialtype\texescape\relax}
+%D \unexpanded\def\arg{\dospecialtype\leftargument\rightargument}
+%D \unexpanded\def\mat{\dospecialtype\$\$}
+%D \unexpanded\def\dis{\dospecialtype{\$\$}{\$\$}}
+%D \stoptyping
+
+\def\setgroupedtype
+ {\let\currenttypingclass\??ty
+ \initializetype
+ \verbatimcolor
+ \dosetverbatimfont
+ %\setcatcodetable \typcatcodesa
+ \catcode`\{=\@@begingroup
+ \catcode`\}=\@@endgroup}
+
+\unexpanded\def\tex{\groupedcommand{\setgroupedtype\texescape}{\relax}}
+\unexpanded\def\arg{\groupedcommand{\setgroupedtype\leftargument}{\rightargument}}
+\unexpanded\def\mat{\groupedcommand{\setgroupedtype\$}{\$}}
+\unexpanded\def\dis{\groupedcommand{\setgroupedtype\$\$}{\$\$}}
+
+\let\normaltexttex\tex
+\let\normaltextarg\arg
+\let\normaltextmat\mat
+\let\normaltextdis\dis
+
+\def\astype
+ {\groupedcommand\dorawtype\relax}
+
+\def\dorawtype
+ {\let\currenttypingclass\??ty
+ \normalverbatimcolor % \verbatimcolor
+ \dosetverbatimfont}
+
+%D \macros
+%D {starttyping}
+%D
+%D Display verbatim is realized far more easy, which is mostly
+%D due to the fact that we use \type{\stop...} as delimiter.
+%D The implementation inherits some features, for instance the
+%D support of linenumbering, which can best be studied in the
+%D documented support module.
+
+\let\currenttyping \empty
+\let\currenttypingclass\??ty % saveguard
+
+\def\typingparameter#1%
+ {\ifcsname\currenttypingclass\currenttyping#1\endcsname
+ \csname\currenttypingclass\currenttyping#1\endcsname
+ \else\ifcsname\currenttypingclass#1\endcsname
+ \csname\currenttypingclass#1\endcsname
+ \fi\fi}
+
+\def\settypingparameter#1#2%
+ {\setvalue{\currenttypingclass\currenttyping#1}{#2}}
+
+\def\setxtypingparameter#1#2%
+ {\setxvalue{\currenttypingclass\currenttyping#1}{#2}}
+
+\setvalue{\??tp:\c!blank:\v!standard}{\ctxparskip}
+\setvalue{\??tp:\c!blank:\v!small }{\smallskipamount}
+\setvalue{\??tp:\c!blank:\v!medium }{\medskipamount}
+\setvalue{\??tp:\c!blank:\v!big }{\bigskipamount}
+\setvalue{\??tp:\c!blank:\v!halfline}{.5\baselineskip}
+\setvalue{\??tp:\c!blank:\v!line }{\baselineskip}
+\setvalue{\??tp:\c!blank:\v!none }{\zeropoint}
+
+\def\doopenupverbatimlineindeed
+ {\getpagestatus
+ \ifrightpage
+ \hskip\typingparameter\c!oddmargin\relax
+ \else
+ \hskip\typingparameter\c!evenmargin\relax
+ \fi}
+
+\def\initializetyping
+ {%\donefalse
+ \switchtobodyfont[\typingparameter\c!bodyfont]%
+ \donefalse
+ \scratchskip\typingparameter\c!oddmargin\relax
+ \ifzeropt\scratchskip\else\donetrue\fi
+ \scratchskip\typingparameter\c!evenmargin\relax
+ \ifzeropt\scratchskip\else\donetrue\fi
+ \ifdone
+ \let\doopenupverbatimline\doopenupverbatimlineindeed
+ \else
+ \doadaptleftskip{\typingparameter\c!margin}%
+ \fi
+ % no symbolic blanks !
+ \edef\!!stringa{\executeifdefined{\??bo\typingparameter\c!blank}{\typingparameter\c!blank}}%
+ \scratchskip\executeifdefined{\??tp:\c!blank:\!!stringa}\!!stringa\relax
+ \ifgridsnapping
+ % this will be adapted
+ \ifdim\scratchskip=.5\baselineskip\relax
+ \edef\verbatimbaselineskip{\the\scratchskip}% new
+ \else
+ \edef\verbatimbaselineskip{\the\baselineskip}%
+ \fi
+ \else
+ \edef\verbatimbaselineskip{\the\scratchskip}%
+ \fi
+\doifsomething{\typingparameter\c!align}{\setupalign[\typingparameter\c!align]}%
+ \setupcommonverbatim}
+
+%D The basic display verbatim commands are defined in an
+%D indirect way. As we will see, they are a specific case of a
+%D more general mechanism.
+
+\newif\ifoptimizeverbatim \optimizeverbatimtrue
+
+\let \beginofverbatimlines \relax
+\let \endofverbatimlines \relax
+
+\def\doverbatimnobreak
+ {\ifoptimizeverbatim\penalty500 \fi}
+
+\def\doverbatimgoodbreak
+ {\ifoptimizeverbatim\penalty\linepenalty\fi}
+
+% \def\doflushverbatimline
+% {\expandafter\dodoverbatimline\expandafter{\savedverbatimline}}
+% \def\doverbatimbeginofline#1% linenumber (optional provided by mkiv / todo)
+% {\dontleavehmode
+% \strut
+% \the\everyline}
+% \def\doverbatimendofline
+% {\par}
+% \def\doverbatimemptyline
+% {\strut
+% \par}
+% \let\handleverbatimline=\relax
+
+% we need this hack because otherwise verbatim skips
+% the first line (everything after the initial command)
+
+\def\dostarttyping#1% tricky non standard lookahead
+ {\bgroup
+ \let\currenttypingclass\??tp
+ \edef\currenttyping{#1}%
+ \obeylines
+ \futurelet\nexttoken\dodostarttyping}
+
+\def\dodostarttyping
+ {\ifx\nexttoken[%
+ \expandafter\dododostarttyping
+ \else
+ \expandafter\nododostarttyping
+ \fi}
+
+\def\nododostarttyping
+ {\dododostarttyping[]}
+
+\def\dotypefileverbatim
+ {\doinitializeverbatim
+ \beginofverbatimlines
+ \ctxlua{buffers.typefile("\readfilename","\typingparameter\c!strip","\typingparameter\c!range")}%
+ \endofverbatimlines}
+
+\def\dotypefilelinesverbatim#1#2%
+ {#1\dotypefileverbatim#2}
+
+\unexpanded\def\dotypeblockverbatim#1#2%
+ {\dowithbuffer{_typing_}{#1}{#2}
+ {}
+ {\doinitializeverbatim
+ \beginofverbatimlines
+ \ctxlua{buffers.type("_typing_","\typingparameter\c!strip","\typingparameter\c!range")}%
+ \endofverbatimlines
+ \csname#2\endcsname}}
+
+\def\dododostarttyping[#1]%
+ {\typingparameter\c!before
+ \startpacked % includes \bgroup
+ \dosetuptypelinenumbering{#1}%
+ \initializetyping
+ \dosetverbatimfont
+ \startverbatimcolor
+ \normalexpanded{\dotypeblockverbatim{\e!start\currenttyping}{\e!stop\currenttyping}}} % was s!start
+
+\def\dostoptyping#1% hm, currenttyping
+ {\stopverbatimcolor
+ \stoppacked % includes \egroup
+ \typingparameter\c!after
+ \normalexpanded{\egroup\checknextindentation[\typingparameter\c!indentnext]}%
+ \dorechecknextindentation}
+
+%D Line numbering for files is combined with filtering, while
+%D display verbatim has 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
+%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 {setuptyping}
+%D
+%D The setup of typing accepts two arguments. The optional
+%D first one identifies the user defined ones. If only one
+%D argument is given, the values apply to both the standard
+%D command \type{\starttyping} and \type{\typefile}.
+
+\def\dosetuptyping[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??tp#1][#2]%
+ \else
+ \getparameters[\??tp][#1]%
+ \fi}
+
+\unexpanded\def\setuptyping
+ {\dodoubleempty\dosetuptyping}
+
+%D \macros
+%D {definetype}
+%D
+%D Specific inline verbatim commands can be defined with the
+%D following command.
+
+\unexpanded\def\definetype
+ {\dodoubleempty\dodefinetype}
+
+\def\dodefinetype[#1][#2]%
+ {\setuvalue{#1}{\dotype{#1}}%
+ \getparameters[\??ty#1][#2]}
+
+%D \macros
+%D {definetyping}
+%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
+%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.
+
+% TODO: parent etc !
+
+\def\presettyping[#1][#2]% brrr also use parent here
+ {\copyparameters[\??tp#1][\??tp][\c!color,\c!style]%
+ \getparameters [\??tp#1][#2]}
+
+\def\dodefinetyping[#1][#2]%
+ {\setvalue{\e!start#1}{\dostarttyping{#1}}%
+ \setvalue{\e!stop #1}{\dostoptyping {#1}}%
+ \presettyping[#1][#2]}
+
+\unexpanded\def\definetyping
+ {\dodoubleempty\dodefinetyping}
+
+%D We can use some core color commands. These are faster than
+%D the standard color switching ones and work ok on a line by
+%D line basis.
+%D
+%D \starttyping
+%D \unexpanded\def\setupverbatimcolor%
+%D {\edef\prettypalet{\prettyidentifier\typingparameter\c!palet}%
+%D \def\beginofpretty[##1]{\startcolormode{\prettypalet:##1}}%
+%D \def\endofpretty {\stopcolormode}}
+%D \stoptyping
+%D
+%D Since we support a global color too, the folowing
+%D definition is better:
+
+\def\normalbeginofpretty [#1]{\startcolor[\prettypalet:#1]}%
+\def\normalendofpretty {\stopcolor}
+\def\normalstartverbatimcolor{\startcolor[\typingparameter\c!color]}%
+\def\normalstopverbatimcolor {\stopcolor}
+\def\normalverbatimcolor {\getvalue{\typingparameter\c!color}}% command !
+
+\unexpanded\def\setupnormalprettyverbatim
+ {\edef\prettypalet{\prettyidentifier\prettypalet}%
+ \let\beginofpretty \normalbeginofpretty
+ \let\endofpretty \normalendofpretty
+ \let\startverbatimcolor\normalstartverbatimcolor
+ \let\stopverbatimcolor \normalstopverbatimcolor
+ \let\verbatimcolor \normalverbatimcolor}
+
+\unexpanded\def\setupignoreprettyverbatim
+ {\let\prettypalet \empty
+ \let\beginofpretty \ignorebeginofpretty
+ \let\endofpretty \ignoreendofpretty
+ \let\startverbatimcolor\normalstartverbatimcolor
+ \let\stopverbatimcolor \normalstopverbatimcolor
+ \let\verbatimcolor \normalverbatimcolor}
+
+\unexpanded\def\setupverbatimcolor
+ {\edef\prettypalet{\typingparameter\c!palet}%
+ \ifx\prettypalet\empty
+ \setupignoreprettyverbatim
+ \else
+ \setupnormalprettyverbatim
+ \fi}
+
+\let\beginofpretty \ignorebeginofpretty
+\let\endofpretty \ignoreendofpretty
+\let\prettypalet \empty
+\let\startverbatimcolor\relax
+\let\stopverbatimcolor \relax
+\let\verbatimcolor \relax
+
+%D \macros
+%D {EveryPar, EveryLine, iflinepar}
+%D
+%D One of the features of these commands is the support of
+%D \type{\EveryPar}, \type{\EveryLine} and \type{\iflinepar}.
+%D In the documentation of the verbatim support module we give
+%D some examples of line- and paragraph numbering using these
+%D macros.
+
+%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:
+
+% new feature (not yet 100\% ok)
+%
+% \setuptyping[file][numbering=file]
+%
+% \typefile[start=2,nlines=3]{zapf}
+% \typefile[start=continue,nlines=13]{zapf}
+% \typefile{zapf}
+%
+% \setuptyping[file][numbering=line]
+%
+% \typefile[start=4,step=3]{zapf}
+% \typefile{zapf}
+
+\def\typefile
+ {\dodoubleempty\dotypefile}
+
+\def\dotypefile[#1][#2]#3%
+ {\ifsecondargument
+ \dodotypefile[#1][#2]{#3}%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\dodotypefile[\v!file][#1]{#3}}
+ {\dodotypefile[#1][]{#3}}%
+ \else
+ \dodotypefile[\v!file][]{#3}%
+ \fi\fi}
+
+\def\dosetuptypelinenumbering#1% fuzzy
+ {%\ifcsname\currenttypingclass\currenttyping\c!start\endcsname \else
+ % \setuptyping[\currenttyping][\c!start=1,\c!stop=,\c!step=1,\c!continue=\v!no,\c!nlines=]%
+ %\fi
+ \doifassignmentelse{#1}{\setuptyping[\currenttyping][#1]}\donothing
+ \doifelse{\typingparameter\c!numbering}\v!file
+ {% kind of special: filters lines !
+ \setuplinenumbering[\currenttyping][\c!method=\v!file]%
+ \donetrue}
+ {\doifelse{\typingparameter\c!numbering}\v!line
+ {\doifinset\v!continue{#1}{\setuptyping[\currenttyping][\c!continue=\v!yes]}% fails: \settypingparameter\c!continue{\v!yes}
+ \donetrue}
+ {\donefalse}}%
+ \ifdone
+ \edef\beginofverbatimlines{\noexpand\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\endofverbatimlines{\stoplinenumbering}%
+ \fi}
+
+\def\reporttypingerror#1% temp hack
+ {\blank
+ \dontleavehmode\hbox\bgroup
+ \expanded{\defconvertedargument\noexpand\ascii{#1}}%
+ \tttf[\makemessage\m!verbatims1\ascii]%
+ \showmessage\m!verbatims1\ascii
+ \egroup
+ \blank}
+
+\def\dosometyping#1#2#3#4#5%
+ {\bgroup
+ \let\currenttypingclass\??tp
+ \edef\currenttyping{#1}%
+ \typingparameter\c!before
+ \startpacked % includes \bgroup
+ \dosetuptypelinenumbering{#2}%
+ \doifinset{\typingparameter\c!option}{\v!commands,\v!slanted,\v!normal}
+ {\setuptyping[#1][\c!option=\v!none]}%
+ \doif{\typingparameter\c!option}\v!color
+ {\expandafter\aftersplitstring#3\at.\to\prettyidentifier
+ \settypingparameter\c!option{\prettyidentifier}}%
+ \initializetyping
+ \dosetverbatimfont
+ \startverbatimcolor
+ \scratchcounter
+ \ifcsname\currenttypingclass#3\v!global\c!start\endcsname
+ \numexpr\csname\currenttypingclass#3\v!global\c!start\endcsname+\plusone\relax
+ \else
+ \plusone
+ \fi
+ \setxvalue{\currenttypingclass#3\v!global\c!start}{\the\scratchcounter}% no direct setxvalue as it defines beforehand
+ \doifelsenothing{\typingparameter\c!start}
+ {#4}
+ {\doif{\typingparameter\c!start}\v!continue
+ {\setevalue{\currenttypingclass#1\c!start}%
+ {\getvalue{\currenttypingclass#3\v!global\c!start}}}%
+ \doifelsenothing{\typingparameter\c!stop}
+ {\doifelsenothing{\typingparameter\c!nlines}
+ {#4}
+ {\setxvalue{\currenttypingclass#3\v!global\c!start}%
+ {\the\numexpr\typingparameter\c!start+\typingparameter\c!nlines+\minusone\relax}%
+ #5{\typingparameter\c!start}{\getvalue{\currenttypingclass#3\v!global\c!start}}}}%
+ {#5{\typingparameter\c!start}{\typingparameter\c!stop}}}%
+ \stopverbatimcolor
+ \stoppacked
+ \typingparameter\c!after
+ \egroup}
+
+\def\doifelsetypingfile#1% sets \readfilename (we will make this proper mkiv i.e. less messy)
+ {\doiflocfileelse{#1}
+ {\firstoftwoarguments}
+ {\doifinputfileelse{#1}
+% {\def\readfilename{\pathplusfile\filepath{#1}}\firstoftwoarguments} % messy, looks wrong too
+ {\def\readfilename{#1}\firstoftwoarguments} % messy, looks wrong too
+ {\secondoftwoarguments}}}
+
+\def\dodotypefile[#1][#2]#3%
+ {\doifelsetypingfile{#3}
+ {\dosometyping{#1}{#2}{#3}\dotypefileverbatim\dotypefilelinesverbatim}
+ {\reporttypingerror{#3}}}
+
+%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 And a bonus macro:
+
+\def\verbatim#1{\defconvertedargument\ascii{#1}\ascii}
+
+%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.
+
+\setuptyping
+ [ \c!before=\blank,
+ \c!after=\blank,
+ \c!bodyfont=,
+ \c!color=,
+ \c!space=\v!off,
+ \c!page=\v!no,
+ \c!tab=\s!ascii,
+ \c!option=\v!none,
+ \c!palet=colorpretty,
+ \c!text=\v!no,
+ \c!style=\tttf,
+ \c!icommand=\ttsl,
+ \c!vcommand=,
+ \c!ccommand=\tttf,
+ \c!indentnext=\v!yes,
+ \c!margin=\!!zeropoint,
+ \c!evenmargin=\!!zeropoint,
+ \c!oddmargin=\!!zeropoint,
+ \c!blank=\v!line,
+ \c!escape=, % yes | no | START,STOP BTEX,ETEX
+ \c!numbering=\v!no,
+ \c!lines=,
+ \c!range=,
+ \c!empty=,
+ \c!start=1,
+ \c!stop=,
+ \c!step=1,
+ \c!continue=,
+ \c!strip=\v!no, % auto or number
+ \c!nlines=]
+
+\definetyping[\v!typing]
+
+\presettyping[\v!file][]
+
+% \setuptyping % not needed
+% [\v!file]
+% [\c!start=1,
+% \c!stop=,
+% \c!step=1,
+% \c!continue=,
+% \c!nlines=]
+
+%D The setups for inline verbatim default to:
+
+\setuptype
+ [ \c!space=\v!off,
+ \c!color=,
+ \c!style=\tt\tf, % \tttf gives problems with {\tx \type...}
+ \c!page=\v!no,
+ \c!tab=\v!yes,
+ \c!palet=colorpretty,
+ \c!option=\v!normal]
+
+%D Beware: only a few are currently (re)implemented in \MKIV.
+
+\definetyping[RAW] [\c!option=RAW]
+\definetyping[MP] [\c!option=MP] % done
+\definetyping[PL] [\c!option=PL]
+\definetyping[PM] [\c!option=PL]
+\definetyping[JS] [\c!option=JS]
+\definetyping[JV] [\c!option=JV]
+\definetyping[SQL] [\c!option=SQL]
+\definetyping[TEX] [\c!option=TEX] % done
+\definetyping[PAS] [\c!option=PAS]
+\definetyping[PASCAL][\c!option=PAS]
+\definetyping[MOD] [\c!option=PAS]
+\definetyping[MODULA][\c!option=PAS]
+\definetyping[DELPHI][\c!option=PAS]
+\definetyping[EIFFEL][\c!option=EIF]
+\definetyping[XML] [\c!option=XML]
+\definetyping[LUA] [\c!option=LUA] % done
+
+\installprettytype [RAW] [RAW]
+
+\installprettytype [TEX] [TEX]
+
+\installprettytype [PERL] [PL]
+\installprettytype [PL] [PL]
+\installprettytype [PM] [PL]
+
+\installprettytype [METAPOST] [MP]
+\installprettytype [METAFONT] [MP]
+\installprettytype [MP] [MP]
+\installprettytype [MF] [MP]
+
+\installprettytype [JAVASCRIPT] [JS]
+\installprettytype [JAVA] [JV]
+\installprettytype [JS] [JS]
+\installprettytype [JV] [JV]
+
+\installprettytype [SQL] [SQL]
+
+\installprettytype [PASCAL] [PAS]
+\installprettytype [PAS] [PAS]
+\installprettytype [MODULA] [PAS]
+\installprettytype [MOD] [PAS]
+
+\installprettytype [EIFFEL] [EIF]
+\installprettytype [EIF] [EIF]
+\installprettytype [E] [EIF]
+
+\installprettytype [XML] [XML]
+
+\installprettytype [LUA] [LUA]
+
+%D We use the \CONTEXT\ color system for switching to and from
+%D color mode. We can always redefine these colors afterwards.
+
+\definecolor [colorprettyone] [r=.9, g=.0, b=.0] % red
+\definecolor [colorprettytwo] [r=.0, g=.8, b=.0] % green
+\definecolor [colorprettythree] [r=.0, g=.0, b=.9] % blue
+\definecolor [colorprettyfour] [r=.8, g=.8, b=.6] % yellow
+
+\definecolor [grayprettyone] [s=.30]
+\definecolor [grayprettytwo] [s=.45]
+\definecolor [grayprettythree] [s=.60]
+\definecolor [grayprettyfour] [s=.75]
+
+\definepalet
+ [colorpretty]
+ [ prettyone=colorprettyone,
+ prettytwo=colorprettytwo,
+ prettythree=colorprettythree,
+ prettyfour=colorprettyfour]
+
+\definepalet
+ [graypretty]
+ [ prettyone=grayprettyone,
+ prettytwo=grayprettytwo,
+ prettythree=grayprettythree,
+ prettyfour=grayprettyfour]
+
+\definepalet [TEXcolorpretty] [colorpretty]
+\definepalet [TEXgraypretty] [graypretty]
+\definepalet [PLcolorpretty] [colorpretty]
+\definepalet [PLgraypretty] [graypretty]
+\definepalet [PMcolorpretty] [colorpretty]
+\definepalet [PMgraypretty] [graypretty]
+\definepalet [MPcolorpretty] [colorpretty]
+\definepalet [MPgraypretty] [graypretty]
+\definepalet [JVcolorpretty] [colorpretty]
+\definepalet [JVgraypretty] [graypretty]
+\definepalet [JScolorpretty] [colorpretty]
+\definepalet [JSgraypretty] [graypretty]
+\definepalet [SQLcolorpretty] [colorpretty]
+\definepalet [SQLgraypretty] [graypretty]
+\definepalet [PAScolorpretty] [colorpretty]
+\definepalet [PASgraypretty] [graypretty]
+\definepalet [EIFcolorpretty] [colorpretty]
+\definepalet [EIFgraypretty] [graypretty]
+\definepalet [XMLcolorpretty] [colorpretty]
+\definepalet [XMLgraypretty] [graypretty]
+\definepalet [LUAcolorpretty] [colorpretty]
+\definepalet [LUAgraypretty] [graypretty]
+
+% patched from verb-ini (todo)
+
+% \let\beginverbatimline\relax
+% \let\endverbatimline \relax
+
+% \appendtoks whatever\par\to\everyverbatimbeginofdisplay
+% \appendtoks whatever\to\everyverbatimendofdisplay
+% \appendtoks [\to\everyverbatimbeginofinline
+% \appendtoks ]\to\everyverbatimendofinline
+
+\let\doopenupverbatimline\empty
+
+\newtoks\everyverbatimbeginofdisplay
+\newtoks\everyverbatimendofdisplay
+\newtoks\everyverbatimbeginofinline
+\newtoks\everyverbatimendofinline
+
+\let\currentverbatimpretty\empty
+
+\def\doverbatimbeginofdisplay#1%
+ {\edef\currentverbatimpretty{#1}%
+ \the\everyverbatimbeginofdisplay}
+
+\def\doverbatimendofdisplay
+ {\the\everyverbatimendofdisplay}
+
+\def\doverbatimbeginofinline#1%
+ {\edef\currentverbatimpretty{#1}%
+ \the\everyverbatimbeginofinline}
+
+\def\doverbatimendofinline
+ {\the\everyverbatimendofinline}
+
+\def\doverbatimbeginofline#1% linenumber
+ {\bgroup % due to pretty status
+ \iflinepar\else\EveryPar{}\fi
+ \noindent % was wrong: \dontleavehmode
+ \xdef\dokeepverbatimlinedata % hm, still needed?
+ {\parindent \the\parindent
+ \hangindent\the\hangindent
+ \hangafter \the\hangafter
+ \leftskip \the\leftskip
+ \rightskip \the\rightskip}%
+ \egroup
+ \dokeepverbatimlinedata
+ \doopenupverbatimline
+ \the\everyline\strut
+ }%\beginverbatimline}
+
+\def\doverbatimendofline
+ {%\endverbatimline
+ \global\lineparfalse
+ \obeyedline\par}
+
+\def\doverbatimemptyline
+ {\strut
+ \par
+ \global\linepartrue}
+
+\protect \endinput
diff --git a/tex/context/base/bxml-apa.mkiv b/tex/context/base/bxml-apa.mkiv
new file mode 100644
index 000000000..5fc87e5ef
--- /dev/null
+++ b/tex/context/base/bxml-apa.mkiv
@@ -0,0 +1,613 @@
+%D \module
+%D [ file=bxml-apa,
+%D version=2010.05.14, % based on bibl-apa.tex
+%D title=APA bibliography style,
+%D subtitle=Publications,
+%D author={Taco Hoekwater \& Hans Hagen},
+%D date=\currentdate,
+%D copyright={Hans Hagen \& Taco Hoekwater}]
+%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
+
+% helpers (todo)
+
+\let\maybeyear\firstofoneargument
+\let\etalchar \firstofoneargument
+
+\setupbibtexcitationvariants
+ [author,year]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!no,
+ \c!inbetween={ },
+ \c!left={(},
+ \c!right={)}]
+
+\setupbibtexcitationvariants
+ [authoryear]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!yes,
+ \c!inbetween={ },
+ \c!left={(},
+ \c!right={)}]
+
+\setupbibtexcitationvariants
+ [authoryears]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!yes,
+ \c!inbetween={, },
+ \c!left={(},
+ \c!right={)}]
+
+\setupbibtexcitationvariants
+ [key,serial,authornum,page,short,type,doi,url]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!no,
+ \c!inbetween={ },
+ \c!left={[},
+ \c!right={]}]
+
+\setupbibtexcitationvariants
+ [num]
+ [\c!andtext={ and },
+ \c!otherstext={ et al.},
+ \c!pubsep={, },
+ \c!lastpubsep={ and },
+ \c!compress=\v!yes,
+ \c!inbetween={--},
+ \c!left={[},
+ \c!right={]}]
+
+\setupbibtexpublications
+ [\c!sorttype=,
+ \c!criterium=,
+ \c!refcommand=authoryears,
+ \c!numbering=\v!no,
+ \c!autohang=\v!no]
+
+\setupbibtexpublications
+ [\c!width=2em, % 24pt,
+ \c!artauthor=invertedshort,
+ \c!editor=invertedshort,
+ \c!author=invertedshort,
+ \c!namesep={, },
+ \c!lastnamesep={ and },
+ \c!finalnamesep={ and },
+ \c!firstnamesep={, },
+ \c!juniorsep={ },
+ \c!vonsep={ },
+ \c!surnamesep={, },
+ \c!authoretallimit=5,
+ \c!editoretallimit=5,
+ \c!artauthoretallimit=5,
+ \c!authoretaldisplay=5,
+ \c!editoretaldisplay=5,
+ \c!artauthoretaldisplay=5,
+ \c!authoretaltext={ et al.},
+ \c!editoretaltext={ et al.},
+ \c!artauthoretaltext={ et al.}]
+
+% common
+
+\startxmlsetups bibtex:apa:common:wherefrom
+ \bibxmldoifelse {address} {
+ \getvariable{bibtex:temp}{left}
+ \bibxmldoifelse {country} {
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \bibxmlflush{address}\bibtexcomma\bibxmlflush{country}: \bibxmlflush{\getvariable{bibtex:temp}{label}}
+ } {
+ \bibxmlflush{address}\bibtexcomma\bibxmlflush{country}
+ }
+ } {
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \bibxmlflush{address}\bibtexcomma\bibxmlflush{\getvariable{bibtex:temp}{label}}
+ } {
+ \bibxmlflush{address}
+ }
+ }
+ \getvariable{bibtex:temp}{right}
+ } {
+ \bibxmldoifelse {country} {
+ \getvariable{bibtex:temp}{left}
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \bibxmlflush{country}: \bibxmlflush{\getvariable{bibtex:temp}{label}}
+ } {
+ \bibxmlflush{country}
+ }
+ \getvariable{bibtex:temp}{right}
+ } {
+ \bibxmldoifelse {\getvariable{bibtex:temp}{label}} {
+ \getvariable{bibtex:temp}{left}
+ \bibxmlflush{\getvariable{bibtex:temp}{label}}
+ \getvariable{bibtex:temp}{right}
+ } {
+ \getvariable{bibtex:temp}{otherwise}
+ }
+ }
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:publisher
+ \setvariables[bibtex:temp][label=publisher,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:organization
+ \setvariables[bibtex:temp][label=organization,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:school
+ \setvariables[bibtex:temp][label=school,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:institution
+ \setvariables[bibtex:temp][label=institution,left=,right=,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:school:subsentence
+ \setvariables[bibtex:temp][label=school,left=\bibtexcomma,right=\bibtexperiod,otherwise=\bibtexperiod]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:institution:subsentence
+ \setvariables[bibtex:temp][label=institution,left=\bibtexcomma,right=\bibtexperiod,otherwise=\bibtexperiod]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:publisher:sentence
+ \setvariables[bibtex:temp][label=publisher,left=\bibtexspace,right=\bibtexperiod,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+\startxmlsetups bibtex:apa:common:organization:sentence
+ \setvariables[bibtex:temp][label=organization,left=\bibtexspace,right=\bibtexperiod,otherwise=]\relax
+ \bibxmlsetup{bibtex:apa:common:wherefrom}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:title-and-series
+ \bibxmldoif {title} {
+ \bibxmlflush{title}
+ \bibxmldoif {series} {
+ \bibtexlparent\bibxmlflush{series}\bibtexrparent
+ }
+ \bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:title-it-and-series
+ \bibxmldoif {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {series} {
+ \bibtexlparent\bibxmlflush{series}\bibtexrparent
+ }
+ \bibtexperiod
+ }
+\stopxmlsetups
+
+\disablemode[bibtex:apa:edited-book]
+
+\startxmlsetups bibtex:apa:common:author-and-year
+ \bibxmldoif {author} {
+ \bibxmlsetup{bibtex:format:author}
+ }
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:author-or-key-and-year
+ \bibxmldoifelse {author} {
+ \bibxmlsetup{bibtex:format:author}
+ } {
+ \bibxmldoif {key} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:key}\bibtexrbracket
+ }
+ }
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:author-editors-crossref-year
+ \bibxmldoif {author} {
+ \bibxmlsetup{bibtex:format:author}
+ } {
+ \bibxmldoifelse {editor} {
+ \enablemode[bibtex:apa:edited-book]
+ \xmlsetup{#1}{bibtex:format:editor}
+ \bibtexcomma\bibtexsingularplural{editor}{editors}
+ } {
+ % weird period
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket\bibtexperiod
+ }
+ }
+ }
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:editor-or-key-and-year
+ \bibxmldoifelse {editor} {
+ \enablemode[bibtex:apa:edited-book]
+ \xmlsetup{#1}{bibtex:format:editor}
+ \bibtexcomma\bibtexsingularplural{editor}{editors}
+ } {
+ \bibxmldoif {key} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:key}\bibtexrbracket
+ }
+ }
+ \bibtexspace
+ \bibxmldoif {year} {
+ \bibtexlparent\bibxmlflush{year}\bibtexrparent
+ }
+ \bibtexperiod
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:note
+ \bibxmldoif {note} {
+ \bibtexspace\bibxmlflush{note}\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:comment
+ \bibxmldoif {comment} {
+ \bibtexspace\bibxmlflush{comment}\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:pages:p
+ \bibxmldoif {pages} {
+ \bibtexspace\bibxmlflush{pages}\bibtexspace p\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:pages:pp
+ \bibxmldoif {pages} {
+ \bibtexspace\bibxmlflush{pages}\bibtexspace pp\bibtexperiod
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:pages:pages
+ \bibxmldoif {pages} {
+ \bibtexcomma pages~\bibxmlflush{pages}
+ }
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:edition:sentense
+ \bibxmldoif {edition} {
+ \bibtexspace\bibxmlflush{edition}\bibtexspace edition\bibtexperiod
+ }
+\stopxmlsetups
+
+% check ewhen the next is used (no period)
+
+% \startxmlsetups bibtex:apa:common:edition
+% \bibxmldoif {edition} {
+% \bibtexspace\bibxmlflush{edition}\bibtexspace edition
+% }
+% \stopxmlsetups
+
+% we can share more, todo
+
+% specific
+
+\startxmlsetups bibtex:apa:article
+ \bibxmlsetup{bibtex:apa:common:author-or-key-and-year}
+ \bibxmldoif {title} {
+ \bibxmlflush{title}\bibtexperiod
+ }
+ \bibxmldoifelse {journal} {
+ \bgroup\it\bibxmlflush{journal}\/\egroup
+ } {
+ \bibxmldoif {crossref} {
+ In\bibtexspace\bibxmlflush{crossref}
+ }
+ }
+ \bibxmldoifelse {volume} {
+ \bibtexcomma\bgroup\it\bibxmlflush{volume}\/\egroup
+ \bibxmldoif {issue} {
+ \bibtexlparent\bibxmlflush{issue}\bibtexlparent
+ }
+ \bibxmldoif {pages} {
+ \bibtexcomma\bibxmlflush{pages}
+ }
+ \bibtexperiod
+ } {
+ \bibxmlsetup{bibtex:apa:common:pages:pp}
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+ \bibxmlsetup{bibtex:apa:common:comment}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:book
+ \bibxmlsetup{bibtex:apa:common:author-editors-crossref-year}
+ \bibxmldoif {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \doifmodeelse {bibtex:apa:edited-book} {
+ \bibxmldoifelse {volume} {
+ \bibtexspace Number\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoifelse {series} {
+ \bibtexspace in\nonbreakablespace\bibxmlflush{series}\bibtexperiod
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibtexspace in\bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ } {
+ \bibtexperiod
+ }
+ }
+ } {
+ \bibxmldoif {series} {
+ \bibtexspace\bibxmlflush{series}
+ }
+ \bibtexperiod
+ }
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ \bibxmldoif {volume} {
+ Volume\nonbreakablespace\bibxmlflush{volume}\bibtexspace of\nonbreakablespace
+ }
+ } {
+ \bibxmldoif {volume} {
+ \bibtexcomma volume\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoif {series} {
+ \bibtexspace of\nonbreakablespace\bgroup\it\bibxmlflush{series}\/\egroup
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ }
+ }
+ }
+ }
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:publisher:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}% twice?
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:inbook
+ \bibxmlsetup{bibtex:apa:common:author-editors-crossref-year}
+ \bibxmldoifelse {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ } {
+ \doifmodeelse {bibtex:apa:edited-book} {
+ \bibxmldoifelse {volume} {
+ \bibtexspace number\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoifelse {series} {
+ \bibtexspace in\nonbreakablespace\bibxmlflush{series}\bibtexperiod
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibtexspace in\bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ } {
+ \bibtexperiod
+ }
+ }
+ } {
+ \bibxmldoif {series} {
+ \bibtexspace\bibxmlflush{series}\bibtexperiod
+ }
+ }
+ } {
+ \bibxmldoifelse {crossref} {
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibxmldoif {volume} {
+ Volume\nonbreakablespace\bibxmlflush{volume}\bibtexspace of\nonbreakablespace
+ }
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ }
+ } {
+ \bibxmldoif {volume} {
+ \bibtexcomma volume\nonbreakablespace\bibxmlflush{volume}
+ \bibxmldoif {series} {
+ \bibtexspace of\nonbreakablespace\bgroup\it\bibxmlflush{series}\/\egroup
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ }
+ }
+ }
+ }
+ \bibtexspace
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:publisher}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:booklet
+ \bibxmlsetup{bibtex:apa:common:author-or-key-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-it-and-series}
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:publication:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:manual
+ \bibxmlsetup{bibtex:apa:common:author-or-key-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-it-and-series}
+ \bibxmlsetup{bibtex:apa:common:edition:sentence}
+ \bibxmlsetup{bibtex:apa:common:organization:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:incollection
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmldoif {arttitle} {
+ \bibxmlflush{arttitle}\bibtexperiod
+ }
+ In\bibtexspace
+ \bibxmldoifelse {title} {
+ \bibxmlsetup{bibtex:format:editors}\bibtexcomma
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {series} {
+ \bibxmldoif {volume} {
+ \bibtexcomma number\bibtexspace\bibxmlflush{volume}\bibtexspace in
+ }
+ \bibtexspace\bibxmlflush{series}
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibxmldoif {edition} {
+ \bibtexspace\bibxmlflush{edition}\bibtexspace edition
+ }
+ \bibxmlsetup{bibtex:apa:common:publisher:sentence}
+ } {
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}
+ }
+ \bibtexspace
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:inproceedings
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmldoif {arttitle} {
+ \bibxmlflush{arttitle}\bibtexperiod
+ }
+ In\bibtexspace
+ \bibxmldoifelse {title} {
+ \bibxmldoif {editors} {
+ \bibxmlflush{bibtex:apa:format:editors}
+ \bibtexcomma\bibtexsingularplural{editor}{editors}\bibtexcomma
+ }
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {series} {
+ \bibxmldoif {volume} {
+ \bibtexcomma number~\bibxmlflush{volume} in
+ }
+ \bibtexspace
+ \bibxmlflush{series}
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ \bibxmlsetup{bibtex:apa:common:organization:sentence}
+ } {
+ \bibxmldoif {crossref} {
+ \bibtexlbracket\bibxmlsetup{bibtex:format:crossref}\bibtexrbracket
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:proceedings
+ \bibxmlsetup{bibtex:apa:common:editor-or-key-and-year}
+ \bibxmldoif {title} {
+ \bgroup\it\bibxmlflush{title}\/\egroup
+ \bibxmldoif {volume} {
+ \bibtexcomma number\bibtexspace\bibxmlflush{volume}\bibtexspace in\bibtexspace
+ }
+ \bibxmldoif {chapter} {
+ \bibtexcomma\bibxmlflush{chapter}\bibtexspace
+ }
+ \bibxmlsetup{bibtex:apa:common:pages:pages}
+ \bibtexperiod
+ \bibxmlsetup{bibtex:apa:common:organization:sentence}
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:common:thesis
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-it-and-series}
+ \bibxmldoifelse {type} {
+ \bibxmlflush{type}
+ } {
+ \getvariable{bibtex:temp}{label}
+ }
+ \bibxmlsetup{bibtex:apa:common:school:subsentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:mastersthesis
+ \setvariables[bibtex:temp][label=Master's thesis]
+ \bibxmlsetup{bibtex:apa:common:thesis}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:phdthesis
+ \setvariables[bibtex:temp][label=PhD thesis]
+ \bibxmlsetup{bibtex:apa:common:thesis}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:techreport
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-and-series}
+ \bibxmldoifelse {type} {
+ \bibxmlflush{type}
+ \bibxmldoif {volume} {
+ \bibtexspace\bibxmlflush{volume}
+ }
+ } {
+ \bibtexspace Technical Report
+ }
+ \bibxmlsetup{bibtex:apa:common:institution:subsentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:misc
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-and-series}
+ \bibxmlsetup{bibtex:apa:common:publisher:sentence}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\startxmlsetups bibtex:apa:unpublished
+ \bibxmlsetup{bibtex:apa:common:author-and-year}
+ \bibxmlsetup{bibtex:apa:common:title-and-series}
+ \bibxmlsetup{bibtex:apa:common:pages:p}
+ \bibxmldoif {type} {
+ \bibtexlparent\bibxmlflush{type}\bibtexrparent
+ }
+ \bibxmlsetup{bibtex:apa:common:note}
+\stopxmlsetups
+
+\protect \endinput
diff --git a/tex/context/base/catc-act.tex b/tex/context/base/catc-act.tex
new file mode 100644
index 000000000..bc24562d7
--- /dev/null
+++ b/tex/context/base/catc-act.tex
@@ -0,0 +1,61 @@
+%D \module
+%D [ file=catc-act,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Default Catcode Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 deals with some active character handling. Use
+%D with care.
+
+%D \macros
+%D {installactivecharacter}
+
+\def\installactivecharacter#1 %
+ {\edef\temp{\detokenize{#1}}%
+ \cctcounterc\expandafter`\temp\relax % relax needed
+ \expandafter\startextendcatcodetable
+ \expandafter\ctxcatcodes\expandafter\catcode\the\cctcounterc\activecatcode
+ \stopextendcatcodetable
+ \letcatcodecommand \ctxcatcodes \cctcounterc \temp \relax
+ \ifnum\currentcatcodetable=\ctxcatcodes \setcatcodetable\ctxcatcodes \fi}
+
+%D \macros
+%D {defineactivecharacter}
+%D
+%D Use this one with care, esp in combination with catcode
+%D vectors. There are better ways now.
+
+\chardef\activehackcode=`~
+
+\def\defineactivecharacter #1#2 #3%
+ {\cctcounterc\uccode\activehackcode
+ \if#1"\uccode\activehackcode\expandafter\doifnumberelse\expandafter{\string#1#2}\empty #1#2\else
+ \uccode\activehackcode\expandafter\doifnumberelse\expandafter{\string#1#2}\empty`#1#2\fi
+ \catcode\uccode\activehackcode\activecatcode
+ \uppercase{\def\next{~}}%
+ \uccode\activehackcode\cctcounterc
+ \expandafter\expandafter\expandafter\def\expandafter\next\expandafter
+ {\expandafter\dohandleactivecharacter\next{#3}}}
+
+\chardef\activecharactermode\plusone % overloading still backward compatible
+
+\def\dodohandleactivecharacter#1#2{#2}
+\def\donthandleactivecharacter#1#2{\noexpand#1}
+
+\def\dohandleactivecharacter
+ {\ifcase\activecharactermode
+ \expandafter\donthandleactivecharacter
+ \else
+ \expandafter\dodohandleactivecharacter
+ \fi}
+
+\def\makecharacteractive #1 {\catcode`#1\active}
+
+\endinput
diff --git a/tex/context/base/catc-ctx.tex b/tex/context/base/catc-ctx.tex
new file mode 100644
index 000000000..21e7d0136
--- /dev/null
+++ b/tex/context/base/catc-ctx.tex
@@ -0,0 +1,250 @@
+%D \module
+%D [ file=catc-cys,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Extra Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 prefer to define relevant catcode tables in this file instead
+%D of everywhere around.
+
+\ifdefined \ctxcatcodes \else \newcatcodetable \ctxcatcodes \fi
+\ifdefined \mthcatcodes \else \newcatcodetable \mthcatcodes \fi % math, not used, too tricky
+\ifdefined \xmlcatcodesn \else \newcatcodetable \xmlcatcodesn \fi % normal
+\ifdefined \xmlcatcodese \else \newcatcodetable \xmlcatcodese \fi % entitle
+\ifdefined \xmlcatcodesr \else \newcatcodetable \xmlcatcodesr \fi % reduce
+\ifdefined \typcatcodesa \else \newcatcodetable \typcatcodesa \fi % { }
+\ifdefined \typcatcodesb \else \newcatcodetable \typcatcodesb \fi % < >
+
+\startcatcodetable \ctxcatcodes
+ \catcode`\^^I = 10
+ \catcode`\^^M = 5
+ % \catcode`\^^J = 10 % new
+ \catcode`\^^L = 5
+ \catcode`\ = 10
+ \catcode`\^^Z = 9
+ \catcode`\\ = 0
+ \catcode`\{ = 1
+ \catcode`\} = 2
+ \catcode`\$ = 3
+ \catcode`\& = 4
+ \catcode`\# = 6
+ \catcode`\^ = 7
+ \catcode`\_ = 8
+ \catcode`\% = 14
+ \catcode`\~ = 13
+ \catcode`\| = 13
+\stopcatcodetable
+
+\startcatcodetable \prtcatcodes
+ \catcode`\^^I = 10
+ \catcode`\^^M = 5
+ \catcode`\^^L = 5
+ \catcode`\ = 10
+ \catcode`\^^Z = 9
+ \catcode`\\ = 0
+ \catcode`\{ = 1
+ \catcode`\} = 2
+ \catcode`\$ = 3
+ \catcode`\& = 4
+ \catcode`\# = 6
+ \catcode`\^ = 7
+ \catcode`\_ = 8
+ \catcode`\% = 14
+ \catcode`\@ = 11
+ \catcode`\! = 11
+ \catcode`\? = 11
+ \catcode`\~ = 13
+ \catcode`\| = 13
+\stopcatcodetable
+
+\startcatcodetable \mthcatcodes
+ \catcode`\^^I = 10
+ \catcode`\^^M = 5
+ %\catcode`\^^J = 10 % new
+ \catcode`\^^L = 5
+ \catcode`\ = 10
+ \catcode`\^^Z = 9
+ \catcode`\\ = 0
+ \catcode`\{ = 1
+ \catcode`\} = 2
+ \catcode`\$ = 3
+ \catcode`\& = 4
+ \catcode`\# = 6
+ \catcode`\^ = 7
+ \catcode`\_ = 8
+ \catcode`\% = 14
+ %\catcode`\~ = 13
+ %\catcode`\| = 13
+\stopcatcodetable
+
+\startcatcodetable \xmlcatcodesn
+ \catcode`\^^I = 10 % ascii tab is a blank space
+ \catcode`\^^M = 5 % ascii return is end-line
+ \catcode`\^^L = 5 % ascii form-feed
+ \catcode`\ = 10 % ascii space is blank space
+ \catcode`\^^Z = 9 % ascii eof is ignored
+ \catcode`\& = 13 % entity
+ \catcode`\< = 13 % element
+ \catcode`\> = 12
+ \catcode`\" = 12 % probably not needed any more
+ \catcode`\/ = 12 % probably not needed any more
+ \catcode`\' = 12 % probably not needed any more
+ \catcode`\~ = 12 % probably not needed any more
+ \catcode`\# = 12 % probably not needed any more
+ \catcode`\\ = 12 % probably not needed any more
+\stopcatcodetable
+
+\startcatcodetable \xmlcatcodese
+ \catcode`\^^I = 10 % ascii tab is a blank space
+ \catcode`\^^M = 5 % ascii return is end-line
+ \catcode`\^^L = 5 % ascii form-feed
+ \catcode`\ = 10 % ascii space is blank space
+ \catcode`\^^Z = 9 % ascii eof is ignored
+ \catcode`\& = 13 % entity
+ \catcode`\< = 13 % element
+ \catcode`\> = 12
+ \catcode`\# = 13
+ \catcode`\$ = 13
+ \catcode`\% = 13
+ \catcode`\\ = 13
+ \catcode`\^ = 13
+ \catcode`\_ = 13
+ \catcode`\{ = 13
+ \catcode`\} = 13
+ \catcode`\| = 13
+ \catcode`\~ = 13
+\stopcatcodetable
+
+\startcatcodetable \xmlcatcodesr
+ \catcode`\^^I = 10 % ascii tab is a blank space
+ \catcode`\^^M = 5 % ascii return is end-line
+ \catcode`\^^L = 5 % ascii form-feed
+ \catcode`\ = 10 % ascii space is blank space
+ \catcode`\^^Z = 9 % ascii eof is ignored
+ \catcode`\& = 13 % entity
+ \catcode`\< = 13 % element
+ \catcode`\> = 12
+ \catcode`\# = 13
+ \catcode`\$ = 13
+ \catcode`\% = 13
+ \catcode`\\ = 13
+ \catcode`\^ = 13
+ \catcode`\_ = 13
+ \catcode`\{ = 13
+ \catcode`\} = 13
+ \catcode`\| = 13
+ \catcode`\~ = 13
+\stopcatcodetable
+
+\startcatcodetable \typcatcodesa
+ \catcode`\^^I = 12
+ \catcode`\^^M = 12
+ \catcode`\^^L = 12
+ \catcode`\ = 12
+ \catcode`\^^Z = 12
+ \catcode`\{ = 1
+ \catcode`\} = 2
+\stopcatcodetable
+
+\startcatcodetable \typcatcodesb
+ \catcode`\^^I = 12
+ \catcode`\^^M = 12
+ \catcode`\^^L = 12
+ \catcode`\ = 12
+ \catcode`\^^Z = 12
+ \catcode`\< = 1
+ \catcode`\> = 2
+\stopcatcodetable
+
+\letcatcodecommand \ctxcatcodes `\| \relax
+\letcatcodecommand \ctxcatcodes `\~ \relax
+
+%letcatcodecommand \prtcatcodes `\| \relax % falls back on ctx
+%letcatcodecommand \prtcatcodes `\~ \relax % falls back on ctx
+
+\letcatcodecommand \xmlcatcodesn `\& \relax
+\letcatcodecommand \xmlcatcodesn `\< \relax
+
+\letcatcodecommand \xmlcatcodese `\& \relax
+\letcatcodecommand \xmlcatcodese `\< \relax
+
+\letcatcodecommand \xmlcatcodesr `\& \relax
+\letcatcodecommand \xmlcatcodesr `\< \relax
+
+\letcatcodecommand \xmlcatcodese `\# \relax
+\letcatcodecommand \xmlcatcodese `\$ \relax
+\letcatcodecommand \xmlcatcodese `\% \relax
+\letcatcodecommand \xmlcatcodese `\\ \relax
+\letcatcodecommand \xmlcatcodese `\^ \relax
+\letcatcodecommand \xmlcatcodese `\_ \relax
+\letcatcodecommand \xmlcatcodese `\{ \relax
+\letcatcodecommand \xmlcatcodese `\} \relax
+\letcatcodecommand \xmlcatcodese `\| \relax
+\letcatcodecommand \xmlcatcodese `\~ \relax
+
+\letcatcodecommand \xmlcatcodesr `\# \relax
+\letcatcodecommand \xmlcatcodesr `\$ \relax
+\letcatcodecommand \xmlcatcodesr `\% \relax
+\letcatcodecommand \xmlcatcodesr `\\ \relax
+\letcatcodecommand \xmlcatcodesr `\^ \relax
+\letcatcodecommand \xmlcatcodesr `\_ \relax
+\letcatcodecommand \xmlcatcodesr `\{ \relax
+\letcatcodecommand \xmlcatcodesr `\} \relax
+\letcatcodecommand \xmlcatcodesr `\| \relax
+\letcatcodecommand \xmlcatcodesr `\~ \relax
+
+ \catcodetable \ctxcatcodes
+\let\defaultcatcodetable\ctxcatcodes
+\let\xmlcatcodes \xmlcatcodesn % beware, in mkiv we use \notcatcodes
+
+\endinput
+
+% under consideration:
+%
+% \newcatcodetable\txtcatcodes
+%
+% \startcatcodetable \txtcatcodes
+% \catcode`\^^I = 10
+% \catcode`\^^M = 5
+% \catcode`\^^L = 5
+% \catcode`\ = 10
+% \catcode`\\ = 0
+% \catcode`\{ = 1
+% \catcode`\} = 2
+% \stopcatcodetable
+%
+% \newcount\relaxedcatcodedepth
+%
+% \def\startrelaxedcatcodes
+% {\global\chardef\relaxedcatcodeparent\catcodetable
+% \global\advance\relaxedcatcodedepth\plusone
+% \nonknuthmode\setcatcodetable\txtcatcodes}
+%
+% \def\stoprelaxedcatcodes
+% {\ifcase\relaxedcatcodedepth
+% % error
+% \or
+% \setcatcodetable\relaxedcatcodeparent
+% \global\relaxedcatcodedepth\zerocount
+% \else
+% \global\advance\relaxedcatcodedepth\minusone
+% \setcatcodetable\txtcatcodes
+% \fi}
+%
+% \starttext
+%
+% \startrelaxedcatcodes
+% \startcomment test \stopcomment
+% test $ test 10% whatever|test \mathematics{x^2=1}
+% \stoprelaxedcatcodes
+%
+% $x^2=1$
+%
+% \stoptext
diff --git a/tex/context/base/catc-def.tex b/tex/context/base/catc-def.tex
new file mode 100644
index 000000000..e80cfe125
--- /dev/null
+++ b/tex/context/base/catc-def.tex
@@ -0,0 +1,142 @@
+%D \module
+%D [ file=catc-def,
+%D version=2006.09.18,
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Default Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 following catcode tables are rather \CONTEXT\ independent.
+
+\ifdefined\nilcatcodes \else \newcatcodetable \nilcatcodes \fi
+\ifdefined\texcatcodes \else \newcatcodetable \texcatcodes \fi
+\ifdefined\luacatcodes \else \newcatcodetable \luacatcodes \fi
+\ifdefined\notcatcodes \else \newcatcodetable \notcatcodes \fi
+\ifdefined\vrbcatcodes \else \newcatcodetable \vrbcatcodes \fi
+\ifdefined\prtcatcodes \else \newcatcodetable \prtcatcodes \fi
+
+\startcatcodetable \nilcatcodes
+ \catcode`\^^I = 10 % ascii tab is a blank space
+ \catcode`\^^M = 5 % ascii return is end-line
+ \catcode`\^^L = 5 % ascii form-feed
+ \catcode`\ = 10 % ascii space is blank space
+ \catcode`\^^Z = 9 % ascii eof is ignored
+\stopcatcodetable
+
+\startcatcodetable \texcatcodes
+ \catcode`\^^I = 10
+ \catcode`\^^M = 5
+ \catcode`\^^L = 5
+ \catcode`\ = 10
+ \catcode`\^^Z = 9
+ \catcode`\\ = 0
+ \catcode`\{ = 1
+ \catcode`\} = 2
+ \catcode`\$ = 3
+ \catcode`\& = 4
+ \catcode`\# = 6
+ \catcode`\^ = 7
+ \catcode`\_ = 8
+ \catcode`\% = 14
+\stopcatcodetable
+
+\startcatcodetable \luacatcodes
+ \catcode`\^^I = 12 % ascii tab is a blank space
+ \catcode`\^^M = 12 % ascii return is end-line
+ \catcode`\^^L = 12 % ascii form-feed
+ \catcode`\ = 12 % ascii space is blank space
+ \catcode`\^^Z = 9 % ascii eof is ignored
+ \catcode`\\ = 0
+ \catcode`\% = 12
+ \catcode`\# = 12
+ \catcode`\_ = 12
+ \catcode`\^ = 12
+ \catcode`\& = 12
+ \catcode`\| = 12
+ \catcode`\{ = 12
+ \catcode`\} = 12
+ \catcode`\~ = 12
+ \catcode`\$ = 12
+\stopcatcodetable
+
+\startcatcodetable \notcatcodes
+ \catcode`\^^I = 10 % ascii tab is a blank space
+ \catcode`\^^M = 5 % ascii return is end-line
+ \catcode`\^^L = 5 % ascii form-feed
+ \catcode`\ = 10 % ascii space is blank space
+ \catcode`\^^Z = 9 % ascii eof is ignored
+ \catcode`\~ = 12
+ \catcode`\# = 12 % probably too much, in principle
+ \catcode`\$ = 12 % nilcatcodes would be ok too
+ \catcode`\% = 12
+ \catcode`\^ = 12
+ \catcode`\& = 12
+ \catcode`\_ = 12
+ \catcode`\< = 12
+ \catcode`\> = 12
+ \catcode`\{ = 12
+ \catcode`\} = 12
+ \catcode`\" = 12
+ \catcode`\' = 12
+ \catcode`\/ = 12
+ \catcode`\\ = 12
+ \catcode`\| = 12
+\stopcatcodetable
+
+\startcatcodetable \vrbcatcodes % probably less needed
+ \catcode`\^^I = 12
+ \catcode`\^^M = 12
+ \catcode`\^^L = 12
+ \catcode`\ = 12
+ \catcode`\^^Z = 12
+\stopcatcodetable
+
+\startcatcodetable \prtcatcodes
+ \catcode`\^^I = 10
+ \catcode`\^^M = 5
+ \catcode`\^^L = 5
+ \catcode`\ = 10
+ \catcode`\^^Z = 9
+ \catcode`\\ = 0
+ \catcode`\{ = 1
+ \catcode`\} = 2
+ \catcode`\$ = 3
+ \catcode`\& = 4
+ \catcode`\# = 6
+ \catcode`\^ = 7
+ \catcode`\_ = 8
+ \catcode`\% = 14
+ \catcode`\@ = 11
+ \catcode`\! = 11
+ \catcode`\? = 11
+ \catcode`\~ = 13
+ \catcode`\| = 13
+\stopcatcodetable
+
+%D Because some characters have a special meaning, we provide
+%D shortcuts to their character representation.
+
+\chardef\%=`\%
+\chardef\&=`\&
+\chardef\#=`\#
+\chardef\$=`\$
+\chardef\{=`\{
+\chardef\}=`\}
+\chardef\\=`\\
+\chardef\^=`\^
+\chardef\_=`\_ % but way too wide in lm, so ... until that's fixed:
+
+%def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}}
+\def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}}
+
+%D From now on we can use the protection mechanisms.
+
+\def\unprotect {\pushcatcodetable\setcatcodetable\prtcatcodes}
+\def\protect {\popcatcodetable}
+
+\endinput
diff --git a/tex/context/base/catc-ini.lua b/tex/context/base/catc-ini.lua
new file mode 100644
index 000000000..2749f403c
--- /dev/null
+++ b/tex/context/base/catc-ini.lua
@@ -0,0 +1,33 @@
+if not modules then modules = { } end modules ['catc-ini'] = {
+ version = 1.001,
+ comment = "companion to catc-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+catcodes = catcodes or { }
+catcodes.numbers = catcodes.numbers or { }
+catcodes.names = catcodes.names or { }
+
+storage.register("catcodes/numbers", catcodes.numbers, "catcodes.numbers")
+storage.register("catcodes/names", catcodes.names, "catcodes.names")
+
+-- this only happens at initime
+
+function catcodes.register(name,number)
+ catcodes.numbers[name] = number
+ local cnn = catcodes.names[number]
+ if cnn then
+ cnn[#cnn+1] = name
+ else
+ catcodes.names[number] = { name }
+ end
+ tex[name] = number
+end
+
+-- this only happens at runtime
+
+for k, v in next, catcodes.numbers do
+ tex[k] = v
+end
diff --git a/tex/context/base/catc-ini.mkii b/tex/context/base/catc-ini.mkii
new file mode 100644
index 000000000..dee15290a
--- /dev/null
+++ b/tex/context/base/catc-ini.mkii
@@ -0,0 +1,249 @@
+%D \module
+%D [ file=catc-ini,
+%D version=2006.09.18,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Catcode Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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've split the functionality of syst-cat.* over more files
+%D now so that we can load more selectively.
+
+%D A long standing wish has been the availability of catcode
+%D arrays. Because traditional \TEX\ does ot provide this we
+%D implement a fake method in the Mark II file.
+
+\ifx\zerocount\undefined \chardef \zerocount= 0 \fi
+\ifx\plusone \undefined \chardef \plusone = 1 \fi
+\ifx\minusone \undefined \newcount\minusone \minusone =-1 \fi
+
+\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 \chardef\other = 12
+\chardef\activecatcode = 13 \chardef\active = 13
+\chardef\commentcatcode = 14
+
+\newif \ifrecatcodeuppercharacters % only used in good old tex
+
+% \newcount\cctdefcounter \cctdefcounter\plusone % 0 = signal
+\newcount\cctdefcounter \cctdefcounter\zerocount % 0 = signal, so advance before allocate
+
+\newcount\cctcountera
+\newcount\cctcounterb
+\newcount\cctcounterc
+
+\def\newcatcodetable#1%
+ {\global\advance\cctdefcounter\plusone
+ \global\mathchardef#1\cctdefcounter
+ \expandafter\xdef\csname @@ccn:\number\cctdefcounter\endcsname{\string#1}% logging
+ \expandafter\newtoks\csname @@cct:\number\cctdefcounter\endcsname}
+
+\mathchardef\currentcatcodetable\zerocount
+
+\newtoks \setdefaultlowercatcodes
+\newtoks \setdefaultuppercatcodes
+
+\def\next#1% we don't have a proper loop defined yet
+ {\edef\nextnext{#1{\the#1\catcode\the\cctcountera\space
+ \ifnum\catcode\cctcountera=\lettercatcode \lettercatcode\else\othercatcode\fi}}%
+ \nextnext\ifnum\cctcountera<\cctcounterb \advance\cctcountera\plusone \expandafter\next\expandafter#1\fi}
+
+\cctcountera 0 \cctcounterb 127 \next\setdefaultlowercatcodes
+\cctcountera 128 \cctcounterb 255 \next\setdefaultuppercatcodes
+
+\recatcodeuppercharactersfalse
+
+\def\catcodetable#1%
+ {\mathchardef\currentcatcodetable#1%
+ \the\setdefaultlowercatcodes
+ \ifrecatcodeuppercharacters\the\setdefaultuppercatcodes\fi
+ \the\csname @@cct:\number#1\endcsname}
+
+\long\def\startcatcodetable#1#2\stopcatcodetable
+ {\global\csname @@cct:\number#1\endcsname{#2}}
+
+\long\def\startextendcatcodetable#1#2\stopextendcatcodetable
+ {\global\csname @@cct:\number#1\endcsname\expandafter{\the\csname @@cct:\number#1\endcsname#2}}
+
+%D The next command can be defined in a cleaner way in the
+%D Mk IV file but we want to have a fast one with a minimal
+%D chance for interference.
+
+\chardef\activehackcode=`\~
+
+%D Once a catcode is assigned, the next assignments will happen faster.
+
+% (expandable) let
+
+\def\letcatcodecommand {\afterassignment\letcatcodecommanda\cctcountera}
+\def\letcatcodecommanda{\afterassignment\letcatcodecommandb\cctcounterb}
+
+\def\letcatcodecommandb % each time
+ {\ifcsname CCL:\number\cctcountera:\number\cctcounterb\endcsname
+ \csname CCL:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \else
+ \expandafter\letcatcodecommandc
+ \fi}
+
+\def\letcatcodecommandc % only first time
+ {\expandafter\gdef\csname CCL:\number\cctcountera:\number\cctcounterb\expandafter\endcsname\expandafter
+ {\expandafter\let\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname}%
+ \reinstatecatcodecommanda
+ \csname CCL:\number\cctcountera:\number\cctcounterb\endcsname}
+
+% expandable def
+
+\def\defcatcodecommand {\afterassignment\defcatcodecommanda\cctcountera}
+\def\defcatcodecommanda{\afterassignment\defcatcodecommandb\cctcounterb}
+
+\def\defcatcodecommandb % each time
+ {\ifcsname CCD:\number\cctcountera:\number\cctcounterb\endcsname
+ \csname CCD:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \else
+ \expandafter\defcatcodecommandc
+ \fi}
+
+\def\defcatcodecommandc % only first time
+ {\expandafter\gdef\csname CCD:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\expandafter\def\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname{##1}}%
+ \reinstatecatcodecommanda
+ \csname CCD:\number\cctcountera:\number\cctcounterb\endcsname}
+
+% un expandable def (e.g. used for discretionaries)
+
+\def\uedcatcodecommand {\afterassignment\uedcatcodecommanda\cctcountera}
+\def\uedcatcodecommanda{\afterassignment\uedcatcodecommandb\cctcounterb}
+
+\def\uedcatcodecommandb % each time
+ {\ifcsname CCU:\number\cctcountera:\number\cctcounterb\endcsname
+ \csname CCU:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \else
+ \expandafter\uedcatcodecommandc
+ \fi}
+
+\def\uedcatcodecommandc % only first time
+ {\expandafter\gdef\csname CCU:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\expandafter\unexpanded\expandafter\def\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname{##1}}%
+ \reinstatecatcodecommanda
+ \csname CCU:\number\cctcountera:\number\cctcounterb\endcsname}
+
+\def\reinstatecatcodecommand{\afterassignment\reinstatecatcodecommanda\cctcounterb}
+
+\def\reinstatecatcodecommanda % can be used when a direct definition has been done
+ {\bgroup % and the selector has been lost
+ \uccode\activehackcode\cctcounterb
+ \catcode\uccode\activehackcode\activecatcode
+ \uppercase{\xdef~{\noexpand\catcodecommand{\number\cctcounterb}}}%
+ \egroup}
+
+\chardef\defaultcatcodetable\zerocount
+
+\def\catcodecommand#1%
+ {\csname CCC:\number
+ \ifcsname CCC:\number\currentcatcodetable:\number#1\endcsname
+ \currentcatcodetable \else \defaultcatcodetable
+ \fi
+ :\number#1\endcsname}
+
+%D \macros
+%D {restorecatcodes,
+%D beginrestorecatcodes,endrestorecatcodes}
+%D
+%D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we
+%D use only one auxiliary file, which deals with tables of
+%D contents, registers, two pass tracking, references etc. This
+%D file, as well as files concerning graphics, is processed when
+%D needed, which can be in the mid of typesetting verbatim.
+%D However, when reading in data in verbatim mode, we should
+%D temporary restore the normal \CATCODES, and that's exactly
+%D what the next macros do. Saving the catcodes can be
+%D disabled by saying \type{\localcatcodestrue}.
+
+\let\savedcatcodetable\relax
+
+\newcount\catcoderestorelevel
+
+\def\pushcatcodetable
+ {\advance\catcoderestorelevel\plusone
+ \tracepushcatcodetable
+ \expandafter\mathchardef\csname scct:\number\catcoderestorelevel\endcsname\currentcatcodetable}
+
+\def\popcatcodetable
+ {\ifcase\catcoderestorelevel
+ \showcatcodenestingerror
+ \else
+ \expandafter\catcodetable\csname scct:\number\catcoderestorelevel\endcsname
+ \tracepopcatcodetable
+ \advance\catcoderestorelevel\minusone
+ \fi}
+
+\def\showcatcodenestingerror % can be overloaded
+ {\immediate\write16{}%
+ \immediate\write16{Fatal error: catcode push/pop mismatch. Fix this!}\wait\end
+ \immediate\write16{}}
+
+\def\restorecatcodes % takes previous level
+ {\ifnum\catcoderestorelevel>\plusone
+ \expandafter\catcodetable\csname scct:\number\numexpr\catcoderestorelevel-1\relax\endcsname
+ \fi}
+
+\newtoks\everycatcodetable
+
+\def\setcatcodetable#1%
+ {\catcodetable#1%
+ \the\everycatcodetable
+ \tracesetcatcodetable}
+
+\def\dotracecatcodetable#1{\immediate\write16{[#1]}}
+
+\def\tracecatcodetables
+ {\def\tracesetcatcodetable {\dotracecatcodetable{set \catcodetablename\space at \number\catcoderestorelevel}}%
+ \def\tracepushcatcodetable{\dotracecatcodetable{push \catcodetablename\space from \catcodetableprev\space at \number\catcoderestorelevel}}%
+ \def\tracepopcatcodetable {\dotracecatcodetable{pop \catcodetablename\space to \catcodetableprev\space at \number\catcoderestorelevel}}}
+
+\def\catcodetableprev
+ {\ifnum\numexpr\catcoderestorelevel-1\relax>\zerocount
+ \csname @@ccn:\number\csname scct:\number\numexpr\catcoderestorelevel-1\relax\endcsname\endcsname
+ \else
+ -%
+ \fi}
+
+\def\catcodetablename
+ {\ifnum\currentcatcodetable>\zerocount
+ \csname @@ccn:\number\currentcatcodetable\endcsname
+ \else
+ -%
+ \fi}
+
+\ifx\empty\undefined \def\empty{} \fi
+
+\let\tracesetcatcodetable \empty
+\let\tracepushcatcodetable\empty
+\let\tracepopcatcodetable \empty
+
+\def\beginrestorecatcodes{\pushcatcodetable}
+\def\endrestorecatcodes {\popcatcodetable}
+
+%D Handy for debugging:
+
+% \tracecatcodetables
+
+\endinput
+
diff --git a/tex/context/base/catc-ini.mkiv b/tex/context/base/catc-ini.mkiv
new file mode 100644
index 000000000..269330a1b
--- /dev/null
+++ b/tex/context/base/catc-ini.mkiv
@@ -0,0 +1,317 @@
+%D \module
+%D [ file=catc-ini,
+%D version=2006.09.18,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Catcode Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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've split the functionality of syst-cat.* over more files
+%D now so that we can load more selectively.
+
+\registerctxluafile{catc-ini} {1.001}
+
+%D A long standing wish has been the availability of catcode
+%D arrays. Because traditional \TEX\ does not provide this we
+%D implement a fake method in the \MKII\ file. There is some
+%D overlap in code with \MKII\ but we take that for granted.
+
+\ifx\zerocount\undefined \chardef \zerocount= 0 \fi
+\ifx\plusone \undefined \chardef \plusone = 1 \fi
+\ifx\minusone \undefined \newcount\minusone \minusone =-1 \fi
+
+\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 \chardef\other = 12
+\chardef\activecatcode = 13 \chardef\active = 13
+\chardef\commentcatcode = 14
+
+\ifx\gobbleoneargument\undefined \long\def\gobbleoneargument#1{} \fi
+
+\newif \ifrecatcodeuppercharacters % only used in good old tex
+
+\newcount\cctdefcounter \cctdefcounter\zerocount % 0 = signal, so advance before allocate
+
+\newcount\cctcountera
+\newcount\cctcounterb
+\newcount\cctcounterc
+
+\def\newcatcodetable#1%
+ {\global\advance\cctdefcounter\plusone
+ \expandafter\xdef\csname @@ccn:\number\cctdefcounter\endcsname{\string#1}% logging
+ \global\chardef#1\cctdefcounter
+ \ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}%
+ % we have two ways to access catcodetable numbers
+ \startruntimectxluacode tex.\expandafter\gobbleoneargument\string#1 = \number#1 ;\stopruntimectxluacode}
+
+\newcatcodetable \scratchcatcodes \initcatcodetable\scratchcatcodes
+
+\newtoks \setdefaultcatcodes
+
+\setdefaultcatcodes
+ {\catcode`\\ \othercatcode
+ \catcode`\^^M \othercatcode
+ \catcode`\ \othercatcode
+ \catcode`\% \othercatcode
+ \catcode127 \othercatcode}
+
+\long\normalprotected\def\startcatcodetable#1#2\stopcatcodetable
+ {\bgroup
+ \catcodetable\scratchcatcodes
+ \the\setdefaultcatcodes
+ #2%
+ \savecatcodetable#1\relax
+ \egroup}
+
+\newcatcodetable\dummycatcodes
+
+\long\normalprotected\def\startextendcatcodetable#1#2\stopextendcatcodetable
+ {\bgroup
+ \catcodetable#1\relax
+ \globaldefs\plusone
+ #2%
+ \globaldefs\zerocount
+ \egroup}
+
+% ==
+%
+% \long\normalprotected\def\startextendcatcodetable#1#2\stopextendcatcodetable
+% {\bgroup
+% \scratchcounter\the\catcodetable
+% \catcodetable #1 #2
+% \catcodetable\scratchcounter
+% \egroup}
+
+\def\letcatcodecommand
+ {\afterassignment\letcatcodecommanda\cctcountera}
+
+\def\letcatcodecommanda
+ {\afterassignment\letcatcodecommandb\cctcounterb}
+
+\let\currentcatcodetable\catcodetable
+
+%D The next command can be defined in a cleaner way in the
+%D Mk IV file but we want to have a fast one with a minimal
+%D chance for interference. Do we still need this complex
+%D mechanism? Future versions of \MKIV\ might only use
+%D active characters for very special cases.
+
+\chardef\activehackcode=`\~
+
+%D Once a catcode is assigned, the next assignments will happen faster.
+
+% (expandable) let
+
+\def\letcatcodecommand {\afterassignment\letcatcodecommanda\cctcountera}
+\def\letcatcodecommanda{\afterassignment\letcatcodecommandb\cctcounterb}
+
+\def\letcatcodecommandb % each time
+ {\ifcsname CCL:\number\cctcountera:\number\cctcounterb\endcsname
+ \csname CCL:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \else
+ \expandafter\letcatcodecommandc
+ \fi}
+
+\def\letcatcodecommandc % only first time
+ {\expandafter\gdef\csname CCL:\number\cctcountera:\number\cctcounterb\expandafter\endcsname\expandafter
+ {\expandafter\let\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname}%
+ \reinstatecatcodecommandua % unexpanded
+ \csname CCL:\number\cctcountera:\number\cctcounterb\endcsname}
+
+% expandable def
+
+\def\defcatcodecommand {\afterassignment\defcatcodecommanda\cctcountera}
+\def\defcatcodecommanda{\afterassignment\defcatcodecommandb\cctcounterb}
+
+\def\defcatcodecommandb % each time
+ {\ifcsname CCD:\number\cctcountera:\number\cctcounterb\endcsname
+ \csname CCD:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \else
+ \expandafter\defcatcodecommandc
+ \fi}
+
+\def\defcatcodecommandc % only first time (we could use \normalexpanded here)
+ {\expandafter\gdef\csname CCD:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\expandafter\def\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname{##1}}%
+ \reinstatecatcodecommanda
+ \csname CCD:\number\cctcountera:\number\cctcounterb\endcsname}
+
+% unexpandable def (e.g. used for discretionaries)
+
+\def\uedcatcodecommand {\afterassignment\uedcatcodecommanda\cctcountera}
+\def\uedcatcodecommanda{\afterassignment\uedcatcodecommandb\cctcounterb}
+
+\def\uedcatcodecommandb % each time
+ {\ifcsname CCU:\number\cctcountera:\number\cctcounterb\endcsname
+ \csname CCU:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \else
+ \expandafter\uedcatcodecommandc
+ \fi}
+
+\def\uedcatcodecommandc % only first time
+ {\expandafter\gdef\csname CCU:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\expandafter\normalprotected\expandafter\def\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname{##1}}%
+ \reinstatecatcodecommandua % unexpanded
+ \csname CCU:\number\cctcountera:\number\cctcounterb\endcsname}
+
+\def\reinstatecatcodecommand{\afterassignment\reinstatecatcodecommanda\cctcounterb}
+
+\def\reinstatecatcodecommanda % can be used when a direct definition has been done
+ {\bgroup % and the selector has been lost
+ \uccode\activehackcode\cctcounterb
+ \catcode\uccode\activehackcode\activecatcode
+ \uppercase{\xdef~{\noexpand\catcodecommand{\number\cctcounterb}}}%
+ \egroup}
+
+\def\reinstatecatcodecommandua % can be used when a direct definition has been done
+ {\bgroup % and the selector has been lost
+ \uccode\activehackcode\cctcounterb
+ \catcode\uccode\activehackcode\activecatcode
+ \uppercase{\normalprotected\xdef~{\noexpand\catcodecommand{\number\cctcounterb}}}%
+ \egroup}
+
+\chardef\defaultcatcodetable\zerocount
+
+\def\catcodecommand#1%
+ {\csname CCC:\number
+ \ifcsname CCC:\number\currentcatcodetable:\number#1\endcsname
+ \currentcatcodetable \else \defaultcatcodetable
+ \fi
+ :\number#1\endcsname}
+
+%D \macros
+%D {restorecatcodes,
+%D beginrestorecatcodes,endrestorecatcodes}
+%D
+%D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we
+%D use only one auxiliary file, which deals with tables of
+%D contents, registers, two pass tracking, references etc. This
+%D file, as well as files concerning graphics, is processed when
+%D needed, which can be in the mid of typesetting verbatim.
+%D However, when reading in data in verbatim mode, we should
+%D temporary restore the normal \CATCODES, and that's exactly
+%D what the next macros do. Saving the catcodes can be
+%D disabled by saying \type{\localcatcodestrue}.
+
+\let\savedcatcodetable\relax
+
+\newcount\catcoderestorelevel
+
+\def\pushcatcodetable
+ {\advance\catcoderestorelevel\plusone
+ \tracepushcatcodetable
+ \expandafter\chardef\csname scct:\number\catcoderestorelevel\endcsname\currentcatcodetable}
+
+\def\popcatcodetable
+ {\ifcase\catcoderestorelevel
+ \showcatcodenestingerror
+ \else
+ \expandafter\catcodetable\csname scct:\number\catcoderestorelevel\endcsname
+ \tracepopcatcodetable
+ \advance\catcoderestorelevel\minusone
+ \fi}
+
+\def\showcatcodenestingerror % can be overloaded
+ {\immediate\write16{}%
+ \immediate\write16{Fatal error: catcode push/pop mismatch. Fix this!}\wait\end
+ \immediate\write16{}}
+
+\def\restorecatcodes % takes previous level
+ {\ifnum\catcoderestorelevel>\plusone
+ \expandafter\catcodetable\csname scct:\number\numexpr\catcoderestorelevel-1\relax\endcsname
+ \fi}
+
+\newtoks\everycatcodetable
+
+\def\setcatcodetable#1%
+ {\catcodetable#1%
+ \the\everycatcodetable
+ \tracesetcatcodetable}
+
+\def\dotracecatcodetable#1{\immediate\write16{[#1]}}
+
+\def\tracecatcodetables
+ {\def\tracesetcatcodetable {\dotracecatcodetable{set \catcodetablename\space at \number\catcoderestorelevel}}%
+ \def\tracepushcatcodetable{\dotracecatcodetable{push \catcodetablename\space from \catcodetableprev\space at \number\catcoderestorelevel}}%
+ \def\tracepopcatcodetable {\dotracecatcodetable{pop \catcodetablename\space to \catcodetableprev\space at \number\catcoderestorelevel}}}
+
+\def\catcodetableprev
+ {\ifnum\numexpr\catcoderestorelevel-1\relax>\zerocount
+ \csname @@ccn:\number\csname scct:\number\numexpr\catcoderestorelevel-1\relax\endcsname\endcsname
+ \else
+ -%
+ \fi}
+
+\def\catcodetablename
+ {\ifnum\currentcatcodetable>\zerocount
+ \csname @@ccn:\number\currentcatcodetable\endcsname
+ \else
+ -%
+ \fi}
+
+\ifx\empty\undefined \def\empty{} \fi
+
+\let\tracesetcatcodetable \empty
+\let\tracepushcatcodetable\empty
+\let\tracepopcatcodetable \empty
+
+\def\beginrestorecatcodes{\pushcatcodetable}
+\def\endrestorecatcodes {\popcatcodetable}
+
+%D Handy for debugging:
+
+% \tracecatcodetables
+
+%D Only in \MKIV\ (to be used when crossing pages with changed catcodes
+%D in the current vector):
+%D
+%D \starttyping
+%D \normalprotected\def\startcrap
+%D {\bgroup
+%D \pushcatcodes
+%D \whitespace
+%D \obeylines
+%D \activatespacehandler\v!yes
+%D \strut}
+%D
+%D \normalprotected\def\stopcrap
+%D {\popcatcodes
+%D \egroup}
+%D \stoptyping
+
+\newcount\catcodetablelevel
+
+\def\pushcatcodes
+ {\bgroup
+ \global\advance\catcodetablelevel\plusone
+ \ifcsname @@ccf:\number\catcodetablelevel\endcsname \else
+ \global\advance\cctdefcounter\plusone
+ \expandafter\global\expandafter\chardef\csname @@ccf:\number\catcodetablelevel\endcsname\cctdefcounter
+ \fi
+ \catcodetable\ctxcatcodes
+ \expandafter\savecatcodetable\csname @@ccf:\number\catcodetablelevel\endcsname
+ \egroup
+ \expandafter\catcodetable\csname @@ccf:\number\catcodetablelevel\endcsname}
+
+\def\popcatcodes
+ {\global\advance\catcodetablelevel\minusone}
+
+\endinput
+
diff --git a/tex/context/base/catc-sym.tex b/tex/context/base/catc-sym.tex
new file mode 100644
index 000000000..067e192c8
--- /dev/null
+++ b/tex/context/base/catc-sym.tex
@@ -0,0 +1,187 @@
+%D \module
+%D [ file=catc-sym,
+%D version=1997.01.03, % moved code
+%D title=\CONTEXT\ Catcode Macros,
+%D subtitle=Some Handy Constants,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% we now have loaded syst-* so we have all @@catcode constants
+
+%D We want to have access to the raw alternatives of the
+%D special characters. We use a \type {\xdef} instead of
+%D \type {\let} because we need an expandable token in a
+%D \type {\write}.
+
+\bgroup
+
+\catcode`B=\begingroupcatcode
+\catcode`E=\endgroupcatcode
+\catcode`.=\escapecatcode
+
+.catcode `.{ 12 .xdef .letteropenbrace B.string{E
+.catcode `.} 12 .xdef .letterclosebrace B.string}E
+.catcode `.& 12 .xdef .letterampersand B.string&E
+.catcode `.< 12 .xdef .letterless B.string 12 .xdef .lettermore B.string>E
+.catcode `.# 12 .xdef .letterhash B.string#E
+.catcode `." 12 .xdef .letterdoublequote B.string"E
+.catcode `.' 12 .xdef .lettersinglequote B.string'E
+.catcode `.$ 12 .xdef .letterdollar B.string$E
+.catcode `.% 12 .xdef .letterpercent B.string%E
+.catcode `.^ 12 .xdef .letterhat B.string^E
+.catcode `._ 12 .xdef .letterunderscore B.string_E
+.catcode `.| 12 .xdef .letterbar B.string|E
+.catcode `.~ 12 .xdef .lettertilde B.string~E
+.catcode `.\ 12 .xdef .letterbackslash B.string\E
+.catcode `./ 12 .xdef .letterslash B.string/E
+.catcode `.? 12 .xdef .letterquestionmark B.string?E
+.catcode `.! 12 .xdef .letterexclamationmark B.string!E
+.catcode `.@ 12 .xdef .letterat B.string@E
+.catcode `.: 12 .xdef .lettercolon B.string:E
+
+ .global .let .letterescape .letterbackslash
+ .global .let .letterbgroup .letteropenbrace
+ .global .let .letteregroup .letterclosebrace
+ .global .let .letterleftbrace .letteropenbrace
+ .global .let .letterrightbrace .letterclosebrace
+
+.egroup
+
+%D \macros
+%D {uncatcodespecials,setnaturalcatcodes,setnormalcatcodes,
+%D uncatcodecharacters,uncatcodeallcharacters,
+%D uncatcodespacetokens}
+%D
+%D The following macros are more or less replaced by switching
+%D to a catcode table (which we simulate in \MKII) but we keep
+%D them for convenience and compatibility. Some old engine code
+%D has been removed.
+
+\def\uncatcodespecials {\setcatcodetable\nilcatcodes \uncatcodespacetokens}
+\def\setnaturalcatcodes {\setcatcodetable\nilcatcodes}
+\def\setnormalcatcodes {\setcatcodetable\ctxcatcodes} % maybe \texcatcodes
+\def\uncatcodecharacters {\setcatcodetable\nilcatcodes} % was fast version, gone now
+\def\uncatcodeallcharacters{\setcatcodetable\nilcatcodes} % was slow one, with restore
+
+\def\uncatcodespacetokens
+ {\catcode`\ =\spacecatcode
+ \catcode`\^^L=\ignorecatcode
+ \catcode`\^^M=\endoflinecatcode
+ \catcode`\^^?=\ignorecatcode}
+
+%D \macros
+%D {setverbosecharacter,setverbosecscharacters}
+%D
+%D Next follows a definition that lets some shortcuts expand to
+%D themselves. This macro is meant for \POSTSCRIPT\ and \PDF\
+%D code passed on to the backend.
+
+\newtoks\everyverbosechacters
+
+\def\setverbosecscharacter#1%
+ {\edef#1{\string#1}}
+
+\def\setverbosecscharacters
+ {\the\everyverbosechacters}
+
+\bgroup
+
+ % if used often we can move the code inline
+
+ \catcode`\|=\activecatcode
+ \catcode`\~=\activecatcode
+
+ \global \everyverbosechacters =
+ {\setverbosecscharacter |\setverbosecscharacter ~% context specific
+ \setverbosecscharacter\|\setverbosecscharacter\~%
+ \setverbosecscharacter\:\setverbosecscharacter\;%
+ \setverbosecscharacter\+\setverbosecscharacter\-%
+ \setverbosecscharacter\[\setverbosecscharacter\]%
+ \setverbosecscharacter\.\setverbosecscharacter\\%
+ \setverbosecscharacter\)\setverbosecscharacter\(%
+ \setverbosecscharacter\0\setverbosecscharacter\1%
+ \setverbosecscharacter\2\setverbosecscharacter\3%
+ \setverbosecscharacter\4\setverbosecscharacter\5%
+ \setverbosecscharacter\6\setverbosecscharacter\7%
+ \setverbosecscharacter\8\setverbosecscharacter\9%
+ \setverbosecscharacter\n\setverbosecscharacter\s%
+ \setverbosecscharacter\/}
+
+\egroup
+
+%D (Inspired by a discussion on the \CONTEXT\ mailing list)
+%D
+%D In \TEX\ each character can have one of 16 catcodes. This way the
+%D backslash, dollar, ampersand, hash and some more characters get
+%D their special meaning. If you want to process tokens under a
+%D certain catcode regime, passing arguments can interfere badly.
+%D
+%D \startbuffer[a]
+%D \def\whatever#1{[#1]}
+%D \whatever{whatever \type {\whatever{you want}} $or$ not!}
+%D \stopbuffer
+%D
+%D \typebuffer[a]
+%D
+%D Here we pass an argument to \type {\whatever} but part of that
+%D argument is to be processed under a different catcode regime, i.e.\
+%D all characters that need to be typeset verbatim need to get
+%D the catcode that makes it a letter. This is what we get when we typeset
+%D the text verbatim:
+%D
+%D \starttyping
+%D whatever \type {\whatever{you want}} $or$ not!
+%D \stoptyping
+%D
+%D However, when passed to \type {\whatever} we get:
+%D
+%D \getbuffer[a]
+%D
+%D In \ETEX\ one can use \type {\scantokens} to circumvent this problem.
+%D
+%D \startbuffer[b]
+%D \def\rescan#1{\scantokens{#1}}
+%D \def\whatever#1{[\rescan{#1}]}
+%D \whatever{whatever \type {\whatever{you want}} $or$ not!}
+%D \stopbuffer
+%D
+%D \getbuffer[b] \typebuffer[b]
+%D
+%D This time the \type {\whatever} call gives:
+%D
+%D \getbuffer[b]
+%D
+%D In this example, two spaces have crept in. The first one, after the
+%D macro name, is inserted by \TEX\ and cannot be avoided. The last space
+%D is inserted by \type {\scantokens}, and is the consequence of the fact
+%D that this macro mimics reading from a file. You can avoid the last
+%D space by a slightly different definition:
+%D
+%D \startbuffer[c]
+%D \def\rescan#1{\scantokens{#1\ignorespaces}}
+%D \def\whatever#1{[\rescan{#1}]}
+%D \whatever{whatever \type {\whatever{you want}} $or$ not!}
+%D \stopbuffer
+%D
+%D \typebuffer[c]
+%D
+%D Unfortunately we still keep the first space, but at least it's better than
+%D a failure:
+%D
+%D \getbuffer[c]
+
+\long\def\rescan#1{\scantokens{#1\ignorespaces}}
+\long\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantokens{#2\ignorespaces}\endgroup}
+
+\ifx\scantextokens\undefined \else
+ \long\def\rescan#1{\scantextokens{#1}}
+ \long\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantextokens{#2}\endgroup}
+\fi
+
+\endinput
diff --git a/tex/context/base/char-act.mkiv b/tex/context/base/char-act.mkiv
new file mode 100644
index 000000000..2dc7823f0
--- /dev/null
+++ b/tex/context/base/char-act.mkiv
@@ -0,0 +1,138 @@
+%D \module
+%D [ file=char-act,
+%D version=2006.12.05,
+%D title=\CONTEXT\ Character Support,
+%D subtitle=Active,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Character Support / Active}
+
+\unprotect
+
+%D \macros
+%D {processingverbatim}
+%D
+%D Typesetting a file in most cases results in more than one
+%D page. Because we don't want problems with files that are
+%D read in during the construction of the page, we set \type
+%D {\ifprocessingverbatim}, so the output routine can adapt
+%D its behavior. Originally we used \type {\scratchread}, but
+%D because we want to support nesting, we decided to use a
+%D separate input file.
+
+\newif\ifprocessingverbatim
+
+%D \macros
+%D {obeyedspace, obeyedtab, obeyedline, obeyedpage}
+%D
+%D We have followed Knuth in naming macros that make \SPACE,
+%D \NEWLINE\ and \NEWPAGE\ active and assigning them
+%D \type{\obeysomething}, but first we set some default values.
+
+\def\obeyedspace {\ifprocessingverbatim\hbox{ }\else\space\fi}
+\def\obeyedtab {\obeyedspace}
+\def\obeyedline {\par}
+\def\obeyedpage {\vfill\eject}
+
+%D \macros
+%D {controlspace,setcontrolspaces}
+%D
+%D First we define \type{\obeyspaces}. When we want visible
+%D spaces (control spaces) we only have to adapt the definition
+%D of \type{\obeyedspace} to:
+
+\def\controlspace{\hbox{\char32}} % rather tex
+\def\normalspace { }
+\def\normalspaces{\catcode`\ =\@@space}
+
+\bgroup
+\catcode`\ =\@@active
+\gdef\obeyspaces{\catcode`\ =\@@active\def {\obeyedspace}}
+\gdef\setcontrolspaces{\catcode`\ =\@@active\def {\controlspace}}
+\egroup
+
+%D \macros
+%D {obeytabs, obeylines, obeypages,ignoretabs, ignorelines, ignorepages}
+%D
+%D Next we take care of \NEWLINE\ and \NEWPAGE\ and because we
+%D want to be able to typeset listings that contain \TAB, we
+%D have to handle those too. Because we have to redefine the
+%D \NEWPAGE\ character locally, we redefine the meaning of
+%D this (often already) active character.
+
+\catcode`\^^L=\@@active \def^^L{\par}
+
+%D The following indirect definitions enable us to implement
+%D all kind of \type{\obeyed} handlers.
+
+\bgroup
+
+\catcode`\^^I=\@@active
+\catcode`\^^M=\@@active
+\catcode`\^^L=\@@active
+
+\gdef\obeytabs {\catcode`\^^I=\@@active\def^^I{\obeyedtab}}
+\gdef\obeylines {\catcode`\^^M=\@@active\def^^M{\obeyedline}}
+\gdef\obeypages {\catcode`\^^L=\@@active\def^^L{\obeyedpage}}
+
+\gdef\ignoretabs {\catcode`\^^I=\@@active\def^^I{\obeyedspace}}
+\gdef\ignorelines {\catcode`\^^M=\@@active\def^^M{\obeyedspace}}
+\gdef\ignorepages {\catcode`\^^L=\@@ignore} % \@@active\def^^L{\obeyedline}}
+\gdef\ignoreeofs {\catcode`\^^Z=\@@ignore}
+
+\egroup
+
+%D \macros
+%D {naturaltextext}
+%D
+%D When one uses \ETEX, switching to normal \TEX\ is possible
+%D too. We also introduce a switch that can be used in the
+%D drivers and set in higher level shell macros.
+
+\def\naturaltextext#1\relax
+ {\bgroup
+ \def\ascii{#1}%
+ \setcatcodetable\ctxcatcodes
+ \prettynaturalfont{\scantextokens\expandafter{\ascii}\ifhmode\unskip\fi}%
+ \egroup}
+
+%D What-a-mess:
+
+% \def\normalspacecodes
+% {\catcode`\^^I = 10
+% \catcode`\^^M = 5
+% \catcode`\^^L = 5
+% \catcode`\ = 10
+% \catcode`\^^Z = 9 }
+
+% \appendtoks
+% \normalspacecodes
+% \to \everybeforeoutput
+
+\endinput \protect
+
+% obsolete (old hack for idris)
+
+%D This is a hack, and only meant for special situations. We don't
+%D support this in for instance verbatim. The active characters map
+%D onto the \CONTEXT\ names and font handling etc. is up to the user.
+
+%D This feature is obsolete.
+
+\registerctxluafile{char-act}{1.001}
+
+\def\enableactiveutf {\ctxlua{characters.active.enable()}}
+\def\disableactiveutf{\ctxlua{characters.active.disable()}}
+\def\testactiveutf #1{\ctxlua{characters.active.test("#1")}}
+
+%D Usage:
+%D
+%D \starttyping
+%D \enableactiveutf \testactiveutf{eacute}
+%D \stoptyping
diff --git a/tex/context/base/char-cmp.lua b/tex/context/base/char-cmp.lua
new file mode 100644
index 000000000..c7deb7901
--- /dev/null
+++ b/tex/context/base/char-cmp.lua
@@ -0,0 +1,268 @@
+if not modules then modules = { } end modules ['char-cmp'] = {
+ version = 1.001,
+ comment = "companion to char-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+local unpack = unpack or table.unpack
+
+characters = characters or { }
+characters.uncomposed = characters.uncomposed or { }
+
+--[[ldx--
+
The code defined here may move to the big character table.
The next three tables can for instance be be used to enhance
+kerning tables that lack kerning pairs for these special characters.
+Of course they may come in handy elsewhere too
The following function is used in the indexing code, where
+we need some sort of default fallback mapping.
+--ldx]]--
+
+function characters.uncompose(n) -- n == string|number, returns string
+ local cdn
+ if type(n) == "string" then
+ cdn = characters.data[utf.byte(n)]
+ else
+ cdn = characters.data[n]
+ end
+ -- return characters.shape(n)
+ if cdn then
+ local shcode = cdn.shcode
+ if not shcode then
+ return characters.uncomposed.both[cdn.contextname] or n
+ elseif type(shcode) == "table" then
+ return utf.char(unpack(cdn.shcode))
+ else
+ return utf.char(cdn.shcode)
+ end
+ end
+ return n
+end
+
+--[[ldx--
+
Only characters with a code smaller than 128 make sense,
+anything larger is encoding dependent. An interesting complication
+is that a character can be in an encoding twice but is hashed
+once.
This module implements some methods and creates additional datastructured
+from the big character table that we use for all kind of purposes:
+char-def.lua.
+
+
We assume that at this point characters.data is already
+loaded!
At this point we assume that the big data table is loaded. From this
+table we derive a few more.
+--ldx]]--
+
+if not characters.fallbacks then
+
+ characters.fallbacks = { }
+ characters.directions = { }
+
+ local fallbacks = characters.fallbacks
+ local directions = characters.directions
+
+ for k,v in next, data do
+ local specials = v.specials
+ if specials and specials[1] == "compat" and specials[2] == 0x0020 and specials[3] then
+ local s = specials[3]
+ fallbacks[k] = s
+ fallbacks[s] = k
+ end
+ directions[k] = v.direction
+ end
+
+end
+
+storage.register("characters.fallbacks", characters.fallbacks, "characters.fallbacks")
+storage.register("characters.directions", characters.directions, "characters.directions")
+
+--[[ldx--
+
The context namespace is used to store methods and data
+which is rather specific to .
+--ldx]]--
+
+--[[ldx--
+
Instead of using a file to define the named glyphs, we
+use the table. After all, we have this information available anyway.
+--ldx]]--
+
+function characters.makeactive(n,name) -- let ?
+ texsprint(ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name))
+end
+
+function tex.uprint(n)
+ texsprint(ctxcatcodes,utfchar(n))
+end
+
+local template_a = "\\startextendcatcodetable{%s}\\chardef\\l=11\\chardef\\a=13\\let\\c\\catcode%s\\let\\a\\undefined\\let\\l\\undefined\\let\\c\\undefined\\stopextendcatcodetable"
+local template_b = "\\chardef\\l=11\\chardef\\a=13\\let\\c\\catcode%s\\let\\a\\undefined\\let\\l\\undefined\\let\\c\\undefined"
+
+-- we need a function for setting the codes ....
+
+function characters.define(tobelettered, tobeactivated) -- catcodetables
+ local is_character, is_command, is_letter = characters.is_character, characters.is_command, characters.is_letter
+ local lettered, activated = { }, { }
+ for u, chr in next, data do
+ -- we can use a macro instead of direct settings
+ local fallback = chr.fallback
+ if fallback then
+ -- texprint(format("{\\catcode %s=13\\unexpanded\\gdef %s{\\checkedchar{%s}{%s}}}",u,utfchar(u),u,fallback))
+ texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}") -- no texprint
+ activated[#activated+1] = "\\c"..u.."\\a"
+ else
+ local contextname = chr.contextname
+ local category = chr.category
+ if contextname then
+ if is_character[category] then
+ -- by this time, we're still in normal catcode mode
+ -- subtle: not "\\",contextname but "\\"..contextname
+ if chr.unicodeslot < 128 then
+ -- texprint(ctxcatcodes, "\\chardef\\"..contextname,"=",u)
+ texprint(ctxcatcodes,format("\\chardef\\%s=%s",contextname,u))
+ else
+ -- texprint(ctxcatcodes, "\\let\\"..contextname,"=",utfchar(u))
+ texprint(ctxcatcodes,format("\\let\\%s=%s",contextname,utfchar(u)))
+ if is_letter[category] then
+ lettered[#lettered+1] = "\\c"..u.."\\l"
+ end
+ end
+ elseif is_command[category] then
+ -- this might change: contextcommand ipv contextname
+ -- texprint(format("{\\catcode %s=13\\unexpanded\\gdef %s{\\%s}}",u,utfchar(u),contextname))
+ texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}") -- no texprint
+ activated[#activated+1] = "\\c"..u.."\\a"
+ end
+ elseif is_letter[category] then
+ if u >= 128 and u <= 65536 then -- catch private mess
+ lettered[#lettered+1] = "\\c"..u.."\\l"
+ end
+ end
+ end
+ if chr.range then
+ lettered[#lettered+1] = format('\\dofastrecurse{"%05X}{"%05X}{1}{\\c\\fastrecursecounter\\l}',u,chr.range)
+ end
+ end
+ -- if false then
+ lettered[#lettered+1] = "\\c"..0x200C.."\\l" -- non-joiner
+ lettered[#lettered+1] = "\\c"..0x200D.."\\l" -- joiner
+ -- fi
+ if tobelettered then
+ lettered = concat(lettered)
+ if true then
+ texsprint(ctxcatcodes,format(template_b,lettered))
+ else
+ for l=1,#tobelettered do
+ texsprint(ctxcatcodes,format(template_a,tobelettered[l],lettered))
+ end
+ end
+ end
+ if tobeactivated then
+ activated = concat(activated)
+ for a=1,#tobeactivated do
+ texsprint(ctxcatcodes,format(template_a,tobeactivated[a],activated))
+ end
+ end
+end
+
+function characters.charcode(box)
+ local b = tex.box[box]
+ local l = b.list
+ texsprint((l and l.id == node.id('glyph') and l.char) or 0)
+end
+
+--[[ldx--
+
Setting the lccodes is also done in a loop over the data table.
+--ldx]]--
+
+-- we need a function ...
+
+function characters.setcodes()
+ for code, chr in next, data do
+ local cc = chr.category
+ if cc == 'll' or cc == 'lu' or cc == 'lt' then
+ local lc, uc = chr.lccode, chr.uccode
+ if not lc then chr.lccode, lc = code, code end
+ if not uc then chr.uccode, uc = code, code end
+ texsprint(ctxcatcodes,format("\\setcclcuc{%i}{%i}{%i}",code,lc,uc))
+ end
+ if cc == "lu" then
+ texprint(ctxcatcodes,"\\sfcode ",code,"999 ")
+ end
+ if cc == "lo" and chr.range then
+ texsprint(ctxcatcodes,format('\\dofastrecurse{"%05X}{"%05X}{1}{\\setcclcucself\\fastrecursecounter}',code,chr.range))
+ end
+ end
+end
+
+--[[ldx--
+
Next comes a whole series of helper methods. These are (will be) part
+of the official .
+--ldx]]--
+
+--[[ldx--
+
This converts a string (if given) into a number.
+--ldx]]--
+
+function characters.number(n)
+ if type(n) == "string" then return tonumber(n,16) else return n end
+end
+
+--[[ldx--
+
Checking for valid characters.
+--ldx]]--
+
+function characters.is_valid(s)
+ return s or ""
+end
+
+function characters.checked(s, default)
+ return s or default
+end
+
+characters.valid = characters.is_valid
+
+--[[ldx--
+
+--ldx]]--
+-- set a table entry; index is number (can be different from unicodeslot)
+
+function characters.set(n, c)
+ data[characters.number(n)] = c
+end
+
+--[[ldx--
+
Get a table entry happens by number. Keep in mind that the unicodeslot
+can be different (not likely).
+--ldx]]--
+
+function characters.uccode(n) return data[n].uccode or n end
+function characters.lccode(n) return data[n].lccode or n end
+
+function characters.flush(n)
+ local c = data[n]
+ if c and c.contextname then
+ texsprint(texcatcodes, "\\"..c.contextname)
+ else
+ texsprint(utfchar(n))
+ end
+end
+
+function characters.shape(n)
+ local shcode = data[n].shcode
+ if not shcode then
+ return n, nil
+ elseif type(shcode) == "table" then
+ return shcode[1], shcode[#shcode]
+ else
+ return shcode, nil
+ end
+end
+
+--[[ldx--
+
Categories play an important role, so here are some checkers.
When a sequence of characters enters the application, it may
+be neccessary to collapse subsequences into their composed variant.
+
+
This module implements methods for collapsing and expanding
+sequences. We also provide means to deal with characters that are
+special to as well as 8-bit characters that need to end up
+in special kinds of output (for instance ).
+
+
We implement these manipulations as filters. One can run multiple filters
+over a string.
It only makes sense to collapse at runtime, since we don't expect
+source code to depend on collapsing.
+--ldx]]--
+
+function utffilters.initialize()
+ if utffilters.collapsing and not utffilters.initialized then
+ for k,v in next, characters.data do
+ -- using vs and first testing for length is faster (.02->.01 s)
+ local vs = v.specials
+ if vs and #vs == 3 and vs[1] == 'char' then
+ local first, second = utfchar(vs[2]), utfchar(vs[3])
+ local cgf = graphemes[first]
+ if not cgf then
+ cgf = { }
+ graphemes[first] = cgf
+ end
+ cgf[second] = utfchar(k)
+ end
+ end
+ utffilters.initialized = true
+ end
+end
+
+-- utffilters.add_grapheme(utfchar(318),'l','\string~')
+-- utffilters.add_grapheme('c','a','b')
+
+function utffilters.add_grapheme(result,first,second)
+ local r, f, s = tonumber(result), tonumber(first), tonumber(second)
+ if r then result = utfchar(r) end
+ if f then first = utfchar(f) end
+ if s then second = utfchar(s) end
+ if not graphemes[first] then
+ graphemes[first] = { [second] = result }
+ else
+ graphemes[first][second] = result
+ end
+end
+
+function utffilters.collapse(str) -- old one
+ if utffilters.collapsing and str and #str > 1 then
+ if not utffilters.initialized then -- saves a call
+ utffilters.initialize()
+ end
+ local tokens, first, done = { }, false, false
+ for second in utfcharacters(str) do
+ local cgf = graphemes[first]
+ if cgf and cgf[second] then
+ first, done = cgf[second], true
+ elseif first then
+ tokens[#tokens+1] = first
+ first = second
+ else
+ first = second
+ end
+ end
+ if done then
+ tokens[#tokens+1] = first
+ return concat(tokens)
+ end
+ end
+ return str
+end
+
+--[[ldx--
+
In order to deal with 8-bit output, we need to find a way to
+go from to 8-bit. This is handled in the
+ engine itself.
+
+
This leaves us problems with characters that are specific to
+ like {}, $ and alike.
+
+
We can remap some chars that tex input files are sensitive for to
+a private area (while writing to a utility file) and revert then
+to their original slot when we read in such a file. Instead of
+reverting, we can (when we resolve characters to glyphs) map them
+to their right glyph there.
+
+
For this purpose we can use the private planes 0x0F0000 and
+0x100000.
+--ldx]]--
+
+utffilters.private = {
+ high = { },
+ low = { },
+ escapes = { },
+}
+
+local low = utffilters.private.low
+local high = utffilters.private.high
+local escapes = utffilters.private.escapes
+local special = "~#$%^&_{}\\|"
+
+function utffilters.private.set(ch)
+ local cb
+ if type(ch) == "number" then
+ cb, ch = ch, utfchar(ch)
+ else
+ cb = utfbyte(ch)
+ end
+ if cb < 256 then
+ low[ch] = utfchar(0x0F0000 + cb)
+ high[utfchar(0x0F0000 + cb)] = ch
+ escapes[ch] = "\\" .. ch
+ end
+end
+
+function utffilters.private.replace(str) return utfgsub(str,"(.)", low ) end
+function utffilters.private.revert(str) return utfgsub(str,"(.)", high ) end
+function utffilters.private.escape(str) return utfgsub(str,"(.)", escapes) end
+
+local set = utffilters.private.set
+
+for ch in gmatch(special,".") do set(ch) end
+
+--[[ldx--
+
We get a more efficient variant of this when we integrate
+replacements in collapser. This more or less renders the previous
+private code redundant. The following code is equivalent but the
+first snippet uses the relocated dollars.
+
+
+[x] [$x$]
+
+--ldx]]--
+
+local cr = utffilters.private.high -- kan via een lpeg
+local cf = utffilters
+
+--[[ldx--
+
The next variant has lazy token collecting, on a 140 page mk.tex this saves
+about .25 seconds, which is understandable because we have no graphmes and
+not collecting tokens is not only faster but also saves garbage collecting.
+
+--ldx]]--
+
+-- lpeg variant is not faster
+
+function utffilters.collapse(str) -- not really tested (we could preallocate a table)
+ if cf.collapsing and str then
+ if #str > 1 then
+ if not cf.initialized then -- saves a call
+ cf.initialize()
+ end
+ local tokens, first, done, n = { }, false, false, 0
+ for second in utfcharacters(str) do
+ if done then
+ local crs = cr[second]
+ if crs then
+ if first then
+ tokens[#tokens+1] = first
+ end
+ first = crs
+ else
+ local cgf = graphemes[first]
+ if cgf and cgf[second] then
+ first = cgf[second]
+ elseif first then
+ tokens[#tokens+1] = first
+ first = second
+ else
+ first = second
+ end
+ end
+ else
+ local crs = cr[second]
+ if crs then
+ for s in utfcharacters(str) do
+ if n == 1 then
+ break
+ else
+ tokens[#tokens+1], n = s, n - 1
+ end
+ end
+ if first then
+ tokens[#tokens+1] = first
+ end
+ first, done = crs, true
+ else
+ local cgf = graphemes[first]
+ if cgf and cgf[second] then
+ for s in utfcharacters(str) do
+ if n == 1 then
+ break
+ else
+ tokens[#tokens+1], n = s, n -1
+ end
+ end
+ first, done = cgf[second], true
+ else
+ first, n = second, n + 1
+ end
+ end
+ end
+ end
+ if done then
+ tokens[#tokens+1] = first
+ return concat(tokens) -- seldom called
+ end
+ elseif #str > 0 then
+ return cr[str] or str
+ end
+ end
+ return str
+end
+
+--[[ldx--
+
Next we implement some commands that are used in the user interface.
+--ldx]]--
+
+function utf.split(str)
+ local t = { }
+ for snippet in utfcharacters(str) do
+ t[#t+1] = snippet
+ end
+ return t
+end
+
+function utf.each(str,fnc)
+ for snippet in utfcharacters(str) do
+ fnc(snippet)
+ end
+end
diff --git a/tex/context/base/char-utf.mkiv b/tex/context/base/char-utf.mkiv
new file mode 100644
index 000000000..16b4029d8
--- /dev/null
+++ b/tex/context/base/char-utf.mkiv
@@ -0,0 +1,47 @@
+%D \module
+%D [ file=char-utf,
+%D version=2006.12.05,
+%D title=\CONTEXT\ Character Support,
+%D subtitle=Unicode UTF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Character Support / Unicode UTF}
+
+%D After a bit of experimenting we reached a clean state where \UTF\
+%D 8, 16 and 32 were supported as well as collapsing (combining
+%D sequences). Writing the code was a relaxed experience, not in the
+%D last place because it was accompanied by listening to those nice
+%D Vienna Teng cd's (who decided that making music was more fun than
+%D programming, but then, she may not know \TEX\ and \LUA).
+
+\unprotect
+
+\registerctxluafile{char-utf}{1.001}
+
+%D We enable collapsing (combining characters) by default, but
+%D since the source files are rather simple, we postpone the
+%D initialization till runtime.
+
+\appendtoks
+ \ctxlua {
+ characters.filters.utf.collapsing = true
+ resolvers.install_text_filter('utf',characters.filters.utf.collapse)
+ }%
+\to \everyjob
+
+%D The next one influences input parsing.
+%D
+%D \starttyping
+%D \definecomposedutf 318 108 126 % lcaron
+%D \stoptyping
+
+\unexpanded\def\definecomposedutf#1 #2 #3 %
+ {\ctxlua{characters.filters.utf.add_grapheme("#1","#2","#3")}}
+
+\protect
diff --git a/tex/context/base/chem-ini.lua b/tex/context/base/chem-ini.lua
new file mode 100644
index 000000000..908749092
--- /dev/null
+++ b/tex/context/base/chem-ini.lua
@@ -0,0 +1,75 @@
+if not modules then modules = { } end modules ['chem-ini'] = {
+ version = 1.001,
+ comment = "companion to chem-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, texsprint = string.format, tex.sprint
+local lpegmatch = lpeg.match
+
+local trace_molecules = false trackers.register("chemistry.molecules", function(v) trace_molecules = v end)
+
+local ctxcatcodes = tex.ctxcatcodes
+
+chemicals = chemicals or { }
+
+--[[
+
The next code is an adaptation of code from Wolfgang Schuster
+as posted on the mailing list. This version supports nested
+braces and unbraced integers as scripts. We could consider
+spaces as terminals for them but first let collect a bunch
+of input then.
+]]--
+
+-- some lpeg, maybe i'll make an syst-lpg module
+
+local lowercase = lpeg.R("az")
+local uppercase = lpeg.R("AZ")
+local backslash = lpeg.P("\\")
+local csname = backslash * lpeg.P(1) * (1-backslash)^0
+local plus = lpeg.P("+") / "\\textplus "
+local minus = lpeg.P("-") / "\\textminus "
+local digit = lpeg.R("09")
+local sign = plus + minus
+local cardinal = digit^1
+local integer = sign^0 * cardinal
+
+local leftbrace = lpeg.P("{")
+local rightbrace = lpeg.P("}")
+local nobrace = 1 - (leftbrace + rightbrace)
+local nested = lpeg.P { leftbrace * (csname + sign + nobrace + lpeg.V(1))^0 * rightbrace }
+local any = lpeg.P(1)
+
+local subscript = lpeg.P("_")
+local superscript = lpeg.P("^")
+local somescript = subscript + superscript
+
+--~ local content = lpeg.Cs(nested + integer + sign + any)
+local content = lpeg.Cs(csname + nested + sign + any)
+
+-- could be made more efficient
+
+local lowhigh = lpeg.Cc("\\lohi{%s}{%s}") * subscript * content * superscript * content / format
+local highlow = lpeg.Cc("\\hilo{%s}{%s}") * superscript * content * subscript * content / format
+local low = lpeg.Cc("\\low{%s}") * subscript * content / format
+local high = lpeg.Cc("\\high{%s}") * superscript * content / format
+local justtext = (1 - somescript)^1
+local parser = lpeg.Cs((csname + lowhigh + highlow + low + high + sign + any)^0)
+
+chemicals.moleculeparser = parser -- can be used to avoid functioncall
+
+function chemicals.molecule(str)
+ return lpegmatch(parser,str)
+end
+
+function commands.molecule(str)
+ if trace_molecules then
+ local rep = lpegmatch(parser,str)
+ logs.report("chemistry", "molecule %s => %s",str,rep)
+ texsprint(ctxcatcodes,rep)
+ else
+ texsprint(ctxcatcodes,lpegmatch(parser,str))
+ end
+end
diff --git a/tex/context/base/chem-ini.mkiv b/tex/context/base/chem-ini.mkiv
new file mode 100644
index 000000000..5184fe1a7
--- /dev/null
+++ b/tex/context/base/chem-ini.mkiv
@@ -0,0 +1,47 @@
+%D \module
+%D [ file=chem-ini,
+%D version=2008.03.06,
+%D subtitle=Chemistry,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Chemistry Macros / Initialization} % might become Inline
+
+\registerctxluafile{chem-ini}{1.001}
+
+\unprotect
+
+%D \macros
+%D {molecule}
+%D
+%D Quick and dirty:
+%D
+%D \starttyping
+%D \def\molecule#1{$\enablesupersub\tf#1$}
+%D \stoptyping
+%D
+%D Using \LUA:
+%D
+%D \startbuffer
+%D \molecule{H_2SO_4^-2}
+%D \molecule{H_2SO_4^{-2}}
+%D \molecule{H_2SO_4^{-2{x}}}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\molecule#1{\ctxlua{commands.molecule(\!!bs#1\!!es)}}
+
+%D For old times sake:
+
+\def\chem#1#2#3%
+ {\dontleavehmode\begingroup#1\lohi{#2}{#3}\endgroup}
+
+\protect \endinput
+
+
diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua
new file mode 100644
index 000000000..ad4cc6c1b
--- /dev/null
+++ b/tex/context/base/chem-str.lua
@@ -0,0 +1,490 @@
+if not modules then modules = { } end modules ['chem-str'] = {
+ version = 1.001,
+ comment = "companion to chem-str.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module in incomplete and experimental.
+
+-- We can push snippets into an mp instance.
+
+local trace_structure = false trackers.register("chemistry.structure", function(v) trace_structure = v end)
+local trace_textstack = false trackers.register("chemistry.textstack", function(v) trace_textstack = v end)
+
+local format, gmatch, match, lower, gsub = string.format, string.gmatch, string.match, string.lower, string.gsub
+local concat, insert, remove = table.concat, table.insert, table.remove
+local apply = structure.processors.apply
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+local lpegmatch = lpeg.match
+
+local variables = interfaces.variables
+
+chemicals = chemicals or { }
+
+chemicals.instance = "metafun" -- "ppchtex"
+chemicals.format = "metafun"
+chemicals.structures = 0
+
+local remapper = {
+ ["+"] = "p",
+ ["-"] = "m",
+}
+
+local common_keys = {
+ b = "line", eb = "line", db = "line", er = "line", dr = "line", br = "line",
+ sb = "line", msb = "line", psb = "line",
+ r = "line", pr = "line", mr = "line",
+ au = "line", ad = "line",
+ rb = "line", mrb = "line", prb = "line",
+ rd = "line", mrd = "line", prd = "line",
+ sr = "line", msr = "line", psr = "line",
+ c = "line", cc = "line", cd = "line", ccd = "line",
+ rn = "number", rtn = "number", rbn = "number",
+ s = "line", ss = "line", pss = "line", mss = "line",
+ mid = "fixed", mids = "fixed", midz = "text",
+ z = "text", rz = "text", mrz = "text", prz = "text", crz = "text",
+ rt = "text", rtt = "text", rbt = "text", zt = "text", zn = "number",
+ mov = "transform", rot = "transform", adj = "transform", dir = "transform", sub = "transform",
+}
+
+local front_keys = {
+ b = "line", bb= "line",
+ sb = "line", msb = "line", psb = "line",
+ r = "line", pr = "line", mr = "line",
+ z = "text", mrz = "text", prz = "text",
+}
+
+local one_keys = {
+ sb = "line", db = "line", tb = "line",
+ ep = "line", es = "line", ed = "line", et = "line",
+ sd = "line", ldd = "line", rdd = "line",
+ hb = "line", bb = "line", oe = "line", bd = "line", bw = "line",
+ z = "text", cz = "text", zt = "text", zn = "number",
+ zbt = "text", zbn = "number", ztt = "text", ztn = "number",
+ mov = "transform", sub = "transform", dir = "transform", off = "transform",
+}
+
+local front_align = {
+ mrz = { { "b","b","b","b","b","b" } },
+ prz = { { "t","t","t","t","t","t" } },
+}
+
+local syntax = {
+ one = {
+ n = 1, max = 8, keys = one_keys,
+ align = {
+ z = { { "r", "r_b", "b", "l_b", "l", "l_t", "t", "r_t" } },
+--~ z = { { "r", "r", "b", "l", "l", "l", "t", "r" } },
+ }
+ },
+ three = {
+ n = 3, max = 3, keys = common_keys,
+ align = {
+ mrz = { { "r","b","l" }, { "b","l","t" }, { "l","t","r" }, { "t","r","b" } },
+ rz = { { "r","l_b","l_t" }, { "b","l_t","r_t" }, { "l","r_t","r_b" }, { "t","r_b","l_b" } },
+ prz = { { "r","l","t" }, { "b","t","r" }, { "l","r","b" }, { "t","b","l" } },
+ }
+ },
+ four = {
+ n = 4, max = 4, keys = common_keys,
+ align = {
+ mrz = { { "t","r","b","l" }, { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" } },
+ rz = { { "r_t","r_b","l_b","l_t" }, { "r_b","l_b","l_t","r_t" }, { "l_b","l_t","r_t","r_b" }, { "l_t","r_t","r_b","l_b" } },
+ prz = { { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" }, { "t","r","b","l" } },
+ }
+ },
+ five = {
+ n = 5, max = 5, keys = common_keys,
+ align = {
+ mrz = { { "t","r","b","b","l" }, { "r","b","l","l","t" }, { "b","l","t","r","r" }, { "l","t","r","r","b" } },
+ rz = { { "r","r","b","l","t" }, { "b","b","l","t","r" }, { "l","l","t","r","b" }, { "t","t","r","b","l" } },
+ prz = { { "r","b","l","t","t" }, { "b","l","t","r","r" }, { "l","t","r","b","b" }, { "t","r","b","l","l" } },
+ }
+ },
+ six = {
+ n = 6, max = 6, keys = common_keys,
+ align = {
+ mrz = { { "t","t","r","b","b","l" }, { "r","b","b","l","t","t" }, { "b","b","l","t","t","r" }, { "l","t","t","r","b","b" } },
+ rz = { { "r","r","b","l","l","t" }, { "b","b","l","t","t","r" }, { "l","l","t","r","r","b" }, { "t","t","r","b","b","l" } },
+ prz = { { "r","b","l","l","t","r" }, { "b","l","t","t","r","b" }, { "l","t","r","r","b","l" }, { "t","r","b","b","l","t" } },
+ }
+ },
+ eight = {
+ n = 8, max = 8, keys = common_keys,
+ align = { -- todo
+ mrz = { { "t","r","r","b","b","l","l","t" }, { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" } },
+ rz = { { "r","r","b","b","l","l","t","t" }, { "b","b","l","l","t","t","r","r" }, { "l","l","t","t","r","r","b","b" }, { "t","t","r","r","b","b","l","l" } },
+ prz = { { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" }, { "t","r","r","b","b","l","l","t" } },
+ }
+ },
+ five_front = {
+ n = -5, max = 5, keys = front_keys, align = front_align,
+ },
+ six_front = {
+ n = -6, max = 6, keys = front_keys, align = front_align,
+ },
+ pb = { direct = 'chem_pb ;' },
+ pe = { direct = 'chem_pe ;' },
+ save = { direct = 'chem_save ;' },
+ restore = { direct = 'chem_restore ;' },
+ space = { direct = 'chem_symbol("\\chemicalsymbol[space]") ;' },
+ plus = { direct = 'chem_symbol("\\chemicalsymbol[plus]") ;' },
+ minus = { direct = 'chem_symbol("\\chemicalsymbol[minus]") ;' },
+ gives = { direct = 'chem_symbol("\\chemicalsymbol[gives]{%s}{%s}") ;', arguments = 2 },
+ equilibrium = { direct = 'chem_symbol("\\chemicalsymbol[equilibrium]{%s}{%s}") ;', arguments = 2 },
+ mesomeric = { direct = 'chem_symbol("\\chemicalsymbol[mesomeric]{%s}{%s}") ;', arguments = 2 },
+ opencomplex = { direct = 'chem_symbol("\\chemicalsymbol[opencomplex]") ;' },
+ closecomplex = { direct = 'chem_symbol("\\chemicalsymbol[closecomplex]") ;' },
+}
+
+local definitions = { }
+
+function chemicals.undefine(name)
+ definitions[lower(name)] = nil
+end
+
+function chemicals.define(name,spec,text)
+ name = lower(name)
+ local dn = definitions[name]
+ if not dn then dn = { } definitions[name] = dn end
+ dn[#dn+1] = {
+ spec = aux.settings_to_array(lower(spec)),
+ text = aux.settings_to_array(text),
+ }
+end
+
+local metacode, kind, keys, bonds, max, txt, textsize, rot, pstack
+local molecule = chemicals.molecule -- or use lpegmatch(chemicals.moleculeparser,...)
+
+local function fetch(txt)
+ local st = stack[txt]
+ local t = st.text[st.n]
+--~ st.n = st.n + 1
+ while not t and txt > 1 do
+ txt = txt - 1
+ st = stack[txt]
+ t = st.text[st.n]
+--~ st.n = st.n + 1
+ end
+ if t then
+ if trace_textstack then
+ logs.report("chemical", "fetching from stack %s slot %s: %s",txt,st.n,t)
+ end
+st.n = st.n + 1
+ end
+ return txt, t
+end
+
+local digit = lpeg.R("09")/tonumber
+local colon = lpeg.P(":")
+local equal = lpeg.P("=")
+local other = 1 - digit - colon - equal
+local remapped = lpeg.S("+-") / remapper
+local operation = lpeg.Cs((remapped^0 * other)^1)
+local amount = digit
+local single = digit
+local special = (colon * lpeg.C(other^1)) + lpeg.Cc("")
+local range = digit * lpeg.P("..") * digit
+local set = lpeg.Ct(digit^2)
+local text = (equal * lpeg.C(lpeg.P(1)^0)) + lpeg.Cc(false)
+local pattern =
+ (amount + lpeg.Cc(1)) *
+ operation *
+ special * (
+ range * lpeg.Cc(false) * text +
+ lpeg.Cc(false) * lpeg.Cc(false) * set * text +
+ single * lpeg.Cc(false) * lpeg.Cc(false) * text +
+ lpeg.Cc(false) * lpeg.Cc(false) * lpeg.Cc(false) * text
+ )
+
+--~ local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357")
+
+--~ print(lpegmatch(pattern,"RZ=x")) 1 RZ false false false x
+--~ print(lpegmatch(pattern,"RZ1=x")) 1 RZ 1 false false x
+--~ print(lpegmatch(pattern,"RZ1..3=x")) 1 RZ 1 3 false x
+--~ print(lpegmatch(pattern,"RZ13=x")) 1 RZ false false table x
+
+local function process(spec,text,n,rulethickness,rulecolor,offset)
+ insert(stack,{ spec=spec, text=text, n=n })
+ local txt = #stack
+ for i=1,#spec do
+ local s = spec[i]
+ local d = definitions[s]
+ if d then
+ for i=1,#d do
+ local di = d[i]
+ process(di.spec,di.text,1,rulethickness,rulecolor)
+ end
+ else
+ local rep, operation, special, index, upto, set, text = lpegmatch(pattern,s)
+ if operation == "pb" then
+ insert(pstack,kind)
+ metacode[#metacode+1] = syntax.pb.direct
+ if keys[special] == "text" and index then
+ if keys["c"..special] == "text" then -- can be option: auto ...
+ metacode[#metacode+1] = format('chem_c%s(%s,%s,"");',special,bonds,index)
+ else
+ metacode[#metacode+1] = format('chem_%s(%s,%s,"");',special,bonds,index)
+ end
+ end
+ elseif operation == "save" then
+ insert(pstack,kind)
+ metacode[#metacode+1] = syntax.save.direct
+ elseif operation == "pe" or operation == "restore" then
+ kind = remove(pstack)
+ local ss = syntax[kind]
+ local prev = bonds or 6
+ keys, bonds, max, rot = ss.keys, ss.n, ss.max, 1
+ metacode[#metacode+1] = syntax[operation].direct
+ metacode[#metacode+1] = format("chem_set(%s,%s) ;",prev,bonds)
+ elseif operation == "front" then
+ if syntax[kind .. "_front"] then
+ kind = kind .. "_front"
+ local ss = syntax[kind]
+ local prev = bonds or 6
+ keys, bonds, max, rot = ss.keys, ss.n, ss.max, 1
+ metacode[#metacode+1] = format("chem_set(%s,%s) ;",prev,bonds)
+ end
+ elseif operation then
+ local ss = syntax[operation]
+ if ss then
+ local ds = ss.direct
+ if ds then
+ local sa = ss.arguments
+ if sa == 1 then
+ local one ; txt, one = fetch(txt)
+ metacode[#metacode+1] = format(ds,one or "")
+ elseif sa ==2 then
+ local one ; txt, one = fetch(txt)
+ local two ; txt, two = fetch(txt)
+ metacode[#metacode+1] = format(ds,one or "",two or "")
+ else
+ metacode[#metacode+1] = ds
+ end
+ elseif ss.keys then
+ local prev = bonds or 6
+ kind, keys, bonds, max, rot = s, ss.keys, ss.n, ss.max, 1
+ metacode[#metacode+1] = format("chem_set(%s,%s) ;",prev,bonds)
+ end
+ else
+ local what = keys[operation]
+ if what == "line" then
+ if set then
+ for i=1,#set do
+ local si = set[i]
+ metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,si,si,rulethickness,rulecolor)
+ end
+ elseif upto then
+ metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,upto,rulethickness,rulecolor)
+ elseif index then
+ metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,index,rulethickness,rulecolor)
+ else
+ metacode[#metacode+1] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,1,max,rulethickness,rulecolor)
+ end
+ elseif what == "number" then
+ if set then
+ for i=1,#set do
+ local si = set[i]
+ metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,si,si)
+ end
+ elseif upto then
+ for i=index,upto do
+ local si = set[i]
+ metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,si,si)
+ end
+ elseif index then
+ metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,index,index)
+ else
+ for i=1,max do
+ metacode[#metacode+1] = format('chem_%s(%s,%s,"\\dochemicaltext{%s}");',operation,bonds,i,i)
+ end
+ end
+ elseif what == "text" then
+ local align = syntax[kind].align
+ align = align and align[operation]
+ align = align and align[rot]
+ if set then
+ for i=1,#set do
+ local si = set[i]
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ local a = align and align[si]
+ if a then a = "." .. a else a = "" end
+ metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,a,bonds,si,molecule(apply(t)))
+ end
+ end
+ elseif upto then
+ for i=index,upto do
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ local s = align and align[i]
+ if s then s = "." .. s else s = "" end
+ metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
+ end
+ end
+ elseif index == 0 then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ metacode[#metacode+1] = format('chem_%s_zero("\\dochemicaltext{%s}");',operation,molecule(apply(t)))
+ end
+ elseif index then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ local s = align and align[index]
+ if s then s = "." .. s else s = "" end
+ metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,index,molecule(apply(t)))
+ end
+ else
+ for i=1,max do
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ local s = align and align[i]
+ if s then s = "." .. s else s = "" end
+ metacode[#metacode+1] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
+ end
+ end
+ end
+ elseif what == "transform" then
+ if index then
+ for r=1,rep do
+ metacode[#metacode+1] = format('chem_%s(%s,%s);',operation,bonds,index)
+ end
+ if operation == "rot" then
+ rot = index
+ end
+ end
+ elseif what == "fixed" then
+ metacode[#metacode+1] = format("chem_%s(%s,%s,%s);",operation,bonds,rulethickness,rulecolor)
+ end
+ end
+ end
+ end
+ end
+ remove(stack)
+end
+
+-- the size related values are somewhat special but we want to be
+-- compatible
+--
+-- maybe we should default to fit
+--
+-- rulethickness in points
+
+function chemicals.start(settings)
+ chemicals.structures = chemicals.structures + 1
+ local textsize, rulethickness, rulecolor = settings.size, settings.rulethickness, settings.rulecolor
+ local width, height, scale, offset = settings.width or 0, settings.height or 0, settings.scale or "medium", settings.offset or 0
+ local l, r, t, b = settings.left or 0, settings.right or 0, settings.top or 0, settings.bottom or 0
+ if scale == variables.small then
+ scale = 500
+ elseif scale == variables.medium or scale == 0 then
+ scale = 625
+ elseif scale == variables.big then
+ scale = 750
+ else
+ scale = tonumber(scale)
+ if not scale or scale == 0 then
+ scale = 750
+ elseif scale < 500 then
+ scale = 500
+ end
+ end
+ if width == variables.fit then
+ width = true
+ else
+ width = tonumber(width) or 0
+ if l == 0 then
+ if r == 0 then
+ l = (width == 0 and 2000) or width/2
+ r = l
+ elseif width ~= 0 then
+ l = width - r
+ end
+ elseif r == 0 and width ~= 0 then
+ r = width - l
+ end
+ width = false
+ end
+ if height == variables.fit then
+ height = true
+ else
+ height = tonumber(height) or 0
+ if t == 0 then
+ if b == 0 then
+ t = (height == 0 and 2000) or height/2
+ b = t
+ elseif height ~= 0 then
+ t = height - b
+ end
+ elseif b == 0 and height ~= 0 then
+ b = height - t
+ end
+ height = false
+ end
+ scale = 0.75 * scale/625
+ metacode = { format("chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ;",
+ chemicals.structures,
+ l/25, r/25, t/25, b/25, scale,
+ tostring(settings.axis == variables.on), tostring(width), tostring(height), tostring(offset)
+ ) }
+ kind, keys, bonds, stack, rot, pstack = "six", { }, 6, { }, 1, { }
+end
+
+function chemicals.stop()
+ metacode[#metacode+1] = "chem_stop_structure ;"
+ local mpcode = concat(metacode,"\n")
+ if trace_structure then
+ logs.report("chemical", "metapost code:\n%s", mpcode)
+ end
+ metapost.graphic(chemicals.instance,chemicals.format,mpcode)
+ metacode = nil
+end
+
+function chemicals.component(spec,text,settings)
+ rulethickness, rulecolor, offset = settings.rulethickness, settings.rulecolor
+ local spec = aux.settings_to_array(lower(spec))
+ local text = aux.settings_to_array(text)
+ metacode[#metacode+1] = "chem_start_component ;"
+ process(spec,text,1,rulethickness,rulecolor)
+ metacode[#metacode+1] = "chem_stop_component ;"
+end
+
+local inline = {
+ ["single"] = "\\chemicalsinglebond", ["-"] = "\\chemicalsinglebond",
+ ["double"] = "\\chemicaldoublebond", ["--"] = "\\chemicaldoublebond",
+ ["triple"] = "\\chemicaltriplebond", ["---"] = "\\chemicaltriplebond",
+ ["gives"] = "\\chemicalgives", ["->"] = "\\chemicalgives",
+ ["equilibrium"] = "\\chemicalequilibrium", ["<->"] = "\\chemicalequilibrium",
+ ["mesomeric"] = "\\chemicalmesomeric", ["<>"] = "\\chemicalmesomeric",
+ ["plus"] = "\\chemicalsplus", ["+"] = "\\chemicalsplus",
+ ["minus"] = "\\chemicalsminus",
+ ["space"] = "\\chemicalsspace",
+}
+
+-- todo: top / bottom
+
+function chemicals.inline(spec)
+ local spec = aux.settings_to_array(spec)
+ for i=1,#spec do
+ local s = spec[i]
+ local inl = inline[lower(s)]
+ if inl then
+ texsprint(ctxcatcodes,inl)
+ else
+ texsprint(ctxcatcodes,format("\\chemicalinline{%s}",molecule(s)))
+ end
+ end
+end
+
+statistics.register("chemical formulas", function()
+ if chemicals.structures > 0 then
+ return format("%s chemical structure formulas",chemicals.structures) -- no timing needed, part of metapost
+ end
+end)
diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv
new file mode 100644
index 000000000..1e17218c8
--- /dev/null
+++ b/tex/context/base/chem-str.mkiv
@@ -0,0 +1,529 @@
+%D \module
+%D [ file=chem-ini,
+%D version=2009.05.13,
+%D subtitle=Chemistry,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 in incomplete and experimental. Eventually this code
+%D will replace \PPCHTEX.
+
+\writestatus{loading}{ConTeXt Chemistry Macros / Structure}
+
+\registerctxluafile{chem-str}{1.001}
+
+% We have a slightly different interface. This is unchanged:
+%
+% \startchemical[axis=on]
+% \chemical[SIX,ROT2,B,R6,SUB1,FIVE,ROT1,B][1]
+% \stopchemical
+%
+% Here we use chemicalformula instead, so no longer a mix:
+%
+% \startchemicalformula
+% \chemical{H_2}{top}{bottom}
+% \chemical{PLUS}{top}{bottom}
+% \chemical{O}{top}{bottom}
+% \chemical{GIVES}{top}{bottom}
+% \chemical{H_2O}{top}{bottom}
+% \stopchemicalformula
+%
+% \startchemicalformula
+% \chemical{H_2}
+% \chemical{PLUS}
+% \chemical{O}
+% \chemical{GIVES}
+% \chemical{H_2O}
+% \stopchemicalformula
+%
+% The inline variant has only one argument:
+%
+% \chemical{H_2,PLUS,O,GIVES,H_2O}
+
+% todo: seven | eight | frontsix | fontfive | carbon | newmans | chair
+
+\unprotect
+
+\unexpanded\def\setupchemical
+ {\dosingleempty\dosetupchemical}
+
+\def\dosetupchemical
+ {\getparameters[\??cm]}
+
+\let\setupchemicals\setupchemical
+
+\unexpanded\def\setupchemicalframed
+ {\dosingleempty\dosetupchemicalframed}
+
+\def\dosetupchemicalframed
+ {\getparameters[\??cm:\c!frame]}
+
+\def\chemicalparameter#1{\csname\??cm#1\endcsname}
+
+\unexpanded\def\definechemical
+ {\dosingleargument\dodefinechemical} % global
+
+\def\dodefinechemical[#1]#2%
+ {\startnointerference
+ \ctxlua{chemicals.undefine("#1")}%
+ \def\chemical{\dodoubleempty\dostructurechemical}%
+ \def\dostructurechemical[##1][##2]{\ctxlua{chemicals.define("#1",\!!bs##1\!!es,\!!bs\detokenize{##2}\!!es)}}%
+ #2% flush
+ \stopnointerference}
+
+\unexpanded\def\definechemicalsymbol
+ {\dodoubleempty\dodefinechemicalsymbol}
+
+\def\dodefinechemicalsymbol[#1][#2]%
+ {\setvalue{\??cm::#1}{#2}}
+
+\def\chemicalsymbol[#1]%
+ {\getvalue{\??cm::#1}}
+
+% size (small medium big)
+
+\def\dosetchemicaltext
+ {\dosetfontattribute \??cm\c!style
+ \dosetcolorattribute\??cm\c!color}
+
+\def\dochemicaltext#1%
+ {\dosetchemicaltext\strut#1} % maybe also \setstrut
+
+\edef\chemicaltoplocation{t}
+\edef\chemicalbotlocation{b}
+
+\def\dochemicaltext#1% in ppchtex we had a more clever alignment
+ {\dosetchemicaltext\strut#1} % maybe also \setstrut
+
+\def\dochemicaltext#1%
+ {\mathematics{\dosetchemicaltext\strut\ifcase\currentxfontsize\or\scriptstyle\or\scriptscriptstyle\fi#1}}
+
+\newconditional\indisplaychemical
+
+\unexpanded\def\startchemical
+ {\dosingleempty\dostartchemical}
+
+\setvalue{\??cm:\c!size:\v!small }{\txx}
+\setvalue{\??cm:\c!size:\v!medium}{\tx}
+\setvalue{\??cm:\c!size:\v!big }{}
+
+\newtoks \everychemical
+\newtoks \everystructurechemical
+\newtoks \withchemicalbox
+\newbox \chemicalbox
+\newconditional\somechemicaltext
+\newdimen \chemicalwidth
+\newdimen \chemicalheight
+\newdimen \chemicaldepth
+
+\def\dostartchemical[#1]%
+ {\ifmmode\vcenter\else\vbox\fi
+ \bgroup
+ \dontcomplain
+ \settrue\indisplaychemical
+ \forgetall
+ \getparameters[\??cm][#1]%
+ \the\everystructurechemical
+ \setbox\chemicalbox\hbox\bgroup
+ \ctxlua{chemicals.start {
+ width = "\chemicalparameter\c!width",
+ height = "\chemicalparameter\c!height",
+ left = \chemicalparameter\c!left,
+ right = \chemicalparameter\c!right,
+ top = \chemicalparameter\c!top,
+ bottom = \chemicalparameter\c!bottom,
+ scale = "\chemicalparameter\c!scale",
+ axis = "\chemicalparameter\c!axis",
+ offset = "\the\dimexpr.25em\relax",
+ } }%
+ \startnointerference}
+
+\unexpanded\def\stopchemical
+ {\stopnointerference
+ \ctxlua{chemicals.stop()}%
+ \egroup
+ \chemicalwidth \wd\chemicalbox
+ \chemicalheight\ht\chemicalbox
+ \chemicaldepth \dp\chemicalbox
+ \the\withchemicalbox
+ \doifelsenothing{\chemicalparameter\c!frame}\handlechemicalframednop\handlechemicalframedyes
+ \egroup}
+
+\def\handlechemicalframedyes
+ {\localframed%
+ [\??cm:\c!frame]%
+ [\c!frame=\chemicalparameter\c!frame,\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\chemicalbox\vss}}} % remove depth
+
+\def\handlechemicalframednop
+ {\localframed%
+ [\??cm:\c!frame]%
+ [\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\chemicalbox\vss}}} % remove depth
+
+\let\startstructurechemical\startchemical
+\let\stopstructurechemical \stopchemical
+
+\unexpanded\def\structurechemical
+ {\dotripleempty\dostructurechemical}
+
+\appendtoks
+ \let\chemical\structurechemical
+\to\everystructurechemical
+
+\def\dostructurechemical
+ {\ifthirdargument
+ \expandafter\dostructurechemicalthree
+ \else
+ \expandafter\dostructurechemicaltwo
+ \fi}
+
+\def\dostructurechemicalthree[#1][#2][#3]%
+ {\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored
+ \ctxlua{chemicals.component(\!!bs#2\!!es, \!!bs\detokenize{#3}\!!es, { % maybe also pass first two args this way
+ rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points
+ rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup
+ } ) }%
+ \ignorespaces}
+
+\def\dostructurechemicaltwo[#1][#2]%
+ {\ctxlua{chemicals.component(\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es, { % maybe also pass first two args this way
+ rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points
+ rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup
+ } ) }%
+ \ignorespaces}
+
+\appendtoks
+ \setbox\chemicalbox\hbox{\raise\MPlly\onebasepoint\box\chemicalbox}%
+ \chemicalwidth \wd\chemicalbox
+ \chemicalheight\ht\chemicalbox
+ \chemicaldepth \dp\chemicalbox
+\to \withchemicalbox
+
+% kind of compatible, but text sizes instead of math sizes (i.e. tx is larger than scriptsize)
+
+\appendtoks
+ \edef\chemicalbodyfont{\chemicalparameter\c!bodyfont}%
+ \doifnot\chemicalbodyfont\fontbody{\switchtobodyfont[\chemicalbodyfont]}% \fontbody is not expanded (yet)
+ \getvalue{\??cm:\c!size:\chemicalparameter\c!size}%
+% \to \everystructurechemical
+\to \everychemical
+
+\def\chemicaltoptext#1{\global\settrue\somechemicaltext\gdef\thetoptext{#1}\ignorespaces}
+\def\chemicalbottext#1{\global\settrue\somechemicaltext\gdef\thebottext{#1}\ignorespaces}
+\def\chemicalmidtext#1{\global\settrue\somechemicaltext\gdef\themidtext{#1}\ignorespaces}
+
+\appendtoks
+ \let\toptext\chemicaltoptext \glet\thetoptext\empty
+ \let\bottext\chemicalbottext \glet\thebottext\empty
+ \let\midtext\chemicalmidtext \glet\themidtext\empty
+ \global\setfalse\somechemicaltext
+\to \everystructurechemical
+
+\def\doaddchemicaltexts
+ {\setbox2\hbox to \chemicalwidth{\strut\hss\hbox{\strut\themidtext}\hss}%
+ \setbox4\hbox to \chemicalwidth{\strut\hss\hbox{\strut\thetoptext}\hss}%
+ \setbox6\hbox to \chemicalwidth{\strut\hss\hbox{\strut\thebottext}\hss}%
+ \setbox\chemicalbox\hbox \bgroup
+ \box\chemicalbox
+ \hskip-\chemicalwidth
+ \raise\chemicalheight\hbox{\lower\ht4\box4}%
+ \hskip-\chemicalwidth
+ \lower.5\dimexpr\ht2-\dp2\relax\box2%
+ \hskip-\chemicalwidth
+ \lower\chemicaldepth \hbox{\raise\dp6\box6}%
+ \hss
+ \egroup} % text on top of chemicals
+
+\appendtoks
+ \ifconditional\somechemicaltext
+ \doaddchemicaltexts
+ \chemicalwidth \wd\chemicalbox
+ \chemicalheight\ht\chemicalbox
+ \chemicaldepth \dp\chemicalbox
+ \fi
+\to \withchemicalbox
+
+% todo: enspace or emspace
+
+\definechemicalsymbol[space] [\enspace\quad\enspace]
+\definechemicalsymbol[plus] [\enspace+\enspace]
+\definechemicalsymbol[minus] [\enspace-\enspace]
+\definechemicalsymbol[gives] [\dochemicalarrow\xrightarrow]
+\definechemicalsymbol[equilibrium] [\dochemicalarrow\xrightoverleftarrow]
+\definechemicalsymbol[mesomeric] [\dochemicalarrow\xleftrightarrow]
+\definechemicalsymbol[opencomplex] [\mathematics{\Bigg[}] % not yet ok
+\definechemicalsymbol[closecomplex][\mathematics{\Bigg]}] % not yet ok
+
+\definechemicalsymbol[SPACE] [{\chemicalsymbol[space]}]
+\definechemicalsymbol[PLUS] [{\chemicalsymbol[plus]}]
+\definechemicalsymbol[MINUS] [{\chemicalsymbol[minus]}]
+\definechemicalsymbol[GIVES] [{\chemicalsymbol[gives]}]
+\definechemicalsymbol[EQUILIBRIUM] [{\chemicalsymbol[equilibrium]}]
+\definechemicalsymbol[MESOMERIC] [{\chemicalsymbol[mesomeric]}]
+\definechemicalsymbol[OPENCOMPLEX] [{\chemicalsymbol[opencomplex]}]
+\definechemicalsymbol[CLOSECOMPLEX][{\chemicalsymbol[closecomplex]}]
+
+\def\dochemicalarrow#1#2#3%
+ {\enspace
+ \mathematics{#1%
+ {\strut\hbox \!!spread 2em{\hss\ctxlua{chemicals.inline(\!!bs#2\!!es)}\hss}}%
+ {\strut\hbox \!!spread 2em{\hss\ctxlua{chemicals.inline(\!!bs#3\!!es)}\hss}}}%
+ \enspace}
+
+% special macros (probably needs some more work)
+
+\def\dochemicaltop#1#2#3#4%
+ {\begingroup
+ \setbox0\hbox{\tx\setstrut\strut#3}%
+ \setbox2\hbox{\setstrut\strut\molecule{#4}}%
+ \setbox0\hbox{\raise\dimexpr\dp0+\ht2\relax\hbox to \wd2{#1\box0#2}}%
+ \smashbox0
+ \hbox{\box0\box2}%
+ \endgroup}%
+
+\def\dochemicalbottom#1#2#3#4%
+ {\begingroup
+ \setbox0\hbox{\tx\setstrut\strut#3}%
+ \setbox2\hbox{\setstrut\strut#4}%
+ \setbox0\hbox{\lower\dimexpr\dp2+\ht0\relax\hbox to \wd2{#1\box0#2}}%
+ \smashbox0
+ \hbox{\box0\box2}%
+ \endgroup}%
+
+\unexpanded\def\chemicalleft#1#2%
+ {\begingroup
+ \hbox{\llap{\tx\setstrut\strut#1}\setstrut\strut#2}%
+ \endgroup}%
+
+\unexpanded\def\chemicalright#1#2%
+ {\begingroup
+ \hbox{\setstrut\strut#2\rlap{\tx\setstrut\strut#1}}%
+ \endgroup}%
+
+\unexpanded\def\chemicaltop {\dochemicaltop \hss \hss }
+\unexpanded\def\chemicallefttop {\dochemicaltop \relax \hss }
+\unexpanded\def\chemicalrighttop {\dochemicaltop \hss \relax}
+\unexpanded\def\chemicalbottom {\dochemicalbottom \hss \hss }
+\unexpanded\def\chemicalleftbottom {\dochemicalbottom \relax \hss }
+\unexpanded\def\chemicalrightbottom {\dochemicalbottom \hss \relax}
+
+\unexpanded\def\chemicaltopleft #1{\chemicalleft {\chemicalrighttop {#1}{}}}
+\unexpanded\def\chemicalbottomleft #1{\chemicalleft {\chemicalrightbottom{#1}{}}}
+\unexpanded\def\chemicaltopright #1{\chemicalright{\chemicallefttop {#1}{}}}
+\unexpanded\def\chemicalbottomright #1{\chemicalright{\chemicalleftbottom {#1}{}}}
+
+\unexpanded\def\chemicalcentered #1{\setbox\scratchbox\hbox{C}\hbox to \wd\scratchbox{\setstrut\strut\hss#1\hss}}
+\unexpanded\def\chemicalleftcentered #1{\setbox\scratchbox\hbox{C}\hbox to \wd\scratchbox{\setstrut\strut #1\hss}}
+\unexpanded\def\chemicalrightcentered#1{\setbox\scratchbox\hbox{C}\hbox to \wd\scratchbox{\setstrut\strut\hss#1}}
+
+\let\chemicalsmashedmiddle\chemicalcentered
+\let\chemicalsmashedleft \chemicalleftcentered
+\let\chemicalsmashedright \chemicalrightcentered
+
+\unexpanded\def\chemicaloxidation#1#2#3%
+ {\chemicaltop{\txx\ifcase#2\relax0\else#1\uppercase\expandafter{\romannumeral#2}\fi}{#3}}
+
+\unexpanded\def\chemicaloxidationplus {\dotriplegroupempty\chemicaloxidation{\textplus }} % {} needed!
+\unexpanded\def\chemicaloxidationminus{\dotriplegroupempty\chemicaloxidation{\textminus}} % {} needed!
+\unexpanded\def\chemicalforeveropen {\dotriplegroupempty\chemicalleft {$\big[$}} % {} needed!
+\unexpanded\def\chemicalforeverclose {\dotriplegroupempty\chemicalright {$\big]$}} % {} needed!
+\unexpanded\def\chemicaloxidationone {\chemicaloxidation\relax1}
+\unexpanded\def\chemicaloxidationtwo {\chemicaloxidation\relax2}
+\unexpanded\def\chemicaloxidationthree{\chemicaloxidation\relax3}
+\unexpanded\def\chemicaloxidationfour {\chemicaloxidation\relax4}
+\unexpanded\def\chemicaloxidationfive {\chemicaloxidation\relax5}
+\unexpanded\def\chemicaloxidationsix {\chemicaloxidation\relax6}
+\unexpanded\def\chemicaloxidationseven{\chemicaloxidation\relax7}
+
+\appendtoks
+ \let \+\chemicaloxidationplus
+ \let \-\chemicaloxidationminus
+ \let \[\chemicalforeveropen
+ \let \]\chemicalforeverclose
+ \let \1\chemicaloxidationone
+ \let \2\chemicaloxidationtwo
+ \let \3\chemicaloxidationthree
+ \let \4\chemicaloxidationfour
+ \let \5\chemicaloxidationfive
+ \let \6\chemicaloxidationsix
+ \let \7\chemicaloxidationseven
+ \let \X\chemicaltighttext
+ \let \T\chemicaltop
+ \let \B\chemicalbottom
+ \let \L\chemicalleft
+ \let\LC\chemicalleftcentered
+ \let \R\chemicalright
+ \let\RC\chemicalrightcentered
+ \let\TL\chemicaltopleft
+ \let\BL\chemicalbottomleft
+ \let\TR\chemicaltopright
+ \let\BR\chemicalbottomright
+ \let\LT\chemicallefttop
+ \let\LB\chemicalleftbottom
+ \let\RT\chemicalrighttop
+ \let\RB\chemicalrightbottom
+ \let\SL\chemicalsmashedleft
+ \let\SM\chemicalsmashedmiddle
+ \let\SR\chemicalsmashedright
+\to \everychemical
+
+\appendtoks
+ \the\everychemical
+\to \everystructurechemical
+
+% inline
+
+\unexpanded\def\chemical
+ {\ifinformula
+ \expandafter\displaychemical
+ \else
+ \expandafter\inlinechemical
+ \fi}
+
+\def\displaychemical
+ {\dotriplegroupempty\dodisplaychemical}
+
+\def\dodisplaychemical#1#2#3% todo:
+ {\the\everychemical \everychemical\emptytoks
+ \quad
+ \vcenter\bgroup
+ \ifthirdargument
+ \ifsecondargument
+ \halign{&\hss##\hss\cr#2\cr\molecule{#1}\cr#3\cr}%
+ \else
+ \halign{&\hss##\hss\cr\molecule{#1}\cr#2\cr}%
+ \fi
+ \else
+ \hbox{\molecule{#1}}%
+ \fi
+ \egroup
+ \quad}
+
+\def\inlinechemical#1%
+ {\dontleavehmode\hbox{\ctxlua{chemicals.inline(\!!bs#1\!!es)}}}
+
+\def\chemicalbondrule{\hbox{\vrule\!!height.75ex\!!depth-\dimexpr.75ex-\linewidth\relax\!!width1em\relax}}
+
+\definechemicalsymbol[i:space] [\enspace\quad\enspace]
+\definechemicalsymbol[i:plus] [\enspace\mathematics{+}\enspace]
+\definechemicalsymbol[i:minus] [\enspace\mathematics{-}\enspace]
+\definechemicalsymbol[i:gives] [\enspace\mathematics{\xrightarrow{}{}}\enspace]
+\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightpverleftarrow{}{}}\enspace]
+\definechemicalsymbol[i:mesomeric] [\enspace\mathematics{\xleftrightarrow{}{}}\enspace]
+\definechemicalsymbol[i:single] [\chemicalbondrule]
+\definechemicalsymbol[i:tripple] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:double] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+
+\def\chemicalsinglebond {\chemicalsymbol[i:single]}
+\def\chemicaldoublebond {\chemicalsymbol[i:tripple]}
+\def\chemicaltriplebond {\chemicalsymbol[i:double]}
+\def\chemicalgives {\chemicalsymbol[i:gives]}
+\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]}
+\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]}
+\def\chemicalsplus {\chemicalsymbol[i:plus]}
+\def\chemicalsminus {\chemicalsymbol[i:minus]}
+\def\chemicalsspace {\chemicalsymbol[i:space]}
+\def\chemicalinline #1{#1}
+
+% display
+
+\newconditional\formulachemicalhastop
+\newconditional\formulachemicalhasbot
+
+\newtoks\formulachemicaltop
+\newtoks\formulachemicalmid
+\newtoks\formulachemicalbot
+
+\newif\ifinchemicalformula
+
+\unexpanded\def\startchemicalformula
+ {\mathortext\vcenter\vbox\bgroup
+ \forgetall
+ \inchemicalformulatrue
+ \the\everychemical
+ \everychemical\emptytoks
+ \formulachemicaltop\emptytoks % not needed
+ \formulachemicalmid\emptytoks % not needed
+ \formulachemicalbot\emptytoks % not needed
+ \let\chemical\formulachemical
+ \setfalse\formulachemicalhastop
+ \setfalse\formulachemicalhasbot }
+
+\unexpanded\def\stopchemicalformula
+ {\tabskip1em\relax
+ \nointerlineskip
+ \ifconditional\formulachemicalhastop
+ \ifconditional\formulachemicalhasbot
+ \halign{&\hss##\hss\cr\the\formulachemicaltop\cr\the\formulachemicalmid\cr\the\formulachemicalbot\cr}%
+ \else
+ \halign{&\hss##\hss\cr\the\formulachemicaltop\cr\the\formulachemicalmid\cr}%
+ \fi
+ \else
+ \ifconditional\formulachemicalhasbot
+ \halign{&\hss##\hss\cr\the\formulachemicalmid\cr\the\formulachemicalbot\cr}%
+ \else
+ \halign{&\hss##\hss\cr\the\formulachemicalmid\cr}%
+ \fi
+ \fi
+ \egroup}
+
+\unexpanded\def\formulachemical
+ {\relax\dotriplegroupempty\doformulachemical}
+
+\def\doformulachemical#1#2#3%
+ {\ifthirdargument
+ \doifelsenothing{#2}\noformulachemicaltop{\doformulachemicaltop{#2}}%
+ \doifelsenothing{#3}\noformulachemicalbot{\doformulachemicalbot{#3}}%
+ \else\ifsecondargument
+ \noformulachemicaltop
+ \doifelsenothing{#2}\noformulachemicalbot{\doformulachemicalbot{#2}}%
+ \else
+ \noformulachemicaltop
+ \noformulachemicalbot
+ \fi\fi
+ \formulachemicalmid\expandafter{\the\formulachemicalmid\dodochemicalformulamid{#1}&}}
+
+\def\noformulachemicaltop {\formulachemicaltop\expandafter{\the\formulachemicaltop&}}
+\def\noformulachemicalbot {\formulachemicalbot\expandafter{\the\formulachemicalbot&}}
+\def\doformulachemicaltop#1{\formulachemicaltop\expandafter{\the\formulachemicaltop\dodochemicalformulatop{#1}&}\settrue\formulachemicalhastop}
+\def\doformulachemicalbot#1{\formulachemicalbot\expandafter{\the\formulachemicalbot\dodochemicalformulabot{#1}&}\settrue\formulachemicalhasbot}
+
+\def\dodochemicalformulamid#1%
+ {\ifcsname\??cm::\detokenize{#1}\endcsname\csname\??cm::\detokenize{#1}\expandafter\endcsname\else\molecule{#1}\fi{}{}}
+
+\def\dodochemicalformulatop#1{\strut#1}
+\def\dodochemicalformulabot#1{\strut#1}
+
+% gone: state option resolution offset (now frame offset) alternative
+
+\setupchemicalframed
+ [\c!align=\v!normal,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!frame=off]
+
+\setupchemical
+ [\c!frame=,
+ \c!width=0,
+ \c!height=0,
+ \c!left=0,
+ \c!right=0,
+ \c!top=0,
+ \c!bottom=0,
+ \c!bodyfont=\the\bodyfontsize,
+ \c!scale=\v!medium,
+ \c!size=\v!medium,
+ \c!textsize=\v!big,
+ \c!axis=\v!off,
+ \c!style=\rm,
+ \c!location=,
+ \c!color=,
+ \c!rulethickness=\linewidth,
+ \c!rulecolor=,
+ \c!factor=1]
+
+\protect \endinput
diff --git a/tex/context/base/colo-ema.tex b/tex/context/base/colo-ema.tex
new file mode 100644
index 000000000..e5e90b235
--- /dev/null
+++ b/tex/context/base/colo-ema.tex
@@ -0,0 +1,590 @@
+%D \module
+%D [ file=colo-ema,
+%D version=2003.03.20,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Emacs Colors,
+%D author=Peter Rolf,
+%D date=\currentdate,
+%D copyright=PRAGMA ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% author : Peter Rolf
+% last change : 17 march 2003
+% origin : /emacs/etc/rgb.txt
+%
+% USAGE:
+%
+% - select emacs menu: Edit -> Text Properties -> Display
+% Colors, if you don't know what I'm talking about
+% - copy this file to your /texmf/tex/context/user directory
+% and add "\input colo-emacs" to your tex-file
+%
+% IMPORTANT NOTES:
+%
+% - all color names are written as ONE word in lowercase
+% letters (no redundancy as in rgb.txt) so if you want to
+% use the color "Light Sky Blue"/"light sky blue" it's new
+% name is lightskyblue
+% - the grayX values [X=0..100] can only be used with \color
+% [grayX]
+% - use it at your own risk :)
+%
+% HINT:
+%
+% I only include this file (\showcolor [ema]) until I've
+% found the colors I want. Copy and paste the color
+% definitions to a seperate file, to decrease compilation
+% time (540 color definitions).
+
+\definecolor [snow] [r=1,g=.980392,b=.980392]
+\definecolor [ghostwhite] [r=.972549,g=.972549,b=1]
+\definecolor [whitesmoke] [s=.960784]
+\definecolor [gainsboro] [s=.862745]
+\definecolor [floralwhite] [r=1,g=.980392,b=.941176]
+\definecolor [oldlace] [r=.992157,g=.960784,b=.901961]
+\definecolor [linen] [r=.980392,g=.941176,b=.901961]
+\definecolor [antiquewhite] [r=.980392,g=.921569,b=.843137]
+\definecolor [papayawhip] [r=1,g=.937255,b=.835294]
+\definecolor [blanchedalmond] [r=1,g=.921569,b=.803922]
+\definecolor [bisque] [r=1,g=.894118,b=.768627]
+\definecolor [peachpuff] [r=1,g=.854902,b=.72549]
+\definecolor [navajowhite] [r=1,g=.870588,b=.678431]
+\definecolor [moccasin] [r=1,g=.894118,b=.709804]
+\definecolor [cornsilk] [r=1,g=.972549,b=.862745]
+\definecolor [ivory] [r=1,g=1,b=.941176]
+\definecolor [lemonchiffon] [r=1,g=.980392,b=.803922]
+\definecolor [seashell] [r=1,g=.960784,b=.933333]
+\definecolor [honeydew] [r=.941176,g=1,b=.941176]
+\definecolor [mintcream] [r=.960784,g=1,b=.980392]
+\definecolor [azure] [r=.941176,g=1,b=1]
+\definecolor [aliceblue] [r=.941176,g=.972549,b=1]
+\definecolor [lavender] [r=.901961,g=.901961,b=.980392]
+\definecolor [lavenderblush] [r=1,g=.941176,b=.960784]
+\definecolor [mistyrose] [r=1,g=.894118,b=.882353]
+%definecolor[white] [s=1]
+%definecolor[black] [s=0]
+\definecolor [darkslategray] [r=.184314,g=.309804,b=.309804]
+\definecolor [dimgray] [s=.411765]
+\definecolor [slategray] [r=.439216,g=.501961,b=.564706]
+\definecolor [lightslategray] [r=.466667,g=.533333,b=.6]
+\definecolor [gray] [s=.745098]
+\definecolor [lightgray] [s=.827451]
+\definecolor [midnightblue] [r=.098039,g=.098039,b=.439216]
+\definecolor [navy] [b=.501961]
+\definecolor [navyblue] [navy]
+\definecolor [cornflowerblue] [r=.392157,g=.584314,b=.929412]
+\definecolor [darkslateblue] [r=.282353,g=.239216,b=.545098]
+\definecolor [slateblue] [r=.415686,g=.352941,b=.803922]
+\definecolor [mediumslateblue] [r=.482353,g=.407843,b=.933333]
+\definecolor [lightslateblue] [r=.517647,g=.439216,b=1]
+\definecolor [mediumblue] [b=.803922]
+\definecolor [royalblue] [r=.254902,g=.411765,b=.882353]
+%definecolor[blue] [b=1]
+\definecolor [dodgerblue] [r=.117647,g=.564706,b=1]
+\definecolor [deepskyblue] [g=.74902,b=1]
+\definecolor [skyblue] [r=.529412,g=.807843,b=.921569]
+\definecolor [lightskyblue] [r=.529412,g=.807843,b=.980392]
+\definecolor [steelblue] [r=.27451,g=.509804,b=.705882]
+\definecolor [lightsteelblue] [r=.690196,g=.768627,b=.870588]
+\definecolor [lightblue] [r=.678431,g=.847059,b=.901961]
+\definecolor [powderblue] [r=.690196,g=.878431,b=.901961]
+\definecolor [paleturquoise] [r=.686275,g=.933333,b=.933333]
+\definecolor [darkturquoise] [g=.807843,b=.819608]
+\definecolor [mediumturquoise] [r=.282353,g=.819608,b=.8]
+\definecolor [turquoise] [r=.25098,g=.878431,b=.815686]
+%definecolor[cyan] [g=1,b=1]
+\definecolor [lightcyan] [r=.878431,g=1,b=1]
+\definecolor [cadetblue] [r=.372549,g=.619608,b=.627451]
+\definecolor [mediumaquamarine] [r=.4,g=.803922,b=.666667]
+\definecolor [aquamarine] [r=.498039,g=1,b=.831373]
+\definecolor [darkgreen] [g=.392157]
+\definecolor [darkolivegreen] [r=.333333,g=.419608,b=.184314]
+\definecolor [darkseagreen] [r=.560784,g=.737255,b=.560784]
+\definecolor [seagreen] [r=.180392,g=.545098,b=.341176]
+\definecolor [mediumseagreen] [r=.235294,g=.701961,b=.443137]
+\definecolor [lightseagreen] [r=.12549,g=.698039,b=.666667]
+\definecolor [palegreen] [r=.596078,g=.984314,b=.596078]
+\definecolor [springgreen] [g=1,b=.498039]
+\definecolor [lawngreen] [r=.486275,g=.988235]
+%definecolor[green] [g=1]
+\definecolor [chartreuse] [r=.498039,g=1]
+\definecolor [mediumspringgreen] [g=.980392,b=.603922]
+\definecolor [greenyellow] [r=.678431,g=1,b=.184314]
+\definecolor [limegreen] [r=.196078,g=.803922,b=.196078]
+\definecolor [yellowgreen] [r=.603922,g=.803922,b=.196078]
+\definecolor [forestgreen] [r=.133333,g=.545098,b=.133333]
+\definecolor [olivedrab] [r=.419608,g=.556863,b=.137255]
+\definecolor [darkkhaki] [r=.741176,g=.717647,b=.419608]
+\definecolor [khaki] [r=.941176,g=.901961,b=.54902]
+\definecolor [palegoldenrod] [r=.933333,g=.909804,b=.666667]
+\definecolor [lightgoldenrodyellow] [r=.980392,g=.980392,b=.823529]
+\definecolor [lightyellow] [r=1,g=1,b=.878431]
+%definecolor[yellow] [r=1,g=1]
+\definecolor [gold] [r=1,g=.843137]
+\definecolor [lightgoldenrod] [r=.933333,g=.866667,b=.509804]
+\definecolor [goldenrod] [r=.854902,g=.647059,b=.12549]
+\definecolor [darkgoldenrod] [r=.721569,g=.52549,b=.043137]
+\definecolor [rosybrown] [r=.737255,g=.560784,b=.560784]
+\definecolor [indianred] [r=.803922,g=.360784,b=.360784]
+\definecolor [saddlebrown] [r=.545098,g=.270588,b=.07451]
+\definecolor [sienna] [r=.627451,g=.321569,b=.176471]
+\definecolor [peru] [r=.803922,g=.521569,b=.247059]
+\definecolor [burlywood] [r=.870588,g=.721569,b=.529412]
+\definecolor [beige] [r=.960784,g=.960784,b=.862745]
+\definecolor [wheat] [r=.960784,g=.870588,b=.701961]
+\definecolor [sandybrown] [r=.956863,g=.643137,b=.376471]
+\definecolor [tan] [r=.823529,g=.705882,b=.54902]
+\definecolor [chocolate] [r=.823529,g=.411765,b=.117647]
+\definecolor [firebrick] [r=.698039,g=.133333,b=.133333]
+\definecolor [brown] [r=.647059,g=.164706,b=.164706]
+\definecolor [darksalmon] [r=.913725,g=.588235,b=.478431]
+\definecolor [salmon] [r=.980392,g=.501961,b=.447059]
+\definecolor [lightsalmon] [r=1,g=.627451,b=.478431]
+\definecolor [orange] [r=1,g=.647059]
+\definecolor [darkorange] [r=1,g=.54902]
+\definecolor [coral] [r=1,g=.498039,b=.313725]
+\definecolor [lightcoral] [r=.941176,g=.501961,b=.501961]
+\definecolor [tomato] [r=1,g=.388235,b=.278431]
+\definecolor [orangered] [r=1,g=.270588]
+%definecolor[red] [r=1]
+\definecolor [hotpink] [r=1,g=.411765,b=.705882]
+\definecolor [deeppink] [r=1,g=.078431,b=.576471]
+\definecolor [pink] [r=1,g=.752941,b=.796078]
+\definecolor [lightpink] [r=1,g=.713725,b=.756863]
+\definecolor [palevioletred] [r=.858824,g=.439216,b=.576471]
+\definecolor [maroon] [r=.690196,g=.188235,b=.376471]
+\definecolor [mediumvioletred] [r=.780392,g=.082353,b=.521569]
+\definecolor [violetred] [r=.815686,g=.12549,b=.564706]
+%definecolor[magenta] [r=1,b=1]
+\definecolor [violet] [r=.933333,g=.509804,b=.933333]
+\definecolor [plum] [r=.866667,g=.627451,b=.866667]
+\definecolor [orchid] [r=.854902,g=.439216,b=.839216]
+\definecolor [mediumorchid] [r=.729412,g=.333333,b=.827451]
+\definecolor [darkorchid] [r=.6,g=.196078,b=.8]
+\definecolor [darkviolet] [r=.580392,b=.827451]
+\definecolor [blueviolet] [r=.541176,g=.168627,b=.886275]
+\definecolor [purple] [r=.627451,g=.12549,b=.941176]
+\definecolor [mediumpurple] [r=.576471,g=.439216,b=.858824]
+\definecolor [thistle] [r=.847059,g=.74902,b=.847059]
+\definecolor [snow1] [r=1,g=.980392,b=.980392]
+\definecolor [snow2] [r=.933333,g=.913725,b=.913725]
+\definecolor [snow3] [r=.803922,g=.788235,b=.788235]
+\definecolor [snow4] [r=.545098,g=.537255,b=.537255]
+\definecolor [seashell1] [r=1,g=.960784,b=.933333]
+\definecolor [seashell2] [r=.933333,g=.898039,b=.870588]
+\definecolor [seashell3] [r=.803922,g=.772549,b=.74902]
+\definecolor [seashell4] [r=.545098,g=.52549,b=.509804]
+\definecolor [antiquewhite1] [r=1,g=.937255,b=.858824]
+\definecolor [antiquewhite2] [r=.933333,g=.87451,b=.8]
+\definecolor [antiquewhite3] [r=.803922,g=.752941,b=.690196]
+\definecolor [antiquewhite4] [r=.545098,g=.513725,b=.470588]
+\definecolor [bisque1] [r=1,g=.894118,b=.768627]
+\definecolor [bisque2] [r=.933333,g=.835294,b=.717647]
+\definecolor [bisque3] [r=.803922,g=.717647,b=.619608]
+\definecolor [bisque4] [r=.545098,g=.490196,b=.419608]
+\definecolor [peachpuff1] [r=1,g=.854902,b=.72549]
+\definecolor [peachpuff2] [r=.933333,g=.796078,b=.678431]
+\definecolor [peachpuff3] [r=.803922,g=.686275,b=.584314]
+\definecolor [peachpuff4] [r=.545098,g=.466667,b=.396078]
+\definecolor [navajowhite1] [r=1,g=.870588,b=.678431]
+\definecolor [navajowhite2] [r=.933333,g=.811765,b=.631373]
+\definecolor [navajowhite3] [r=.803922,g=.701961,b=.545098]
+\definecolor [navajowhite4] [r=.545098,g=.47451,b=.368627]
+\definecolor [lemonchiffon1] [r=1,g=.980392,b=.803922]
+\definecolor [lemonchiffon2] [r=.933333,g=.913725,b=.74902]
+\definecolor [lemonchiffon3] [r=.803922,g=.788235,b=.647059]
+\definecolor [lemonchiffon4] [r=.545098,g=.537255,b=.439216]
+\definecolor [cornsilk1] [r=1,g=.972549,b=.862745]
+\definecolor [cornsilk2] [r=.933333,g=.909804,b=.803922]
+\definecolor [cornsilk3] [r=.803922,g=.784314,b=.694118]
+\definecolor [cornsilk4] [r=.545098,g=.533333,b=.470588]
+\definecolor [ivory1] [r=1,g=1,b=.941176]
+\definecolor [ivory2] [r=.933333,g=.933333,b=.878431]
+\definecolor [ivory3] [r=.803922,g=.803922,b=.756863]
+\definecolor [ivory4] [r=.545098,g=.545098,b=.513725]
+\definecolor [honeydew1] [r=.941176,g=1,b=.941176]
+\definecolor [honeydew2] [r=.878431,g=.933333,b=.878431]
+\definecolor [honeydew3] [r=.756863,g=.803922,b=.756863]
+\definecolor [honeydew4] [r=.513725,g=.545098,b=.513725]
+\definecolor [lavenderblush1] [r=1,g=.941176,b=.960784]
+\definecolor [lavenderblush2] [r=.933333,g=.878431,b=.898039]
+\definecolor [lavenderblush3] [r=.803922,g=.756863,b=.772549]
+\definecolor [lavenderblush4] [r=.545098,g=.513725,b=.52549]
+\definecolor [mistyrose1] [r=1,g=.894118,b=.882353]
+\definecolor [mistyrose2] [r=.933333,g=.835294,b=.823529]
+\definecolor [mistyrose3] [r=.803922,g=.717647,b=.709804]
+\definecolor [mistyrose4] [r=.545098,g=.490196,b=.482353]
+\definecolor [azure1] [r=.941176,g=1,b=1]
+\definecolor [azure2] [r=.878431,g=.933333,b=.933333]
+\definecolor [azure3] [r=.756863,g=.803922,b=.803922]
+\definecolor [azure4] [r=.513725,g=.545098,b=.545098]
+\definecolor [slateblue1] [r=.513725,g=.435294,b=1]
+\definecolor [slateblue2] [r=.478431,g=.403922,b=.933333]
+\definecolor [slateblue3] [r=.411765,g=.34902,b=.803922]
+\definecolor [slateblue4] [r=.278431,g=.235294,b=.545098]
+\definecolor [royalblue1] [r=.282353,g=.462745,b=1]
+\definecolor [royalblue2] [r=.262745,g=.431373,b=.933333]
+\definecolor [royalblue3] [r=.227451,g=.372549,b=.803922]
+\definecolor [royalblue4] [r=.152941,g=.25098,b=.545098]
+\definecolor [blue1] [blue]
+\definecolor [blue2] [b=.933333]
+\definecolor [blue3] [b=.803922]
+\definecolor [blue4] [b=.545098]
+\definecolor [dodgerblue1] [r=.117647,g=.564706,b=1]
+\definecolor [dodgerblue2] [r=.109804,g=.52549,b=.933333]
+\definecolor [dodgerblue3] [r=.094118,g=.454902,b=.803922]
+\definecolor [dodgerblue4] [r=.062745,g=.305882,b=.545098]
+\definecolor [steelblue1] [r=.388235,g=.721569,b=1]
+\definecolor [steelblue2] [r=.360784,g=.67451,b=.933333]
+\definecolor [steelblue3] [r=.309804,g=.580392,b=.803922]
+\definecolor [steelblue4] [r=.211765,g=.392157,b=.545098]
+\definecolor [deepskyblue1] [g=.74902,b=1]
+\definecolor [deepskyblue2] [g=.698039,b=.933333]
+\definecolor [deepskyblue3] [g=.603922,b=.803922]
+\definecolor [deepskyblue4] [g=.407843,b=.545098]
+\definecolor [skyblue1] [r=.529412,g=.807843,b=1]
+\definecolor [skyblue2] [r=.494118,g=.752941,b=.933333]
+\definecolor [skyblue3] [r=.423529,g=.65098,b=.803922]
+\definecolor [skyblue4] [r=.290196,g=.439216,b=.545098]
+\definecolor [lightskyblue1] [r=.690196,g=.886275,b=1]
+\definecolor [lightskyblue2] [r=.643137,g=.827451,b=.933333]
+\definecolor [lightskyblue3] [r=.552941,g=.713725,b=.803922]
+\definecolor [lightskyblue4] [r=.376471,g=.482353,b=.545098]
+\definecolor [slategray1] [r=.776471,g=.886275,b=1]
+\definecolor [slategray2] [r=.72549,g=.827451,b=.933333]
+\definecolor [slategray3] [r=.623529,g=.713725,b=.803922]
+\definecolor [slategray4] [r=.423529,g=.482353,b=.545098]
+\definecolor [lightsteelblue1] [r=.792157,g=.882353,b=1]
+\definecolor [lightsteelblue2] [r=.737255,g=.823529,b=.933333]
+\definecolor [lightsteelblue3] [r=.635294,g=.709804,b=.803922]
+\definecolor [lightsteelblue4] [r=.431373,g=.482353,b=.545098]
+\definecolor [lightblue1] [r=.74902,g=.937255,b=1]
+\definecolor [lightblue2] [r=.698039,g=.87451,b=.933333]
+\definecolor [lightblue3] [r=.603922,g=.752941,b=.803922]
+\definecolor [lightblue4] [r=.407843,g=.513725,b=.545098]
+\definecolor [lightcyan1] [r=.878431,g=1,b=1]
+\definecolor [lightcyan2] [r=.819608,g=.933333,b=.933333]
+\definecolor [lightcyan3] [r=.705882,g=.803922,b=.803922]
+\definecolor [lightcyan4] [r=.478431,g=.545098,b=.545098]
+\definecolor [paleturquoise1] [r=.733333,g=1,b=1]
+\definecolor [paleturquoise2] [r=.682353,g=.933333,b=.933333]
+\definecolor [paleturquoise3] [r=.588235,g=.803922,b=.803922]
+\definecolor [paleturquoise4] [r=.4,g=.545098,b=.545098]
+\definecolor [cadetblue1] [r=.596078,g=.960784,b=1]
+\definecolor [cadetblue2] [r=.556863,g=.898039,b=.933333]
+\definecolor [cadetblue3] [r=.478431,g=.772549,b=.803922]
+\definecolor [cadetblue4] [r=.32549,g=.52549,b=.545098]
+\definecolor [turquoise1] [g=.960784,b=1]
+\definecolor [turquoise2] [g=.898039,b=.933333]
+\definecolor [turquoise3] [g=.772549,b=.803922]
+\definecolor [turquoise4] [g=.52549,b=.545098]
+\definecolor [cyan1] [cyan]
+\definecolor [cyan2] [g=.933333,b=.933333]
+\definecolor [cyan3] [g=.803922,b=.803922]
+\definecolor [cyan4] [g=.545098,b=.545098]
+\definecolor [darkslategray1] [r=.592157,g=1,b=1]
+\definecolor [darkslategray2] [r=.552941,g=.933333,b=.933333]
+\definecolor [darkslategray3] [r=.47451,g=.803922,b=.803922]
+\definecolor [darkslategray4] [r=.321569,g=.545098,b=.545098]
+\definecolor [aquamarine1] [r=.498039,g=1,b=.831373]
+\definecolor [aquamarine2] [r=.462745,g=.933333,b=.776471]
+\definecolor [aquamarine3] [r=.4,g=.803922,b=.666667]
+\definecolor [aquamarine4] [r=.270588,g=.545098,b=.454902]
+\definecolor [darkseagreen1] [r=.756863,g=1,b=.756863]
+\definecolor [darkseagreen2] [r=.705882,g=.933333,b=.705882]
+\definecolor [darkseagreen3] [r=.607843,g=.803922,b=.607843]
+\definecolor [darkseagreen4] [r=.411765,g=.545098,b=.411765]
+\definecolor [seagreen1] [r=.329412,g=1,b=.623529]
+\definecolor [seagreen2] [r=.305882,g=.933333,b=.580392]
+\definecolor [seagreen3] [r=.262745,g=.803922,b=.501961]
+\definecolor [seagreen4] [r=.180392,g=.545098,b=.341176]
+\definecolor [palegreen1] [r=.603922,g=1,b=.603922]
+\definecolor [palegreen2] [r=.564706,g=.933333,b=.564706]
+\definecolor [palegreen3] [r=.486275,g=.803922,b=.486275]
+\definecolor [palegreen4] [r=.329412,g=.545098,b=.329412]
+\definecolor [springgreen1] [g=1,b=.498039]
+\definecolor [springgreen2] [g=.933333,b=.462745]
+\definecolor [springgreen3] [g=.803922,b=.4]
+\definecolor [springgreen4] [g=.545098,b=.270588]
+\definecolor [green1] [green]
+\definecolor [green2] [g=.933333]
+\definecolor [green3] [g=.803922]
+\definecolor [green4] [g=.545098]
+\definecolor [chartreuse1] [r=.498039,g=1]
+\definecolor [chartreuse2] [r=.462745,g=.933333]
+\definecolor [chartreuse3] [r=.4,g=.803922]
+\definecolor [chartreuse4] [r=.270588,g=.545098]
+\definecolor [olivedrab1] [r=.752941,g=1,b=.243137]
+\definecolor [olivedrab2] [r=.701961,g=.933333,b=.227451]
+\definecolor [olivedrab3] [r=.603922,g=.803922,b=.196078]
+\definecolor [olivedrab4] [r=.411765,g=.545098,b=.133333]
+\definecolor [darkolivegreen1] [r=.792157,g=1,b=.439216]
+\definecolor [darkolivegreen2] [r=.737255,g=.933333,b=.407843]
+\definecolor [darkolivegreen3] [r=.635294,g=.803922,b=.352941]
+\definecolor [darkolivegreen4] [r=.431373,g=.545098,b=.239216]
+\definecolor [khaki1] [r=1,g=.964706,b=.560784]
+\definecolor [khaki2] [r=.933333,g=.901961,b=.521569]
+\definecolor [khaki3] [r=.803922,g=.776471,b=.45098]
+\definecolor [khaki4] [r=.545098,g=.52549,b=.305882]
+\definecolor [lightgoldenrod1] [r=1,g=.92549,b=.545098]
+\definecolor [lightgoldenrod2] [r=.933333,g=.862745,b=.509804]
+\definecolor [lightgoldenrod3] [r=.803922,g=.745098,b=.439216]
+\definecolor [lightgoldenrod4] [r=.545098,g=.505882,b=.298039]
+\definecolor [lightyellow1] [r=1,g=1,b=.878431]
+\definecolor [lightyellow2] [r=.933333,g=.933333,b=.819608]
+\definecolor [lightyellow3] [r=.803922,g=.803922,b=.705882]
+\definecolor [lightyellow4] [r=.545098,g=.545098,b=.478431]
+\definecolor [yellow1] [yellow]
+\definecolor [yellow2] [r=.933333,g=.933333]
+\definecolor [yellow3] [r=.803922,g=.803922]
+\definecolor [yellow4] [r=.545098,g=.545098]
+\definecolor [gold1] [r=1,g=.843137]
+\definecolor [gold2] [r=.933333,g=.788235]
+\definecolor [gold3] [r=.803922,g=.678431]
+\definecolor [gold4] [r=.545098,g=.458824]
+\definecolor [goldenrod1] [r=1,g=.756863,b=.145098]
+\definecolor [goldenrod2] [r=.933333,g=.705882,b=.133333]
+\definecolor [goldenrod3] [r=.803922,g=.607843,b=.113725]
+\definecolor [goldenrod4] [r=.545098,g=.411765,b=.078431]
+\definecolor [darkgoldenrod1] [r=1,g=.72549,b=.058824]
+\definecolor [darkgoldenrod2] [r=.933333,g=.678431,b=.054902]
+\definecolor [darkgoldenrod3] [r=.803922,g=.584314,b=.047059]
+\definecolor [darkgoldenrod4] [r=.545098,g=.396078,b=.031373]
+\definecolor [rosybrown1] [r=1,g=.756863,b=.756863]
+\definecolor [rosybrown2] [r=.933333,g=.705882,b=.705882]
+\definecolor [rosybrown3] [r=.803922,g=.607843,b=.607843]
+\definecolor [rosybrown4] [r=.545098,g=.411765,b=.411765]
+\definecolor [indianred1] [r=1,g=.415686,b=.415686]
+\definecolor [indianred2] [r=.933333,g=.388235,b=.388235]
+\definecolor [indianred3] [r=.803922,g=.333333,b=.333333]
+\definecolor [indianred4] [r=.545098,g=.227451,b=.227451]
+\definecolor [sienna1] [r=1,g=.509804,b=.278431]
+\definecolor [sienna2] [r=.933333,g=.47451,b=.258824]
+\definecolor [sienna3] [r=.803922,g=.407843,b=.223529]
+\definecolor [sienna4] [r=.545098,g=.278431,b=.14902]
+\definecolor [burlywood1] [r=1,g=.827451,b=.607843]
+\definecolor [burlywood2] [r=.933333,g=.772549,b=.568627]
+\definecolor [burlywood3] [r=.803922,g=.666667,b=.490196]
+\definecolor [burlywood4] [r=.545098,g=.45098,b=.333333]
+\definecolor [wheat1] [r=1,g=.905882,b=.729412]
+\definecolor [wheat2] [r=.933333,g=.847059,b=.682353]
+\definecolor [wheat3] [r=.803922,g=.729412,b=.588235]
+\definecolor [wheat4] [r=.545098,g=.494118,b=.4]
+\definecolor [tan1] [r=1,g=.647059,b=.309804]
+\definecolor [tan2] [r=.933333,g=.603922,b=.286275]
+\definecolor [tan3] [r=.803922,g=.521569,b=.247059]
+\definecolor [tan4] [r=.545098,g=.352941,b=.168627]
+\definecolor [chocolate1] [r=1,g=.498039,b=.141176]
+\definecolor [chocolate2] [r=.933333,g=.462745,b=.129412]
+\definecolor [chocolate3] [r=.803922,g=.4,b=.113725]
+\definecolor [chocolate4] [r=.545098,g=.270588,b=.07451]
+\definecolor [firebrick1] [r=1,g=.188235,b=.188235]
+\definecolor [firebrick2] [r=.933333,g=.172549,b=.172549]
+\definecolor [firebrick3] [r=.803922,g=.14902,b=.14902]
+\definecolor [firebrick4] [r=.545098,g=.101961,b=.101961]
+\definecolor [brown1] [r=1,g=.25098,b=.25098]
+\definecolor [brown2] [r=.933333,g=.231373,b=.231373]
+\definecolor [brown3] [r=.803922,g=.2,b=.2]
+\definecolor [brown4] [r=.545098,g=.137255,b=.137255]
+\definecolor [salmon1] [r=1,g=.54902,b=.411765]
+\definecolor [salmon2] [r=.933333,g=.509804,b=.384314]
+\definecolor [salmon3] [r=.803922,g=.439216,b=.329412]
+\definecolor [salmon4] [r=.545098,g=.298039,b=.223529]
+\definecolor [lightsalmon1] [r=1,g=.627451,b=.478431]
+\definecolor [lightsalmon2] [r=.933333,g=.584314,b=.447059]
+\definecolor [lightsalmon3] [r=.803922,g=.505882,b=.384314]
+\definecolor [lightsalmon4] [r=.545098,g=.341176,b=.258824]
+\definecolor [orange1] [r=1,g=.647059]
+\definecolor [orange2] [r=.933333,g=.603922]
+\definecolor [orange3] [r=.803922,g=.521569]
+\definecolor [orange4] [r=.545098,g=.352941]
+\definecolor [darkorange1] [r=1,g=.498039]
+\definecolor [darkorange2] [r=.933333,g=.462745]
+\definecolor [darkorange3] [r=.803922,g=.4]
+\definecolor [darkorange4] [r=.545098,g=.270588]
+\definecolor [coral1] [r=1,g=.447059,b=.337255]
+\definecolor [coral2] [r=.933333,g=.415686,b=.313725]
+\definecolor [coral3] [r=.803922,g=.356863,b=.270588]
+\definecolor [coral4] [r=.545098,g=.243137,b=.184314]
+\definecolor [tomato1] [r=1,g=.388235,b=.278431]
+\definecolor [tomato2] [r=.933333,g=.360784,b=.258824]
+\definecolor [tomato3] [r=.803922,g=.309804,b=.223529]
+\definecolor [tomato4] [r=.545098,g=.211765,b=.14902]
+\definecolor [orangered1] [r=1,g=.270588]
+\definecolor [orangered2] [r=.933333,g=.25098]
+\definecolor [orangered3] [r=.803922,g=.215686]
+\definecolor [orangered4] [r=.545098,g=.145098]
+\definecolor [red1] [red]
+\definecolor [red2] [r=.933333]
+\definecolor [red3] [r=.803922]
+\definecolor [red4] [r=.545098]
+\definecolor [deeppink1] [r=1,g=.078431,b=.576471]
+\definecolor [deeppink2] [r=.933333,g=.070588,b=.537255]
+\definecolor [deeppink3] [r=.803922,g=.062745,b=.462745]
+\definecolor [deeppink4] [r=.545098,g=.039216,b=.313725]
+\definecolor [hotpink1] [r=1,g=.431373,b=.705882]
+\definecolor [hotpink2] [r=.933333,g=.415686,b=.654902]
+\definecolor [hotpink3] [r=.803922,g=.376471,b=.564706]
+\definecolor [hotpink4] [r=.545098,g=.227451,b=.384314]
+\definecolor [pink1] [r=1,g=.709804,b=.772549]
+\definecolor [pink2] [r=.933333,g=.662745,b=.721569]
+\definecolor [pink3] [r=.803922,g=.568627,b=.619608]
+\definecolor [pink4] [r=.545098,g=.388235,b=.423529]
+\definecolor [lightpink1] [r=1,g=.682353,b=.72549]
+\definecolor [lightpink2] [r=.933333,g=.635294,b=.678431]
+\definecolor [lightpink3] [r=.803922,g=.54902,b=.584314]
+\definecolor [lightpink4] [r=.545098,g=.372549,b=.396078]
+\definecolor [palevioletred1] [r=1,g=.509804,b=.670588]
+\definecolor [palevioletred2] [r=.933333,g=.47451,b=.623529]
+\definecolor [palevioletred3] [r=.803922,g=.407843,b=.537255]
+\definecolor [palevioletred4] [r=.545098,g=.278431,b=.364706]
+\definecolor [maroon1] [r=1,g=.203922,b=.701961]
+\definecolor [maroon2] [r=.933333,g=.188235,b=.654902]
+\definecolor [maroon3] [r=.803922,g=.160784,b=.564706]
+\definecolor [maroon4] [r=.545098,g=.109804,b=.384314]
+\definecolor [violetred1] [r=1,g=.243137,b=.588235]
+\definecolor [violetred2] [r=.933333,g=.227451,b=.54902]
+\definecolor [violetred3] [r=.803922,g=.196078,b=.470588]
+\definecolor [violetred4] [r=.545098,g=.133333,b=.321569]
+\definecolor [magenta1] [magenta]
+\definecolor [magenta2] [r=.933333,b=.933333]
+\definecolor [magenta3] [r=.803922,b=.803922]
+\definecolor [magenta4] [r=.545098,b=.545098]
+\definecolor [orchid1] [r=1,g=.513725,b=.980392]
+\definecolor [orchid2] [r=.933333,g=.478431,b=.913725]
+\definecolor [orchid3] [r=.803922,g=.411765,b=.788235]
+\definecolor [orchid4] [r=.545098,g=.278431,b=.537255]
+\definecolor [plum1] [r=1,g=.733333,b=1]
+\definecolor [plum2] [r=.933333,g=.682353,b=.933333]
+\definecolor [plum3] [r=.803922,g=.588235,b=.803922]
+\definecolor [plum4] [r=.545098,g=.4,b=.545098]
+\definecolor [mediumorchid1] [r=.878431,g=.4,b=1]
+\definecolor [mediumorchid2] [r=.819608,g=.372549,b=.933333]
+\definecolor [mediumorchid3] [r=.705882,g=.321569,b=.803922]
+\definecolor [mediumorchid4] [r=.478431,g=.215686,b=.545098]
+\definecolor [darkorchid1] [r=.74902,g=.243137,b=1]
+\definecolor [darkorchid2] [r=.698039,g=.227451,b=.933333]
+\definecolor [darkorchid3] [r=.603922,g=.196078,b=.803922]
+\definecolor [darkorchid4] [r=.407843,g=.133333,b=.545098]
+\definecolor [purple1] [r=.607843,g=.188235,b=1]
+\definecolor [purple2] [r=.568627,g=.172549,b=.933333]
+\definecolor [purple3] [r=.490196,g=.14902,b=.803922]
+\definecolor [purple4] [r=.333333,g=.101961,b=.545098]
+\definecolor [mediumpurple1] [r=.670588,g=.509804,b=1]
+\definecolor [mediumpurple2] [r=.623529,g=.47451,b=.933333]
+\definecolor [mediumpurple3] [r=.537255,g=.407843,b=.803922]
+\definecolor [mediumpurple4] [r=.364706,g=.278431,b=.545098]
+\definecolor [thistle1] [r=1,g=.882353,b=1]
+\definecolor [thistle2] [r=.933333,g=.823529,b=.933333]
+\definecolor [thistle3] [r=.803922,g=.709804,b=.803922]
+\definecolor [thistle4] [r=.545098,g=.482353,b=.545098]
+\definecolor [gray0] [black]
+\definecolor [gray1] [s=.01]
+\definecolor [gray2] [s=.02]
+\definecolor [gray3] [s=.03]
+\definecolor [gray4] [s=.04]
+\definecolor [gray5] [s=.05]
+\definecolor [gray6] [s=.06]
+\definecolor [gray7] [s=.07]
+\definecolor [gray8] [s=.08]
+\definecolor [gray9] [s=.09]
+\definecolor [gray10] [s=.1]
+\definecolor [gray11] [s=.11]
+\definecolor [gray12] [s=.12]
+\definecolor [gray13] [s=.13]
+\definecolor [gray14] [s=.14]
+\definecolor [gray15] [s=.15]
+\definecolor [gray16] [s=.16]
+\definecolor [gray17] [s=.17]
+\definecolor [gray18] [s=.18]
+\definecolor [gray19] [s=.19]
+\definecolor [gray20] [s=.2]
+\definecolor [gray21] [s=.21]
+\definecolor [gray22] [s=.22]
+\definecolor [gray23] [s=.23]
+\definecolor [gray24] [s=.24]
+\definecolor [gray25] [s=.25]
+\definecolor [gray26] [s=.26]
+\definecolor [gray27] [s=.27]
+\definecolor [gray28] [s=.28]
+\definecolor [gray29] [s=.29]
+\definecolor [gray30] [s=.3]
+\definecolor [gray31] [s=.31]
+\definecolor [gray32] [s=.32]
+\definecolor [gray33] [s=.33]
+\definecolor [gray34] [s=.34]
+\definecolor [gray35] [s=.35]
+\definecolor [gray36] [s=.36]
+\definecolor [gray37] [s=.37]
+\definecolor [gray38] [s=.38]
+\definecolor [gray39] [s=.39]
+\definecolor [gray40] [s=.4]
+\definecolor [gray41] [s=.41]
+\definecolor [gray42] [s=.42]
+\definecolor [gray43] [s=.43]
+\definecolor [gray44] [s=.44]
+\definecolor [gray45] [s=.45]
+\definecolor [gray46] [s=.46]
+\definecolor [gray47] [s=.47]
+\definecolor [gray48] [s=.48]
+\definecolor [gray49] [s=.49]
+\definecolor [gray50] [s=.5]
+\definecolor [gray51] [s=.51]
+\definecolor [gray52] [s=.52]
+\definecolor [gray53] [s=.53]
+\definecolor [gray54] [s=.54]
+\definecolor [gray55] [s=.55]
+\definecolor [gray56] [s=.56]
+\definecolor [gray57] [s=.57]
+\definecolor [gray58] [s=.58]
+\definecolor [gray59] [s=.59]
+\definecolor [gray60] [s=.6]
+\definecolor [gray61] [s=.61]
+\definecolor [gray62] [s=.62]
+\definecolor [gray63] [s=.63]
+\definecolor [gray64] [s=.64]
+\definecolor [gray65] [s=.65]
+\definecolor [gray66] [s=.66]
+\definecolor [gray67] [s=.67]
+\definecolor [gray68] [s=.68]
+\definecolor [gray69] [s=.69]
+\definecolor [gray70] [s=.7]
+\definecolor [gray71] [s=.71]
+\definecolor [gray72] [s=.72]
+\definecolor [gray73] [s=.73]
+\definecolor [gray74] [s=.74]
+\definecolor [gray75] [s=.75]
+\definecolor [gray76] [s=.76]
+\definecolor [gray77] [s=.77]
+\definecolor [gray78] [s=.78]
+\definecolor [gray79] [s=.79]
+\definecolor [gray80] [s=.8]
+\definecolor [gray81] [s=.81]
+\definecolor [gray82] [s=.82]
+\definecolor [gray83] [s=.83]
+\definecolor [gray84] [s=.84]
+\definecolor [gray85] [s=.85]
+\definecolor [gray86] [s=.86]
+\definecolor [gray87] [s=.87]
+\definecolor [gray88] [s=.88]
+\definecolor [gray89] [s=.89]
+\definecolor [gray90] [s=.9]
+\definecolor [gray91] [s=.91]
+\definecolor [gray92] [s=.92]
+\definecolor [gray93] [s=.93]
+\definecolor [gray94] [s=.94]
+\definecolor [gray95] [s=.95]
+\definecolor [gray96] [s=.96]
+\definecolor [gray97] [s=.97]
+\definecolor [gray98] [s=.98]
+\definecolor [gray99] [s=.99]
+\definecolor [gray100] [white]
+\definecolor [darkgray] [s=.662745]
+\definecolor [darkblue] [b=.545098]
+\definecolor [darkcyan] [g=.545098,b=.545098]
+\definecolor [darkmagenta] [r=.545098,b=.545098]
+\definecolor [darkred] [r=.545098]
+\definecolor [lightgreen] [r=.564706,g=.933333,b=.564706]
diff --git a/tex/context/base/colo-ext.mkii b/tex/context/base/colo-ext.mkii
new file mode 100644
index 000000000..473c010e0
--- /dev/null
+++ b/tex/context/base/colo-ext.mkii
@@ -0,0 +1,59 @@
+%D \module
+%D [ file=colo-ext, % mostof thsi code used to be in colo-ini.tex
+%D version=1997.04.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Extras,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Color Macros / Extras}
+
+\unprotect
+
+%D \macros
+%D {negatecolorcomponent, negativecolorbox}
+%D
+%D Sometimes, especially when we deal with typesetting
+%D devices, we want to reverse the color scheme. Instead of
+%D recalculating all those colors, we use a quick and dirty
+%D approach:
+%D
+%D \starttyping
+%D \negativecolorbox0
+%D \stoptyping
+%D
+%D will negate the colors in box zero.
+
+\def\negatecolorbox#1%
+ {\setbox#1\hbox
+ {\dostartnegative
+ \localstartcolor[white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\localstopcolor
+ \hskip-\wd#1%
+ \box#1%
+ \dostopnegative}}
+
+%D There are in principle two ways to handle overprint: bound to colors
+%D or independent. For the moment we only support independent overprint
+%D handling. Here we deal with a per-document setting.
+
+\setupcolors
+ [\c!intent=\v!none]
+
+\def\starttextoverprint
+ {\doifelse\@@clintent\v!overprint
+ {\glet\stoptextoverprint \dostopoverprint
+ \glet\starttextoverprint\dostartoverprint
+ \dostartoverprint}
+ {\glet\stoptextoverprint\donothing}}
+
+\let\stoptextoverprint\donothing
+
+\appendtoks \starttextoverprint \to \everystarttextproperties
+\appendtoks \stoptextoverprint \to \everystoptextproperties
+
+\protect \endinput
diff --git a/tex/context/base/colo-ext.mkiv b/tex/context/base/colo-ext.mkiv
new file mode 100644
index 000000000..b17608f59
--- /dev/null
+++ b/tex/context/base/colo-ext.mkiv
@@ -0,0 +1,103 @@
+%D \module
+%D [ file=colo-ext, % mostof thsi code used to be in colo-ini.tex
+%D version=1997.04.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Extras,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Color Macros / Extras}
+
+\unprotect
+
+%D \macros
+%D {negatecolorcomponent, negativecolorbox}
+%D
+%D Sometimes, especially when we deal with typesetting
+%D devices, we want to reverse the color scheme. Instead of
+%D recalculating all those colors, we use a quick and dirty
+%D approach:
+%D
+%D \starttyping
+%D \negativecolorbox0
+%D \stoptyping
+%D
+%D will negate the colors in box zero.
+
+\def\negatecolorbox#1%
+ {\setbox#1\hbox
+ {\startnegativeproperty % might change
+ \startcolor[white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor
+ \hskip-\wd#1%
+ \box#1%
+ \stopnegativeproperty}}
+
+%D There are in principle two ways to handle overprint: bound to colors
+%D or independent. For the moment we only support independent overprint
+%D handling. Here we deal with a per-document setting.
+
+\unexpanded\def\startcolorintent[#1]%
+ {\pushattribute\colorintentattribute
+ \dotriggercolorintent{#1}}
+
+\unexpanded\def\stopcolorintent
+ {\popattribute\colorintentattribute}
+
+\unexpanded\def\startoverprint{\startcolorintent[\v!overprint]}
+\unexpanded\def\stopoverprint {\stopcolorintent}
+
+\unexpanded\def\startknockout {\startcolorintent[\v!knockout ]}
+\unexpanded\def\stopknockout {\stopcolorintent}
+
+\let\starttextcolorintent\relax
+\let\stoptextcolorintent \relax
+
+\setupcolors
+ [\c!overprint=\v!no]
+
+\appendtoks
+ \dosettextcolorintent
+\to \everysetupcolors
+
+\def\dosettextcolorintent
+ {\doifnot\@@clintent\v!none
+ {\xdef\starttextcolorintent{\noexpand\dotriggercolorintent{\@@clintent}}%
+ \glet\dosettextcolorintent\relax
+ \dotriggercolorintent\@@clintent}}
+
+\appendtoks \starttextcolorintent \to \everystarttextproperties
+\appendtoks \stoptextcolorintent \to \everystoptextproperties
+
+\setupcolors[\c!intent=\v!none]
+
+% 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]
+% \starttext
+% test {\mycolora OEPS} test
+% test {\mycolorb OEPS} test
+% \stoptext
+
+\unexpanded\def\defineintermediatecolor
+ {\dotripleempty\dodefineintermediatecolor}
+
+\def\dodefineintermediatecolor[#1][#2][#3]% \dotripleempty adds {} inside []
+ {\dododefineintermediatecolor[#1][#2][#3]}
+
+\def\dododefineintermediatecolor[#1][#2,#3,#4][#5]%
+ {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
+ \ctxlua{colors.defineintermediatecolor("#1","#2",
+ \thecolorattribute{#3},\thecolorattribute{#4},
+ \thetransparencyattribute{#3},\thetransparencyattribute{#4},
+ "#5",false,\iffreezecolors true\else false\fi)}% not global
+ \dodefinecolorcommand\setvalue{#1}}
+
+\protect \endinput
diff --git a/tex/context/base/colo-hex.mkii b/tex/context/base/colo-hex.mkii
new file mode 100644
index 000000000..db67f1841
--- /dev/null
+++ b/tex/context/base/colo-hex.mkii
@@ -0,0 +1,125 @@
+%D \module
+%D [ file=colo-hex,
+%D version=2004.06.23,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Hex Colors,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifdefined \hexcolorprefix
+ \expandafter \endinput
+\fi
+
+\writestatus{loading}{ConTeXt Color Macros / Hexadecimal}
+
+% \edef\testcolor{\string#FFC0C0}
+% \edef\testcolor{\string#55}
+%
+% \setupcolors[state=start]
+%
+% \expanded{\definecolor[thehexcolor][\hexcolorspec\testcolor]}
+%
+% \checkhexcolor[\testcolor]
+%
+% \definecolor[thehexcolor][\testcolor]
+%
+% \starttext
+%
+% test \color[thehexcolor]{rood}
+% test \color[red]{rood}
+% test \color[\testcolor]{rood}
+%
+% \stoptext
+
+\unprotect
+
+% \definecolor[rgbtestcolor] [r=0.87843,g=0.87451,b=0.89020] % RGB(224,223,227)
+% \definecolor[hextestcolor] [h=E0DFE3]
+%
+% \startMPpage
+% path p ; % example by Peter Rolf
+% p := unitsquare xyscaled(5cm,5cm) ;
+% fill (point 0 of p -- point 1 of p -- point 2 of p --cycle) withcolor \MPcolor{rgbtestcolor} ; % bottom right part of the square
+% fill (point 0 of p -- point 3 of p -- point 2 of p --cycle) withcolor \MPcolor{hextestcolor} ; % top left part
+% \stopMPpage
+
+\newdimen\hexcolorfraction \hexcolorfraction=\dimexpr1pt/255\relax
+
+\chardef\hexcolorprefix=`#
+
+\def\hexcolorspec #1{\expandafter\dohexcolorspec #1\empty\empty\empty\empty\relax}
+\def\hexcolorpattern#1{\expandafter\dohexcolorpattern#1\empty\empty\empty\empty\relax}
+
+\ifx\dohexstringtonumber\undefined \def\dohexstringtonumber{"} \fi
+
+\def\hexcolorcomponent#1#2%
+ {\ifnum\dohexstringtonumber#1#2=\zerocount0\else\ifnum\dohexstringtonumber#1#2=\plusone1\else
+ \expandafter\withoutpt\the\dimexpr\dohexstringtonumber#1#2\hexcolorfraction\relax
+ \fi\fi}
+
+\def\dohexcolorspec#1#2#3#4#5#6#7#8\relax
+ {\ifx#4\empty
+ s=\hexcolorcomponent#2#3%
+ \else
+ r=\hexcolorcomponent#2#3,g=\hexcolorcomponent#4#5,b=\hexcolorcomponent#6#7%
+ \fi}
+
+\def\dohexcolorpattern#1#2#3#4#5#6#7#8\relax
+ {0\ifx#4\empty
+ S:\hexcolorcomponent#2#3%
+ \else
+ R:\hexcolorcomponent#2#3:\hexcolorcomponent#4#5:\hexcolorcomponent#6#7%
+ \fi:0:0}
+
+\def\doifhexcolorelse#1%
+ {\expandafter\dodoifhexcolorelse#10\od} % 0 is a dirty trick to catch an empty #1
+
+\def\dodoifhexcolorelse#1#2\od
+ {\ifnum`#1=\hexcolorprefix
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\docheckhexcolor#1%
+ {\doifhexcolorelse{#1}{\doifundefined{#1}{\setxvalue{\??cr#1}{\hexcolorpattern{#1}}}}\donothing}
+
+\def\checkhexcolor[#1]%
+ {\expanded{\docheckhexcolor{#1}}}
+
+\def\colorHpattern{\@EA\hexcolorpattern\@EA{\@EA*\@@cl@@h}} % * == dummy placeholder
+
+\let\dodododefinecolor\dododefinecolor % we will overload this one
+
+\def\dododefinecolor#1#2#3#4[#5][#6]%
+ {\doifhexcolorelse{#6}
+ {\setxvalue{\??cr#5}{\hexcolorpattern{#6}}}
+ {\dodododefinecolor#1#2#3#4[#5][#6]}}
+
+%D For Adam Lindsay and his XeTeX special driver:
+
+% because we intercept the zero condition, the .23pt in 1.23pt will disappear in the
+% ifcase zero part branch
+
+\def\colorhexcomponent#1%
+ {\ifdim#1\points<.005\points
+ 00\else\lchexnumbers{\the\dimexpr255\dimexpr#1\points\relax+.5\points\relax}%
+ \fi}
+
+% the faster one
+
+\newdimen\hex@color@a \hex@color@a=.005pt
+\newdimen\hex@color@b \hex@color@b=.5pt
+\chardef \hex@color@c =255
+
+\def\colorhexcomponent#1%
+ {\ifdim#1\points<\hex@color@a
+ 00\else\lchexnumbers{\the\dimexpr#1\points*\hex@color@c+\hex@color@b\relax}%
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/colo-hex.mkiv b/tex/context/base/colo-hex.mkiv
new file mode 100644
index 000000000..f661b2445
--- /dev/null
+++ b/tex/context/base/colo-hex.mkiv
@@ -0,0 +1,28 @@
+%D \module
+%D [ file=colo-hex,
+%D version=2004.06.23,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Hex Colors,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is built in.
+
+% \definecolor[rgbtestcolor] [r=0.87843,g=0.87451,b=0.89020] % RGB(224,223,227)
+% \definecolor[hextestcolor] [\letterhash E0DFE3] % or [h=E0DFE3]
+%
+% \startMPpage
+% path p ; % example by Peter Rolf
+% p := unitsquare xyscaled(5cm,5cm) ;
+% fill (point 0 of p -- point 1 of p -- point 2 of p --cycle) withcolor \MPcolor{rgbtestcolor} ; % bottom right part of the square
+% fill (point 0 of p -- point 3 of p -- point 2 of p --cycle) withcolor \MPcolor{hextestcolor} ; % top left part
+% \stopMPpage
+
+\def\checkhexcolor[#1]{\doifcolorelse{#1}\donothing{\definecolor[#1][x=#1]}} % is this ok?
+
+\endinput
diff --git a/tex/context/base/colo-hex.tex b/tex/context/base/colo-hex.tex
new file mode 100644
index 000000000..7d223c131
--- /dev/null
+++ b/tex/context/base/colo-hex.tex
@@ -0,0 +1,3 @@
+% this is just a stub
+
+\loadmarkfile{colo-hex}
diff --git a/tex/context/base/colo-ini.lua b/tex/context/base/colo-ini.lua
new file mode 100644
index 000000000..342d6110d
--- /dev/null
+++ b/tex/context/base/colo-ini.lua
@@ -0,0 +1,480 @@
+if not modules then modules = { } end modules ['colo-ini'] = {
+ version = 1.000,
+ comment = "companion to colo-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type = type
+local concat = table.concat
+local format, gmatch, gsub, lower, match, find = string.format, string.gmatch, string.gsub, string.lower, string.match, string.find
+local texsprint = tex.sprint
+local ctxcatcodes = tex.ctxcatcodes
+
+local trace_define = false trackers.register("colors.define",function(v) trace_define = v end)
+
+local settings_to_hash_strict = aux.settings_to_hash_strict
+
+colors = colors or { }
+transparencies = transparencies or { }
+
+local registrations = backends.registrations
+
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+local a_background = attributes.private('background')
+
+local register_color = colors.register
+local attributes_list = attributes.list
+
+local function definecolor(name, ca, global)
+ if ca and ca > 0 then
+ if global then
+ if trace_define then
+ commands.writestatus("color","define global color '%s' with attribute: %s",name,ca)
+ end
+ context.colordefagc(name,ca)
+ else
+ if trace_define then
+ commands.writestatus("color","define local color '%s' with attribute: %s",name,ca)
+ end
+ context.colordefalc(name,ca)
+ end
+ else
+ if global then
+ context.colordefrgc(name)
+ else
+ context.colordefrlc(name)
+ end
+ end
+end
+
+local function inheritcolor(name, ca, global)
+ if ca and ca ~= "" then
+ if global then
+ if trace_define then
+ commands.writestatus("color","inherit global color '%s' with attribute: %s",name,ca)
+ end
+ context.colordeffgc(name,ca)
+ else
+ if trace_define then
+ commands.writestatus("color","inherit local color '%s' with attribute: %s",name,ca)
+ end
+ context.colordefflc(name,ca)
+ end
+ else
+ if global then
+ context.colordefrgc(name)
+ else
+ context.colordefrlc(name)
+ end
+ end
+end
+
+local function definetransparent(name, ta, global)
+ if ta and ta > 0 then
+ if global then
+ if trace_define then
+ commands.writestatus("color","define global transparency '%s' with attribute: %s",name,ta)
+ end
+ context.colordefagt(name,ta)
+ else
+ if trace_define then
+ commands.writestatus("color","define local transparency '%s' with attribute: %s",name,ta)
+ end
+ context.colordefalt(name,ta)
+ end
+ else
+ if global then
+ context.colordefrgt(name)
+ else
+ context.colordefrlt(name)
+ end
+ end
+end
+
+local function inherittransparent(name, ta, global)
+ if ta and ta ~= "" then
+ if global then
+ if trace_define then
+ commands.writestatus("color","inherit global transparency '%s' with attribute: %s",name,ta)
+ end
+ context.colordeffgt(name,ta)
+ else
+ if trace_define then
+ commands.writestatus("color","inherit local transparency '%s' with attribute: %s",name,ta)
+ end
+ context.colordefflt(name,ta)
+ end
+ else
+ if global then
+ context.colordefrgt(name)
+ else
+ context.colordefrlt(name)
+ end
+ end
+end
+
+local transparent = {
+ none = 0,
+ normal = 1,
+ multiply = 2,
+ screen = 3,
+ overlay = 4,
+ softlight = 5,
+ hardlight = 6,
+ colordodge = 7,
+ colorburn = 8,
+ darken = 9,
+ lighten = 10,
+ difference = 11,
+ exclusion = 12,
+}
+
+-- 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.)
+
+colors.couple = true
+
+function colors.definetransparency(name,n)
+ transparent[name] = n
+end
+
+local registered = { }
+
+local function do_registerspotcolor(parent,name,parentnumber,e,f,d,p)
+ if not registered[parentnumber] then
+ local v = colors.values[parentnumber]
+ if v then
+ local kind = colors.default -- else problems with shading etc
+ if kind == 1 then kind = v[1] end
+ if e and e ~= "" then
+ registrations.spotcolorname(parent,e) -- before registration of the color
+ end
+ if kind == 2 then -- name noffractions names p's r g b
+ registrations.grayspotcolor(parent,f,d,p,v[2])
+ elseif kind == 3 then
+ registrations.rgbspotcolor (parent,f,d,p,v[3],v[4],v[5])
+ elseif kind == 4 then
+ registrations.cmykspotcolor(parent,f,d,p,v[6],v[7],v[8],v[9])
+ end
+ end
+ registered[parentnumber] = true
+ end
+end
+
+local function do_registermultitonecolor(parent,name,parentnumber,e,f,d,p) -- same as spot but different template
+ if not registered[parentnumber] then
+ local v = colors.values[parentnumber]
+ if v then
+ local kind = colors.default -- else problems with shading etc
+ if kind == 1 then kind = v[1] end
+ if kind == 2 then
+ registrations.grayindexcolor(parent,f,d,p,v[2])
+ elseif kind == 3 then
+ registrations.rgbindexcolor (parent,f,d,p,v[3],v[4],v[5])
+ elseif kind == 4 then
+ registrations.cmykindexcolor(parent,f,d,p,v[6],v[7],v[8],v[9])
+ end
+ end
+ registered[parentnumber] = true
+ end
+end
+
+function colors.definesimplegray(name,s)
+ return register_color(name,'gray',s) -- we still need to get rid of 'color'
+end
+
+function colors.defineprocesscolor(name,str,global,freeze) -- still inconsistent color vs transparent
+ local x = match(str,"^#(.+)$") -- for old times sake (if we need to feed from xml or so)
+ if x then
+ local r, g, b = match(x .. "000000","(..)(..)(..)") -- watch the 255
+ definecolor(name, register_color(name,'rgb',(tonumber(r,16) or 0)/255,(tonumber(g,16) or 0)/255,(tonumber(b,16) or 0)/255), global)
+ else
+ local settings = settings_to_hash_strict(str)
+ if settings then
+ local r, g, b = settings.r, settings.g, settings.b
+ if r or g or b then
+ definecolor(name, register_color(name,'rgb', tonumber(r) or 0, tonumber(g) or 0, tonumber(b) or 0), global)
+ else
+ local c, m, y, k = settings.c, settings.m, settings.y, settings.k
+ if c or m or y or b then
+ definecolor(name, register_color(name,'cmyk',tonumber(c) or 0, tonumber(m) or 0, tonumber(y) or 0, tonumber(k) or 0), global)
+ else
+ local h, s, v = settings.h, settings.s, settings.v
+ if v then
+ r, g, b = colors.hsvtorgb(tonumber(h) or 0, tonumber(s) or 1, tonumber(v) or 1) -- maybe later native
+ definecolor(name, register_color(name,'rgb',r,g,b), global)
+ else
+ local x = settings.x or h
+ if x then
+ r, g, b = match(x .. "000000","(..)(..)(..)") -- watch the 255
+ definecolor(name, register_color(name,'rgb',(tonumber(r,16) or 0)/255,(tonumber(g,16) or 0)/255,(tonumber(b,16) or 0)/255), global)
+ else
+ definecolor(name, register_color(name,'gray',tonumber(s) or 0), global)
+ end
+ end
+ end
+ end
+ local a, t = settings.a, settings.t
+ if a and t then
+ definetransparent(name, transparencies.register(name,transparent[a] or tonumber(a) or 1,tonumber(t) or 1), global)
+ elseif colors.couple then
+ -- definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ definetransparent(name, 0, global) -- can be sped up
+ end
+ elseif freeze then
+ local ca = attributes_list[a_color] [str]
+ local ta = attributes_list[a_transparency][str]
+ if ca then
+ definecolor(name, ca, global)
+ end
+ if ta then
+ definetransparent(name, ta, global)
+ end
+ else
+ inheritcolor(name, str, global)
+ inherittransparent(name, str, global)
+ -- if global and str ~= "" then -- For Peter Rolf who wants access to the numbers in Lua. (Currently only global is supported.)
+ -- attributes_list[a_color] [name] = attributes_list[a_color] [str] or attributes.unsetvalue -- reset
+ -- attributes_list[a_transparency][name] = attributes_list[a_transparency][str] or attributes.unsetvalue
+ -- end
+ end
+ end
+end
+
+function colors.isblack(ca) -- maybe commands
+ local cv = ca > 0 and colors.value(ca)
+ return (cv and cv[2] == 0) or false
+end
+
+function colors.definespotcolor(name,parent,str,global)
+ if parent == "" or find(parent,"=") then
+ colors.registerspotcolor(name, parent)
+ elseif name ~= parent then
+ local cp = attributes_list[a_color][parent]
+ if cp then
+ local t = settings_to_hash_strict(str)
+ if t then
+ local tp = tonumber(t.p) or 1
+ do_registerspotcolor(parent, name, cp, t.e, 1, "", tp) -- p not really needed, only diagnostics
+ if name and name ~= "" then
+ definecolor(name, register_color(name,'spot', parent, 1, "", tp), true)
+ local ta, tt = t.a, t.t
+ if ta and tt then
+ definetransparent(name, transparencies.register(name,transparent[ta] or tonumber(ta) or 1,tonumber(tt) or 1), global)
+ elseif colors.couple then
+ --~ definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ definetransparent(name, 0, global) -- can be sped up
+ end
+ end
+ end
+ end
+ end
+end
+
+function colors.registerspotcolor(parent, str)
+ local cp = attributes_list[a_color][parent]
+ if cp then
+ local e = ""
+ if str then
+ local t = settings_to_hash_strict(str)
+ e = (t and t.e) or ""
+ end
+ do_registerspotcolor(parent, "dummy", cp, e, 1, "", 1) -- p not really needed, only diagnostics
+ end
+end
+
+function colors.definemultitonecolor(name,multispec,colorspec,selfspec)
+ local dd, pp, nn = { }, { }, { }
+ for k,v in gmatch(multispec,"(%a+)=([^%,]*)") do
+ dd[#dd+1] = k
+ pp[#pp+1] = v
+ nn[#nn+1] = k
+ nn[#nn+1] = format("%1.3g",tonumber(v) or 0) -- 0 can't happen
+ end
+--~ v = tonumber(v) * p
+ local nof = #dd
+ if nof > 0 then
+ dd, pp, nn = concat(dd,','), concat(pp,','), concat(nn,'_')
+ local parent = gsub(lower(nn),"[^%d%a%.]+","_")
+ colors.defineprocesscolor(parent,colorspec..","..selfspec,true,true)
+ local cp = attributes_list[a_color][parent]
+ if cp then
+ do_registerspotcolor(parent, name, cp, "", nof, dd, pp)
+ do_registermultitonecolor(parent, name, cp, "", nof, dd, pp)
+ definecolor(name, register_color(name, 'spot', parent, nof, dd, pp), true)
+ local t = settings_to_hash_strict(selfspec)
+ if t and t.a and t.t then
+ definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
+ elseif colors.couple then
+ -- definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
+ definetransparent(name, 0, global) -- can be sped up
+ end
+ end
+ end
+end
+
+function colors.mp(model,ca,ta,default)
+ local cv = colors.value(ca) -- faster when direct colors.values[ca]
+ if cv then
+ local tv = transparencies.value(ta)
+ if model == 1 then
+ model = cv[1]
+ end
+ if tv then
+ if model == 2 then
+ return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
+ elseif model == 3 then
+ return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
+ else
+ return format("transparent(%s,%s,multitonecolor(\"%s\",%s,\"%s\",\"%s\"))",tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
+ end
+ else
+ if model == 2 then
+ return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
+ elseif model == 3 then
+ return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
+ else
+ return format("multitonecolor(\"%s\",%s,\"%s\",\"%s\")",cv[10],cv[11],cv[12],cv[13])
+ end
+ end
+ else
+ default = default or 0 -- rgb !
+ return format("(%s,%s,%s)",default,default,default)
+ end
+end
+
+function colors.formatcolor(ca,separator)
+ local cv = colors.value(ca)
+ if cv then
+ local c, f, t, model = { }, 13, 13, cv[1]
+ if model == 2 then
+ f, t = 2, 2
+ elseif model == 3 then
+ f, t = 3, 5
+ elseif model == 4 then
+ f, t = 6, 9
+ end
+ for i=f,t do
+ c[#c+1] = format("%0.3f",cv[i])
+ end
+ return concat(c,separator)
+ else
+ return format("%0.3f",0)
+ end
+end
+
+function colors.formatgray(ca,separator)
+ local cv = colors.value(ca)
+ return format("%0.3f",(cv and cv[2]) or 0)
+end
+
+function colors.colorcomponents(ca) -- return list
+ local cv = colors.value(ca)
+ if cv then
+ local model = cv[1]
+ if model == 2 then
+ return format("s=%1.3f",cv[2])
+ elseif model == 3 then
+ return format("r=%1.3f g=%1.3f b=%1.3f",cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("c=%1.3f m=%1.3f y=%1.3f k=%1.3f",cv[6],cv[7],cv[8],cv[9])
+ elseif type(cv[13]) == "string" then
+ return format("p=%s",cv[13])
+ else
+ return format("p=%1.3f",cv[13])
+ end
+ else
+ return ""
+ end
+end
+
+function colors.transparencycomponents(ta)
+ local tv = transparencies.value(ta)
+ if tv then
+ return format("a=%1.3f t=%1.3f",tv[1],tv[2])
+ else
+ return ""
+ end
+end
+
+function colors.spotcolorname(ca,default)
+ local cv, v = colors.value(ca), "unknown"
+ if cv and cv[1] == 5 then
+ v = cv[10]
+ end
+ return tostring(v)
+end
+
+function colors.spotcolorparent(ca,default)
+ local cv, v = colors.value(ca), "unknown"
+ if cv and cv[1] == 5 then
+ v = cv[12]
+ if v == "" then
+ v = cv[10]
+ end
+ end
+ return tostring(v)
+end
+
+function colors.spotcolorvalue(ca,default)
+ local cv, v = colors.value(ca), 0
+ if cv and cv[1] == 5 then
+ v = cv[13]
+ end
+ return tostring(v)
+end
+
+-- experiment (a bit of a hack, as we need to get the attribute number)
+
+local min = math.min
+
+-- a[b,c] -> b+a*(c-b)
+
+local function f(one,two,i,fraction)
+ local o, t = one[i], two[i]
+ local otf = o + fraction * (t - o)
+ if otf > 1 then
+ otf = 1
+ end
+ return otf
+end
+
+function colors.defineintermediatecolor(name,fraction,c_one,c_two,a_one,a_two,specs,global,freeze)
+ fraction = tonumber(fraction) or 1
+ local one, two = colors.value(c_one), colors.value(c_two)
+ if one and two then
+ local csone, cstwo = one[1], two[1]
+ if csone == cstwo then
+ -- actually we can set all 8 values at once here but this is cleaner as we avoid
+ -- problems with weighted gray conversions and work with original values
+ local ca
+ if csone == 2 then
+ ca = register_color(name,'gray',f(one,two,2,fraction))
+ elseif csone == 3 then
+ ca = register_color(name,'rgb',f(one,two,3,fraction),f(one,two,4,fraction),f(one,two,5,fraction))
+ elseif csone == 4 then
+ ca = register_color(name,'cmyk',f(one,two,6,fraction),f(one,two,7,fraction),f(one,two,8,fraction),f(one,two,9,fraction))
+ else
+ ca = register_color(name,'gray',f(one,two,2,fraction))
+ end
+ definecolor(name,ca,global,freeze)
+ end
+ end
+ local one, two = transparencies.value(a_one), transparencies.value(a_two)
+ local t = settings_to_hash_strict(specs)
+ local ta = tonumber((t and t.a) or (one and one[1]) or (two and two[1]))
+ local tt = tonumber((t and t.t) or (one and two and f(one,two,2,fraction)))
+ if ta and tt then
+--~ print(ta,tt)
+ definetransparent(name,transparencies.register(name,ta,tt),global)
+ end
+end
diff --git a/tex/context/base/colo-ini.mkii b/tex/context/base/colo-ini.mkii
new file mode 100644
index 000000000..2d2a7bdaa
--- /dev/null
+++ b/tex/context/base/colo-ini.mkii
@@ -0,0 +1,2776 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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 hav eto make sure that mkiv
+%D code works ok.
+
+\writestatus{loading}{ConTeXt Color Macros / Initialization}
+
+%D This module implements color. Since \MKII\ and \MKIV\ use a completely
+%D different approach, this module only implements a few generic mechanisms.
+
+\unprotect
+
+\chardef\colorversion=1 % temp, needed for tracing purposes, mkiv transition
+
+%D We use a couple of local registers. That way we don't have
+%D to group when converting colors. By the way, this is not
+%D really faster. We can sqeeze half a second runtime for 50K
+%D switches on a 1G machine, but the macros will become rather
+%D ugly then. To mention one such improvement: no colon
+%D after the key character (.25 sec).
+
+\newdimen\colordimen
+\newcount\colorcount
+
+%D When typesetting for paper, we prefer using the \cap{CMYK}
+%D color space, but for on||screen viewing we prefer \cap{RGB}
+%D (the previous implementation supported only this scheme).
+%D Independant of such specifications, we support some automatic
+%D conversions:
+%D
+%D \startitemize[packed]
+%D \item convert all colors to \cap{RGB}
+%D \item convert all colors to \cap{CMYK}
+%D \item convert all colors to gray scales
+%D \stopitemize
+%D
+%D We also support optimization of colors to gray scales.
+%D
+%D \startitemize[continue]
+%D \item reduce gray colors to gray scales
+%D \item reduce \cap{CMY} components to \cap{K}
+%D \stopitemize
+%D
+%D These options are communicated by means of:
+
+\newif\ifRGBsupported
+\newif\ifCMYKsupported
+\newif\ifSPOTsupported
+\newif\ifpreferGRAY
+\newif\ifGRAYprefered
+\newif\ifreduceCMYK
+\newif\ifconverttoGRAY
+\newif\ifweightGRAY \weightGRAYtrue
+
+\newif\ifconvertMPcolors
+\newif\ifreduceMPcolors
+\newif\ifforcegrayMPcolors
+
+%D The last boolean controls reduction of \cap{CMYK} to
+%D \cap{CMY} colors. When set to true, the black component
+%D is added to the other ones.
+%D
+%D Prefering gray is not the same as converting to gray.
+%D Conversion treats each color components in a different way,
+%D while prefering is just a reduction and thus a
+%D space||saving option.
+
+\newif\iffreezecolors \freezecolorsfalse
+\newif\ifincolor % true if colors enabled
+\newif\iflocalcolor
+
+\let\colorlist \empty
+\let\currentspotcolor \empty
+\let\allspotcolors \empty
+\let\usedspotcolors \empty
+\let\usedcolorchannels\empty
+\let\currentpalet \empty
+
+%D \macros
+%D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor}
+%D
+%D \startbuffer
+%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 \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 \stopbuffer
+%D
+%D \getbuffer \typebuffer
+
+\def\definecolor {\dodoubleargument\dodefinecolor}
+\def\defineglobalcolor {\dodoubleargument\dodefineglobalcolor}
+\def\definenamedcolor {\dodoubleargument\dodefinenamedcolor}
+\def\definespotcolor {\dotripleargument\dodefinespotcolor}
+\def\definemultitonecolor{\doquadrupleempty\dodefinemultitonecolor}
+
+% check: registerusedspotcolors
+% check: registerusedcolorchannels
+
+%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.
+
+\ifx\doifcolorelse\undefined
+ \let\doifcolorelse\secondoftwoarguments
+ \let\doifcolor \gobbleoneargument
+\fi
+
+%D \macros
+%D {localstartcolor,localstopcolor}
+%D
+%D Simple color support, that is without nesting, is provided
+%D by:
+
+\ifx\localstartcolor\undefined
+ \let\localstartcolor\undefined
+ \let\localstopcolor \undefined
+\fi
+
+%D \macros
+%D {faststartcolor,faststopcolor}
+%D
+%D No checking for arguments and such:
+
+\ifx\faststartcolor\undefined
+ \def\faststartcolor[#1]{}
+ \def\faststopcolor {}
+\fi
+
+%D These local ones may go away in future versions.
+
+%D \macros
+%D {startcolor,stopcolor}
+%D
+%D The more save method, the one that saves the current color
+%D state and returns to this state afterward, is activated by:
+%D
+%D \showsetup{startcolor}
+
+\ifx\startcolor\undefined
+ \let\startcolor\undefined
+ \let\stopcolor \undefined
+\fi
+
+%D \macros
+%D {startcurrentcolor,stopcurrentcolor}
+
+\def\startcurrentcolor{\startcolor[\outercolorname]}
+\def\stopcurrentcolor {\stopcolor}
+
+%D \macros
+%D {color,graycolor}
+%D
+%D This leaves the simple color command:
+%D
+%D \showsetup{color}
+%D \showsetup{graycolor}
+
+\ifx\color\undefined
+ \def\color [#1]{}
+ \def\graycolor[#1]{}
+ \def\gray {\graycolor}
+\fi
+
+%D \macros
+%D {localstartraster,localstopraster,
+%D startraster,stopraster,raster}
+%D
+%D The previous conversions are not linear and treat each color
+%D component according to human perception curves. Pure gray
+%D (we call them rasters) has equal color components. In
+%D \CONTEXT\ rasters are only used as backgrounds and these
+%D don't cross page boundaries in the way color does. Therefore
+%D we don't need stacks and marks. Just to be compatible with
+%D color support we offer both 'global' and 'local' commands.
+
+\ifx\startraster\undefined
+ \def\startraster [#1]{}
+ \def\stopraster {}
+ \def\raster [#1]{}
+ \def\localstartraster[#1]{}
+ \def\localstopraster {}
+\fi
+
+%D \macros
+%D {colorvalue, grayvalue}
+%D
+%D We can typeset the color components using \type{\colorvalue} and
+%D \type{\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 \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+
+\def\colorformatseparator{ }
+
+\ifx\colorvalue\undefined
+ \let\colorvalue\gobbleoneargument
+ \let\grayvalue \gobbleoneargument
+\fi
+
+% check: \currentcolorname
+% check: \outercolorname
+
+%D \macros
+%D {setupcolor}
+%D
+%D Color definitions can be grouped in files with the name:
+%D
+%D \starttyping
+%D \f!colorprefix-identifier.tex
+%D \stoptyping
+%D
+%D where \type{\f!colorprefix} is \unprotect {\tttf \f!colorprefix}.
+%D Loading such a file is done by \protect
+%D
+%D \showsetup{setupcolor}
+%D
+%D Some default colors are specified in \type{colo-rgb.tex},
+%D which is loaded into the format by:
+%D
+%D \starttyping
+%D \setupcolor[rgb]
+%D \stoptyping
+
+\let\colorstyle\empty
+
+\def\setupcolor
+ {\dosingleargument\dosetupcolor}
+
+\def\dosetupcolor[#1]%
+ {\doifnot{#1}\colorstyle
+ {\def\colorstyle{#1}%
+ \processcommalist[#1]\dodosetupcolor}}
+
+\def\dodosetupcolor#1%
+ {\makeshortfilename[\truefilename{\f!colorprefix#1}]%
+ \startreadingfile
+ \readsysfile\shortfilename
+ {\showmessage\m!colors4\colorstyle}
+ {\showmessage\m!colors5\colorstyle}%
+ \stopreadingfile}
+
+\let\usecolors\setupcolor
+
+% check: \chardef\currentcolorchannel=0
+% check: \startcolormode
+% check: \newif\iffilterspotcolor \filterspotcolorfalse
+% check: \newif\ifdoingspotcolor \doingspotcolorfalse
+% check: \registercolorchannel
+
+%D \macros
+%D {definetransparency}
+%D
+%D This command numbers to names:
+
+\def\definetransparency
+ {\dodoubleargument\dodefinetransparency}
+
+\def\setupcolors
+ {\dosingleargument\dosetupcolors}
+
+\def\resetcolorsplitting
+ {\chardef\currentcolorchannel\zerocount
+ \let\currentspotcolor\empty
+ \filterspotcolorfalse}
+
+\def\colorsplitsuffix{\ifcase\currentcolorchannel\else-\@@clsplit\fi}
+\def\colorsplitprefix{\ifcase\currentcolorchannel\else\@@clsplit-\fi}
+
+\def\setcolorsplitting
+ {\resetsystemmode{\v!color\colorsplitsuffix}%
+ \resetcolorsplitting
+ \processaction
+ [\@@clsplit]
+ [ c=>\chardef\currentcolorchannel1,%
+ m=>\chardef\currentcolorchannel2,%
+ y=>\chardef\currentcolorchannel3,%
+ k=>\chardef\currentcolorchannel4,%
+ r=>\chardef\currentcolorchannel5,%
+ g=>\chardef\currentcolorchannel6,%
+ b=>\chardef\currentcolorchannel7,%
+ s=>\chardef\currentcolorchannel8,%
+ \v!no=>,% \currentcolorchannel0,% all colors
+ \s!default=>,% \currentcolorchannel0,% all colors
+ \s!unknown=>\filterspotcolortrue
+ \edef\currentspotcolor{\commalistelement}]%
+ \setsystemmode{\v!color\colorsplitsuffix}%
+ \iffilterspotcolor \let\@@clrgb\v!no \fi}
+
+\ifx\dosetupcolormodel\undefined
+ \let\dosetupcolormodel\relax
+\fi
+
+\def\dosetupcolors[#1]% some no longer make sense in MkIV
+ {\getparameters[\??cl][#1]%
+ \doifelse\@@clspot\v!yes
+ \SPOTsupportedtrue
+ \SPOTsupportedfalse
+ \doifelsenothing\@@clsplit
+ \resetcolorsplitting
+ \setcolorsplitting
+ \doifelse\@@clreduction\v!yes
+ \reduceCMYKtrue
+ \reduceCMYKfalse
+ \doifelse\@@clexpansion\v!yes
+ \freezecolorstrue
+ \freezecolorsfalse
+ \doifelse\@@clcriterium\v!all
+ \hidesplitcolortrue
+ \hidesplitcolorfalse
+ \doifelse\@@clrgb\v!no
+ {\ifRGBsupported \ifproductionrun\showmessage\m!colors {9}\v!rgb \fi\RGBsupportedfalse \fi}
+ {\ifRGBsupported \else\ifproductionrun\showmessage\m!colors{10}\v!rgb \fi\RGBsupportedtrue \fi}%
+ \doifelse\@@clcmyk\v!no
+ {\ifCMYKsupported \ifproductionrun\showmessage\m!colors {9}\v!cmyk \fi\CMYKsupportedfalse\fi}
+ {\ifCMYKsupported\else\ifproductionrun\showmessage\m!colors{10}\v!cmyk \fi\CMYKsupportedtrue \fi}%
+ \doifelse\@@clmpcmyk\v!no
+ {\ifMPcmykcolors \ifproductionrun\showmessage\m!colors {9}{\v!mp\v!cmyk}\fi\MPcmykcolorsfalse \fi}
+ {\ifMPcmykcolors \else\ifproductionrun\showmessage\m!colors{10}{\v!mp\v!cmyk}\fi\MPcmykcolorstrue \fi}%
+ \doifelse\@@clmpspot\v!no
+ {\ifMPspotcolors \ifproductionrun\showmessage\m!colors {9}{\v!mp\v!spot}\fi\MPspotcolorsfalse \fi}
+ {\ifMPspotcolors \else\ifproductionrun\showmessage\m!colors{10}{\v!mp\v!spot}\fi\MPspotcolorstrue \fi}%
+ \preferGRAYfalse
+ \processaction
+ [\@@clconversion]
+ [ \v!yes=>\preferGRAYtrue,
+ \v!always=>\preferGRAYtrue\RGBsupportedfalse\CMYKsupportedfalse]%
+ \ifRGBsupported
+ \converttoGRAYfalse
+ \forcegrayMPcolorsfalse
+ \else\ifCMYKsupported
+ \converttoGRAYfalse
+ \forcegrayMPcolorsfalse
+ \convertMPcolorstrue
+ \ifreduceCMYK
+ \reduceMPcolorstrue
+ \fi
+ \else
+ \ifconverttoGRAY\else\showmessage\m!colors{11}\empty\fi
+ \converttoGRAYtrue
+ \forcegrayMPcolorstrue
+ \convertMPcolorsfalse
+ \reduceMPcolorsfalse
+ \fi\fi
+ \processaction
+ [\@@clstate]
+ [ \v!global=>\ifincolor\else\showmessage\m!colors1\colorstyle\fi
+ \incolortrue\localcolorfalse,
+ \v!local=>\ifincolor\else\showmessage\m!colors2\colorstyle\fi
+ \incolortrue\localcolortrue,
+ \v!start=>\ifincolor\else\showmessage\m!colors1\colorstyle\fi
+ \incolortrue\localcolorfalse
+ \let\@@clstate\v!global,
+ \v!stop=>\incolorfalse\localcolorfalse
+ \forcegrayMPcolorstrue]%
+ \dosetupcolormodel
+ \initializemaintextcolor}
+
+%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.
+
+\ifx\startregistercolor\undefined
+ \def\startregistercolor[#1]{}
+ \def\stopregistercolor {}
+\fi
+
+%D We use these macros for implementing text colors
+%D (actually, the first application was in foreground
+%D 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
+
+\def\maintextcolor {}
+\def\defaulttextcolor {black}
+\def\@@themaintextcolor{themaintextcolor}
+
+\ifx\initializemaintextcolor\undefined
+ \def\starttextcolor [#1]{}
+ \def\stoptextcolor {}
+ \def\initializemaintextcolor {}
+\fi
+
+\ifx\restoretextcolor\undefined % to be redone
+ \let\restoretextcolor \firstofoneargument
+ \let\localstarttextcolor\relax
+ \let\localstoptextcolor \relax
+\fi
+
+%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
+%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
+%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 \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
+%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
+%D palet components (not 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
+%D deal with pretty verbatim typesetting.
+
+\def\definepalet
+ {\dodoubleargument\dodefinepalet}
+
+\def\dodefinepalet[#1][#2]%
+ {\doifassignmentelse{#2}
+ {%\showmessage\m!colors6{#1}%
+ \letvalue{\??pa#1}\empty
+ \setevalue{\??pa\??pa#1}{#2}%
+ \def\dodododefinepalet[##1=##2]%
+ {\doifvaluesomething{\??pa#1}
+ {\setevalue{\??pa#1}{\csname\??pa#1\endcsname,}}%
+ \setevalue{\??pa#1}{\csname\??pa#1\endcsname##1}%
+ \dodefinepaletcolor{#1}{##1}{##2}}%
+ \def\dododefinepalet##1%
+ {\dodododefinepalet[##1]}%
+ \processcommalist[#2]\dododefinepalet}
+ {\doifdefined{\??pa#2}
+ {\expanded{\dodefinepalet[#1][\csname\??pa\??pa#2\endcsname]}}}}
+
+\ifx\dodefinepaletcolor\undefined
+ \let\dodefinepaletcolor\gobblethreearguments
+\fi
+
+\let\paletsize\!!zerocount
+
+\def\getpaletsize[#1]%
+ {\getcommacommandsize[\csname\??pa\??pa#1\endcsname]%
+ \edef\paletsize{\number\commalistsize}}
+
+%D Instead of refering to colors, one can also directly specify
+%D 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.
+%D Setting the current palet is done by:
+%D
+%D \showsetup{setuppalet}
+
+\let\currentpalet\empty
+
+\def\setuppalet
+ {\dosingleempty\dosetuppalet}
+
+\def\dosetuppalet[#1]%
+ {\edef\currentpalet{#1}%
+ \ifx\currentpalet\empty
+ % seems to be a reset
+ \else\ifcsname\??pa\currentpalet\endcsname
+ \edef\currentpalet{#1:}%
+ \else
+ \showmessage\m!colors7\currentpalet
+ \let\currentpalet\empty
+ \fi\fi}
+
+%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!colorprefix\s!run}
+
+%D \macros
+%D {showcolorcomponents}
+%D
+%D \starttyping
+%D \showcolorcomponents[color-1,color-2]
+%D \stoptyping
+
+\fetchruntimecommand \showcolorcomponents {\f!colorprefix\s!run}
+
+%D \macros
+%D {definecolorgroup}
+%D
+%D The naming of the colors in this palet suggests some
+%D ordening, which in turn is suported by color grouping.
+%D
+%D \starttyping
+%D \definecolorgroup
+%D [red]
+%D [1.00:0.90:0.90,
+%D 1.00:0.80:0.80,
+%D 1.00:0.70:0.70,
+%D 1.00:0.55:0.55,
+%D 1.00:0.40:0.40,
+%D 1.00:0.25:0.25,
+%D 1.00:0.15:0.15,
+%D 0.90:0.00:0.00]
+%D \stoptyping
+%D
+%D In such a color group colors are numbered from~$1$ to~$n$.
+%D
+%D \showsetup{definecolorgroup}
+%D
+%D This kind of specification is not only more compact than
+%D defining each color separate, it also loads faster and takes
+%D less bytes.
+
+\def\definecolorgroup
+ {\dotripleempty\dodefinecolorgroup}
+
+\def\dododefinecolorgroupgray [#1][#2:#3]{\definecolor [#1:\the\colorcount][s=#2]}
+\def\dododefinecolorgrouprgb [#1][#2:#3:#4:#5]{\definecolor [#1:\the\colorcount][r=#2,g=#3,b=#4]}
+\def\dododefinecolorgroupcmyk[#1][#2:#3:#4:#5:#6]{\definecolor [#1:\the\colorcount][c=#2,m=#3=,y=#4,k=#5]}
+\def\dododefinecolorgroupspot [#1][#2:#3:#4]{\definespotcolor[#1:\the\colorcount][#2][p=#3]}
+
+\def\dododefinecolorgroup#1#2%
+ {\advance\colorcount\plusone
+ \getvalue{dododefinecolorgroup\currentcolorspace}[#1][#2:0:0:0:0]}
+
+\def\dodefinecolorgroup[#1][#2][#3]% obsolete, just use palets
+ {\ifthirdargument
+ \doifelsenothing{#2}{\let\currentcolorspace\v!rgb}{\def\currentcolorspace{#2}}%
+ \colorcount\zerocount
+ \processcommalist[#3]{\dododefinecolorgroup{#1}}%
+ \else
+ \doifinstringelse{:}{#2}
+ {\definecolorgroup[#1][\v!rgb][#2]}
+ {\doloop
+ {\doifdefinedelse{\??cr#2:\recurselevel}
+ {\setevalue{\??cr#1:\recurselevel}{\csname\??cr#2:\recurselevel\endcsname}}
+ {\exitloop}}}%
+ \fi}
+
+%D \macros
+%D {showcolorgroup}
+%D
+%D We can show the group by:
+%D
+%D \startbuffer
+%D \showcolorgroup [blue] [horizontal,name,number,value]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or in color:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D which uses:
+%D
+%D \showsetup{showcolorgroup}
+
+\fetchruntimecommand \showcolorgroup {\f!colorprefix\s!run}
+
+%D There are ten predefined color groups, like
+%D \color[green]{\em groen}, \color[red]{\em rood},
+%D \color[blue]{\em blauw}, \color[cyan]{\em cyaan},
+%D \color[magenta]{\em magenta} and \color[yellow]{\em geel}.
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\hss
+%D \showcolorgroup [red] [vertical,name,number]\hss
+%D \showcolorgroup [green] [vertical,name]\hss
+%D \showcolorgroup [blue] [vertical,name]\hss
+%D \showcolorgroup [cyan] [vertical,name]\hss
+%D \showcolorgroup [magenta][vertical,name]\hss
+%D \showcolorgroup [yellow] [vertical,name]\hss}
+%D \stoplinecorrection
+%D
+%D These groups are used to define palets {\em alfa} upto {\em
+%D zeta}. As long as we don't use colors from the same row, we
+%D get ourselves distinctive palets. By activating such a palet
+%D one gains access to its members {\em top} to {\em charm} (of
+%D course one should use more suitable names than these).
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\showpalet [alfa] [vertical,name,number]\hss
+%D \showpalet [beta] [vertical,name]\hss
+%D \showpalet [gamma] [vertical,name]\hss
+%D \showpalet [delta] [vertical,name]\hss
+%D \showpalet [epsilon] [vertical,name]\hss
+%D \showpalet [zeta] [vertical,name]}
+%D \stoplinecorrection
+%D
+%D By using the keyword \type {value} the individual color
+%D components are shown too. When printed in color, these
+%D showcases show both the colors and the gray value.
+
+%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!colorprefix\s!run}
+
+%D \macros
+%D {comparecolorgroup}
+%D
+%D The similar command:
+%D
+%D \startbuffer
+%D \comparecolorgroup [blue]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows color groups:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D this commands are defined as:
+%D
+%D \showsetup{comparecolorgroup}
+
+\fetchruntimecommand \comparecolorgroup {\f!colorprefix\s!run}
+
+%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
+%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!colorprefix\s!run}
+
+%D It would make sense to put the following code in \type
+%D {colo-mps}, but it it rather low level.
+
+%D \macros
+%D {negatecolorcomponent,negatedcolorcomponent}
+%D
+%D These speak for themselves. See \type {colo-ext} for usage.
+
+\def\negatecolorcomponent#1% #1 = \macro
+ {\scratchdimen\onepoint\advance\scratchdimen-#1\onepoint
+ \ifdim\scratchdimen<\zeropoint\scratchdimen\zeropoint\fi
+ \edef#1{\withoutpt\the\scratchdimen}}
+
+\let\negatedcolorcomponent\firstofoneargument
+
+\def\negatedcolorcomponent#1%
+ {\ifdim\dimexpr\onepoint-#1\onepoint\relax<\zeropoint
+ \!!zerocount
+ \else
+ \expandafter\withoutpt\the\dimexpr\onepoint-#1\onepoint\relax
+ \fi}
+
+\def\negatecolorcomponent#1% #1 = \macro
+ {\edef#1{\negatedcolorcomponent{#1}}}
+
+%D \macros
+%D {ifMPgraphics, ifMPcmykcolors, MPcolor}
+%D
+%D A very special macro is \type{\MPcolor}. This one can be
+%D used to pass a \CONTEXT\ color to \METAPOST.
+%D
+%D \starttyping
+%D \MPcolor{my own red}
+%D \stoptyping
+%D
+%D This macro returns a \METAPOST\ triplet \type{(R,G,B)}.
+%D Unless \CMYK\ color support is turned on with \type
+%D {MPcmyk}, only \cap{RGB} colors and gray scales are
+%D supported.
+
+\newif\ifMPcmykcolors % \MPcmykcolorsfalse
+\newif\ifMPspotcolors % \MPspotcolorsfalse
+
+\ifx\MPcolor\undefined
+ \def\MPcolor#1{(0,0,0)}
+\fi
+
+%D \macros
+%D {PDFcolor,FDFcolor}
+%D
+%D Similar alternatives are avaliable for \PDF:
+
+%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
+%D Well, in case we want to do color separation and use CMYK
+%D colors only, this is dangerous since unwanted remapping may
+%D take place. Especially when we redefine already defined
+%D colors in another color space (e.g. darkgreen is
+%D predefined in RGB color space, so a redefinition in CMYK
+%D coordinates before RGB mode is disabled, would give
+%D unexpected results due to the already frozen color spec.)
+%D
+%D So, from now on, colors are not frozen any more!
+
+\chardef\currentcolorchannel=0
+
+\newif\iffilterspotcolor \filterspotcolorfalse
+\newif\ifdoingspotcolor \doingspotcolorfalse
+
+\def\registercolorchannel#1%
+ {\ifdoingspotcolor \else
+ \global\expandafter\chardef\csname\??cs#1\endcsname\zerocount
+ \fi}
+
+\newif\ifhidesplitcolor \hidesplitcolortrue
+
+%D The next macro is for instance used in figure splitting:
+
+\def\doifseparatingcolorselse
+ {\iffilterspotcolor
+ \@EA\firstoftwoarguments
+ \else\ifcase\currentcolorchannel
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi\fi}
+
+\def\doifcolorchannelelse#1%
+ {\doifseparatingcolorselse
+ {\doifelsenothing{#1}
+ \secondoftwoarguments
+ {\doifelse{#1}\@@clsplit
+ \firstoftwoarguments
+ \secondoftwoarguments}}
+ \secondoftwoarguments}
+
+\def\resetcolorseparation
+ {\filterspotcolorfalse
+ \chardef\currentcolorchannel\zerocount}
+
+%D These can be used in selecting specific files (like
+%D figuredatabases).
+
+% we already have:
+%
+% \def\colorsplitsuffix{\ifcase\currentcolorchannel\else-\@@clsplitsen\fi}
+% \def\colorsplitprefix{\ifcase\currentcolorchannel\else\@@clsplitsen-\fi}
+
+\def\colorchannelprefix{\doifseparatingcolorselse\@@clsplit\empty-}
+\def\colorchannelsuffix{-\doifseparatingcolorselse\@@clsplit\empty}
+
+%D We now define the low level macros:
+
+\chardef\colorversion=1
+
+%D Color support is not present in \TEX. Colorful output can
+%D however be accomplished by using specials. This also means
+%D that this support depends on the \DVI\ driver used. At the
+%D moment this module was written, still no decent standard on
+%D color specials has been agreed upon. We therefore decided to
+%D implement a mechanism that is as independant as possible of
+%D drivers.
+%D
+%D Color support shares with fonts that is must be implemented
+%D in a way that permits processing of individual \DVI\ pages.
+%D Furthermore it should honour grouping. The first condition
+%D forces us to use a scheme that keeps track of colors at
+%D page boundaries. This can be done by means of \TEX's
+%D marking mechanism (\type{\mark}).
+%D
+%D When building pages, \TEX\ periodically looks at the
+%D accumulated typeset contents and breaks the page when
+%D suitable. At that moment, control is transfered to the
+%D output routine. This routine takes care of building the
+%D pagebody and for instance adds headers and footers. The page
+%D can be broken in the middle of some colored text, but
+%D headers and footers are often in black upon white or
+%D background. If colors are applied there, they definitely
+%D are used local, which means that they don't cross page
+%D borders.
+%D
+%D Boxes are handled as a whole, which means that when we
+%D apply colors inside a box, those colors don't cross page
+%D boundaries, unless of course boxes are split or unboxed.
+%D Especially in interactive texts, colors are often used in
+%D such a local way: in boxes (buttons and navigational tools)
+%D or in the pagebody (backgrounds).
+%D
+%D So we can distinguish local colors, that don't cross
+%D pages from global colors, of which we can end many pages
+%D later. The color macros will treat both types in a different
+%D way, thus gaining some speed.
+%D
+%D This module also deals with gray scales. Because similar
+%D colors can end up in the same gray scale when printed in
+%D black and white, we also implement a palet system that deals
+%D with these matters. Because of fundamental differences
+%D between color and gray scale printing, in \CONTEXT\ we also
+%D differ between these. For historic reasons |<|we first
+%D implemented gray scales using patterns of tiny periods|>|
+%D and therefore called them {\em rasters}. So don't be
+%D surprised if this term shows up.
+
+%D \macros
+%D {definecolor}
+%D
+%D We will enable users to specify colors in \cap{RGB} and
+%D \cap{CMYK} color spaces or gray scales using
+%D
+%D \showsetup{definecolor}
+%D
+%D For example:
+%D
+%D \starttyping
+%D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05]
+%D \stoptyping
+%D
+%D Such color specifications are saved in a macro in the
+%D following way:
+%D
+%D \starttyping
+%D \setvalue{\??cr name}{R:r:g:b}
+%D \setvalue{\??cr name}{C:c:m:y:k}
+%D \setvalue{\??cr name}{S:s}
+%D \stoptyping
+%D
+%D Gray scales are specified with the \type{s} parameter,
+%D where the \type {s} is derived from {\em screen}.
+%D
+%D Starting with \PDF\ 1.4 (2001) \CONTEXT\ supports
+%D transparent colors. The transparency factor is represented
+%D by a \type {t} and the transparency method by an \type {a}
+%D (alternative). Later we will implement more control
+%D (probably by symbolic methods. So, currently the data is
+%D stored as follows:
+%D
+%D \starttyping
+%D \setvalue{\??cr name}{R:r:g:b:a:t}
+%D \setvalue{\??cr name}{C:c:m:y:k:a:t}
+%D \setvalue{\??cr name}{S:s:a:t}
+%D \stoptyping
+
+% r g b : rbg
+% c m y k : cmyk
+% s : gray
+% p n d f : spot
+% h : hexadecimal
+% t a : transparency
+% e : equivalent (spotcolors)
+
+\def\@@cl@@z{0}
+\def\@@cl@@o{1}
+
+\def\@@resetcolorparameters
+ {\let\@@cl@@r\@@cl@@z \let\@@cl@@g\@@cl@@z \let\@@cl@@b\@@cl@@z
+ \let\@@cl@@c\@@cl@@z \let\@@cl@@m\@@cl@@z \let\@@cl@@y\@@cl@@z \let\@@cl@@k\@@cl@@z
+ \let\@@cl@@s\@@cl@@z
+ \let\@@cl@@p\@@cl@@o \let\@@cl@@n\empty \let\@@cl@@d\empty \let\@@cl@@f\@@cl@@o
+ \let\@@cl@@h\empty
+ \let\@@cl@@e\empty
+ \let\@@cl@@t\@@cl@@z \let\@@cl@@a\@@cl@@z}
+
+\@@resetcolorparameters
+
+\def\@@cl@@A{\@@cl@@a} % a hook for symbolic conversion, see below
+
+%D Handling a few nested \type{\cs}'s is no problem (\type
+%D {\@EA\@EAEAEA\@EA}) but we need a full expansion, so I
+%D tried one of the fully expandable primitives using a sort
+%D of delimited thing. I tried \type {\number} first, but this
+%D does not work, but \type {\romannumeral} does. Actually,
+%D \type{\romannumeral0} returns nothing, so it's a perfect
+%D candidate for this kind of hackery. This reminds me that I
+%D have to look into David Kastrup's Euro\TeX\ 2002 article
+%D because he is using \type {\romannumeral} for loops
+%D (repetitive \quote {m} stuff).
+
+% \def\x{\y}\def\y{\z}\def\z{0:1:1:1}
+%
+% \def\bla #1:#2:#3\end{}
+%
+% \@EA\bla\romannumeral\x\end
+
+\def\colorXpattern{0S:\@@cl@@z:\@@cl@@z:\@@cl@@z}
+\def\colorZpattern{0S:\@@cl@@z:\@@cl@@A:\@@cl@@t}
+\def\colorSpattern{0S:\@@cl@@s:\@@cl@@A:\@@cl@@t}
+\def\colorCpattern{0C:\@@cl@@c:\@@cl@@m:\@@cl@@y:\@@cl@@k:\@@cl@@A:\@@cl@@t}
+\def\colorRpattern{0R:\@@cl@@r:\@@cl@@g:\@@cl@@b:\@@cl@@A:\@@cl@@t}
+
+%def\colorPpattern{0P:\@@cl@@n:\@@cl@@p:\@@cl@@A:\@@cl@@t}
+
+\def\colorPpattern{0P:\@@cl@@n:\@@cl@@f:\@@cl@@d:\@@cl@@p:\@@cl@@A:\@@cl@@t}
+
+%D The extra 0 catches empty colors specs (needed for the
+%D \type {\MPcolor} and \type {\PDFcolor} conversion (\type
+%D {\@@cr} equals \type {\relax}!).
+
+\def\handlecolorwith#1{\@EA#1\romannumeral0}
+
+%D Next comes the main definition macro.
+
+\def\dodefinecolor {\dododefinecolor\relax \setvalue \setevalue1}
+\def\dodefineglobalcolor{\dododefinecolor\doglobal\setgvalue\setxvalue1}
+\def\dodefinenamedcolor {\dododefinecolor\doglobal\setvalue \setevalue0}
+
+\let\colorlist\empty % not really used, only for colo-run
+\setfalse\collectcolorsinlist
+\def\collectcolorinlist#1{\doglobal\addtocommalist{#1}\colorlist}
+
+\def\dododefinecolor#1#2#3#4[#5][#6]% #2==set(g)value #3==set[e|x]value
+ {\ifconditional\collectcolorsinlist\collectcolorinlist{#5}\fi
+ \doifassignmentelse{#6}
+ {\@@resetcolorparameters
+ \getparameters[\??cl @@][#6]%
+ \ifx\@@cl@@h\empty
+ \doifelse{\@@cl@@r\@@cl@@g\@@cl@@b}{\@@cl@@z\@@cl@@z\@@cl@@z}
+ {\doifelse{\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k}{\@@cl@@z\@@cl@@z\@@cl@@z\@@cl@@z}
+ {\doifelse\@@cl@@s\@@cl@@z
+ {\showmessage\m!colors8{{[#6]},#5}%
+ #3{\??cr#5}{\colorZpattern}}
+ {#3{\??cr#5}{\colorSpattern}}}
+ {#3{\??cr#5}{\colorCpattern}}}
+ {#3{\??cr#5}{\colorRpattern}}%
+ \else
+ \setxvalue{\??cr#5}{\colorHpattern}%
+ \fi
+ % new: e=external spot color name
+ \ifx\@@cl@@e\empty \else
+ \doregisterspotcolorname{#5}\@@cl@@e
+ \fi}
+ {\doifelsenothing\currentpalet
+ \donefalse
+ {\doifdefinedelse{\??cr\currentpalet#6}\donetrue\donefalse}%
+ \ifdone
+ \doifnot{#5}{#6}
+ {#2{\??cr#5}{\paletcolorspec{#6}}}%
+ \else
+ \doifdefinedelse{\??cr#6}
+ {\doifelse{#5}{#6}
+ {% this way we can freeze \definecolor[somecolor][somecolor]
+ % and still prevent cyclic definitions
+ \iffreezecolors#3{\??cr#5}{\csname\??cr#6\endcsname}\fi}
+ {\iffreezecolors\@EA#3\else\@EA#2\fi{\??cr#5}{\csname\??cr#6\endcsname}}}
+ {\showmessage\m!colors3{#5 (def)}}%
+ \fi}%
+ \ifcase#4\or
+ \unexpanded#2{#5}{\switchtocolor[#5]}% \unexpanded toegevoegd
+ \fi}
+
+\def\paletcolorspec#1%
+ {\csname\??cr\currentpalet#1\endcsname}
+
+%D Hex color support is not enabled by default. You need to say \type
+%D {\setupcolor [hex]} to get this working.
+
+\ifx\colorHpattern\undefined \let\colorHpattern\colorZpattern \fi
+
+%D New and experimental.
+
+\def\dodefinespotcolor[#1][#2][#3]% todo: always global
+ {\doifnot{#1}{#2}
+ {\@@resetcolorparameters
+ \ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
+ \edef\@@cl@@n{#2}%
+ \getparameters[\??cl @@][#3]%
+ \doifnothing\@@cl@@p{\let\@@cl@@p\!!plusone}%
+ \ifx\@@cl@@e\empty \else
+ \doregisterspotcolorname{#2}\@@cl@@e
+ \fi
+ \doglobal\addtocommalist{#2}\allspotcolors
+ \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue
+ \setgvalue{#1}{\switchtocolor[#1]}}} % was \setvalue
+
+\def\registerusedspotcolors
+ {\ifx\allspotcolors\empty \else
+ \bgroup
+ \let\usedspotcolors\empty
+ \def\docommand##1%
+ {\doifdefined{\??cs##1}{\addtocommalist{##1}\usedspotcolors}}%
+ \processcommacommand[\allspotcolors]\docommand
+ \savecurrentvalue\usedspotcolors\usedspotcolors
+ \egroup
+ \fi}
+
+\def\registerusedcolorchannels
+ {\bgroup
+ \doifdefinedelse{\??cs c}
+ {\def\usedcolorchannels{c,m,y,k}}%
+ {\let\usedcolorchannels\empty}%
+ \doifdefined{\??cs r}
+ {\addtocommalist{r,g,b}\usedcolorchannels}%
+ \doifdefined{\??cs s}
+ {\ExpandBothAfter\doifnotinset{k}\usedcolorchannels
+ {\addtocommalist{s}\usedcolorchannels}}%
+ \savecurrentvalue\usedcolorchannels\usedcolorchannels
+ \egroup}
+
+\prependtoks
+ \registerusedspotcolors
+ \registerusedcolorchannels
+\to \everylastshipout
+
+\def\registerusedspotcolor#1%
+ {\global\@EA\chardef\csname\??cs#1\endcsname\zerocount}
+
+%D On top of spotcolors, we define multitone colors. You'd better know
+%D what you're doing because invalid definitions will lead to invalid
+%D documents (i.e.\ resources).
+
+% \definecolor [darkblue] [c=.5,m=.5]
+% \definecolor [darkyellow] [y=.5]
+%
+% \definemultitonecolor [whatever] [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25] [a=1,t=.5]
+% \definemultitonecolor [another] [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25]
+
+\def\dodefinemultitonecolor[#1][#2][#3][#4]%
+ {\let\@@cl@@cl@@D\empty % n's
+ \let\@@cl@@cl@@P\empty % p's
+ \let\@@cl@@cl@@N\empty % name
+ \scratchcounter\zerocount
+ \processcommacommand[#2]\dododefinemultitonecolor
+ \bgroup
+ \lccode`\.=`\_%
+ \lccode`\,=`\_%
+ \lccode`\:=`\_%
+ \lccode`\;=`\_%
+ \lccode`\+=`\_%
+ \lccode`\-=`\_%
+ \lccode`\*=`\_%
+ \lccode`\/=`\_%
+% \lccode`\_=`\_%
+ % not needed, other attribute in driver:
+ %
+ % \@@resetcolorparameters
+ % \getparameters[#4]%
+ % \ifx\@@cl@@t\@@cl@@z\else
+ % \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@t_\@@cl@@a}%
+ % \fi
+ \lowercase\@EA{\@EA\xdef\@EA\@@cleancolor\@EA{\@@cl@@cl@@N}}%
+ \egroup
+ \setxvalue{\??cl\@@cleancolor\s!check}{\noexpand\docheckmultitonecolor{\@@cl@@cl@@D}}%
+ \expanded{\defineglobalcolor[\@@cleancolor][#3,#4]}%
+ \expanded{\definespotcolor[#1][\@@cleancolor][#4,f=\the\scratchcounter,p={\@@cl@@cl@@P},d={\@@cl@@cl@@D}]}}
+
+\def\docheckmultitonecolor#1%
+ {\flushatshipout
+ {\let\checkmultitonecolor\gobbleoneargument
+ \def\docommand##1{\hbox{\definecolor[\s!dummy-100][##1][p=1]\color[\s!dummy-100]}}%
+ \processcommalist[#1]\docommand}}
+
+\def\checkmultitonecolor#1%
+ {\csname\??cl#1\s!check\endcsname\letgvalue{\??cl#1\s!check}\relax}
+
+\def\dodefinespotcolor[#1][#2][#3]% todo: always global (REDEFINED)
+ {\doifnot{#1}{#2}
+ {\@@resetcolorparameters
+ \ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
+ \edef\@@cl@@n{#2}%
+ \getparameters[\??cl @@][#3]%
+ \doifnothing \@@cl@@p{\let\@@cl@@p\!!plusone}%
+ \doifsomething\@@cl@@e{\doregisterspotcolorname{#2}\@@cl@@e}%
+ \doglobal\addtocommalist{#2}\allspotcolors
+ \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue
+ \setgvalue{#1}{\switchtocolor[#1]}}}% was \setvalue
+
+\def\dododefinemultitonecolor#1%
+ {\advance\scratchcounter\plusone
+ \splitstring#1\at=\to\!!stringa\and\!!stringb
+ \ifx\@@cl@@cl@@D\empty
+ \let\@@cl@@cl@@D\!!stringa
+ \let\@@cl@@cl@@P\!!stringb
+ \normalizecolor\!!stringb
+ \edef\@@cl@@cl@@N{\!!stringa_\!!stringb}%
+ \else
+ \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\!!stringa}%
+ \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\!!stringb}%
+ \normalizecolor\!!stringb
+ \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\!!stringa_\!!stringb}%
+ \fi}
+
+% \def\dododefinemultitonecolor#1% a/b safe
+% {\advance\scratchcounter\plusone
+% \splitstring#1\at=\to\@@cl@@one\and\@@cl@@two
+% \ifx\@@cl@@cl@@D\empty
+% \let\@@cl@@cl@@D\@@cl@@one
+% \let\@@cl@@cl@@P\@@cl@@two
+% \normalizecolor\@@cl@@two
+% \edef\@@cl@@cl@@N{\@@cl@@one_\@@cl@@two}%
+% \else
+% \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\@@cl@@one}%
+% \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\@@cl@@two}%
+% \normalizecolor\@@cl@@two
+% \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@one_\@@cl@@two}%
+% \fi}
+
+%D The names of colors are stored in a comma separated list
+%D only for the purpose of showing them with \type {\showcolor}.
+%D
+%D \startbuffer
+%D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+%D
+%D This color shows up as \color [SomeKindOfRed] {some kind
+%D of red}.
+%D
+%D \starttyping
+%D \setupcolors[state=start]
+%D
+%D \definecolor[mygreen][green]
+%D \definecolor[green][g=.5]
+%D
+%D \startcolor[mygreen]test\stopcolor
+%D
+%D \setupcolors[expansion=no]
+%D
+%D \definecolor[mygreen][green]
+%D \definecolor[green][g=.5]
+%D
+%D \startcolor[mygreen]test\stopcolor
+%D \stoptyping
+
+%D \macros
+%D {startcolormode,stopcolormode,permitcolormode}
+%D
+%D We use \type{\stopcolormode} to reset the color in
+%D whatever color space and do so by calling the corresponding
+%D special. Both commands can be used for fast color
+%D switching, like in colored verbatim,
+
+\newif\ifpermitcolormode \permitcolormodetrue
+
+\def\dowithcolor#1#2% #1=\action #2=color
+ {\ifincolor\ifpermitcolormode
+ \ifcsname\??cr\currentpalet#2\endcsname
+ \handlecolorwith#1\csname\??cr\currentpalet#2\endcsname\od
+ \else\ifcsname\??cr#2\endcsname
+ \handlecolorwith#1\csname\??cr#2\endcsname\od
+ \fi\fi
+ \fi\fi}
+
+\def\startcolormode % includes \ifincolor\ifpermitcolormode
+ {%\dostoptransparency % needed for: {test \trans test \notrans test}
+ \conditionalstoptransparency
+ \dowithcolor\execcolorRCSP}
+
+\def\stopcolormode
+ {\ifincolor\ifpermitcolormode
+ \supportedstoptransparency
+ \dostopcolormode
+ \fi\fi}
+
+\def\restorecolormode
+ {\ifincolor\ifpermitcolormode
+ \supportedstoptransparency
+ \dostopcolormode
+ \ifx\maintextcolor\empty \else
+ \startcolormode\maintextcolor
+ \fi
+ \fi\fi}
+
+%D Color modes are entered using the next set of commands.
+%D The \type{\stop} alternatives are implemented in a way
+%D that permits non||grouped use.
+%D
+%D The, for this module redundant, check if we are in color
+%D mode is needed when we use these macros in other modules.
+
+\def\execcolorRCSP#1:%
+ {\csname execcolor#1\endcsname}
+
+\def\execcolorR
+ {\iffilterspotcolor
+ \@EA\noexeccolorR
+ \else
+ \@EA\doexeccolorR
+ \fi}
+
+\def\execcolorC
+ {\iffilterspotcolor
+ \@EA\noexeccolorC
+ \else
+ \@EA\doexeccolorC
+ \fi}
+
+\def\execcolorS
+ {\iffilterspotcolor
+ \@EA\noexeccolorS
+ \else
+ \@EA\doexeccolorS
+ \fi}
+
+\def\execcolorP
+ {\iffilterspotcolor
+ \@EA\doexeccolorPP
+ \else\ifcase\currentcolorchannel
+ \@EAEAEA\doexeccolorP
+ \else
+ \@EAEAEA\noexeccolorP
+ \fi\fi}
+
+\def\doexeccolorR#1:#2:#3:%
+ {\edef\@@cl@@r{#1}\edef\@@cl@@g{#2}\edef\@@cl@@b{#3}%
+ \ifpreferGRAY\ifx\@@cl@@r\@@cr@@g\ifx\@@cl@@r\@@cl@@b
+ \GRAYpreferedtrue
+ \fi\fi\fi
+ \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi
+ \ifGRAYprefered
+ \registercolorchannel\c!s
+ \let\@@cl@@s\@@cl@@r
+ \normalizeGRAY
+ \doexeccolorgray
+ \else\ifRGBsupported
+ \registercolorchannel\c!r
+ \normalizeRGB
+ \doexeccolorrgb
+ \else\ifCMYKsupported
+ \registercolorchannel\c!c
+ \convertRGBtoCMYK\@@cl@@r\@@cl@@g\@@cl@@b
+ \normalizeCMYK
+ \doexeccolorcmyk
+ \else
+ \registercolorchannel\c!s
+ \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b
+ \normalizeGRAY
+ \doexeccolorgray
+ \fi\fi\fi
+ \exectransparency}
+
+\def\doexeccolorC#1:#2:#3:#4:%
+ {\edef\@@cl@@c{#1}\edef\@@cl@@m{#2}\edef\@@cl@@y{#3}\edef\@@cl@@k{#4}%
+ \ifpreferGRAY\ifx\@@cl@@k\@@cl@@z\ifx\@@cl@@c\@@cr@@m\ifx\@@cl@@c\@@cl@@y
+ \GRAYpreferedtrue
+ \fi\fi\fi\fi
+ \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi
+ \ifGRAYprefered
+ \registercolorchannel\c!s
+ \let\@@cl@@s\@@cl@@c
+ \normalizeGRAY
+ \doexeccolorgray
+ \else\ifCMYKsupported
+ \registercolorchannel\c!c
+ \ifreduceCMYK
+ \convertCMYKtoCMY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
+ \fi
+ \normalizeCMYK
+ \doexeccolorcmyk
+ \else\ifRGBsupported
+ \registercolorchannel\c!r
+ \convertCMYKtoRGB\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
+ \normalizeRGB
+ \doexeccolorrgb
+ \else
+ \registercolorchannel\c!s
+ \convertCMYKtoGRAY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
+ \normalizeGRAY
+ \doexeccolorgray
+ \fi\fi\fi
+ \exectransparency}
+
+\def\doexeccolorS#1:%
+ {\edef\@@cl@@s{#1}%
+ \registercolorchannel\c!s
+ \normalizeGRAY
+ \doexeccolorgray
+ \exectransparency}
+
+% \def\doexeccolorP#1:#2:%
+% {\edef\@@cl@@n{#1}%
+% \edef\@@cl@@p{#2}%
+% \registerusedspotcolor\@@cl@@n
+% \ifSPOTsupported
+% \dowithcolor\registerspotcolor\@@cl@@n
+% \dostartspotcolormode\@@cl@@n\@@cl@@p
+% \else
+% \doingspotcolortrue
+% \let\spotcolorfactor\@@cl@@p
+% \factorizecolortrue % using counter and array
+% \dowithcolor\execcolorRCSP\@@cl@@n
+% \factorizecolorfalse
+% \let\spotcolorfactor\@@cl@@o
+% \doingspotcolorfalse
+% \fi
+% \exectransparency}
+
+\def\doexeccolorP#1:#2:#3:#4:%
+ {\edef\@@cl@@n{#1}% name
+ \edef\@@cl@@f{#2}% fractions
+ \edef\@@cl@@d{#3}% definitions
+ \edef\@@cl@@p{#4}%
+ \ifx\@@cl@@d\empty
+ \let\@@cl@@d\@@cl@@n
+ \fi
+ \registerusedspotcolor\@@cl@@n
+ \ifSPOTsupported
+ \checkmultitonecolor\@@cl@@n
+ \dowithcolor\registerspotcolor\@@cl@@n
+ \dostartspotcolormode\@@cl@@n\@@cl@@p
+ \else
+ \doingspotcolortrue
+ \normalizespotcolor\@@cl@@p
+ \let\spotcolorfactor\@@cl@@p
+ \factorizecolortrue % using counter and array
+ \dowithcolor\execcolorRCSP\@@cl@@n
+ \factorizecolorfalse
+ \let\spotcolorfactor\@@cl@@o
+ \doingspotcolorfalse
+ \fi
+ \exectransparency}
+
+\def\doexeccolorPindex#1:#2:#3:#4:%
+ {\edef\@@cl@@n{#1}%
+ \edef\@@cl@@f{#2}%
+ \edef\@@cl@@d{#3}%
+ \edef\@@cl@@p{#4}%
+ \ifx\@@cl@@d\empty
+ \let\@@cl@@d\@@cl@@n
+ \fi
+ \ifSPOTsupported
+ \checkmultitonecolor\@@cl@@n
+ \dowithcolor\registerindexcolor\@@cl@@n
+ \fi
+ \noexectransparency}
+
+\def\doexeccolorPP#1:#2:%
+ {\edef\@@cl@@n{#1}%
+ \edef\@@cl@@p{#2}%
+ \registerusedspotcolor\@@cl@@n
+ \ifx\@@cl@@n\currentspotcolor
+ \normalizeSPOT
+ \dostartgraycolormode\@@cl@@p % was spotcolormode
+ \else
+ \dovidecolor\@@cl@@p\@@cl@@o
+ \fi
+ \exectransparency}
+
+\def\doexeccolorrgb
+ {\ifcase\currentcolorchannel
+ \dostartrgbcolormode\@@cl@@r\@@cl@@g\@@cl@@b
+ \or \or \or \or
+ \or \dostartgraycolormode\@@cl@@r
+ \or \dostartgraycolormode\@@cl@@g
+ \or \dostartgraycolormode\@@cl@@b
+ \fi}
+
+\def\doexeccolorcmyk
+ {\ifcase\currentcolorchannel
+ \dostartcmykcolormode\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
+ \or \negatecolorcomponent\@@cl@@c\dostartgraycolormode\@@cl@@c
+ \or \negatecolorcomponent\@@cl@@m\dostartgraycolormode\@@cl@@m
+ \or \negatecolorcomponent\@@cl@@y\dostartgraycolormode\@@cl@@y
+ \or \negatecolorcomponent\@@cl@@k\dostartgraycolormode\@@cl@@k
+ \fi}
+
+\def\doexeccolorgray
+ {\ifcase\currentcolorchannel
+ \dostartgraycolormode\@@cl@@s
+ \or \or \or
+ \or \dostartgraycolormode\@@cl@@s
+ \or \or \or
+ \or \dostartgraycolormode\@@cl@@s
+ \fi}
+
+%D When filtering colors, we need to either erase
+%D the background, or ignore the foreground.
+
+% \newif\ifhidesplitcolor \hidesplitcolortrue
+%
+% \def\noexeccolor#1\od
+% {\dostartgraycolormode\@@cl@@o}
+%
+% \let\noexeccolorS\noexeccolor
+% \let\noexeccolorP\noexeccolor
+
+%D Well, here comes some real trickery. When we have the 100\%
+%D spot color or black color, we don't want to erase the
+%D background. So, instead we hide the content by giving it
+%D zero transparency.
+
+% todo : #1#2#3 met #2 > of < and #3 een threshold
+
+\def\dohidecolor#1#2%
+ {\ifhidesplitcolor
+ \ifx#1#2%
+ \dostartgraycolormode\@@cl@@o
+ \else
+ \doregisternonecolor
+ \dostartnonecolormode
+ \fi
+ \else
+ \dostartgraycolormode\@@cl@@o
+ \fi}
+
+\def\dovidecolor#1#2%
+ {\ifhidesplitcolor
+ \ifx#1#2%
+ \doregisternonecolor
+ \dostartnonecolormode
+ \else
+ \dostartgraycolormode\@@cl@@o
+ \fi
+ \else
+ \dostartgraycolormode\@@cl@@o
+ \fi}
+
+% \def\fullytransparentcolor % fails on floats
+% {\dostartgraycolormode\@@cl@@o % better than z
+% %\global\@EA\chardef\csname\@@currenttransparent\endcsname\plusone
+% %\global\intransparenttrue
+% \dostarttransparency10}
+
+\def\noexeccolorR#1:#2:#3:#4\od
+ {\edef\@@cl@@r{#1}\edef\@@cl@@g{#2}\edef\@@cl@@b{#3}%
+ \dohidecolor\@@cl@@s\@@cl@@o}
+
+\def\noexeccolorC#1:#2:#3:#4:#5\od
+ {\edef\@@cl@@c{#1}\edef\@@cl@@m{#2}\edef\@@cl@@y{#3}\edef\@@cl@@k{#4}%
+ \dohidecolor\@@cl@@s\@@cl@@o}
+
+\def\noexeccolorS#1:#2\od
+ {\edef\@@cl@@s{#1}%
+ \dohidecolor\@@cl@@s\@@cl@@o}
+
+\def\noexeccolorP#1:#2:#3:#4:#5\od
+ {\edef\@@cl@@p{#4}%
+ \dohidecolor\@@cl@@p\@@cl@@z}
+
+%D For the sake of postprocessing (i.e.\ color separation)
+%D we can normalize colors, which comes down to giving equal
+%D values an equal accuracy and format. This feature is
+%D turned off by default due to a speed penalty. This macro
+%D also handles spot color percentages.
+
+\newif\iffactorizecolor
+\newif\ifnormalizecolor
+
+\def\spotcolorfactor{1}
+
+% \def\normalizecolor#1%
+% {\colordimen#1\thousandpoint
+% \colordimen\spotcolorfactor\colordimen
+% \colorcount\colordimen
+% \advance\colorcount \medcard
+% \divide\colorcount \maxcard
+% \edef#1{\realcolorvalue\colorcount}}
+
+\def\normalizecolor#1%
+ {\colorcount\numexpr(\dimexpr\spotcolorfactor\dimexpr#1\thousandpoint\relax\relax+\medcard)/\maxcard\relax
+ \edef#1{\realcolorvalue\colorcount}}
+
+% \def\normalizespotcolor#1%
+% {\colordimen-#1\thousandpoint
+% \advance\colordimen\thousandpoint
+% \colorcount\colordimen
+% \advance\colorcount \medcard
+% \divide\colorcount \maxcard
+% \edef#1{\realcolorvalue\colorcount}}
+
+\def\normalizespotcolor#1%
+ {\colorcount\numexpr(\dimexpr\thousandpoint-#1\thousandpoint\relax+\medcard)/\maxcard\relax
+ \edef#1{\realcolorvalue\colorcount}}
+
+\def\donormalizeRGB
+ {\normalizecolor\@@cl@@r
+ \normalizecolor\@@cl@@g
+ \normalizecolor\@@cl@@b}
+
+\def\normalizeRGB
+ {\ifnormalizecolor
+ \donormalizeRGB
+ \else\iffactorizecolor
+ \donormalizeRGB
+ \fi\fi}
+
+\def\donormalizeCMYK
+ {\normalizecolor\@@cl@@c
+ \normalizecolor\@@cl@@m
+ \normalizecolor\@@cl@@y
+ \normalizecolor\@@cl@@k}
+
+\def\normalizeCMYK
+ {\ifnormalizecolor
+ \donormalizeCMYK
+ \else\iffactorizecolor
+ \donormalizeCMYK
+ \fi\fi}
+
+\def\donormalizeGRAY
+ {\normalizecolor\@@cl@@s}
+
+\def\normalizeGRAY
+ {\ifnormalizecolor
+ \donormalizeGRAY
+ \else\iffactorizecolor
+ \donormalizeGRAY
+ \fi\fi}
+
+\def\normalizeSPOT
+ {\normalizespotcolor\@@cl@@p}
+
+%D We need to register spot colors (i.e.\ resources need to
+%D be created.
+
+\def\registerspotcolor#1:%
+ {\ifcsname\??cl:\c!p:\@@cl@@n\endcsname
+ \@EA\dontregisterspotcolor
+ \else
+ \letgvalue{\??cl:\c!p:\@@cl@@n}\empty
+ %\@EA\@EA\csname registerspotcolor#1\endcsname
+ \csname registerspotcolor#1\@EA\endcsname
+ \fi}
+
+% todo: convert to rgb if needed, will will do this in mkiv
+
+\def\dontregisterspotcolor #1\od{}
+\def\registerspotcolorR #1:#2:#3:#4\od{\doregisterrgbspotcolor \@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}}
+\def\registerspotcolorC#1:#2:#3:#4:#5\od{\doregistercmykspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}{#4}}
+\def\registerspotcolorS #1:#2\od{\doregistergrayspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}}
+\def\registerspotcolorP #1:#2:#3\od{\doregistergrayspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#2}}
+
+%D Experimental feature:
+
+% \definecolor [darkblue] [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
+% \definecolor [darkyellow] [c=0,m=.28,y=1,k=.06] % pantone pms 124 uncoated m
+%
+% \definecolor [darkblue-50] [darkblue] [p=.5]
+% \definecolor [darkyellow-50] [darkyellow] [p=.5]
+% \definecolor [darkblue-80] [darkblue] [p=.8]
+% \definecolor [darkyellow-80] [darkyellow] [p=.8]
+%
+% \definecolor [darkblue,darkyellow] [r=.8]
+% \definecolor [darkdull-5030] [darkblue,darkyellow] [p={.5,.3}]
+%
+% \setupcolors[state=start]
+%
+% \blackrule[width=4cm,height=3cm,color=darkblue-50]
+% \blackrule[width=4cm,height=3cm,color=darkblue-80]
+% \blackrule[width=4cm,height=3cm,color=darkyellow-50]
+% \blackrule[width=4cm,height=3cm,color=darkyellow-80]
+% \blackrule[width=4cm,height=3cm,color=darkdull-5030]
+
+%D Experimental too (special purpose code).
+
+\def\registerindexcolor#1:%
+ {\ifcsname\??cl:i:\@@cl@@n\endcsname
+ \@EA\dontregisterindexcolor
+ \else
+ \letgvalue{\??cl:i:\@@cl@@n}\empty % signal
+ \showmessage\m!colors{12}\@@cl@@n
+ \@EA\@EA\csname registerindexcolor#1\endcsname
+ \fi}
+
+\let\dontregisterindexcolor\dontregisterspotcolor
+
+\def\registerindexcolorR #1:#2:#3:#4\od{\doregisterrgbindexcolor \@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}}
+\def\registerindexcolorC#1:#2:#3:#4:#5\od{\doregistercmykindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}{#4}}
+\def\registerindexcolorS #1:#2\od{\doregistergrayindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}}
+\def\registerindexcolorP #1:#2:#3\od{\doregistergrayindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#2}}
+
+\def\predefinecolor[#1]%
+ {\bgroup
+ \flushatshipout{\hbox{\localcolortrue\color[#1]{}}}% real ones
+ \egroup}
+
+\def\predefineindexcolor[#1]%
+ {\bgroup
+ \flushatshipout{\hbox{\localcolortrue\color[#1]{}}}% real ones
+ \let\doexeccolorP\doexeccolorPindex
+ \flushatshipout{\hbox{\localcolortrue\color[#1]{}}}% index one
+ \egroup}
+
+% \def\checkpredefinedcolor[#1]%
+% {\ifcase\internalspotcolorsize{#1}\relax
+% \@EA\predefinecolor\or\@EA\predefinecolor\else\@EA\predefineindexcolor
+% \fi[#1]}
+
+\let\checkpredefinedcolor\predefineindexcolor % we need an index in order to negate bitmaps
+
+%D Transparency is handled similar for all three color modes. We
+%D can turn transparency off with the following switch:
+
+\newif\iftransparencysupported \transparencysupportedtrue % only mkii
+
+\def\exectransparency
+ {\iftransparencysupported
+ \expandafter\doexectransparency
+ \else
+ \expandafter\noexectransparency
+ \fi}
+
+\def\doexectransparency#1:#2\od
+ {\ifcase#1\space
+ \global\intransparentfalse
+ \else
+ \global\intransparentfalse
+ %\dostarttransparency{#1}{#2}%
+ \supportedstarttransparency{#1}{#2}%
+ \global\intransparenttrue
+ \fi}
+
+\def\noexectransparency#1\od
+ {}
+
+%D Experimental: minimize transparency resets.
+
+\newif\ifintransparent
+\newif\ifoptimizetransparency \optimizetransparencytrue % under test
+
+\let\supportedstoptransparency\relax
+
+\def\conditionalstoptransparency
+ {\ifoptimizetransparency
+ \ifintransparent
+ \global\intransparentfalse
+ \supportedstoptransparency
+ \fi
+ \else
+ \supportedstoptransparency
+ \fi}
+
+\def\supportedstarttransparency
+ {\iftransparencysupported
+ \globallet\supportedstoptransparency\dostoptransparency
+ \expandafter\dostarttransparency
+ \else
+ \expandafter\gobbletwoarguments
+ \fi}
+
+%D We now use the \type {\@@cl@@A} hook to implement
+%D symbolic names. These are converted into numbers
+%D at definition time (which saves runtime).
+
+\def\dodefinetransparency[#1][#2]%
+ {\@EA\chardef\csname\??cl-#1\endcsname#2\relax}
+
+\def\transparencynumber#1%
+ {\number\executeifdefined{\??cl-#1}{#1}}
+
+%D Now we hook 'm into the patterns:
+
+\def\@@cl@@A{\transparencynumber\@@cl@@a}
+
+%D The next macro can be used to return to the (normal)
+%D page color. This macro is used in the same way as
+%D \type {\color}.
+
+\def\startregistercolor[#1]%
+ {\permitcolormodefalse\startcolor[#1]\permitcolormodetrue}
+
+\def\stopregistercolor
+ {\permitcolormodefalse\stopcolor\permitcolormodetrue}
+
+\def\starttextcolor[#1]%
+ {\doifsomething{#1}
+ {\bgroup
+ \def\stoptextcolor % also goes ok with \page after
+ {\let\maintextcolor\empty % this one because the top of
+ \stopregistercolor % page sets the color right (side
+ \egroup}% % effect)
+ \def\starttextcolor[##1]%
+ {\bgroup
+ % \@@themaintextcolor==##1 is catched in \definecolor
+ \definecolor[\@@themaintextcolor][##1]%
+ \let\stoptextcolor\egroup}%
+ \startregistercolor[\@@themaintextcolor]%
+ \definecolor[\@@themaintextcolor][#1]%
+ \let\maintextcolor\@@themaintextcolor}}
+
+\let\stoptextcolor\relax
+
+%D The following hook permits proper support at the text
+%D level. This definition actually belongs in another
+%D module. (May need a different \MKIV\ implementation.)
+
+% \ifx\initializemaintextcolor\undefined
+
+ \let\@@clprevcolor\empty
+
+ \def\initializemaintextcolor
+ {% saveguard for setting text color to empty after
+ % it has been set
+ \doifnothing\@@cltextcolor
+ {\ifx\@@clprevcolor\empty\else
+ \let\@@cltextcolor\defaulttextcolor
+ \fi}%
+ \doifelsenothing\@@cltextcolor
+ {\let\maintextcolor\empty}
+ {\edef\@@clprevcolor{\@@cltextcolor}%
+ \let\maintextcolor\@@themaintextcolor
+ \doifelsenothing\@@cltextcolor % another saveguard
+ {\definecolor[\@@themaintextcolor][\defaulttextcolor]}%
+ {\definecolor[\@@themaintextcolor][\@@cltextcolor]}%
+ \doinitializemaintextcolor}}
+
+ \def\doinitializemaintextcolor
+ {\appendtoks\starttextcolor[\@@themaintextcolor]\to\everystarttext
+ \appendtoks\stoptextcolor \to\everystoptext
+ \let\doinitializemaintextcolor\relax}
+
+% \fi
+
+\def\localstarttextcolor
+ {\ifx\maintextcolor\empty
+ \startcolormode\defaulttextcolor
+ \else
+ \startcolormode\maintextcolor
+ \fi}
+
+% \def\localstoptextcolor
+% {\stopcolormode}
+%
+% better:
+
+\def\localstoptextcolor
+ {\restorecolormode}
+
+\def\restoretextcolor
+ {\ifx\maintextcolor\empty
+ \expandafter\dorestoretextcolor
+ \else
+ % obey main text color
+ \fi}
+
+\def\dorestoretextcolor
+ {\color[\defaulttextcolor]}
+
+%D We use some reserved names for local color components.
+%D Consistent use of these scratch variables saves us
+%D unneccessary hash entries.
+%D
+%D \starttyping
+%D \@@cl@@r \@@cl@@g \@@cl@@b
+%D \@@cl@@c \@@cl@@m \@@cl@@y \@@cl@@k
+%D \@@cl@@s
+%D \stoptyping
+%D
+%D We implement several conversion routines.
+%D
+%D \starttyping
+%D \convertRGBtoCMYK {r} {g} {b}
+%D \convertRGBtoGRAY {r} {g} {b}
+%D \convertCMYKtoRGB {c} {m} {y} {k}
+%D \convertCMYKtoGRAY {c} {m} {y} {k}
+%D \convertCMYKtoCMY {c} {m} {y} {k}
+%D \stoptyping
+%D
+%D The relation between \cap{Gray}, \cap{RGB} and \cap{CMYK}
+%D is:
+%D
+%D \placeformula[-]
+%D \startformula
+%D G = .30r + .59g + .11b
+%D = 1.0 - \min(1.0,\ .30c + .59m + .11y + k)
+%D \stopformula
+%D
+%D When converting from \cap{CMYK} to \cap{RGB} we use the
+%D formula:
+%D
+%D \placeformula[-]
+%D \startformula
+%D \eqalign
+%D {r &= 1.0 - \min(1.0,\ c+k) \cr
+%D g &= 1.0 - \min(1.0,\ m+k) \cr
+%D b &= 1.0 - \min(1.0,\ y+k)}
+%D \stopformula
+%D
+%D In the conversion routine the color components are calculated
+%D in three digits precision.
+
+\def\realcolorvalue#1%
+ {\ifnum#1>\zerocount % important, first encountered in --modu supp-mpe
+ \ifnum#1<\plusten 0.00\the#1\else
+ \ifnum#1<\plushundred 0.0\the#1\else
+ \ifnum#1<\plusthousand 0.\the#1\else
+ 1\fi\fi\fi
+ \else 0\fi}
+
+% \def\doconvertCMYKtoRGB#1\k#2\to#3%
+% {\ifdim#2\points>#1\points% >= problem, repaired 2/12/2002
+% \let#3\@@cl@@z % k >= color
+% \else
+% \colordimen\onepoint
+% \advance\colordimen -#1\points
+% \advance\colordimen -#2\points
+% \multiply\colordimen \plusthousand
+% \colorcount\colordimen
+% \advance\colorcount \medcard
+% \divide\colorcount \maxcard
+% \edef#3{\realcolorvalue\colorcount}%
+% \fi}
+
+\def\doconvertCMYKtoRGB#1\k#2\to#3%
+ {\colorcount\numexpr(\dimexpr\plusthousand\dimexpr\onepoint-#1\points-#2\points\relax\relax+\medcard)/\maxcard\relax
+ \ifnum\colorcount>\zeropoint
+ \edef#3{\realcolorvalue\colorcount}%
+ \else
+ \let#3\@@cl@@z
+ \fi}
+
+\def\convertCMYKtoRGB#1#2#3#4%
+ {\doconvertCMYKtoRGB#1\k#4\to\@@cl@@r
+ \doconvertCMYKtoRGB#2\k#4\to\@@cl@@g
+ \doconvertCMYKtoRGB#3\k#4\to\@@cl@@b}
+
+% \def\doconvertRGBtoCMYK#1\to#2%
+% {\colordimen#1\points
+% \multiply\colordimen \plusthousand
+% \colorcount\colordimen
+% \advance\colorcount \medcard
+% \divide\colorcount \maxcard
+% \colorcount-\colorcount
+% \advance\colorcount \plusthousand
+% \edef#2{\realcolorvalue\colorcount}}
+
+\def\doconvertRGBtoCMYK#1\to#2%
+ {\colorcount\numexpr\plusthousand-(\dimexpr\plusthousand\dimexpr#1\points\relax\relax+\medcard)/\maxcard\relax
+ \edef#2{\realcolorvalue\colorcount}}
+
+\def\convertRGBtoCMYK#1#2#3%
+ {\doconvertRGBtoCMYK#1\to\@@cl@@c
+ \doconvertRGBtoCMYK#2\to\@@cl@@m
+ \doconvertRGBtoCMYK#3\to\@@cl@@y
+ \let\@@cl@@k\@@cl@@z}
+
+%D The following switch is mainly meant for (hidden)
+%D documentation purposes.
+
+\def\nGRAYfactor{333.333}
+\def\rGRAYfactor{\ifweightGRAY300\else\nGRAYfactor\fi}
+\def\gGRAYfactor{\ifweightGRAY590\else\nGRAYfactor\fi}
+\def\bGRAYfactor{\ifweightGRAY110\else\nGRAYfactor\fi}
+
+% \def\convertRGBtoGRAY#1#2#3%
+% {\colordimen#1\points
+% \colordimen\rGRAYfactor\colordimen
+% \colorcount\colordimen
+% \colordimen#2\points
+% \colordimen\gGRAYfactor\colordimen
+% \advance\colorcount \colordimen
+% \colordimen#3\points
+% \colordimen\bGRAYfactor\colordimen
+% \advance\colorcount \colordimen
+% \advance\colorcount \medcard
+% \divide\colorcount \maxcard
+% \edef\@@cl@@s{\realcolorvalue\colorcount}}
+
+\def\convertRGBtoGRAY#1#2#3%
+ {\colorcount\numexpr
+ (\dimexpr\rGRAYfactor\dimexpr#1\points\relax\relax+
+ \dimexpr\gGRAYfactor\dimexpr#2\points\relax\relax+
+ \dimexpr\bGRAYfactor\dimexpr#3\points\relax\relax+
+ \medcard)/\maxcard
+ \relax
+ \edef\@@cl@@s{\realcolorvalue\colorcount}}
+
+\def\convertCMYKtoGRAY#1#2#3#4%
+ {\convertCMYKtoRGB{#1}{#2}{#3}{#4}%
+ \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b}
+
+% \def\doconvertCMYKtoCMY#1\k#2\to#3%
+% {\colordimen#1\points
+% \advance\colordimen #2\points\relax
+% \ifdim\colordimen>\onepoint
+% \colordimen\onepoint
+% %\else
+% % \colordimen\colordimen
+% \fi
+% \multiply\colordimen \plusthousand
+% \colorcount\colordimen
+% \advance\colorcount \medcard
+% \divide\colorcount \maxcard
+% \edef#3{\realcolorvalue\colorcount}}
+
+\def\doconvertCMYKtoCMY#1\k#2\to#3%
+ {\colorcount\numexpr(\dimexpr\plusthousand\dimexpr#1\points+#2\points\relax\relax+\medcard)/\maxcard\relax
+ \ifnum\colorcount>\plusthousand
+ \let#3\@@cl@@o
+ \else
+ \edef#3{\realcolorvalue\colorcount}%
+ \fi}
+
+\def\convertCMYKtoCMY#1#2#3#4%
+ {\doconvertCMYKtoCMY#1\k#4\to\@@cl@@c
+ \doconvertCMYKtoCMY#2\k#4\to\@@cl@@m
+ \doconvertCMYKtoCMY#3\k#4\to\@@cl@@y
+ \let\@@cl@@k\@@cl@@z}
+
+%D Before we present the color macros, we first define the
+%D setup command. This command takes care of setting up the
+%D booleans that control local and global behavior (more on
+%D that later) and conversion to other color spaces.
+
+\let\currentspotcolor \empty
+\let\previousspotcolor\empty
+
+%D The tests depend on the use of constants. If we use the \MKIV\
+%D method we can share more.
+
+\def\doifcolorelse#1%
+ {\ifcsname\??cr\ifcsname\??cr\currentpalet#1\endcsname\currentpalet\fi#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifcolor#1%
+ {\ifcsname\??cr\ifcsname\??cr\currentpalet#1\endcsname\currentpalet\fi#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D There are a couple of different color switching macros,
+%D the local ones can be used to speed up things (only in \MKII).
+
+\def\localstartcolor
+ {\ifincolor
+ \localcolortrue
+ \expandafter\doglobalstartcolor
+ \else
+ \expandafter\noglobalstartcolor
+ \fi}
+
+\def\localstopcolor
+ {\ifincolor
+ \doglobalstopcolor
+ \else
+ \noglobalstopcolor
+ \fi}
+
+\unexpanded\def\startcolor
+ {\ifincolor
+ \expandafter\doglobalstartcolor
+ \else
+ \expandafter\noglobalstartcolor
+ \fi}
+
+\unexpanded\def\stopcolor
+ {\ifincolor
+ \doglobalstopcolor
+ \else
+ \noglobalstopcolor
+ \fi}
+
+%D This macros call the global color switching ones. Starting
+%D a global, i.e. a possible page boundary crossing, color
+%D mode also sets a \type{\mark} in \TEX's internal list.
+
+\newcount\colorlevel
+
+\letvalue{\??cl0C}\empty % saved color
+\letvalue{\??cl0S}\empty % stop command
+
+%D We keep a positive color stack for foreground colors, and
+%D a negative one for backgrounds. Not that brilliant a
+%D solution, but it suits. The signs are swapped when the
+%D page ornaments are typeset.
+
+\let\@@colorplus \plusone
+\let\@@colorminus\minusone
+
+\def\@@currentcolorname {\??cl\the\colorlevel C}
+\def\@@currentcolorstop {\??cl\the\colorlevel S}
+%def\@@currenttransparent{\??cl\the\colorlevel T}
+
+\letvalue{\??cl*\s!black}\s!black
+
+\def\currentcolorname
+ {\csname
+ \ifcsname\@@currentcolorname\endcsname
+ \expandafter\ifx\csname\@@currentcolorname\endcsname\empty
+ \??cl*\s!black
+ \else
+ \@@currentcolorname
+ \fi
+ \else
+ \??cl*\s!black
+ \fi
+ \endcsname}
+
+\def\outercolorname
+ {\ifcsname\@@currentcolorname\endcsname
+ \expandafter\ifx\csname\@@currentcolorname\endcsname\empty
+ \s!black
+ \else
+ currentcolor%
+ \fi
+ \else
+ \s!black
+ \fi}
+
+% not the following, because we need a different tag in order to trick the stack
+%
+% \def\outercolorname{\executeifdefined\@@currentcolorname\s!black}
+%
+% \def\startcurrentcolor{\expanded{\startcolor[\s!black]\noexpand\startcolor[\outercolorname]}}
+% \def\stopcurrentcolor {\stopcolor\stopcolor}
+%
+% test case:
+%
+% \setupcolors[state=start,textcolor=red]
+% \starttext
+% red
+% \color[green]{green
+% \startMPcode
+% label(\sometxt{green\color[blue]{blue}green}, origin) withcolor red;
+% draw fullcircle scaled 1cm xscaled 2;
+% \stopMPcode
+% green}
+% red
+% \stoptext
+
+\def\dodoglobalstartcolor
+ {\global\@EA\let\@EA\@@currentcolor\csname\@@currentcolorname\endcsname
+ \global\advance\colorlevel \@@colorplus
+ \global\@EA\let\csname\@@currentcolorname\endcsname\@@askedcolor
+ %\debuggerinfo\m!colors
+ % {start \@@askedcolor\space at level \the\colorlevel}%
+ \ifx\@@askedcolor\empty
+ \global\@EA\let\csname\@@currentcolorname\endcsname\@@currentcolor
+ \global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor
+ \else\ifx\@@askedcolor\@@currentcolor
+ \global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor
+ \else
+ \doifcolorelse\@@askedcolor
+ {%\docolormark\@@askedcolor
+ \ifpermitcolormode\docolormark\@@askedcolor\fi
+ \global\@EA\let\csname\@@currentcolorstop\endcsname\dodoglobalstopcolor
+ \startcolormode\@@askedcolor}
+ {\global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor
+ \showmessage\m!colors3\@@askedcolor\empty}%
+ \fi\fi}
+
+\def\doglobalstartcolor[#1]%
+ {\edef\@@askedcolor{#1}%
+ \ifcase\colorlevel\relax
+ \ifx\@@askedcolor\empty
+ \global\@EA\let\csname\@@currentcolorstop\endcsname\empty
+ \else
+ \dodoglobalstartcolor
+ \fi
+ \else
+ \dodoglobalstartcolor
+ \fi
+ \ignorespaces}
+
+\def\noglobalstartcolor[#1]%
+ {}
+
+\def\dodoglobalstopcolor
+ {\ifcase\colorlevel \else
+ \donoglobalstopcolor
+ \global\@EA\let\@EA\@@previouscolor\csname\@@currentcolorname\endcsname
+ \ifcase\colorlevel\relax
+ \ifpermitcolormode
+ \docolormark\empty
+ \conditionalstoptransparency
+ \dostopcolormode
+ \fi
+ \else % let's do a bit redundant testing here
+ \docolormark\@@previouscolor
+ \ifx\@@previouscolor\empty
+ \ifpermitcolormode
+ \conditionalstoptransparency
+ \dostopcolormode
+ \fi
+ \else
+ \doifcolorelse\@@previouscolor
+ {\ifx\@@currentcolor\@@previouscolor\else
+ % alternatively we could let \startcolormode handle this
+ \ifpermitcolormode
+ \conditionalstoptransparency % really needed
+ % more safe but less efficient: \dostopcolormode
+ \fi
+ \startcolormode\@@previouscolor
+ \fi}
+ {\ifpermitcolormode
+ \conditionalstoptransparency
+ \dostopcolormode
+ \fi}%
+ \fi
+ \fi
+ \fi}
+
+\def\donoglobalstopcolor
+ {\ifcase\colorlevel \else
+ \global\@EA\let\@EA\@@currentcolor\csname\@@currentcolorname\endcsname
+ %\debuggerinfo{\m!colors}
+ % {stop \@@currentcolor\normalspace at level \the\colorlevel}%
+ \global\advance\colorlevel \@@colorminus
+ \fi}
+
+\def\doglobalstopcolor
+ {\csname\@@currentcolorstop\endcsname}
+
+\let\noglobalstopcolor\relax
+
+\let\faststartcolor\doglobalstartcolor
+\let\faststopcolor \doglobalstopcolor
+
+%D We don't use grouping and save each stop alternative. This
+%D permits be especially useful in for instance local color
+%D support in verbatim. Using \type{\bgroup}||\type{\egroup}
+%D pairs could interfere with calling commands
+
+%D This color mechanism takes care of nested colors, like in:
+%D
+%D \startbuffer
+%D \color[green]{groen \color[green]{groen \color[red]{rood}} groen}
+%D \color[green]{groen \color[]{groen \color[red]{rood}} groen}
+%D \color[green]{groen \color[red]{rood \color[red]{rood}} groen}
+%D \color[green]{groen \color[green]{groen \color[]{groen}} groen}
+%D \color[green]{groen \color[red]{rood} groen}
+%D \color[green]{groen \color[]{groen} groen}
+%D \color[]{zwart \color[red]{rood} zwart}
+%D \color[]{zwart}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D Crossing page boundaries is of course also handled.
+%D Undefined or empty color specifications are treated as
+%D efficient as possible.
+%D
+%D \startbuffer
+%D \startcolor[green]
+%D [green] \input tufte [green] \par
+%D \startcolor[]
+%D [green] \input knuth [green] \par
+%D \startcolor[red]
+%D [red] \input tufte [red] \par
+%D \startcolor[yellow]
+%D [yellow] \input knuth [yellow] \par
+%D \stopcolor
+%D [red] \input tufte [red] \par
+%D \stopcolor
+%D [green] \input knuth [green] \par
+%D \stopcolor
+%D [green] \input tufte [green] \par
+%D \stopcolor
+%D \stopbuffer
+%D
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+%D
+%D These quotes are typeset by saying:
+%D
+%D \typebuffer
+
+%D We already mentioned that colors interfere with building
+%D the pagebody. This means that when the page is composed,
+%D the colors temporary have to be reset. After the page is
+%D shipped out, we have to revive the current color.
+%D
+%D We use \type{\mark}s to keep track of colors across page
+%D boundaries. Unfortunately standard \TEX\ supports only one mark,
+%D and using this one for color support only would be a waste.
+%D We therefore use an adapted version of J.~Fox's multiple mark
+%D mechanism as (re|)|implemented in \module{supp-mrk}.
+
+\doifdefinedelse{rawnewmark}
+ {\rawnewmark\colormark}
+ {\let\colormark\gobbleoneargument}
+
+%D Using this mark mechanism with lots of colors has one
+%D major drawback: \TEX's memory tends to overflow when
+%D very colorful text is stored in a global box. Even worse is that
+%D the processing time grows considerably. We therefore support
+%D local as well as global color switching.
+%D
+%D Of the next macros, \type {\popcolor} is to be used after
+%D the actual \type {\shipout} and \type {\startcolorpage} and
+%D \type {\stopcolorpage} are called when entering and leaving
+%D the \type {\pagebody} builder. In case of emergencies
+%D \type {\pushcolor} can be used to undo the current color,
+%D for instance when insertions are appended to the page.
+%D
+%D Out of efficiency we only use marks when needed. The next
+%D macro tries to find out if indeed a mark should be set.
+%D This macro uses the boolean \type {\ifinpagebody}, which can
+%D be defined and set in the module that handles the pagebody.
+
+\def\docolormark#1%
+ {\iflocalcolor \else \ifinpagebody \else \ifinframed \else
+ \dodocolormark{#1}%
+ \fi \fi \fi}
+
+\let\lastcolormark=\empty
+
+\def\dodocolormark#1%
+ {\edef\newcolormark{#1}%
+ \ifx\newcolormark\lastcolormark\else
+ \global\let\lastcolormark\newcolormark
+ \@EA\rawsetmark\@EA\colormark\@EA{\lastcolormark}%
+ \fi}
+
+%D \macros
+%D {pushcolor, popcolor}
+%D
+%D Pushing the current state in the output routine simply comes
+%D to resetting the color to black, while popping restores the
+%D color state to that of before the break.
+
+\def\topofpagecolor{\rawgetbotmark\colormark} % see postponing
+
+\def\pushcolor
+ {\stopcolormode}
+
+\def\popcolor
+ {\doifsomething{\rawgetbotmark\colormark}
+ {%\debuggerinfo\m!colors{popping \getbotmark\colormark}%
+ \startcolormode{\rawgetbotmark\colormark}}}
+
+\def\popsplitcolor
+ {\getsplitmarks\colormark % hier wel
+ \doifsomething{\rawgetsplitbotmark\colormark}
+ {%\debuggerinfo\m!colors{split popping \getsplitbotmark\colormark}%
+ \startcolormode{\rawgetsplitbotmark\colormark}}}
+
+\appendtoks\pushcolor \to\everypushproperties
+\appendtoks\popcolor \to\everypopproperties
+\appendtoks\popsplitcolor\to\everypopsplitproperties
+
+% Private macro: only needed in test cases (like multiple
+% seperations in one file); no user command!
+
+\def\resynccolor
+ {\ifcase\pagetotal % \ifdim\pagetotal=\zeropoint
+ \popcolor
+ \else\ifx\@@currentcolor\empty
+ \ifx\maintextcolor\empty\else
+ \startcolormode\maintextcolor
+ \fi
+ \else
+ \startcolormode\@@currentcolor
+ \fi\fi}
+
+% weird stuff
+
+\def\pushpostponedpagecolor
+ {\edef\savedtopofpagecolor{\topofpagecolor}%
+ \doifsomething\savedtopofpagecolor\restorecolormode} % \stopcolormode
+
+\def\poppostponedpagecolor
+ {\doifsomething\savedtopofpagecolor\startcolormode\savedtopofpagecolor}
+
+%D \macros
+%D {startcolorpage, stopcolorpage}
+%D
+%D Local use can be forced with the next two macros. Nesting
+%D is still supported but colors are no longer marked.
+%D
+%D The next implementation makes (simple) color separation more
+%D easy. It also supports nested colors in page backgrounds
+%D and texts.
+
+\def\startcolorpage
+ {\bgroup
+ \let\@@colorplus \minusone
+ \let\@@colorminus\plusone
+ \let\docolormark\gobbleoneargument
+ \edef\savedcolorlevel{\the\colorlevel}%
+ \global\colorlevel\zerocount % before \localstartcolor of
+ \ifx\maintextcolor\empty % course, ugly bug removed
+ \localstartcolor[\defaulttextcolor]%
+ \else
+ \localstartcolor[\maintextcolor]%
+ \fi}
+
+\def\stopcolorpage
+ {\localstopcolor
+ \global\colorlevel\savedcolorlevel
+ \egroup}
+
+\appendtoks \startcolorpage\to\everystarttextproperties
+\prependtoks\stopcolorpage \to\everystoptextproperties
+
+%D We want color support to be similar to font support and
+%D therefore implement \type{\color} using grouping.
+%D
+%D When \type {\somecolor} is issued, we can savely assume
+%D grouping. Using \type {\groupedcommand} here (i.e.\ the
+%D definition of \type {\color}) is unsafe because in
+%D interferes with for instance switching attributes.
+
+\unexpanded\def\color[#1]%
+ {\groupedcommand{\startcolor[#1]}\stopcolor}
+
+%D This implementation enables use of defined colors like:
+%D
+%D \starttyping
+%D Look at the {\brightgreen bright} side of life and get
+%D yourself no \red{red} head!
+%D \stoptyping
+
+%D Also wrong, test in combinations: \type{...{}{\red test}}
+%D
+%D \def\switchtocolor[#1]%
+%D {\startcolor[#1]\aftergroup\stopcolor}
+
+\def\switchtocolor[#1]% grouping is realy needed, else migration
+ {\bgroup\startcolor[#1]\aftergroup\stopcolor\aftergroup\egroup}
+
+\unexpanded\def\color[#1]%
+ {\groupedcommand{\startcolor[#1]}\stopcolor}
+
+\unexpanded\def\graycolor[#1]% not \gray because this is a color
+ {\groupedcommand{\RGBsupportedfalse\CMYKsupportedfalse\SPOTsupportedfalse\startcolor[#1]}\stopcolor}
+
+\unexpanded\def\colored[#1]%
+ {\groupedcommand{\definecolor[@colored@][#1]\startcolor[@colored@]}\stopcolor}
+
+%D We can speed the following macros a bit up, but this
+%D hardly pays off; they are only used in the manual.
+
+\def\realcolorformat#1%
+ {\ifnum#1<\plusten 0.00\the#1\else
+ \ifnum#1<\plushundred 0.0\the#1\else
+ \ifnum#1<\plusthousand 0.\the#1\else
+ 1.000\fi\fi\fi}
+
+\def\dodoformatcolor#1%
+ {\colordimen#1\points\relax
+ \ifdim\colordimen>\onepoint
+ \colordimen\onepoint
+ \fi
+ \multiply\colordimen \plusthousand
+ \colorcount\colordimen
+ \advance\colorcount \medcard
+ \divide\colorcount \maxcard \relax
+ \realcolorformat\colorcount}
+
+\def\doformatcolorR#1:#2:#3:#4:#5\od
+ {\dodoformatcolor{#1}\colorformatseparator
+ \dodoformatcolor{#2}\colorformatseparator
+ \dodoformatcolor{#3}}
+
+\def\doformatcolorC#1:#2:#3:#4:#5:#6\od
+ {\dodoformatcolor{#1}\colorformatseparator
+ \dodoformatcolor{#2}\colorformatseparator
+ \dodoformatcolor{#3}\colorformatseparator
+ \dodoformatcolor{#4}}
+
+\def\doformatcolorS#1:#2:#3\od
+ {\dodoformatcolor{#1}}
+
+\def\doformatcolorP#1:#2:#3:#4:#5:#6\od
+ {#1\colorformatseparator
+ \dodoformatcolor{#2}\colorformatseparator
+ \dodoformatcolor{#3}\colorformatseparator
+ \dodoformatcolor{#4}\colorformatseparator}
+
+\def\doformatcolor#1:%
+ {\csname doformatcolor#1\endcsname}
+
+\def\colorvalue
+ {\dowithcolor\doformatcolor}
+
+\def\doformatgrayR#1:#2:#3:#4:#5\od
+ {\convertRGBtoGRAY{#1}{#2}{#3}%
+ \dodoformatcolor\@@cl@@s}
+
+\def\doformatgrayC#1:#2:#3:#4:#5:#6\od
+ {\convertCMYKtoGRAY{#1}{#2}{#3}{#4}%
+ \dodoformatcolor\@@cl@@s}
+
+\def\doformatgrayS#1:#2:#3\od
+ {\dodoformatcolor{#1}}
+
+% \def\doformatgrayP#1:#2:#3:#4:#5:#6\od
+% {\convertSPOTtoGRAY{#1}{#2}{#3}{#4}%
+% \dodoformatcolor\@@cl@@s}
+
+\def\doformatgrayP#1:#2:#3:#4:#5:#6\od
+ {todo}
+
+\def\doformatgray#1:%
+ {\csname doformatgray#1\endcsname}
+
+\def\grayvalue
+ {\dowithcolor\doformatgray}
+
+%D \macros
+%D {localstartraster,localstopraster,
+%D startraster,stopraster}
+%D
+%D The previous conversions are not linear and treat each color
+%D component according to human perception curves. Pure gray
+%D (we call them rasters) has equal color components. In
+%D \CONTEXT\ rasters are only used as backgrounds and these
+%D don't cross page boundaries in the way color does. Therefore
+%D we don't need stacks and marks. Just to be compatible with
+%D color support we offer both 'global' and 'local' commands.
+%D
+%D \starttyping
+%D \def\localstartraster[#1]%
+%D {\doifelsenothing{#1}
+%D {\dostartgraymode\@@rsscreen}
+%D {\dostartgraymode{#1}}}
+%D
+%D \def\localstopraster
+%D {\dostopgraymode}
+%D
+%D \let\startraster\localstartraster
+%D \let\stopraster \localstopraster
+%D \stoptyping
+%D
+%D The next alternative is slower, since it works on top of the
+%D color (stack) mechanism, but it does provide nesting.
+
+\def\dosetrastercolor#1%
+ {\edef\@@cl@@s{#1}%
+ \ifx\@@cl@@s\empty
+ \let\@@cl@@s\@@rsscreen
+ \fi
+ \let\@@cl@@t\@@cl@@z % else we get rogue
+ \let\@@cl@@a\@@cl@@z % transpancies
+ \setevalue{\??cr\??rs}{\colorSpattern}}
+
+% beware, don't add extra grouping, else color in tables
+% fails
+
+\def\localstartraster[#1]%
+ {\ifincolor\dosetrastercolor{#1}\localstartcolor[\??rs]\fi}
+
+\def\startraster[#1]%
+ {\ifincolor\dosetrastercolor{#1}\startcolor[\??rs]\fi}
+
+\def\localstopraster{\ifincolor\localstopcolor\fi}
+\def\stopraster {\ifincolor\stopcolor\fi}
+
+\def\raster[#1]{\groupedcommand{\startraster[#1]}{\stopraster}}
+
+%D Palets use an auxiliary macro:
+
+\def\dodefinepaletcolor#1#2#3%
+ {\doifassignmentelse{#3}
+ {% == \definepalet[test][xx={y=.4}]
+ \definecolor[\??pa#1:#2][#3]%
+ \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{\??cr#1:#2}{\csname\??cr\??pa#1:#2\endcsname}}
+ {% == \definepalet[test][xx=green]
+ \doifdefinedelse{\??cr#3}
+ {\iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{\??cr#1:#2}{\csname\??cr#3\endcsname}}
+ {\letvalue{\??cr#1:#2}\colorXpattern}}}
+
+%D \MP\ related conversions:
+
+\def\scaledMPcolor#1#2%
+ {\ifMPgraphics
+ \handlecolorwith\doMPcolor
+ \csname\??cr
+ \ifcsname\??cr\currentpalet#2\endcsname\currentpalet\fi
+ #2\endcsname
+ :::::::\end#1\end
+ \else
+ #2%
+ \fi}
+
+\def\MPcolor{\scaledMPcolor1}
+
+%D Before we had transparency available, the following
+%D conversion macro was available:
+%D
+%D \starttyping
+%D \def\doMPcolor#1:#2:#3:#4:#5:#6:#7:#8\end
+%D {\if #1R(#2,#3,#4)%
+%D \else\if#1C\ifMPcmykcolors cmyk(#2,#3,#4,#5)\else(1-#2-#5,1-#3-#5,1-#4-#5)\fi
+%D \else\if#1S(#2,#2,#2)%
+%D \else (0,0,0)%
+%D \fi\fi\fi}
+%D \stoptyping
+%D
+%D In order to be useful, this macro is to be fully
+%D expandabele.
+
+\def\doMPcolor#1:% #1 can be \relax ! ! ! i.e. an empty color
+ {\csname MPc\@EA\ifx\csname MPc\string#1\endcsname\relax B\else#1\fi\endcsname}
+
+\def\MPcR{\doMPrgb}
+\def\MPcC{\ifMPcmykcolors\@EA\doMPcmykY\else\@EA\doMPcmykN\fi}
+\def\MPcS{\doMPgray}
+\def\MPcP{\ifMPspotcolors\@EA\doMPspotY\else\@EA\doMPspotN\fi}
+\def\MPcB{\doMPblack}
+
+\def\transparentMP {transparent}
+\def\cmykMP {scaledcmyk}
+\def\cmykASrgbMP {scaledcmykasrgb} % not really needed any more
+\def\rgbMP {scaledrgb}
+\def\grayMP {scaledgray}
+\def\spotMP {spotcolor}
+
+\def\doMPtransparent#1#2:#3:#4\end
+ {\ifcase#2\space(#1)\else\transparentMP(#2,#3,(#1))\fi}
+
+\def\doMPgray#1:#2\end#3\end
+ {\doMPtransparent{\grayMP(#1,#3)}#2\end}
+
+\def\doMPrgb#1:#2:#3:#4\end#5\end
+ {\doMPtransparent{\rgbMP(#1,#2,#3,#5)}#4\end}
+
+\def\doMPcmykY#1:#2:#3:#4:#5\end#6\end
+ {\doMPtransparent{\cmykMP(#1,#2,#3,#4,#6)}#5\end}
+
+\def\doMPcmykN#1:#2:#3:#4:#5\end#6\end
+ {\doMPtransparent{\cmykASrgbMP(#1,#2,#3,#4,#6)}#5\end}
+
+\def\doMPspotY#1:#2:#3:#4:#5\end#6\end % best make #3 same as #1 when empty
+ {\doMPtransparent{multitonecolor("#1",#2,"#3","#4")}#5\end}
+
+\def\doMPspotN#1:#2:#3:#4:#5\end#6\end
+ {\scaledMPcolor{#4}{#1}}
+
+\def\doMPblack#1\end#2\end
+ {\unknownMPcolor}
+
+\def\unknownMPcolor
+ {(0,0,0)}
+
+\let\processMP\spotMP % for some time, will become obsolete, brrr
+
+%D \PDF\ related conversions:
+
+\def\PDFcolor #1{\handlecolorwith\doPDFcolor \csname\??cr#1\endcsname:::::::\end}
+\def\PDFcolorvalue#1{\handlecolorwith\doPDFcolorvalue\csname\??cr#1\endcsname:::::::\end}
+\def\FDFcolor #1{\handlecolorwith\doFDFcolor \csname\??cr#1\endcsname:::::::\end}
+
+\def\doPDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end
+ {\if #1R#2 #3 #4 rg%
+ \else\if#1C#2 #3 #4 #5 k%
+ \else\if#1S#2 g%
+ \else\if#1P#5 g%
+ \else 0 g%
+ \fi\fi\fi\fi}
+
+\def\doPDFcolorvalue#1:#2:#3:#4:#5:#6:#7:#8\end
+ {\if #1R#2 #3 #4%
+ \else\if#1C#2 #3 #4 #5%
+ \else\if#1S#2%
+ \else\if#1P#5%
+ \else 0%
+ \fi\fi\fi\fi}
+
+\def\doFDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end
+ {[\if #1R#2 #3 #4%
+ \else\if#1C#2 #3 #4 #5%
+ \else\if#1S#2%
+ \else\if#1P#5%
+ \else 0%
+ \fi\fi\fi\fi]}
+
+\def\internalspotcolorname#1{\handlecolorwith\dointernalspotcolorname\csname\??cr#1\endcsname:::::::\end}
+\def\internalspotcolorsize#1{\handlecolorwith\dointernalspotcolorsize\csname\??cr#1\endcsname:::::::\end}
+
+\def\dointernalspotcolorname#1:#2:#3:#4:#5:#6:#7:#8\end{\if#1P\ifcase0#3 #1\else#2\fi\else#1\fi}
+\def\dointernalspotcolorsize#1:#2:#3:#4:#5:#6:#7:#8\end{\if#1P\ifcase0#3 0\else#3\fi\else 0\fi}
+
+%D Slow but ok \unknown
+
+\def\colorcomponents#1% might be broken
+ {\startnointerference
+ \localcolortrue
+ \globallet\thecolorcomponents\empty
+ \def\doexeccolorR ##1:##2:##3:##4:##5\od{\gdef\thecolorcomponents{r=\twodigitrounding{##1} g=\twodigitrounding{##2} b=\twodigitrounding{##3}}}%
+ \def\doexeccolorC##1:##2:##3:##4:##5:##6\od{\gdef\thecolorcomponents{c=\twodigitrounding{##1} m=\twodigitrounding{##2} y=\twodigitrounding{##3} k=\twodigitrounding{##4}}}%
+ \def\doexeccolorS ##1:##2:##3\od{\gdef\thecolorcomponents{s=\twodigitrounding{##1}}}%
+ \def\doexeccolorP##1:##2:##3:##4:##5:##6\od{\gdef\thecolorcomponents{p=\twodigitrounding{##4} n=##1}}%
+ \let\doexeccolorPindex\doexeccolorP
+ \backgroundline[#1]{}%
+ \stopnointerference
+ \thecolorcomponents}
+
+\def\transparencycomponents#1%
+ {\startnointerference
+ \localcolortrue
+ \globallet\thetransparencycomponents\empty
+ \def\doexeccolorR ##1:##2:##3:##4:##5\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##4} t=\twodigitrounding{##5}}}%
+ \def\doexeccolorC##1:##2:##3:##4:##5:##6\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##5} t=\twodigitrounding{##6}}}%
+ \def\doexeccolorS ##1:##2:##3\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##2} t=\twodigitrounding{##3}}}%
+ \def\doexeccolorP##1:##2:##3:##4:##5:##6\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##5} t=\twodigitrounding{##6}}}%
+ \let\doexeccolorPindex\doexeccolorP
+ \backgroundline[#1]{}%
+ \stopnointerference
+ \thetransparencycomponents}
+
+%D \macros
+%D {everyshapebox}
+%D
+%D A terrible hack, needed because we cannot have marks in
+%D shape boxes.
+
+\appendtoks \localcolortrue \to \everyshapebox
+
+%D \macros
+%D {forcecolorhack}
+%D
+%D Awful \unknown
+
+\let\forcecolorhack\relax
+
+%D We default to the colors defined in \module{colo-rgb} and
+%D support both \cap{RGB} and \cap{CMYK} output. As you can
+%D see, color support is turned off by default. Reduction of
+%D gray colors to gray scales is turned on.
+
+\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]
+
+\setupcolors
+ [\c!state=\v!stop,
+ \c!conversion=\v!yes,
+ \c!reduction=\v!no,
+ \c!rgb=\v!yes,
+ \c!cmyk=\v!yes,
+ \c!spot=\v!yes,
+ \c!mp\c!cmyk=\@@clcmyk,
+ \c!mp\c!spot=\@@clspot,
+ \c!expansion=\v!no,
+ \c!textcolor=,
+ \c!split=\v!no,
+ \c!criterium=\v!all]
+
+\setupcolor
+ [\v!rgb]
+
+\protect \endinput
diff --git a/tex/context/base/colo-ini.mkiv b/tex/context/base/colo-ini.mkiv
new file mode 100644
index 000000000..1bceb5aa7
--- /dev/null
+++ b/tex/context/base/colo-ini.mkiv
@@ -0,0 +1,1091 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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 hav eto make sure that mkiv
+%D code works ok.
+
+\writestatus{loading}{ConTeXt Color Macros / Initialization}
+
+%D This module implements color. Since \MKII\ and \MKIV\ use a completely
+%D different approach, this module only implements a few generic mechanisms.
+
+\registerctxluafile{colo-ini}{1.000}
+\registerctxluafile{lpdf-col}{1.000}
+
+\unprotect
+
+%D We use a couple of local registers. That way we don't have
+%D to group when converting colors. By the way, this is not
+%D really faster. We can sqeeze half a second runtime for 50K
+%D switches on a 1G machine, but the macros will become rather
+%D ugly then. To mention one such improvement: no colon
+%D after the key character (.25 sec).
+
+\newcount\colorcount
+
+%D When typesetting for paper, we prefer using the \cap{CMYK}
+%D color space, but for on||screen viewing we prefer \cap{RGB}
+%D (the previous implementation supported only this scheme).
+%D Independant of such specifications, we support some automatic
+%D conversions:
+%D
+%D \startitemize[packed]
+%D \item convert all colors to \cap{RGB}
+%D \item convert all colors to \cap{CMYK}
+%D \item convert all colors to gray scales
+%D \stopitemize
+%D
+%D We also support optimization of colors to gray scales.
+%D
+%D \startitemize[continue]
+%D \item reduce gray colors to gray scales
+%D \item reduce \cap{CMY} components to \cap{K}
+%D \stopitemize
+%D
+%D These options are communicated by means of:
+
+\newif\ifRGBsupported
+\newif\ifCMYKsupported
+\newif\ifSPOTsupported
+\newif\ifpreferGRAY
+\newif\ifGRAYprefered
+\newif\ifconvertGRAY \convertGRAYtrue
+\newif\ifreduceCMYK
+\newif\ifconverttoGRAY
+\newif\ifweightGRAY \weightGRAYtrue
+
+\newif\ifconvertMPcolors
+\newif\ifreduceMPcolors
+\newif\ifforcegrayMPcolors
+
+%D The last boolean controls reduction of \cap{CMYK} to
+%D \cap{CMY} colors. When set to true, the black component
+%D is added to the other ones.
+%D
+%D Prefering gray is not the same as converting to gray.
+%D Conversion treats each color components in a different way,
+%D while prefering is just a reduction and thus a
+%D space||saving option.
+
+\newif\iffreezecolors \freezecolorsfalse
+\newif\ifincolor % true if colors enabled
+
+\let\colorlist \empty
+\let\currentspotcolor \empty
+\let\allspotcolors \empty
+\let\usedspotcolors \empty
+\let\currentpalet \empty
+
+%D \macros
+%D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor}
+%D
+%D \startbuffer
+%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 \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 \stopbuffer
+%D
+%D \getbuffer \typebuffer
+
+\unexpanded\def\definecolor {\dodoubleargument\dodefinecolor}
+\unexpanded\def\defineglobalcolor {\dodoubleargument\dodefineglobalcolor}
+\unexpanded\def\definenamedcolor {\dodoubleargument\dodefinenamedcolor}
+\unexpanded\def\definespotcolor {\dotripleargument\dodefinespotcolor}
+\unexpanded\def\definemultitonecolor{\doquadrupleempty\dodefinemultitonecolor}
+
+%D \macros
+%D {startcolor,stopcolor,
+%D faststartcolor,faststopcolor,
+%D startraster,stopraster,raster,
+%D color,graycolor}
+%D
+%D The local and global and raster commands are here just
+%D for compatibility with \MKII.
+%D
+%D \showsetup{startcolor}
+%D
+%D \macros
+%D {color,graycolor}
+%D
+%D This leaves the simple color command:
+%D
+%D \showsetup{color}
+%D \showsetup{graycolor}
+%D
+%D This leaves the simple color command:
+%D
+%D \showsetup{color}
+%D \showsetup{graycolor}
+
+ \def\switchtocolor [#1]{\getvalue{#1}}
+\unexpanded\def\color [#1]{\groupedcommand{\doactivatecolor{#1}}{}}
+\unexpanded\def\startcolor [#1]{\begingroup\doactivatecolor{#1}}
+\unexpanded\def\stopcolor {\endgroup}
+\unexpanded\def\graycolor [#1]{\groupedcommand{\dosetcolormodel{gray}\getvalue{#1}}{}}
+\unexpanded\def\colored [#1]{\groupedcommand{\definecolor[@colored@][#1]\doactivatecolor{@colored@}}{}}
+\unexpanded\def\fastcolored [#1]#2{\begingroup\dodefinefastcolor[@colored@][#1]\doactivatecolor{@colored@}#2\endgroup}
+ \def\predefinecolor [#1]{\flushatshipout{\hbox{\color[#1]{}}}}
+ \def\predefineindexcolor[#1]{\flushatshipout{\hbox{\color[#1]{}}}}
+ \unexpanded\def\startcolorpage {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}
+ \unexpanded\def\stopcolorpage {\stopcolor}
+ \unexpanded\def\startraster [#1]{\dosetrastercolor{#1}}
+ \unexpanded\def\stopraster {}
+ \def\raster [#1]{\groupedcommand{\dosetrastercolor{#1}}{}}
+ \def\faststartcolor [#1]{\doactivatecolor{#1}}
+ \def\faststopcolor {}
+\unexpanded\def\dosetcolorattribute#1#2{\ifcsname#1#2\endcsname\doactivatecolor{\csname#1#2\endcsname}\fi}
+
+\let\grey\graycolor
+
+%D Stacking:
+
+% \colormodelattribute \colorattribute \transparencyattribute
+
+\newcount\currentcolornesting
+
+\unexpanded\def\pushcolor[#1]%
+ {\global\advance\currentcolornesting\plusone
+ \expandafter\edef\csname\??cl:s:\number\currentcolornesting\endcsname
+ {\attribute\colormodelattribute \the\attribute\colormodelattribute
+ \attribute\colorattribute \the\attribute\colorattribute
+ \attribute\transparencyattribute\the\attribute\transparencyattribute
+ \space}% stack
+ \doactivatecolor{#1}}
+
+\unexpanded\def\popcolor
+ {\csname\??cl:s:\number\currentcolornesting\endcsname
+ \global\advance\currentcolornesting\minusone}
+
+%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 \f!colorprefix-identifier.tex
+%D \stoptyping
+%D
+%D where \type{\f!colorprefix} is \unprotect {\tttf \f!colorprefix}.
+%D Loading such a file is done by \protect
+%D
+%D \showsetup{setupcolor}
+%D
+%D Some default colors are specified in \type{colo-rgb.tex},
+%D which is loaded into the format by:
+%D
+%D \starttyping
+%D \setupcolor[rgb]
+%D \stoptyping
+
+\let\colorstyle\empty
+
+\unexpanded\def\setupcolor
+ {\dosingleargument\dosetupcolor}
+
+\def\dosetupcolor[#1]%
+ {\doifnot{#1}\colorstyle
+ {\def\colorstyle{#1}%
+ \processcommalist[#1]\dodosetupcolor}}
+
+\def\dodosetupcolor#1%
+ {\makeshortfilename[\truefilename{\f!colorprefix#1}]%
+ \startreadingfile
+ \readsysfile\shortfilename
+ {\showcolormessage\m!colors4\colorstyle}
+ {\showcolormessage\m!colors5\colorstyle}%
+ \stopreadingfile}
+
+\let\usecolors\setupcolor
+
+% check: \startcolormode
+
+%D \macros
+%D {definetransparency}
+%D
+%D This command numbers to names:
+
+\unexpanded\def\definetransparency
+ {\dodoubleargument\dodefinetransparency}
+
+\unexpanded\def\setupcolors
+ {\dosingleargument\dosetupcolors}
+
+\let\showcolormessage\gobblethreearguments
+
+\newtoks\everysetupcolors
+
+\def\dosetupcolors[#1]% some no longer make sense in MkIV
+ {\getparameters[\??cl][#1]%
+ \doifelse\@@clspot\v!yes
+ \SPOTsupportedtrue
+ \SPOTsupportedfalse
+ \doifelse\@@clreduction\v!yes
+ \reduceCMYKtrue
+ \reduceCMYKfalse
+ \doifelse\@@clexpansion\v!yes
+ \freezecolorstrue
+ \freezecolorsfalse
+ \doifelse\@@clfactor\v!no
+ \weightGRAYfalse
+ \weightGRAYtrue
+ \doifelse\@@clrgb\v!no
+ {\ifRGBsupported \showcolormessage\m!colors {9}\v!rgb \RGBsupportedfalse \fi}
+ {\ifRGBsupported \else\showcolormessage\m!colors{10}\v!rgb \RGBsupportedtrue \fi}%
+ \doifelse\@@clcmyk\v!no
+ {\ifCMYKsupported \showcolormessage\m!colors {9}\v!cmyk \CMYKsupportedfalse\fi}
+ {\ifCMYKsupported\else\showcolormessage\m!colors{10}\v!cmyk \CMYKsupportedtrue \fi}%
+ \doifelse\@@clmpcmyk\v!no
+ {\ifMPcmykcolors \showcolormessage\m!colors {9}{\v!mp\v!cmyk}\MPcmykcolorsfalse \fi}
+ {\ifMPcmykcolors \else\showcolormessage\m!colors{10}{\v!mp\v!cmyk}\MPcmykcolorstrue \fi}%
+ \doifelse\@@clmpspot\v!no
+ {\ifMPspotcolors \showcolormessage\m!colors {9}{\v!mp\v!spot}\MPspotcolorsfalse \fi}
+ {\ifMPspotcolors \else\showcolormessage\m!colors{10}{\v!mp\v!spot}\MPspotcolorstrue \fi}%
+ \preferGRAYfalse
+ \convertGRAYtrue
+ \processaction
+ [\@@clconversion]
+ [ \v!yes=>\preferGRAYtrue,
+ \v!no=>\convertGRAYfalse,
+ \v!never=>\convertGRAYfalse,
+ \v!always=>\preferGRAYtrue\RGBsupportedfalse\CMYKsupportedfalse]%
+ \ifRGBsupported
+ \converttoGRAYfalse
+ \forcegrayMPcolorsfalse
+ \else\ifCMYKsupported
+ \converttoGRAYfalse
+ \forcegrayMPcolorsfalse
+ \convertMPcolorstrue
+ \ifreduceCMYK
+ \reduceMPcolorstrue
+ \fi
+ \else
+ \ifconverttoGRAY\else\showcolormessage\m!colors{11}\empty\fi
+ \converttoGRAYtrue
+ \forcegrayMPcolorstrue
+ \convertMPcolorsfalse
+ \reduceMPcolorsfalse
+ \fi\fi
+ \doifelse\@@clstate\v!stop
+ {\incolorfalse\forcegrayMPcolorstrue}%
+ {\ifincolor\else\showcolormessage\m!colors1\colorstyle\fi\incolortrue\let\@@clstate\v!start}%
+ \dosetupcolormodel
+ \the\everysetupcolors}
+
+%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
+%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
+%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 \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
+%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
+%D palet components (not 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
+%D deal with pretty verbatim typesetting.
+
+\unexpanded\def\definepalet
+ {\dodoubleargument\dodefinepalet}
+
+\def\dodefinepalet[#1][#2]%
+ {\doifassignmentelse{#2}
+ {%\showcolormessage\m!colors6{#1}%
+ \letvalue{\??pa#1}\empty
+ \setevalue{\??pa\??pa#1}{#2}%
+ \def\dodododefinepalet[##1=##2]%
+ {\doifvaluesomething{\??pa#1}
+ {\setevalue{\??pa#1}{\csname\??pa#1\endcsname,}}%
+ \setevalue{\??pa#1}{\csname\??pa#1\endcsname##1}%
+ \dodefinepaletcolor{#1}{##1}{##2}}%
+ \def\dododefinepalet##1%
+ {\dodododefinepalet[##1]}%
+ \processcommalist[#2]\dododefinepalet}
+ {\doifdefined{\??pa#2}
+ {\expanded{\dodefinepalet[#1][\csname\??pa\??pa#2\endcsname]}}}}
+
+\let\paletsize\!!zerocount
+
+\def\getpaletsize[#1]%
+ {\getcommacommandsize[\csname\??pa\??pa#1\endcsname]%
+ \edef\paletsize{\number\commalistsize}}
+
+%D Instead of refering to colors, one can also directly specify
+%D 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.
+%D Setting the current palet is done by:
+%D
+%D \showsetup{setuppalet}
+
+\let\currentpalet\empty
+
+\unexpanded\def\setuppalet
+ {\dosingleempty\dosetuppalet}
+
+\def\dosetuppalet[#1]%
+ {\edef\currentpalet{#1}%
+ \ifx\currentpalet\empty
+ % seems to be a reset
+ \else\ifcsname\??pa\currentpalet\endcsname
+ \edef\currentpalet{#1:}%
+ \else
+ \showcolormessage\m!colors7\currentpalet
+ \let\currentpalet\empty
+ \fi\fi
+ \initializemaintextcolor}
+
+%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!colorprefix\s!run}
+
+%D \macros
+%D {showcolorcomponents}
+%D
+%D \starttyping
+%D \showcolorcomponents[color-1,color-2]
+%D \stoptyping
+
+\fetchruntimecommand \showcolorcomponents {\f!colorprefix\s!run}
+
+%D \macros
+%D {definecolorgroup}
+%D
+%D The naming of the colors in this palet suggests some
+%D ordening, which in turn is suported by color grouping.
+%D
+%D \starttyping
+%D \definecolorgroup
+%D [red]
+%D [1.00:0.90:0.90,
+%D 1.00:0.80:0.80,
+%D 1.00:0.70:0.70,
+%D 1.00:0.55:0.55,
+%D 1.00:0.40:0.40,
+%D 1.00:0.25:0.25,
+%D 1.00:0.15:0.15,
+%D 0.90:0.00:0.00]
+%D \stoptyping
+%D
+%D In such a color group colors are numbered from~$1$ to~$n$.
+%D
+%D \showsetup{definecolorgroup}
+%D
+%D This kind of specification is not only more compact than
+%D defining each color separate, it also loads faster and takes
+%D less bytes.
+
+\unexpanded\def\definecolorgroup
+ {\dotripleempty\dodefinecolorgroup}
+
+\def\dododefinecolorgroupgray [#1][#2:#3]{\definecolor [#1:\the\colorcount][s=#2]}
+\def\dododefinecolorgrouprgb [#1][#2:#3:#4:#5]{\definecolor [#1:\the\colorcount][r=#2,g=#3,b=#4]}
+\def\dododefinecolorgroupcmyk[#1][#2:#3:#4:#5:#6]{\definecolor [#1:\the\colorcount][c=#2,m=#3=,y=#4,k=#5]}
+\def\dododefinecolorgroupspot [#1][#2:#3:#4]{\definespotcolor[#1:\the\colorcount][#2][p=#3]}
+
+\def\dododefinecolorgroup#1#2%
+ {\advance\colorcount\plusone
+ \getvalue{dododefinecolorgroup\currentcolorspace}[#1][#2:0:0:0:0]}
+
+\def\dodefinecolorgroup[#1][#2][#3]% obsolete, just use palets
+ {\ifthirdargument
+ \doifelsenothing{#2}{\let\currentcolorspace\v!rgb}{\def\currentcolorspace{#2}}%
+ \colorcount\zerocount
+ \processcommalist[#3]{\dododefinecolorgroup{#1}}%
+ \else
+ \doifinstringelse{:}{#2}
+ {\definecolorgroup[#1][\v!rgb][#2]}
+ {\doloop
+ {\ifcsname\??cr#2:\recurselevel\endcsname
+ \setevalue{\??cr#1:\recurselevel}{\csname\??cr#2:\recurselevel\endcsname}%
+ \else
+ \exitloop
+ \fi}}%
+ \fi}
+
+%D \macros
+%D {showcolorgroup}
+%D
+%D We can show the group by:
+%D
+%D \startbuffer
+%D \showcolorgroup [blue] [horizontal,name,number,value]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or in color:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D which uses:
+%D
+%D \showsetup{showcolorgroup}
+
+\fetchruntimecommand \showcolorgroup {\f!colorprefix\s!run}
+
+%D There are ten predefined color groups, like
+%D \color[green]{\em groen}, \color[red]{\em rood},
+%D \color[blue]{\em blauw}, \color[cyan]{\em cyaan},
+%D \color[magenta]{\em magenta} and \color[yellow]{\em geel}.
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\hss
+%D \showcolorgroup [red] [vertical,name,number]\hss
+%D \showcolorgroup [green] [vertical,name]\hss
+%D \showcolorgroup [blue] [vertical,name]\hss
+%D \showcolorgroup [cyan] [vertical,name]\hss
+%D \showcolorgroup [magenta][vertical,name]\hss
+%D \showcolorgroup [yellow] [vertical,name]\hss}
+%D \stoplinecorrection
+%D
+%D These groups are used to define palets {\em alfa} upto {\em
+%D zeta}. As long as we don't use colors from the same row, we
+%D get ourselves distinctive palets. By activating such a palet
+%D one gains access to its members {\em top} to {\em charm} (of
+%D course one should use more suitable names than these).
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\showpalet [alfa] [vertical,name,number]\hss
+%D \showpalet [beta] [vertical,name]\hss
+%D \showpalet [gamma] [vertical,name]\hss
+%D \showpalet [delta] [vertical,name]\hss
+%D \showpalet [epsilon] [vertical,name]\hss
+%D \showpalet [zeta] [vertical,name]}
+%D \stoplinecorrection
+%D
+%D By using the keyword \type {value} the individual color
+%D components are shown too. When printed in color, these
+%D showcases show both the colors and the gray value.
+
+%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!colorprefix\s!run}
+
+%D \macros
+%D {comparecolorgroup}
+%D
+%D The similar command:
+%D
+%D \startbuffer
+%D \comparecolorgroup [blue]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows color groups:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D this commands are defined as:
+%D
+%D \showsetup{comparecolorgroup}
+
+\fetchruntimecommand \comparecolorgroup {\f!colorprefix\s!run}
+
+%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
+%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!colorprefix\s!run}
+
+%D It would make sense to put the following code in \type
+%D {colo-mps}, but it it rather low level.
+
+%D \macros
+%D {negatecolorcomponent,negatedcolorcomponent}
+%D
+%D These speak for themselves. See \type {colo-ext} for usage.
+
+\def\negatecolorcomponent#1% #1 = \macro
+ {\scratchdimen\onepoint\advance\scratchdimen-#1\onepoint
+ \ifdim\scratchdimen<\zeropoint\scratchdimen\zeropoint\fi
+ \edef#1{\withoutpt\the\scratchdimen}}
+
+\let\negatedcolorcomponent\firstofoneargument
+
+\def\negatedcolorcomponent#1%
+ {\ifdim\dimexpr\onepoint-#1\onepoint\relax<\zeropoint
+ \!!zerocount
+ \else
+ \expandafter\withoutpt\the\dimexpr\onepoint-#1\onepoint\relax
+ \fi}
+
+\def\negatecolorcomponent#1% #1 = \macro
+ {\edef#1{\negatedcolorcomponent{#1}}}
+
+%D \macros
+%D {ifMPgraphics, ifMPcmykcolors, MPcolor}
+%D
+%D A very special macro is \type{\MPcolor}. This one can be
+%D used to pass a \CONTEXT\ color to \METAPOST.
+%D
+%D \starttyping
+%D \MPcolor{my own red}
+%D \stoptyping
+%D
+%D This macro returns a \METAPOST\ triplet \type{(R,G,B)}.
+%D Unless \CMYK\ color support is turned on with \type
+%D {MPcmyk}, only \cap{RGB} colors and gray scales are
+%D supported.
+
+\newif\ifMPcmykcolors % \MPcmykcolorsfalse
+\newif\ifMPspotcolors % \MPspotcolorsfalse
+
+\ifx\MPcolor\undefined
+ \def\MPcolor#1{(0,0,0)}
+\fi
+
+%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
+%D Well, in case we want to do color separation and use CMYK
+%D colors only, this is dangerous since unwanted remapping may
+%D take place. Especially when we redefine already defined
+%D colors in another color space (e.g. darkgreen is
+%D predefined in RGB color space, so a redefinition in CMYK
+%D coordinates before RGB mode is disabled, would give
+%D unexpected results due to the already frozen color spec.)
+
+%D In \MKIV\ we don't support color separation as we might now assume
+%D that printing houses have the right programs to do it themselves.
+%D The \MKII\ color separator was implemented as part of a project
+%D that needed. If it's ever needed in \MKIV\ i'll do it in the
+%D backend.
+
+\let\doifseparatingcolorselse\secondoftwoarguments
+\let\doifcolorchannelelse \secondofthreearguments
+\let\resetcolorseparation \relax
+\let\colorchannelprefix \empty
+\let\colorchannelsuffix \empty
+
+%D We now define the low level macros:
+
+% todo: palets in definecolor
+% todo: {\red xx} vs \red{xx}
+
+% check: registerusedspotcolors
+% check: \currentcolorname
+% check: \outercolorname
+% check: \startcolormode
+
+% \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
+
+\ifx\currentcolormodel\undefined \newcount\currentcolormodel \fi
+
+% \def\setcolormodel#1%
+% {\showcolormessage\m!colors1{#1}%
+% \dosetcolormodel{#1}}
+
+\def\dosetcolormodel#1% no message
+ {\currentcolormodel\ctxlua{tex.print(colors.setmodel('#1',\ifweightGRAY true\else false\fi))}%
+ \attribute\colormodelattribute\currentcolormodel}
+
+\dosetcolormodel{all}
+
+
+\def\dosetupcolormodel
+ {\ifincolor
+ \ifRGBsupported
+ \ifCMYKsupported
+ \dosetcolormodel{all}%
+ \else
+ \dosetcolormodel{rgb}%
+ \fi
+ \else
+ \ifCMYKsupported
+ \dosetcolormodel{cmyk}%
+ \else
+ \ifconvertGRAY
+ \dosetcolormodel{gray}%
+ \else
+ \dosetcolormodel{none}%
+ \fi
+ \fi
+ \fi
+ \else
+ \ifconvertGRAY
+ \dosetcolormodel{gray}%
+ \else
+ \dosetcolormodel{none}%
+ \fi
+ \fi}
+
+\appendtoks
+ \dosetupcolormodel
+\to \everyjob
+
+% 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.
+
+% Since we couple definitions, we could stick to one test. Todo. Same for mpcolor.
+
+\letvalue{(cs:-}\empty
+\letvalue{(ts:-}\empty
+
+\def\doactivatecolor#1% : in currentpalet, maybe not, ugly
+ {\def\currentcolorname{#1}%
+ \ifcsname(cs:\currentpalet#1)\endcsname
+ \csname(cs:\currentpalet#1)\endcsname
+ \csname(ts:\currentpalet#1)\endcsname
+ \else\ifcsname(cs:#1)\endcsname
+ \csname(cs:#1)\endcsname
+ \csname(ts:#1)\endcsname
+ \fi\fi}
+
+\let\normaldoactivatecolor\doactivatecolor
+
+% if it becomes a bottleneck we can set up a more complex system with one shared
+% attribute for colorspace, color and transparency
+
+\def\doactivatecolor
+ {\ifproductionrun
+ \ctxlua{colors.enable() transparencies.enable()}% not that efficient but at least robust
+ \let\doactivatecolor\normaldoactivatecolor
+ \expandafter\doactivatecolor
+ \else
+ \expandafter\normaldoactivatecolor
+ \fi}
+
+\def\deactivatecolor
+ {\let\currentcolorname\s!black
+ \attribute\colorattribute\attributeunsetvalue
+ \attribute\transparencyattribute\attributeunsetvalue}
+
+\def\dodefinecolorcommand#1#2%
+ {\unexpanded#1{#2}{\doactivatecolor{#2}}}
+
+\let\colorlist\empty % not really used, only for colo-run
+\setfalse\collectcolorsinlist
+\def\collectcolorinlist#1{\doglobal\addtocommalist{#1}\colorlist}
+
+\def\doregistercolor#1#2{\ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}}
+
+\def\dodefinecolor[#1][#2]%
+ {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
+ \ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
+ \dodefinecolorcommand\setvalue{#1}}
+
+\def\dodefineglobalcolor[#1][#2]%
+ {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
+ \ctxlua{colors.defineprocesscolor("#1","#2",true,\iffreezecolors true\else false\fi)}%
+ \dodefinecolorcommand\setgvalue{#1}}
+
+\def\dodefinenamedcolor[#1][#2]%
+ {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
+ \ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
+ \dodefinecolorcommand\setvalue{#1}}
+
+\def\dodefinespotcolor[#1][#2][#3]%
+ {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
+ \ctxlua{colors.definespotcolor("#1","#2","#3",true)}%
+ \dodefinecolorcommand\setxvalue{#1}}
+
+\def\dodefinemultitonecolor[#1][#2][#3][#4]%
+ {\ctxlua{colors.definemultitonecolor("#1","#2","#3","#4",true)}%
+ \dodefinecolorcommand\setxvalue{#1}}
+
+\def\dodefinetransparency[#1][#2]%
+ {\ctxlua{colors.definetransparency("#1",#2)}}
+
+\def\dosetrastercolor#1% slow, we need a fast one
+ {\edef\@@rastervalue{#1}%
+ \ifx\@@rastervalue\empty
+ \let\@@rastervalue\@@rsscreen
+ \fi
+ \attribute\colorattribute\ctxlua{tex.sprint(colors.definesimplegray("_raster_",\@@rastervalue))}\relax}
+
+\def\dodefinefastcolor[#1][#2]% still not fast but ok
+ {\ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
+ \dodefinecolorcommand\setvalue{#1}}
+
+%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.
+
+\def\doifcolorelse#1%
+ {\ifcsname(ca:\currentpalet#1)\endcsname
+ \@EA\firstoftwoarguments
+ \else\ifcsname(ca:#1)\endcsname
+ \@EAEAEA\firstoftwoarguments
+ \else
+ \@EAEAEA\secondoftwoarguments
+ \fi\fi}
+
+\def\doifcolor#1%
+ {\ifcsname(ca:\currentpalet#1)\endcsname
+ \@EA\firstofoneargument
+ \else\ifcsname(ca:#1)\endcsname
+ \@EAEAEA\firstofoneargument
+ \else
+ \@EAEAEA\gobbleoneargument
+ \fi\fi}
+
+%D \macros
+%D {colored}
+%D
+%D A bit like \type {\definedfont}:
+
+\unexpanded\def\colored[#1]%
+ {\ctxlua{colors.defineprocesscolor("@colored@","#1",false,false)}%
+ \groupedcommand{\doactivatecolor{@colored@}}{}}
+
+%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
+%D We use these macros for implementing text colors
+%D (actually, the first application was in foreground
+%D 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
+
+% can be cleaned up
+
+\let\maintextcolor \empty
+\def\defaulttextcolor {black}
+\def\@@themaintextcolor{themaintextcolor}
+
+\appendtoks
+ \deactivatecolor
+ \ifx\maintextcolor\empty\else\doactivatecolor\maintextcolor\fi
+\to \everybeforeoutput
+
+\def\registermaintextcolor{\ctxlua{colors.main = \thecolorattribute\maintextcolor}}
+
+\unexpanded\def\starttextcolor[#1]%
+ {\doifsomething{#1}
+ {\definecolor[\@@themaintextcolor][#1]%
+ \let\maintextcolor\@@themaintextcolor
+ \doactivatecolor\maintextcolor
+ \registermaintextcolor}}
+
+\let\stoptextcolor\relax
+
+\def\initializemaintextcolor
+ {\doifelsenothing\@@cltextcolor
+ {\definecolor[\@@themaintextcolor][\defaulttextcolor]}
+ {\definecolor[\@@themaintextcolor][\@@cltextcolor]}%
+ \let\maintextcolor\@@themaintextcolor
+ \doactivatecolor\maintextcolor
+ \registermaintextcolor}
+
+\appendtoks \initializemaintextcolor \to \everyjob
+\appendtoks \initializemaintextcolor \to \everysetupcolors
+
+\def\dodefinepaletcolor#1#2#3%
+ {\doifassignmentelse{#3}% \definepalet[test][xx={y=.4}]
+ {\definecolor[\??pa#1:#2][#3]%
+ \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(cs:#1:#2)}{\csname(cs:\??pa#1:#2)\endcsname}%
+ \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(ca:#1:#2)}{\csname(ca:\??pa#1:#2)\endcsname}}
+ {\ifcsname(cs:#3)\endcsname % \definepalet[test][xx=green]
+ \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(cs:#1:#2)}{\csname(cs:#3)\endcsname}%
+ \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(ca:#1:#2)}{\csname(ca:#3)\endcsname}%
+ \else
+ % not entered when making format
+ \localundefine{(cs:#1:#2)}% \letvalue{(cs:#1:#2)}\undefined
+ \localundefine{(ca:#1:#2)}% \letvalue{(ca:#1:#2)}\undefined
+ \fi}}
+
+\setvalue{(cs:)}{} \setvalue{(ca:)}{0}
+\setvalue{(ts:)}{} \setvalue{(ta:)}{0}
+
+\def\doinheritca#1{\csname(ca:\ifcsname(ca:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ca:#1)\endcsname#1\fi\fi)\endcsname}
+\def\doinheritcs#1{\csname(cs:\ifcsname(cs:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(cs:#1)\endcsname#1\fi\fi)\endcsname}
+\def\doinheritta#1{\csname(ta:\ifcsname(ta:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ta:#1)\endcsname#1\fi\fi)\endcsname}
+\def\doinheritts#1{\csname(ts:\ifcsname(ts:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ts:#1)\endcsname#1\fi\fi)\endcsname}
+
+%D Low level defs:
+
+\def\colordefalc#1#2{\setevalue{(ca:#1)}{#2}\setvalue {(cs:#1)}{\attribute\colorattribute #2 }}
+\def\colordefagc#1#2{\setxvalue{(ca:#1)}{#2}\setvalue {(cs:#1)}{\attribute\colorattribute #2 }}
+\def\colordefalt#1#2{\setevalue{(ta:#1)}{#2}\setvalue {(ts:#1)}{\attribute\transparencyattribute#2 }}
+\def\colordefagt#1#2{\setxvalue{(ta:#1)}{#2}\setgvalue{(ts:#1)}{\attribute\transparencyattribute#2 }}
+
+\def\colordefflc#1#2{\setvalue {(ca:#1)}{\doinheritca{#2}}\setvalue {(cs:#1)}{\doinheritcs{#2}}}
+\def\colordeffgc#1#2{\setgvalue{(ca:#1)}{\doinheritca{#2}}\setvalue {(cs:#1)}{\doinheritcs{#2}}}
+\def\colordefflt#1#2{\setvalue {(ta:#1)}{\doinheritta{#2}}\setvalue {(ts:#1)}{\doinheritts{#2}}}
+\def\colordeffgt#1#2{\setgvalue{(ta:#1)}{\doinheritta{#2}}\setgvalue{(ts:#1)}{\doinheritts{#2}}}
+
+\def\colordefrlc #1{\localundefine {(ca:#1)}\localundefine {(cs:#1)}}
+\def\colordefrgc #1{\globalundefine{(ca:#1)}\globalundefine{(cs:#1)}}
+\def\colordefrlt #1{\localundefine {(ta:#1)}\localundefine {(ts:#1)}}
+\def\colordefrgt #1{\globalundefine{(ta:#1)}\globalundefine{(ts:#1)}}
+
+%D \macros
+%D {colorvalue, grayvalue}
+%D
+%D We can typeset the color components using \type{\colorvalue} and
+%D \type{\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 \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+
+\def\colorformatseparator{ }
+
+\def\MPcolor#1{\ctxlua{tex.sprint(colors.mp(\number\currentcolormodel,\number\doinheritca{#1},\number\doinheritta{#1}))}}
+
+\let\currentcolorname\s!black % todo
+\let\outercolorname \s!black % todo
+
+\def\thecolorattribute #1{\number\csname(ca:\ifcsname(ca:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ca:#1)\endcsname#1\fi\fi)\endcsname}
+\def\thetransparencyattribute#1{\number\csname(ta:\ifcsname(ta:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ta:#1)\endcsname#1\fi\fi)\endcsname}
+
+\def\internalspotcolorname #1{\ctxlua{tex.sprint(colors.spotcolorname (\thecolorattribute{#1}))}}
+\def\internalspotcolorparent#1{\ctxlua{tex.sprint(colors.spotcolorparent(\thecolorattribute{#1}))}}
+\def\internalspotcolorsize #1{\ctxlua{tex.sprint(colors.spotcolorvalue (\thecolorattribute{#1}))}}
+
+\def\colorcomponents #1{\ctxlua{tex.sprint(colors.colorcomponents (\thecolorattribute {#1}))}}
+\def\transparencycomponents#1{\ctxlua{tex.sprint(colors.transparencycomponents(\thetransparencyattribute{#1}))}}
+
+\def\colorvalue#1{\ctxlua{tex.sprint(colors.formatcolor(\thecolorattribute{#1},"\colorformatseparator"))}}
+\def\grayvalue #1{\ctxlua{tex.sprint(colors.formatgray (\thecolorattribute{#1},"\colorformatseparator"))}}
+
+\def\doifblackelse #1{\ctxlua{commands.doifelse(colors.isblack(\thecolorattribute{#1}))}}
+\def\doifdrawingblackelse {\ctxlua{commands.doifelse(colors.isblack(tex.attribute[attributes.numbers['color']]))}}
+
+%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
+%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\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint}
+
+% \normal added else fails in metafun manual (leaders do a hard scan)
+
+\unexpanded\def\forcecolorhack{\leaders\hrule\normalhskip\zeropoint}
+
+%D We default to the colors defined in \module{colo-rgb} and
+%D support both \cap{RGB} and \cap{CMYK} output. As you can
+%D see, color support is turned off by default. Reduction of
+%D gray colors to gray scales is turned on.
+
+\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]
+
+\setupcolors
+ [\c!state=\v!stop, % will be enabled later on
+ \c!conversion=\v!yes,
+ \c!reduction=\v!no,
+ \c!rgb=\v!yes,
+ \c!cmyk=\v!yes,
+ \c!spot=\v!yes,
+ \c!mp\c!cmyk=\@@clcmyk,
+ \c!mp\c!spot=\@@clspot,
+ \c!expansion=\v!no,
+ \c!textcolor=,
+ \c!split=\v!no, % obsolete
+ \c!factor=\v!yes,
+ \c!criterium=\v!all] % obsolete
+
+\appendtoks
+ \setupcolors[\c!state=\v!start]% later direct
+\to \everyjob
+
+\appendtoks
+ \let\showcolormessage\showmessage
+\to \everyjob
+
+\setupcolor
+ [\v!rgb]
+
+\protect \endinput
diff --git a/tex/context/base/colo-rgb.tex b/tex/context/base/colo-rgb.tex
new file mode 100644
index 000000000..038e0ab0b
--- /dev/null
+++ b/tex/context/base/colo-rgb.tex
@@ -0,0 +1,530 @@
+%D \module
+%D [ file=colo-rgb,
+%D version=1995.01.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=RGB,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Just to give users a start we define some colors. While
+%D switching fonts is as international as can be, thanks to the
+%D mnemonics, naming colors is very interface dependant. To
+%D support international setups, we define both english and
+%D interface dependant colors. We use the color inheritance
+%D mechanisms to implement the interface dependant ones.
+
+%D First we define some simple primary \cap{RGB} and \cap{CMYK}
+%D colors. All colors are defined in \cap{RGB} color space.
+
+\definecolor [red] [r=1, g=0, b=0]
+\definecolor [green] [r=0, g=1, b=0]
+\definecolor [blue] [r=0, g=0, b=1]
+
+\definecolor [cyan] [r=0, g=1, b=1]
+\definecolor [magenta] [r=1, g=0, b=1]
+\definecolor [yellow] [r=1, g=1, b=0]
+
+\definecolor [white] [s=1] % [r=1, g=1, b=1]
+\definecolor [black] [s=0]
+\definecolor [gray] [s=.9]
+
+\definecolor [darkred] [r=.8, g=0, b=0]
+\definecolor [middlered] [r=.9, g=0, b=0]
+\definecolor [lightred] [r=1, g=0, b=0]
+
+\definecolor [darkgreen] [r=0, g=.6, b=0]
+\definecolor [middlegreen] [r=0, g=.8, b=0]
+\definecolor [lightgreen] [r=0, g=1, b=0]
+
+\definecolor [darkblue] [r=0, g=0, b=.8]
+\definecolor [middleblue] [r=0, g=0, b=.9]
+\definecolor [lightblue] [r=0, g=0, b=1]
+
+\definecolor [darkcyan] [r=.6, g=.8, b=.8]
+\definecolor [middlecyan] [r=0, g=.8, b=.8]
+
+\definecolor [darkmagenta] [r=.8, g=.6, b=.8]
+\definecolor [middlemagenta] [r=1, g=0, b=.6]
+
+\definecolor [darkyellow] [r=.8, g=.8, b=.6]
+\definecolor [middleyellow] [r=1, g=1, b=.2]
+
+\definecolor [darkgray] [s=.5]
+\definecolor [middlegray] [s=.7]
+\definecolor [lightgray] [s=.9]
+
+%D These colors are mapped to interface dependant colornames.
+
+\startinterface dutch
+
+ \definecolor [rood] [red]
+ \definecolor [groen] [green]
+ \definecolor [blauw] [blue]
+
+ \definecolor [cyaan] [cyan]
+ \definecolor [magenta] [magenta]
+ \definecolor [geel] [yellow]
+
+ \definecolor [wit] [white]
+ \definecolor [grijs] [gray]
+ \definecolor [zwart] [black]
+
+ \definecolor [donkerrood] [darkred]
+ \definecolor [middelrood] [middlered]
+ \definecolor [lichtrood] [lightred]
+
+ \definecolor [donkergroen] [darkgreen]
+ \definecolor [middelgroen] [middlegreen]
+ \definecolor [lichtgroen] [lightgreen]
+
+ \definecolor [donkerblauw] [darkblue]
+ \definecolor [middelblauw] [middleblue]
+ \definecolor [lichtblauw] [lightblue]
+
+ \definecolor [donkercyaan] [darkcyan]
+ \definecolor [middelcyaan] [middlecyan]
+
+ \definecolor [donkermagenta] [darkmagenta]
+ \definecolor [middelmagenta] [middlemagenta]
+
+ \definecolor [donkergeel] [darkyellow]
+ \definecolor [middelgeel] [middleyellow]
+
+ \definecolor [donkergrijs] [darkgray]
+ \definecolor [middengrijs] [middlegray]
+ \definecolor [lichtgrijs] [lightgray]
+
+\stopinterface
+
+\startinterface german
+
+ \definecolor [rot] [red]
+ \definecolor [gruen] [green]
+ \definecolor [blau] [blue]
+
+ \definecolor [cyan] [cyan]
+ \definecolor [magenta] [magenta]
+ \definecolor [gelb] [yellow]
+
+ \definecolor [weiss] [white]
+ \definecolor [grau] [gray]
+ \definecolor [schwarz] [black]
+
+ \definecolor [dunkelrot] [darkred]
+ \definecolor [mittelrot] [middlered]
+ \definecolor [hellrot] [lightred]
+
+ \definecolor [dunkelgruen] [darkgreen]
+ \definecolor [mittelgruen] [middlegreen]
+ \definecolor [hellgruen] [lightgreen]
+
+ \definecolor [dunkelblau] [darkblue]
+ \definecolor [mittelblau] [middleblue]
+ \definecolor [hellblau] [lightblue]
+
+ \definecolor [dunkelcyan] [darkcyan]
+ \definecolor [mittelcyan] [middlecyan]
+
+ \definecolor [dunkelmagenta] [darkmagenta]
+ \definecolor [mittelmagenta] [middlemagenta]
+
+ \definecolor [dunkelgelb] [darkyellow]
+ \definecolor [mittelgelb] [middleyellow]
+
+ \definecolor [dunkelgrau] [darkgray]
+ \definecolor [mittelgrau] [middlegray]
+ \definecolor [hellgrau] [lightgray]
+
+\stopinterface
+
+\startinterface czech
+
+ \definecolor [cervena] [red]
+ \definecolor [zelena] [green]
+ \definecolor [modra] [blue]
+
+ \definecolor [azurova] [cyan]
+ \definecolor [fialova] [magenta]
+ \definecolor [zluta] [yellow]
+
+ \definecolor [bila] [white]
+ \definecolor [cerna] [black]
+
+ \definecolor [tmavecervena] [darkred]
+ \definecolor [strednecervena] [middlered]
+ \definecolor [svetlecervena] [lightred]
+
+ \definecolor [tmavezelena] [darkgreen]
+ \definecolor [strednezelena] [middlegreen]
+ \definecolor [svetlezelena] [lightgreen]
+
+ \definecolor [tmavemodra] [darkblue]
+ \definecolor [strednemodra] [middleblue]
+ \definecolor [svetlemodra] [lightblue]
+
+ \definecolor [tmaveazurova] [darkcyan]
+ \definecolor [stredneazurova] [middlecyan]
+
+ \definecolor [tmavefialova] [darkmagenta]
+ \definecolor [strednefialova] [middlemagenta]
+
+ \definecolor [tmavezluta] [darkyellow]
+ \definecolor [strednezluta] [middleyellow]
+
+ \definecolor [tmaveseda] [darkgray]
+ \definecolor [stredneseda] [middlegray]
+ \definecolor [svetleseda] [lightgray]
+
+\stopinterface
+
+\startinterface italian
+
+ \definecolor [rosso] [red]
+ \definecolor [verde] [green]
+ \definecolor [blu] [blue]
+
+ \definecolor [azzurro] [cyan]
+ \definecolor [turchino] [cyan]
+ \definecolor [ciano] [cyan]
+ \definecolor [cremisi] [magenta]
+ \definecolor [giallo] [yellow]
+
+ \definecolor [bianco] [white]
+ \definecolor [grigio] [gray]
+ \definecolor [nero] [black]
+
+ \definecolor [rossoscuro] [darkred]
+ \definecolor [rossomedio] [middlered]
+ \definecolor [rossochiaro] [lightred]
+
+ \definecolor [verdescuro] [darkgreen]
+ \definecolor [verdemedio] [middlegreen]
+ \definecolor [verdechiaro] [lightgreen]
+
+ \definecolor [bluscuro] [darkblue]
+ \definecolor [blumedio] [middleblue]
+ \definecolor [bluchiaro] [lightblue]
+
+ \definecolor [azzurroscuro] [darkcyan]
+ \definecolor [azzurrochiaro] [middlecyan]
+
+ \definecolor [cremisiscuro] [darkmagenta]
+ \definecolor [cremisichiaro] [middlemagenta]
+
+
+ \definecolor [gialloscuro] [darkyellow]
+ \definecolor [giallomedio] [middleyellow]
+
+ \definecolor [grigioscuro] [darkgray]
+ \definecolor [grigiomedio] [middlegray]
+ \definecolor [grigiochiaro] [lightgray]
+
+\stopinterface
+
+\startinterface romanian
+
+ \definecolor [rosu] [red]
+ \definecolor [verde] [green]
+ \definecolor [albastru] [blue]
+
+ \definecolor [cian] [cyan]
+ \definecolor [magenta] [magenta]
+ \definecolor [galben] [yellow]
+
+ \definecolor [alb] [white]
+ \definecolor [gri] [gray]
+ \definecolor [negru] [black]
+
+ \definecolor [rosuinchis] [darkred]
+ \definecolor [rosumediu] [middlered]
+ \definecolor [rosudeschis] [lightred]
+
+ \definecolor [verdeinchis] [darkgreen]
+ \definecolor [verdemediu] [middlegreen]
+ \definecolor [verdedeschis] [lightgreen]
+
+ \definecolor [albastruinchis] [darkblue]
+ \definecolor [albastrumediu] [middleblue]
+ \definecolor [albastrudeschis] [lightblue]
+
+ \definecolor [cianinchis] [darkcyan]
+ \definecolor [cianmediu] [middlecyan]
+
+ \definecolor [magentainchis] [darkmagenta]
+ \definecolor [magentamediu] [middlemagenta]
+
+ \definecolor [galbeninchis] [darkyellow]
+ \definecolor [galbenmediu] [middleyellow]
+
+ \definecolor [griinchis] [darkgray]
+ \definecolor [grimediu] [middlegray]
+ \definecolor [grideschis] [lightgray]
+
+\stopinterface
+
+%D Like colors, we first define the english colorgroups. These
+%D colorgroups are tuned for distinctive gray scale printing.
+
+% todo : more efficient and real gray
+
+\definecolorgroup
+ [gray]
+ [0.95:0.95:0.95,
+ 0.90:0.90:0.90,
+ 0.80:0.80:0.80,
+ 0.70:0.70:0.70,
+ 0.60:0.60:0.60,
+ 0.50:0.50:0.50,
+ 0.40:0.40:0.40,
+ 0.30:0.30:0.30,
+ 0.20:0.20:0.20,
+ 0.10:0.10:0.10,
+ 0.00:0.00:0.00]
+
+\definecolorgroup
+ [red]
+ [1.00:0.90:0.90,
+ 1.00:0.80:0.80,
+ 1.00:0.70:0.70,
+ 1.00:0.55:0.55,
+ 1.00:0.40:0.40,
+ 1.00:0.25:0.25,
+ 1.00:0.15:0.15,
+ 0.90:0.00:0.00]
+
+\definecolorgroup
+ [green]
+ [0.90:1.00:0.90,
+ 0.70:1.00:0.70,
+ 0.50:1.00:0.50,
+ 0.30:1.00:0.30,
+ 0.15:0.90:0.15,
+ 0.00:0.80:0.00,
+ 0.00:0.65:0.00,
+ 0.00:0.50:0.00]
+
+\definecolorgroup
+ [blue]
+ [0.90:0.95:1.00,
+ 0.80:0.90:1.00,
+ 0.55:0.85:1.00,
+ 0.30:0.80:1.00,
+ 0.15:0.75:1.00,
+ 0.00:0.70:1.00,
+ 0.00:0.55:1.00,
+ 0.00:0.40:1.00]
+
+\definecolorgroup
+ [cyan]
+ [0.80:1.00:1.00,
+ 0.60:1.00:1.00,
+ 0.30:1.00:1.00,
+ 0.00:0.95:0.95,
+ 0.00:0.85:0.85,
+ 0.00:0.75:0.75,
+ 0.00:0.60:0.60,
+ 0.00:0.50:0.50]
+
+\definecolorgroup
+ [magenta]
+ [1.00:0.90:1.00,
+ 1.00:0.80:1.00,
+ 1.00:0.65:1.00,
+ 1.00:0.50:1.00,
+ 1.00:0.35:1.00,
+ 1.00:0.15:1.00,
+ 0.90:0.05:0.90,
+ 0.80:0.00:0.80]
+
+\definecolorgroup
+ [yellow]
+ [1.00:1.00:0.70,
+ 1.00:1.00:0.00,
+ 1.00:0.85:0.05,
+ 1.00:0.70:0.00,
+ 1.00:0.55:0.00,
+ 0.95:0.40:0.00,
+ 0.80:0.30:0.00,
+ 0.60:0.30:0.00]
+
+\definecolorgroup
+ [red*]
+ [1.00:0.95:0.95,
+ 1.00:0.90:0.90,
+ 1.00:0.80:0.80,
+ 1.00:0.70:0.70,
+ 1.00:0.60:0.60,
+ 1.00:0.50:0.50,
+ 1.00:0.40:0.40,
+ 1.00:0.30:0.30]
+
+\definecolorgroup
+ [green*]
+ [0.95:1.00:0.95,
+ 0.90:1.00:0.90,
+ 0.80:1.00:0.80,
+ 0.70:1.00:0.70,
+ 0.60:1.00:0.60,
+ 0.50:1.00:0.50,
+ 0.40:1.00:0.40,
+ 0.30:1.00:0.30]
+
+\definecolorgroup
+ [blue*]
+ [0.95:0.95:1.00,
+ 0.90:0.90:1.00,
+ 0.80:0.80:1.00,
+ 0.70:0.70:1.00,
+ 0.60:0.60:1.00,
+ 0.50:0.50:1.00,
+ 0.40:0.40:1.00,
+ 0.30:0.30:1.00]
+
+\definecolorgroup
+ [yellow*]
+ [1.00:1.00:0.10,
+ 1.00:1.00:0.00,
+ 0.90:0.90:0.00,
+ 0.80:0.80:0.00,
+ 0.70:0.70:0.00,
+ 0.60:0.60:0.00,
+ 0.50:0.50:0.00,
+ 0.40:0.40:0.00]
+
+%D For the sake of implementing interface dependant color
+%D groups we support colorgroup duplication.
+
+\startinterface dutch
+ \definecolorgroup [grijs] [gray]
+ \definecolorgroup [rood] [red]
+ \definecolorgroup [groen] [green]
+ \definecolorgroup [blauw] [blue]
+ \definecolorgroup [cyaan] [cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [geel] [yellow]
+ \definecolorgroup [rood*] [red*]
+ \definecolorgroup [groen*] [green*]
+ \definecolorgroup [blauw*] [blue*]
+ \definecolorgroup [geel*] [yellow*]
+\stopinterface
+
+\startinterface german
+ \definecolorgroup [grau] [gray]
+ \definecolorgroup [rot] [red]
+ \definecolorgroup [gruen] [green]
+ \definecolorgroup [blau] [blue]
+ \definecolorgroup [cyan] [cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [gelb] [yellow]
+ \definecolorgroup [rot*] [red*]
+ \definecolorgroup [gruen*] [green*]
+ \definecolorgroup [blau*] [blue*]
+ \definecolorgroup [gelb*] [yellow*]
+\stopinterface
+
+\startinterface czech
+ \definecolorgroup [seda] [gray]
+ \definecolorgroup [cervena] [red]
+ \definecolorgroup [zelena] [green]
+ \definecolorgroup [modra] [blue]
+ \definecolorgroup [azurova] [cyan]
+ \definecolorgroup [fialova] [magenta]
+ \definecolorgroup [zluta] [yellow]
+ \definecolorgroup [cervena*] [red*]
+ \definecolorgroup [zelena*] [green*]
+ \definecolorgroup [modra*] [blue*]
+ \definecolorgroup [zluta*] [yellow*]
+\stopinterface
+
+\startinterface italian
+ \definecolorgroup [grigio] [gray]
+ \definecolorgroup [rosso] [red]
+ \definecolorgroup [verde] [green]
+ \definecolorgroup [blu] [blue]
+ \definecolorgroup [ciano] [cyan]
+ \definecolorgroup [azzurro] [cyan]
+ \definecolorgroup [turchino][cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [cremisi] [magenta]
+ \definecolorgroup [giallo] [yellow]
+ \definecolorgroup [rosso*] [red*]
+ \definecolorgroup [verde*] [green*]
+ \definecolorgroup [blu*] [blue*]
+ \definecolorgroup [giallo*] [yellow*]
+\stopinterface
+
+%D The next set of color palets is quite language independant.
+%D These palets are meant as examples.
+
+\definepalet
+ [alfa]
+ [ top=red:7,
+ bottom=green:6,
+ up=blue:5,
+ down=cyan:4,
+ strange=magenta:3,
+ charm=yellow:2]
+
+\definepalet
+ [beta]
+ [ top=red:7,
+ bottom=green:5,
+ up=blue:3,
+ down=cyan:6,
+ strange=magenta:2,
+ charm=yellow:1]
+
+\definepalet
+ [gamma]
+ [ top=red:2,
+ bottom=green:5,
+ up=blue:3,
+ down=cyan:6,
+ strange=magenta:7,
+ charm=yellow:4]
+
+\definepalet
+ [delta]
+ [ top=yellow*:5,
+ bottom=yellow*:3,
+ up=yellow*:2,
+ down=magenta:6,
+ strange=blue:4,
+ charm=blue:1]
+
+\definepalet
+ [epsilon]
+ [ top=cyan:7,
+ bottom=cyan:5,
+ up=blue:3,
+ down=yellow:6,
+ strange=yellow:4,
+ charm=yellow:2]
+
+\definepalet
+ [zeta]
+ [ top=red:6,
+ bottom=green:5,
+ up=blue:7,
+ down=cyan:4,
+ strange=magenta:3,
+ charm=yellow:2]
+
+%D The next four colors are used for typesetting verbatim \TEX\
+%D in color.
+
+\definecolor [texcolorone] [middlered]
+\definecolor [texcolortwo] [middlegreen]
+\definecolor [texcolorthree] [middleblue]
+\definecolor [texcolorfour] [darkyellow]
+
+%D Bonus (needed for FO test):
+
+\definecolor [orange] [r=1,g=.5]
+
+\endinput
diff --git a/tex/context/base/colo-run.tex b/tex/context/base/colo-run.tex
new file mode 100644
index 000000000..d94ea9801
--- /dev/null
+++ b/tex/context/base/colo-run.tex
@@ -0,0 +1,257 @@
+%D \module
+%D [ file=colo-run,
+%D version=1997.04.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Runtime loaded commands,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+% temp hack (not do be documented)
+
+% \gdef\doformatcolorP#1:#2:#3:#4:#5:#6\od % was undefined in colo-ini
+% {#1\colorformatseparator
+% \dodoformatcolor{#2}\colorformatseparator
+% \dodoformatcolor{#3}\colorformatseparator
+% \dodoformatcolor{#4}\colorformatseparator}
+
+% \gdef\doformatgrayP#1:#2:#3:#4:#5:#6\od
+% {todo}
+
+% so far
+
+\gdef\showpalet
+ {\dodoubleargument\doshowpalet}
+
+\gdef\doshowpalet[#1][#2]%
+ {\doifdefined{\??pa#1}
+ {\doifinsetelse\v!vertical{#2}
+ {\showverticalpalet[#1][#2]}
+ {\showhorizontalpalet[#1][#2]}}}
+
+\gdef\showverticalpalet[#1][#2]%
+ {\localvbox
+ {\offinterlineskip
+ \setuppalet[#1]
+ \def\rule
+ {\vrule\!!width3em\!!height\strutht\!!depth\strutdp}
+ \tabskip\zeropoint
+ \def\doshowpalet##1%
+ {\doifinsetelse\v!number{#2}{##1\hskip.5em}{}&
+ \color[##1]{\rule}\graycolor[##1]{\rule}&
+ \doifinset\v!value{#2}{\hskip.5em\colorvalue{##1}}\crcr}
+ \halign
+ {\hss##&\hss##\hss#\cr
+ &\doifinset{\v!name}{#2}{\strut#1}&\cr%
+ \processpalet[#1]\doshowpalet\crcr}}}
+
+\gdef\showhorizontalpalet[#1][#2]%
+ {\localvbox
+ {\offinterlineskip
+ \setuppalet[#1]
+ \tabskip\zeropoint
+ \!!widtha\zeropoint
+ \doifinset\v!number{#2}
+ {\def\doshowpalet##1%
+ {\setbox0\hbox{##1}%
+ \ifdim\!!widtha<\wd0\!!widtha\wd0\fi}%
+ \processpalet[#1]\doshowpalet}%
+ \advance\!!widtha 1em
+ \ifdim\!!widtha<5em
+ \!!widtha5em
+ \fi
+ \halign
+ {##&&\hbox to \!!widtha{\hss##\hss}\cr
+ \doifinset\v!number{#2}
+ {\def\doshowpalet##1{&\strut##1}%
+ \processpalet[#1]\doshowpalet}\cr
+ \doifinset\v!name{#2}{#1\hskip.5em}%
+ \def\doshowpalet##1%
+ {&\strut\color[##1]{\vrule\!!width\!!widtha\!!height\strutht\!!depth\zeropoint}}%
+ \processpalet[#1]\doshowpalet\crcr
+ \noalign{\vskip-\strutdepth}%
+ \def\doshowpalet##1%
+ {&\graycolor[##1]{\vrule\!!width\!!widtha\!!height\zeropoint\!!depth\strutdp}}%
+ \processpalet[#1]\doshowpalet\crcr
+ \doifinset\v!value{#2}
+ {\def\doshowpalet##1%
+ {&\vbox
+ {\hsize\!!widtha
+ \vskip.25ex
+ \everypar{\strut}
+ \veryraggedcenter
+ \let\colorformatseparator=\endgraf
+ \colorvalue{##1}}}%
+ \processpalet[#1]\doshowpalet}%
+ \crcr}}}
+
+\gdef\processpalet[#1]%
+ {\expanded{\globalprocesscommalist[\getvalue{\??pa#1}]}}
+
+\gdef\showcolorgroup
+ {\dodoubleargument\doshowcolorgroup}
+
+\gdef\doshowcolorgroup[#1][#2]%
+ {\doifcolor{#1:1}
+ {\doifinsetelse\v!vertical{#2}
+ {\showverticalcolorgroup[#1][#2]}
+ {\showhorizontalcolorgroup[#1][#2]}}}
+
+\gdef\showhorizontalcolorgroup[#1][#2]%
+ {\localvbox
+ {\offinterlineskip
+ \setuppalet
+ \tabskip\zeropoint
+ \def\rule
+ {\vrule\!!width4em\!!height\strutht\!!depth\strutdp}
+ \def\colorformatseparator{\strut\cr}
+ \def\dodoshowgroup##1%
+ {\halign
+ {\hss####\hss\cr
+ \doifinset\v!number{#2}{\strut##1}\cr
+ \color[#1:##1]{\vrule\!!width4em\!!height\strutht\!!depth\zeropoint}\cr
+ \graycolor[#1:##1]{\vrule\!!width4em\!!height\zeropoint\!!depth\strutdp}\cr
+ \doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}}
+ \def\doshowgroup##1%
+ {\doifcolor{#1:##1}
+ {\vbox{\dodoshowgroup{##1}}}}%
+ \hbox
+ {\doifinset\v!name{#2}
+ {\strut
+ \doifinsetelse\v!value{#2}
+ {\raise3\lineheight\hbox{#1\hskip.5em}}
+ {#1}%
+ \hskip.5em}%
+ \doshowgroup1\doshowgroup2\doshowgroup3\doshowgroup4%
+ \doshowgroup5\doshowgroup6\doshowgroup7\doshowgroup8}}}
+
+\gdef\showverticalcolorgroup[#1][#2]%
+ {\localvbox
+ {\offinterlineskip
+ \setuppalet
+ \tabskip\zeropoint
+ \def\rule
+ {\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}%
+ \def\doshowgroup##1%
+ {\doifcolor{#1:##1}
+ {\doifinset\v!number{#2}{##1\hskip.5em}&
+ \color[#1:##1]{\rule}\graycolor[#1:##1]{\rule}&
+ \doifinset\v!value{#2}{\hskip.5em\colorvalue{#1:##1}}\crcr}}%
+ \halign
+ {\hss##&\hss##\hss#\hss\cr
+ &\doifinset\v!name{#2}{\strut#1}&\crcr
+ \doshowgroup1\doshowgroup2\doshowgroup3\doshowgroup4%
+ \doshowgroup5\doshowgroup6\doshowgroup7\doshowgroup8}}}
+
+\gdef\showcolor
+ {\dosingleempty\doshowcolor}
+
+\gdef\doshowcolor[#1]%
+ {\bgroup
+ \iffirstargument
+ \let\colorlist\empty % not really used, only for colo-run
+ \let\colorstyle\empty
+ \settrue\collectcolorsinlist
+ \setupcolor[#1]%
+ \fi
+ \def\rule
+ {\vrule\!!width4em\!!height\strutht\!!depth\strutdp}%
+ \def\docommand##1%
+ {\NC\graycolor[##1]{\rule}\NC\color[##1]{\rule}\NC\grayvalue{##1}\NC\colorvalue{##1}\NC##1\NC\NR}%
+ \starttabulate[|l|l|l|l|l|l|l|]
+ \expanded{\globalprocesscommalist[\colorlist]}\docommand
+ \stoptabulate
+ \egroup}
+
+\gdef\comparepalet
+ {\dosingleargument\docomparepalet}
+
+\gdef\docomparepalet[#1]%
+ {\doifdefined{\??pa#1}
+ {\hbox
+ {\dodocomparepalet\color[#1]%
+ \quad
+ \dodocomparepalet\graycolor[#1]}}}
+
+\gdef\dodocomparepalet#1[#2]%
+ {\localvbox
+ {\offinterlineskip
+ \setuppalet[#2]
+ \getcommacommandsize[\getvalue{\??pa#2}]
+ \!!widtha2em\relax
+ \hsize\commalistsize\!!widtha
+ \def\rule%
+ {\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}
+ \def\dododocomparepalet##1%
+ {\hbox
+ {\setbox0\hbox
+ {#1[##1]{\vrule\!!width\hsize\!!height3ex}}%
+ \wd0\zeropoint
+ \box0
+ \hbox to \hsize
+ {\def\dododocomparepalet####1%
+ {\hbox to \!!widtha
+ {\hss#1[####1]{\rule}\hss}}%
+ \processcommacommand[\getvalue{\??pa#2}]\dododocomparepalet}}
+ \endgraf}
+ \processcommacommand[\getvalue{\??pa#2}]\dododocomparepalet}}
+
+\gdef\comparecolorgroup
+ {\dosingleargument\docomparecolorgroup}
+
+\gdef\docomparecolorgroup[#1]%
+ {\doifcolor{#1:1}
+ {\hbox
+ {\dodocomparecolorgroup\color[#1]%
+ \quad
+ \dodocomparecolorgroup\graycolor[#1]}}}
+
+\gdef\dodocomparecolorgroup#1[#2]%
+ {\localvbox
+ {\!!counta\zerocount
+ \dorecurse{15}
+ {\doifcolor{#2:\recurselevel}{\advance\!!counta\plusone}}
+ \!!widtha2em\relax
+ \hsize\!!counta\!!widtha
+ \def\rule
+ {\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}
+ \def\dododocomparecolorgroup##1%
+ {\hbox to \hsize
+ {\setbox0\hbox
+ {#1[#2:##1]{\vrule\!!width\hsize\!!height3ex}}%
+ \wd0\zeropoint
+ \box0
+ \hbox to \hsize
+ {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\rule}\hss}}}
+ \endgraf}
+ \dorecurse\!!counta{\dododocomparecolorgroup\recurselevel}}}
+
+\gdef\dogetcolorcomponents#1%
+ {\doifelsenothing{#1}
+ {\appendtoks
+ \TB
+ \to \scratchtoks}
+ {\appendtoks
+ \NC\showcolorbar[#1]\NC#1\NC\transparencycomponents{#1}\NC\colorcomponents{#1}\NC \NR
+ \to \scratchtoks}}
+
+\gdef\showcolorbar[#1]%
+ {\backgroundline[#1]{\strut\enspace\color[white]{white}\enspace\color[black]{black}\enspace}}
+
+\gdef\showcolorcomponents[#1]%
+ {\begingroup
+ \scratchtoks{\TB}%
+ \processcommacommand[#1]\dogetcolorcomponents
+ \starttabulate[|lT|lT|lT|lT|]
+ \NC color \NC name \NC transparency \NC specification \NC\NR
+ \the\scratchtoks
+ \stoptabulate
+ \endgroup}
+
+\protect \endinput
diff --git a/tex/context/base/colo-x11.tex b/tex/context/base/colo-x11.tex
new file mode 100644
index 000000000..45d3aac62
--- /dev/null
+++ b/tex/context/base/colo-x11.tex
@@ -0,0 +1,677 @@
+%D \module
+%D [ file=colo-x11,
+%D version=2009.11.13,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=X11,
+%D author=Alan Braslau]
+%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 Standard X11 rgb colors (from \type {/usr/share/X11/rgb.txt}):
+
+\doifnotmode{mkiv} {
+ \input colo-hex.mkii
+}
+
+\definecolor [snow] [h=fffafa]
+\definecolor [ghostwhite] [h=f8f8ff]
+\definecolor [whitesmoke] [s=0.96]
+\definecolor [gainsboro] [s=0.86]
+\definecolor [floralwhite] [h=fffaf0]
+\definecolor [oldlace] [h=fdf5e6]
+\definecolor [linen] [h=faf0e6]
+\definecolor [antiquewhite] [h=faebd7]
+\definecolor [papayawhip] [h=ffefd5]
+\definecolor [blanchedalmond] [h=ffebcd]
+\definecolor [bisque] [h=ffe4c4]
+\definecolor [peachpuff] [h=ffdab9]
+\definecolor [navajowhite] [h=ffdead]
+\definecolor [moccasin] [h=ffe4b5]
+\definecolor [cornsilk] [h=fff8dc]
+\definecolor [ivory] [h=fffff0]
+\definecolor [lemonchiffon] [h=fffacd]
+\definecolor [seashell] [h=fff5ee]
+\definecolor [honeydew] [h=f0fff0]
+\definecolor [mintcream] [h=f5fffa]
+\definecolor [azure] [h=f0ffff]
+\definecolor [aliceblue] [h=f0f8ff]
+\definecolor [lavender] [h=e6e6fa]
+\definecolor [lavenderblush] [h=fff0f5]
+\definecolor [mistyrose] [h=ffe4e1]
+\definecolor [white] [s=1]
+\definecolor [black] [s=0]
+\definecolor [darkslategray] [h=2f4f4f]
+\definecolor [darkslategrey] [darkslategray]
+\definecolor [dimgray] [s=0.41]
+\definecolor [dimgrey] [dimgray]
+\definecolor [slategray] [h=708090]
+\definecolor [slategrey] [slategray]
+\definecolor [lightslategray] [h=778899]
+\definecolor [lightslategrey] [lightslategray]
+\definecolor [gray] [s=0.75]
+\definecolor [grey] [gray]
+\definecolor [lightgrey] [s=0.83]
+\definecolor [lightgray] [lightgrey]
+\definecolor [midnightblue] [h=191970]
+\definecolor [navy] [h=000080]
+\definecolor [navyblue] [navy]
+\definecolor [cornflowerblue] [h=6495ed]
+\definecolor [darkslateblue] [h=483d8b]
+\definecolor [slateblue] [h=6a5acd]
+\definecolor [mediumslateblue] [h=7b68ee]
+\definecolor [lightslateblue] [h=8470ff]
+\definecolor [mediumblue] [h=0000cd]
+\definecolor [royalblue] [h=4169e1]
+\definecolor [blue] [h=0000ff]
+\definecolor [dodgerblue] [h=1e90ff]
+\definecolor [deepskyblue] [h=00bfff]
+\definecolor [skyblue] [h=87ceeb]
+\definecolor [lightskyblue] [h=87cefa]
+\definecolor [steelblue] [h=4682b4]
+\definecolor [lightsteelblue] [h=b0c4de]
+\definecolor [lightblue] [h=add8e6]
+\definecolor [powderblue] [h=b0e0e6]
+\definecolor [paleturquoise] [h=afeeee]
+\definecolor [darkturquoise] [h=00ced1]
+\definecolor [mediumturquoise] [h=48d1cc]
+\definecolor [turquoise] [h=40e0d0]
+\definecolor [cyan] [h=00ffff]
+\definecolor [lightcyan] [h=e0ffff]
+\definecolor [cadetblue] [h=5f9ea0]
+\definecolor [mediumaquamarine] [h=66cdaa]
+\definecolor [aquamarine] [h=7fffd4]
+\definecolor [darkgreen] [h=006400]
+\definecolor [darkolivegreen] [h=556b2f]
+\definecolor [darkseagreen] [h=8fbc8f]
+\definecolor [seagreen] [h=2e8b57]
+\definecolor [mediumseagreen] [h=3cb371]
+\definecolor [lightseagreen] [h=20b2aa]
+\definecolor [palegreen] [h=98fb98]
+\definecolor [springgreen] [h=00ff7f]
+\definecolor [lawngreen] [h=7cfc00]
+\definecolor [green] [h=00ff00]
+\definecolor [chartreuse] [h=7fff00]
+\definecolor [mediumspringgreen] [h=00fa9a]
+\definecolor [greenyellow] [h=adff2f]
+\definecolor [limegreen] [h=32cd32]
+\definecolor [yellowgreen] [h=9acd32]
+\definecolor [forestgreen] [h=228b22]
+\definecolor [olivedrab] [h=6b8e23]
+\definecolor [darkkhaki] [h=bdb76b]
+\definecolor [khaki] [h=f0e68c]
+\definecolor [palegoldenrod] [h=eee8aa]
+\definecolor [lightgoldenrodyellow] [h=fafad2]
+\definecolor [lightyellow] [h=ffffe0]
+\definecolor [yellow] [h=ffff00]
+\definecolor [gold] [h=ffd700]
+\definecolor [lightgoldenrod] [h=eedd82]
+\definecolor [goldenrod] [h=daa520]
+\definecolor [darkgoldenrod] [h=b8860b]
+\definecolor [rosybrown] [h=bc8f8f]
+\definecolor [indianred] [h=cd5c5c]
+\definecolor [saddlebrown] [h=8b4513]
+\definecolor [sienna] [h=a0522d]
+\definecolor [peru] [h=cd853f]
+\definecolor [burlywood] [h=deb887]
+\definecolor [beige] [h=f5f5dc]
+\definecolor [wheat] [h=f5deb3]
+\definecolor [sandybrown] [h=f4a460]
+\definecolor [tan] [h=d2b48c]
+\definecolor [chocolate] [h=d2691e]
+\definecolor [firebrick] [h=b22222]
+\definecolor [brown] [h=a52a2a]
+\definecolor [darksalmon] [h=e9967a]
+\definecolor [salmon] [h=fa8072]
+\definecolor [lightsalmon] [h=ffa07a]
+\definecolor [orange] [h=ffa500]
+\definecolor [darkorange] [h=ff8c00]
+\definecolor [coral] [h=ff7f50]
+\definecolor [lightcoral] [h=f08080]
+\definecolor [tomato] [h=ff6347]
+\definecolor [orangered] [h=ff4500]
+\definecolor [red] [h=ff0000]
+\definecolor [hotpink] [h=ff69b4]
+\definecolor [deeppink] [h=ff1493]
+\definecolor [pink] [h=ffc0cb]
+\definecolor [lightpink] [h=ffb6c1]
+\definecolor [palevioletred] [h=db7093]
+\definecolor [maroon] [h=b03060]
+\definecolor [mediumvioletred] [h=c71585]
+\definecolor [violetred] [h=d02090]
+\definecolor [magenta] [h=ff00ff]
+\definecolor [violet] [h=ee82ee]
+\definecolor [plum] [h=dda0dd]
+\definecolor [orchid] [h=da70d6]
+\definecolor [mediumorchid] [h=ba55d3]
+\definecolor [darkorchid] [h=9932cc]
+\definecolor [darkviolet] [h=9400d3]
+\definecolor [blueviolet] [h=8a2be2]
+\definecolor [purple] [h=a020f0]
+\definecolor [mediumpurple] [h=9370db]
+\definecolor [thistle] [h=d8bfd8]
+\definecolor [snow1] [h=fffafa]
+\definecolor [snow2] [h=eee9e9]
+\definecolor [snow3] [h=cdc9c9]
+\definecolor [snow4] [h=8b8989]
+\definecolor [seashell1] [h=fff5ee]
+\definecolor [seashell2] [h=eee5de]
+\definecolor [seashell3] [h=cdc5bf]
+\definecolor [seashell4] [h=8b8682]
+\definecolor [antiquewhite1] [h=ffefdb]
+\definecolor [antiquewhite2] [h=eedfcc]
+\definecolor [antiquewhite3] [h=cdc0b0]
+\definecolor [antiquewhite4] [h=8b8378]
+\definecolor [bisque1] [h=ffe4c4]
+\definecolor [bisque2] [h=eed5b7]
+\definecolor [bisque3] [h=cdb79e]
+\definecolor [bisque4] [h=8b7d6b]
+\definecolor [peachpuff1] [h=ffdab9]
+\definecolor [peachpuff2] [h=eecbad]
+\definecolor [peachpuff3] [h=cdaf95]
+\definecolor [peachpuff4] [h=8b7765]
+\definecolor [navajowhite1] [h=ffdead]
+\definecolor [navajowhite2] [h=eecfa1]
+\definecolor [navajowhite3] [h=cdb38b]
+\definecolor [navajowhite4] [h=8b795e]
+\definecolor [lemonchiffon1] [h=fffacd]
+\definecolor [lemonchiffon2] [h=eee9bf]
+\definecolor [lemonchiffon3] [h=cdc9a5]
+\definecolor [lemonchiffon4] [h=8b8970]
+\definecolor [cornsilk1] [h=fff8dc]
+\definecolor [cornsilk2] [h=eee8cd]
+\definecolor [cornsilk3] [h=cdc8b1]
+\definecolor [cornsilk4] [h=8b8878]
+\definecolor [ivory1] [h=fffff0]
+\definecolor [ivory2] [h=eeeee0]
+\definecolor [ivory3] [h=cdcdc1]
+\definecolor [ivory4] [h=8b8b83]
+\definecolor [honeydew1] [h=f0fff0]
+\definecolor [honeydew2] [h=e0eee0]
+\definecolor [honeydew3] [h=c1cdc1]
+\definecolor [honeydew4] [h=838b83]
+\definecolor [lavenderblush1] [h=fff0f5]
+\definecolor [lavenderblush2] [h=eee0e5]
+\definecolor [lavenderblush3] [h=cdc1c5]
+\definecolor [lavenderblush4] [h=8b8386]
+\definecolor [mistyrose1] [h=ffe4e1]
+\definecolor [mistyrose2] [h=eed5d2]
+\definecolor [mistyrose3] [h=cdb7b5]
+\definecolor [mistyrose4] [h=8b7d7b]
+\definecolor [azure1] [h=f0ffff]
+\definecolor [azure2] [h=e0eeee]
+\definecolor [azure3] [h=c1cdcd]
+\definecolor [azure4] [h=838b8b]
+\definecolor [slateblue1] [h=836fff]
+\definecolor [slateblue2] [h=7a67ee]
+\definecolor [slateblue3] [h=6959cd]
+\definecolor [slateblue4] [h=473c8b]
+\definecolor [royalblue1] [h=4876ff]
+\definecolor [royalblue2] [h=436eee]
+\definecolor [royalblue3] [h=3a5fcd]
+\definecolor [royalblue4] [h=27408b]
+\definecolor [blue1] [h=0000ff]
+\definecolor [blue2] [h=0000ee]
+\definecolor [blue3] [h=0000cd]
+\definecolor [blue4] [h=00008b]
+\definecolor [dodgerblue1] [h=1e90ff]
+\definecolor [dodgerblue2] [h=1c86ee]
+\definecolor [dodgerblue3] [h=1874cd]
+\definecolor [dodgerblue4] [h=104e8b]
+\definecolor [steelblue1] [h=63b8ff]
+\definecolor [steelblue2] [h=5cacee]
+\definecolor [steelblue3] [h=4f94cd]
+\definecolor [steelblue4] [h=36648b]
+\definecolor [deepskyblue1] [h=00bfff]
+\definecolor [deepskyblue2] [h=00b2ee]
+\definecolor [deepskyblue3] [h=009acd]
+\definecolor [deepskyblue4] [h=00688b]
+\definecolor [skyblue1] [h=87ceff]
+\definecolor [skyblue2] [h=7ec0ee]
+\definecolor [skyblue3] [h=6ca6cd]
+\definecolor [skyblue4] [h=4a708b]
+\definecolor [lightskyblue1] [h=b0e2ff]
+\definecolor [lightskyblue2] [h=a4d3ee]
+\definecolor [lightskyblue3] [h=8db6cd]
+\definecolor [lightskyblue4] [h=607b8b]
+\definecolor [slategray1] [h=c6e2ff]
+\definecolor [slategray2] [h=b9d3ee]
+\definecolor [slategray3] [h=9fb6cd]
+\definecolor [slategray4] [h=6c7b8b]
+\definecolor [lightsteelblue1] [h=cae1ff]
+\definecolor [lightsteelblue2] [h=bcd2ee]
+\definecolor [lightsteelblue3] [h=a2b5cd]
+\definecolor [lightsteelblue4] [h=6e7b8b]
+\definecolor [lightblue1] [h=bfefff]
+\definecolor [lightblue2] [h=b2dfee]
+\definecolor [lightblue3] [h=9ac0cd]
+\definecolor [lightblue4] [h=68838b]
+\definecolor [lightcyan1] [h=e0ffff]
+\definecolor [lightcyan2] [h=d1eeee]
+\definecolor [lightcyan3] [h=b4cdcd]
+\definecolor [lightcyan4] [h=7a8b8b]
+\definecolor [paleturquoise1] [h=bbffff]
+\definecolor [paleturquoise2] [h=aeeeee]
+\definecolor [paleturquoise3] [h=96cdcd]
+\definecolor [paleturquoise4] [h=668b8b]
+\definecolor [cadetblue1] [h=98f5ff]
+\definecolor [cadetblue2] [h=8ee5ee]
+\definecolor [cadetblue3] [h=7ac5cd]
+\definecolor [cadetblue4] [h=53868b]
+\definecolor [turquoise1] [h=00f5ff]
+\definecolor [turquoise2] [h=00e5ee]
+\definecolor [turquoise3] [h=00c5cd]
+\definecolor [turquoise4] [h=00868b]
+\definecolor [cyan1] [h=00ffff]
+\definecolor [cyan2] [h=00eeee]
+\definecolor [cyan3] [h=00cdcd]
+\definecolor [cyan4] [h=008b8b]
+\definecolor [darkslategray1] [h=97ffff]
+\definecolor [darkslategray2] [h=8deeee]
+\definecolor [darkslategray3] [h=79cdcd]
+\definecolor [darkslategray4] [h=528b8b]
+\definecolor [aquamarine1] [h=7fffd4]
+\definecolor [aquamarine2] [h=76eec6]
+\definecolor [aquamarine3] [h=66cdaa]
+\definecolor [aquamarine4] [h=458b74]
+\definecolor [darkseagreen1] [h=c1ffc1]
+\definecolor [darkseagreen2] [h=b4eeb4]
+\definecolor [darkseagreen3] [h=9bcd9b]
+\definecolor [darkseagreen4] [h=698b69]
+\definecolor [seagreen1] [h=54ff9f]
+\definecolor [seagreen2] [h=4eee94]
+\definecolor [seagreen3] [h=43cd80]
+\definecolor [seagreen4] [h=2e8b57]
+\definecolor [palegreen1] [h=9aff9a]
+\definecolor [palegreen2] [h=90ee90]
+\definecolor [palegreen3] [h=7ccd7c]
+\definecolor [palegreen4] [h=548b54]
+\definecolor [springgreen1] [h=00ff7f]
+\definecolor [springgreen2] [h=00ee76]
+\definecolor [springgreen3] [h=00cd66]
+\definecolor [springgreen4] [h=008b45]
+\definecolor [green1] [h=00ff00]
+\definecolor [green2] [h=00ee00]
+\definecolor [green3] [h=00cd00]
+\definecolor [green4] [h=008b00]
+\definecolor [chartreuse1] [h=7fff00]
+\definecolor [chartreuse2] [h=76ee00]
+\definecolor [chartreuse3] [h=66cd00]
+\definecolor [chartreuse4] [h=458b00]
+\definecolor [olivedrab1] [h=c0ff3e]
+\definecolor [olivedrab2] [h=b3ee3a]
+\definecolor [olivedrab3] [h=9acd32]
+\definecolor [olivedrab4] [h=698b22]
+\definecolor [darkolivegreen1] [h=caff70]
+\definecolor [darkolivegreen2] [h=bcee68]
+\definecolor [darkolivegreen3] [h=a2cd5a]
+\definecolor [darkolivegreen4] [h=6e8b3d]
+\definecolor [khaki1] [h=fff68f]
+\definecolor [khaki2] [h=eee685]
+\definecolor [khaki3] [h=cdc673]
+\definecolor [khaki4] [h=8b864e]
+\definecolor [lightgoldenrod1] [h=ffec8b]
+\definecolor [lightgoldenrod2] [h=eedc82]
+\definecolor [lightgoldenrod3] [h=cdbe70]
+\definecolor [lightgoldenrod4] [h=8b814c]
+\definecolor [lightyellow1] [h=ffffe0]
+\definecolor [lightyellow2] [h=eeeed1]
+\definecolor [lightyellow3] [h=cdcdb4]
+\definecolor [lightyellow4] [h=8b8b7a]
+\definecolor [yellow1] [h=ffff00]
+\definecolor [yellow2] [h=eeee00]
+\definecolor [yellow3] [h=cdcd00]
+\definecolor [yellow4] [h=8b8b00]
+\definecolor [gold1] [h=ffd700]
+\definecolor [gold2] [h=eec900]
+\definecolor [gold3] [h=cdad00]
+\definecolor [gold4] [h=8b7500]
+\definecolor [goldenrod1] [h=ffc125]
+\definecolor [goldenrod2] [h=eeb422]
+\definecolor [goldenrod3] [h=cd9b1d]
+\definecolor [goldenrod4] [h=8b6914]
+\definecolor [darkgoldenrod1] [h=ffb90f]
+\definecolor [darkgoldenrod2] [h=eead0e]
+\definecolor [darkgoldenrod3] [h=cd950c]
+\definecolor [darkgoldenrod4] [h=8b6508]
+\definecolor [rosybrown1] [h=ffc1c1]
+\definecolor [rosybrown2] [h=eeb4b4]
+\definecolor [rosybrown3] [h=cd9b9b]
+\definecolor [rosybrown4] [h=8b6969]
+\definecolor [indianred1] [h=ff6a6a]
+\definecolor [indianred2] [h=ee6363]
+\definecolor [indianred3] [h=cd5555]
+\definecolor [indianred4] [h=8b3a3a]
+\definecolor [sienna1] [h=ff8247]
+\definecolor [sienna2] [h=ee7942]
+\definecolor [sienna3] [h=cd6839]
+\definecolor [sienna4] [h=8b4726]
+\definecolor [burlywood1] [h=ffd39b]
+\definecolor [burlywood2] [h=eec591]
+\definecolor [burlywood3] [h=cdaa7d]
+\definecolor [burlywood4] [h=8b7355]
+\definecolor [wheat1] [h=ffe7ba]
+\definecolor [wheat2] [h=eed8ae]
+\definecolor [wheat3] [h=cdba96]
+\definecolor [wheat4] [h=8b7e66]
+\definecolor [tan1] [h=ffa54f]
+\definecolor [tan2] [h=ee9a49]
+\definecolor [tan3] [h=cd853f]
+\definecolor [tan4] [h=8b5a2b]
+\definecolor [chocolate1] [h=ff7f24]
+\definecolor [chocolate2] [h=ee7621]
+\definecolor [chocolate3] [h=cd661d]
+\definecolor [chocolate4] [h=8b4513]
+\definecolor [firebrick1] [h=ff3030]
+\definecolor [firebrick2] [h=ee2c2c]
+\definecolor [firebrick3] [h=cd2626]
+\definecolor [firebrick4] [h=8b1a1a]
+\definecolor [brown1] [h=ff4040]
+\definecolor [brown2] [h=ee3b3b]
+\definecolor [brown3] [h=cd3333]
+\definecolor [brown4] [h=8b2323]
+\definecolor [salmon1] [h=ff8c69]
+\definecolor [salmon2] [h=ee8262]
+\definecolor [salmon3] [h=cd7054]
+\definecolor [salmon4] [h=8b4c39]
+\definecolor [lightsalmon1] [h=ffa07a]
+\definecolor [lightsalmon2] [h=ee9572]
+\definecolor [lightsalmon3] [h=cd8162]
+\definecolor [lightsalmon4] [h=8b5742]
+\definecolor [orange1] [h=ffa500]
+\definecolor [orange2] [h=ee9a00]
+\definecolor [orange3] [h=cd8500]
+\definecolor [orange4] [h=8b5a00]
+\definecolor [darkorange1] [h=ff7f00]
+\definecolor [darkorange2] [h=ee7600]
+\definecolor [darkorange3] [h=cd6600]
+\definecolor [darkorange4] [h=8b4500]
+\definecolor [coral1] [h=ff7256]
+\definecolor [coral2] [h=ee6a50]
+\definecolor [coral3] [h=cd5b45]
+\definecolor [coral4] [h=8b3e2f]
+\definecolor [tomato1] [h=ff6347]
+\definecolor [tomato2] [h=ee5c42]
+\definecolor [tomato3] [h=cd4f39]
+\definecolor [tomato4] [h=8b3626]
+\definecolor [orangered1] [h=ff4500]
+\definecolor [orangered2] [h=ee4000]
+\definecolor [orangered3] [h=cd3700]
+\definecolor [orangered4] [h=8b2500]
+\definecolor [red1] [h=ff0000]
+\definecolor [red2] [h=ee0000]
+\definecolor [red3] [h=cd0000]
+\definecolor [red4] [h=8b0000]
+\definecolor [debianred] [h=d70751]
+\definecolor [deeppink1] [h=ff1493]
+\definecolor [deeppink2] [h=ee1289]
+\definecolor [deeppink3] [h=cd1076]
+\definecolor [deeppink4] [h=8b0a50]
+\definecolor [hotpink1] [h=ff6eb4]
+\definecolor [hotpink2] [h=ee6aa7]
+\definecolor [hotpink3] [h=cd6090]
+\definecolor [hotpink4] [h=8b3a62]
+\definecolor [pink1] [h=ffb5c5]
+\definecolor [pink2] [h=eea9b8]
+\definecolor [pink3] [h=cd919e]
+\definecolor [pink4] [h=8b636c]
+\definecolor [lightpink1] [h=ffaeb9]
+\definecolor [lightpink2] [h=eea2ad]
+\definecolor [lightpink3] [h=cd8c95]
+\definecolor [lightpink4] [h=8b5f65]
+\definecolor [palevioletred1] [h=ff82ab]
+\definecolor [palevioletred2] [h=ee799f]
+\definecolor [palevioletred3] [h=cd6889]
+\definecolor [palevioletred4] [h=8b475d]
+\definecolor [maroon1] [h=ff34b3]
+\definecolor [maroon2] [h=ee30a7]
+\definecolor [maroon3] [h=cd2990]
+\definecolor [maroon4] [h=8b1c62]
+\definecolor [violetred1] [h=ff3e96]
+\definecolor [violetred2] [h=ee3a8c]
+\definecolor [violetred3] [h=cd3278]
+\definecolor [violetred4] [h=8b2252]
+\definecolor [magenta1] [h=ff00ff]
+\definecolor [magenta2] [h=ee00ee]
+\definecolor [magenta3] [h=cd00cd]
+\definecolor [magenta4] [h=8b008b]
+\definecolor [orchid1] [h=ff83fa]
+\definecolor [orchid2] [h=ee7ae9]
+\definecolor [orchid3] [h=cd69c9]
+\definecolor [orchid4] [h=8b4789]
+\definecolor [plum1] [h=ffbbff]
+\definecolor [plum2] [h=eeaeee]
+\definecolor [plum3] [h=cd96cd]
+\definecolor [plum4] [h=8b668b]
+\definecolor [mediumorchid1] [h=e066ff]
+\definecolor [mediumorchid2] [h=d15fee]
+\definecolor [mediumorchid3] [h=b452cd]
+\definecolor [mediumorchid4] [h=7a378b]
+\definecolor [darkorchid1] [h=bf3eff]
+\definecolor [darkorchid2] [h=b23aee]
+\definecolor [darkorchid3] [h=9a32cd]
+\definecolor [darkorchid4] [h=68228b]
+\definecolor [purple1] [h=9b30ff]
+\definecolor [purple2] [h=912cee]
+\definecolor [purple3] [h=7d26cd]
+\definecolor [purple4] [h=551a8b]
+\definecolor [mediumpurple1] [h=ab82ff]
+\definecolor [mediumpurple2] [h=9f79ee]
+\definecolor [mediumpurple3] [h=8968cd]
+\definecolor [mediumpurple4] [h=5d478b]
+\definecolor [thistle1] [h=ffe1ff]
+\definecolor [thistle2] [h=eed2ee]
+\definecolor [thistle3] [h=cdb5cd]
+\definecolor [thistle4] [h=8b7b8b]
+\definecolor [gray0] [s=0.00]
+\definecolor [grey0] [gray0]
+\definecolor [gray1] [s=0.01]
+\definecolor [grey1] [gray1]
+\definecolor [gray2] [s=0.02]
+\definecolor [grey2] [gray2]
+\definecolor [gray3] [s=0.03]
+\definecolor [grey3] [gray3]
+\definecolor [gray4] [s=0.04]
+\definecolor [grey4] [gray4]
+\definecolor [gray5] [s=0.05]
+\definecolor [grey5] [gray5]
+\definecolor [gray6] [s=0.06]
+\definecolor [grey6] [gray6]
+\definecolor [gray7] [s=0.07]
+\definecolor [grey7] [gray7]
+\definecolor [gray8] [s=0.08]
+\definecolor [grey8] [gray8]
+\definecolor [gray9] [s=0.09]
+\definecolor [grey9] [gray9]
+\definecolor [gray10] [s=0.10]
+\definecolor [grey10] [gray10]
+\definecolor [gray11] [s=0.11]
+\definecolor [grey11] [gray11]
+\definecolor [gray12] [s=0.12]
+\definecolor [grey12] [gray12]
+\definecolor [gray13] [s=0.13]
+\definecolor [grey13] [gray13]
+\definecolor [gray14] [s=0.14]
+\definecolor [grey14] [gray14]
+\definecolor [gray15] [s=0.15]
+\definecolor [grey15] [gray15]
+\definecolor [gray16] [s=0.16]
+\definecolor [grey16] [gray16]
+\definecolor [gray17] [s=0.17]
+\definecolor [grey17] [gray17]
+\definecolor [gray18] [s=0.18]
+\definecolor [grey18] [gray18]
+\definecolor [gray19] [s=0.19]
+\definecolor [grey19] [gray19]
+\definecolor [gray20] [s=0.20]
+\definecolor [grey20] [gray20]
+\definecolor [gray21] [s=0.21]
+\definecolor [grey21] [gray21]
+\definecolor [gray22] [s=0.22]
+\definecolor [grey22] [gray22]
+\definecolor [gray23] [s=0.23]
+\definecolor [grey23] [gray23]
+\definecolor [gray24] [s=0.24]
+\definecolor [grey24] [gray24]
+\definecolor [gray25] [s=0.25]
+\definecolor [grey25] [gray25]
+\definecolor [gray26] [s=0.26]
+\definecolor [grey26] [gray26]
+\definecolor [gray27] [s=0.27]
+\definecolor [grey27] [gray27]
+\definecolor [gray28] [s=0.28]
+\definecolor [grey28] [gray28]
+\definecolor [gray29] [s=0.29]
+\definecolor [grey29] [gray29]
+\definecolor [gray30] [s=0.30]
+\definecolor [grey30] [gray30]
+\definecolor [gray31] [s=0.31]
+\definecolor [grey31] [gray31]
+\definecolor [gray32] [s=0.32]
+\definecolor [grey32] [gray32]
+\definecolor [gray33] [s=0.33]
+\definecolor [grey33] [gray33]
+\definecolor [gray34] [s=0.34]
+\definecolor [grey34] [gray34]
+\definecolor [gray35] [s=0.35]
+\definecolor [grey35] [gray35]
+\definecolor [gray36] [s=0.36]
+\definecolor [grey36] [gray36]
+\definecolor [gray37] [s=0.37]
+\definecolor [grey37] [gray37]
+\definecolor [gray38] [s=0.38]
+\definecolor [grey38] [gray38]
+\definecolor [gray39] [s=0.39]
+\definecolor [grey39] [gray39]
+\definecolor [gray40] [s=0.40]
+\definecolor [grey40] [gray40]
+\definecolor [gray41] [s=0.41]
+\definecolor [grey41] [gray41]
+\definecolor [gray42] [s=0.42]
+\definecolor [grey42] [gray42]
+\definecolor [gray43] [s=0.43]
+\definecolor [grey43] [gray43]
+\definecolor [gray44] [s=0.44]
+\definecolor [grey44] [gray44]
+\definecolor [gray45] [s=0.45]
+\definecolor [grey45] [gray45]
+\definecolor [gray46] [s=0.46]
+\definecolor [grey46] [gray46]
+\definecolor [gray47] [s=0.47]
+\definecolor [grey47] [gray47]
+\definecolor [gray48] [s=0.48]
+\definecolor [grey48] [gray48]
+\definecolor [gray49] [s=0.49]
+\definecolor [grey49] [gray49]
+\definecolor [gray50] [s=0.50]
+\definecolor [grey50] [gray50]
+\definecolor [gray51] [s=0.51]
+\definecolor [grey51] [gray51]
+\definecolor [gray52] [s=0.52]
+\definecolor [grey52] [gray52]
+\definecolor [gray53] [s=0.53]
+\definecolor [grey53] [gray53]
+\definecolor [gray54] [s=0.54]
+\definecolor [grey54] [gray54]
+\definecolor [gray55] [s=0.55]
+\definecolor [grey55] [gray55]
+\definecolor [gray56] [s=0.56]
+\definecolor [grey56] [gray56]
+\definecolor [gray57] [s=0.57]
+\definecolor [grey57] [gray57]
+\definecolor [gray58] [s=0.58]
+\definecolor [grey58] [gray58]
+\definecolor [gray59] [s=0.59]
+\definecolor [grey59] [gray59]
+\definecolor [gray60] [s=0.60]
+\definecolor [grey60] [gray60]
+\definecolor [gray61] [s=0.61]
+\definecolor [grey61] [gray61]
+\definecolor [gray62] [s=0.62]
+\definecolor [grey62] [gray62]
+\definecolor [gray63] [s=0.63]
+\definecolor [grey63] [gray63]
+\definecolor [gray64] [s=0.64]
+\definecolor [grey64] [gray64]
+\definecolor [gray65] [s=0.65]
+\definecolor [grey65] [gray65]
+\definecolor [gray66] [s=0.66]
+\definecolor [grey66] [gray66]
+\definecolor [gray67] [s=0.67]
+\definecolor [grey67] [gray67]
+\definecolor [gray68] [s=0.68]
+\definecolor [grey68] [gray68]
+\definecolor [gray69] [s=0.69]
+\definecolor [grey69] [gray69]
+\definecolor [gray70] [s=0.70]
+\definecolor [grey70] [gray70]
+\definecolor [gray71] [s=0.71]
+\definecolor [grey71] [gray71]
+\definecolor [gray72] [s=0.72]
+\definecolor [grey72] [gray72]
+\definecolor [gray73] [s=0.73]
+\definecolor [grey73] [gray73]
+\definecolor [gray74] [s=0.74]
+\definecolor [grey74] [gray74]
+\definecolor [gray75] [s=0.75]
+\definecolor [grey75] [gray75]
+\definecolor [gray76] [s=0.76]
+\definecolor [grey76] [gray76]
+\definecolor [gray77] [s=0.77]
+\definecolor [grey77] [gray77]
+\definecolor [gray78] [s=0.78]
+\definecolor [grey78] [gray78]
+\definecolor [gray79] [s=0.79]
+\definecolor [grey79] [gray79]
+\definecolor [gray80] [s=0.80]
+\definecolor [grey80] [gray80]
+\definecolor [gray81] [s=0.81]
+\definecolor [grey81] [gray81]
+\definecolor [gray82] [s=0.82]
+\definecolor [grey82] [gray82]
+\definecolor [gray83] [s=0.83]
+\definecolor [grey83] [gray83]
+\definecolor [gray84] [s=0.84]
+\definecolor [grey84] [gray84]
+\definecolor [gray85] [s=0.85]
+\definecolor [grey85] [gray85]
+\definecolor [gray86] [s=0.86]
+\definecolor [grey86] [gray86]
+\definecolor [gray87] [s=0.87]
+\definecolor [grey87] [gray87]
+\definecolor [gray88] [s=0.88]
+\definecolor [grey88] [gray88]
+\definecolor [gray89] [s=0.89]
+\definecolor [grey89] [gray89]
+\definecolor [gray90] [s=0.90]
+\definecolor [grey90] [gray90]
+\definecolor [gray91] [s=0.91]
+\definecolor [grey91] [gray91]
+\definecolor [gray92] [s=0.92]
+\definecolor [grey92] [gray92]
+\definecolor [gray93] [s=0.93]
+\definecolor [grey93] [gray93]
+\definecolor [gray94] [s=0.94]
+\definecolor [grey94] [gray94]
+\definecolor [gray95] [s=0.95]
+\definecolor [grey95] [gray95]
+\definecolor [gray96] [s=0.96]
+\definecolor [grey96] [gray96]
+\definecolor [gray97] [s=0.97]
+\definecolor [grey97] [gray97]
+\definecolor [gray98] [s=0.98]
+\definecolor [grey98] [gray98]
+\definecolor [gray99] [s=0.99]
+\definecolor [grey99] [gray99]
+\definecolor [gray100] [s=1.00]
+\definecolor [grey100] [gray100]
+\definecolor [darkgrey] [s=0.66]
+\definecolor [darkgray] [darkgrey]
+\definecolor [darkblue] [h=00008b]
+\definecolor [darkcyan] [h=008b8b]
+\definecolor [darkmagenta] [h=8b008b]
+\definecolor [darkred] [h=8b0000]
+\definecolor [lightgreen] [h=90ee90]
+
+\endinput
diff --git a/tex/context/base/colo-xwi.tex b/tex/context/base/colo-xwi.tex
new file mode 100644
index 000000000..81e09d871
--- /dev/null
+++ b/tex/context/base/colo-xwi.tex
@@ -0,0 +1,142 @@
+%D \module
+%D [ file=colo-xwi,
+%D version=1995.01.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=X Windows,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 I've forgotten where I got these definitions from, but maybe
+%D they can be of use.
+
+\definecolor [aliceblue] [r=0.94,g=0.97,b=1.00]
+\definecolor [antiquewhite] [r=0.98,g=0.92,b=0.84]
+\definecolor [aquamarine] [r=0.50,g=1.00,b=0.83]
+\definecolor [azure] [r=0.94,g=1.00,b=1.00]
+\definecolor [beige] [r=0.96,g=0.96,b=0.86]
+\definecolor [bisque] [r=1.00,g=0.89,b=0.77]
+\definecolor [black] [s=0] % [r=0.00,g=0.00,b=0.00]
+\definecolor [blanchedalmond] [r=1.00,g=0.92,b=0.80]
+\definecolor [blue] [r=0.00,g=0.00,b=1.00]
+\definecolor [blueviolet] [r=0.54,g=0.17,b=0.89]
+\definecolor [brown] [r=0.65,g=0.16,b=0.16]
+\definecolor [burlywood] [r=0.87,g=0.72,b=0.53]
+\definecolor [cadetblue] [r=0.37,g=0.62,b=0.63]
+\definecolor [chartreuse] [r=0.50,g=1.00,b=0.00]
+\definecolor [chocolate] [r=0.82,g=0.41,b=0.12]
+\definecolor [coral] [r=1.00,g=0.50,b=0.31]
+\definecolor [cornflowerblue] [r=0.39,g=0.58,b=0.93]
+\definecolor [cornsilk] [r=1.00,g=0.97,b=0.86]
+\definecolor [cyan] [r=0.00,g=1.00,b=1.00]
+\definecolor [darkgoldenrod] [r=0.72,g=0.53,b=0.04]
+\definecolor [darkgreen] [r=0.00,g=0.39,b=0.00]
+\definecolor [darkkhaki] [r=0.74,g=0.72,b=0.42]
+\definecolor [darkolivegreen] [r=0.33,g=0.42,b=0.18]
+\definecolor [darkorange] [r=1.00,g=0.55,b=0.00]
+\definecolor [darkorchid] [r=0.60,g=0.20,b=0.80]
+\definecolor [darksalmon] [r=0.91,g=0.59,b=0.48]
+\definecolor [darkseagreen] [r=0.56,g=0.74,b=0.56]
+\definecolor [darkslateblue] [r=0.28,g=0.24,b=0.55]
+\definecolor [darkturquoise] [r=0.00,g=0.81,b=0.82]
+\definecolor [darkviolet] [r=0.58,g=0.00,b=0.83]
+\definecolor [deeppink] [r=1.00,g=0.08,b=0.58]
+\definecolor [deepskyblue] [r=0.00,g=0.75,b=1.00]
+\definecolor [dodgerblue] [r=0.12,g=0.56,b=1.00]
+\definecolor [firebrick] [r=0.70,g=0.13,b=0.13]
+\definecolor [floralwhite] [r=1.00,g=0.98,b=0.94]
+\definecolor [forestgreen] [r=0.13,g=0.55,b=0.13]
+\definecolor [gainsboro] [r=0.86,g=0.86,b=0.86]
+\definecolor [ghostwhite] [r=0.97,g=0.97,b=1.00]
+\definecolor [gold] [r=1.00,g=0.84,b=0.00]
+\definecolor [goldenrod] [r=0.85,g=0.65,b=0.13]
+\definecolor [green] [r=0.00,g=1.00,b=0.00]
+\definecolor [greenyellow] [r=0.68,g=1.00,b=0.18]
+\definecolor [honeydew] [r=0.94,g=1.00,b=0.94]
+\definecolor [hotpink] [r=1.00,g=0.41,b=0.71]
+\definecolor [indianred] [r=0.80,g=0.36,b=0.36]
+\definecolor [ivory] [r=1.00,g=1.00,b=0.94]
+\definecolor [khaki] [r=0.94,g=0.90,b=0.55]
+\definecolor [lavender] [r=0.90,g=0.90,b=0.98]
+\definecolor [lavenderblush] [r=1.00,g=0.94,b=0.96]
+\definecolor [lawngreen] [r=0.49,g=0.99,b=0.00]
+\definecolor [lemonchiffon] [r=1.00,g=0.98,b=0.80]
+\definecolor [lightblue] [r=0.68,g=0.85,b=0.90]
+\definecolor [lightcoral] [r=0.94,g=0.50,b=0.50]
+\definecolor [lightcyan] [r=0.88,g=1.00,b=1.00]
+\definecolor [lightgoldenrod] [r=0.93,g=0.87,b=0.51]
+\definecolor [lightgoldenrodyellow] [r=0.98,g=0.98,b=0.82]
+\definecolor [lightpink] [r=1.00,g=0.71,b=0.76]
+\definecolor [lightsalmon] [r=1.00,g=0.63,b=0.48]
+\definecolor [lightseagreen] [r=0.13,g=0.70,b=0.67]
+\definecolor [lightskyblue] [r=0.53,g=0.81,b=0.98]
+\definecolor [lightslateblue] [r=0.52,g=0.44,b=1.00]
+\definecolor [lightsteelblue] [r=0.69,g=0.77,b=0.87]
+\definecolor [lightyellow] [r=1.00,g=1.00,b=0.88]
+\definecolor [limegreen] [r=0.20,g=0.80,b=0.20]
+\definecolor [linen] [r=0.98,g=0.94,b=0.90]
+\definecolor [magenta] [r=1.00,g=0.00,b=1.00]
+\definecolor [maroon] [r=0.69,g=0.19,b=0.38]
+\definecolor [mediumaquamarine] [r=0.40,g=0.80,b=0.67]
+\definecolor [mediumblue] [r=0.00,g=0.00,b=0.80]
+\definecolor [mediumorchid] [r=0.73,g=0.33,b=0.83]
+\definecolor [mediumpurple] [r=0.58,g=0.44,b=0.86]
+\definecolor [mediumseagreen] [r=0.24,g=0.70,b=0.44]
+\definecolor [mediumslateblue] [r=0.48,g=0.41,b=0.93]
+\definecolor [mediumspringgreen] [r=0.00,g=0.98,b=0.60]
+\definecolor [mediumturquoise] [r=0.28,g=0.82,b=0.80]
+\definecolor [mediumvioletred] [r=0.78,g=0.08,b=0.52]
+\definecolor [midnightblue] [r=0.10,g=0.10,b=0.44]
+\definecolor [mintcream] [r=0.96,g=1.00,b=0.98]
+\definecolor [mistyrose] [r=1.00,g=0.89,b=0.88]
+\definecolor [moccasin] [r=1.00,g=0.89,b=0.71]
+\definecolor [navajowhite] [r=1.00,g=0.87,b=0.68]
+\definecolor [navy] [r=0.00,g=0.00,b=0.50]
+\definecolor [navyblue] [r=0.00,g=0.00,b=0.50]
+\definecolor [oldlace] [r=0.99,g=0.96,b=0.90]
+\definecolor [olivedrab] [r=0.42,g=0.56,b=0.14]
+\definecolor [orange] [r=1.00,g=0.65,b=0.00]
+\definecolor [orangered] [r=1.00,g=0.27,b=0.00]
+\definecolor [orchid] [r=0.85,g=0.44,b=0.84]
+\definecolor [palegoldenrod] [r=0.93,g=0.91,b=0.67]
+\definecolor [palegreen] [r=0.60,g=0.98,b=0.60]
+\definecolor [paleturquoise] [r=0.69,g=0.93,b=0.93]
+\definecolor [palevioletred] [r=0.86,g=0.44,b=0.58]
+\definecolor [papayawhip] [r=1.00,g=0.94,b=0.84]
+\definecolor [peachpuff] [r=1.00,g=0.85,b=0.73]
+\definecolor [peru] [r=0.80,g=0.52,b=0.25]
+\definecolor [pink] [r=1.00,g=0.75,b=0.80]
+\definecolor [plum] [r=0.87,g=0.63,b=0.87]
+\definecolor [powderblue] [r=0.69,g=0.88,b=0.90]
+\definecolor [purple] [r=0.63,g=0.13,b=0.94]
+\definecolor [red ] [r=1.00,g=0.00,b=0.00]
+\definecolor [rosybrown] [r=0.74,g=0.56,b=0.56]
+\definecolor [royalblue] [r=0.25,g=0.41,b=0.88]
+\definecolor [saddlebrown] [r=0.55,g=0.27,b=0.07]
+\definecolor [salmon] [r=0.98,g=0.50,b=0.45]
+\definecolor [sandybrown] [r=0.96,g=0.64,b=0.38]
+\definecolor [seagreen] [r=0.18,g=0.55,b=0.34]
+\definecolor [seashell] [r=1.00,g=0.96,b=0.93]
+\definecolor [sienna] [r=0.63,g=0.32,b=0.18]
+\definecolor [skyblue] [r=0.53,g=0.81,b=0.92]
+\definecolor [slateblue] [r=0.42,g=0.35,b=0.80]
+\definecolor [snow] [r=1.00,g=0.98,b=0.98]
+\definecolor [springgreen] [r=0.00,g=1.00,b=0.50]
+\definecolor [steelblue] [r=0.27,g=0.51,b=0.71]
+\definecolor [tan ] [r=0.82,g=0.71,b=0.55]
+\definecolor [thistle] [r=0.85,g=0.75,b=0.85]
+\definecolor [tomato] [r=1.00,g=0.39,b=0.28]
+\definecolor [turquoise] [r=0.25,g=0.88,b=0.82]
+\definecolor [violet] [r=0.93,g=0.51,b=0.93]
+\definecolor [violetred] [r=0.82,g=0.13,b=0.56]
+\definecolor [wheat] [r=0.96,g=0.87,b=0.70]
+\definecolor [white] [r=1.00,g=1.00,b=1.00]
+\definecolor [whitesmoke] [s=0.96] % [r=0.96,g=0.96,b=0.96]
+\definecolor [yellow] [r=1.00,g=1.00,b=0.00]
+\definecolor [yellowgreen] [r=0.60,g=0.80,b=0.20]
+
+\endinput
diff --git a/tex/context/base/cont-cs.tex b/tex/context/base/cont-cs.tex
new file mode 100644
index 000000000..f878920aa
--- /dev/null
+++ b/tex/context/base/cont-cs.tex
@@ -0,0 +1,39 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!cs]
+
+\loaduserspecifications
+
+\installlanguage [\s!en] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!sk] [\c!state=\v!start]
+\installlanguage [\s!cs] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-de.tex b/tex/context/base/cont-de.tex
new file mode 100644
index 000000000..460ca7eca
--- /dev/null
+++ b/tex/context/base/cont-de.tex
@@ -0,0 +1,44 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!de]
+
+\loaduserspecifications
+
+\installlanguage [\s!us] [\c!state=\v!start]
+\installlanguage [\s!gb] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!fr] [\c!state=\v!start]
+\installlanguage [\s!es] [\c!state=\v!start]
+\installlanguage [\s!nl] [\c!state=\v!start]
+\installlanguage [\s!it] [\c!state=\v!start]
+
+\installlanguage [deo] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-en.tex b/tex/context/base/cont-en.tex
new file mode 100644
index 000000000..e2b09ecbe
--- /dev/null
+++ b/tex/context/base/cont-en.tex
@@ -0,0 +1,46 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!en]
+
+\loaduserspecifications
+
+% Do we need more defaults? or maybe all languages?
+
+\installlanguage [\s!us] [\c!state=\v!start]
+\installlanguage [\s!gb] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!fr] [\c!state=\v!start]
+\installlanguage [\s!es] [\c!state=\v!start]
+\installlanguage [\s!pt] [\c!state=\v!start]
+\installlanguage [\s!it] [\c!state=\v!start]
+\installlanguage [\s!nl] [\c!state=\v!start]
+\installlanguage [\s!cs] [\c!state=\v!start]
+\installlanguage [\s!sk] [\c!state=\v!start]
+\installlanguage [\s!pl] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+% \prependtoks
+% \the \everysetupdocument
+% \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-err.tex b/tex/context/base/cont-err.tex
new file mode 100644
index 000000000..f01ce87aa
--- /dev/null
+++ b/tex/context/base/cont-err.tex
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=cont-err,
+%D version=2003.08.12,
+%D title=\CONTEXT\ System Files,
+%D subtitle=Just A warning,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+\writestatus\m!systems{no file 'cont-sys.tex', using 'cont-sys.rme' instead}
+
+\protect \endinput
diff --git a/tex/context/base/cont-fil.tex b/tex/context/base/cont-fil.tex
new file mode 100644
index 000000000..b295872ca
--- /dev/null
+++ b/tex/context/base/cont-fil.tex
@@ -0,0 +1,124 @@
+%D \module
+%D [ file=cont-fil,
+%D version=1997.11.15,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=File Synonyms,
+%D author=J. Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 File Synonyms}
+
+\definefilesynonym [chemie] [chemic]
+\definefilesynonym [chemics] [chemic]
+
+\definefilesynonym [unit] [units]
+\definefilesynonym [eenheid] [units]
+\definefilesynonym [einheit] [units]
+
+\definefilesynonym [pstric] [pstricks]
+\definefilesynonym [pstrick] [pstricks]
+
+\definefilesynonym [finance] [financ]
+
+\definefilesynonym [con-01] [contml] % will go away
+
+%definefilesynonym [sch-base] [sch-00]
+%definefilesynonym [sch-make] [sch-01]
+
+\definefilesynonym [dir-make] [dir-01]
+\definefilesynonym [dir-identify] [dir-05]
+
+\definefilesynonym [xml-format] [xml-01]
+\definefilesynonym [xml-pretty] [xml-02]
+\definefilesynonym [xml-analyze] [xml-11]
+
+\definefilesynonym [int-load] [set-11]
+\definefilesynonym [int-make] [set-12]
+
+\definefilesynonym [fig-base] [fig-00]
+\definefilesynonym [fig-make] [fig-01]
+\definefilesynonym [fig-fake] [fig-02]
+\definefilesynonym [fig-missing] [fig-06]
+
+\definefilesynonym [exi-interface] [exi-21]
+
+\definefilesynonym [res-make] [res-01]
+\definefilesynonym [res-base] [res-04]
+\definefilesynonym [res-crop] [res-07]
+\definefilesynonym [res-trace] [res-08]
+\definefilesynonym [res-log] [res-09]
+\definefilesynonym [res-identify] [res-12]
+
+\definefilesynonym [med-show] [res-50]
+
+\definefilesynonym [pre-general] [pre-00]
+
+\definefilesynonym [pre-original] [pre-01]
+\definefilesynonym [pre-green] [pre-02]
+\definefilesynonym [pre-funny] [pre-03]
+\definefilesynonym [pre-colorful] [pre-04]
+\definefilesynonym [pre-fuzzy] [pre-05]
+\definefilesynonym [pre-polish] [pre-06]
+\definefilesynonym [pre-spider] [pre-07]
+\definefilesynonym [pre-wonder] [pre-08]
+\definefilesynonym [pre-windows] [pre-09]
+\definefilesynonym [pre-grow] [pre-10]
+\definefilesynonym [pre-stack] [pre-11]
+\definefilesynonym [pre-arrows] [pre-12]
+\definefilesynonym [pre-writing] [pre-13]
+\definefilesynonym [pre-split] [pre-14]
+\definefilesynonym [pre-balls] [pre-15]
+\definefilesynonym [pre-knot] [pre-16]
+\definefilesynonym [pre-weird] [pre-17]
+\definefilesynonym [pre-shade] [pre-18]
+\definefilesynonym [pre-organic] [pre-19]
+\definefilesynonym [pre-speckle] [pre-20]
+\definefilesynonym [pre-zoom] [pre-21]
+\definefilesynonym [pre-cycle] [pre-22]
+\definefilesynonym [pre-super] [pre-23]
+
+%definefilesynonym [pre-more] [pre-24]
+%definefilesynonym [pre-more] [pre-25]
+
+\definefilesynonym [pre-more] [pre-26]
+
+%definefilesynonym [pre-more] [pre-27]
+%definefilesynonym [pre-more] [pre-28]
+%definefilesynonym [pre-more] [pre-29]
+%definefilesynonym [pre-more] [pre-30]
+
+\definefilesynonym [pre-stepwise] [pre-60]
+\definefilesynonym [pre-stepper] [pre-61]
+
+\definefilesynonym [pre-punk] [pre-70]
+\definefilesynonym [pre-random] [pre-71]
+
+\definefilesynonym [abr-pseudocaps] [abr-01]
+\definefilesynonym [abr-smallcaps] [abr-02]
+
+\definefilesynonym [chinese] [chi-00]
+\definefilesynonym [japanese] [jap-00]
+
+%definefilesynonym [chi-simplified] [chi-01]
+%definefilesynonym [chi-traditional] [chi-02]
+
+\definefilesynonym [greek] [grk-00]
+
+\definefilesynonym [unic-chi] [unic-cjk]
+\definefilesynonym [unic-jap] [unic-cjk]
+
+%definefilesynonym [practexjournal] [ptj-01]
+\definefilesynonym [pracjourn] [ptj-01]
+
+\definefilesynonym [maps] [map-10]
+\definefilesynonym [map-se] [map-10] % for some time
+
+\definefilesynonym [mml] [mathml]
+\definefilesynonym [cml] [chemml]
+
+\endinput
diff --git a/tex/context/base/cont-fr.tex b/tex/context/base/cont-fr.tex
new file mode 100644
index 000000000..d812b28f9
--- /dev/null
+++ b/tex/context/base/cont-fr.tex
@@ -0,0 +1,42 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!fr]
+
+\loaduserspecifications
+
+\installlanguage [\s!us] [\c!state=\v!start]
+\installlanguage [\s!gb] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!fr] [\c!state=\v!start]
+\installlanguage [\s!es] [\c!state=\v!start]
+\installlanguage [\s!nl] [\c!state=\v!start]
+\installlanguage [\s!it] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-gb.tex b/tex/context/base/cont-gb.tex
new file mode 100644
index 000000000..99d297425
--- /dev/null
+++ b/tex/context/base/cont-gb.tex
@@ -0,0 +1,42 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!gb]
+
+\loaduserspecifications
+
+\installlanguage [\s!us] [\c!state=\v!start]
+\installlanguage [\s!gb] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!fr] [\c!state=\v!start]
+\installlanguage [\s!es] [\c!state=\v!start]
+\installlanguage [\s!nl] [\c!state=\v!start]
+\installlanguage [\s!it] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-it.tex b/tex/context/base/cont-it.tex
new file mode 100644
index 000000000..2141e3bc9
--- /dev/null
+++ b/tex/context/base/cont-it.tex
@@ -0,0 +1,41 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!it]
+
+\loaduserspecifications
+
+\installlanguage [\s!us] [\c!state=\v!start]
+\installlanguage [\s!gb] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!fr] [\c!state=\v!start]
+\installlanguage [\s!es] [\c!state=\v!start]
+\installlanguage [\s!it] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-log.tex b/tex/context/base/cont-log.tex
new file mode 100644
index 000000000..9bfec2999
--- /dev/null
+++ b/tex/context/base/cont-log.tex
@@ -0,0 +1,359 @@
+%D \module
+%D [ file=cont-log,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=\TEX\ Logos,
+%D author=J. Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 TeX Logos}
+
+%D The system that is used to typeset this text is called \TEX,
+%D typeset with an lowered~E. From te beginning of \TEX,
+%D authors of macro packages adapted this raising and lowering
+%D style. In this module we define some of those logos.
+%D Watch the \type{cmr} detection hack.
+
+\unprotect
+
+\defconvertedargument\someCMRfont{cmr} % hm, we now have lm
+
+% \def\doifCMRfontelse#1#2%
+% {\doifinstringelse{\someCMRfont}{\fontname\font}
+% {\def\next{#1}}
+% {\def\next{#2}}%
+% \next}
+
+\def\doifCMRfontelse
+ {\doifinstringelse\someCMRfont{\fontname\font}}
+
+\unexpanded\def\CMRkern
+ {\doifCMRfontelse\kern{\scratchdimen=}}
+
+% \def\TeX
+% {T%
+% \kern-.1667em\lower.5ex\hbox{E}%
+% \kern-.125emX}
+
+\def\Mkern#1%
+ {{\setbox\scratchbox\hbox{M}\kern#1\wd\scratchbox}}
+
+\unexpanded\def\TeX
+ {T%
+ \Mkern{-.1667}\lower.5ex\hbox{E}%
+ \Mkern{-.125}X}
+
+\unexpanded\def\ConTeXt
+ {C%
+ \CMRkern-.0333emo%
+ \CMRkern-.0333emn%
+% \CMRkern-.1667em\TeX%
+ \CMRkern-.0667em\TeX%
+ \CMRkern-.0333emt}
+
+\unexpanded\def\PPCHTeX
+ {ppch\TeX}
+
+\unexpanded\def\PRAGMA
+ {Pragma ADE}
+
+%\def\LaTeX
+% {L%
+% \kern-.30em\raise.3ex\hbox{\txx A}%
+% \kern-.18em\TeX}
+
+\unexpanded\def\LaTeX % requested by erik frambach
+ {{\setbox\scratchbox\hbox{L}%
+ \scratchdimen\ht\scratchbox
+ \setbox\scratchbox\hbox{\txx A}%
+ L\kern-.55\wd\scratchbox
+ \raise\scratchdimen\hbox{\lower\ht\scratchbox\copy\scratchbox}%
+ \kern-.2\wd\scratchbox\TeX}}
+
+\unexpanded\def\TaBlE
+ {T%
+ \kern-.27em\lower.5ex\hbox{A}%
+ \kern-.18emB%
+ \kern-.1em\lower.5ex\hbox{L}%
+ \kern-.075emE}
+
+\unexpanded\def\PiCTeX
+ {P%
+ \kern-.12em\lower.5ex\hbox{I}%
+ \kern-.075em C%
+ \kern-.11em\TeX}
+
+\def\AMSswitch#1%
+ {$\cal\ifdim\bodyfontsize>1.1em\scriptstyle\fi#1$}
+
+\unexpanded\def\AmSTeX
+ {\AMSswitch A%
+ \kern-.1667em\lower.5ex\hbox{\AMSswitch M}%
+ \kern-.125em\AMSswitch S%
+ -\TeX}
+
+\unexpanded\def\LamSTeX
+ {L%
+ \kern-.4em\raise.3ex\hbox{\AMSswitch A}%
+ \kern-.25em\lower.4ex\hbox{\AMSswitch M}%
+ \kern-.1em{\AMSswitch S}%
+ -\TeX}
+
+\unexpanded\def\AmSLaTeX
+ {\AMSswitch A%
+ \kern-.1667em\lower.5ex\hbox{\AMSswitch M}%
+ \kern-.125em\AMSswitch S%
+ -\LaTeX}
+
+%D Alternative \CONTEXT\ logo, first Idris S.~Hamid's version:
+%D
+%D \def\Context
+%D {{\sc C\kern -.0667emo\kern -.0667emn\kern -.0549emt\kern
+%D -.1667em\lower.5ex\hbox {e}\kern -.125emx\kern -.0549emt}}
+%D
+%D I changed this into one that adapts itself:
+
+\unexpanded\def\Context
+ {{C\kern -.0667em\getscaledglyph{.8}\empty{O\kern -.0667emN\kern
+ -.0549emT\doifitalicelse{\kern-.1em}{\kern-.1667em}\lower.5ex\hbox
+ {E}\doifitalicelse\empty{\kern-.11em}X\kern-.055emT}}}
+
+%D The \METAFONT\ and \METAPOST\ logos adapt themselves to the
+%D current fontsize, an ugly but usefull hack.
+
+% rather hard coded
+%
+% \loadmapfile[original-base.map] % \loadmapfile[original-vogel-symbol]
+%
+% \unexpanded\def\setMFPfont
+% {\font\logofont=logo%
+% \ifnum\fam=\bffam\c!bf\else
+% \ifnum\fam=\slfam\c!sl\else
+% \ifnum\fam=\itfam\c!sl\else
+% \ifnum\fam=\bsfam\c!bf\else
+% \ifnum\fam=\bifam\c!bf\else
+% \fi\fi\fi\fi\fi
+% 10 at \currentfontscale\bodyfontsize
+% \logofont}
+%
+% or:
+%
+% \definefontsynonym [MetaLogo] [logo10]
+% \definefontsynonym [MetaLogoBold] [logobf10]
+% \definefontsynonym [MetaLogoSlanted] [logosl10]
+% \definefontsynonym [MetaLogoItalic] [logosl10]
+% \definefontsynonym [MetaLogoBoldSlanted] [logobf10]
+% \definefontsynonym [MetaLogoBoldtalic] [logobf10]
+%
+% \loadmapfile[original-base.map] % \loadmapfile[original-vogel-symbol]
+%
+% \def\setMFPfont{\symbolicfont{MetaLogo}}
+
+\let\logofont\nullfont
+
+\loadmapfile[original-base.map]
+
+\unexpanded\def\setMFPfont% more sensitive for low level changes
+ {\font\logofont=logo%
+ \ifx\fontalternative\c!bf\else
+ \ifx\fontalternative\c!it\else
+ \ifx\fontalternative\c!sl\else
+ \ifx\fontalternative\c!bi\else
+ \ifx\fontalternative\c!bs\else
+ \fi\fi\fi\fi\fi
+ 10 at \currentfontscale\bodyfontsize
+ \logofont}
+
+%\unexpanded\def\MetaFont%
+% {\hbox{\setMFPfont METAFONT}}
+%
+%\unexpanded\def\MetaPost%
+% {\hbox{\setMFPfont METAPOST}}
+
+\def\MetaHyphen% there is no hyphenchar in this font
+ {\discretionary{\vrule\!!height.33em\!!depth-.27em\!!width.33em}{}{}}
+
+\unexpanded\def\MetaFont
+ {{\setMFPfont META\MetaHyphen FONT}}
+
+\unexpanded\def\MetaPost
+ {{\setMFPfont META\MetaHyphen POST}}
+
+\unexpanded\def\MetaFun
+ {MetaFun}
+
+%D \macros
+%D {TEX, METAFONT, METAPOST, METAFUN,
+%D PICTEX, TABLE,
+%D CONTEXT, PPCHTEX,
+%D AMSTEX, LATEX, LAMSTEX}
+%D
+%D We define the funny written ones as well as th eless
+%D error prone upper case names (in \CONTEXT\ we tend to
+%D write all user defined commands, like abbreviations, in
+%D uppercase.)
+
+\unexpanded\def\METAFONT {\MetaFont}
+\unexpanded\def\METAPOST {\MetaPost}
+\unexpanded\def\PPCHTEX {\PPCHTeX}
+\unexpanded\def\CONTEXT {\ConTeXt}
+\unexpanded\def\METAFUN {\MetaFun}
+
+\unexpanded\def\TEX {\TeX}
+\unexpanded\def\LATEX {\LaTeX}
+\unexpanded\def\PICTEX {\PiCTeX}
+\unexpanded\def\TABLE {\TaBlE}
+\unexpanded\def\AMSTEX {\AmSTeX}
+\unexpanded\def\LAMSTEX {\LamSTeX}
+\unexpanded\def\INRSTEX {inrs\TeX}
+
+%D And this is how they show up: \TeX, \MetaFont, \MetaPost,
+%D \PiCTeX, \TaBlE, \ConTeXt, \PPCHTeX, \AmSTeX, \LaTeX,
+%D \LamSTeX.
+
+% \def\TEXEDIT {\TeX edit}
+% \def\TEXFORM {\TeX form}
+% \def\TEXADRES {\TeX adres}
+% \def\TEXSPELL {\TeX spell}
+% \def\TEXUTIL {\TeX util}
+% \def\TEXEXEC {\TeX exec}
+
+%D Some placeholders:
+
+\unexpanded\def\eTeX {\mathematics{\varepsilon}-\TeX}
+\unexpanded\def\pdfTeX {pdf\TeX}
+\unexpanded\def\pdfeTeX{pdfe-\TeX}
+\unexpanded\def\luaTeX {lua\TeX}
+\unexpanded\def\metaTeX{meta\TeX}
+\unexpanded\def\XeTeX {X\lower.5ex\hbox{\kern-.15em\mirror{E}}\kern-.1667em\TeX}
+
+% Better, since lm has a mirrored E (don't ask me why)
+
+% \unexpanded\def\XeTeX
+% {X\lower.5ex
+% \hbox
+% {\kern-.15em
+% \ifx\XeTeXcharglyph\undefined
+% \mirror{E}%
+% \else\ifcase\XeTeXcharglyph"018E\relax
+% \mirror{E}%
+% \else
+% \char"018E%
+% \fi}%
+% \kern-.1667em \TeX}
+
+% Adapted from a patch by Mojca:
+
+\def\@XeTeX@
+ {\setbox\scratchbox\hbox{E}%
+ \raise\dimexpr\ht\scratchbox+\dp\scratchbox\relax\hbox{\rotate[\c!rotation=180]{\box\scratchbox}}}
+
+\ifnum\texengine=\pdftexengine
+
+ \unexpanded\def\XeTeX
+ {X\lower.5ex
+ \hbox
+ {\kern-.15em
+ \ifx\fontalternative\c!bf\mirror{E}\else
+ \ifx\fontalternative\c!it \@XeTeX@\else
+ \ifx\fontalternative\c!sl \@XeTeX@\else
+ \ifx\fontalternative\c!bi \@XeTeX@\else
+ \ifx\fontalternative\c!bs \@XeTeX@\else
+ \mirror{E}\fi\fi\fi\fi\fi}%
+ \kern-.1667em \TeX}
+
+\else
+
+ \unexpanded\def\XeTeX
+ {X\lower.5ex
+ \hbox
+ {\kern-.15em
+ \iffontchar\font"018E\relax
+ \char"018E%
+ \else
+ \ifx\fontalternative\c!bf\mirror{E}\else
+ \ifx\fontalternative\c!it \@XeTeX@\else
+ \ifx\fontalternative\c!sl \@XeTeX@\else
+ \ifx\fontalternative\c!bi \@XeTeX@\else
+ \ifx\fontalternative\c!bs \@XeTeX@\else
+ \mirror{E}\fi\fi\fi\fi\fi
+ \fi}%
+ \kern-.1667em \TeX}
+
+\fi
+
+\let\ETEX \eTeX
+\let\PDFTEX \pdfTeX
+\let\PDFETEX\pdfeTeX
+\let\LUATEX \luaTeX
+\let\LuaTeX \luaTeX
+\let\XETEX \XeTeX
+
+\unexpanded\def\MkApproved
+ {\dontleavehmode\rotate
+ [\c!rotation={\ifnum\texengine=\luatexengine\ctxlua{tex.write(45-45*\the\luatexversion/100)}\else0\fi},
+ \c!align=\v!middle,
+ \c!foregroundstyle=\v!type,
+ \c!foregroundcolor=darkred,
+ \c!frame=\v!on,
+ \c!offset=1ex,
+ \c!background=\v!color,
+ \c!backgroundcolor=lightgray,
+ \c!framecolor=darkred,
+ \c!rulethickness=2pt]
+ {Mk\ifnum\texengine=\luatexengine IV\else II\fi\\approved}}
+
+
+% \unexpanded\def\luaTeX
+% {\dontleavehmode\begingroup
+% Lua%
+% \setbox0\hbox{oT}%
+% \setbox2\hbox{o\kern0ptT}%
+% \ifdim\wd0=\wd2
+% \setbox0\hbox dir TRT{To}%
+% \setbox2\hbox{T\kern0pto}%
+% \hskip\dimexpr\wd0-\wd2\relax
+% \fi
+% \TeX
+% \endgroup}
+%
+% a further iteration from the list, patched again
+
+% \ifx\fontalternative\c!it -\else
+% \ifx\fontalternative\c!sl -\else
+% \ifx\fontalternative\c!bi -\else
+% \ifx\fontalternative\c!bs -\fi\fi\fi\fi
+
+\def\LuaTeX
+ {\dontleavehmode
+ \begingroup
+ Lua%
+ % hope for kerning, try aT
+ \setbox0\hbox{aT}%
+ \setbox2\hbox{a\kern\zeropoint T}%
+ \ifdim\wd0=\wd2 % kerns can go two ways
+ % no aT kerning, try oT as a is not symmetrical
+ \setbox0\hbox{oT}%
+ \setbox2\hbox{o\kern\zeropoint T}%
+ \ifdim\wd0=\wd2 % kerns can go two ways
+ % no aT and oT kerning, try To
+ \setbox0\hbox{To}%
+ \setbox2\hbox{T\kern\zeropoint o}%
+ % maybe we need to compensate for the angle (sl/it/bs/bi)
+ \fi
+ \ifdim\wd0=\wd2\else
+ \kern\dimexpr\wd0-\wd2\relax
+ \fi
+ \fi
+ \TeX
+ \endgroup}
+
+\let\luaTeX \LuaTeX
+\let\LUATEX \LuaTeX
+
+\protect \endinput
diff --git a/tex/context/base/cont-mtx.tex b/tex/context/base/cont-mtx.tex
new file mode 100644
index 000000000..833785a7f
--- /dev/null
+++ b/tex/context/base/cont-mtx.tex
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=cont-mtx,
+%D version=2006.01.01, % no date -)
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Experimental MetaTeX Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% format generation : texexec --make --all --luatex
+%
+% pdftex compatible run : texexec --luatex filename
+% aleph compatible run : texexec --luatex --output=dvipdfmx filename
+%
+% or, at top of tex file : % engine=luatex
+
+% \loadcorefile{meta-xxx.tex}
+
+%D Here we load files that are not yet part of the core.
+
+\endinput
diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii
new file mode 100644
index 000000000..2defba6d7
--- /dev/null
+++ b/tex/context/base/cont-new.mkii
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=cont-new,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=New Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\enablemode[mkii]
+
+\long\def\startluacode#1\stopluacode{}
+\long\def\ctxlua #1{}
+
+\def\enabletrackers [#1]{}
+\def\disabletrackers[#1]{}
+
+\endinput
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
new file mode 100644
index 000000000..6269e5a61
--- /dev/null
+++ b/tex/context/base/cont-new.mkiv
@@ -0,0 +1,40 @@
+%D \module
+%D [ file=cont-new,
+%D version=2006.10.04,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=New Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% potential new defaults:
+%
+% \setbreakpoints[compound]
+
+\unprotect
+
+\ctxlua{logs.report = commands.report} % this will become default
+
+\def\immediatemessage#1{\ctxlua{commands.writestatus("message","#1")}}
+
+% we need to figure this out (to be discussed)
+
+\unexpanded\def\textminus
+ {\char \iffontchar\font"2012 "2012 % figuredash
+ \else\iffontchar\font"2013 "2013 % endash
+ \else\iffontchar\font"2212 "2212 % math minus
+ "002D % hyphen
+ \fi\fi\fi}
+
+\unexpanded\def\textplus
+ {\char"002B } % plus
+
+% till we fixed all styles
+
+\let\\=\crlf
+
+\protect \endinput
diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex
new file mode 100644
index 000000000..9c4fdba18
--- /dev/null
+++ b/tex/context/base/cont-new.tex
@@ -0,0 +1,992 @@
+%D \module
+%D [ file=cont-new,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=New Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\newcontextversion{2010.05.24 13:05}
+
+%D This file is loaded at runtime, thereby providing an
+%D excellent place for hacks, patches, extensions and new
+%D features.
+
+\unprotect
+
+% it's about time to clean up this file ...
+
+\writestatus\m!systems{beware: some patches loaded from cont-new.tex}
+
+% \ifx\pdfmapfile \undefined \else \pdfmapfile{ } \fi
+
+% \font\f=dummyfont \rpcode\f0=500 \hbox{..}\char0
+% todo: mp-new
+% caption: grid=top|bottom in xml defs
+
+\def\fastscale#1%
+ {\begingroup
+ \ifnum#1=1000\relax
+ \setfalse\scaleboxdone
+ \else
+ \settrue\scaleboxdone
+ \edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1pt/1000\relax}%
+ \let\finalscaleboxyscale\finalscaleboxxscale
+ \fi
+ \dowithnextbox{\doscaleboxindeed\flushnextbox\endgroup}\hbox}
+
+% \setupcaption [figure] [align=flushleft]
+% \setupcaption [figure-1] [align=flushleft,leftmargin=10mm]
+% \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth]
+%
+% \startsetups somefigure
+% \ifdim\floatsetupwidth>\textwidth
+% \placesetupfloat[figure-2]
+% \else
+% \placesetupfloat[figure-1]
+% \fi
+% \stopsetups
+%
+% \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]}
+
+\def\placefloatwithsetups
+ {\dotripleempty\doplacefloatwithsetups}
+
+\long\def\doplacefloatwithsetups[#1][#2][#3]#4%
+ {\def\floatsetupcaption {#4}%
+ \def\floatsetupcontent {\copy\nextbox}%
+ \def\floatsetupwidth {\wd\nextbox}%
+ \def\floatsetupheight {\ht\nextbox}%
+ \def\placesetupfloat[##1]{\placefloat[##1][#2][#3]{#4}{\floatsetupcontent}}% #4 and not \floatsetupcaption (unexpanded)
+ \dowithnextbox{\setups[#1]}\vbox}
+
+\def\dividedsize#1#2#3% size gap n
+ {\dimexpr
+ \ifnum\dimexpr#1\relax>\plusone
+ (\dimexpr#1\relax-\numexpr#3-1\relax\dimexpr#2\relax)/#3\else#1%
+ \fi
+ \relax}
+
+% \setuplabeltext[\s!itemcount1={{I(},{)}}]
+% \def\labeledcountervalue#1{\labeltexts{#1}{\countervalue{#1}}}
+
+\def\singlewidened #1{\hbox spread 1em{\hss#1\hss}}
+\def\complexwidened[#1]#2{\hbox spread #1{\hss#2\hss}}
+
+\definecomplexorsimple\widened
+
+% todo
+%
+% \def\definelocation{\dodoubleargument\dodefinelocation}
+% \def\dodefinelocation[#1][#2]{\setvalue{loc:#1}{#2}}
+%
+% \definelocation[lt] [\v!left\v!top]
+% \definelocation[tl] [\v!left\v!top]
+% \definelocation[\v!top\v!left][\v!left\v!top]
+%
+% \def\getlocation#1{\executeifdefined{loc:#1}{#1}}
+
+% just in case we load something from a file (pdfr-ec for instance)
+
+\prependtoks \restoreendofline \to \everybeforeshipout
+
+\let\cs\getvalue
+
+% experimental so this may change
+
+\def\startdescriptions
+ {\dosingleempty\dostartdescriptions}
+
+\def\dostartdescriptions[#1]%
+ {\begingroup
+ \def\item{\getvalue{#1}}%
+ \let\dostoppairdescription \donothing
+ \let\@@description \dostartpairdescription
+ \let\@@startsomedescription\dostartsomedescription}
+
+\def\stopdescriptions
+ {\dostoppairdescription
+ \endgroup}
+
+\def\dostartpairdescription[#1][#2]%
+ {\dostoppairdescription
+ \def\dostoppairdescription{\@@stopdescription{#1}}%
+ \bgroup
+ \def\currentdescription{#1}%
+ \doifelse{\descriptionparameter{\s!do\c!state}}\v!start
+ {\@@makedescription{#1}[#2]{}}
+ {\@@makedescription{#1}[#2]}}
+
+\def\dostartsomedescription% #1[#2]#3%
+ {\bgroup
+ \@@makedescription} % {#1}[#2]{#3}}
+
+% \starttext
+%
+% \definedescription[test]
+%
+% \startdescriptions
+% \test{Foo} Bar bar bar
+% \test{Foo} Bar bar bar
+% \test{Foo} Bar bar bar
+% \stopdescriptions
+%
+% \startdescriptions[test]
+% \item{Foo} Bar bar bar
+% \item{Foo} Bar bar bar
+% \item{Foo} Bar bar bar
+% \stopdescriptions
+%
+% \startdescriptions
+% \starttest{Foo} Bar bar bar \stoptest
+% \starttest{Foo} Bar bar bar \stoptest
+% \starttest{Foo} Bar bar bar \stoptest
+% \stopdescriptions
+%
+% \startdescriptions[test]
+% \item{Foo} Bar bar bar
+% \item{Foo} Bar bar bar
+% \item{Foo} Bar bar bar
+% \stopdescriptions
+%
+% \stoptext
+
+% to do:
+%
+% \def\defineshapesynonym
+% {\dodoubleargument\dodefineshapesynonym}
+%
+% \def\dodefineshapesynonym[#1][#2]%
+% {\setvalue{shsy:#1}{#2}}
+%
+% \def\shapesynonym#1%
+% {\ifcsname shsy:#1\endcsname
+% \expandafter\shapesynonym\csname shsy:#1\endcsname\else#1%
+% \fi}
+%
+%\defineshapesynonym[eacute] [e]
+%\defineshapesynonym[egrave] [e]
+%\defineshapesynonym[eumlaut [e]
+%\defineshapesynonym[eogonek][e]
+%
+% more reduction
+%
+%\defineshapesynonym[e][o]
+%\defineshapesynonym[w][v]
+%\defineshapesynonym[m][n]
+%
+% \shapesynonym{eacute}
+
+% this will be activated when
+
+% \newinsert\thispageinsert % <- installinsertion
+
+% \def\flushatthispage
+% {\bgroup
+% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}%
+% \hbox}
+
+% \appendtoks
+% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi
+% \to \everyshipout
+
+% \definemarkedpage[nobackgrounds]
+% \markpage[nobackgrounds]
+% \doifmarkedpageelse{nobackgrounds}
+
+\newcounter\nofmarkedpages
+
+\def\definemarkedpage[#1]%
+ {\definetwopasslist{\v!page:#1}}
+
+\def\markpage[#1]% looks very much like domarginreference
+ {\iftrialtypesetting\else
+ \doglobal\increment\nofmarkedpages\relax
+ \lazysavetwopassdata{\v!page:#1}{\nofmarkedpages}{\noexpand\realfolio}%
+ \fi}
+
+\def\doifmarkedpageelse#1%
+ {\gettwopassdatalist{\v!page:#1}%
+ \expanded{\doifinsetelse{\realfolio}{\twopassdatalist}}}
+
+% Just a simple and fast hanger, for usage in macros.
+
+\def\setuphanging
+ {\dodoubleempty\getparameters[\??ha]}
+
+\setuphanging
+ [\c!distance=.5em]
+
+\def\starthanging
+ {\noindent\bgroup
+ \dowithnextbox
+ {\setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}%
+ \hangindent\nextboxwd
+ \hangafter\plusone
+ \flushnextbox\ignorespaces}
+ \hbox}
+
+\def\stophanging
+ {\endgraf
+ \egroup}
+
+% experimental
+
+\def\stophangaround
+ {\endgraf
+ \egroup}
+
+\def\starthangaround
+ {\noindent\bgroup
+ \dowithnextbox
+ {\ifdim\nextboxht>\strutht\setbox\nextbox\tbox{\flushnextbox}\fi
+ \setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}%
+ \getboxheight\scratchdimen\of\box\nextbox
+ \getnoflines\scratchdimen
+ \nextboxht\strutht
+ \nextboxdp\strutdp
+ \hangindent\nextboxwd
+ \hangafter-\noflines
+ \llap{\flushnextbox}\ignorespaces}
+ \hbox}
+
+\def\modevalue#1#2#3%
+ {\@EA\ifx\csname\@mode@\systemmodeprefix#1\endcsname\endcsname\enabledmode#2\else#2\fi}
+
+\def\systemmodevalue#1%
+ {\modevalue{\systemmodeprefix#1}}
+
+% \getmulticolumnlines -> now in cont-loc, to be tested and really needed
+
+% \tracefonthandlingtrue
+
+% new, still to be improved
+%
+% \dorecurse{10}
+% {\input thuan
+% \placefigure{}{\framed[height=1.5cm]{test}}
+% \placefloatplaceholder}
+
+\def\placefloatplaceholder
+ {\ifroomforfloat \else
+ \scratchdimen\pagegoal
+ \advance\scratchdimen-\pagetotal
+ \advance\scratchdimen-3\lineheight
+ \ifdim\scratchdimen>\zeropoint
+ \startlinecorrection[blank]
+ \mhbox{\inframed{\labeltexts{placeholder}{\lastcaptiontag}}}%
+ \stoplinecorrection
+ \else
+ \allowbreak
+ \fi
+ \fi}
+
+\setuplabeltext
+ [placeholder={, moved}]
+
+% etex only, of course we could just parse (scan for \% in string)
+
+\newif\ifpercentdimendone
+
+\bgroup % usage: \setpercentdimen\somedimen{% or dimen} todo: pct
+\catcode124=\@@comment
+\catcode 37=\@@active
+\gdef\setpercentdimen#1#2|
+ {\xdef\@@expanded{#2}|
+ \ifx\@@expanded\empty\else
+ \bgroup
+ \global\percentdimendonefalse
+ \def\%{\dimexpr#1/100\relax\global\percentdimendonetrue\ignorespaces}| scantokens add's a space
+ \catcode`%=\@@active
+ \catcode`\\=\@@escape
+ \let%\%|
+ \scratchdimen#1|
+ \xdef\@@expanded{\@@expanded\scratchdimen\!!zeropoint}| trick: when 1.2 => .2\scratchdimen and 0pt typeset
+ \startnointerference
+ \global\globalscratchdimen\scantokens\@EA{\@@expanded}| i'm lazy and use etex
+ \stopnointerference
+ \egroup
+ #1\globalscratchdimen
+ \fi}
+\egroup
+
+% TEX alternative, in principle accurate enough and also a bit faster
+
+% \bgroup
+%
+% \catcode`\%=\@@other
+% \catcode`\|=\@@comment
+%
+% \gdef\setpercentdimen#1#2|
+% {\beforesplitstring#2\at%\to\ascii
+% \doifelse\ascii{#2}
+% {#1=#2}
+% {\divide#1by100\relax#1=\ascii#1\relax}} | or: {#1=\ascii#1\divide#1by100\relax}}
+%
+% \egroup
+%
+% \dimen0=1000pt \setpercentdimen{\dimen0}{10%} \the\dimen0
+% \dimen0= 100pt \setpercentdimen{\dimen0}{10%} \the\dimen0
+% \dimen0= 95pt \setpercentdimen{\dimen0}{10%} \the\dimen0
+% \dimen0= 10pt \setpercentdimen{\dimen0}{10%} \the\dimen0
+% \dimen0= 1pt \setpercentdimen{\dimen0}{10%} \the\dimen0
+
+\bgroup
+
+\obeylines % don't remove %'s !
+
+\gdef\collapsedspace#1%
+ {\ifx#1^^M%
+ \expandafter\collapsedspace
+ \else
+ \space
+ \expandafter#1%
+ \fi}
+
+\gdef\collapsespaces
+ {\prependtoksonce\relax\to\everyeof%
+ \ignorelines%
+ \ignoretabs%
+ \let\obeyedspace\collapsedspace%
+ \obeyspaces}
+
+\egroup
+
+\def\inlinedbox
+ {\bgroup
+ \dowithnextbox
+ {\scratchdimen\nextboxht
+ \advance\scratchdimen\nextboxdp
+ \advance\scratchdimen-\lineheight
+ \divide\scratchdimen\plustwo
+ \advance\scratchdimen\strutdepth
+ \setbox\nextbox\hbox{\lower\scratchdimen\flushnextbox}%
+ \nextboxht\strutht
+ \nextboxdp\strutdp
+ \flushnextbox
+ \egroup}%
+ \hbox}
+
+% \readfile{cont-exp}\donothing\donothing % speed up (5-20%)
+
+\def\dimenratio#1#2% etex only
+ {\withoutpt\the\dimexpr2\dimexpr(#1)/\dimexpr(#2)/32768\relax\relax}
+
+\def\doxprecurse#1#2%
+ {\ifnum#1=\zerocount % no \ifcase
+ \expandafter\gobblethreearguments
+ \else
+ #2\expandafter\expandafter\expandafter\doxprecurse\expandafter
+ \fi\expandafter{\the\numexpr#1-1\relax}{#2}}
+
+\def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie
+
+\unexpanded\def\asciistr#1{\dontleavehmode{\defconvertedargument\ascii{#1}\verbatimfont\ascii}}
+
+\def\shapefill{\vskip\zeropoint\!!plus\lineheight\!!minus\lineheight\relax}
+
+\let\normaltype\type
+
+\ifx\scantextokens\undefined
+ \ifx\scantokens\undefined
+ \unexpanded\def\retype#1{\dontleavehmode{\defconvertedargument\ascii{#1}\@EA\normaltype\@EA{\ascii}}}
+ \else
+ \unexpanded\def\retype#1{\dontleavehmode\scantokens{\normaltype{#1}\ignorespaces}\relax}
+ \fi
+\else
+ \unexpanded\def\retype#1{\dontleavehmode\scantextokens{\normaltype{#1}}}
+\fi
+
+\def\simplifytype{\let\type\retype}
+
+% \ruledhbox
+% {\startignorespaces
+% \def\oeps{a}
+% \startignorespaces
+% \def\oeps{a}
+% \stopignorespaces
+% \def\oeps{a}
+% \stopignorespaces
+% \oeps}
+
+\newsignal\boissignal
+\newcount \boislevel
+
+\long\def\startignorespaces
+ {\advance\boislevel\plusone
+ \ifcase\boislevel\or \ifhmode
+ \hskip\boissignal
+ \fi \fi
+ \ignorespaces}
+
+\long\def\stopignorespaces
+ {\ifcase\boislevel\or \ifhmode
+ \doloop
+ {\ifdim\lastskip=\zeropoint
+ \exitloop
+ \else\ifdim\lastskip=\boissignal
+ \unskip
+ \exitloop
+ \else
+ \unskip
+ \fi\fi}%
+ \fi \fi
+ \advance\boislevel\minusone}
+
+\def\minimalhbox#1#%
+ {\dowithnextbox
+ {\bgroup
+ \setbox\scratchbox\hbox#1{\hss}%
+ \ifdim\nextboxwd<\wd\scratchbox\nextboxwd\wd\scratchbox\fi
+ \flushnextbox
+ \egroup}
+ \hbox}
+
+% \def\dodimchoice#1#2#3%
+% {\ifx#3\relax
+% #1\@EA\gobbleuntilrelax
+% \else\ifdim#1#2%
+% #3\@EAEAEA\gobbleuntilrelax
+% \else
+% \@EAEAEA\dodimchoice
+% \fi\fi{#1}}
+
+% \def\donumchoice#1#2#3%
+% {\ifx#3\relax
+% #1\@EA\gobbleuntilrelax
+% \else\ifnum#1#2%
+% #3\@EAEAEA\gobbleuntilrelax
+% \else
+% \@EAEAEA\dodimchoice
+% \fi\fi{#1}}
+
+% \def\dimchoice#1#2{\dodimchoice{#1}#2\empty\relax}
+% \def\numchoice#1#2{\donumchoice{#1}#2\empty\relax}
+
+\def\gobbleuntilempty#1\empty{}
+
+\def\dodimchoice#1#2#3%
+ {\ifdim#1#2%
+ #3\@EA\gobbleuntilempty
+ \else
+ \@EA\dodimchoice
+ \fi{#1}}
+
+\def\donumchoice#1#2#3%
+ {\ifnum#1#2%
+ #3\@EA\gobbleuntilempty
+ \else
+ \@EA\dodimchoice
+ \fi{#1}}
+
+\def\dimchoice#1#2{\dodimchoice{#1}#2{=#1}{#1}\empty}
+\def\numchoice#1#2{\donumchoice{#1}#2{=#1}{#1}\empty}
+
+% \the\dimexpr(\dimchoice {7pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% \the\dimexpr(\dimchoice{11pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% \the\dimexpr(\dimchoice{14pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+
+\def\showsetupsdefinition[#1]{\showvalue{\??su:#1}} % temp hack for debugging
+
+% documentation : \setupregister[alternative=a|b|A|B]
+\unprotected \def\traceposstring#1#2#3%
+ {\iftracepositions
+ \smashedhbox%
+ {#1{\infofont#2#3}%
+ \scratchdimen.5\points
+ \kern-2\scratchdimen
+ \vrule\!!width4\scratchdimen\!!height\scratchdimen\!!depth\scratchdimen}%
+ \fi}
+
+% will be a MyWay
+%
+% \setuplayout[grid=yes] \setupcaption[figure][inbetween=] \useMPlibrary[dum] \setupcolors[state=start]
+%
+% \starttext \showgrid \showstruts
+%
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.4,grid=yes]}
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.4,grid=fit]}
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.4,grid=height]}
+% \input ward
+% \page
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.5,grid=yes]}
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.5,grid=fit]}
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.5,grid=height]}
+% \input ward
+% \page
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.6,grid=yes]}
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.6,grid=fit]}
+% \input ward \placefigure{}{\externalfigure[dummy][width=.5\hsize,lines=1.6,grid=height]}
+% \input ward
+% \page
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.4,grid=yes]}
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.4,grid=fit]}
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.4,grid=height]}
+% \input ward
+% \page
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.5,grid=yes]}
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.5,grid=fit]}
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.5,grid=height]}
+% \input ward
+% \page
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.6,grid=yes]}
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.6,grid=fit]}
+% \input ward \placefigure[none]{}{\externalfigure[dummy][width=.5\hsize,lines=1.6,grid=height]}
+% \input ward
+%
+% \stoptext
+
+% funny, as field action with e.g. dissolve ... only the field dissolves, bug?
+
+\setglobalsystemreference\rt!exec{Transition}{transition}
+
+%def\PDFexecutetransition {/Trans /Trans <>}
+\def\PDFexecutetransition {/Trans /Trans <<\executeifdefined{PDFpage\argumentA}\PDFpagereplace>>}
+
+% new, continuous blocks, \som \par \startdoorlopendblok ...
+
+% \startitemize
+% \item bagger
+% \item bagger
+% \item \startdoorlopendblok bagger \stopdoorlopendblok
+% \item \endgraf \startdoorlopendblok bagger \stopdoorlopendblok
+% \item \endgraf \startdoorlopendblok \strut bagger \stopdoorlopendblok
+% \item \startdoorlopendblok
+% \starttabulate
+% \NC test \NC test \NC \NR
+% \NC test \NC test \NC \NR
+% \NC test \NC test \NC \NR
+% \stoptabulate
+% \stopdoorlopendblok
+% \item test
+% \stopitemize
+
+\def\startdoorlopendblok % for special cases, don't change it too much and don't rely on it
+ {\ifhmode\endgraf\nobreak\fi % don't remove the \nobreak
+ \dowithnextboxcontent
+ {\setlocalhsize \hsize\localhsize \forgetall}
+ {\bgroup
+ \forgeteverypar
+ \forgetparskip
+ \scratchdimen\nextboxht
+ \advance\scratchdimen\nextboxdp
+ \getnoflines\scratchdimen
+ \advance\scratchdimen-\strutheight
+ \setbox\nextbox\hbox{\lower\scratchdimen\box\nextbox}%
+ \ht\nextbox\strutheight
+ \dp\nextbox\strutdepth
+ \setbox\nextbox\vbox
+ {\indent\box\nextbox
+ \endgraf
+ \nobreak
+ \advance\noflines\minusone
+ \dorecurse\noflines{\crlf\nobreak}}%
+ \verticalstrut
+ \endgraf
+ \nobreak
+ \offinterlineskip
+ \kern-2\lineheight % 2\lineheight when no vertical struts in main \vbox
+ \nobreak
+ \unvbox\nextbox
+ \prevdepth\strutdepth
+ % evt (eerst testen) een signal zodat een direct volgend blok goed gaat)
+ \egroup}
+ \vbox\bgroup
+ \vskip-\lineheight \verticalstrut\endgraf
+ \insidefloattrue
+ \doinhibitblank} % beware, no \inhibitblank ! ! ! ! ! !
+
+\def\stopdoorlopendblok
+ {\endgraf\verticalstrut\endgraf\kern-2\lineheight
+ \egroup}
+
+\def\tabulaterule % to be redone, not correct
+ {\dotabulaterule
+ {\hrule\!!height.5\scratchdimen\!!depth.5\scratchdimen\relax
+ \doifvalue{\??tt\currenttabulate\c!distance}\v!grid
+ {\kern-\scratchdimen}}} % experimental tm-prikkels
+
+% experimental: \synchronizegrid bla bla bla
+
+\newcounter\currentgridsync
+
+\def\gridsynctag{grs:\currentgridsync}
+
+\def\synchronizegrid
+ {\doglobal\increment\currentgridsync
+ \par\prevdepth\zeropoint
+ \nointerlineskip
+ \hpos\gridsynctag{\strut}\par
+ \vskip-\lineheight
+ \nointerlineskip
+ % top of text
+ \scratchdimen\MPy{\v!text:\MPp\gridsynctag}%
+ \advance\scratchdimen\MPh{\v!text:\MPp\gridsynctag}%
+ % move to first baseline
+ \advance\scratchdimen-\topskip
+ % subtract wrong baseline
+ \advance\scratchdimen-\MPy\gridsynctag
+ % get minimal number of lines
+ \advance\scratchdimen\lineheight
+ \getnoflines\scratchdimen
+ % calculate difference
+ \advance\scratchdimen-\noflines\lineheight\relax
+ \scratchdimen-\scratchdimen\relax
+ \ifdim\scratchdimen>\zeropoint
+ \nointerlineskip
+ \advance\scratchdimen-\lineheight
+ \vskip\scratchdimen \dontleavehmode \quad \strut
+ \par
+ %\else
+ % \message{no grid correction: \the\scratchdimen}\wait
+ \fi}
+
+% needed for extreme (will go away)
+
+\definesystemvariable{ie}
+
+\def\definetest
+ {\dodoubleempty\dodefinetest}
+
+\def\dodefinetest[#1][#2]#3%
+ {\setgvalue{\??ie#1}{#3}%
+ \ifsecondargument
+ \processaction
+ [#2]
+ [% first test true, rest depends
+ \v!next=>\setgvalue{\??ie#1}{\setgvalue{\??ie#1}{#3}\firstoftwoarguments},
+ % rest true if first true
+ % \v!first=>\setgvalue{\??ie#1}{#3{\letgvalue{\??ie#1}%
+ % \firstoftwoarguments\firstoftwoarguments}%
+ % \secondoftwoarguments},
+ % always true
+ \v!yes=>\letgvalue{\??ie#1}\firstoftwoarguments,
+ % always false
+ \v!no=>\letgvalue{\??ie#1}\secondoftwoarguments]%
+ \fi}
+
+\def\doperformtest#1%
+ {\executeifdefined{\??ie#1}\secondoftwoarguments}
+
+\def\definecolumnsethsize#1#2#3#4% will be improved/speed up
+ {\bgroup
+ \def\OTRSETidentifier{#1}%
+ \ifcase\columnsetlevel\relax
+ \mofcolumns\plusone
+ \OTRSETinitializecolumns
+ \OTRSETassignwidths
+ \OTRSETsethsize
+ \fi
+ \!!counta#2\!!countb#3\docalculatecolumnsetspan
+ \expandafter\egroup\expandafter\edef\expandafter
+ #4\expandafter{\the\!!widtha}}
+
+% so far
+
+% between alignment lines certain rules apply, and even a
+% simple test can mess up a table, which is why we have a
+% special test facility
+%
+% \ruledvbox
+% {\starttabulate[|l|p|]
+% \NC 1test \NC test \NC \NR
+% \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
+% \stoptabulate}
+
+\long\def\tableifelse#1%
+ {\TABLEnoalign{#1%
+ {\aftergroup \firstoftwoarguments}%
+ {\aftergroup\secondoftwoarguments}}}
+
+\long \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
+
+% experiment, not yet to be used
+
+\def\displaybreak
+ {\ifhmode
+ \removeunwantedspaces
+ \ifcase\raggedstatus\hfill\fi
+ \strut\penalty-9999 % \break fails on case (3)
+ \fi}
+
+\def\startdisplay{\displaybreak\ignorespaces\startpacked}
+\def\stopdisplay {\stoppacked\displaybreak\ignorespaces}
+
+\def\tightvbox{\dowithnextbox{\nextboxdp\zeropoint\flushnextbox}\vbox}
+\def\tightvtop{\dowithnextbox{\nextboxht\zeropoint\flushnextbox}\vtop}
+
+% what is this stupid macro meant for:
+
+\def\hyphenationpoint
+ {\hskip\zeropoint}
+
+\def\hyphenated#1%
+ {\bgroup
+ \!!counta\zerocount
+ \def\hyphenated##1{\advance\!!counta\plusone}%
+ \handletokens#1\with\hyphenated
+ \!!countb\plusone
+ \def\hyphenated##1%
+ {##1%
+ \advance\!!countb\plusone\relax
+ \ifnum\!!countb>2 \ifnum\!!countb<\!!counta
+ \hyphenationpoint
+ \fi\fi}%
+ \handletokens#1\with\hyphenated
+ \egroup}
+
+\def\obeysupersubletters
+ {\let\super\normalsuper
+ \let\suber\normalsuber
+ \let\normalsuper\letterhat
+ \let\normalsuber\letterunderscore
+ \enablesupersub}
+
+\def\obeysupersubmath
+ {\let\normalsuper\letterhat
+ \let\normalsuber\letterunderscore
+ \enablesupersub}
+
+%\let\normaltype\type
+%
+%\def\type#1%
+% {\expanded{\normaltype{\detokenize{#1}}}}
+
+% {x123 \os x123} {\tfa x123 \os x123} {x123 \tx x123 \os x123}
+% \definefontsynonym[OldStyle][Serif]
+% {x123 \os x123} {\tfa x123 \os x123} {x123 \tx x123 \os x123}
+
+% testen :
+%
+% \appendtoks
+% \let\registerparoptions\relax
+% \to \everyforgetall
+
+\def\startgridcorrection
+ {\dosingleempty\dostartgridcorrection}
+
+\def\dostartgridcorrection[#1]%
+ {\ifgridsnapping
+ \iffirstargument\doifsomething{#1}{\moveongrid[#1]}\fi
+ \snaptogrid\vbox\bgroup
+ \else
+ \startbaselinecorrection
+ \fi}
+
+\def\stopgridcorrection
+ {\ifgridsnapping
+ \egroup
+ \else
+ \stopbaselinecorrection
+ \fi}
+
+\def\checkgridsnapping
+ {\lineskip\ifgridsnapping\zeropoint\else\normallineskip\fi}
+
+\def\startplaatsen
+ {\dosingleempty\dostartplaatsen}
+
+\def\dostartplaatsen[#1]% tzt n*links etc
+ {\endgraf
+ \noindent\bgroup
+ \setlocalhsize
+ \hbox to \localhsize\bgroup
+ \doifnot{#1}\v!left\hss
+ \def\stopplaatsen
+ {\unskip\unskip\unskip
+ \doifnot{#1}\v!right\hss
+ \egroup
+ \egroup
+ \endgraf}%
+ \gobblespacetokens}
+
+% \startplaatsen[links] bla \stopplaatsen
+
+% we don't register the paragraph characteristics, only the
+% width
+
+\appendtoks
+ \setinnerparpositions % see "techniek" for application
+\to \everytabulate
+
+\def\fontclassname#1#2%
+ {\ifcsname\??ff#1#2\endcsname
+ \fontclassname{#1}{\csname\??ff#1#2\endcsname}%
+ \else\ifcsname\??ff#2\endcsname
+ \fontclassname{#1}{\csname\??ff#2\endcsname}%
+ \else
+ #2%
+ \fi\fi}
+
+\def\defineclassfontsynonym
+ {\dotripleargument\dodefineclassfontsynonym}
+
+\def\dodefineclassfontsynonym[#1][#2][#3]%
+ {\definefontsynonym[#1][\fontclassname{#2}{#3}]}
+
+%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}]
+%
+%\defineclassfontsynonym [KopFont] [officina] [SerifBold]
+
+\def\startcolumnmakeup % don't change
+ {\bgroup
+ \getrawnoflines\textheight % teksthoogte kan topskip hebben, dus raw
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen-\lineheight
+ \advance\scratchdimen\topskip
+ \setbox\scratchbox
+ \ifcase\showgridstate\vbox\else\ruledvbox\fi to \scratchdimen\bgroup
+ \forgetall} % ! don't change
+
+\def\stopcolumnmakeup
+ {\egroup
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\textwidth
+ \box\scratchbox
+ \egroup
+ \synchronizehsize}
+
+\long\def\startexternalfigure
+ {\dotripleempty\dostartexternalfigure}
+
+\long\def\dostartexternalfigure[#1][#2][#3]#4\stopexternalfigure
+ {\gdef\figuredescription{#4}%
+ \externalfigure[#1][#2][#3]%
+ \globallet\figuredescription\empty}
+
+\let\figuredescription\empty
+
+%% where does this come from, old code probably
+%%
+%%
+%% \newif\ifpagechanged \let\lastchangedpage\empty
+%%
+%% \def\checkpagechange#1%
+%% {\gettwopassdata\s!paragraph
+%% \pagechangedfalse
+%% \iftwopassdatafound
+%% \ifnum\twopassdata>0\getvalue{\s!paragraph:p:#1}\relax
+%% \pagechangedtrue
+%% \fi
+%% \fi
+%% \ifpagechanged
+%% \letgvalue{\s!paragraph:p:#1}\twopassdata
+%% \globallet\lastchangedpage\twopassdata
+%% \else
+%% \globallet\lastchangedpage\realfolio
+%% \fi
+%% \doparagraphreference}
+%%
+%% \def\changedpage#1%
+%% {\getvalue{\s!paragraph:p:#1}}
+
+\newcount\nofprofiled
+
+\def\profilemacro#1%
+ {\nofprofiled\zerocount
+ \letvalue{\string#1\string#1}#1%
+ \appendtoks
+ \normalwritestatus\m!systems{profile \string#1: \number\nofprofiled}%
+ \to \everystoptext
+ \unexpanded\def#1%
+ {\global\advance\nofprofiled\plusone
+ \csname\string#1\string#1\endcsname}}
+
+% incomplete, will be a special case of float placement
+
+\def\startfixed{\dosingleempty\dostartfixed}
+
+\def\dostartfixed[#1]%
+ {\expanded{\dowithnextbox{\noexpand\dodofixed{\ifhmode0\else1\fi}{#1}}}%
+ \vbox\bgroup
+ \setlocalhsize}
+
+\def\stopfixed
+ {\egroup}
+
+\def\dodofixed#1#2%
+ {\ifcase#1\relax
+ \processaction
+ [#2]
+ [ \v!high=>\bbox {\flushnextbox},
+ \v!low=>\tbox {\flushnextbox},
+ \v!middle=>\vcenter{\flushnextbox},
+ \v!lohi=>\vcenter{\flushnextbox},
+ \s!unknown=>\tbox {\flushnextbox},
+ \s!default=>\tbox {\flushnextbox}]%
+ \else
+ \startbaselinecorrection
+ \noindent\flushnextbox
+ \stopbaselinecorrection
+ \fi}
+
+% \startitemize
+%
+% \item \externalfigure[koe][height=2cm]
+% \item \externalfigure[koe][height=2cm]
+% \item \externalfigure[koe][height=2cm]
+% \item \externalfigure[koe][height=2cm]
+%
+% \page
+%
+% \item \startfixed \externalfigure[koe][height=2cm]\stopfixed
+% \item \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
+% \item \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
+% \item \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
+%
+% \page
+%
+% \item test \startfixed \externalfigure[koe][height=2cm]\stopfixed
+% \item test \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
+% \item test \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
+% \item test \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
+%
+% \page
+%
+% \item test \par \startfixed \externalfigure[koe][height=2cm]\stopfixed
+% \item test \par \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
+% \item test \par \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
+% \item test \par \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
+%
+% \stopitemize
+
+\def\obeyfollowingtoken{{}} % end \cs scanning
+
+% \def\comparedimension#1#2%
+% {\chardef\compresult
+% \ifdim#1<#2%
+% \zerocount
+% \else\ifdim#1<#2%
+% \plusone
+% \else
+% \plustwo
+% \fi\fi}
+% \newdimen\roundingeps \roundingeps=10sp
+% \def\comparedimensioneps#1#2%
+% {\chardef\compresult
+% \ifdim\dimexpr(#1-#2)<\roudingeps
+% \zerocount
+% \else\ifdim\dimexpr(#2-#1)<\roudingeps
+% \zerocount
+% \else\ifdim#1<#2%
+% \plusone
+% \else
+% \plustwo
+% \fi\fi\fi}
+
+%D Next we load a few local optimizations and new features. They
+%D live on on my machine and are not distributed, but they may end
+%D up in the distributed files.
+
+\loadmarkfile{cont-new}
+
+\readsysfile {cont-loc} {} {} % local improvements, patches, new features
+\readsysfile {cont-exp} {} {} % experimental features (e.g. local speed-ups)
+%readsysfile {cont-mtx} {} {} % experimental metatex features
+
+\protect \endinput
diff --git a/tex/context/base/cont-nl.tex b/tex/context/base/cont-nl.tex
new file mode 100644
index 000000000..32b82b01a
--- /dev/null
+++ b/tex/context/base/cont-nl.tex
@@ -0,0 +1,42 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!nl]
+
+\loaduserspecifications
+
+\installlanguage [\s!us] [\c!state=\v!start]
+\installlanguage [\s!gb] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!fr] [\c!state=\v!start]
+\installlanguage [\s!es] [\c!state=\v!start]
+\installlanguage [\s!nl] [\c!state=\v!start]
+\installlanguage [\s!it] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-old.tex b/tex/context/base/cont-old.tex
new file mode 100644
index 000000000..360b5f2e6
--- /dev/null
+++ b/tex/context/base/cont-old.tex
@@ -0,0 +1,48 @@
+%D \module
+%D [ file=cont-old,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Old Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Old Macros}
+
+\unprotect
+
+\def\middleraggedness {6\bodyfontsize}
+
+\def\dosubstitutecommand#1#2%
+ {\writestatus\m!systems{\string#1\normalspace -> \string#2}%
+ \gdef#1{#2}%
+ #2}
+
+\def\substitutecommand#1#2%
+ {\gdef#1{\dosubstitutecommand{#1}{#2}}}
+
+\substitutecommand \volgendehoofdstuk {\setupheadnumber[hoofdstuk][+1]}
+\substitutecommand \volgendeparagraaf {\setupheadnumber[paragraaf][+1]}
+\substitutecommand \volgendesubparagraaf {\setupheadnumber[subparagraaf][+1]}
+\substitutecommand \volgendesubsubparagraaf {\setupheadnumber[subsubparagraaf][+1]}
+
+\substitutecommand \volledigeinhoudsopgave \volledigeinhoud
+\substitutecommand \plaatsinhoudsopgave \plaatsinhoud
+\substitutecommand \stelinhoudsopgavein \stelinhoudin
+
+\substitutecommand \streep \onderstreep
+\substitutecommand \strepen \onderstrepen
+
+\substitutecommand \pragmakenmerk \referral
+
+\substitutecommand \definieersynoniem \definesynonyms
+
+\substitutecommand \setupintermezzos \setupintermezzi
+
+\let \Everybodyfont \EveryBodyFont
+
+\protect \endinput
diff --git a/tex/context/base/cont-pe.tex b/tex/context/base/cont-pe.tex
new file mode 100644
index 000000000..fdf47d680
--- /dev/null
+++ b/tex/context/base/cont-pe.tex
@@ -0,0 +1,45 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!pe]
+
+\loaduserspecifications
+
+% Do we need more defaults? or maybe all languages?
+
+\installlanguage [\s!us] [\c!state=\v!start]
+\installlanguage [\s!gb] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!fr] [\c!state=\v!start]
+\installlanguage [\s!es] [\c!state=\v!start]
+\installlanguage [\s!it] [\c!state=\v!start]
+\installlanguage [\s!nl] [\c!state=\v!start]
+\installlanguage [\s!pe] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-ro.tex b/tex/context/base/cont-ro.tex
new file mode 100644
index 000000000..9be9b1162
--- /dev/null
+++ b/tex/context/base/cont-ro.tex
@@ -0,0 +1,38 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\input context.tex
+
+\unprotect
+
+\setupcurrentlanguage[\s!ro]
+
+\loaduserspecifications
+
+\installlanguage [\s!en] [\c!state=\v!start]
+\installlanguage [\s!de] [\c!state=\v!start]
+\installlanguage [\s!ro] [\c!state=\v!start]
+
+\ifnum\texengine=\luatexengine
+ % will be runtime option: typeface
+ \appendtoks
+ \usetypescript[modern]
+ \setuptypeface[modern]
+ \to \everyjob
+\else
+ \setupencoding[default=ec] \usetypescript[fallback][\defaultencoding] \setupbodyfont[rm,12pt]
+\fi
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/cont-sys.ori b/tex/context/base/cont-sys.ori
new file mode 100644
index 000000000..11c0141e7
--- /dev/null
+++ b/tex/context/base/cont-sys.ori
@@ -0,0 +1,182 @@
+%D \module
+%D [ file=cont-sys,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=System Specific Setups,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+% Speed up typescript loading, but at the cost of much memory:
+
+\preloadtypescripts
+
+% If you want another default font:
+%
+% \let\preloadfonts\relax
+% \usetypescript[palatino][\defaultencoding]
+% \setupbodyfont[palatino,rm,12pt]
+%
+% Please make sure that this defines rm, ss, tt and mm.
+
+% Occasionally we will support both A4 and letter in
+% styles. If you want letter size paper to be the default,
+% uncomment:
+%
+% \enablemode[\systemmodeprefix letter]
+%
+% If you always want to default to letter, you may uncomment
+% the following line, but beware: it makes your documents less
+% portable:
+%
+% \setuppapersize[letter][letter]
+
+% If you want some extras, just uncomment the following
+% line:
+%
+% \usemodule[plus] % experimental code
+%
+% Here you can take care of overloading some (style)
+% defaults. What goes here, depends on your local system.
+
+% The following commands sets the default font encoding:
+%
+% \setupencoding [\s!default=texnansi]
+%
+% or:
+
+\setupencoding [\s!default=ec]
+
+% If you want the default berry names:
+%
+% \usetypescript [berry] [\defaultencoding]
+%
+% or, if you also want other encodings:
+
+\usetypescript [berry] [ec,t5,8r] % texnansi is never present
+
+% If you run into missing font metrics kind of problems,
+% you may want to uncomment:
+%
+% \usetypescript[adobekb] [\defaultencoding]
+
+% You can let \CONTEXT\ load the map files for \PDFTEX.
+
+\autoloadmapfilestrue
+
+% (1) you can prevent loading with:
+%
+% \preloadmapfile[<...somename...>.map]
+%
+% (2) otherwise, use this if you have a fast machine
+%
+% \resetmapfiles \usetypescript [map] [base] [all]
+%
+% (3) or this if it's a slow one:
+
+\resetmapfiles
+
+% more recent versions of pdftex support map loading on each page
+
+\donefalse \ifx\pdftexversion\undefined \else \ifnum\number\pdftexversion>119
+ \donetrue
+\fi \fi \ifdone
+
+ \loadmapfile[original-base.map]
+ \loadmapfile[original-ams-base.map]
+ \loadmapfile[original-ams-euler.map]
+ \loadmapfile[original-public-lm.map]
+
+\else
+
+ \loadmapfile[original-base.map]
+ \loadmapfile[texnansi-base.map]
+ \loadmapfile[ec-base.map]
+ \loadmapfile[qx-base.map]
+ \loadmapfile[t5-base.map]
+ %loadmapfile[il2-base.map]
+ %loadmapfile[pl0-base.map]
+ \loadmapfile[8r-base.map]
+
+ \loadmapfile[original-ams-base.map]
+ \loadmapfile[original-ams-euler.map]
+
+ \loadmapfile[original-public-lm.map]
+
+ %loadmapfile[texnansi-public-lm.map]
+ %loadmapfile[ec-public-lm.map]
+ %loadmapfile[qx-public-lm.map]
+ %loadmapfile[t5-public-lm.map]
+ %loadmapfile[pl0-public-lm.map]
+ %loadmapfile[il2-public-lm.map]
+
+\fi
+
+% When you have your own fonts installed, you may want to predefine:
+%
+% \usetypescriptfile[type-buy]
+
+% Some styles default to Lucida Bright. You can overload
+% Lucida by Times cum suis. Watch out, the pos collection
+% is not scaled relatively.
+%
+% \definetypescriptsynonym [lbr] [pos]
+
+% Compensate for missing files:
+%
+% \definefontsynonym [gbhei] [gbsong]
+% \definefontsynonym [gbheisl] [gbsong]
+% \definefontsynonym [gbheisl] [gbsong]
+
+% Setting up a global figure path
+%
+% \setupexternalfigures [\c!directory={e:/fig/eps,t:/mine/figs}]
+%
+% Loading a specific special driver:
+%
+% \setupoutput [dviwindo]
+
+% Changing language defaults
+%
+% \setuplanguage
+% [nl]
+% [\c!leftquote=\upperleftsinglesixquote,
+% \c!leftquotation=\upperleftdoublesixquote]
+
+% Loading local preferences, for example
+%
+% \input prag-gen % company styles
+% \input prag-log % more company styles
+%
+% Enabling run time \METAPOST\ (also enable \write18 in
+% texmf.cnf):
+
+\runMPgraphicstrue
+\runMPTEXgraphicstrue
+
+% This saves some runtime, but needs a format, which you can
+% make with 'texexec --make --alone metafun'. Make sure that
+% the mem files are moved to the used web2c path (locate with
+% 'kpsewhich plain.mem').
+
+\useMETAFUNformattrue
+
+% This can be a way to get things working on system with
+% name clashes. (Some \TeX's tend do search system wide.)
+
+\protectbufferstrue
+
+% You can enable a more extensive figure searching, but
+% normally this is not really needed and even annoying.
+%
+% \runutilityfiletrue
+
+% So far.
+
+\protect \endinput
diff --git a/tex/context/base/cont-usr.ori b/tex/context/base/cont-usr.ori
new file mode 100644
index 000000000..5a3070362
--- /dev/null
+++ b/tex/context/base/cont-usr.ori
@@ -0,0 +1,109 @@
+%D \module
+%D [ file=cont-usr,
+%D version=1997.10.05,
+%D title=\CONTEXT\ User Format Specifications,
+%D subtitle=System Specific Setups,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 User Settings}
+
+\unprotect
+
+%D Additional languages can be defined here. Beware of
+%D encoding incompatibilities. Please take a look at the
+%D \type {cont-en.tex}, \type {cont-nl.tex}, enz.\ files
+%D first. Normally you don't have to change a byte. If you
+%D want to play safe, use \typ {texexec --make --alone
+%D --all}.
+
+% \preloadallpatterns % will load them all
+
+% \installlanguage [\s!af] [\c!state=\v!start] % afrikaans
+% \installlanguage [\s!ca] [\c!state=\v!start] % catalan
+% \installlanguage [\s!cs] [\c!state=\v!start] % czech
+% \installlanguage [\s!da] [\c!state=\v!start] % danish
+% \installlanguage [\s!de] [\c!state=\v!start] % german
+% \installlanguage [\s!en] [\c!state=\v!start] % english us
+% \installlanguage [\s!es] [\c!state=\v!start] % spanish
+% \installlanguage [\s!fi] [\c!state=\v!start] % finnish
+% \installlanguage [\s!fr] [\c!state=\v!start] % french
+% \installlanguage [\s!hr] [\c!state=\v!start] % croatian
+% \installlanguage [\s!hu] [\c!state=\v!start] % hungarian
+% \installlanguage [\s!it] [\c!state=\v!start] % italian
+% \installlanguage [\s!la] [\c!state=\v!start] % latin
+% \installlanguage [\s!nl] [\c!state=\v!start] % dutch
+% \installlanguage [\s!nb] [\c!state=\v!start] % bokmal
+% \installlanguage [\s!nn] [\c!state=\v!start] % nynorsk
+% \installlanguage [\s!pl] [\c!state=\v!start] % polish
+% \installlanguage [\s!pt] [\c!state=\v!start] % portuguese
+% \installlanguage [\s!ro] [\c!state=\v!start] % romanian
+% \installlanguage [\s!ru] [\c!state=\v!start] % russian
+% \installlanguage [\s!sk] [\c!state=\v!start] % slovak
+% \installlanguage [\s!sl] [\c!state=\v!start] % slovenian
+% \installlanguage [\s!sv] [\c!state=\v!start] % swedish
+% \installlanguage [\s!tr] [\c!state=\v!start] % turkish
+% \installlanguage [\s!ua] [\c!state=\v!start] % ukrainian
+% \installlanguage [\s!gb] [\c!state=\v!start] % english uk
+% \installlanguage [\s!vn] [\c!state=\v!start] % vietnamese
+
+% \installlanguage [deo] [\c!state=\v!start] % old german
+
+%D The next lines can be used for setting the language to be
+%D used at startup time.
+
+% \setupcurrentlanguage[\s!af]
+% \setupcurrentlanguage[\s!ca]
+% \setupcurrentlanguage[\s!cs]
+% \setupcurrentlanguage[\s!da]
+% \setupcurrentlanguage[\s!de]
+% \setupcurrentlanguage[\s!en]
+% \setupcurrentlanguage[\s!es]
+% \setupcurrentlanguage[\s!fi]
+% \setupcurrentlanguage[\s!fr]
+% \setupcurrentlanguage[\s!hr]
+% \setupcurrentlanguage[\s!hu]
+% \setupcurrentlanguage[\s!it]
+% \setupcurrentlanguage[\s!la]
+% \setupcurrentlanguage[\s!nl]
+% \setupcurrentlanguage[\s!nb]
+% \setupcurrentlanguage[\s!nn]
+% \setupcurrentlanguage[\s!pl]
+% \setupcurrentlanguage[\s!pt]
+% \setupcurrentlanguage[\s!ro]
+% \setupcurrentlanguage[\s!ru]
+% \setupcurrentlanguage[\s!sk]
+% \setupcurrentlanguage[\s!sl]
+% \setupcurrentlanguage[\s!sv]
+% \setupcurrentlanguage[\s!tr]
+% \setupcurrentlanguage[\s!ua]
+
+%D Local font settings can go here. Normally suitable
+%D defaults are already preloaded, almost certainly the
+%D Computer Modern Roman typefaces or some derivate. So, the
+%D next line is only meant as sample, take a look at the
+%D format related files first.
+
+% This is obsolete due to latin modern:
+%
+% \definefilesynonym [font-cmr] [font-csr] % czech & slovak
+% \definefilesynonym [font-cmr] [font-plr] % polish
+
+%D In some languages, compound characters, like \type {"e}
+%D are used to get accented and non latin characters.
+
+% Per 21/9/2006 one needs to explicitly enable this.
+
+% \useencoding[fde] % german
+% \useencoding[ffr] % french
+% \useencoding[fro] % romanian
+% \useencoding[fpl] % polish
+
+%D Don't remove the next few lines.
+
+\protect \endinput
diff --git a/tex/context/base/context-base.lmx b/tex/context/base/context-base.lmx
new file mode 100644
index 000000000..fd27927bf
--- /dev/null
+++ b/tex/context/base/context-base.lmx
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+ 0) and v('refreshurl') then ?>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tex/context/base/context-characters.lmx b/tex/context/base/context-characters.lmx
new file mode 100644
index 000000000..f018e412b
--- /dev/null
+++ b/tex/context/base/context-characters.lmx
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tex/context/base/context.css b/tex/context/base/context.css
new file mode 100644
index 000000000..f332ae242
--- /dev/null
+++ b/tex/context/base/context.css
@@ -0,0 +1,241 @@
+body {
+ color: #FFFFFF ;
+ background-color: ;
+ font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans ;
+ font-size: 12px ;
+ line-height: 18px ;
+}
+a:link, a:active, a:visited {
+ color: #FFFFFF ;
+}
+a.dir-view:link, a.dir-view:active, a.dir-view:visited {
+ color: #FFFFFF ;
+ text-decoration: underline ;
+}
+.valid {
+ color: #00FF00 ;
+}
+.invalid {
+ color: #FF0000 ;
+}
+h1, .title {
+ font-style: normal ;
+ font-weight: normal ;
+ font-size: 18px ;
+ line-height: 18px ;
+ margin-bottom: 20px ;
+}
+h2, .subtitle {
+ font-style: normal ;
+ font-weight: normal ;
+ font-size: 12px ;
+ margin-top: 18px ;
+ margin-bottom: 18px ;
+}
+table {
+ line-height: 18px ;
+ font-size: 12px ;
+ margin: 0 ;
+}
+th {
+ font-weight: bold ;
+ text-align: left ;
+ padding-bottom: 6px ;
+}
+.tc {
+ font-weight: bold ;
+ text-align: left ;
+}
+p, li {
+ max-width: 60em ;
+}
+.empty-line {
+ margin-top: 4px ;
+}
+.more-room {
+ margin-right: 1.5em ;
+}
+.much-more-room {
+ margin-right: 3em ;
+}
+#main {
+ position: absolute;
+ left: 10% ;
+ top: 10% ;
+ right: 10% ;
+ bottom: 10% ;
+ z-index: 2 ;
+ width: 80% ;
+ height: 80% ;
+ padding: 0% ;
+ margin: 0% ;
+ overflow: auto ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: ;
+}
+#main-settings {
+ margin: 12px ;
+ x_max-width: 60em ;
+ line-height: 18px ;
+ font-size: 12px ;
+}
+#left {
+ position: absolute;
+ top : 10% ;
+ left: 0% ;
+ bottom: 0%;
+ right: 90% ;
+ z-index: 1 ;
+ width: 10% ;
+ height: 90% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: ;
+}
+#right {
+ position: absolute;
+ top : 0% ;
+ left: 90% ;
+ bottom: 10% ;
+ right: 0% ;
+ z-index: 1 ;
+ width: 10% ;
+ height: 90% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: ;
+ _margin-left: -15px ;
+}
+#bottom {
+ position: absolute ;
+ left: 10% ;
+ right: 0% ;
+ top: 90% ;
+ bottom: 0% ;
+ z-index: 1 ;
+ width: 90% ;
+ height: 10% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: ;
+}
+#top {
+ position: absolute ;
+ left: 0% ;
+ right: 10% ;
+ top: 0% ;
+ bottom: 90% ;
+ z-index: 1 ;
+ width: 90% ;
+ height: 10% ;
+ padding: 0% ;
+ margin: 0% ;
+ font-size: 16px ;
+ border-style: none ;
+ border-width: 0 ;
+ background-color: ;
+}
+#top-one {
+ position: absolute ;
+ bottom: 50% ;
+ width: 100% ;
+ buggedheight: 100% ;
+}
+#top-two {
+ position: relative ;
+ margin-bottom: -9px ;
+ margin-left: 12px ;
+ margin-right: 12px ;
+ line-height: 18px ;
+ text-align: right ;
+ vertical-align: middle ;
+}
+#bottom-one {
+ position: absolute ;
+ bottom: 50% ;
+ width: 100% ;
+ buggedheight: 100% ;
+}
+#bottom-two {
+ position: relative ;
+ margin-bottom: -9px ;
+ margin-left: 12px ;
+ margin-right: 12px ;
+ line-height: 18px ;
+ text-align: left ;
+ vertical-align: middle ;
+}
+#left-one {
+ position: absolute ;
+ width: 100% ;
+ buggedheight: 100% ;
+}
+#left-two {
+ position: relative ;
+ margin-top: 12px ;
+ line-height: 18px ;
+ text-align: center ;
+ vertical-align: top ;
+}
+#right-one {
+ display: table ;
+ height: 100% ;
+ width: 100% ;
+}
+#right-two {
+ display: table-row ;
+ height: 100% ;
+ width: 100% ;
+}
+#right-three {
+ display: table-cell ;
+ width: 100% ;
+ vertical-align: bottom ;
+ _position: absolute ;
+ _top: 100% ;
+}
+#right-four {
+ text-align: center ;
+ margin-bottom: 2ex ;
+ _position: relative ;
+ _top: -100% ;
+}
+#more-top {
+ position: absolute;
+ top: 0% ;
+ left: 90% ;
+ bottom: 90%;
+ right: 0% ;
+ z-index: 3 ;
+ width: 10% ;
+ height: 10% ;
+ padding: 0% ;
+ margin: 0% ;
+ border-style: none ;
+ border-width: 0 ;
+}
+#more-top-settings {
+ text-align: center ;
+}
+#more-right-settings {
+ margin-right: 12px ;
+ margin-left: 12px ;
+ line-height: 18px ;
+ font-size: 10px ;
+ text-align: center ;
+}
+#right-safari {
+ display: table ;
+ width: 100% ;
+ height: 100% ;
+}
diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii
new file mode 100644
index 000000000..4be60cbfc
--- /dev/null
+++ b/tex/context/base/context.mkii
@@ -0,0 +1,391 @@
+%D \module
+%D [ file=context,
+%D version=2008.28.10, % 1995.10.10,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Format Generation,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 First we load the system modules. These implement a lot of
+%D manipulation macros. The first one loads \PLAIN\ \TEX, as
+%D minimal as possible.
+
+\loadcorefile{syst-ini}
+\loadcorefile{syst-pln}
+
+\loadcorefile{norm-tex}
+\loadcorefile{norm-etx}
+\loadcorefile{norm-ptx}
+\loadcorefile{norm-xtx}
+\loadcorefile{norm-ctx}
+
+\loadmarkfile{catc-ini}
+\loadcorefile{catc-act}
+\loadcorefile{catc-def}
+\loadcorefile{catc-ctx}
+\loadcorefile{catc-sym}
+
+\loadmarkfile{syst-gen}
+\loadmarkfile{syst-ext}
+\loadmarkfile{syst-new}
+\loadmarkfile{syst-con}
+\loadcorefile{syst-ltx}
+\loadmarkfile{thrd-trg} % based on: David Carlisle
+
+\loadmarkfile{syst-fnt}
+\loadmarkfile{syst-str}
+\loadmarkfile{syst-rtp}
+
+\ifnum\texengine=\xetexengine
+ \loadmarkfile{xetx-ini}
+ \loadmarkfile{xetx-utf}
+ \loadmarkfile{xetx-chr}
+ \loadmarkfile{xetx-cls}
+\fi
+
+%D To enable selective loading, we say:
+
+\newif\ifCONTEXT \CONTEXTtrue % will disappear
+
+%D In order to conveniently load files, we need a few
+%D support modules.
+
+\loadmarkfile{supp-fil}
+\loadmarkfile{supp-dir}
+
+%D After this we're ready for the multi||lingual interface
+%D modules.
+
+\loadmarkfile{mult-ini}
+\loadcorefile{mult-fst}
+\loadcorefile{mult-sys}
+\loadcorefile{mult-def}
+\loadmarkfile{mult-chk}
+
+%D Now we're ready for some general support modules. These
+%D modules implement some basic typesetting functionality.
+
+\loadmarkfile{core-var}
+\loadmarkfile{core-env}
+
+\loadcorefile{supp-box}
+\loadmarkfile{supp-mrk}
+\loadcorefile{supp-vis}
+\loadcorefile{supp-fun}
+%loadmarkfile{supp-eps}
+\loadmarkfile{supp-spe}
+\loadmarkfile{supp-ran}
+\loadmarkfile{supp-mps}
+\loadmarkfile{supp-tpi}
+\loadmarkfile{supp-mat}
+\loadcorefile{supp-ali}
+\loadcorefile{supp-num}
+
+%D Verbatim typesetting is implemented in a separate class of
+%D modules. The pretty typesetting modules are loaded at run
+%D time.
+
+\loadmarkfile{verb-ini}
+
+%D The following modules are not sequentially dependent,
+%D i.e. they have ugly dependencies, which will be cleaned
+%D up by adding more overloading.
+
+%D When loading the font, color and special modules, we need a
+%D bit more advanced file handling as well as some general
+%D variables, and features, so next we load:
+
+\loadmarkfile{page-ins}
+\loadmarkfile{core-fil}
+\loadmarkfile{core-con}
+
+%D We already need some synonyms (patterns). At runtime this
+%D file will be reloaded.
+
+\loadcorefile{cont-fil}
+
+%D \CONTEXT\ does not implement its own table handling. We
+%D just go for the best there is and load \TABLE. Just to be
+%D sure we do it here, before we redefine \type{|}.
+
+\loadcorefile{thrd-tab} % based on: Michael Wichura / will be reimplemented
+
+%D Here comes the last support modules. They take care of
+%D some language specific things.
+
+\loadmarkfile{supp-pat}
+
+%D The next few modules do what their names state. They
+%D load additional definition modules when needed.
+
+\loadmarkfile{regi-ini}
+\loadcorefile{regi-syn}
+\loadmarkfile{enco-ini}
+%loadmarkfile{filt-ini}
+\loadmarkfile{hand-ini}
+
+\loadmarkfile{lang-ini}
+\loadmarkfile{lang-spe}
+\loadmarkfile{lang-lab}
+
+\loadmarkfile{unic-ini}
+
+\loadmarkfile{core-gen}
+\loadmarkfile{core-uti}
+\loadmarkfile{core-two}
+\loadmarkfile{core-stg}
+
+\loadmarkfile{spec-ini}
+\loadmarkfile{spec-mis}
+\loadmarkfile{spec-def}
+\loadmarkfile{spec-var}
+
+\loadmarkfile{colo-ini}
+\loadmarkfile{colo-ext}
+
+%D For the moment we load a lot of languages. In the future
+%D we'll have to be more space conservative.
+
+\loadmarkfile{lang-mis}
+\loadmarkfile{lang-url}
+
+\loadcorefile{lang-ger}
+\loadcorefile{lang-ita}
+\loadcorefile{lang-sla}
+\loadcorefile{lang-alt}
+\loadcorefile{lang-ana}
+\loadcorefile{lang-art}
+\loadcorefile{lang-bal}
+\loadcorefile{lang-cel}
+\loadcorefile{lang-grk}
+\loadcorefile{lang-ind}
+\loadcorefile{lang-ura}
+\loadcorefile{lang-vn}
+\loadcorefile{lang-cyr}
+
+\loadmarkfile{typo-ini}
+
+%D All kind of symbols are handled in:
+
+\loadmarkfile{symb-ini}
+
+%D Sorting:
+
+\loadmarkfile{sort-ini}
+
+%D Next we load some core macro's. These implement the
+%D macros' that are seen by the users. The order of loading
+%D is important, due to dependancies.
+
+\loadmarkfile{spac-gen}
+\loadmarkfile{spac-grd}
+
+\loadmarkfile{strc-mar}
+\loadmarkfile{anch-pos}
+
+\loadmarkfile{buff-ver}
+\loadmarkfile{buff-ini}
+
+\loadmarkfile{pack-rul}
+\loadmarkfile{trac-vis}
+\loadmarkfile{strc-num}
+\loadmarkfile{tabl-com}
+\loadmarkfile{tabl-pln}
+\loadmarkfile{tabl-tab}
+\loadmarkfile{tabl-tsp}
+\loadmarkfile{scrn-nav}
+\loadmarkfile{strc-ref}
+\loadmarkfile{pack-obj}
+\loadmarkfile{strc-lst}
+\loadmarkfile{strc-itm}
+\loadmarkfile{strc-des}
+\loadmarkfile{strc-mat} % should come after math-pln etc
+\loadmarkfile{strc-syn}
+\loadmarkfile{core-sys}
+
+\loadmarkfile{page-ini}
+\loadmarkfile{page-bck}
+\loadmarkfile{page-not}
+\loadmarkfile{page-one}
+\loadmarkfile{page-lay}
+\loadmarkfile{page-log}
+\loadmarkfile{page-txt}
+\loadmarkfile{page-sid}
+\loadmarkfile{strc-flt}
+\loadmarkfile{page-mis}
+\loadmarkfile{page-mul}
+\loadmarkfile{page-set}
+\loadmarkfile{pack-lyr}
+\loadmarkfile{page-mak}
+\loadmarkfile{strc-pag}
+\loadmarkfile{page-lin}
+\loadmarkfile{page-par}
+\loadmarkfile{page-mar}
+
+\loadmarkfile{core-job} % why so late?
+
+% so far
+
+\loadmarkfile{strc-sec}
+\loadmarkfile{strc-swd}
+\loadmarkfile{strc-blk}
+
+\loadmarkfile{page-imp}
+\loadmarkfile{tabl-tbl}
+\loadmarkfile{scrn-int}
+\loadmarkfile{tabl-ntb}
+\loadmarkfile{tabl-nte}
+\loadmarkfile{tabl-ltb}
+
+%D A few more languages, that have specifics using core
+%D functionality:
+
+%loadmarkfile{lang-ara} % undefined
+\loadmarkfile{lang-chi}
+\loadmarkfile{lang-jap}
+
+%D How about fill||in fields and related stuff?
+
+\loadmarkfile{java-ini}
+\loadmarkfile{scrn-fld}
+\loadmarkfile{scrn-hlp}
+
+%D Registers can depend on fields, so we load that now.
+
+\loadmarkfile{strc-reg}
+
+%D Of course we do need fonts. There are no \TFM\ files
+%D loaded yet, so the format file is independant of their
+%D content. Here we also redefine \type{\it} as {\it italic}
+%D instead of italian.
+
+\loadmarkfile{font-ini}
+
+\ifnum\texengine=\xetexengine
+ \loadmarkfile{font-xtx}
+\fi
+
+\loadmarkfile{font-unk}
+\loadmarkfile{font-uni}
+\loadmarkfile{font-bfm}
+
+\loadmarkfile{enco-pfr}
+
+\loadmarkfile{type-ini}
+\loadmarkfile{type-set}
+
+%D Properties. Don't ask.
+
+\loadmarkfile{prop-ini}
+\loadmarkfile{prop-lay}
+\loadmarkfile{prop-mis}
+
+%D Like languages, fonts, encodings and symbols, \METAPOST\
+%D support is also organized in its own class of modules.
+
+\loadmarkfile{meta-ini}
+\loadmarkfile{meta-tex}
+\loadmarkfile{meta-pdf}
+
+\loadmarkfile{meta-pag}
+
+%D Special page handling (maybe even later)
+
+\loadmarkfile{page-flw}
+\loadmarkfile{page-spr}
+\loadmarkfile{page-plg}
+\loadmarkfile{page-str}
+
+%D Anchoring graphics:
+
+\loadmarkfile{anch-pgr}
+\loadmarkfile{anch-bar}
+\loadmarkfile{anch-snc}
+
+%D Math.
+
+\loadmarkfile{math-pln}
+\loadmarkfile{math-ini}
+\loadmarkfile{math-arr}
+\loadmarkfile{math-frc}
+
+%D Now we're ready for more core modules.
+
+\loadmarkfile{core-fnt}
+\loadmarkfile{strc-not}
+\loadmarkfile{strc-lnt}
+
+\loadmarkfile{core-mis}
+
+\loadmarkfile{grph-trf}
+\loadmarkfile{grph-inc}
+\loadmarkfile{grph-fig}
+
+\loadmarkfile{core-par}
+
+\loadmarkfile{pack-box}
+\loadmarkfile{page-app}
+\loadmarkfile{meta-fig}
+
+%D Language specific spacing.
+
+\loadcorefile{lang-spa}
+
+%D Bibliographies:
+
+\loadmarkfile{bibl-tra}
+
+%D Only the basic XML parser and remapper are part of the core.
+%D These macros are loaded last since they overload and|/|or
+%D extend previously defined ones.
+
+\loadcorefile{xtag-ini}
+\loadcorefile{xtag-ext}
+\loadcorefile{xtag-exp}
+\loadcorefile{xtag-pre}
+\loadcorefile{xtag-xsd}
+\loadcorefile{xtag-rng}
+
+%D How about this:
+
+\loadcorefile{meta-xml}
+
+%D \TEX\ related logo's are always typeset in a special way.
+%D Here they come:
+
+\loadcorefile{cont-log}
+
+%D This one overloads af few things:
+
+\loadmarkfile{core-ctx}
+
+%D Defaults go here (more will be moved to this module
+%D later):
+
+\loadmarkfile{core-ini}
+\loadmarkfile{core-def}
+
+%D Preloaded modules (some need xml support):
+
+%usemodule[x][res-04] % xml resource libraries
+%usemodule[x][res-08] % rlx runtime conversion
+\usemodule[x][res-12] % rli external indentification
+
+%D At run time, a few more files are loaded, like:
+%D
+%D \startitemize[packed]
+%D \item \type{cont-sys}: local (system dependant) defaults
+%D \item \type{cont-old}: substitutes for old (obsolete) macros
+%D \item \type{cont-new}: new macro implementations (for testing)
+%D \item \type{cont-fil}: filename and module synonyms
+%D \stopitemize
+
+% %D Except from english, no hyphenation patterns are loaded
+% %D yet. Users can specify their needs in the next module:
+%
+% \input cont-usr
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
new file mode 100644
index 000000000..33fa3a901
--- /dev/null
+++ b/tex/context/base/context.mkiv
@@ -0,0 +1,380 @@
+%D \module
+%D [ file=context,
+%D version=2008.28.10, % 1995.10.10,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Format Generation,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% syst-cat -> catc-ini + vectors
+% spec-* -> special backends for luatex
+
+%D First we load the system modules. These implement a lot of
+%D manipulation macros. The first one loads \PLAIN\ \TEX, as
+%D minimal as possible.
+
+\loadcorefile{syst-ini}
+
+\ifnum\luatexversion<60 % also change message
+ \writestatus{!!!!}{Your luatex binary is too old, you need at least version 0.60!}
+ \expandafter\end
+\fi
+
+\newtoks\contextversiontoks \contextversiontoks\expandafter{\contextversion} % at the lua end
+
+\loadcorefile{norm-ctx}
+\loadcorefile{syst-pln}
+
+\newif\ifCONTEXT \CONTEXTtrue % will disappear
+
+\loadmarkfile{luat-cod}
+\loadmarkfile{luat-bas}
+\loadmarkfile{luat-lib}
+
+\loadmarkfile{catc-ini}
+\loadcorefile{catc-act}
+\loadcorefile{catc-def}
+\loadcorefile{catc-ctx}
+\loadcorefile{catc-sym}
+
+% From here on we have \unexpanded being \normalprotected, as we
+% already had \unexpanded long before etex came around.
+
+\loadmarkfile{syst-aux}
+\loadmarkfile{syst-lua}
+\loadmarkfile{syst-con}
+\loadcorefile{syst-ltx}
+
+\loadmarkfile{syst-fnt}
+\loadmarkfile{syst-str}
+\loadmarkfile{syst-rtp}
+
+\loadmarkfile{supp-fil}
+\loadmarkfile{supp-dir}
+
+\loadmarkfile{char-ini}
+\loadmarkfile{char-utf}
+\loadmarkfile{char-act}
+
+\loadmarkfile{mult-ini}
+\loadcorefile{mult-fst}
+\loadcorefile{mult-sys}
+\loadcorefile{mult-def}
+\loadmarkfile{mult-chk}
+\loadmarkfile{mult-cld}
+
+\loadmarkfile{luat-ini}
+
+\loadmarkfile{toks-ini}
+
+\loadmarkfile{node-ini}
+\loadmarkfile{node-fin}
+\loadmarkfile{node-mig}
+\loadmarkfile{node-par}
+%loadmarkfile{node-pag}
+
+\loadmarkfile{core-var}
+
+\loadmarkfile{back-ini}
+\loadmarkfile{lpdf-ini} % some day back-ini will load this
+\loadmarkfile{lpdf-pdx} % might be merged into lpdf-ini
+\loadmarkfile{back-pdf} % some day back-ini will load this
+
+\loadmarkfile{attr-ini}
+
+\loadmarkfile{core-env}
+
+\loadmarkfile{trac-tex}
+\loadmarkfile{trac-lmx}
+\loadmarkfile{trac-deb}
+
+\loadmarkfile{blob-ini} % not to be used, we only use a helper
+
+\loadcorefile{supp-box}
+
+\loadcorefile{supp-vis}
+\loadcorefile{supp-fun}
+
+\loadmarkfile{supp-ran}
+\loadmarkfile{supp-mat}
+\loadcorefile{supp-ali}
+\loadcorefile{supp-num}
+
+\loadmarkfile{typo-ini}
+
+\loadmarkfile{page-ins}
+\loadmarkfile{core-fil}
+\loadmarkfile{core-con}
+
+\loadcorefile{cont-fil}
+
+\loadmarkfile{regi-ini}
+\loadcorefile{regi-syn}
+\loadmarkfile{enco-ini}
+\loadmarkfile{hand-ini}
+
+\loadmarkfile{lang-ini}
+\loadmarkfile{lang-lab}
+\loadmarkfile{lang-wrd}
+
+\loadmarkfile{unic-ini}
+
+\loadmarkfile{core-gen}
+\loadmarkfile{core-uti}
+\loadmarkfile{core-two}
+
+\loadmarkfile{colo-ini}
+\loadmarkfile{colo-ext}
+
+\loadmarkfile{trac-vis}
+
+\loadmarkfile{lang-mis}
+\loadmarkfile{lang-url}
+
+\loadcorefile{lang-ger}
+\loadcorefile{lang-ita}
+\loadcorefile{lang-sla}
+\loadcorefile{lang-alt}
+\loadcorefile{lang-ana}
+\loadcorefile{lang-art}
+\loadcorefile{lang-bal}
+\loadcorefile{lang-cel}
+\loadcorefile{lang-grk}
+\loadcorefile{lang-ind}
+\loadcorefile{lang-ura}
+\loadcorefile{lang-vn}
+\loadcorefile{lang-cyr}
+
+\loadmarkfile{lang-ara}
+\loadmarkfile{lang-cjk}
+
+\loadmarkfile{symb-ini}
+
+\loadmarkfile{sort-ini}
+
+\loadmarkfile{pack-rul}
+
+\loadmarkfile{lxml-ini}
+\loadmarkfile{lxml-sor}
+
+\loadmarkfile{strc-ini}
+\loadmarkfile{strc-doc}
+\loadmarkfile{strc-mar}
+\loadmarkfile{strc-prc}
+\loadmarkfile{strc-sbe}
+\loadmarkfile{strc-lst}
+\loadmarkfile{strc-sec}
+\loadmarkfile{strc-num}
+\loadmarkfile{strc-ren}
+\loadmarkfile{strc-xml}
+\loadmarkfile{strc-pag} % hm, depends on core-num
+\loadmarkfile{strc-def} % might happen later
+\loadmarkfile{strc-ref}
+\loadmarkfile{strc-reg}
+
+\loadmarkfile{spac-hor}
+\loadmarkfile{spac-ver}
+\loadmarkfile{spac-ali}
+\loadmarkfile{spac-pag}
+\loadmarkfile{spac-fnt}
+\loadmarkfile{spac-par}
+\loadmarkfile{spac-def}
+\loadmarkfile{spac-grd}
+
+\loadmarkfile{anch-pos}
+
+\loadmarkfile{scrn-nav}
+\loadmarkfile{pack-obj}
+
+\loadmarkfile{strc-itm}
+\loadmarkfile{strc-des}
+\loadmarkfile{strc-syn}
+
+\loadmarkfile{core-sys}
+
+\loadmarkfile{page-ini}
+\loadmarkfile{page-flt}
+\loadmarkfile{page-bck}
+\loadmarkfile{page-not}
+\loadmarkfile{page-one}
+\loadmarkfile{page-lay}
+\loadmarkfile{page-txt}
+\loadmarkfile{page-sid}
+
+\loadmarkfile{strc-flt}
+
+\loadmarkfile{page-mis}
+\loadmarkfile{page-mul}
+\loadmarkfile{page-set}
+\loadmarkfile{pack-lyr}
+\loadmarkfile{page-mak}
+
+\loadmarkfile{page-lin}
+\loadmarkfile{page-par}
+\loadmarkfile{page-mar}
+
+\loadmarkfile{core-job} % why so late?
+
+\loadmarkfile{buff-ini}
+\loadmarkfile{buff-ver}
+
+\loadmarkfile{strc-blk}
+
+\loadmarkfile{page-imp}
+
+\loadmarkfile{scrn-int}
+\loadmarkfile{scrn-men}
+\loadmarkfile{scrn-but}
+\loadmarkfile{scrn-bar}
+\loadmarkfile{strc-bkm} % bookmarks
+
+\loadmarkfile{tabl-com}
+\loadmarkfile{tabl-pln}
+\loadcorefile{thrd-tab}
+\loadmarkfile{tabl-tab}
+\loadmarkfile{tabl-tbl}
+\loadmarkfile{tabl-ntb}
+\loadmarkfile{tabl-nte}
+\loadmarkfile{tabl-ltb}
+\loadmarkfile{tabl-tsp}
+
+\loadmarkfile{java-ini}
+
+\loadmarkfile{scrn-fld}
+\loadmarkfile{scrn-hlp}
+
+\loadmarkfile{char-enc}
+\loadmarkfile{font-ini}
+\loadmarkfile{font-unk}
+\loadmarkfile{font-tra}
+\loadmarkfile{font-uni}
+\loadmarkfile{font-col}
+\loadmarkfile{font-gds}
+
+\loadmarkfile{typo-spa}
+\loadmarkfile{typo-krn}
+\loadmarkfile{typo-mir}
+\loadmarkfile{typo-brk}
+\loadmarkfile{typo-cap}
+\loadmarkfile{typo-dig}
+\loadmarkfile{typo-rep}
+
+\loadmarkfile{type-ini}
+\loadmarkfile{type-set}
+
+\loadmarkfile{scrp-ini}
+
+\loadmarkfile{prop-ini}
+\loadmarkfile{prop-lay}
+\loadmarkfile{prop-mis}
+
+\loadmarkfile{mlib-ctx}
+\loadmarkfile{mlib-pdf}
+\loadmarkfile{mlib-pps}
+
+\loadmarkfile{meta-ini}
+\loadmarkfile{meta-tex}
+\loadmarkfile{meta-pdf}
+\loadmarkfile{meta-fun}
+
+\loadmarkfile{meta-pag}
+
+\loadmarkfile{page-flw}
+\loadmarkfile{page-spr}
+\loadmarkfile{page-plg}
+\loadmarkfile{page-str}
+
+\loadmarkfile{anch-pgr} % overloads tabl-tbl
+\loadmarkfile{anch-bar}
+\loadmarkfile{anch-snc}
+
+\loadmarkfile{math-ini}
+\loadmarkfile{math-pln}
+\loadmarkfile{math-for}
+\loadmarkfile{math-def}
+\loadmarkfile{math-ali}
+\loadmarkfile{math-arr}
+\loadmarkfile{math-frc}
+\loadmarkfile{math-scr}
+\loadmarkfile{math-int}
+\loadmarkfile{math-del}
+\loadmarkfile{math-inl}
+\loadmarkfile{math-dis}
+\loadmarkfile{math-lan}
+
+\loadmarkfile{strc-mat}
+
+\loadmarkfile{chem-ini}
+\loadmarkfile{chem-str}
+
+\loadmarkfile{core-fnt}
+\loadmarkfile{node-rul}
+
+\loadmarkfile{strc-not}
+\loadmarkfile{strc-lnt}
+
+\loadmarkfile{core-mis}
+
+\loadmarkfile{grph-trf}
+\loadmarkfile{grph-inc}
+\loadmarkfile{grph-fig}
+
+\loadmarkfile{pack-box}
+\loadmarkfile{pack-bar}
+\loadmarkfile{page-app}
+\loadmarkfile{meta-fig}
+
+\loadmarkfile{node-bck} % overloads anch-pgr (experimental and undocumented)
+
+\loadcorefile{lang-spa}
+
+\loadmarkfile{bibl-bib}
+\loadmarkfile{bibl-tra}
+
+\loadmarkfile{x-xtag} % at some point this will not be preloaded
+
+\loadcorefile{meta-xml}
+
+\loadcorefile{cont-log}
+
+\loadmarkfile{task-ini}
+
+\loadmarkfile{core-ctx}
+
+\loadmarkfile{core-ini}
+\loadmarkfile{core-def}
+
+%usemodule[x][res-04] % xml resource libraries
+%usemodule[x][res-08] % rlx runtime conversion
+%usemodule[x][res-12] % rli external indentification
+
+\unprotect
+
+\setupcurrentlanguage[\s!en]
+
+\prependtoks
+ \ctxlua{statistics.starttiming(ctx)}%
+\to \everyjob
+
+\appendtoks
+ \ctxlua{statistics.stoptiming(ctx)}%
+\to \everyjob
+
+\appendtoks
+ \writestatus\m!lua{used config path - \ctxlua{tex.print(caches.configpath())}}%
+ \writestatus\m!lua{used cache path - \ctxlua{tex.print(caches.path)}}%
+\to \everydump
+
+\appendtoks
+ \ctxlua {
+ statistics.report_storage("log")
+ statistics.save_fmt_status("\jobname","\contextversion","context.tex")
+ }%
+\to \everydump
+
+\protect \errorstopmode \dump \endinput
diff --git a/tex/context/base/context.rme b/tex/context/base/context.rme
new file mode 100644
index 000000000..1b1e48902
--- /dev/null
+++ b/tex/context/base/context.rme
@@ -0,0 +1,85 @@
+Some Basic information
+----------------------
+
+There are currently three interfaces available:
+
+ cont-en the english version
+ cont-de the german version
+ cont-nl the dutch version
+ cont-cz the czech version
+ cont-ro the romanian version
+ cont-it the italian version
+
+One should compile one of these (or all) into a fmt file.
+When one uses the main file,
+
+ context the undefined version
+
+TeX ask for an interface language as well as a message
+language. Here one has to specify the full name (english,
+german, dutch, etc.) or use the default (enter). The \
+savest way to update the TeX and MetaPost format files
+is to use TeXExec:
+
+texexec --make --alone en nl metafun
+
+In the TeXExec manual you can read how to generate a format
+with specific fonts and patterns.
+
+By default only the english hyphenation patterns are loaded,
+unless more are enabled in:
+
+ cont-usr the typesetting language specifications
+
+Furthermore, users can preset commands etc in the file
+
+ cont-sys a system file loaded at runtime
+
+For questions and remarks on ConTeXt, one can subscribe to
+the list:
+
+ ntg-context@ntg.nl
+
+by sending the message
+
+ subscribe ntg-context
+
+to the list server:
+
+ majordomo@ntg.nl
+
+One can find more info at:
+
+ www.pragma-ade.com
+
+or at the mirror sites mentioned there.
+
+Don't hesitate to ask questions. ConTeXt can do a lot, and
+the manuals are always a bit behind and incomplete. Also take
+a look at the files
+
+ mreadme.pdf
+ minstall.pdf
+ mtexexec.pdf
+ mtexutil.pdf
+
+The teTeX, fpTeX, and 4TeX distributions demonstrate how
+ConTeXt can be integrated in a TeX directory structure.
+
+-------------------------
+
+functionality removed from mkiv:
+
+page-log : layers can do teh same and are more flexible
+core-dat : just use lua for database purposes
+core-swd : this was a temporary solution
+
+functionality changed in mkii and mkiv:
+
+xtag-map : no longer preloaded
+xtag-stk : no longer preloaded
+xtag-prs : no longer preloaded
+
+-------------------------
+
+Hans Hagen, pragma@wxs.nl
diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex
new file mode 100644
index 000000000..47489658e
--- /dev/null
+++ b/tex/context/base/context.tex
@@ -0,0 +1,225 @@
+%D \module
+%D [ file=context,
+%D version=1995.10.10,
+%D title=\CONTEXT,
+%D subtitle=\CONTEXT\ Format Generation,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 \catcode`\#=6
+
+%D From the next string (which is set by the script that assembles the
+%D distribution) later on we will calculate a number that can be used
+%D by use modules to identify the feature level. Starting with version
+%D 2004.8.30 the low level interface is english. Watch out and adapt
+%D your styles an modules.
+
+\edef\contextformat {\jobname}
+\edef\contextversion{2010.05.24 13:05}
+
+%D For those who want to use this:
+
+\let\fmtname \contextformat
+\let\fmtversion\contextversion
+
+\let\showcontextbanner\relax
+
+%D Here we will test for what branch of source files we will take. The
+%D file suffix depends on the maintream engine: either lua enhanced,
+%D or traditional:
+%D
+%D \starttyping
+%D mki : low level dutch
+%D mkii : low level english
+%D mkiv : lua enhanced
+%D \stoptyping
+%D
+%D There is no \type {mkiii} unless you want to tag the transition
+%D version that way (going completely etex, code cleanup and such).
+
+\ifx\normalinput\undefined \let\normalinput\input \fi
+
+%D We have two versions, one for \PDFTEX\ and \XETEX, and one for
+%D \LUATEX.
+
+\chardef\contextmarkmode = \ifx\directlua\undefined 2 \else 4 \fi
+
+\def\loadcorefile#1{\normalinput#1\relax}
+\def\loadmarkfile#1{\normalinput#1.\mksuffix\relax}
+
+\ifnum\contextmarkmode=4
+ \def\loadmarkiifile#1{} \let\loadmarkivfile\loadcorefile \edef\mksuffix {mkiv} \edef\contextmark{MKIV}
+\else
+ \def\loadmarkivfile#1{} \let\loadmarkiifile\loadcorefile \edef\mksuffix {mkii} \edef\contextmark{MKII}
+\fi
+
+\let\loadmkiifile\loadmarkiifile
+\let\loadmkivfile\loadmarkivfile
+\let\loadmkfile \loadmarkfile
+
+%D Welcome to the main module. When this module is ran through
+%D \type{initex} or \type {tex -i} or \type {whatevertex} using
+%D \type{whatever switch}, the \CONTEXT\ format file is
+%D generated. During this process the user is asked for an
+%D interface language. Supplying \type{dutch} will generate a
+%D dutch version of \CONTEXT, supplying \type {english} will of
+%D course end op in a english version.
+%D
+%D Another option is to use \TEXEXEC\ (for \MKII):
+%D
+%D \starttyping
+%D texexec --make [--alone] [--engine] [--all]
+%D texexec --make [--alone] [--engine] en nl ... metafun mptopdf
+%D \stoptyping
+%D
+%D More information can be found in the \TEXEXEC\ manual.
+%D
+%D For \MKIV\ you have to do:
+%D
+%D \starttyping
+%D luatools --generate
+%D context --make en nl ...
+%D \stoptyping
+
+%D When you write modules (or extensions) you should avoid
+%D conflicts with existing macro names and mechanisms. If you are
+%D coming from another macro package, don't assume that macros
+%D with the same name are doing the same! \CONTEXT\ was written
+%D from scratch and therefore similarities are often a coincidence
+%D (to some extent one always ends up with the same names for
+%D similar concepts). The underlying models for elementary subsystems
+%D that deal with encodings, languages and fonts probably differ.
+%D
+%D Time has learned that users coming from \LATEX\ should not fall
+%D into thinking that macros like \type {\protect} represent the
+%D same functionality in both systems; actually, due to the way
+%D \CONTEXT\ is set up, some of those macros do complete different
+%D things. Macro packages evolve independent of each other, which
+%D means that code written for one system will not work in another
+%D system, unless it's real generic code.
+%D
+%D An API will become available soon (keep an eye on the ConTeXt
+%D Wiki www.contextgarden.org) and or listen in to the context
+%D mailing list (ntg-context@ntg.nl). Much additional information
+%D can be found at the PRAGMA website (www.pragma-ade.com).
+
+%D We now go either the \MKII\ or \MKIV\ route:
+
+\loadmarkfile{context}
+
+%D Let's quit this file when doing a \type {cont-..} generation.
+
+\doifparentfileelse{context}{\donothing}{\endinput}
+
+%D Unless we're generating a \type {cont-..} format, we also
+%D do the following.
+
+%D Except from english, no hyphenation patterns are loaded
+%D yet. Users can specify their needs in the next module:
+
+\loaduserspecifications
+
+%D Next we default to the same language as the interface.
+
+\unprotect
+
+\installlanguage [\s!us] [\c!state=\v!start]
+
+\startinterface english
+ \installlanguage [\s!gb] [\c!state=\v!start]
+\stopinterface
+
+\appendtoks \language [\s!us] \to \everyjob
+\appendtoks \mainlanguage [\s!us] \to \everyjob
+
+\startinterface german
+
+ \installlanguage [\s!de] [\c!state=\v!start]
+
+ \appendtoks \language [\s!de] \to \everyjob
+ \appendtoks \mainlanguage [\s!de] \to \everyjob
+
+\stopinterface
+
+\startinterface dutch
+
+ \installlanguage [\s!nl] [\c!state=\v!start]
+
+ \appendtoks \language [\s!nl] \to \everyjob
+ \appendtoks \mainlanguage [\s!nl] \to \everyjob
+
+\stopinterface
+
+\startinterface czech
+
+ \installlanguage [\s!cs] [\c!state=\v!start]
+
+ \appendtoks \language [\s!cs] \to \everyjob
+ \appendtoks \mainlanguage [\s!cs] \to \everyjob
+
+\stopinterface
+
+\startinterface italian
+
+ \installlanguage [\s!it] [\c!state=\v!start]
+
+ \appendtoks \language [\s!it] \to \everyjob
+ \appendtoks \mainlanguage [\s!it] \to \everyjob
+
+\stopinterface
+
+\startinterface romanian
+
+ \installlanguage [\s!ro] [\c!state=\v!start]
+
+ \appendtoks \language [\s!ro] \to \everyjob
+ \appendtoks \mainlanguage [\s!ro] \to \everyjob
+
+\stopinterface
+
+\startinterface french
+
+ \installlanguage [\s!fr] [\c!state=\v!start]
+
+ \appendtoks \language [\s!fr] \to \everyjob
+ \appendtoks \mainlanguage [\s!fr] \to \everyjob
+
+\stopinterface
+
+\startinterface persian
+
+ \installlanguage [\s!pe] [\c!state=\v!start]
+
+ \appendtoks \language [\s!pe] \to \everyjob
+ \appendtoks \mainlanguage [\s!pe] \to \everyjob
+
+\stopinterface
+
+\protect
+
+%D Finally we (pre)load some fonts.
+
+\setupencoding[default=ec]
+
+\usetypescript[fallback][\defaultencoding]
+
+\setupbodyfont[rm,12pt]
+
+%D The next hook can be used to generate a local (extended)
+%D format. This file is only searched for at the current
+%D path.
+
+% \readlocfile{cont-def.tex}
+% {\writestatus{loading}{adding extensions from cont-def}}
+% {}
+
+%D Now dumping the format is all that's left to be done.
+
+\errorstopmode \dump
+
+\endinput
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua
new file mode 100644
index 000000000..dca1c7d10
--- /dev/null
+++ b/tex/context/base/core-con.lua
@@ -0,0 +1,605 @@
+if not modules then modules = { } end modules ['core-con'] = {
+ version = 1.001,
+ comment = "companion to core-con.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
This module implements a bunch of conversions. Some are more
+efficient than their counterpart, some are even
+slower but look nicer this way.
+
+
Some code may move to a module in the language namespace.
+--ldx]]--
+
+local utf = unicode.utf8
+
+local floor, date, time, concat = math.floor, os.date, os.time, table.concat
+local lower, format, rep = string.lower, string.format, string.rep
+local texsprint, utfchar = tex.sprint, utf.char
+local tonumber, tostring = tonumber, tostring
+
+local ctxcatcodes = tex.ctxcatcodes
+
+converters = converters or { }
+languages = languages or { }
+
+--~ ['arabic-digits'] = {
+--~ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664,
+--~ 0x0665, 0x0666, 0x0667, 0x0668, 0x0669
+--~ },
+--~ ['persian-digits'] = {
+--~ 0x06F0, 0x06F1, 0x06F2, 0x06F3, 0x06F4,
+--~ 0x06F5, 0x06F6, 0x06F7, 0x06F8, 0x06F9
+--~ },
+
+languages.counters = {
+ ['**'] = {
+ 0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
+ 0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
+ 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
+ 0x0075, 0x0076, 0x0077, 0x0078, 0x0079,
+ 0x007A
+ },
+ ['slovenian'] = {
+ 0x0061, 0x0062, 0x0063, 0x010D, 0x0064,
+ 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006A, 0x006B, 0x006C, 0x006D, 0x006E,
+ 0x006F, 0x0070, 0x0072, 0x0073, 0x0161,
+ 0x0074, 0x0075, 0x0076, 0x007A, 0x017E
+ },
+ ['greek'] = { -- this should be the lowercase table
+ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
+ 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
+ 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
+ 0x03A6, 0x03A7, 0x03A8, 0x03A9
+ },
+ ['arabic'] = {
+ 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
+ 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
+ 0x0643, 0x0644, 0x0645, 0x0646, 0x0633,
+ 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
+ 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
+ 0x0636, 0x0638, 0x063A,
+ },
+ ['persian'] = {
+ 0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
+ 0x0648, 0x0632, 0x062D, 0x0637, 0x0649,
+ 0x06A9, 0x0644, 0x0645, 0x0646, 0x0633,
+ 0x0639, 0x0641, 0x0635, 0x0642, 0x0631,
+ 0x0634, 0x062A, 0x062B, 0x062E, 0x0630,
+ 0x0636, 0x0638, 0x063A,
+ },
+ ['thai'] = {
+ 0xE050, 0xE051, 0xE052, 0xE053, 0xE054,
+ 0xE055, 0xE056, 0xE057, 0xE058, 0xE059
+ },
+ ['devangari'] = {
+ 0x0966, 0x0967, 0x0968, 0x0969, 0x096A,
+ 0x096B, 0x096C, 0x096D, 0x096E, 0x096F
+ },
+ ['gurmurkhi'] = {
+ 0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A,
+ 0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F
+ },
+ ['gujarati'] = {
+ 0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA,
+ 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF
+ },
+ ['tibetan'] = {
+ 0x0F20, 0x0F21, 0x0F22, 0x0F23, 0x0F24,
+ 0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29
+ },
+ ['korean'] = {
+ 0x3131, 0x3134, 0x3137, 0x3139, 0x3141,
+ 0x3142, 0x3145, 0x3147, 0x3148, 0x314A,
+ 0x314B, 0x314C, 0x314D, 0x314E
+ },
+ ['korean-parent'] = { -- parenthesed
+ 0x3200, 0x3201, 0x3202, 0x3203, 0x3204,
+ 0x3205, 0x3206, 0x3207, 0x3208, 0x3209,
+ 0x320A, 0x320B, 0x320C, 0x320D
+ },
+ ['korean-circle'] = { -- circled
+ 0x3260, 0x3261, 0x3262, 0x3263, 0x3264,
+ 0x3265, 0x3266, 0x3267, 0x3268, 0x3269,
+ 0x326A, 0x326B, 0x326C, 0x326D
+ },
+}
+
+local counters = languages.counters
+
+counters['ar'] = counters['arabic']
+counters['gr'] = counters['greek']
+counters['g'] = counters['greek']
+counters['sl'] = counters['slovenian']
+counters['kr'] = counters['korean']
+counters['kr-p'] = counters['korean-parent']
+counters['kr-c'] = counters['korean-circle']
+
+local fallback = utf.byte('0')
+
+local function chr(n,m)
+ if n > 0 and n < 27 then
+ texsprint(utfchar(n+m))
+ end
+end
+local function chrs(n,m)
+ if n > 26 then
+ chrs(floor((n-1)/26),m)
+ n = (n-1)%26 + 1
+ end
+ texsprint(utfchar(n+m))
+end
+local function maxchrs(n,m,cmd)
+ if n > m then
+ maxchrs(floor((n-1)/m),m,cmd)
+ n = (n-1)%m + 1
+ end
+ texsprint(ctxcatcodes, format("%s{%s}",cmd,n))
+end
+
+converters.chr = chr
+converters.chrs = chrs
+converters.maxchrs = maxchrs
+
+--~ more efficient but needs testing
+--~
+--~ local escapes = utffilters.private.escapes
+--~
+--~ local function do_alphabetic(n,mapping,chr)
+--~ local max = #mapping
+--~ if n > max then
+--~ do_alphabetic(floor((n-1)/max),max,chr)
+--~ n = (n-1)%max+1
+--~ end
+--~ n = chr(n,mapping)
+--~ texsprint(ctxcatcodes,escapes[n] or utfchar(n))
+--~ end
+
+--~ local lccodes, uccodes = characters.lccode, characters.uccode
+
+--~ local function do_alphabetic(n,mapping,chr)
+--~ local max = #mapping
+--~ if n > max then
+--~ do_alphabetic(floor((n-1)/max),mapping,chr)
+--~ n = (n-1)%max+1
+--~ end
+--~ characters.flush(chr(n,mapping))
+--~ end
+--~
+--~ local function lowercased(n,mapping) return characters.lccode(mapping[n] or fallback) end
+--~ local function uppercased(n,mapping) return characters.uccode(mapping[n] or fallback) end
+--~
+--~ function converters.alphabetic(n,code)
+--~ do_alphabetic(n,counters[code] or counters['**'],lowercased) -- lccode catches wrong tables
+--~ end
+--~
+--~ function converters.Alphabetic(n,code)
+--~ do_alphabetic(n,counters[code] or counters['**'],uppercased)
+--~ end
+
+--
+
+local function do_alphabetic(n,mapping,mapper)
+ local chr = mapper(mapping[n] or fallback)
+ local max = #mapping
+ if n > max then
+ do_alphabetic(floor((n-1)/max),mapping,mapper)
+ n = (n-1)%max+1
+ end
+ characters.flush(chr)
+end
+
+function converters.alphabetic(n,code)
+ do_alphabetic(n,counters[code] or counters['**'],characters.lccode)
+end
+
+function converters.Alphabetic(n,code)
+ do_alphabetic(n,counters[code] or counters['**'],characters.uccode)
+end
+
+--
+
+function converters.character (n) chr (n,96) end
+function converters.Character (n) chr (n,64) end
+function converters.characters(n) chrs(n,96) end
+function converters.Characters(n) chrs(n,64) end
+
+function converters.weekday(day,month,year)
+ texsprint(date("%w",time{year=year,month=month,day=day})+1)
+end
+
+function converters.isleapyear(year)
+ return (year % 400 == 0) or ((year % 100 ~= 0) and (year % 4 == 0))
+end
+
+function converters.leapyear(year)
+ if converters.isleapyear(year) then texsprint(1) else texsprint(0) end
+end
+
+local days = {
+ [false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ [true] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+}
+
+function converters.nofdays(year,month)
+ texsprint(days[converters.isleapyear(year)][month])
+end
+
+function converters.year () texsprint(date("%Y")) end
+function converters.month () texsprint(date("%m")) end
+function converters.hour () texsprint(date("%H")) end
+function converters.minute () texsprint(date("%M")) end
+function converters.second () texsprint(date("%S")) end
+function converters.textime() texsprint(tonumber(date("%H"))*60+tonumber(date("%M"))) end
+
+local roman = {
+ { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' },
+ { [0] = '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC' },
+ { [0] = '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM' },
+}
+
+local function toroman(n)
+ if n >= 4000 then
+ return toroman(floor(n/1000)) .. " " .. toroman(n%1000)
+ else
+ return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] ..
+ roman[2][floor((n%100)/10)] .. roman[1][floor((n% 10)/1)]
+ end
+end
+
+function converters.romannumerals(n) return texsprint(lower(toroman(n))) end
+function converters.Romannumerals(n) return texsprint( toroman(n) ) end
+
+converters.toroman = toroman
+
+--~ local small = {
+--~ 0x0627, 0x066E, 0x062D, 0x062F, 0x0647, 0x0648, 0x0631
+--~ }
+
+--~ local large = {
+--~ { 0x0627, 0x0628, 0x062C, 0x062F, 0x0647, 0x0648, 0x0632, 0x062D, 0x0637, },
+--~ { 0x064A, 0x0643, 0x0644, 0x0645, 0x0646, 0x0633, 0x0639, 0x0641, 0x0635, },
+--~ { 0x0642, 0x0631, 0x0634, 0x062A, 0x062B, 0x062E, 0x0630, 0x0636, 0x0638, },
+--~ { 0x063A },
+--~ }
+
+local small = {
+ "ا", "ٮ", "ح", "د", "ه", "و", "ر",
+}
+
+local medium = {
+ "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" ,
+ "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" ,
+ "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" ,
+ "غ" ,
+}
+
+local large = {
+ { "ا", "ب", "ج", "د", "ه", "و","ز", "ح", "ط" },
+ { "ي", "ك", "ل", "م", "ن", "س", "ع", "ف", "ص" },
+ { "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ" },
+ { "غ" },
+}
+
+function converters.toabjad(n,what)
+ if n <= 0 or n >= 2000 then
+ return tostring(n)
+ elseif what == 2 and n <= 7 then
+ return small[n]
+ elseif what == 3 and n <= 28 then
+ return medium[n]
+ else
+ local a, b, c, d
+ a, n = floor(n/1000), n % 1000 -- mod(n,1000)
+ b, n = floor(n/ 100), n % 100 -- mod(n, 100)
+ c, n = floor(n/ 10), n % 10 -- mod(n, 10)
+ d, n = floor(n/ 1), n % 1 -- mod(n, 1)
+ return (large[4][a] or "") .. (large[3][b] or "") .. (large[2][c] or "") .. (large[1][d] or "")
+ end
+end
+
+function converters.abjadnumerals (n) return texsprint(converters.toabjad(n,false)) end
+function converters.abjadnodotnumerals(n) return texsprint(converters.toabjad(n,true)) end
+
+local vector = {
+ normal = {
+ [0] = "〇",
+ [1] = "一",
+ [2] = "二",
+ [3] = "三",
+ [4] = "四",
+ [5] = "五",
+ [6] = "六",
+ [7] = "七",
+ [8] = "八",
+ [9] = "九",
+ [10] = "十",
+ [100] = "百",
+ [1000] = "千",
+ [10000] = "万",
+ [100000000] = "亿",
+ },
+ cap = {
+ [0] = "零",
+ [1] = "壹",
+ [2] = "贰",
+ [3] = "叁",
+ [4] = "肆",
+ [5] = "伍",
+ [6] = "陆",
+ [7] = "柒",
+ [8] = "捌",
+ [9] = "玖",
+ [10] = "拾",
+ [100] = "佰",
+ [1000] = "仟",
+ [10000] = "萬",
+ [100000000] = "亿",
+ },
+ all = {
+ [0] = "〇",
+ [1] = "一",
+ [2] = "二",
+ [3] = "三",
+ [4] = "四",
+ [5] = "五",
+ [6] = "六",
+ [7] = "七",
+ [8] = "八",
+ [9] = "九",
+ [10] = "十",
+ [20] = "廿",
+ [30] = "卅",
+ [100] = "百",
+ [1000] = "千",
+ [10000] = "万",
+ [100000000] = "亿",
+ }
+}
+
+--~ function tochinese(n,name) -- normal, caps, all
+--~ local result = { }
+--~ local vector = vector[name] or vector.normal
+--~ while true do
+--~ if n == 0 then
+--~ break
+--~ elseif n >= 100000000 then
+--~ local m = floor(n/100000000)
+--~ if m > 1 then result[#result+1] = tochinese(m) end
+--~ result[#result+1] = vector[100000000]
+--~ n = n % 100000000
+--~ elseif n >= 10000000 then
+--~ result[#result+1] = tochinese(floor(n/10000))
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 1000000 then
+--~ result[#result+1] = tochinese(floor(n/10000))
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 100000 then
+--~ result[#result+1] = tochinese(floor(n/10000))
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 10000 then
+--~ local m = floor(n/10000)
+--~ if m > 1 then result[#result+1] = vector[m] end
+--~ result[#result+1] = vector[10000]
+--~ n = n % 10000
+--~ elseif n >= 1000 then
+--~ local m = floor(n/1000)
+--~ if m > 1 then result[#result+1] = vector[m] end
+--~ result[#result+1] = vector[1000]
+--~ n = n % 1000
+--~ elseif n >= 100 then
+--~ local m = floor(n/100)
+--~ if m > 1 then result[#result+1] = vector[m] end
+--~ result[#result+1] = vector[100]
+--~ n = n % 100
+--~ elseif n >= 10 then
+--~ local m = floor(n/10)
+--~ if vector[m*10] then
+--~ result[#result+1] = vector[m*10]
+--~ else
+--~ result[#result+1] = vector[m]
+--~ result[#result+1] = vector[10]
+--~ end
+--~ n = n % 10
+--~ else
+--~ result[#result+1] = vector[n]
+--~ break
+--~ end
+--~ end
+--~ return concat(result)
+--~ end
+
+function tochinese(n,name) -- normal, caps, all
+ -- improved version by Li Yanrui
+ local result = { }
+ local vector = vector[name] or vector.normal
+ while true do
+ if n == 0 then
+ break
+ elseif n >= 100000000 then
+ local m = floor(n/100000000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[100000000]
+ local z = n - m * 100000000
+ if z > 0 and z < 10000000 then result[#result+1] = vector[0] end
+ n = n % 100000000
+ elseif n >= 10000000 then
+ local m = floor(n/10000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 1000000 then
+ local m = floor(n/10000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 100000 then
+ local m = floor(n/10000)
+ result[#result+1] = tochinese(m,name)
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 10000 then
+ local m = floor(n/10000)
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[10000]
+ local z = n - m * 10000
+ if z > 0 and z < 1000 then result[#result+1] = vector[0] end
+ n = n % 10000
+ elseif n >= 1000 then
+ local m = floor(n/1000)
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[1000]
+ local z = n - m * 1000
+ if z > 0 and z < 100 then result[#result+1] = vector[0] end
+ n = n % 1000
+ elseif n >= 100 then
+ local m = floor(n/100)
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[100]
+ local z = n - m * 100
+ if z > 0 and z < 10 then result[#result+1] = vector[0] end
+ n = n % 100
+ elseif n >= 10 then
+ local m = floor(n/10)
+ if m > 1 and vector[m*10] then
+ result[#result+1] = vector[m*10]
+ else
+ result[#result+1] = vector[m]
+ result[#result+1] = vector[10]
+ end
+ n = n % 10
+ else
+ result[#result+1] = vector[n]
+ break
+ end
+ end
+ if (result[1] == vector[1] and result[2] == vector[10]) then
+ result[1] = ""
+ end
+ return concat(result)
+end
+
+--~ local t = { 1,10,15,25,35,45,11,100,111,1111,10000,11111,100000,111111,1111111,11111111,111111111,100000000,1111111111,11111111111,111111111111,1111111111111 }
+--~ for k=1,#t do
+--~ local v = t[k]
+--~ print(v,tochinese(v),tochinese(v,"all"),tochinese(v,"cap"))
+--~ end
+
+function converters.chinesenumerals (n) return texsprint(tochinese(n,"normal")) end
+function converters.chinesecapnumerals(n) return texsprint(tochinese(n,"cap" )) end
+function converters.chineseallnumerals(n) return texsprint(tochinese(n,"all" )) end
+
+--~ Well, since the one asking for this didn't test it the following code is not
+--~ enabled.
+--~
+--~ -- This Lua version is based on a Javascript by Behdad Esfahbod which in turn
+--~ -- is based on GPL'd code by Roozbeh Pournader of the The FarsiWeb Project
+--~ -- Group: http://www.farsiweb.info/jalali/jalali.js.
+--~ --
+--~ -- We start tables at one, I kept it zero based in order to stay close to
+--~ -- the original.
+--~ --
+--~ -- Conversion by Hans Hagen
+--~
+--~ local g_days_in_month = { [0]=31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+--~ local j_days_in_month = { [0]=31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 }
+--~
+--~ local function div(a,b)
+--~ return math.floor(a/b)
+--~ end
+--~
+--~ local function remainder(a,b)
+--~ return a - div(a,b)*b
+--~ end
+--~
+--~ function gregorian_to_jalali(gy,gm,gd)
+--~ local jy, jm, jd, g_day_no, j_day_no, j_np, i
+--~ gy, gm, gd = gy - 1600, gm - 1, gd - 1
+--~ g_day_no = 365*gy + div((gy+3),4) - div((gy+99),100) + div((gy+399),400)
+--~ i = 0
+--~ while i < gm do
+--~ g_day_no = g_day_no + g_days_in_month[i]
+--~ i = i + 1
+--~ end
+--~ if (gm>1 and ((gy%4==0 and gy%100~=0) or (gy%400==0))) then
+--~ g_day_no = g_day_no + 1
+--~ end
+--~ g_day_no = g_day_no + gd
+--~ j_day_no = g_day_no - 79
+--~ j_np = div(j_day_no,12053)
+--~ j_day_no = remainder(j_day_no,12053)
+--~ jy = 979 + 33*j_np + 4*div(j_day_no,1461)
+--~ j_day_no = remainder(j_day_no,1461)
+--~ if j_day_no >= 366 then
+--~ jy = jy + div((j_day_no-1),365)
+--~ j_day_no = remainder((j_day_no-1),365)
+--~ end
+--~ i = 0
+--~ while i < 11 and j_day_no >= j_days_in_month[i] do
+--~ j_day_no = j_day_no - j_days_in_month[i]
+--~ i = i + 1
+--~ end
+--~ jm = i + 1
+--~ jd = j_day_no + 1
+--~ return jy, jm, jd
+--~ end
+--~
+--~ function jalali_to_gregorian(jy,jm,jd)
+--~ local gy, gm, gd, g_day_no, j_day_no, leap, i
+--~ jy, jm, jd = jy - 979, jm - 1, jd - 1
+--~ j_day_no = 365*jy + div(jy,33)*8 + div((remainder(jy,33)+3),4)
+--~ i = 0
+--~ while i < jm do
+--~ j_day_no = j_day_no + j_days_in_month[i]
+--~ i = i + 1
+--~ end
+--~ j_day_no = j_day_no + jd
+--~ g_day_no = j_day_no + 79
+--~ gy = 1600 + 400*div(g_day_no,146097)
+--~ g_day_no = remainder (g_day_no, 146097)
+--~ leap = 1
+--~ if g_day_no >= 36525 then
+--~ g_day_no = g_day_no - 1
+--~ gy = gy + 100*div(g_day_no,36524)
+--~ g_day_no = remainder (g_day_no, 36524)
+--~ if g_day_no >= 365 then
+--~ g_day_no = g_day_no + 1
+--~ else
+--~ leap = 0
+--~ end
+--~ end
+--~ gy = gy + 4*div(g_day_no,1461)
+--~ g_day_no = remainder (g_day_no, 1461)
+--~ if g_day_no >= 366 then
+--~ leap = 0
+--~ g_day_no = g_day_no - 1
+--~ gy = gy + div(g_day_no, 365)
+--~ g_day_no = remainder(g_day_no, 365)
+--~ end
+--~ i = 0
+--~ while g_day_no >= g_days_in_month[i] + ((i == 1 and leap) or 0) do
+--~ g_day_no = g_day_no - g_days_in_month[i] + ((i == 1 and leap) or 0)
+--~ i = i + 1
+--~ end
+--~ gm = i + 1
+--~ gd = g_day_no + 1
+--~ return gy, gm, gd
+--~ end
+--~
+--~ print(gregorian_to_jalali(2009,02,24))
+--~ print(jalali_to_gregorian(1387,12,06))
diff --git a/tex/context/base/core-con.mkii b/tex/context/base/core-con.mkii
new file mode 100644
index 000000000..c39bdd9d4
--- /dev/null
+++ b/tex/context/base/core-con.mkii
@@ -0,0 +1,969 @@
+%D \module
+%D [ file=core-con,
+%D version=1997.26.08,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Conversion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Conversion}
+
+\unprotect
+
+\ifx\currentlanguage\undefined \let\currentlanguage\empty \fi
+\ifx\labeltext \undefined \let\labeltext\firstofoneargument \fi
+
+%D This module deals with all kind of conversions from numbers
+%D and dates. I considered splitting this module in a support
+%D one and a core one, but to keep things simple as well as
+%D preserve the overview, I decided against splitting.
+
+\let\spr\firstofoneargument % separator
+\let\stp\firstofoneargument % stopper
+
+% cleaner, some day:
+%
+% \def\isolateseparators % etex only, even works with list separator overloading
+% {\unexpanded\def\spr##1{{##1}}%
+% \unexpanded\def\stp##1{{##1}}}
+
+% needed for arab :
+
+\def\isolateseparators % even works with list separator overloading
+ {\def\spr##1{{##1}}%
+ \def\stp##1{{##1}}}
+
+%D \macros
+%D {numbers}
+%D
+%D First we deal with the dummy conversion of numbers using the
+%D \TEX\ primitive \type{\number}. The uppercase alternative is
+%D only there for compatibility with the other conversion
+%D macros. We could do without \type{#1} but this way we get
+%D rid of unwanted braces. For the savety we also define a
+%D non||sence uppercase alternative.
+%D
+%D \showsetup{numbers}
+%D
+%D \starttyping
+%D \def\numbers#1{\number#1}
+%D \def\Numbers#1{\number#1}
+%D \stoptyping
+%D
+%D Due to read ahead, as in \type{[\pagenumber\space]} the space will
+%D disappear, unless we use:
+
+\def\numbers#1{\purenumber{#1}}
+\def\Numbers#1{\purenumber{#1}}
+
+%D \macros
+%D {romannumerals,Romannumerals}
+%D
+%D \TEX\ the program uses a rather tricky conversion from
+%D numbers to their roman counterparts. This conversion could
+%D of course be programmed in \TEX\ itself, but I guess Knuth
+%D found the programming trick worth presenting.
+%D
+%D \showsetup{romannumerals}
+%D \showsetup{Romannumerals}
+
+%D When upcasing the result, we just follow the text book rules
+%D of expansion. Later on we'll see some more uppercase tricks.
+
+\def\romannumerals#1%
+ {\romannumeral#1}
+
+%D For some years we had \unknown
+%D
+%D \starttyping
+%D \def\Romannumerals#1%
+%D {\uppercase\expandafter{\romannumeral#1}}
+%D \stoptyping
+%D
+%D \unknown but we need to be fully expandable in order to get
+%D the utility output file right, so now we have the following
+%D solution. It was Patrick Gundlach who first noticed this
+%D ommision.
+
+\def\Romannumerals#1%
+ {\expandafter\doRomannumerals\number#1\relax}
+
+\def\doRomannumerals#1#2\relax % spaces after ifcase prevent \relax
+ {\ifnum#1#2<10
+ \ifcase0#1#2 \or I\or II\or III\or IV\or V\or VI\or VII\or VIII\or IX\fi
+ \else\ifnum#1#2<100
+ \ifcase0#1 \or X\or XX\or XXX\or XL\or L\or LX\or LXX\or LXXX\or XC\fi
+ \doRomannumerals#2\relax
+ \else\ifnum#1#2<1000
+ \ifcase0#1 \or C\or CC\or CCC\or CD\or D\or DC\or DCC\or DCCC\or CM\fi
+ \doRomannumerals#2\relax
+ \else\ifnum#1#2<4000
+ \ifcase0#1 \or M\or MM\or MMM\fi
+ \doRomannumerals#2\relax
+ \else
+ \uppercase\expandafter{\romannumeral#1#2}%
+ \fi\fi\fi\fi}
+
+%D \macros
+%D {character,Character}
+%D
+%D Converting a number into a character can of course only
+%D be done with numbers less or equal to~26. At the cost of
+%D much more macros a faster conversion is possible, using:
+%D
+%D \starttyping
+%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}}
+%D \stoptyping
+%D
+%D But we prefer a simpel \type{\case}.
+%D
+%D \showsetup{character}
+%D \showsetup{Character}
+
+\def\unknowncharacter{-} % else in lists \relax
+
+%D Big case statements but pretty fast:
+
+\def\character#1%
+ {\ifcase#1\unknowncharacter
+ \or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m%
+ \or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z%
+ \else
+ \unknowncharacter
+ \fi}
+
+\def\Character#1%
+ {\ifcase#1\unknowncharacter
+ \or A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or K\or L\or M%
+ \or N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or X\or Y\or Z%
+ \else
+ \unknowncharacter
+ \fi}
+
+%D \macros
+%D {characters,Characters}
+%D
+%D Converting large numbers is supported by the next two
+%D macros. This time we just count on: $\cdots$~x, y, z, aa,
+%D ab, ac~$\cdots$.
+%D
+%D \showsetup{characters}
+%D \showsetup{Characters}
+
+%D The fully expandable alternative:
+
+\def\dodoconvertcharacters#1#2#3%
+ {\ifcase#3\else
+ \ifnum#3>#1
+ \expandafter\doconvertcharacters\expandafter#2\expandafter{\the\numexpr(#3+12)/#1-1\relax}%
+ \expandafter#2\expandafter{\the\numexpr#3-((#3+12)/#1-1)*#1\relax}%
+ \else
+ \expandafter#2\expandafter{\number#3}%
+ \fi
+ \fi}
+
+\def\doconvertcharacters{\dodoconvertcharacters{26}}
+
+\def\characters{\doconvertcharacters\character}
+\def\Characters{\doconvertcharacters\Character}
+
+%D \macros
+%D {greeknumerals,Greeknumerals}
+%D
+%D Why should we only honour the romans, and not the greek?
+
+\def\greeknumerals#1%
+ {% no longer needed: \mathematics
+ {\ifcase#1\unknowncharacter\or
+ \alpha \or \beta \or \gamma \or \delta \or
+ \varepsilon \or \zeta \or \eta \or \theta \or
+ \iota \or \kappa \or \lambda \or \mu \or
+ \nu \or \xi \or \omicron \or \pi \or
+ \varrho \or \sigma \or \tau \or \upsilon \or
+ \phi \or \chi \or \psi \or \omega
+ \else
+ \unknowncharacter
+ \fi}}
+
+\def\Greeknumerals#1%
+ {% no longer needed: \mathematics
+ {\ifcase#1\unknowncharacter \or
+ \Alpha \or \Beta \or \Gamma \or \Delta \or
+ \Epsilon \or \Zeta \or \Eta \or \Theta \or
+ \Iota \or \Kappa \or \Lambda \or \Mu \or
+ \Nu \or \Xi \or \Omicron \or \Pi \or
+ \Rho \or \Sigma \or \Tau \or \Upsilon \or
+ \Phi \or \Xi \or \Psi \or \Omega
+ \else
+ \unknowncharacter
+ \fi}}
+
+%D \macros
+%D {oldstylenumerals,oldstyleromannumerals}
+%D
+%D These conversions are dedicated to Frans Goddijn.
+
+\unexpanded\def\oldstylenumerals#1%
+ {{\os\number#1}}
+
+\unexpanded\def\oldstyleromannumerals#1%
+ {{\leftrulefalse\rightrulefalse\ss\txx\boxrulewidth.15ex
+ \ruledhbox spread .15em{\hss\uppercased{\romannumerals{#1}}\hss}}}
+
+%D \macros
+%D {protectconversion}
+%D
+%D The previous two commands are not robust enough to be
+%D passed to \type{\write} en \type{\message}. That's why we
+%D introduce:
+
+\def\protectconversion
+ {\def\doconvertcharacters##1{##1}} % was \relax
+ %{\def\doconvertcharacters##1{\ifcase0##1 0\else##1\fi}} more save
+
+%D \macros
+%D {normaltime,normalyear,normalmonth,normalday}
+%D
+%D The last part of this module is dedicated to converting
+%D dates. Because we want to use as meaningful commands as
+%D possible, and because \TEX\ already uses up some of those,
+%D we save the original meanings.
+
+\savenormalmeaning\time
+\savenormalmeaning\year
+\savenormalmeaning\month
+\savenormalmeaning\day
+
+%D \macros
+%D {month,MONTH}
+%D
+%D Converting the month number into a month name is done
+%D using a case statement, abstact values and the label
+%D mechanism. This way users can easily redefine a label from
+%D for instance german into austrian.
+%D
+%D \starttyping
+%D \setuplabeltext [de] [january=J\"anner]
+%D \stoptyping
+%D
+%D Anyhow, the conversion looks like:
+
+\def\domonthtag#1%
+ {\ifcase#1%
+ \or \v!january \or \v!february \or \v!march \or \v!april
+ \or \v!may \or \v!june \or \v!july \or \v!august
+ \or \v!september \or \v!october \or \v!november \or \v!december
+ \else
+ \v!unknown
+ \fi}
+
+\def\doconvertmonthlong #1{\labeltext{\domonthtag{#1}}}
+\def\doconvertmonthshort#1{\labeltext{\domonthtag{#1}:\s!mnem}}
+
+\let\doconvertmonth\doconvertmonthlong
+
+%D We redefine the \TEX\ primitive \type{\month} as:
+%D
+%D \showsetup{month}
+%D \showsetup{MONTH}
+
+\def\monthlong {\doconvertmonthlong}
+\def\monthshort{\doconvertmonthshort}
+\def\month {\doconvertmonth}
+
+\def\MONTH #1{{\let\labeltext\LABELTEXT\month {#1}}}
+\def\MONTHLONG #1{{\let\labeltext\LABELTEXT\monthlong {#1}}}
+\def\MONTHSHORT#1{{\let\labeltext\LABELTEXT\monthshort{#1}}}
+
+%D We never explicitly needed this, but Tobias Burnus pointed
+%D out that it would be handy to convert to the day of the
+%D week. In doing so, we have to calculate the total number of
+%D days, taking leapyears into account. For those who are
+%D curious:
+%D
+%D \startitemize[packed]
+%D \item years that can be divided by 4 are leapyears
+%D \item exept years that can be divided by 100
+%D \item unless years can be divided by 400
+%D \stopitemize
+%D
+%D This makes the year 1900 into a normal year and 1996 and
+%D 2000 into leap years, right? Well, converting to string
+%D looks familiar:
+
+\def\doconvertday#1%
+ {\labeltext
+ {\ifcase#1
+ \or \v!sunday \or \v!monday \or \v!tuesday \or \v!wednesday
+ \or \v!thursday \or \v!friday \or \v!saturday \fi}}
+
+%D \macros
+%D {getdayoftheweek, dayoftheweek}
+%D
+%D The conversion algoritm is an old one and a translation from
+%D a procedure written in MODULA~2 back in the 80's. I finaly
+%D found the 4--100-400 rules in some enclopedia. Look at this
+%D messy low level routine that takes the day, month and year
+%D as arguments:
+
+\newcount\normalweekday
+
+\def\getdayoftheweek#1#2#3%
+ {\bgroup
+ \!!counta#3\relax
+ \advance\!!counta \minusone
+ \!!countb\!!counta
+ \multiply\!!countb 365
+ \advance\!!countb \ifcase#2\relax
+ 0 \or 0 \or 31 \or 59 \or 90 \or120 \or151 \or
+ 181 \or212 \or243 \or273 \or304 \or334 \or365 \fi
+ \advance\!!countb #1\relax
+ \ifnum#2>2
+ \doifleapyearelse{#3}{\advance\!!countb 1}{}\relax
+ \fi
+ \!!countc\!!counta
+ \dosetdivision\!!countc4\!!countc
+ \advance\!!countb \!!countc
+ \!!countc\!!counta
+ \dosetdivision\!!countc{100}\!!countc
+ \advance\!!countb -\!!countc
+ \!!countc\!!counta
+ \dosetdivision\!!countc{400}\!!countc
+ \advance\!!countb \!!countc
+ \dosetmodulo\!!countb7\!!countb
+ \advance\!!countb \plusone
+ \@EA\egroup\@EA\normalweekday\the\!!countb\relax}
+
+\def\dayoftheweek#1#2#3%
+ {\getdayoftheweek{#1}{#2}{#3}\doconvertday{\normalweekday}}
+
+%D Using this macro in
+%D
+%D \startbuffer
+%D monday: \dayoftheweek {4} {5} {1992}
+%D friday: \dayoftheweek {16} {6} {1995}
+%D monday: \dayoftheweek {25} {8} {1997}
+%D saturday: \dayoftheweek {30} {8} {1997}
+%D tuesday: \dayoftheweek {2} {1} {1996}
+%D tuesday: \dayoftheweek {7} {1} {1997}
+%D tuesday: \dayoftheweek {13} {1} {1998}
+%D friday: \dayoftheweek {1} {1} {2000}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D gives
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D The macro \type {\getdayoftheweek} can be used to calculate
+%D the number \type {\normalweekday}.
+
+%D \macros
+%D {weekday,WEEKDAY}
+%D
+%D The first one is sort of redundant. It takes the day
+%D number argument.
+%D
+%D \showsetup{weekday}
+%D \showsetup{WEEKDAY}
+
+\def\weekday
+ {\doconvertday}
+
+\def\WEEKDAY#1%
+ {{\let\labeltext\LABELTEXT\doconvertday{#1}}}
+
+%D \macros
+%D {weekoftheday}
+%D
+%D {\em not yet implemented:}
+%D
+%D \starttyping
+%D \def\weekoftheday#1#2#3%
+%D {}
+%D \stoptyping
+
+%D \macros
+%D {doifleapyearelse,
+%D getdayspermonth}
+%D
+%D Sometimes we need to know if we're dealing with a
+%D leapyear, so here is a testmacro:
+%D
+%D \starttyping
+%D \doifleapyearelse{year}{yes}{no}
+%D \stoptyping
+%D
+%D An example of its use can be seen in the macro
+%D
+%D \starttyping
+%D \getdayspermonth{year}{month}
+%D \stoptyping
+%D
+%D The number of days is available in the macro \type
+%D {\numberofdays}.
+
+\def\doifleapyearelse#1% #2#3%
+ {\bgroup
+ \!!doneafalse
+ \!!counta#1%
+ \dosetmodulo\!!counta4\!!countb
+ \ifcase\!!countb
+ \dosetmodulo\!!counta{100}\!!countb
+ \ifcase\!!countb \else \!!doneatrue \fi
+ \dosetmodulo\!!counta{400}\!!countb
+ \ifcase\!!countb \!!doneatrue \fi
+ \fi
+ \if!!donea
+ \egroup\@EA\firstoftwoarguments % \def\next{#2}%
+ \else
+ \egroup\@EA\secondoftwoarguments % \def\next{#3}%
+ \fi} % \next}
+
+% untested but cleaner:
+%
+% \def\doifleapyearelse#1% #2#3%
+% {\bgroup
+% \dosetmodulo{#1}{400}\scratchcounter
+% \ifcase\scratchcounter
+% \else
+% \dosetmodulo{#1}{100}\scratchcounter
+% \ifcase\scratchcounter
+% \scratchcounter\plusone
+% \else
+% \dosetmodulo{#1}4\scratchcounter
+% \fi
+% \fi
+% \ifcase\scratchcounter
+% \egroup\@EA\firstoftwoarguments
+% \else
+% \egroup\@EA\secondoftwoarguments
+% \fi}
+
+\def\getdayspermonth#1#2%
+ {\doifleapyearelse{#1}
+ {\def\numberofdays{29}}
+ {\def\numberofdays{28}}%
+ \edef\numberofdays
+ {\ifcase#2 \or31\or\numberofdays\or31\or30\or
+ 31\or30\or31\or31\or30\or31\or30\or31\fi}}
+
+%D \macros
+%D {currentdate, date}
+%D
+%D We use these conversion macros in the date formatting
+%D macro:
+%D
+%D \showsetup{currentdate}
+%D
+%D This macro takes care of proper spacing and delivers for
+%D instance:
+%D
+%D \startbuffer
+%D \currentdate[weekday,day,month,year] % still dutch example
+%D \currentdate[WEEKDAY,day,MONTH,year] % still dutch example
+%D \stopbuffer
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D depending of course on the keywords. Here we gave:
+%D
+%D \typebuffer
+%D
+%D If needed one can also add non||keywords, like in
+%D
+%D \startbuffer
+%D \currentdate[dd,--,mm,--,yy]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or typeset: \getbuffer.
+%D
+%D When no argument is passed, the current date is given as
+%D specified per language (using \type{\installlanguage}).
+%D
+%D \showsetup{currentdate}
+%D
+%D \startbuffer
+%D \date
+%D \date[d=12,m=12,y=1998][weekday]
+%D \date[d=12,m=12,y=1998]
+%D \stopbuffer
+%D
+%D We can also typeset arbitrary dates, using the previous
+%D command.
+%D
+%D \typebuffer
+%D
+%D The date is specified by one character keys. When no date
+%D is given, we get the current date.
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\def\kenmerkdatumpatroon{j,mm,dd} % jj,mm,dd changed at januari 1-1-2000
+
+\newsignal\datesignal
+
+\def\dobetweendates
+ {\ifdim\lastskip=\datesignal\relax\else
+ \unskip\space
+ \hskip\datesignal\relax
+ \fi}
+
+\newtoks \everycurrentdate
+
+\def\complexcurrentdate[#1]%
+ {\bgroup
+ \the\everycurrentdate
+ \def\betweendates{\let\betweendates\dobetweendates}%
+ % was \processcommacommandp[#1]\docomplexcurrentdate
+ \safeedef\ascii{\empty#1}% keep encoded chars
+ \@EA\processcommalist\@EA[\ascii]\docomplexcurrentdate
+ \ifdim\lastskip=\datesignal\relax
+ \unskip
+ \fi
+ \egroup}
+
+\def\docomplexcurrentdate#1%
+ {\lowercase{\edef\!!stringa{#1}}% permits usage in \smallcapped
+ \expanded{\processaction[\!!stringa]}% [#1]
+ [ \v!day=>\betweendates\the\normalday,
+ %\v!day+=>\betweendates\ordinaldaynumber\normalday,
+ \v!day+=>\betweendates\convertnumber{\v!day+}\normalday,
+ \v!month=>\betweendates\month\normalmonth,
+ \v!year=>\betweendates\the\normalyear,
+ \v!space=>\unskip\ \hskip\datesignal,% optimization -)
+ \ =>\unskip\ \hskip\datesignal,% optimization -)
+ d=>\convertnumber\v!day\normalday,
+ %d+=>\ordinaldaynumber\normalday,
+ d+=>\convertnumber{\v!day+}\normalday,
+ m=>\convertnumber\v!month\normalmonth,
+ j=>\convertnumber\v!year\normalyear,
+ y=>\convertnumber\v!year\normalyear,
+ w=>\betweendates\dayoftheweek\normalday\normalmonth\normalyear,
+ dd=>\ifnum\normalday >9 \else0\fi\the\normalday,
+ %dd+=>\ordinaldaynumber{\ifnum\normalday >9 \else0\fi\the\normalday},
+ dd+=>\convertnumber{\v!day+}{\ifnum\normalday >9 \else0\fi\the\normalday},
+ mm=>\ifnum\normalmonth>9 \else0\fi\the\normalmonth,
+ jj=>\expandafter\gobbletwoarguments\the\normalyear,
+ yy=>\expandafter\gobbletwoarguments\the\normalyear,
+ \v!weekday=>\betweendates\dayoftheweek\normalday\normalmonth\normalyear,
+ \v!referral=>\expanded{\complexcurrentdate[\kenmerkdatumpatroon]},
+ \s!unknown=>\unskip
+ % #1 and not the lowercased \commalistelement, vietnamese has text
+ % {} because #1 can have comma, like: {\ ,}
+ {#1}%
+ \hskip\datesignal
+ \def\betweendates{\let\betweendates\dobetweendates}]}
+
+\def\simplecurrentdate
+ {\expanded{\complexcurrentdate[\currentdatespecification]}}
+
+\definecomplexorsimple\currentdate
+
+\def\dodate[#1][#2]%
+ {\bgroup
+ \iffirstargument
+ \getparameters[\??da][d=\normalday,m=\normalmonth,y=\normalyear,#1]%
+ \normalday \@@dad\relax
+ \normalmonth\@@dam\relax
+ \normalyear \@@day\relax
+ \ifsecondargument
+ \currentdate[#2]%
+ \else
+ \currentdate
+ \fi
+ \else
+ \currentdate
+ \fi
+ \egroup}
+
+\def\date
+ {\dodoubleempty\dodate}
+
+%D \macros
+%D {currenttime}
+%D
+%D The currenttime is actually the jobtime. You can specify
+%D a pattern similar to the previous date macro using the
+%D keys \type {h}, \type {m} and a separator.
+
+\def\calculatecurrenttime
+ {\dosetdivision\time{60}\scratchcounter
+ \edef\currenthour {\ifnum\scratchcounter<10 0\fi \the\scratchcounter}%
+ \dosetmodulo \time{60}\scratchcounter
+ \edef\currentminute{\ifnum\scratchcounter<10 0\fi \the\scratchcounter}}
+
+\let\currenthour \!!plusone
+\let\currentminute\!!plusone
+
+\def\currenttimespecification{h,:,m}
+
+\def\complexcurrenttime[#1]%
+ {\calculatecurrenttime
+ \processallactionsinset[#1]
+ [h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]}
+
+\def\simplecurrenttime
+ {\expanded{\complexcurrenttime[\currenttimespecification]}}
+
+\definecomplexorsimple\currenttime
+
+%D Because we're dealing with dates, we also introduce a few
+%D day loops:
+%D
+%D \starttyping
+%D \processmonth{year}{month}{command}
+%D \processyear{year}{command}{before}{after}
+%D \stoptyping
+%D
+%D The counters \type {\normalyear}, \type {\normalmonth} and
+%D \type{\normalday} can be used for for date manipulations.
+
+\long\def\processmonth#1#2#3% year month command
+ {\bgroup
+ \getdayspermonth{#1}{#2}%
+ \dostepwiserecurse1\numberofdays1%
+ {\normalyear #1\relax
+ \normalmonth#2\relax
+ \normalday \recurselevel\relax
+ #3}%
+ \egroup}
+
+\def\lastmonth{12} % can be set to e.g. 1 when testing
+
+\long\def\processyear#1#2#3#4% year command before after
+ {\bgroup
+ \dorecurse\lastmonth
+ {\normalyear #1\relax
+ \normalmonth\recurselevel\relax
+ #3\processmonth\normalyear\normalmonth{#2}#4}%
+ \egroup}
+
+%D \macros
+%D {defineconversion, convertnumber}
+%D
+%D Conversion involves the macros that we implemented earlier
+%D in this module.
+%D
+%D \showsetup{defineconversion}
+%D \showsetup{convertnumber}
+%D
+%D We can feed this command with conversion macros as well as
+%D a set of conversion symbols. Both need a bit different
+%D treatment.
+%D
+%D \starttyping
+%D \defineconversion [roman] [\romannumerals]
+%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$]
+%D \stoptyping
+%D
+%D You can define a language dependent conversion with:
+%D
+%D \starttyping
+%D \defineconversion [en] [whatever] [\something]
+%D \stoptyping
+
+% \def\dodefineconversion[#1][#2]%
+% {\ConvertConstantAfter\doifinstringelse{,}{#2}
+% {\scratchcounter=0
+% \def\docommand##1%
+% {\advance\scratchcounter 1
+% \setvalue{\??cv#1\the\scratchcounter}{##1}}%
+% \processcommalist[#2]\docommand
+% \setvalue{\??cv#1}##1{\csname\??cv#1##1\endcsname}}
+% {\setvalue{\??cv#1}{#2}}}
+%
+% \def\defineconversion%
+% {\dodoubleargument\dodefineconversion}
+
+\def\defineconversion
+ {\dotripleempty\dodefineconversion}
+
+\def\dodefineconversion[#1][#2][#3]%
+ {\ifthirdargument
+ \dododefineconversion[#1][#2][#3]%
+ \else
+ \dododefineconversion[][#1][#2]%
+ \fi}
+
+%D \starttyping
+%D \def\dododefineconversion[#1][#2][#3]%
+%D {\ConvertConstantAfter\doifinstringelse{,}{#3}
+%D {\scratchcounter\zerocount
+%D \def\docommand##1%
+%D {\advance\scratchcounter \plusone
+%D \setvalue{\??cv#1#2\the\scratchcounter}{##1}}%
+%D \processcommalist[#3]\docommand
+%D \setvalue{\??cv#1#2}##1{\executeifdefined{\??cv#1#2##1}\unknown}} % catch out-of-range numbers
+%D {\setvalue{\??cv#1#2}{#3}}}
+%D \stoptyping
+
+%D This approach has the disadvantage that when you run out of
+%D symbols you get unknown results. The following implementation
+%D permits overloading of the converter:
+
+\def\dododefineconversion[#1][#2][#3]%
+ {\ConvertConstantAfter\doifinstringelse{,}{#3}
+ {\scratchcounter\zerocount
+ \def\docommand##1%
+ {\advance\scratchcounter \plusone
+ \setvalue{\??cv#1#2\the\scratchcounter}{##1}}%
+ \processcommalist[#3]\docommand
+ \setevalue{\??cv#1#2}##1%
+ {\noexpand\docheckedconversion{#1#2}{\the\scratchcounter}{##1}}}
+ {\setvalue{\??cv#1#2}{#3}}}
+
+\def\docheckedconversion#1#2#3% class maxnumber number
+ {\executeifdefined{\??cv#1#3}\unknown}
+
+%D When Gerben reported problems with footnote numbering per page,
+%D Taco came with the following wrap around solution. So, let's
+%D overload the checked conversion macro:
+
+\def\docheckedconversion#1#2#3% class maxnumber number
+ {\executeifdefined{\??cv#1\modulatednumber{#2}{#3}}\unknown}
+
+%D Taco's modulo code is implemented in the system module
+%D \type {syst-con}.
+
+%D If a conversion is just a font switch then we need to make sure
+%D that the number is indeed end up as number in the input, so we
+%D need to handle the second argument.
+
+\def\convertnumber#1#2%
+ {\csname\??cv
+ \ifcsname\??cv\currentlanguage#1\endcsname
+ \currentlanguage#1%
+ \else\ifcsname\??cv#1\endcsname
+ #1%
+ \else
+ \s!default
+ \fi\fi
+ \endcsname{\number#2}}
+
+\def\doifconversiondefinedelse#1%
+ {\ifcsname\??cv\currentlanguage#1\endcsname
+ \@EA\firstoftwoarguments
+ \else\ifcsname\??cv#1\endcsname
+ \@EAEAEA\firstoftwoarguments
+ \else
+ \@EAEAEA\secondoftwoarguments
+ \fi\fi}
+
+\def\doifelseconversionnumber#1#2% slow but seldom used
+ {\doifdefinedelse{\??cv#1#2}}
+
+%D Handy.
+
+\setvalue{\??cv:\c!n:\v!one }{1}
+\setvalue{\??cv:\c!n:\v!two }{2}
+\setvalue{\??cv:\c!n:\v!three}{3}
+\setvalue{\??cv:\c!n:\v!four }{4}
+\setvalue{\??cv:\c!n:\v!five }{5}
+
+\def\wordtonumber#1#2{\ifcsname\??cv:\c!n:#1\endcsname\csname\??cv:\c!n:#1\endcsname\else#2\fi}
+
+% \defineconversion[ctx][c,o,n,t,e,x,t]
+%
+% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}}
+
+\defineconversion [\s!default] [\numbers]
+
+%D As longs as symbols are linked to levels or numbers, we can
+%D also use the conversion mechanism, but in for instance the
+%D itemization macros, we prefer symbols because they can more
+%D easier be (partially) redefined. Symbols are implemented
+%D in another module.
+
+\defineconversion [] [\numbers] % the default conversion
+
+\defineconversion [a] [\characters]
+\defineconversion [A] [\Characters]
+\defineconversion [AK] [\smallcapped\characters]
+\defineconversion [KA] [\smallcapped\characters]
+
+\defineconversion [n] [\numbers]
+\defineconversion [N] [\Numbers]
+\defineconversion [m] [\mediaeval]
+
+\defineconversion [i] [\romannumerals]
+\defineconversion [I] [\Romannumerals]
+\defineconversion [r] [\romannumerals]
+\defineconversion [R] [\Romannumerals]
+\defineconversion [KR] [\smallcapped\romannumerals]
+\defineconversion [RK] [\smallcapped\romannumerals]
+
+\defineconversion [g] [\greeknumerals]
+\defineconversion [G] [\Greeknumerals]
+
+\defineconversion [o] [\oldstylenumerals]
+\defineconversion [O] [\oldstylenumerals]
+\defineconversion [or] [\oldstyleromannumerals]
+
+\defineconversion [\v!character] [\character]
+\defineconversion [\v!Character] [\Character]
+
+\defineconversion [\v!characters] [\characters]
+\defineconversion [\v!Characters] [\Characters]
+
+\defineconversion [\v!numbers] [\numbers]
+\defineconversion [\v!Numbers] [\Numbers]
+\defineconversion [\v!mediaeval] [\mediaeval]
+
+\defineconversion [\v!romannumerals] [\romannumerals]
+\defineconversion [\v!Romannumerals] [\Romannumerals]
+
+\defineconversion [\v!greek] [\greeknumerals]
+\defineconversion [\v!Greek] [\Greeknumerals]
+
+\defineconversion [arabicnumerals] [\arabicnumerals]
+\defineconversion [persiannumerals] [\arabicnumerals]
+
+\defineconversion [month] [\doconvertmonthlong]
+\defineconversion [month:mnem] [\doconvertmonthshort]
+
+% Some bonus ones:
+
+\defineconversion [\v!empty] [\gobbleoneargument]
+\defineconversion [\v!none] [\numbers]
+
+\ifx\symbol\undefined \def\symbol[#1]{#1} \fi % todo
+
+\defineconversion
+ [set 0]
+ [{\symbol[bullet]},
+ {\symbol[dash]},
+ {\symbol[star]},
+ {\symbol[triangle]},
+ {\symbol[circle]},
+ {\symbol[medcircle]},
+ {\symbol[bigcircle]},
+ {\symbol[square]}]
+
+\defineconversion
+ [set 1]
+ [\mathematics{\star},
+ \mathematics{\star\star},
+ \mathematics{\star\star\star},
+ \mathematics{\ddagger},
+ \mathematics{\ddagger\ddagger},
+ \mathematics{\ddagger\ddagger\ddagger},
+ \mathematics{\ast},
+ \mathematics{\ast\ast},
+ \mathematics{\ast\ast\ast}]
+
+\defineconversion
+ [set 2]
+ [\mathematics{*},
+ \mathematics{\dag},
+ \mathematics{\ddag},
+ \mathematics{**},
+ \mathematics{\dag\dag},
+ \mathematics{\ddag\ddag},
+ \mathematics{***},
+ \mathematics{\dag\dag\dag},
+ \mathematics{\ddag\ddag\ddag},
+ \mathematics{****},
+ \mathematics{\dag\dag\dag\dag},
+ \mathematics{\ddag\ddag\ddag\ddag}]
+
+\defineconversion
+ [set 3]
+ [\mathematics{\star},
+ \mathematics{\star\star},
+ \mathematics{\star\star\star},
+ \mathematics{\ddagger},
+ \mathematics{\ddagger\ddagger},
+ \mathematics{\ddagger\ddagger\ddagger},
+ \mathematics{\P},
+ \mathematics{\P\P},
+ \mathematics{\P\P\P},
+ \mathematics{\S},
+ \mathematics{\S\S},
+ \mathematics{\S\S\S},
+ \mathematics{\ast},
+ \mathematics{\ast\ast},
+ \mathematics{\ast\ast\ast}]
+
+%D \macros
+%D {defineconversionvector,conversionnumber} % bad names so no danger for clash
+%D
+%D For Adam and friends \unknown
+%D
+%D \startitemize[persiannummerals]
+%D \item test \item test \item test \item test
+%D \stopitemize
+
+\def\defineconversionvector#1#2% name base
+ {\bgroup
+ % dirty trick
+ \uccode`\*=`\1
+ % plain:
+ % \uccode`\0=\numexpr#2+0\relax \uccode`\1=\numexpr#2+1\relax
+ % \uccode`\2=\numexpr#2+2\relax \uccode`\3=\numexpr#2+3\relax
+ % \uccode`\4=\numexpr#2+4\relax \uccode`\5=\numexpr#2+5\relax
+ % \uccode`\6=\numexpr#2+6\relax \uccode`\7=\numexpr#2+7\relax
+ % \uccode`\8=\numexpr#2+8\relax \uccode`\9=\numexpr#2+9\relax
+ % context:
+ \dostepwiserecurse091{\expandafter\uccode\expandafter`\recurselevel=\numexpr#2+\recurselevel}%
+ % prepared macro
+ \uppercase\expandafter{\expandafter\gdef\csname::cvn::#1::\endcsname##*%
+ {\ifcase##* 0\or1\or2\or3\or4\or5\or6\or7\or8\or9\fi}}%
+ \egroup}
+
+\def\conversionnumber#1#2%
+ {\ifcsname::cvn::#1::\endcsname
+ \expandafter\doconversionnumber\csname::cvn::#1::\expandafter\endcsname\number#2\relax
+ \else
+ \number#2%
+ \fi}
+
+\def\doconversionnumber#1#2%
+ {\ifx#2\relax
+ \expandafter\gobbleoneargument
+ \else
+ #1{#2}%
+ \expandafter\doconversionnumber
+ \fi#1}
+
+% actually mkiii code
+
+\ifnum\texengine=\xetexengine
+
+ \defineconversionvector{arabicnumerals} {"0660}
+ \defineconversionvector{persiannumerals} {"06F0}
+ \defineconversionvector{thainumerals} {"0E50}
+ \defineconversionvector{devanagarinumerals}{"0966}
+ \defineconversionvector{gurmurkhinumerals} {"0A66}
+ \defineconversionvector{gujaratinumerals} {"0AE6}
+ \defineconversionvector{tibetannumerals} {"0F20} % also "half numerals?"
+
+ \defineconversion[arabicnumerals] [\conversionnumber{arabicnumerals}]
+ \defineconversion[persiannumerals] [\conversionnumber{persiannumerals}]
+ \defineconversion[thainumerals] [\conversionnumber{thainumerals}]
+ \defineconversion[devanagarinumerals][\conversionnumber{devanagarinumerals}]
+ \defineconversion[gurmurkhinumerals] [\conversionnumber{gurmurkhinumerals}]
+ \defineconversion[gujaratinumerals] [\conversionnumber{gujaratinumerals}]
+ \defineconversion[tibetannumerals] [\conversionnumber{tibetannumerals}]
+
+\fi
+
+\protect \endinput
diff --git a/tex/context/base/core-con.mkiv b/tex/context/base/core-con.mkiv
new file mode 100644
index 000000000..2d2e5d5d7
--- /dev/null
+++ b/tex/context/base/core-con.mkiv
@@ -0,0 +1,860 @@
+%D \module
+%D [ file=core-con,
+%D version=1997.26.08,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Conversion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Conversion}
+
+\registerctxluafile{core-con}{1.001}
+
+\unprotect
+
+\ifx\currentlanguage\undefined \let\currentlanguage\empty \fi
+\ifx\labeltext \undefined \let\labeltext\firstofoneargument \fi
+
+%D This module deals with all kind of conversions from numbers
+%D and dates. I considered splitting this module in a support
+%D one and a core one, but to keep things simple as well as
+%D preserve the overview, I decided against splitting.
+
+\let\spr\firstofoneargument % separator
+\let\stp\firstofoneargument % stopper
+
+% cleaner, some day:
+%
+% \def\isolateseparators % etex only, even works with list separator overloading
+% {\unexpanded\def\spr##1{{##1}}%
+% \unexpanded\def\stp##1{{##1}}}
+
+% needed for arab :
+
+\def\isolateseparators % even works with list separator overloading
+ {\def\spr##1{{##1}}%
+ \def\stp##1{{##1}}}
+
+%D \macros
+%D {numbers}
+%D
+%D First we deal with the dummy conversion of numbers using the
+%D \TEX\ primitive \type{\number}. The uppercase alternative is
+%D only there for compatibility with the other conversion
+%D macros. We could do without \type{#1} but this way we get
+%D rid of unwanted braces. For the savety we also define a
+%D non||sence uppercase alternative.
+%D
+%D \showsetup{numbers}
+%D
+%D \starttyping
+%D \def\numbers#1{\number#1}
+%D \def\Numbers#1{\number#1}
+%D \stoptyping
+%D
+%D Due to read ahead, as in \type{[\pagenumber\space]} the space will
+%D disappear, unless we use:
+
+\def\numbers#1{\purenumber{#1}}
+\def\Numbers#1{\purenumber{#1}}
+
+%D \macros
+%D {romannumerals,Romannumerals}
+%D
+%D \TEX\ the program uses a rather tricky conversion from
+%D numbers to their roman counterparts. This conversion could
+%D of course be programmed in \TEX\ itself, but I guess Knuth
+%D found the programming trick worth presenting.
+%D
+%D \showsetup{romannumerals}
+%D \showsetup{Romannumerals}
+
+\def\romannumerals#1{\ctxlua{converters.romannumerals(\number#1)}}
+\def\Romannumerals#1{\ctxlua{converters.Romannumerals(\number#1)}}
+
+%D Arabic etc:
+
+\def\abjadnumerals #1{\ctxlua{converters.abjadnumerals (\number#1)}}
+\def\abjadnodotnumerals#1{\ctxlua{converters.abjadnodotnumerals(\number#1)}}
+\def\abjadnaivenumerals#1{\ctxlua{converters.arabicnumerals (\number#1)}}
+
+\def\languagecharacters#1{\ctxlua{converters.alphabetic(\number#1,"\currentlanguage")}} % new
+\def\languageCharacters#1{\ctxlua{converters.Alphabetic(\number#1,"\currentlanguage")}} % new
+
+% we could use an auxiliary macro to save some bytes in the format
+%
+% \def\dolanguagecharacters#1#2{\ctxlua{converters.alphabetic(\number#2,"#1")}}
+
+\def\thainumerals #1{\ctxlua{converters.alphabetic(\number#1,"thai")}}
+\def\devanagarinumerals#1{\ctxlua{converters.alphabetic(\number#1,"devanagari")}}
+\def\gurmurkhinumerals #1{\ctxlua{converters.alphabetic(\number#1,"gurmurkhi")}}
+\def\gujaratinumerals #1{\ctxlua{converters.alphabetic(\number#1,"gujarati")}}
+\def\tibetannumerals #1{\ctxlua{converters.alphabetic(\number#1,"tibetan")}}
+\def\greeknumerals #1{\ctxlua{converters.alphabetic(\number#1,"greek")}}
+\def\Greeknumerals #1{\ctxlua{converters.Alphabetic(\number#1,"greek")}}
+\def\arabicnumerals #1{\ctxlua{converters.alphabetic(\number#1,"arabic")}}
+\def\persiannumerals #1{\ctxlua{converters.alphabetic(\number#1,"persian")}}
+
+\let\arabicexnumerals \persiannumerals
+
+\def\koreannumerals #1{\ctxlua{converters.alphabetic(\number#1,"korean")}}
+\def\koreannumeralsp#1{\ctxlua{converters.alphabetic(\number#1,"korean-parent")}}
+\def\koreannumeralsc#1{\ctxlua{converters.alphabetic(\number#1,"korean-circle")}}
+
+\def\chinesenumerals #1{\ctxlua{converters.chinesenumerals (\number#1)}}
+\def\chinesecapnumerals#1{\ctxlua{converters.chinesecapnumerals(\number#1,"cap")}}
+\def\chineseallnumerals#1{\ctxlua{converters.chineseallnumerals(\number#1,"all")}}
+
+%D \macros
+%D {character,Character}
+%D
+%D Converting a number into a character can of course only
+%D be done with numbers less or equal to~26. At the cost of
+%D much more macros a faster conversion is possible, using:
+%D
+%D \starttyping
+%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}}
+%D \stoptyping
+%D
+%D But we prefer a simpel \type{\case}.
+%D
+%D \showsetup{character}
+%D \showsetup{Character}
+
+\def\unknowncharacter{-} % else in lists \relax
+
+\def\character#1{\ctxlua{converters.character (\number#1)}}
+\def\Character#1{\ctxlua{converters.Character (\number#1)}}
+
+%D \macros
+%D {characters,Characters}
+%D
+%D Converting large numbers is supported by the next two
+%D macros. This time we just count on: $\cdots$~x, y, z, aa,
+%D ab, ac~$\cdots$.
+%D
+%D \showsetup{characters}
+%D \showsetup{Characters}
+
+\def\characters#1{\ctxlua{converters.characters(\number#1)}}
+\def\Characters#1{\ctxlua{converters.Characters(\number#1)}}
+
+%D \macros
+%D {greeknumerals,Greeknumerals}
+%D
+%D Why should we only honour the romans, and not the greek?
+
+\let\greeknumerals\gobbleoneargument
+\let\Greeknumerals\gobbleoneargument
+
+%D \macros
+%D {oldstylenumerals,oldstyleromannumerals}
+%D
+%D These conversions are dedicated to Frans Goddijn.
+
+\unexpanded\def\oldstylenumerals#1%
+ {{\os\number#1}}
+
+\unexpanded\def\oldstyleromannumerals#1%
+ {{\leftrulefalse\rightrulefalse\ss\txx\boxrulewidth.15ex
+ \ruledhbox spread .15em{\hss\uppercased{\romannumerals{#1}}\hss}}}
+
+%D \macros
+%D {protectconversion}
+%D
+%D The previous two commands are not robust enough to be
+%D passed to \type{\write} en \type{\message}. That's why we
+%D introduce:
+
+\def\protectconversion
+ {\def\doconvertcharacters##1{##1}} % was \relax
+ %{\def\doconvertcharacters##1{\ifcase0##1 0\else##1\fi}} more save
+
+%D \macros
+%D {normaltime,normalyear,normalmonth,normalday}
+%D
+%D The last part of this module is dedicated to converting
+%D dates. Because we want to use as meaningful commands as
+%D possible, and because \TEX\ already uses up some of those,
+%D we save the original meanings.
+
+\savenormalmeaning\time
+\savenormalmeaning\year
+\savenormalmeaning\month
+\savenormalmeaning\day
+
+%D \macros
+%D {month,MONTH}
+%D
+%D Converting the month number into a month name is done
+%D using a case statement, abstact values and the label
+%D mechanism. This way users can easily redefine a label from
+%D for instance german into austrian.
+%D
+%D \starttyping
+%D \setuplabeltext [de] [january=J\"anner]
+%D \stoptyping
+%D
+%D Anyhow, the conversion looks like:
+
+\def\domonthtag#1%
+ {\ifcase#1%
+ \or \v!january \or \v!february \or \v!march \or \v!april
+ \or \v!may \or \v!june \or \v!july \or \v!august
+ \or \v!september \or \v!october \or \v!november \or \v!december
+ \else
+ \v!unknown
+ \fi}
+
+\def\doconvertmonthlong #1{\labeltext{\domonthtag{#1}}}
+\def\doconvertmonthshort#1{\labeltext{\domonthtag{#1}:\s!mnem}}
+
+\let\doconvertmonth\doconvertmonthlong
+
+%D We redefine the \TEX\ primitive \type{\month} as:
+%D
+%D \showsetup{month}
+%D \showsetup{MONTH}
+
+\def\monthlong {\doconvertmonthlong}
+\def\monthshort{\doconvertmonthshort}
+\def\month {\doconvertmonth}
+
+\def\MONTH #1{{\let\labeltext\LABELTEXT\month {#1}}}
+\def\MONTHLONG #1{{\let\labeltext\LABELTEXT\monthlong {#1}}}
+\def\MONTHSHORT#1{{\let\labeltext\LABELTEXT\monthshort{#1}}}
+
+%D We never explicitly needed this, but Tobias Burnus pointed
+%D out that it would be handy to convert to the day of the
+%D week. In doing so, we have to calculate the total number of
+%D days, taking leapyears into account. For those who are
+%D curious:
+%D
+%D \startitemize[packed]
+%D \item years that can be divided by 4 are leapyears
+%D \item exept years that can be divided by 100
+%D \item unless years can be divided by 400
+%D \stopitemize
+%D
+%D This makes the year 1900 into a normal year and 1996 and
+%D 2000 into leap years, right? Well, converting to string
+%D looks familiar:
+
+\def\doconvertday#1%
+ {\labeltext
+ {\ifcase#1
+ \or \v!sunday \or \v!monday \or \v!tuesday \or \v!wednesday
+ \or \v!thursday \or \v!friday \or \v!saturday \fi}}
+
+%D \macros
+%D {getdayoftheweek, dayoftheweek}
+%D
+%D The conversion algoritm is an old one and a translation from
+%D a procedure written in MODULA~2 back in the 80's. I finaly
+%D found the 4--100-400 rules in some enclopedia. Look at this
+%D messy low level routine that takes the day, month and year
+%D as arguments:
+
+\newcount\normalweekday
+
+\def\getdayoftheweek#1#2#3{\normalweekday\ctxlua{converters.weekday(\number#1,\number#2,\number#3)}}
+\def\dayoftheweek #1#2#3{\doconvertday{\ctxlua{converters.weekday(\number#1,\number#2,\number#3)}}}
+
+%D Using this macro in
+%D
+%D \startbuffer
+%D monday: \dayoftheweek {4} {5} {1992}
+%D friday: \dayoftheweek {16} {6} {1995}
+%D monday: \dayoftheweek {25} {8} {1997}
+%D saturday: \dayoftheweek {30} {8} {1997}
+%D tuesday: \dayoftheweek {2} {1} {1996}
+%D tuesday: \dayoftheweek {7} {1} {1997}
+%D tuesday: \dayoftheweek {13} {1} {1998}
+%D friday: \dayoftheweek {1} {1} {2000}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D gives
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D The macro \type {\getdayoftheweek} can be used to calculate
+%D the number \type {\normalweekday}.
+
+%D \macros
+%D {weekday,WEEKDAY}
+%D
+%D The first one is sort of redundant. It takes the day
+%D number argument.
+%D
+%D \showsetup{weekday}
+%D \showsetup{WEEKDAY}
+
+\def\weekday
+ {\doconvertday}
+
+\def\WEEKDAY#1%
+ {{\let\labeltext\LABELTEXT\doconvertday{#1}}}
+
+%D \macros
+%D {weekoftheday}
+%D
+%D {\em not yet implemented:}
+%D
+%D \starttyping
+%D \def\weekoftheday#1#2#3%
+%D {}
+%D \stoptyping
+
+%D \macros
+%D {doifleapyearelse,
+%D getdayspermonth}
+%D
+%D Sometimes we need to know if we're dealing with a
+%D leapyear, so here is a testmacro:
+%D
+%D \starttyping
+%D \doifleapyearelse{year}{yes}{no}
+%D \stoptyping
+%D
+%D An example of its use can be seen in the macro
+%D
+%D \starttyping
+%D \getdayspermonth{year}{month}
+%D \stoptyping
+%D
+%D The number of days is available in the macro \type
+%D {\numberofdays}.
+
+\def\doifleapyearelse#1%
+ {\ifcase\ctxlua{converters.leapyear(\number#1)}
+ \@EA\secondoftwoarguments
+ \else
+ \@EA\firstoftwoarguments
+ \fi}
+
+\def\getdayspermonth#1#2%
+ {\edef\numberofdays{\ctxlua{converters.nofdays(\number#1,\number#2)}}}
+
+\def\dayspermonth#1#2%
+ {\ctxlua{converters.nofdays(\number#1,\number#2)}}
+
+% problem is that we calculate with those numbers
+%
+% \def\time {\numexpr\ctxlua{converters.textime()}\relax}
+% \def\year {\numexpr\ctxlua{converters.year ()}\relax}
+% \def\month{\numexpr\ctxlua{converters.month ()}\relax}
+% \def\day {\numexpr\ctxlua{converters.day ()}\relax}
+
+% \dayoftheweek{2006}{9}{15}
+% \doifleapyearelse{2000}{OK}{NOT OK}
+% \doifleapyearelse{2100}{NOT OK}{OK}
+% \doifleapyearelse{2004}{OK}{NOT OK}
+% \doifleapyearelse{2003}{NOT OK}{OK}
+% \dayspermonth{2000}{2}
+% [\the\normaltime=\the\time]
+
+%D \macros
+%D {currentdate, date}
+%D
+%D We use these conversion macros in the date formatting
+%D macro:
+%D
+%D \showsetup{currentdate}
+%D
+%D This macro takes care of proper spacing and delivers for
+%D instance:
+%D
+%D \startbuffer
+%D \currentdate[weekday,day,month,year] % still dutch example
+%D \currentdate[WEEKDAY,day,MONTH,year] % still dutch example
+%D \stopbuffer
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D depending of course on the keywords. Here we gave:
+%D
+%D \typebuffer
+%D
+%D If needed one can also add non||keywords, like in
+%D
+%D \startbuffer
+%D \currentdate[dd,--,mm,--,yy]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or typeset: \getbuffer.
+%D
+%D When no argument is passed, the current date is given as
+%D specified per language (using \type{\installlanguage}).
+%D
+%D \showsetup{currentdate}
+%D
+%D \startbuffer
+%D \date
+%D \date[d=12,m=12,y=1998][weekday]
+%D \date[d=12,m=12,y=1998]
+%D \stopbuffer
+%D
+%D We can also typeset arbitrary dates, using the previous
+%D command.
+%D
+%D \typebuffer
+%D
+%D The date is specified by one character keys. When no date
+%D is given, we get the current date.
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\def\kenmerkdatumpatroon{j,mm,dd} % jj,mm,dd changed at januari 1-1-2000
+
+\newsignal\datesignal
+
+\def\dobetweendates
+ {\ifdim\lastskip=\datesignal\relax\else
+ \unskip\space
+ \hskip\datesignal\relax
+ \fi}
+
+\newtoks \everycurrentdate
+
+\def\complexcurrentdate[#1]%
+ {\bgroup
+ \the\everycurrentdate
+ \def\betweendates{\let\betweendates\dobetweendates}%
+ % was \processcommacommandp[#1]\docomplexcurrentdate
+ \safeedef\ascii{\empty#1}% keep encoded chars
+ \@EA\processcommalist\@EA[\ascii]\docomplexcurrentdate
+ \ifdim\lastskip=\datesignal\relax
+ \unskip
+ \fi
+ \egroup}
+
+\def\docomplexcurrentdate#1%
+ {\lowercase{\edef\!!stringa{#1}}% permits usage in \smallcapped
+ \expanded{\processaction[\!!stringa]}% [#1]
+ [ \v!day=>\betweendates\the\normalday,
+ %\v!day+=>\betweendates\ordinaldaynumber\normalday,
+ \v!day+=>\betweendates\convertnumber{\v!day+}\normalday,
+ \v!month=>\betweendates\month\normalmonth,
+ \v!year=>\betweendates\the\normalyear,
+ \v!space=>\unskip\ \hskip\datesignal,% optimization -)
+ \ =>\unskip\ \hskip\datesignal,% optimization -)
+ d=>\convertnumber\v!day\normalday,
+ %d+=>\ordinaldaynumber\normalday,
+ d+=>\convertnumber{\v!day+}\normalday,
+ m=>\convertnumber\v!month\normalmonth,
+ j=>\convertnumber\v!year\normalyear,
+ y=>\convertnumber\v!year\normalyear,
+ w=>\betweendates\dayoftheweek\normalday\normalmonth\normalyear,
+ dd=>\ifnum\normalday >9 \else0\fi\the\normalday,
+ %dd+=>\ordinaldaynumber{\ifnum\normalday >9 \else0\fi\the\normalday},
+ dd+=>\convertnumber{\v!day+}{\ifnum\normalday >9 \else0\fi\the\normalday},
+ mm=>\ifnum\normalmonth>9 \else0\fi\the\normalmonth,
+ jj=>\expandafter\gobbletwoarguments\the\normalyear,
+ yy=>\expandafter\gobbletwoarguments\the\normalyear,
+ \v!weekday=>\betweendates\dayoftheweek\normalday\normalmonth\normalyear,
+ \v!referral=>\expanded{\complexcurrentdate[\kenmerkdatumpatroon]},
+ \s!unknown=>\unskip
+ % #1 and not the lowercased \commalistelement, vietnamese has text
+ % {} because #1 can have comma, like: {\ ,}
+ {#1}%
+ \hskip\datesignal
+ \def\betweendates{\let\betweendates\dobetweendates}]}
+
+\def\simplecurrentdate
+ {\expanded{\complexcurrentdate[\currentdatespecification]}}
+
+\definecomplexorsimple\currentdate
+
+\def\dodate[#1][#2]%
+ {\bgroup
+ \iffirstargument
+ \getparameters[\??da][d=\normalday,m=\normalmonth,y=\normalyear,#1]%
+ \normalday \@@dad\relax
+ \normalmonth\@@dam\relax
+ \normalyear \@@day\relax
+ \ifsecondargument
+ \currentdate[#2]%
+ \else
+ \currentdate
+ \fi
+ \else
+ \currentdate
+ \fi
+ \egroup}
+
+\def\date
+ {\dodoubleempty\dodate}
+
+%D \macros
+%D {currenttime}
+%D
+%D The currenttime is actually the jobtime. You can specify
+%D a pattern similar to the previous date macro using the
+%D keys \type {h}, \type {m} and a separator.
+
+\def\calculatecurrenttime
+ {\edef\currenthour {\ctxlua{converters.hour ()}}%
+ \edef\currentminute{\ctxlua{converters.minute()}}%
+ \edef\currentsecond{\ctxlua{converters.second()}}}
+
+\let\currenthour \!!plusone
+\let\currentminute\!!plusone
+
+\def\currenttimespecification{h,:,m}
+
+\def\complexcurrenttime[#1]%
+ {\calculatecurrenttime
+ \processallactionsinset[#1]
+ [h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]}
+
+\def\simplecurrenttime
+ {\expanded{\complexcurrenttime[\currenttimespecification]}}
+
+\definecomplexorsimple\currenttime
+
+%D Because we're dealing with dates, we also introduce a few
+%D day loops:
+%D
+%D \starttyping
+%D \processmonth{year}{month}{command}
+%D \processyear{year}{command}{before}{after}
+%D \stoptyping
+%D
+%D The counters \type {\normalyear}, \type {\normalmonth} and
+%D \type{\normalday} can be used for for date manipulations.
+
+\long\def\processmonth#1#2#3% year month command
+ {\bgroup
+ \getdayspermonth{#1}{#2}%
+ \dostepwiserecurse1\numberofdays1%
+ {\normalyear #1\relax
+ \normalmonth#2\relax
+ \normalday \recurselevel\relax
+ #3}%
+ \egroup}
+
+\def\lastmonth{12} % can be set to e.g. 1 when testing
+
+\long\def\processyear#1#2#3#4% year command before after
+ {\bgroup
+ \dorecurse\lastmonth
+ {\normalyear #1\relax
+ \normalmonth\recurselevel\relax
+ #3\processmonth\normalyear\normalmonth{#2}#4}%
+ \egroup}
+
+%D \macros
+%D {defineconversion, convertnumber}
+%D
+%D Conversion involves the macros that we implemented earlier
+%D in this module.
+%D
+%D \showsetup{defineconversion}
+%D \showsetup{convertnumber}
+%D
+%D We can feed this command with conversion macros as well as
+%D a set of conversion symbols. Both need a bit different
+%D treatment.
+%D
+%D \starttyping
+%D \defineconversion [roman] [\romannumerals]
+%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$]
+%D \stoptyping
+%D
+%D You can define a language dependent conversion with:
+%D
+%D \starttyping
+%D \defineconversion [en] [whatever] [\something]
+%D \stoptyping
+
+% \def\dodefineconversion[#1][#2]%
+% {\ConvertConstantAfter\doifinstringelse{,}{#2}
+% {\scratchcounter=0
+% \def\docommand##1%
+% {\advance\scratchcounter 1
+% \setvalue{\??cv#1\the\scratchcounter}{##1}}%
+% \processcommalist[#2]\docommand
+% \setvalue{\??cv#1}##1{\csname\??cv#1##1\endcsname}}
+% {\setvalue{\??cv#1}{#2}}}
+%
+% \unexpanded\def\defineconversion%
+% {\dodoubleargument\dodefineconversion}
+
+\unexpanded\def\defineconversion
+ {\dotripleempty\dodefineconversion}
+
+\def\dodefineconversion[#1][#2][#3]%
+ {\ifthirdargument
+ \dododefineconversion[#1][#2][#3]%
+ \else
+ \dododefineconversion[][#1][#2]%
+ \fi}
+
+%D \starttyping
+%D \def\dododefineconversion[#1][#2][#3]%
+%D {\ConvertConstantAfter\doifinstringelse{,}{#3}
+%D {\scratchcounter\zerocount
+%D \def\docommand##1%
+%D {\advance\scratchcounter \plusone
+%D \setvalue{\??cv#1#2\the\scratchcounter}{##1}}%
+%D \processcommalist[#3]\docommand
+%D \setvalue{\??cv#1#2}##1{\executeifdefined{\??cv#1#2##1}\unknown}} % catch out-of-range numbers
+%D {\setvalue{\??cv#1#2}{#3}}}
+%D \stoptyping
+
+%D This approach has the disadvantage that when you run out of
+%D symbols you get unknown results. The following implementation
+%D permits overloading of the converter:
+
+\def\dododefineconversion[#1][#2][#3]%
+ {\ConvertConstantAfter\doifinstringelse{,}{#3}
+ {\scratchcounter\zerocount
+ \def\docommand##1%
+ {\advance\scratchcounter \plusone
+ \setvalue{\??cv#1#2\the\scratchcounter}{##1}}%
+ \processcommalist[#3]\docommand
+ \setevalue{\??cv#1#2}##1%
+ {\noexpand\docheckedconversion{#1#2}{\the\scratchcounter}{##1}}}
+ {\setvalue{\??cv#1#2}{#3}}}
+
+\def\docheckedconversion#1#2#3% class maxnumber number
+ {\executeifdefined{\??cv#1#3}\unknown}
+
+%D When Gerben reported problems with footnote numbering per page,
+%D Taco came with the following wrap around solution. So, let's
+%D overload the checked conversion macro:
+
+\def\docheckedconversion#1#2#3% class maxnumber number
+ {\executeifdefined{\??cv#1\modulatednumber{#2}{#3}}\unknown}
+
+%D Taco's modulo code is implemented in the system module
+%D \type {syst-con}.
+
+%D If a conversion is just a font switch then we need to make sure
+%D that the number is indeed end up as number in the input, so we
+%D need to handle the second argument.
+
+\def\convertnumber#1#2%
+ {\csname\??cv
+ \ifcsname\??cv\currentlanguage#1\endcsname
+ \currentlanguage#1%
+ \else\ifcsname\??cv#1\endcsname
+ #1%
+ \else
+ \s!default
+ \fi\fi
+ \endcsname{\number#2}}
+
+\def\doifconversiondefinedelse#1%
+ {\ifcsname\??cv\currentlanguage#1\endcsname
+ \@EA\firstoftwoarguments
+ \else\ifcsname\??cv#1\endcsname
+ \@EAEAEA\firstoftwoarguments
+ \else
+ \@EAEAEA\secondoftwoarguments
+ \fi\fi}
+
+\def\doifelseconversionnumber#1#2% slow but seldom used
+ {\doifdefinedelse{\??cv#1#2}}
+
+%D Handy.
+
+\setvalue{\??cv:\c!n:\v!one }{1}
+\setvalue{\??cv:\c!n:\v!two }{2}
+\setvalue{\??cv:\c!n:\v!three}{3}
+\setvalue{\??cv:\c!n:\v!four }{4}
+\setvalue{\??cv:\c!n:\v!five }{5}
+
+\def\wordtonumber#1#2{\ifcsname\??cv:\c!n:#1\endcsname\csname\??cv:\c!n:#1\endcsname\else#2\fi}
+
+% \defineconversion[ctx][c,o,n,t,e,x,t]
+%
+% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}}
+
+%D \macros
+%D {ordinaldaynumber, highordinalstr, ordinalstr}
+%D
+%D Efficient general ordinal number converters are sometimes
+%D difficult to implement. Fortunately dates never exceed the
+%D number~31.
+
+\ifx\high \undefined \let\high \firstofoneargument \fi
+\ifx\notsmallcapped\undefined \let\notsmallcapped\firstofoneargument \fi
+
+\def\highordinalstr#1{\high{\notsmallcapped{#1}}}
+\def\ordinalstr #1{\notsmallcapped{#1}}
+
+\def\ordinaldaynumber#1% \strippedcsname\ordinaldaynumber
+ {\expanded{\executeifdefined{\currentlanguage ordinaldaynumber}\noexpand\firstofoneargument{\number#1}}}
+
+%D As longs as symbols are linked to levels or numbers, we can
+%D also use the conversion mechanism, but in for instance the
+%D itemization macros, we prefer symbols because they can more
+%D easier be (partially) redefined. Symbols are implemented
+%D in another module.
+
+\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}}
+\def\smallcappedcharacters #1{\smallcapped{\characters {#1}}}
+
+\defineconversion [] [\numbers] % the default conversion
+\defineconversion [\v!empty] [\gobbleoneargument]
+\defineconversion [\v!none] [\numbers]
+\defineconversion [\s!default] [\numbers]
+
+\defineconversion [month] [\doconvertmonthlong]
+\defineconversion [month:mnem] [\doconvertmonthshort]
+
+\defineconversion [\v!character] [\character]
+\defineconversion [\v!Character] [\Character]
+
+\defineconversion [\v!characters] [\characters]
+\defineconversion [\v!Characters] [\Characters]
+
+\defineconversion [a] [\characters]
+\defineconversion [A] [\Characters]
+\defineconversion [AK] [\smallcappedcharacters]
+\defineconversion [KA] [\smallcappedcharacters]
+
+\defineconversion [\v!numbers] [\numbers]
+\defineconversion [\v!Numbers] [\Numbers]
+\defineconversion [\v!mediaeval] [\mediaeval]
+
+\defineconversion [n] [\numbers]
+\defineconversion [N] [\Numbers]
+\defineconversion [m] [\mediaeval]
+\defineconversion [o] [\oldstylenumerals]
+\defineconversion [O] [\oldstylenumerals]
+\defineconversion [or] [\oldstyleromannumerals]
+
+\defineconversion [\v!romannumerals] [\romannumerals]
+\defineconversion [\v!Romannumerals] [\Romannumerals]
+
+\defineconversion [i] [\romannumerals]
+\defineconversion [I] [\Romannumerals]
+\defineconversion [r] [\romannumerals]
+\defineconversion [R] [\Romannumerals]
+
+\defineconversion [KR] [\smallcappedromannumerals]
+\defineconversion [RK] [\smallcappedromannumerals]
+
+\defineconversion [\v!greek] [\greeknumerals]
+\defineconversion [\v!Greek] [\Greeknumerals]
+
+\defineconversion [g] [\greeknumerals]
+\defineconversion [G] [\Greeknumerals]
+
+\defineconversion [arabicnumerals] [\arabicnumerals]
+\defineconversion [persiannumerals] [\persiannumerals]
+
+\defineconversion [abjadnumerals] [\abjadnumerals]
+\defineconversion [abjadnodotnumerals] [\adjadnodotnumerals]
+\defineconversion [abjadnaivenumerals] [\adjadnaivenumerals]
+
+\defineconversion [thainumerals] [\thainumerals]
+\defineconversion [devanagarinumerals] [\devanagarinumerals]
+\defineconversion [gurmurkhinumerals] [\gurmurkhinumerals]
+\defineconversion [gujaratinumerals] [\gujaratinumerals]
+\defineconversion [tibetannumerals] [\tibetannumerals]
+\defineconversion [greeknumerals] [\greeknumerals]
+\defineconversion [Greeknumerals] [\Greeknumerals]
+\defineconversion [arabicnumerals] [\arabicnumerals]
+\defineconversion [persiannumerals] [\persiannumerals]
+\defineconversion [arabicexnumerals] [\arabicexnumerals]
+
+
+\defineconversion [koreannumerals] [\koreannumerals]
+\defineconversion [koreanparentnumerals] [\koreanparentnumerals]
+\defineconversion [koreancirclenumerals] [\koreancirclenumerals]
+
+\defineconversion [kr] [\koreannumerals]
+\defineconversion [kr-p] [\koreanparentnumerals]
+\defineconversion [kr-c] [\koreancirclenumerals]
+
+\defineconversion [chinesenumerals] [\chinesenumerals]
+\defineconversion [chinesecapnumeralscn] [\chinesecapnumerals]
+\defineconversion [chineseallnumeralscn] [\chineseallnumerals]
+
+\defineconversion [cn] [\chinesenumerals]
+\defineconversion [cn-c] [\chinesecapnumerals]
+\defineconversion [cn-a] [\chineseallnumerals]
+
+%D Symbol sets:
+
+\ifx\symbol\undefined \def\symbol[#1]{#1} \fi % todo
+
+\defineconversion
+ [set 0]
+ [{\symbol[bullet]},
+ {\symbol[dash]},
+ {\symbol[star]},
+ {\symbol[triangle]},
+ {\symbol[circle]},
+ {\symbol[medcircle]},
+ {\symbol[bigcircle]},
+ {\symbol[square]}]
+
+\defineconversion
+ [set 1]
+ [\mathematics{\star},
+ \mathematics{\star\star},
+ \mathematics{\star\star\star},
+ \mathematics{\ddagger},
+ \mathematics{\ddagger\ddagger},
+ \mathematics{\ddagger\ddagger\ddagger},
+ \mathematics{\ast},
+ \mathematics{\ast\ast},
+ \mathematics{\ast\ast\ast}]
+
+\defineconversion
+ [set 2]
+ [\mathematics{*},
+ \mathematics{\dag},
+ \mathematics{\ddag},
+ \mathematics{**},
+ \mathematics{\dag\dag},
+ \mathematics{\ddag\ddag},
+ \mathematics{***},
+ \mathematics{\dag\dag\dag},
+ \mathematics{\ddag\ddag\ddag},
+ \mathematics{****},
+ \mathematics{\dag\dag\dag\dag},
+ \mathematics{\ddag\ddag\ddag\ddag}]
+
+\defineconversion
+ [set 3]
+ [\mathematics{\star},
+ \mathematics{\star\star},
+ \mathematics{\star\star\star},
+ \mathematics{\ddagger},
+ \mathematics{\ddagger\ddagger},
+ \mathematics{\ddagger\ddagger\ddagger},
+ \mathematics{\P},
+ \mathematics{\P\P},
+ \mathematics{\P\P\P},
+ \mathematics{\S},
+ \mathematics{\S\S},
+ \mathematics{\S\S\S},
+ \mathematics{\ast},
+ \mathematics{\ast\ast},
+ \mathematics{\ast\ast\ast}]
+
+\protect \endinput
diff --git a/tex/context/base/core-ctx.lua b/tex/context/base/core-ctx.lua
new file mode 100644
index 000000000..1dad7c2d7
--- /dev/null
+++ b/tex/context/base/core-ctx.lua
@@ -0,0 +1,93 @@
+if not modules then modules = { } end modules ['core-ctx'] = {
+ version = 1.001,
+ comment = "companion to core-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_prepfiles = false trackers.register("resolvers.prepfiles", function(v) trace_prepfiles = v end)
+
+commands = commands or { }
+
+local list, suffix, islocal, found = { }, "prep", false, false
+
+function commands.loadctxpreplist()
+ local ctlname = file.replacesuffix(tex.jobname,"ctl")
+ if lfs.isfile(ctlname) then
+ local x = xml.load(ctlname)
+ if x then
+ islocal = xml.found(x,"ctx:preplist[@local=='yes']")
+--~ if trace_prepfiles then
+ if islocal then
+ commands.writestatus("systems","loading ctx log file (local)") -- todo: m!systems
+ else
+ commands.writestatus("systems","loading ctx log file (specified)") -- todo: m!systems
+ end
+--~ end
+ for e in xml.collected(x,"ctx:prepfile") do
+ local name = xml.text(e)
+ if islocal then
+ name = file.basename(name)
+ end
+ local done = e.at['done'] or 'no'
+ if trace_prepfiles then
+ commands.writestatus("systems","registering %s -> %s",done)
+ end
+ found = true
+ list[name] = done -- 'yes' or 'no'
+ end
+ end
+ end
+end
+
+-- -- --
+
+local function found(name) -- used in resolve
+ local prepname = name .. "." .. suffix
+ if list[name] and lfs.isfile(prepname) then
+ if trace_prepfiles then
+ commands.writestatus("systems", "preprocessing: using %s",prepname)
+ end
+ return prepname
+ end
+ return false
+end
+
+local function resolve(name) -- used a few times later on
+ local filename = file.collapse_path(name)
+ local prepname = islocal and found(file.basename(name))
+ if prepname then
+ return prepname
+ end
+ prepname = found(filename)
+ if prepname then
+ return prepname
+ end
+ return false
+end
+
+--~ support.doiffileexistelse(name)
+
+local processfile = commands.processfile
+local doifinputfileelse = commands.doifinputfileelse
+
+function commands.processfile(name,maxreadlevel) -- overloaded
+ local prepname = resolve(name)
+ if prepname then
+ return processfile(prepname,0)
+ end
+ return processfile(name,maxreadlevel)
+end
+
+function commands.doifinputfileelse(name,depth)
+ local prepname = resolve(name)
+ if prepname then
+ return doifinputfileelse(prepname,0)
+ end
+ return doifinputfileelse(name,depth)
+end
+
+function commands.preparedfile(name)
+ return resolve(name) or name
+end
diff --git a/tex/context/base/core-ctx.mkii b/tex/context/base/core-ctx.mkii
new file mode 100644
index 000000000..93cf8b4be
--- /dev/null
+++ b/tex/context/base/core-ctx.mkii
@@ -0,0 +1,203 @@
+%D \module
+%D [ file=core-ctx,
+%D version=2006.08.16, % old stuff
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Job Control,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Job Control}
+
+\unprotect
+
+\chardef\preprocessmethod 2 % 0=no check 1=present_check 2=log_check
+\chardef\preprocessstate 0 % 1=found 2=not_present (skip)
+\chardef\preprocesslocal 0 % 0=no 1=yes
+\def \preprocesssuffix {.prep}
+
+\def\loadctxpreplist
+ {\begingroup
+ \chardef\XMLtokensreduction\plusone
+ \ifcase\preprocessmethod
+ % no checking
+ \or
+ % simple checking
+ \or
+ \doiffileexistselse{./\jobname.ctl}
+ {\bgroup
+ \defineXMLenvironment[ctx:preplist][local=no]
+ {\doifelse{\XMLop{local}}{yes}
+ {\global\chardef\preprocesslocal\plusone
+ \writestatus\m!systems{loading ctx log file (local)}}%
+ {\writestatus\m!systems{loading ctx log file (specified)}}}
+ \donothing
+ \defineXMLenvironmentsave[ctx:prepfile][done=no]
+ \donothing
+ {\edef\readfilename{\XMLflush{ctx:prepfile}}%
+ \ifcase\preprocesslocal\else
+ \splitfilename\readfilename
+ \let\readfilename\splitoffbase
+ \fi
+ \writestatus\m!systems{registering \readfilename\space -> \XMLop{done}}%
+ \setxvalue{fp..\readfilename}{\XMLop{done}}}%
+ \processXMLfile{./\jobname.ctl}%
+ \egroup}%
+ {\global\chardef\preprocessmode\plusone}%
+ \fi
+ \global\let\loadctxpreplist\relax
+ \endgroup}
+
+\appendtoks\loadctxpreplist\to\everystarttext % will become: \prependtoks\loadctxpreplist\to\everyjob
+
+\def\docheckprepfile
+ {\ifcase\preprocessmethod
+ \iftracefiles\writestatus\m!systems{preprocessing - not needed}\fi
+ % no preprocessing
+ \or
+ % only check for existence
+ \iftracefiles\writestatus\m!systems{preprocessing - check existence of \readfilename\preprocesssuffix}\fi
+ \doiffileexistselse{\readfilename\preprocesssuffix}
+ {\chardef\preprocessstate\plusone}
+ \donothing
+ \or
+ % check when in list, otherwise assume normal file
+ \bgroup
+ \splitfilename\readfilename
+ \ifx\splitofftype\empty
+ % saveguard and speed up
+ \iftracefiles\writestatus\m!systems{preprocessing - no suffix}\fi
+ \egroup
+ \else\ifcase\preprocesslocal
+ % also ./ strippen
+ \iftracefiles\writestatus\m!systems{preprocessing - check presence of \readfilename\preprocesssuffix}\fi
+ \doifdefinedelse{fp..\readfilename}
+ {\egroup
+ \doiffileexistselse{\readfilename\preprocesssuffix}
+ {\chardef\preprocessstate\plusone}
+ {\chardef\preprocessstate\plustwo}}%
+ {\doifdefinedelse{fp.../\readfilename}
+ {\egroup
+ \edef\readfilename{./\readfilename}%
+ \doiffileexistselse{\readfilename\preprocesssuffix}
+ {\chardef\preprocessstate\plusone}
+ {\chardef\preprocessstate\plustwo}}%
+ {\doifdefinedelse{fp..\splitoffbase}%
+ {\egroup
+ \doiffileexistselse{\readfilename\preprocesssuffix}
+ {\chardef\preprocessstate\plusone}
+ {\chardef\preprocessstate\plustwo}}%
+ {\egroup}}}%
+ \else
+ % maybe just filecheck, why ctl
+ \iftracefiles\writestatus\m!systems{preprocessing - check local presence of \readfilename\preprocesssuffix}\fi
+ \doifdefinedelse{fp..\readfilename}
+ {\egroup
+ \doiffileexistselse{\readfilename\preprocesssuffix}
+ {\chardef\preprocessstate\plusone}
+ {\chardef\preprocessstate\plustwo}}%
+ {\egroup}%
+ \fi
+ \fi\fi}
+
+% beware, \readfilename keeps the original one, but we load and store the
+% suffixed with .prep file (if present)
+
+\def\doreadfile#1#2#3#4% beware, this one already works at format generation time!
+ {\sanitizefilename#2\to\readfilename
+ \ifx\readfilename\empty
+ % silently ignore
+ \else
+ \let\trackedfilename\readfilename
+ \chardef\preprocessstate\zerocount
+ \ifconditional\trackfilenames
+ \doifundefinedelse{fn..\trackedfilename}\donetrue\donefalse
+ \else
+ \donetrue
+ \fi
+ \ifdone
+ \checkfilename\readfilename
+ \ifcase\kindoffile
+ % not a full path or url, check for existence
+ \doifelsenothing{#1}
+ {\iftracefiles\writestatus\m!systems{searching for \readfilename\space on tex path}\fi
+ \def\next{\redoreadfile\readfilename{#3}{#4}}}%
+ {\iftracefiles\writestatus\m!systems{searching for \readfilename\space on #1}\fi
+ \def\next{\redoreadfile{\pathplusfile{#1}{\readfilename}}{#3}{#4}}}%
+ \else
+ % a full path or url, no further checking done
+ \docheckprepfile
+ \ifcase\preprocessstate
+ \doiffileexistselse\readfilename
+ {\iftracefiles\writestatus\m!systems{located \readfilename}\fi
+ \def\next{#3\dodoreadfile}}%
+ {\iftracefiles\writestatus\m!systems{not found \readfilename}\fi
+ \def\next{#4}}%
+ \or
+ \iftracefiles\writestatus\m!systems{located \readfilename\preprocesssuffix}\fi
+ \def\next{#3\dodoreadfile}%
+ \or
+ \iftracefiles\writestatus\m!systems{not found \readfilename\preprocesssuffix}\fi
+ \def\next{#4}%
+ \fi
+ \fi
+ \else
+ \edef\readfilename{\getvalue{fn..\readfilename}}% ??? is done !
+ \iftracefiles\writestatus\m!systems{already located \readfilename}\fi
+ \def\next{#3\dodoreadfile}%
+ \fi
+ \expandafter\next
+ \fi}
+
+\def\redoreadfile#1#2#3%
+ {\docheckprepfile
+ \ifcase\preprocessstate
+ \doiffileexistselse{#1}%
+ {\edef\readfilename{#1}%
+ \iftracefiles\writestatus\m!systems{#1 located}\fi
+ \def\next{#2\dodoreadfile}}%
+ {\iftracefiles\writestatus\m!systems{cannot locate #1}\fi
+ \advance\readlevel\minusone
+ \ifnum\readlevel>\zerocount
+ \edef\readfilename{\pathplusfile{\f!parentpath}{\readfilename}}%
+ \def\next{\redoreadfile\readfilename{#2}{#3}}%
+ \else
+ \def\next{#3}%
+ \fi}%
+ \or
+ \ifcase\preprocesslocal
+ \edef\readfilename{#1}% nor found
+ \else
+ % no path prepending
+ \fi
+ \iftracefiles\writestatus\m!systems{#1\preprocesssuffix\space located}\fi
+ \def\next{#2\dodoreadfile}%
+ \or
+ \def\next{#3}%
+ \fi
+ \next}
+
+\def\dodoreadfile % we provide hooks, for instance for \enableXML
+ {\ifconditional\trackfilenames
+ \setxvalue{fn..\trackedfilename}{\readfilename\ifcase\preprocessstate\or\preprocesssuffix\fi}%
+ \fi
+ \the\everybeforereadfile
+ \ifcase\preprocessstate
+ % no checking or not found when using method 1
+ \def\dodoreadfileindeed{\inputgivenfile\readfilename}%
+ \or
+ % found when using method 1 or 2
+ \def\dodoreadfileindeed{\inputgivenfile{\readfilename\preprocesssuffix}}%
+ \or
+ % not found when using method 2
+ \let\dodoreadfileindeed\relax
+ \fi
+ \dodoreadfileindeed
+ \relax
+ \the\everyafterreadfile}
+
+\protect \endinput
diff --git a/tex/context/base/core-ctx.mkiv b/tex/context/base/core-ctx.mkiv
new file mode 100644
index 000000000..9bf456952
--- /dev/null
+++ b/tex/context/base/core-ctx.mkiv
@@ -0,0 +1,28 @@
+%D \module
+%D [ file=core-ctx,
+%D version=2006.08.16, % old stuff
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Job Control,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Job Control}
+
+\unprotect
+
+\chardef\preprocessmethod \plustwo % always check in mkiv
+
+\registerctxluafile{core-ctx}{1.000}
+
+\def\loadctxpreplist{\ctxlua{commands.loadctxpreplist()}\global\let\loadctxpreplist\relax}
+
+% \prependtoks\loadctxpreplist\to\everyjob
+
+\appendtoks\loadctxpreplist\to\everystarttext
+
+\protect \endinput
diff --git a/tex/context/base/core-def.mkii b/tex/context/base/core-def.mkii
new file mode 100644
index 000000000..840f853a7
--- /dev/null
+++ b/tex/context/base/core-def.mkii
@@ -0,0 +1,105 @@
+%D \module
+%D [ file=core-def,
+%D version=2002.05.07,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Defaults,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Defaults}
+
+%D Here we collect settings that cannot be done earlier due to
+%D depedencies. More code will moved to this module later.
+
+\unprotect
+
+\usesymbols[mis,mvs] % 'glm' no longer needed due to lm
+
+\usesymbols[nav] \setupsymbolset[navigation 1]
+
+\setupinteraction[\c!symbolset=navigation 1]
+
+% initialization order:
+
+%appendtoks \initializeluainstances \to \everyjob
+\appendtoks \showcontextbanner \to \everyjob
+\appendtoks \initializenewlinechar \to \everyjob
+\appendtoks \checksystemcommandmode \to \everyjob
+\appendtoks \calculatecurrenttime \to \everyjob
+\appendtoks \loadsystemfiles \to \everyjob
+
+\appendtoks \loadoptionfile \to \everyjob % can load files !
+
+\appendtoks \preloadfonts \to \everyjob
+\appendtoks \settopskip \to \everyjob
+\appendtoks \preloadlanguages \to \everyjob
+\appendtoks \preloadspecials \to \everyjob
+\appendtoks \openspecialfile \to \everyjob
+\appendtoks \openutilities \to \everyjob
+\appendtoks \splitjobfilename \to \everyjob
+\appendtoks \checknotes \to \everyjob % depends on bodyfont
+\appendtoks \initializeMPgraphics \to \everyjob % after loading system files
+\appendtoks \reportsystemcommandmode \to \everyjob
+\appendtoks \initializemainlanguage \to \everyjob
+\appendtoks \settrue\trackfilenames \to \everyjob
+\appendtoks \newbackgroundfalse \to \everyjob % global
+
+\ifdefined\initializepagecounters
+ \appendtoks \initializepagecounters \to \everyjob
+\fi
+
+\appendtoks \directsetup{*runtime:options} \to \everyjob % we could erase them afterwards % order can change
+\appendtoks \directsetup{*runtime:modules} \to \everyjob % we could erase them afterwards % order can change
+
+\appendtoks \checkpreprocessor \to \everyjob
+
+%appendtoks \page[\v!last] \page \to \everybye % moved to core-job, we need to do this cleaner
+\appendtoks \ifarrangingpages\poparrangedpages\fi \to \everybye
+\appendtoks \registerfileinfo[end]\jobname \to \everybye
+\appendtoks \savenofpages \to \everybye
+\appendtoks \savenofsubpages \to \everybye
+
+\appendtoks \closeutilities \to \everygoodbye
+\appendtoks \stopcopyingblocks \to \everygoodbye
+\appendtoks \closespecialfile \to \everygoodbye
+
+\prependtoks \resetutilities \to \everystarttext % moved 28-02-2002
+\prependtoks \loadtwopassdata \to \everystarttext % moved 28-02-2002
+\appendtoks \checkreferences \to \everystarttext % new 04-12-1999
+
+% \appendtoks\everyjob\expandafter{\the\everyjob\checkpreprocessor}\to\everydump
+
+% temporary here:
+
+% \in \at \about \from \over
+
+\unexpanded\def\arg{\mathortext\normalmatharg\normaltextarg}
+
+% brrr
+% normally one does not want this to happen nested, maybe there
+% is more; non public vars btw, will become conditionals
+
+\ifx\writetoregisterfalse\undefined \else \appendtoks \writetoregisterfalse \to \everybeforeutilityread \fi
+\ifx\writetolistfalse \undefined \else \appendtoks \writetolistfalse \to \everybeforeutilityread \fi
+\ifx\notesenabledfalse \undefined \else \appendtoks \notesenabledfalse \to \everybeforeutilityread \fi
+
+\def\synctexwarning
+ {\ifdefined\synctex \ifnum\synctex=\zerocount \else
+ \writeline
+ \writestatus\m!systems{BEWARE: syntex functionality is enabled!}%
+ \writeline
+ \globallet\synctexwarning\relax
+ \fi \fi}
+
+\prependtoks \synctexwarning \to \everyjob
+\prependtoks \synctexwarning \to \everystarttext
+\appendtoks \synctexwarning \to \everystoptext
+
+% last minute hacks
+
+\protect \endinput
diff --git a/tex/context/base/core-def.mkiv b/tex/context/base/core-def.mkiv
new file mode 100644
index 000000000..59451a914
--- /dev/null
+++ b/tex/context/base/core-def.mkiv
@@ -0,0 +1,94 @@
+%D \module
+%D [ file=core-def,
+%D version=2002.05.07,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Defaults,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Defaults}
+
+%D Here we collect settings that cannot be done earlier due to
+%D depedencies. More code will moved to this module later.
+
+\unprotect
+
+\usesymbols[mis,mvs,nav]
+
+\setupsymbolset[navigation 1]
+
+\setupinteraction[\c!symbolset=navigation 1]
+
+% initialization order:
+
+\appendtoks \showcontextbanner \to \everyjob
+\appendtoks \initializenewlinechar \to \everyjob
+\appendtoks \calculatecurrenttime \to \everyjob
+\appendtoks \loadsystemfiles \to \everyjob
+\appendtoks \loadoptionfile \to \everyjob % can load files !
+\appendtoks \preloadfonts \to \everyjob
+\appendtoks \settopskip \to \everyjob
+\appendtoks \preloadlanguages \to \everyjob
+\appendtoks \preloadspecials \to \everyjob
+\appendtoks \initializeMPgraphics \to \everyjob % after loading system files
+\appendtoks \initializemainlanguage \to \everyjob
+%appendtoks \MPLIBregister \to \everyjob
+\appendtoks \xmlinitialize \to \everyjob
+\appendtoks \newbackgroundfalse \to \everyjob % global
+\appendtoks \initializepagecounters \to \everyjob
+\appendtoks \directsetup{*runtime:options} \to \everyjob % we could erase them afterwards % order can change
+\appendtoks \directsetup{*runtime:modules} \to \everyjob % we could erase them afterwards % order can change
+\appendtoks \checkpreprocessor \to \everyjob
+
+%appendtoks \page[\v!last] \page \to \everybye % moved to core-job, we need to do this cleaner
+\appendtoks \ifarrangingpages\poparrangedpages\fi \to \everybye
+%appendtoks \registerfileinfo[end]\jobfilename \to \everybye
+
+%appendtoks \MPLIBallocate{1000} \to \everydump
+
+\prependtoks \resetallattributes \to \everybeforeoutput
+
+\appendtoks \the\everybackendshipout \to \everyshipout
+\prependtoks \the\everylastbackendshipout \to \everylastshipout
+
+\prependtoks \lefttoright \to \everybeforeoutput
+
+% temporary here:
+
+\ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \dospecialin } \else \let\in \dospecialin \fi
+\ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \dospecialat } \else \let\at \dospecialat \fi
+\ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\dospecialabout} \else \let\about\dospecialabout \fi
+\ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \dospecialfrom } \else \let\from \dospecialfrom \fi
+\ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \dospecialabout} \else \let\over \dospecialabout \fi
+
+\unexpanded\def\arg{\mathortext\normalmatharg\normaltextarg}
+
+% brrr
+
+\appendtoks
+ \synchronizegloballinespecs
+ \synchronizelocallinespecs
+\to \everysetupbodyfont
+
+\appendtoks
+ \synchronizelocallinespecs
+\to \everyswitchtobodyfont
+
+\def\synctexwarning
+ {\ifdefined\synctex \ifnum\synctex=\zerocount \else
+ \writeline
+ \writestatus\m!systems{BEWARE: synctex functionality is enabled!}%
+ \writeline
+ \globallet\synctexwarning\relax
+ \fi \fi}
+
+\prependtoks \synctexwarning \to \everyjob
+\prependtoks \synctexwarning \to \everystarttext
+\appendtoks \synctexwarning \to \everystoptext
+
+\protect \endinput
diff --git a/tex/context/base/core-env.mkii b/tex/context/base/core-env.mkii
new file mode 100644
index 000000000..a22594b27
--- /dev/null
+++ b/tex/context/base/core-env.mkii
@@ -0,0 +1,543 @@
+%D \module
+%D [ file=core-env, % was core-new
+%D version=1995.01.01, % wrong
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=New ones,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Environments}
+
+\unprotect
+
+% Clean labels:
+
+\bgroup % some day this will go away / we could use detokenize as well
+
+% actually we should handle all discretionaries here
+
+\catcode`:=\@@active
+
+\gdef\cleanuplabel#1%
+ {\begingroup
+ \let:\lettercolon
+ \xdef\cleanlabel{#1}%
+ \endgroup}
+
+\gdef\cleanupprefixedlabel#1#2%
+ {\begingroup
+ \let:\lettercolon
+ \xdef\cleanprefix{#1}%
+ \xdef\cleanlabel {#2}%
+ \endgroup}
+
+\gdef\protectlabels
+ {\let:\lettercolon}
+
+\global\def\blabelgroup {\begingroup \let:\lettercolon}
+\global\let\elabelgroup \endgroup
+
+\gdef\labelcsname
+ {\begingroup\let:\lettercolon
+ \expandafter\endgroup\csname}
+
+\gdef\labelvalue#1%
+ {\labelcsname#1\endcsname}
+
+\egroup
+
+%D Modes:
+%D
+%D \starttyping
+%D \enablemode[screen,paper,bound]
+%D
+%D \doifmodeelse {paper} {this} {that}
+%D \doifmode {paper,screen} {this}
+%D \doifnotmode {paper,bound} {that}
+%D
+%D \startmode [list]
+%D \stopmode
+%D
+%D \startnotmode [list]
+%D \stopnotmode
+%D \stoptyping
+%D
+%D system modes have a * as prefix
+%D
+%D Sometimes, we want to prevent a mode for being set. Think
+%D of situations where a style enables a mode, but an outer
+%D level style does not want that. Preventing can be
+%D considered a permanent disabling on forehand.
+
+\def\@mode@{@md@}
+
+\def\systemmodeprefix{*}
+
+\def\disabledmode {0}
+\def\enabledmode {1}
+\def\preventedmode {2}
+
+% fast internal ones
+
+\def\setmode #1{\@EA\let\csname\@mode@#1\endcsname\enabledmode }
+\def\resetmode#1{\@EA\let\csname\@mode@#1\endcsname\disabledmode}
+
+\def\setsystemmode #1{\@EA\let\csname\@mode@\systemmodeprefix#1\endcsname\enabledmode }
+\def\resetsystemmode#1{\@EA\let\csname\@mode@\systemmodeprefix#1\endcsname\disabledmode}
+
+% user ones
+
+\def\preventmode{\unprotect\dopreventmode}
+\def\enablemode {\unprotect\doenablemode }
+\def\disablemode{\unprotect\dodisablemode}
+
+\def\dopreventmode[#1]{\protect\cleanuplabel{#1}\rawprocesscommalist[\cleanlabel]\dodopreventmode}
+\def\doenablemode [#1]{\protect\cleanuplabel{#1}\rawprocesscommalist[\cleanlabel]\dodoenablemode }
+\def\dodisablemode[#1]{\protect\cleanuplabel{#1}\rawprocesscommalist[\cleanlabel]\dododisablemode}
+
+\def\dodopreventmode#1%
+ {\@EA\let\csname\@mode@#1\endcsname\preventedmode}
+
+\def\dodoenablemode#1% mode can be relax
+ {\ifcase0\csname\@mode@#1\endcsname\relax
+ \@EA\let\csname\@mode@#1\endcsname\enabledmode
+ \fi}
+
+\def\dododisablemode#1%
+ {\ifcase0\csname\@mode@#1\endcsname\or
+ \@EA\let\csname\@mode@#1\endcsname\disabledmode
+ \fi}
+
+% handy for mp
+
+\def\booleanmodevalue#1% can be \relax
+ {\expandafter\ifx\csname\@mode@#1\endcsname\relax
+ fals%
+ \else\ifnum0\csname\@mode@#1\endcsname=0
+ fals%
+ \else
+ tru%
+ \fi\fi e}
+
+% check macros
+
+\newif\ifcheckedmode
+
+\def\dodocheckformode#1%
+ {\ifcase0\csname\@mode@#1\endcsname\or\checkedmodetrue\fi}
+
+\def\docheckformode#1#2#3% will be sped up with a quit
+ {\cleanuplabel{#3}%
+ \protect\checkedmodefalse\rawprocesscommacommand[\cleanlabel]\dodocheckformode
+ \ifcheckedmode\@EA#1\else\@EA#2\fi}
+
+\def\dodocheckforallmodes#1%
+ {\ifcase0\csname\@mode@#1\endcsname\relax\checkedmodefalse\or\or\checkedmodefalse\fi}
+
+\def\docheckforallmodes#1#2#3% will be sped up with a quit
+ {\cleanuplabel{#3}%
+ \protect\checkedmodetrue\rawprocesscommacommand[\cleanlabel]\dodocheckforallmodes
+ \ifcheckedmode\@EA#1\else\@EA#2\fi}
+
+% simple ones
+
+\def\doifmodeelse{\unprotect\dodoifmodeelse}
+\def\doifmode {\unprotect\dodoifmode}
+\def\doifnotmode {\unprotect\dodoifnotmode}
+\def\startmode {\unprotect\dostartmode}
+\def\startnotmode{\unprotect\dostartnotmode}
+
+\def\dodoifmodeelse
+ {\docheckformode\firstoftwoarguments\secondoftwoarguments}
+
+\def\dodoifmode
+ {\docheckformode\firstofoneargument\gobbleoneargument}
+
+\def\dodoifnotmode
+ {\docheckformode\gobbleoneargument\firstofoneargument}
+
+\long\def\dostartmode[#1]%
+ {\docheckformode\donothing\dostopmode{#1}}
+
+\long\def\dostartnotmode[#1]%
+ {\docheckformode\dostopnotmode\donothing{#1}}
+
+\let\stopmode \donothing
+\let\stopnotmode\donothing
+
+\long\def\dostopmode #1\stopmode {}
+\long\def\dostopnotmode#1\stopnotmode{}
+
+\def\doifallmodeselse{\unprotect\dodoifallmodeselse}
+\def\doifallmodes {\unprotect\dodoifallmodes}
+\def\doifnotallmodes {\unprotect\dodoifnotallmodes}
+\def\startallmodes {\unprotect\dostartallmodes}
+\def\startnotallmodes{\unprotect\dostartnotallmodes}
+
+\def\dodoifallmodeselse
+ {\docheckforallmodes\firstoftwoarguments\secondoftwoarguments}
+
+\def\dodoifallmodes
+ {\docheckforallmodes\firstofoneargument\gobbleoneargument}
+
+\def\dodoifnotallmodes
+ {\docheckforallmodes\gobbleoneargument\firstofoneargument}
+
+\long\def\dostartallmodes[#1]%
+ {\docheckforallmodes\donothing\dostopallmodes{#1}}
+
+\long\def\dostartnotallmodes[#1]%
+ {\docheckforallmodes\dostopnotallmodes\donothing{#1}}
+
+\let\stopallmodes \donothing
+\let\stopnotallmodes\donothing
+
+\long\def\dostopallmodes #1\stopallmodes {}
+\long\def\dostopnotallmodes#1\stopnotallmodes{}
+
+% Setups
+
+\let\startsetups\relax % to please dep checker
+\let\stopsetups \relax % to please dep checker
+
+\expanded
+ {\long\def\@EA\noexpand\csname\e!start\v!setups\endcsname
+ {\begingroup\noexpand\doifnextoptionalelse
+ {\noexpand\startsetupsA\@EA\noexpand\csname\e!stop\v!setups\endcsname}
+ {\noexpand\startsetupsB\@EA\noexpand\csname\e!stop\v!setups\endcsname}}}
+
+\letvalue{\e!stop\v!setups}\relax
+
+\unexpanded \def\setups{\doifnextbgroupelse\dosetupsA\dosetupsB} % {..} or [..]
+\unexpanded \def\setup {\doifnextbgroupelse\dosetups \dosetupsC} % {..} or [..]
+
+\def\dosetupsA #1{\cleanuplabel{#1}\processcommacommand[\cleanlabel]\dosetups} % {..}
+\def\dosetupsB[#1]{\cleanuplabel{#1}\processcommacommand[\cleanlabel]\dosetups} % [..]
+\def\dosetupsC[#1]{\cleanuplabel{#1}\dosetups\cleanlabel} % [..]
+
+% \def\dosetups#1% the grid option will be extended to other main modes
+% {\executeifdefined{\??su\ifgridsnapping\v!grid\fi:#1}
+% {\executeifdefined{\??su :#1}\gobbleoneargument}\empty} % takes one argument
+%
+% \def\setupwithargument#1% the grid option will be extended to other main modes
+% {\executeifdefined{\??su:#1}\gobbleoneargument}
+
+% better:
+
+% \def\dosetups#1% the grid option will be extended to other main modes
+% {\executeifdefined{\??su\ifgridsnapping\v!grid\fi:#1}
+% {\executeifdefined{\??su :#1}\gobbleoneargument}\empty} % takes one argument
+%
+% \def\setupwithargument#1% the grid option will be extended to other main modes
+% {\executeifdefined{\??su:#1}\gobbleoneargument}
+
+% faster:
+
+\letvalue{\??su:\letterpercent}\gobbleoneargument
+
+\def\dosetups#1% the grid option will be extended to other main modes
+ {\csname\??su
+ \ifgridsnapping
+ \ifcsname\??su\v!grid:#1\endcsname\v!grid:#1\else\ifcsname\??su:#1\endcsname:#1\else:\letterpercent\fi\fi
+ \else
+ \ifcsname\??su:#1\endcsname:#1\else:\letterpercent\fi
+ \fi
+ \endcsname\empty} % takes one argument
+
+\def\setupwithargument#1% the grid option will be extended to other main modes
+ {\csname\??su:\ifcsname\??su:#1\endcsname#1\else\letterpercent\fi\endcsname}
+
+\let\directsetup\dosetups
+
+% somehow fails ...
+%
+% \letvalue{\??su:..}\gobbleoneargument
+%
+% \def\dosetups#1% the grid option will be extended to other main modes
+% {\csname \??su
+% \ifcsname\??su\ifgridsnapping\v!grid\fi:#1\endcsname\v!grid:#1\else
+% \ifcsname\??su :#1\endcsname :#1\else
+% :..\fi\fi
+% \endcsname\empty} % takes one argument
+%
+% \def\setupwithargument#1% the grid option will be extended to other main modes
+% {\csname\??su:\ifcsname\??su:#1\endcsname#1\else..\fi\endcsname}
+
+\let\directsetup\dosetups
+
+\def\doifsetupselse#1% to be done: grid
+ {\doifdefinedelse{\??su:#1}}
+
+\chardef\setupseolmode\plusone
+
+\def\startsetups {\xxstartsetups\plusone \stopsetups } \let\stopsetups \relax
+\def\startlocalsetups{\xxstartsetups\plusone \stoplocalsetups} \let\stoplocalsetups\relax
+\def\startrawsetups {\xxstartsetups\zerocount\stoprawsetups } \let\stoprawsetups \relax
+\def\startxmlsetups {\xxstartsetups\plustwo \stopxmlsetups } \let\stopxmlsetups \relax
+
+\def\xxstartsetups#1#2%
+ {\begingroup\chardef\setupseolmode#1\doifnextoptionalelse{\startsetupsA#2}{\startsetupsB#2}}
+
+\def\startsetupsA#1% [ ] delimited
+ {\ifcase\setupseolmode\or\catcode`\^^M\@@ignore\or\catcode`\^^M\@@ignore\catcode`\|\@@other\fi
+ \dotripleempty\dostartsetups[#1]}
+
+\def\startsetupsB#1#2 % space delimited
+ {\ifcase\setupseolmode\or\catcode`\^^M\@@ignore\or\catcode`\^^M\@@ignore\catcode`\|\@@other\fi
+ \dodostartsetups#1\empty{#2}}
+
+\def\startsetupsC[#1][#2][#3]{\dodostartsetups#1{#2}{#3}} % [..] [..]
+\def\startsetupsD[#1][#2][#3]{\dodostartsetups#1\empty{#2}} % [..]
+
+\def\dostartsetups
+ {\ifthirdargument\@EA\startsetupsC\else\@EA\startsetupsD\fi}
+
+% \long\def\dodostartsetups#1#2#3% watch out: not \grabuntil
+% {\dograbuntil#1{\endgroup\dodoglobal\long\setvalue{\??su#2:#3}}} % \doglobal
+%
+% better:
+
+% \long\def\dodostartsetups#1#2#3% watch out: not \grabuntil
+% {\cleanuplabel{\??su#2:#3}\dograbuntil#1{\endgroup\dodoglobal\long\setvalue\cleanlabel}} % \doglobal
+
+% \long\def\dodostartsetups#1#2#3%
+% {\cleanuplabel{\??su#2:#3}%
+% \long\def\dododostartsetups##1#1{\endgroup\dodoglobal\long\setvalue\cleanlabel####1{##1}}\dododostartsetups}
+
+\long\def\dodostartsetups#1#2#3%
+ {\cleanuplabel{\??su#2:#3}%
+ \long\def\dododostartsetups##1#1%
+ {\endgroup
+ \dodoglobal % bah
+ \long\expandafter\setvalue\expandafter\cleanlabel\expandafter####\expandafter1\expandafter{##1}}%
+ \dododostartsetups\empty} % the empty trick prevents the { } in {arg} from being eaten up
+
+\def\systemsetupsprefix{*}
+
+\def\systemsetups#1{\dosetups{\systemsetupsprefix#1}}
+
+\def\resetsetups[#1]% see x-fo for usage
+ {\ifundefined{\??su\ifgridsnapping\v!grid\fi:#1}%
+ \dodoglobal\letbeundefined{\??su:#1}%
+ \else
+ \dodoglobal\letbeundefined{\??su\ifgridsnapping\v!grid\fi:#1}%
+ \fi}
+
+% or
+%
+% \def\resetsetups[#1]%
+% {\letbeundefined
+% {\??su:%
+% \ifundefined{\??su\ifgridsnapping\v!grid\fi:#1}#1\else\ifgridsnapping\v!grid\fi%
+% #1}}
+
+%D new and beta and will become a module instead
+
+\def\defineshortcut
+ {\dotripleargument\dodefineshortcut}
+
+\def\dodefineshortcut[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelsenothing{#1}
+ {\dododefineshortcut[<>][#2][#3]}
+ {\dododefineshortcut[#1][#2][#3]}%
+ \else\ifsecondargument
+ \dododefineshortcut[<>][#1][#2]%
+ \else
+ \dododefineshortcut[<>][][#1]%
+ \fi\fi}
+
+\def\dododefineshortcut[#1#2][#3][#4]% #1 is the trigger, #2 the delimiter/tag
+ {\doifundefined{\??te\??te\string#2}{\letvalue{\??te\??te\string#2}=#1}%
+ \defineactivecharacter #1 {\@EA\doshortcut\string#2} %
+ \getparameters
+ [\??te\string#2#3]
+ [\c!commands=,\c!command=,\c!style=,\c!color=,#4]}
+
+\def\doshortcut#1%
+ {\ifmmode
+ \getvalue{\??te\??te#1}%
+ \else
+ \bgroup
+ \catcode`#1=\@@other
+ \def\dodoshortcut##1#1%
+ {\def\shorttag{\??te#1}%
+ \def\shortcut{##1}%
+ \dododoshortcut##1:\end}%
+ \@EA\dodoshortcut
+ \fi}
+
+\def\dododoshortcut#1:#2\end
+ {\doifelsenothing{#2}
+ {\doifundefinedelse{\shorttag\c!commands}
+ {\shortcut}
+ {\@EA\dodododoshortcut\@EA\shorttag\@EA:\shortcut:\end}}
+ {\doifundefinedelse{\shorttag#1\c!commands}
+ {\shortcut}
+ {\dodododoshortcut\shorttag#1:#2\end}}%
+ \egroup}
+
+\def\dodododoshortcut#1:#2:\end
+ {\getvalue{#1\c!commands}%
+ \doattributes{#1}\c!style\c!color{\getvalue{#1\c!command}{#2}}}
+
+%D \defineshortcut [style=type]
+%D \defineshortcut [b] [style=bold]
+%D \defineshortcut [e] [style=\em]
+%D \defineshortcut [t] [style=type]
+%D \defineshortcut [c] [style=cap]
+%D \defineshortcut [k] [style=cap]
+%D \defineshortcut [u] [style=type,command=\hyphenatedurl]
+%D
+%D \startlines
+%D test test
+%D test test
+%D test test
+%D test test
+%D zus<>zo zus<:>zo zus<::>zo
+%D test test dat (ziezo)
+%D test test dat (:ziezo)
+%D test test dat (ziezo:)
+%D test test dat (zi:ezo:)
+%D well, looks fuzzy
+%D $10<20$
+%D \stoplines
+%D
+%D \defineshortcut [<>] [i] [style=\it]
+%D \defineshortcut [()] [b] [style=\bf]
+%D \defineshortcut [++] [s] [style=\sl]
+%D \defineshortcut [//] [u] [style=\underbars]
+%D \defineshortcut [--] [a] [style=\overstrike]
+%D
+%D \startlines
+%D it seems well
+%D it seems (b:to work) well
+%D it seems +s:to work+ well
+%D it seems /u:to work/ well
+%D it seems -a:to work- well
+%D \stoplines
+
+%D \macros
+%D {setvariables,getvariable,getvariabledefault}
+%D
+%D \starttyping
+%D \setvariables[xx][title=]
+%D \setvariables[xx][title=test test]
+%D \setvariables[xx][title=test $x=1$ test] % fatal error reported
+%D \setvariables[xx][title=test {$x=1$} test]
+%D \setvariables[xx][title] % fatal error reported
+%D \setvariables[xx][titletitel=e]
+%D \stoptyping
+
+\def\??vars{@@vars}
+
+\def\setvariables {\dotripleargument\dosetvariables[\getrawparameters ]}
+\def\setevariables{\dotripleargument\dosetvariables[\getraweparameters]}
+\def\setgvariables{\dotripleargument\dosetvariables[\getrawgparameters]}
+\def\setxvariables{\dotripleargument\dosetvariables[\getrawxparameters]}
+
+\def\globalsetvariables % obsolete
+ {\dotripleargument\dosetvariables[\globalgetrawparameters]}
+
+\long\def\dosetvariables[#1][#2][#3]% tricky, test on s-pre-60
+ {\errorisfataltrue
+ \doifelse{#2}\currentvariableclass
+ {#1[\??vars:#2:][#3]}%
+ {\pushmacro\currentvariableclass
+ \def\currentvariableclass{#2}%
+ \getvariable{#2}\s!reset
+ #1[\??vars:#2:][#3]%
+ \getvariable{#2}\s!set
+ \popmacro\currentvariableclass}%
+ \errorisfatalfalse}
+
+\long\def\setvariable #1#2#3{\long\setvalue {\??vars:#1:#2}{#3}}
+\long\def\setevariable#1#2#3{\long\setevalue{\??vars:#1:#2}{#3}}
+\long\def\setgvariable#1#2#3{\long\setgvalue{\??vars:#1:#2}{#3}}
+\long\def\setxvariable#1#2#3{\long\setxvalue{\??vars:#1:#2}{#3}}
+
+\def\getvariable#1#2% to be sped up
+ {\csname
+ \ifcsname\??vars:#1:#2\endcsname\??vars:#1:#2\else\s!empty\fi
+ \endcsname}
+
+\def\showvariable#1#2%
+ {\showvalue{\ifcsname\??vars:#1:#2\endcsname\??vars:#1:#2\else\s!empty\fi}}
+
+\let\currentvariableclass\empty
+
+%D \macros
+%D {doifelsevariable,doifvariable,doifnotvariable}
+%D
+%D A few trivial macros:
+
+\def\doifelsevariable#1#2%
+ {\ifcsname\??vars:#1:#2\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifvariable#1#2%
+ {\ifcsname\??vars:#1:#2\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doifnotvariable#1#2%
+ {\ifcsname\??vars:#1:#2\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\getvariabledefault#1#2% #3% can be command, so no ifcsname here
+ {\executeifdefined{\??vars:#1:#2}}% {#3}
+
+%D \macros
+%D {checkvariables}
+%D
+%D I'll probably forget that this on exists.
+
+\def\checkvariables
+ {\dodoubleargument\docheckvariables}
+
+\def\docheckvariables
+ {\dogetparameters\docheckrawvalue}
+
+\def\docheckrawvalue#1#2#3%
+ {\doifundefined {\??vars:#1:#2}{\setvalue{\??vars:#1:#2}{#3}}
+ {\doifvaluenothing{\??vars:#1:#2}{\setvalue{\??vars:#1:#2}{#3}}}}
+
+% \def\setupenv{\dodoubleargument\rawgetparameters[\??en]}
+%
+% \def\doifenvelse#1{\doifdefinedelse{\??en#1}} % speed up
+% \def\doifenv #1{\doifdefined {\??en#1}} % speed up
+% \def\doifnotenv #1{\doifundefined {\??en#1}} % speed up
+%
+% \def\env#1{\csname\??en#1\endcsname}
+%
+% \def\envvar#1#2%
+% {\ifcsname\??en#1\endcsname
+% \csname\??en#1\endcsname\else#2%
+% \fi}
+
+% low level change, now also accessible as \getvariable{environment}{...}; the
+% next macros will become obsolete some day in favor of normal variables
+
+\def\s!environment{environment}
+
+\def\setupenv {\dotripleargument\dosetvariables[\getrawparameters][\s!environment]}
+\def\doifenvelse{\doifelsevariable \s!environment}
+\def\doifenv {\doifvariable \s!environment}
+\def\doifnotenv {\doifnotvariable \s!environment}
+\def\env {\getvariable \s!environment}
+\def\envvar {\getvariabledefault\s!environment}
+
+\protect \endinput
diff --git a/tex/context/base/core-env.mkiv b/tex/context/base/core-env.mkiv
new file mode 100644
index 000000000..d927ff3ad
--- /dev/null
+++ b/tex/context/base/core-env.mkiv
@@ -0,0 +1,388 @@
+%D \module
+%D [ file=core-env, % was core-new
+%D version=1995.01.01, % wrong
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=New ones,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Environments}
+
+\unprotect
+
+%D Modes:
+%D
+%D \starttyping
+%D \enablemode[screen,paper,bound]
+%D
+%D \doifmodeelse {paper} {this} {that}
+%D \doifmode {paper,screen} {this}
+%D \doifnotmode {paper,bound} {that}
+%D
+%D \startmode [list]
+%D \stopmode
+%D
+%D \startnotmode [list]
+%D \stopnotmode
+%D \stoptyping
+%D
+%D system modes have a * as prefix
+%D
+%D Sometimes, we want to prevent a mode for being set. Think
+%D of situations where a style enables a mode, but an outer
+%D level style does not want that. Preventing can be
+%D considered a permanent disabling on forehand.
+
+\def\@mode@{@md@}
+
+\def\systemmodeprefix{*}
+
+\def\disabledmode {0} % no chardefs
+\def\enabledmode {1}
+\def\preventedmode{2}
+
+% fast internal ones
+
+\def\setmode #1{\@EA\let\csname\@mode@#1\endcsname\enabledmode }
+\def\resetmode#1{\@EA\let\csname\@mode@#1\endcsname\disabledmode}
+
+\def\setsystemmode #1{\@EA\let\csname\@mode@\systemmodeprefix#1\endcsname\enabledmode }
+\def\resetsystemmode#1{\@EA\let\csname\@mode@\systemmodeprefix#1\endcsname\disabledmode}
+
+% user ones
+
+\def\preventmode{\unprotect\dopreventmode}
+\def\enablemode {\unprotect\doenablemode }
+\def\disablemode{\unprotect\dodisablemode}
+
+\def\dopreventmode[#1]{\protect\rawprocesscommacommand[#1]\dodopreventmode}
+\def\doenablemode [#1]{\protect\rawprocesscommacommand[#1]\dodoenablemode }
+\def\dodisablemode[#1]{\protect\rawprocesscommacommand[#1]\dododisablemode}
+
+\def\dodopreventmode#1%
+ {\@EA\let\csname\@mode@#1\endcsname\preventedmode}
+
+\def\dodoenablemode#1% mode can be relax
+ {\ifcase0\csname\@mode@#1\endcsname\relax
+ \@EA\let\csname\@mode@#1\endcsname\enabledmode
+ \fi}
+
+\def\dododisablemode#1%
+ {\ifcase0\csname\@mode@#1\endcsname\or
+ \@EA\let\csname\@mode@#1\endcsname\disabledmode
+ \fi}
+
+% handy for mp
+
+\def\booleanmodevalue#1% can be \relax
+ {\expandafter\ifx\csname\@mode@#1\endcsname\relax
+ fals%
+ \else\ifnum0\csname\@mode@#1\endcsname=0
+ fals%
+ \else
+ tru%
+ \fi\fi e}
+
+% check macros
+
+\newif\ifcheckedmode
+
+\def\dodocheckformode#1%
+ {\ifcase0\csname\@mode@#1\endcsname\or\checkedmodetrue\fi}
+
+\def\docheckformode#1#2#3% will be sped up with a quit
+ {\protect\checkedmodefalse\rawprocesscommacommand[#3]\dodocheckformode
+ \ifcheckedmode\@EA#1\else\@EA#2\fi}
+
+\def\dodocheckforallmodes#1%
+ {\ifcase0\csname\@mode@#1\endcsname\relax\checkedmodefalse\or\or\checkedmodefalse\fi}
+
+\def\docheckforallmodes#1#2#3% will be sped up with a quit
+ {\protect\checkedmodetrue\rawprocesscommacommand[#3]\dodocheckforallmodes
+ \ifcheckedmode\@EA#1\else\@EA#2\fi}
+
+% simple ones
+
+\unexpanded\def\doifmodeelse{\unprotect\dodoifmodeelse}
+\unexpanded\def\doifmode {\unprotect\dodoifmode}
+\unexpanded\def\doifnotmode {\unprotect\dodoifnotmode}
+\unexpanded\def\startmode {\unprotect\dostartmode}
+\unexpanded\def\startnotmode{\unprotect\dostartnotmode}
+
+\def\dodoifmodeelse
+ {\docheckformode\firstoftwoarguments\secondoftwoarguments}
+
+\def\dodoifmode
+ {\docheckformode\firstofoneargument\gobbleoneargument}
+
+\def\dodoifnotmode
+ {\docheckformode\gobbleoneargument\firstofoneargument}
+
+\long\unexpanded\def\dostartmode[#1]%
+ {\docheckformode\donothing\dostopmode{#1}}
+
+\long\def\dostartnotmode[#1]%
+ {\docheckformode\dostopnotmode\donothing{#1}}
+
+\unexpanded\def\stopmode {} % no relax
+\unexpanded\def\stopnotmode{} % no relax
+
+\long\def\dostopmode #1\stopmode {}
+\long\def\dostopnotmode#1\stopnotmode{}
+
+\unexpanded\def\doifallmodeselse{\unprotect\dodoifallmodeselse}
+\unexpanded\def\doifallmodes {\unprotect\dodoifallmodes}
+\unexpanded\def\doifnotallmodes {\unprotect\dodoifnotallmodes}
+\unexpanded\def\startallmodes {\unprotect\dostartallmodes}
+\unexpanded\def\startnotallmodes{\unprotect\dostartnotallmodes}
+
+\def\dodoifallmodeselse
+ {\docheckforallmodes\firstoftwoarguments\secondoftwoarguments}
+
+\def\dodoifallmodes
+ {\docheckforallmodes\firstofoneargument\gobbleoneargument}
+
+\def\dodoifnotallmodes
+ {\docheckforallmodes\gobbleoneargument\firstofoneargument}
+
+\long\def\dostartallmodes[#1]%
+ {\docheckforallmodes\donothing\dostopallmodes{#1}}
+
+\long\def\dostartnotallmodes[#1]%
+ {\docheckforallmodes\dostopnotallmodes\donothing{#1}}
+
+\unexpanded\def\stopallmodes {} % no relax
+\unexpanded\def\stopnotallmodes{} % no relax
+
+\long\def\dostopallmodes #1\stopallmodes {}
+\long\def\dostopnotallmodes#1\stopnotallmodes{}
+
+%D Lets now set a mode:
+
+\enablemode[mkiv] \setsystemmode{mkiv}
+
+%D Setups:
+
+\unexpanded\def\startsetups{} % to please dep checker
+\unexpanded\def\stopsetups {} % to please dep checker
+
+\expanded
+ {\long\def\@EA\noexpand\csname\e!start\v!setups\endcsname
+ {\begingroup\noexpand\doifnextoptionalelse
+ {\noexpand\dostartsetupsA\@EA\noexpand\csname\e!stop\v!setups\endcsname}
+ {\noexpand\dostartsetupsB\@EA\noexpand\csname\e!stop\v!setups\endcsname}}}
+
+\letvalue{\e!stop\v!setups}\relax
+
+\unexpanded\def\setups{\doifnextbgroupelse\dosetupsA\dosetupsB} % {..} or [..]
+\unexpanded\def\setup {\doifnextbgroupelse\dosetups \dosetupsC} % {..} or [..]
+
+\def\dosetupsA #1{\processcommacommand[#1]\dosetups} % {..}
+\def\dosetupsB[#1]{\processcommacommand[#1]\dosetups} % [..]
+\def\dosetupsC[#1]{\dosetups{#1}} % [..]
+
+\letvalue{\??su:\letterpercent}\gobbleoneargument
+
+\def\dosetups#1% the grid option will be extended to other main modes
+ {\csname\??su
+ \ifgridsnapping
+ \ifcsname\??su\v!grid:#1\endcsname\v!grid:#1\else\ifcsname\??su:#1\endcsname:#1\else:\letterpercent\fi\fi
+ \else
+ \ifcsname\??su:#1\endcsname:#1\else:\letterpercent\fi
+ \fi
+ \endcsname\empty} % takes one argument
+
+% the next one is meant for \c!setups situations, hence the check for
+% a shortcut
+
+\def\doprocesslocalsetups#1%
+ {\edef\tobeprocessedsetups{#1}%
+ \ifx\tobeprocessedsetups\empty\else
+ \dodoprocesslocalsetups
+ \fi}
+
+\def\dodoprocesslocalsetups
+ {\@EA\processcommalist\@EA[\tobeprocessedsetups]\dosetups}
+
+\edef\setupwithargument#1% saves a few expansions
+ {\noexpand\csname\??su:\noexpand\ifcsname\??su:#1\endcsname#1\noexpand\else\letterpercent\noexpand\fi\endcsname}
+
+\let\directsetup\dosetups
+
+\def\doifsetupselse#1% to be done: grid
+ {\doifdefinedelse{\??su:#1}}
+
+\chardef\setupseolmode\plusone
+
+\unexpanded\def\startsetups {\xxstartsetups\plusone \stopsetups } \let\stopsetups \relax
+\unexpanded\def\startlocalsetups{\xxstartsetups\plusone \stoplocalsetups} \let\stoplocalsetups\relax
+\unexpanded\def\startrawsetups {\xxstartsetups\zerocount\stoprawsetups } \let\stoprawsetups \relax
+\unexpanded\def\startxmlsetups {\xxstartsetups\plustwo \stopxmlsetups } \let\stopxmlsetups \relax
+
+\def\xxstartsetups#1#2%
+ {\begingroup\let\setupseolmode#1\doifnextoptionalelse{\dostartsetupsA#2}{\dostartsetupsB#2}}
+
+\def\dostartsetupsA#1% [ ] delimited
+ {\ifcase\setupseolmode\or\catcode`\^^M\@@ignore\or\catcode`\^^M\@@ignore\catcode`\|\@@other\fi
+ \dotripleempty\dostartsetups[#1]}
+
+\def\dostartsetupsB#1#2 % space delimited
+ {\ifcase\setupseolmode\or\catcode`\^^M\@@ignore\or\catcode`\^^M\@@ignore\catcode`\|\@@other\fi
+ \dodostartsetups#1\empty{#2}}
+
+\def\dostartsetupsC[#1][#2][#3]{\dodostartsetups#1{#2}{#3}} % [..] [..]
+\def\dostartsetupsD[#1][#2][#3]{\dodostartsetups#1\empty{#2}} % [..]
+
+\def\dostartsetups
+ {\ifthirdargument\@EA\dostartsetupsC\else\@EA\dostartsetupsD\fi}
+
+\long\def\dodostartsetups#1#2#3%
+ {\long\def\dododostartsetups##1#1%
+ {\endgroup
+ \dodoglobal % bah
+ \long\expandafter\def\csname\??su#2:#3\expandafter\endcsname\expandafter####\expandafter1\expandafter{##1}}%
+ \dododostartsetups\empty} % the empty trick prevents the { } in {arg} from being eaten up
+
+\def\systemsetupsprefix{*}
+
+\def\systemsetups#1{\dosetups{\systemsetupsprefix#1}}
+
+\def\resetsetups[#1]% see x-fo for usage
+ {\ifcsname\??su\ifgridsnapping\v!grid\fi:#1\endcsname
+ \dodoglobal\letbeundefined{\??su\ifgridsnapping\v!grid\fi:#1}%
+ \else
+ \dodoglobal\letbeundefined{\??su:#1}%
+ \fi}
+
+%D \macros
+%D {setvariables,getvariable,getvariabledefault}
+%D
+%D \starttyping
+%D \setvariables[xx][title=]
+%D \setvariables[xx][title=test test]
+%D \setvariables[xx][title=test $x=1$ test] % fatal error reported
+%D \setvariables[xx][title=test {$x=1$} test]
+%D \setvariables[xx][title] % fatal error reported
+%D \setvariables[xx][titletitel=e]
+%D \stoptyping
+
+\def\??vars{@@vars}
+
+\def\setvariables {\dotripleargument\dosetvariables[\getrawparameters ]}
+\def\setevariables{\dotripleargument\dosetvariables[\getraweparameters]}
+\def\setgvariables{\dotripleargument\dosetvariables[\getrawgparameters]}
+\def\setxvariables{\dotripleargument\dosetvariables[\getrawxparameters]}
+
+\def\globalsetvariables % obsolete
+ {\dotripleargument\dosetvariables[\globalgetrawparameters]}
+
+\long\def\dosetvariables[#1][#2][#3]% tricky, test on s-pre-60
+ {\errorisfataltrue
+ \doifelse{#2}\currentvariableclass
+ {#1[\??vars:#2:][#3]}%
+ {\pushmacro\currentvariableclass
+ \def\currentvariableclass{#2}%
+ \getvariable{#2}\s!reset
+ #1[\??vars:#2:][#3]%
+ \getvariable{#2}\s!set
+ \popmacro\currentvariableclass}%
+ \errorisfatalfalse}
+
+\long\def\setvariable #1#2#3{\long\expandafter\def \csname\??vars:#1:#2\endcsname{#3}}
+\long\def\setevariable#1#2#3{\long\expandafter\edef\csname\??vars:#1:#2\endcsname{#3}}
+\long\def\setgvariable#1#2#3{\long\expandafter\gdef\csname\??vars:#1:#2\endcsname{#3}}
+\long\def\setxvariable#1#2#3{\long\expandafter\xdef\csname\??vars:#1:#2\endcsname{#3}}
+
+\def\getvariable#1#2%
+ {\csname
+ \ifcsname\??vars:#1:#2\endcsname\??vars:#1:#2\else\s!empty\fi
+ \endcsname}
+
+\def\showvariable#1#2%
+ {\showvalue{\ifcsname\??vars:#1:#2\endcsname\??vars:#1:#2\else\s!empty\fi}}
+
+\let\currentvariableclass\empty
+
+%D \macros
+%D {checkvariables}
+%D
+%D I'll probably forget that this on exists.
+
+\def\checkvariables
+ {\dodoubleargument\docheckvariables}
+
+\def\docheckvariables
+ {\dogetparameters\docheckrawvalue}
+
+\long\def\docheckrawvalue#1#2#3%
+ {\ifcsname\??vars:#1:#2\endcsname
+ \edef\checkedrawvalue{\csname\??vars:#1:#2\endcsname}%
+ \ifx\checkedrawvalue\empty
+ \long\expandafter\def\csname\??vars:#1:#2\endcsname{#3}%
+ \fi
+ \else
+ \long\expandafter\def\csname\??vars:#1:#2\endcsname{#3}%
+ \fi}
+
+%D \macros
+%D {doifelsevariable,doifvariable,doifnotvariable}
+%D
+%D A few trivial macros:
+
+\def\doifelsevariable#1#2%
+ {\ifcsname\??vars:#1:#2\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifvariable#1#2%
+ {\ifcsname\??vars:#1:#2\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doifnotvariable#1#2%
+ {\ifcsname\??vars:#1:#2\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\getvariabledefault#1#2% #3% can be command, so no ifcsname here
+ {\executeifdefined{\??vars:#1:#2}}% {#3}
+
+% \unexpanded\def\setupenv{\dodoubleargument\rawgetparameters[\??en]}
+%
+% \def\doifenvelse#1{\doifdefinedelse{\??en#1}} % speed up
+% \def\doifenv #1{\doifdefined {\??en#1}} % speed up
+% \def\doifnotenv #1{\doifundefined {\??en#1}} % speed up
+%
+% \def\env#1{\csname\??en#1\endcsname}
+%
+% \def\envvar#1#2%
+% {\ifcsname\??en#1\endcsname
+% \csname\??en#1\endcsname\else#2%
+% \fi}
+%
+% low level change, now also accessible as \getvariable
+% {environment}{...}; the next macros will become obsolete
+% some day in favor of normal variables in the environment
+% namespace
+
+\def\s!environment{environment}
+
+\unexpanded\def\setupenv {\dotripleargument\dosetvariables[\getrawparameters][\s!environment]}
+\def\doifenvelse{\doifelsevariable \s!environment}
+\def\doifenv {\doifvariable \s!environment}
+\def\doifnotenv {\doifnotvariable \s!environment}
+\def\env {\getvariable \s!environment}
+\def\envvar {\getvariabledefault\s!environment}
+
+\protect \endinput
diff --git a/tex/context/base/core-fil.mkii b/tex/context/base/core-fil.mkii
new file mode 100644
index 000000000..fca253a7b
--- /dev/null
+++ b/tex/context/base/core-fil.mkii
@@ -0,0 +1,347 @@
+%D \module
+%D [ file=core-fil,
+%D version=1997.11.15,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=File Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / File Support}
+
+\unprotect
+
+%D Files registered as temporary files will be deleted after a
+%D run by texexec:
+
+% \starttext
+% \immediate\openout\scratchwrite=oeps.tmp
+% \immediate\write\scratchwrite{oeps}
+% \immediate\closeout\scratchwrite
+% \registertempfile{oeps.tmp}
+% \typefile{oeps.tmp}
+% \stoptext
+
+\let\usedtempfile\gobbleoneargument
+
+\def\registertempfile#1{\immediatewriteutility{f t {#1}}}
+
+%D \macros
+%D {definefilesynonym}
+%D
+%D One of the problems with loading files is that their names
+%D can depend on the interface language. We therefore need a
+%D method to define filesynonyms. The actual synonyms are
+%D defined elsewhere, but look like:
+%D
+%D \starttyping
+%D \definefilesynonym [chemic] [chemie]
+%D \definefilesynonym [einheit] [unit]
+%D \definefilesynonym [unit] [unit]
+%D \stoptyping
+%D
+%D So we can say in english:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemic,unit]
+%D \stoptyping
+%D
+%D and in dutch:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemie,unit]
+%D \stoptyping
+
+% will be redone in mkiv
+
+\def\definefilesynonym
+ {\dodoubleempty\dodefinefilesynonym}
+
+\def\dodefinefilesynonym[#1][#2]%
+ {\ifundefined{\??fs#1}\else
+ \doifnotvalue{\??fs#1}{#2}{\showmessage\m!files1{#1 (#2),\getvalue{\??fs#1}}}%
+ \fi
+ \doifelse{#1}{#2}{\letbeundefined{\??fs#1}{#2}}{\setevalue{\??fs#1}{#2}}}
+
+%D \macros
+%D {definefilefallback}
+
+\def\definefilefallback
+ {\dodoubleargument\dodefinefilefallback}
+
+\def\dodefinefilefallback[#1][#2]%
+ {\doifnotfile{#1}
+ {\def\docommand##1{\doiffile{##1}{\definefilesynonym[#1][##1]\quitcommalist}}%
+ \processcommalist[#2]\docommand}}
+
+%D \macros
+%D {truefilename}
+%D
+%D At the system level such a filename can be called upon by
+%D saying:
+%D
+%D \starttyping
+%D \truefilename{filename/filesynonym}
+%D \stoptyping
+%D
+%D The implementation shows that nesting is supported.
+
+\def\truefilename#1%
+ {\ifundefined{\??fs#1}#1\else\truefilename{\csname\??fs#1\endcsname}\fi}
+
+%D \macros
+%D {makeshortfilename}
+%D
+%D To prevent cross platform problems with filenames, we
+%D lowercase them as well as only use the first 8~characters.
+%D
+%D \starttyping
+%D \def\domakeshortfilename[#1#2#3#4#5#6#7#8#9]%
+%D {\lowercase{\edef\shortfilename{#1#2#3#4#5#6#7#8.}}%
+%D \expandafter\beforesplitstring\shortfilename\at.\to\shortfilename}
+%D
+%D \def\makeshortfilename[#1]%
+%D {\edef\fullfilename{#1.........}%
+%D \expanded{\domakeshortfilename[\fullfilename]}}
+%D \stoptyping
+%D
+%D In 2005 there is no need for the 8~character limit any more, so:
+
+\def\makeshortfilename[#1]% no need for further cleanup and shortening
+ {\lowercase{\edef\shortfilename{#1.}}%
+ \expandafter\beforesplitstring\shortfilename\at.\to\shortfilename}
+
+%D \macros
+%D {usemodule}
+%D
+%D Most of \CONTEXT is preloaded in the format file. Some very
+%D domain specific typesetting topics are however dealt with in
+%D separate modules, e.g. typesetting of chemical structure
+%D formulas. These modules are loaded by:
+%D
+%D \showsetup{usemodule}
+%D
+%D More information on the specific modules can be found in
+%D their dedicated manuals. We use \type {\next} so that we
+%D can \type {\end} in modules.
+
+\newconditional\moduleisloaded
+
+\def\dododousemodules#1#2% no \unprotect/\protect when loading,
+ {\relax % since we need to use ? ! unprotected
+ \ifconditional\moduleisloaded % sometimes (see xtag-map)
+ \let\next\relax % or: \expandafter\gobbleoneargument
+ \else
+ \makeshortfilename[#1\truefilename{#2}]% beware: *- is not part of syn
+ \doifelseflagged\shortfilename
+ {\showmessage\m!systems7{#2 (line \number\inputlineno)}%
+ \settrue\moduleisloaded
+ \let\next\relax}
+ {\doglobal\setflag\shortfilename
+ \def\next
+ {\startreadingfile
+ \readsysfile\shortfilename
+ {\showmessage\m!systems5{#2}\settrue\moduleisloaded}
+ {\readsysfile{\shortfilename.\mksuffix} % new
+ {\showmessage\m!systems5{#2 (\mksuffix)}\settrue\moduleisloaded}
+ \donothing}%
+ \stopreadingfile}}%
+ \fi
+ \next}
+
+\def\dodousemodules#1#2%
+ {\setfalse\moduleisloaded
+ \doifelsenothing{#1}
+ {\dododousemodules\f!moduleprefix {#2}%
+ \dododousemodules\f!privateprefix{#2}%
+ \dododousemodules\f!styleprefix {#2}%
+ \dododousemodules\f!xstyleprefix {#2}%
+ \dododousemodules\f!thirdprefix {#2}%
+ \dododousemodules\empty {#2}}% new, fall back on raw name
+ {\dododousemodules{#1-}{#2}}%
+ \ifconditional\moduleisloaded\else
+ \showmessage\m!systems6{#2}%
+ \appendtoks\showmessage\m!systems6{#2}\to\everynotabene
+ \fi}
+
+% \def\usemodules
+% {\dodoubleempty\dousemodules}
+%
+% \def\dousemodules[#1][#2]%
+% {\ifsecondargument
+% \doifelsenothing{#2}
+% {\let\next\relax}
+% {\def\next{\processcommalist[#2]{\dodousemodules{#1}}}}%
+% \else
+% \def\next{\usemodules[][#1]}%
+% \fi
+% \next}
+%
+% \let\usemodule\usemodules
+
+\def\usemodules
+ {\dotripleempty\dousemodules}
+
+\def\dousemodules[#1][#2][#3]%
+ {\pushmacro\currentmodule
+ \pushmacro\currentmoduleparameters
+ \let\currentmoduleparameters\empty
+ \ifthirdargument
+ \doifelsenothing{#2}
+ {\let\next\relax}
+ {\def\currentmoduleparameters{#3}%
+ \def\next{\processcommalist[#2]{\dodousemodules{#1}}}}%
+ \else\ifsecondargument
+ \doifelsenothing{#2}
+ {\let\next\relax}
+ {\doifassignmentelse{#2}
+ {\def\currentmoduleparameters{#2}%
+ \def\next{\processcommalist[#1]{\dodousemodules{}}}}
+ {\def\next{\processcommalist[#2]{\dodousemodules{#1}}}}}%
+ \else
+ \def\next{\processcommalist[#1]{\dodousemodules{}}}%
+ \fi\fi
+ \next
+ \popmacro\currentmoduleparameters
+ \popmacro\currentmodule}
+
+\let\currentmoduleparameters\empty
+\let\currentmodule \s!unknown
+
+\def\startmodule
+ {\doifnextoptionalelse\dostartmodule\nostartmodule}
+
+\def\nostartmodule #1 %
+ {\dostartmodule[#1]}
+
+\def\dostartmodule[#1]%
+ {\pushmacro\currentmodule
+ \pushmacro\currentmoduleparameters
+ \def\currentmodule{#1}}
+
+\def\stopmodule
+ {\popmacro\currentmoduleparameters
+ \popmacro\currentmodule}
+
+\def\setupmodule
+ {\dodoubleempty\dosetupmodule}
+
+\def\dosetupmodule[#1][#2]%
+ {\scratchtoks\expandafter{\currentmoduleparameters}%
+ \ifsecondargument
+ \getparameters[\??md:#1:][#2]%
+ \expanded{\getparameters[\??md:#1:][\the\scratchtoks]}%
+ \else
+ \getparameters[\??md:\currentmodule:][#1]%
+ \expanded{\getparameters[\??md:\currentmodule:][\the\scratchtoks]}%
+ \fi
+ \let\currentmoduleparameters\empty}
+
+\def\moduleparameter #1#2{\executeifdefined{\??md:#1:#2}\s!empty}
+\def\currentmoduleparameter#1{\executeifdefined{\??md:\currentmodule:#1}\s!empty}
+
+% \usemodule[newmml]
+% \usemodule[newmml][a=b]
+% \usemodule[x][newmml]
+% \usemodule[x][newmml][a=b]
+%
+% \startmodule [mathml]
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars will be set afterwards
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars are now forgotten
+% \stopmodule
+
+% one can introduce test sections with:
+%
+% \enablemode[newmml:test:\currentmoduleparameter{test}]
+% \startmode[newmml:test:yes} ... \stopmode
+%
+% these will be ignored unless test=yes
+%
+% however, a better way is:
+
+\let\stopmoduletestsection\donothing
+
+\def\startmoduletestsection
+ {\bgroup
+ \setupmodule % we need to make sure that the vars are set
+ \doifelse{\currentmoduleparameter\v!test}\v!yes
+ {\egroup
+ \writestatus{\currentmodule}{loading experimental code}}
+ {\egroup
+ \writestatus{\currentmodule}{skipping experimental code}%
+ \gobbleuntil\stopmoduletestsection}}
+
+%D We also support a singular call, which saves us for
+%D frustrations when we do a typo.
+
+\let\usemodule=\usemodules
+
+% %D The definition shows that the language specific settings
+% %D are activated after loading all the modules specified.
+
+%D \macros
+%D {ifprotectbuffers, bufferprefix,
+%D TEXbufferfile, MPgraphicfile}
+%D
+%D The next switch enables protection of temporary filenames,
+%D which is needed when we process more files on one path at
+%D the same time.
+
+\newif\ifprotectbuffers
+
+\def\bufferprefix{\ifprotectbuffers\jobname-\fi}
+
+% The following filenames are defined here:
+
+\def\TEXbufferfile #1{\bufferprefix#1.\f!temporaryextension}
+\def\MPgraphicfile {\bufferprefix mp\ifMPrun run\else graph\fi} % not needed in luatex
+\def\convertMPcolorfile{\bufferprefix metacmyk.tmp}
+
+%D To save memory, we implement some seldomly used commands
+%D in a lazy way. Nota bene: such runtime definitions are
+%D global.
+%D
+%D \starttyping
+%D \fetchruntimecommand\showaccents{\f!encodingprefix ...}
+%D \stoptyping
+
+\def\fetchruntimecommand#1#2%
+ {\def#1{\dofetchruntimecommand#1{#2}}}
+
+\def\dofetchruntimecommand#1#2%
+ {\doifnotflagged{#2}
+ {\let#1\undefined
+ \startreadingfile
+ \startnointerference % \bgroup
+ \cleanupfeatures % better \setnormalcatcodes / test first
+ \readfile{#2}\donothing\donothing
+ \stopnointerference % \egroup
+ \stopreadingfile
+ \doglobal\setflag{#2}}%
+ \ifx#1\undefined
+ \writestatus\m!systems{command \string#1 not found in file #2}%
+ \def#1{{\infofont[unknown command \string#1]}}%
+ \fi
+ #1}
+
+%D Experimental:
+
+\let\checkpreprocessor\relax
+
+%D To be documented and probably moved
+
+\def\documentresources{\@@erurl}
+
+\def\setupexternalresources
+ {\dodoubleargument\getparameters[\??er]}
+
+\setupexternalresources
+ [url=]
+
+%D This module will be perfected / changed / weeded.
+
+\protect \endinput
diff --git a/tex/context/base/core-fil.mkiv b/tex/context/base/core-fil.mkiv
new file mode 100644
index 000000000..daef176d2
--- /dev/null
+++ b/tex/context/base/core-fil.mkiv
@@ -0,0 +1,284 @@
+%D \module
+%D [ file=core-fil,
+%D version=1997.11.15,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=File Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / File Support}
+
+\unprotect
+
+%D \macros
+%D {definefilesynonym}
+%D
+%D One of the problems with loading files is that their names
+%D can depend on the interface language. We therefore need a
+%D method to define filesynonyms. The actual synonyms are
+%D defined elsewhere, but look like:
+%D
+%D \starttyping
+%D \definefilesynonym [chemic] [chemie]
+%D \definefilesynonym [einheit] [unit]
+%D \definefilesynonym [unit] [unit]
+%D \stoptyping
+%D
+%D So we can say in english:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemic,unit]
+%D \stoptyping
+%D
+%D and in dutch:
+%D
+%D \starttyping
+%D \usemodules[pictex,chemie,unit]
+%D \stoptyping
+
+% will be redone in mkiv
+
+\unexpanded\def\definefilesynonym
+ {\dodoubleempty\dodefinefilesynonym}
+
+\def\dodefinefilesynonym[#1][#2]%
+ {\ifcsname\??fs#1\endcsname
+ \doifnotvalue{\??fs#1}{#2}{\showmessage\m!files1{#1 (#2),\getvalue{\??fs#1}}}%
+ \fi
+ \doifelse{#1}{#2}{\letbeundefined{\??fs#1}{#2}}{\setevalue{\??fs#1}{#2}}}
+
+%D \macros
+%D {definefilefallback}
+
+\unexpanded\def\definefilefallback
+ {\dodoubleargument\dodefinefilefallback}
+
+\def\dodefinefilefallback[#1][#2]%
+ {\doifnotfile{#1}
+ {\def\docommand##1{\doiffile{##1}{\definefilesynonym[#1][##1]\quitcommalist}}%
+ \processcommalist[#2]\docommand}}
+
+%D \macros
+%D {truefilename}
+%D
+%D At the system level such a filename can be called upon by
+%D saying:
+%D
+%D \starttyping
+%D \truefilename{filename/filesynonym}
+%D \stoptyping
+%D
+%D The implementation shows that nesting is supported.
+
+\def\truefilename#1%
+ {\ifcsname\??fs#1\endcsname\expandafter\truefilename\csname\??fs#1\endcsname\else#1\fi}
+
+%D \macros
+%D {makeshortfilename}
+%D
+%D To prevent cross platform problems with filenames, we
+%D lowercase them as well as only use the first 8~characters.
+%D
+%D \starttyping
+%D \def\domakeshortfilename[#1#2#3#4#5#6#7#8#9]%
+%D {\lowercase{\edef\shortfilename{#1#2#3#4#5#6#7#8.}}%
+%D \expandafter\beforesplitstring\shortfilename\at.\to\shortfilename}
+%D
+%D \def\makeshortfilename[#1]%
+%D {\edef\fullfilename{#1.........}%
+%D \expanded{\domakeshortfilename[\fullfilename]}}
+%D \stoptyping
+%D
+%D In 2005 there is no need for the 8~character limit any more, so:
+
+\def\makeshortfilename[#1]% no need for further cleanup and shortening
+ {\lowercase{\edef\shortfilename{#1.}}%
+ \expandafter\beforesplitstring\shortfilename\at.\to\shortfilename}
+
+%D \macros
+%D {usemodule}
+%D
+%D Most of \CONTEXT is preloaded in the format file. Some very
+%D domain specific typesetting topics are however dealt with in
+%D separate modules, e.g. typesetting of chemical structure
+%D formulas. These modules are loaded by:
+%D
+%D \showsetup{usemodule}
+%D
+%D More information on the specific modules can be found in
+%D their dedicated manuals. We use \type {\next} so that we
+%D can \type {\end} in modules.
+
+\def\dodousemodules#1#2%
+ {\ctxlua{support.usemodules("#1","#2","\truefilename{#2}")}}
+
+\def\usemodules
+ {\dotripleempty\dousemodules}
+
+\def\dousemodules[#1][#2][#3]%
+ {\pushmacro\currentmodule
+ \pushmacro\currentmoduleparameters
+ \let\currentmoduleparameters\empty
+ \ifthirdargument
+ \doifelsenothing{#2}
+ {\let\next\relax}
+ {\def\currentmoduleparameters{#3}%
+ \def\next{\processcommalist[#2]{\dodousemodules{#1}}}}%
+ \else\ifsecondargument
+ \doifelsenothing{#2}
+ {\let\next\relax}
+ {\doifassignmentelse{#2}
+ {\def\currentmoduleparameters{#2}%
+ \def\next{\processcommalist[#1]{\dodousemodules{}}}}
+ {\def\next{\processcommalist[#2]{\dodousemodules{#1}}}}}%
+ \else
+ \def\next{\processcommalist[#1]{\dodousemodules{}}}%
+ \fi\fi
+ \next
+ \popmacro\currentmoduleparameters
+ \popmacro\currentmodule}
+
+\let\currentmoduleparameters\empty
+\let\currentmodule \s!unknown
+
+\unexpanded\def\startmodule
+ {\doifnextoptionalelse\dostartmodule\nostartmodule}
+
+\def\nostartmodule #1 %
+ {\dostartmodule[#1]}
+
+\def\dostartmodule[#1]%
+ {\pushmacro\currentmodule
+ \pushmacro\currentmoduleparameters
+ \def\currentmodule{#1}}
+
+\unexpanded\def\stopmodule
+ {\popmacro\currentmoduleparameters
+ \popmacro\currentmodule}
+
+\unexpanded\def\setupmodule
+ {\dodoubleempty\dosetupmodule}
+
+\def\dosetupmodule[#1][#2]%
+ {\scratchtoks\expandafter{\currentmoduleparameters}%
+ \ifsecondargument
+ \getparameters[\??md:#1:][#2]%
+ \expanded{\getparameters[\??md:#1:][\the\scratchtoks]}%
+ \else
+ \getparameters[\??md:\currentmodule:][#1]%
+ \expanded{\getparameters[\??md:\currentmodule:][\the\scratchtoks]}%
+ \fi
+ \let\currentmoduleparameters\empty}
+
+\def\moduleparameter #1#2{\executeifdefined{\??md:#1:#2}\s!empty}
+\def\currentmoduleparameter#1{\executeifdefined{\??md:\currentmodule:#1}\s!empty}
+
+\def\useluamodule [#1]{\ctxlua{dofile(resolvers.findctxfile("#1"))}}
+\def\luaenvironment #1 {\ctxlua{dofile(resolvers.findctxfile("#1"))}}
+
+% \usemodule[newmml]
+% \usemodule[newmml][a=b]
+% \usemodule[x][newmml]
+% \usemodule[x][newmml][a=b]
+%
+% \startmodule [mathml]
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars will be set afterwards
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars are now forgotten
+% \stopmodule
+
+% one can introduce test sections with:
+%
+% \enablemode[newmml:test:\currentmoduleparameter{test}]
+% \startmode[newmml:test:yes} ... \stopmode
+%
+% these will be ignored unless test=yes
+%
+% however, a better way is:
+
+\let\stopmoduletestsection\donothing
+
+\unexpanded\def\startmoduletestsection
+ {\bgroup
+ \setupmodule % we need to make sure that the vars are set
+ \doifelse{\currentmoduleparameter\v!test}\v!yes
+ {\egroup
+ \writestatus{\currentmodule}{loading experimental code}}
+ {\egroup
+ \writestatus{\currentmodule}{skipping experimental code}%
+ \gobbleuntil\stopmoduletestsection}}
+
+%D We also support a singular call, which saves us for
+%D frustrations when we do a typo.
+
+\let\usemodule=\usemodules
+
+% %D The definition shows that the language specific settings
+% %D are activated after loading all the modules specified.
+
+%D \macros
+%D {ifprotectbuffers, bufferprefix,
+%D TEXbufferfile, MPgraphicfile}
+%D
+%D The next switch enables protection of temporary filenames,
+%D which is needed when we process more files on one path at
+%D the same time.
+
+\newif\ifprotectbuffers
+
+\def\bufferprefix{\ifprotectbuffers\jobname-\fi}
+
+% The following filenames are defined here:
+
+\def\TEXbufferfile #1{\bufferprefix#1.\f!temporaryextension}
+\def\MPgraphicfile {\bufferprefix mp\ifMPrun run\else graph\fi} % not needed in luatex
+\def\convertMPcolorfile{\bufferprefix metacmyk.tmp}
+
+%D To save memory, we implement some seldomly used commands
+%D in a lazy way. Nota bene: such runtime definitions are
+%D global.
+%D
+%D \starttyping
+%D \fetchruntimecommand\showaccents{\f!encodingprefix ...}
+%D \stoptyping
+
+\def\fetchruntimecommand#1#2%
+ {\def#1{\dofetchruntimecommand#1{#2}}}
+
+\def\dofetchruntimecommand#1#2%
+ {\doifnotflagged{#2}
+ {\let#1\undefined
+ \startreadingfile
+ \startnointerference % \bgroup
+ \cleanupfeatures % better \setnormalcatcodes / test first
+ \readfile{#2}\donothing\donothing
+ \stopnointerference % \egroup
+ \stopreadingfile
+ \doglobal\setflag{#2}}%
+ \ifx#1\undefined
+ \writestatus\m!systems{command \string#1 not found in file #2}%
+ \def#1{{\infofont[unknown command \string#1]}}%
+ \fi
+ #1}
+
+%D Experimental:
+
+\let\checkpreprocessor\relax
+
+%D To be documented and probably moved
+
+\def\documentresources{\@@erurl}
+
+\unexpanded\def\setupexternalresources
+ {\dodoubleargument\getparameters[\??er]}
+
+\setupexternalresources
+ [url=]
+
+%D This module will be perfected / changed / weeded.
+
+\protect \endinput
diff --git a/tex/context/base/core-fnt.mkii b/tex/context/base/core-fnt.mkii
new file mode 100644
index 000000000..9bc2a66f5
--- /dev/null
+++ b/tex/context/base/core-fnt.mkii
@@ -0,0 +1,726 @@
+%D \module
+%D [ file=core-fnt,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Fonts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Fonts}
+
+\unprotect
+
+%D \macros
+%D {compound}
+%D
+%D We will overload the already active \type {|} so we have
+%D to save its meaning in order to be able to use this handy
+%D macro.
+%D
+%D \starttyping
+%D so test\compound{}test can be used instead of test||test
+%D \stoptyping
+
+\bgroup \catcode`\|=\@@active \gdef\compound#1{|#1|} \egroup
+
+%D Here we hook some code into the clean up mechanism needed
+%D for verbatim data.
+
+\appendtoks
+ \disablecompoundcharacters
+ \disablediscretionaries
+\to \everycleanupfeatures
+
+%D \macros
+%D {kap,KAP,Kap,Kaps,nokap,userealcaps,usepseudocaps}
+%D
+%D We already introduced \type{\cap} as way to capitalize
+%D words. This command comes in several versions:
+%D
+%D \startbuffer
+%D \cap {let's put on a \cap{cap}}
+%D \cap {let's put on a \nocap{cap}}
+%D \CAP {let's put on a \\{cap}}
+%D \Cap {let's put on a \\{cap}}
+%D \Caps{let's put on a cap}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Note the use of \type{\nocap}, \type{\\} and the nested
+%D \type{\cap}.
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D These macros show te main reason why we introduced the
+%D smaller \type{\tx} and \type{\txx}.
+%D
+%D \starttyping
+%D \cap\romannumerals{1995}
+%D \stoptyping
+%D
+%D This at first sight unusual capitilization is completely
+%D legal.
+%D
+%D \showsetup{smallcapped}
+%D \showsetup{notsmallcapped}
+%D \showsetup{CAPPED}
+%D \showsetup{SmallCapped}
+%D \showsetup{SmallCaps}
+%D
+%D The difference between pseudo and real caps is demonstrated
+%D below:
+%D
+%D \startbuffer
+%D \usepseudocaps \cap{Hans Hagen}
+%D \userealcaps \cap{Hans Hagen}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D The \type {\bgroup} trickery below is needed because of
+%D \type {\groupedcommand}.
+
+\def\usepseudocaps
+ {\def\cap@@uppercase{\the\everyuppercase\uppercased}%
+ \def\cap@@lowercase{\the\everylowercase\lowercased}%
+ \def\cap@@visualize{\tx}}
+
+\def\userealcaps
+ {\let\cap@@uppercase\relax
+ %\let\cap@@lowercase\relax % Definitely not!
+ \def\cap@@visualize{\sc}}
+
+\usepseudocaps
+
+\unexpanded\def\smallcapped % else conflict with math
+ {\futurelet\next\dosmallcapped}
+
+\def\disablepseudocaps
+ {\let\smallcapped\donothing}
+
+\def\dosmallcapped
+ {\ifx\next\bgroup
+ \expandafter\dodosmallcapped\expandafter\relax
+ \else
+ \expandafter\dodosmallcapped
+ \fi}
+
+\def\dodosmallcapped#1#2%
+ {\ifmmode\hbox\fi
+ \bgroup
+ \cap@@visualize
+ \cap@@uppercase{#1{#2}}%
+ \egroup}
+
+\unexpanded\def\notsmallcapped#1%
+ {\cap@@lowercase{#1}}
+
+\unexpanded\def\CAPPED#1%
+ {{\def\\##1{\smallcapped{##1}}#1}}
+
+\unexpanded\def\SmallCapped#1%
+ {\CAPPED{\\#1}}
+
+\unexpanded\def\SmallCaps
+ {\let\processword\SmallCapped
+ \processwords}
+
+%D Sure:
+
+\def\kap{\smallcapped} % for old times sake
+
+%D Some precautions for a \PLAIN\ \TEX\ definition.
+
+\unexpanded\def\normalcap{\dohandlemathtoken{cap}}
+\unexpanded\def\normalCap{\dohandlemathtoken{Cap}}
+
+\def\cap{\mathortext\normalcap\smallcapped}
+\def\Cap{\mathortext\normalCap\SmallCapped}
+
+\appendtoks
+ \let\cap\firstofoneargument
+ \let\Cap\firstofoneargument
+\to \simplifiedcommands
+
+%D \macros
+%D {setupcapitals}
+%D
+%D By default we use pseudo small caps in titles. This can be
+%D set up with:
+%D
+%D \showsetup{setupcapitals}
+
+\let\normalsmallcapped\smallcapped
+
+\def\setupcapitals
+ {\dosingleempty\dosetupcapitals}
+
+\def\dosetupcapitals[#1]%
+ {\getparameters[\??kk][#1]%
+ \doifelse\@@kktitle\v!yes
+ {\definealternativestyle[\v!capital][\normalsmallcapped][\normalsmallcapped]%
+ \definealternativestyle[\v!smallcaps][\sc][\sc]%
+ \unexpanded\def\smallcapped{\normalsmallcapped}}
+ {\definealternativestyle[\v!capital][\normalsmallcapped][\uppercased]%
+ \definealternativestyle[\v!smallcaps][\sc][\uppercased]%
+ \unexpanded\def\smallcapped{\doconvertfont\v!capital}}%
+ \doifelse\@@kksc\v!yes
+ \userealcaps
+ \usepseudocaps}
+
+\ifx\uppercased\undefined \let\uppercased\uppercase \fi
+\ifx\lowercased\undefined \let\lowercased\lowercase \fi
+
+% pretty tricky stuff:
+%
+% \usemodule[abr-01] \TEX \METAPOST \PPCHTEX \LATEX
+% \usemodule[abr-02] \TEX \METAPOST \PPCHTEX \LATEX
+
+%def\uppercased#1{{\forceunexpanded\xdef\@@globalcrap{\uppercase{#1}}}\@@globalcrap}
+%def\lowercased#1{{\forceunexpanded\xdef\@@globalcrap{\lowercase{#1}}}\@@globalcrap}
+
+\def\uppercased#1{{\forceunexpanded\xdef\@@expanded{\uppercase{#1}}}\@@expanded}
+\def\lowercased#1{{\forceunexpanded\xdef\@@expanded{\lowercase{#1}}}\@@expanded}
+
+\setupcapitals
+ [\c!title=\v!yes,
+ \c!sc=\v!no]
+
+%D \macros
+%D {Word, Words, WORD, WORDS, doprocesswords}
+%D
+%D This is probably not the right place to present the next set
+%D of macros.
+%D
+%D \starttyping
+%D \Word {far too many words}
+%D \Words{far too many words}
+%D \WORD {far too many words}
+%D \WORDS{far too many words}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D This calls result in:
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D \showsetup{Word}
+%D \showsetup{Words}
+%D \showsetup{WORD}
+%D \showsetup{WORDS}
+
+\def\doWord#1%
+ {\bgroup
+ \the\everyuppercase
+ \uppercase{#1}%
+ \egroup}
+
+\unexpanded\def\Word#1%
+ {\doWord#1}
+
+\def\doprocesswords#1 #2\od
+ {\ConvertToConstant\doifnot{#1}{}
+ {\processword{#1} %
+ \doprocesswords#2 \od}}
+
+\def\processwords#1%
+ {\doprocesswords#1 \od\unskip}
+
+\let\processword\relax
+
+\unexpanded\def\Words
+ {\let\processword\Word
+ \processwords}
+
+\unexpanded\def\WORD#1%
+ {\bgroup
+ \let\smallcapped\firstofoneargument
+ \let\WORD\firstofoneargument
+ \douppercase{#1}%
+ \egroup}
+
+\unexpanded\def\WORDS#1%
+ {\WORD{#1}}
+
+%D \macros
+%D {stretched}
+%D
+%D Stretching characters in a word is a sort of typographical
+%D murder. Nevertheless we support this manipulation for use in
+%D for instance titles.
+%D
+%D \starttyping
+%D \hbox to 5cm{\stretched{murder}}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D \showsetup{stretched}
+
+\def\stretched#1%
+ {\ifvmode\hbox to \hsize\else\ifinner\else\hbox\fi\fi
+ \bgroup\processtokens\relax\hss\relax{\hss\hss}{#1}\egroup}
+
+%D \startbuffer
+%D \stretched{Unknown Box}
+%D \hbox to .5\hsize{\stretched{A Horizontal Box}}
+%D \vbox to 2cm{\stretched{A Vertical Box}}
+%D \hbox to 3cm{\stretched{sp{\'e}c{\`\i}{\"a}l}}
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D The first line of this macros takes care of boxing. Normally
+%D one will use an \type{\hbox} specification. The last line
+%D shows how special characters should be passed.
+%D
+%D \typebuffer
+
+%D \macros
+%D {stretchednormalcase, stretcheduppercase, stretchedlowercase}
+%D
+%D A convenient alternative is:
+%D
+%D \starttyping
+%D \stretcheduppercase{Is this what you like?}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D this one uses fixed skips and kerns.
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D The default skip can be set with:
+
+% \def\stretchedspacefactor{4}
+% \def\stretchedspaceamount{.25em}
+%
+% \unexpanded\def\stretcheduppercase#1%
+% {\bgroup
+% \the\everyuppercase
+% \uppercase{\def\textstring{#1}}%
+% \ifdim\stretchedspaceamount>\zeropoint
+% \def\textkern%
+% {\kern\stretchedspaceamount}%
+% \def\textskip%
+% {\scratchdimen=\stretchedspaceamount
+% \hskip\stretchedspacefactor\scratchdimen}%
+% \@EA\processtokens\@EA\relax\@EA\textkern\@EA\relax\@EA
+% \textskip\@EA{\textstring}%
+% \else
+% \textstring
+% \fi
+% \egroup}
+
+%D Given the following settings, the space is 1em by default:
+
+\def\stretchedspacefactor{4}
+\def\stretchedspaceamount{.25em}
+\def\stretchedbreaktokens{.@/}
+
+\unexpanded\def\stretchednormalcase
+ {\stretchedsomecase\firstofoneargument}
+
+\unexpanded\def\stretcheduppercase
+ {\stretchedsomecase{\the\everyuppercase\uppercase}}
+
+\unexpanded\def\stretchedlowercase
+ {\stretchedsomecase{\the\everylowercase\lowercase}}
+
+\def\stretchedsomecase#1#2%
+ {\bgroup
+ #1{\def\textstring{#2}}%
+ \ifdim\stretchedspaceamount=\zeropoint
+ \textstring
+ \else
+ \def\textkern##1%
+ {% beware: ##1 may not be \box\somebox -)
+ \determinemidwordbreak{##1}{\stretchedbreaktokens}%
+ \kern\stretchedspaceamount##1\domidwordbreak}%
+ \def\textskip
+ {\scratchdimen\stretchedspaceamount
+ \hskip\stretchedspacefactor\scratchdimen}%
+ \@EA\processtokens\@EA\relax\@EA\textkern\@EA\relax\@EA
+ \textskip\@EA{\textstring}%
+ \fi
+ \egroup}
+
+%D An auxiliary macro, see for usage \type {\stretcheduppercase}.
+
+\let\domidwordbreak\relax
+
+\def\setmidwordbreaktoken#1%
+ {\sfcode`#1=5000\relax}
+
+\def\determinemidwordbreak#1#2%
+ {\edef\midwordbreaktokens{#2}%
+ \ifx\midwordbreaktokens\empty
+ \global\let\domidwordbreak\relax
+ \else
+ \setbox\scratchbox\hbox
+ {\expandafter\handletokens\midwordbreaktokens\with\setmidwordbreaktoken
+ a\space \!!dimena\lastskip
+ #1\space\!!dimenb\lastskip \relax % needed
+ \ifdim\!!dimena=\!!dimenb
+ \globallet\domidwordbreak\relax
+ \else
+ \globallet\domidwordbreak\allowbreak
+ \fi}%
+ \fi}
+
+%D \macros
+%D {underbar,underbars,
+%D overbar,overbars,
+%D overstrike,overstrikes,
+%D setupunderbar}
+%D
+%D In the rare case that we need undelined words, for instance
+%D because all font alternatives are already in use, one can
+%D use \type{\underbar} and \type{\overstrike} and their plural
+%D forms.
+%D
+%D \startbuffer
+%D \underbars{drawing \underbar{bars} under words is a typewriter leftover}
+%D \overstrikes{striking words makes them \overstrike{unreadable} but
+%D sometimes even \overbar{top lines} come into view.}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D The next macros are derived from the \PLAIN\ \TEX\ one, but
+%D also supports nesting. The \type{$} keeps us in horizontal
+%D mode and at the same time applies grouping.
+%D
+%D \showsetup{underbar}
+%D \showsetup{underbars}
+%D \showsetup{overbar}
+%D \showsetup{overbars}
+%D \showsetup{overstrike}
+%D \showsetup{overstrikes}
+%D
+%D Although underlining is ill advised, we permit some
+%D alternatives, that can be set up by:
+%D
+%D \showsetup{setupunderbar}
+%D
+%D The alternatives show up as
+%D {\setupunderbar [alternative=a]\underbar{alternative a}},
+%D {\setupunderbar [alternative=b]\underbar{alternative b}},
+%D {\setupunderbar [alternative=c]\underbar{alternative c}}
+%D and
+%D {\setupunderbar [rulethickness=1pt]\underbar{1pt width}},
+%D {\setupunderbar [rulethickness=2pt]\underbar{2pt width}},
+%D or whatever. Because \type{\overstrike} uses the same
+%D method, the settings also apply to that macro.
+
+\newcount\underbarlevel
+
+\def\underbarmethoda#1#2#3% RULE
+ {\hbox to #1{\vrule\!!width#1\!!height#2\!!depth#3}}
+
+\def\underbarmethodb#1#2#3% DASH
+ {\hbox to #1
+ {\hskip-.25em
+ \xleaders
+ \hbox{\hskip.25em\vrule\!!width.25em\!!height#2\!!depth#3}
+ \hfil}}
+
+\def\underbarmethodc#1#2#3% PERIOD
+ {\hbox to #1
+ {\dimen4=#3
+ \advance\dimen4 .2ex
+ \hskip-.25em
+ \xleaders
+ \hbox{\hskip.25em\lower\dimen4\hbox{.}}
+ \hfil}}
+
+\def\dododounderbar#1#2#3%
+ {\startmathmode
+ \setbox0\hbox{#3}%
+ \setbox2\hbox{\color[\@@onrulecolor]{\getvalue{underbarmethod\@@onalternative}{\wd0}{#1}{#2}}}%
+ \wd0\zeropoint
+ \ht2\ht0
+ \dp2\dp0
+ \box0\box2
+ \stopmathmode}
+
+\unexpanded\def\dodounderbar#1%
+ {\bgroup
+ \dimen0=\@@onbottomoffset
+ \dimen0=\underbarlevel\dimen0
+ \ifdone \else
+ \advance\dimen0 -\strutht
+ \fi
+ \dimen2\dimen0
+ \advance\dimen2 \@@onrulethickness
+ \dododounderbar{-\dimen0}{\dimen2}{#1}%
+ \egroup}
+
+\def\betweenunderbarwords
+ {\bgroup
+ \setbox0\hbox{\dodounderbar{\hskip\interwordspace}}%
+ \nobreak
+ \hskip\zeropoint\!!minus\interwordshrink
+ \discretionary{}{}{\box0}%
+ \egroup}
+
+\def\betweenunderbarspaces
+ {\hskip\currentspaceskip}
+
+% \unexpanded\def\dounderbar#1#2%
+% {\let\betweenisolatedwords#1%
+% \processisolatedwords{#2}\dodounderbar
+% \egroup}
+
+\unexpanded\def\underbar
+ {\bgroup
+ \advance\underbarlevel\plusone
+ \donetrue
+ \dounderbar\betweenunderbarwords}
+
+\unexpanded\def\dounderbar#1%
+ {\let\betweenisolatedwords#1%
+ \dosingleempty\redounderbar}
+
+\unexpanded\def\redounderbar[#1]#2%
+ {\iffirstargument\setupunderbar[#1]\fi
+ \processisolatedwords{#2}\dodounderbar
+ \egroup}
+
+\unexpanded\def\underbars
+ {\bgroup
+ \advance\underbarlevel\plusone
+ \donetrue
+ \dounderbar\betweenunderbarspaces}
+
+\unexpanded\def\overbar
+ {\bgroup
+ \advance\underbarlevel\minusone
+ \donefalse
+ \dounderbar\betweenunderbarwords}
+
+\unexpanded\def\overbars
+ {\bgroup
+ \advance\underbarlevel\minusone
+ \donefalse
+ \dounderbar\betweenunderbarspaces}
+
+\def\dooverstrike#1%
+ {\bgroup
+ \dimen0=\@@ontopoffset
+ \dimen2=\dimen0
+ \advance\dimen2 \@@onrulethickness
+ \dododounderbar{\dimen2}{-\dimen0}{#1}%
+ \egroup}
+
+\def\betweenoverstrikewords
+ {\bgroup
+ \setbox0\hbox{\dooverstrike{\hskip\interwordspace}}%
+ \nobreak
+ \hskip\zeropoint\!!minus\interwordshrink
+ \discretionary{}{}{\box0}%
+ \egroup}
+
+\unexpanded\def\overstrike#1%
+ {\bgroup
+ \let\betweenisolatedwords\betweenoverstrikewords
+ \processisolatedwords{#1}\dooverstrike
+ \egroup}
+
+\unexpanded\def\overstrikes#1%
+ {\bgroup
+ \processisolatedwords{#1}\dooverstrike
+ \egroup}
+
+\def\underbarparameter#1{\csname\??on#1\csname}
+
+\def\setupunderbar
+ {\dodoubleargument\getparameters[\??on]}
+
+%D \macros
+%D {shiftedword, shiftedwords}
+%D
+%D Used as \type {\shiftedwords {10pt} {some text}} this macro will
+%D move
+
+% \def\shiftedword#1% #2%
+% {\raise#1\hbox} % {#2}} % officially: {\ifdim#1>\zeropoint\raise\else\lower\fi#1\hbox{#2}}
+
+% \def\shiftedwords#1#2%
+% {\processisolatedwords{#2}{\shiftedword{#1}}}
+
+%D \macros
+%D {low, high, lohi}
+%D
+%D Although \TEX\ is pretty well aware of super- and
+%D subscripts, its mechanism is mainly tuned for math mode.
+%D The next few commands take care of script texts both modes.
+%D
+%D \startbuffer
+%D The higher\high{one goes} the lower\low{one drops}, or\lohi{yes}{no}?
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D Note the different placement of \type {\lohi}, where we
+%D need a bit more space. The implementation looks a bit
+%D fuzzy, since some \type {\fontdimen}'s are involved to
+%D determine the optimal placement.
+
+\def\dodohighlow
+ {\ifx\fontsize\empty
+ \ifmmode
+ \ifnum\fam<0 \tx \else \holamathfont \fi
+ \else
+ \tx
+ \fi
+ \else
+ \tx
+ \fi}
+
+\def\dohighlow#1#2#3#4#5% todo, named fontdimens
+ {\dontleavehmode
+ \bgroup
+ \scratchdimen\ifdim\fontexheight\textfont2=1ex #2\textfont2\else #3ex\fi
+ \advance\scratchdimen #4ex
+ \kern.1ex
+ \setbox\scratchbox\hbox{#1\scratchdimen\hbox{\dodohighlow#5}}%
+ \ht\scratchbox\strutheight
+ \dp\scratchbox\strutdepth
+ \box\scratchbox
+ \egroup}
+
+\unexpanded\def\high{\dohighlow\raise\mathsupnormal{.86}{0}}
+\unexpanded\def\low {\dohighlow\lower\mathsubnormal{.48}{0}}
+
+% \unexpanded\def\lohi#1#2%
+% {\dontleavehmode
+% \hbox
+% {\setbox4=\hbox{\dohighlow\lower\mathsubnormal{.48}{.1}{#1}}%
+% \setbox6=\hbox{\dohighlow\raise\mathsupnormal{.86}{.1}{#2}}%
+% \ifdim\wd4<\wd6
+% \wd4=\zeropoint\box4\box6
+% \else
+% \wd6=\zeropoint\box6\box4
+% \fi}}
+
+\unexpanded\def\lohi
+ {\dosingleempty\dolohi}
+
+\def\dolohi[#1]#2#3%
+ {\dontleavehmode
+ \hbox
+ {\setbox4\hbox{\dohighlow\lower\mathsubnormal{.48}{.1}{#2}}%
+ \setbox6\hbox{\dohighlow\raise\mathsupnormal{.86}{.1}{#3}}%
+ \doif{#1}{\v!left}
+ {\ifdim\wd4<\wd6
+ \setbox4\hbox to \wd6{\hss\box4}%
+ \else
+ \setbox6\hbox to \wd4{\hss\box6}%
+ \fi}%
+ \ifdim\wd4<\wd6
+ \wd4=\zeropoint\box4\box6
+ \else
+ \wd6=\zeropoint\box6\box4
+ \fi}}
+
+%D You can provide an optional keyword \type {left}, in which
+%D case the super and subscripts will be aligned in a way that
+%D permits placement at the left of a word (which means that
+%D it will be right aligned).
+%D
+%D \startbuffer
+%D \lohi{aha}{ah} test \lohi{aha}{ah} test
+%D \lohi[left]{aha}{ah} test \lohi[left]{aha}{ah} test
+%D \lohi{aha}{ah} test\lohi{aha}{ah} test
+%D \lohi[left]{aha}{ah}test \lohi[left]{aha}{ah}test
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+%D \macros
+%D {setupinitial,placeinitial,checkinitial}
+%D
+%D {\em To be documented.}
+%D
+%D \starttyping
+%D \setupinitial[state=start] \placeinitial \input tufte
+%D \stoptyping
+%D
+%D and
+%D
+%D \starttyping
+%D \def\bpar{\ifvmode\checkinitial\fi}
+%D \def\epar{\ifhmode\par\fi\checkinitial}
+%D \stoptyping
+
+% to do: more fine tuning
+
+\def\setupinitial
+ {\dodoubleempty\getparameters[\??dc]}
+
+\definefontsynonym[Initial][Regular] % prefered initial identifier
+\definefontsynonym[initial][Initial] % internal but accepted too
+
+\setupinitial
+ [\c!state=\v!stop,
+ \c!location=\v!text,
+ \c!n=3,
+ \c!distance=.125em,
+ \c!command=,
+ \s!font=initial]
+
+\def\AutoDroppedCapsCommand{\NiceDroppedCaps\@@dccommand\@@dcfont\@@dcdistance\@@dcn}%
+
+\def\placeinitial
+ {\doifelse\@@dclocation\v!margin{\chardef\DropMode\plusone}{\chardef\DropMode\zerocount}%
+ \doif \@@dcstate\v!start{\ifcase\@@dcn\else\AutoDroppedCaps\fi}}
+
+\let\checkinitial\CheckDroppedCaps
+
+%D This module has only a few setups:
+
+\setupunderbar
+ [\c!alternative=a,
+ \c!rulethickness=\linewidth,
+ \c!bottomoffset=1.5pt,
+ \c!topoffset=2.5pt,
+ \c!rulecolor=]
+
+\protect \endinput
diff --git a/tex/context/base/core-fnt.mkiv b/tex/context/base/core-fnt.mkiv
new file mode 100644
index 000000000..a7c84a5a0
--- /dev/null
+++ b/tex/context/base/core-fnt.mkiv
@@ -0,0 +1,293 @@
+%D \module
+%D [ file=core-fnt,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Fonts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Fonts}
+
+\unprotect
+
+%D \macros
+%D {compound}
+%D
+%D We will overload the already active \type {|} so we have
+%D to save its meaning in order to be able to use this handy
+%D macro.
+%D
+%D \starttyping
+%D so test\compound{}test can be used instead of test||test
+%D \stoptyping
+
+\bgroup \catcode`\|=\@@active \gdef\compound#1{|#1|} \egroup
+
+%D Here we hook some code into the clean up mechanism needed
+%D for verbatim data.
+
+\appendtoks
+ \disablecompoundcharacters
+ \disablediscretionaries
+\to \everycleanupfeatures
+
+%D \macros
+%D {stretched}
+%D
+%D Stretching characters in a word is a sort of typographical
+%D murder. Nevertheless we support this manipulation for use in
+%D for instance titles.
+%D
+%D \starttyping
+%D \hbox to 5cm{\stretched{murder}}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D \showsetup{stretched}
+
+\def\stretched#1%
+ {\ifvmode\hbox to \hsize\else\ifinner\else\hbox\fi\fi
+ \bgroup\processtokens\relax\hss\relax{\hss\hss}{#1}\egroup}
+
+%D \startbuffer
+%D \stretched{Unknown Box}
+%D \hbox to .5\hsize{\stretched{A Horizontal Box}}
+%D \vbox to 2cm{\stretched{A Vertical Box}}
+%D \hbox to 3cm{\stretched{sp{\'e}c{\`\i}{\"a}l}}
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D The first line of this macros takes care of boxing. Normally
+%D one will use an \type{\hbox} specification. The last line
+%D shows how special characters should be passed.
+%D
+%D \typebuffer
+
+%D \macros
+%D {stretchednormalcase, stretcheduppercase, stretchedlowercase}
+%D
+%D A convenient alternative is:
+%D
+%D \starttyping
+%D \stretcheduppercase{Is this what you like?}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D this one uses fixed skips and kerns.
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D The default skip can be set with:
+
+%D Given the following settings, the space is 1em by default:
+
+\def\stretchedspacefactor{4}
+\def\stretchedspaceamount{.25em}
+\def\stretchedbreaktokens{.@/}
+
+\unexpanded\def\stretchednormalcase
+ {\stretchedsomecase\firstofoneargument}
+
+\unexpanded\def\stretcheduppercase
+ {\stretchedsomecase{\the\everyuppercase\uppercase}}
+
+\unexpanded\def\stretchedlowercase
+ {\stretchedsomecase{\the\everylowercase\lowercase}}
+
+\def\stretchedsomecase#1#2%
+ {\bgroup
+ #1{\def\textstring{#2}}%
+ \ifdim\stretchedspaceamount=\zeropoint
+ \textstring
+ \else
+ \def\textkern##1%
+ {% beware: ##1 may not be \box\somebox -)
+ \determinemidwordbreak{##1}{\stretchedbreaktokens}%
+ \kern\stretchedspaceamount##1\domidwordbreak}%
+ \def\textskip
+ {\scratchdimen\stretchedspaceamount
+ \hskip\stretchedspacefactor\scratchdimen}%
+ \@EA\processtokens\@EA\relax\@EA\textkern\@EA\relax\@EA\textskip\@EA{\textstring}%
+ \fi
+ \egroup}
+
+%D An auxiliary macro, see for usage \type {\stretcheduppercase}.
+
+\let\domidwordbreak\relax
+
+\def\setmidwordbreaktoken#1%
+ {\sfcode`#1=5000\relax}
+
+\def\determinemidwordbreak#1#2%
+ {\edef\midwordbreaktokens{#2}%
+ \ifx\midwordbreaktokens\empty
+ \global\let\domidwordbreak\relax
+ \else
+ \setbox\scratchbox\hbox
+ {\expandafter\handletokens\midwordbreaktokens\with\setmidwordbreaktoken
+ a\space \!!dimena\lastskip
+ #1\space\!!dimenb\lastskip \relax % needed
+ \ifdim\!!dimena=\!!dimenb
+ \globallet\domidwordbreak\relax
+ \else
+ \globallet\domidwordbreak\allowbreak
+ \fi}%
+ \fi}
+
+%D \macros
+%D {shiftedword, shiftedwords}
+%D
+%D Used as \type {\shiftedwords {10pt} {some text}} this macro will
+%D move
+
+% \def\shiftedword#1% #2%
+% {\raise#1\hbox} % {#2}} % officially: {\ifdim#1>\zeropoint\raise\else\lower\fi#1\hbox{#2}}
+
+% \def\shiftedwords#1#2%
+% {\processisolatedwords{#2}{\shiftedword{#1}}}
+
+%D \macros
+%D {low, high, lohi, hilo}
+%D
+%D Although \TEX\ is pretty well aware of super- and
+%D subscripts, its mechanism is mainly tuned for math mode.
+%D The next few commands take care of script texts both modes.
+%D
+%D \startbuffer
+%D The higher\high{one goes} the lower\low{one drops}, or\lohi{yes}{no}?
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D Note the different placement of \type {\lohi}, where we
+%D need a bit more space. The implementation looks a bit
+%D fuzzy, since some \type {\fontdimen}'s are involved to
+%D determine the optimal placement.
+
+\def\dodohighlow
+ {\ifx\fontsize\empty
+ \ifmmode
+ \ifnum\fam<0 \tx \else \holamathfont \fi
+ \else
+ \tx
+ \fi
+ \else
+ \tx
+ \fi}
+
+\def\dohighlow#1#2#3#4#5% todo, named fontdimens
+ {\dontleavehmode
+ \bgroup
+ \scratchdimen\ifdim\fontexheight\textfont2=1ex #2\textfont2\else #3ex\fi
+ \advance\scratchdimen #4ex
+ \kern.1ex
+ \setbox\scratchbox\hbox{#1\scratchdimen\hbox{\dodohighlow#5}}%
+ \ht\scratchbox\strutheight
+ \dp\scratchbox\strutdepth
+ \box\scratchbox
+ \egroup}
+
+\unexpanded\def\high{\dohighlow\raise\mathsupnormal{.86}{0}}
+\unexpanded\def\low {\dohighlow\lower\mathsubnormal{.48}{0}}
+
+\unexpanded\def\lohi
+ {\dosingleempty\dolohi}
+
+\unexpanded\def\hilo
+ {\dosingleempty\dohilo}
+
+\def\dolohi[#1]#2#3%
+ {\dontleavehmode
+ \hbox
+ {\setbox4\hbox{\dohighlow\lower\mathsubnormal{.48}{.1}{#2}}%
+ \setbox6\hbox{\dohighlow\raise\mathsupnormal{.86}{.1}{#3}}%
+ \doif{#1}{\v!left}
+ {\ifdim\wd4<\wd6
+ \setbox4\hbox to \wd6{\hss\box4}%
+ \else
+ \setbox6\hbox to \wd4{\hss\box6}%
+ \fi}%
+ \ifdim\wd4<\wd6
+ \wd4=\zeropoint\box4\box6
+ \else
+ \wd6=\zeropoint\box6\box4
+ \fi}}
+
+\def\dohilo[#1]#2#3%
+ {\dolohi[#1]{#3}{#2}}
+
+%D You can provide an optional keyword \type {left}, in which
+%D case the super and subscripts will be aligned in a way that
+%D permits placement at the left of a word (which means that
+%D it will be right aligned).
+%D
+%D \startbuffer
+%D \lohi{aha}{ah} test \lohi{aha}{ah} test
+%D \lohi[left]{aha}{ah} test \lohi[left]{aha}{ah} test
+%D \lohi{aha}{ah} test\lohi{aha}{ah} test
+%D \lohi[left]{aha}{ah}test \lohi[left]{aha}{ah}test
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+%D \macros
+%D {setupinitial,placeinitial,checkinitial}
+%D
+%D {\em To be documented.}
+%D
+%D \starttyping
+%D \setupinitial[state=start] \placeinitial \input tufte
+%D \stoptyping
+%D
+%D and
+%D
+%D \starttyping
+%D \def\bpar{\ifvmode\checkinitial\fi}
+%D \def\epar{\ifhmode\par\fi\checkinitial}
+%D \stoptyping
+
+% to do: more fine tuning
+
+\unexpanded\def\setupinitial
+ {\dodoubleempty\getparameters[\??dc]}
+
+\definefontsynonym[Initial][Regular] % prefered initial identifier
+\definefontsynonym[initial][Initial] % internal but accepted too
+
+\setupinitial
+ [\c!state=\v!stop,
+ \c!location=\v!text,
+ \c!n=3,
+ \c!distance=.125em,
+ \c!command=,
+ \s!font=initial]
+
+\def\AutoDroppedCapsCommand{\NiceDroppedCaps\@@dccommand\@@dcfont\@@dcdistance\@@dcn}%
+
+\unexpanded\def\placeinitial
+ {\doifelse\@@dclocation\v!margin{\chardef\DropMode\plusone}{\chardef\DropMode\zerocount}%
+ \doif \@@dcstate\v!start{\ifcase\@@dcn\else\AutoDroppedCaps\fi}}
+
+\let\checkinitial\CheckDroppedCaps
+
+\protect \endinput
diff --git a/tex/context/base/core-gen.mkii b/tex/context/base/core-gen.mkii
new file mode 100644
index 000000000..b6ab2a208
--- /dev/null
+++ b/tex/context/base/core-gen.mkii
@@ -0,0 +1,166 @@
+%D \module
+%D [ file=core-gen,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=General,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / General}
+
+\unprotect
+
+%D \macros
+%D {assigndimension,assignalfadimension}
+%D
+%D Hieronder worden enkele commando's gedefinieerd rond
+%D toekenningen. Allereerst een commando om waarden aan
+%D een \DIMENSION\ toe te kennen:
+%D
+%D \starttyping
+%D \assigndimension
+%D {|klein|middel|groot|-klein|-middel|-groot|geen}
+%D {\dimension}
+%D {waarde klein}
+%D {waarde middel}
+%D {waarde groot}
+%D \stoptyping
+%D
+%D Hierbij krijgt de \DIMENSION\ \type{\dimension} een waarde
+%D afhankelijk van het meegegeven trefwoord.
+%D
+%D \startnarrower
+%D \startlines
+%D \type{(-)klein }\qquad (--) waarde klein
+%D \type{(-)middel}\qquad (--) waarde middel
+%D \type{(-)groot }\qquad (--) waarde groot
+%D \type{geen }\qquad 0pt
+%D \type{waarde }\qquad waarde
+%D \stoplines
+%D \stopnarrower
+%D
+%D Een trefwoord mag worden voorafgegaan door een \type{-}.
+%D Deze macro toont een voorbeeld van het gebruik van
+%D \type{\processaction} en constanten.
+%D
+%D Analoog aan het bovenstaande commando kennen we een
+%D commando om waarden toe te kennen aan een macro:
+%D
+%D \starttyping
+%D \assignalfadimension
+%D {|klein|middel|groot|geen}
+%D {\macro}
+%D {waarde klein}
+%D {waarde middel}
+%D {waarde groot}
+%D \stoptyping
+
+% The third (optimized) version:
+
+\def\@ad@{@ad@}
+
+\setvalue{\@ad@ \v!none }{\zeropoint\gobblethreearguments}
+\setvalue{\@ad@ \v!big }{\thirdofthreearguments}
+\setvalue{\@ad@ \v!medium}{\secondofthreearguments}
+\setvalue{\@ad@ \v!small }{\firstofthreearguments}
+\setvalue{\@ad@-\v!big }{-\thirdofthreearguments}
+\setvalue{\@ad@-\v!medium}{-\secondofthreearguments}
+\setvalue{\@ad@-\v!small }{-\firstofthreearguments}
+
+\def\assigndimension#1#2% #3 #4 #5
+ {#2=\ifcsname\@ad@#1\endcsname
+ \csname\@ad@#1\expandafter\endcsname
+ \else
+ #1\expandafter\gobblethreearguments
+ \fi}
+
+\def\@aa@{@aa@}
+
+\setvalue{\@aa@\v!none }{0\gobblethreearguments}
+\setvalue{\@aa@\v!big }{\thirdofthreearguments}
+\setvalue{\@aa@\v!medium}{\secondofthreearguments}
+\setvalue{\@aa@\v!small }{\firstofthreearguments}
+
+\def\assignalfadimension#1#2#3#4#5% #3#4#5 are single digits
+ {\edef#2{\ifcsname\@aa@#1\endcsname
+ \csname\@aa@#1\expandafter\endcsname
+ \else
+ #1\expandafter\gobblethreearguments
+ \fi#3#4#5}}
+
+%D \macros
+%D {assignvalue}
+%D
+%D Een variant hierop is het commando:
+%D
+%D \starttyping
+%D \assignvalue
+%D {|klein|middel|groot}
+%D {\macro}
+%D {waarde klein }
+%D {waarde middel}
+%D {waarde groot}
+%D \stoptyping
+%D
+%D Hierbij krijgt \type{\macro} een waarde afhankelijk van
+%D het meegegeven trefwoord:
+%D
+%D \startnarrower
+%D \startlines
+%D \type{klein }\qquad waarde klein
+%D \type{middel}\qquad waarde middel
+%D \type{groot }\qquad waarde groot
+%D \type{waarde}\qquad waarde
+%D \stoplines
+%D \stopnarrower
+%D
+%D Hier doet \type{geen} dus niet mee.
+
+\def\@av@{@av@}
+
+\letvalue{\@av@\v!big }\thirdofthreearguments
+\letvalue{\@av@\v!medium}\secondofthreearguments
+\letvalue{\@av@\v!small }\firstofthreearguments
+
+\def\assignvalue#1#2#3#4#5%
+ {\edef#2{\ifcsname\@av@#1\endcsname
+ \csname\@av@#1\expandafter\endcsname
+ \else
+ #1\expandafter\gobblethreearguments
+ \fi{#3}{#4}{#5}}}
+
+%D \macros
+%D {assignwidth}
+%D
+%D Een breedte van een opgegeven tekst kan worden berekend en
+%D toegekend aan een \DIMENSION\ met:
+%D
+%D \starttyping
+%D \assignwidth
+%D {\dimension}
+%D {|passend|ruim}
+%D {tekst}
+%D \stoptyping
+%D
+%D Dit commando sluit, evenals de bovenstaande
+%D \type{\assign}||commando's, aan op de wijze waarop
+%D in de andere \CONTEXT||modules toekenningen
+%D plaatsvinden. Bij \type{ruim} wordt de gemeten breedte
+%D met 1~em vermeerderd.
+
+\def\assignwidth#1#2#3#4%
+ {\doifelsenothing{#2}
+ {\setbox\scratchbox\hbox{#3}%
+ #1\wd\scratchbox}
+ {\doifinsetelse{#2}{\v!fit,\v!broad}
+ {\setbox\scratchbox\hbox{#3}%
+ #1\wd\scratchbox
+ \doif{#2}\v!broad{\advance#1 #4}}%
+ {#1=#2}}}%
+
+\protect \endinput
diff --git a/tex/context/base/core-gen.mkiv b/tex/context/base/core-gen.mkiv
new file mode 100644
index 000000000..b6ab2a208
--- /dev/null
+++ b/tex/context/base/core-gen.mkiv
@@ -0,0 +1,166 @@
+%D \module
+%D [ file=core-gen,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=General,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / General}
+
+\unprotect
+
+%D \macros
+%D {assigndimension,assignalfadimension}
+%D
+%D Hieronder worden enkele commando's gedefinieerd rond
+%D toekenningen. Allereerst een commando om waarden aan
+%D een \DIMENSION\ toe te kennen:
+%D
+%D \starttyping
+%D \assigndimension
+%D {|klein|middel|groot|-klein|-middel|-groot|geen}
+%D {\dimension}
+%D {waarde klein}
+%D {waarde middel}
+%D {waarde groot}
+%D \stoptyping
+%D
+%D Hierbij krijgt de \DIMENSION\ \type{\dimension} een waarde
+%D afhankelijk van het meegegeven trefwoord.
+%D
+%D \startnarrower
+%D \startlines
+%D \type{(-)klein }\qquad (--) waarde klein
+%D \type{(-)middel}\qquad (--) waarde middel
+%D \type{(-)groot }\qquad (--) waarde groot
+%D \type{geen }\qquad 0pt
+%D \type{waarde }\qquad waarde
+%D \stoplines
+%D \stopnarrower
+%D
+%D Een trefwoord mag worden voorafgegaan door een \type{-}.
+%D Deze macro toont een voorbeeld van het gebruik van
+%D \type{\processaction} en constanten.
+%D
+%D Analoog aan het bovenstaande commando kennen we een
+%D commando om waarden toe te kennen aan een macro:
+%D
+%D \starttyping
+%D \assignalfadimension
+%D {|klein|middel|groot|geen}
+%D {\macro}
+%D {waarde klein}
+%D {waarde middel}
+%D {waarde groot}
+%D \stoptyping
+
+% The third (optimized) version:
+
+\def\@ad@{@ad@}
+
+\setvalue{\@ad@ \v!none }{\zeropoint\gobblethreearguments}
+\setvalue{\@ad@ \v!big }{\thirdofthreearguments}
+\setvalue{\@ad@ \v!medium}{\secondofthreearguments}
+\setvalue{\@ad@ \v!small }{\firstofthreearguments}
+\setvalue{\@ad@-\v!big }{-\thirdofthreearguments}
+\setvalue{\@ad@-\v!medium}{-\secondofthreearguments}
+\setvalue{\@ad@-\v!small }{-\firstofthreearguments}
+
+\def\assigndimension#1#2% #3 #4 #5
+ {#2=\ifcsname\@ad@#1\endcsname
+ \csname\@ad@#1\expandafter\endcsname
+ \else
+ #1\expandafter\gobblethreearguments
+ \fi}
+
+\def\@aa@{@aa@}
+
+\setvalue{\@aa@\v!none }{0\gobblethreearguments}
+\setvalue{\@aa@\v!big }{\thirdofthreearguments}
+\setvalue{\@aa@\v!medium}{\secondofthreearguments}
+\setvalue{\@aa@\v!small }{\firstofthreearguments}
+
+\def\assignalfadimension#1#2#3#4#5% #3#4#5 are single digits
+ {\edef#2{\ifcsname\@aa@#1\endcsname
+ \csname\@aa@#1\expandafter\endcsname
+ \else
+ #1\expandafter\gobblethreearguments
+ \fi#3#4#5}}
+
+%D \macros
+%D {assignvalue}
+%D
+%D Een variant hierop is het commando:
+%D
+%D \starttyping
+%D \assignvalue
+%D {|klein|middel|groot}
+%D {\macro}
+%D {waarde klein }
+%D {waarde middel}
+%D {waarde groot}
+%D \stoptyping
+%D
+%D Hierbij krijgt \type{\macro} een waarde afhankelijk van
+%D het meegegeven trefwoord:
+%D
+%D \startnarrower
+%D \startlines
+%D \type{klein }\qquad waarde klein
+%D \type{middel}\qquad waarde middel
+%D \type{groot }\qquad waarde groot
+%D \type{waarde}\qquad waarde
+%D \stoplines
+%D \stopnarrower
+%D
+%D Hier doet \type{geen} dus niet mee.
+
+\def\@av@{@av@}
+
+\letvalue{\@av@\v!big }\thirdofthreearguments
+\letvalue{\@av@\v!medium}\secondofthreearguments
+\letvalue{\@av@\v!small }\firstofthreearguments
+
+\def\assignvalue#1#2#3#4#5%
+ {\edef#2{\ifcsname\@av@#1\endcsname
+ \csname\@av@#1\expandafter\endcsname
+ \else
+ #1\expandafter\gobblethreearguments
+ \fi{#3}{#4}{#5}}}
+
+%D \macros
+%D {assignwidth}
+%D
+%D Een breedte van een opgegeven tekst kan worden berekend en
+%D toegekend aan een \DIMENSION\ met:
+%D
+%D \starttyping
+%D \assignwidth
+%D {\dimension}
+%D {|passend|ruim}
+%D {tekst}
+%D \stoptyping
+%D
+%D Dit commando sluit, evenals de bovenstaande
+%D \type{\assign}||commando's, aan op de wijze waarop
+%D in de andere \CONTEXT||modules toekenningen
+%D plaatsvinden. Bij \type{ruim} wordt de gemeten breedte
+%D met 1~em vermeerderd.
+
+\def\assignwidth#1#2#3#4%
+ {\doifelsenothing{#2}
+ {\setbox\scratchbox\hbox{#3}%
+ #1\wd\scratchbox}
+ {\doifinsetelse{#2}{\v!fit,\v!broad}
+ {\setbox\scratchbox\hbox{#3}%
+ #1\wd\scratchbox
+ \doif{#2}\v!broad{\advance#1 #4}}%
+ {#1=#2}}}%
+
+\protect \endinput
diff --git a/tex/context/base/core-ini.mkii b/tex/context/base/core-ini.mkii
new file mode 100644
index 000000000..69edf9735
--- /dev/null
+++ b/tex/context/base/core-ini.mkii
@@ -0,0 +1,67 @@
+%D \module
+%D [ file=core-ini,
+%D version=2003.12.01,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Additional Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Additional Initialization}
+
+%D We will move more code to here, so that we become less dependent of the
+%D orde in which modules are loaded.
+
+\unprotect
+
+\everypar \emptytoks
+\neverypar \emptytoks
+
+\appendtoks \flushnotes \to \everypar
+\appendtoks \synchronizesidefloats \to \everypar
+
+\appendtoks \checkinlinedirection \to \everypar
+
+\appendtoks \checkindentation \to \everypar
+\appendtoks \showparagraphnumber \to \everypar
+\appendtoks \flushmargincontents \to \everypar
+\appendtoks \flushcommentanchors \to \everypar
+\appendtoks \synchronizenotes \to \everypar
+\appendtoks \OTRSETshowstatus \to \everypar
+\appendtoks \flushpostponedbookmark \to \everypar
+\appendtoks \registerparoptions \to \everypar
+\appendtoks \flushsyncpositions \to \everypar
+\appendtoks \flushpostponednodedata \to \everypar
+\appendtoks \dohandlerepeatdelimitedtext \to \everypar
+\appendtoks \insertparagraphintro \to \everypar
+
+\appendtoks \flushpostponedbookmark \to \neverypar
+\appendtoks \flushpostponedbookmark \to \everylistentry
+
+\appendtoks \flushnotes \to \everydisplay
+\appendtoks \adjustsidefloatdisplaylines \to \everydisplay
+
+\appendtoks \flushsyncpositions \to \everyheadstart
+
+\appendtoks \flushsyncresets \to \everyendoftextbody
+
+\appendtoks \ignorespaces \to \everybeginofpar
+
+\appendtoks \removeunwantedspaces \to \everyendofpar
+%appendtoks \strut \to \everyendofpar % option ?
+\appendtoks \flushsyncresets \to \everyendofpar
+\appendtoks \setlastlinewidth \to \everyendofpar % must happen before endgraf
+\appendtoks \endgraf \to \everyendofpar
+
+% Todo: verbatim, xml, tex, move code to here
+
+\ifx\normalcompound\undefined \let\normalcompound=| \fi
+
+\appendtoks \catcode`|=\@@active \let|\normalcompound \to \everyTEXinputmode
+\appendtoks \catcode`|=\@@letter \to \everyXMLinputmode
+
+\protect \endinput
diff --git a/tex/context/base/core-ini.mkiv b/tex/context/base/core-ini.mkiv
new file mode 100644
index 000000000..d6a72bb26
--- /dev/null
+++ b/tex/context/base/core-ini.mkiv
@@ -0,0 +1,66 @@
+%D \module
+%D [ file=core-ini,
+%D version=2003.12.01,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Additional Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Additional Initialization}
+
+%D We will move more code to here, so that we become less dependent of the
+%D orde in which modules are loaded.
+
+\unprotect
+
+\everypar \emptytoks
+\neverypar \emptytoks
+
+\appendtoks \flushnotes \to \everypar
+\appendtoks \synchronizesidefloats \to \everypar
+
+\appendtoks \checkindentation \to \everypar
+\appendtoks \showparagraphnumber \to \everypar
+\appendtoks \restoreinterlinepenalty \to \everypar
+\appendtoks \flushmargincontents \to \everypar
+\appendtoks \flushcommentanchors \to \everypar
+\appendtoks \synchronizenotes \to \everypar
+\appendtoks \OTRSETshowstatus \to \everypar
+\appendtoks \flushpostponedbookmark \to \everypar
+\appendtoks \registerparoptions \to \everypar
+\appendtoks \flushsyncpositions \to \everypar
+\appendtoks \flushpostponednodedata \to \everypar
+\appendtoks \dohandlerepeatdelimitedtext \to \everypar
+\appendtoks \insertparagraphintro \to \everypar
+
+\appendtoks \flushpostponedbookmark \to \neverypar
+\appendtoks \flushpostponedbookmark \to \everylistentry
+
+\appendtoks \flushnotes \to \everydisplay
+\appendtoks \adjustsidefloatdisplaylines \to \everydisplay
+
+\appendtoks \flushsyncpositions \to \everyheadstart
+
+\appendtoks \flushsyncresets \to \everyendoftextbody
+
+\appendtoks \ignorespaces \to \everybeginofpar
+
+\appendtoks \removeunwantedspaces \to \everyendofpar
+%appendtoks \strut \to \everyendofpar % option ?
+\appendtoks \flushsyncresets \to \everyendofpar
+%appendtoks \setlastlinewidth \to \everyendofpar % gone, will be done in lua
+\appendtoks \endgraf \to \everyendofpar
+
+% Todo: verbatim, xml, tex, move code to here
+
+\ifx\normalcompound\undefined \let\normalcompound=| \fi
+
+\appendtoks \catcode`|=\@@active \let|\normalcompound \to \everyTEXinputmode
+\appendtoks \catcode`|=\@@letter \to \everyXMLinputmode
+
+\protect \endinput
diff --git a/tex/context/base/core-job.lua b/tex/context/base/core-job.lua
new file mode 100644
index 000000000..d557818bb
--- /dev/null
+++ b/tex/context/base/core-job.lua
@@ -0,0 +1,202 @@
+if not modules then modules = { } end modules ['core-job'] = {
+ version = 1.001,
+ comment = "companion to core-job.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local texsprint, texprint, texwrite = tex.sprint, tex.print, tex.write
+local ctxcatcodes, texcatcodes = tex.ctxcatcodes, tex.texcatcodes
+local lower, format, find, gmatch, gsub, match = string.lower, string.format, string.find, string.gmatch, string.gsub, string.match
+local concat = table.concat
+
+-- main code
+
+resolvers.maxreadlevel = 3
+
+directives.register("resolvers.maxreadlevel", function(v) resolvers.maxreadlevel = tonumber(v) or resolvers.maxreadlevel end)
+
+local function exists(n)
+ if io.exists(n) then
+ return n
+ else
+ n = file.addsuffix(n,'tex')
+ if io.exists(n) then
+ return n
+ end
+ end
+ return nil
+end
+
+function resolvers.findctxfile(name,maxreadlevel)
+ if file.is_qualified_path(name) then
+ return name
+ else
+ -- not that efficient, too many ./ lookups
+ local n = "./" .. name
+ local found = exists(n)
+ if found then
+ return found
+ else
+ for i=1,maxreadlevel or resolvers.maxreadlevel or 0 do
+ n = "../" .. n
+ found = exists(n)
+ if found then
+ return found
+ end
+ end
+ end
+ return resolvers.find_file(name) or ""
+ end
+end
+
+function commands.maxreadlevel()
+ texwrite(resolvers.maxreadlevel)
+end
+
+function commands.processfile(name,maxreadlevel)
+ name = resolvers.findctxfile(name,maxreadlevel)
+ if name ~= "" then
+ texsprint(ctxcatcodes,format("\\input %s\\relax",name)) -- we need \input {name}
+ end
+end
+
+function commands.doifinputfileelse(name,maxreadlevel)
+ commands.doifelse(resolvers.findctxfile(name,maxreadlevel) ~= "")
+end
+
+function commands.locatefilepath(name,maxreadlevel)
+ texsprint(texcatcodes,file.dirname(resolvers.findctxfile(name,maxreadlevel)))
+end
+
+function commands.usepath(paths,maxreadlevel)
+ resolvers.register_extra_path(paths)
+ texsprint(texcatcodes,concat(resolvers.instance.extra_paths or {}, ""))
+end
+
+function commands.usesubpath(subpaths,maxreadlevel)
+ resolvers.register_extra_path(nil,subpaths)
+ texsprint(texcatcodes,concat(resolvers.instance.extra_paths or {}, ""))
+end
+
+function commands.usezipfile(name,tree)
+ if tree and tree ~= "" then
+ resolvers.usezipfile(format("zip:///%s?tree=%s",name,tree))
+ else
+ resolvers.usezipfile(format("zip:///%s",name))
+ end
+end
+
+-- for the moment here, maybe a module
+
+--~
+--~
+--~ nee
+--~ standaard
+--~
+
+local function convertexamodes(str)
+ local x = xml.convert(str)
+ for e in xml.collected(x,"exa:variable") do
+ local label = e.at and e.at.label
+ if label and label ~= "" then
+ local data = xml.text(e)
+ local mode = match(label,"^mode:(.+)$")
+ if mode then
+ texsprint(ctxcatcodes,format("\\enablemode[%s:%s]",mode,data))
+ end
+ texsprint(ctxcatcodes,format("\\setvariable{exa:variables}{%s}{%s}",label,gsub(data,"([{}])","\\%1")))
+ end
+ end
+end
+
+-- we need a system file option: ,. .. etc + paths but no tex lookup so resolvers.find_file is wrong here
+
+function commands.loadexamodes(filename)
+ if not filename or filename == "" then
+ filename = file.removesuffix(tex.jobname)
+ end
+ filename = resolvers.find_file(file.addsuffix(filename,'ctm')) or ""
+ if filename ~= "" then
+ commands.writestatus("examodes","loading %s",filename) -- todo: message system
+ convertexamodes(io.loaddata(filename))
+ else
+ commands.writestatus("examodes","no mode file %s",filename) -- todo: message system
+ end
+end
+
+function commands.logoptionfile(name)
+ -- todo: xml if xml logmode
+ local f = io.open(name)
+ if f then
+ texio.write_nl("log","%\n%\tbegin of optionfile\n%\n")
+ for line in f:lines() do
+ texio.write("log",format("%%\t%s\n",line))
+ end
+ texio.write("log","%\n%\tend of optionfile\n%\n")
+ f:close()
+ end
+end
+
+--~ set functions not ok and not faster on mk runs either
+--~
+--~ local function doifcommonelse(a,b)
+--~ local ba = find(a,",")
+--~ local bb = find(b,",")
+--~ if ba and bb then
+--~ for sa in gmatch(a,"[^ ,]+") do
+--~ for sb in gmatch(b,"[^ ,]+") do
+--~ if sa == sb then
+--~ texsprint(ctxcatcodes,"\\def\\commalistelement{",sa,"}")
+--~ return true
+--~ end
+--~ end
+--~ end
+--~ elseif ba then
+--~ for sa in gmatch(a,"[^ ,]+") do
+--~ if sa == b then
+--~ texsprint(ctxcatcodes,"\\def\\commalistelement{",b,"}")
+--~ return true
+--~ end
+--~ end
+--~ elseif bb then
+--~ for sb in gmatch(b,"[^ ,]+") do
+--~ if a == sb then
+--~ texsprint(ctxcatcodes,"\\def\\commalistelement{",a,"}")
+--~ return true
+--~ end
+--~ end
+--~ else
+--~ if a == b then
+--~ texsprint(ctxcatcodes,"\\def\\commalistelement{",a,"}")
+--~ return true
+--~ end
+--~ end
+--~ texsprint(ctxcatcodes,"\\let\\commalistelement\\empty")
+--~ return false
+--~ end
+--~ local function doifinsetelse(a,b)
+--~ local bb = find(b,",")
+--~ if bb then
+--~ for sb in gmatch(b,"[^ ,]+") do
+--~ if a == sb then
+--~ texsprint(ctxcatcodes,"\\def\\commalistelement{",a,"}")
+--~ return true
+--~ end
+--~ end
+--~ else
+--~ if a == b then
+--~ texsprint(ctxcatcodes,"\\def\\commalistelement{",a,"}")
+--~ return true
+--~ end
+--~ end
+--~ texsprint(ctxcatcodes,"\\let\\commalistelement\\empty")
+--~ return false
+--~ end
+--~ function commands.doifcommon (a,b) commands.doif (doifcommonelse(a,b)) end
+--~ function commands.doifnotcommon (a,b) commands.doifnot (doifcommonelse(a,b)) end
+--~ function commands.doifcommonelse(a,b) commands.doifelse(doifcommonelse(a,b)) end
+--~ function commands.doifinset (a,b) commands.doif (doifinsetelse(a,b)) end
+--~ function commands.doifnotinset (a,b) commands.doifnot (doifinsetelse(a,b)) end
+--~ function commands.doifinsetelse (a,b) commands.doifelse(doifinsetelse(a,b)) end
diff --git a/tex/context/base/core-job.mkii b/tex/context/base/core-job.mkii
new file mode 100644
index 000000000..5c280c15b
--- /dev/null
+++ b/tex/context/base/core-job.mkii
@@ -0,0 +1,415 @@
+%D \module
+%D [ file=core-job, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Job Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is still to be split and documented.
+
+\writestatus{loading}{ConTeXt Core Macros / Job Handling}
+
+\unprotect
+
+\let \currentproject \empty
+\let \currentproduct \empty
+\let \currentenvironment \empty
+\let \currentcomponent \empty
+
+\let \loadedfiles \empty
+\let \processedfiles \empty
+
+\let \nomorefiles \relax
+
+\let \allinputpaths \empty
+\let \locatedfilepath \empty
+
+\newcount\textlevel
+\newcount\fileprocesslevel
+
+\setvalue{\c!file::0}{\jobname}
+
+\def\processedfile % is used in styles, don't change !
+ {\getvalue{\c!file::\number\fileprocesslevel}}
+
+\def\dostarttextfile#1%
+ {\global\advance\fileprocesslevel\plusone
+ \setxvalue{\c!file::\number\fileprocesslevel}{#1}%
+ \@EA\doglobal\@EA\addtocommalist\@EA{#1}\processedfiles}
+
+\def\dostoptextfile
+ {\global\advance\fileprocesslevel\minusone}
+
+\def\processlocalfile#1#2%
+ {#1{#2}\donothing{\readfile{#2}\donothing\donothing}}
+
+\def\processfile#1%
+ {\ifx\allinputpaths\empty
+ \def\next{\processlocalfile\readlocfile}%
+ \else
+ \let\filepath\empty
+ \def\docommand##1%
+ {\doiffileelse{\pathplusfile{##1}{#1}}{\donetrue\def\filepath{##1}}\donefalse
+ \ifdone\expandafter\quitcommalist\fi}%
+ \doifparentfileelse{#1} % new
+ {\processcommacommand [\allinputpaths]\docommand}
+ {\processcommacommand[.,\allinputpaths]\docommand}%
+ \ifx\filepath\empty
+ \def\next{\processlocalfile\readlocfile}% fall back ../../..
+ \else
+ \def\next{\processlocalfile{\readsetfile\filepath}}% file found
+ \fi
+ \fi
+ \next{#1}}
+
+\def\doifinputfileelse#1% rarely used
+ {\ifx\allinputpaths\empty
+ \@EA\secondoftwoarguments
+ \else
+ \let\filepath\empty
+ \def\docommand##1%
+ {\doiffileelse{\pathplusfile{##1}{#1}}{\donetrue\def\filepath{##1}}\donefalse
+ \ifdone\expandafter\quitcommalist\fi}%
+ \processcommacommand[.,\allinputpaths]\docommand
+ \ifx\filepath\empty
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi
+ \fi}
+
+\let\locatedfilepath\empty
+
+\def\locatefilepath#1%
+ {\let\locatedfilepath\empty
+ \ifx\allinputpaths\empty \else
+ \def\docommand##1%
+ {\doiffileelse{\pathplusfile{##1}{#1}}{\donetrue\def\locatedfilepath{##1}}\donefalse
+ \ifdone\expandafter\quitcommalist\fi}%
+ \doifparentfileelse{#1} % new
+ {\processcommacommand [\allinputpaths]\docommand}
+ {\processcommacommand[.,\allinputpaths]\docommand}%
+ \fi}
+
+\def\usepath[#1]%
+ {\def\docommand##1%
+ {\doifelse{##1}\v!reset
+ {\let\allinputpaths\empty}
+ {\sanitizefilename#1\to\ascii
+ \defconvertedcommand\ascii\ascii
+ \addtocommalist\ascii\allinputpaths}}%
+ \processcommalist[#1]\docommand}
+
+\def\usesubpath[#1]% test for a real long time, permits ../{name} i.e. braces
+ {\ifx\allinputpaths\empty
+ \sanitizefilename#1\to\allinputpaths
+ \else
+ \def\docommand##1%
+ {\def\dodocommand####1%
+ {\sanitizefilename####1\to\ascii
+ \defconvertedcommand\ascii\ascii
+ \addtocommalist{##1/\ascii}\allinputpaths}%
+ \processcommalist[#1]\dodocommand}%
+ \processcommacommand[\allinputpaths]\docommand
+ \fi}
+
+\def\registerfileinfo[#1#2]#3% geen \showmessage ?
+ {\writestatus\m!systems{#1#2 file #3 at line \the\inputlineno}%
+ \immediatewriteutility{f #1 {#3}}}
+
+\ifx\preloadfonts \undefined \let\preloadfonts \relax \fi
+\ifx\preloadspecials\undefined \let\preloadspecials\relax \fi
+
+\def\loadallsystemfiles#1#2%
+ {\ifx\@@svdirectory\empty
+ \readsysfile{#1}{\showmessage\m!systems2{#1}}{#2}%
+ \else% yet undocumented
+ \def\doloadsystemfile##1%
+ {\readsetfile{##1}{#1}{\showmessage\m!systems2{#1}}{#2}}%
+ \processcommacommand[\@@svdirectory]\doloadsystemfile
+ \fi}
+
+\ifx\disableXML\undefined \let\disableXML\relax \fi
+
+\def\loadsystemfiles
+ {\reportprotectionstate
+ \readsysfile\f!newfilename{\showmessage\m!systems2\f!newfilename}\donothing
+ %\readsysfile\f!oldfilename{\showmessage\m!systems2\f!oldfilename}\donothing
+ \loadallsystemfiles\f!filfilename
+ \donothing
+ \loadallsystemfiles\f!sysfilename
+ {\loadallsystemfiles{\f!sysfilename.rme}\donothing % new, fall back
+ \doglobal\appendtoks % brrr better \setcatcodetable\ctxcatcodes % % test
+ \bgroup\disableXML\loadallsystemfiles\f!errfilename\donothing\egroup
+ \to\everygoodbye}}
+
+%D Loading of \type {cont-usr.tex} (edited by the user)
+%D and \type {cont-fmt.tex} (generated by texexec).
+
+\def\loaduserspecifications
+ {% this used to be the file where users can tune their system, especially patterns
+ \readsysfile\f!usrfilename{\showmessage\m!systems2\f!usrfilename}\donothing
+ % this one took care of user preferences (fonts, messages) but lm made this obsolete
+ \readjobfile\f!fmtfilename{\showmessage\m!systems2\f!fmtfilename}\donothing
+ % from now on we preload all patterns (only in mkii)
+ \preloadallpatterns}
+
+\let\loaduserspecifications\relax
+
+%D We don't want multiple jobfiles to interfere.
+
+\def\loadoptionfile
+ {\readjobfile{\jobname.\f!optionextension}
+ {\showmessage\m!systems2{\jobname.\f!optionextension}}%
+ {\writestatus\m!systems {no \jobname.\f!optionextension}}}
+
+% Most natural ...
+%
+% \def\doateverystarttext
+% {\the\everystarttext
+% \global\let\doateverystarttext\relax}
+%
+% ... most practical, since we can load env's in a
+% something.run file (nested \starttext's; see for
+% instance x-res-08, where we definitely want to
+% open the file!).
+
+\def\doateverystarttext
+ {\the\everystarttext
+ \global\everystarttext\emptytoks}
+
+\def\starttext
+ {\doateverystarttext
+ \ifcase\textlevel
+ \registerfileinfo[begin]\jobname
+ \expandafter\startcopyingblocks
+ \fi
+ \global\advance\textlevel\plusone}
+
+\def\stoptext
+ {\global\advance\textlevel\minusone
+ \ifnum\textlevel>\zerocount \else
+ \page[\v!last]\page % new, moved from everybye to here; flushes headers, colors etc etc etc
+ \the\everystoptext
+ %\the\everybye %
+ %\the\everygoodbye % == \end (new)
+ %\expandafter\normalend %
+ \expandafter\finalend
+ \fi}
+
+\def\forcequitjob#1%
+ {\writestatus\m!systems{forcing quit: #1}%
+ \batchmode
+ \dorecurse\textlevel\stoptext
+ \normalend}
+
+\let\autostoptext\relax
+
+\def\autostarttext
+ {\ifcase\textlevel
+ \starttext
+ \writestatus\m!systems{auto \string\starttext..\string\stoptext}%
+ \let\autostoptext\stoptext
+ \fi}
+
+\def\finalend
+ {\ifnum\textlevel>\zerocount \else
+ \the\everybye
+ \the\everygoodbye
+ \doifsometokselse\everynotabene{\writeline\the\everynotabene\writeline}\donothing
+ \global\everybye \emptytoks % rather unneeded
+ \global\everygoodbye\emptytoks % but for sure
+ \expandafter\normalend
+ \fi}
+
+\let\end\finalend
+
+\def\emergencyend
+ {\writestatus\m!systems{invalid \@EA\string\csname\e!start\v!text\endcsname...\@EA\string\csname\e!stop\v!text\endcsname\space structure}%
+ \stoptext}
+
+\def\currentfile{\inputfilename}
+
+\def\doexecutefileonce#1%
+ {\beforesplitstring#1\at.\to\currentfile
+ \fullexpandtwoargsafter\doifnotinset\currentfile\loadedfiles
+ {\fullexpandoneargafter\addtocommalist\currentfile\loadedfiles
+ \doexecutefile{#1}}}
+
+\def\doexecutefile#1%
+ {\registerfileinfo[begin]{#1}%
+ \dostarttextfile{#1}%
+ \processfile{#1}%
+ \dostoptextfile
+ \registerfileinfo[end]{#1}}
+
+\def\donotexecutefile#1%
+ {}
+
+\def\verwerkfile#1 %
+ {\doexecutefile{#1}}
+
+\def\useenvironment[#1]% maybe commalist
+ {\environment #1 \relax}
+
+\def\environment #1 % at outermost level only (load only once)
+ {\pushmacro\startenvironment
+ \pushmacro\stopenvironment
+ \def\startenvironment ##1 {}%
+ \let\stopenvironment\relax
+ \startreadingfile
+ \doexecutefileonce{#1}
+ \stopreadingfile
+ \popmacro\stopenvironment
+ \popmacro\startenvironment}
+
+\def\component #1 % at outermost level only
+ {\dostarttextfile{#1}%
+ \processfile{#1}%
+ \dostoptextfile}
+
+\newcount\filelevel
+
+\let\currentcomponent \v!text
+\let\currentcomponentpath\f!currentpath
+
+\def\donextlevel#1#2#3#4#5#6#7\\%
+ {\pushmacro\currentcomponent
+ \pushmacro\currentcomponentpath
+ \let\currentcomponent#1%
+ \setsystemmode\currentcomponent
+ \splitfilename{#1}%
+ \ifx\splitoffpath\empty
+ \let\currentcomponentpath\f!currentpath
+ \else
+ \let\currentcomponentpath\splitoffpath
+ \fi
+ \beforesplitstring#7\at.\to#2\relax % can become path + base
+ \ifcase\filelevel\relax
+ \starttext
+ \def\project ##1 {#3{##1}}%
+ \def\environment ##1 {#4{##1}}%
+ \def\product ##1 {#5{##1}}%
+ \def\component ##1 {#6{##1}}%
+ \fi
+ \advance\filelevel\plusone
+ \fullexpandoneargafter\addtocommalist{#1}\loadedfiles}
+
+\def\doprevlevel
+ {\popmacro\currentcomponentpath
+ \popmacro\currentcomponent
+ \setsystemmode\currentcomponent
+ \ifnum\filelevel=\plusone
+ \expandafter\stoptext
+ \else
+ \advance\filelevel\minusone
+ \expandafter\endinput
+ \fi}
+
+\def\startproject #1 %
+ {\donextlevel\v!project\currentproject
+ \donotexecutefile\doexecutefileonce
+ \doexecutefileonce\doexecutefile#1\\}
+
+\def\startproduct #1 %
+ {\doateverystarttext
+ \donextlevel\v!product\currentproduct
+ \doexecutefileonce\doexecutefileonce
+ \donotexecutefile\doexecutefile#1\\}
+
+\def\startcomponent #1 %
+ {\doateverystarttext
+ \donextlevel\v!component\currentcomponent
+ \doexecutefileonce\doexecutefileonce
+ \donotexecutefile\doexecutefile#1\\}
+
+\def\startenvironment #1 %
+ {\donextlevel\v!environment\currentenvironment
+ \donotexecutefile\doexecutefileonce
+ \donotexecutefile\donotexecutefile#1\\}
+
+% \startproject test
+% 1: \startmode[*project] project \stopmode \endgraf
+% 2: \startmode[*product] product \stopmode \endgraf
+% \stopproject
+
+\def\stopproject {\doprevlevel}
+\def\stopproduct {\doprevlevel}
+\def\stopcomponent {\doprevlevel}
+\def\stopenvironment{\doprevlevel}
+
+% more or less replaced by modes
+
+\setvalue{\e!start\v!localenvironment}[#1]%
+ {\let\loadedlocalenvironments\empty
+ \def\docommand##1%
+ {\beforesplitstring##1\at.\to\someevironment
+ \fullexpandoneargafter\addtocommalist\someevironment\loadedlocalenvironments}%
+ \processcommalist[#1]\docommand
+ \fullexpandtwoargsafter\doifcommonelse % no longer next needed
+ {\currentproject,\currentproduct,%
+ \currentcomponent,\currentenvironment}
+ {\loadedlocalenvironments}
+ {\letvalue{\e!stop\v!localenvironment}\relax}
+ {\grabuntil{\e!stop\v!localenvironment}\gobbleoneargument}} % TH: fixed, was \relax
+
+\setvalue{\v!localenvironment}#1 {\doexecutefileonce{#1}}
+
+% NOT TOEVOEGEN: \the\everytrace
+
+\neverypar=\emptytoks
+
+% \appendtoks \flushnotes \to \everypar
+% \appendtoks \synchronizesidefloats \to \everypar
+% \appendtoks \checkindentation \to \everypar
+% \appendtoks \showparagraphnumber \to \everypar
+% \appendtoks \flushmargincontents \to \everypar
+% \appendtoks \flushcommentanchors \to \everypar
+% \appendtoks \synchronizenotes \to \everypar
+
+% \appendtoks \flushnotes \to \everydisplay
+% \appendtoks \adjustsidefloatdisplaylines \to \everydisplay
+
+% soon, when pdftex 1.22 is out in the field:
+
+\chardef\systemcommandmode\zerocount % 0=unknown 1=disabled 2=enabled
+
+\def\checksystemcommandmode
+ {\ifx\pdfshellescape\undefined \else
+ \chardef\systemcommandmode \ifcase\pdfshellescape \plusone \else \plustwo \fi
+ \fi
+ \global\let\checksystemcommandmode\relax}
+
+\def\reportsystemcommandmode
+ {\ifcase\systemcommandmode
+ \or
+ \writestatus\m!systems{system commands are disabled}%
+ \or
+ \writestatus\m!systems{system commands are enabled}%
+ \fi}
+
+% \ifx\etexversion\undefined \else \ifnum\etexversion<202
+% \prependtoks
+% \writestatus\m!systems{eTeX version \number\etexversion\space -> too old (bugs)}%
+% \writeline
+% \to \everyjob
+% \fi \fi
+
+% \ifx\pdftexversion\undefined \else \ifnum\number\pdftexversion<120
+% \prependtoks
+% \writestatus\m!systems{pdfTeX version \number\pdftexversion\space -> please update}%
+% \writeline
+% \to \everyjob
+% \fi \fi
+
+% Default-instellingen (verborgen)
+
+\resetutilities
+
+\protect \endinput
diff --git a/tex/context/base/core-job.mkiv b/tex/context/base/core-job.mkiv
new file mode 100644
index 000000000..de328c92b
--- /dev/null
+++ b/tex/context/base/core-job.mkiv
@@ -0,0 +1,309 @@
+%D \module
+%D [ file=core-job, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Job Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is still to be split and documented.
+
+\writestatus{loading}{ConTeXt Core Macros / Job Handling}
+
+\unprotect
+
+\registerctxluafile{core-job}{1.001}
+
+\let \currentproject \empty
+\let \currentproduct \empty
+\let \currentenvironment \empty
+\let \currentcomponent \empty
+
+\let \loadedfiles \empty
+\let \processedfiles \empty
+
+\let \nomorefiles \relax
+
+\let \allinputpaths \empty
+\let \locatedfilepath \empty
+
+\newcount\textlevel
+\newcount\fileprocesslevel
+
+\setvalue{\c!file::0}{\jobname}
+
+\def\processedfile % is used in styles, don't change !
+ {\getvalue{\c!file::\number\fileprocesslevel}}
+
+\def\dostarttextfile#1%
+ {\global\advance\fileprocesslevel\plusone
+ \setxvalue{\c!file::\number\fileprocesslevel}{#1}%
+ \@EA\doglobal\@EA\addtocommalist\@EA{#1}\processedfiles}
+
+\def\dostoptextfile
+ {\global\advance\fileprocesslevel\minusone}
+
+\def\processlocalfile#1#2%
+ {#1{#2}\donothing{\readfile{#2}\donothing\donothing}}
+
+\def\processfile #1{\ctxlua{commands.processfile("#1")}}
+\def\doifinputfileelse #1{\ctxlua{commands.doifinputfileelse("#1")}}
+\def\locatefilepath #1{\edef\locatedfilepath{\ctxlua{commands.locatefilepath("#1")}}}
+\def\usepath [#1]{\edef\allinputpaths{\ctxlua{commands.usepath("#1")}}}
+\def\usesubpath [#1]{\edef\allinputpaths{\ctxlua{commands.usesubpath("#1")}}}
+\def\usezipfile {\dodoubleempty\dousezipfile}
+\def\dousezipfile[#1][#2]{\ctxlua{commands.usezipfile("#1","#2")}} % [filename] [optional subtree]
+
+\def\loadexamodes {\dosingleempty\doloadexamodes}
+\def\doloadexamodes [#1]{\ctxlua{commands.loadexamodes("#1")}}
+
+\def\registerfileinfo[#1#2]#3% geen \showmessage ?
+ {\writestatus\m!systems{#1#2 file #3 at line \the\inputlineno}}
+
+\ifx\preloadfonts \undefined \let\preloadfonts \relax \fi
+\ifx\preloadspecials\undefined \let\preloadspecials\relax \fi
+
+\def\loadallsystemfiles#1#2%
+ {\ifx\@@svdirectory\empty
+ \readsysfile{#1}{\showmessage\m!systems2{#1}}{#2}%
+ \else% yet undocumented
+ \def\doloadsystemfile##1%
+ {\readsetfile{##1}{#1}{\showmessage\m!systems2{#1}}{#2}}%
+ \processcommacommand[\@@svdirectory]\doloadsystemfile
+ \fi}
+
+\ifx\disableXML\undefined \let\disableXML\relax \fi
+
+\def\loadsystemfiles
+ {\reportprotectionstate
+ \readsysfile\f!newfilename{\showmessage\m!systems2\f!newfilename}\donothing
+ %\readsysfile\f!oldfilename{\showmessage\m!systems2\f!oldfilename}\donothing
+ \loadallsystemfiles\f!filfilename
+ \donothing
+ \loadallsystemfiles\f!sysfilename
+ {\loadallsystemfiles{\f!sysfilename.rme}\donothing % new, fall back
+ \doglobal\appendtoks % brrr better \setcatcodetable\ctxcatcodes % % test
+ \bgroup\disableXML\loadallsystemfiles\f!errfilename\donothing\egroup
+ \to\everygoodbye}}
+
+%D We don't want multiple jobfiles to interfere.
+
+\def\loadoptionfile
+ {\readjobfile{\jobname.\f!optionextension}
+ {\showmessage\m!systems2{\jobname.\f!optionextension}%
+ \ctxlua{commands.logoptionfile("\jobname.\f!optionextension")}}%
+ {\writestatus\m!systems {no \jobname.\f!optionextension}}}
+
+% Most natural ...
+%
+% \def\doateverystarttext
+% {\the\everystarttext
+% \global\let\doateverystarttext\relax}
+%
+% ... most practical, since we can load env's in a
+% something.run file (nested \starttext's; see for
+% instance x-res-08, where we definitely want to
+% open the file!).
+
+\def\doateverystarttext
+ {\the\everystarttext
+ \global\everystarttext\emptytoks}
+
+\unexpanded\def\starttext
+ {\doateverystarttext
+ \ifcase\textlevel
+ \registerfileinfo[begin]\jobfilename
+ \fi
+ \global\advance\textlevel\plusone}
+
+\unexpanded\def\stoptext
+ {\global\advance\textlevel\minusone
+ \ifnum\textlevel>\zerocount \else
+ \flushfinallayoutpage % optional
+ \page % anyway
+ \the\everystoptext
+ %\the\everybye %
+ %\the\everygoodbye % == \end (new)
+ %\expandafter\normalend %
+\ifcase\textlevel
+ \registerfileinfo[end]\jobfilename
+\fi
+ \expandafter\finalend
+ \fi}
+
+\def\forcequitjob#1%
+ {\writestatus\m!systems{forcing quit: #1}%
+ \batchmode
+ \dorecurse\textlevel{\stoptext}
+ \normalend}
+
+\let\autostoptext\relax
+
+\def\autostarttext
+ {\ifcase\textlevel
+ \starttext
+ \writestatus\m!systems{auto \string\starttext..\string\stoptext}%
+ \let\autostoptext\stoptext
+ \fi}
+
+\def\finalend
+ {\ifnum\textlevel>\zerocount \else
+ \the\everybye
+ \the\everygoodbye
+ \doifsometokselse\everynotabene{\writeline\the\everynotabene\writeline}\donothing
+ \global\everybye \emptytoks % rather unneeded
+ \global\everygoodbye\emptytoks % but for sure
+ \expandafter\normalend
+ \fi}
+
+\let\end\finalend
+
+\def\emergencyend
+ {\writestatus\m!systems{invalid \@EA\string\csname\e!start\v!text\endcsname...\@EA\string\csname\e!stop\v!text\endcsname\space structure}%
+ \stoptext}
+
+\def\currentfile{\inputfilename}
+
+\def\doexecutefileonce#1%
+ {\beforesplitstring#1\at.\to\currentfile
+ \fullexpandtwoargsafter\doifnotinset\currentfile\loadedfiles
+ {\fullexpandoneargafter\addtocommalist\currentfile\loadedfiles
+ \doexecutefile{#1}}}
+
+\def\doexecutefile#1%
+ {\registerfileinfo[begin]{#1}%
+ \dostarttextfile{#1}%
+ \processfile{#1}%
+ \dostoptextfile
+ \registerfileinfo[end]{#1}}
+
+\def\donotexecutefile#1%
+ {}
+
+\def\useenvironment[#1]% maybe commalist
+ {\environment #1 \relax}
+
+\def\environment #1 % at outermost level only (load only once)
+ {\pushmacro\startenvironment
+ \pushmacro\stopenvironment
+ \unexpanded\def\startenvironment ##1 {}%
+ \let\stopenvironment\relax
+ \startreadingfile
+ \doexecutefileonce{#1}
+ \stopreadingfile
+ \popmacro\stopenvironment
+ \popmacro\startenvironment}
+
+\def\component #1 % at outermost level only
+ {\dostarttextfile{#1}%
+ \processfile{#1}%
+ \dostoptextfile}
+
+\newcount\filelevel
+
+\let\currentcomponent \v!text
+\let\currentcomponentpath\f!currentpath
+
+\def\donextlevel#1#2#3#4#5#6#7\\%
+ {\pushmacro\currentcomponent
+ \pushmacro\currentcomponentpath
+ \let\currentcomponent#1%
+ \setsystemmode\currentcomponent
+ \splitfilename{#1}%
+ \ifx\splitoffpath\empty
+ \let\currentcomponentpath\f!currentpath
+ \else
+ \let\currentcomponentpath\splitoffpath
+ \fi
+ \beforesplitstring#7\at.\to#2\relax % can become path + base
+ \ifcase\filelevel\relax
+ \starttext
+ \def\project ##1 {#3{##1}}%
+ \def\environment ##1 {#4{##1}}%
+ \def\product ##1 {#5{##1}}%
+ \def\component ##1 {#6{##1}}%
+ \fi
+ \advance\filelevel\plusone
+ \fullexpandoneargafter\addtocommalist{#1}\loadedfiles}
+
+\def\doprevlevel
+ {\popmacro\currentcomponentpath
+ \popmacro\currentcomponent
+ \setsystemmode\currentcomponent
+ \ifnum\filelevel=\plusone
+ \expandafter\stoptext
+ \else
+ \advance\filelevel\minusone
+ \expandafter\endinput
+ \fi}
+
+\unexpanded\def\startproject #1 %
+ {\donextlevel\v!project\currentproject
+ \donotexecutefile\doexecutefileonce
+ \doexecutefileonce\doexecutefile#1\\}
+
+\unexpanded\def\startproduct #1 %
+ {\doateverystarttext
+ \donextlevel\v!product\currentproduct
+ \doexecutefileonce\doexecutefileonce
+ \donotexecutefile\doexecutefile#1\\}
+
+\unexpanded\def\startcomponent #1 %
+ {\doateverystarttext
+ \donextlevel\v!component\currentcomponent
+ \doexecutefileonce\doexecutefileonce
+ \donotexecutefile\doexecutefile#1\\}
+
+\unexpanded\def\startenvironment #1 %
+ {\donextlevel\v!environment\currentenvironment
+ \donotexecutefile\doexecutefileonce
+ \donotexecutefile\donotexecutefile#1\\}
+
+% \startproject test
+% 1: \startmode[*project] project \stopmode \endgraf
+% 2: \startmode[*product] product \stopmode \endgraf
+% \stopproject
+
+\unexpanded\def\stopproject {\doprevlevel}
+\unexpanded\def\stopproduct {\doprevlevel}
+\unexpanded\def\stopcomponent {\doprevlevel}
+\unexpanded\def\stopenvironment{\doprevlevel}
+
+% more or less replaced by modes
+
+\setvalue{\e!start\v!localenvironment}[#1]%
+ {\let\loadedlocalenvironments\empty
+ \def\docommand##1%
+ {\beforesplitstring##1\at.\to\someevironment
+ \fullexpandoneargafter\addtocommalist\someevironment\loadedlocalenvironments}%
+ \processcommalist[#1]\docommand
+ \fullexpandtwoargsafter\doifcommonelse % no longer next needed
+ {\currentproject,\currentproduct,%
+ \currentcomponent,\currentenvironment}
+ {\loadedlocalenvironments}
+ {\letvalue{\e!stop\v!localenvironment}\relax}
+ {\grabuntil{\e!stop\v!localenvironment}\gobbleoneargument}} % TH: fixed, was \relax
+
+\setvalue{\v!localenvironment}#1 {\doexecutefileonce{#1}}
+
+% NOT TOEVOEGEN: \the\everytrace
+
+\neverypar\emptytoks
+
+% \appendtoks \flushnotes \to \everypar
+% \appendtoks \synchronizesidefloats \to \everypar
+% \appendtoks \checkindentation \to \everypar
+% \appendtoks \showparagraphnumber \to \everypar
+% \appendtoks \flushmargincontents \to \everypar
+% \appendtoks \flushcommentanchors \to \everypar
+% \appendtoks \synchronizenotes \to \everypar
+
+% \appendtoks \flushnotes \to \everydisplay
+% \appendtoks \adjustsidefloatdisplaylines \to \everydisplay
+
+\protect \endinput
diff --git a/tex/context/base/core-mis.mkii b/tex/context/base/core-mis.mkii
new file mode 100644
index 000000000..98079830d
--- /dev/null
+++ b/tex/context/base/core-mis.mkii
@@ -0,0 +1,2742 @@
+%D \module
+%D [ file=core-mis,
+%D version=1998.01.29,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Miscelaneous,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Misc Commands}
+
+% todo: kleur in legenda + letter
+
+% %D You would not expect the next macro in \CONTEXT,
+% %D wouldn't you? It's there to warn \LATEX\ users that
+% %D something is wrong.
+% %D
+% %D Obsolete now:
+% %
+% % \def\documentstyle{\showmessage\m!systems3\empty\stoptekst}
+% %
+% % \let\documentclass=\documentstyle
+% %D \macros
+% %D {simplifiedcommands, simplifycommands}
+% %D
+% %D I first needed this simplification in bookmarks. Users can
+% %D add their own if needed.
+
+\unprotect
+
+%D Sometimes (for instance in bookmarks) we need to simplify macro
+%D behaviour, so here is the hook.
+
+\ifx\simplifiedcommands\undefined \newtoks\simplifiedcommands \fi
+
+\def\simplifycommands{\the\simplifiedcommands}
+
+%D A possibly growing list:
+
+%appendtoks \def\executesynonym#1#2#3#4{#3}\to\simplifiedcommands
+%appendtoks \def\executesort#1#2#3{#3}\to\simplifiedcommands
+
+\appendtoks \def\ { }\to\simplifiedcommands
+\appendtoks \def\type#1{\letterbackslash\strippedcsname#1}\to\simplifiedcommands
+\appendtoks \def\tex#1{\letterbackslash#1}\to\simplifiedcommands
+\appendtoks \def\TeX{TeX}\to\simplifiedcommands
+\appendtoks \def\ConTeXt{ConTeXt}\to\simplifiedcommands
+\appendtoks \def\MetaPost{MetaPost}\to\simplifiedcommands
+\appendtoks \def\MetaFont{MetaFont}\to\simplifiedcommands
+\appendtoks \def\MetaFun{MetaFun}\to\simplifiedcommands
+%appendtoks \def||{-}\to\simplifiedcommands
+\appendtoks \def|#1|{\ifx#1\empty\empty-\else#1\fi}\to\simplifiedcommands
+
+\appendtoks\let\buildtextaccent\secondoftwoarguments\to\simplifiedcommands
+
+% THIS WAS MAIN-002.TEX
+
+%\def\checkinterlineskip
+% {\ifvmode
+% \ifdim\lastskip>\zeropoint
+% \nointerlineskip
+% \else\ifdim\lastkern>\zeropoint
+% \nointerlineskip
+% \fi\fi
+% \fi}
+
+\def\horitems#1#2% #1=breedte #2=commandos
+ {\scratchdimen#1%
+ \divide\scratchdimen \nofitems
+ \!!counta\zerocount
+ \def\docommand##1%
+ {\advance\!!counta \plusone
+ \processaction
+ [\@@isalign]
+ [ \v!left=>\hbox to \scratchdimen{\strut##1\hss},
+ \v!right=>\hbox to \scratchdimen{\hss\strut##1},
+ \v!middle=>\hbox to \scratchdimen{\hss\strut##1\hss},
+ \v!margin=>\ifnum\!!counta=\plusone\hss\else\hfill\fi
+ \strut##1%
+ \ifnum\!!counta=\nofitems\hss\else\hfill\fi,
+ \s!default=>\hbox to \scratchdimen{\hss\strut##1\hss}, % midden
+ \s!unknown=>\hbox to \scratchdimen{\strut##1\hss}]}% % links
+ \hbox to #1{\hss#2\hss}}
+
+\def\veritems#1#2% #1=breedte #2=commandos
+ {\scratchdimen#1%
+ \def\docommand##1%
+ {\ifdim\scratchdimen<\zeropoint % the - was a signal
+ \hbox to -\scratchdimen{\hss\strut##1}%
+ \else\ifdim\scratchdimen>\zeropoint
+ \hbox to \scratchdimen{\strut##1\hss}%
+ \else
+ \hbox{\strut##1}%
+ \fi\fi}%
+ \vbox{#2}}
+
+\def\dosetupitems[#1]%
+ {\getparameters[\??is][#1]%
+ \doif\@@iswidth\v!unknown
+ {\def\@@iswidth{\hsize}}%
+ \doifconversiondefinedelse\@@issymbol
+ {\def\doitembullet##1{\convertnumber{\@@issymbol}{##1}}}
+ {\doifsymboldefinedelse\@@issymbol
+ {\def\doitembullet##1{\symbol[\@@issymbol]}}{}}}
+
+\def\makeitemsandbullets#1%
+ {\doifelse\@@isn\v!unknown
+ {\getcommalistsize[#1]%
+ \edef\nofitems{\commalistsize}}
+ {\edef\nofitems{\@@isn}}%
+ \setbox0\hbox
+ {\doitems \@@iswidth
+ {\processcommalist[#1]\docommand}}%
+ \setbox2\hbox
+ {\doitems \@@isbulletbreedte
+ {\dorecurse\nofitems
+ {\docommand{\strut\doitembullet\recurselevel}}}}}
+
+\def\dostartitems#1#2#3%
+ {\let\doitems#2%
+ \def\@@isbulletbreedte{#3}%
+ \makeitemsandbullets{#1}%
+ \@@isbefore}
+
+\def\dostopitems
+ {\@@isafter
+ \egroup}
+
+\setvalue{doitems\v!top}#1%
+ {\dostartitems{#1}\horitems\@@iswidth
+ \noindent\vbox
+ {\forgetall
+ \doifsomething\@@issymbol
+ {\doifnot\@@issymbol\v!none
+ {\box2
+ \@@isinbetween
+ \nointerlineskip}}%
+ \box0}%
+ \dostopitems}
+
+\setvalue{doitems\v!bottom}#1%
+ {\dostartitems{#1}\horitems\@@iswidth
+ \noindent\vbox
+ {\forgetall
+ \box0
+ \doifsomething\@@issymbol
+ {\@@isinbetween
+ \nointerlineskip
+ \box2}}%
+ \dostopitems}
+
+\setvalue{doitems\v!inmargin}#1%
+ {\dostartitems{#1}\veritems{-1.5em}% - is a signal
+ \noindent\hbox{\llap{\box2\hskip\leftmargindistance}\box0}%
+ \dostopitems}
+
+\setvalue{doitems\v!left}#1%
+ {\advance\hsize -1.5em%
+ \dostartitems{#1}\veritems{1.5em}%
+ \noindent\hbox{\box2\box0}%
+ \dostopitems}
+
+\setvalue{doitems\v!right}#1%
+ {\dostartitems{#1}\veritems{0em}%
+ \noindent\hbox{\box0\hskip-\wd2\box2}%
+ \dostopitems}
+
+\def\setupitems
+ {\dosingleargument\dosetupitems}
+
+\def\complexitems[#1]%
+ {\bgroup
+ \setupitems[#1]%
+ \parindent\zeropoint
+ \setlocalhsize
+ \hsize\localhsize
+ \dontcomplain
+ %\doifundefined{doitems\@@islocation}%
+ % {\let\@@islocation\v!left}%
+ %\getvalue{doitems\@@islocation}}
+ \executeifdefined{doitems\@@islocation}{\let\@@islocation\v!left}}
+
+\definecomplexorsimpleempty\items
+
+\setupitems
+ [\c!location=\v!left,
+ \c!symbol=5,
+ \c!width=\hsize,
+ \c!align=\v!middle,
+ \c!n=\v!unknown,
+ \c!before=\blank,
+ \c!inbetween={\blank[\v!medium]},
+ \c!after=\blank]
+
+% \definieerplaats[naam][instellingen]
+% \stelplaatsin[naam][instellingen]
+% \plaats[[instellingen]]
+%
+% - still undocumented and also not in setupb yet
+% - kan ook intern/direct (scheelt duplicatie), zie \framedtext
+
+\def\dodefineplacement[#1][#2]%
+ {\getparameters
+ [\??pl#1]
+ [\c!left=\hss,
+ \c!right=\hss,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ \c!margin=\v!standard,
+ \c!grid=\v!middle,
+ %\c!before=,
+ %\c!after=,
+ #2]%
+ \setvalue{\e!place#1}{\doplacement[\??pl#1]}}
+
+\def\defineplacement
+ {\dodoubleempty\dodefineplacement}
+
+\def\setupplacement
+ {\dodoubleempty\dosetupplacement}
+
+\def\dosetupplacement[#1]%
+ {\dodoubleempty\getparameters[\??pl#1]}
+
+\def\doplacement
+ {\dodoubleempty\dodoplacement}
+
+\def\dodoplacement[#1][#2]% correctie moet mooier
+ {\bgroup
+ \dowithnextboxcontent
+ {\forgetall}
+ {\setlocalhsize
+ \getparameters[#1][#2]%
+ \getvalue{#1\c!before}%
+ \begingroup
+ \disableparpositions
+ \setbox\nextbox\hbox to \localhsize
+ {\getvalue{#1\c!left}%
+ \flushnextbox
+ \getvalue{#1\c!right}}%
+ \ifinsidefloat \else
+ \addlocalbackgroundtobox\nextbox
+ \fi
+ \ifgridsnapping
+ \doifundefined{#1\c!grid}{\letvalue{#1\c!grid}\v!middle}%
+ % unchecked
+ \doifinset{\getvalue{#1\c!margin}}{\v!standard,\v!yes}\noindent
+ \snaptogrid[\getvalue{#1\c!grid}]\hbox{\flushnextbox}%
+ \else
+ \doifvalue{#1\c!linecorrection}\v!on \startbaselinecorrection
+ \doifinset{\getvalue{#1\c!margin}}{\v!standard,\v!yes}\noindent
+ \flushnextbox
+ \doifvalue{#1\c!depthcorrection}\v!on\baselinecorrection
+ \doifvalue{#1\c!linecorrection }\v!on\stopbaselinecorrection
+ \fi
+ \endgroup
+ \getvalue{#1\c!after}%
+ \egroup}
+ \vbox}
+
+% Te zijner tijd [plaats=boven,onder,midden] implementeren,
+% in dat geval moet eerst de maximale hoogte worden bepaald.
+%
+% Overigens kan een en ander mooier met \halign.
+
+% there is quite some historic balast in this mechanism, the next variant
+% is a first cleanup
+
+\let\currentparagraph\empty
+
+\newcount\alcounter \newcount\alnsize \newdimen\alhsize
+
+\def\paragraphparameter#1% \checkedparameter\??al\currentparagraph#1
+ {\executeifdefined{\??al\currentparagraph#1}{\executeifdefined{\??al#1}\empty}}
+
+\def\paragraphcellmeter#1#2% \checkedparameter\??al\currentparagraph#1
+ {\executeifdefined{\??al\currentparagraph\number#1#2}{\paragraphparameter{#2}}}
+
+\def\dodefineparagraphs[#1][#2]%
+ {\edef\currentparagraph{#1}%
+ \setvalue{\s!do\s!next\currentparagraph}%
+ {\def\\{\getvalue\currentparagraph}}%
+ \setvalue\currentparagraph
+ {\getvalue{\s!do\s!next#1}%
+ \dostartparagraphs{#1}}%
+ \setvalue{\e!next\currentparagraph}%
+ {\getvalue{#1}}%
+ \setvalue{\e!start\currentparagraph}%
+ {\bgroup
+ \edef\currentparagraph{#1}%
+ \letvalue{\s!do\s!next\currentparagraph}\empty
+ \setvalue{\e!stop\currentparagraph}{\getvalue\currentparagraph\egroup}%
+ \getvalue\currentparagraph}%
+ \getparameters[\??al\currentparagraph]%
+ [%\c!n=3,
+ %\c!before=\blank,
+ %\c!after=\blank,
+ %\c!distance=1em,
+ %\c!height=\v!fit,
+ %\c!rule=\v!off,
+ %\c!command=,
+ %\c!align=,
+ %\c!tolerance=\v!tolerant,
+ %\c!rulethickness=\linewidth,
+ %\c!rulecolor=,
+ %\c!style=,
+ %\c!color=,
+ %\c!top=,
+ %\c!top=\vss,
+ %\c!bottom=\vfill,
+ #2]%
+ \setvalue{\e!setup#1\e!endsetup}%
+ {\setupparagraphs[#1]}%
+ \dorecurse
+ {\paragraphparameter\c!n}
+ {\setupparagraphs
+ [\currentparagraph]
+ [\recurselevel]
+ [\c!width=,
+ %\c!bottom=\paragraphparameter\c!bottom,
+ %\c!top=\paragraphparameter\c!top,
+ %\c!height=\paragraphparameter\c!height,
+ %\c!rule=\paragraphparameter\c!rule,
+ %\c!rulethickness=\paragraphparameter\c!rulethickness,
+ %\c!rulecolor=\paragraphparameter\c!rulecolor,
+ %\c!align=\paragraphparameter\c!align,
+ %\c!tolerance=\paragraphparameter\c!tolerance, % obsolete
+ %\c!distance=\paragraphparameter\c!distance,
+ \c!style=\paragraphparameter\c!style,
+ \c!color=\paragraphparameter\c!color]}%
+ \setupparagraphs[\currentparagraph][1][\c!distance=\zeropoint]}
+
+\def\defineparagraphs
+ {\dodoubleargument\dodefineparagraphs}
+
+\def\dosetupparagraphs[#1][#2][#3]%
+ {\edef\currentparagraph{#1}%
+ \ifsecondargument
+ \doifelse{#2}\v!each
+ {\dorecurse
+ {\paragraphparameter\c!n}
+ {\getparameters[\??al\currentparagraph\recurselevel][#3]}}
+ {\doifelsenothing{#3}
+ {\getparameters[\??al\currentparagraph][#2]}
+ {\def\docommand##1{\getparameters[\??al\currentparagraph##1][#3]}%
+ \processcommalist[#2]\docommand}}%
+ \else
+ \getparameters[\??al][#1]%
+ \fi}
+
+\def\setupparagraphs
+ {\dotripleempty\dosetupparagraphs}
+
+\setupparagraphs
+ [\c!n=3,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance=1em,
+ \c!height=\v!fit,
+ \c!rule=\v!off,
+ \c!command=,
+ \c!align=,
+ \c!tolerance=\v!tolerant, % obsolete
+ \c!rulethickness=\linewidth,
+ \c!rulecolor=,
+ \c!style=,
+ \c!color=,
+ \c!top=,
+ \c!top=\vss,
+ \c!bottom=\vfill]
+
+\def\doparagraphrule
+ {\doifelse{\paragraphcellmeter\alcounter\c!rule}\v!on
+ {\linewidth\paragraphcellmeter\alcounter\c!rulethickness
+ \scratchdimen\paragraphcellmeter\alcounter\c!distance
+ \advance\scratchdimen-\linewidth
+ \divide\scratchdimen \plustwo
+ \hskip\scratchdimen
+ \color[\paragraphcellmeter\alcounter\c!rulecolor]{\vrule\!!width\linewidth}%
+ \hskip\scratchdimen}
+ {\hskip\paragraphcellmeter\alcounter\c!distance}}
+
+\def\dostartparagraph
+ {\doifelsenothing{\paragraphcellmeter\alcounter\c!width}
+ {\!!widtha\alhsize
+ \divide\!!widtha \alnsize}
+ {\!!widtha\paragraphcellmeter\alcounter\c!width}%
+ \dostartattributes{\??al\currentparagraph\number\alcounter}\c!style\c!color\empty
+ \doifelse{\paragraphcellmeter\alcounter\c!height}\v!fit
+ {\setbox\scratchbox\vtop}
+ {\setbox\scratchbox\vtop to \paragraphcellmeter\alcounter\c!height}%
+ \bgroup
+ \blank[\v!disable]%
+ \forgetall
+ \paragraphcellmeter\alcounter\c!top
+ \paragraphparameter\c!inner
+ \hsize\!!widtha % setting \wd afterwards removed
+ \paragraphcellmeter\alcounter\c!inner % twice
+ \expanded{\setupalign [\paragraphcellmeter\alcounter\c!align ]}% {normal,verytolerant,stretch}
+ \expanded{\setuptolerance[\paragraphcellmeter\alcounter\c!tolerance]}% obsolete
+ \ignorespaces
+ \endgraf
+ \ignorespaces
+ %
+ % Nadeel van de onderstaande constructie is dat \everypar
+ % binnen een groep kan staan en zo steeds \begstruts
+ % worden geplaatst. Mooi is anders dus moet het anders!
+ %
+ % Hier is \Everypar niet nodig.
+ %
+ \everypar{\begstrut\everypar\emptytoks}%
+ %
+ \nospace % remove + ignore
+ \paragraphcellmeter\alcounter\c!command}
+
+\def\dostopparagraph
+ {\ifvmode
+ \removelastskip
+ \else
+ \unskip\endstrut\endgraf
+ \fi
+ \paragraphcellmeter\alcounter\c!bottom
+ \egroup
+ \ifdim\wd\scratchbox=\zeropoint % no data
+ \wd\scratchbox\!!widtha
+ \fi
+ \box\scratchbox
+ \dostopattributes
+ \ifnum\alcounter<\paragraphparameter\c!n\relax
+ \@EA\doparagraphcell
+ \else
+ \@EA\dostopparagraphs
+ \fi}
+
+\def\doparagraphcell
+ {\global\advance\alcounter \plusone
+ \doifelsenothing{\paragraphcellmeter\alcounter\c!distance}
+ {\ifnum\alcounter=\plusone\else
+ \hskip\paragraphparameter\c!distance
+ \fi}
+ {\ifnum\alcounter=\plusone
+ \hskip\paragraphcellmeter\alcounter\c!distance
+ \else
+ \doparagraphrule
+ \fi}%
+ \letvalue\currentparagraph\dostopparagraph
+ \dostartparagraph}
+
+\def\dostartparagraphs#1%
+ {\bgroup
+ \edef\currentparagraph{#1}%
+ \global\alcounter\zerocount
+ \parindent\zeropoint
+ \setlocalhsize
+ \alhsize\localhsize
+ \alnsize\paragraphparameter\c!n\relax
+ \dorecurse \alnsize
+ {\doifelsenothing{\paragraphcellmeter\recurselevel\c!distance}
+ {\ifnum\recurselevel=\plusone\else
+ \global\advance\alhsize -\paragraphparameter\c!distance
+ \fi}
+ {\global\advance\alhsize -\paragraphcellmeter\recurselevel\c!distance}%
+ \doifsomething{\paragraphcellmeter\recurselevel\c!width}
+ {\global\advance\alnsize \minusone
+ \global\advance\alhsize -\paragraphcellmeter\recurselevel\c!width}}%
+ %whitespace % gaat fout bij \framed
+ \paragraphparameter\c!before
+ \leavevmode % gaat wel goed bij \framed, brrr
+ \setbox\scratchbox\vbox\bgroup\hbox\bgroup\doparagraphcell}
+
+\def\dostopparagraphs
+ {\egroup
+ \egroup
+ \iftrue
+ \hbox{\raise\strutheight\box\scratchbox}% new
+ \else
+ \box\scratchbox % old
+ \fi
+ \par
+ \paragraphparameter\c!after
+ \egroup}
+
+\def\dosetuptab[#1]%
+ {\getparameters[\??ta]
+ [\c!headstyle=\v!normal,
+ \c!headcolor=,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!width=\v!broad,
+ \c!sample={\hskip4em},
+ \c!before=,
+ \c!after=,
+ #1]%
+ \definedescription
+ [tab]
+ [\c!headstyle=\@@taheadstyle,
+ \c!headcolor=\@@tacolor,
+ \c!sample=\@@tasample,
+ \c!width=\@@tawidth,
+ \c!before=\@@tabefore,
+ \c!after=\@@taafter]}
+
+\def\setuptab
+ {\dosingleargument\dosetuptab}
+
+\setuptab
+ [\c!location=\v!left]
+
+% The following macro's are derived from PPCHTEX and
+% therefore take some LaTeX font-switching into account.
+
+\newif\ifloweredsubscripts
+
+% Due to some upward incompatibality of LaTeX to LaTeX2.09
+% and/or LaTeX2e we had to force \@@chemieletter. Otherwise
+% some weird \nullfont error comes up.
+
+\doifundefined{@@chemieletter}{\def\@@chemieletter{\rm}}
+
+\def\beginlatexmathmodehack
+ {\ifmmode
+ \let\endlatexmathmodehack\relax
+ \else
+ \def\endlatexmathmodehack{$}$\@@chemieletter
+ \fi}
+
+\def\setsubscripts
+ {\beginlatexmathmodehack
+ \def\dosetsubscript##1##2##3%
+ {\dimen0=##3\fontexheight##2%
+ \setxvalue{@@\string##1\string##2}{\the##1##2\relax}%
+ ##1##2=\dimen0\relax}%
+ \def\dodosetsubscript##1##2%
+ {\dosetsubscript{##1}{\textfont2}{##2}%
+ \dosetsubscript{##1}{\scriptfont2}{##2}%
+ \dosetsubscript{##1}{\scriptscriptfont2}{##2}}%
+ %dodosetsubscript\mathsupnormal {?}%
+ \dodosetsubscript\mathsubnormal {.7}%
+ \dodosetsubscript\mathsubcombined{.7}%
+ \global\loweredsubscriptstrue
+ \endlatexmathmodehack}
+
+\def\resetsubscripts
+ {\ifloweredsubscripts
+ \beginlatexmathmodehack
+ \def\doresetsubscript##1##2%
+ {\dimen0=\getvalue{@@\string##1\string##2}\relax
+ ##1##2=\dimen0}%
+ \def\dodoresetsubscript##1%
+ {\doresetsubscript{##1}{\textfont2}%
+ \doresetsubscript{##1}{\scriptfont2}%
+ \doresetsubscript{##1}{\scriptscriptfont2}}%
+ %dodoresetsubscript\mathsupnormal
+ \dodoresetsubscript\mathsubnormal
+ \dodoresetsubscript\mathsubcombined
+ \global\loweredsubscriptsfalse
+ \endlatexmathmodehack
+ \fi}
+
+\let\beginlatexmathmodehack = \relax
+\let\endlatexmathmodehack = \relax
+
+\def\chem#1#2#3%
+ {\bgroup
+ \setsubscripts
+ \mathematics{\hbox{#1}_{#2}^{#3}}%
+ \resetsubscripts
+ \egroup}
+
+\unexpanded\def\celsius #1{#1\mathematics{^\circ}C}
+\unexpanded\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax}
+\unexpanded\def\fraction#1#2{\mathematics{#1\over#2}}
+
+% very dutch
+
+\unexpanded\def\graden {\mathematics{^\circ}}
+
+\def\bedragprefix {\euro\normalfixedspace}
+\def\bedragsuffix {}
+\def\bedragempty {\euro}
+
+\unexpanded\def\bedrag#1%
+ {\strut\hbox\bgroup
+ \let\normalfixedspace\nonbreakablespace
+ \doifelsenothing{#1}
+ {\bedragempty}
+ {\bedragprefix\digits{#1}\bedragsuffix}%
+ \egroup}
+
+% \definieeralineas[test][n=3]
+%
+% \stelalineasin[test][3][breedte=4cm,uitlijnen=links]
+%
+% \startopelkaar
+% \test hans \\ ton \\ \bedrag{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{~.~~1,--} \\
+% \test hans \\ ton \\ \bedrag{~.~~1,~~} \\
+% \test hans \\ ton \\ \bedrag{~.100,--} \\
+% \test hans \\ ton \\ \subtot{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{1.000,--} \\
+% \test hans \\ ton \\ \totaal{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{nihil,--} \\
+% \test hans \\ ton \\ \totaal{nihil,--} \\
+% \test hans \\ ton \\ \subtot{nihil,--} \\
+% \stopopelkaar
+
+\def\periodswidth {.5em}
+\def\periodsdefault{3} % was 5, but now it's like \unknown
+
+\unexpanded\def\periods
+ {\dosingleempty\doperiods}
+
+\def\doperiods[#1]%
+ {\dontleavehmode
+ \begingroup
+ \scratchdimen\periodswidth
+ \hbox to \iffirstargument#1\else\periodsdefault\fi \scratchdimen
+ {\leaders\hbox to \scratchdimen{\hss.\hss}\hss}%
+ \endgroup}
+
+\unexpanded\def\unknown
+ {\periods\relax} % relax prevents lookahead for []
+
+% compatibility macros
+
+\def\doorsnede
+ {\hbox{\rlap/$\circ$} }
+
+\unexpanded\def\ongeveer
+ {\mathematics\pm}
+
+\chardef\boundarycharactermode\plusone
+
+\def\midboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \languageparameter#1%
+ %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \or
+ \languageparameter#1%
+ \fi
+ \chardef\boundarycharactermode\plusone}
+
+\def\leftboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \languageparameter#1%
+ \nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \or
+ \languageparameter#1%
+ \fi
+ \chardef\boundarycharactermode\plusone}
+
+\def\rightboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \prewordbreak %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \languageparameter#1%
+ \or
+ \languageparameter#1%
+ \fi
+ \chardef\boundarycharactermode\plusone}
+
+% actually this is pretty old, but temporary moved here
+%
+% obsolete:
+
+\def\setuphyphenmark
+ {\dodoubleargument\getparameters[\??kp]}
+
+\def\setuphyphenmark[#1]% sign=normal|wide
+ {\dodoubleargument\getparameters[\??kp][#1]%
+ \doifinsetelse\@@kpsign {\v!normal}
+ {\let\textmodehyphen\normalhyphen \let\textmodehyphendiscretionary\normalhyphendiscretionary}
+ {\let\textmodehyphen\composedhyphen\let\textmodehyphendiscretionary\composedhyphendiscretionary}}
+
+\setuphyphenmark[\c!sign=\v!wide]
+% % \setuphyphenmark[\c!sign=\v!normal]
+
+\definesymbol[\c!lefthyphen] [\languageparameter\c!lefthyphen]
+\definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen]
+\definesymbol[\c!hyphen] [\languageparameter\c!hyphen]
+
+\def\normalhyphen
+ {\hbox{\directsymbol\empty\c!hyphen}}
+
+\def\composedhyphen
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}
+
+\def\normalhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!lefthyphen}}
+ {\hbox{\directsymbol\empty\c!righthyphen}}
+ {\hbox{\directsymbol\empty\c!hyphen}}}
+
+\def\composedhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}}
+
+\let\textmodehyphen \composedhyphen
+\let\textmodehyphendiscretionary\composedhyphendiscretionary
+
+\definesymbol[\c!leftcompoundhyphen] [\languageparameter\c!leftcompoundhyphen]
+\definesymbol[\c!rightcompoundhyphen] [\languageparameter\c!rightcompoundhyphen]
+\definesymbol[\c!compoundhyphen] [\languageparameter\c!compoundhyphen]
+
+\definehspace [sentence] [\zeropoint]
+\definehspace [intersentence] [.250em]
+
+\definesymbol
+ [\c!midsentence]
+ [\midboundarycharacter\c!midsentence{sentence}]
+
+\definesymbol
+ [\c!leftsentence]
+ [\leftboundarycharacter\c!leftsentence{sentence}]
+
+\definesymbol
+ [\c!rightsentence]
+ [\rightboundarycharacter\c!rightsentence{sentence}]
+
+\definesymbol
+ [\c!leftsubsentence]
+ [\leftboundarycharacter\c!leftsubsentence{sentence}]
+
+\definesymbol
+ [\c!rightsubsentence]
+ [\rightboundarycharacter\c!rightsubsentence{sentence}]
+
+\newsignal \subsentencesignal
+\newcounter\subsentencelevel
+
+\let\beforesubsentence\donothing
+\let\aftersubsentence \donothing
+
+% todo: make this language option
+%
+% \def\beforesubsentence{\removeunwantedspaces}
+% \def\aftersubsentence {\ignorespaces}
+
+\def\midsentence
+ {\symbol[\c!midsentence]}
+
+\def\beginofsubsentence
+ {\beforesubsentence
+ \ifdim\lastkern=\subsentencesignal
+ \unskip
+ \kern\hspaceamount\currentlanguage{intersentence}%
+ \fi
+ \doglobal\increment\subsentencelevel
+ \ifnum\subsentencelevel=\plusone
+ \dontleavehmode % was \leaveoutervmode
+ \fi
+ \symbol[\ifodd\subsentencelevel\c!leftsentence\else\c!leftsubsentence\fi]%
+ }% \ignorespaces}
+
+\def\endofsubsentence % relax prevents space gobbling
+ {\symbol[\ifodd\subsentencelevel\c!rightsentence\else\c!rightsubsentence\fi]%
+ \doglobal\decrement\subsentencelevel
+ \unskip
+ \kern\subsentencesignal\relax
+ \aftersubsentence}
+
+\def\beginofsubsentencespacing % relax prevents space gobbling
+ {\kern\subsentencesignal\relax}% \ignorespaces}
+
+\def\endofsubsentencespacing
+ {\ifdim\lastkern=\subsentencesignal
+ \unskip
+ \hskip\hspaceamount\currentlanguage{intersentence}%
+ % no good, actually language dependent:
+% \ignorespaces
+ \else
+ \unskip
+ \fi}
+
+%D \startbuffer
+%D test |<|test |<|test|>| test|>| test \par
+%D test|<|test|<|test|>|test|>|test \par
+%D test |<||<|test|>||>| test \par
+%D test \directdiscretionary{<}test\directdiscretionary{>} test \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\def\startsubsentence{\beginofsubsentence \prewordbreak\beginofsubsentencespacing}
+\def\stopsubsentence {\endofsubsentencespacing\prewordbreak\endofsubsentence}
+
+%D \defineXMLenvironment [subsentence]
+%D {|<|}
+%D {|>|}
+%D \defineXMLenvironment [subsentence]
+%D {\directdiscretionary{<}}
+%D {\directdiscretionary{>}}
+%D \defineXMLenvironment [subsentence]
+%D {\startsubsentence}
+%D {\stopsubsentence}
+%D
+%D \startbuffer
+%D test test test
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \processXMLbuffer
+
+\enableactivediscretionaries
+
+\definehspace [quotation] [\zeropoint]
+\definehspace [interquotation] [.125em]
+
+%definehspace [quote] [\zeropoint]
+%definehspace [speech] [\zeropoint]
+
+\definehspace [quote] [\hspaceamount\currentlanguage{quotation}]
+\definehspace [speech] [\hspaceamount\currentlanguage{quotation}]
+
+\definesymbol
+ [\c!leftquotation]
+ [\leftboundarycharacter\c!leftquotation{quotation}]
+
+\definesymbol
+ [\c!rightquotation]
+ [\rightboundarycharacter\c!rightquotation{quotation}]
+
+\definesymbol
+ [\c!leftquote]
+ [\leftboundarycharacter\c!leftquote{quote}]
+
+\definesymbol
+ [\c!rightquote]
+ [\rightboundarycharacter\c!rightquote{quote}]
+
+\definesymbol
+ [\c!leftspeech]
+ [\leftboundarycharacter\c!leftspeech{speech}]
+
+\definesymbol
+ [\c!rightspeech]
+ [\rightboundarycharacter\c!rightspeech{speech}]
+
+\definesymbol
+ [\c!middlespeech]
+ [\leftboundarycharacter\c!middlespeech{speech}]
+
+\appendtoks\def\quotation#1{"#1"}\to\simplifiedcommands
+\appendtoks\def\quote #1{'#1'}\to\simplifiedcommands
+
+%D The next features was so desperately needed by Giuseppe
+%D Bilotta that he made a module for it. Since this is a
+%D typical example of core functionality, I decided to extend
+%D the low level quotation macros in such a way that a speech
+%D feature could be build on top of it. The speech opening and
+%D closing symbols are defined per language. Italian is an
+%D example of a language that has them set.
+
+% this will replace the quotation and speed definitions
+
+\newsignal\delimitedtextsignal
+
+\let\currentdelimitedtext\s!unknown
+
+\def\delimitedtextparameter#1% will be sped up
+ {\executeifdefined{\??ci\currentdelimitedtext:\csname\??ci\currentdelimitedtext\c!level\endcsname#1}%
+ {\executeifdefined{\??ci\currentdelimitedtext#1}%
+ {\executeifdefined{\??ci#1}\empty}}}
+
+\def\definedelimitedtext
+ {\dodoubleempty\dodefinedelimitedtext}
+
+\def\dodefinedelimitedtext[#1][#2]%
+ {\doifassignmentelse{#2}
+ {\getparameters
+ [\??ci#1]
+ [\c!location=\v!margin, % \v!text \v!paragraph
+ \c!spacebefore=,
+ \c!spaceafter=\delimitedtextparameter\c!spacebefore,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\delimitedtextparameter\c!leftmargin,
+ \c!indentnext=\v!yes,
+ \c!before=,
+ \c!after=,
+ \c!left=,
+ \c!right=,
+ \c!level=0,
+ \c!repeat=\v!no,
+ \c!method=,
+ #2]}%
+ {\doifdefined{#2}
+ {\copyparameters[\??ci#1][\??ci#2]
+ [\c!location,\c!spacebefore,\c!spaceafter,\c!style,\c!color,
+ \c!leftmargin,\c!rightmargin,\c!indentnext,
+ \c!before,\c!after,\c!left,\c!right]}}%
+ \doifsomething{#1}
+ {\unexpanded\setvalue{#1}{\delimitedtext[#1]}%
+ \setvalue{\e!start#1}{\startdelimitedtext[#1]}%
+ \setvalue{\e!stop #1}{\stopdelimitedtext}}}
+
+\def\setupdelimitedtext
+ {\dotripleargument\dosetupdelimitedtext}
+
+\def\dosetupdelimitedtext[#1][#2][#3]% #2 = optional level
+ {\ifthirdargument
+ \getparameters[\??ci#1:#2][#3]%
+ \else\ifsecondargument
+ \getparameters[\??ci#1][#2]%
+ \else
+ \getparameters[\??ci][#1]%
+ \fi\fi}
+
+\def\dorepeatdelimitedtext
+ {\relax\ifcase\delimitedtextparameter\c!level\else
+ \dohandledelimitedtext\c!middle % maybe better \dohandleleftdelimitedtext
+ \fi}
+
+\let\dohandlerepeatdelimitedtext\relax
+
+\def\startdelimitedtext[#1]%
+ {\bgroup
+ \pushdelimitedtext{#1}%
+ \doifelse{\delimitedtextparameter\c!method}\s!font
+ {\def\dostopdelimitedtext
+ {\removeunwantedspaces\ignoredelimitedtext\c!right}%
+ \ignoredelimitedtext\c!left\ignorespaces}
+ {\doifelse{\delimitedtextparameter\c!repeat}\v!yes
+ {\let\dohandlerepeatdelimitedtext\dorepeatdelimitedtext}%
+ {\let\dohandlerepeatdelimitedtext\relax}%
+ \doifinsetelse{\delimitedtextparameter\c!location}{\v!paragraph,\v!margin}%
+ {\dosingleempty\dostartdelimitedtextpar}\dostartdelimitedtexttxt}}
+
+\def\dostartdelimitedtextpar[#1]%
+ {\let\dostopdelimitedtext\dostopdelimitedtextpar
+ \doifsomething{\delimitedtextparameter\c!spacebefore}
+ {\blank[\delimitedtextparameter\c!spacebefore]}%
+ \delimitedtextparameter\c!before
+ % nicer:
+ % \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+ % \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+ % backward compatible:
+ \doifelsenothing{#1}
+ {\endgraf
+ \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+ \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+ \let\dodostopdelimitedtextpar\endgraf}
+ {\startnarrower[#1]\let\dodostopdelimitedtextpar\stopnarrower}%
+ % so far
+ % \dochecknextindentation{\??ci\currentdelimitedtext}% AM: not here
+ \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color\empty
+ \leftdelimitedtextmark
+ \ignorespaces}
+
+\def\dostopdelimitedtextpar
+ {\removeunwantedspaces
+ \removelastskip
+ \rightdelimitedtextmark
+ \dostopattributes
+ \dodostopdelimitedtextpar
+ \delimitedtextparameter\c!after
+ \doifsomething{\delimitedtextparameter\c!spaceafter}
+ {\blank[\delimitedtextparameter\c!spaceafter]}%
+ \dochecknextindentation{\??ci\currentdelimitedtext}% AM: here
+ \dorechecknextindentation}% AM: This was missing!
+
+\def\dostartdelimitedtexttxt
+ {\let\dostopdelimitedtext\dostopdelimitedtexttxt
+ \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color\empty
+ \dohandleleftdelimitedtext\c!left
+ \ignorespaces}
+
+\def\dostopdelimitedtexttxt
+ {\removeunwantedspaces
+ \dohandlerightdelimitedtext\c!right
+ \dostopattributes}
+
+\def\stopdelimitedtext
+ {\dostopdelimitedtext
+ \popdelimitedtext
+ \egroup}
+
+\def\pushdelimitedtext#1%
+ {\globalpushmacro\currentdelimitedtext
+ \def\currentdelimitedtext{#1}%
+ \doglobal\incrementvalue{\??ci\currentdelimitedtext\c!level}}
+
+\def\popdelimitedtext
+ {\doglobal\decrementvalue{\??ci\currentdelimitedtext\c!level}%
+ \globalpopmacro\currentdelimitedtext}
+
+\def\delimitedtext[#1]%
+ {\pushdelimitedtext{#1}%
+ \doifelse{\delimitedtextparameter\c!method}\s!font
+ {\dofontdrivendelimited}
+ {\doifinsetelse{\delimitedtextparameter\c!location}{\v!paragraph,\v!margin}%
+ \dodelimitedtextpar\dodelimitedtexttxt}}
+
+% shortcuts
+
+\def\startdelimited{\startdelimitedtext}
+\def\stopdelimited {\stopdelimitedtext} % no let, dynamically assigned
+\def\delimited {\delimitedtext}
+
+\def\leftdelimitedtextmark
+ {\doifsomething{\delimitedtextparameter\c!left}
+ {\setbox\scratchbox\hbox{\delimitedtextparameter\c!left}%
+ \dontleavehmode
+ \doif{\delimitedtextparameter\c!location}\v!margin{\hskip-\wd\scratchbox}%
+ \box\scratchbox}}
+
+\def\rightdelimitedtextmark
+ {\doifsomething{\delimitedtextparameter\c!right}
+ {\hsmash{\delimitedtextparameter\c!right}}}
+
+% \starttext
+% \hyphenatedword{groepsvrijstellingsverordeningen}\par
+% \hyphenatedword{\quote{groepsvrijstellingsverordeningen}}\par
+% \dorecurse{100}{\hskip300pt\hskip\recurselevel pt test \quote{xxx xxxx}.\par}
+% \page \setuppapersize[A5][A4]
+% \quotation {overly beautiful pusillanimous sesquipedalian
+% longwinded} test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test
+% \stoptext
+
+\def\dohandledelimitedtext#1#2%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+% \ifdim\lastskip=\delimitedtextsignal
+% \unskip
+ \ifdim\lastkern=\delimitedtextsignal
+ \unkern
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else
+ #2%
+ \fi
+ \ifhmode % else funny pagebeaks
+ \penalty\!!tenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+% \penalty\!!tenthousand % else overfull boxes, but that's better than dangling periods
+ \kern\delimitedtextsignal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\dohandleleftdelimitedtext#1#2%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\delimitedtextsignal
+ \unkern
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else\ifdim\lastskip=\delimitedtextsignal
+ \unskip
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else
+ #2%
+ \fi\fi
+ \strut % new, needed below
+ \ifhmode % else funny pagebeaks
+ \penalty\!!tenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \hskip\delimitedtextsignal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\dohandlerightdelimitedtext#1#2%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\delimitedtextsignal
+ \unkern
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else\ifdim\lastskip=\delimitedtextsignal
+ \unskip
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else
+ #2%
+ \fi\fi
+ \ifhmode % else funny pagebeaks
+ \penalty\!!tenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \kern\delimitedtextsignal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\ignoredelimitedtext#1%
+ {\delimitedtextparameter#1}
+
+\def\handledelimitedtext#1%
+ {\dohandledelimitedtext{#1}\relax}
+
+\def\handleleftdelimitedtext#1%
+ {\dohandleleftdelimitedtext{#1}\relax}
+
+\def\handlerightdelimitedtext#1%
+ {\dohandlerightdelimitedtext{#1}\relax}
+
+\unexpanded\def\dodelimitedtextpar
+ {\dohandleleftdelimitedtext\c!left\relax
+ \groupedcommand
+ \donothing
+ {\dohandlerightdelimitedtext\c!right\removelastskip
+ \popdelimitedtext}}
+
+\unexpanded\def\dodelimitedtexttxt
+ {\doifelse{\delimitedtextparameter\c!style}\v!normal
+ \doquoteddelimited\doattributeddelimited}
+
+\def\doquoteddelimited
+ {\dohandleleftdelimitedtext\c!left\relax
+ \groupedcommand
+ \donothing
+ {\dohandlerightdelimitedtext\c!right
+ \removelastskip
+ \popdelimitedtext}}
+
+\def\doattributeddelimited
+ {\groupedcommand
+ {\dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color}
+ {\dostopattributes
+ \popdelimitedtext}}
+
+\def\dofontdrivendelimited
+ {\simplegroupedcommand
+ {\languageparameter{\c!left\currentdelimitedtext}}
+ {\languageparameter{\c!right\currentdelimitedtext}%
+ \popdelimitedtext}}
+
+% testcase for nesting:
+%
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+% \setupdelimitedtext[quotation][1][left=(,right=)]
+% \setupdelimitedtext[quotation][2][left={[},right={]}]
+% \setupdelimitedtext[quotation][3][left=\{,right=\}]
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+
+\definedelimitedtext
+ [\v!quotation]
+ [\c!left={\symbol[\c!leftquotation]},
+ \c!right={\symbol[\c!rightquotation]},
+ \c!leftmargin=\v!standard]
+
+\definedelimitedtext
+ [\v!quote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!quote]
+ [\c!location=\v!text,
+ \c!left={\symbol[\c!leftquote]},
+ \c!right={\symbol[\c!rightquote]}]
+
+\definedelimitedtext
+ [\v!blockquote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!blockquote]
+ [\c!left=,
+ \c!right=]
+
+\definedelimitedtext
+ [\v!speech][\v!quotation]
+
+\setupdelimitedtext
+ [\v!speech]
+ [\c!repeat=\v!yes,
+ \c!left={\symbol[\c!leftspeech]},
+ \c!middle={\symbol[\c!middlespeech]},
+ \c!right={\symbol[\c!rightspeech]}]
+
+% how do we call an tight quote
+%
+% \definedelimitedtext
+% [\v!quotation][\v!quotation]
+%
+% \setupdelimitedtext
+% [\v!quotation]
+% [\c!indentnext=\v!no,
+% \c!spacebefore=\v!nowhite]
+
+\def\setupquotation{\setupdelimitedtext[\v!quotation]}
+\def\setupquote {\setupdelimitedtext[\v!quote]}
+
+% seldom used, move from kernel to run time module
+
+\ifx\tfx\undefined \let\tfx\relax \fi
+
+\def\basegrid
+ {\dosingleempty\dobasegrid}
+
+\def\dobasegrid[#1]%
+ {\begingroup
+ \getparameters[\??rt]
+ [\c!x=0,\c!y=0,
+ \c!nx=10,\c!ny=10,
+ \c!dx=.5,\c!dy=.5,
+ \c!xstep=0,\c!ystep=0,
+ \c!unit=\s!cm,
+ \c!scale=1,
+ \c!factor=1,
+ \c!offset=\v!yes,
+ \c!location=\v!left,
+ #1]%
+ \startpositioning
+ \dimen0=\@@rtdx\@@rtunit\relax
+ \dimen0=\@@rtscale\dimen0\relax
+ \dimen0=\@@rtfactor\dimen0\relax
+ \multiply\dimen0 \@@rtnx\relax
+ \dimen2=\@@rtdy\@@rtunit\relax
+ \dimen2=\@@rtscale\dimen2\relax
+ \dimen2=\@@rtfactor\dimen2\relax
+ \multiply\dimen2 \@@rtny\relax
+ \def\horline
+ {\vbox
+ {\hrule
+ \!!width \dimen0
+ \!!height \linewidth
+ \!!depth \!!zeropoint}}%
+ \def\verline%
+ {\vrule
+ \!!width \linewidth
+ \!!height \dimen2
+ \!!depth \!!zeropoint}%
+ \doglobal\newcounter\@@gridc
+ \doglobal\newcounter\@@gridd
+ \doglobal\newcounter\@@gride
+ \def\setlegend##1##2##3%
+ {\gdef\@@gridc{0}%
+ \dimen0=2em\relax
+ \dimen2=##2\@@rtunit\relax
+ \dimen2=\@@rtscale\dimen2\relax
+ \dimen2=\@@rtfactor\dimen2\relax
+ \divide\dimen0 \dimen2\relax
+ \xdef\@@gride{\number\dimen0}%
+ \ifnum\@@gride>50
+ \gdef\@@gride{100}%
+ \else\ifnum\@@gride>10
+ \gdef\@@gride{50}%
+ \else\ifnum\@@gride>5
+ \gdef\@@gride{10}%
+ \else\ifnum\@@gride>1
+ \gdef\@@gride{5}%
+ \else
+ \gdef\@@gride{1}%
+ \fi\fi\fi\fi
+ \gdef\@@gridd{0}%
+ \def\legend
+ {\ifnum\@@gridd=\zerocount
+ \vbox
+ {\increment(\@@gridc,##1)%
+ \hbox to 2em{\hss\@@gridc\hss}}%
+ \global\let\@@gridd=\@@gride
+ \fi
+ \doglobal\decrement\@@gridd
+ \doglobal\increment(\@@gridc,##1)}}%
+ \def\draw##1##2##3##4##5##6##7##8##9%
+ {\setuppositioning
+ [\c!state=##8,
+ \c!xstep=\v!absolute,
+ \c!ystep=\v!absolute,
+ \c!unit=\@@rtunit,
+ \c!scale=\@@rtscale,
+ \c!factor=\@@rtfactor,
+ \c!offset=\@@rtoffset,
+ \c!xoffset=##6,
+ \c!yoffset=##7]%
+ \doifelse{##9}\v!middle
+ {\scratchdimen##3pt\scratchdimen.5\scratchdimen
+ \edef\@@psxx{\withoutpt\the\scratchdimen}%
+ \scratchdimen##4pt\scratchdimen.5\scratchdimen
+ \edef\@@psyy{\withoutpt\the\scratchdimen}%
+ \scratchcounter##2\advance\scratchcounter -1
+ \edef\@@pszz{\the\scratchcounter}}
+ {\edef\@@psxx{0}\edef\@@psyy{0}\edef\@@pszz{##2}}%
+ \position(\@@psxx,\@@psyy){##1}%
+ \setuppositioning
+ [\c!state=##8,
+ \c!xstep=\v!relative,
+ \c!ystep=\v!relative,
+ \c!scale=\@@rtscale,
+ \c!factor=\@@rtfactor,
+ \c!offset=\@@rtoffset,
+ \c!unit=\@@rtunit]%
+ \dorecurse\@@pszz{\position(##3,##4){##5}}}%
+ \draw
+ \verline\@@rtnx\@@rtdx0\verline\!!zeropoint\!!zeropoint\v!start\empty
+ \draw
+ \horline\@@rtny0\@@rtdy\horline\!!zeropoint\!!zeropoint\v!start\empty
+ \tfx
+ \doifnot\@@rtxstep{0}
+ {\setlegend\@@rtxstep\@@rtdx\@@rtx
+ \draw\legend\@@rtnx\@@rtdx0\legend{-1em}{-1.5em}\v!overlay\@@rtlocation}%
+ \doifnot\@@rtystep{0}
+ {\setlegend\@@rtystep\@@rtdy\@@rty
+ \draw\legend\@@rtny0\@@rtdy\legend{-2em}{-.75ex}\v!overlay\@@rtlocation}%
+ \stoppositioning
+ \endgroup}
+
+\let\grid\basegrid
+
+% Dit wordt:
+%
+% \doorverwijzen[naam][instellingen] enz.
+%
+% waarbij bijvoorbeeld publicatie is. Dit levert:
+%
+% \start
+% \stop
+%
+% \beginvan
+% \eindvan
+%
+% \publicatie
+%
+% \volledigelijstmetpublicaties
+%
+% eigenlijk kan ook door... zo worden uitgebreid!
+
+% old, will become obsolete or module, replace by bib module
+
+% \defineenumeration
+% [@publicatie]
+% [\c!location=\v!left,
+% \c!width=\@@pbwidth,\c!hang=,\c!sample=,
+% \c!before=\@@pbbefore,\c!after=\@@pbafter,\c!inbetween=,
+% \c!headstyle=\@@pbheadstyle,\c!style=,
+% \c!headcolor=\@@pbheadcolor,\c!color=,
+% \c!way=\@@pbway,\c!blockway=\@@pbblockway,
+% \c!text=,\c!left=\@@pbleft,\c!right=\@@pbright]
+
+% \def\dosetuppublications[#1]%
+% {\getparameters[\??pb][#1]}
+%
+% \def\setuppublications%
+% {\dosingleargument\dosetuppublications}
+%
+% \def\apa@publicatie
+% {\doifsomething\@@pb@naam {\@@pb@naam,\space}%
+% \doifsomething\@@pb@titel {{\sl\@@pb@titel}.\space}%
+% \doifsomething\@@pb@jaar {(\@@pb@jaar).\space}%
+% \doifsomething\@@pb@plaats {\@@pb@plaats\doifelsenothing\@@pb@uitgever{.}{:\space}}%
+% \doifsomething\@@pb@uitgever{\@@pb@uitgever.}}
+%
+% \def\normaal@publicatie
+% {\@@pb@naam, \@@pb@titel, \@@pb@jaar, \@@pb@pagina, \@@pb@plaats, \@@pb@uitgever.}
+%
+% \def\complexstartpublicatie[#1]#2\stoppublicatie
+% {\bgroup
+% \def\dosetpublicatie
+% {\processcommalist
+% [naam,titel,jaar,plaats,pagina,uitgever]
+% \setpublicatie
+% \ignorespaces}%
+% \def\setpublicatie##1%
+% {\letvalue{\??pb @##1}\empty
+% \setvalue{##1}####1{\setvalue{\??pb @##1}{####1}\ignorespaces}}%
+% \def\getpublicatie%
+% {\doifsomething\@@pbalternative{\getvalue{\@@pbalternative @publicatie}}}%
+% \doifelse\@@pbnumbering\v!yes
+% {\@publicatie[#1]\dosetpublicatie#2\getpublicatie\par}%
+% {\@@pbbefore
+% \dosetpublicatie\ignorespaces#2\getpublicatie
+% \@@pbafter}%
+% \egroup}
+%
+% \definecomplexorsimpleempty\startpublicatie
+%
+% \def\publication#1[#2]%
+% {\@@pbleft\in{#1}[#2]\@@pbright}
+%
+% \setuppublications
+% [\c!numbering=\v!yes,
+% \c!alternative=\c!apa,
+% \c!width=2em,
+% \c!hang=,
+% \c!sample=,
+% \c!before=,
+% \c!after=,
+% \c!inbetween=,
+% \c!headstyle=,
+% \c!headcolor=,
+% \c!style=,
+% \c!color=,
+% \c!blockway=\v!by\v!text,
+% \c!way=\v!by\v!text,
+% \c!text=,
+% \c!left={[},
+% \c!right={]}]
+
+% only used at pragma, move from kernel to run time module
+
+\def\referraldate
+ {\currentdate[\v!referral]}
+
+\def\doreferral[#1]%
+ {\noheaderandfooterlines
+ \bgroup
+ \getparameters
+ [\??km]
+ [\c!bet=\unknown,\c!dat=\unknown,\c!ken=\unknown,
+ \c!from=,\c!to=,\c!ref=,#1]%
+ % moet anders, hoort niet in 01b
+ \assigntranslation[\s!nl=referentie,\s!en=reference,\s!de=Referenz,\s!sp=referencia]\to\@@@kmref
+ \assigntranslation[\s!nl=van,\s!en=from,\s!de=Von,\s!sp=de]\to\@@@kmvan
+ \assigntranslation[\s!nl=aan,\s!en=to,\s!de=An,\s!sp=a]\to\@@@kmaan
+ \assigntranslation[\s!nl=betreft,\s!en=concerns,\s!de=Betreff,\s!sp=]\to\@@@kmbet
+ \assigntranslation[\s!nl=datum,\s!en=date,\s!de=Datum,\s!sp=fecha]\to\@@@kmdat
+ \assigntranslation[\s!nl=kenmerk,\s!en=mark,\s!de=Kennzeichen,\s!sp=]\to\@@@kmken
+ %
+ \definetabulate[\s!dummy][|l|p|]
+ \startdummy
+ \NC\@@@kmbet\EQ\@@kmbet\NC\NR
+ \NC\@@@kmdat\EQ\@@kmdat\NC\NR
+ \NC\@@@kmken\EQ\expanded{\smallcapped{\@@kmken}}\NC\NR
+ \doifsomething{\@@kmfrom\@@kmto}{\NC\NC\NC\NR}%
+ \doifsomething \@@kmfrom {\NC\@@@kmvan\EQ\@@kmfrom\NC\NR}%
+ \doifsomething \@@kmto {\NC\@@@kmaan\EQ\@@kmto\NC\NR}%
+ \doifsomething \@@kmref {\NC\NC\NC\NR\NC\@@@kmref\EQ\@@kmref\NC\NR}%
+ \stopdummy
+ \egroup}
+
+\def\referral
+ {\dosingleargument\doreferral}
+
+% FUZZY OLD STUFF: will be removed when not used in some manual;
+% rows instead of columns, i'd forgotten that this code exist
+%
+% \definesystemvariable{ri}
+%
+% \def\setuprows
+% {\dodoubleargument\getparameters[\??ri]}
+%
+% \definecomplexorsimpleempty\startrows
+%
+% \def\complexstartrows[#1]%
+% {\bgroup
+% \setuprows[#1]%
+% \let\do@@ribottom\relax
+% \def\row
+% {\do@@ribottom
+% \egroup
+% \dimen0\vsize
+% \divide\dimen0 \@@rin
+% \advance\dimen0 -\lineskip
+% \vbox to \dimen0
+% \bgroup
+% \@@ritop
+% \let\do@@ribottom\@@ribottom
+% \ignorespaces}%
+% \bgroup
+% \row}
+%
+% \def\stoprows
+% {\do@@ribottom
+% \egroup
+% \egroup}
+%
+% \setuprows
+% [\c!n=2,
+% \c!top=,
+% \c!bottom=\vfill]
+
+% THIS WAS MAIN-003.TEX
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+\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={=}]
+
+\unexpanded\def\xbox
+ {\bgroup\aftergroup\egroup\hbox\bgroup\tx\let\next=}
+
+\unexpanded\def\xxbox
+ {\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=}
+
+% \def\mrm#1%
+% {$\rm#1$}
+
+%D \macros
+%D {definepairedbox, setuppairedbox, placepairedbox}
+%D
+%D Paired boxes, formally called legends, but from now on a
+%D legend is just an instance, are primarily meant for
+%D typesetting some text alongside an illustration. Although
+%D there is quite some variation possible, the functionality is
+%D kept simple, if only because in most cases such pairs are
+%D typeset sober.
+%D
+%D The location specification accepts a pair, where the first
+%D keyword specifies the arrangement, and the second one the
+%D alignment. The first key of the location pair is one of
+%D \type {left}, \type {right}, \type {top} or \type {bottom},
+%D while the second key can also be \type {middle}.
+%D
+%D The first box is just collected in an horizontal box, but
+%D the second one is a vertical box that gets passed the
+%D bodyfont and alignment settings.
+
+%D Today we would implement this using layers .... but for the
+%D moment we keep it this way.
+
+% \startbuffer[test]
+% \test left \test left,top \test left,bottom \test left,middle
+% \test right \test right,top \test right,bottom \test right,middle
+% \test top \test top,left \test top,right \test top,middle
+% \test bottom \test bottom,left \test bottom,right \test bottom,middle
+% \stopbuffer
+%
+% \def\showtest#1%
+% {\pagina
+% \typebuffer[demo]
+% \def\test##1
+% {\startlinecorrection[blank]
+% \getbuffer[demo]%
+% \ruledhbox\placelegend
+% [bodyfont=6pt,location={##1}]
+% {\framed[width=.25\textwidth]{\tttf##1}}
+% {#1}
+% \stoplinecorrection}
+% \getbuffer[test]}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=\hsize,maxwidth=\makeupwidth,
+% height=\vsize,maxheight=\makeupheight]
+% \stopbuffer
+%
+% \showtest{These examples demonstrate the default settings.}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=\textwidth,
+% maxwidth=\textwidth]
+% \stopbuffer
+%
+% \showtest{\input tufte }
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=.65\textwidth]
+% \stopbuffer
+%
+% \showtest{\input knuth }
+%
+% \startbuffer[demo]
+% \setuplegend
+% [height=2cm]
+% \stopbuffer
+%
+% \showtest{These examples demonstrate some other settings.}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=.65\textwidth,
+% height=2cm]
+% \stopbuffer
+%
+% \showtest{These examples demonstrate some other settings.}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [n=2,align=right,width=.5\textwidth]
+% \stopbuffer
+%
+% \showtest{\input zapf }
+
+%D \macros
+%D {setuplegend, placelegend}
+%D
+%D It makes sense to typeset a legend to a figure in \TEX\
+%D and not in a drawing package. The macro \type {\placelegend}
+%D combines a figure (or something else) and its legend. This
+%D command is just a paired box.
+%D
+%D The legend is placed according to \type {location}, being
+%D \type {bottom} or \type {right}. The macro macro is used as
+%D follows.
+%D
+%D \starttyping
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulation
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulation}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulation[|l|l|l|l|]
+%D \NC 1 \NC head \NC 3 \NC tail \NC \NR
+%D \NC 2 \NC legs \NC \NC \NC \NR
+%D \stoptabulation}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\starttabulation
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulation}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {head \par legs \par tail}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2,width=.8\hsize]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D \stoptyping
+
+\newbox\firstpairedbox
+\newbox\secondpairedbox
+
+\def\definepairedbox
+ {\dodoubleempty\dodefinepairedbox}
+
+\def\dodefinepairedbox[#1][#2]%
+ {\getparameters
+ [\??ld#1]
+ [\c!n=1,
+ \c!distance=\bodyfontsize,
+ \c!before=,
+ \c!after=,
+ \c!color=,
+ \c!style=,
+ \c!inbetween={\blank[\v!medium]},
+ \c!width=\hsize,
+ \c!height=\vsize,
+ \c!maxwidth=\textwidth, % \makeupwidth,
+ \c!maxheight=\textheight, % \makeupheight,
+ \c!bodyfont=,
+ \c!align=,
+ \c!location=\v!bottom,
+ #2]%
+ \setvalue{\e!setup#1\e!endsetup}{\setuppairedbox[#1]}%
+ \setvalue{\e!place#1}{\placepairedbox[#1]}}
+
+\def\setuppairedbox
+ {\dodoubleempty\dosetuppairedbox}
+
+\def\dosetuppairedbox[#1]%
+ {\getparameters[\??ld#1]}
+
+\def\placepairedbox
+ {\bgroup\dodoubleempty\doplacepairedbox}
+
+\def\doplacepairedbox[#1][#2]% watch the hsize/vsize tricks
+ {\setuppairedbox[#1][#2]% % and don't change them
+ \copyparameters % brrr
+ [\??ld][\??ld#1]
+ [\c!n,\c!distance,\c!inbetween,\c!before,\c!after,
+ \c!width,\c!height,\c!maxwidth,\c!maxheight,
+ \c!color,\c!style,\c!bodyfont,\c!align,\c!location]%
+ \@@ldbefore\bgroup
+ \global\setsystemmode{pairedbox}%
+ \beforefirstpairedbox
+ \dowithnextbox
+ {\betweenbothpairedboxes
+ \dowithnextbox
+ {\afterbothpairedboxes
+ \egroup\@@ldafter
+ \egroup}
+ \vbox\bgroup
+ \insidesecondpairedbox
+ \let\next=}
+ \hbox}
+
+\def\beforefirstpairedbox
+ {\chardef\pairedlocationa1 % left
+ \chardef\pairedlocationb4 % middle
+ \getfromcommacommand[\@@ldlocation][1]%
+ \processaction
+ [\commalistelement]
+ [ \v!left=>\chardef\pairedlocationa0,
+ \v!right=>\chardef\pairedlocationa1,
+ \v!top=>\chardef\pairedlocationa2,
+ \v!bottom=>\chardef\pairedlocationa3]%
+ \getfromcommacommand[\@@ldlocation][2]%
+ \processaction
+ [\commalistelement]
+ [ \v!left=>\chardef\pairedlocationb0,
+ \v!right=>\chardef\pairedlocationb1,
+ \v!high=>\chardef\pairedlocationb2,
+ \v!top=>\chardef\pairedlocationb2,
+ \v!low=>\chardef\pairedlocationb3,
+ \v!bottom=>\chardef\pairedlocationb3,
+ \v!middle=>\chardef\pairedlocationb4]}
+
+\def\betweenbothpairedboxes
+ {\switchtobodyfont[\@@ldbodyfont]% split under same regime
+ \setbox\firstpairedbox\flushnextbox
+ \ifnum\pairedlocationa<2
+ \hsize\wd\firstpairedbox % trick
+ \hsize\@@ldwidth
+ \scratchdimen\wd\firstpairedbox
+ \advance\scratchdimen \@@lddistance
+ \bgroup\advance\scratchdimen \hsize
+ \ifdim\scratchdimen>\@@ldmaxwidth\relax
+ \egroup
+ \hsize\@@ldmaxwidth
+ \advance\hsize -\scratchdimen
+ \else
+ \egroup
+ \fi
+ \else
+ \hsize\wd\firstpairedbox
+ \hsize\@@ldwidth % can be \hsize
+ \ifdim\hsize>\@@ldmaxwidth\relax \hsize\@@ldmaxwidth \fi % can be \hsize
+ \fi
+ \ifnum\@@ldn>\plusone
+ \setrigidcolumnhsize\hsize\@@lddistance\@@ldn
+ \fi}
+
+\def\afterbothpairedboxes
+ {\setbox\secondpairedbox\vbox
+ {% \localstartcolor[\@@ldcolor]% does not work yet
+ \ifnum\@@ldn>1
+ \rigidcolumnbalance\nextbox
+ \else
+ \flushnextbox
+ \fi
+ }% \localstopcolor}%
+ \ifnum\pairedlocationa<2\hbox\else\vbox\fi\bgroup % hide vsize
+ \forgetall
+ \ifnum\pairedlocationa<2
+ \scratchdimen\maxoftwoboxdimens\ht\firstpairedbox\secondpairedbox
+ \vsize\scratchdimen
+ \ifdim\scratchdimen<\@@ldheight\relax % can be \vsize
+ \scratchdimen\@@ldheight
+ \fi
+ \ifdim\scratchdimen>\@@ldmaxheight\relax
+ \scratchdimen\@@ldmaxheight
+ \fi
+ \valignpairedbox\firstpairedbox \scratchdimen
+ \valignpairedbox\secondpairedbox\scratchdimen
+ \else
+ \scratchdimen\maxoftwoboxdimens\wd\firstpairedbox\secondpairedbox
+ \halignpairedbox\firstpairedbox \scratchdimen
+ \halignpairedbox\secondpairedbox\scratchdimen
+ \scratchdimen\ht\secondpairedbox
+ \vsize\scratchdimen
+ \ifdim\ht\secondpairedbox<\@@ldheight\relax % can be \vsize
+ \scratchdimen\@@ldheight\relax % \relax needed
+ \fi
+ \ifdim\scratchdimen>\@@ldmaxheight\relax % todo: totale hoogte
+ \scratchdimen\@@ldmaxheight\relax % \relax needed
+ \fi
+ \ifdim\scratchdimen>\ht\secondpairedbox
+ \setbox\secondpairedbox\vbox to \scratchdimen
+ {\ifnum\pairedlocationa=3 \vss\fi %
+ \box\secondpairedbox
+ \ifnum\pairedlocationa=2 \vss\fi}% \kern\zeropoint
+ \fi
+ \fi
+ \ifcase\pairedlocationa
+ \box\secondpairedbox\hskip\@@lddistance\box\firstpairedbox \or
+ \box\firstpairedbox \hskip\@@lddistance\box\secondpairedbox\or
+ \box\secondpairedbox\endgraf \nointerlineskip \@@ldinbetween \box\firstpairedbox \or
+ \box\firstpairedbox \endgraf \nointerlineskip \@@ldinbetween \box\secondpairedbox\else
+ \fi
+ \egroup}
+
+\def\insidesecondpairedbox
+ {\forgetall
+ \setupalign[\@@ldalign]%
+ \tolerantTABLEbreaktrue % hm.
+ \blank[\v!disable]%
+ \everypar{\begstrut}}
+
+\def\maxoftwoboxdimens#1#2#3%
+ {#1\ifdim#1#2>#1#3 #2\else#3\fi}
+
+\def\valignpairedbox#1#2%
+ {\setbox#1\vbox to #2
+ {\ifcase\pairedlocationb\or\or\or\vss\or\vss\fi
+ \box#1\relax
+ \ifcase\pairedlocationb\or\or\vss\or\or\vss\fi}}
+
+\def\halignpairedbox#1#2%
+ {\setbox#1\hbox to #2
+ {\ifcase\pairedlocationb\or\hss\or\or\or\hss\fi
+ \box#1\relax
+ \ifcase\pairedlocationb\hss\or\or\or\or\hss\fi}}
+
+\definepairedbox[\v!legend]
+
+%D Goody:
+
+\appendtoks
+ \global\resetsystemmode{combination}%
+ \global\resetsystemmode{pairedbox}%
+\to \everyinsidefloat
+
+% todo: \startcombination \startcomb \stopcomb ...
+
+\newcount\horcombination % counter
+\newcount\totcombination
+
+\def\definecombination
+ {\dodoubleempty\dodefinecombination}
+
+\def\dodefinecombination[#1][#2]%
+ {\copyparameters
+ [\??co#1][\??co]
+ [\c!width,\c!height,\c!distance,\c!location,%
+ \c!before,\c!inbetween,\c!after,\c!align,%
+ \c!style,\c!color]%
+ \getparameters
+ [\??co#1][#2]}
+
+\def\setupcombinations
+ {\dodoubleempty\dosetupcombinations}
+
+\def\dosetupcombinations[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??co#1][#2]%
+ \else
+ \getparameters[\??co][#1]%
+ \fi}
+
+\def\combinationparameter#1%
+ {\csname\??co\currentcombination#1\endcsname}%
+
+\def\startcombination
+ {\bgroup % so we can grab a group
+ \dodoubleempty\dostartcombination}
+
+% \startcombination {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2*1] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[1*2] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2] {alpha} {a} {beta} {b} \stopcombination
+
+\def\dostartcombination[#1][#2]%
+ {\global\setsystemmode{combination}%
+ \doifnothing{#1}\firstargumentfalse % to be sure (when called in macros)
+ \doifnothing{#2}\secondargumentfalse % to be sure (when called in macros)
+ \ifsecondargument
+ \def\currentcombination{#1}%
+ \edef\currentcombinationspec{#2*1*}%
+ \else % better : \doifcombinationelse ... \??co#1\c!location
+ \doifinstringelse{*}{#1}
+ {\let\currentcombination\empty
+ \edef\currentcombinationspec{#1*1*}}
+ {\doifnumberelse{#1}
+ {\let\currentcombination\empty
+ \edef\currentcombinationspec{#1*1*}}
+ {\def\currentcombination{#1}%
+ \edef\currentcombinationspec{2*1*}}}%
+ \fi
+ \forgetall
+ \doifelse{\combinationparameter\c!height}\v!fit
+ \vbox {\vbox to \combinationparameter\c!height}%
+ \bgroup
+ \expanded{\dodostartcombination[\currentcombinationspec]}}
+
+\long\def\dodostartcombination[#1*#2*#3]%
+ {\setuphorizontaldivision
+ [\c!n=\v!fit,\c!distance=\combinationparameter\c!distance]%
+ \global\horcombination#1%
+ \global\totcombination#2%
+ \global\setbox\combinationstack\emptybox
+ \xdef\maxhorcombination{\the\horcombination}%
+ \multiply\totcombination\horcombination
+ \tabskip\zeropoint
+ \doifelse{\combinationparameter\c!width}\v!fit
+ {\halign}{\halign to \combinationparameter\c!width}%
+ \bgroup&%
+ %\hfil##\hfil% now : location={left,top}
+ \expanded{\doifnotinset{\v!left}{\combinationparameter\c!location}}\hfil
+ ##%
+ \expanded{\doifnotinset{\v!right}{\combinationparameter\c!location}}\hfil
+ &\tabskip\zeropoint \!!plus 1fill##\cr
+ \docombination}
+
+\def\docombination % we want to add struts but still ignore an empty box
+ {\dowithnextbox
+ {\setbox0\flushnextbox
+ \dowithnextbox
+ {\setbox2\flushnextbox
+ \dodocombination}%
+ \vtop\bgroup
+ \def\next
+ {\futurelet\nexttoken\nextnext}%
+ \def\nextnext
+ {\ifx\nexttoken\egroup \else % the next box is empty
+ \hsize\wd0
+ \setupalign[\combinationparameter\c!align]%
+ \dostartattributes{\??co\currentcombination}\c!style\c!color\empty
+ \bgroup
+ \aftergroup\endstrut
+ \aftergroup\dostopattributes
+ \aftergroup\egroup
+ \begstrut
+ \fi}%
+ \afterassignment\next\let\nexttoken=}
+ \hbox}
+
+% stupid version, does not align top stuff when captions,
+% keep as example
+%
+% \def\dodocombination
+% {\vbox
+% {\forgetall % \setupwhitespace[\v!none]%
+% \let\next\vbox
+% \ExpandFirstAfter\processallactionsinset
+% [\combinationparameter\c!location]
+% [ \v!top=>\let\next\tbox,
+% \v!middle=>\let\next\halfwaybox]%
+% \next{\copy0}%
+% \ifdim\ht2>\zeropoint % beter dan \wd2, nu \strut mogelijk
+% \combinationparameter\c!inbetween
+% %\vtop % wrong code
+% % {\nointerlineskip % recently added
+% % \hsize\wd0
+% % \setupalign[\combinationparameter\c!align]% % \raggedcenter
+% % \begstrut\unhbox2\endstrut}%
+% \box2
+% \fi}%
+% \ifnum\totcombination>\plusone
+% \global\advance\totcombination\minusone
+% \global\advance\horcombination\minusone
+% \ifnum\horcombination=\zerocount
+% \def\next
+% {\cr\noalign
+% {\forgetall % \setupwhitespace[\v!geen]% no
+% \nointerlineskip
+% \combinationparameter\c!before
+% \combinationparameter\c!after
+% \vss
+% \nointerlineskip}%
+% \global\horcombination\maxhorcombination\relax
+% \docombination}%
+% \else
+% \def\next
+% {&&&\hskip\combinationparameter\c!distance&\docombination}%
+% \fi
+% \else
+% \def\next
+% {\cr\egroup}%
+% \fi
+% \next}
+
+% \def\dodocombination
+% {\vbox
+% {\forgetall % \setupwhitespace[\v!none]%
+% \let\next\vbox
+% \ExpandFirstAfter\processallactionsinset
+% [\combinationparameter\c!plaats]
+% [ \v!top=>\let\next\tbox,
+% \v!middle=>\let\next\halfwaybox]%
+% \next{\copy0}%
+% % we need to save the caption for a next alignment line
+% \saveoncombinationstack2}%
+% \ifnum\totcombination>\plusone
+% \global\advance\totcombination\minusone
+% \global\advance\horcombination\minusone
+% \ifnum\horcombination=\zerocount
+% \def\next
+% {\cr
+% \flushcombinationstack
+% \noalign
+% {\forgetall % \setupwhitespace[\v!none]% no
+% \global\setbox\combinationstack\emptybox
+% \nointerlineskip
+% \combinationparameter\c!after
+% \combinationparameter\c!before
+% \vss
+% \nointerlineskip}%
+% \global\horcombination\maxhorcombination\relax
+% \docombination}%
+% \else
+% \def\next
+% {&&&\hskip\combinationparameter\c!distance&\docombination}%
+% \fi
+% \else
+% \def\next
+% {\cr
+% \flushcombinationstack
+% \egroup}%
+% \fi
+% \next}
+
+\def\depthonlybox
+ {\dowithnextbox{\vtop{\hsize\wd\nextbox\kern\zeropoint\box\nextbox}}\vbox}
+
+% \def\boxwithstrutheight
+% {\dowithnextbox
+% {\scratchdimen\strutheight
+% \advance\scratchdimen-\nextboxht
+% \hbox{\raise\scratchdimen\box\nextbox}}%
+% \vbox}
+
+\def\dodocombination
+ {\vbox
+ {\forgetall % \setupwhitespace[\v!none]%
+ \let\next\vbox
+ \expanded{\processallactionsinset[\combinationparameter\c!location]}
+ [ \v!top=>\let\next\depthonlybox, % \tbox,
+ \v!middle=>\let\next\halfwaybox]%
+ \next{\copy0}%
+ % we need to save the caption for a next alignment line
+ \saveoncombinationstack2}%
+ \ifnum\totcombination>\plusone
+ \global\advance\totcombination\minusone
+ \global\advance\horcombination\minusone
+ \ifnum\horcombination=\zerocount
+ \def\next
+ {\cr
+ \flushcombinationstack
+ \noalign
+ {\forgetall % \setupwhitespace[\v!none]% no
+ \global\setbox\combinationstack\emptybox
+ \nointerlineskip
+ \combinationparameter\c!after
+ \combinationparameter\c!before
+ \vss
+ \nointerlineskip}%
+ \global\horcombination\maxhorcombination\relax
+ \docombination}%
+ \else
+ \def\next
+ {&&&\hskip\combinationparameter\c!distance&\docombination}%
+ \fi
+ \else
+ \def\next
+ {\cr
+ \flushcombinationstack
+ \egroup}%
+ \fi
+ \next}
+
+% formally ok:
+%
+% \def\stopcombination
+% {\egroup
+% \egroup}
+%
+% more robust:
+%
+% \def\stopcombination
+% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries
+% \egroup
+% \egroup}
+%
+% even better:
+
+\def\stopcombination
+ {{\scratchtoks{{}{}{}}\dorecurse\totcombination{\appendtoks{}{}{}{}\to\scratchtoks}\expandafter}\the\scratchtoks
+ \egroup
+ \egroup}
+
+\newbox\combinationstack
+
+\def\saveoncombinationstack#1%
+ {\global\setbox\combinationstack\hbox
+ {\hbox{\box#1}\unhbox\combinationstack}}
+
+\def\flushcombinationstack
+ {\noalign
+ {\ifdim\ht\combinationstack>\zeropoint
+\nointerlineskip % nieuw
+ \combinationparameter\c!inbetween
+ \global\horcombination\maxhorcombination
+ \globallet\doflushcombinationstack\dodoflushcombinationstack
+ \else
+ \global\setbox\combinationstack\emptybox
+ \globallet\doflushcombinationstack\donothing
+ \fi}%
+ \doflushcombinationstack\crcr}
+
+\gdef\dodoflushcombinationstack
+ {\global\setbox\combinationstack\hbox
+ {\unhbox\combinationstack
+ \global\setbox1\lastbox}%
+ \box1% \ruledhbox{\box1}%
+ \global\advance\horcombination\minusone\relax
+ \ifnum\horcombination>\zerocount
+ \def\next{&&&&\doflushcombinationstack}%
+ \else
+ \global\setbox\combinationstack\emptybox
+ %\let\next\relax
+ \@EA\gobbleoneargument
+ \fi
+ \next}
+
+\setupcombinations
+ [\c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!distance=1em,
+ \c!location=\v!bottom, % can be something {top,left}
+ \c!before=\blank,
+ \c!inbetween={\blank[\v!medium]},
+ \c!style=,
+ \c!color=,
+ \c!after=,
+ \c!align=\v!middle]
+
+%D \macros
+%D {startfloatcombination}
+%D
+%D \setupexternalfigures[directory={../sample}]
+%D \startbuffer
+%D \placefigure
+%D [left,none]
+%D {}
+%D {\startfloatcombination[2*2]
+%D \placefigure{alpha}{\externalfigure[cow.pdf][width=1cm]}
+%D \placefigure{beta} {\externalfigure[cow.pdf][width=2cm]}
+%D \placefigure{gamma}{\externalfigure[cow.pdf][width=3cm]}
+%D \placefigure{delta}{\externalfigure[cow.pdf][width=4cm]}
+%D \stopfloatcombination}
+%D
+%D \input tufte
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\startfloatcombination
+ {\dodoubleempty\dostartfloatcombination}
+
+\def\dostartfloatcombination[#1][#2]%
+ {\vbox\bgroup
+ %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature
+ \chardef\postcenterfloatmethod\zerocount
+ \forcelocalfloats
+ \def\stopfloatcombination
+ {\scratchtoks\emptytoks
+ \dorecurse\noflocalfloats
+ {\appendetoks{\noexpand\getlocalfloat{\recurselevel}}{}\to\scratchtoks}%
+ \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination
+ \resetlocalfloats
+ \egroup}}
+
+\def\placerelativetoeachother#1#2%
+ {\bgroup
+ \dowithnextbox
+ {\bgroup
+ \setbox0\box\nextbox
+ \dowithnextbox
+ {\setbox2\box\nextbox
+ #1{#2#########2\cr\box0\cr\box2\cr}
+ \egroup
+ \egroup}
+ \hbox}
+ \hbox}
+
+\def\placeontopofeachother{\placerelativetoeachother\halign\hss}
+\def\placesidebyside {\placerelativetoeachother\valign\vss}
+
+% this will be replaced or go away, never used
+
+\def\douseexternalfiles[#1][#2]%
+ {\getparameters
+ [\??fi#1]
+ [\c!file=,
+ \c!bodyfont=,
+ \c!option=,
+ #2]}
+
+\def\useexternalfiles
+ {\dodoubleargument\douseexternalfiles}
+
+\def\dostelexternefilesin[#1][#2]%
+ {\doifundefinedelse{\??fi#1\c!file}
+ {\useexternalfiles[#1][#2]}
+ {\getparameters[\??fi#1][#2]}}
+
+\def\stelexternefilesin
+ {\dodoubleargument\dostelexternefilesin}
+
+\def\verwerkexternefile#1#2#3%
+ {\bgroup
+ \getparameters[\??fi#1][\c!file=,#3]%
+ \doinputonce{\getvalue{\??fi#1\c!file}}%
+ \ExpandFirstAfter\switchtobodyfont[\getvalue{\??fi#1\c!bodyfont}]%
+ \readsysfile{#2} % beter: loc of fix gebied
+ \donothing
+ {\showmessage\m!systems{41}{#2,#1}}%
+ \egroup}
+
+\def\douseexternalfile[#1][#2][#3][#4]%
+ {\stelexternefilesin[#1][]%
+ \doinputonce{\getvalue{\??fi#1\c!file}}%
+ \doifelsenothing{#2}
+ {\setvalue{#3}{\verwerkexternefile{#1}{#3}{#4}}}
+ {\setvalue{#2}{\verwerkexternefile{#1}{#3}{#4}}}}
+
+\def\useexternalfile
+ {\doquadrupleargument\douseexternalfile}
+
+\useexternalfiles
+ [pictex]
+ [\c!bodyfont=\v!small,
+ \c!file=pictex]
+
+\useexternalfiles
+ [table]
+ [\c!file=table]
+
+%D A couple of examples, demonstrating how the depth is
+%D taken care of:
+%D
+%D \startbuffer
+%D test\rotate[frame=on, rotation=0] {gans}%
+%D test\rotate[frame=on, rotation=90] {gans}%
+%D test\rotate[frame=on, rotation=180]{gans}%
+%D test\rotate[frame=on, rotation=270]{gans}%
+%D test
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% When we rotate over arbitrary angles, we need to relocate the
+% resulting box because rotation brings that box onto the negative
+% axis. The calculations (mostly sin and cosine) need to be tuned for
+% the way a box is packages (i.e. the refence point). A typical example
+% of drawing, scribbling, and going back to the days of school math.
+%
+% We do a bit more calculations than needed, simply because that way
+% it's easier to debug the code.
+
+\def\dododorotatenextbox
+ {\setbox\nextbox\vbox to \@@layerysiz
+ {\vfill
+ \hbox to \@@layerxsiz
+ {\dostartrotation\@@rorotation
+ \nextboxwd\zeropoint
+ \nextboxht\zeropoint
+ \flushnextbox
+ \dostoprotation
+ \hfill}%
+ \kern\@@layerypos}%
+ \setbox\nextbox\hbox
+ {\kern\@@layerxpos
+ \kern\@@layerxoff
+ \lower\@@layeryoff\flushnextbox}}
+
+\def\dodorotatenextbox#1#2% quite some trial and error -)
+ {\dontshowcomposition
+ \dontcomplain
+ \ifnum#2=\plusfour
+ % new, location=middle
+ \!!widthb \nextboxwd
+ \!!heightb\nextboxht
+ \!!depthb \nextboxdp
+ \setbox\nextbox\vbox{\vskip.5\nextboxht\hskip-.5\nextboxwd\flushnextbox}%
+ \smashbox\nextbox
+ \fi
+ \!!widtha \nextboxwd
+ \!!heighta\nextboxht
+ \!!deptha \nextboxdp
+ \!!doneafalse
+ \!!donebfalse
+ \ifcase#2\or
+ % 1: fit
+ \or
+ % 2: depth, not fit
+ \!!doneatrue
+ \!!donebtrue
+ \or
+ % 3: depth, fit
+ \!!donebtrue
+ \fi
+ \setbox\nextbox\vbox{\hbox{\raise\nextboxdp\flushnextbox}}%
+ \!!dimena \nextboxht
+ \setcalculatedcos\cos\@@rorotation
+ \setcalculatedsin\sin\@@rorotation
+ \@@layerxpos\zeropoint
+ \@@layerypos\zeropoint
+ \@@layerxoff\zeropoint
+ \@@layeryoff\zeropoint
+ \ifdim\sin\points>\zeropoint
+ \ifdim\cos\points>\zeropoint
+ \@@layerxsiz \cos\!!widtha
+ \@@layerysiz \sin\!!widtha
+ \advance\@@layerxsiz \sin\!!dimena
+ \advance\@@layerysiz \cos\!!dimena
+ \@@layerypos \cos\!!dimena
+ \if!!donea
+ \@@layerxoff \negated\sin\!!dimena
+ \advance\@@layerxoff \sin\!!deptha
+ \fi
+ \if!!doneb
+ \@@layeryoff \cos\!!deptha
+ \fi
+ \dododorotatenextbox
+ \else
+ \@@layerxsiz \negated\cos\!!widtha
+ \@@layerysiz \sin\!!widtha
+ \advance\@@layerxsiz \sin\!!dimena
+ \advance\@@layerysiz \negated\cos\!!dimena
+ \@@layerxpos \negated\cos\!!widtha
+ \if!!donea
+ \@@layerxoff -\@@layerxsiz
+ \advance\@@layerxoff \sin\!!deptha
+ \fi
+ \if!!doneb
+ \@@layeryoff \negated\cos\!!heighta
+ \fi
+ \dododorotatenextbox
+ \wd\nextbox\if!!donea\sin\!!deptha\else\@@layerxsiz\fi
+ \fi
+ \else
+ \ifdim\cos\points<\zeropoint
+ \@@layerxsiz \negated\cos\!!widtha
+ \@@layerysiz \negated\sin\!!widtha
+ \advance\@@layerxsiz \negated\sin\!!dimena
+ \advance\@@layerysiz \negated\cos\!!dimena
+ \@@layerxpos \@@layerxsiz
+ \@@layerypos \negated\sin\!!widtha
+ \if!!donea
+ \@@layerxoff -\@@layerxsiz
+ \advance\@@layerxoff \negated\sin\!!heighta
+ \fi
+ \if!!doneb
+ \@@layeryoff \@@layerysiz
+ \advance\@@layeryoff \cos\!!deptha
+ \fi
+ \dododorotatenextbox
+ \wd\nextbox\if!!donea\negated\sin\!!heighta\else\@@layerxsiz\fi
+ \else
+ \@@layerxsiz \cos\!!widtha
+ \@@layerysiz \negated\sin\!!widtha
+ \advance\@@layerxsiz \negated\sin\!!dimena
+ \advance\@@layerysiz \cos\!!dimena
+ \ifdim\sin\points=\zeropoint
+ \@@layerxpos \zeropoint
+ \@@layerxoff \zeropoint
+ \@@layerypos \@@layerysiz
+ \if!!doneb
+ \@@layeryoff \!!deptha
+ \fi
+ \else
+ \@@layerypos \@@layerysiz
+ \@@layerxpos \negated\sin\!!dimena
+ \if!!donea
+ \@@layerxoff -\@@layerxsiz
+ \advance\@@layerxoff \negated\sin\!!heighta
+ \fi
+ \if!!doneb
+ \@@layeryoff \negated\sin\!!deptha
+ \fi
+ \fi
+ \dododorotatenextbox
+ \ifdim\sin\points=\zeropoint
+ \else
+ \wd\nextbox\if!!donea\negated\sin\!!heighta\else\@@layerxsiz\fi
+ \fi
+ \fi
+ \fi
+ % new, location=middle
+ \ifnum#2=\plusfour
+ \setbox\nextbox\vbox{\vskip-.5\!!heightb\hskip.5\!!heightb\flushnextbox}%
+ \nextboxwd\!!widthb
+ \nextboxht\!!heightb
+ \nextboxdp\!!depthb
+ \fi}
+
+\def\dorotatenextbox#1#2%
+ {\doifsomething{#1}
+ {\edef\@@rorotation{\realnumber{#1}}% get rid of leading zeros and spaces
+ \setbox\nextbox\vbox{\flushnextbox}% not really needed
+ \dodorotatenextbox\@@rorotation#2}%
+ \hbox{\boxcursor\flushnextbox}}
+
+\def\dodorotatebox#1% {angle} \hbox/\vbox/\vtop
+ {\bgroup\hbox\bgroup % compatibility hack
+ \dowithnextbox
+ {\dorotatenextbox{#1}\plusone
+ \egroup\egroup}}
+
+\def\dorotatebox#1% {angle} \hbox/\vbox/\vtop
+ {\ifcase#1\relax
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\dodorotatebox
+ \fi{#1}}
+
+\unexpanded\def\rotate % \bgroup: \rotate kan argument zijn
+ {\bgroup\complexorsimpleempty\rotate}
+
+% \def\complexrotate[#1]% framed met diepte !
+% {\getparameters[\??ro][#1]%
+% \processaction
+% [\@@rolocation]
+% [ \v!depth=>\!!counta\plusthree\donefalse,% depth fit - raw box
+% \v!fit=>\!!counta\plustwo \donefalse,% depth tight - raw box
+% \v!broad=>\!!counta\plusone \donefalse,% nodepth fit - raw box
+% \v!high=>\!!counta\plusone \donetrue ,% nodepth fit - framed
+% \v!middle=>\!!counta\plusfour \donefalse,% centered, keep dimensions
+% \s!default=>\!!counta\plusthree\donetrue ,% depth fit - framed
+% \s!unknown=>\!!counta\plusthree\donetrue ]% depth fit - framed
+% \ifdone
+% \def\docommand{\localframed[\??ro][#1,\c!location=]}%
+% \else
+% \let\docommand\relax
+% \fi
+% \dowithnextbox{\dorotatenextbox\@@rorotation\!!counta\egroup}\vbox\docommand}
+
+\setvalue{\??ro::\c!location::\v!depth }{\!!counta\plusthree\donefalse} % depth fit - raw box
+\setvalue{\??ro::\c!location::\v!fit }{\!!counta\plustwo \donefalse} % depth tight - raw box
+\setvalue{\??ro::\c!location::\v!broad }{\!!counta\plusone \donefalse} % nodepth fit - raw box
+\setvalue{\??ro::\c!location::\v!high }{\!!counta\plusone \donetrue } % nodepth fit - framed
+\setvalue{\??ro::\c!location::\v!middle }{\!!counta\plusfour \donefalse} % centered, keep dimensions
+\setvalue{\??ro::\c!location::\v!default}{\!!counta\plusthree\donetrue } % depth fit - framed
+
+\def\complexrotate[#1]% framed met diepte !
+ {\getparameters[\??ro][#1]%
+ \executeifdefined{\??ro::\c!location::\@@rolocation}{\!!counta\plusthree\donetrue}%
+ \ifdone
+ \def\docommand{\localframed[\??ro][#1,\c!location=]}%
+ \else
+ \let\docommand\relax
+ \fi
+ \dowithnextbox{\dorotatenextbox\@@rorotation\!!counta\egroup}\vbox\docommand}
+
+\presetlocalframed[\??ro]
+
+\def\setuprotate
+ {\dodoubleargument\getparameters[\??ro]}
+
+\setuprotate
+ [\c!rotation=90,
+ \c!location=\v!normal,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+% \dostepwiserecurse{0}{360}{10}
+% {\startlinecorrection[blank]
+% \hbox
+% {\expanded{\setuprotate[rotation=\recurselevel]}%
+% \traceboxplacementtrue
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=depth] {\ruledhbox{\bfb (depth)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=fit] {\ruledhbox{\bfb (fit)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=broad] {\ruledhbox{\bfb (broad)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=normal]{\ruledhbox{\bfb (normal)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=high] {\ruledhbox{\bfb (high)}}}}}
+% \stoplinecorrection}
+
+% to be used in some other places! todo!
+%
+% divides \hsize in fractions, will be made a bit more
+% clever and advanced when needed
+%
+% \horizontaldivision[n/m,elements,distance]
+%
+% \horizontaldivision[2/5,3,1em]
+% \horizontaldivision[2/5,3,1em]
+% \horizontaldivision[1/5,3,1em]
+%
+% \setuphorizontaldivision[afstand=,aantal=] (passend,passend)
+
+\def\??fr{@@fr}
+
+\def\setuphorizontaldivision
+ {\dodoubleargument\getparameters[\??fr]}
+
+\def\horizontaldivision
+ {\dosingleargument\dohorizontaldivision}
+
+\def\dohorizontaldivision[#1]%
+ {\dodohorizontaldivision[#1,,,,,,]}
+
+\def\dodohorizontaldivision[#1/#2,#3,#4,#5]%
+ {\doifelsenothing{#3}
+ {\doifelse\@@frn\v!fit
+ {\!!counta#2\relax}
+ {\!!counta\@@frn\relax}}
+ {\!!counta#3\relax}%
+ \doifelsenothing{#4}
+ {\doifelse\@@frdistance\v!fit
+ {\!!widtha\zeropoint}
+ {\!!widtha\@@frdistance}}
+ {\!!widtha#4}%
+ \advance\!!counta \minusone
+ \multiply\!!widtha \!!counta
+ \advance\hsize -\!!widtha
+ \divide\hsize #2\relax
+ \hsize#1\hsize}
+
+\setuphorizontaldivision
+ [\c!distance=\tfskipsize,
+ \c!n=\v!fit]
+
+%D This one is for Daniel Pittman, who wanted tight
+%D fractions. We show three versions. First the simple
+%D one using \type {\low} and \type {high}:
+%D
+%D \startbuffer
+%D \def\vfrac#1#2%
+%D {\hbox{\high{\tx#1\kern-.25em}/\low{\kern-.25em\tx#2}}}
+%D
+%D test \vfrac{1}{2} test \vfrac{123}{456} test
+%D \stopbuffer
+%D
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D A better way to handle the kerning is the following, here
+%D we kind of assume that tye slash is symmetrical and has
+%D nearly zero width.
+%D
+%D \startbuffer
+%D \def\vfract#1#2%
+%D {\hbox{\high{\tx#1}\hbox to \zeropoint{\hss/\hss}\low{\tx#2}}}
+%D \stopbuffer
+%D
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D The third and best alternative is the following:
+%D
+%D {\showmakeup\getbuffer}\crlf\getbuffer
+%D
+%D This time we measure the height of the \type {/} and
+%D shift over the maximum height and depths of this
+%D character and the fractional digits (we use 57 as
+%D sample). Here we combine all methods in one macros.
+
+\chardef\vulgarfractionmethod=3
+
+\definehspace[vulgarfraction][.25em] % [.15em]
+\definesymbol[vulgarfraction][/] % [\raise.2ex\hbox{/}]
+
+\unexpanded\def\vulgarfraction#1#2%
+ {\dontleavehmode
+ \hbox
+ {\def\vulgarfraction{vulgarfraction}%
+ \ifcase\vulgarfractionmethod
+ #1\symbol[\vulgarfraction]#2%
+ \or
+ \high{\tx#1\kern-\hspaceamount\empty\vulgarfraction}%
+ \symbol[\vulgarfraction]%
+ \low {\kern-\hspaceamount\empty\vulgarfraction\tx#2}%
+ \or
+ \high{\tx#1}%
+ \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}%
+ \low{\tx#2}%
+ \or
+ \setbox0\hbox{\symbol[\vulgarfraction]}%
+ \setbox2\hbox{\txx57}%
+ \raise\ht0\hbox{\lower\ht2\hbox{\txx#1}}%
+ \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}%
+ \lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}%
+ \fi}}
+
+\ifx\vfrac\undefined \let\vfrac\vulgarfraction \fi
+
+%D \starttabulate
+%D \HL
+%D \NC \bf method \NC \bf visualization \NC\NR
+%D \HL
+%D \NC 0 \NC \chardef\vulgarfractionmethod0\vulgarfraction{1}{2} \NC\NR
+%D \NC 1 \NC \chardef\vulgarfractionmethod1\vulgarfraction{1}{2} \NC\NR
+%D \NC 2 \NC \chardef\vulgarfractionmethod2\vulgarfraction{1}{2} \NC\NR
+%D \NC 3 \NC \chardef\vulgarfractionmethod3\vulgarfraction{1}{2} \NC\NR
+%D \HL
+%D \stoptabulate
+
+%D Under construction:
+%D
+%D \starttyping
+%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 \stoptyping
+
+\let\handlecommalistsentence\firstofoneargument
+
+\def\commalistsentenceone{and-1}
+\def\commalistsentencetwo{and-2}
+
+\def\commalistsentence
+ {\dodoubleempty\docommalistsentence}
+
+\def\docommalistsentence[#1][#2]%
+ {\bgroup
+ \getfromcommalist[#2][1]%
+ \ifx\commalistelement\empty
+ \def\@@commalistsentenceone{\labeltext\commalistsentenceone}%
+ \else
+ \let\@@commalistsentenceone\commalistelement
+ \fi
+ \getfromcommalist[#2][2]%
+ \ifx\commalistelement\empty
+ \def\@@commalistsentencetwo{\labeltext\commalistsentencetwo}%
+ \else
+ \let\@@commalistsentencetwo\commalistelement
+ \fi
+ \getcommalistsize[#1]%
+ \ifcase\commalistsize\relax
+ \def\serializedcommalist{#1}%
+ \else
+ \let\serializedcommalist\empty
+ \scratchcounter\zerocount
+ \def\docommand##1%
+ {\advance\scratchcounter \plusone
+ \ifnum\scratchcounter=\plusone
+ \scratchtoks{\handlecommalistsentence{##1}}%
+ \else
+ \ifnum\scratchcounter=\commalistsize
+ \appendtoks\@@commalistsentencetwo\handlecommalistsentence{##1}\to\scratchtoks
+ \else
+ \appendtoks\@@commalistsentenceone\handlecommalistsentence{##1}\to\scratchtoks
+ \fi
+ \fi}%
+ \processcommacommand[#1]\docommand
+ \edef\serializedcommalist{\the\scratchtoks}%
+ \fi
+ \serializedcommalist
+ \egroup}
+
+\def\commacommandsentence[#1]{\@EA\commalistsentence\@EA[#1]}
+
+\ifx\textcomma\undefined \def\textcomma{,} \fi
+
+\setuplabeltext [\s!nl] [and-1=\textcomma\ , and-2= en ]
+\setuplabeltext [\s!en] [and-1=\textcomma\ , and-2=\textcomma\ and ]
+\setuplabeltext [\s!de] [and-1=\textcomma\ , and-2= und ]
+
+%D \macros
+%D {somekindoftab}
+%D
+%D This macro can be used to create tabs:
+%D
+%D \starttyping
+%D \setupheadertexts[{\somekindoftab[alternative=horizontal]{\framed{\realfolio}}}]
+%D \setuptexttexts [{\somekindoftab[alternative=vertical] {\framed{\realfolio}}}]
+%D
+%D \starttext
+%D \showframe \dorecurse{10}{test\page}
+%D \stoptext
+%D \stoptyping
+
+\def\somekindoftab
+ {\dosingleempty\dosomekindoftab}
+
+\def\dosomekindoftab[#1]%
+ {\bgroup
+ \getparameters[xx]
+ [\c!alternative=\v!vertical,
+ \c!width=\textwidth,\c!height=\textheight,
+ \c!n=\lastpage,\c!m=\realpageno,
+ #1]%
+ \doifelse\xxalternative\v!vertical
+ {\dodosomekindoftab\vbox\vskip\xxheight}
+ {\dodosomekindoftab\hbox\hskip\xxwidth }}
+
+\def\dodosomekindoftab#1#2#3#4%
+ {#1 to #3 \bgroup
+ \forgetall
+ \ifnum\xxm>\plusone
+ #2\zeropoint \!!plus \the\numexpr\xxm -1\relax fill\relax
+ \fi
+ #4%
+ \ifnum\xxm<\xxn\relax
+ #2\zeropoint \!!plus \the\numexpr\xxn-\xxm\relax fill\relax
+ \fi
+ \egroup
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/core-mis.mkiv b/tex/context/base/core-mis.mkiv
new file mode 100644
index 000000000..e2bd28bd5
--- /dev/null
+++ b/tex/context/base/core-mis.mkiv
@@ -0,0 +1,2505 @@
+%D \module
+%D [ file=core-mis,
+%D version=1998.01.29,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Miscelaneous,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Misc Commands}
+
+% todo: kleur in legenda + letter
+
+% %D You would not expect the next macro in \CONTEXT,
+% %D wouldn't you? It's there to warn \LATEX\ users that
+% %D something is wrong.
+% %D
+% %D Obsolete now:
+% %
+% % \def\documentstyle{\showmessage\m!systems3\empty\stoptekst}
+% %
+% % \let\documentclass=\documentstyle
+% %D \macros
+% %D {simplifiedcommands, simplifycommands}
+% %D
+% %D I first needed this simplification in bookmarks. Users can
+% %D add their own if needed.
+
+\unprotect
+
+%D Sometimes (for instance in bookmarks) we need to simplify macro
+%D behaviour, so here is the hook.
+
+\ifx\simplifiedcommands\undefined \newtoks\simplifiedcommands \fi
+
+\def\simplifycommands{\the\simplifiedcommands}
+
+%D A possibly growing list:
+
+%appendtoks \def\executesynonym#1#2#3#4{#3}\to\simplifiedcommands
+%appendtoks \def\executesort#1#2#3{#3}\to\simplifiedcommands
+
+\appendtoks \def\ { }\to\simplifiedcommands
+\appendtoks \def\type#1{\letterbackslash\checkedstrippedcsname#1}\to\simplifiedcommands
+\appendtoks \def\tex#1{\letterbackslash#1}\to\simplifiedcommands
+\appendtoks \def\TeX{TeX}\to\simplifiedcommands
+\appendtoks \def\ConTeXt{ConTeXt}\to\simplifiedcommands
+\appendtoks \def\MetaPost{MetaPost}\to\simplifiedcommands
+\appendtoks \def\MetaFont{MetaFont}\to\simplifiedcommands
+\appendtoks \def\MetaFun{MetaFun}\to\simplifiedcommands
+%appendtoks \def||{-}\to\simplifiedcommands
+\appendtoks \def|#1|{\ifx#1\empty\empty-\else#1\fi}\to\simplifiedcommands
+
+\appendtoks\let\buildtextaccent\secondoftwoarguments\to\simplifiedcommands
+
+% THIS WAS MAIN-002.TEX
+
+%\def\checkinterlineskip
+% {\ifvmode
+% \ifdim\lastskip>\zeropoint
+% \nointerlineskip
+% \else\ifdim\lastkern>\zeropoint
+% \nointerlineskip
+% \fi\fi
+% \fi}
+
+\def\horitems#1#2% #1=breedte #2=commandos
+ {\scratchdimen#1%
+ \divide\scratchdimen \nofitems
+ \!!counta\zerocount
+ \def\docommand##1%
+ {\advance\!!counta \plusone
+ \processaction
+ [\@@isalign]
+ [ \v!left=>\hbox to \scratchdimen{\strut##1\hss},
+ \v!right=>\hbox to \scratchdimen{\hss\strut##1},
+ \v!middle=>\hbox to \scratchdimen{\hss\strut##1\hss},
+ \v!margin=>\ifnum\!!counta=\plusone\hss\else\hfill\fi
+ \strut##1%
+ \ifnum\!!counta=\nofitems\hss\else\hfill\fi,
+ \s!default=>\hbox to \scratchdimen{\hss\strut##1\hss}, % midden
+ \s!unknown=>\hbox to \scratchdimen{\strut##1\hss}]}% % links
+ \hbox to #1{\hss#2\hss}}
+
+\def\veritems#1#2% #1=breedte #2=commandos
+ {\scratchdimen#1%
+ \def\docommand##1%
+ {\ifdim\scratchdimen<\zeropoint % the - was a signal
+ \hbox to -\scratchdimen{\hss\strut##1}%
+ \else\ifdim\scratchdimen>\zeropoint
+ \hbox to \scratchdimen{\strut##1\hss}%
+ \else
+ \hbox{\strut##1}%
+ \fi\fi}%
+ \vbox{#2}}
+
+\def\dosetupitems[#1]%
+ {\getparameters[\??is][#1]%
+ \doif\@@iswidth\v!unknown
+ {\def\@@iswidth{\hsize}}%
+ \doifconversiondefinedelse\@@issymbol
+ {\def\doitembullet##1{\convertnumber{\@@issymbol}{##1}}}
+ {\doifsymboldefinedelse\@@issymbol
+ {\def\doitembullet##1{\symbol[\@@issymbol]}}{}}}
+
+\def\makeitemsandbullets#1%
+ {\doifelse\@@isn\v!unknown
+ {\getcommalistsize[#1]%
+ \edef\nofitems{\commalistsize}}
+ {\edef\nofitems{\@@isn}}%
+ \setbox0\hbox
+ {\doitems \@@iswidth
+ {\processcommalist[#1]\docommand}}%
+ \setbox2\hbox
+ {\doitems \@@isbulletbreedte
+ {\dorecurse\nofitems
+ {\docommand{\strut\doitembullet\recurselevel}}}}}
+
+\def\dostartitems#1#2#3%
+ {\let\doitems#2%
+ \def\@@isbulletbreedte{#3}%
+ \makeitemsandbullets{#1}%
+ \@@isbefore}
+
+\def\dostopitems
+ {\@@isafter
+ \egroup}
+
+\setvalue{doitems\v!top}#1%
+ {\dostartitems{#1}\horitems\@@iswidth
+ \noindent\vbox
+ {\forgetall
+ \doifsomething\@@issymbol
+ {\doifnot\@@issymbol\v!none
+ {\box2
+ \@@isinbetween
+ \nointerlineskip}}%
+ \box0}%
+ \dostopitems}
+
+\setvalue{doitems\v!bottom}#1%
+ {\dostartitems{#1}\horitems\@@iswidth
+ \noindent\vbox
+ {\forgetall
+ \box0
+ \doifsomething\@@issymbol
+ {\@@isinbetween
+ \nointerlineskip
+ \box2}}%
+ \dostopitems}
+
+\setvalue{doitems\v!inmargin}#1%
+ {\dostartitems{#1}\veritems{-1.5em}% - is a signal
+ \noindent\hbox{\llap{\box2\hskip\leftmargindistance}\box0}%
+ \dostopitems}
+
+\setvalue{doitems\v!left}#1%
+ {\advance\hsize -1.5em%
+ \dostartitems{#1}\veritems{1.5em}%
+ \noindent\hbox{\box2\box0}%
+ \dostopitems}
+
+\setvalue{doitems\v!right}#1%
+ {\dostartitems{#1}\veritems{0em}%
+ \noindent\hbox{\box0\hskip-\wd2\box2}%
+ \dostopitems}
+
+\unexpanded\def\setupitems
+ {\dosingleargument\dosetupitems}
+
+\def\complexitems[#1]%
+ {\bgroup
+ \setupitems[#1]%
+ \parindent\zeropoint
+ \setlocalhsize
+ \hsize\localhsize
+ \dontcomplain
+ %\doifundefined{doitems\@@islocation}%
+ % {\let\@@islocation\v!left}%
+ %\getvalue{doitems\@@islocation}}
+ \executeifdefined{doitems\@@islocation}{\let\@@islocation\v!left}}
+
+\definecomplexorsimpleempty\items
+
+\setupitems
+ [\c!location=\v!left,
+ \c!symbol=5,
+ \c!width=\hsize,
+ \c!align=\v!middle,
+ \c!n=\v!unknown,
+ \c!before=\blank,
+ \c!inbetween={\blank[\v!medium]},
+ \c!after=\blank]
+
+% \definieerplaats[naam][instellingen]
+% \stelplaatsin[naam][instellingen]
+% \plaats[[instellingen]]
+%
+% - still undocumented and also not in setupb yet
+% - kan ook intern/direct (scheelt duplicatie), zie \framedtext
+
+\def\dodefineplacement[#1][#2]%
+ {\getparameters
+ [\??pl#1]
+ [\c!left=\hss,
+ \c!right=\hss,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ \c!margin=\v!standard,
+ \c!grid=\v!middle,
+ %\c!before=,
+ %\c!after=,
+ #2]%
+ \setvalue{\e!place#1}{\doplacement[\??pl#1]}}
+
+\unexpanded\def\defineplacement
+ {\dodoubleempty\dodefineplacement}
+
+\unexpanded\def\setupplacement
+ {\dodoubleempty\dosetupplacement}
+
+\def\dosetupplacement[#1]%
+ {\dodoubleempty\getparameters[\??pl#1]}
+
+\def\doplacement
+ {\dodoubleempty\dodoplacement}
+
+\def\dodoplacement[#1][#2]% correctie moet mooier
+ {\bgroup
+ \dowithnextboxcontent
+ {\forgetall}
+ {\setlocalhsize
+ \getparameters[#1][#2]%
+ \getvalue{#1\c!before}%
+ \begingroup
+ \disableparpositions
+ \setbox\nextbox\hbox to \localhsize
+ {\getvalue{#1\c!left}%
+ \flushnextbox
+ \getvalue{#1\c!right}}%
+ \ifinsidefloat \else
+ \addlocalbackgroundtobox\nextbox
+ \fi
+ \ifgridsnapping
+ \doifundefined{#1\c!grid}{\letvalue{#1\c!grid}\v!middle}%
+ % unchecked
+ \doifinset{\getvalue{#1\c!margin}}{\v!standard,\v!yes}\noindent
+ \snaptogrid[\getvalue{#1\c!grid}]\hbox{\flushnextbox}%
+ \else
+ \doifvalue{#1\c!linecorrection}\v!on \startbaselinecorrection
+ \doifinset{\getvalue{#1\c!margin}}{\v!standard,\v!yes}\noindent
+ \flushnextbox
+ \doifvalue{#1\c!depthcorrection}\v!on\baselinecorrection
+ \doifvalue{#1\c!linecorrection }\v!on\stopbaselinecorrection
+ \fi
+ \endgroup
+ \getvalue{#1\c!after}%
+ \egroup}
+ \vbox}
+
+% Te zijner tijd [plaats=boven,onder,midden] implementeren,
+% in dat geval moet eerst de maximale hoogte worden bepaald.
+%
+% Overigens kan een en ander mooier met \halign.
+
+% there is quite some historic balast in this mechanism, the next variant
+% is a first cleanup
+
+\let\currentparagraph\empty
+
+\newcount\alcounter \newcount\alnsize \newdimen\alhsize
+
+\def\paragraphparameter#1% \checkedparameter\??al\currentparagraph#1
+ {\executeifdefined{\??al\currentparagraph#1}{\executeifdefined{\??al#1}\empty}}
+
+\def\paragraphcellmeter#1#2% \checkedparameter\??al\currentparagraph#1
+ {\executeifdefined{\??al\currentparagraph\number#1#2}{\paragraphparameter{#2}}}
+
+\def\dodefineparagraphs[#1][#2]%
+ {\edef\currentparagraph{#1}%
+ \setvalue{\s!do\s!next\currentparagraph}%
+ {\def\\{\getvalue\currentparagraph}}%
+ \setvalue\currentparagraph
+ {\getvalue{\s!do\s!next#1}%
+ \dostartparagraphs{#1}}%
+ \setvalue{\e!next\currentparagraph}%
+ {\getvalue{#1}}%
+ \setvalue{\e!start\currentparagraph}%
+ {\bgroup
+ \edef\currentparagraph{#1}%
+ \letvalue{\s!do\s!next\currentparagraph}\empty
+ \setvalue{\e!stop\currentparagraph}{\getvalue\currentparagraph\egroup}%
+ \getvalue\currentparagraph}%
+ \getparameters[\??al\currentparagraph]%
+ [%\c!n=3,
+ %\c!before=\blank,
+ %\c!after=\blank,
+ %\c!distance=1em,
+ %\c!height=\v!fit,
+ %\c!rule=\v!off,
+ %\c!command=,
+ %\c!align=,
+ %\c!tolerance=\v!tolerant,
+ %\c!rulethickness=\linewidth,
+ %\c!rulecolor=,
+ %\c!style=,
+ %\c!color=,
+ %\c!top=,
+ %\c!top=\vss,
+ %\c!bottom=\vfill,
+ #2]%
+ \setvalue{\e!setup#1\e!endsetup}%
+ {\setupparagraphs[#1]}%
+ \dorecurse
+ {\paragraphparameter\c!n}
+ {\setupparagraphs
+ [\currentparagraph]
+ [\recurselevel]
+ [\c!width=,
+ %\c!bottom=\paragraphparameter\c!bottom,
+ %\c!top=\paragraphparameter\c!top,
+ %\c!height=\paragraphparameter\c!height,
+ %\c!rule=\paragraphparameter\c!rule,
+ %\c!rulethickness=\paragraphparameter\c!rulethickness,
+ %\c!rulecolor=\paragraphparameter\c!rulecolor,
+ %\c!align=\paragraphparameter\c!align,
+ %\c!tolerance=\paragraphparameter\c!tolerance, % obsolete
+ %\c!distance=\paragraphparameter\c!distance,
+ \c!style=\paragraphparameter\c!style,
+ \c!color=\paragraphparameter\c!color]}%
+ \setupparagraphs[\currentparagraph][1][\c!distance=\zeropoint]}
+
+\unexpanded\def\defineparagraphs
+ {\dodoubleargument\dodefineparagraphs}
+
+\def\dosetupparagraphs[#1][#2][#3]%
+ {\edef\currentparagraph{#1}%
+ \ifsecondargument
+ \doifelse{#2}\v!each
+ {\dorecurse
+ {\paragraphparameter\c!n}
+ {\getparameters[\??al\currentparagraph\recurselevel][#3]}}
+ {\doifelsenothing{#3}
+ {\getparameters[\??al\currentparagraph][#2]}
+ {\def\docommand##1{\getparameters[\??al\currentparagraph##1][#3]}%
+ \processcommalist[#2]\docommand}}%
+ \else
+ \getparameters[\??al][#1]%
+ \fi}
+
+\unexpanded\def\setupparagraphs
+ {\dotripleempty\dosetupparagraphs}
+
+\setupparagraphs
+ [\c!n=3,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance=1em,
+ \c!height=\v!fit,
+ \c!rule=\v!off,
+ \c!command=,
+ \c!align=,
+ \c!tolerance=\v!tolerant, % obsolete
+ \c!rulethickness=\linewidth,
+ \c!rulecolor=,
+ \c!style=,
+ \c!color=,
+ \c!top=,
+ \c!top=\vss,
+ \c!bottom=\vfill]
+
+\def\doparagraphrule
+ {\doifelse{\paragraphcellmeter\alcounter\c!rule}\v!on
+ {\linewidth\paragraphcellmeter\alcounter\c!rulethickness
+ \scratchdimen\dimexpr(\paragraphcellmeter\alcounter\c!distance-\linewidth)/2\relax
+ \hskip\scratchdimen
+ \color[\paragraphcellmeter\alcounter\c!rulecolor]{\vrule\!!width\linewidth}%
+ \hskip\scratchdimen}
+ {\hskip\paragraphcellmeter\alcounter\c!distance}}
+
+\def\dostartparagraph
+ {\doifelsenothing{\paragraphcellmeter\alcounter\c!width}
+ {\!!widtha\alhsize
+ \divide\!!widtha \alnsize}
+ {\!!widtha\paragraphcellmeter\alcounter\c!width}%
+ \dostartattributes{\??al\currentparagraph\number\alcounter}\c!style\c!color\empty
+ \doifelse{\paragraphcellmeter\alcounter\c!height}\v!fit
+ {\setbox\scratchbox\vtop}
+ {\setbox\scratchbox\vtop to \paragraphcellmeter\alcounter\c!height}%
+ \bgroup
+ \blank[\v!disable]%
+ \forgetall
+ \paragraphcellmeter\alcounter\c!top
+ \paragraphparameter\c!inner
+ \hsize\!!widtha % setting \wd afterwards removed
+ \paragraphcellmeter\alcounter\c!inner % twice
+ \expanded{\setupalign [\paragraphcellmeter\alcounter\c!align ]}% {normal,verytolerant,stretch}
+ \expanded{\setuptolerance[\paragraphcellmeter\alcounter\c!tolerance]}% obsolete
+ \ignorespaces
+ \endgraf
+ \ignorespaces
+ %
+ % Nadeel van de onderstaande constructie is dat \everypar
+ % binnen een groep kan staan en zo steeds \begstruts
+ % worden geplaatst. Mooi is anders dus moet het anders!
+ %
+ % Hier is \Everypar niet nodig.
+ %
+ \everypar{\begstrut\everypar\emptytoks}%
+ %
+ \nospace % remove + ignore
+ \paragraphcellmeter\alcounter\c!command}
+
+\def\dostopparagraph
+ {\ifvmode
+ \removelastskip
+ \else
+ \unskip\endstrut\endgraf
+ \fi
+ \paragraphcellmeter\alcounter\c!bottom
+ \egroup
+ \ifdim\wd\scratchbox=\zeropoint % no data
+ \wd\scratchbox\!!widtha
+ \fi
+ \box\scratchbox
+ \dostopattributes
+ \ifnum\alcounter<\paragraphparameter\c!n\relax
+ \@EA\doparagraphcell
+ \else
+ \@EA\dostopparagraphs
+ \fi}
+
+\def\doparagraphcell
+ {\global\advance\alcounter \plusone
+ \doifelsenothing{\paragraphcellmeter\alcounter\c!distance}
+ {\ifnum\alcounter=\plusone\else
+ \hskip\paragraphparameter\c!distance
+ \fi}
+ {\ifnum\alcounter=\plusone
+ \hskip\paragraphcellmeter\alcounter\c!distance
+ \else
+ \doparagraphrule
+ \fi}%
+ \letvalue\currentparagraph\dostopparagraph
+ \dostartparagraph}
+
+\def\dostartparagraphs#1%
+ {\bgroup
+ \edef\currentparagraph{#1}%
+ \global\alcounter\zerocount
+ \parindent\zeropoint
+ \setlocalhsize
+ \alhsize\localhsize
+ \alnsize\paragraphparameter\c!n\relax
+ \dorecurse \alnsize
+ {\doifelsenothing{\paragraphcellmeter\recurselevel\c!distance}
+ {\ifnum\recurselevel=\plusone\else
+ \global\advance\alhsize -\paragraphparameter\c!distance
+ \fi}
+ {\global\advance\alhsize -\paragraphcellmeter\recurselevel\c!distance}%
+ \doifsomething{\paragraphcellmeter\recurselevel\c!width}
+ {\global\advance\alnsize \minusone
+ \global\advance\alhsize -\paragraphcellmeter\recurselevel\c!width}}%
+ %whitespace % gaat fout bij \framed
+ \paragraphparameter\c!before
+ \leavevmode % gaat wel goed bij \framed, brrr
+ \setbox\scratchbox\vbox\bgroup\hbox\bgroup\doparagraphcell}
+
+\def\dostopparagraphs
+ {\egroup
+ \egroup
+ \iftrue
+ \hbox{\raise\strutheight\box\scratchbox}% new
+ \else
+ \box\scratchbox % old
+ \fi
+ \par
+ \paragraphparameter\c!after
+ \egroup}
+
+\def\dosetuptab[#1]%
+ {\getparameters[\??ta]
+ [\c!headstyle=\v!normal,
+ \c!headcolor=,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!width=\v!broad,
+ \c!sample={\hskip4em},
+ \c!before=,
+ \c!after=,
+ #1]%
+ \definedescription
+ [tab]
+ [\c!headstyle=\@@taheadstyle,
+ \c!headcolor=\@@tacolor,
+ \c!sample=\@@tasample,
+ \c!width=\@@tawidth,
+ \c!before=\@@tabefore,
+ \c!after=\@@taafter]}
+
+\unexpanded\def\setuptab
+ {\dosingleargument\dosetuptab}
+
+\setuptab
+ [\c!location=\v!left]
+
+\unexpanded\def\celsius #1{#1\mathematics{^\circ}C}
+\unexpanded\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax}
+\unexpanded\def\fraction#1#2{\mathematics{#1\over#2}}
+
+% very dutch
+
+\unexpanded\def\graden {\mathematics{^\circ}}
+
+\def\bedragprefix {\euro\normalfixedspace}
+\def\bedragsuffix {}
+\def\bedragempty {\euro}
+
+\unexpanded\def\bedrag#1%
+ {\strut\hbox\bgroup
+ \let\normalfixedspace\nonbreakablespace
+ \doifelsenothing{#1}
+ {\bedragempty}
+ {\bedragprefix\digits{#1}\bedragsuffix}%
+ \egroup}
+
+% \definieeralineas[test][n=3]
+%
+% \stelalineasin[test][3][breedte=4cm,uitlijnen=links]
+%
+% \startopelkaar
+% \test hans \\ ton \\ \bedrag{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{~.~~1,--} \\
+% \test hans \\ ton \\ \bedrag{~.~~1,~~} \\
+% \test hans \\ ton \\ \bedrag{~.100,--} \\
+% \test hans \\ ton \\ \subtot{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{1.000,--} \\
+% \test hans \\ ton \\ \totaal{1.000,--} \\
+% \test hans \\ ton \\ \bedrag{nihil,--} \\
+% \test hans \\ ton \\ \totaal{nihil,--} \\
+% \test hans \\ ton \\ \subtot{nihil,--} \\
+% \stopopelkaar
+
+\def\periodswidth {.5em}
+\def\periodsdefault{3} % was 5, but now it's like \unknown
+
+\unexpanded\def\periods
+ {\dosingleempty\doperiods}
+
+\def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2
+ {\dontleavehmode
+ \begingroup
+ \scratchdimen\periodswidth
+ \hbox to \iffirstargument#1\else\periodsdefault\fi \scratchdimen
+ {\leaders\hbox to \scratchdimen{\hss.\hss}\hss}%
+ \endgroup}
+
+\unexpanded\def\unknown
+ {\periods\relax} % relax prevents lookahead for []
+
+% Example by Wolfgang Schuster on the context list:
+%
+% \unexpanded\def\fourdots{{\def\periodswidth{.3em}\periods[4]}}
+%
+% Hello\fourdots\ World\fourdots \par Hello\fourdots\ World.
+
+% compatibility macros
+
+\def\doorsnede
+ {\hbox{\rlap/$\circ$} }
+
+\unexpanded\def\ongeveer
+ {\mathematics\pm}
+
+\chardef\boundarycharactermode\plusone
+
+\def\midboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \languageparameter#1%
+ %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \or
+ \languageparameter#1%
+ \fi
+ \chardef\boundarycharactermode\plusone}
+
+\def\leftboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \languageparameter#1%
+ \nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \or
+ \languageparameter#1%
+ \fi
+ \chardef\boundarycharactermode\plusone}
+
+\def\rightboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \prewordbreak %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \languageparameter#1%
+ \or
+ \languageparameter#1%
+ \fi
+ \chardef\boundarycharactermode\plusone}
+
+% actually this is pretty old, but temporary moved here
+%
+% obsolete:
+
+\unexpanded\def\setuphyphenmark
+ {\dodoubleargument\getparameters[\??kp]}
+
+\unexpanded\def\setuphyphenmark[#1]% sign=normal|wide
+ {\dodoubleargument\getparameters[\??kp][#1]%
+ \doifelse\@@kpsign {\v!normal}% was inset?
+ {\let\textmodehyphen\normalhyphen \let\textmodehyphendiscretionary\normalhyphendiscretionary}
+ {\let\textmodehyphen\composedhyphen\let\textmodehyphendiscretionary\composedhyphendiscretionary}}
+
+\setuphyphenmark[\c!sign=\v!wide]
+% % \setuphyphenmark[\c!sign=\v!normal]
+
+\definesymbol[\c!lefthyphen] [\languageparameter\c!lefthyphen]
+\definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen]
+\definesymbol[\c!hyphen] [\languageparameter\c!hyphen]
+
+\def\normalhyphen
+ {\hbox{\directsymbol\empty\c!hyphen}}
+
+\def\composedhyphen
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}
+
+\def\normalhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!righthyphen}}
+ {\hbox{\directsymbol\empty\c!lefthyphen}}
+ {\hbox{\directsymbol\empty\c!hyphen}}}
+
+\def\composedhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}}
+
+\let\textmodehyphen \composedhyphen
+\let\textmodehyphendiscretionary\composedhyphendiscretionary
+
+\definesymbol[\c!leftcompoundhyphen] [\languageparameter\c!leftcompoundhyphen]
+\definesymbol[\c!rightcompoundhyphen] [\languageparameter\c!rightcompoundhyphen]
+\definesymbol[\c!compoundhyphen] [\languageparameter\c!compoundhyphen]
+
+\definehspace [sentence] [\zeropoint]
+\definehspace [intersentence] [.250em]
+
+\definesymbol
+ [\c!midsentence]
+ [\midboundarycharacter\c!midsentence{sentence}]
+
+\definesymbol
+ [\c!leftsentence]
+ [\leftboundarycharacter\c!leftsentence{sentence}]
+
+\definesymbol
+ [\c!rightsentence]
+ [\rightboundarycharacter\c!rightsentence{sentence}]
+
+\definesymbol
+ [\c!leftsubsentence]
+ [\leftboundarycharacter\c!leftsubsentence{sentence}]
+
+\definesymbol
+ [\c!rightsubsentence]
+ [\rightboundarycharacter\c!rightsubsentence{sentence}]
+
+\newsignal \subsentencesignal
+\newcount \subsentencelevel
+
+\let\beforesubsentence\donothing
+\let\aftersubsentence \donothing
+
+% todo: make this language option
+%
+% \def\beforesubsentence{\removeunwantedspaces}
+% \def\aftersubsentence {\ignorespaces}
+
+\def\midsentence
+ {\symbol[\c!midsentence]}
+
+\def\beginofsubsentence
+ {\beforesubsentence
+ \ifdim\lastkern=\subsentencesignal
+ \unskip
+ \kern\hspaceamount\currentlanguage{intersentence}%
+ \fi
+ \global\advance\subsentencelevel\plusone
+ \ifnum\subsentencelevel=\plusone
+ \dontleavehmode % was \leaveoutervmode
+ \fi
+ \symbol[\ifodd\subsentencelevel\c!leftsentence\else\c!leftsubsentence\fi]%
+ }% \ignorespaces}
+
+\def\endofsubsentence % relax prevents space gobbling
+ {\symbol[\ifodd\subsentencelevel\c!rightsentence\else\c!rightsubsentence\fi]%
+ \global\advance\subsentencelevel\minusone
+ \unskip
+ \kern\subsentencesignal\relax
+ \aftersubsentence}
+
+\def\beginofsubsentencespacing % relax prevents space gobbling
+ {\kern\subsentencesignal\relax}% \ignorespaces}
+
+\def\endofsubsentencespacing
+ {\ifdim\lastkern=\subsentencesignal
+ \unskip
+ \hskip\hspaceamount\currentlanguage{intersentence}%
+ % no good, actually language dependent:
+% \ignorespaces
+ \else
+ \unskip
+ \fi}
+
+%D \startbuffer
+%D test |<|test |<|test|>| test|>| test \par
+%D test|<|test|<|test|>|test|>|test \par
+%D test |<||<|test|>||>| test \par
+%D test \directdiscretionary{<}test\directdiscretionary{>} test \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\unexpanded\def\startsubsentence{\beginofsubsentence \prewordbreak\beginofsubsentencespacing}
+\unexpanded\def\stopsubsentence {\endofsubsentencespacing\prewordbreak\endofsubsentence}
+
+%D \defineXMLenvironment [subsentence]
+%D {|<|}
+%D {|>|}
+%D \defineXMLenvironment [subsentence]
+%D {\directdiscretionary{<}}
+%D {\directdiscretionary{>}}
+%D \defineXMLenvironment [subsentence]
+%D {\startsubsentence}
+%D {\stopsubsentence}
+%D
+%D \startbuffer
+%D test test test
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \processXMLbuffer
+
+\enableactivediscretionaries
+
+\definehspace [quotation] [\zeropoint]
+\definehspace [interquotation] [.125em]
+
+%definehspace [quote] [\zeropoint]
+%definehspace [speech] [\zeropoint]
+
+\definehspace [quote] [\hspaceamount\currentlanguage{quotation}]
+\definehspace [speech] [\hspaceamount\currentlanguage{quotation}]
+
+\definesymbol
+ [\c!leftquotation]
+ [\leftboundarycharacter\c!leftquotation{quotation}]
+
+\definesymbol
+ [\c!rightquotation]
+ [\rightboundarycharacter\c!rightquotation{quotation}]
+
+\definesymbol
+ [\c!leftquote]
+ [\leftboundarycharacter\c!leftquote{quote}]
+
+\definesymbol
+ [\c!rightquote]
+ [\rightboundarycharacter\c!rightquote{quote}]
+
+\definesymbol
+ [\c!leftspeech]
+ [\leftboundarycharacter\c!leftspeech{speech}]
+
+\definesymbol
+ [\c!rightspeech]
+ [\rightboundarycharacter\c!rightspeech{speech}]
+
+\definesymbol
+ [\c!middlespeech]
+ [\leftboundarycharacter\c!middlespeech{speech}]
+
+\appendtoks\def\quotation#1{"#1"}\to\simplifiedcommands
+\appendtoks\def\quote #1{'#1'}\to\simplifiedcommands
+
+%D The next features was so desperately needed by Giuseppe
+%D Bilotta that he made a module for it. Since this is a
+%D typical example of core functionality, I decided to extend
+%D the low level quotation macros in such a way that a speech
+%D feature could be build on top of it. The speech opening and
+%D closing symbols are defined per language. Italian is an
+%D example of a language that has them set.
+
+% this will replace the quotation and speed definitions
+
+\newsignal\delimitedtextsignal
+
+\let\currentdelimitedtext\s!unknown
+
+\def\delimitedtextlevel{\csname\??ci:\currentdelimitedtext:\c!level\endcsname}
+
+\def\doinitializetextlevel#1%
+ {\ifcsname\??ci:#1:\c!level\endcsname
+ \csname\??ci:#1:\c!level\endcsname\zerocount
+ \else
+ \expandafter\newcount\csname\??ci:#1:\c!level\endcsname
+ \fi}
+
+\def\delimitedtextparameter#1% will be sped up
+ {\executeifdefined{\??ci\currentdelimitedtext:\number\delimitedtextlevel#1}%
+ {\executeifdefined{\??ci\currentdelimitedtext#1}%
+ {\executeifdefined{\??ci#1}\empty}}}
+
+\unexpanded\def\definedelimitedtext
+ {\dodoubleempty\dodefinedelimitedtext}
+
+\def\dodefinedelimitedtext[#1][#2]%
+ {\doinitializetextlevel{#1}%
+ \doifassignmentelse{#2}
+ {\getparameters
+ [\??ci#1]
+ [\c!location=\v!margin, % \v!text \v!paragraph
+ \c!spacebefore=,
+ \c!spaceafter=\delimitedtextparameter\c!spacebefore,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\delimitedtextparameter\c!leftmargin,
+ \c!indentnext=\v!yes,
+ \c!before=,
+ \c!after=,
+ \c!left=,
+ \c!right=,
+ %\c!level=0,
+ \c!repeat=\v!no,
+ \c!method=,
+ #2]}%
+ {\doifdefined{#2}
+ {\copyparameters[\??ci#1][\??ci#2]
+ [\c!location,\c!spacebefore,\c!spaceafter,\c!style,\c!color,
+ \c!leftmargin,\c!rightmargin,\c!indentnext,
+ \c!before,\c!after,\c!left,\c!right]}}%
+ \doifsomething{#1}
+ {\setuvalue{#1}{\delimitedtext[#1]}%
+ \setvalue{\e!start#1}{\startdelimitedtext[#1]}%
+ \setvalue{\e!stop #1}{\stopdelimitedtext}}}
+
+\unexpanded\def\setupdelimitedtext
+ {\dotripleargument\dosetupdelimitedtext}
+
+\def\dosetupdelimitedtext[#1][#2][#3]% #2 = optional level
+ {\ifthirdargument
+ \getparameters[\??ci#1:#2][#3]%
+ \else\ifsecondargument
+ \getparameters[\??ci#1][#2]%
+ \else
+ \getparameters[\??ci][#1]%
+ \fi\fi}
+
+\def\dorepeatdelimitedtext
+ {\relax\ifcase\delimitedtextlevel\else
+ \dohandledelimitedtext\c!middle % maybe better \dohandleleftdelimitedtext
+ \fi}
+
+\let\dohandlerepeatdelimitedtext\relax
+
+\unexpanded\def\startdelimitedtext[#1]%
+ {\bgroup
+ \pushdelimitedtext{#1}%
+ \doifelse{\delimitedtextparameter\c!method}\s!font
+ {\def\dostopdelimitedtext
+ {\removeunwantedspaces\ignoredelimitedtext\c!right}%
+ \ignoredelimitedtext\c!left\ignorespaces}
+ {\doifelse{\delimitedtextparameter\c!repeat}\v!yes
+ {\let\dohandlerepeatdelimitedtext\dorepeatdelimitedtext}%
+ {\let\dohandlerepeatdelimitedtext\relax}%
+ \doifinsetelse{\delimitedtextparameter\c!location}{\v!paragraph,\v!margin}%
+ {\dosingleempty\dostartdelimitedtextpar}\dostartdelimitedtexttxt}}
+
+% \def\dostartdelimitedtextpar[#1]%
+% {\let\dostopdelimitedtext\dostopdelimitedtextpar
+% \doifsomething{\delimitedtextparameter\c!spacebefore}
+% {\blank[\delimitedtextparameter\c!spacebefore]}%
+% \delimitedtextparameter\c!before
+% % nicer:
+% % \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+% % \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+% % backward compatible:
+% \doifelsenothing{#1}
+% {\endgraf
+% \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+% \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+% \let\dodostopdelimitedtextpar\endgraf}
+% {\startnarrower[#1]\let\dodostopdelimitedtextpar\stopnarrower}%
+% % so far
+% % \dochecknextindentation{\??ci\currentdelimitedtext}% AM: not here
+% \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color\empty
+% \leftdelimitedtextmark
+% \ignorespaces}
+
+% \def\dostopdelimitedtextpar
+% {\removeunwantedspaces
+% \removelastskip
+% \rightdelimitedtextmark
+% \dostopattributes
+% \dodostopdelimitedtextpar
+% \delimitedtextparameter\c!after
+% \doifsomething{\delimitedtextparameter\c!spaceafter}
+% {\blank[\delimitedtextparameter\c!spaceafter]}%
+% \dochecknextindentation{\??ci\currentdelimitedtext}% AM: here
+% \dorechecknextindentation}% AM: This was missing!
+
+\def\dostartdelimitedtextpar[#1]%
+ {\let\dostopdelimitedtext\dostopdelimitedtextpar
+ \doifsomething{\delimitedtextparameter\c!spacebefore}
+ {\blank[\delimitedtextparameter\c!spacebefore]}%
+ \delimitedtextparameter\c!before
+ % nicer:
+ % \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+ % \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+ % backward compatible:
+ \doifelsenothing{#1}
+ {\endgraf
+ \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+ \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+ \let\dodostopdelimitedtextpar\endgraf}
+ {\startnarrower[#1]\let\dodostopdelimitedtextpar\stopnarrower}%
+ % so far
+ % \dochecknextindentation{\??ci\currentdelimitedtext}% AM: not here
+ \pushmacro\checkindentation
+ \doifsomething{\delimitedtextparameter\c!indenting} % WS
+ {\setupindenting[\delimitedtextparameter\c!indenting]}%
+ \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color\empty
+ \leftdelimitedtextmark
+ \ignorespaces}
+
+\def\dostopdelimitedtextpar
+ {\removeunwantedspaces
+ \removelastskip
+ \rightdelimitedtextmark
+ \dostopattributes
+ \popmacro\checkindentation
+ \dodostopdelimitedtextpar
+ \delimitedtextparameter\c!after
+ \doifsomething{\delimitedtextparameter\c!spaceafter}
+ {\blank[\delimitedtextparameter\c!spaceafter]}%
+ \dochecknextindentation{\??ci\currentdelimitedtext}% AM: here
+ \dorechecknextindentation}% AM: This was missing!
+
+\def\dostartdelimitedtexttxt
+ {\let\dostopdelimitedtext\dostopdelimitedtexttxt
+ \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color\empty
+ \dohandleleftdelimitedtext\c!left
+ \ignorespaces}
+
+\def\dostopdelimitedtexttxt
+ {\removeunwantedspaces
+ \dohandlerightdelimitedtext\c!right
+ \dostopattributes}
+
+\unexpanded\def\stopdelimitedtext
+ {\dostopdelimitedtext
+ \popdelimitedtext
+ \egroup}
+
+\def\pushdelimitedtext#1%
+ {\globalpushmacro\currentdelimitedtext
+ \def\currentdelimitedtext{#1}%
+ \global\advance\delimitedtextlevel\plusone}
+
+\def\popdelimitedtext
+ {\global\advance\delimitedtextlevel\minusone
+ \globalpopmacro\currentdelimitedtext}
+
+\unexpanded\def\delimitedtext[#1]%
+ {\dontleavehmode % following ones can be omited
+ \pushdelimitedtext{#1}%
+ \doifelse{\delimitedtextparameter\c!method}\s!font
+ {\dofontdrivendelimited}
+ {\doifinsetelse{\delimitedtextparameter\c!location}{\v!paragraph,\v!margin}%
+ \dodelimitedtextpar\dodelimitedtexttxt}}
+
+% shortcuts
+
+\unexpanded\def\startdelimited{\startdelimitedtext}
+\unexpanded\def\stopdelimited {\stopdelimitedtext} % no let, dynamically assigned
+\def\delimited {\delimitedtext}
+
+\def\leftdelimitedtextmark
+ {\doifsomething{\delimitedtextparameter\c!left}
+ {\setbox\scratchbox\hbox{\delimitedtextparameter\c!left}%
+ \dontleavehmode
+ \doif{\delimitedtextparameter\c!location}\v!margin{\hskip-\wd\scratchbox}%
+ \box\scratchbox}}
+
+\def\rightdelimitedtextmark
+ {\doifsomething{\delimitedtextparameter\c!right}
+ {\hsmash{\delimitedtextparameter\c!right}}}
+
+% \starttext
+% \hyphenatedword{groepsvrijstellingsverordeningen}\par
+% \hyphenatedword{\quote{groepsvrijstellingsverordeningen}}\par
+% \dorecurse{100}{\hskip300pt\hskip\recurselevel pt test \quote{xxx xxxx}.\par}
+% \page \setuppapersize[A5][A4]
+% \quotation {overly beautiful pusillanimous sesquipedalian
+% longwinded} test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test
+% \stoptext
+
+\def\dohandledelimitedtext#1#2%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+% \ifdim\lastskip=\delimitedtextsignal
+% \unskip
+ \ifdim\lastkern=\delimitedtextsignal
+ \unkern
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else
+ #2%
+ \fi
+ \ifhmode % else funny pagebeaks
+ \penalty\plustenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+% \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods
+ \kern\delimitedtextsignal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\dohandleleftdelimitedtext#1#2%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\delimitedtextsignal
+ \unkern
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else\ifdim\lastskip=\delimitedtextsignal
+ \unskip
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else
+ #2%
+ \fi\fi
+ \strut % new, needed below
+ \ifhmode % else funny pagebeaks
+ \penalty\plustenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \hskip\delimitedtextsignal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\dohandlerightdelimitedtext#1#2%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\delimitedtextsignal
+ \unkern
+ \penalty\plustenthousand
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else\ifdim\lastskip=\delimitedtextsignal
+ \unskip
+ \penalty\plustenthousand
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else
+ #2%
+ \fi\fi
+ \ifhmode % else funny pagebeaks
+ \penalty\plustenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \kern\delimitedtextsignal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+
+\def\ignoredelimitedtext#1%
+ {\delimitedtextparameter#1}
+
+\def\handledelimitedtext#1%
+ {\dohandledelimitedtext{#1}\relax}
+
+\def\handleleftdelimitedtext#1%
+ {\dohandleleftdelimitedtext{#1}\relax}
+
+\def\handlerightdelimitedtext#1%
+ {\dohandlerightdelimitedtext{#1}\relax}
+
+\unexpanded\def\dodelimitedtextpar
+ {\dohandleleftdelimitedtext\c!left\relax
+ \groupedcommand
+ \donothing
+ {\dohandlerightdelimitedtext\c!right\removelastskip
+ \popdelimitedtext}}
+
+\unexpanded\def\dodelimitedtexttxt
+ {\doifelse{\delimitedtextparameter\c!style}\v!normal
+ \doquoteddelimited\doattributeddelimited}
+
+\def\doquoteddelimited
+ {\dohandleleftdelimitedtext\c!left\relax
+ \groupedcommand
+ \donothing
+ {\dohandlerightdelimitedtext\c!right
+ \removelastskip
+ \popdelimitedtext}}
+
+\def\doattributeddelimited
+ {\groupedcommand
+ {\dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color}
+ {\dostopattributes
+ \popdelimitedtext}}
+
+\def\dofontdrivendelimited
+ {\simplegroupedcommand
+ {\languageparameter{\c!left\currentdelimitedtext}}
+ {\languageparameter{\c!right\currentdelimitedtext}%
+ \popdelimitedtext}}
+
+% testcase for nesting:
+%
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+% \setupdelimitedtext[quotation][1][left=(,right=)]
+% \setupdelimitedtext[quotation][2][left={[},right={]}]
+% \setupdelimitedtext[quotation][3][left=\{,right=\}]
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+
+\definedelimitedtext
+ [\v!quotation]
+ [\c!left={\symbol[\c!leftquotation]},
+ \c!right={\symbol[\c!rightquotation]},
+ \c!leftmargin=\v!standard]
+
+\definedelimitedtext
+ [\v!quote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!quote]
+ [\c!location=\v!text,
+ \c!left={\symbol[\c!leftquote]},
+ \c!right={\symbol[\c!rightquote]}]
+
+\definedelimitedtext
+ [\v!blockquote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!blockquote]
+ [\c!left=,
+ \c!right=]
+
+\definedelimitedtext
+ [\v!speech][\v!quotation]
+
+\setupdelimitedtext
+ [\v!speech]
+ [\c!repeat=\v!yes,
+ \c!left={\symbol[\c!leftspeech]},
+ \c!middle={\symbol[\c!middlespeech]},
+ \c!right={\symbol[\c!rightspeech]}]
+
+% how do we call an tight quote
+%
+% \definedelimitedtext
+% [\v!quotation][\v!quotation]
+%
+% \setupdelimitedtext
+% [\v!quotation]
+% [\c!indentnext=\v!no,
+% \c!spacebefore=\v!nowhite]
+
+\unexpanded\def\setupquotation{\setupdelimitedtext[\v!quotation]}
+\unexpanded\def\setupquote {\setupdelimitedtext[\v!quote]}
+
+% seldom used, move from kernel to run time module
+
+\ifx\tfx\undefined \let\tfx\relax \fi
+
+\def\basegrid
+ {\dosingleempty\dobasegrid}
+
+\def\dobasegrid[#1]%
+ {\begingroup
+ \getparameters[\??rt]
+ [\c!x=0,\c!y=0,
+ \c!nx=10,\c!ny=10,
+ \c!dx=.5,\c!dy=.5,
+ \c!xstep=0,\c!ystep=0,
+ \c!unit=\s!cm,
+ \c!scale=1,
+ \c!factor=1,
+ \c!offset=\v!yes,
+ \c!location=\v!left,
+ #1]%
+ \startpositioning
+ \dimen0=\@@rtdx\@@rtunit\relax
+ \dimen0=\@@rtscale\dimen0\relax
+ \dimen0=\@@rtfactor\dimen0\relax
+ \multiply\dimen0 \@@rtnx\relax
+ \dimen2=\@@rtdy\@@rtunit\relax
+ \dimen2=\@@rtscale\dimen2\relax
+ \dimen2=\@@rtfactor\dimen2\relax
+ \multiply\dimen2 \@@rtny\relax
+ \def\horline
+ {\vbox
+ {\hrule
+ \!!width \dimen0
+ \!!height \linewidth
+ \!!depth \!!zeropoint}}%
+ \def\verline%
+ {\vrule
+ \!!width \linewidth
+ \!!height \dimen2
+ \!!depth \!!zeropoint}%
+ \doglobal\newcounter\@@gridc
+ \doglobal\newcounter\@@gridd
+ \doglobal\newcounter\@@gride
+ \def\setlegend##1##2##3%
+ {\gdef\@@gridc{0}%
+ \dimen0=2em\relax
+ \dimen2=##2\@@rtunit\relax
+ \dimen2=\@@rtscale\dimen2\relax
+ \dimen2=\@@rtfactor\dimen2\relax
+ \divide\dimen0 \dimen2\relax
+ \xdef\@@gride{\number\dimen0}%
+ \ifnum\@@gride>50
+ \gdef\@@gride{100}%
+ \else\ifnum\@@gride>10
+ \gdef\@@gride{50}%
+ \else\ifnum\@@gride>5
+ \gdef\@@gride{10}%
+ \else\ifnum\@@gride>1
+ \gdef\@@gride{5}%
+ \else
+ \gdef\@@gride{1}%
+ \fi\fi\fi\fi
+ \gdef\@@gridd{0}%
+ \def\legend
+ {\ifnum\@@gridd=\zerocount
+ \vbox
+ {\increment(\@@gridc,##1)%
+ \hbox to 2em{\hss\@@gridc\hss}}%
+ \global\let\@@gridd=\@@gride
+ \fi
+ \doglobal\decrement\@@gridd
+ \doglobal\increment(\@@gridc,##1)}}%
+ \def\draw##1##2##3##4##5##6##7##8##9%
+ {\setuppositioning
+ [\c!state=##8,
+ \c!xstep=\v!absolute,
+ \c!ystep=\v!absolute,
+ \c!unit=\@@rtunit,
+ \c!scale=\@@rtscale,
+ \c!factor=\@@rtfactor,
+ \c!offset=\@@rtoffset,
+ \c!xoffset=##6,
+ \c!yoffset=##7]%
+ \doifelse{##9}\v!middle
+ {\scratchdimen##3pt\scratchdimen.5\scratchdimen
+ \edef\@@psxx{\withoutpt\the\scratchdimen}%
+ \scratchdimen##4pt\scratchdimen.5\scratchdimen
+ \edef\@@psyy{\withoutpt\the\scratchdimen}%
+ \scratchcounter##2\advance\scratchcounter -1
+ \edef\@@pszz{\the\scratchcounter}}
+ {\edef\@@psxx{0}\edef\@@psyy{0}\edef\@@pszz{##2}}%
+ \position(\@@psxx,\@@psyy){##1}%
+ \setuppositioning
+ [\c!state=##8,
+ \c!xstep=\v!relative,
+ \c!ystep=\v!relative,
+ \c!scale=\@@rtscale,
+ \c!factor=\@@rtfactor,
+ \c!offset=\@@rtoffset,
+ \c!unit=\@@rtunit]%
+ \dorecurse\@@pszz{\position(##3,##4){##5}}}%
+ \draw
+ \verline\@@rtnx\@@rtdx0\verline\!!zeropoint\!!zeropoint\v!start\empty
+ \draw
+ \horline\@@rtny0\@@rtdy\horline\!!zeropoint\!!zeropoint\v!start\empty
+ \tfx
+ \doifnot\@@rtxstep{0}
+ {\setlegend\@@rtxstep\@@rtdx\@@rtx
+ \draw\legend\@@rtnx\@@rtdx0\legend{-1em}{-1.5em}\v!overlay\@@rtlocation}%
+ \doifnot\@@rtystep{0}
+ {\setlegend\@@rtystep\@@rtdy\@@rty
+ \draw\legend\@@rtny0\@@rtdy\legend{-2em}{-.75ex}\v!overlay\@@rtlocation}%
+ \stoppositioning
+ \endgroup}
+
+\let\grid\basegrid
+
+% only used at pragma, move from kernel to run time module
+
+\def\referraldate
+ {\currentdate[\v!referral]}
+
+\def\doreferral[#1]%
+ {\noheaderandfooterlines
+ \bgroup
+ \getparameters
+ [\??km]
+ [\c!bet=\unknown,\c!dat=\unknown,\c!ken=\unknown,
+ \c!from=,\c!to=,\c!ref=,#1]%
+ % moet anders, hoort niet in 01b
+ \assigntranslation[\s!nl=referentie,\s!en=reference,\s!de=Referenz,\s!sp=referencia]\to\@@@kmref
+ \assigntranslation[\s!nl=van,\s!en=from,\s!de=Von,\s!sp=de]\to\@@@kmvan
+ \assigntranslation[\s!nl=aan,\s!en=to,\s!de=An,\s!sp=a]\to\@@@kmaan
+ \assigntranslation[\s!nl=betreft,\s!en=concerns,\s!de=Betreff,\s!sp=]\to\@@@kmbet
+ \assigntranslation[\s!nl=datum,\s!en=date,\s!de=Datum,\s!sp=fecha]\to\@@@kmdat
+ \assigntranslation[\s!nl=kenmerk,\s!en=mark,\s!de=Kennzeichen,\s!sp=]\to\@@@kmken
+ %
+ \definetabulate[\s!dummy][|l|p|]
+ \startdummy
+ \NC\@@@kmbet\EQ\@@kmbet\NC\NR
+ \NC\@@@kmdat\EQ\@@kmdat\NC\NR
+ \NC\@@@kmken\EQ\expanded{\smallcapped{\@@kmken}}\NC\NR
+ \doifsomething{\@@kmfrom\@@kmto}{\NC\NC\NC\NR}%
+ \doifsomething \@@kmfrom {\NC\@@@kmvan\EQ\@@kmfrom\NC\NR}%
+ \doifsomething \@@kmto {\NC\@@@kmaan\EQ\@@kmto\NC\NR}%
+ \doifsomething \@@kmref {\NC\NC\NC\NR\NC\@@@kmref\EQ\@@kmref\NC\NR}%
+ \stopdummy
+ \egroup}
+
+\def\referral
+ {\dosingleargument\doreferral}
+
+% FUZZY OLD STUFF: will be removed when not used in some manual;
+% rows instead of columns, i'd forgotten that this code exist
+%
+% \definesystemvariable{ri}
+%
+% \unexpanded\def\setuprows
+% {\dodoubleargument\getparameters[\??ri]}
+%
+% \definecomplexorsimpleempty\startrows
+%
+% \def\complexstartrows[#1]%
+% {\bgroup
+% \setuprows[#1]%
+% \let\do@@ribottom\relax
+% \def\row
+% {\do@@ribottom
+% \egroup
+% \dimen0\vsize
+% \divide\dimen0 \@@rin
+% \advance\dimen0 -\lineskip
+% \vbox to \dimen0
+% \bgroup
+% \@@ritop
+% \let\do@@ribottom\@@ribottom
+% \ignorespaces}%
+% \bgroup
+% \row}
+%
+% \unexpanded\def\stoprows
+% {\do@@ribottom
+% \egroup
+% \egroup}
+%
+% \setuprows
+% [\c!n=2,
+% \c!top=,
+% \c!bottom=\vfill]
+
+% THIS WAS MAIN-003.TEX
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+\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={=}]
+
+\unexpanded\def\xbox
+ {\bgroup\aftergroup\egroup\hbox\bgroup\tx\let\next=}
+
+\unexpanded\def\xxbox
+ {\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=}
+
+% \def\mrm#1%
+% {$\rm#1$}
+
+%D \macros
+%D {definepairedbox, setuppairedbox, placepairedbox}
+%D
+%D Paired boxes, formally called legends, but from now on a
+%D legend is just an instance, are primarily meant for
+%D typesetting some text alongside an illustration. Although
+%D there is quite some variation possible, the functionality is
+%D kept simple, if only because in most cases such pairs are
+%D typeset sober.
+%D
+%D The location specification accepts a pair, where the first
+%D keyword specifies the arrangement, and the second one the
+%D alignment. The first key of the location pair is one of
+%D \type {left}, \type {right}, \type {top} or \type {bottom},
+%D while the second key can also be \type {middle}.
+%D
+%D The first box is just collected in an horizontal box, but
+%D the second one is a vertical box that gets passed the
+%D bodyfont and alignment settings.
+
+%D Today we would implement this using layers .... but for the
+%D moment we keep it this way.
+
+% \startbuffer[test]
+% \test left \test left,top \test left,bottom \test left,middle
+% \test right \test right,top \test right,bottom \test right,middle
+% \test top \test top,left \test top,right \test top,middle
+% \test bottom \test bottom,left \test bottom,right \test bottom,middle
+% \stopbuffer
+%
+% \def\showtest#1%
+% {\pagina
+% \typebuffer[demo]
+% \def\test##1
+% {\startlinecorrection[blank]
+% \getbuffer[demo]%
+% \ruledhbox\placelegend
+% [bodyfont=6pt,location={##1}]
+% {\framed[width=.25\textwidth]{\tttf##1}}
+% {#1}
+% \stoplinecorrection}
+% \getbuffer[test]}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=\hsize,maxwidth=\makeupwidth,
+% height=\vsize,maxheight=\makeupheight]
+% \stopbuffer
+%
+% \showtest{These examples demonstrate the default settings.}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=\textwidth,
+% maxwidth=\textwidth]
+% \stopbuffer
+%
+% \showtest{\input tufte }
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=.65\textwidth]
+% \stopbuffer
+%
+% \showtest{\input knuth }
+%
+% \startbuffer[demo]
+% \setuplegend
+% [height=2cm]
+% \stopbuffer
+%
+% \showtest{These examples demonstrate some other settings.}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [width=.65\textwidth,
+% height=2cm]
+% \stopbuffer
+%
+% \showtest{These examples demonstrate some other settings.}
+%
+% \startbuffer[demo]
+% \setuplegend
+% [n=2,align=right,width=.5\textwidth]
+% \stopbuffer
+%
+% \showtest{\input zapf }
+
+%D \macros
+%D {setuplegend, placelegend}
+%D
+%D It makes sense to typeset a legend to a figure in \TEX\
+%D and not in a drawing package. The macro \type {\placelegend}
+%D combines a figure (or something else) and its legend. This
+%D command is just a paired box.
+%D
+%D The legend is placed according to \type {location}, being
+%D \type {bottom} or \type {right}. The macro macro is used as
+%D follows.
+%D
+%D \starttyping
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulation
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulation}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend
+%D {\externalfigure[cow]}
+%D {\starttabulation[|l|l|l|l|]
+%D \NC 1 \NC head \NC 3 \NC tail \NC \NR
+%D \NC 2 \NC legs \NC \NC \NC \NR
+%D \stoptabulation}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\starttabulation
+%D \NC 1 \NC head \NC \NR
+%D \NC 2 \NC legs \NC \NR
+%D \NC 3 \NC tail \NC \NR
+%D \stoptabulation}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {head \par legs \par tail}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D
+%D \placefigure
+%D {whow}
+%D {\placelegend[n=2,width=.8\hsize]
+%D {\externalfigure[cow]}
+%D {\startitemize[packed]
+%D \item head \item legs \item tail \item belly \item horns
+%D \stopitemize}}
+%D \stoptyping
+
+\newbox\firstpairedbox
+\newbox\secondpairedbox
+
+\unexpanded\def\definepairedbox
+ {\dodoubleempty\dodefinepairedbox}
+
+\def\dodefinepairedbox[#1][#2]%
+ {\getparameters
+ [\??ld#1]
+ [\c!n=1,
+ \c!distance=\bodyfontsize,
+ \c!before=,
+ \c!after=,
+ \c!color=,
+ \c!style=,
+ \c!inbetween={\blank[\v!medium]},
+ \c!width=\hsize,
+ \c!height=\vsize,
+ \c!maxwidth=\textwidth, % \makeupwidth,
+ \c!maxheight=\textheight, % \makeupheight,
+ \c!bodyfont=,
+ \c!align=,
+ \c!location=\v!bottom,
+ #2]%
+ \setvalue{\e!setup#1\e!endsetup}{\setuppairedbox[#1]}%
+ \setvalue{\e!place#1}{\placepairedbox[#1]}}
+
+\unexpanded\def\setuppairedbox
+ {\dodoubleempty\dosetuppairedbox}
+
+\def\dosetuppairedbox[#1]%
+ {\getparameters[\??ld#1]}
+
+\unexpanded\def\placepairedbox
+ {\bgroup\dodoubleempty\doplacepairedbox}
+
+\def\doplacepairedbox[#1][#2]% watch the hsize/vsize tricks
+ {\setuppairedbox[#1][#2]% % and don't change them
+ \copyparameters % brrr
+ [\??ld][\??ld#1]
+ [\c!n,\c!distance,\c!inbetween,\c!before,\c!after,
+ \c!width,\c!height,\c!maxwidth,\c!maxheight,
+ \c!color,\c!style,\c!bodyfont,\c!align,\c!location]%
+ \@@ldbefore\bgroup
+ \global\setsystemmode{pairedbox}%
+ \beforefirstpairedbox
+ \dowithnextbox
+ {\betweenbothpairedboxes
+ \dowithnextbox
+ {\afterbothpairedboxes
+ \egroup\@@ldafter
+ \egroup}
+ \vbox\bgroup
+ \insidesecondpairedbox
+ \let\next=}
+ \hbox}
+
+\def\beforefirstpairedbox
+ {\chardef\pairedlocationa1 % left
+ \chardef\pairedlocationb4 % middle
+ \getfromcommacommand[\@@ldlocation][1]%
+ \processaction
+ [\commalistelement]
+ [ \v!left=>\chardef\pairedlocationa0,
+ \v!right=>\chardef\pairedlocationa1,
+ \v!top=>\chardef\pairedlocationa2,
+ \v!bottom=>\chardef\pairedlocationa3]%
+ \getfromcommacommand[\@@ldlocation][2]%
+ \processaction
+ [\commalistelement]
+ [ \v!left=>\chardef\pairedlocationb0,
+ \v!right=>\chardef\pairedlocationb1,
+ \v!high=>\chardef\pairedlocationb2,
+ \v!top=>\chardef\pairedlocationb2,
+ \v!low=>\chardef\pairedlocationb3,
+ \v!bottom=>\chardef\pairedlocationb3,
+ \v!middle=>\chardef\pairedlocationb4]}
+
+\def\betweenbothpairedboxes
+ {\switchtobodyfont[\@@ldbodyfont]% split under same regime
+ \setbox\firstpairedbox\flushnextbox
+ \ifnum\pairedlocationa<2
+ \hsize\wd\firstpairedbox % trick
+ \hsize\@@ldwidth
+ \scratchdimen\wd\firstpairedbox
+ \advance\scratchdimen \@@lddistance
+ \bgroup\advance\scratchdimen \hsize
+ \ifdim\scratchdimen>\@@ldmaxwidth\relax
+ \egroup
+ \hsize\@@ldmaxwidth
+ \advance\hsize -\scratchdimen
+ \else
+ \egroup
+ \fi
+ \else
+ \hsize\wd\firstpairedbox
+ \hsize\@@ldwidth % can be \hsize
+ \ifdim\hsize>\@@ldmaxwidth\relax \hsize\@@ldmaxwidth \fi % can be \hsize
+ \fi
+ \ifnum\@@ldn>\plusone
+ \setrigidcolumnhsize\hsize\@@lddistance\@@ldn
+ \fi}
+
+\def\afterbothpairedboxes
+ {\setbox\secondpairedbox\vbox
+ {\ifnum\@@ldn>1
+ \rigidcolumnbalance\nextbox
+ \else
+ \flushnextbox
+ \fi}%
+ \ifnum\pairedlocationa<2\hbox\else\vbox\fi\bgroup % hide vsize
+ \forgetall
+ \ifnum\pairedlocationa<2
+ \scratchdimen\maxoftwoboxdimens\ht\firstpairedbox\secondpairedbox
+ \vsize\scratchdimen
+ \ifdim\scratchdimen<\@@ldheight\relax % can be \vsize
+ \scratchdimen\@@ldheight
+ \fi
+ \ifdim\scratchdimen>\@@ldmaxheight\relax
+ \scratchdimen\@@ldmaxheight
+ \fi
+ \valignpairedbox\firstpairedbox \scratchdimen
+ \valignpairedbox\secondpairedbox\scratchdimen
+ \else
+ \scratchdimen\maxoftwoboxdimens\wd\firstpairedbox\secondpairedbox
+ \halignpairedbox\firstpairedbox \scratchdimen
+ \halignpairedbox\secondpairedbox\scratchdimen
+ \scratchdimen\ht\secondpairedbox
+ \vsize\scratchdimen
+ \ifdim\ht\secondpairedbox<\@@ldheight\relax % can be \vsize
+ \scratchdimen\@@ldheight\relax % \relax needed
+ \fi
+ \ifdim\scratchdimen>\@@ldmaxheight\relax % todo: totale hoogte
+ \scratchdimen\@@ldmaxheight\relax % \relax needed
+ \fi
+ \ifdim\scratchdimen>\ht\secondpairedbox
+ \setbox\secondpairedbox\vbox to \scratchdimen
+ {\ifnum\pairedlocationa=3 \vss\fi %
+ \box\secondpairedbox
+ \ifnum\pairedlocationa=2 \vss\fi}% \kern\zeropoint
+ \fi
+ \fi
+ \ifcase\pairedlocationa
+ \box\secondpairedbox\hskip\@@lddistance\box\firstpairedbox \or
+ \box\firstpairedbox \hskip\@@lddistance\box\secondpairedbox\or
+ \box\secondpairedbox\endgraf \nointerlineskip \@@ldinbetween \box\firstpairedbox \or
+ \box\firstpairedbox \endgraf \nointerlineskip \@@ldinbetween \box\secondpairedbox\else
+ \fi
+ \egroup}
+
+\def\insidesecondpairedbox
+ {\forgetall
+ \setupalign[\@@ldalign]%
+ \tolerantTABLEbreaktrue % hm.
+ \blank[\v!disable]%
+ \everypar{\begstrut}}
+
+\def\maxoftwoboxdimens#1#2#3%
+ {#1\ifdim#1#2>#1#3 #2\else#3\fi}
+
+\def\valignpairedbox#1#2%
+ {\setbox#1\vbox to #2
+ {\ifcase\pairedlocationb\or\or\or\vss\or\vss\fi
+ \box#1\relax
+ \ifcase\pairedlocationb\or\or\vss\or\or\vss\fi}}
+
+\def\halignpairedbox#1#2%
+ {\setbox#1\hbox to #2
+ {\ifcase\pairedlocationb\or\hss\or\or\or\hss\fi
+ \box#1\relax
+ \ifcase\pairedlocationb\hss\or\or\or\or\hss\fi}}
+
+\definepairedbox[\v!legend]
+
+%D Goody:
+
+\appendtoks
+ \global\resetsystemmode{combination}%
+ \global\resetsystemmode{pairedbox}%
+\to \everyinsidefloat
+
+% todo: \startcombination \startcomb \stopcomb ...
+
+% needs to be mkiv'd
+
+\newcount\horcombination % counter
+\newcount\totcombination
+
+\unexpanded\def\definecombination
+ {\dodoubleempty\dodefinecombination}
+
+\def\dodefinecombination[#1][#2]%
+ {\copyparameters
+ [\??co#1][\??co]
+ [\c!width,\c!height,\c!distance,\c!location,%
+ \c!before,\c!inbetween,\c!after,\c!align,%
+ \c!style,\c!color]%
+ \getparameters
+ [\??co#1][#2]}
+
+\unexpanded\def\setupcombinations
+ {\dodoubleempty\dosetupcombinations}
+
+\def\dosetupcombinations[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??co#1][#2]%
+ \else
+ \getparameters[\??co][#1]%
+ \fi}
+
+\def\combinationparameter#1%
+ {\csname\??co\currentcombination#1\endcsname}%
+
+\unexpanded\def\startcombination
+ {\bgroup % so we can grab a group
+ \dodoubleempty\dostartcombination}
+
+% \startcombination {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2*1] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[1*2] {alpha} {a} {beta} {b} \stopcombination
+% \startcombination[2] {alpha} {a} {beta} {b} \stopcombination
+
+\def\dostartcombination[#1][#2]%
+ {\global\setsystemmode{combination}%
+ \doifnothing{#1}\firstargumentfalse % to be sure (when called in macros)
+ \doifnothing{#2}\secondargumentfalse % to be sure (when called in macros)
+ \ifsecondargument
+ \def\currentcombination{#1}%
+ \edef\currentcombinationspec{#2*1*}%
+ \else % better : \doifcombinationelse ... \??co#1\c!location
+ \doifinstringelse{*}{#1}
+ {\let\currentcombination\empty
+ \edef\currentcombinationspec{#1*1*}}
+ {\doifnumberelse{#1}
+ {\let\currentcombination\empty
+ \edef\currentcombinationspec{#1*1*}}
+ {\def\currentcombination{#1}%
+ \edef\currentcombinationspec{2*1*}}}%
+ \fi
+ \forgetall
+ \doifelse{\combinationparameter\c!height}\v!fit
+ \vbox {\vbox to \combinationparameter\c!height}%
+ \bgroup
+ \expanded{\dodostartcombination[\currentcombinationspec]}}
+
+\long\def\dodostartcombination[#1*#2*#3]%
+ {\setuphorizontaldivision
+ [\c!n=\v!fit,\c!distance=\combinationparameter\c!distance]%
+ \global\horcombination#1%
+ \global\totcombination#2%
+ \global\setbox\combinationstack\emptybox
+ \xdef\maxhorcombination{\the\horcombination}%
+ \multiply\totcombination\horcombination
+ \tabskip\zeropoint
+ \doifelse{\combinationparameter\c!width}\v!fit
+ {\halign}{\halign to \combinationparameter\c!width}%
+ \bgroup&%
+ %\hfil##\hfil% now : location={left,top}
+ \expanded{\doifnotinset{\v!left}{\combinationparameter\c!location}}\hfil
+ ##%
+ \expanded{\doifnotinset{\v!right}{\combinationparameter\c!location}}\hfil
+ &\tabskip\zeropoint \!!plus 1fill##\cr
+ \docombination}
+
+\def\docombination % we want to add struts but still ignore an empty box
+ {\dowithnextbox
+ {\setbox0\flushnextbox
+ \dowithnextbox
+ {\setbox2\flushnextbox
+ \dodocombination}%
+ \vtop\bgroup
+ \def\next
+ {\futurelet\nexttoken\nextnext}%
+ \def\nextnext
+ {\ifx\nexttoken\egroup \else % the next box is empty
+ \hsize\wd0
+ \setupalign[\combinationparameter\c!align]%
+ \dostartattributes{\??co\currentcombination}\c!style\c!color\empty
+ \bgroup
+ \aftergroup\endstrut
+ \aftergroup\dostopattributes
+ \aftergroup\egroup
+ \begstrut
+ \fi}%
+ \afterassignment\next\let\nexttoken=}
+ \hbox}
+
+\def\depthonlybox
+ {\dowithnextbox{\vtop{\hsize\wd\nextbox\kern\zeropoint\box\nextbox}}\vbox}
+
+\def\dodocombination
+ {\vbox
+ {\forgetall % \setupwhitespace[\v!none]%
+ \let\next\vbox
+ \expanded{\processallactionsinset[\combinationparameter\c!location]}
+ [ \v!top=>\let\next\depthonlybox, % \tbox,
+ \v!middle=>\let\next\halfwaybox]%
+ \next{\copy0}%
+ % we need to save the caption for a next alignment line
+ \saveoncombinationstack2}%
+ \ifnum\totcombination>\plusone
+ \global\advance\totcombination\minusone
+ \global\advance\horcombination\minusone
+ \ifnum\horcombination=\zerocount
+ \def\next
+ {\cr
+ \flushcombinationstack
+ \noalign
+ {\forgetall % \setupwhitespace[\v!none]% no
+ \global\setbox\combinationstack\emptybox
+ \nointerlineskip
+ \combinationparameter\c!after
+ \combinationparameter\c!before
+ \vss
+ \nointerlineskip}%
+ \global\horcombination\maxhorcombination\relax
+ \docombination}%
+ \else
+ \def\next
+ {&&&\hskip\combinationparameter\c!distance&\docombination}%
+ \fi
+ \else
+ \def\next
+ {\cr
+ \flushcombinationstack
+ \egroup}%
+ \fi
+ \next}
+
+% formally ok:
+%
+% \unexpanded\def\stopcombination
+% {\egroup
+% \egroup}
+%
+% more robust:
+%
+% \unexpanded\def\stopcombination
+% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries
+% \egroup
+% \egroup}
+%
+% even better:
+
+\unexpanded\def\stopcombination
+ {{\scratchtoks{{}{}{}}\dorecurse\totcombination{\appendtoks{}{}{}{}\to\scratchtoks}\expandafter}\the\scratchtoks
+ \egroup
+ \egroup}
+
+\newbox\combinationstack
+
+\def\saveoncombinationstack#1%
+ {\global\setbox\combinationstack\hbox
+ {\hbox{\box#1}\unhbox\combinationstack}}
+
+\def\flushcombinationstack
+ {\noalign
+ {\ifdim\ht\combinationstack>\zeropoint
+\nointerlineskip % nieuw
+ \combinationparameter\c!inbetween
+ \global\horcombination\maxhorcombination
+ \globallet\doflushcombinationstack\dodoflushcombinationstack
+ \else
+ \global\setbox\combinationstack\emptybox
+ \globallet\doflushcombinationstack\donothing
+ \fi}%
+ \doflushcombinationstack\crcr}
+
+\gdef\dodoflushcombinationstack
+ {\global\setbox\combinationstack\hbox
+ {\unhbox\combinationstack
+ \global\setbox1\lastbox}%
+ \box1% \ruledhbox{\box1}%
+ \global\advance\horcombination\minusone\relax
+ \ifnum\horcombination>\zerocount
+ \def\next{&&&&\doflushcombinationstack}%
+ \else
+ \global\setbox\combinationstack\emptybox
+ %\let\next\relax
+ \@EA\gobbleoneargument
+ \fi
+ \next}
+
+\setupcombinations
+ [\c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!distance=1em,
+ \c!location=\v!bottom, % can be something {top,left}
+ \c!before=\blank,
+ \c!inbetween={\blank[\v!medium]},
+ \c!style=,
+ \c!color=,
+ \c!after=,
+ \c!align=\v!middle]
+
+%D \macros
+%D {startfloatcombination}
+%D
+%D \setupexternalfigures[directory={../sample}]
+%D \startbuffer
+%D \placefigure
+%D [left,none]
+%D {}
+%D {\startfloatcombination[2*2]
+%D \placefigure{alpha}{\externalfigure[cow.pdf][width=1cm]}
+%D \placefigure{beta} {\externalfigure[cow.pdf][width=2cm]}
+%D \placefigure{gamma}{\externalfigure[cow.pdf][width=3cm]}
+%D \placefigure{delta}{\externalfigure[cow.pdf][width=4cm]}
+%D \stopfloatcombination}
+%D
+%D \input tufte
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\startfloatcombination
+ {\dodoubleempty\dostartfloatcombination}
+
+\def\dostartfloatcombination[#1][#2]%
+ {\vbox\bgroup
+ %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature
+ \chardef\postcenterfloatmethod\zerocount
+ \forcelocalfloats
+ \unexpanded\def\stopfloatcombination
+ {\scratchtoks\emptytoks
+ \dorecurse\noflocalfloats
+ {\appendetoks{\noexpand\getlocalfloat{\recurselevel}}{}\to\scratchtoks}%
+ \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination
+ \resetlocalfloats
+ \egroup}}
+
+\unexpanded\def\placerelativetoeachother#1#2%
+ {\bgroup
+ \dowithnextbox
+ {\bgroup
+ \setbox0\box\nextbox
+ \dowithnextbox
+ {\setbox2\box\nextbox
+ #1{#2#########2\cr\box0\cr\box2\cr}
+ \egroup
+ \egroup}
+ \hbox}
+ \hbox}
+
+\unexpanded\def\placeontopofeachother{\placerelativetoeachother\halign\hss}
+\unexpanded\def\placesidebyside {\placerelativetoeachother\valign\vss}
+
+%D A couple of examples, demonstrating how the depth is
+%D taken care of:
+%D
+%D \startbuffer
+%D test\rotate[frame=on, rotation=0] {gans}%
+%D test\rotate[frame=on, rotation=90] {gans}%
+%D test\rotate[frame=on, rotation=180]{gans}%
+%D test\rotate[frame=on, rotation=270]{gans}%
+%D test
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% When we rotate over arbitrary angles, we need to relocate the
+% resulting box because rotation brings that box onto the negative
+% axis. The calculations (mostly sin and cosine) need to be tuned for
+% the way a box is packages (i.e. the refence point). A typical example
+% of drawing, scribbling, and going back to the days of school math.
+%
+% We do a bit more calculations than needed, simply because that way
+% it's easier to debug the code.
+
+\def\dododorotatenextbox
+ {\setbox\nextbox\vbox to \@@layerysiz
+ {\vfill
+ \hbox to \@@layerxsiz
+ {\dostartrotation\@@rorotation
+ \nextboxwd\zeropoint
+ \nextboxht\zeropoint
+ \flushnextbox
+ \dostoprotation
+ \hfill}%
+ \kern\@@layerypos}%
+ \setbox\nextbox\hbox
+ {\kern\@@layerxpos
+ \kern\@@layerxoff
+ \lower\@@layeryoff\flushnextbox}}
+
+\def\dodorotatenextbox#1#2% quite some trial and error -)
+ {\dontshowcomposition
+ \dontcomplain
+ \ifnum#2=\plusfour
+ % new, location=middle
+ \!!widthb \nextboxwd
+ \!!heightb\nextboxht
+ \!!depthb \nextboxdp
+ \setbox\nextbox\vbox{\vskip.5\nextboxht\hskip-.5\nextboxwd\flushnextbox}%
+ \smashbox\nextbox
+ \fi
+ \!!widtha \nextboxwd
+ \!!heighta\nextboxht
+ \!!deptha \nextboxdp
+ \!!doneafalse
+ \!!donebfalse
+ \ifcase#2\or
+ % 1: fit
+ \or
+ % 2: depth, not fit
+ \!!doneatrue
+ \!!donebtrue
+ \or
+ % 3: depth, fit
+ \!!donebtrue
+ \fi
+ \setbox\nextbox\vbox{\hbox{\raise\nextboxdp\flushnextbox}}%
+ \!!dimena \nextboxht
+ \setcalculatedcos\cos\@@rorotation
+ \setcalculatedsin\sin\@@rorotation
+ \@@layerxpos\zeropoint
+ \@@layerypos\zeropoint
+ \@@layerxoff\zeropoint
+ \@@layeryoff\zeropoint
+ \ifdim\sin\points>\zeropoint
+ \ifdim\cos\points>\zeropoint
+ \@@layerxsiz \cos\!!widtha
+ \@@layerysiz \sin\!!widtha
+ \advance\@@layerxsiz \sin\!!dimena
+ \advance\@@layerysiz \cos\!!dimena
+ \@@layerypos \cos\!!dimena
+ \if!!donea
+ \@@layerxoff \negated\sin\!!dimena
+ \advance\@@layerxoff \sin\!!deptha
+ \fi
+ \if!!doneb
+ \@@layeryoff \cos\!!deptha
+ \fi
+ \dododorotatenextbox
+ \else
+ \@@layerxsiz \negated\cos\!!widtha
+ \@@layerysiz \sin\!!widtha
+ \advance\@@layerxsiz \sin\!!dimena
+ \advance\@@layerysiz \negated\cos\!!dimena
+ \@@layerxpos \negated\cos\!!widtha
+ \if!!donea
+ \@@layerxoff -\@@layerxsiz
+ \advance\@@layerxoff \sin\!!deptha
+ \fi
+ \if!!doneb
+ \@@layeryoff \negated\cos\!!heighta
+ \fi
+ \dododorotatenextbox
+ \wd\nextbox\if!!donea\sin\!!deptha\else\@@layerxsiz\fi
+ \fi
+ \else
+ \ifdim\cos\points<\zeropoint
+ \@@layerxsiz \negated\cos\!!widtha
+ \@@layerysiz \negated\sin\!!widtha
+ \advance\@@layerxsiz \negated\sin\!!dimena
+ \advance\@@layerysiz \negated\cos\!!dimena
+ \@@layerxpos \@@layerxsiz
+ \@@layerypos \negated\sin\!!widtha
+ \if!!donea
+ \@@layerxoff -\@@layerxsiz
+ \advance\@@layerxoff \negated\sin\!!heighta
+ \fi
+ \if!!doneb
+ \@@layeryoff \@@layerysiz
+ \advance\@@layeryoff \cos\!!deptha
+ \fi
+ \dododorotatenextbox
+ \wd\nextbox\if!!donea\negated\sin\!!heighta\else\@@layerxsiz\fi
+ \else
+ \@@layerxsiz \cos\!!widtha
+ \@@layerysiz \negated\sin\!!widtha
+ \advance\@@layerxsiz \negated\sin\!!dimena
+ \advance\@@layerysiz \cos\!!dimena
+ \ifdim\sin\points=\zeropoint
+ \@@layerxpos \zeropoint
+ \@@layerxoff \zeropoint
+ \@@layerypos \@@layerysiz
+ \if!!doneb
+ \@@layeryoff \!!deptha
+ \fi
+ \else
+ \@@layerypos \@@layerysiz
+ \@@layerxpos \negated\sin\!!dimena
+ \if!!donea
+ \@@layerxoff -\@@layerxsiz
+ \advance\@@layerxoff \negated\sin\!!heighta
+ \fi
+ \if!!doneb
+ \@@layeryoff \negated\sin\!!deptha
+ \fi
+ \fi
+ \dododorotatenextbox
+ \ifdim\sin\points=\zeropoint
+ \else
+ \wd\nextbox\if!!donea\negated\sin\!!heighta\else\@@layerxsiz\fi
+ \fi
+ \fi
+ \fi
+ % new, location=middle
+ \ifnum#2=\plusfour
+ \setbox\nextbox\vbox{\vskip-.5\!!heightb\hskip.5\!!heightb\flushnextbox}%
+ \nextboxwd\!!widthb
+ \nextboxht\!!heightb
+ \nextboxdp\!!depthb
+ \fi}
+
+\def\dorotatenextbox#1#2%
+ {\doifsomething{#1}
+ {\edef\@@rorotation{\realnumber{#1}}% get rid of leading zeros and spaces
+ \setbox\nextbox\vbox{\flushnextbox}% not really needed
+ \dodorotatenextbox\@@rorotation#2}%
+ \hbox{\boxcursor\flushnextbox}}
+
+\def\dodorotatebox#1% {angle} \hbox/\vbox/\vtop
+ {\bgroup\hbox\bgroup % compatibility hack
+ \dowithnextbox
+ {\dorotatenextbox{#1}\plusone
+ \egroup\egroup}}
+
+\def\dorotatebox#1% {angle} \hbox/\vbox/\vtop
+ {\ifcase#1\relax
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\dodorotatebox
+ \fi{#1}}
+
+\unexpanded\def\rotate % \bgroup: \rotate kan argument zijn
+ {\bgroup\complexorsimpleempty\rotate}
+
+% \def\complexrotate[#1]% framed met diepte !
+% {\getparameters[\??ro][#1]%
+% \processaction
+% [\@@rolocation]
+% [ \v!depth=>\!!counta\plusthree\donefalse,% depth fit - raw box
+% \v!fit=>\!!counta\plustwo \donefalse,% depth tight - raw box
+% \v!broad=>\!!counta\plusone \donefalse,% nodepth fit - raw box
+% \v!high=>\!!counta\plusone \donetrue ,% nodepth fit - framed
+% \v!middle=>\!!counta\plusfour \donefalse,% centered, keep dimensions
+% \s!default=>\!!counta\plusthree\donetrue ,% depth fit - framed
+% \s!unknown=>\!!counta\plusthree\donetrue ]% depth fit - framed
+% \ifdone
+% \def\docommand{\localframed[\??ro][#1,\c!location=]}%
+% \else
+% \let\docommand\relax
+% \fi
+% \dowithnextbox{\dorotatenextbox\@@rorotation\!!counta\egroup}\vbox\docommand}
+
+\setvalue{\??ro::\c!location::\v!depth }{\!!counta\plusthree\donefalse} % depth fit - raw box
+\setvalue{\??ro::\c!location::\v!fit }{\!!counta\plustwo \donefalse} % depth tight - raw box
+\setvalue{\??ro::\c!location::\v!broad }{\!!counta\plusone \donefalse} % nodepth fit - raw box
+\setvalue{\??ro::\c!location::\v!high }{\!!counta\plusone \donetrue } % nodepth fit - framed
+\setvalue{\??ro::\c!location::\v!middle }{\!!counta\plusfour \donefalse} % centered, keep dimensions
+\setvalue{\??ro::\c!location::\v!default}{\!!counta\plusthree\donetrue } % depth fit - framed
+
+\def\complexrotate[#1]% framed met diepte !
+ {\getparameters[\??ro][#1]%
+ \executeifdefined{\??ro::\c!location::\@@rolocation}{\!!counta\plusthree\donetrue}%
+ \ifdone
+ \def\docommand{\localframed[\??ro][#1,\c!location=]}%
+ \else
+ \let\docommand\relax
+ \fi
+ \dowithnextbox{\dorotatenextbox\@@rorotation\!!counta\egroup}\vbox\docommand}
+
+\presetlocalframed[\??ro]
+
+\unexpanded\def\setuprotate
+ {\dodoubleargument\getparameters[\??ro]}
+
+\setuprotate
+ [\c!rotation=90,
+ \c!location=\v!normal,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+% \dostepwiserecurse{0}{360}{10}
+% {\startlinecorrection[blank]
+% \hbox
+% {\expanded{\setuprotate[rotation=\recurselevel]}%
+% \traceboxplacementtrue
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=depth] {\ruledhbox{\bfb (depth)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=fit] {\ruledhbox{\bfb (fit)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=broad] {\ruledhbox{\bfb (broad)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=normal]{\ruledhbox{\bfb (normal)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=high] {\ruledhbox{\bfb (high)}}}}}
+% \stoplinecorrection}
+
+% to be used in some other places! todo!
+%
+% divides \hsize in fractions, will be made a bit more
+% clever and advanced when needed
+%
+% \horizontaldivision[n/m,elements,distance]
+%
+% \horizontaldivision[2/5,3,1em]
+% \horizontaldivision[2/5,3,1em]
+% \horizontaldivision[1/5,3,1em]
+%
+% \setuphorizontaldivision[afstand=,aantal=] (passend,passend)
+
+\def\??fr{@@fr}
+
+\unexpanded\def\setuphorizontaldivision
+ {\dodoubleargument\getparameters[\??fr]}
+
+\def\horizontaldivision
+ {\dosingleargument\dohorizontaldivision}
+
+\def\dohorizontaldivision[#1]%
+ {\dodohorizontaldivision[#1,,,,,,]}
+
+\def\dodohorizontaldivision[#1/#2,#3,#4,#5]%
+ {\doifelsenothing{#3}
+ {\doifelse\@@frn\v!fit
+ {\!!counta#2\relax}
+ {\!!counta\@@frn\relax}}
+ {\!!counta#3\relax}%
+ \doifelsenothing{#4}
+ {\doifelse\@@frdistance\v!fit
+ {\!!widtha\zeropoint}
+ {\!!widtha\@@frdistance}}
+ {\!!widtha#4}%
+ \advance\!!counta \minusone
+ \multiply\!!widtha \!!counta
+ \advance\hsize -\!!widtha
+ \divide\hsize #2\relax
+ \hsize#1\hsize}
+
+\setuphorizontaldivision
+ [\c!distance=\tfskipsize,
+ \c!n=\v!fit]
+
+%D This one is for Daniel Pittman, who wanted tight
+%D fractions. We show three versions. First the simple
+%D one using \type {\low} and \type {high}:
+%D
+%D \startbuffer
+%D \def\vfrac#1#2%
+%D {\hbox{\high{\tx#1\kern-.25em}/\low{\kern-.25em\tx#2}}}
+%D
+%D test \vfrac{1}{2} test \vfrac{123}{456} test
+%D \stopbuffer
+%D
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D A better way to handle the kerning is the following, here
+%D we kind of assume that tye slash is symmetrical and has
+%D nearly zero width.
+%D
+%D \startbuffer
+%D \def\vfract#1#2%
+%D {\hbox{\high{\tx#1}\hbox to \zeropoint{\hss/\hss}\low{\tx#2}}}
+%D \stopbuffer
+%D
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D The third and best alternative is the following:
+%D
+%D {\showmakeup\getbuffer}\crlf\getbuffer
+%D
+%D This time we measure the height of the \type {/} and
+%D shift over the maximum height and depths of this
+%D character and the fractional digits (we use 57 as
+%D sample). Here we combine all methods in one macros.
+
+\chardef\vulgarfractionmethod=3
+
+\definehspace[vulgarfraction][.25em] % [.15em]
+\definesymbol[vulgarfraction][/] % [\raise.2ex\hbox{/}]
+
+\unexpanded\def\vulgarfraction#1#2%
+ {\dontleavehmode
+ \hbox
+ {\def\vulgarfraction{vulgarfraction}%
+ \ifcase\vulgarfractionmethod
+ #1\symbol[\vulgarfraction]#2%
+ \or
+ \high{\tx#1\kern-\hspaceamount\empty\vulgarfraction}%
+ \symbol[\vulgarfraction]%
+ \low {\kern-\hspaceamount\empty\vulgarfraction\tx#2}%
+ \or
+ \high{\tx#1}%
+ \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}%
+ \low{\tx#2}%
+ \or
+ \setbox0\hbox{\symbol[\vulgarfraction]}%
+ \setbox2\hbox{\txx57}%
+ \raise\ht0\hbox{\lower\ht2\hbox{\txx#1}}%
+ \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}%
+ \lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}%
+ \fi}}
+
+\ifx\vfrac\undefined \let\vfrac\vulgarfraction \fi
+
+%D \starttabulate
+%D \HL
+%D \NC \bf method \NC \bf visualization \NC\NR
+%D \HL
+%D \NC 0 \NC \chardef\vulgarfractionmethod0\vulgarfraction{1}{2} \NC\NR
+%D \NC 1 \NC \chardef\vulgarfractionmethod1\vulgarfraction{1}{2} \NC\NR
+%D \NC 2 \NC \chardef\vulgarfractionmethod2\vulgarfraction{1}{2} \NC\NR
+%D \NC 3 \NC \chardef\vulgarfractionmethod3\vulgarfraction{1}{2} \NC\NR
+%D \HL
+%D \stoptabulate
+
+%D Under construction:
+%D
+%D \starttyping
+%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 \stoptyping
+
+\let\handlecommalistsentence\firstofoneargument
+
+\def\commalistsentenceone{and-1}
+\def\commalistsentencetwo{and-2}
+
+\def\commalistsentence
+ {\dodoubleempty\docommalistsentence}
+
+\def\docommalistsentence[#1][#2]%
+ {\bgroup
+ \getfromcommalist[#2][1]%
+ \ifx\commalistelement\empty
+ \def\@@commalistsentenceone{\labeltext\commalistsentenceone}%
+ \else
+ \let\@@commalistsentenceone\commalistelement
+ \fi
+ \getfromcommalist[#2][2]%
+ \ifx\commalistelement\empty
+ \def\@@commalistsentencetwo{\labeltext\commalistsentencetwo}%
+ \else
+ \let\@@commalistsentencetwo\commalistelement
+ \fi
+ \getcommalistsize[#1]%
+ \ifcase\commalistsize\relax
+ \def\serializedcommalist{#1}%
+ \else
+ \let\serializedcommalist\empty
+ \scratchcounter\zerocount
+ \def\docommand##1%
+ {\advance\scratchcounter \plusone
+ \ifnum\scratchcounter=\plusone
+ \scratchtoks{\handlecommalistsentence{##1}}%
+ \else
+ \ifnum\scratchcounter=\commalistsize
+ \appendtoks\@@commalistsentencetwo\handlecommalistsentence{##1}\to\scratchtoks
+ \else
+ \appendtoks\@@commalistsentenceone\handlecommalistsentence{##1}\to\scratchtoks
+ \fi
+ \fi}%
+ \processcommacommand[#1]\docommand
+ \edef\serializedcommalist{\the\scratchtoks}%
+ \fi
+ \serializedcommalist
+ \egroup}
+
+\def\commacommandsentence[#1]{\@EA\commalistsentence\@EA[#1]}
+
+\ifx\textcomma\undefined \def\textcomma{,} \fi
+
+\setuplabeltext [\s!nl] [and-1=\textcomma\ , and-2= en ]
+\setuplabeltext [\s!en] [and-1=\textcomma\ , and-2=\textcomma\ and ]
+\setuplabeltext [\s!de] [and-1=\textcomma\ , and-2= und ]
+
+%D \macros
+%D {somekindoftab}
+%D
+%D This macro can be used to create tabs:
+%D
+%D \starttyping
+%D \setupheadertexts[{\somekindoftab[alternative=horizontal]{\framed{\realfolio}}}]
+%D \setuptexttexts [{\somekindoftab[alternative=vertical] {\framed{\realfolio}}}]
+%D
+%D \starttext
+%D \showframe \dorecurse{10}{test\page}
+%D \stoptext
+%D \stoptyping
+
+\def\somekindoftab
+ {\dosingleempty\dosomekindoftab}
+
+\def\dosomekindoftab[#1]%
+ {\bgroup
+ \getparameters[xx]
+ [\c!alternative=\v!vertical,
+ \c!width=\textwidth,\c!height=\textheight,
+ \c!n=\lastpage,\c!m=\realpageno,
+ #1]%
+ \doifelse\xxalternative\v!vertical
+ {\dodosomekindoftab\vbox\vskip\xxheight}
+ {\dodosomekindoftab\hbox\hskip\xxwidth }}
+
+\def\dodosomekindoftab#1#2#3#4%
+ {#1 to #3 \bgroup
+ \forgetall
+ \ifnum\xxm>\plusone
+ #2\zeropoint \!!plus \the\numexpr\xxm -1\relax fill\relax
+ \fi
+ #4%
+ \ifnum\xxm<\xxn\relax
+ #2\zeropoint \!!plus \the\numexpr\xxn-\xxm\relax fill\relax
+ \fi
+ \egroup
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/core-par.mkii b/tex/context/base/core-par.mkii
new file mode 100644
index 000000000..0b283b294
--- /dev/null
+++ b/tex/context/base/core-par.mkii
@@ -0,0 +1,300 @@
+%D \module
+%D [ file=core-par,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Paragraph Tricks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Pararaph Tricks}
+
+\unprotect
+
+% \ifprocesspreviousparagraphs
+%
+% \nofskippedparagraphs
+% \paragraphnumber
+% \nofparagraphs
+%
+% \dosetparagraph
+% \doresetparagraph
+% \dobeforeparagraph
+% \doafterparagraph
+% \dobeforeskipparagraph
+% \doafterskipparagraph
+%
+% \pushparagraphs\endcommand alle alineas tot \endcommand laden
+% \pushmoreparagraphs\endcommand alle alineas tot \endcommand toevoegen
+% \popparagraphs alle alineas oproepen
+% \popparagraphs[a,b,c] enkele alineas oproepen [geen]
+%
+% tzt een optionele prefix:
+%
+% \pushparagraphs[xxx]\endcommand alle alineas tot \endcommand laden
+% \popparagraphs[xxx] alle alineas oproepen
+% \popparagraphs[xxx][a,b,c] enkele alineas oproepen
+%
+% \numberparagraphs
+% \numberparagraphlines
+% \resetparagraphlines
+
+\newif\ifprocesspreviousparagraphs % public
+\newif\ifprocessallparagraphs % private
+
+\newcounter\totalnofparagraphs % private
+\newcounter\globalparagraphnumber % private
+\newcounter\discardedparagraphs % private
+\newcounter\mostrecentparagraphtotal % public
+
+\let\dosetparagraph = \relax % public
+\let\doresetparagraph = \relax % public
+\let\dobeforeparagraph = \relax % public
+\let\doafterparagraph = \relax % public
+\let\dobeforeskipparagraph = \relax % public
+\let\doafterskipparagraph = \relax % public
+
+\def\paragraphnumber {} % public
+\def\nofparagraphs {} % public
+\def\nofskippedparagraphs {} % public
+
+\def\paragraphprefix {paragraph} % private
+
+% voorlopig, wordt nog class
+
+\def\resetparagraphlines
+ {\global\linenumber\plusone}
+
+\def\numberparagraphs % instelbaar maken en slimmer ivm breedte regelnummer !!!!!
+ {\processpreviousparagraphstrue
+ \def\dosetparagraph
+ {\bgroup
+ \resetparagraphlines
+ \EveryPar
+ {\strut\inleftmargin{\tf{\tx\paragraphnumber}\kern2em}%
+ \ignorespaces}}%
+ \def\doresetparagraph
+ {\resetparagraphlines
+ \egroup}}
+
+\def\numberparagraphlines
+ {\processpreviousparagraphstrue
+ \def\dosetparagraph
+ {\resetparagraphlines}%
+ \def\doresetparagraph
+ {\resetparagraphlines}%
+ \def\dobeforeparagraph
+ {\startlinenumbering[\v!continue]}%
+ \def\doafterparagraph
+ {\stoplinenumbering}%
+ \def\dobeforeskipparagraph
+ {\stoplinenumbering
+ \let\paragraphnumber\relax}%
+ \def\doafterskipparagraph
+ {\startlinenumbering[\v!continue]}}
+
+\long\def\directpushparagraph#1%
+ {\doglobal\increment\totalnofparagraphs
+ \ifnum\totalnofparagraphs>0\nofskippedparagraphs\relax
+ \setgvalue{\paragraphprefix\totalnofparagraphs}{#1}%
+ \else
+ \setgvalue{\paragraphprefix\totalnofparagraphs}{\skipparagraph#1\par}%
+ \fi}
+
+\long\def\directskipparagraph#1%
+ {\doglobal\increment\totalnofparagraphs
+ \setgvalue{\paragraphprefix\totalnofparagraphs}{\skipparagraph#1\par}}
+
+\def\dopushparagraphs#1%
+ {\global\let\mostrecentparagraphtotal\totalnofparagraphs
+ \ifx#1\undefined
+ \let#1\relax
+ \fi
+ \defconvertedargument\asciia{#1}%
+ \defconvertedargument\asciib{ }% % lege regel
+ \def\dopushparagraph##1\par
+ {\defconvertedargument\asciic{##1}%
+ \doifelse\asciic\asciia
+ {#1}
+ {\doifsomething\asciic % lege paragraaf
+ {\doifnot\asciic\asciib
+ {\directpushparagraph{#1}}}%
+ \dopushparagraph}}%
+ \dopushparagraph}
+
+\def\pushparagraphs
+ {\doglobal\newcounter\totalnofparagraphs
+ \dopushparagraphs}
+
+\def\pushmoreparagraphs
+ {\dopushparagraphs}
+
+\def\dododopopparagraph#1% no grouping, i.v.m. sidefloats
+ {\ifnum#1>\totalnofparagraphs\relax
+ \else
+ \let\paragraphnumber\globalparagraphnumber
+ \decrement(\paragraphnumber,\discardedparagraphs)%
+ \dobeforeparagraph
+ \ifhmode\indentation\fi\getvalue{\paragraphprefix#1}\par
+ \doafterparagraph
+ \fi}
+
+\long\def\skipparagraph#1\par
+ {\doglobal\increment\discardedparagraphs
+ \ifprocessallparagraphs
+ \dobeforeskipparagraph
+ \ifhmode\indentation\fi#1\par
+ \doafterskipparagraph
+ \fi}
+
+\def\dodopopparagraph
+ {\dododopopparagraph}
+
+\def\dodoprocessparagraph#1%
+ {\ifprocesspreviousparagraphs
+ \bgroup
+ \setbox0\vbox{\dododopopparagraph{#1}}%
+ \egroup
+ \fi}
+
+\def\processpreviousparagraphs[#1]% process previous ones
+ {\ifprocesspreviousparagraphs
+ \bgroup
+ \getfromcommacommand[#1][1]% tzt snelle \..command.. testen
+ \let\totalnofparagraphs\commalistelement
+ \decrement\totalnofparagraphs
+ \let\dodopopparagraph\dodoprocessparagraph
+ \popparagraphs
+ \egroup
+ \fi}
+
+\def\dopopparagraphs[#1]%
+ {\doifnotinset{#1}{\v!none,0}
+ {\dosetparagraph
+ \doglobal\newcounter\globalparagraphnumber
+ \doglobal\newcounter\discardedparagraphs
+ \doifelse{#1}{}
+ {\processallparagraphstrue}
+ {\processallparagraphsfalse}%
+ \def\dopopparagraph
+ {\doglobal\increment\globalparagraphnumber
+ \ifnum\globalparagraphnumber>\totalnofparagraphs\relax
+ \let\dopopparagraph\relax
+ \else\ifprocessallparagraphs
+ \ifnum\globalparagraphnumber>\mostrecentparagraphtotal\relax
+ \dodopopparagraph\globalparagraphnumber
+ \else
+ \dodoprocessparagraph\globalparagraphnumber
+ \fi
+ \else
+ \let\paragraphnumber\globalparagraphnumber
+ \decrement(\paragraphnumber,\discardedparagraphs)%
+ \ExpandBothAfter\doifinsetelse{\paragraphnumber}{#1}
+ {\dodopopparagraph\globalparagraphnumber}
+ {\dodoprocessparagraph\globalparagraphnumber}%
+ \fi\fi
+ \dopopparagraph}%
+ \dopopparagraph
+ \doresetparagraph}}
+
+\def\popparagraphs
+ {\dosingleempty\dopopparagraphs}
+
+\def\countparagraphs
+ {\popparagraphs[\!!maxcard]%
+ \global\let\nofparagraphs\totalnofparagraphs
+ \doglobal\decrement(\nofparagraphs,\discardedparagraphs)}
+
+% \showframe
+%
+% \numberparagraphlines
+% \numberparagraphs
+%
+% \def\nofskippedparagraphs{1}
+%
+% \pushparagraphs\ThatsIt
+%
+% \ruledbaseline eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste
+%
+% \ruledbaseline eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste eerste eerste eerste
+% eerste eerste eerste eerste eerste
+%
+% \ruledbaseline tweede tweede tweede tweede tweede tweede
+% tweede tweede tweede tweede tweede tweede tweede tweede
+% tweede tweede tweede tweede tweede tweede tweede tweede
+% tweede tweede tweede tweede tweede tweede tweede tweede
+% tweede tweede tweede tweede tweede tweede tweede tweede
+% tweede tweede tweede tweede tweede tweede tweede tweede
+% tweede tweede tweede tweede tweede
+%
+% \skipparagraph \ruledbaseline skipped skipped skipped
+% skipped skipped skipped skipped skipped skipped skipped
+% skipped skipped skipped skipped skipped skipped skipped
+% skipped skipped
+%
+% \ruledbaseline derde derde derde derde derde derde derde
+% derde derde derde derde derde derde derde derde derde derde
+% derde derde derde derde derde derde derde derde derde derde
+% derde derde derde derde derde derde derde derde derde derde
+% derde derde derde derde derde derde derde derde derde derde
+% derde derde derde derde derde derde derde derde derde derde
+%
+% \skipparagraph \ruledbaseline skipped skipped skipped
+% skipped skipped skipped skipped skipped skipped skipped
+% skipped skipped skipped skipped skipped skipped skipped
+% skipped skipped skipped
+%
+% \ruledbaseline vierde vierde vierde vierde vierde vierde
+% vierde vierde vierde vierde vierde vierde vierde vierde
+% vierde vierde vierde vierde vierde vierde vierde vierde
+% vierde vierde vierde vierde
+%
+% \ruledbaseline vijfde vijfde vijfde vijfde vijfde vijfde
+% vijfde vijfde vijfde vijfde vijfde vijfde vijfde vijfde
+% vijfde vijfde vijfde vijfde vijfde vijfde vijfde vijfde
+% vijfde vijfde vijfde vijfde vijfde vijfde vijfde vijfde
+% vijfde vijfde vijfde
+%
+% \skipparagraph \ruledbaseline skipped skipped skipped
+% skipped skipped skipped skipped skipped skipped skipped
+% skipped skipped skipped skipped skipped skipped skipped
+% skipped skipped skipped
+%
+% \ThatsIt
+%
+% \popparagraphs
+%
+% \countparagraphs
+%
+% \blanko[2*groot]
+%
+% nofparagraphs:~\nofparagraphs
+%
+% \pagina
+%
+% \popparagraphs[1]
+% \popparagraphs[2]
+% \popparagraphs[3]
+% \popparagraphs[4]
+% \popparagraphs[5]
+%
+% \pagina
+%
+% \ruledvbox{\popparagraphs[1,2,3,4,5]}
+%
+% \pagina
+
+\protect \endinput
diff --git a/tex/context/base/core-stg.mkii b/tex/context/base/core-stg.mkii
new file mode 100644
index 000000000..429e1e894
--- /dev/null
+++ b/tex/context/base/core-stg.mkii
@@ -0,0 +1,72 @@
+%D \module
+%D [ file=core-stg,
+%D version=2006.08.16,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Strategies,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is a prelude to strategies. It is rather old code
+%D used in a project many years ago. Use with care since I
+%D will pick up this thread. (moved from cont-new)
+
+\unprotect
+
+\def\s!strategy{strategy}
+
+\def\currentstrategypass {1}
+\def\currentstrategyvariable{0}
+\def\maximumstrategypass {8}
+
+\newconditional\strategypassneeded
+\newconditional\strategypassforced
+
+\definetwopasslist{\s!strategy}
+
+\def\registerstrategypass
+ {\ifnum\currentstrategypass>\maximumstrategypass \else
+ \ifconditional\strategypassforced
+ \doglobal\increment\currentstrategypass
+ \else%\ifconditional\strategypassneeded
+ %\doglobal\increment\currentstrategypass
+ \fi%\fi
+ \fi
+ \savecurrentvalue\currentstrategypass{\currentstrategypass}}
+
+\appendtoks \registerstrategypass \to \everybye % \everylastshipout
+
+\def\setstrategyvariable#1#2% key value
+ {%\doifnotstrategyvariable{#1}{\global\settrue\strategypassneeded}%
+ \doglobal\increment\currentstrategyvariable
+ \savetaggedtwopassdata{\s!strategy}{\currentstrategyvariable}{#1}{#2}}
+
+\def\doifstrategyvariableelse#1#2#3%
+ {\getstrategyvariable{#1}\iftwopassdatafound#2\else#3\fi}
+
+\def\getstrategyvariable#1% key
+ {\findtwopassdata{\s!strategy}{#1}%
+ \setxvalue{\s!strategy:#1}{\twopassdata}}
+
+\def\retainstrategyvariable#1% key
+ {\expanded{\setstrategyvariable{#1}{\strategyvariable{#1}}}}
+
+\def\strategyvariable#1% key
+ {\csname\s!strategy:#1\endcsname}
+
+\let\stratvar\strategyvariable
+
+\def\forcestrategy{\global\settrue \strategypassforced}
+\def\abortstrategy{\global\setfalse\strategypassforced}
+
+\def\doifstrategyvariableelse#1#2#3%
+ {\getstrategyvariable{#1}\iftwopassdatafound#2\else#3\fi}
+
+\def\doifstrategyvariable #1#2{\doifstrategyvariableelse{#1}{#2}{}}
+\def\doifnotstrategyvariable#1#2{\doifstrategyvariableelse{#1}{}{#2}}
+
+\protect \endinput
diff --git a/tex/context/base/core-sys.lua b/tex/context/base/core-sys.lua
new file mode 100644
index 000000000..c5aa89d98
--- /dev/null
+++ b/tex/context/base/core-sys.lua
@@ -0,0 +1,22 @@
+if not modules then modules = { } end modules ['core-sys'] = {
+ version = 1.001,
+ comment = "companion to core-sys.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lower, extname, basename, removesuffix = string.lower, file.extname, file.basename, file.removesuffix
+
+function commands.updatefilenames(inputfilename,outputfilename)
+ environment.inputfilename = inputfilename or ""
+ environment.outputfilename = outputfilename or ""
+ environment.jobfilename = inputfilename or tex.jobname or ""
+ environment.jobfilesuffix = lower(extname(environment.jobfilename))
+ environment.inputfilebarename = removesuffix(basename(inputfilename))
+ environment.inputfilesuffix = lower(extname(inputfilename))
+end
+
+statistics.register("result saved in file", function()
+ return string.format( "%s.%s", environment.outputfilename, (tex.pdfoutput>0 and "pdf") or "dvi")
+end)
diff --git a/tex/context/base/core-sys.mkii b/tex/context/base/core-sys.mkii
new file mode 100644
index 000000000..24975ffb6
--- /dev/null
+++ b/tex/context/base/core-sys.mkii
@@ -0,0 +1,396 @@
+%D \module
+%D [ file=core-sys, % moved from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=System,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / System}
+
+\unprotect
+
+%D Version checking:
+
+\def\newcontextversion#1%
+ {\doifelse{#1}\contextversion
+ {\let\newcontextversion\gobbleoneargument}
+ {\writeline
+ \writestatus{Fatal Error}{Your format does not match the base files!}%
+ \writeline
+ \writestatus{Format Version}{\contextversion\space\contextmark}%
+ \writestatus{Files Version}{#1}%
+ \batchmode
+ \normalend}}
+
+%D End of lines to the output. \TEX\ will map this onto the platform specific
+%D line ending. I hate this mess.
+
+%newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}}
+\newlinechar=10 \edef\outputnewlinechar{^^J}
+
+% in case formats are shared:
+
+\def\initializenewlinechar
+ {\bgroup\newlinechar=10\xdef\outputnewlinechar{^^J}\egroup}
+
+%D Job names.
+
+\def\outputfilename {\@@svfile}
+\def\inputfilename {\@@svinputfile}
+\def\operatingsystem{\@@svtype}
+
+\let\jobfilename \jobname
+\let\jobfilesuffix\c!tex
+
+\def\splitjobfilename % todo: mkiv
+ {\resetsystemmode{suffix-\jobfilesuffix}%
+ \edef\ascii{\inputfilename}\defconvertedcommand\ascii\ascii
+ \splitstring\ascii\at.\to\jobfilename\and\jobfilesuffix
+ \lowercasestring\jobfilesuffix\to\jobfilesuffix
+ \doifnothing\jobfilename {\let\jobfilename \jobname}%
+ % todo and totest: \defconvertedcommand\jobfilename\jobfilename
+ \doifnothing\jobfilesuffix{\let\jobfilesuffix\c!tex}%
+ \setsystemmode{suffix-\jobfilesuffix}}
+
+% Some mechanisms (see x-res-01) use either \jobfilename or
+% \jobfilename.somesuffix, in which case we need to use the
+% full name if given or a default (like \jobfilename.xml);
+% this comes down to replacing the default tex suffix.
+
+\def\jobfullname{\jobfilename.\jobfilesuffix}
+
+\def\setjobfullname#1% #1 = default if not given
+ {\doifelsenothing\jobfilename
+ {\let\jobfullname\empty}
+ {\doif\jobfilesuffix\c!tex{\edef\jobfullname{\jobfilename.#1}}}}
+
+% ...
+
+\def\dosetupsystem[#1]%
+ {\getparameters[\??sv][#1]%
+ \setuprandomize[\@@svrandom]%
+ \beforesplitstring\@@svresolution\at dpi\to\@@svresolution
+ \let\outputresolution\@@svresolution
+ \ifcase\@@svn
+ % % 0 : unknown
+ \or
+ \setsystemmode\v!first % 1 : first run
+ \or
+ % % 2 : successive run
+ \or
+ \setsystemmode\v!first % 3 : first and only run
+ \or
+ \setsystemmode\v!last % 4 : (extra) last run
+ \fi
+% \processaction
+% [\@@svtype]
+% %[ mswin=>\edef\@@svline{\rawcharacter{13}\rawcharacter{10}}, % crlf
+% [ mswin=>\edef\@@svline{\rawcharacter{13}}, % cr % crlf
+% darwin=>\edef\@@svline{\rawcharacter{13}}, % cr
+% \s!unknown=>\edef\@@svline{\rawcharacter{10}}]% % lf
+ \splitjobfilename}
+
+% \edef\@@svline{\rawcharacter{10}} % unix is the most critical/sensitive system
+
+\let\systemendofline\outputnewlinechar % will become obsolete
+
+\def\setupsystem
+ {\dosingleargument\dosetupsystem}
+
+\def\systemparameter#1{\executeifdefined{\??sv#1}\empty}
+
+%D The system modes set by the setup command can be used in
+%D situations like:
+%D
+%D \starttyping
+%D \startmode[*first]
+%D \executesystemcommand{cleanupxml text.xml clean-text.xml}
+%D \stopmode
+%D
+%D \starttext
+%D \typefile{clean-text.xml}
+%D \stoptext
+%D \stoptyping
+
+\def\setuprandomize[#1]%
+ {\doifsomething{#1}
+ {\bgroup
+ % tex's time is in minutes
+ \scratchcounter\normaltime
+ \processaction
+ [#1]
+ [ \v!small=>\divide\scratchcounter 15, % 900,
+ \v!medium=>\divide\scratchcounter 30, % 1800,
+ \v!big=>\divide\scratchcounter 60, % 3600,
+ \v!normal=>\getnewrandomseed\scratchcounter,
+ \s!default=>\getnewrandomseed\scratchcounter,
+ \s!unknown=>\scratchcounter#1]%
+ \expanded{\setrandomseed{\the\scratchcounter}}%
+% \writestatus\m!systems{randomseed: \the\scratchcounter}%
+ \egroup}}
+
+
+\setupsystem
+ [\c!directory=,
+ \c!n=0, % 0:unknown 1: one run 2: first 3: successive 4: final run
+ \c!resolution=600dpi,
+ \c!random=,
+ \c!file=\jobname,
+ \c!inputfile=\outputfilename,
+ \c!type=unix, % windows is normally less sensitive to handle
+ \c!bodyfont=\normalizedlocalbodyfontsize] % of iets anders
+
+%D Remark: windows programs normally handle \type {cr|lf|crlf} but unix
+%D is more picky, so we default to the \type {cr}. I never understood why
+%D \type {crlf} was not used in all systems, since it makes most sense.
+
+\def\dostartglobaldefs#1#2%
+ {\edef\!!stringa{\the\globaldefs}%
+ \ifnum\globaldefs#10
+ \globaldefs-\globaldefs
+ \fi
+ \advance\globaldefs #21
+ \setevalue{@gd@\the\globaldefs}{\!!stringa}}
+
+\def\dostopglobaldefs
+ {\doifdefinedelse{@gd@\the\globaldefs}
+ {\globaldefs\getvalue{@gd@\the\globaldefs}\relax}
+ {\globaldefs\zerocount}}
+
+\def\startlocal {\dostartglobaldefs>-}
+\def\stoplocal {\dostopglobaldefs}
+\def\startglobal {\dostartglobaldefs<+}
+\def\stopglobal {\dostopglobaldefs}
+
+\def\complexstart[#1]{\bgroup\getvalue{\e!start#1}}
+\def\complexstop [#1]{\getvalue{\e!stop #1}\egroup}
+
+\let\simplestart\bgroup
+\let\simplestop \egroup
+
+\definecomplexorsimple\start
+\definecomplexorsimple\stop
+
+\def\dododefinestartstop[#1][#2]% todo: use indirect commands
+ {\getparameters
+ [\??be#1]
+ [\c!before=,
+ \c!after=,
+ \c!inbetween=,
+ \c!commands=,
+ \c!style=,
+ #2]%
+ \unexpanded\setvalue{#1}%
+ {\groupedcommand
+ {\getvalue{\??be#1\c!commands}%
+ \dostartattributes{\??be#1}\c!style\c!color}
+ {\dostopattributes
+ \getvalue{\??be#1\c!inbetween}}}%
+ \setvalue{\e!start#1}%
+ {\getvalue{\??be#1\c!before}%
+ \bgroup
+ \getvalue{\??be#1\c!commands}%
+ \dostartattributes{\??be#1}\c!style\c!color\empty}%
+ \setvalue{\e!stop#1}%
+ {\dostopattributes
+ \egroup
+ \getvalue{\??be#1\c!after}}}
+
+\def\dodefinestartstop[#1][#2]%
+ {\def\docommand##1{\dododefinestartstop[##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+\def\definestartstop
+ {\dodoubleargument\dodefinestartstop}
+
+\def\dosetupstartstop[#1][#2]%
+ {\def\docommand##1{\getparameters[\??be##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+\def\setupstartstop
+ {\dodoubleargument\dosetupstartstop}
+
+% \docommand kan niet worden gebruikt omdat deze macro
+% soms lokaal wordt gebruikt
+
+% te zijner tijd:
+%
+% \definevariable {pc} % ProtectedCommand
+%
+% \def\executeprotected#1%
+% {\csname\??pc\string#1\endcsname}
+%
+% \def\defineprotected#1#2%
+% {\expandafter\def\csname\??pc\string#2\endcsname}
+%
+% \def\defineunprotected#1%
+% {\def#1}
+%
+% \def\doprotected%
+% {\ifx\next\define
+% \let\next=\defineprotected
+% \else
+% \let\next=\executeprotected
+% \fi
+% \next}
+%
+% \def\unexpanded%
+% {\futurelet\next\doprotected}
+%
+% \unexpanded\define\ziezo{ziezo}
+%
+% \unexpanded\ziezo
+
+\def\complexdefine[#1]#2#3%
+ {\ifx#2\undefined
+ \else
+ \showmessage\m!systems4{\string#2}%
+ \fi
+ \ifcase0#1\def#2{#3}%
+ \or\def#2##1{#3}%
+ \or\def#2##1##2{#3}%
+ \or\def#2##1##2##3{#3}%
+ \or\def#2##1##2##3##4{#3}%
+ \or\def#2##1##2##3##4##5{#3}%
+ \or\def#2##1##2##3##4##5##6{#3}%
+ \or\def#2##1##2##3##4##5##6##7{#3}%
+ \or\def#2##1##2##3##4##5##6##7##8{#3}%
+ \or\def#2##1##2##3##4##5##6##7##8##9{#3}%
+ \else\def#2{#3}%
+ \fi}
+
+\definecomplexorsimpleempty\define
+
+\unexpanded\def\macroname#1% brrr
+ {\executeifdefined{#1}\empty}
+
+\def\usecommands#1%
+ {\bgroup
+ \def\docommand##1{\setbox0\hbox{\getvalue{\string##1}##1}}%
+ \processcommalist[#1]\docommand
+ \egroup}
+
+\newif\ifforcefileexpansion % handy for document level overload
+
+%D The next implementation is about 4 times as faster than a
+%D processaction alternative on an string of average length.
+%D Since this feature is used in XML processing, it made sense
+%D to support this faster alternative. It's installable as well.
+
+\def\installexpander#1#2#3% changed, no longer \convert..\to...
+ {\setvalue{\s!do\c!expansion#1l}{#2}%
+ \setvalue{\s!do\c!expansion#1g}{#3}}%
+
+% \convertexpanded is obsolete
+
+\long\def\doconvertexpanded#1#2#3% #4 % [l|g] \cs {kind} {data}
+ {\csname % that we assign all exp a value
+ \s!do\c!expansion
+ \ifforcefileexpansion
+ \v!yes
+ \else\ifcsname\s!do\c!expansion#3#1\endcsname
+ #3%
+ \else
+ \s!default
+ \fi\fi
+ #1%
+ \endcsname#2}% #3
+
+\long\def\defconvertexpanded {\doconvertexpanded l}
+\long\def\gdefconvertexpanded{\doconvertexpanded g}
+
+\installexpander\v!command \defconvertedcommand \gdefconvertedcommand
+\installexpander\s!default \defconvertedargument \gdefconvertedargument
+\installexpander\empty \defconvertedargument \gdefconvertedargument
+\installexpander\v!no \defconvertedargument \gdefconvertedargument
+\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
+\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
+\installexpander\v!strict \defreducedargument \gdefreducedargument
+\installexpander {utf} \defreducedtoutf \gdefreducedtoutf
+
+%installexpander {xml} {see xtag-ext}
+
+\def\dodefconvertedmeaning#1#2#3% watch the double expansion !
+ {\bgroup
+ \honorunexpanded
+ \convertencodedtokens % can be overloaded
+ \xdef\@@globalexpanded{#3}%
+ \xdef\@@globalexpanded{\@@globalexpanded}%
+ \egroup
+ #1#2\@@globalexpanded}
+
+\def\defconvertedmeaning {\dodefconvertedmeaning\defconvertedcommand}
+\def\gdefconvertedmeaning{\dodefconvertedmeaning\gdefconvertedcommand}
+
+\def\dodefreducedargument#1#2#3%
+ {\begingroup
+ \reducetocoding[raw]%
+ \edef\ascii{#3}%
+ \expandafter\endgroup\expandafter#1\expandafter#2\expandafter{\ascii}}
+
+\def\defreducedargument {\dodefreducedargument\edef}
+\def\gdefreducedargument{\dodefreducedargument\xdef}
+
+% \setupindex[expansion=utf]\index{\eacute}
+
+\def\dodefreducedtoutf#1#2#3%
+ {\begingroup
+ \reducetocoding[uc]%
+ \let\uchar\uchartoutf
+ \let\unicodechar\numbertoutf
+ \edef\ascii{#3}%
+ \expandafter\endgroup\expandafter#1\expandafter#2\expandafter{\ascii}}
+
+\def\defreducedtoutf {\dodefreducedtoutf\edef}
+\def\gdefreducedtoutf{\dodefreducedtoutf\xdef}
+
+% old syntax:
+
+\def\convertmeaning#1\to#2% watch the double expansion !
+ {\bgroup
+ \honorunexpanded
+ \convertencodedtokens % can be overloaded
+ \xdef\@@globalexpanded{#1}%
+ \xdef\@@globalexpanded{\@@globalexpanded}%
+ \egroup
+ \defconvertedcommand#2\@@globalexpanded}
+
+\def\reduceargument#1\to#2%
+ {\begingroup
+ \reducetocoding[raw]%
+ \edef\ascii{#1}%
+ \expandafter\endgroup\expandafter\edef\expandafter#2\expandafter{\ascii}}
+
+\def\reducetoutf#1\to#2%
+ {\begingroup
+ \reducetocoding[uc]%
+ \let\uchar\uchartoutf
+ \let\unicodechar\numbertoutf
+ \edef\ascii{#1}%
+ \expandafter\endgroup\expandafter\edef\expandafter#2\expandafter{\ascii}}
+
+% \setvalue{statevalue\v!stop }{0}
+% \setvalue{statevalue\v!start }{1}
+% \setvalue{statevalue\v!normaal}{2}
+% \setvalue{statevalue\v!leeg }{3}
+% \setvalue{statevalue\v!geen }{4}
+%
+% \def\setcurrentstate#1%
+% {\chardef\currentstate=0\getvalue{statevalue\getvalue{#1\c!state}\relax}
+%
+% \ifcase\currentstate ...
+
+\def\redo{\dorepeat} % [n*10], kind of obsolete
+
+% obsolete, use \dorecurse instead
+%
+% \def\herhaler {\repeater}
+% \def\herhaalmetcommando {\dorepeatwithcommand}
+
+\protect \endinput
diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv
new file mode 100644
index 000000000..649e5e65c
--- /dev/null
+++ b/tex/context/base/core-sys.mkiv
@@ -0,0 +1,432 @@
+%D \module
+%D [ file=core-sys, % moved from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=System,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% we need to mkiv-ize this file !
+
+\writestatus{loading}{ConTeXt Core Macros / System}
+
+\registerctxluafile{core-sys}{1.001}
+
+\unprotect
+
+%D Version checking:
+
+\def\newcontextversion#1%
+ {\doifelse{#1}\contextversion
+ {\let\newcontextversion\gobbleoneargument}
+ {\writeline
+ \writestatus{Fatal Error}{Your format does not match the base files!}%
+ \writeline
+ \writestatus{Format Version}{\contextversion\space\contextmark}%
+ \writestatus{Files Version}{#1}%
+ \batchmode
+ \normalend}}
+
+%D End of lines to the output. \TEX\ will map this onto the platform specific
+%D line ending. I hate this mess.
+
+%newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}}
+\newlinechar=10 \edef\outputnewlinechar{^^J}
+
+\edef\operatingsystem {\ctxlua{tex.write(os.platform)}}
+
+\def\jobfilename {\ctxlua{tex.sprint(tex.texcatcodes,environment.jobfilename or "")}}
+\def\jobfilesuffix {\ctxlua{tex.sprint(tex.texcatcodes,environment.jobfilesuffix or "")}}
+\def\inputfilebarename{\ctxlua{tex.sprint(tex.texcatcodes,environment.inputfilebarename or "")}}
+\def\inputfilesuffix {\ctxlua{tex.sprint(tex.texcatcodes,environment.inputfilesuffix or "")}}
+\def\inputfilename {\ctxlua{tex.sprint(tex.texcatcodes,environment.inputfilename or "")}}
+\def\outputfilename {\ctxlua{tex.sprint(tex.texcatcodes,environment.outputfilename or "")}}
+
+\def\initializenewlinechar
+ {\bgroup\newlinechar=10\xdef\outputnewlinechar{^^J}\egroup}
+
+\newtoks \everysetupsystem
+
+\unexpanded\def\setupsystem
+ {\dosingleargument\dosetupsystem}
+
+\def\dosetupsystem[#1]%
+ {\getparameters[\??sv][#1]%
+ \the\everysetupsystem}
+
+\appendtoks
+ \edef\outputresolution{\@@svresolution}%
+\to \everysetupsystem
+
+\appendtoks
+ \ifcase\@@svn
+ % % 0 : unknown
+ \or
+ \setsystemmode\v!first % 1 : first run
+ \or
+ % % 2 : successive run
+ \or
+ \setsystemmode\v!first % 3 : first and only run
+ \or
+ \setsystemmode\v!last % 4 : (extra) last run
+ \fi
+\to \everysetupsystem
+
+\appendtoks
+ \edef\outputfilename{\@@svfile}%
+ \edef\inputfilename {\@@svinputfile}%
+\to \everysetupsystem
+
+\let\@@jobsuffix\s!unknown
+
+\appendtoks
+ \resetsystemmode{suffix-\@@jobsuffix}%
+ \edef\@@jobsuffix{\jobsuffix}%
+ \setsystemmode{suffix-\@@jobsuffix}%
+\to \everysetupsystem
+
+\appendtoks
+ \ctxlua {commands.updatefilenames("\inputfilename","\outputfilename")}%
+\to \everysetupsystem
+
+% Some mechanisms (see x-res-01) use either \jobfilename or
+% \jobfilename.somesuffix, in which case we need to use the
+% full name if given or a default (like \jobfilename.xml);
+% this comes down to replacing the default tex suffix.
+
+\def\jobfullname{\jobfilename.\jobfilesuffix}
+
+\def\setjobfullname#1% #1 = default if not given
+ {\doifelsenothing\jobfilename
+ {\let\jobfullname\empty}
+ {\doif\jobfilesuffix\c!tex{\edef\jobfullname{\jobfilename.#1}}}}
+
+\let\systemendofline\outputnewlinechar % will become obsolete
+
+\def\systemparameter#1{\executeifdefined{\??sv#1}\empty}
+
+%D There are a couple of system states avaiable:
+%D
+%D \starttabulate [|T|T|]
+%D \NC \type{\jobname} \NC \jobname \NC \NR
+%D \NC \type{\jobfilename} \NC \jobfilename \NC \NR
+%D \NC \type{\jobfilesuffix} \NC \jobfilesuffix \NC \NR
+%D \NC \type{\inputfilename} \NC \inputfilename \NC \NR
+%D \NC \type{\inputfilebarename} \NC \inputfilebarename \NC \NR
+%D \NC \type{\inputfilesuffix} \NC \inputfilesuffix \NC \NR
+%D \NC \type{\outputfilename} \NC \outputfilename \NC \NR
+%D \NC \type{\operatingsystem} \NC \operatingsystem \NC \NR
+%D \stoptabulate
+
+%D The system modes set by the setup command can be used in
+%D situations like:
+%D
+%D \starttyping
+%D \startmode[*first]
+%D \executesystemcommand{cleanupxml text.xml clean-text.xml}
+%D \stopmode
+%D
+%D \starttext
+%D \typefile{clean-text.xml}
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\setuprandomize[#1]%
+ {\doifsomething{#1}
+ {\bgroup
+ % tex's time is in minutes
+ \scratchcounter\normaltime
+ \processaction
+ [#1]
+ [ \v!small=>\divide\scratchcounter 15, % 900,
+ \v!medium=>\divide\scratchcounter 30, % 1800,
+ \v!big=>\divide\scratchcounter 60, % 3600,
+ \v!normal=>\getnewrandomseed\scratchcounter,
+ \s!default=>\getnewrandomseed\scratchcounter,
+ \s!unknown=>\scratchcounter#1]%
+ \expanded{\setrandomseed{\the\scratchcounter}}%
+ % \writestatus\m!systems{randomseed: \the\scratchcounter}%
+ \egroup}}
+
+\setupsystem
+ [\c!directory=,
+ \c!n=0, % 0:unknown 1: one run 2: first 3: successive 4: final run
+ \c!resolution=600,% in dpi, no unit in mkiv
+ %c!random=, % obsolete here
+ \c!file=\jobname,
+ \c!inputfile=\outputfilename,
+ \c!type=unix, % windows is normally less sensitive to handle
+ \c!bodyfont=\normalizedlocalbodyfontsize] % of iets anders
+
+%D Remark: windows programs normally handle \type {cr|lf|crlf} but unix
+%D is more picky, so we default to the \type {cr}. I never understood why
+%D \type {crlf} was not used in all systems, since it makes most sense.
+
+\def\dostartglobaldefs#1#2%
+ {\edef\!!stringa{\the\globaldefs}%
+ \ifnum\globaldefs#10
+ \globaldefs-\globaldefs
+ \fi
+ \advance\globaldefs #21
+ \setevalue{@gd@\the\globaldefs}{\!!stringa}}
+
+\def\dostopglobaldefs
+ {\doifdefinedelse{@gd@\the\globaldefs}
+ {\globaldefs\getvalue{@gd@\the\globaldefs}\relax}
+ {\globaldefs\zerocount}}
+
+\unexpanded\def\startlocal {\dostartglobaldefs>-}
+\unexpanded\def\stoplocal {\dostopglobaldefs}
+\unexpanded\def\startglobal {\dostartglobaldefs<+}
+\unexpanded\def\stopglobal {\dostopglobaldefs}
+
+\def\complexstart[#1]{\bgroup\getvalue{\e!start#1}}
+\def\complexstop [#1]{\getvalue{\e!stop #1}\egroup}
+
+\let\simplestart\bgroup
+\let\simplestop \egroup
+
+\definecomplexorsimple\start
+\definecomplexorsimple\stop
+
+\def\dododefinestartstop[#1][#2]% todo: use indirect commands
+ {\getparameters
+ [\??be#1]
+ [\c!before=,
+ \c!after=,
+ \c!inbetween=,
+ \c!commands=,
+ \c!style=,
+ #2]%
+ \setuvalue{#1}%
+ {\groupedcommand
+ {\getvalue{\??be#1\c!commands}%
+ \dostartattributes{\??be#1}\c!style\c!color}
+ {\dostopattributes
+ \getvalue{\??be#1\c!inbetween}}}%
+ \setvalue{\e!start#1}%
+ {\getvalue{\??be#1\c!before}%
+ \bgroup
+ \getvalue{\??be#1\c!commands}%
+ \dostartattributes{\??be#1}\c!style\c!color\empty}%
+ \setvalue{\e!stop#1}%
+ {\dostopattributes
+ \egroup
+ \getvalue{\??be#1\c!after}}}
+
+\def\dodefinestartstop[#1][#2]%
+ {\def\docommand##1{\dododefinestartstop[##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+\unexpanded\def\definestartstop
+ {\dodoubleargument\dodefinestartstop}
+
+\def\dosetupstartstop[#1][#2]%
+ {\def\docommand##1{\getparameters[\??be##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+\unexpanded\def\setupstartstop
+ {\dodoubleargument\dosetupstartstop}
+
+% \docommand kan niet worden gebruikt omdat deze macro
+% soms lokaal wordt gebruikt
+
+% te zijner tijd:
+%
+% \definevariable {pc} % ProtectedCommand
+%
+% \def\executeprotected#1%
+% {\csname\??pc\string#1\endcsname}
+%
+% \unexpanded\def\defineprotected#1#2%
+% {\expandafter\def\csname\??pc\string#2\endcsname}
+%
+% \unexpanded\def\defineunprotected#1%
+% {\def#1}
+%
+% \def\doprotected%
+% {\ifx\next\define
+% \let\next=\defineprotected
+% \else
+% \let\next=\executeprotected
+% \fi
+% \next}
+%
+% \def\unexpanded%
+% {\futurelet\next\doprotected}
+%
+% \unexpanded\define\ziezo{ziezo}
+%
+% \unexpanded\ziezo
+
+\def\complexdefine[#1]#2#3%
+ {\ifx#2\undefined
+ \else
+ \showmessage\m!systems4{\string#2}%
+ \fi
+ \ifcase0#1\def#2{#3}%
+ \or\def#2##1{#3}%
+ \or\def#2##1##2{#3}%
+ \or\def#2##1##2##3{#3}%
+ \or\def#2##1##2##3##4{#3}%
+ \or\def#2##1##2##3##4##5{#3}%
+ \or\def#2##1##2##3##4##5##6{#3}%
+ \or\def#2##1##2##3##4##5##6##7{#3}%
+ \or\def#2##1##2##3##4##5##6##7##8{#3}%
+ \or\def#2##1##2##3##4##5##6##7##8##9{#3}%
+ \else\def#2{#3}%
+ \fi}
+
+\definecomplexorsimpleempty\define
+
+% \startluacode
+% local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+% local format, match, gmatch, rep = string.format, string.match, string.gmatch, string.rep
+% local empty = {
+% "single",
+% "double",
+% "triple",
+% "quadruple",
+% "quintuple",
+% }
+% local check = {
+% "first",
+% "second",
+% "third",
+% "fourth",
+% "fifth",
+% }
+% function commands.define(str)
+% -- we could store the defaults in lua and call lua instead but why bother
+% local arg, cmd = match(str,"(.*)\\(.-)$")
+% local a = { }
+% for s in gmatch(arg,"%[(.-)%]") do
+% a[#a+1] = s
+% end
+% local n = tonumber(a[#a])
+% if n then
+% a[#a] = nil
+% else
+% n = 0
+% end
+% texsprint(ctxcatcodes,format("\\unexpanded\\def\\%s",cmd))
+% if #a > 0 then
+% texsprint(ctxcatcodes,format("{\\do%sempty\\do%s}",empty[#a],cmd))
+% texsprint(ctxcatcodes,format("\\def\\do%s",cmd))
+% for i=1,#a do
+% texsprint(ctxcatcodes,"[#",i,"]")
+% end
+% texsprint(ctxcatcodes,"{")
+% for i=#a,1,-1 do
+% texsprint(ctxcatcodes,format("\\if%sargument",check[i]))
+% texsprint(ctxcatcodes,format("\\def\\next{\\dodo%s",cmd))
+% for j=1,#a-i do
+% texsprint(ctxcatcodes,format("[%s]",a[j]))
+% end
+% for j=1,i do
+% texsprint(ctxcatcodes,format("[#%s]",j))
+% end
+% texsprint(ctxcatcodes,"}")
+% if i == 1 then
+% texsprint(ctxcatcodes,rep("\\fi",#a))
+% else
+% texsprint(ctxcatcodes,"\\else")
+% end
+% end
+% texsprint(ctxcatcodes,"\\next}")
+% texsprint(ctxcatcodes,format("\\def\\dodo%s",cmd))
+% for i=1,#a do
+% texsprint(ctxcatcodes,"[#",i,"]")
+% end
+% end
+% for i=1,n do
+% texsprint(ctxcatcodes,"#",#a+i)
+% end
+% end
+% \stopluacode
+%
+% \unexpanded\def\define#1#{\ctxlua{commands.define([[\detokenize{#1}]])}}
+%
+% \starttext
+% \define[2]\whatevera{#1+#2}
+% \whatevera{A}{B}
+% \define[me][too][2]\whateverb{#1+#2+#3+#4}
+% \whateverb[A]{B}{C}
+% \whateverb[A][B]{C}{D}
+% \stoptext
+
+\unexpanded\def\macroname#1% brrr
+ {\executeifdefined{#1}\empty}
+
+\def\usecommands#1%
+ {\bgroup
+ \def\docommand##1{\setbox0\hbox{\getvalue{\string##1}##1}}%
+ \processcommalist[#1]\docommand
+ \egroup}
+
+\newif\ifforcefileexpansion % handy for document level overload
+
+%D The next implementation is about 4 times as faster than a
+%D processaction alternative on an string of average length.
+%D Since this feature is used in XML processing, it made sense
+%D to support this faster alternative. It's installable as well.
+%D
+%D We keep this around for \MKII\ \XML\ but it's not used in \MKIV\
+%D code as expansion is controlled in another way there.
+
+\def\installexpander#1#2#3% changed, no longer \convert..\to...
+ {\setvalue{\s!do\c!expansion#1l}{#2}%
+ \setvalue{\s!do\c!expansion#1g}{#3}}%
+
+% \convertexpanded is obsolete
+
+\long\def\doconvertexpanded#1#2#3% #4 % [l|g] \cs {kind} {data}
+ {\csname % that we assign all exp a value
+ \s!do\c!expansion
+ \ifforcefileexpansion
+ \v!yes
+ \else\ifcsname\s!do\c!expansion#3#1\endcsname
+ #3%
+ \else
+ \s!default
+ \fi\fi
+ #1%
+ \endcsname#2}% #3
+
+\long\def\defconvertexpanded {\doconvertexpanded l}
+\long\def\gdefconvertexpanded{\doconvertexpanded g}
+
+\installexpander\v!command \defconvertedcommand \gdefconvertedcommand
+\installexpander\s!default \defconvertedargument \gdefconvertedargument
+\installexpander\empty \defconvertedargument \gdefconvertedargument
+\installexpander\v!no \defconvertedargument \gdefconvertedargument
+\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
+\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
+\installexpander\v!strict \defreducedargument \gdefreducedargument
+\installexpander {utf} \defreducedtoutf \gdefreducedtoutf
+
+\def\dodefconvertedmeaning#1#2#3% watch the double expansion !
+ {\bgroup
+ \xdef\@@globalexpanded{#3}%
+ \xdef\@@globalexpanded{\@@globalexpanded}%
+ \egroup
+ #1#2\@@globalexpanded}
+
+\def\defconvertedmeaning {\dodefconvertedmeaning\defconvertedcommand}
+\def\gdefconvertedmeaning{\dodefconvertedmeaning\gdefconvertedcommand}
+
+\def\dodefreducedargument#1#2#3%
+ {\begingroup
+ \reducetocoding[raw]%
+ \edef\ascii{#3}%
+ \expandafter\endgroup\expandafter#1\expandafter#2\expandafter{\ascii}}
+
+\def\defreducedargument {\dodefreducedargument\edef}
+\def\gdefreducedargument{\dodefreducedargument\xdef}
+
+\protect \endinput
diff --git a/tex/context/base/core-two.lua b/tex/context/base/core-two.lua
new file mode 100644
index 000000000..24a3191a7
--- /dev/null
+++ b/tex/context/base/core-two.lua
@@ -0,0 +1,137 @@
+if not modules then modules = { } end modules ['core-two'] = {
+ version = 1.001,
+ comment = "companion to core-two.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local remove, concat = table.remove, table.concat
+
+local texprint = tex.print
+
+--[[ldx--
+
We save multi-pass information in the main utility table. This is a
+bit of a mess because we support old and new methods.
+--ldx]]--
+
+jobpasses = jobpasses or { }
+jobpasses.collected = jobpasses.collected or { }
+jobpasses.tobesaved = jobpasses.tobesaved or { }
+
+local collected, tobesaved = jobpasses.collected, jobpasses.tobesaved
+
+local function initializer()
+ collected, tobesaved = jobpasses.collected, jobpasses.tobesaved
+end
+
+job.register('jobpasses.collected', jobpasses.tobesaved, initializer, nil)
+
+local function allocate(id)
+ local p = tobesaved[id]
+ if not p then
+ p = { }
+ tobesaved[id] = p
+ end
+ return p
+end
+
+jobpasses.define = allocate
+
+function jobpasses.save(id,str)
+ local jti = allocate(id)
+ jti[#jti+1] = str
+end
+
+function jobpasses.savetagged(id,tag,str)
+ local jti = allocate(id)
+ jti[tag] = str
+end
+
+function jobpasses.getcollected(id)
+ return collected[id] or { }
+end
+
+function jobpasses.gettobesaved(id)
+ return allocate(id)
+end
+
+function jobpasses.get(id)
+ local jti = collected[id]
+ if jti and #jti > 0 then
+ texprint(remove(jti,1))
+ end
+end
+
+function jobpasses.first(id)
+ local jti = collected[id]
+ if jti and #jti > 0 then
+ texprint(jti[1])
+ end
+end
+
+function jobpasses.last(id)
+ local jti = collected[id]
+ if jti and #jti > 0 then
+ texprint(jti[#jti])
+ end
+end
+
+jobpasses.check = jobpasses.first
+
+function jobpasses.find(id,n)
+ local jti = collected[id]
+ if jti and jti[n] then
+ texprint(jti[n])
+ end
+end
+
+function jobpasses.count(id)
+ local jti = collected[id]
+ texprint((jti and #jti) or 0)
+end
+
+function jobpasses.list(id)
+ local jti = collected[id]
+ if jti then
+ texprint(concat(jti,','))
+ end
+end
+
+function jobpasses.doifinlistelse(id,str)
+ local jti = collected[id]
+ if jti then
+ local found = false
+ for _, v in next, jti do
+ if v == str then
+ found = true
+ break
+ end
+ end
+ commands.testcase(found)
+ else
+ commands.testcase(false)
+ end
+end
+
+--
+
+function jobpasses.savedata(id,data)
+ local jti = allocate(id)
+ jti[#jti+1] = data
+ return #jti
+end
+
+function jobpasses.getdata(id,index,default)
+ local jti = collected[id]
+ local value = jit and jti[index]
+ texprint((value ~= "" and value) or default or "")
+end
+
+function jobpasses.getfield(id,index,tag,default)
+ local jti = collected[id]
+ jti = jti and jti[index]
+ local value = jti and jti[tag]
+ texprint((value ~= "" and value) or default or "")
+end
+
diff --git a/tex/context/base/core-two.mkii b/tex/context/base/core-two.mkii
new file mode 100644
index 000000000..0f2e0048c
--- /dev/null
+++ b/tex/context/base/core-two.mkii
@@ -0,0 +1,206 @@
+%D \module
+%D [ file=core-two, % moved from core-uti
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Two Pass Data,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Two Pass Data}
+
+%D This is a rather old mechanism which has not changed much over
+%D time, apart from adding a few more selectors. This code used
+%D to be part of \type {core-uti}. The following examples demonstrate
+%D the interface.
+%D
+%D \startbuffer
+%D \definetwopasslist{test-1}
+%D
+%D \gettwopassdatalist{test-1} [\twopassdatalist=]
+%D \checktwopassdata {test-1} [\twopassdata=]
+%D \checktwopassdata {test-1} [\twopassdata=]
+%D \gettwopassdata {test-1} [\twopassdata=]
+%D \gettwopassdata {test-1} [\twopassdata=]
+%D
+%D \definetwopasslist{test-2}
+%D
+%D \lazysavetwopassdata{test-2}{1}{x}
+%D \lazysavetwopassdata{test-2}{2}{y}
+%D \lazysavetwopassdata{test-2}{3}{z}
+%D
+%D \gettwopassdatalist{test-2} [\twopassdatalist=x,y,z]
+%D \checktwopassdata {test-2} [\twopassdata=x]
+%D \checktwopassdata {test-2} [\twopassdata=x]
+%D \gettwopassdata {test-2} [\twopassdata=x]
+%D \gettwopassdata {test-2} [\twopassdata=y]
+%D \gettwopassdata {test-2} [\twopassdata=z]
+%D \gettwopassdata {test-2} [\twopassdata=]
+%D
+%D \definetwopasslist{test-3}
+%D
+%D \lazysavetaggedtwopassdata{test-3}{1}{x}{a}
+%D \lazysavetaggedtwopassdata{test-3}{2}{y}{b}
+%D \lazysavetaggedtwopassdata{test-3}{3}{z}{c}
+%D
+%D \findtwopassdata{test-3}{x} [\twopassdata=a]
+%D \findtwopassdata{test-3}{y} [\twopassdata=b]
+%D \findtwopassdata{test-3}{z} [\twopassdata=c]
+%D \findtwopassdata{test-3}{w} [\twopassdata=]
+%D
+%D \definetwopasslist{test-4}
+%D
+%D \lazysavetwopassdata{test-4}{1}{A}
+%D \lazysavetwopassdata{test-4}{2}{B}
+%D \lazysavetwopassdata{test-4}{3}{C}
+%D
+%D \getfirsttwopassdata{test-4} [\twopassdata=A]
+%D \getlasttwopassdata {test-4} [\twopassdata=C]
+%D \getfirsttwopassdata{test-4} [\twopassdata=A]
+%D \getlasttwopassdata {test-4} [\twopassdata=C]
+%D \getfromtwopassdata {test-4}{1} [\twopassdata=A]
+%D \getfromtwopassdata {test-4}{3} [\twopassdata=C]
+%D \getfromtwopassdata {test-4}{2} [\twopassdata=B]
+%D \stopbuffer
+%D
+%D \getbuffer \typebuffer
+
+\unprotect
+
+\let\alltwopasslists\empty
+\let\twopassentry \gobblethreearguments % permits loading a MK II file
+\let\twopassdata \empty
+\let\twopassdatalist\empty
+
+\newif\iftwopassdatafound
+
+\addutilityreset{twopassentries}
+
+\def\immediatesavetwopassdata #1#2#3{\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3}}}
+\def\savetwopassdata #1#2#3{\writeutilitycommand{\twopassentry{#1}{#2}{#3}}}
+\def\lazysavetwopassdata #1#2#3{\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3}}}} % expanded !
+\def\savetaggedtwopassdata #1#2#3#4{\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3::#4}}}
+\def\lazysavetaggedtwopassdata#1#2#3#4{\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3::#4}}}} % expanded !
+
+\def\resettwopassentries
+ {\let\twopassentry\gobblethreearguments}
+
+\def\settwopassentries
+ {\def\twopassentry##1{\executeifdefined{@@##1\s!pass}\gobbletwoarguments}}
+
+\resettwopassentries
+
+\def\appendtwopasselement#1#2#3% can sometimes become a large list
+ {%\debuggerinfo{\m!systems}{twopass data #1 - #2 = #3}%
+ \expandafter\xdef\csname#1:\s!list\endcsname
+ {\@EA\ifx\csname#1:\s!list\endcsname\empty \else
+ \csname#1:\s!list\endcsname,\fi#3}}
+
+\def\dodefinetwopasslist#1%
+ {\doifundefined{#1:\s!list}
+ {%\debuggerinfo\m!systems{defining twopass class #1}%
+ \doglobal\addutilityreset{#1\s!pass}%
+ \setgvalue{\s!set #1\s!pass}{\dosettwopasslist {#1}}%
+ \setgvalue{\s!reset#1\s!pass}{\doresettwopasslist{#1}}%
+ \getvalue {\s!reset#1\s!pass}}}
+
+\def\definetwopasslist#1%
+ {\expanded{\dodefinetwopasslist{#1}}%
+ \doglobal\addtocommalist{#1}\alltwopasslists}
+
+\def\dosettwopasslist#1%
+ {\letgvalue{\s!set#1\s!pass}\gobbletwoarguments
+ \setgvalue{@@#1\s!pass}{\appendtwopasselement{#1}}}
+
+\def\doresettwopasslist#1%
+ {\letgvalue{@@#1\s!pass}\gobbletwoarguments}
+
+\def\doloadtwopassdata#1%
+ {\doifundefined{#1:\s!list}
+ {\startnointerference
+ \letgvalueempty{#1:\s!list}%
+ \protectlabels
+ \doutilities{twopassentries,#1\s!pass}\jobname\empty\relax\relax
+ \stopnointerference}}
+
+\def\loadtwopassdata
+ {\ifx\alltwopasslists\empty\else
+ \processcommacommand[\alltwopasslists]\doloadtwopassdata
+ \globallet\alltwopasslists\empty
+ \fi}
+
+\def\dogettwopassdata[#1,#2]#3#4%
+ {\edef\twopassdata{#1}%
+ \ifx\twopassdata\empty
+ \twopassdatafoundfalse
+ \let\twopassdata\empty
+ \else
+ \twopassdatafoundtrue
+ \ifcase#4\or\setxvalue{#3:\s!list}{#2}\fi
+ \fi}
+
+\def\gettwopassdata#1%
+ {\loadtwopassdata \@EAEAEA\dogettwopassdata\@EA\@EA\@EA[\csname#1:\s!list\endcsname,]{#1}\plusone}
+
+\def\checktwopassdata#1%
+ {\loadtwopassdata \@EAEAEA\dogettwopassdata\@EA\@EA\@EA[\csname#1:\s!list\endcsname,]{#1}\zerocount}
+
+\def\findtwopassdata#1#2%
+ {\loadtwopassdata \expanded{\dofindtwopassdata{#1}{#2}}}
+
+\def\dofindtwopassdata#1#2%
+ {\def\dodofindtwopassdata[##1,##2#2::##3,##4]{\edef\twopassdata{##3}}%
+ \@EAEAEA\dodofindtwopassdata\@EA\@EA\@EA[\@EA\@EA\@EA,\csname#1:\s!list\endcsname,#2,#2::,]%
+ \ifx\twopassdata\empty
+ \twopassdatafoundfalse
+ \else
+ \twopassdatafoundtrue
+ \fi}
+
+\let\getfirsttwopassdata\checktwopassdata
+
+\def\getlasttwopassdata#1%
+ {\loadtwopassdata
+ \scratchcounter\zerocount
+ \@EAEAEA\rawprocesscommalist\@EA\@EA\@EA[\csname#1:\s!list\endcsname]\dogetlasttwopassdata
+ \edef\noftwopassitems{\the\scratchcounter}%
+ \iftwopassdatafound\else
+ \let\twopassdata\empty
+ \fi}
+
+\def\dogetlasttwopassdata#1%
+ {\edef\nexttwopassdata{#1}%
+ \ifx\nexttwopassdata\empty \else
+ \let\twopassdata\nexttwopassdata
+ \advance\scratchcounter \plusone
+ \twopassdatafoundtrue
+ \fi}
+
+\def\getfromtwopassdata#1#2%
+ {\loadtwopassdata
+ \@EAEAEA\getfromcommalist\@EA\@EA\@EA[\csname#1:\s!list\endcsname][#2]%
+ \ifx\commalistelement\empty
+ \twopassdatafoundfalse
+ \let\twopassdata\empty
+ \else
+ \twopassdatafoundtrue
+ \let\twopassdata\commalistelement
+ \fi}
+
+\def\gettwopassdatalist#1%
+ {\loadtwopassdata
+ \letcscsname\twopassdatalist\csname#1:\s!list\endcsname
+ \ifx\twopassdatalist\relax\let\twopassdatalist\empty\fi}
+
+\def\gettwopassdatalist
+ {\getnamedtwopassdatalist\twopassdatalist}
+
+\def\doifelseintwopassdata#1#2% tag dat
+ {\gettwopassdatalist{#1}%
+ \expanded{\doifinsetelse{#2}{\twopassdatalist}}}
+
+\protect \endinput
diff --git a/tex/context/base/core-two.mkiv b/tex/context/base/core-two.mkiv
new file mode 100644
index 000000000..2cc9412af
--- /dev/null
+++ b/tex/context/base/core-two.mkiv
@@ -0,0 +1,106 @@
+%D \module
+%D [ file=core-two, % moved from core-uti
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Two Pass Data,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Two Pass Data}
+
+%D This is a rather old mechanism which has not changed much over
+%D time, apart from adding a few more selectors. This code used
+%D to be part of \type {core-uti}. The following examples demonstrate
+%D the interface.
+%D
+%D \startbuffer
+%D \definetwopasslist{test-1}
+%D
+%D \gettwopassdatalist{test-1} [\twopassdatalist=]
+%D \checktwopassdata {test-1} [\twopassdata=]
+%D \checktwopassdata {test-1} [\twopassdata=]
+%D \gettwopassdata {test-1} [\twopassdata=]
+%D \gettwopassdata {test-1} [\twopassdata=]
+%D
+%D \definetwopasslist{test-2}
+%D
+%D \lazysavetwopassdata{test-2}{1}{x}
+%D \lazysavetwopassdata{test-2}{2}{y}
+%D \lazysavetwopassdata{test-2}{3}{z}
+%D
+%D \gettwopassdatalist{test-2} [\twopassdatalist=x,y,z]
+%D \checktwopassdata {test-2} [\twopassdata=x]
+%D \checktwopassdata {test-2} [\twopassdata=x]
+%D \gettwopassdata {test-2} [\twopassdata=x]
+%D \gettwopassdata {test-2} [\twopassdata=y]
+%D \gettwopassdata {test-2} [\twopassdata=z]
+%D \gettwopassdata {test-2} [\twopassdata=]
+%D
+%D \definetwopasslist{test-3}
+%D
+%D \lazysavetaggedtwopassdata{test-3}{1}{x}{a}
+%D \lazysavetaggedtwopassdata{test-3}{2}{y}{b}
+%D \lazysavetaggedtwopassdata{test-3}{3}{z}{c}
+%D
+%D \findtwopassdata{test-3}{x} [\twopassdata=a]
+%D \findtwopassdata{test-3}{y} [\twopassdata=b]
+%D \findtwopassdata{test-3}{z} [\twopassdata=c]
+%D \findtwopassdata{test-3}{w} [\twopassdata=]
+%D
+%D \definetwopasslist{test-4}
+%D
+%D \lazysavetwopassdata{test-4}{1}{A}
+%D \lazysavetwopassdata{test-4}{2}{B}
+%D \lazysavetwopassdata{test-4}{3}{C}
+%D
+%D \getfirsttwopassdata{test-4} [\twopassdata=A]
+%D \getlasttwopassdata {test-4} [\twopassdata=C]
+%D \getfirsttwopassdata{test-4} [\twopassdata=A]
+%D \getlasttwopassdata {test-4} [\twopassdata=C]
+%D \getfromtwopassdata {test-4}{1} [\twopassdata=A]
+%D \getfromtwopassdata {test-4}{3} [\twopassdata=C]
+%D \getfromtwopassdata {test-4}{2} [\twopassdata=B]
+%D \stopbuffer
+%D
+%D \getbuffer \typebuffer
+
+\unprotect
+
+\let\twopassdatalist\empty
+
+\newif\iftwopassdatafound
+
+\registerctxluafile{core-two}{1.001}
+
+%D I'm not that sure if this behaves exactly like mkii. This needs a cleanup.
+
+\def\immediatesavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlua {jobpasses.save('#1',"#3")}}}
+\def\savetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatelua{jobpasses.save('#1',"#3")}}}
+\def\lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatelua{jobpasses.save('#1',"#3")}}}
+\def\savetaggedtwopassdata #1#2#3#4{\normalexpanded{\noexpand\ctxlua {jobpasses.savetagged('#1','#3',"#4")}}}
+\def\lazysavetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\ctxlatelua{jobpasses.savetagged('#1','#3',"#4")}}}
+
+% temp hack: needs a proper \starteverytimeluacode
+
+\def\testtwopassdata{\ifx\twopassdata\empty\twopassdatafoundfalse\else\twopassdatafoundtrue\fi}
+
+% todo: move the edef to lua
+
+\unexpanded\def\definetwopasslist #1{\ctxlua{jobpasses.define('#1')}}
+\def\gettwopassdata #1{\edef\twopassdata{\ctxlua{jobpasses.get("#1")}}\testtwopassdata}
+\def\checktwopassdata #1{\edef\twopassdata{\ctxlua{jobpasses.check("#1")}}\testtwopassdata}
+\def\findtwopassdata #1#2{\edef\twopassdata{\ctxlua{jobpasses.find("#1","#2")}}\testtwopassdata}
+\def\getfirsttwopassdata #1{\edef\twopassdata{\ctxlua{jobpasses.first("#1")}}\testtwopassdata}
+\def\getlasttwopassdata #1{\edef\twopassdata{\ctxlua{jobpasses.last("#1")}}\edef\noftwopassitems{\ctxlua{jobpasses.count("#1")}}\testtwopassdata}
+\def\getnamedtwopassdatalist#1#2{\edef#1{\ctxlua{jobpasses.list("#2")}}}
+\def\gettwopassdatalist #1{\edef\twopassdatalist{\ctxlua{jobpasses.list("#1")}}}
+\def\doifelseintwopassdata #1#2{\ctxlua{jobpasses.doifinlistelse("#1","#2")}}
+
+\let\getfromtwopassdata\findtwopassdata
+
+\protect \endinput
diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua
new file mode 100644
index 000000000..01fd8522b
--- /dev/null
+++ b/tex/context/base/core-uti.lua
@@ -0,0 +1,294 @@
+if not modules then modules = { } end modules ['core-uti'] = {
+ version = 1.001,
+ comment = "companion to core-uti.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: keep track of changes here (hm, track access, and only true when
+-- accessed and changed)
+
+--[[ldx--
+
A utility file has always been part of and with
+the move to we also moved a lot of multi-pass info
+to a table. Instead of loading a based
+utility file under different setups, we now load a table once. This
+saves much runtime but at the cost of more memory usage.
+--ldx]]--
+
+local sort, concat, format, match = table.sort, table.concat, string.format, string.match
+local next, type, tostring = next, type, tostring
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+
+if not jobs then jobs = { } end
+if not job then jobs['main'] = { } end job = jobs['main']
+
+jobs.version = 1.10
+
+--[[ldx--
+
Variables are saved using in the previously defined table and passed
+onto using the following method. Of course one can also
+directly access the variable using a call.
+--ldx]]--
+
+local savelist, comment = { }, { }
+
+function job.comment(str)
+ comment[#comment+1] = str
+end
+
+job.comment(format("version: %1.2f",jobs.version))
+
+function job.initialize(loadname,savename)
+ job.load(loadname)
+ main.register_stop_actions(function()
+ if not status.lasterrorstring or status.lasterrorstring == "" then
+ job.save(savename)
+ end
+ end)
+end
+
+function job.register(...) -- collected, tobesaved, initializer, finalizer
+ savelist[#savelist+1] = { ... }
+end
+
+-- as an example we implement variables
+
+jobvariables = jobvariables or { }
+jobvariables.collected = jobvariables.collected or { }
+jobvariables.tobesaved = jobvariables.tobesaved or { }
+jobvariables.checksums = jobvariables.checksums or { }
+
+if not jobvariables.checksums.old then jobvariables.checksums.old = md5.HEX("old") end -- used in experiment
+if not jobvariables.checksums.new then jobvariables.checksums.new = md5.HEX("new") end -- used in experiment
+
+job.register('jobvariables.checksums', jobvariables.checksums)
+
+local function initializer()
+ local r = jobvariables.collected.randomseed
+ if not r then
+ r = math.random()
+ math.setrandomseedi(r,"initialize")
+ else
+ math.setrandomseedi(r,"previous run")
+ end
+ jobvariables.tobesaved.randomseed = r
+ for cs, value in next, jobvariables.collected do
+ texsprint(ctxcatcodes,format("\\xdef\\%s{%s}",cs,value))
+ end
+end
+
+job.register('jobvariables.collected', jobvariables.tobesaved, initializer)
+
+function jobvariables.save(cs,value)
+ jobvariables.tobesaved[cs] = value
+end
+
+-- experiment (bugged: some loop in running)
+
+-- for the moment here, very experimental stuff
+
+packer = packer or { }
+packer.version = 1.00
+
+local function hashed(t)
+ local s = { }
+ for k, v in next, t do
+ if type(v) == "table" then
+ s[#s+1] = k.."={"..hashed(v).."}"
+ else
+ s[#s+1] = k.."="..tostring(v)
+ end
+ end
+ sort(s)
+ return concat(s,",")
+end
+
+local function pack(t,keys,hash,index)
+ for k,v in next, t do
+ if type(v) == "table" then
+ pack(v,keys,hash,index)
+ end
+ if keys[k] and type(v) == "table" then
+ local h = hashed(v)
+ local i = hash[h]
+ if not i then
+ i = #index+1
+ index[i] = v
+ hash[h] = i
+ end
+ t[k] = i
+ end
+ end
+end
+
+local function unpack(t,keys,index)
+ for k,v in next, t do
+ if keys[k] and type(v) == "number" then
+ local iv = index[v]
+ if iv then
+ v = iv
+ t[k] = v
+ end
+ end
+ if type(v) == "table" then
+ unpack(v,keys,index)
+ end
+ end
+end
+
+function packer.new(keys,version)
+ return {
+ version = version or packer.version,
+ keys = table.tohash(keys),
+ hash = { },
+ index = { },
+ }
+end
+
+function packer.pack(t,p,shared)
+ if shared then
+ pack(t,p.keys,p.hash,p.index)
+ elseif not t.packer then
+ pack(t,p.keys,p.hash,p.index)
+ if #p.index > 0 then
+ t.packer = {
+ version = p.version or packer.version,
+ keys = p.keys,
+ index = p.index,
+ }
+ end
+ p.hash, p.index = { }, { }
+ end
+end
+
+function packer.unpack(t,p,shared)
+ if shared then
+ if p then
+ unpack(t,p.keys,p.index)
+ end
+ else
+ local tp = t.packer
+ if tp then
+ if tp.version == (p and p.version or packer.version) then
+ unpack(t,tp.keys,tp.index)
+ else
+ -- fatal error, wrong version
+ end
+ t.packer = nil
+ end
+ end
+end
+
+function packer.strip(p)
+ p.hash = nil
+end
+
+local packlist = {
+ "numbers",
+ "metadata",
+ "sectiondata",
+ "prefixdata",
+ "numberdata",
+ "pagedata",
+ "directives",
+ "specification",
+ "processors", -- might become key under directives or metadata
+-- "references", -- we need to rename of them as only one packs (not structure.lists.references)
+}
+
+local jobpacker = packer.new(packlist,1.01)
+
+job.pack = true
+
+job._save_, job._load_ = { }, { } -- registers timing
+
+function job.save(filename)
+ statistics.starttiming(job._save_)
+ local f = io.open(filename,'w')
+ if f then
+ for c=1,#comment do
+ f:write("-- ",comment[c],"\n")
+ end
+ f:write("\n")
+ for l=1,#savelist do
+ local list = savelist[l]
+ local target, data, finalizer = list[1], list[2], list[4]
+ if type(finalizer) == "function" then
+ finalizer()
+ end
+ if job.pack then
+ packer.pack(data,jobpacker,true)
+ end
+ f:write(aux.definetable(target),"\n")
+ f:write(table.serialize(data,target,true,true),"\n")
+ end
+ if job.pack then
+ packer.strip(jobpacker)
+ f:write(table.serialize(jobpacker,"job.packer",true,true),"\n")
+ end
+ f:close()
+ end
+ statistics.stoptiming(job._save_)
+end
+
+function job.load(filename)
+ statistics.starttiming(job._load_)
+ local data = io.loaddata(filename)
+ if data and data ~= "" then
+ local version = tonumber(match(data,"^-- version: ([%d%.]+)"))
+ if version ~= jobs.version then
+ logs.report("job","version mismatch with jobfile: %s <> %s", version or "?", jobs.version)
+ else
+ local data = loadstring(data)
+ if data then
+ data()
+ end
+ for l=1,#savelist do
+ local list = savelist[l]
+ local target, initializer = list[1], list[3]
+ packer.unpack(aux.accesstable(target),job.packer,true)
+ if type(initializer) == "function" then
+ initializer(aux.accesstable(target))
+ end
+ end
+ job.packer = nil
+ end
+ end
+ statistics.stoptiming(job._load_)
+end
+
+-- eventually this will end up in strc-ini
+
+statistics.register("startup time", function()
+ return statistics.elapsedseconds(ctx,"including runtime option file processing")
+end)
+
+statistics.register("jobdata time",function()
+ if statistics.elapsedindeed(job._save_) or statistics.elapsedindeed(job._load_) then
+ return format("%s seconds saving, %s seconds loading", statistics.elapsedtime(job._save_), statistics.elapsedtime(job._load_))
+ end
+end)
+
+statistics.register("callbacks", function()
+ local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
+ local pages = tex.count['realpageno'] - 1
+ if pages > 1 then
+ return format("direct: %s, indirect: %s, total: %s (%i per page)", total-indirect, indirect, total, total/pages)
+ else
+ return format("direct: %s, indirect: %s, total: %s", total-indirect, indirect, total)
+ end
+end)
+
+function statistics.formatruntime(runtime)
+ local shipped = tex.count['nofshipouts']
+ local pages = tex.count['realpageno'] - 1
+ if shipped > 0 or pages > 0 then
+ local persecond = shipped / runtime
+ if pages == 0 then pages = shipped end
+ return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond)
+ else
+ return format("%s seconds",runtime)
+ end
+end
diff --git a/tex/context/base/core-uti.mkii b/tex/context/base/core-uti.mkii
new file mode 100644
index 000000000..5b8f66f50
--- /dev/null
+++ b/tex/context/base/core-uti.mkii
@@ -0,0 +1,349 @@
+%D \module
+%D [ file=core-uti,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Utility File Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Utility File Handling}
+
+\unprotect
+
+% todo : safe lan etc too
+% todo : load all commands at once (tok)
+% todo : merge status info patch into tui file (language, encoding, etc),
+
+% Utility-file
+%
+% De onderstaande macro's ondersteunen het gebruik van de
+% zogeheten utility-file. Alle extern onder te brengen
+% informatie wordt opgeslagen in de file \jobname.tui, tenzij
+% er selectief pagina's worden gezet. In dat geval wordt de
+% file \jobname.tmp gebruikt. Informatie wordt ingelezen uit
+% de file \jobname.tuo, welke door TeXUtil wordt aangemaakt.
+
+\edef\utilityversion{1998.07.07} % was: 1996.03.15 % status variables
+\edef\utilityversion{1998.12.20} % was: 1998.07.07 % index attributes
+\edef\utilityversion{2003.07.19} % was: 1998.12.20 % object pages
+\edef\utilityversion{2006.06.23} % was: 2003.07.19 % -- instead of :
+\edef\utilityversion{2006.09.21} % pt in pos
+\edef\utilityversion{2008.10.14} % moved more to lua in mkiv
+
+% Bepaalde commando's worden als string weggeschreven. Deze
+% zijn aan het eind van deze file gedefinieerd.
+
+% Om een opbouw van spaties te voorkomen (???) moet ^^M een
+% andere betekenis krijgen:
+%
+% \catcode`\^^M=14 (comment)
+%
+% read file
+%
+% \catcode`\^^M=5 (end of line)
+
+\newwrite\utility@tui
+\newif\ifutilitydone
+
+\ifx\sectionseparator\undefined \def\sectionseparator{-} \fi
+
+\def\@@utilityerrormessage
+ {\showmessage\m!systems8\empty
+ \globallet\@@utilityerrormessage\relax}
+
+\def\thisisutilityversion#1%
+ {\doifelse\utilityversion{#1}%
+ {\checksectionseparator}
+ {\@@utilityerrormessage\resetutilities\endinput}}
+
+\def\checksectionseparator % catches backward compatibility conflict
+ {}% \doifnot\sectionseparator:\endinput} % this dependency may go in a few years
+
+\def\dosplitofffoliopart[#1--#2--#3]{#3}
+
+\def\thisissectionseparator#1%
+ {\bgroup
+ \globallet\checksectionseparator\relax
+ \defconvertedcommand \asciia\sectionseparator
+ \defconvertedargument\asciib{#1}%
+ \expanded{\gdef\noexpand\dosplitofffoliopart[####1\sectionseparator
+ \sectionseparator####2\sectionseparator\sectionseparator####3]{####3}}%
+ \ifx\asciia\asciib
+ \egroup
+ \else
+ \egroup
+ % todo \@@utilityerrormessage
+ \resetutilities
+ \endinput
+ \fi}
+
+\def\writeutility {\write\utility@tui}
+\def\writeutilitycommand#1{\write\utility@tui{c \string#1}}
+
+% less tokens
+%
+% \def\immediatewriteutility {\immediate\writeutility}
+% \def\immediatewriteutilitycommand{\immediate\writeutilitycommand}
+%
+% more flexible (for overloading)
+
+\def\immediatewriteutility {\immediate\write\utility@tui}
+\def\immediatewriteutilitycommand#1{\immediate\write\utility@tui{c \string#1}}
+
+% as in:
+
+\def\cwriteutility#1%
+ {\write\utility@tui{\noexpand\checkedutility{\number\nofshipouts}{#1}}}
+
+\def\cwriteutilitycommand#1%
+ {\write\utility@tui{\noexpand\checkedutility{\number\nofshipouts}{c \string#1}}}
+
+\let\checkedutility\secondoftwoarguments
+
+\def\docheckedutility#1#2{\ifnum#1=\nofshipouts#2\else\letterpercent\fi}
+
+\prependtoks
+ \let\checkedutility\docheckedutility
+\to \everybeforeshipout
+
+% Better use marks.
+
+\newtoks \everyopenutilities
+\newtoks \everycloseutilities
+\newtoks \everycheckutilities
+
+\def\openutilities {\the\everyopenutilities } % \global\everyopenutilities\emptytoks
+\def\closeutilities{\the\everycloseutilities}
+\def\checkutilities{\the\everycheckutilities}
+
+\appendtoks
+ \let\writeutility \cwriteutility
+ \let\writeutilitycommand \cwriteutilitycommand
+ %\let\immediatewriteutility \cimmediatewriteutility
+ %\let\immediatewriteutilitycommand\cimmediatewriteutilitycommand
+ \let\checkutilities \relax
+\to \everycheckutilities
+
+\appendtoks
+ \immediate\openout\utility@tui\jobname.\f!inputextension
+ \immediatewriteutilitycommand{\thisissectionseparator{\sectionseparator}}% for the moment
+ \immediatewriteutilitycommand{\thisisutilityversion {\utilityversion }}% in this order
+\to \everyopenutilities
+
+\appendtoks
+% \immediate\closeout\utility@tui % niet echt nodig
+ \reportutilityproblems
+ % should be a message :
+ \let\writeutilitycommand \gobbleoneargument
+ \let\writeutility \gobbleoneargument
+ \let\immediatewriteutilitycommand\gobbleoneargument
+ \let\immediatewriteutility \gobbleoneargument
+\to \everycloseutilities
+
+% \def\reopenutilities
+% {\immediate\closeout\utility@tui
+% \openutilities}
+
+\def\abortutilitygeneration
+ {\immediatewriteutilitycommand\utilitygenerationaborted
+ \immediatewriteutility{q {quit}}}
+
+\def\utilitygenerationaborted
+ {\showmessage\m!systems{21}\empty
+ \globallet\utilitygenerationaborted\endinput
+ \gdef\reportutilityproblems{\showmessage\m!systems{22}\empty}%
+ \endinput}
+
+\def\savecurrentvalue#1#2%
+ {\immediatewriteutilitycommand{\initializevariable\string#1{#2}}}
+
+\let\initializevariable\gdef
+
+\appendtoks
+ \globallet\initializevariable\gobbletwoarguments
+\to \everyafterutilityread
+
+\let\reportutilityproblems\relax
+
+\newtoks\utilityresetlist
+
+\def\addutilityreset#1%
+ {\@EA\appendtoks\csname\s!reset#1\endcsname\to\utilityresetlist}
+
+\def\resetutilities
+ {\the\utilityresetlist}
+
+% #1=type #2=file #3=melding #4=voor #5=na
+%
+% Er wordt gegroepeerd. Als binnen een lijst (bijvoorbeeld) de
+% \leftskip is aangepast, maar nog geen \par is gegeven, dan
+% geldt buiten de groep de oude \leftskip. Aan #5 kan dan
+% ook \par worden meegegeven om de paragraaf af te sluiten.
+
+\newif\ifdoinpututilities
+\newif\ifunprotectutilities % voor't geval er \v!xxxxxx's zijn
+
+\def\currentutilityfilename{\jobname}
+
+% we need to pop and push, else problems with reading
+% utility files (toc) in xml mode and (e.g.) in a toc
+% entry doing a doifmode
+%
+% the following is not ok because we have no way to signal
+% xml content (yet), so for the moment we use this:
+
+\appendtoks
+ \ifprocessingXML
+ \processingXMLfalse
+ \enableXML
+ \catcode`\\=\@@escape
+ \catcode`\{=\@@begingroup
+ \catcode`\}=\@@endgroup
+ \catcode`\%=\@@comment\relax
+ \fi
+\to \everybeforeutilityread
+
+% \edef\testbytesequence
+% {\rawcharacter{7}%
+% \rawcharacter{27}%
+% %rawcharacter{227}% invalid in xetex, which expects utf
+% \rawcharacter{195}\rawcharacter{128}} % valid utf code
+%
+% \def\thisisbytesequence#1%
+% {\ifx\testbytesequence\empty\else
+% \defconvertedcommand\testbytesequence\testbytesequence
+% \defconvertedargument\ascii{#1}%
+% \ifx\testbytesequence\ascii \else
+% \writestatus\m!systems{possible problem with 8 bit output}%
+% \fi
+% \fi
+% \global\let\thisisbytesequence\gobbleoneargument}
+%
+% \ifnum\texengine=\xetexengine
+% \let\testbytesequence\empty
+% \fi
+%
+% \appendtoks
+% \immediatewriteutilitycommand{\thisisbytesequence{\testbytesequence}}%
+% \to \everyopenutilities
+
+\let\testbytesequence \empty % keep this
+\let\thisisbytesequence\gobbleoneargument % keep this
+
+\long\def\doutilities#1#2#3#4#5% % introduceren in utility file
+ {\resetutilities
+ % more than one utility thing can be handled in one pass,
+ % for instance lists, so we process ##1 as list
+ \def\douticommand##1{\csname\s!set##1\endcsname}%
+ \processcommacommand[#1]\douticommand
+ \begingroup
+ \def\currentutilityfilename{#2}%
+ \notesenabledfalse
+ \doinpututilitiestrue
+ \global\utilitydonefalse
+ \pushendofline % geeft problemen zodra andere file wordt ingelezen
+ \pushcatcodetable
+ \setcatcodetable\ctxcatcodes
+ \ifunprotectutilities % nog nodig ?
+ \unprotect
+ \fi
+ #4%
+ \the\everybeforeutilityread
+ \readjobfile{#2.\f!outputextension}\donothing\donothing
+ \the\everyafterutilityread
+ \popcatcodetable
+ #5%
+ \relax
+ \ifunprotectutilities
+ \protect
+ \fi
+ \popendofline
+ \ifutilitydone\else
+ \doifsomething{#3}
+ {\showmessage\m!systems9{{#3}}%
+ \doifconcepttracing
+ {\blank
+ \setmessagetext\m!systems9{{#3}}%
+ \type{[\currentmessagetext]}%
+ \blank}}%
+ \fi
+ \endgroup}
+
+% Default-instellingen (verborgen)
+
+\prependtoks \resetutilities \to \everyjob
+
+% Experiment
+%
+% \installprogram{Hello World}
+% \installprogram[hw]{Hello World}
+% \installedprogram[hw]
+
+\def\installprogram
+ {\dosingleempty\doinstallprogram}
+
+\def\doinstallprogram[#1]#2%
+ {\doifelsenothing{#1}
+ {\dodoinstallprogram{#2}}
+ {\setvalue{\??up#1}{\dodoinstallprogram{#2}}}}
+
+\def\dodoinstallprogram#1%
+ {\immediatewriteutility{e p {#1}}}
+
+\def\installedprogram[#1]%
+ {\getvalue{\??up#1}}
+
+% \writeplugindata{texutil}{{alpha}}
+% \writeplugindata{texutil}{{beta}}
+% \writeplugindata{texutil}{{gamma}}
+% \writeplugindata{texutil}{{delta}}
+%
+% \loadplugindata {plugintest}
+
+\def\immediatewriteplugindata#1#2%
+ {\immediatewriteutility{p u {#1} #2}}
+
+\def\writeplugindata#1#2%
+ {\writeutility{p u {#1} #2}}
+
+\def\loadplugindata#1%
+ {\doutilities{#1}\jobname\empty\relax\relax}
+
+% \plugincommand{\command{}{}{}}
+%
+% this way we can catch undefined commands
+
+\long\def\plugincommand#1%
+ {\doplugincommand#1\relax}
+
+\long\def\doplugincommand#1%
+ {\ifx#1\undefined
+ \expandafter\noplugincommand
+ \else
+ \expandafter#1%
+ \fi}
+
+\long\def\noplugincommand#1\relax
+ {}
+
+% \addutilityreset{plugintest}
+%
+% \def\resetplugintest{\let\plugintest\gobbletwoarguments}
+% \def\setplugintest {\let\plugintest\writestatus}
+%
+% \installplugin
+% {plugintest}
+% {\let\plugintest\gobbletwoarguments}
+% {\let\plugintest\writestatus}
+
+\long\def\installplugin#1#2#3%
+ {\addutilityreset {#1}%
+ \long\setvalue{\s!reset#1}{#2}%
+ \long\setvalue{\s!set #1}{#3}}
+
+\protect \endinput
diff --git a/tex/context/base/core-uti.mkiv b/tex/context/base/core-uti.mkiv
new file mode 100644
index 000000000..6b2dae2c9
--- /dev/null
+++ b/tex/context/base/core-uti.mkiv
@@ -0,0 +1,66 @@
+%D \module
+%D [ file=core-uti,
+%D version=1997.03.31, % 2006.09.19 mkiv
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Utility File Handling,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Utility File Handling}
+
+\unprotect
+
+\registerctxluafile{core-uti}{1.001}
+
+\def\savecurrentvalue#1#2%
+ {\ctxlua{jobvariables.save("\strippedcsname#1","#2")}}
+
+\appendtoks
+ \ctxlua{storage.dump()}% will move to lua
+\to \everydump
+
+\appendtoks
+ \ctxlua{storage.finalize()}% will move to lua
+\to \everyfinalizeluacode
+
+\appendtoks
+ \ctxlua{nodes.cleanup_reserved()}% will move to lua
+\to \everydump
+
+\appendtoks
+ \ctxlua {
+ job.comment("file: \jobname")
+ job.comment("format: \contextformat")
+ job.comment("stamp: \contextversion")
+ job.comment("escape: \!!bs\space...\space\!!es")
+ job.initialize("\jobname.tuc","\jobname.tua")
+ }%
+\to \everystarttext
+
+\def\notuccompression{\ctxlua{job.pack=false}}
+
+% cleaner, for the moment
+
+% \appendtoks
+% \ctxlua {
+% os.remove("\jobname.tui")
+% os.remove("\jobname.tuo")
+% }%
+% \to \everystarttext
+
+%D Some styles might use these use these commands:
+
+\newif \ifutilitydone
+\let \checkutilities \relax
+\let \currentutilityfilename \jobname
+\def \installprogram {\dosingleempty\doinstallprogram}
+\def \doinstallprogram [#1]{\gobbleoneargument}
+\def \installedprogram [#1]{}
+\let \installplugin \gobblethreearguments
+
+\protect \endinput
diff --git a/tex/context/base/core-var.mkii b/tex/context/base/core-var.mkii
new file mode 100644
index 000000000..4de1b8718
--- /dev/null
+++ b/tex/context/base/core-var.mkii
@@ -0,0 +1,286 @@
+%D \module
+%D [ file=core-var,
+%D version=1998.02.21,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Variables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Variables}
+
+\unprotect
+
+%D We introduce a couple of variables that are used all over
+%D \CONTEXT. Alternatively we could define them in each module
+%D but as they are part of the bigger picture we prefer to do
+%D it here.
+
+%D \macros
+%D {every...}
+%D
+%D A few every's. Some are only used in \MKII\ or \MKIV.
+
+%D Output routine:
+
+\newtoks \everybeforeoutput
+\newtoks \everyafteroutput
+
+%D Shipout:
+
+\newtoks \everyshipout
+\newtoks \everybeforeshipout
+\newtoks \everyaftershipout
+\newtoks \everyfirstshipout
+\newtoks \everylastshipout
+
+%D End of run:
+
+\newtoks \everybye
+\newtoks \everygoodbye
+\newtoks \everynotabene
+
+%D Document
+
+\newtoks \everysetupdocument
+\newtoks \everyendoftextbody
+
+\newtoks \everystarttext
+\newtoks \everystoptext
+
+%D Purity:
+
+\newtoks \everyforgetall
+\newtoks \everycleanupfeatures
+
+\def\cleanupfeatures{\the\everycleanupfeatures}
+\def\forgetall {\the\everyforgetall}
+
+%D Page building:
+
+\newtoks \everybeforepagebody
+\newtoks \everyafterpagebody
+
+\let \everypagebody \everybeforepagebody % backward compatible
+
+%D Multipass:
+
+\newtoks \everybeforeutilityread
+\newtoks \everyafterutilityread
+
+%D Floats:
+
+\newtoks \everyinsidefloat
+
+%D Sectioning:
+
+\newtoks \everyheadstart
+
+%D Par building (experimental, used in xml
..
)
+
+\newtoks \everybeginofpar
+\newtoks \everyendofpar
+%newtoks \everyparflush
+
+\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar
+\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi} % test prevents problems with \bpar\epar
+
+%D Lists:
+
+\newtoks \everylistentry
+\newtoks \everysavesortkeys
+
+%D Marks:
+
+\newtoks \everymarking
+
+%D Fonts:
+
+\newtoks \everyfont
+\newtoks \everyglobalbodyfont
+\newtoks \everydefinedfont
+
+\newevery \everybodyfont \EveryBodyFont
+\newevery \everyfontswitch \EveryFontSwitch
+
+%D Math:
+
+\newtoks \everybeforedisplayformula
+\newtoks \everymathematics
+
+\prependtoks \the\everymathematics \to \everymath
+\prependtoks \the\everymathematics \to \everydisplay
+
+%D Tables
+
+\newtoks \everytable
+
+%D State mess:
+
+\newtoks \everypushsomestate
+\newtoks \everypopsomestate
+
+\def\pushsomestates{\the\everypushsomestate}
+\def\popsomestates {\the\everypopsomestate }
+
+%D More generic (used to be pushcolor etc)
+
+\newtoks\everypushproperties
+\newtoks\everypopproperties
+\newtoks\everypopsplitproperties
+
+\newtoks\everystarttextproperties
+\newtoks\everystoptextproperties
+
+\def\pushproperties {\the\everypushproperties}
+\def\popproperties {\the\everypopproperties}
+\def\popsplitproperties {\the\everypopsplitproperties}
+
+\def\starttextproperties{\the\everystarttextproperties}
+\def\stoptextproperties {\the\everystoptextproperties}
+
+%D This is pretty important (esp since we now ignore shipouts).
+%D Actually we should nil all writes, marks, specials.
+
+\appendtoks \globallet\popproperties \relax \to \everylastshipout
+\appendtoks \globallet\popsplitproperties\relax \to \everylastshipout
+
+%D \macros
+%D {defineinputmode,setinputmode}
+%D
+%D New. Some work needs to be done.
+
+% not in mkiv
+
+\def\defineinputmode[#1]{\@EA\newtoks\csname every#1inputmode\endcsname}
+\def\setinputmode [#1]{\the\executeifdefined{every#1inputmode}\emptytoks}
+
+\defineinputmode [TEX]
+\defineinputmode [XML]
+
+\setinputmode [TEX]
+
+%D \macros
+%D {trialtypesetting}
+%D
+%D We disable trial typesetting in the output routine,
+%D just to be sure.
+
+\newif\iftrialtypesetting
+
+\prependtoks \trialtypesettingfalse \to \everybeforepagebody
+
+%D \macros
+%D {ifinpagebody,ifinsidecolumns,ifdoublesided,ifsinglesided}
+
+\newif \ifinpagebody
+\newif \ifinsidecolumns
+\newif \ifdoublesided \doublesidedfalse
+\newif \ifsinglesided \singlesidedtrue
+\newif \ifinsidefloat
+\newif \ifdoingblocks
+\newif \ifgridsnapping
+
+%D \macros
+%D {ifprocessingXML}
+%D
+%D We need this one even if no \XML\ is supported.
+
+\newif\ifprocessingXML % old way
+
+%D \macros
+%D {ifproductionrun}
+%D
+%D This boolean can be used to bypass certain
+%D initializations.
+
+\ifx\protectionlevel\undefined \newcount\protectionlevel \fi
+
+\newif\ifproductionrun
+
+\appendtoks \productionruntrue \to \everydump
+
+\appendtoks \ifcase\protectionlevel\else\reportunprotection\fi \to \everydump
+
+%D \macros
+%D {everyboxedcontent, ifboxedcontent,
+%D startboxedcontent, stopboxedcontent}
+%D
+%D This one is relatively new and will be used as a more
+%D robust test for inner situations.
+
+\newif \ifboxedcontent
+\newtoks\everyboxedcontent
+
+\appendtoks \boxedcontenttrue \to \everyboxedcontent
+
+\def\startboxedcontent{\bgroup\the\everyboxedcontent}
+\let\stopboxedcontent \egroup
+
+%D \macros
+%D {fastmode,silentmode}
+%D
+%D These commands are obsolete.
+
+\let\fastmode \relax
+\let\silentmode\relax
+
+%D \macros
+%D {defineselector,setupselector}
+%D
+%D \starttyping
+%D \defineselector[caption][max=2,n=2]
+%D
+%D \start
+%D \setupselector[caption][n=1]
+%D \placelist[figure][criterium=all]
+%D \stop
+%D
+%D \starttext
+%D \placefigure
+%D {\select{caption}{zapf}{\input zapf \relax}}
+%D {}
+%D \stoptext
+%D \stoptyping
+
+\def\defineselector{\dodoubleargument\dodefineselector}
+\def\setupselector {\dodoubleargument\dosetupselector}
+
+\def\dodefineselector[#1][#2]{\getparameters[\??sx#1][\c!max=2,\c!n=1,#2]}
+\def\dosetupselector [#1][#2]{\getparameters[\??sx#1][#2]}
+
+\unexpanded\def\select#1%
+ {\filterfromnext
+ {\executeifdefined{\??sx#1\c!max}1}
+ {\executeifdefined{\??sx#1\c!n }1}}
+
+%D We store some original meanings, maybe in \type
+%D {math-ini}.
+
+\let\normalat \at
+\let\normalin \in
+\let\normalfrom \from
+%let\normalover \over
+\let\normalabout\about
+
+%D Add-ons:
+
+\let\startlayoutcomponent\gobbletwoarguments
+\let\stoplayoutcomponent \relax
+
+%D Concepts:
+
+\chardef\conceptmode\zerocount
+
+\def\doifconcepttracing
+ {\ifnum\conceptmode>\plustwo
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/core-var.mkiv b/tex/context/base/core-var.mkiv
new file mode 100644
index 000000000..62cc9fc50
--- /dev/null
+++ b/tex/context/base/core-var.mkiv
@@ -0,0 +1,270 @@
+%D \module
+%D [ file=core-var,
+%D version=1998.02.21,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Variables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Variables}
+
+\unprotect
+
+%D We introduce a couple of variables that are used all over
+%D \CONTEXT. Alternatively we could define them in each module
+%D but as they are part of the bigger picture we prefer to do
+%D it here.
+
+%D \macros
+%D {every...}
+%D
+%D A few every's. Some are only used in \MKII\ or \MKIV.
+
+%D Output routine:
+
+\newtoks \everybeforeoutput
+\newtoks \everyafteroutput
+
+%D Shipout:
+
+\newtoks \everyshipout
+\newtoks \everybeforeshipout
+\newtoks \everyaftershipout
+\newtoks \everyfirstshipout
+\newtoks \everylastshipout
+
+%D End of run:
+
+\newtoks \everybye
+\newtoks \everygoodbye
+\newtoks \everynotabene
+
+%D Document
+
+\newtoks \everysetupdocument
+\newtoks \everyendoftextbody
+
+\newtoks \everystarttext
+\newtoks \everystoptext
+
+%D Purity:
+
+\newtoks \everyforgetall
+\newtoks \everycleanupfeatures
+
+\def\cleanupfeatures{\the\everycleanupfeatures}
+\def\forgetall {\the\everyforgetall}
+
+%D Page building:
+
+\newtoks \everybeforepagebody
+\newtoks \everyafterpagebody
+
+\let \everypagebody \everybeforepagebody % backward compatible
+
+%D Multipass:
+
+\newtoks \everybeforeutilityread
+\newtoks \everyafterutilityread
+
+%D Floats:
+
+\newtoks \everyinsidefloat
+
+%D Sectioning:
+
+\newtoks \everyheadstart
+
+%D Par building (experimental, used in xml
..
)
+
+\newtoks \everybeginofpar
+\newtoks \everyendofpar
+%newtoks \everyparflush
+
+\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar
+\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi} % test prevents problems with \bpar\epar
+
+%D Lists:
+
+\newtoks \everylistentry
+\newtoks \everysavesortkeys
+
+%D Marks:
+
+\newtoks \everymarking
+
+%D Fonts:
+
+\newtoks \everyfont
+\newtoks \everyglobalbodyfont
+\newtoks \everydefinedfont
+
+\newevery \everybodyfont \EveryBodyFont
+\newevery \everyfontswitch \EveryFontSwitch
+
+\newtoks \everysetupbodyfont
+\newtoks \everyswitchtobodyfont
+
+%D Math:
+
+\newtoks \everybeforedisplayformula
+\newtoks \everymathematics
+
+\prependtoks \the\everymathematics \to \everymath
+\prependtoks \the\everymathematics \to \everydisplay
+
+%D Tables
+
+\newtoks \everytable
+
+%D State mess:
+
+\newtoks \everypushsomestate
+\newtoks \everypopsomestate
+
+\def\pushsomestates{\the\everypushsomestate}
+\def\popsomestates {\the\everypopsomestate }
+
+%D More generic (used to be pushcolor etc)
+
+\newtoks\everystarttextproperties
+\newtoks\everystoptextproperties
+
+\unexpanded\def\starttextproperties{\the\everystarttextproperties}
+\unexpanded\def\stoptextproperties {\the\everystoptextproperties}
+
+%D \macros
+%D {defineinputmode,setinputmode}
+%D
+%D New. Some work needs to be done.
+
+% not in mkiv
+
+\unexpanded\def\defineinputmode[#1]{\@EA\newtoks\csname every#1inputmode\endcsname}
+\def\setinputmode [#1]{\the\executeifdefined{every#1inputmode}\emptytoks}
+
+\defineinputmode [TEX]
+\defineinputmode [XML]
+
+\setinputmode [TEX]
+
+%D \macros
+%D {trialtypesetting}
+%D
+%D We disable trial typesetting in the output routine,
+%D just to be sure.
+
+\newif\iftrialtypesetting
+
+\prependtoks \trialtypesettingfalse \to \everybeforepagebody
+
+%D \macros
+%D {ifinpagebody,ifinsidecolumns,ifdoublesided,ifsinglesided}
+
+\newif \ifinpagebody
+\newif \ifinsidecolumns
+\newif \ifdoublesided \doublesidedfalse
+\newif \ifsinglesided \singlesidedtrue
+\newif \ifinsidefloat
+\newif \ifdoingblocks
+\newif \ifgridsnapping
+
+%D \macros
+%D {ifprocessingXML}
+%D
+%D We need this one even if no \XML\ is supported.
+
+\newif\ifprocessingXML % old way
+
+%D \macros
+%D {ifproductionrun}
+%D
+%D This boolean can be used to bypass certain
+%D initializations.
+
+\newif\ifproductionrun \appendtoks \productionruntrue \to \everydump
+
+%D \macros
+%D {everyboxedcontent, ifboxedcontent,
+%D startboxedcontent, stopboxedcontent}
+%D
+%D This one is relatively new and will be used as a more
+%D robust test for inner situations.
+
+\newif \ifboxedcontent
+\newtoks\everyboxedcontent
+
+\appendtoks \boxedcontenttrue \to \everyboxedcontent
+
+\unexpanded\def\startboxedcontent{\bgroup\the\everyboxedcontent}
+\let\stopboxedcontent \egroup
+
+%D \macros
+%D {fastmode,silentmode}
+%D
+%D These commands are obsolete.
+
+\let\fastmode \relax
+\let\silentmode\relax
+
+%D \macros
+%D {defineselector,setupselector}
+%D
+%D \starttyping
+%D \defineselector[caption][max=2,n=2]
+%D
+%D \start
+%D \setupselector[caption][n=1]
+%D \placelist[figure][criterium=all]
+%D \stop
+%D
+%D \starttext
+%D \placefigure
+%D {\select{caption}{zapf}{\input zapf \relax}}
+%D {}
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\defineselector{\dodoubleargument\dodefineselector}
+\unexpanded\def\setupselector {\dodoubleargument\dosetupselector}
+
+\def\dodefineselector[#1][#2]{\getparameters[\??sx#1][\c!max=2,\c!n=1,#2]}
+\def\dosetupselector [#1][#2]{\getparameters[\??sx#1][#2]}
+
+\unexpanded\def\select#1%
+ {\filterfromnext
+ {\executeifdefined{\??sx#1\c!max}1}
+ {\executeifdefined{\??sx#1\c!n }1}}
+
+%D We store some original meanings, maybe in \type
+%D {math-ini}.
+
+\let\normalat \at
+\let\normalin \in
+\let\normalfrom \from
+%let\normalover \over
+\let\normalabout\about
+
+%D Add-ons:
+
+\let\setlayoutcomponentattribute \gobbletwoarguments
+\let\resetlayoutcomponentattribute\relax
+\let\layoutcomponentboxattribute \empty
+
+%D Concepts:
+
+\chardef\conceptmode\zerocount
+
+\def\doifconcepttracing
+ {\ifnum\conceptmode>\plustwo
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/data-aux.lua b/tex/context/base/data-aux.lua
new file mode 100644
index 000000000..26e1f551c
--- /dev/null
+++ b/tex/context/base/data-aux.lua
@@ -0,0 +1,57 @@
+if not modules then modules = { } end modules ['data-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local find = string.find
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+function resolvers.update_script(oldname,newname) -- oldname -> own.name, not per se a suffix
+ local scriptpath = "scripts/context/lua"
+ newname = file.addsuffix(newname,"lua")
+ local oldscript = resolvers.clean_path(oldname)
+ if trace_locating then
+ logs.report("fileio","to be replaced old script %s", oldscript)
+ end
+ local newscripts = resolvers.find_files(newname) or { }
+ if #newscripts == 0 then
+ if trace_locating then
+ logs.report("fileio","unable to locate new script")
+ end
+ else
+ for i=1,#newscripts do
+ local newscript = resolvers.clean_path(newscripts[i])
+ if trace_locating then
+ logs.report("fileio","checking new script %s", newscript)
+ end
+ if oldscript == newscript then
+ if trace_locating then
+ logs.report("fileio","old and new script are the same")
+ end
+ elseif not find(newscript,scriptpath) then
+ if trace_locating then
+ logs.report("fileio","new script should come from %s",scriptpath)
+ end
+ elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
+ if trace_locating then
+ logs.report("fileio","invalid new script name")
+ end
+ else
+ local newdata = io.loaddata(newscript)
+ if newdata then
+ if trace_locating then
+ logs.report("fileio","old script content replaced by new content")
+ end
+ io.savedata(oldscript,newdata)
+ break
+ elseif trace_locating then
+ logs.report("fileio","unable to load new script")
+ end
+ end
+ end
+ end
+end
diff --git a/tex/context/base/data-bin.lua b/tex/context/base/data-bin.lua
new file mode 100644
index 000000000..5e4397a54
--- /dev/null
+++ b/tex/context/base/data-bin.lua
@@ -0,0 +1,27 @@
+if not modules then modules = { } end modules ['data-bin'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+local unpack = unpack or table.unpack
+
+function resolvers.findbinfile(filename, filetype)
+ return resolvers.methodhandler('finders',filename, filetype)
+end
+
+function resolvers.openbinfile(filename)
+ return resolvers.methodhandler('loaders',filename)
+end
+
+function resolvers.loadbinfile(filename, filetype)
+ local fname = resolvers.methodhandler('finders',filename, filetype)
+ if fname and fname ~= "" then
+ return resolvers.openbinfile(fname)
+ else
+ return unpack(loaders.notfound)
+ end
+end
diff --git a/tex/context/base/data-con.lua b/tex/context/base/data-con.lua
new file mode 100644
index 000000000..fabe0baa1
--- /dev/null
+++ b/tex/context/base/data-con.lua
@@ -0,0 +1,120 @@
+if not modules then modules = { } end modules ['data-con'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, lower, gsub = string.format, string.lower, string.gsub
+
+local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
+local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
+local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
+
+--[[ldx--
+
Once we found ourselves defining similar cache constructs
+several times, containers were introduced. Containers are used
+to collect tables in memory and reuse them when possible based
+on (unique) hashes (to be provided by the calling function).
+
+
Caching to disk is disabled by default. Version numbers are
+stored in the saved table which makes it possible to change the
+table structures without bothering about the disk cache.
+
+
Examples of usage can be found in the font related code.
+--ldx]]--
+
+containers = containers or { }
+
+containers.usecache = true
+
+local function report(container,tag,name)
+ if trace_cache or trace_containers then
+ logs.report(format("%s cache",container.subcategory),"%s: %s",tag,name or 'invalid')
+ end
+end
+
+local allocated = { }
+
+-- tracing
+
+function containers.define(category, subcategory, version, enabled)
+ return function()
+ if category and subcategory then
+ local c = allocated[category]
+ if not c then
+ c = { }
+ allocated[category] = c
+ end
+ local s = c[subcategory]
+ if not s then
+ s = {
+ category = category,
+ subcategory = subcategory,
+ storage = { },
+ enabled = enabled,
+ version = version or 1.000,
+ trace = false,
+ path = caches and caches.setpath and caches.setpath(category,subcategory),
+ }
+ c[subcategory] = s
+ end
+ return s
+ else
+ return nil
+ end
+ end
+end
+
+function containers.is_usable(container, name)
+ return container.enabled and caches and caches.iswritable(container.path, name)
+end
+
+function containers.is_valid(container, name)
+ if name and name ~= "" then
+ local storage = container.storage[name]
+ return storage and storage.cache_version == container.version
+ else
+ return false
+ end
+end
+
+function containers.read(container,name)
+ if container.enabled and caches and not container.storage[name] and containers.usecache then
+ container.storage[name] = caches.loaddata(container.path,name)
+ if containers.is_valid(container,name) then
+ report(container,"loaded",name)
+ else
+ container.storage[name] = nil
+ end
+ end
+ if container.storage[name] then
+ report(container,"reusing",name)
+ end
+ return container.storage[name]
+end
+
+function containers.write(container, name, data)
+ if data then
+ data.cache_version = container.version
+ if container.enabled and caches then
+ local unique, shared = data.unique, data.shared
+ data.unique, data.shared = nil, nil
+ caches.savedata(container.path, name, data)
+ report(container,"saved",name)
+ data.unique, data.shared = unique, shared
+ end
+ report(container,"stored",name)
+ container.storage[name] = data
+ end
+ return data
+end
+
+function containers.content(container,name)
+ return container.storage[name]
+end
+
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w%d]+","-"))
+end
diff --git a/tex/context/base/data-crl.lua b/tex/context/base/data-crl.lua
new file mode 100644
index 000000000..55b1a8fad
--- /dev/null
+++ b/tex/context/base/data-crl.lua
@@ -0,0 +1,60 @@
+if not modules then modules = { } end modules ['data-crl'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local gsub = string.gsub
+
+curl = curl or { }
+
+curl.cached = { }
+curl.cachepath = caches.definepath("curl")
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+
+function curl.fetch(protocol, name)
+ local cachename = curl.cachepath() .. "/" .. gsub(name,"[^%a%d%.]+","-")
+-- cachename = gsub(cachename,"[\\/]", io.fileseparator)
+ cachename = gsub(cachename,"[\\]", "/") -- cleanup
+ if not curl.cached[name] then
+ if not io.exists(cachename) then
+ curl.cached[name] = cachename
+ local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name -- no protocol .. "://"
+ os.spawn(command)
+ end
+ if io.exists(cachename) then
+ curl.cached[name] = cachename
+ else
+ curl.cached[name] = ""
+ end
+ end
+ return curl.cached[name]
+end
+
+function finders.curl(protocol,filename)
+ local foundname = curl.fetch(protocol, filename)
+ return finders.generic(protocol,foundname,filetype)
+end
+
+function openers.curl(protocol,filename)
+ return openers.generic(protocol,filename)
+end
+
+function loaders.curl(protocol,filename)
+ return loaders.generic(protocol,filename)
+end
+
+-- todo: metamethod
+
+function curl.install(protocol)
+ finders[protocol] = function (filename,filetype) return finders.curl(protocol,filename) end
+ openers[protocol] = function (filename) return openers.curl(protocol,filename) end
+ loaders[protocol] = function (filename) return loaders.curl(protocol,filename) end
+end
+
+curl.install('http')
+curl.install('https')
+curl.install('ftp')
diff --git a/tex/context/base/data-ctx.lua b/tex/context/base/data-ctx.lua
new file mode 100644
index 000000000..89eb2742d
--- /dev/null
+++ b/tex/context/base/data-ctx.lua
@@ -0,0 +1,31 @@
+if not modules then modules = { } end modules ['data-ctx'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+function resolvers.save_used_files_in_trees(filename,jobname)
+ if not filename then filename = 'luatex.jlg' end
+ local found = instance.foundintrees
+ local f = io.open(filename,'w')
+ if f then
+ f:write("\n")
+ f:write("\n")
+ if jobname then
+ f:write(format("\t%s\n",jobname))
+ end
+ f:write("\t\n")
+ local sorted = table.sortedkeys(found)
+ for k=1,#sorted do
+ local v = sorted[k]
+ f:write(format("\t\t%s\n",found[v],v))
+ end
+ f:write("\t\n")
+ f:write("\n")
+ f:close()
+ end
+end
diff --git a/tex/context/base/data-gen.lua b/tex/context/base/data-gen.lua
new file mode 100644
index 000000000..5a0755831
--- /dev/null
+++ b/tex/context/base/data-gen.lua
@@ -0,0 +1,9 @@
+if not modules then modules = { } end modules ['data-gen'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- move generators here
diff --git a/tex/context/base/data-inp.lua b/tex/context/base/data-inp.lua
new file mode 100644
index 000000000..b7354e1ae
--- /dev/null
+++ b/tex/context/base/data-inp.lua
@@ -0,0 +1,15 @@
+if not modules then modules = { } end modules ['data-inp'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+resolvers.finders = resolvers.finders or { }
+resolvers.openers = resolvers.openers or { }
+resolvers.loaders = resolvers.loaders or { }
+
+resolvers.finders.notfound = { nil }
+resolvers.openers.notfound = { nil }
+resolvers.loaders.notfound = { false, nil, 0 }
diff --git a/tex/context/base/data-kps.lua b/tex/context/base/data-kps.lua
new file mode 100644
index 000000000..09d502409
--- /dev/null
+++ b/tex/context/base/data-kps.lua
@@ -0,0 +1,101 @@
+if not modules then modules = { } end modules ['luat-kps'] = {
+ version = 1.001,
+ comment = "companion to luatools.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
This file is used when we want the input handlers to behave like
+kpsewhich. What to do with the following:
If you wondered abou tsome of the previous mappings, how about
+the next bunch:
+--ldx]]--
+
+formats['bib'] = ''
+formats['bst'] = ''
+formats['mft'] = ''
+formats['ist'] = ''
+formats['web'] = ''
+formats['cweb'] = ''
+formats['MetaPost support'] = ''
+formats['TeX system documentation'] = ''
+formats['TeX system sources'] = ''
+formats['Troff fonts'] = ''
+formats['dvips config'] = ''
+formats['graphic/figure'] = ''
+formats['ls-R'] = ''
+formats['other text files'] = ''
+formats['other binary files'] = ''
+
+formats['gf'] = ''
+formats['pk'] = ''
+formats['base'] = 'MFBASES'
+formats['cnf'] = ''
+formats['mem'] = 'MPMEMS'
+formats['mf'] = 'MFINPUTS'
+formats['mfpool'] = 'MFPOOL'
+formats['mppool'] = 'MPPOOL'
+formats['texpool'] = 'TEXPOOL'
+formats['PostScript header'] = 'TEXPSHEADERS'
+formats['cmap files'] = 'CMAPFONTS'
+formats['type42 fonts'] = 'T42FONTS'
+formats['web2c files'] = 'WEB2C'
+formats['pdftex config'] = 'PDFTEXCONFIG'
+formats['texmfscripts'] = 'TEXMFSCRIPTS'
+formats['bitmap font'] = ''
+formats['lig files'] = 'LIGFONTS'
diff --git a/tex/context/base/data-lst.lua b/tex/context/base/data-lst.lua
new file mode 100644
index 000000000..82f675486
--- /dev/null
+++ b/tex/context/base/data-lst.lua
@@ -0,0 +1,63 @@
+if not modules then modules = { } end modules ['data-lst'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- used in mtxrun
+
+local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+
+resolvers.listers = resolvers.listers or { }
+
+local function tabstr(str)
+ if type(str) == 'table' then
+ return concat(str," | ")
+ else
+ return str
+ end
+end
+
+local function list(list,report)
+ local instance = resolvers.instance
+ local pat = upper(pattern or "","")
+ local report = report or texio.write_nl
+ local sorted = table.sortedkeys(list)
+ for i=1,#sorted do
+ local key = sorted[i]
+ if instance.pattern == "" or find(upper(key),pat) then
+ if instance.kpseonly then
+ if instance.kpsevars[key] then
+ report(format("%s=%s",key,tabstr(list[key])))
+ end
+ else
+ report(format('%s %s=%s',(instance.kpsevars[key] and 'K') or 'E',key,tabstr(list[key])))
+ end
+ end
+ end
+end
+
+function resolvers.listers.variables () list(resolvers.instance.variables ) end
+function resolvers.listers.expansions() list(resolvers.instance.expansions) end
+
+function resolvers.listers.configurations(report)
+ local report = report or texio.write_nl
+ local instance = resolvers.instance
+ local sorted = table.sortedkeys(instance.kpsevars)
+ for i=1,#sorted do
+ local key = sorted[i]
+ if not instance.pattern or (instance.pattern=="") or find(key,instance.pattern) then
+ report(format("%s\n",key))
+ local order = instance.order
+ for i=1,#order do
+ local str = order[i][key]
+ if str then
+ report(format("\t%s\t%s",i,str))
+ end
+ end
+ report("")
+ end
+ end
+end
diff --git a/tex/context/base/data-lua.lua b/tex/context/base/data-lua.lua
new file mode 100644
index 000000000..988133fbe
--- /dev/null
+++ b/tex/context/base/data-lua.lua
@@ -0,0 +1,152 @@
+if not modules then modules = { } end modules ['data-lua'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- some loading stuff ... we might move this one to slot 2 depending
+-- on the developments (the loaders must not trigger kpse); we could
+-- of course use a more extensive lib path spec
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local gsub, insert = string.gsub, table.insert
+local unpack = unpack or table.unpack
+
+local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
+local clibformats = { 'lib' }
+
+local _path_, libpaths, _cpath_, clibpaths
+
+function package.libpaths()
+ if not _path_ or package.path ~= _path_ then
+ _path_ = package.path
+ libpaths = file.split_path(_path_,";")
+ end
+ return libpaths
+end
+
+function package.clibpaths()
+ if not _cpath_ or package.cpath ~= _cpath_ then
+ _cpath_ = package.cpath
+ clibpaths = file.split_path(_cpath_,";")
+ end
+ return clibpaths
+end
+
+local function thepath(...)
+ local t = { ... } t[#t+1] = "?.lua"
+ local path = file.join(unpack(t))
+ if trace_locating then
+ logs.report("fileio","! appending '%s' to 'package.path'",path)
+ end
+ return path
+end
+
+local p_libpaths, a_libpaths = { }, { }
+
+function package.append_libpath(...)
+ insert(a_libpath,thepath(...))
+end
+
+function package.prepend_libpath(...)
+ insert(p_libpaths,1,thepath(...))
+end
+
+-- beware, we need to return a loadfile result !
+
+local function loaded(libpaths,name,simple)
+ for i=1,#libpaths do -- package.path, might become option
+ local libpath = libpaths[i]
+ local resolved = gsub(libpath,"%?",simple)
+ if trace_locating then -- more detail
+ logs.report("fileio","! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
+ end
+ if resolvers.isreadable.file(resolved) then
+ if trace_locating then
+ logs.report("fileio","! lib '%s' located via 'package.path': '%s'",name,resolved)
+ end
+ return loadfile(resolved)
+ end
+ end
+end
+
+
+package.loaders[2] = function(name) -- was [#package.loaders+1]
+ if trace_locating then -- mode detail
+ logs.report("fileio","! locating '%s'",name)
+ end
+ for i=1,#libformats do
+ local format = libformats[i]
+ local resolved = resolvers.find_file(name,format) or ""
+ if trace_locating then -- mode detail
+ logs.report("fileio","! checking for '%s' using 'libformat path': '%s'",name,format)
+ end
+ if resolved ~= "" then
+ if trace_locating then
+ logs.report("fileio","! lib '%s' located via environment: '%s'",name,resolved)
+ end
+ return loadfile(resolved)
+ end
+ end
+ -- libpaths
+ local libpaths, clibpaths = package.libpaths(), package.clibpaths()
+ local simple = gsub(name,"%.lua$","")
+ local simple = gsub(simple,"%.","/")
+ local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
+ if resolved then
+ return resolved
+ end
+ --
+ local libname = file.addsuffix(simple,os.libsuffix)
+ for i=1,#clibformats do
+ -- better have a dedicated loop
+ local format = clibformats[i]
+ local paths = resolvers.expanded_path_list_from_var(format)
+ for p=1,#paths do
+ local path = paths[p]
+ local resolved = file.join(path,libname)
+ if trace_locating then -- mode detail
+ logs.report("fileio","! checking for '%s' using 'clibformat path': '%s'",libname,path)
+ end
+ if resolvers.isreadable.file(resolved) then
+ if trace_locating then
+ logs.report("fileio","! lib '%s' located via 'clibformat': '%s'",libname,resolved)
+ end
+ return package.loadlib(resolved,name)
+ end
+ end
+ end
+ for i=1,#clibpaths do -- package.path, might become option
+ local libpath = clibpaths[i]
+ local resolved = gsub(libpath,"?",simple)
+ if trace_locating then -- more detail
+ logs.report("fileio","! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
+ end
+ if resolvers.isreadable.file(resolved) then
+ if trace_locating then
+ logs.report("fileio","! lib '%s' located via 'package.cpath': '%s'",name,resolved)
+ end
+ return package.loadlib(resolved,name)
+ end
+ end
+ -- just in case the distribution is messed up
+ if trace_loading then -- more detail
+ logs.report("fileio","! checking for '%s' using 'luatexlibs': '%s'",name)
+ end
+ local resolved = resolvers.find_file(file.basename(name),'luatexlibs') or ""
+ if resolved ~= "" then
+ if trace_locating then
+ logs.report("fileio","! lib '%s' located by basename via environment: '%s'",name,resolved)
+ end
+ return loadfile(resolved)
+ end
+ if trace_locating then
+ logs.report("fileio",'? unable to locate lib: %s',name)
+ end
+-- return "unable to locate " .. name
+end
+
+resolvers.loadlualib = require
diff --git a/tex/context/base/data-out.lua b/tex/context/base/data-out.lua
new file mode 100644
index 000000000..f73ff9bdc
--- /dev/null
+++ b/tex/context/base/data-out.lua
@@ -0,0 +1,10 @@
+if not modules then modules = { } end modules ['data-out'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+outputs = outputs or { }
+
diff --git a/tex/context/base/data-pre.lua b/tex/context/base/data-pre.lua
new file mode 100644
index 000000000..9348f6cd3
--- /dev/null
+++ b/tex/context/base/data-pre.lua
@@ -0,0 +1,109 @@
+if not modules then modules = { } end modules ['data-res'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--~ print(resolvers.resolve("abc env:tmp file:cont-en.tex path:cont-en.tex full:cont-en.tex rel:zapf/one/p-chars.tex"))
+
+local upper, lower, gsub = string.upper, string.lower, string.gsub
+
+local prefixes = { }
+
+prefixes.environment = function(str)
+ return resolvers.clean_path(os.getenv(str) or os.getenv(upper(str)) or os.getenv(lower(str)) or "")
+end
+
+prefixes.relative = function(str,n)
+ if io.exists(str) then
+ -- nothing
+ elseif io.exists("./" .. str) then
+ str = "./" .. str
+ else
+ local p = "../"
+ for i=1,n or 2 do
+ if io.exists(p .. str) then
+ str = p .. str
+ break
+ else
+ p = p .. "../"
+ end
+ end
+ end
+ return resolvers.clean_path(str)
+end
+
+prefixes.auto = function(str)
+ local fullname = prefixes.relative(str)
+ if not lfs.isfile(fullname) then
+ fullname = prefixes.locate(str)
+ end
+ return fullname
+end
+
+prefixes.locate = function(str)
+ local fullname = resolvers.find_given_file(str) or ""
+ return resolvers.clean_path((fullname ~= "" and fullname) or str)
+end
+
+prefixes.filename = function(str)
+ local fullname = resolvers.find_given_file(str) or ""
+ return resolvers.clean_path(file.basename((fullname ~= "" and fullname) or str))
+end
+
+prefixes.pathname = function(str)
+ local fullname = resolvers.find_given_file(str) or ""
+ return resolvers.clean_path(file.dirname((fullname ~= "" and fullname) or str))
+end
+
+prefixes.env = prefixes.environment
+prefixes.rel = prefixes.relative
+prefixes.loc = prefixes.locate
+prefixes.kpse = prefixes.locate
+prefixes.full = prefixes.locate
+prefixes.file = prefixes.filename
+prefixes.path = prefixes.pathname
+
+function resolvers.allprefixes(separator)
+ local all = table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i] = all[i] .. ":"
+ end
+ end
+ return all
+end
+
+local function _resolve_(method,target)
+ if prefixes[method] then
+ return prefixes[method](target)
+ else
+ return method .. ":" .. target
+ end
+end
+
+local function resolve(str)
+ if type(str) == "table" then
+ for k=1,#str do
+ local v = str[k]
+ str[k] = resolve(v) or v
+ end
+ elseif str and str ~= "" then
+ str = gsub(str,"([a-z]+):([^ \"\']*)",_resolve_)
+ end
+ return str
+end
+
+resolvers.resolve = resolve
+
+if os.uname then
+
+ for k, v in next, os.uname() do
+ if not prefixes[k] then
+ prefixes[k] = function() return v end
+ end
+ end
+
+end
diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua
new file mode 100644
index 000000000..ecef14188
--- /dev/null
+++ b/tex/context/base/data-res.lua
@@ -0,0 +1,2181 @@
+if not modules then modules = { } end modules ['data-inp'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- After a few years using the code the large luat-inp.lua file
+-- has been split up a bit. In the process some functionality was
+-- dropped:
+--
+-- * support for reading lsr files
+-- * selective scanning (subtrees)
+-- * some public auxiliary functions were made private
+--
+-- TODO: os.getenv -> os.env[]
+-- TODO: instances.[hashes,cnffiles,configurations,522]
+-- TODO: check escaping in find etc, too much, too slow
+
+-- This lib is multi-purpose and can be loaded again later on so that
+-- additional functionality becomes available. We will split thislogs.report("fileio",
+-- module in components once we're done with prototyping. This is the
+-- first code I wrote for LuaTeX, so it needs some cleanup. Before changing
+-- something in this module one can best check with Taco or Hans first; there
+-- is some nasty trickery going on that relates to traditional kpse support.
+
+-- To be considered: hash key lowercase, first entry in table filename
+-- (any case), rest paths (so no need for optimization). Or maybe a
+-- separate table that matches lowercase names to mixed case when
+-- present. In that case the lower() cases can go away. I will do that
+-- only when we run into problems with names ... well ... Iwona-Regular.
+
+-- Beware, loading and saving is overloaded in luat-tmp!
+
+local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
+local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
+local next, type = next, type
+local lpegmatch = lpeg.match
+
+local trace_locating, trace_detail, trace_expansions = false, false, false
+
+trackers.register("resolvers.locating", function(v) trace_locating = v end)
+trackers.register("resolvers.details", function(v) trace_detail = v end)
+trackers.register("resolvers.expansions", function(v) trace_expansions = v end) -- todo
+
+if not resolvers then
+ resolvers = {
+ suffixes = { },
+ formats = { },
+ dangerous = { },
+ suffixmap = { },
+ alternatives = { },
+ locators = { }, -- locate databases
+ hashers = { }, -- load databases
+ generators = { }, -- generate databases
+ }
+end
+
+local resolvers = resolvers
+
+resolvers.locators .notfound = { nil }
+resolvers.hashers .notfound = { nil }
+resolvers.generators.notfound = { nil }
+
+resolvers.cacheversion = '1.0.1'
+resolvers.cnfname = 'texmf.cnf'
+resolvers.luaname = 'texmfcnf.lua'
+resolvers.homedir = os.env[os.type == "windows" and 'USERPROFILE'] or os.env['HOME'] or '~'
+resolvers.cnfdefault = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}'
+
+local dummy_path_expr = "^!*unset/*$"
+
+local formats = resolvers.formats
+local suffixes = resolvers.suffixes
+local dangerous = resolvers.dangerous
+local suffixmap = resolvers.suffixmap
+local alternatives = resolvers.alternatives
+
+formats['afm'] = 'AFMFONTS' suffixes['afm'] = { 'afm' }
+formats['enc'] = 'ENCFONTS' suffixes['enc'] = { 'enc' }
+formats['fmt'] = 'TEXFORMATS' suffixes['fmt'] = { 'fmt' }
+formats['map'] = 'TEXFONTMAPS' suffixes['map'] = { 'map' }
+formats['mp'] = 'MPINPUTS' suffixes['mp'] = { 'mp' }
+formats['ocp'] = 'OCPINPUTS' suffixes['ocp'] = { 'ocp' }
+formats['ofm'] = 'OFMFONTS' suffixes['ofm'] = { 'ofm', 'tfm' }
+formats['otf'] = 'OPENTYPEFONTS' suffixes['otf'] = { 'otf' } -- 'ttf'
+formats['opl'] = 'OPLFONTS' suffixes['opl'] = { 'opl' }
+formats['otp'] = 'OTPINPUTS' suffixes['otp'] = { 'otp' }
+formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' }
+formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' }
+formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' }
+formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' }
+formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' }
+formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' }
+formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
+
+formats['fea'] = 'FONTFEATURES' suffixes['fea'] = { 'fea' }
+formats['cid'] = 'FONTCIDMAPS' suffixes['cid'] = { 'cid', 'cidmap' }
+
+formats ['texmfscripts'] = 'TEXMFSCRIPTS' -- new
+suffixes['texmfscripts'] = { 'rb', 'pl', 'py' } -- 'lua'
+
+formats ['lua'] = 'LUAINPUTS' -- new
+suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' }
+
+-- backward compatible ones
+
+alternatives['map files'] = 'map'
+alternatives['enc files'] = 'enc'
+alternatives['cid maps'] = 'cid' -- great, why no cid files
+alternatives['font feature files'] = 'fea' -- and fea files here
+alternatives['opentype fonts'] = 'otf'
+alternatives['truetype fonts'] = 'ttf'
+alternatives['truetype collections'] = 'ttc'
+alternatives['truetype dictionary'] = 'dfont'
+alternatives['type1 fonts'] = 'pfb'
+
+-- obscure ones
+
+formats ['misc fonts'] = ''
+suffixes['misc fonts'] = { }
+
+formats ['sfd'] = 'SFDFONTS'
+suffixes ['sfd'] = { 'sfd' }
+alternatives['subfont definition files'] = 'sfd'
+
+-- lib paths
+
+formats ['lib'] = 'CLUAINPUTS' -- new (needs checking)
+suffixes['lib'] = (os.libsuffix and { os.libsuffix }) or { 'dll', 'so' }
+
+-- In practice we will work within one tds tree, but i want to keep
+-- the option open to build tools that look at multiple trees, which is
+-- why we keep the tree specific data in a table. We used to pass the
+-- instance but for practical pusposes we now avoid this and use a
+-- instance variable.
+
+-- here we catch a few new thingies (todo: add these paths to context.tmf)
+--
+-- FONTFEATURES = .;$TEXMF/fonts/fea//
+-- FONTCIDMAPS = .;$TEXMF/fonts/cid//
+
+-- we always have one instance active
+
+resolvers.instance = resolvers.instance or nil -- the current one (slow access)
+local instance = resolvers.instance or nil -- the current one (fast access)
+
+function resolvers.newinstance()
+
+ -- store once, freeze and faster (once reset we can best use
+ -- instance.environment) maybe better have a register suffix
+ -- function
+
+ for k, v in next, suffixes do
+ for i=1,#v do
+ local vi = v[i]
+ if vi then
+ suffixmap[vi] = k
+ end
+ end
+ end
+
+ -- because vf searching is somewhat dangerous, we want to prevent
+ -- too liberal searching esp because we do a lookup on the current
+ -- path anyway; only tex (or any) is safe
+
+ for k, v in next, formats do
+ dangerous[k] = true
+ end
+ dangerous.tex = nil
+
+ -- the instance
+
+ local newinstance = {
+ rootpath = '',
+ treepath = '',
+ progname = 'context',
+ engine = 'luatex',
+ format = '',
+ environment = { },
+ variables = { },
+ expansions = { },
+ files = { },
+ remap = { },
+ configuration = { },
+ setup = { },
+ order = { },
+ found = { },
+ foundintrees = { },
+ kpsevars = { },
+ hashes = { },
+ cnffiles = { },
+ luafiles = { },
+ lists = { },
+ remember = true,
+ diskcache = true,
+ renewcache = false,
+ scandisk = true,
+ cachepath = nil,
+ loaderror = false,
+ sortdata = false,
+ savelists = true,
+ cleanuppaths = true,
+ allresults = false,
+ pattern = nil, -- lists
+ data = { }, -- only for loading
+ force_suffixes = true,
+ fakepaths = { },
+ }
+
+ local ne = newinstance.environment
+
+ for k,v in next, os.env do
+ ne[k] = resolvers.bare_variable(v)
+ end
+
+ return newinstance
+
+end
+
+function resolvers.setinstance(someinstance)
+ instance = someinstance
+ resolvers.instance = someinstance
+ return someinstance
+end
+
+function resolvers.reset()
+ return resolvers.setinstance(resolvers.newinstance())
+end
+
+local function reset_hashes()
+ instance.lists = { }
+ instance.found = { }
+end
+
+local function check_configuration() -- not yet ok, no time for debugging now
+ local ie, iv = instance.environment, instance.variables
+ local function fix(varname,default)
+ local proname = varname .. "." .. instance.progname or "crap"
+ local p, v = ie[proname], ie[varname] or iv[varname]
+ if not ((p and p ~= "") or (v and v ~= "")) then
+ iv[varname] = default -- or environment?
+ end
+ end
+ local name = os.name
+ if name == "windows" then
+ fix("OSFONTDIR", "c:/windows/fonts//")
+ elseif name == "macosx" then
+ fix("OSFONTDIR", "$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
+ else
+ -- bad luck
+ end
+ fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm
+ -- this will go away some day
+ fix("FONTFEATURES", ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
+ fix("FONTCIDMAPS" , ".;$TEXMF/fonts/{data,cid}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
+ --
+ fix("LUATEXLIBS" , ".;$TEXMF/luatex/lua//")
+end
+
+function resolvers.bare_variable(str) -- assumes str is a string
+ return (gsub(str,"\s*([\"\']?)(.+)%1\s*", "%2"))
+end
+
+function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
+ if n then
+ trackers.disable("resolvers.*")
+ trackers.enable("resolvers."..n)
+ end
+end
+
+resolvers.settrace(os.getenv("MTX_INPUT_TRACE"))
+
+function resolvers.osenv(key)
+ local ie = instance.environment
+ local value = ie[key]
+ if value == nil then
+ -- local e = os.getenv(key)
+ local e = os.env[key]
+ if e == nil then
+ -- value = "" -- false
+ else
+ value = resolvers.bare_variable(e)
+ end
+ ie[key] = value
+ end
+ return value or ""
+end
+
+function resolvers.env(key)
+ return instance.environment[key] or resolvers.osenv(key)
+end
+
+--
+
+local function expand_vars(lst) -- simple vars
+ local variables, env = instance.variables, resolvers.env
+ local function resolve(a)
+ return variables[a] or env(a)
+ end
+ for k=1,#lst do
+ lst[k] = gsub(lst[k],"%$([%a%d%_%-]+)",resolve)
+ end
+end
+
+local function expanded_var(var) -- simple vars
+ local function resolve(a)
+ return instance.variables[a] or resolvers.env(a)
+ end
+ return (gsub(var,"%$([%a%d%_%-]+)",resolve))
+end
+
+local function entry(entries,name)
+ if name and (name ~= "") then
+ name = gsub(name,'%$','')
+ local result = entries[name..'.'..instance.progname] or entries[name]
+ if result then
+ return result
+ else
+ result = resolvers.env(name)
+ if result then
+ instance.variables[name] = result
+ resolvers.expand_variables()
+ return instance.expansions[name] or ""
+ end
+ end
+ end
+ return ""
+end
+
+local function is_entry(entries,name)
+ if name and name ~= "" then
+ name = gsub(name,'%$','')
+ return (entries[name..'.'..instance.progname] or entries[name]) ~= nil
+ else
+ return false
+ end
+end
+
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
+-- this one is better and faster, but it took me a while to realize
+-- that this kind of replacement is cleaner than messy parsing and
+-- fuzzy concatenating we can probably gain a bit with selectively
+-- applying lpeg, but experiments with lpeg parsing this proved not to
+-- work that well; the parsing is ok, but dealing with the resulting
+-- table is a pain because we need to work inside-out recursively
+
+local function do_first(a,b)
+ local t = { }
+ for s in gmatch(b,"[^,]+") do t[#t+1] = a .. s end
+ return "{" .. concat(t,",") .. "}"
+end
+
+local function do_second(a,b)
+ local t = { }
+ for s in gmatch(a,"[^,]+") do t[#t+1] = s .. b end
+ return "{" .. concat(t,",") .. "}"
+end
+
+local function do_both(a,b)
+ local t = { }
+ for sa in gmatch(a,"[^,]+") do
+ for sb in gmatch(b,"[^,]+") do
+ t[#t+1] = sa .. sb
+ end
+ end
+ return "{" .. concat(t,",") .. "}"
+end
+
+local function do_three(a,b,c)
+ return a .. b.. c
+end
+
+local function splitpathexpr(str, t, validate)
+ -- no need for further optimization as it is only called a
+ -- few times, we can use lpeg for the sub
+ if trace_expansions then
+ logs.report("fileio","expanding variable '%s'",str)
+ end
+ t = t or { }
+ str = gsub(str,",}",",@}")
+ str = gsub(str,"{,","{@,")
+ -- str = "@" .. str .. "@"
+ local ok, done
+ while true do
+ done = false
+ while true do
+ str, ok = gsub(str,"([^{},]+){([^{}]+)}",do_first)
+ if ok > 0 then done = true else break end
+ end
+ while true do
+ str, ok = gsub(str,"{([^{}]+)}([^{},]+)",do_second)
+ if ok > 0 then done = true else break end
+ end
+ while true do
+ str, ok = gsub(str,"{([^{}]+)}{([^{}]+)}",do_both)
+ if ok > 0 then done = true else break end
+ end
+ str, ok = gsub(str,"({[^{}]*){([^{}]+)}([^{}]*})",do_three)
+ if ok > 0 then done = true end
+ if not done then break end
+ end
+ str = gsub(str,"[{}]", "")
+ str = gsub(str,"@","")
+ if validate then
+ for s in gmatch(str,"[^,]+") do
+ s = validate(s)
+ if s then t[#t+1] = s end
+ end
+ else
+ for s in gmatch(str,"[^,]+") do
+ t[#t+1] = s
+ end
+ end
+ if trace_expansions then
+ for k=1,#t do
+ logs.report("fileio","% 4i: %s",k,t[k])
+ end
+ end
+ return t
+end
+
+local function expanded_path_from_list(pathlist) -- maybe not a list, just a path
+ -- a previous version fed back into pathlist
+ local newlist, ok = { }, false
+ for k=1,#pathlist do
+ if find(pathlist[k],"[{}]") then
+ ok = true
+ break
+ end
+ end
+ if ok then
+ local function validate(s)
+ s = file.collapse_path(s)
+ return s ~= "" and not find(s,dummy_path_expr) and s
+ end
+ for k=1,#pathlist do
+ splitpathexpr(pathlist[k],newlist,validate)
+ end
+ else
+ for k=1,#pathlist do
+ for p in gmatch(pathlist[k],"([^,]+)") do
+ p = file.collapse_path(p)
+ if p ~= "" then newlist[#newlist+1] = p end
+ end
+ end
+ end
+ return newlist
+end
+
+-- we follow a rather traditional approach:
+--
+-- (1) texmf.cnf given in TEXMFCNF
+-- (2) texmf.cnf searched in default variable
+--
+-- also we now follow the stupid route: if not set then just assume *one*
+-- cnf file under texmf (i.e. distribution)
+
+local args = environment and environment.original_arguments or arg -- this needs a cleanup
+
+resolvers.ownbin = resolvers.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
+resolvers.ownbin = gsub(resolvers.ownbin,"\\","/")
+
+function resolvers.getownpath()
+ local ownpath = resolvers.ownpath or os.selfdir
+ if not ownpath or ownpath == "" or ownpath == "unset" then
+ ownpath = args[-1] or arg[-1]
+ ownpath = ownpath and file.dirname(gsub(ownpath,"\\","/"))
+ if not ownpath or ownpath == "" then
+ ownpath = args[-0] or arg[-0]
+ ownpath = ownpath and file.dirname(gsub(ownpath,"\\","/"))
+ end
+ local binary = resolvers.ownbin
+ if not ownpath or ownpath == "" then
+ ownpath = ownpath and file.dirname(binary)
+ end
+ if not ownpath or ownpath == "" then
+ if os.binsuffix ~= "" then
+ binary = file.replacesuffix(binary,os.binsuffix)
+ end
+ for p in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
+ local b = file.join(p,binary)
+ if lfs.isfile(b) then
+ -- we assume that after changing to the path the currentdir function
+ -- resolves to the real location and use this side effect here; this
+ -- trick is needed because on the mac installations use symlinks in the
+ -- path instead of real locations
+ local olddir = lfs.currentdir()
+ if lfs.chdir(p) then
+ local pp = lfs.currentdir()
+ if trace_locating and p ~= pp then
+ logs.report("fileio","following symlink '%s' to '%s'",p,pp)
+ end
+ ownpath = pp
+ lfs.chdir(olddir)
+ else
+ if trace_locating then
+ logs.report("fileio","unable to check path '%s'",p)
+ end
+ ownpath = p
+ end
+ break
+ end
+ end
+ end
+ if not ownpath or ownpath == "" then
+ ownpath = "."
+ logs.report("fileio","forcing fallback ownpath .")
+ elseif trace_locating then
+ logs.report("fileio","using ownpath '%s'",ownpath)
+ end
+ end
+ resolvers.ownpath = ownpath
+ function resolvers.getownpath()
+ return resolvers.ownpath
+ end
+ return ownpath
+end
+
+local own_places = { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF" }
+
+local function identify_own()
+ local ownpath = resolvers.getownpath() or dir.current()
+ local ie = instance.environment
+ if ownpath then
+ if resolvers.env('SELFAUTOLOC') == "" then os.env['SELFAUTOLOC'] = file.collapse_path(ownpath) end
+ if resolvers.env('SELFAUTODIR') == "" then os.env['SELFAUTODIR'] = file.collapse_path(ownpath .. "/..") end
+ if resolvers.env('SELFAUTOPARENT') == "" then os.env['SELFAUTOPARENT'] = file.collapse_path(ownpath .. "/../..") end
+ else
+ logs.report("fileio","error: unable to locate ownpath")
+ os.exit()
+ end
+ if resolvers.env('TEXMFCNF') == "" then os.env['TEXMFCNF'] = resolvers.cnfdefault end
+ if resolvers.env('TEXOS') == "" then os.env['TEXOS'] = resolvers.env('SELFAUTODIR') end
+ if resolvers.env('TEXROOT') == "" then os.env['TEXROOT'] = resolvers.env('SELFAUTOPARENT') end
+ if trace_locating then
+ for i=1,#own_places do
+ local v = own_places[i]
+ logs.report("fileio","variable '%s' set to '%s'",v,resolvers.env(v) or "unknown")
+ end
+ end
+ identify_own = function() end
+end
+
+function resolvers.identify_cnf()
+ if #instance.cnffiles == 0 then
+ -- fallback
+ identify_own()
+ -- the real search
+ resolvers.expand_variables()
+ local t = resolvers.split_path(resolvers.env('TEXMFCNF'))
+ t = expanded_path_from_list(t)
+ expand_vars(t) -- redundant
+ local function locate(filename,list)
+ for i=1,#t do
+ local ti = t[i]
+ local texmfcnf = file.collapse_path(file.join(ti,filename))
+ if lfs.isfile(texmfcnf) then
+ list[#list+1] = texmfcnf
+ end
+ end
+ end
+ locate(resolvers.luaname,instance.luafiles)
+ locate(resolvers.cnfname,instance.cnffiles)
+ end
+end
+
+local function load_cnf_file(fname)
+ fname = resolvers.clean_path(fname)
+ local lname = file.replacesuffix(fname,'lua')
+ if lfs.isfile(lname) then
+ local dname = file.dirname(fname) -- fname ?
+ if not instance.configuration[dname] then
+ resolvers.load_data(dname,'configuration',lname and file.basename(lname))
+ instance.order[#instance.order+1] = instance.configuration[dname]
+ end
+ else
+ f = io.open(fname)
+ if f then
+ if trace_locating then
+ logs.report("fileio","loading configuration file %s", fname)
+ end
+ local line, data, n, k, v
+ local dname = file.dirname(fname)
+ if not instance.configuration[dname] then
+ instance.configuration[dname] = { }
+ instance.order[#instance.order+1] = instance.configuration[dname]
+ end
+ local data = instance.configuration[dname]
+ while true do
+ local line, n = f:read(), 0
+ if line then
+ while true do -- join lines
+ line, n = gsub(line,"\\%s*$", "")
+ if n > 0 then
+ line = line .. f:read()
+ else
+ break
+ end
+ end
+ if not find(line,"^[%%#]") then
+ local l = gsub(line,"%s*%%.*$","")
+ local k, v = match(l,"%s*(.-)%s*=%s*(.-)%s*$")
+ if k and v and not data[k] then
+ v = gsub(v,"[%%#].*",'')
+ data[k] = gsub(v,"~","$HOME")
+ instance.kpsevars[k] = true
+ end
+ end
+ else
+ break
+ end
+ end
+ f:close()
+ elseif trace_locating then
+ logs.report("fileio","skipping configuration file '%s'", fname)
+ end
+ end
+end
+
+local function collapse_cnf_data() -- potential optimization: pass start index (setup and configuration are shared)
+ local order = instance.order
+ for i=1,#order do
+ local c = order[i]
+ for k,v in next, c do
+ if not instance.variables[k] then
+ if instance.environment[k] then
+ instance.variables[k] = instance.environment[k]
+ else
+ instance.kpsevars[k] = true
+ instance.variables[k] = resolvers.bare_variable(v)
+ end
+ end
+ end
+ end
+end
+
+function resolvers.load_cnf()
+ local function loadoldconfigdata()
+ local cnffiles = instance.cnffiles
+ for i=1,#cnffiles do
+ load_cnf_file(cnffiles[i])
+ end
+ end
+ -- instance.cnffiles contain complete names now !
+ -- we still use a funny mix of cnf and new but soon
+ -- we will switch to lua exclusively as we only use
+ -- the file to collect the tree roots
+ if #instance.cnffiles == 0 then
+ if trace_locating then
+ logs.report("fileio","no cnf files found (TEXMFCNF may not be set/known)")
+ end
+ else
+ local cnffiles = instance.cnffiles
+ instance.rootpath = cnffiles[1]
+ for k=1,#cnffiles do
+ instance.cnffiles[k] = file.collapse_path(cnffiles[k])
+ end
+ for i=1,3 do
+ instance.rootpath = file.dirname(instance.rootpath)
+ end
+ instance.rootpath = file.collapse_path(instance.rootpath)
+ if instance.diskcache and not instance.renewcache then
+ resolvers.loadoldconfig(instance.cnffiles)
+ if instance.loaderror then
+ loadoldconfigdata()
+ resolvers.saveoldconfig()
+ end
+ else
+ loadoldconfigdata()
+ if instance.renewcache then
+ resolvers.saveoldconfig()
+ end
+ end
+ collapse_cnf_data()
+ end
+ check_configuration()
+end
+
+function resolvers.load_lua()
+ if #instance.luafiles == 0 then
+ -- yet harmless
+ else
+ instance.rootpath = instance.luafiles[1]
+ local luafiles = instance.luafiles
+ for k=1,#luafiles do
+ instance.luafiles[k] = file.collapse_path(luafiles[k])
+ end
+ for i=1,3 do
+ instance.rootpath = file.dirname(instance.rootpath)
+ end
+ instance.rootpath = file.collapse_path(instance.rootpath)
+ resolvers.loadnewconfig()
+ collapse_cnf_data()
+ end
+ check_configuration()
+end
+
+-- database loading
+
+function resolvers.load_hash()
+ resolvers.locatelists()
+ if instance.diskcache and not instance.renewcache then
+ resolvers.loadfiles()
+ if instance.loaderror then
+ resolvers.loadlists()
+ resolvers.savefiles()
+ end
+ else
+ resolvers.loadlists()
+ if instance.renewcache then
+ resolvers.savefiles()
+ end
+ end
+end
+
+function resolvers.append_hash(type,tag,name)
+ if trace_locating then
+ logs.report("fileio","hash '%s' appended",tag)
+ end
+ insert(instance.hashes, { ['type']=type, ['tag']=tag, ['name']=name } )
+end
+
+function resolvers.prepend_hash(type,tag,name)
+ if trace_locating then
+ logs.report("fileio","hash '%s' prepended",tag)
+ end
+ insert(instance.hashes, 1, { ['type']=type, ['tag']=tag, ['name']=name } )
+end
+
+function resolvers.extend_texmf_var(specification) -- crap, we could better prepend the hash
+-- local t = resolvers.expanded_path_list('TEXMF') -- full expansion
+ local t = resolvers.split_path(resolvers.env('TEXMF'))
+ insert(t,1,specification)
+ local newspec = concat(t,";")
+ if instance.environment["TEXMF"] then
+ instance.environment["TEXMF"] = newspec
+ elseif instance.variables["TEXMF"] then
+ instance.variables["TEXMF"] = newspec
+ else
+ -- weird
+ end
+ resolvers.expand_variables()
+ reset_hashes()
+end
+
+-- locators
+
+function resolvers.locatelists()
+ local texmfpaths = resolvers.clean_path_list('TEXMF')
+ for i=1,#texmfpaths do
+ local path = texmfpaths[i]
+ if trace_locating then
+ logs.report("fileio","locating list of '%s'",path)
+ end
+ resolvers.locatedatabase(file.collapse_path(path))
+ end
+end
+
+function resolvers.locatedatabase(specification)
+ return resolvers.methodhandler('locators', specification)
+end
+
+function resolvers.locators.tex(specification)
+ if specification and specification ~= '' and lfs.isdir(specification) then
+ if trace_locating then
+ logs.report("fileio","tex locator '%s' found",specification)
+ end
+ resolvers.append_hash('file',specification,filename)
+ elseif trace_locating then
+ logs.report("fileio","tex locator '%s' not found",specification)
+ end
+end
+
+-- hashers
+
+function resolvers.hashdatabase(tag,name)
+ return resolvers.methodhandler('hashers',tag,name)
+end
+
+function resolvers.loadfiles()
+ instance.loaderror = false
+ instance.files = { }
+ if not instance.renewcache then
+ local hashes = instance.hashes
+ for k=1,#hashes do
+ local hash = hashes[k]
+ resolvers.hashdatabase(hash.tag,hash.name)
+ if instance.loaderror then break end
+ end
+ end
+end
+
+function resolvers.hashers.tex(tag,name)
+ resolvers.load_data(tag,'files')
+end
+
+-- generators:
+
+function resolvers.loadlists()
+ local hashes = instance.hashes
+ for i=1,#hashes do
+ resolvers.generatedatabase(hashes[i].tag)
+ end
+end
+
+function resolvers.generatedatabase(specification)
+ return resolvers.methodhandler('generators', specification)
+end
+
+-- starting with . or .. etc or funny char
+
+local weird = lpeg.P(".")^1 + lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+
+--~ local l_forbidden = lpeg.S("~`!#$%^&*()={}[]:;\"\'||\\/<>,?\n\r\t")
+--~ local l_confusing = lpeg.P(" ")
+--~ local l_character = lpeg.patterns.utf8
+--~ local l_dangerous = lpeg.P(".")
+
+--~ local l_normal = (l_character - l_forbidden - l_confusing - l_dangerous) * (l_character - l_forbidden - l_confusing^2)^0 * lpeg.P(-1)
+--~ ----- l_normal = l_normal * lpeg.Cc(true) + lpeg.Cc(false)
+
+--~ local function test(str)
+--~ print(str,lpeg.match(l_normal,str))
+--~ end
+--~ test("ヒラギノ明朝 Pro W3")
+--~ test("..ヒラギノ明朝 Pro W3")
+--~ test(":ヒラギノ明朝 Pro W3;")
+--~ test("ヒラギノ明朝 /Pro W3;")
+--~ test("ヒラギノ明朝 Pro W3")
+
+function resolvers.generators.tex(specification)
+ local tag = specification
+ if trace_locating then
+ logs.report("fileio","scanning path '%s'",specification)
+ end
+ instance.files[tag] = { }
+ local files = instance.files[tag]
+ local n, m, r = 0, 0, 0
+ local spec = specification .. '/'
+ local attributes = lfs.attributes
+ local directory = lfs.dir
+ local function action(path)
+ local full
+ if path then
+ full = spec .. path .. '/'
+ else
+ full = spec
+ end
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ -- if lpegmatch(l_normal,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if path then
+ n = n + 1
+ local f = files[name]
+ if f then
+ if type(f) == 'string' then
+ files[name] = { f, path }
+ else
+ f[#f+1] = path
+ end
+ else -- probably unique anyway
+ files[name] = path
+ local lower = lower(name)
+ if name ~= lower then
+ files["remap:"..lower] = name
+ r = r + 1
+ end
+ end
+ end
+ elseif mode == 'directory' then
+ m = m + 1
+ if path then
+ action(path..'/'..name)
+ else
+ action(name)
+ end
+ end
+ end
+ end
+ end
+ action()
+ if trace_locating then
+ logs.report("fileio","%s files found on %s directories with %s uppercase remappings",n,m,r)
+ end
+end
+
+-- savers, todo
+
+function resolvers.savefiles()
+ resolvers.save_data('files')
+end
+
+-- A config (optionally) has the paths split in tables. Internally
+-- we join them and split them after the expansion has taken place. This
+-- is more convenient.
+
+--~ local checkedsplit = string.checkedsplit
+
+local cache = { }
+
+local splitter = lpeg.Ct(lpeg.splitat(lpeg.S(os.type == "windows" and ";" or ":;")))
+
+local function split_kpse_path(str) -- beware, this can be either a path or a {specification}
+ local found = cache[str]
+ if not found then
+ if str == "" then
+ found = { }
+ else
+ str = gsub(str,"\\","/")
+--~ local split = (find(str,";") and checkedsplit(str,";")) or checkedsplit(str,io.pathseparator)
+local split = lpegmatch(splitter,str)
+ found = { }
+ for i=1,#split do
+ local s = split[i]
+ if not find(s,"^{*unset}*") then
+ found[#found+1] = s
+ end
+ end
+ if trace_expansions then
+ logs.report("fileio","splitting path specification '%s'",str)
+ for k=1,#found do
+ logs.report("fileio","% 4i: %s",k,found[k])
+ end
+ end
+ cache[str] = found
+ end
+ end
+ return found
+end
+
+resolvers.split_kpse_path = split_kpse_path
+
+function resolvers.splitconfig()
+ for i=1,#instance do
+ local c = instance[i]
+ for k,v in next, c do
+ if type(v) == 'string' then
+ local t = split_kpse_path(v)
+ if #t > 1 then
+ c[k] = t
+ end
+ end
+ end
+ end
+end
+
+function resolvers.joinconfig()
+ local order = instance.order
+ for i=1,#order do
+ local c = order[i]
+ for k,v in next, c do -- indexed?
+ if type(v) == 'table' then
+ c[k] = file.join_path(v)
+ end
+ end
+ end
+end
+
+function resolvers.split_path(str)
+ if type(str) == 'table' then
+ return str
+ else
+ return split_kpse_path(str)
+ end
+end
+
+function resolvers.join_path(str)
+ if type(str) == 'table' then
+ return file.join_path(str)
+ else
+ return str
+ end
+end
+
+function resolvers.splitexpansions()
+ local ie = instance.expansions
+ for k,v in next, ie do
+ local t, h, p = { }, { }, split_kpse_path(v)
+ for kk=1,#p do
+ local vv = p[kk]
+ if vv ~= "" and not h[vv] then
+ t[#t+1] = vv
+ h[vv] = true
+ end
+ end
+ if #t > 1 then
+ ie[k] = t
+ else
+ ie[k] = t[1]
+ end
+ end
+end
+
+-- end of split/join code
+
+function resolvers.saveoldconfig()
+ resolvers.splitconfig()
+ resolvers.save_data('configuration')
+ resolvers.joinconfig()
+end
+
+resolvers.configbanner = [[
+-- This is a Luatex configuration file created by 'luatools.lua' or
+-- 'luatex.exe' directly. For comment, suggestions and questions you can
+-- contact the ConTeXt Development Team. This configuration file is
+-- not copyrighted. [HH & TH]
+]]
+
+function resolvers.serialize(files)
+ -- This version is somewhat optimized for the kind of
+ -- tables that we deal with, so it's much faster than
+ -- the generic serializer. This makes sense because
+ -- luatools and mtxtools are called frequently. Okay,
+ -- we pay a small price for properly tabbed tables.
+ local t = { }
+ local function dump(k,v,m) -- could be moved inline
+ if type(v) == 'string' then
+ return m .. "['" .. k .. "']='" .. v .. "',"
+ elseif #v == 1 then
+ return m .. "['" .. k .. "']='" .. v[1] .. "',"
+ else
+ return m .. "['" .. k .. "']={'" .. concat(v,"','").. "'},"
+ end
+ end
+ t[#t+1] = "return {"
+ if instance.sortdata then
+ local sortedfiles = sortedkeys(files)
+ for i=1,#sortedfiles do
+ local k = sortedfiles[i]
+ local fk = files[k]
+ if type(fk) == 'table' then
+ t[#t+1] = "\t['" .. k .. "']={"
+ local sortedfk = sortedkeys(fk)
+ for j=1,#sortedfk do
+ local kk = sortedfk[j]
+ t[#t+1] = dump(kk,fk[kk],"\t\t")
+ end
+ t[#t+1] = "\t},"
+ else
+ t[#t+1] = dump(k,fk,"\t")
+ end
+ end
+ else
+ for k, v in next, files do
+ if type(v) == 'table' then
+ t[#t+1] = "\t['" .. k .. "']={"
+ for kk,vv in next, v do
+ t[#t+1] = dump(kk,vv,"\t\t")
+ end
+ t[#t+1] = "\t},"
+ else
+ t[#t+1] = dump(k,v,"\t")
+ end
+ end
+ end
+ t[#t+1] = "}"
+ return concat(t,"\n")
+end
+
+local data_state = { }
+
+function resolvers.data_state()
+ return data_state or { }
+end
+
+function resolvers.save_data(dataname, makename) -- untested without cache overload
+ for cachename, files in next, instance[dataname] do
+ local name = (makename or file.join)(cachename,dataname)
+ local luaname, lucname = name .. ".lua", name .. ".luc"
+ if trace_locating then
+ logs.report("fileio","preparing '%s' for '%s'",dataname,cachename)
+ end
+ for k, v in next, files do
+ if type(v) == "table" and #v == 1 then
+ files[k] = v[1]
+ end
+ end
+ local data = {
+ type = dataname,
+ root = cachename,
+ version = resolvers.cacheversion,
+ date = os.date("%Y-%m-%d"),
+ time = os.date("%H:%M:%S"),
+ content = files,
+ uuid = os.uuid(),
+ }
+ local ok = io.savedata(luaname,resolvers.serialize(data))
+ if ok then
+ if trace_locating then
+ logs.report("fileio","'%s' saved in '%s'",dataname,luaname)
+ end
+ if utils.lua.compile(luaname,lucname,false,true) then -- no cleanup but strip
+ if trace_locating then
+ logs.report("fileio","'%s' compiled to '%s'",dataname,lucname)
+ end
+ else
+ if trace_locating then
+ logs.report("fileio","compiling failed for '%s', deleting file '%s'",dataname,lucname)
+ end
+ os.remove(lucname)
+ end
+ elseif trace_locating then
+ logs.report("fileio","unable to save '%s' in '%s' (access error)",dataname,luaname)
+ end
+ end
+end
+
+function resolvers.load_data(pathname,dataname,filename,makename) -- untested without cache overload
+ filename = ((not filename or (filename == "")) and dataname) or filename
+ filename = (makename and makename(dataname,filename)) or file.join(pathname,filename)
+ local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
+ if blob then
+ local data = blob()
+ if data and data.content and data.type == dataname and data.version == resolvers.cacheversion then
+ data_state[#data_state+1] = data.uuid
+ if trace_locating then
+ logs.report("fileio","loading '%s' for '%s' from '%s'",dataname,pathname,filename)
+ end
+ instance[dataname][pathname] = data.content
+ else
+ if trace_locating then
+ logs.report("fileio","skipping '%s' for '%s' from '%s'",dataname,pathname,filename)
+ end
+ instance[dataname][pathname] = { }
+ instance.loaderror = true
+ end
+ elseif trace_locating then
+ logs.report("fileio","skipping '%s' for '%s' from '%s'",dataname,pathname,filename)
+ end
+end
+
+-- some day i'll use the nested approach, but not yet (actually we even drop
+-- engine/progname support since we have only luatex now)
+--
+-- first texmfcnf.lua files are located, next the cached texmf.cnf files
+--
+-- return {
+-- TEXMFBOGUS = 'effe checken of dit werkt',
+-- }
+
+function resolvers.resetconfig()
+ identify_own()
+ instance.configuration, instance.setup, instance.order, instance.loaderror = { }, { }, { }, false
+end
+
+function resolvers.loadnewconfig()
+ local luafiles = instance.luafiles
+ for i=1,#luafiles do
+ local cnf = luafiles[i]
+ local pathname = file.dirname(cnf)
+ local filename = file.join(pathname,resolvers.luaname)
+ local blob = loadfile(filename)
+ if blob then
+ local data = blob()
+ if data then
+ if trace_locating then
+ logs.report("fileio","loading configuration file '%s'",filename)
+ end
+ if true then
+ -- flatten to variable.progname
+ local t = { }
+ for k, v in next, data do -- v = progname
+ if type(v) == "string" then
+ t[k] = v
+ else
+ for kk, vv in next, v do -- vv = variable
+ if type(vv) == "string" then
+ t[vv.."."..v] = kk
+ end
+ end
+ end
+ end
+ instance['setup'][pathname] = t
+ else
+ instance['setup'][pathname] = data
+ end
+ else
+ if trace_locating then
+ logs.report("fileio","skipping configuration file '%s'",filename)
+ end
+ instance['setup'][pathname] = { }
+ instance.loaderror = true
+ end
+ elseif trace_locating then
+ logs.report("fileio","skipping configuration file '%s'",filename)
+ end
+ instance.order[#instance.order+1] = instance.setup[pathname]
+ if instance.loaderror then break end
+ end
+end
+
+function resolvers.loadoldconfig()
+ if not instance.renewcache then
+ local cnffiles = instance.cnffiles
+ for i=1,#cnffiles do
+ local cnf = cnffiles[i]
+ local dname = file.dirname(cnf)
+ resolvers.load_data(dname,'configuration')
+ instance.order[#instance.order+1] = instance.configuration[dname]
+ if instance.loaderror then break end
+ end
+ end
+ resolvers.joinconfig()
+end
+
+function resolvers.expand_variables()
+ local expansions, environment, variables = { }, instance.environment, instance.variables
+ local env = resolvers.env
+ instance.expansions = expansions
+ if instance.engine ~= "" then environment['engine'] = instance.engine end
+ if instance.progname ~= "" then environment['progname'] = instance.progname end
+ for k,v in next, environment do
+ local a, b = match(k,"^(%a+)%_(.*)%s*$")
+ if a and b then
+ expansions[a..'.'..b] = v
+ else
+ expansions[k] = v
+ end
+ end
+ for k,v in next, environment do -- move environment to expansions
+ if not expansions[k] then expansions[k] = v end
+ end
+ for k,v in next, variables do -- move variables to expansions
+ if not expansions[k] then expansions[k] = v end
+ end
+ local busy = false
+ local function resolve(a)
+ busy = true
+ return expansions[a] or env(a)
+ end
+ while true do
+ busy = false
+ for k,v in next, expansions do
+ local s, n = gsub(v,"%$([%a%d%_%-]+)",resolve)
+ local s, m = gsub(s,"%$%{([%a%d%_%-]+)%}",resolve)
+ if n > 0 or m > 0 then
+ expansions[k]= s
+ end
+ end
+ if not busy then break end
+ end
+ for k,v in next, expansions do
+ expansions[k] = gsub(v,"\\", '/')
+ end
+end
+
+function resolvers.variable(name)
+ return entry(instance.variables,name)
+end
+
+function resolvers.expansion(name)
+ return entry(instance.expansions,name)
+end
+
+function resolvers.is_variable(name)
+ return is_entry(instance.variables,name)
+end
+
+function resolvers.is_expansion(name)
+ return is_entry(instance.expansions,name)
+end
+
+function resolvers.unexpanded_path_list(str)
+ local pth = resolvers.variable(str)
+ local lst = resolvers.split_path(pth)
+ return expanded_path_from_list(lst)
+end
+
+function resolvers.unexpanded_path(str)
+ return file.join_path(resolvers.unexpanded_path_list(str))
+end
+
+do -- no longer needed
+
+ local done = { }
+
+ function resolvers.reset_extra_path()
+ local ep = instance.extra_paths
+ if not ep then
+ ep, done = { }, { }
+ instance.extra_paths = ep
+ elseif #ep > 0 then
+ instance.lists, done = { }, { }
+ end
+ end
+
+ function resolvers.register_extra_path(paths,subpaths)
+ local ep = instance.extra_paths or { }
+ local n = #ep
+ if paths and paths ~= "" then
+ if subpaths and subpaths ~= "" then
+ for p in gmatch(paths,"[^,]+") do
+ -- we gmatch each step again, not that fast, but used seldom
+ for s in gmatch(subpaths,"[^,]+") do
+ local ps = p .. "/" .. s
+ if not done[ps] then
+ ep[#ep+1] = resolvers.clean_path(ps)
+ done[ps] = true
+ end
+ end
+ end
+ else
+ for p in gmatch(paths,"[^,]+") do
+ if not done[p] then
+ ep[#ep+1] = resolvers.clean_path(p)
+ done[p] = true
+ end
+ end
+ end
+ elseif subpaths and subpaths ~= "" then
+ for i=1,n do
+ -- we gmatch each step again, not that fast, but used seldom
+ for s in gmatch(subpaths,"[^,]+") do
+ local ps = ep[i] .. "/" .. s
+ if not done[ps] then
+ ep[#ep+1] = resolvers.clean_path(ps)
+ done[ps] = true
+ end
+ end
+ end
+ end
+ if #ep > 0 then
+ instance.extra_paths = ep -- register paths
+ end
+ if #ep > n then
+ instance.lists = { } -- erase the cache
+ end
+ end
+
+end
+
+local function made_list(instance,list)
+ local ep = instance.extra_paths
+ if not ep or #ep == 0 then
+ return list
+ else
+ local done, new = { }, { }
+ -- honour . .. ../.. but only when at the start
+ for k=1,#list do
+ local v = list[k]
+ if not done[v] then
+ if find(v,"^[%.%/]$") then
+ done[v] = true
+ new[#new+1] = v
+ else
+ break
+ end
+ end
+ end
+ -- first the extra paths
+ for k=1,#ep do
+ local v = ep[k]
+ if not done[v] then
+ done[v] = true
+ new[#new+1] = v
+ end
+ end
+ -- next the formal paths
+ for k=1,#list do
+ local v = list[k]
+ if not done[v] then
+ done[v] = true
+ new[#new+1] = v
+ end
+ end
+ return new
+ end
+end
+
+function resolvers.clean_path_list(str)
+ local t = resolvers.expanded_path_list(str)
+ if t then
+ for i=1,#t do
+ t[i] = file.collapse_path(resolvers.clean_path(t[i]))
+ end
+ end
+ return t
+end
+
+function resolvers.expand_path(str)
+ return file.join_path(resolvers.expanded_path_list(str))
+end
+
+function resolvers.expanded_path_list(str)
+ if not str then
+ return ep or { } -- ep ?
+ elseif instance.savelists then
+ -- engine+progname hash
+ str = gsub(str,"%$","")
+ if not instance.lists[str] then -- cached
+ local lst = made_list(instance,resolvers.split_path(resolvers.expansion(str)))
+ instance.lists[str] = expanded_path_from_list(lst)
+ end
+ return instance.lists[str]
+ else
+ local lst = resolvers.split_path(resolvers.expansion(str))
+ return made_list(instance,expanded_path_from_list(lst))
+ end
+end
+
+function resolvers.expanded_path_list_from_var(str) -- brrr
+ local tmp = resolvers.var_of_format_or_suffix(gsub(str,"%$",""))
+ if tmp ~= "" then
+ return resolvers.expanded_path_list(tmp)
+ else
+ return resolvers.expanded_path_list(str)
+ end
+end
+
+function resolvers.expand_path_from_var(str)
+ return file.join_path(resolvers.expanded_path_list_from_var(str))
+end
+
+function resolvers.format_of_var(str)
+ return formats[str] or formats[alternatives[str]] or ''
+end
+function resolvers.format_of_suffix(str)
+ return suffixmap[file.extname(str)] or 'tex'
+end
+
+function resolvers.variable_of_format(str)
+ return formats[str] or formats[alternatives[str]] or ''
+end
+
+function resolvers.var_of_format_or_suffix(str)
+ local v = formats[str]
+ if v then
+ return v
+ end
+ v = formats[alternatives[str]]
+ if v then
+ return v
+ end
+ v = suffixmap[file.extname(str)]
+ if v then
+ return formats[isf]
+ end
+ return ''
+end
+
+function resolvers.expand_braces(str) -- output variable and brace expansion of STRING
+ local ori = resolvers.variable(str)
+ local pth = expanded_path_from_list(resolvers.split_path(ori))
+ return file.join_path(pth)
+end
+
+resolvers.isreadable = { }
+
+function resolvers.isreadable.file(name)
+ local readable = lfs.isfile(name) -- brrr
+ if trace_detail then
+ if readable then
+ logs.report("fileio","file '%s' is readable",name)
+ else
+ logs.report("fileio","file '%s' is not readable", name)
+ end
+ end
+ return readable
+end
+
+resolvers.isreadable.tex = resolvers.isreadable.file
+
+-- name
+-- name/name
+
+local function collect_files(names)
+ local filelist = { }
+ for k=1,#names do
+ local fname = names[k]
+ if trace_detail then
+ logs.report("fileio","checking name '%s'",fname)
+ end
+ local bname = file.basename(fname)
+ local dname = file.dirname(fname)
+ if dname == "" or find(dname,"^%.") then
+ dname = false
+ else
+ dname = "/" .. dname .. "$"
+ end
+ local hashes = instance.hashes
+ for h=1,#hashes do
+ local hash = hashes[h]
+ local blobpath = hash.tag
+ local files = blobpath and instance.files[blobpath]
+ if files then
+ if trace_detail then
+ logs.report("fileio","deep checking '%s' (%s)",blobpath,bname)
+ end
+ local blobfile = files[bname]
+ if not blobfile then
+ local rname = "remap:"..bname
+ blobfile = files[rname]
+ if blobfile then
+ bname = files[rname]
+ blobfile = files[bname]
+ end
+ end
+ if blobfile then
+ if type(blobfile) == 'string' then
+ if not dname or find(blobfile,dname) then
+ filelist[#filelist+1] = {
+ hash.type,
+ file.join(blobpath,blobfile,bname), -- search
+ resolvers.concatinators[hash.type](blobpath,blobfile,bname) -- result
+ }
+ end
+ else
+ for kk=1,#blobfile do
+ local vv = blobfile[kk]
+ if not dname or find(vv,dname) then
+ filelist[#filelist+1] = {
+ hash.type,
+ file.join(blobpath,vv,bname), -- search
+ resolvers.concatinators[hash.type](blobpath,vv,bname) -- result
+ }
+ end
+ end
+ end
+ end
+ elseif trace_locating then
+ logs.report("fileio","no match in '%s' (%s)",blobpath,bname)
+ end
+ end
+ end
+ if #filelist > 0 then
+ return filelist
+ else
+ return nil
+ end
+end
+
+function resolvers.suffix_of_format(str)
+ if suffixes[str] then
+ return suffixes[str][1]
+ else
+ return ""
+ end
+end
+
+function resolvers.suffixes_of_format(str)
+ if suffixes[str] then
+ return suffixes[str]
+ else
+ return {}
+ end
+end
+
+function resolvers.register_in_trees(name)
+ if not find(name,"^%.") then
+ instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+ end
+end
+
+-- split the next one up for readability (bu this module needs a cleanup anyway)
+
+local function can_be_dir(name) -- can become local
+ local fakepaths = instance.fakepaths
+ if not fakepaths[name] then
+ if lfs.isdir(name) then
+ fakepaths[name] = 1 -- directory
+ else
+ fakepaths[name] = 2 -- no directory
+ end
+ end
+ return (fakepaths[name] == 1)
+end
+
+local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc)
+ local result = collected or { }
+ local stamp = nil
+ filename = file.collapse_path(filename)
+ -- speed up / beware: format problem
+ if instance.remember then
+ stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format
+ if instance.found[stamp] then
+ if trace_locating then
+ logs.report("fileio","remembering file '%s'",filename)
+ end
+ return instance.found[stamp]
+ end
+ end
+ if not dangerous[instance.format or "?"] then
+ if resolvers.isreadable.file(filename) then
+ if trace_detail then
+ logs.report("fileio","file '%s' found directly",filename)
+ end
+ instance.found[stamp] = { filename }
+ return { filename }
+ end
+ end
+ if find(filename,'%*') then
+ if trace_locating then
+ logs.report("fileio","checking wildcard '%s'", filename)
+ end
+ result = resolvers.find_wildcard_files(filename)
+ elseif file.is_qualified_path(filename) then
+ if resolvers.isreadable.file(filename) then
+ if trace_locating then
+ logs.report("fileio","qualified name '%s'", filename)
+ end
+ result = { filename }
+ else
+ local forcedname, ok, suffix = "", false, file.extname(filename)
+ if suffix == "" then -- why
+ if instance.format == "" then
+ forcedname = filename .. ".tex"
+ if resolvers.isreadable.file(forcedname) then
+ if trace_locating then
+ logs.report("fileio","no suffix, forcing standard filetype 'tex'")
+ end
+ result, ok = { forcedname }, true
+ end
+ else
+ local suffixes = resolvers.suffixes_of_format(instance.format)
+ for _, s in next, suffixes do
+ forcedname = filename .. "." .. s
+ if resolvers.isreadable.file(forcedname) then
+ if trace_locating then
+ logs.report("fileio","no suffix, forcing format filetype '%s'", s)
+ end
+ result, ok = { forcedname }, true
+ break
+ end
+ end
+ end
+ end
+ if not ok and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = file.basename(filename)
+ local pattern = gsub(filename .. "$","([%.%-])","%%%1")
+ local savedformat = instance.format
+ local format = savedformat or ""
+ if format == "" then
+ instance.format = resolvers.format_of_suffix(suffix)
+ end
+ if not format then
+ instance.format = "othertextfiles" -- kind of everything, maybe texinput is better
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename)
+ if #result == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered)
+ end
+ end
+ resolvers.format = savedformat
+ --
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1], ok = rr, true
+ end
+ end
+ end
+ -- a real wildcard:
+ --
+ -- if not ok then
+ -- local filelist = collect_files({basename})
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- end
+ end
+ if not ok and trace_locating then
+ logs.report("fileio","qualified name '%s'", filename)
+ end
+ end
+ else
+ -- search spec
+ local filetype, extra, done, wantedfiles, ext = '', nil, false, { }, file.extname(filename)
+ if ext == "" then
+ if not instance.force_suffixes then
+ wantedfiles[#wantedfiles+1] = filename
+ end
+ else
+ wantedfiles[#wantedfiles+1] = filename
+ end
+ if instance.format == "" then
+ if ext == "" then
+ local forcedname = filename .. '.tex'
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.format_of_suffix(forcedname)
+ if trace_locating then
+ logs.report("fileio","forcing filetype '%s'",filetype)
+ end
+ else
+ filetype = resolvers.format_of_suffix(filename)
+ if trace_locating then
+ logs.report("fileio","using suffix based filetype '%s'",filetype)
+ end
+ end
+ else
+ if ext == "" then
+ local suffixes = resolvers.suffixes_of_format(instance.format)
+ for _, s in next, suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. s
+ end
+ end
+ filetype = instance.format
+ if trace_locating then
+ logs.report("fileio","using given filetype '%s'",filetype)
+ end
+ end
+ local typespec = resolvers.variable_of_format(filetype)
+ local pathlist = resolvers.expanded_path_list(typespec)
+ if not pathlist or #pathlist == 0 then
+ -- no pathlist, access check only / todo == wildcard
+ if trace_detail then
+ logs.report("fileio","checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and resolvers.isreadable.file(fname) then
+ filename, done = fname, true
+ result[#result+1] = file.join('.',fname)
+ break
+ end
+ end
+ -- this is actually 'other text files' or 'any' or 'whatever'
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ filename = fl[3]
+ result[#result+1] = filename
+ done = true
+ end
+ else
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = file.dirname(filelist[i][2]) .. "/"
+ end
+ end
+ if trace_detail then
+ logs.report("fileio","checking filename '%s'",filename)
+ end
+ -- a bit messy ... esp the doscan setting here
+ local doscan
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ if find(path,"^!!") then doscan = false else doscan = true end
+ local pathname = gsub(path,"^!+", '')
+ done = false
+ -- using file list
+ if filelist then
+ local expression
+ -- compare list entries with permitted pattern -- /xx /xx//
+ if not find(pathname,"/$") then
+ expression = pathname .. "/"
+ else
+ expression = pathname
+ end
+ expression = gsub(expression,"([%-%.])","%%%1") -- this also influences
+ expression = gsub(expression,"//+$", '/.*') -- later usage of pathname
+ expression = gsub(expression,"//", '/.-/') -- not ok for /// but harmless
+ expression = "^" .. expression .. "$"
+ if trace_detail then
+ logs.report("fileio","using pattern '%s' for path '%s'",expression,pathname)
+ end
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ --- todo, test for readable
+ result[#result+1] = fl[3]
+ resolvers.register_in_trees(f) -- for tracing used files
+ done = true
+ if instance.allresults then
+ if trace_detail then
+ logs.report("fileio","match in hash for file '%s' on path '%s', continue scanning",f,d)
+ end
+ else
+ if trace_detail then
+ logs.report("fileio","match in hash for file '%s' on path '%s', quit scanning",f,d)
+ end
+ break
+ end
+ elseif trace_detail then
+ logs.report("fileio","no match in hash for file '%s' on path '%s'",f,d)
+ end
+ end
+ end
+ if not done and doscan then
+ -- check if on disk / unchecked / does not work at all / also zips
+ if resolvers.splitmethod(pathname).scheme == 'file' then -- ?
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ local ppname = gsub(pname,"/+$","")
+ if can_be_dir(ppname) then
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = file.join(ppname,w)
+ if resolvers.isreadable.file(fname) then
+ if trace_detail then
+ logs.report("fileio","found '%s' by scanning",fname)
+ end
+ result[#result+1] = fname
+ done = true
+ if not instance.allresults then break end
+ end
+ end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
+ end
+ end
+ end
+ end
+ if not done and doscan then
+ -- todo: slow path scanning
+ end
+ if done and not instance.allresults then break end
+ end
+ end
+ end
+ for k=1,#result do
+ result[k] = file.collapse_path(result[k])
+ end
+ if instance.remember then
+ instance.found[stamp] = result
+ end
+ return result
+end
+
+if not resolvers.concatinators then resolvers.concatinators = { } end
+
+resolvers.concatinators.tex = file.join
+resolvers.concatinators.file = resolvers.concatinators.tex
+
+function resolvers.find_files(filename,filetype,mustexist)
+ if type(mustexist) == boolean then
+ -- all set
+ elseif type(filetype) == 'boolean' then
+ filetype, mustexist = nil, false
+ elseif type(filetype) ~= 'string' then
+ filetype, mustexist = nil, false
+ end
+ instance.format = filetype or ''
+ local result = collect_instance_files(filename)
+ if #result == 0 then
+ local lowered = lower(filename)
+ if filename ~= lowered then
+ return collect_instance_files(lowered)
+ end
+ end
+ instance.format = ''
+ return result
+end
+
+function resolvers.find_file(filename,filetype,mustexist)
+ return (resolvers.find_files(filename,filetype,mustexist)[1] or "")
+end
+
+function resolvers.find_given_files(filename)
+ local bname, result = file.basename(filename), { }
+ local hashes = instance.hashes
+ for k=1,#hashes do
+ local hash = hashes[k]
+ local files = instance.files[hash.tag] or { }
+ local blist = files[bname]
+ if not blist then
+ local rname = "remap:"..bname
+ blist = files[rname]
+ if blist then
+ bname = files[rname]
+ blist = files[bname]
+ end
+ end
+ if blist then
+ if type(blist) == 'string' then
+ result[#result+1] = resolvers.concatinators[hash.type](hash.tag,blist,bname) or ""
+ if not instance.allresults then break end
+ else
+ for kk=1,#blist do
+ local vv = blist[kk]
+ result[#result+1] = resolvers.concatinators[hash.type](hash.tag,vv,bname) or ""
+ if not instance.allresults then break end
+ end
+ end
+ end
+ end
+ return result
+end
+
+function resolvers.find_given_file(filename)
+ return (resolvers.find_given_files(filename)[1] or "")
+end
+
+local function doit(path,blist,bname,tag,kind,result,allresults)
+ local done = false
+ if blist and kind then
+ if type(blist) == 'string' then
+ -- make function and share code
+ if find(lower(blist),path) then
+ result[#result+1] = resolvers.concatinators[kind](tag,blist,bname) or ""
+ done = true
+ end
+ else
+ for kk=1,#blist do
+ local vv = blist[kk]
+ if find(lower(vv),path) then
+ result[#result+1] = resolvers.concatinators[kind](tag,vv,bname) or ""
+ done = true
+ if not allresults then break end
+ end
+ end
+ end
+ end
+ return done
+end
+
+function resolvers.find_wildcard_files(filename) -- todo: remap:
+ local result = { }
+ local bname, dname = file.basename(filename), file.dirname(filename)
+ local path = gsub(dname,"^*/","")
+ path = gsub(path,"*",".*")
+ path = gsub(path,"-","%%-")
+ if dname == "" then
+ path = ".*"
+ end
+ local name = bname
+ name = gsub(name,"*",".*")
+ name = gsub(name,"-","%%-")
+ path = lower(path)
+ name = lower(name)
+ local files, allresults, done = instance.files, instance.allresults, false
+ if find(name,"%*") then
+ local hashes = instance.hashes
+ for k=1,#hashes do
+ local hash = hashes[k]
+ local tag, kind = hash.tag, hash.type
+ for kk, hh in next, files[hash.tag] do
+ if not find(kk,"^remap:") then
+ if find(lower(kk),name) then
+ if doit(path,hh,kk,tag,kind,result,allresults) then done = true end
+ if done and not allresults then break end
+ end
+ end
+ end
+ end
+ else
+ local hashes = instance.hashes
+ for k=1,#hashes do
+ local hash = hashes[k]
+ local tag, kind = hash.tag, hash.type
+ if doit(path,files[tag][bname],bname,tag,kind,result,allresults) then done = true end
+ if done and not allresults then break end
+ end
+ end
+ -- we can consider also searching the paths not in the database, but then
+ -- we end up with a messy search (all // in all path specs)
+ return result
+end
+
+function resolvers.find_wildcard_file(filename)
+ return (resolvers.find_wildcard_files(filename)[1] or "")
+end
+
+-- main user functions
+
+function resolvers.automount()
+ -- implemented later
+end
+
+function resolvers.load(option)
+ statistics.starttiming(instance)
+ resolvers.resetconfig()
+ resolvers.identify_cnf()
+ resolvers.load_lua() -- will become the new method
+ resolvers.expand_variables()
+ resolvers.load_cnf() -- will be skipped when we have a lua file
+ resolvers.expand_variables()
+ if option ~= "nofiles" then
+ resolvers.load_hash()
+ resolvers.automount()
+ end
+ statistics.stoptiming(instance)
+end
+
+function resolvers.for_files(command, files, filetype, mustexist)
+ if files and #files > 0 then
+ local function report(str)
+ if trace_locating then
+ logs.report("fileio",str) -- has already verbose
+ else
+ print(str)
+ end
+ end
+ if trace_locating then
+ report('') -- ?
+ end
+ for f=1,#files do
+ local file = files[f]
+ local result = command(file,filetype,mustexist)
+ if type(result) == 'string' then
+ report(result)
+ else
+ for i=1,#result do
+ report(result[i]) -- could be unpack
+ end
+ end
+ end
+ end
+end
+
+-- strtab
+
+resolvers.var_value = resolvers.variable -- output the value of variable $STRING.
+resolvers.expand_var = resolvers.expansion -- output variable expansion of STRING.
+
+function resolvers.show_path(str) -- output search path for file type NAME
+ return file.join_path(resolvers.expanded_path_list(resolvers.format_of_var(str)))
+end
+
+-- resolvers.find_file(filename)
+-- resolvers.find_file(filename, filetype, mustexist)
+-- resolvers.find_file(filename, mustexist)
+-- resolvers.find_file(filename, filetype)
+
+function resolvers.register_file(files, name, path)
+ if files[name] then
+ if type(files[name]) == 'string' then
+ files[name] = { files[name], path }
+ else
+ files[name] = path
+ end
+ else
+ files[name] = path
+ end
+end
+
+function resolvers.splitmethod(filename)
+ if not filename then
+ return { } -- safeguard
+ elseif type(filename) == "table" then
+ return filename -- already split
+ elseif not find(filename,"://") then
+ return { scheme="file", path = filename, original=filename } -- quick hack
+ else
+ return url.hashed(filename)
+ end
+end
+
+function table.sequenced(t,sep) -- temp here
+ local s = { }
+ for k, v in next, t do -- indexed?
+ s[#s+1] = k .. "=" .. tostring(v)
+ end
+ return concat(s, sep or " | ")
+end
+
+function resolvers.methodhandler(what, filename, filetype) -- ...
+ filename = file.collapse_path(filename)
+ local specification = (type(filename) == "string" and resolvers.splitmethod(filename)) or filename -- no or { }, let it bomb
+ local scheme = specification.scheme
+ if resolvers[what][scheme] then
+ if trace_locating then
+ logs.report("fileio","handler '%s' -> '%s' -> '%s'",specification.original,what,table.sequenced(specification))
+ end
+ return resolvers[what][scheme](filename,filetype) -- todo: specification
+ else
+ return resolvers[what].tex(filename,filetype) -- todo: specification
+ end
+end
+
+function resolvers.clean_path(str)
+ if str then
+ str = gsub(str,"\\","/")
+ str = gsub(str,"^!+","")
+ str = gsub(str,"^~",resolvers.homedir)
+ return str
+ else
+ return nil
+ end
+end
+
+function resolvers.do_with_path(name,func)
+ local pathlist = resolvers.expanded_path_list(name)
+ for i=1,#pathlist do
+ func("^"..resolvers.clean_path(pathlist[i]))
+ end
+end
+
+function resolvers.do_with_var(name,func)
+ func(expanded_var(name))
+end
+
+function resolvers.with_files(pattern,handle)
+ local hashes = instance.hashes
+ for i=1,#hashes do
+ local hash = hashes[i]
+ local blobpath = hash.tag
+ local blobtype = hash.type
+ if blobpath then
+ local files = instance.files[blobpath]
+ if files then
+ for k,v in next, files do
+ if find(k,"^remap:") then
+ k = files[k]
+ v = files[k] -- chained
+ end
+ if find(k,pattern) then
+ if type(v) == "string" then
+ handle(blobtype,blobpath,v,k)
+ else
+ for _,vv in next, v do -- indexed
+ handle(blobtype,blobpath,vv,k)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function resolvers.locate_format(name)
+ local barename, fmtname = gsub(name,"%.%a+$",""), ""
+ if resolvers.usecache then
+ local path = file.join(caches.setpath("formats")) -- maybe platform
+ fmtname = file.join(path,barename..".fmt") or ""
+ end
+ if fmtname == "" then
+ fmtname = resolvers.find_files(barename..".fmt")[1] or ""
+ end
+ fmtname = resolvers.clean_path(fmtname)
+ if fmtname ~= "" then
+ local barename = file.removesuffix(fmtname)
+ local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
+ if lfs.isfile(luiname) then
+ return barename, luiname
+ elseif lfs.isfile(lucname) then
+ return barename, lucname
+ elseif lfs.isfile(luaname) then
+ return barename, luaname
+ end
+ end
+ return nil, nil
+end
+
+function resolvers.boolean_variable(str,default)
+ local b = resolvers.expansion(str)
+ if b == "" then
+ return default
+ else
+ b = toboolean(b)
+ return (b == nil and default) or b
+ end
+end
+
+texconfig.kpse_init = false
+
+kpse = { original = kpse } setmetatable(kpse, { __index = function(k,v) return resolvers[v] end } )
+
+-- for a while
+
+input = resolvers
diff --git a/tex/context/base/data-sch.lua b/tex/context/base/data-sch.lua
new file mode 100644
index 000000000..e68b6cd01
--- /dev/null
+++ b/tex/context/base/data-sch.lua
@@ -0,0 +1,142 @@
+if not modules then modules = { } end modules ['data-sch'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local http = require("socket.http")
+local ltn12 = require("ltn12")
+
+local gsub, concat, format = string.gsub, table.concat, string.format
+
+local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end)
+
+schemes = schemes or { }
+
+schemes.cached = { }
+schemes.cachepath = caches.definepath("schemes")
+schemes.threshold = 24 * 60 * 60
+
+directives.register("schemes.threshold", function(v) schemes.threshold = tonumber(v) or schemes.threshold end)
+
+local cached, loaded, reused = schemes.cached, { }, { }
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+
+function schemes.curl(name,cachename)
+ local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name -- no protocol .. "://"
+ os.spawn(command)
+end
+
+function schemes.fetch(protocol,name,handler)
+ local cachename = schemes.cachepath() .. "/" .. gsub(name,"[^%a%d%.]+","-")
+ cachename = gsub(cachename,"[\\]", "/") -- cleanup
+ if not cached[name] then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > schemes.threshold) then
+ cached[name] = cachename
+ if handler then
+ if trace_schemes then
+ logs.report("schemes","fetching '%s', protocol '%s', method 'built-in'",name,protocol)
+ end
+ io.flush()
+ handler(protocol,name,cachename)
+ else
+ if trace_schemes then
+ logs.report("schemes","fetching '%s', protocol '%s', method 'curl'",name,protocol)
+ end
+ io.flush()
+ schemes.curl(name,cachename)
+ end
+ end
+ if io.exists(cachename) then
+ cached[name] = cachename
+ if trace_schemes then
+ logs.report("schemes","using cached '%s', protocol '%s', cachename '%s'",name,protocol,cachename)
+ end
+ else
+ cached[name] = ""
+ if trace_schemes then
+ logs.report("schemes","using missing '%s', protocol '%s'",name,protocol)
+ end
+ end
+ loaded[protocol] = loaded[protocol] + 1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ logs.report("schemes","reusing '%s', protocol '%s'",name,protocol)
+ end
+ reused[protocol] = reused[protocol] + 1
+ end
+ return cached[name]
+end
+
+function finders.schemes(protocol,filename,handler)
+ local foundname = schemes.fetch(protocol,filename,handler)
+ return finders.generic(protocol,foundname,filetype)
+end
+
+function openers.schemes(protocol,filename)
+ return openers.generic(protocol,filename)
+end
+
+function loaders.schemes(protocol,filename)
+ return loaders.generic(protocol,filename)
+end
+
+-- could be metatable
+
+function schemes.install(protocol,handler)
+ loaded [protocol] = 0
+ reused [protocol] = 0
+ finders[protocol] = function (filename,filetype) return finders.schemes(protocol,filename,handler) end
+ openers[protocol] = function (filename) return openers.schemes(protocol,filename) end
+ loaders[protocol] = function (filename) return loaders.schemes(protocol,filename) end
+end
+
+local function http_handler(protocol,name,cachename)
+ local tempname = cachename .. ".tmp"
+ local f = io.open(tempname,"wb")
+ local status, message = http.request {
+ url = name,
+ sink = ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+end
+
+schemes.install('http',http_handler)
+schemes.install('https')
+schemes.install('ftp')
+
+statistics.register("scheme handling time", function()
+ local l, r = { }, { }
+ for k, v in table.sortedhash(loaded) do
+ if v > 0 then
+ l[#l+1] = k .. ":" .. v
+ end
+ end
+ for k, v in table.sortedhash(reused) do
+ if v > 0 then
+ r[#r+1] = k .. ":" .. v
+ end
+ end
+ local n = #l + #r
+ if n > 0 then
+ l = (#l > 0 and concat(l)) or "none"
+ r = (#r > 0 and concat(r)) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes), n, schemes.threshold, l, r)
+ else
+ return nil
+ end
+end)
+
+--~ trace_schemes = true
+--~ print(schemes.fetch("http","http://www.pragma-ade.com/show-man.pdf",http_handler))
diff --git a/tex/context/base/data-tex.lua b/tex/context/base/data-tex.lua
new file mode 100644
index 000000000..c9fa3625a
--- /dev/null
+++ b/tex/context/base/data-tex.lua
@@ -0,0 +1,226 @@
+if not modules then modules = { } end modules ['data-tex'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- special functions that deal with io
+
+local format, lower = string.format, string.lower
+local unpack = unpack or table.unpack
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local texiowrite_nl = (texio and texio.write_nl) or print
+local texiowrite = (texio and texio.write) or print
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+
+function finders.generic(tag,filename,filetype)
+ local foundname = resolvers.find_file(filename,filetype)
+ if foundname and foundname ~= "" then
+ if trace_locating then
+ logs.report("fileio","%s finder: file '%s' found",tag,filename)
+ end
+ return foundname
+ else
+ if trace_locating then
+ logs.report("fileio","%s finder: unknown file '%s'",tag,filename)
+ end
+ return unpack(finders.notfound)
+ end
+end
+
+--~ local lpegmatch = lpeg.match
+--~ local getlines = lpeg.Ct(lpeg.patterns.textline)
+
+local input_translator, utf_translator, user_translator = nil, nil, nil
+
+function resolvers.install_text_filter(name,func)
+ if name == "input" then input_translator = func
+ elseif name == "utf" then utf_translator = func
+ elseif name == "user" then user_translator = func end
+end
+
+function openers.text_opener(filename,file_handle,tag)
+ local u = unicode.utftype(file_handle)
+ local t = { }
+ if u > 0 then
+ if trace_locating then
+ logs.report("fileio","%s opener, file '%s' opened using method '%s'",tag,filename,unicode.utfname[u])
+ end
+ local l
+ if u > 2 then
+ l = unicode.utf32_to_utf8(file_handle:read("*a"),u==4)
+ else
+ l = unicode.utf16_to_utf8(file_handle:read("*a"),u==2)
+ end
+ file_handle:close()
+ t = {
+ utftype = u, -- may go away
+ lines = l,
+ current = 0, -- line number, not really needed
+ handle = nil,
+ noflines = #l,
+ close = function()
+ if trace_locating then
+ logs.report("fileio","%s closer, file '%s' closed",tag,filename)
+ end
+ logs.show_close(filename)
+ t = nil
+ end,
+ reader = function(self)
+ self = self or t
+ local current, lines = self.current, self.lines
+ if current >= #lines then
+ return nil
+ else
+ current = current + 1
+ self.current = current
+ local line = lines[current]
+ if not line then
+ return nil
+ elseif line == "" then
+ return ""
+ else
+ if input_translator then
+ line = input_translator(line)
+ end
+ if utf_translator then
+ line = utf_translator(line)
+ end
+ if user_translator then
+ line = user_translator(line)
+ end
+ return line
+ end
+ end
+ end
+ }
+ else
+ if trace_locating then
+ logs.report("fileio","%s opener, file '%s' opened",tag,filename)
+ end
+ -- todo: file;name -> freeze / eerste regel scannen -> freeze
+ --~ local data = lpegmatch(getlines,file_handle:read("*a"))
+ --~ local n = 0
+ t = {
+ reader = function() -- self
+ local line = file_handle:read()
+ --~ n = n + 1
+ --~ local line = data[n]
+ --~ print(line)
+ if not line then
+ return nil
+ elseif line == "" then
+ return ""
+ else
+ if input_translator then
+ line = input_translator(line)
+ end
+ if utf_translator then
+ line = utf_translator(line)
+ end
+ if user_translator then
+ line = user_translator(line)
+ end
+ return line
+ end
+ end,
+ close = function()
+ if trace_locating then
+ logs.report("fileio","%s closer, file '%s' closed",tag,filename)
+ end
+ logs.show_close(filename)
+ file_handle:close()
+ t = nil
+ collectgarbage("step") -- saves some memory
+ end,
+ handle = function()
+ return file_handle
+ end,
+ noflines = function()
+ t.noflines = io.noflines(file_handle)
+ return t.noflines
+ end
+ }
+ end
+ return t
+end
+
+function openers.generic(tag,filename)
+ if filename and filename ~= "" then
+ local f = io.open(filename,"r")
+ if f then
+ logs.show_open(filename) -- todo
+ if trace_locating then
+ logs.report("fileio","%s opener, file '%s' opened",tag,filename)
+ end
+ return openers.text_opener(filename,f,tag)
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","%s opener, file '%s' not found",tag,filename)
+ end
+ return unpack(openers.notfound)
+end
+
+function loaders.generic(tag,filename)
+ if filename and filename ~= "" then
+ local f = io.open(filename,"rb")
+ if f then
+ logs.show_load(filename)
+ if trace_locating then
+ logs.report("fileio","%s loader, file '%s' loaded",tag,filename)
+ end
+ local s = f:read("*a")
+ if garbagecollector and garbagecollector.check then garbagecollector.check(#s) end
+ f:close()
+ if s then
+ return true, s, #s
+ end
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","%s loader, file '%s' not found",tag,filename)
+ end
+ return unpack(loaders.notfound)
+end
+
+function finders.tex(filename,filetype)
+ return finders.generic('tex',filename,filetype)
+end
+
+function openers.tex(filename)
+ return openers.generic('tex',filename)
+end
+
+function loaders.tex(filename)
+ return loaders.generic('tex',filename)
+end
+
+function resolvers.findtexfile(filename, filetype)
+ return resolvers.methodhandler('finders',filename, filetype)
+end
+
+function resolvers.opentexfile(filename)
+ return resolvers.methodhandler('openers',filename)
+end
+
+function resolvers.openfile(filename)
+ local fullname = resolvers.findtexfile(filename)
+ if fullname and (fullname ~= "") then
+ return resolvers.opentexfile(fullname)
+ else
+ return nil
+ end
+end
+
+function resolvers.texdatablob(filename, filetype)
+ local ok, data, size = resolvers.loadbinfile(filename, filetype)
+ return data or ""
+end
+
+resolvers.loadtexfile = resolvers.texdatablob
diff --git a/tex/context/base/data-tmf.lua b/tex/context/base/data-tmf.lua
new file mode 100644
index 000000000..7421eacfc
--- /dev/null
+++ b/tex/context/base/data-tmf.lua
@@ -0,0 +1,75 @@
+if not modules then modules = { } end modules ['data-tmf'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local find, gsub, match = string.find, string.gsub, string.match
+local getenv, setenv = os.getenv, os.setenv
+
+-- loads *.tmf files in minimal tree roots (to be optimized and documented)
+
+function resolvers.check_environment(tree)
+ logs.simpleline()
+ setenv('TMP', getenv('TMP') or getenv('TEMP') or getenv('TMPDIR') or getenv('HOME'))
+ setenv('TEXOS', getenv('TEXOS') or ("texmf-" .. os.platform))
+ setenv('TEXPATH', gsub(tree or "tex","\/+$",''))
+ setenv('TEXMFOS', getenv('TEXPATH') .. "/" .. getenv('TEXOS'))
+ logs.simpleline()
+ logs.simple("preset : TEXPATH => %s", getenv('TEXPATH'))
+ logs.simple("preset : TEXOS => %s", getenv('TEXOS'))
+ logs.simple("preset : TEXMFOS => %s", getenv('TEXMFOS'))
+ logs.simple("preset : TMP => %s", getenv('TMP'))
+ logs.simple('')
+end
+
+function resolvers.load_environment(name) -- todo: key=value as well as lua
+ local f = io.open(name)
+ if f then
+ for line in f:lines() do
+ if find(line,"^[%%%#]") then
+ -- skip comment
+ else
+ local key, how, value = match(line,"^(.-)%s*([<=>%?]+)%s*(.*)%s*$")
+ if how then
+ value = gsub(value,"%%(.-)%%", function(v) return getenv(v) or "" end)
+ if how == "=" or how == "<<" then
+ setenv(key,value)
+ elseif how == "?" or how == "??" then
+ setenv(key,getenv(key) or value)
+ elseif how == "<" or how == "+=" then
+ if getenv(key) then
+ setenv(key,getenv(key) .. io.fileseparator .. value)
+ else
+ setenv(key,value)
+ end
+ elseif how == ">" or how == "=+" then
+ if getenv(key) then
+ setenv(key,value .. io.pathseparator .. getenv(key))
+ else
+ setenv(key,value)
+ end
+ end
+ end
+ end
+ end
+ f:close()
+ end
+end
+
+function resolvers.load_tree(tree)
+ if tree and tree ~= "" then
+ local setuptex = 'setuptex.tmf'
+ if lfs.attributes(tree, "mode") == "directory" then -- check if not nil
+ setuptex = tree .. "/" .. setuptex
+ else
+ setuptex = tree
+ end
+ if io.exists(setuptex) then
+ resolvers.check_environment(tree)
+ resolvers.load_environment(setuptex)
+ end
+ end
+end
diff --git a/tex/context/base/data-tmp.lua b/tex/context/base/data-tmp.lua
new file mode 100644
index 000000000..25f5b975c
--- /dev/null
+++ b/tex/context/base/data-tmp.lua
@@ -0,0 +1,178 @@
+if not modules then modules = { } end modules ['data-tmp'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
This module deals with caching data. It sets up the paths and
+implements loaders and savers for tables. Best is to set the
+following variable. When not set, the usual paths will be
+checked. Personally I prefer the (users) temporary path.
Currently we do no locking when we write files. This is no real
+problem because most caching involves fonts and the chance of them
+being written at the same time is small. We also need to extend
+luatools with a recache feature.
+--ldx]]--
+
+local format, lower, gsub = string.format, string.lower, string.gsub
+
+local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end) -- not used yet
+
+caches = caches or { }
+
+caches.path = caches.path or nil
+caches.base = caches.base or "luatex-cache"
+caches.more = caches.more or "context"
+caches.direct = false -- true is faster but may need huge amounts of memory
+caches.tree = false
+caches.paths = caches.paths or nil
+caches.force = false
+caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
+
+function caches.temp()
+ local cachepath = nil
+ local function check(list,isenv)
+ if not cachepath then
+ for k=1,#list do
+ local v = list[k]
+ cachepath = (isenv and (os.env[v] or "")) or v or ""
+ if cachepath == "" then
+ -- next
+ else
+ cachepath = resolvers.clean_path(cachepath)
+ if lfs.isdir(cachepath) and file.iswritable(cachepath) then -- lfs.attributes(cachepath,"mode") == "directory"
+ break
+ elseif caches.force or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
+ dir.mkdirs(cachepath)
+ if lfs.isdir(cachepath) and file.iswritable(cachepath) then
+ break
+ end
+ end
+ end
+ cachepath = nil
+ end
+ end
+ end
+ check(resolvers.clean_path_list("TEXMFCACHE") or { })
+ check(caches.defaults,true)
+ if not cachepath then
+ print("\nfatal error: there is no valid (writable) cache path defined\n")
+ os.exit()
+ elseif not lfs.isdir(cachepath) then -- lfs.attributes(cachepath,"mode") ~= "directory"
+ print(format("\nfatal error: cache path %s is not a directory\n",cachepath))
+ os.exit()
+ end
+ cachepath = file.collapse_path(cachepath)
+ function caches.temp()
+ return cachepath
+ end
+ return cachepath
+end
+
+function caches.configpath()
+ return table.concat(resolvers.instance.cnffiles,";")
+end
+
+function caches.hashed(tree)
+ return md5.hex(gsub(lower(tree),"[\\\/]+","/"))
+end
+
+function caches.treehash()
+ local tree = caches.configpath()
+ if not tree or tree == "" then
+ return false
+ else
+ return caches.hashed(tree)
+ end
+end
+
+function caches.setpath(...)
+ if not caches.path then
+ if not caches.path then
+ caches.path = caches.temp()
+ end
+ caches.path = resolvers.clean_path(caches.path) -- to be sure
+ caches.tree = caches.tree or caches.treehash()
+ if caches.tree then
+ caches.path = dir.mkdirs(caches.path,caches.base,caches.more,caches.tree)
+ else
+ caches.path = dir.mkdirs(caches.path,caches.base,caches.more)
+ end
+ end
+ if not caches.path then
+ caches.path = '.'
+ end
+ caches.path = resolvers.clean_path(caches.path)
+ local dirs = { ... }
+ if #dirs > 0 then
+ local pth = dir.mkdirs(caches.path,...)
+ return pth
+ end
+ caches.path = dir.expand_name(caches.path)
+ return caches.path
+end
+
+function caches.definepath(category,subcategory)
+ return function()
+ return caches.setpath(category,subcategory)
+ end
+end
+
+function caches.setluanames(path,name)
+ return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
+end
+
+function caches.loaddata(path,name)
+ local tmaname, tmcname = caches.setluanames(path,name)
+ local loader = loadfile(tmcname) or loadfile(tmaname)
+ if loader then
+ loader = loader()
+ collectgarbage("step")
+ return loader
+ else
+ return false
+ end
+end
+
+--~ function caches.loaddata(path,name)
+--~ local tmaname, tmcname = caches.setluanames(path,name)
+--~ return dofile(tmcname) or dofile(tmaname)
+--~ end
+
+function caches.iswritable(filepath,filename)
+ local tmaname, tmcname = caches.setluanames(filepath,filename)
+ return file.iswritable(tmaname)
+end
+
+function caches.savedata(filepath,filename,data,raw)
+ local tmaname, tmcname = caches.setluanames(filepath,filename)
+ local reduce, simplify = true, true
+ if raw then
+ reduce, simplify = false, false
+ end
+ data.cache_uuid = os.uuid()
+ if caches.direct then
+ file.savedata(tmaname, table.serialize(data,'return',false,true,false)) -- no hex
+ else
+ table.tofile(tmaname, data,'return',false,true,false) -- maybe not the last true
+ end
+ local cleanup = resolvers.boolean_variable("PURGECACHE", false)
+ local strip = resolvers.boolean_variable("LUACSTRIP", true)
+ utils.lua.compile(tmaname, tmcname, cleanup, strip)
+end
+
+-- here we use the cache for format loading (texconfig.[formatname|jobname])
+
+--~ if tex and texconfig and texconfig.formatname and texconfig.formatname == "" then
+if tex and texconfig and (not texconfig.formatname or texconfig.formatname == "") and input and resolvers.instance then
+ if not texconfig.luaname then texconfig.luaname = "cont-en.lua" end -- or luc
+ texconfig.formatname = caches.setpath("formats") .. "/" .. gsub(texconfig.luaname,"%.lu.$",".fmt")
+end
diff --git a/tex/context/base/data-tre.lua b/tex/context/base/data-tre.lua
new file mode 100644
index 000000000..d5ca258e4
--- /dev/null
+++ b/tex/context/base/data-tre.lua
@@ -0,0 +1,47 @@
+if not modules then modules = { } end modules ['data-tre'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- \input tree://oeps1/**/oeps.tex
+
+local find, gsub = string.find, string.gsub
+local unpack = unpack or table.unpack
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+
+local done, found = { }, { }
+
+function finders.tree(specification,filetype)
+ local fnd = found[specification]
+ if not fnd then
+ local spec = resolvers.splitmethod(specification).path or ""
+ if spec ~= "" then
+ local path, name = file.dirname(spec), file.basename(spec)
+ if path == "" then path = "." end
+ local hash = done[path]
+ if not hash then
+ local pattern = path .. "/*" -- we will use the proper splitter
+ hash = dir.glob(pattern)
+ done[path] = hash
+ end
+ local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$"
+ for k=1,#hash do
+ local v = hash[k]
+ if find(v,pattern) then
+ found[specification] = v
+ return v
+ end
+ end
+ end
+ fnd = unpack(finders.notfound)
+ found[specification] = fnd
+ end
+ return fnd
+end
+
+openers.tree = openers.generic
+loaders.tree = loaders.generic
diff --git a/tex/context/base/data-use.lua b/tex/context/base/data-use.lua
new file mode 100644
index 000000000..5ecd7805f
--- /dev/null
+++ b/tex/context/base/data-use.lua
@@ -0,0 +1,129 @@
+if not modules then modules = { } end modules ['data-use'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, lower, gsub, find = string.format, string.lower, string.gsub, string.find
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+-- since we want to use the cache instead of the tree, we will now
+-- reimplement the saver.
+
+local save_data = resolvers.save_data
+local load_data = resolvers.load_data
+
+resolvers.cachepath = nil -- public, for tracing
+resolvers.usecache = true -- public, for tracing
+
+function resolvers.save_data(dataname)
+ save_data(dataname, function(cachename,dataname)
+ resolvers.usecache = not toboolean(resolvers.expansion("CACHEINTDS") or "false",true)
+ if resolvers.usecache then
+ resolvers.cachepath = resolvers.cachepath or caches.definepath("trees")
+ return file.join(resolvers.cachepath(),caches.hashed(cachename))
+ else
+ return file.join(cachename,dataname)
+ end
+ end)
+end
+
+function resolvers.load_data(pathname,dataname,filename)
+ load_data(pathname,dataname,filename,function(dataname,filename)
+ resolvers.usecache = not toboolean(resolvers.expansion("CACHEINTDS") or "false",true)
+ if resolvers.usecache then
+ resolvers.cachepath = resolvers.cachepath or caches.definepath("trees")
+ return file.join(resolvers.cachepath(),caches.hashed(pathname))
+ else
+ if not filename or (filename == "") then
+ filename = dataname
+ end
+ return file.join(pathname,filename)
+ end
+ end)
+end
+
+-- we will make a better format, maybe something xml or just text or lua
+
+resolvers.automounted = resolvers.automounted or { }
+
+function resolvers.automount(usecache)
+ local mountpaths = resolvers.clean_path_list(resolvers.expansion('TEXMFMOUNT'))
+ if (not mountpaths or #mountpaths == 0) and usecache then
+ mountpaths = { caches.setpath("mount") }
+ end
+ if mountpaths and #mountpaths > 0 then
+ statistics.starttiming(resolvers.instance)
+ for k=1,#mountpaths do
+ local root = mountpaths[k]
+ local f = io.open(root.."/url.tmi")
+ if f then
+ for line in f:lines() do
+ if line then
+ if find(line,"^[%%#%-]") then -- or %W
+ -- skip
+ elseif find(line,"^zip://") then
+ if trace_locating then
+ logs.report("fileio","mounting %s",line)
+ end
+ table.insert(resolvers.automounted,line)
+ resolvers.usezipfile(line)
+ end
+ end
+ end
+ f:close()
+ end
+ end
+ statistics.stoptiming(resolvers.instance)
+ end
+end
+
+-- status info
+
+statistics.register("used config path", function() return caches.configpath() end)
+statistics.register("used cache path", function() return caches.temp() or "?" end)
+
+-- experiment (code will move)
+
+function statistics.save_fmt_status(texname,formatbanner,sourcefile) -- texname == formatname
+ local enginebanner = status.list().banner
+ if formatbanner and enginebanner and sourcefile then
+ local luvname = file.replacesuffix(texname,"luv")
+ local luvdata = {
+ enginebanner = enginebanner,
+ formatbanner = formatbanner,
+ sourcehash = md5.hex(io.loaddata(resolvers.find_file(sourcefile)) or "unknown"),
+ sourcefile = sourcefile,
+ }
+ io.savedata(luvname,table.serialize(luvdata,true))
+ end
+end
+
+function statistics.check_fmt_status(texname)
+ local enginebanner = status.list().banner
+ if enginebanner and texname then
+ local luvname = file.replacesuffix(texname,"luv")
+ if lfs.isfile(luvname) then
+ local luv = dofile(luvname)
+ if luv and luv.sourcefile then
+ local sourcehash = md5.hex(io.loaddata(resolvers.find_file(luv.sourcefile)) or "unknown")
+ local luvbanner = luv.enginebanner or "?"
+ if luvbanner ~= enginebanner then
+ return string.format("engine mismatch (luv:%s <> bin:%s)",luvbanner,enginebanner)
+ end
+ local luvhash = luv.sourcehash or "?"
+ if luvhash ~= sourcehash then
+ return string.format("source mismatch (luv:%s <> bin:%s)",luvhash,sourcehash)
+ end
+ else
+ return "invalid status file"
+ end
+ else
+ return "missing status file"
+ end
+ end
+ return true
+end
diff --git a/tex/context/base/data-zip.lua b/tex/context/base/data-zip.lua
new file mode 100644
index 000000000..aa3740a83
--- /dev/null
+++ b/tex/context/base/data-zip.lua
@@ -0,0 +1,241 @@
+if not modules then modules = { } end modules ['data-zip'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, find, match = string.format, string.find, string.match
+local unpack = unpack or table.unpack
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+-- zip:///oeps.zip?name=bla/bla.tex
+-- zip:///oeps.zip?tree=tex/texmf-local
+-- zip:///texmf.zip?tree=/tex/texmf
+-- zip:///texmf.zip?tree=/tex/texmf-local
+-- zip:///texmf-mine.zip?tree=/tex/texmf-projects
+
+zip = zip or { }
+zip.archives = zip.archives or { }
+zip.registeredfiles = zip.registeredfiles or { }
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+local locators, hashers, concatinators = resolvers.locators, resolvers.hashers, resolvers.concatinators
+
+local archives = zip.archives
+
+local function validzip(str) -- todo: use url splitter
+ if not find(str,"^zip://") then
+ return "zip:///" .. str
+ else
+ return str
+ end
+end
+
+function zip.openarchive(name)
+ if not name or name == "" then
+ return nil
+ else
+ local arch = archives[name]
+ if not arch then
+ local full = resolvers.find_file(name) or ""
+ arch = (full ~= "" and zip.open(full)) or false
+ archives[name] = arch
+ end
+ return arch
+ end
+end
+
+function zip.closearchive(name)
+ if not name or (name == "" and archives[name]) then
+ zip.close(archives[name])
+ archives[name] = nil
+ end
+end
+
+function locators.zip(specification) -- where is this used? startup zips (untested)
+ specification = resolvers.splitmethod(specification)
+ local zipfile = specification.path
+ local zfile = zip.openarchive(name) -- tricky, could be in to be initialized tree
+ if trace_locating then
+ if zfile then
+ logs.report("fileio","zip locator, archive '%s' found",specification.original)
+ else
+ logs.report("fileio","zip locator, archive '%s' not found",specification.original)
+ end
+ end
+end
+
+function hashers.zip(tag,name)
+ if trace_locating then
+ logs.report("fileio","loading zip file '%s' as '%s'",name,tag)
+ end
+ resolvers.usezipfile(format("%s?tree=%s",tag,name))
+end
+
+function concatinators.zip(tag,path,name)
+ if not path or path == "" then
+ return format('%s?name=%s',tag,name)
+ else
+ return format('%s?name=%s/%s',tag,path,name)
+ end
+end
+
+function resolvers.isreadable.zip(name)
+ return true
+end
+
+function finders.zip(specification,filetype)
+ specification = resolvers.splitmethod(specification)
+ if specification.path then
+ local q = url.query(specification.query)
+ if q.name then
+ local zfile = zip.openarchive(specification.path)
+ if zfile then
+ if trace_locating then
+ logs.report("fileio","zip finder, archive '%s' found",specification.path)
+ end
+ local dfile = zfile:open(q.name)
+ if dfile then
+ dfile = zfile:close()
+ if trace_locating then
+ logs.report("fileio","zip finder, file '%s' found",q.name)
+ end
+ return specification.original
+ elseif trace_locating then
+ logs.report("fileio","zip finder, file '%s' not found",q.name)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip finder, unknown archive '%s'",specification.path)
+ end
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","zip finder, '%s' not found",filename)
+ end
+ return unpack(finders.notfound)
+end
+
+function openers.zip(specification)
+ local zipspecification = resolvers.splitmethod(specification)
+ if zipspecification.path then
+ local q = url.query(zipspecification.query)
+ if q.name then
+ local zfile = zip.openarchive(zipspecification.path)
+ if zfile then
+ if trace_locating then
+ logs.report("fileio","zip opener, archive '%s' opened",zipspecification.path)
+ end
+ local dfile = zfile:open(q.name)
+ if dfile then
+ logs.show_open(specification)
+ if trace_locating then
+ logs.report("fileio","zip opener, file '%s' found",q.name)
+ end
+ return openers.text_opener(specification,dfile,'zip')
+ elseif trace_locating then
+ logs.report("fileio","zip opener, file '%s' not found",q.name)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip opener, unknown archive '%s'",zipspecification.path)
+ end
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","zip opener, '%s' not found",filename)
+ end
+ return unpack(openers.notfound)
+end
+
+function loaders.zip(specification)
+ specification = resolvers.splitmethod(specification)
+ if specification.path then
+ local q = url.query(specification.query)
+ if q.name then
+ local zfile = zip.openarchive(specification.path)
+ if zfile then
+ if trace_locating then
+ logs.report("fileio","zip loader, archive '%s' opened",specification.path)
+ end
+ local dfile = zfile:open(q.name)
+ if dfile then
+ logs.show_load(filename)
+ if trace_locating then
+ logs.report("fileio","zip loader, file '%s' loaded",filename)
+ end
+ local s = dfile:read("*all")
+ dfile:close()
+ return true, s, #s
+ elseif trace_locating then
+ logs.report("fileio","zip loader, file '%s' not found",q.name)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip loader, unknown archive '%s'",specification.path)
+ end
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","zip loader, '%s' not found",filename)
+ end
+ return unpack(openers.notfound)
+end
+
+-- zip:///somefile.zip
+-- zip:///somefile.zip?tree=texmf-local -> mount
+
+function resolvers.usezipfile(zipname)
+ zipname = validzip(zipname)
+ local specification = resolvers.splitmethod(zipname)
+ local zipfile = specification.path
+ if zipfile and not zip.registeredfiles[zipname] then
+ local tree = url.query(specification.query).tree or ""
+ local z = zip.openarchive(zipfile)
+ if z then
+ local instance = resolvers.instance
+ if trace_locating then
+ logs.report("fileio","zip registering, registering archive '%s'",zipname)
+ end
+ statistics.starttiming(instance)
+ resolvers.prepend_hash('zip',zipname,zipfile)
+ resolvers.extend_texmf_var(zipname) -- resets hashes too
+ zip.registeredfiles[zipname] = z
+ instance.files[zipname] = resolvers.register_zip_file(z,tree or "")
+ statistics.stoptiming(instance)
+ elseif trace_locating then
+ logs.report("fileio","zip registering, unknown archive '%s'",zipname)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip registering, '%s' not found",zipname)
+ end
+end
+
+function resolvers.register_zip_file(z,tree)
+ local files, filter = { }, ""
+ if tree == "" then
+ filter = "^(.+)/(.-)$"
+ else
+ filter = format("^%s/(.+)/(.-)$",tree)
+ end
+ if trace_locating then
+ logs.report("fileio","zip registering, using filter '%s'",filter)
+ end
+ local register, n = resolvers.register_file, 0
+ for i in z:files() do
+ local path, name = match(i.filename,filter)
+ if path then
+ if name and name ~= '' then
+ register(files, name, path)
+ n = n + 1
+ else
+ -- directory
+ end
+ else
+ register(files, i.filename, '')
+ n = n + 1
+ end
+ end
+ logs.report("fileio","zip registering, %s files registered",n)
+ return files
+end
diff --git a/tex/context/base/enco-032.mkii b/tex/context/base/enco-032.mkii
new file mode 100644
index 000000000..d7e15126c
--- /dev/null
+++ b/tex/context/base/enco-032.mkii
@@ -0,0 +1,82 @@
+%D \module
+%D [ file=enco-032,
+%D version=2006.03.30,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Unicode Goodies,
+%D author={Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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
+
+% unicode table 32 (= hex 20)
+
+\startencoding [default]
+
+ \definecommand unic@threeperemspace {\hskip .33333em }
+ \definecommand unic@fourperemspace {\hskip .25em }
+ \definecommand unic@sixperemspace {\hskip .16667em }
+ \definecommand unic@figurespace {\hphantom{0}}
+ \definecommand unic@punctuationspace {\hphantom{,}}
+ \definecommand unic@hairspace {\hskip .08333em }
+ \definecommand unic@zerowidthspace {\hskip 0em plus 1sp }
+ \definecommand unic@zerowidthjoiner {\kern 0em }
+ \definecommand unic@zerowidthnonjoiner {\hskip 0em }
+
+ \definecommand unic@quotedblleftreversed {\mirror{\quotedblright}}
+ \definecommand unic@quoteleftreversed {\mirror{\quoteright}}
+
+ \definecommand unic@onedotleader {{\periods[1]}}
+ \definecommand unic@twodotleader {{\periods[2]}}
+ \definecommand unic@hyphenationpoint {.\allowbreak }
+
+ \definecommand unic@doubleexclamationmark {!!}
+ \definecommand unic@exclamationquestionmark {!?}
+ \definecommand unic@questionexclamationmark {?!}
+ \definecommand unic@doublequestionmark {??}
+
+ \definecommand unic@reversedpilcrowsign {\mirror{\P}}
+ \definecommand unic@reversedsemicolon {\mirror{;}}
+
+ \definecommand unic@superscriptzero {\high{0}}
+ \definecommand unic@superscripti {\high{i}}
+ \definecommand unic@superscriptfour {\high{4}}
+ \definecommand unic@superscriptfive {\high{5}}
+ \definecommand unic@superscriptsix {\high{6}}
+ \definecommand unic@superscriptseven {\high{7}}
+ \definecommand unic@superscripteight {\high{8}}
+ \definecommand unic@superscriptnine {\high{9}}
+ \definecommand unic@superscriptplus {\high{+}}
+ \definecommand unic@superscriptminus {\high{\textminus}}
+ \definecommand unic@superscriptequals {\high{=}}
+ \definecommand unic@superscriptleft {\high{(}}
+ \definecommand unic@superscriptright {\high{)}}
+ \definecommand unic@superscriptn {\high{n}}
+ \definecommand unic@subscriptzero {\low{0}}
+ \definecommand unic@subscriptone {\low{1}}
+ \definecommand unic@subscripttwo {\low{2}}
+ \definecommand unic@subscriptthree {\low{3}}
+ \definecommand unic@subscriptfour {\low{4}}
+ \definecommand unic@subscriptfive {\low{5}}
+ \definecommand unic@subscriptsix {\low{6}}
+ \definecommand unic@subscriptseven {\low{7}}
+ \definecommand unic@subscripteight {\low{8}}
+ \definecommand unic@subscriptnine {\low{9}}
+ \definecommand unic@subscriptplus {\low{+}}
+ \definecommand unic@subscriptminus {\low{\textminus}}
+ \definecommand unic@subscriptequals {\low{=}}
+ \definecommand unic@subscriptleft {\low{(}}
+ \definecommand unic@subscriptright {\low{)}}
+ \definecommand unic@subscripta {\low{a}}
+ \definecommand unic@subscripte {\low{e}}
+ \definecommand unic@subscripto {\low{o}}
+ \definecommand unic@subscriptx {\low{x}}
+ \definecommand unic@subscriptschwa {\low{\schwa}}
+
+\stopencoding
+
+\protect \endinput
diff --git a/tex/context/base/enco-037.mkii b/tex/context/base/enco-037.mkii
new file mode 100644
index 000000000..d9fc653b2
--- /dev/null
+++ b/tex/context/base/enco-037.mkii
@@ -0,0 +1,276 @@
+%D \module
+%D [ file=enco-037,
+%D version=2006.02.13,
+%D title=\CONTEXT\ \UNICODE\ Macros,
+%D subtitle=Encoding for vector 37,
+%D author=Luigi Scarso,
+%D date=\currentdate,
+%D copyright={PRAGMA}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startencoding[default]
+
+\definecharacter UnicodeLightHorizontal {\uchar{37}{000}} %%BOX DRAWINGS LIGHT HORIZONTAL
+\definecharacter UnicodeHeavyHorizontal {\uchar{37}{001}} %%BOX DRAWINGS HEAVY HORIZONTAL
+\definecharacter UnicodeLightVertical {\uchar{37}{002}} %%BOX DRAWINGS LIGHT VERTICAL
+\definecharacter UnicodeHeavyVertical {\uchar{37}{003}} %%BOX DRAWINGS HEAVY VERTICAL
+\definecharacter UnicodeLightTripleDashHorizontal {\uchar{37}{004}} %%BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL
+\definecharacter UnicodeHeavyTripleDashHorizontal {\uchar{37}{005}} %%BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL
+\definecharacter UnicodeLightTripleDashVertical {\uchar{37}{006}} %%BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL
+\definecharacter UnicodeHeavyTripleDashVertical {\uchar{37}{007}} %%BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL
+\definecharacter UnicodeLightQuadrupleDashHorizontal {\uchar{37}{008}} %%BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL
+\definecharacter UnicodeHeavyQuadrupleDashHorizontal {\uchar{37}{009}} %%BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL
+\definecharacter UnicodeLightQuadrupleDashVertical {\uchar{37}{010}} %%BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL
+\definecharacter UnicodeHeavyQuadrupleDashVertical {\uchar{37}{011}} %%BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL
+\definecharacter UnicodeLightDownAndRight {\uchar{37}{012}} %%BOX DRAWINGS LIGHT DOWN AND RIGHT
+\definecharacter UnicodeDownLightAndRightHeavy {\uchar{37}{013}} %%BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY
+\definecharacter UnicodeDownHeavyAndRightLight {\uchar{37}{014}} %%BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT
+\definecharacter UnicodeHeavyDownAndRight {\uchar{37}{015}} %%BOX DRAWINGS HEAVY DOWN AND RIGHT
+\definecharacter UnicodeLightDownAndLeft {\uchar{37}{016}} %%BOX DRAWINGS LIGHT DOWN AND LEFT
+\definecharacter UnicodeDownLightAndLeftHeavy {\uchar{37}{017}} %%BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY
+\definecharacter UnicodeDownHeavyAndLeftLight {\uchar{37}{018}} %%BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT
+\definecharacter UnicodeHeavyDownAndLeft {\uchar{37}{019}} %%BOX DRAWINGS HEAVY DOWN AND LEFT
+\definecharacter UnicodeLightUpAndRight {\uchar{37}{020}} %%BOX DRAWINGS LIGHT UP AND RIGHT
+\definecharacter UnicodeUpLightAndRightHeavy {\uchar{37}{021}} %%BOX DRAWINGS UP LIGHT AND RIGHT HEAVY
+\definecharacter UnicodeUpHeavyAndRightLight {\uchar{37}{022}} %%BOX DRAWINGS UP HEAVY AND RIGHT LIGHT
+\definecharacter UnicodeHeavyUpAndRight {\uchar{37}{023}} %%BOX DRAWINGS HEAVY UP AND RIGHT
+\definecharacter UnicodeLightUpAndLeft {\uchar{37}{024}} %%BOX DRAWINGS LIGHT UP AND LEFT
+\definecharacter UnicodeUpLightAndLeftHeavy {\uchar{37}{025}} %%BOX DRAWINGS UP LIGHT AND LEFT HEAVY
+\definecharacter UnicodeUpHeavyAndLeftLight {\uchar{37}{026}} %%BOX DRAWINGS UP HEAVY AND LEFT LIGHT
+\definecharacter UnicodeHeavyUpAndLeft {\uchar{37}{027}} %%BOX DRAWINGS HEAVY UP AND LEFT
+\definecharacter UnicodeLightVerticalAndRight {\uchar{37}{028}} %%BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+\definecharacter UnicodeVerticalLightAndRightHeavy {\uchar{37}{029}} %%BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY
+\definecharacter UnicodeUpHeavyAndRightDownLight {\uchar{37}{030}} %%BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT
+\definecharacter UnicodeDownHeavyAndRightUpLight {\uchar{37}{031}} %%BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT
+\definecharacter UnicodeVerticalHeavyAndRightLight {\uchar{37}{032}} %%BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT
+\definecharacter UnicodeDownLightAndRightUpHeavy {\uchar{37}{033}} %%BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY
+\definecharacter UnicodeUpLightAndRightDownHeavy {\uchar{37}{034}} %%BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY
+\definecharacter UnicodeHeavyVerticalAndRight {\uchar{37}{035}} %%BOX DRAWINGS HEAVY VERTICAL AND RIGHT
+\definecharacter UnicodeLightVerticalAndLeft {\uchar{37}{036}} %%BOX DRAWINGS LIGHT VERTICAL AND LEFT
+\definecharacter UnicodeVerticalLightAndLeftHeavy {\uchar{37}{037}} %%BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY
+\definecharacter UnicodeUpHeavyAndLeftDownLight {\uchar{37}{038}} %%BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT
+\definecharacter UnicodeDownHeavyAndLeftUpLight {\uchar{37}{039}} %%BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT
+\definecharacter UnicodeVerticalHeavyAndLeftLight {\uchar{37}{040}} %%BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT
+\definecharacter UnicodeDownLightAndLeftUpHeavy {\uchar{37}{041}} %%BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY
+\definecharacter UnicodeUpLightAndLeftDownHeavy {\uchar{37}{042}} %%BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY
+\definecharacter UnicodeHeavyVerticalAndLeft {\uchar{37}{043}} %%BOX DRAWINGS HEAVY VERTICAL AND LEFT
+\definecharacter UnicodeLightDownAndHorizontal {\uchar{37}{044}} %%BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+\definecharacter UnicodeLeftHeavyAndRightDownLight {\uchar{37}{045}} %%BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT
+\definecharacter UnicodeRightHeavyAndLeftDownLight {\uchar{37}{046}} %%BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT
+\definecharacter UnicodeDownLightAndHorizontalHeavy {\uchar{37}{047}} %%BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY
+\definecharacter UnicodeDownHeavyAndHorizontalLight {\uchar{37}{048}} %%BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT
+\definecharacter UnicodeRightLightAndLeftDownHeavy {\uchar{37}{049}} %%BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY
+\definecharacter UnicodeLeftLightAndRightDownHeavy {\uchar{37}{050}} %%BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY
+\definecharacter UnicodeHeavyDownAndHorizontal {\uchar{37}{051}} %%BOX DRAWINGS HEAVY DOWN AND HORIZONTAL
+\definecharacter UnicodeLightUpAndHorizontal {\uchar{37}{052}} %%BOX DRAWINGS LIGHT UP AND HORIZONTAL
+\definecharacter UnicodeLeftHeavyAndRightUpLight {\uchar{37}{053}} %%BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT
+\definecharacter UnicodeRightHeavyAndLeftUpLight {\uchar{37}{054}} %%BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT
+\definecharacter UnicodeUpLightAndHorizontalHeavy {\uchar{37}{055}} %%BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY
+\definecharacter UnicodeUpHeavyAndHorizontalLight {\uchar{37}{056}} %%BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT
+\definecharacter UnicodeRightLightAndLeftUpHeavy {\uchar{37}{057}} %%BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY
+\definecharacter UnicodeLeftLightAndRightUpHeavy {\uchar{37}{058}} %%BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY
+\definecharacter UnicodeHeavyUpAndHorizontal {\uchar{37}{059}} %%BOX DRAWINGS HEAVY UP AND HORIZONTAL
+\definecharacter UnicodeLightVerticalAndHorizontal {\uchar{37}{060}} %%BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+\definecharacter UnicodeLeftHeavyAndRightVerticalLight {\uchar{37}{061}} %%BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT
+\definecharacter UnicodeRightHeavyAndLeftVerticalLight {\uchar{37}{062}} %%BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT
+\definecharacter UnicodeVerticalLightAndHorizontalHeavy {\uchar{37}{063}} %%BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY
+\definecharacter UnicodeUpHeavyAndDownHorizontalLight {\uchar{37}{064}} %%BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT
+\definecharacter UnicodeDownHeavyAndUpHorizontalLight {\uchar{37}{065}} %%BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT
+\definecharacter UnicodeVerticalHeavyAndHorizontalLight {\uchar{37}{066}} %%BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT
+\definecharacter UnicodeLeftUpHeavyAndRightDownLight {\uchar{37}{067}} %%BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT
+\definecharacter UnicodeRightUpHeavyAndLeftDownLight {\uchar{37}{068}} %%BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT
+\definecharacter UnicodeLeftDownHeavyAndRightUpLight {\uchar{37}{069}} %%BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT
+\definecharacter UnicodeRightDownHeavyAndLeftUpLight {\uchar{37}{070}} %%BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT
+\definecharacter UnicodeDownLightAndUpHorizontalHeavy {\uchar{37}{071}} %%BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY
+\definecharacter UnicodeUpLightAndDownHorizontalHeavy {\uchar{37}{072}} %%BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY
+\definecharacter UnicodeRightLightAndLeftVerticalHeavy {\uchar{37}{073}} %%BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY
+\definecharacter UnicodeLeftLightAndRightVerticalHeavy {\uchar{37}{074}} %%BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY
+\definecharacter UnicodeHeavyVerticalAndHorizontal {\uchar{37}{075}} %%BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
+\definecharacter UnicodeLightDoubleDashHorizontal {\uchar{37}{076}} %%BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL
+\definecharacter UnicodeHeavyDoubleDashHorizontal {\uchar{37}{077}} %%BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL
+\definecharacter UnicodeLightDoubleDashVertical {\uchar{37}{078}} %%BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL
+\definecharacter UnicodeHeavyDoubleDashVertical {\uchar{37}{079}} %%BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
+\definecharacter UnicodeDoubleHorizontal {\uchar{37}{080}} %%BOX DRAWINGS DOUBLE HORIZONTAL
+\definecharacter UnicodeDoubleVertical {\uchar{37}{081}} %%BOX DRAWINGS DOUBLE VERTICAL
+\definecharacter UnicodeDownSingleAndRightDouble {\uchar{37}{082}} %%BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+\definecharacter UnicodeDownDoubleAndRightSingle {\uchar{37}{083}} %%BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+\definecharacter UnicodeDoubleDownAndRight {\uchar{37}{084}} %%BOX DRAWINGS DOUBLE DOWN AND RIGHT
+\definecharacter UnicodeDownSingleAndLeftDouble {\uchar{37}{085}} %%BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+\definecharacter UnicodeDownDoubleAndLeftSingle {\uchar{37}{086}} %%BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+\definecharacter UnicodeDoubleDownAndLeft {\uchar{37}{087}} %%BOX DRAWINGS DOUBLE DOWN AND LEFT
+\definecharacter UnicodeUpSingleAndRightDouble {\uchar{37}{088}} %%BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+\definecharacter UnicodeUpDoubleAndRightSingle {\uchar{37}{089}} %%BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+\definecharacter UnicodeDoubleUpAndRight {\uchar{37}{090}} %%BOX DRAWINGS DOUBLE UP AND RIGHT
+\definecharacter UnicodeUpSingleAndLeftDouble {\uchar{37}{091}} %%BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+\definecharacter UnicodeUpDoubleAndLeftSingle {\uchar{37}{092}} %%BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+\definecharacter UnicodeDoubleUpAndLeft {\uchar{37}{093}} %%BOX DRAWINGS DOUBLE UP AND LEFT
+\definecharacter UnicodeVerticalSingleAndRightDouble {\uchar{37}{094}} %%BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+\definecharacter UnicodeVerticalDoubleAndRightSingle {\uchar{37}{095}} %%BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+\definecharacter UnicodeDoubleVerticalAndRight {\uchar{37}{096}} %%BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+\definecharacter UnicodeVerticalSingleAndLeftDouble {\uchar{37}{097}} %%BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+\definecharacter UnicodeVerticalDoubleAndLeftSingle {\uchar{37}{098}} %%BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+\definecharacter UnicodeDoubleVerticalAndLeft {\uchar{37}{099}} %%BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+\definecharacter UnicodeDownSingleAndHorizontalDouble {\uchar{37}{100}} %%BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+\definecharacter UnicodeDownDoubleAndHorizontalSingle {\uchar{37}{101}} %%BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+\definecharacter UnicodeDoubleDownAndHorizontal {\uchar{37}{102}} %%BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+\definecharacter UnicodeUpSingleAndHorizontalDouble {\uchar{37}{103}} %%BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+\definecharacter UnicodeUpDoubleAndHorizontalSingle {\uchar{37}{104}} %%BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+\definecharacter UnicodeDoubleUpAndHorizontal {\uchar{37}{105}} %%BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+\definecharacter UnicodeVerticalSingleAndHorizontalDouble {\uchar{37}{106}} %%BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+\definecharacter UnicodeVerticalDoubleAndHorizontalSingle {\uchar{37}{107}} %%BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+\definecharacter UnicodeDoubleVerticalAndHorizontal {\uchar{37}{108}} %%BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+\definecharacter UnicodeLightArcDownAndRight {\uchar{37}{109}} %%BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
+\definecharacter UnicodeLightArcDownAndLeft {\uchar{37}{110}} %%BOX DRAWINGS LIGHT ARC DOWN AND LEFT
+\definecharacter UnicodeLightArcUpAndLeft {\uchar{37}{111}} %%BOX DRAWINGS LIGHT ARC UP AND LEFT
+\definecharacter UnicodeLightArcUpAndRight {\uchar{37}{112}} %%BOX DRAWINGS LIGHT ARC UP AND RIGHT
+\definecharacter UnicodeLightDiagonalUpperRightToLowerLeft {\uchar{37}{113}} %%BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
+\definecharacter UnicodeLightDiagonalUpperLeftToLowerRight {\uchar{37}{114}} %%BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
+\definecharacter UnicodeLightDiagonalCross {\uchar{37}{115}} %%BOX DRAWINGS LIGHT DIAGONAL CROSS
+\definecharacter UnicodeLightLeft {\uchar{37}{116}} %%BOX DRAWINGS LIGHT LEFT
+\definecharacter UnicodeLightUp {\uchar{37}{117}} %%BOX DRAWINGS LIGHT UP
+\definecharacter UnicodeLightRight {\uchar{37}{118}} %%BOX DRAWINGS LIGHT RIGHT
+\definecharacter UnicodeLightDown {\uchar{37}{119}} %%BOX DRAWINGS LIGHT DOWN
+\definecharacter UnicodeHeavyLeft {\uchar{37}{120}} %%BOX DRAWINGS HEAVY LEFT
+\definecharacter UnicodeHeavyUp {\uchar{37}{121}} %%BOX DRAWINGS HEAVY UP
+\definecharacter UnicodeHeavyRight {\uchar{37}{122}} %%BOX DRAWINGS HEAVY RIGHT
+\definecharacter UnicodeHeavyDown {\uchar{37}{123}} %%BOX DRAWINGS HEAVY DOWN
+\definecharacter UnicodeLightLeftAndHeavyRight {\uchar{37}{124}} %%BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT
+\definecharacter UnicodeLightUpAndHeavyDown {\uchar{37}{125}} %%BOX DRAWINGS LIGHT UP AND HEAVY DOWN
+\definecharacter UnicodeHeavyLeftAndLightRight {\uchar{37}{126}} %%BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT
+\definecharacter UnicodeHeavyUpAndLightDown {\uchar{37}{127}} %%BOX DRAWINGS HEAVY UP AND LIGHT DOWN
+\definecharacter UnicodeUpperHalfBlock {\uchar{37}{128}} %%UPPER HALF BLOCK
+\definecharacter UnicodeLowerOneEighthBlock {\uchar{37}{129}} %%LOWER ONE EIGHTH BLOCK
+\definecharacter UnicodeLowerOneQuarterBlock {\uchar{37}{130}} %%LOWER ONE QUARTER BLOCK
+\definecharacter UnicodeLowerThreeEighthsBlock {\uchar{37}{131}} %%LOWER THREE EIGHTHS BLOCK
+\definecharacter UnicodeLowerHalfBlock {\uchar{37}{132}} %%LOWER HALF BLOCK
+\definecharacter UnicodeLowerFiveEighthsBlock {\uchar{37}{133}} %%LOWER FIVE EIGHTHS BLOCK
+\definecharacter UnicodeLowerThreeQuartersBlock {\uchar{37}{134}} %%LOWER THREE QUARTERS BLOCK
+\definecharacter UnicodeLowerSevenEighthsBlock {\uchar{37}{135}} %%LOWER SEVEN EIGHTHS BLOCK
+\definecharacter UnicodeFullBlock {\uchar{37}{136}} %%FULL BLOCK
+\definecharacter UnicodeLeftSevenEighthsBlock {\uchar{37}{137}} %%LEFT SEVEN EIGHTHS BLOCK
+\definecharacter UnicodeLeftThreeQuartersBlock {\uchar{37}{138}} %%LEFT THREE QUARTERS BLOCK
+\definecharacter UnicodeLeftFiveEighthsBlock {\uchar{37}{139}} %%LEFT FIVE EIGHTHS BLOCK
+\definecharacter UnicodeLeftHalfBlock {\uchar{37}{140}} %%LEFT HALF BLOCK
+\definecharacter UnicodeLeftThreeEighthsBlock {\uchar{37}{141}} %%LEFT THREE EIGHTHS BLOCK
+\definecharacter UnicodeLeftOneQuarterBlock {\uchar{37}{142}} %%LEFT ONE QUARTER BLOCK
+\definecharacter UnicodeLeftOneEighthBlock {\uchar{37}{143}} %%LEFT ONE EIGHTH BLOCK
+\definecharacter UnicodeRightHalfBlock {\uchar{37}{144}} %%RIGHT HALF BLOCK
+\definecharacter UnicodeLightShade {\uchar{37}{145}} %%LIGHT SHADE
+\definecharacter UnicodeMediumShade {\uchar{37}{146}} %%MEDIUM SHADE
+\definecharacter UnicodeDarkShade {\uchar{37}{147}} %%DARK SHADE
+\definecharacter UnicodeUpperOneEighthBlock {\uchar{37}{148}} %%UPPER ONE EIGHTH BLOCK
+\definecharacter UnicodeRightOneEighthBlock {\uchar{37}{149}} %%RIGHT ONE EIGHTH BLOCK
+\definecharacter UnicodeQuadrantLowerLeft {\uchar{37}{150}} %%[Unassigned U+2596]
+\definecharacter UnicodeQuadrantLowerRight {\uchar{37}{151}} %%[Unassigned U+2597]
+\definecharacter UnicodeQuadrantUpperLeft {\uchar{37}{152}} %%[Unassigned U+2598]
+\definecharacter UnicodeQuadrantUpperLeftAndLowerLeftAndLowerRight {\uchar{37}{153}} %%[Unassigned U+2599]
+\definecharacter UnicodeQuadrantUpperLeftAndLowerRight {\uchar{37}{154}} %%[Unassigned U+259A]
+\definecharacter UnicodeQuadrantUpperLeftAndUpperRightandLowerLeft {\uchar{37}{155}} %%[Unassigned U+259B]
+\definecharacter UnicodeQuadrantUpperLeftAndUpperRightAndLowerRight {\uchar{37}{156}} %%[Unassigned U+259C]
+\definecharacter UnicodeQuadrantUpperRight {\uchar{37}{157}} %%[Unassigned U+259D]
+\definecharacter UnicodeQuadrantUpperRightAndLowerLeft {\uchar{37}{158}} %%[Unassigned U+259E]
+\definecharacter UnicodeQuadrantUpperRightAndLowerLeftAndLowerRight {\uchar{37}{159}} %%[Unassigned U+259F]
+\definecharacter UnicodeBlackSquare {\uchar{37}{160}} %%BLACK SQUARE
+\definecharacter UnicodeWhiteSquare {\uchar{37}{161}} %%WHITE SQUARE
+\definecharacter UnicodeWhiteSquareWithRoundedCorners {\uchar{37}{162}} %%WHITE SQUARE WITH ROUNDED CORNERS
+\definecharacter UnicodeWhiteSquareContainingBlackSmallSquare {\uchar{37}{163}} %%WHITE SQUARE CONTAINING BLACK SMALL SQUARE
+\definecharacter UnicodeSquareWithHorizontalFill {\uchar{37}{164}} %%SQUARE WITH HORIZONTAL FILL
+\definecharacter UnicodeSquareWithVerticalFill {\uchar{37}{165}} %%SQUARE WITH VERTICAL FILL
+\definecharacter UnicodeSquareWithOrthogonalCrosshatchFill {\uchar{37}{166}} %%SQUARE WITH ORTHOGONAL CROSSHATCH FILL
+\definecharacter UnicodeSquareWithUpperLeftToLowerRightFill {\uchar{37}{167}} %%SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL
+\definecharacter UnicodeSquareWithUpperRightToLowerLeftFill {\uchar{37}{168}} %%SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL
+\definecharacter UnicodeSquareWithDiagonalCrosshatchFill {\uchar{37}{169}} %%SQUARE WITH DIAGONAL CROSSHATCH FILL
+\definecharacter UnicodeBlackSmallSquare {\uchar{37}{170}} %%BLACK SMALL SQUARE
+\definecharacter UnicodeWhiteSmallSquare {\uchar{37}{171}} %%WHITE SMALL SQUARE
+\definecharacter UnicodeBlackRectangle {\uchar{37}{172}} %%BLACK RECTANGLE
+\definecharacter UnicodeWhiteRectangle {\uchar{37}{173}} %%WHITE RECTANGLE
+\definecharacter UnicodeBlackVerticalRectangle {\uchar{37}{174}} %%BLACK VERTICAL RECTANGLE
+\definecharacter UnicodeWhiteVerticalRectangle {\uchar{37}{175}} %%WHITE VERTICAL RECTANGLE
+\definecharacter UnicodeBlackParallelogram {\uchar{37}{176}} %%BLACK PARALLELOGRAM
+\definecharacter UnicodeWhiteParallelogram {\uchar{37}{177}} %%WHITE PARALLELOGRAM
+\definecharacter UnicodeBlackUpPointingTriangle {\uchar{37}{178}} %%BLACK UP-POINTING TRIANGLE
+\definecharacter UnicodeWhiteUpPointingTriangle {\uchar{37}{179}} %%WHITE UP-POINTING TRIANGLE
+\definecharacter UnicodeBlackUpPointingSmallTriangle {\uchar{37}{180}} %%BLACK UP-POINTING SMALL TRIANGLE
+\definecharacter UnicodeWhiteUpPointingSmallTriangle {\uchar{37}{181}} %%WHITE UP-POINTING SMALL TRIANGLE
+\definecharacter UnicodeBlackRightPointingTriangle {\uchar{37}{182}} %%BLACK RIGHT-POINTING TRIANGLE
+\definecharacter UnicodeWhiteRightPointingTriangle {\uchar{37}{183}} %%WHITE RIGHT-POINTING TRIANGLE
+\definecharacter UnicodeBlackRightPointingSmallTriangle {\uchar{37}{184}} %%BLACK RIGHT-POINTING SMALL TRIANGLE
+\definecharacter UnicodeWhiteRightPointingSmallTriangle {\uchar{37}{185}} %%WHITE RIGHT-POINTING SMALL TRIANGLE
+\definecharacter UnicodeBlackRightPointingPointer {\uchar{37}{186}} %%BLACK RIGHT-POINTING POINTER
+\definecharacter UnicodeWhiteRightPointingPointer {\uchar{37}{187}} %%WHITE RIGHT-POINTING POINTER
+\definecharacter UnicodeBlackDownPointingTriangle {\uchar{37}{188}} %%BLACK DOWN-POINTING TRIANGLE
+\definecharacter UnicodeWhiteDownPointingTriangle {\uchar{37}{189}} %%WHITE DOWN-POINTING TRIANGLE
+\definecharacter UnicodeBlackDownPointingSmallTriangle {\uchar{37}{190}} %%BLACK DOWN-POINTING SMALL TRIANGLE
+\definecharacter UnicodeWhiteDownPointingSmallTriangle {\uchar{37}{191}} %%WHITE DOWN-POINTING SMALL TRIANGLE
+\definecharacter UnicodeBlackLeftPointingTriangle {\uchar{37}{192}} %%BLACK LEFT-POINTING TRIANGLE
+\definecharacter UnicodeWhiteLeftPointingTriangle {\uchar{37}{193}} %%WHITE LEFT-POINTING TRIANGLE
+\definecharacter UnicodeBlackLeftPointingSmallTriangle {\uchar{37}{194}} %%BLACK LEFT-POINTING SMALL TRIANGLE
+\definecharacter UnicodeWhiteLeftPointingSmallTriangle {\uchar{37}{195}} %%WHITE LEFT-POINTING SMALL TRIANGLE
+\definecharacter UnicodeBlackLeftPointingPointer {\uchar{37}{196}} %%BLACK LEFT-POINTING POINTER
+\definecharacter UnicodeWhiteLeftPointingPointer {\uchar{37}{197}} %%WHITE LEFT-POINTING POINTER
+\definecharacter UnicodeBlackDiamond {\uchar{37}{198}} %%BLACK DIAMOND
+\definecharacter UnicodeWhiteDiamond {\uchar{37}{199}} %%WHITE DIAMOND
+\definecharacter UnicodeWhiteDiamondContainingBlackSmallDiamond {\uchar{37}{200}} %%WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND
+\definecharacter UnicodeFisheye {\uchar{37}{201}} %%FISHEYE
+\definecharacter UnicodeLozenge {\uchar{37}{202}} %%LOZENGE
+\definecharacter UnicodeWhiteCircle {\uchar{37}{203}} %%WHITE CIRCLE
+\definecharacter UnicodeDottedCircle {\uchar{37}{204}} %%DOTTED CIRCLE
+\definecharacter UnicodeCircleWithVerticalFill {\uchar{37}{205}} %%CIRCLE WITH VERTICAL FILL
+\definecharacter UnicodeBullseye {\uchar{37}{206}} %%BULLSEYE
+\definecharacter UnicodeBlackCircle {\uchar{37}{207}} %%BLACK CIRCLE
+\definecharacter UnicodeCircleWithLeftHalfBlack {\uchar{37}{208}} %%CIRCLE WITH LEFT HALF BLACK
+\definecharacter UnicodeCircleWithRightHalfBlack {\uchar{37}{209}} %%CIRCLE WITH RIGHT HALF BLACK
+\definecharacter UnicodeCircleWithLowerHalfBlack {\uchar{37}{210}} %%CIRCLE WITH LOWER HALF BLACK
+\definecharacter UnicodeCircleWithUpperHalfBlack {\uchar{37}{211}} %%CIRCLE WITH UPPER HALF BLACK
+\definecharacter UnicodeCircleWithUpperRightQuadrantBlack {\uchar{37}{212}} %%CIRCLE WITH UPPER RIGHT QUADRANT BLACK
+\definecharacter UnicodeCircleWithAllButUpperLeftQuadrantBlack {\uchar{37}{213}} %%CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK
+\definecharacter UnicodeLeftHalfBlackCircle {\uchar{37}{214}} %%LEFT HALF BLACK CIRCLE
+\definecharacter UnicodeRightHalfBlackCircle {\uchar{37}{215}} %%RIGHT HALF BLACK CIRCLE
+\definecharacter UnicodeInverseBullet {\uchar{37}{216}} %%INVERSE BULLET
+\definecharacter UnicodeInverseWhiteCircle {\uchar{37}{217}} %%INVERSE WHITE CIRCLE
+\definecharacter UnicodeUpperHalfInverseWhiteCircle {\uchar{37}{218}} %%UPPER HALF INVERSE WHITE CIRCLE
+\definecharacter UnicodeLowerHalfInverseWhiteCircle {\uchar{37}{219}} %%LOWER HALF INVERSE WHITE CIRCLE
+\definecharacter UnicodeUpperLeftQuadrantCircularArc {\uchar{37}{220}} %%UPPER LEFT QUADRANT CIRCULAR ARC
+\definecharacter UnicodeUpperRightQuadrantCircularArc {\uchar{37}{221}} %%UPPER RIGHT QUADRANT CIRCULAR ARC
+\definecharacter UnicodeLowerRightQuadrantCircularArc {\uchar{37}{222}} %%LOWER RIGHT QUADRANT CIRCULAR ARC
+\definecharacter UnicodeLowerLeftQuadrantCircularArc {\uchar{37}{223}} %%LOWER LEFT QUADRANT CIRCULAR ARC
+\definecharacter UnicodeUpperHalfCircle {\uchar{37}{224}} %%UPPER HALF CIRCLE
+\definecharacter UnicodeLowerHalfCircle {\uchar{37}{225}} %%LOWER HALF CIRCLE
+\definecharacter UnicodeBlackLowerRightTriangle {\uchar{37}{226}} %%BLACK LOWER RIGHT TRIANGLE
+\definecharacter UnicodeBlackLowerLeftTriangle {\uchar{37}{227}} %%BLACK LOWER LEFT TRIANGLE
+\definecharacter UnicodeBlackUpperLeftTriangle {\uchar{37}{228}} %%BLACK UPPER LEFT TRIANGLE
+\definecharacter UnicodeBlackUpperRightTriangle {\uchar{37}{229}} %%BLACK UPPER RIGHT TRIANGLE
+\definecharacter UnicodeWhiteBullet {\uchar{37}{230}} %%WHITE BULLET
+\definecharacter UnicodeSquareWithLeftHalfBlack {\uchar{37}{231}} %%SQUARE WITH LEFT HALF BLACK
+\definecharacter UnicodeSquareWithRightHalfBlack {\uchar{37}{232}} %%SQUARE WITH RIGHT HALF BLACK
+\definecharacter UnicodeSquareWithUpperLeftDiagonalHalfBlack {\uchar{37}{233}} %%SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK
+\definecharacter UnicodeSquareWithLowerRightDiagonalHalfBlack {\uchar{37}{234}} %%SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK
+\definecharacter UnicodeWhiteSquareWithVerticalBisectingLine {\uchar{37}{235}} %%WHITE SQUARE WITH VERTICAL BISECTING LINE
+\definecharacter UnicodeWhiteUpPointingTriangleWithDot {\uchar{37}{236}} %%WHITE UP-POINTING TRIANGLE WITH DOT
+\definecharacter UnicodeUpPointingTriangleWithLeftHalfBlack {\uchar{37}{237}} %%UP-POINTING TRIANGLE WITH LEFT HALF BLACK
+\definecharacter UnicodeUpPointingTriangleWithRightHalfBlack {\uchar{37}{238}} %%UP-POINTING TRIANGLE WITH RIGHT HALF BLACK
+\definecharacter UnicodeLargeCircle {\uchar{37}{239}} %%LARGE CIRCLE
+\definecharacter UnicodeWhiteSquareWithUpperLeftQuadrant {\uchar{37}{240}} %%WHITE SQUARE WITH UPPER LEFT QUADRANT
+\definecharacter UnicodeWhiteSquareWithLowerLeftQuadrant {\uchar{37}{241}} %%WHITE SQUARE WITH LOWER LEFT QUADRANT
+\definecharacter UnicodeWhiteSquareWithLowerRightQuadrant {\uchar{37}{242}} %%WHITE SQUARE WITH LOWER RIGHT QUADRANT
+\definecharacter UnicodeWhiteSquareWithUpperRightQuadrant {\uchar{37}{243}} %%WHITE SQUARE WITH UPPER RIGHT QUADRANT
+\definecharacter UnicodeWhiteCircleWithUpperLeftQuadrant {\uchar{37}{244}} %%WHITE CIRCLE WITH UPPER LEFT QUADRANT
+\definecharacter UnicodeWhiteCircleWithLowerLeftQuadrant {\uchar{37}{245}} %%WHITE CIRCLE WITH LOWER LEFT QUADRANT
+\definecharacter UnicodeWhiteCircleWithLowerRightQuadrant {\uchar{37}{246}} %%WHITE CIRCLE WITH LOWER RIGHT QUADRANT
+\definecharacter UnicodeWhiteCircleWithUpperRightQuadrant {\uchar{37}{247}} %%WHITE CIRCLE WITH UPPER RIGHT QUADRANT
+\definecharacter UnicodeUpperLeftTriangle {\uchar{37}{248}} %%[Unassigned U+25F8]
+\definecharacter UnicodeUpperRightTriangle {\uchar{37}{249}} %%[Unassigned U+25F9]
+\definecharacter UnicodeLowerLeftTriangle {\uchar{37}{250}} %%[Unassigned U+25FA]
+\definecharacter UnicodeWhiteMediumSquare {\uchar{37}{251}} %%[Unassigned U+25FB]
+\definecharacter UnicodeBlackMediumSquare {\uchar{37}{252}} %%[Unassigned U+25FC]
+\definecharacter UnicodeWhiteMediumSmallSquare {\uchar{37}{253}} %%[Unassigned U+25FD]
+\definecharacter UnicodeBlackMediumSmallSquare {\uchar{37}{254}} %%[Unassigned U+25FE]
+\definecharacter UnicodeLowerRightTriangle {\uchar{37}{255}} %%[Unassigned U+25FF]
+
+\stopencoding
+
+\endinput
+
diff --git a/tex/context/base/enco-acc.mkii b/tex/context/base/enco-acc.mkii
new file mode 100644
index 000000000..e02536be6
--- /dev/null
+++ b/tex/context/base/enco-acc.mkii
@@ -0,0 +1,139 @@
+%D \module
+%D [ file=enco-acc,
+%D version=2000.20.12, % split from base file
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Composed Characters Commands,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen \& Ton Otten]
+%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 Although it is technically possible to redefine the commands
+%D that are responsible for building composed characters, this
+%D is seldom needed, since they map onto named glyphs. The
+%D meaning of these names glyphs may change, although their
+%D visual appearance seldom will.
+
+\startencoding[default]
+
+\defineaccent ^ A {\Acircumflex} \defineaccent ^ a {\acircumflex}
+\defineaccent ^ C {\Ccircumflex} \defineaccent ^ c {\ccircumflex}
+\defineaccent ^ E {\Ecircumflex} \defineaccent ^ e {\ecircumflex}
+\defineaccent ^ G {\Gcircumflex} \defineaccent ^ g {\gcircumflex}
+\defineaccent ^ H {\Hcircumflex} \defineaccent ^ h {\hcircumflex}
+\defineaccent ^ I {\Icircumflex} \defineaccent ^ i {\icircumflex} \defineaccent ^ {\i} {\icircumflex}
+\defineaccent ^ J {\Jcircumflex} \defineaccent ^ j {\jcircumflex} \defineaccent ^ {\j} {\jcircumflex}
+\defineaccent ^ O {\Ocircumflex} \defineaccent ^ o {\ocircumflex}
+\defineaccent ^ S {\Scircumflex} \defineaccent ^ s {\scircumflex}
+\defineaccent ^ U {\Ucircumflex} \defineaccent ^ u {\ucircumflex}
+\defineaccent ^ W {\Wcircumflex} \defineaccent ^ w {\wcircumflex}
+\defineaccent ^ Y {\Ycircumflex} \defineaccent ^ y {\ycircumflex}
+
+\defineaccent ` A {\Agrave} \defineaccent ` a {\agrave}
+\defineaccent ` E {\Egrave} \defineaccent ` e {\egrave}
+\defineaccent ` I {\Igrave} \defineaccent ` i {\igrave} \defineaccent ` {\i} {\igrave}
+\defineaccent ` O {\Ograve} \defineaccent ` o {\ograve}
+\defineaccent ` U {\Ugrave} \defineaccent ` u {\ugrave}
+\defineaccent ` Y {\Ygrave} \defineaccent ` y {\ygrave}
+
+\defineaccent ~ A {\Atilde} \defineaccent ~ a {\atilde}
+\defineaccent ~ I {\Itilde} \defineaccent ~ i {\itilde} \defineaccent ~ {\i} {\itilde}
+\defineaccent ~ O {\Otilde} \defineaccent ~ o {\otilde}
+\defineaccent ~ U {\Utilde} \defineaccent ~ u {\utilde}
+
+\defineaccent " A {\Adiaeresis} \defineaccent " a {\adiaeresis}
+\defineaccent " E {\Ediaeresis} \defineaccent " e {\ediaeresis}
+\defineaccent " I {\Idiaeresis} \defineaccent " i {\idiaeresis} \defineaccent " {\i} {\idiaeresis}
+\defineaccent " O {\Odiaeresis} \defineaccent " o {\odiaeresis}
+\defineaccent " U {\Udiaeresis} \defineaccent " u {\udiaeresis}
+\defineaccent " Y {\Ydiaeresis} \defineaccent " y {\ydiaeresis}
+
+\defineaccent ' A {\Aacute} \defineaccent ' a {\aacute}
+\defineaccent ' C {\Cacute} \defineaccent ' c {\cacute}
+\defineaccent ' E {\Eacute} \defineaccent ' e {\eacute}
+\defineaccent ' I {\Iacute} \defineaccent ' i {\iacute} \defineaccent ' {\i} {\iacute}
+\defineaccent ' L {\Lacute} \defineaccent ' l {\lacute}
+\defineaccent ' N {\Nacute} \defineaccent ' n {\nacute}
+\defineaccent ' O {\Oacute} \defineaccent ' o {\oacute}
+\defineaccent ' R {\Racute} \defineaccent ' r {\racute}
+\defineaccent ' S {\Sacute} \defineaccent ' s {\sacute}
+\defineaccent ' U {\Uacute} \defineaccent ' u {\uacute}
+\defineaccent ' Y {\Yacute} \defineaccent ' y {\yacute}
+\defineaccent ' Z {\Zacute} \defineaccent ' z {\zacute}
+
+\defineaccent . C {\Cdotaccent} \defineaccent . c {\cdotaccent}
+\defineaccent . E {\Edotaccent} \defineaccent . e {\edotaccent}
+\defineaccent . G {\Gdotaccent} \defineaccent . g {\gdotaccent}
+\defineaccent . I {\Idotaccent} \defineaccent . i {\idotaccent} \defineaccent . {\i} {\idotaccent}
+\defineaccent . Z {\Zdotaccent} \defineaccent . z {\zdotaccent}
+
+\defineaccent = A {\Amacron} \defineaccent = a {\amacron}
+\defineaccent = E {\Emacron} \defineaccent = e {\emacron}
+\defineaccent = I {\Imacron} \defineaccent = i {\imacron} \defineaccent = {\i} {\imacron}
+\defineaccent = O {\Omacron} \defineaccent = o {\omacron}
+\defineaccent = U {\Umacron} \defineaccent = u {\umacron}
+
+\defineaccent c C {\Ccedilla} \defineaccent c c {\ccedilla}
+\defineaccent c K {\Kcedilla} \defineaccent c k {\kcedilla}
+\defineaccent c L {\Lcedilla} \defineaccent c l {\lcedilla}
+\defineaccent c N {\Ncedilla} \defineaccent c n {\ncedilla}
+\defineaccent c R {\Rcedilla} \defineaccent c r {\rcedilla}
+\defineaccent c S {\Scedilla} \defineaccent c s {\scedilla}
+\defineaccent c T {\Tcedilla} \defineaccent c t {\tcedilla}
+
+\defineaccent H O {\Ohungarumlaut} \defineaccent H o {\ohungarumlaut}
+\defineaccent H u {\uhungarumlaut} \defineaccent H U {\Uhungarumlaut}
+
+\defineaccent k A {\Aogonek} \defineaccent k a {\aogonek}
+\defineaccent k E {\Eogonek} \defineaccent k e {\eogonek}
+\defineaccent k I {\Iogonek} \defineaccent k i {\iogonek}
+\defineaccent k U {\Uogonek} \defineaccent k u {\uogonek}
+
+\defineaccent r A {\Aring} \defineaccent r a {\aring}
+\defineaccent r U {\Uring} \defineaccent r u {\uring}
+
+\defineaccent u A {\Abreve} \defineaccent u a {\abreve}
+\defineaccent u E {\Ebreve} \defineaccent u e {\ebreve}
+\defineaccent u G {\Gbreve} \defineaccent u g {\gbreve}
+\defineaccent u I {\Ibreve} \defineaccent u i {\ibreve} \defineaccent u {\i} {\ibreve}
+\defineaccent u O {\Obreve} \defineaccent u o {\obreve}
+\defineaccent u U {\Ubreve} \defineaccent u u {\ubreve}
+
+\defineaccent v C {\Ccaron} \defineaccent v c {\ccaron}
+\defineaccent v D {\Dcaron} \defineaccent v d {\dcaron}
+\defineaccent v E {\Ecaron} \defineaccent v e {\ecaron}
+\defineaccent v L {\Lcaron} \defineaccent v l {\lcaron}
+\defineaccent v N {\Ncaron} \defineaccent v n {\ncaron}
+\defineaccent v R {\Rcaron} \defineaccent v r {\rcaron}
+\defineaccent v S {\Scaron} \defineaccent v s {\scaron}
+\defineaccent v T {\Tcaron} \defineaccent v t {\tcaron}
+\defineaccent v Z {\Zcaron} \defineaccent v z {\zcaron}
+
+\stopencoding
+
+\startencoding[default]
+
+% vietnamese: if needed, \useencoding[enco-vna]
+
+\stopencoding
+
+% For Tobias Burnus, who wants:
+%
+% \starttypen
+% \setupinteraction[state=start]
+% \setupinteractionscreen[option=bookmark]
+% \placebookmarks[chapter]
+%
+% \starttext \chapter{F\"ur Na\"ive und Na\"\i ve} \stoptext
+% \stoptypen
+
+\startencoding[default]
+
+ \defineaccent " {\i} {\idiaeresis}
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-agr.mkii b/tex/context/base/enco-agr.mkii
new file mode 100644
index 000000000..cfd86dfd3
--- /dev/null
+++ b/tex/context/base/enco-agr.mkii
@@ -0,0 +1,364 @@
+%D \module
+%D [ file=enco-agr,
+%D version=2005.02.20,
+%D title=\CONTEXT\ \UNICODE\ Macros,
+%D subtitle=Ancient Greek,
+%D author=Thomas A. Schmitz,
+%D date=\currentdate]
+
+\startmapping[agr]
+
+ \definecasemaps 13 to 64 lc 0 uc 0
+ \definecasemaps 65 to 66 lc +32 uc 0
+ \definecasemaps 67 to 67 lc 0 uc 0
+ \definecasemaps 68 to 85 lc +32 uc 0
+ \definecasemaps 86 to 86 lc 0 uc 0
+ \definecasemaps 87 to 90 lc +32 uc 0
+ \definecasemaps 91 to 255 lc 0 uc 0
+
+\stopmapping
+
+\startencoding[agr]
+
+\definecharacter greeksigmalunate 1
+\definecharacter endash 2
+\definecharacter emdash 3
+\definecharacter apostrophe 4
+\definecharacter greekaltbeta 5
+\definecharacter epih 6
+
+\definecharacter textbraceleft 8
+\definecharacter textbraceright 9
+\definecharacter textbreve 10
+
+\definecharacter greekSigmalunate 13
+\definecharacter greekIotadialytika 14
+\definecharacter greekUpsilondialytika 15
+
+\definecharacter greekepsilonperispomeni 18
+\definecharacter greekomicronperispomeni 19
+\definecharacter greekepsilondasiaperispomeni 20
+\definecharacter greekomicrondasiaperispomeni 21
+\definecharacter greekepsilonpsiliperispomeni 22
+\definecharacter greekomicronpsiliperispomeni 23
+\definecharacter greekiotadialytikaperispomeni 24
+\definecharacter greekupsilondialytikaperispomeni 25
+\definecharacter greekdialytikaperispomeni 26
+
+\definecharacter textbottomdot 33
+\definecharacter greeksampi 34
+\definecharacter greekdigamma 35
+\definecharacter greekstigma 36
+\definecharacter greeknumkoppa 37
+\definecharacter greekkoppa 38
+\definecharacter guilsingleright 39
+
+\definecharacter textdag 43
+
+\definecharacter greekoxia 47
+
+\definecharacter greekanoteleia 59
+\definecharacter greekdasia 60
+
+\definecharacter greekpsili 62
+\definecharacter greekquestionmark 63
+\definecharacter dialytika 64
+\definecharacter greekAlpha 65
+\definecharacter greekBeta 66
+\definecharacter greekomegaiotasub 67
+\definecharacter greekDelta 68
+\definecharacter greekEpsilon 69
+\definecharacter greekPhi 70
+\definecharacter greekGamma 71
+\definecharacter greekEta 72
+\definecharacter greekIota 73
+\definecharacter greekTheta 74
+\definecharacter greekKappa 75
+\definecharacter greekLambda 76
+\definecharacter greekMu 77
+\definecharacter greekNu 78
+\definecharacter greekOmicron 79
+\definecharacter greekPi 80
+\definecharacter greekChi 81
+\definecharacter greekRho 82
+\definecharacter greekSigma 83
+\definecharacter greekTau 84
+\definecharacter greekUpsilon 85
+\definecharacter greeketaiotasub 86
+\definecharacter greekOmega 87
+\definecharacter greekXi 88
+\definecharacter greekPsi 89
+\definecharacter greekZeta 90
+\definecharacter bracketleft 91
+\definecharacter greekvaria 92
+\definecharacter bracketright 93
+\definecharacter greekperispomeni 94
+
+\definecharacter guilsingleleft 96
+
+% the above is a quote character
+\definecharacter greekalpha 97
+\definecharacter greekbeta 98
+\definecharacter greekfinalsigma 99
+\definecharacter greekdelta 100
+\definecharacter greekepsilon 101
+\definecharacter greekphi 102
+\definecharacter greekgamma 103
+\definecharacter greeketa 104
+\definecharacter greekiota 105
+\definecharacter greektheta 106
+\definecharacter greekkappa 107
+\definecharacter greeklambda 108
+\definecharacter greekmu 109
+\definecharacter greeknu 110
+\definecharacter greekomicron 111
+\definecharacter greekpi 112
+\definecharacter greekchi 113
+\definecharacter greekrho 114
+\definecharacter greeksigma 115
+\definecharacter greektau 116
+\definecharacter greekupsilon 117
+\definecharacter greekalphaiotasub 118
+\definecharacter greekomega 119
+\definecharacter greekxi 120
+\definecharacter greekpsi 121
+\definecharacter greekzeta 122
+\definecharacter floorleft 123
+\definecharacter textbar 124
+\definecharacter floorright 125
+\definecharacter greekperispomeni 126
+
+\definecharacter quotedblleft 128
+\definecharacter quotedblright 129
+\definecharacter exclam 130
+\definecharacter greekiotadasia 131
+\definecharacter greekiotapsili 132
+\definecharacter greekiotaoxia 133
+\definecharacter greekiotadasiatonos 134
+\definecharacter greekiotapsilitonos 135
+\definecharacter greekiotavaria 136
+\definecharacter greekiotadasiavaria 137
+\definecharacter greekiotapsilivaria 138
+\definecharacter greekiotaperispomeni 139
+\definecharacter greekiotadasiaperispomeni 140
+\definecharacter greekiotapsiliperispomeni 141
+\definecharacter greekiotadialytika 142
+\definecharacter greekiotadialytikatonos 143
+\definecharacter greekiotadialytikavaria 144
+\definecharacter greekdasiaperispomeni 145
+\definecharacter greekpsiliperispomeni 146
+\definecharacter greekdasiatonos 147
+\definecharacter greekpsilitonos 148
+\definecharacter greekdasiavaria 149
+\definecharacter greekpsilivaria 150
+\definecharacter greekdialytikatonos 151
+\definecharacter greekepsilondasia 152
+\definecharacter greekepsilonpsili 153
+\definecharacter greekepsilonoxia 154
+\definecharacter greekepsilondasiatonos 155
+\definecharacter greekepsilonpsilitonos 156
+\definecharacter greekepsilonvaria 157
+\definecharacter greekepsilondasiavaria 158
+\definecharacter greekepsilonpsilivaria 159
+\definecharacter greekdialytikavaria 160
+\definecharacter greekalphadasia 161
+\definecharacter greekalphapsili 162
+\definecharacter greekalphaoxia 163
+\definecharacter greekalphadasiatonos 164
+\definecharacter greekalphapsilitonos 165
+\definecharacter greekalphavaria 166
+\definecharacter greekalphadasiavaria 167
+\definecharacter greekalphapsilivaria 168
+\definecharacter greekalphaperispomeni 169
+\definecharacter greekalphadasiaperispomeni 170
+\definecharacter greekalphapsiliperispomeni 171
+\definecharacter greekalphaiotasubdasia 172
+\definecharacter greekalphaiotasubpsili 173
+\definecharacter greekalphaiotasubtonos 174
+\definecharacter greekalphaiotasubdasiatonos 175
+\definecharacter greekalphaiotasubpsilitonos 176
+\definecharacter greekalphaiotasubvaria 177
+\definecharacter greekalphaiotasubdasiavaria 178
+\definecharacter greekalphaiotasubpsilivaria 179
+\definecharacter greekalphaiotasubperispomeni 180
+\definecharacter greekalphaiotasubdasiaperispomeni 181
+\definecharacter greekalphaiotasubpsiliperispomeni 182
+\definecharacter greekrhodasia 183
+\definecharacter greekrhopsili 184
+\definecharacter greeketadasia 185
+\definecharacter greeketapsili 186
+\definecharacter greeketaoxia 187
+\definecharacter greeketadasiatonos 188
+\definecharacter greeketapsilitonos 189
+\definecharacter greeketavaria 190
+\definecharacter greeketadasiavaria 191
+\definecharacter greeketapsilivaria 192
+\definecharacter greeketaperispomeni 193
+\definecharacter greeketadasiaperispomeni 194
+\definecharacter greeketapsiliperispomeni 195
+\definecharacter textslash 196
+\definecharacter greeketaiotasubdasia 197
+\definecharacter greeketaiotasubpsili 198
+\definecharacter greeketaiotasubtonos 199
+\definecharacter greeketaiotasubdasiatonos 200
+\definecharacter greeketaiotasubpsilitonos 201
+\definecharacter greeketaiotasubvaria 202
+\definecharacter greeketaiotasubdasiavaria 203
+\definecharacter greeketaiotasubpsilivaria 204
+\definecharacter greeketaiotasubperispomeni 205
+\definecharacter greeketaiotasubdasiaperispomeni 206
+\definecharacter greeketaiotasubpsiliperispomeni 207
+\definecharacter greekomicrondasia 208
+\definecharacter greekomicronpsili 209
+\definecharacter greekomicronoxia 210
+\definecharacter greekomicrondasiatonos 211
+\definecharacter greekomicronpsilitonos 212
+\definecharacter greekomicronvaria 213
+\definecharacter greekomicrondasiavaria 214
+\definecharacter greekomicronpsilivaria 215
+\definecharacter greekupsilondasia 216
+\definecharacter greekupsilonpsili 217
+\definecharacter greekupsilonoxia 218
+\definecharacter greekupsilondasiatonos 219
+\definecharacter greekupsilonpsilitonos 220
+\definecharacter greekupsilonvaria 221
+\definecharacter greekupsilondasiavaria 222
+\definecharacter greekupsilonpsilivaria 223
+\definecharacter greekupsilonperispomeni 224
+\definecharacter greekupsilondasiaperispomeni 225
+\definecharacter greekupsilonpsiliperispomeni 226
+\definecharacter greekupsilondiaeresis 227
+\definecharacter greekupsilondialytikatonos 228
+\definecharacter greekupsilondialytikavaria 229
+\definecharacter greekomegadasia 230
+\definecharacter greekomegapsili 231
+\definecharacter greekomegaoxia 232
+\definecharacter greekomegadasiatonos 233
+\definecharacter greekomegapsilitonos 234
+\definecharacter greekomegavaria 235
+\definecharacter greekomegadasiavaria 236
+\definecharacter greekomegapsilivaria 237
+\definecharacter greekomegaperispomeni 238
+\definecharacter greekomegadasiaperispomeni 239
+\definecharacter greekomegapsiliperispomeni 240
+\definecharacter greekomegaiotasubdasia 241
+\definecharacter greekomegaiotasubpsili 242
+\definecharacter greekomegaiotasubtonos 243
+\definecharacter greekomegaiotasubdasiatonos 244
+\definecharacter greekomegaiotasubpsilitonos 245
+\definecharacter greekomegaiotasubvaria 246
+\definecharacter greekomegaiotasubdasiavaria 247
+\definecharacter greekomegaiotasubpsilivaria 248
+\definecharacter greekomegaiotasubperispomeni 249
+\definecharacter greekomegaiotasubdasiaperispomeni 250
+\definecharacter greekomegaiotasubpsiliperispomeni 251
+\definecharacter greeknumeralsign 254
+\definecharacter greeknumeralsignlower 255
+
+\stopencoding
+
+\startencoding[default]
+
+\definecharacter greekAlphapsili {\greekpsili \greekAlpha}
+\definecharacter greekAlphadasia {\greekdasia \greekAlpha}
+\definecharacter greekAlphapsilivaria {\greekpsilivaria \greekAlpha}
+\definecharacter greekAlphadasiavaria {\greekdasiavaria \greekAlpha}
+\definecharacter greekAlphapsilitonos {\greekpsilitonos \greekAlpha}
+\definecharacter greekAlphadasiatonos {\greekdasiatonos \greekAlpha}
+\definecharacter greekAlphapsiliperispomeni {\greekpsiliperispomeni \greekAlpha}
+\definecharacter greekAlphadasiaperispomeni {\greekdasiaperispomeni \greekAlpha}
+\definecharacter greekEpsilonpsili {\greekpsili \greekEpsilon}
+\definecharacter greekEpsilondasia {\greekdasia \greekEpsilon}
+\definecharacter greekEpsilonpsilivaria {\greekpsilivaria \greekEpsilon}
+\definecharacter greekEpsilondasiavaria {\greekdasiavaria \greekEpsilon}
+\definecharacter greekEpsilonpsilitonos {\greekpsilitonos \greekEpsilon}
+\definecharacter greekEpsilondasiatonos {\greekdasiatonos \greekEpsilon}
+\definecharacter greekEtapsili {\greekpsili \greekEta}
+\definecharacter greekEtadasia {\greekdasia \greekEta}
+\definecharacter greekEtapsilivaria {\greekpsilivaria \greekEta}
+\definecharacter greekEtadasiavaria {\greekdasiavaria \greekEta}
+\definecharacter greekEtapsilitonos {\greekpsilitonos \greekEta}
+\definecharacter greekEtadasiatonos {\greekdasiatonos \greekEta}
+\definecharacter greekEtapsiliperispomeni {\greekpsiliperispomeni \greekEta}
+\definecharacter greekEtadasiaperispomeni {\greekdasiaperispomeni \greekEta}
+\definecharacter greekIotapsili {\greekpsili \greekIota}
+\definecharacter greekIotadasia {\greekdasia \greekIota}
+\definecharacter greekIotapsilivaria {\greekpsilivaria \greekIota}
+\definecharacter greekIotadasiavaria {\greekdasiavaria \greekIota}
+\definecharacter greekIotapsilitonos {\greekpsilitonos \greekIota}
+\definecharacter greekIotadasiatonos {\greekdasiatonos \greekIota}
+\definecharacter greekIotapsiliperispomeni {\greekpsiliperispomeni \greekIota}
+\definecharacter greekIotadasiaperispomeni {\greekdasiaperispomeni \greekIota}
+\definecharacter greekOmicronpsili {\greekpsili \greekOmicron}
+\definecharacter greekOmicrondasia {\greekdasia \greekOmicron}
+\definecharacter greekOmicronpsilivaria {\greekpsilivaria \greekOmicron}
+\definecharacter greekOmicrondasiavaria {\greekdasiavaria \greekOmicron}
+\definecharacter greekOmicronpsilitonos {\greekpsilitonos \greekOmicron}
+\definecharacter greekOmicrondasiatonos {\greekdasiatonos \greekOmicron}
+\definecharacter greekUpsilondasia {\greekdasia \greekUpsilon}
+\definecharacter greekUpsilondasiavaria {\greekdasiavaria \greekUpsilon}
+\definecharacter greekUpsilondasiatonos {\greekdasiatonos \greekUpsilon}
+\definecharacter greekUpsilondasiaperispomeni {\greekdasiaperispomeni \greekUpsilon}
+\definecharacter greekOmegapsili {\greekpsili \greekOmega}
+\definecharacter greekOmegadasia {\greekdasia \greekOmega}
+\definecharacter greekOmegapsilivaria {\greekpsilivaria \greekOmega}
+\definecharacter greekOmegadasiavaria {\greekdasiavaria \greekOmega}
+\definecharacter greekOmegapsilitonos {\greekpsilitonos \greekOmega}
+\definecharacter greekOmegadasiatonos {\greekdasiatonos \greekOmega}
+\definecharacter greekOmegapsiliperispomeni {\greekpsiliperispomeni \greekOmega}
+\definecharacter greekOmegadasiaperispomeni {\greekdasiaperispomeni \greekOmega}
+\definecharacter greekAlphaiotasubpsili {\greekpsili \greekAlpha \greekiota}
+\definecharacter greekAlphaiotasubdasia {\greekdasia \greekAlpha \greekiota}
+\definecharacter greekAlphaiotasubpsilivaria {\greekpsilivaria \greekAlpha \greekiota}
+\definecharacter greekAlphaiotasubdasiavaria {\greekdasiavaria \greekAlpha \greekiota}
+\definecharacter greekAlphaiotasubpsilitonos {\greekpsilitonos \greekAlpha \greekiota}
+\definecharacter greekAlphaiotasubdasiatonos {\greekdasiatonos \greekAlpha \greekiota}
+\definecharacter greekAlphaiotasubpsiliperispomeni {\greekpsiliperispomeni \greekAlpha \greekiota}
+\definecharacter greekAlphaiotasubdasiaperispomeni {\greekdasiaperispomeni \greekAlpha \greekiota}
+\definecharacter greekEtaiotasubpsili {\greekpsili \greekEta \greekiota}
+\definecharacter greekEtaiotasubdasia {\greekdasia \greekEta \greekiota}
+\definecharacter greekEtaiotasubpsilivaria {\greekpsilivaria \greekEta \greekiota}
+\definecharacter greekEtaiotasubdasiavaria {\greekdasiavaria \greekEta \greekiota}
+\definecharacter greekEtaiotasubpsilitonos {\greekpsilitonos \greekEta \greekiota}
+\definecharacter greekEtaiotasubdasiatonos {\greekdasiatonos \greekEta \greekiota}
+\definecharacter greekEtaiotasubpsiliperispomeni {\greekpsiliperispomeni \greekEta \greekiota}
+\definecharacter greekEtaiotasubdasiaperispomeni {\greekdasiaperispomeni \greekEta \greekiota}
+\definecharacter greekOmegaiotasubpsili {\greekpsili \greekOmega \greekiota}
+\definecharacter greekOmegaiotasubdasia {\greekdasia \greekOmega \greekiota}
+\definecharacter greekOmegaiotasubpsilivaria {\greekpsilivaria \greekOmega \greekiota}
+\definecharacter greekOmegaiotasubdasiavaria {\greekdasiavaria \greekOmega \greekiota}
+\definecharacter greekOmegaiotasubpsilitonos {\greekpsilitonos \greekOmega \greekiota}
+\definecharacter greekOmegaiotasubdasiatonos {\greekdasiatonos \greekOmega \greekiota}
+\definecharacter greekOmegaiotasubpsiliperispomeni {\greekpsiliperispomeni \greekOmega \greekiota}
+\definecharacter greekOmegaiotasubdasiaperispomeni {\greekdasiaperispomeni \greekOmega \greekiota}
+\definecharacter greekAlphavaria {\greekvaria \greekAlpha}
+\definecharacter greekAlphaoxia {\greekoxia \greekAlpha}
+\definecharacter greekAlphaiotasub {\greekAlpha \greekiota}
+\definecharacter greekEpsilonvaria {\greekvaria \greekEpsilon}
+\definecharacter greekEpsilonoxia {\greekoxia \greekEpsilon}
+\definecharacter greekEtavaria {\greekvaria \greekEta}
+\definecharacter greekEtaoxia {\greekoxia \greekEta}
+\definecharacter greekEtaiotasub {\greekEta \greekiota}
+\definecharacter greekIotavaria {\greekvaria \greekIota}
+\definecharacter greekIotaoxia {\greekoxia \greekIota}
+\definecharacter greekUpsilonvaria {\greekvaria \greekUpsilon}
+\definecharacter greekUpsilonoxia {\greekoxia \greekUpsilon}
+\definecharacter greekOmicronvaria {\greekvaria \greekOmicron}
+\definecharacter greekOmicronoxia {\greekoxia \greekOmicron}
+\definecharacter greekOmegavaria {\greekvaria \greekOmega}
+\definecharacter greekOmegaoxia {\greekoxia \greekOmega}
+\definecharacter greekOmegaiotasub {\greekOmega \greekiota}
+\definecharacter greekRhodasia {\greekdasia \greekRho}
+\definecharacter digamma {\greekdigamma}
+\definecharacter sampi {\greeksampi}
+\definecharacter stigma {\greekstigma}
+\definecharacter koppa {\greeknumkoppa}
+\definecharacter lunars {\greeksigmalunate}
+\definecharacter lunarS {\greekSigmalunate}
+\definecharacter halfbraceleft {\floorleft}
+\definecharacter halfbraceright {\floorright}
+\definecharacter crux {\textdag}
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-ans.mkii b/tex/context/base/enco-ans.mkii
new file mode 100644
index 000000000..7a48b5b55
--- /dev/null
+++ b/tex/context/base/enco-ans.mkii
@@ -0,0 +1,237 @@
+%D \module
+%D [ file=enco-ans,
+%D version=2000.05.07, % 1995.01.01,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=\YandY\ texnansi Encoding,
+%D author={Patrick Gundlach, Hans Hagen},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 is \YandY's texnansi encoding vector, which combines
+%D the best of the ansi encoding vector (prebuilt accented
+%D characters etc.) and some of \TEX's vectors.
+
+\startmapping[texnansi]
+
+\resetcaserange 128 to 158
+\resetcaserange 160 to 191
+\resetcaserange 215 to 215
+\resetcaserange 247 to 247
+
+\definecasemaps 192 to 214 lc +32 uc 0
+\definecasemaps 224 to 246 lc 0 uc -32
+\definecasemaps 216 to 222 lc +32 uc 0
+\definecasemaps 248 to 254 lc 0 uc -32
+
+\definecaseself 223
+\definecaseswap 156 140
+\definecaseswap 255 159
+
+% needed by some patterns:
+
+% \definecaseself 34 % quotedbl
+% \definecaseself 132 % quotedblbase
+% \definecaseself 147 % quotedblleft
+% \definecaseself 148 % quotedblright
+% \definecaseself 129 % quotesingle
+% \definecaseself 130 % quotesinglebase
+% \definecaseself 145 % quoteleft
+% \definecaseself 146 % quoteright
+
+\stopmapping
+
+\startencoding[texnansi]
+
+\definecharacter textacute 19
+\definecharacter textbreve 21
+\definecharacter textcaron 20
+\definecharacter textcedilla 184
+\definecharacter textcircumflex 94 % 136
+\definecharacter textdiaeresis 168
+\definecharacter textdotaccent 5
+\definecharacter textgrave 18
+\definecharacter texthungarumlaut 6
+\definecharacter textmacron 175
+\definecharacter textogonek 7
+\definecharacter textring 23
+\definecharacter texttilde 152
+
+\definecharacter dotlessi 16 % 105
+\definecharacter dotlessj 17
+
+\definecharacter endash 150 % lig
+\definecharacter emdash 151 % lig
+
+\definecharacter aeligature 230
+\definecharacter AEligature 198
+\definecharacter oeligature 156
+\definecharacter OEligature 140
+
+\definecharacter ssharp 223
+
+\definecharacter thorn 254
+\definecharacter Thorn 222
+
+\definecharacter Dstroke 208 % also Eth, mapped in enco-def
+\definecharacter eth 240
+
+\definecharacter exclamdown 161
+\definecharacter questiondown 191
+
+\definecharacter copyright 169
+\definecharacter registered 174
+\definecharacter trademark 153
+
+\definecharacter sectionmark 167
+\definecharacter paragraphmark 182
+
+\definecharacter onequarter 188
+\definecharacter onehalf 189
+\definecharacter threequarter 190
+
+\definecharacter onesuperior 185
+\definecharacter twosuperior 178
+\definecharacter threesuperior 179
+
+\definecharacter textcent 162 % ?
+\definecharacter textcurrency 164
+\definecharacter texteuro 1
+\definecharacter textflorin 131
+\definecharacter textsterling 163
+\definecharacter textyen 165
+
+\definecharacter percent 37
+\definecharacter perthousand 137
+
+\definecharacter softhyphen 45
+\definecharacter periodcentered 183
+
+\definecharacter textasciicircum 142
+\definecharacter textasciitilde 158
+\definecharacter textbackslash 92
+\definecharacter textbraceleft 123
+\definecharacter textbar 124
+\definecharacter textbraceright 125
+\definecharacter textunderscore 95
+
+\definecharacter textbrokenbar 166
+\definecharacter textbullet 149
+\definecharacter textdag 134
+\definecharacter textddag 135
+\definecharacter textdegree 176
+\definecharacter textdiv 247
+\definecharacter textellipsis 133
+\definecharacter textfraction 4
+\definecharacter textlognot 172
+\definecharacter textminus 143
+\definecharacter textmu 181
+\definecharacter textmultiply 215
+\definecharacter textpm 177
+
+\definecharacter quotedbl 34
+\definecharacter quotedblbase 132
+\definecharacter quotedblleft 147
+\definecharacter quotedblright 148
+
+\definecharacter quotesingle 129
+\definecharacter quotesinglebase 130
+
+\definecharacter quoteleft 145
+\definecharacter quoteright 146
+
+\definecharacter guilsingleleft 139
+\definecharacter guilsingleright 155
+\definecharacter leftguillemot 171
+\definecharacter rightguillemot 187
+
+\definecharacter aacute 225
+\definecharacter Aacute 193
+\definecharacter eacute 233
+\definecharacter Eacute 201
+\definecharacter iacute 237
+\definecharacter Iacute 205
+\definecharacter oacute 243
+\definecharacter Oacute 211
+\definecharacter uacute 250
+\definecharacter Uacute 218
+\definecharacter yacute 253
+\definecharacter Yacute 221
+
+\definecharacter scaron 154
+\definecharacter Scaron 138
+\definecharacter zcaron 157
+\definecharacter Zcaron 141
+
+\definecharacter ccedilla 231
+\definecharacter Ccedilla 199
+
+\definecharacter acircumflex 226
+\definecharacter Acircumflex 194
+\definecharacter ecircumflex 234
+\definecharacter Ecircumflex 202
+\definecharacter icircumflex 238
+\definecharacter Icircumflex 206
+\definecharacter ocircumflex 244
+\definecharacter Ocircumflex 212
+\definecharacter ucircumflex 251
+\definecharacter Ucircumflex 219
+
+\definecharacter adiaeresis 228
+\definecharacter Adiaeresis 196
+\definecharacter ediaeresis 235
+\definecharacter Ediaeresis 203
+\definecharacter idiaeresis 239
+\definecharacter Idiaeresis 207
+\definecharacter odiaeresis 246
+\definecharacter Odiaeresis 214
+\definecharacter udiaeresis 252
+\definecharacter Udiaeresis 220
+\definecharacter ydiaeresis 255
+\definecharacter Ydiaeresis 159
+
+\definecharacter agrave 224
+\definecharacter Agrave 192
+\definecharacter egrave 232
+\definecharacter Egrave 200
+\definecharacter igrave 236
+\definecharacter Igrave 204
+\definecharacter ograve 242
+\definecharacter Ograve 210
+\definecharacter ugrave 249
+\definecharacter Ugrave 217
+
+\definecharacter aring 229
+\definecharacter Aring 197
+
+\definecharacter Lstroke 128
+\definecharacter lstroke 144
+\definecharacter ostroke 248
+\definecharacter Ostoke 216
+
+\definecharacter atilde 227
+\definecharacter Atilde 195
+\definecharacter ntilde 241
+\definecharacter Ntilde 209
+\definecharacter otilde 245
+\definecharacter Otilde 213
+
+\stopencoding
+
+% will be replaced by math collection, fails anyway
+
+\startencoding[texnansi]
+
+\definecharacter mathgrave "7060
+\definecharacter mathacute "70B4
+\definecharacter mathhat "7088
+\definecharacter mathtilde "7098
+\definecharacter mathddot "70A8
+\definecharacter mathbar "70AF
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-cas.mkii b/tex/context/base/enco-cas.mkii
new file mode 100644
index 000000000..38d12f9fa
--- /dev/null
+++ b/tex/context/base/enco-cas.mkii
@@ -0,0 +1,143 @@
+%D \module
+%D [ file=enco-cas,
+%D version=2005.08.23,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Named Glyph Case Mapping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 For quite some years \CONTEXT\ used a rather compact way of
+%D defining encoded characters as well as case maps. When late
+%D 2000 more advanced remapping features were needed (like pdf
+%D unicode remapping), named glyphs were introduced to keep the
+%D coding tables more readable. At the same time, we introduced
+%D named glyph case mapping.
+
+\defineULcharacter Acircumflex acircumflex
+\defineULcharacter Ccircumflex ccircumflex
+\defineULcharacter Ecircumflex ecircumflex
+\defineULcharacter Gcircumflex gcircumflex
+\defineULcharacter Hcircumflex hcircumflex
+\defineULcharacter Icircumflex icircumflex
+\defineULcharacter Jcircumflex jcircumflex
+\defineULcharacter Ocircumflex ocircumflex
+\defineULcharacter Scircumflex scircumflex
+\defineULcharacter Ucircumflex ucircumflex
+\defineULcharacter Wcircumflex wcircumflex
+\defineULcharacter Ycircumflex ycircumflex
+
+\defineULcharacter Agrave agrave
+\defineULcharacter Egrave egrave
+\defineULcharacter Igrave igrave
+\defineULcharacter Ograve ograve
+\defineULcharacter Ugrave ugrave
+\defineULcharacter Ygrave ygrave
+
+\defineULcharacter Atilde atilde
+\defineULcharacter Itilde itilde
+\defineULcharacter Otilde otilde
+\defineULcharacter Ntilde ntilde
+\defineULcharacter Utilde utilde
+
+\defineULcharacter Adiaeresis adiaeresis
+\defineULcharacter Ediaeresis ediaeresis
+\defineULcharacter Idiaeresis idiaeresis
+\defineULcharacter Odiaeresis odiaeresis
+\defineULcharacter Udiaeresis udiaeresis
+\defineULcharacter Ydiaeresis ydiaeresis
+
+\defineULcharacter Aacute aacute
+\defineULcharacter Cacute cacute
+\defineULcharacter Eacute eacute
+\defineULcharacter Iacute iacute
+\defineULcharacter Lacute lacute
+\defineULcharacter Nacute nacute
+\defineULcharacter Oacute oacute
+\defineULcharacter Racute racute
+\defineULcharacter Sacute sacute
+\defineULcharacter Uacute uacute
+\defineULcharacter Yacute yacute
+\defineULcharacter Zacute zacute
+
+\defineULcharacter Dstroke dstroke
+\defineULcharacter Hstroke hstroke
+\defineULcharacter Lstroke lstroke
+\defineULcharacter Lslash lslash
+\defineULcharacter Ostroke ostroke
+\defineULcharacter Tstroke tstroke
+
+\defineULcharacter Cdotaccent cdotaccent
+\defineULcharacter Edotaccent edotaccent
+\defineULcharacter Gdotaccent gdotaccent
+\defineULcharacter Idotaccent idotaccent
+\defineULcharacter Zdotaccent zdotaccent
+
+\defineULcharacter Amacron amacron
+\defineULcharacter Emacron emacron
+\defineULcharacter Imacron imacron
+\defineULcharacter Omacron omacron
+\defineULcharacter Umacron umacron
+
+\defineULcharacter Ccedilla ccedilla
+\defineULcharacter Gcedilla gcedilla
+\defineULcharacter Kcedilla kcedilla
+\defineULcharacter Lcedilla lcedilla
+\defineULcharacter Ncedilla ncedilla
+\defineULcharacter Rcedilla rcedilla
+\defineULcharacter Scedilla scedilla
+\defineULcharacter Tcedilla tcedilla
+
+\defineULcharacter Ccommaaccent ccommaaccent
+\defineULcharacter Gcommaaccent gcommaaccent
+\defineULcharacter Kcommaaccent kcommaaccent
+\defineULcharacter Lcommaaccent lcommaaccent
+\defineULcharacter Ncommaaccent ncommaaccent
+\defineULcharacter Rcommaaccent rcommaaccent
+\defineULcharacter Scommaaccent scommaaccent
+\defineULcharacter Tcommaaccent tcommaaccent
+
+\defineULcharacter Ohungarumlaut ohungarumlaut
+\defineULcharacter Uhungarumlaut uhungarumlaut
+
+\defineULcharacter Aogonek aogonek
+\defineULcharacter Eogonek eogonek
+\defineULcharacter Iogonek iogonek
+\defineULcharacter Uogonek uogonek
+
+\defineULcharacter Aring aring
+\defineULcharacter Uring uring
+
+\defineULcharacter Abreve abreve
+\defineULcharacter Ebreve ebreve
+\defineULcharacter Gbreve gbreve
+\defineULcharacter Ibreve ibreve
+\defineULcharacter Obreve obreve
+\defineULcharacter Ubreve ubreve
+
+\defineULcharacter Ccaron ccaron
+\defineULcharacter Dcaron dcaron
+\defineULcharacter Ecaron ecaron
+\defineULcharacter Lcaron lcaron
+\defineULcharacter Ncaron ncaron
+\defineULcharacter Rcaron rcaron
+\defineULcharacter Scaron scaron
+\defineULcharacter Tcaron tcaron
+\defineULcharacter Zcaron zcaron
+
+\defineULcharacter dotlessI dotlessi
+\defineULcharacter dotlessJ dotlessj
+
+\defineULcharacter AEligature aeligature
+\defineULcharacter OEligature oeligature
+\defineULcharacter Ssharp ssharp
+\defineULcharacter IJligature ijligature
+
+\defineULcharacter Eth eth
+\defineULcharacter Thorn thorn
+
+\endinput
diff --git a/tex/context/base/enco-chi.mkii b/tex/context/base/enco-chi.mkii
new file mode 100644
index 000000000..9d77893a0
--- /dev/null
+++ b/tex/context/base/enco-chi.mkii
@@ -0,0 +1,371 @@
+%D \module
+%D [ file=enco-chi,
+%D version=1999.12.02,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Traditional and Simplified Chinese,
+%D author={Wang Lei \& Hans Hagen},
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% actually this is also a filter -> enco-fcn.tex
+
+%D This is an experimental definition. Since we are dealing
+%D with unicode's, the registered values are not saved, so
+%D actually we're dealing with an pseudo encoding. The digits
+%D on the other hand are encoding specific.
+
+% chinese classes: left=1|right=2|center=3
+
+% untested, probably wrong
+
+\startencoding[cjk-uni]
+
+\defineuclass 1 32 24
+\defineuclass 1 32 28
+\defineuclass 1 48 20
+\defineuclass 1 48 8
+\defineuclass 1 48 10
+\defineuclass 1 48 12
+\defineuclass 1 48 14
+\defineuclass 1 48 22
+\defineuclass 1 48 16
+\defineuclass 1 255 8
+\defineuclass 1 255 59
+\defineuclass 1 255 64
+\defineuclass 1 255 91
+
+\defineuclass 3 0 183
+\defineuclass 3 0 168
+\defineuclass 3 32 38
+\defineuclass 3 255 30
+
+\defineuclass 2 48 1
+\defineuclass 2 48 2
+\defineuclass 2 32 20
+\defineuclass 2 255 94
+\defineuclass 2 32 25
+\defineuclass 2 32 29
+\defineuclass 2 48 21
+\defineuclass 2 48 9
+\defineuclass 2 48 11
+\defineuclass 2 48 13
+\defineuclass 2 48 15
+\defineuclass 2 48 23
+\defineuclass 2 48 17
+\defineuclass 2 34 55
+\defineuclass 2 0 176
+\defineuclass 2 32 50
+\defineuclass 2 32 51
+\defineuclass 2 255 1
+\defineuclass 2 255 2
+\defineuclass 2 255 7
+\defineuclass 2 255 9
+\defineuclass 2 255 12
+\defineuclass 2 255 14
+\defineuclass 2 255 26
+\defineuclass 2 255 27
+\defineuclass 2 255 31
+\defineuclass 2 255 61
+\defineuclass 2 255 93
+
+\defineudigit 0 37 203
+\defineudigit 1 78 0
+\defineudigit 2 78 140
+\defineudigit 3 78 9
+\defineudigit 4 86 219
+\defineudigit 5 78 148
+\defineudigit 6 81 109
+\defineudigit 7 78 3
+\defineudigit 8 81 107
+\defineudigit 9 78 93
+\defineudigit 10 83 65
+\defineudigit 100 118 126
+\defineudigit 1000 83 67
+\defineudigit 10000 78 7
+\defineudigit 100000000 78 191
+
+\defineudigit 0* 150 246
+\defineudigit 1* 88 249
+\defineudigit 2* 141 48
+\defineudigit 3* 83 193
+\defineudigit 4* 128 134
+\defineudigit 5* 79 13
+\defineudigit 6* 150 70
+\defineudigit 7* 103 210
+\defineudigit 8* 99 76
+\defineudigit 9* 115 150
+\defineudigit 10* 98 254
+\defineudigit 100* 79 112
+\defineudigit 1000* 78 223
+\defineudigit 10000* 132 44
+\defineudigit 100000000* 78 191
+
+\defineudigit 20 94 255
+\defineudigit 21 78 0
+\defineudigit 22 78 140
+\defineudigit 23 78 9
+\defineudigit 24 86 219
+\defineudigit 25 78 148
+\defineudigit 26 81 109
+\defineudigit 27 78 3
+\defineudigit 28 81 107
+\defineudigit 29 78 93
+
+\defineudigit 30 83 69
+\defineudigit 31 78 0
+\defineudigit 32 78 140
+\defineudigit 33 78 9
+\defineudigit 34 86 219
+\defineudigit 35 78 148
+\defineudigit 36 81 109
+\defineudigit 37 78 3
+\defineudigit 38 81 107
+\defineudigit 39 78 93
+
+\stopencoding
+
+% \doif \currentregime {utf} \endinput
+
+\startencoding[big5]
+
+\defineuclass 1 161 93
+\defineuclass 1 161 95
+\defineuclass 1 161 97
+\defineuclass 1 161 99
+\defineuclass 1 161 101
+\defineuclass 1 161 103
+\defineuclass 1 161 105
+\defineuclass 1 161 107
+\defineuclass 1 161 111
+\defineuclass 1 161 111
+\defineuclass 1 161 113
+\defineuclass 1 161 115
+\defineuclass 1 161 117
+\defineuclass 1 161 119
+\defineuclass 1 161 121
+\defineuclass 1 161 123
+\defineuclass 1 161 125
+\defineuclass 1 161 161
+\defineuclass 1 161 163
+\defineuclass 1 161 165
+\defineuclass 1 161 167
+\defineuclass 1 161 169
+\defineuclass 1 161 171
+
+\defineuclass 3 161 69
+\defineuclass 3 161 75
+\defineuclass 3 161 76
+
+\defineuclass 2 161 65
+\defineuclass 2 161 66
+\defineuclass 2 161 67
+\defineuclass 2 161 68
+\defineuclass 2 161 70
+\defineuclass 2 161 71
+\defineuclass 2 161 72
+\defineuclass 2 161 73
+\defineuclass 2 161 74
+\defineuclass 2 161 77
+\defineuclass 2 161 78
+\defineuclass 2 161 79
+\defineuclass 2 161 80
+\defineuclass 2 161 81
+\defineuclass 2 161 82
+\defineuclass 2 161 83
+\defineuclass 2 161 84
+\defineuclass 2 161 88
+\defineuclass 2 161 94
+\defineuclass 2 161 96
+\defineuclass 2 161 98
+\defineuclass 2 161 100
+\defineuclass 2 161 102
+\defineuclass 2 161 104
+\defineuclass 2 161 106
+\defineuclass 2 161 108
+\defineuclass 2 161 110
+\defineuclass 2 161 112
+\defineuclass 2 161 114
+\defineuclass 2 161 116
+\defineuclass 2 161 118
+\defineuclass 2 161 120
+\defineuclass 2 161 122
+\defineuclass 2 161 124
+\defineuclass 2 161 126
+\defineuclass 2 161 162
+\defineuclass 2 161 164
+\defineuclass 2 161 166
+\defineuclass 2 161 168
+\defineuclass 2 161 170
+\defineuclass 2 161 172
+\defineuclass 2 161 196
+\defineuclass 2 161 227
+\defineuclass 2 162 88
+\defineuclass 2 163 223
+
+\defineudigit 0 162 179
+\defineudigit 1 164 64
+\defineudigit 2 164 71
+\defineudigit 3 164 84
+\defineudigit 4 165 124
+\defineudigit 5 164 173
+\defineudigit 6 164 187
+\defineudigit 7 164 67
+\defineudigit 8 164 75
+\defineudigit 9 164 69
+\defineudigit 10 164 81
+\defineudigit 100 166 202
+\defineudigit 1000 164 100
+\defineudigit 10000 201 69
+\defineudigit 100000000 187 245
+
+\defineudigit 0* 185 115
+\defineudigit 1* 179 252
+\defineudigit 2* 182 76
+\defineudigit 3* 176 209
+\defineudigit 4* 184 118
+\defineudigit 5* 165 238
+\defineudigit 6* 179 176
+\defineudigit 7* 172 110
+\defineudigit 8* 174 195
+\defineudigit 9* 168 104
+\defineudigit 10* 172 66
+\defineudigit 100* 168 213
+\defineudigit 1000* 165 97
+\defineudigit 10000* 184 85
+\defineudigit 100000000* 187 245
+
+\defineudigit 20 164 220
+\defineudigit 21 164 64
+\defineudigit 22 164 71
+\defineudigit 23 164 84
+\defineudigit 24 165 124
+\defineudigit 25 164 173
+\defineudigit 26 164 187
+\defineudigit 27 164 67
+\defineudigit 28 164 75
+\defineudigit 29 164 69
+
+\defineudigit 30 164 202
+\defineudigit 31 164 64
+\defineudigit 32 164 71
+\defineudigit 33 164 84
+\defineudigit 34 165 124
+\defineudigit 35 164 173
+\defineudigit 36 164 187
+\defineudigit 37 164 67
+\defineudigit 38 164 75
+\defineudigit 39 164 69
+
+\stopencoding
+
+\startencoding[gbk]
+
+\defineuclass 1 161 174
+\defineuclass 1 161 176
+\defineuclass 1 161 178
+\defineuclass 1 161 180
+\defineuclass 1 161 182
+\defineuclass 1 161 184
+\defineuclass 1 161 186
+\defineuclass 1 161 188
+\defineuclass 1 161 190
+\defineuclass 1 163 168
+\defineuclass 1 163 219
+\defineuclass 1 163 224
+\defineuclass 1 163 251
+
+\defineuclass 3 161 164
+\defineuclass 3 161 167
+\defineuclass 3 161 173
+\defineuclass 3 163 190
+
+\defineuclass 2 161 162
+\defineuclass 2 161 163
+\defineuclass 2 161 170
+\defineuclass 2 161 171
+\defineuclass 2 161 175
+\defineuclass 2 161 177
+\defineuclass 2 161 179
+\defineuclass 2 161 181
+\defineuclass 2 161 183
+\defineuclass 2 161 185
+\defineuclass 2 161 187
+\defineuclass 2 161 189
+\defineuclass 2 161 191
+\defineuclass 2 161 203
+\defineuclass 2 161 227
+\defineuclass 2 161 228
+\defineuclass 2 161 229
+\defineuclass 2 163 161
+\defineuclass 2 163 162
+\defineuclass 2 163 167
+\defineuclass 2 163 169
+\defineuclass 2 163 172
+\defineuclass 2 163 174
+\defineuclass 2 163 186
+\defineuclass 2 163 187
+\defineuclass 2 163 191
+\defineuclass 2 163 221
+\defineuclass 2 163 253
+
+\defineudigit 0 161 240
+\defineudigit 1 210 187
+\defineudigit 2 182 254
+\defineudigit 3 200 253
+\defineudigit 4 203 196
+\defineudigit 5 206 229
+\defineudigit 6 193 249
+\defineudigit 7 198 223
+\defineudigit 8 176 203
+\defineudigit 9 190 197
+\defineudigit 10 202 174
+\defineudigit 100 176 217
+\defineudigit 1000 199 167
+\defineudigit 10000 205 242
+\defineudigit 100000000 210 218
+
+\defineudigit 0* 193 227
+\defineudigit 1* 210 188
+\defineudigit 2* 183 161
+\defineudigit 3* 200 254
+\defineudigit 4* 203 193
+\defineudigit 5* 206 233
+\defineudigit 6* 194 189
+\defineudigit 7* 198 226
+\defineudigit 8* 176 198
+\defineudigit 9* 190 193
+\defineudigit 10* 202 176
+\defineudigit 100* 176 219
+\defineudigit 1000* 199 170
+\defineudigit 10000* 200 102
+\defineudigit 100000000* 210 218
+
+\defineudigit 20 216 165
+\defineudigit 21 210 187
+\defineudigit 22 182 254
+\defineudigit 23 200 253
+\defineudigit 24 203 196
+\defineudigit 25 206 229
+\defineudigit 26 193 249
+\defineudigit 27 198 223
+\defineudigit 28 176 203
+\defineudigit 29 190 197
+
+\defineudigit 30 216 166
+\defineudigit 31 210 187
+\defineudigit 32 182 254
+\defineudigit 33 200 253
+\defineudigit 34 203 196
+\defineudigit 35 206 229
+\defineudigit 36 193 249
+\defineudigit 37 198 223
+\defineudigit 38 176 203
+\defineudigit 39 190 197
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-com.mkii b/tex/context/base/enco-com.mkii
new file mode 100644
index 000000000..42d0d4774
--- /dev/null
+++ b/tex/context/base/enco-com.mkii
@@ -0,0 +1,37 @@
+%D \module
+%D [ file=enco-com,
+%D version=2000.20.12, % split from base file
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Composed Characters Commands,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen \& Ton Otten]
+%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 Here we map some \quote {short} names onto the more
+%D verbose glyph names.
+
+\def\AA{\Aring}
+\def\aa{\aring}
+\def\AE{\AEligature}
+\def\ae{\aeligature}
+\def\CC{\Ccedilla}
+\def\cc{\ccedilla}
+\def \L{\Lstroke}
+\def \l{\lstroke}
+\def \O{\Ostroke}
+\def \o{\ostroke}
+\def\OE{\OEligature}
+\def\oe{\oeligature}
+\def\SZ{\Ssharp}
+\def\sz{\ssharp}
+\def\SS{\ssharp}
+\def\IJ{\IJligature}
+\def\ij{\ijligature}
+\def \i{\dotlessi}
+\def \j{\dotlessj}
+
+\endinput
diff --git a/tex/context/base/enco-cyr.mkii b/tex/context/base/enco-cyr.mkii
new file mode 100644
index 000000000..36bca82b5
--- /dev/null
+++ b/tex/context/base/enco-cyr.mkii
@@ -0,0 +1,1037 @@
+%D \module
+%D [ file=enco-cyr,
+%D version=2003.01.24,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Cyrillic,
+%D author=...,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 following kerning test is inspired by a test file
+%D provided by Victor Figurnov. I hope he still recognizes
+%D some bit and pieces.
+%D
+%D \starttyping
+%D \setupoutput[pdftex]
+%D
+%D \startMPenvironment[global]
+%D \useregime[cyr]
+%D \useencoding[cyr]
+%D \mainlanguage[ru]
+%D \enableregime[cp1251]
+%D \setupbodyfont[cyr]
+%D \stopMPenvironment
+%D
+%D \startbuffer
+%D \starttabulate[|l|l|l|]
+%D \NC \ruledhbox{} \NC \ruledhbox{AV} \NC with kerning \NC \NR
+%D \NC \ruledhbox{{}{}} \NC \ruledhbox{A{}V} \NC without kerning \NC \NR
+%D \NC \ruledhbox{\tfd } \NC \ruledhbox{\tfd AV} \NC with kerning \NC \NR
+%D \NC \ruledhbox{\tfd {}{}} \NC \ruledhbox{\tfd A{}V} \NC without kerning \NC \NR
+%D \stoptabulate
+%D
+%D \showkerning{ }
+%D \stopbuffer
+%D
+%D \starttext
+%D
+%D \title{Kerning test}
+%D
+%D \typebuffer
+%D
+%D \rm \subject{Serif font} \getbuffer
+%D \ss \subject{SansSerif font} \getbuffer
+%D \tt \subject{MonoSpacec font} \getbuffer
+%D
+%D \stoptext
+%D \stoptyping
+
+%D We start with a fallback, define by HH, who assumes that
+%D this is phonetic.
+
+\startmapping[t2a]
+
+\resetcaserange 128 to 255
+
+\definecasemaps 192 to 223 lc +32 uc 0 % base letters (russian)
+\definecasemaps 224 to 255 lc 0 uc -32
+
+\definecasemaps 128 to 156 lc +32 uc 0 % extra letters (cyrillic and old-slav)
+\definecasemaps 160 to 188 lc 0 uc -32
+
+\definecasemap 73 105 73 \definecasemap 105 105 73 % cyrillicII
+\definecasemap 74 106 74 \definecasemap 106 106 74 % cyrillicJE
+\definecasemap 81 113 81 \definecasemap 113 113 81 % cyrillicQ
+\definecasemap 87 119 87 \definecasemap 119 119 87 % cyrillicW
+
+\stopmapping
+
+\startencoding[t2a]
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter texthungarumlaut 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter textogonek 12
+
+\definecharacter textcyrillicflex 18
+\definecharacter textdblgrave 19
+\definecharacter textcyrillicbreve 20
+
+\definecharacter endash 21
+\definecharacter emdash 22
+
+\definecharacter textcompwordmark 23
+\definecharacter textbackslash 92
+\definecharacter textasciicircum 94
+\definecharacter textunderscore 95
+\definecharacter textbraceleft 123
+\definecharacter textbraceright 125
+\definecharacter textasciitilde 126
+\definecharacter textnumero 157
+\definecharacter textcurrency 158
+\definecharacter sectionmark 159
+
+\definecharacter quotedbl 34
+\definecharacter quoteleft 96
+\definecharacter upperleftsingleninequote 39
+\definecharacter quotedblleft 16
+\definecharacter quotedblright 17
+\definecharacter lowerleftdoubleninequote 189
+\definecharacter upperrightdoublesixquote 16
+\definecharacter upperrightdoubleninequote 17
+\definecharacter quotedblbase 189
+
+\definecharacter cyrillicpalochka 13
+\definecharacter cyrilliclangle 14
+\definecharacter cyrillicrangle 15
+
+\definecharacter leftguillemot 190
+\definecharacter rightguillemot 191
+\definecharacter dotlessi 25
+
+\definecharacter cyrillicA 192
+\definecharacter cyrillica 224
+\definecharacter cyrillicB 193
+\definecharacter cyrillicb 225
+\definecharacter cyrillicV 194
+\definecharacter cyrillicv 226
+\definecharacter cyrillicG 195
+\definecharacter cyrillicg 227
+\definecharacter cyrillicD 196
+\definecharacter cyrillicd 228
+\definecharacter cyrillicE 197
+\definecharacter cyrillice 229
+\definecharacter cyrillicZH 198
+\definecharacter cyrilliczh 230
+\definecharacter cyrillicZ 199
+\definecharacter cyrillicz 231
+\definecharacter cyrillicI 200
+\definecharacter cyrillici 232
+\definecharacter cyrillicISHRT 201
+\definecharacter cyrillicishrt 233
+\definecharacter cyrillicK 202
+\definecharacter cyrillick 234
+\definecharacter cyrillicL 203
+\definecharacter cyrillicl 235
+\definecharacter cyrillicM 204
+\definecharacter cyrillicm 236
+\definecharacter cyrillicN 205
+\definecharacter cyrillicn 237
+\definecharacter cyrillicO 206
+\definecharacter cyrillico 238
+\definecharacter cyrillicP 207
+\definecharacter cyrillicp 239
+\definecharacter cyrillicR 208
+\definecharacter cyrillicr 240
+\definecharacter cyrillicS 209
+\definecharacter cyrillics 241
+\definecharacter cyrillicT 210
+\definecharacter cyrillict 242
+\definecharacter cyrillicU 211
+\definecharacter cyrillicu 243
+\definecharacter cyrillicF 212
+\definecharacter cyrillicf 244
+\definecharacter cyrillicH 213
+\definecharacter cyrillich 245
+\definecharacter cyrillicC 214
+\definecharacter cyrillicc 246
+\definecharacter cyrillicCH 215
+\definecharacter cyrillicch 247
+\definecharacter cyrillicSH 216
+\definecharacter cyrillicsh 248
+\definecharacter cyrillicSHCH 217
+\definecharacter cyrillicshch 249
+\definecharacter cyrillicHRDSN 218
+\definecharacter cyrillichrdsn 250
+\definecharacter cyrillicERY 219
+\definecharacter cyrillicery 251
+\definecharacter cyrillicSFTSN 220
+\definecharacter cyrillicsftsn 252
+\definecharacter cyrillicEREV 221
+\definecharacter cyrillicerev 253
+\definecharacter cyrillicYU 222
+\definecharacter cyrillicyu 254
+\definecharacter cyrillicYA 223
+\definecharacter cyrillicya 255
+\definecharacter cyrillicGUP 128
+\definecharacter cyrillicgup 160
+\definecharacter cyrillicGHCRS 129
+\definecharacter cyrillicghcrs 161
+\definecharacter cyrillicDJE 130
+\definecharacter cyrillicdje 162
+\definecharacter cyrillicTSHE 131
+\definecharacter cyrillictshe 163
+\definecharacter cyrillicSHHA 132
+\definecharacter cyrillicshha 164
+\definecharacter cyrillicZHDSC 133
+\definecharacter cyrilliczhdsc 165
+\definecharacter cyrillicZDSC 134
+\definecharacter cyrilliczdsc 166
+\definecharacter cyrillicLJE 135
+\definecharacter cyrilliclje 167
+\definecharacter cyrillicYI 136
+\definecharacter cyrillicyi 168
+\definecharacter cyrillicKDSC 137
+\definecharacter cyrillickdsc 169
+\definecharacter cyrillicKBEAK 138
+\definecharacter cyrillickbeak 170
+\definecharacter cyrillicKVCRS 139
+\definecharacter cyrillickvcrs 171
+\definecharacter cyrillicAE 140
+\definecharacter cyrillicae 172
+\definecharacter cyrillicNDSC 141
+\definecharacter cyrillicndsc 173
+\definecharacter cyrillicNG 142
+\definecharacter cyrillicng 174
+\definecharacter cyrillicDZE 143
+\definecharacter cyrillicdze 175
+\definecharacter cyrillicOTLD 144
+\definecharacter cyrillicotld 176
+\definecharacter cyrillicSDSC 145
+\definecharacter cyrillicsdsc 177
+\definecharacter cyrillicUSHRT 146
+\definecharacter cyrillicushrt 178
+\definecharacter cyrillicY 147
+\definecharacter cyrillicy 179
+\definecharacter cyrillicYHCRS 148
+\definecharacter cyrillicyhcrs 180
+\definecharacter cyrillicHDSC 149
+\definecharacter cyrillichdsc 181
+\definecharacter cyrillicDZHE 150
+\definecharacter cyrillicdzhe 182
+\definecharacter cyrillicCHVCRS 151
+\definecharacter cyrillicchvcrs 183
+\definecharacter cyrillicCHRDSC 152
+\definecharacter cyrillicchrdsc 184
+\definecharacter cyrillicIE 153
+\definecharacter cyrillicie 185
+\definecharacter cyrillicSCHWA 154
+\definecharacter cyrillicschwa 186
+\definecharacter cyrillicNJE 155
+\definecharacter cyrillicnje 187
+\definecharacter cyrillicYO 156
+\definecharacter cyrillicyo 188
+\definecharacter cyrillicII 73
+\definecharacter cyrillicii 105
+\definecharacter cyrillicJE 74
+\definecharacter cyrillicje 106
+\definecharacter cyrillicQ 81
+\definecharacter cyrillicq 113
+\definecharacter cyrillicW 87
+\definecharacter cyrillicw 119
+
+% \definecharacter textperthousand {\%\char 24 }
+% \definecharacter textpertenthousand {\%\char 24\char 24 }
+
+\definecharacter cyrillicgheupturn 160 % to satisfy the patterns
+
+\stopencoding
+
+\startmapping[t2b]
+
+\resetcaserange 128 to 255
+
+\definecasemaps 192 to 223 lc +32 uc 0 % base letters (russian)
+\definecasemaps 224 to 255 lc 0 uc -32
+
+\definecasemaps 128 to 156 lc +32 uc 0 % extra letters (cyrillic and old-slav)
+\definecasemaps 160 to 188 lc 0 uc -32
+
+\definecasemap 73 105 73 \definecasemap 105 105 73 % cyrillicII
+\definecasemap 74 106 74 \definecasemap 106 106 74 % cyrillicJE
+\definecasemap 81 113 81 \definecasemap 113 113 81 % cyrillicQ
+\definecasemap 83 115 83 \definecasemap 115 115 83 % cyrillicDZE
+\definecasemap 87 119 87 \definecasemap 119 119 87 % cyrillicW
+
+\stopmapping
+
+\startencoding[t2b]
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter texthungarumlaut 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter textogonek 12
+
+\definecharacter textcyrillicflex 18
+\definecharacter textdblgrave 19
+\definecharacter textcyrillicbreve 20
+
+\definecharacter endash 21
+\definecharacter emdash 22
+
+\definecharacter textcompwordmark 23
+\definecharacter textbackslash 92
+\definecharacter textasciicircum 94
+\definecharacter textunderscore 95
+\definecharacter textbraceleft 123
+\definecharacter textbraceright 125
+\definecharacter textasciitilde 126
+\definecharacter textnumero 157
+\definecharacter textcurrency 158
+\definecharacter sectionmark 159
+\definecharacter quotedbl 34
+\definecharacter quoteleft 96
+\definecharacter upperleftsingleninequote 39
+\definecharacter quotedblleft 16
+\definecharacter quotedblright 17
+\definecharacter lowerleftdoubleninequote 189
+
+\definecharacter upperrightdoublesixquote 16
+\definecharacter upperrightdoubleninequote 17
+\definecharacter quotedblbase 189
+
+\definecharacter cyrillicpalochka 13
+\definecharacter cyrilliclangle 14
+\definecharacter cyrillicrangle 15
+
+\definecharacter leftguillemot 190
+\definecharacter rightguillemot 191
+\definecharacter dotlessi 25
+
+\definecharacter cyrillicA 192
+\definecharacter cyrillica 224
+\definecharacter cyrillicB 193
+\definecharacter cyrillicb 225
+\definecharacter cyrillicV 194
+\definecharacter cyrillicv 226
+\definecharacter cyrillicG 195
+\definecharacter cyrillicg 227
+\definecharacter cyrillicD 196
+\definecharacter cyrillicd 228
+\definecharacter cyrillicE 197
+\definecharacter cyrillice 229
+\definecharacter cyrillicZH 198
+\definecharacter cyrilliczh 230
+\definecharacter cyrillicZ 199
+\definecharacter cyrillicz 231
+\definecharacter cyrillicI 200
+\definecharacter cyrillici 232
+\definecharacter cyrillicISHRT 201
+\definecharacter cyrillicishrt 233
+\definecharacter cyrillicK 202
+\definecharacter cyrillick 234
+\definecharacter cyrillicL 203
+\definecharacter cyrillicl 235
+\definecharacter cyrillicM 204
+\definecharacter cyrillicm 236
+\definecharacter cyrillicN 205
+\definecharacter cyrillicn 237
+\definecharacter cyrillicO 206
+\definecharacter cyrillico 238
+\definecharacter cyrillicP 207
+\definecharacter cyrillicp 239
+\definecharacter cyrillicR 208
+\definecharacter cyrillicr 240
+\definecharacter cyrillicS 209
+\definecharacter cyrillics 241
+\definecharacter cyrillicT 210
+\definecharacter cyrillict 242
+\definecharacter cyrillicU 211
+\definecharacter cyrillicu 243
+\definecharacter cyrillicF 212
+\definecharacter cyrillicf 244
+\definecharacter cyrillicH 213
+\definecharacter cyrillich 245
+\definecharacter cyrillicC 214
+\definecharacter cyrillicc 246
+\definecharacter cyrillicCH 215
+\definecharacter cyrillicch 247
+\definecharacter cyrillicSH 216
+\definecharacter cyrillicsh 248
+\definecharacter cyrillicSHCH 217
+\definecharacter cyrillicshch 249
+\definecharacter cyrillicHRDSN 218
+\definecharacter cyrillichrdsn 250
+\definecharacter cyrillicERY 219
+\definecharacter cyrillicery 251
+\definecharacter cyrillicSFTSN 220
+\definecharacter cyrillicsftsn 252
+\definecharacter cyrillicEREV 221
+\definecharacter cyrillicerev 253
+\definecharacter cyrillicYU 222
+\definecharacter cyrillicyu 254
+\definecharacter cyrillicYA 223
+\definecharacter cyrillicya 255
+\definecharacter cyrillicGDSCHCRS 128
+\definecharacter cyrillicgdschcrs 160
+\definecharacter cyrillicGHCRS 129
+\definecharacter cyrillicghcrs 161
+\definecharacter cyrillicGDSC 130
+\definecharacter cyrillicgdsc 162
+\definecharacter cyrillicGHK 131
+\definecharacter cyrillicghk 163
+\definecharacter cyrillicSHHA 132
+\definecharacter cyrillicshha 164
+\definecharacter cyrillicZHDSC 133
+\definecharacter cyrilliczhdsc 165
+\definecharacter cyrillicDELTA 134
+\definecharacter cyrillicdelta 166
+\definecharacter cyrillicABHDZE 135
+\definecharacter cyrillicabhdze 167
+\definecharacter cyrillicLJE 136
+\definecharacter cyrilliclje 168
+\definecharacter cyrillicKDSC 137
+\definecharacter cyrillickdsc 169
+\definecharacter cyrillicLDSC 138
+\definecharacter cyrillicldsc 170
+\definecharacter cyrillicKHK 139
+\definecharacter cyrillickhk 171
+\definecharacter cyrillicLHK 140
+\definecharacter cyrilliclhk 172
+\definecharacter cyrillicNDSC 141
+\definecharacter cyrillicndsc 173
+\definecharacter cyrillicNG 142
+\definecharacter cyrillicng 174
+\definecharacter cyrillicNHK 143
+\definecharacter cyrillicnhk 175
+\definecharacter cyrillicOTLD 144
+\definecharacter cyrillicotld 176
+\definecharacter cyrillicSACRS 145
+\definecharacter cyrillicsacrs 177
+\definecharacter cyrillicUSHRT 146
+\definecharacter cyrillicushrt 178
+\definecharacter cyrillicY 147
+\definecharacter cyrillicy 179
+\definecharacter cyrillicHHCRS 148
+\definecharacter cyrillichhcrs 180
+\definecharacter cyrillicHDSC 149
+\definecharacter cyrillichdsc 181
+\definecharacter cyrillicHHK 150
+\definecharacter cyrillichhk 182
+\definecharacter cyrillicCHLDSC 151
+\definecharacter cyrillicchldsc 183
+\definecharacter cyrillicCHRDSC 152
+\definecharacter cyrillicchrdsc 184
+\definecharacter cyrillicNJE 153
+\definecharacter cyrillicnje 185
+\definecharacter cyrillicSCHWA 154
+\definecharacter cyrillicschwa 186
+\definecharacter cyrillicEPS 155
+\definecharacter cyrilliceps 187
+\definecharacter cyrillicYO 156
+\definecharacter cyrillicyo 188
+\definecharacter cyrillicII 73
+\definecharacter cyrillicii 105
+\definecharacter cyrillicJE 74
+\definecharacter cyrillicje 106
+\definecharacter cyrillicQ 81
+\definecharacter cyrillicq 113
+\definecharacter cyrillicDZE 83
+\definecharacter cyrillicdze 115
+\definecharacter cyrillicW 87
+\definecharacter cyrillicw 119
+
+\stopencoding
+
+\startmapping[t2c]
+
+\resetcaserange 128 to 255
+
+\definecasemaps 192 to 223 lc +32 uc 0 % base letters (russian)
+\definecasemaps 224 to 255 lc 0 uc -32
+
+\definecasemaps 128 to 156 lc +32 uc 0 % extra letters (cyrillic and old-slav)
+\definecasemaps 160 to 188 lc 0 uc -32
+
+\definecasemap 73 105 73 \definecasemap 105 105 73 % cyrillicII
+\definecasemap 74 106 74 \definecasemap 106 106 74 % cyrillicJE
+\definecasemap 81 113 81 \definecasemap 113 113 81 % cyrillicQ
+\definecasemap 83 115 83 \definecasemap 115 115 83 % cyrillicDZE
+\definecasemap 87 119 87 \definecasemap 119 119 87 % cyrillicW
+
+\stopmapping
+
+\startencoding[t2c]
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter texthungarumlaut 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter textogonek 12
+
+\definecharacter textcyrillicflex 18
+\definecharacter textdblgrave 19
+\definecharacter textcyrillicbreve 20
+
+\definecharacter endash 21
+\definecharacter emdash 22
+
+\definecharacter textcompwordmark 23
+\definecharacter textbackslash 92
+\definecharacter textasciicircum 94
+\definecharacter textunderscore 95
+\definecharacter textbraceleft 123
+\definecharacter textbraceright 125
+\definecharacter textasciitilde 126
+\definecharacter textnumero 157
+\definecharacter textcurrency 158
+\definecharacter sectionmark 159
+\definecharacter quotedbl 34
+\definecharacter quoteleft 96
+\definecharacter upperleftsingleninequote 39
+\definecharacter quotedblleft 16
+\definecharacter quotedblright 17
+\definecharacter lowerleftdoubleninequote 189
+\definecharacter upperrightdoublesixquote 16
+\definecharacter upperrightdoubleninequote 17
+\definecharacter quotedblbase 189
+
+\definecharacter cyrillicpalochka 13
+\definecharacter cyrilliclangle 14
+\definecharacter cyrillicrangle 15
+
+\definecharacter leftguillemot 190
+\definecharacter rightguillemot 191
+
+\definecharacter dotlessi 25
+
+\definecharacter cyrillicA 192
+\definecharacter cyrillica 224
+\definecharacter cyrillicB 193
+\definecharacter cyrillicb 225
+\definecharacter cyrillicV 194
+\definecharacter cyrillicv 226
+\definecharacter cyrillicG 195
+\definecharacter cyrillicg 227
+\definecharacter cyrillicD 196
+\definecharacter cyrillicd 228
+\definecharacter cyrillicE 197
+\definecharacter cyrillice 229
+\definecharacter cyrillicZH 198
+\definecharacter cyrilliczh 230
+\definecharacter cyrillicZ 199
+\definecharacter cyrillicz 231
+\definecharacter cyrillicI 200
+\definecharacter cyrillici 232
+\definecharacter cyrillicISHRT 201
+\definecharacter cyrillicishrt 233
+\definecharacter cyrillicK 202
+\definecharacter cyrillick 234
+\definecharacter cyrillicL 203
+\definecharacter cyrillicl 235
+\definecharacter cyrillicM 204
+\definecharacter cyrillicm 236
+\definecharacter cyrillicN 205
+\definecharacter cyrillicn 237
+\definecharacter cyrillicO 206
+\definecharacter cyrillico 238
+\definecharacter cyrillicP 207
+\definecharacter cyrillicp 239
+\definecharacter cyrillicR 208
+\definecharacter cyrillicr 240
+\definecharacter cyrillicS 209
+\definecharacter cyrillics 241
+\definecharacter cyrillicT 210
+\definecharacter cyrillict 242
+\definecharacter cyrillicU 211
+\definecharacter cyrillicu 243
+\definecharacter cyrillicF 212
+\definecharacter cyrillicf 244
+\definecharacter cyrillicH 213
+\definecharacter cyrillich 245
+\definecharacter cyrillicC 214
+\definecharacter cyrillicc 246
+\definecharacter cyrillicCH 215
+\definecharacter cyrillicch 247
+\definecharacter cyrillicSH 216
+\definecharacter cyrillicsh 248
+\definecharacter cyrillicSHCH 217
+\definecharacter cyrillicshch 249
+\definecharacter cyrillicHRDSN 218
+\definecharacter cyrillichrdsn 250
+\definecharacter cyrillicERY 219
+\definecharacter cyrillicery 251
+\definecharacter cyrillicSFTSN 220
+\definecharacter cyrillicsftsn 252
+\definecharacter cyrillicEREV 221
+\definecharacter cyrillicerev 253
+\definecharacter cyrillicYU 222
+\definecharacter cyrillicyu 254
+\definecharacter cyrillicYA 223
+\definecharacter cyrillicya 255
+\definecharacter cyrillicPHK 128
+\definecharacter cyrillicphk 160
+\definecharacter cyrillicTETSE 129
+\definecharacter cyrillictetse 161
+\definecharacter cyrillicTDSC 130
+\definecharacter cyrillictdsc 162
+\definecharacter cyrillicGHK 131
+\definecharacter cyrillicghk 163
+\definecharacter cyrillicSHHA 132
+\definecharacter cyrillicshha 164
+\definecharacter cyrillicRDSC 133
+\definecharacter cyrillicrdsc 165
+\definecharacter cyrillicRTICK 134
+\definecharacter cyrillicrtick 166
+\definecharacter cyrillicABHDZE 135
+\definecharacter cyrillicabhdze 167
+\definecharacter cyrillicMDSC 136
+\definecharacter cyrillicmdsc 168
+\definecharacter cyrillicKDSC 137
+\definecharacter cyrillickdsc 169
+\definecharacter cyrillicLDSC 138
+\definecharacter cyrillicldsc 170
+\definecharacter cyrillicKHCRS 139
+\definecharacter cyrillickhcrs 171
+\definecharacter cyrillicLHK 140
+\definecharacter cyrilliclhk 172
+\definecharacter cyrillicNDSC 141
+\definecharacter cyrillicndsc 173
+\definecharacter cyrillicMHK 142
+\definecharacter cyrillicmhk 174
+\definecharacter cyrillicNHK 143
+\definecharacter cyrillicnhk 175
+\definecharacter cyrillicOTLD 144
+\definecharacter cyrillicotld 176
+\definecharacter cyrillicABHCH 145
+\definecharacter cyrillicabhch 177
+\definecharacter cyrillicABHCHDSC 146
+\definecharacter cyrillicabhchdsc 178
+\definecharacter cyrillicSEMISFTSN 147
+\definecharacter cyrillicsemisftsn 179
+\definecharacter cyrillicISHRTDSC 148
+\definecharacter cyrillicishrtdsc 180
+\definecharacter cyrillicHDSC 149
+\definecharacter cyrillichdsc 181
+\definecharacter cyrillicDZHE 150
+\definecharacter cyrillicdzhe 182
+\definecharacter cyrillicABHHA 151
+\definecharacter cyrillicabhha 183
+\definecharacter cyrillicCHRDSC 152
+\definecharacter cyrillicchrdsc 184
+\definecharacter cyrillicNLHK 153
+\definecharacter cyrillicnlhk 185
+\definecharacter cyrillicSCHWA 154
+\definecharacter cyrillicschwa 186
+\definecharacter cyrillicRHK 155
+\definecharacter cyrillicrhk 187
+\definecharacter cyrillicYO 156
+\definecharacter cyrillicyo 188
+\definecharacter cyrillicII 73
+\definecharacter cyrillicii 105
+\definecharacter cyrillicJE 74
+\definecharacter cyrillicje 106
+\definecharacter cyrillicQ 81
+\definecharacter cyrillicq 113
+\definecharacter cyrillicDZE 83
+\definecharacter cyrillicdze 115
+\definecharacter cyrillicW 87
+\definecharacter cyrillicw 119
+
+\stopencoding
+
+\startmapping[x2]
+
+\resetcaserange 128 to 255
+
+\definecasemaps 192 to 223 lc +32 uc 0 % base letters (russian)
+\definecasemaps 224 to 255 lc 0 uc -32
+
+\definecasemaps 128 to 156 lc +32 uc 0 % extra letters (cyrillic and old-slav)
+\definecasemaps 160 to 188 lc 0 uc -32
+
+\definecasemaps 65 to 90 lc +32 uc 0 % more extra letters (cyrillic and old-slav)
+\definecasemaps 97 to 122 lc 0 uc -32
+
+\definecasemap 28 29 28 \definecasemap 29 29 28 % cyrillicNLHK
+\definecasemap 30 31 30 \definecasemap 31 31 30 % cyrillicDELTA
+
+\stopmapping
+
+\startencoding[x2]
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter texthungarumlaut 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter textogonek 12
+
+\definecharacter endash 21
+\definecharacter emdash 22
+
+\definecharacter textcompwordmark 23
+\definecharacter textvisiblespace 32
+\definecharacter textdollar 36
+\definecharacter textless 60
+\definecharacter textgreater 62
+\definecharacter textbackslash 92
+\definecharacter textasciicircum 94
+\definecharacter textunderscore 95
+\definecharacter textbraceleft 123
+\definecharacter textbar 124
+\definecharacter textbraceright 125
+\definecharacter textasciitilde 126
+\definecharacter textnumero 157
+\definecharacter textcurrency 158
+\definecharacter textsection 159
+\definecharacter sectionmark 159
+\definecharacter textquotedbl 34
+
+\definecharacter cyrillicpalochka 13
+\definecharacter cyrilliclangle 14
+\definecharacter cyrillicrangle 15
+
+\definecharacter leftguillemot 190
+\definecharacter rightguillemot 191
+
+\definecharacter upperleftsinglesixquote 96
+\definecharacter upperleftsingleninequote 39
+\definecharacter upperleftdoublesixquote 16
+\definecharacter upperleftdoubleninequote 17
+\definecharacter lowerleftdoubleninequote 189
+
+\definecharacter upperrightsinglesixquote 96
+\definecharacter upperrightsingleninequote 39
+\definecharacter upperrightdoublesixquote 16
+\definecharacter upperrightdoubleninequote 17
+\definecharacter lowerrightdoubleninequote 189
+
+\definecharacter cyrillicA 192
+\definecharacter cyrillica 224
+\definecharacter cyrillicB 193
+\definecharacter cyrillicb 225
+\definecharacter cyrillicV 194
+\definecharacter cyrillicv 226
+\definecharacter cyrillicG 195
+\definecharacter cyrillicg 227
+\definecharacter cyrillicD 196
+\definecharacter cyrillicd 228
+\definecharacter cyrillicE 197
+\definecharacter cyrillice 229
+\definecharacter cyrillicZH 198
+\definecharacter cyrilliczh 230
+\definecharacter cyrillicZ 199
+\definecharacter cyrillicz 231
+\definecharacter cyrillicI 200
+\definecharacter cyrillici 232
+\definecharacter cyrillicISHRT 201
+\definecharacter cyrillicishrt 233
+\definecharacter cyrillicK 202
+\definecharacter cyrillick 234
+\definecharacter cyrillicL 203
+\definecharacter cyrillicl 235
+\definecharacter cyrillicM 204
+\definecharacter cyrillicm 236
+\definecharacter cyrillicN 205
+\definecharacter cyrillicn 237
+\definecharacter cyrillicO 206
+\definecharacter cyrillico 238
+\definecharacter cyrillicP 207
+\definecharacter cyrillicp 239
+\definecharacter cyrillicR 208
+\definecharacter cyrillicr 240
+\definecharacter cyrillicS 209
+\definecharacter cyrillics 241
+\definecharacter cyrillicT 210
+\definecharacter cyrillict 242
+\definecharacter cyrillicU 211
+\definecharacter cyrillicu 243
+\definecharacter cyrillicF 212
+\definecharacter cyrillicf 244
+\definecharacter cyrillicH 213
+\definecharacter cyrillich 245
+\definecharacter cyrillicC 214
+\definecharacter cyrillicc 246
+\definecharacter cyrillicCH 215
+\definecharacter cyrillicch 247
+\definecharacter cyrillicSH 216
+\definecharacter cyrillicsh 248
+\definecharacter cyrillicSHCH 217
+\definecharacter cyrillicshch 249
+\definecharacter cyrillicHRDSN 218
+\definecharacter cyrillichrdsn 250
+\definecharacter cyrillicERY 219
+\definecharacter cyrillicery 251
+\definecharacter cyrillicSFTSN 220
+\definecharacter cyrillicsftsn 252
+\definecharacter cyrillicEREV 221
+\definecharacter cyrillicerev 253
+\definecharacter cyrillicYU 222
+\definecharacter cyrillicyu 254
+\definecharacter cyrillicYA 223
+\definecharacter cyrillicya 255
+\definecharacter cyrillicGUP 128
+\definecharacter cyrillicgup 160
+\definecharacter cyrillicGHCRS 129
+\definecharacter cyrillicghcrs 161
+\definecharacter cyrillicGDSC 130
+\definecharacter cyrillicgdsc 162
+\definecharacter cyrillicGHK 131
+\definecharacter cyrillicghk 163
+\definecharacter cyrillicSHHA 132
+\definecharacter cyrillicshha 164
+\definecharacter cyrillicZHDSC 133
+\definecharacter cyrilliczhdsc 165
+\definecharacter cyrillicZDSC 134
+\definecharacter cyrilliczdsc 166
+\definecharacter cyrillicABHDZE 135
+\definecharacter cyrillicabhdze 167
+\definecharacter cyrillicYI 136
+\definecharacter cyrillicyi 168
+\definecharacter cyrillicKDSC 137
+\definecharacter cyrillickdsc 169
+\definecharacter cyrillicKBEAK 138
+\definecharacter cyrillickbeak 170
+\definecharacter cyrillicKHK 139
+\definecharacter cyrillickhk 171
+\definecharacter cyrillicLHK 140
+\definecharacter cyrilliclhk 172
+\definecharacter cyrillicNDSC 141
+\definecharacter cyrillicndsc 173
+\definecharacter cyrillicNG 142
+\definecharacter cyrillicng 174
+\definecharacter cyrillicNHK 143
+\definecharacter cyrillicnhk 175
+\definecharacter cyrillicOTLD 144
+\definecharacter cyrillicotld 176
+\definecharacter cyrillicSDSC 145
+\definecharacter cyrillicsdsc 177
+\definecharacter cyrillicUSHRT 146
+\definecharacter cyrillicushrt 178
+\definecharacter cyrillicY 147
+\definecharacter cyrillicy 179
+\definecharacter cyrillicYHCRS 148
+\definecharacter cyrillicyhcrs 180
+\definecharacter cyrillicHDSC 149
+\definecharacter cyrillichdsc 181
+\definecharacter cyrillicHHK 150
+\definecharacter cyrillichhk 182
+\definecharacter cyrillicCHLDSC 151
+\definecharacter cyrillicchldsc 183
+\definecharacter cyrillicCHRDSC 152
+\definecharacter cyrillicchrdsc 184
+\definecharacter cyrillicIE 153
+\definecharacter cyrillicie 185
+\definecharacter cyrillicSCHWA 154
+\definecharacter cyrillicschwa 186
+\definecharacter cyrillicEPS 155
+\definecharacter cyrilliceps 187
+\definecharacter cyrillicYO 156
+\definecharacter cyrillicyo 188
+\definecharacter cyrillicAE 65
+\definecharacter cyrillicae 97
+\definecharacter cyrillicDJE 66
+\definecharacter cyrillicdje 98
+\definecharacter cyrillicTSHE 67
+\definecharacter cyrillictshe 99
+\definecharacter cyrillicABHCH 68
+\definecharacter cyrillicabhch 100
+\definecharacter cyrillicABHCHDSC 69
+\definecharacter cyrillicabhchdsc 101
+\definecharacter cyrillicKVCRS 70
+\definecharacter cyrillickvcrs 102
+\definecharacter cyrillicKHCRS 71
+\definecharacter cyrillickhcrs 103
+\definecharacter cyrillicLDSC 72
+\definecharacter cyrillicldsc 104
+\definecharacter cyrillicII 73
+\definecharacter cyrillicii 105
+\definecharacter cyrillicJE 74
+\definecharacter cyrillicje 106
+\definecharacter cyrillicLJE 75
+\definecharacter cyrilliclje 107
+\definecharacter cyrillicMDSC 76
+\definecharacter cyrillicmdsc 108
+\definecharacter cyrillicNJE 77
+\definecharacter cyrillicnje 109
+\definecharacter cyrillicABHHA 78
+\definecharacter cyrillicabhha 110
+\definecharacter cyrillicPHK 79
+\definecharacter cyrillicphk 111
+\definecharacter cyrillicRDSC 80
+\definecharacter cyrillicrdsc 112
+\definecharacter cyrillicQ 81
+\definecharacter cyrillicq 113
+\definecharacter cyrillicTDSC 82
+\definecharacter cyrillictdsc 114
+\definecharacter cyrillicDZE 83
+\definecharacter cyrillicdze 115
+\definecharacter cyrillicTETSE 84
+\definecharacter cyrillictetse 116
+\definecharacter cyrillicDZHE 85
+\definecharacter cyrillicdzhe 117
+\definecharacter cyrillicCHVCRS 86
+\definecharacter cyrillicchvcrs 118
+\definecharacter cyrillicW 87
+\definecharacter cyrillicw 119
+\definecharacter cyrillicYAT 88
+\definecharacter cyrillicyat 120
+\definecharacter cyrillicBYUS 89
+\definecharacter cyrillicbyus 121
+\definecharacter cyrillicIZH 90
+\definecharacter cyrillicizh 122
+\definecharacter cyrillicNLHK 28
+\definecharacter cyrillicnlhk 29
+\definecharacter cyrillicDELTA 30
+\definecharacter cyrillicdelta 31
+
+\stopencoding
+
+\startmapping[lcy]
+
+\resetcaserange 128 to 255
+
+\definecasemaps 128 to 143 lc +32 uc 0
+\definecasemaps 160 to 175 lc 0 uc -32
+
+\definecasemaps 144 to 159 lc +80 uc 0
+\definecasemaps 224 to 239 lc 0 uc -80
+
+\definecasemap 240 241 240 \definecasemap 241 241 240 % cyrillicYO
+\definecasemap 242 243 242 \definecasemap 243 243 242 % cyrillicGUP
+\definecasemap 244 245 244 \definecasemap 245 245 244 % cyrillicIE
+\definecasemap 244 247 244 \definecasemap 247 247 244 % cyrillicII
+\definecasemap 248 249 248 \definecasemap 249 249 248 % cyrillicYI
+\definecasemap 250 251 240 \definecasemap 241 241 240 % cyrillicUSHRT
+
+\stopmapping
+
+\startencoding[lcy]
+
+%D Characters 0 to 127 are as in normal cmr slots
+
+\definecharacter cyrillicA 128
+\definecharacter cyrillicB 129
+\definecharacter cyrillicV 130
+\definecharacter cyrillicG 131
+\definecharacter cyrillicD 132
+\definecharacter cyrillicE 133
+\definecharacter cyrillicZH 134
+\definecharacter cyrillicZ 135
+\definecharacter cyrillicI 136
+\definecharacter cyrillicISHRT 137
+\definecharacter cyrillicK 138
+\definecharacter cyrillicL 139
+\definecharacter cyrillicM 140
+\definecharacter cyrillicN 141
+\definecharacter cyrillicO 142
+\definecharacter cyrillicP 143
+\definecharacter cyrillicR 144
+\definecharacter cyrillicS 145
+\definecharacter cyrillicT 146
+\definecharacter cyrillicU 147
+\definecharacter cyrillicF 148
+\definecharacter cyrillicH 149
+\definecharacter cyrillicC 150
+\definecharacter cyrillicCH 151
+\definecharacter cyrillicSH 152
+\definecharacter cyrillicSHCH 153
+\definecharacter cyrillicHRDSN 154
+\definecharacter cyrillicERY 155
+\definecharacter cyrillicSFTSN 156
+\definecharacter cyrillicEREV 157
+\definecharacter cyrillicYU 158
+\definecharacter cyrillicYA 159
+\definecharacter cyrillica 160
+\definecharacter cyrillicb 161
+\definecharacter cyrillicv 162
+\definecharacter cyrillicg 163
+\definecharacter cyrillicd 164
+\definecharacter cyrillice 165
+\definecharacter cyrilliczh 166
+\definecharacter cyrillicz 167
+\definecharacter cyrillici 168
+\definecharacter cyrillicishrt 169
+\definecharacter cyrillick 170
+\definecharacter cyrillicl 171
+\definecharacter cyrillicm 172
+\definecharacter cyrillicn 173
+\definecharacter cyrillico 174
+\definecharacter cyrillicp 175
+\definecharacter cyrillicr 224
+\definecharacter cyrillics 225
+\definecharacter cyrillict 226
+\definecharacter cyrillicu 227
+\definecharacter cyrillicf 228
+\definecharacter cyrillich 229
+\definecharacter cyrillicc 230
+\definecharacter cyrillicch 231
+\definecharacter cyrillicsh 232
+\definecharacter cyrillicshch 233
+\definecharacter cyrillichrdsn 234
+\definecharacter cyrillicery 235
+\definecharacter cyrillicsftsn 236
+\definecharacter cyrillicerev 237
+\definecharacter cyrillicyu 238
+\definecharacter cyrillicya 239
+\definecharacter cyrillicYO 240
+\definecharacter cyrillicyo 241
+\definecharacter cyrillicGUP 242
+\definecharacter cyrillicgup 243
+\definecharacter cyrillicIE 244
+\definecharacter cyrillicie 245
+\definecharacter cyrillicII 246
+\definecharacter cyrillicii 247
+\definecharacter cyrillicYI 248
+\definecharacter cyrillicyi 249
+\definecharacter cyrillicUSHRT 250
+\definecharacter cyrillicushrt 251
+
+\definecharacter emdash 196
+\definecharacter textcurrency 197
+\definecharacter textnumero 252
+\definecharacter leftguillemot 253
+\definecharacter rightguillemot 254
+\definecharacter quotedblbase 255
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-def.mkii b/tex/context/base/enco-def.mkii
new file mode 100644
index 000000000..4d8e280cb
--- /dev/null
+++ b/tex/context/base/enco-def.mkii
@@ -0,0 +1,922 @@
+%D \module
+%D [ file=enco-def,
+%D version=2000.05.07, % 2000.20.12, % split from less verbose base file
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Default Character Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 Instead of overloading plain \TEX\ macros (and keeping them
+%D available as an escape), we now use the more verbose
+%D definitions in this file. Since memory is less a problem
+%D these days, this verbosity has only a small price, but we
+%D gain readability. The following definitions are based on
+%D usage of the the original \TEX\ fonts, where composed
+%D characters were not part of the design. So, occasionally
+%D we have to revert to hacks. Thanks to all those users who
+%D helped me to fill in the details.
+
+\startencoding[default]
+
+\definecharacter textcomma ,
+\definecharacter textperiod .
+
+\definecharacter textacute 19
+\definecharacter textbottomdot 46
+\definecharacter textbreve 21
+\definecharacter textcaron 20
+\definecharacter textcedilla 24
+\definecharacter textcircumflex 94
+\definecharacter textdiaeresis 127
+\definecharacter textdotaccent 95
+\definecharacter textgrave 18
+\definecharacter texthungarumlaut 125
+\definecharacter textmacron 22
+\definecharacter textogonek 24 % fake
+\definecharacter textring 23
+\definecharacter texttilde 126
+
+\definecharacter textat 64 % for mojca
+
+\definecharacter textbottomcomma {\hbox{\lower.35ex\hbox{\tx,}}} % for mojca
+
+\definecharacter dotlessi {\char"10 }
+\definecharacter dotlessj {\char"11 }
+\definecharacter dotlessI {I}
+\definecharacter dotlessJ {J}
+
+\definecharacter endash 123
+\definecharacter emdash 124
+
+\definecharacter aeligature {\char26 } % "1A
+\definecharacter AEligature {\char29 } % "1D
+\definecharacter ijligature {ij}
+\definecharacter IJligature {IJ}
+\definecharacter oeligature {\char27 } % "1B
+\definecharacter OEligature {\char30 } % "1E
+
+\definecharacter ssharp {\char25 } % "19
+\definecharacter Ssharp {SS}
+
+\definecharacter thorn {\unknownchar}
+\definecharacter Thorn {\unknownchar}
+
+\definecharacter eth {\unknownchar} % mojca prefers this (was \dstroke)
+%definecharacter Eth {\unknownchar}
+\definecharacter Eth {\Dstroke} % mojca prefers this too
+
+\definecharacter exclamdown 60
+\definecharacter questiondown 62
+
+\definecharacter copyright {\encircled{\txx C}}
+\definecharacter registered {\encircled{\txx R}}
+\definecharacter trademark {\high{\txx TM}}
+
+\definecharacter sectionmark {\mathematics{\mathhexbox278}}
+\definecharacter paragraphmark {\mathematics{\mathhexbox27B}}
+
+\definecharacter onequarter {\vulgarfraction{1}{4}}
+\definecharacter onehalf {\vulgarfraction{1}{2}}
+\definecharacter threequarter {\vulgarfraction{3}{4}}
+
+\definecharacter onesuperior {\high{1}}
+\definecharacter twosuperior {\high{2}}
+\definecharacter threesuperior {\high{3}}
+
+\definecharacter textcent {c}
+\definecharacter textcurrency {\unknownchar}
+\definecharacter textdollar {\fakedollar}
+\definecharacter texteuro {E}
+\definecharacter textflorin {\fakeflorin}
+\definecharacter textsterling {\fakesterling}
+\definecharacter textyen {Y}
+
+\definecharacter ordfeminine {\high{\txx a}}
+\definecharacter ordmasculine {\high{\txx o}}
+
+\definecharacter percent {\fakepercent}
+\definecharacter perthousand {\fakeperthousand}
+
+\definecharacter softhyphen 45
+\definecharacter periodcentered {\hbox{\mathematics\cdot}}
+\definecharacter compoundwordmark 23
+
+\definecharacter textasciicircum 94
+\definecharacter textasciitilde 126
+\definecharacter textslash 47
+\definecharacter textbackslash {\tex{}} % todo
+\definecharacter textbraceleft {\mathematics\{}
+\definecharacter textbraceright {\mathematics\}}
+\definecharacter textunderscore {\fakeunderscore}
+\definecharacter textvisiblespace {\fakevisiblespace}
+
+\definecharacter textbrokenbar {\mathematics\vert}
+\definecharacter textbullet {\mathematics\bullet}
+\definecharacter textdag {\mathematics\dag}
+\definecharacter textddag {\mathematics\ddag}
+\definecharacter textdegree {\mathematics{{}^{\circ}}}
+\definecharacter textdiv {\mathematics\div}
+\definecharacter textellipsis {\mathematics\cdots}
+\definecharacter textfraction {\mathematics/}
+\definecharacter textlognot {\mathematics\neg}
+\definecharacter textminus {\mathematics-}
+\definecharacter textmu {\mathematics\mu}
+\definecharacter textmultiply {\mathematics\times}
+\definecharacter textpm {\mathematics\pm}
+
+\definecharacter quotedbl {"}
+\definecharacter quotedblbase {,,}
+\definecharacter quotedblleft {``}
+\definecharacter quotedblright {''}
+
+\definecharacter quotesingle {`}
+\definecharacter quotesinglebase {,}
+
+\definecharacter quoteleft {`}
+\definecharacter quoteright {'}
+
+\definecharacter guilsingleleft {\fakeleftsubguillemot }
+\definecharacter guilsingleright {\fakerightsubguillemot}
+
+\definecharacter leftguillemot {\fakeleftguillemot }
+\definecharacter rightguillemot {\fakerightguillemot}
+
+\definecharacter Acircumflex {\buildtextaccent\textcircumflex A}
+\definecharacter acircumflex {\buildtextaccent\textcircumflex a}
+\definecharacter Ccircumflex {\buildtextaccent\textcircumflex C}
+\definecharacter ccircumflex {\buildtextaccent\textcircumflex c}
+\definecharacter Ecircumflex {\buildtextaccent\textcircumflex E}
+\definecharacter ecircumflex {\buildtextaccent\textcircumflex e}
+\definecharacter Gcircumflex {\buildtextaccent\textcircumflex G}
+\definecharacter gcircumflex {\buildtextaccent\textcircumflex g}
+\definecharacter Hcircumflex {\buildtextaccent\textcircumflex H}
+\definecharacter hcircumflex {\buildtextaccent\textcircumflex h}
+\definecharacter Icircumflex {\buildtextaccent\textcircumflex \dotlessI}
+\definecharacter icircumflex {\buildtextaccent\textcircumflex \dotlessi}
+\definecharacter Jcircumflex {\buildtextaccent\textcircumflex \dotlessJ}
+\definecharacter jcircumflex {\buildtextaccent\textcircumflex \dotlessj}
+\definecharacter Ocircumflex {\buildtextaccent\textcircumflex O}
+\definecharacter ocircumflex {\buildtextaccent\textcircumflex o}
+\definecharacter Scircumflex {\buildtextaccent\textcircumflex S}
+\definecharacter scircumflex {\buildtextaccent\textcircumflex s}
+\definecharacter Ucircumflex {\buildtextaccent\textcircumflex U}
+\definecharacter ucircumflex {\buildtextaccent\textcircumflex u}
+\definecharacter Wcircumflex {\buildtextaccent\textcircumflex W}
+\definecharacter wcircumflex {\buildtextaccent\textcircumflex w}
+\definecharacter Ycircumflex {\buildtextaccent\textcircumflex Y}
+\definecharacter ycircumflex {\buildtextaccent\textcircumflex y}
+
+\definecharacter Agrave {\buildtextaccent\textgrave A}
+\definecharacter agrave {\buildtextaccent\textgrave a}
+\definecharacter Egrave {\buildtextaccent\textgrave E}
+\definecharacter egrave {\buildtextaccent\textgrave e}
+\definecharacter Igrave {\buildtextaccent\textgrave \dotlessI}
+\definecharacter igrave {\buildtextaccent\textgrave \dotlessi}
+\definecharacter Ograve {\buildtextaccent\textgrave O}
+\definecharacter ograve {\buildtextaccent\textgrave o}
+\definecharacter Ugrave {\buildtextaccent\textgrave U}
+\definecharacter ugrave {\buildtextaccent\textgrave u}
+\definecharacter Ygrave {\buildtextaccent\textgrave Y}
+\definecharacter ygrave {\buildtextaccent\textgrave y}
+
+\definecharacter Atilde {\buildtextaccent\texttilde A}
+\definecharacter atilde {\buildtextaccent\texttilde a}
+\definecharacter Itilde {\buildtextaccent\texttilde \dotlessI}
+\definecharacter itilde {\buildtextaccent\texttilde \dotlessi}
+\definecharacter Ntilde {\buildtextaccent\texttilde N}
+\definecharacter ntilde {\buildtextaccent\texttilde n}
+\definecharacter Otilde {\buildtextaccent\texttilde O}
+\definecharacter otilde {\buildtextaccent\texttilde o}
+\definecharacter Utilde {\buildtextaccent\texttilde U}
+\definecharacter utilde {\buildtextaccent\texttilde u}
+\definecharacter Ytilde {\buildtextaccent\texttilde Y}
+\definecharacter ytilde {\buildtextaccent\texttilde y}
+
+\definecharacter Adiaeresis {\buildtextaccent\textdiaeresis A}
+\definecharacter adiaeresis {\buildtextaccent\textdiaeresis a}
+\definecharacter Ediaeresis {\buildtextaccent\textdiaeresis E}
+\definecharacter ediaeresis {\buildtextaccent\textdiaeresis e}
+\definecharacter Idiaeresis {\buildtextaccent\textdiaeresis \dotlessI}
+\definecharacter idiaeresis {\buildtextaccent\textdiaeresis \dotlessi}
+\definecharacter Odiaeresis {\buildtextaccent\textdiaeresis O}
+\definecharacter odiaeresis {\buildtextaccent\textdiaeresis o}
+\definecharacter Udiaeresis {\buildtextaccent\textdiaeresis U}
+\definecharacter udiaeresis {\buildtextaccent\textdiaeresis u}
+\definecharacter Ydiaeresis {\buildtextaccent\textdiaeresis Y}
+\definecharacter ydiaeresis {\buildtextaccent\textdiaeresis y}
+
+\definecharacter Aacute {\buildtextaccent\textacute A}
+\definecharacter aacute {\buildtextaccent\textacute a}
+\definecharacter Cacute {\buildtextaccent\textacute C}
+\definecharacter cacute {\buildtextaccent\textacute c}
+\definecharacter Eacute {\buildtextaccent\textacute E}
+\definecharacter eacute {\buildtextaccent\textacute e}
+\definecharacter Iacute {\buildtextaccent\textacute \dotlessI}
+\definecharacter iacute {\buildtextaccent\textacute \dotlessi}
+\definecharacter Lacute {\buildtextaccent\textacute L}
+\definecharacter lacute {\buildtextaccent\textacute l}
+\definecharacter Nacute {\buildtextaccent\textacute N}
+\definecharacter nacute {\buildtextaccent\textacute n}
+\definecharacter Oacute {\buildtextaccent\textacute O}
+\definecharacter oacute {\buildtextaccent\textacute o}
+\definecharacter Racute {\buildtextaccent\textacute R}
+\definecharacter racute {\buildtextaccent\textacute r}
+\definecharacter Sacute {\buildtextaccent\textacute S}
+\definecharacter sacute {\buildtextaccent\textacute s}
+\definecharacter Uacute {\buildtextaccent\textacute U}
+\definecharacter uacute {\buildtextaccent\textacute u}
+\definecharacter Yacute {\buildtextaccent\textacute Y}
+\definecharacter yacute {\buildtextaccent\textacute y}
+\definecharacter Zacute {\buildtextaccent\textacute Z}
+\definecharacter zacute {\buildtextaccent\textacute z}
+
+%definecharacter Dstroke {D}
+%definecharacter dstroke {d}
+
+\definecharacter dstroke {\pseudoencodeddj}
+\definecharacter Dstroke {\pseudoencodedDJ}
+\definecharacter Hstroke {H}
+\definecharacter hstroke {h}
+\definecharacter Tstroke {T}
+\definecharacter tstroke {t}
+
+\definecharacter Cdotaccent {\buildtextaccent\textdotaccent C}
+\definecharacter cdotaccent {\buildtextaccent\textdotaccent c}
+\definecharacter Edotaccent {\buildtextaccent\textdotaccent E}
+\definecharacter edotaccent {\buildtextaccent\textdotaccent e}
+\definecharacter Gdotaccent {\buildtextaccent\textdotaccent G}
+\definecharacter gdotaccent {\buildtextaccent\textdotaccent g}
+\definecharacter Idotaccent {\buildtextaccent\textdotaccent \dotlessI}
+\definecharacter idotaccent {\buildtextaccent\textdotaccent \dotlessi}
+\definecharacter Zdotaccent {\buildtextaccent\textdotaccent Z}
+\definecharacter zdotaccent {\buildtextaccent\textdotaccent z}
+
+\definecharacter Amacron {\buildtextaccent\textmacron A}
+\definecharacter amacron {\buildtextaccent\textmacron a}
+\definecharacter Emacron {\buildtextaccent\textmacron E}
+\definecharacter emacron {\buildtextaccent\textmacron e}
+\definecharacter Imacron {\buildtextaccent\textmacron \dotlessI}
+\definecharacter imacron {\buildtextaccent\textmacron \dotlessi}
+\definecharacter Omacron {\buildtextaccent\textmacron O}
+\definecharacter omacron {\buildtextaccent\textmacron o}
+\definecharacter Umacron {\buildtextaccent\textmacron U}
+\definecharacter umacron {\buildtextaccent\textmacron u}
+
+\definecharacter Ccedilla {\buildtextcedilla C}
+\definecharacter ccedilla {\buildtextcedilla c}
+\definecharacter Kcedilla {\buildtextcedilla K}
+\definecharacter kcedilla {\buildtextcedilla k}
+\definecharacter Lcedilla {\buildtextcedilla L}
+\definecharacter lcedilla {\buildtextcedilla l}
+\definecharacter Ncedilla {\buildtextcedilla N}
+\definecharacter ncedilla {\buildtextcedilla n}
+\definecharacter Rcedilla {\buildtextcedilla R}
+\definecharacter rcedilla {\buildtextcedilla r}
+\definecharacter Scedilla {\buildtextcedilla S}
+\definecharacter scedilla {\buildtextcedilla s}
+\definecharacter Tcedilla {\buildtextcedilla T}
+\definecharacter tcedilla {\buildtextcedilla t}
+
+\definecharacter Ohungarumlaut {\buildtextaccent\texthungarumlaut O}
+\definecharacter ohungarumlaut {\buildtextaccent\texthungarumlaut o}
+\definecharacter Uhungarumlaut {\buildtextaccent\texthungarumlaut U}
+\definecharacter uhungarumlaut {\buildtextaccent\texthungarumlaut u}
+
+\definecharacter Aogonek {\buildtextogonek A}
+\definecharacter aogonek {\buildtextogonek a}
+\definecharacter Eogonek {\buildtextogonek E}
+\definecharacter eogonek {\buildtextogonek e}
+\definecharacter Iogonek {\buildtextogonek I}
+\definecharacter iogonek {\buildtextogonek i}
+\definecharacter Uogonek {\buildtextogonek U}
+\definecharacter uogonek {\buildtextogonek u}
+
+\definecharacter Aring {\buildtextaccent\textring A}
+\definecharacter aring {\buildtextaccent\textring a}
+\definecharacter Uring {\buildtextaccent\textring U}
+\definecharacter uring {\buildtextaccent\textring u}
+
+\definecharacter Abreve {\buildtextaccent\textbreve A}
+\definecharacter abreve {\buildtextaccent\textbreve a}
+\definecharacter Ebreve {\buildtextaccent\textbreve E}
+\definecharacter ebreve {\buildtextaccent\textbreve e}
+\definecharacter Gbreve {\buildtextaccent\textbreve G}
+\definecharacter gbreve {\buildtextaccent\textbreve g}
+\definecharacter Ibreve {\buildtextaccent\textbreve \dotlessI}
+\definecharacter ibreve {\buildtextaccent\textbreve \dotlessi}
+\definecharacter Obreve {\buildtextaccent\textbreve O}
+\definecharacter obreve {\buildtextaccent\textbreve o}
+\definecharacter Ubreve {\buildtextaccent\textbreve U}
+\definecharacter ubreve {\buildtextaccent\textbreve u}
+
+\definecharacter Ccaron {\buildtextaccent\textcaron C}
+\definecharacter ccaron {\buildtextaccent\textcaron c}
+\definecharacter Dcaron {\buildtextaccent\textcaron D}
+\definecharacter dcaron {\buildtextaccent\textcaron d}
+\definecharacter Ecaron {\buildtextaccent\textcaron E}
+\definecharacter ecaron {\buildtextaccent\textcaron e}
+\definecharacter Lcaron {\buildtextaccent\textcaron L}
+\definecharacter lcaron {\buildtextaccent\textcaron l}
+\definecharacter Ncaron {\buildtextaccent\textcaron N}
+\definecharacter ncaron {\buildtextaccent\textcaron n}
+\definecharacter Rcaron {\buildtextaccent\textcaron R}
+\definecharacter rcaron {\buildtextaccent\textcaron r}
+\definecharacter Scaron {\buildtextaccent\textcaron S}
+\definecharacter scaron {\buildtextaccent\textcaron s}
+\definecharacter Tcaron {\buildtextaccent\textcaron T}
+\definecharacter tcaron {\buildtextaccent\textcaron t}
+\definecharacter Ycaron {\buildtextaccent\textcaron Y}
+\definecharacter ycaron {\buildtextaccent\textcaron y}
+\definecharacter Zcaron {\buildtextaccent\textcaron Z}
+\definecharacter zcaron {\buildtextaccent\textcaron z}
+
+\definecharacter Lstroke {\hsmash{\char32}L}
+\definecharacter lstroke {\hsmash{\char32}l}
+\definecharacter Ostroke {\char31 } % "1F
+\definecharacter ostroke {\char28 } % "1C
+
+\definecharacter aumlaut {\moveaccent{-.1ex}\adiaeresis}
+\definecharacter eumlaut {\moveaccent{-.1ex}\ediaeresis}
+\definecharacter iumlaut {\moveaccent{-.1ex}\idiaeresis}
+\definecharacter oumlaut {\moveaccent{-.1ex}\odiaeresis}
+\definecharacter uumlaut {\moveaccent{-.1ex}\udiaeresis}
+
+\definecharacter Aumlaut {\smashaccent\Adiaeresis}
+\definecharacter Eumlaut {\smashaccent\Ediaeresis}
+\definecharacter Iumlaut {\smashaccent\Idiaeresis}
+\definecharacter Oumlaut {\smashaccent\Odiaeresis}
+\definecharacter Uumlaut {\smashaccent\Udiaeresis}
+
+\definecharacter scommaaccent {\buildtextbottomcomma s}
+\definecharacter Scommaaccent {\buildtextbottomcomma S}
+\definecharacter tcommaaccent {\buildtextbottomcomma t}
+\definecharacter Tcommaaccent {\buildtextbottomcomma T}
+\definecharacter lcommaaccent {\buildtextbottomcomma l}
+\definecharacter Lcommaaccent {\buildtextbottomcomma L}
+
+\definecharacter Etilde {\buildtextaccent\texttilde E}
+\definecharacter etilde {\buildtextaccent\texttilde e}
+
+\definecharacter Ahook {A}
+\definecharacter ahook {a}
+\definecharacter Ehook {E}
+\definecharacter ehook {e}
+\definecharacter Ihook {I}
+\definecharacter ihook {i}
+\definecharacter Ohook {O}
+\definecharacter ohook {o}
+\definecharacter Uhook {U}
+\definecharacter uhook {u}
+\definecharacter Yhook {Y}
+\definecharacter yhook {y}
+
+\definecharacter Acircumflexgrave {\Acircumflex}
+\definecharacter Acircumflexacute {\Acircumflex}
+\definecharacter Acircumflextilde {\Acircumflex}
+\definecharacter Acircumflexhook {\Acircumflex}
+\definecharacter acircumflexgrave {\acircumflex}
+\definecharacter acircumflexacute {\acircumflex}
+\definecharacter acircumflextilde {\acircumflex}
+\definecharacter acircumflexhook {\acircumflex}
+\definecharacter Ecircumflexgrave {\Ecircumflex}
+\definecharacter Ecircumflexacute {\Ecircumflex}
+\definecharacter Ecircumflextilde {\Ecircumflex}
+\definecharacter Ecircumflexhook {\Ecircumflex}
+\definecharacter ecircumflexgrave {\ecircumflex}
+\definecharacter ecircumflexacute {\ecircumflex}
+\definecharacter ecircumflextilde {\ecircumflex}
+\definecharacter ecircumflexhook {\ecircumflex}
+\definecharacter Ocircumflexgrave {\Ocircumflex}
+\definecharacter Ocircumflexacute {\Ocircumflex}
+\definecharacter Ocircumflextilde {\Ocircumflex}
+\definecharacter Ocircumflexhook {\Ocircumflex}
+\definecharacter ocircumflexgrave {\ocircumflex}
+\definecharacter ocircumflexacute {\ocircumflex}
+\definecharacter ocircumflextilde {\ocircumflex}
+\definecharacter ocircumflexhook {\ocircumflex}
+
+\definecharacter Abrevegrave {\Abreve}
+\definecharacter Abreveacute {\Abreve}
+\definecharacter Abrevetilde {\Abreve}
+\definecharacter Abrevehook {\Abreve}
+\definecharacter abrevegrave {\abreve}
+\definecharacter abreveacute {\abreve}
+\definecharacter abrevetilde {\abreve}
+\definecharacter abrevehook {\abreve}
+
+\definecharacter Adotbelow {\buildtextbottomdot A}
+\definecharacter adotbelow {\buildtextbottomdot a}
+\definecharacter Edotbelow {\buildtextbottomdot E}
+\definecharacter edotbelow {\buildtextbottomdot e}
+\definecharacter Idotbelow {\buildtextbottomdot I}
+\definecharacter idotbelow {\buildtextbottomdot i}
+\definecharacter Odotbelow {\buildtextbottomdot O}
+\definecharacter odotbelow {\buildtextbottomdot o}
+\definecharacter Udotbelow {\buildtextbottomdot U}
+\definecharacter udotbelow {\buildtextbottomdot u}
+\definecharacter Ydotbelow {\buildtextbottomdot Y}
+\definecharacter ydotbelow {\buildtextbottomdot y}
+
+\definecharacter Ohorndotbelow {\buildtextbottomdot\Ohorn}
+\definecharacter ohorndotbelow {\buildtextbottomdot\ohorn}
+\definecharacter Uhorndotbelow {\buildtextbottomdot\Uhorn}
+\definecharacter uhorndotbelow {\buildtextbottomdot\uhorn}
+
+\definecharacter Acircumflexdotbelow {\buildtextbottomdot\Acircumflex}
+\definecharacter acircumflexdotbelow {\buildtextbottomdot\acircumflex}
+\definecharacter Ecircumflexdotbelow {\buildtextbottomdot\Ecircumflex}
+\definecharacter ecircumflexdotbelow {\buildtextbottomdot\ecircumflex}
+\definecharacter Ocircumflexdotbelow {\buildtextbottomdot\Ocircumflex}
+\definecharacter ocircumflexdotbelow {\buildtextbottomdot\ocircumflex}
+\definecharacter Abrevedotbelow {\buildtextbottomdot\Abreve}
+\definecharacter abrevedotbelow {\buildtextbottomdot\abreve}
+
+\definecharacter Ohorn {O}
+\definecharacter Ohorngrave {\Ograve}
+\definecharacter Ohornacute {\Oacute}
+\definecharacter Ohorntilde {\Otilde}
+\definecharacter Ohornhook {O}
+\definecharacter ohorn {o}
+\definecharacter ohorngrave {\ograve}
+\definecharacter ohornacute {\oacute}
+\definecharacter ohorntilde {\otilde}
+\definecharacter ohornhook {o}
+\definecharacter Uhorn {U}
+\definecharacter Uhorngrave {\Ugrave}
+\definecharacter Uhornacute {\Uacute}
+\definecharacter Uhorntilde {\Utilde}
+\definecharacter Uhornhook {U}
+\definecharacter uhorn {u}
+\definecharacter uhorngrave {\ugrave}
+\definecharacter uhornacute {\uacute}
+\definecharacter uhorntilde {\utilde}
+\definecharacter uhornhook {u}
+
+\stopencoding
+
+%D Needed for transliterated chinese (provided by Tobias Burnus).
+
+\startencoding[default]
+
+\definecharacter acaron {\buildtextaccent\textcaron a} % U+01CE
+\definecharacter icaron {\buildtextaccent\textcaron \dotlessi} % U+01D0
+\definecharacter ocaron {\buildtextaccent\textcaron o} % U+01D2
+\definecharacter ucaron {\buildtextaccent\textcaron u} % U+01D4
+
+\stopencoding
+
+%D Greek (moved to here):
+
+\startencoding[default]
+
+% Uppercase Greek letters
+
+\definecharacter greekAlpha {\Alpha}
+\definecharacter greekBeta {\Beta}
+\definecharacter greekGamma {\Gamma}
+\definecharacter greekDelta {\Delta}
+\definecharacter greekEpsilon {\Epsilon}
+\definecharacter greekZeta {\Zeta}
+\definecharacter greekEta {\Eta}
+\definecharacter greekTheta {\Theta}
+\definecharacter greekIota {\Iota}
+\definecharacter greekKappa {\Kappa}
+\definecharacter greekLambda {\Lambda}
+\definecharacter greekMu {\Mu}
+\definecharacter greekNu {\Nu}
+\definecharacter greekXi {\Xi}
+\definecharacter greekOmicron {\Omicron}
+\definecharacter greekPi {\Pi}
+\definecharacter greekRho {\Rho}
+\definecharacter greekSigma {\Sigma}
+\definecharacter greekTau {\Tau}
+\definecharacter greekUpsilon {\Upsilon}
+\definecharacter greekPhi {\Phi}
+\definecharacter greekChi {\Chi}
+\definecharacter greekPsi {\Psi}
+\definecharacter greekOmega {\Omega}
+
+% Lowercase Greek letters
+
+\definecharacter greekalpha {\alpha}
+\definecharacter greekbeta {\beta}
+\definecharacter greekgamma {\gamma}
+\definecharacter greekdelta {\delta}
+\definecharacter greekepsilon {\varepsilon}
+\definecharacter greekepsilonalt {\epsilon}
+\definecharacter greekzeta {\zeta}
+\definecharacter greeketa {\eta}
+\definecharacter greektheta {\theta}
+\definecharacter greekthetaalt {\vartheta}
+\definecharacter greekiota {\iota}
+\definecharacter greekkappa {\kappa}
+\definecharacter greeklambda {\lambda}
+\definecharacter greekmu {\mu}
+\definecharacter greeknu {\nu}
+\definecharacter greekxi {\xi}
+\definecharacter greekomicron {\omicron}
+\definecharacter greekpi {\pi}
+\definecharacter greekrho {\rho}
+\definecharacter greeksigma {\sigma}
+\definecharacter greekfinalsigma {\varsigma}
+\definecharacter greektau {\tau}
+\definecharacter greekupsilon {\upsilon}
+\definecharacter greekphi {\varphi}
+\definecharacter greekphialt {\phi}
+\definecharacter greekchi {\chi}
+\definecharacter greekpsi {\psi}
+\definecharacter greekomega {\omega}
+
+% Accented Uppercase Greek letters
+
+\definecharacter greekAlphatonos {'A}
+\definecharacter greekEpsilontonos {'E}
+\definecharacter greekEtatonos {'H}
+\definecharacter greekIotatonos {'I}
+\definecharacter greekOmicrontonos {'O}
+\definecharacter greekUpsilontonos {'U}
+\definecharacter greekOmegatonos {'W}
+\definecharacter greekIotadialytika {"I}
+\definecharacter greekUpsilondialytika {"U}
+
+% Accented Lowercase Greek letters
+
+\definecharacter greekalphatonos {'a}
+\definecharacter greekepsilontonos {'e}
+\definecharacter greeketatonos {'h}
+\definecharacter greekiotatonos {'i}
+\definecharacter greekomicrontonos {'o}
+\definecharacter greekupsilontonos {'u}
+\definecharacter greekomegatonos {'w}
+\definecharacter greekiotadialytika {"i}
+\definecharacter greekupsilondialytika {"u}
+\definecharacter greekiotadialytikatonos {'"i}
+\definecharacter greekupsilondialytikatonos {'"u}
+
+% Miscellaneous Greek symbols
+
+\definecharacter greekleftquot {((}
+\definecharacter greekrightquot {))}
+\definecharacter greektonos {'}
+\definecharacter greekdialytikatonos {'"}
+\definecharacter greekapostrophos {''}
+
+\stopencoding
+
+%D Cyrillic (moved to here):
+
+\startencoding[default]
+
+\definecharacter cyrillicA {A}
+\definecharacter cyrillicB {B}
+\definecharacter cyrillicV {V}
+\definecharacter cyrillicG {G}
+\definecharacter cyrillicD {D}
+\definecharacter cyrillicE {E}
+\definecharacter cyrillicZH {ZH}
+\definecharacter cyrillicZ {Z}
+\definecharacter cyrillicI {I}
+\definecharacter cyrillicISHRT {ISHRT}
+\definecharacter cyrillicK {K}
+\definecharacter cyrillicL {L}
+\definecharacter cyrillicM {M}
+\definecharacter cyrillicN {N}
+\definecharacter cyrillicO {O}
+\definecharacter cyrillicP {P}
+\definecharacter cyrillicR {R}
+\definecharacter cyrillicS {S}
+\definecharacter cyrillicT {T}
+\definecharacter cyrillicU {U}
+\definecharacter cyrillicF {F}
+\definecharacter cyrillicH {H}
+\definecharacter cyrillicC {C}
+\definecharacter cyrillicCH {CH}
+\definecharacter cyrillicSH {SH}
+\definecharacter cyrillicSHCH {SHCH}
+\definecharacter cyrillicHRDSN {HRDSN}
+\definecharacter cyrillicERY {ERY}
+\definecharacter cyrillicSFTSN {SFTSN}
+\definecharacter cyrillicEREV {EREV}
+\definecharacter cyrillicYU {YU}
+\definecharacter cyrillicYA {YA}
+\definecharacter cyrillicGUP {GUP}
+\definecharacter cyrillicGHCRS {GHCRS}
+\definecharacter cyrillicDJE {DJE}
+\definecharacter cyrillicTSHE {TSHE}
+\definecharacter cyrillicSHHA {SHHA}
+\definecharacter cyrillicZHDSC {ZHDSC}
+\definecharacter cyrillicZDSC {ZDSC}
+\definecharacter cyrillicLJE {LJE}
+\definecharacter cyrillicYI {YI}
+\definecharacter cyrillicKDSC {KDSC}
+\definecharacter cyrillicKBEAK {KBEAK}
+\definecharacter cyrillicKVCRS {KVCRS}
+\definecharacter cyrillicAE {AE}
+\definecharacter cyrillicNDSC {NDSC}
+\definecharacter cyrillicNG {NG}
+\definecharacter cyrillicDZE {DZE}
+\definecharacter cyrillicOTLD {OTLD}
+\definecharacter cyrillicSDSC {SDSC}
+\definecharacter cyrillicUSHRT {USHRT}
+\definecharacter cyrillicY {Y}
+\definecharacter cyrillicYHCRS {YHCRS}
+\definecharacter cyrillicHDSC {HDSC}
+\definecharacter cyrillicDZHE {DZHE}
+\definecharacter cyrillicCHVCRS {CHVCRS}
+\definecharacter cyrillicCHRDSC {CHRDSC}
+\definecharacter cyrillicIE {IE}
+\definecharacter cyrillicSCHWA {SCHWA}
+\definecharacter cyrillicNJE {NJE}
+\definecharacter cyrillicYO {YO}
+\definecharacter cyrillicII {II}
+\definecharacter cyrillicJE {JE}
+\definecharacter cyrillicQ {Q}
+\definecharacter cyrillicW {W}
+
+\definecharacter cyrillica {a}
+\definecharacter cyrillicb {b}
+\definecharacter cyrillicv {v}
+\definecharacter cyrillicg {g}
+\definecharacter cyrillicd {d}
+\definecharacter cyrillice {e}
+\definecharacter cyrilliczh {zh}
+\definecharacter cyrillicz {z}
+\definecharacter cyrillici {i}
+\definecharacter cyrillicishrt {ishrt}
+\definecharacter cyrillick {k}
+\definecharacter cyrillicl {l}
+\definecharacter cyrillicm {m}
+\definecharacter cyrillicn {n}
+\definecharacter cyrillico {o}
+\definecharacter cyrillicp {p}
+\definecharacter cyrillicr {r}
+\definecharacter cyrillics {s}
+\definecharacter cyrillict {t}
+\definecharacter cyrillicu {u}
+\definecharacter cyrillicf {f}
+\definecharacter cyrillich {h}
+\definecharacter cyrillicc {c}
+\definecharacter cyrillicch {ch}
+\definecharacter cyrillicsh {sh}
+\definecharacter cyrillicshch {shch}
+\definecharacter cyrillichrdsn {hrdsn}
+\definecharacter cyrillicery {ery}
+\definecharacter cyrillicsftsn {sftsn}
+\definecharacter cyrillicerev {erev}
+\definecharacter cyrillicyu {yu}
+\definecharacter cyrillicya {ya}
+\definecharacter cyrillicgup {gup}
+\definecharacter cyrillicghcrs {ghcrs}
+\definecharacter cyrillicdje {dje}
+\definecharacter cyrillictshe {tshe}
+\definecharacter cyrillicshha {shha}
+\definecharacter cyrilliczhdsc {zhdsc}
+\definecharacter cyrilliczdsc {zdsc}
+\definecharacter cyrilliclje {lje}
+\definecharacter cyrillicyi {yi}
+\definecharacter cyrillickdsc {kdsc}
+\definecharacter cyrillickbeak {kbeak}
+\definecharacter cyrillickvcrs {kvcrs}
+\definecharacter cyrillicae {ae}
+\definecharacter cyrillicndsc {ndsc}
+\definecharacter cyrillicng {ng}
+\definecharacter cyrillicdze {dze}
+\definecharacter cyrillicotld {otld}
+\definecharacter cyrillicsdsc {sdsc}
+\definecharacter cyrillicushrt {ushrt}
+\definecharacter cyrillicy {y}
+\definecharacter cyrillicyhcrs {yhcrs}
+\definecharacter cyrillichdsc {hdsc}
+\definecharacter cyrillicdzhe {dzhe}
+\definecharacter cyrillicchvcrs {chvcrs}
+\definecharacter cyrillicchrdsc {chrdsc}
+\definecharacter cyrillicie {ie}
+\definecharacter cyrillicschwa {schwa}
+\definecharacter cyrillicnje {nje}
+\definecharacter cyrillicyo {yo}
+\definecharacter cyrillicii {ii}
+\definecharacter cyrillicje {je}
+\definecharacter cyrillicq {q}
+\definecharacter cyrillicw {w}
+
+\definecharacter cyrillicGJE {\'\cyrillicG}
+\definecharacter cyrillicgje {\'\cyrillicg}
+\definecharacter cyrillicKJE {\'\cyrillicK}
+\definecharacter cyrillickje {\'\cyrillick}
+
+\stopencoding
+
+\def\cyrillicio{\cyrillicyo}
+\def\cyrillicIO{\cyrillicYO}
+
+%D Hebrew:
+
+\startencoding[default]
+
+\definecharacter hebrewAlef {'}
+\definecharacter hebrewBet {b}
+\definecharacter hebrewGimel {g}
+\definecharacter hebrewDalet {d}
+\definecharacter hebrewHe {h}
+\definecharacter hebrewVav {w}
+\definecharacter hebrewZayin {z}
+\definecharacter hebrewHet {\hstroke}
+\definecharacter hebrewTet {\tcedilla}
+\definecharacter hebrewYod {y}
+\definecharacter hebrewKaffinal {k}
+\definecharacter hebrewKaf {k}
+\definecharacter hebrewLamed {l}
+\definecharacter hebrewMemfinal {m}
+\definecharacter hebrewMem {m}
+\definecharacter hebrewNunfinal {n}
+\definecharacter hebrewNun {n}
+\definecharacter hebrewSamekh {s}
+\definecharacter hebrewAyin {\gdotaccent}
+\definecharacter hebrewPefinal {p}
+\definecharacter hebrewPe {p}
+\definecharacter hebrewTsadifinal {\scedilla}
+\definecharacter hebrewTsadi {\scedilla}
+\definecharacter hebrewQof {q}
+\definecharacter hebrewResh {r}
+\definecharacter hebrewShin {\scaron}
+\definecharacter hebrewTav {th}
+
+\stopencoding
+
+%D A few goodies:
+
+\def\eszett{\ssharp}
+\def\Eszett{\Ssharp}
+
+\def\lslash{\lstroke}
+\def\Lslash{\Lstroke}
+\def\dslash{\dstroke}
+\def\Dslash{\Dstroke}
+\def\oslash{\ostroke}
+\def\Oslash{\Ostroke}
+
+\def\dcroat{\dstroke}
+\def\Dcroat{\Dstroke}
+
+% \startencoding [default]
+%
+% \definecharacter scommaaccent {\scedilla}
+% \definecharacter Scommaaccent {\Scedilla}
+% \definecharacter tcommaaccent {\tcedilla}
+% \definecharacter Tcommaaccent {\Tcedilla}
+%
+% \stopencoding
+
+% for plain tex's sake
+
+\def\S {\sectionmark }
+\def\P {\paragraphmark}
+
+% for latex users sake
+
+\def\textS {\sectionmark }
+\def\textP {\paragraphmark}
+
+% for old times sake
+
+\def\florin {\textflorin } \def\florijn{\textflorin}
+\def\dollar {\textdollar }
+\def\pound {\textsterling}
+\def\sterling{\textsterling}
+
+% idem
+
+\def\promille{\perthousand}
+\def\permille{\perthousand}
+\def\procent {\percent }
+\def\permine {\fakepermine}
+
+% some more
+
+\def\hyphen {\softhyphen}
+\def\cwm {\compoundwordmark}
+\def\nonbreakinghyphen {\hyphen}
+\def\breakinghyphen {\hyphen\prewordbreak}
+
+% quotes
+
+\def\lowerleftsingleninequote {\quotesinglebase}
+\def\lowerleftdoubleninequote {\quotedblbase}
+\def\lowerrightsingleninequote {\quotesinglebase}
+\def\lowerrightdoubleninequote {\quotedblbase}
+
+\def\upperleftsingleninequote {\quoteright}
+\def\upperleftdoubleninequote {\quotedblright}
+\def\upperrightsingleninequote {\quoteright}
+\def\upperrightdoubleninequote {\quotedblright}
+
+\def\upperleftsinglesixquote {\quoteleft}
+\def\upperleftdoublesixquote {\quotedblleft}
+\def\upperrightsinglesixquote {\quoteleft}
+\def\upperrightdoublesixquote {\quotedblleft}
+
+\def\leftsubguillemot {\guilsingleleft}
+\def\rightsubguillemot {\guilsingleright}
+
+%D A couple of fallbacks suggestion by users, slightly
+%D adapted and obscured by memory saving hacks.
+
+\unprotect
+
+\startencoding[default]
+
+\definecharacter textcent {c\rlap{\hskip-.2\s!em
+ \vrule\!!width.2\s!pt\!!height1.2\s!ex\!!depth.2\s!ex}}
+
+\definecharacter texteuro {C\rlap{\hskip-.75\s!em
+ \vrule\!!width.4\s!em\!!height.85\s!ex\!!depth-.8\s!ex}}
+
+\definecharacter textblacksquare {\dontleavehmode\hbox{%
+ \vrule\!!width.3\s!em\!!height.4\s!em\!!depth-.1\s!em}}
+
+\definecharacter textbrokenbar {\dontleavehmode\hbox{\kern.05\s!em
+ \vrule\!!width.4\s!pt\!!height1.8\s!ex\!!depth-.85\s!ex
+ \llap{%
+ \vrule\!!width.4\s!pt\!!height.35\s!ex\!!depth.6\s!ex}%
+ \kern.05\s!em}}
+
+\stopencoding
+
+\protect
+
+%D We also use symbolic names for math accents.
+
+\startencoding[default]
+
+\definecharacter mathacute "7013
+\definecharacter mathgrave "7012
+\definecharacter mathddot "707F
+\definecharacter mathtilde "707E
+\definecharacter mathbar "7016
+\definecharacter mathbreve "7015
+\definecharacter mathcheck "7014
+\definecharacter mathhat "705E
+\definecharacter mathvec "017E
+\definecharacter mathdot "705F
+\definecharacter mathwidetilde "0365
+\definecharacter mathwidehat "0362
+
+\stopencoding
+
+% \startencoding [default]
+
+% \definecommand prime {\mathematics{'}}
+% \definecommand doubleprime {\mathematics{''}}
+% \definecommand tripleprime {\mathematics{'''}}
+
+% \stopencoding
+
+\ifx\zdot\undefined \def\zdot{\zdotaccent} \fi
+\ifx\Zdot\undefined \def\Zdot{\Zdotaccent} \fi
+
+\ifx\greeklamda\undefined \def\greeklamda{\greeklambda} \fi
+\ifx\greekLamda\undefined \def\greekLamda{\greekLambda} \fi
+
+\ifx\leftguillemet \undefined \def\leftguillemet {\leftguillemot } \fi
+\ifx\rightguillemet\undefined \def\rightguillemet{\rightguillemot} \fi
+
+%D New:
+
+\startencoding[\s!default]
+
+\definecharacter schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}}
+\definecharacter schwagrave {\buildtextgrave\schwa}
+
+\stopencoding
+
+%D Also new, from Taco, for Mojca, who wanted another 8~regimes.
+
+\startencoding[\s!default]
+
+\definecharacter texthorizontalbar {{\endash\kern\zeropoint\endash}}
+\definecharacter textdong {\underbar{\dstroke}}
+
+\stopencoding
+
+%D Goodie (makes more sense):
+
+\def\normalcontrolspace
+ {\getglyph{ComputerModernMono}{\char32}}
+
+\def\fakedcontrolspace % can be virtual in luatex
+ {\dontleavehmode\hbox
+ {\scratchdimen.1ex%
+ \kern\scratchdimen
+ \vrule \!!width\scratchdimen \!!height5.5\scratchdimen \!!depth3\scratchdimen
+ \vrule \!!width\dimexpr.5em-4\scratchdimen\relax \!!height-2\scratchdimen \!!depth3\scratchdimen
+ \vrule \!!width\scratchdimen \!!height5.5\scratchdimen \!!depth3\scratchdimen
+ \kern\scratchdimen}}
+
+\def\fakecontrolspace{\let\normalcontrolspace\fakedcontrolspace}
+
+\endinput
diff --git a/tex/context/base/enco-ec.mkii b/tex/context/base/enco-ec.mkii
new file mode 100644
index 000000000..1ac41cadf
--- /dev/null
+++ b/tex/context/base/enco-ec.mkii
@@ -0,0 +1,295 @@
+%D \module
+%D [ file=enco-ec,
+%D version=2000.05.07, % 1999.16.07,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=\LATEX\ EC Encoding,
+%D author={Patrick Gundlach, Hans Hagen, Taco Hoekwater, Mojca Miklavec},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 is \LATEX2e's T1 encoding vector. All standard \LATEX\
+%D accents will work, including \type{\k}. The only accent that
+%D does not work is \type{\t} (there is no tie in T1 encoding).
+%D
+%D Annoyingly, most \POSTSCRIPT\ fonts do not have \type
+%D {\dotlessj}, and T1 encoding does not make the various
+%D prebuilts with \type {j} available. When this is the case:
+%D
+%D \starttyping
+%D \startencoding[ec]
+%D \definecharacter dotlessj {j}
+%D \stopencoding
+%D \stoptyping
+%D
+%D is a way out.
+
+%D There is hardly a point in supporting TS1 encoding.
+
+\startmapping[ec]
+
+% a problem is that the uppercase of dstroke (158) and eth (240)
+% is the same glyph (208) so we cannot do lowercase mapping there
+
+\definecasemaps 128 to 156 lc +32 uc 0
+\definecasemap 157 `i 157 % Idotaccent i
+\definecasemap 158 158 208 % dstroke Eth
+\definecasemap 159 159 159 % sectionmark
+\definecasemaps 160 to 187 lc 0 uc -32
+\resetcaserange 189 to 191 % exclamdown, questiondown, textsterling
+\definecasemaps 192 to 223 lc +32 uc 0
+\definecasemaps 224 to 254 lc 0 uc -32
+\definecaseswap 255 223 % ssharp (else patterns fail)
+\definecaseswap 25 `I % dotless i
+
+% 156 vs. 188 IJligature
+
+%D Some languages need this:
+
+% \definecaseself 34 % quotedbl
+% \definecaseself 18 % quotedblbase
+% \definecaseself 16 % quotedblleft
+% \definecaseself 17 % quotedblright
+% \definecaseself 39 % quotesingle
+% \definecaseself 13 % quotesinglebase
+% \definecaseself 96 % quoteleft
+% \definecaseself 39 % quoteright
+
+%D So far for the mapping.
+
+%D The following characters are kind of dangerous,
+%D that is, they are normally not part of fonts, unless
+%D explicitly constructed.
+%D
+%D \startitemize[columns,two]
+%D \item \type{\dotlessj} - but then it may not be defined!!!!
+%D \item \type{\IJligature}
+%D \item \type{\ijligature}
+%D \item \type{\Ssharp}
+%D \item \type{\perthousand}
+%D \item \type{\compoundwordmark}
+% \item \type{\textvisiblespace}
+%D \stopitemize
+
+%D So, for the moment we nil them; we can always create
+%D another vector if needed.
+
+\stopmapping
+
+\startencoding[ec][ec] % second arg defines auto regime, needed here ?
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter texthungarumlaut 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter textogonek 12
+\definecharacter quotesinglebase 13
+\definecharacter guilsingleleft 14
+\definecharacter guilsingleright 15
+\definecharacter quotedblleft 16
+\definecharacter quotedblright 17
+\definecharacter quotedblbase 18
+\definecharacter leftguillemot 19
+\definecharacter rightguillemot 20
+\definecharacter endash 21
+\definecharacter emdash 22
+%definecharacter compoundwordmark 23
+%definecharacter perthousand 24
+\definecharacter dotlessi 25 % or when missing: {j}
+\definecharacter dotlessj 26
+% ff 27
+% fi 28
+% fl 29
+% ffi 30
+% ffl 31
+%definecharacter textvisiblespace 32
+% exclam ! 33
+\definecharacter quotedbl 34
+% numbersign # 35
+% dollar $ 36
+\definecharacter percent 37
+% ampersand & 38
+%definecharacter quotesingle 39 % fake 'm TODO:enco-def!!!!
+\definecharacter quoteright 39
+% parenleft ( 40
+% parenright ) 41
+% asterisk * 42
+% plus + 43
+% comma , 44
+\definecharacter softhyphen 45
+% period . 46
+% slash / 47
+% 0-9 48-57
+% colon : 58
+% semicolon ; 59
+% less < 60
+% equal = 61
+% greater > 62
+% question ? 63
+% at @ 64
+% A-Z 65-90
+% bracketleft [ 91
+\definecharacter textbackslash 92
+% bracketright ] 93
+\definecharacter textasciicircum 94
+\definecharacter textunderscore 95
+\definecharacter quoteleft 96
+% a-z 97-122
+\definecharacter textbraceleft 123
+\definecharacter textbraceright 125
+\definecharacter textasciitilde 126
+%definecharacter softhyphen 127 % -> 45 (127 often undefined)
+\definecharacter Abreve 128 % abreve 160
+\definecharacter Aogonek 129 % aogonek 161
+\definecharacter Cacute 130 % cacute 162
+\definecharacter Ccaron 131 % ccaron 163
+\definecharacter Dcaron 132 % dcaron 164
+\definecharacter Ecaron 133 % ecaron 165
+\definecharacter Eogonek 134 % eogonek 166
+\definecharacter Gbreve 135 % gbreve 167
+\definecharacter Lacute 136 % lacute 168
+\definecharacter Lcaron 137 % lcaron 169
+\definecharacter Lstroke 138 % lstroke 170
+\definecharacter Nacute 139 % nacute 171
+\definecharacter Ncaron 140 % ncaron 172
+\definecharacter Eng 141 % eng 173
+\definecharacter Neng 141 % Neng 173
+\definecharacter Ohungarumlaut 142 % ohungarumlaut 174
+\definecharacter Racute 143 % racute 175
+\definecharacter Rcaron 144 % rcaron 176
+\definecharacter Sacute 145 % sacute 177
+\definecharacter Scaron 146 % scaron 178
+\definecharacter Scedilla 147 % scedilla 179
+\definecharacter Tcaron 148 % tcaron 180
+\definecharacter Tcedilla 149 % tcedilla 181
+\definecharacter Uhungarumlaut 150 % uhungarumlaut 182
+\definecharacter Uring 151 % uring 183
+\definecharacter Ydiaeresis 152 % ydiaeresis 184
+\definecharacter Zacute 153 % zacute 185
+\definecharacter Zcaron 154 % zcaron 186
+\definecharacter Zdotaccent 155 % zdotaccent 187
+\definecharacter IJligature 156 % ijligature 188
+\definecharacter Idotaccent 157
+\definecharacter dstroke 158 % Dstroke 208
+\definecharacter sectionmark 159
+\definecharacter abreve 160 % Abreve 128
+\definecharacter aogonek 161 % Aogonek 129
+\definecharacter cacute 162 % Cacute 130
+\definecharacter ccaron 163 % Ccaron 131
+\definecharacter dcaron 164 % Dcaron 132
+\definecharacter ecaron 165 % Ecaron 133
+\definecharacter eogonek 166 % Eogonek 134
+\definecharacter gbreve 167 % Gbreve 135
+\definecharacter lacute 168 % Lacute 136
+\definecharacter lcaron 169 % Lcaron 137
+\definecharacter lstroke 170 % Lstroke 138
+\definecharacter nacute 171 % Nacute 139
+\definecharacter ncaron 172 % Ncaron 140
+\definecharacter eng 173 % Eng 141
+\definecharacter ohungarumlaut 174 % Ohungarumlaut 142
+\definecharacter racute 175 % Racute 143
+\definecharacter rcaron 176 % Rcaron 144
+\definecharacter sacute 177 % Sacute 145
+\definecharacter scaron 178 % Scaron 146
+\definecharacter scedilla 179 % Scedilla 147
+\definecharacter tcaron 180 % Tcaron 148
+\definecharacter tcedilla 181 % Tcedilla 149
+\definecharacter uhungarumlaut 182 % Uhungarumlaut 150
+\definecharacter uring 183 % Uring 151
+\definecharacter ydiaeresis 184 % Ydiaeresis 152
+\definecharacter zacute 185 % Zacute 153
+\definecharacter zcaron 186 % Zcaron 154
+\definecharacter zdotaccent 187 % Zdotaccent 155
+\definecharacter ijligature 188 % IJligature 156
+\definecharacter exclamdown 189
+\definecharacter questiondown 190
+\definecharacter textsterling 191
+\definecharacter Agrave 192 % agrave 224
+\definecharacter Aacute 193 % aacute 225
+\definecharacter Acircumflex 194 % acircumflex 226
+\definecharacter Atilde 195 % atilde 227
+\definecharacter Adiaeresis 196 % adiaeresis 228
+\definecharacter Aring 197 % aring 229
+\definecharacter AEligature 198 % aeligature 230
+\definecharacter Ccedilla 199 % ccedilla 231
+\definecharacter Egrave 200 % egrave 232
+\definecharacter Eacute 201 % eacute 233
+\definecharacter Ecircumflex 202 % ecircumflex 234
+\definecharacter Ediaeresis 203 % ediaeresis 235
+\definecharacter Igrave 204 % igrave 236
+\definecharacter Iacute 205 % iacute 237
+\definecharacter Icircumflex 206 % icircumflex 238
+\definecharacter Idiaeresis 207 % idiaeresis 239
+\definecharacter Eth 208 % eth 240
+\definecharacter Dstroke 208 % dstroke 158
+\definecharacter Ntilde 209 % ntilde 241
+\definecharacter Ograve 210 % ograve 242
+\definecharacter Oacute 211 % oacute 243
+\definecharacter Ocircumflex 212 % ocircumflex 244
+\definecharacter Otilde 213 % otilde 245
+\definecharacter Odiaeresis 214 % odiaeresis 246
+\definecharacter OEligature 215 % oeligature 247
+\definecharacter Ostroke 216 % ostroke 248
+\definecharacter Ugrave 217 % ugrave 249
+\definecharacter Uacute 218 % uacute 250
+\definecharacter Ucircumflex 219 % ucircumflex 251
+\definecharacter Udiaeresis 220 % udiaeresis 252
+\definecharacter Yacute 221 % yacute 253
+\definecharacter Thorn 222 % thorn 254
+\definecharacter Ssharp 223 % ssharp 255
+\definecharacter agrave 224 % Agrave 192
+\definecharacter aacute 225 % Aacute 193
+\definecharacter acircumflex 226 % Acircumflex 194
+\definecharacter atilde 227 % Atilde 195
+\definecharacter adiaeresis 228 % Adiaeresis 196
+\definecharacter aring 229 % Aring 197
+\definecharacter aeligature 230 % AEligature 198
+\definecharacter ccedilla 231 % Ccedilla 199
+\definecharacter egrave 232 % Egrave 200
+\definecharacter eacute 233 % Eacute 201
+\definecharacter ecircumflex 234 % Ecircumflex 202
+\definecharacter ediaeresis 235 % Ediaeresis 203
+\definecharacter igrave 236 % Igrave 204
+\definecharacter iacute 237 % Iacute 205
+\definecharacter icircumflex 238 % Icircumflex 206
+\definecharacter idiaeresis 239 % Idiaeresis 207
+\definecharacter eth 240 % Eth 208
+\definecharacter ntilde 241 % Ntilde 209
+\definecharacter ograve 242 % Ograve 210
+\definecharacter oacute 243 % Oacute 211
+\definecharacter ocircumflex 244 % Ocircumflex 212
+\definecharacter otilde 245 % Otilde 213
+\definecharacter odiaeresis 246 % Odiaeresis 214
+\definecharacter oeligature 247 % OEligature 215
+\definecharacter ostroke 248 % Ostroke 216
+\definecharacter ugrave 249 % Ugrave 217
+\definecharacter uacute 250 % Uacute 218
+\definecharacter ucircumflex 251 % Ucircumflex 219
+\definecharacter udiaeresis 252 % Udiaeresis 220
+\definecharacter yacute 253 % Yacute 221
+\definecharacter thorn 254 % Thorn 222
+\definecharacter ssharp 255 % Ssharp 223
+
+\stopencoding
+
+\startencoding[ec]
+
+\definecharacter Scommaaccent {\Scedilla}
+\definecharacter scommaaccent {\scedilla}
+\definecharacter Tcommaaccent {\Tcedilla}
+\definecharacter tcommaaccent {\tcedilla}
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-ecm.mkii b/tex/context/base/enco-ecm.mkii
new file mode 100644
index 000000000..b74473960
--- /dev/null
+++ b/tex/context/base/enco-ecm.mkii
@@ -0,0 +1,33 @@
+%D \module
+%D [ file=enco-ec,
+%D version=2000.05.07,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Glyphs that may not be present in EC,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 next typescript removes a few problematic characters
+%D from the ec encoding vector. So, in case of troubles, say
+%D
+%D \starttyping
+%D \useencoding[ecm] % ec minus
+%D \stoptyping
+
+\startencoding[ec][ec]
+
+\definecharacter ijligature {ij}
+\definecharacter IJligature {IJ}
+\definecharacter Ssharp {SS}
+\definecharacter tcaron {\buildtextaccent\textcaron t}
+\definecharacter Tcedilla {\buildtextcedilla T}
+\definecharacter tcedilla {\buildtextcedilla t}
+\definecharacter ydiaeresis {\buildtextaccent\textdiaeresis y}
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-el.mkii b/tex/context/base/enco-el.mkii
new file mode 100644
index 000000000..24729967b
--- /dev/null
+++ b/tex/context/base/enco-el.mkii
@@ -0,0 +1,272 @@
+%D \module
+%D [ file=enco-el,
+%D version=2005.08.24,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=EuroLetter,
+%D author={Several Users},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 EuroLetter encoding vector, also known as Dense Encoding is
+%D the result of discussion among users, most noticably Adam Lindsay,
+%D Mojka Miklavec, Patrick Gundlach, Taco Hoekwater and \unknown.
+%D It was a follow up of a thread started long ago where we
+%D discussed an encoding without the weird, never used symbols, but
+%D with as many characters as possible in order to support the utf-8
+%D input regime.
+
+\startencoding[el]
+
+\definecasemaps 1 to 15 lc +16 uc 0
+\definecasemaps 17 to 31 lc 0 uc -16
+
+\definecasemaps 128 to 159 lc +32 uc 0
+\definecasemaps 160 to 191 lc 0 uc -32
+
+\definecasemaps 192 to 223 lc +32 uc 0
+\definecasemaps 224 to 255 lc 0 uc -32
+
+\definecasemap 92 92 124
+\definecasemap 92 124 92
+
+\definecharacter dotlessi 160
+\definecharacter endash 32
+\definecharacter emdash 16
+
+\definecharacter aeligature 230
+\definecharacter AEligature 198
+\definecharacter oeligature 247
+\definecharacter OEligature 215
+
+\definecharacter ssharp 38
+
+\definecharacter thorn 254
+\definecharacter Thorn 222
+
+\definecharacter eth 240
+\definecharacter Eth 208
+
+\definecharacter exclamdown 42
+\definecharacter questiondown 43
+
+\definecharacter quotedbl 35
+\definecharacter quotedblbase 36
+\definecharacter quotedblleft 34
+\definecharacter quotedblright 35
+
+\definecharacter quotesingle 39
+\definecharacter quotesinglebase 0
+
+\definecharacter quoteleft 96
+\definecharacter quoteright 39
+
+\definecharacter guilsingleleft 60
+\definecharacter guilsingleright 62
+
+\definecharacter leftguillemot 123
+\definecharacter rightguillemot 125
+
+\definecharacter Acircumflex 194
+\definecharacter acircumflex 226
+%definecharacter Ccircumflex {\buildtextaccent\textcircumflex C}
+%definecharacter ccircumflex {\buildtextaccent\textcircumflex c}
+\definecharacter Ecircumflex 202
+\definecharacter ecircumflex 234
+%definecharacter Gcircumflex {\buildtextaccent\textcircumflex G}
+%definecharacter gcircumflex {\buildtextaccent\textcircumflex g}
+%definecharacter Hcircumflex {\buildtextaccent\textcircumflex H}
+%definecharacter hcircumflex {\buildtextaccent\textcircumflex h}
+\definecharacter Icircumflex 206
+\definecharacter icircumflex 238
+%definecharacter Jcircumflex {\buildtextaccent\textcircumflex \dotlessJ}
+%definecharacter jcircumflex {\buildtextaccent\textcircumflex \dotlessj}
+\definecharacter Ocircumflex 212
+\definecharacter ocircumflex 244
+%definecharacter Scircumflex {\buildtextaccent\textcircumflex S}
+%definecharacter scircumflex {\buildtextaccent\textcircumflex s}
+\definecharacter Ucircumflex 219
+\definecharacter ucircumflex 251
+\definecharacter Wcircumflex 154
+\definecharacter wcircumflex 186
+\definecharacter Ycircumflex 156
+\definecharacter ycircumflex 188
+
+\definecharacter Agrave 192
+\definecharacter agrave 224
+\definecharacter Egrave 200
+\definecharacter egrave 232
+\definecharacter Igrave 204
+\definecharacter igrave 236
+\definecharacter Ograve 210
+\definecharacter ograve 242
+\definecharacter Ugrave 217
+\definecharacter ugrave 249
+\definecharacter Ygrave 155
+\definecharacter ygrave 187
+
+\definecharacter Atilde 195
+\definecharacter atilde 227
+%definecharacter Itilde {\buildtextaccent\texttilde \dotlessI}
+%definecharacter itilde {\buildtextaccent\texttilde \dotlessi}
+\definecharacter Ntilde 209
+\definecharacter ntilde 241
+\definecharacter Otilde 213
+\definecharacter otilde 245
+%definecharacter Utilde {\buildtextaccent\texttilde U}
+%definecharacter utilde {\buildtextaccent\texttilde u}
+%definecharacter Ytilde {\buildtextaccent\texttilde Y}
+%definecharacter ytilde {\buildtextaccent\texttilde y}
+
+\definecharacter Adiaeresis 196
+\definecharacter adiaeresis 228
+\definecharacter Ediaeresis 203
+\definecharacter ediaeresis 235
+\definecharacter Idiaeresis 207
+\definecharacter idiaeresis 239
+\definecharacter Odiaeresis 214
+\definecharacter odiaeresis 246
+\definecharacter Udiaeresis 220
+\definecharacter udiaeresis 252
+\definecharacter Ydiaeresis 223
+\definecharacter ydiaeresis 255
+
+\definecharacter Aacute 193
+\definecharacter aacute 225
+\definecharacter Cacute 4
+\definecharacter cacute 20
+\definecharacter Eacute 201
+\definecharacter eacute 233
+\definecharacter Iacute 205
+\definecharacter iacute 237
+\definecharacter Lacute 132
+\definecharacter lacute 164
+\definecharacter Nacute 136
+\definecharacter nacute 168
+\definecharacter Oacute 211
+\definecharacter oacute 243
+\definecharacter Racute 141
+\definecharacter racute 173
+\definecharacter Sacute 144
+\definecharacter sacute 176
+\definecharacter Uacute 218
+\definecharacter uacute 250
+\definecharacter Yacute 221
+\definecharacter yacute 253
+\definecharacter Zacute 157
+\definecharacter zacute 189
+
+\definecharacter Dstroke 8
+\definecharacter dstroke 24
+\definecharacter Hstroke 92
+\definecharacter hstroke 124
+%definecharacter Tstroke {T}
+%definecharacter tstroke {t}
+
+\definecharacter Cdotaccent 6
+\definecharacter cdotaccent 22
+\definecharacter Edotaccent 10
+\definecharacter edotaccent 26
+\definecharacter Gdotaccent 15
+\definecharacter gdotaccent 31
+\definecharacter Idotaccent 128
+%definecharacter idotaccent {\buildtextaccent\textdotaccent \dotlessi}
+\definecharacter Zdotaccent 159
+\definecharacter zdotaccent 191
+
+\definecharacter Amacron 2
+\definecharacter amacron 18
+\definecharacter Emacron 11
+\definecharacter emacron 27
+\definecharacter Imacron 129
+\definecharacter imacron 161
+\definecharacter Omacron 140
+\definecharacter omacron 172
+\definecharacter Umacron 152
+\definecharacter umacron 184
+
+\definecharacter Ccedilla 199
+\definecharacter ccedilla 231
+\definecharacter Scedilla 146
+\definecharacter scedilla 178
+
+\definecharacter Gcommaaccent 14
+\definecharacter gcommaaccent 30
+\definecharacter Kcommaaccent 131
+\definecharacter kcommaaccent 163
+\definecharacter Lcommaaccent 135
+\definecharacter lcommaaccent 167
+\definecharacter Ncommaaccent 138
+\definecharacter ncommaaccent 170
+\definecharacter Rcommaaccent 143
+\definecharacter rcommaaccent 175
+%definecharacter Tcedilla 149 % there is no tcedilla in encoding
+%definecharacter tcedilla 181
+
+\definecharacter Scommaaccent 147
+\definecharacter scommaaccent 179
+\definecharacter Tcommaaccent 149
+\definecharacter tcommaaccent 181
+
+\definecharacter Ohungarumlaut 139
+\definecharacter ohungarumlaut 171
+\definecharacter Uhungarumlaut 150
+\definecharacter uhungarumlaut 182
+
+\definecharacter Aogonek 3
+\definecharacter aogonek 19
+\definecharacter Eogonek 12
+\definecharacter eogonek 28
+\definecharacter Iogonek 130
+\definecharacter iogonek 162
+\definecharacter Uogonek 153
+\definecharacter uogonek 185
+
+\definecharacter Aring 197
+\definecharacter aring 229
+\definecharacter Uring 151
+\definecharacter uring 183
+
+\definecharacter Abreve 1
+\definecharacter abreve 17
+%definecharacter Ebreve {\buildtextaccent\textbreve E}
+%definecharacter ebreve {\buildtextaccent\textbreve e}
+\definecharacter Gbreve 13
+\definecharacter gbreve 29
+%definecharacter Ibreve {\buildtextaccent\textbreve \dotlessI}
+%definecharacter ibreve {\buildtextaccent\textbreve \dotlessi}
+%definecharacter Obreve {\buildtextaccent\textbreve O}
+%definecharacter obreve {\buildtextaccent\textbreve o}
+%definecharacter Ubreve {\buildtextaccent\textbreve U}
+%definecharacter ubreve {\buildtextaccent\textbreve u}
+
+\definecharacter Ccaron 5
+\definecharacter ccaron 21
+\definecharacter Dcaron 7
+\definecharacter dcaron 23
+\definecharacter Ecaron 9
+\definecharacter ecaron 25
+\definecharacter Lcaron 133
+\definecharacter lcaron 165
+\definecharacter Ncaron 137
+\definecharacter ncaron 169
+\definecharacter Rcaron 142
+\definecharacter rcaron 174
+\definecharacter Scaron 145
+\definecharacter scaron 177
+\definecharacter Tcaron 148
+\definecharacter tcaron 180
+%definecharacter Ycaron {\buildtextaccent\textcaron Y}
+%definecharacter ycaron {\buildtextaccent\textcaron y}
+\definecharacter Zcaron 158
+\definecharacter zcaron 190
+
+\definecharacter Lstroke 134
+\definecharacter lstroke 166
+\definecharacter Ostroke 216
+\definecharacter ostroke 248
+
+\stopencoding
diff --git a/tex/context/base/enco-fde.mkii b/tex/context/base/enco-fde.mkii
new file mode 100644
index 000000000..a7c11abfc
--- /dev/null
+++ b/tex/context/base/enco-fde.mkii
@@ -0,0 +1,128 @@
+%D \module
+%D [ file=enco-fde,
+%D version=2000.08.20,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=German Input Filter,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\doifmode{mkiv}{\endinput}
+
+\unprotect
+
+\installactivecharacter "
+
+\startlanguagespecifics[\s!de]
+
+ \installcompoundcharacter "a {\aumlaut\midworddiscretionary}
+ \installcompoundcharacter "e {\eumlaut\midworddiscretionary}
+ \installcompoundcharacter "i {\iumlaut\midworddiscretionary}
+ \installcompoundcharacter "o {\oumlaut\midworddiscretionary}
+ \installcompoundcharacter "u {\uumlaut\midworddiscretionary}
+ \installcompoundcharacter "s {\ssharp}
+ \installcompoundcharacter "z {\ssharp}
+
+ \installcompoundcharacter "A {\Aumlaut}
+ \installcompoundcharacter "E {\Eumlaut}
+ \installcompoundcharacter "I {\Iumlaut}
+ \installcompoundcharacter "O {\Oumlaut}
+ \installcompoundcharacter "U {\Uumlaut}
+ \installcompoundcharacter "Z {SZ}
+ \installcompoundcharacter "S {SS}
+
+\stoplanguagespecifics
+
+\startlanguagespecifics[\s!de]
+
+ \installcompoundcharacter "ck {\discretionary {k-}{k}{ck}}
+ \installcompoundcharacter "ff {\discretionary{ff-}{f}{ff}}
+ \installcompoundcharacter "ll {\discretionary{ll-}{l}{ll}}
+ \installcompoundcharacter "mm {\discretionary{mm-}{m}{mm}}
+ \installcompoundcharacter "nn {\discretionary{nn-}{n}{nn}}
+ \installcompoundcharacter "pp {\discretionary{pp-}{p}{pp}}
+ \installcompoundcharacter "rr {\discretionary{rr-}{r}{rr}}
+ \installcompoundcharacter "tt {\discretionary{tt-}{t}{tt}}
+
+ \installcompoundcharacter "CK {\discretionary {K-}{K}{CK}}
+ \installcompoundcharacter "FF {\discretionary{FF-}{F}{FF}}
+ \installcompoundcharacter "LL {\discretionary{LL-}{L}{LL}}
+ \installcompoundcharacter "MM {\discretionary{MM-}{M}{MM}}
+ \installcompoundcharacter "NN {\discretionary{NN-}{N}{NN}}
+ \installcompoundcharacter "PP {\discretionary{PP-}{P}{PP}}
+ \installcompoundcharacter "RR {\discretionary{RR-}{R}{RR}}
+ \installcompoundcharacter "TT {\discretionary{TT-}{T}{TT}}
+
+\stoplanguagespecifics
+
+\startlanguagespecifics[\s!de]
+
+ \installcompoundcharacter "` {\startdelimitedtext[\v!quotation]}
+ \installcompoundcharacter "' {\stopdelimitedtext}
+ \installcompoundcharacter ". {\kern.1em\ignorespaces}
+
+ %installcompoundcharacter "` {\languageparameter\c!leftquotation }
+ %installcompoundcharacter "' {\languageparameter\c!rightquotation}
+
+ \def\setupDElanguage
+ {\setuplanguage
+ [\s!de]
+ [\c!leftsentence=\leftguillemot,
+ \c!rightsentence=\rightguillemot,
+ \c!leftsubsentence=\leftsubguillemot,
+ \c!rightsubsentence=\rightsubguillemot]}
+
+ \installcompoundcharacter "< {{\setupDElanguage|<|}}
+ \installcompoundcharacter "> {{\setupDElanguage|>|}}
+ \installcompoundcharacter "| {|*|}
+
+\stoplanguagespecifics
+
+% \hyphenatedword{hinauff|*|liegen}
+% \hyphenatedword{hinauff"|liegen}
+
+%D An experimental hack:
+
+% no {\simplifiedcompoundcharacter"}
+
+% \startencoding[pdfdoc]
+% \startlanguagespecifics[\s!de]% hm, a % is needed
+% \defineactivecharacter " {\"}
+% \stoplanguagespecifics
+% \stopencoding
+
+\startencoding[ec]
+ \startlanguagespecifics[\s!de]%
+ \installcompoundcharacter "a {\adiaeresis}
+ \installcompoundcharacter "e {\ediaeresis}
+ \installcompoundcharacter "i {\idiaeresis}
+ \installcompoundcharacter "o {\odiaeresis}
+ \installcompoundcharacter "u {\udiaeresis}
+ \installcompoundcharacter "A {\Adiaeresis}
+ \installcompoundcharacter "E {\Ediaeresis}
+ \installcompoundcharacter "I {\Idiaeresis}
+ \installcompoundcharacter "O {\Odiaeresis}
+ \installcompoundcharacter "U {\Udiaeresis}
+ \stoplanguagespecifics
+\stopencoding
+
+\startencoding[texnansi]
+ \startlanguagespecifics[\s!de]%
+ \installcompoundcharacter "a {\adiaeresis}
+ \installcompoundcharacter "e {\ediaeresis}
+ \installcompoundcharacter "i {\idiaeresis}
+ \installcompoundcharacter "o {\odiaeresis}
+ \installcompoundcharacter "u {\udiaeresis}
+ \installcompoundcharacter "A {\Adiaeresis}
+ \installcompoundcharacter "E {\Ediaeresis}
+ \installcompoundcharacter "I {\Idiaeresis}
+ \installcompoundcharacter "O {\Odiaeresis}
+ \installcompoundcharacter "U {\Udiaeresis}
+ \stoplanguagespecifics
+\stopencoding
+
+\protect \endinput
diff --git a/tex/context/base/enco-ffr.mkii b/tex/context/base/enco-ffr.mkii
new file mode 100644
index 000000000..093cc6500
--- /dev/null
+++ b/tex/context/base/enco-ffr.mkii
@@ -0,0 +1,57 @@
+%D \module
+%D [ file=enco-ffr,
+%D version=2002.05.07,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=French Input Filter,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\doifmode{mkiv}{\endinput}
+
+% \definehspace[fr][:][.25em]
+% \definehspace[fr][;][.25em]
+% \definehspace[fr][!][.25em]
+% \definehspace[fr][?][.25em]
+
+\enablemode[activecolon] \usemodule[tryout] % for the moment
+
+\installactivecharacter :
+\installactivecharacter ;
+\installactivecharacter ?
+\installactivecharacter !
+
+\unprotect
+
+\startlanguagespecifics[\s!fr]
+ \definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentmainlanguage{:}:}
+ \definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentmainlanguage{;};}
+ \definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentmainlanguage{?}?}
+ \definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentmainlanguage{!}!}
+\stoplanguagespecifics
+
+\startlanguagespecifics[\s!fr]
+ \defineactivecharacter : {\mathortext{:}{\directdiscretionary{:}}}
+ \defineactivecharacter ; {\mathortext{;}{\directdiscretionary{;}}}
+ \defineactivecharacter ! {\mathortext{!}{\directdiscretionary{!}}}
+ \defineactivecharacter ? {\mathortext{?}{\directdiscretionary{?}}}
+\stoplanguagespecifics
+
+\appendtoks % maybe everywhere
+ \chardef\activecharactermode\zerocount
+\to\everyMPgraphic
+
+% maybe tricky due to possible name clashes:
+%
+% \def\ieme {\highordinalstr{e}}
+% \def\iemes{\highordinalstr{es}}
+% \def\ier {\highordinalstr{er}}
+% \def\iers {\highordinalstr{ers}}
+% \def\iere {\highordinalstr{re}}
+% \def\ieres{\highordinalstr{res}}
+
+\protect \endinput
diff --git a/tex/context/base/enco-fpl.mkii b/tex/context/base/enco-fpl.mkii
new file mode 100644
index 000000000..14d102ff1
--- /dev/null
+++ b/tex/context/base/enco-fpl.mkii
@@ -0,0 +1,98 @@
+%D \module
+%D [ file=enco-fpl,
+%D version=2000.08.20,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Polish Input Filter,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%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 These definitions used to be part of lang-sla.tex.
+
+\unprotect
+
+% todo : named glyphs
+
+\installactivecharacter /
+
+\startlanguagespecifics[\s!pl]
+
+% \appendtoks \makecharacteractive / \to \everynormalcatcodes % obsolete
+
+ \installcompoundcharacter /a {\aogonek}
+ \installcompoundcharacter /c {\cacute}
+ \installcompoundcharacter /e {\eogonek}
+ \installcompoundcharacter /l {\lstroke}
+ \installcompoundcharacter /n {\nacute}
+ \installcompoundcharacter /o {\oacute}
+ \installcompoundcharacter /s {\sacute}
+ \installcompoundcharacter /x {\zacute}
+ \installcompoundcharacter /z {\zdotaccent}
+ \installcompoundcharacter /A {\Aogonek}
+ \installcompoundcharacter /C {\Cacute}
+ \installcompoundcharacter /E {\Eogonek}
+ \installcompoundcharacter /L {\Lstroke}
+ \installcompoundcharacter /N {\Nacute}
+ \installcompoundcharacter /O {\Oacute}
+ \installcompoundcharacter /S {\Sacute}
+ \installcompoundcharacter /X {\Zacute}
+ \installcompoundcharacter /Z {\Zdotaccent}
+
+\stoplanguagespecifics
+
+\startlanguagespecifics[\s!pl]
+
+ \installcompoundcharacter /, {\handlequotation\c!leftquotation}
+ \installcompoundcharacter /' {\handlequotation\c!rightquotation}
+
+ \def\setupPLlanguage%
+ {\setuplanguage
+ [\s!pl]
+ [\c!leftsentence=\leftguillemot,
+ \c!rightsentence=\rightguillemot,
+ \c!leftsubsentence=\leftsubguillemot,
+ \c!rightsubsentence=\rightsubguillemot]}
+
+ \installcompoundcharacter /< {{\setupPLlanguage|<|}}
+ \installcompoundcharacter /> {{\setupPLlanguage|>|}}
+
+ \installcompoundcharacter /- {|-|}
+
+\stoplanguagespecifics
+
+% obsolete
+%
+% \startlanguagespecifics[\s!pl]
+%
+% \definesortkey {/a}{a}{a}{\k a}
+% \definesortkey {/A}{a}{a}{\k a}
+% \definesortkey {/c}{c}{a}{\'c}
+% \definesortkey {/C}{c}{a}{\'c}
+% \definesortkey {/e}{e}{a}{\k e}
+% \definesortkey {/E}{e}{a}{\k e}
+% \definesortkey {/l}{l}{a}{\l }
+% \definesortkey {/L}{l}{a}{\l }
+% \definesortkey {/n}{n}{a}{\'n}
+% \definesortkey {/N}{n}{a}{\'n}
+% \definesortkey {/o}{o}{a}{\'o}
+% \definesortkey {/O}{o}{a}{\'o}
+% \definesortkey {/s}{s}{a}{\'s}
+% \definesortkey {/S}{s}{a}{\'s}
+% \definesortkey {/x}{z}{a}{\'x}
+% \definesortkey {/X}{z}{a}{\'x}
+% \definesortkey {/z}{z}{b}{\.z}
+% \definesortkey {/Z}{z}{b}{\.z}
+%
+% \stoplanguagespecifics
+
+\startencoding[pdfdoc]
+ \startlanguagespecifics[pl]% hm
+ \defineactivecharacter / {\simplifiedcompoundcharacter/}
+ \stoplanguagespecifics
+\stopencoding
+
+\protect \endinput
diff --git a/tex/context/base/enco-fro.mkii b/tex/context/base/enco-fro.mkii
new file mode 100644
index 000000000..e5f5e1257
--- /dev/null
+++ b/tex/context/base/enco-fro.mkii
@@ -0,0 +1,35 @@
+%D \module
+%D [ file=enco-fro,
+%D version=2000.08.20,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Romanian Input Filter,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%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 These definitions used to be part of lang-ita.tex.
+
+\unprotect
+
+\installactivecharacter "
+
+\startlanguagespecifics[\s!ro]
+
+ \installcompoundcharacter "a {\acircumflex}
+ \installcompoundcharacter "i {\icircumflex}
+ \installcompoundcharacter "s {\scedilla}
+ \installcompoundcharacter "t {\tcedilla}
+ \installcompoundcharacter "A {\Acircumflex}
+ \installcompoundcharacter "I {\Icircumflex}
+ \installcompoundcharacter "S {\Scedilla}
+ \installcompoundcharacter "T {\Tcedilla}
+ \installcompoundcharacter "` {\startdelimitedtext[\v!quotation]}
+ \installcompoundcharacter "' {\stopdelimitedtext}
+
+\stoplanguagespecifics
+
+\protect \endinput
diff --git a/tex/context/base/enco-fsl.mkii b/tex/context/base/enco-fsl.mkii
new file mode 100644
index 000000000..86a41c88a
--- /dev/null
+++ b/tex/context/base/enco-fsl.mkii
@@ -0,0 +1,32 @@
+%D \module
+%D [ file=enco-fsl,
+%D version=2005.08.17,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Slovenian Specialities,
+%D author={Hans Hagen, Mojka Miklavec},
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%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 Usage:
+%D
+%D \starttyping
+%D \useencoding[fsl]
+%D
+%D \starttext
+%D \dstroke \language[sl] \dstroke
+%D \stoptext
+%D \stoptyping
+
+\unprotect
+
+\startlanguagespecifics[\s!sl]
+ \startencoding[\s!default]
+ \definecharacter dstroke {d\zcaron} % hm, expects a space delimiter
+ \stopencoding
+\stoplanguagespecifics
+
+\protect \endinput
diff --git a/tex/context/base/enco-grk.mkii b/tex/context/base/enco-grk.mkii
new file mode 100644
index 000000000..882a3c9b0
--- /dev/null
+++ b/tex/context/base/enco-grk.mkii
@@ -0,0 +1,190 @@
+%D \module
+%D [ file=enco-grk,
+%D version=2003.03.01,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Greek,
+%D author=Apostolos Syropoulos,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startmapping[iso-8859-7]
+
+% Uppercase Greek letters
+
+\definecasemap 193 193 225 % greekAlpha
+\definecasemap 194 194 226 % greekBeta
+\definecasemap 195 195 227 % greekGamma
+\definecasemap 196 196 228 % greekDelta
+\definecasemap 197 197 229 % greekEpsilon
+\definecasemap 198 198 230 % greekZeta
+\definecasemap 199 199 213 % greekEta
+\definecasemap 200 200 232 % greekTheta
+\definecasemap 201 201 233 % greekIota
+\definecasemap 202 202 234 % greekKappa
+\definecasemap 203 203 235 % greekLambda
+\definecasemap 204 204 236 % greekMu
+\definecasemap 205 205 237 % greekNu
+\definecasemap 206 206 238 % greekXi
+\definecasemap 207 207 239 % greekOmicron
+\definecasemap 208 208 240 % greekPi
+\definecasemap 209 209 241 % greekRho
+\definecasemap 211 211 243 % greekSigma
+\definecasemap 212 212 244 % greekTau
+\definecasemap 213 213 245 % greekUpsilon
+\definecasemap 214 214 246 % greekPhi
+\definecasemap 215 215 247 % greekChi
+\definecasemap 216 216 248 % greekPsi
+\definecasemap 217 217 249 % greekOmega
+
+% Lowercase Greek letters
+
+\definecasemap 225 193 225 % greekalpha
+\definecasemap 226 194 226 % greekbeta
+\definecasemap 227 195 227 % greekgamma
+\definecasemap 228 196 228 % greekdelta
+\definecasemap 229 197 229 % greekepsilon
+\definecasemap 230 198 230 % greekzeta
+\definecasemap 213 199 213 % greeketa
+\definecasemap 232 200 232 % greektheta
+\definecasemap 233 201 233 % greekiota
+\definecasemap 234 202 234 % greekkappa
+\definecasemap 235 203 235 % greeklambda
+\definecasemap 236 204 236 % greekmu
+\definecasemap 237 205 237 % greeknu
+\definecasemap 238 206 238 % greekxi
+\definecasemap 239 207 239 % greekomicron
+\definecasemap 240 208 240 % greekpi
+\definecasemap 241 209 241 % greekrho
+\definecasemap 242 211 242 % greekfinalsigma
+\definecasemap 243 211 243 % greekSigma
+\definecasemap 244 212 244 % greekTau
+\definecasemap 245 213 245 % greekUpsilon
+\definecasemap 246 214 246 % greekPhi
+\definecasemap 247 215 247 % greekChi
+\definecasemap 248 216 248 % greekPsi
+\definecasemap 249 217 249 % greekOmega
+
+% Accented Uppercase Greek letters
+
+\definecasemap 182 193 220 % greekAlphatonos
+\definecasemap 184 197 221 % greekEpsilontonos
+\definecasemap 185 199 222 % greekEtatonos
+\definecasemap 186 201 223 % greekIotatonos
+\definecasemap 188 207 252 % greekOmicrontonos
+\definecasemap 190 213 253 % greekUpsilontonos
+\definecasemap 191 217 254 % greekOmegatonos
+\definecasemap 218 218 250 % greekIotadialytika
+\definecasemap 219 219 251 % greekUpsilondialytika
+
+% Accented Lowercase Greek letters
+
+\definecasemap 220 193 220 % greekalphatonos
+\definecasemap 221 197 221 % greekepsilontonos
+\definecasemap 222 199 222 % greeketatonos
+\definecasemap 223 201 223 % greekiotatonos
+\definecasemap 252 207 252 % greekomicrontonos
+\definecasemap 253 213 253 % greekupsilontonos
+\definecasemap 254 217 254 % greekomegatonos
+\definecasemap 250 218 250 % greekiotadialytika
+\definecasemap 251 219 251 % greekupsilondialytika
+\definecasemap 192 218 192 % greekiotadialytikatonos
+\definecasemap 224 219 224 % greekupsilondialytikatonos
+
+\stopmapping
+
+\startencoding[iso-8859-7]
+
+% Uppercase Greek letters
+
+\definecharacter greekAlpha 193
+\definecharacter greekBeta 194
+\definecharacter greekGamma 195
+\definecharacter greekDelta 196
+\definecharacter greekEpsilon 197
+\definecharacter greekZeta 198
+\definecharacter greekEta 199
+\definecharacter greekTheta 200
+\definecharacter greekIota 201
+\definecharacter greekKappa 202
+\definecharacter greekLambda 203
+\definecharacter greekMu 204
+\definecharacter greekNu 205
+\definecharacter greekXi 206
+\definecharacter greekOmicron 207
+\definecharacter greekPi 208
+\definecharacter greekRho 209
+\definecharacter greekSigma 211
+\definecharacter greekTau 212
+\definecharacter greekUpsilon 213
+\definecharacter greekPhi 214
+\definecharacter greekChi 215
+\definecharacter greekPsi 216
+\definecharacter greekOmega 217
+
+% Lowercase Greek letters
+
+\definecharacter greekalpha 225
+\definecharacter greekbeta 226
+\definecharacter greekgamma 227
+\definecharacter greekdelta 228
+\definecharacter greekepsilon 229
+\definecharacter greekzeta 230
+\definecharacter greeketa 231
+\definecharacter greektheta 232
+\definecharacter greekiota 233
+\definecharacter greekkappa 234
+\definecharacter greeklambda 235
+\definecharacter greekmu 236
+\definecharacter greeknu 237
+\definecharacter greekxi 238
+\definecharacter greekomicron 239
+\definecharacter greekpi 240
+\definecharacter greekrho 241
+\definecharacter greekfinalsigma 242
+\definecharacter greeksigma 243
+\definecharacter greektau 244
+\definecharacter greekupsilon 245
+\definecharacter greekphi 246
+\definecharacter greekchi 247
+\definecharacter greekpsi 248
+\definecharacter greekomega 249
+
+% Accented Uppercase Greek letters
+
+\definecharacter greekAlphatonos 182
+\definecharacter greekEpsilontonos 184
+\definecharacter greekEtatonos 185
+\definecharacter greekIotatonos 186
+\definecharacter greekOmicrontonos 188
+\definecharacter greekUpsilontonos 190
+\definecharacter greekOmegatonos 191
+\definecharacter greekIotadialytika 218
+\definecharacter greekUpsilondialytika 219
+
+% Accented Lowercase Greek letters
+
+\definecharacter greekalphatonos 220
+\definecharacter greekepsilontonos 221
+\definecharacter greeketatonos 222
+\definecharacter greekiotatonos 223
+\definecharacter greekomicrontonos 252
+\definecharacter greekupsilontonos 253
+\definecharacter greekomegatonos 254
+\definecharacter greekiotadialytika 250
+\definecharacter greekupsilondialytika 251
+\definecharacter greekiotadialytikatonos 192
+\definecharacter greekupsilondialytikatonos 224
+
+% Miscellaneous Greek symbols
+
+\definecharacter greekleftquot 171
+\definecharacter greekrightquot 187
+\definecharacter greektonos 180
+\definecharacter greekdialytikatonos 181
+\definecharacter greekapostrophos 162
+
+\stopencoding
diff --git a/tex/context/base/enco-heb.mkii b/tex/context/base/enco-heb.mkii
new file mode 100644
index 000000000..443745752
--- /dev/null
+++ b/tex/context/base/enco-heb.mkii
@@ -0,0 +1,16 @@
+%D \module
+%D [ file=enco-heb,
+%D version=2005.01.27,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Hebrew,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 To be done.
+
+\endinput
diff --git a/tex/context/base/enco-ibm.mkii b/tex/context/base/enco-ibm.mkii
new file mode 100644
index 000000000..48695ca52
--- /dev/null
+++ b/tex/context/base/enco-ibm.mkii
@@ -0,0 +1,7 @@
+% temporary module, needed for downward compatibility
+
+%\input regi-ibm.tex
+
+\enableregime[ibm]
+
+\endinput
diff --git a/tex/context/base/enco-il2.mkii b/tex/context/base/enco-il2.mkii
new file mode 100644
index 000000000..9fb87b2fd
--- /dev/null
+++ b/tex/context/base/enco-il2.mkii
@@ -0,0 +1,157 @@
+%D \module
+%D [ file=enco-il2,
+%D version=2000.05.07, % 1998.12.01,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Czech and Slovak ISO Latin 2 Encoding,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% This encoding will go but the regime will remain.
+
+%D This Czech/Slovak encoding is dedicated to Han The Thanh.
+%D The numbers are derived from some files he sent me. This
+%D definition file is (still) sort of beta.
+
+\startmapping[il2]
+
+\resetcaserange 127 to 255 % we map them all to themselves
+
+\definecaseswap 184 152
+\definecaseswap 181 165
+\definecaseswap 185 169
+\definecaseswap 187 171
+\definecaseswap 190 174
+\definecaseswap 224 192
+\definecaseswap 225 193
+\definecaseswap 228 196
+\definecaseswap 229 197
+\definecaseswap 232 200
+\definecaseswap 233 201
+\definecaseswap 236 204
+\definecaseswap 237 205
+\definecaseswap 239 207
+\definecaseswap 242 210
+\definecaseswap 243 211
+\definecaseswap 244 212
+\definecaseswap 246 214
+\definecaseswap 248 216
+\definecaseswap 249 217
+\definecaseswap 250 218
+\definecaseswap 252 220
+\definecaseswap 253 221
+
+\stopmapping
+
+\startencoding[il2][il2]
+
+\definecharacter textgrave 18
+\definecharacter textacute 19
+\definecharacter textcaron 20
+\definecharacter textbreve 21
+\definecharacter textmacron 22
+\definecharacter textring 23
+\definecharacter textcedilla 24
+\definecharacter textcircumflex 94
+\definecharacter textdotaccent 95
+\definecharacter texthungarumlaut 125
+\definecharacter texttilde 126
+\definecharacter textdiaeresis 127
+
+\definecharacter dotlessi 16
+\definecharacter dotlessj 17
+
+\definecharacter aeligature 26
+\definecharacter AEligature 29
+\definecharacter oeligature 27
+\definecharacter OEligature 30
+
+\definecharacter ssharp 25
+
+\definecharacter Racute 192
+\definecharacter Aacute 193
+\definecharacter Lacute 197
+\definecharacter Eacute 201
+\definecharacter Iacute 205
+\definecharacter Oacute 211
+\definecharacter Uacute 218
+\definecharacter Yacute 221
+\definecharacter racute 224
+\definecharacter aacute 225
+\definecharacter lacute 229
+\definecharacter eacute 233
+\definecharacter iacute 237
+\definecharacter oacute 243
+\definecharacter uacute 250
+\definecharacter yacute 253
+
+\definecharacter Lcaron 165
+\definecharacter Scaron 169
+\definecharacter Tcaron 171
+\definecharacter Zcaron 174
+\definecharacter lcaron 181
+\definecharacter scaron 185
+\definecharacter tcaron 187
+\definecharacter zcaron 190
+\definecharacter Ccaron 200
+\definecharacter Ecaron 204
+\definecharacter Dcaron 207
+\definecharacter Ncaron 210
+\definecharacter Rcaron 216
+\definecharacter ccaron 232
+\definecharacter ecaron 236
+\definecharacter dcaron 239
+\definecharacter ncaron 242
+\definecharacter rcaron 248
+
+\definecharacter Ocircumflex 212
+\definecharacter ocircumflex 244
+
+\definecharacter Adiaeresis 196
+\definecharacter Odiaeresis 214
+\definecharacter Udiaeresis 220
+\definecharacter adiaeresis 228
+\definecharacter odiaeresis 246
+\definecharacter udiaeresis 252
+
+\definecharacter Agrave 152
+\definecharacter agrave 184
+
+\definecharacter Ohungarumlaut 213
+\definecharacter Uhungarumlaut 219
+\definecharacter ohungarumlaut 245
+\definecharacter uhungarumlaut 251
+
+\definecharacter Uring 217
+\definecharacter uring 249
+\definecharacter Aring {\ilencodedrA}
+
+\definecharacter ostroke 28
+\definecharacter Ostroke 31
+\definecharacter Lstroke {\ilencodedL}
+\definecharacter lstroke {\ilencodedl}
+
+\def\ilencodedrA
+ {\dontleavehmode\hbox\bgroup
+ \setbox0\hbox{h}%
+ \dimen0=\ht0
+ \advance\dimen0 by -1ex
+ \rlap{\raise.67\dimen0\hbox{\char'27}}A%
+ \egroup}
+
+\def\ilencodedl
+ {\dontleavehmode{\char32l}}
+
+\def\ilencodedL
+ {\dontleavehmode\hbox\bgroup
+ \setbox0\hbox{L}%
+ \hbox to\wd0{\hss\char32L}%
+ \egroup}
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-ini.mkii b/tex/context/base/enco-ini.mkii
new file mode 100644
index 000000000..33825f94d
--- /dev/null
+++ b/tex/context/base/enco-ini.mkii
@@ -0,0 +1,1137 @@
+%D \module
+%D [ file=enco-ini,
+%D version=2007.02.19, % 2000.12.27, % 1998.12.03,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Quite some code will be moved to the mk files once we're ready
+%D for it.
+
+%D This module is a reimplementation of the module that handled
+%D composed characters and non \ASCII\ characters. The changed
+%D are not that fundamental, and mainly concerns moving
+%D definitions of specific glyphs and accents to other files as
+%D well as moving plain handling of accents to this module
+%D instead of overloading plain \TEX\ commands.
+
+%D Patterns are kind of mixed with font encodings and
+%D mappings. Alas.
+
+\ifx\synchronizepatterns\undefined \let\synchronizepatterns\relax \fi
+
+%D While dealing with input (the text source) and output (the
+%D glyphs), encoding comes into view. To summarize a few:
+%D
+%D \startitemize
+%D \item Bytes in the input file are mapped to an internal
+%D representation. An~\type {a} often stays an~\type {a},
+%D but~\type {\"e} can become either one code or become
+%D two codes (ending in overlapping glyphs).
+%D \item Characters can be made active and mapped onto another
+%D character.
+%D \item When changing case, characters are mapped onto
+%D themselves, their case||counterpart or a reasonable
+%D alternative, like~\"e onto~e.
+%D \item Single character representations in a \DVI\ file can
+%D be mapped onto one or more characters, either of not
+%D in more than one font file (virtual fonts).
+%D \item In the final format, fonts collections can be
+%D partially embedded, thereby losing the one||to||one
+%D relation between several instances of one font.
+%D \item For special purposes, individual characters should be
+%D mapped onto a dedicated encoding vector, for instance
+%D \PDF\ document encoding.
+%D \stopitemize
+%D
+%D These and other kind of mappings are to be dealt with, and
+%D the exact way of dealing often depends on the language to be
+%D typeset.
+
+\writestatus{loading}{ConTeXt Encoding Macros / Initialization}
+
+\unprotect
+
+%D First we define a few local or not yet initialized constants.
+
+\def\@map@{@m@ap@} % mapping prefix
+\def\@fha@{@f@ha@} % font prefix
+\def\@cas@{@c@as@} % casecom prefix
+
+\ifx\currentlanguage\undefined \let\currentlanguage\s!en \fi
+
+%D \macros
+%D {setupencoding}
+%D
+%D The following setup command is used to tune encoding
+%D handling.
+
+\def\setupencoding
+ {\dosingleargument\dosetupencoding}
+
+\def\dosetupencoding[#1]%
+ {\getparameters[\??ec][#1]%
+ \edef\defaultencoding
+ {\ifx\@@ecdefault\empty\s!default\else\@@ecdefault\fi}}
+
+%D \macros
+%D {useencoding}
+%D
+%D Encodings things are defined in separate files and are
+%D loaded only once, using:
+%D
+%D \showsetup{useencoding}
+
+\def\douseencoding#1%
+ {\doifundefined{\c!file\f!encodingprefix#1}%
+ {\letvalue{\c!file\f!encodingprefix#1}\empty
+ \makeshortfilename[\truefilename{\f!encodingprefix#1}]%
+ \startreadingfile
+ \readsysfile{\shortfilename.mkii}
+ {\showmessage\m!encodings2{#1}}
+ {\showmessage\m!encodings3{#1}}%
+ \stopreadingfile}}
+
+\def\useencoding[#1]%
+ {\processcommalist[#1]\douseencoding}
+
+%D \macros
+%D {startmapping,enablemapping}
+%D
+%D In order to process patterns, convert from lower to
+%D uppercase and vise versa and some more, we provide a
+%D mechanism to define mappings. The first real application
+%D of this command was:
+%D
+%D \starttyping
+%D \startmapping [something]
+%D \definecasemap 165 181 165
+%D \definecasemap 171 187 171
+%D ...
+%D \defineuppercasecom \i {I}
+%D \defineuppercasecom \l \L
+%D \definelowercasecom \AE \ae
+%D ...
+%D \stopmapping
+%D \stoptyping
+%D
+%D So, character 165 becomes 181 in uppercase and 165 in
+%D lowercase. A mapping is activated with \type {\enablemapping}.
+
+\def\startsavingmappingtoks#1%
+ {\bgroup
+ \edef\charactermapping{@#1@}%
+ \checkmappingtoks
+ \setmappingtoks
+ \the\mappingtoks}
+
+\def\stopsavingmappingtoks
+ {\global\mappingtoks\emptytoks
+ \dostepwiserecurse{0}{255}\plusone
+ {\edef\@@expanded
+ {\the\mappingtoks
+ \ifnum\recurselevel>127
+ \noexpand\settoletterunlessactive{\recurselevel}%
+ \fi
+ \lccode\recurselevel\ifnum\lccode\recurselevel=\zerocount\zerocount\else\space\the\lccode\recurselevel\space\fi
+ \uccode\recurselevel\ifnum\uccode\recurselevel=\zerocount\zerocount\else\space\the\uccode\recurselevel\space\fi
+ \ifnum\sfcode\recurselevel=\plusthousand\else\sfcode\recurselevel=\the\sfcode\recurselevel\space\fi
+ }%
+ \global\mappingtoks\expandafter{\@@expanded}}%
+ \egroup
+ \let\enabledmapping\empty
+ \enablemapping[\currentmapping]}
+
+\def\startmapping[#1]%
+ {\startsavingmappingtoks{#1}}
+
+\def\stopmapping
+ {\stopsavingmappingtoks}
+
+\def\optimizemapping[#1]%
+ {\startsavingmappingtoks{#1}%
+ % nothing, just an automatic cleanup
+ \stopsavingmappingtoks
+ % we need to resync
+ %\let\enabledmapping\relax
+ }%\enablemapping[\currentmapping]}
+
+\def\setmappingtoks
+ {\@EA\let\@EA\mappingtoks\csname\@map@\charactermapping\endcsname
+ \@EA\let\@EA\casecomtoks\csname\@cas@\charactermapping\endcsname}
+
+\def\checkmappingtoks
+ {\ifundefined{\@map@\charactermapping}%
+ \expandafter\newtoks\csname\@map@\charactermapping\endcsname
+ \fi
+ \ifundefined{\@cas@\charactermapping}%
+ \expandafter\newtoks\csname\@cas@\charactermapping\endcsname
+ \fi}
+
+\def\definecasemap #1 #2 #3 % code lower upper
+ {\doifelse{#2}{to}
+ {\presetcaserange{#1}{#3}}
+ {\lccode#1=#2\relax
+ \uccode#1=#3\relax}%
+ \ignorespaces}
+
+%D Saves a few tokens
+
+\def\definecaseswap #1 #2 % lower upper
+ {\lccode#1=#1\relax
+ \uccode#2=#2\relax
+ \lccode#2=#1\relax
+ \uccode#1=#2\relax
+ \ignorespaces}
+
+\def\definecaseself #1 % lower=upper=self
+ {\lccode#1=#1\relax
+ \uccode#1=#1\relax
+ \ignorespaces}
+
+%D Watch the \type {\definecasemap 127 to 255} option!
+%D Dedicated to Taco there is also:
+
+\def\definecasemaps #1 to #2 lc #3 uc #4 % from to lc+ uc+
+ {\dostepwiserecurse{#1}{#2}\plusone
+ {\scratchcounter\recurselevel\advance\scratchcounter#3\lccode\recurselevel=\scratchcounter
+ \scratchcounter\recurselevel\advance\scratchcounter#4\uccode\recurselevel=\scratchcounter}%
+ \ignorespaces}
+
+%D This can be used like:
+%D
+%D \starttyping
+%D \definecasemaps 128 to 156 lc 32 uc 0
+%D \definecasemaps 160 to 188 lc -32 uc 0
+%D \definecasemaps 160 to 188 lc -32 uc 0
+%D \definecasemaps 192 to 255 lc 32 uc 0
+%D \stoptyping
+%D
+%D and saves a lot of typing (copying).
+
+\def\resetcaserange #1 to #2
+ {\dostepwiserecurse{#1}{#2}\plusone
+ {\lccode\recurselevel\zerocount
+ \uccode\recurselevel\zerocount}%
+ \ignorespaces}
+
+\def\presetcaserange#1#2% could be pre-expanded
+ {\dostepwiserecurse{#1}{#2}\plusone
+ {\lccode\recurselevel=\recurselevel
+ \uccode\recurselevel=\recurselevel}%
+ \ignorespaces}
+
+\def\setcasemap #1 #2 #3 %
+ {\settoletterunlessactive{#1}%
+ \lccode #1=#2
+ \uccode #1=#3 }
+
+\def\setcaseswap #1 #2 %
+ {\settoletterunlessactive{#1}%
+ \settoletterunlessactive{#2}%
+ \lccode #1=#1
+ \uccode #2=#2
+ \lccode #2=#1
+ \uccode #1=#2 }
+
+\def\setcaseself #1 %
+ {\settoletterunlessactive{#1}%
+ \lccode #1=#1
+ \uccode #1=#1 }
+
+\def\definespacemap #1 #2 % code sfcode
+ {\sfcode#1=#2%
+ \ignorespaces}
+
+\def\setspacemap #1 #2 %
+ {\settootherunlessactive{#1}%
+ %\lccode #1=\zerocount
+ %\uccode #1=\zerocount
+ \sfcode #1=#2 }
+
+\def\defineuppercasecom#1#2%
+ {\global\casecomtoks\expandafter{\the\casecomtoks\setuppercasecom#1{#2}}%
+ \ignorespaces}
+
+\def\definelowercasecom#1#2%
+ {\global\casecomtoks\expandafter{\the\casecomtoks\setlowercasecom#1{#2}}%
+ \ignorespaces}
+
+\let\setuppercasecom\gobbletwoarguments
+\let\setlowercasecom\gobbletwoarguments
+
+\def\setcasecom#1#2{\def#1{#2}}
+
+\let\enabledmapping\empty % indirect, needed to handle default too
+
+\def\enablemapping[#1]%
+ {\edef\charactermapping{@#1@}%
+ \ifx\enabledmapping\charactermapping \else
+ \doifdefined{\@map@\charactermapping}
+ {%\expandafter\showthe\csname\@map@\charactermapping\endcsname\endcsname
+ \the\csname\@map@\charactermapping\endcsname}%
+ % == \the\executeifdefined{\@map@\charactermapping}\emptytoks
+ \edef\enabledmapping{\charactermapping}%
+ \enablelanguagespecifics[\currentlanguage]% new
+ % \edef\enabledmapping{\charactermapping\currentlanguage}% can be comma list
+ \fi
+ \synchronizepatterns}
+
+% on behalf of font switching:
+
+\def\fastenablemapping#1%
+ {\edef\charactermapping{@#1@}%
+ \ifx\enabledmapping\charactermapping \else
+ \@EA\ifx\csname\@map@\charactermapping\endcsname\relax\else
+ \the\csname\@map@\charactermapping\endcsname
+ \fi
+ % == \the\executeifdefined{\@map@\charactermapping}\emptytoks
+ \let\enabledmapping\charactermapping
+ \enablelanguagespecifics[\currentlanguage]% to faster
+ \fi}
+
+%D This macro wil be implemented in \type {lang-ini.tex}.
+
+\ifx\enablelanguagespecifics\undefined
+ \def\enablelanguagespecifics[#1]{}
+\fi
+
+%D Further on we have to take some precautions when dealing
+%D with special characters like~\type{~}, \type{_}
+%D and~\type{^}, so let us define ourselve some handy macros
+%D first.
+
+\def\protectfontcharacters
+ {\edef\unprotectfontcharacters
+ {\catcode`\noexpand ~=\the\catcode`~\relax
+ \catcode`\noexpand _=\the\catcode`_\relax
+ \catcode`\noexpand ^=\the\catcode`^\relax}%
+ \catcode`~=\@@letter
+ \catcode`_=\@@letter
+ \catcode`^=\@@letter\relax}
+
+%D The completeness of the Computer Modern Roman typefaces
+%D makes clear how incomplete other faces are. To honour 7~bit
+%D \ASCII, these fonts were designed using only the first 127
+%D values of the 256 ones that can be presented by one byte.
+%D Nowadays 8~bit character codings are more common, mainly
+%D because they permit us to predefine some composed
+%D characters, which are needed in most european languages.
+%D
+%D Supporting more than the standard \TEX\ encoding vector
+%D |<|which in itself is far from standard and differs per
+%D font|>| puts a burden on the fonts mechanism. The \CONTEXT\
+%D mechanism is far from complete, but can handle several
+%D schemes at once. The main problem lays in the accented
+%D characters and ligatures like~ff, although handling
+%D ligatures is not the responsibility of this module.
+%D
+%D By default, we use \PLAIN\ \TEX's approach of placing
+%D accents. All other schemes sooner or later give problems
+%D when we distribute \DVI||files are distributed across
+%D machines and platforms. Nevertheless, we have to take care
+%D of different encoding vectors, which tell us where to find
+%D the characters we need. This means that all kind of
+%D character placement macro's like \type{\"} and \type{\ae}
+%D have to be implemented and adapted in a way that suits
+%D these vectors.
+%D
+%D The main difference between different vector is the way
+%D accents are ordered and/or the availability of prebuilt
+%D accented characters. Accented characters can for instance be
+%D called for by sequences like \type{\"e}. Here the \type{\"}
+%D is defined as:
+%D
+%D \starttyping
+%D \def\"#1{{\accent"7F #1}}
+%D \stoptyping
+%D
+%D This macro places the accent \accent"7F {} on top of an~e
+%D gives \"e. Some fonts however can have prebuild accents and
+%D use a more direct approach like
+%D
+%D \starttyping
+%D \def\"#1{\if#1e\char 235\else ... \fi}
+%D \stoptyping
+%D
+%D The latter approach is not used in \CONTEXT, because we
+%D store relevant combinations of accents and characters in
+%D individual macros.
+
+%D We define character substitutes and commands with definition
+%D commands like:
+%D
+%D \starttyping
+%D \startcoding[texnansi]
+%D
+%D \defineaccent " a 228
+%D \defineaccent ^ e 234
+%D \defineaccent ' {\dotlessi} 237
+%D
+%D \definecharacter ae 230
+%D \definecharacter oe 156
+%D
+%D \definecommand b \texnansiencodedb
+%D \definecommand c \texnansiencodedc
+%D
+%D \stopcoding
+%D \stoptyping
+%D
+%D The last argument of \type{\defineaccent} and
+%D \type{\definecharacter} tells \TEX\ the position of the
+%D accented character in the encoding vector. In order to
+%D complish this, we tag each implementation with the character
+%D coding identifier. We therefore need two auxiliary variables
+%D \type{\characterencoding} and \type{\nocharacterencoding}. These
+%D contain the current and default encoding vectors and both
+%D default to the \PLAIN\ one.
+
+\edef\characterencoding {@\s!default @}
+\edef\nocharacterencoding {@\s!default @}
+\edef\charactermapping {@\s!default @}
+
+% todo, else \d j == \dj, print file and check
+
+\def\accentprefix {}%{*}
+\def\commandprefix {}%{=}
+\def\characterprefix{}%{-}
+
+%D \macros
+%D {startcoding, reducetocoding}
+%D
+%D Before we can redefine accents and special characters, we
+%D have to tell \CONTEXT\ what encoding is in force. The next
+%D command is responsible for doing this and also takes care of
+%D the definition of the recoding commands. We use the \type
+%D {\start}||\type {\stop}||commands for definitions and the
+%D \type {\reduceto}||command for local switching to
+%D simplified commands.
+
+% etex : \ifcsname
+
+\def\justhandleaccent#1#2% \empty makes #2={} save % no \unexpanded
+ {\ifundefined{\accentprefix\characterencoding#1\string#2\empty}%
+ #2%
+ \else
+ \csname\accentprefix\characterencoding#1\string#2\empty\endcsname
+ \fi}
+
+\def\justhandlecommand#1% % no \unexpanded, otherwise pdfdoc will fail
+ {\ifundefined{\commandprefix\characterencoding#1}% as well as hyph patterns
+ #1%
+ \else
+ \csname\commandprefix\characterencoding#1\endcsname
+ \fi}
+
+\def\enableencoding
+ {\dodoubleempty\doenableencoding}
+
+\def\doenableencoding[#1][#2]% main fallback
+ {\iffirstargument\edef\characterencoding{@#1@}\fi
+ \edef\nocharacterencoding{@\ifsecondargument#2\else\s!default\fi @}%
+ \synchronizepatterns}
+
+\edef\xnocharacterencoding{@\s!default @}
+
+\def\fastenableencoding#1%
+ {\edef\characterencoding{@#1@}%
+ \let\nocharacterencoding\xnocharacterencoding}
+
+\def\startencoding
+ {\dodoubleempty\dostartencoding}
+
+\def\dostartencoding[#1][#2]% encoding regime
+ {%\showmessage\m!encodings1{#1}%
+ \pushmacro\characterencoding
+ \pushmacro\currentregime
+ \pushmacro\dohandleaccent % still needed?
+ \pushmacro\dohandlecommand % still needed?
+ \pushmacro\doautosetregime
+ \let\dohandleaccent\donthandleaccent % still needed?
+ \let\dohandlecommand\donthandlecommand % still needed?
+ %let\definesortkey\savesortkey
+ \edef\characterencoding{@#1@}%
+ \doifelsenothing{#2}%
+ {\let\doautosetregime\gobbletwoarguments}
+ {\def\currentregime{#2}}}
+
+\def\stopencoding
+ {\popmacro\doautosetregime
+ \popmacro\dohandlecommand % still needed?
+ \popmacro\dohandleaccent % still needed?
+ \popmacro\currentregime
+ \popmacro\characterencoding}
+
+% probably obsolete (hm, not yet)
+
+\def\reducetocoding[#1]% use grouped!
+ {\doifsomething{#1}
+ {\let\dohandleaccent \justhandleaccent
+ \let\dohandlecommand\justhandlecommand
+ \enableencoding[#1]%
+ \enablelanguagespecifics[\currentlanguage]}}
+
+\let\startcoding \startencoding
+\def\stopcoding {\stopencoding}
+\let\enablecoding \enableencoding
+
+%D The use of these macros are not limited to font
+%D definition files, but may also be used when loading
+%D patterns.
+
+%D \macros
+%D {definesortkey,flushsortkeys,flushsortkey}
+%D
+%D Yet another definition concerns sorting of indexes and
+%D lists.
+%D
+%D \starttyping
+%D \definesortkey {\'e} {e} {a} {\'e}
+%D \stoptyping
+%D
+%D The first argument denotes the string to be treated. The
+%D second argument is the raw replacement, while the third
+%D argument determines the sort order given the replacement.
+%D The last argument is used as entry in the index (a, b, etc).
+%D
+%D The keys can be flushed using \type {\flushsortkeys}
+%D which in turn results in a sequence of calls to \type
+%D {\flushsortkey}, a macro taking 4~arguments.
+%D
+%D This mechanism is currently being tested and subjected to
+%D changes! Obsolete:
+
+\let\definesortkey\gobblefourarguments
+\let\savesortkey \gobblefourarguments
+\let\flushsortkeys\relax
+\let\flushsortkey \relax
+
+%D \macros
+%D {defineaccent, definecharacter, definecommand}
+%D
+%D The actual definition of accents, special characters and
+%D commands is done with the next three commands.
+
+\def\defineaccent
+ {\protectfontcharacters
+ \dodefineaccent}
+
+\def\dodefineaccent#1 #2 %
+ {\unprotectfontcharacters
+ \dododefineaccent#1 #2 }
+
+\def\dododefineaccent#1 #2 #3 %
+ {\setvalue{#1}{\dohandleaccent{#1}}%
+ \doifnumberelse{\string#3}
+ {\setvalue{\accentprefix\characterencoding#1\string#2}{\char#3 }} % space added
+ {\setvalue{\accentprefix\characterencoding#1\string#2}{#3}}}
+
+\def\dohandleaccent#1#2%
+ {\ifcsname\accentprefix\characterencoding#1\string#2\empty\endcsname
+ \csname\accentprefix\characterencoding#1\string#2\empty\endcsname
+ \else\ifcsname\accentprefix\nocharacterencoding#1\string#2\empty\endcsname
+ \csname\accentprefix\nocharacterencoding#1\string#2\empty\endcsname
+ \else\ifcsname\accentprefix\characterencoding#1\endcsname
+ \csname\accentprefix\characterencoding#1\endcsname{#2}%
+ \else%\ifcsname\accentprefix\nocharacterencoding#1\endcsname
+ \csname\accentprefix\nocharacterencoding#1\endcsname{#2}%
+% \else
+% \donormaltextaccent{#1}{#2}%
+ \fi\fi\fi}%\fi}
+
+\def\patternchar#1 {\rawcharacter{#1}} % space is part of character definition !
+
+% \ifx \enablepatterntokens\undefined
+% \def\handlepatterntoken#1]{\csname#1\endcsname}
+% \fi
+
+% we need to postpone catcode changes, e.g. hr patterns
+% have \catcode" -> which fails when " is letter
+
+\def\pathypsettings
+ {\ifx \enablepatterntokens\undefined
+ \defineactivecharacter [ {\handlepatterntoken}%
+ \else
+ \enablepatterntokens
+ \fi
+ \let\dochar\thechr
+ \lccode16=16 % brrr, extra quote in ec (turkish)
+ \lccode17=17 % brrr, extra quote in ec (turkish)
+ \lccode`\-=`\-
+ \lccode`\'=`\'
+ \lccode`\"=`\"
+ \relax}
+
+\def\patterns {\pathypsettings\normalpatterns }
+\def\hyphenation{\pathypsettings\normalhyphenation}
+
+%D Because we don't want to use the second command grouped, we
+%D (re)define it as follows:
+
+\def\hyphenation
+ {\begingroup\def\hyphenation{\normalhyphenation{\the\scratchtoks}\endgroup}%
+ \pathypsettings\afterassignment\hyphenation\scratchtoks=}
+
+%D This is not needed for patterns because they are loaded grouped
+%D anyway and it saves us an assignment. Can go ... no longer
+%D shared patterns.
+
+\def\startpatternloading#1#2#3% % we should use \everypatternloading
+ {\startreadingfile
+ \bgroup
+ % let's get rid of interfering stuff
+ \let\everyjob\scratchtoks
+ \let\message \gobbleoneargument
+ % we want direct characters
+ \let\char\patternchar
+ \doifelsenothing{#2}{\enableencoding[ec]}{\enableencoding[#2]}%
+ \doifelsenothing{#3}{\enablemapping [ec]}{\enablemapping [#3]}%
+ \expanded{\doifinstring{\f!languageprefix}{#1}}
+ {\ifx \enablepatternxml\undefined \else
+ \enablepatternxml
+ \fi}%
+ \let\dohandleaccent\normaldohandleaccent}
+
+\def\stoppatternloading
+ {\egroup
+ \stopreadingfile}
+
+ \def\thechr#1{\char#1 } % just in case \relax interferes
+\unexpanded\def\numchr#1{\char#1\relax}
+\unexpanded\def\strchr#1{\csname#1\endcsname}
+
+\let\dochar\numchr
+
+\def\startdirectcharacters {\pushmacro\dochar \let\dochar\thechr}
+\def\stopdirectcharacters {\popmacro \dochar}
+
+\def\definecharacter#1 #2 %
+ {\ifundefined{#1}\setvalue{#1}{\dohandlecharacter{#1}}\fi
+ \doifnumberelse{\string#2}
+ {\setvalue{\characterprefix\characterencoding\string#1}{\dochar{#2}}%
+ \doautosetregime{#1}{#2}}
+ {\setvalue{\characterprefix\characterencoding\string#1}{#2}}}
+
+\def\dohandlecharacter#1%
+ {\csname\characterprefix\ifcsname\characterprefix\characterencoding#1\endcsname
+ \characterencoding\else\nocharacterencoding\fi#1\endcsname}
+
+% \def\fallbackpatternchar{x} % makes no sense, duplicate patterns
+
+\def\defaultcharacter#1%
+ {\csname\characterprefix\nocharacterencoding\strippedcsname#1\endcsname}
+
+%D Instead of numbers, a command may be entered.
+
+\def\definecommand#1 #2 %
+ {\setvalue{\string#1}{\dohandlecommand{#1}}%
+ %\redefinecommand #1 % just to be sure
+ \setvalue{\commandprefix\characterencoding\string#1}{#2}}
+
+%D Here we see that redefining accents is characters is more
+%D or less the same as redefining commands. We also could have
+%D said:
+%D
+%D \starttyping
+%D \def\defineaccent#1 #2 {\definecommand#1\string#2 \char}
+%D \def\definecharacter#1 {\definecommand#1 \char}
+%D \stoptyping
+
+%D \macros
+%D {defineaccentcommand}
+%D
+%D When needed, one can overload the default positions of the
+%D accents. The \PLAIN\ \TEX\ defaults are:
+%D
+%D \starttyping
+%D \defineaccentcommand ` 18
+%D \defineaccentcommand ' 19
+%D \defineaccentcommand v 20
+%D \defineaccentcommand u 21
+%D \defineaccentcommand = 22
+%D \defineaccentcommand ^ 94
+%D \defineaccentcommand . 95
+%D \defineaccentcommand H 125 % "7D
+%D \defineaccentcommand ~ 126 % "7E
+%D \defineaccentcommand " 127 % "7F
+%D \stoptyping
+
+\def\defineaccentcommand
+ {\protectfontcharacters
+ \dodefineaccentcommand}
+
+\def\dodefineaccentcommand#1 #2 % \string toegevoegd
+ {\doifnumberelse{\string#2}
+ {\setvalue{\accentprefix\characterencoding\string#1}##1{{\accent#2 ##1}}}
+ {\setvalue{\accentprefix\characterencoding\string#1}##1{{#2##1}}}%
+ \unprotectfontcharacters}
+
+%D We don't have to define them for the default \PLAIN\ case.
+%D Commands may be used instead of character codes.
+
+%D \macros
+%D {redefinecommand}
+%D
+%D Redefinition of encoding dependant commands like \type{\b}
+%D and \type{\c} can be triggered by:
+%D
+%D \starttyping
+%D \redefinecommand b % something math
+%D \redefinecommand c % something math
+%D \stoptyping
+%D
+%D Handling of characters is easier than handling accents
+%D because here we don't have to take care of arguments. We
+%D just call for the right glyph in the right place.
+%D
+%D The \type{\next} construction permits handling of commands
+%D that take arguments. This means that we can use this
+%D command to redefine accent handling commands too
+%D (although today the next is not needed any longer in test
+%D macros).
+
+\def\redefinecommand#1 %
+ {% no \unexpanded, else pdfdoc fails
+ \setvalue{\string#1}{\dohandlecommand{#1}}}%
+
+\def\dohandlecommand#1%
+ {\csname\commandprefix
+ \ifcsname\commandprefix\characterencoding#1\endcsname
+ \characterencoding
+ \else
+ \nocharacterencoding
+ \fi
+ #1\endcsname}
+
+%D \macros
+%D {currentencoding, currentmapping}
+%D
+%D When we show 'm, we don't want to see the protection
+%D measures.
+
+\def\currentencoding{\@EA\dopureencodingname\characterencoding}
+\def\currentmapping {\@EA\dopureencodingname\charactermapping }
+
+\def\dopureencodingname @#1@{#1}
+
+\def\pureencodingname#1{\@EA\dopureencodingname#1}
+
+%D \macros
+%D {showaccents, showcharacters,
+%D showcharacterbounds, showhyphenations}
+%D
+%D Encoding is a tricky business. Therefore we provide a
+%D a few macros that show most of the characters involved. The
+%D next two tables show the result of \type {\showaccents}.
+%D
+%D \placetable
+%D {The special glyphs in default encoding.}
+%D {\showaccents}
+%D
+%D \placetable
+%D {The special glyphs in texnansi encoding.}
+%D {\switchtobodyfont[lbr]\showaccents}
+%D
+%D The command
+%D
+%D \starttyping
+%D \showhyphenations{doordefini\"eren}
+%D \stoptyping
+%D
+%D can be used to check the correct loading of hyphenation
+%D patterns.
+
+\fetchruntimecommand \showaccents {\f!encodingprefix\s!run.mkii}
+\fetchruntimecommand \showcharacters {\f!encodingprefix\s!run.mkii}
+\fetchruntimecommand \showcharacterbounds {\f!encodingprefix\s!run.mkii}
+\fetchruntimecommand \showhyphenations {\f!encodingprefix\s!run.mkii}
+\fetchruntimecommand \showmapping {\f!encodingprefix\s!run.mkii}
+
+%D \macros
+%D {everyuppercase, EveryUppercase,
+%D everyuppercase, EveryUppercase}
+%D
+%D When we want to uppercase strings of characters, we have to
+%D take care of those characters that have a special meaning or
+%D are only accessible by means of macros. The next hack was
+%D introduced when Tobias Burnus started translating head and
+%D label texts into spanish and italian. The first application
+%D of this token register therefore can be found in the module
+%D that deals with these texts.
+
+\newevery \everyuppercase \EveryUppercase
+\newevery \everylowercase \EveryLowercase
+
+%D This magic trick maps takes care of mapping from lower to
+%D upper case and reverse.
+
+\def\reloadmapping{\the\executeifdefined{\@cas@\charactermapping}\emptytoks}
+
+\appendtoks\let\setuppercasecom\setcasecom\to\everyuppercase
+\appendtoks\let\setlowercasecom\setcasecom\to\everylowercase
+
+\appendtoks\reloadmapping\to\everyuppercase % slow, will be sped up
+\appendtoks\reloadmapping\to\everylowercase % slow, will be sped up
+
+\newtoks\everyULmap
+
+\appendtoks\let\remapcase\remapuppercase\the\everyULmap\to\everyuppercase
+\appendtoks\let\remapcase\remaplowercase\the\everyULmap\to\everylowercase
+
+\let\remapcase\gobbletwoarguments
+
+\def\remapuppercase#1#2{\let#2#1} % more efficient:
+\def\remaplowercase#1#2{\let#1#2} \let\remaplowercase\let
+
+\def\defineLCcharacter #1 #2 %
+ {\appendtoks\let\to\everylowercase
+ \@EA\appendtoks\csname#1\endcsname\to\everylowercase
+ \@EA\appendtoks\csname#2\endcsname\to\everylowercase}
+
+\def\defineUCcharacter #1 #2 %
+ {\appendtoks\let\to\everyuppercase
+ \@EA\appendtoks\csname#1\endcsname\to\everyuppercase
+ \@EA\appendtoks\csname#2\endcsname\to\everyuppercase}
+
+\def\defineULcharacter #1 #2 %
+ {\appendtoks\remapcase\to\everyULmap
+ \@EA\appendtoks\csname#1\endcsname\to\everyULmap
+ \@EA\appendtoks\csname#2\endcsname\to\everyULmap}
+
+% slightly faster with \smallcapped's but far more hash and stringspace
+%
+% \newif\ifuppercase \appendtoks\uppercasetrue\to\everyuppercase
+% \newif\iflowercase \appendtoks\lowercasetrue\to\everylowercase
+%
+% \def\defineULcharacter #1 #2 %
+% {\def\!!stringa{@#1}\@EA\letvalue\@EA\!!stringa\csname#1\endcsname
+% \def\!!stringa{@#2}\@EA\letvalue\@EA\!!stringa\csname#2\endcsname
+% \setvalue{#1}{\getvalue{@\ifuppercase#2\else#1\fi}}%
+% \setvalue{#2}{\getvalue{@\iflowercase#1\else#2\fi}}}
+
+% 2 = tricky, since expanding \definedfont[lowcasename] ... goes wrong
+
+\chardef\uppercasemode\plusthree % 0=ignore 1=normal 2=expand 3=auto
+\chardef\casecommode \plusone % 0=noexpand 1=expand
+
+\def\setcasecom #1#2{\def#1{\ifcase\casecommode\noexpand#1\else#2\fi}}
+
+% \def\OEPS{whatever}
+%
+% \startmapping[ec]
+% \defineuppercasecom \oeps {\getvalue{OEPS}}
+% \stopmapping
+%
+% \WORD{xx \oeps}
+
+\def\douppercase#1%
+ {\bgroup
+ \let\douppercase\firstofoneargument
+ \the\everyuppercase % currently also checks uppercasemode
+ \let\dochar\rawcharacter
+ \ifcase\uppercasemode
+ #1%
+ \or % No expansion here, otherwise \getvalue problems! Default!!!
+ %\edef\next{#1}% keep this to prevent roll back
+ %\uppercase\expandafter{\next}% keep this to prevent roll back
+ \uppercase{#1}%
+ \or
+ \chardef\casecommode\zerocount
+ \let\docasecom\firstoftwoarguments
+ \edef\ascii{#1}%
+ \edef\ascii{\expandafter\uppercase\expandafter{\ascii}}% needed when in regime
+ \chardef\casecommode\plusone
+ \ascii
+ \else
+ % mode three may trigger setting 2 elsewhere (e.g. regime test)
+ \uppercase{#1}%
+ \fi
+ \egroup}
+
+\prependtoksonce
+ \doifnot\currentregime\s!default
+ {\ifnum\uppercasemode=\plusthree \chardef\uppercasemode\plustwo \fi}%
+\to \everyuppercase
+
+%D \macros
+%D {everysanitize, EverySanitize}
+%D
+%D Whenever we are sanitizing strings, like we sometimes do
+%D when we deal with specials, the next token register can be
+%D called.
+
+\newevery \everysanitize \EverySanitize
+
+%D \macros
+%D {defineuclass,defineudigit,udigit}
+%D
+%D The next few macros are experimental and needed for unicoded
+%D chinese characters.
+
+\def\defineuclass #1 #2 #3 %
+ {\setvalue{uc\the\numexpr#2*256+#3\relax}{#1}}
+
+\def\defineudigit #1 #2 #3 {\setvalue{\characterencoding uc#1}{\uchar{#2}{#3}}}
+
+%D It may look strange, but for the moment, we want the encoding
+%D to be part of the digit specification. This may change!
+
+\unexpanded\def\udigit#1#2{\getvalue{@#1@uc\number#2}}
+
+%D \macros
+%D {uchar, octuchar, hexuchar}
+
+\ifx\uchar\undefined \def\uchar#1#2{(\number#1,\number#2)} \fi
+
+\def\octuchar#1#2{\uchar{`#1}{`#2}}
+\def\hexuchar#1#2{\uchar{"#1}{"#2}}
+
+%D Basics and fallbacks.
+
+\newif\ifignoreaccent
+
+\let\textaccent \accent
+\let\normaltextaccent\textaccent
+
+% ** we will explicitly embrace the two arguments, since in definitions
+% this may not be the case, and we don't want faulty expansions like
+% "\dobuildtextaccent \char 18 a" but "\dobuildtextaccent {\char 18}{a}"
+% instead
+
+\def\buildmathaccent#1%
+ {\mathaccent#1 }
+
+\def\buildtextaccent#1#2% **
+ {\ifignoreaccent
+ \expandafter\nobuildtextaccent
+ \else
+ \expandafter\dobuildtextaccent
+ \fi{#1}{#2}}
+
+\unexpanded\def\nobuildtextaccent#1#2%
+ {#2}
+
+\unexpanded\def\dobuildtextaccent#1#2%
+ {{\let\char\normalaccent#1\let\char\normalchar#2}}
+
+% some fake ones, name will change into build
+
+\unexpanded\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode % why this align mess
+ \vtop
+ {\forgetall
+ \baselineskip\zeropoint
+ \lineskip#1%
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \lineskiplimit\zeropoint
+ \setbox0\hbox{#4}%
+ \halign
+ {##\crcr\hbox{#5}\crcr
+ \hidewidth
+ \hskip#2\wd0
+ \hskip-#3\slantperpoint % in plain 1ex * dimenless value
+ \vbox to .2ex{\box0\vss}\hidewidth
+ \crcr}}}
+
+\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}}
+\def\buildtextbottomdot{\bottomaccent{.25ex}{0}{5}{\textbottomdot}}
+\def\buildtextcedilla {\bottomaccent{0ex}{0}{5}{\textcedilla}}
+\def\buildtextogonek {\bottomaccent{-.1ex}{.5}{0}{\textogonek}}
+
+%D A collectors item:
+
+\def\buildtextbottomcomma{\bottomaccent{.15ex}{0}{5}{\tx,}}
+
+%D Rarely needed but there:
+
+\unexpanded\def\topaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode
+ \bgroup
+ \setbox0\hbox{#4}%
+ \setbox2\hbox{#5}%
+ \hbox to \wd2 \bgroup
+ \hss\copy2\hss
+ \hskip-\wd2
+ \hss\hskip#2\wd0\hskip-#3\slantperpoint\raise#1\hbox{#4}\hss
+ \egroup
+ \egroup}
+
+\def\buildtextgrave{\topaccent{0pt}{0}{15}{\textgrave}} % e.g.
+
+% \definecharacter schwa {\hbox{\rotate[rotation=180,location=high]{\hbox{e}}}}
+% \definecharacter schwagrave {\buildtextgrave\schwa}
+
+% math stuff, will change
+
+\def\definemathaccent#1 #2%
+ {\setvalue{\string#1}{#2}%
+ \setvalue{normalmathaccent\string#1}{#2}}
+
+\def\donormalmathaccent#1%
+ {\getvalue{normalmathaccent\string#1}}
+
+%D Some precautions:
+
+\ifx\usepdffontresource\undefined
+ \def\usepdffontresource #1 {} % this will be defined elsewhere
+\fi
+
+\def\donthandleaccent #1{\expandafter\string\csname#1\endcsname\space}
+\def\donthandlecommand #1{\expandafter\string\csname#1\endcsname\space}
+\def\donthandlecharacter #1{\expandafter\string\csname#1\endcsname\space}
+
+\def\stringifyhandleaccent #1{\strchr{#1}}
+\def\stringifyhandlecommand #1{\strchr{#1}}
+\def\stringifyhandlecharacter#1{\strchr{#1}}
+
+\def\keephandleaccent #1{\expandafter\noexpand\csname#1\endcsname}
+\def\keephandlecommand #1{\expandafter\noexpand\csname#1\endcsname}
+\def\keephandlecharacter #1{\expandafter\noexpand\csname#1\endcsname}
+
+\def\handleaccent #1{\csname#1\endcsname}
+\def\handlecommand #1{\csname#1\endcsname}
+\def\handlecharacter #1{\csname#1\endcsname}
+
+\def\dontexpandencoding
+ {\let\dohandleaccent \donthandleaccent
+ \let\dohandlecommand \donthandlecommand
+ \let\dohandlecharacter\donthandlecharacter}
+
+\def\keepencodedtokens
+ {\let\dohandleaccent \keephandleaccent
+ \let\dohandlecommand \keephandlecommand
+ \let\dohandlecharacter\keephandlecharacter}
+
+\def\literateencodedtokens
+ {% \let\dohandleaccent \keephandleaccent
+ % \let\dohandlecommand \keephandlecommand
+ \let\dohandlecharacter\keephandlecharacter}
+
+\def\stringifyencodedtokens
+ {% \let\dohandleaccent \stringifyhandleaccent
+ % \let\dohandlecommand \stringifyhandlecommand
+ \let\dohandlecharacter\stringifyhandlecharacter}
+
+\unexpanded\def\uhandleaccent #1{\csname#1\endcsname}
+\unexpanded\def\uhandlecommand #1{\csname#1\endcsname}
+\unexpanded\def\uhandlecharacter#1{\csname#1\endcsname}
+
+\def\dontexpandencodedtokens
+ {\def\dohandleaccent {\uhandleaccent}%
+ \def\dohandlecommand {\uhandlecommand}%
+ \def\dohandlecharacter{\uhandlecharacter}}
+
+% no longer: \def\convertencodedtokens{\dontexpandencoding} but:
+
+\def\convertencodedtokens{\stringifyencodedtokens}
+
+% test case:
+%
+% \enableregime[cp1250]
+% \mainlanguage[cz]
+%
+% \starttext
+%
+% \title{Ϭuޯu餭 kon졺p
+% \placelist[chapter][criterium=all]
+%
+% \startbuffer
+%
+% Ϭuޯu餭 kon졺pitle>
+%
+% \stopbuffer
+%
+% \defineXMLenvironment
+% [chapter]
+% {\defineXMLsave[title]}
+% {\expanded{\chapter{\XMLflush{title}}}}
+% \processXMLbuffer
+%
+% \setuphead[chapter][expansion=yes]
+% \defineXMLenvironment
+% [chapter]
+% {\defineXMLsave[title]}
+% {\chapter{\XMLflush{title}}}
+% \processXMLbuffer
+%
+% \stoptext
+
+%D Still valid? To be checked:
+
+\def\doignoreaccent #1#2{\string#1\string#2}%
+\def\doignorecommand #1{\string#1}
+\def\doignorecharacter#1{\string#1}
+
+\def\ignoreencoding
+ {\let\dohandleaccent \doignoreaccent
+ \let\dohandlecommand \doignorecommand
+ \let\dohandlecharacter\doignorecharacter}
+
+\appendtoks
+ \ignoreencoding
+\to \everycleanupfeatures
+
+\appendtoks
+ \keepencodedtokens
+\to \everysafeexpanded
+
+%D Now we will not redefine any more, so:
+
+\let\normaldohandleaccent \dohandleaccent
+\let\normaldohandlecharacter\dohandlecharacter
+
+\definecommand ` {\buildtextaccent\textgrave}
+\definecommand ' {\buildtextaccent\textacute}
+\definecommand r {\buildtextaccent\textring}
+\definecommand v {\buildtextaccent\textcaron}
+\definecommand u {\buildtextaccent\textbreve}
+\definecommand = {\buildtextaccent\textmacron}
+\definecommand ^ {\buildtextaccent\textcircumflex}
+\definecommand . {\buildtextaccent\textdotaccent}
+\definecommand H {\buildtextaccent\texthungarumlaut}
+\definecommand ~ {\buildtextaccent\texttilde}
+\definecommand " {\buildtextaccent\textdiaeresis}
+
+\definecommand c {\buildtextcedilla}
+\definecommand b {\buildtextmacron}
+\definecommand d {\buildtextbottomdot}
+\definecommand k {\buildtextogonek}
+
+\definemathaccent acute {\buildmathaccent\mathacute}
+\definemathaccent grave {\buildmathaccent\mathgrave}
+\definemathaccent ddot {\buildmathaccent\mathddot}
+\definemathaccent tilde {\buildmathaccent\mathtilde}
+\definemathaccent bar {\buildmathaccent\mathbar}
+\definemathaccent breve {\buildmathaccent\mathbreve}
+\definemathaccent check {\buildmathaccent\mathcheck}
+\definemathaccent hat {\buildmathaccent\mathhat}
+\definemathaccent vec {\buildmathaccent\mathvec}
+\definemathaccent dot {\buildmathaccent\mathdot}
+\definemathaccent widetilde {\buildmathaccent\mathwidetilde}
+\definemathaccent widehat {\buildmathaccent\mathwidehat}
+
+\useencoding[def] % defaults (partly simplified)
+\useencoding[acc] % accent commands
+\useencoding[raw] % simplified (incomplete)
+\useencoding[com] % a few commands
+\useencoding[cas] % case mapping, not needed in mkiv
+\useencoding[mis] % a few commands
+
+%D We preload several encodings:
+
+\ifnum\texengine=\xetexengine
+ \setupencoding[\s!default=\s!default]
+\else
+ \useencoding[ans,il2,ec,tbo,pdf,pol,qx,t5,l7x,cyr,agr] % pol and il2 will go away, not needed in mkiv, uc removed
+ \useencoding[032,033,037] % fallbacks for some unicode chars
+ \setupencoding[\s!default=ec] % was: [\s!default=\s!default]
+\fi
+
+\protect \endinput
diff --git a/tex/context/base/enco-ini.mkiv b/tex/context/base/enco-ini.mkiv
new file mode 100644
index 000000000..da1892faf
--- /dev/null
+++ b/tex/context/base/enco-ini.mkiv
@@ -0,0 +1,536 @@
+%D \module
+%D [ file=enco-ini,
+%D version=2007.02.19, % 2000.12.27, % 1998.12.03,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is stripped down version of th eoriginal enco-ini.tex
+%D file. For more details you might want to study the \MKII\ file
+%D but since \LUATEX\ is unicode inside we need less code.
+
+% When dealing with characters we have four cases to take into account
+% when moving from mkii to mkiv:
+
+% 1. => ref to slot 200 in current font
+% 2. \char 200 => ref to slot 200 in current font
+% 3. => can (e.g.) map to another slot in current font
+% 4. \namedglyph => can map to some slot in some font
+
+% Using case 2 for special characters is doomed to fail because we are not going
+% to intercept these on the fly as happens automatically with traditional font
+% encoding handling. We could do that in a node pass but it's not worth the effort
+% because we seldom use this case in a document source.
+
+% We can consider using utf as internal format for mkii. The main reason for not
+% doing this before was that it was slow. On the other hand, it would make dealing
+% with utility files easier. However, we've now kind of frozen mkii.
+
+\writestatus{loading}{ConTeXt Encoding Macros / Initialization}
+
+\unprotect
+
+%D Quite some commands are now obsolete. We keep only a few commands
+%D around, just in case they are used in styles (and in for instance
+%D symb and xtag files).
+
+\unexpanded\def\startencoding [#1]{} % used in symb
+\let\stopencoding \relax
+\unexpanded\def\setupencoding [#1]{}
+\def\enablemapping [#1]{}
+\def\enableencoding[#1]{}
+
+\def\currentencoding{utf}
+\def\currentmapping {utf}
+\let\defaultencoding\s!default
+
+% todo:
+
+% \def\showaccents {\f!encodingprefix\s!run}
+% \def\showcharacters {\f!encodingprefix\s!run}
+% \def\showcharacterbounds {\f!encodingprefix\s!run}
+% \def\showhyphenations {\f!encodingprefix\s!run}
+% \def\showmapping {\f!encodingprefix\s!run}
+
+%D \macros
+%D {defineaccent, definecharacter, definecommand}
+
+\unexpanded\def\defineaccent#1 #2 #3 %
+ {\setevalue{\string#1}{\noexpand\dohandleaccent{\string#1}}%
+ \setvalue{\??ac\string#1\string#2}{#3}}
+
+\def\dohandleaccent#1#2%
+ {\csname\??ac\string#1\string#2\empty\endcsname}
+
+\unexpanded\def\definecharacter#1 #2 %
+ {\doifnumberelse{\string#2}
+ {\setevalue{\string#1}{\utfchar{#2}}} % or {\expandafter\chardef\csname#1\endcsname#2\relax}
+ {\setuvalue {\string#1}{#2}}}
+
+\unexpanded\def\definecommand#1 #2 %
+ {\setuvalue{\string#1}{#2}}
+
+%D \macros
+%D {everyuppercase, EveryUppercase,
+%D everyuppercase, EveryUppercase,
+%D everysanitize, EverySanitize}
+
+\newevery \everyuppercase \EveryUppercase
+\newevery \everylowercase \EveryLowercase
+\newevery \everysanitize \EverySanitize
+
+%D Some saved meanings (not really needed):
+
+\let\textaccent \accent
+\let\normaltextaccent\accent
+
+%D Accent handling (try to avoid this):
+
+\newbox\accenttestbox
+
+\def\buildmathaccent#1%
+ {\mathaccent#1 }
+
+\unexpanded\def\buildtextaccent#1#2%
+ {\begingroup
+ \global\setbox\accenttestbox\hbox{#1}%
+ \scratchcounter\ctxlua{characters.charcode(\number\accenttestbox)}%
+ \ifcase\scratchcounter\else\accent\scratchcounter\fi
+ \relax#2%
+ \endgroup}
+
+\unexpanded\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode % why this align mess
+ \vtop
+ {\forgetall
+ \baselineskip\zeropoint
+ \lineskip#1%
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \lineskiplimit\zeropoint
+ \setbox0\hbox{#4}%
+ \halign
+ {##\crcr\hbox{#5}\crcr
+ \hidewidth
+ \hskip#2\wd0
+ \hskip-#3\slantperpoint % in plain 1ex * dimenless value
+ \vbox to .2ex{\box0\vss}\hidewidth
+ \crcr}}}
+
+\unexpanded\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}}
+\unexpanded\def\buildtextbottomdot {\bottomaccent{.25ex}{0}{5}{\textbottomdot}}
+\unexpanded\def\buildtextcedilla {\bottomaccent{0ex}{0}{5}{\textcedilla}}
+\unexpanded\def\buildtextogonek {\bottomaccent{-.1ex}{.5}{0}{\textogonek}}
+\unexpanded\def\buildtextbottomcomma{\bottomaccent{.15ex}{0}{5}{\tx,}}
+
+\let\d\buildtextbottomdot
+
+\unexpanded\def\topaccent#1#2#3#4#5% down right slantcorrection accent char
+ {\dontleavehmode
+ \bgroup
+ \setbox0\hbox{#4}%
+ \setbox2\hbox{#5}%
+ \hbox to \wd2 \bgroup
+ \hss\copy2\hss
+ \hskip-\wd2
+ \hss\hskip#2\wd0\hskip-#3\slantperpoint\raise#1\hbox{#4}\hss
+ \egroup
+ \egroup}
+
+\def\buildtextgrave{\topaccent{0pt}{0}{15}{\textgrave}} % e.g.
+
+\unexpanded\def\definemathaccent#1 #2%
+ {\setvalue{#1}{\mathaccent#2 }}
+
+%D Math (will move):
+
+\definemathaccent acute \mathacute
+\definemathaccent grave \mathgrave
+\definemathaccent ddot \mathddot
+\definemathaccent tilde \mathtilde
+\definemathaccent bar \mathbar
+\definemathaccent breve \mathbreve
+\definemathaccent check \mathcheck
+\definemathaccent hat \mathhat
+\definemathaccent vec \mathvec
+\definemathaccent dot \mathdot
+\definemathaccent widetilde \mathwidetilde
+\definemathaccent widehat \mathwidehat
+
+% from enco-com:
+
+\def\AA{\Aring}
+\def\aa{\aring}
+\def\AE{\AEligature}
+\def\ae{\aeligature}
+\def\CC{\Ccedilla}
+\def\cc{\ccedilla}
+\def \L{\Lstroke}
+\def \l{\lstroke}
+\def \O{\Ostroke}
+\def \o{\ostroke}
+\def\OE{\OEligature}
+\def\oe{\oeligature}
+\def\SZ{\Ssharp}
+\def\sz{\ssharp}
+\def\SS{\ssharp}
+\def\IJ{\IJligature}
+\def\ij{\ijligature}
+\def \i{\dotlessi}
+\def \j{\dotlessj}
+
+% from enco-def:
+
+\def\dotlessI {I}
+\def\dotlessJ {J}
+
+\def\Ssharp {SS}
+
+\def\eszett {\ssharp}
+\def\Eszett {\Ssharp}
+
+\def\lslash {\lstroke}
+\def\Lslash {\Lstroke}
+\def\dslash {\dstroke}
+\def\Dslash {\Dstroke}
+\def\oslash {\ostroke}
+\def\Oslash {\Ostroke}
+\def\dcroat {\dstroke}
+\def\Dcroat {\Dstroke}
+
+\def\Kcedilla {\Kcommaaccent}
+\def\kcedilla {\kcommaaccent}
+\def\Lcedilla {\Lcommaaccent}
+\def\lcedilla {\lcommaaccent}
+\def\Ncedilla {\Ncommaaccent}
+\def\ncedilla {\ncommaaccent}
+\def\Rcedilla {\Rcommaaccent}
+\def\rcedilla {\rcommaaccent}
+
+\def\S {\sectionmark}
+\def\P {\paragraphmark}
+
+\def\aumlaut {\adiaeresis}
+\def\eumlaut {\ediaeresis}
+\def\iumlaut {\idiaeresis}
+\def\oumlaut {\odiaeresis}
+\def\uumlaut {\udiaeresis}
+\def\Aumlaut {\Adiaeresis}
+\def\Eumlaut {\Ediaeresis}
+\def\Iumlaut {\Idiaeresis}
+\def\Oumlaut {\Odiaeresis}
+\def\Uumlaut {\Udiaeresis}
+
+% for latex users
+
+\def\textS {\sectionmark}
+\def\textP {\paragraphmark}
+
+% for old times sake
+
+\def\textflorin{\fhook}
+\def\florin {\textflorin}
+\def\dollar {\textdollar}
+\def\pound {\textsterling}
+\def\sterling {\textsterling}
+\def\promille {\perthousand}
+\def\permille {\perthousand}
+\def\procent {\percent}
+\def\permine {\fakepermine}
+
+% some more
+
+\def\hyphen {\softhyphen}
+\def\compoundwordmark {\hyphen}
+\def\cwm {\hyphen}
+\def\nonbreakinghyphen{\hyphen}
+\def\breakinghyphen {\hyphen\prewordbreak}
+
+% quotes
+
+\def\lowerleftsingleninequote {\quotesinglebase}
+\def\lowerleftdoubleninequote {\quotedblbase}
+\def\lowerrightsingleninequote {\quotesinglebase}
+\def\lowerrightdoubleninequote {\quotedblbase}
+
+\def\upperleftsingleninequote {\quoteright}
+\def\upperleftdoubleninequote {\quotedblright}
+\def\upperrightsingleninequote {\quoteright}
+\def\upperrightdoubleninequote {\quotedblright}
+
+\def\upperleftsinglesixquote {\quoteleft}
+\def\upperleftdoublesixquote {\quotedblleft}
+\def\upperrightsinglesixquote {\quoteleft}
+\def\upperrightdoublesixquote {\quotedblleft}
+
+\def\leftsubguillemot {\guilsingleleft}
+\def\rightsubguillemot {\guilsingleright}
+
+% obsolete:
+
+% \greekleftquot {[obsolete]}
+% \greekrightquot {[obsolete]}
+% \greekapostrophos {[obsolete]}
+% \greekupsilondialytika{[obsolete]}
+% \Ycaron {[obsolete]}
+% \ycaron {[obsolete]}
+
+% to be done in char-def:
+
+% \definecharacter cyrillicGUP {GUP}
+% \definecharacter cyrillicGHCRS {GHCRS}
+% \definecharacter cyrillicZHDSC {ZHDSC}
+% \definecharacter cyrillicKDSC {KDSC}
+% \definecharacter cyrillicKBEAK {KBEAK}
+% \definecharacter cyrillicKVCRS {KVCRS}
+% \definecharacter cyrillicNG {NG}
+% \definecharacter cyrillicOTLD {OTLD}
+% \definecharacter cyrillicY {Y}
+% \definecharacter cyrillicYHCRS {YHCRS}
+% \definecharacter cyrillicHDSC {HDSC}
+% \definecharacter cyrillicCHVCRS {CHVCRS}
+% \definecharacter cyrillicCHRDSC {CHRDSC}
+% \definecharacter cyrillicQ {Q}
+% \definecharacter cyrillicW {W}
+%
+% \definecharacter cyrillicgup {gup}
+% \definecharacter cyrillicghcrs {ghcrs}
+% \definecharacter cyrilliczhdsc {zhdsc}
+% \definecharacter cyrillickdsc {kdsc}
+% \definecharacter cyrillickbeak {kbeak}
+% \definecharacter cyrillickvcrs {kvcrs}
+% \definecharacter cyrillicng {ng}
+% \definecharacter cyrillicotld {otld}
+% \definecharacter cyrillicy {y}
+% \definecharacter cyrillicyhcrs {yhcrs}
+% \definecharacter cyrillichdsc {hdsc}
+% \definecharacter cyrillicchvcrs {chvcrs}
+% \definecharacter cyrillicchrdsc {chrdsc}
+% \definecharacter cyrillicq {q}
+% \definecharacter cyrillicw {w}
+
+% \definecharacter softhyphen 45
+% \definecharacter compoundwordmark 23
+
+% left-overs (some day in private unicode space, so that we can roundtrip)
+
+\unexpanded\def\textblacksquare {\dontleavehmode\hbox{\vrule\!!width.3\s!em\!!height.4\s!em\!!depth-.1\s!em}}
+\unexpanded\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}}
+\unexpanded\def\schwagrave {\buildtextgrave\schwa}
+
+\chardef\textcontrolspace"2423
+
+\unexpanded\def\fallbackcontrolspace
+ %{\getglyph{ComputerModernMono}\textcontrolspace}
+ {\getglyph{LMTypewriter10-Regular}\textcontrolspace}
+
+\unexpanded\def\normalcontrolspace
+ {\iffontchar\font\textcontrolspace
+ \textcontrolspace
+ \else
+ \fallbackcontrolspace
+ \fi}
+
+\let\textvisiblespace\normalcontrolspace
+
+\unexpanded\def\fastcontrolspace % no glyph resolving after first (use grouped)
+ {\dofastcontrolspace}
+
+\def\dofastcontrolspace
+ {\iffontchar\font\textcontrolspace
+ \nofastfallbackcontrolspace
+ \else
+ \dofastfallbackcontrolspace
+ \fi
+ \dofastcontrolspace}
+
+\newbox\controlspacebox
+
+\def\nofastfallbackcontrolspace
+ {\let\dofastcontrolspace\textcontrolspace}
+
+\def\dofastfallbackcontrolspace
+ {\setbox\controlspacebox\hbox{\space}%
+ \setbox\controlspacebox\hbox to \wd\controlspacebox{\hss\fallbackcontrolspace\hss}%
+ \let\dofastcontrolspace\flushcontrolspacebox}
+
+\def\flushcontrolspacebox
+ {\copy\controlspacebox}
+
+% a few defaults (\{}), we really need the verbose \empty as it will be
+% stringified
+
+\defineaccent ^ {\empty} {\textcircumflex}
+\defineaccent ` {\empty} {\textgrave}
+\defineaccent ~ {\empty} {\texttilde}
+\defineaccent " {\empty} {\textdiaeresis}
+\defineaccent ' {\empty} {\textacute}
+\defineaccent . {\empty} {\textdotaccent}
+\defineaccent = {\empty} {\textmacron}
+\defineaccent c {\empty} {\textcedilla}
+\defineaccent H {\empty} {\texthungarumlaut}
+\defineaccent k {\empty} {\textogonek}
+\defineaccent r {\empty} {\textring}
+\defineaccent u {\empty} {\textbreve}
+\defineaccent v {\empty} {\textcaron}
+
+% from enco-acc:
+%
+% we should to this at the lua end and share code ..
+
+\defineaccent ^ A {\Acircumflex} \defineaccent ^ a {\acircumflex}
+\defineaccent ^ C {\Ccircumflex} \defineaccent ^ c {\ccircumflex}
+\defineaccent ^ E {\Ecircumflex} \defineaccent ^ e {\ecircumflex}
+\defineaccent ^ G {\Gcircumflex} \defineaccent ^ g {\gcircumflex}
+\defineaccent ^ H {\Hcircumflex} \defineaccent ^ h {\hcircumflex}
+\defineaccent ^ I {\Icircumflex} \defineaccent ^ i {\icircumflex} \defineaccent ^ {\i} {\icircumflex}
+\defineaccent ^ J {\Jcircumflex} \defineaccent ^ j {\jcircumflex} \defineaccent ^ {\j} {\jcircumflex}
+\defineaccent ^ O {\Ocircumflex} \defineaccent ^ o {\ocircumflex}
+\defineaccent ^ S {\Scircumflex} \defineaccent ^ s {\scircumflex}
+\defineaccent ^ U {\Ucircumflex} \defineaccent ^ u {\ucircumflex}
+\defineaccent ^ W {\Wcircumflex} \defineaccent ^ w {\wcircumflex}
+\defineaccent ^ Y {\Ycircumflex} \defineaccent ^ y {\ycircumflex}
+
+\defineaccent ` A {\Agrave} \defineaccent ` a {\agrave}
+\defineaccent ` E {\Egrave} \defineaccent ` e {\egrave}
+\defineaccent ` I {\Igrave} \defineaccent ` i {\igrave} \defineaccent ` {\i} {\igrave}
+\defineaccent ` O {\Ograve} \defineaccent ` o {\ograve}
+\defineaccent ` U {\Ugrave} \defineaccent ` u {\ugrave}
+\defineaccent ` Y {\Ygrave} \defineaccent ` y {\ygrave}
+
+\defineaccent ~ A {\Atilde} \defineaccent ~ a {\atilde}
+\defineaccent ~ I {\Itilde} \defineaccent ~ i {\itilde} \defineaccent ~ {\i} {\itilde}
+\defineaccent ~ O {\Otilde} \defineaccent ~ o {\otilde}
+\defineaccent ~ U {\Utilde} \defineaccent ~ u {\utilde}
+\defineaccent ~ N {\Ntilde} \defineaccent ~ n {\ntilde}
+
+\defineaccent " A {\Adiaeresis} \defineaccent " a {\adiaeresis}
+\defineaccent " E {\Ediaeresis} \defineaccent " e {\ediaeresis}
+\defineaccent " I {\Idiaeresis} \defineaccent " i {\idiaeresis} \defineaccent " {\i} {\idiaeresis}
+\defineaccent " O {\Odiaeresis} \defineaccent " o {\odiaeresis}
+\defineaccent " U {\Udiaeresis} \defineaccent " u {\udiaeresis}
+\defineaccent " Y {\Ydiaeresis} \defineaccent " y {\ydiaeresis}
+
+\defineaccent ' A {\Aacute} \defineaccent ' a {\aacute}
+\defineaccent ' C {\Cacute} \defineaccent ' c {\cacute}
+\defineaccent ' E {\Eacute} \defineaccent ' e {\eacute}
+\defineaccent ' I {\Iacute} \defineaccent ' i {\iacute} \defineaccent ' {\i} {\iacute}
+\defineaccent ' L {\Lacute} \defineaccent ' l {\lacute}
+\defineaccent ' N {\Nacute} \defineaccent ' n {\nacute}
+\defineaccent ' O {\Oacute} \defineaccent ' o {\oacute}
+\defineaccent ' R {\Racute} \defineaccent ' r {\racute}
+\defineaccent ' S {\Sacute} \defineaccent ' s {\sacute}
+\defineaccent ' U {\Uacute} \defineaccent ' u {\uacute}
+\defineaccent ' Y {\Yacute} \defineaccent ' y {\yacute}
+\defineaccent ' Z {\Zacute} \defineaccent ' z {\zacute}
+
+\defineaccent . C {\Cdotaccent} \defineaccent . c {\cdotaccent}
+\defineaccent . E {\Edotaccent} \defineaccent . e {\edotaccent}
+\defineaccent . G {\Gdotaccent} \defineaccent . g {\gdotaccent}
+\defineaccent . I {\Idotaccent} \defineaccent . i {\idotaccent} \defineaccent . {\i} {\idotaccent}
+\defineaccent . Z {\Zdotaccent} \defineaccent . z {\zdotaccent}
+
+\defineaccent = A {\Amacron} \defineaccent = a {\amacron}
+\defineaccent = E {\Emacron} \defineaccent = e {\emacron}
+\defineaccent = I {\Imacron} \defineaccent = i {\imacron} \defineaccent = {\i} {\imacron}
+\defineaccent = O {\Omacron} \defineaccent = o {\omacron}
+\defineaccent = U {\Umacron} \defineaccent = u {\umacron}
+
+\defineaccent c C {\Ccedilla} \defineaccent c c {\ccedilla}
+\defineaccent c K {\Kcedilla} \defineaccent c k {\kcedilla}
+\defineaccent c L {\Lcedilla} \defineaccent c l {\lcedilla}
+\defineaccent c N {\Ncedilla} \defineaccent c n {\ncedilla}
+\defineaccent c R {\Rcedilla} \defineaccent c r {\rcedilla}
+\defineaccent c S {\Scedilla} \defineaccent c s {\scedilla}
+\defineaccent c T {\Tcedilla} \defineaccent c t {\tcedilla}
+
+\defineaccent H O {\Ohungarumlaut} \defineaccent H o {\ohungarumlaut}
+\defineaccent H u {\uhungarumlaut} \defineaccent H U {\Uhungarumlaut}
+
+\defineaccent k A {\Aogonek} \defineaccent k a {\aogonek}
+\defineaccent k E {\Eogonek} \defineaccent k e {\eogonek}
+\defineaccent k I {\Iogonek} \defineaccent k i {\iogonek}
+\defineaccent k U {\Uogonek} \defineaccent k u {\uogonek}
+
+\defineaccent r A {\Aring} \defineaccent r a {\aring}
+\defineaccent r U {\Uring} \defineaccent r u {\uring}
+
+\defineaccent u A {\Abreve} \defineaccent u a {\abreve}
+\defineaccent u E {\Ebreve} \defineaccent u e {\ebreve}
+\defineaccent u G {\Gbreve} \defineaccent u g {\gbreve}
+\defineaccent u I {\Ibreve} \defineaccent u i {\ibreve} \defineaccent u {\i} {\ibreve}
+\defineaccent u O {\Obreve} \defineaccent u o {\obreve}
+\defineaccent u U {\Ubreve} \defineaccent u u {\ubreve}
+
+\defineaccent v C {\Ccaron} \defineaccent v c {\ccaron}
+\defineaccent v D {\Dcaron} \defineaccent v d {\dcaron}
+\defineaccent v E {\Ecaron} \defineaccent v e {\ecaron}
+\defineaccent v L {\Lcaron} \defineaccent v l {\lcaron}
+\defineaccent v N {\Ncaron} \defineaccent v n {\ncaron}
+\defineaccent v R {\Rcaron} \defineaccent v r {\rcaron}
+\defineaccent v S {\Scaron} \defineaccent v s {\scaron}
+\defineaccent v T {\Tcaron} \defineaccent v t {\tcaron}
+\defineaccent v Z {\Zcaron} \defineaccent v z {\zcaron}
+
+% from enco-mis:
+
+\def\fakepercent
+ {\mathematics{^{\scriptscriptstyle0}\kern-.25em/\kern-.2em_{\scriptscriptstyle0}}}
+
+\def\fakeperthousand
+ {\mathematics{^{\scriptscriptstyle0}\kern-.25em/\kern-.2em_{\scriptscriptstyle00}}}
+
+\def\fakepermine
+ {\dontleavehmode
+ \bgroup
+ \setbox\scratchbox\hbox
+ {\mathematics{+}}%
+ \hbox to \wd\scratchbox
+ {\hss
+ \mathematics{^{\scriptscriptstyle-}\kern-.4em/\kern-.3em_{\scriptscriptstyle-}}%
+ \hss}%
+ \egroup}
+
+%D A smaller and bolder variant, more like the math and monospaced ones.
+
+% \def\fakeunderscore
+% {\dontleavehmode\hbox % was \leavevmode
+% {\setbox\scratchbox\hbox{(}%
+% \scratchdimen.2\dp\scratchbox
+% \setbox\scratchbox\hbox{\space}%
+% \vrule
+% \!!depth \scratchdimen
+% \!!width \wd\scratchbox
+% \!!height\zeropoint}}
+
+% \startTEXpage
+% \ruledhbox{\strut$1\fakeunderscore^{1\fakeunderscore}$}
+% \ruledhbox{\strut$1\xfakeunderscore^{1\xfakeunderscore}$}
+% \stopTEXpage
+
+\def\fakeunderscore
+ {\relax\ifmmode
+ \vrule\!!depth .12\fontexheight\mathstylefont\normalmathstyle\!!width \fontinterwordspace\mathstylefont\normalmathstyle\!!height\zeropoint\relax
+ \else
+ \dontleavehmode\hbox{\vrule\!!depth .12\fontexheight\font\!!width \fontinterwordspace\font\!!height\zeropoint}%
+ \fi}
+
+\def\fakeunderscores{\let\_\fakeunderscore}
+\def\textunderscores{\let\_\textunderscore}
+
+\textunderscores
+
+\ifx\mathunderscore\undefined \let\mathunderscore\fakeunderscore \fi
+\ifx\textunderscore\undefined \let\textunderscore\fakeunderscore \fi
+
+\unexpanded\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi}
+
+\let\_\normalunderscore
+
+\protect \endinput
diff --git a/tex/context/base/enco-l7x.mkii b/tex/context/base/enco-l7x.mkii
new file mode 100644
index 000000000..8f355317b
--- /dev/null
+++ b/tex/context/base/enco-l7x.mkii
@@ -0,0 +1,236 @@
+%D \module
+%D [ file=enco-l7x,
+%D version=2010.01.22,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=\LATEX\ L7x Encoding,
+%D author={Hans Hagen \& Mojca Miklavec},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 Encoding vector to support Latvian and Lithuanian. The first
+%D part is taken from EC encoding, the rest has not been tested
+%D extensively.
+
+\startmapping[l7x]
+
+\definecaseswap 25 `I % dotless i (TODO - probably wrong; maybe use \defineuppercasecom)
+\definecaseswap 156 140 % oeligature
+\definecaseswap 184 168 % ostroke
+\definecaseswap 186 170 % rcommaaccent
+\definecaseswap 191 175 % aeligature
+\definecaseself 223 % ssharp (this is wrong, but no better way)
+
+\definecasemaps 192 to 222 lc +32 uc 0
+\definecasemaps 224 to 254 lc 0 uc -32
+\resetcaserange 215 to 215 % textmultiply
+\resetcaserange 247 to 247 % textdiv
+
+\stopmapping
+
+\startencoding[l7x]
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter texthungarumlaut 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter textogonek 12
+\definecharacter quotesinglebase 13
+\definecharacter guilsingleleft 14
+\definecharacter guilsingleright 15
+\definecharacter quotedblleft 16
+\definecharacter quotedblright 17
+\definecharacter quotedblbase 18
+\definecharacter leftguillemot 19
+\definecharacter rightguillemot 20
+\definecharacter endash 21
+\definecharacter emdash 22
+%definecharacter compoundwordmark 23
+%definecharacter perthousand 24
+\definecharacter dotlessi 25 % or when missing: {j}
+\definecharacter dotlessj 26
+% ff 27
+% fi 28
+% fl 29
+% ffi 30
+% ffl 31
+%definecharacter textvisiblespace 32
+% exclam ! 33
+\definecharacter quotedbl 34
+% numbersign # 35
+% dollar $ 36
+\definecharacter percent 37
+% ampersand & 38
+%definecharacter quotesingle 39 % fake 'm TODO:enco-def!!!!
+\definecharacter quoteright 39
+% parenleft ( 40
+% parenright ) 41
+% asterisk * 42
+% plus + 43
+% comma , 44
+\definecharacter softhyphen 45
+% period . 46
+% slash / 47
+% 0-9 48-57
+% colon : 58
+% semicolon ; 59
+% less < 60
+% equal = 61
+% greater > 62
+% question ? 63
+% at @ 64
+% A-Z 65-90
+% bracketleft [ 91
+\definecharacter textbackslash 92
+% bracketright ] 93
+\definecharacter textasciicircum 94
+\definecharacter textunderscore 95
+\definecharacter quoteleft 96
+% a-z 97-122
+\definecharacter textbraceleft 123
+\definecharacter textbraceright 125
+\definecharacter textasciitilde 126
+% .notdef 127
+\definecharacter texteuro 128
+% .notdef 129
+\definecharacter quotesinglebase 130
+\definecharacter textflorin 131 \definecharacter fhook 131
+\definecharacter quotedblbase 132
+\definecharacter textellipsis 133
+\definecharacter textdag 134
+\definecharacter textddag 135
+% .notdef 136
+\definecharacter perthousand 137
+% .notdef 138
+\definecharacter guilsingleleft 139
+\definecharacter OEligature 140 % TODO: also \OE???
+\definecharacter textdiaeresis 141
+\definecharacter textcaron 142
+\definecharacter textcedilla 143
+% .notdef 144
+\definecharacter quoteleft 145
+\definecharacter quoteright 146
+\definecharacter quotedblleft 147
+\definecharacter quotedblright 148
+\definecharacter textbullet 149
+\definecharacter endash 150
+\definecharacter emdash 151
+% .notdef 152
+\definecharacter trademark 153
+% .notdef 154
+\definecharacter guilsingleright 155
+\definecharacter oeligature 156
+\definecharacter textmacron 157
+\definecharacter textogonek 158
+% .notdef 159
+%definecharacter space 160 % TODO!!!
+\definecharacter quotedblright 161
+\definecharacter textcent 162
+\definecharacter textsterling 163
+\definecharacter textcurrency 164
+\definecharacter quotedblbase 165
+\definecharacter textbrokenbar 166
+\definecharacter sectionmark 167
+\definecharacter Ostroke 168
+\definecharacter copyright 169
+\definecharacter Rcommaaccent 170
+\definecharacter leftguillemot 171
+\definecharacter textlognot 172
+%definecharacter softhyphen 173 % -> 45 (TODO!!!)
+\definecharacter registered 174
+\definecharacter AEligature 175
+\definecharacter textdegree 176
+\definecharacter textpm 177
+\definecharacter twosuperior 178
+\definecharacter threesuperior 179
+\definecharacter quotedblleft 180
+\definecharacter textmu 181
+\definecharacter paragraphmark 182
+\definecharacter periodcentered 183
+\definecharacter ostroke 184
+\definecharacter onesuperior 185
+\definecharacter rcommaaccent 186
+\definecharacter rightguillemot 187
+\definecharacter onequarter 188
+\definecharacter onehalf 189
+\definecharacter threequarter 190
+\definecharacter aeligature 191
+\definecharacter Aogonek 192
+\definecharacter Iogonek 193
+\definecharacter Amacron 194
+\definecharacter Cacute 195
+\definecharacter Adiaeresis 196
+\definecharacter Aring 197
+\definecharacter Eogonek 198
+\definecharacter Emacron 199
+\definecharacter Ccaron 200
+\definecharacter Eacute 201
+\definecharacter Zacute 202
+\definecharacter Edotaccent 203
+\definecharacter Gcommaaccent 204
+\definecharacter Kcommaaccent 205
+\definecharacter Imacron 206
+\definecharacter Lcommaaccent 207
+\definecharacter Scaron 208
+\definecharacter Nacute 209
+\definecharacter Ncommaaccent 210
+\definecharacter Oacute 211
+\definecharacter Omacron 212
+\definecharacter Otilde 213
+\definecharacter Odiaeresis 214
+\definecharacter textmultiply 215
+\definecharacter Uogonek 216
+\definecharacter Lstroke 217
+\definecharacter Sacute 218
+\definecharacter Umacron 219
+\definecharacter Udiaeresis 220
+\definecharacter Zdotaccent 221
+\definecharacter Zcaron 222
+\definecharacter ssharp 223
+\definecharacter aogonek 224
+\definecharacter iogonek 225
+\definecharacter amacron 226
+\definecharacter cacute 227
+\definecharacter adiaeresis 228
+\definecharacter aring 229
+\definecharacter eogonek 230
+\definecharacter emacron 231
+\definecharacter ccaron 232
+\definecharacter eacute 233
+\definecharacter zacute 234
+\definecharacter edotaccent 235
+\definecharacter gcommaaccent 236
+\definecharacter kcommaaccent 237
+\definecharacter imacron 238
+\definecharacter lcommaaccent 239
+\definecharacter scaron 240
+\definecharacter nacute 241
+\definecharacter ncommaaccent 242
+\definecharacter oacute 243
+\definecharacter omacron 244
+\definecharacter otilde 245
+\definecharacter odiaeresis 246
+\definecharacter textdiv 247
+\definecharacter uogonek 248
+\definecharacter lstroke 249
+\definecharacter sacute 250
+\definecharacter umacron 251
+\definecharacter udiaeresis 252
+\definecharacter zdotaccent 253
+\definecharacter zcaron 254
+\definecharacter quoteright 255
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-lat.mkii b/tex/context/base/enco-lat.mkii
new file mode 100644
index 000000000..2623aae8d
--- /dev/null
+++ b/tex/context/base/enco-lat.mkii
@@ -0,0 +1,7 @@
+% temporary module, needed for downward compatibility
+
+\input regi-lat.tex
+
+\enableregime[latin2]
+
+\endinput
diff --git a/tex/context/base/enco-mis.mkii b/tex/context/base/enco-mis.mkii
new file mode 100644
index 000000000..92dc61b3f
--- /dev/null
+++ b/tex/context/base/enco-mis.mkii
@@ -0,0 +1,188 @@
+%D \module
+%D [ file=enco-mis,
+%D version=2000.05.07, % 1999.11.11,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Missing Glyphs,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 In this file we collect some definitions that construct
+%D pseudo characters. Some day we will move some definitions
+%D from \type {plain.tex} to this file. Some definitions are
+%D derived from definitions in the \LATEX\ distribution,
+%D especially Johannes Braams' Babel system.
+
+\startmapping[\s!default]
+
+\defineuppercasecom \dj \DJ
+\defineuppercasecom \Dj \dj
+\defineuppercasecom \DJ \dj
+
+\definecharacter dstroke {\pseudoencodeddj}
+\definecharacter Dstroke {\pseudoencodedDJ}
+
+\stopmapping
+
+%D We need proper names like in enco-com.tex!
+
+\definecharacter dj {\dstroke} % {\pseudoencodeddj}
+\definecharacter Dj {\Dstroke} % {\pseudoencodedDJ}
+\definecharacter DJ {\Dstroke} % {\pseudoencodedDJ}
+
+\unprotect
+
+\def\pseudoencodeddj % like in babel, but safer
+ {\dontleavehmode\hbox\bgroup
+ \setbox\scratchbox\hbox{d}%
+ \scratchdimen\ht\scratchbox
+ \advance\scratchdimen 1ex
+ \scratchdimen.45\scratchdimen
+ \dimen2=\withoutpt\the\slantperpoint\dimen0
+ \advance\dimen2 .5ex
+ \hbox to \wd\scratchbox
+ {\box\scratchbox\hss
+ \raise\scratchdimen\hbox{\kern\dimen2\vbox{\hrule\!!height0.1ex\!!width0.3em}}}%
+ \egroup}
+
+\def\pseudoencodedDJ % design: taco; quality assurance: mojca; cleanup: hans
+ {\dontleavehmode
+ \hbox\bgroup
+ \setbox\scratchbox\hbox{D}%
+ \dimen2=1.1ex
+ \dimen2=\withoutpt\the\slantperpoint\dimen2
+ \hbox to \wd\scratchbox
+ {\rlap
+ {\raise.52\ht\scratchbox
+ \hbox
+ {\kern\dimen2
+ \vbox{\hrule\!!height.04ex\!!depth.04ex\!!width.4\wd\scratchbox}}}%
+ \box\scratchbox}%
+ \egroup}
+
+% currency
+
+\def\fakedollar % pretty cmr dependent
+ {\bgroup
+ \ifnum\fam=\itfam
+ \sl
+ \else\ifnum\fam=\bifam
+ \bs
+ \fi\fi
+ \$%
+ \egroup}
+
+\def\fakesterling % pretty cmr dependent
+ {\bgroup
+ \ifnum\fam=\bffam
+ \bi
+ \else\ifnum\fam=\bifam
+ \bi
+ \else\ifnum\fam=\bsfam
+ \bi
+ \else
+ \it
+ \fi\fi\fi
+ \$%
+ \egroup}
+
+\def\fakeflorin
+ {\bgroup
+ \ifnum\fam=\bffam
+ \bi
+ \else\ifnum\fam=\bifam
+ \bi
+ \else\ifnum\fam=\bsfam
+ \bi
+ \else
+ \it
+ \fi\fi\fi
+ f%
+ \egroup}
+
+% perthings
+
+\def\fakepercent
+ {\mathematics{^{\scriptscriptstyle0}\kern-.25em/\kern-.2em_{\scriptscriptstyle0}}}
+
+\def\fakeperthousand
+ {\mathematics{^{\scriptscriptstyle0}\kern-.25em/\kern-.2em_{\scriptscriptstyle00}}}
+
+\def\fakepermine
+ {\dontleavehmode
+ \bgroup
+ \setbox\scratchbox\hbox
+ {\mathematics{+}}%
+ \hbox to \wd\scratchbox
+ {\hss
+ \mathematics{^{\scriptscriptstyle-}\kern-.4em/\kern-.3em_{\scriptscriptstyle-}}%
+ \hss}%
+ \egroup}
+
+% guillemots
+
+%D Yes I know, they are ugly:
+
+\def\fakeleftguillemot
+ {\dontleavehmode\hbox{\raise.25ex\hbox{$\scriptscriptstyle\ll$}}}
+
+\def\fakerightguillemot
+ {\hbox{\raise.25ex\hbox{$\scriptscriptstyle\gg$}}}
+
+\def\fakeleftsubguillemot
+ {\dontleavehmode\hbox{\raise.25ex\hbox{$\scriptscriptstyle<$}}}
+
+\def\fakerightsubguillemot
+ {\hbox{\raise.25ex\hbox{$\scriptscriptstyle>$}}}
+
+%D Needed:
+
+\def\fakevisiblespace
+ {\leavevmode\hbox
+ {\setbox\scratchbox\hbox{(}%
+ \scratchdimen.1\dp\scratchbox
+ \setbox\scratchbox\hbox{\space}%
+ \hbox to \wd\scratchbox
+ {\vrule
+ \!!depth 5\scratchdimen
+ \!!width \scratchdimen
+ \!!height \zeropoint
+ \hss
+ \vrule
+ \!!depth 5\scratchdimen
+ \!!width \wd\scratchbox
+ \!!height-4\scratchdimen
+ \hss
+ \vrule
+ \!!depth 5\scratchdimen
+ \!!width \scratchdimen
+ \!!height \zeropoint}}}
+
+%\def\fakeunderscore{\leavevmode\kern.06em\vbox{\hrule\!!width.3em}}
+
+\def\fakeunderscore
+ {\leavevmode\hbox
+ {\setbox\scratchbox\hbox{(}%
+ \scratchdimen.2\dp\scratchbox
+ \setbox\scratchbox\hbox{\space}%
+ \vrule
+ \!!depth \scratchdimen
+ \!!width \wd\scratchbox
+ \!!height\zeropoint}}
+
+\ifx\mathunderscore\undefined \let\mathunderscore\fakeunderscore \fi
+\ifx\textunderscore\undefined \let\textunderscore\fakeunderscore \fi
+
+\unexpanded\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi}
+
+\let\_\normalunderscore
+
+% Handy but obsolete, replaced by \unknownchar:
+%
+% \def\missingglyph{\ruledhbox{?}}
+
+\protect \endinput
diff --git a/tex/context/base/enco-pdf.mkii b/tex/context/base/enco-pdf.mkii
new file mode 100644
index 000000000..a03e81df2
--- /dev/null
+++ b/tex/context/base/enco-pdf.mkii
@@ -0,0 +1,278 @@
+%D \module
+%D [ file=enco-pdf,
+%D version=1995.01.01,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=\YandY\ texnansi Encoding,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%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 is the \PDF\ document encoding.
+
+\startencoding[pdfdoc] % \rawcharacter{number}
+
+\definecharacter oeligature ^^9c
+
+\definecharacter leftguillemot ^^ab
+\definecharacter rightguillemot ^^bb
+
+\definecharacter Agrave ^^c0
+\definecharacter Aacute ^^c1
+\definecharacter Acircumflex ^^c2
+\definecharacter Atilde ^^c3
+\definecharacter Adiaeresis ^^c4
+\definecharacter OAligature ^^c5
+\definecharacter AEligature ^^c6
+\definecharacter Ccedilla ^^c7
+\definecharacter Egrave ^^c8
+\definecharacter Eacute ^^c9
+\definecharacter Ecircumflex ^^ca
+\definecharacter Ediaeresis ^^cb
+\definecharacter Igrave ^^cc
+\definecharacter Iacute ^^cd
+\definecharacter Icircumflex ^^ce
+\definecharacter Idiaeresis ^^cf
+
+\definecharacter Ntilde ^^d1
+\definecharacter Ograve ^^d2
+\definecharacter Oacute ^^d3
+\definecharacter Ocircumflex ^^d4
+\definecharacter Otilde ^^d5
+\definecharacter Odiaeresis ^^d6
+
+\definecharacter Ugrave ^^d9
+\definecharacter Uacute ^^da
+\definecharacter Ucircumflex ^^db
+\definecharacter Udiaeresis ^^dc
+\definecharacter Yacute ^^dd
+
+\definecharacter ssharp ^^df
+\definecharacter agrave ^^e0
+\definecharacter aacute ^^e1
+\definecharacter acircumflex ^^e2
+\definecharacter atilde ^^e3
+\definecharacter adiaeresis ^^e4
+\definecharacter oaligature ^^e5
+\definecharacter aeligature ^^e6
+\definecharacter ccedilla ^^e7
+\definecharacter egrave ^^e8
+\definecharacter eacute ^^e9
+\definecharacter ecircumflex ^^ea
+\definecharacter ediaeresis ^^eb
+\definecharacter igrave ^^ec
+\definecharacter iacute ^^ed
+\definecharacter icircumflex ^^ee
+\definecharacter idiaeresis ^^ef
+
+\definecharacter ntilde ^^f1
+\definecharacter ograve ^^f2
+\definecharacter oacute ^^f3
+\definecharacter ocircumflex ^^f4
+\definecharacter otilde ^^f5
+\definecharacter odiaeresis ^^f6
+
+\definecharacter ugrave ^^f9
+\definecharacter uacute ^^fa
+\definecharacter ucircumflex ^^fb
+\definecharacter udiaeresis ^^fc
+\definecharacter yacute ^^fd
+
+\definecharacter ydiaeresis ^^ff
+
+\definecharacter leftsubguillemot {\leftguillemot}
+\definecharacter rightsubguillemot {\rightguillemot}
+
+\definecharacter Uhungarumlaut {\Ucircumflex}
+\definecharacter uhungarumlaut {\ucircumflex}
+\definecharacter Ohungarumlaut {\Ocircumflex}
+\definecharacter ohungarumlaut {\ocircumflex}
+
+\definecharacter Aogonek {A}
+\definecharacter aogonek {a}
+\definecharacter Eogonek {E}
+\definecharacter eogonek {e}
+\definecharacter Iogonek {I}
+\definecharacter iogonek {i}
+\definecharacter Uogonek {U}
+\definecharacter uogonek {u}
+
+\definecharacter Aring {A}
+\definecharacter aring {a}
+\definecharacter Uring {U}
+\definecharacter uring {u}
+
+\definecharacter Abreve {A}
+\definecharacter abreve {a}
+\definecharacter Ebreve {E}
+\definecharacter ebreve {e}
+\definecharacter Gbreve {G}
+\definecharacter gbreve {g}
+\definecharacter Ibreve {I}
+\definecharacter ibreve {i}
+\definecharacter Obreve {O}
+\definecharacter obreve {o}
+\definecharacter Ubreve {U}
+\definecharacter ubreve {u}
+
+\definecharacter Ccaron {C}
+\definecharacter ccaron {c}
+\definecharacter Dcaron {D}
+\definecharacter dcaron {d}
+\definecharacter Ecaron {E}
+\definecharacter ecaron {e}
+\definecharacter Lcaron {L}
+\definecharacter lcaron {l}
+\definecharacter Ncaron {N}
+\definecharacter ncaron {n}
+\definecharacter Rcaron {R}
+\definecharacter rcaron {r}
+\definecharacter Scaron {S}
+\definecharacter scaron {s}
+\definecharacter Tcaron {T}
+\definecharacter tcaron {t}
+\definecharacter Ycaron {Y}
+\definecharacter ycaron {y}
+\definecharacter Zcaron {Z}
+\definecharacter zcaron {z}
+
+\definecharacter Lstroke {L}
+\definecharacter lstroke {l}
+\definecharacter Ostroke {O}
+\definecharacter ostroke {o}
+
+\definecharacter aumlaut {\adiaeresis}
+\definecharacter eumlaut {\ediaeresis}
+\definecharacter iumlaut {\idiaeresis}
+\definecharacter oumlaut {\odiaeresis}
+\definecharacter uumlaut {\udiaeresis}
+
+\definecharacter Aumlaut {\Adiaeresis}
+\definecharacter Eumlaut {\Ediaeresis}
+\definecharacter Iumlaut {\Idiaeresis}
+\definecharacter Oumlaut {\Odiaeresis}
+\definecharacter Uumlaut {\Udiaeresis}
+
+\definecharacter scommaaccent {s}
+\definecharacter Scommaaccent {S}
+\definecharacter tcommaaccent {t}
+\definecharacter Tcommaaccent {T}
+
+\definecharacter Etilde {E}
+\definecharacter etilde {e}
+
+\definecharacter Ahook {A}
+\definecharacter ahook {a}
+\definecharacter Ehook {E}
+\definecharacter ehook {e}
+\definecharacter Ihook {I}
+\definecharacter ihook {i}
+\definecharacter Ohook {O}
+\definecharacter ohook {o}
+\definecharacter Uhook {U}
+\definecharacter uhook {u}
+\definecharacter Yhook {Y}
+\definecharacter yhook {y}
+
+\definecharacter Acircumflexgrave {\Acircumflex}
+\definecharacter Acircumflexacute {\Acircumflex}
+\definecharacter Acircumflextilde {\Acircumflex}
+\definecharacter Acircumflexhook {\Acircumflex}
+\definecharacter acircumflexgrave {\acircumflex}
+\definecharacter acircumflexacute {\acircumflex}
+\definecharacter acircumflextilde {\acircumflex}
+\definecharacter acircumflexhook {\acircumflex}
+\definecharacter Ecircumflexgrave {\Ecircumflex}
+\definecharacter Ecircumflexacute {\Ecircumflex}
+\definecharacter Ecircumflextilde {\Ecircumflex}
+\definecharacter Ecircumflexhook {\Ecircumflex}
+\definecharacter ecircumflexgrave {\ecircumflex}
+\definecharacter ecircumflexacute {\ecircumflex}
+\definecharacter ecircumflextilde {\ecircumflex}
+\definecharacter ecircumflexhook {\ecircumflex}
+\definecharacter Ocircumflexgrave {\Ocircumflex}
+\definecharacter Ocircumflexacute {\Ocircumflex}
+\definecharacter Ocircumflextilde {\Ocircumflex}
+\definecharacter Ocircumflexhook {\Ocircumflex}
+\definecharacter ocircumflexgrave {\ocircumflex}
+\definecharacter ocircumflexacute {\ocircumflex}
+\definecharacter ocircumflextilde {\ocircumflex}
+\definecharacter ocircumflexhook {\ocircumflex}
+
+\definecharacter Abrevegrave {A}
+\definecharacter Abreveacute {A}
+\definecharacter Abrevetilde {A}
+\definecharacter Abrevehook {A}
+\definecharacter abrevegrave {a}
+\definecharacter abreveacute {a}
+\definecharacter abrevetilde {a}
+\definecharacter abrevehook {a}
+
+\definecharacter Adotbelow {A}
+\definecharacter adotbelow {a}
+\definecharacter Edotbelow {E}
+\definecharacter edotbelow {e}
+\definecharacter Idotbelow {I}
+\definecharacter idotbelow {i}
+\definecharacter Odotbelow {O}
+\definecharacter odotbelow {o}
+\definecharacter Udotbelow {U}
+\definecharacter udotbelow {u}
+\definecharacter Ydotbelow {Y}
+\definecharacter ydotbelow {y}
+\definecharacter Ohorndotbelow {O}
+\definecharacter ohorndotbelow {o}
+\definecharacter Uhorndotbelow {U}
+\definecharacter uhorndotbelow {u}
+
+\definecharacter Acircumflexdotbelow {\Acircumflex}
+\definecharacter acircumflexdotbelow {\acircumflex}
+\definecharacter Ecircumflexdotbelow {\Ecircumflex}
+\definecharacter ecircumflexdotbelow {\ecircumflex}
+\definecharacter Ocircumflexdotbelow {\Ocircumflex}
+\definecharacter ocircumflexdotbelow {\ocircumflex}
+\definecharacter Abrevedotbelow {\Abreve}
+\definecharacter abrevedotbelow {\abreve}
+
+\definecharacter Ohorn {O}
+\definecharacter Ohorngrave {O}
+\definecharacter Ohornacute {O}
+\definecharacter Ohorntilde {O}
+\definecharacter Ohornhook {O}
+
+\definecharacter ohorn {o}
+\definecharacter ohorngrave {o}
+\definecharacter ohornacute {o}
+\definecharacter ohorntilde {o}
+\definecharacter ohornhook {o}
+
+\definecharacter Uhorn {U}
+\definecharacter Uhorngrave {U}
+\definecharacter Uhornacute {U}
+\definecharacter Uhorntilde {U}
+\definecharacter Uhornhook {U}
+
+\definecharacter uhorn {u}
+\definecharacter uhorngrave {u}
+\definecharacter uhornacute {u}
+\definecharacter uhorntilde {u}
+\definecharacter uhornhook {u}
+
+\definecharacter Utilde {U}
+\definecharacter utilde {u}
+\definecharacter Itilde {I}
+\definecharacter itilde {i}
+\definecharacter Ygrave {Y}
+\definecharacter ygrave {y}
+\definecharacter Ytilde {Y}
+\definecharacter ytilde {y}
+
+\definecharacter dstroke {d}
+\definecharacter Dstroke {D}
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-pfr.mkii b/tex/context/base/enco-pfr.mkii
new file mode 100644
index 000000000..b279e40aa
--- /dev/null
+++ b/tex/context/base/enco-pfr.mkii
@@ -0,0 +1,305 @@
+%D \module
+%D [ file=enco-pfr,
+%D version=2000.12.10, % adapted 2005.08.14 to more delayed loading
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=PDF Resources,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifnum\texengine>\pdftexengine
+ \expandafter \endinput
+\fi
+
+\ifdefined\pdffontresource \else
+ \expandafter \endinput
+\fi
+
+\writestatus{loading}{ConTeXt Encoding Macros / PDF Resources}
+
+%D This is an experimental module in which we implement
+%D font resource inclusion in \PDF. One reason to include
+%D font resources is that it enables a search engine to
+%D perform a search (I'm told). This feature ws requested by
+%D Petr Ferdus from Czech.
+
+%D A simple test file may look like this (watch how we first
+%D load the encoding and then the font; previous font
+%D definitions are left untouched.)
+%D
+%D \starttyping
+%D % output=pdftex interface=en
+%D
+%D \useencoding[pfr]
+%D \setupbodyfont[csr]
+%D
+%D \starttext
+%D test \`z \'z \bf test \sl test \bs quite funny \`z \page
+%D test \`z \'z \bf test \sl test \bs quite funny \`z \page
+%D \stoptext
+%D \stoptyping
+%D
+%D We do our best to include a (often large) font resources
+%D only once. The current implementation is not that
+%D general which is also due to the fact that \type
+%D {\pdffontattr} is expanded instantly and persistent. A
+%D more versatile (but also slower) approach is to keep track
+%D of the fonts and either flush the information at shipout
+%D time, or at the end of the document.
+
+%D \macros
+%D {ifincludepdffontresources}
+%D
+%D You can turn of this feature using the following switch.
+
+\newif\ifincludepdffontresources \includepdffontresourcestrue
+
+\ifx\pdfglyphtounicode\undefined \else
+ \appendtoks
+ \doif\jobsuffix{pdf}{\readfile{pdfr-def.mkii}\donothing\donothing}%
+ \to \everystarttext
+\fi
+
+% somehow we cannot preload this beast; also, it's mk dependent
+%
+% \appendtoks
+% \doifelse{\jobsuffix}{pdf}{\loadmkiifile{pdfr-def.mkii}}%
+% \to \everystarttext
+
+% ugly, this should go to the driver spec-tpd
+
+\ifx\pdfgentounicode\undefined \else
+ \ifcase\pdfgentounicode \else
+ \expandafter \expandafter \expandafter \endinput
+ \fi
+\fi
+
+\unprotect
+
+% a problem is that there is always an ec vector added even when
+% we switch to texnansi early; this has to do with the fact that
+% we need to setup fonts at startup; this a pain when we have
+% textless documents, so we should have a way around, i.e. an
+% extension to pdftex where we can tag numbers inside user specs
+% and attributes.
+%
+% currently we need to use immediate so we end up with entries
+
+%D The name of the resource is stored in a macro, as is its
+%D object reference. A resource is only processed once. When
+%D done, the resource name is erased, and we use this fact to
+%D prevent redefinition as well as well as reloading. So, a
+%D macro defined with \type {\pdffontfileresource} can have
+%D three states:
+%D
+%D \startitemize[packed]
+%D \item undefined: not yet loaded, and not yet included
+%D \item some value: loaded, but not yet included
+%D \item empty: loaded, and already included
+%D \stopitemize
+
+\def\pdffontresource {pdfr:\currentencoding}
+\def\pdffontfileresource{pdff:\pdffontresource}
+
+%D A resource is defined in a file prefixed by \type {pdfr-}.
+%D The following \PDF\ code is composed by Ondrej Koala Vacha (I
+%D probably mispelled this name).
+%D
+%D \starttyping
+%D \startpdffontresource[il2]
+%D /CIDInit /ProcSet findresource begin
+%D 12 dict begin
+%D begincmap
+%D /CIDSystemInfo
+%D << /Registry (Adobe)
+%D /Ordering (T1UV)
+%D /Supplement 0
+%D >> def
+%D /CMapName /Adobe-Identity-UCS def
+%D /CMapType 1 def
+%D 1 begincodespacerange
+%D <00>
+%D endcodespacerange
+%D %%FontSpecificEncoding
+%D 191 beginbfrange
+%D <20> <20> <0020> % space dec: 32 oct:040 hex:20
+%D .... .... ...... . ........ .... .. ....... ......
+%D <00ff> % dotaccent dec:255 oct:377 hex:ff
+%D endbfrange
+%D endcmap
+%D CMapName currentdict /CMap defineresource pop end
+%D end
+%D \stoppdffontresource
+%D \stoptyping
+%D
+%D We don't preload such huge definitions, and process them
+%D run||time to save memory. Therefore, in the encoding
+%D vector, we only add an entry like:
+%D
+%D \starttyping
+%D \startencoding [il2]
+%D \usepdffontresource il2
+%D \stopencoding
+%D \stoptyping
+%D
+%D This macro is defined as follows.
+
+\def\usepdffontresource #1 %
+ {\doifundefinedelse\pdffontfileresource % okay, undefined, so either
+ {\setxvalue\pdffontfileresource{#1}} % brand new, or not yet loaded
+ {\doifvaluesomething\pdffontfileresource % only if not loaded in which
+ {\setxvalue\pdffontfileresource{#1}}}} % case it's made empty
+
+%D Watch how we check for duplicated loading. The resource
+%D itself, when asked for, is included immediately, after which
+%D we save its reference. Normally a document will have one
+%D such a resource.
+
+% \long\def\startpdffontresource[#1]#2\stoppdffontresource
+% {\doif{#1}\currentencoding
+% {\immediate\pdfobj useobjnum \getvalue{\pdffontresource} stream {#2}}}
+
+% alternatively we can use object references
+
+% fails when we switch back and forward between dvi/pdf mode
+%
+% \long\def\startpdffontresource[#1]#2\stoppdffontresource
+% {\doif{#1}\currentencoding{\doifdefined\pdffontresource
+% {\immediate\pdfobj useobjnum \getvalue{\pdffontresource} stream {#2}}}}
+
+\long\def\startpdffontresource[#1]#2\stoppdffontresource
+ {\doif{#1}\currentencoding{\doifdefined\pdffontresource
+ {\expanded{\doshipoutpdffontresource{\getvalue{\pdffontresource}}{#2}}}}}
+
+\def\doshipoutpdffontresource#1#2%
+ {\ifnum\realpageno<\plustwo
+ \doglobal\appendtoks
+ \ifcase\pdfoutput\else\immediate\pdfobj useobjnum #1 stream {#2}\fi
+ \to\everyfirstshipout
+ \else
+ \ifcase\pdfoutput\else\immediate\pdfobj useobjnum #1 stream {#2}\fi
+ \fi}
+
+% cleaner but not better:
+%
+% \newtoks \collectedpdffontresources
+%
+% \def\doshipoutpdffontresource#1#2%
+% {\doglobal\appendtoks
+% \ifcase\pdfoutput\else\immediate\pdfobj useobjnum #1 stream {#2}\fi
+% \to \collectedpdffontresources}
+%
+% \def\dofluspdffontresources
+% {\the\collectedpdffontresources
+% \global\collectedpdffontresources\emptytoks}
+%
+% \appendtoks \dofluspdffontresources \to \everybeforeshipout
+
+%D The reference to such a vector is to be handled at font
+%D definition time, which is why we hook it into the font
+%D loading routine. A little bit of indirectness speeds up
+%D the process when this feature is disabled and keeps the
+%D macros readable.
+
+% \newevery \everyfont \relax
+
+\appendtoksonce \includepdffontresource \to \everyfont
+
+% \def\includepdffontresource
+% {\ifincludepdffontresources
+% \ifx\pdffontattr\undefined
+% % we're not using (a recent version of) pdftex
+% \else\ifcase\pdfoutput
+% % we're not in pdf mode
+% \else
+% \doincludepdffontresource
+% \fi\fi
+% \fi}
+
+\def\includepdffontresource
+ {\ifx\pdfgentounicode\undefined
+ \expandafter\ifx\the\font\nullfont \else
+ \ifx\pdffontattr\undefined
+ % we're not using (a recent version of) pdftex
+ \else\ifcase\pdfoutput
+ % we're not in pdf mode
+ \else
+ \doincludepdffontresource
+ \fi\fi
+ \fi
+ \else\ifcase\pdfgentounicode
+ \ifincludepdffontresources
+ \expandafter\ifx\the\font\nullfont \else
+ \ifx\pdffontattr\undefined
+ % we're not using (a recent version of) pdftex
+ \else\ifcase\pdfoutput
+ % we're not in pdf mode
+ \else
+ \doincludepdffontresource
+ \fi\fi
+ \fi
+ \fi
+ \or
+ \global\let\includepdffontresource\relax % automatic, built in
+ \fi\fi}
+
+\def\dododoincludepdffontresource#1% encoding
+ {\bgroup
+ \edef\currentencoding{#1}%
+ \doifvaluesomething\pdffontfileresource
+ {\startreadingfile
+ \ignorelines % just in case \par is redefined; this thing can get called anywhere
+ \readsysfile{pdfr-\getvalue\pdffontfileresource.mkii}\donothing\donothing
+ \stopreadingfile
+ \letgvalue\pdffontfileresource\empty}%
+ \egroup}
+
+\def\doincludepdffontresource
+ {\ifcsname\s!ucmap\fontfile\endcsname\else
+ \dodoincludepdffontresource
+ \fi}
+
+\def\dodoincludepdffontresource
+ {% does this font has an encoding specified vector
+ \doifsomething\currentencoding % no \ifx
+ {% is there a pdf font encoding resource file defined
+ \ifcsname\pdffontresource\endcsname
+ % (fake) object defined
+ \else\ifcsname\pdffontfileresource\endcsname
+ % is there a resource already included
+ \doifsomething\pdffontfileresource
+ {\pdfobj reserveobjnum {}%
+ \setxvalue\pdffontresource{\the\pdflastobj}%
+ \flushatshipout{\dododoincludepdffontresource{\currentencoding}}}%
+% \doglobal\appendetoks
+% \noexpand\dododoincludepdffontresource{\currentencoding}%
+% \to \everybeforeshipout}% prevent multiple loading
+ \fi\fi
+ \ifcsname\pdffontresource\endcsname
+ \expanded{\pdffontattr\font{/ToUnicode \csname\pdffontresource\endcsname\space0 R}}%
+ % do it only once for each font
+ \letgvalue{\s!ucmap\fontfile}\empty
+ \fi}}
+
+%D For the moment, we keep this definition here, if only
+%D because \type {\usepdffontencoding} is not defined in the
+%D core. In the end, this will go to \type {enco-*.tex}.
+%D
+%D Test:
+%D
+%D \starttyping
+%D \useencoding[pfr] \usetypescript[palatino][ec] \setupbodyfont[palatino]
+%D
+%D \starttext
+%D fi ff ffi
+%D \stoptext
+%D \stoptyping
+
+\startencoding [il2] \usepdffontresource il2 \stopencoding
+\startencoding [ec] \usepdffontresource ec \stopencoding
+
+\protect \endinput
diff --git a/tex/context/base/enco-pol.mkii b/tex/context/base/enco-pol.mkii
new file mode 100644
index 000000000..a012f0370
--- /dev/null
+++ b/tex/context/base/enco-pol.mkii
@@ -0,0 +1,276 @@
+%D \module
+%D [ file=enco-pol,
+%D version=2000.05.07, % 1999.28.8,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Polish Mixed Encoding,
+%D author={Taco Hoekwater \& Hans Hagen},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% This encoding will go but the regime will remain.
+
+%D Polish native encoding; normally polish users will use
+%D translate=cp1250pl in combination with ec encoding.
+
+\startmapping[pl0]
+
+\resetcaserange 128 to 255
+
+\definecaseswap 161 129 % a ogonek
+\definecaseswap 162 130 % c acute
+\definecaseswap 166 134 % e ogonek
+\definecaseswap 170 138 % l crossed
+\definecaseswap 171 139 % n acute
+\definecaseswap 177 145 % s acute
+\definecaseswap 185 153 % z acute
+\definecaseswap 187 155 % z dotaccent
+\definecaseswap 243 211 % o acute
+
+% \definecasemap 161 161 129 % a ogonek
+% \definecasemap 162 162 130 % c acute
+% \definecasemap 166 166 134 % e ogonek
+% \definecasemap 170 170 138 % l crossed
+% \definecasemap 171 171 139 % n acute
+% \definecasemap 177 177 145 % s acute
+% \definecasemap 185 185 153 % z acute
+% \definecasemap 187 187 155 % z dotaccent
+% \definecasemap 243 243 211 % o acute
+
+% \definecasemap 129 161 129 % A ogonek
+% \definecasemap 130 162 130 % C acute
+% \definecasemap 134 166 134 % E ogonek
+% \definecasemap 138 170 138 % L crossed
+% \definecasemap 139 171 139 % N acute
+% \definecasemap 145 177 145 % S acute
+% \definecasemap 153 185 153 % Z acute
+% \definecasemap 155 187 155 % Z dotaccent
+% \definecasemap 211 243 211 % O acute
+
+\stopmapping
+
+\startmapping[pl0]
+
+\definespacemap 129 999 % A ogonek
+\definespacemap 130 999 % C acute
+\definespacemap 134 999 % E ogonek
+\definespacemap 138 999 % L crossed
+\definespacemap 139 999 % N acute
+\definespacemap 211 999 % O acute
+\definespacemap 145 999 % S acute
+\definespacemap 153 999 % Z acute
+\definespacemap 155 999 % Z dot
+
+\stopmapping
+
+\startencoding[pl0][pl0]
+
+\definecharacter Aogonek 129
+\definecharacter Cacute 130
+\definecharacter Eogonek 134
+\definecharacter Lstroke 138
+\definecharacter Nacute 139
+\definecharacter Sacute 145
+\definecharacter Zacute 153
+\definecharacter Zdotaccent 155
+\definecharacter aogonek 161
+\definecharacter cacute 162
+\definecharacter eogonek 166
+\definecharacter lstroke 170
+\definecharacter nacute 171
+\definecharacter sacute 177
+\definecharacter zacute 185
+\definecharacter zdotaccent 187
+\definecharacter Oacute 211
+\definecharacter oacute 243
+
+\stopencoding
+
+\startencoding[pl0][pl0]
+
+\definecharacter leftguillemot 174
+\definecharacter rightguillemot 175
+\definecharacter guilsingleleft 174
+\definecharacter guilsingleright 175
+
+\stopencoding
+
+% obsolete
+%
+% \startencoding[pl0]
+%
+% \definesortkey {161} {a}{a}{\k a} \definesortkey {129} {a}{a}{\k a}
+% \definesortkey {162} {c}{a}{\'c} \definesortkey {130} {c}{a}{\'c}
+% \definesortkey {166} {e}{a}{\k e} \definesortkey {134} {e}{a}{\k e}
+% \definesortkey {170} {l}{a}{\l } \definesortkey {138} {l}{a}{\l }
+% \definesortkey {171} {n}{a}{\'n} \definesortkey {139} {n}{a}{\'n}
+% \definesortkey {177} {s}{a}{\'s} \definesortkey {145} {s}{a}{\'s}
+% \definesortkey {185} {z}{a}{\'z} \definesortkey {153} {z}{a}{\'z}
+% \definesortkey {187} {z}{b}{\.z} \definesortkey {155} {z}{b}{\.z}
+% \definesortkey {243} {o}{a}{\'o} \definesortkey {211} {o}{a}{\'o}
+%
+% \definesortkey {\'c} {c}{a}{\'c} \definesortkey {\'C} {c}{a}{\'c}
+% \definesortkey {\'n} {n}{a}{\'n} \definesortkey {\'N} {n}{a}{\'n}
+% \definesortkey {\'o} {o}{a}{\'o} \definesortkey {\'O} {o}{a}{\'o}
+% \definesortkey {\'s} {s}{a}{\'s} \definesortkey {\'S} {s}{a}{\'s}
+% \definesortkey {\'z} {z}{a}{\'z} \definesortkey {\'Z} {z}{a}{\'z}
+% \definesortkey {\.z} {z}{b}{\.z} \definesortkey {\.Z} {z}{b}{\.z}
+% \definesortkey {\k a}{a}{a}{\k a} \definesortkey {\k A}{a}{a}{\k a}
+% \definesortkey {\k e}{e}{a}{\k e} \definesortkey {\k E}{e}{a}{\k e}
+% \definesortkey {\l } {l}{a}{\l} \definesortkey {\L } {l}{a}{\l}
+%
+% \stopencoding
+
+%D Polish CP-1250 encoding.
+
+% \startmapping[pl1]
+%
+%
+% \resetcaserange 128 to 255
+%
+% \definecasemap 185 185 165 % a ogonek
+% \definecasemap 230 230 198 % c acute
+% \definecasemap 234 234 202 % e ogonek
+% \definecasemap 179 179 163 % l crossed
+% \definecasemap 241 241 209 % n acute
+% \definecasemap 243 243 211 % o acute
+% \definecasemap 156 156 140 % s acute
+% \definecasemap 159 159 143 % z acute
+% \definecasemap 191 191 175 % z dot
+%
+% \definecasemap 165 165 185 % A ogonek
+% \definecasemap 198 198 230 % C acute
+% \definecasemap 202 202 234 % E ogonek
+% \definecasemap 163 163 179 % L crossed
+% \definecasemap 209 209 241 % N acute
+% \definecasemap 211 211 243 % O acute
+% \definecasemap 140 140 156 % S acute
+% \definecasemap 143 143 159 % Z acute
+% \definecasemap 175 175 191 % Z dot
+%
+% \stopmapping
+%
+% \startmapping[pl1]
+%
+% \definespacemap 165 999 % A ogonek
+% \definespacemap 198 999 % C acute
+% \definespacemap 202 999 % E ogonek
+% \definespacemap 163 999 % L crossed
+% \definespacemap 209 999 % N acute
+% \definespacemap 211 999 % O acute
+% \definespacemap 140 999 % S acute
+% \definespacemap 143 999 % Z acute
+% \definespacemap 175 999 % Z dot
+%
+% \stopmapping
+%
+% \startencoding[pl1]
+%
+% \definecharacter Sacute 140
+% \definecharacter Zacute 143
+% \definecharacter sacute 156
+% \definecharacter zacute 159
+% \definecharacter Lstroke 163
+% \definecharacter Aogonek 165
+% \definecharacter Zdotaccent 175
+% \definecharacter lstroke 179
+% \definecharacter aogonek 185
+% \definecharacter zdotaccent 191
+% \definecharacter Cacute 198
+% \definecharacter Eogonek 202
+% \definecharacter Nacute 209
+% \definecharacter Oacute 211
+% \definecharacter cacute 230
+% \definecharacter eogonek 234
+% \definecharacter nacute 241
+% \definecharacter oacute 243
+%
+% \stopencoding
+%
+% \startencoding[pl1]
+%
+% \definecharacter leftguillemot 174
+% \definecharacter rightguillemot 175
+% \definecharacter guilsingleleft 174
+% \definecharacter guilsingleright 175
+%
+% \stopencoding
+
+%D Polish ISO-8859-2 encoding.
+
+% \startmapping[pl2]
+%
+% \resetcaserange 128 to 255
+%
+% \definecasemap 177 177 161 % a ogonek
+% \definecasemap 230 230 198 % c acute
+% \definecasemap 234 234 202 % e ogonek
+% \definecasemap 179 179 163 % l crossed
+% \definecasemap 241 241 209 % n acute
+% \definecasemap 243 243 211 % o acute
+% \definecasemap 182 182 166 % s acute
+% \definecasemap 188 188 172 % z acute
+% \definecasemap 191 191 175 % z dotaccent
+%
+% \definecasemap 161 161 177 % A ogonek
+% \definecasemap 198 198 230 % C acute
+% \definecasemap 202 202 234 % E ogonek
+% \definecasemap 163 163 179 % L crossed
+% \definecasemap 209 209 241 % N acute
+% \definecasemap 211 211 243 % O acute
+% \definecasemap 166 166 182 % S acute
+% \definecasemap 172 172 188 % Z acute
+% \definecasemap 175 175 191 % Z dotaccent
+%
+% \stopmapping
+%
+% \startmapping[pl2]
+%
+% \definespacemap 161 999 % A ogonek
+% \definespacemap 198 999 % C acute
+% \definespacemap 202 999 % E ogonek
+% \definespacemap 163 999 % L crossed
+% \definespacemap 209 999 % N acute
+% \definespacemap 211 999 % O acute
+% \definespacemap 166 999 % S acute
+% \definespacemap 172 999 % Z acute
+% \definespacemap 175 999 % Z dot
+%
+% \stopmapping
+%
+% \startencoding[pl2]
+%
+% \definecharacter Aogonek 161
+% \definecharacter Lstroke 163
+% \definecharacter Sacute 166
+% \definecharacter Zacute 172
+% \definecharacter Zdotaccent 175
+% \definecharacter aogonek 177
+% \definecharacter lstroke 179
+% \definecharacter sacute 182
+% \definecharacter zacute 188
+% \definecharacter zdotaccent 191
+% \definecharacter Cacute 198
+% \definecharacter Eogonek 202
+% \definecharacter Nacute 209
+% \definecharacter Oacute 211
+% \definecharacter cacute 230
+% \definecharacter eogonek 234
+% \definecharacter nacute 241
+% \definecharacter oacute 243
+%
+% \stopencoding
+%
+% \startencoding[pl2]
+%
+% \definecharacter leftguillemot 174
+% \definecharacter rightguillemot 175
+% \definecharacter guilsingleleft 174
+% \definecharacter guilsingleright 175
+%
+% \stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-qx.mkii b/tex/context/base/enco-qx.mkii
new file mode 100644
index 000000000..407d60bd7
--- /dev/null
+++ b/tex/context/base/enco-qx.mkii
@@ -0,0 +1,266 @@
+%D \module
+%D [ file=enco-qx,
+%D version=2004.04.03,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Polish QX Encoding,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% to be done
+
+% 35 numbersign
+% 95 dotaccent
+% 132 greaterequal
+% 133 approxequal
+% 137 lessequal
+% 142 ell
+% 156 IJ
+% 173 infinity
+% 182 threequartersemdash
+% 188 ij
+% 247 anglearc
+% 248 diameter
+
+\startmapping[qx] % to be done
+
+\resetcaserange 128 to 128
+\resetcaserange 131 to 133
+\resetcaserange 136 to 137
+\resetcaserange 140 to 144
+\resetcaserange 148 to 148
+\resetcaserange 150 to 150
+\resetcaserange 157 to 160
+\resetcaserange 163 to 165
+\resetcaserange 168 to 169
+\resetcaserange 172 to 176
+\resetcaserange 180 to 180
+\resetcaserange 182 to 182
+\resetcaserange 189 to 191
+\resetcaserange 198 to 198
+\resetcaserange 215 to 216
+\resetcaserange 223 to 223
+\resetcaserange 230 to 230
+\resetcaserange 247 to 248
+\resetcaserange 255 to 255
+
+\definecaseswap 161 129
+\definecaseswap 162 130
+
+\definecaseswap 166 134
+\definecaseswap 167 135
+
+\definecaseswap 170 138
+\definecaseswap 171 139
+
+\definecaseswap 177 145
+\definecaseswap 178 146
+\definecaseswap 179 147
+
+\definecaseswap 181 149
+
+\definecasemaps 151 to 156 lc +32 uc 0
+\definecasemaps 183 to 188 lc 0 uc -32
+
+\definecasemaps 192 to 197 lc +32 uc 0
+\definecasemaps 224 to 229 lc 0 uc -32
+
+\definecasemaps 199 to 214 lc +32 uc 0
+\definecasemaps 231 to 246 lc 0 uc -32
+
+\definecasemaps 217 to 222 lc +32 uc 0
+\definecasemaps 249 to 254 lc 0 uc -32
+
+\stopmapping
+
+\startencoding[qx]
+
+\definecharacter textacute 19
+\definecharacter textbreve 21
+\definecharacter textcaron 20
+\definecharacter textcedilla 24
+\definecharacter textcircumflex 94
+\definecharacter textdiaeresis 127
+\definecharacter textdotaccent 94
+\definecharacter textgrave 18
+\definecharacter texthungarumlaut 125
+\definecharacter textmacron 22
+\definecharacter textogonek 150
+\definecharacter textring 23
+\definecharacter texttilde 126
+
+\definecharacter dotlessi 16
+\definecharacter dotlessj 17
+
+\definecharacter endash 123
+\definecharacter emdash 124
+
+\definecharacter aeligature 26
+\definecharacter AEligature 29
+\definecharacter oeligature 27
+\definecharacter OEligature 30
+
+\definecharacter ssharp 25
+%definecharacter Ssharp 25
+
+\definecharacter thorn 254
+\definecharacter Thorn 222
+
+\definecharacter Dstroke 208 % also Eth, mapped into enco-def
+\definecharacter eth 240
+
+\definecharacter exclamdown 60
+\definecharacter questiondown 62
+
+\definecharacter sectionmark 159
+
+\definecharacter percent 37
+\definecharacter perthousand 216
+
+\definecharacter textasciicircum 141
+\definecharacter textasciitilde 140
+\definecharacter textbackslash 198
+\definecharacter textbraceleft 157
+\definecharacter textbraceright 158
+\definecharacter textunderscore 230
+
+\definecharacter textcurrency 215
+\definecharacter textdollar 36
+\definecharacter texteuro 128
+
+\definecharacter periodcentered 189
+\definecharacter textdag 143
+\definecharacter textddag 144
+\definecharacter textdegree 148
+\definecharacter textbullet 180
+
+\definecharacter paragraphmark 176
+
+\definecharacter copyright 164
+\definecharacter registered 163
+
+\definecharacter textbrokenbar 223
+\definecharacter textellipsis 8
+\definecharacter textslash 47
+\definecharacter textpm 172
+\definecharacter textdiv 165
+\definecharacter textminus 168
+\definecharacter textmultiply 169
+\definecharacter textmu 7
+
+\definecharacter quotedbl 190
+\definecharacter quotedblbase 255
+\definecharacter quotedblleft 92
+\definecharacter quotedblright 34
+
+\definecharacter quotesingle 191
+
+\definecharacter quoteleft 96
+\definecharacter quoteright 39
+
+\definecharacter leftguillemot 174
+\definecharacter rightguillemot 175
+
+\definecharacter aacute 225
+\definecharacter Aacute 193
+\definecharacter cacute 162
+\definecharacter Cacute 130
+\definecharacter eacute 233
+\definecharacter Eacute 201
+\definecharacter iacute 237
+\definecharacter Iacute 205
+\definecharacter Nacute 139
+\definecharacter Oacute 211
+\definecharacter nacute 171
+\definecharacter oacute 243
+\definecharacter sacute 177
+\definecharacter Sacute 145
+\definecharacter uacute 250
+\definecharacter Uacute 218
+\definecharacter yacute 253
+\definecharacter Yacute 221
+\definecharacter zacute 185
+\definecharacter Zacute 153
+
+\definecharacter scaron 178
+\definecharacter Scaron 146
+\definecharacter zcaron 186
+\definecharacter Zcaron 154
+
+\definecharacter ccedilla 231
+\definecharacter Ccedilla 199
+
+\definecharacter acircumflex 226
+\definecharacter Acircumflex 194
+\definecharacter ecircumflex 234
+\definecharacter Ecircumflex 202
+\definecharacter icircumflex 238
+\definecharacter Icircumflex 206
+\definecharacter ocircumflex 244
+\definecharacter Ocircumflex 212
+\definecharacter ucircumflex 251
+\definecharacter Ucircumflex 219
+
+\definecharacter adiaeresis 228
+\definecharacter Adiaeresis 196
+\definecharacter ediaeresis 235
+\definecharacter Ediaeresis 203
+\definecharacter idiaeresis 239
+\definecharacter Idiaeresis 207
+\definecharacter odiaeresis 246
+\definecharacter Odiaeresis 214
+\definecharacter udiaeresis 252
+\definecharacter Udiaeresis 220
+\definecharacter ydiaeresis 184
+\definecharacter Ydiaeresis 152
+
+\definecharacter zdotaccent 187
+\definecharacter Zdotaccent 155
+
+\definecharacter agrave 224
+\definecharacter Agrave 192
+\definecharacter egrave 232
+\definecharacter Egrave 200
+\definecharacter igrave 236
+\definecharacter Igrave 204
+\definecharacter ograve 242
+\definecharacter Ograve 210
+\definecharacter ugrave 249
+\definecharacter Ugrave 217
+
+\definecharacter aogonek 161
+\definecharacter Aogonek 129
+\definecharacter eogonek 166
+\definecharacter Eogonek 134
+\definecharacter iogonek 167
+\definecharacter Iogonek 135
+\definecharacter uogonek 183
+\definecharacter Uogonek 151
+
+\definecharacter aring 229
+\definecharacter Aring 197
+
+\definecharacter lstroke 170
+\definecharacter Lstroke 138
+\definecharacter ostroke 28
+\definecharacter Ostroke 31
+
+\definecharacter atilde 227
+\definecharacter Atilde 195
+\definecharacter ntilde 241
+\definecharacter Ntilde 209
+\definecharacter otilde 245
+\definecharacter Otilde 213
+
+\definecharacter scommaaccent 179
+\definecharacter Scommaaccent 147
+\definecharacter tcommaaccent 181
+\definecharacter Tcommaaccent 149
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-raw.mkii b/tex/context/base/enco-raw.mkii
new file mode 100644
index 000000000..e3a46e3d7
--- /dev/null
+++ b/tex/context/base/enco-raw.mkii
@@ -0,0 +1,119 @@
+% default instelbaar maken: \enableencoding[main][fallback]
+
+\startencoding[raw]
+
+\definecharacter Acircumflex {A} \definecharacter acircumflex {a}
+\definecharacter Ccircumflex {C} \definecharacter ccircumflex {c}
+\definecharacter Ecircumflex {E} \definecharacter ecircumflex {e}
+\definecharacter Gcircumflex {G} \definecharacter gcircumflex {g}
+\definecharacter Hcircumflex {H} \definecharacter hcircumflex {h}
+\definecharacter Icircumflex {I} \definecharacter icircumflex {i}
+\definecharacter Jcircumflex {J} \definecharacter jcircumflex {j}
+\definecharacter Ocircumflex {O} \definecharacter ocircumflex {o}
+\definecharacter Scircumflex {S} \definecharacter scircumflex {s}
+\definecharacter Ucircumflex {U} \definecharacter ucircumflex {u}
+\definecharacter Wcircumflex {W} \definecharacter wcircumflex {w}
+\definecharacter Ycircumflex {Y} \definecharacter ycircumflex {y}
+
+\definecharacter Agrave {A} \definecharacter agrave {a}
+\definecharacter Egrave {E} \definecharacter egrave {e}
+\definecharacter Igrave {I} \definecharacter igrave {i}
+\definecharacter Ograve {O} \definecharacter ograve {o}
+\definecharacter Ugrave {U} \definecharacter ugrave {u}
+\definecharacter Ygrave {Y} \definecharacter ygrave {y}
+
+\definecharacter Atilde {A} \definecharacter atilde {a}
+\definecharacter Itilde {I} \definecharacter itilde {i}
+\definecharacter Otilde {O} \definecharacter otilde {o}
+\definecharacter Utilde {U} \definecharacter utilde {u}
+\definecharacter Utilde {N} \definecharacter utilde {n}
+
+\definecharacter Adiaeresis {A} \definecharacter adiaeresis {a}
+\definecharacter Ediaeresis {E} \definecharacter ediaeresis {e}
+\definecharacter Idiaeresis {I} \definecharacter idiaeresis {i}
+\definecharacter Odiaeresis {O} \definecharacter odiaeresis {o}
+\definecharacter Udiaeresis {U} \definecharacter udiaeresis {u}
+\definecharacter Ydiaeresis {Y} \definecharacter ydiaeresis {y}
+
+\definecharacter Aacute {A} \definecharacter aacute {a}
+\definecharacter Cacute {C} \definecharacter cacute {c}
+\definecharacter Eacute {E} \definecharacter eacute {e}
+\definecharacter Iacute {I} \definecharacter iacute {i}
+\definecharacter Lacute {L} \definecharacter lacute {l}
+\definecharacter Nacute {N} \definecharacter nacute {n}
+\definecharacter Oacute {O} \definecharacter oacute {o}
+\definecharacter Racute {R} \definecharacter racute {r}
+\definecharacter Sacute {S} \definecharacter sacute {s}
+\definecharacter Uacute {U} \definecharacter uacute {u}
+\definecharacter Yacute {Y} \definecharacter yacute {y}
+\definecharacter Zacute {Z} \definecharacter zacute {z}
+
+\definecharacter Dstroke {D} \definecharacter dstroke {d}
+\definecharacter Hstroke {H} \definecharacter hstroke {h}
+\definecharacter Tstroke {T} \definecharacter tstroke {t}
+
+\definecharacter Cdotaccent {C} \definecharacter cdotaccent {c}
+\definecharacter Edotaccent {E} \definecharacter edotaccent {e}
+\definecharacter Gdotaccent {G} \definecharacter gdotaccent {g}
+\definecharacter Idotaccent {I} \definecharacter idotaccent {i}
+\definecharacter Zdotaccent {Z} \definecharacter zdotaccent {z}
+
+\definecharacter Amacron {A} \definecharacter amacron {a}
+\definecharacter Emacron {E} \definecharacter emacron {e}
+\definecharacter Imacron {I} \definecharacter imacron {i}
+\definecharacter Omacron {O} \definecharacter omacron {o}
+\definecharacter Umacron {U} \definecharacter umacron {u}
+
+\definecharacter Ccedilla {C} \definecharacter ccedilla {c}
+\definecharacter Kcedilla {K} \definecharacter kcedilla {k}
+\definecharacter Lcedilla {L} \definecharacter lcedilla {l}
+\definecharacter Ncedilla {N} \definecharacter ncedilla {n}
+\definecharacter Rcedilla {R} \definecharacter rcedilla {r}
+\definecharacter Scedilla {S} \definecharacter scedilla {s}
+\definecharacter Tcedilla {T} \definecharacter tcedilla {t}
+
+\definecharacter Ohungarumlaut {O} \definecharacter ohungarumlaut {o}
+\definecharacter Uhungarumlaut {U} \definecharacter uhungarumlaut {u}
+
+\definecharacter Aogonek {A} \definecharacter aogonek {a}
+\definecharacter Eogonek {E} \definecharacter eogonek {e}
+\definecharacter Iogonek {I} \definecharacter iogonek {i}
+\definecharacter Uogonek {U} \definecharacter uogonek {u}
+
+\definecharacter Aring {A} \definecharacter aring {a}
+\definecharacter Uring {U} \definecharacter uring {u}
+
+\definecharacter Abreve {A} \definecharacter abreve {a}
+\definecharacter Ebreve {E} \definecharacter ebreve {e}
+\definecharacter Gbreve {G} \definecharacter gbreve {g}
+\definecharacter Ibreve {I} \definecharacter ibreve {i}
+\definecharacter Obreve {O} \definecharacter obreve {o}
+\definecharacter Ubreve {U} \definecharacter ubreve {u}
+
+\definecharacter Ccaron {C} \definecharacter ccaron {c}
+\definecharacter Dcaron {D} \definecharacter dcaron {d}
+\definecharacter Ecaron {E} \definecharacter ecaron {e}
+\definecharacter Lcaron {L} \definecharacter lcaron {l}
+\definecharacter Ncaron {N} \definecharacter ncaron {n}
+\definecharacter Rcaron {R} \definecharacter rcaron {r}
+\definecharacter Scaron {S} \definecharacter scaron {s}
+\definecharacter Tcaron {T} \definecharacter tcaron {t}
+\definecharacter Zcaron {Z} \definecharacter zcaron {z}
+
+\definecharacter dotlessI {I} \definecharacter dotlessi {i}
+\definecharacter dotlessJ {J} \definecharacter dotlessj {j}
+
+\definecharacter AEligature {AE} \definecharacter aeligature {ae}
+\definecharacter Lstroke {L} \definecharacter lstroke {l}
+\definecharacter Ostroke {O} \definecharacter ostroke {o}
+\definecharacter OEligature {OE} \definecharacter oeligature {oe}
+\definecharacter Ssharp {SS} \definecharacter ssharp {ss}
+\definecharacter IJligature {IJ} \definecharacter ijligature {ij}
+
+\definecharacter Aumlaut {A} \definecharacter aumlaut {a}
+\definecharacter Eumlaut {E} \definecharacter eumlaut {e}
+\definecharacter Iumlaut {I} \definecharacter iumlaut {i}
+\definecharacter Oumlaut {O} \definecharacter oumlaut {o}
+\definecharacter Uumlaut {U} \definecharacter uumlaut {u}
+
+\stopencoding
diff --git a/tex/context/base/enco-run.mkii b/tex/context/base/enco-run.mkii
new file mode 100644
index 000000000..50fb52e15
--- /dev/null
+++ b/tex/context/base/enco-run.mkii
@@ -0,0 +1,149 @@
+%D \module
+%D [ file=enco-run,
+%D version=2000.27.12, % moved to runtime module
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen \& Ton Otten]
+%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
+
+\gdef\visualizecharacters% {}'s needed
+ {\def\uchar##1##2{\hbox to 2.5em
+ {\ifcase##1\relax\red\or\blue\else\green\fi##1\hss##2}}%
+ \let\normalbuildtextaccent\buildtextaccent
+ \let\normalbottomaccent \bottomaccent
+ %\def\char{\green\normalchar}%
+ \def\char % can be used in \oalign
+ {\bgroup\def\char{\green\normalchar\scratchcounter\egroup}%
+ \afterassignment\char\scratchcounter}%
+ \def\buildtextaccent{\let\green\empty\blue\normalbuildtextaccent}%
+ \def\bottomaccent{\let\green\empty\red\normalbottomaccent}}
+
+\unexpanded\gdef\visualizecharacterslegend
+ {\hbox
+ {\edef\banner{\currentencoding\space\fontname\font}%
+ \tttf\banner:\space
+ {\blue composed}\space{\red bottom}\space{\green char}\space raw}}
+
+\gdef\showaccents
+ {\bgroup
+ \savefont
+ \setuptextrules[\c!bodyfont=,\c!style=]
+ \starttextrule{\visualizecharacterslegend}
+ \whitespace
+ \restorefont\setupinterlinespace
+ \visualizecharacters
+ \def\do##1%
+ {{\def\dodo####1%
+ {\hss\hbox to 1em{\hss\expanded{##1####1\recurselevel}\hss}}%
+ \hbox to \hsize
+ {\strut
+ \localcolortrue
+ \hbox to 2em{\tttf\string##1\hss}%
+ \dorecurse{26}{\dodo\character}}%
+ \hbox to \hsize
+ {\strut
+ \localcolortrue
+ \hskip2em
+ \dorecurse{26}{\dodo\Character}}}%
+ \par}
+ \do\'\do\`\do\^\do\~\do\"
+ \do\H\do\r\do\v\do\u\do\=
+ \do\.\do\b\do\d\do\k\do\c
+ \stoptextrule
+ \egroup}
+
+\gdef\showcharacters
+ {\bgroup
+ \savefont
+ \setuptextrules[\c!bodyfont=,\c!style=]
+ \starttextrule{\visualizecharacterslegend}
+ \whitespace
+ \dontcomplain
+ \forgetall
+ \def\startencoding[##1]{}
+ \def\stopencoding{\endinput}
+ \dimen0=\zeropoint
+ \dimen2=\zeropoint
+ \def\definecharacter ##1 ##2 %
+ {\setbox0=\hbox spread 1em{\getvalue{##1}}%
+ \ifdim\wd0>\dimen0 \dimen0=\wd0 \fi
+ \setbox2=\hbox spread 1em{\box0 \tttf##1}
+ \ifdim\wd2>\dimen2 \dimen2=\wd2 \fi}%
+ \readsysfile{\f!encodingprefix def}{}{}
+ \edef\encwidth{\the\dimen0}
+ \dimen0=\hsize
+ \advance\dimen0 2em
+ \advance\dimen2 2em
+ \divide \dimen0 by \dimen2 \advance\dimen0 1sp
+ \edef\enccols{\number\dimen0}
+ \visualizecharacters
+ \startcolumns[\c!n=\enccols,\c!distance=2em]
+ \restorefont\setupinterlinespace
+ \def\definecharacter ##1 ##2 %
+ {\setbox0=\hbox to \hsize{\localcolortrue\hbox to \encwidth{\getvalue{##1}\hss}\tttf##1}%
+ \ht0\strutheight \dp0\strutdepth \box0 \allowbreak}
+ \readsysfile{\f!encodingprefix def}{}{}
+ \stopcolumns
+ \stoptextrule
+ \egroup}
+
+% \hbox
+% {\font\test=uplr8t \test \ruledhbox{t}
+% \font\test=uplr8r \test \ruledhbox{t}}
+
+\ifnum\texengine=\pdftexengine
+
+ \gdef\showhyphenations#1%
+ {\starttabulate[|le|l|]
+ \NC language \NC \currentlanguage\ (internal code:\the\normallanguage) \NC \NR
+ \NC font \NC \fontname\font \NC \NR
+ \NC encoding \NC \ifx\@@fontencoding\empty not set\else\@@fontencoding\fi \NC \NR
+ \NC mapping \NC \ifx\@@fontmapping \empty not set\else\@@fontmapping \fi \NC \NR
+ \NC handling \NC \ifx\@@fonthandling\empty not set\else\@@fonthandling\fi \NC \NR
+ \NC sample \NC \hyphenatedword{#1} \NC \NR
+ \stoptabulate}
+
+ \gdef\showmapping
+ {\dostepwiserecurse{128}{255}{1}
+ {\hbox\bgroup
+ \hbox to 2em{\hss\recurselevel}%
+ \hbox to 2em{\hss\char\recurselevel\hss}%
+ \hbox to 3em{\hss\ifcase\lccode\recurselevel\else\the \lccode\recurselevel\fi}%
+ \hbox to 2em{\hss\ifcase\lccode\recurselevel\else\char\lccode\recurselevel\fi\hss}%
+ \hbox to 3em{\hss\ifcase\lccode\recurselevel\else\the \uccode\recurselevel\fi}%
+ \hbox to 2em{\hss\ifcase\uccode\recurselevel\else\char\uccode\recurselevel\fi\hss}%
+ \egroup
+ \endgraf}}
+
+ \gdef\showcharacterbounds
+ {\bgroup
+ \localcolortrue
+ \dorecurse{255}
+ {\ifdim\fontcharwd\font\recurselevel>\zeropoint
+ \noindent\ruledhbox{\darkgray\char\recurselevel}\space
+ \fi}\unskip
+ \egroup}
+
+\else
+
+ \gdef\showhyphenations#1%
+ {\starttabulate[|le|l|]
+ \NC language \NC \currentlanguage\ (internal code:\the\normallanguage) \NC \NR
+ \NC font \NC \fontname\font \NC \NR
+ \NC sample \NC \hyphenatedword{#1} \NC \NR
+ \stoptabulate}
+
+ \globallet\showmapping\relax
+
+ \globallet\showcharacterbounds\relax
+
+\fi
+
+\protect \endinput
diff --git a/tex/context/base/enco-t5.mkii b/tex/context/base/enco-t5.mkii
new file mode 100644
index 000000000..251c68765
--- /dev/null
+++ b/tex/context/base/enco-t5.mkii
@@ -0,0 +1,244 @@
+%D \module
+%D [ file=enco-t5,
+%D version=2004.11.16,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=New Vietnamese Encoding,
+%D author=Hans Hagen \& Adam Lindsay,
+%D date=\currentdate,
+%D copyright=PRAGMA \& Adam Lindsay]
+%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 is derived from the enco-x5 encoding, but now
+%D approaches the world with named glyphs.
+
+\startencoding[t5]
+
+\definecasemaps 128 to 159 lc +32 uc 0
+
+\definecasemaps 160 to 191 lc 0 uc -32
+
+\definecasemaps 192 to 223 lc +32 uc 0
+
+\definecasemaps 224 to 225 lc 0 uc -32
+
+\definecasemap 26 26 27 \definecasemap 27 26 27
+\definecasemap 28 28 29 \definecasemap 29 28 29
+\definecasemap 30 30 31 \definecasemap 31 30 31
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter textbottomdot 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter texthookabove 12
+\definecharacter textogonek {}
+
+\definecharacter quotesinglebase 13
+\definecharacter guilsingleleft 14
+\definecharacter guilsingleright 15
+\definecharacter quotedblleft 16
+\definecharacter quotedblright 17
+\definecharacter quotedblbase 18
+\definecharacter leftguillemot 19
+\definecharacter rightguillemot 20
+\definecharacter endash 21
+\definecharacter emdash 22
+
+\definecharacter cwm 23
+\definecharacter zeroinferior 24
+\definecharacter Yhook 26
+\definecharacter yhook 27
+\definecharacter Ydotbelow 28
+\definecharacter ydotbelow 29
+\definecharacter Dstroke 30
+\definecharacter dstroke 31
+\definecharacter textvisiblespace 32
+
+\definecharacter dotlessi 25
+%definecharacter DJ 30
+%definecharacter dj 31
+\definecharacter Agrave 128
+\definecharacter Aacute 129
+\definecharacter Atilde 130
+\definecharacter Ahook 131
+\definecharacter Adotbelow 132
+\definecharacter Acircumflex 133
+\definecharacter Acircumflexgrave 134
+\definecharacter Acircumflexacute 135
+\definecharacter Acircumflextilde 136
+\definecharacter Acircumflexhook 137
+\definecharacter Acircumflexdotbelow 138
+\definecharacter Abreve 139
+\definecharacter Abrevegrave 140
+\definecharacter Abreveacute 141
+\definecharacter Abrevetilde 142
+\definecharacter Abrevehook 143
+\definecharacter Abrevedotbelow 144
+\definecharacter Egrave 145
+\definecharacter Eacute 146
+\definecharacter Etilde 147
+\definecharacter Ehook 148
+\definecharacter Edotbelow 149
+\definecharacter Ecircumflex 150
+\definecharacter Ecircumflexgrave 151
+\definecharacter Ecircumflexacute 152
+\definecharacter Ecircumflextilde 153
+\definecharacter Ecircumflexhook 154
+\definecharacter Ecircumflexdotbelow 155
+\definecharacter Igrave 156
+\definecharacter Iacute 157
+\definecharacter Itilde 158
+\definecharacter Ihook 159
+\definecharacter agrave 160
+\definecharacter aacute 161
+\definecharacter atilde 162
+\definecharacter ahook 163
+\definecharacter adotbelow 164
+\definecharacter acircumflex 165
+\definecharacter acircumflexgrave 166
+\definecharacter acircumflexacute 167
+\definecharacter acircumflextilde 168
+\definecharacter acircumflexhook 169
+\definecharacter acircumflexdotbelow 170
+\definecharacter abreve 171
+\definecharacter abrevegrave 172
+\definecharacter abreveacute 173
+\definecharacter abrevetilde 174
+\definecharacter abrevehook 175
+\definecharacter abrevedotbelow 176
+\definecharacter egrave 177
+\definecharacter eacute 178
+\definecharacter etilde 179
+\definecharacter ehook 180
+\definecharacter edotbelow 181
+\definecharacter ecircumflex 182
+\definecharacter ecircumflexgrave 183
+\definecharacter ecircumflexacute 184
+\definecharacter ecircumflextilde 185
+\definecharacter ecircumflexhook 186
+\definecharacter ecircumflexdotbelow 187
+\definecharacter igrave 188
+\definecharacter iacute 189
+\definecharacter itilde 190
+\definecharacter ihook 191
+\definecharacter Idotbelow 192
+\definecharacter Ograve 193
+\definecharacter Oacute 194
+\definecharacter Otilde 195
+\definecharacter Ohook 196
+\definecharacter Odotbelow 197
+\definecharacter Ocircumflex 198
+\definecharacter Ocircumflexgrave 199
+\definecharacter Ocircumflexacute 200
+\definecharacter Ocircumflextilde 201
+\definecharacter Ocircumflexhook 202
+\definecharacter Ocircumflexdotbelow 203
+\definecharacter Ohorn 204
+\definecharacter Ohorngrave 205
+\definecharacter Ohornacute 206
+\definecharacter Ohorntilde 207
+\definecharacter Ohornhook 208
+\definecharacter Ohorndotbelow 209
+\definecharacter Ugrave 210
+\definecharacter Uacute 211
+\definecharacter Utilde 212
+\definecharacter Uhook 213
+\definecharacter Udotbelow 214
+\definecharacter Uhorn 215
+\definecharacter Uhorngrave 216
+\definecharacter Uhornacute 217
+\definecharacter Uhorntilde 218
+\definecharacter Uhornhook 219
+\definecharacter Uhorndotbelow 220
+\definecharacter Ytilde 223
+\definecharacter idotbelow 224
+\definecharacter ograve 225
+\definecharacter oacute 226
+\definecharacter otilde 227
+\definecharacter ohook 228
+\definecharacter odotbelow 229
+\definecharacter ocircumflex 230
+\definecharacter ocircumflexgrave 231
+\definecharacter ocircumflexacute 232
+\definecharacter ocircumflextilde 233
+\definecharacter ocircumflexhook 234
+\definecharacter ocircumflexdotbelow 235
+\definecharacter ohorn 236
+\definecharacter ohorngrave 237
+\definecharacter ohornacute 238
+\definecharacter ohorntilde 239
+\definecharacter ohornhook 240
+\definecharacter ohorndotbelow 241
+\definecharacter ugrave 242
+\definecharacter uacute 243
+\definecharacter utilde 244
+\definecharacter uhook 245
+\definecharacter udotbelow 246
+\definecharacter uhorn 247
+\definecharacter uhorngrave 248
+\definecharacter uhornacute 249
+\definecharacter uhorntilde 250
+\definecharacter uhornhook 251
+\definecharacter uhorndotbelow 252
+\definecharacter ygrave 253
+\definecharacter yacute 254
+\definecharacter ytilde 255
+
+\stopencoding
+
+\endinput
+
+% \startencoding [x5]
+%
+% \definecharacter aa {\xfiveencodedaa}
+% \definecharacter AA {\xfiveencodedAA}
+%
+% \stopencoding
+%
+% \def\xfiveencodedaa%
+% {\accent23a}
+%
+% \def\xfiveencodedAA%
+% {\leavevmode
+% \setbox\zerocount\hbox{h}%
+% \dimen@\ht\zerocount
+% \advance\dimen@ -1ex
+% \rlap{\raise.67\dimen@\hbox{\char23}}A}
+
+% \quotesinglbase 13
+% \guilsinglleft 14
+% \guilsinglright 15
+% \textquotedblleft 16
+% \textquotedblright 17
+% \quotedblbase 18
+% \guillemotleft 19
+% \guillemotright 20
+% \textendash 21
+% \textemdash 22
+% \textcompwordmark 23
+% \textperthousand \% \char 24
+% \textpertenthousand \%\char 24\char 24
+% \textvisiblespace 32
+% \textquotedbl `\"
+% \textdollar `\$
+% \textquoteright `\'
+% \textless `\<
+% \textgreater `\>
+% \textbackslash `\
+% \textasciicircum `\^
+% \textunderscore 95
+% \textquoteleft `\`
+% \textbraceleft `\{
+% \textbar `\|
+% \textbraceright `\}
+% \textasciitilde `\~
diff --git a/tex/context/base/enco-tbo.mkii b/tex/context/base/enco-tbo.mkii
new file mode 100644
index 000000000..475be4602
--- /dev/null
+++ b/tex/context/base/enco-tbo.mkii
@@ -0,0 +1,222 @@
+%D \module
+%D [ file=enco-tbo,
+%D version=2000.05.07, % 2001.8.4,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=TeXBaseOne Encoding,
+%D author={Patrick Gundlach, Hans Hagen},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startmapping[8r]
+
+\resetcaserange 128 to 255
+
+\definecasemap 228 228 196 \definecasemap 196 228 196
+\definecasemap 235 235 203 \definecasemap 203 235 203
+\definecasemap 239 239 207 \definecasemap 207 239 207
+\definecasemap 246 246 214 \definecasemap 214 246 214
+\definecasemap 252 252 220 \definecasemap 220 252 220
+\definecasemap 255 255 159 \definecasemap 159 255 159
+
+\definecasemap 225 225 193 \definecasemap 193 225 193
+\definecasemap 233 233 201 \definecasemap 201 233 201
+\definecasemap 237 237 205 \definecasemap 205 237 205
+\definecasemap 243 243 211 \definecasemap 211 243 211
+\definecasemap 250 250 218 \definecasemap 218 250 218
+\definecasemap 253 253 221 \definecasemap 221 253 221
+
+\definecasemap 224 224 192 \definecasemap 192 224 192
+\definecasemap 232 232 200 \definecasemap 200 232 200
+\definecasemap 236 236 204 \definecasemap 204 236 204
+\definecasemap 242 242 210 \definecasemap 210 242 210
+\definecasemap 249 249 217 \definecasemap 217 249 217
+
+\definecasemap 226 226 194 \definecasemap 194 226 194
+\definecasemap 234 234 202 \definecasemap 202 234 202
+\definecasemap 238 238 206 \definecasemap 206 238 206
+\definecasemap 244 244 212 \definecasemap 212 244 212
+\definecasemap 251 251 219 \definecasemap 219 251 219
+
+\definecasemap 227 227 195 \definecasemap 195 227 195
+\definecasemap 241 241 209 \definecasemap 209 241 209
+\definecasemap 245 245 213 \definecasemap 213 245 213
+
+\stopmapping
+
+\startencoding[8r]
+
+\definecharacter textacute 180
+\definecharacter textbreve 11
+\definecharacter textcaron 16
+\definecharacter textcedilla 184
+\definecharacter textcircumflex 136
+\definecharacter textdiaeresis 168
+\definecharacter textdotaccent 1
+\definecharacter textgrave 30
+\definecharacter texthungarumlaut 5
+\definecharacter textmacron 175
+\definecharacter textogonek 8
+\definecharacter textring 9
+\definecharacter texttilde 152
+
+\definecharacter dotlessi 17
+%definecharacter dotlessj 18
+
+\definecharacter endash 150
+\definecharacter emdash 151
+
+\definecharacter oeligature 156
+\definecharacter OEligature 140
+\definecharacter aeligature 230
+\definecharacter AEligature 198
+
+\definecharacter ssharp 223
+
+\definecharacter thorn 254
+\definecharacter Thorn 222
+
+\definecharacter exclamdown 161
+\definecharacter questiondown 191
+
+\definecharacter copyright 169
+\definecharacter registered 174
+\definecharacter trademark 153
+
+\definecharacter sectionmark 167
+\definecharacter paragraphmark 182
+
+\definecharacter onequarter 188
+\definecharacter onehalf 189
+\definecharacter threequarter 190
+\definecharacter onesuperior 185
+\definecharacter twosuperior 178
+\definecharacter threesuperior 179
+
+\definecharacter textcent 162
+\definecharacter textcurrency 164
+\definecharacter texteuro 128
+\definecharacter textflorin 131
+\definecharacter textsterling 163
+\definecharacter textyen 165
+
+\definecharacter percent 37
+\definecharacter perthousand 137
+
+\definecharacter periodcentered 183
+\definecharacter softhyphen 173
+
+\definecharacter textasciicircum 94
+\definecharacter textasciitilde 126
+\definecharacter textslash 47
+\definecharacter textbackslash 92
+\definecharacter textbraceleft 123
+\definecharacter textbraceright 125
+\definecharacter textunderscore 95
+
+\definecharacter textbrokenbar 166
+\definecharacter textbullet 149
+\definecharacter textdag 134
+\definecharacter textddag 135
+\definecharacter textdegree 176
+\definecharacter textdiv 247
+\definecharacter textellipsis 133
+\definecharacter textfraction 4
+\definecharacter textlognot 172
+\definecharacter textminus 12
+\definecharacter textmu 181
+\definecharacter textmultiply 215
+\definecharacter textpm 177
+
+\definecharacter quotedbl 34
+\definecharacter quotedblbase 132
+\definecharacter quotedblleft 147
+\definecharacter quotedblright 148
+
+\definecharacter quotesingle 31
+\definecharacter quotesinglebase 130
+
+\definecharacter quoteleft 96
+\definecharacter quoteright 39
+
+\definecharacter guilsingleleft 139
+\definecharacter guilsingleright 155
+\definecharacter leftguillemot 171
+\definecharacter rightguillemot 187
+
+\definecharacter aacute 225
+\definecharacter Aacute 193
+\definecharacter eacute 233
+\definecharacter Eacute 201
+\definecharacter iacute 237
+\definecharacter Iacute 205
+\definecharacter oacute 243
+\definecharacter Oacute 211
+\definecharacter uacute 250
+\definecharacter Uacute 218
+\definecharacter Yacute 221
+\definecharacter yacute 253
+
+\definecharacter scaron 154
+\definecharacter Scaron 138
+%definecharacter Zcaron 141
+
+\definecharacter ccedilla 231
+\definecharacter Ccedilla 199
+
+\definecharacter acircumflex 226
+\definecharacter Acircumflex 194
+\definecharacter ecircumflex 234
+\definecharacter Ecircumflex 202
+\definecharacter icircumflex 238
+\definecharacter Icircumflex 206
+\definecharacter ocircumflex 244
+\definecharacter Ocircumflex 212
+\definecharacter ucircumflex 251
+\definecharacter Ucircumflex 219
+
+\definecharacter adiaeresis 228
+\definecharacter Adiaeresis 196
+\definecharacter ediaeresis 235
+\definecharacter Ediaeresis 203
+\definecharacter idiaeresis 239
+\definecharacter Idiaeresis 207
+\definecharacter odiaeresis 246
+\definecharacter Odiaeresis 214
+\definecharacter udiaeresis 252
+\definecharacter Udiaeresis 220
+\definecharacter ydiaeresis 255
+\definecharacter Ydiaeresis 159
+
+\definecharacter agrave 224
+\definecharacter Agrave 192
+\definecharacter egrave 232
+\definecharacter Egrave 200
+\definecharacter igrave 236
+\definecharacter Igrave 204
+\definecharacter ograve 242
+\definecharacter Ograve 210
+\definecharacter ugrave 249
+\definecharacter Ugrave 217
+
+\definecharacter aring 229
+\definecharacter Aring 197
+
+\definecharacter lstroke 7
+\definecharacter Lstroke 6
+\definecharacter ostroke 248
+\definecharacter Ostroke 216
+
+\definecharacter atilde 227
+\definecharacter Atilde 195
+\definecharacter ntilde 241
+\definecharacter Ntilde 209
+\definecharacter otilde 245
+\definecharacter Otilde 213
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-uc.mkii b/tex/context/base/enco-uc.mkii
new file mode 100644
index 000000000..981eb6ae4
--- /dev/null
+++ b/tex/context/base/enco-uc.mkii
@@ -0,0 +1,1091 @@
+%D \module
+%D [ file=enco-uc,
+%D version=2000.xx.xx, % and later
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Unicode (backwards mapping),
+%D author={Adam Lindsay \& Hans Hagen},
+%D date=\currentdate,
+%D copyright=PRAGMA ADE]
+%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 An alternative approach would be to misuse the utf vectors, but they
+%D don't carry enough info around.
+
+% todo : \defineucharacter hebrewAlef 5 "D0
+
+\startencoding[uc]
+
+\definecharacter Agrave {\uchar0{192}}
+\definecharacter Aacute {\uchar0{193}}
+\definecharacter Acircumflex {\uchar0{194}}
+\definecharacter Atilde {\uchar0{195}}
+\definecharacter Adiaeresis {\uchar0{196}}
+\definecharacter Aring {\uchar0{197}}
+\definecharacter AEligature {\uchar0{198}}
+\definecharacter Ccedilla {\uchar0{199}}
+\definecharacter Egrave {\uchar0{200}}
+\definecharacter Eacute {\uchar0{201}}
+\definecharacter Ediaeresis {\uchar0{203}}
+\definecharacter Igrave {\uchar0{204}}
+\definecharacter Iacute {\uchar0{205}}
+\definecharacter Icircumflex {\uchar0{206}}
+\definecharacter Idiaeresis {\uchar0{207}}
+\definecharacter Eth {\uchar0{208}}
+\definecharacter Ntilde {\uchar0{209}}
+\definecharacter Ograve {\uchar0{210}}
+\definecharacter Oacute {\uchar0{211}}
+\definecharacter Ocircumflex {\uchar0{212}}
+\definecharacter Otilde {\uchar0{213}}
+\definecharacter Odiaeresis {\uchar0{214}}
+
+\definecharacter Ostroke {\uchar0{216}}
+\definecharacter Ugrave {\uchar0{217}}
+\definecharacter Uacute {\uchar0{218}}
+\definecharacter Uhungarumlaut {\uchar0{219}}
+\definecharacter Udiaeresis {\uchar0{220}}
+\definecharacter Yacute {\uchar0{221}}
+\definecharacter Thorn {\uchar0{222}}
+\definecharacter ssharp {\uchar0{223}}
+\definecharacter agrave {\uchar0{224}}
+\definecharacter aacute {\uchar0{225}}
+\definecharacter acircumflex {\uchar0{226}}
+\definecharacter atilde {\uchar0{227}}
+\definecharacter adiaeresis {\uchar0{228}}
+\definecharacter aring {\uchar0{229}}
+\definecharacter aeligature {\uchar0{230}}
+\definecharacter ccedilla {\uchar0{231}}
+\definecharacter egrave {\uchar0{232}}
+\definecharacter eacute {\uchar0{233}}
+\definecharacter ecircumflex {\uchar0{234}}
+\definecharacter ediaeresis {\uchar0{235}}
+\definecharacter igrave {\uchar0{236}}
+\definecharacter iacute {\uchar0{237}}
+\definecharacter icircumflex {\uchar0{238}}
+\definecharacter idiaeresis {\uchar0{239}}
+\definecharacter eth {\uchar0{240}}
+\definecharacter ntilde {\uchar0{241}}
+\definecharacter ograve {\uchar0{242}}
+\definecharacter oacute {\uchar0{243}}
+\definecharacter ocircumflex {\uchar0{244}}
+\definecharacter otilde {\uchar0{245}}
+\definecharacter odiaeresis {\uchar0{246}}
+
+\definecharacter ostroke {\uchar0{248}}
+\definecharacter ugrave {\uchar0{249}}
+\definecharacter uacute {\uchar0{250}}
+\definecharacter ucircumflex {\uchar0{251}}
+\definecharacter udiaeresis {\uchar0{252}}
+\definecharacter yacute {\uchar0{253}}
+\definecharacter thorn {\uchar0{254}}
+\definecharacter ydiaeresis {\uchar0{255}}
+
+\definecharacter Amacron {\uchar1{0}}
+\definecharacter amacron {\uchar1{1}}
+\definecharacter Abreve {\uchar1{2}}
+\definecharacter abreve {\uchar1{3}}
+\definecharacter Aogonek {\uchar1{4}}
+\definecharacter aogonek {\uchar1{5}}
+\definecharacter Cacute {\uchar1{6}}
+\definecharacter cacute {\uchar1{7}}
+\definecharacter Ccircumflex {\uchar1{8}}
+\definecharacter ccircumflex {\uchar1{9}}
+\definecharacter Cdotaccent {\uchar1{10}}
+\definecharacter cdotaccent {\uchar1{11}}
+\definecharacter Ccaron {\uchar1{12}}
+\definecharacter ccaron {\uchar1{13}}
+\definecharacter Dcaron {\uchar1{14}}
+\definecharacter dcaron {\uchar1{15}}
+\definecharacter Dstroke {\uchar1{16}}
+\definecharacter dstroke {\uchar1{17}}
+\definecharacter Emacron {\uchar1{18}}
+\definecharacter emacron {\uchar1{19}}
+\definecharacter Ebreve {\uchar1{20}}
+\definecharacter ebreve {\uchar1{21}}
+\definecharacter Edotaccent {\uchar1{22}}
+\definecharacter edotaccent {\uchar1{23}}
+\definecharacter Eogonek {\uchar1{24}}
+\definecharacter eogonek {\uchar1{25}}
+\definecharacter Ecaron {\uchar1{26}}
+\definecharacter ecaron {\uchar1{27}}
+\definecharacter Gcircumflex {\uchar1{28}}
+\definecharacter gcircumflex {\uchar1{29}}
+\definecharacter Gbreve {\uchar1{30}}
+\definecharacter gbreve {\uchar1{31}}
+\definecharacter Gdotaccent {\uchar1{32}}
+\definecharacter gdotaccent {\uchar1{33}}
+\definecharacter Gcommaaccent {\uchar1{34}}
+\definecharacter gcommaaccent {\uchar1{35}}
+\definecharacter Hcircumflex {\uchar1{36}}
+\definecharacter hcircumflex {\uchar1{37}}
+\definecharacter Hstroke {\uchar1{38}}
+\definecharacter hstroke {\uchar1{39}}
+\definecharacter Itilde {\uchar1{40}}
+\definecharacter itilde {\uchar1{41}}
+\definecharacter Imacron {\uchar1{42}}
+\definecharacter imacron {\uchar1{43}}
+\definecharacter Ibreve {\uchar1{44}}
+\definecharacter ibreve {\uchar1{45}}
+\definecharacter Iogonek {\uchar1{46}}
+\definecharacter iogonek {\uchar1{47}}
+\definecharacter Idotaccent {\uchar1{48}}
+\definecharacter dotlessi {\uchar1{49}}
+\definecharacter IJligature {\uchar1{50}}
+\definecharacter ijligature {\uchar1{51}}
+\definecharacter Jcircumflex {\uchar1{52}}
+\definecharacter jcircumflex {\uchar1{53}}
+\definecharacter Kcommaaccent {\uchar1{54}}
+\definecharacter kcommaaccent {\uchar1{55}}
+\definecharacter kkra {\uchar1{56}}
+\definecharacter Lacute {\uchar1{57}}
+\definecharacter lacute {\uchar1{58}}
+\definecharacter Lcommaaccent {\uchar1{59}}
+\definecharacter lcommaaccent {\uchar1{60}}
+\definecharacter Lcaron {\uchar1{61}}
+\definecharacter lcaron {\uchar1{62}}
+\definecharacter Ldotmiddle {\uchar1{63}}
+\definecharacter ldotmiddle {\uchar1{64}}
+\definecharacter Lstroke {\uchar1{65}}
+\definecharacter lstroke {\uchar1{66}}
+\definecharacter Nacute {\uchar1{67}}
+\definecharacter nacute {\uchar1{68}}
+\definecharacter Ncommaaccent {\uchar1{69}}
+\definecharacter ncommaaccent {\uchar1{70}}
+\definecharacter Ncaron {\uchar1{71}}
+\definecharacter ncaron {\uchar1{72}}
+\definecharacter napostrophe {\uchar1{73}}
+\definecharacter Neng {\uchar1{74}}
+\definecharacter neng {\uchar1{75}}
+\definecharacter Omacron {\uchar1{76}}
+\definecharacter omacron {\uchar1{77}}
+\definecharacter Obreve {\uchar1{78}}
+\definecharacter obreve {\uchar1{79}}
+\definecharacter Ohungarumlaut {\uchar1{80}}
+\definecharacter ohungarumlaut {\uchar1{81}}
+\definecharacter OEligature {\uchar1{82}}
+\definecharacter oeligature {\uchar1{83}}
+\definecharacter Racute {\uchar1{84}}
+\definecharacter racute {\uchar1{85}}
+\definecharacter Rcommaaccent {\uchar1{86}}
+\definecharacter rcommaaccent {\uchar1{87}}
+\definecharacter Rcaron {\uchar1{88}}
+\definecharacter rcaron {\uchar1{89}}
+\definecharacter Sacute {\uchar1{90}}
+\definecharacter sacute {\uchar1{91}}
+\definecharacter Scircumflex {\uchar1{92}}
+\definecharacter scircumflex {\uchar1{93}}
+\definecharacter Scedilla {\uchar1{94}}
+\definecharacter scedilla {\uchar1{95}}
+\definecharacter Scaron {\uchar1{96}}
+\definecharacter scaron {\uchar1{97}}
+\definecharacter Tcedilla {\uchar1{98}}
+\definecharacter tcedilla {\uchar1{99}}
+\definecharacter Tcaron {\uchar1{100}}
+\definecharacter tcaron {\uchar1{101}}
+\definecharacter Tstroke {\uchar1{102}}
+\definecharacter tstroke {\uchar1{103}}
+\definecharacter Utilde {\uchar1{104}}
+\definecharacter utilde {\uchar1{105}}
+\definecharacter Umacron {\uchar1{106}}
+\definecharacter umacron {\uchar1{107}}
+\definecharacter Ubreve {\uchar1{108}}
+\definecharacter ubreve {\uchar1{109}}
+\definecharacter Uring {\uchar1{110}}
+\definecharacter uring {\uchar1{111}}
+\definecharacter Uhungarumlaut {\uchar1{112}}
+\definecharacter uhungarumlaut {\uchar1{113}}
+\definecharacter Uogonek {\uchar1{114}}
+\definecharacter uogonek {\uchar1{115}}
+\definecharacter Wcircumflex {\uchar1{116}}
+\definecharacter wcircumflex {\uchar1{117}}
+\definecharacter Ycircumflex {\uchar1{118}}
+\definecharacter ycircumflex {\uchar1{119}}
+\definecharacter Ydiaeresis {\uchar1{120}}
+\definecharacter Zacute {\uchar1{121}}
+\definecharacter zacute {\uchar1{122}}
+\definecharacter Zdotaccent {\uchar1{123}}
+\definecharacter zdotaccent {\uchar1{124}}
+\definecharacter Zcaron {\uchar1{125}}
+\definecharacter zcaron {\uchar1{126}}
+\definecharacter slong {\uchar1{127}}
+
+\stopencoding
+
+\startencoding[uc]
+
+\definecharacter endash {\uchar{32}{19}}
+\definecharacter emdash {\uchar{32}{20}}
+\definecharacter quoteleft {\uchar{32}{24}}
+\definecharacter quoteright {\uchar{32}{25}}
+\definecharacter quotesinglebase {\uchar{32}{26}}
+
+\definecharacter quotedblleft {\uchar{32}{28}}
+\definecharacter quotedblright {\uchar{32}{29}}
+\definecharacter quotedblbase {\uchar{32}{30}}
+
+\definecharacter leftguillemot {\uchar0{171}}
+\definecharacter rightguillemot {\uchar0{187}}
+
+\definecharacter guilsingleleft {\uchar{32}{57}}
+\definecharacter guilsingleright {\uchar{32}{58}}
+
+\stopencoding
+
+%D Adam Lindsay's additions
+
+\startencoding[uc]
+
+\definecharacter exclamdown {\uchar0{161}}
+\definecharacter textcent {\uchar0{162}}
+\definecharacter textsterling {\uchar0{163}}
+\definecharacter textcurrency {\uchar0{164}}
+\definecharacter textyen {\uchar0{165}}
+\definecharacter textbrokenbar {\uchar0{166}}
+\definecharacter sectionmark {\uchar0{167}}
+\definecharacter textdiaresis {\uchar0{168}}
+\definecharacter copyright {\uchar0{169}}
+
+\definecharacter textlognot {\uchar0{172}}
+\definecharacter softhyphen {\uchar0{173}}
+\definecharacter registered {\uchar0{174}}
+\definecharacter textmacron {\uchar0{175}}
+\definecharacter textdegree {\uchar0{176}}
+\definecharacter textpm {\uchar0{177}}
+\definecharacter twosuperior {\uchar0{178}}
+\definecharacter threesuperior {\uchar0{179}}
+\definecharacter textacute {\uchar0{180}}
+\definecharacter textmu {\uchar0{181}}
+\definecharacter paragraphmark {\uchar0{182}}
+\definecharacter periodcentered {\uchar0{183}}
+\definecharacter textcedilla {\uchar0{184}}
+\definecharacter onesuperior {\uchar0{185}}
+
+\definecharacter textgrave {\uchar3{0}}
+\definecharacter textacute {\uchar3{1}}
+\definecharacter textcircumflex {\uchar3{2}}
+\definecharacter texttilde {\uchar3{3}}
+\definecharacter textmacron {\uchar3{4}}
+\definecharacter textbreve {\uchar3{6}}
+\definecharacter textdotaccent {\uchar3{7}}
+\definecharacter textdiaeresis {\uchar3{8}}
+\definecharacter textring {\uchar3{10}}
+\definecharacter texthungarumlaut {\uchar3{11}}
+\definecharacter textcaron {\uchar3{12}}
+\definecharacter textogonek {\uchar3{40}}
+
+\definecharacter percent {\uchar0{37}}
+\definecharacter textunderscore {\uchar0{95}}
+
+\definecharacter ordfeminine {\uchar0{170}}
+\definecharacter ordmasculine {\uchar0{186}}
+\definecharacter onequarter {\uchar0{188}}
+\definecharacter onehalf {\uchar0{189}}
+\definecharacter threequarter {\uchar0{190}}
+\definecharacter questiondown {\uchar0{191}}
+
+\definecharacter textmultiply {\uchar0{215}}
+\definecharacter textdiv {\uchar0{247}}
+
+\definecharacter textminus {\uchar{32}{18}}
+\definecharacter textdag {\uchar{32}{32}}
+\definecharacter textddag {\uchar{32}{33}}
+\definecharacter textbullet {\uchar{32}{34}}
+\definecharacter textellipsis {\uchar{32}{38}}
+\definecharacter perthousand {\uchar{32}{48}}
+
+%new:
+\definecharacter Scommaaccent {\uchar2{24}}
+\definecharacter scommaaccent {\uchar2{25}}
+\definecharacter Tcommaaccent {\uchar2{26}}
+\definecharacter tcommaaccent {\uchar2{27}}
+
+\stopencoding
+
+%D Mojca's and Taco's additions:
+
+\startencoding[uc]
+
+\definecharacter textasciicircum {\uchar{0}{94}} % 5e
+\definecharacter textgrave {\uchar{0}{96}} % 60
+\definecharacter textdiaeresis {\uchar{0}{168}} % a8
+%definecharacter textmacron {\uchar{0}{175}} % af
+%definecharacter textacute {\uchar{0}{180}} % b4
+%definecharacter textcedilla {\uchar{0}{184}} % b8
+\definecharacter textcircumflex {\uchar{2}{198}} % c6
+\definecharacter textcaron {\uchar{2}{199}} % c7
+\definecharacter textbreve {\uchar{2}{216}} % d8
+\definecharacter textdotaccent {\uchar{2}{217}} % d9
+\definecharacter textring {\uchar{2}{218}} % da
+\definecharacter textogonek {\uchar{2}{219}} % db
+\definecharacter texttilde {\uchar{2}{220}} % dc
+\definecharacter texthungarumlaut {\uchar{2}{221}} % dd
+
+\stopencoding
+
+%D Vietnamese:
+
+\startencoding[uc]
+
+\definecharacter Ohorn {\uchar1{160}}
+\definecharacter ohorn {\uchar1{161}}
+\definecharacter Uhorn {\uchar1{175}}
+\definecharacter uhorn {\uchar1{176}}
+
+\definecharacter Yhook {\uchar{30}{246}}
+\definecharacter yhook {\uchar{30}{247}}
+\definecharacter Ydotbelow {\uchar{30}{244}}
+\definecharacter ydotbelow {\uchar{30}{245}}
+\definecharacter Ahook {\uchar{30}{162}}
+\definecharacter Adotbelow {\uchar{30}{160}}
+\definecharacter Acircumflexgrave {\uchar{30}{166}}
+\definecharacter Acircumflexacute {\uchar{30}{164}}
+\definecharacter Acircumflextilde {\uchar{30}{170}}
+\definecharacter Acircumflexhook {\uchar{30}{168}}
+\definecharacter Acircumflexdotbelow {\uchar{30}{172}}
+\definecharacter Abrevegrave {\uchar{30}{176}}
+\definecharacter Abreveacute {\uchar{30}{174}}
+\definecharacter Abrevetilde {\uchar{30}{180}}
+\definecharacter Abrevehook {\uchar{30}{178}}
+\definecharacter Abrevedotbelow {\uchar{30}{182}}
+\definecharacter Ehook {\uchar{30}{186}}
+\definecharacter Edotbelow {\uchar{30}{184}}
+\definecharacter Ecircumflexgrave {\uchar{30}{192}}
+\definecharacter Ecircumflexacute {\uchar{30}{190}}
+\definecharacter Ecircumflextilde {\uchar{30}{196}}
+\definecharacter Ecircumflexhook {\uchar{30}{194}}
+\definecharacter Ecircumflexdotbelow {\uchar{30}{198}}
+\definecharacter Ihook {\uchar{30}{200}}
+\definecharacter ahook {\uchar{30}{163}}
+\definecharacter adotbelow {\uchar{30}{161}}
+\definecharacter acircumflexgrave {\uchar{30}{167}}
+\definecharacter acircumflexacute {\uchar{30}{165}}
+\definecharacter acircumflextilde {\uchar{30}{171}}
+\definecharacter acircumflexhook {\uchar{30}{169}}
+\definecharacter acircumflexdotbelow {\uchar{30}{173}}
+\definecharacter abrevegrave {\uchar{30}{177}}
+\definecharacter abreveacute {\uchar{30}{175}}
+\definecharacter abrevetilde {\uchar{30}{181}}
+\definecharacter abrevehook {\uchar{30}{179}}
+\definecharacter abrevedotbelow {\uchar{30}{183}}
+\definecharacter ehook {\uchar{30}{187}}
+\definecharacter edotbelow {\uchar{30}{185}}
+\definecharacter ecircumflexgrave {\uchar{30}{193}}
+\definecharacter ecircumflexacute {\uchar{30}{191}}
+\definecharacter ecircumflextilde {\uchar{30}{197}}
+\definecharacter ecircumflexhook {\uchar{30}{195}}
+\definecharacter ecircumflexdotbelow {\uchar{30}{199}}
+\definecharacter ihook {\uchar{30}{201}}
+\definecharacter Idotbelow {\uchar{30}{202}}
+\definecharacter Ohook {\uchar{30}{206}}
+\definecharacter Odotbelow {\uchar{30}{204}}
+\definecharacter Ocircumflexgrave {\uchar{30}{210}}
+\definecharacter Ocircumflexacute {\uchar{30}{208}}
+\definecharacter Ocircumflextilde {\uchar{30}{214}}
+\definecharacter Ocircumflexhook {\uchar{30}{212}}
+\definecharacter Ocircumflexdotbelow {\uchar{30}{216}}
+\definecharacter Ohorngrave {\uchar{30}{220}}
+\definecharacter Ohornacute {\uchar{30}{218}}
+\definecharacter Ohorntilde {\uchar{30}{224}}
+\definecharacter Ohornhook {\uchar{30}{222}}
+\definecharacter Ohorndotbelow {\uchar{30}{226}}
+\definecharacter Uhook {\uchar{30}{230}}
+\definecharacter Udotbelow {\uchar{30}{228}}
+\definecharacter Uhorngrave {\uchar{30}{234}}
+\definecharacter Uhornacute {\uchar{30}{232}}
+\definecharacter Uhorntilde {\uchar{30}{238}}
+\definecharacter Uhornhook {\uchar{30}{236}}
+\definecharacter Uhorndotbelow {\uchar{30}{240}}
+\definecharacter Ytilde {\uchar{30}{248}}
+\definecharacter idotbelow {\uchar{30}{203}}
+\definecharacter ohook {\uchar{30}{207}}
+\definecharacter odotbelow {\uchar{30}{205}}
+\definecharacter ocircumflexgrave {\uchar{30}{211}}
+\definecharacter ocircumflexacute {\uchar{30}{209}}
+\definecharacter ocircumflextilde {\uchar{30}{215}}
+\definecharacter ocircumflexhook {\uchar{30}{213}}
+\definecharacter ocircumflexdotbelow {\uchar{30}{217}}
+\definecharacter ohorngrave {\uchar{30}{221}}
+\definecharacter ohornacute {\uchar{30}{219}}
+\definecharacter ohorntilde {\uchar{30}{225}}
+\definecharacter ohornhook {\uchar{30}{223}}
+\definecharacter ohorndotbelow {\uchar{30}{227}}
+\definecharacter uhook {\uchar{30}{231}}
+\definecharacter udotbelow {\uchar{30}{229}}
+\definecharacter uhorngrave {\uchar{30}{235}}
+\definecharacter uhornacute {\uchar{30}{233}}
+\definecharacter uhorntilde {\uchar{30}{239}}
+\definecharacter uhornhook {\uchar{30}{237}}
+\definecharacter uhorndotbelow {\uchar{30}{241}}
+\definecharacter ytilde {\uchar{30}{249}}
+
+\definecharacter Etilde {\uchar{30}{188}}
+\definecharacter etilde {\uchar{30}{189}}
+\definecharacter Ygrave {\uchar{30}{242}}
+\definecharacter ygrave {\uchar{30}{243}}
+
+\stopencoding
+
+% Greek:
+
+\startencoding[uc]
+
+\definecharacter greekAlphatonos {\uchar3{134}}
+\definecharacter greekEpsilontonos {\uchar3{136}}
+\definecharacter greekEtatonos {\uchar3{137}}
+\definecharacter greekIotatonos {\uchar3{138}}
+\definecharacter greekOmicrontonos {\uchar3{140}}
+\definecharacter greekUpsilontonos {\uchar3{142}}
+\definecharacter greekOmegatonos {\uchar3{143}}
+\definecharacter greekiotadialytikatonos {\uchar3{144}}
+\definecharacter greekAlpha {\uchar3{145}}
+\definecharacter greekBeta {\uchar3{146}}
+\definecharacter greekGamma {\uchar3{147}}
+\definecharacter greekDelta {\uchar3{148}}
+\definecharacter greekEpsilon {\uchar3{149}}
+\definecharacter greekZeta {\uchar3{150}}
+\definecharacter greekEta {\uchar3{151}}
+\definecharacter greekTheta {\uchar3{152}}
+\definecharacter greekIota {\uchar3{153}}
+\definecharacter greekKappa {\uchar3{154}}
+\definecharacter greekLambda {\uchar3{155}}
+\definecharacter greekMu {\uchar3{156}}
+\definecharacter greekNu {\uchar3{157}}
+\definecharacter greekXi {\uchar3{158}}
+\definecharacter greekOmicron {\uchar3{159}}
+\definecharacter greekPi {\uchar3{160}}
+\definecharacter greekRho {\uchar3{161}}
+\definecharacter greekSigma {\uchar3{163}}
+\definecharacter greekTau {\uchar3{164}}
+\definecharacter greekUpsilon {\uchar3{165}}
+\definecharacter greekPhi {\uchar3{166}}
+\definecharacter greekChi {\uchar3{167}}
+\definecharacter greekPsi {\uchar3{168}}
+\definecharacter greekOmega {\uchar3{169}}
+
+\definecharacter greekalpha {\uchar3{177}}
+\definecharacter greekbeta {\uchar3{178}}
+\definecharacter greekgamma {\uchar3{179}}
+\definecharacter greekdelta {\uchar3{180}}
+\definecharacter greekepsilon {\uchar3{181}}
+\definecharacter greekzeta {\uchar3{182}}
+\definecharacter greeketa {\uchar3{183}}
+\definecharacter greektheta {\uchar3{184}}
+\definecharacter greekiota {\uchar3{185}}
+\definecharacter greekkappa {\uchar3{186}}
+\definecharacter greeklambda {\uchar3{187}}
+\definecharacter greekmu {\uchar3{188}}
+\definecharacter greeknu {\uchar3{189}}
+\definecharacter greekxi {\uchar3{190}}
+\definecharacter greekomicron {\uchar3{191}}
+\definecharacter greekpi {\uchar3{192}}
+\definecharacter greekrho {\uchar3{193}}
+\definecharacter greekfinalsigma {\uchar3{194}}
+\definecharacter greeksigma {\uchar3{195}}
+\definecharacter greektau {\uchar3{196}}
+\definecharacter greekupsilon {\uchar3{197}}
+\definecharacter greekphi {\uchar3{198}}
+\definecharacter greekchi {\uchar3{199}}
+\definecharacter greekpsi {\uchar3{200}}
+\definecharacter greekomega {\uchar3{201}}
+\definecharacter greekiotadialytika {\uchar3{202}}
+\definecharacter greekupsilondialytika {\uchar3{203}}
+\definecharacter greekomicrontonos {\uchar3{204}}
+\definecharacter greekupsilontonos {\uchar3{205}}
+\definecharacter greekomegatonos {\uchar3{206}}
+
+\definecharacter greekIotadialytika {\uchar3{170}}
+\definecharacter greekUpsilondialytika {\uchar3{171}}
+
+\definecharacter greekalphatonos {\uchar3{172}}
+\definecharacter greekepsilontonos {\uchar3{173}}
+\definecharacter greeketatonos {\uchar3{174}}
+\definecharacter greekiotatonos {\uchar3{175}}
+\definecharacter greekupsilondialytikatonos {\uchar3{176}}
+
+% new:
+\definecharacter greekthetaalt {\uchar3{209}}
+\definecharacter greekphialt {\uchar3{213}}
+\definecharacter greekpialt {\uchar3{214}}
+\definecharacter greekrhoalt {\uchar3{241}}
+\definecharacter greekepsilonalt {\uchar3{245}}
+
+\stopencoding
+
+% Cyrillic:
+
+\startencoding[uc]
+
+\definecharacter cyrillicA {\uchar4{16}}
+\definecharacter cyrillicB {\uchar4{17}}
+\definecharacter cyrillicV {\uchar4{18}}
+\definecharacter cyrillicG {\uchar4{19}}
+\definecharacter cyrillicD {\uchar4{20}}
+\definecharacter cyrillicE {\uchar4{21}}
+\definecharacter cyrillicZH {\uchar4{22}}
+\definecharacter cyrillicZ {\uchar4{23}}
+\definecharacter cyrillicI {\uchar4{24}}
+\definecharacter cyrillicISHRT {\uchar4{25}}
+\definecharacter cyrillicK {\uchar4{26}}
+\definecharacter cyrillicL {\uchar4{27}}
+\definecharacter cyrillicM {\uchar4{28}}
+\definecharacter cyrillicN {\uchar4{29}}
+\definecharacter cyrillicO {\uchar4{30}}
+\definecharacter cyrillicP {\uchar4{31}}
+\definecharacter cyrillicR {\uchar4{32}}
+\definecharacter cyrillicS {\uchar4{33}}
+\definecharacter cyrillicT {\uchar4{34}}
+\definecharacter cyrillicU {\uchar4{35}}
+\definecharacter cyrillicF {\uchar4{36}}
+\definecharacter cyrillicH {\uchar4{37}}
+\definecharacter cyrillicC {\uchar4{38}}
+\definecharacter cyrillicCH {\uchar4{39}}
+\definecharacter cyrillicSH {\uchar4{40}}
+\definecharacter cyrillicSHCH {\uchar4{41}}
+\definecharacter cyrillicHRDSN {\uchar4{42}}
+\definecharacter cyrillicERY {\uchar4{43}}
+\definecharacter cyrillicSFTSN {\uchar4{44}}
+\definecharacter cyrillicEREV {\uchar4{45}}
+\definecharacter cyrillicYU {\uchar4{46}}
+\definecharacter cyrillicYA {\uchar4{47}}
+
+\definecharacter cyrillica {\uchar4{48}}
+\definecharacter cyrillicb {\uchar4{49}}
+\definecharacter cyrillicv {\uchar4{50}}
+\definecharacter cyrillicg {\uchar4{51}}
+\definecharacter cyrillicd {\uchar4{52}}
+\definecharacter cyrillice {\uchar4{53}}
+\definecharacter cyrilliczh {\uchar4{54}}
+\definecharacter cyrillicz {\uchar4{55}}
+\definecharacter cyrillici {\uchar4{56}}
+\definecharacter cyrillicishrt {\uchar4{57}}
+\definecharacter cyrillick {\uchar4{58}}
+\definecharacter cyrillicl {\uchar4{59}}
+\definecharacter cyrillicm {\uchar4{60}}
+\definecharacter cyrillicn {\uchar4{61}}
+\definecharacter cyrillico {\uchar4{62}}
+\definecharacter cyrillicp {\uchar4{63}}
+\definecharacter cyrillicr {\uchar4{64}}
+\definecharacter cyrillics {\uchar4{65}}
+\definecharacter cyrillict {\uchar4{66}}
+\definecharacter cyrillicu {\uchar4{67}}
+\definecharacter cyrillicf {\uchar4{68}}
+\definecharacter cyrillich {\uchar4{69}}
+\definecharacter cyrillicc {\uchar4{70}}
+\definecharacter cyrillicch {\uchar4{71}}
+\definecharacter cyrillicsh {\uchar4{72}}
+\definecharacter cyrillicshch {\uchar4{73}}
+\definecharacter cyrillichrdsn {\uchar4{74}}
+\definecharacter cyrillicery {\uchar4{75}}
+\definecharacter cyrillicsftsn {\uchar4{76}}
+\definecharacter cyrillicerev {\uchar4{77}}
+\definecharacter cyrillicyu {\uchar4{78}}
+\definecharacter cyrillicya {\uchar4{79}}
+
+%D I tried to figure out what these were, but the unicode
+%D tables suggested they were the same as cyrillici, which was
+%D already defined! So, a temporary definition:
+
+% \def\cyrillicII{\cyrillicI}
+% \def\cyrillicii{\cyrillici}
+
+%D a guess derived from looking at enco-cyr suggests that this is
+%D identical to the Roman I/i pair. To me, that sounds like
+%D CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I in the UC tables!
+
+\definecharacter cyrillicII {\uchar4{6}}
+\definecharacter cyrillicii {\uchar4{86}}
+
+%D Guessing that tlir6a corresponds with t2a encoding as advertised,
+%D here are some more, cos I had some spare time: (AL)
+
+\definecharacter cyrillicDJE {\uchar4{2}}
+\definecharacter cyrillicTSHE {\uchar4{11}}
+%definecharacter cyrillicSHHA 132
+%definecharacter cyrillicZHDSC 133
+\definecharacter cyrillicZDSC {\uchar4{152}}
+\definecharacter cyrillicLJE {\uchar4{9}}
+\definecharacter cyrillicYI {\uchar4{7}}
+\definecharacter cyrillicAE {\uchar4{212}}
+%definecharacter cyrillicNDSC 141
+%definecharacter cyrillicNG 142
+\definecharacter cyrillicDZE {\uchar4{5}}
+%definecharacter cyrillicOTLD 144
+\definecharacter cyrillicSDSC {\uchar4{170}}
+\definecharacter cyrillicUSHRT {\uchar4{14}}
+%definecharacter cyrillicY 147
+%definecharacter cyrillicYHCRS 148
+%definecharacter cyrillicHDSC 149
+\definecharacter cyrillicDZHE {\uchar4{15}}
+\definecharacter cyrillicIE {\uchar4{4}}
+\definecharacter cyrillicNJE {\uchar4{10}}
+\definecharacter cyrillicYO {\uchar4{1}}
+
+\definecharacter cyrillicdje {\uchar4{82}}
+\definecharacter cyrillictshe {\uchar4{91}}
+%definecharacter cyrillicshha 164
+%definecharacter cyrilliczhdsc 165
+\definecharacter cyrilliczdsc {\uchar4{153}}
+\definecharacter cyrilliclje {\uchar4{89}}
+\definecharacter cyrillicyi {\uchar4{87}}
+\definecharacter cyrillicae {\uchar4{213}}
+%definecharacter cyrillicndsc 173
+%definecharacter cyrillicng 174
+\definecharacter cyrillicdze {\uchar4{85}}
+%definecharacter cyrillicotld 176
+\definecharacter cyrillicsdsc {\uchar4{171}}
+\definecharacter cyrillicushrt {\uchar4{94}}
+%definecharacter cyrillicy 179
+%definecharacter cyrillicyhcrs 180
+%definecharacter cyrillichdsc 181
+\definecharacter cyrillicdzhe {\uchar4{95}}
+\definecharacter cyrillicie {\uchar4{84}}
+\definecharacter cyrillicnje {\uchar4{90}}
+\definecharacter cyrillicyo {\uchar4{81}}
+
+% is there overlap with the above definitions
+
+\definecharacter cyrillicEgrave {\uchar4{0}}
+\definecharacter cyrillicGJE {\uchar4{3}}
+\definecharacter cyrillicJE {\uchar4{8}}
+\definecharacter cyrillicKJE {\uchar4{12}}
+\definecharacter cyrillicIgrave {\uchar4{13}}
+\definecharacter cyrillicegrave {\uchar4{80}}
+\definecharacter cyrillicgje {\uchar4{83}}
+\definecharacter cyrillicje {\uchar4{88}}
+\definecharacter cyrillickje {\uchar4{92}}
+\definecharacter cyrillicigrave {\uchar4{93}}
+\definecharacter cyrillicOMEGA {\uchar4{96}}
+\definecharacter cyrillicomega {\uchar4{97}}
+\definecharacter cyrillicYAT {\uchar4{98}}
+\definecharacter cyrillicyat {\uchar4{99}}
+\definecharacter cyrillicEiotified {\uchar4{100}}
+\definecharacter cyrilliceiotified {\uchar4{101}}
+\definecharacter cyrillicLITTLEYUS {\uchar4{102}}
+\definecharacter cyrilliclittleyus {\uchar4{103}}
+\definecharacter cyrillicLITTLEYUSiotified {\uchar4{104}}
+\definecharacter cyrilliclittleyusiotified {\uchar4{105}}
+\definecharacter cyrillicBIGYUS {\uchar4{106}}
+\definecharacter cyrillicbigyus {\uchar4{107}}
+\definecharacter cyrillicBIGYUSiotified {\uchar4{108}}
+\definecharacter cyrillicbigyusiotified {\uchar4{109}}
+\definecharacter cyrillicKSI {\uchar4{110}}
+\definecharacter cyrillicksi {\uchar4{111}}
+\definecharacter cyrillicPSI {\uchar4{112}}
+\definecharacter cyrillicpsi {\uchar4{113}}
+\definecharacter cyrillicFITA {\uchar4{114}}
+\definecharacter cyrillicfita {\uchar4{115}}
+\definecharacter cyrillicIZHITSA {\uchar4{116}}
+\definecharacter cyrillicizhitsa {\uchar4{117}}
+\definecharacter cyrillicIZHITSAdoublegrave {\uchar4{118}}
+\definecharacter cyrillicizhitsadoublegrave {\uchar4{119}}
+\definecharacter cyrillicUK {\uchar4{120}}
+\definecharacter cyrillicuk {\uchar4{121}}
+\definecharacter cyrillicOMEGAround {\uchar4{122}}
+\definecharacter cyrillicomegaround {\uchar4{123}}
+\definecharacter cyrillicOMEGAtitlo {\uchar4{124}}
+\definecharacter cyrillicomegatitlo {\uchar4{125}}
+\definecharacter cyrillicOT {\uchar4{126}}
+\definecharacter cyrillicot {\uchar4{127}}
+\definecharacter cyrillicKOPPA {\uchar4{128}}
+\definecharacter cyrillickoppa {\uchar4{129}}
+\definecharacter cyrillicTITLO {\uchar4{131}}
+\definecharacter cyrillicPALATALIZATION {\uchar4{132}}
+\definecharacter cyrillicDASIAPNEUMATA {\uchar4{133}}
+\definecharacter cyrillicPSILIPNEUMATA {\uchar4{134}}
+\definecharacter cyrillicISHRTtail {\uchar4{138}}
+\definecharacter cyrillicishrttail {\uchar4{139}}
+\definecharacter cyrillicSEMISOFT {\uchar4{140}}
+\definecharacter cyrillicsemisoft {\uchar4{141}}
+\definecharacter cyrillicERtick {\uchar4{142}}
+\definecharacter cyrillicertick {\uchar4{143}}
+\definecharacter cyrillicGHEupturn {\uchar4{144}}
+\definecharacter cyrillicgheupturn {\uchar4{145}}
+\definecharacter cyrillicGHEstroke {\uchar4{146}}
+\definecharacter cyrillicghestroke {\uchar4{147}}
+\definecharacter cyrillicGHEmidhook {\uchar4{148}}
+\definecharacter cyrillicghemidhook {\uchar4{149}}
+\definecharacter cyrillicZHEdescender {\uchar4{150}}
+\definecharacter cyrilliczhedescender {\uchar4{151}}
+\definecharacter cyrillicZDSC {\uchar4{152}}
+\definecharacter cyrilliczdsc {\uchar4{153}}
+\definecharacter cyrillicKADC {\uchar4{154}}
+\definecharacter cyrillickadc {\uchar4{155}}
+\definecharacter cyrillicKAvertstroke {\uchar4{156}}
+\definecharacter cyrillickavertstroke {\uchar4{157}}
+\definecharacter cyrillicKAstroke {\uchar4{158}}
+\definecharacter cyrillickastroke {\uchar4{159}}
+\definecharacter cyrillicKAbashkir {\uchar4{160}}
+\definecharacter cyrillickabashkir {\uchar4{161}}
+\definecharacter cyrillicENDC {\uchar4{162}}
+\definecharacter cyrillicendc {\uchar4{163}}
+\definecharacter cyrillicENGHE {\uchar4{164}}
+\definecharacter cyrillicenghe {\uchar4{165}}
+\definecharacter cyrillicPEmidhook {\uchar4{166}}
+\definecharacter cyrillicpemidhook {\uchar4{167}}
+\definecharacter cyrillicHA {\uchar4{168}}
+\definecharacter cyrillicha {\uchar4{169}}
+%definecharacter cyrillicSDSC {\uchar4{170}} % already defined
+%definecharacter cyrilliccdsc {\uchar4{171}} % already defined
+\definecharacter cyrillicTEDC {\uchar4{172}}
+\definecharacter cyrillictedc {\uchar4{173}}
+\definecharacter cyrillicYstr {\uchar4{174}}
+\definecharacter cyrillicystr {\uchar4{175}}
+\definecharacter cyrillicYstrstroke {\uchar4{176}}
+\definecharacter cyrillicystrstroke {\uchar4{177}}
+\definecharacter cyrillicHADC {\uchar4{178}}
+\definecharacter cyrillichadc {\uchar4{179}}
+\definecharacter cyrillicTETSE {\uchar4{180}}
+\definecharacter cyrillictetse {\uchar4{181}}
+\definecharacter cyrillicCHEDC {\uchar4{182}}
+\definecharacter cyrillicchedc {\uchar4{183}}
+\definecharacter cyrillicCHEvertstroke {\uchar4{184}}
+\definecharacter cyrillicchevertstroke {\uchar4{185}}
+\definecharacter cyrillicSHHA {\uchar4{186}}
+\definecharacter cyrillicshha {\uchar4{187}}
+\definecharacter cyrillicCHEabkhasian {\uchar4{188}}
+\definecharacter cyrilliccheabkhasian {\uchar4{189}}
+\definecharacter cyrillicCHEDCabkhasian {\uchar4{190}}
+\definecharacter cyrillicchedcabkhasian {\uchar4{191}}
+\definecharacter cyrillicPALOCHKA {\uchar4{192}}
+\definecharacter cyrillicZHEbreve {\uchar4{193}}
+\definecharacter cyrilliczhebreve {\uchar4{194}}
+\definecharacter cyrillicKAhook {\uchar4{195}}
+\definecharacter cyrillickahook {\uchar4{196}}
+\definecharacter cyrillicELtail {\uchar4{197}}
+\definecharacter cyrilliceltail {\uchar4{198}}
+\definecharacter cyrillicENhook {\uchar4{199}}
+\definecharacter cyrillicenhook {\uchar4{200}}
+\definecharacter cyrillicENtail {\uchar4{201}}
+\definecharacter cyrillicentail {\uchar4{202}}
+\definecharacter cyrillicCHEkhakassian {\uchar4{203}}
+\definecharacter cyrillicchekhakassian {\uchar4{204}}
+\definecharacter cyrillicEMtail {\uchar4{205}}
+\definecharacter cyrillicemtail {\uchar4{206}}
+\definecharacter cyrillicAbreve {\uchar4{208}}
+\definecharacter cyrillicabreve {\uchar4{209}}
+\definecharacter cyrillicAdiaeresis {\uchar4{210}}
+\definecharacter cyrillicadiaeresis {\uchar4{211}}
+%definecharacter cyrillicAE {\uchar4{212}} % already defined
+%definecharacter cyrillicae {\uchar4{213}} % already defined
+\definecharacter cyrillicEbreve {\uchar4{214}}
+\definecharacter cyrillicebreve {\uchar4{215}}
+\definecharacter cyrillicSCHWA {\uchar4{216}}
+\definecharacter cyrillicschwa {\uchar4{217}}
+\definecharacter cyrillicSCHWAdiaeresis {\uchar4{218}}
+\definecharacter cyrillicschwadiaeresis {\uchar4{219}}
+\definecharacter cyrillicZHEdiaeresis {\uchar4{220}}
+\definecharacter cyrilliczhediaeresis {\uchar4{221}}
+\definecharacter cyrillicZEdiaeresis {\uchar4{222}}
+\definecharacter cyrilliczediaeresis {\uchar4{223}}
+\definecharacter cyrillicDZEabkhasian {\uchar4{224}}
+\definecharacter cyrillicdzeabkhasian {\uchar4{225}}
+\definecharacter cyrillicImacron {\uchar4{226}}
+\definecharacter cyrillicimacron {\uchar4{227}}
+\definecharacter cyrillicIdiaeresis {\uchar4{228}}
+\definecharacter cyrillicidiaeresis {\uchar4{229}}
+\definecharacter cyrillicOdiaeresis {\uchar4{230}}
+\definecharacter cyrillicodiaeresis {\uchar4{231}}
+\definecharacter cyrillicObarred {\uchar4{232}}
+\definecharacter cyrillicobarred {\uchar4{233}}
+\definecharacter cyrillicObarreddiaeresis {\uchar4{234}}
+\definecharacter cyrillicobarreddiaeresis {\uchar4{235}}
+\definecharacter cyrillicEdiaeresis {\uchar4{236}}
+\definecharacter cyrillicediaeresis {\uchar4{237}}
+\definecharacter cyrillicUmacron {\uchar4{238}}
+\definecharacter cyrillicumacron {\uchar4{239}}
+\definecharacter cyrillicUdiaeresis {\uchar4{240}}
+\definecharacter cyrillicudiaeresis {\uchar4{241}}
+\definecharacter cyrillicUdoubleacute {\uchar4{242}}
+\definecharacter cyrillicudoubleacute {\uchar4{243}}
+\definecharacter cyrillicCHEdiaeresis {\uchar4{244}}
+\definecharacter cyrillicchediaeresis {\uchar4{245}}
+\definecharacter cyrillicYERUdiaeresis {\uchar4{248}}
+\definecharacter cyrillicyerudiaeresis {\uchar4{249}}
+
+\stopencoding
+
+% Greek Extended
+
+\startencoding[uc]
+
+\definecharacter greekalphapsili {\uchar{31}{0}}
+\definecharacter greekalphadasia {\uchar{31}{1}}
+\definecharacter greekalphapsilivaria {\uchar{31}{2}}
+\definecharacter greekalphadasiavaria {\uchar{31}{3}}
+\definecharacter greekalphapsilitonos {\uchar{31}{4}}
+\definecharacter greekalphadasiatonos {\uchar{31}{5}}
+\definecharacter greekalphapsiliperispomeni {\uchar{31}{6}}
+\definecharacter greekalphadasiaperispomeni {\uchar{31}{7}}
+\definecharacter greekAlphapsili {\uchar{31}{8}}
+\definecharacter greekAlphadasia {\uchar{31}{9}}
+\definecharacter greekAlphapsilivaria {\uchar{31}{10}}
+\definecharacter greekAlphadasiavaria {\uchar{31}{11}}
+\definecharacter greekAlphapsilitonos {\uchar{31}{12}}
+\definecharacter greekAlphadasiatonos {\uchar{31}{13}}
+\definecharacter greekAlphapsiliperispomeni {\uchar{31}{14}}
+\definecharacter greekAlphadasiaperispomeni {\uchar{31}{15}}
+\definecharacter greekepsilonpsili {\uchar{31}{16}} % 1f10
+\definecharacter greekepsilondasia {\uchar{31}{17}}
+\definecharacter greekepsilonpsilivaria {\uchar{31}{18}}
+\definecharacter greekepsilondasiavaria {\uchar{31}{19}}
+\definecharacter greekepsilonpsilitonos {\uchar{31}{20}}
+\definecharacter greekepsilondasiatonos {\uchar{31}{21}}
+\definecharacter greekEpsilonpsili {\uchar{31}{24}}
+\definecharacter greekEpsilondasia {\uchar{31}{25}}
+\definecharacter greekEpsilonpsilivaria {\uchar{31}{26}}
+\definecharacter greekEpsilondasiavaria {\uchar{31}{27}}
+\definecharacter greekEpsilonpsilitonos {\uchar{31}{28}}
+\definecharacter greekEpsilondasiatonos {\uchar{31}{29}}
+\definecharacter greeketapsili {\uchar{31}{32}} % 1f20
+\definecharacter greeketadasia {\uchar{31}{33}}
+\definecharacter greeketapsilivaria {\uchar{31}{34}}
+\definecharacter greeketadasiavaria {\uchar{31}{35}}
+\definecharacter greeketapsilitonos {\uchar{31}{36}}
+\definecharacter greeketadasiatonos {\uchar{31}{37}}
+\definecharacter greeketapsiliperispomeni {\uchar{31}{38}}
+\definecharacter greeketadasiaperispomeni {\uchar{31}{39}}
+\definecharacter greekEtapsili {\uchar{31}{40}}
+\definecharacter greekEtadasia {\uchar{31}{41}}
+\definecharacter greekEtapsilivaria {\uchar{31}{42}}
+\definecharacter greekEtadasiavaria {\uchar{31}{43}}
+\definecharacter greekEtapsilitonos {\uchar{31}{44}}
+\definecharacter greekEtadasiatonos {\uchar{31}{45}}
+\definecharacter greekEtapsiliperispomeni {\uchar{31}{46}}
+\definecharacter greekEtadasiaperispomeni {\uchar{31}{47}}
+\definecharacter greekiotapsili {\uchar{31}{48}} % 1f30
+\definecharacter greekiotadasia {\uchar{31}{49}}
+\definecharacter greekiotapsilivaria {\uchar{31}{50}}
+\definecharacter greekiotadasiavaria {\uchar{31}{51}}
+\definecharacter greekiotapsilitonos {\uchar{31}{52}}
+\definecharacter greekiotadasiatonos {\uchar{31}{53}}
+\definecharacter greekiotapsiliperispomeni {\uchar{31}{54}}
+\definecharacter greekiotadasiaperispomeni {\uchar{31}{55}}
+\definecharacter greekIotapsili {\uchar{31}{56}}
+\definecharacter greekIotadasia {\uchar{31}{57}}
+\definecharacter greekIotapsilivaria {\uchar{31}{58}}
+\definecharacter greekIotadasiavaria {\uchar{31}{59}}
+\definecharacter greekIotapsilitonos {\uchar{31}{60}}
+\definecharacter greekIotadasiatonos {\uchar{31}{61}}
+\definecharacter greekIotapsiliperispomeni {\uchar{31}{62}}
+\definecharacter greekIotadasiaperispomeni {\uchar{31}{63}}
+\definecharacter greekomicronpsili {\uchar{31}{64}} % 1f40
+\definecharacter greekomicrondasia {\uchar{31}{65}}
+\definecharacter greekomicronpsilivaria {\uchar{31}{66}}
+\definecharacter greekomicrondasiavaria {\uchar{31}{67}}
+\definecharacter greekomicronpsilitonos {\uchar{31}{68}}
+\definecharacter greekomicrondasiatonos {\uchar{31}{69}}
+\definecharacter greekOmicronpsili {\uchar{31}{72}}
+\definecharacter greekOmicrondasia {\uchar{31}{73}}
+\definecharacter greekOmicronpsilivaria {\uchar{31}{74}}
+\definecharacter greekOmicrondasiavaria {\uchar{31}{75}}
+\definecharacter greekOmicronpsilitonos {\uchar{31}{76}}
+\definecharacter greekOmicrondasiatonos {\uchar{31}{77}}
+\definecharacter greekupsilonpsili {\uchar{31}{80}} % 1f50
+\definecharacter greekupsilondasia {\uchar{31}{81}}
+\definecharacter greekupsilonpsilivaria {\uchar{31}{82}}
+\definecharacter greekupsilondasiavaria {\uchar{31}{83}}
+\definecharacter greekupsilonpsilitonos {\uchar{31}{84}}
+\definecharacter greekupsilondasiatonos {\uchar{31}{85}}
+\definecharacter greekupsilonpsiliperispomeni {\uchar{31}{86}}
+\definecharacter greekupsilondasiaperispomeni {\uchar{31}{87}}
+\definecharacter greekUpsilondasia {\uchar{31}{89}}
+\definecharacter greekUpsilondasiavaria {\uchar{31}{91}}
+\definecharacter greekUpsilondasiatonos {\uchar{31}{93}}
+\definecharacter greekUpsilondasiaperispomeni {\uchar{31}{95}}
+\definecharacter greekomegapsili {\uchar{31}{96}} % 1f60
+\definecharacter greekomegadasia {\uchar{31}{97}}
+\definecharacter greekomegapsilivaria {\uchar{31}{98}}
+\definecharacter greekomegadasiavaria {\uchar{31}{99}}
+\definecharacter greekomegapsilitonos {\uchar{31}{100}}
+\definecharacter greekomegadasiatonos {\uchar{31}{101}}
+\definecharacter greekomegapsiliperispomeni {\uchar{31}{102}}
+\definecharacter greekomegadasiaperispomeni {\uchar{31}{103}}
+\definecharacter greekOmegapsili {\uchar{31}{104}}
+\definecharacter greekOmegadasia {\uchar{31}{105}}
+\definecharacter greekOmegapsilivaria {\uchar{31}{106}}
+\definecharacter greekOmegadasiavaria {\uchar{31}{107}}
+\definecharacter greekOmegapsilitonos {\uchar{31}{108}}
+\definecharacter greekOmegadasiatonos {\uchar{31}{109}}
+\definecharacter greekOmegapsiliperispomeni {\uchar{31}{110}}
+\definecharacter greekOmegadasiaperispomeni {\uchar{31}{111}}
+\definecharacter greekalphavaria {\uchar{31}{112}} % 1f70
+\definecharacter greekalphaoxia {\uchar{31}{113}}
+\definecharacter greekepsilonvaria {\uchar{31}{114}}
+\definecharacter greekepsilonoxia {\uchar{31}{115}}
+\definecharacter greeketavaria {\uchar{31}{116}}
+\definecharacter greeketaoxia {\uchar{31}{117}}
+\definecharacter greekiotavaria {\uchar{31}{118}}
+\definecharacter greekiotaoxia {\uchar{31}{119}}
+\definecharacter greekomicronvaria {\uchar{31}{120}}
+\definecharacter greekomicronoxia {\uchar{31}{121}}
+\definecharacter greekupsilonvaria {\uchar{31}{122}}
+\definecharacter greekupsilonoxia {\uchar{31}{123}}
+\definecharacter greekomegavaria {\uchar{31}{124}}
+\definecharacter greekomegaoxia {\uchar{31}{125}}
+\definecharacter greekalphaiotasubpsili {\uchar{31}{128}} % 1f80
+\definecharacter greekalphaiotasubdasia {\uchar{31}{129}}
+\definecharacter greekalphaiotasubpsilivaria {\uchar{31}{130}}
+\definecharacter greekalphaiotasubdasiavaria {\uchar{31}{131}}
+\definecharacter greekalphaiotasubpsilitonos {\uchar{31}{132}}
+\definecharacter greekalphaiotasubdasiatonos {\uchar{31}{133}}
+\definecharacter greekalphaiotasubpsiliperispomeni {\uchar{31}{134}}
+\definecharacter greekalphaiotasubdasiaperispomeni {\uchar{31}{135}}
+\definecharacter greekAlphaiotasubpsili {\uchar{31}{136}}
+\definecharacter greekAlphaiotasubdasia {\uchar{31}{137}}
+\definecharacter greekAlphaiotasubpsilivaria {\uchar{31}{138}}
+\definecharacter greekAlphaiotasubdasiavaria {\uchar{31}{139}}
+\definecharacter greekAlphaiotasubpsilitonos {\uchar{31}{140}}
+\definecharacter greekAlphaiotasubdasiatonos {\uchar{31}{141}}
+\definecharacter greekAlphaiotasubpsiliperispomeni {\uchar{31}{142}}
+\definecharacter greekAlphaiotasubdasiaperispomeni {\uchar{31}{143}}
+\definecharacter greeketaiotasubpsili {\uchar{31}{144}} % 1f90
+\definecharacter greeketaiotasubdasia {\uchar{31}{145}}
+\definecharacter greeketaiotasubpsilivaria {\uchar{31}{146}}
+\definecharacter greeketaiotasubdasiavaria {\uchar{31}{147}}
+\definecharacter greeketaiotasubpsilitonos {\uchar{31}{148}}
+\definecharacter greeketaiotasubdasiatonos {\uchar{31}{149}}
+\definecharacter greeketaiotasubpsiliperispomeni {\uchar{31}{150}}
+\definecharacter greeketaiotasubdasiaperispomeni {\uchar{31}{151}}
+\definecharacter greekEtaiotasubpsili {\uchar{31}{152}}
+\definecharacter greekEtaiotasubdasia {\uchar{31}{153}}
+\definecharacter greekEtaiotasubpsilivaria {\uchar{31}{154}}
+\definecharacter greekEtaiotasubdasiavaria {\uchar{31}{155}}
+\definecharacter greekEtaiotasubpsilitonos {\uchar{31}{156}}
+\definecharacter greekEtaiotasubdasiatonos {\uchar{31}{157}}
+\definecharacter greekEtaiotasubpsiliperispomeni {\uchar{31}{158}}
+\definecharacter greekEtaiotasubdasiaperispomeni {\uchar{31}{159}}
+\definecharacter greekomegaiotasubpsili {\uchar{31}{160}} % 1fa0
+\definecharacter greekomegaiotasubdasia {\uchar{31}{161}}
+\definecharacter greekomegaiotasubpsilivaria {\uchar{31}{162}}
+\definecharacter greekomegaiotasubdasiavaria {\uchar{31}{163}}
+\definecharacter greekomegaiotasubpsilitonos {\uchar{31}{164}}
+\definecharacter greekomegaiotasubdasiatonos {\uchar{31}{165}}
+\definecharacter greekomegaiotasubpsiliperispomeni {\uchar{31}{166}}
+\definecharacter greekomegaiotasubdasiaperispomeni {\uchar{31}{167}}
+\definecharacter greekOmegaiotasubpsili {\uchar{31}{168}}
+\definecharacter greekOmegaiotasubdasia {\uchar{31}{169}}
+\definecharacter greekOmegaiotasubpsilivaria {\uchar{31}{170}}
+\definecharacter greekOmegaiotasubdasiavaria {\uchar{31}{171}}
+\definecharacter greekOmegaiotasubpsilitonos {\uchar{31}{172}}
+\definecharacter greekOmegaiotasubdasiatonos {\uchar{31}{173}}
+\definecharacter greekOmegaiotasubpsiliperispomeni {\uchar{31}{174}}
+\definecharacter greekOmegaiotasubdasiaperispomeni {\uchar{31}{175}}
+\definecharacter greekalphavrachy {\uchar{31}{176}} % 1fb0
+\definecharacter greekalphamacron {\uchar{31}{177}}
+\definecharacter greekalphaiotasubvaria {\uchar{31}{178}}
+\definecharacter greekalphaiotasub {\uchar{31}{179}}
+\definecharacter greekalphaiotasubtonos {\uchar{31}{180}}
+\definecharacter greekalphaperispomeni {\uchar{31}{182}}
+\definecharacter greekalphaiotasubperispomeni {\uchar{31}{183}}
+\definecharacter greekAlphavrachy {\uchar{31}{184}}
+\definecharacter greekAlphamacron {\uchar{31}{185}}
+\definecharacter greekAlphavaria {\uchar{31}{186}}
+\definecharacter greekAlphatonos {\uchar{31}{187}}
+\definecharacter greekAlphaiotasub {\uchar{31}{188}}
+\definecharacter greekCoronis {\uchar{31}{189}}
+\definecharacter greekprosgegrammeni {\uchar{31}{190}}
+\definecharacter greekpsili {\uchar{31}{191}}
+\definecharacter greekperispomeni {\uchar{31}{192}} % 1fc0
+\definecharacter greekdialytikaperispomeni {\uchar{31}{193}}
+\definecharacter greeketaiotasubvaria {\uchar{31}{194}}
+\definecharacter greeketaiotasub {\uchar{31}{195}}
+\definecharacter greeketaiotasubtonos {\uchar{31}{196}}
+\definecharacter greeketaperispomeni {\uchar{31}{198}}
+\definecharacter greeketaiotasubperispomeni {\uchar{31}{199}}
+\definecharacter greekEpsilonvaria {\uchar{31}{200}}
+\definecharacter greekEpsilontonos {\uchar{31}{201}}
+\definecharacter greekEtavaria {\uchar{31}{202}}
+\definecharacter greekEtatonos {\uchar{31}{203}}
+\definecharacter greekEtaiotasub {\uchar{31}{204}}
+\definecharacter greekpsilivaria {\uchar{31}{205}}
+\definecharacter greekpsilitonos {\uchar{31}{206}}
+\definecharacter greekpsiliperispomeni {\uchar{31}{207}}
+\definecharacter greekiotavrachy {\uchar{31}{208}} % 1fd0
+\definecharacter greekiotamacron {\uchar{31}{209}}
+\definecharacter greekiotadialytikavaria {\uchar{31}{210}}
+\definecharacter greekiotadialytikatonos {\uchar{31}{211}}
+\definecharacter greekiotaperispomeni {\uchar{31}{214}}
+\definecharacter greekiotadialytikaperispomeni {\uchar{31}{215}}
+\definecharacter greekIotavrachy {\uchar{31}{216}}
+\definecharacter greekIotamacron {\uchar{31}{217}}
+\definecharacter greekIotavaria {\uchar{31}{218}}
+\definecharacter greekIotatonos {\uchar{31}{219}}
+\definecharacter greekdasiavaria {\uchar{31}{221}}
+\definecharacter greekdasiatonos {\uchar{31}{222}}
+\definecharacter greekdasiaperispomeni {\uchar{31}{223}}
+\definecharacter greekupsilonvrachy {\uchar{31}{224}} % 1fe0
+\definecharacter greekupsilonmacron {\uchar{31}{225}}
+\definecharacter greekupsilondialytikavaria {\uchar{31}{226}}
+\definecharacter greekupsilondialytikatonos {\uchar{31}{227}}
+\definecharacter greekrhopsili {\uchar{31}{228}}
+\definecharacter greekrhodasia {\uchar{31}{229}}
+\definecharacter greekupsilonperispomeni {\uchar{31}{230}}
+\definecharacter greekupsilondialytikaperispomeni {\uchar{31}{231}}
+\definecharacter greekUpsilonvrachy {\uchar{31}{232}}
+\definecharacter greekUpsilonmacron {\uchar{31}{233}}
+\definecharacter greekUpsilonvaria {\uchar{31}{234}}
+\definecharacter greekUpsilontonos {\uchar{31}{235}}
+\definecharacter greekRhodasia {\uchar{31}{236}}
+\definecharacter greekdialytikavaria {\uchar{31}{237}}
+\definecharacter greekdialytikatonos {\uchar{31}{238}}
+\definecharacter greekvaria {\uchar{31}{239}}
+\definecharacter greekomegaiotasubvaria {\uchar{31}{242}}
+\definecharacter greekomegaiotasub {\uchar{31}{243}}
+\definecharacter greekomegaiotasubtonos {\uchar{31}{244}}
+\definecharacter greekomegaperispomeni {\uchar{31}{246}}
+\definecharacter greekomegaiotasubperispomeni {\uchar{31}{247}}
+\definecharacter greekOmicronvaria {\uchar{31}{248}}
+\definecharacter greekOmicrontonos {\uchar{31}{249}}
+\definecharacter greekOmegavaria {\uchar{31}{250}}
+\definecharacter greekOmegatonos {\uchar{31}{251}}
+\definecharacter greekOmegaiotasub {\uchar{31}{252}}
+\definecharacter greekoxia {\uchar{31}{253}}
+\definecharacter greekdasia {\uchar{31}{254}}
+\definecharacter greeksigmalunate {\uchar3{242}}
+\definecharacter greekSigmalunate {\uchar3{249}}
+\definecharacter greeksampi {\uchar3{225}}
+\definecharacter greekdigamma {\uchar3{221}}
+\definecharacter greekstigma {\uchar3{219}}
+\definecharacter greeknumkoppa {\uchar3{223}}
+\definecharacter greekkoppa {\uchar3{217}}
+\definecharacter greekupsilondiaeresis {\uchar3{203}}
+
+\stopencoding
+
+% Hebrew:
+
+\startencoding[uc]
+
+\definecharacter hebrewAlef {\uchar5{208}} % 05D0
+\definecharacter hebrewBet {\uchar5{209}}
+\definecharacter hebrewGimel {\uchar5{210}}
+\definecharacter hebrewDalet {\uchar5{211}}
+\definecharacter hebrewHe {\uchar5{212}}
+\definecharacter hebrewVav {\uchar5{213}}
+\definecharacter hebrewZayin {\uchar5{214}}
+\definecharacter hebrewHet {\uchar5{215}}
+\definecharacter hebrewTet {\uchar5{216}}
+\definecharacter hebrewYod {\uchar5{217}}
+\definecharacter hebrewKaffinal {\uchar5{218}}
+\definecharacter hebrewKaf {\uchar5{219}}
+\definecharacter hebrewLamed {\uchar5{220}}
+\definecharacter hebrewMemfinal {\uchar5{221}}
+\definecharacter hebrewMem {\uchar5{222}}
+\definecharacter hebrewNunfinal {\uchar5{223}}
+\definecharacter hebrewNun {\uchar5{224}}
+\definecharacter hebrewSamekh {\uchar5{225}}
+\definecharacter hebrewAyin {\uchar5{226}}
+\definecharacter hebrewPefinal {\uchar5{227}}
+\definecharacter hebrewPe {\uchar5{228}}
+\definecharacter hebrewTsadifinal {\uchar5{229}}
+\definecharacter hebrewTsadi {\uchar5{230}}
+\definecharacter hebrewQof {\uchar5{231}}
+\definecharacter hebrewResh {\uchar5{232}}
+\definecharacter hebrewShin {\uchar5{233}}
+\definecharacter hebrewTav {\uchar5{234}} % 05EA
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-vis.mkii b/tex/context/base/enco-vis.mkii
new file mode 100644
index 000000000..3c1fd7765
--- /dev/null
+++ b/tex/context/base/enco-vis.mkii
@@ -0,0 +1,3 @@
+% temporary module, needed for downward compatibility
+
+\input regi-vis.tex \enableregime[viscii] \endinput
diff --git a/tex/context/base/enco-vna.mkii b/tex/context/base/enco-vna.mkii
new file mode 100644
index 000000000..05753f37b
--- /dev/null
+++ b/tex/context/base/enco-vna.mkii
@@ -0,0 +1,145 @@
+%D \module
+%D [ file=enco-vna,
+%D version=1999.12.12,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Vietnamese Accents,
+%D author=Han The Thanh & Adam Lindsay & Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 is originally derived from the some files Han The Thanh
+%D prepared for \LATEX. The dual accent support is still preliminary,
+%D but works ok. It's now adapted to named glyphs, and is activated by
+%D \type {\useencoding[thisfile]}.
+
+%D This was apparently buggy from the start: there is nothing to
+%D disambiguate \type {\ohorn} from \type {\ohook}. Both are entered
+%D with \type {\h{o}} (AL)!
+
+%D Once stable, this code will move to \type {enco-acc.tex}.
+
+\startencoding[default]
+
+\defineaccent h A {\Ahook}
+\defineaccent d A {\Adotbelow}
+\defineaccent ` ^A {\Acircumflexgrave}
+\defineaccent ' ^A {\Acircumflexacute}
+\defineaccent ~ ^A {\Acircumflextilde}
+\defineaccent h ^A {\Acircumflexhook}
+\defineaccent d ^A {\Acircumflexdotbelow}
+\defineaccent ` uA {\Abrevegrave}
+\defineaccent ' uA {\Abreveacute}
+\defineaccent ~ uA {\Abrevetilde}
+\defineaccent h uA {\Abrevehook}
+\defineaccent d uA {\Abrevedotbelow}
+\defineaccent h E {\Ehook}
+\defineaccent d E {\Edotbelow}
+\defineaccent ` ^E {\Ecircumflexgrave}
+\defineaccent ' ^E {\Ecircumflexacute}
+\defineaccent ~ ^E {\Ecircumflextilde}
+\defineaccent h ^E {\Ecircumflexhook}
+\defineaccent d ^E {\Ecircumflexdotbelow}
+\defineaccent h I {\Ihook}
+\defineaccent d I {\Idotbelow}
+\defineaccent h O {\Ohook}
+\defineaccent d O {\Odotbelow}
+\defineaccent ` ^O {\Ocircumflexgrave}
+\defineaccent ' ^O {\Ocircumflexacute}
+\defineaccent ~ ^O {\Ocircumflextilde}
+\defineaccent h ^O {\Ocircumflexhook}
+\defineaccent d ^O {\Ocircumflexdotbelow}
+%defineaccent h O {\Ohorn} % !!! conflict with \Ohook!
+\defineaccent ` hO {\Ohorngrave}
+\defineaccent ` {\Ohorn} {\Ohorngrave}
+\defineaccent ' hO {\Ohornacute}
+\defineaccent ' {\Ohorn} {\Ohornacute}
+\defineaccent ~ hO {\Ohorntilde}
+\defineaccent ~ {\Ohorn} {\Ohorntilde}
+\defineaccent h hO {\Ohornhook}
+\defineaccent h {\Ohorn} {\Ohornhook}
+\defineaccent d hO {\Ohorndotbelow}
+\defineaccent d {\Ohorn} {\Ohorndotbelow}
+\defineaccent h U {\Uhook}
+\defineaccent d U {\Udotbelow}
+%defineaccent h U {\Uhorn} % !!! conflict with \Uhook! honestly, people!
+\defineaccent ` hU {\Uhorngrave}
+\defineaccent ` {\Uhorn} {\Uhorngrave}
+\defineaccent ' hU {\Uhornacute}
+\defineaccent ' {\Uhorn} {\Uhornacute}
+\defineaccent ~ hU {\Uhorntilde}
+\defineaccent ~ {\Uhorn} {\Uhorntilde}
+\defineaccent h hU {\Uhornhook}
+\defineaccent h {\Uhorn} {\Uhornhook}
+\defineaccent d hU {\Uhorndotbelow}
+\defineaccent d {\Uhorn} {\Uhorndotbelow}
+\defineaccent ` Y {\Ygrave}
+\defineaccent ' Y {\Yacute}
+\defineaccent ~ Y {\Ytilde}
+\defineaccent h Y {\Yhook}
+\defineaccent d Y {\Ydotbelow}
+\defineaccent h a {\ahook}
+\defineaccent d a {\adotbelow}
+\defineaccent ` ^a {\acircumflexgrave}
+\defineaccent ' ^a {\acircumflexacute}
+\defineaccent ~ ^a {\acircumflextilde}
+\defineaccent h ^a {\acircumflexhook}
+\defineaccent d ^a {\acircumflexdotbelow}
+\defineaccent ` ua {\abrevegrave}
+\defineaccent ' ua {\abreveacute}
+\defineaccent ~ ua {\abrevetilde}
+\defineaccent h ua {\abrevehook}
+\defineaccent d ua {\abrevedotbelow}
+\defineaccent h e {\ehook}
+\defineaccent d e {\edotbelow}
+\defineaccent ` ^e {\ecircumflexgrave}
+\defineaccent ' ^e {\ecircumflexacute}
+\defineaccent ~ ^e {\ecircumflextilde}
+\defineaccent h ^e {\ecircumflexhook}
+\defineaccent d ^e {\ecircumflexdotbelow}
+\defineaccent h i {\ihook}
+\defineaccent d i {\idotbelow}
+\defineaccent h o {\ohook}
+\defineaccent d o {\odotbelow}
+\defineaccent ^ o {\ocircumflex}
+\defineaccent ` ^o {\ocircumflexgrave}
+\defineaccent ' ^o {\ocircumflexacute}
+\defineaccent ~ ^o {\ocircumflextilde}
+\defineaccent h ^o {\ocircumflexhook}
+\defineaccent d ^o {\ocircumflexdotbelow}
+%defineaccent h o {\ohorn} % !!!
+\defineaccent ` ho {\ohorngrave}
+\defineaccent ' ho {\ohornacute}
+\defineaccent ~ ho {\ohorntilde}
+\defineaccent h ho {\ohornhook}
+\defineaccent d ho {\ohorndotbelow}
+\defineaccent ` {\ohorn} {\ohorngrave}
+\defineaccent ' {\ohorn} {\ohornacute}
+\defineaccent ~ {\ohorn} {\ohorntilde}
+\defineaccent h {\ohorn} {\ohornhook}
+\defineaccent d {\ohorn} {\ohorndotbelow}
+\defineaccent h u {\uhook}
+\defineaccent d u {\udotbelow}
+%defineaccent h u {\uhorn} % !!!
+\defineaccent ` hu {\uhorngrave}
+\defineaccent ' hu {\uhornacute}
+\defineaccent ~ hu {\uhorntilde}
+\defineaccent h hu {\uhornhook}
+\defineaccent d hu {\uhorndotbelow}
+\defineaccent ` {\uhorn} {\uhorngrave}
+\defineaccent ' {\uhorn} {\uhornacute}
+\defineaccent ~ {\uhorn} {\uhorntilde}
+\defineaccent h {\uhorn} {\uhornhook}
+\defineaccent d {\uhorn} {\uhorndotbelow}
+\defineaccent ` y {\ygrave}
+\defineaccent ' y {\yacute}
+\defineaccent ~ y {\ytilde}
+\defineaccent h y {\yhook}
+\defineaccent d y {\ydotbelow}
+
+\stopencoding
+
+\endinput
diff --git a/tex/context/base/enco-win.mkii b/tex/context/base/enco-win.mkii
new file mode 100644
index 000000000..826371d8a
--- /dev/null
+++ b/tex/context/base/enco-win.mkii
@@ -0,0 +1,7 @@
+% temporary module, needed for downward compatibility
+
+%\input regi-win.tex
+
+\enableregime[windows]
+
+\endinput
diff --git a/tex/context/base/enco-x5.mkii b/tex/context/base/enco-x5.mkii
new file mode 100644
index 000000000..f82ec6c5c
--- /dev/null
+++ b/tex/context/base/enco-x5.mkii
@@ -0,0 +1,218 @@
+%D \module
+%D [ file=enco-x5,
+%D version=1999.12.12,
+%D title=\CONTEXT\ Encoding Macros,
+%D subtitle=Vietnamese Encoding,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%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 is derived from the some files Han The Thanh
+%D prepared for \LATEX. The dual accent support is still
+%D preliminary, but works ok.
+
+\startencoding[x5]
+
+\definecharacter textgrave 0
+\definecharacter textacute 1
+\definecharacter textcircumflex 2
+\definecharacter texttilde 3
+\definecharacter textdiaeresis 4
+\definecharacter texthungarumlaut 5
+\definecharacter textring 6
+\definecharacter textcaron 7
+\definecharacter textbreve 8
+\definecharacter textmacron 9
+\definecharacter textdotaccent 10
+\definecharacter textcedilla 11
+\definecharacter textogonek 12
+
+\definecharacter dotlessi 25
+\definecharacter DJ 30
+\definecharacter dj 31
+
+\defineaccent ` A 128
+\defineaccent ' A 129
+\defineaccent ~ A 130
+\defineaccent h A 131
+\defineaccent d A 132
+\defineaccent ^ A 133
+\defineaccent ` ^A 134
+\defineaccent ' ^A 135
+\defineaccent ~ ^A 136
+\defineaccent h ^A 137
+\defineaccent d ^A 138
+\defineaccent u A 139
+\defineaccent ` uA 140
+\defineaccent ' uA 141
+\defineaccent ~ uA 142
+\defineaccent h uA 143
+\defineaccent d uA 144
+\defineaccent ` E 145
+\defineaccent ' E 146
+\defineaccent ~ E 147
+\defineaccent h E 148
+\defineaccent d E 149
+\defineaccent ^ E 150
+\defineaccent ` ^E 151
+\defineaccent ' ^E 152
+\defineaccent ~ ^E 153
+\defineaccent h ^E 154
+\defineaccent d ^E 155
+\defineaccent ` I 156
+\defineaccent ' I 157
+\defineaccent ~ I 158
+\defineaccent h I 159
+\defineaccent d I 192
+\defineaccent ` O 193
+\defineaccent ' O 194
+\defineaccent ~ O 195
+\defineaccent h O 196
+\defineaccent d O 197
+\defineaccent ^ O 198
+\defineaccent ` ^O 199
+\defineaccent ' ^O 200
+\defineaccent ~ ^O 201
+\defineaccent h ^O 202
+\defineaccent d ^O 203
+\defineaccent h O 204
+\defineaccent ` hO 205
+\defineaccent ' hO 206
+\defineaccent ~ hO 207
+\defineaccent h hO 208
+\defineaccent d hO 209
+\defineaccent ` U 210
+\defineaccent ' U 211
+\defineaccent ~ U 212
+\defineaccent h U 213
+\defineaccent d U 214
+\defineaccent h U 215
+\defineaccent ` hU 216
+\defineaccent ' hU 217
+\defineaccent ~ hU 218
+\defineaccent h hU 219
+\defineaccent d hU 220
+\defineaccent ` Y 221
+\defineaccent ' Y 222
+\defineaccent ~ Y 223
+\defineaccent h Y 26
+\defineaccent d Y 28
+\defineaccent ` a 160
+\defineaccent ' a 161
+\defineaccent ~ a 162
+\defineaccent h a 163
+\defineaccent d a 164
+\defineaccent ^ a 165
+\defineaccent ` ^a 166
+\defineaccent ' ^a 167
+\defineaccent ~ ^a 168
+\defineaccent h ^a 169
+\defineaccent d ^a 170
+\defineaccent u a 171
+\defineaccent ` ua 172
+\defineaccent ' ua 173
+\defineaccent ~ ua 174
+\defineaccent h ua 175
+\defineaccent d ua 176
+\defineaccent ` e 177
+\defineaccent ' e 178
+\defineaccent ~ e 179
+\defineaccent h e 180
+\defineaccent d e 181
+\defineaccent ^ e 182
+\defineaccent ` ^e 183
+\defineaccent ' ^e 184
+\defineaccent ~ ^e 185
+\defineaccent h ^e 186
+\defineaccent d ^e 187
+\defineaccent ` i 188
+\defineaccent ' i 189
+\defineaccent ~ i 190
+\defineaccent h i 191
+\defineaccent d i 224
+\defineaccent ` o 225
+\defineaccent ' o 226
+\defineaccent ~ o 227
+\defineaccent h o 228
+\defineaccent d o 229
+\defineaccent ^ o 230
+\defineaccent ` ^o 231
+\defineaccent ' ^o 232
+\defineaccent ~ ^o 233
+\defineaccent h ^o 234
+\defineaccent d ^o 235
+\defineaccent h o 236
+\defineaccent ` ho 237
+\defineaccent ' ho 238
+\defineaccent ~ ho 239
+\defineaccent h ho 240
+\defineaccent d ho 241
+\defineaccent ` u 242
+\defineaccent ' u 243
+\defineaccent ~ u 244
+\defineaccent h u 245
+\defineaccent d u 246
+\defineaccent h u 247
+\defineaccent ` hu 248
+\defineaccent ' hu 249
+\defineaccent ~ hu 250
+\defineaccent h hu 251
+\defineaccent d hu 252
+\defineaccent ` y 253
+\defineaccent ' y 254
+\defineaccent ~ y 255
+\defineaccent h y 27
+\defineaccent d y 29
+
+\stopencoding
+
+\endinput
+
+% \startencoding [x5]
+%
+% \definecharacter aa {\xfiveencodedaa}
+% \definecharacter AA {\xfiveencodedAA}
+%
+% \stopencoding
+%
+% \def\xfiveencodedaa%
+% {\accent23a}
+%
+% \def\xfiveencodedAA%
+% {\leavevmode
+% \setbox\zerocount\hbox{h}%
+% \dimen@\ht\zerocount
+% \advance\dimen@ -1ex
+% \rlap{\raise.67\dimen@\hbox{\char23}}A}
+
+% \quotesinglbase 13
+% \guilsinglleft 14
+% \guilsinglright 15
+% \textquotedblleft 16
+% \textquotedblright 17
+% \quotedblbase 18
+% \guillemotleft 19
+% \guillemotright 20
+% \textendash 21
+% \textemdash 22
+% \textcompwordmark 23
+% \textperthousand \% \char 24
+% \textpertenthousand \%\char 24\char 24
+% \textvisiblespace 32
+% \textquotedbl `\"
+% \textdollar `\$
+% \textquoteright `\'
+% \textless `\<
+% \textgreater `\>
+% \textbackslash `\
+% \textasciicircum `\^
+% \textunderscore 95
+% \textquoteleft `\`
+% \textbraceleft `\{
+% \textbar `\|
+% \textbraceright `\}
+% \textasciitilde `\~
diff --git a/tex/context/base/filt-bas.mkii b/tex/context/base/filt-bas.mkii
new file mode 100644
index 000000000..ca3bc3d70
--- /dev/null
+++ b/tex/context/base/filt-bas.mkii
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=filt-bas,
+%D version=2000.09.19,
+%D title=\CONTEXT\ Filter Macros,
+%D subtitle=A Base Collection,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% BEWARE: THIS IS A TEST MODULE, NAMES MAY CHANGE!
+
+\definefiltersynonym [utf8 to unicode16] [inutf8]
+
+\definefiltersynonym [persian fix] [FarsiToArabic]
+\definefiltersynonym [arabic analysis] [uni2cuni]
+\definefiltersynonym [arabic glyphs] [cuni2oar]
+
+\definefiltersequence
+ [farsi]
+ [utf8 to unicode16,
+ persian fix,
+ arabic analysis,
+ arabic glyphs]
+
+\definefiltersynonym [basic context analysis step1] [bcaa-1]
+\definefiltersynonym [basic context analysis step2] [bcaa-2]
+\definefiltersynonym [basic context analysis step3] [bcaa-3]
+\definefiltersynonym [farsi processing for uomarab] [uomarab-farsi]
+
+\definefiltersynonym [basic presentation forms to sf] [bpftosf]
+
+\definefiltersynonym [omega persian fix] [FarsiToArabic]
+\definefiltersynonym [omega arabic analysis] [uni2cuni]
+\definefiltersynonym [omega arabic glyphs] [cuni2oar]
+
+\definefiltersequence
+ [farsi-1]
+ [utf8 to unicode16,
+ omega persian fix,
+ omega arabic analysis,
+ omega arabic glyphs]
+
+\definefiltersequence
+ [farsi-2]
+ [utf8 to unicode16,
+ basic context analysis step1,
+ basic context analysis step2,
+ basic context analysis step3,
+ farsi processing for uomarab]
+
+\definefiltersequence
+ [farsi-3]
+ [utf8 to unicode16,
+ basic context analysis step1,
+ basic context analysis step2,
+ basic context analysis step3,
+ basic presentation forms to sf]
+
+\endinput
diff --git a/tex/context/base/filt-ini.mkii b/tex/context/base/filt-ini.mkii
new file mode 100644
index 000000000..6e1a16e9a
--- /dev/null
+++ b/tex/context/base/filt-ini.mkii
@@ -0,0 +1,121 @@
+%D \module
+%D [ file=filt-ini,
+%D version=2000.09.19,
+%D title=\CONTEXT\ Filter Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Filter Macros / Initialization}
+
+% \ifx\OmegaVersion\undefined
+
+% \let\definefiltersynonym \gobbledoubleempty
+% \let\definefiltersequence \gobbledoubleempty
+% \unexpanded\def\usefiltersequence {\gobblesingleempty}
+% \let\usefilter \gobblesingleempty
+% \let\truefiltername \gobbleoneargument
+
+% \expandafter \endinput
+% \fi
+
+\unprotect
+
+%D The real work starts here.
+
+% We need the {\??ot::#1} check because otherwise aleph will crash. Taco's
+% torture test:
+%
+% \ocp\ArabicContext = contextual
+%
+% \dorecurse {5000} {
+% \message{[\recurselevel]}
+% \ocplist\Arabic=\addbeforeocplist 1 \ArabicContext \nullocplist
+% }
+
+%D \macros
+%D {definefiltersynonym}
+
+\def\definefiltersynonym
+ {\dodoubleargument\dodefinefiltersynonym}
+
+\def\dodefinefiltersynonym[#1][#2]%
+ {\setvalue{\??or#1}{#2}}
+
+%D \macros
+%D {truefiltername}
+
+\def\truefiltername#1%
+ {\ifundefined{\??or#1}#1\else\truefiltername{\getvalue{\??or#1}}\fi}
+
+%D \macros
+%D {definefiltersequence}
+
+\def\definefiltersequence
+ {\dodoubleargument\dodefinefiltersequence}
+
+% \def\dodefinefiltersequence[#1][#2]%
+% {\setvalue{\??ot#1}{#2}}
+
+\def\dodefinefiltersequence[#1][#2]%
+ {\setxvalue{\??ot#1}{#2}%
+ \letgvalue{\??ot::#1}\v!stop}
+
+%D \macros
+%D {usefiltersequence}
+%D
+
+\def\magicocpnumber{1}
+
+% one can do:
+%
+% \definefiltersequence
+% [farsi]
+% [utf8 to unicode16=>5,
+% persian fix,
+% arabic analysis=>3,
+% arabic glyphs]
+%
+% so, => is used to signal a priority
+
+\def\dodousefiltersequence#1%
+ {\expandafter\ocp\csname\??or:#1\endcsname=\truefiltername{#1}\relax
+ \splitstring#1\at=>\to\!!stringa\and\!!stringb
+ \edef\!!stringb{\number\ifx\!!stringb\empty\magicocpnumber\else\!!stringb\fi}%
+ \appendetoks
+ \noexpand\addbeforeocplist
+ \!!stringb\space
+ \expandafter\noexpand\csname\??or:\!!stringa\endcsname
+ \to \scratchtoks}
+
+\unexpanded\def\usefiltersequence[#1]%
+ {\doifdefined{\??ot::#1}%
+ {\doifvalue{\??ot::#1}\v!stop
+ {\scratchtoks\emptytoks
+ \expanded{\processcommalist[\getvalue{\??ot#1}]}\dodousefiltersequence
+ \expanded{\global\ocplist\csname\??ot:#1\endcsname=\the\scratchtoks}\nullocplist
+ \letgvalue{\??ot::#1}\v!start}%
+ \expanded{\pushocplist\csname\??ot:#1\endcsname}\relax}}
+
+%D \macros
+%D {usefilter}
+
+\def\dousefilter#1%
+ {\doifundefined{\c!file\f!filterprefix#1}%
+ {\letvalue{\c!file\f!filterprefix#1}\empty
+ \makeshortfilename[\truefilename{\f!filterprefix#1}]%
+ \startreadingfile
+ \readsysfile{\shortfilename.mkii}
+ {\showmessage\m!filters1{#1}}
+ {\showmessage\m!filters2{#1}}%
+ \stopreadingfile}}
+
+\def\usefilter[#1]%
+ {\processcommalist[#1]\dousefilter}
+
+\protect \endinput
diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua
new file mode 100644
index 000000000..87dec59c6
--- /dev/null
+++ b/tex/context/base/font-afm.lua
@@ -0,0 +1,855 @@
+if not modules then modules = { } end modules ['font-afm'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
Some code may look a bit obscure but this has to do with the
+fact that we also use this code for testing and much code evolved
+in the transition from to to .
+
+
The following code still has traces of intermediate font support
+where we handles font encodings. Eventually font encoding goes
+away.
+--ldx]]--
+
+local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
+local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
+local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
+
+local format, match, gmatch, lower, gsub = string.format, string.match, string.gmatch, string.lower, string.gsub
+local lpegmatch = lpeg.match
+local abs = math.abs
+
+fonts = fonts or { }
+fonts.afm = fonts.afm or { }
+
+local afm = fonts.afm
+local tfm = fonts.tfm
+
+afm.version = 1.402 -- incrementing this number one up will force a re-cache
+afm.syncspace = true -- when true, nicer stretch values
+afm.enhance_data = true -- best leave this set to true
+afm.features = { }
+afm.features.aux = { }
+afm.features.data = { }
+afm.features.list = { }
+afm.features.default = { }
+afm.cache = containers.define("fonts", "afm", afm.version, true)
+
+--[[ldx--
+
We start with the basic reader which we give a name similar to the
+built in and reader.
+--ldx]]--
+
+--~ Comment FONTIDENTIFIER LMMATHSYMBOLS10
+--~ Comment CODINGSCHEME TEX MATH SYMBOLS
+--~ Comment DESIGNSIZE 10.0 pt
+--~ Comment CHECKSUM O 4261307036
+--~ Comment SPACE 0 plus 0 minus 0
+--~ Comment QUAD 1000
+--~ Comment EXTRASPACE 0
+--~ Comment NUM 676.508 393.732 443.731
+--~ Comment DENOM 685.951 344.841
+--~ Comment SUP 412.892 362.892 288.889
+--~ Comment SUB 150 247.217
+--~ Comment SUPDROP 386.108
+--~ Comment SUBDROP 50
+--~ Comment DELIM 2390 1010
+--~ Comment AXISHEIGHT 250
+
+local c = lpeg.P("Comment")
+local s = lpeg.S(" \t")
+local l = lpeg.S("\n\r")
+local w = lpeg.C((1 - l)^1)
+local n = lpeg.C((lpeg.R("09") + lpeg.S("."))^1) / tonumber * s^0
+
+local fd = { }
+
+local pattern = ( c * s^1 * (
+ ("CODINGSCHEME" * s^1 * w ) / function(a) end +
+ ("DESIGNSIZE" * s^1 * n * w ) / function(a) fd[ 1] = a end +
+ ("CHECKSUM" * s^1 * n * w ) / function(a) fd[ 2] = a end +
+ ("SPACE" * s^1 * n * "plus" * n * "minus" * n) / function(a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end +
+ ("QUAD" * s^1 * n ) / function(a) fd[ 6] = a end +
+ ("EXTRASPACE" * s^1 * n ) / function(a) fd[ 7] = a end +
+ ("NUM" * s^1 * n * n * n ) / function(a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end +
+ ("DENOM" * s^1 * n * n ) / function(a,b ) fd[11], fd[12] = a, b end +
+ ("SUP" * s^1 * n * n * n ) / function(a,b,c) fd[13], fd[14], fd[15] = a, b, c end +
+ ("SUB" * s^1 * n * n ) / function(a,b) fd[16], fd[17] = a, b end +
+ ("SUPDROP" * s^1 * n ) / function(a) fd[18] = a end +
+ ("SUBDROP" * s^1 * n ) / function(a) fd[19] = a end +
+ ("DELIM" * s^1 * n * n ) / function(a,b) fd[20], fd[21] = a, b end +
+ ("AXISHEIGHT" * s^1 * n ) / function(a) fd[22] = a end +
+ (1-l)^0
+) + (1-c)^1)^0
+
+local function scan_comment(str)
+ fd = { }
+ lpegmatch(pattern,str)
+ return fd
+end
+
+-- On a rainy day I will rewrite this in lpeg ...
+
+local keys = { }
+
+function keys.FontName (data,line) data.metadata.fullname = line:strip() end
+function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end
+function keys.IsFixedPitch(data,line) data.metadata.isfixedpitch = toboolean(line,true) end
+function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end
+function keys.XHeight (data,line) data.metadata.xheight = tonumber (line) end
+function keys.Descender (data,line) data.metadata.descender = tonumber (line) end
+function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
+function keys.Comment (data,line)
+ -- Comment DesignSize 12 (pts)
+ -- Comment TFM designsize: 12 (in points)
+ line = lower(line)
+ local designsize = match(line,"designsize[^%d]*(%d+)")
+ if designsize then data.metadata.designsize = tonumber(designsize) end
+end
+
+local function get_charmetrics(data,charmetrics,vector)
+ local characters = data.characters
+ local chr, str, ind = { }, "", 0
+ for k,v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
+ if k == 'C' then
+ if str ~= "" then characters[str] = chr end
+ chr = { }
+ str = ""
+ v = tonumber(v)
+ if v < 0 then
+ ind = ind + 1
+ else
+ ind = v
+ end
+ chr.index = ind
+ elseif k == 'WX' then
+ chr.width = v
+ elseif k == 'N' then
+ str = v
+ elseif k == 'B' then
+ local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
+ chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) }
+ elseif k == 'L' then
+ local plus, becomes = match(v,"^(.-) +(.-)$")
+ if not chr.ligatures then chr.ligatures = { } end
+ chr.ligatures[plus] = becomes
+ end
+ end
+ if str ~= "" then
+ characters[str] = chr
+ end
+end
+
+local function get_kernpairs(data,kernpairs)
+ local characters = data.characters
+ for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
+ local chr = characters[one]
+ if chr then
+ if not chr.kerns then chr.kerns = { } end
+ chr.kerns[two] = tonumber(value)
+ end
+ end
+end
+
+local function get_variables(data,fontmetrics)
+ for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
+ if keys[key] then keys[key](data,rest) end
+ end
+end
+
+local function get_indexes(data,filename)
+ local pfbfile = file.replacesuffix(filename,"pfb")
+ local pfbname = resolvers.find_file(pfbfile,"pfb") or ""
+ if pfbname == "" then
+ pfbname = resolvers.find_file(file.basename(pfbfile),"pfb") or ""
+ end
+ if pfbname ~= "" then
+ data.luatex.filename = pfbname
+ local pfbblob = fontloader.open(pfbname)
+ if pfbblob then
+ local characters = data.characters
+ local pfbdata = fontloader.to_table(pfbblob)
+ --~ print(table.serialize(pfbdata))
+ if pfbdata then
+ local glyphs = pfbdata.glyphs
+ if glyphs then
+ if trace_loading then
+ logs.report("load afm","getting index data from %s",pfbname)
+ end
+ -- local offset = (glyphs[0] and glyphs[0] != .notdef) or 0
+ for index, glyph in next, glyphs do
+ local name = glyph.name
+ if name then
+ local char = characters[name]
+ if char then
+ if trace_indexing then
+ logs.report("load afm","glyph %s has index %s",name,index)
+ end
+ char.index = index
+ end
+ end
+ end
+ elseif trace_loading then
+ logs.report("load afm","no glyph data in pfb file %s",pfbname)
+ end
+ elseif trace_loading then
+ logs.report("load afm","no data in pfb file %s",pfbname)
+ end
+ fontloader.close(pfbblob)
+ elseif trace_loading then
+ logs.report("load afm","invalid pfb file %s",pfbname)
+ end
+ elseif trace_loading then
+ logs.report("load afm","no pfb file for %s",filename)
+ end
+end
+
+function afm.read_afm(filename)
+ local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging
+-- local ok, afmblob = true, file.readdata(filename)
+ if ok and afmblob then
+ local data = {
+ characters = { },
+ metadata = {
+ version = version or '0', -- hm
+ filename = file.removesuffix(file.basename(filename))
+ }
+ }
+ afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
+ if trace_loading then
+ logs.report("load afm","loading char metrics")
+ end
+ get_charmetrics(data,charmetrics,vector)
+ return ""
+ end)
+ afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs)
+ if trace_loading then
+ logs.report("load afm","loading kern pairs")
+ end
+ get_kernpairs(data,kernpairs)
+ return ""
+ end)
+ afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics)
+ if trace_loading then
+ logs.report("load afm","loading variables")
+ end
+ data.afmversion = version
+ get_variables(data,fontmetrics)
+ data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now
+ return ""
+ end)
+ data.luatex = { }
+ get_indexes(data,filename)
+ return data
+ else
+ if trace_loading then
+ logs.report("load afm","no valid afm file %s",filename)
+ end
+ return nil
+ end
+end
+
+--[[ldx--
+
We cache files. Caching is taken care of in the loader. We cheat a bit
+by adding ligatures and kern information to the afm derived data. That
+way we can set them faster when defining a font.
+--ldx]]--
+
+function afm.load(filename)
+ -- hm, for some reasons not resolved yet
+ filename = resolvers.find_file(filename,'afm') or ""
+ if filename ~= "" then
+ local name = file.removesuffix(file.basename(filename))
+ local data = containers.read(afm.cache(),name)
+ local size = lfs.attributes(filename,"size") or 0
+ if not data or data.verbose ~= fonts.verbose or data.size ~= size then
+ logs.report("load afm", "reading %s",filename)
+ data = afm.read_afm(filename)
+ if data then
+ -- data.luatex = data.luatex or { }
+ logs.report("load afm", "unifying %s",filename)
+ afm.unify(data,filename)
+ if afm.enhance_data then
+ logs.report("load afm", "add ligatures")
+ afm.add_ligatures(data,'ligatures') -- easier this way
+ logs.report("load afm", "add tex-ligatures")
+ afm.add_ligatures(data,'texligatures') -- easier this way
+ logs.report("load afm", "add extra kerns")
+ afm.add_kerns(data) -- faster this way
+ end
+ logs.report("load afm", "add tounicode data")
+ fonts.map.add_to_unicode(data,filename)
+ data.size = size
+ data.verbose = fonts.verbose
+ logs.report("load afm","saving: %s in cache",name)
+ data = containers.write(afm.cache(), name, data)
+ data = containers.read(afm.cache(),name)
+ end
+ end
+ return data
+ else
+ return nil
+ end
+end
+
+function afm.unify(data, filename)
+ local unicodevector = fonts.enc.load('unicode').hash
+ local glyphs, indices, unicodes, names = { }, { }, { }, { }
+ local verbose, private = fonts.verbose, fonts.private
+ for name, blob in next, data.characters do
+ local code = unicodevector[name] -- or characters.name_to_unicode[name]
+ if not code then
+ local u = match(name,"^uni(%x+)$")
+ code = u and tonumber(u,16)
+ if not code then
+ code = private
+ private = private + 1
+ logs.report("afm glyph", "assigning private slot U+%04X for unknown glyph name %s", code, name)
+ end
+ end
+ local index = blob.index
+ unicodes[name] = code
+ indices[code] = index
+ glyphs[index] = blob
+ names[name] = index
+ blob.name = name
+ if verbose then
+ local bu = blob.unicode
+ if not bu then
+ blob.unicode = code
+ elseif type(bu) == "table" then
+ bu[#bu+1] = code
+ else
+ blob.unicode = { bu, code }
+ end
+ else
+ blob.index = nil
+ end
+ end
+ data.glyphs = glyphs
+ data.characters = nil
+ local luatex = data.luatex
+ luatex.filename = luatex.filename or file.removesuffix(file.basename(filename))
+ luatex.unicodes = unicodes -- name to unicode
+ luatex.indices = indices -- unicode to index
+ luatex.marks = { } -- todo
+ luatex.names = names -- name to index
+ luatex.private = private
+end
+
+--[[ldx--
+
These helpers extend the basic table with extra ligatures, texligatures
+and extra kerns. This saves quite some lookups later.
+--ldx]]--
+
+function afm.add_ligatures(afmdata,ligatures)
+ local glyphs, luatex = afmdata.glyphs, afmdata.luatex
+ local indices, unicodes, names = luatex.indices, luatex.unicodes, luatex.names
+ for k,v in next, characters[ligatures] do -- main characters table
+ local one = glyphs[names[k]]
+ if one then
+ for _, b in next, v do
+ two, three = b[1], b[2]
+ if two and three and names[two] and names[three] then
+ local ol = one[ligatures]
+ if ol then
+ if not ol[two] then -- was one.ligatures ... bug
+ ol[two] = three
+ end
+ else
+ one[ligatures] = { [two] = three }
+ end
+ end
+ end
+ end
+ end
+end
+
+--[[ldx--
+
We keep the extra kerns in separate kerning tables so that we can use
+them selectively.
+--ldx]]--
+
+function afm.add_kerns(afmdata)
+ local glyphs = afmdata.glyphs
+ local names = afmdata.luatex.names
+ local uncomposed = characters.uncomposed
+ local function do_it_left(what)
+ for index, glyph in next, glyphs do
+ local kerns = glyph.kerns
+ if kerns then
+ local extrakerns = glyph.extrakerns or { }
+ for complex, simple in next, uncomposed[what] do
+ if names[compex] then
+ local ks = kerns[simple]
+ if ks and not kerns[complex] then
+ extrakerns[complex] = ks
+ end
+ end
+ end
+ if next(extrakerns) then
+ glyph.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ local function do_it_copy(what)
+ for complex, simple in next, uncomposed[what] do
+ local c = glyphs[names[complex]]
+ if c then -- optional
+ local s = glyphs[names[simple]]
+ if s then
+ if not c.kerns then
+ c.extrakerns = s.kerns or { }
+ end
+ if s.extrakerns then
+ local extrakerns = c.extrakerns or { }
+ for k, v in next, s.extrakerns do
+ extrakerns[k] = v
+ end
+ if next(extrakerns) then
+ s.extrakerns = extrakerns
+ end
+ end
+ end
+ end
+ end
+ end
+ -- add complex with values of simplified when present
+ do_it_left("left")
+ do_it_left("both")
+ -- copy kerns from simple char to complex char unless set
+ do_it_copy("both")
+ do_it_copy("right")
+end
+
+--[[ldx--
+
The copying routine looks messy (and is indeed a bit messy).
+--ldx]]--
+
+-- once we have otf sorted out (new format) we can try to make the afm
+-- cache similar to it (similar tables)
+
+function afm.add_dimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name
+ if data then
+ for index, glyph in next, data.glyphs do
+ local bb = glyph.boundingbox
+ if bb then
+ local ht, dp = bb[4], -bb[2]
+ if ht == 0 or ht < 0 then
+ -- no need to set it and no negative heights, nil == 0
+ else
+ glyph.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- no negative depths and no negative depths, nil == 0
+ else
+ glyph.depth = dp
+ end
+ end
+ end
+ end
+end
+
+fonts.formats.afm = "type1"
+fonts.formats.pfb = "type1"
+
+function afm.copy_to_tfm(data)
+ if data then
+ local glyphs = data.glyphs
+ if glyphs then
+ local metadata, luatex = data.metadata, data.luatex
+ local unicodes, indices = luatex.unicodes, luatex.indices
+ local characters, parameters, descriptions = { }, { }, { }
+ -- todo : merge into tfm
+ for u, i in next, indices do
+ local d = glyphs[i]
+ characters[u] = { }
+ descriptions[u] = d
+ end
+ local filename = fonts.tfm.checked_filename(luatex) -- was metadata.filename
+ local fontname = metadata.fontname or metadata.fullname
+ local fullname = metadata.fullname or metadata.fontname
+ local endash, emdash, space, spaceunits = unicodes['space'], unicodes['emdash'], "space", 500
+ -- same as otf
+ if metadata.isfixedpitch then
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width, "emdash"
+ end
+ if not spaceunits and metadata.charwidth then
+ spaceunits, spacer = metadata.charwidth, "charwidth"
+ end
+ else
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and metadata.charwidth then
+ spaceunits, spacer = metadata.charwidth, "charwidth"
+ end
+ end
+ spaceunits = tonumber(spaceunits)
+ if spaceunits < 200 then
+ -- todo: warning
+ end
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits
+ parameters.space_stretch = 500
+ parameters.space_shrink = 333
+ parameters.x_height = 400
+ parameters.quad = 1000
+ local italicangle = data.metadata.italicangle
+ if italicangle then
+ parameters.slant = parameters.slant - math.round(math.tan(italicangle*math.pi/180))
+ end
+ if metadata.isfixedpitch then
+ parameters.space_stretch = 0
+ parameters.space_shrink = 0
+ elseif afm.syncspace then
+ parameters.space_stretch = spaceunits/2
+ parameters.space_shrink = spaceunits/3
+ end
+ parameters.extra_space = parameters.space_shrink
+ if metadata.xheight and metadata.xheight > 0 then
+ parameters.x_height = metadata.xheight
+ else
+ -- same as otf
+ local x = unicodes['x']
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.x_height = x.height
+ end
+ end
+ --
+ end
+ local fd = data.fontdimens
+ if fd and fd[8] and fd[9] and fd[10] then -- math
+ for k,v in next, fd do
+ parameters[k] = v
+ end
+ end
+ --
+ if next(characters) then
+ return {
+ characters = characters,
+ parameters = parameters,
+ descriptions = descriptions,
+ indices = indices,
+ unicodes = unicodes,
+ luatex = luatex,
+ encodingbytes = 2,
+ filename = filename,
+ fontname = fontname,
+ fullname = fullname,
+ psname = fullname, -- in otf: tfm.fontname or tfm.fullname
+ name = filename or fullname or fontname,
+ format = fonts.fontformat(filename,"type1"),
+ type = 'real',
+ units = 1000,
+ direction = 0,
+ boundarychar_label = 0,
+ boundarychar = 65536,
+ --~ false_boundarychar = 65536, -- produces invalid tfm in luatex
+ designsize = (metadata.designsize or 10)*65536,
+ spacer = spacer,
+ ascender = abs(metadata.ascender or 0),
+ descender = abs(metadata.descender or 0),
+ italicangle = italicangle,
+ }
+ end
+ end
+ end
+ return nil
+end
+
+--[[ldx--
+
Originally we had features kind of hard coded for
+files but since I expect to support more font formats, I decided
+to treat this fontformat like any other and handle features in a
+more configurable way.
+--ldx]]--
+
+function afm.features.register(name,default)
+ afm.features.list[#afm.features.list+1] = name
+ afm.features.default[name] = default
+end
+
+function afm.set_features(tfmdata)
+ local shared = tfmdata.shared
+ local afmdata = shared.afmdata
+ local features = shared.features
+ if features and next(features) then
+ local mode = tfmdata.mode or fonts.mode
+ local initializers = fonts.initializers
+ local fi = initializers[mode]
+ local fiafm = fi and fi.afm
+ if fiafm then
+ local lists = {
+ fonts.triggers,
+ afm.features.list,
+ fonts.manipulators,
+ }
+ for l=1,3 do
+ local list = lists[l]
+ if list then
+ for i=1,#list do
+ local f = list[i]
+ local value = features[f]
+ if value and fiafm[f] then -- brr
+ if trace_features then
+ logs.report("define afm","initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown')
+ end
+ fiafm[f](tfmdata,value)
+ mode = tfmdata.mode or fonts.mode
+ fiafm = initializers[mode].afm
+ end
+ end
+ end
+ end
+ end
+ local fm = fonts.methods[mode]
+ local fmafm = fm and fm.afm
+ if fmfm then
+ local lists = {
+ afm.features.list,
+ }
+ local sp = shared.processors
+ for l=1,1 do
+ local list = lists[l]
+ if list then
+ for i=1,#list do
+ local f = list[i]
+ if features[f] and fmafm[f] then -- brr
+ if not sp then
+ sp = { fmafm[f] }
+ shared.processors = sp
+ else
+ sp[#sp+1] = fmafm[f]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function afm.check_features(specification)
+ local features, done = fonts.define.check(specification.features.normal,afm.features.default)
+ if done then
+ specification.features.normal = features
+ tfm.hash_instance(specification,true)
+ end
+end
+
+function afm.afm_to_tfm(specification)
+ local afmname = specification.filename or specification.name
+ if specification.forced == "afm" or specification.format == "afm" then -- move this one up
+ if trace_loading then
+ logs.report("load afm","forcing afm format for %s",afmname)
+ end
+ else
+ local tfmname = resolvers.findbinfile(afmname,"ofm") or ""
+ if tfmname ~= "" then
+ if trace_loading then
+ logs.report("load afm","fallback from afm to tfm for %s",afmname)
+ end
+ afmname = ""
+ end
+ end
+ if afmname == "" then
+ return nil
+ else
+ afm.check_features(specification)
+ specification = fonts.define.resolve(specification) -- new, was forgotten
+ local features = specification.features.normal
+ local cache_id = specification.hash
+ local tfmdata = containers.read(tfm.cache(), cache_id) -- cache with features applied
+ if not tfmdata then
+ local afmdata = afm.load(afmname)
+ if afmdata and next(afmdata) then
+ afm.add_dimensions(afmdata)
+ tfmdata = afm.copy_to_tfm(afmdata)
+ if tfmdata and next(tfmdata) then
+ tfmdata.shared = tfmdata.shared or { }
+ tfmdata.unique = tfmdata.unique or { }
+ tfmdata.shared.afmdata = afmdata
+ tfmdata.shared.features = features
+ afm.set_features(tfmdata)
+ end
+ elseif trace_loading then
+ logs.report("load afm","no (valid) afm file found with name %s",afmname)
+ end
+ tfmdata = containers.write(tfm.cache(),cache_id,tfmdata)
+ end
+ return tfmdata
+ end
+end
+
+--[[ldx--
+
As soon as we could intercept the reader, I implemented an
+ reader. Since traditional could use
+fonts with companions, the following method also could handle
+those cases, but now that we can handle directly we no longer
+need this features.
+--ldx]]--
+
+tfm.default_encoding = 'unicode'
+
+function tfm.set_normal_feature(specification,name,value)
+ if specification and name then
+ specification.features = specification.features or { }
+ specification.features.normal = specification.features.normal or { }
+ specification.features.normal[name] = value
+ end
+end
+
+function tfm.read_from_afm(specification)
+ local tfmtable = afm.afm_to_tfm(specification)
+ if tfmtable then
+ tfmtable.name = specification.name
+ tfmtable = tfm.scale(tfmtable, specification.size, specification.relativeid)
+ local afmdata = tfmtable.shared.afmdata
+--~ local filename = afmdata and afmdata.luatex and afmdata.luatex.filename
+--~ if filename then
+--~ tfmtable.encodingbytes = 2
+--~ tfmtable.filename = resolvers.findbinfile(filename,"") or filename
+--~ tfmtable.fontname = afmdata.metadata.fontname or afmdata.metadata.fullname
+--~ tfmtable.fullname = afmdata.metadata.fullname or afmdata.metadata.fontname
+--~ tfmtable.format = 'type1'
+--~ tfmtable.name = afmdata.luatex.filename or tfmtable.fullname
+--~ end
+ if fonts.dontembed[filename] then
+ tfmtable.file = nil -- or filename ?
+ end
+ fonts.logger.save(tfmtable,'afm',specification)
+ end
+ return tfmtable
+end
+
+--[[ldx--
+
Here comes the implementation of a few features. We only implement
+those that make sense for this format.
So far we haven't really dealt with features (or whatever we want
+to pass along with the font definition. We distinguish the following
+situations:
+situations:
+
+
+name:xetex like specs
+name@virtual font spec
+name*context specification
+
+--ldx]]--
+
+function specify.predefined(specification)
+ local detail = specification.detail
+ if detail ~= "" then
+ -- detail = gsub(detail,"["..define.splitsymbols.."].*$","") -- get rid of *whatever specs and such
+ if define.methods[detail] then -- since these may be appended at the
+ specification.features.vtf = { preset = detail } -- tex end by default
+ end
+ end
+ return specification
+end
+
+define.register_split("@", specify.predefined)
+
+storage.register("fonts/setups" , define.specify.context_setups , "fonts.define.specify.context_setups" )
+storage.register("fonts/numbers", define.specify.context_numbers, "fonts.define.specify.context_numbers")
+storage.register("fonts/merged", define.specify.context_merged, "fonts.define.specify.context_merged")
+storage.register("fonts/synonyms", define.specify.synonyms, "fonts.define.specify.synonyms")
+
+local normalize_meanings = fonts.otf.meanings.normalize
+local settings_to_hash = aux.settings_to_hash
+local default_features = fonts.otf.features.default
+
+local function preset_context(name,parent,features) -- currently otf only
+ if features == "" and find(parent,"=") then
+ features = parent
+ parent = ""
+ end
+ if features == "" then
+ features = { }
+ elseif type(features) == "string" then
+ features = normalize_meanings(settings_to_hash(features))
+ else
+ features = normalize_meanings(features)
+ end
+ -- todo: synonyms, and not otf bound
+ if parent ~= "" then
+ for p in gmatch(parent,"[^, ]+") do
+ local s = setups[p]
+ if s then
+ for k,v in next, s do
+ if features[k] == nil then
+ features[k] = v
+ end
+ end
+ end
+ end
+ end
+ -- these are auto set so in order to prevent redundant definitions
+ -- we need to preset them (we hash the features and adding a default
+ -- setting during initialization may result in a different hash)
+ for k,v in next, triggers do
+ if features[v] == nil then -- not false !
+ local vv = default_features[v]
+ if vv then features[v] = vv end
+ end
+ end
+ -- sparse 'm so that we get a better hash and less test (experimental
+ -- optimization)
+ local t = { } -- can we avoid t ?
+ for k,v in next, features do
+ if v then t[k] = v end
+ end
+ -- needed for dynamic features
+ local number = (setups[name] and setups[name].number) or 0
+ if number == 0 then
+ number = #numbers + 1
+ numbers[number] = name
+ end
+ t.number = number
+ setups[name] = t
+ return number, t
+end
+
+local function context_number(name) -- will be replaced
+ local t = setups[name]
+ if not t then
+ return 0
+ elseif t.auto then
+ local lng = tonumber(tex.language)
+ local tag = name .. ":" .. lng
+ local s = setups[tag]
+ if s then
+ return s.number or 0
+ else
+ local script, language = languages.association(lng)
+ if t.script ~= script or t.language ~= language then
+ local s = table.fastcopy(t)
+ local n = #numbers + 1
+ setups[tag] = s
+ numbers[n] = tag
+ s.number = n
+ s.script = script
+ s.language = language
+ return n
+ else
+ setups[tag] = t
+ return t.number or 0
+ end
+ end
+ else
+ return t.number or 0
+ end
+end
+
+local function merge_context(currentnumber,extraname,option)
+ local current = setups[numbers[currentnumber]]
+ local extra = setups[extraname]
+ if extra then
+ local mergedfeatures, mergedname = { }, nil
+ if option < 0 then
+ if current then
+ for k, v in next, current do
+ if not extra[k] then
+ mergedfeatures[k] = v
+ end
+ end
+ end
+ mergedname = currentnumber .. "-" .. extraname
+ else
+ if current then
+ for k, v in next, current do
+ mergedfeatures[k] = v
+ end
+ end
+ for k, v in next, extra do
+ mergedfeatures[k] = v
+ end
+ mergedname = currentnumber .. "+" .. extraname
+ end
+ local number = #numbers + 1
+ mergedfeatures.number = number
+ numbers[number] = mergedname
+ merged[number] = option
+ setups[mergedname] = mergedfeatures
+ return number -- context_number(mergedname)
+ else
+ return currentnumber
+ end
+end
+
+local function register_context(fontnumber,extraname,option)
+ local extra = setups[extraname]
+ if extra then
+ local mergedfeatures, mergedname = { }, nil
+ if option < 0 then
+ mergedname = fontnumber .. "-" .. extraname
+ else
+ mergedname = fontnumber .. "+" .. extraname
+ end
+ for k, v in next, extra do
+ mergedfeatures[k] = v
+ end
+ local number = #numbers + 1
+ mergedfeatures.number = number
+ numbers[number] = mergedname
+ merged[number] = option
+ setups[mergedname] = mergedfeatures
+ return number -- context_number(mergedname)
+ else
+ return 0
+ end
+end
+
+specify.preset_context = preset_context
+specify.context_number = context_number
+specify.merge_context = merge_context
+specify.register_context = register_context
+
+local current_font = font.current
+local tex_attribute = tex.attribute
+
+local cache = { } -- concat might be less efficient than nested tables
+
+function fonts.withset(name,what)
+ local zero = tex_attribute[0]
+ local hash = zero .. "+" .. name .. "*" .. what
+ local done = cache[hash]
+ if not done then
+ done = merge_context(zero,name,what)
+ cache[hash] = done
+ end
+ tex_attribute[0] = done
+end
+function fonts.withfnt(name,what)
+ local font = current_font()
+ local hash = font .. "*" .. name .. "*" .. what
+ local done = cache[hash]
+ if not done then
+ done = register_context(font,name,what)
+ cache[hash] = done
+ end
+ tex_attribute[0] = done
+end
+
+function specify.show_context(name)
+ return setups[name] or setups[numbers[name]] or setups[numbers[tonumber(name)]] or { }
+end
+
+local function split_context(features)
+ return setups[features] or (preset_context(features,"","") and setups[features])
+end
+
+specify.split_context = split_context
+
+function specify.context_tostring(name,kind,separator,yes,no,strict,omit) -- not used
+ return aux.hash_to_string(table.merged(fonts[kind].features.default or {},setups[name] or {}),separator,yes,no,strict,omit)
+end
+
+local splitter = lpeg.splitat(",")
+
+function specify.starred(features) -- no longer fallbacks here
+ local detail = features.detail
+ if detail and detail ~= "" then
+ features.features.normal = split_context(detail)
+ else
+ features.features.normal = { }
+ end
+ return features
+end
+
+define.register_split('*',specify.starred)
+
+-- define (two steps)
+
+local P, C, Cc = lpeg.P, lpeg.C, lpeg.Cc
+
+local space = P(" ")
+local spaces = space^0
+local leftparent = (P"(")
+local rightparent = (P")")
+local value = C((leftparent * (1-rightparent)^0 * rightparent + (1-space))^1)
+local dimension = C((space/"" + P(1))^1)
+local rest = C(P(1)^0)
+local scale_none = Cc(0)
+local scale_at = P("at") * Cc(1) * spaces * dimension -- value
+local scale_sa = P("sa") * Cc(2) * spaces * dimension -- value
+local scale_mo = P("mo") * Cc(3) * spaces * dimension -- value
+local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- value
+
+local sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_scaled + scale_none)
+local splitpattern = spaces * value * spaces * rest
+
+local specification --
+
+local get_specification = define.get_specification
+
+-- we can make helper macros which saves parsing (but normaly not
+-- that many calls, e.g. in mk a couple of 100 and in metafun 3500)
+
+function define.command_1(str)
+ statistics.starttiming(fonts)
+ local fullname, size = lpegmatch(splitpattern,str)
+ local lookup, name, sub, method, detail = get_specification(fullname)
+ if not name then
+ logs.report("define font","strange definition '%s'",str)
+ texsprint(ctxcatcodes,"\\fcglet\\somefontname\\defaultfontfile")
+ elseif name == "unknown" then
+ texsprint(ctxcatcodes,"\\fcglet\\somefontname\\defaultfontfile")
+ else
+ texsprint(ctxcatcodes,"\\fcxdef\\somefontname{",name,"}")
+ end
+ -- we can also use a count for the size
+ if size and size ~= "" then
+ local mode, size = lpegmatch(sizepattern,size)
+ if size and mode then
+ count.scaledfontmode = mode
+ texsprint(ctxcatcodes,"\\def\\somefontsize{",size,"}")
+ else
+ count.scaledfontmode = 0
+ texsprint(ctxcatcodes,"\\let\\somefontsize\\empty")
+ end
+ elseif true then
+ -- so we don't need to check in tex
+ count.scaledfontmode = 2
+ texsprint(ctxcatcodes,"\\let\\somefontsize\\empty")
+ else
+ count.scaledfontmode = 0
+ texsprint(ctxcatcodes,"\\let\\somefontsize\\empty")
+ end
+ specification = define.makespecification(str,lookup,name,sub,method,detail,size)
+end
+
+local n = 0
+
+-- we can also move rscale to here (more consistent)
+
+function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfallbacks,fontfallbacks,mathsize,textsize,relativeid)
+ if trace_defining then
+ logs.report("define font","memory usage before: %s",statistics.memused())
+ end
+ -- name is now resolved and size is scaled cf sa/mo
+ local lookup, name, sub, method, detail = get_specification(str or "")
+ -- asome settings can be overloaded
+ if lookup and lookup ~= "" then
+ specification.lookup = lookup
+ end
+ if relativeid and relativeid ~= "" then -- experimental hook
+ local id = tonumber(relativeid) or 0
+ specification.relativeid = id > 0 and id
+ end
+ specification.name = name
+ specification.size = size
+ specification.sub = (sub and sub ~= "" and sub) or specification.sub
+ specification.mathsize = mathsize
+ specification.textsize = textsize
+ if detail and detail ~= "" then
+ specification.method, specification.detail = method or "*", detail
+ elseif specification.detail and specification.detail ~= "" then
+ -- already set
+ elseif fontfeatures and fontfeatures ~= "" then
+ specification.method, specification.detail = "*", fontfeatures
+ elseif classfeatures and classfeatures ~= "" then
+ specification.method, specification.detail = "*", classfeatures
+ end
+ if fontfallbacks and fontfallbacks ~= "" then
+ specification.fallbacks = fontfallbacks
+ elseif classfallbacks and classfallbacks ~= "" then
+ specification.fallbacks = classfallbacks
+ end
+ local tfmdata = define.read(specification,size) -- id not yet known
+ if not tfmdata then
+ logs.report("define font","unable to define %s as \\%s",name,cs)
+ texsetcount("global","lastfontid",-1)
+ elseif type(tfmdata) == "number" then
+ if trace_defining then
+ logs.report("define font","reusing %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s)",name,tfmdata,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ end
+ tex.definefont(global,cs,tfmdata)
+ -- resolved (when designsize is used):
+ texsprint(ctxcatcodes,format("\\def\\somefontsize{%isp}",fontdata[tfmdata].size))
+ texsetcount("global","lastfontid",tfmdata)
+ else
+ -- local t = os.clock(t)
+ local id = font.define(tfmdata)
+ -- print(name,os.clock()-t)
+ tfmdata.id = id
+ define.register(tfmdata,id)
+ tex.definefont(global,cs,id)
+ tfm.cleanup_table(tfmdata)
+ if trace_defining then
+ logs.report("define font","defining %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s)",name,id,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ end
+ -- resolved (when designsize is used):
+ texsprint(ctxcatcodes,format("\\def\\somefontsize{%isp}",tfmdata.size))
+ --~ if specification.fallbacks then
+ --~ fonts.collections.prepare(specification.fallbacks)
+ --~ end
+ texsetcount("global","lastfontid",id)
+ end
+ if trace_defining then
+ logs.report("define font","memory usage after: %s",statistics.memused())
+ end
+ statistics.stoptiming(fonts)
+end
+
+local enable_auto_r_scale = false
+
+experiments.register("fonts.autorscale", function(v)
+ enable_auto_r_scale = v
+end)
+
+local calculate_scale = fonts.tfm.calculate_scale
+
+function fonts.tfm.calculate_scale(tfmtable, scaledpoints, relativeid)
+ local scaledpoints, delta, units = calculate_scale(tfmtable, scaledpoints, relativeid)
+ if enable_auto_r_scale and relativeid then -- for the moment this is rather context specific
+ local relativedata = fontdata[relativeid]
+ local id_x_height = relativedata and relativedata.parameters and relativedata.parameters.x_height
+ local tf_x_height = id_x_height and tfmtable.parameters and tfmtable.parameters.x_height * delta
+ if tf_x_height then
+ scaledpoints = (id_x_height/tf_x_height) * scaledpoints
+ delta = scaledpoints/units
+ end
+ end
+ return scaledpoints, delta, units
+end
+
+--~ table.insert(readers.sequence,1,'vtf')
+
+--~ function readers.vtf(specification)
+--~ if specification.features.vtf and specification.features.vtf.preset then
+--~ return tfm.make(specification)
+--~ else
+--~ return nil
+--~ end
+--~ end
+
+-- we need a place for this .. outside the generic scope
+
+local dimenfactors = number.dimenfactors
+
+function fonts.dimenfactor(unit,tfmdata)
+ if unit == "ex" then
+ return (tfmdata and tfmdata.parameters.x_height) or 655360
+ elseif unit == "em" then
+ return (tfmdata and tfmdata.parameters.em_height) or 655360
+ else
+ return dimenfactors[unit] or unit
+ end
+end
+
+function fonts.cleanname(name)
+ texsprint(ctxcatcodes,fonts.names.cleanname(name))
+end
+
+local p, f = 1, "%0.1fpt" -- normally this value is changed only once
+
+local stripper = lpeg.patterns.strip_zeros
+
+function fonts.nbfs(amount,precision)
+ if precision ~= p then
+ p = precision
+ f = "%0." .. p .. "fpt"
+ end
+ texsprint(ctxcatcodes,lpegmatch(stripper,format(f,amount/65536)))
+end
+
+-- for the moment here, this will become a chain of extras that is
+-- hooked into the ctx registration (or scaler or ...)
+
+function fonts.set_digit_width(font)
+ local tfmtable = fontdata[font]
+ local parameters = tfmtable.parameters
+ local width = parameters.digitwidth
+ if not width then
+ width = round(parameters.quad/2) -- maybe tex.scale
+ local characters = tfmtable.characters
+ for i=48,57 do
+ local wd = round(characters[i].width)
+ if wd > width then
+ width = wd
+ end
+ end
+ parameters.digitwidth = width
+ end
+ return width
+end
+
+fonts.get_digit_width = fonts.set_digit_width
+
+-- soon to be obsolete:
+
+local loaded = { -- prevent loading (happens in cont-sys files)
+ ["original-base.map" ] = true,
+ ["original-ams-base.map" ] = true,
+ ["original-ams-euler.map"] = true,
+ ["original-public-lm.map"] = true,
+}
+
+function fonts.map.loadfile(name)
+ name = file.addsuffix(name,"map")
+ if not loaded[name] then
+ pdf.mapfile(name)
+ loaded[name] = true
+ end
+end
+
+local loaded = { -- prevent double loading
+}
+
+function fonts.map.loadline(how,line)
+ if line then
+ how = how .. " " .. line
+ elseif how == "" then
+ how = "= " .. line
+ end
+ if not loaded[how] then
+ pdf.mapline(how)
+ loaded[how] = true
+ end
+end
+
+function fonts.map.reset()
+ pdf.mapfile("")
+end
+
+fonts.map.reset() -- resets the default file
+
+-- we need an 'do after the banner hook'
+
+-- pdf.mapfile("mkiv-base.map") -- loads the default file
+
+local nounicode = byte("?")
+
+local function name_to_slot(name) -- maybe some day rawdata
+ local tfmdata = fonts.ids[font.current()]
+ local shared = tfmdata and tfmdata.shared
+ local fntdata = shared and shared.otfdata or shared.afmdata
+ if fntdata then
+ local unicode = fntdata.luatex.unicodes[name]
+ if not unicode then
+ return nounicode
+ elseif type(unicode) == "number" then
+ return unicode
+ else -- multiple unicodes
+ return unicode[1]
+ end
+ end
+ return nounicode
+end
+
+fonts.name_to_slot = name_to_slot
+
+function fonts.char(n) -- todo: afm en tfm
+ if type(n) == "string" then
+ n = name_to_slot(n)
+ end
+ if type(n) == "number" then
+ texsprint(ctxcatcodes,format("\\char%s ",n))
+ end
+end
+
+-- moved from ini:
+
+fonts.color = { } -- dummy in ini
+
+local attribute = attributes.private('color')
+local mapping = (attributes and attributes.list[attribute]) or { }
+
+local set_attribute = node.set_attribute
+local unset_attribute = node.unset_attribute
+
+function fonts.color.set(n,c)
+ local mc = mapping[c]
+ if not mc then
+ unset_attribute(n,attribute)
+ else
+ set_attribute(n,attribute,mc)
+ end
+end
+
+function fonts.color.reset(n)
+ unset_attribute(n,attribute)
+end
+
+-- this will become obsolete:
+
+fonts.otf.name_to_slot = name_to_slot
+fonts.afm.name_to_slot = name_to_slot
+
+fonts.otf.char = fonts.char
+fonts.afm.char = fonts.char
+
+-- this will change ...
+
+function fonts.show_char_data(n)
+ local tfmdata = fonts.ids[font.current()]
+ if tfmdata then
+ if type(n) == "string" then
+ n = utf.byte(n)
+ end
+ local chr = tfmdata.characters[n]
+ if chr then
+ write_nl(format("%s @ %s => U%04X => %s => ",tfmdata.fullname,tfmdata.size,n,utf.char(n)) .. serialize(chr,false))
+ end
+ end
+end
+
+function fonts.show_font_parameters()
+ local tfmdata = fonts.ids[font.current()]
+ if tfmdata then
+ local parameters, mathconstants = tfmdata.parameters, tfmdata.MathConstants
+ local hasparameters, hasmathconstants = parameters and next(parameters), mathconstants and next(mathconstants)
+ if hasparameters then
+ write_nl(format("%s @ %s => parameters => ",tfmdata.fullname,tfmdata.size) .. serialize(parameters,false))
+ end
+ if hasmathconstants then
+ write_nl(format("%s @ %s => math constants => ",tfmdata.fullname,tfmdata.size) .. serialize(mathconstants,false))
+ end
+ if not hasparameters and not hasmathconstants then
+ write_nl(format("%s @ %s => no parameters and/or mathconstants",tfmdata.fullname,tfmdata.size))
+ end
+ end
+end
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua
new file mode 100644
index 000000000..c3b10162c
--- /dev/null
+++ b/tex/context/base/font-def.lua
@@ -0,0 +1,651 @@
+if not modules then modules = { } end modules ['font-def'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, concat, gmatch, match, find, lower = string.format, table.concat, string.gmatch, string.match, string.find, string.lower
+local tostring, next = tostring, next
+local lpegmatch = lpeg.match
+
+local trace_defining = false trackers .register("fonts.defining", function(v) trace_defining = v end)
+local directive_embedall = false directives.register("fonts.embedall", function(v) directive_embedall = v end)
+
+trackers.register("fonts.loading", "fonts.defining", "otf.loading", "afm.loading", "tfm.loading")
+trackers.register("fonts.all", "fonts.*", "otf.*", "afm.*", "tfm.*")
+
+--[[ldx--
+
Here we deal with defining fonts. We do so by intercepting the
+default loader that only handles .
+--ldx]]--
+
+fonts = fonts or { }
+fonts.define = fonts.define or { }
+fonts.tfm = fonts.tfm or { }
+fonts.ids = fonts.ids or { }
+fonts.vf = fonts.vf or { }
+fonts.used = fonts.used or { }
+
+local tfm = fonts.tfm
+local vf = fonts.vf
+local define = fonts.define
+
+tfm.version = 1.01
+tfm.cache = containers.define("fonts", "tfm", tfm.version, false) -- better in font-tfm
+
+define.method = "afm or tfm" -- afm, tfm, afm or tfm, tfm or afm
+define.specify = fonts.define.specify or { }
+define.methods = fonts.define.methods or { }
+
+tfm.fonts = tfm.fonts or { }
+tfm.readers = tfm.readers or { }
+tfm.internalized = tfm.internalized or { } -- internal tex numbers
+
+tfm.readers.sequence = { 'otf', 'ttf', 'afm', 'tfm' }
+
+tfm.auto_afm = true
+
+local readers = tfm.readers
+local sequence = readers.sequence
+
+--[[ldx--
+
We hardly gain anything when we cache the final (pre scaled)
+ table. But it can be handy for debugging.
The following function split the font specification into components
+and prepares a table that will move along as we proceed.
+--ldx]]--
+
+-- beware, we discard additional specs
+--
+-- method:name method:name(sub) method:name(sub)*spec method:name*spec
+-- name name(sub) name(sub)*spec name*spec
+-- name@spec*oeps
+
+local splitter, specifiers = nil, ""
+
+local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc
+
+local left = P("(")
+local right = P(")")
+local colon = P(":")
+local space = P(" ")
+
+define.defaultlookup = "file"
+
+local prefixpattern = P(false)
+
+function define.add_specifier(symbol)
+ specifiers = specifiers .. symbol
+ local method = S(specifiers)
+ local lookup = C(prefixpattern) * colon
+ local sub = left * C(P(1-left-right-method)^1) * right
+ local specification = C(method) * C(P(1)^1)
+ local name = C((1-sub-specification)^1)
+ splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc("")))
+end
+
+function define.add_lookup(str,default)
+ prefixpattern = prefixpattern + P(str)
+end
+
+define.add_lookup("file")
+define.add_lookup("name")
+define.add_lookup("spec")
+
+function define.get_specification(str)
+ return lpegmatch(splitter,str)
+end
+
+function define.register_split(symbol,action)
+ define.add_specifier(symbol)
+ define.specify[symbol] = action
+end
+
+function define.makespecification(specification, lookup, name, sub, method, detail, size)
+ size = size or 655360
+ if trace_defining then
+ logs.report("define font","%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s",
+ specification, (lookup ~= "" and lookup) or "[file]", (name ~= "" and name) or "-",
+ (sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-")
+ end
+--~ if specification.lookup then
+--~ lookup = specification.lookup -- can come from xetex [] syntax
+--~ specification.lookup = nil
+--~ end
+ if not lookup or lookup == "" then
+ lookup = define.defaultlookup
+ end
+ local t = {
+ lookup = lookup, -- forced type
+ specification = specification, -- full specification
+ size = size, -- size in scaled points or -1000*n
+ name = name, -- font or filename
+ sub = sub, -- subfont (eg in ttc)
+ method = method, -- specification method
+ detail = detail, -- specification
+ resolved = "", -- resolved font name
+ forced = "", -- forced loader
+ features = { }, -- preprocessed features
+ }
+ return t
+end
+
+function define.analyze(specification, size)
+ -- can be optimized with locals
+ local lookup, name, sub, method, detail = define.get_specification(specification or "")
+ return define.makespecification(specification, lookup, name, sub, method, detail, size)
+end
+
+--[[ldx--
+
A unique hash value is generated by:
+--ldx]]--
+
+local sortedhashkeys = table.sortedhashkeys
+
+function tfm.hash_features(specification)
+ local features = specification.features
+ if features then
+ local t = { }
+ local normal = features.normal
+ if normal and next(normal) then
+ local f = sortedhashkeys(normal)
+ for i=1,#f do
+ local v = f[i]
+ if v ~= "number" and v ~= "features" then -- i need to figure this out, features
+ t[#t+1] = v .. '=' .. tostring(normal[v])
+ end
+ end
+ end
+ local vtf = features.vtf
+ if vtf and next(vtf) then
+ local f = sortedhashkeys(vtf)
+ for i=1,#f do
+ local v = f[i]
+ t[#t+1] = v .. '=' .. tostring(vtf[v])
+ end
+ end
+--~ if specification.mathsize then
+--~ t[#t+1] = "mathsize=" .. specification.mathsize
+--~ end
+ if #t > 0 then
+ return concat(t,"+")
+ end
+ end
+ return "unknown"
+end
+
+fonts.designsizes = { }
+
+--[[ldx--
+
In principle we can share tfm tables when we are in node for a font, but then
+we need to define a font switch as an id/attr switch which is no fun, so in that
+case users can best use dynamic features ... so, we will not use that speedup. Okay,
+when we get rid of base mode we can optimize even further by sharing, but then we
+loose our testcases for .
+--ldx]]--
+
+function tfm.hash_instance(specification,force)
+ local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks
+ if force or not hash then
+ hash = tfm.hash_features(specification)
+ specification.hash = hash
+ end
+ if size < 1000 and fonts.designsizes[hash] then
+ size = math.round(tfm.scaled(size, fonts.designsizes[hash]))
+ specification.size = size
+ end
+--~ local mathsize = specification.mathsize or 0
+--~ if mathsize > 0 then
+--~ local textsize = specification.textsize
+--~ if fallbacks then
+--~ return hash .. ' @ ' .. tostring(size) .. ' [ ' .. tostring(mathsize) .. ' : ' .. tostring(textsize) .. ' ] @ ' .. fallbacks
+--~ else
+--~ return hash .. ' @ ' .. tostring(size) .. ' [ ' .. tostring(mathsize) .. ' : ' .. tostring(textsize) .. ' ]'
+--~ end
+--~ else
+ if fallbacks then
+ return hash .. ' @ ' .. tostring(size) .. ' @ ' .. fallbacks
+ else
+ return hash .. ' @ ' .. tostring(size)
+ end
+--~ end
+end
+
+--[[ldx--
+
We can resolve the filename using the next function:
+--ldx]]--
+
+define.resolvers = resolvers
+
+function define.resolvers.file(specification)
+ specification.forced = file.extname(specification.name)
+ specification.name = file.removesuffix(specification.name)
+end
+
+function define.resolvers.name(specification)
+ local resolve = fonts.names.resolve
+ if resolve then
+ specification.resolved, specification.sub = fonts.names.resolve(specification.name,specification.sub)
+ if specification.resolved then
+ specification.forced = file.extname(specification.resolved)
+ specification.name = file.removesuffix(specification.resolved)
+ end
+ else
+ define.resolvers.file(specification)
+ end
+end
+
+function define.resolvers.spec(specification)
+ local resolvespec = fonts.names.resolvespec
+ if resolvespec then
+ specification.resolved, specification.sub = fonts.names.resolvespec(specification.name,specification.sub)
+ if specification.resolved then
+ specification.forced = file.extname(specification.resolved)
+ specification.name = file.removesuffix(specification.resolved)
+ end
+ else
+ define.resolvers.name(specification)
+ end
+end
+
+function define.resolve(specification)
+ if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash
+ local r = define.resolvers[specification.lookup]
+ if r then
+ r(specification)
+ end
+ end
+ if specification.forced == "" then
+ specification.forced = nil
+ else
+ specification.forced = specification.forced
+ end
+ specification.hash = lower(specification.name .. ' @ ' .. tfm.hash_features(specification))
+ if specification.sub and specification.sub ~= "" then
+ specification.hash = specification.sub .. ' @ ' .. specification.hash
+ end
+ return specification
+end
+
+--[[ldx--
+
The main read function either uses a forced reader (as determined by
+a lookup) or tries to resolve the name using the list of readers.
+
+
We need to cache when possible. We do cache raw tfm data (from , or ). After that we can cache based
+on specificstion (name) and size, that is, only needs a number
+for an already loaded fonts. However, it may make sense to cache fonts
+before they're scaled as well (store 's with applied methods
+and features). However, there may be a relation between the size and
+features (esp in virtual fonts) so let's not do that now.
+
+
Watch out, here we do load a font, but we don't prepare the
+specification yet.
+--ldx]]--
+
+function tfm.read(specification)
+ local hash = tfm.hash_instance(specification)
+ local tfmtable = tfm.fonts[hash] -- hashes by size !
+ if not tfmtable then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ tfmtable = readers[lower(forced)](specification)
+ if not tfmtable then
+ logs.report("define font","forced type %s of %s not found",forced,specification.name)
+ end
+ else
+ for s=1,#sequence do -- reader sequence
+ local reader = sequence[s]
+ if readers[reader] then -- not really needed
+ if trace_defining then
+ logs.report("define font","trying (reader sequence driven) type %s for %s with file %s",reader,specification.name,specification.filename or "unknown")
+ end
+ tfmtable = readers[reader](specification)
+ if tfmtable then
+ break
+ else
+ specification.filename = nil
+ end
+ end
+ end
+ end
+ if tfmtable then
+ if directive_embedall then
+ tfmtable.embedding = "full"
+ elseif tfmtable.filename and fonts.dontembed[tfmtable.filename] then
+ tfmtable.embedding = "no"
+ else
+ tfmtable.embedding = "subset"
+ end
+ tfm.fonts[hash] = tfmtable
+ fonts.designsizes[specification.hash] = tfmtable.designsize -- we only know this for sure after loading once
+ --~ tfmtable.mode = specification.features.normal.mode or "base"
+ end
+ end
+ if not tfmtable then
+ logs.report("define font","font with name %s is not found",specification.name)
+ end
+ return tfmtable
+end
+
+--[[ldx--
+
For virtual fonts we need a slightly different approach:
+--ldx]]--
+
+function tfm.read_and_define(name,size) -- no id
+ local specification = define.analyze(name,size)
+ local method = specification.method
+ if method and define.specify[method] then
+ specification = define.specify[method](specification)
+ end
+ specification = define.resolve(specification)
+ local hash = tfm.hash_instance(specification)
+ local id = define.registered(hash)
+ if not id then
+ local fontdata = tfm.read(specification)
+ if fontdata then
+ fontdata.hash = hash
+ id = font.define(fontdata)
+ define.register(fontdata,id)
+ tfm.cleanup_table(fontdata)
+ else
+ id = 0 -- signal
+ end
+ end
+ return fonts.ids[id], id
+end
+
+--[[ldx--
+
Next follow the readers. This code was written while
+evolved. Each one has its own way of dealing with its format.
+--ldx]]--
+
+local function check_tfm(specification,fullname)
+ -- ofm directive blocks local path search unless set; btw, in context we
+ -- don't support ofm files anyway as this format is obsolete
+ local foundname = resolvers.findbinfile(fullname, 'tfm') or "" -- just to be sure
+ if foundname == "" then
+ foundname = resolvers.findbinfile(fullname, 'ofm') or "" -- bonus for usage outside context
+ end
+ if foundname ~= "" then
+ specification.filename, specification.format = foundname, "ofm"
+ return tfm.read_from_tfm(specification)
+ end
+end
+
+local function check_afm(specification,fullname)
+ local foundname = resolvers.findbinfile(fullname, 'afm') or "" -- just to be sure
+ if foundname == "" and tfm.auto_afm then
+ local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
+ if encoding and shortname and fonts.enc.known[encoding] then
+ shortname = resolvers.findbinfile(shortname,'afm') or "" -- just to be sure
+ if shortname ~= "" then
+ foundname = shortname
+ -- tfm.set_normal_feature(specification,'encoding',encoding) -- will go away
+ if trace_loading then
+ logs.report("load afm","stripping encoding prefix from filename %s",afmname)
+ end
+ end
+ end
+ end
+ if foundname ~= "" then
+ specification.filename, specification.format = foundname, "afm"
+ return tfm.read_from_afm(specification)
+ end
+end
+
+function readers.tfm(specification)
+ local fullname, tfmtable = specification.filename or "", nil
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ tfmtable = check_tfm(specification,specification.name .. "." .. forced)
+ end
+ if not tfmtable then
+ tfmtable = check_tfm(specification,specification.name)
+ end
+ else
+ tfmtable = check_tfm(specification,fullname)
+ end
+ return tfmtable
+end
+
+function readers.afm(specification,method)
+ local fullname, tfmtable = specification.filename or "", nil
+ if fullname == "" then
+ local forced = specification.forced or ""
+ if forced ~= "" then
+ tfmtable = check_afm(specification,specification.name .. "." .. forced)
+ end
+ if not tfmtable then
+ method = method or define.method or "afm or tfm"
+ if method == "tfm" then
+ tfmtable = check_tfm(specification,specification.name)
+ elseif method == "afm" then
+ tfmtable = check_afm(specification,specification.name)
+ elseif method == "tfm or afm" then
+ tfmtable = check_tfm(specification,specification.name) or check_afm(specification,specification.name)
+ else -- method == "afm or tfm" or method == "" then
+ tfmtable = check_afm(specification,specification.name) or check_tfm(specification,specification.name)
+ end
+ end
+ else
+ tfmtable = check_afm(specification,fullname)
+ end
+ return tfmtable
+end
+
+-- maybe some day a set of names
+
+local function check_otf(forced,specification,suffix,what)
+ local name = specification.name
+ if forced then
+ name = file.addsuffix(name,suffix)
+ end
+ local fullname, tfmtable = resolvers.findbinfile(name,suffix) or "", nil -- one shot
+ if fullname == "" then
+ local fb = fonts.names.old_to_new[name]
+ if fb then
+ fullname = resolvers.findbinfile(fb,suffix) or ""
+ end
+ end
+ if fullname == "" then
+ local fb = fonts.names.new_to_old[name]
+ if fb then
+ fullname = resolvers.findbinfile(fb,suffix) or ""
+ end
+ end
+ if fullname ~= "" then
+ specification.filename, specification.format = fullname, what -- hm, so we do set the filename, then
+ tfmtable = tfm.read_from_open_type(specification) -- we need to do it for all matches / todo
+ end
+ return tfmtable
+end
+
+function readers.opentype(specification,suffix,what)
+ local forced = specification.forced or ""
+ if forced == "otf" then
+ return check_otf(true,specification,forced,"opentype")
+ elseif forced == "ttf" or forced == "ttc" or forced == "dfont" then
+ return check_otf(true,specification,forced,"truetype")
+ else
+ return check_otf(false,specification,suffix,what)
+ end
+end
+
+function readers.otf (specification) return readers.opentype(specification,"otf","opentype") end
+function readers.ttf (specification) return readers.opentype(specification,"ttf","truetype") end
+function readers.ttc (specification) return readers.opentype(specification,"ttf","truetype") end -- !!
+function readers.dfont(specification) return readers.opentype(specification,"ttf","truetype") end -- !!
+
+--[[ldx--
+
We need to check for default features. For this we provide
+a helper function.
+--ldx]]--
+
+function define.check(features,defaults) -- nb adapts features !
+ local done = false
+ if features and next(features) then
+ for k,v in next, defaults do
+ if features[k] == nil then
+ features[k], done = v, true
+ end
+ end
+ else
+ features, done = table.fastcopy(defaults), true
+ end
+ return features, done -- done signals a change
+end
+
+--[[ldx--
+
So far the specifyers. Now comes the real definer. Here we cache
+based on id's. Here we also intercept the virtual font handler. Since
+it evolved stepwise I may rewrite this bit (combine code).
+
+In the previously defined reader (the one resulting in a
+table) we cached the (scaled) instances. Here we cache them again, but
+this time based on id. We could combine this in one cache but this does
+not gain much. By the way, passing id's back to in the callback was
+introduced later in the development.
+--ldx]]--
+
+define.last = nil
+
+function define.register(fontdata,id)
+ if fontdata and id then
+ local hash = fontdata.hash
+ if not tfm.internalized[hash] then
+ if trace_defining then
+ logs.report("define font","loading at 2 id %s, hash: %s",id or "?",hash or "?")
+ end
+ fonts.identifiers[id] = fontdata
+ fonts.characters [id] = fontdata.characters
+ fonts.quads [id] = fontdata.parameters.quad
+ -- todo: extra functions, e.g. setdigitwidth etc in list
+ tfm.internalized[hash] = id
+ end
+ end
+end
+
+function define.registered(hash)
+ local id = tfm.internalized[hash]
+ return id, id and fonts.ids[id]
+end
+
+local cache_them = false
+
+function tfm.make(specification)
+ -- currently fonts are scaled while constructing the font, so we
+ -- have to do scaling of commands in the vf at that point using
+ -- e.g. "local scale = g.factor or 1" after all, we need to work
+ -- with copies anyway and scaling needs to be done at some point;
+ -- however, when virtual tricks are used as feature (makes more
+ -- sense) we scale the commands in fonts.tfm.scale (and set the
+ -- factor there)
+ local fvm = define.methods[specification.features.vtf.preset]
+ if fvm then
+ return fvm(specification)
+ else
+ return nil
+ end
+end
+
+function define.read(specification,size,id) -- id can be optional, name can already be table
+ statistics.starttiming(fonts)
+ if type(specification) == "string" then
+ specification = define.analyze(specification,size)
+ end
+ local method = specification.method
+ if method and define.specify[method] then
+ specification = define.specify[method](specification)
+ end
+ specification = define.resolve(specification)
+ local hash = tfm.hash_instance(specification)
+ if cache_them then
+ local fontdata = containers.read(fonts.cache(),hash) -- for tracing purposes
+ end
+ local fontdata = define.registered(hash) -- id
+ if not fontdata then
+ if specification.features.vtf and specification.features.vtf.preset then
+ fontdata = tfm.make(specification)
+ else
+ fontdata = tfm.read(specification)
+ if fontdata then
+ tfm.check_virtual_id(fontdata)
+ end
+ end
+ if cache_them then
+ fontdata = containers.write(fonts.cache(),hash,fontdata) -- for tracing purposes
+ end
+ if fontdata then
+ fontdata.hash = hash
+ fontdata.cache = "no"
+ if id then
+ define.register(fontdata,id)
+ end
+ end
+ end
+ define.last = fontdata or id -- todo ! ! ! ! !
+ if not fontdata then
+ logs.report("define font", "unknown font %s, loading aborted",specification.name)
+ elseif trace_defining and type(fontdata) == "table" then
+ logs.report("define font","using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s",
+ fontdata.type or "unknown",
+ id or "?",
+ fontdata.name or "?",
+ fontdata.size or "default",
+ fontdata.encodingbytes or "?",
+ fontdata.encodingname or "unicode",
+ fontdata.fullname or "?",
+ file.basename(fontdata.filename or "?"))
+
+ end
+ statistics.stoptiming(fonts)
+ return fontdata
+end
+
+function vf.find(name)
+ name = file.removesuffix(file.basename(name))
+ if tfm.resolve_vf then
+ local format = fonts.logger.format(name)
+ if format == 'tfm' or format == 'ofm' then
+ if trace_defining then
+ logs.report("define font","locating vf for %s",name)
+ end
+ return resolvers.findbinfile(name,"ovf")
+ else
+ if trace_defining then
+ logs.report("define font","vf for %s is already taken care of",name)
+ end
+ return nil -- ""
+ end
+ else
+ if trace_defining then
+ logs.report("define font","locating vf for %s",name)
+ end
+ return resolvers.findbinfile(name,"ovf")
+ end
+end
+
+--[[ldx--
+
We overload both the and readers.
+--ldx]]--
+
+callbacks.register('define_font' , define.read, "definition of fonts (tfmtable preparation)")
+callbacks.register('find_vf_file', vf.find , "locating virtual fonts, insofar needed") -- not that relevant any more
diff --git a/tex/context/base/font-dum.lua b/tex/context/base/font-dum.lua
new file mode 100644
index 000000000..0a9bcd301
--- /dev/null
+++ b/tex/context/base/font-dum.lua
@@ -0,0 +1,301 @@
+if not modules then modules = { } end modules ['font-dum'] = {
+ version = 1.001,
+ comment = "companion to luatex-*.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+fonts = fonts or { }
+
+-- general
+
+fonts.otf.pack = false -- only makes sense in context
+fonts.tfm.resolve_vf = false -- no sure about this
+fonts.tfm.fontname_mode = "specification" -- somehow latex needs this
+
+-- readers
+
+fonts.tfm.readers = fonts.tfm.readers or { }
+fonts.tfm.readers.sequence = { 'otf', 'ttf', 'tfm' }
+fonts.tfm.readers.afm = nil
+
+-- define
+
+fonts.define = fonts.define or { }
+
+--~ fonts.define.method = "tfm"
+
+fonts.define.specify.colonized_default_lookup = "name"
+
+function fonts.define.get_specification(str)
+ return "", str, "", ":", str
+end
+
+-- logger
+
+fonts.logger = fonts.logger or { }
+
+function fonts.logger.save()
+end
+
+-- names
+--
+-- Watch out, the version number is the same as the one used in
+-- the mtx-fonts.lua function scripts.fonts.names as we use a
+-- simplified font database in the plain solution and by using
+-- a different number we're less dependent on context.
+
+fonts.names = fonts.names or { }
+
+fonts.names.version = 1.001 -- not the same as in context
+fonts.names.basename = "luatex-fonts-names.lua"
+fonts.names.new_to_old = { }
+fonts.names.old_to_new = { }
+
+local data, loaded = nil, false
+
+local fileformats = { "lua", "tex", "other text files" }
+
+function fonts.names.resolve(name,sub)
+ if not loaded then
+ local basename = fonts.names.basename
+ if basename and basename ~= "" then
+ for i=1,#fileformats do
+ local format = fileformats[i]
+ local foundname = resolvers.find_file(basename,format) or ""
+ if foundname ~= "" then
+ data = dofile(foundname)
+ break
+ end
+ end
+ end
+ loaded = true
+ end
+ if type(data) == "table" and data.version == fonts.names.version then
+ local condensed = string.gsub(string.lower(name),"[^%a%d]","")
+ local found = data.mappings and data.mappings[condensed]
+ if found then
+ local fontname, filename, subfont = found[1], found[2], found[3]
+ if subfont then
+ return filename, fontname
+ else
+ return filename, false
+ end
+ else
+ return name, false -- fallback to filename
+ end
+ end
+end
+
+fonts.names.resolvespec = fonts.names.resolve -- only supported in mkiv
+
+-- For the moment we put this (adapted) pseudo feature here.
+
+table.insert(fonts.triggers,"itlc")
+
+local function itlc(tfmdata,value)
+ if value then
+ -- the magic 40 and it formula come from Dohyun Kim
+ local metadata = tfmdata.shared.otfdata.metadata
+ if metadata then
+ local italicangle = metadata.italicangle
+ if italicangle and italicangle ~= 0 then
+ local uwidth = (metadata.uwidth or 40)/2
+ for unicode, d in next, tfmdata.descriptions do
+ local it = d.boundingbox[3] - d.width + uwidth
+ if it ~= 0 then
+ d.italic = it
+ end
+ end
+ tfmdata.has_italic = true
+ end
+ end
+ end
+end
+
+fonts.initializers.base.otf.itlc = itlc
+fonts.initializers.node.otf.itlc = itlc
+
+-- slant and extend
+
+function fonts.initializers.common.slant(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 1 then
+ value = 1
+ elseif value < -1 then
+ value = -1
+ end
+ tfmdata.slant_factor = value
+end
+
+function fonts.initializers.common.extend(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 10 then
+ value = 10
+ elseif value < -10 then
+ value = -10
+ end
+ tfmdata.extend_factor = value
+end
+
+table.insert(fonts.triggers,"slant")
+table.insert(fonts.triggers,"extend")
+
+fonts.initializers.base.otf.slant = fonts.initializers.common.slant
+fonts.initializers.node.otf.slant = fonts.initializers.common.slant
+fonts.initializers.base.otf.extend = fonts.initializers.common.extend
+fonts.initializers.node.otf.extend = fonts.initializers.common.extend
+
+-- expansion and protrusion
+
+fonts.protrusions = fonts.protrusions or { }
+fonts.protrusions.setups = fonts.protrusions.setups or { }
+
+local setups = fonts.protrusions.setups
+
+function fonts.initializers.common.protrusion(tfmdata,value)
+ if value then
+ local setup = setups[value]
+ if setup then
+ local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1
+ local emwidth = tfmdata.parameters.quad
+ tfmdata.auto_protrude = true
+ for i, chr in next, tfmdata.characters do
+ local v, pl, pr = setup[i], nil, nil
+ if v then
+ pl, pr = v[1], v[2]
+ end
+ if pl and pl ~= 0 then chr.left_protruding = left *pl*factor end
+ if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end
+ end
+ end
+ end
+end
+
+fonts.expansions = fonts.expansions or { }
+fonts.expansions.setups = fonts.expansions.setups or { }
+
+local setups = fonts.expansions.setups
+
+function fonts.initializers.common.expansion(tfmdata,value)
+ if value then
+ local setup = setups[value]
+ if setup then
+ local stretch, shrink, step, factor = setup.stretch or 0, setup.shrink or 0, setup.step or 0, setup.factor or 1
+ tfmdata.stretch, tfmdata.shrink, tfmdata.step, tfmdata.auto_expand = stretch * 10, shrink * 10, step * 10, true
+ for i, chr in next, tfmdata.characters do
+ local v = setup[i]
+ if v and v ~= 0 then
+ chr.expansion_factor = v*factor
+ else -- can be option
+ chr.expansion_factor = factor
+ end
+ end
+ end
+ end
+end
+
+table.insert(fonts.manipulators,"protrusion")
+table.insert(fonts.manipulators,"expansion")
+
+fonts.initializers.base.otf.protrusion = fonts.initializers.common.protrusion
+fonts.initializers.node.otf.protrusion = fonts.initializers.common.protrusion
+fonts.initializers.base.otf.expansion = fonts.initializers.common.expansion
+fonts.initializers.node.otf.expansion = fonts.initializers.common.expansion
+
+-- left over
+
+function fonts.register_message()
+end
+
+-- example vectors
+
+local byte = string.byte
+
+fonts.expansions.setups['default'] = {
+
+ stretch = 2, shrink = 2, step = .5, factor = 1,
+
+ [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
+ [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
+ [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
+ [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
+ [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
+ [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
+ [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
+ [byte('w')] = 0.7, [byte('z')] = 0.7,
+ [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
+}
+
+fonts.protrusions.setups['default'] = {
+
+ factor = 1, left = 1, right = 1,
+
+ [0x002C] = { 0, 1 }, -- comma
+ [0x002E] = { 0, 1 }, -- period
+ [0x003A] = { 0, 1 }, -- colon
+ [0x003B] = { 0, 1 }, -- semicolon
+ [0x002D] = { 0, 1 }, -- hyphen
+ [0x2013] = { 0, 0.50 }, -- endash
+ [0x2014] = { 0, 0.33 }, -- emdash
+ [0x3001] = { 0, 1 }, -- ideographic comma 、
+ [0x3002] = { 0, 1 }, -- ideographic full stop 。
+ [0x060C] = { 0, 1 }, -- arabic comma ،
+ [0x061B] = { 0, 1 }, -- arabic semicolon ؛
+ [0x06D4] = { 0, 1 }, -- arabic full stop ۔
+
+}
+
+-- normalizer
+
+fonts.otf.meanings = fonts.otf.meanings or { }
+
+fonts.otf.meanings.normalize = fonts.otf.meanings.normalize or function(t)
+ if t.rand then
+ t.rand = "random"
+ end
+end
+
+-- bonus
+
+function fonts.otf.name_to_slot(name)
+ local tfmdata = fonts.ids[font.current()]
+ if tfmdata and tfmdata.shared then
+ local otfdata = tfmdata.shared.otfdata
+ local unicode = otfdata.luatex.unicodes[name]
+ return unicode and (type(unicode) == "number" and unicode or unicode[1])
+ end
+end
+
+function fonts.otf.char(n)
+ if type(n) == "string" then
+ n = fonts.otf.name_to_slot(n)
+ end
+ if type(n) == "number" then
+ tex.sprint("\\char" .. n)
+ end
+end
+
+-- another one:
+
+fonts.strippables = table.tohash {
+ 0x000AD, 0x017B4, 0x017B5, 0x0200B, 0x0200C, 0x0200D, 0x0200E, 0x0200F, 0x0202A, 0x0202B,
+ 0x0202C, 0x0202D, 0x0202E, 0x02060, 0x02061, 0x02062, 0x02063, 0x0206A, 0x0206B, 0x0206C,
+ 0x0206D, 0x0206E, 0x0206F, 0x0FEFF, 0x1D173, 0x1D174, 0x1D175, 0x1D176, 0x1D177, 0x1D178,
+ 0x1D179, 0x1D17A, 0xE0001, 0xE0020, 0xE0021, 0xE0022, 0xE0023, 0xE0024, 0xE0025, 0xE0026,
+ 0xE0027, 0xE0028, 0xE0029, 0xE002A, 0xE002B, 0xE002C, 0xE002D, 0xE002E, 0xE002F, 0xE0030,
+ 0xE0031, 0xE0032, 0xE0033, 0xE0034, 0xE0035, 0xE0036, 0xE0037, 0xE0038, 0xE0039, 0xE003A,
+ 0xE003B, 0xE003C, 0xE003D, 0xE003E, 0xE003F, 0xE0040, 0xE0041, 0xE0042, 0xE0043, 0xE0044,
+ 0xE0045, 0xE0046, 0xE0047, 0xE0048, 0xE0049, 0xE004A, 0xE004B, 0xE004C, 0xE004D, 0xE004E,
+ 0xE004F, 0xE0050, 0xE0051, 0xE0052, 0xE0053, 0xE0054, 0xE0055, 0xE0056, 0xE0057, 0xE0058,
+ 0xE0059, 0xE005A, 0xE005B, 0xE005C, 0xE005D, 0xE005E, 0xE005F, 0xE0060, 0xE0061, 0xE0062,
+ 0xE0063, 0xE0064, 0xE0065, 0xE0066, 0xE0067, 0xE0068, 0xE0069, 0xE006A, 0xE006B, 0xE006C,
+ 0xE006D, 0xE006E, 0xE006F, 0xE0070, 0xE0071, 0xE0072, 0xE0073, 0xE0074, 0xE0075, 0xE0076,
+ 0xE0077, 0xE0078, 0xE0079, 0xE007A, 0xE007B, 0xE007C, 0xE007D, 0xE007E, 0xE007F,
+}
+
diff --git a/tex/context/base/font-enc.lua b/tex/context/base/font-enc.lua
new file mode 100644
index 000000000..874f7c3f4
--- /dev/null
+++ b/tex/context/base/font-enc.lua
@@ -0,0 +1,122 @@
+if not modules then modules = { } end modules ['font-enc'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local match, gmatch, gsub = string.match, string.gmatch, string.gsub
+
+--[[ldx--
+
Because encodings are going to disappear, we don't bother defining
+them in tables. But we may do so some day, for consistency.
Beware! The generic encoding files don't always apply to the ones that
+ship with fonts. This has to do with the fact that names follow (slightly)
+different standards. However, the fonts where this applies to (for instance
+Latin Modern or Gyre) come in OpenType variants too, so these
+will be used.
+--ldx]]--
+
+function fonts.enc.load(filename)
+ local name = file.removesuffix(filename)
+ local data = containers.read(fonts.enc.cache(),name)
+ if data then
+ return data
+ end
+ if name == "unicode" then
+ data = fonts.enc.make_unicode_vector() -- special case, no tex file for this
+ end
+ if data then
+ return data
+ end
+ local vector, tag, hash, unicodes = { }, "", { }, { }
+ local foundname = resolvers.find_file(filename,'enc')
+ if foundname and foundname ~= "" then
+ local ok, encoding, size = resolvers.loadbinfile(foundname)
+ if ok and encoding then
+ local enccodes = characters.enccodes
+ encoding = gsub(encoding,"%%(.-)\n","")
+ local tag, vec = match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
+ local i = 0
+ for ch in gmatch(vec,"/([%a%d%.]+)") do
+ if ch ~= ".notdef" then
+ vector[i] = ch
+ if not hash[ch] then
+ hash[ch] = i
+ else
+ -- duplicate, play safe for tex ligs and take first
+ end
+ if enccodes[ch] then
+ unicodes[enccodes[ch]] = i
+ end
+ end
+ i = i + 1
+ end
+ end
+ end
+ local data = {
+ name=name,
+ tag=tag,
+ vector=vector,
+ hash=hash,
+ unicodes=unicodes
+ }
+ return containers.write(fonts.enc.cache(), name, data)
+end
+
+--[[ldx--
+
There is no unicode encoding but for practical purposed we define
+one.
+--ldx]]--
+
+-- maybe make this a function:
+
+function fonts.enc.make_unicode_vector()
+ local vector, hash = { }, { }
+ for code, v in next, characters.data do
+ local name = v.adobename
+ if name then
+ vector[code], hash[name] = name, code
+ else
+ vector[code] = '.notdef'
+ end
+ end
+ for name, code in next, characters.synonyms do
+ vector[code], hash[name] = name, code
+ end
+ return containers.write(fonts.enc.cache(), 'unicode', { name='unicode', tag='unicode', vector=vector, hash=hash })
+end
diff --git a/tex/context/base/font-enh.lua b/tex/context/base/font-enh.lua
new file mode 100644
index 000000000..fc70c04c5
--- /dev/null
+++ b/tex/context/base/font-enh.lua
@@ -0,0 +1,201 @@
+if not modules then modules = { } end modules ['font-enh'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, match = next, string.match
+
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+-- tfmdata has also fast access to indices and unicodes
+-- to be checked: otf -> tfm -> tfmscaled
+--
+-- watch out: no negative depths and negative eights permitted in regular fonts
+
+--[[ldx--
+
The next function encapsulates the standard loader as
+supplied by .
+--ldx]]--
+
+-- auto complete font with missing composed characters
+
+table.insert(fonts.manipulators,"compose")
+
+function fonts.initializers.common.compose(tfmdata,value)
+ if value then
+ fonts.vf.aux.compose_characters(tfmdata)
+ end
+end
+
+-- tfm features, experimental
+
+tfm.features = tfm.features or { }
+tfm.features.list = tfm.features.list or { }
+tfm.features.default = tfm.features.default or { }
+
+function tfm.enhance(tfmdata,specification)
+ -- we don't really share tfm data because we always reload
+ -- but this is more in sycn with afm and such
+ local features = (specification.features and specification.features.normal ) or { }
+ tfmdata.shared = tfmdata.shared or { }
+ tfmdata.shared.features = features
+ -- tfmdata.shared.tfmdata = tfmdata -- circular
+ tfmdata.filename = specification.name
+ if not features.encoding then
+ local name, size = specification.name, specification.size
+ local encoding, filename = match(name,"^(.-)%-(.*)$") -- context: encoding-name.*
+ if filename and encoding and fonts.enc.known[encoding] then
+ features.encoding = encoding
+ end
+ end
+ tfm.set_features(tfmdata)
+end
+
+function tfm.set_features(tfmdata)
+ -- todo: no local functions
+ local shared = tfmdata.shared
+-- local tfmdata = shared.tfmdata
+ local features = shared.features
+ if features and next(features) then
+ local mode = tfmdata.mode or fonts.mode
+ local fi = fonts.initializers[mode]
+ if fi and fi.tfm then
+ local function initialize(list) -- using tex lig and kerning
+ if list then
+ for i=1,#list do
+ local f = list[i]
+ local value = features[f]
+ if value and fi.tfm[f] then -- brr
+ if tfm.trace_features then
+ logs.report("define font","initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown')
+ end
+ fi.tfm[f](tfmdata,value)
+ mode = tfmdata.mode or fonts.mode
+ fi = fonts.initializers[mode]
+ end
+ end
+ end
+ end
+ initialize(fonts.triggers)
+ initialize(tfm.features.list)
+ initialize(fonts.manipulators)
+ end
+ local fm = fonts.methods[mode]
+ if fm and fm.tfm then
+ local function register(list) -- node manipulations
+ if list then
+ for i=1,#list do
+ local f = list[i]
+ if features[f] and fm.tfm[f] then -- brr
+ if not shared.processors then -- maybe also predefine
+ shared.processors = { fm.tfm[f] }
+ else
+ shared.processors[#shared.processors+1] = fm.tfm[f]
+ end
+ end
+ end
+ end
+ end
+ register(tfm.features.list)
+ end
+ end
+end
+
+function tfm.features.register(name,default)
+ tfm.features.list[#tfm.features.list+1] = name
+ tfm.features.default[name] = default
+end
+
+function tfm.reencode(tfmdata,encoding)
+ if encoding and fonts.enc.known[encoding] then
+ local data = fonts.enc.load(encoding)
+ if data then
+ local characters, original, vector = tfmdata.characters, { }, data.vector
+ tfmdata.encoding = encoding -- not needed
+ for k, v in next, characters do
+ v.name, v.index, original[k] = vector[k], k, v
+ end
+ for k,v in next, data.unicodes do
+ if k ~= v then
+ if trace_defining then
+ logs.report("define font","reencoding U+%04X to U+%04X",k,v)
+ end
+ characters[k] = original[v]
+ end
+ end
+ end
+ end
+end
+
+tfm.features.register('reencode')
+
+fonts.initializers.base.tfm.reencode = tfm.reencode
+fonts.initializers.node.tfm.reencode = tfm.reencode
+
+fonts.enc = fonts.enc or { }
+fonts.enc.remappings = fonts.enc.remappings or { }
+
+function tfm.remap(tfmdata,remapping)
+ local vector = remapping and fonts.enc.remappings[remapping]
+ if vector then
+ local characters, original = tfmdata.characters, { }
+ for k, v in next, characters do
+ original[k], characters[k] = v, nil
+ end
+ for k,v in next, vector do
+ if k ~= v then
+ if trace_defining then
+ logs.report("define font","remapping U+%04X to U+%04X",k,v)
+ end
+ local c = original[k]
+ characters[v] = c
+ c.index = k
+ end
+ end
+ tfmdata.encodingbytes = 2
+ tfmdata.format = 'type1'
+ end
+end
+
+tfm.features.register('remap')
+
+fonts.initializers.base.tfm.remap = tfm.remap
+fonts.initializers.node.tfm.remap = tfm.remap
+
+--~ obsolete
+--~
+--~ function tfm.enhance(tfmdata,specification)
+--~ local name, size = specification.name, specification.size
+--~ local encoding, filename = match(name,"^(.-)%-(.*)$") -- context: encoding-name.*
+--~ if filename and encoding and fonts.enc.known[encoding] then
+--~ local data = fonts.enc.load(encoding)
+--~ if data then
+--~ local characters = tfmdata.characters
+--~ tfmdata.encoding = encoding
+--~ local vector = data.vector
+--~ local original = { }
+--~ for k, v in next, characters do
+--~ v.name = vector[k]
+--~ v.index = k
+--~ original[k] = v
+--~ end
+--~ for k,v in next, data.unicodes do
+--~ if k ~= v then
+--~ if trace_defining then
+--~ logs.report("define font","mapping %s onto %s",k,v)
+--~ end
+--~ characters[k] = original[v]
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua
new file mode 100644
index 000000000..05bdaf2fc
--- /dev/null
+++ b/tex/context/base/font-ext.lua
@@ -0,0 +1,623 @@
+if not modules then modules = { } end modules ['font-ext'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+local next, type, byte = next, type, string.byte
+local gmatch, concat = string.gmatch, table.concat
+local utfchar = utf.char
+
+local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end)
+local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end)
+
+commands = commands or { }
+
+--[[ldx--
+
When we implement functions that deal with features, most of them
+will depend of the font format. Here we define the few that are kind
+of neutral.
+--ldx]]--
+
+fonts.triggers = fonts.triggers or { }
+fonts.initializers = fonts.initializers or { }
+fonts.methods = fonts.methods or { }
+fonts.initializers.common = fonts.initializers.common or { }
+
+local initializers = fonts.initializers
+local methods = fonts.methods
+
+--[[ldx--
+
This feature will remove inter-digit kerns.
+--ldx]]--
+
+table.insert(fonts.triggers,"equaldigits")
+
+function initializers.common.equaldigits(tfmdata,value)
+ if value then
+ local chr = tfmdata.characters
+ for i = utfbyte('0'), utfbyte('9') do
+ local c = chr[i]
+ if c then
+ c.kerns = nil
+ end
+ end
+ end
+end
+
+--[[ldx--
+
This feature will give all glyphs an equal height and/or depth. Valid
+values are none, height, depth and
+both.
+--ldx]]--
+
+table.insert(fonts.triggers,"lineheight")
+
+function initializers.common.lineheight(tfmdata,value)
+ if value and type(value) == "string" then
+ if value == "none" then
+ for _,v in next, tfmdata.characters do
+ v.height, v.depth = 0, 0
+ end
+ else
+ local ascender, descender = tfmdata.ascender, tfmdata.descender
+ if ascender and descender then
+ local ht, dp = ascender or 0, descender or 0
+ if value == "height" then
+ dp = 0
+ elseif value == "depth" then
+ ht = 0
+ end
+ if ht > 0 then
+ if dp > 0 then
+ for _,v in next, tfmdata.characters do
+ v.height, v.depth = ht, dp
+ end
+ else
+ for _,v in next, tfmdata.characters do
+ v.height = ht
+ end
+ end
+ elseif dp > 0 then
+ for _,v in next, tfmdata.characters do
+ v.depth = dp
+ end
+ end
+ end
+ end
+ end
+end
+
+-- -- -- -- -- --
+-- shared
+-- -- -- -- -- --
+
+local function get_class_and_vector(tfmdata,value,where) -- "expansions"
+ local g_where = tfmdata.goodies and tfmdata.goodies[where]
+ local f_where = fonts[where]
+ local g_classes = g_where and g_where.classes
+ local class = g_where and g_where[value] or f_where.classes[value]
+ if class then
+ local class_vector = class.vector
+ local g_vectors = g_where and g_where.vectors
+ local vector = g_vectors and g_vectors[class_vector] or f_where.vectors[class_vector]
+ return class, vector
+ end
+end
+
+-- -- -- -- -- --
+-- expansion (hz)
+-- -- -- -- -- --
+
+fonts.expansions = fonts.expansions or { }
+fonts.expansions.classes = fonts.expansions.classes or { }
+fonts.expansions.vectors = fonts.expansions.vectors or { }
+
+local expansions = fonts.expansions
+local classes = fonts.expansions.classes
+local vectors = fonts.expansions.vectors
+
+-- beware, pdftex itself uses percentages * 10
+
+classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 }
+
+function commands.setupfontexpansion(class,settings)
+ aux.getparameters(classes,class,'preset',settings)
+end
+
+classes['quality'] = {
+ stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1
+}
+
+vectors['default'] = {
+ [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
+ [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
+ [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
+ [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
+ [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
+ [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
+ [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
+ [byte('w')] = 0.7, [byte('z')] = 0.7,
+ [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
+}
+
+vectors['quality'] = vectors['default'] -- metatable ?
+
+--~ function table.locator(...)
+--~ local k = { ... }
+--~ return function(t)
+--~ for i=1,#k do
+--~ t = t[k[i]]
+--~ if not k then
+--~ return false
+--~ end
+--~ end
+--~ return t
+--~ end
+--~ end
+
+--~ local locate = table.locator { "goodies", "expansions" }
+
+function initializers.common.expansion(tfmdata,value)
+ if value then
+ local class, vector = get_class_and_vector(tfmdata,value,"expansions")
+ if class then
+ if vector then
+ local stretch, shrink, step, factor = class.stretch or 0, class.shrink or 0, class.step or 0, class.factor or 1
+ if trace_expansion then
+ logs.report("fonts","set expansion class %s, vector: %s, factor: %s, stretch: %s, shrink: %s, step: %s",value,class_vector,factor,stretch,shrink,step)
+ end
+ tfmdata.stretch, tfmdata.shrink, tfmdata.step, tfmdata.auto_expand = stretch * 10, shrink * 10, step * 10, true
+ local data = characters and characters.data
+ for i, chr in next, tfmdata.characters do
+ local v = vector[i]
+ if data and not v then -- we could move the data test outside (needed for plain)
+ local d = data[i]
+ if d then
+ local s = d.shcode
+ if not s then
+ -- sorry
+ elseif type(s) == "table" then
+ v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2
+ else
+ v = vector[s] or 0
+ end
+ end
+ end
+ if v and v ~= 0 then
+ chr.expansion_factor = v*factor
+ else -- can be option
+ chr.expansion_factor = factor
+ end
+ end
+ elseif trace_expansion then
+ logs.report("fonts","unknown expansion vector '%s' in class '%s",class_vector,value)
+ end
+ elseif trace_expansion then
+ logs.report("fonts","unknown expansion class '%s'",value)
+ end
+ end
+end
+
+table.insert(fonts.manipulators,"expansion")
+
+initializers.base.otf.expansion = initializers.common.expansion
+initializers.node.otf.expansion = initializers.common.expansion
+
+initializers.base.afm.expansion = initializers.common.expansion
+initializers.node.afm.expansion = initializers.common.expansion
+
+fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end)
+
+-- -- -- -- -- --
+-- protrusion
+-- -- -- -- -- --
+
+fonts.protrusions = fonts.protrusions or { }
+fonts.protrusions.classes = fonts.protrusions.classes or { }
+fonts.protrusions.vectors = fonts.protrusions.vectors or { }
+
+local protrusions = fonts.protrusions
+local classes = fonts.protrusions.classes
+local vectors = fonts.protrusions.vectors
+
+-- the values need to be revisioned
+
+classes.preset = { factor = 1, left = 1, right = 1 }
+
+function commands.setupfontprotrusion(class,settings)
+ aux.getparameters(classes,class,'preset',settings)
+end
+
+classes['pure'] = {
+ vector = 'pure', factor = 1
+}
+classes['punctuation'] = {
+ vector = 'punctuation', factor = 1
+}
+classes['alpha'] = {
+ vector = 'alpha', factor = 1
+}
+classes['quality'] = {
+ vector = 'quality', factor = 1
+}
+
+vectors['pure'] = {
+
+ [0x002C] = { 0, 1 }, -- comma
+ [0x002E] = { 0, 1 }, -- period
+ [0x003A] = { 0, 1 }, -- colon
+ [0x003B] = { 0, 1 }, -- semicolon
+ [0x002D] = { 0, 1 }, -- hyphen
+ [0x2013] = { 0, 0.50 }, -- endash
+ [0x2014] = { 0, 0.33 }, -- emdash
+ [0x3001] = { 0, 1 }, -- ideographic comma 、
+ [0x3002] = { 0, 1 }, -- ideographic full stop 。
+ [0x060C] = { 0, 1 }, -- arabic comma ،
+ [0x061B] = { 0, 1 }, -- arabic semicolon ؛
+ [0x06D4] = { 0, 1 }, -- arabic full stop ۔
+
+}
+
+vectors['punctuation'] = {
+
+ [0x003F] = { 0, 0.20 }, -- ?
+ [0x00BF] = { 0, 0.20 }, -- ¿
+ [0x0021] = { 0, 0.20 }, -- !
+ [0x00A1] = { 0, 0.20 }, -- ¡
+ [0x0028] = { 0.05, 0 }, -- (
+ [0x0029] = { 0, 0.05 }, -- )
+ [0x005B] = { 0.05, 0 }, -- [
+ [0x005D] = { 0, 0.05 }, -- ]
+ [0x002C] = { 0, 0.70 }, -- comma
+ [0x002E] = { 0, 0.70 }, -- period
+ [0x003A] = { 0, 0.50 }, -- colon
+ [0x003B] = { 0, 0.50 }, -- semicolon
+ [0x002D] = { 0, 0.70 }, -- hyphen
+ [0x2013] = { 0, 0.30 }, -- endash
+ [0x2014] = { 0, 0.20 }, -- emdash
+ [0x060C] = { 0, 0.70 }, -- arabic comma
+ [0x061B] = { 0, 0.50 }, -- arabic semicolon
+ [0x06D4] = { 0, 0.70 }, -- arabic full stop
+ [0x061F] = { 0, 0.20 }, -- ؟
+
+ -- todo: left and right quotes: .5 double, .7 single
+
+ [0x2039] = { 0.70, 0.70 }, -- left single guillemet ‹
+ [0x203A] = { 0.70, 0.70 }, -- right single guillemet ›
+ [0x00AB] = { 0.50, 0.50 }, -- left guillemet «
+ [0x00BB] = { 0.50, 0.50 }, -- right guillemet »
+
+ [0x2018] = { 0.70, 0.70 }, -- left single quotation mark ‘
+ [0x2019] = { 0, 0.70 }, -- right single quotation mark ’
+ [0x201A] = { 0.70, 0 }, -- single low-9 quotation mark ,
+ [0x201B] = { 0.70, 0 }, -- single high-reversed-9 quotation mark ‛
+ [0x201C] = { 0.50, 0.50 }, -- left double quotation mark “
+ [0x201D] = { 0, 0.50 }, -- right double quotation mark ”
+ [0x201E] = { 0.50, 0 }, -- double low-9 quotation mark „
+ [0x201F] = { 0.50, 0 }, -- double high-reversed-9 quotation mark ‟
+
+}
+
+vectors['alpha'] = {
+
+ [byte("A")] = { .05, .05 },
+ [byte("F")] = { 0, .05 },
+ [byte("J")] = { .05, 0 },
+ [byte("K")] = { 0, .05 },
+ [byte("L")] = { 0, .05 },
+ [byte("T")] = { .05, .05 },
+ [byte("V")] = { .05, .05 },
+ [byte("W")] = { .05, .05 },
+ [byte("X")] = { .05, .05 },
+ [byte("Y")] = { .05, .05 },
+
+ [byte("k")] = { 0, .05 },
+ [byte("r")] = { 0, .05 },
+ [byte("t")] = { 0, .05 },
+ [byte("v")] = { .05, .05 },
+ [byte("w")] = { .05, .05 },
+ [byte("x")] = { .05, .05 },
+ [byte("y")] = { .05, .05 },
+
+}
+
+vectors['quality'] = table.merge( {},
+ vectors['punctuation'],
+ vectors['alpha']
+)
+
+-- As this is experimental code, users should not depend on it. The
+-- implications are still discussed on the ConTeXt Dev List and we're
+-- not sure yet what exactly the spec is (the next code is tested with
+-- a gyre font patched by / fea file made by Khaled Hosny). The double
+-- trick should not be needed it proper hanging punctuation is used in
+-- which case values < 1 can be used.
+--
+-- preferred (in context, usine vectors):
+--
+-- \definefontfeature[whatever][default][mode=node,protrusion=quality]
+--
+-- using lfbd and rtbd, with possibibility to enable only one side :
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn]
+-- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn]
+--
+-- idem, using multiplier
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
+-- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn]
+--
+-- idem, using named feature file (less frozen):
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
+
+classes['double'] = { -- for testing opbd
+ factor = 2, left = 1, right = 1,
+}
+
+local function map_opbd_onto_protrusion(tfmdata,value,opbd)
+ local characters, descriptions = tfmdata.characters, tfmdata.descriptions
+ local otfdata = tfmdata.shared.otfdata
+ local singles = otfdata.shared.featuredata.gpos_single
+ local script, language = tfmdata.script, tfmdata.language
+ local done, factor, left, right = false, 1, 1, 1
+ local class = classes[value]
+ if class then
+ factor = class.factor or 1
+ left = class.left or 1
+ right = class.right or 1
+ else
+ factor = tonumber(value) or 1
+ end
+ if opbd ~= "right" then
+ local validlookups, lookuplist = fonts.otf.collect_lookups(otfdata,"lfbd",script,language)
+ if validlookups then
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local data = singles[lookup]
+ if data then
+ if trace_protrusion then
+ logs.report("fonts","set left protrusion using lfbd lookup '%s'",lookup)
+ end
+ for k, v in next, data do
+ -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same
+ local p = - (v[1] / 1000) * factor * left
+ characters[k].left_protruding = p
+ if trace_protrusion then
+ logs.report("opbd","lfbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," "))
+ end
+ end
+ done = true
+ end
+ end
+ end
+ end
+ if opbd ~= "left" then
+ local validlookups, lookuplist = fonts.otf.collect_lookups(otfdata,"rtbd",script,language)
+ if validlookups then
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local data = singles[lookup]
+ if data then
+ if trace_protrusion then
+ logs.report("fonts","set right protrusion using rtbd lookup '%s'",lookup)
+ end
+ for k, v in next, data do
+ -- local p = v[3] / descriptions[k].width -- or 3
+ local p = (v[1] / 1000) * factor * right
+ characters[k].right_protruding = p
+ if trace_protrusion then
+ logs.report("opbd","rtbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," "))
+ end
+ end
+ end
+ done = true
+ end
+ end
+ end
+ tfmdata.auto_protrude = done
+end
+
+-- The opbd test is just there because it was discussed on the
+-- context development list. However, the mentioned fxlbi.otf font
+-- only has some kerns for digits. So, consider this feature not
+-- supported till we have a proper test font.
+
+function initializers.common.protrusion(tfmdata,value)
+ if value then
+ local opbd = tfmdata.shared.features.opbd
+ if opbd then
+ -- possible values: left right both yes no (experimental)
+ map_opbd_onto_protrusion(tfmdata,value,opbd)
+ else
+ local class, vector = get_class_and_vector(tfmdata,value,"protrusions")
+ if class then
+ if vector then
+ local factor = class.factor or 1
+ local left = class.left or 1
+ local right = class.right or 1
+ if trace_protrusion then
+ logs.report("fonts","set protrusion class %s, vector: %s, factor: %s, left: %s, right: %s",value,class_vector,factor,left,right)
+ end
+ local data = characters.data
+ local emwidth = tfmdata.parameters.quad
+ tfmdata.auto_protrude = true
+ for i, chr in next, tfmdata.characters do
+ local v, pl, pr = vector[i], nil, nil
+ if v then
+ pl, pr = v[1], v[2]
+ else
+ local d = data[i]
+ if d then
+ local s = d.shcode
+ if not s then
+ -- sorry
+ elseif type(s) == "table" then
+ local vl, vr = vector[s[1]], vector[s[#s]]
+ if vl then pl = vl[1] end
+ if vr then pr = vr[2] end
+ else
+ v = vector[s]
+ if v then
+ pl, pr = v[1], v[2]
+ end
+ end
+ end
+ end
+ if pl and pl ~= 0 then
+ chr.left_protruding = left *pl*factor
+ end
+ if pr and pr ~= 0 then
+ chr.right_protruding = right*pr*factor
+ end
+ end
+ elseif trace_protrusion then
+ logs.report("fonts","unknown protrusion vector '%s' in class '%s",class_vector,value)
+ end
+ elseif trace_protrusion then
+ logs.report("fonts","unknown protrusion class '%s'",value)
+ end
+ end
+ end
+end
+
+table.insert(fonts.manipulators,"protrusion")
+
+initializers.base.otf.protrusion = initializers.common.protrusion
+initializers.node.otf.protrusion = initializers.common.protrusion
+
+initializers.base.afm.protrusion = initializers.common.protrusion
+initializers.node.afm.protrusion = initializers.common.protrusion
+
+fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end)
+
+-- -- --
+
+function initializers.common.nostackmath(tfmdata,value)
+ tfmdata.ignore_stack_math = value
+end
+
+table.insert(fonts.manipulators,"nostackmath")
+
+initializers.base.otf.nostackmath = initializers.common.nostackmath
+initializers.node.otf.nostackmath = initializers.common.nostackmath
+
+table.insert(fonts.triggers,"itlc")
+
+function initializers.common.itlc(tfmdata,value)
+ if value then
+ -- the magic 40 and it formula come from Dohyun Kim
+ local fontdata = tfmdata.shared.otfdata or tfmdata.shared.afmdata
+ local metadata = fontdata and fontdata.metadata
+ if metadata then
+ local italicangle = metadata.italicangle
+ if italicangle and italicangle ~= 0 then
+ local uwidth = (metadata.uwidth or 40)/2
+ for unicode, d in next, tfmdata.descriptions do
+ local it = d.boundingbox[3] - d.width + uwidth
+ if it ~= 0 then
+ d.italic = it
+ end
+ end
+ tfmdata.has_italic = true
+ end
+ end
+ end
+end
+
+initializers.base.otf.itlc = initializers.common.itlc
+initializers.node.otf.itlc = initializers.common.itlc
+
+initializers.base.afm.itlc = initializers.common.itlc
+initializers.node.afm.itlc = initializers.common.itlc
+
+-- slanting
+
+table.insert(fonts.triggers,"slant")
+
+function initializers.common.slant(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 1 then
+ value = 1
+ elseif value < -1 then
+ value = -1
+ end
+ tfmdata.slant_factor = value
+end
+
+initializers.base.otf.slant = initializers.common.slant
+initializers.node.otf.slant = initializers.common.slant
+
+initializers.base.afm.slant = initializers.common.slant
+initializers.node.afm.slant = initializers.common.slant
+
+table.insert(fonts.triggers,"extend")
+
+function initializers.common.extend(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 10 then
+ value = 10
+ elseif value < -10 then
+ value = -10
+ end
+ tfmdata.extend_factor = value
+end
+
+initializers.base.otf.extend = initializers.common.extend
+initializers.node.otf.extend = initializers.common.extend
+
+initializers.base.afm.extend = initializers.common.extend
+initializers.node.afm.extend = initializers.common.extend
+
+-- historic stuff, move from font-ota
+
+local delete_node = nodes.delete
+local glyph = node.id("glyph")
+local fontdata = fonts.ids
+
+fonts.strippables = fonts.strippables or { -- just a placeholder
+ [0x200C] = true, -- zwnj
+ [0x200D] = true, -- zwj
+}
+
+local strippables = fonts.strippables
+
+local function processformatters(head,font)
+ local how = fontdata[font].shared.features.formatters
+ if how == nil or how == "strip" then -- nil when forced
+ local current, done = head, false
+ while current do
+ if current.id == glyph and current.subtype<256 and current.font == font then
+ local char = current.char
+ if strippables[char] then
+ head, current = delete_node(head,current)
+ done = true
+ else
+ current = current.next
+ end
+ else
+ current = current.next
+ end
+ end
+ return head, done
+ else
+ return head, false
+ end
+end
+
+methods.node.otf.formatters = processformatters
+methods.base.otf.formatters = processformatters
+
+fonts.otf.tables.features['formatters'] = 'Hide Formatting Characters'
+
+fonts.otf.features.register("formatters")
+
+table.insert(fonts.manipulators,"formatters") -- at end
diff --git a/tex/context/base/font-fbk.lua b/tex/context/base/font-fbk.lua
new file mode 100644
index 000000000..1ad1cc781
--- /dev/null
+++ b/tex/context/base/font-fbk.lua
@@ -0,0 +1,316 @@
+if not modules then modules = { } end modules ['font-fbk'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local cos, tan, rad, format = math.cos, math.tan, math.rad, string.format
+
+local trace_combining = false trackers.register("fonts.combining", function(v) trace_combining = v end)
+
+--[[ldx--
+
This is very experimental code!
+--ldx]]--
+
+fonts.fallbacks = fonts.fallbacks or { }
+
+local vf = fonts.vf
+local tfm = fonts.tfm
+
+vf.aux.combine.commands["enable-tracing"] = function(g,v)
+ trace_combining = true
+end
+
+vf.aux.combine.commands["disable-tracing"] = function(g,v)
+ trace_combining = false
+end
+
+vf.aux.combine.commands["set-tracing"] = function(g,v)
+ if v[2] == nil then
+ trace_combining = true
+ else
+ trace_combining = v[2]
+ end
+end
+
+function vf.aux.combine.initialize_trace()
+ if trace_combining then
+ return "special", "pdf: .8 0 0 rg .8 0 0 RG", "pdf: 0 .8 0 rg 0 .8 0 RG", "pdf: 0 0 .8 rg 0 0 .8 RG", "pdf: 0 g 0 G"
+ else
+ return "comment", "", "", "", ""
+ end
+end
+
+vf.aux.combine.force_fallback = false
+
+vf.aux.combine.commands["fake-character"] = function(g,v) -- g, nr, fallback_id
+ local index, fallback = v[2], v[3]
+ if vf.aux.combine.force_fallback or not g.characters[index] then
+ if fonts.fallbacks[fallback] then
+ g.characters[index], g.descriptions[index] = fonts.fallbacks[fallback](g)
+ end
+ end
+end
+
+fonts.fallbacks['textcent'] = function (g)
+ local c = ("c"):byte()
+ local t = table.fastcopy(g.characters[c])
+ local a = - tan(rad(g.italicangle or 0))
+ local special, red, green, blue, black = vf.aux.combine.initialize_trace()
+ local quad = g.parameters.quad
+ if a == 0 then
+ t.commands = {
+ {"push"}, {"slot", 1, c}, {"pop"},
+ {"right", .5*t.width},
+ {"down", .2*t.height},
+ {special, green},
+ {"rule", 1.4*t.height, .02*quad},
+ {special, black},
+ }
+ else
+ t.commands = {
+ {"push"},
+ {"right", .5*t.width-.025*quad},
+ {"down", .2*t.height},
+ {"special",format("pdf: q 1 0 %s 1 0 0 cm",a)},
+ {special, green},
+ {"rule", 1.4*t.height, .025*quad},
+ {special, black},
+ {"special","pdf: Q"},
+ {"pop"},
+ {"slot", 1, c} -- last else problems with cm
+ }
+ end
+ -- somehow the width is messed up now
+ -- todo: set height
+ t.height = 1.2*t.height
+ t.depth = 0.2*t.height
+ g.virtualized = true
+ local d = g.descriptions
+ return t, d and d[c]
+end
+
+fonts.fallbacks['texteuro'] = function (g)
+ local c = ("C"):byte()
+ local t = table.fastcopy(g.characters[c])
+ local d = cos(rad(90+(g.italicangle)))
+ local special, red, green, blue, black = vf.aux.combine.initialize_trace()
+ local quad = g.parameters.quad
+ t.width = 1.05*t.width
+ t.commands = {
+ {"right", .05*t.width},
+ {"push"}, {"slot", 1, c}, {"pop"},
+ {"right", .5*t.width*d},
+ {"down", -.5*t.height},
+ {special, green},
+ {"rule", .05*quad, .4*quad},
+ {special, black},
+ }
+ g.virtualized = true
+ return t, g.descriptions[c]
+end
+
+-- maybe store llx etc instead of bbox in tfm blob / more efficient
+
+vf.aux.combine.force_composed = false
+
+local push, pop = { "push" }, { "pop" }
+
+local cache = { } -- we could make these weak
+
+function vf.aux.compose_characters(g) -- todo: scaling depends on call location
+ -- this assumes that slot 1 is self, there will be a proper self some day
+ local chars, descs = g.characters, g.descriptions
+ local X = ("X"):byte()
+ local xchar = chars[X]
+ local xdesc = descs[X]
+ if xchar and xdesc then
+ local scale = g.factor or 1
+ local cap_lly = scale*xdesc.boundingbox[4]
+ local ita_cor = cos(rad(90+(g.italicangle or 0)))
+ local force = vf.aux.combine.force_composed
+ local fallbacks = characters.fallbacks
+ local special, red, green, blue, black
+ if trace_combining then
+ special, red, green, blue, black = vf.aux.combine.initialize_trace()
+ red, green, blue, black = { special, red }, { special, green }, { special, blue }, { special, black }
+ end
+ local done = false
+ for i,c in next, characters.data do
+ if force or not chars[i] then
+ local s = c.specials
+ if s and s[1] == 'char' then
+ local chr = s[2]
+ local charschr = chars[chr]
+ if charschr then
+ local cc = c.category
+ if cc == 'll' or cc == 'lu' or cc == 'lt' then
+ local acc = s[3]
+ local t = { }
+ for k, v in next, charschr do
+ if k ~= "commands" then
+ t[k] = v
+ end
+ end
+ local charsacc = chars[acc]
+--~ local ca = charsacc.category
+--~ if ca == "mn" then
+--~ -- mark nonspacing
+--~ elseif ca == "ms" then
+--~ -- mark spacing combining
+--~ elseif ca == "me" then
+--~ -- mark enclosing
+--~ else
+ if not charsacc then
+ acc = fallbacks[acc]
+ charsacc = acc and chars[acc]
+ end
+ if charsacc then
+ local chr_t = cache[chr]
+ if not cht_t then
+ chr_t = {"slot", 1, chr}
+ cache[chr] = chr_t
+ end
+ local acc_t = cache[acc]
+ if not acc_t then
+ acc_t = {"slot", 1, acc}
+ cache[acc] = acc_t
+ end
+ local cb = descs[chr].boundingbox
+ local ab = descs[acc].boundingbox
+ if cb and ab then
+ -- can be sped up for scale == 1
+ local c_llx, c_lly, c_urx, c_ury = scale*cb[1], scale*cb[2], scale*cb[3], scale*cb[4]
+ local a_llx, a_lly, a_urx, a_ury = scale*ab[1], scale*ab[2], scale*ab[3], scale*ab[4]
+ local dx = (c_urx - a_urx - a_llx + c_llx)/2
+ local dd = (c_urx - c_llx)*ita_cor
+ if a_ury < 0 then
+ if trace_combining then
+ t.commands = {
+ push,
+ {"right", dx-dd},
+ red,
+ acc_t,
+ black,
+ pop,
+ chr_t,
+ }
+ else
+ t.commands = {
+ push,
+ {"right", dx-dd},
+ acc_t,
+ pop,
+ chr_t,
+ }
+ end
+ elseif c_ury > a_lly then
+ local dy = cap_lly-a_lly
+ if trace_combining then
+ t.commands = {
+ push,
+ {"right", dx+dd},
+ {"down", -dy},
+ green,
+ acc_t,
+ black,
+ pop,
+ chr_t,
+ }
+ else
+ t.commands = {
+ push,
+ {"right", dx+dd},
+ {"down", -dy},
+ acc_t,
+ pop,
+ chr_t,
+ }
+ end
+ else
+ if trace_combining then
+ t.commands = {
+ {"push"},
+ {"right", dx+dd},
+ blue,
+ acc_t,
+ black,
+ {"pop"},
+ chr_t,
+ }
+ else
+ t.commands = {
+ {"push"},
+ {"right", dx+dd},
+ acc_t,
+ {"pop"},
+ chr_t,
+ }
+ end
+ end
+ done = true
+ end
+ end
+ chars[i] = t
+ local d = { }
+ for k, v in next, descs[chr] do
+ d[k] = v
+ end
+ d.name = c.adobename or "unknown"
+ -- d.unicode = i
+ descs[i] = d
+ end
+ end
+ end
+ end
+ end
+ if done then
+ g.virtualized = true
+ end
+ end
+end
+
+vf.aux.combine.commands["complete-composed-characters"] = function(g,v)
+ vf.aux.compose_characters(g)
+end
+
+--~ {'special', 'pdf: q ' .. s .. ' 0 0 '.. s .. ' 0 0 cm'},
+--~ {'special', 'pdf: q 1 0 0 1 ' .. -w .. ' ' .. -h .. ' cm'},
+--~ -- {'special', 'pdf: /Fm\XX\space Do'},
+--~ {'special', 'pdf: Q'},
+--~ {'special', 'pdf: Q'},
+
+-- for documentation purposes we provide:
+
+fonts.define.methods.install("fallback", { -- todo: auto-fallback with loop over data.characters
+ { "fake-character", 0x00A2, 'textcent' },
+ { "fake-character", 0x20AC, 'texteuro' }
+})
+
+vf.aux.combine.commands["enable-force"] = function(g,v)
+ vf.aux.combine.force_composed = true
+ vf.aux.combine.force_fallback = true
+end
+vf.aux.combine.commands["disable-force"] = function(g,v)
+ vf.aux.combine.force_composed = false
+ vf.aux.combine.force_fallback = false
+end
+
+fonts.define.methods.install("demo-2", {
+ { "enable-tracing" },
+ { "enable-force" },
+ { "initialize" },
+ { "include-method", "fallback" },
+ { "complete-composed-characters" },
+ { "disable-tracing" },
+ { "disable-force" },
+})
+
+fonts.define.methods.install("demo-3", {
+ { "enable-tracing" },
+ { "initialize" },
+ { "complete-composed-characters" },
+ { "disable-tracing" },
+})
diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua
new file mode 100644
index 000000000..e3db8c816
--- /dev/null
+++ b/tex/context/base/font-gds.lua
@@ -0,0 +1,294 @@
+if not modules then modules = { } end modules ['font-gds'] = {
+ version = 1.000,
+ comment = "companion to font-gds.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next = type, next
+local gmatch = string.gmatch
+
+local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end)
+
+-- goodies=name,colorscheme=,featureset=
+--
+-- goodies=auto
+
+-- goodies
+
+fonts.goodies = fonts.goodies or { }
+fonts.goodies.data = fonts.goodies.data or { }
+fonts.goodies.list = fonts.goodies.list or { }
+
+local data = fonts.goodies.data
+local list = fonts.goodies.list
+
+function fonts.goodies.report(what,trace,goodies)
+ if trace_goodies or trace then
+ local whatever = goodies[what]
+ if whatever then
+ logs.report("fonts", "goodie '%s' found in '%s'",what,goodies.name)
+ end
+ end
+end
+
+local function getgoodies(filename) -- maybe a merge is better
+ local goodies = data[filename] -- we assume no suffix is given
+ if goodies ~= nil then
+ -- found or tagged unfound
+ elseif type(filename) == "string" then
+ local fullname = resolvers.find_file(file.addsuffix(filename,"lfg")) or "" -- prefered suffix
+ if fullname == "" then
+ fullname = resolvers.find_file(file.addsuffix(filename,"lua")) or "" -- fallback suffix
+ end
+ if fullname == "" then
+ logs.report("fonts", "goodie file '%s.lfg' is not found",filename)
+ data[filename] = false -- signal for not found
+ else
+ goodies = dofile(fullname) or false
+ if not goodies then
+ logs.report("fonts", "goodie file '%s' is invalid",fullname)
+ return nil
+ elseif trace_goodies then
+ logs.report("fonts", "goodie file '%s' is loaded",fullname)
+ end
+ goodies.name = goodies.name or "no name"
+ for name, fnc in next, list do
+ fnc(goodies)
+ end
+ goodies.initialized = true
+ data[filename] = goodies
+ end
+ end
+ return goodies
+end
+
+function fonts.goodies.register(name,fnc)
+ list[name] = fnc
+end
+
+fonts.goodies.get = getgoodies
+
+-- register goodies file
+
+local preset_context = fonts.define.specify.preset_context
+
+function fonts.initializers.common.goodies(tfmdata,value)
+ local goodies = tfmdata.goodies or { } -- future versions might store goodies in the cached instance
+ for filename in gmatch(value,"[^, ]+") do
+ -- we need to check for duplicates
+ local ok = getgoodies(filename)
+ if ok then
+ goodies[#goodies+1] = ok
+ end
+ end
+ tfmdata.goodies = goodies -- shared ?
+end
+
+-- featuresets
+
+local function flattened(t,tt)
+ -- first set value dominates
+ local tt = tt or { }
+ for i=1,#t do
+ local ti = t[i]
+ if type(ti) == "table" then
+ flattened(ti,tt)
+ elseif tt[ti] == nil then
+ tt[ti] = true
+ end
+ end
+ for k, v in next, t do
+ if type(k) ~= "number" then
+ if type(v) == "table" then
+ flattened(v,tt)
+ elseif tt[k] == nil then
+ tt[k] = v
+ end
+ end
+ end
+ return tt
+end
+
+fonts.flattened_features = flattened
+
+function fonts.goodies.prepare_features(goodies,name,set)
+ if set then
+ local ff = fonts.flattened_features(set)
+ local fullname = goodies.name .. "::" .. name
+ local n, s = preset_context(fullname,"",ff)
+ goodies.featuresets[name] = s -- set
+ if trace_goodies then
+ logs.report("fonts", "feature set '%s' gets number %s and name '%s'",name,n,fullname)
+ end
+ return n
+ end
+end
+
+local function initialize(goodies,tfmdata)
+ local featuresets = goodies.featuresets
+ local goodiesname = goodies.name
+ if featuresets then
+ if trace_goodies then
+ logs.report("fonts", "checking featuresets in '%s'",goodies.name)
+ end
+ for name, set in next, featuresets do
+ fonts.goodies.prepare_features(goodies,name,set)
+ end
+ end
+end
+
+fonts.goodies.register("featureset",initialize)
+
+function fonts.initializers.common.featureset(tfmdata,set)
+ local goodies = tfmdata.goodies -- shared ?
+ if goodies then
+ local features = tfmdata.shared.features
+ local what
+ for i=1,#goodies do
+ -- last one counts
+ local g = goodies[i]
+ what = (g.featuresets and g.featuresets[set]) or what
+ end
+ if what then
+ for feature, value in next, what do
+ if features[feature] == nil then
+ features[feature] = value
+ end
+ end
+ tfmdata.mode = features.mode or tfmdata.mode
+ end
+ end
+end
+
+-- colorschemes
+
+fonts.goodies.colorschemes = fonts.goodies.colorschemes or { }
+fonts.goodies.colorschemes.data = fonts.goodies.colorschemes.data or { }
+
+local colorschemes = fonts.goodies.colorschemes
+
+function fonts.initializers.common.colorscheme(tfmdata,scheme)
+ if type(scheme) == "string" then
+ local goodies = tfmdata.goodies
+ -- todo : check for already defined in shared
+ if goodies then
+ local what
+ for i=1,#goodies do
+ -- last one counts
+ local g = goodies[i]
+ what = (g.colorschemes and g.colorschemes[scheme]) or what
+ end
+ if what then
+ -- this is font bound but we can share them if needed
+ -- just as we could hash the conversions (per font)
+ local hash, reverse = tfmdata.luatex.unicodes, { }
+ for i=1,#what do
+ local w = what[i]
+ for j=1,#w do
+ local name = w[j]
+ local unicode = hash[name]
+ if unicode then
+ reverse[unicode] = i
+ end
+ end
+ end
+ tfmdata.colorscheme = reverse
+ return
+ end
+ end
+ end
+ tfmdata.colorscheme = false
+end
+
+local fontdata = fonts.ids
+local fcs = fonts.color.set
+local has_attribute = node.has_attribute
+local traverse_id = node.traverse_id
+local a_colorscheme = attributes.private('colorscheme')
+local glyph = node.id("glyph")
+
+function fonts.goodies.colorschemes.coloring(head)
+ local lastfont, lastscheme
+ for n in traverse_id(glyph,head) do
+ local a = has_attribute(n,a_colorscheme)
+ if a then
+ local f = n.font
+ if f ~= lastfont then
+ lastscheme, lastfont = fontdata[f].colorscheme, f
+ end
+ if lastscheme then
+ local sc = lastscheme[n.char]
+ if sc then
+ fcs(n,"colorscheme:"..a..":"..sc) -- slow
+ end
+ end
+ end
+ end
+end
+
+function fonts.goodies.colorschemes.enable()
+ tasks.appendaction("processors","fonts","fonts.goodies.colorschemes.coloring")
+ function fonts.goodies.colorschemes.enable() end
+end
+
+-- installation (collected to keep the overview)
+
+fonts.otf.tables.features['goodies'] = 'Goodies on top of built in features'
+fonts.otf.tables.features['featurset'] = 'Goodie Feature Set'
+fonts.otf.tables.features['colorscheme'] = 'Goodie Color Scheme'
+
+fonts.otf.features.register('goodies')
+fonts.otf.features.register('featureset')
+fonts.otf.features.register('colorscheme')
+
+table.insert(fonts.triggers, 1, "goodies")
+table.insert(fonts.triggers, 2, "featureset") -- insert after
+table.insert(fonts.triggers, "colorscheme")
+
+fonts.initializers.base.otf.goodies = fonts.initializers.common.goodies
+fonts.initializers.node.otf.goodies = fonts.initializers.common.goodies
+
+fonts.initializers.base.otf.featureset = fonts.initializers.common.featureset
+fonts.initializers.node.otf.featureset = fonts.initializers.common.featureset
+
+fonts.initializers.base.otf.colorscheme = fonts.initializers.common.colorscheme
+fonts.initializers.node.otf.colorscheme = fonts.initializers.common.colorscheme
+
+-- experiment, we have to load the definitions immediately as they precede
+-- the definition so they need to be initialized in the typescript
+
+local function initialize(goodies)
+ local mathgoodies = goodies.mathematics
+ local virtuals = mathgoodies and mathgoodies.virtuals
+ local mapfiles = mathgoodies and mathgoodies.mapfiles
+ local maplines = mathgoodies and mathgoodies.maplines
+ if virtuals then
+ for name, specification in next, virtuals do
+ mathematics.make_font(name,specification)
+ end
+ end
+ if mapfiles then
+ for i=1,#mapfiles do
+ fonts.map.loadfile(mapfiles[i]) -- todo: backend function
+ end
+ end
+ if maplines then
+ for i=1,#maplines do
+ fonts.map.loadline(maplines[i]) -- todo: backend function
+ end
+ end
+end
+
+fonts.goodies.register("mathematics", initialize)
+
+-- The following file (husayni.lfg) is the experimental setup that we used
+-- for Idris font. For the moment we don't store this in the cache and quite
+-- probably these files sit in one of the paths:
+--
+-- tex/context/fonts/goodies
+-- tex/fonts/goodies/context
+-- tex/fonts/data/foundry/collection
+--
+-- see lfg files in distribution
diff --git a/tex/context/base/font-gds.mkiv b/tex/context/base/font-gds.mkiv
new file mode 100644
index 000000000..e36116283
--- /dev/null
+++ b/tex/context/base/font-gds.mkiv
@@ -0,0 +1,83 @@
+%D \module
+%D [ file=font-gds,
+%D version=2009.10.14,
+%D title=\CONTEXT\ Font Support,
+%D subtitle=Colorschemes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Support / Colorschemes}
+
+% \registerctxluafile{font-gds}{1.001}
+
+\unprotect
+
+\def\loadfontgoodies[#1]%
+ {\ctxlua{fonts.goodies.get("#1")}}
+
+
+% this will become colorgroups and move to font-col or so
+
+\definecolor[colorscheme:1:1][s=.75]
+\definecolor[colorscheme:1:2][r=.75]
+\definecolor[colorscheme:1:3][g=.75]
+\definecolor[colorscheme:1:4][b=.75]
+\definecolor[colorscheme:1:5][c=.75]
+\definecolor[colorscheme:1:6][m=.75]
+\definecolor[colorscheme:1:7][y=.75]
+
+\definecolor[colorscheme:2:7][s=.75]
+\definecolor[colorscheme:2:6][r=.75]
+\definecolor[colorscheme:2:5][g=.75]
+\definecolor[colorscheme:2:4][b=.75]
+\definecolor[colorscheme:2:3][c=.75]
+\definecolor[colorscheme:2:2][m=.75]
+\definecolor[colorscheme:2:1][y=.75]
+
+\definesystemattribute[colorscheme] \chardef\colorschemeattribute \dogetattributeid{colorscheme}
+
+\def\setfontcolorscheme
+ {\ctxlua{fonts.goodies.colorschemes.enable()}%
+ \xdef\setfontcolorscheme[##1]{\attribute\colorschemeattribute##1\relax}%
+ \setfontcolorscheme}
+
+\edef\resetfontcolorscheme{\attribute\colorschemeattribute\attributeunsetvalue}
+
+\protect \endinput
+
+% \definefontfeature[husayni-colored][goodies=husayni,colorscheme=default,featureset=default]
+%
+% \definedfont[husayni*husayni-colored at 36pt]
+%
+% \starttext \pardir TRT \textdir TRT
+%
+% \setfontcolorscheme[1]
+%
+% اَلْحَمْدُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ
+% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛
+% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ،
+% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ
+% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ.
+%
+% \setfontcolorscheme[2]
+%
+% اَلْحَمْدُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ
+% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛
+% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ،
+% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ
+% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ.
+%
+% \resetfontcolorscheme
+%
+% اَلْحَمْدُ لِلّٰهِ حَمْدَ مُعْتَرِفٍ بِحَمْدِهٖ، مُغْتَرِفٌ مِنْ بِحَارِ
+% مَجْدِهٖ، بِلِسَانِ ٱلثَّنَاۤءِ شَاكِرًا، وَلِحُسْنِ اٰلاۤئِهٖ نَاشِرًا؛
+% اَلَّذِيْ خَلَقَ ٱلْمَوْتَ وَٱلْحَيٰوةَ، وَٱلْخَيْرَ وَٱلشَّرَّ،
+% وَٱلنَّفْعَ وَٱلضَّرَّ، وَٱلسُّكُوْنَ وَٱلْحَرَكَةَ، وَٱلْأَرْوَاحَ
+% وَٱلْأَجْسَامَ، وَٱلذِّكْرَ وَٱلنِّسْيَانَ.
+%
+% \stoptext
diff --git a/tex/context/base/font-heb.mkii b/tex/context/base/font-heb.mkii
new file mode 100644
index 000000000..3ec0395f3
--- /dev/null
+++ b/tex/context/base/font-heb.mkii
@@ -0,0 +1,5 @@
+\unprotected \writestatus\m!systems{load ARABTEX as a module instead}
+
+\usemodule[arabtex]
+
+\endinput
diff --git a/tex/context/base/font-ini.lua b/tex/context/base/font-ini.lua
new file mode 100644
index 000000000..e45149781
--- /dev/null
+++ b/tex/context/base/font-ini.lua
@@ -0,0 +1,95 @@
+if not modules then modules = { } end modules ['font-ini'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
Not much is happening here.
+--ldx]]--
+
+local utf = unicode.utf8
+local format, serialize = string.format, table.serialize
+local write_nl = texio.write_nl
+
+if not fontloader then fontloader = fontforge end
+
+fontloader.totable = fontloader.to_table
+
+-- vtf comes first
+-- fix comes last
+
+fonts = fonts or { }
+
+fonts.ids = fonts.ids or { } fonts.identifiers = fonts.ids -- aka fontdata
+fonts.chr = fonts.chr or { } fonts.characters = fonts.chr -- aka chardata
+fonts.qua = fonts.qua or { } fonts.quads = fonts.qua -- aka quaddata
+
+fonts.tfm = fonts.tfm or { }
+
+fonts.mode = 'base'
+fonts.private = 0xF0000 -- 0x10FFFF
+fonts.verbose = false -- more verbose cache tables
+
+fonts.ids[0] = { -- nullfont
+ characters = { },
+ descriptions = { },
+ name = "nullfont",
+}
+
+fonts.chr[0] = { }
+
+fonts.methods = fonts.methods or {
+ base = { tfm = { }, afm = { }, otf = { }, vtf = { }, fix = { } },
+ node = { tfm = { }, afm = { }, otf = { }, vtf = { }, fix = { } },
+}
+
+fonts.initializers = fonts.initializers or {
+ base = { tfm = { }, afm = { }, otf = { }, vtf = { }, fix = { } },
+ node = { tfm = { }, afm = { }, otf = { }, vtf = { }, fix = { } }
+}
+
+fonts.triggers = fonts.triggers or {
+ 'mode',
+ 'language',
+ 'script',
+ 'strategy',
+}
+
+fonts.processors = fonts.processors or {
+}
+
+fonts.manipulators = fonts.manipulators or {
+}
+
+fonts.define = fonts.define or { }
+fonts.define.specify = fonts.define.specify or { }
+fonts.define.specify.synonyms = fonts.define.specify.synonyms or { }
+
+-- tracing
+
+if not fonts.color then
+
+ fonts.color = {
+ set = function() end,
+ reset = function() end,
+ }
+
+end
+
+-- format identification
+
+fonts.formats = { }
+
+function fonts.fontformat(filename,default)
+ local extname = file.extname(filename)
+ local format = fonts.formats[extname]
+ if format then
+ return format
+ else
+ logs.report("fonts define","unable to detemine font format for '%s'",filename)
+ return default
+ end
+end
diff --git a/tex/context/base/font-ini.mkii b/tex/context/base/font-ini.mkii
new file mode 100644
index 000000000..89fbb5d07
--- /dev/null
+++ b/tex/context/base/font-ini.mkii
@@ -0,0 +1,4573 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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 / Initialization}
+
+\unprotect
+
+% \def\fontrange#1%
+% {\dofontrange{#1 =\bodyfontsize}}
+%
+% \def\dofontrange#1%
+% {\dodofontrange#1 \relax}% \fontstringA
+%
+% \def\dodofontrange#1 #2 %
+% {\ifdim\bodyfontsize#2%
+% #1\expandafter\gobbleuntilrelax
+% \else
+% \expandafter\dodofontrange
+% \fi}
+%
+% \definefont
+% [crap]
+% [\fontrange
+% {Regular <10pt
+% RegularBold <12pt
+% RegularSlanted <15pt
+% Regular} sa 1]
+%
+% may be better:
+%
+% \definefontrange
+% [crap]
+% [Regular <10pt
+% RegularBold <12pt
+% RegularSlanted <15pt]
+% [Regular sa 1]
+%
+%
+% \dostepwiserecurse{2}{15}{1}
+% {{\switchtobodyfont[\recurselevel pt]\crap test}\endgraf}
+
+% adapted, else wrong interlinespace
+
+\def\setfontparameters
+ {\synchronizefontsfalse
+ \the\everybodyfont
+ \synchronizefontstrue}
+
+% handy
+
+\newcounter\pushedfont
+
+\def\savefont
+ {\edef\savedfont{\the\font}%
+ \pushmacro\savedfont
+ \pushmacro\currentregime
+ \pushmacro\charactermapping
+ \pushmacro\characterencoding}
+
+\def\restorefont
+ {\popmacro\characterencoding
+ \popmacro\charactermapping
+ \popmacro\currentregime
+ \popmacro\savedfont
+ \savedfont}
+
+\def\pushcurrentfont
+ {\edef\popcurrentfont
+ {\noexpand\def\noexpand\fontbody{\fontbody}%
+ \noexpand\def\noexpand\fontstyle{\fontstyle}%
+ \noexpand\dosetcurrentfontalternative{\fontalternative}%
+ \noexpand\dosetcurrentfontsize{\fontsize}%
+ \noexpand\synchronizefont}}
+
+% \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 {definedfont,startfont,doiffontcharelse}
+%D
+%D A couple of relatively new macros:
+
+\newevery \everydefinedfont \relax
+
+\def\dodefinedfont[#1]%
+ {\iffirstargument\definefont[\string\thedefinedfont][#1]\fi
+ \csname\string\thedefinedfont\endcsname % can be \relax
+ \the\everydefinedfont} % hm, redundant
+
+\unexpanded\def\definedfont
+ {\dosingleempty\dodefinedfont}
+
+\unexpanded\def\startfont
+ {\bgroup\definedfont}
+
+\def\stopfont
+ {\egroup}
+
+\def\doiffontcharelse#1#2%
+ {\bgroup
+ \definedfont[#1]%
+ \iffontchar\font#2\relax
+ \egroup\expandafter\firstoftwoarguments
+ \else
+ \egroup\expandafter\secondoftwoarguments
+ \fi}
+
+%%% message 14 added
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+%D This module is one of the oldest modules of \CONTEXT. The
+%D macros below evolved out of the \PLAIN\ \TEX\ macros and
+%D therefore use a similar naming scheme (\type{\rm},
+%D \type{\bf}, etc). This module grew out of our needs. We
+%D started with the \PLAIN\ \TEX\ definitions, generalized the
+%D underlaying macros, and extended those to a level at which
+%D probably no one will ever recognize them.
+%D
+%D In 2001 we ran into a couple of projects where more than
+%D one combined set of fonts was involved in a document. To
+%D make definitions more readable, as well as to overcome the
+%D problem of ever growing file name lists, and also because
+%D we needed to scale fonts relative to each other, the low
+%D level implementation was partly rewritten. Global
+%D font assignments, relative scaling, font classes and alike
+%D were added then. At the same time some macros were made a
+%D bit more readable, and math support was extended to the
+%D larger sizes.
+%D
+%D One important characteristic of the font mechanism presented
+%D here is the postponing of font loading. This makes it
+%D possible to distribute \type{fmt} files without bothering
+%D about the specific breed of \type{tfm} files.
+%D
+%D Another feature implemented here is the massive switching
+%D from roman to {\ss sans serif}, {\tt teletype} or else. This
+%D means one doesn't have to take care of all kind of relations
+%D between fonts.
+%D
+%D \page[bigpreference]
+
+%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
+%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
+%D using Lucida Bright we 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 Anyone who feels the need, can define additional ones, like
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC faxfont \NC \type{\ff} \NC\FR
+%D \NC blackboard \NC \type{\bb} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Or even
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC hebrew \NC \type{\hb} \NC\SR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Styles are grouped in font sets. At the moment there are
+%D three main sets defined:
+%D
+%D \startlinecorrection
+%D \starttable[|l|l||]
+%D \HL
+%D \NC Computer Modern Roman \NC Knuth \NC \type{cmr} \NC\FR
+%D \NC Lucida Bright \NC Bigelow \& Holmes \NC \type{lbr} \NC\MR
+%D \NC Standard Postscript Fonts \NC Adobe \NC \type{pos} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D There are also some Computer Modern Roman alternatives:
+%D
+%D \startlinecorrection
+%D \starttable[|l|l||]
+%D \HL
+%D \NC Computer Modern Roman \NC Knuth \& Sauter \NC \type{sau} \NC\FR
+%D \NC Euler fonts \NC Zapf \NC \type{eul} \NC\MR
+%D \NC Computer Modern Concrete \NC Knuth \& Zapf \NC \type{con} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D All these definitions are ordered in files with names like
+%D \type{font-cmr} and \type{font-pos}, where the last three
+%D characters specify the name as known to \CONTEXT.
+%D
+%D Within such a font set (\type{cmr}) and style (\type{\rm})
+%D we can define a number 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 For old stylish Frans Goddijn we have:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC oldstyle \NC \type{\os} \NC\SR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D The availability of these alternatives depends on the
+%D completeness of a font family and of course the definitions
+%D in the font files.
+%D
+%D But let's not forget math. In addition to the previous \TEX\
+%D families (the mysterious \type{\fam}'s) we've got some more:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC Math Roman \NC \type{\mr} \NC\FR
+%D \NC Math Italic \NC \type{\mi} \NC\MR
+%D \NC Math Symbol \NC \type{\sy} \NC\MR
+%D \NC Math Extra \NC \type{\ex} \NC\MR
+%D \NC Math A \NC \type{\ma} \NC\MR
+%D \NC Math B \NC \type{\mb} \NC\MR
+%D \NC Math C \NC \type{\mc} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Users can call for specific fonts in many ways. Switches to
+%D other typefaces, like the switch from normal to bold, are as
+%D intuitive as possible, which means that all dependant fonts
+%D also switch. One can imagine that this takes quite some
+%D processing time.
+%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
+%D During the definition of a bodyfont one can also declare the
+%D available larger 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
+%D larger alternatives on the 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
+%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 \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%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
+%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
+%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
+%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
+%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 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
+%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
+
+%D \macros
+%D {mf}
+%D
+%D Math fonts are a species in their own. They are tightly
+%D hooked into smaller and even smaller ones of similar breed
+%D to form a tight family. Let's first see how these are
+%D related:
+%D
+%D \startbuffer
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+ \bi x^2 =\rm 6x^2$
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+{\bi x^2}=\rm 6x^2$
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+ \bi x^2 =\tf 6x^2$
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+{\bi x^2}=\tf 6x^2$
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+ \bi x^2 =\bf 6x^2$
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+{\bi x^2}=\bf 6x^2$
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+ \bi x^2 =\sl 6x^2$
+%D $\tf x^2+\bf x^2+\sl x^2+\it x^2+\bs x^2+{\bi x^2}=\sl 6x^2$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Gives both an expected and unexpected result:
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D We see here that the character shapes change accordingly to
+%D the current family, but that the symbols are always typeset
+%D in the font assigned to \type{\fam0}.
+%D
+%D \startbuffer
+%D $\tf\mf x^2 + x^2 + x^2 + x^2 + x^2 + x^2 = 6x^2$
+%D $\bf\mf x^2 + x^2 + x^2 + x^2 + x^2 + x^2 = 6x^2$
+%D $\sl\mf x^2 + x^2 + x^2 + x^2 + x^2 + x^2 = 6x^2$
+%D $\bs\mf x^2 + x^2 + x^2 + x^2 + x^2 + x^2 = 6x^2$
+%D $\it\mf x^2 + x^2 + x^2 + x^2 + x^2 + x^2 = 6x^2$
+%D $\bi\mf x^2 + x^2 + x^2 + x^2 + x^2 + x^2 = 6x^2$
+%D \stopbuffer
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D In this example we see a new command \type{\mf} surface
+%D which means as much as {\em math font}. This commands
+%D reactivates the last font alternative and therefore equals
+%D \type{\bf}, \type{\sl} etc. but by default it equals
+%D \type{\tf}:
+
+\unexpanded\def\mf
+ {\dodosetmathfont\fontalternative
+ \csname\fontalternative\endcsname}
+
+%D The previous example was typeset saying:
+%D
+%D \typebuffer
+%D
+%D Beware: the exact location of \type{\mf} is not that
+%D important, we could as well has said
+%D
+%D \startbuffer
+%D $\bf x^2 + x^2 + x^2 + x^2 + x^2 + x^2 = \mf 6x^2$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This is due to the way \TEX\ handles fonts in math mode.
+%D
+%D Of course we'll have to redefine \type{\mf} every time we
+%D change the current \type{\fam}.
+
+%D \macros
+%D {mbox,enablembox,mathop}
+%D
+%D Now how can we put this to use? Will the next sequence
+%D give the desired result?
+%D
+%D \startbuffer
+%D $\bf x^2 + \hbox{\mf whatever} + \sin(2x)$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D It won't!
+%D
+%D \startvoorbeeld
+%D \let\mathop=\normalmathop \getbuffer
+%D \stopvoorbeeld
+%D
+%D The reason for this is that \type{\sin} is defined as:
+%D
+%D \starttyping
+%D \def\sin{\mathop{\rm sin}\nolimits}
+%D \stoptyping
+%D
+%D We can fix this by defining
+
+\unexpanded\def\mathop
+ {\normalmathop
+ \bgroup
+ \let\rm\mf
+ \let\next=}
+
+%D We can fix arbitrary horizontal boxes by redefining the
+%D \TEX\ primitive \type{\hbox}:
+%D
+%D \starttyping
+%D \def\hbox{\ifmmode\mbox\else\normalhbox\fi}
+%D \stoptyping
+%D
+%D with
+%D
+%D \starttyping
+%D \def\mbox#1#%
+%D {\normalhbox#1\bgroup\mf\let\next=}
+%D \stoptyping
+%D
+%D or more robust, that is, also accepting \type{\hbox\bgroup}:
+%D
+%D \starttyping
+%D \def\mbox%
+%D {\normalhbox\bgroup\mf
+%D \dowithnextbox{\flushnextbox\egroup}%
+%D \normalhbox}
+%D \stoptyping
+%D
+%D And now:
+%D
+%D \startbuffer
+%D $\bf x^2 + \hbox{whatever} + \sin(2x)$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Indeed gives:
+%D
+%D \startvoorbeeld
+%D \enablembox\getbuffer
+%D \stopvoorbeeld
+%D
+%D But, do we want this kind of trickery to be activated? No,
+%D simply because we cannot be sure of incompatibilities,
+%D although for instance unboxing goes ok. Therefore we
+%D introduce:
+
+% best can go to math-ini and make \mf a hook then
+
+% better use \dowithnextboxcontent
+
+\def\normalmbox
+ {\normalhbox\bgroup\mf
+ \dowithnextbox{\flushnextbox\egroup}\normalhbox}
+
+% to test:
+%
+% \def\normalmbox
+% {\dowithnextboxcontent\mf\flushnextbox\normalhbox}
+
+\def\mbox
+ {\ifmmode\normalmbox\else\normalhbox\fi}
+
+\def\enablembox
+ {\appendtoks
+ \ifx\normalhbox\undefined\let\normalhbox\hbox\fi
+ \let\hbox\mbox
+ \to\everymathematics}
+
+%D So in fact one can enable this feature if needed. I would say:
+%D go along, but use grouping if needed!
+
+%D \macros
+%D {mrfam,mifam,syfam,exfam,
+%D bsfam,bifam,scfam,tffam,
+%D mafam,mbfam,msfam}
+%D
+%D After this short mathematical excursion, we enter the world
+%D of fonts and fontswitching. We start with something very
+%D \TEX: \type{\fam} specified font families. \TEX\ uses
+%D families for managing fonts in math mode. Such a family has
+%D three members: text, script and scriptscript: $x^{y^z}$. In
+%D \CONTEXT\ we take a bit different approach than \PLAIN\
+%D \TEX\ does. \PLAIN\ \TEX\ needs at least four families for
+%D typesetting math. We use those but give them symbolic names.
+
+\chardef\mrfam = 0 % (Plain TeX) Math Roman
+\chardef\mifam = 1 % (Plain TeX) Math Italic
+\chardef\syfam = 2 % (Plain TeX) Math Symbol
+\chardef\exfam = 3 % (Plain TeX) Math Extra
+
+%D \PLAIN\ \TEX\ also defines families for {\it italic}, {\sl
+%D slanted} and {\bf bold} typefaces, so we don't have to
+%D define them here.
+
+\ifx\itfam\undefined
+
+\chardef\itfam = 4 % (Plain TeX) Italic
+\chardef\slfam = 5 % (Plain TeX) Slanted
+\chardef\bffam = 6 % (Plain TeX) Boldface
+
+\fi
+
+%D Family~7 in \PLAIN\ \TEX\ is not used in \CONTEXT, because
+%D we do massive switches from roman to sans serif, teletype or
+%D other faces.
+
+\ifx\ttfam\undefined
+
+\chardef\ttfam = 7 % (Plain TeX) can be reused!
+
+\fi
+
+%D We define ourselves some more families for {\bs bold
+%D slanted}, {\bi bold italic} and {\sc Small Caps}, so
+%D we can use them in math mode too. Instead of separate
+%D families for {\ss sans serif} and \type{teletype} we use the
+%D more general \type{\tffam}, which stands for typeface.
+
+\chardef\bsfam = 8 % (ConTeXt) BoldSlanted
+\chardef\bifam = 9 % (ConTeXt) BoldItalic
+\chardef\scfam = 10 % (ConTeXt) SmallCaps
+\chardef\tffam = 11 % (ConTeXt) TypeFace
+
+%D Because Taco needs a few more math families, we reuse
+%D family~7 for all those typefaces that have no related
+%D family, and therefore are grouped into one.
+
+\chardef\nnfam = 7 % (ReUsed) NoName
+
+%D Normally \type{\mrfam} equals \type{\tffam}, but a more
+%D distinctive alternatives are possible, for instance the
+%D Euler and Concrete Typefaces.
+%D
+%D After having defined all those in nature non||mathematical
+%D families, we define ourselves some real math ones. These are
+%D needed for the \AMS\ Symbol Fonts and Extended Lucida
+%D Bright.
+
+\chardef\mafam = 12 % (ConTeXt) Math A Fam (AmsTeX A)
+\chardef\mbfam = 13 % (ConTeXt) Math B Fam (AmsTeX B)
+\chardef\mcfam = 14 % (ConTeXt) Math C Fam (MathTime)
+\chardef\mdfam = 15 % (ConTeXt) Math D Fam (MathTime)
+
+%D Because there are 16~families and because \type{\ttfam}
+%D is reused, at the moment we have no so many families
+%D left. By default, we map any newly defined family on the
+%D last one (F).
+
+\def\newfam#1{\chardef#1=15 }
+
+%D This hack is also needed because in \ETEX\ we are going
+%D to reuse the \type {\newfam} allocation counter.
+
+%D To ease the support of font packages, we als define
+%D shortcuts to these familynames. This is necessary because
+%D the family names are in fact \type{\chardef}'s, which means
+%D that we're dealing with numbers (one can check this by
+%D applying \type{\showthe} and \type{\show}). In the
+%D specification of math symbols however we need hexadecimal
+%D numbers, so we have to convert the \type{\fam}'s value.
+
+\edef\hexmrfam {\hexnumber\mrfam} \edef\hexbsfam {\hexnumber\bsfam}
+\edef\hexmifam {\hexnumber\mifam} \edef\hexbifam {\hexnumber\bifam}
+\edef\hexsyfam {\hexnumber\syfam} \edef\hexscfam {\hexnumber\scfam}
+\edef\hexexfam {\hexnumber\exfam} \edef\hextffam {\hexnumber\tffam}
+\edef\hexitfam {\hexnumber\itfam} \edef\hexmafam {\hexnumber\mafam}
+\edef\hexslfam {\hexnumber\slfam} \edef\hexmbfam {\hexnumber\mbfam}
+\edef\hexbffam {\hexnumber\bffam} \edef\hexmcfam {\hexnumber\mcfam}
+\edef\hexnnfam {\hexnumber\nnfam} \edef\hexmdfam {\hexnumber\mdfam}
+
+%D \macros
+%D {uchar}
+%D
+%D This macro prepares \CONTEXT\ for \UNICODE\ support. By
+%D defining it here, we have at least an safeguard for utility
+%D file reading.
+
+\ifx\uchar\undefined \unexpanded\def\uchar#1#2{[#1,#2]} \fi
+
+%D We define some (very private) constants to improve speed,
+%D memory usage and consistency.
+
+\def\@size@ {@f@si@} % bodyfont size prefix (12pt etc)
+\def\@style@ {@f@st@} % full style prefix (roman etc)
+\def\@shortstyle@ {@f@sh@} % short style prefix (rm etc)
+\def\@letter@ {@f@le@} % first alternative typeface
+\def\@noletter@ {@f@no@} % second alternative typeface
+\def\@fontclass@ {@f@cl@} % fontclass
+
+%D The families can be grouped into math specific ones and
+%D more text related families, although text ones can be
+%D mapped onto the math ones to get for instance bold math.
+%D
+%D Both groups of families are handles by a couple of token
+%D list tagged as strategies. This implementation makes
+%D implementing extensions more comfortable.
+
+\newtoks \textstrategies
+\newtoks \mathstrategies
+\newtoks \symbstrategies
+
+\newif\ifsynchronizemathfonts \synchronizemathfontstrue
+
+\def\synchronizetext % stylish text in mmode
+ {\ifsynchronizemathfonts\the\textstrategies\fi} % \if...\fam\minusone\fi}
+
+\def\synchronizemath % math stuff in mmode
+ {\ifsynchronizemathfonts\the\mathstrategies\fi} % \if...\fam\minusone\fi}
+
+\def\synchronizesymb % stylish math stuff in mmode
+ {\ifsynchronizemathfonts\the\symbstrategies\fi} % \if...\fam\minusone\fi}
+
+%D By not setting the family we can append a font switch to \type
+%D {\everymath}. On the other hand, one never knows in what family
+%D state the strategies brought us.
+%D
+%D \starttyping
+%D {\bfa $\the\fam$} {\bfa \everymath{} $\the\fam$}
+%D \stoptyping
+
+%D \macros
+%D {textonly}
+%D
+%D We can inhibit this slow||downer with:
+
+\def\textonly{\synchronizemathfontsfalse} % document this
+
+\appendtoks
+ \dosettextfamily\c!tf
+ \dosettextfamily\c!bf
+ \dosettextfamily\c!sl
+ \dosettextfamily\c!it
+ \dosettextfamily\c!bs
+ \dosettextfamily\c!bi
+ \dosettextfamily\c!sc
+\to \textstrategies
+
+\def\dosettextfamily#1% better pass fontbody to dodoset
+ {\let\savedfontbody\fontbody
+ \let\fontfamily#1%
+ \let\fontbody\scriptscriptface\dodosettextfamily\scriptscriptfont
+ \let\fontbody\scriptface \dodosettextfamily \scriptfont
+ \let\fontbody\textface \dodosettextfamily \textfont
+ \let\fontbody\savedfontbody}
+
+% \def\s!nullfont{nullfont}
+
+\def\dodosettextfamily
+ {\ifx\fontclass\empty
+ \@EA\dodosettextfamilyA
+ \else
+ \@EA\dodosettextfamilyB
+ \fi}
+
+\def\dodosettextfamilyA#1%
+ {\ifcsname \fontbody\c!mm\fontfamily\fontsize\endcsname \autofontsizefalse
+ \csname \fontbody\c!mm\fontfamily\fontsize\endcsname \else
+ \ifcsname \fontbody\c!mm\fontfamily\endcsname \autofontsizetrue
+ \csname \fontbody\c!mm\fontfamily\endcsname \else
+ \ifcsname \fontbody\c!rm\fontfamily\fontsize\endcsname \autofontsizefalse
+ \csname \fontbody\c!rm\fontfamily\fontsize\endcsname \else
+ \ifcsname \fontbody\c!rm\fontfamily\endcsname \autofontsizetrue
+ \csname \fontbody\c!rm\fontfamily\endcsname \else
+ \nullfont \autofontsizetrue
+ \fi\fi\fi\fi
+ #1\csname\fontfamily\s!fam\endcsname\font}
+
+\def\dodosettextfamilyB#1%
+ {\ifcsname\fontclass\fontbody\c!mm\fontfamily\fontsize\endcsname \autofontsizefalse
+ \csname\fontclass\fontbody\c!mm\fontfamily\fontsize\endcsname \else
+ \ifcsname\fontclass\fontbody\c!mm\fontfamily\endcsname \autofontsizetrue
+ \csname\fontclass\fontbody\c!mm\fontfamily\endcsname \else
+ \ifcsname\fontclass\fontbody\c!rm\fontfamily\fontsize\endcsname \autofontsizefalse
+ \csname\fontclass\fontbody\c!rm\fontfamily\fontsize\endcsname \else
+ \ifcsname\fontclass\fontbody\c!rm\fontfamily\endcsname \autofontsizetrue
+ \csname\fontclass\fontbody\c!rm\fontfamily\endcsname \else
+ \dodosettextfamilyA#1%
+ \fi\fi\fi\fi
+ #1\csname\fontfamily\s!fam\endcsname\font}
+
+\def\mrfallback{\c!rm\c!tf}
+
+\appendtoks
+ \dosetmathfamily\mrfam\textface\scriptface\scriptscriptface\c!mr\mrfallback
+ \dosetmathfamily\mifam\textface\scriptface\scriptscriptface\c!mi\empty
+ \dosetmathfamily\syfam\textface\scriptface\scriptscriptface\c!sy\empty
+ \dosetmathfamily\exfam\textface\textface \textface \c!ex\empty
+ \dosetmathfamily\mafam\textface\scriptface\scriptscriptface\c!ma\empty
+ \dosetmathfamily\mbfam\textface\scriptface\scriptscriptface\c!mb\empty
+ \dosetmathfamily\mcfam\textface\scriptface\scriptscriptface\c!mc\empty
+% \dosetmathfamily\mdfam\textface\scriptface\scriptscriptface\c!md\empty
+ \dosetmathfamily\nnfam\textface\scriptface\scriptscriptface\c!nn\empty
+\to \mathstrategies
+
+\appendtoks
+ \dosetskewchar\mifam\defaultskewcharmi % implemented later on
+ \dosetskewchar\syfam\defaultskewcharsy % implemented later on
+\to \mathstrategies
+
+\def\dosetmathfamily#1#2#3#4#5#6%
+ {\let\savedfontbody\fontbody % op hoger plan
+ \let\fontfamily#5%
+ \let\backfamily#6%
+ \let\fontbody #4\dodosetmathfamily\scriptscriptfont#1%
+ \let\fontbody #3\dodosetmathfamily \scriptfont#1%
+ \let\fontbody #2\dodosetmathfamily \textfont#1%
+ \let\fontbody\savedfontbody}
+
+\def\dodosetmathfamily
+ {\ifx\fontclass\empty
+ \@EA\dodosetmathfamilyA
+ \else
+ \@EA\dodosetmathfamilyB
+ \fi}
+
+\def\dodosetmathfamilyA#1#2%
+ {\ifcsname \fontbody\c!mm\fontfamily\fontsize\endcsname \autofontsizefalse
+ \csname \fontbody\c!mm\fontfamily\fontsize\endcsname \else
+ \ifcsname \fontbody\c!mm\fontfamily \endcsname \autofontsizetrue
+ \csname \fontbody\c!mm\fontfamily \endcsname \else
+ \ifcsname \fontbody \backfamily\fontsize\endcsname \autofontsizefalse
+ \csname \fontbody \backfamily\fontsize\endcsname \else
+ \ifcsname \fontbody \backfamily \endcsname \autofontsizetrue
+ \csname \fontbody \backfamily \endcsname \else
+ \nullfont \autofontsizetrue
+ \fi\fi\fi\fi
+ #1#2\font}
+
+\def\dodosetmathfamilyB#1#2%
+ {\ifcsname\fontclass\fontbody\c!mm\fontfamily\fontsize\endcsname \autofontsizefalse
+ \csname\fontclass\fontbody\c!mm\fontfamily\fontsize\endcsname \else
+ \ifcsname\fontclass\fontbody\c!mm\fontfamily \endcsname \autofontsizetrue
+ \csname\fontclass\fontbody\c!mm\fontfamily \endcsname \else
+ \ifcsname\fontclass\fontbody \backfamily\fontsize\endcsname \autofontsizefalse
+ \csname\fontclass\fontbody \backfamily\fontsize\endcsname \else
+ \ifcsname\fontclass\fontbody \backfamily \endcsname \autofontsizetrue
+ \csname\fontclass\fontbody \backfamily \endcsname \else
+ \dodosetmathfamilyA#1#2%
+ \fi\fi\fi\fi
+ #1#2\font}
+
+\appendtoks
+ \dosetsymbfamily\mrfam\textface\scriptface\scriptscriptface\c!mr
+ \dosetsymbfamily\mifam\textface\scriptface\scriptscriptface\c!mi
+ \dosetsymbfamily\syfam\textface\scriptface\scriptscriptface\c!sy
+ \dosetsymbfamily\exfam\textface\textface \textface \c!ex
+ \dosetsymbfamily\mafam\textface\scriptface\scriptscriptface\c!ma
+ \dosetsymbfamily\mbfam\textface\scriptface\scriptscriptface\c!mb
+ \dosetsymbfamily\mcfam\textface\scriptface\scriptscriptface\c!mc
+% \dosetsymbfamily\mdfam\textface\scriptface\scriptscriptface\c!md % also ?
+\to \symbstrategies
+
+\def\dosetsymbfamily#1#2#3#4#5%
+ {\let\savedfontbody\fontbody
+ \let\fontfamily#5%
+ \let\fontbody #4\dodosetsymbfamily\scriptscriptfont#1%
+ \let\fontbody #3\dodosetsymbfamily \scriptfont#1%
+ \let\fontbody #2\dodosetsymbfamily \textfont#1%
+ \let\fontbody\savedfontbody}
+
+\def\dodosetsymbfamily#1#2%
+ {\ifcsname\fontclass\fontbody\c!mm\fontfamily\fontalternative\fontsize\endcsname
+ \csname\fontclass\fontbody\c!mm\fontfamily\fontalternative\fontsize\endcsname
+ #1#2\font
+ \else\ifcsname\fontbody\c!mm\fontfamily\fontalternative\fontsize\endcsname
+ \csname\fontbody\c!mm\fontfamily\fontalternative\fontsize\endcsname
+ #1#2\font
+ \fi\fi}
+
+%D All used styles, like rm, ss and tt, are saved in a comma
+%D separated list. Appart from practical limitations one can
+%D define as many styles as needed.
+
+\def\fontrelativesizelist{\s!text,\s!script,\s!scriptscript,\c!x,\c!xx,\c!big,\c!small}
+
+%D \macros
+%D {magfactor,magfactorhalf}
+%D
+%D There are several ways to specify a font. Three of them are
+%D pure \TeX\ ones, the fourth one is new:
+%D
+%D \starttyping
+%D \font\name=cmr12
+%D \font\name=cmr12 at 10pt
+%D \font\name=cmr12 scaled \magstep2
+%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 value 1.440 in this example is derived
+%D from the \type{\magstep}'s as mentioned in
+%D \in{table}[tab:magstep]. We therefore introduce
+%D \type{\magfactor} as an alternative for \type{\magstep}.
+%D
+%D \placetable[here][tab:magstep]
+%D {Factors to be used with \type{sa.}}
+%D \starttable[|c|c|c|]
+%D \HL
+%D \NC \bf magstep \NC \bf equivalent \NC \bf factor \NC\SR
+%D \HL
+%D \NC 1 \NC \type{\magfactor1} \NC 1.200 \NC\FR
+%D \NC 2 \NC \type{\magfactor2} \NC 1.440 \NC\MR
+%D \NC 3 \NC \type{\magfactor3} \NC 1.728 \NC\MR
+%D \NC 4 \NC \type{\magfactor4} \NC 2.074 \NC\MR
+%D \NC 5 \NC \type{\magfactor5} \NC 2.488 \NC\LR
+%D \HL
+%D \stoptable
+
+\def\magstep#1% \relax removed, otherwise space after it sticks, else added
+ {\ifcase#1 1000\or1200\or1440\or1728\or2074\or2488\or1000\fi}
+
+\def\magstephalf
+ {1095}
+
+\def\magfactor#1%
+ {\ifcase#1 1.000\or1.200\or1.440\or1.728\or2.074\or2.488\or1\fi}
+
+\def\magfactorhalf
+ {1.095}
+
+%D These macros enable the use of definitions like \type{sa
+%D \magfactor3} which saves us both (mis|)|calculations and
+%D potential mistypings.
+%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.
+
+\let\defaultrelativefontsize \plusone
+\let\localrelativefontsize \plusone
+\def\localabsolutefontsize {\fontbody}
+
+\let\relativefontsize \defaultrelativefontsize
+
+\def\saverelativefontsize#1#2% #1=rm|ss|.. #2=waarde
+ {\setxvalue{\fontclass#1\s!rscale}{#2}}
+
+\def\checkrelativefontsize#1%
+ {\edef\relativefontsize
+ {\ifcsname\fontclass#1\s!rscale\endcsname
+ \csname\fontclass#1\s!rscale\endcsname
+ \else
+ \defaultrelativefontsize
+ \fi}}
+
+%D We also save:
+
+\def\savemathtextstyle#1% #1=rm|ss|..
+ {\doifsomething{#1}{\setxvalue{\fontclass\c!mm\s!text}{#1}}}
+
+\def\currentmathtextstyle % we default to empty !
+ {\executeifdefined{\fontclass\c!mm\s!text}\empty}
+
+%D Scaling macros:
+
+\newdimen\scaledfont
+
+\let\somefontspec\empty
+
+\def\@fs@{@fs@}
+
+% \def\parsefontspec#1%
+% {\xdef\somefontspec{#1\space\relax}%
+% \@EA\doparsefontspec\somefontspec]% =>#1 \relax]
+% \donoparsefontspec}
+%
+% but, better:
+
+\let\somefontname\empty
+
+\def\parsefontspec#1%
+ {\xdef\somefontspec{#1\space}%
+ \@EA\doparsefontspec\somefontspec\relax]% =>#1 \relax]
+ \donoparsefontspec}
+
+\def\doparsefontspec#1 #2%
+ {\def\somefontname{#1}%
+ \ifx\somefontname\empty % space before fontname
+ \@EA\doparsefontspec
+ \else\ifx#2\relax
+ \@EAEAEA\setnaturalfontspec
+ \else
+ \@EAEAEA\setforcedfontspec
+ \fi\fi
+ #2}
+
+\def\setnaturalfontspec#1]%
+ {\@fs@scaled\plusthousand\relax}
+
+\def\setforcedfontspec#1 #2\relax]%
+ {\csname\@fs@#1\endcsname#2\relax}
+
+\def\@fs@scaled
+ {\afterassignment\do@fs@scaled\scratchcounter}
+
+\def\do@fs@scaled#1\relax
+ {\scaledfont\number\scratchcounter\points
+ \scaledfont\localrelativefontsize\scaledfont
+ \ifautofontsize\scaledfont\currentfontbodyscale\scaledfont\fi
+ \scratchcounter\scaledfont % \scaledfont is now pretty large
+ \advance\scratchcounter \medcard
+ \divide\scratchcounter \maxcard
+ \xdef\somefontspec{ scaled \the\scratchcounter}}
+
+\def\@fs@at
+ {\afterassignment\do@fs@at\scaledfont}
+
+\def\do@fs@at#1\relax
+ {\scaledfont\localrelativefontsize\scaledfont
+ \ifautofontsize\scaledfont\currentfontbodyscale\scaledfont\fi
+ \xdef\somefontspec{ at \the\scaledfont}}
+
+\def\@fs@sa
+ {\scaledfont\localabsolutefontsize
+ \setsamofontspec}
+
+\def\@fs@mo
+ {\scaledfont\setmappedfontsize\localabsolutefontsize
+ \setsamofontspec}
+
+\def\setsamofontspec#1\relax
+ {\checkfontscale#1\end\scaledfont
+ \scaledfont\localrelativefontsize\scaledfont
+ \ifautofontsize\scaledfont\currentfontbodyscale\scaledfont\fi
+ \xdef\somefontspec{ at \the\scaledfont}}
+
+\def\getfontparameters
+ {\expandafter\dogetfontparameter\@@fontdata,]=,}
+
+\def\getglobalfontparameters
+ {\expandafter\dogetglobalfontparameter\@@fontdata,]=,}
+
+\def\dogetfontparameter#1=#2,%
+ {\if]#1\else
+ \expandafter\def\csname\??ff\@@fontfile#1\endcsname{#2}%
+ \expandafter\dogetfontparameter
+ \fi}
+
+\def\dogetglobalfontparameter#1=#2,%
+ {\if]#1\else
+ \expandafter\gdef\csname\??ff\@@fontfile#1\endcsname{#2}%
+ \expandafter\dogetglobalfontparameter
+ \fi}
+
+\let\@@fontencoding\empty
+\let\@@fontmapping \empty
+\let\@@fonthandling\empty
+\let\@@fontfeatures\empty
+\let\@@skewchar \empty
+\let\@@hyphenchar \empty % todo, will go to encoding
+
+%D This brings down maps processing from 466 to 309 seconds
+%D ($-33$\%) and mfonts from 42 to 34 seconds ($-15$\%).
+
+\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue
+
+%D When fontclasses are used, we define the font global,
+%D since namespaces are used. Otherwise we parse the specs
+%D each time.
+
+% wrong: this way we cannot set encoding etc
+%
+% \def\donoparsefontspec#1%
+% {\edef\fontfile{\truefontname\somefontname}%
+% \ifx\fontfile\s!unknown \let\fontfile\defaultfontfile \fi
+% \edef\lastfontname{\fontfile\somefontspec}%
+% \ifx\fontclass\empty\else\global\fi
+% \expandafter\font\csname#1\endcsname\lastfontname\relax
+% \relax}
+
+\let\fontfile\s!unknown
+
+\ifx\checkfontfilename\undefined \let\checkfontfilename\relax \fi
+
+% \definefontsynonym
+% [blabla]
+% [name:Latin Modern Something]
+% \definefontsynonym
+% [blabla]
+% [file:texnansi-lmr10]
+% [encoding=texnansi]
+% \definedfont[blabla] test \currentencoding/\fontfile \par
+% \definefontsynonym
+% [blabla]
+% [texnansi-lmtt10]
+% [encoding=texnansi]
+% \definedfont[blabla] test \currentencoding/\fontfile \par
+% \definefontsynonym
+% [blabla]
+% [ec-lmtt10]
+% [encoding=ec]
+% \definedfont[blabla] test \currentencoding/\fontfile \par
+
+\def\checkfontfilename
+ {\expandafter\docheckfontfilename\fontfile:\empty:\empty\relax}
+
+\def\docheckfontfilename#1:#2:#3#4\relax
+ {\edef\!!stringa{#1}%
+ \edef\!!stringb{#2}%
+ \ifx\!!stringb\empty
+ \edef\checkedfontfile{\!!stringa}%
+ \else\ifx\!!stringa\v!file
+ \edef\checkedfontfile{"\!!stringb"}%
+ \else\ifx\!!stringa\v!name
+ \edef\checkedfontfile{"\!!stringb"}%
+ \else
+ \edef\checkedfontfile{\!!stringb}%
+ \fi\fi\fi}
+
+% \definefontfeature[default] [liga=yes,texligatures=yes,texquotes=yes]
+% \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn]
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular][features=default]
+% \definefontsynonym[SerifCaps][palatinonova-regular][features=default-caps] % also sets Serif
+% \stoptypescript
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular*default]
+% \definefontsynonym[SerifCaps] [palatinonova-regular*default-caps]
+% \stoptypescript
+
+% \definetypeface[mainface][rm][serif][palatino-nova-regular][default] \setupbodyfont[mainface]
+%
+% \starttext
+% ``Test'' -- --- ff fi fl \sc ``Test'' -- --- ff fi fl
+% \stoptext
+
+% \starttext
+% \definefont
+% [blabla]
+% [name:Latin Modern Something]
+% \definefont
+% [blabla]
+% [file:texnansi-lmr10]
+% \blabla test
+% \definefont
+% [blabla]
+% [texnansi-lmtt10]
+% \blabla test
+% \stoptext
+
+% \starttext
+%
+% \setupcolors[state=start]
+%
+% \definefontfeature
+% [default-base]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes]
+% \definefontfeature
+% [default-node]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes,mode=node]
+% \definefontfeature
+% [default-none]
+% [script=latn,language=dflt,liga=yes,kern=no, tlig=yes,trep=yes]
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:lmroman12regular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:lmroman12regular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:lmroman12regular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:texgyrepagella*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:texgyrepagella*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:texgyrepagella*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:palatinonovaregular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:palatinonovaregular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:palatinonovaregular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:OfficinaSerifBookITC*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:OfficinaSerifBookITC*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:OfficinaSerifBookITC*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \definefontfeature[superdefault][default][compose=yes]
+%
+% {\font\oeps=name:lmroman10regular*default at 30pt \oeps test \char7683}
+% {\font\oeps=name:lmroman10regular*superdefault at 30pt \oeps test \char7683}
+%
+% \stoptext
+
+\let\doshowcheckedfontfeatures\relax
+
+\def\showcheckedfontfeatures
+ {\def\doshowcheckedfontfeatures{\writestatus\m!fonts{checked: \checkedfontfile}}}
+
+\def\checkedfontfile{\fontfile} % default
+
+\newtoks\everydefinefont
+
+\def\donoparsefontspec % #1 == \cs
+ {\edef\fontfile{\truefontname\somefontname}%
+ \ifx\fontfile\s!unknown \let\fontfile\defaultfontfile \fi % can for instance happen with MathGamma
+ \updatefontparameters
+ \checkfontfilename
+ \edef\lastfontname{\checkedfontfile\somefontspec}%
+ \ifx\fontclass\empty
+ \expandafter\definefontlocal
+ \else
+ \expandafter\definefontglobal
+ \fi} % #1 == \cs
+
+\def\definefontlocal#1%
+ {\expandafter\edef\csname#1\endcsname % ! ! ! ! not needed in luatex ! ! ! !
+ {\noexpand\csname#1:\endcsname
+ \noexpand\reactivatefont{\somefontname}{\fontfile}}%
+ \expandafter\font\csname#1:\endcsname\lastfontname\relax
+ \expandafter\let\expandafter\lastrawfontcall\csname#1:\endcsname
+ \the\everydefinefont}
+
+\def\definefontglobal#1% stores \somefontname=Mono and \fontfile=cmtt10
+ {\expandafter\xdef\csname#1\endcsname % ! ! ! ! not needed in luatex ! ! ! !
+ {\noexpand\csname#1:\endcsname
+ \noexpand\reactivatefont{\somefontname}{\fontfile}}%
+ \global\expandafter\font\csname#1:\endcsname\lastfontname\relax
+ \expandafter\let\expandafter\lastrawfontcall\csname#1:\endcsname
+ \the\everydefinefont}
+
+\def\reactivatefont#1#2%
+ {\def\somefontname{#1}%
+ \def\fontfile {#2}%
+ \updatefontparameters}
+
+% can be handy for tracing purposes
+%
+% \def\reportfontdefinition
+% {\bgroup
+% \expanded{\infofont
+% [\lastfontidentifier
+% ->\newfontidentifier
+% ->\fontname\csname\newfontidentifier\endcsname]}%
+% \endgraf
+% \egroup}
+
+%D An additional the second \type {\font} definition can
+%D prevent fuzzy font refs
+%D
+%D \starttyping
+%D \expandafter\font\csname\dummyfontname\endcsname\lastfontname
+%D \stoptyping
+%D
+%D but somehow they changed \TEX\ so that it does not matter
+%D any more.
+
+\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
+\edef\nullfontname {\fontname\nullfont}
+\edef\dummyfontname {font\strippedcsname\\}
+
+%D \macros
+%D {everyfont,everyfontswitch}
+%D
+%D For special purposes, we provide a hook.
+
+% \newevery \everyfont \relax
+% \newevery \everyfontswitch \relax
+
+% safer but sometimes introducing newlines in the log
+%
+% \batchmode
+% \font\lastloadedfont\fontfile\somefontspec\relax
+% \errorstopmode
+% \edef\lastfontname{\fontname\lastloadedfont}%
+% \ifx\lastfontname\nullfontname
+% \showmessage\m!fonts{10}{\fontfile}%
+% \expandafter\font\csname#1\endcsname=\defaultfontfile\somefontspec\relax
+% \else
+% \expandafter\let\csname#1\endcsname\lastloadedfont
+% \fi
+
+%D We also accept \type{sa a}||\type{sa d} as specification.
+
+\def\checkfontscale#1#2\end#3%
+ {#3\ifcsname\??ft\s!default\noexpand#1\endcsname
+ \csname\??ft\s!default\noexpand#1\endcsname\else#1#2%
+ \fi#3}
+
+%D The duplicate font definition, using the ever the same dummy
+%D font name, results in less fuzzy error messages. In the log
+%D file, for instance when overfull boxes are reported, the
+%D simple keyword `font' replaces the \TEX\ ordinated name. The
+%D latter can be too misleading, due to the fact that \TEX\ has
+%D a rather optimized font memory management. Thanks to Taco
+%D for helping me sort this out.
+
+%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
+%D
+%D The definitions can be accessed by:
+%D
+%D \startlines
+%D name: \type {\truefontname{Lucida-Bright}}
+%D data: \type {\truefontdata{\truefontname{Lucida-Bright}}}
+%D \stoplines
+
+% \def\definefontsynonym
+% {\dotripleempty\dodefinefontsynonym}
+%
+% \def\dodefinefontsynonym[#1][#2][#3]%
+% {\@EA\edef\csname\??ff\fontclass#1\endcsname{#2}%
+% \ifthirdargument
+% \edef\@@fontdata{#3}%
+% \ifx\@@fontdata\empty \else
+% \edef\@@fontfile{#2}%
+% \ifx\fontclass\empty
+% \getfontparameters
+% \else
+% \getglobalfontparameters
+% \fi
+% \fi
+% \fi}
+%
+% slightly faster, noticable when loading many typefaces,
+%
+% \testfeatureonce{5000}{\definefontsynonym[somefont][somename]} \end
+
+\def\classfont#1#2{#1#2} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
+
+\def\definefontsynonym[#1]#2[#3]%
+ {\edef\@@fontfile{#3}%
+ \@EA\let\csname\??ff\fontclass#1\endcsname\@@fontfile
+ \doifnextoptionalelse\dodefinefontsynonym\donothing}
+
+\def\dodefinefontsynonym[#1]%
+ {\edef\@@fontdata{#1}%
+ \ifx\@@fontdata\empty \else \ifx\fontclass\empty
+ \getfontparameters
+ \else
+ \getglobalfontparameters
+ \fi \fi}
+
+\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
+
+\def\setupfontsynonym
+ {\dodoubleempty\dosetupfontsynonym}
+
+\def\dosetupfontsynonym[#1][#2]%
+ {\edef\@@fontdata{#2}%
+ \ifx\@@fontdata\empty \else
+ \edef\@@fontfile{#1}%
+ \ifx\fontclass\empty
+ \getfontparameters
+ \else
+ \getglobalfontparameters
+ \fi
+ \fi}
+
+\def\truefontdata#1#2%
+ {\ifcsname\??ff#1#2\endcsname
+ % raw(Regular) raw(key)
+ \csname\??ff#1#2\endcsname
+ \else\ifcsname\??ff\fontclass#1\endcsname
+ % exp(palatino Regular) raw(key)
+ \expandafter\truefontdata\csname\??ff\fontclass#1\endcsname#2%
+ \else\ifcsname\??ff#1\endcsname
+ % exp(Regular) raw(key)
+ \expandafter\truefontdata\csname\??ff#1\endcsname#2%
+ \else\ifcsname\??ff#2\endcsname
+ % raw(key)
+ \csname\??ff#2\endcsname
+ \fi\fi\fi\fi}
+
+\def\truefontname#1%
+ {\ifcsname\??ff\fontclass#1\endcsname
+ \@EA\truefontname\csname\??ff\fontclass#1\endcsname
+ \else\ifcsname\??ff#1\endcsname
+ \@EA\truefontname\csname\??ff#1\endcsname
+ \else
+ #1%
+ \fi\fi}
+
+\def\expandfontsynonym#1#2% #2 := onelevelexpansion(#1)
+ {\ifcsname\??ff\fontclass#2\endcsname
+ \expandafter\def\expandafter#1\expandafter{\csname\??ff\fontclass#2\endcsname}%
+ \fi}
+
+\def\doifelsefontsynonym#1%
+ {\ifcsname\??ff\fontclass#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+% \definetypeface[palatino][rm][serif][palatino,allbold][default]
+%
+% \startfontclass[palatino]
+% \definefontsynonym [Serif] [SerifBold]
+% \definefontsynonym [SerifItalic] [SerifBoldItalic]
+% \definefontsynonym [SerifSlanted] [SerifBoldSlanted]
+% \definefontsynonym [SerifCaps] [SerifBold]
+% \stopfontclass
+%
+% \setupbodyfont[palatino]
+
+\def\startfontclass
+ {\dosingleempty\dostartfontclass}
+
+\def\dostartfontclass[#1]%
+ {\pushmacro\fontclass
+ \doifelse{#1}{\v!each}
+ {\let\fontclass\empty}
+ {\doifsomething{#1}{\def\fontclass{#1}}}}
+
+\def\stopfontclass
+ {\popmacro\fontclass}
+
+%D \macros
+%D {tracedfontname}
+%D
+%D A goody:
+
+\def\tracedfontencoding#1%
+ {\ifcsname\??ff#1\s!encoding\endcsname
+ \space[\csname\??ff#1\s!encoding\endcsname]%
+ \fi}
+
+\def\tracedfontname#1%
+ {\ifcsname\??ff\fontclass#1\endcsname
+ #1\tracedfontencoding{\fontclass#1}\space->\space
+ \@EA\tracedfontname\csname\??ff\fontclass#1\endcsname
+ \else\ifcsname\??ff#1\endcsname
+ #1\tracedfontencoding{#1}\space->\space
+ \@EA\tracedfontname\csname\??ff#1\endcsname
+ \else
+ #1%
+ \fi\fi}
+
+%D \macros
+%D {getfontfileparameters}
+%D
+%D For special purposes, one can use the next macro to
+%D access font file characteristics, for instance:
+%D
+%D \starttyping
+%D \getfontfileparameters{Regular}
+%D \stoptyping
+%D
+%D can result in:
+%D
+%D \starttyping
+%D \def\currentfontfileencoding{texnansi}
+%D \stoptyping
+
+% \def\@@currentfontfile{currentfontfile}
+%
+% \def\getfontfileparameters#1%
+% {\edef\fontdata{\truefontdata{\truefontname{#1}}}%
+% \expanded{\getparameters[\@@currentfontfile][\fontdata]}}
+
+\def\getfontfileparameters#1% can be simpler for mkii
+ {\edef\@@truefontname{\truefontname{#1}}%
+ \edef\currentfontfileencoding{\truefontdata\@@truefontname\s!encoding}%
+ \edef\currentfontfilemapping {\truefontdata\@@truefontname\s!mapping }%
+ \edef\currentfontfilehandling{\truefontdata\@@truefontname\s!handling}%
+ \edef\currentfontfilefeatures{\truefontdata\@@truefontname\s!features}}
+
+%D \macros
+%D {definefont}
+%D
+%D Before we implement the main definition macro, we first show
+%D 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 mp 2] \Nice nice
+%D \definefont[Text][LucidaBright sa 5.4] \Text last
+%D \stoptyping
+%D
+%D The implementation looks as follows:
+
+\def\definefont
+ {\dotripleempty\dodefinefont}
+
+\def\dodefinefont[#1][#2][#3]% [name][spec][1.6 | line=10pt | setup_id]
+ {\doifinstringelse{ }{#2}
+ {\ifthirdargument
+ \unexpanded\setvalue{#1}{\redodefinefont{#1}{#2}{#3}}%
+ \else
+ \unexpanded\setvalue{#1}{\dododefinefont{#1}{#2}}%
+ \fi}
+ {\definefont[#1][#2 sa *][#3]}}
+
+\def\redodefinefont#1#2#3%
+ {\dododefinefont{#1}{#2}%
+ \doifsetupselse{#3}
+ {\setups[#3]} % don't forget to document this !
+ {\setuplocalinterlinespace[#3]%
+ \setupspacing}} % needed ?
+
+\def\definefrozenfont
+ {\dotripleempty\dodefinefrozenfont}
+
+\def\dodefinefrozenfont[#1][#2][#3]%
+ {\dodefinefont[#1][#2][#3]%
+ \expandafter\let\csname\lastfontidentifier\expandafter\endcsname\csname\rawfontidentifier\endcsname}
+
+% \def\defineclassfont
+% {\doquadrupleempty\dodefineclassfont}
+%
+% \def\dodefineclassfont[#1][#2][#3][#4]% #2 = class
+% {\iffourthargument
+% \definefont[#1][#2#3][#4]%
+% %\else\ifthirdargument
+% % \definefont[#1][#2#3]%
+% \else
+% \definefont[#1][#2]%
+% \fi}
+
+%D The \type {*} makes the switch local, so that we can redefine a
+%D logical name and/or change the size in between.
+
+\newif\ifautofontsize \autofontsizetrue
+
+\let\lastfontidentifier\empty
+
+\def\rawfontidentifier{**\lastfontidentifier\fontsize**}
+\def\newfontidentifier{*\fontclass\lastfontidentifier\fontsize*}
+
+% best we can add the style as well because otherwise we get math encoding mixups
+%
+% \setupbodyfont [8pt] [\currentencoding/\ccaron\scaron\zcaron]
+% \blank
+% \switchtobodyfont[7pt] [\currentencoding/\ccaron\scaron\zcaron]
+
+\def\newfontidentifier{*\fontclass\lastfontidentifier\fontstyle\fontsize*}
+
+\def\dododefinefont#1#2%
+ {\edef\lastfontidentifier{#1}%
+ \let\localrelativefontsize\defaultrelativefontsize
+ \let\localabsolutefontsize\fontbody
+ \parsefontspec{#2}\rawfontidentifier
+ \let\localrelativefontsize\defaultrelativefontsize % not needed
+ \csname\rawfontidentifier\endcsname
+ \autofontsizefalse
+ \setfontcharacteristics
+ \the\everyfontswitch}
+
+\def\xxdododefinefont#1#2#3#4% \autofontsizetrue is set by calling routine
+ {\edef\lastfontidentifier{#3}%
+ \ifcsname\newfontidentifier\endcsname\else
+ \def\localrelativefontsize{#1}%
+ \def\localabsolutefontsize{#2}%
+ \parsefontspec{#4}\newfontidentifier
+ \let\localrelativefontsize\defaultrelativefontsize % not needed
+ \fi
+ \csname\newfontidentifier\endcsname
+ \autofontsizefalse
+ %\edef\lastfontidentifier{#3}%
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+%D I considered checking for mistakenly use of \PLAIN's
+%D \type{\magstep}'s but although it would take only a few
+%D lines of code, this would not add to consistent use. I
+%D therefore removed this check.
+
+%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
+%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
+
+\def\mapfontsize
+ {\dodoubleargument\domapfontsize}
+
+\def\domapfontsize[#1][#2]%
+ {\scratchdimen#1\relax % \relax is really needed here
+ \setvalue{\??ft*\the\scratchdimen}{#2}}
+
+\def\setmappedfontsize#1%
+ {\ifcsname\??ft*#1\endcsname
+ \csname\??ft*#1\endcsname
+ \else
+ #1%
+ \fi}
+
+%D \macros
+%D {getfontname}
+%D
+%D The names of the fonts can be called with the rather simple
+%D macro \type{\getfontname}. When for instance we pass
+%D \type{12ptrmtf} as argument, we get \getfontname{12ptrmtf}.
+
+\def\getfontname#1%
+ {\csname\??ft#1\endcsname}
+
+%D To be documented.
+
+\let\fontsizelist\empty
+\let\fontstylelist\empty
+
+\def\definefontsize[#1]% sneller met toks
+ {\addtocommalist{#1}\fontsizelist
+ \def\docommand##1%
+ {\def\dodocommand####1%
+ {\def\dododocommand########1%
+ %{\checkbodyfont{}{########1}{####1}{##1}}%
+ {\checkbodyfont{########1}{####1}{##1}}%
+ \processcommacommand[\fontstylelist]\dododocommand}%
+ \processcommacommand[\fontalternativelist]\dodocommand}%
+ \processcommacommand[\fontsizelist]\docommand}
+
+\def\fontalternativetextlist{\c!tf,\c!bf,\c!it,\c!sl,\c!bs,\c!bi,\c!sc}
+\def\fontalternativemathlist{\c!mr,\c!mi,\c!sy,\c!ex,\c!ma,\c!mb}
+
+\let\fontalternativelist\fontalternativetextlist % upward compatible
+
+%D \macros
+%D {currentfontscale,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 \type {cont-log.tex} for an example of its use.
+
+\def\currentfontscale
+ {\csname\??ft\s!default
+ \ifcsname\??ft\s!default\xfontsize\endcsname \xfontsize \else
+ \ifcsname\??ft\s!default\s!text \endcsname \s!text \fi\fi
+ \endcsname}
+
+\def\currentfontbodyscale
+ {\csname\??ft\s!default
+ \ifcsname\??ft\s!default\fontsize\endcsname \fontsize \else
+ \ifcsname\??ft\s!default\s!text \endcsname \s!text \fi\fi
+ \endcsname}
+
+\setvalue{\??ft\s!default}{1}
+
+%D Both alternatives use \type {\xfontsize}, a macro that
+%D expands to the current size in terms of \type {a} \unknown
+%D \type {d}, nothing, or \type {x} \unknown \type {xx}.
+
+\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\c!x\else\c!xx\fi}
+
+%D A typical use of this command is in commands that switch
+%D to another font bypassing the font mechanism:
+%D
+%D \starttyping
+%D \font\myfont=\truefontname{MyFont} at \currentfontscale\bodyfontsize
+%D \stoptyping
+
+%D Now we enter the area of font switching. The switching
+%D mechanism has to take care 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 \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 \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
+%D the moment we stick 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
+%D settings apply. All second parameters are specified in
+%D dimensions and tell us more about related sizes.
+%D
+%D Afterwards, one can change values with
+%D
+%D \showsetup{setupbodyfontenvironment}
+%D
+%D Due to the fact that \type{\c!text} and \type{\s!text} can
+%D have a similar meaning, and therefore can lead to an
+%D unwanted loop, we temporary redefine \type{\c!text}. For
+%D the moment this in only place that some trickery is needed
+%D to fool the multilingual interface.
+%D
+%D When instead of a size the keyword \type{unknown} is
+%D passed, fractions (relations) are used instead of fixed
+%D sizes.
+
+\let\bodyfontenvironmentlist\empty
+
+\newcount\@@fontdefhack
+
+\def\@@beginfontdef
+ {\ifcase\@@fontdefhack
+ \let\k!savedtext \k!text \let\k!text \s!text
+ \let\k!k!savedtext \k!k!text \let\k!k!text \!!plusone
+ \let\k!saveddefault \k!default \let\k!default \s!default
+ \let\k!k!saveddefault\k!k!default \let\k!k!default \!!plusone
+ \fi
+ \advance\@@fontdefhack \plusone }
+
+\def\@@endfontdef
+ {\advance\@@fontdefhack \minusone
+ \ifcase\@@fontdefhack
+ \let\k!k!default\k!k!saveddefault
+ \let\k!default \k!saveddefault
+ \let\k!k!text \k!k!savedtext
+ \let\k!text \k!savedtext
+ \fi}
+
+\def\definebodyfontenvironment
+ {\dotripleempty\dodefinebodyfontenvironment}
+
+\def\dodefinebodyfontenvironment[#1][#2][#3]% class size settings
+ {\ifthirdargument
+ \@@beginfontdef
+ \doifelse{#2}\s!default
+ {\getparameters[\??ft\s!default][#3]}
+ {\normalizebodyfontsize#2\to\tempbodyfontsize
+ \addtocommalist\tempbodyfontsize\bodyfontenvironmentlist
+ \@EA\dododefinebodyfontenvironment\@EA[\tempbodyfontsize][#1][#3]}%
+ \@@endfontdef
+ \else
+ \definebodyfontenvironment[\fontclass][#1][#2]% change */*
+ \fi}
+
+\def\dododefinebodyfontenvironment[#1][#2][#3]% size class settings
+ {\@@beginfontdef
+ \doifundefined{\??ft#2#1\c!em} % \s!text goes wrong in testing because
+ {\def\docommand##1% % the 12pt alternative will called when
+ {\scratchdimen#1\relax % typesetting the test (or so)
+ \scratchdimen\csname\??ft\s!default##1\endcsname\scratchdimen
+ \normalizebodyfontsize\scratchdimen\to\tempbodyfontsize
+ \setevalue{\??ft#2#1##1}{\tempbodyfontsize}}%
+ \processcommacommand[\fontrelativesizelist]\docommand
+ \copyparameters
+ [\??ft#2#1][\??ft\s!default]
+ [\c!interlinespace,\c!em]}%
+ \getparameters[\??ft#2#1][#3]%
+ \@@endfontdef
+ % new code, see remark
+ \ifloadingfonts \else % only runtime
+ \doifundefined{\@size@#1} % only once
+ {\letvalue{\@size@#1}\empty % prevent loop
+ \defineunknownfont{#1}}% % safeguard
+ \fi
+ % so far
+ \setvalue{\@size@#1}{\docompletefontswitch[#1]}}
+
+%D {\bf Remark:} We need to cover the following cases,
+%D otherwise users can get 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 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 environment at the outer level.
+
+\def\checkbodyfontenvironment[#1]%
+ {\definebodyfontenvironment[\fontclass][#1][]}
+
+% original
+%
+% \def\setupbodyfontenvironment
+% {\dotripleempty\dosetupbodyfontenvironment}
+%
+% \def\dosetupbodyfontenvironment[#1][#2][#3]% class size settings
+% {\@@beginfontdef
+% \ifthirdargument
+% \getparameters[\??ft#1#2][#3]%
+% \else
+% \getparameters[\??ft#1][#2]%
+% \fi
+% \@@endfontdef}
+%
+% this one already catches both define/setup
+
+\def\setupbodyfontenvironment{\definebodyfontenvironment}
+
+% officially, but not needed (yet):
+%
+% \def\dosetupbodyfontenvironment[#1][#2][#3]% class size settings
+% {\ifthirdargument
+% \localbodyfontsize#2\relax
+% \normalizebodyfontsize\localbodyfontsize\to\normalizedbodyfontsize
+% \doifundefinedelse{\??ft#1\normalizedbodyfontsize\c!em}
+% {\definebodyfontenvironment[#1][#2][#3]}%
+% {\getparameters[\??ft#1\normalizedbodyfontsize][#3]}%
+% \else
+% \localbodyfontsize#1\relax
+% \normalizebodyfontsize\localbodyfontsize\to\normalizedbodyfontsize
+% \doifundefinedelse{\??ft\normalizedbodyfontsize\c!em}
+% {\definebodyfontenvironment[#1][#2]}%
+% {\getparameters[\??ft\normalizedbodyfontsize][#2]}%
+% \fi}
+
+%D Just a couple of interface macros:
+
+\def\bodyfontvariable#1%
+ {\??ft\ifcsname\??ft\fontclass#1\endcsname\fontclass\fi#1}
+
+\def\bodyfontcsname
+ {\csname\bodyfontvariable}
+
+\def\bodyfontinterlinespecs
+ {\bodyfontvariable{\normalizedbodyfontsize\c!interlinespace}}
+
+\def\bodyfontinterlinespace
+ {\csname\bodyfontinterlinespecs\endcsname}
+
+%D We default all parameters to the main bodyfont size (begin
+%D \type{#1}), so the next setup is valid too:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[24pt]
+%D \stoptyping
+%D
+%D All parameters can be redefined when needed, so one does
+%D not have to stick to the 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
+%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
+%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.
+%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 \magstep1,
+%D tfb=cmr12 scaled \magstep2,
+%D tfc=cmr12 scaled \magstep3,
+%D tfd=cmr12 scaled \magstep4,
+%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
+%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.
+
+\def\definebodyfont
+ {\doquadrupleempty\redefinebodyfont}
+
+\def\redefinebodyfont[#1][#2][#3][#4]%
+ {\iffourthargument
+ \processcommacommand[#1]{\reredefinebodyfont[#2][#3][#4]}%
+ \else
+ \dodefinebodyfont[#1][#2][#3]%
+ \fi}
+
+\def\reredefinebodyfont[#1][#2][#3]#4%
+ {\pushmacro\fontclass
+ \doifelse{#4}\s!default
+ {\let\fontclass\empty}
+ {\def\fontclass{#4}}%
+ \definebodyfont[#1][#2][#3]%
+ \popmacro\fontclass}
+
+\def\dodefinebodyfont[#1][#2][#3]% body|identifier style defs|identifier
+ {\ifthirdargument
+ \doifnumberelse{#1}
+ {\doifassignmentelse{#3}
+ {% [12pt] [style] [settings]
+ \doifundefined{#2}{\expanded{\definefontstyle[#2][#2]}}% new
+ \processcommalist[#1]{\dododefinebodyfont{#2}{#3}}}
+ {% [12pt] [style] [identifier]
+ \dodefinedefaultbodyfont[#1][#2][#3]}} % body style identifier
+ {% [identifier] [style] [settings] % see ***
+ \setvalue{\s!default#1#2}##1##2{\expanded{\xdodefinebodyfont[##1][##2][#3]}}}%
+ \else\ifsecondargument
+ \definebodyfont[#1][\c!rm][#2]%
+ \else
+ \doifundefined{\@size@#1} % Maybe there are default dependancies
+ {\defineunknownfont{#1}}% defined which we can use ([unknown])
+ \doifundefined{\@size@#1} % and if not, then we have at least to
+ {\definebodyfont[#1][\c!rm][]}% make sure some basics are set up.
+ \fi\fi}
+
+\def\xdodefinebodyfont[#1][#2][#3]% body|identifier style defs|identifier
+ {%\writestatus{[#1]}{[#2][#3]}%
+ \checkrelativefontsize{#2}% rather new, inherit from other defs
+ \ifundefined{#2}\expanded{\definefontstyle[#2][#2]}\fi % new
+ \processcommalist[#1]{\dododefinebodyfont{#2}{#3}}%
+ \let\relativefontsize\defaultrelativefontsize}
+
+\def\dododefinebodyfont#1#2#3% style defs body
+ {\checkbodyfontenvironment[#3]% just to be sure.
+ \processcommalist[#2]{\dodododefinebodyfont{#1}{#3}}}
+
+\def\dodododefinebodyfont#1#2#3% style body def
+ {\dododododefinebodyfont{#1}{#2}[#3]}
+
+\newif \ifresolvefontfile % protected by fontclass anyway
+
+\def\resolvefontname#1 {\truefontname{#1} }
+
+\def\iflocalclassfonts{\ifx\fontclass\empty}
+
+\def\dododododefinebodyfont#1#2[#3#4#5=#6]% style body def
+ {\ifundefined{#1#3#4#5}%
+ %\checkbodyfont{#2}{#1}{#3#4}{#5}% not \definefontsize[#5]
+ \checkbodyfont{#1}{#3#4}{#5}% not \definefontsize[#5]
+ \fi
+ \iflocalclassfonts
+ \letbeundefined{*\fontclass#2#1#3#4#5*}%
+ \scratchtoks{#6}%
+ \expanded{\unexpanded\noexpand\setvalue{#2#1#3#4#5}%
+ {\noexpand\xxdododefinefont{\relativefontsize}{#2}%
+ {#2#1#3#4#5}{\the\scratchtoks}}}%
+ \else
+ %\expanded{\writestatus{defining}{[\fontclass][#2#1#3#4#5] \resolvefontname#6 }}%
+ \global\letbeundefined{*\fontclass#2#1#3#4#5*}%
+ \ifresolvefontfile
+ \unexpanded\setxvalue{\fontclass#2#1#3#4#5}%
+ {\noexpand\xxdododefinefont{\relativefontsize}{#2}%
+ {#2#1#3#4#5}{\resolvefontname#6 }}%
+ \else
+ \scratchtoks{#6}%
+ \expanded{\unexpanded\noexpand\setgvalue{\fontclass#2#1#3#4#5}%
+ {\noexpand\xxdododefinefont{\relativefontsize}{#2}%
+ {#2#1#3#4#5}{\the\scratchtoks}}}%
+ \fi
+ \fi}
+
+% \def\checkbodyfont#1#2#3#4% body style alt size / gdef % #4 can be empty
+% {\def\c!!mm{#2}%
+% \ifx\c!!mm\c!mm % prevents \max and alike (re)defs
+% \unexpanded\setgvalue {#2}{\setcurrentfontstyle {#2}}% \rm
+% \unexpanded\setgvalue {#3}{\setcurrentfontalternative {#3}}% \sl
+% \else
+% \unexpanded\setgvalue {#2#4}{\setcurrentfontstylesize {#2}{#4}}% \rma
+% \unexpanded\setgvalue {#3#4}{\setcurrentfontalternativesize {#3}{#4}}% \sla
+% \unexpanded\setgvalue {#2#3#4}{\setcurrentfontstylealternativesize{#2}{#3}{#4}}% \rmsla
+% \unexpanded\setgvalue {#2}{\setcurrentfontstyle {#2}}% \rm
+% \unexpanded\setgvalue {#3}{\setcurrentfontalternative {#3}}% \sl
+% \unexpanded\setgvalue {#2\c!x}{\setcurrentfontxstylealternative {#2}}% \rmx
+% \unexpanded\setgvalue{#2\c!xx}{\setcurrentfontxxstylealternative {#2}}% \rmxx
+% \unexpanded\setgvalue {#3\c!x}{\setcurrentfontxalternative {#3}}% \slx
+% \unexpanded\setgvalue{#3\c!xx}{\setcurrentfontxxalternative {#3}}% \slxx
+% \unexpanded\setgvalue {#2#3}{\setcurrentfontstylealternative {#2}{#3}}% \rmsl
+% \fi}
+%
+% leaner
+
+\def\checkbodyfont#1% tests for ttsl mmbf
+ {\def\c!!mm{#1}%
+ \ifx\c!!mm\c!mm % prevents \max and alike (re)defs
+ \expandafter\checkmathbodyfont
+ \else
+ \expandafter\checktextbodyfont
+ \fi{#1}} % no \c!!mm, not expanded later on
+
+\def\checkmathbodyfont#1#2#3% style alt size / gdef % #3 can be empty
+ {%\message{!m #1 #2 #3!}%
+ % #1 #2 #3 = signal
+ \unexpanded\setgvalue {#1#2#3}{\setcurrentfontstylealternativesize{#1}{#2}{#3}}% \mmsla
+ \unexpanded\setgvalue {#1}{\setcurrentfontstyle {#1}}% \mm
+ \unexpanded\setgvalue {#2}{\setcurrentfontalternative {#2}}}% \sl
+
+\def\checktextbodyfont#1#2#3% style alt size / gdef % #3 can be empty
+ {%\message{!t #1 #2 #3!}%
+ \unexpanded\setgvalue {#1#3}{\setcurrentfontstylesize {#1}{#3}}% \rma
+ \unexpanded\setgvalue {#2#3}{\setcurrentfontalternativesize {#2}{#3}}% \sla
+ \unexpanded\setgvalue {#1#2#3}{\setcurrentfontstylealternativesize{#1}{#2}{#3}}% \rmsla
+ \unexpanded\setgvalue {#1}{\setcurrentfontstyle {#1}}% \rm
+ \unexpanded\setgvalue {#2}{\setcurrentfontalternative {#2}}% \sl
+ \unexpanded\setgvalue {#1\c!x}{\setcurrentfontxstylealternative {#1}}% \rmx
+ \unexpanded\setgvalue{#1\c!xx}{\setcurrentfontxxstylealternative {#1}}% \rmxx
+ \unexpanded\setgvalue {#2\c!x}{\setcurrentfontxalternative {#2}}% \slx
+ \unexpanded\setgvalue{#2\c!xx}{\setcurrentfontxxalternative {#2}}% \slxx
+ \unexpanded\setgvalue {#1#2}{\setcurrentfontstylealternative {#1}{#2}}}% \rmsl
+
+\def\dodefinedefaultbodyfont[#1][#2][#3]% sizes styles identifier
+ {\def\dododefinedefaultbodyfont##1%
+ {\def\dodododefinedefaultbodyfont####1%
+ {\def\dododododefinedefaultbodyfont########1%
+ {\doifdefined{\s!default########1####1}
+ {% [12pt] [style] [identifier]
+ \getvalue{\s!default########1####1}{##1}{####1}}}%
+ \processcommalist[#3]\dododododefinedefaultbodyfont}%
+ \processcommalist[#2]\dodododefinedefaultbodyfont}%
+ \processcommalist[#1]\dododefinedefaultbodyfont}
+
+%D Unknown families are added to the family list! For the
+%D moment we also set the direct calls here. Some day a better
+%D solution will be implemented. The good news is that unknown
+%D fonts are defined automatically.
+
+\newif\ifdefiningunknownfont
+
+% \def\defineunknownfont#1%
+% {\let\c!savedtext\c!text
+% \let\c!text\s!text
+% \donefalse
+% \def\docommand##1%
+% {\doifdefined{\??ft\s!default##1}
+% {\donetrue
+% \scratchdimen#1\relax
+% \scratchdimen\csname\??ft\s!default##1\endcsname\scratchdimen
+% \normalizebodyfontsize\scratchdimen\to\!!stringa
+% \letvalue{\??ft#1##1}\!!stringa}}%
+% \processcommacommand[\fontrelativesizelist]\docommand
+% \let\c!text\c!savedtext
+% \ifdone
+% \donefalse
+% \def\defineunknownbodyfont##1% see ***
+% %{\doifdefined{\s!default##1}
+% % {\donetrue\getvalue{\s!default##1}{#1}}}%
+% {\doifdefined{\s!default\s!default##1}
+% {\donetrue\getvalue{\s!default\s!default##1}{#1}{##1}}}%
+% \processcommacommand
+% [\fontstylelist]
+% \defineunknownbodyfont
+% \ifdone
+% \setvalue{\@size@#1}{\docompletefontswitch[#1]}%
+% \ifdefiningunknownfont \else
+% \definingunknownfonttrue
+% \def\defineunknownsubfont##1%
+% {\doifundefined{\@size@\getvalue{\??ft#1##1}}
+% {\defineunknownfont{\getvalue{\??ft#1##1}}}}%
+% \processcommacommand[\fontrelativesizelist]\defineunknownsubfont
+% \definingunknownfontfalse
+% \fi
+% \fi
+% \ifdone
+% \showmessage\m!fonts{14}{#1}%
+% \fi
+% \fi}
+
+\def\dodefineunknownfont#1#2%
+ {\doifdefined{\??ft\s!default#2}
+ {\donetrue
+ \scratchdimen#1\relax
+ \scratchdimen\csname\??ft\s!default#2\endcsname\scratchdimen
+ \normalizebodyfontsize\scratchdimen\to\!!stringa
+ \letvalue{\??ft#1#2}\!!stringa}}
+
+% \def\dodefineunknownbodyfont#1#2% see ***
+% {\doifdefined{\s!default\s!default#2}
+% {\donetrue
+% \getvalue{\s!default\s!default#2}{#1}{#2}}}
+%
+% but ... it needs to be as follows:
+%
+% \def\dodefineunknownbodyfont#1#2% see ***
+% {\doifdefined{\s!default\fontclass#2}% was \s!default\s!default (related to change */*)
+% {\donetrue
+% \getvalue{\s!default\fontclass#2}{#1}{#2}}}
+%
+% eh ... this does not work so we revert back to:
+
+\def\dodefineunknownbodyfont#1#2% see ***
+ {\doifdefined{\s!default\s!default#2}% somehow related to */*
+ {\donetrue
+ \getvalue{\s!default\s!default#2}{#1}{#2}}}
+
+\def\dodefineunknownsubfont#1#2%
+ {\doifundefined{\@size@\getvalue{\??ft#1#2}}
+ {\donetrue
+ \defineunknownfont{\getvalue{\??ft#1#2}}}}
+
+\def\defineunknownfont#1%
+ {\let\c!savedtext\c!text
+ \let\c!text\s!text
+ \donefalse
+ \processcommacommand[\fontrelativesizelist]{\dodefineunknownfont{#1}}%
+ \let\c!text\c!savedtext
+ \ifdone
+ \donefalse
+ \processcommacommand
+ [\fontstylelist]
+ {\dodefineunknownbodyfont{#1}}%
+ \ifdone
+ \donefalse
+ \setvalue{\@size@#1}{\docompletefontswitch[#1]}%
+ \ifdefiningunknownfont \else
+ \definingunknownfonttrue
+ \processcommacommand[\fontrelativesizelist]{\dodefineunknownsubfont{#1}}%
+ \definingunknownfontfalse
+ \fi
+ \fi
+ \ifdone
+ \showmessage\m!fonts{14}{#1}%
+ \fi
+ \fi}
+
+% \def\defineunknownfontstyles#1%
+% {\def\defineunknownbodyfont##1% see ***
+% {\executeifdefined{\s!default\s!default##1}\gobbletwoarguments{#1}{##1}}%
+% \rawprocesscommacommand[\fontstylelist]\defineunknownbodyfont}
+
+%D These macros show that quite some definitions take place.
+%D Fonts are not loaded yet! This means that at format
+%D generation time, no font files are preloaded.
+
+%D A previous implementation used:
+%D
+%D \starttyping
+%D \type {\setvalue{name}{\donottest...}}
+%D \stoptyping
+%D
+%D instead of the more memory hungry:
+%D
+%D \starttyping
+%D \unexpanded\setvalue{name}{...}
+%D \stoptyping
+%D
+%D The first alternative saves about 500 hash entries (about
+%D 2.5\% of the total number of entries used. The second
+%D alternative is currently used, because that one can more
+%D easily be made \ETEX\ aware.
+
+%D \macros
+%D {everybodyfont,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.
+
+% \ifx\everybodyfont\undefined % permits reloading
+% \newevery \everybodyfont \EveryBodyFont
+% \fi
+
+%D At the system level one can initialize thing like:
+%D
+%D \starttyping
+%D \appendtoks \setupspacing \to \everybodyfont
+%D \stoptyping
+%D
+%D While users can add their own non standard commands like:
+%D
+%D \starttyping
+%D \EveryBodyFont{\message{changing to bodyfont \the\bodyfontsize}}
+%D \stoptyping
+%D
+%D Personnaly I never felt the need for such extensions, but
+%D at least its possible.
+
+%D \macros
+%D {globalbodyfontsize,localbodyfontsize}
+%D
+%D Next we'll do the tough job of font switching. Here we
+%D have to distinguish between the global (overal) bodyfont
+%D size and the local (sometimes in the textflow) size. We
+%D store these dimensions in two \DIMENSION\ registers.
+
+\ifdefined\globalbodyfontsize\else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
+\ifdefined\localbodyfontsize \else \newdimen\localbodyfontsize \fi \localbodyfontsize =\globalbodyfontsize
+
+%D \macros
+%D {bodyfontsize}
+%D
+%D These two registers are not to be misused in calculations.
+%D For this purpose we keep a copy:
+
+\newdimen\bodyfontsize \bodyfontsize=\globalbodyfontsize
+
+%D \macros
+%D {outputresolution}
+%D
+%D Sometimes (to be honest: not in this module) we need to
+%D take the system resolution into account. Therefore we also
+%D define a macro:
+
+\def\outputresolution {600}
+
+%D \macros
+%D {bodyfontfactor,bodyfontpoints}
+%D
+%D For multiplication purposes we keep an auxiliary counter
+%D and macro (here the expansion is not explicitly needed):
+
+\newcount\bodyfontpoints \dimensiontocount\bodyfontsize\bodyfontpoints
+
+\edef\bodyfontfactor{\withoutpt\the\bodyfontsize}
+
+%D When we assign for instance 12pt to a \DIMENSION\ register
+%D the \type{\the}'d value comes out as 12.0pt, which is
+%D often not the way users specify the bodyfont size. Therefore
+%D we also store the normalized value.
+
+\chardef\fontdigits=2 % was 1
+
+% \def\normalizebodyfontsize#1\to#2%
+% {\scratchdimen#1\relax
+% \ifcase\fontdigits\advance\scratchdimen.5\points\fi
+% \@EA\@EA\@EA\donormalizedbodyfontsize\@EA\WITHOUTPT\the\scratchdimen00\to#2}
+%
+% \def\donormalizedbodyfontsize#1.#2#3#4\to#5% \points ?
+% {\edef#5%
+% {#1%
+% \ifcase\fontdigits\or
+% \ifcase#2 \else.#2\fi % and not: \ifcase#2\else ...
+% \else
+% \ifcase#2#3 \else.#2\ifcase#3 \else#3\fi\fi % not: \ifcase#2#3\else ...
+% \fi
+% \s!pt}}
+
+\def\normalizebodyfontsize#1\to#2%
+ {\scratchdimen\dimexpr#1+\ifcase\fontdigits.5\or.05\or.005\fi\points\relax
+ \@EA\@EA\@EA\donormalizedbodyfontsize\@EA\WITHOUTPT\the\scratchdimen000\to#2}
+
+\def\donormalizedbodyfontsize#1.#2#3#4#5\to#6% \points ?
+ {\edef#6% not \ifcase#2\else due to \relax adding
+ {#1%
+ \ifcase\fontdigits
+ \or \ifcase#2 \else .#2\fi % 1
+ \or \ifcase#2#3 \else .#2\ifcase#3 \else #3\fi\fi % 2
+ \else \ifcase#2#3#4 \else .#2\ifcase#4 \ifcase#3 \else#3\fi \else#3#4\fi\fi % 3
+ \fi
+ \s!pt}}
+
+%D To be internationalized:
+
+\def\korpsgrootte {\bodyfontsize}
+\def\korpspunten {\bodyfontpoints}
+
+%D some day.
+
+%D \macros
+%D {fontstyle,fontalternative,fontsize}
+%D
+%D Within a bodyfont, fonts can come in different sizes. For
+%D instance \type{\tf} is accompanied by \type{\tfa},
+%D \type{\tfb} etc. The first two characters denote the
+%D alternative, while the third character in these sequences
+%D represents the size. The actual size is saved in a macro
+%D
+%D The style, being roman (\type{\rm}), sans serif (\type{\ss})
+%D etc. is also available in a macro in \type{rm}, \type{ss}
+%D etc. form:
+
+\let\defaultfontalternative = \c!tf
+\let\defaultfontstyle = \empty
+\let\defaultfontsize = \empty
+
+\let\fontalternative = \defaultfontalternative
+\let\fontstyle = \defaultfontstyle
+\let\fontsize = \defaultfontsize
+
+%D {\em The following approach is obsolete.}
+%D
+%D All things related to fonts are grouped into files with
+%D names like \type{font-cmr}. These files are loaded by:
+
+\def\resetfontdefinitionfile[#1]%
+ {\letbeundefined{\c!file\f!fontprefix#1}}
+
+\newif\ifloadfontfileonce
+
+\def\doreadfontdefinitionfile#1#2% #1 = set/switch state
+ {\doifundefined{\c!file\f!fontprefix#2}%
+ {\ifloadfontfileonce
+ \letvalue{\c!file\f!fontprefix#2}\empty
+ \fi
+ \makeshortfilename[\truefilename{\f!fontprefix#2}]%
+ \startreadingfile
+ \readsysfile{\shortfilename.mkii}
+ {\showmessage\m!fonts2{#2}}
+ {\showmessage\m!fonts3{#2}}%
+ \stopreadingfile}}
+
+%D When \type {\loadfontfileoncetrue}, such files are
+%D only loaded once! This permits redundant loading, but at
+%D the same time forced grouping when we want continuously mix
+%D all kind of font, which of course is a kind of
+%D typographically sin. The \type{"} is made inactive if
+%D needed to prevent problems with loading files that use this
+%D character in numbers.
+
+\def\doswitchpoints[#1]%
+ {\expanded{\dodoswitchpoints{#1}}}
+
+\def\dodoswitchpoints#1%
+ {\doifundefined{\@size@#1}
+ {\defineunknownfont{#1}}%
+ %\defineunknownfontstyles{#1}%
+ \doifdefinedelse{\@size@#1}
+ {\getvalue{\@size@#1}%
+ \localbodyfontsize#1\relax
+ \normalizebodyfontsize\localbodyfontsize\to\normalizedbodyfontsize
+ \checkbodyfontenvironment[\normalizedbodyfontsize]}
+ {\showmessage\m!fonts4{#1}}}
+
+\unprotected \def\doswitchstyle[#1]%
+ {\doifdefinedelse{\@style@#1}
+ {\getvalue{\@style@#1}%
+ \edef\fontstyle{#1}%
+ \ifmmode\mr\fi % in order to be compatible with \rm in math mode
+ }% \the\everybodyfont} % cleaner, in setting size as well as style
+ {\showmessage\m!fonts5{#1}}}
+
+%D \TEX\ loads font metric files like \type{cmr10.tfm} and
+%D \type{tir.tfm} only once. In \PLAIN\ \TEX\ some font files
+%D are {\em preloaded}. This means that the font files are
+%D loaded, but not accessible yet by name. This is accomplished
+%D by saying:
+%D
+%D \starttyping
+%D \font\preloaded=cmr10 at 11pt
+%D \stoptyping
+%D
+%D and using the name \type{\preloaded} again and again, so
+%D fonts are indeed loaded, but unnamed, and therefore
+%D unaccessible. In \CONTEXT\ we don't preload fonts, not even
+%D the \PLAIN\ \TEX\ ones, although users can access them. Now
+%D why is this done?
+
+%D Defining fonts using \type{\definebodyfont} takes time, so we
+%D prefer to predefine at least the Computer Modern Roman
+%D fonts. However, loading all those fonts at definition time
+%D would take both time and space. But even worse, once fonts
+%D are loaded into memory, their encoding vector is fixed,
+%D which is a handicap when we want to distribute the compact
+%D \type{fmt} files. So what we want to do is defining fonts in
+%D a way that postpones the loading. We accomplish this by only
+%D loading the fonts when we switch to another bodyfont size.
+%D Among the other alternatives, such as loading the font at
+%D the moment of activation and redefining the activation
+%D macro afterwards, this proved to be the most efficient
+%D alternative.
+%D
+%D The next few macros take care of the one exeption on this
+%D scheme. When at format generation time we load the default
+%D font file, the one that defines the Computer Modern Fonts,
+%D we don't want the fonts metrics to end up in the format
+%D file, so we temporary prohibit loading. This means that at
+%D runtime we have to load the default bodyfont size just before
+%D we start typesetting.
+%D
+%D Therefore we have to signal the font switching macros that
+%D we are preloading fonts. As long as the next boolean is,
+%D true, no loading is done.
+
+\newif\ifloadingfonts \loadingfontstrue
+
+%D \macros
+%D {preloadfonts}
+%D
+%D Preloading is only called for once, during the startup
+%D sequence of a session. After the loading job is done, the
+%D macro relaxes itself and reset the signal.
+
+\def\preloadfonts % never called, needs a clean up
+ {\showmessage\m!fonts6{\normalizedbodyfontsize\normalspace\fontstyle}%
+ \global\loadingfontsfalse
+ \doswitchpoints[\normalizedbodyfontsize]%
+ \doswitchstyle[\fontstyle]%
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace
+ \global\let\preloadfonts\relax}
+
+% \prependtoks \preloadfonts \to \everydump % saves .1 s on a DELL P60 - 2GHZ
+
+%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.
+
+\def\dosetfont#1#2% #1 = set/switch state
+ {\doifelse{#2}\v!global
+ {\restoreglobalbodyfont}
+ {\processcommacommand[#2]{\dodosetfont{#1}}% ##1 get also passed
+ \ifloadingfonts\else
+ \doswitchpoints[\normalizedbodyfontsize]%
+ \doswitchstyle[\fontstyle]%
+ \fi}%
+ \chardef\currentxfontsize\zerocount}
+
+\def\dodosetfont#1#2% #1 = set/switch state | check fo rempty, else space
+ {\doifsomething{#2}{\dododosetfont{#1}{#2}{\showmessage\m!fonts4{#2}}}}
+
+\def\dododosetfont#1#2#3% #1 = set/switch state
+ {\doifnumberelse{#2}
+ {\dodododosetfont{#1}{#2}{#3}}
+ {\doifdefinedelse{\??ft\normalizedbodyfontsize\interfaced{#2}}
+ {\edef\fontstep{\bodyfontcsname\normalizedbodyfontsize\interfaced{#2}\endcsname}%
+ \expanded{\dodododosetfont{#1}{\fontstep}}{#3}}
+ {\doifelse{#2}\v!reset
+ {\let\fontstyle\empty % new 31/7/2006
+ \let\fontsize \empty}
+ {\doifdefinedelse{\@style@#2}
+ {\edef\fontstyle{#2}}
+ {\doreadfontdefinitionfile{#1}{#2}}}}}}
+
+\def\dodododosetfont#1#2#3% #1 = set/switch state
+ {\scratchdimen#2\relax
+ \normalizebodyfontsize\scratchdimen\to\normalizedsetfont
+ \doifundefined{\@size@\normalizedsetfont}
+ {\defineunknownfont{#2}}%
+ \doifdefinedelse{\@size@\normalizedsetfont}
+ {\localbodyfontsize\normalizedsetfont
+ \let\normalizedbodyfontsize\normalizedsetfont}
+ {#3\dosetsubstitutefont{#1}{#2}}}
+
+%D In the previous 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.
+
+\chardef\currentxfontsize=0
+
+%D When users specify for instance a 13 point bodyfont while no
+%D such bodyfont is defined, the system automatically tries to
+%D find a best fit, that is the nearest smaller defined
+%D bodyfontzize. A smaller one is definitely better than a larger
+%D one, simply because otherwise a lot of overfull box messages
+%D are more probable to occur. By taking a value slightly
+%D smaller than half a point, we can use the next method.
+
+\def\dosetsubstitutefont#1#2% #1 = set/switch state
+ {\scratchdimen#2\relax
+ \advance\scratchdimen .499\points
+ \dimensiontocount\scratchdimen\scratchcounter
+ \advance\scratchcounter \minusone
+ \ifnum\scratchcounter>\plusthree
+ \dododosetfont{#1}{\the\scratchcounter\s!pt}{}%
+ \fi}
+
+% The following bunch of macros deals with the (run time)
+% expansion of names onto the definitions made by \type
+% {\definebodyfont}.
+
+% \let\fontbody \empty % ... 10pt 11pt 12pt ...
+% \let\fontstyle \empty % rm ss tt mm hw cg ...
+% \let\fontalternative\empty % tf bf sl it bs bi sc ...
+% \let\fontsize \empty % xy-abcd ...
+
+\def\defaultfontbody{\normalizedbodyfontsize}
+
+\let\fontbody\defaultfontbody
+
+\let\fontclass\empty \let\globalfontclass\fontclass
+
+% \def\setcurrentfontclass#1%
+% {\edef\fontclass{#1}}
+
+\def\registerfontclass#1%
+ {\letgvalue{\@fontclass@#1}\v!yes} % global ?
+
+\def\setcurrentfontclass#1%
+ {\ifcsname\@fontclass@#1\endcsname
+ \edef\fontclass{#1}%
+ \fi}
+
+\let\defaultfontstyle \c!rm
+\let\defaultfontalternative \c!tf
+\let\defaultfontsize \empty
+
+%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
+
+\chardef\synchronizebigmathflag=1
+
+\appendtoks
+ \ifcase\synchronizebigmathflag
+ % never
+ \or
+ \synchronizebigmath
+ \or
+ % always
+ \fi
+\to \everymathematics
+
+\def\nobigmath{\chardef\synchronizebigmathflag 0 }
+\def\bigmath {\chardef\synchronizebigmathflag 2 \synchronizebigmath}
+
+\let\bigmathfontsize\empty
+
+\def\synchronizebigmath
+ {\ifx\bigmathfontsize\fontsize
+ % already in sync
+ \else
+ \let\bigmathfontsize\fontsize
+ \synchronizemath \synchronizetext
+ \fi}
+
+\def\checkbigmathsynchronization
+ {\ifcase\synchronizebigmathflag
+ % never
+ \or
+ \ifmmode \synchronizebigmath \fi
+ \or
+ \synchronizebigmath
+ \fi}
+
+%D So far for synchronisation.
+
+\def\dosetcurrentfontsize#1%
+ {\edef\fontsize{#1}%
+ \checkbigmathsynchronization}
+
+\def\dosetcurrentfontalternative#1%
+ {\edef\fontalternative{#1}%
+ \ifmmode % maybe no test, or actually, an option
+ \fam\csname\fontalternative\s!fam\endcsname
+ \fi}
+
+\def\setcurrentfont#1#2#3#4%
+ {%\message{[1 #1 #2 #3 #4]}%
+ \edef\fontbody{#1}%
+ \edef\fontstyle{#2}%
+ \dosetcurrentfontalternative{#3}%
+ \dosetcurrentfontsize{#4}%
+ \synchronizefont}
+
+\def\setcurrentfontbody#1%
+ {%\message{[2 #1]}%
+ \edef\fontbody{#1}%
+ \synchronizefont}
+
+% \def\setcurrentfontstyle#1%
+% {%\message{[3 #1]}%
+% \edef\fontstyle{#1}%
+% \ifmmode\mr\fi % otherwise \rm not downward compatible
+% \synchronizefont}
+%
+% For Taco: optional fall backs:
+
+\ifx\checkfontclass\undefined \let\checkfontclass\gobbleoneargument \fi % implemented in type-ini
+
+\def\setcurrentfontstyle#1%
+ {%\message{[3 #1]}%
+ \checkfontclass{#1}%
+ \edef\fontstyle{#1}%
+ \ifmmode\mr\fi % otherwise \rm not downward compatible
+ \synchronizefont}
+
+\def\setcurrentfontbodyalternative#1#2%
+ {%\message{[4 #1 #2]}%
+ \edef\fontbody{#1}%
+ \dosetcurrentfontalternative{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontalternative#1%
+ {%\message{[5 #1]}%
+ \dosetcurrentfontalternative{#1}%
+ \synchronizefont}
+
+\def\setcurrentfontsize#1%
+ {%\message{[6 #1]}%
+ \dosetcurrentfontsize{#1}%
+ \synchronizefont}
+
+\def\setcurrentfontstylealternative#1#2% \rmsl
+ {%\message{[7 #1 #2]}%
+ \edef\fontstyle{#1}%
+ \dosetcurrentfontalternative{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontstylesize#1#2% \rmsla
+ {%\message{[8 #1 #2]}%
+ \edef\fontstyle{#1}%
+ \dosetcurrentfontsize{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontalternativesize#1#2% \sla
+ {%\message{[9 #1 #2]}%
+ \dosetcurrentfontalternative{#1}%
+ \dosetcurrentfontsize{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontstylealternativesize#1#2#3% \rmsla
+ {%\message{[10 #1 #2 #3]}%
+ \edef\fontstyle{#1}%
+ \dosetcurrentfontalternative{#2}%
+ \dosetcurrentfontsize{#3}%
+ \synchronizefont}
+
+%D In principle one can assign alternative fallback routines.
+%D Some day we will.
+
+\newtoks\fontstrategies
+\newif\iftryingfont
+
+\let\fontstrategy\relax
+
+\def\synchronizefont
+ {\tryingfonttrue
+ \ifx\fontclass\empty\else
+ \global\let\fontstrategy\dofontclassstrategy
+ \the\fontstrategies \relax % \relax still needed ?
+ \fi
+ \iftryingfont
+ \global\let\fontstrategy\dofontstrategy
+ \the\fontstrategies \relax % \relax still needed ?
+ \fi
+ \ifskipfontcharacteristics
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+\def\dofontstrategy#1#2#3#4#5%
+ {\ifcsname#2#3#4#5\endcsname
+ #1\csname#2#3#4#5\endcsname \tryingfontfalse
+ \fi}
+
+\def\dofontclassstrategy#1#2#3#4#5%
+ {\ifcsname\fontclass#2#3#4#5\endcsname
+ #1\csname\fontclass#2#3#4#5\endcsname \tryingfontfalse
+ \fi}
+
+\appendtoks \iftryingfont \fontstrategy \autofontsizefalse % --- --- --- --- % pt tt bf a
+ \fontbody \fontstyle \fontalternative \fontsize
+\fi \to \fontstrategies
+
+\appendtoks \iftryingfont \fontstrategy \autofontsizetrue % --- --- --- def % pt tt bf
+ \fontbody \fontstyle \fontalternative \defaultfontsize
+\fi \to \fontstrategies
+
+\appendtoks \iftryingfont \fontstrategy \autofontsizetrue % --- --- def --- % pt tt tf a
+ \fontbody \fontstyle \defaultfontalternative \fontsize
+\fi \to \fontstrategies
+
+\appendtoks \iftryingfont \fontstrategy \autofontsizetrue % --- --- def def % pt tt tf
+ \fontbody \fontstyle \defaultfontalternative \defaultfontsize
+\fi \to \fontstrategies
+
+\appendtoks \iftryingfont \fontstrategy \autofontsizefalse % --- def def def % pt rm tf
+ \fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize
+\fi \to \fontstrategies
+
+\appendtoks \iftryingfont \fontstrategy \autofontsizetrue % def def def def % rm tf
+ \defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize
+\fi \to \fontstrategies
+
+%D Let's synchronize:
+
+\newif\ifsynchronizefonts \synchronizefontstrue
+
+\prependtoks
+ \ifsynchronizefonts
+ \synchronizemath
+ \synchronizetext
+ \synchronizefont % problem: syncs last font
+ \fi
+\to \everybodyfont
+
+%D Setting the normal sized 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}.
+
+\def\dosetcurrentfontxxxalternative#1#2#3#4%
+ {\chardef\currentxfontsize#2\relax
+ \ifmmode
+ #4%
+ \else\ifcsname\bodyfontvariable{\normalizedbodyfontsize#3}\endcsname
+ \setcurrentfontbodyalternative{\bodyfontcsname\normalizedbodyfontsize#3\endcsname}{#1}%
+ \fi\fi}
+
+\def\setcurrentfontxalternative#1%
+ {\dosetcurrentfontxxxalternative{#1}1\c!x\scriptstyle
+ \let\tx\txx}
+
+\def\setcurrentfontxxalternative#1%
+ {\dosetcurrentfontxxxalternative{#1}2\c!xx\scriptscriptstyle
+ \let\tx\empty
+ \let\txx\empty}
+
+\def\checknestedxfontsize % option
+ {\ifcase\currentxfontsize\else\ifx\fontsize\empty\else
+ \chardef\currentxfontsize\zeropoint
+ \let\fontsize\empty
+ \let\tx\normaltx
+ \let\txx\normaltxx
+ \fi\fi}
+
+\def\setcurrentfontxalternative#1%
+ {\checknestedxfontsize
+ \dosetcurrentfontxxxalternative{#1}1\c!x\scriptstyle
+ \let\tx\txx}
+
+\def\setcurrentfontxxalternative#1%
+ {\checknestedxfontsize
+ \dosetcurrentfontxxxalternative{#1}2\c!xx\scriptscriptstyle
+ \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.
+
+% \def\setcurrentfontxstylealternative #1{\csname#1\endcsname\tfx}
+% \def\setcurrentfontxxstylealternative#1{\csname#1\endcsname\tfxx}
+
+\def\setcurrentfontxstylealternative #1{\csname#1\endcsname\tx}
+\def\setcurrentfontxxstylealternative#1{\csname#1\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
+%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 \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%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.
+
+\unexpanded\def\tx {\setcurrentfontxalternative \fontalternative}
+\unexpanded\def\txx{\setcurrentfontxxalternative\fontalternative}
+
+\let\normaltx \tx
+\let\normaltxx\txx
+
+%D \macros
+%D {definefontstyle}
+%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
+%D \starttyping
+%D \definefontstyle [serif,rm] [rm]
+%D \definefontstyle [sansserif,ss] [ss]
+%D \stoptyping
+
+\def\dodefinefontstyle[#1][#2]%
+ {\rawdoifinsetelse{#2}{\fontstylelist}
+ {}%\debuggerinfo\m!fonts{unknown style #2}}
+ {\addtocommalist{#2}\fontstylelist
+ \showmessage\m!fonts8{#2\space (#1)}}%
+ % check kan hier
+ \def\docommand##1%
+ {\setvalue{\@shortstyle@##1}{#2}%
+ \setvalue{\@style@##1}{\csname#2\endcsname}}%
+ \processcommalist[#1]\docommand}
+
+\def\definefontstyle
+ {\dodoubleargument\dodefinefontstyle}
+
+\def\setfontstyle#1#2% #1:name (roman, romaan) #2:style (rm)
+ {\edef\fontstyle{#1}%
+ \setcurrentfontstyle\normalizedbodyfontsize}
+
+\chardef\defaultskewcharmi=127 % '177
+\chardef\defaultskewcharsy= 48 % '60
+
+% \def\dosetskewchar#1%
+% {\skewchar\font\ifx\@@fontskewchar\empty#1\else\@@fontskewchar\fi}
+
+\def\dosetskewchar#1#2%
+ {\ifx\@@fontskewchar\empty
+ \skewchar\textfont #1#2%
+ \skewchar\scriptfont #1#2%
+ \skewchar\scriptscriptfont#1#2%
+ \else
+ \skewchar\textfont #1\@@fontskewchar
+ \skewchar\scriptfont #1\@@fontskewchar
+ \skewchar\scriptscriptfont#1\@@fontskewchar
+ \fi}
+
+%D The previous macros show that it's is not always
+%D neccessary to define the whole bunch of fonts, take for
+%D instance the sequence:
+%D
+%D \starttyping
+%D \setupbodyfont
+%D [ams]
+%D
+%D \definebodyfont [24pt] [mm]
+%D [ma=msam10 at 24pt,
+%D mb=msbm10 at 24pt]
+%D
+%D \switchtobodyfont
+%D [24pt]
+%D
+%D This is a 24pt $\blacktriangleleft$
+%D \stoptyping
+%D
+%D Here we didn't define the 24 point bodyfont environment, so
+%D it's defined automatically. Of course one can always use the
+%D \TEX\ primitive \type{\font} to switch to whatever font
+%D needed.
+
+%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}
+
+\def\dosetbodyfontface#1#2%
+ {\edef#1{\bodyfontcsname\normalizedbodyfontsize#2\endcsname}}
+
+\def\docompletefontswitch[#1]%
+ {\bodyfontsize#1\relax
+ \dimensiontocount\bodyfontsize\bodyfontpoints
+ \edef\bodyfontfactor{\withoutpt\the\bodyfontsize}%
+ \normalizebodyfontsize\bodyfontsize\to\normalizedbodyfontsize
+ \dosetbodyfontface \textface \s!text
+ \dosetbodyfontface \scriptface \s!script
+ \dosetbodyfontface \scriptscriptface \s!scriptscript}
+
+\docompletefontswitch[12pt] % init
+
+%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
+%D \starttyping
+%D \setupbodyfont[cmr,ams,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
+%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
+%D all kind of keywords into account.
+
+\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi
+\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi
+
+\chardef\bodyfontsetstate=0
+
+\definecomplexorsimple\setupbodyfont
+
+\def\simplesetupbodyfont
+ {\restoreglobalbodyfont
+ \saveinterlinespace}
+
+\def\complexsetupbodyfont[#1]%
+ {\doifsomething{#1}
+ {\dosetfont1{#1}%
+ \globalbodyfontsize\localbodyfontsize
+ \normalizebodyfontsize\globalbodyfontsize\to\normalizedglobalbodyfontsize
+ \let\globalfontstyle\fontstyle
+ \ifloadingfonts\else
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace
+ \fi}}
+
+\unexpanded\def\switchtobodyfont[#1]%
+ {\doifsomething{#1}
+ {\doifdefinedelse{\??ft\normalizedbodyfontsize\interfaced{#1}}
+ {\setbodyfontstep{#1}} % so we have a fast [small] switch
+ {\dosetfont0{#1}}%
+ \the\everybodyfont}} % indeed needed in case nothing is executed
+
+%D The following alternative is meant for math||to||text
+%D switching and will be optimized.
+
+\def\fastswitchtobodyfont#1%
+ {\ifcsname\??ft\normalizedbodyfontsize#1\endcsname
+ \edef\futurebodyfontsize
+ {\csname\??ft\normalizedbodyfontsize#1\endcsname}%
+ \ifcsname\@size@\futurebodyfontsize\endcsname
+ \csname\@size@\futurebodyfontsize\endcsname
+ \localbodyfontsize\futurebodyfontsize\relax
+ \fi
+ \fi
+ \csname\@style@\fontstyle\endcsname
+ \the\everybodyfont}
+
+%D Because the last macro can appear in arguments or be assigned
+%D to parameters, we protect this one for unwanted expansion.
+
+\def\dodosetmathfont#1%
+ {\setcurrentfontalternative{#1}%
+ % \doifdefinedelse{#1\s!fam} % adapted
+ % {\edef\mffam{\getvalue{#1\s!fam}}}
+ % {\edef\mffam{\getvalue{\c!nn\s!fam}}}%
+ \textfont \mrfam\textfont \mffam
+ \scriptfont \mrfam\scriptfont \mffam
+ \scriptscriptfont\mrfam\scriptscriptfont\mffam}
+
+\def\domffam#1%
+ {\csname\ifcsname#1\s!fam\endcsname#1\else\c!nn\fi\s!fam\endcsname}
+
+\def\mffam
+ {\domffam\fontalternative}
+
+\def\dosetmathfont
+ {\def\rm{\fam\mrfam}\dodosetmathfont}
+
+\def\enableencodinginmath
+ {\appendtoks
+ \everyhbox{\mr\everyhbox\emptytoks}%
+ \everyvbox{\mr\everyvbox\emptytoks}%
+ \to \everymathematics} % was \everymath
+
+% \enableencodinginmath % too untested to enable by default
+
+%D \starttyping
+%D $\cases{& \ccaron}$ $x=\hbox{\ccaron $x=\hbox{\ccaron}$}$
+%D \stoptyping
+
+%D The font specific features are bound to the filename.
+
+\def\updatefontparameters
+ {\edef\@@fontencoding{\truefontdata\fontfile \s!encoding}%
+ \edef\@@fontmapping {\truefontdata\fontfile \s!mapping }%
+ \edef\@@fonthandling{\truefontdata\somefontname\s!handling}%
+ \edef\@@fontfeatures{\truefontdata\fontfile \s!features}%
+ \edef\@@fontskewchar{\truefontdata\fontfile \s!skewchar}}
+
+\def\setfontcharacteristics
+ {\updatefontparameters % redundant, will go away, faster too
+ \fastenableencoding
+ {\ifx\@@fontencoding\empty
+ \s!default \else \@@fontencoding
+ \fi}%
+ \fastenablemapping
+ {\ifx\@@fontmapping\empty
+ \ifx\@@fontencoding\empty
+ \s!default \else \@@fontencoding
+ \fi
+ \else
+ \@@fontmapping
+ \fi}%
+ \fastenablehandling
+ {\ifx\@@fonthandling\empty
+ \s!default \else \@@fonthandling
+ \fi}%
+ {\lastfontidentifier}%
+ \the\everyfont
+ \synchronizepatternswithfont}
+
+\ifx\synchronizepatternswithfont\undefined
+ \def\synchronizepatternswithfont{\synchronizepatterns}
+\fi
+
+%D Experimental:
+
+\def\definefontfeature
+ {\dotripleargument\dodefinefontfeature}
+
+\def\dododefinefontfeature#1%
+ {\edef\!!stringa{\ifx\!!stringa\empty\else\!!stringa,\fi\executeifdefined{\??fa#1}\empty}}
+
+\def\dodefinefontfeature[#1][#2][#3]%
+ {\doifassignmentelse{#2}
+ {\setevalue{\??fa#1}{#2}}
+ {\let\!!stringa\empty
+ \processcommalist[#2]\dododefinefontfeature
+ \setevalue{\??fa#1}{\ifx\!!stringa\empty\else\!!stringa,\fi#3}}}
+
+\definefontfeature
+ [default]
+ [liga=yes,kern=yes,tlig=yes,trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [smallcaps]
+ [liga=yes,kern=yes,tlig=yes,trep=yes,smcp=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [oldstyle]
+ [liga=yes,kern=yes,tlig=yes,trep=yes,onum=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature % no calt
+ [arabic]
+ [language=dflt,script=arab,
+ init=yes,medi=yes,fina=yes,isol=yes,
+ liga=yes,dlig=yes,rlig=yes,clig=yes,
+ mark=yes,mkmk=yes,kern=yes,curs=yes]
+
+\definefontfeature
+ [none]
+ [features=no]
+
+%D The next auxilliary macro is an alternative to \type
+%D {\fontname}.
+
+% \def\purefontname#1{\expandafter\splitoffpurefontname\fontname#1 \\}
+%
+% extra level is needed:
+
+\def\purefontname#1{\@EA\splitoffpurefontname\@EA{\@EA{\@EA\unstringed\fontname#1}} \\}
+
+\def\splitoffpurefontname#1 #2\\{#1}
+
+%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
+
+\definecomplexorsimple\switchstyleonly
+
+\def\simpleswitchstyleonly#1% stupid version
+ {\complexswitchstyleonly[\strippedcsname#1]}
+
+\def\complexswitchstyleonly[#1]% todo : check
+ {\setcurrentfontstyle{\getvalue{\@shortstyle@#1}}%
+ \the\everybodyfont} % needed ?
+
+%D \macros
+%D {os,frak, goth, cal}
+%D
+%D Old style numerals can be typeset with \type{\os} and look
+%D like {\os 1234567890} instead of the more common looking
+%D 1234567890.
+%D
+%D On behalf of {\frac Tobias Burnus}, we define some more of
+%D these. Later we will link these names to real file names.
+
+% older
+%
+% \definefont [os] [OldStyle sa *]
+% \definefont [frak] [Fraktur sa *]
+% \definefont [goth] [Gothic sa *]
+% \definefont [cal] [Calligraphic sa *]
+% \definefont [bbd] [Blackboard sa *]
+%
+% newer
+
+\unexpanded\def\os {\mathortext{\fam\purefamily {oldstyle}}{\symbolicfont {OldStyle}}}
+\unexpanded\def\frak{\mathortext{\fam\purefamily {fraktur}}{\symbolicfont {Fraktur}}}
+\unexpanded\def\goth{\mathortext{\fam\purefamily {gothic}}{\symbolicfont {Gothic}}}
+\unexpanded\def\cal {\mathortext{\fam\purefamily{calligraphic}}{\symbolicfont{Calligraphic}}}
+\unexpanded\def\bbd {\mathortext{\fam\purefamily {blackboard}}{\symbolicfont {Blackboard}}}
+
+\definefontsynonym [OldStyle] [Serif]
+\definefontsynonym [Fraktur] [Serif]
+\definefontsynonym [Gothic] [Serif]
+\definefontsynonym [Calligraphic] [Serif]
+\definefontsynonym [Blackboard] [Serif]
+
+%D \macros
+%D {fraktur, gothic, calligraphic, blackboard}
+%D
+%D These macros assume that we use text fonts, and not math
+%D families.
+
+\ifx\mathtext\undefined \let\mathtext\hbox \fi
+
+\unexpanded\def\fraktur #1{\mathortext\domathtext\donothing{\frak#1}}
+\unexpanded\def\gothic #1{\mathortext\domathtext\donothing{\goth#1}}
+\unexpanded\def\calligraphic#1{\mathortext\domathtext\donothing{\cal #1}}
+\unexpanded\def\blackboard #1{\mathortext\domathtext\donothing{\bbd#1}}
+
+%D Torture test:
+%D
+%D \starttyping
+%D \usetypescript[modern] [texnansi]
+%D \usetypescript[lucida] [texnansi]
+%D \usetypescript[palatino][texnansi]
+%D \usetypescript[times] [texnansi]
+%D \usetypescript[fourier] [ec]
+%D
+%D \startbuffer
+%D \section{\blackboard{T\high{\blackboard{T}}} \blackboard{E}\high{\blackboard{E}} \blackboard{X}\high{\blackboard{X}}}
+%D
+%D {\fontclass: 123 \os123 \cal TEX $\os 123$}
+%D
+%D $\blackboard{T}^{\blackboard{T}} \blackboard{E}^{\blackboard{E}} \blackboard{X}^{\blackboard{X}}$
+%D \blackboard{T}\high{\blackboard{T}} \blackboard{E}\high{\blackboard{E}} \blackboard{X}\high{\blackboard{X}}
+%D \stopbuffer
+%D
+%D {\setupbodyfont[lucida] \getbuffer}
+%D {\setupbodyfont[modern] \getbuffer}
+%D {\setupbodyfont[palatino] \getbuffer}
+%D {\setupbodyfont[times] \getbuffer}
+%D {\setupbodyfont[fourier] \getbuffer}
+%D \stoptyping
+
+%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
+%D \starttyping
+%D \definebodyfontswitch [twelvepoint] [12pt]
+%D \stoptyping
+%D
+%D We don't support language specific synonyms here, mainly
+%D because \PLAIN\ \TEX\ is english anyway.
+
+\def\dodefinebodyfontswitch[#1][#2]%
+ {\def\docommand##1{\setvalue{##1}{\switchtobodyfont[#2]}}%
+ \processcommalist[#1]\docommand}
+
+\def\definebodyfontswitch
+ {\dodoubleargument\dodefinebodyfontswitch}
+
+%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.
+
+\let\fontstep\empty % we can use \fontstep for tracing purposes
+
+\def\setbodyfontstep#1%
+ {\edef\fontstep{\bodyfontcsname\normalizedbodyfontsize\interfaced{#1}\endcsname}%
+ \doswitchpoints[\fontstep]%
+ \doswitchstyle[\fontstyle]}
+
+\unexpanded\def\setsmallbodyfont{\setbodyfontstep\v!small\the\everybodyfont}
+\unexpanded\def\setbigbodyfont {\setbodyfontstep\v!big \the\everybodyfont}
+
+\unexpanded\def\setmainbodyfont
+ {\doswitchpoints[\normalizedbodyfontsize]%
+ \doswitchstyle[\fontstyle]%
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+%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:
+
+\let\mainfontclass\empty
+
+\def\fullrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \chardef\currentxfontsize\zerocount
+ \let\fontclass\globalfontclass
+ \doswitchpoints[\normalizedglobalbodyfontsize]%
+ \doswitchstyle[\globalfontstyle]%
+ \redoconvertfont % just in case a pagebreak occurs
+ \tf
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+\def\partialrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \chardef\currentxfontsize\zerocount
+ \redoconvertfont
+ \tf
+ \saveinterlinespace}
+
+\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 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 \macros
+%D {rasterfont}
+%D
+%D There are (at the moment) two situations in which we want to
+%D have fast access to a particular font. When we are using
+%D \TEX\ to typeset rasters, we use small {\rasterfont.}'s
+%D (a rather small period indeed), the same as \PICTEX\ uses
+%D for drawing purposes.
+
+\definefont [rasterfont] [Serif at 5pt]
+
+%D \macros
+%D {infofont}
+%D
+%D The second situation occurs when we enable the info mode,
+%D and put all kind of status information in the margin. We
+%D don't want huge switches to the main bodyfont and style, so
+%D here too we use a direct method.
+
+% old mechanism
+%
+% \def\infofont{\getvalue{\!!sixpoint\c!tt\c!tf}\the\everybodyfont}
+
+\let\infofont\relax % satisfy dep checker
+
+\definefont [infofont] [Mono at 6pt] % todo \the\everybodyfont
+
+%D \macros
+%D {definealternativestyle}
+%D
+%D In the main modules we are going to implement lots of
+%D parameterized commands and one of these parameters will
+%D concern the font to use. To suit consistent use of fonts we
+%D here implement a mechanism for defining the keywords that
+%D present a 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
+%D second command takes care of headings and alike. Consider
+%D 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
+%D \type{\tfd} does not look that well, so therefore we leave
+%D the second argument of \type{\definealternativestyle} empty.
+%D When we capatalize characters using the pseudo small cap
+%D command \type{\cap}, we want this to take effect in both
+%D text and headings, which is accomplished by assigning both
+%D arguments.
+
+\def\dodefinealternativestyle[#1][#2][#3]%
+ {\def\docommand##1%
+ {\doifundefined{##1}{\setvalue{##1}{\groupedcommand{#2}{}}}%
+ \setvalue{\@letter@ ##1}{#2}%
+ \setvalue{\@noletter@##1}{#3}}%
+ \processcommalist[#1]\docommand}
+
+\def\definealternativestyle
+ {\dotripleempty\dodefinealternativestyle}
+
+\def\definestyle{\definealternativestyle}
+
+%D Maybe too geneneric, but probably ok is the following. (Maybe one
+%D day we will use a dedicated grouped command for styles.)
+
+\appendtoks
+ \let\groupedcommand\thirdofthreearguments
+\to \simplifiedcommands
+
+%D This command also defines the keyword as command. This means
+%D that the example definition of \type{bold} we gave before,
+%D results in a command \type{\bold} 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 \startvoorbeeld
+%D \definealternativestyle[bold][\bf][]\getbuffer
+%D \stopvoorbeeld
+%D
+%D Such definitions are of course unwanted for \type{\cap}
+%D because this would result in an endless recursive call.
+%D Therefore we check on the existance of both the command and
+%D the substitution. The latter is needed because for instance
+%D \type{\type} is an entirely diferent command. That command
+%D handles verbatim, while the style command would just switch
+%D to teletype font. This is just an example of a tricky
+%D naming coincidence.
+
+%D \macros
+%D {doconvertfont,noconvertfont,
+%D dontconvertfont,redoconvertfont}
+%D
+%D After having defined such keywords, we can call for them by
+%D using
+%D
+%D \starttyping
+%D \doconvertfont{keyword}{text}
+%D \stoptyping
+%D
+%D We deliberately pass an argument. This enables us to
+%D assign converters that handle one agrument, like
+%D \type{\cap}.
+%D
+%D By default the first specification is used to set the style,
+%D exept when we say \type{\dontconvertfont}, after which the
+%D second specification is used. We can also directly call for
+%D \type{\noconvertfont}. In nested calls, we can restore the
+%D conversion by saying \type{\redoconvertfont}.
+
+\def\@@dodoconvertfont#1{\csname\@letter@ #1\endcsname}
+\def\@@donoconvertfont#1{\csname\@noletter@#1\endcsname}
+
+\unexpanded\def\dodoconvertfont#1% #2% we need the protection
+ {\doifdefinedelse{\@letter@#1} % in testing
+ {\doifelsenothing{#1}\gobbleoneargument\@@dodoconvertfont}
+ {\doifdefinedelse{#1}\getvalue \firstofoneargument}%
+ {#1}} % {#2}}
+
+\let\doconvertfont\dodoconvertfont
+
+\def\noconvertfont#1% #2%
+ {\doifdefinedelse{\@noletter@#1}
+ {\doifelsenothing{#1}\gobbleoneargument\@@donoconvertfont}\gobbleoneargument
+ {#1}} % {#2}}
+
+%D Extras:
+
+\unexpanded\def\dontconvertfont
+ {\let\doconvertfont\noconvertfont}
+
+\unexpanded\def\redoconvertfont
+ {\let\doconvertfont\dodoconvertfont}
+
+%D These commands are not grouped! Grouping is most probably
+%D done by the calling macro's and would lead to unnecessary
+%D overhead.
+
+%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 furter 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
+%D \starttyping
+%D \def\emphasistypeface {\it}
+%D \def\emphasisboldface {\bi}
+%D \stoptyping
+%D
+%D But we prefer:
+
+\def\emphasistypeface {\sl}
+\def\emphasisboldface {\bs}
+
+%D or even better:
+
+% \def\doemphasistypeface#1#2%
+% {\doifelsevalue{\??ft\fontclass\normalizedbodyfontsize\c!em}\v!slanted#1%
+% {\doifelsevalue{\??ft\fontclass\normalizedbodyfontsize\c!em}\v!italic #2%
+% {\doifelsevalue{\??ft \normalizedbodyfontsize\c!em}\v!slanted#1%
+% {\doifvalue {\??ft \normalizedbodyfontsize\c!em}\v!italic #2}}}}
+
+\def\doemphasistypeface#1#2%
+ {\doifelsevalue{\??ft\fontclass\normalizedbodyfontsize\c!em}\v!slanted
+ {#1}%
+ {\doifelsevalue{\??ft\fontclass\normalizedbodyfontsize\c!em}\v!italic
+ {#2}%
+ {\doifelsevaluenothing{\??ft\fontclass\normalizedbodyfontsize\c!em}
+ {\doifelsevalue{\??ft\normalizedbodyfontsize\c!em}\v!slanted
+ {#1}%
+ {\doifelsevalue{\??ft\normalizedbodyfontsize\c!em}\v!italic
+ {#2}%
+ {\getvalue{\??ft\normalizedbodyfontsize\c!em}}}}
+ {\getvalue{\??ft\fontclass\normalizedbodyfontsize\c!em}}}}}
+
+\def\emphasistypeface{\doemphasistypeface\sl\it}
+\def\emphasisboldface{\doemphasistypeface\bs\bi}
+
+%D To be set with the default body font environment: \type
+%D {em} being \type {slanted} or \type {italic}.
+
+\newconditional\emneeded
+
+\newtoks\everyemphasized
+
+\unexpanded\def\em
+ {\relax
+ \ifdim\slantperpoint>\zeropoint
+ \settrue\emneeded
+ \else
+ \setfalse\emneeded
+ \fi
+ \setemphasisboldface % new
+ \ifx\fontalternative\c!it % \ifnum\fam=\itfam
+ \def\emphasistypeface{\it}\tf
+ \else\ifx\fontalternative\c!sl % \ifnum\fam=\slfam
+ \def\emphasistypeface{\sl}\tf
+ \else\ifx\fontalternative\c!bf % \ifnum\fam=\bffam
+ \emphasisboldface
+ \else\ifx\fontalternative\c!bs % \ifnum\fam=\bsfam
+ \def\emphasisboldface{\bs}\bf
+ \else\ifx\fontalternative\c!bi % \ifnum\fam=\bifam
+ \def\emphasisboldface{\bi}\bf
+ \else
+ \emphasistypeface
+ \fi\fi\fi\fi\fi
+ \the\everyemphasized
+ \ifconditional\emneeded\relax
+ \else
+ \expandafter\aftergroup
+ \fi
+ \emphasiscorrection}
+
+% compare ...
+%
+% \appendtoks \red \to \everyemphasized
+% \setupbodyfontenvironment [default] [em={\italic\color[red]}]
+
+%D The next feature was not present in previous versions. It
+%D takes care of \type {\em \bf ...} sitiations.
+
+\def\setemphasisboldface
+ {\let\normalbf\bf
+ \let\setemphasisboldface\relax
+ \unexpanded\def\bf
+ {%\relax
+ \let\bf\relax % new
+ \ifx\fontalternative\c!it % \ifnum\fam=\itfam
+ \bi
+ \else\ifx\fontalternative\c!sl % \ifnum\fam=\slfam
+ \bs
+ \else
+ \normalbf
+ \fi\fi
+ \let\bf\normalbf}}
+
+%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.
+
+\let\italiccorrection=\/
+
+\def\emphasiscorrection
+ {\ifhmode
+ \expandafter\emphasislook
+ \fi}
+
+\def\emphasislook
+ {\begingroup
+ \beginrobusttest
+ \futurelet\next\emphasistest}
+
+\def\emphasistest
+ {\normalifcat\noexpand\next,%
+ \endrobusttest\expandafter\doemphasiscorrection
+ \normalelse
+ \endrobusttest\expandafter\dododoemphasiscorrection
+ \normalfi}
+
+\def\doemphasiscorrection
+ {\futurelet\next\dodoemphasiscorrection}
+
+\def\dodoemphasiscorrection
+ {\setbox\scratchbox\hbox{\next}%
+ \ifdim\ht\scratchbox=\zeropoint % probably a space
+ \expandafter\dododoemphasiscorrection
+ \else\ifdim\ht\scratchbox<.3ex
+ \expandafter\expandafter\expandafter\endgroup
+ \else
+ \expandafter\expandafter\expandafter\dododoemphasiscorrection
+ \fi\fi}
+
+\def\dododoemphasiscorrection
+ {\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
+%D some punctuation is met. We also show how the mechanism
+%D 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 \startvoorbeeld
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+%D \stopvoorbeeld
+
+%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.
+
+\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
+\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
+\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
+\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
+
+%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
+
+%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:
+
+\def\setfont% geen \dosetfont mogelijk
+ {\def\next{\nextfont\setupinterlinespace}%
+ \afterassignment\next\font\nextfont=}
+
+%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
+%D struts are set.
+
+%D \macros
+%D {showbodyfont}
+%D
+%D One can call for a rather simple overview of a bodyfont and the
+%D relations between its alternative fonts.
+%D
+%D \showsetup{showbodyfont}
+%D
+%D The current bodyfont (here we omitted the argument) looks like:
+%D
+%D \showbodyfont
+%D
+%D The implementation is rather straightforward in using
+%D \type{\halign}.
+
+\fetchruntimecommand \showbodyfont {\f!fontprefix\s!run.mkii}
+
+%D \macros
+%D {showfontstrip, testminimalbaseline, showminimalbaseline}
+%D
+%D The next command can come in handy when combining
+%D different fonts into a collection (typeface) and
+%D determining optimal baseline distances.
+%D
+%D \showfontstrip \blank \showminimalbaseline
+
+\fetchruntimecommand \showfontstrip {\f!fontprefix\s!run.mkii}
+\fetchruntimecommand \testminimalbaseline {\f!fontprefix\s!run.mkii}
+\fetchruntimecommand \showminimalbaseline {\f!fontprefix\s!run.mkii}
+
+%D \macros
+%D {showkerning}
+%D
+%D A goody is:
+%D
+%D \showkerning{Can you guess what kerning is?}
+
+\fetchruntimecommand \showkerning {\f!fontprefix\s!run.mkii}
+
+%D \macros
+%D {showbodyfontenvironment}
+%D
+%D The current bodyfontenvironment is:
+%D
+%D \showbodyfontenvironment
+%D
+%D This overview is generated using:
+%D
+%D \showsetup{showbodyfontenvironment}
+
+\fetchruntimecommand \showbodyfontenvironment {\f!fontprefix\s!run.mkii}
+
+%D \macros
+%D {showfont,showfontstyle,showligatures}
+%D
+%D The following command generates a fontmap:
+%D
+%D \startbuffer
+%D \showfont[SansBold at 12pt]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Below the table the name, encoding, mapping and handling are
+%D shown. Special characters like the \type {\skewchar} and
+%D \type {\hyphenchar} als marked.
+%D
+%D \getbuffer
+
+% to be internationalized
+
+\fetchruntimecommand \showfont {\f!fontprefix\s!run.mkii}
+\fetchruntimecommand \showfontstyle {\f!fontprefix\s!run.mkii}
+\fetchruntimecommand \showligature {\f!fontprefix\s!run.mkii}
+\fetchruntimecommand \showligatures {\f!fontprefix\s!run.mkii}
+\fetchruntimecommand \showcharratio {\f!fontprefix\s!run.mkii}
+
+%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
+%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.
+
+\def\fontstringA
+ {\ifx\fontstyle\c!rm \s!Serif \else
+ \ifx\fontstyle\c!ss \s!Sans \else
+ \ifx\fontstyle\c!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+\def\fontstringB
+ {\ifx\fontstyle\c!rm \s!Regular \else
+ \ifx\fontstyle\c!ss \s!Support \else
+ \ifx\fontstyle\c!tt \s!Type \else
+ \s!Serif \fi\fi\fi}
+
+\def\fontstringC
+ {\ifx\fontalternative\c!bf \s!Bold \else
+ \ifx\fontalternative\c!sl \s!Slanted \else
+ \ifx\fontalternative\c!it \s!Italic \else
+ \ifx\fontalternative\c!bs \s!BoldSlanted \else
+ \ifx\fontalternative\c!bi \s!BoldItalic \fi\fi\fi\fi\fi}
+
+\def\fontstringD % default fontstyle
+ {\expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!rm \s!Serif \else
+ \expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!ss \s!Sans \else
+ \expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+% potential generalization:
+
+% \letvalue{\??ff:t:\c!rm}\s!Serif
+% \letvalue{\??ff:t:\c!ss}\s!Sans
+% \letvalue{\??ff:t:\c!tt}\s!Mono
+%
+% \letvalue{\??ff:s:\c!bf}\s!Bold
+% \letvalue{\??ff:s:\c!sl}\s!Slanted
+% \letvalue{\??ff:s:\c!it}\s!Italic
+% \letvalue{\??ff:s:\c!bs}\s!BoldSlanted
+% \letvalue{\??ff:s:\c!bi}\s!BoldItalic
+%
+% \letvalue{\??ff:a:\c!rm}\s!Regular
+% \letvalue{\??ff:a:\c!ss}\s!Support
+% \letvalue{\??ff:a:\c!tt}\s!Type
+%
+% \def\fontstringA{\executeifdefined{\??ff:t:\fontstyle}\s!Serif}
+% \def\fontstringB{\executeifdefined{\??ff:a:\fontstyle}\s!Serif}
+% \def\fontstringC{\executeifdefined{\??ff:s:\fontstyle}\empty}
+% \def\fontstringD{\executeifdefined{\??ff:t:\csname\??tf\fontclass\s!default\endcsname}\s!Serif}
+
+\def\glyphfontfile#1%
+ {#1%
+ \ifcsname\??ff#1\fontstringA\fontstringC\endcsname
+ \fontstringA\fontstringC
+ \else\ifcsname\??ff#1\fontstringB\fontstringC\endcsname
+ \fontstringB\fontstringC
+ \else\ifcsname\??ff#1\fontstringA\endcsname
+ \fontstringA
+ \else\ifcsname\??ff#1\fontstringB\endcsname
+ \fontstringB
+ \else\ifcsname\??ff#1\fontstringC\endcsname
+ \fontstringC
+ \fi\fi\fi\fi\fi}
+
+%D The next macro can be used to make decisions based on the shape:
+
+\def\doifitalicelse#1#2%
+ {\ifx\fontalternative\c!sl#1\else
+ \ifx\fontalternative\c!it#1\else
+ \ifx\fontalternative\c!bs#1\else
+ \ifx\fontalternative\c!bi#1\else#2\fi\fi\fi\fi}
+
+%D For an example of usage of the following command,
+%D see \type {cont-log.tex}.
+%D
+%D \starttyping
+%D \def\symbolicfont#1%
+%D {\definedfont[\glyphfontfile{#1} sa *]}
+%D \stoptyping
+%D
+%D Since we know what scaling it to be applied, we can
+%D implement a much faster alternative:
+
+\let\thedefinedfont\relax
+
+% \def\symbolicscaledfont#1#2%
+% {\scaledfont\fontbody
+% \scaledfont#1\scaledfont
+% \font\thedefinedfont\truefontname{\glyphfontfile{#2}} at
+% \currentfontbodyscale\scaledfont
+% \thedefinedfont}
+%
+% \unexpanded\def\symbolicfont
+% {\symbolicscaledfont\plusone}
+%
+% even more control (needed for mthsqrt etc)
+
+\def\symbolicsizedfont#1#2#3%
+ {\scaledfont#1%
+ \scaledfont#2\scaledfont
+ \font\thedefinedfont\truefontname{\glyphfontfile{#3}} at
+ \currentfontbodyscale\scaledfont
+ \thedefinedfont}
+
+\def\symbolicscaledfont
+ {\symbolicsizedfont\fontbody}
+
+\unexpanded\def\symbolicfont
+ {\symbolicsizedfont\fontbody\plusone}
+
+\unexpanded\def\getglyph#1#2% slow, faster, much faster
+ %{{\definefont[\s!dummy][\glyphfontfile{#1} sa \currentfontscale]\dummy#2}}
+ %{{\definefont[\s!dummy][\glyphfontfile{#1} sa *]\dummy#2}}
+ %{{\symbolicfont{#1}#2}}
+ {{\symbolicfont{#1}\doifnumberelse{#2}\char\donothing#2}}
+
+\unexpanded\def\getscaledglyph#1#2#3%
+ {{\symbolicscaledfont{#1}{#2}\doifnumberelse{#3}\char\donothing#3}}
+
+\unexpanded\def\getrawglyph#1#2% for simple symbols
+ {{\scaledfont\fontbody
+ \font\thedefinedfont=#1 at \currentfontbodyscale\scaledfont
+ \thedefinedfont\doifnumberelse{#2}\char\donothing#2}}
+
+%D The last implementation of \type {\getglyph} permits
+%D 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
+%D environment.
+
+%D Fonts can only be used when loaded. In \CONTEXT\ we
+%D postpone the loading of fonts, even when we load \PLAIN.
+%D This means that we have to redefine one of the \PLAIN\
+%D macros. Let's tell that to the user first:
+
+\writestatus{loading}{Postponed Plain TeX Font Definitions}
+
+%D \macros
+%D {bordermatrix}
+%D
+%D In \PLAIN\ \TEX\ the width of a parenthesis is stored in
+%D the \DIMENSION\ \type{\mathparentwd}. This value is derived from
+%D the width of \type{\tenrm B}, so let's take care of it now:
+
+\let\normalbordermatrix=\bordermatrix
+
+\def\bordermatrix%
+ {\bgroup
+ \setbox0\hbox{\getvalue{\textface\c!mm\c!ex}B}%
+ \global\mathparentwd\wd0\relax
+ \egroup
+ \normalbordermatrix}
+
+%D Because we want to be as \PLAIN\ compatible as possible, we
+%D make most of \PLAIN's font mechanisme available to the
+%D \CONTEXT\ user.
+
+\def\setplainfonts#1#2%
+ {\setvalue {ten#1}{\getvalue{\!!tenpoint #2}}%
+ \setvalue{seven#1}{\getvalue{\!!sevenpoint#2}}%
+ \setvalue {five#1}{\getvalue{\!!fivepoint #2}}}
+
+\setplainfonts {\c!rm} {\c!rm\c!tf}
+\setplainfonts {\c!bf} {\c!rm\c!bf}
+\setplainfonts {\c!sl} {\c!rm\c!sl}
+\setplainfonts {\c!it} {\c!rm\c!it}
+\setplainfonts {\c!tt} {\c!rm\c!tt}
+\setplainfonts {\c!sy} {\c!mm\c!sy}
+\setplainfonts {\c!ex} {\c!mm\c!ex}
+\setplainfonts {\c!i} {\c!mm\c!mi}
+
+\let\setplainfonts=\undefined
+
+%D \macros
+%D {ss, SS, sz}
+%D
+%D We are going to redefine \type{\ss} but for those wo still
+%D want to have access to the german \SS, we save it's value in
+%D \type{\SS}. Ok, I should have used \type{\sf} instead of
+%D \type{\ss} in the first place.
+
+\ifx\undefined\SS \let\SS=\ss \fi
+\ifx\undefined\sz \let\sz=\ss \fi
+
+%D \macros
+%D {xi}
+%D
+%D We are going to redefine \type{\xi}, but fortunately this
+%D is a math mode character, so we can just say:
+
+\let\normalxi=\xi
+
+%D \macros
+%D {smashaccent}
+%D
+%D When we let \TEX\ put an accent on top of a character, such
+%D composed characters can get more height that height of a
+%D standard \type{\strut}. The next macro takes care of such
+%D unwanted compositions.
+%D
+%D We need to reach over the number that specifies the accent,
+%D and in doing so we use \type{\scratchcounter} as a placeholder
+%D because it accepts 8 bit numbers in octal, decimal or
+%D hexadecimal format. Next we set the height of the accented
+%D character to the natural height of the character.
+
+\unexpanded\def\smashaccent#1%
+ {\dontleavehmode
+ \bgroup
+ \setbox\scratchbox\hbox{#1}%
+ \ifdim\ht\scratchbox>\strutheight\relax\ht\scratchbox\strutheight\fi
+ \ifdim\dp\scratchbox>\strutdepth \relax\dp\scratchbox\strutdepth \fi
+ \box\scratchbox
+ \egroup}
+
+%D For instance we can say:
+%D
+%D \starttyping
+%D \smashaccent{\"Uberhaupt}
+%D \stoptyping
+%D
+%D But normally one will use it as a prefix in definitions.
+%D The difference is in the height:
+%D
+%D \leavevmode\ruledhbox
+%D {\ruledhbox{\smashaccent{\"U}berhaupt}\quad
+%D oder\quad
+%D \ruledhbox{\"Uberhaupt}}
+
+%D \macros
+%D {moveaccent}
+%D
+%D Exact positioning of accents can be realized by saying:
+%D
+%D \starttyping
+%D \moveaccent{-.1ex}{\"u}berhaupt
+%D \stoptyping
+%D
+%D Again, this one will mostly used as a prefix in definitions.
+%D Here the difference is in the position:
+%D
+%D \leavevmode\ruledhbox
+%D {\ruledhbox{\moveaccent{-.1ex}{\"}Uberhaupt}\quad
+%D oder\quad
+%D \ruledhbox{\"Uberhaupt}}
+
+\unexpanded\def\moveaccent#1#2%
+ {\smashaccent
+ {\dimen0\exheight
+ \dimen2\dimen0
+ \advance\dimen2 -#1%
+ \exheight\dimen2
+ #2\relax
+ \exheight\dimen0}}
+
+%D Personally I think that using \TEX\ is complicated by the
+%D way fonts are handled. Apart from the many encodings, we
+%D also deal with different naming schemes. Confronted with
+%D this problem, I decided to change the definitions 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
+
+%D Now we're up to some definitions.
+
+\definebodyfontenvironment
+ [\s!default]
+ [ \s!text=1.0,
+ \s!script=0.7,
+ \s!scriptscript=0.5,
+ \c!a=1.200,
+ \c!b=1.440,
+ \c!c=1.728,
+ \c!d=2.074,
+ *=\currentfontscale, % wildcard
+ \c!x=0.8,
+ \c!xx=0.6,
+ \c!big=1.2,
+ \c!small=0.8,
+ \c!interlinespace=,
+ \c!em=\v!slanted]
+
+\definebodyfontenvironment
+ [20.7pt]
+ [ \s!text=20.7pt,
+ \s!script=\!!fourteenpointfour,
+ \s!scriptscript=\!!twelvepoint,
+ \c!x=17.3pt,
+ \c!xx=\!!fourteenpointfour,
+ \c!big=20.7pt, % !!!!
+ \c!small=17.3pt]
+
+\definebodyfontenvironment
+ [17.3pt]
+ [ \s!text=17.3pt,
+ \s!script=\!!twelvepoint,
+ \s!scriptscript=\!!tenpoint,
+ \c!x=\!!fourteenpointfour,
+ \c!xx=\!!twelvepoint,
+ \c!big=20.7pt,
+ \c!small=\!!fourteenpointfour]
+
+\definebodyfontenvironment
+ [\!!fourteenpointfour]
+ [ \s!text=\!!fourteenpointfour,
+ \s!script=\!!elevenpoint,
+ \s!scriptscript=\!!ninepoint,
+ \c!x=\!!twelvepoint,
+ \c!xx=\!!tenpoint,
+ \c!big=17.3pt,
+ \c!small=\!!twelvepoint]
+
+\definebodyfontenvironment
+ [\!!twelvepoint]
+ [ \s!text=\!!twelvepoint,
+ \s!script=\!!ninepoint,
+ \s!scriptscript=\!!sevenpoint,
+ \c!x=\!!tenpoint,
+ \c!xx=\!!eightpoint,
+ \c!big=\!!fourteenpointfour,
+ \c!small=\!!tenpoint]
+
+\definebodyfontenvironment
+ [\!!elevenpoint]
+ [ \s!text=\!!elevenpoint,
+ \s!script=\!!eightpoint,
+ \s!scriptscript=\!!sixpoint,
+ \c!x=\!!ninepoint,
+ \c!xx=\!!sevenpoint,
+ \c!big=\!!twelvepoint,
+ \c!small=\!!ninepoint]
+
+\definebodyfontenvironment
+ [\!!tenpoint]
+ [ \s!text=\!!tenpoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!eightpoint,
+ \c!xx=\!!sixpoint,
+ \c!big=\!!twelvepoint,
+ \c!small=\!!eightpoint]
+
+\definebodyfontenvironment
+ [\!!ninepoint]
+ [ \s!text=\!!ninepoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!sevenpoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!elevenpoint,
+ \c!small=\!!sevenpoint]
+
+\definebodyfontenvironment
+ [\!!eightpoint]
+ [ \s!text=\!!eightpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!sixpoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!tenpoint,
+ \c!small=\!!sixpoint]
+
+\definebodyfontenvironment
+ [\!!sevenpoint]
+ [ \s!text=\!!sevenpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!sixpoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!ninepoint,
+ \c!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!sixpoint]
+ [ \s!text=\!!sixpoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!fivepoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!eightpoint,
+ \c!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fivepoint]
+ [ \s!text=\!!fivepoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!fivepoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!sevenpoint,
+ \c!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fourpoint]
+ [ \s!text=\!!fourpoint,
+ \s!script=\!!fourpoint,
+ \s!scriptscript=\!!fourpoint,
+ \c!x=\!!fourpoint,
+ \c!xx=\!!fourpoint,
+ \c!big=\!!sixpoint,
+ \c!small=\!!fourpoint]
+
+\definebodyfontswitch [fourteenpointfour] [\!!fourteenpointfour]
+\definebodyfontswitch [twelvepoint] [\!!twelvepoint]
+\definebodyfontswitch [elevenpoint] [\!!elevenpoint]
+\definebodyfontswitch [tenpoint] [\!!tenpoint]
+\definebodyfontswitch [ninepoint] [\!!ninepoint]
+\definebodyfontswitch [eightpoint] [\!!eightpoint]
+\definebodyfontswitch [sevenpoint] [\!!sevenpoint]
+\definebodyfontswitch [sixpoint] [\!!sixpoint]
+\definebodyfontswitch [fivepoint] [\!!fivepoint]
+\definebodyfontswitch [fourpoint] [\!!fourpoint]
+
+\definebodyfontswitch [xii] [\!!twelvepoint]
+\definebodyfontswitch [xi] [\!!elevenpoint]
+\definebodyfontswitch [x] [\!!tenpoint]
+\definebodyfontswitch [ix] [\!!ninepoint]
+\definebodyfontswitch [viii] [\!!eightpoint]
+\definebodyfontswitch [vii] [\!!sevenpoint]
+\definebodyfontswitch [vi] [\!!sixpoint]
+
+%D So far.
+
+\definefontstyle [\c!mm] [\c!mm]
+\definefontstyle [\c!rm,\v!roman,\v!serif,\v!regular] [\c!rm]
+\definefontstyle [\c!ss,\v!sansserif,\v!sans,\v!support] [\c!ss]
+\definefontstyle [\c!tt,\v!teletype,\v!type,\v!mono] [\c!tt]
+\definefontstyle [\c!hw,\v!handwritten] [\c!hw]
+\definefontstyle [\c!cg,\v!calligraphic] [\c!cg]
+
+\definefontsize[\c!a] \definefontsize[\c!b]
+\definefontsize[\c!c] \definefontsize[\c!d]
+
+\definealternativestyle [\v!mediaeval] [\os] []
+\definealternativestyle [\v!normal] [\tf] []
+\definealternativestyle [\v!bold] [\bf] []
+\definealternativestyle [\v!type] [\tt] []
+\definealternativestyle [\v!mono] [\tt] []
+\definealternativestyle [\v!slanted] [\sl] []
+\definealternativestyle [\v!italic] [\it] []
+\definealternativestyle [\v!boldslanted,\v!slantedbold] [\bs] []
+\definealternativestyle [\v!bolditalic,\v!italicbold] [\bi] []
+\definealternativestyle [\v!small,\v!smallnormal] [\tfx] []
+\definealternativestyle [\v!smallbold] [\bfx] []
+\definealternativestyle [\v!smalltype] [\ttx] []
+\definealternativestyle [\v!smallslanted] [\slx] []
+\definealternativestyle [\v!smallboldslanted,\v!smallslantedbold] [\bsx] []
+\definealternativestyle [\v!smallbolditalic,\v!smallitalicbold] [\bix] []
+
+\definealternativestyle [\v!sans,\v!sansserif] [\ss] []
+\definealternativestyle [\v!sansbold] [\ss\bf] []
+
+%D Slow but handy:
+
+\definealternativestyle [\v!smallbodyfont] [\setsmallbodyfont] []
+\definealternativestyle [\v!bigbodyfont] [\setbigbodyfont] []
+
+%D We treat {\sc Small Caps} and \cap {Pseudo Caps} a bit
+%D different. We also provide an \WORD {uppercase} style.
+
+\definealternativestyle [\v!cap,\v!capital] [\smallcapped] [\smallcapped]
+\definealternativestyle [\v!smallcaps] [\sc] [\sc]
+\definealternativestyle [\v!WORD] [\WORD] [\WORD]
+
+%D \macros
+%D {...math}
+%D
+%D New or old?
+
+% tzt proper \define...
+%
+% watch out: \synchronizesymb resets the family so we need a second
+% \mf (or maybe \mr): messy and to be sorted out
+
+\def\tfmath{\tf\mf\synchronizesymb\mf}
+\def\bfmath{\bf\mf\synchronizesymb\mf}
+\def\slmath{\sl\mf\synchronizesymb\mf}
+\def\itmath{\it\mf\synchronizesymb\mf}
+\def\bsmath{\bs\mf\synchronizesymb\mf}
+\def\bimath{\bi\mf\synchronizesymb\mf}
+\def\scmath{\sc\mf\synchronizesymb\mf}
+\def\nnmath{\nn\mf\synchronizesymb\mf}
+
+\def\textmath {\synchronizesymb}
+
+%D \macros
+%D {fontstylesuffix}
+%D
+%D The next macro is used to map non latin fontnames on
+%D fonts. See \type {font-uni} for an example of its use.
+
+%\def\fontstylesuffix%
+% {\ifnum\fam=\tffam \s!Regular \else
+% \ifnum\fam=\bffam \s!Bold \else
+% \ifnum\fam=\slfam \s!Slanted \else
+% \ifnum\fam=\itfam \s!Italic \else
+% \ifnum\fam=\bsfam \s!BoldSlanted \else
+% \ifnum\fam=\bifam \s!BoldItalic \else
+% \s!Regular \fi\fi\fi\fi\fi\fi}%
+
+\def\fontstylesuffix% why the \s!Regular ? see \getglyph
+ {\ifx\fontalternative\c!tf \s!Regular \else
+ \ifx\fontalternative\c!bf \s!Bold \else
+ \ifx\fontalternative\c!sl \s!Slanted \else
+ \ifx\fontalternative\c!it \s!Italic \else
+ \ifx\fontalternative\c!bs \s!BoldSlanted \else
+ \ifx\fontalternative\c!bi \s!BoldItalic \else
+ \ifx\fontalternative\c!sc \s!Caps \else
+ \s!Regular \fi\fi\fi\fi\fi\fi\fi}%
+
+%D We still have to take care of \type{\xi}, so:
+
+\def\xi{\ifmmode\normalxi\else\elevenpoint\fi}
+
+%D \macros
+%D {definefontvariant,fontvariant,variant}
+%D
+%D A slightly adapted version of Adam Lindsays variant patches:
+%D
+%D \starttyping
+%D \usetypescriptfile[type-psc] \loadmapfile[texnansi-public-fpl]
+%D \usetypescript[palatino][texnansi] \setupbodyfont[palatino]
+%D
+%D \definefontvariant [Serif][osf] [OsF]
+%D
+%D \startlines
+%D {\sc abcdefgHIJKlmnop}
+%D 123{\Var[osf]456}789
+%D {\Var[osf] 123{\Var[reset]456}789}
+%D {\it 123{\Var[osf]456}789
+%D {\Var[osf]123{\Var[reset]456}789}}
+%D {\tfb\bf 123{\Var[osf]456}789
+%D {\Var[osf] 123{\Var[reset]456}789}}
+%D {\sc 123{\Var[osf]456}789
+%D {\Var[osf] 123{\Var[reset]456}789}}
+%D \stoplines
+%D \stoptyping
+
+\def\definefontvariant
+ {\dotripleargument\dodefinefontvariant}
+
+\def\dodefinefontvariant[#1][#2][#3]%
+ {\setvalue{\??fv#1#2}{#3}}
+
+\def\fontvariant#1#2{\executeifdefined{\??fv#1#2}\empty}
+
+\def\dosetscaledfont
+ {\checkrelativefontsize\fontstyle
+ \scaledfont\currentfontscale\bodyfontsize
+ \scaledfont\relativefontsize\scaledfont}
+
+\unexpanded\def\variant[#1]% slow
+ {\dosetscaledfont
+ \expanded{\definedfont
+ [\truefontname{\fontstringA\fontstylesuffix\fontvariant\fontstringA{#1}}
+ at \scaledfont]}%
+ \ignoreimplicitspaces}
+
+\ifx\Var\undefined \let\Var\variant \fi
+
+%D By default we load the Computer Modern Roman fonts (but
+%D not yet at this moment) and activate the 12pt roman
+%D bodyfont. Sans serif and teletype are also available and
+%D can be called for by \type{\ss} and \type{\tt}.
+
+% \setupbodyfont [unk, rm]
+
+%D Also needed is:
+
+\definefont[tinyfont][Mono at 1ex]
+
+%D \macros
+%D {doiffontpresentelse}
+%D
+%D Some unused left||overs:
+%D
+%D \starttyping
+%D \def\doiffontpresentelse#1#2#3%
+%D {\bgroup
+%D \batchmode\font\dummy=\truefontname{#1}\errorstopmode
+%D \edef\lastfontname{\fontname\dummy}%
+%D \ifx\lastfontname\nullfontname\egroup#3\else\egroup#2\fi}
+%D
+%D \def\abortiffontnotfound#1%
+%D {\doiffontpresentelse{#1}{}{\showmessage\m!fonts{10}{\truefontname{#1}}\endinput}}
+%D \stoptyping
+%D
+%D We now provide (slow, but sometimes handy):
+%D
+%D \starttyping
+%D \doiffontpresentelse{texnansi-lmr10}{YES}{NO}
+%D \doiffontpresentelse{adam-lindsay-modern-serif}{YES}{NO}
+%D \stoptyping
+
+\def\doiffontpresentelse#1%
+ {\bgroup
+ \scratchcounter\interactionmode
+ \batchmode
+ \font\dummy=\truefontname{#1}\relax
+ \interactionmode\scratchcounter
+ \edef\lastfontname{\fontname\dummy}%
+ \ifx\lastfontname\nullfontname
+ \egroup\expandafter\secondoftwoarguments
+ \else
+ \egroup\expandafter\firstoftwoarguments
+ \fi}
+
+%D New commands (not yet interfaced):
+
+\def\style[#1]% for inline usage, like \color
+ {\groupedcommand{\ifcsname#1\endcsname\csname#1\endcsname\else\definedfont[#1]\fi}{}}
+
+\def\startstyle[#1]%
+ {\begingroup
+ \ifcsname#1\endcsname\csname#1\endcsname\else\definedfont[#1]\fi}
+
+\def\stopstyle
+ {\endgroup}
+
+%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}}
+
+\definesystemvariable{sx}
+
+\def\definestylecollection
+ {\dosingleargument\dodefinestylecollection}
+
+\def\dodefinestylecollection[#1]%
+ {\iffirstargument
+ \unexpanded\setvalue{#1}{\styleinstance[#1]}%
+ \def\docommand##1%
+ {\def\dodocommand####1{\letbeundefined{\??sx##1:####1:\commalistelement}}%
+ \processcommacommand[\fontalternativelist,\s!default]\dodocommand}%
+ \processcommacommand[\fontstylelist,\s!default]\docommand
+ \fi}
+
+\def\definestyleinstance
+ {\doquadrupleargument\dodefinestyleinstance}
+
+\def\dodefinestyleinstance[#1][#2][#3][#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever]
+ {\iffirstargument
+ \doifundefined{#1}{\definestylecollection[#1]}%
+ \fi
+ \iffourthargument
+ \setvalue{\??sx#1:#2:#3}{#4}%
+ \else\ifthirdargument
+ \setvalue{\??sx#1::#2}{#3}%
+ \else\ifsecondargument
+ \letvalue{\??sx#1::#2}\empty
+ \fi\fi\fi}
+
+\unexpanded\def\styleinstance[#1]% will be faster
+ {%\begingroup\expanded{\infofont[#1:\fontstyle:\fontalternative]}\endgroup
+ \executeifdefined{\??sx#1:\fontstyle:\fontalternative}%
+ {\executeifdefined{\??sx#1:\fontstyle:\s!default}%
+ {\executeifdefined{\??sx#1::\fontalternative}
+ {\getvalue {\??sx#1::\s!default}}}}}
+
+% \unexpanded\def\styleinstance[#1]%
+% {\csname\??sx#1%
+% \ifcsname:\fontstyle:\fontalternative\endcsname
+% :\fontstyle:\fontalternative
+% \else\ifcsname:\fontstyle:\s!default\endcsname
+% :\fontstyle:\s!default
+% \else\ifcsname::\fontalternative\endcsname
+% ::\fontalternative
+% \else\ifcsname::\s!default\endcsname
+% ::\s!default
+% \else
+% % nothing, \relax
+% \fi\fi\fi\fi
+% \endcsname}
+
+%D \Compatibility with \MKIV:
+
+\def\somefontsize{\scaledfont}
+
+\protect \endinput
diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv
new file mode 100644
index 000000000..c7d515cca
--- /dev/null
+++ b/tex/context/base/font-ini.mkiv
@@ -0,0 +1,3896 @@
+%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 / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% runtime commands will move to modules
+
+% simplification ... we no longer deal with specific mmtfa specifications
+
+% todo: always fontclass, then less testing
+
+% \definefontfeature[smallcaps][smcp=yes,script=latn]
+% \definefontfeature[smallcaps][SmallCapitals=yes,script=latn]
+% \definefontfeature[smallcaps][Small Capitals=yes,script=latn]
+% \definefontfeature[smallcaps][small capitals=yes,script=latn]
+% \definefontfeature[smallcaps][smallcapitals=yes,script=latn]
+%
+% \definedfont[cambria*smallcaps] test
+
+% \starttext
+% \definefontfeature[basekerned][default][mode=base]
+% \definefontfeature[nodekerned][default][mode=node]
+% \definefontfeature[nonekerned][default][mode=base,kern=no]
+% \setupcolors[state=start]
+% \startoverlay
+% {\vbox{\red \definedfont[Serif*nonekerned at 12pt]\input tufte }}
+% {\vbox{\blue \definedfont[Serif*basekerned at 12pt]\input tufte }}
+% {\vbox{\green\definedfont[Serif*nodekerned at 12pt]\input tufte }}
+% \stopoverlay
+% \stoptext
+
+% \enabletrackers[otf.kerns]
+%
+% \definefontfeature[withkern][default][mode=node]
+% \definefontfeature[nokern] [default][mode=node,kern=no]
+% \definefontfeature[single] [default][mode=node,cpsp=yes]
+% \definefontfeature[simple] [default][mode=node,cpsp=yes,kern=no]
+%
+% {\definedfont[Serif*default] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+% {\definedfont[Serif*nokern] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+% {\definedfont[Serif*single] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+% {\definedfont[Serif*simple] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
+
+% figure out why \fontbody is not expanded
+
+\writestatus{loading}{ConTeXt Font Macros / Initialization}
+
+\registerctxluafile{font-ini}{1.001}
+\registerctxluafile{node-fnt}{1.001} % here
+\registerctxluafile{font-enc}{1.001}
+\registerctxluafile{font-map}{1.001}
+\registerctxluafile{font-syn}{1.001}
+\registerctxluafile{font-log}{1.001}
+\registerctxluafile{font-tfm}{1.001}
+\registerctxluafile{font-enh}{1.001}
+\registerctxluafile{font-afm}{1.001}
+\registerctxluafile{font-cid}{1.001} % cid maps
+\registerctxluafile{font-ott}{1.001} % otf tables
+\registerctxluafile{font-otf}{1.001} % otf main
+\registerctxluafile{font-otd}{1.001} % otf dynamics
+\registerctxluafile{font-oti}{1.001} % otf initialization
+\registerctxluafile{font-otb}{1.001} % otf main base
+\registerctxluafile{font-otn}{1.001} % otf main node
+\registerctxluafile{font-ota}{1.001} % otf analyzers
+\registerctxluafile{font-otp}{1.001} % otf pack
+\registerctxluafile{font-otc}{1.001} % otf context
+\registerctxluafile{font-vf} {1.001}
+\registerctxluafile{font-def}{1.001}
+\registerctxluafile{font-ctx}{1.001}
+\registerctxluafile{font-xtx}{1.001}
+\registerctxluafile{font-fbk}{1.001}
+\registerctxluafile{font-gds}{1.001}
+\registerctxluafile{font-ext}{1.001}
+\registerctxluafile{font-pat}{1.001}
+\registerctxluafile{font-chk}{1.001}
+\registerctxluafile{font-agl}{1.001}
+
+\unprotect
+
+% \def\fontrange#1%
+% {\dofontrange{#1 =\bodyfontsize}}
+%
+% \def\dofontrange#1%
+% {\dodofontrange#1 \relax}% \fontstringA
+%
+% \def\dodofontrange#1 #2 %
+% {\ifdim\bodyfontsize#2%
+% #1\expandafter\gobbleuntilrelax
+% \else
+% \expandafter\dodofontrange
+% \fi}
+%
+% \definefont
+% [crap]
+% [\fontrange
+% {Regular <10pt
+% RegularBold <12pt
+% RegularSlanted <15pt
+% Regular} sa 1]
+%
+% may be better:
+%
+% \definefontrange
+% [crap]
+% [Regular <10pt
+% RegularBold <12pt
+% RegularSlanted <15pt]
+% [Regular sa 1]
+%
+%
+% \dostepwiserecurse{2}{15}{1}
+% {{\switchtobodyfont[\recurselevel pt]\crap test}\endgraf}
+
+% adapted, else wrong interlinespace
+
+\def\setfontparameters
+ {\synchronizefontsfalse
+ \the\everybodyfont
+ \synchronizefontstrue}
+
+% handy
+
+\newcounter\pushedfont
+
+\def\savefont
+ {\edef\savedfont{\the\font}%
+ \pushmacro\savedfont}
+
+\def\restorefont
+ {\popmacro\savedfont
+ \savedfont}
+
+\def\pushcurrentfont
+ {\edef\popcurrentfont
+ {\noexpand\def\noexpand\fontbody{\fontbody}%
+ \noexpand\def\noexpand\fontstyle{\fontstyle}%
+ \noexpand\dosetcurrentfontalternative{\fontalternative}%
+ \noexpand\dosetcurrentfontsize{\fontsize}%
+ \noexpand\synchronizefont}}
+
+% \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 {definedfont,startfont,doiffontcharelse}
+%D
+%D A couple of relatively new macros:
+
+% \newtoks \everydefinedfont % not ot be confused with \everydefinefont
+
+\def\dodefinedfont[#1]%
+ {\iffirstargument\definefont[thedefinedfont][#1]\fi % we can speed this one up
+ \csname thedefinedfont\endcsname
+ \the\everydefinedfont}
+
+\unexpanded\def\definedfont
+ {\dosingleempty\dodefinedfont}
+
+\unexpanded\def\startfont
+ {\bgroup\definedfont}
+
+\unexpanded\def\stopfont
+ {\egroup}
+
+\def\doiffontcharelse#1#2%
+ {\bgroup
+ \definedfont[#1]%
+ \iffontchar\font#2\relax
+ \egroup\expandafter\firstoftwoarguments
+ \else
+ \egroup\expandafter\secondoftwoarguments
+ \fi}
+
+%D For more detailed (and historic information) we refer to the file
+%D \type {font-ini.mkii}. Here we have a much simplified lower level
+%D implementation due to a different approach to math. Also the chapter
+%D on fonts in the reference manual explains a lot.
+
+%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
+%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
+%D using Lucida Bright we 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})
+%D we can define a number 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}.
+%D Users are not confronted with sizes, but use the style or
+%D style+alternative to activate them.
+%D
+%D During the definition of a bodyfont one can also declare the
+%D available larger 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
+%D larger alternatives on the 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
+%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 \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%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
+%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
+%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
+%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
+%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
+%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
+%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
+%D
+%D Remark: math support has changed a bit.
+
+%D \macros
+%D {uchar}
+%D
+%D This macro prepares \CONTEXT\ for \UNICODE\ support. By
+%D defining it here, we have at least an safeguard for utility
+%D file reading.
+
+\ifdefined\uchar\else \unexpanded\def\uchar#1#2{[#1,#2]} \fi
+
+%D We define some (very private) constants to improve speed,
+%D memory usage and consistency.
+
+\def\@size@ {@f@si@} % bodyfont size prefix (12pt etc)
+\def\@style@ {@f@st@} % full style prefix (roman etc)
+\def\@shortstyle@ {@f@sh@} % short style prefix (rm etc)
+\def\@letter@ {@f@le@} % first alternative typeface
+\def\@noletter@ {@f@no@} % second alternative typeface
+\def\@fontclass@ {@f@cl@} % fontclass
+
+%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.
+
+\let\fontclass \empty
+\let\defaultfontclass\empty
+
+%D \macros
+%D {textonly}
+%D
+%D Traditionally math has a big impact on font definitions, mainly
+%D because we need to define alphabet variants using families and
+%D fonts. This means that one can easily get 10 fonts loaded per
+%D math size. In \MKIV\ we use a different approach: one family
+%D which has either a virtual font made of traditional fonts, or
+%D an \OPENTYPE\ font that has it all.
+%D
+%D We currently use only one math family but in the future we
+%D might consider using a second one for bold math. For the
+%D moment we keep the \MKII\ method of using a token register
+%D for definitions but we already dropped the text and symbols
+%D ones since they now live in the same family.
+
+\newtoks \mathstrategies
+
+\newif\ifsynchronizemathfonts \synchronizemathfontstrue
+
+\def\synchronizemath % math stuff in mmode
+ {\ifsynchronizemathfonts\the\mathstrategies\fi}
+
+\def\textonly{\synchronizemathfontsfalse} % document this
+
+%D The main math font definer. We have removed some optimized
+%D code simply because we now always have a fontclass. We could
+%D check for fontclass being default or empty and save a few
+%D tests but it does not help us when no math is defined.
+
+\chardef\mrfam\zerocount % math regular
+\chardef\mbfam\plusone % math bold
+
+\unexpanded\def\mr{\ifmmode\fam\zerocount\else\setcurrentfontalternative\c!mr\fi} % \fam\csname\c!mr fam\endcsname
+\unexpanded\def\mb{\ifmmode\fam\plusone \else\setcurrentfontalternative\c!mb\fi} % \fam\csname\c!mb fam\endcsname
+
+\def\mathtextsuffix {-text}
+\def\mathscriptsuffix {-script}
+\def\mathscriptscriptsuffix{-scriptscript}
+
+% \let\mathsizesuffix\empty
+
+\let\currentmathsize\empty
+
+\def\mathsizesuffix{\ifcase0\currentmathsize\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi}
+
+\def\dodosetmathfamily#1#2%
+ {\ifcsname\fontclass \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \autofontsizefalse
+ \csname\fontclass \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \else
+ \ifcsname\fontclass \fontbody\c!mm\fontfamily \currentmathsize\endcsname \autofontsizetrue
+ \csname\fontclass \fontbody\c!mm\fontfamily \currentmathsize\endcsname \else
+ \dodosetmathfamilyx#1#2%
+ \fi\fi
+ #1#2\font}
+
+\def\dodosetmathfamilyx#1#2%
+ {\ifcsname\defaultfontclass\fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \autofontsizefalse
+ \csname\defaultfontclass\fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \else
+ \ifcsname\defaultfontclass\fontbody\c!mm\fontfamily \currentmathsize\endcsname \autofontsizetrue
+ \csname\defaultfontclass\fontbody\c!mm\fontfamily \currentmathsize\endcsname \else
+ \dodosetmathfamilyxx#1#2%
+ \fi\fi}
+
+\def\dodosetmathfamilyxx#1#2%
+ {\ifcsname \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \autofontsizefalse
+ \csname \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \else
+ \ifcsname \fontbody\c!mm\fontfamily \currentmathsize\endcsname \autofontsizetrue
+ \csname \fontbody\c!mm\fontfamily \currentmathsize\endcsname \else
+ \nullfont \autofontsizetrue
+ \fi\fi}
+
+\def\dosetmathfamily#1#2%
+ {\let\savedfontbody\fontbody % op hoger plan
+ \let\fontfamily#2%
+ \let\currentmathsize\!!plusthree\let\fontbody\scriptscriptface\dodosetmathfamily\scriptscriptfont#1%
+ \let\currentmathsize\!!plustwo \let\fontbody\scriptface \dodosetmathfamily\scriptfont #1%
+ \let\currentmathsize\!!plusone \let\fontbody\textface \dodosetmathfamily\textfont #1%
+ \let\currentmathsize\empty
+ \let\fontbody\savedfontbody
+ \autofontsizefalse}
+
+\appendtoks
+ \dosetmathfamily\mrfam\c!mr
+\to \mathstrategies
+
+% not official !
+
+\chardef\boldmathmode\zerocount % might change ... maybe \mathfontsupport 1 (normal) 2 (bold too)
+
+\def\enableboldmath {\chardef\boldmathmode\plusone } % todo: \setupbodyfont[boldmath,...]
+\def\disableboldmath{\chardef\boldmathmode\zerocount}
+
+\appendtoks
+ \ifcase\boldmathmode\or\dosetmathfamily\mbfam\c!mb\fi
+\to \mathstrategies
+
+% \chardef\msfam\plustwo % math symbol
+%
+% \def\c!ms{ms}
+%
+% \unexpanded\def\ms{\ifmmode\fam\plustwo\else\setcurrentfontalternative\c!ms\fi}
+%
+% \chardef\symbolmathmode\zerocount
+%
+% \def\enablesymbolmath {\chardef\symbolmathmode\plusone }
+% \def\disablesymbolmath{\chardef\symbolmathmode\zerocount}
+%
+% \appendtoks
+% \ifcase\symbolmathmode\or\dosetmathfamily\msfam\c!ms\fi
+% \to \mathstrategies
+
+%D All used styles, like rm, ss and tt, are saved in a comma
+%D separated list. Appart from practical limitations one can
+%D define as many styles as needed.
+
+\def\fontrelativesizelist{\s!text,\s!script,\s!scriptscript,\c!x,\c!xx,\c!big,\c!small}
+
+%D There are several ways to specify a font. Three of them are
+%D pure \TeX\ ones, the 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
+%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
+%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.
+
+% \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
+
+\let\defaultrelativefontsize \plusone
+\let\localrelativefontsize \plusone
+\def\localabsolutefontsize {\fontbody}
+
+\let\relativefontsize \defaultrelativefontsize
+
+% \def\saverelativefontsize#1#2% #1=rm|ss|.. #2=waarde
+% {\setxvalue{\fontclass#1\s!rscale}{#2}}
+
+\def\checkrelativefontid
+ {\ifcsname\??tf\fontclass\s!rname\endcsname
+ \@EA\let\@EA\relativefontid\csname\??tf\fontclass\s!rname\endcsname
+ \else
+ \@EA\xdef\csname\??tf\fontclass\s!rname\endcsname{\the\lastfontid}%
+ \let\relativefontid\empty
+ \fi}
+
+\def\checkrelativefontsize#1%
+ {\edef\relativefontsize
+ {\ifcsname\fontclass#1\s!rscale\endcsname
+ \csname\fontclass#1\s!rscale\endcsname
+ \else\ifcsname\defaultfontclass#1\s!rscale\endcsname
+ \csname\defaultfontclass#1\s!rscale\endcsname
+ \else
+ \defaultrelativefontsize
+ \fi\fi}%
+ \ifx\relativefontsize\v!auto
+ \let\relativefontsize\plusone
+ \checkrelativefontid
+ \else
+ \let\relativefontid\minusone
+ \fi}
+
+%D Scaling macros:
+%D
+%D This system is somewhat complicated by two (possible conflicting)
+%D 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 \stopitemize
+
+%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.
+
+% 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
+%
+% {\definedfont[cmbx10 at 10pt]x\definedfont[cmbx8 at 10pt]x}
+
+\def\safontscale{\number\dimexpr\localabsolutefontsize\relax}
+\def\mofontscale{\number\dimexpr\setmappedfontsize\localabsolutefontsize\relax}
+
+\let\somefontname\s!unknown
+\let\somefontspec\s!unknown
+\let\somefontsize\zerocount
+
+\newcount\scaledfontmode
+\newdimen\scaledfontsize
+\newtoks \everydefinefont
+\newcount\lastfontid
+
+\def\currentfontbodysize
+ {\ifcsname\??ft\s!default\somefontsize\endcsname
+ \csname\??ft\s!default\somefontsize\endcsname
+ \else
+ \somefontsize
+ \fi}
+
+\let\relativefontid\empty
+
+\def\lowleveldefinefont#1#2% #2 = cs
+ {%
+ \ctxlua{fonts.define.command_1("\luaescapestring{#1}")}% the escapestring catches at \somedimen
+ % sets \scaledfontmode and \somefontname and \somefontsize
+ \ifcase\scaledfontmode\relax
+ % none, avoid the designsize if possible
+ \scaledfontsize-1000\scaledpoint
+ \or
+ % at
+ \scaledfontsize\somefontsize
+ \or
+ % sa
+ \scaledfontsize\localabsolutefontsize\relax
+ \scaledfontsize\currentfontbodysize\scaledfontsize
+ \or
+ % mo
+ \scaledfontsize\setmappedfontsize\localabsolutefontsize
+ \scaledfontsize\currentfontbodysize\scaledfontsize
+ \or
+ % scaled, don't use this one as it's unpredictable
+ \scaledfontsize-\somefontsize\scaledpoint
+ \fi
+ \scaledfontsize\localrelativefontsize\scaledfontsize
+ \ifautofontsize
+ \scaledfontsize\currentfontbodyscale\scaledfontsize
+ \fi
+ \edef\somefontspec{at \number\scaledfontsize sp}%
+ \edef\somefontfile{\truefontname\somefontname}%
+ \ifx\somefontfile\s!unknown
+ \edef\somefontfile{\defaultfontfile}%
+ \fi
+ \updatefontparameters
+ \updatefontclassparameters
+ \ctxlua{fonts.define.command_2(
+ \ifx\fontclass\empty false\else true\fi,
+ "#2", % cs, trailing % is gone
+ "\somefontfile",
+ \number\scaledfontsize,
+ "\@@fontclassfeatures",
+ "\@@fontfeatures",
+ "\@@fontclassfallbacks",
+ "\@@fontfallbacks",
+ 0\currentmathsize,
+ \number\dimexpr\textface\relax,
+ "\relativefontid" % experiment
+ )}%
+ \edef\somefontspec{at \somefontsize}% we need the resolved designsize (for fallbacks)
+ \expandafter\let\expandafter\lastrawfontcall\csname#2\endcsname
+ \the\everydefinefont}
+
+\def\updatefontclassparameters
+ {\edef\@@fontclassfeatures {\ifcsname\fontclass\fontstyle\s!features \endcsname\csname\fontclass\fontstyle\s!features \endcsname\fi}%
+ \edef\@@fontclassfallbacks{\ifcsname\fontclass\fontstyle\s!fallbacks\endcsname\csname\fontclass\fontstyle\s!fallbacks\endcsname\fi}}
+
+% resolve
+
+\def\@@thefeaturesyes#1%
+ {\ifcsname\??ff\fontclass#1\s!features \endcsname\@EA\let\@EA\@@fontfeatures \csname\??ff\fontclass#1\s!features \endcsname\else
+ \ifcsname\??ff #1\s!features \endcsname\@EA\let\@EA\@@fontfeatures \csname\??ff #1\s!features \endcsname\else
+ \ifcsname\??ff\fontclass #1\endcsname\@EA \@@thefeaturesyes \csname\??ff\fontclass #1\endcsname\else
+ \ifcsname\??ff #1\endcsname\@EA \@@thefeaturesyes \csname\??ff #1\endcsname\else
+ \let \@@fontfeatures \empty \fi\fi\fi\fi}
+
+\def\@@thefallbacksyes#1%
+ {\ifcsname\??ff\fontclass#1\s!fallbacks\endcsname\@EA\let\@EA\@@fontfallbacks \csname\??ff\fontclass#1\s!fallbacks\endcsname\else
+ \ifcsname\??ff #1\s!fallbacks\endcsname\@EA\let\@EA\@@fontfallbacks \csname\??ff #1\s!fallbacks\endcsname\else
+ \ifcsname\??ff\fontclass #1\endcsname\@EA \@@thefallbacksyes\csname\??ff\fontclass #1\endcsname\else
+ \ifcsname\??ff #1\endcsname\@EA \@@thefallbacksyes\csname\??ff #1\endcsname\else
+ \let \@@fontfallbacks \empty \fi\fi\fi\fi}
+
+\def\@@thefeaturesnop#1%
+ {\ifcsname\??ff#1\s!features \endcsname\@EA\let\@EA\@@fontfeatures \csname\??ff#1\s!features \endcsname\else
+ \ifcsname\??ff #1\endcsname\@EA \@@thefeaturesnop \csname\??ff #1\endcsname\else
+ \let \@@fontfeatures \empty \fi\fi}
+
+\def\@@thefallbacksnop#1%
+ {\ifcsname\??ff#1\s!fallbacks\endcsname\@EA\let\@EA\@@fontfallbacks \csname\??ff#1\s!fallbacks\endcsname\else
+ \ifcsname\??ff #1\endcsname\@EA \@@thefallbacksnop\csname\??ff #1\endcsname\else
+ \let \@@fontfallbacks \empty \fi\fi}
+
+\def\updatefontparametersyes
+ {\@@thefeaturesyes \somefontname
+ \@@thefallbacksyes\somefontname}
+
+\def\updatefontparametersnop
+ {\@@thefeaturesnop \somefontname
+ \@@thefallbacksnop\somefontname}
+
+\def\updatefontparameters
+ {\ifx\fontclass\empty\updatefontparametersnop\else\updatefontparametersyes\fi}
+
+\let\@@fontclassfeatures \empty
+\let\@@fontclassfallbacks\empty
+
+\let\@@fontfallbacks\empty
+\let\@@fontfeatures \empty
+\let\@@hyphenchar \empty % todo, will go to encoding
+
+%D This brings down maps processing from 466 to 309 seconds
+%D ($-33$\%) and mfonts from 42 to 34 seconds ($-15$\%).
+
+\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue
+
+%D When fontclasses are used, we define the font global,
+%D since namespaces are used. Otherwise we parse the specs
+%D each time.
+
+\let\fontfile\s!unknown
+
+% \definefontfeature[slanted] [default][slant=.25]
+% \definefontfeature[stretched][default][stretch=2]
+%
+% \start \definedfont[SerifBold*slanted at 20pt] \ruledhbox{Test!} \stop
+% \start \definedfont[SerifBold*stretched at 20pt] \ruledhbox{Test!} \stop
+
+% \definefontfeature[default] [liga=yes,texligatures=yes,texquotes=yes]
+% \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn]
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular][features=default]
+% \definefontsynonym[SerifCaps][palatinonova-regular][features=default-caps] % also sets Serif
+% \stoptypescript
+%
+% \starttypescript [serif] [palatino-nova-regular] [name]
+% \definefontsynonym[Serif] [palatinonova-regular*default]
+% \definefontsynonym[SerifCaps] [palatinonova-regular*default-caps]
+% \stoptypescript
+
+% \definetypeface[mainface][rm][serif][palatino-nova-regular][default] \setupbodyfont[mainface]
+%
+% \starttext
+% ``Test'' -- --- ff fi fl \sc ``Test'' -- --- ff fi fl
+% \stoptext
+
+% \starttext
+% \definefont
+% [blabla]
+% [name:Latin Modern Something]
+% \definefont
+% [blabla]
+% [file:texnansi-lmr10]
+% \blabla test
+% \definefont
+% [blabla]
+% [texnansi-lmtt10]
+% \blabla test
+% \stoptext
+
+% \starttext
+%
+% \setupcolors[state=start]
+%
+% \definefontfeature
+% [default-base]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes]
+% \definefontfeature
+% [default-node]
+% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes,mode=node]
+% \definefontfeature
+% [default-none]
+% [script=latn,language=dflt,liga=yes,kern=no, tlig=yes,trep=yes]
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:lmroman12regular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:lmroman12regular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:lmroman12regular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:texgyrepagella*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:texgyrepagella*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:texgyrepagella*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \blank
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:palatinonovaregular*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:palatinonovaregular*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:palatinonovaregular*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \startoverlay
+% {\vtop{\color[red] {\font\test=name:OfficinaSerifBookITC*default-node \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[green]{\font\test=name:OfficinaSerifBookITC*default-base \test \input ward \input zapf \input linden }}}
+% {\vtop{\color[blue] {\font\test=name:OfficinaSerifBookITC*default-none \test \input ward \input zapf \input linden }}}
+% \stopoverlay
+%
+% \definefontfeature[superdefault][default][compose=yes]
+%
+% {\font\oeps=name:lmroman10regular*default at 30pt \oeps test \char7683}
+% {\font\oeps=name:lmroman10regular*superdefault at 30pt \oeps test \char7683}
+%
+% \stoptext
+
+\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
+\edef\nullfontname {\fontname\nullfont}
+
+%D \macros
+%D {everyfont,everyfontswitch}
+%D
+%D For special purposes, we provide a hook.
+
+% \newevery \everyfont \relax
+% \newevery \everyfontswitch \relax
+
+%D We also accept \type{sa a}||\type{sa d} as specification.
+
+%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
+
+\def\classfont#1#2{#1#2} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
+
+% We need to move the feature into the filename else it may be
+% overloaded by another reference. For instance the definition of
+% a regular and caps variant can use the same font.
+
+% We could use an indirect method ... store in 'array' and refer to
+% slot.
+
+\unexpanded\def\definefontsynonym[#1]#2[#3]%
+ {\edef\@@fontname{#1}%
+ \edef\@@fontfile{#3}%
+ \ifx\fontclass\empty
+ \expandafter\dodefinefontsynonymnop
+ \else
+ \expandafter\dodefinefontsynonymyes
+ \fi}
+
+\def\dodefinefontsynonymnop
+ {\@EA\let\csname\??ff\@@fontname\endcsname\@@fontfile % maybe just #1 #3, saves expansion
+ \doifnextoptionalelse\dododefinefontsynonymnop\nonodefinefontsynonymnop}
+
+\def\dodefinefontsynonymyes
+ {\@EA\let\csname\??ff\fontclass\@@fontname\endcsname\@@fontfile % maybe just #1 #3, saves expansion
+ \doifnextoptionalelse\dododefinefontsynonymyes\nonodefinefontsynonymyes}
+
+\def\dododefinefontsynonymnop[#1]%
+ {\let\@@ff@@features \undefined
+ \let\@@ff@@fallbacks\undefined
+ \expandafter\dogetfontparameternop#1,]=,}
+
+\def\dododefinefontsynonymyes[#1]%
+ {\let\@@ff@@features \undefined
+ \let\@@ff@@fallbacks\undefined
+ \expandafter\dogetfontparameteryes#1,]=,}
+
+\def\dogetfontparameternop#1=#2,%
+ {\if]#1%
+ \dodododefinefontsynonymnop
+ \else
+ \expandafter\def\csname @@ff@@#1\endcsname{#2}%
+ \expandafter\dogetfontparameternop
+ \fi}
+
+\def\dogetfontparameteryes#1=#2,%
+ {\if]#1%
+ \dodododefinefontsynonymyes
+ \else
+ \expandafter\def\csname @@ff@@#1\endcsname{#2}%
+ \expandafter\dogetfontparameteryes
+ \fi}
+
+% hm, was wrong, class/global reversed
+
+\let\fcglobal\global
+\let\fcxdef \xdef
+\let\fcglet \glet
+
+\def\nonodefinefontsynonymnop
+ {\@EA\let\csname\??ff\@@fontname\s!features \endcsname\undefined
+ \@EA\let\csname\??ff\@@fontname\s!fallbacks\endcsname\undefined}
+
+\def\nonodefinefontsynonymyes
+ {\fcglobal\@EA\let\csname\??ff\fontclass\@@fontname\s!features \endcsname\undefined
+ \fcglobal\@EA\let\csname\??ff\fontclass\@@fontname\s!fallbacks\endcsname\undefined}
+
+\def\dodododefinefontsynonymnop
+ {\@EA\let\csname\??ff\@@fontname\s!features \endcsname\@@ff@@features
+ \@EA\let\csname\??ff\@@fontname\s!fallbacks\endcsname\@@ff@@fallbacks}
+
+\def\dodododefinefontsynonymyes
+ {\fcglobal\@EA\let\csname\??ff\fontclass\@@fontname\s!features \endcsname\@@ff@@features
+ \fcglobal\@EA\let\csname\??ff\fontclass\@@fontname\s!fallbacks\endcsname\@@ff@@fallbacks}
+
+\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
+
+\unexpanded\def\setupfontsynonym
+ {\dodoubleempty\dosetupfontsynonym}
+
+\def\dosetupfontsynonym[#1][#2]% not yet supported, will do when needed
+ {}
+
+\def\truefontname#1%
+ {\@EA\dotruefontname#1*\empty*\relax}
+
+\def\dotruefontname#1*#2#3*#4\relax
+ {\ifcsname\??ff\fontclass#1\endcsname
+ \ifx#2\empty
+ \@EA\truefontname\csname\??ff\fontclass#1\endcsname
+ \else
+ \@EA\redotruefontname\csname\??ff\fontclass#1\endcsname*#2#3%
+ \fi
+ \else\ifcsname\??ff\defaultfontclass#1\endcsname
+ \ifx#2\empty
+ \@EA\truefontname\csname\??ff\defaultfontclass#1\endcsname
+ \else
+ \@EA\redotruefontname\csname\??ff\defaultfontclass#1\endcsname*#2#3%
+ \fi
+ \else\ifcsname\??ff#1\endcsname
+ \ifx#2\empty
+ \@EA\truefontname\csname\??ff#1\endcsname
+ \else
+ \@EA\redotruefontname\csname\??ff#1\endcsname*#2#3%
+ \fi
+ \else
+ #1\ifx#2\empty\else*#2#3\fi
+ \fi\fi\fi}
+
+\def\redotruefontname#1%
+ {\@EA\dodotruefontname#1*\relax}
+
+\def\dodotruefontname#1*#2\relax
+ {\ifcsname\??ff\fontclass#1\endcsname
+ \@EA\redotruefontname\csname\??ff\fontclass#1\endcsname
+ \else\ifcsname\??ff\defaultfontclass#1\endcsname
+ \@EA\redotruefontname\csname\??ff\defaultfontclass#1\endcsname
+ \else\ifcsname\??ff#1\endcsname
+ \@EA\redotruefontname\csname\??ff#1\endcsname
+ \else
+ #1%
+ \fi\fi\fi}
+
+\def\expandfontsynonym#1#2% #2 := onelevelexpansion(#1)
+ {\ifcsname\??ff\fontclass#2\endcsname
+ \expandafter\def\expandafter#1\expandafter{\csname\??ff\fontclass#2\endcsname}%
+ \else\ifcsname\??ff\defaultfontclass#2\endcsname
+ \expandafter\def\expandafter#1\expandafter{\csname\??ff\defaultfontclass#2\endcsname}%
+ \fi\fi}
+
+\def\doifelsefontsynonym#1%
+ {\ifcsname\??ff\fontclass#1\endcsname
+ \@EA\firstoftwoarguments
+ \else\ifcsname\??ff\defaultfontclass#1\endcsname
+ \@EAEAEA\firstoftwoarguments
+ \else
+ \@EAEAEA\secondoftwoarguments
+ \fi\fi}
+
+% \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\dostartfontclass}
+
+\def\dostartfontclass[#1]%
+ {\pushmacro\fontclass
+ \doifelse{#1}\v!each
+ {\let\fontclass\empty}
+ {\doifsomething{#1}{\def\fontclass{#1}}}}
+
+\unexpanded\def\stopfontclass
+ {\popmacro\fontclass}
+
+%D \macros
+%D {tracedfontname}
+%D
+%D A goody:
+
+\def\tracedfontname#1%
+ {#1\ifcsname\??ff\fontclass#1\endcsname
+ \@EA\tracedfontname\csname\??ff\fontclass#1\endcsname
+ \else\ifcsname\??ff#1\endcsname
+ \@EA\tracedfontname\csname\??ff#1\endcsname
+ \fi\fi}
+
+%D \macros
+%D {definefont}
+%D
+%D Before we implement the main definition macro, we first show
+%D 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
+ {\dotripleempty\dodefinefont}
+
+\def\dodefinefont[#1][#2][#3]% [name][spec][1.6 | line=10pt | setup_id]
+ {\ifthirdargument
+ \setuvalue{#1}{\redodefinefont{#1}{#2}{#3}}%
+ \else
+ \setuvalue{#1}{\dododefinefont{#1}{#2}}%
+ \fi}
+
+\def\redodefinefont#1#2#3%
+ {\dododefinefont{#1}{#2}%
+ \doifsetupselse{#3}
+ {\setups[#3]} % don't forget to document this !
+ {\setuplocalinterlinespace[#3]%
+ \setupspacing}} % needed ?
+
+\unexpanded\def\definefrozenfont
+ {\dotripleempty\dodefinefrozenfont}
+
+\def\dodefinefrozenfont[#1][#2][#3]%
+ {\dodefinefont[#1][#2][#3]%
+ \expandafter\let\csname\lastfontidentifier\expandafter\endcsname\csname\rawfontidentifier\endcsname}
+
+%D The \type {*} makes the switch local, so that we can redefine a
+%D logical name and/or change the size in between.
+
+\newif\ifautofontsize \autofontsizetrue
+
+\let\lastfontidentifier\empty
+
+\def\rawfontidentifier{**\lastfontidentifier\fontsize\currentmathsize**}
+\def\newfontidentifier{*\fontclass\lastfontidentifier\fontsize\currentmathsize*}
+
+\let\oldrawfontidentifier\rawfontidentifier
+\let\oldnewfontidentifier\newfontidentifier
+
+\def\newfontidentifier{*\fontclass\lastfontidentifier\fontstyle\fontsize*}
+
+\def\dododefinefont#1#2%
+ {\edef\lastfontidentifier{#1}%
+ \let\localrelativefontsize\defaultrelativefontsize
+ \let\localabsolutefontsize\fontbody
+ \lowleveldefinefont{#2}\rawfontidentifier
+ \csname\rawfontidentifier\endcsname
+ \autofontsizefalse
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \let\rawfontidentifier\oldrawfontidentifier}
+
+\def\xxdododefinefont#1#2#3#4% \autofontsizetrue is set by calling routine
+ {\edef\lastfontidentifier{#3}%
+ \ifcsname\newfontidentifier\endcsname\else
+ \def\localrelativefontsize{#1}%
+ \def\localabsolutefontsize{#2}%
+ \lowleveldefinefont{#4}\newfontidentifier
+ \fi
+ \csname\newfontidentifier\endcsname
+ \autofontsizefalse
+ %\edef\lastfontidentifier{#3}%
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi
+ \let\newfontidentifier\oldnewfontidentifier}
+
+%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
+%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
+
+\def\mapfontsize
+ {\dodoubleargument\domapfontsize}
+
+\def\domapfontsize[#1][#2]%
+ {\setvalue{\??ft*\the\dimexpr#1\relax}{#2}}
+
+\def\setmappedfontsize#1%
+ {\ifcsname\??ft*#1\endcsname
+ \csname\??ft*#1\endcsname
+ \else
+ #1%
+ \fi}
+
+%D \macros
+%D {getfontname}
+%D
+%D The names of the fonts can be called with the rather simple
+%D macro \type{\getfontname}. When for instance we pass
+%D \type{12ptrmtf} as argument, we get \getfontname{12ptrmtf}.
+
+\def\getfontname#1%
+ {\csname\??ft#1\endcsname}
+
+%D To be documented.
+
+\let\fontsizelist \empty
+\let\fontalternativelist\empty
+\let\fontstylelist \empty
+
+\def\checkfontnamecombinations % we need to split math and text here ... todo (math only has mr and mb)
+ {\def\docommand##1%
+ {\def\dodocommand####1%
+ {\def\dododocommand########1{\checkbodyfont{########1}{####1}{##1}}%
+ \processcommacommand[\fontstylelist]\dododocommand}%
+ \processcommacommand[\fontalternativelist]\dodocommand}%
+ \processcommacommand[\fontsizelist]\docommand}
+
+\unexpanded\def\definefontsize[#1]% sneller met toks
+ {\addtocommalist{#1}\fontsizelist
+ \checkfontnamecombinations}
+
+\unexpanded\def\definefontalternative[#1]%
+ {\addtocommalist{#1}\fontalternativelist
+ \checkfontnamecombinations}
+
+%D \macros
+%D {currentfontscale,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 \type {cont-log.tex} for an example of its use.
+
+\def\currentfontscale
+ {\csname\??ft\s!default
+ \ifcsname\??ft\s!default\xfontsize\endcsname \xfontsize \else
+ \ifcsname\??ft\s!default\s!text \endcsname \s!text \fi\fi
+ \endcsname}
+
+\def\currentfontbodyscale
+ {\csname\??ft\s!default
+ \ifcsname\??ft\s!default\fontsize\endcsname \fontsize \else
+ \ifcsname\??ft\s!default\s!text \endcsname \s!text \fi\fi
+ \endcsname}
+
+\setvalue{\??ft\s!default}{1}
+
+%D Both alternatives use \type {\xfontsize}, a macro that
+%D expands to the current size in terms of \type {a} \unknown
+%D \type {d}, nothing, or \type {x} \unknown \type {xx}.
+
+\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\c!x\else\c!xx\fi}
+
+%D A typical use of this command is in commands that switch
+%D to another font bypassing the font mechanism:
+%D
+%D \starttyping
+%D \font\myfont=\truefontname{MyFont} at \the\dimexpr\currentfontscale\bodyfontsize\relax
+%D \stoptyping
+
+%D Now we enter the area of font switching. The switching
+%D mechanism has to take care 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 \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 \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
+%D the moment we stick 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
+%D settings apply. All second parameters are specified in
+%D dimensions and tell us more about related sizes.
+%D
+%D Afterwards, one can change values with
+%D
+%D \showsetup{setupbodyfontenvironment}
+%D
+%D Due to the fact that \type{\c!text} and \type{\s!text} can
+%D have a similar meaning, and therefore can lead to an
+%D unwanted loop, we temporary redefine \type{\c!text}. For
+%D the moment this in only place that some trickery is needed
+%D to fool the multilingual interface. However, long ago
+%D we decided to stick to \s!text in definitions as it closely
+%D relates to the math model where text, script and scriptscript
+%D are used untranslated. Also, we are now english at the low
+%D level so it cannot go wrong anymore.
+%D
+%D When instead of a size the keyword \type{unknown} is
+%D passed, fractions (relations) are used instead of fixed
+%D sizes.
+
+\let\bodyfontenvironmentlist\empty
+
+\newcount\@@fontdefhack % check if this is still needed
+
+\def\@@beginfontdef
+ {\ifcase\@@fontdefhack
+ \let\k!savedtext \k!text \let\k!text \s!text
+ \let\k!k!savedtext \k!k!text \let\k!k!text \!!plusone
+ \let\k!saveddefault \k!default \let\k!default \s!default
+ \let\k!k!saveddefault\k!k!default \let\k!k!default \!!plusone
+ \fi
+ \advance\@@fontdefhack \plusone }
+
+\def\@@endfontdef
+ {\advance\@@fontdefhack \minusone
+ \ifcase\@@fontdefhack
+ \let\k!k!default\k!k!saveddefault
+ \let\k!default \k!saveddefault
+ \let\k!k!text \k!k!savedtext
+ \let\k!text \k!savedtext
+ \fi}
+
+\unexpanded\def\definebodyfontenvironment
+ {\dotripleempty\dodefinebodyfontenvironment}
+
+\def\dodefinebodyfontenvironment[#1][#2][#3]% class size settings
+ {\ifthirdargument
+ \@@beginfontdef
+ \doifelse{#2}\s!default
+ {\getparameters[\??ft\s!default][#3]}
+ {\normalizebodyfontsize#2\to\tempbodyfontsize
+ \addtocommalist\tempbodyfontsize\bodyfontenvironmentlist
+ \@EA\dododefinebodyfontenvironment\@EA[\tempbodyfontsize][#1][#3]}%
+ \@@endfontdef
+ \else
+ \ifx\fontclass\empty\else
+ \writestatus\m!fonts{beware: fontclass ignored (if needed use: [fontclass][size][settings])}%
+ \fi
+ \pushmacro\fontclass
+ \let\fontclass\empty
+ \definebodyfontenvironment[\fontclass][#1][#2]% change */*
+ \popmacro\fontclass
+ \fi}
+
+\def\dododefinebodyfontenvironment[#1][#2][#3]% size class settings
+ {\@@beginfontdef % \s!text goes wrong in testing because the 12pt alternative will called when typesetting the test (or so)
+ \ifcsname\??ft#2#1\c!em\endcsname
+ % we test for em as we assume it to be set
+ \else
+ \def\docommand##1%
+ {\scratchdimen\csname\??ft\s!default##1\endcsname\dimexpr#1\relax
+ \normalizebodyfontsize\scratchdimen\to\tempbodyfontsize
+ \letvalue{\??ft#2#1##1}\tempbodyfontsize}%
+ \processcommacommand[\fontrelativesizelist]\docommand
+ \copyparameters
+ [\??ft#2#1][\??ft\s!default]
+ [\c!interlinespace,\c!em]%
+ \fi
+ \getparameters[\??ft#2#1][#3]%
+ \@@endfontdef
+ % new code, see remark
+ \ifloadingfonts
+ % only runtime
+ \else\ifcsname\@size@#1\endcsname
+ % only once
+ \else
+ % prevent loop (hence \empty)
+ \letvalue{\@size@#1}\empty
+ \pushmacro\fontclass % new per 26102009
+ \edef\fontclass{#2}% % new per 26102009
+ \defineunknownfont{#1}%
+ \popmacro\fontclass % new per 26102009
+ \fi\fi
+ % so far
+ \setvalue{\@size@#1}{\docompletefontswitch[#1]}}
+
+%D {\bf Remark:} We need to cover the following cases,
+%D otherwise users can get 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 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 environment at the outer level.
+
+\def\checkbodyfontenvironment[#1]%
+ {\definebodyfontenvironment[\fontclass][#1][]}
+
+\def\checkbodyfontenvironment[#1]%
+ {\ifcsname\??ft\fontclass#1\c!em\endcsname
+ % we test for em as we assume it to be set
+ \else
+ \definebodyfontenvironment[\fontclass][#1][]%
+ \fi}
+
+% this one already catches both define/setup
+
+\let\setupbodyfontenvironment\definebodyfontenvironment
+
+%D Just a couple of interface macros:
+
+\def\bodyfontvariable#1%
+ {\??ft\ifcsname\??ft\fontclass#1\endcsname\fontclass\fi#1}
+
+\def\bodyfontinterlinespecs
+ {\bodyfontvariable{\normalizedbodyfontsize\c!interlinespace}}
+
+\def\bodyfontinterlinespace
+ {\csname\bodyfontinterlinespecs\endcsname}
+
+%D We default all parameters to the main bodyfont size (begin
+%D \type{#1}), so the next setup is valid too:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[24pt]
+%D \stoptyping
+%D
+%D All parameters can be redefined when needed, so one does
+%D not have to stick to the 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
+%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
+%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
+%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
+%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.
+
+\unexpanded\def\definebodyfont
+ {\doquadrupleempty\redefinebodyfont}
+
+\def\redefinebodyfont[#1][#2][#3][#4]%
+ {\iffourthargument
+ \processcommacommand[#1]{\reredefinebodyfont[#2][#3][#4]}%
+ \else
+ \dodefinebodyfont[#1][#2][#3]%
+ \fi}
+
+\def\reredefinebodyfont[#1][#2][#3]#4%
+ {\pushmacro\fontclass
+ \doifelse{#4}\s!default
+ {\let\fontclass\empty}
+ {\def\fontclass{#4}}%
+ \definebodyfont[#1][#2][#3]%
+ \popmacro\fontclass}
+
+\def\dodefinebodyfont[#1][#2][#3]% body|identifier style defs|identifier
+ {\ifthirdargument
+ \doifnumberelse{#1}
+ {\doifassignmentelse{#3}
+ {% [12pt] [style] [settings]
+ \ifcsname#2\endcsname\else\normalexpanded{\noexpand\definefontstyle[#2][#2]}\fi % new
+ \processcommalist[#1]{\dododefinebodyfont{#2}{#3}}}
+ {% [12pt] [style] [identifier]
+ \dodefinedefaultbodyfont[#1][#2][#3]}} % body style identifier
+ {% [identifier] [style] [settings] % see ***
+ \setvalue{\s!default#1#2}##1##2{\normalexpanded{\noexpand\xdodefinebodyfont[##1][##2][#3]}}}%
+ \else\ifsecondargument
+ \definebodyfont[#1][\c!rm][#2]%
+ \else
+ % Maybe there are default dependencies defined which we can use ([unknown]) and
+ % if not, then we have at least to make sure some basics are set up.
+ \ifcsname\@size@#1\endcsname \else
+ \defineunknownfont{#1}%
+ \fi
+ \ifcsname\@size@#1\endcsname \else
+ \definebodyfont[#1][\c!rm][]%
+ \fi
+ \fi\fi}
+
+\def\xdodefinebodyfont[#1][#2][#3]% body|identifier style defs|identifier
+ {\checkrelativefontsize{#2}% rather new, inherit from other defs
+ \ifcsname#2\endcsname\else\normalexpanded{\noexpand\definefontstyle[#2][#2]}\fi % new
+ \processcommalist[#1]{\dododefinebodyfont{#2}{#3}}%
+ \let\relativefontsize\defaultrelativefontsize}
+
+\def\dododefinebodyfont#1#2#3% style defs body
+ {\checkbodyfontenvironment[#3]% just to be sure.
+ \processcommalist[#2]{\dodododefinebodyfont{#1}{#3}}}
+
+\def\dodododefinebodyfont#1#2#3% style body def
+ {\dododododefinebodyfont{#1}{#2}[#3]}
+
+\def\dododododefinebodyfont
+ {\ifx\fontclass\empty
+ \expandafter\dododododefinebodyfontnop
+ \else
+ \expandafter\dododododefinebodyfontyes
+ \fi}
+
+\def\dododododefinebodyfontyes#1% style body def
+ {\edef\askedbodyfontstyle{#1}%
+ \ifx\askedbodyfontstyle\c!mm
+ \expandafter\dodefinebodyfontyesmm
+ \else
+ \expandafter\dodefinebodyfontyesxx
+ \fi\askedbodyfontstyle} % we can get rid of #1
+
+\def\dododododefinebodyfontnop#1% style body def
+ {\edef\askedbodyfontstyle{#1}%
+ \ifx\askedbodyfontstyle\c!mm
+ \expandafter\dodefinebodyfontnopmm
+ \else
+ \expandafter\dodefinebodyfontnopxx
+ \fi\askedbodyfontstyle} % we can get rid of #1
+
+\def\dodefinebodyfontnopxx#1#2[#3#4#5=#6]% style body def
+ {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
+ \@EA\let\csname*#2#1#3#4#5*\endcsname\undefined
+ \unexpanded\@EA\edef\csname#2#1#3#4#5\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#5}{\normalunexpanded{#6}}}}
+
+\def\dodefinebodyfontyesxx#1#2[#3#4#5=#6]% style body def
+ {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
+ \fcglobal\@EA\let\csname*\fontclass#2#1#3#4#5*\endcsname\undefined
+ \unexpanded\@EA\fcxdef\csname\fontclass#2#1#3#4#5\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#5}{\normalunexpanded{#6}}}}
+
+\def\dodefinebodyfontnopmm#1#2[#3#4#5=#6]% style body def
+ {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
+ \@EA\let\csname*#2#1#3#4#51*\endcsname\undefined
+ \@EA\let\csname*#2#1#3#4#52*\endcsname\undefined
+ \@EA\let\csname*#2#1#3#4#53*\endcsname\undefined
+ \unexpanded\@EA\edef\csname#2#1#3#4#51\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#51}{\normalunexpanded{#6}}}%
+ \unexpanded\@EA\edef\csname#2#1#3#4#52\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#52}{\normalunexpanded{#6}}}%
+ \unexpanded\@EA\edef\csname#2#1#3#4#53\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#53}{\normalunexpanded{#6}}}}
+
+\def\dodefinebodyfontyesmm#1#2[#3#4#5=#6]% style body def
+ {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
+ \fcglobal\@EA\let\csname*\fontclass#2#1#3#4#51*\endcsname\undefined
+ \fcglobal\@EA\let\csname*\fontclass#2#1#3#4#52*\endcsname\undefined
+ \fcglobal\@EA\let\csname*\fontclass#2#1#3#4#53*\endcsname\undefined
+ \unexpanded\@EA\fcxdef\csname\fontclass#2#1#3#4#51\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#51}{\normalunexpanded{#6}}}%
+ \unexpanded\@EA\fcxdef\csname\fontclass#2#1#3#4#52\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#52}{\normalunexpanded{#6}}}%
+ \unexpanded\@EA\fcxdef\csname\fontclass#2#1#3#4#53\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#53}{\normalunexpanded{#6}}}}
+
+\def\checkbodyfont#1% tests for ttsl mmbf
+ {\edef\c!!mm{#1}%
+ \ifx\c!!mm\c!mm % prevents \max and alike (re)defs
+ \expandafter\checkmathbodyfont
+ \else
+ \expandafter\checktextbodyfont
+ \fi{#1}} % no \c!!mm, not expanded later on
+
+% some day we can do an auto-fam if needed
+
+\def\checkmathbodyfont#1#2#3% style alt size / gdef % #3 can be empty
+ {%\message{!m #1 #2 #3!}%
+ % #1 #2 #3 = signal
+ %setugvalue {#2}{\setcurrentfontalternative {#2}}% \mr \mb
+ \setugvalue {#1}{\setcurrentfontstyle {#1}}}% \mm
+
+\def\checktextbodyfont#1#2#3% style alt size / gdef % #3 can be empty
+ {%\message{!t #1 #2 #3!}%
+ \setugvalue {#1#3}{\setcurrentfontstylesize {#1}{#3}}% \rma
+ \setugvalue {#2#3}{\setcurrentfontalternativesize {#2}{#3}}% \sla
+ \setugvalue {#1#2#3}{\setcurrentfontstylealternativesize{#1}{#2}{#3}}% \rmsla
+ \setugvalue {#1}{\setcurrentfontstyle {#1}}% \rm
+ \setugvalue {#2}{\setcurrentfontalternative {#2}}% \sl
+ \setugvalue {#1\c!x}{\setcurrentfontxstylealternative {#1}}% \rmx
+ \setugvalue{#1\c!xx}{\setcurrentfontxxstylealternative {#1}}% \rmxx
+ \setugvalue {#2\c!x}{\setcurrentfontxalternative {#2}}% \slx
+ \setugvalue{#2\c!xx}{\setcurrentfontxxalternative {#2}}% \slxx
+ \setugvalue {#1#2}{\setcurrentfontstylealternative {#1}{#2}}}% \rmsl
+
+\def\dodefinedefaultbodyfont[#1][#2][#3]% sizes styles identifier
+ {\def\dododefinedefaultbodyfont##1%
+ {\def\dodododefinedefaultbodyfont####1%
+ {\def\dododododefinedefaultbodyfont########1%
+ {\ifcsname\s!default########1####1\endcsname
+ % [12pt] [style] [identifier]
+ \csname\s!default########1####1\endcsname{##1}{####1}%
+ \fi}%
+ \processcommalist[#3]\dododododefinedefaultbodyfont}%
+ \processcommalist[#2]\dodododefinedefaultbodyfont}%
+ \processcommalist[#1]\dododefinedefaultbodyfont}
+
+%D Unknown families are added to the family list! For the
+%D moment we also set the direct calls here. Some day a better
+%D solution will be implemented. The good news is that unknown
+%D fonts are defined automatically.
+
+\newif\ifdefiningunknownfont
+
+\def\dodefineunknownfont#1#2%
+ {\ifcsname\??ft\s!default#2\endcsname
+ \donetrue
+ \normalizebodyfontsize\csname\??ft\s!default#2\endcsname\dimexpr#1\relax\to\tempbodyfontsize
+ \letvalue{\??ft#1#2}\tempbodyfontsize
+ \fi}
+
+\def\dodefineunknownbodyfont#1#2% see ***
+ {\ifcsname\s!default\s!default#2\endcsname % somehow related to */*
+ \donetrue
+ \csname\s!default\s!default#2\endcsname{#1}{#2}%
+ \fi}
+
+\def\dodefineunknownsubfont#1#2%
+ {\ifcsname\@size@\csname\??ft#1#2\endcsname\endcsname
+ \else
+ \donetrue
+ \defineunknownfont{\csname\??ft#1#2\endcsname}%
+ \fi}
+
+\unexpanded\def\defineunknownfont#1%
+ {\let\c!savedtext\c!text
+ \let\c!text\s!text
+ \donefalse
+ \processcommacommand[\fontrelativesizelist]{\dodefineunknownfont{#1}}%
+ \let\c!text\c!savedtext
+ \ifdone
+ \donefalse
+ \processcommacommand
+ [\fontstylelist]
+ {\dodefineunknownbodyfont{#1}}%
+ \ifdone
+ \donefalse
+ \setvalue{\@size@#1}{\docompletefontswitch[#1]}%
+ \ifdefiningunknownfont \else
+ \definingunknownfonttrue
+ \processcommacommand[\fontrelativesizelist]{\dodefineunknownsubfont{#1}}%
+ \definingunknownfontfalse
+ \fi
+ \fi
+ \ifdone
+ \showmessage\m!fonts{14}{#1}%
+ \fi
+ \fi}
+
+%D These macros show that quite some definitions take place.
+%D Fonts are not loaded yet! This means that at format
+%D generation time, no font files are preloaded.
+
+%D \macros
+%D {everybodyfont,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 At the system level one can initialize thing like:
+%D
+%D \starttyping
+%D \appendtoks \setupspacing \to \everybodyfont
+%D \stoptyping
+%D
+%D While users can add their own non standard commands like:
+%D
+%D \starttyping
+%D \EveryBodyFont{\message{changing to bodyfont \the\bodyfontsize}}
+%D \stoptyping
+%D
+%D Personnaly I never felt the need for such extensions, but
+%D at least its possible.
+
+%D \macros
+%D {globalbodyfontsize,localbodyfontsize}
+%D
+%D Next we'll do the tough job of font switching. Here we
+%D have to distinguish between the global (overal) bodyfont
+%D size and the local (sometimes in the textflow) size. We
+%D store these dimensions in two \DIMENSION\ registers.
+
+\ifdefined\globalbodyfontsize\else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
+\ifdefined\localbodyfontsize \else \newdimen\localbodyfontsize \fi \localbodyfontsize =\globalbodyfontsize
+
+%D \macros
+%D {bodyfontsize}
+%D
+%D These two registers are not to be misused in calculations.
+%D For this purpose we keep a copy:
+
+\newdimen\bodyfontsize \bodyfontsize=\globalbodyfontsize
+
+%D \macros
+%D {bodyfontfactor,bodyfontpoints}
+%D
+%D For multiplication purposes we keep an auxiliary counter
+%D and macro (here the expansion is not explicitly needed):
+
+\newcount\bodyfontpoints \dimensiontocount\bodyfontsize\bodyfontpoints
+
+\edef\bodyfontfactor{\withoutpt\the\bodyfontsize}
+
+%D When we assign for instance 12pt to a \DIMENSION\ register
+%D the \type{\the}'d value comes out as 12.0pt, which is
+%D often not the way users specify the bodyfont size. Therefore
+%D we also store the normalized value.
+
+\chardef\fontdigits=2 % was 1
+
+% \def\normalizebodyfontsize#1\to#2%
+% {\@EA\@EA\@EA\donormalizedbodyfontsize\@EA\WITHOUTPT\the\dimexpr#1+\ifcase\fontdigits.5\or.05\or.005\fi\points\relax000\to#2}
+%
+% \def\donormalizedbodyfontsize#1.#2#3#4#5\to#6% \points ?
+% {\edef#6% not \ifcase#2\else due to \relax adding
+% {#1%
+% \ifcase\fontdigits
+% \or \ifcase#2 \else .#2\fi % 1
+% \or \ifcase#2#3 \else .#2\ifcase#3 \else #3\fi\fi % 2
+% \else \ifcase#2#3#4 \else .#2\ifcase#4 \ifcase#3 \else#3\fi \else#3#4\fi\fi % 3
+% \fi
+% \s!pt}}
+
+\def\normalizebodyfontsize#1\to#2%
+ {\edef#2{\ctxlua{fonts.nbfs(\number\dimexpr#1\relax,\number\fontdigits)}}}
+
+\def\thenormalizedbodyfontsize#1%
+ {\ctxlua{fonts.nbfs(\number\dimexpr#1\relax,\number\fontdigits)}}
+
+\normalizebodyfontsize\bodyfontsize\to\normalizedglobalbodyfontsize
+\normalizebodyfontsize\bodyfontsize\to\normalizedlocalbodyfontsize
+\normalizebodyfontsize\bodyfontsize\to\normalizedbodyfontsize
+
+%D \macros
+%D {fontstyle,fontalternative,fontsize}
+%D
+%D Within a bodyfont, fonts can come in different sizes. For
+%D instance \type{\tf} is accompanied by \type{\tfa},
+%D \type{\tfb} etc. The first two characters denote the
+%D alternative, while the third character in these sequences
+%D represents the size. The actual size is saved in a macro
+%D
+%D The style, being roman (\type{\rm}), sans serif (\type{\ss})
+%D etc. is also available in a macro in \type{rm}, \type{ss}
+%D etc. form:
+
+\let\defaultfontalternative = \c!tf
+\let\defaultfontstyle = \empty
+\let\defaultfontsize = \empty
+
+\let\fontalternative = \defaultfontalternative
+\let\fontstyle = \defaultfontstyle
+\let\fontsize = \defaultfontsize
+
+%D When \type {\loadfontfileoncetrue}, such files are
+%D only loaded once! This permits redundant loading, but at
+%D the same time forced grouping when we want continuously mix
+%D all kind of font, which of course is a kind of
+%D typographically sin. The \type{"} is made inactive if
+%D needed to prevent problems with loading files that use this
+%D character in numbers.
+
+% can be made faster (only used internally now)
+
+\def\doswitchpoints[#1]%
+ {\normalexpanded{\dodoswitchpoints{#1}}}
+
+\unexpanded \def\dodoswitchpoints#1%
+ {\ifcsname\@size@#1\endcsname \else
+ \defineunknownfont{#1}%
+ \fi%
+ %\defineunknownfontstyles{#1}%
+ \ifcsname\@size@#1\endcsname
+ \csname\@size@#1\endcsname
+ \localbodyfontsize#1\relax
+ \normalizebodyfontsize\localbodyfontsize\to\normalizedbodyfontsize
+ % \edef\fontbody{\fontbody}% to be tested but we can clean up mkiv further
+ \checkbodyfontenvironment[\normalizedbodyfontsize]%
+ \else
+ \showmessage\m!fonts4{#1}%
+ \fi}
+
+\unexpanded \def\doswitchstyle[#1]%
+ {\ifcsname\@style@#1\endcsname
+ \csname\@style@#1\endcsname
+ \edef\fontstyle{#1}%
+ \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{#1}%
+ \fi}
+
+%D \TEX\ loads font metric files like \type{cmr10.tfm} and
+%D \type{tir.tfm} only once. In \PLAIN\ \TEX\ some font files
+%D are {\em preloaded}. This means that the font files are
+%D loaded, but not accessible yet by name. This is accomplished
+%D by saying:
+%D
+%D \starttyping
+%D \font\preloaded=cmr10 at 11pt
+%D \stoptyping
+%D
+%D and using the name \type{\preloaded} again and again, so
+%D fonts are indeed loaded, but unnamed, and therefore
+%D unaccessible. In \CONTEXT\ we don't preload fonts, not even
+%D the \PLAIN\ \TEX\ ones, although users can access them. Now
+%D why is this done?
+
+%D Defining fonts using \type{\definebodyfont} takes time, so we
+%D prefer to predefine at least the Computer Modern Roman
+%D fonts. However, loading all those fonts at definition time
+%D would take both time and space. But even worse, once fonts
+%D are loaded into memory, their encoding vector is fixed,
+%D which is a handicap when we want to distribute the compact
+%D \type{fmt} files. So what we want to do is defining fonts in
+%D a way that postpones the loading. We accomplish this by only
+%D loading the fonts when we switch to another bodyfont size.
+%D Among the other alternatives, such as loading the font at
+%D the moment of activation and redefining the activation
+%D macro afterwards, this proved to be the most efficient
+%D alternative.
+%D
+%D The next few macros take care of the one exeption on this
+%D scheme. When at format generation time we load the default
+%D font file, the one that defines the Computer Modern Fonts,
+%D we don't want the fonts metrics to end up in the format
+%D file, so we temporary prohibit loading. This means that at
+%D runtime we have to load the default bodyfont size just before
+%D we start typesetting.
+%D
+%D Therefore we have to signal the font switching macros that
+%D we are preloading fonts. As long as the next boolean is,
+%D true, no loading is done.
+
+\newif\ifloadingfonts \loadingfontstrue
+
+%D \macros
+%D {preloadfonts}
+%D
+%D Preloading is only called for once, during the startup
+%D sequence of a session. After the loading job is done, the
+%D macro relaxes itself and reset the signal.
+
+% \appendtoks
+% \to \everysetupdocument
+
+\newconditional\fontsareloaded
+
+\def\preloadfonts % never called, needs a clean up
+ {\global\loadingfontsfalse
+ \ifconditional\fontsareloaded \else
+ \doifmodeelse {*nofonts}
+ {\writestatus\m!fonts{latin modern fonts are not preloaded}}
+ {\writestatus\m!fonts{preloading latin modern fonts}%
+ \usetypescript[modern]%
+ \setuptypeface[modern]%
+ \showmessage\m!fonts6{\normalizedbodyfontsize\normalspace\fontstyle}}%
+ \fi
+ \global\let\preloadfonts\relax}
+
+% maybe add this to \everystarttext
+%
+% \ifconditional\fontsareloaded\else
+% \usetypescript[modern]%
+% \setuptypeface[modern]%
+% \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.
+
+\def\dosetfont#1#2% #1 = set/switch state
+ {\doifelse{#2}\v!global
+ {\restoreglobalbodyfont}
+ {\processcommacommand[#2]{\dodosetfont{#1}}% ##1 get also passed
+ \ifloadingfonts\else
+ \global\settrue\fontsareloaded
+ \doswitchpoints[\normalizedbodyfontsize]%
+ \doswitchstyle[\fontstyle]%
+ \ifx\defaultfontclass\empty
+ \let\defaultfontclass\fontclass
+ \fi
+ \fi}%
+ \chardef\currentxfontsize\zerocount}
+
+\def\dodosetfont#1#2% #1 = set/switch state | check fo rempty, else space
+ {\doifsomething{#2}{\dododosetfont{#1}{#2}{\showmessage\m!fonts4{#2}}}}
+
+% % % this can be retrofitted in mkii code % % %
+
+% \def\normalizebodyfontsize#1\to#2%
+% {\@EA\@EA\@EA\donormalizedbodyfontsize\@EA\WITHOUTPT\the\dimexpr#1+\ifcase\fontdigits.5\or.05\or.005\fi\points\relax000\to#2}
+
+\def\dododosetfont#1#2#3% #1 = set/switch state ! ! ! !could also be used for mkii
+ {\doifnumberelse{#2}\dodododosetfont\redododosetfont{#1}{#2}{#3}}
+
+\def\redododosetfont#1#2#3% #1 = set/switch state ! ! ! !could also be used for mkii
+ {\edef\expandedfontthing{#2}%
+ \def\interfacedfontsize{\normalizedbodyfontsize\interfaced\expandedfontthing}%
+ \ifcsname\??ft\interfacedfontsize\endcsname
+ \edef\fontstep{\csname\bodyfontvariable\interfacedfontsize\endcsname}%
+ \normalexpanded{\noexpand\dodododosetfont{#1}{\fontstep}}{#3}%
+ \else\ifx\expandedfontthing\v!reset
+ \let\fontstyle\empty % new 31/7/2006
+ \let\fontsize \empty
+ \else
+ \ifcsname\@style@\expandedfontthing\endcsname
+ \let\fontstyle\expandedfontthing
+ \else
+ \setcurrentfontclass\expandedfontthing
+ \ifcase#1\relax
+ \let\globalfontclass\globalfontclass
+ \else
+ \let\globalfontclass\fontclass
+ \fi
+ \ifx\fontclass\empty
+ \let\fontstyle\c!rm
+ \else\ifcsname\??tf\fontclass\s!default\endcsname
+ \edef\fontstyle{\csname\??tf\fontclass\s!default\endcsname}%
+ \else
+ \let\fontstyle\c!rm
+ \fi\fi
+ \fi
+ \fi\fi}
+
+\def\dodododosetfont#1#2#3% #1 = set/switch state
+ {\normalizebodyfontsize#2\to\normalizedsetfont
+ \ifcsname\@size@\normalizedsetfont\endcsname \else
+ \defineunknownfont{#2}%
+ \fi
+ \ifcsname\@size@\normalizedsetfont\endcsname
+ \localbodyfontsize\normalizedsetfont
+ \let\normalizedbodyfontsize\normalizedsetfont
+ \else
+ #3\dosetsubstitutefont{#1}{#2}%
+ \fi}
+
+% % %
+
+%D In the previous 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.
+
+\chardef\currentxfontsize=0
+
+%D When users specify for instance a 13 point bodyfont while no
+%D such bodyfont is defined, the system automatically tries to
+%D find a best fit, that is the nearest smaller defined
+%D bodyfontzize. A smaller one is definitely better than a larger
+%D one, simply because otherwise a lot of overfull box messages
+%D are more probable to occur. By taking a value slightly
+%D smaller than half a point, we can use the next method.
+
+\def\dosetsubstitutefont#1#2% #1 = set/switch state
+ {\scratchdimen#2\relax
+ \advance\scratchdimen .499\points
+ \dimensiontocount\scratchdimen\scratchcounter
+ \advance\scratchcounter \minusone
+ \ifnum\scratchcounter>\plusthree
+ \dododosetfont{#1}{\the\scratchcounter\s!pt}{}%
+ \fi}
+
+% The following bunch of macros deals with the (run time)
+% expansion of names onto the definitions made by \type
+% {\definebodyfont}.
+
+% \let\fontbody \empty % ... 10pt 11pt 12pt ...
+% \let\fontstyle \empty % rm ss tt mm hw cg ...
+% \let\fontalternative\empty % tf bf sl it bs bi sc ...
+% \let\fontsize \empty % xy-abcd ...
+
+\def\defaultfontbody{\normalizedbodyfontsize}
+
+\let\fontbody\defaultfontbody
+
+\let\fontclass\empty \let\globalfontclass\fontclass
+
+% we need to check the fontclass
+
+\def\registerfontclass#1%
+ {\letgvalue{\@fontclass@#1}\v!yes} % global ?
+
+\edef\@no@fontclass@{\@fontclass@:?:}
+
+\def\setcurrentfontclass#1%
+ {\ifcsname\@fontclass@#1\endcsname
+ \edef\fontclass{#1}%
+ \else\ifcsname\@no@fontclass@#1\endcsname
+ % already tried
+ \else\ifcase\currentgrouplevel
+ \trycurrentfontclass{#1}%
+ \fi\fi\fi}
+
+\def\savefontclassparameters#1#2#3#4% #1=rm|ss|.. rscale features fallbacks
+ {\setxvalue{\fontclass#1\s!rscale }{#2}%
+ \setxvalue{\fontclass#1\s!features }{#3}%
+ \setxvalue{\fontclass#1\s!fallbacks}{#4}}
+
+\settrue\autotypescripts
+
+% \def\trycurrentfontclass#1%
+% {\ifconditional\autotypescripts
+% \usetypescript[#1]%
+% \ifcsname\@fontclass@#1\endcsname
+% \edef\fontclass{#1}%
+% \else
+% \letvalue{\@no@fontclass@#1}\empty
+% \fi
+% \else
+% \letvalue{\@no@fontclass@#1}\empty
+% \fi}
+
+\def\trycurrentfontclass#1%
+ {\ifconditional\autotypescripts
+ % try to load typescript #1
+ \usetypescript[#1]%
+ \ifcsname\@fontclass@#1\endcsname
+ \edef\fontclass{#1}%
+ \else
+ % try to load type-#1.mkiv
+ \usetypescriptfile[\f!typeprefix#1]%
+ % try to load typescript #1
+ \usetypescript[#1]%
+ \ifcsname\@fontclass@#1\endcsname
+ \edef\fontclass{#1}%
+ \else
+ % todo: message
+ \letvalue{\@no@fontclass@#1}\empty
+ \fi
+ \fi
+ \else
+ % todo: message
+ \letvalue{\@no@fontclass@#1}\empty
+ \fi}
+
+\let\defaultfontstyle \c!rm
+\let\defaultfontalternative \c!tf
+\let\defaultfontsize \empty
+
+%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
+
+\chardef\synchronizebigmathflag=1
+
+\appendtoks
+ \ifcase\synchronizebigmathflag
+ % never
+ \or
+ \synchronizebigmath
+ \or
+ % always
+ \fi
+\to \everymathematics
+
+\def\nobigmath {\chardef\synchronizebigmathflag\zerocount}
+\def\autobigmath{\chardef\synchronizebigmathflag\plusone\synchronizebigmath}
+\def\bigmath {\chardef\synchronizebigmathflag\plustwo\synchronizebigmath}
+
+\let\bigmathfontsize\empty
+
+\def\synchronizebigmath
+ {\ifx\bigmathfontsize\fontsize
+ % already in sync
+ \else
+ \let\bigmathfontsize\fontsize
+ \synchronizemath
+ \fi}
+
+\def\checkbigmathsynchronization
+ {\ifcase\synchronizebigmathflag
+ % never
+ \or
+ \ifmmode \synchronizebigmath \fi
+ \or
+ \synchronizebigmath
+ \fi}
+
+%D So far for synchronisation. (We can inline the following macros.)
+
+\def\dosetcurrentfontsize#1%
+ {\edef\fontsize{#1}%
+ \checkbigmathsynchronization}
+
+\def\dosetcurrentfontalternative#1%
+ {\edef\fontalternative{#1}}
+
+\def\setcurrentfont#1#2#3#4%
+ {%\message{[1 #1 #2 #3 #4]}%
+ \edef\fontbody{#1}%
+ \edef\fontstyle{#2}%
+ \dosetcurrentfontalternative{#3}%
+ \dosetcurrentfontsize{#4}%
+ \synchronizefont}
+
+\def\setcurrentfontbody#1%
+ {%\message{[2 #1]}%
+ \edef\fontbody{#1}%
+ \synchronizefont}
+
+% For Taco: optional fall backs:
+
+\ifx\checkfontclass\undefined \let\checkfontclass\gobbleoneargument \fi % implemented in type-ini
+
+% \def\setcurrentfontstyle#1%
+% {%\message{[3 #1]}%
+% \checkfontclass{#1}%
+% \edef\fontstyle{#1}%
+% \ifmmode\mr\fi % otherwise \rm not downward compatible
+% \synchronizefont}
+
+\def\setcurrentfontstyle#1%
+ {%\message{[3 #1]}%
+ \edef\fontstyle{#1}%
+ \checkfontclass\fontstyle
+ \ifmmode\mr\fi % otherwise \rm not downward compatible
+ \synchronizefont}
+
+\def\setcurrentfontbodyalternative#1#2%
+ {%\message{[4 #1 #2]}%
+ \edef\fontbody{#1}%
+ \dosetcurrentfontalternative{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontalternative#1%
+ {%\message{[5 #1]}%
+ \dosetcurrentfontalternative{#1}%
+ \synchronizefont}
+
+\def\setcurrentfontsize#1%
+ {%\message{[6 #1]}%
+ \dosetcurrentfontsize{#1}%
+ \synchronizefont}
+
+\def\setcurrentfontstylealternative#1#2% \rmsl
+ {%\message{[7 #1 #2]}%
+ \edef\fontstyle{#1}%
+ \dosetcurrentfontalternative{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontstylesize#1#2% \rmsla
+ {%\message{[8 #1 #2]}%
+ \edef\fontstyle{#1}%
+ \dosetcurrentfontsize{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontalternativesize#1#2% \sla
+ {%\message{[9 #1 #2]}%
+ \dosetcurrentfontalternative{#1}%
+ \dosetcurrentfontsize{#2}%
+ \synchronizefont}
+
+\def\setcurrentfontstylealternativesize#1#2#3% \rmsla
+ {%\message{[10 #1 #2 #3]}%
+ \edef\fontstyle{#1}%
+ \dosetcurrentfontalternative{#2}%
+ \dosetcurrentfontsize{#3}%
+ \synchronizefont}
+
+%D In principle one can assign alternative fallback routines.
+%D Some day we will.
+
+\newtoks\fontstrategies
+\newif\iftryingfont
+
+\let\fontstrategy\relax
+
+\def\synchronizefont % we can have dups i.e. no need to let fontstrategy
+ {\tryingfonttrue
+ \ifx\fontclass\empty
+ \applyfontstrategies
+ \else
+ \applyfontclassstrategies
+ \fi
+ \autofontsizefalse
+ \ifskipfontcharacteristics
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+\def\fontclassstrategiesa % --- --- --- --- % pt tt bf a
+ {\ifcsname\fontclass\fontbody \fontstyle \fontalternative \fontsize\endcsname
+ \autofontsizefalse
+ \csname\fontclass\fontbody \fontstyle \fontalternative \fontsize\endcsname
+ \else
+ \expandafter\fontclassstrategiesb
+ \fi}
+
+\def\fontclassstrategiesb % --- --- --- def % pt tt bf
+ {\ifcsname\fontclass\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
+ \autofontsizetrue
+ \csname\fontclass\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
+ \else
+ \expandafter\fontclassstrategiesc
+ \fi}
+
+\def\fontclassstrategiesc % --- --- def --- % pt tt tf a
+ {\ifcsname\fontclass\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
+ \autofontsizetrue
+ \csname\fontclass\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
+ \else
+ \expandafter\fontclassstrategiesd
+ \fi}
+
+\def\fontclassstrategiesd % --- --- def def % pt tt tf
+ {\ifcsname\fontclass\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \autofontsizetrue
+ \csname\fontclass\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \else
+ \expandafter\fontclassstrategiese
+ \fi}
+
+\def\fontclassstrategiese % --- def def def % pt rm tf
+ {\ifcsname\fontclass\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \autofontsizefalse
+ \csname\fontclass\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \else
+ \expandafter\fontclassstrategiesf
+ \fi}
+
+\def\fontclassstrategiesf % def def def def % rm tf
+ {\ifcsname\fontclass\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \autofontsizetrue
+ \csname\fontclass\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \else
+ \expandafter\fontstrategiesa
+ \fi}
+
+% no class
+
+\def\fontstrategiesa % --- --- --- --- % pt tt bf a
+ {\ifcsname\fontbody \fontstyle \fontalternative \fontsize\endcsname
+ \autofontsizefalse
+ \csname\fontbody \fontstyle \fontalternative \fontsize\endcsname
+ \else
+ \expandafter\fontstrategiesb
+ \fi}
+
+\def\fontstrategiesb % --- --- --- --- % pt tt bf a
+ {\ifcsname\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
+ \autofontsizetrue
+ \csname\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
+ \else
+ \expandafter\fontstrategiesc
+ \fi}
+
+\def\fontstrategiesc % --- --- --- --- % pt tt bf a
+ {\ifcsname\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
+ \autofontsizetrue
+ \csname\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
+ \else
+ \expandafter\fontstrategiesd
+ \fi}
+
+\def\fontstrategiesd % --- --- --- --- % pt tt bf a
+ {\ifcsname\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \autofontsizetrue
+ \csname\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \else
+ \expandafter\fontstrategiese
+ \fi}
+
+\def\fontstrategiese % --- --- --- --- % pt tt bf a
+ {\ifcsname\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \autofontsizefalse
+ \csname\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \else
+ \expandafter\fontstrategiesf
+ \fi}
+
+\def\fontstrategiesf % --- --- --- --- % pt tt bf a
+ {\ifcsname\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \autofontsizetrue
+ \csname\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
+ \fi}
+
+\let\applyfontstrategies \fontstrategiesa
+\let\applyfontclassstrategies\fontclassstrategiesa
+
+%D Let's synchronize:
+
+\newif\ifsynchronizefonts \synchronizefontstrue
+
+\prependtoks
+ \ifsynchronizefonts
+ \synchronizemath
+ \synchronizefont % problem: syncs last font
+ \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}.
+
+\def\dosetcurrentfontxxxalternative#1#2#3#4%
+ {\chardef\currentxfontsize#2\relax
+ \ifmmode
+ #4%
+ \else\ifcsname\bodyfontvariable{\normalizedbodyfontsize#3}\endcsname
+ \setcurrentfontbodyalternative{\csname\bodyfontvariable\normalizedbodyfontsize#3\endcsname}{#1}%
+ \fi\fi}
+
+\def\setcurrentfontxalternative#1%
+ {\dosetcurrentfontxxxalternative{#1}1\c!x\scriptstyle
+ \let\tx\txx}
+
+\def\setcurrentfontxxalternative#1%
+ {\dosetcurrentfontxxxalternative{#1}2\c!xx\scriptscriptstyle
+ \let\tx\empty
+ \let\txx\empty}
+
+\def\checknestedxfontsize % option
+ {\ifcase\currentxfontsize\else\ifx\fontsize\empty\else
+ \chardef\currentxfontsize\zeropoint
+ \let\fontsize\empty
+ \let\tx\normaltx
+ \let\txx\normaltxx
+ \fi\fi}
+
+\def\setcurrentfontxalternative#1%
+ {\checknestedxfontsize
+ \dosetcurrentfontxxxalternative{#1}1\c!x\scriptstyle
+ \let\tx\txx}
+
+\def\setcurrentfontxxalternative#1%
+ {\checknestedxfontsize
+ \dosetcurrentfontxxxalternative{#1}2\c!xx\scriptscriptstyle
+ \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.
+
+\def\setcurrentfontxstylealternative #1{\csname#1\endcsname\tx}
+\def\setcurrentfontxxstylealternative#1{\csname#1\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
+%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 \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%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.
+
+\unexpanded\def\tx {\setcurrentfontxalternative \fontalternative}
+\unexpanded\def\txx{\setcurrentfontxxalternative\fontalternative}
+
+\let\normaltx \tx
+\let\normaltxx\txx
+
+%D \macros
+%D {definefontstyle}
+%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
+%D \starttyping
+%D \definefontstyle [serif,rm] [rm]
+%D \definefontstyle [sansserif,ss] [ss]
+%D \stoptyping
+
+\def\dodefinefontstyle[#1][#2]%
+ {\rawdoifinsetelse{#2}{\fontstylelist}
+ {%\debuggerinfo\m!fonts{unknown style #2}%
+ }
+ {%\debuggerinfo\m!fonts8{#2\space (#1)}%
+ \addtocommalist{#2}\fontstylelist}%
+ % check kan hier
+ \def\docommand##1%
+ {\setvalue{\@shortstyle@##1}{#2}%
+ \setvalue{\@style@##1}{\csname#2\endcsname}}%
+ \processcommalist[#1]\docommand}
+
+\unexpanded\def\definefontstyle
+ {\dodoubleargument\dodefinefontstyle}
+
+\def\setfontstyle#1#2% #1:name (roman, romaan) #2:style (rm)
+ {\edef\fontstyle{#1}%
+ \checkfontnamecombinations
+ \setcurrentfontstyle\normalizedbodyfontsize}
+
+%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}
+
+\def\dosetbodyfontface#1#2%
+ {\edef#1{\csname\bodyfontvariable\normalizedbodyfontsize#2\endcsname}}
+
+\def\docompletefontswitch[#1]%
+ {\bodyfontsize#1\relax
+ \dimensiontocount\bodyfontsize\bodyfontpoints % rounded, still used in m-chart
+ \edef\bodyfontfactor{\withoutpt\the\bodyfontsize}%
+ \normalizebodyfontsize\bodyfontsize\to\normalizedbodyfontsize
+ \dosetbodyfontface \textface \s!text
+ \dosetbodyfontface \scriptface \s!script
+ \dosetbodyfontface \scriptscriptface \s!scriptscript}
+
+\docompletefontswitch[12pt] % init
+
+%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
+%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
+%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
+%D all kind of keywords into account.
+
+\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi
+\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi
+
+% \newtoks \everysetupbodyfont
+% \newtoks \everyswitchtobodyfont
+
+\chardef\bodyfontsetstate=0
+
+\definecomplexorsimple\setupbodyfont
+
+\def\simplesetupbodyfont
+ {\restoreglobalbodyfont
+ \saveinterlinespace}
+
+\def\complexsetupbodyfont[#1]%
+ {\doifsomething{#1}
+ {\dosetfont1{#1}%
+ \globalbodyfontsize\localbodyfontsize
+ \normalizebodyfontsize\globalbodyfontsize\to\normalizedglobalbodyfontsize
+ \let\globalfontstyle\fontstyle
+ \ifloadingfonts\else
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace
+ \fi
+ \the\everysetupbodyfont}}
+
+\unexpanded\def\switchtobodyfont[#1]%
+ {\doifsomething{#1}
+ {\ifcsname\??ft\normalizedbodyfontsize\interfaced{#1}\endcsname
+ \setbodyfontstep{#1}% so we have a fast [small] switch
+ \else
+ \dosetfont0{#1}%
+ \fi
+ \the\everybodyfont
+ \the\everyswitchtobodyfont}}
+
+%D The following alternative is meant for math||to||text
+%D switching and will be optimized.
+
+\def\fastswitchtobodyfont#1%
+ {\ifcsname\??ft\normalizedbodyfontsize#1\endcsname
+ \edef\futurebodyfontsize{\csname\??ft\normalizedbodyfontsize#1\endcsname}%
+ \ifcsname\@size@\futurebodyfontsize\endcsname
+ \csname\@size@\futurebodyfontsize\endcsname
+ \localbodyfontsize\futurebodyfontsize\relax
+ \fi
+ \fi
+ \csname\@style@\fontstyle\endcsname
+ \the\everybodyfont}
+
+%D \starttyping
+%D $\cases{& \ccaron}$ $x=\hbox{\ccaron $x=\hbox{\ccaron}$}$
+%D \stoptyping
+
+\def\setfontcharacteristics
+ {\the\everyfont}
+
+%D Predefined:
+
+% \installfontfeature[otf][tlig]
+% \installfontfeature[otf][trep]
+
+%D tricky but ok:
+
+\appendtoks\ctxlua{fonts.tfm.cleanup()}\to\everyshipout
+
+%D Todo:
+
+% \def\os{\groupedcommand{\setfontfeature{oldstyle}}{}}
+
+%D Experimental:
+
+\unexpanded\def\definefontfeature
+ {\dotripleargument\dodefinefontfeature}
+
+\def\dodefinefontfeature[#1][#2][#3]%
+ {\global\expandafter\chardef\csname\??fq=#1\endcsname % beware () needed as we get two values returned
+ \ctxlua{tex.write((fonts.define.specify.preset_context("#1","#2","#3")))}\relax}
+
+\definefontfeature
+ [default]
+ [%mode=node,
+ liga=yes,kern=yes,tlig=yes,trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [smallcaps]
+ [%mode=node,liga=yes,
+ smcp=yes,kern=yes,tlig=yes,trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [oldstyle]
+ [%mode=node,
+ onum=yes,liga=yes,kern=yes,tlig=yes,trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature % == default unless redefined
+ [ligatures]
+ [%mode=node,
+ liga=yes,kern=yes,tlig=yes,trep=yes]
+
+\definefontfeature % can be used for type1 fonts
+ [complete]
+ [liga=yes,kern=yes,compose=yes,tlig=yes,trep=yes]
+
+\definefontfeature
+ [arabic]
+ [mode=node,language=dflt,script=arab,ccmp=yes,
+ init=yes,medi=yes,fina=yes,isol=yes,
+ liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes,
+ mark=yes,mkmk=yes,kern=yes,curs=yes]
+
+\definefontfeature
+ [none]
+ [mode=none,features=no]
+
+\definefontfeature
+ [virtualmath]
+ [mode=base,liga=yes,kern=yes,tlig=yes,trep=yes]
+
+% for the moment here, this will change but we need it for mk.tex
+
+\definefontfeature[math-text] [virtualmath][ssty=no]
+\definefontfeature[math-script] [virtualmath][ssty=1,mathsize=yes]
+\definefontfeature[math-scriptscript][virtualmath][ssty=2,mathsize=yes]
+
+\definefontfeature [math-nostack-text] [math-text] [nostackmath=yes]
+\definefontfeature [math-nostack-script] [math-script] [nostackmath=yes]
+\definefontfeature [math-nostack-scriptscript][math-scriptscript][nostackmath=yes]
+
+% \definefontfeature[mathtext] [math-text]
+% \definefontfeature[mathscript] [math-script]
+% \definefontfeature[mathscriptscript] [math-scriptscript]
+
+%D Also new, handy for manuals:
+
+\unexpanded\def\fontchar#1{\ctxlua{fonts.char("#1")}}
+
+\let\otfchar\fontchar % will disappear, for compatibility only
+\let\afmchar\fontchar % will disappear, for compatibility only
+
+%D: We cannot yet inherit because no colors are predefined.
+
+\definecolor[font:init][r=.75]
+\definecolor[font:medi][g=.75]
+\definecolor[font:fina][b=.75]
+\definecolor[font:isol][r=.75,g=.75] % [y=.75]
+\definecolor[font:mark][r=.75,b=.75] % [m=.75]
+\definecolor[font:rest][g=.75,b=.75] % [c=.75]
+
+%D Experimental!
+
+\def\installfontfeature
+ {\dodoubleargument\doinstallfontfeature}
+
+\def\doinstallfontfeature[#1][#2]%
+ {\writestatus\m!fonts{installing font features was experimental}} % \ctxlua{fonts.install_feature("#1","#2")}}
+
+%D Not yet in \MKII.
+
+\def\fontfeatureslist
+ {\dodoubleargument\dofontfeatureslist}
+
+\def\dofontfeatureslist[#1][#2]% todo: arg voor type
+ {\ctxlua{tex.sprint(tex.ctxcatcodes,fonts.define.specify.context_tostring("#1","otf","\luaescapestring{#2}","yes","no",true,{"number"}))}}
+
+\attribute\zerocount\zerocount % first in list, so fast match
+
+\let\currentfeature\empty
+
+% ! ! ! very experimental, some test code for idris advanced features ! ! !
+%
+% \startbuffer
+% \definefontfeature[smallcaps][smallcaps][script=latn]
+% \definefontfeature[oldstyle] [oldstyle] [script=latn]
+%
+% \definedfont[name:cambria at 15pt]
+%
+% Hello there {\setff{smallcaps}capped 123 \setff{oldstyle}123!} \blank
+% Hello there {\addff{smallcaps}capped 123 \addff{oldstyle}123!} \blank
+% Hello there {\addff{smallcaps}capped \subff{smallcaps}normal} \blank
+% \stopbuffer
+%
+% \typebuffer \getbuffer
+
+\def\featureattribute#1{\ctxlua{tex.sprint(fonts.define.specify.context_number("#1"))}}
+\def\setfontfeature #1{\edef\currentfeature{#1}\attribute\zerocount\featureattribute{#1}\relax}
+\def\resetfontfeature#1{\let\currentfeature\empty\attribute\zerocount\zerocount} % initial value
+
+\def\addfontfeaturetoset #1{\ctxlua{fonts.withset("#1", 1)}} % merge
+\def\subtractfontfeaturefromset #1{\ctxlua{fonts.withset("#1",-1)}} % merge
+\def\addfontfeaturetofont #1{\ctxlua{fonts.withfnt("#1", 2)}} % overload
+\def\subtractfontfeaturefromfont#1{\ctxlua{fonts.withfnt("#1",-2)}} % overload
+
+\let\setff\setfontfeature
+\let\addfs\addfontfeaturetoset
+\let\subfs\subtractfontfeaturefromset
+\let\addff\addfontfeaturetofont
+\let\subff\subtractfontfeaturefromfont
+
+%D The next auxilliary macro is an alternative to \type
+%D {\fontname}.
+
+\def\purefontname#1{\ctxlua{file.basename("\fontname#1"}} % will be function using id
+
+%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
+
+\definecomplexorsimple\switchstyleonly
+
+\def\simpleswitchstyleonly#1% stupid version
+ {\complexswitchstyleonly[\checkedstrippedcsname#1]}
+
+\def\complexswitchstyleonly[#1]% todo : check
+ {\setcurrentfontstyle{\csname\@shortstyle@#1\endcsname}%
+ \the\everybodyfont} % needed ?
+
+%D \macros
+%D {os}
+%D
+%D In good old \TEX, the old style numerals were often taken
+%D from the math fonts. No longer.
+
+\definefontfeature
+ [just-os]
+ [mode=node,onum=yes]
+
+% \def\sc{\setfontfeature{smallcaps}}
+\unexpanded\def\os{\setfontfeature{just-os}}
+
+%D Code for switching to fraktur and script has also been
+%D changed. We now have an alphabet switcher.
+
+\ifx\mathtext\undefined \let\mathtext\hbox \fi
+
+%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
+%D \starttyping
+%D \definebodyfontswitch [twelvepoint] [12pt]
+%D \stoptyping
+%D
+%D We don't support language specific synonyms here, mainly
+%D because \PLAIN\ \TEX\ is english anyway.
+
+\def\dodefinebodyfontswitch[#1][#2]%
+ {\def\docommand##1{\setvalue{##1}{\switchtobodyfont[#2]}}%
+ \processcommalist[#1]\docommand}
+
+\unexpanded\def\definebodyfontswitch
+ {\dodoubleargument\dodefinebodyfontswitch}
+
+%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.
+
+\let\fontstep\empty % we can use \fontstep for tracing purposes
+
+\def\setbodyfontstep#1%
+ {\edef\fontstep{\csname\bodyfontvariable\normalizedbodyfontsize\interfaced{#1}\endcsname}%
+ \doswitchpoints[\fontstep]%
+ \doswitchstyle[\fontstyle]}
+
+\unexpanded\def\setsmallbodyfont{\setbodyfontstep\v!small\the\everybodyfont}
+\unexpanded\def\setbigbodyfont {\setbodyfontstep\v!big \the\everybodyfont}
+
+\unexpanded\def\setmainbodyfont
+ {\doswitchpoints[\normalizedbodyfontsize]%
+ \doswitchstyle[\fontstyle]%
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+%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:
+
+\let\globalfontstyle\c!rm
+
+\def\fullrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \chardef\currentxfontsize\zerocount
+ \let\fontclass\globalfontclass
+ \doswitchpoints[\normalizedglobalbodyfontsize]%
+ \doswitchstyle[\globalfontstyle]%
+ \redoconvertfont % just in case a pagebreak occurs
+ \tf
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+\def\partialrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \chardef\currentxfontsize\zerocount
+ \redoconvertfont
+ \tf
+ \the\everybodyfont % indeed needed
+ \the\everyglobalbodyfont % indeed needed
+ \saveinterlinespace}
+
+\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 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 \macros
+%D {rasterfont}
+%D
+%D There are (at the moment) two situations in which we want to
+%D have fast access to a particular font. When we are using
+%D \TEX\ to typeset rasters, we use small {\rasterfont.}'s
+%D (a rather small period indeed), the same as \PICTEX\ uses
+%D for drawing purposes.
+
+\definefont [rasterfont] [Serif at 5pt]
+
+%D \macros
+%D {infofont}
+%D
+%D The second situation occurs when we enable the info mode,
+%D and put all kind of status information in the margin. We
+%D don't want huge switches to the main bodyfont and style, so
+%D here too we use a direct method.
+
+\let\infofont\relax % satisfy dep checker
+
+\definefont [infofont] [Mono at 6pt] % todo \the\everybodyfont
+
+%D \macros
+%D {definealternativestyle}
+%D
+%D In the main modules we are going to implement lots of
+%D parameterized commands and one of these parameters will
+%D concern the font to use. To suit consistent use of fonts we
+%D here implement a mechanism for defining the keywords that
+%D present a 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
+%D second command takes care of headings and alike. Consider
+%D 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
+%D \type{\tfd} does not look that well, so therefore we leave
+%D the second argument of \type{\definealternativestyle} empty.
+%D When we capatalize characters using the pseudo small cap
+%D command \type{\cap}, we want this to take effect in both
+%D text and headings, which is accomplished by assigning both
+%D arguments.
+
+\def\dodefinealternativestyle[#1][#2][#3]%
+ {\def\docommand##1%
+ {\ifcsname##1\endcsname\else\setuvalue{##1}{\groupedcommand{#2}{}}\fi
+ \setvalue{\@letter@ ##1}{#2}%
+ \setvalue{\@noletter@##1}{#3}}%
+ \processcommalist[#1]\docommand}
+
+\unexpanded\def\definealternativestyle
+ {\dotripleempty\dodefinealternativestyle}
+
+\unexpanded\def\definestyle{\definealternativestyle}
+
+%D Maybe too geneneric, but probably ok is the following. (Maybe one
+%D day we will use a dedicated grouped command for styles.)
+
+\appendtoks
+ \let\groupedcommand\thirdofthreearguments
+\to \simplifiedcommands
+
+%D This command also defines the keyword as command. This means
+%D that the example definition of \type{bold} we gave before,
+%D results in a command \type{\bold} 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 \startvoorbeeld
+%D \definealternativestyle[bold][\bf][]\getbuffer
+%D \stopvoorbeeld
+%D
+%D Such definitions are of course unwanted for \type{\cap}
+%D because this would result in an endless recursive call.
+%D Therefore we check on the existance of both the command and
+%D the substitution. The latter is needed because for instance
+%D \type{\type} is an entirely diferent command. That command
+%D handles verbatim, while the style command would just switch
+%D to teletype font. This is just an example of a tricky
+%D naming coincidence.
+
+%D \macros
+%D {doconvertfont,noconvertfont,
+%D dontconvertfont,redoconvertfont}
+%D
+%D After having defined such keywords, we can call for them by
+%D using
+%D
+%D \starttyping
+%D \doconvertfont{keyword}{text}
+%D \stoptyping
+%D
+%D We deliberately pass an argument. This enables us to
+%D assign converters that handle one argument, like
+%D \type{\cap}.
+%D
+%D By default the first specification is used to set the style,
+%D exept when we say \type{\dontconvertfont}, after which the
+%D second specification is used. We can also directly call for
+%D \type{\noconvertfont}. In nested calls, we can restore the
+%D conversion by saying \type{\redoconvertfont}.
+
+% subtle ... \expandafter is needed else problems with lookahead caps
+
+\def\@@dodoconvertfont{\csname\@letter@ \p!defined\expandafter\endcsname\gobbleoneargument}
+\def\@@donoconvertfont{\csname\@noletter@\p!defined\endcsname}
+\def\@@redoconvertfont{\csname \p!defined\expandafter\endcsname\gobbleoneargument}
+
+% beware: p!defined can contain crap like \edef crap {...} and such
+% so we need to pass #1 as well
+
+\unexpanded\def\dodoconvertfont#1% #2% we need the protection
+ {\edef\p!defined{#1}%
+ \ifx\p!defined\empty\else
+ \@EA\dododoconvertfont
+ \fi{#1}}
+
+\def\dododoconvertfont % #1
+ {\ifcsname\@letter@\detokenize\@EA{\p!defined}\endcsname
+ \@EA\@@dodoconvertfont
+ \else\ifcsname\detokenize\@EA{\p!defined}\endcsname
+ \@EAEAEA\@@redoconvertfont
+ \else
+ \@EAEAEA\firstofoneargument
+ \fi\fi} % {#1}
+
+\let\doconvertfont\dodoconvertfont
+
+\unexpanded\def\noconvertfont#1% #2%
+ {\edef\p!defined{#1}%
+ \ifx\p!defined\empty
+ \else
+ \@EA\nononoconvertfont
+ \fi}
+
+\def\nononoconvertfont
+ {\ifcsname\@noletter@\detokenize\@EA{\p!defined}\endcsname
+ \@EA\@@donoconvertfont
+ \fi}
+
+%D Extras:
+
+\unexpanded\def\dontconvertfont{\let\doconvertfont\noconvertfont}
+\unexpanded\def\redoconvertfont{\let\doconvertfont\dodoconvertfont}
+
+%D These commands are not grouped! Grouping is most probably
+%D done by the calling macro's and would lead to unnecessary
+%D overhead.
+
+%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 furter 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
+%D \starttyping
+%D \def\emphasistypeface {\it}
+%D \def\emphasisboldface {\bi}
+%D \stoptyping
+%D
+%D But we prefer:
+
+\def\emphasistypeface {\sl}
+\def\emphasisboldface {\bs}
+
+%D or even better:
+
+\def\doemphasistypeface#1#2%
+ {\edef\emphasizedtypeface{\csname\??ft\fontclass\normalizedbodyfontsize\c!em\endcsname}%
+ \ifx\emphasizedtypeface\v!slanted
+ #1%
+ \else\ifx\emphasizedtypeface\v!italic
+ #2%
+ \else\ifx\emphasizedtypeface\v!empty
+ \edef\emphasizedtypeface{\csname\??ft\normalizedbodyfontsize\c!em\endcsname}%
+ \ifx\emphasizedtypeface\v!slanted
+ #1%
+ \else\ifx\emphasizedtypeface\v!italic
+ #2%
+ \else
+ \getvalue\emphasizedtypeface
+ \fi\fi
+ \else
+ \getvalue\emphasizedtypeface
+ \fi\fi\fi}
+
+\def\emphasistypeface{\doemphasistypeface\sl\it}
+\def\emphasisboldface{\doemphasistypeface\bs\bi}
+
+%D To be set with the default body font environment: \type
+%D {em} being \type {slanted} or \type {italic}.
+
+\newconditional\emneeded
+
+\newtoks\everyemphasized
+
+\unexpanded\def\em
+ {\relax
+ \ifdim\slantperpoint>\zeropoint
+ \settrue\emneeded
+ \else
+ \setfalse\emneeded
+ \fi
+ \setemphasisboldface % new
+ \ifx\fontalternative\c!it
+ \def\emphasistypeface{\it}\tf
+ \else\ifx\fontalternative\c!sl
+ \def\emphasistypeface{\sl}\tf
+ \else\ifx\fontalternative\c!bf
+ \emphasisboldface
+ \else\ifx\fontalternative\c!bs
+ \def\emphasisboldface{\bs}\bf
+ \else\ifx\fontalternative\c!bi
+ \def\emphasisboldface{\bi}\bf
+ \else
+ \emphasistypeface
+ \fi\fi\fi\fi\fi
+ \the\everyemphasized
+ \ifconditional\emneeded\relax
+ \else
+ \expandafter\aftergroup
+ \fi
+ \emphasiscorrection}
+
+% compare ...
+%
+% \appendtoks \red \to \everyemphasized
+% \setupbodyfontenvironment [default] [em={\italic\color[red]}]
+
+%D The next feature was not present in previous versions. It
+%D takes care of \type {\em \bf ...} sitiations.
+
+\def\setemphasisboldface
+ {\let\savedemphasisboldface\bf
+ \let\setemphasisboldface\relax
+ \unexpanded\def\bf
+ {%\relax
+ \let\bf\relax % new
+ \ifx\fontalternative\c!it
+ \bi
+ \else\ifx\fontalternative\c!sl
+ \bs
+ \else
+ \savedemphasisboldface
+ \fi\fi
+ \let\bf\savedemphasisboldface}}
+
+%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.
+
+\let\italiccorrection=\/ % tex primitive
+
+\def\emphasiscorrection
+ {\ifhmode
+ \expandafter\emphasislook
+ \fi}
+
+\def\emphasislook
+ {\begingroup
+ \futurelet\next\emphasistest}
+
+\def\emphasistest
+ {\ifcat\noexpand\next,% still ok?
+ \expandafter\doemphasiscorrection
+ \else
+ \expandafter\dododoemphasiscorrection
+ \fi}
+
+\def\doemphasiscorrection
+ {\futurelet\next\dodoemphasiscorrection}
+
+\def\dodoemphasiscorrection
+ {\setbox\scratchbox\hbox{\next}%
+ \ifdim\ht\scratchbox=\zeropoint % probably a space
+ \expandafter\dododoemphasiscorrection
+ \else\ifdim\ht\scratchbox<.3ex
+ \expandafter\expandafter\expandafter\endgroup
+ \else
+ \expandafter\expandafter\expandafter\dododoemphasiscorrection
+ \fi\fi}
+
+\def\dododoemphasiscorrection
+ {\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
+%D some punctuation is met. We also show how the mechanism
+%D 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 \startvoorbeeld
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+%D \stopvoorbeeld
+
+%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.
+
+\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
+\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
+\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
+\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
+
+%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
+
+%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:
+
+\def\setfont% geen \dosetfont mogelijk
+ {\def\next{\nextfont\setupinterlinespace}% hm, we need to use \setuplocalinterlinespace
+ \afterassignment\next\font\nextfont=}
+
+%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
+%D struts are set.
+
+%D \macros
+%D {showbodyfont}
+%D
+%D One can call for a rather simple overview of a bodyfont and the
+%D relations between its alternative fonts.
+%D
+%D \showsetup{showbodyfont}
+%D
+%D The current bodyfont (here we omitted the argument) looks like:
+%D
+%D \showbodyfont
+%D
+%D The implementation is rather straightforward in using
+%D \type{\halign}.
+
+\fetchruntimecommand \showbodyfont {\f!fontprefix\s!run.mkiv}
+
+%D \macros
+%D {showfontstrip, testminimalbaseline, showminimalbaseline}
+%D
+%D The next command can come in handy when combining
+%D different fonts into a collection (typeface) and
+%D determining optimal baseline distances.
+%D
+%D \showfontstrip \blank \showminimalbaseline
+
+\fetchruntimecommand \showfontstrip {\f!fontprefix\s!run.mkiv}
+\fetchruntimecommand \testminimalbaseline {\f!fontprefix\s!run.mkiv}
+\fetchruntimecommand \showminimalbaseline {\f!fontprefix\s!run.mkiv}
+
+%D \macros
+%D {showkerning}
+%D
+%D A goody is:
+%D
+%D \showkerning{Can you guess what kerning is?}
+
+\fetchruntimecommand \showkerning {\f!fontprefix\s!run.mkiv}
+
+%D \macros
+%D {showbodyfontenvironment}
+%D
+%D The current bodyfontenvironment is:
+%D
+%D \showbodyfontenvironment
+%D
+%D This overview is generated using:
+%D
+%D \showsetup{showbodyfontenvironment}
+
+\fetchruntimecommand \showbodyfontenvironment {\f!fontprefix\s!run.mkiv}
+
+%D \macros
+%D {showfont,showfontstyle,showligatures}
+%D
+%D The following command generates a fontmap:
+%D
+%D \startbuffer
+%D \showfont[SansBold at 12pt]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+% to be internationalized
+
+\fetchruntimecommand \showfont {\f!fontprefix\s!run.mkiv}
+\fetchruntimecommand \showfontstyle {\f!fontprefix\s!run.mkiv}
+\fetchruntimecommand \showligature {\f!fontprefix\s!run.mkiv}
+\fetchruntimecommand \showligatures {\f!fontprefix\s!run.mkiv}
+\fetchruntimecommand \showcharratio {\f!fontprefix\s!run.mkiv}
+
+%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
+%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.
+
+\def\fontstringA
+ {\ifx\fontstyle\c!rm \s!Serif \else
+ \ifx\fontstyle\c!ss \s!Sans \else
+ \ifx\fontstyle\c!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+\def\fontstringB
+ {\ifx\fontstyle\c!rm \s!Regular \else
+ \ifx\fontstyle\c!ss \s!Support \else
+ \ifx\fontstyle\c!tt \s!Type \else
+ \s!Serif \fi\fi\fi}
+
+\def\fontstringC
+ {\ifx\fontalternative\c!bf \s!Bold \else
+ \ifx\fontalternative\c!sl \s!Slanted \else
+ \ifx\fontalternative\c!it \s!Italic \else
+ \ifx\fontalternative\c!bs \s!BoldSlanted \else
+ \ifx\fontalternative\c!bi \s!BoldItalic \fi\fi\fi\fi\fi}
+
+\def\fontstringD % default fontstyle
+ {\expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!rm \s!Serif \else
+ \expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!ss \s!Sans \else
+ \expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+% potential generalization:
+
+% \letvalue{\??ff:t:\c!rm}\s!Serif
+% \letvalue{\??ff:t:\c!ss}\s!Sans
+% \letvalue{\??ff:t:\c!tt}\s!Mono
+%
+% \letvalue{\??ff:s:\c!bf}\s!Bold
+% \letvalue{\??ff:s:\c!sl}\s!Slanted
+% \letvalue{\??ff:s:\c!it}\s!Italic
+% \letvalue{\??ff:s:\c!bs}\s!BoldSlanted
+% \letvalue{\??ff:s:\c!bi}\s!BoldItalic
+%
+% \letvalue{\??ff:a:\c!rm}\s!Regular
+% \letvalue{\??ff:a:\c!ss}\s!Support
+% \letvalue{\??ff:a:\c!tt}\s!Type
+%
+% \def\fontstringA{\executeifdefined{\??ff:t:\fontstyle}\s!Serif}
+% \def\fontstringB{\executeifdefined{\??ff:a:\fontstyle}\s!Serif}
+% \def\fontstringC{\executeifdefined{\??ff:s:\fontstyle}\empty}
+% \def\fontstringD{\executeifdefined{\??ff:t:\csname\??tf\fontclass\s!default\endcsname}\s!Serif}
+
+\def\glyphfontfile#1%
+ {#1%
+ \ifcsname\??ff#1\fontstringA\fontstringC\endcsname
+ \fontstringA\fontstringC
+ \else\ifcsname\??ff#1\fontstringB\fontstringC\endcsname
+ \fontstringB\fontstringC
+ \else\ifcsname\??ff#1\fontstringA\endcsname
+ \fontstringA
+ \else\ifcsname\??ff#1\fontstringB\endcsname
+ \fontstringB
+ \else\ifcsname\??ff#1\fontstringC\endcsname
+ \fontstringC
+ \fi\fi\fi\fi\fi}
+
+%D The next macro can be used to make decisions based on the shape:
+
+\def\doifitalicelse#1#2%
+ {\ifx\fontalternative\c!sl#1\else
+ \ifx\fontalternative\c!it#1\else
+ \ifx\fontalternative\c!bs#1\else
+ \ifx\fontalternative\c!bi#1\else#2\fi\fi\fi\fi}
+
+%D For an example of usage of the following command,
+%D see \type {cont-log.tex}.
+%D
+%D \starttyping
+%D \def\symbolicfont#1{\definedfont[\glyphfontfile{#1} sa *]}
+%D \stoptyping
+%D
+%D Since we know what scaling it to be applied, we can
+%D implement a much faster alternative:
+
+\let\thedefinedfont\relax
+
+\def\symbolicsizedfont#1#2#3%
+ {\scaledfontsize#1%
+ \scaledfontsize#2\scaledfontsize
+ \font\thedefinedfont=\truefontname{\glyphfontfile{#3}} at \currentfontbodyscale\scaledfontsize\relax
+ \thedefinedfont}
+
+\def\symbolicscaledfont
+ {\symbolicsizedfont\fontbody}
+
+\unexpanded\def\symbolicfont
+ {\symbolicsizedfont\fontbody\plusone}
+
+\unexpanded\def\getglyph#1#2% slow, faster, much faster
+ %{{\definefont[\s!dummy][\glyphfontfile{#1} sa \currentfontscale]\dummy#2}}
+ %{{\definefont[\s!dummy][\glyphfontfile{#1} sa *]\dummy#2}}
+ %{{\symbolicfont{#1}#2}}
+ {{\symbolicfont{#1}\doifnumberelse{#2}\char\donothing#2}}
+
+\unexpanded\def\getscaledglyph#1#2#3%
+ {{\symbolicscaledfont{#1}{#2}\doifnumberelse{#3}\char\donothing#3}}
+
+\unexpanded\def\getrawglyph#1#2% for simple symbols
+ {{\scaledfontsize\fontbody
+ \font\thedefinedfont=#1 at \currentfontbodyscale\scaledfontsize\relax
+ \thedefinedfont\doifnumberelse{#2}\char\donothing#2}}
+
+%D The last implementation of \type {\getglyph} permits
+%D 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
+%D environment.
+
+%D \macros
+%D {ss, SS, sz}
+%D
+%D We are going to redefine \type{\ss} but for those wo still
+%D want to have access to the german \SS, we save it's value in
+%D \type{\SS}. Ok, I should have used \type{\sf} instead of
+%D \type{\ss} in the first place.
+
+\ifx\undefined\SS \let\SS=\ss \fi
+\ifx\undefined\sz \let\sz=\ss \fi
+
+%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
+%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
+
+%D Now we're up to some definitions.
+
+\definebodyfontenvironment
+ [\s!default]
+ [ \s!text=1.0,
+ \s!script=0.7,
+ \s!scriptscript=0.5,
+ \c!a=1.200,
+ \c!b=1.440,
+ \c!c=1.728,
+ \c!d=2.074,
+ *=\currentfontscale, % wildcard
+ \c!x=0.8,
+ \c!xx=0.6,
+ \c!big=1.2,
+ \c!small=0.8,
+ \c!interlinespace=,
+ \c!em=\v!slanted]
+
+\definebodyfontenvironment
+ [20.7pt]
+ [ \s!text=20.7pt,
+ \s!script=\!!fourteenpointfour,
+ \s!scriptscript=\!!twelvepoint,
+ \c!x=17.3pt,
+ \c!xx=\!!fourteenpointfour,
+ \c!big=20.7pt, % !!!!
+ \c!small=17.3pt]
+
+\definebodyfontenvironment
+ [17.3pt]
+ [ \s!text=17.3pt,
+ \s!script=\!!twelvepoint,
+ \s!scriptscript=\!!tenpoint,
+ \c!x=\!!fourteenpointfour,
+ \c!xx=\!!twelvepoint,
+ \c!big=20.7pt,
+ \c!small=\!!fourteenpointfour]
+
+\definebodyfontenvironment
+ [\!!fourteenpointfour]
+ [ \s!text=\!!fourteenpointfour,
+ \s!script=\!!elevenpoint,
+ \s!scriptscript=\!!ninepoint,
+ \c!x=\!!twelvepoint,
+ \c!xx=\!!tenpoint,
+ \c!big=17.3pt,
+ \c!small=\!!twelvepoint]
+
+\definebodyfontenvironment
+ [\!!twelvepoint]
+ [ \s!text=\!!twelvepoint,
+ \s!script=\!!ninepoint,
+ \s!scriptscript=\!!sevenpoint,
+ \c!x=\!!tenpoint,
+ \c!xx=\!!eightpoint,
+ \c!big=\!!fourteenpointfour,
+ \c!small=\!!tenpoint]
+
+\definebodyfontenvironment
+ [\!!elevenpoint]
+ [ \s!text=\!!elevenpoint,
+ \s!script=\!!eightpoint,
+ \s!scriptscript=\!!sixpoint,
+ \c!x=\!!ninepoint,
+ \c!xx=\!!sevenpoint,
+ \c!big=\!!twelvepoint,
+ \c!small=\!!ninepoint]
+
+\definebodyfontenvironment
+ [\!!tenpoint]
+ [ \s!text=\!!tenpoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!eightpoint,
+ \c!xx=\!!sixpoint,
+ \c!big=\!!twelvepoint,
+ \c!small=\!!eightpoint]
+
+\definebodyfontenvironment
+ [\!!ninepoint]
+ [ \s!text=\!!ninepoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!sevenpoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!elevenpoint,
+ \c!small=\!!sevenpoint]
+
+\definebodyfontenvironment
+ [\!!eightpoint]
+ [ \s!text=\!!eightpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!sixpoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!tenpoint,
+ \c!small=\!!sixpoint]
+
+\definebodyfontenvironment
+ [\!!sevenpoint]
+ [ \s!text=\!!sevenpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!sixpoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!ninepoint,
+ \c!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!sixpoint]
+ [ \s!text=\!!sixpoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!fivepoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!eightpoint,
+ \c!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fivepoint]
+ [ \s!text=\!!fivepoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \c!x=\!!fivepoint,
+ \c!xx=\!!fivepoint,
+ \c!big=\!!sevenpoint,
+ \c!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fourpoint]
+ [ \s!text=\!!fourpoint,
+ \s!script=\!!fourpoint,
+ \s!scriptscript=\!!fourpoint,
+ \c!x=\!!fourpoint,
+ \c!xx=\!!fourpoint,
+ \c!big=\!!sixpoint,
+ \c!small=\!!fourpoint]
+
+\definebodyfontswitch [fourteenpointfour] [\!!fourteenpointfour]
+\definebodyfontswitch [twelvepoint] [\!!twelvepoint]
+\definebodyfontswitch [elevenpoint] [\!!elevenpoint]
+\definebodyfontswitch [tenpoint] [\!!tenpoint]
+\definebodyfontswitch [ninepoint] [\!!ninepoint]
+\definebodyfontswitch [eightpoint] [\!!eightpoint]
+\definebodyfontswitch [sevenpoint] [\!!sevenpoint]
+\definebodyfontswitch [sixpoint] [\!!sixpoint]
+\definebodyfontswitch [fivepoint] [\!!fivepoint]
+\definebodyfontswitch [fourpoint] [\!!fourpoint]
+
+% \definebodyfontswitch [xii] [\!!twelvepoint]
+% \definebodyfontswitch [xi] [\!!elevenpoint]
+% \definebodyfontswitch [x] [\!!tenpoint]
+% \definebodyfontswitch [ix] [\!!ninepoint]
+% \definebodyfontswitch [viii] [\!!eightpoint]
+% \definebodyfontswitch [vii] [\!!sevenpoint]
+% \definebodyfontswitch [vi] [\!!sixpoint]
+
+%D So far.
+
+\definefontstyle [\c!mm] [\c!mm]
+\definefontstyle [\c!rm,\v!roman,\v!serif,\v!regular] [\c!rm]
+\definefontstyle [\c!ss,\v!sansserif,\v!sans,\v!support] [\c!ss]
+\definefontstyle [\c!tt,\v!teletype,\v!type,\v!mono] [\c!tt]
+\definefontstyle [\c!hw,\v!handwritten] [\c!hw]
+\definefontstyle [\c!cg,\v!calligraphic] [\c!cg]
+
+\definefontalternative[\c!tf]
+\definefontalternative[\c!bf]
+\definefontalternative[\c!it]
+\definefontalternative[\c!sl]
+\definefontalternative[\c!bs]
+\definefontalternative[\c!bi]
+\definefontalternative[\c!sc]
+
+\definefontsize[\c!a] \definefontsize[\c!b]
+\definefontsize[\c!c] \definefontsize[\c!d]
+
+\definealternativestyle [\v!mediaeval] [\os] []
+\definealternativestyle [\v!normal] [\tf] []
+\definealternativestyle [\v!bold] [\bf] []
+\definealternativestyle [\v!type] [\tt] []
+\definealternativestyle [\v!mono] [\tt] []
+\definealternativestyle [\v!slanted] [\sl] []
+\definealternativestyle [\v!italic] [\it] []
+\definealternativestyle [\v!boldslanted,\v!slantedbold] [\bs] []
+\definealternativestyle [\v!bolditalic,\v!italicbold] [\bi] []
+\definealternativestyle [\v!small,\v!smallnormal] [\tfx] []
+\definealternativestyle [\v!smallbold] [\bfx] []
+\definealternativestyle [\v!smalltype] [\ttx] []
+\definealternativestyle [\v!smallslanted] [\slx] []
+\definealternativestyle [\v!smallboldslanted,\v!smallslantedbold] [\bsx] []
+\definealternativestyle [\v!smallbolditalic,\v!smallitalicbold] [\bix] []
+
+\definealternativestyle [\v!sans,\v!sansserif] [\ss] []
+\definealternativestyle [\v!sansbold] [\ss\bf] []
+
+%D Slow but handy:
+
+\definealternativestyle [\v!smallbodyfont] [\setsmallbodyfont] []
+\definealternativestyle [\v!bigbodyfont] [\setbigbodyfont] []
+
+%D We treat {\sc Small Caps} and \cap {Pseudo Caps} a bit
+%D different. We also provide an \WORD {uppercase} style.
+
+\definealternativestyle [\v!cap,\v!capital] [\smallcapped] [\smallcapped]
+\definealternativestyle [\v!smallcaps] [\sc] [\sc]
+\definealternativestyle [\v!WORD] [\WORD] [\WORD]
+
+%D \macros
+%D {fontstylesuffix}
+%D
+%D The next macro is used to map non latin fontnames on
+%D fonts. See \type {font-uni} for an example of its use.
+
+\def\fontstylesuffix% why the \s!Regular ? see \getglyph
+ {\ifx\fontalternative\c!tf \s!Regular \else
+ \ifx\fontalternative\c!bf \s!Bold \else
+ \ifx\fontalternative\c!sl \s!Slanted \else
+ \ifx\fontalternative\c!it \s!Italic \else
+ \ifx\fontalternative\c!bs \s!BoldSlanted \else
+ \ifx\fontalternative\c!bi \s!BoldItalic \else
+ \ifx\fontalternative\c!sc \s!Caps \else
+ \s!Regular \fi\fi\fi\fi\fi\fi\fi}%
+
+%D \macros
+%D {definefontvariant,fontvariant,variant}
+%D
+%D This command is obsolete in \MKIV\ as we have features. It might
+%D come back using the local features handlers.
+
+\unexpanded\def\definefontvariant{\dotripleargument\dodefinefontvariant}
+
+\def\dodefinefontvariant[#1][#2][#3]{}
+\def\variant [#1]{}
+
+\ifdefined\Var\else \let\Var\variant \fi
+
+%D By default we load the Computer Modern Roman fonts (but
+%D not yet at this moment) and activate the 12pt roman
+%D bodyfont. Sans serif and teletype are also available and
+%D can be called for by \type{\ss} and \type{\tt}. Loading
+%D takes place elsewhere.
+%D
+%D For tracing purposes we define:
+
+\definefont[tinyfont][Mono at 1ex]
+
+% \tracinglostchars=1
+
+% this needs some interfacing
+%
+% \setupfonts[check=...]
+
+\def\checkcharactersinfont {\ctxlua{fonts.checkers.enable()}}
+\def\removemissingcharacters{\ctxlua{fonts.checkers.enable(true)}}
+
+%D New commands (not yet interfaced):
+
+\def\style[#1]% for inline usage, like \color
+ {\groupedcommand{\ifcsname#1\endcsname\csname#1\endcsname\else\definedfont[#1]\fi}{}}
+
+\unexpanded\def\startstyle[#1]%
+ {\begingroup
+ \ifcsname#1\endcsname\csname#1\endcsname\else\definedfont[#1]\fi}
+
+\unexpanded\def\stopstyle
+ {\endgroup}
+
+%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}}
+
+\unexpanded\def\definestylecollection
+ {\dosingleargument\dodefinestylecollection}
+
+\def\dodefinestylecollection[#1]%
+ {\iffirstargument
+ \setuvalue{#1}{\styleinstance[#1]}%
+ \def\docommand##1%
+ {\def\dodocommand####1{\letbeundefined{\??sx##1:####1:\commalistelement}}%
+ \processcommacommand[\fontalternativelist,\s!default]\dodocommand}%
+ \processcommacommand[\fontstylelist,\s!default]\docommand
+ \fi}
+
+\unexpanded\def\definestyleinstance
+ {\doquadrupleargument\dodefinestyleinstance}
+
+\def\dodefinestyleinstance[#1][#2][#3][#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever]
+ {\iffirstargument
+ \ifcsname#1\endcsname\else\definestylecollection[#1]\fi
+ \fi
+ \iffourthargument
+ \setvalue{\??sx#1:#2:#3}{#4}%
+ \else\ifthirdargument
+ \setvalue{\??sx#1::#2}{#3}%
+ \else\ifsecondargument
+ \letvalue{\??sx#1::#2}\empty
+ \fi\fi\fi}
+
+\unexpanded\def\styleinstance[#1]% will be made faster
+ {%\begingroup\normalexpanded{\noexpand\infofont[#1:\fontstyle:\fontalternative]}\endgroup
+ \executeifdefined{\??sx#1:\fontstyle:\fontalternative}%
+ {\executeifdefined{\??sx#1:\fontstyle:\s!default}%
+ {\executeifdefined{\??sx#1::\fontalternative}
+ {\getvalue {\??sx#1::\s!default}}}}}
+
+% \unexpanded\def\styleinstance[#1]%
+% {\csname\??sx#1%
+% \ifcsname:\fontstyle:\fontalternative\endcsname
+% :\fontstyle:\fontalternative
+% \else\ifcsname:\fontstyle:\s!default\endcsname
+% :\fontstyle:\s!default
+% \else\ifcsname::\fontalternative\endcsname
+% ::\fontalternative
+% \else\ifcsname::\s!default\endcsname
+% ::\s!default
+% \else
+% % nothing, \relax
+% \fi\fi\fi\fi
+% \endcsname}
+
+%D goodies:
+
+\def\showchardata#1{\ctxlua{fonts.show_char_data("#1")}}
+\def\showfontdata {\ctxlua{fonts.show_font_parameters()}}
+
+%D some low level helpers
+%D
+%D \starttyping
+%D \def\TestLookup#1%
+%D {\dolookupfontbyspec{#1}
+%D pattern: #1, found: \dolookupnoffound
+%D \blank
+%D \dorecurse {\dolookupnoffound} {%
+%D \recurselevel:~\dolookupgetkeyofindex{fontname}{\recurselevel}\quad
+%D }%
+%D \blank}
+%D
+%D \TestLookup{familyname=helveticaneue}
+%D \TestLookup{familyname=helveticaneue,weight=bold}
+%D \TestLookup{familyname=helveticaneue,weight=bold,style=italic}
+%D \stoptyping
+
+% we can also move the lookups to the fonts.namespace (of commands)
+
+\def\dolookupfontbyspec #1{\ctxlua{fonts.names.lookup("#1")}}
+\def\dolookupnoffound {\ctxlua{tex.write(fonts.names.noflookups())}}
+\def\dolookupgetkeyofindex#1#2{\ctxlua{tex.write(fonts.names.getlookupkey("#1",#2))}}
+\def\dolookupgetkey #1{\ctxlua{tex.write(fonts.names.getlookupkey("#1"))}}
+\def\cleanfontname #1{\ctxlua{fonts.cleanname("#1")}}
+
+\protect \endinput
+
+% \startluacode
+% function commands.doifelsecurrentfonthasfeature(name)
+% local f = fonts.ids[font.current()]
+% f = f and f.shared
+% f = f and f.otfdata
+% f = f and f.luatex
+% f = f and f.features
+% commands.doifelse(f and (f.gpos[name] or f.gsub[name]))
+% end
+% \stopluacode
+
+% \def\doifelsecurrentfonthasfeature#1%
+% {\ctxlua{commands.doifelsecurrentfonthasfeature("#1")}}
+
+% \doifelsecurrentfonthasfeature{smcp}{YES}{NO}
+% \doifelsecurrentfonthasfeature{crap}{YES}{NO}
+% \doifelsecurrentfonthasfeature{kern}{YES}{NO}
diff --git a/tex/context/base/font-jap.mkii b/tex/context/base/font-jap.mkii
new file mode 100644
index 000000000..42480df43
--- /dev/null
+++ b/tex/context/base/font-jap.mkii
@@ -0,0 +1,83 @@
+%D \module
+%D [ file=font-jap,
+%D version=2006.01.13,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Japanese,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D suggestions=Wang Lei,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifx\handlejapaneseunicodeglyph\undefined \else \endinput \fi
+\ifx\handlechineseunicodeglyph \undefined \input font-chi.tex \fi
+
+\writestatus{loading}{ConTeXt Font Macros / Japanese}
+
+\unprotect
+
+\newif\iftracejapanese
+
+\let\japaneseencoding\empty
+
+\def\setjapaneseencoding
+ {\getfontfileparameters\unicodestyle
+ \ifx\currentfontfileencoding\undefined \else
+ \let\japaneseencoding\currentfontfileencoding
+ \fi}
+
+\def\japaneseunicodescale {\chineseunicodescale }
+\def\japaneseunicodeheight {\chineseunicodeheight }
+\def\japaneseunicodedepth {\chineseunicodedepth }
+\def\japaneseinterglyphskip{\chineseinterglyphskip}
+\def\japanesesurroundskip {\chinesesurroundskip }
+
+\setupunicodefont
+ [japanese]
+ [ \c!scale=\japaneseunicodescale,
+ \c!height=\japaneseunicodeheight,
+ \c!depth=\japaneseunicodedepth,
+ \c!strut=\v!yes,
+ \c!interlinespace=\v!yes,
+ \c!conversion=\japanesenumber,
+ \c!commands=\setjapaneseencoding, % needed for digits
+ \c!command=\handlejapaneseunicodeglyph]
+
+\def\japanesenumber{\numbers}
+
+\def\handlejapaneseunicodeglyph
+ {\begingroup
+% \let\chineseunicodescale \japaneseunicodescale
+% \let\chineseunicodeheight \japaneseunicodeheight
+% \let\chineseunicodedepth \japaneseunicodedepth
+% \let\chineseinterglyphskip\japaneseinterglyphskip
+% \let\chinesesurroundskip \japanesesurroundskip
+ \iftracejapanese\tracechinesetrue\else\tracechinesefalse\fi
+ \handlechineseunicodeglyph
+ \endgroup}
+
+\doifelse \currentregime {utf} {
+
+ % todo: typescripts
+
+ \definefontsynonym [JapaneseRegular] [uni-cybercjk-][encoding=cjk-uni]
+ \definefontsynonym [JapaneseSlanted] [uni-cybercjk-][encoding=cjk-uni]
+ \definefontsynonym [JapaneseItalic] [uni-cybercjk-][encoding=cjk-uni]
+ \definefontsynonym [JapaneseBold] [uni-cybercjk-][encoding=cjk-uni]
+ \definefontsynonym [JapaneseBoldSlanted][uni-cybercjk-][encoding=cjk-uni]
+ \definefontsynonym [JapaneseBoldItalic] [uni-cybercjk-][encoding=cjk-uni]
+
+ \loadmapfile[uni-cybercjk.map]
+
+ \defineunicodefont [Japanese] [Japanese] [japanese]
+
+} {
+ \writestatus{Japanese}{No fonts defined}
+}
+
+\Japanese
+
+\protect \endinput
diff --git a/tex/context/base/font-log.lua b/tex/context/base/font-log.lua
new file mode 100644
index 000000000..97cb4ff7c
--- /dev/null
+++ b/tex/context/base/font-log.lua
@@ -0,0 +1,58 @@
+if not modules then modules = { } end modules ['font-log'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, format, lower, concat = next, string.format, string.lower, table.concat
+
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+fonts.logger = fonts.logger or { }
+
+--[[ldx--
+
The following functions are used for reporting about the fonts
+used. The message itself is not that useful in regular runs but since
+we now have several readers it may be handy to know what reader is
+used for which font.
+--ldx]]--
+
+function fonts.logger.save(tfmtable,source,specification) -- save file name in spec here ! ! ! ! ! !
+ if tfmtable and specification and specification.specification then
+ local name = lower(specification.name)
+ if trace_defining and not fonts.used[name] then
+ logs.report("define font","registering %s as %s (used: %s)",file.basename(specification.name),source,file.basename(specification.filename))
+ end
+ specification.source = source
+ fonts.loaded[lower(specification.specification)] = specification
+ -- fonts.used[name] = source
+ fonts.used[lower(specification.filename or specification.name)] = source
+ end
+end
+
+function fonts.logger.report(complete)
+ local t = { }
+ for name, used in table.sortedhash(fonts.used) do
+ if complete then
+ t[#t+1] = used .. "->" .. file.basename(name)
+ else
+ t[#t+1] = file.basename(name)
+ end
+ end
+ return t
+end
+
+function fonts.logger.format(name)
+ return fonts.used[name] or "unknown"
+end
+
+statistics.register("loaded fonts", function()
+ if next(fonts.used) then
+ local t = fonts.logger.report()
+ return (#t > 0 and format("%s files: %s",#t,concat(t,separator or " "))) or "none"
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua
new file mode 100644
index 000000000..299508764
--- /dev/null
+++ b/tex/context/base/font-map.lua
@@ -0,0 +1,370 @@
+if not modules then modules = { } end modules ['font-map'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower
+local lpegmatch = lpeg.match
+local utfbyte = utf.byte
+
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+local trace_unimapping = false trackers.register("otf.unimapping", function(v) trace_unimapping = v end)
+
+local ctxcatcodes = tex and tex.ctxcatcodes
+
+--[[ldx--
+
Eventually this code will disappear because map files are kind
+of obsolete. Some code may move to runtime or auxiliary modules.
+
The name to unciode related code will stay of course.
+--ldx]]--
+
+fonts = fonts or { }
+fonts.map = fonts.map or { }
+
+local function load_lum_table(filename) -- will move to font goodies
+ local lumname = file.replacesuffix(file.basename(filename),"lum")
+ local lumfile = resolvers.find_file(lumname,"map") or ""
+ if lumfile ~= "" and lfs.isfile(lumfile) then
+ if trace_loading or trace_unimapping then
+ logs.report("load otf","enhance: loading %s ",lumfile)
+ end
+ lumunic = dofile(lumfile)
+ return lumunic, lumfile
+ end
+end
+
+local hex = lpeg.R("AF","09")
+local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
+local hexsix = (hex^1) / function(s) return tonumber(s,16) end
+local dec = (lpeg.R("09")^1) / tonumber
+local period = lpeg.P(".")
+
+local unicode = lpeg.P("uni") * (hexfour * (period + lpeg.P(-1)) * lpeg.Cc(false) + lpeg.Ct(hexfour^1) * lpeg.Cc(true))
+local ucode = lpeg.P("u") * (hexsix * (period + lpeg.P(-1)) * lpeg.Cc(false) + lpeg.Ct(hexsix ^1) * lpeg.Cc(true))
+local index = lpeg.P("index") * dec * lpeg.Cc(false)
+
+local parser = unicode + ucode + index
+
+local parsers = { }
+
+local function make_name_parser(str)
+ if not str or str == "" then
+ return parser
+ else
+ local p = parsers[str]
+ if not p then
+ p = lpeg.P(str) * period * dec * lpeg.Cc(false)
+ parsers[str] = p
+ end
+ return p
+ end
+end
+
+--~ local parser = fonts.map.make_name_parser("Japan1")
+--~ local parser = fonts.map.make_name_parser()
+--~ local function test(str)
+--~ local b, a = lpegmatch(parser,str)
+--~ print((a and table.serialize(b)) or b)
+--~ end
+--~ test("a.sc")
+--~ test("a")
+--~ test("uni1234")
+--~ test("uni1234.xx")
+--~ test("uni12349876")
+--~ test("index1234")
+--~ test("Japan1.123")
+
+local function tounicode16(unicode)
+ if unicode < 0x10000 then
+ return format("%04X",unicode)
+ else
+ return format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00)
+ end
+end
+
+local function tounicode16sequence(unicodes)
+ local t = { }
+ for l=1,#unicodes do
+ local unicode = unicodes[l]
+ if unicode < 0x10000 then
+ t[l] = format("%04X",unicode)
+ else
+ t[l] = format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00)
+ end
+ end
+ return concat(t)
+end
+
+--~ This is quite a bit faster but at the cost of some memory but if we
+--~ do this we will also use it elsewhere so let's not follow this route
+--~ now. I might use this method in the plain variant (no caching there)
+--~ but then I need a flag that distinguishes between code branches.
+--~
+--~ local cache = { }
+--~
+--~ function fonts.map.tounicode16(unicode)
+--~ local s = cache[unicode]
+--~ if not s then
+--~ if unicode < 0x10000 then
+--~ s = format("%04X",unicode)
+--~ else
+--~ s = format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00)
+--~ end
+--~ cache[unicode] = s
+--~ end
+--~ return s
+--~ end
+
+fonts.map.load_lum_table = load_lum_table
+fonts.map.make_name_parser = make_name_parser
+fonts.map.tounicode16 = tounicode16
+fonts.map.tounicode16sequence = tounicode16sequence
+
+local separator = lpeg.S("_.")
+local other = lpeg.C((1 - separator)^1)
+local ligsplitter = lpeg.Ct(other * (separator * other)^0)
+
+--~ print(table.serialize(lpegmatch(ligsplitter,"this")))
+--~ print(table.serialize(lpegmatch(ligsplitter,"this.that")))
+--~ print(table.serialize(lpegmatch(ligsplitter,"japan1.123")))
+--~ print(table.serialize(lpegmatch(ligsplitter,"such_so_more")))
+--~ print(table.serialize(lpegmatch(ligsplitter,"such_so_more.that")))
+
+fonts.map.add_to_unicode = function(data,filename)
+ local unicodes = data.luatex and data.luatex.unicodes
+ if not unicodes then
+ return
+ end
+ -- we need to move this code
+ unicodes['space'] = unicodes['space'] or 32
+ unicodes['hyphen'] = unicodes['hyphen'] or 45
+ unicodes['zwj'] = unicodes['zwj'] or 0x200D
+ unicodes['zwnj'] = unicodes['zwnj'] or 0x200C
+ -- the tounicode mapping is sparse and only needed for alternatives
+ local tounicode, originals, ns, nl, private, unknown = { }, { }, 0, 0, fonts.private, format("%04X",utfbyte("?"))
+ data.luatex.tounicode, data.luatex.originals = tounicode, originals
+ local lumunic, uparser, oparser
+ if false then -- will become an option
+ lumunic = load_lum_table(filename)
+ lumunic = lumunic and lumunic.tounicode
+ end
+ local cidinfo, cidnames, cidcodes = data.cidinfo
+ local usedmap = cidinfo and cidinfo.usedname
+ usedmap = usedmap and lower(usedmap)
+ usedmap = usedmap and fonts.cid.map[usedmap]
+ if usedmap then
+ oparser = usedmap and make_name_parser(cidinfo.ordering)
+ cidnames = usedmap.names
+ cidcodes = usedmap.unicodes
+ end
+ uparser = make_name_parser()
+ local aglmap = fonts.map and fonts.map.agl_to_unicode
+ for index, glyph in next, data.glyphs do
+ local name, unic = glyph.name, glyph.unicode or -1 -- play safe
+ if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
+ local unicode = (lumunic and lumunic[name]) or (aglmap and aglmap[name])
+ if unicode then
+ originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ end
+ -- cidmap heuristics, beware, there is no guarantee for a match unless
+ -- the chain resolves
+ if (not unicode) and usedmap then
+ local foundindex = lpegmatch(oparser,name)
+ if foundindex then
+ unicode = cidcodes[foundindex] -- name to number
+ if unicode then
+ originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ else
+ local reference = cidnames[foundindex] -- number to name
+ if reference then
+ local foundindex = lpegmatch(oparser,reference)
+ if foundindex then
+ unicode = cidcodes[foundindex]
+ if unicode then
+ originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ end
+ end
+ if not unicode then
+ local foundcodes, multiple = lpegmatch(uparser,reference)
+ if foundcodes then
+ if multiple then
+ originals[index], tounicode[index], nl, unicode = foundcodes, tounicode16sequence(foundcodes), nl + 1, true
+ else
+ originals[index], tounicode[index], ns, unicode = foundcodes, tounicode16(foundcodes), ns + 1, foundcodes
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ -- a.whatever or a_b_c.whatever or a_b_c (no numbers)
+ if not unicode then
+ local split = lpegmatch(ligsplitter,name)
+ local nplit = (split and #split) or 0
+ if nplit == 0 then
+ -- skip
+ elseif nplit == 1 then
+ local base = split[1]
+ unicode = unicodes[base] or (aglmap and aglmap[base])
+ if unicode then
+ if type(unicode) == "table" then
+ unicode = unicode[1]
+ end
+ originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ end
+ else
+ local t = { }
+ for l=1,nplit do
+ local base = split[l]
+ local u = unicodes[base] or (aglmap and aglmap[base])
+ if not u then
+ break
+ elseif type(u) == "table" then
+ t[#t+1] = u[1]
+ else
+ t[#t+1] = u
+ end
+ end
+ if #t > 0 then -- done then
+ originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
+ end
+ end
+ end
+ -- last resort
+ if not unicode then
+ local foundcodes, multiple = lpegmatch(uparser,name)
+ if foundcodes then
+ if multiple then
+ originals[index], tounicode[index], nl, unicode = foundcodes, tounicode16sequence(foundcodes), nl + 1, true
+ else
+ originals[index], tounicode[index], ns, unicode = foundcodes, tounicode16(foundcodes), ns + 1, foundcodes
+ end
+ end
+ end
+ if not unicode then
+ originals[index], tounicode[index] = 0xFFFD, "FFFD"
+ end
+ end
+ end
+ if trace_unimapping then
+ for index, glyph in table.sortedhash(data.glyphs) do
+ local toun, name, unic = tounicode[index], glyph.name, glyph.unicode or -1 -- play safe
+ if toun then
+ logs.report("load otf","internal: 0x%05X, name: %s, unicode: 0x%05X, tounicode: %s",index,name,unic,toun)
+ else
+ logs.report("load otf","internal: 0x%05X, name: %s, unicode: 0x%05X",index,name,unic)
+ end
+ end
+ end
+ if trace_loading and (ns > 0 or nl > 0) then
+ logs.report("load otf","enhance: %s tounicode entries added (%s ligatures)",nl+ns, ns)
+ end
+end
+
+-- the following is sort of obsolete
+--
+-- fonts.map.data = fonts.map.data or { }
+-- fonts.map.encodings = fonts.map.encodings or { }
+-- fonts.map.loaded = fonts.map.loaded or { }
+-- fonts.map.line = fonts.map.line or { }
+--
+-- function fonts.map.line.pdftex(e)
+-- if e.name and e.fontfile then
+-- local fullname = e.fullname or ""
+-- if e.slant and e.slant ~= 0 then
+-- if e.encoding then
+-- pdf.mapline(format('= %s %s "%g SlantFont" <%s <%s',e.name,fullname,e.slant,e.encoding,e.fontfile)))
+-- else
+-- pdf.mapline(format('= %s %s "%g SlantFont" <%s',e.name,fullname,e.slant,e.fontfile)))
+-- end
+-- elseif e.extend and e.extend ~= 1 and e.extend ~= 0 then
+-- if e.encoding then
+-- pdf.mapline(format('= %s %s "%g ExtendFont" <%s <%s',e.name,fullname,e.extend,e.encoding,e.fontfile)))
+-- else
+-- pdf.mapline(format('= %s %s "%g ExtendFont" <%s',e.name,fullname,e.extend,e.fontfile)))
+-- end
+-- else
+-- if e.encoding then
+-- pdf.mapline(format('= %s %s <%s <%s',e.name,fullname,e.encoding,e.fontfile)))
+-- else
+-- pdf.mapline(format('= %s %s <%s',e.name,fullname,e.fontfile)))
+-- end
+-- end
+-- else
+-- return nil
+-- end
+-- end
+--
+-- function fonts.map.flush(backend) -- will also erase the accumulated data
+-- local flushline = fonts.map.line[backend or "pdftex"] or fonts.map.line.pdftex
+-- for _, e in next, fonts.map.data do
+-- flushline(e)
+-- end
+-- fonts.map.data = { }
+-- end
+--
+-- fonts.map.line.dvips = fonts.map.line.pdftex
+-- fonts.map.line.dvipdfmx = function() end
+--
+-- function fonts.map.convert_entries(filename)
+-- if not fonts.map.loaded[filename] then
+-- fonts.map.data, fonts.map.encodings = fonts.map.load_file(filename,fonts.map.data, fonts.map.encodings)
+-- fonts.map.loaded[filename] = true
+-- end
+-- end
+--
+-- function fonts.map.load_file(filename, entries, encodings)
+-- entries = entries or { }
+-- encodings = encodings or { }
+-- local f = io.open(filename)
+-- if f then
+-- local data = f:read("*a")
+-- if data then
+-- for line in gmatch(data,"(.-)[\n\t]") do
+-- if find(line,"^[%#%%%s]") then
+-- -- print(line)
+-- else
+-- local extend, slant, name, fullname, fontfile, encoding
+-- line = gsub(line,'"(.+)"', function(s)
+-- extend = find(s,'"([^"]+) ExtendFont"')
+-- slant = find(s,'"([^"]+) SlantFont"')
+-- return ""
+-- end)
+-- if not name then
+-- -- name fullname encoding fontfile
+-- name, fullname, encoding, fontfile = match(line,"^(%S+)%s+(%S*)[%s<]+(%S*)[%s<]+(%S*)%s*$")
+-- end
+-- if not name then
+-- -- name fullname (flag) fontfile encoding
+-- name, fullname, fontfile, encoding = match(line,"^(%S+)%s+(%S*)[%d%s<]+(%S*)[%s<]+(%S*)%s*$")
+-- end
+-- if not name then
+-- -- name fontfile
+-- name, fontfile = match(line,"^(%S+)%s+[%d%s<]+(%S*)%s*$")
+-- end
+-- if name then
+-- if encoding == "" then encoding = nil end
+-- entries[name] = {
+-- name = name, -- handy
+-- fullname = fullname,
+-- encoding = encoding,
+-- fontfile = fontfile,
+-- slant = tonumber(slant),
+-- extend = tonumber(extend)
+-- }
+-- encodings[name] = encoding
+-- elseif line ~= "" then
+-- -- print(line)
+-- end
+-- end
+-- end
+-- end
+-- f:close()
+-- end
+-- return entries, encodings
+-- end
diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua
new file mode 100644
index 000000000..80a56332a
--- /dev/null
+++ b/tex/context/base/font-mis.lua
@@ -0,0 +1,101 @@
+if not modules then modules = { } end modules ['font-mis'] = {
+ version = 1.001,
+ comment = "companion to luatex-fonts.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+local lower, strip = string.lower, string.strip
+
+fonts.otf = fonts.otf or { }
+
+fonts.otf.version = fonts.otf.version or 2.650
+fonts.otf.pack = true
+fonts.otf.cache = containers.define("fonts", "otf", fonts.otf.version, true)
+
+function fonts.otf.loadcached(filename,format,sub)
+ -- no recache when version mismatch
+ local name = file.basename(file.removesuffix(filename))
+ if sub == "" then sub = false end
+ local hash = name
+ if sub then
+ hash = hash .. "-" .. sub
+ end
+ hash = containers.cleanname(hash)
+ local data = containers.read(fonts.otf.cache(), hash)
+ if data and not data.verbose then
+ fonts.otf.enhancers.unpack(data)
+ return data
+ else
+ return nil
+ end
+end
+
+local featuregroups = { "gsub", "gpos" }
+
+function fonts.get_features(name,t,script,language)
+ local t = lower(t or (name and file.extname(name)) or "")
+ if t == "otf" or t == "ttf" or t == "ttc" or t == "dfont" then
+ local filename = resolvers.find_file(name,t) or ""
+ if filename ~= "" then
+ local data = fonts.otf.loadcached(filename)
+ if data and data.luatex and data.luatex.features then
+ return data.luatex.features
+ else
+ local ff = fontloader.open(filename)
+ if ff then
+ local data = fontloader.to_table(ff)
+ fontloader.close(ff)
+ local features = { }
+ for k=1,#featuregroups do
+ local what = featuregroups[k]
+ local dw = data[what]
+ if dw then
+ local f = { }
+ features[what] = f
+ for i=1,#dw do
+ local d = dw[i]
+ local dfeatures = d.features
+ if dfeatures then
+ for i=1,#dfeatures do
+ local df = dfeatures[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag] if not ft then ft = {} f[tag] = ft end
+ local dfscripts = df.scripts
+ for i=1,#dfscripts do
+ local ds = dfscripts[i]
+ local scri = strip(lower(ds.script))
+ local fts = ft[scri] if not fts then fts = {} ft[scri] = fts end
+ local dslangs = ds.langs
+ for i=1,#dslangs do
+ local lang = dslangs[i]
+ lang = strip(lower(lang))
+ if scri == script then
+ if lang == language then
+ fts[lang] = 'sl'
+ else
+ fts[lang] = 's'
+ end
+ else
+ if lang == language then
+ fts[lang] = 'l'
+ else
+ fts[lang] = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ return features
+ end
+ end
+ end
+ end
+ return nil, nil
+end
diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua
new file mode 100644
index 000000000..0b61e17d1
--- /dev/null
+++ b/tex/context/base/font-ota.lua
@@ -0,0 +1,286 @@
+if not modules then modules = { } end modules ['font-ota'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (analysing)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this might become scrp-*.lua
+
+local type, tostring, match, format, concat = type, tostring, string.match, string.format, table.concat
+
+if not trackers then trackers = { register = function() end } end
+
+local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
+local trace_cjk = false trackers.register("cjk.injections", function(v) trace_cjk = v end)
+
+trackers.register("cjk.analyzing","otf.analyzing")
+
+fonts = fonts or { }
+fonts.analyzers = fonts.analyzers or { }
+fonts.analyzers.initializers = fonts.analyzers.initializers or { node = { otf = { } } }
+fonts.analyzers.methods = fonts.analyzers.methods or { node = { otf = { } } }
+
+local otf = fonts.otf
+local tfm = fonts.tfm
+
+local initializers = fonts.analyzers.initializers
+local methods = fonts.analyzers.methods
+
+local glyph = node.id('glyph')
+local glue = node.id('glue')
+local penalty = node.id('penalty')
+
+local set_attribute = node.set_attribute
+local has_attribute = node.has_attribute
+local traverse_id = node.traverse_id
+local traverse_node_list = node.traverse
+
+local fontdata = fonts.ids
+local state = attributes.private('state')
+
+local fcs = (fonts.color and fonts.color.set) or function() end
+local fcr = (fonts.color and fonts.color.reset) or function() end
+
+local a_to_script = otf.a_to_script
+local a_to_language = otf.a_to_language
+
+-- in the future we will use language/script attributes instead of the
+-- font related value, but then we also need dynamic features which is
+-- somewhat slower; and .. we need a chain of them
+
+function fonts.initializers.node.otf.analyze(tfmdata,value,attr)
+ if attr and attr > 0 then
+ script, language = a_to_script[attr], a_to_language[attr]
+ else
+ script, language = tfmdata.script, tfmdata.language
+ end
+ local action = initializers[script]
+ if action then
+ if type(action) == "function" then
+ return action(tfmdata,value)
+ else
+ local action = action[language]
+ if action then
+ return action(tfmdata,value)
+ end
+ end
+ end
+ return nil
+end
+
+function fonts.methods.node.otf.analyze(head,font,attr)
+ local tfmdata = fontdata[font]
+ local script, language
+ if attr and attr > 0 then
+ script, language = a_to_script[attr], a_to_language[attr]
+ else
+ script, language = tfmdata.script, tfmdata.language
+ end
+ local action = methods[script]
+ if action then
+ if type(action) == "function" then
+ return action(head,font,attr)
+ else
+ action = action[language]
+ if action then
+ return action(head,font,attr)
+ end
+ end
+ end
+ return head, false
+end
+
+otf.features.register("analyze",true) -- we always analyze
+table.insert(fonts.triggers,"analyze") -- we need a proper function for doing this
+
+-- latin
+
+fonts.analyzers.methods.latn = fonts.analyzers.aux.setstate
+
+-- this info eventually will go into char-def
+
+local zwnj = 0x200C
+local zwj = 0x200D
+
+local isol = {
+ [0x0600] = true, [0x0601] = true, [0x0602] = true, [0x0603] = true,
+ [0x0608] = true, [0x060B] = true, [0x0621] = true, [0x0674] = true,
+ [0x06DD] = true, [zwnj] = true,
+}
+
+local isol_fina = {
+ [0x0622] = true, [0x0623] = true, [0x0624] = true, [0x0625] = true,
+ [0x0627] = true, [0x0629] = true, [0x062F] = true, [0x0630] = true,
+ [0x0631] = true, [0x0632] = true, [0x0648] = true, [0x0671] = true,
+ [0x0672] = true, [0x0673] = true, [0x0675] = true, [0x0676] = true,
+ [0x0677] = true, [0x0688] = true, [0x0689] = true, [0x068A] = true,
+ [0x068B] = true, [0x068C] = true, [0x068D] = true, [0x068E] = true,
+ [0x068F] = true, [0x0690] = true, [0x0691] = true, [0x0692] = true,
+ [0x0693] = true, [0x0694] = true, [0x0695] = true, [0x0696] = true,
+ [0x0697] = true, [0x0698] = true, [0x0699] = true, [0x06C0] = true,
+ [0x06C3] = true, [0x06C4] = true, [0x06C5] = true, [0x06C6] = true,
+ [0x06C7] = true, [0x06C8] = true, [0x06C9] = true, [0x06CA] = true,
+ [0x06CB] = true, [0x06CD] = true, [0x06CF] = true, [0x06D2] = true,
+ [0x06D3] = true, [0x06D5] = true, [0x06EE] = true, [0x06EF] = true,
+ [0x0759] = true, [0x075A] = true, [0x075B] = true, [0x076B] = true,
+ [0x076C] = true, [0x0771] = true, [0x0773] = true, [0x0774] = true,
+ [0x0778] = true, [0x0779] = true, [0xFEF5] = true, [0xFEF7] = true,
+ [0xFEF9] = true, [0xFEFB] = true,
+}
+
+local isol_fina_medi_init = {
+ [0x0626] = true, [0x0628] = true, [0x062A] = true, [0x062B] = true,
+ [0x062C] = true, [0x062D] = true, [0x062E] = true, [0x0633] = true,
+ [0x0634] = true, [0x0635] = true, [0x0636] = true, [0x0637] = true,
+ [0x0638] = true, [0x0639] = true, [0x063A] = true, [0x063B] = true,
+ [0x063C] = true, [0x063D] = true, [0x063E] = true, [0x063F] = true,
+ [0x0640] = true, [0x0641] = true, [0x0642] = true, [0x0643] = true,
+ [0x0644] = true, [0x0645] = true, [0x0646] = true, [0x0647] = true,
+ [0x0649] = true, [0x064A] = true, [0x066E] = true, [0x066F] = true,
+ [0x0678] = true, [0x0679] = true, [0x067A] = true, [0x067B] = true,
+ [0x067C] = true, [0x067D] = true, [0x067E] = true, [0x067F] = true,
+ [0x0680] = true, [0x0681] = true, [0x0682] = true, [0x0683] = true,
+ [0x0684] = true, [0x0685] = true, [0x0686] = true, [0x0687] = true,
+ [0x069A] = true, [0x069B] = true, [0x069C] = true, [0x069D] = true,
+ [0x069E] = true, [0x069F] = true, [0x06A0] = true, [0x06A1] = true,
+ [0x06A2] = true, [0x06A3] = true, [0x06A4] = true, [0x06A5] = true,
+ [0x06A6] = true, [0x06A7] = true, [0x06A8] = true, [0x06A9] = true,
+ [0x06AA] = true, [0x06AB] = true, [0x06AC] = true, [0x06AD] = true,
+ [0x06AE] = true, [0x06AF] = true, [0x06B0] = true, [0x06B1] = true,
+ [0x06B2] = true, [0x06B3] = true, [0x06B4] = true, [0x06B5] = true,
+ [0x06B6] = true, [0x06B7] = true, [0x06B8] = true, [0x06B9] = true,
+ [0x06BA] = true, [0x06BB] = true, [0x06BC] = true, [0x06BD] = true,
+ [0x06BE] = true, [0x06BF] = true, [0x06C1] = true, [0x06C2] = true,
+ [0x06CC] = true, [0x06CE] = true, [0x06D0] = true, [0x06D1] = true,
+ [0x06FA] = true, [0x06FB] = true, [0x06FC] = true, [0x06FF] = true,
+ [0x0750] = true, [0x0751] = true, [0x0752] = true, [0x0753] = true,
+ [0x0754] = true, [0x0755] = true, [0x0756] = true, [0x0757] = true,
+ [0x0758] = true, [0x075C] = true, [0x075D] = true, [0x075E] = true,
+ [0x075F] = true, [0x0760] = true, [0x0761] = true, [0x0762] = true,
+ [0x0763] = true, [0x0764] = true, [0x0765] = true, [0x0766] = true,
+ [0x0767] = true, [0x0768] = true, [0x0769] = true, [0x076A] = true,
+ [0x076D] = true, [0x076E] = true, [0x076F] = true, [0x0770] = true,
+ [0x0772] = true, [0x0775] = true, [0x0776] = true, [0x0777] = true,
+ [0x077A] = true, [0x077B] = true, [0x077C] = true, [0x077D] = true,
+ [0x077E] = true, [0x077F] = true, [zwj] = true,
+}
+
+local arab_warned = { }
+
+-- todo: gref
+
+local function warning(current,what)
+ local char = current.char
+ if not arab_warned[char] then
+ log.report("analyze","arab: character %s (U+%04X) has no %s class", char, char, what)
+ arab_warned[char] = true
+ end
+end
+
+function fonts.analyzers.methods.nocolor(head,font,attr)
+ for n in traverse_node_list(head,glyph) do
+ if not font or n.font == font then
+ fcr(n)
+ end
+ end
+ return head, true
+end
+
+local function finish(first,last)
+ if last then
+ if first == last then
+ local fc = first.char
+ if isol_fina_medi_init[fc] or isol_fina[fc] then
+ set_attribute(first,state,4) -- isol
+ if trace_analyzing then fcs(first,"font:isol") end
+ else
+ warning(first,"isol")
+ set_attribute(first,state,0) -- error
+ if trace_analyzing then fcr(first) end
+ end
+ else
+ local lc = last.char
+ if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ?
+ -- if laststate == 1 or laststate == 2 or laststate == 4 then
+ set_attribute(last,state,3) -- fina
+ if trace_analyzing then fcs(last,"font:fina") end
+ else
+ warning(last,"fina")
+ set_attribute(last,state,0) -- error
+ if trace_analyzing then fcr(last) end
+ end
+ end
+ first, last = nil, nil
+ elseif first then
+ -- first and last are either both set so we never com here
+ local fc = first.char
+ if isol_fina_medi_init[fc] or isol_fina[fc] then
+ set_attribute(first,state,4) -- isol
+ if trace_analyzing then fcs(first,"font:isol") end
+ else
+ warning(first,"isol")
+ set_attribute(first,state,0) -- error
+ if trace_analyzing then fcr(first) end
+ end
+ first = nil
+ end
+ return first, last
+end
+
+function fonts.analyzers.methods.arab(head,font,attr) -- maybe make a special version with no trace
+ local tfmdata = fontdata[font]
+ local marks = tfmdata.marks
+ local first, last, current, done = nil, nil, head, false
+ while current do
+ if current.id == glyph and current.subtype<256 and current.font == font and not has_attribute(current,state) then
+ done = true
+ local char = current.char
+ if marks[char] then
+ set_attribute(current,state,5) -- mark
+ if trace_analyzing then fcs(current,"font:mark") end
+ elseif isol[char] then -- can be zwj or zwnj too
+ first, last = finish(first,last)
+ set_attribute(current,state,4) -- isol
+ if trace_analyzing then fcs(current,"font:isol") end
+ first, last = nil, nil
+ elseif not first then
+ if isol_fina_medi_init[char] then
+ set_attribute(current,state,1) -- init
+ if trace_analyzing then fcs(current,"font:init") end
+ first, last = first or current, current
+ elseif isol_fina[char] then
+ set_attribute(current,state,4) -- isol
+ if trace_analyzing then fcs(current,"font:isol") end
+ first, last = nil, nil
+ else -- no arab
+ first, last = finish(first,last)
+ end
+ elseif isol_fina_medi_init[char] then
+ first, last = first or current, current
+ set_attribute(current,state,2) -- medi
+ if trace_analyzing then fcs(current,"font:medi") end
+ elseif isol_fina[char] then
+ if not has_attribute(last,state,1) then
+ -- tricky, we need to check what last may be !
+ set_attribute(last,state,2) -- medi
+ if trace_analyzing then fcs(last,"font:medi") end
+ end
+ set_attribute(current,state,3) -- fina
+ if trace_analyzing then fcs(current,"font:fina") end
+ first, last = nil, nil
+ elseif char >= 0x0600 and char <= 0x06FF then
+ if trace_analyzing then fcs(current,"font:rest") end
+ first, last = finish(first,last)
+ else --no
+ first, last = finish(first,last)
+ end
+ else
+ first, last = finish(first,last)
+ end
+ current = current.next
+ end
+ first, last = finish(first,last)
+ return head, done
+end
diff --git a/tex/context/base/font-otb.lua b/tex/context/base/font-otb.lua
new file mode 100644
index 000000000..a3d347737
--- /dev/null
+++ b/tex/context/base/font-otb.lua
@@ -0,0 +1,373 @@
+if not modules then modules = { } end modules ['font-otb'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local concat = table.concat
+local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
+local type, next, tonumber, tostring = type, next, tonumber, tostring
+local lpegmatch = lpeg.match
+
+local otf = fonts.otf
+local tfm = fonts.tfm
+
+local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end)
+local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end)
+local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
+local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
+
+local wildcard = "*"
+local default = "dflt"
+
+local split_at_space = lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway
+
+local pcache, fcache = { }, { } -- could be weak
+
+local function gref(descriptions,n)
+ if type(n) == "number" then
+ local name = descriptions[n].name
+ if name then
+ return format("U+%04X (%s)",n,name)
+ else
+ return format("U+%04X")
+ end
+ elseif n then
+ local num, nam = { }, { }
+ for i=1,#n do
+ local ni = n[i]
+ num[i] = format("U+%04X",ni)
+ nam[i] = descriptions[ni].name or "?"
+ end
+ return format("%s (%s)",concat(num," "), concat(nam," "))
+ else
+ return "?"
+ end
+end
+
+local function cref(kind,lookupname)
+ if lookupname then
+ return format("feature %s, lookup %s",kind,lookupname)
+ else
+ return format("feature %s",kind)
+ end
+end
+
+local function resolve_ligatures(tfmdata,ligatures,kind)
+ kind = kind or "unknown"
+ local unicodes = tfmdata.unicodes
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local changed = tfmdata.changed
+ local done = { }
+ while true do
+ local ok = false
+ for k,v in next, ligatures do
+ local lig = v[1]
+ if not done[lig] then
+ local ligs = lpegmatch(split_at_space,lig)
+ if #ligs == 2 then
+ local uc = v[2]
+ local c, f, s = characters[uc], ligs[1], ligs[2]
+ local uft, ust = unicodes[f] or 0, unicodes[s] or 0
+ if not uft or not ust then
+ logs.report("define otf","%s: unicode problem with base ligature %s = %s + %s",cref(kind),gref(descriptions,uc),gref(descriptions,uft),gref(descriptions,ust))
+ -- some kind of error
+ else
+ if type(uft) == "number" then uft = { uft } end
+ if type(ust) == "number" then ust = { ust } end
+ for ufi=1,#uft do
+ local uf = uft[ufi]
+ for usi=1,#ust do
+ local us = ust[usi]
+ if changed[uf] or changed[us] then
+ if trace_baseinit and trace_ligatures then
+ logs.report("define otf","%s: base ligature %s + %s ignored",cref(kind),gref(descriptions,uf),gref(descriptions,us))
+ end
+ else
+ local first, second = characters[uf], us
+ if first and second then
+ local t = first.ligatures
+ if not t then
+ t = { }
+ first.ligatures = t
+ end
+ if type(uc) == "number" then
+ t[second] = { type = 0, char = uc }
+ else
+ t[second] = { type = 0, char = uc[1] } -- can this still happen?
+ end
+ if trace_baseinit and trace_ligatures then
+ logs.report("define otf","%s: base ligature %s + %s => %s",cref(kind),gref(descriptions,uf),gref(descriptions,us),gref(descriptions,uc))
+ end
+ end
+ end
+ end
+ end
+ end
+ ok, done[lig] = true, descriptions[uc].name
+ end
+ end
+ end
+ if ok then
+ -- done has "a b c" = "a_b_c" and ligatures the already set ligatures: "a b" = 123
+ -- and here we add extras (f i i = fi + i and alike)
+ --
+ -- we could use a hash for fnc and pattern
+ --
+ -- this might be interfering !
+ for d,n in next, done do
+ local pattern = pcache[d] if not pattern then pattern = "^(" .. d .. ") " pcache[d] = pattern end
+ local fnc = fcache[n] if not fnc then fnc = function() return n .. " " end fcache[n] = fnc end
+ for k,v in next, ligatures do
+ v[1] = gsub(v[1],pattern,fnc)
+ end
+ end
+ else
+ break
+ end
+ end
+end
+
+local splitter = lpeg.splitat(" ")
+
+function prepare_base_substitutions(tfmdata,kind,value) -- we can share some code with the node features
+ if value then
+ local otfdata = tfmdata.shared.otfdata
+ local validlookups, lookuplist = otf.collect_lookups(otfdata,kind,tfmdata.script,tfmdata.language)
+ if validlookups then
+ local ligatures = { }
+ local unicodes = tfmdata.unicodes -- names to unicodes
+ local indices = tfmdata.indices
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local changed = tfmdata.changed
+ --
+ local actions = {
+ substitution = function(p,lookup,k,glyph,unicode)
+ local pv = p[2] -- p.variant
+ if pv then
+ local upv = unicodes[pv]
+ if upv then
+ if type(upv) == "table" then
+ upv = upv[1]
+ end
+ if characters[upv] then
+ if trace_baseinit and trace_singles then
+ logs.report("define otf","%s: base substitution %s => %s",cref(kind,lookup),gref(descriptions,k),gref(descriptions,upv))
+ end
+ changed[k] = upv
+ end
+ end
+ end
+ end,
+ alternate = function(p,lookup,k,glyph,unicode)
+ local pc = p[2] -- p.components
+ if pc then
+ -- a bit optimized ugliness
+ if value == 1 then
+ pc = lpegmatch(splitter,pc)
+ elseif value == 2 then
+ local a, b = lpegmatch(splitter,pc)
+ pc = b or a
+ else
+ pc = { lpegmatch(splitter,pc) }
+ pc = pc[value] or pc[#pc]
+ end
+ if pc then
+ local upc = unicodes[pc]
+ if upc then
+ if type(upc) == "table" then
+ upc = upc[1]
+ end
+ if characters[upc] then
+ if trace_baseinit and trace_alternatives then
+ logs.report("define otf","%s: base alternate %s %s => %s",cref(kind,lookup),tostring(value),gref(descriptions,k),gref(descriptions,upc))
+ end
+ changed[k] = upc
+ end
+ end
+ end
+ end
+ end,
+ ligature = function(p,lookup,k,glyph,unicode)
+ local pc = p[2]
+ if pc then
+ if trace_baseinit and trace_ligatures then
+ local upc = { lpegmatch(splitter,pc) }
+ for i=1,#upc do upc[i] = unicodes[upc[i]] end
+ -- we assume that it's no table
+ logs.report("define otf","%s: base ligature %s => %s",cref(kind,lookup),gref(descriptions,upc),gref(descriptions,k))
+ end
+ ligatures[#ligatures+1] = { pc, k }
+ end
+ end,
+ }
+ --
+ for k,c in next, characters do
+ local glyph = descriptions[k]
+ local lookups = glyph.slookups
+ if lookups then
+ for l=1,#lookuplist do
+ local lookup = lookuplist[l]
+ local p = lookups[lookup]
+ if p then
+ local a = actions[p[1]]
+ if a then
+ a(p,lookup,k,glyph,unicode)
+ end
+ end
+ end
+ end
+ local lookups = glyph.mlookups
+ if lookups then
+ for l=1,#lookuplist do
+ local lookup = lookuplist[l]
+ local ps = lookups[lookup]
+ if ps then
+ for i=1,#ps do
+ local p = ps[i]
+ local a = actions[p[1]]
+ if a then
+ a(p,lookup,k,glyph,unicode)
+ end
+ end
+ end
+ end
+ end
+ end
+ resolve_ligatures(tfmdata,ligatures,kind)
+ end
+ else
+ tfmdata.ligatures = tfmdata.ligatures or { } -- left over from what ?
+ end
+end
+
+local function prepare_base_kerns(tfmdata,kind,value) -- todo what kind of kerns, currently all
+ if value then
+ local otfdata = tfmdata.shared.otfdata
+ local validlookups, lookuplist = otf.collect_lookups(otfdata,kind,tfmdata.script,tfmdata.language)
+ if validlookups then
+ local unicodes = tfmdata.unicodes -- names to unicodes
+ local indices = tfmdata.indices
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local sharedkerns = { }
+ for u, chr in next, characters do
+ local d = descriptions[u]
+ if d then
+ local dk = d.mykerns -- shared
+ if dk then
+ local s = sharedkerns[dk]
+ if s == false then
+ -- skip
+ elseif s then
+ chr.kerns = s
+ else
+ local t, done = chr.kerns or { }, false
+ for l=1,#lookuplist do
+ local lookup = lookuplist[l]
+ local kerns = dk[lookup]
+ if kerns then
+ for k, v in next, kerns do
+ if v ~= 0 and not t[k] then -- maybe no 0 test here
+ t[k], done = v, true
+ if trace_baseinit and trace_kerns then
+ logs.report("define otf","%s: base kern %s + %s => %s",cref(kind,lookup),gref(descriptions,u),gref(descriptions,k),v)
+ end
+ end
+ end
+ end
+ end
+ if done then
+ sharedkerns[dk] = t
+ chr.kerns = t -- no empty assignments
+ else
+ sharedkerns[dk] = false
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+-- In principle we could register each feature individually which was
+-- what we did in earlier versions. However, after the rewrite it
+-- made more sense to collect them in an overall features initializer
+-- just as with the node variant. There it was needed because we need
+-- to do complete mixed runs and not run featurewise (as we did before).
+
+local supported_gsub = {
+ 'liga', 'dlig', 'rlig', 'hlig',
+ 'pnum', 'onum', 'tnum', 'lnum',
+ 'zero',
+ 'smcp', 'cpsp', 'c2sc', 'ornm', 'aalt',
+ 'hwid', 'fwid',
+ 'ssty', 'rtlm', -- math
+-- 'tlig', 'trep',
+}
+
+local supported_gpos = {
+ 'kern'
+}
+
+function otf.features.register_base_substitution(tag)
+ supported_gsub[#supported_gsub+1] = tag
+end
+function otf.features.register_base_kern(tag)
+ supported_gsub[#supported_gpos+1] = tag
+end
+
+local basehash, basehashes = { }, 1
+
+function fonts.initializers.base.otf.features(tfmdata,value)
+ if true then -- value then
+ -- not shared
+ local t = trace_preparing and os.clock()
+ local features = tfmdata.shared.features
+ if features then
+ local h = { }
+ for f=1,#supported_gsub do
+ local feature = supported_gsub[f]
+ local value = features[feature]
+ prepare_base_substitutions(tfmdata,feature,value)
+ if value then
+ h[#h+1] = feature .. "=" .. tostring(value)
+ end
+ end
+ for f=1,#supported_gpos do
+ local feature = supported_gpos[f]
+ local value = features[feature]
+ prepare_base_kerns(tfmdata,feature,features[feature])
+ if value then
+ h[#h+1] = feature .. "=" .. tostring(value)
+ end
+ end
+ local hash = concat(h," ")
+ local base = basehash[hash]
+ if not base then
+ basehashes = basehashes + 1
+ base = basehashes
+ basehash[hash] = base
+ end
+ -- We need to make sure that luatex sees the difference between
+ -- base fonts that have different glyphs in the same slots in fonts
+ -- that have the same fullname (or filename). LuaTeX will merge fonts
+ -- eventually (and subset later on). If needed we can use a more
+ -- verbose name as long as we don't use <()<>[]{}/%> and the length
+ -- is < 128.
+ tfmdata.fullname = tfmdata.fullname .. "-" .. base -- tfmdata.psname is the original
+ --~ logs.report("otf define","fullname base hash: '%s', featureset '%s'",tfmdata.fullname,hash)
+ end
+ if trace_preparing then
+ logs.report("otf define","preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?")
+ end
+ end
+end
diff --git a/tex/context/base/font-otc.lua b/tex/context/base/font-otc.lua
new file mode 100644
index 000000000..357d347b1
--- /dev/null
+++ b/tex/context/base/font-otc.lua
@@ -0,0 +1,213 @@
+if not modules then modules = { } end modules ['font-otc'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (context)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, insert = string.format, table.insert
+local type, next = type, next
+
+-- we assume that the other otf stuff is loaded already
+
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+
+local otf = fonts.otf
+local tfm = fonts.tfm
+
+-- instead of "script = "DFLT", langs = { 'dflt' }" we now use wildcards (we used to
+-- have always); some day we can write a "force always when true" trick for other
+-- features as well
+--
+-- we could have a tnum variant as well
+
+local extra_lists = {
+ tlig = {
+ {
+ endash = "hyphen hyphen",
+ emdash = "hyphen hyphen hyphen",
+ -- quotedblleft = "quoteleft quoteleft",
+ -- quotedblright = "quoteright quoteright",
+ -- quotedblleft = "grave grave",
+ -- quotedblright = "quotesingle quotesingle",
+ -- quotedblbase = "comma comma",
+ },
+ },
+ trep = {
+ {
+ -- [0x0022] = 0x201D,
+ [0x0027] = 0x2019,
+ -- [0x0060] = 0x2018,
+ },
+ },
+ anum = {
+ { -- arabic
+ [0x0030] = 0x0660,
+ [0x0031] = 0x0661,
+ [0x0032] = 0x0662,
+ [0x0033] = 0x0663,
+ [0x0034] = 0x0664,
+ [0x0035] = 0x0665,
+ [0x0036] = 0x0666,
+ [0x0037] = 0x0667,
+ [0x0038] = 0x0668,
+ [0x0039] = 0x0669,
+ },
+ { -- persian
+ [0x0030] = 0x06F0,
+ [0x0031] = 0x06F1,
+ [0x0032] = 0x06F2,
+ [0x0033] = 0x06F3,
+ [0x0034] = 0x06F4,
+ [0x0035] = 0x06F5,
+ [0x0036] = 0x06F6,
+ [0x0037] = 0x06F7,
+ [0x0038] = 0x06F8,
+ [0x0039] = 0x06F9,
+ },
+ },
+}
+
+local extra_features = { -- maybe just 1..n so that we prescribe order
+ tlig = {
+ {
+ features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "tlig", comment = "added bij mkiv" }, },
+ name = "ctx_tlig_1",
+ subtables = { { name = "ctx_tlig_1_s" } },
+ type = "gsub_ligature",
+ flags = { },
+ },
+ },
+ trep = {
+ {
+ features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "trep", comment = "added bij mkiv" }, },
+ name = "ctx_trep_1",
+ subtables = { { name = "ctx_trep_1_s" } },
+ type = "gsub_single",
+ flags = { },
+ },
+ },
+ anum = {
+ {
+ features = { { scripts = { { script = "arab", langs = { "dflt", "FAR" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ name = "ctx_anum_1",
+ subtables = { { name = "ctx_anum_1_s" } },
+ type = "gsub_single",
+ flags = { },
+ },
+ {
+ features = { { scripts = { { script = "arab", langs = { "URD" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ name = "ctx_anum_2",
+ subtables = { { name = "ctx_anum_2_s" } },
+ type = "gsub_single",
+ flags = { },
+ },
+ },
+}
+
+fonts.otf.enhancers["add some missing characters"] = function(data,filename)
+ -- todo
+end
+
+fonts.otf.enhancers["enrich with features"] = function(data,filename)
+ -- could be done elsewhere (true can be #)
+ local used = { }
+ for i=1,#otf.glists do
+ local g = data[otf.glists[i]]
+ if g then
+ for i=1,#g do
+ local f = g[i].features
+ if f then
+ for i=1,#f do
+ local t = f[i].tag
+ if t then used[t] = true end
+ end
+ end
+ end
+ end
+ end
+ --
+ local glyphs = data.glyphs
+ local indices = data.map.map
+ data.gsub = data.gsub or { }
+ for kind, specifications in next, extra_features do
+ if not used[kind] then
+ local done = 0
+ for s=1,#specifications do
+ local added = false
+ local specification = specifications[s]
+ local list = extra_lists[kind][s]
+ local name = specification.name .. "_s"
+ if specification.type == "gsub_ligature" then
+ for unicode, index in next, indices do
+ local glyph = glyphs[index]
+ local ligature = list[glyph.name]
+ if ligature then
+ local o = glyph.lookups or { }
+ -- o[name] = { "ligature", ligature, glyph.name }
+ o[name] = {
+ {
+ ["type"] = "ligature",
+ ["specification"] = {
+ char = glyph.name,
+ components = ligature,
+ }
+ }
+ }
+ glyph.lookups, done, added = o, done+1, true
+ end
+ end
+ elseif specification.type == "gsub_single" then
+ for unicode, index in next, indices do
+ local glyph = glyphs[index]
+ local r = list[unicode]
+ if r then
+ local replacement = indices[r]
+ if replacement and glyphs[replacement] then
+ local o = glyph.lookups or { }
+ -- o[name] = { { "substitution", glyphs[replacement].name } }
+ o[name] = {
+ {
+ ["type"] = "substitution",
+ ["specification"] = {
+ variant = glyphs[replacement].name,
+ }
+ }
+ }
+ glyph.lookups, done, added = o, done+1, true
+ end
+ end
+ end
+ end
+ if added then
+ insert(data.gsub,s,table.fastcopy(specification)) -- right order
+ end
+ end
+ if done > 0 then
+ if trace_loading then
+ logs.report("load otf","enhance: registering %s feature (%s glyphs affected)",kind,done)
+ end
+ end
+ end
+ end
+end
+
+otf.tables.features['tlig'] = 'TeX Ligatures'
+otf.tables.features['trep'] = 'TeX Replacements'
+otf.tables.features['anum'] = 'Arabic Digits'
+
+otf.features.register_base_substitution('tlig')
+otf.features.register_base_substitution('trep')
+otf.features.register_base_substitution('anum')
+
+-- the functionality is defined elsewhere
+
+fonts.initializers.base.otf.equaldigits = fonts.initializers.common.equaldigits
+fonts.initializers.node.otf.equaldigits = fonts.initializers.common.equaldigits
+
+fonts.initializers.base.otf.lineheight = fonts.initializers.common.lineheight
+fonts.initializers.node.otf.lineheight = fonts.initializers.common.lineheight
+
+fonts.initializers.base.otf.compose = fonts.initializers.common.compose
+fonts.initializers.node.otf.compose = fonts.initializers.common.compose
diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua
new file mode 100644
index 000000000..41e885331
--- /dev/null
+++ b/tex/context/base/font-otd.lua
@@ -0,0 +1,78 @@
+if not modules then modules = { } end modules ['font-otd'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
+
+fonts = fonts or { }
+fonts.otf = fonts.otf or { }
+
+local otf = fonts.otf
+local fontdata = fonts.ids
+
+otf.features = otf.features or { }
+otf.features.default = otf.features.default or { }
+
+local context_setups = fonts.define.specify.context_setups
+local context_numbers = fonts.define.specify.context_numbers
+
+local a_to_script = { } otf.a_to_script = a_to_script
+local a_to_language = { } otf.a_to_language = a_to_language
+
+function otf.set_dynamics(font,dynamics,attribute)
+ features = context_setups[context_numbers[attribute]] -- can be moved to caller
+ if features then
+ local script = features.script or 'dflt'
+ local language = features.language or 'dflt'
+ local ds = dynamics[script]
+ if not ds then
+ ds = { }
+ dynamics[script] = ds
+ end
+ local dsl = ds[language]
+ if not dsl then
+ dsl = { }
+ ds[language] = dsl
+ end
+ local dsla = dsl[attribute]
+ if dsla then
+ -- if trace_dynamics then
+ -- logs.report("otf define","using dynamics %s: attribute %s, script %s, language %s",context_numbers[attribute],attribute,script,language)
+ -- end
+ return dsla
+ else
+ local tfmdata = fontdata[font]
+ a_to_script [attribute] = script
+ a_to_language[attribute] = language
+ -- we need to save some values
+ local saved = {
+ script = tfmdata.script,
+ language = tfmdata.language,
+ mode = tfmdata.mode,
+ features = tfmdata.shared.features
+ }
+ tfmdata.mode = "node"
+ tfmdata.language = language
+ tfmdata.script = script
+ tfmdata.shared.features = { }
+ -- end of save
+ dsla = otf.set_features(tfmdata,fonts.define.check(features,otf.features.default))
+ if trace_dynamics then
+ logs.report("otf define","setting dynamics %s: attribute %s, script %s, language %s",context_numbers[attribute],attribute,script,language)
+ end
+ -- we need to restore some values
+ tfmdata.script = saved.script
+ tfmdata.language = saved.language
+ tfmdata.mode = saved.mode
+ tfmdata.shared.features = saved.features
+ -- end of restore
+ dynamics[script][language][attribute] = dsla -- cache
+ return dsla
+ end
+ end
+ return nil -- { }
+end
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
new file mode 100644
index 000000000..9cecf21f0
--- /dev/null
+++ b/tex/context/base/font-otf.lua
@@ -0,0 +1,1752 @@
+if not modules then modules = { } end modules ['font-otf'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+
+local concat, getn, utfbyte = table.concat, table.getn, utf.byte
+local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
+local type, next, tonumber, tostring = type, next, tonumber, tostring
+local abs = math.abs
+local lpegmatch = lpeg.match
+
+local trace_private = false trackers.register("otf.private", function(v) trace_private = v end)
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+local trace_features = false trackers.register("otf.features", function(v) trace_features = v end)
+local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
+local trace_sequences = false trackers.register("otf.sequences", function(v) trace_sequences = v end)
+local trace_math = false trackers.register("otf.math", function(v) trace_math = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+--~ trackers.enable("otf.loading")
+
+--[[ldx--
+
The fontforge table has organized lookups in a certain way. A first implementation
+of this code was organized featurewise: information related to features was
+collected and processing boiled down to a run over the features. The current
+implementation honors the order in the main feature table. Since we can reorder this
+table as we want, we can eventually support several models of processing. We kept
+the static as well as dynamic feature processing, because it had proved to be
+rather useful. The formerly three loop variants have beem discarded but will
+reapear at some time.
+
+
+we loop over all lookups
+for each lookup we do a run over the list of glyphs
+but we only process them for features that are enabled
+if we're dealing with a contextual lookup, we loop over all contexts
+in that loop we quit at a match and then process the list of sublookups
+we always continue after the match
+
+
+
In we do this for each font that is used in a list, so in
+practice we have quite some nested loops.
+
+
We process the whole list and then consult the glyph nodes. An alternative approach
+is to collect strings of characters using the same font including spaces (because some
+lookups involve spaces). However, we then need to reconstruct the list which is no fun.
+Also, we need to carry quite some information, like attributes, so eventually we don't
+gain much (if we gain something at all).
+
+
Another consideration has been to operate on sublists (subhead, subtail) but again
+this would complicate matters as we then neext to keep track of a changing subhead
+and subtail. On the other hand, this might save some runtime. The number of changes
+involved is not that large. This only makes sense when we have many fonts in a list
+and don't change to frequently.
+--ldx]]--
+
+fonts = fonts or { }
+fonts.otf = fonts.otf or { }
+fonts.tfm = fonts.tfm or { }
+
+local otf = fonts.otf
+local tfm = fonts.tfm
+
+local fontdata = fonts.ids
+
+otf.tables = otf.tables or { } -- defined in font-ott.lua
+otf.meanings = otf.meanings or { } -- defined in font-ott.lua
+otf.tables.features = otf.tables.features or { } -- defined in font-ott.lua
+otf.tables.languages = otf.tables.languages or { } -- defined in font-ott.lua
+otf.tables.scripts = otf.tables.scripts or { } -- defined in font-ott.lua
+
+otf.features = otf.features or { }
+otf.features.list = otf.features.list or { }
+otf.features.default = otf.features.default or { }
+
+otf.enhancers = otf.enhancers or { }
+otf.glists = { "gsub", "gpos" }
+
+otf.version = 2.650 -- beware: also sync font-mis.lua
+otf.pack = true -- beware: also sync font-mis.lua
+otf.syncspace = true
+otf.notdef = false
+otf.cache = containers.define("fonts", "otf", otf.version, true)
+otf.cleanup_aat = false -- only context
+
+local wildcard = "*"
+local default = "dflt"
+
+--[[ldx--
+
We start with a lot of tables and related functions.
+--ldx]]--
+
+local function load_featurefile(ff,featurefile)
+ if featurefile then
+ featurefile = resolvers.find_file(file.addsuffix(featurefile,'fea'),'fea')
+ if featurefile and featurefile ~= "" then
+ if trace_loading then
+ logs.report("load otf", "featurefile: %s", featurefile)
+ end
+ fontloader.apply_featurefile(ff, featurefile)
+ end
+ end
+end
+
+function otf.enhance(name,data,filename,verbose)
+ local enhancer = otf.enhancers[name]
+ if enhancer then
+ if (verbose ~= nil and verbose) or trace_loading then
+ logs.report("load otf","enhance: %s (%s)",name,filename)
+ end
+ enhancer(data,filename)
+ end
+end
+
+local enhancers = {
+ -- pack and unpack are handled separately; they might even be moved
+ -- away from the enhancers namespace
+ "patch bugs",
+ "merge cid fonts", "prepare unicode", "cleanup ttf tables", "compact glyphs", "reverse coverage",
+ "cleanup aat", "enrich with features", "add some missing characters",
+ "reorganize mark classes",
+ "reorganize kerns", -- moved here
+ "flatten glyph lookups", "flatten anchor tables", "flatten feature tables",
+ "simplify glyph lookups", -- some saving
+ "prepare luatex tables",
+ "analyse features", "rehash features",
+ "analyse anchors", "analyse marks", "analyse unicodes", "analyse subtables",
+ "check italic correction","check math",
+ "share widths",
+ "strip not needed data",
+ "migrate metadata",
+ "check math parameters",
+}
+
+function otf.load(filename,format,sub,featurefile)
+ local name = file.basename(file.removesuffix(filename))
+ if featurefile then
+ name = name .. "@" .. file.removesuffix(file.basename(featurefile))
+ end
+ if sub == "" then sub = false end
+ local hash = name
+ if sub then
+ hash = hash .. "-" .. sub
+ end
+ hash = containers.cleanname(hash)
+ local data = containers.read(otf.cache(), hash)
+ local size = lfs.attributes(filename,"size") or 0
+ if not data or data.verbose ~= fonts.verbose or data.size ~= size then
+ logs.report("load otf","loading: %s (hash: %s)",filename,hash)
+ local ff, messages
+ if sub then
+ ff, messages = fontloader.open(filename,sub)
+ else
+ ff, messages = fontloader.open(filename)
+ end
+ if trace_loading and messages and #messages > 0 then
+ if type(messages) == "string" then
+ logs.report("load otf","warning: %s",messages)
+ else
+ for m=1,#messages do
+ logs.report("load otf","warning: %s",tostring(messages[m]))
+ end
+ end
+ else
+ logs.report("load otf","font loaded okay")
+ end
+ if ff then
+ load_featurefile(ff,featurefile)
+ data = fontloader.to_table(ff)
+ fontloader.close(ff)
+ if data then
+ logs.report("load otf","file size: %s", size)
+ logs.report("load otf","enhancing ...")
+ for e=1,#enhancers do
+ otf.enhance(enhancers[e],data,filename)
+ io.flush() -- we want instant messages
+ end
+ if otf.pack and not fonts.verbose then
+ otf.enhance("pack",data,filename)
+ end
+ data.size = size
+ data.verbose = fonts.verbose
+ logs.report("load otf","saving in cache: %s",filename)
+ data = containers.write(otf.cache(), hash, data)
+ collectgarbage("collect")
+ data = containers.read(otf.cache(), hash) -- this frees the old table and load the sparse one
+ collectgarbage("collect")
+ else
+ logs.report("load otf","loading failed (table conversion error)")
+ end
+ else
+ logs.report("load otf","loading failed (file read error)")
+ end
+ end
+ if data then
+ if trace_defining then
+ logs.report("define font","loading from cache: %s",hash)
+ end
+ otf.enhance("unpack",data,filename,false) -- no message here
+ otf.add_dimensions(data)
+ if trace_sequences then
+ otf.show_feature_order(data,filename)
+ end
+ end
+ return data
+end
+
+function otf.add_dimensions(data)
+ -- todo: forget about the width if it's the defaultwidth (saves mem)
+ -- we could also build the marks hash here (instead of storing it)
+ if data then
+ local force = otf.notdef
+ local luatex = data.luatex
+ local defaultwidth = luatex.defaultwidth or 0
+ local defaultheight = luatex.defaultheight or 0
+ local defaultdepth = luatex.defaultdepth or 0
+ for _, d in next, data.glyphs do
+ local bb, wd = d.boundingbox, d.width
+ if not wd then
+ d.width = defaultwidth
+ elseif wd ~= 0 and d.class == "mark" then
+ d.width = -wd
+ end
+ if force and not d.name then
+ d.name = ".notdef"
+ end
+ if bb then
+ local ht, dp = bb[4], -bb[2]
+ if ht == 0 or ht < 0 then
+ -- no need to set it and no negative heights, nil == 0
+ else
+ d.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- no negative depths and no negative depths, nil == 0
+ else
+ d.depth = dp
+ end
+ end
+ end
+ end
+end
+
+function otf.show_feature_order(otfdata,filename)
+ local sequences = otfdata.luatex.sequences
+ if sequences and #sequences > 0 then
+ if trace_loading then
+ logs.report("otf check","font %s has %s sequences",filename,#sequences)
+ logs.report("otf check"," ")
+ end
+ for nos=1,#sequences do
+ local sequence = sequences[nos]
+ local typ = sequence.type or "no-type"
+ local name = sequence.name or "no-name"
+ local subtables = sequence.subtables or { "no-subtables" }
+ local features = sequence.features
+ if trace_loading then
+ logs.report("otf check","%3i %-15s %-20s [%s]",nos,name,typ,concat(subtables,","))
+ end
+ if features then
+ for feature, scripts in next, features do
+ local tt = { }
+ for script, languages in next, scripts do
+ local ttt = { }
+ for language, _ in next, languages do
+ ttt[#ttt+1] = language
+ end
+ tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
+ end
+ if trace_loading then
+ logs.report("otf check"," %s: %s",feature,concat(tt," "))
+ end
+ end
+ end
+ end
+ if trace_loading then
+ logs.report("otf check","\n")
+ end
+ elseif trace_loading then
+ logs.report("otf check","font %s has no sequences",filename)
+ end
+end
+
+-- todo: normalize, design_size => designsize
+
+otf.enhancers["reorganize mark classes"] = function(data,filename)
+ if data.mark_classes then
+ local unicodes = data.luatex.unicodes
+ local reverse = { }
+ for name, class in next, data.mark_classes do
+ local t = { }
+ for s in gmatch(class,"[^ ]+") do
+ local us = unicodes[s]
+ if type(us) == "table" then
+ for u=1,#us do
+ t[us[u]] = true
+ end
+ else
+ t[us] = true
+ end
+ end
+ reverse[name] = t
+ end
+ data.luatex.markclasses = reverse
+ data.mark_classes = nil
+ end
+end
+
+otf.enhancers["prepare luatex tables"] = function(data,filename)
+ data.luatex = data.luatex or { }
+ local luatex = data.luatex
+ luatex.filename = filename
+ luatex.version = otf.version
+ luatex.creator = "context mkiv"
+end
+
+otf.enhancers["cleanup aat"] = function(data,filename)
+ if otf.cleanup_aat then
+ end
+end
+
+local function analyze_features(g, features)
+ if g then
+ local t, done = { }, { }
+ for k=1,#g do
+ local f = features or g[k].features
+ if f then
+ for k=1,#f do
+ -- scripts and tag
+ local tag = f[k].tag
+ if not done[tag] then
+ t[#t+1] = tag
+ done[tag] = true
+ end
+ end
+ end
+ end
+ if #t > 0 then
+ return t
+ end
+ end
+ return nil
+end
+
+otf.enhancers["analyse features"] = function(data,filename)
+ -- local luatex = data.luatex
+ -- luatex.gposfeatures = analyze_features(data.gpos)
+ -- luatex.gsubfeatures = analyze_features(data.gsub)
+end
+
+otf.enhancers["rehash features"] = function(data,filename)
+ local features = { }
+ data.luatex.features = features
+ for k, what in next, otf.glists do
+ local dw = data[what]
+ if dw then
+ local f = { }
+ features[what] = f
+ for i=1,#dw do
+ local d= dw[i]
+ local dfeatures = d.features
+ if dfeatures then
+ for i=1,#dfeatures do
+ local df = dfeatures[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag] if not ft then ft = {} f[tag] = ft end
+ local dscripts = df.scripts
+ for script, languages in next, dscripts do
+ script = strip(lower(script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers["analyse anchors"] = function(data,filename)
+ local classes = data.anchor_classes
+ local luatex = data.luatex
+ local anchor_to_lookup, lookup_to_anchor = { }, { }
+ luatex.anchor_to_lookup, luatex.lookup_to_anchor = anchor_to_lookup, lookup_to_anchor
+ if classes then
+ for c=1,#classes do
+ local class = classes[c]
+ local anchor = class.name
+ local lookups = class.lookup
+ if type(lookups) ~= "table" then
+ lookups = { lookups }
+ end
+ local a = anchor_to_lookup[anchor]
+ if not a then a = { } anchor_to_lookup[anchor] = a end
+ for l=1,#lookups do
+ local lookup = lookups[l]
+ local l = lookup_to_anchor[lookup]
+ if not l then l = { } lookup_to_anchor[lookup] = l end
+ l[anchor] = true
+ a[lookup] = true
+ end
+ end
+ end
+end
+
+otf.enhancers["analyse marks"] = function(data,filename)
+ local glyphs = data.glyphs
+ local marks = { }
+ data.luatex.marks = marks
+ for unicode, index in next, data.luatex.indices do
+ local glyph = glyphs[index]
+ if glyph.class == "mark" then
+ marks[unicode] = true
+ end
+ end
+end
+
+otf.enhancers["analyse unicodes"] = fonts.map.add_to_unicode
+
+otf.enhancers["analyse subtables"] = function(data,filename)
+ data.luatex = data.luatex or { }
+ local luatex = data.luatex
+ local sequences = { }
+ local lookups = { }
+ luatex.sequences = sequences
+ luatex.lookups = lookups
+ for _, g in next, { data.gsub, data.gpos } do
+ for k=1,#g do
+ local gk = g[k]
+ local typ = gk.type
+ if typ == "gsub_contextchain" or typ == "gpos_contextchain" then
+ gk.chain = 1
+ elseif typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain" then
+ gk.chain = -1
+ else
+ gk.chain = 0
+ end
+ local features = gk.features
+ if features then
+ sequences[#sequences+1] = gk
+ -- scripts, tag, ismac
+ local t = { }
+ for f=1,#features do
+ local feature = features[f]
+ local hash = { }
+ -- only script and langs matter
+ for s, languages in next, feature.scripts do
+ s = lower(s)
+ local h = hash[s]
+ if not h then h = { } hash[s] = h end
+ for l=1,#languages do
+ h[strip(lower(languages[l]))] = true
+ end
+ end
+ t[feature.tag] = hash
+ end
+ gk.features = t
+ else
+ lookups[gk.name] = gk
+ gk.name = nil
+ end
+ local subtables = gk.subtables
+ if subtables then
+ local t = { }
+ for s=1,#subtables do
+ local subtable = subtables[s]
+ local name = subtable.name
+ t[#t+1] = name
+ end
+ gk.subtables = t
+ end
+ local flags = gk.flags
+ if flags then
+ gk.flags = { -- forcing false packs nicer
+ (flags.ignorecombiningmarks and "mark") or false,
+ (flags.ignoreligatures and "ligature") or false,
+ (flags.ignorebaseglyphs and "base") or false,
+ flags.r2l or false,
+ }
+ if flags.mark_class then
+ gk.markclass = luatex.markclasses[flags.mark_class]
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers["merge cid fonts"] = function(data,filename)
+ -- we can also move the names to data.luatex.names which might
+ -- save us some more memory (at the cost of harder tracing)
+ if data.subfonts then
+ if data.glyphs and next(data.glyphs) then
+ logs.report("load otf","replacing existing glyph table due to subfonts")
+ end
+ local cidinfo = data.cidinfo
+ local verbose = fonts.verbose
+ if cidinfo.registry then
+ local cidmap, cidname = fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
+ if cidmap then
+ cidinfo.usedname = cidmap.usedname
+ local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, { }, 0, 0
+ local unicodes, names = cidmap.unicodes, cidmap.names
+ for n, subfont in next, data.subfonts do
+ for index, g in next, subfont.glyphs do
+ if not next(g) then
+ -- dummy entry
+ else
+ local unicode, name = unicodes[index], names[index]
+ g.cidindex = n
+ g.boundingbox = g.boundingbox -- or zerobox
+ g.name = g.name or name or "unknown"
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ g.unicode = unicode
+ elseif name then
+ nofnames = nofnames + 1
+ g.unicode = -1
+ end
+ glyphs[index] = g
+ end
+ end
+ subfont.glyphs = nil
+ end
+ if trace_loading then
+ logs.report("load otf","cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ end
+ data.glyphs = glyphs
+ data.map = data.map or { }
+ data.map.map = uni_to_int
+ data.map.backmap = int_to_uni
+ elseif trace_loading then
+ logs.report("load otf","unable to remap cid font, missing cid file for %s",filename)
+ end
+ elseif trace_loading then
+ logs.report("load otf","font %s has no glyphs",filename)
+ end
+ end
+end
+
+otf.enhancers["prepare unicode"] = function(data,filename)
+ local luatex = data.luatex
+ if not luatex then luatex = { } data.luatex = luatex end
+ local indices, unicodes, multiples, internals = { }, { }, { }, { }
+ local glyphs = data.glyphs
+ local mapmap = data.map
+ if not mapmap then
+ logs.report("load otf","no map in %s",filename)
+ mapmap = { }
+ data.map = { map = mapmap }
+ elseif not mapmap.map then
+ logs.report("load otf","no unicode map in %s",filename)
+ mapmap = { }
+ data.map.map = mapmap
+ else
+ mapmap = mapmap.map
+ end
+ local criterium = fonts.private
+ local private = fonts.private
+ for index, glyph in next, glyphs do
+ if index > 0 then
+ local name = glyph.name
+ if name then
+ local unicode = glyph.unicode
+ if unicode == -1 or unicode >= criterium then
+ glyph.unicode = private
+ indices[private] = index
+ unicodes[name] = private
+ internals[index] = true
+ if trace_private then
+ logs.report("load otf","enhance: glyph %s at index U+%04X is moved to private unicode slot U+%04X",name,index,private)
+ end
+ private = private + 1
+ else
+ indices[unicode] = index
+ unicodes[name] = unicode
+ end
+ end
+ end
+ end
+ -- beware: the indices table is used to initialize the tfm table
+ for unicode, index in next, mapmap do
+ if not internals[index] then
+ local name = glyphs[index].name
+ if name then
+ local un = unicodes[name]
+ if not un then
+ unicodes[name] = unicode -- or 0
+ elseif type(un) == "number" then
+ if un ~= unicode then
+ multiples[#multiples+1] = name
+ unicodes[name] = { un, unicode }
+ indices[unicode] = index
+ end
+ else
+ local ok = false
+ for u=1,#un do
+ if un[u] == unicode then
+ ok = true
+ break
+ end
+ end
+ if not ok then
+ multiples[#multiples+1] = name
+ un[#un+1] = unicode
+ indices[unicode] = index
+ end
+ end
+ end
+ end
+ end
+ if trace_loading then
+ if #multiples > 0 then
+ logs.report("load otf","%s glyph are reused: %s",#multiples, concat(multiples," "))
+ else
+ logs.report("load otf","no glyph are reused")
+ end
+ end
+ luatex.indices = indices
+ luatex.unicodes = unicodes
+ luatex.private = private
+end
+
+otf.enhancers["cleanup ttf tables"] = function(data,filename)
+ local ttf_tables = data.ttf_tables
+ if ttf_tables then
+ for k=1,#ttf_tables do
+ if ttf_tables[k].data then ttf_tables[k].data = "deleted" end
+ end
+ end
+ data.ttf_tab_saved = nil
+end
+
+otf.enhancers["compact glyphs"] = function(data,filename)
+ table.compact(data.glyphs) -- needed?
+ if data.subfonts then
+ for _, subfont in next, data.subfonts do
+ table.compact(subfont.glyphs) -- needed?
+ end
+ end
+end
+
+otf.enhancers["reverse coverage"] = function(data,filename)
+ -- we prefer the before lookups in a normal order
+ if data.lookups then
+ for _, v in next, data.lookups do
+ if v.rules then
+ for _, vv in next, v.rules do
+ local c = vv.coverage
+ if c and c.before then
+ c.before = table.reverse(c.before)
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers["check italic correction"] = function(data,filename)
+ local glyphs = data.glyphs
+ local ok = false
+ for index, glyph in next, glyphs do
+ local ic = glyph.italic_correction
+ if ic then
+ if ic ~= 0 then
+ glyph.italic = ic
+ end
+ glyph.italic_correction = nil
+ ok = true
+ end
+ end
+ -- we can use this to avoid calculations
+ otf.tables.valid_fields[#otf.tables.valid_fields+1] = "has_italic"
+ data.has_italic = true
+end
+
+otf.enhancers["check math"] = function(data,filename)
+ if data.math then
+ -- we move the math stuff into a math subtable because we then can
+ -- test faster in the tfm copy
+ local glyphs = data.glyphs
+ local unicodes = data.luatex.unicodes
+ for index, glyph in next, glyphs do
+ local mk = glyph.mathkern
+ local hv = glyph.horiz_variants
+ local vv = glyph.vert_variants
+ if mk or hv or vv then
+ local math = { }
+ glyph.math = math
+ if mk then
+ for k, v in next, mk do
+ if not next(v) then
+ mk[k] = nil
+ end
+ end
+ math.kerns = mk
+ glyph.mathkern = nil
+ end
+ if hv then
+ math.horiz_variants = hv.variants
+ local p = hv.parts
+ if p then
+ if #p>0 then
+ for i=1,#p do
+ local pi = p[i]
+ pi.glyph = unicodes[pi.component] or 0
+ end
+ math.horiz_parts = p
+ end
+ end
+ local ic = hv.italic_correction
+ if ic and ic ~= 0 then
+ math.horiz_italic_correction = ic
+ end
+ glyph.horiz_variants = nil
+ end
+ if vv then
+ local uc = unicodes[index]
+ math.vert_variants = vv.variants
+ local p = vv.parts
+ if p then
+ if #p>0 then
+ for i=1,#p do
+ local pi = p[i]
+ pi.glyph = unicodes[pi.component] or 0
+ end
+ math.vert_parts = p
+ end
+ end
+ local ic = vv.italic_correction
+ if ic and ic ~= 0 then
+ math.vert_italic_correction = ic
+ end
+ glyph.vert_variants = nil
+ end
+ local ic = glyph.italic_correction
+ if ic then
+ if ic ~= 0 then
+ math.italic_correction = ic
+ end
+ glyph.italic_correction = nil
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers["share widths"] = function(data,filename)
+ local glyphs = data.glyphs
+ local widths = { }
+ for index, glyph in next, glyphs do
+ local width = glyph.width
+ widths[width] = (widths[width] or 0) + 1
+ end
+ -- share width for cjk fonts
+ local wd, most = 0, 1
+ for k,v in next, widths do
+ if v > most then
+ wd, most = k, v
+ end
+ end
+ if most > 1000 then
+ if trace_loading then
+ logs.report("load otf", "most common width: %s (%s times), sharing (cjk font)",wd,most)
+ end
+ for k, v in next, glyphs do
+ if v.width == wd then
+ v.width = nil
+ end
+ end
+ data.luatex.defaultwidth = wd
+ end
+end
+
+-- kern: ttf has a table with kerns
+
+--~ otf.enhancers["reorganize kerns"] = function(data,filename)
+--~ local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
+--~ local mkdone = false
+--~ for index, glyph in next, data.glyphs do
+--~ if glyph.kerns then
+--~ local mykerns = { }
+--~ for k,v in next, glyph.kerns do
+--~ local vc, vo, vl = v.char, v.off, v.lookup
+--~ if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
+--~ local uvc = unicodes[vc]
+--~ if not uvc then
+--~ if trace_loading then
+--~ logs.report("load otf","problems with unicode %s of kern %s at glyph %s",vc,k,index)
+--~ end
+--~ else
+--~ if type(vl) ~= "table" then
+--~ vl = { vl }
+--~ end
+--~ for l=1,#vl do
+--~ local vll = vl[l]
+--~ local mkl = mykerns[vll]
+--~ if not mkl then
+--~ mkl = { }
+--~ mykerns[vll] = mkl
+--~ end
+--~ if type(uvc) == "table" then
+--~ for u=1,#uvc do
+--~ mkl[uvc[u]] = vo
+--~ end
+--~ else
+--~ mkl[uvc] = vo
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+--~ glyph.mykerns = mykerns
+--~ glyph.kerns = nil -- saves space and time
+--~ mkdone = true
+--~ end
+--~ end
+--~ if trace_loading and mkdone then
+--~ logs.report("load otf", "replacing 'kerns' tables by 'mykerns' tables")
+--~ end
+--~ if data.kerns then
+--~ if trace_loading then
+--~ logs.report("load otf", "removing global 'kern' table")
+--~ end
+--~ data.kerns = nil
+--~ end
+--~ local dgpos = data.gpos
+--~ if dgpos then
+--~ for gp=1,#dgpos do
+--~ local gpos = dgpos[gp]
+--~ local subtables = gpos.subtables
+--~ if subtables then
+--~ for s=1,#subtables do
+--~ local subtable = subtables[s]
+--~ local kernclass = subtable.kernclass -- name is inconsistent with anchor_classes
+--~ if kernclass then -- the next one is quite slow
+--~ for k=1,#kernclass do
+--~ local kcl = kernclass[k]
+--~ local firsts, seconds, offsets, lookups = kcl.firsts, kcl.seconds, kcl.offsets, kcl.lookup -- singular
+--~ if type(lookups) ~= "table" then
+--~ lookups = { lookups }
+--~ end
+--~ for l=1,#lookups do
+--~ local lookup = lookups[l]
+--~ -- weird, as maxfirst and maxseconds can have holes
+--~ local maxfirsts, maxseconds = getn(firsts), getn(seconds)
+--~ if trace_loading then
+--~ logs.report("load otf", "adding kernclass %s with %s times %s pairs",lookup, maxfirsts, maxseconds)
+--~ end
+--~ for fk, fv in next, firsts do
+--~ for first in gmatch(fv,"[^ ]+") do
+--~ local first_unicode = unicodes[first]
+--~ if type(first_unicode) == "number" then
+--~ first_unicode = { first_unicode }
+--~ end
+--~ for f=1,#first_unicode do
+--~ local glyph = glyphs[mapmap[first_unicode[f]]]
+--~ if glyph then
+--~ local mykerns = glyph.mykerns
+--~ if not mykerns then
+--~ mykerns = { } -- unicode indexed !
+--~ glyph.mykerns = mykerns
+--~ end
+--~ local lookupkerns = mykerns[lookup]
+--~ if not lookupkerns then
+--~ lookupkerns = { }
+--~ mykerns[lookup] = lookupkerns
+--~ end
+--~ for sk, sv in next, seconds do
+--~ local offset = offsets[(fk-1) * maxseconds + sk]
+--~ --~ local offset = offsets[sk] -- (fk-1) * maxseconds + sk]
+--~ for second in gmatch(sv,"[^ ]+") do
+--~ local second_unicode = unicodes[second]
+--~ if type(second_unicode) == "number" then
+--~ lookupkerns[second_unicode] = offset
+--~ else
+--~ for s=1,#second_unicode do
+--~ lookupkerns[second_unicode[s]] = offset
+--~ end
+--~ end
+--~ end
+--~ end
+--~ elseif trace_loading then
+--~ logs.report("load otf", "no glyph data for U+%04X", first_unicode[f])
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+--~ subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
+--~ subtable.kernclass = { }
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+
+otf.enhancers["reorganize kerns"] = function(data,filename)
+ local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
+ local mkdone = false
+ for index, glyph in next, data.glyphs do
+ if glyph.kerns then
+ local mykerns = { }
+ for k,v in next, glyph.kerns do
+ local vc, vo, vl = v.char, v.off, v.lookup
+ if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
+ local uvc = unicodes[vc]
+ if not uvc then
+ if trace_loading then
+ logs.report("load otf","problems with unicode %s of kern %s at glyph %s",vc,k,index)
+ end
+ else
+ if type(vl) ~= "table" then
+ vl = { vl }
+ end
+ for l=1,#vl do
+ local vll = vl[l]
+ local mkl = mykerns[vll]
+ if not mkl then
+ mkl = { }
+ mykerns[vll] = mkl
+ end
+ if type(uvc) == "table" then
+ for u=1,#uvc do
+ mkl[uvc[u]] = vo
+ end
+ else
+ mkl[uvc] = vo
+ end
+ end
+ end
+ end
+ end
+ glyph.mykerns = mykerns
+ glyph.kerns = nil -- saves space and time
+ mkdone = true
+ end
+ end
+ if trace_loading and mkdone then
+ logs.report("load otf", "replacing 'kerns' tables by 'mykerns' tables")
+ end
+ if data.kerns then
+ if trace_loading then
+ logs.report("load otf", "removing global 'kern' table")
+ end
+ data.kerns = nil
+ end
+ local dgpos = data.gpos
+ if dgpos then
+ local separator = lpeg.P(" ")
+ local other = ((1 - separator)^0) / unicodes
+ local splitter = lpeg.Ct(other * (separator * other)^0)
+ for gp=1,#dgpos do
+ local gpos = dgpos[gp]
+ local subtables = gpos.subtables
+ if subtables then
+ for s=1,#subtables do
+ local subtable = subtables[s]
+ local kernclass = subtable.kernclass -- name is inconsistent with anchor_classes
+ if kernclass then -- the next one is quite slow
+ for k=1,#kernclass do
+ local kcl = kernclass[k]
+ local firsts, seconds, offsets, lookups = kcl.firsts, kcl.seconds, kcl.offsets, kcl.lookup -- singular
+ if type(lookups) ~= "table" then
+ lookups = { lookups }
+ end
+ local split = { }
+ for l=1,#lookups do
+ local lookup = lookups[l]
+ -- weird, as maxfirst and maxseconds can have holes, first seems to be indexed, seconds starts at 2
+ local maxfirsts, maxseconds = getn(firsts), getn(seconds)
+ for _, s in next, firsts do
+ split[s] = split[s] or lpegmatch(splitter,s)
+ end
+ for _, s in next, seconds do
+ split[s] = split[s] or lpegmatch(splitter,s)
+ end
+ if trace_loading then
+ logs.report("load otf", "adding kernclass %s with %s times %s pairs",lookup, maxfirsts, maxseconds)
+ end
+ local function do_it(fk,first_unicode)
+ local glyph = glyphs[mapmap[first_unicode]]
+ if glyph then
+ local mykerns = glyph.mykerns
+ if not mykerns then
+ mykerns = { } -- unicode indexed !
+ glyph.mykerns = mykerns
+ end
+ local lookupkerns = mykerns[lookup]
+ if not lookupkerns then
+ lookupkerns = { }
+ mykerns[lookup] = lookupkerns
+ end
+ local baseoffset = (fk-1) * maxseconds
+ for sk=2,maxseconds do
+ local sv = seconds[sk]
+ local offset = offsets[baseoffset + sk]
+ --~ local offset = offsets[sk] -- (fk-1) * maxseconds + sk]
+ local splt = split[sv]
+ if splt then
+ for i=1,#splt do
+ local second_unicode = splt[i]
+ if tonumber(second_unicode) then
+ lookupkerns[second_unicode] = offset
+ else
+ for s=1,#second_unicode do
+ lookupkerns[second_unicode[s]] = offset
+ end
+ end
+ end
+ end
+ end
+ elseif trace_loading then
+ logs.report("load otf", "no glyph data for U+%04X", first_unicode)
+ end
+ end
+ for fk=1,#firsts do
+ local fv = firsts[fk]
+ local splt = split[fv]
+ if splt then
+ for i=1,#splt do
+ local first_unicode = splt[i]
+ if tonumber(first_unicode) then
+ do_it(fk,first_unicode)
+ else
+ for f=1,#first_unicode do
+ do_it(fk,first_unicode[f])
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
+ subtable.kernclass = { }
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers["strip not needed data"] = function(data,filename)
+ local verbose = fonts.verbose
+ local int_to_uni = data.luatex.unicodes
+ for k, v in next, data.glyphs do
+ local d = v.dependents
+ if d then v.dependents = nil end
+ local a = v.altuni
+ if a then v.altuni = nil end
+ if verbose then
+ local code = int_to_uni[k]
+ -- looks like this is done twice ... bug?
+ if code then
+ local vu = v.unicode
+ if not vu then
+ v.unicode = code
+ elseif type(vu) == "table" then
+ if vu[#vu] == code then
+ -- weird
+ else
+ vu[#vu+1] = code
+ end
+ elseif vu ~= code then
+ v.unicode = { vu, code }
+ end
+ end
+ else
+ v.unicode = nil
+ v.index = nil
+ end
+ end
+ data.luatex.comment = "Glyph tables have their original index. When present, mykern tables are indexed by unicode."
+ data.map = nil
+ data.names = nil -- funny names for editors
+ data.glyphcnt = nil
+ data.glyphmax = nil
+ if true then
+ data.gpos = nil
+ data.gsub = nil
+ data.anchor_classes = nil
+ end
+end
+
+otf.enhancers["migrate metadata"] = function(data,filename)
+ local global_fields = otf.tables.global_fields
+ local metadata = { }
+ for k,v in next, data do
+ if not global_fields[k] then
+ metadata[k] = v
+ data[k] = nil
+ end
+ end
+ data.metadata = metadata
+ -- goodies
+ local pfminfo = data.pfminfo
+ metadata.isfixedpitch = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose["proportion"] == "Monospaced")
+ metadata.charwidth = pfminfo and pfminfo.avgwidth
+end
+
+local private_math_parameters = {
+ "FractionDelimiterSize",
+ "FractionDelimiterDisplayStyleSize",
+}
+
+otf.enhancers["check math parameters"] = function(data,filename)
+ local mathdata = data.metadata.math
+ if mathdata then
+ for m=1,#private_math_parameters do
+ local pmp = private_math_parameters[m]
+ if not mathdata[pmp] then
+ if trace_loading then
+ logs.report("load otf", "setting math parameter '%s' to 0", pmp)
+ end
+ mathdata[pmp] = 0
+ end
+ end
+ end
+end
+
+otf.enhancers["flatten glyph lookups"] = function(data,filename)
+ for k, v in next, data.glyphs do
+ local lookups = v.lookups
+ if lookups then
+ for kk, vv in next, lookups do
+ for kkk=1,#vv do
+ local vvv = vv[kkk]
+ local s = vvv.specification
+ if s then
+ local t = vvv.type
+ if t == "ligature" then
+ vv[kkk] = { "ligature", s.components, s.char }
+ elseif t == "alternate" then
+ vv[kkk] = { "alternate", s.components }
+ elseif t == "substitution" then
+ vv[kkk] = { "substitution", s.variant }
+ elseif t == "multiple" then
+ vv[kkk] = { "multiple", s.components }
+ elseif t == "position" then
+ vv[kkk] = { "position", { s.x or 0, s.y or 0, s.h or 0, s.v or 0 } }
+ elseif t == "pair" then
+ local one, two, paired = s.offsets[1], s.offsets[2], s.paired or ""
+ if one then
+ if two then
+ vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
+ else
+ vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
+ end
+ else
+ if two then
+ vv[kkk] = { "pair", paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
+ else
+ vv[kkk] = { "pair", paired }
+ end
+ end
+ else
+ if trace_loading then
+ logs.report("load otf", "flattening needed, report to context list")
+ end
+ for a, b in next, s do
+ if trace_loading and vvv[a] then
+ logs.report("load otf", "flattening conflict, report to context list")
+ end
+ vvv[a] = b
+ end
+ vvv.specification = nil
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers["simplify glyph lookups"] = function(data,filename)
+ for k, v in next, data.glyphs do
+ local lookups = v.lookups
+ if lookups then
+ local slookups, mlookups
+ for kk, vv in next, lookups do
+ if #vv == 1 then
+ if not slookups then
+ slookups = { }
+ v.slookups = slookups
+ end
+ slookups[kk] = vv[1]
+ else
+ if not mlookups then
+ mlookups = { }
+ v.mlookups = mlookups
+ end
+ mlookups[kk] = vv
+ end
+ end
+ v.lookups = nil
+ end
+ end
+end
+
+otf.enhancers["flatten anchor tables"] = function(data,filename)
+ for k, v in next, data.glyphs do
+ if v.anchors then
+ for kk, vv in next, v.anchors do
+ for kkk, vvv in next, vv do
+ if vvv.x or vvv.y then
+ vv[kkk] = { vvv.x or 0, vvv.y or 0 }
+ else
+ for kkkk=1,#vvv do
+ local vvvv = vvv[kkkk]
+ vvv[kkkk] = { vvvv.x or 0, vvvv.y or 0 }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers["flatten feature tables"] = function(data,filename)
+ -- is this needed? do we still use them at all?
+ for _, tag in next, otf.glists do
+ if data[tag] then
+ if trace_loading then
+ logs.report("load otf", "flattening %s table", tag)
+ end
+ for k, v in next, data[tag] do
+ local features = v.features
+ if features then
+ for kk=1,#features do
+ local vv = features[kk]
+ local t = { }
+ local scripts = vv.scripts
+ for kkk=1,#scripts do
+ local vvv = scripts[kkk]
+ t[vvv.script] = vvv.langs
+ end
+ vv.scripts = t
+ end
+ end
+ end
+ end
+ end
+end
+
+otf.enhancers.patches = otf.enhancers.patches or { }
+
+otf.enhancers["patch bugs"] = function(data,filename)
+ local basename = file.basename(lower(filename))
+ for pattern, action in next, otf.enhancers.patches do
+ if find(basename,pattern) then
+ action(data,filename)
+ end
+ end
+end
+
+-- tex features
+
+fonts.otf.enhancers["enrich with features"] = function(data,filename)
+ -- later, ctx only
+end
+
+function otf.features.register(name,default)
+ otf.features.list[#otf.features.list+1] = name
+ otf.features.default[name] = default
+end
+
+-- for context this will become a task handler
+
+function otf.set_features(tfmdata,features)
+ local processes = { }
+ if features and next(features) then
+ local lists = { -- why local
+ fonts.triggers,
+ fonts.processors,
+ fonts.manipulators,
+ }
+ local mode = tfmdata.mode or fonts.mode -- or features.mode
+ local initializers = fonts.initializers
+ local fi = initializers[mode]
+ if fi then
+ local fiotf = fi.otf
+ if fiotf then
+ local done = { }
+ for l=1,4 do
+ local list = lists[l]
+ if list then
+ for i=1,#list do
+ local f = list[i]
+ local value = features[f]
+ if value and fiotf[f] then -- brr
+ if not done[f] then -- so, we can move some to triggers
+ if trace_features then
+ logs.report("define otf","initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown', tfmdata.fullname or 'unknown')
+ end
+ fiotf[f](tfmdata,value) -- can set mode (no need to pass otf)
+ mode = tfmdata.mode or fonts.mode -- keep this, mode can be set local !
+ local im = initializers[mode]
+ if im then
+ fiotf = initializers[mode].otf
+ end
+ done[f] = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ local fm = fonts.methods[mode] -- todo: zonder node/mode otf/...
+ if fm then
+ local fmotf = fm.otf
+ if fmotf then
+ for l=1,4 do
+ local list = lists[l]
+ if list then
+ for i=1,#list do
+ local f = list[i]
+ if fmotf[f] then -- brr
+ if trace_features then
+ logs.report("define otf","installing feature handler %s for mode %s for font %s",f,mode or 'unknown', tfmdata.fullname or 'unknown')
+ end
+ processes[#processes+1] = fmotf[f]
+ end
+ end
+ end
+ end
+ end
+ else
+ -- message
+ end
+ end
+ return processes, features
+end
+
+function otf.otf_to_tfm(specification)
+ local name = specification.name
+ local sub = specification.sub
+ local filename = specification.filename
+ local format = specification.format
+ local features = specification.features.normal
+ local cache_id = specification.hash
+ local tfmdata = containers.read(tfm.cache(),cache_id)
+--~ print(cache_id)
+ if not tfmdata then
+ local otfdata = otf.load(filename,format,sub,features and features.featurefile)
+ if otfdata and next(otfdata) then
+ otfdata.shared = otfdata.shared or {
+ featuredata = { },
+ anchorhash = { },
+ initialized = false,
+ }
+ tfmdata = otf.copy_to_tfm(otfdata,cache_id)
+ if tfmdata and next(tfmdata) then
+ tfmdata.unique = tfmdata.unique or { }
+ tfmdata.shared = tfmdata.shared or { } -- combine
+ local shared = tfmdata.shared
+ shared.otfdata = otfdata
+ shared.features = features -- default
+ shared.dynamics = { }
+ shared.processes = { }
+ shared.set_dynamics = otf.set_dynamics -- fast access and makes other modules independent
+ -- this will be done later anyway, but it's convenient to have
+ -- them already for fast access
+ tfmdata.luatex = otfdata.luatex
+ tfmdata.indices = otfdata.luatex.indices
+ tfmdata.unicodes = otfdata.luatex.unicodes
+ tfmdata.marks = otfdata.luatex.marks
+ tfmdata.originals = otfdata.luatex.originals
+ tfmdata.changed = { }
+ tfmdata.has_italic = otfdata.metadata.has_italic
+ if not tfmdata.language then tfmdata.language = 'dflt' end
+ if not tfmdata.script then tfmdata.script = 'dflt' end
+ shared.processes, shared.features = otf.set_features(tfmdata,fonts.define.check(features,otf.features.default))
+ end
+ end
+ containers.write(tfm.cache(),cache_id,tfmdata)
+ end
+ return tfmdata
+end
+
+--~ {
+--~ ['boundingbox']={ 95, -458, 733, 1449 },
+--~ ['class']="base",
+--~ ['name']="braceleft",
+--~ ['unicode']=123,
+--~ ['vert_variants']={
+--~ ['italic_correction']=0,
+--~ ['parts']={
+--~ { ['component']="uni23A9", ['endConnectorLength']=1000, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=0, }, -- bot
+--~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
+--~ { ['component']="uni23A8", ['endConnectorLength']=1000, ['fullAdvance']=4688, ['is_extender']=0, ['startConnectorLength']=1000, }, -- mid
+--~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
+--~ { ['component']="uni23A7", ['endConnectorLength']=0, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=1000, }, -- top
+--~ },
+--~ ['variants']="braceleft braceleft.vsize1 braceleft.vsize2 braceleft.vsize3 braceleft.vsize4 braceleft.vsize5 braceleft.vsize6 braceleft.vsize7",
+--~ },
+--~ ['width']=793,
+--~ },
+
+-- the first version made a top/mid/not extensible table, now we just pass on the variants data
+-- and deal with it in the tfm scaler (there is no longer an extensible table anyway)
+
+-- we cannot share descriptions as virtual fonts might extend them (ok, we could
+-- use a cache with a hash
+
+fonts.formats.dfont = "truetype"
+fonts.formats.ttc = "truetype"
+fonts.formats.ttf = "truetype"
+fonts.formats.otf = "opentype"
+
+function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder the tma to unicode (nasty due to one->many)
+ if data then
+ local glyphs, pfminfo, metadata = data.glyphs or { }, data.pfminfo or { }, data.metadata or { }
+ local luatex = data.luatex
+ local unicodes = luatex.unicodes -- names to unicodes
+ local indices = luatex.indices
+ local characters, parameters, math_parameters, descriptions = { }, { }, { }, { }
+ local designsize = metadata.designsize or metadata.design_size or 100
+ if designsize == 0 then
+ designsize = 100
+ end
+ local spaceunits = 500
+ -- indices maps from unicodes to indices
+ for u, i in next, indices do
+ characters[u] = { } -- we need this because for instance we add protruding info and loop over characters
+ descriptions[u] = glyphs[i]
+ end
+ -- math
+ if metadata.math then
+ -- parameters
+ for name, value in next, metadata.math do
+ math_parameters[name] = value
+ end
+ -- we could use a subset
+ for u, char in next, characters do
+ local d = descriptions[u]
+ local m = d.math
+ -- we have them shared because that packs nicer
+ -- we could prepare the variants and keep 'm in descriptions
+ if m then
+ local variants = m.horiz_variants
+ if variants then
+ local c = char
+ for n in gmatch(variants,"[^ ]+") do
+ local un = unicodes[n]
+ if un and u ~= un then
+ c.next = un
+ c = characters[un]
+ end
+ end
+ c.horiz_variants = m.horiz_parts
+ else
+ local variants = m.vert_variants
+ if variants then
+ local c = char
+ for n in gmatch(variants,"[^ ]+") do
+ local un = unicodes[n]
+ if un and u ~= un then
+ c.next = un
+ c = characters[un]
+ end
+ end
+ c.vert_variants = m.vert_parts
+ c.vert_italic_correction = m.vert_italic_correction
+ end
+ end
+ local kerns = m.kerns
+ if kerns then
+ char.mathkerns = kerns
+ end
+ end
+ end
+ end
+ -- end math
+ local endash, emdash, space = 0x20, 0x2014, "space" -- unicodes['space'], unicodes['emdash']
+ if metadata.isfixedpitch then
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width, "emdash"
+ end
+ if not spaceunits and metadata.charwidth then
+ spaceunits, spacer = metadata.charwidth, "charwidth"
+ end
+ else
+ if descriptions[endash] then
+ spaceunits, spacer = descriptions[endash].width, "space"
+ end
+ if not spaceunits and descriptions[emdash] then
+ spaceunits, spacer = descriptions[emdash].width/2, "emdash/2"
+ end
+ if not spaceunits and metadata.charwidth then
+ spaceunits, spacer = metadata.charwidth, "charwidth"
+ end
+ end
+ spaceunits = tonumber(spaceunits) or tfm.units/2 -- 500 -- brrr
+ -- we need a runtime lookup because of running from cdrom or zip, brrr (shouldn't we use the basename then?)
+ local filename = fonts.tfm.checked_filename(luatex)
+ local fontname = metadata.fontname
+ local fullname = metadata.fullname or fontname
+ local cidinfo = data.cidinfo
+ local units = metadata.units_per_em or 1000
+ --
+ cidinfo.registry = cidinfo and cidinfo.registry or "" -- weird here, fix upstream
+ --
+ parameters.slant = 0
+ parameters.space = spaceunits -- 3.333 (cmr10)
+ parameters.space_stretch = units/2 -- 500 -- 1.666 (cmr10)
+ parameters.space_shrink = 1*units/3 -- 333 -- 1.111 (cmr10)
+ parameters.x_height = 2*units/5 -- 400
+ parameters.quad = units -- 1000
+ if spaceunits < 2*units/5 then
+ -- todo: warning
+ end
+ local italicangle = metadata.italicangle
+ if italicangle then -- maybe also in afm _
+ parameters.slant = parameters.slant - math.round(math.tan(italicangle*math.pi/180))
+ end
+ if metadata.isfixedpitch then
+ parameters.space_stretch = 0
+ parameters.space_shrink = 0
+ elseif otf.syncspace then --
+ parameters.space_stretch = spaceunits/2
+ parameters.space_shrink = spaceunits/3
+ end
+ parameters.extra_space = parameters.space_shrink -- 1.111 (cmr10)
+ if pfminfo.os2_xheight and pfminfo.os2_xheight > 0 then
+ parameters.x_height = pfminfo.os2_xheight
+ else
+ local x = 0x78 -- unicodes['x']
+ if x then
+ local x = descriptions[x]
+ if x then
+ parameters.x_height = x.height
+ end
+ end
+ end
+ --
+ return {
+ characters = characters,
+ parameters = parameters,
+ math_parameters = math_parameters,
+ descriptions = descriptions,
+ indices = indices,
+ unicodes = unicodes,
+ type = "real",
+ direction = 0,
+ boundarychar_label = 0,
+ boundarychar = 65536,
+ designsize = (designsize/10)*65536,
+ spacer = "500 units",
+ encodingbytes = 2,
+ filename = filename,
+ fontname = fontname,
+ fullname = fullname,
+ psname = fontname or fullname,
+ name = filename or fullname,
+ units = units,
+ format = fonts.fontformat(filename,"opentype"),
+ cidinfo = cidinfo,
+ ascender = abs(metadata.ascent or 0),
+ descender = abs(metadata.descent or 0),
+ spacer = spacer,
+ italicangle = italicangle,
+ }
+ else
+ return nil
+ end
+end
+
+otf.features.register('mathsize')
+
+function tfm.read_from_open_type(specification)
+ local tfmtable = otf.otf_to_tfm(specification)
+ if tfmtable then
+ local otfdata = tfmtable.shared.otfdata
+ tfmtable.name = specification.name
+ tfmtable.sub = specification.sub
+ local s = specification.size
+ local m = otfdata.metadata.math
+ if m then
+ -- this will move to a function
+ local f = specification.features
+ if f then
+ local f = f.normal
+ if f and f.mathsize then
+ local mathsize = specification.mathsize or 0
+ if mathsize == 2 then
+ local p = m.ScriptPercentScaleDown
+ if p then
+ local ps = p * specification.textsize / 100
+ if trace_math then
+ logs.report("define font","asked script size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100)
+ end
+ s = ps
+ end
+ elseif mathsize == 3 then
+ local p = m.ScriptScriptPercentScaleDown
+ if p then
+ local ps = p * specification.textsize / 100
+ if trace_math then
+ logs.report("define font","asked scriptscript size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100)
+ end
+ s = ps
+ end
+ end
+ end
+ end
+ end
+ tfmtable = tfm.scale(tfmtable,s,specification.relativeid)
+ if tfm.fontname_mode == "specification" then
+ -- not to be used in context !
+ local specname = specification.specification
+ if specname then
+ tfmtable.name = specname
+ if trace_defining then
+ logs.report("define font","overloaded fontname: '%s'",specname)
+ end
+ end
+ end
+ fonts.logger.save(tfmtable,file.extname(specification.filename),specification)
+ end
+--~ print(tfmtable.fullname)
+ return tfmtable
+end
+
+-- helpers
+
+function otf.collect_lookups(otfdata,kind,script,language)
+ -- maybe store this in the font
+ local sequences = otfdata.luatex.sequences
+ if sequences then
+ local featuremap, featurelist = { }, { }
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local features = sequence.features
+ features = features and features[kind]
+ features = features and (features[script] or features[default] or features[wildcard])
+ features = features and (features[language] or features[default] or features[wildcard])
+ if features then
+ local subtables = sequence.subtables
+ if subtables then
+ for s=1,#subtables do
+ local ss = subtables[s]
+ if not featuremap[s] then
+ featuremap[ss] = true
+ featurelist[#featurelist+1] = ss
+ end
+ end
+ end
+ end
+ end
+ if #featurelist > 0 then
+ return featuremap, featurelist
+ end
+ end
+ return nil, nil
+end
diff --git a/tex/context/base/font-oti.lua b/tex/context/base/font-oti.lua
new file mode 100644
index 000000000..4cb270626
--- /dev/null
+++ b/tex/context/base/font-oti.lua
@@ -0,0 +1,57 @@
+if not modules then modules = { } end modules ['font-oti'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- i need to check features=yes|no also in relation to hashing
+
+local lower = string.lower
+
+local otf = fonts.otf
+
+otf.default_language = 'latn'
+otf.default_script = 'dflt'
+
+local languages = otf.tables.languages
+local scripts = otf.tables.scripts
+
+function otf.features.language(tfmdata,value)
+ if value then
+ value = lower(value)
+ if languages[value] then
+ tfmdata.language = value
+ end
+ end
+end
+
+function otf.features.script(tfmdata,value)
+ if value then
+ value = lower(value)
+ if scripts[value] then
+ tfmdata.script = value
+ end
+ end
+end
+
+function otf.features.mode(tfmdata,value)
+ if value then
+ tfmdata.mode = lower(value)
+ end
+end
+
+fonts.initializers.base.otf.language = otf.features.language
+fonts.initializers.base.otf.script = otf.features.script
+fonts.initializers.base.otf.mode = otf.features.mode
+fonts.initializers.base.otf.method = otf.features.mode
+
+fonts.initializers.node.otf.language = otf.features.language
+fonts.initializers.node.otf.script = otf.features.script
+fonts.initializers.node.otf.mode = otf.features.mode
+fonts.initializers.node.otf.method = otf.features.mode
+
+otf.features.register("features",true) -- we always do features
+table.insert(fonts.processors,"features") -- we need a proper function for doing this
+
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
new file mode 100644
index 000000000..d4f89adc6
--- /dev/null
+++ b/tex/context/base/font-otn.lua
@@ -0,0 +1,2660 @@
+if not modules then modules = { } end modules ['font-otn'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this is still somewhat preliminary and it will get better in due time;
+-- much functionality could only be implemented thanks to the husayni font
+-- of Idris Samawi Hamid to who we dedicate this module.
+
+-- I'm in the process of cleaning up the code (which happens in another
+-- file) so don't rely on things staying the same.
+
+-- some day when we can jit this, we can use more functions
+
+-- we can use more lpegs when lpeg is extended with function args and so
+-- resolving to unicode does not gain much
+
+-- in retrospect it always looks easy but believe it or not, it took a lot
+-- of work to get proper open type support done: buggy fonts, fuzzy specs,
+-- special made testfonts, many skype sessions between taco, idris and me,
+-- torture tests etc etc ... unfortunately the code does not show how much
+-- time it took ...
+
+-- todo:
+--
+-- kerning is probably not yet ok for latin around dics nodes
+-- extension infrastructure (for usage out of context)
+-- sorting features according to vendors/renderers
+-- alternative loop quitters
+-- check cursive and r2l
+-- find out where ignore-mark-classes went
+-- remove unused tables
+-- slide tail (always glue at the end so only needed once
+-- default features (per language, script)
+-- cleanup kern(class) code, remove double info
+-- handle positions (we need example fonts)
+-- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
+
+--[[ldx--
+
This module is a bit more split up that I'd like but since we also want to test
+with plain it has to be so. This module is part of
+and discussion about improvements and functionality mostly happens on the
+ mailing list.
+
+
The specification of OpenType is kind of vague. Apart from a lack of a proper
+free specifications there's also the problem that Microsoft and Adobe
+may have their own interpretation of how and in what order to apply features.
+In general the Microsoft website has more detailed specifications and is a
+better reference. There is also some information in the FontForge help files.
+
+
Because there is so much possible, fonts might contain bugs and/or be made to
+work with certain rederers. These may evolve over time which may have the side
+effect that suddenly fonts behave differently.
+
+
After a lot of experiments (mostly by Taco, me and Idris) we're now at yet another
+implementation. Of course all errors are mine and of course the code can be
+improved. There are quite some optimizations going on here and processing speed
+is currently acceptable. Not all functions are implemented yet, often because I
+lack the fonts for testing. Many scripts are not yet supported either, but I will
+look into them as soon as users ask for it.
+
+
Because there are different interpretations possible, I will extend the code
+with more (configureable) variants. I can also add hooks for users so that they can
+write their own extensions.
+
+
Glyphs are indexed not by unicode but in their own way. This is because there is no
+relationship with unicode at all, apart from the fact that a font might cover certain
+ranges of characters. One character can have multiple shapes. However, at the
+ end we use unicode so and all extra glyphs are mapped into a private
+space. This is needed because we need to access them and has to include
+then in the output eventually.
+
+
The raw table as it coms from gets reorganized in to fit out needs.
+In that table is packed (similar tables are shared) and cached on disk
+so that successive runs can use the optimized table (after loading the table is
+unpacked). The flattening code used later is a prelude to an even more compact table
+format (and as such it keeps evolving).
+
+
This module is sparsely documented because it is a moving target. The table format
+of the reader changes and we experiment a lot with different methods for supporting
+features.
+
+
As with the code, we may decide to store more information in the
+ table.
+
+
Incrementing the version number will force a re-cache. We jump the number by one
+when there's a fix in the library or code that
+results in different tables.
+--ldx]]--
+
+-- action handler chainproc chainmore comment
+--
+-- gsub_single ok ok ok
+-- gsub_multiple ok ok not implemented yet
+-- gsub_alternate ok ok not implemented yet
+-- gsub_ligature ok ok ok
+-- gsub_context ok --
+-- gsub_contextchain ok --
+-- gsub_reversecontextchain ok --
+-- chainsub -- ok
+-- reversesub -- ok
+-- gpos_mark2base ok ok
+-- gpos_mark2ligature ok ok
+-- gpos_mark2mark ok ok
+-- gpos_cursive ok untested
+-- gpos_single ok ok
+-- gpos_pair ok ok
+-- gpos_context ok --
+-- gpos_contextchain ok --
+--
+-- actions:
+--
+-- handler : actions triggered by lookup
+-- chainproc : actions triggered by contextual lookup
+-- chainmore : multiple substitutions triggered by contextual lookup (e.g. fij -> f + ij)
+--
+-- remark: the 'not implemented yet' variants will be done when we have fonts that use them
+-- remark: we need to check what to do with discretionaries
+
+local concat, insert, remove = table.concat, table.insert, table.remove
+local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
+local type, next, tonumber, tostring = type, next, tonumber, tostring
+local lpegmatch = lpeg.match
+
+local otf = fonts.otf
+local tfm = fonts.tfm
+
+local trace_lookups = false trackers.register("otf.lookups", function(v) trace_lookups = v end)
+local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end)
+local trace_contexts = false trackers.register("otf.contexts", function(v) trace_contexts = v end)
+local trace_marks = false trackers.register("otf.marks", function(v) trace_marks = v end)
+local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
+local trace_cursive = false trackers.register("otf.cursive", function(v) trace_cursive = v end)
+local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
+local trace_bugs = false trackers.register("otf.bugs", function(v) trace_bugs = v end)
+local trace_details = false trackers.register("otf.details", function(v) trace_details = v end)
+local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
+local trace_steps = false trackers.register("otf.steps", function(v) trace_steps = v end)
+local trace_skips = false trackers.register("otf.skips", function(v) trace_skips = v end)
+local trace_directions = false trackers.register("otf.directions", function(v) trace_directions = v end)
+
+trackers.register("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
+trackers.register("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
+
+trackers.register("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
+trackers.register("otf.positions","otf.marks,otf.kerns,otf.cursive")
+trackers.register("otf.actions","otf.replacements,otf.positions")
+trackers.register("otf.injections","nodes.injections")
+
+trackers.register("*otf.sample","otf.steps,otf.actions,otf.analyzing")
+
+local insert_node_after = node.insert_after
+local delete_node = nodes.delete
+local copy_node = node.copy
+local find_node_tail = node.tail or node.slide
+local set_attribute = node.set_attribute
+local has_attribute = node.has_attribute
+
+local zwnj = 0x200C
+local zwj = 0x200D
+local wildcard = "*"
+local default = "dflt"
+
+local split_at_space = lpeg.splitters[" "] or lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway
+
+local glyph = node.id('glyph')
+local glue = node.id('glue')
+local kern = node.id('kern')
+local disc = node.id('disc')
+local whatsit = node.id('whatsit')
+
+local state = attributes.private('state')
+local markbase = attributes.private('markbase')
+local markmark = attributes.private('markmark')
+local markdone = attributes.private('markdone')
+local cursbase = attributes.private('cursbase')
+local curscurs = attributes.private('curscurs')
+local cursdone = attributes.private('cursdone')
+local kernpair = attributes.private('kernpair')
+
+local set_mark = nodes.set_mark
+local set_cursive = nodes.set_cursive
+local set_kern = nodes.set_kern
+local set_pair = nodes.set_pair
+
+local markonce = true
+local cursonce = true
+local kernonce = true
+
+local fontdata = fonts.ids
+
+otf.features.process = { }
+
+-- we share some vars here, after all, we have no nested lookups and
+-- less code
+
+local tfmdata = false
+local otfdata = false
+local characters = false
+local descriptions = false
+local marks = false
+local indices = false
+local unicodes = false
+local currentfont = false
+local lookuptable = false
+local anchorlookups = false
+local handlers = { }
+local rlmode = 0
+local featurevalue = false
+
+-- we cheat a bit and assume that a font,attr combination are kind of ranged
+
+local context_setups = fonts.define.specify.context_setups
+local context_numbers = fonts.define.specify.context_numbers
+local context_merged = fonts.define.specify.context_merged
+
+-- we cannot optimize with "start = first_character(head)" because then we don't
+-- know which rlmode we're in which messes up cursive handling later on
+--
+-- head is always a whatsit so we can safely assume that head is not changed
+
+local special_attributes = {
+ init = 1,
+ medi = 2,
+ fina = 3,
+ isol = 4
+}
+
+-- we use this for special testing and documentation
+
+local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
+local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
+local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ logs.report("otf direct",...)
+end
+local function logwarning(...)
+ logs.report("otf direct",...)
+end
+
+local function gref(n)
+ if type(n) == "number" then
+ local description = descriptions[n]
+ local name = description and description.name
+ if name then
+ return format("U+%04X (%s)",n,name)
+ else
+ return format("U+%04X",n)
+ end
+ elseif not n then
+ return ""
+ else
+ local num, nam = { }, { }
+ for i=1,#n do
+ local ni = n[i]
+ num[#num+1] = format("U+%04X",ni)
+ local dni = descriptions[ni]
+ nam[#num] = (dni and dni.name) or "?"
+ end
+ return format("%s (%s)",concat(num," "), concat(nam," "))
+ end
+end
+
+local function cref(kind,chainname,chainlookupname,lookupname,index)
+ if index then
+ return format("feature %s, chain %s, sub %s, lookup %s, index %s",kind,chainname,chainlookupname,lookupname,index)
+ elseif lookupname then
+ return format("feature %s, chain %s, sub %s, lookup %s",kind,chainname or "?",chainlookupname or "?",lookupname)
+ elseif chainlookupname then
+ return format("feature %s, chain %s, sub %s",kind,chainname or "?",chainlookupname)
+ elseif chainname then
+ return format("feature %s, chain %s",kind,chainname)
+ else
+ return format("feature %s",kind)
+ end
+end
+
+local function pref(kind,lookupname)
+ return format("feature %s, lookup %s",kind,lookupname)
+end
+
+-- we can assume that languages that use marks are not hyphenated
+-- we can also assume that at most one discretionary is present
+
+local function markstoligature(kind,lookupname,start,stop,char)
+ local n = copy_node(start)
+ local keep = start
+ local current
+ current, start = insert_node_after(start,start,n)
+ local snext = stop.next
+ current.next = snext
+ if snext then
+ snext.prev = current
+ end
+ start.prev, stop.next = nil, nil
+ current.char, current.subtype, current.components = char, 2, start
+ return keep
+end
+
+local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
+ if start ~= stop then
+--~ if discfound then
+--~ local lignode = copy_node(start)
+--~ lignode.font = start.font
+--~ lignode.char = char
+--~ lignode.subtype = 2
+--~ start = node.do_ligature_n(start, stop, lignode)
+--~ if start.id == disc then
+--~ local prev = start.prev
+--~ start = start.next
+--~ end
+ if discfound then
+ -- print("start->stop",nodes.tosequence(start,stop))
+ local lignode = copy_node(start)
+ lignode.font, lignode.char, lignode.subtype = start.font, char, 2
+ local next, prev = stop.next, start.prev
+ stop.next = nil
+ lignode = node.do_ligature_n(start, stop, lignode)
+ prev.next = lignode
+ if next then
+ next.prev = lignode
+ end
+ lignode.next, lignode.prev = next, prev
+ start = lignode
+ -- print("start->end",nodes.tosequence(start))
+ else -- start is the ligature
+ local deletemarks = markflag ~= "mark"
+ local n = copy_node(start)
+ local current
+ current, start = insert_node_after(start,start,n)
+ local snext = stop.next
+ current.next = snext
+ if snext then
+ snext.prev = current
+ end
+ start.prev, stop.next = nil, nil
+ current.char, current.subtype, current.components = char, 2, start
+ local head = current
+ if deletemarks then
+ if trace_marks then
+ while start do
+ if marks[start.char] then
+ logwarning("%s: remove mark %s",pref(kind,lookupname),gref(start.char))
+ end
+ start = start.next
+ end
+ end
+ else
+ local i = 0
+ while start do
+ if marks[start.char] then
+ set_attribute(start,markdone,i)
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
+ end
+ head, current = insert_node_after(head,current,copy_node(start))
+ else
+ i = i + 1
+ end
+ start = start.next
+ end
+ start = current.next
+ while start and start.id == glyph do
+ if marks[start.char] then
+ set_attribute(start,markdone,i)
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
+ end
+ else
+ break
+ end
+ start = start.next
+ end
+ end
+ return head
+ end
+ else
+ start.char = char
+ end
+ return start
+end
+
+function handlers.gsub_single(start,kind,lookupname,replacement)
+ if trace_singles then
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement))
+ end
+ start.char = replacement
+ return start, true
+end
+
+local function alternative_glyph(start,alternatives,kind,chainname,chainlookupname,lookupname) -- chainname and chainlookupname optional
+ local value, choice, n = featurevalue or tfmdata.shared.features[kind], nil, #alternatives -- global value, brrr
+ if value == "random" then
+ local r = math.random(1,n)
+ value, choice = format("random, choice %s",r), alternatives[r]
+ elseif value == "first" then
+ value, choice = format("first, choice %s",1), alternatives[1]
+ elseif value == "last" then
+ value, choice = format("last, choice %s",n), alternatives[n]
+ else
+ value = tonumber(value)
+ if type(value) ~= "number" then
+ value, choice = "default, choice 1", alternatives[1]
+ elseif value > n then
+ value, choice = format("no %s variants, taking %s",value,n), alternatives[n]
+ elseif value == 0 then
+ value, choice = format("choice %s (no change)",value), start.char
+ elseif value < 1 then
+ value, choice = format("no %s variants, taking %s",value,1), alternatives[1]
+ else
+ value, choice = format("choice %s",value), alternatives[value]
+ end
+ end
+ if not choice then
+ logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char))
+ choice, value = start.char, format("no replacement instead of %s",value)
+ end
+ return choice, value
+end
+
+function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence)
+ local choice, index = alternative_glyph(start,alternative,kind,lookupname)
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index)
+ end
+ start.char = choice
+ return start, true
+end
+
+function handlers.gsub_multiple(start,kind,lookupname,multiple)
+ if trace_multiples then
+ logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple))
+ end
+ start.char = multiple[1]
+ if #multiple > 1 then
+ for k=2,#multiple do
+ local n = copy_node(start)
+ n.char = multiple[k]
+ local sn = start.next
+ n.next = sn
+ n.prev = start
+ if sn then
+ sn.prev = n
+ end
+ start.next = n
+ start = n
+ end
+ end
+ return start, true
+end
+
+function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or maybe pass lookup ref
+ local s, stop, discfound = start.next, nil, false
+ local startchar = start.char
+ if marks[startchar] then
+ while s do
+ local id = s.id
+ if id == glyph and s.subtype<256 then
+ if s.font == currentfont then
+ local char = s.char
+ local lg = ligature[1][char]
+ if not lg then
+ break
+ else
+ stop = s
+ ligature = lg
+ s = s.next
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if stop and ligature[2] then
+ if trace_ligatures then
+ local stopchar = stop.char
+ start = markstoligature(kind,lookupname,start,stop,ligature[2])
+ logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+ else
+ start = markstoligature(kind,lookupname,start,stop,ligature[2])
+ end
+ return start, true
+ end
+ else
+ local skipmark = sequence.flags[1]
+ while s do
+ local id = s.id
+ if id == glyph and s.subtype<256 then
+ if s.font == currentfont then
+ local char = s.char
+ if skipmark and marks[char] then
+ s = s.next
+ else
+ local lg = ligature[1][char]
+ if not lg then
+ break
+ else
+ stop = s
+ ligature = lg
+ s = s.next
+ end
+ end
+ else
+ break
+ end
+ elseif id == disc then
+ discfound = true
+ s = s.next
+ else
+ break
+ end
+ end
+ if stop and ligature[2] then
+ if trace_ligatures then
+ local stopchar = stop.char
+ start = toligature(kind,lookupname,start,stop,ligature[2],skipmark,discfound)
+ logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+ else
+ start = toligature(kind,lookupname,start,stop,ligature[2],skipmark,discfound)
+ end
+ return start, true
+ end
+ end
+ return start, false
+end
+
+--[[ldx--
+
We get hits on a mark, but we're not sure if the it has to be applied so
+we need to explicitly test for basechar, baselig and basemark entries.
+--ldx]]--
+
+function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence)
+ local markchar = start.char
+ if marks[markchar] then
+ local base = start.prev -- [glyph] [start=mark]
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ local basechar = base.char
+ if marks[basechar] then
+ while true do
+ base = base.prev
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ basechar = base.char
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
+ end
+ return start, false
+ end
+ end
+ end
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
+ end
+ if baseanchors then
+ local baseanchors = baseanchors['basechar']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)",
+ pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return start, true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s, no matching anchors for mark %s and base %s",pref(kind,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ else -- if trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ fonts.register_message(currentfont,basechar,"no base anchors")
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char",pref(kind,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
+ end
+ return start, false
+end
+
+function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
+ -- check chainpos variant
+ local markchar = start.char
+ if marks[markchar] then
+ local base = start.prev -- [glyph] [optional marks] [start=mark]
+ local index = 1
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ local basechar = base.char
+ if marks[basechar] then
+ index = index + 1
+ while true do
+ base = base.prev
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ basechar = base.char
+ if marks[basechar] then
+ index = index + 1
+ else
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
+ end
+ return start, false
+ end
+ end
+ end
+ local i = has_attribute(start,markdone)
+ if i then index = i end
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
+ if baseanchors then
+ local baseanchors = baseanchors['baselig']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma,index)
+ if trace_marks then
+ logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
+ pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return start, true
+ end
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and baselig %s",pref(kind,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ else -- if trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ fonts.register_message(currentfont,basechar,"no base anchors")
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char",pref(kind,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
+ end
+ return start, false
+end
+
+function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence)
+ local markchar = start.char
+ if marks[markchar] then
+--~ local alreadydone = markonce and has_attribute(start,markmark)
+--~ if not alreadydone then
+ local base = start.prev -- [glyph] [basemark] [start=mark]
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then -- subtype test can go
+ local basechar = base.char
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
+ if baseanchors then
+ baseanchors = baseanchors['basemark']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
+ pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return start,true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ else -- if trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ fonts.register_message(currentfont,basechar,"no base anchors")
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark",pref(kind,lookupname))
+ end
+--~ elseif trace_marks and trace_details then
+--~ logprocess("%s, mark %s is already bound (n=%s), ignoring mark2mark",pref(kind,lookupname),gref(markchar),alreadydone)
+--~ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
+ end
+ return start,false
+end
+
+function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence) -- to be checked
+ local alreadydone = cursonce and has_attribute(start,cursbase)
+ if not alreadydone then
+ local done = false
+ local startchar = start.char
+ if marks[startchar] then
+ if trace_cursive then
+ logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
+ end
+ else
+ local nxt = start.next
+ while not done and nxt and nxt.id == glyph and nxt.subtype<256 and nxt.font == currentfont do
+ local nextchar = nxt.char
+ if marks[nextchar] then
+ -- should not happen (maybe warning)
+ nxt = nxt.next
+ else
+ local entryanchors = descriptions[nextchar]
+ if entryanchors then
+ entryanchors = entryanchors.anchors
+ if entryanchors then
+ entryanchors = entryanchors['centry']
+ if entryanchors then
+ local al = anchorlookups[lookupname]
+ for anchor, entry in next, entryanchors do
+ if al[anchor] then
+ local exit = exitanchors[anchor]
+ if exit then
+ local dx, dy, bound = set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ if trace_cursive then
+ logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
+ end
+ done = true
+ break
+ end
+ end
+ end
+ end
+ end
+ else -- if trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
+ fonts.register_message(currentfont,startchar,"no entry anchors")
+ end
+ break
+ end
+ end
+ end
+ return start, done
+ else
+ if trace_cursive and trace_details then
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+ end
+ return start, false
+ end
+end
+
+function handlers.gpos_single(start,kind,lookupname,kerns,sequence)
+ local startchar = start.char
+ local dx, dy, w, h = set_pair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
+ end
+ return start, false
+end
+
+function handlers.gpos_pair(start,kind,lookupname,kerns,sequence)
+ -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
+ -- todo: kerns in components of ligatures
+ local snext = start.next
+ if not snext then
+ return start, false
+ else
+ local prev, done = start, false
+ local factor = tfmdata.factor
+ while snext and snext.id == glyph and snext.subtype<256 and snext.font == currentfont do
+ local nextchar = snext.char
+local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = snext.next
+ else
+ local krn = kerns[nextchar]
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if krn[1] == "pair" then
+ local a, b = krn[3], krn[4]
+ if a and #a > 0 then
+ local startchar = start.char
+ local x, y, w, h = set_pair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting first of pair %s and %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b > 0 then
+ local startchar = start.char
+ local x, y, w, h = set_pair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
+ if trace_kerns then
+ logprocess("%s: shifting second of pair %s and %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ logs.report("%s: check this out (old kern stuff)",pref(kind,lookupname))
+ local a, b = krn[3], krn[7]
+ if a and a ~= 0 then
+ local k = set_kern(snext,factor,rlmode,a)
+ if trace_kerns then
+ logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar))
+ end
+ end
+ if b and b ~= 0 then
+ logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor)
+ end
+ end
+ done = true
+ elseif krn ~= 0 then
+ local k = set_kern(snext,factor,rlmode,krn)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar))
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return start, done
+ end
+end
+
+--[[ldx--
+
I will implement multiple chain replacements once I run into a font that uses
+it. It's not that complex to handle.
+--ldx]]--
+
+local chainmores = { }
+local chainprocs = { }
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ logs.report("otf subchain",...)
+end
+local function logwarning(...)
+ logs.report("otf subchain",...)
+end
+
+-- ['coverage']={
+-- ['after']={ "r" },
+-- ['before']={ "q" },
+-- ['current']={ "a", "b", "c" },
+-- },
+-- ['lookups']={ "ls_l_1", "ls_l_1", "ls_l_1" },
+
+function chainmores.chainsub(start,stop,kind,chainname,currentcontext,cache,lookuplist,chainlookupname,n)
+ logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
+ return start, false
+end
+
+-- handled later:
+--
+-- function chainmores.gsub_single(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n)
+-- return chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n)
+-- end
+
+function chainmores.gsub_multiple(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n)
+ logprocess("%s: gsub_multiple not yet supported",cref(kind,chainname,chainlookupname))
+ return start, false
+end
+function chainmores.gsub_alternate(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n)
+ logprocess("%s: gsub_alternate not yet supported",cref(kind,chainname,chainlookupname))
+ return start, false
+end
+
+-- handled later:
+--
+-- function chainmores.gsub_ligature(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n)
+-- return chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n)
+-- end
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ logs.report("otf chain",...)
+end
+local function logwarning(...)
+ logs.report("otf chain",...)
+end
+
+-- We could share functions but that would lead to extra function calls with many
+-- arguments, redundant tests and confusing messages.
+
+function chainprocs.chainsub(start,stop,kind,chainname,currentcontext,cache,lookuplist,chainlookupname)
+ logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
+ return start, false
+end
+
+-- The reversesub is a special case, which is why we need to store the replacements
+-- in a bit weird way. There is no lookup and the replacement comes from the lookup
+-- itself. It is meant mostly for dealing with Urdu.
+
+function chainprocs.reversesub(start,stop,kind,chainname,currentcontext,cache,replacements)
+ local char = start.char
+ local replacement = replacements[char]
+ if replacement then
+ if trace_singles then
+ logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
+ end
+ start.char = replacement
+ return start, true
+ else
+ return start, false
+ end
+end
+
+--[[ldx--
+
This chain stuff is somewhat tricky since we can have a sequence of actions to be
+applied: single, alternate, multiple or ligature where ligature can be an invalid
+one in the sense that it will replace multiple by one but not neccessary one that
+looks like the combination (i.e. it is the counterpart of multiple then). For
+example, the following is valid:
Therefore we we don't really do the replacement here already unless we have the
+single lookup case. The efficiency of the replacements can be improved by deleting
+as less as needed but that would also mke the code even more messy.
+--ldx]]--
+
+local function delete_till_stop(start,stop,ignoremarks)
+ if start ~= stop then
+ -- todo keep marks
+ local done = false
+ while not done do
+ done = start == stop
+ delete_node(start,start.next)
+ end
+ end
+end
+
+--[[ldx--
+
Here we replace start by a single variant, First we delete the rest of the
+match.
+--ldx]]--
+
+function chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex)
+ -- todo: marks ?
+ if not chainindex then
+ delete_till_stop(start,stop) -- ,currentlookup.flags[1])
+ end
+ local current = start
+ local subtables = currentlookup.subtables
+ while current do
+ if current.id == glyph then
+ local currentchar = current.char
+ local lookupname = subtables[1]
+ local replacement = cache.gsub_single[lookupname]
+ if not replacement then
+ if trace_bugs then
+ logwarning("%s: no single hits",cref(kind,chainname,chainlookupname,lookupname,chainindex))
+ end
+ else
+ replacement = replacement[currentchar]
+ if not replacement then
+ if trace_bugs then
+ logwarning("%s: no single for %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar))
+ end
+ else
+ if trace_singles then
+ logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
+ end
+ current.char = replacement
+ end
+ end
+ return start, true
+ elseif current == stop then
+ break
+ else
+ current = current.next
+ end
+ end
+ return start, false
+end
+
+chainmores.gsub_single = chainprocs.gsub_single
+
+--[[ldx--
+
Here we replace start by a sequence of new glyphs. First we delete the rest of
+the match.
+--ldx]]--
+
+function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname)
+ delete_till_stop(start,stop)
+ local startchar = start.char
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local replacements = cache.gsub_multiple[lookupname]
+ if not replacements then
+ if trace_bugs then
+ logwarning("%s: no multiple hits",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ else
+ replacements = replacements[startchar]
+ if not replacements then
+ if trace_bugs then
+ logwarning("%s: no multiple for %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar))
+ end
+ else
+ if trace_multiples then
+ logprocess("%s: replacing %s by multiple characters %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar),gref(replacements))
+ end
+ local sn = start.next
+ for k=1,#replacements do
+ if k == 1 then
+ start.char = replacements[k]
+ else
+ local n = copy_node(start) -- maybe delete the components and such
+ n.char = replacements[k]
+ n.next, n.prev = sn, start
+ if sn then
+ sn.prev = n
+ end
+ start.next, start = n, n
+ end
+ end
+ return start, true
+ end
+ end
+ return start, false
+end
+
+--[[ldx--
+
Here we replace start by new glyph. First we delete the rest of the match.
+--ldx]]--
+
+function chainprocs.gsub_alternate(start,stop,kind,lookupname,currentcontext,cache,currentlookup)
+ -- todo: marks ?
+ delete_till_stop(start,stop)
+ local current = start
+ local subtables = currentlookup.subtables
+ while current do
+ if current.id == glyph then
+ local currentchar = current.char
+ local lookupname = subtables[1]
+ local alternatives = cache.gsub_alternate[lookupname]
+ if not alternatives then
+ if trace_bugs then
+ logwarning("%s: no alternative hits",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ else
+ alternatives = alternatives[currentchar]
+ if not alternatives then
+ if trace_bugs then
+ logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar))
+ end
+ else
+ local choice, index = alternative_glyph(current,alternatives,kind,chainname,chainlookupname,lookupname)
+ current.char = choice
+ if trace_alternatives then
+ logprocess("%s: replacing single %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),index,gref(currentchar),gref(choice),index)
+ end
+ end
+ end
+ return start, true
+ elseif current == stop then
+ break
+ else
+ current = current.next
+ end
+ end
+ return start, false
+end
+
+--[[ldx--
+
When we replace ligatures we use a helper that handles the marks. I might change
+this function (move code inline and handle the marks by a separate function). We
+assume rather stupid ligatures (no complex disc nodes).
+--ldx]]--
+
+function chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex)
+ local startchar = start.char
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local ligatures = cache.gsub_ligature[lookupname]
+ if not ligatures then
+ if trace_bugs then
+ logwarning("%s: no ligature hits",cref(kind,chainname,chainlookupname,lookupname,chainindex))
+ end
+ else
+ ligatures = ligatures[startchar]
+ if not ligatures then
+ if trace_bugs then
+ logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
+ end
+ else
+ local s, discfound, last, nofreplacements = start.next, false, stop, 0
+ while s do
+ local id = s.id
+ if id == disc then
+ s = s.next
+ discfound = true
+ else
+ local schar = s.char
+ if marks[schar] then -- marks
+ s = s.next
+ else
+ local lg = ligatures[1][schar]
+ if not lg then
+ break
+ else
+ ligatures, last, nofreplacements = lg, s, nofreplacements + 1
+ if s == stop then
+ break
+ else
+ s = s.next
+ end
+ end
+ end
+ end
+ end
+ local l2 = ligatures[2]
+ if l2 then
+ if chainindex then
+ stop = last
+ end
+ if trace_ligatures then
+ if start == stop then
+ logprocess("%s: replacing character %s by ligature %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2))
+ else
+ logprocess("%s: replacing character %s upto %s by ligature %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2))
+ end
+ end
+ start = toligature(kind,lookup,start,stop,l2,currentlookup.flags[1],discfound)
+ return start, true, nofreplacements
+ elseif trace_bugs then
+ if start == stop then
+ logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
+ else
+ logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char))
+ end
+ end
+ end
+ end
+ return start, false, 0
+end
+
+chainmores.gsub_ligature = chainprocs.gsub_ligature
+
+function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname)
+ local markchar = start.char
+ if marks[markchar] then
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local markanchors = cache.gpos_mark2base[lookupname]
+ if markanchors then
+ markanchors = markanchors[markchar]
+ end
+ if markanchors then
+ local base = start.prev -- [glyph] [start=mark]
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ local basechar = base.char
+ if marks[basechar] then
+ while true do
+ base = base.prev
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ basechar = base.char
+ if not marks[basechar] then
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
+ end
+ return start, false
+ end
+ end
+ end
+ local baseanchors = descriptions[basechar].anchors
+ if baseanchors then
+ local baseanchors = baseanchors['basechar']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)",
+ cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return start, true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s, no matching anchors for mark %s and base %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no char",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
+ end
+ return start, false
+end
+
+function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname)
+ local markchar = start.char
+ if marks[markchar] then
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local markanchors = cache.gpos_mark2ligature[lookupname]
+ if markanchors then
+ markanchors = markanchors[markchar]
+ end
+ if markanchors then
+ local base = start.prev -- [glyph] [optional marks] [start=mark]
+ local index = 1
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ local basechar = base.char
+ if marks[basechar] then
+ index = index + 1
+ while true do
+ base = base.prev
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then
+ basechar = base.char
+ if marks[basechar] then
+ index = index + 1
+ else
+ break
+ end
+ else
+ if trace_bugs then
+ logwarning("%s: no base for mark %s",cref(kind,chainname,chainlookupname,lookupname),markchar)
+ end
+ return start, false
+ end
+ end
+ end
+ -- todo: like marks a ligatures hash
+ local i = has_attribute(start,markdone)
+ if i then index = i end
+ local baseanchors = descriptions[basechar].anchors
+ if baseanchors then
+ local baseanchors = baseanchors['baselig']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ ba = ba[index]
+ if ba then
+ local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma,index)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
+ cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
+ end
+ return start, true
+ end
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and baselig %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("feature %s, lookup %s: prev node is no char",kind,lookupname)
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
+ end
+ return start, false
+end
+
+function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname)
+ local markchar = start.char
+ if marks[markchar] then
+--~ local alreadydone = markonce and has_attribute(start,markmark)
+--~ if not alreadydone then
+ -- local markanchors = descriptions[markchar].anchors markanchors = markanchors and markanchors.mark
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local markanchors = cache.gpos_mark2mark[lookupname]
+ if markanchors then
+ markanchors = markanchors[markchar]
+ end
+ if markanchors then
+ local base = start.prev -- [glyph] [basemark] [start=mark]
+ if base and base.id == glyph and base.subtype<256 and base.font == currentfont then -- subtype test can go
+ local basechar = base.char
+ local baseanchors = descriptions[basechar].anchors
+ if baseanchors then
+ baseanchors = baseanchors['basemark']
+ if baseanchors then
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = set_mark(start,base,tfmdata.factor,rlmode,ba,ma)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
+ cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+ end
+ return start, true
+ end
+ end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and basemark %s",gref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
+ end
+ end
+ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark",cref(kind,chainname,chainlookupname,lookupname))
+ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
+ end
+--~ elseif trace_marks and trace_details then
+--~ logprocess("%s, mark %s is already bound (n=%s), ignoring mark2mark",pref(kind,lookupname),gref(markchar),alreadydone)
+--~ end
+ elseif trace_bugs then
+ logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
+ end
+ return start, false
+end
+
+-- ! ! ! untested ! ! !
+
+function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname)
+ local alreadydone = cursonce and has_attribute(start,cursbase)
+ if not alreadydone then
+ local startchar = start.char
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local exitanchors = cache.gpos_cursive[lookupname]
+ if exitanchors then
+ exitanchors = exitanchors[startchar]
+ end
+ if exitanchors then
+ local done = false
+ if marks[startchar] then
+ if trace_cursive then
+ logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
+ end
+ else
+ local nxt = start.next
+ while not done and nxt and nxt.id == glyph and nxt.subtype<256 and nxt.font == currentfont do
+ local nextchar = nxt.char
+ if marks[nextchar] then
+ -- should not happen (maybe warning)
+ nxt = nxt.next
+ else
+ local entryanchors = descriptions[nextchar]
+ if entryanchors then
+ entryanchors = entryanchors.anchors
+ if entryanchors then
+ entryanchors = entryanchors['centry']
+ if entryanchors then
+ local al = anchorlookups[lookupname]
+ for anchor, entry in next, entryanchors do
+ if al[anchor] then
+ local exit = exitanchors[anchor]
+ if exit then
+ local dx, dy, bound = set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
+ if trace_cursive then
+ logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
+ end
+ done = true
+ break
+ end
+ end
+ end
+ end
+ end
+ else -- if trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
+ fonts.register_message(currentfont,startchar,"no entry anchors")
+ end
+ break
+ end
+ end
+ end
+ return start, done
+ else
+ if trace_cursive and trace_details then
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+ end
+ return start, false
+ end
+ end
+ return start, false
+end
+
+function chainprocs.gpos_single(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex,sequence)
+ -- untested
+ local startchar = start.char
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = cache.gpos_single[lookupname]
+ if kerns then
+ kerns = kerns[startchar]
+ if kerns then
+ local dx, dy, w, h = set_pair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting single %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
+ end
+ end
+ end
+ return start, false
+end
+
+-- when machines become faster i will make a shared function
+
+function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex,sequence)
+-- logwarning("%s: gpos_pair not yet supported",cref(kind,chainname,chainlookupname))
+ local snext = start.next
+ if snext then
+ local startchar = start.char
+ local subtables = currentlookup.subtables
+ local lookupname = subtables[1]
+ local kerns = cache.gpos_pair[lookupname]
+ if kerns then
+ kerns = kerns[startchar]
+ if kerns then
+ local prev, done = start, false
+ local factor = tfmdata.factor
+ while snext and snext.id == glyph and snext.subtype<256 and snext.font == currentfont do
+ local nextchar = snext.char
+ local krn = kerns[nextchar]
+ if not krn and marks[nextchar] then
+ prev = snext
+ snext = snext.next
+ else
+ if not krn then
+ -- skip
+ elseif type(krn) == "table" then
+ if krn[1] == "pair" then
+ local a, b = krn[3], krn[4]
+ if a and #a > 0 then
+ local startchar = start.char
+ local x, y, w, h = set_pair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
+ if trace_kerns then
+ logprocess("%s: shifting first of pair %s and %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ if b and #b > 0 then
+ local startchar = start.char
+ local x, y, w, h = set_pair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
+ if trace_kerns then
+ logprocess("%s: shifting second of pair %s and %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
+ end
+ end
+ else
+ logs.report("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
+ local a, b = krn[3], krn[7]
+ if a and a ~= 0 then
+ local k = set_kern(snext,factor,rlmode,a)
+ if trace_kerns then
+ logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+ end
+ end
+ if b and b ~= 0 then
+ logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
+ end
+ end
+ done = true
+ elseif krn ~= 0 then
+ local k = set_kern(snext,factor,rlmode,krn)
+ if trace_kerns then
+ logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+ end
+ done = true
+ end
+ break
+ end
+ end
+ return start, done
+ end
+ end
+ end
+ return start, false
+end
+
+-- what pointer to return, spec says stop
+-- to be discussed ... is bidi changer a space?
+-- elseif char == zwnj and sequence[n][32] then -- brrr
+
+-- somehow l or f is global
+-- we don't need to pass the currentcontext, saves a bit
+-- make a slow variant then can be activated but with more tracing
+
+local function show_skip(kind,chainname,char,ck,class)
+ if ck[9] then
+ logwarning("%s: skipping char %s (%s) in rule %s, lookuptype %s (%s=>%s)",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
+ else
+ logwarning("%s: skipping char %s (%s) in rule %s, lookuptype %s",cref(kind,chainname),gref(char),class,ck[1],ck[2])
+ end
+end
+
+local function normal_handle_contextchain(start,kind,chainname,contexts,sequence,cache)
+ -- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6]
+ local flags, done = sequence.flags, false
+ local skipmark, skipligature, skipbase = flags[1], flags[2], flags[3]
+ local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !)
+ local markclass = sequence.markclass -- todo, first we need a proper test
+ local skipped = false
+ for k=1,#contexts do
+ local match, current, last = true, start, start
+ local ck = contexts[k]
+ local seq = ck[3]
+ local s = #seq
+ -- f..l = mid string
+ if s == 1 then
+ -- never happens
+ match = current.id == glyph and current.subtype<256 and current.font == currentfont and seq[1][current.char]
+ else
+ -- todo: better space check (maybe check for glue)
+ local f, l = ck[4], ck[5]
+ if f == l then
+ -- already a hit
+ match = true
+ else
+ -- no need to test first hit (to be optimized)
+ local n = f + 1
+ last = last.next
+ -- we cannot optimize for n=2 because there can be disc nodes
+ -- if not someskip and n == l then
+ -- -- n=2 and no skips then faster loop
+ -- match = last and last.id == glyph and last.subtype<256 and last.font == currentfont and seq[n][last.char]
+ -- else
+ while n <= l do
+ if last then
+ local id = last.id
+ if id == glyph then
+ if last.subtype<256 and last.font == currentfont then
+ local char = last.char
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ last = last.next
+ elseif seq[n][char] then
+ if n < l then
+ last = last.next
+ end
+ n = n + 1
+ else
+ match = false break
+ end
+ else
+ match = false break
+ end
+ else
+ match = false break
+ end
+ elseif id == disc then -- what to do with kerns?
+ last = last.next
+ else
+ match = false break
+ end
+ else
+ match = false break
+ end
+ end
+ -- end
+ end
+ if match and f > 1 then
+ -- before
+ local prev = start.prev
+ if prev then
+ local n = f-1
+ while n >= 1 do
+ if prev then
+ local id = prev.id
+ if id == glyph then
+ if prev.subtype<256 and prev.font == currentfont then -- normal char
+ local char = prev.char
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n -1
+ else
+ match = false break
+ end
+ else
+ match = false break
+ end
+ else
+ match = false break
+ end
+ elseif id == disc then
+ -- skip 'm
+ elseif seq[n][32] then
+ n = n -1
+ else
+ match = false break
+ end
+ prev = prev.prev
+ elseif seq[n][32] then
+ n = n -1
+ else
+ match = false break
+ end
+ end
+ elseif f == 2 then
+ match = seq[1][32]
+ else
+ for n=f-1,1 do
+ if not seq[n][32] then
+ match = false break
+ end
+ end
+ end
+ end
+ if match and s > l then
+ -- after
+ local current = last.next
+ if current then
+ -- removed optimization for s-l == 1, we have to deal with marks anyway
+ local n = l + 1
+ while n <= s do
+ if current then
+ local id = current.id
+ if id == glyph then
+ if current.subtype<256 and current.font == currentfont then -- normal char
+ local char = current.char
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ skipped = true
+ if trace_skips then
+ show_skip(kind,chainname,char,ck,class)
+ end
+ elseif seq[n][char] then
+ n = n + 1
+ else
+ match = false break
+ end
+ else
+ match = false break
+ end
+ else
+ match = false break
+ end
+ elseif id == disc then
+ -- skip 'm
+ elseif seq[n][32] then -- brrr
+ n = n + 1
+ else
+ match = false break
+ end
+ current = current.next
+ elseif seq[n][32] then
+ n = n + 1
+ else
+ match = false break
+ end
+ end
+ elseif s-l == 1 then
+ match = seq[s][32]
+ else
+ for n=l+1,s do
+ if not seq[n][32] then
+ match = false break
+ end
+ end
+ end
+ end
+ end
+ if match then
+ -- ck == currentcontext
+ if trace_contexts then
+ local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5]
+ local char = start.char
+ if ck[9] then
+ logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %s (%s=>%s)",cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10])
+ else
+ logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %s",cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype)
+ end
+ end
+ local chainlookups = ck[6]
+ if chainlookups then
+ local nofchainlookups = #chainlookups
+ -- we can speed this up if needed
+ if nofchainlookups == 1 then
+ local chainlookupname = chainlookups[1]
+ local chainlookup = lookuptable[chainlookupname]
+ local cp = chainprocs[chainlookup.type]
+ if cp then
+ start, done = cp(start,last,kind,chainname,ck,cache,chainlookup,chainlookupname,nil,sequence)
+ else
+ logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ end
+ else
+ -- actually this needs a more complex treatment for which we will use chainmores
+--~ local i = 1
+--~ repeat
+--~ local chainlookupname = chainlookups[i]
+--~ local chainlookup = lookuptable[chainlookupname]
+--~ local cp = chainmores[chainlookup.type]
+--~ if cp then
+--~ local ok, n
+--~ start, ok, n = cp(start,last,kind,chainname,ck,cache,chainlookup,chainlookupname,i,sequence)
+--~ -- messy since last can be changed !
+--~ if ok then
+--~ done = true
+--~ start = start.next
+--~ if n then
+--~ -- skip next one(s) if ligature
+--~ i = i + n - 1
+--~ end
+--~ end
+--~ else
+--~ logprocess("%s: multiple subchains for %s are not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+--~ end
+--~ i = i + 1
+--~ until i > nofchainlookups
+
+ local i = 1
+ repeat
+if skipped then
+ while true do
+ local char = start.char
+ local ccd = descriptions[char]
+ if ccd then
+ local class = ccd.class
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ start = start.next
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+end
+ local chainlookupname = chainlookups[i]
+ local chainlookup = lookuptable[chainlookupname]
+ local cp = chainmores[chainlookup.type]
+ if cp then
+ local ok, n
+ start, ok, n = cp(start,last,kind,chainname,ck,cache,chainlookup,chainlookupname,i,sequence)
+ -- messy since last can be changed !
+ if ok then
+ done = true
+ -- skip next one(s) if ligature
+ i = i + (n or 1)
+ else
+ i = i + 1
+ end
+ else
+ logprocess("%s: multiple subchains for %s are not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ i = i + 1
+ end
+ start = start.next
+ until i > nofchainlookups
+
+ end
+ else
+ local replacements = ck[7]
+ if replacements then
+ start, done = chainprocs.reversesub(start,last,kind,chainname,ck,cache,replacements) -- sequence
+ else
+ done = true -- can be meant to be skipped
+ if trace_contexts then
+ logprocess("%s: skipping match",cref(kind,chainname))
+ end
+ end
+ end
+ end
+ end
+ return start, done
+end
+
+-- Because we want to keep this elsewhere (an because speed is less an issue) we
+-- pass the font id so that the verbose variant can access the relevant helper tables.
+
+local verbose_handle_contextchain = function(font,...)
+ logwarning("no verbose handler installed, reverting to 'normal'")
+ otf.setcontextchain()
+ return normal_handle_contextchain(...)
+end
+
+otf.chainhandlers = {
+ normal = normal_handle_contextchain,
+ verbose = verbose_handle_contextchain,
+}
+
+function otf.setcontextchain(method)
+ if not method or method == "normal" or not otf.chainhandlers[method] then
+ if handlers.contextchain then -- no need for a message while making the format
+ logwarning("installing normal contextchain handler")
+ end
+ handlers.contextchain = normal_handle_contextchain
+ else
+ logwarning("installing contextchain handler '%s'",method)
+ local handler = otf.chainhandlers[method]
+ handlers.contextchain = function(...)
+ return handler(currentfont,...) -- hm, get rid of ...
+ end
+ end
+ handlers.gsub_context = handlers.contextchain
+ handlers.gsub_contextchain = handlers.contextchain
+ handlers.gsub_reversecontextchain = handlers.contextchain
+ handlers.gpos_contextchain = handlers.contextchain
+ handlers.gpos_context = handlers.contextchain
+end
+
+otf.setcontextchain()
+
+local missing = { } -- we only report once
+
+local function logprocess(...)
+ if trace_steps then
+ registermessage(...)
+ end
+ logs.report("otf process",...)
+end
+local function logwarning(...)
+ logs.report("otf process",...)
+end
+
+local function report_missing_cache(typ,lookup)
+ local f = missing[currentfont] if not f then f = { } missing[currentfont] = f end
+ local t = f[typ] if not t then t = { } f[typ] = t end
+ if not t[lookup] then
+ t[lookup] = true
+ logwarning("missing cache for lookup %s of type %s in font %s (%s)",lookup,typ,currentfont,tfmdata.fullname)
+ end
+end
+
+local resolved = { } -- we only resolve a font,script,language pair once
+
+-- todo: pass all these 'locals' in a table
+
+function fonts.methods.node.otf.features(head,font,attr)
+ if trace_steps then
+ checkstep(head)
+ end
+ tfmdata = fontdata[font]
+ local shared = tfmdata.shared
+ otfdata = shared.otfdata
+ local luatex = otfdata.luatex
+ descriptions = tfmdata.descriptions
+ characters = tfmdata.characters
+ indices = tfmdata.indices
+ unicodes = tfmdata.unicodes
+ marks = tfmdata.marks
+ anchorlookups = luatex.lookup_to_anchor
+ currentfont = font
+ rlmode = 0
+ local featuredata = otfdata.shared.featuredata -- can be made local to closure
+ local sequences = luatex.sequences
+ lookuptable = luatex.lookups
+ local done = false
+ local script, language, s_enabled, a_enabled, dyn
+ local attribute_driven = attr and attr ~= 0
+ if attribute_driven then
+ local features = context_setups[context_numbers[attr]] -- could be a direct list
+ dyn = context_merged[attr] or 0
+ language, script = features.language or "dflt", features.script or "dflt"
+ a_enabled = features -- shared.features -- can be made local to the resolver
+ if dyn == 2 or dyn == -2 then
+ -- font based
+ s_enabled = shared.features
+ end
+ else
+ language, script = tfmdata.language or "dflt", tfmdata.script or "dflt"
+ s_enabled = shared.features -- can be made local to the resolver
+ dyn = 0
+ end
+ -- we can save some runtime by caching feature tests
+ local res = resolved[font] if not res then res = { } resolved[font] = res end
+ local rs = res [script] if not rs then rs = { } res [script] = rs end
+ local rl = rs [language] if not rl then rl = { } rs [language] = rl end
+ local ra = rl [attr] if ra == nil then ra = { } rl [attr] = ra end -- attr can be false
+ -- sequences always > 1 so no need for optimization
+ for s=1,#sequences do
+ local pardir, txtdir = 0, { }
+ local success = false
+ local sequence = sequences[s]
+ local r = ra[s] -- cache
+ if r == nil then
+ --
+ -- this bit will move to font-ctx and become a function
+ ---
+ local chain = sequence.chain or 0
+ local features = sequence.features
+ if not features then
+ -- indirect lookup, part of chain (todo: make this a separate table)
+ r = false -- { false, false, chain }
+ else
+ local valid, attribute, kind, what = false, false
+ for k,v in next, features do
+ -- we can quit earlier but for the moment we want the tracing
+ local s_e = s_enabled and s_enabled[k]
+ local a_e = a_enabled and a_enabled[k]
+ if s_e or a_e then
+ local l = v[script] or v[wildcard]
+ if l then
+ -- not l[language] or l[default] or l[wildcard] because we want tracing
+ -- only first attribute match check, so we assume simple fina's
+ -- default can become a font feature itself
+ if l[language] then
+ valid, what = s_e or a_e, language
+ -- elseif l[default] then
+ -- valid, what = true, default
+ elseif l[wildcard] then
+ valid, what = s_e or a_e, wildcard
+ end
+ if valid then
+ kind, attribute = k, special_attributes[k] or false
+ if a_e and dyn < 0 then
+ valid = false
+ end
+ if trace_applied then
+ local typ, action = match(sequence.type,"(.*)_(.*)")
+ logs.report("otf node mode",
+ "%s font: %03i, dynamic: %03i, kind: %s, lookup: %3i, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s",
+ (valid and "+") or "-",font,attr or 0,kind,s,script,language,what,typ,action,sequence.name)
+ end
+ break
+ end
+ end
+ end
+ end
+ if valid then
+ r = { valid, attribute, chain, kind }
+ else
+ r = false -- { valid, attribute, chain, "generic" } -- false anyway, could be flag instead of table
+ end
+ end
+ ra[s] = r
+ end
+ featurevalue = r and r[1] -- todo: pass to function instead of using a global
+ if featurevalue then
+ local attribute, chain, typ, subtables = r[2], r[3], sequence.type, sequence.subtables
+ if chain < 0 then
+ -- this is a limited case, no special treatments like 'init' etc
+ local handler = handlers[typ]
+ local thecache = featuredata[typ] or { }
+ -- we need to get rid of this slide !
+ local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
+ while start do
+ local id = start.id
+ if id == glyph then
+ if start.subtype<256 and start.font == font and (not attr or has_attribute(start,0,attr)) then
+--~ if start.subtype<256 and start.font == font and has_attribute(start,0,attr) then
+ for i=1,#subtables do
+ local lookupname = subtables[i]
+ local lookupcache = thecache[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ start, success = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i)
+ if success then
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ if start then start = start.prev end
+ else
+ start = start.prev
+ end
+ else
+ start = start.prev
+ end
+ end
+ else
+ local handler = handlers[typ]
+ local ns = #subtables
+ local thecache = featuredata[typ] or { }
+ local start = head -- local ?
+ rlmode = 0 -- to be checked ?
+ if ns == 1 then
+ local lookupname = subtables[1]
+ local lookupcache = thecache[lookupname]
+ if not lookupcache then
+ report_missing_cache(typ,lookupname)
+ else
+ while start do
+ local id = start.id
+ if id == glyph then
+--~ if start.font == font and start.subtype<256 and has_attribute(start,0,attr) and (not attribute or has_attribute(start,state,attribute)) then
+ if start.font == font and start.subtype<256 and (not attr or has_attribute(start,0,attr)) and (not attribute or has_attribute(start,state,attribute)) then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- sequence kan weg
+ local ok
+ start, ok = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,1)
+ if ok then
+ success = true
+ end
+ end
+ if start then start = start.next end
+ else
+ start = start.next
+ end
+ -- elseif id == glue then
+ -- if p[5] then -- chain
+ -- local pc = pp[32]
+ -- if pc then
+ -- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
+ -- if ok then
+ -- done = true
+ -- end
+ -- if start then start = start.next end
+ -- else
+ -- start = start.next
+ -- end
+ -- else
+ -- start = start.next
+ -- end
+ elseif id == whatsit then
+ local subtype = start.subtype
+ if subtype == 7 then
+ local dir = start.dir
+ if dir == "+TRT" or dir == "+TLT" then
+ insert(txtdir,dir)
+ elseif dir == "-TRT" or dir == "-TLT" then
+ remove(txtdir)
+ end
+ local d = txtdir[#txtdir]
+ if d == "+TRT" then
+ rlmode = -1
+ elseif d == "+TLT" then
+ rlmode = 1
+ else
+ rlmode = pardir
+ end
+ if trace_directions then
+ logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ end
+ elseif subtype == 6 then
+ local dir = start.dir
+ if dir == "TRT" then
+ pardir = -1
+ elseif dir == "TLT" then
+ pardir = 1
+ else
+ pardir = 0
+ end
+ rlmode = pardir
+ --~ txtdir = { }
+ if trace_directions then
+ logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ end
+ end
+ start = start.next
+ else
+ start = start.next
+ end
+ end
+ end
+ else
+ while start do
+ local id = start.id
+ if id == glyph then
+ if start.subtype<256 and start.font == font and (not attr or has_attribute(start,0,attr)) and (not attribute or has_attribute(start,state,attribute)) then
+--~ if start.subtype<256 and start.font == font and has_attribute(start,0,attr) and (not attribute or has_attribute(start,state,attribute)) then
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = thecache[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local ok
+ start, ok = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i)
+ if ok then
+ success = true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ if start then start = start.next end
+ else
+ start = start.next
+ end
+ -- elseif id == glue then
+ -- if p[5] then -- chain
+ -- local pc = pp[32]
+ -- if pc then
+ -- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
+ -- if ok then
+ -- done = true
+ -- end
+ -- if start then start = start.next end
+ -- else
+ -- start = start.next
+ -- end
+ -- else
+ -- start = start.next
+ -- end
+ elseif id == whatsit then
+ local subtype = start.subtype
+ local subtype = start.subtype
+ if subtype == 7 then
+ local dir = start.dir
+ if dir == "+TRT" or dir == "+TLT" then
+ insert(txtdir,dir)
+ elseif dir == "-TRT" or dir == "-TLT" then
+ remove(txtdir)
+ end
+ local d = txtdir[#txtdir]
+ if d == "+TRT" then
+ rlmode = -1
+ elseif d == "+TLT" then
+ rlmode = 1
+ else
+ rlmode = pardir
+ end
+ if trace_directions then
+ logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ end
+ elseif subtype == 6 then
+ local dir = start.dir
+ if dir == "TRT" then
+ pardir = -1
+ elseif dir == "TLT" then
+ pardir = 1
+ else
+ pardir = 0
+ end
+ rlmode = pardir
+ --~ txtdir = { }
+ if trace_directions then
+ logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ end
+ end
+ start = start.next
+ else
+ start = start.next
+ end
+ end
+ end
+ end
+ if success then
+ done = true
+ end
+ if trace_steps then -- ?
+ registerstep(head)
+ end
+ end
+ end
+ return head, done
+end
+
+otf.features.prepare = { }
+
+-- we used to share code in the following functions but that costs a lot of
+-- memory due to extensive calls to functions (easily hundreds of thousands per
+-- document)
+
+local function split(replacement,original,cache,unicodes)
+ -- we can cache this too, but not the same (although unicode is a unique enough hash)
+ local o, t, n = { }, { }, 0
+ for s in gmatch(original,"[^ ]+") do
+ local us = unicodes[s]
+ if type(us) == "number" then -- tonumber(us)
+ o[#o+1] = us
+ else
+ o[#o+1] = us[1]
+ end
+ end
+ for s in gmatch(replacement,"[^ ]+") do
+ n = n + 1
+ local us = unicodes[s]
+ if type(us) == "number" then -- tonumber(us)
+ t[o[n]] = us
+ else
+ t[o[n]] = us[1]
+ end
+ end
+ return t
+end
+
+local function uncover(covers,result,cache,unicodes)
+ -- lpeg hardly faster (.005 sec on mk)
+ for n=1,#covers do
+ local c = covers[n]
+ local cc = cache[c]
+ if not cc then
+ local t = { }
+ for s in gmatch(c,"[^ ]+") do
+ local us = unicodes[s]
+ if type(us) == "number" then
+ t[us] = true
+ else
+ for i=1,#us do
+ t[us[i]] = true
+ end
+ end
+ end
+ cache[c] = t
+ result[#result+1] = t
+ else
+ result[#result+1] = cc
+ end
+ end
+end
+
+local function prepare_lookups(tfmdata)
+ local otfdata = tfmdata.shared.otfdata
+ local featuredata = otfdata.shared.featuredata
+ local anchor_to_lookup = otfdata.luatex.anchor_to_lookup
+ local lookup_to_anchor = otfdata.luatex.lookup_to_anchor
+ --
+ local multiple = featuredata.gsub_multiple
+ local alternate = featuredata.gsub_alternate
+ local single = featuredata.gsub_single
+ local ligature = featuredata.gsub_ligature
+ local pair = featuredata.gpos_pair
+ local position = featuredata.gpos_single
+ local kerns = featuredata.gpos_pair
+ local mark = featuredata.gpos_mark2mark
+ local cursive = featuredata.gpos_cursive
+ --
+ local unicodes = tfmdata.unicodes -- names to unicodes
+ local indices = tfmdata.indices
+ local descriptions = tfmdata.descriptions
+ --
+ -- we can change the otf table after loading but then we need to adapt base mode
+ -- as well (no big deal)
+ --
+ local action = {
+ substitution = function(p,lookup,k,glyph,unicode)
+ local old, new = unicode, unicodes[p[2]]
+ if type(new) == "table" then
+ new = new[1]
+ end
+ local s = single[lookup]
+ if not s then s = { } single[lookup] = s end
+ s[old] = new
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: substitution %s => %s",lookup,old,new)
+ --~ end
+ end,
+ multiple = function (p,lookup,k,glyph,unicode)
+ local old, new = unicode, { }
+ local m = multiple[lookup]
+ if not m then m = { } multiple[lookup] = m end
+ m[old] = new
+ for pc in gmatch(p[2],"[^ ]+") do
+ local upc = unicodes[pc]
+ if type(upc) == "number" then
+ new[#new+1] = upc
+ else
+ new[#new+1] = upc[1]
+ end
+ end
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: multiple %s => %s",lookup,old,concat(new," "))
+ --~ end
+ end,
+ alternate = function(p,lookup,k,glyph,unicode)
+ local old, new = unicode, { }
+ local a = alternate[lookup]
+ if not a then a = { } alternate[lookup] = a end
+ a[old] = new
+ for pc in gmatch(p[2],"[^ ]+") do
+ local upc = unicodes[pc]
+ if type(upc) == "number" then
+ new[#new+1] = upc
+ else
+ new[#new+1] = upc[1]
+ end
+ end
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: alternate %s => %s",lookup,old,concat(new,"|"))
+ --~ end
+ end,
+ ligature = function (p,lookup,k,glyph,unicode)
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: ligature %s => %s",lookup,p[2],glyph.name)
+ --~ end
+ local first = true
+ local t = ligature[lookup]
+ if not t then t = { } ligature[lookup] = t end
+ for s in gmatch(p[2],"[^ ]+") do
+ if first then
+ local u = unicodes[s]
+ if not u then
+ logs.report("define otf","lookup %s: ligature %s => %s ignored due to invalid unicode",lookup,p[2],glyph.name)
+ break
+ elseif type(u) == "number" then
+ if not t[u] then
+ t[u] = { { } }
+ end
+ t = t[u]
+ else
+ local tt = t
+ local tu
+ for i=1,#u do
+ local u = u[i]
+ if i==1 then
+ if not t[u] then
+ t[u] = { { } }
+ end
+ tu = t[u]
+ t = tu
+ else
+ if not t[u] then
+ tt[u] = tu
+ end
+ end
+ end
+ end
+ first = false
+ else
+ s = unicodes[s]
+ local t1 = t[1]
+ if not t1[s] then
+ t1[s] = { { } }
+ end
+ t = t1[s]
+ end
+ end
+ t[2] = unicode
+ end,
+ position = function(p,lookup,k,glyph,unicode)
+ -- not used
+ local s = position[lookup]
+ if not s then s = { } position[lookup] = s end
+ s[unicode] = p[2] -- direct pointer to kern spec
+ end,
+ pair = function(p,lookup,k,glyph,unicode)
+ local s = pair[lookup]
+ if not s then s = { } pair[lookup] = s end
+ local others = s[unicode]
+ if not others then others = { } s[unicode] = others end
+ -- todo: fast check for space
+ local two = p[2]
+ local upc = unicodes[two]
+ if not upc then
+ for pc in gmatch(two,"[^ ]+") do
+ local upc = unicodes[pc]
+ if type(upc) == "number" then
+ others[upc] = p -- direct pointer to main table
+ else
+ for i=1,#upc do
+ others[upc[i]] = p -- direct pointer to main table
+ end
+ end
+ end
+ elseif type(upc) == "number" then
+ others[upc] = p -- direct pointer to main table
+ else
+ for i=1,#upc do
+ others[upc[i]] = p -- direct pointer to main table
+ end
+ end
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: pair for U+%04X",lookup,unicode)
+ --~ end
+ end,
+ }
+ --
+ for unicode, glyph in next, descriptions do
+ local lookups = glyph.slookups
+ if lookups then
+ for lookup, p in next, lookups do
+ action[p[1]](p,lookup,k,glyph,unicode)
+ end
+ end
+ local lookups = glyph.mlookups
+ if lookups then
+ for lookup, whatever in next, lookups do
+ for i=1,#whatever do -- normaly one
+ local p = whatever[i]
+ action[p[1]](p,lookup,k,glyph,unicode)
+ end
+ end
+ end
+ local list = glyph.mykerns
+ if list then
+ for lookup, krn in next, list do
+ local k = kerns[lookup]
+ if not k then k = { } kerns[lookup] = k end
+ k[unicode] = krn -- ref to glyph, saves lookup
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: kern for U+%04X",lookup,unicode)
+ --~ end
+ end
+ end
+ local oanchor = glyph.anchors
+ if oanchor then
+ for typ, anchors in next, oanchor do -- types
+ if typ == "mark" then
+ for name, anchor in next, anchors do
+ local lookups = anchor_to_lookup[name]
+ if lookups then
+ for lookup, _ in next, lookups do
+ local f = mark[lookup]
+ if not f then f = { } mark[lookup] = f end
+ f[unicode] = anchors -- ref to glyph, saves lookup
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: mark anchor %s for U+%04X",lookup,name,unicode)
+ --~ end
+ end
+ end
+ end
+ elseif typ == "cexit" then -- or entry?
+ for name, anchor in next, anchors do
+ local lookups = anchor_to_lookup[name]
+ if lookups then
+ for lookup, _ in next, lookups do
+ local f = cursive[lookup]
+ if not f then f = { } cursive[lookup] = f end
+ f[unicode] = anchors -- ref to glyph, saves lookup
+ --~ if trace_lookups then
+ --~ logs.report("define otf","lookup %s: exit anchor %s for U+%04X",lookup,name,unicode)
+ --~ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+-- local cache = { }
+luatex = luatex or {} -- this has to change ... we need a better one
+
+function prepare_contextchains(tfmdata)
+ local otfdata = tfmdata.shared.otfdata
+ local lookups = otfdata.lookups
+ if lookups then
+ local featuredata = otfdata.shared.featuredata
+ local contextchain = featuredata.gsub_contextchain -- shared with gpos
+ local reversecontextchain = featuredata.gsub_reversecontextchain -- shared with gpos
+ local characters = tfmdata.characters
+ local unicodes = tfmdata.unicodes
+ local indices = tfmdata.indices
+ local cache = luatex.covers
+ if not cache then
+ cache = { }
+ luatex.covers = cache
+ end
+ --
+ for lookupname, lookupdata in next, otfdata.lookups do
+ local lookuptype = lookupdata.type
+ if not lookuptype then
+ logs.report("otf process","missing lookuptype for %s",lookupname)
+ else
+ local rules = lookupdata.rules
+ if rules then
+ local fmt = lookupdata.format
+ -- contextchain[lookupname][unicode]
+ if fmt == "coverage" then
+ if lookuptype ~= "chainsub" and lookuptype ~= "chainpos" then
+ logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname)
+ else
+ local contexts = contextchain[lookupname]
+ if not contexts then
+ contexts = { }
+ contextchain[lookupname] = contexts
+ end
+ local t = { }
+ for nofrules=1,#rules do -- does #rules>1 happen often?
+ local rule = rules[nofrules]
+ local coverage = rule.coverage
+ if coverage and coverage.current then
+ local current, before, after, sequence = coverage.current, coverage.before, coverage.after, { }
+ if before then
+ uncover(before,sequence,cache,unicodes)
+ end
+ local start = #sequence + 1
+ uncover(current,sequence,cache,unicodes)
+ local stop = #sequence
+ if after then
+ uncover(after,sequence,cache,unicodes)
+ end
+ if sequence[1] then
+ t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
+ for unic, _ in next, sequence[start] do
+ local cu = contexts[unic]
+ if not cu then
+ contexts[unic] = t
+ end
+ end
+ end
+ end
+ end
+ end
+ elseif fmt == "reversecoverage" then
+ if lookuptype ~= "reversesub" then
+ logs.report("otf process","unsupported reverse coverage %s for %s",lookuptype,lookupname)
+ else
+ local contexts = reversecontextchain[lookupname]
+ if not contexts then
+ contexts = { }
+ reversecontextchain[lookupname] = contexts
+ end
+ local t = { }
+ for nofrules=1,#rules do
+ local rule = rules[nofrules]
+ local reversecoverage = rule.reversecoverage
+ if reversecoverage and reversecoverage.current then
+ local current, before, after, replacements, sequence = reversecoverage.current, reversecoverage.before, reversecoverage.after, reversecoverage.replacements, { }
+ if before then
+ uncover(before,sequence,cache,unicodes)
+ end
+ local start = #sequence + 1
+ uncover(current,sequence,cache,unicodes)
+ local stop = #sequence
+ if after then
+ uncover(after,sequence,cache,unicodes)
+ end
+ if replacements then
+ replacements = split(replacements,current[1],cache,unicodes)
+ end
+ if sequence[1] then
+ -- this is different from normal coverage, we assume only replacements
+ t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
+ for unic, _ in next, sequence[start] do
+ local cu = contexts[unic]
+ if not cu then
+ contexts[unic] = t
+ end
+ end
+ end
+ end
+ end
+ end
+ elseif fmt == "glyphs" then
+ if lookuptype ~= "chainsub" and lookuptype ~= "chainpos" then
+ logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname)
+ else
+ local contexts = contextchain[lookupname]
+ if not contexts then
+ contexts = { }
+ contextchain[lookupname] = contexts
+ end
+ local t = { }
+ for nofrules=1,#rules do
+ -- nearly the same as coverage so we could as well rename it
+ local rule = rules[nofrules]
+ local glyphs = rule.glyphs
+ if glyphs and glyphs.names then
+ local fore, back, names, sequence = glyphs.fore, glyphs.back, glyphs.names, { }
+ if fore and fore ~= "" then
+ fore = lpegmatch(split_at_space,fore)
+ uncover(fore,sequence,cache,unicodes)
+ end
+ local start = #sequence + 1
+ names = lpegmatch(split_at_space,names)
+ uncover(names,sequence,cache,unicodes)
+ local stop = #sequence
+ if back and back ~= "" then
+ back = lpegmatch(split_at_space,back)
+ uncover(back,sequence,cache,unicodes)
+ end
+ if sequence[1] then
+ t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }
+ for unic, _ in next, sequence[start] do
+ local cu = contexts[unic]
+ if not cu then
+ contexts[unic] = t
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function fonts.initializers.node.otf.features(tfmdata,value)
+ if true then -- value then
+ if not tfmdata.shared.otfdata.shared.initialized then
+ local t = trace_preparing and os.clock()
+ local otfdata = tfmdata.shared.otfdata
+ local featuredata = otfdata.shared.featuredata
+ -- caches
+ featuredata.gsub_multiple = { }
+ featuredata.gsub_alternate = { }
+ featuredata.gsub_single = { }
+ featuredata.gsub_ligature = { }
+ featuredata.gsub_contextchain = { }
+ featuredata.gsub_reversecontextchain = { }
+ featuredata.gpos_pair = { }
+ featuredata.gpos_single = { }
+ featuredata.gpos_mark2base = { }
+ featuredata.gpos_mark2ligature = featuredata.gpos_mark2base
+ featuredata.gpos_mark2mark = featuredata.gpos_mark2base
+ featuredata.gpos_cursive = { }
+ featuredata.gpos_contextchain = featuredata.gsub_contextchain
+ featuredata.gpos_reversecontextchain = featuredata.gsub_reversecontextchain
+ --
+ prepare_contextchains(tfmdata)
+ prepare_lookups(tfmdata)
+ otfdata.shared.initialized = true
+ if trace_preparing then
+ logs.report("otf process","preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?")
+ end
+ end
+ end
+end
diff --git a/tex/context/base/font-otp.lua b/tex/context/base/font-otp.lua
new file mode 100644
index 000000000..a80c515ad
--- /dev/null
+++ b/tex/context/base/font-otp.lua
@@ -0,0 +1,504 @@
+if not modules then modules = { } end modules ['font-otp'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (packing)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: pack math (but not that much to share)
+
+local next, type, tostring = next, type, tostring
+local sort, concat = table.sort, table.concat
+
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+
+fonts = fonts or { }
+fonts.otf = fonts.otf or { }
+fonts.otf.enhancers = fonts.otf.enhancers or { }
+fonts.otf.glists = fonts.otf.glists or { "gsub", "gpos" }
+
+local criterium, threshold, tabstr = 1, 0, table.serialize
+
+local function tabstr(t) -- hashed from core-uti / experiment
+ local s = { }
+ for k, v in next, t do
+ if type(v) == "table" then
+ s[#s+1] = k.."={"..tabstr(v).."}"
+ else
+ s[#s+1] = k.."="..tostring(v)
+ end
+ end
+ sort(s)
+ return concat(s,",")
+end
+
+function fonts.otf.enhancers.pack(data)
+ if data then
+ local h, t, c = { }, { }, { }
+ local hh, tt, cc = { }, { }, { }
+ local function pack_1(v)
+ -- v == table
+ local tag = tabstr(v)
+ local ht = h[tag]
+ if not ht then
+ ht = #t+1
+ t[ht] = v
+ h[tag] = ht
+ c[ht] = 1
+ else
+ c[ht] = c[ht] + 1
+ end
+ return ht
+ end
+ local function pack_2(v)
+ -- v == number
+ if c[v] <= criterium then
+ return t[v]
+ else
+ -- compact hash
+ local hv = hh[v]
+ if not hv then
+ hv = #tt+1
+ tt[hv] = t[v]
+ hh[v] = hv
+ cc[hv] = c[v]
+ end
+ return hv
+ end
+ end
+ local function success(stage,pass)
+ if #t == 0 then
+ if trace_loading then
+ logs.report("load otf","pack quality: nothing to pack")
+ end
+ return false
+ elseif #t >= threshold then
+ local one, two, rest = 0, 0, 0
+ if pass == 1 then
+ for k,v in next, c do
+ if v == 1 then
+ one = one + 1
+ elseif v == 2 then
+ two = two + 1
+ else
+ rest = rest + 1
+ end
+ end
+ else
+ for k,v in next, cc do
+ if v >20 then
+ rest = rest + 1
+ elseif v >10 then
+ two = two + 1
+ else
+ one = one + 1
+ end
+ end
+ data.tables = tt
+ end
+ if trace_loading then
+ logs.report("load otf","pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)", stage, pass, one+two+rest, one, two, rest, criterium)
+ end
+ return true
+ else
+ if trace_loading then
+ logs.report("load otf","pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)", stage, pass, #t, threshold)
+ end
+ return false
+ end
+ end
+ for pass=1,2 do
+ local pack = (pass == 1 and pack_1) or pack_2
+ for k, v in next, data.glyphs do
+ v.boundingbox = pack(v.boundingbox)
+ local l = v.slookups
+ if l then
+ for k,v in next, l do
+ l[k] = pack(v)
+ end
+ end
+ local l = v.mlookups
+ if l then
+ for k,v in next, l do
+ for kk=1,#v do
+ local vkk = v[kk]
+ local what = vkk[1]
+ if what == "pair" then
+ local t = vkk[3] if t then vkk[3] = pack(t) end
+ local t = vkk[4] if t then vkk[4] = pack(t) end
+ elseif what == "position" then
+ local t = vkk[2] if t then vkk[2] = pack(t) end
+ end
+ -- v[kk] = pack(vkk)
+ end
+ end
+ end
+ local m = v.mykerns
+ if m then
+ for k,v in next, m do
+ m[k] = pack(v)
+ end
+ end
+ local m = v.math
+ if m then
+ local mk = m.kerns
+ if mk then
+ for k,v in next, mk do
+ mk[k] = pack(v)
+ end
+ end
+ end
+ local a = v.anchors
+ if a then
+ for k,v in next, a do
+ if k == "baselig" then
+ for kk, vv in next, v do
+ for kkk=1,#vv do
+ vv[kkk] = pack(vv[kkk])
+ end
+ end
+ else
+ for kk, vv in next, v do
+ v[kk] = pack(vv)
+ end
+ end
+ end
+ end
+ end
+ if data.lookups then
+ for k, v in next, data.lookups do
+ if v.rules then
+ for kk, vv in next, v.rules do
+ local l = vv.lookups
+ if l then
+ vv.lookups = pack(l)
+ end
+ local c = vv.coverage
+ if c then
+ local cc = c.before if cc then c.before = pack(cc) end
+ local cc = c.after if cc then c.after = pack(cc) end
+ local cc = c.current if cc then c.current = pack(cc) end
+ end
+ local c = vv.reversecoverage
+ if c then
+ local cc = c.before if cc then c.before = pack(cc) end
+ local cc = c.after if cc then c.after = pack(cc) end
+ local cc = c.current if cc then c.current = pack(cc) end
+ end
+ -- no need to pack vv.glyphs
+ local c = vv.glyphs
+ if c then
+ if c.fore == "" then c.fore = nil end
+ if c.back == "" then c.back = nil end
+ end
+ end
+ end
+ end
+ end
+ if data.luatex then
+ local la = data.luatex.anchor_to_lookup
+ if la then
+ for lookup, ldata in next, la do
+ la[lookup] = pack(ldata)
+ end
+ end
+ local la = data.luatex.lookup_to_anchor
+ if la then
+ for lookup, ldata in next, la do
+ la[lookup] = pack(ldata)
+ end
+ end
+ local ls = data.luatex.sequences
+ if ls then
+ for feature, fdata in next, ls do
+ local flags = fdata.flags
+ if flags then
+ fdata.flags = pack(flags)
+ end
+ local subtables = fdata.subtables
+ if subtables then
+ fdata.subtables = pack(subtables)
+ end
+ local features = fdata.features
+ if features then
+ for script, sdata in next, features do
+ features[script] = pack(sdata)
+ end
+ end
+ end
+ end
+ local ls = data.luatex.lookups
+ if ls then
+ for lookup, fdata in next, ls do
+ local flags = fdata.flags
+ if flags then
+ fdata.flags = pack(flags)
+ end
+ local subtables = fdata.subtables
+ if subtables then
+ fdata.subtables = pack(subtables)
+ end
+ end
+ end
+ local lf = data.luatex.features
+ if lf then
+ for _, g in next, fonts.otf.glists do
+ local gl = lf[g]
+ if gl then
+ for feature, spec in next, gl do
+ gl[feature] = pack(spec)
+ end
+ end
+ end
+ end
+ end
+ if not success(1,pass) then
+ return
+ end
+ end
+ if #t > 0 then
+ for pass=1,2 do
+ local pack = (pass == 1 and pack_1) or pack_2
+ for k, v in next, data.glyphs do
+ local m = v.mykerns
+ if m then
+ v.mykerns = pack(m)
+ end
+ local m = v.math
+ if m then
+ local mk = m.kerns
+ if mk then
+ m.kerns = pack(mk)
+ end
+ end
+ local a = v.anchors
+ if a then
+ v.anchors = pack(a)
+ end
+ local l = v.mlookups
+ if l then
+ for k,v in next, l do
+ for kk=1,#v do
+ v[kk] = pack(v[kk])
+ end
+ end
+ end
+ end
+ local ls = data.luatex.sequences
+ if ls then
+ for feature, fdata in next, ls do
+ fdata.features = pack(fdata.features)
+ end
+ end
+ if not success(2,pass) then
+--~ return
+ end
+ end
+ end
+ end
+end
+
+function fonts.otf.enhancers.unpack(data)
+ if data then
+ local t = data.tables
+ if t then
+ local unpacked = { }
+ for k, v in next, data.glyphs do
+ local tv = t[v.boundingbox] if tv then v.boundingbox = tv end
+ local l = v.slookups
+ if l then
+ for k,v in next, l do
+ local tv = t[v] if tv then l[k] = tv end
+ end
+ end
+ local l = v.mlookups
+ if l then
+ for k,v in next, l do
+ for i=1,#v do
+ local vi = v[i]
+ local tv = t[vi]
+ if tv then
+ v[i] = tv
+ if unpacked[tv] then
+ vi = false
+ else
+ unpacked[tv], vi = true, tv
+ end
+ end
+ if vi then
+ local what = vi[1]
+ if what == "pair" then
+ local tv = t[vi[3]] if tv then vi[3] = tv end
+ local tv = t[vi[4]] if tv then vi[4] = tv end
+ elseif what == "position" then
+ local tv = t[vi[2]] if tv then vi[2] = tv end
+ end
+ end
+ end
+ end
+ end
+ local m = v.mykerns
+ if m then
+ local tm = t[m]
+ if tm then
+ v.mykerns = tm
+ if unpacked[tm] then
+ m = false
+ else
+ unpacked[tm], m = true, tm
+ end
+ end
+ if m then
+ for k,v in next, m do
+ local tv = t[v] if tv then m[k] = tv end
+ end
+ end
+ end
+ local m = v.math
+ if m then
+ local mk = m.kerns
+ if mk then
+ local tm = t[mk]
+ if tm then
+ m.kerns = tm
+ if unpacked[tm] then
+ mk = false
+ else
+ unpacked[tm], mk = true, tm
+ end
+ end
+ if mk then
+ for k,v in next, mk do
+ local tv = t[v] if tv then mk[k] = tv end
+ end
+ end
+ end
+ end
+ local a = v.anchors
+ if a then
+ local ta = t[a]
+ if ta then
+ v.anchors = ta
+ if not unpacked[ta] then
+ unpacked[ta], a = true, ta
+ else
+ a = false
+ end
+ end
+ if a then
+ for k,v in next, a do
+ if k == "baselig" then
+ for kk, vv in next, v do
+ for kkk=1,#vv do
+ local tv = t[vv[kkk]] if tv then vv[kkk] = tv end
+ end
+ end
+ else
+ for kk, vv in next, v do
+ local tv = t[vv] if tv then v[kk] = tv end
+ end
+ end
+ end
+ end
+ end
+ end
+ if data.lookups then
+ for k, v in next, data.lookups do
+ local r = v.rules
+ if r then
+ for kk, vv in next, r do
+ local l = vv.lookups
+ if l then
+ local tv = t[l] if tv then vv.lookups = tv end
+ end
+ local c = vv.coverage
+ if c then
+ local cc = c.before if cc then local tv = t[cc] if tv then c.before = tv end end
+ cc = c.after if cc then local tv = t[cc] if tv then c.after = tv end end
+ cc = c.current if cc then local tv = t[cc] if tv then c.current = tv end end
+ end
+ local c = vv.reversecoverage
+ if c then
+ local cc = c.before if cc then local tv = t[cc] if tv then c.before = tv end end
+ cc = c.after if cc then local tv = t[cc] if tv then c.after = tv end end
+ cc = c.current if cc then local tv = t[cc] if tv then c.current = tv end end
+ end
+ -- no need to unpack vv.glyphs
+ end
+ end
+ end
+ end
+ local luatex = data.luatex
+ if luatex then
+ local la = luatex.anchor_to_lookup
+ if la then
+ for lookup, ldata in next, la do
+ local tv = t[ldata] if tv then la[lookup] = tv end
+ end
+ end
+ local la = luatex.lookup_to_anchor
+ if la then
+ for lookup, ldata in next, la do
+ local tv = t[ldata] if tv then la[lookup] = tv end
+ end
+ end
+ local ls = luatex.sequences
+ if ls then
+ for feature, fdata in next, ls do
+ local flags = fdata.flags
+ if flags then
+ local tv = t[flags] if tv then fdata.flags = tv end
+ end
+ local subtables = fdata.subtables
+ if subtables then
+ local tv = t[subtables] if tv then fdata.subtables = tv end
+ end
+ local features = fdata.features
+ if features then
+ local tv = t[features]
+ if tv then
+ fdata.features = tv
+ if not unpacked[tv] then
+ unpacked[tv], features = true, tv
+ else
+ features = false
+ end
+ end
+ if features then
+ for script, sdata in next, features do
+ local tv = t[sdata] if tv then features[script] = tv end
+ end
+ end
+ end
+ end
+ end
+ local ls = luatex.lookups
+ if ls then
+ for lookups, fdata in next, ls do
+ local flags = fdata.flags
+ if flags then
+ local tv = t[flags] if tv then fdata.flags = tv end
+ end
+ local subtables = fdata.subtables
+ if subtables then
+ local tv = t[subtables] if tv then fdata.subtables = tv end
+ end
+ end
+ end
+ local lf = luatex.features
+ if lf then
+ for _, g in next, fonts.otf.glists do
+ local gl = lf[g]
+ if gl then
+ for feature, spec in next, gl do
+ local tv = t[spec] if tv then gl[feature] = tv end
+ end
+ end
+ end
+ end
+ end
+ data.tables = nil
+ end
+ end
+end
diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua
new file mode 100644
index 000000000..2be1bf06c
--- /dev/null
+++ b/tex/context/base/font-ott.lua
@@ -0,0 +1,956 @@
+if not modules then modules = { } end modules ['font-otf'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (tables)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next, tonumber, tostring = type, next, tonumber, tostring
+local gsub, lower = string.gsub, string.lower
+
+fonts = fonts or { }
+fonts.otf = fonts.otf or { }
+
+local otf = fonts.otf
+
+otf.tables = otf.tables or { }
+otf.meanings = otf.meanings or { }
+
+otf.tables.scripts = {
+ ['dflt'] = 'Default',
+
+ ['arab'] = 'Arabic',
+ ['armn'] = 'Armenian',
+ ['bali'] = 'Balinese',
+ ['beng'] = 'Bengali',
+ ['bopo'] = 'Bopomofo',
+ ['brai'] = 'Braille',
+ ['bugi'] = 'Buginese',
+ ['buhd'] = 'Buhid',
+ ['byzm'] = 'Byzantine Music',
+ ['cans'] = 'Canadian Syllabics',
+ ['cher'] = 'Cherokee',
+ ['copt'] = 'Coptic',
+ ['cprt'] = 'Cypriot Syllabary',
+ ['cyrl'] = 'Cyrillic',
+ ['deva'] = 'Devanagari',
+ ['dsrt'] = 'Deseret',
+ ['ethi'] = 'Ethiopic',
+ ['geor'] = 'Georgian',
+ ['glag'] = 'Glagolitic',
+ ['goth'] = 'Gothic',
+ ['grek'] = 'Greek',
+ ['gujr'] = 'Gujarati',
+ ['guru'] = 'Gurmukhi',
+ ['hang'] = 'Hangul',
+ ['hani'] = 'CJK Ideographic',
+ ['hano'] = 'Hanunoo',
+ ['hebr'] = 'Hebrew',
+ ['ital'] = 'Old Italic',
+ ['jamo'] = 'Hangul Jamo',
+ ['java'] = 'Javanese',
+ ['kana'] = 'Hiragana and Katakana',
+ ['khar'] = 'Kharosthi',
+ ['khmr'] = 'Khmer',
+ ['knda'] = 'Kannada',
+ ['lao' ] = 'Lao',
+ ['latn'] = 'Latin',
+ ['limb'] = 'Limbu',
+ ['linb'] = 'Linear B',
+ ['math'] = 'Mathematical Alphanumeric Symbols',
+ ['mlym'] = 'Malayalam',
+ ['mong'] = 'Mongolian',
+ ['musc'] = 'Musical Symbols',
+ ['mymr'] = 'Myanmar',
+ ['nko' ] = "N'ko",
+ ['ogam'] = 'Ogham',
+ ['orya'] = 'Oriya',
+ ['osma'] = 'Osmanya',
+ ['phag'] = 'Phags-pa',
+ ['phnx'] = 'Phoenician',
+ ['runr'] = 'Runic',
+ ['shaw'] = 'Shavian',
+ ['sinh'] = 'Sinhala',
+ ['sylo'] = 'Syloti Nagri',
+ ['syrc'] = 'Syriac',
+ ['tagb'] = 'Tagbanwa',
+ ['tale'] = 'Tai Le',
+ ['talu'] = 'Tai Lu',
+ ['taml'] = 'Tamil',
+ ['telu'] = 'Telugu',
+ ['tfng'] = 'Tifinagh',
+ ['tglg'] = 'Tagalog',
+ ['thaa'] = 'Thaana',
+ ['thai'] = 'Thai',
+ ['tibt'] = 'Tibetan',
+ ['ugar'] = 'Ugaritic Cuneiform',
+ ['xpeo'] = 'Old Persian Cuneiform',
+ ['xsux'] = 'Sumero-Akkadian Cuneiform',
+ ['yi' ] = 'Yi',
+}
+
+otf.tables.languages = {
+ ['dflt'] = 'Default',
+
+ ['aba'] = 'Abaza',
+ ['abk'] = 'Abkhazian',
+ ['ady'] = 'Adyghe',
+ ['afk'] = 'Afrikaans',
+ ['afr'] = 'Afar',
+ ['agw'] = 'Agaw',
+ ['als'] = 'Alsatian',
+ ['alt'] = 'Altai',
+ ['amh'] = 'Amharic',
+ ['ara'] = 'Arabic',
+ ['ari'] = 'Aari',
+ ['ark'] = 'Arakanese',
+ ['asm'] = 'Assamese',
+ ['ath'] = 'Athapaskan',
+ ['avr'] = 'Avar',
+ ['awa'] = 'Awadhi',
+ ['aym'] = 'Aymara',
+ ['aze'] = 'Azeri',
+ ['bad'] = 'Badaga',
+ ['bag'] = 'Baghelkhandi',
+ ['bal'] = 'Balkar',
+ ['bau'] = 'Baule',
+ ['bbr'] = 'Berber',
+ ['bch'] = 'Bench',
+ ['bcr'] = 'Bible Cree',
+ ['bel'] = 'Belarussian',
+ ['bem'] = 'Bemba',
+ ['ben'] = 'Bengali',
+ ['bgr'] = 'Bulgarian',
+ ['bhi'] = 'Bhili',
+ ['bho'] = 'Bhojpuri',
+ ['bik'] = 'Bikol',
+ ['bil'] = 'Bilen',
+ ['bkf'] = 'Blackfoot',
+ ['bli'] = 'Balochi',
+ ['bln'] = 'Balante',
+ ['blt'] = 'Balti',
+ ['bmb'] = 'Bambara',
+ ['bml'] = 'Bamileke',
+ ['bos'] = 'Bosnian',
+ ['bre'] = 'Breton',
+ ['brh'] = 'Brahui',
+ ['bri'] = 'Braj Bhasha',
+ ['brm'] = 'Burmese',
+ ['bsh'] = 'Bashkir',
+ ['bti'] = 'Beti',
+ ['cat'] = 'Catalan',
+ ['ceb'] = 'Cebuano',
+ ['che'] = 'Chechen',
+ ['chg'] = 'Chaha Gurage',
+ ['chh'] = 'Chattisgarhi',
+ ['chi'] = 'Chichewa',
+ ['chk'] = 'Chukchi',
+ ['chp'] = 'Chipewyan',
+ ['chr'] = 'Cherokee',
+ ['chu'] = 'Chuvash',
+ ['cmr'] = 'Comorian',
+ ['cop'] = 'Coptic',
+ ['cos'] = 'Corsican',
+ ['cre'] = 'Cree',
+ ['crr'] = 'Carrier',
+ ['crt'] = 'Crimean Tatar',
+ ['csl'] = 'Church Slavonic',
+ ['csy'] = 'Czech',
+ ['dan'] = 'Danish',
+ ['dar'] = 'Dargwa',
+ ['dcr'] = 'Woods Cree',
+ ['deu'] = 'German',
+ ['dgr'] = 'Dogri',
+ ['div'] = 'Divehi',
+ ['djr'] = 'Djerma',
+ ['dng'] = 'Dangme',
+ ['dnk'] = 'Dinka',
+ ['dri'] = 'Dari',
+ ['dun'] = 'Dungan',
+ ['dzn'] = 'Dzongkha',
+ ['ebi'] = 'Ebira',
+ ['ecr'] = 'Eastern Cree',
+ ['edo'] = 'Edo',
+ ['efi'] = 'Efik',
+ ['ell'] = 'Greek',
+ ['eng'] = 'English',
+ ['erz'] = 'Erzya',
+ ['esp'] = 'Spanish',
+ ['eti'] = 'Estonian',
+ ['euq'] = 'Basque',
+ ['evk'] = 'Evenki',
+ ['evn'] = 'Even',
+ ['ewe'] = 'Ewe',
+ ['fan'] = 'French Antillean',
+ ['far'] = 'Farsi',
+ ['fin'] = 'Finnish',
+ ['fji'] = 'Fijian',
+ ['fle'] = 'Flemish',
+ ['fne'] = 'Forest Nenets',
+ ['fon'] = 'Fon',
+ ['fos'] = 'Faroese',
+ ['fra'] = 'French',
+ ['fri'] = 'Frisian',
+ ['frl'] = 'Friulian',
+ ['fta'] = 'Futa',
+ ['ful'] = 'Fulani',
+ ['gad'] = 'Ga',
+ ['gae'] = 'Gaelic',
+ ['gag'] = 'Gagauz',
+ ['gal'] = 'Galician',
+ ['gar'] = 'Garshuni',
+ ['gaw'] = 'Garhwali',
+ ['gez'] = "Ge'ez",
+ ['gil'] = 'Gilyak',
+ ['gmz'] = 'Gumuz',
+ ['gon'] = 'Gondi',
+ ['grn'] = 'Greenlandic',
+ ['gro'] = 'Garo',
+ ['gua'] = 'Guarani',
+ ['guj'] = 'Gujarati',
+ ['hai'] = 'Haitian',
+ ['hal'] = 'Halam',
+ ['har'] = 'Harauti',
+ ['hau'] = 'Hausa',
+ ['haw'] = 'Hawaiin',
+ ['hbn'] = 'Hammer-Banna',
+ ['hil'] = 'Hiligaynon',
+ ['hin'] = 'Hindi',
+ ['hma'] = 'High Mari',
+ ['hnd'] = 'Hindko',
+ ['ho'] = 'Ho',
+ ['hri'] = 'Harari',
+ ['hrv'] = 'Croatian',
+ ['hun'] = 'Hungarian',
+ ['hye'] = 'Armenian',
+ ['ibo'] = 'Igbo',
+ ['ijo'] = 'Ijo',
+ ['ilo'] = 'Ilokano',
+ ['ind'] = 'Indonesian',
+ ['ing'] = 'Ingush',
+ ['inu'] = 'Inuktitut',
+ ['iri'] = 'Irish',
+ ['irt'] = 'Irish Traditional',
+ ['isl'] = 'Icelandic',
+ ['ism'] = 'Inari Sami',
+ ['ita'] = 'Italian',
+ ['iwr'] = 'Hebrew',
+ ['jan'] = 'Japanese',
+ ['jav'] = 'Javanese',
+ ['jii'] = 'Yiddish',
+ ['jud'] = 'Judezmo',
+ ['jul'] = 'Jula',
+ ['kab'] = 'Kabardian',
+ ['kac'] = 'Kachchi',
+ ['kal'] = 'Kalenjin',
+ ['kan'] = 'Kannada',
+ ['kar'] = 'Karachay',
+ ['kat'] = 'Georgian',
+ ['kaz'] = 'Kazakh',
+ ['keb'] = 'Kebena',
+ ['kge'] = 'Khutsuri Georgian',
+ ['kha'] = 'Khakass',
+ ['khk'] = 'Khanty-Kazim',
+ ['khm'] = 'Khmer',
+ ['khs'] = 'Khanty-Shurishkar',
+ ['khv'] = 'Khanty-Vakhi',
+ ['khw'] = 'Khowar',
+ ['kik'] = 'Kikuyu',
+ ['kir'] = 'Kirghiz',
+ ['kis'] = 'Kisii',
+ ['kkn'] = 'Kokni',
+ ['klm'] = 'Kalmyk',
+ ['kmb'] = 'Kamba',
+ ['kmn'] = 'Kumaoni',
+ ['kmo'] = 'Komo',
+ ['kms'] = 'Komso',
+ ['knr'] = 'Kanuri',
+ ['kod'] = 'Kodagu',
+ ['koh'] = 'Korean Old Hangul',
+ ['kok'] = 'Konkani',
+ ['kon'] = 'Kikongo',
+ ['kop'] = 'Komi-Permyak',
+ ['kor'] = 'Korean',
+ ['koz'] = 'Komi-Zyrian',
+ ['kpl'] = 'Kpelle',
+ ['kri'] = 'Krio',
+ ['krk'] = 'Karakalpak',
+ ['krl'] = 'Karelian',
+ ['krm'] = 'Karaim',
+ ['krn'] = 'Karen',
+ ['krt'] = 'Koorete',
+ ['ksh'] = 'Kashmiri',
+ ['ksi'] = 'Khasi',
+ ['ksm'] = 'Kildin Sami',
+ ['kui'] = 'Kui',
+ ['kul'] = 'Kulvi',
+ ['kum'] = 'Kumyk',
+ ['kur'] = 'Kurdish',
+ ['kuu'] = 'Kurukh',
+ ['kuy'] = 'Kuy',
+ ['kyk'] = 'Koryak',
+ ['lad'] = 'Ladin',
+ ['lah'] = 'Lahuli',
+ ['lak'] = 'Lak',
+ ['lam'] = 'Lambani',
+ ['lao'] = 'Lao',
+ ['lat'] = 'Latin',
+ ['laz'] = 'Laz',
+ ['lcr'] = 'L-Cree',
+ ['ldk'] = 'Ladakhi',
+ ['lez'] = 'Lezgi',
+ ['lin'] = 'Lingala',
+ ['lma'] = 'Low Mari',
+ ['lmb'] = 'Limbu',
+ ['lmw'] = 'Lomwe',
+ ['lsb'] = 'Lower Sorbian',
+ ['lsm'] = 'Lule Sami',
+ ['lth'] = 'Lithuanian',
+ ['ltz'] = 'Luxembourgish',
+ ['lub'] = 'Luba',
+ ['lug'] = 'Luganda',
+ ['luh'] = 'Luhya',
+ ['luo'] = 'Luo',
+ ['lvi'] = 'Latvian',
+ ['maj'] = 'Majang',
+ ['mak'] = 'Makua',
+ ['mal'] = 'Malayalam Traditional',
+ ['man'] = 'Mansi',
+ ['map'] = 'Mapudungun',
+ ['mar'] = 'Marathi',
+ ['maw'] = 'Marwari',
+ ['mbn'] = 'Mbundu',
+ ['mch'] = 'Manchu',
+ ['mcr'] = 'Moose Cree',
+ ['mde'] = 'Mende',
+ ['men'] = "Me'en",
+ ['miz'] = 'Mizo',
+ ['mkd'] = 'Macedonian',
+ ['mle'] = 'Male',
+ ['mlg'] = 'Malagasy',
+ ['mln'] = 'Malinke',
+ ['mlr'] = 'Malayalam Reformed',
+ ['mly'] = 'Malay',
+ ['mnd'] = 'Mandinka',
+ ['mng'] = 'Mongolian',
+ ['mni'] = 'Manipuri',
+ ['mnk'] = 'Maninka',
+ ['mnx'] = 'Manx Gaelic',
+ ['moh'] = 'Mohawk',
+ ['mok'] = 'Moksha',
+ ['mol'] = 'Moldavian',
+ ['mon'] = 'Mon',
+ ['mor'] = 'Moroccan',
+ ['mri'] = 'Maori',
+ ['mth'] = 'Maithili',
+ ['mts'] = 'Maltese',
+ ['mun'] = 'Mundari',
+ ['nag'] = 'Naga-Assamese',
+ ['nan'] = 'Nanai',
+ ['nas'] = 'Naskapi',
+ ['ncr'] = 'N-Cree',
+ ['ndb'] = 'Ndebele',
+ ['ndg'] = 'Ndonga',
+ ['nep'] = 'Nepali',
+ ['new'] = 'Newari',
+ ['ngr'] = 'Nagari',
+ ['nhc'] = 'Norway House Cree',
+ ['nis'] = 'Nisi',
+ ['niu'] = 'Niuean',
+ ['nkl'] = 'Nkole',
+ ['nko'] = "N'ko",
+ ['nld'] = 'Dutch',
+ ['nog'] = 'Nogai',
+ ['nor'] = 'Norwegian',
+ ['nsm'] = 'Northern Sami',
+ ['nta'] = 'Northern Tai',
+ ['nto'] = 'Esperanto',
+ ['nyn'] = 'Nynorsk',
+ ['oci'] = 'Occitan',
+ ['ocr'] = 'Oji-Cree',
+ ['ojb'] = 'Ojibway',
+ ['ori'] = 'Oriya',
+ ['oro'] = 'Oromo',
+ ['oss'] = 'Ossetian',
+ ['paa'] = 'Palestinian Aramaic',
+ ['pal'] = 'Pali',
+ ['pan'] = 'Punjabi',
+ ['pap'] = 'Palpa',
+ ['pas'] = 'Pashto',
+ ['pgr'] = 'Polytonic Greek',
+ ['pil'] = 'Pilipino',
+ ['plg'] = 'Palaung',
+ ['plk'] = 'Polish',
+ ['pro'] = 'Provencal',
+ ['ptg'] = 'Portuguese',
+ ['qin'] = 'Chin',
+ ['raj'] = 'Rajasthani',
+ ['rbu'] = 'Russian Buriat',
+ ['rcr'] = 'R-Cree',
+ ['ria'] = 'Riang',
+ ['rms'] = 'Rhaeto-Romanic',
+ ['rom'] = 'Romanian',
+ ['roy'] = 'Romany',
+ ['rsy'] = 'Rusyn',
+ ['rua'] = 'Ruanda',
+ ['rus'] = 'Russian',
+ ['sad'] = 'Sadri',
+ ['san'] = 'Sanskrit',
+ ['sat'] = 'Santali',
+ ['say'] = 'Sayisi',
+ ['sek'] = 'Sekota',
+ ['sel'] = 'Selkup',
+ ['sgo'] = 'Sango',
+ ['shn'] = 'Shan',
+ ['sib'] = 'Sibe',
+ ['sid'] = 'Sidamo',
+ ['sig'] = 'Silte Gurage',
+ ['sks'] = 'Skolt Sami',
+ ['sky'] = 'Slovak',
+ ['sla'] = 'Slavey',
+ ['slv'] = 'Slovenian',
+ ['sml'] = 'Somali',
+ ['smo'] = 'Samoan',
+ ['sna'] = 'Sena',
+ ['snd'] = 'Sindhi',
+ ['snh'] = 'Sinhalese',
+ ['snk'] = 'Soninke',
+ ['sog'] = 'Sodo Gurage',
+ ['sot'] = 'Sotho',
+ ['sqi'] = 'Albanian',
+ ['srb'] = 'Serbian',
+ ['srk'] = 'Saraiki',
+ ['srr'] = 'Serer',
+ ['ssl'] = 'South Slavey',
+ ['ssm'] = 'Southern Sami',
+ ['sur'] = 'Suri',
+ ['sva'] = 'Svan',
+ ['sve'] = 'Swedish',
+ ['swa'] = 'Swadaya Aramaic',
+ ['swk'] = 'Swahili',
+ ['swz'] = 'Swazi',
+ ['sxt'] = 'Sutu',
+ ['syr'] = 'Syriac',
+ ['tab'] = 'Tabasaran',
+ ['taj'] = 'Tajiki',
+ ['tam'] = 'Tamil',
+ ['tat'] = 'Tatar',
+ ['tcr'] = 'TH-Cree',
+ ['tel'] = 'Telugu',
+ ['tgn'] = 'Tongan',
+ ['tgr'] = 'Tigre',
+ ['tgy'] = 'Tigrinya',
+ ['tha'] = 'Thai',
+ ['tht'] = 'Tahitian',
+ ['tib'] = 'Tibetan',
+ ['tkm'] = 'Turkmen',
+ ['tmn'] = 'Temne',
+ ['tna'] = 'Tswana',
+ ['tne'] = 'Tundra Nenets',
+ ['tng'] = 'Tonga',
+ ['tod'] = 'Todo',
+ ['trk'] = 'Turkish',
+ ['tsg'] = 'Tsonga',
+ ['tua'] = 'Turoyo Aramaic',
+ ['tul'] = 'Tulu',
+ ['tuv'] = 'Tuvin',
+ ['twi'] = 'Twi',
+ ['udm'] = 'Udmurt',
+ ['ukr'] = 'Ukrainian',
+ ['urd'] = 'Urdu',
+ ['usb'] = 'Upper Sorbian',
+ ['uyg'] = 'Uyghur',
+ ['uzb'] = 'Uzbek',
+ ['ven'] = 'Venda',
+ ['vit'] = 'Vietnamese',
+ ['wa' ] = 'Wa',
+ ['wag'] = 'Wagdi',
+ ['wcr'] = 'West-Cree',
+ ['wel'] = 'Welsh',
+ ['wlf'] = 'Wolof',
+ ['xbd'] = 'Tai Lue',
+ ['xhs'] = 'Xhosa',
+ ['yak'] = 'Yakut',
+ ['yba'] = 'Yoruba',
+ ['ycr'] = 'Y-Cree',
+ ['yic'] = 'Yi Classic',
+ ['yim'] = 'Yi Modern',
+ ['zhh'] = 'Chinese Hong Kong',
+ ['zhp'] = 'Chinese Phonetic',
+ ['zhs'] = 'Chinese Simplified',
+ ['zht'] = 'Chinese Traditional',
+ ['znd'] = 'Zande',
+ ['zul'] = 'Zulu'
+}
+
+otf.tables.features = {
+ ['aalt'] = 'Access All Alternates',
+ ['abvf'] = 'Above-Base Forms',
+ ['abvm'] = 'Above-Base Mark Positioning',
+ ['abvs'] = 'Above-Base Substitutions',
+ ['afrc'] = 'Alternative Fractions',
+ ['akhn'] = 'Akhands',
+ ['blwf'] = 'Below-Base Forms',
+ ['blwm'] = 'Below-Base Mark Positioning',
+ ['blws'] = 'Below-Base Substitutions',
+ ['c2pc'] = 'Petite Capitals From Capitals',
+ ['c2sc'] = 'Small Capitals From Capitals',
+ ['calt'] = 'Contextual Alternates',
+ ['case'] = 'Case-Sensitive Forms',
+ ['ccmp'] = 'Glyph Composition/Decomposition',
+ ['cjct'] = 'Conjunct Forms',
+ ['clig'] = 'Contextual Ligatures',
+ ['cpsp'] = 'Capital Spacing',
+ ['cswh'] = 'Contextual Swash',
+ ['curs'] = 'Cursive Positioning',
+ ['dflt'] = 'Default Processing',
+ ['dist'] = 'Distances',
+ ['dlig'] = 'Discretionary Ligatures',
+ ['dnom'] = 'Denominators',
+ ['dtls'] = 'Dotless Forms', -- math
+ ['expt'] = 'Expert Forms',
+ ['falt'] = 'Final glyph Alternates',
+ ['fin2'] = 'Terminal Forms #2',
+ ['fin3'] = 'Terminal Forms #3',
+ ['fina'] = 'Terminal Forms',
+ ['flac'] = 'Flattened Accents Over Capitals', -- math
+ ['frac'] = 'Fractions',
+ ['fwid'] = 'Full Width',
+ ['half'] = 'Half Forms',
+ ['haln'] = 'Halant Forms',
+ ['halt'] = 'Alternate Half Width',
+ ['hist'] = 'Historical Forms',
+ ['hkna'] = 'Horizontal Kana Alternates',
+ ['hlig'] = 'Historical Ligatures',
+ ['hngl'] = 'Hangul',
+ ['hojo'] = 'Hojo Kanji Forms',
+ ['hwid'] = 'Half Width',
+ ['init'] = 'Initial Forms',
+ ['isol'] = 'Isolated Forms',
+ ['ital'] = 'Italics',
+ ['jalt'] = 'Justification Alternatives',
+ ['jp04'] = 'JIS2004 Forms',
+ ['jp78'] = 'JIS78 Forms',
+ ['jp83'] = 'JIS83 Forms',
+ ['jp90'] = 'JIS90 Forms',
+ ['kern'] = 'Kerning',
+ ['lfbd'] = 'Left Bounds',
+ ['liga'] = 'Standard Ligatures',
+ ['ljmo'] = 'Leading Jamo Forms',
+ ['lnum'] = 'Lining Figures',
+ ['locl'] = 'Localized Forms',
+ ['mark'] = 'Mark Positioning',
+ ['med2'] = 'Medial Forms #2',
+ ['medi'] = 'Medial Forms',
+ ['mgrk'] = 'Mathematical Greek',
+ ['mkmk'] = 'Mark to Mark Positioning',
+ ['mset'] = 'Mark Positioning via Substitution',
+ ['nalt'] = 'Alternate Annotation Forms',
+ ['nlck'] = 'NLC Kanji Forms',
+ ['nukt'] = 'Nukta Forms',
+ ['numr'] = 'Numerators',
+ ['onum'] = 'Old Style Figures',
+ ['opbd'] = 'Optical Bounds',
+ ['ordn'] = 'Ordinals',
+ ['ornm'] = 'Ornaments',
+ ['palt'] = 'Proportional Alternate Width',
+ ['pcap'] = 'Petite Capitals',
+ ['pnum'] = 'Proportional Figures',
+ ['pref'] = 'Pre-base Forms',
+ ['pres'] = 'Pre-base Substitutions',
+ ['pstf'] = 'Post-base Forms',
+ ['psts'] = 'Post-base Substitutions',
+ ['pwid'] = 'Proportional Widths',
+ ['qwid'] = 'Quarter Widths',
+ ['rand'] = 'Randomize',
+ ['rkrf'] = 'Rakar Forms',
+ ['rlig'] = 'Required Ligatures',
+ ['rphf'] = 'Reph Form',
+ ['rtbd'] = 'Right Bounds',
+ ['rtla'] = 'Right-To-Left Alternates',
+ ['rtlm'] = 'Right To Left Math', -- math
+ ['ruby'] = 'Ruby Notation Forms',
+ ['salt'] = 'Stylistic Alternates',
+ ['sinf'] = 'Scientific Inferiors',
+ ['size'] = 'Optical Size',
+ ['smcp'] = 'Small Capitals',
+ ['smpl'] = 'Simplified Forms',
+ ['ss01'] = 'Stylistic Set 1',
+ ['ss02'] = 'Stylistic Set 2',
+ ['ss03'] = 'Stylistic Set 3',
+ ['ss04'] = 'Stylistic Set 4',
+ ['ss05'] = 'Stylistic Set 5',
+ ['ss06'] = 'Stylistic Set 6',
+ ['ss07'] = 'Stylistic Set 7',
+ ['ss08'] = 'Stylistic Set 8',
+ ['ss09'] = 'Stylistic Set 9',
+ ['ss10'] = 'Stylistic Set 10',
+ ['ss11'] = 'Stylistic Set 11',
+ ['ss12'] = 'Stylistic Set 12',
+ ['ss13'] = 'Stylistic Set 13',
+ ['ss14'] = 'Stylistic Set 14',
+ ['ss15'] = 'Stylistic Set 15',
+ ['ss16'] = 'Stylistic Set 16',
+ ['ss17'] = 'Stylistic Set 17',
+ ['ss18'] = 'Stylistic Set 18',
+ ['ss19'] = 'Stylistic Set 19',
+ ['ss20'] = 'Stylistic Set 20',
+ ['ssty'] = 'Script Style', -- math
+ ['subs'] = 'Subscript',
+ ['sups'] = 'Superscript',
+ ['swsh'] = 'Swash',
+ ['titl'] = 'Titling',
+ ['tjmo'] = 'Trailing Jamo Forms',
+ ['tnam'] = 'Traditional Name Forms',
+ ['tnum'] = 'Tabular Figures',
+ ['trad'] = 'Traditional Forms',
+ ['twid'] = 'Third Widths',
+ ['unic'] = 'Unicase',
+ ['valt'] = 'Alternate Vertical Metrics',
+ ['vatu'] = 'Vattu Variants',
+ ['vert'] = 'Vertical Writing',
+ ['vhal'] = 'Alternate Vertical Half Metrics',
+ ['vjmo'] = 'Vowel Jamo Forms',
+ ['vkna'] = 'Vertical Kana Alternates',
+ ['vkrn'] = 'Vertical Kerning',
+ ['vpal'] = 'Proportional Alternate Vertical Metrics',
+ ['vrt2'] = 'Vertical Rotation',
+ ['zero'] = 'Slashed Zero',
+
+ ['trep'] = 'Traditional TeX Replacements',
+ ['tlig'] = 'Traditional TeX Ligatures',
+}
+
+otf.tables.baselines = {
+ ['hang'] = 'Hanging baseline',
+ ['icfb'] = 'Ideographic character face bottom edge baseline',
+ ['icft'] = 'Ideographic character face tope edige baseline',
+ ['ideo'] = 'Ideographic em-box bottom edge baseline',
+ ['idtp'] = 'Ideographic em-box top edge baseline',
+ ['math'] = 'Mathmatical centered baseline',
+ ['romn'] = 'Roman baseline'
+}
+
+-- can be sped up by local tables
+
+function otf.tables.to_tag(id)
+ return stringformat("%4s",lower(id))
+end
+
+local function resolve(tab,id)
+ if tab and id then
+ id = lower(id)
+ return tab[id] or tab[gsub(id," ","")] or tab['dflt'] or ''
+ else
+ return "unknown"
+ end
+end
+
+function otf.meanings.script(id)
+ return resolve(otf.tables.scripts,id)
+end
+function otf.meanings.language(id)
+ return resolve(otf.tables.languages,id)
+end
+function otf.meanings.feature(id)
+ return resolve(otf.tables.features,id)
+end
+function otf.meanings.baseline(id)
+ return resolve(otf.tables.baselines,id)
+end
+
+otf.tables.to_scripts = table.reverse_hash(otf.tables.scripts )
+otf.tables.to_languages = table.reverse_hash(otf.tables.languages)
+otf.tables.to_features = table.reverse_hash(otf.tables.features )
+
+local scripts = otf.tables.scripts
+local languages = otf.tables.languages
+local features = otf.tables.features
+
+local to_scripts = otf.tables.to_scripts
+local to_languages = otf.tables.to_languages
+local to_features = otf.tables.to_features
+
+for k, v in next, to_features do
+ local stripped = gsub(k,"%-"," ")
+ to_features[stripped] = v
+ local stripped = gsub(k,"[^a-zA-Z0-9]","")
+ to_features[stripped] = v
+end
+for k, v in next, to_features do
+ to_features[lower(k)] = v
+end
+
+otf.meanings.checkers = {
+ rand = function(v)
+ return v and "random"
+ end
+}
+
+local checkers = otf.meanings.checkers
+
+function otf.meanings.normalize(features)
+ local h = { }
+ for k,v in next, features do
+ k = lower(k)
+ if k == "language" or k == "lang" then
+ v = gsub(lower(v),"[^a-z0-9%-]","")
+ k = language
+ if not languages[v] then
+ h.language = to_languages[v] or "dflt"
+ else
+ h.language = v
+ end
+ elseif k == "script" then
+ v = gsub(lower(v),"[^a-z0-9%-]","")
+ if not scripts[v] then
+ h.script = to_scripts[v] or "dflt"
+ else
+ h.script = v
+ end
+ else
+ if type(v) == "string" then
+ local b = v:is_boolean()
+ if type(b) == "nil" then
+ v = tonumber(v) or lower(v)
+ else
+ v = b
+ end
+ end
+ k = to_features[k] or k
+ local c = checkers[k]
+ h[k] = c and c(v) or v
+ end
+ end
+ return h
+end
+
+-- When I feel the need ...
+
+--~ otf.tables.aat = {
+--~ [ 0] = {
+--~ name = "allTypographicFeaturesType",
+--~ [ 0] = "allTypeFeaturesOnSelector",
+--~ [ 1] = "allTypeFeaturesOffSelector",
+--~ },
+--~ [ 1] = {
+--~ name = "ligaturesType",
+--~ [0 ] = "requiredLigaturesOnSelector",
+--~ [1 ] = "requiredLigaturesOffSelector",
+--~ [2 ] = "commonLigaturesOnSelector",
+--~ [3 ] = "commonLigaturesOffSelector",
+--~ [4 ] = "rareLigaturesOnSelector",
+--~ [5 ] = "rareLigaturesOffSelector",
+--~ [6 ] = "logosOnSelector ",
+--~ [7 ] = "logosOffSelector ",
+--~ [8 ] = "rebusPicturesOnSelector",
+--~ [9 ] = "rebusPicturesOffSelector",
+--~ [10] = "diphthongLigaturesOnSelector",
+--~ [11] = "diphthongLigaturesOffSelector",
+--~ [12] = "squaredLigaturesOnSelector",
+--~ [13] = "squaredLigaturesOffSelector",
+--~ [14] = "abbrevSquaredLigaturesOnSelector",
+--~ [15] = "abbrevSquaredLigaturesOffSelector",
+--~ },
+--~ [ 2] = {
+--~ name = "cursiveConnectionType",
+--~ [ 0] = "unconnectedSelector",
+--~ [ 1] = "partiallyConnectedSelector",
+--~ [ 2] = "cursiveSelector ",
+--~ },
+--~ [ 3] = {
+--~ name = "letterCaseType",
+--~ [ 0] = "upperAndLowerCaseSelector",
+--~ [ 1] = "allCapsSelector ",
+--~ [ 2] = "allLowerCaseSelector",
+--~ [ 3] = "smallCapsSelector ",
+--~ [ 4] = "initialCapsSelector",
+--~ [ 5] = "initialCapsAndSmallCapsSelector",
+--~ },
+--~ [ 4] = {
+--~ name = "verticalSubstitutionType",
+--~ [ 0] = "substituteVerticalFormsOnSelector",
+--~ [ 1] = "substituteVerticalFormsOffSelector",
+--~ },
+--~ [ 5] = {
+--~ name = "linguisticRearrangementType",
+--~ [ 0] = "linguisticRearrangementOnSelector",
+--~ [ 1] = "linguisticRearrangementOffSelector",
+--~ },
+--~ [ 6] = {
+--~ name = "numberSpacingType",
+--~ [ 0] = "monospacedNumbersSelector",
+--~ [ 1] = "proportionalNumbersSelector",
+--~ },
+--~ [ 7] = {
+--~ name = "appleReserved1Type",
+--~ },
+--~ [ 8] = {
+--~ name = "smartSwashType",
+--~ [ 0] = "wordInitialSwashesOnSelector",
+--~ [ 1] = "wordInitialSwashesOffSelector",
+--~ [ 2] = "wordFinalSwashesOnSelector",
+--~ [ 3] = "wordFinalSwashesOffSelector",
+--~ [ 4] = "lineInitialSwashesOnSelector",
+--~ [ 5] = "lineInitialSwashesOffSelector",
+--~ [ 6] = "lineFinalSwashesOnSelector",
+--~ [ 7] = "lineFinalSwashesOffSelector",
+--~ [ 8] = "nonFinalSwashesOnSelector",
+--~ [ 9] = "nonFinalSwashesOffSelector",
+--~ },
+--~ [ 9] = {
+--~ name = "diacriticsType",
+--~ [ 0] = "showDiacriticsSelector",
+--~ [ 1] = "hideDiacriticsSelector",
+--~ [ 2] = "decomposeDiacriticsSelector",
+--~ },
+--~ [10] = {
+--~ name = "verticalPositionType",
+--~ [ 0] = "normalPositionSelector",
+--~ [ 1] = "superiorsSelector ",
+--~ [ 2] = "inferiorsSelector ",
+--~ [ 3] = "ordinalsSelector ",
+--~ },
+--~ [11] = {
+--~ name = "fractionsType",
+--~ [ 0] = "noFractionsSelector",
+--~ [ 1] = "verticalFractionsSelector",
+--~ [ 2] = "diagonalFractionsSelector",
+--~ },
+--~ [12] = {
+--~ name = "appleReserved2Type",
+--~ },
+--~ [13] = {
+--~ name = "overlappingCharactersType",
+--~ [ 0] = "preventOverlapOnSelector",
+--~ [ 1] = "preventOverlapOffSelector",
+--~ },
+--~ [14] = {
+--~ name = "typographicExtrasType",
+--~ [0 ] = "hyphensToEmDashOnSelector",
+--~ [1 ] = "hyphensToEmDashOffSelector",
+--~ [2 ] = "hyphenToEnDashOnSelector",
+--~ [3 ] = "hyphenToEnDashOffSelector",
+--~ [4 ] = "unslashedZeroOnSelector",
+--~ [5 ] = "unslashedZeroOffSelector",
+--~ [6 ] = "formInterrobangOnSelector",
+--~ [7 ] = "formInterrobangOffSelector",
+--~ [8 ] = "smartQuotesOnSelector",
+--~ [9 ] = "smartQuotesOffSelector",
+--~ [10] = "periodsToEllipsisOnSelector",
+--~ [11] = "periodsToEllipsisOffSelector",
+--~ },
+--~ [15] = {
+--~ name = "mathematicalExtrasType",
+--~ [ 0] = "hyphenToMinusOnSelector",
+--~ [ 1] = "hyphenToMinusOffSelector",
+--~ [ 2] = "asteriskToMultiplyOnSelector",
+--~ [ 3] = "asteriskToMultiplyOffSelector",
+--~ [ 4] = "slashToDivideOnSelector",
+--~ [ 5] = "slashToDivideOffSelector",
+--~ [ 6] = "inequalityLigaturesOnSelector",
+--~ [ 7] = "inequalityLigaturesOffSelector",
+--~ [ 8] = "exponentsOnSelector",
+--~ [ 9] = "exponentsOffSelector",
+--~ },
+--~ [16] = {
+--~ name = "ornamentSetsType",
+--~ [ 0] = "noOrnamentsSelector",
+--~ [ 1] = "dingbatsSelector ",
+--~ [ 2] = "piCharactersSelector",
+--~ [ 3] = "fleuronsSelector ",
+--~ [ 4] = "decorativeBordersSelector",
+--~ [ 5] = "internationalSymbolsSelector",
+--~ [ 6] = "mathSymbolsSelector",
+--~ },
+--~ [17] = {
+--~ name = "characterAlternativesType",
+--~ [ 0] = "noAlternatesSelector",
+--~ },
+--~ [18] = {
+--~ name = "designComplexityType",
+--~ [ 0] = "designLevel1Selector",
+--~ [ 1] = "designLevel2Selector",
+--~ [ 2] = "designLevel3Selector",
+--~ [ 3] = "designLevel4Selector",
+--~ [ 4] = "designLevel5Selector",
+--~ },
+--~ [19] = {
+--~ name = "styleOptionsType",
+--~ [ 0] = "noStyleOptionsSelector",
+--~ [ 1] = "displayTextSelector",
+--~ [ 2] = "engravedTextSelector",
+--~ [ 3] = "illuminatedCapsSelector",
+--~ [ 4] = "titlingCapsSelector",
+--~ [ 5] = "tallCapsSelector ",
+--~ },
+--~ [20] = {
+--~ name = "characterShapeType",
+--~ [0 ] = "traditionalCharactersSelector",
+--~ [1 ] = "simplifiedCharactersSelector",
+--~ [2 ] = "jis1978CharactersSelector",
+--~ [3 ] = "jis1983CharactersSelector",
+--~ [4 ] = "jis1990CharactersSelector",
+--~ [5 ] = "traditionalAltOneSelector",
+--~ [6 ] = "traditionalAltTwoSelector",
+--~ [7 ] = "traditionalAltThreeSelector",
+--~ [8 ] = "traditionalAltFourSelector",
+--~ [9 ] = "traditionalAltFiveSelector",
+--~ [10] = "expertCharactersSelector",
+--~ },
+--~ [21] = {
+--~ name = "numberCaseType",
+--~ [ 0] = "lowerCaseNumbersSelector",
+--~ [ 1] = "upperCaseNumbersSelector",
+--~ },
+--~ [22] = {
+--~ name = "textSpacingType",
+--~ [ 0] = "proportionalTextSelector",
+--~ [ 1] = "monospacedTextSelector",
+--~ [ 2] = "halfWidthTextSelector",
+--~ [ 3] = "normallySpacedTextSelector",
+--~ },
+--~ [23] = {
+--~ name = "transliterationType",
+--~ [ 0] = "noTransliterationSelector",
+--~ [ 1] = "hanjaToHangulSelector",
+--~ [ 2] = "hiraganaToKatakanaSelector",
+--~ [ 3] = "katakanaToHiraganaSelector",
+--~ [ 4] = "kanaToRomanizationSelector",
+--~ [ 5] = "romanizationToHiraganaSelector",
+--~ [ 6] = "romanizationToKatakanaSelector",
+--~ [ 7] = "hanjaToHangulAltOneSelector",
+--~ [ 8] = "hanjaToHangulAltTwoSelector",
+--~ [ 9] = "hanjaToHangulAltThreeSelector",
+--~ },
+--~ [24] = {
+--~ name = "annotationType",
+--~ [ 0] = "noAnnotationSelector",
+--~ [ 1] = "boxAnnotationSelector",
+--~ [ 2] = "roundedBoxAnnotationSelector",
+--~ [ 3] = "circleAnnotationSelector",
+--~ [ 4] = "invertedCircleAnnotationSelector",
+--~ [ 5] = "parenthesisAnnotationSelector",
+--~ [ 6] = "periodAnnotationSelector",
+--~ [ 7] = "romanNumeralAnnotationSelector",
+--~ [ 8] = "diamondAnnotationSelector",
+--~ },
+--~ [25] = {
+--~ name = "kanaSpacingType",
+--~ [ 0] = "fullWidthKanaSelector",
+--~ [ 1] = "proportionalKanaSelector",
+--~ },
+--~ [26] = {
+--~ name = "ideographicSpacingType",
+--~ [ 0] = "fullWidthIdeographsSelector",
+--~ [ 1] = "proportionalIdeographsSelector",
+--~ },
+--~ [103] = {
+--~ name = "cjkRomanSpacingType",
+--~ [ 0] = "halfWidthCJKRomanSelector",
+--~ [ 1] = "proportionalCJKRomanSelector",
+--~ [ 2] = "defaultCJKRomanSelector",
+--~ [ 3] = "fullWidthCJKRomanSelector",
+--~ },
+--~ }
diff --git a/tex/context/base/font-pat.lua b/tex/context/base/font-pat.lua
new file mode 100644
index 000000000..6aba4d47e
--- /dev/null
+++ b/tex/context/base/font-pat.lua
@@ -0,0 +1,126 @@
+if not modules then modules = { } end modules ['font-pat'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local match, lower, find = string.match, string.lower, string.find
+
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+
+-- this will become a per font patch file
+--
+-- older versions of latin modern didn't have the designsize set
+-- so for them we get it from the name
+
+local patches = fonts.otf.enhancers.patches
+
+local function patch(data,filename)
+ if data.design_size == 0 then
+ local ds = match(file.basename(lower(filename)),"(%d+)")
+ if ds then
+ if trace_loading then
+ logs.report("load otf","patching design size (%s)",ds)
+ end
+ data.design_size = tonumber(ds) * 10
+ end
+ end
+ local uni_to_ind = data.map.map
+ if not uni_to_ind[0x391] then
+ -- beware, this is a hack, features for latin often don't apply to greek
+ -- but lm has not much features anyway (and only greek for math)
+ if trace_loading then
+ logs.report("load otf","adding 13 greek capitals")
+ end
+ uni_to_ind[0x391] = uni_to_ind[0x41]
+ uni_to_ind[0x392] = uni_to_ind[0x42]
+ uni_to_ind[0x395] = uni_to_ind[0x45]
+ uni_to_ind[0x397] = uni_to_ind[0x48]
+ uni_to_ind[0x399] = uni_to_ind[0x49]
+ uni_to_ind[0x39A] = uni_to_ind[0x4B]
+ uni_to_ind[0x39C] = uni_to_ind[0x4D]
+ uni_to_ind[0x39D] = uni_to_ind[0x4E]
+ uni_to_ind[0x39F] = uni_to_ind[0x4F]
+ uni_to_ind[0x3A1] = uni_to_ind[0x52]
+ uni_to_ind[0x3A4] = uni_to_ind[0x54]
+ uni_to_ind[0x3A7] = uni_to_ind[0x58]
+ uni_to_ind[0x396] = uni_to_ind[0x5A]
+ end
+ -- better make this into a feature
+ --
+ -- local glyphs = data.glyphs
+ -- for i=0x300,0x36F do
+ -- local c = glyphs[uni_to_ind[i]]
+ -- if c and c.width == 0 then
+ -- local boundingbox = c.boundingbox
+ -- c.width = boundingbox[3] - boundingbox[1]
+ -- end
+ -- end
+end
+
+patches["^lmroman"] = patch
+patches["^lmsans"] = patch
+patches["^lmtypewriter"] = patch
+
+-- for some reason (either it's a bug in the font, or it's
+-- a problem in the library) the palatino arabic fonts don't
+-- have the mkmk features properly set up
+
+local function patch(data,filename)
+ local gpos = data.gpos
+ if gpos then
+ for k=1,#gpos do
+ local v = gpos[k]
+ if not v.features and v.type == "gpos_mark2mark" then
+ if trace_loading then
+ logs.report("load otf","patching mkmk feature (name: %s)", v.name or "?")
+ end
+ v.features = {
+ {
+ scripts = {
+ {
+ langs = { "ARA ", "FAR ", "URD ", "dflt" },
+ script = "arab",
+ },
+ },
+ tag = "mkmk"
+ }
+ }
+ end
+ end
+ end
+end
+
+patches["palatino.*arabic"] = patch
+
+local function patch_domh(data,filename,threshold)
+ local m = data.math
+ if m then
+ local d = m.DisplayOperatorMinHeight or 0
+ if d < threshold then
+ if trace_loading then
+ logs.report("load otf","patching DisplayOperatorMinHeight(%s -> %s)",d,threshold)
+ end
+ m.DisplayOperatorMinHeight = threshold
+ end
+ end
+ if tex.luatexversion < 48 then
+ for _, g in next, data.glyphs do
+ local name = g.name
+ if find(name,"^integral$") or find(name,"^integral%.vsize") then
+ local width, italic = g.width or 0, g.italic_correction or 0
+ local newwidth = width - italic
+ if trace_loading then
+ logs.report("load otf","patching width of %s: %s (width) - %s (italic) = %s",name,width,italic,newwidth)
+ end
+ g.width = newwidth
+ end
+ end
+ end
+end
+
+patches["cambria"] = function(data,filename) patch_domh(data,filename,2800) end
+patches["cambmath"] = function(data,filename) patch_domh(data,filename,2800) end
+patches["asana"] = function(data,filename) patch_domh(data,filename,1350) end
diff --git a/tex/context/base/font-run.mkii b/tex/context/base/font-run.mkii
new file mode 100644
index 000000000..0a0ddd057
--- /dev/null
+++ b/tex/context/base/font-run.mkii
@@ -0,0 +1,326 @@
+%D \module
+%D [ file=font-run,
+%D version=1998.09.11, % (second)
+%D version=2001.02.20, % (third)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 code is hooked into the core macros and saves some
+%D format space.]
+
+\unprotect
+
+\gdef\@@onlyenglish#1%
+ {\blank{\tttf \type {#1} is only available in the english interface}\blank}
+
+\gdef\dosetshowfonttitle#1%
+ {\tabskip\zeropoint
+ \parindent\zeropoint
+ \setlocalhsize
+ \doifelsenothing{#1}
+ {\def\title{[\the\bodyfontsize]}}
+ {\switchtobodyfont[#1]\def\title{[#1]}}
+ \doifsomething\fontclass
+ {\doifnot{[\fontclass]}\title
+ {\edef\title{[\fontclass]\space\title}}}}
+
+\gdef\showbodyfont
+ {\dosingleempty\doshowbodyfont}
+
+\gdef\doshowbodyfont[#1]%
+ {\ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox
+ {\dosetshowfonttitle{#1}%
+ \def\bigstrut##1##2%
+ {\hbox{\vrule
+ \!!height##1\strutht
+ \!!depth ##2\strutdp
+ \!!width \zeropoint}}
+ \def\next##1##2##3%
+ {\tf##3\sc##3%
+ \sl##3\it##3\bf##3\bs##3\bi##3%
+ \tfx##3\tfxx##3%
+ \tfa##3\tfb##3\tfc##3\tfd##3&\cr}%
+ \halign to \localhsize
+ {\bigstrut{1.5}{2}##&\vrule##
+ \tabskip=\!!zeropoint \!!plus 1fill
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil#\vrule
+ \tabskip=\!!zeropoint\cr
+ \noalign{\hrule}
+ &\multispan{29}{\vrule\hfil\tttf\strut\title\hfil
+ \llap{\string\mr\hbox to 1em{\hss:\hss}$\mr \languageparameter\c!text$\quad}\vrule}\cr
+ \noalign{\hrule}\next{}{\tt\string}{}
+ \noalign{\hrule}\next{\tt\string\rm}\rm{\languageparameter\c!text}
+ \noalign{\hrule}\next{\tt\string\ss}\ss{\languageparameter\c!text}
+ \noalign{\hrule}\next{\tt\string\tt}\tt{\languageparameter\c!text}
+ \noalign{\hrule}}}
+ \ifinsidefloat\else\stopbaselinecorrection\fi}
+
+\gdef\showbodyfontenvironment
+ {\dosingleempty\doshowbodyfontenvironment}
+
+\gdef\doshowbodyfontenvironment[#1]%
+ {\ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox
+ {\dosetshowfonttitle{#1}%
+ \def\next##1%
+ {&&\getvalue{\bodyfontvariable{##1\s!text}}%
+ &&\getvalue{\bodyfontvariable{##1\s!script}}%
+ &&\getvalue{\bodyfontvariable{##1\s!scriptscript}}%
+ &&\getvalue{\bodyfontvariable{##1\c!x}}%
+ &&\getvalue{\bodyfontvariable{##1\c!xx}}%
+ &&\getvalue{\bodyfontvariable{##1\interfaced\v!small}}%
+ &&\getvalue{\bodyfontvariable{##1\interfaced\v!big}}%
+ &&\edef\next{\getvalue{\bodyfontvariable{##1\c!interlinespace}}}\ifx\next\empty not set\else\next\fi&\cr
+ \noalign{\hrule}}
+ \halign to \localhsize
+ {##&\vrule##\strut
+ \tabskip=\!!zeropoint \!!plus 1fill
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil#\vrule
+ \tabskip\zeropoint\cr
+ \noalign{\hrule}
+ &\multispan{17}{\vrule\hfil\tttf\strut\title\hfil}\vrule\cr
+ \noalign{\hrule}
+ &&\tttf\tx\s!text&&\tttf\tx\s!script&&\tttf\tx\s!scriptscript
+ &&\tttf\tx\c!x&&\tttf\tx\c!xx&&\tttf\tx\v!small&&\tttf\tx\v!big
+ &&\tttf\tx\c!interlinespace&\cr
+ \noalign{\hrule}
+ \@EA\globalprocesscommalist\@EA[\bodyfontenvironmentlist]\next}}
+ \ifinsidefloat\else\stopbaselinecorrection\fi}
+
+\gdef\showfont
+ {\dodoubleempty\doshowfont}
+
+\gdef\doshowfont[#1][#2]%
+ {\bgroup
+ \boxrulewidth=.1pt
+ \setupcolors[\c!state=\v!local]%
+ \iffirstargument
+ \definefont[\s!dummy][#1]\dummy
+ \else\ifdim2.5em>.05\hsize \tx
+ \ifdim2.5em>.05\hsize \txx
+ \fi\fi\fi
+ \ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox\bgroup
+ \forgetall
+ \startoverlay
+ {\vbox
+ {\tf \setstrut \dummy
+ \localcolortrue \offinterlineskip
+ \dostepwiserecurse{0}{15}{1}
+ {\let\row\recurselevel
+ \hbox
+ {\red
+ \dostepwiserecurse{0}{15}{1}
+ {\let\col\recurselevel
+ \@EA\scratchcounter\normaldblquote\hexnumber\row\hexnumber\col\relax
+ \edef\rowcol{\the\scratchcounter}%
+ \iffontchar\font\scratchcounter
+ \setbox\scratchbox\ruledhbox{\black\char\scratchcounter}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \donetrue \else \donefalse
+ \fi
+ \else
+ \setbox\scratchbox\hbox{\gray\vrule\!!width1ex\!!height.5ex\!!depth.5ex}%
+ \fi
+ \startoverlay
+ {\tf\vbox to 2.5em
+ {\vss
+ \hbox to 2.5em
+ {\dummy\ifdim\interwordspace=\zeropoint
+ \setbox\scratchbox\hbox
+ {\raise.5\dp\scratchbox\hbox
+ {\lower.5\ht\scratchbox\copy\scratchbox}}%
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \else
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \strut
+ \fi
+ \hss\copy\scratchbox\hss}
+ \vss}}
+ {\tf\vbox to 2.3em
+ {\ifdone
+ \hsize2.4em
+ \blue
+ \edef\theshowfontspecs
+ {\ifnum\hyphenchar\font=\rowcol hyph\else
+ \ifnum\skewchar \font=\rowcol skew\fi\fi}%
+ \tinyfont % after \edef, else wrong font analyzed
+ \doifnot\v!unknown{#2}{{\red\theshowfontspecs}}\hfill\number\rowcol
+ \vfill
+ \octnumber\rowcol\hfill\lchexnumbers\rowcol
+ \par
+ \fi}}
+ \stopoverlay}}}
+ \par}}
+ {\tf\basegrid[\c!nx=16,\c!ny=16,\c!dx=2.5,\c!dy=2.5,\c!unit=em]}
+ \stopoverlay
+ \nointerlineskip
+ \vskip2pt
+ % the \noexpand before \blank is needed for non etex
+ \edef\ascii{name: {\noexpand\black\fontname\font}}
+ \def\do##1##2{\ifx##1\undefined\else\ifx##1\empty\else##2\fi\fi}%
+ \doifelse\v!unknown{#2}
+ {\edef\theshowfontspecs
+ {name: {\noexpand\black\fontname\font}}}
+ {\edef\theshowfontspecs
+ {name: {\noexpand\black\fontname\font}\noexpand\quad
+ \do\currentencoding{encoding: {\noexpand\black\currentencoding\noexpand\quad}}%
+ \do\currentmapping {mapping: {\noexpand\black\currentmapping \noexpand\quad}}%
+ \do\fonthandling {handling: {\noexpand\black\fonthandling }}}}%
+ \tf % also sets em
+ \hbox to 40em{\blue\hfill\tinyfont\setstrut\strut\theshowfontspecs}
+ \egroup
+ \ifinsidefloat\else\stopbaselinecorrection\fi
+ \egroup}
+
+\gdef\showfontstyle
+ {\dotripleempty\doshowfontstyle}
+
+\gdef\doshowfontstyle[#1][#2][#3]%
+ {\ifthirdargument
+ \bgroup
+ \raggedright
+ \switchtobodyfont[#1]
+ \def\dodocommand##1##2%
+ {\starttextrule{\tttf #1 ##1 ##2}
+ \nobreak \getvalue{##2}%
+ \dorecurse{255}
+ {\iffontchar\font\recurselevel\relax
+ \char\recurselevel\relax\space
+ \fi}
+ \par \nobreak
+ \stoptextrule}
+ \def\docommand##1%
+ {\getvalue{##1}\processcommacommand[#3]{\dodocommand{##1}}}
+ \processcommalist[#2]\docommand
+ \egroup
+ \else\ifsecondargument
+ \showfontstyle[#1][#2][\fontalternativelist]% math is gone
+ \else
+ \showfontstyle[#1][\c!rm]\showfontstyle[#1][\c!ss]
+ \showfontstyle[#1][\c!tt]\showfontstyle[#1][\c!mm]
+ \fi\fi}
+
+\gdef\showligature#1%
+ {\hbox{\type{#1}\enspace\red\ruledhbox{\black#1}}}
+
+\gdef\showligatures[#1]%
+ {\ifx\starttabulate\undefined
+ \@@onlyenglish\showligatures
+ \else
+ \bgroup
+ \setupcolors[\c!state=\v!local]%
+ \def\show##1{\hbox{\red\ruledhbox{\black##1}}}%
+ \definefont[\s!dummy][#1]\dummy
+ \starttabulate[|*{9}{c|}]
+ \NC\type{ff}\NC\type{fi}\NC\type{fl}\NC\type{ffi}\NC\type{ffl}\NC
+ \type{``}\NC\type{''}\NC\type{--}\NC\type{---}\NC\NR
+ \NC\show{ff}\NC\show{fi}\NC\show{fl}\NC\show{ffi}\NC\show{ffl}\NC
+ \show{``}\NC\show{''}\NC\show{--}\NC\show{---}\NC\NR
+ \stoptabulate
+ \egroup
+ \fi}
+
+\gdef\showfontstrip
+ {\dosingleempty\doshowfontstrip}
+
+\gdef\doshowfontstrip[#1]%
+ {\ifx\starttabulate\undefined
+ \@@onlyenglish\showfontstrip
+ \else
+ \bgroup
+ \def\dofontstripa##1##2%
+ {\tttf\string##1}
+ \def\dofontstripb##1##2%
+ {\ruledhbox{\switchtobodyfont[#1]##1{##2}}}
+ \def\dofontstripc##1##2%
+ {\setbox\scratchbox\hbox{\switchtobodyfont[#1]##1{##2}}%
+ \tt\tfx\the\ht\scratchbox}%
+ \def\dofontstripd##1##2%
+ {\setbox\scratchbox\hbox{\switchtobodyfont[#1]##1{##2}}%
+ \tt\tfx\the\wd\scratchbox}%
+ \def\fontstrip##1##2##3%
+ {\NC##2\rm{##3}\NC
+ ##2\ss{##3}\NC
+ ##2\tt{##3}\NC
+ ##2\mathematics{##3}\NC
+ \tttf##1\NR}
+ \starttabulate[|c|c|c|c|c|]
+ \fontstrip\relax\dofontstripa\empty
+ \TB
+ \fontstrip\relax\dofontstripb{xxxx}
+ \fontstrip\relax\dofontstripb{12345}
+ \fontstrip\relax\dofontstripb{(Agw)}
+ \TB
+ \fontstrip{(x height)}\dofontstripc{x}
+ \fontstrip{(m width)}\dofontstripd{m}
+ \stoptabulate
+ \egroup
+ \fi}
+
+\ifx\databox\undefined \newbox\databox \fi
+
+\gdef\testminimalbaseline#1%
+ {\setbox\databox\ruledhbox{#1}%
+ \scratchdimen\ht\databox
+ \advance\scratchdimen\dp\databox
+ \scratchtoks{#1}%
+ \expanded
+ {\NC \ruledhbox{\the\scratchtoks}
+ \noexpand \NC ->
+ \noexpand \NC \the\scratchdimen
+ \noexpand \NC =
+ \noexpand \NC \the\ht\databox
+ \noexpand \NC +
+ \noexpand \NC \the\dp\databox
+ \noexpand \NC \ifdim\scratchdimen<\baselineskip <
+ \else\ifdim\scratchdimen=\baselineskip =
+ \else > \fi\fi
+ \noexpand \NC \the\baselineskip
+ \noexpand \NC (\ifdim\scratchdimen>\baselineskip not \fi ok)
+ \noexpand \NC \noexpand \NR }}
+
+\gdef\showminimalbaseline
+ {\ifx\starttabulate\undefined
+ \@@onlyenglish\showminimalbaseline
+ \else
+ \starttabulate[||T|T|T|T|T|T|T|T|T|]
+ \testminimalbaseline{\hbox to 1em{\hss\showstruts\strut\hss}}%
+ \testminimalbaseline{(/)}%
+ \testminimalbaseline{$\frac{1}{2}x^2_3$}
+ \stoptabulate
+ \fi}
+
+\gdef\showkerning#1%
+ {\bgroup
+ \let\MPfshowcommand\ruledhbox
+ \setMPtext\s!dummy{#1}%
+ \startMPcode draw textext(\MPstring\s!dummy);\stopMPcode
+ \egroup}
+
+\gdef\showcharratio
+ {\dowithnextboxcontent
+ {\switchtobodyfont[10pt]}%
+ {(\expanded{\withoutpt\the\nextboxht},%
+ \expanded{\withoutpt\the\nextboxdp})}%
+ \hbox}
+
+\protect \endinput
diff --git a/tex/context/base/font-run.mkiv b/tex/context/base/font-run.mkiv
new file mode 100644
index 000000000..aad6bebe8
--- /dev/null
+++ b/tex/context/base/font-run.mkiv
@@ -0,0 +1,337 @@
+%D \module
+%D [ file=font-run,
+%D version=1998.09.11, % (second)
+%D version=2001.02.20, % (third)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 code is hooked into the core macros and saves some
+%D format space.]
+
+\unprotect
+
+\gdef\@@onlyenglish#1%
+ {\blank{\tttf \type {#1} is only available in the english interface}\blank}
+
+\gdef\dosetshowfonttitle#1%
+ {\tabskip\zeropoint
+ \parindent\zeropoint
+ \setlocalhsize
+ \doifelsenothing{#1}
+ {\def\title{[\the\bodyfontsize]}}
+ {\switchtobodyfont[#1]\def\title{[#1]}}
+ \doifsomething\fontclass
+ {\doifnot{[\fontclass]}\title
+ {\edef\title{[\fontclass]\space\title}}}}
+
+\gdef\showbodyfont
+ {\dosingleempty\doshowbodyfont}
+
+\gdef\doshowbodyfont[#1]%
+ {\ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox
+ {\dosetshowfonttitle{#1}%
+ \def\bigstrut##1##2%
+ {\hbox{\vrule
+ \!!height##1\strutht
+ \!!depth ##2\strutdp
+ \!!width \zeropoint}}
+ \def\next##1##2##3%
+ {\tf##3\sc##3%
+ \sl##3\it##3\bf##3\bs##3\bi##3%
+ \tfx##3\tfxx##3%
+ \tfa##3\tfb##3\tfc##3\tfd##3&\cr}%
+ \halign to \localhsize
+ {\bigstrut{1.5}{2}##&\vrule##
+ \tabskip=\!!zeropoint \!!plus 1fill
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil#\vrule
+ \tabskip=\!!zeropoint\cr
+ \noalign{\hrule}
+ &\multispan{29}{\vrule\hfil\tttf\strut\title\hfil
+ \llap{\string\mr\hbox to 1em{\hss:\hss}$\mr \languageparameter\c!text$\quad}\vrule}\cr
+ \noalign{\hrule}\next{}{\tt\string}{}
+ \noalign{\hrule}\next{\tt\string\rm}\rm{\languageparameter\c!text}
+ \noalign{\hrule}\next{\tt\string\ss}\ss{\languageparameter\c!text}
+ \noalign{\hrule}\next{\tt\string\tt}\tt{\languageparameter\c!text}
+ \noalign{\hrule}}}
+ \ifinsidefloat\else\stopbaselinecorrection\fi}
+
+\gdef\showbodyfontenvironment
+ {\dosingleempty\doshowbodyfontenvironment}
+
+\gdef\doshowbodyfontenvironment[#1]%
+ {\ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox
+ {\dosetshowfonttitle{#1}%
+ \def\next##1%
+ {&&\getvalue{\bodyfontvariable{##1\s!text}}%
+ &&\getvalue{\bodyfontvariable{##1\s!script}}%
+ &&\getvalue{\bodyfontvariable{##1\s!scriptscript}}%
+ &&\getvalue{\bodyfontvariable{##1\c!x}}%
+ &&\getvalue{\bodyfontvariable{##1\c!xx}}%
+ &&\getvalue{\bodyfontvariable{##1\interfaced\v!small}}%
+ &&\getvalue{\bodyfontvariable{##1\interfaced\v!big}}%
+ &&\edef\next{\getvalue{\bodyfontvariable{##1\c!interlinespace}}}\ifx\next\empty not set\else\next\fi&\cr
+ \noalign{\hrule}}
+ \halign to \localhsize
+ {##&\vrule##\strut
+ \tabskip=\!!zeropoint \!!plus 1fill
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
+ &\hfil##\hfil&\vrule##&\hfil##\hfil#\vrule
+ \tabskip\zeropoint\cr
+ \noalign{\hrule}
+ &\multispan{17}{\vrule\hfil\tttf\strut\title\hfil}\vrule\cr
+ \noalign{\hrule}
+ &&\tttf\tx\s!text&&\tttf\tx\s!script&&\tttf\tx\s!scriptscript
+ &&\tttf\tx\c!x&&\tttf\tx\c!xx&&\tttf\tx\v!small&&\tttf\tx\v!big
+ &&\tttf\tx\c!interlinespace&\cr
+ \noalign{\hrule}
+ \@EA\globalprocesscommalist\@EA[\bodyfontenvironmentlist]\next}}
+ \ifinsidefloat\else\stopbaselinecorrection\fi}
+
+\gdef\showfont
+ {\dodoubleempty\doshowfont}
+
+\gdef\doshowfont[#1][#2]%
+ {\bgroup
+ \iffirstargument
+ \definefont[\s!dummy][#1]\dummy
+ \fi
+ \doifelsenothing{#2}
+ {\dodoshowfont{#1}{0}}
+ {\doifelse{#2}\v!all
+ {\dostepwiserecurse{0}{255}{1}
+ {\donefalse
+ \let\charplane\recurselevel
+ \dostepwiserecurse{0}{255}{1}
+ {\iffontchar\font\numexpr\charplane*256+\recurselevel\relax
+ \donetrue
+ \exitloop
+ \fi}%
+ \ifdone
+ \dodoshowfont{#1}\charplane
+ \fi}}
+ {\processcommalist[#2]{\dodoshowfont{#1}}}}%
+ \egroup}
+
+\gdef\dodoshowfont#1#2%
+ {\bgroup
+ \edef\charplane{\number#2}%
+ \boxrulewidth=.1pt
+ \iffirstargument
+% \definefont[\s!dummy][#1]\dummy
+ \else\ifdim2.5em>.05\hsize \tx
+ \ifdim2.5em>.05\hsize \txx
+ \fi\fi\fi
+ \ifinsidefloat\else\startbaselinecorrection\fi
+ \vbox\bgroup
+ \forgetall
+ \startoverlay
+ {\vbox
+ {\tf \setstrut \dummy
+ \offinterlineskip
+ \dostepwiserecurse{0}{15}{1}
+ {\let\row\recurselevel
+ \hbox
+ {\red
+ \dostepwiserecurse{0}{15}{1}
+ {\let\col\recurselevel
+ \@EA\scratchcounter\string"\hexnumber\row\hexnumber\col\relax
+ \edef\rowcol{\the\scratchcounter}%
+ \iffontchar\font\scratchcounter
+ \setbox\scratchbox\ruledhbox{\black\char\numexpr\charplane*256+\scratchcounter\relax}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \donetrue \else \donefalse
+ \fi
+ \else
+ \setbox\scratchbox\hbox{\gray\vrule\!!width1ex\!!height.5ex\!!depth.5ex}%
+ \fi
+ \startoverlay
+ {\tf\vbox to 2.5em
+ {\vss
+ \hbox to 2.5em
+ {\dummy\ifdim\interwordspace=\zeropoint
+ \setbox\scratchbox\hbox
+ {\raise.5\dp\scratchbox\hbox
+ {\lower.5\ht\scratchbox\copy\scratchbox}}%
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \else
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \strut
+ \fi
+ \hss\copy\scratchbox\hss}
+ \vss}}
+ {\tf\vbox to 2.3em
+ {\ifdone
+ \hsize2.4em
+ \blue
+ \tinyfont
+ \hfill\number\rowcol
+ \vfill
+ \octnumber\rowcol\hfill\lchexnumbers\rowcol
+ \par
+ \fi}}
+ \stopoverlay}}}
+ \par}}
+ {\tf\basegrid[\c!nx=16,\c!ny=16,\c!dx=2.5,\c!dy=2.5,\c!unit=em]}
+ \stopoverlay
+ \nointerlineskip
+ \vskip2pt
+ % the \noexpand before \blank is needed for non etex
+ \edef\ascii{name: {\noexpand\black\fontname\font}}
+ \def\do##1##2{\ifx##1\undefined\else\ifx##1\empty\else##2\fi\fi}%
+ \edef\theshowfontspecs{name: {\noexpand\black\fontname\font}\quad plane: \charplane\enspace"\hexnumber\charplane}%
+ \tf % also sets em
+ \hbox to 40em{\blue\hfill\tinyfont\setstrut\strut\theshowfontspecs}
+ \egroup
+ \ifinsidefloat\else\stopbaselinecorrection\fi
+ \egroup}
+
+\gdef\showfontstyle
+ {\dotripleempty\doshowfontstyle}
+
+\gdef\doshowfontstyle[#1][#2][#3]%
+ {\ifthirdargument
+ \bgroup
+ \raggedright
+ \switchtobodyfont[#1]
+ \def\dodocommand##1##2%
+ {\starttextrule{\tttf #1 ##1 ##2}
+ \nobreak \getvalue{##2}%
+ \dorecurse{255}
+ {\iffontchar\font\recurselevel\relax
+ \char\recurselevel\relax\space
+ \fi}
+ \par \nobreak
+ \stoptextrule}
+ \def\docommand##1%
+ {\getvalue{##1}\processcommacommand[#3]{\dodocommand{##1}}}
+ \processcommalist[#2]\docommand
+ \egroup
+ \else\ifsecondargument
+ \showfontstyle[#1][#2][\fontalternativelist]% math is gone
+ \else
+ \showfontstyle[#1][\c!rm]\showfontstyle[#1][\c!ss]
+ \showfontstyle[#1][\c!tt]\showfontstyle[#1][\c!mm]
+ \fi\fi}
+
+\gdef\showligature#1%
+ {\hbox{\type{#1}\enspace\red\ruledhbox{\black#1}}}
+
+\gdef\showligatures[#1]%
+ {\ifx\starttabulate\undefined
+ \@@onlyenglish\showligatures
+ \else
+ \bgroup
+ \def\show##1{\hbox{\red\ruledhbox{\black##1}}}%
+ \definefont[\s!dummy][#1]\dummy
+ \starttabulate[|*{9}{c|}]
+ \NC\type{ff}\NC\type{fi}\NC\type{fl}\NC\type{ffi}\NC\type{ffl}\NC
+ \type{``}\NC\type{''}\NC\type{--}\NC\type{---}\NC\NR
+ \NC\show{ff}\NC\show{fi}\NC\show{fl}\NC\show{ffi}\NC\show{ffl}\NC
+ \show{``}\NC\show{''}\NC\show{--}\NC\show{---}\NC\NR
+ \stoptabulate
+ \egroup
+ \fi}
+
+\gdef\showfontstrip
+ {\dosingleempty\doshowfontstrip}
+
+\gdef\doshowfontstrip[#1]%
+ {\ifx\starttabulate\undefined
+ \@@onlyenglish\showfontstrip
+ \else
+ \bgroup
+ \def\dofontstripa##1##2%
+ {\tttf\string##1}
+ \def\dofontstripb##1##2%
+ {\ruledhbox{\switchtobodyfont[#1]##1{##2}}}
+ \def\dofontstripc##1##2%
+ {\setbox\scratchbox\hbox{\switchtobodyfont[#1]##1{##2}}%
+ \tt\tfx\the\ht\scratchbox}%
+ \def\dofontstripd##1##2%
+ {\setbox\scratchbox\hbox{\switchtobodyfont[#1]##1{##2}}%
+ \tt\tfx\the\wd\scratchbox}%
+ \def\fontstrip##1##2##3%
+ {\NC##2\rm{##3}\NC
+ ##2\ss{##3}\NC
+ ##2\tt{##3}\NC
+ ##2\mathematics{##3}\NC
+ \tttf##1\NR}
+ \starttabulate[|c|c|c|c|c|]
+ \fontstrip\relax\dofontstripa\empty
+ \TB
+ \fontstrip\relax\dofontstripb{xxxx}
+ \fontstrip\relax\dofontstripb{12345}
+ \fontstrip\relax\dofontstripb{(Agw)}
+ \TB
+ \fontstrip{(x height)}\dofontstripc{x}
+ \fontstrip{(m width)}\dofontstripd{m}
+ \stoptabulate
+ \egroup
+ \fi}
+
+\ifx\databox\undefined \newbox\databox \fi
+
+\gdef\testminimalbaseline#1%
+ {\setbox\databox\ruledhbox{#1}%
+ \scratchdimen\ht\databox
+ \advance\scratchdimen\dp\databox
+ \scratchtoks{#1}%
+ \expanded
+ {\NC \ruledhbox{\the\scratchtoks}
+ \noexpand \NC ->
+ \noexpand \NC \the\scratchdimen
+ \noexpand \NC =
+ \noexpand \NC \the\ht\databox
+ \noexpand \NC +
+ \noexpand \NC \the\dp\databox
+ \noexpand \NC \ifdim\scratchdimen<\baselineskip <
+ \else\ifdim\scratchdimen=\baselineskip =
+ \else > \fi\fi
+ \noexpand \NC \the\baselineskip
+ \noexpand \NC (\ifdim\scratchdimen>\baselineskip not \fi ok)
+ \noexpand \NC \noexpand \NR }}
+
+\gdef\showminimalbaseline
+ {\ifx\starttabulate\undefined
+ \@@onlyenglish\showminimalbaseline
+ \else
+ \starttabulate[||T|T|T|T|T|T|T|T|T|]
+ \testminimalbaseline{\hbox to 1em{\hss\showstruts\strut\hss}}%
+ \testminimalbaseline{(/)}%
+ \testminimalbaseline{$\frac{1}{2}x^2_3$}
+ \stoptabulate
+ \fi}
+
+\gdef\showkerning#1%
+ {\bgroup
+ \let\MPfshowcommand\ruledhbox
+ \setMPtext\s!dummy{#1}%
+ \startMPcode draw textext(\MPstring\s!dummy);\stopMPcode
+ \egroup}
+
+\gdef\showcharratio
+ {\dowithnextboxcontent
+ {\switchtobodyfont[10pt]}%
+ {(\expanded{\withoutpt\the\nextboxht},%
+ \expanded{\withoutpt\the\nextboxdp})}%
+ \hbox}
+
+\protect \endinput
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
new file mode 100644
index 000000000..5ad92e002
--- /dev/null
+++ b/tex/context/base/font-syn.lua
@@ -0,0 +1,1454 @@
+if not modules then modules = { } end modules ['font-syn'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: subs in lookups requests
+
+local utf = unicode.utf8
+local next, tonumber = next, tonumber
+local gsub, lower, match, find, lower, upper = string.gsub, string.lower, string.match, string.find, string.lower, string.upper
+local find, gmatch = string.find, string.gmatch
+local concat, sort, format = table.concat, table.sort, string.format
+local lpegmatch = lpeg.match
+local utfgsub, utflower = utf.gsub, utf.lower
+local unpack = unpack or table.unpack
+
+local trace_names = false trackers.register("fonts.names", function(v) trace_names = v end)
+local trace_warnings = false trackers.register("fonts.warnings", function(v) trace_warnings = v end)
+
+--[[ldx--
+
This module implements a name to filename resolver. Names are resolved
+using a table that has keys filtered from the font related files.
+--ldx]]--
+
+local texsprint = (tex and tex.sprint) or print
+
+fonts = fonts or { }
+input = input or { }
+texmf = texmf or { }
+
+fonts.names = fonts.names or { }
+fonts.names.filters = fonts.names.filters or { }
+fonts.names.data = fonts.names.data or { }
+
+local names = fonts.names
+local filters = fonts.names.filters
+
+names.version = 1.103
+names.basename = "names"
+names.saved = false
+names.loaded = false
+names.be_clever = true
+names.enabled = true
+names.autoreload = toboolean(os.env['MTX.FONTS.AUTOLOAD'] or os.env['MTX_FONTS_AUTOLOAD'] or "no")
+names.cache = containers.define("fonts","data",names.version,true)
+
+--[[ldx--
+
A few helpers.
+--ldx]]--
+
+local P, C, Cc, Cs, Carg = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg
+
+-- what to do with 'thin'
+
+local weights = Cs ( -- not extra
+ P("demibold")
+ + P("semibold")
+ + P("mediumbold")
+ + P("ultrabold")
+ + P("extrabold")
+ + P("ultralight")
+ + P("bold")
+ + P("demi")
+ + P("semi")
+ + P("light")
+ + P("medium")
+ + P("heavy")
+ + P("ultra")
+ + P("black")
+ + P("bol") -- / "bold"
+ + P("regular") / "normal"
+)
+
+local styles = Cs (
+ P("reverseoblique") / "reverseitalic"
+ + P("regular") / "normal"
+ + P("italic")
+ + P("oblique") / "italic"
+ + P("slanted")
+ + P("roman") / "normal"
+ + P("ital") / "italic"
+ + P("ita") / "italic"
+)
+
+local widths = Cs(
+ P("condensed")
+ + P("thin")
+ + P("expanded")
+ + P("cond") / "condensed"
+ + P("normal")
+ + P("book") / "normal"
+)
+
+local variants = Cs( -- fax casual
+ P("smallcaps")
+ + P("oldstyle")
+ + P("caps") / "smallcaps"
+)
+
+local any = P(1)
+
+local analysed_table
+
+local analyser = Cs (
+ (
+ weights / function(s) analysed_table[1] = s return "" end
+ + styles / function(s) analysed_table[2] = s return "" end
+ + widths / function(s) analysed_table[3] = s return "" end
+ + variants / function(s) analysed_table[4] = s return "" end
+ + any
+ )^0
+)
+
+local splitter = lpeg.splitat("-")
+
+function names.splitspec(askedname)
+ local name, weight, style, width, variant = lpegmatch(splitter,askedname)
+ weight = weight and lpegmatch(weights, weight) or weight
+ style = style and lpegmatch(styles, style) or style
+ width = width and lpegmatch(widths, width) or width
+ variant = variant and lpegmatch(variants,variant) or variant
+ if trace_names then
+ logs.report("fonts","requested name '%s' split in name '%s', weight '%s', style '%s', width '%s' and variant '%s'",
+ askedname,name or '',weight or '',style or '',width or '',variant or '')
+ end
+ if not weight or not weight or not width or not variant then
+ weight, style, width, variant = weight or "normal", style or "normal", width or "normal", variant or "normal"
+ if trace_names then
+ logs.report("fonts","request '%s' normalized to '%s-%s-%s-%s-%s'",
+ askedname,name,weight,style,width,variant)
+ end
+ end
+ return name or askedname, weight, style, width, variant
+end
+
+local function analysespec(somename)
+ if somename then
+ analysed_table = { }
+ local name = lpegmatch(analyser,somename)
+ return name, analysed_table[1], analysed_table[2], analysed_table[3], analysed_table[4]
+ end
+end
+
+--[[ldx--
+
It would make sense to implement the filters in the related modules,
+but to keep the overview, we define them here.
+--ldx]]--
+
+filters.otf = fontloader.info
+filters.ttf = fontloader.info
+filters.ttc = fontloader.info
+filters.dfont = fontloader.info
+
+function fontloader.fullinfo(...)
+ local ff = fontloader.open(...)
+ if ff then
+ local d = ff and fontloader.to_table(ff)
+ d.glyphs, d.subfonts, d.gpos, d.gsub, d.lookups = nil, nil, nil, nil, nil
+ fontloader.close(ff)
+ return d
+ else
+ return nil, "error in loading font"
+ end
+end
+
+filters.otf = fontloader.fullinfo
+
+function filters.afm(name)
+ -- we could parse the afm file as well, and then report an error but
+ -- it's not worth the trouble
+ local pfbname = resolvers.find_file(file.removesuffix(name)..".pfb","pfb") or ""
+ if pfbname == "" then
+ pfbname = resolvers.find_file(file.removesuffix(file.basename(name))..".pfb","pfb") or ""
+ end
+ if pfbname ~= "" then
+ local f = io.open(name)
+ if f then
+ local hash = { }
+ for line in f:lines() do
+ local key, value = match(line,"^(.+)%s+(.+)%s*$")
+ if key and #key > 0 then
+ hash[lower(key)] = value
+ end
+ if find(line,"StartCharMetrics") then
+ break
+ end
+ end
+ f:close()
+ return hash
+ end
+ end
+ return nil, "no matching pfb file"
+end
+
+function filters.pfb(name)
+ return fontloader.info(name)
+end
+
+--[[ldx--
+
The scanner loops over the filters using the information stored in
+the file databases. Watch how we check not only for the names, but also
+for combination with the weight of a font.
+--ldx]]--
+
+filters.list = {
+ "otf", "ttf", "ttc", "dfont", "afm",
+--~ "ttc", "otf", "ttf", "dfont", "afm",
+}
+
+names.xml_configuration_file = "fonts.conf" -- a bit weird format, bonus feature
+names.environment_path_variable = "OSFONTDIR" -- the official way, in minimals etc
+
+filters.paths = { }
+filters.names = { }
+
+function names.getpaths(trace)
+ local hash, result = { }, { }
+ local function collect(t)
+ for i=1, #t do
+ local v = resolvers.clean_path(t[i])
+ v = gsub(v,"/+$","")
+ local key = lower(v)
+ if not hash[key] then
+ hash[key], result[#result+1] = true, v
+ end
+ end
+ end
+ local path = names.environment_path_variable or ""
+ if path ~= "" then
+ collect(resolvers.expanded_path_list(path))
+ end
+ if xml then
+ local confname = names.xml_configuration_file or ""
+ if confname ~= "" then
+ -- first look in the tex tree
+ local name = resolvers.find_file(confname,"other")
+ if name == "" then
+ -- after all, fontconfig is a unix thing
+ name = file.join("/etc",confname)
+ if not lfs.isfile(name) then
+ name = "" -- force quit
+ end
+ end
+ if name ~= "" and lfs.isfile(name) then
+ if trace_names then
+ logs.report("fontnames","loading fontconfig file: %s",name)
+ end
+ local xmldata = xml.load(name)
+ -- begin of untested mess
+ xml.include(xmldata,"include","",true,function(incname)
+ if not file.is_qualified_path(incname) then
+ local path = file.dirname(name) -- main name
+ if path ~= "" then
+ incname = file.join(path,incname)
+ end
+ end
+ if lfs.isfile(incname) then
+ if trace_names then
+ logs.report("fontnames","merging included fontconfig file: %s",incname)
+ end
+ return io.loaddata(incname)
+ elseif trace_names then
+ logs.report("fontnames","ignoring included fontconfig file: %s",incname)
+ end
+ end)
+ -- end of untested mess
+ local fontdirs = xml.collect_texts(xmldata,"dir",true)
+ if trace_names then
+ logs.report("fontnames","%s dirs found in fontconfig",#fontdirs)
+ end
+ collect(fontdirs)
+ end
+ end
+ end
+ function names.getpaths()
+ return result
+ end
+ return result
+end
+
+local function cleanname(name)
+ return (gsub(lower(name),"[^%a%d]",""))
+ -- once we can load files with utf names, we can play with the following:
+ -- return (utfgsub(utfgsub(lower(str),"[^%a%A%d]",""),"%s",""))
+end
+
+names.cleanname = cleanname
+
+local function check_names(result)
+ local names = result.names
+ if names then
+ for i=1,#names do
+ local name = names[i]
+ if name.lang == "English (US)" then
+ return name.names
+ end
+ end
+ end
+end
+
+local function walk_tree(pathlist,suffix,identify)
+ if pathlist then
+ for i=1,#pathlist do
+ local path = pathlist[i]
+ path = resolvers.clean_path(path .. "/")
+ path = gsub(path,"/+","/")
+ local pattern = path .. "**." .. suffix -- ** forces recurse
+ logs.report("fontnames", "globbing path %s",pattern)
+ local t = dir.glob(pattern)
+ sort(t,sorter)
+ for j=1,#t do
+ local completename = t[j]
+ identify(completename,file.basename(completename),suffix,completename)
+ end
+ end
+ end
+end
+
+local function check_name(data,result,filename,suffix,subfont)
+ -- shortcuts
+ local specifications = data.specifications
+ local families = data.families
+ -- prepare
+ local names = check_names(result)
+ -- fetch
+ local familyname = (names and names.preffamilyname) or result.familyname
+ local fullname = (names and names.fullname) or result.fullname
+ local fontname = result.fontname
+ local subfamily = (names and names.subfamily)
+ local modifiers = (names and names.prefmodifiers)
+ local weight = (names and names.weight) or result.weight
+ local italicangle = tonumber(result.italicangle)
+ local subfont = subfont or nil
+ local rawname = fullname or fontname or familyname
+ -- normalize
+ familyname = familyname and cleanname(familyname)
+ fullname = fullname and cleanname(fullname)
+ fontname = fontname and cleanname(fontname)
+ subfamily = subfamily and cleanname(subfamily)
+ modifiers = modifiers and cleanname(modifiers)
+ weight = weight and cleanname(weight)
+ italicangle = (italicangle == 0) and nil
+ -- analyse
+ local a_name, a_weight, a_style, a_width, a_variant = analysespec(fullname or fontname or familyname)
+ -- check
+ local width = a_width
+ local variant = a_variant
+ local style = modifiers and gsub(modifiers,"[^%a]","")
+ if not style and italicangle then
+ style = "italic"
+ end
+ if not variant or variant == "" then
+ variant = "normal"
+ end
+ if not weight or weight == "" then
+ weight = a_weight
+ end
+ if not style or style == "" then
+ style = a_style
+ end
+ if not familyname then
+ familyname = a_name
+ end
+ fontname = fontname or fullname or familyname or file.basename(filename)
+ fullname = fullname or fontname
+ familyname = familyname or fontname
+ specifications[#specifications + 1] = {
+ filename = filename,
+ format = lower(suffix),
+ subfont = subfont,
+ rawname = rawname,
+ familyname = familyname,
+ fullname = fullname,
+ fontname = fontname,
+ subfamily = subfamily,
+ modifiers = modifiers,
+ weight = weight,
+ style = style,
+ width = width,
+ variant = variant,
+ minsize = result.design_range_bottom or 0,
+ maxsize = result.design_range_top or 0,
+ designsize = result.design_size or 0,
+ }
+end
+
+local function cleanupkeywords()
+ local data = names.data
+ local specifications = names.data.specifications
+ if specifications then
+ local weights, styles, widths, variants = { }, { }, { }, { }
+ for i=1,#specifications do
+ local s = specifications[i]
+ -- fix (sofar styles are taken from the name, and widths from the specification)
+ local _, b_weight, b_style, b_width, b_variant = analysespec(s.weight)
+ local _, c_weight, c_style, c_width, c_variant = analysespec(s.style)
+ local _, d_weight, d_style, d_width, d_variant = analysespec(s.width)
+ local _, e_weight, e_style, e_width, e_variant = analysespec(s.variant)
+ local _, f_weight, f_style, f_width, f_variant = analysespec(s.fullname or "")
+ local weight = b_weight or c_weight or d_weight or e_weight or f_weight or "normal"
+ local style = b_style or c_style or d_style or e_style or f_style or "normal"
+ local width = b_width or c_width or d_width or e_width or f_width or "normal"
+ local variant = b_variant or c_variant or d_variant or e_variant or f_variant or "normal"
+ if not weight or weight == "" then weight = "normal" end
+ if not style or style == "" then style = "normal" end
+ if not width or width == "" then width = "normal" end
+ if not variant or variant == "" then variant = "normal" end
+ weights [weight ] = (weights [weight ] or 0) + 1
+ styles [style ] = (styles [style ] or 0) + 1
+ widths [width ] = (widths [width ] or 0) + 1
+ variants[variant] = (variants[variant] or 0) + 1
+ if weight ~= s.weight then
+ s.fontweight = s.weight
+ end
+ s.weight, s.style, s.width, s.variant = weight, style, width, variant
+ end
+ local stats = data.statistics
+ stats.used_weights, stats.used_styles, stats.used_widths, stats.used_variants = weights, styles, widths, variants
+ end
+end
+
+local function collectstatistics()
+ local data = names.data
+ local specifications = data.specifications
+ if specifications then
+ local weights, styles, widths, variants = { }, { }, { }, { }
+ for i=1,#specifications do
+ local s = specifications[i]
+ local weight, style, width, variant = s.weight, s.style, s.width, s.variant
+ if weight then weights [weight ] = (weights [weight ] or 0) + 1 end
+ if style then styles [style ] = (styles [style ] or 0) + 1 end
+ if width then widths [width ] = (widths [width ] or 0) + 1 end
+ if variant then variants[variant] = (variants[variant] or 0) + 1 end
+ end
+ local stats = data.statistics
+ stats.weights, stats.styles, stats.widths, stats.variants, stats.fonts = weights, styles, widths, variants, #specifications
+ end
+end
+
+local function collecthashes()
+ local data = names.data
+ local mappings = data.mappings
+ local fallbacks = data.fallbacks
+ local specifications = data.specifications
+ local nofmappings, noffallbacks = 0, 0
+ if specifications then
+ -- maybe multiple passes
+ for index=1,#specifications do
+ local s = specifications[index]
+ local format, fullname, fontname, familyname, weight, subfamily = s.format, s.fullname, s.fontname, s.familyname, s.weight, s.subfamily
+ local mf, ff = mappings[format], fallbacks[format]
+ if fullname and not mf[fullname] then
+ mf[fullname], nofmappings = index, nofmappings + 1
+ end
+ if fontname and not mf[fontname] then
+ mf[fontname], nofmappings = index, nofmappings + 1
+ end
+ if familyname and weight then
+ local madename = familyname .. weight
+ if not mf[madename] and not ff[madename] then
+ ff[madename], noffallbacks = index, noffallbacks + 1
+ end
+ end
+ if familyname and subfamily then
+ local extraname = familyname .. subfamily
+ if not mf[extraname] and not ff[extraname] then
+ ff[extraname], noffallbacks = index, noffallbacks + 1
+ end
+ end
+ if familyname then
+ if not mf[familyname] and not ff[familyname] then
+ ff[familyname], noffallbacks = index, noffallbacks + 1
+ end
+ end
+ end
+ end
+ return nofmappings, noffallbacks
+end
+
+local function collectfamilies()
+ local data = names.data
+ local specifications = data.specifications
+ local families = data.families
+ for index=1,#specifications do
+ local familyname = specifications[index].familyname
+ local family = families[familyname]
+ if not family then
+ families[familyname] = { index }
+ else
+ family[#family+1] = index
+ end
+ end
+end
+
+local function checkduplicate(where) -- fails on "Romantik" but that's a border case anyway
+ local data = names.data
+ local mapping = data[where]
+ local specifications, loaded = data.specifications, { }
+ if specifications and mapping then
+ for _, m in next, mapping do
+ for k, v in next, m do
+ local s = specifications[v]
+ local hash = format("%s-%s-%s-%s-%s",s.familyname,s.weight or "*",s.style or "*",s.width or "*",s.variant or "*")
+ local h = loaded[hash]
+ if h then
+ local ok = true
+ local fn = s.filename
+ for i=1,#h do
+ local hn = s.filename
+ if h[i] == fn then
+ ok = false
+ break
+ end
+ end
+ if ok then
+ h[#h+1] = fn
+ end
+ else
+ loaded[hash] = { s.filename }
+ end
+ end
+ end
+ end
+ local n = 0
+ for k, v in table.sortedhash(loaded) do
+ local nv = #v
+ if nv > 1 then
+ if trace_warnings then
+ logs.report("fontnames", "double lookup: %s => %s",k,concat(v," | "))
+ end
+ n = n + nv
+ end
+ end
+ logs.report("fontnames", "%s double lookups in %s",n,where)
+end
+
+local function checkduplicates()
+ checkduplicate("mappings")
+ checkduplicate("fallbacks")
+end
+
+local sorter = function(a,b)
+ return a > b -- to be checked
+end
+
+local function sorthashes()
+ local data, list = names.data, filters.list
+ local mappings, fallbacks, sorted_mappings, sorted_fallbacks = data.mappings, data.fallbacks, { }, { }
+ data.sorted_mappings, data.sorted_fallbacks = sorted_mappings, sorted_fallbacks
+ for i=1,#list do
+ local l = list[i]
+ sorted_mappings[l], sorted_fallbacks[l] = table.keys(mappings[l]), table.keys(fallbacks[l])
+ sort(sorted_mappings[l],sorter)
+ sort(sorted_fallbacks[l],sorter)
+ end
+ data.sorted_families = table.keys(data.families)
+ sort(data.sorted_families,sorter)
+end
+
+local function unpackreferences()
+ local data = names.data
+ local specifications = data.specifications
+ if specifications then
+ for k, v in next, data.families do
+ for i=1,#v do
+ v[i] = specifications[v[i]]
+ end
+ end
+ local mappings = data.mappings
+ if mappings then
+ for _, m in next, mappings do
+ for k, v in next, m do
+ m[k] = specifications[v]
+ end
+ end
+ end
+ local fallbacks = data.fallbacks
+ if fallbacks then
+ for _, f in next, fallbacks do
+ for k, v in next, f do
+ f[k] = specifications[v]
+ end
+ end
+ end
+ end
+end
+
+local function analysefiles()
+ local data = names.data
+ local done, totalnofread, totalnofskipped = { }, 0, 0
+ local skip_paths, skip_names = filters.paths, filters.names
+ local function identify(completename,name,suffix,storedname)
+ local basename = file.basename(completename)
+ local basepath = file.dirname(completename)
+ if done[name] then
+ -- already done (avoid otf afm clash)
+ elseif not io.exists(completename) then
+ -- weird error
+ elseif not file.is_qualified_path(completename) and resolvers.find_file(completename,suffix) == "" then
+ -- not locateble by backend anyway
+ else
+ nofread = nofread + 1
+ if #skip_paths > 0 then
+ for i=1,#skip_paths do
+ if find(basepath,skip_paths[i]) then
+ if trace_names then
+ logs.report("fontnames","rejecting path of %s font %s",suffix,completename)
+ logs.push()
+ end
+ return
+ end
+ end
+ end
+ if #skip_names > 0 then
+ for i=1,#skip_paths do
+ if find(basename,skip_names[i]) then
+ done[name] = true
+ if trace_names then
+ logs.report("fontnames","rejecting name of %s font %s",suffix,completename)
+ logs.push()
+ end
+ return
+ end
+ end
+ end
+ if trace_names then
+ logs.report("fontnames","identifying %s font %s",suffix,completename)
+ logs.push()
+ end
+ local result, message = filters[lower(suffix)](completename)
+ if trace_names then
+ logs.pop()
+ end
+ if result then
+ if not result[1] then
+ local ok = check_name(data,result,storedname,suffix)
+ if not ok then
+ nofskipped = nofskipped + 1
+ end
+ else
+ for r=1,#result do
+ local ok = check_name(data,result[r],storedname,suffix,r-1) -- subfonts start at zero
+ if not ok then
+ nofskipped = nofskipped + 1
+ end
+ end
+ end
+ if trace_warnings and message and message ~= "" then
+ logs.report("fontnames","warning when identifying %s font %s: %s",suffix,completename,message)
+ end
+ elseif trace_warnings then
+ logs.report("fontnames","error when identifying %s font %s: %s",suffix,completename,message or "unknown")
+ end
+ done[name] = true
+ end
+ end
+ local function traverse(what, method)
+ local list = filters.list
+ for n=1,#list do
+ local suffix = list[n]
+ local t = os.gettimeofday() -- use elapser
+ nofread, nofskipped = 0, 0
+ suffix = lower(suffix)
+ logs.report("fontnames", "identifying %s font files with suffix %s",what,suffix)
+ method(suffix)
+ suffix = upper(suffix)
+ logs.report("fontnames", "identifying %s font files with suffix %s",what,suffix)
+ method(suffix)
+ totalnofread, totalnofskipped = totalnofread + nofread, totalnofskipped + nofskipped
+ local elapsed = os.gettimeofday() - t
+ logs.report("fontnames", "%s %s files identified, %s hash entries added, runtime %0.3f seconds",nofread,what,nofread-nofskipped,elapsed)
+ end
+ end
+ if not trace_warnings then
+ logs.report("fontnames", "warnings are disabled (tracker 'fonts.warnings')")
+ end
+ traverse("tree", function(suffix) -- TEXTREE only
+ resolvers.with_files(".*%." .. suffix .. "$", function(method,root,path,name)
+ if method == "file" then
+ local completename = root .."/" .. path .. "/" .. name
+ identify(completename,name,suffix,name,name)
+ end
+ end)
+ end)
+ if texconfig.kpse_init then
+ -- we do this only for a stupid names run, not used for context itself,
+ -- using the vars is to clumsy so we just stick to a full scan instead
+ traverse("lsr", function(suffix) -- all trees
+ local pathlist = resolvers.split_path(resolvers.show_path("ls-R") or "")
+ walk_tree(pathlist,suffix,identify)
+ end)
+ else
+ traverse("system", function(suffix) -- OSFONTDIR cum suis
+ walk_tree(names.getpaths(trace),suffix,identify)
+ end)
+ end
+ data.statistics.readfiles, data.statistics.skippedfiles = totalnofread, totalnofskipped
+end
+
+local function rejectclashes() -- just to be sure, so no explicit afm will be found then
+ local specifications, used, okay = names.data.specifications, { }, { }
+ for i=1,#specifications do
+ local s = specifications[i]
+ local f = s.fontname
+ if f then
+ local fnd, fnm = used[f], s.filename
+ if fnd then
+ if trace_warnings then
+ logs.report("fontnames", "fontname '%s' clashes, rejecting '%s' in favor of '%s'",f,fnm,fnd)
+ end
+ else
+ used[f], okay[#okay+1] = fnm, s
+ end
+ else
+ okay[#okay+1] = s
+ end
+ end
+ local d = #specifications - #okay
+ if d > 0 then
+ logs.report("fontnames", "%s files rejected due to clashes",d)
+ end
+ names.data.specifications = okay
+end
+
+local function resetdata()
+ local mappings, fallbacks = { }, { }
+ for _, k in next, filters.list do
+ mappings[k], fallbacks[k] = { }, { }
+ end
+ names.data = {
+ version = names.version,
+ mappings = mappings,
+ fallbacks = fallbacks,
+ specifications = { },
+ families = { },
+ statistics = { },
+ data_state = resolvers.data_state(),
+ }
+end
+
+function names.identify()
+ resetdata()
+ analysefiles()
+ rejectclashes()
+ collectfamilies()
+ collectstatistics()
+ cleanupkeywords()
+ collecthashes()
+ checkduplicates()
+ -- sorthashes() -- will be resorted when saved
+end
+
+function names.is_permitted(name)
+ return containers.is_usable(names.cache(), name)
+end
+function names.write_data(name,data)
+ containers.write(names.cache(),name,data)
+end
+function names.read_data(name)
+ return containers.read(names.cache(),name)
+end
+
+function names.load(reload,verbose)
+ if not names.loaded then
+ if reload then
+ if names.is_permitted(names.basename) then
+ names.identify(verbose)
+ names.write_data(names.basename,names.data)
+ else
+ logs.report("font table", "unable to access database cache")
+ end
+ names.saved = true
+ end
+ local data = names.read_data(names.basename)
+ names.data = data
+ if not names.saved then
+ if not data or not next(data) or not data.specifications or not next(data.specifications) then
+ names.load(true)
+ end
+ names.saved = true
+ end
+ if not data then
+ logs.report("font table", "accessing the data table failed")
+ else
+ unpackreferences()
+ sorthashes()
+ end
+ names.loaded = true
+ end
+end
+
+local function list_them(mapping,sorted,pattern,t,all)
+ if mapping[pattern] then
+ t[pattern] = mapping[pattern]
+ else
+ for k=1,#sorted do
+ local v = sorted[k]
+ if not t[v] and find(v,pattern) then
+ t[v] = mapping[v]
+ if not all then
+ return
+ end
+ end
+ end
+ end
+end
+
+function names.list(pattern,reload,all) -- here?
+ names.load(reload)
+ if names.loaded then
+ local t = { }
+ local data = names.data
+ if data then
+ local list = filters.list
+ local mappings, sorted_mappings = data.mappings, data.sorted_mappings
+ local fallbacks, sorted_fallbacks = data.fallbacks, data.sorted_fallbacks
+ for i=1,#list do
+ local format = list[i]
+ list_them(mappings[format],sorted_mappings[format],pattern,t,all)
+ if next(t) and not all then
+ return t
+ end
+ list_them(fallbacks[format],sorted_fallbacks[format],pattern,t,all)
+ if next(t) and not all then
+ return t
+ end
+ end
+ end
+ return t
+ end
+end
+
+local reloaded = false
+
+local function is_reloaded()
+ if not reloaded then
+ local data = names.data
+ if names.autoreload then
+ local c_status = table.serialize(resolvers.data_state())
+ local f_status = table.serialize(data.data_state)
+ if c_status == f_status then
+ -- logs.report("fonts","font database matches configuration and file hashes")
+ return
+ else
+ logs.report("fonts","font database does not match configuration and file hashes")
+ end
+ end
+ names.loaded = false
+ reloaded = true
+ io.flush()
+ names.load(true)
+ end
+end
+
+--[[ldx--
+
The resolver also checks if the cached names are loaded. Being clever
+here is for testing purposes only (it deals with names prefixed by an
+encoding name).
+--ldx]]--
+
+local function fuzzy(mapping,sorted,name,sub)
+ local condensed = gsub(name,"[^%a%d]","")
+ for k=1,#sorted do
+ local v = sorted[k]
+ if find(v,condensed) then
+ return mapping[v], v
+ end
+ end
+end
+
+-- we could cache a lookup .. maybe some day ... (only when auto loaded!)
+
+local function foundname(name,sub) -- sub is not used currently
+ local data = names.data
+ local mappings, sorted_mappings = data.mappings, data.sorted_mappings
+ local fallbacks, sorted_fallbacks = data.fallbacks, data.sorted_fallbacks
+ local list = filters.list
+ -- dilemma: we lookup in the order otf ttf ttc ... afm but now an otf fallback
+ -- can come after an afm match ... well, one should provide nice names anyway
+ -- and having two lists is not an option
+ for i=1,#list do
+ local l = list[i]
+ local found = mappings[l][name]
+ if found then
+ if trace_names then
+ logs.report("fonts","resolved via direct name match: '%s'",name)
+ end
+ return found
+ end
+ end
+ for i=1,#list do
+ local l = list[i]
+ local found, fname = fuzzy(mappings[l],sorted_mappings[l],name,sub)
+ if found then
+ if trace_names then
+ logs.report("fonts","resolved via fuzzy name match: '%s' => '%s'",name,fname)
+ end
+ return found
+ end
+ end
+ for i=1,#list do
+ local l = list[i]
+ local found = fallbacks[l][name]
+ if found then
+ if trace_names then
+ logs.report("fonts","resolved via direct fallback match: '%s'",name)
+ end
+ return found
+ end
+ end
+ for i=1,#list do
+ local l = list[i]
+ local found, fname = fuzzy(sorted_mappings[l],sorted_fallbacks[l],name,sub)
+ if found then
+ if trace_names then
+ logs.report("fonts","resolved via fuzzy fallback match: '%s' => '%s'",name,fname)
+ end
+ return found
+ end
+ end
+end
+
+function names.resolvedspecification(askedname,sub)
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = cleanname(askedname)
+ names.load()
+ local found = foundname(askedname,sub)
+ if not found and is_reloaded() then
+ found = foundname(askedname,sub)
+ end
+ return found
+ end
+end
+
+function names.resolve(askedname,sub)
+ local found = names.resolvedspecification(askedname,sub)
+ if found then
+ return found.filename, found.subfont and found.rawname
+ end
+end
+
+-- specified search
+
+local function s_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,family)
+ if family then
+ for i=1,#family do
+ local f = family[i]
+ if f and weight == f.weight and style == f.style and width == f.width and variant == f.variant then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and style == f.style and width == f.width and variant == f.variant and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_weight_style_width(found,done,all,weight,style,width,family)
+ if family then
+ for i=1,#family do
+ local f = family[i]
+ if f and weight == f.weight and style == f.style and width == f.width then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight_style_width(found,done,all,weight,style,width,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and style == f.style and width == f.width and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_weight_style(found,done,all,weight,style,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and weight == f.weight and style == f.style then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight_style(found,done,all,weight,style,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and style == f.style and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_style_width(found,done,all,style,width,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and style == f.style and width == f.width then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_style_width(found,done,all,style,width,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and style == f.style and width == f.width and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_weight(found,done,all,weight,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and weight == f.weight then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_weight(found,done,all,weight,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and weight == f.weight and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_style(found,done,all,style,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and style == f.style then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_style(found,done,all,style,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and style == f.style and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect_width(found,done,all,width,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f and width == f.width then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect_width(found,done,all,width,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and width == f.width and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function s_collect(found,done,all,family)
+ if family then
+ for i=1,#family do local f = family[i]
+ if f then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+local function m_collect(found,done,all,families,sorted,strictname)
+ for i=1,#sorted do
+ local k = sorted[i]
+ local family = families[k]
+ for i=1,#family do
+ local f = family[i]
+ if not done[f] and find(f.fontname,strictname) then
+ found[#found+1], done[f] = f, true
+ if not all then return end
+ end
+ end
+ end
+end
+
+local function collect(stage,found,done,name,weight,style,width,variant,all)
+ local data = names.data
+ local families, sorted = data.families, data.sorted_families
+ strictname = "^".. name -- to be checked
+ local family = families[name]
+ if trace_names then
+ logs.report("fonts","resolving name '%s', weight '%s', style '%s', width '%s', variant '%s'",
+ name or "?",tostring(weight),tostring(style),tostring(width),tostring(variant))
+ end
+ --~ print(name,table.serialize(family))
+ if weight and weight ~= "" then
+ if style and style ~= "" then
+ if width and width ~= "" then
+ if variant and variant ~= "" then
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s', width '%s', variant '%s'",stage,name,weight,style,width,variant)
+ end
+ s_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,family)
+ m_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,families,sorted,strictname)
+ else
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s', width '%s'",stage,name,weight,style,width)
+ end
+ s_collect_weight_style_width(found,done,all,weight,style,width,family)
+ m_collect_weight_style_width(found,done,all,weight,style,width,families,sorted,strictname)
+ end
+ else
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s'",stage,name,weight,style)
+ end
+ s_collect_weight_style(found,done,all,weight,style,family)
+ m_collect_weight_style(found,done,all,weight,style,families,sorted,strictname)
+ end
+ else
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s', weight '%s'",stage,name,weight)
+ end
+ s_collect_weight(found,done,all,weight,family)
+ m_collect_weight(found,done,all,weight,families,sorted,strictname)
+ end
+ elseif style and style ~= "" then
+ if width and width ~= "" then
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s', style '%s', width '%s'",stage,name,style,width)
+ end
+ s_collect_style_width(found,done,all,style,width,family)
+ m_collect_style_width(found,done,all,style,width,families,sorted,strictname)
+ else
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s', style '%s'",stage,name,style)
+ end
+ s_collect_style(found,done,all,style,family)
+ m_collect_style(found,done,all,style,families,sorted,strictname)
+ end
+ elseif width and width ~= "" then
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s', width '%s'",stage,name,width)
+ end
+ s_collect_width(found,done,all,width,family)
+ m_collect_width(found,done,all,width,families,sorted,strictname)
+ else
+ if trace_names then
+ logs.report("fonts","resolving stage %s, name '%s'",stage,name)
+ end
+ s_collect(found,done,all,family)
+ m_collect(found,done,all,families,sorted,strictname)
+ end
+end
+
+function heuristic(name,weight,style,width,variant,all) -- todo: fallbacks
+ local found, done = { }, { }
+--~ print(name,weight,style,width,variant)
+ weight, style, width, variant = weight or "normal", style or "normal", width or "normal", variant or "normal"
+ name = cleanname(name)
+ collect(1,found,done,name,weight,style,width,variant,all)
+ -- still needed ?
+ if #found == 0 and variant ~= "normal" then -- not weight
+ variant = "normal"
+ collect(4,found,done,name,weight,style,width,variant,all)
+ end
+ if #found == 0 and width ~= "normal" then
+ width = "normal"
+ collect(2,found,done,name,weight,style,width,variant,all)
+ end
+ if #found == 0 and weight ~= "normal" then -- not style
+ weight = "normal"
+ collect(3,found,done,name,weight,style,width,variant,all)
+ end
+ if #found == 0 and style ~= "normal" then -- not weight
+ style = "normal"
+ collect(4,found,done,name,weight,style,width,variant,all)
+ end
+ --
+ local nf = #found
+ if trace_names then
+ if nf then
+ local t = { }
+ for i=1,nf do
+ t[#t+1] = format("'%s'",found[i].fontname)
+ end
+ logs.report("fonts","name '%s' resolved to %s instances: %s",name,nf,concat(t," "))
+ else
+ logs.report("fonts","name '%s' unresolved",name)
+ end
+ end
+ if all then
+ return nf > 0 and found
+ else
+ return found[1]
+ end
+end
+
+function names.specification(askedname,weight,style,width,variant,reload,all)
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = lower(askedname) -- or cleanname
+ names.load(reload)
+ local found = heuristic(askedname,weight,style,width,variant,all)
+ if not found and is_reloaded() then
+ found = heuristic(askedname,weight,style,width,variant,all)
+ if not filename then
+ found = foundname(askedname) -- old method
+ end
+ end
+ return found
+ end
+end
+
+function names.collect(askedname,weight,style,width,variant,reload,all)
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = lower(askedname) -- or cleanname
+ names.load(reload)
+ local list = heuristic(askedname,weight,style,width,variant,true)
+ if not list or #list == 0 and is_reloaded() then
+ list = heuristic(askedname,weight,style,width,variant,true)
+ end
+ return list
+ end
+end
+
+function names.collectspec(askedname,reload,all)
+ local name, weight, style, width, variant = names.splitspec(askedname)
+ return names.collect(name,weight,style,width,variant,reload,all)
+end
+
+function names.resolvespec(askedname,sub)
+ local found = names.specification(names.splitspec(askedname))
+ if found then
+ return found.filename, found.subfont and found.rawname
+ end
+end
+
+function names.collectfiles(askedname,reload) -- no all
+ if askedname and askedname ~= "" and names.enabled then
+ askedname = lower(askedname) -- or cleanname
+ names.load(reload)
+ local list = { }
+ local basename = file.basename
+ local specifications = names.data.specifications
+ for i=1,#specifications do
+ local s = specifications[i]
+ if find(lower(basename(s.filename)),askedname) then
+ list[#list+1] = s
+ end
+ end
+ return list
+ end
+end
+
+--[[ldx--
+
Fallbacks, not permanent but a transition thing.
+--ldx]]--
+
+names.new_to_old = {
+ ["lmroman10-capsregular"] = "lmromancaps10-oblique",
+ ["lmroman10-capsoblique"] = "lmromancaps10-regular",
+ ["lmroman10-demi"] = "lmromandemi10-oblique",
+ ["lmroman10-demioblique"] = "lmromandemi10-regular",
+ ["lmroman8-oblique"] = "lmromanslant8-regular",
+ ["lmroman9-oblique"] = "lmromanslant9-regular",
+ ["lmroman10-oblique"] = "lmromanslant10-regular",
+ ["lmroman12-oblique"] = "lmromanslant12-regular",
+ ["lmroman17-oblique"] = "lmromanslant17-regular",
+ ["lmroman10-boldoblique"] = "lmromanslant10-bold",
+ ["lmroman10-dunhill"] = "lmromandunh10-oblique",
+ ["lmroman10-dunhilloblique"] = "lmromandunh10-regular",
+ ["lmroman10-unslanted"] = "lmromanunsl10-regular",
+ ["lmsans10-demicondensed"] = "lmsansdemicond10-regular",
+ ["lmsans10-demicondensedoblique"] = "lmsansdemicond10-oblique",
+ ["lmsansquotation8-bold"] = "lmsansquot8-bold",
+ ["lmsansquotation8-boldoblique"] = "lmsansquot8-boldoblique",
+ ["lmsansquotation8-oblique"] = "lmsansquot8-oblique",
+ ["lmsansquotation8-regular"] = "lmsansquot8-regular",
+ ["lmtypewriter8-regular"] = "lmmono8-regular",
+ ["lmtypewriter9-regular"] = "lmmono9-regular",
+ ["lmtypewriter10-regular"] = "lmmono10-regular",
+ ["lmtypewriter12-regular"] = "lmmono12-regular",
+ ["lmtypewriter10-italic"] = "lmmono10-italic",
+ ["lmtypewriter10-oblique"] = "lmmonoslant10-regular",
+ ["lmtypewriter10-capsoblique"] = "lmmonocaps10-oblique",
+ ["lmtypewriter10-capsregular"] = "lmmonocaps10-regular",
+ ["lmtypewriter10-light"] = "lmmonolt10-regular",
+ ["lmtypewriter10-lightoblique"] = "lmmonolt10-oblique",
+ ["lmtypewriter10-lightcondensed"] = "lmmonoltcond10-regular",
+ ["lmtypewriter10-lightcondensedoblique"] = "lmmonoltcond10-oblique",
+ ["lmtypewriter10-dark"] = "lmmonolt10-bold",
+ ["lmtypewriter10-darkoblique"] = "lmmonolt10-boldoblique",
+ ["lmtypewritervarwd10-regular"] = "lmmonoproplt10-regular",
+ ["lmtypewritervarwd10-oblique"] = "lmmonoproplt10-oblique",
+ ["lmtypewritervarwd10-light"] = "lmmonoprop10-regular",
+ ["lmtypewritervarwd10-lightoblique"] = "lmmonoprop10-oblique",
+ ["lmtypewritervarwd10-dark"] = "lmmonoproplt10-bold",
+ ["lmtypewritervarwd10-darkoblique"] = "lmmonoproplt10-boldoblique",
+}
+
+names.old_to_new = table.swapped(names.new_to_old)
+
+function names.exists(name)
+ local found = false
+ local list = filters.list
+ for k=1,#list do
+ local v = list[k]
+ found = (resolvers.find_file(name,v) or "") ~= ""
+ if found then
+ return found
+ end
+ end
+ return ((resolvers.find_file(name,"tfm") or "") ~= "") or ((names.resolve(name) or "") ~= "")
+end
+
+-- for i=1,fonts.names.lookup(pattern) do
+-- texio.write_nl(fonts.names.getkey("filename",i))
+-- end
+
+local lastlookups, lastpattern = { }, ""
+
+function names.lookup(pattern,name,reload) -- todo: find
+ if lastpattern ~= pattern then
+ names.load(reload)
+ local specifications = names.data.specifications
+ local families = names.data.families
+ local lookups = specifications
+ if name then
+ lookups = families[name]
+ elseif not find(pattern,"=") then
+ lookups = families[pattern]
+ end
+ if trace_names then
+ logs.report("fonts","starting with %s lookups for '%s'",#lookups,pattern)
+ end
+ if lookups then
+ for key, value in gmatch(pattern,"([^=,]+)=([^=,]+)") do
+ local t = { }
+ for i=1,#lookups do
+ local s = lookups[i]
+ if s[key] == value then
+ t[#t+1] = lookups[i]
+ end
+ end
+ if trace_names then
+ logs.report("fonts","%s matches for key '%s' with value '%s'",#t,key,value)
+ end
+ lookups = t
+ end
+ end
+ lastpattern = pattern
+ lastlookups = lookups or { }
+ end
+ return #lastlookups
+end
+
+function names.getlookupkey(key,n)
+ local l = lastlookups[n or 1]
+ return (l and l[key]) or ""
+end
+
+function names.noflookups()
+ return #lastlookups
+end
+
+function names.getlookups(pattern,name,reload)
+ if pattern then
+ names.lookup(pattern,name,reload)
+ end
+ return lastlookups
+end
+
+function table.formatcolumns(result)
+ if result and #result > 0 then
+ local widths = { }
+ local first = result[1]
+ local n = #first
+ for i=1,n do
+ widths[i] = 0
+ end
+ for i=1,#result do
+ local r = result[i]
+ for j=1,n do
+ local w = #r[j]
+ if w > widths[j] then
+ widths[j] = w
+ end
+ end
+ end
+ for i=1,n do
+ widths[i] = "%-" .. widths[i] .. "s"
+ end
+ local template = concat(widths," ")
+ for i=1,#result do
+ local str = format(template,unpack(result[i]))
+ result[i] = string.strip(str)
+ end
+ end
+ return result
+end
diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua
new file mode 100644
index 000000000..31ae2cae1
--- /dev/null
+++ b/tex/context/base/font-tfm.lua
@@ -0,0 +1,736 @@
+if not modules then modules = { } end modules ['font-tfm'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+
+local next, format, match, lower, gsub = next, string.format, string.match, string.lower, string.gsub
+local concat, sortedkeys, utfbyte, serialize = table.concat, table.sortedkeys, utf.byte, table.serialize
+
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end)
+
+-- tfmdata has also fast access to indices and unicodes
+-- to be checked: otf -> tfm -> tfmscaled
+--
+-- watch out: no negative depths and negative eights permitted in regular fonts
+
+--[[ldx--
+
Here we only implement a few helper functions.
+--ldx]]--
+
+fonts = fonts or { }
+fonts.tfm = fonts.tfm or { }
+fonts.ids = fonts.ids or { }
+
+local tfm = fonts.tfm
+
+fonts.loaded = fonts.loaded or { }
+fonts.dontembed = fonts.dontembed or { }
+fonts.triggers = fonts.triggers or { } -- brrr
+fonts.initializers = fonts.initializers or { }
+fonts.initializers.common = fonts.initializers.common or { }
+
+local fontdata = fonts.ids
+local disc = node.id('disc')
+local glyph = node.id('glyph')
+local set_attribute = node.set_attribute
+
+--[[ldx--
+
The next function encapsulates the standard loader as
+supplied by .
+--ldx]]--
+
+tfm.resolve_vf = true -- false
+tfm.share_base_kerns = false -- true (.5 sec slower on mk but brings down mem from 410M to 310M, beware: then script/lang share too)
+tfm.mathactions = { }
+tfm.fontname_mode = "fullpath"
+
+tfm.enhance = tfm.enhance or function() end
+
+function tfm.read_from_tfm(specification)
+ local fname, tfmdata = specification.filename or "", nil
+ if fname ~= "" then
+ if trace_defining then
+ logs.report("define font","loading tfm file %s at size %s",fname,specification.size)
+ end
+ tfmdata = font.read_tfm(fname,specification.size) -- not cached, fast enough
+ if tfmdata then
+ tfmdata.descriptions = tfmdata.descriptions or { }
+ if tfm.resolve_vf then
+ fonts.logger.save(tfmdata,file.extname(fname),specification) -- strange, why here
+ fname = resolvers.findbinfile(specification.name, 'ovf')
+ if fname and fname ~= "" then
+ local vfdata = font.read_vf(fname,specification.size) -- not cached, fast enough
+ if vfdata then
+ local chars = tfmdata.characters
+ for k,v in next, vfdata.characters do
+ chars[k].commands = v.commands
+ end
+ tfmdata.type = 'virtual'
+ tfmdata.fonts = vfdata.fonts
+ end
+ end
+ end
+ tfm.enhance(tfmdata,specification)
+ end
+ elseif trace_defining then
+ logs.report("define font","loading tfm with name %s fails",specification.name)
+ end
+ return tfmdata
+end
+
+--[[ldx--
+
We need to normalize the scale factor (in scaled points). This has to
+do with the fact that uses a negative multiple of 1000 as
+a signal for a font scaled based on the design size.
+--ldx]]--
+
+local factors = {
+ pt = 65536.0,
+ bp = 65781.8,
+}
+
+function tfm.setfactor(f)
+ tfm.factor = factors[f or 'pt'] or factors.pt
+end
+
+tfm.setfactor()
+
+function tfm.scaled(scaledpoints, designsize) -- handles designsize in sp as well
+ if scaledpoints < 0 then
+ if designsize then
+ if designsize > tfm.factor then -- or just 1000 / when? mp?
+ return (- scaledpoints/1000) * designsize -- sp's
+ else
+ return (- scaledpoints/1000) * designsize * tfm.factor
+ end
+ else
+ return (- scaledpoints/1000) * 10 * tfm.factor
+ end
+ else
+ return scaledpoints
+ end
+end
+
+--[[ldx--
+
Before a font is passed to we scale it. Here we also need
+to scale virtual characters.
+--ldx]]--
+
+function tfm.get_virtual_id(tfmdata)
+ -- since we don't know the id yet, we use 0 as signal
+ if not tfmdata.fonts then
+ tfmdata.type = "virtual"
+ tfmdata.fonts = { { id = 0 } }
+ return 1
+ else
+ tfmdata.fonts[#tfmdata.fonts+1] = { id = 0 }
+ return #tfmdata.fonts
+ end
+end
+
+function tfm.check_virtual_id(tfmdata, id)
+ if tfmdata and tfmdata.type == "virtual" then
+ if not tfmdata.fonts or #tfmdata.fonts == 0 then
+ tfmdata.type, tfmdata.fonts = "real", nil
+ else
+ local vfonts = tfmdata.fonts
+ for f=1,#vfonts do
+ local fnt = vfonts[f]
+ if fnt.id and fnt.id == 0 then
+ fnt.id = id
+ end
+ end
+ end
+ end
+end
+
+--[[ldx--
+
Beware, the boundingbox is passed as reference so we may not overwrite it
+in the process; numbers are of course copies. Here 65536 equals 1pt. (Due to
+excessive memory usage in CJK fonts, we no longer pass the boundingbox.)
+--ldx]]--
+
+fonts.trace_scaling = false
+
+-- the following hack costs a bit of runtime but safes memory
+--
+-- basekerns are scaled and will be hashed by table id
+-- sharedkerns are unscaled and are be hashed by concatenated indexes
+
+--~ function tfm.check_base_kerns(tfmdata)
+--~ if tfm.share_base_kerns then
+--~ local sharedkerns = tfmdata.sharedkerns
+--~ if sharedkerns then
+--~ local basekerns = { }
+--~ tfmdata.basekerns = basekerns
+--~ return sharedkerns, basekerns
+--~ end
+--~ end
+--~ return nil, nil
+--~ end
+
+--~ function tfm.prepare_base_kerns(tfmdata)
+--~ if tfm.share_base_kerns and not tfmdata.sharedkerns then
+--~ local sharedkerns = { }
+--~ tfmdata.sharedkerns = sharedkerns
+--~ for u, chr in next, tfmdata.characters do
+--~ local kerns = chr.kerns
+--~ if kerns then
+--~ local hash = concat(sortedkeys(kerns), " ")
+--~ local base = sharedkerns[hash]
+--~ if not base then
+--~ sharedkerns[hash] = kerns
+--~ else
+--~ chr.kerns = base
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+
+-- we can have cache scaled characters when we are in node mode and don't have
+-- protruding and expansion: hash == fullname @ size @ protruding @ expansion
+-- but in practice (except from mk) the otf hash will be enough already so it
+-- makes no sense to mess up the code now
+
+local charactercache = { }
+
+-- The scaler is only used for otf and afm and virtual fonts. If
+-- a virtual font has italic correction make sure to set the
+-- has_italic flag. Some more flags will be added in the future.
+
+function tfm.calculate_scale(tfmtable, scaledpoints, relativeid)
+ if scaledpoints < 0 then
+ scaledpoints = (- scaledpoints/1000) * tfmtable.designsize -- already in sp
+ end
+ local units = tfmtable.units or 1000
+ local delta = scaledpoints/units -- brr, some open type fonts have 2048
+ return scaledpoints, delta, units
+end
+
+function tfm.do_scale(tfmtable, scaledpoints, relativeid)
+ -- tfm.prepare_base_kerns(tfmtable) -- optimalization
+ local t = { } -- the new table
+ local scaledpoints, delta, units = tfm.calculate_scale(tfmtable, scaledpoints, relativeid)
+ t.units_per_em = units or 1000
+ local hdelta, vdelta = delta, delta
+ -- unicoded unique descriptions shared cidinfo characters changed parameters indices
+ for k,v in next, tfmtable do
+ if type(v) == "table" then
+ -- print(k)
+ else
+ t[k] = v
+ end
+ end
+ local extend_factor = tfmtable.extend_factor or 0
+ if extend_factor ~= 0 and extend_factor ~= 1 then
+ hdelta = hdelta * extend_factor
+ t.extend = extend_factor * 1000
+ else
+ t.extend = 1000
+ end
+ local slant_factor = tfmtable.slant_factor or 0
+ if slant_factor ~= 0 then
+ t.slant = slant_factor * 1000
+ else
+ t.slant = 0
+ end
+ -- status
+ local isvirtual = tfmtable.type == "virtual" or tfmtable.virtualized
+ local hasmath = (tfmtable.math_parameters ~= nil and next(tfmtable.math_parameters) ~= nil) or (tfmtable.MathConstants ~= nil and next(tfmtable.MathConstants) ~= nil)
+ local nodemode = tfmtable.mode == "node"
+ local hasquality = tfmtable.auto_expand or tfmtable.auto_protrude
+ local hasitalic = tfmtable.has_italic
+ --
+ t.parameters = { }
+ t.characters = { }
+ t.MathConstants = { }
+ -- fast access
+ local descriptions = tfmtable.descriptions or { }
+ t.unicodes = tfmtable.unicodes
+ t.indices = tfmtable.indices
+ t.marks = tfmtable.marks
+t.goodies = tfmtable.goodies
+t.colorscheme = tfmtable.colorscheme
+--~ t.embedding = tfmtable.embedding
+ t.descriptions = descriptions
+ if tfmtable.fonts then
+ t.fonts = table.fastcopy(tfmtable.fonts) -- hm also at the end
+ end
+ local tp = t.parameters
+ local mp = t.math_parameters
+ local tfmp = tfmtable.parameters -- let's check for indexes
+ --
+ tp.slant = (tfmp.slant or tfmp[1] or 0)
+ tp.space = (tfmp.space or tfmp[2] or 0)*hdelta
+ tp.space_stretch = (tfmp.space_stretch or tfmp[3] or 0)*hdelta
+ tp.space_shrink = (tfmp.space_shrink or tfmp[4] or 0)*hdelta
+ tp.x_height = (tfmp.x_height or tfmp[5] or 0)*vdelta
+ tp.quad = (tfmp.quad or tfmp[6] or 0)*hdelta
+ tp.extra_space = (tfmp.extra_space or tfmp[7] or 0)*hdelta
+ local protrusionfactor = (tp.quad ~= 0 and 1000/tp.quad) or 0
+ local tc = t.characters
+ local characters = tfmtable.characters
+ local nameneeded = not tfmtable.shared.otfdata --hack
+ local changed = tfmtable.changed or { } -- for base mode
+ local ischanged = changed and next(changed)
+ local indices = tfmtable.indices
+ local luatex = tfmtable.luatex
+ local tounicode = luatex and luatex.tounicode
+ local defaultwidth = luatex and luatex.defaultwidth or 0
+ local defaultheight = luatex and luatex.defaultheight or 0
+ local defaultdepth = luatex and luatex.defaultdepth or 0
+ -- experimental, sharing kerns (unscaled and scaled) saves memory
+ -- local sharedkerns, basekerns = tfm.check_base_kerns(tfmtable)
+ -- loop over descriptions (afm and otf have descriptions, tfm not)
+ -- there is no need (yet) to assign a value to chr.tonunicode
+ local scaledwidth = defaultwidth * hdelta
+ local scaledheight = defaultheight * vdelta
+ local scaleddepth = defaultdepth * vdelta
+ local stackmath = tfmtable.ignore_stack_math ~= true
+ local private = fonts.private
+ local sharedkerns = { }
+ for k,v in next, characters do
+ local chr, description, index
+ if ischanged then
+ -- basemode hack
+ local c = changed[k]
+ if c then
+ description = descriptions[c] or v
+ v = characters[c] or v
+ index = (indices and indices[c]) or c
+ else
+ description = descriptions[k] or v
+ index = (indices and indices[k]) or k
+ end
+ else
+ description = descriptions[k] or v
+ index = (indices and indices[k]) or k
+ end
+ local width = description.width
+ local height = description.height
+ local depth = description.depth
+ if width then width = hdelta*width else width = scaledwidth end
+ if height then height = vdelta*height else height = scaledheight end
+ -- if depth then depth = vdelta*depth else depth = scaleddepth end
+ if depth and depth ~= 0 then
+ depth = delta*depth
+ if nameneeded then
+ chr = {
+ name = description.name,
+ index = index,
+ height = height,
+ depth = depth,
+ width = width,
+ }
+ else
+ chr = {
+ index = index,
+ height = height,
+ depth = depth,
+ width = width,
+ }
+ end
+ else
+ -- this saves a little bit of memory time and memory, esp for big cjk fonts
+ if nameneeded then
+ chr = {
+ name = description.name,
+ index = index,
+ height = height,
+ width = width,
+ }
+ else
+ chr = {
+ index = index,
+ height = height,
+ width = width,
+ }
+ end
+ end
+ -- if trace_scaling then
+ -- logs.report("define font","t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or k,description.index,description.name or '-',description.class or '-')
+ -- end
+ if tounicode then
+ local tu = tounicode[index] -- nb: index!
+ if tu then
+ chr.tounicode = tu
+ end
+ end
+ if hasquality then
+ -- we could move these calculations elsewhere (saves calculations)
+ local ve = v.expansion_factor
+ if ve then
+ chr.expansion_factor = ve*1000 -- expansionfactor, hm, can happen elsewhere
+ end
+ local vl = v.left_protruding
+ if vl then
+ chr.left_protruding = protrusionfactor*width*vl
+ end
+ local vr = v.right_protruding
+ if vr then
+ chr.right_protruding = protrusionfactor*width*vr
+ end
+ end
+ -- todo: hasitalic
+ if hasitalic then
+ local vi = description.italic or v.italic
+ if vi and vi ~= 0 then
+ chr.italic = vi*hdelta
+ end
+ end
+ -- to be tested
+ if hasmath then
+ -- todo, just operate on descriptions.math
+ local vn = v.next
+ if vn then
+ chr.next = vn
+ else
+ local vv = v.vert_variants
+ if vv then
+ local t = { }
+ for i=1,#vv do
+ local vvi = vv[i]
+ t[i] = {
+ ["start"] = (vvi["start"] or 0)*vdelta,
+ ["end"] = (vvi["end"] or 0)*vdelta,
+ ["advance"] = (vvi["advance"] or 0)*vdelta,
+ ["extender"] = vvi["extender"],
+ ["glyph"] = vvi["glyph"],
+ }
+ end
+ chr.vert_variants = t
+ --~ local ic = v.vert_italic_correction
+ --~ if ic then
+ --~ chr.italic = ic * hdelta
+ --~ print(format("0x%05X -> %s",k,chr.italic))
+ --~ end
+ else
+ local hv = v.horiz_variants
+ if hv then
+ local t = { }
+ for i=1,#hv do
+ local hvi = hv[i]
+ t[i] = {
+ ["start"] = (hvi["start"] or 0)*hdelta,
+ ["end"] = (hvi["end"] or 0)*hdelta,
+ ["advance"] = (hvi["advance"] or 0)*hdelta,
+ ["extender"] = hvi["extender"],
+ ["glyph"] = hvi["glyph"],
+ }
+ end
+ chr.horiz_variants = t
+ end
+ end
+ end
+ local vt = description.top_accent
+ if vt then
+ chr.top_accent = vdelta*vt
+ end
+ if stackmath then
+ local mk = v.mathkerns
+ if mk then
+ local kerns = { }
+ local v = mk.top_right if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.top_right = k end
+ local v = mk.top_left if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.top_left = k end
+ local v = mk.bottom_left if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.bottom_left = k end
+ local v = mk.bottom_right if v then local k = { } for i=1,#v do local vi = v[i]
+ k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
+ end kerns.bottom_right = k end
+ chr.mathkern = kerns -- singular
+ end
+ end
+ end
+ if not nodemode then
+ local vk = v.kerns
+ if vk then
+ --~ if sharedkerns then
+ --~ local base = basekerns[vk] -- hashed by table id, not content
+ --~ if not base then
+ --~ base = {}
+ --~ for k,v in next, vk do base[k] = v*hdelta end
+ --~ basekerns[vk] = base
+ --~ end
+ --~ chr.kerns = base
+ --~ else
+ --~ local tt = {}
+ --~ for k,v in next, vk do tt[k] = v*hdelta end
+ --~ chr.kerns = tt
+ --~ end
+ local s = sharedkerns[vk]
+ if not s then
+ s = { }
+ for k,v in next, vk do s[k] = v*hdelta end
+ sharedkerns[vk] = s
+ end
+ chr.kerns = s
+ end
+ local vl = v.ligatures
+ if vl then
+ if true then
+ chr.ligatures = vl -- shared
+ else
+ local tt = { }
+ for i,l in next, vl do
+ tt[i] = l
+ end
+ chr.ligatures = tt
+ end
+ end
+ end
+ if isvirtual then
+ local vc = v.commands
+ if vc then
+ -- we assume non scaled commands here
+ -- tricky .. we need to scale pseudo math glyphs too
+ -- which is why we deal with rules too
+ local ok = false
+ for i=1,#vc do
+ local key = vc[i][1]
+ if key == "right" or key == "down" then
+ ok = true
+ break
+ end
+ end
+ if ok then
+ local tt = { }
+ for i=1,#vc do
+ local ivc = vc[i]
+ local key = ivc[1]
+ if key == "right" then
+ tt[#tt+1] = { key, ivc[2]*hdelta }
+ elseif key == "down" then
+ tt[#tt+1] = { key, ivc[2]*vdelta }
+ elseif key == "rule" then
+ tt[#tt+1] = { key, ivc[2]*vdelta, ivc[3]*hdelta }
+ else -- not comment
+ tt[#tt+1] = ivc -- shared since in cache and untouched
+ end
+ end
+ chr.commands = tt
+ else
+ chr.commands = vc
+ end
+ end
+ end
+ tc[k] = chr
+ end
+ -- t.encodingbytes, t.filename, t.fullname, t.name: elsewhere
+ t.size = scaledpoints
+ t.factor = delta
+ t.hfactor = hdelta
+ t.vfactor = vdelta
+ if t.fonts then
+ t.fonts = table.fastcopy(t.fonts) -- maybe we virtualize more afterwards
+ end
+ if hasmath then
+ -- mathematics.extras.copy(t) -- can be done elsewhere if needed
+ local ma = tfm.mathactions
+ for i=1,#ma do
+ ma[i](t,tfmtable,delta,hdelta,vdelta) -- what delta?
+ end
+ end
+ -- needed for \high cum suis
+ local tpx = tp.x_height
+ if hasmath then
+ if not tp[13] then tp[13] = .86*tpx end -- mathsupdisplay
+ if not tp[14] then tp[14] = .86*tpx end -- mathsupnormal
+ if not tp[15] then tp[15] = .86*tpx end -- mathsupcramped
+ if not tp[16] then tp[16] = .48*tpx end -- mathsubnormal
+ if not tp[17] then tp[17] = .48*tpx end -- mathsubcombined
+ if not tp[22] then tp[22] = 0 end -- mathaxisheight
+ if t.MathConstants then t.MathConstants.AccentBaseHeight = nil end -- safeguard
+ end
+ t.tounicode = 1
+ t.cidinfo = tfmtable.cidinfo
+ -- we have t.name=metricfile and t.fullname=RealName and t.filename=diskfilename
+ -- when collapsing fonts, luatex looks as both t.name and t.fullname as ttc files
+ -- can have multiple subfonts
+ if hasmath then
+ if trace_defining then
+ logs.report("define font","math enabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename")
+ end
+ else
+ if trace_defining then
+ logs.report("define font","math disabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename")
+ end
+ t.nomath, t.MathConstants = true, nil
+ end
+ if not t.psname then
+ -- name used in pdf file as well as for selecting subfont in ttc/dfont
+ t.psname = t.fontname or (t.fullname and fonts.names.cleanname(t.fullname))
+ end
+ if trace_defining then
+ logs.report("define font","used for accesing subfont: '%s'",t.psname or "nopsname")
+ logs.report("define font","used for subsetting: '%s'",t.fontname or "nofontname")
+ end
+--~ print(t.fontname,table.serialize(t.MathConstants))
+ return t, delta
+end
+
+--[[ldx--
+
The reason why the scaler is split, is that for a while we experimented
+with a helper function. However, in practice the calls are too slow to
+make this profitable and the based variant was just faster. A days
+wasted day but an experience richer.
+--ldx]]--
+
+tfm.auto_cleanup = true
+
+local lastfont = nil
+
+-- we can get rid of the tfm instance when we have fast access to the
+-- scaled character dimensions at the tex end, e.g. a fontobject.width
+--
+-- flushing the kern and ligature tables from memory saves a lot (only
+-- base mode) but it complicates vf building where the new characters
+-- demand this data .. solution: functions that access them
+
+function tfm.cleanup_table(tfmdata) -- we need a cleanup callback, now we miss the last one
+ if tfm.auto_cleanup then -- ok, we can hook this into everyshipout or so ... todo
+ if tfmdata.type == 'virtual' or tfmdata.virtualized then
+ for k, v in next, tfmdata.characters do
+ if v.commands then v.commands = nil end
+ -- if v.kerns then v.kerns = nil end
+ end
+ else
+ -- for k, v in next, tfmdata.characters do
+ -- if v.kerns then v.kerns = nil end
+ -- end
+ end
+ end
+end
+
+function tfm.cleanup(tfmdata) -- we need a cleanup callback, now we miss the last one
+end
+
+function tfm.scale(tfmtable, scaledpoints, relativeid)
+ local t, factor = tfm.do_scale(tfmtable, scaledpoints, relativeid)
+ t.factor = factor
+ t.ascender = factor*(tfmtable.ascender or 0)
+ t.descender = factor*(tfmtable.descender or 0)
+ t.shared = tfmtable.shared or { }
+ t.unique = table.fastcopy(tfmtable.unique or {})
+--~ print("scaling", t.name, t.factor) -- , tfm.hash_features(tfmtable.specification))
+ tfm.cleanup(t)
+ return t
+end
+
+--[[ldx--
+
Analyzers run per script and/or language and are needed in order to
+process features right.
+--ldx]]--
+
+fonts.analyzers = fonts.analyzers or { }
+fonts.analyzers.aux = fonts.analyzers.aux or { }
+fonts.analyzers.methods = fonts.analyzers.methods or { }
+fonts.analyzers.initializers = fonts.analyzers.initializers or { }
+
+-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
+-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze
+
+-- an example analyzer (should move to font-ota.lua)
+
+local state = attributes.private('state')
+
+function fonts.analyzers.aux.setstate(head,font)
+ local tfmdata = fontdata[font]
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean
+ while current do
+ local id = current.id
+ if id == glyph and current.font == font then
+ local d = descriptions[current.char]
+ if d then
+ if d.class == "mark" then
+ done = true
+ set_attribute(current,state,5) -- mark
+ elseif n == 0 then
+ first, last, n = current, current, 1
+ set_attribute(current,state,1) -- init
+ else
+ last, n = current, n+1
+ set_attribute(current,state,2) -- medi
+ end
+ else -- finish
+ if first and first == last then
+ set_attribute(last,state,4) -- isol
+ elseif last then
+ set_attribute(last,state,3) -- fina
+ end
+ first, last, n = nil, nil, 0
+ end
+ elseif id == disc then
+ -- always in the middle
+ set_attribute(current,state,2) -- midi
+ last = current
+ else -- finish
+ if first and first == last then
+ set_attribute(last,state,4) -- isol
+ elseif last then
+ set_attribute(last,state,3) -- fina
+ end
+ first, last, n = nil, nil, 0
+ end
+ current = current.next
+ end
+ if first and first == last then
+ set_attribute(last,state,4) -- isol
+ elseif last then
+ set_attribute(last,state,3) -- fina
+ end
+ return head, done
+end
+
+function tfm.replacements(tfm,value)
+ -- tfm.characters[0x0022] = table.fastcopy(tfm.characters[0x201D])
+ -- tfm.characters[0x0027] = table.fastcopy(tfm.characters[0x2019])
+ -- tfm.characters[0x0060] = table.fastcopy(tfm.characters[0x2018])
+ -- tfm.characters[0x0022] = tfm.characters[0x201D]
+ tfm.characters[0x0027] = tfm.characters[0x2019]
+ -- tfm.characters[0x0060] = tfm.characters[0x2018]
+end
+
+-- checking
+
+function tfm.checked_filename(metadata,whatever)
+ local foundfilename = metadata.foundfilename
+ if not foundfilename then
+ local askedfilename = metadata.filename or ""
+ if askedfilename ~= "" then
+ foundfilename = resolvers.findbinfile(askedfilename,"") or ""
+ if foundfilename == "" then
+ logs.report("fonts","source file '%s' is not found",askedfilename)
+ foundfilename = resolvers.findbinfile(file.basename(askedfilename),"") or ""
+ if foundfilename ~= "" then
+ logs.report("fonts","using source file '%s' (cache mismatch)",foundfilename)
+ end
+ end
+ elseif whatever then
+ logs.report("fonts","no source file for '%s'",whatever)
+ foundfilename = ""
+ end
+ metadata.foundfilename = foundfilename
+ -- logs.report("fonts","using source file '%s'",foundfilename)
+ end
+ return foundfilename
+end
+
+-- status info
+
+statistics.register("fonts load time", function()
+ return statistics.elapsedseconds(fonts)
+end)
diff --git a/tex/context/base/font-tra.mkiv b/tex/context/base/font-tra.mkiv
new file mode 100644
index 000000000..e47c8c49d
--- /dev/null
+++ b/tex/context/base/font-tra.mkiv
@@ -0,0 +1,113 @@
+%D \module
+%D [ file=font-tra,
+%D version=2009.01.02, % or so
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Tracing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+%D \macros
+%D {doiffontpresentelse}
+%D
+%D \starttyping
+%D \doiffontpresentelse{texnansi-lmr10}{YES}{NO}
+%D \doiffontpresentelse{adam-lindsay-modern-serif}{YES}{NO}
+%D \stoptyping
+
+\def\doiffontpresentelse#1{\ctxlua{commands.doifelse(fonts.names.exists("#1"))}}
+
+% experimental, maybe this becomes a module
+
+\newbox\otfcollector
+
+\unexpanded\def\startotfcollecting{\ctxlua{nodes.tracers.steppers.start()}}
+\unexpanded\def\stopotfcollecting {\ctxlua{nodes.tracers.steppers.stop()}}
+\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}}
+
+% Rather experimental:
+%
+% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{الضَّرَّ} \page
+% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{لِلّٰهِ} \page
+
+\def\showotfstepglyphs#1%
+ {\ctxlua{nodes.tracers.steppers.glyphs(\number\otfcollector,#1)}%
+ \unhbox\otfcollector}
+
+\def\otfstepcharcommand#1#2% font char
+ {\removeunwantedspaces
+ \hskip.5em plus .125em\relax
+ U+\hexnumber{#2}:\ruledhbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}%
+ \hskip.5em plus .125em\relax}
+
+\def\otfstepmessagecommand#1#2%
+ {\begingroup
+ \tttf\language\minusone
+ \veryraggedright
+ \hangindent1em
+ \hangafter\plusone
+ \dontleavehmode\hbox{\detokenize{#1}}\removeunwantedspaces
+ \doifsomething{#2}{\break\detokenize{#2}}\endgraf
+ \endgroup
+ \blank}
+
+\def\showotfstepchars#1%
+ {\ctxlua{nodes.tracers.steppers.codes(#1,\!!bs\detokenize{\otfstepcharcommand}\!!es)}}
+
+\def\showotfstepmessages#1%
+ {\ctxlua{nodes.tracers.steppers.messages(#1,\!!bs\detokenize{\otfstepmessagecommand}\!!es,true)}}
+
+\def\showotfstepfeatures
+ {\ctxlua{nodes.tracers.steppers.features()}}
+
+\def\showotfsteps
+ {\dontleavehmode\bgroup\tttf \language\minusone features: \showotfstepfeatures\egroup
+ \blank
+ \dontleavehmode\bgroup\tttf result:\egroup
+ \blank
+ \startlinecorrection
+ \ruledhbox\bgroup\box\otfcompositionbox\egroup
+ \stoplinecorrection
+ \dorecurse{\ctxlua{nodes.tracers.steppers.nofsteps()}}
+ {\blank
+ \showotfstepmessages\recurselevel
+ \blank
+ \startlinecorrection
+ \dontleavehmode\bgroup\resetallattributes\pardir TLT\textdir TLT\relax\tttf\recurselevel: \showotfstepchars\recurselevel\egroup
+ \stoplinecorrection
+ \blank
+ \startlinecorrection
+ \ruledhbox % can be mode
+ \bgroup\resetallattributes\showotfstepglyphs\recurselevel\egroup % reset is new, we don't want additional processing
+ \stoplinecorrection
+ \blank}}
+
+\unexpanded\def\startotfsample
+ {\enabletrackers[*otf.sample]% beware, kind of global
+ \startotfcollecting
+ \begingroup}
+
+\unexpanded\def\stopotfsample
+ {\endgroup
+ \stopotfcollecting
+ \disabletrackers[*otf.sample]% beware, kind of global: otf.sample
+ \showotfsteps
+ \resetotfcollecting}
+
+\newbox\otfcompositionbox
+
+\def\showotfcomposition#1#2#3% {font*features at size}, rl=-1, text
+ {\begingroup
+ \setupcolors[\c!state=\v!start]% can be option
+ \startotfsample
+ \global\setbox\otfcompositionbox\hbox{\definedfont[#1]\ifnum#2<0 \textdir TRT\else\ifnum#2>0 \textdir TLT\fi\fi\relax#3}%
+ \stopotfsample
+ \endgroup}
+
+\protect \endinput
diff --git a/tex/context/base/font-uni.mkii b/tex/context/base/font-uni.mkii
new file mode 100644
index 000000000..02ab6ce2c
--- /dev/null
+++ b/tex/context/base/font-uni.mkii
@@ -0,0 +1,444 @@
+%D \module
+%D [ file=font-uni,
+%D version=1999.10.10,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=\UNICODE,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Unicode}
+
+%D In \XETEX, unicode support is straightforward, so we
+%D simply output a \type {\char} with a 16||bit number.
+
+\ifnum\texengine=\xetexengine
+ \unexpanded\def\uchar#1#2{\char\numexpr#2+#1*\pluscclvi\relax}
+ \let\uc\uchar
+ \expandafter \endinput
+\fi
+
+%D Now comes the more traditional 8 bit \TEX\ hackery.
+
+%D I wrote this module when Wang Lei asked me how to use
+%D Chinese in \CONTEXT. From the samples he sent me, I deduced
+%D that some mixture of one and two byte encoding was used,
+%D which he confirmed. Since \TEX\ normally does not use the
+%D characters $>127$, so as long as the two byte characters
+%D have a first character with code $>127$, we can use active
+%D characters to handle them. In an optimistic mood, I called
+%D this module the \UNICODE\ font module. In the module that
+%D handles Chinese, we will see that some more interpretation
+%D is involved, which is why the macros handling those
+%D characters look ahead.
+
+\unprotect
+
+%D \macros
+%D {handleunicodeflowglyph, uchar,
+%D handleunicodeglyph, insertunicodeglyph,
+%D unicodeposition, unicodeone, unicodetwo}
+%D
+%D For the moment \UNICODE\ support is rather primitive but
+%D nevertheless effective. The reference to \UNICODE\ is not
+%D entirely correct, since in many cases one will use \quote
+%D {older} mappings, but in principle, \UNICODE\ can be
+%D supported.
+%D
+%D We expect each character to come as two eight bit
+%D characters. Those doubles are handled by making all
+%D characters in the range $>127$ active, so that they can
+%D pick up the next one, and act upon both their values.
+%D Internally only numbers are used. A first implementation
+%D simply internally prefixed the second part of the \UNICODE\
+%D pair with \type {\string} or \type {\char}, but this was
+%D not that handy when it came to testing those values.
+%D Because in principle we are dealing with an encoding, the
+%D making active is handled in \type {enco-uni}.
+%D
+%D There are two commands to handle unicode characters:
+%D
+%D \starttyping
+%D \handleunicodeflowglyph{number}{character}
+%D \uchar{number}{number}
+%D \stoptyping
+%D
+%D The first one can be assigned to an active character, the
+%D second one can be used to directly access a glyph. Both
+%D command call \type {\handleunicodeglyph} that in turn
+%D calls \type {\insertunicodeglyph}. Both can be overruled
+%D in specialized modules. The low level command \type
+%D {\unicodeglyph} can best be left untouched, which is not
+%D so much a problem because there is a hook into this macro:
+%D \type {\unicodecharcommand}.
+%D
+%D In most cases one will redefine \type {\handleunicodeglyph}
+%D in such a way that it identifies special situations first,
+%D takes some actions next, calls \type {\insertunicodeglyph},
+%D if needed with \type {\unicodecharcommand} changed, and
+%D finally does some finishing:
+%D
+%D \starttyping
+%D \def\handleunicodeglyph
+%D {take actions based on \unicodeone-two-position cq. \nextutoken
+%D redefine \unicodecharcommand if needed
+%D expand \insertunicodeglyph
+%D take some final actions}
+%D \stoptyping
+
+\newcount\unicodeposition
+
+%D The multistep approach is needed to pick up the second
+%D token, since this token can have any value and any
+%D catcode.
+
+% the \relax trick prevents eating up the space (needed for
+% korean
+
+\def\handleunicodeflowglyph#1#2%
+ {\begingroup
+ \edef\unicodeone{#1}%
+ \@EA\afterassignment\@EA\dohandleunicodeflowglyph % two redundant ea's
+ \@EA\chardef\@EA\nexttoken\@EA`\string#2\relax}
+
+\def\dohandleunicodeflowglyph\relax
+ {\futurelet\nextutoken\dodohandleunicodeflowglyph}
+
+\def\dodohandleunicodeflowglyph % todo tex (or maybe no longer)
+ {\edef\unicodetwo{\the\nexttoken}%
+ \unicodeposition\numexpr\unicodeone*256+\unicodetwo\relax
+ \handleunicodeglyph
+ \endgroup}
+
+\unexpanded\def\uchar#1#2% use as standalone glyph
+ {\begingroup
+ \edef\unicodeone{#1}%
+ \edef\unicodetwo{#2}%
+ \unicodeposition\numexpr\unicodeone*256+\unicodetwo\relax
+ \handleunicodeglyph
+ \endgroup}
+
+\let\nextutoken\relax
+
+\unexpanded\def\lookaheaduchar#1#2%
+ {\def\dolookaheaduchar{\uchar{#1}{#2}\let\nextutoken\relax}%
+ \futurelet\nextutoken\dolookaheaduchar}
+
+\def\dohandleucflowglyph
+ {\unicodeposition\numexpr\unicodeone*256+\unicodetwo\relax
+ \handleunicodeglyph
+ \endgroup}
+
+\unexpanded\def\uc#1#2% used in tricky situations
+ {\begingroup
+ \edef\unicodeone{#1}%
+ \edef\unicodetwo{#2}%
+ \futurelet\nextutoken\dohandleucflowglyph}
+
+\def\insertunicodeglyph
+ {\unicodeglyph\unicodeone\unicodetwo}
+
+\let\handleunicodeglyph\insertunicodeglyph
+
+%D One can use the \type {\unicodeposition} in the macros
+%D that handle pre and post material.
+
+%D \macros
+%D {unicodestyle, unicodecharcommand}
+%D
+%D Each character pair will become one glyph. Because \TEX\
+%D cannot handle fonts with more that 256 characters, we use
+%D \TFM\ files for each range. The first character of the pair
+%D is appended to the name of a font, and the second is used to
+%D access the glyph in that font. This means that a particular
+%D font is split up in subfonts with names in the range:
+%D
+%D \starttyping
+%D 80 ... ff
+%D \stoptyping
+%D
+%D The \type {} as well as the composed name are
+%D mapped ones. The next macros take care of this mapping.
+%D Let us assume that the next mapping has taken place,
+%D
+%D \starttyping
+%D \definefontsynonym [UnicodeRegular] [gbsong]
+%D \stoptyping
+%D
+%D Let us also assume that we are dealing with the range \type
+%D {b1}. Given that a font name results from:
+%D
+%D \starttyping
+%D \truefontname{\truefontname{UnicodeRegular}b1}
+%D \stoptyping
+%D
+%D we get \type {gbsongb1}. The outer \type {\truefontname}
+%D takes care of additional mapping, so when we say:
+%D
+%D \starttyping
+%D \definefontsynonym [gbsongb1] [gbsong-b1]
+%D \stoptyping
+%D
+%D the filename used will be \type {gbsong-b1}. From the next
+%D definition it will be clear that other fontshapes are also
+%D supported. The prefix \type {Unicode} is mapped!
+%D
+%D The command \type {\unicodecharcommand} can be used to
+%D handle special cases. At that moment \type {1em} is known.
+
+\def\unicodestyle
+ {\truefontname\s!Unicode\fontstylesuffix}
+
+\let\unicodecharcommand\firstofoneargument
+
+\unexpanded\def\unicodeglyph#1#2% watch the double mapping
+ {\begingroup
+ \getvalue{@@\currentucharmapping\strippedcsname\uchar}{#1}{#2}% map to a to hex font range
+ \bodyfontsize\unicodescale\bodyfontsize
+ % readable:
+ % \doifelsefontsynonym{\unicodestyle\unicodeone}
+ % {\font\unicodefont=\truefontname{\unicodestyle\unicodeone}
+ % at \currentfontscale\bodyfontsize}
+ % {\font\unicodefont=\truefontname{\truefontname\unicodestyle\unicodeone}
+ % at \currentfontscale\bodyfontsize}%
+ % unreadable but more efficient:
+ \font\unicodefont=\truefontname{\doifelsefontsynonym{\unicodestyle
+ \unicodeone}\empty\truefontname\unicodestyle\unicodeone}
+ at \currentfontscale\bodyfontsize
+ \unicodestrut % off by default
+ \unicodefont\unicodecharcommand{\char\unicodetwo\relax}%
+ \endgroup}
+
+%D This handler is used by default, for instance in:
+%D
+%D \starttyping
+%D \defineunicodefont [MySwitch] [MyFont] % [strut=no,command=\insertunicodeglyph]
+%D
+%D \definefontsynonym [MyFontRegular40] [Sans]
+%D \definefontsynonym [MyFontBold40] [SansBold]
+%D
+%D {\MySwitch \uchar{"40}{`a}}
+%D {\MySwitch \bf \uchar{"40}{`a}}
+%D \stoptyping
+%D
+%D \starttyping
+%D \definefontsynonym [MyFontRegular] [Sans]
+%D \definefontsynonym [MyFontBold] [SansBold]
+%D \stoptyping
+%D
+%D Is also possible, but in that case the number is appended to the raw font
+%D name!
+
+%D \macros
+%D {currentucharmapping,defineucharmapping}
+%D
+%D A (plane,char) pair can be remapped using a uchar mapping
+%D function. The default mapping is to convert the plane to a
+%D lowercase hexadecimal number, and leave the number
+%D untouched. The current remapping is kept in a macro.
+
+\let\currentucharmapping\s!default
+
+\def\defineucharmapping#1%
+ {\setvalue{@@#1\strippedcsname\uchar}}
+
+\defineucharmapping{\s!default}#1#2%
+ {\edef\unicodeone{\lchexnumbers{#1}}\edef\unicodetwo{#2}}
+
+%D An example of a remapping is the following:
+%D
+%D \starttyping
+%D \defineucharmapping{GBK}#1#2%
+%D {\unicodeposition=#1
+%D \advance\unicodeposition -129
+%D \multiply\unicodeposition 190
+%D \advance\unicodeposition #2
+%D \advance\unicodeposition-\ifnum#2>127 65\else64\fi
+%D \dorepositionunicode}
+%D \stoptyping
+%D
+%D This maps the GBK vector onto a compact GBK one. The
+%D auxiliary macro is defined here as a goody.
+
+\def\dorepositionunicode
+ {\dosetdivision\unicodeposition{256}\scratchcounter
+ \advance\scratchcounter \plusone
+ \edef\unicodeone{\ifnum\scratchcounter<10 0\fi\the\scratchcounter}%
+ \dosetmodulo\unicodeposition{256}\scratchcounter
+ \edef\unicodetwo{\the\scratchcounter}}
+
+%D \macros
+%D {setunicodestrut, setunicodescale, nextutoken,
+%D handleunicodeglyph, insertunicodeglyph}
+%D
+%D A careful analysis of the previous macros, learns that the
+%D process of mapping comes down to:
+%D
+%D \startitemize[packed,n]
+%D \item taking care of preceding material (and spacing)
+%D \item defining the font at \type {\currentfontscale} $\times$
+%D \type {\unicodescale} $\times$ \type {\bodyfontsize}
+%D \item inserting a \type {\unicodestrut}
+%D \item inserting the character (glyph)
+%D \item executing some actions afterwards
+%D \stopitemize
+%D
+%D The actions before and after placing the glyph, is up to
+%D the user supplied handler. This handler (\type
+%D {\handleunicodeglpyh}) must, at a certain moment, insert
+%D the glyph using \type {\insertunicodeglyph}
+
+\def\setunicodescale#1%
+ {\def\unicodescale{#1}}
+
+\def\dosetunicodestrut#1#2% height depth
+ {\def\unicodestrut
+ {\vrule
+ \!!width \zeropoint
+ \!!height#1\strutht
+ \!!depth #2\strutdp
+ \relax}}
+
+\def\setunicodestrut#1#2% height depth
+ {\ifdim#1\strutht>\zeropoint
+ \dosetunicodestrut{#1}{#2}%
+ \else\ifdim#1\strutdp>\zeropoint
+ \dosetunicodestrut{#1}{#2}%
+ \else
+ \let\unicodestrut\empty
+ \fi\fi}
+
+\def\resetunicodestrut
+ {\let\unicodestrut\empty}
+
+%D The additional scaling and strut default to:
+
+\setunicodescale{1}
+\setunicodestrut{1}{1}
+
+%D But better is not to have a strut added by default:
+
+\resetunicodestrut
+
+%D The actual code for the additional actions as well as
+%D specific spacing is handled outside these routines. The
+%D character after the two that are under treatment is
+%D available in \type {\nextutoken}.
+
+%D \macros
+%D {defineunicodefont, setupunicodefont}
+%D
+%D Apart from this rather low level implementation, we also
+%D provide a more user friendly alternative. Given that one
+%D has defined:
+%D
+%D \starttyping
+%D \defineunicodefont
+%D [SimChi] [SimplifiedChinese]
+%D [\c!scale=0.85,
+%D \c!height=1.25,
+%D \c!depth=1.00,
+%D \c!interlinespaceinterlinie=yes,
+%D \c!conversion=\chinesenumber,
+%D \c!command=\handlechineseunicodeglyph]
+%D \stoptyping
+%D
+%D Together with:
+%D
+%D \starttyping
+%D \definefontsynonym [SimplifiedChineseRegular] [gbsong]
+%D \definefontsynonym [SimplifiedChineseSlanted] [gbsongsl]
+%D \stoptyping
+%D
+%D we can now switch to Simplified Chinese by saying \type
+%D {SimChi}. Some values can be changed afterwards with
+%D
+%D \starttyping
+%D \setupunicodefont[SimChi][...=...]
+%D \stoptyping
+%D
+%D Specific initializations can be assigned to \type
+%D {commands}.
+
+\def\defineunicodefont
+ {\dotripleempty\dodefineunicodefont}
+
+\def\dodefineunicodefont[#1][#2][#3]%
+ {\doifassignmentelse{#3}
+ {\setupunicodefont[#1][#3]}
+ {\doifelsenothing{#3}
+ {\setupunicodefont[#1][#3]}
+ {\copyparameters
+ [\??uc#1][\??uc#3]
+ [\c!height,\c!depth,\c!scale,\c!commands,\c!strut,
+ \c!interlinespace,\c!command,\c!conversion]}}%
+ \doifelsenothing{#2}
+ {\setvalue{#1}{[uc font #1 undefined]}}
+ {\setvalue{\??uc#1\c!file}{#2}%
+ \doifundefined{\??ff#2\s!Bold}
+ {\definefontsynonym[#2\s!Bold] [#2\s!Regular]%
+ \definefontsynonym[#2\s!Slanted] [#2\s!Regular]%
+ \definefontsynonym[#2\s!Italic] [#2\s!Regular]%
+ \definefontsynonym[#2\s!BoldSlanted][#2\s!Slanted]%
+ \definefontsynonym[#2\s!BoldItalic] [#2\s!Italic]}%
+ \unexpanded\setvalue{#1}{\enableunicodefont{#1}}}}
+
+\def\setupunicodefont
+ {\dodoubleempty\dosetupunicodefont}
+
+\def\dosetupunicodefont[#1][#2]% also predefines
+ {\doifundefined{\??uc#1\c!command}
+ {\copyparameters
+ [\??uc#1][\??uc\s!default]
+ [\c!height,\c!depth,\c!scale,\c!commands,\v!strut,
+ \c!interlinespace,\c!command,\c!conversion]}%
+ \getparameters[\??uc#1][#2]}
+
+\def\enableunicodefont#1%
+ {\definefontsynonym[\s!Unicode][\getvalue{\??uc#1\c!file}]%
+ \def\unicodescale {\getvalue{\??uc#1\c!scale}}%
+ \def\unicodeheight {\getvalue{\??uc#1\c!height}}%
+ \def\unicodedepth {\getvalue{\??uc#1\c!depth}}%
+ \def\unicodedigits {\getvalue{\??uc#1\c!conversion}}%
+ \def\handleunicodeglyph {\getvalue{\??uc#1\c!command}}%
+ \doifnot\currentregime{utf}{\enableregime[unicode]}%
+ % the following \relax's are realy needed
+ \doifvalue{\??uc#1\c!interlinespace}\v!yes
+ \setupinterlinespace\relax
+ \doifelsevalue{\??uc#1\c!strut}\v!yes
+ {\setunicodestrut\unicodeheight\unicodedepth}
+ {\resetunicodestrut}%
+ \getvalue{\??uc#1\c!commands}\relax}
+
+%D \macros
+%D {unicodedigits}
+%D
+%D For convenience we also predefine a number conversion
+%D macro:
+
+\let\unicodedigits\number
+
+%D Because we cannot be sure of the pressence of all font
+%D styles, we remap some by default.
+
+\definefontsynonym [\s!Unicode\s!Bold] [\s!Unicode\s!Regular]
+\definefontsynonym [\s!Unicode\s!Slanted] [\s!Unicode\s!Regular]
+\definefontsynonym [\s!Unicode\s!Italic] [\s!Unicode\s!Regular]
+\definefontsynonym [\s!Unicode\s!BoldSlanted] [\s!Unicode\s!Slanted]
+\definefontsynonym [\s!Unicode\s!BoldItalic] [\s!Unicode\s!Italic]
+
+\setupunicodefont
+ [\s!default]
+ [\c!height=1,
+ \c!depth=1,
+ \c!scale=1,
+ \c!strut=\v!no,
+ \c!interlinespace=\v!no,
+ \c!command=\insertunicodeglyph,
+ \c!conversion=\number]
+
+\protect \endinput
diff --git a/tex/context/base/font-uni.mkiv b/tex/context/base/font-uni.mkiv
new file mode 100644
index 000000000..40ab75ed6
--- /dev/null
+++ b/tex/context/base/font-uni.mkiv
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=font-uni,
+%D version=2008.11.03, % 1999.10.10,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=\UNICODE,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Unicode}
+
+%D In \MKIV\ we only provide the \type {\uchar} macro and
+%D implement it as just an \UTF\ converter. We expand it so
+%D best not use not use it for active characters.
+
+\unprotect
+
+\def\uchar#1#2{\ctxlua{commands.uchar(\number#1,\number#2)}}
+
+\let\uc\uchar
+
+\protect \endinput
diff --git a/tex/context/base/font-unk.mkii b/tex/context/base/font-unk.mkii
new file mode 100644
index 000000000..30f824781
--- /dev/null
+++ b/tex/context/base/font-unk.mkii
@@ -0,0 +1,187 @@
+%D \module
+%D [ file=font-unk,
+%D version=1998.09.10,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Unknown Defaults,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is rather important, because it enables us to
+%D define and call for not yet defined fonts in a way
+%D completely independant of real font names. First we map
+%D some meaningful names onto unknown filenames.
+
+\unprotect
+
+\definefontsynonym [Serif] [unknown]
+\definefontsynonym [SerifBold] [unknown]
+\definefontsynonym [SerifItalic] [unknown]
+\definefontsynonym [SerifSlanted] [unknown]
+\definefontsynonym [SerifBoldItalic] [unknown]
+\definefontsynonym [SerifBoldSlanted] [unknown]
+\definefontsynonym [SerifCaps] [unknown]
+
+\definefontsynonym [Sans] [unknown]
+\definefontsynonym [SansBold] [unknown]
+\definefontsynonym [SansItalic] [unknown]
+\definefontsynonym [SansSlanted] [unknown]
+\definefontsynonym [SansBoldItalic] [unknown]
+\definefontsynonym [SansBoldSlanted] [unknown]
+\definefontsynonym [SansCaps] [unknown]
+
+\definefontsynonym [Mono] [unknown]
+\definefontsynonym [MonoBold] [unknown]
+\definefontsynonym [MonoItalic] [unknown]
+\definefontsynonym [MonoSlanted] [unknown]
+\definefontsynonym [MonoBoldItalic] [unknown]
+\definefontsynonym [MonoBoldSlanted] [unknown]
+\definefontsynonym [MonoCaps] [unknown]
+
+\definefontsynonym [MathRoman] [unknown]
+\definefontsynonym [MathExtension] [unknown]
+\definefontsynonym [MathItalic] [unknown]
+\definefontsynonym [MathSymbol] [unknown]
+
+\definefontsynonym [MathNoName] [unknown]
+
+\definefontsynonym [MathAlpha] [unknown]
+\definefontsynonym [MathBeta] [unknown]
+\definefontsynonym [MathGamma] [unknown]
+\definefontsynonym [MathDelta] [unknown]
+
+\definefontsynonym [MathRomanBold] [MathRoman]
+\definefontsynonym [MathExtensionBold] [MathExtension]
+\definefontsynonym [MathItalicBold] [MathItalic]
+\definefontsynonym [MathSymbolBold] [MathSymbol]
+\definefontsynonym [MathAlphaBold] [MathAlpha]
+\definefontsynonym [MathBetaBold] [MathBeta]
+\definefontsynonym [MathGammaBold] [MathGamma]
+\definefontsynonym [MathDeltaBold] [MathDelta]
+
+\definefontsynonym [Handwriting] [unknown]
+\definefontsynonym [Calligraphic] [unknown]
+
+%D This permit us to define (use) fonts that refer to the default
+%D style (so, Bold may expand to SansBold or SerifBold, depending
+%D on the default style in the typeface).
+
+% \def\setfontsynonym[#1]#2[#3]{\setvalue{\??ff\fontclass#1}{#3}}
+%
+% \setfontsynonym[\s!Normal] [\fontstringD]
+% \setfontsynonym[\s!Bold] [\fontstringD\s!Bold]
+% \setfontsynonym[\s!Italic] [\fontstringD\s!Italic]
+% \setfontsynonym[\s!Slanted] [\fontstringD\s!Slanted]
+% \setfontsynonym[\s!BoldItalic] [\fontstringD\s!BoldItalic]
+% \setfontsynonym[\s!BoldSlanted][\fontstringD\s!BoldSlanted]
+% \setfontsynonym[\s!Caps] [\fontstringD\s!Caps]
+
+\definefontsynonym[\s!Normal] [\noexpand\fontstringD]
+\definefontsynonym[\s!Bold] [\noexpand\fontstringD\noexpand\s!Bold]
+\definefontsynonym[\s!Italic] [\noexpand\fontstringD\noexpand\s!Italic]
+\definefontsynonym[\s!Slanted] [\noexpand\fontstringD\noexpand\s!Slanted]
+\definefontsynonym[\s!BoldItalic] [\noexpand\fontstringD\noexpand\s!BoldItalic]
+\definefontsynonym[\s!BoldSlanted][\noexpand\fontstringD\noexpand\s!BoldSlanted]
+\definefontsynonym[\s!Caps] [\noexpand\fontstringD\noexpand\s!Caps]
+
+%D Also handy:
+
+\definefontsynonym [Regular] [Serif]
+\definefontsynonym [RegularBold] [SerifBold]
+\definefontsynonym [RegularItalic] [SerifItalic]
+\definefontsynonym [RegularSlanted] [SerifSlanted]
+\definefontsynonym [RegularBoldItalic] [SerifBoldItalic]
+\definefontsynonym [RegularBoldSlanted] [SerifBoldSlanted]
+\definefontsynonym [RegularCaps] [SerifCaps]
+
+\definefontsynonym [Support] [Sans]
+\definefontsynonym [SupportBold] [SansBold]
+\definefontsynonym [SupportItalic] [SansItalic]
+\definefontsynonym [SupportSlanted] [SansSlanted]
+\definefontsynonym [SupportBoldItalic] [SansBoldItalic]
+\definefontsynonym [SupportBoldSlanted] [SansBoldSlanted]
+\definefontsynonym [SupportCaps] [SansCaps]
+
+%D Well, not that good an idea:
+
+\definefontsynonym [Roman] [Serif]
+\definefontsynonym [RomanBold] [SerifBold]
+\definefontsynonym [RomanItalic] [SerifItalic]
+\definefontsynonym [RomanSlanted] [SerifSlanted]
+\definefontsynonym [RomanBoldItalic] [SerifBoldItalic]
+\definefontsynonym [RomanBoldSlanted] [SerifBoldSlanted]
+\definefontsynonym [RomanCaps] [SerifCaps]
+
+\definefontsynonym [Type] [Mono]
+\definefontsynonym [TypeBold] [MonoBold]
+\definefontsynonym [TypeItalic] [MonoItalic]
+\definefontsynonym [TypeSlanted] [MonoSlanted]
+\definefontsynonym [TypeBoldItalic] [MonoBoldItalic]
+\definefontsynonym [TypeBoldSlanted] [MonoBoldSlanted]
+\definefontsynonym [TypeCaps] [MonoCaps]
+
+%D Next we define roman, sans and monospaced font sets.
+
+\definebodyfont [default] [rm]
+ [tf=Serif sa 1,
+ bf=SerifBold sa 1,
+ it=SerifItalic sa 1,
+ sl=SerifSlanted sa 1,
+ bi=SerifBoldItalic sa 1,
+ bs=SerifBoldSlanted sa 1,
+ sc=SerifCaps sa 1]
+
+\definebodyfont [default] [ss]
+ [tf=Sans sa 1,
+ bf=SansBold sa 1,
+ it=SansItalic sa 1,
+ sl=SansSlanted sa 1,
+ bi=SansBoldItalic sa 1,
+ bs=SansBoldSlanted sa 1,
+ sc=SansCaps sa 1]
+
+\definebodyfont [default] [tt]
+ [tf=Mono sa 1,
+ bf=MonoBold sa 1,
+ it=MonoItalic sa 1,
+ sl=MonoSlanted sa 1,
+ bi=MonoBoldItalic sa 1,
+ bs=MonoBoldSlanted sa 1,
+ sc=MonoCaps sa 1]
+
+\definebodyfont [default] [mm]
+ [mr=MathRoman mo 1,
+ ex=MathExtension mo 1,
+ mi=MathItalic mo 1,
+ sy=MathSymbol mo 1,
+ nn=MathNoName mo 1,
+ ma=MathAlpha mo 1,
+ mb=MathBeta mo 1,
+ mc=MathGamma mo 1,
+ md=MathDelta mo 1]
+
+\definebodyfont [bfmath] [mm]
+ [mrbf=MathRomanBold mo 1,
+ exbf=MathExtensionBold mo 1,
+ mibf=MathItalicBold mo 1,
+ sybf=MathSymbolBold mo 1,
+ mabf=MathAlphaBold mo 1,
+ mbbf=MathBetaBold mo 1,
+ mcbf=MathGammaBold mo 1,
+ mdbf=MathDeltaBold mo 1]
+
+\definebodyfont [default] [hw]
+ [tf=Handwriting sa 1]
+
+\definebodyfont [default] [cg]
+ [tf=Calligraphy sa 1]
+
+%D These definitions come into action as soon as names are
+%D mapped onto real file names (or names that themselves are
+%D mapped).
+
+\protect \endinput
diff --git a/tex/context/base/font-unk.mkiv b/tex/context/base/font-unk.mkiv
new file mode 100644
index 000000000..bd699ef71
--- /dev/null
+++ b/tex/context/base/font-unk.mkiv
@@ -0,0 +1,162 @@
+%D \module
+%D [ file=font-unk,
+%D version=1998.09.10,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Unknown Defaults,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is rather important, because it enables us to
+%D define and call for not yet defined fonts in a way
+%D completely independant of real font names. First we map
+%D some meaningful names onto unknown filenames.
+
+\unprotect
+
+\definefontsynonym [Serif] [unknown]
+\definefontsynonym [SerifBold] [unknown]
+\definefontsynonym [SerifItalic] [unknown]
+\definefontsynonym [SerifSlanted] [unknown]
+\definefontsynonym [SerifBoldItalic] [unknown]
+\definefontsynonym [SerifBoldSlanted] [unknown]
+\definefontsynonym [SerifCaps] [unknown]
+
+\definefontsynonym [Sans] [unknown]
+\definefontsynonym [SansBold] [unknown]
+\definefontsynonym [SansItalic] [unknown]
+\definefontsynonym [SansSlanted] [unknown]
+\definefontsynonym [SansBoldItalic] [unknown]
+\definefontsynonym [SansBoldSlanted] [unknown]
+\definefontsynonym [SansCaps] [unknown]
+
+\definefontsynonym [Mono] [unknown]
+\definefontsynonym [MonoBold] [unknown]
+\definefontsynonym [MonoItalic] [unknown]
+\definefontsynonym [MonoSlanted] [unknown]
+\definefontsynonym [MonoBoldItalic] [unknown]
+\definefontsynonym [MonoBoldSlanted] [unknown]
+\definefontsynonym [MonoCaps] [unknown]
+
+\definefontsynonym [MathRoman] [unknown]
+\definefontsynonym [MathExtension] [unknown]
+\definefontsynonym [MathItalic] [unknown]
+\definefontsynonym [MathSymbol] [unknown]
+
+\definefontsynonym [MathNoName] [unknown]
+
+\definefontsynonym [MathAlpha] [unknown]
+\definefontsynonym [MathBeta] [unknown]
+\definefontsynonym [MathGamma] [unknown]
+\definefontsynonym [MathDelta] [unknown]
+
+\definefontsynonym [MathRomanBold] [MathRoman] % todo:
+\definefontsynonym [MathExtensionBold] [MathExtension] % [MathRoman]
+\definefontsynonym [MathItalicBold] [MathItalic] % [MathRoman]
+\definefontsynonym [MathSymbolBold] [MathSymbol] % [MathRoman]
+\definefontsynonym [MathAlphaBold] [MathAlpha] % [MathRoman]
+\definefontsynonym [MathBetaBold] [MathBeta] % [MathRoman]
+\definefontsynonym [MathGammaBold] [MathGamma] % [MathRoman]
+\definefontsynonym [MathDeltaBold] [MathDelta] % [MathRoman]
+
+\definefontsynonym [Handwriting] [unknown]
+\definefontsynonym [Calligraphic] [unknown]
+
+%D This permit us to define (use) fonts that refer to the default
+%D style (so, Bold may expand to SansBold or SerifBold, depending
+%D on the default style in the typeface).
+
+\definefontsynonym[\s!Normal] [\noexpand\fontstringD]
+\definefontsynonym[\s!Bold] [\noexpand\fontstringD\noexpand\s!Bold]
+\definefontsynonym[\s!Italic] [\noexpand\fontstringD\noexpand\s!Italic]
+\definefontsynonym[\s!Slanted] [\noexpand\fontstringD\noexpand\s!Slanted]
+\definefontsynonym[\s!BoldItalic] [\noexpand\fontstringD\noexpand\s!BoldItalic]
+\definefontsynonym[\s!BoldSlanted][\noexpand\fontstringD\noexpand\s!BoldSlanted]
+\definefontsynonym[\s!Caps] [\noexpand\fontstringD\noexpand\s!Caps]
+
+%D Also handy:
+
+\definefontsynonym [Regular] [Serif]
+\definefontsynonym [RegularBold] [SerifBold]
+\definefontsynonym [RegularItalic] [SerifItalic]
+\definefontsynonym [RegularSlanted] [SerifSlanted]
+\definefontsynonym [RegularBoldItalic] [SerifBoldItalic]
+\definefontsynonym [RegularBoldSlanted] [SerifBoldSlanted]
+\definefontsynonym [RegularCaps] [SerifCaps]
+
+\definefontsynonym [Support] [Sans]
+\definefontsynonym [SupportBold] [SansBold]
+\definefontsynonym [SupportItalic] [SansItalic]
+\definefontsynonym [SupportSlanted] [SansSlanted]
+\definefontsynonym [SupportBoldItalic] [SansBoldItalic]
+\definefontsynonym [SupportBoldSlanted] [SansBoldSlanted]
+\definefontsynonym [SupportCaps] [SansCaps]
+
+%D Well, not that good an idea:
+
+\definefontsynonym [Roman] [Serif]
+\definefontsynonym [RomanBold] [SerifBold]
+\definefontsynonym [RomanItalic] [SerifItalic]
+\definefontsynonym [RomanSlanted] [SerifSlanted]
+\definefontsynonym [RomanBoldItalic] [SerifBoldItalic]
+\definefontsynonym [RomanBoldSlanted] [SerifBoldSlanted]
+\definefontsynonym [RomanCaps] [SerifCaps]
+
+\definefontsynonym [Type] [Mono]
+\definefontsynonym [TypeBold] [MonoBold]
+\definefontsynonym [TypeItalic] [MonoItalic]
+\definefontsynonym [TypeSlanted] [MonoSlanted]
+\definefontsynonym [TypeBoldItalic] [MonoBoldItalic]
+\definefontsynonym [TypeBoldSlanted] [MonoBoldSlanted]
+\definefontsynonym [TypeCaps] [MonoCaps]
+
+%D Next we define roman, sans and monospaced font sets.
+
+\definebodyfont [default] [rm]
+ [tf=Serif sa 1,
+ bf=SerifBold sa 1,
+ it=SerifItalic sa 1,
+ sl=SerifSlanted sa 1,
+ bi=SerifBoldItalic sa 1,
+ bs=SerifBoldSlanted sa 1,
+ sc=SerifCaps sa 1]
+
+\definebodyfont [default] [ss]
+ [tf=Sans sa 1,
+ bf=SansBold sa 1,
+ it=SansItalic sa 1,
+ sl=SansSlanted sa 1,
+ bi=SansBoldItalic sa 1,
+ bs=SansBoldSlanted sa 1,
+ sc=SansCaps sa 1]
+
+\definebodyfont [default] [tt]
+ [tf=Mono sa 1,
+ bf=MonoBold sa 1,
+ it=MonoItalic sa 1,
+ sl=MonoSlanted sa 1,
+ bi=MonoBoldItalic sa 1,
+ bs=MonoBoldSlanted sa 1,
+ sc=MonoCaps sa 1]
+
+\definebodyfont [default] [mm]
+ [mr=MathRoman mo 1]
+
+\definebodyfont [bfmath] [mm]
+ [mr=MathRomanBold mo 1]
+
+\definebodyfont [default] [hw]
+ [tf=Handwriting sa 1]
+
+\definebodyfont [default] [cg]
+ [tf=Calligraphy sa 1]
+
+%D These definitions come into action as soon as names are
+%D mapped onto real file names (or names that themselves are
+%D mapped).
+
+\protect \endinput
diff --git a/tex/context/base/font-vf.lua b/tex/context/base/font-vf.lua
new file mode 100644
index 000000000..4f99c47b9
--- /dev/null
+++ b/tex/context/base/font-vf.lua
@@ -0,0 +1,213 @@
+if not modules then modules = { } end modules ['font-vf'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
This is very experimental code! Not yet adapted to recent
+changes. This will change.
+--ldx]]--
+
+-- define.methods elsewhere !
+
+fonts = fonts or { }
+fonts.vf = fonts.vf or { }
+
+local vf = fonts.vf
+local tfm = fonts.tfm
+
+fonts.define = fonts.define or { }
+fonts.define.methods = fonts.define.methods or { }
+
+vf.combinations = vf.combinations or { }
+vf.aux = vf.aux or { }
+vf.aux.combine = vf.aux.combine or { }
+
+function fonts.define.methods.install(tag, rules)
+ vf.combinations[tag] = rules
+ fonts.define.methods[tag] = function(specification)
+ return vf.combine(specification,tag)
+ end
+end
+
+function vf.aux.combine.assign(g, name, from, to, start, force)
+ local f, id = vf.aux.combine.load(g,name)
+ if f and id then
+ -- optimize for whole range, then just g = f
+ if not from then from, to = 0, 0xFF00 end
+ if not to then to = from end
+ if not start then start = from end
+ local fc, gc = f.characters, g.characters
+ local fd, gd = f.descriptions, g.descriptions
+ local hn = #g.fonts+1
+ g.fonts[hn] = { id = id } -- no need to be sparse
+ for i=from,to do
+ if fc[i] and (force or not gc[i]) then
+ gc[i] = table.fastcopy(fc[i]) -- can be optimized
+ gc[i].commands = { { 'slot', hn, start } }
+ gd[i] = fd[i]
+ end
+ start = start + 1
+ end
+ if not g.parameters and #g.fonts > 0 then -- share this code !
+ g.parameters = table.fastcopy(f.parameters)
+ g.italicangle = f.italicangle
+ g.ascender = f.ascender
+ g.descender = f.descender
+ g.factor = f.factor -- brrr
+ end
+ end
+end
+
+function vf.aux.combine.process(g,list)
+ if list then
+ for _,v in next, list do
+ (vf.aux.combine.commands[v[1]] or nop)(g,v)
+ end
+ end
+end
+
+function vf.aux.combine.load(g,name)
+ return tfm.read_and_define(name or g.specification.name,g.specification.size)
+end
+
+function vf.aux.combine.names(g,name,force)
+ local f, id = tfm.read_and_define(name,g.specification.size)
+ if f and id then
+ local fc, gc = f.characters, g.characters
+ local fd, gd = f.descriptions, g.descriptions
+ g.fonts[#g.fonts+1] = { id = id } -- no need to be sparse
+ local hn = #g.fonts
+ for k, v in next, fc do
+ if force or not gc[k] then
+ gc[k] = table.fastcopy(v)
+ gc[k].commands = { { 'slot', hn, k } }
+ gd[i] = fd[i]
+ end
+ end
+ if not g.parameters and #g.fonts > 0 then -- share this code !
+ g.parameters = table.fastcopy(f.parameters)
+ g.italicangle = f.italicangle
+ g.ascender = f.ascender
+ g.descender = f.descender
+ g.factor = f.factor -- brrr
+ end
+ end
+end
+
+vf.aux.combine.commands = {
+ ["initialize"] = function(g,v) vf.aux.combine.assign (g,g.name) end,
+ ["include-method"] = function(g,v) vf.aux.combine.process (g,vf.combinations[v[2]]) end, -- name
+ ["copy-parameters"] = function(g,v) vf.aux.combine.parameters(g,v[2]) end, -- name
+ ["copy-range"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[4],v[5],true) end, -- name, from-start, from-end, to-start
+ ["copy-char"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[3],v[4],true) end, -- name, from, to
+ ["fallback-range"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[4],v[5],false) end, -- name, from-start, from-end, to-start
+ ["fallback-char"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[3],v[4],false) end, -- name, from, to
+ ["copy_names"] = function(g,v) vf.aux.combine.names (g,v[2],true) end,
+ ["fallback_names"] = function(g,v) vf.aux.combine.names (g,v[2],false) end,
+}
+
+function vf.combine(specification,tag)
+ local g = {
+ name = specification.name,
+ -- type = 'virtual',
+ virtualized = true,
+ fonts = { },
+ characters = { },
+ descriptions = { },
+ specification = table.fastcopy(specification)
+ }
+ vf.aux.combine.process(g,vf.combinations[tag])
+ return g
+end
+
+vf.aux.combine.commands["feature"] = function(g,v)
+ local key, value = v[2], v[3]
+ if key then
+ if value == nil then
+ value = true
+ end
+ if g.specification and g.specification.features.normal then
+ g.specification.features.normal[key] = value -- otf?
+ end
+ end
+end
+
+-- simple example with features
+
+fonts.define.methods.install(
+ "ligatures", {
+ { "feature", "liga" } ,
+ { "feature", "dlig" } ,
+ { "initialize" } ,
+ }
+)
+
+--~ fonts.define.methods.install (
+--~ "ligatures-x", {
+--~ { "feature", "liga" } ,
+--~ { "feature", "dlig" } ,
+--~ { "initialize" } ,
+--~ { "lineheight" }
+--~ }
+--~ )
+
+--~ fonts.define.methods.install(
+--~ "lmsymbol10", {
+--~ { "fallback_names", "lmsy10.afm" } ,
+--~ { "fallback_names", "msam10.afm" } ,
+--~ { "fallback_names", "msbm10.afm" }
+--~ }
+--~ )
+--~ \font\TestFont=dummy@lmsymbol10 at 24pt
+
+-- docu case
+
+--~ fonts.define.methods.install(
+--~ "weird", {
+--~ { "copy-range", "lmroman10-regular" } ,
+--~ { "copy-char", "lmroman10-regular", 65, 66 } ,
+--~ { "copy-range", "lmsans10-regular", 0x0100, 0x01FF } ,
+--~ { "copy-range", "lmtypewriter10-regular", 0x0200, 0xFF00 } ,
+--~ { "fallback-range", "lmtypewriter10-regular", 0x0000, 0x0200 }
+--~ }
+--~ )
+
+-- demo case -> move to module
+
+fonts.define.methods["demo-1"] = function(specification)
+ local name = specification.name -- symbolic name
+ local size = specification.size -- given size
+ local f, id = tfm.read_and_define('lmroman10-regular',size)
+ if f and id then
+ local capscale, digscale = 0.85, 0.75
+ -- f.name, f.type = name, 'virtual'
+ f.name, f.virtualized = name, true
+ f.fonts = {
+ { id = id },
+ { name = 'lmsans10-regular' , size = size*capscale }, -- forced extra name
+ { name = 'lmtypewriter10-regular', size = size*digscale } -- forced extra name
+ }
+ local i_is_of_category = characters.i_is_of_category
+ local characters, descriptions = f.characters, f.descriptions
+ local red = {'special','pdf: 1 0 0 rg'}
+ local green = {'special','pdf: 0 1 0 rg'}
+ local blue = {'special','pdf: 0 0 1 rg'}
+ local black = {'special','pdf: 0 g'}
+ for u,v in next, characters do
+ if u and i_is_of_category(u,'lu') then
+ v.width = capscale*v.width
+ v.commands = { red, {'slot',2,u}, black }
+ elseif u and i_is_of_category(u,'nd') then
+ v.width = digscale*v.width
+ v.commands = { blue, {'slot',3,u}, black }
+ else
+ v.commands = { green, {'slot',1,u}, black }
+ end
+ end
+ end
+ return f
+end
diff --git a/tex/context/base/font-xtx.lua b/tex/context/base/font-xtx.lua
new file mode 100644
index 000000000..eac75dd29
--- /dev/null
+++ b/tex/context/base/font-xtx.lua
@@ -0,0 +1,122 @@
+if not modules then modules = { } end modules ['font-xtx'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local texsprint, count = tex.sprint, tex.count
+local format, concat, gmatch, match, find, lower = string.format, table.concat, string.gmatch, string.match, string.find, string.lower
+local tostring, next = tostring, next
+local lpegmatch = lpeg.match
+
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+
+--[[ldx--
+
Choosing a font by name and specififying its size is only part of the
+game. In order to prevent complex commands, introduced
+a method to pass feature information as part of the font name. At the
+risk of introducing nasty parsing and compatinility problems, this
+syntax was expanded over time.
+
+
For the sake of users who have defined fonts using that syntax, we
+will support it, but we will provide additional methods as well.
+Normally users will not use this direct way, but use a more abstract
+interface.
+
+
The next one is the official one. However, in the plain
+variant we need to support the crappy [] specification as
+well and that does not work too well with the general design
+of the specifier.
+--ldx]]--
+
+--~ function fonts.define.specify.colonized(specification) -- xetex mode
+--~ local list = { }
+--~ if specification.detail and specification.detail ~= "" then
+--~ for v in gmatch(specification.detail,"%s*([^;]+)%s*") do
+--~ local a, b = match(v,"^(%S*)%s*=%s*(%S*)$")
+--~ if a and b then
+--~ list[a] = b:is_boolean()
+--~ if type(list[a]) == "nil" then
+--~ list[a] = b
+--~ end
+--~ else
+--~ local a, b = match(v,"^([%+%-]?)%s*(%S+)$")
+--~ if a and b then
+--~ list[b] = a ~= "-"
+--~ end
+--~ end
+--~ end
+--~ end
+--~ specification.features.normal = list
+--~ return specification
+--~ end
+
+--~ check("oeps/BI:+a;-b;c=d")
+--~ check("[oeps]/BI:+a;-b;c=d")
+--~ check("file:oeps/BI:+a;-b;c=d")
+--~ check("name:oeps/BI:+a;-b;c=d")
+
+local list = { }
+
+fonts.define.specify.colonized_default_lookup = "file"
+
+local function issome () list.lookup = fonts.define.specify.colonized_default_lookup end
+local function isfile () list.lookup = 'file' end
+local function isname () list.lookup = 'name' end
+local function thename(s) list.name = s end
+local function issub (v) list.sub = v end
+local function iscrap (s) list.crap = string.lower(s) end
+local function istrue (s) list[s] = 'yes' end
+local function isfalse(s) list[s] = 'no' end
+local function iskey (k,v) list[k] = v end
+
+local function istrue (s) list[s] = true end
+local function isfalse(s) list[s] = false end
+
+local spaces = lpeg.P(" ")^0
+local namespec = (1-lpeg.S("/:("))^0 -- was: (1-lpeg.S("/: ("))^0
+local crapspec = spaces * lpeg.P("/") * (((1-lpeg.P(":"))^0)/iscrap) * spaces
+local filename = (lpeg.P("file:")/isfile * (namespec/thename)) + (lpeg.P("[") * lpeg.P(true)/isname * (((1-lpeg.P("]"))^0)/thename) * lpeg.P("]"))
+local fontname = (lpeg.P("name:")/isname * (namespec/thename)) + lpeg.P(true)/issome * (namespec/thename)
+local sometext = (lpeg.R("az","AZ","09") + lpeg.S("+-."))^1
+local truevalue = lpeg.P("+") * spaces * (sometext/istrue)
+local falsevalue = lpeg.P("-") * spaces * (sometext/isfalse)
+local keyvalue = (lpeg.C(sometext) * spaces * lpeg.P("=") * spaces * lpeg.C(sometext))/iskey
+local somevalue = sometext/istrue
+local subvalue = lpeg.P("(") * (lpeg.C(lpeg.P(1-lpeg.S("()"))^1)/issub) * lpeg.P(")") -- for Kim
+local option = spaces * (keyvalue + falsevalue + truevalue + somevalue) * spaces
+local options = lpeg.P(":") * spaces * (lpeg.P(";")^0 * option)^0
+local pattern = (filename + fontname) * subvalue^0 * crapspec^0 * options^0
+
+local normalize_meanings = fonts.otf.meanings.normalize
+
+function fonts.define.specify.colonized(specification) -- xetex mode
+ list = { }
+ lpegmatch(pattern,specification.specification)
+--~ for k, v in next, list do
+--~ list[k] = v:is_boolean()
+--~ if type(list[a]) == "nil" then
+--~ list[k] = v
+--~ end
+--~ end
+ list.crap = nil -- style not supported, maybe some day
+ if list.name then
+ specification.name = list.name
+ list.name = nil
+ end
+ if list.lookup then
+ specification.lookup = list.lookup
+ list.lookup = nil
+ end
+ if list.sub then
+ specification.sub = list.sub
+ list.sub = nil
+ end
+-- specification.features.normal = list
+ specification.features.normal = normalize_meanings(list)
+ return specification
+end
+
+fonts.define.register_split(":", fonts.define.specify.colonized)
diff --git a/tex/context/base/font-xtx.mkii b/tex/context/base/font-xtx.mkii
new file mode 100644
index 000000000..d6086b44e
--- /dev/null
+++ b/tex/context/base/font-xtx.mkii
@@ -0,0 +1,376 @@
+%D \module
+%D [ file=font-xtx,
+%D version=2004.09.11,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=\XETEX\ Hacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifnum\texengine=\xetexengine
+ \writestatus{loading}{ConTeXt Font Macros / XeTeX Hacks}
+\else
+ \endinput
+\fi
+
+\unprotect
+
+%D Loading:
+
+%D for some reason xetex does not support [filename] for tfm files and
+%D quotes also behave kind of strange " vs ' vs [ vs ...
+%D
+%D \starttyping
+%D \font\myfont = msam7 % ok
+%D \font\myfont = "msam7" % also ok
+%D \font\myfont = "msam7" at 8pt % error
+%D \stoptyping
+
+\newconditional\tracexetexfonts
+
+%D Because \XETEX\ is not that fast on locating fonts we cache lookups so
+%D that we minimize the test. It saves a little bit of runtime, depending
+%D on the number of fonts loaded (which is normally not that much).
+
+\def\doiffoundXTXfontelse#1#2%
+ {\ifcsname xtx@fnt@#2\somefontspec\endcsname
+ \ifconditional\tracexetexfonts
+ \writestatus\m!fonts{already checked #1: #2\somefontspec\space (state: \number\csname xtx@fnt@#2\somefontspec\endcsname)}%
+ \fi
+ \else
+ \suppressfontnotfounderror\plusone
+ \font\xetextempfont=#2\somefontspec\relax
+ \suppressfontnotfounderror\zerocount
+ \edef\xetextempfont{\fontname\xetextempfont}%
+ \global\expandafter\chardef\csname xtx@fnt@#2\somefontspec\endcsname
+ \ifx\xetextempfont\nullfontname
+ \zerocount \ifconditional\tracexetexfonts
+ \writestatus\m!fonts{not found #1: #2\somefontspec}%
+ \fi
+ \else
+ \plusone \ifconditional\tracexetexfonts
+ \writestatus\m!fonts{found #1: #2\somefontspec}%
+ \fi
+ \fi
+ \fi
+ \ifcase\csname xtx@fnt@#2\somefontspec\endcsname
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\docheckfontfilenameprefix#1:#2:#3#4\relax
+ {\edef\!!stringa{#1}%
+ \edef\!!stringb{#2}%
+ \ifx\!!stringb\empty
+ % no prefix
+ \let\checkedfontfile\!!stringa
+ \doiffoundXTXfontelse{1a}{\checkedfontfile\checkedfontfeatures}
+ {\edef\checkedfontfile{\checkedfontfile\checkedfontfeatures}}
+ {\doiffoundXTXfontelse{1b}{"\checkedfontfile\checkedfontfeatures"}
+ {\edef\checkedfontfile{"\checkedfontfile\checkedfontfeatures"}}
+ {\doiffoundXTXfontelse{1c}{"[\checkedfontfile]\checkedfontfeatures"}
+ {\edef\checkedfontfile{"[\checkedfontfile]\checkedfontfeatures"}}
+ {}}}%
+ \else\ifx\!!stringa\v!file
+ % force file, only file check when no spaces
+ \let\checkedfontfile\!!stringb
+ \doiffoundXTXfontelse{2a}{"[\checkedfontfile]\checkedfontfeatures"}
+ {\edef\checkedfontfile{"[\checkedfontfile]\checkedfontfeatures"}}
+ {\doiffoundXTXfontelse{2b}{"\checkedfontfile\checkedfontfeatures"}
+ {\edef\checkedfontfile{"\checkedfontfile\checkedfontfeatures"}}
+ {}}%
+ \else\ifx\!!stringa\v!name
+ % force name, always lookup by xetex itself, "" forces otf/ttf/type1
+ \edef\checkedfontfile{"\!!stringb\checkedfontfeatures"}%
+ \ifconditional\tracexetexfonts
+ \writestatus\m!fonts{no checking 3a: \checkedfontfile}%
+ \fi
+ \else
+ % whatever, maybe even xetex spec, forget about features
+ \edef\checkedfontfile{"\!!stringa\!!stringb"}%
+ \ifconditional\tracexetexfonts
+ \writestatus\m!fonts{no checking 3b: \checkedfontfile}%
+ \fi
+ \fi\fi\fi}
+
+\newconditional\enabledfontfeatures
+
+\def\checkfontfilename% -- todo: integrate so that we call do.. directly
+ {\expandafter\docheckfontfilename\fontfile*\empty*\relax}
+
+\def\docheckfontfilename#1*#2#3*#4\relax % class overrules file
+ {\settrue\enabledfontfeatures
+ \edef\checkedfontfeatures
+ {\expandafter\ifx\csname\fontclass\s!features\endcsname\empty
+ \ifx\@@fontfeatures\empty\ifx#2\empty\else#2#3\fi\else\@@fontfeatures\fi
+ \else\expandafter\ifx\csname\fontclass\s!features\endcsname\relax % redundant, will go away
+ \ifx\@@fontfeatures\empty\ifx#2\empty\else#2#3\fi\else\@@fontfeatures\fi
+ \else
+ \csname\fontclass\s!features\endcsname
+ \fi\fi}%
+ \ifx\checkedfontfeatures\empty
+ % done
+ \else
+ \edef\checkedfontfeatures{\executeifdefined{\??fa\checkedfontfeatures}\empty}%
+ \ifx\checkedfontfeatures\empty
+ % done
+ \else
+ \let\convertedfontfeatures\empty
+ \processcommacommand[\checkedfontfeatures]\doconvertfontfeatures % raw
+ \ifx\convertedfontfeatures\empty
+ \let\checkedfontfeatures\empty
+ \else\ifconditional\enabledfontfeatures
+ \edef\checkedfontfeatures{:\convertedfontfeatures}%
+ \else
+ \let\checkedfontfeatures\empty
+ \fi\fi
+ \fi
+ \fi
+ \docheckfontfilenameprefix#1:\empty:\empty\relax
+ \doshowcheckedfontfeatures}
+
+\edef\@@fontfeaturesareno {features\v!no}
+\edef\@@fontfeaturesareoff{features\v!off}
+
+\def\dodoconvertfontfeatures#1=#2#3=#4\relax
+ {\ifx#2\empty
+ % invalid feature
+ \else\ifcsname @xtx@#1@#2#3\endcsname
+ \expandafter\ifx\csname @xtx@#1@#2#3\endcsname\empty\else
+ \edef\convertedfontfeatures{\convertedfontfeatures\csname @xtx@#1@#2#3\endcsname;}%
+ \fi
+ \else
+ \edef\!!stringa{#1}%
+ \edef\!!stringb{#2#3}%
+ \edef\!!stringc{#1#2#3}%
+ \ifx\!!stringc\@@fontfeaturesareoff
+ \setfalse\enabledfontfeatures
+ \else\ifx\!!stringc\@@fontfeaturesareno
+ \setfalse\enabledfontfeatures
+ \else
+ \edef\convertedfontfeatures
+ {\convertedfontfeatures
+ \ifx\!!stringb\v!yes
+ +\!!stringa
+ \else\ifx\!!stringb\v!on
+ +\!!stringa
+ \else\ifx\!!stringb\v!no
+ -\!!stringa
+ \else\ifx\!!stringb\v!off
+ -\!!stringa
+ \else
+ \!!stringa=\!!stringb
+ \fi\fi\fi\fi;}%
+ \fi\fi
+ \fi\fi}
+
+\def\doconvertfontfeatures#1%
+ {\dodoconvertfontfeatures#1=\empty=\relax}
+
+\def\remapfontfeature #1 #2 #3 {\setevalue{@xtx@#1@#2}{#3}}
+
+% this may move to another file, maybe font-xtx
+
+\remapfontfeature tlig yes mapping=tlig
+%remapfontfeature tlig no mapping=
+\remapfontfeature trep yes {}
+\remapfontfeature trep no {}
+\remapfontfeature texligatures yes mapping=tlig
+%remapfontfeature texligatures no mapping=
+%remapfontfeature texquotes yes mapping=tex-text
+%remapfontfeature texquotes no mapping=
+
+%D Variants:
+
+\unexpanded\def\variant[#1]%
+ {\dosetscaledfont
+ \font\variantfont\truefontname{\fontstringA\fontstylesuffix\fontvariant\fontstringA{#1}} at \scaledfont
+ \variantfont}
+
+%D Possible optimizations:
+
+% \def\updatefontparameters
+% {\edef\@@fontfeatures{\truefontdata\fontfile\s!features}%
+% \edef\@@fontskewchar{\truefontdata\fontfile\s!skewchar}}
+
+% \def\setfontcharacteristics
+% {\updatefontparameters % redundant, will go away, faster too
+% \the\everyfont}
+
+% \let\synchronizepatternswithfont\relax
+
+%D Names:
+
+% We need to move the feature into the filename else it may be
+% overloaded by another reference. For instance the definition of
+% a regular and caps variant can use the same font.
+
+% We could use an indirect method ... store in 'array' and refer to
+% slot.
+
+\def\definefontsynonym[#1]#2[#3]%
+ {\edef\@@fontname{#1}%
+ \edef\@@fontfile{#3}%
+ \doifnextoptionalelse\dodefinefontsynonym\nodefinefontsynonym}
+
+\def\nodefinefontsynonym
+ {\@EA\let\csname\??ff\fontclass\@@fontname\endcsname\@@fontfile}
+
+\def\dodefinefontsynonym[#1]%
+ {\edef\@@fontdata{#1}%
+ \ifx\@@fontdata\empty
+ \nodefinefontsynonym
+ \else
+ \ifx\fontclass\empty
+ \getfontparameters
+ \else
+ \getglobalfontparameters
+ \fi
+ \ifcsname\??ff\@@fontfile\s!features\endcsname
+ \@EA\edef\csname\??ff\fontclass\@@fontname\endcsname{\@@fontfile*\csname\??ff\@@fontfile\s!features\endcsname}%
+ \@EA\let\csname\??ff\@@fontfile\s!features\endcsname\undefined
+ \else
+ \nodefinefontsynonym
+ \fi
+ \fi}
+
+\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
+
+% simple version
+%
+% \def\truefontname#1%
+% {\@EA\dotruefontname#1*\relax}
+%
+% \def\dotruefontname#1*#2\relax
+% {\ifcsname\??ff\fontclass#1\endcsname
+% \@EA\truefontname\csname\??ff\fontclass#1\endcsname
+% \else\ifcsname\??ff#1\endcsname
+% \@EA\truefontname\csname\??ff#1\endcsname
+% \else
+% #1%
+% \fi\fi}
+%
+% last counts
+%
+% \def\truefontname#1%
+% {\@EA\dotruefontname#1*\empty*\relax}
+%
+% \def\dotruefontname#1*#2#3*#4\relax
+% {\ifcsname\??ff\fontclass#1\endcsname
+% \ifx#2\empty
+% \@EA\truefontname\csname\??ff\fontclass#1\endcsname
+% \else
+% \@EA\truefontname\csname\??ff\fontclass#1\endcsname*#2#3%
+% \fi
+% \else\ifcsname\??ff#1\endcsname
+% \ifx#2\empty
+% \@EA\truefontname\csname\??ff#1\endcsname
+% \else
+% \@EA\truefontname\csname\??ff#1\endcsname*#2#3%
+% \fi
+% \else
+% \ifx#2\empty
+% #1%
+% \else
+% #1*#2#3%
+% \fi
+% \fi\fi}
+%
+% first counts
+
+\def\truefontname#1%
+ {\@EA\dotruefontname#1*\empty*\relax}
+
+\def\dotruefontname#1*#2#3*#4\relax
+ {\ifcsname\??ff\fontclass#1\endcsname
+ \ifx#2\empty
+ \@EA\truefontname\csname\??ff\fontclass#1\endcsname
+ \else
+ \@EA\redotruefontname\csname\??ff\fontclass#1\endcsname*#2#3%
+ \fi
+ \else\ifcsname\??ff#1\endcsname
+ \ifx#2\empty
+ \@EA\truefontname\csname\??ff#1\endcsname
+ \else
+ \@EA\redotruefontname\csname\??ff#1\endcsname*#2#3%
+ \fi
+ \else
+ #1\ifx#2\empty\else*#2#3\fi
+ \fi\fi}
+
+\def\redotruefontname#1%
+ {\@EA\dodotruefontname#1*\relax}
+
+\def\dodotruefontname#1*#2\relax
+ {\ifcsname\??ff\fontclass#1\endcsname
+ \@EA\redotruefontname\csname\??ff\fontclass#1\endcsname
+ \else\ifcsname\??ff#1\endcsname
+ \@EA\redotruefontname\csname\??ff#1\endcsname
+ \else
+ #1%
+ \fi\fi}
+
+%D Default:
+
+\def\defaultfontfile{file:lmmono10-regular}
+
+%D Maybe:
+
+% \def\updatefontparameters
+% {\edef\@@fontfeatures{\truefontdata\fontfile \s!features}%
+% \edef\@@fontskewchar{\truefontdata\fontfile \s!skewchar}}
+
+% \def\setfontcharacteristics
+% {%\updatefontparameters % redundant, will go away, faster too
+% \the\everyfont
+% \synchronizepatternswithfont}
+
+\protect \endinput
+
+% \starttypescript[serif] [myzhfont]
+% \definefontsynonym [Serif] [file:SimSun]
+% \definefontsynonym [SerifBold] [file:SimSun]
+% \definefontsynonym [SerifItalic] [file:SimSun]
+% \definefontsynonym [SerifBoldItalic] [file:SimSun]
+% \stoptypescript
+% \starttypescript[sans] [myzhfont]
+% \definefontsynonym [Sans] [file:SimSun]
+% \definefontsynonym [SansBold] [file:SimSun]
+% \definefontsynonym [SansItalic] [file:SimSun]
+% \definefontsynonym [SansBoldItalic] [file:SimSun]
+% \stoptypescript
+% \starttypescript[mono] [myzhfont]
+% \definefontsynonym [Mono] [file:SimSun]
+% \definefontsynonym [MonoBold] [file:SimSun]
+% \definefontsynonym [MonoItalic] [file:SimSun]
+% \definefontsynonym [MonoBoldItalic] [file:SimSun]
+% \stoptypescript
+% \definetypeface [myzhfont] [rm] [serif][myzhfont] [default]
+% \definetypeface [myzhfont] [ss] [sans] [myzhfont] [default]
+% \definetypeface [myzhfont] [tt] [mono] [myzhfont] [default]
+
+% \starttext
+% % on windows: make sure fonts.conf has no cache mentioned
+% %
+% % 64 sec xetex, 11 sec luatex (56 sec xetex when \nobigmath)
+% %
+% \setupbodyfont[myzhfont] \dorecurse{10000}{{hello {\switchtobodyfont[myzhfont] 你好}}\par}
+% %
+% % 67 sec xetex, 11.5 sec luatex
+% %
+% % \dorecurse{10000}{{hello {\switchtobodyfont[myzhfont] 你好}}\par}
+% %
+% % 5 sec xetex, 7 sec luatex
+% %
+% % \setupbodyfont[myzhfont] \dorecurse{10000}{{hello {你好}}\par}
+% %
+% % 5 sec xetex, 7 sec luatex
+% %
+% % \setupbodyfont[myzhfont] \dorecurse{10000}{{\bf hello {你好}}\par}
+% \stoptext
+
diff --git a/tex/context/base/grph-fig.mkii b/tex/context/base/grph-fig.mkii
new file mode 100644
index 000000000..c7f990af2
--- /dev/null
+++ b/tex/context/base/grph-fig.mkii
@@ -0,0 +1,559 @@
+%D \module
+%D [ file=grph-fig,
+%D version=2006.08.26, % overhaul of 1997.03.31
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Figure Inclusion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphic Macros / Figure Handling}
+
+\unprotect
+
+\def\setupexternalfigures
+ {\dosingleempty\dosetupexternalfigures}
+
+\def\dosetupexternalfigures[#1]%
+ {\getparameters[\??ef][#1]% local settings
+ \getparameters[\??ex][#1]% global settings
+ \setfigurepathlist} % the path may be used elsewhere too (as in x-res-04)
+
+\presetlocalframed[\??ef]
+
+\newconditional\externalfigurelevel % true=background false=normal
+\newconditional\externalfigureflush % true=place false=ignore
+
+\setfalse\externalfigurelevel
+\settrue \externalfigureflush
+
+\def\doplaceexternalfigure[#1][#2][#3][#4][#5]%
+ {\doifsomething{#2}% catches \defineexternalfigure dummies
+ {\doifundefinedelse{\??ef\??ef#2}
+ {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]}
+ {\doifelse{#1}{#2}
+ {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]}
+ {\getvalue{\??ef\??ef#2}[#5]}}}}
+
+\def\dodoplaceexternalfigure[#1][#2][#3][#4][#5]%
+ {\bgroup
+ \pushmacro\textunderscore
+ \edef\textunderscore{\string_}% brrr, temp hack, still needed?
+ \calculateexternalfigure [][#1][#2][#3][#4][#5]% [] is dummy dwcomp
+ \calculateexternalscreenfigure[][#1][#2][#3][#4][#5]% [] is dummy dwcomp
+ \popmacro\textunderscore
+ \box\foundexternalfigure
+ \egroup}
+
+\def\externalfigurereplacement#1#2#3%
+ {\setupcolors
+ [\c!state=\v!local]%
+ \expanded{\localframed
+ [\??ef]
+ [\c!width=\figurewidth,
+ \c!height=\figureheight,
+ \c!background=\v!screen,
+ \c!backgroundscreen=.8,
+ \c!frame=\@@efframe]}%
+ {\tt\tfxx \nohyphens
+ name: \expanded{\verbatimstring{#1}}\\%
+ file: \expanded{\verbatimstring{#2}}\\%
+ state: \expanded{\verbatimstring{#3}}}}
+
+\def\externalfigureplaceholder#1#2#3%
+ {\localframed
+ [\??ef]
+ [\c!width=#2,
+ \c!height=#3,
+ \c!frame=\v!on]%
+ {\tt\tfxx \nohyphens
+ name: \expanded{\verbatimstring{#1}}\\%
+ state: \expanded{\verbatimstring{placeholder}}}}
+
+% new: more convenient/efficient than
+%
+% \use..[a][a][setting] \externalfigure[b][a]
+%
+% is equivalent to:
+%
+% \def..[a][setting] \externalfigure[b][a]
+%
+% see x-res modules for usage:
+%
+% \defineexternalfigure[name][settings]
+
+\def\defineexternalfigure
+ {\dodoubleargument\dodefineexternalfigure}
+
+\def\dodefineexternalfigure[#1][#2]%
+ {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][][][#2]}}
+
+\def\getexternalfigure#1% efef has 4 args already and take an 5th
+ {\wait} % OBSOLETE
+
+% \useexternalfigure[alpha][koe]
+% \useexternalfigure[beta] [koe] [breedte=1cm]
+% \useexternalfigure[gamma][koe][alpha]
+% \useexternalfigure[delta][koe][alpha][breedte=2cm]
+%
+% volle breedte: \externalfigure[koe] \par
+% 3cm breed: \externalfigure[koe] [breedte=3cm] \par
+% volle breedte: \externalfigure[alpha] \par
+% 1cm breed: \externalfigure[beta] \par
+% volle breedte: \externalfigure[gamma] \par
+% 2cm breed: \externalfigure[delta] \par
+% 4cm breed: \externalfigure[beta] [breedte=4cm] \par
+% 5cm breed: \externalfigure[gamma][breedte=5cm] \par
+
+% \defineexternalfigure[a][width=10cm]
+% \defineexternalfigure[b][width=5cm]
+% \externalfigure[cow][a]
+% \externalfigure[cow][b][height=8cm]
+
+% \useexternalfigure[x][cow][width=10cm,height=1cm]
+% \externalfigure[x]
+% \externalfigure[x][width=3cm]
+
+\def\useexternalfigure
+ {\doquadrupleempty\douseexternalfigure}
+
+% [label] [filename]
+% [label] [filename] [parent]
+% [label] [filename] [parent] [settings]
+% [label] [filename] [settings]
+
+\def\useexternalfigure
+ {\doquadrupleempty\douseexternalfigure}
+
+\def\douseexternalfigure[#1][#2][#3][#4]%
+ {\doifelsenothing{#1}
+ {\doifsomething{#2}
+ {\doifassignmentelse{#3}
+ {\setvalue{\??ef\??ef#2}{\doplaceexternalfigure[#2][#2][#3][#4]}}
+ {\setvalue{\??ef\??ef#2}{\doplaceexternalfigure[#2][#2][][#4]}}}}
+ {\doifelsenothing{#2}
+ {\doifassignmentelse{#3}
+ {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#1][][#3]}}
+ {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#1][#3][#4]}}}
+ {\doifassignmentelse{#3}
+ {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][][#3]}}
+ {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][#3][#4]}}}}}
+
+\def\dosetefparameters#1#2#3% parent_id use_settings current_settings
+ {\doifelsenothing{#1} % inherit from parent
+ {\getparameters[\??ef][#2,#3]}
+ {\doifdefinedelse{\??ef\??ef#1}
+ {\pushmacro\doplaceexternalfigure
+ \def\doplaceexternalfigure[##1][##2][##3][##4]{\getparameters[\??ef][##4,#2,#3]}%
+ \getvalue{\??ef\??ef#1}%
+ \popmacro\doplaceexternalfigure}
+ {\getparameters[\??ef][#2,#3]}}}
+
+\unexpanded\def\externalfigure
+ {\dotripleempty\doexternalfigure}
+
+\def\doexternalfigure[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings]
+ {\bgroup
+ \doifelsenothing{#1}
+ {\framed[\c!width=\defaultfigurewidth,\c!height=\defaultfigureheight]{external\\figure\\no name}}
+ {\doifundefinedelse{\??ef\??ef#1}
+ {\useexternalfigure[\s!dummy][#1][#2][#3]%
+ \getvalue{\??ef\??ef\s!dummy}[]} % [] is dummy arg 5
+ {\doifassignmentelse{#2}
+ {\getvalue{\??ef\??ef#1}[#2]}%
+ {\getvalue{\??ef\??ef#1}[#3]}}}%
+ \globallet\currentresourcecomment\empty
+ \egroup}
+
+\long\def\resourcecomment#1%
+ {\long\gdef\currentresourcecomment{#1}}
+
+\long\def\startresourcecomment#1\stopresourcecomment
+ {\long\gdef\currentresourcecomment{#1}}
+
+\let\currentresourcecomment\empty
+
+\def\showexternalfigures % maybe run time command is better, but no core-run, unless figs-run ...
+ {%\writestatus\m!systems{for \string\showexternalfigures\space see \truefilename{x-res-20}.tex}
+ \usemodule[res-20]\showexternalfigures} % so for the moment we do it this way
+
+\def\overlayfigure#1%
+ {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]}
+
+%D Still undocumented! No one uses it I think, better be done with layers.
+
+\newcount\efreference
+\newdimen\efxsteps
+\newdimen\efysteps
+
+\def\calculateefsteps
+ {\ifnum0\@@exxmax=\zerocount
+ \ifnum0\@@exymax=\zerocount
+ \def\@@exymax{24}%
+ \fi
+ \efysteps\figureheight \divide\efysteps \@@exymax
+ \efxsteps\efysteps
+ \dimen0=\figurewidth
+ \advance\dimen0 \efysteps
+ \divide \dimen0 \efysteps
+ \edef\@@exxmax{\number\dimen0}%
+ \else
+ \efxsteps\figurewidth \divide\efxsteps \@@exxmax
+ \efysteps\figureheight \divide\efysteps \@@exymax
+ \fi}
+
+\def\efcomment#1(#2,#3)#4(#5,#6)% {kader}(x,y)(h,b)[...]{tekst}
+ {\def\complexefdocomment[##1]##2%
+ {\position(#2,#3)%
+ {\setnostrut
+ \framed
+ [\c!width=#5\efxsteps,
+ \c!height=#6\exysteps,
+ \c!offset=\v!none,
+ \c!frame=#1,
+ ##1]%
+ {##2}}}%
+ \complexorsimpleempty\efdocomment}
+
+\def\efnocomment(#1,#2)#3(#4,#5)% (x,y)(h,b)[...]{tekst}
+ {\def\complexefdonocomment[##1]##2{}%
+ \complexorsimpleempty\efdonocomment}
+
+\def\efdomarker(#1,#2)#3#4% (h,b){kader}{tekst}
+ {\framed
+ [\c!width=#1\efxsteps,
+ \c!height=#2\efysteps,
+ \c!offset=\v!none,
+ \c!frame=#3]%
+ {#4}}
+
+\def\effigure#1%
+ {\position(0,0){\getvalue{#1}}}
+
+\def\efdoarea(#1,#2)#3#4% (h,b){kader}{tekst}
+ {\bgroup
+ \setnostrut
+ \framed
+ [\c!width=#1\efxsteps,
+ \c!height=#2\efysteps,
+ \c!offset=\!!zeropoint,
+ \c!frame=#3]
+ {#4}%
+ \egroup}
+
+\def\efgoto(#1,#2)#3[#4]% (h,b)kader[ref]
+ {\setbox0=\vbox{\efdoarea(#1,#2)#3{}}%
+ \gotobox{\copy0}[#4]}
+
+\def\efmark(#1,#2)#3(#4,#5)#6[#7]%
+ {\advance\efreference \plusone
+ \position(#1,#2)
+ {\hbox{\the\efreference}}%
+ \position(#1,#2)
+ {\gotosomeinternal\s!vwb{#7}\realfolio
+ {\efdomarker(#4,#5)\v!on{\thisissomeinternal\s!vwa{#7}}}}}
+
+\def\eftext#1(#2,#3)#4(#5,#6)#7[#8]%
+ {\advance\efreference \plusone
+ \hbox
+ {\quad
+ \thisissomeinternal\s!vwb{#8}%
+ \gotosomeinternal \s!vwa{#8}\realfolio
+ {\hbox to 1.5em{\the\efreference\presetgoto\hfill}}%
+ \quad#1 (#2,#3) (#5,#6) [#8]\hfill}%
+ \endgraf}
+
+\def\efthisis(#1,#2)#3[#4]%
+ {\efdoarea(#1,#2){#3}{\pagereference[#4]}}
+
+\newbox\colorbarbox
+
+\def\makecolorbar[#1]%
+ {\def\docommand##1%
+ {\color[##1]
+ {\blackrule
+ [\c!width=2em,
+ \c!height=1ex,
+ \c!depth=\!!zeropoint]}%
+ \endgraf}%
+ \global\setbox\colorbarbox\vbox
+ {\forgetall
+ \processcommalist[#1]\docommand}%
+ \global\setbox\colorbarbox\vbox
+ {\hskip2em\box\colorbarbox}%
+ \global\wd\colorbarbox\zeropoint}
+
+\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]%
+ {\hbox
+ {\setbox0\hbox
+ {\useexternalfigure[\s!dummy][#2][#3,#5]%
+ \externalfigure[\s!dummy]}%
+ \calculateefsteps
+ \startpositioning
+ \def\referring(##1,##2)##3(##4,##5)##6[##7]%
+ {\position(##1,##2){\efgoto(##4,##5){\@@exframes}[##7]}}%
+ \def\marking(##1,##2)##3(##4,##5)##6[##7]%
+ {\position(##1,##2){\efthisis(##4,##5){\@@exframes}[##7]}}%
+ \def\remark{\efnocomment}%
+ \def\colorbar##1[##2]{}%
+ \position(0,0){\box0}%
+ \linewidth\onepoint
+ \setuppositioning
+ [\c!unit=pt,
+ \c!xscale=\withoutpt\the\efxsteps,
+ \c!yscale=\withoutpt\the\efysteps,
+ \c!factor=1]%
+ \ignorespaces#4%
+ \def\referring(##1,##2)##3(##4,##5)##6[##7]%
+ {}%
+ \let\marking\referring
+ \def\remark{\efcomment\v!no}%
+ \def\colorbar##1[##2]{\makecolorbar[##2]}%
+ \ignorespaces#4%
+ \stoppositioning
+ \box\colorbarbox}}
+
+\def\dodostartfigure[#1][#2][#3]#4\stopfigure
+ {\doifelse\v!test\@@exoption
+ {\teststartfigure[#1][#2][#3]#4\teststopfigure
+ \let\@@exframes\v!on}
+ {\let\@@exframes\v!off}%
+ \setvalue{\??ef\??ef#1}%
+ {\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}%
+ }% no longer \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
+
+% De onderstaande macro mag niet zondermeer worden aangepast
+% en is afgestemd op gebruik in de handleiding.
+
+\def\teststartfigure[#1][#2][#3]#4\teststopfigure%
+ {\begingroup
+ \setbox0\hbox
+ {\useexternalfigure[\s!dummy][#2][\c!wfactor=\v!max]%
+ \externalfigure[\s!dummy]}%
+ \def\referring{\efmark}%
+ \def\marking{\efmark}%
+ \def\remark{\efcomment\v!yes}%
+ \def\colorbar##1[##2]{}%
+ \efreference\zerocount
+ \setbox0\vbox
+ {\hsize240pt
+ \startpositioning
+ \calculateefsteps
+ \position(0,0)
+ {\box0}%
+ \position(0,0)
+ {\basegrid
+ [\c!nx=\@@exxmax,
+ \c!dx=\withoutpt\the\efxsteps,
+ \c!ny=\@@exymax,
+ \c!dy=\withoutpt\the\efysteps,
+ \c!xstep=1,
+ \c!ystep=1,
+ \c!scale=1,
+ \c!offset=\v!no,
+ \c!unit=pt]}%
+ \setuppositioning
+ [\c!unit=pt,
+ \c!xscale=\withoutpt\the\efxsteps,
+ \c!yscale=\withoutpt\the\efysteps,
+ \c!factor=1]%
+ \linewidth\onepoint
+ \ignorespaces#4\relax
+ \stoppositioning
+ \vfill}%
+ \efreference\zerocount
+ \def\referring{\eftext{$\rightarrow$}}%
+ \def\marking{\eftext{$\leftarrow$}}%
+ \def\remark{\efnocomment}%
+ \def\colorbar##1[##2]{}%
+ \setbox2\vbox
+ {{\tfa\doifelsenothing{#1}{#2}{#1}}
+ \blank
+ \tfxx#4
+ \vfilll}%
+ \ifdim\ht0>\ht2
+ \ht2\ht0
+ \else
+ \ht0\ht2
+ \fi
+ \hbox
+ {\hskip3em
+ \vtop{\vskip12pt\box0\vskip6pt}%
+ \vtop{\vskip12pt\box2\vskip6pt}}%
+ \endgroup}
+
+\def\dodostartfigure[#1][#2][#3]#4\stopfigure
+ {\doifelse\v!test\@@exoption
+ {\teststartfigure[#1][#2][#3]#4\teststopfigure
+ \let\@@exframe\v!on}
+ {\let\@@exframe\v!off}%
+ \setvalue{\??ef\??ef#1}%
+ {\def\next{\placestartfigure[#1][#2][#3]#4\placestopfigure}%
+ \dosingleempty\next}%
+ }% no longer: \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
+
+\long\def\dostartfigure#1%
+ {\dotripleargument\dodostartfigure#1\stopfigure}
+
+\def\startfigure
+ {\grabuntil{\e!stop\v!figure}\dostartfigure}
+
+%D defining sound tracks:
+%D
+%D \starttyping
+%D \useexternalsoundtrack[label][file]
+%D \stoptyping
+%D
+%D associated actions: StartSound StopSound PauseSound ResumeSound
+%D
+%D Todo: like external figures, also search on path,
+%D although, they need to be present ar viewing time, so ...
+
+\def\useexternalsoundtrack
+ {\dodoubleargument\douseexternalsoundtrack}
+
+\def\douseexternalsoundtrack[#1][#2]%
+ {\setgvalue{\??sd:#1}{#2}}
+
+\def\checksoundtrack#1%
+ {\iflocation
+ \doifdefined{\??sd:#1}{\doifvaluesomething{\??sd:#1}
+ {\doinsertsoundtrack{\getvalue{\??sd:#1}}{#1}\@@sdoption
+ % brr, \..empty not really needed and maybe even wrong;
+ % also, not here but in driver
+ % well, no: sounds need to be reinitialize each time (i.e., be on page), so no
+ }}% \letgvalueempty{\??sd:#1}}}%
+ \fi}
+
+\setexecutecommandcheck {startsound} \checksoundtrack
+
+\def\setupexternalsoundtracks
+ {\dodoubleargument\getparameters[\??sd]}
+
+\setupexternalsoundtracks
+ [\c!option=]
+
+%D NEW: used in styledesign manual
+
+% \setbuffer[typeset-b]\endbuffer
+% \setbuffer[typeset-a]\endbuffer
+%
+% todo:
+%
+% \appendtoks \setbuffer[typeset-b]\endbuffer\to \everystarttext
+% \appendtoks \setbuffer[typeset-a]\endbuffer\to \everystarttext
+
+\def\typesetbuffer
+ {\dodoubleempty\dotypesetbuffer}
+
+\newcounter\noftypesetbuffers % all loaded at the end
+
+\defineexternalfigure
+ [typeset]
+ [\c!background=\v!color,
+ \c!backgroundcolor=\s!white]
+
+\def\dotypesetbuffer[#1][#2]% beware: this will mix up the mp graphics
+ {\bgroup
+ \def\TEXbufferfile##1{\bufferprefix##1.tex}%
+ \expanded{\setbuffer[typeset]%
+ \def\noexpand\bufferprefix{\ifprotectbuffers\jobname-\fi typeset-}}%
+ \starttext
+ \getbuffer[b,#1,a]%
+ \stoptext
+ \endbuffer
+ \doglobal\increment\noftypesetbuffers
+ % batch is needed
+ \executesystemcommand{texmfstart texexec --batch --pdf --result=\bufferprefix typeset-\noftypesetbuffers\space \bufferprefix typeset.tex}%
+ %\externalfigure[\bufferprefix typeset-\noftypesetbuffers.pdf][\c!object=\v!no,#2]%
+ \externalfigure[\bufferprefix typeset-\noftypesetbuffers.pdf][#2]%
+ \egroup}
+
+% for me only (manuals and such)
+
+\definesystemvariable{tz}
+
+\def\definetypesetting{\dotripleempty\dodefinetypesetting}
+\def\typesetfile {\dotripleempty\dotypesetfile}
+
+\def\dodefinetypesetting[#1][#2][#3]%
+ {\doifsomething{#1}{\setvalue{\??tz#1}{\dodotypesetfile{#2}{#3}}}}
+
+\def\dotypesetfile[#1][#2][#3]%
+ {\executeifdefined{\??tz#1}\gobbletwoarguments{#2}{#3}}
+
+\def\dodotypesetfile#1#2#3#4% args settings file settings
+ {\doifmode{*\v!first}{\executesystemcommand{texmfstart texexec.pl --batch --pdf #1 #3}}%
+ \doglobal\beforesplitstring#3\at.\to\typesetfilename
+ \externalfigure[\typesetfilename.pdf][#2,#4]}
+
+\setupexternalfigures
+ [\c!option=,
+ \c!object=\v!yes, % we only check for no
+ \c!reset=\v!no,
+ \c!maxwidth=\@@efwidth,
+ \c!maxheight=\@@efheight,
+ \c!bodyfont=\bodyfontsize,
+ \c!directory=,
+ \c!file=\f!utilityfilename.\f!figureextension,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ \c!frame=\v!off,
+ \c!background=, % new
+ \c!splitcolor=\s!white,
+ \c!conversion=,
+ \c!prefix=,
+ \c!cache=,
+% \c!grid=,
+ \c!equalwidth=,
+ \c!equalheight=,
+ \c!location={\v!local,\v!global}]
+
+\setupexternalfigures
+ [\c!frames=\v!off,
+ \c!ymax=24,
+ \c!xmax=]
+
+\useexternalfigure
+ [buffer] [\jobname] [\c!type=\v!buffer,\c!object=\v!no]
+
+\protect \endinput
+
+% alternative for positioning
+
+% \definelayer[figure][width=\overlaywidth,height=\overlayheight]
+% \defineoverlay[figure][{\directsetup{figure}\tightlayer[figure]}]
+
+% \setupcolors[state=start]
+
+% \starttext
+
+% \startsetups figure
+% \setlayerframed[figure][preset=rightbottom,x=.25\layerwidth,y=.25\layerheight]{HERE}
+% \setlayerframed[figure][preset=leftbottom, x=.15\layerwidth,y=.35\layerheight]{THERE}
+% \stopsetups
+
+% \externalfigure[cow][background={foreground,figure},width=4cm,height=8cm]
+
+% \startsetups figure
+% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{MORE}
+% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE}
+% \stopsetups
+
+% \externalfigure[cow][background={foreground,figure},width=14cm,height=2cm]
+
+% \defineexternalfigure[whatever][background={foreground,figure}]
+
+% \startsetups figure
+% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{\red MORE}
+% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE}
+% \stopsetups
+
+% \externalfigure[cow][whatever][width=14cm,height=4cm]
+
+% \stoptext
+
diff --git a/tex/context/base/grph-fig.mkiv b/tex/context/base/grph-fig.mkiv
new file mode 100644
index 000000000..e10dc0a32
--- /dev/null
+++ b/tex/context/base/grph-fig.mkiv
@@ -0,0 +1,640 @@
+%D \module
+%D [ file=grph-fig,
+%D version=2006.08.26, % overhaul of 1997.03.31
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Figure Inclusion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphic Macros / Figure Handling}
+
+\unprotect
+
+\unexpanded\def\setupexternalfigures
+ {\dosingleempty\dosetupexternalfigures}
+
+\def\dosetupexternalfigures[#1]%
+ {\getparameters[\??ef][#1]% local settings
+ \getparameters[\??ex][#1]% global settings
+ \setfigurepathlist} % the path may be used elsewhere too (as in x-res-04)
+
+\presetlocalframed[\??ef]
+
+\newconditional\externalfigurelevel % true=background false=normal
+\newconditional\externalfigureflush % true=place false=ignore
+
+\setfalse\externalfigurelevel
+\settrue \externalfigureflush
+
+\def\doplaceexternalfigure[#1][#2][#3][#4][#5]%
+ {\doifsomething{#2}% catches \defineexternalfigure dummies
+ {\doifundefinedelse{\??ef\??ef#2}
+ {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]}
+ {\doifelse{#1}{#2}
+ {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]}
+ {\getvalue{\??ef\??ef#2}[#5]}}}}
+
+\def\dodoplaceexternalfigure[#1][#2][#3][#4][#5]%
+ {\bgroup
+ \pushmacro\textunderscore
+ \edef\textunderscore{\string_}% brrr, temp hack, still needed?
+ \calculateexternalfigure[][#1][#2][#3][#4][#5]% [] is dummy dwcomp
+ \popmacro\textunderscore
+ \box\foundexternalfigure
+ \egroup}
+
+\def\externalfigurereplacement#1#2#3%
+ {\setupcolors
+ [\c!state=\v!local]%
+ \expanded{\localframed
+ [\??ef]
+ [\c!width=\figurewidth,
+ \c!height=\figureheight,
+ \c!background=\v!color,
+ \c!backgroundcolor=missingfigurecolor,
+ \c!frame=\@@efframe]}%
+ {\tt\tfxx \nohyphens
+ name: \expanded{\verbatimstring{#1}}\\%
+ file: \expanded{\verbatimstring{#2}}\\%
+ state: \expanded{\verbatimstring{#3}}}}
+
+\definecolor[missingfigurecolor][s=.8]
+
+\def\externalfigureplaceholder#1#2#3%
+ {\localframed
+ [\??ef]
+ [\c!width=#2,
+ \c!height=#3,
+ \c!frame=\v!on]%
+ {\tt\tfxx \nohyphens
+ name: \expanded{\verbatimstring{#1}}\\%
+ state: \expanded{\verbatimstring{placeholder}}}}
+
+% new: more convenient/efficient than
+%
+% \use..[a][a][setting] \externalfigure[b][a]
+%
+% is equivalent to:
+%
+% \def..[a][setting] \externalfigure[b][a]
+%
+% see x-res modules for usage:
+%
+% \defineexternalfigure[name][settings]
+
+\unexpanded\def\defineexternalfigure
+ {\dodoubleargument\dodefineexternalfigure}
+
+\def\dodefineexternalfigure[#1][#2]%
+ {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][][][#2]}}
+
+\def\getexternalfigure#1% efef has 4 args already and take an 5th
+ {\wait} % OBSOLETE
+
+% \useexternalfigure[alpha][koe]
+% \useexternalfigure[beta] [koe] [breedte=1cm]
+% \useexternalfigure[gamma][koe][alpha]
+% \useexternalfigure[delta][koe][alpha][breedte=2cm]
+%
+% volle breedte: \externalfigure[koe] \par
+% 3cm breed: \externalfigure[koe] [breedte=3cm] \par
+% volle breedte: \externalfigure[alpha] \par
+% 1cm breed: \externalfigure[beta] \par
+% volle breedte: \externalfigure[gamma] \par
+% 2cm breed: \externalfigure[delta] \par
+% 4cm breed: \externalfigure[beta] [breedte=4cm] \par
+% 5cm breed: \externalfigure[gamma][breedte=5cm] \par
+
+% \defineexternalfigure[a][width=10cm]
+% \defineexternalfigure[b][width=5cm]
+% \externalfigure[cow][a]
+% \externalfigure[cow][b][height=8cm]
+
+% \useexternalfigure[x][cow][width=10cm,height=1cm]
+% \externalfigure[x]
+% \externalfigure[x][width=3cm]
+
+\def\useexternalfigure
+ {\doquadrupleempty\douseexternalfigure}
+
+% [label] [filename]
+% [label] [filename] [parent]
+% [label] [filename] [parent] [settings]
+% [label] [filename] [settings]
+
+\def\useexternalfigure
+ {\doquadrupleempty\douseexternalfigure}
+
+% \def\douseexternalfigure[#1][#2][#3][#4]%
+% {\doifelsenothing{#1}
+% {\doifsomething{#2}
+% {\doifassignmentelse{#3}
+% {\setvalue{\??ef\??ef#2}{\doplaceexternalfigure[#2][#2][#3][#4]}}
+% {\setvalue{\??ef\??ef#2}{\doplaceexternalfigure[#2][#2][][#4]}}}}
+% {\doifelsenothing{#2}
+% {\doifassignmentelse{#3}
+% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#1][][#3]}}
+% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#1][#3][#4]}}}
+% {\doifassignmentelse{#3}
+% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][][#3]}}
+% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][#3][#4]}}}}}
+
+\def\douseexternalfigure[#1][#2][#3][#4]%
+ {\doifelsenothing{#1}
+ {\doifsomething{#2}
+ {\doifassignmentelse{#3}
+ {\dodouseexternalfigure{#2}{#2}{#3}{#4}}
+ {\dodouseexternalfigure{#2}{#2}{}{#4}}}}
+ {\doifelsenothing{#2}
+ {\doifassignmentelse{#3}
+ {\dodouseexternalfigure{#1}{#1}{}{#3}}
+ {\dodouseexternalfigure{#1}{#1}{#3}{#4}}}
+ {\doifassignmentelse{#3}
+ {\dodouseexternalfigure{#1}{#2}{}{#3}}
+ {\dodouseexternalfigure{#1}{#2}{#3}{#4}}}}}
+
+\def\dodouseexternalfigure#1#2#3#4%
+ {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][#3][#4]}%
+ \doanalyseexternalfigurecollection[#2][#4]}
+
+\newconditional\inexternalfigurecollection
+\newdimen\xexternalfigurecollectionminwidth
+\newdimen\xexternalfigurecollectionmaxwidth
+\newdimen\xexternalfigurecollectionminheight
+\newdimen\xexternalfigurecollectionmaxheight
+
+\def\doanalyseexternalfigurecollection[#1][#2]%
+ {\ifconditional\inexternalfigurecollection
+ \setfalse\inexternalfigurecollection
+ \getfiguredimensions[#1][#2]%
+ \settrue\inexternalfigurecollection
+ \scratchdimen\naturalfigurewidth
+ \ifdim\scratchdimen>\xexternalfigurecollectionmaxwidth \xexternalfigurecollectionmaxwidth \scratchdimen \fi
+ \ifdim\scratchdimen<\xexternalfigurecollectionminwidth \xexternalfigurecollectionminwidth \scratchdimen \fi
+ \scratchdimen\naturalfigureheight
+ \ifdim\scratchdimen>\xexternalfigurecollectionmaxheight \xexternalfigurecollectionmaxheight\scratchdimen \fi
+ \ifdim\scratchdimen<\xexternalfigurecollectionminheight \xexternalfigurecollectionminheight\scratchdimen \fi
+ \fi}
+
+\unexpanded\def\startexternalfigurecollection[#1]%
+ {\begingroup
+ \def\currentexternalfigurecollection{#1}%
+ \settrue\inexternalfigurecollection
+ \xexternalfigurecollectionminwidth \maxdimen
+ \xexternalfigurecollectionmaxwidth \zeropoint
+ \xexternalfigurecollectionminheight\maxdimen
+ \xexternalfigurecollectionmaxheight\zeropoint}
+
+\unexpanded\def\stopexternalfigurecollection
+ {\setxvalue{\??ef:c:\currentexternalfigurecollection:\c!minwidth }{\the\xexternalfigurecollectionminwidth }%
+ \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!maxwidth }{\the\xexternalfigurecollectionmaxwidth }%
+ \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!minheight}{\the\xexternalfigurecollectionminheight}%
+ \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!maxheight}{\the\xexternalfigurecollectionmaxheight}%
+ \endgroup}
+
+\def\externalfigurecollectionparameter#1#2%
+ {\csname\ifcsname\??ef:c:#1:#2\endcsname\??ef:c:#1:#2\else\s!empty\fi\endcsname}
+
+\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth }
+\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth }
+\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight}
+\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight}
+
+\let\efcparameter\externalfigurecollectionparameter
+\let\efcminwidth \externalfigurecollectionminwidth
+\let\efcmaxwidth \externalfigurecollectionmaxwidth
+\let\efcminheight\externalfigurecollectionminheight
+\let\efcmaxheight\externalfigurecollectionmaxheight
+
+% \startexternalfigurecollection[name]
+% \useexternalfigure[cow] [cow.pdf]
+% \useexternalfigure[mill][mill.png]
+% \stopexternalfigurecollection
+% \starttext
+% \bTABLE
+% \bTR
+% \bTD \externalfigure[cow] [height=\externalfigurecollectionmaxheight{name}] \eTD
+% \bTD \externalfigure[mill][height=\externalfigurecollectionmaxheight{name}] \eTD
+% \eTR
+% \eTABLE
+% \stoptext
+
+\def\dosetefparameters#1#2#3% parent_id use_settings current_settings
+ {\doifelsenothing{#1} % inherit from parent
+ {\getparameters[\??ef][#2,#3]}
+ {\doifdefinedelse{\??ef\??ef#1}
+ {\pushmacro\doplaceexternalfigure
+ \def\doplaceexternalfigure[##1][##2][##3][##4]{\getparameters[\??ef][##4,#2,#3]}%
+ \getvalue{\??ef\??ef#1}%
+ \popmacro\doplaceexternalfigure}
+ {\getparameters[\??ef][#2,#3]}}}
+
+\unexpanded\def\externalfigure
+ {\dotripleempty\doexternalfigure}
+
+\def\doexternalfigure[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings]
+ {\bgroup
+ \doifelsenothing{#1}
+ {\framed[\c!width=\defaultfigurewidth,\c!height=\defaultfigureheight]{external\\figure\\no name}}
+ {\doifundefinedelse{\??ef\??ef#1}
+ {\useexternalfigure[\s!dummy][#1][#2][#3]%
+ \getvalue{\??ef\??ef\s!dummy}[]} % [] is dummy arg 5
+ {\doifassignmentelse{#2}
+ {\getvalue{\??ef\??ef#1}[#2]}%
+ {\getvalue{\??ef\??ef#1}[#3]}}}%
+ \globallet\currentresourcecomment\empty
+ \egroup}
+
+\long\def\resourcecomment#1%
+ {\long\gdef\currentresourcecomment{#1}}
+
+\long\unexpanded\def\startresourcecomment#1\stopresourcecomment
+ {\long\gdef\currentresourcecomment{#1}}
+
+\let\currentresourcecomment\empty
+
+\def\showexternalfigures % maybe run time command is better, but no core-run, unless figs-run ...
+ {%\writestatus\m!systems{for \string\showexternalfigures\space see \truefilename{x-res-20}.tex}
+ \usemodule[res-20]\showexternalfigures} % so for the moment we do it this way
+
+\def\overlayfigure#1%
+ {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]}
+
+%D Still undocumented! No one uses it I think, better be done with layers.
+
+% when there is need for this i'll reimplement it
+%
+% \newcount\efreference
+% \newdimen\efxsteps
+% \newdimen\efysteps
+%
+% \def\calculateefsteps
+% {\ifnum0\@@exxmax=\zerocount
+% \ifnum0\@@exymax=\zerocount
+% \def\@@exymax{24}%
+% \fi
+% \efysteps\figureheight \divide\efysteps \@@exymax
+% \efxsteps\efysteps
+% \dimen0=\figurewidth
+% \advance\dimen0 \efysteps
+% \divide \dimen0 \efysteps
+% \edef\@@exxmax{\number\dimen0}%
+% \else
+% \efxsteps\figurewidth \divide\efxsteps \@@exxmax
+% \efysteps\figureheight \divide\efysteps \@@exymax
+% \fi}
+%
+% \def\efcomment#1(#2,#3)#4(#5,#6)% {kader}(x,y)(h,b)[...]{tekst}
+% {\def\complexefdocomment[##1]##2%
+% {\position(#2,#3)%
+% {\setnostrut
+% \framed
+% [\c!width=#5\efxsteps,
+% \c!height=#6\exysteps,
+% \c!offset=\v!none,
+% \c!frame=#1,
+% ##1]%
+% {##2}}}%
+% \complexorsimpleempty\efdocomment}
+%
+% \def\efnocomment(#1,#2)#3(#4,#5)% (x,y)(h,b)[...]{tekst}
+% {\def\complexefdonocomment[##1]##2{}%
+% \complexorsimpleempty\efdonocomment}
+%
+% \def\efdomarker(#1,#2)#3#4% (h,b){kader}{tekst}
+% {\framed
+% [\c!width=#1\efxsteps,
+% \c!height=#2\efysteps,
+% \c!offset=\v!none,
+% \c!frame=#3]%
+% {#4}}
+%
+% \def\effigure#1%
+% {\position(0,0){\getvalue{#1}}}
+%
+% \def\efdoarea(#1,#2)#3#4% (h,b){kader}{tekst}
+% {\bgroup
+% \setnostrut
+% \framed
+% [\c!width=#1\efxsteps,
+% \c!height=#2\efysteps,
+% \c!offset=\!!zeropoint,
+% \c!frame=#3]
+% {#4}%
+% \egroup}
+%
+% \def\efgoto(#1,#2)#3[#4]% (h,b)kader[ref]
+% {\setbox0=\vbox{\efdoarea(#1,#2)#3{}}%
+% \gotobox{\copy0}[#4]}
+%
+% \def\efmark(#1,#2)#3(#4,#5)#6[#7]%
+% {\advance\efreference \plusone
+% \position(#1,#2)
+% {\hbox{\the\efreference}}%
+% \position(#1,#2)
+% {\gotosomeinternal\s!vwb{#7}\realfolio
+% {\efdomarker(#4,#5)\v!on{\thisissomeinternal\s!vwa{#7}}}}}
+%
+% \def\eftext#1(#2,#3)#4(#5,#6)#7[#8]%
+% {\advance\efreference \plusone
+% \hbox
+% {\quad
+% \thisissomeinternal\s!vwb{#8}%
+% \gotosomeinternal \s!vwa{#8}\realfolio
+% {\hbox to 1.5em{\the\efreference\presetgoto\hfill}}%
+% \quad#1 (#2,#3) (#5,#6) [#8]\hfill}%
+% \endgraf}
+%
+% \def\efthisis(#1,#2)#3[#4]%
+% {\efdoarea(#1,#2){#3}{\pagereference[#4]}}
+
+\newbox\colorbarbox
+
+\def\makecolorbar[#1]%
+ {\def\docommand##1%
+ {\color[##1]
+ {\blackrule
+ [\c!width=2em,
+ \c!height=1ex,
+ \c!depth=\!!zeropoint]}%
+ \endgraf}%
+ \global\setbox\colorbarbox\vbox
+ {\forgetall
+ \processcommalist[#1]\docommand}%
+ \global\setbox\colorbarbox\vbox
+ {\hskip2em\box\colorbarbox}%
+ \global\wd\colorbarbox\zeropoint}
+
+\unexpanded\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]%
+ {\hbox
+ {\setbox0\hbox
+ {\useexternalfigure[\s!dummy][#2][#3,#5]%
+ \externalfigure[\s!dummy]}%
+ \calculateefsteps
+ \startpositioning
+ \def\referring(##1,##2)##3(##4,##5)##6[##7]%
+ {\position(##1,##2){\efgoto(##4,##5){\@@exframes}[##7]}}%
+ \def\marking(##1,##2)##3(##4,##5)##6[##7]%
+ {\position(##1,##2){\efthisis(##4,##5){\@@exframes}[##7]}}%
+ \def\remark{\efnocomment}%
+ \def\colorbar##1[##2]{}%
+ \position(0,0){\box0}%
+ \linewidth\onepoint
+ \setuppositioning
+ [\c!unit=pt,
+ \c!xscale=\withoutpt\the\efxsteps,
+ \c!yscale=\withoutpt\the\efysteps,
+ \c!factor=1]%
+ \ignorespaces#4%
+ \def\referring(##1,##2)##3(##4,##5)##6[##7]%
+ {}%
+ \let\marking\referring
+ \def\remark{\efcomment\v!no}%
+ \def\colorbar##1[##2]{\makecolorbar[##2]}%
+ \ignorespaces#4%
+ \stoppositioning
+ \box\colorbarbox}}
+
+\def\dodostartfigure[#1][#2][#3]#4\stopfigure
+ {\doifelse\v!test\@@exoption
+ {\teststartfigure[#1][#2][#3]#4\teststopfigure
+ \let\@@exframes\v!on}
+ {\let\@@exframes\v!off}%
+ \setvalue{\??ef\??ef#1}%
+ {\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}%
+ }% no longer \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
+
+% De onderstaande macro mag niet zondermeer worden aangepast
+% en is afgestemd op gebruik in de handleiding.
+
+\def\teststartfigure[#1][#2][#3]#4\teststopfigure%
+ {\begingroup
+ \setbox0\hbox
+ {\useexternalfigure[\s!dummy][#2][\c!wfactor=\v!max]%
+ \externalfigure[\s!dummy]}%
+ \def\referring{\efmark}%
+ \def\marking{\efmark}%
+ \def\remark{\efcomment\v!yes}%
+ \def\colorbar##1[##2]{}%
+ \efreference\zerocount
+ \setbox0\vbox
+ {\hsize240pt
+ \startpositioning
+ \calculateefsteps
+ \position(0,0)
+ {\box0}%
+ \position(0,0)
+ {\basegrid
+ [\c!nx=\@@exxmax,
+ \c!dx=\withoutpt\the\efxsteps,
+ \c!ny=\@@exymax,
+ \c!dy=\withoutpt\the\efysteps,
+ \c!xstep=1,
+ \c!ystep=1,
+ \c!scale=1,
+ \c!offset=\v!no,
+ \c!unit=pt]}%
+ \setuppositioning
+ [\c!unit=pt,
+ \c!xscale=\withoutpt\the\efxsteps,
+ \c!yscale=\withoutpt\the\efysteps,
+ \c!factor=1]%
+ \linewidth\onepoint
+ \ignorespaces#4\relax
+ \stoppositioning
+ \vfill}%
+ \efreference\zerocount
+ \def\referring{\eftext{$\rightarrow$}}%
+ \def\marking{\eftext{$\leftarrow$}}%
+ \def\remark{\efnocomment}%
+ \def\colorbar##1[##2]{}%
+ \setbox2\vbox
+ {{\tfa\doifelsenothing{#1}{#2}{#1}}
+ \blank
+ \tfxx#4
+ \vfilll}%
+ \ifdim\ht0>\ht2
+ \ht2\ht0
+ \else
+ \ht0\ht2
+ \fi
+ \hbox
+ {\hskip3em
+ \vtop{\vskip12pt\box0\vskip6pt}%
+ \vtop{\vskip12pt\box2\vskip6pt}}%
+ \endgroup}
+
+\def\dodostartfigure[#1][#2][#3]#4\stopfigure
+ {\doifelse\v!test\@@exoption
+ {\teststartfigure[#1][#2][#3]#4\teststopfigure
+ \let\@@exframe\v!on}
+ {\let\@@exframe\v!off}%
+ \setvalue{\??ef\??ef#1}%
+ {\def\next{\placestartfigure[#1][#2][#3]#4\placestopfigure}%
+ \dosingleempty\next}%
+ }% no longer: \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
+
+\long\def\dostartfigure#1%
+ {\dotripleargument\dodostartfigure#1\stopfigure}
+
+\unexpanded\def\startfigure
+ {\grabuntil{\e!stop\v!figure}\dostartfigure}
+
+%D NEW: used in styledesign manual
+
+% beware in mkiv we don't have the typeset- prefix
+%
+% \setbuffer[typeset-b]\endbuffer
+% \setbuffer[typeset-a]\endbuffer
+%
+% todo:
+%
+% \appendtoks \setbuffer[typeset-b]\endbuffer\to \everystarttext
+% \appendtoks \setbuffer[typeset-a]\endbuffer\to \everystarttext
+
+\newcount\noftypesetbuffers
+
+\def\typesetbuffer
+ {\dodoubleempty\dotypesetbuffer}
+
+\def\dotypesetbuffer[#1][#2]% beware: this will mix up the mp graphics
+ {\ifsecondargument
+ \dodotypesetbuffer[#1][#2]%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\dodotypesetbuffer[\jobname][#1]}%
+ {\dodotypesetbuffer[#1][]}%
+ \else
+ \dodotypesetbuffer[\jobname][]
+ \fi\fi}
+
+% \def\dodotypesetbuffer[#1][#2]%
+% {\bgroup
+% \global\advance\noftypesetbuffers\plusone
+% \edef\bufferfilename{\jobname-buffer-\the\noftypesetbuffers}%
+% \doifmode{*\v!first}
+% {\ctxlua{buffers.save("\bufferfilename.tmp","#1",true)}%
+% \executesystemcommand{context \bufferfilename.tmp}}%
+% \externalfigure[\bufferfilename.pdf][#2]%
+% \egroup}
+
+\def\dodotypesetbuffer[#1][#2]%
+ {\bgroup
+ \global\advance\noftypesetbuffers\plusone
+ \edef\bufferfilename{\jobname-buffer-\the\noftypesetbuffers}%
+ \ctxlua{buffers.run("\bufferfilename.tmp","#1",true)}%
+ \externalfigure[\bufferfilename.pdf][#2]%
+ \egroup}
+
+\def\dodotypesetbufferindeed#1%
+ {}
+
+% for me only (manuals and such)
+%
+% \definetypesetting [name] [options] [settings-a]
+%
+% \typesetfile [name] [file] [settings-b]
+% \typesetfile [file] [options] [settings-b]
+% \typesetfile [file] [settings-b]
+% \typesetfile [file]
+%
+% \enabletrackers[files.run]
+% \starttext
+% \typesetfile[oepsoeps.tex][width=10cm,frame=on]
+% \stoptext
+
+\definesystemvariable{tz}
+
+\unexpanded\def\definetypesetting{\dotripleempty\dodefinetypesetting}
+\def\typesetfile {\dotripleempty\dotypesetfile}
+
+\unexpanded\def\definetypesetting{\dotripleempty\dodefinetypesetting}
+\def\typesetfile {\dotripleempty\dotypesetfile}
+
+\def\dodefinetypesetting[#1][#2][#3]% options settings-a
+ {\doifsomething{#1}{\setvalue{\??tz#1}{\dodotypesetfile{#2}{#3}}}}
+
+\def\dotypesetfile[#1][#2][#3]% filename settings-b | filename options settings
+ {\ifcsname\??tz#1\endcsname
+ \csname\??tz#1\endcsname{#2}{#3}%
+ \else\ifthirdargument % filename options settings
+ \dodotypesetfile{#2}{#3}{#1}{}%
+ \else\ifsecondargument % filename settings
+ \dodotypesetfile{}{#2}{#1}{}%
+ \fi\fi\fi}
+
+\def\dodotypesetfile#1#2#3#4% options settings-a filename settings-b
+ {\edef\typesetfilename{\ctxlua{tex.write(jobfiles.run("#3","#1"))}}%
+ \expanded{\externalfigure[\typesetfilename]}[#2,#4]}
+
+\setupexternalfigures
+ [\c!option=,
+ \c!object=\v!yes, % we only check for no
+ \c!reset=\v!no,
+ \c!maxwidth=\@@efwidth,
+ \c!maxheight=\@@efheight,
+ \c!bodyfont=\bodyfontsize,
+ \c!directory=,
+ \c!file=\f!utilityfilename.\f!figureextension,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ \c!frame=\v!off,
+ \c!background=, % new
+ \c!splitcolor=\s!white,
+ \c!conversion=,
+ \c!prefix=,
+ \c!cache=,
+% \c!grid=,
+ \c!equalwidth=,
+ \c!equalheight=,
+ \c!location={\v!local,\v!global}]
+
+\setupexternalfigures
+ [\c!frames=\v!off,
+ \c!ymax=24,
+ \c!xmax=]
+
+\useexternalfigure
+ [buffer] [\jobname.buffer] [\c!object=\v!no]
+
+\protect \endinput
+
+% alternative for positioning
+
+% \definelayer[figure][width=\overlaywidth,height=\overlayheight]
+% \defineoverlay[figure][{\directsetup{figure}\tightlayer[figure]}]
+
+% \setupcolors[state=start]
+
+% \starttext
+
+% \startsetups figure
+% \setlayerframed[figure][preset=rightbottom,x=.25\layerwidth,y=.25\layerheight]{HERE}
+% \setlayerframed[figure][preset=leftbottom, x=.15\layerwidth,y=.35\layerheight]{THERE}
+% \stopsetups
+
+% \externalfigure[cow][background={foreground,figure},width=4cm,height=8cm]
+
+% \startsetups figure
+% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{MORE}
+% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE}
+% \stopsetups
+
+% \externalfigure[cow][background={foreground,figure},width=14cm,height=2cm]
+
+% \defineexternalfigure[whatever][background={foreground,figure}]
+
+% \startsetups figure
+% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{\red MORE}
+% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE}
+% \stopsetups
+
+% \externalfigure[cow][whatever][width=14cm,height=4cm]
+
+% \stoptext
+
diff --git a/tex/context/base/grph-fil.lua b/tex/context/base/grph-fil.lua
new file mode 100644
index 000000000..2e32c7a60
--- /dev/null
+++ b/tex/context/base/grph-fil.lua
@@ -0,0 +1,42 @@
+if not modules then modules = { } end modules ['grph-fil'] = {
+ version = 1.001,
+ comment = "companion to grph-fig.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, concat = string.format, table.concat
+
+local trace_run = false trackers.register("files.run",function(v) trace_run = v end)
+
+local command = "context %s"
+
+jobfiles = jobfiles or { }
+jobfiles.collected = jobfiles.collected or { }
+jobfiles.tobesaved = jobfiles.tobesaved or { }
+
+local tobesaved, collected = jobfiles.tobesaved, jobfiles.collected
+
+local function initializer()
+ tobesaved, collected = jobfiles.tobesaved, jobfiles.collected
+end
+
+job.register('jobfiles.collected', jobfiles.tobesaved, initializer)
+
+jobfiles.forcerun = false
+
+function jobfiles.run(name,...)
+ local oldchecksum = collected[name]
+ local newchecksum = file.checksum(name)
+ if jobfiles.forcerun or not oldchecksum or oldchecksum ~= newchecksum then
+ if trace_run then
+ commands.writestatus("buffers","changes in '%s', processing forced",name)
+ end
+ os.execute(format(command,concat({ name, ... }," ")))
+ elseif trace_run then
+ commands.writestatus("buffers","no changes in '%s', not processed",name)
+ end
+ tobesaved[name] = newchecksum
+ return file.replacesuffix(name,"pdf")
+end
diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua
new file mode 100644
index 000000000..508240a3b
--- /dev/null
+++ b/tex/context/base/grph-inc.lua
@@ -0,0 +1,1115 @@
+if not modules then modules = { } end modules ['grph-inc'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- lowercase types
+-- mps tex tmp svg
+-- partly qualified
+-- dimensions
+-- consult rlx
+
+-- figures.boxnumber can go as we now can use names
+
+--[[
+The ConTeXt figure inclusion mechanisms are among the oldest code
+in ConTeXt and evolve dinto a complex whole. One reason is that we
+deal with backend in an abstract way. What complicates matters is
+that we deal with internal graphics as well: TeX code, MetaPost code,
+etc. Later on figure databases were introduced, which resulted in
+a plug in model for locating images. On top of that runs a conversion
+mechanism (with caching) and resource logging.
+
+Porting that to Lua is not that trivial because quite some
+status information is kept between al these stages. Of course, image
+reuse also has some price, and so I decided to implement the graphics
+inclusion in several layers: detection, loading, inclusion, etc.
+
+Object sharing and scaling can happen at each stage, depending on the
+way the resource is dealt with.
+
+The TeX-Lua mix is suboptimal. This has to do with the fact that we cannot
+run TeX code from within Lua. Some more functionality will move to Lua.
+]]--
+
+local format, lower, find, match, gsub, gmatch = string.format, string.lower, string.find, string.match, string.gsub, string.gmatch
+local texsprint, texbox = tex.sprint, tex.box
+local contains = table.contains
+local concat = table.concat
+local todimen = string.todimen
+
+local ctxcatcodes = tex.ctxcatcodes
+local variables = interfaces.variables
+
+local trace_figures = false trackers.register("figures.locating", function(v) trace_figures = v end)
+local trace_bases = false trackers.register("figures.bases", function(v) trace_bases = v end)
+local trace_programs = false trackers.register("figures.programs", function(v) trace_programs = v end)
+local trace_conversion = false trackers.register("figures.conversion", function(v) trace_conversion = v end)
+local trace_inclusion = false trackers.register("figures.inclusion", function(v) trace_inclusion = v end)
+
+--- some extra img functions ---
+
+local imgkeys = img.keys()
+
+function img.totable(imgtable)
+ local result = { }
+ for k=1,#imgkeys do
+ local key = imgkeys[k]
+ result[key] = imgtable[key]
+ end
+ return result
+end
+
+function img.serialize(i)
+ return table.serialize(img.totable(i))
+end
+
+function img.clone(i,data)
+ i.width = data.width or i.width
+ i.height = data.height or i.height
+ -- attr etc
+ return i
+end
+
+local validsizes = table.tohash(img.boxes())
+local validtypes = table.tohash(img.types())
+
+function img.check_size(size)
+ if size then
+ size = gsub(size,"box","")
+ return (validsizes[size] and size) or "crop"
+ else
+ return "crop"
+ end
+end
+
+---
+
+figures = figures or { }
+figures.loaded = figures.loaded or { }
+figures.used = figures.used or { }
+figures.found = figures.found or { }
+figures.suffixes = figures.suffixes or { }
+figures.patterns = figures.patterns or { }
+figures.boxnumber = figures.boxnumber or 0
+figures.defaultsearch = true
+figures.defaultwidth = 0
+figures.defaultheight = 0
+figures.defaultdepth = 0
+figures.n = 0
+figures.prefer_quality = true -- quality over location
+
+figures.localpaths = {
+ ".", "..", "../.."
+}
+figures.cachepaths = {
+ prefix = "",
+ path = ".",
+ subpath = ".",
+}
+
+figures.paths = table.copy(figures.localpaths)
+
+figures.order = {
+ "pdf", "mps", "jpg", "png", "jbig", "svg", "eps", "gif", "mov", "buffer", "tex",
+}
+
+figures.formats = {
+ ["pdf"] = { list = { "pdf" } },
+ ["mps"] = { patterns = { "mps", "%d+" } },
+ ["jpg"] = { list = { "jpg", "jpeg" } },
+ ["png"] = { list = { "png" } },
+ ["jbig"] = { list = { "jbig", "jbig2", "jb2" } },
+ ["svg"] = { list = { "svg", "svgz" } },
+ ["eps"] = { list = { "eps", "ai" } },
+ ["gif"] = { list = { "gif" } },
+ ["mov"] = { list = { "mov", "avi" } },
+ ["buffer"] = { list = { "tmp", "buffer", "buf" } },
+ ["tex"] = { list = { "tex" } },
+}
+
+function figures.setlookups()
+ figures.suffixes, figures.patterns = { }, { }
+ for _, format in next, figures.order do
+ local data = figures.formats[format]
+ local fs, fp = figures.suffixes, figures.patterns
+ local list = data.list
+ if list then
+ for i=1,#list do
+ fs[list[i]] = format -- hash
+ end
+ else
+ fs[format] = format
+ end
+ local patterns = data.patterns
+ if patterns then
+ for i=1,#patterns do
+ fp[#fp+1] = { patterns[i], format } -- array
+ end
+ end
+ end
+end
+
+figures.setlookups()
+
+local function register(tag,target,what)
+ local data = figures.formats[target] -- resolver etc
+ if not data then
+ data = { }
+ figures.formats[target] = data
+ end
+ local d = data[tag] -- list or pattern
+ if d and not contains(d,what) then
+ d[#d+1] = what -- suffix or patternspec
+ else
+ data[tag] = { what }
+ end
+ if not contains(figures.order,target) then
+ figures.order[#figures.order+1] = target
+ end
+ figures.setlookups()
+end
+
+function figures.registersuffix (suffix, target) register('list', target,suffix ) end
+function figures.registerpattern(pattern,target) register('pattern',target,pattern) end
+
+local last_locationset, last_pathlist = last_locationset or nil, last_pathlist or nil
+
+function figures.setpaths(locationset,pathlist)
+ if last_locationset == locationset and last_pathlist == pathlist then
+ -- this function can be called each graphic so we provide this optimization
+ return
+ end
+ local iv, t, h = interfaces.variables, figures.paths, locationset:tohash()
+ if last_locationset ~= locationset then
+ -- change == reset (actually, a 'reset' would indeed reset
+ if h[iv["local"]] then
+ t = table.fastcopy(figures.localpaths or { })
+ else
+ t = { }
+ end
+ figures.defaultsearch = h[iv["default"]]
+ last_locationset = locationset
+ end
+ if h[iv["global"]] then
+ -- for s in gmatch(pathlist,",* *([^,]+)") do
+ local list = aux.settings_to_array(pathlist)
+ for i=1,#list do
+ local s = list[i]
+ if not contains(t,s) then
+ t[#t+1] = s
+ end
+ end
+ end
+ figures.paths, last_pathlist = t, pathlist
+ if trace_figures then
+ commands.writestatus("figures","locations: %s",last_locationset)
+ commands.writestatus("figures","path list: %s",concat(figures.paths, " "))
+ end
+end
+
+-- check conversions and handle it here
+
+function figures.hash(data)
+ return data.status.hash or tostring(data.status.private) -- the
+-- return data.status.fullname .. "+".. (data.status.page or data.request.page or 1) -- img is still not perfect
+end
+
+-- interfacing to tex
+
+do
+
+ local figuredata = { }
+ local callstack = { }
+
+ function figures.new()
+ figuredata = {
+ request = {
+ name = false,
+ label = false,
+ format = false,
+ page = false,
+ width = false,
+ height = false,
+ preview = false,
+ ["repeat"] = false,
+ controls = false,
+ display = false,
+ conversion = false,
+ cache = false,
+ prefix = false,
+ size = false,
+ },
+ used = {
+ fullname = false,
+ format = false,
+ name = false,
+ path = false,
+ suffix = false,
+ width = false,
+ height = false,
+ },
+ status = {
+ status = 0,
+ converted = false,
+ cached = false,
+ fullname = false,
+ format = false,
+ },
+ }
+ return figuredata
+ end
+
+ function figures.push(request)
+ local ncs = #callstack + 1
+ if ncs == 1 then
+ statistics.starttiming(figures)
+ end
+ local figuredata = figures.new()
+ if request then
+ local iv = interfaces.variables
+ -- request.width/height are strings and are only used when no natural dimensions
+ -- can be determined; at some point the handlers might set them to numbers instead
+ -- local w, h = tonumber(request.width), tonumber(request.height)
+ request.page = math.max(tonumber(request.page) or 1,1)
+ request.size = img.check_size(request.size)
+ request.object = iv[request.object] == variables.yes
+ request["repeat"] = iv[request["repeat"]] == variables.yes
+ request.preview = iv[request.preview] == variables.yes
+ request.cache = request.cache ~= "" and request.cache
+ request.prefix = request.prefix ~= "" and request.prefix
+ request.format = request.format ~= "" and request.format
+ -- request.width = (w and w > 0) or false
+ -- request.height = (h and h > 0) or false
+ table.merge(figuredata.request,request)
+ end
+ callstack[ncs] = figuredata
+ return figuredata
+ end
+ function figures.pop()
+ local ncs = #callstack
+ figuredata = callstack[ncs]
+ callstack[ncs] = nil
+ if ncs == 1 then
+ statistics.stoptiming(figures)
+ end
+ end
+ -- maybe move texsprint to tex
+ function figures.get(category,tag,default)
+ local value = figuredata[category]
+ value = value and value[tag]
+ if not value or value == "" or value == true then
+ return default or ""
+ else
+ return value
+ end
+ end
+ function figures.tprint(category,tag,default)
+ texsprint(ctxcatcodes,figures.get(category,tag,default))
+ end
+ function figures.current()
+ return callstack[#callstack]
+ end
+
+end
+
+local defaultformat = "pdf"
+local defaultprefix = "m_k_v_i_"
+
+local function register(askedname,specification)
+ if specification then
+ local format = specification.format
+ if format then
+ local conversion = specification.conversion
+ if conversion == "" then
+ conversion = nil
+ end
+ local newformat = conversion
+ if not newformat or newformat == "" then
+ newformat = defaultformat
+ end
+ local converter = (newformat ~= format) and figures.converters[format]
+ if trace_conversion then
+ logs.report("figures","checking conversion of '%s': old format '%s', new format '%s', conversion '%s'",
+ askedname,format,newformat,conversion or "default")
+ end
+ if converter then
+ if converter[newformat] then
+ converter = converter[newformat]
+ else
+ newformat = defaultformat
+ if converter[newformat] then
+ converter = converter[newformat]
+ else
+ newformat = defaultformat
+ end
+ end
+ end
+ if converter then
+ local oldname = specification.fullname
+ local newpath = file.dirname(oldname)
+ local oldbase = file.basename(oldname)
+ local newbase = file.replacesuffix(oldbase,newformat)
+ local fc = specification.cache or figures.cachepaths.path
+ if fc and fc ~= "" and fc ~= "." then
+ newpath = fc
+ else
+ newbase = defaultprefix .. newbase
+ end
+ local subpath = specification.subpath or figures.cachepaths.subpath
+ if subpath and subpath ~= "" and subpath ~= "." then
+ newpath = newpath .. "/" .. subpath
+ end
+ local prefix = specification.prefix or figures.cachepaths.prefix
+ if prefix and prefix ~= "" then
+ newbase = prefix .. newbase
+ end
+ local newname = file.join(newpath,newbase)
+ dir.makedirs(newpath)
+ oldname = file.collapse_path(oldname)
+ newname = file.collapse_path(newname)
+ local oldtime = lfs.attributes(oldname,'modification') or 0
+ local newtime = lfs.attributes(newname,'modification') or 0
+ if oldtime > newtime then
+ if trace_conversion then
+ logs.report("figures","converting '%s' from '%s' to '%s'",askedname,format,newformat)
+ end
+ converter(oldname,newname)
+ else
+ if trace_conversion then
+ logs.report("figures","no need to convert '%s' from '%s' to '%s'",askedname,format,newformat)
+ end
+ end
+ if io.exists(newname) then
+ specification.foundname = oldname
+ specification.fullname = newname
+ specification.prefix = prefix
+ specification.subpath = subpath
+ specification.converted = true
+ format = newformat
+ elseif io.exists(oldname) then
+ specification.fullname = newname
+ specification.converted = false
+ end
+ end
+ end
+ local found = figures.suffixes[format] -- validtypes[format]
+ if not found then
+ specification.found = false
+ if trace_figures then
+ commands.writestatus("figures","format not supported: %s",format)
+ end
+ else
+ specification.found = true
+ if trace_figures then
+ if validtypes[format] then
+ commands.writestatus("figures","format natively supported by backend: %s",format)
+ else
+ commands.writestatus("figures","format supported by output file format: %s",format)
+ end
+ end
+ end
+ else
+ specification = { }
+ end
+ specification.foundname = specification.foundname or specification.fullname
+ figures.found[askedname .. "->" .. (specification.conversion or "default")] = specification
+ return specification
+end
+
+local resolve_too = true -- urls
+
+local function locate(request) -- name, format, cache
+ local askedname = resolvers.clean_path(request.name)
+ local foundname = figures.found[askedname .. "->" .. (request.conversion or "default")]
+ if foundname then
+ return foundname
+ end
+ -- protocol check
+ local hashed = url.hashed(askedname)
+ if hashed and hashed.scheme ~= "file" then
+ local foundname = resolvers.findbinfile(askedname)
+ if foundname then
+ askedname = foundname
+ end
+ end
+ -- we could use the hashed data instead
+ local askedpath= file.is_rootbased_path(askedname)
+ local askedbase = file.basename(askedname)
+ local askedformat = (request.format ~= "" and request.format ~= "unknown" and request.format) or file.extname(askedname) or ""
+ local askedcache = request.cache
+ local askedconversion = request.conversion
+ if askedformat ~= "" then
+ if trace_figures then
+ commands.writestatus("figures","strategy: forced format")
+ end
+ askedformat = lower(askedformat)
+ local format = figures.suffixes[askedformat]
+ if not format then
+ local figurepatterns = figures.patterns
+ for i=1,#figurepatterns do
+ local pattern = figurepatterns[i]
+ if find(askedformat,pattern[1]) then
+ format = pattern[2]
+ break
+ end
+ end
+ end
+ if format then
+ local foundname = figures.exists(askedname,format,resolve_too) -- not askedformat
+ if foundname then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = askedname,
+ format = format,
+ cache = askedcache,
+ foundname = foundname,
+ conversion = askedconversion,
+ })
+ end
+ end
+ if askedpath then
+ -- path and type given, todo: strip pieces of path
+ if figures.exists(askedname,askedformat,resolve_too) then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = askedname,
+ format = askedformat,
+ cache = askedcache,
+ conversion = askedconversion,
+ })
+ end
+ else
+ -- type given
+ local figurepaths = figures.paths
+ for i=1,#figurepaths do
+ local path = figurepaths[i]
+ local check = path .. "/" .. askedname
+ -- we pass 'true' as it can be an url as well, as the type
+ -- is given we don't waste much time
+ if figures.exists(check,askedformat,resolve_too) then
+ return register(check, {
+ askedname = askedname,
+ fullname = check,
+ format = askedformat,
+ cache = askedcache,
+ conversion = askedconversion,
+ })
+ end
+ end
+ if figures.defaultsearch then
+ local check = resolvers.find_file(askedname)
+ if check and check ~= "" then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = check,
+ format = askedformat,
+ cache = askedcache,
+ conversion = askedconversion,
+ })
+ end
+ end
+ end
+ elseif askedpath then
+ if trace_figures then
+ commands.writestatus("figures","strategy: rootbased path")
+ end
+ local figureorder = figures.order
+ for i=1,#figureorder do
+ local format = figureorder[i]
+ local list = figures.formats[format].list or { format }
+ for j=1,#list do
+ local suffix = list[j]
+ local check = file.addsuffix(askedname,suffix)
+ if figures.exists(check,format,resolve_too) then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = check,
+ format = format,
+ cache = askedcache,
+ conversion = askedconversion,
+ })
+ end
+ end
+ end
+ else
+ if figures.prefer_quality then
+ if trace_figures then
+ commands.writestatus("figures","strategy: unknown format, prefer quality")
+ end
+ local figurepaths = figures.paths
+ local figureorder = figures.order
+ for j=1,#figureorder do
+ local format = figureorder[j]
+ local list = figures.formats[format].list or { format }
+ for k=1,#list do
+ local suffix = list[k]
+ -- local name = file.replacesuffix(askedbase,suffix)
+ local name = file.replacesuffix(askedname,suffix)
+ for i=1,#figurepaths do
+ local path = figurepaths[i]
+ local check = path .. "/" .. name
+ local isfile = url.hashed(check).scheme == "file"
+ if not isfile then
+ if trace_figures then
+ commands.writestatus("figures","warning: skipping path %s",path)
+ end
+ elseif figures.exists(check,format,true) then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = check,
+ format = format,
+ cache = askedcache,
+ conversion = askedconversion,
+ })
+ end
+ end
+ end
+ end
+ else -- 'location'
+ if trace_figures then
+ commands.writestatus("figures","strategy: unknown format, prefer path")
+ end
+ local figurepaths = figures.paths
+ local figureorder = figures.order
+ for i=1,#figurepaths do
+ local path = figurepaths[i]
+ for j=1,#figureorder do
+ local format = figureorder[j]
+ local list = figures.formats[format].list or { format }
+ for k=1,#list do
+ local suffix = list[k]
+ local check = path .. "/" .. file.replacesuffix(askedbase,suffix)
+ if figures.exists(check,format,resolve_too) then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = check,
+ format = format,
+ cache = askedcache,
+ conversion = askedconversion,
+ })
+ end
+ end
+ end
+ end
+ end
+ if figures.defaultsearch then
+ if trace_figures then
+ commands.writestatus("figures","strategy: default tex path")
+ end
+ local figureorder = figures.order
+ for j=1,#figureorder do
+ local format = figureorder[j]
+ local list = figures.formats[format].list or { format }
+ for k=1,#list do
+ local suffix = list[k]
+ local check = resolvers.find_file(file.replacesuffix(askedname,suffix))
+ if check and check ~= "" then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = check,
+ format = format,
+ cache = askedcache,
+ conversion = askedconversion,
+ })
+ end
+ end
+ end
+ end
+ end
+ return register(askedname)
+end
+
+-- -- -- plugins -- -- --
+
+figures.existers = figures.existers or { }
+figures.checkers = figures.checkers or { }
+figures.includers = figures.includers or { }
+figures.converters = figures.converters or { }
+figures.identifiers = figures.identifiers or { }
+figures.programs = figures.programs or { }
+
+figures.identifiers.list = {
+ figures.identifiers.default
+}
+
+function figures.identifiers.default(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local l = locate(dr)
+ local foundname = l.foundname
+ local fullname = l.fullname or foundname
+ if fullname then
+ du.format = l.format or false
+ du.fullname = fullname -- can be cached
+ ds.fullname = foundname -- original
+ ds.format = l.format
+ ds.status = (l.found and 10) or 0
+ end
+ return data
+end
+
+function figures.identify(data)
+ data = data or figures.current()
+ local list = figures.identifiers.list
+ for i=1,#list do
+ local identifier = list[i]
+ data = identifier(data)
+ if data.status.status > 0 then
+ break
+ end
+ end
+ return data
+end
+function figures.exists(askedname,format,resolve)
+ return (figures.existers[format] or figures.existers.generic)(askedname,resolve)
+end
+function figures.check(data)
+ data = data or figures.current()
+ local dr, du, ds = data.request, data.used, data.status
+ return (figures.checkers[ds.format] or figures.checkers.generic)(data)
+end
+function figures.include(data)
+ data = data or figures.current()
+ local dr, du, ds = data.request, data.used, data.status
+ return (figures.includers[ds.format] or figures.includers.generic)(data)
+end
+function figures.scale(data) -- will become lua code
+ texsprint(ctxcatcodes,"\\doscalefigure")
+ return data
+end
+function figures.done(data)
+ figures.n = figures.n + 1
+ data = data or figures.current()
+--~ print(table.serialize(figures.current()))
+ local dr, du, ds, nr = data.request, data.used, data.status, figures.boxnumber
+ local box = texbox[nr]
+ ds.width = box.width
+ ds.height = box.height
+ ds.xscale = ds.width /(du.width or 1)
+ ds.yscale = ds.height/(du.height or 1)
+--~ print(table.serialize(figures.current()))
+ return data
+end
+
+function figures.dummy(data)
+ data = data or figures.current()
+ local dr, du, ds, nr = data.request, data.used, data.status, figures.boxnumber
+ local box = node.hpack(node.new("hlist")) -- we need to set the dir (luatex 0.60 buglet)
+ du.width = du.width or figures.defaultwidth
+ du.height = du.height or figures.defaultheight
+ du.depth = du.depth or figures.defaultdepth
+ -- box.dir = "TLT"
+ box.width = du.width
+ box.height = du.height
+ box.depth = du.depth
+ texbox[nr] = box -- hm, should be global (to be checked for consistency)
+end
+
+-- -- -- generic -- -- --
+
+function figures.existers.generic(askedname,resolve)
+ -- not findbinfile
+ local result
+ if lfs.isfile(askedname) then
+ result = askedname
+ elseif resolve then
+ result = resolvers.findbinfile(askedname) or ""
+ if result == "" then result = false end
+ end
+ if trace_figures then
+ if result then
+ commands.writestatus("figures","found: %s -> %s",askedname,result)
+ else
+ commands.writestatus("figures","not found: %s",askedname)
+ end
+ end
+ return result
+end
+function figures.checkers.generic(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local name, page, size, color = du.fullname or "unknown generic", du.page or dr.page, dr.size or "crop", dr.color or "natural"
+ local conversion = dr.conversion
+ if not conversion or conversion == "" then
+ conversion = "unknown"
+ end
+ local hash = name .. "->" .. page .. "->" .. size .. "->" .. color .. "->" .. conversion
+ local figure = figures.loaded[hash]
+ if figure == nil then
+ figure = img.new { filename = name, page = page, pagebox = dr.size }
+ backends.codeinjections.setfigurecolorspace(data,figure)
+ figure = (figure and img.scan(figure)) or false
+ local f, d = backends.codeinjections.setfigurealternative(data,figure)
+ figure, data = f or figure, d or data
+ figures.loaded[hash] = figure
+ if trace_conversion then
+ logs.report("figures","new graphic, hash: %s",hash)
+ end
+ else
+ if trace_conversion then
+ logs.report("figures","existing graphic, hash: %s",hash)
+ end
+ end
+ if figure then
+ du.width = figure.width
+ du.height = figure.height
+ du.pages = figure.pages
+ ds.private = figure
+ ds.hash = hash
+ end
+ return data
+end
+function figures.includers.generic(data)
+ local dr, du, ds = data.request, data.used, data.status
+ -- here we set the 'natural dimensions'
+ dr.width = du.width
+ dr.height = du.height
+ local hash = figures.hash(data)
+ local figure = figures.used[hash]
+ if figure == nil then
+ figure = ds.private
+ if figure then
+ figure = img.copy(figure)
+ figure = (figure and img.clone(figure,data.request)) or false
+ end
+ figures.used[hash] = figure
+ end
+ if figure then
+ local nr = figures.boxnumber
+ -- it looks like we have a leak in attributes here .. todo
+ local box = node.hpack(img.node(figure)) -- img.node(figure) not longer valid
+ box.width, box.height, box.depth = figure.width, figure.height, 0 -- new, hm, tricky, we need to do that in tex (yet)
+ texbox[nr] = box
+ ds.objectnumber = figure.objnum
+ texsprint(ctxcatcodes,"\\relocateexternalfigure")
+ end
+ return data
+end
+
+-- -- -- nongeneric -- -- --
+
+function figures.checkers.nongeneric(data,command)
+ local dr, du, ds = data.request, data.used, data.status
+ local name = du.fullname or "unknown nongeneric"
+ local hash = name
+ if dr.object then
+ -- hm, bugged
+ if not jobobjects.get("FIG::"..hash) then
+ texsprint(ctxcatcodes,command)
+ texsprint(ctxcatcodes,format("\\setobject{FIG}{%s}\\vbox{\\box\\foundexternalfigure}",hash))
+ end
+ texsprint(ctxcatcodes,format("\\global\\setbox\\foundexternalfigure\\vbox{\\getobject{FIG}{%s}}",hash))
+ else
+ texsprint(ctxcatcodes,command)
+ end
+ return data
+end
+function figures.includers.nongeneric(data)
+ return data
+end
+
+-- -- -- mov -- -- --
+
+function figures.checkers.mov(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local width = todimen(dr.width or figures.defaultwidth)
+ local height = todimen(dr.height or figures.defaultheight)
+ local foundname = du.fullname
+ dr.width, dr.height = width, height
+ du.width, du.height, du.foundname = width, height, foundname
+ if trace_inclusion then
+ logs.report("figures","including movie '%s': width %s, height %s",foundname,width,height)
+ end
+ -- we need to push the node.write in between ... we could make a shared helper for this
+ context.startfoundexternalfigure(width .. "sp",height .. "sp")
+ context(function()
+ backends.codeinjections.insertmovie {
+ width = width,
+ height = height,
+ factor = number.dimenfactors.bp,
+ ["repeat"] = dr["repeat"],
+ controls = dr.controls,
+ preview = dr.preview,
+ label = dr.label,
+ foundname = foundname,
+ }
+ end)
+ context.stopfoundexternalfigure()
+ return data
+end
+
+figures.includers.mov = figures.includers.nongeneric
+
+-- -- -- mps -- -- --
+
+local function internal(askedname)
+ local spec, mprun, mpnum = match(lower(askedname),"mprun(:?)(.-)%.(%d+)")
+ if spec == ":" then
+ return mprun, mpnum
+ else
+ return "", mpnum
+ end
+end
+
+function figures.existers.mps(askedname)
+ local mprun, mpnum = internal(askedname)
+ if mpnum then
+ return askedname
+ else
+ return figures.existers.generic(askedname)
+ end
+end
+function figures.checkers.mps(data)
+ local mprun, mpnum = internal(data.used.fullname)
+ if mpnum then
+ return figures.checkers.nongeneric(data,format("\\docheckfiguremprun{%s}{%s}",mprun,mpnum))
+ else
+ return figures.checkers.nongeneric(data,format("\\docheckfiguremps{%s}",data.used.fullname))
+ end
+end
+figures.includers.mps = figures.includers.nongeneric
+
+-- -- -- buffer -- -- --
+
+function figures.existers.buffer(askedname)
+ askedname = file.nameonly(askedname)
+ return buffers.exists(askedname) and askedname
+end
+function figures.checkers.buffer(data)
+ return figures.checkers.nongeneric(data,format("\\docheckfigurebuffer{%s}", file.nameonly(data.used.fullname)))
+end
+figures.includers.buffers = figures.includers.nongeneric
+
+-- -- -- tex -- -- --
+
+function figures.existers.tex(askedname)
+ askedname = resolvers.find_file(askedname)
+ return (askedname ~= "" and askedname) or false
+end
+function figures.checkers.tex(data)
+ return figures.checkers.nongeneric(data,format("\\docheckfiguretex{%s}", data.used.fullname))
+end
+figures.includers.tex = figures.includers.nongeneric
+
+-- -- -- converters -- -- --
+
+local function makeoptions(program)
+ local to = type(options)
+ return (to == "table" and concat(options," ")) or (to == "string" and options) or ""
+end
+
+local function runprogram(...)
+ local command = format(...)
+ if trace_conversion or trace_programs then
+ logs.report("figures","running %s",command)
+ end
+ os.spawn(command)
+end
+
+-- -- -- eps -- -- --
+
+local epsconverter = { }
+figures.converters.eps = epsconverter
+
+figures.programs.gs = {
+ options = {
+ "-dAutoRotatePages=/None",
+ "-dPDFSETTINGS=/prepress",
+ "-dEPSCrop",
+ },
+ command = (os.type == "windows" and "gswin32") or "gs"
+}
+
+function epsconverter.pdf(oldname,newname)
+ local gs = figures.programs.gs
+ runprogram (
+ '%s -q -sDEVICE=pdfwrite -dNOPAUSE -dNOCACHE -dBATCH %s -sOutputFile="%s" "%s" -c quit',
+ gs.command, makeoptions(gs.options), newname, oldname
+ )
+end
+
+epsconverter.default = epsconverter.pdf
+
+-- -- -- svg -- -- --
+
+local svgconverter = { }
+figures.converters.svg = svgconverter
+figures.converters.svgz = svgconverter
+
+-- inkscape on windows only works with complete paths
+
+figures.programs.inkscape = {
+ options = {
+ "--export-dpi=600"
+ },
+ command = "inkscape"
+}
+
+function svgconverter.pdf(oldname,newname)
+ local inkscape = figures.programs.inkscape
+ runprogram (
+ '%s "%s" --export-pdf="%s" %s',
+ inkscape.command, oldname, newname, makeoptions(inkscape.options)
+ )
+end
+
+function svgconverter.png(oldname,newname)
+ local inkscape = figures.programs.inkscape
+ runprogram (
+ '%s "%s" --export-png="%s" %s',
+ inkscape.command, oldname, newname, makeoptions(inkscape.options)
+ )
+end
+
+svgconverter.default = svgconverter.pdf
+
+-- -- -- gif -- -- --
+
+local gifconverter = { }
+figures.converters.gif = gifconverter
+
+figures.programs.convert = {
+ command = "convert" -- imagemagick
+}
+
+function gifconverter.pdf(oldname,newname)
+ local convert = figures.programs.convert
+ runprogram (
+ "convert %s %s",
+ convert.command, makeoptions(convert.options), oldname, newname
+ )
+end
+
+gifconverter.default = gifconverter.pdf
+
+-- todo: lowres
+
+-- -- -- bases -- -- --
+
+figures.bases = { }
+figures.bases.list = { } -- index => { basename, fullname, xmlroot }
+figures.bases.used = { } -- [basename] => { basename, fullname, xmlroot } -- pointer to list
+figures.bases.found = { }
+figures.bases.enabled = false
+
+local bases = figures.bases
+
+function bases.use(basename)
+ if basename == "reset" then
+ bases.list, bases.used, bases.found, bases.enabled = { }, { }, { }, false
+ else
+ basename = file.addsuffix(basename,"xml")
+ if not bases.used[basename] then
+ local t = { basename, nil, nil }
+ bases.used[basename] = t
+ bases.list[#bases.list+1] = t
+ if not bases.enabled then
+ bases.enabled = true
+ xml.registerns("rlx","http://www.pragma-ade.com/schemas/rlx") -- we should be able to do this per xml file
+ end
+ if trace_bases then
+ commands.writestatus("figures","registering base '%s'",basename)
+ end
+ end
+ end
+end
+
+function bases.find(basename,askedlabel)
+ if trace_bases then
+ commands.writestatus("figures","checking for '%s' in base '%s'",askedlabel,basename)
+ end
+ basename = file.addsuffix(basename,"xml")
+ local t = bases.found[askedlabel]
+ if t == nil then
+ local base = bases.used[basename]
+ local page = 0
+ if base[2] == nil then
+ -- no yet located
+ local figurepaths = figures.paths
+ for i=1,#figurepaths do
+ local path = figurepaths[i]
+ local xmlfile = path .. "/" .. basename
+ if io.exists(xmlfile) then
+ base[2] = xmlfile
+ base[3] = xml.load(xmlfile)
+ if trace_bases then
+ commands.writestatus("figures","base '%s' loaded",xmlfile)
+ end
+ break
+ end
+ end
+ end
+ t = false
+ if base[2] and base[3] then -- rlx:library
+ for e in xml.collected(base[3],"/(*:library|figurelibrary)/*:figure/*:label") do
+ page = page + 1
+ if xml.text(e) == askedlabel then
+ t = {
+ base = file.replacesuffix(base[2],"pdf"),
+ format = "pdf",
+ name = xml.text(e,"../*:file"), -- to be checked
+ page = page,
+ }
+ bases.found[askedlabel] = t
+ if trace_bases then
+ commands.writestatus("figures","figure '%s' found in base '%s'",askedlabel,base[2])
+ end
+ return t
+ end
+ end
+ if trace_bases and not t then
+ commands.writestatus("figures","figure '%s' not found in base '%s'",askedlabel,base[2])
+ end
+ end
+ end
+ return t
+end
+
+-- we can access sequential or by name
+
+function bases.locate(askedlabel)
+ local list = bases.list
+ for i=1,#list do
+ local entry = list[i]
+ local t = bases.find(entry[1],askedlabel)
+ if t then
+ return t
+ end
+ end
+ return false
+end
+
+function figures.identifiers.base(data)
+ if bases.enabled then
+ local dr, du, ds = data.request, data.used, data.status
+ local fbl = bases.locate(dr.name or dr.label)
+ if fbl then
+ du.page = fbl.page
+ du.format = fbl.format
+ du.fullname = fbl.base
+ ds.fullname = fbl.name
+ ds.format = fbl.format
+ ds.page = fbl.page
+ ds.status = 10
+ end
+ end
+ return data
+end
+
+figures.identifiers.list = {
+ figures.identifiers.base,
+ figures.identifiers.default
+}
+
+-- tracing
+
+statistics.register("graphics processing time", function()
+ local n = figures.n
+ if n > 0 then
+ return format("%s seconds including tex, n=%s", statistics.elapsedtime(figures),n)
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/grph-inc.mkii b/tex/context/base/grph-inc.mkii
new file mode 100644
index 000000000..1bd7544d8
--- /dev/null
+++ b/tex/context/base/grph-inc.mkii
@@ -0,0 +1,1243 @@
+%D \module
+%D [ file=grph-inc, % moved from core-fig
+%D version=2006.08.26, % overhaul of 1997.03.31
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Figure Inclusion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphic Macros / Figure Inclusion}
+
+% todo: directory : system -> \allinputpaths (so that we can \usesubpath)
+
+%D This is a reimplementation of the original module, which
+%D over time had evolved into a pretty complex whole. This
+%D was partly due to the fact that we needed to handle many
+%D formats, deal with substitute graphics, handle fallbacks
+%D and driver specifics (objects), etc. In the meantime we
+%D have more clever backends, moved away from texutil to
+%D rlxtools, can use runtime or betweentime runs etc. Also,
+%D more memory permits a cleaner implementation. Time to
+%D move on. We can now also assume that scaling is available.
+%D
+%D Another mess that can go is the llx/lly handling since
+%D drivers now automatically can determine such things.
+
+%D Messages 3 and 5 needs to be translated!
+
+\unprotect
+
+%D Due to the mere fact that \DVI|/|\PDF\ drivers differ in their
+%D needs for figure dimensions, we have to provide the width,
+%D height, horizontal and vertical scale. Also we want to
+%D specify at the user level either width and|/|or height, scale,
+%D or a factor related to the current document bodyfont size.
+%D Even better: we can also specify isometric scaling and
+%D automatically let \CONTEXT\ calculate the maximum possible
+%D dimensions. Whatever we calculate, the results will come
+%D available in the next registers.
+
+\letempty \@@DriverImageBox
+\letempty \@@DriverImageOptions
+\letempty \@@DriverImageWidth
+\letempty \@@DriverImageHeight
+\letempty \@@DriverImageFile
+\letempty \@@DriverImageLabel
+\letempty \@@DriverImageType
+\letempty \@@DriverImageMethod
+\letempty \@@DriverImagePage
+
+%D Because looking for dimensions can take many steps (locating
+%D the figure, maybe on more directories, scanning the figure
+%D on dimension, or when not found, trying to find them in the
+%D utility file, and again when not found, trying to generate
+%D such a file, and, as a last resort, trying to use the
+%D dimensions. Now when things do not work out the way we want,
+%D we can set a switch and get some information on what takes
+%D place.
+
+\newif\iftraceexternalfigures
+
+\let\traceexternalfigures\traceexternalfigurestrue
+
+\def\doshowfigurestate
+ {\iftraceexternalfigures
+ \expandafter\writestatus\expandafter\m!figures
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doshowfiguremessage
+ {\iftraceexternalfigures
+ \expandafter\gobbletwoarguments
+ \else
+ \expandafter\showmessage\expandafter\m!figures
+ \fi}
+
+%D Another switch tells \CONTEXT\ to locate and calculate a
+%D figure, but does not actually insert it. Especially when we
+%D use \PDFTEX\ this saves a lot of time on trialruns. (Keep
+%D in mind that \PDFTEX\ is both a \TEX\ pre|| and postprocessor.)
+
+\newif\ifskipexternalfigures % can be set elsewhere
+
+% \newif\ifrunutilityfile
+% \newif\ifconsultutilityfile
+%
+% Let's save two hash entries:
+
+\let\runutilityfiletrue \relax \let\runutilityfilefalse \relax
+\let\consultutilityfiletrue\relax \let\consultutilityfilefalse\relax
+
+%D Intermediate, private.
+
+\newdimen\determinedfigurewidth
+\newdimen\determinedfigureheight
+
+\let\naturalfigureheight\!!zeropoint
+\let\naturalfigurewidth \!!zeropoint
+
+\def\defaultfigurewidth {8\lineheight}
+\def\defaultfigureheight{6\lineheight}
+
+\def\defaultfigurepathsignal{(\v!default)}
+
+\def\checknaturalfiguredimensions
+ {\edef\naturalfigurewidth{\the\dimexpr\ifzeropt\determinedfigurewidth
+ \defaultfigurewidth \else\determinedfigurewidth \fi\relax}%
+ \edef\naturalfigureheight{\the\dimexpr\ifzeropt\determinedfigureheight
+ \defaultfigureheight\else\determinedfigureheight\fi\relax}}
+
+%D Locating figures. Dilemma: we do support eps and svg parsing but drivers
+%D don't always support it.
+
+\def\figuretypes{\c!mps,\c!pdf,\c!eps,\c!svg,\c!svg z,\c!png,\c!tif,jb2,\c!jpg}
+
+\def\supportedfiguretypes{\figuretypes}
+
+\def\checksupportedfiguretypes
+ {\begingroup
+ \global\let\supportedfiguretypes\empty
+ \def\docommand##1%
+ {\doiffileinsertionsupportedelse{##1}
+ {\doglobal\addtocommalist{##1}\supportedfiguretypes}
+ \donothing}%
+ \processcommacommand[\figuretypes]\docommand
+ \gdef\checksupportedfiguretypes{\let\figuretypes\supportedfiguretypes}%
+ \endgroup
+ \checksupportedfiguretypes}
+
+%D The next box is used to store the graphic. It's globally assigned.
+
+\newbox\foundexternalfigure
+
+\chardef\figurestatus\zerocount % nothing found
+
+\def\noffigurepages{\nofinsertpages}
+
+%D Variables.
+
+\newtoks\everyexternalfigureresets
+
+\def\resetfigurevariables
+ {\the\everyexternalfigureresets}
+
+%D Example usage:
+
+\appendtoks
+ \global\let\externalfigurelog\empty
+\to\everyexternalfigureresets
+
+%D Intermediate, private
+
+\def\resetprivatefigurevariables
+ {\let \wantedfigurefull \empty
+ \let \wantedfigurepath \empty
+ \let \wantedfigurename \empty
+ \let \wantedfigurebase \empty
+ \let \wantedfiguretype \empty
+ \let \wantedfigurefullname \empty
+ \let \wantedfiguretypespec \empty
+ \let \wantedfiguremethod \empty
+ \let \wantedfigurepage \empty
+ \let \wantedfigureoptions \empty
+ \let \wantedfigureconversion\empty
+ \let \wantedfigureprefix \empty
+ \let \wantedfiguretypelist \figuretypes
+ \let \figurepathlist \empty
+ \chardef \figurestatus \zerocount
+ \let \expandedfigurename \empty
+ \global\let \analyzedfigurewidth \!!zeropoint % set by indentifying code
+ \global\let \analyzedfigureheight \!!zeropoint % set by indentifying code
+ \global\setbox\foundexternalfigure \emptybox
+ \def \frozenfigurestamp {\externalfigurestamp}} % no edef
+
+\resetprivatefigurevariables
+
+\appendtoks
+ \resetprivatefigurevariables
+\to\everyexternalfigureresets
+
+%D Private/public.
+
+\def\resetpublicfigurevariables
+ {\let\figurewidth \!!zeropoint
+ \let\figureheight \!!zeropoint
+ \let\figurenaturalwidth \!!zeropoint
+ \let\figurenaturalheight \!!zeropoint
+ \let\figurelabel \empty
+ \let\figurefileoriginal \empty
+ \let\figurefileoptions \empty
+ \let\figurefilename \empty
+ \let\figurefiletype \empty
+ \let\figurefilepage \!!zerocount
+ \let\figurefileconversion\empty
+ \let\figurefileprefix \empty
+ \let\figurefilepath \empty
+ \let\figurefilecache \empty}
+
+\resetpublicfigurevariables
+
+\appendtoks
+ \resetpublicfigurevariables
+\to\everyexternalfigureresets
+
+\newcounter\figurenestinglevel
+
+\def\pushpublicfigurevariables
+ {\ifcase\figurenestinglevel\else
+ \doshowfigurestate{variables : push}%
+ \globalpushmacro\figurewidth
+ \globalpushmacro\figureheight
+ \globalpushmacro\figurenaturalwidth
+ \globalpushmacro\figurenaturalheight
+ \globalpushmacro\figurelabel
+ \globalpushmacro\figurefileoriginal
+ \globalpushmacro\figurefileoptions
+ \globalpushmacro\figurefilename
+ \globalpushmacro\figurefiletype
+ \globalpushmacro\figurefilepage
+ \globalpushmacro\figurefileconversion
+ \globalpushmacro\figurefileprefix
+ \globalpushmacro\figurefilepath
+ \globalpushmacro\figurefilecache
+ \fi}
+
+\def\poppublicfigurevariables
+ {\ifcase\figurenestinglevel\else
+ \doshowfigurestate{variables : pop}%
+ \globalpopmacro\figurefilecache
+ \globalpopmacro\figurefilepath
+ \globalpopmacro\figurefileprefix
+ \globalpopmacro\figurefileconversion
+ \globalpopmacro\figurefilepage
+ \globalpopmacro\figurefiletype
+ \globalpopmacro\figurefilename
+ \globalpopmacro\figurefileoptions
+ \globalpopmacro\figurefileoriginal
+ \globalpopmacro\figurelabel
+ \globalpopmacro\figurenaturalheight
+ \globalpopmacro\figurenaturalwidth
+ \globalpopmacro\figureheight
+ \globalpopmacro\figurewidth
+ \fi}
+
+\def\setpublicfigurevariables % todo: type vs typespec
+ {\xdef\figurewidth {\the\wd\foundexternalfigure}%
+ \xdef\figureheight {\the\ht\foundexternalfigure}%
+ \xdef\figurenaturalwidth {\naturalfigurewidth}%
+ \xdef\figurenaturalheight {\naturalfigureheight}%
+ \xdef\figurelabel {\wantedfigurelabel}%
+ \xdef\figurefilepath {\wantedfigurepath}%
+ \xdef\figurefilename {\wantedfigurename}%
+ \xdef\figurefiletype {\wantedfiguretypespec}%
+ \xdef\figurefilepage {\wantedfigurepage}%
+ \xdef\figurefileoptions {\wantedfigureoptions}%
+ \xdef\figurefileconversion{\wantedfigureconversion}%
+ \xdef\figurefilecache {\wantedconversioncache}%
+ \xdef\figurefileprefix {\wantedconversionprefix}%
+ \xdef\figurefileoriginal {\wantedconversionname}%
+ \xdef\figurefullname {\wantedfigurepath/\wantedfigurename.\wantedfiguretypespec}%
+ \ifcase\figurestatus
+ \let\figurefiletype\empty % ?
+ \fi}
+
+\def\setpublicfigurescalevariables
+ {\edef\figurescalewidth {\finalscaleboxwidth }%
+ \edef\figurescaleheight {\finalscaleboxheight}%
+ \edef\figurescalexscale {\finalscaleboxxscale}%
+ \edef\figurescaleyscale {\finalscaleboxyscale}}
+
+\def\resetpublicfigurescalevariables
+ {\let\figurescalewidth \!!zeropoint
+ \let\figurescaleheight \!!zeropoint
+ \let\figurescalexscale \!!plusone
+ \let\figurescaleyscale \!!plusone}
+
+\resetpublicfigurescalevariables
+
+\appendtoks
+ \resetpublicfigurescalevariables
+\to \everyexternalfigureresets
+
+%D The next one is for instance used in symbols. Since
+%D we only need to reset some parameters, we can
+%D better use the fast alternative:
+%D
+%D \starttyping
+%D \def\resetexternalfigures
+%D {\getparameters[\??ef]
+%D [\c!option=,\c!maxwidth=,\c!maxheight=,
+%D \c!foregroundcolor=,\c!color=,
+%D %\c!conversion=,\c!prefix=,\c!splitcolor=,
+%D \c!frame=\v!off,\c!background=]}
+%D \stoptyping
+%D
+%D This one dropped the runtime of the \MAPS\ bibliography
+%D from over 110 seconds down to less than 105 seconds. The
+%D tremendously faster (but uglier) implementation is:
+
+\def\resetexternalfigures
+ {\let\@@efoption \empty % \let\@@efprefix\empty
+ \let\@@efmaxwidth \empty % \let\@@efcache \empty
+ \let\@@efmaxheight \empty % \let\@@efframe \v!off
+ \let\@@efforegroundcolor\empty
+ \let\@@efcolor \empty
+ \let\@@efconversion \empty
+ \let\@@efbackground \empty}
+
+%D The following code will move:
+
+\appendtoks \resetexternalfigures \to \everyoverlay
+\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed
+%appendtoks \resetexternalfigures \to \everysymbol
+
+%D We need this one for bookkeeping:
+
+\newcounter\forcedMPSobject % better something \every
+
+%D Features:
+
+% converted -> prefix, suffix
+% alternative -> other suffix
+% buffer -> prefix
+
+%D Still messy:
+
+\newtoks\everyfiguretypepresets
+
+\def\presetfiguretypeprocessing
+ {\the\everyfiguretypepresets}
+
+\def\presetspecialfigure#1%
+ {\doif\wantedfiguretype{#1}%
+ {\let\@@efobject\v!no
+ \let\@@efpreset\v!no
+ \ifx\@@efwidth \empty\def\@@efwidth {\defaultfigurewidth }\fi
+ \ifx\@@efheight\empty\def\@@efheight{\defaultfigureheight}\fi}}
+
+\appendtoks
+ \presetspecialfigure\c!mov
+ \presetspecialfigure\c!avi
+\to \everyfiguretypepresets
+
+\def\checkformpsfigurefiles % to be checked
+ {\doif\wantedfigurename{mprun}
+ {\doshowfigurestate{type check : forcing mps (mprun)}%
+ \doifnotinstring{^\bufferprefix}{^\wantedfigurename}
+ {\edef\wantedfigurename{\bufferprefix\wantedfigurename}}%
+ \let\wantedfiguremethod \c!mps
+ \let\wantedfiguretypespec\c!mps}%
+ \doifnumberelse\wantedfiguretype
+ {\doshowfigurestate{type check : forcing mps (number)}%
+ \let\wantedfiguremethod \c!mps
+ \let\wantedfiguretypespec\c!mps}
+ \donothing
+ \doif\wantedfiguretypespec\c!mps
+ {\let\wantedfiguretypelist\wantedfiguretypespec
+ \ifcase\EPSspecial\else\ifinobject\else
+ \doglobal\increment\forcedMPSobject
+ \edef\externalfigurestamp{\c!mps::\forcedMPSobject}%
+ \let\@@efobject\v!yes
+ \fi\fi}}
+
+\appendtoks
+ \checkformpsfigurefiles
+\to \everyfiguretypepresets
+
+\def\checkfortexfigurefiles % to be checked (brrr: c!) / brrr: eftype
+ {\doifinset\wantedfiguretype{\c!tex,\c!tmp}
+ {\let\wantedfiguretypespec \wantedfiguretype}%
+ \doifinset\wantedfiguretypespec{\c!tex,\c!tmp,\v!buffer}
+ {\doshowfigurestate{type check : forcing tex (\wantedfiguretypespec)}%
+ \let\wantedfiguretypelist\wantedfiguretypespec
+ \let\wantedfiguremethod \c!tex
+ \let\@@efobject\v!no
+ \doifnothing\wantedfiguretype{\let\wantedfiguretype\c!tmp}%
+ % there can be a non buffer \jobname.tmp (made by texexec)
+ \doifnotinstring{^\bufferprefix}{^\wantedfigurename}
+ {\edef\wantedfigurename{\bufferprefix\wantedfigurename}}}}
+
+\appendtoks
+ \checkfortexfigurefiles
+\to \everyfiguretypepresets
+
+\def\checkforunknownfigurefiles
+ {\doifnothing\wantedfiguretype
+ {\dogetcommacommandelement\plusone\from\@@eftype\to\commalistelement
+ \edef\wantedfigurefullname{\wantedfigurename.\commalistelement}}}
+
+\appendtoks
+ \checkforunknownfigurefiles
+\to \everyfiguretypepresets
+
+% note * : this is needed because reusable graphics
+% combined with funny page aspect aspect ratio's can lead to
+% strange side effects of preceding factor=max specs. This
+% surfaced in the metafun manual, where the two side by
+% side clipped cow heads [the second one was a reused object]
+% where the second one inherited some characteristics from
+% the factor=max one some 30 pages back. Sigh.
+
+\chardef\splitexternalfigure\zerocount % 0 nosplit 1 split/yes 2 split/no
+
+\def\checkfigurecolorsettings
+ {% seperation, seldom used
+ \doifseparatingcolorselse
+ {\let\@@efforegroundcolor\empty
+ \doifelsenothing\@@efsplit
+ {\chardef\splitexternalfigure\zerocount}
+ {\doifcolorchannelelse\@@efsplit
+ {\let\@@efobject\v!no % why?
+ \chardef\splitexternalfigure\plusone}
+ {\chardef\splitexternalfigure\plustwo}}}
+ {\chardef\splitexternalfigure\zerocount}%
+ % fake color in gray bitmaps, assumes that
+ % a transparent color is used
+ \doifsomething\@@efforegroundcolor
+ {\def\@@efbackground{\v!foreground,\v!color}%
+ \def\@@efbackgroundcolor{\@@efforegroundcolor}}%
+ \doifsomething\@@efcolor
+ {\doifcolorelse\@@efcolor
+ {\checkpredefinedcolor[\@@efcolor]%
+ \doregisterfigurecolor\@@efcolor}}%
+ \donothing}
+
+\def\setextrafiguredriveroptions
+ {\let\@@DriverImageOptions\empty
+ \doifsomething\@@efpage {\addtocommalist\@@efpage \@@DriverImageOptions}%
+ \doif \@@efpreview \v!yes{\addtocommalist\v!preview \@@DriverImageOptions}%
+ \doif \@@efcontrols\v!yes{\addtocommalist\v!controls\@@DriverImageOptions}%
+ \doif \@@efrepeat \v!yes{\addtocommalist\v!repeat \@@DriverImageOptions}%
+ \doifinsetelse\@@efsize{mediabox,cropbox,artbox,bleedbox,trimbox}
+ {\let \@@DriverImageBox \@@efsize}%
+ {\doifinsetelse\@@efsize{media,crop,art,bleed,trim}
+ {\edef\@@DriverImageBox{\@@efsize box}}%
+ {\let \@@DriverImageBox \empty}}%
+ \let\wantedfigureoptions\@@DriverImageOptions}
+
+\def\checkiffigureobjectpresent
+ {\doifnot\@@efobject\v!no
+ {\doifobjectssupportedelse
+ {\doifobjectfoundelse{FIG}\externalfigurestamp
+ {\doshowfigurestate{object found : \externalfigurestamp}%
+ \getobjectdimensions{FIG}\externalfigurestamp
+ \edef\frozenfigurestamp{\externalfigurestamp}%
+ \xdef\analyzedfigurewidth {\the\dimexpr\objectwidth \relax}%
+ \xdef\analyzedfigureheight{\the\dimexpr\objectheight\relax}%
+ \setanalyzedfiguredimensions\plusone}
+ {\doshowfigurestate{unknown object: \externalfigurestamp}}}
+ {}}}
+
+\def\checkifknownfigureobjectpresent
+ {\ifx\wantedfiguretype\empty
+ \let\savedwantedfiguretype\wantedfiguretype
+ \def\docommand##1%
+ {\ifcase\figurestatus
+ \edef\wantedfiguretype{##1}%
+ \checkiffigureobjectpresent
+ \fi}%
+ \processcommacommand[\figuretypes]\docommand
+ \ifcase\figurestatus
+ \let\wantedfiguretype\savedwantedfiguretype
+ \fi
+ \fi}
+
+\def\checkforfigurefile
+ {\ifcase\figurestatus
+ \ifconditional\externalfigureflush
+ \analyzefigurefiles
+ \fi
+ \fi}
+
+\def\externalfigurestamp % needs \edef'd macros!
+ {\ifx\wantedfigurepath\empty\else
+ -\wantedfigurepath
+ \fi
+ \wantedfigurename
+ \ifx\wantedfiguretype\empty\else
+ \ifx\wantedfiguretype\s!unknown\else
+ -\wantedfiguretype
+ \fi
+ \fi
+ \ifx\wantedfiguretypespec\empty\else
+ \ifx\wantedfiguretypespec\s!unknown\else
+ \ifx\wantedfiguretypespec\wantedfiguretype\else
+ -\wantedfiguretypespec
+ \fi
+ \fi
+ \fi
+ \ifnum\wantedfigurepage>\zeropoint
+ -\wantedfigurepage
+ \fi}
+
+\def\checkfigurerenderingoptions
+ {\ifcase\figurestatus
+ \let\@@efframe\v!on
+ \fi
+ \doif\@@exoption\v!frame
+ {\let\@@efframe\v!on}%
+ \doif\@@exoption\v!empty
+ {\skipexternalfigurestrue
+ \let\@@efframe\v!off}}
+
+\newtoks\externalfigurepostprocessors
+
+\def\resetfigureusersettings
+ {\let\@@eftype \s!unknown \let\@@efmethod \empty \let\@@efpreset\v!yes
+ \let\@@eflabel \empty \let\@@efsize \empty \let\@@efpage \!!zerocount
+ \let\@@efobject \@@exobject \let\@@efdisplay \empty
+ \let\@@efsplit \empty \let\@@efcolor \empty \let\@@efsymbol\v!no
+ \let\@@efcontrols \v!no \let\@@efpreview \v!no \let\@@efrepeat\v!no
+ \let\@@efhfactor \empty \let\@@efwfactor \empty \let\@@effactor\empty
+ \let\@@efmaxwidth \@@exmaxwidth \let\@@efmaxheight\@@exmaxheight
+ \let\@@efxscale \empty \let\@@efyscale \empty \let\@@efscale \empty
+ \let\@@efsx \!!plusone \let\@@efsy \!!plusone
+ \let\@@efwidth \empty \let\@@efheight \empty
+ \let\@@eflines \empty \let\@@efgrid \empty
+ \let\@@efconversion\@@exconversion \let\@@efprefix \@@exprefix \let\@@efcache \@@excache}
+
+%D Types and Methods are a bit history. Anyhow, user scan use the
+%D type to force the handler. So, what to do with the method. We can
+%D use that one to force a handler with a given suffix, so when no
+%D type is given, but a suffix is part of the name, the method will
+%D determine the handler.
+
+\def\checkfigureusersettings
+ {\doif\@@efreset\v!yes\resetexternalfigures
+ \doifelsenothing\@@eflabel
+ {\doifnothing\wantedfigurelabel{\let\wantedfigurelabel\wantedfigurename}}%
+ {\let\wantedfigurelabel\@@eflabel}%
+ \doifsomething\@@eftype
+ {\doifnot\@@eftype\s!unknown
+ {\edef\wantedfiguretypespec{\@@eftype}%
+ \let\wantedfiguremethod\wantedfiguretypespec}}%
+ \doifnothing\wantedfigurepage % can be set by plug in
+ {\let\wantedfigurepage\@@efpage}%
+ \doif\wantedfigurepage\empty
+ {\let\wantedfigurepage\!!zerocount}% 0 is signal !
+ \doifsomething\@@efmethod % rather untested misusage of the remapper
+ {\doifsomething\wantedfiguretype
+ {\definegraphictypesynonym[\wantedfiguretype][\@@method]}}}
+
+% #1 is now obsolete
+
+\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current
+ {\doshowfigurestate{begin}%
+ \dontcomplain
+ % let's limit the search, which means that e.g. svg has to be given explicitly
+ \checksupportedfiguretypes
+ % recently added; we presume local use
+ \restorecatcodes
+ % collected resets (token list)
+ \resetfigurevariables
+\resetwantedconversionvariables % new here
+ % analyze filename and set wanted variables
+ \analyzefigurefilename{#3}{#2}%
+ \doanalyzefiguredimensionsfromfile
+ % handle user settings
+ \resetfigureusersettings
+ \dosetefparameters{#4}{#5}{#6}%
+ \checkfigureusersettings
+ \checkfigurecolorsettings
+ % adapt settings based on suffix and/or type
+ \presetfiguretypeprocessing
+ % now we really start
+ \checkiffigureobjectpresent % first guess, we may not yet know the typespec
+ \checkifknownfigureobjectpresent
+ \checkforfigurefilepresence
+ \checkiffigureobjectpresent % to be sure, in case we now know the typespec
+ \checkfigurerenderingoptions % was later, moved here
+ \checknaturalfiguredimensions % inherit from global values and/or fallbacks
+ % by now we know what we're dealing with (put in box and scale)
+ \setextrafiguredriveroptions
+ \prepackageexternalfigureobject
+ % set public variables in case postprocessing needs them
+ \pushpublicfigurevariables
+ \setpublicfigurevariables
+ \setpublicfigureconversionvariables
+ \setpublicfigurescalevariables
+ % package final graphic, only now we can apply backgrounds and such
+ \doglobal\increment\figurenestinglevel
+ \finishexternalfigure
+ \doglobal\decrement\figurenestinglevel
+ % restore variables
+ \poppublicfigurevariables
+ \doshowfigurestate{end}}
+
+\def\checkforfigurefilepresence
+ {\checkforconvertedfigure
+ \checkforfigurefile}
+
+%D Figure objects.
+
+\def\setfigureobject
+ {\doshowfigurestate{object set : \externalfigurestamp}%
+ \setobject{FIG}\externalfigurestamp}
+
+% \def\getfigureobject
+% {\doshowfigurestate{object used : \externalfigurestamp}%
+% \getobject{FIG}\externalfigurestamp}
+
+\def\getfigureobject
+ {\doshowfigurestate{object used : \frozenfigurestamp}%
+ \getobject{FIG}\frozenfigurestamp}
+
+\def\prepackageexternalfigureobject
+ {\ifcase\figurestatus
+ \doshowfiguremessage1\expandedfigurename
+ \doshowfigurestate{state : figure not found (\expandedfigurename)}%
+ \global\setbox\foundexternalfigure\naturalvbox
+ {\doscalebox\??ef{\blackrule[\c!width=\naturalfigurewidth,\c!height=\naturalfigureheight]}}%
+ \xdef\noffigurepages{0}%
+ \or
+ \doshowfiguremessage8\expandedfigurename
+ \doshowfigurestate{state : reusing existing figure}%
+ \global\setbox\foundexternalfigure\naturalvbox
+ {\doscalebox\??ef{\dowithfigure{\getfigureobject}}}%
+ \xdef\noffigurepages{\number\getvalue{\externalfigurestamp\c!n}}%
+ \or
+ \doshowfiguremessage2\expandedfigurename
+ \doshowfigurestate{state : using special figure}%
+ \setbox\scratchbox\naturalvbox % make a dummy
+ {\doscalebox\??ef{\blackrule[\c!width=\naturalfigurewidth,\c!height=\naturalfigureheight]}}%
+ \global\setbox\foundexternalfigure\naturalvbox to \finalscaleboxheight
+ {\vfill
+ \hsize\finalscaleboxwidth
+ \dowithfigure{\insertscaledfiguredriverdata}}%
+ \xdef\noffigurepages{\number\nofinsertpages}%
+ \else
+ \ifdim\naturalfigurewidth>\zeropoint
+ \ifnum\figurestatus>\!!ten\relax
+ \doshowfiguremessage3\expandedfigurename
+ \else
+ \doshowfiguremessage4\expandedfigurename
+ \fi
+ \else
+ \doshowfiguremessage5\expandedfigurename
+ \fi
+ \doshowfigurestate{state : using found figure}% 3=self 4=rlx
+ \doifelse\@@efobject\v!no
+ {\donefalse}
+ {\doifobjectssupportedelse\donetrue\donefalse}%
+ \ifdone
+ % make an object and use it
+ \packageexternalfigureobject
+ \setfigureobject\vbox{\box\foundexternalfigure}%
+ \setxvalue{\externalfigurestamp\c!n}{\number\nofinsertpages}%
+ \global\setbox\foundexternalfigure\naturalvbox
+ {\doscalebox\??ef{\dowithfigure{\getfigureobject}}}%
+ \xdef\noffigurepages{\number\getvalue{\externalfigurestamp\c!n}}%
+ \else
+ % maybe a tex figure
+ \global\setbox\foundexternalfigure\naturalvbox
+ {\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}%
+ \xdef\noffigurepages{\number\nofinsertpages}%
+ \fi
+ \fi
+ \global\wd\foundexternalfigure\finalscaleboxwidth
+ \global\ht\foundexternalfigure\finalscaleboxheight
+ \global\let\lastfigureobjectname\externalfigurestamp
+ \doresetobjects} % clean up driver left overs
+
+\def\packageexternalfigureobject
+ {\global\setbox\foundexternalfigure\vbox to \naturalfigureheight
+ {\vfill
+ \ifdim\wd\foundexternalfigure=\zeropoint
+ \setextrafiguredriveroptions
+ \insertunscaledfiguredriverdata
+ \else\ifskipexternalfigures
+ \ruledhbox{\backgroundline[\@@efsplitcolor]{\fakebox\foundexternalfigure}}%
+ \else
+ \box\foundexternalfigure
+ \fi\fi}%
+ \wd\foundexternalfigure\naturalfigurewidth
+ \ht\foundexternalfigure\naturalfigureheight}
+
+\def\finishexternalfigure % here we use \figurevariables
+ {\global\setbox\foundexternalfigure\vbox
+ {\forgetall
+ \ifcase\figurestatus
+ \resetsystemmode\v!figure % todo, also: \v!resource
+ \else
+ \setsystemmode \v!figure % todo, also: \v!resource
+ \fi
+ \ifconditional\externalfigureflush
+ \ifconditional\externalfigurelevel % probably background
+ \ifskipexternalfigures
+ % nothing
+ \fakebox\foundexternalfigure
+ \else\ifcase\figurestatus
+ % nothing
+ \else\ifnum\splitexternalfigure=\plustwo\else
+ \the\externalfigurepostprocessors
+ \box\foundexternalfigure
+ \fi\fi\fi
+ \else
+ \iftrialtypesetting \else \feedbackexternalfigure \fi
+ \settrue\externalfigurelevel
+ \ifskipexternalfigures
+ \ifcase\figurestatus
+ \externalfigurereplacement\figurelabel\figurefilename{unknown}%
+ \else
+ \externalfigurereplacement\figurelabel\figurefullname{skipped}%
+ \fi
+ \else\ifcase\figurestatus
+ \externalfigurereplacement\figurelabel\figurefilename{unknown}%
+ \else\ifnum\splitexternalfigure=\plustwo
+ \backgroundline[\@@efsplitcolor]{\fakebox\foundexternalfigure}%
+ \else
+ \the\externalfigurepostprocessors
+ \doifelse\@@efreset\v!yes
+ {\wd\foundexternalfigure\figurewidth
+ \ht\foundexternalfigure\figureheight
+ \dp\foundexternalfigure\zeropoint
+ \box\foundexternalfigure}
+ {\localframed % should also be applied to high res !
+ [\??ef]
+ [\c!offset=\v!overlay,
+ \c!width=\figurewidth,
+ \c!height=\figureheight]
+ {\vfilll
+ \ifnum\splitexternalfigure=\plusone
+ % hm, eigenlijk in dit geval achtergrondkleur
+ \hidesplitcolorfalse % really needed
+ \backgroundline[\@@efsplitcolor]{\box\foundexternalfigure}%
+ \else % = 0, no split mode
+ \box\foundexternalfigure
+ \fi}}%
+ \fi\fi\fi
+ \fi
+ \else
+ % maybe also \the\externalfigurepostprocessors
+ \iftrialtypesetting \else \feedbackexternalfigure \fi
+ \fi}}
+
+\def\insertfiguredriverdata#1#2%
+ {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec
+ \lowercasestring\wantedfiguremethod \to\lcwantedfiguremethod
+ \edef\@@DriverImageWidth {\the\dimexpr#1\relax}%
+ \edef\@@DriverImageHeight{\the\dimexpr#2\relax}%
+ \let \@@DriverImageFile \wantedfigurefullname
+ \let \@@DriverImageType \lcwantedfiguretypespec
+ \let \@@DriverImageMethod \lcwantedfiguremethod
+ \let \@@DriverImageLabel \wantedfigurelabel
+ \let \@@DriverImagePage \wantedfigurepage
+ \doinsertfile}
+
+\def\insertunscaledfiguredriverdata
+ {\insertfiguredriverdata\naturalfigurewidth\naturalfigureheight}
+
+\def\insertscaledfiguredriverdata
+ {\insertfiguredriverdata\finalscaleboxwidth\finalscaleboxheight}
+
+\ifx\externalfigurereplacement\undefined\let\externalfigurereplacement\gobblethreearguments\fi
+\ifx\externalfigureplaceholder\undefined\let\externalfigureplaceholder\gobblethreearguments\fi
+
+\def\registerexternalfigure % no placement, handy for preprocessing
+ {\dotripleempty\doregisterexternalfigure}
+
+\def\doregisterexternalfigure[#1][#2][#3]%
+ {\bgroup
+ \setfalse\externalfigureflush
+ \externalfigure[#1][#2][#3]% or \doexternalfigure
+ \egroup}
+
+\let\feedbackexternalfigure\relax % \gobblefourarguments
+\let\dowithfigure \relax
+
+%D Conversion stuff:
+
+\newcount\nofconversionfigures
+
+\def\resetwantedconversionvariables
+ {\let\wantedconversionpath \empty % these point to the to be converted graphic
+ \let\wantedconversionname \empty
+ \let\wantedconversiontype \empty
+ \let\wantedconversioncache \empty
+ \let\wantedconversionprefix\empty}
+
+\resetwantedconversionvariables
+
+\def\checkforconvertedfigure
+ {\ifcase\figurestatus
+ \resetwantedconversionvariables
+ \doifsomething\@@efconversion
+ {\global\advance\nofconversionfigures\plusone
+ \doshowfigurestate{n-of-conversions : \number\nofconversionfigures}%
+ \edef\wantedfigureconversion{\@@efconversion}%
+ \edef\wantedconversioncache {\@@efcache}%
+ \edef\wantedconversionprefix{\@@efprefix}%
+ \doshowfigurestate{checking paths : \figurepathlist}%
+ \processcommacommand[\figurepathlist]\dolocatefigureconversionfile
+ \ifcase\figurestatus
+ \doshowfigurestate{remark : no conversion file found}%
+ \else
+ \doshowfigurestate{remark : conversion file found}%
+ \chardef\figurestatus\zerocount
+ \fi
+ \let\wantedconversionname\wantedfigurename
+ \edef\wantedfigurename{\wantedconversionprefix\wantedfigurename}%
+ \ifx\wantedconversioncache\empty
+ \let \wantedfigurepath \wantedconversionpath
+ \else
+ \checkfilename\@@efcache
+ \ifnum\kindoffile=\plusone
+ \let\wantedfigurepath\@@efcache % root related path
+ \else % brrr
+ \edef\wantedfigurepath{\@@efcache,\wantedconversionpath/\@@efcache}% in case of explicit paths, what a mess
+ \fi
+ \fi
+ \let\wantedfiguretype \empty
+ \let\wantedfiguretypelist\figuretypes % hm, why needed
+ \ifx\figurepathlist\empty
+ \let\figurepathlist\wantedfigurepath
+ \else
+ \edef\figurepathlist{\wantedfigurepath,\figurepathlist}%
+ \fi
+ \doshowfigurestate{conversion path : \wantedconversionpath}%
+ \doshowfigurestate{conversion name : \wantedconversionname}}%
+ \doshowfigurestate{new figure path : \wantedfigurepath}%
+ \fi}
+
+\def\dolocatefigureconversionfile#1%
+ {\ifcase\figurestatus
+ \setwantedfigurefullname{#1}\wantedfigurename\wantedfiguretype
+ \doshowfigurestate{locating original : \wantedfigurefullname}%
+ \doiffile\wantedfigurefullname
+ {\def\wantedconversionpath{#1}%
+ \let\wantedconversionname\wantedfigurename
+ \let\wantedconversiontype\wantedfiguretype
+ \chardef\figurestatus\plusfive}%
+ \fi}
+
+\def\setpublicfigureconversionvariables % also prefix, cache
+ {\doifsomething\@@efconversion
+ {\doifmode{\systemmodeprefix\v!first}
+ {\let\figurefilepath\wantedconversionpath
+ \let\figurefilename\wantedconversionname
+ \let\figurefiletype\wantedconversiontype
+ \let\figurefileconversion\wantedfigureconversion
+ \def\figurefullname
+ {\ifx\wantedconversionpath\empty\else\wantedconversionpath/\fi
+ \wantedconversionname
+ \ifx\wantedconversiontype\empty\else.\wantedconversiontype\fi}}}}
+
+%D In \PDF\ one can specify an alternative graphic. This means
+%D that for instance a low resolution graphic can be used for
+%D viewing and a high res one for printing. Because this
+%D feature depends much on the driver, here we only take care
+%D of perparations. It is up to the special driver to handle
+%D the inclusion. The driver routines can change the content of
+%D box \type {\foundexternalfigure} if suitable.
+%D
+%D One complication is for instance that an alternative may
+%D not itself have an alternative, and these kind of situations
+%D are best handled by the driver.
+
+\let\lastfigureobjectname\empty
+
+%D The next macro does not work well with figure bases yet.
+
+\def\calculateexternalscreenfigure[#1][#2][#3][#4][#5][#6]%
+ {\ifx\@@efdisplay\empty\else
+ \doifnot\@@efobject\v!no
+ {\doifobjectssupportedelse
+ {\doifspecialavailableelse\doregisterfigure
+ {\doshowfigurestate{screen alternative : start}%
+ \bgroup
+ \dosetefparameters{#4}{#5}{#6}%
+ \doregisterfigure{FIG}{\lastfigureobjectname}%
+ \let\@@ef@@scherm\@@efdisplay
+ \calculateexternalfigure[#1][\@@ef@@scherm][\@@ef@@scherm][#4,\c!display=][#5][#6]%
+ \doshowfigurestate{screen alternative : stop}%
+ \egroup}
+ {}}
+ {}}%
+ \fi}
+
+\def\getfiguredimensions
+ {\dodoubleempty\dogetfiguredimensions}
+
+\def\dogetfiguredimensions[#1][#2]%
+ {{\let\immediate\relax % very dirty but prevents flushing, will change
+ \setbox0\hbox{\externalfigure[#1][#2,\c!display=,\c!object=\v!no]}}}
+
+% use the next one when the object must be forgotten (xobj
+% nums can migrate to the next object; maybe it should
+% always be done; todo ....
+
+\def\getfiguredimensionsonly
+ {\dodoubleempty\dogetfiguredimensionsonly}
+
+\def\dogetfiguredimensionsonly[#1][#2]%
+ {\dogetfiguredimensions[#1][#2]%
+ \doresetobjects}
+
+\def\doiffigureelse#1%
+ {\getfiguredimensions[#1]% so data is available !
+ \ifdim\analyzedfigurewidth=\zeropoint % todo: \figurestatus
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+%D Size determination.
+%D
+%D An analyzer must set the following dimensions (global macros):
+%D
+%D \starttyping
+%D \analyzedfigurewidth
+%D \analyzedfigureheight
+%D \stoptyping
+%D
+%D And afterwards, when succeeded, call:
+%D
+%D \starttyping
+%D \setanalyzedfiguredimensions{number>=10}
+%D \stoptyping
+%D
+%D Numbers upto 9 are reserved for special purposes:
+%D
+%D \starttabulate
+%D \NC 0 \NC not found \NC \NR
+%D \NC 1 \NC object (will be reused) \NC \NR
+%D \NC 2 \NC found but no dimensions (e.g. special annotation) \NC \NR
+%D \stoptabulate
+
+\let\doanalyzefiguredimensionsfromfile\relax % hook for figuredatabase
+\let\doanalyzefiguredimensionsinternal\relax
+\let\doanalyzefiguredimensionsexternal\relax % hook for rli support (see later)
+\let\doanalyzefiguredimensionsfallback\relax
+
+\def\doanalyzefiguredimensions
+ {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec
+ \doiffileinsertionsupportedelse\lcwantedfiguretypespec
+ {\doiffileelse\wantedfigurefullname
+ {\doshowfigurestate{analyzing : \wantedfigurefullname}%
+ \doanalyzefiguredimensionsinternal
+ \doanalyzefiguredimensionsexternal
+ \doanalyzefiguredimensionsfallback}
+ {\doshowfigurestate{not found : \wantedfigurefullname}}}
+ {}}
+
+\def\setanalyzedfiguredimensions#1%
+ {\ifdim\analyzedfigurewidth>\zeropoint
+ \ifdim\analyzedfigureheight>\zeropoint
+ \determinedfigurewidth \analyzedfigurewidth
+ \determinedfigureheight\analyzedfigureheight
+ \chardef\figurestatus #1\relax
+ \doshowfigurestate{dimensions :
+ \the\dimexpr\analyzedfigurewidth\relax\space x\space
+ \the\dimexpr\analyzedfigureheight\relax}%
+ \else
+ \determinedfigurewidth \zeropoint
+ \determinedfigureheight\zeropoint
+ \chardef\figurestatus \zerocount
+ \fi
+ \else
+ \determinedfigurewidth \zeropoint
+ \determinedfigureheight\zeropoint
+ \chardef\figurestatus \zerocount
+ \fi}
+
+%D We can remap types. This is to be dealt with in the driver files.
+
+\def\definegraphictypesynonym
+ {\dodoubleargument\dodefinegraphictypesynonym}
+
+\def\dodefinegraphictypesynonym[#1][#2]%
+ {\setvalue{\??ef:\??ex:#1}{#2}}
+
+\def\truegraphictype#1%
+ {\ifcsname\??ef:\??ex:#1\endcsname
+ \expandafter\truegraphictype\csname\??ef:\??ex:#1\endcsname\else#1%
+ \fi}
+
+\definegraphictypesynonym[epdf] [pdf]
+\definegraphictypesynonym[jpeg] [jpg]
+\definegraphictypesynonym[jp2] [jpg]
+\definegraphictypesynonym[jbig] [jb2]
+\definegraphictypesynonym[jbig2][jb2]
+\definegraphictypesynonym[jbg] [jb2]
+
+%D The self method (mostly used) uses the driver.
+
+% todo: when zero width mps, ok
+%
+% analyzer must set the analyzed dimensions
+
+\def\doanalyzefiguredimensionsinternal
+ {\ifcase\figurestatus
+ \lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec
+ \let\@@DriverImageFile \wantedfigurefullname
+ \let\@@DriverImagePage \wantedfigurepage
+ \let\@@DriverImageType\lcwantedfiguretypespec
+ % use internal when available, otherwise try driver (\dogetfiguresize)
+ \executeifdefined{dogetfiguresize\@@DriverImageType}\dogetfiguresize
+ \setanalyzedfiguredimensions\!!ten
+ \fi}
+
+%D The tex method.
+
+\def\dogetfiguresizetex
+ {\ifcase\figurestatus
+ \global\setbox\foundexternalfigure\vbox
+ {\insidefloattrue
+ \forgetall
+ \blank[\v!disable]% niet meer weg !
+ \startreadingfile
+ \readfile\wantedfigurefullname \donothing \donothing
+ \stopreadingfile
+ \endgraf
+ \removelastskip}%
+ \global\setbox\foundexternalfigure\hbox
+ {\raise\dp\foundexternalfigure\box\foundexternalfigure}%
+ \xdef\analyzedfigurewidth {\the\wd\foundexternalfigure}%
+ \xdef\analyzedfigureheight{\the\ht\foundexternalfigure}%
+ \fi}
+
+\let\dogetfiguresizetmp \dogetfiguresizetex
+\let\dogetfiguresizebuffer\dogetfiguresizetex
+
+%D The eps, mps and svg files are read directly.
+
+\def\dogetfiguresizeeps
+ {\dogetEPSboundingbox\wantedfigurefullname\!!widtha\!!heighta\!!widthb\!!heightb
+ \xdef\analyzedfigurewidth {\the\!!widthb}%
+ \xdef\analyzedfigureheight{\the\!!heightb}}
+
+\let\dogetfiguresizemps\dogetfiguresizeeps
+
+\def\dogetfiguresizesvg
+ {\doifinset\wantedfiguretypespec\c!svg
+ {\startnointerference
+ \startXMLignore
+ \defineXMLcommand[svg][width=100,height=75]
+ {\doifdimensionelse{\XMLop{width}}
+ {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{width}\relax}}
+ {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{width}\onebasepoint\relax}}%
+ \doifdimensionelse{\XMLop{height}}
+ {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{height}\relax}}
+ {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{height}\onebasepoint\relax}}%
+ \endinput}%
+ \processXMLfilegrouped\wantedfigurefullname
+ \stopXMLignore
+ \stopnointerference}}
+
+%D Do some checking on the filename.
+
+\newconditional \figurefileisqualified
+
+\def\setfigurepathlist
+ {\let\figurepathlist\empty
+ \expanded{\doifinset{\v!global }{\@@exlocation}}
+ {\let\figurepathlist\@@exdirectory}%
+ \expanded{\doifinset{\v!local }{\@@exlocation}}
+ {\prependtocommalist\f!currentpath\figurepathlist}%
+ \expanded{\doifinset{\v!default}{\@@exlocation}}
+ {\appendtocommalist\defaultfigurepathsignal\figurepathlist}}
+
+% The combined path and qualified path hack is dedicated to Onno Tomson,
+% our partner in fighting inconsistent and faulty image specifications in
+% user files.
+
+\def\analyzefigurefilename#1#2%
+ {\sanitizefilename#1\to\expandedfigurename
+ \expanded{\checkfilename{\expandedfigurename}}%
+ \ifcase\kindoffile
+ \splitfigurefilename
+ \ifcase\splitoffkind
+ \let\wantedfigurepath\empty % no . either
+ \setfigurepathlist
+ \setfalse\figurefileisqualified
+ \else
+ \splitfigurefilename
+ % will become splitoffkind 3 ! ! ! !
+ \setfalse\figurefileisqualified
+ \doifinstring{$$/}{$$\wantedfigurepath}{\settrue\figurefileisqualified}%
+ \doifinstring {:} {\wantedfigurepath}{\settrue\figurefileisqualified}%
+ \ifconditional\figurefileisqualified
+ \let\figurepathlist\wantedfigurepath
+ \let\wantedfigurepath\empty
+ \settrue\figurefileisqualified
+ \else
+ \let\figurepathlist\@@exdirectory
+ \let\oldfigurepathlist\figurepathlist
+ \let\figurepathlist\wantedfigurepath
+ \def\docommand##1{\edef\figurepathlist{\figurepathlist,##1/\wantedfigurepath}}%
+ \processcommacommand[\oldfigurepathlist]\docommand
+ \fi
+ \fi
+ \else % fully qualified
+ \splitfigurefilename
+ \let\wantedfigurepath\empty
+ \settrue\figurefileisqualified
+ \fi
+ \ifx\figurepathlist\empty
+ \let\figurepathlist\defaultfigurepathsignal % will prepend no path
+ \fi
+ \doifelsenothing\wantedfiguretype
+ {\doifparentfileelse\wantedfigurename
+ {\@EA\removefromcommalist\@EA{\jobsuffix }\wantedfiguretypelist
+ \@EA\removefromcommalist\@EA{\jobfilesuffix}\wantedfiguretypelist}
+ {}}
+ {\let\wantedfiguretypelist\empty
+ \let\wantedfiguretypespec\wantedfiguretype}%
+ \edef\wantedfigurelabel{#2}%
+ \doshowfigurestate{type check : \ifx\wantedfiguretypelist\empty forced type \wantedfiguretypespec\else\wantedfiguretypelist\fi}%
+ \doshowfigurestate{file specs : \wantedfigurefull\space [\wantedfigurepath] [\wantedfigurename] [\wantedfiguretype]}%
+ \doshowfigurestate{file type : \ifconditional\figurefileisqualified qualified\else simple\fi}}
+
+\def\setwantedfigurefullname#1#2#3% path name spec
+ {\ifx\wantedfiguremethod\empty
+ % the either explicit or gambled typespec determines the method
+ \edef\wantedfiguretypespec{#3}%
+ \doifelse{#1}\defaultfigurepathsignal
+ {\edef\wantedfigurefullname {#2.\wantedfiguretypespec}}
+ {\edef\wantedfigurefullname{#1/#2.\wantedfiguretypespec}}%
+ \else\ifx\wantedfiguretype\empty %
+ % the typespec (probably the same as the method) determines the suffix
+ \doifelse{#1}\defaultfigurepathsignal
+ {\edef\wantedfigurefullname {#2.\wantedfiguretypespec}}
+ {\edef\wantedfigurefullname{#1/#2.\wantedfiguretypespec}}%
+ \let\wantedfiguretypespec\wantedfiguremethod
+ \else
+ % the given suffix is used
+ \let\wantedfiguretypespec\wantedfiguremethod
+ \doifelse{#1}\defaultfigurepathsignal
+ {\edef\wantedfigurefullname {#2.\wantedfiguretype}}
+ {\edef\wantedfigurefullname{#1/#2.\wantedfiguretype}}%
+ \fi\fi}
+
+\def\splitfigurefilename
+ {\splitfilename\expandedfigurename
+ \let\wantedfigurefull\splitofffull
+ \let\wantedfigurepath\splitoffpath
+ \let\wantedfigurename\splitoffname
+ \let\wantedfigurebase\splitoffbase
+ \let\wantedfiguretype\splitofftype}
+
+\def\analyzefigurefiles
+ {\ifconditional\figurefileisqualified
+ \ifx\wantedfiguretype\empty
+ \doshowfigurestate{locating : unknown type}%
+ \doanalyzeunknownfiguretype
+ \else
+ % this file or none
+ \doshowfigurestate{locating : known type}%
+ \doanalyzequalifiedfigure
+ \fi
+ \else
+ \ifx\wantedfiguretype\empty
+ % locate best fit / check support
+ \doshowfigurestate{locating : best fit}%
+ \doanalyzeunknownfiguretype
+ \else
+ % only check on paths
+ \doshowfigurestate{locating : known types}%
+ \doanalyzeknownfiguretype
+ \fi
+ \fi}
+
+\def\doanalyzequalifiedfigure
+ {\let\wantedfigurefullname\wantedfigurefull
+ \let\wantedfiguretypespec\wantedfiguretype
+ \doshowfigurestate{forced type : \wantedfiguretype}%
+ \doshowfigurestate{identifying : \wantedfigurefullname}%
+ \doanalyzefiguredimensions}
+
+\def\doanalyzeknownfiguretype
+ {\doshowfigurestate{using paths : \figurepathlist}%
+ \doshowfigurestate{known type : \wantedfiguretype}%
+ \doshowfigurestate{identifying : \wantedfigurename}%
+ \let\wantedfiguretypespec\wantedfiguretype
+ \processcommacommand[\figurepathlist]\dodoanalyzeknownfiguretype}
+
+\def\dodoanalyzeknownfiguretype#1% path
+ {\ifcase\figurestatus
+ \setwantedfigurefullname{#1}\wantedfigurename\wantedfiguretype
+ \doanalyzefiguredimensions
+ \fi}
+
+\def\doanalyzeunknownfiguretype
+ {\doshowfigurestate{using paths : \figurepathlist}%
+ \doshowfigurestate{using types : \wantedfiguretypelist}%
+ \doshowfigurestate{identifying : \wantedfigurename}%
+ \processcommacommand[\wantedfiguretypelist]\dodoanalyzeunknownfiguretype}
+
+\def\dodoanalyzeunknownfiguretype#1%
+ {\processcommacommand[\figurepathlist]{\dododoanalyzeunknownfiguretype{#1}}}
+
+\def\dododoanalyzeunknownfiguretype#1#2% type path
+ {\ifcase\figurestatus
+ \setwantedfigurefullname{#2}\wantedfigurename{#1}% path spec
+ \doanalyzefiguredimensions
+ \fi}
+
+%D Some files, take for instance movies, cannot easilly be
+%D parsed on dimensions, that is, not yet. Although the current
+%D mechanism has no problems with this, as long as the user
+%D specified width and height reflect the right aspect ratio.
+%D Nevertheless, when one does not want any scanning done, one
+%D can disable \type{preset}. When no preset is needed, we only
+%D locate the file.
+
+\def\doanalyzefiguredimensionsfallback
+ {\ifcase\figurestatus
+ \doshowfigurestate{warning : assuming adaptive figure}%
+ \xdef\analyzedfigurewidth {\the\dimexpr\@@efwidth +\zeropoint\relax}%
+ \xdef\analyzedfigureheight{\the\dimexpr\@@efheight+\zeropoint\relax}%
+ \setanalyzedfiguredimensions\plustwo
+ \fi}
+
+%D This is \MKII\ only and comes from cont-new (maybe used in a project).
+
+% maybe to be integrated (option=...)
+
+\def\directexternalfigure
+ {\dodoubleempty\dodirectexternalfigure}
+
+\def\dodirectexternalfigure[#1][#2]%
+ {\bgroup
+ \getparameters[\??ef][\c!type=\splitofftype,\c!page=1,#2]%
+ \sanitizefilename#1\to\expandedfigurename
+ \splitfilename\expandedfigurename
+ \let\@@DriverImageWidth \!!zeropoint
+ \let\@@DriverImageHeight \!!zeropoint
+ \let\@@DriverImageFile \splitofffull
+ \let\@@DriverImageType \@@eftype
+ \let\@@DriverImageMethod \@@eftype
+ \let\@@DriverImageLabel \empty
+ \let\@@DriverImagePage \@@efpage
+ \doinsertfile
+ \egroup}
+
+% \directexternalfigure[cow.pdf]
+
+\protect \endinput
diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv
new file mode 100644
index 000000000..16ee1097a
--- /dev/null
+++ b/tex/context/base/grph-inc.mkiv
@@ -0,0 +1,433 @@
+%D \module
+%D [ file=grph-inc, % moved from core-fig
+%D version=2006.08.26, % overhaul of 1997.03.31
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Figure Inclusion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphic Macros / Figure Inclusion}
+
+%D todo:
+%D
+%D - color conversion
+%D - alternative images
+%D - a few more obscure things
+
+\registerctxluafile{grph-inc}{1.001}
+\registerctxluafile{grph-fil}{1.001}
+\registerctxluafile{grph-u3d}{1.001} % this will change
+\registerctxluafile{grph-swf}{1.001} % this will change
+
+\unprotect
+
+%D The following registers are used (if only to be downward compatible).
+
+\newbox \foundexternalfigure
+\newif \ifskipexternalfigures
+\newtoks \everyexternalfigureresets
+\newtoks \everyexternalfigurechecks
+\newtoks \externalfigurepostprocessors
+
+\def\resetfigurevariables {\the\everyexternalfigureresets}
+\def\checkfigurevariables {\the\everyexternalfigurechecks}
+
+%D Historic feature:
+
+\appendtoks
+ \global\let\externalfigurelog\empty
+\to \everyexternalfigureresets
+
+\let\runutilityfiletrue \relax \let\runutilityfilefalse \relax
+\let\consultutilityfiletrue\relax \let\consultutilityfilefalse\relax
+
+%D You can register additional suffixes with the following command:
+%D
+%D \starttyping
+%D \definegraphictypesynonym[jbig] [jb2]
+%D \definegraphictypesynonym[jbig2][jb2]
+%D \definegraphictypesynonym[jbg] [jb2]
+%D \stoptyping
+
+\unexpanded\def\definegraphictypesynonym
+ {\dodoubleargument\dodefinegraphictypesynonym}
+
+\def\dodefinegraphictypesynonym[#1][#2]%
+ {\ctxlua{figures.registersuffix("#1","#2")}}
+
+%D Additional paths can be installed with the regular setup command. The next
+%D macro picks up the list.
+
+\def\setfigurepathlist
+ {\ctxlua{figures.setpaths("\@@exlocation",\!!bs\@@exdirectory\!!es)}}
+
+%D Variables:
+
+\def\defaultfigurewidth {8\lineheight}
+\def\defaultfigureheight {6\lineheight}
+
+\def\figurestatus {\numexpr\ctxlua{figures.tprint("status","status",0)}\relax} % number: 0 = not found
+\def\figurewidth {\ctxlua{figures.tprint("status","width",0)}sp}
+\def\figureheight {\ctxlua{figures.tprint("status","height",0)}sp}
+\def\figurexscale {\ctxlua{figures.tprint("status","xscale",1)}}
+\def\figureyscale {\ctxlua{figures.tprint("status","yscale",1)}}
+
+\def\figurelabel {\ctxlua{figures.tprint("request","label")}}
+\def\figurefileoriginal {\ctxlua{figures.tprint("request","name")}}
+\def\figurefilepage {\ctxlua{figures.tprint("request","page",1)}}
+\def\figurefileoptions {\ctxlua{figures.tprint("request","options")}}
+\def\figurefileconversion{\ctxlua{figures.tprint("request","conversion")}}
+\def\figurefilecache {\ctxlua{figures.tprint("request","cache")}}
+\def\figurefileprefix {\ctxlua{figures.tprint("request","prefix")}}
+
+\def\figurenaturalwidth {\ctxlua{figures.tprint("used","width", \number\dimexpr\defaultfigurewidth \relax)}sp}
+\def\figurenaturalheight {\ctxlua{figures.tprint("used","height",\number\dimexpr\defaultfigureheight\relax)}sp}
+
+\def\figurefilepath {\ctxlua{tex.sprint(tex.ctxcatcodes,file.dirname (figures.get("used","fullname")))}}
+\def\figurefilename {\ctxlua{tex.sprint(tex.ctxcatcodes,file.nameonly(figures.get("used","fullname")))}}
+\def\figurefiletype {\ctxlua{tex.sprint(tex.ctxcatcodes,file.extname (figures.get("used","fullname")))}}
+\def\figurefullname {\ctxlua{figures.tprint("used","fullname")}}
+\def\noffigurepages {\ctxlua{figures.tprint("used","pages",0)}}
+
+\let\naturalfigurewidth \figurenaturalwidth
+\let\naturalfigureheight \figurenaturalheight
+
+\let\figurescalewidth \figurewidth
+\let\figurescaleheight \figureheight
+\let\figurescalexscale \figurexscale
+\let\figurescaleyscale \figureyscale
+
+\appendtoks
+ \ctxlua { % figures.defaultwidth .. why not dimen
+ figures.setpaths("\@@exlocation","\@@exdirectory") ;
+ figures.defaultwidth = \number\dimexpr\defaultfigurewidth \relax ;
+ figures.defaultheight = \number\dimexpr\defaultfigureheight\relax ;
+ figures.boxnumber = \number\foundexternalfigure ;
+ }%
+\to \everyexternalfigureresets
+
+%D In some situations we need to make sure that the figure related variables
+%D are reset. This is especially important when we are nesting. Is this still
+%D needed in \MKIV.
+
+\def\resetexternalfigures
+ {\let\@@efoption \empty % \let\@@efprefix\empty
+ \let\@@efmaxwidth \empty % \let\@@efcache \empty
+ \let\@@efmaxheight \empty % \let\@@efframe \v!off
+ \let\@@efforegroundcolor\empty
+ \let\@@efcolor \empty
+ \let\@@efconversion \empty
+ \let\@@efbackground \empty}
+
+\appendtoks \resetexternalfigures \to \everyoverlay
+\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed
+
+\def\resetfigureusersettings
+ {%
+ \let\@@efmethod \empty
+ \let\@@eflabel \empty
+ \let\@@efsize \empty
+ \let\@@efconversion\@@exconversion
+ \let\@@efprefix \@@exprefix
+ \let\@@efcache \@@excache
+ \let\@@efpage \!!zerocount
+ \let\@@efobject \@@exobject
+ \let\@@efdisplay \empty
+ %
+ \let\@@efpreset \v!yes
+ \let\@@efsplit \empty
+ \let\@@efcolor \empty
+ %
+ \let\@@efsymbol \v!no
+ %
+ \let\@@efcontrols \v!no
+ \let\@@efpreview \v!no
+ \let\@@efrepeat \v!no
+ %
+ \let\@@efforegroundcolor\empty
+ %
+ \let\@@efhfactor \empty
+ \let\@@efwfactor \empty
+ \let\@@effactor \empty
+ \let\@@efmaxwidth \@@exmaxwidth
+ \let\@@efmaxheight \@@exmaxheight
+ \let\@@efxscale \empty
+ \let\@@efyscale \empty
+ \let\@@efscale \empty
+ \let\@@efsx \!!plusone
+ \let\@@efsy \!!plusone
+ \let\@@efwidth \empty
+ \let\@@efheight \empty
+ \let\@@eflines \empty
+ \let\@@efgrid \empty}
+
+\resetfigureusersettings
+
+\appendtoks
+ \resetfigureusersettings
+\to \everyexternalfigureresets
+
+\def\checkfigureusersettings
+ {% old features
+ \doif\@@exoption\v!frame
+ {\let\@@efframe\v!on}%
+ \doif\@@exoption\v!empty
+ {\skipexternalfigurestrue
+ \let\@@efframe\v!off}%
+ \doifsomething\@@efwidth {\doifdimensionelse\@@efwidth {\edef\@@efwidth {\the\dimexpr\@@efwidth }}\donothing}%
+ \doifsomething\@@efheight{\doifdimensionelse\@@efheight{\edef\@@efheight{\the\dimexpr\@@efheight}}\donothing}%
+ % fake color in gray bitmaps, assumes that
+ % a transparent color is used
+ \doifsomething\@@efforegroundcolor
+ {\def\@@efbackground{\v!foreground,\v!color}%
+ \def\@@efbackgroundcolor{\@@efforegroundcolor}}}
+
+\appendtoks
+ \checkfigureusersettings
+\to \everyexternalfigurechecks
+
+%D Internal graphics are handled at the \TEX\ end:
+
+\def\doprocesstexlikefigure#1% retrofit into mkii
+ {\global\setbox\foundexternalfigure\vbox\framed
+ [\c!strut=\v!no,\c!align=\v!normal,\c!frame=\v!off,
+ \c!offset=\v!overlay,\c!width=\v!fit,\c!height=\v!fit]
+ {\blank[\v!disable]#1\endgraf\removelastskip}} % disable should stay here!
+
+\def\doprocessmpslikefigure#1% retrofit into mkii
+ {\global\setbox\foundexternalfigure\vbox{\convertMPtoPDF{#1}11}}
+
+\def\docheckfigurebuffer #1{\doprocesstexlikefigure{\getbuffer[#1]}}
+\def\docheckfiguretex #1{\doprocesstexlikefigure{\input#1\relax}}
+\def\docheckfiguremps #1{\doprocessmpslikefigure{#1}}
+\def\docheckfiguremprun #1#2{\doprocesstexlikefigure{\useMPrun{#1}{#2}}}
+
+\def\doscalefigure
+ {\global\setbox\foundexternalfigure\vbox{\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}}
+
+\newconditional\testexternalfigureonly
+
+% \enabletrackers[figures.conversion]
+% \externalfigure[demo.svg]
+% \externalfigure[demo.svg][conversion=png]
+
+\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current
+ {\dontcomplain
+ \restorecatcodes
+ \forgetall
+ \resetfigurevariables
+ \dosetefparameters{#4}{#5}{#6}%
+ \checkfigurevariables
+% \begingroup
+% \color[\@@efcolor]{\xdef\globcolorattr{\internalspotcolorname}}
+% \endgroup
+ \ctxlua{figures.push {
+ name="#3",
+ label="#2", % todo: \@eflabel
+ page="\@@efpage",
+ size="\@@efsize",
+ object="\@@efobject",
+ prefix="\@@efprefix",
+ cache="\@@efcache",
+ format="\@@efmethod",
+ preset="\@@efprefix",
+ controls="\@@efcontrols",
+ preview="\@@efpreview",
+ display="\@@efdisplay",
+ conversion="\@@efconversion",
+ color="\internalspotcolorparent\@@efcolor", % hack is needed
+ ["repeat"]="\@@efrepeat",
+ width="\@@efwidth", % can be crap
+ height="\@@efheight", % can be crap
+ } }%
+ \ctxlua{figures.identify()}%
+ \ifconditional\testexternalfigureonly
+ \ifcase\figurestatus \else
+ \ctxlua{figures.check()}%
+ \ctxlua{figures.dummy()}%
+ \ctxlua{figures.scale()}%
+ \ctxlua{figures.done()}%
+ \fi
+ \signalexternalfigure
+ \else
+ \ifcase\figurestatus
+ \ctxlua{figures.dummy()}%
+ \ctxlua{figures.scale()}%
+ \else
+ \ctxlua{figures.check()}%
+ \ctxlua{figures.include()}%
+ \ctxlua{figures.scale()}%
+ \fi
+ \ctxlua{figures.done()}%
+ \signalexternalfigure
+ \finishexternalfigure
+ \fi
+ \ctxlua{figures.pop()}}
+
+\def\relocateexternalfigure % easier here than in lua
+ {\global\setbox\foundexternalfigure\vbox to \ht\foundexternalfigure\bgroup
+ \vss
+ \ht\foundexternalfigure\zeropoint
+ \hbox to \wd\foundexternalfigure\bgroup
+ \box\foundexternalfigure
+ \hss
+ \egroup
+ \egroup}
+
+\def\signalexternalfigure % global
+ {\ifcase\figurestatus
+ \global\resetsystemmode\v!figure % todo, also: \v!resource
+ \else
+ \global\setsystemmode \v!figure % todo, also: \v!resource
+ \fi}
+
+\unexpanded\def\startfoundexternalfigure#1#2% ht wd
+ {\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup}
+
+\unexpanded\def\stopfoundexternalfigure
+ {\hss\egroup\egroup}
+
+\def\emptyfoundexternalfigure
+ {\startfoundexternalfigure\defaultfigurewidth\defaultfigureheight
+ \stopfoundexternalfigure}
+
+\def\finishexternalfigure % here we use \figurevariables
+ {\global\setbox\foundexternalfigure\vbox
+ {\ifcase\figurestatus
+ \let\@@efframe\v!on
+ \fi
+ \ifconditional\externalfigureflush
+ \ifconditional\externalfigurelevel % probably background
+ \ifskipexternalfigures
+ % nothing
+ \fakebox\foundexternalfigure
+ \else\ifcase\figurestatus
+ % nothing
+ \else
+ \the\externalfigurepostprocessors
+ \box\foundexternalfigure
+ \fi\fi
+ \else
+ \iftrialtypesetting \else \feedbackexternalfigure \fi
+ \settrue\externalfigurelevel
+ \ifskipexternalfigures
+ \ifcase\figurestatus
+ \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}%
+ \else
+ \externalfigurereplacement\figurelabel\figurefullname{skipped}%
+ \fi
+ \else\ifcase\figurestatus
+ \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}%
+ \else
+ \the\externalfigurepostprocessors
+ \doifelse\@@efreset\v!yes
+ {\wd\foundexternalfigure\figurewidth
+ \ht\foundexternalfigure\figureheight
+ \dp\foundexternalfigure\zeropoint
+ \box\foundexternalfigure}
+ {\localframed % should also be applied to high res !
+ [\??ef]
+ [\c!offset=\v!overlay,
+ \c!width=\figurewidth,
+ \c!height=\figureheight]
+ {\vfilll\box\foundexternalfigure}}%
+ \fi\fi
+ \fi
+ \else
+ % maybe also \the\externalfigurepostprocessors
+ \iftrialtypesetting \else \feedbackexternalfigure \fi
+ \fi}}
+
+\ifx\externalfigurereplacement\undefined\let\externalfigurereplacement\gobblethreearguments\fi
+\ifx\externalfigureplaceholder\undefined\let\externalfigureplaceholder\gobblethreearguments\fi
+
+\let\feedbackexternalfigure\relax % \gobblefourarguments
+\let\dowithfigure \relax
+
+\def\getfiguredimensions
+ {\dodoubleempty\dogetfiguredimensions}
+
+\def\dogetfiguredimensions[#1][#2]%
+ {\startnointerference
+ \settrue\testexternalfigureonly
+ \externalfigure[#1][#2,\c!display=,\c!object=\v!no]%
+ \stopnointerference}
+
+\let\getfiguredimensionsonly\getfiguredimensions
+
+\def\doiffigureelse#1%
+ {\getfiguredimensions[#1]% so data is available !
+ \ifdim\figurewidth=\zeropoint % todo: \figurestatus
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\registerexternalfigure % no placement, handy for preprocessing
+ {\dotripleempty\doregisterexternalfigure}
+
+\def\doregisterexternalfigure[#1][#2][#3]%
+ {\startnointerference
+ \testexternalfigureonly
+ \setfalse\externalfigureflush % == test ?
+ \externalfigure[#1][#2][#3]% or \doexternalfigure
+ \externalfigure[#1][#2,\c!display=,\c!object=\v!no]%
+ \stopnointerference}
+
+% figurebases
+
+\def\usefigurebase[#1]%
+ {\ctxlua{figures.bases.use("#1")}}
+
+\protect \endinput
+
+% \startbuffer
+% \definecolor [blue] [c=1,m=.38,y=0,k=.64]
+% \definecolor [yellow] [c=0,m=.28,y=1,k=.06]
+%
+% \definespotcolor [blue-100] [blue] [p=1]
+% \definespotcolor [yellow-100] [yellow] [p=1]
+%
+% \definemultitonecolor [combicolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
+%
+% \definemultitonecolor [combicolor-b] [blue=1] [c=1,m=.38,y=0,k=.64] % force multitone
+% \definemultitonecolor [combicolor-y] [yellow=1] [c=0,m=.28,y=1,k=.06] % force multitone
+%
+% \useexternalfigure[demo-a][mill.png] [object=no,width=.2\textwidth]
+% \useexternalfigure[demo-b][hacker-bw.jpg][object=no,width=.2\textwidth]
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-a]} {no color}
+% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-a][color=combicolor-b]} {spot color}
+% {\externalfigure[demo-a][color=combicolor-y]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-b]} {no color}
+% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-b][color=combicolor-b]} {spot color}
+% {\externalfigure[demo-b][color=combicolor-y]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-a]} {no color}
+% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-a][color=blue-100]} {spot color}
+% {\externalfigure[demo-a][color=yellow-100]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-b]} {no color}
+% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-b][color=blue-100]} {spot color}
+% {\externalfigure[demo-b][color=yellow-100]} {spot color}
+% \stopcombination \stopbaselinecorrection
+% \stopbuffer
+%
+% \getbuffer \typebuffer
diff --git a/tex/context/base/grph-swf.lua b/tex/context/base/grph-swf.lua
new file mode 100644
index 000000000..e55454b52
--- /dev/null
+++ b/tex/context/base/grph-swf.lua
@@ -0,0 +1,43 @@
+if not modules then modules = { } end modules ['grph-swf'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+local texsprint = tex.sprint
+local ctxcatcodes = tex.ctxcatcodes
+local pdfannotation = nodes.pdfannotation
+
+function figures.checkers.swf(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local width = (dr.width or figures.defaultwidth):todimen()
+ local height = (dr.height or figures.defaultheight):todimen()
+ local foundname = du.fullname
+ dr.width, dr.height = width, height
+ du.width, du.height, du.foundname = width, height, foundname
+ texsprint(ctxcatcodes,format("\\startfoundexternalfigure{%ssp}{%ssp}",width,height))
+ local annot, preview, ref = backends.pdf.helpers.insertswf {
+ foundname = foundname,
+ width = width,
+ height = height,
+ -- factor = number.dimenfactors.bp,
+ -- display = dr.display,
+ -- controls = dr.controls,
+ -- label = dr.label,
+ }
+ -- node.write(pdfannotation(width,-height,0,annot()))
+ texsprint(ctxcatcodes,format("\\pdfannot width %ssp height %ssp {%s}",width,height,annot())) -- brrrr
+--~ if ref then -- wrong ! a direct ref should work
+--~ texsprint(ctxcatcodes,format("\\smash{\\pdfrefximage%s\\relax}",ref)) -- brrrr
+--~ end
+ texsprint(ctxcatcodes,"\\stopfoundexternalfigure")
+ return data
+end
+
+figures.includers.swf = figures.includers.nongeneric
+
+figures.registersuffix("swf","swf")
diff --git a/tex/context/base/grph-trf.mkii b/tex/context/base/grph-trf.mkii
new file mode 100644
index 000000000..3e32395b4
--- /dev/null
+++ b/tex/context/base/grph-trf.mkii
@@ -0,0 +1,579 @@
+%D \module
+%D [ file=grph-fig,
+%D version=2006.08.26, % overhaul/split of 1997.03.31 core-fig
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Transformations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 It may be that some functionality got lost. If it concerns
+%D defined features, let me know and it will be sorted out.
+
+\writestatus{loading}{ConTeXt Graphic Macros / Transformations}
+
+\unprotect
+
+%D Scaling:
+
+\unexpanded\def\scale{\dodoubleempty\doscalenextbox[\??xy]}
+
+% probably too many dimens / the width calculations can go
+% since we may assume scaling is available (was not true
+% long ago which is why we also calculate the width)
+
+\newdimen\scaleboxwidth
+\newdimen\scaleboxheight
+\newdimen\scaleboxdepth
+
+\newdimen\scaleboxsizex
+\newdimen\scaleboxsizey
+\newdimen\scaleboxoffsetx
+\newdimen\scaleboxoffsety
+
+\newdimen\scaleboxhsize
+\newdimen\scaleboxvsize
+
+% global
+
+\newdimen\scaleboxdimx \let\figwid \scaleboxdimx
+\newdimen\scaleboxdimy \let\fighei \scaleboxdimy
+\newcount\scaleboxscax \let\figxsca\scaleboxscax
+\newcount\scaleboxscay \let\figysca\scaleboxscay
+
+\newdimen\scaleboxoutervsize % we cannot manipulate any global vsize !
+
+\let\finalscaleboxxscale \!!plusone
+\let\finalscaleboxyscale \!!plusone
+\let\finalscaleboxwidth \!!zeropoint
+\let\finalscaleboxheight \!!zeropoint
+\let\finalscaleboxxfactor\!!hundred
+\let\finalscaleboxyfactor\!!hundred
+
+\newconditional\scaleboxdone
+
+\def\doscalenextbox[#1][#2]%
+ {\bgroup
+ \getparameters
+ [#1]
+ [\c!scale=,\c!xscale=,\c!yscale=,\c!width=,\c!height=,\c!lines=,
+ \c!factor=,\c!hfactor=,\c!wfactor=,\c!grid=,\c!sx=1,\c!sy=1,
+ \c!equalwidth=,\c!equalheight=,
+ \c!maxwidth=\scaleparameter\c!width,\c!maxheight=\scaleparameter\c!height,
+ #2]%
+ \dowithnextbox{\dodoscalenextbox{#1}\egroup}\hbox}
+
+\def\doscalebox#1%
+ {\bgroup\dowithnextbox{\dodoscalenextbox{#1}\egroup}\hbox}
+
+\let\currentscaletag\??xy
+
+\def\scaleparameter#1%
+ {\csname\currentscaletag#1\endcsname}
+
+\def\setscaleparameter#1#2%
+ {\setvalue{\currentscaletag#1}{#2}}
+
+\def\dodoscalenextbox#1%
+ {\edef\currentscaletag{#1}%
+ \doif{\scaleparameter\c!depth}\v!no{\setbox\nextbox\hbox{\raise\nextboxdp\box\nextbox}}% new
+ \forgetall
+ \dontshowcomposition
+ \dontcomplain
+ \doscaleboxcalculations
+ \doscaleboxindeed
+ \doscaleboxposition
+ \flushnextbox}
+
+\def\doscaleboxindeed
+ {\ifconditional\scaleboxdone
+ \scaleboxwidth \finalscaleboxxscale\nextboxwd
+ \scaleboxheight\finalscaleboxyscale\nextboxht
+ \scaleboxdepth \finalscaleboxyscale\nextboxdp
+ \setbox\nextbox\hbox
+ {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
+ \smashedbox\nextbox
+ \dostopscaling}%
+ \nextboxwd\scaleboxwidth
+ \nextboxht\scaleboxheight
+ \nextboxdp\scaleboxdepth
+ \fi}
+
+\def\doscaleboxcalculations
+ {\setfalse\scaleboxdone
+ % initial final value
+ \global\let\finalscaleboxxscale \!!plusone
+ \global\let\finalscaleboxyscale \!!plusone
+ \xdef \finalscaleboxwidth {\the\nextboxwd}%
+ \xdef \finalscaleboxheight{\the\nextboxht}%
+ \global\let\finalscaleboxxfactor\!!hundred
+ \global\let\finalscaleboxyfactor\!!hundred
+ \ifdim\nextboxht>\zeropoint \ifdim\nextboxwd>\zeropoint
+ \edef\scaleboxstampa % slow way [can be combined]
+ {\scaleparameter\c!scale \scaleparameter\c!xscale \scaleparameter\c!yscale
+ \scaleparameter\c!factor\scaleparameter\c!wfactor\scaleparameter\c!hfactor
+ \scaleparameter\c!lines \scaleparameter\c!width \scaleparameter\c!height}%
+ \edef\scaleboxstampb % fast way [just sx/sy]
+ {\scaleparameter\c!sx
+ \scaleparameter\c!sy}%
+ \edef\scaleboxstampc
+ {11}%
+ \ifx\scaleboxstampa\empty
+ \ifx\scaleboxstampb\scaleboxstampc
+ % no scaling, but still check; new, gone again
+% wrong: scaled proportionally as side effect
+% \doifsomething{\scaleparameter\c!maxwidth }{\letvalue{\currentscaletag\c!factor}\v!fit}%
+% \doifsomething{\scaleparameter\c!maxheight}{\letvalue{\currentscaletag\c!factor}\v!fit}%
+ \insidefloattrue % trick
+ \dodoscaleboxcalculations
+ \else
+ \dosetscalboxsxsy
+ \nodoscaleboxcalculations
+ \fi
+ \else
+ \ifx\scaleboxstampb\empty
+ % no need to check further
+ \else
+ \dosetscalboxsxsy
+ \fi
+ \dodoscaleboxcalculations
+ \fi
+ \fi \fi}
+
+\def\dosetscalboxsxsy
+ {\ifdim\scaleparameter\c!sx\onepoint=\onepoint\else
+ \setevalue{\currentscaletag\c!width }{\the\dimexpr\scaleparameter\c!sx\wd\nextbox\relax}%
+ \fi
+ \ifdim\scaleparameter\c!sy\onepoint=\onepoint\else
+ \setevalue{\currentscaletag\c!height}{\the\dimexpr\scaleparameter\c!sy\ht\nextbox\relax}%
+ \fi}
+
+\def\doscaleboxrounding#1.#2\relax{#1}
+
+\def\scaleboxrounding#1%
+ {\@EA\@EA\@EA\doscaleboxrounding\@EA\WITHOUTPT\the\dimexpr#1\points*100+32768sp\relax.\relax}
+
+\def\nodoscaleboxcalculations
+ {\settrue\scaleboxdone
+ \xdef\finalscaleboxwidth {\the\dimexpr\scaleparameter\c!sx\wd\nextbox\relax}%
+ \xdef\finalscaleboxheight {\the\dimexpr\scaleparameter\c!sy\ht\nextbox\relax}%
+ \xdef\finalscaleboxxscale {\scaleparameter\c!sx}%
+ \xdef\finalscaleboxyscale {\scaleparameter\c!sy}%
+ \ifx\finalscaleboxxscale\empty\let\finalscaleboxxscale\!!plusone\fi
+ \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi
+ \xdef\finalscaleboxxfactor{\scaleboxrounding\finalscaleboxxscale}%
+ \xdef\finalscaleboxyfactor{\scaleboxrounding\finalscaleboxyscale}}
+
+\def\dodoscaleboxcalculations
+ {\settrue\scaleboxdone
+ % initial values
+ \scaleboxoffsetx\zeropoint
+ \scaleboxoffsety\zeropoint
+ \scaleboxsizex \nextboxwd
+ \scaleboxsizey \nextboxht % alleen ht wordt geschaald!
+ % final values
+ \global\scaleboxdimx \zeropoint % see note * (core-fig)
+ \global\scaleboxdimy \zeropoint % see note * (core-fig)
+ \scaleboxscax \plusone % see note * (core-fig)
+ \scaleboxscay \plusone % see note * (core-fig)
+ % preparations
+ \setfalse\scaleboxscalingdone
+ \checkscaleboxsettings
+ % calculators
+ % beware, they operate in sequence, and calculate missing dimensions / messy
+ %setscaleboxbynature % when? needed?
+ \ifconditional\scaleboxscalingdone\else\setscaleboxbyfactor \fi
+ \ifconditional\scaleboxscalingdone\else\setscaleboxbyscale \fi
+ \ifconditional\scaleboxscalingdone\else\setscaleboxbydimension\fi
+ % finalizers / to be done (no longer needed this way, clean up)
+ \convertscaleboxinsertscale\scaleboxhsize\figx\scaleboxscax\scax
+ \convertscaleboxinsertscale\scaleboxvsize\figy\scaleboxscay\scay
+ % used in actual scaling
+ \xdef\finalscaleboxwidth {\the\scaleboxdimx}%
+ \xdef\finalscaleboxheight {\the\scaleboxdimy}%
+ \xdef\finalscaleboxxfactor{\the\scaleboxscax}%
+ \xdef\finalscaleboxyfactor{\the\scaleboxscay}%
+ \xdef\finalscaleboxxscale {\withoutpt\the\dimexpr\scax\points/\plushundred\relax}%
+ \xdef\finalscaleboxyscale {\withoutpt\the\dimexpr\scay\points/\plushundred\relax}}
+
+
+\setvalue{\??xy:\c!grid:\v!yes }{\getnoflines \fighei\setevalue{\currentscaletag\c!height}{\the\noflines\lineheight}}
+\setvalue{\??xy:\c!grid:\v!height }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight+\strutdepth\relax}}
+\setvalue{\??xy:\c!grid:\v!depth }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight-\strutdepth\relax}}
+\setvalue{\??xy:\c!grid:\v!halfline}{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight+.5\lineheight\relax}}
+\setvalue{\??xy:\c!grid:\v!fit }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\noflines\lineheight}}
+\letvalue{\??xy:\c!grid:\empty }\donothing
+
+\def\checkscaleboxsettings
+ {\doifsomething{\scaleparameter\c!maxwidth }% can be defined in itself
+ {\setevalue{\currentscaletag\c!maxwidth }{\the\dimexpr\scaleparameter\c!maxwidth \relax}}%
+ \doifsomething{\scaleparameter\c!maxheight}% can be defined in itself
+ {\setevalue{\currentscaletag\c!maxheight}{\the\dimexpr\scaleparameter\c!maxheight\relax}}%
+ \doifsomething{\scaleparameter\c!lines}
+ {\setevalue{\currentscaletag\c!height}{\the\dimexpr\scaleparameter\c!lines\lineheight\relax}}%
+ \getvalue{\??xy:\c!grid:\scaleparameter\c!grid}}
+
+\def\setscaleboxbynature % where ! ! ! ! !
+ {\doifsomething{\scaleparameter\c!width }{\global\scaleboxdimx\scaleparameter\c!width }%
+ \doifsomething{\scaleparameter\c!height}{\global\scaleboxdimy\scaleparameter\c!height}%
+ \doifsomething{\scaleparameter\c!scale } {\scaleboxscax\scaleparameter\c!scale
+ \scaleboxscay\scaleparameter\c!scale }%
+ \doifsomething{\scaleparameter\c!xscale} {\scaleboxscax\scaleparameter\c!xscale}%
+ \doifsomething{\scaleparameter\c!yscale} {\scaleboxscay\scaleparameter\c!yscale}} % oeps, was x
+
+% \defineexternalfigure[width-6][factor=auto,maxwidth=\textheight,maxheight=\textwidth]
+% \defineexternalfigure[width-7][factor=auto,maxwidth=\textwidth,maxheight=\textheight]
+% \placefigure{none}{\rotate[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-6]}} \page
+% \placefigure{none}{\framed[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-7]}}
+
+\def\setscaleboxbyfactor
+ {\doifinsetelse{\scaleparameter\c!factor}{\v!max,\v!fit,\v!broad,\v!auto}
+ {\doapplyscaleboxsize
+ \ifdim\scaleboxsizex>\scaleboxsizey
+ \docalculatescaleboxnorm \scaleboxdimx\c!factor\c!maxwidth\hsize\scaleboxhsize
+ \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
+ \else
+ \docalculatescaleboxnorm \scaleboxdimy\c!factor\c!maxheight\scaleboxoutervsize\scaleboxvsize
+ \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
+ \fi
+ \donetrue}
+ {\doifinsetelse{\scaleparameter\c!hfactor}{\v!max,\v!fit,\v!broad,\v!auto}
+ {\doapplyscaleboxsize
+ \docalculatescaleboxnorm \scaleboxdimy\c!hfactor\c!maxheight\scaleboxoutervsize\scaleboxvsize
+ \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
+ \donetrue}
+ {\doifinsetelse{\scaleparameter\c!wfactor}{\v!max,\v!fit,\v!broad,\v!auto}
+ {\doapplyscaleboxsize
+ \docalculatescaleboxnorm \scaleboxdimx\c!wfactor\c!maxwidth\hsize\scaleboxhsize
+ \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
+ \donetrue}
+ {\docalculatescaleboxnorm\scaleboxdimy\c!factor \c!height \textheight\scaleboxvsize
+ \docalculatescaleboxnorm\scaleboxdimy\c!hfactor\c!height \textheight\scaleboxvsize
+ \docalculatescaleboxnorm\scaleboxdimx\c!wfactor\c!width \hsize \hsize
+ \donefalse}}}%
+ \ifdone
+ \settrue\scaleboxscalingdone
+ \ifdim\scaleboxdimx>\scaleboxhsize
+ \global\scaleboxdimy\zeropoint \global\scaleboxdimx\scaleboxhsize
+ \else\ifdim\scaleboxdimy>\scaleboxvsize
+ \global\scaleboxdimx\zeropoint \global\scaleboxdimy\scaleboxvsize
+ \fi\fi
+ \setscaleboxbydimension
+ \fi}
+
+\def\setscaleboxbyscale
+ {\doifsomething{\scaleparameter\c!scale\scaleparameter\c!xscale\scaleparameter\c!yscale}
+ {\doapplyscaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax\c!xscale
+ \doapplyscaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay\c!yscale
+ \global\scaleboxdimx\zeropoint
+ \global\scaleboxdimy\zeropoint
+ \doifelsenothing{\scaleparameter\c!maxwidth}
+ {\doifsomething{\scaleparameter\c!maxheight}
+ {\ifdim\scaleboxsizey>\scaleparameter\c!maxheight\relax
+ \global\scaleboxdimy\scaleparameter\c!maxheight
+ \fi}}
+ {\ifdim\scaleboxsizex>\scaleparameter\c!maxwidth\relax
+ \global\scaleboxdimx\scaleparameter\c!maxwidth
+ \fi}}}
+
+\def\setscaleboxbydimension
+ {\ifdim\scaleboxdimx>\zeropoint
+ \ifdim\scaleboxdimy>\zeropoint
+ \dosetdimensionscaleboxsize
+ {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
+ \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
+ {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
+ \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
+ {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
+ \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
+ \else
+ \dosetdimensionscaleboxsize
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ \fi
+ \else
+ \ifdim\scaleboxdimy>\zeropoint
+ \dosetdimensionscaleboxsize
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ \else
+ \dosetdimensionscaleboxsize
+ {\doapplyscaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax\c!xscale
+ \doapplyscaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay\c!yscale}%
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ \fi
+ \fi}
+
+\def\dosetdimensionscaleboxsize#1#2#3%
+ {#1\relax
+ \doifsomething{\scaleparameter\c!maxwidth}
+ {\ifdim\scaleboxdimx>\scaleparameter\c!maxwidth\relax
+ \global\scaleboxdimx\scaleparameter\c!maxwidth
+ #2\relax
+ \fi}%
+ \doifsomething{\scaleparameter\c!maxheight}
+ {\ifdim\scaleboxdimy>\scaleparameter\c!maxheight\relax
+ \global\scaleboxdimy\scaleparameter\c!maxheight
+ #3\relax
+ \fi}}
+
+\def\docalculatescaleboxnorm#1#2#3#4#5% 2 3 parameters (dodo:speedup)
+ {\processaction
+ [\scaleparameter#2]
+ [ \v!max=>\global#1\dimexpr#4\relax,
+ \v!fit=>\global#1\dimexpr#5\relax,
+ \v!broad=>\global#1\dimexpr#5-4\@@exbodyfont\relax,
+ \v!auto=>\doifsomething{\scaleparameter#3}{\global#1\dimexpr\scaleparameter#3\relax},
+ \s!default=>\doifsomething{\scaleparameter#3}{\global#1\dimexpr\scaleparameter#3\relax},
+ \s!unknown=>\global#1\dimexpr\scaleparameter#2\dimexpr\@@exbodyfont/10\relax\relax]}
+
+\def\docalculatescaleboxscales#1#2#3#4%
+ {\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax
+ \scaleboxscax\scratchdimen
+ \scaleboxscay\scratchdimen
+ #3\dimexpr\scaleboxscax\dimexpr#4/\plusthousand\relax\relax}
+
+\def\docalculatescaleboxscale#1#2#3%
+ {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax}
+
+\def\doapplyscaleboxscale#1#2#3#4% $4 = parameter / scale can be empty
+ {\ifcase0\scaleparameter#4\relax
+ \ifcase0\scaleparameter\c!scale\relax
+ #3=\plusthousand
+ \else
+ #3=\scaleparameter\c!scale
+ \fi
+ \else
+ #3=\scaleparameter#4%
+ \fi
+ \relax % important ! still ?
+ \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi
+ \relax}
+
+\def\doapplyscaleboxsize
+ {\doifelsenothing{\scaleparameter\c!maxheight}
+ {\scaleboxoutervsize\textheight
+ \ifinner
+ \scaleboxoutervsize \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinsidefloat
+ \scaleboxoutervsize \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinpagebody
+ \scaleboxoutervsize \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else % hm, there should be an option to force this
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \scratchdimen\pagegoal
+ \advance\scratchdimen -\pagetotal
+ \else
+ \scratchdimen\scaleboxoutervsize % \textheight
+ \fi
+ \else
+ \scratchdimen\scaleboxoutervsize % \textheight
+ \fi
+ \fi\fi\fi}
+ {\scratchdimen\scaleparameter\c!maxheight
+ \scaleboxoutervsize\scratchdimen}%
+ \doifelsenothing{\scaleparameter\c!height}
+ {\scaleboxvsize\scratchdimen}
+ {\scaleboxvsize\scaleparameter\c!height}%
+ \doifelsenothing{\scaleparameter\c!width}
+ {\scaleboxhsize\hsize}
+ {\scaleboxhsize\scaleparameter\c!width}}
+
+\def\convertscaleboxinsertscale#1#2#3#4%
+ {\scratchdimen#1\relax
+ \ifnum#3=\plusthousand
+ % == scale 1
+ \else
+ % better 1000 100 10 ranges, evt round 2sp
+ \divide\scratchdimen \plusthousand
+ \multiply\scratchdimen #3\relax
+ \fi
+ \scratchdimen-\scratchdimen % beter hier - dan in driver
+ \edef#2{\the\scratchdimen}%
+ \scratchcounter#3\relax
+ \ifnum\scratchcounter>\plustenthousand
+ \divide\scratchcounter\!!ten \scratchdimen\the\scratchcounter\points
+ \else
+ \scratchdimen\the\scratchcounter\points \divide\scratchdimen\!!ten
+ \fi
+ \edef#4{\withoutpt\the\scratchdimen}}
+
+% \startcombination
+% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {}
+% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {}
+% \stopcombination
+
+\def\doscaleboxposition
+ {\doifsomething{\scaleparameter\c!equalwidth}
+ {\scratchdimen\scaleparameter\c!equalwidth\relax
+ \ifdim\wd\nextbox<\scratchdimen
+ \setbox\nextbox\hbox to \scratchdimen{\hss\box\nextbox\hss}%
+ \fi}%
+ \doifsomething{\scaleparameter\c!equalheight}
+ {\scratchdimen\scaleparameter\c!equalheight\relax
+ \ifdim\ht\nextbox<\scratchdimen
+ \setbox\nextbox\vbox to \scratchdimen{\vss\box\nextbox\vss}%
+ \fi}}
+
+%D \macros
+%D {clip, setupclipping}
+%D
+%D Although related to figures, clipping can be applied to
+%D arbitrary content. We can use \METAPOST\ to provide a non
+%D rectangular clipping path.
+%D
+%D \starttyping
+%D \startMPclip{fun}
+%D clip currentpicture to fullcircle
+%D shifted (.5,.5) xscaled \width yscaled \height ;
+%D \stopMPclip
+%D \stoptyping
+%D
+%D We get a rectangular piece of the figure when we say:
+%D
+%D \starttyping
+%D \clip[x=2,y=1]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D When we want to clip to the oval we defined a few lines ago,
+%D we say:
+%D
+%D \starttyping
+%D \clip[nx=1,ny=1,x=1,y=1,mp=fun]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D The general characteristics of clipping can be set up with
+%D
+%D \showsetup{setupclipping}
+
+\def\setupclipping
+ {\dodoubleargument\getparameters[\??cp]}
+
+\def\clip
+ {\dosingleempty\doclip}
+
+\def\doclip[#1]% nb top->bottom left->right
+ {\bgroup
+ \getparameters[\??cp][#1]%
+ \doifelse\@@cpstate\v!start\dodoclip{\egroup\hbox}}
+
+\def\dodoclip
+ {\dowithnextbox
+ {\ifdim\@@cpwidth>\zeropoint
+ \!!dimena\@@cpwidth
+ \!!dimenc\@@cphoffset
+ \else
+ \!!dimena\nextboxwd
+ \divide\!!dimena \@@cpnx
+ \!!dimenc\@@cpx\!!dimena
+ \advance\!!dimenc -\!!dimena
+ \!!dimena\@@cpsx\!!dimena
+ \fi
+ \relax % sure
+ \ifdim\@@cpheight>\zeropoint
+ \!!dimenb\@@cpheight
+ \!!dimend\nextboxht
+ \advance\!!dimend -\@@cpvoffset
+ \advance\!!dimend -\!!dimenb
+ \else
+ \!!dimenb\nextboxht
+ \divide\!!dimenb \@@cpny
+ \!!dimend-\@@cpy\!!dimenb
+ \advance\!!dimend -\@@cpsy\!!dimenb
+ \advance\!!dimend \!!dimenb
+ \!!dimenb\@@cpsy\!!dimenb
+ \advance\!!dimend \nextboxht % dimend !
+ \fi
+ \setbox\nextbox\hbox % old
+ {\advance\!!dimenc -\@@cpleftoffset % new !
+ \advance\!!dimend -\@@cpbottomoffset % new ! % - added
+ \hskip-\!!dimenc\lower\!!dimend\flushnextbox}% old
+ \nextboxwd\zeropoint
+ \nextboxht\zeropoint
+ \nextboxdp\zeropoint
+ \setbox\nextbox\hbox
+ {\advance\!!dimena \@@cpleftoffset % new !
+ \advance\!!dimena \@@cprightoffset % new !
+ \advance\!!dimenb \@@cpbottomoffset % new !
+ \advance\!!dimenb \@@cptopoffset % new !
+ \dostartclipping\@@cpmp\!!dimena\!!dimenb % old
+ \flushnextbox
+ \dostopclipping}%
+ \setbox\nextbox\hbox % new !
+ {\!!dimena-\@@cpleftoffset % new !
+ \!!dimenb \@@cpbottomoffset % new ! % - removed
+ \hskip\!!dimena\lower\!!dimenb\flushnextbox}% new !
+ \nextboxwd\!!dimena
+ \nextboxht\!!dimenb
+ \nextboxdp\zeropoint
+ \flushnextbox
+ \egroup}%
+ \hbox}
+
+\setupclipping
+ [\c!state=\v!start,
+ \c!n=1, % was 2
+ \c!nx=\@@cpn,\c!x=1,\c!sx=1,
+ \c!ny=\@@cpn,\c!y=1,\c!sy=1,
+ \c!width=\!!zeropoint,
+ \c!height=\!!zeropoint,
+ \c!hoffset=\!!zeropoint,
+ \c!voffset=\!!zeropoint,
+ \c!offset=\zeropoint,
+ \c!leftoffset=\@@cpoffset, % \zeropoint,
+ \c!rightoffset=\@@cpoffset, % \zeropoint,
+ \c!topoffset=\@@cpoffset, % \zeropoint,
+ \c!bottomoffset=\@@cpoffset,% \zeropoint,
+ \c!mp=]
+
+%D \startbuffer
+%D \startuseMPgraphic{test}
+%D path p ; p := fullcircle scaled 4cm ;
+%D draw p withpen pencircle scaled 1cm ;
+%D setbounds currentpicture to boundingbox p ;
+%D \stopuseMPgraphic
+%D
+%D \hbox to \hsize \bgroup
+%D \hss
+%D \ruledhbox{\useMPgraphic{test}}%
+%D \hss
+%D \ruledhbox{\clip{\useMPgraphic{test}}}%
+%D \hss
+%D \egroup
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D Mirroring.
+
+\def\domirrorbox % \hbox/\vbox/\vtop
+ {\bgroup
+ \dowithnextbox
+ {\dontshowcomposition
+ \scratchdimen\nextboxwd
+ % better use an hbox (if no \forgetall, leftskip etc may creep in)
+ %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\nextboxwd\flushnextbox\dostopmirroring}%
+ \setbox\nextbox\hbox{\dostartmirroring\hskip-\nextboxwd\flushnextbox\dostopmirroring}%
+ \nextboxwd\scratchdimen
+ \flushnextbox
+ \egroup}}
+
+\unexpanded\def\mirror
+ {\domirrorbox\hbox}
+
+% \setbox0=\hbox{gans}
+% \ruledhbox{\copy0 \schaal[sx=2,sy=2]{\copy0}}
+% \mirror{\ruledhbox{\copy0 \schaal{\box0}}}
+
+\protect \endinput
diff --git a/tex/context/base/grph-trf.mkiv b/tex/context/base/grph-trf.mkiv
new file mode 100644
index 000000000..9924a68e8
--- /dev/null
+++ b/tex/context/base/grph-trf.mkiv
@@ -0,0 +1,580 @@
+%D \module
+%D [ file=grph-fig,
+%D version=2006.08.26, % overhaul/split of 1997.03.31 core-fig
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Transformations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 It may be that some functionality got lost. If it concerns
+%D defined features, let me know and it will be sorted out.
+
+%D We will move the calculations to lua.
+
+\writestatus{loading}{ConTeXt Graphic Macros / Transformations}
+
+\unprotect
+
+%D Scaling:
+
+\unexpanded\def\scale{\dodoubleempty\doscalenextbox[\??xy]}
+
+% probably too many dimens / the width calculations can go
+% since we may assume scaling is available (was not true
+% long ago which is why we also calculate the width)
+
+\newdimen\scaleboxwidth
+\newdimen\scaleboxheight
+\newdimen\scaleboxdepth
+
+\newdimen\scaleboxsizex
+\newdimen\scaleboxsizey
+\newdimen\scaleboxoffsetx
+\newdimen\scaleboxoffsety
+
+\newdimen\scaleboxhsize
+\newdimen\scaleboxvsize
+
+% global
+
+\newdimen\scaleboxdimx \let\figwid \scaleboxdimx
+\newdimen\scaleboxdimy \let\fighei \scaleboxdimy
+\newcount\scaleboxscax \let\figxsca\scaleboxscax
+\newcount\scaleboxscay \let\figysca\scaleboxscay
+
+\newdimen\scaleboxoutervsize % we cannot manipulate any global vsize !
+
+\let\finalscaleboxxscale \!!plusone
+\let\finalscaleboxyscale \!!plusone
+\let\finalscaleboxwidth \!!zeropoint
+\let\finalscaleboxheight \!!zeropoint
+\let\finalscaleboxxfactor\!!hundred
+\let\finalscaleboxyfactor\!!hundred
+
+\newconditional\scaleboxdone
+
+\def\doscalenextbox[#1][#2]%
+ {\bgroup
+ \getparameters
+ [#1]
+ [\c!scale=,\c!xscale=,\c!yscale=,\c!width=,\c!height=,\c!lines=,
+ \c!factor=,\c!hfactor=,\c!wfactor=,\c!grid=,\c!sx=1,\c!sy=1,
+ \c!equalwidth=,\c!equalheight=,
+ \c!maxwidth=\scaleparameter\c!width,\c!maxheight=\scaleparameter\c!height,
+ #2]%
+ \dowithnextbox{\dodoscalenextbox{#1}\egroup}\hbox}
+
+\def\doscalebox#1%
+ {\bgroup\dowithnextbox{\dodoscalenextbox{#1}\egroup}\hbox}
+
+\let\currentscaletag\??xy
+
+\def\scaleparameter#1%
+ {\csname\currentscaletag#1\endcsname}
+
+\def\setscaleparameter#1#2%
+ {\setvalue{\currentscaletag#1}{#2}}
+
+\def\dodoscalenextbox#1%
+ {\edef\currentscaletag{#1}%
+ \doif{\scaleparameter\c!depth}\v!no{\setbox\nextbox\hbox{\raise\nextboxdp\box\nextbox}}% new
+ \forgetall
+ \dontshowcomposition
+ \dontcomplain
+ \doscaleboxcalculations
+ \doscaleboxindeed
+ \doscaleboxposition
+ \flushnextbox}
+
+\def\doscaleboxindeed
+ {\ifconditional\scaleboxdone
+ \scaleboxwidth \finalscaleboxxscale\nextboxwd
+ \scaleboxheight\finalscaleboxyscale\nextboxht
+ \scaleboxdepth \finalscaleboxyscale\nextboxdp
+ \setbox\nextbox\hbox
+ {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
+ \smashedbox\nextbox
+ \dostopscaling}%
+ \nextboxwd\scaleboxwidth
+ \nextboxht\scaleboxheight
+ \nextboxdp\scaleboxdepth
+ \fi}
+
+\def\doscaleboxcalculations
+ {\setfalse\scaleboxdone
+ % initial final value
+ \global\let\finalscaleboxxscale \!!plusone
+ \global\let\finalscaleboxyscale \!!plusone
+ \xdef \finalscaleboxwidth {\the\nextboxwd}%
+ \xdef \finalscaleboxheight{\the\nextboxht}%
+ \global\let\finalscaleboxxfactor\!!hundred
+ \global\let\finalscaleboxyfactor\!!hundred
+ \ifdim\nextboxht>\zeropoint \ifdim\nextboxwd>\zeropoint
+ % hm, still useful? better in lua anyway
+ \edef\scaleboxstampa % slow way [can be combined]
+ {\scaleparameter\c!scale \scaleparameter\c!xscale \scaleparameter\c!yscale
+ \scaleparameter\c!factor\scaleparameter\c!wfactor\scaleparameter\c!hfactor
+ \scaleparameter\c!lines \scaleparameter\c!width \scaleparameter\c!height}%
+ \edef\scaleboxstampb % fast way [just sx/sy]
+ {\scaleparameter\c!sx
+ \scaleparameter\c!sy}%
+ \edef\scaleboxstampc
+ {11}%
+ \ifx\scaleboxstampa\empty
+ \ifx\scaleboxstampb\scaleboxstampc
+ % no scaling, but still check; new, gone again
+% wrong: scaled proportionally as side effect
+% \doifsomething{\scaleparameter\c!maxwidth }{\letvalue{\currentscaletag\c!factor}\v!fit}%
+% \doifsomething{\scaleparameter\c!maxheight}{\letvalue{\currentscaletag\c!factor}\v!fit}%
+ \insidefloattrue % trick
+ \dodoscaleboxcalculations
+ \else
+ \dosetscalboxsxsy
+ \nodoscaleboxcalculations
+ \fi
+ \else
+ \ifx\scaleboxstampb\empty
+ % no need to check further
+ \else
+ \dosetscalboxsxsy
+ \fi
+ \dodoscaleboxcalculations
+ \fi
+ \fi \fi}
+
+\def\dosetscalboxsxsy
+ {\ifdim\scaleparameter\c!sx\onepoint=\onepoint\else
+ \setevalue{\currentscaletag\c!width }{\the\dimexpr\scaleparameter\c!sx\wd\nextbox\relax}%
+ \fi
+ \ifdim\scaleparameter\c!sy\onepoint=\onepoint\else
+ \setevalue{\currentscaletag\c!height}{\the\dimexpr\scaleparameter\c!sy\ht\nextbox\relax}%
+ \fi}
+
+\def\doscaleboxrounding#1.#2\relax{#1}
+
+\def\scaleboxrounding#1%
+ {\@EA\@EA\@EA\doscaleboxrounding\@EA\WITHOUTPT\the\dimexpr#1\points*100+32768sp\relax.\relax}
+
+\def\nodoscaleboxcalculations
+ {\settrue\scaleboxdone
+ \xdef\finalscaleboxwidth {\the\dimexpr\scaleparameter\c!sx\wd\nextbox\relax}%
+ \xdef\finalscaleboxheight {\the\dimexpr\scaleparameter\c!sy\ht\nextbox\relax}%
+ \xdef\finalscaleboxxscale {\scaleparameter\c!sx}%
+ \xdef\finalscaleboxyscale {\scaleparameter\c!sy}%
+ \ifx\finalscaleboxxscale\empty\let\finalscaleboxxscale\!!plusone\fi
+ \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi
+ \xdef\finalscaleboxxfactor{\scaleboxrounding\finalscaleboxxscale}%
+ \xdef\finalscaleboxyfactor{\scaleboxrounding\finalscaleboxyscale}}
+
+\def\dodoscaleboxcalculations
+ {\settrue\scaleboxdone
+ % initial values
+ \scaleboxoffsetx\zeropoint
+ \scaleboxoffsety\zeropoint
+ \scaleboxsizex \nextboxwd
+ \scaleboxsizey \nextboxht % alleen ht wordt geschaald!
+ % final values
+ \global\scaleboxdimx \zeropoint % see note * (core-fig)
+ \global\scaleboxdimy \zeropoint % see note * (core-fig)
+ \scaleboxscax \plusone % see note * (core-fig)
+ \scaleboxscay \plusone % see note * (core-fig)
+ % preparations
+ \setfalse\scaleboxscalingdone
+ \checkscaleboxsettings
+ % calculators
+ % beware, they operate in sequence, and calculate missing dimensions / messy
+ %setscaleboxbynature % when? needed?
+ \ifconditional\scaleboxscalingdone\else\setscaleboxbyfactor \fi
+ \ifconditional\scaleboxscalingdone\else\setscaleboxbyscale \fi
+ \ifconditional\scaleboxscalingdone\else\setscaleboxbydimension\fi
+ % finalizers / to be done (no longer needed this way, clean up)
+ \convertscaleboxinsertscale\scaleboxhsize\figx\scaleboxscax\scax
+ \convertscaleboxinsertscale\scaleboxvsize\figy\scaleboxscay\scay
+ % used in actual scaling
+ \xdef\finalscaleboxwidth {\the\scaleboxdimx}%
+ \xdef\finalscaleboxheight {\the\scaleboxdimy}%
+ \xdef\finalscaleboxxfactor{\the\scaleboxscax}%
+ \xdef\finalscaleboxyfactor{\the\scaleboxscay}%
+ \xdef\finalscaleboxxscale {\withoutpt\the\dimexpr\scax\points/\plushundred\relax}%
+ \xdef\finalscaleboxyscale {\withoutpt\the\dimexpr\scay\points/\plushundred\relax}}
+
+\setvalue{\??xy:\c!grid:\v!yes }{\getnoflines \fighei\setevalue{\currentscaletag\c!height}{\the\noflines\lineheight}}
+\setvalue{\??xy:\c!grid:\v!height }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight+\strutdepth\relax}}
+\setvalue{\??xy:\c!grid:\v!depth }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight-\strutdepth\relax}}
+\setvalue{\??xy:\c!grid:\v!halfline}{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight+.5\lineheight\relax}}
+\setvalue{\??xy:\c!grid:\v!fit }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\noflines\lineheight}}
+\letvalue{\??xy:\c!grid:\empty }\donothing
+
+\def\checkscaleboxsettings
+ {\doifsomething{\scaleparameter\c!maxwidth }% can be defined in itself
+ {\setevalue{\currentscaletag\c!maxwidth }{\the\dimexpr\scaleparameter\c!maxwidth \relax}}%
+ \doifsomething{\scaleparameter\c!maxheight}% can be defined in itself
+ {\setevalue{\currentscaletag\c!maxheight}{\the\dimexpr\scaleparameter\c!maxheight\relax}}%
+ \doifsomething{\scaleparameter\c!lines}
+ {\setevalue{\currentscaletag\c!height}{\the\dimexpr\scaleparameter\c!lines\lineheight\relax}}%
+ \getvalue{\??xy:\c!grid:\scaleparameter\c!grid}}
+
+\def\setscaleboxbynature % where ! ! ! ! !
+ {\doifsomething{\scaleparameter\c!width }{\global\scaleboxdimx\scaleparameter\c!width }%
+ \doifsomething{\scaleparameter\c!height}{\global\scaleboxdimy\scaleparameter\c!height}%
+ \doifsomething{\scaleparameter\c!scale } {\scaleboxscax\scaleparameter\c!scale
+ \scaleboxscay\scaleparameter\c!scale }%
+ \doifsomething{\scaleparameter\c!xscale} {\scaleboxscax\scaleparameter\c!xscale}%
+ \doifsomething{\scaleparameter\c!yscale} {\scaleboxscay\scaleparameter\c!yscale}} % oeps, was x
+
+% \defineexternalfigure[width-6][factor=auto,maxwidth=\textheight,maxheight=\textwidth]
+% \defineexternalfigure[width-7][factor=auto,maxwidth=\textwidth,maxheight=\textheight]
+% \placefigure{none}{\rotate[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-6]}} \page
+% \placefigure{none}{\framed[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-7]}}
+
+\def\setscaleboxbyfactor
+ {\doifinsetelse{\scaleparameter\c!factor}{\v!max,\v!fit,\v!broad,\v!auto}
+ {\doapplyscaleboxsize
+ \ifdim\scaleboxsizex>\scaleboxsizey
+ \docalculatescaleboxnorm \scaleboxdimx\c!factor\c!maxwidth\hsize\scaleboxhsize
+ \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
+ \else
+ \docalculatescaleboxnorm \scaleboxdimy\c!factor\c!maxheight\scaleboxoutervsize\scaleboxvsize
+ \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
+ \fi
+ \donetrue}
+ {\doifinsetelse{\scaleparameter\c!hfactor}{\v!max,\v!fit,\v!broad,\v!auto}
+ {\doapplyscaleboxsize
+ \docalculatescaleboxnorm \scaleboxdimy\c!hfactor\c!maxheight\scaleboxoutervsize\scaleboxvsize
+ \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
+ \donetrue}
+ {\doifinsetelse{\scaleparameter\c!wfactor}{\v!max,\v!fit,\v!broad,\v!auto}
+ {\doapplyscaleboxsize
+ \docalculatescaleboxnorm \scaleboxdimx\c!wfactor\c!maxwidth\hsize\scaleboxhsize
+ \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
+ \donetrue}
+ {\docalculatescaleboxnorm\scaleboxdimy\c!factor \c!height \textheight\scaleboxvsize
+ \docalculatescaleboxnorm\scaleboxdimy\c!hfactor\c!height \textheight\scaleboxvsize
+ \docalculatescaleboxnorm\scaleboxdimx\c!wfactor\c!width \hsize \hsize
+ \donefalse}}}%
+ \ifdone
+ \settrue\scaleboxscalingdone
+ \ifdim\scaleboxdimx>\scaleboxhsize
+ \global\scaleboxdimy\zeropoint \global\scaleboxdimx\scaleboxhsize
+ \else\ifdim\scaleboxdimy>\scaleboxvsize
+ \global\scaleboxdimx\zeropoint \global\scaleboxdimy\scaleboxvsize
+ \fi\fi
+ \setscaleboxbydimension
+ \fi}
+
+\def\setscaleboxbyscale
+ {\doifsomething{\scaleparameter\c!scale\scaleparameter\c!xscale\scaleparameter\c!yscale}
+ {\doapplyscaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax\c!xscale
+ \doapplyscaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay\c!yscale
+ \global\scaleboxdimx\zeropoint
+ \global\scaleboxdimy\zeropoint
+ \doifelsenothing{\scaleparameter\c!maxwidth}
+ {\doifsomething{\scaleparameter\c!maxheight}
+ {\ifdim\scaleboxsizey>\scaleparameter\c!maxheight\relax
+ \global\scaleboxdimy\scaleparameter\c!maxheight
+ \fi}}
+ {\ifdim\scaleboxsizex>\scaleparameter\c!maxwidth\relax
+ \global\scaleboxdimx\scaleparameter\c!maxwidth
+ \fi}}}
+
+\def\setscaleboxbydimension
+ {\ifdim\scaleboxdimx>\zeropoint
+ \ifdim\scaleboxdimy>\zeropoint
+ \dosetdimensionscaleboxsize
+ {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
+ \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
+ {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
+ \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
+ {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
+ \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
+ \else
+ \dosetdimensionscaleboxsize
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ \fi
+ \else
+ \ifdim\scaleboxdimy>\zeropoint
+ \dosetdimensionscaleboxsize
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ \else
+ \dosetdimensionscaleboxsize
+ {\doapplyscaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax\c!xscale
+ \doapplyscaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay\c!yscale}%
+ {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ \fi
+ \fi}
+
+\def\dosetdimensionscaleboxsize#1#2#3%
+ {#1\relax
+ \doifsomething{\scaleparameter\c!maxwidth}
+ {\ifdim\scaleboxdimx>\scaleparameter\c!maxwidth\relax
+ \global\scaleboxdimx\scaleparameter\c!maxwidth
+ #2\relax
+ \fi}%
+ \doifsomething{\scaleparameter\c!maxheight}
+ {\ifdim\scaleboxdimy>\scaleparameter\c!maxheight\relax
+ \global\scaleboxdimy\scaleparameter\c!maxheight
+ #3\relax
+ \fi}}
+
+\def\docalculatescaleboxnorm#1#2#3#4#5% 2 3 parameters (dodo:speedup)
+ {\processaction
+ [\scaleparameter#2]
+ [ \v!max=>\global#1\dimexpr#4\relax,
+ \v!fit=>\global#1\dimexpr#5\relax,
+ \v!broad=>\global#1\dimexpr#5-4\@@exbodyfont\relax,
+ \v!auto=>\doifsomething{\scaleparameter#3}{\global#1\dimexpr\scaleparameter#3\relax},
+ \s!default=>\doifsomething{\scaleparameter#3}{\global#1\dimexpr\scaleparameter#3\relax},
+ \s!unknown=>\global#1\dimexpr\scaleparameter#2\dimexpr\@@exbodyfont/10\relax\relax]}
+
+\def\docalculatescaleboxscales#1#2#3#4%
+ {\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax
+ \scaleboxscax\scratchdimen
+ \scaleboxscay\scratchdimen
+ #3\dimexpr\scaleboxscax\dimexpr#4/\plusthousand\relax\relax}
+
+\def\docalculatescaleboxscale#1#2#3%
+ {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax}
+
+\def\doapplyscaleboxscale#1#2#3#4% $4 = parameter / scale can be empty
+ {\ifcase0\scaleparameter#4\relax
+ \ifcase0\scaleparameter\c!scale\relax
+ #3=\plusthousand
+ \else
+ #3=\scaleparameter\c!scale
+ \fi
+ \else
+ #3=\scaleparameter#4%
+ \fi
+ \relax % important ! still ?
+ \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi
+ \relax}
+
+\def\doapplyscaleboxsize
+ {\doifelsenothing{\scaleparameter\c!maxheight}
+ {\scaleboxoutervsize\textheight
+ \ifinner
+ \scaleboxoutervsize \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinsidefloat
+ \scaleboxoutervsize \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinpagebody
+ \scaleboxoutervsize \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else % hm, there should be an option to force this
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \scratchdimen\scaleboxoutervsize % \textheight
+ \fi
+ \else
+ \scratchdimen\scaleboxoutervsize % \textheight
+ \fi
+ \fi\fi\fi}
+ {\scratchdimen\scaleparameter\c!maxheight
+ \scaleboxoutervsize\scratchdimen}%
+ \doifelsenothing{\scaleparameter\c!height}
+ {\scaleboxvsize\scratchdimen}
+ {\scaleboxvsize\scaleparameter\c!height}%
+ \doifelsenothing{\scaleparameter\c!width}
+ {\scaleboxhsize\hsize}
+ {\scaleboxhsize\scaleparameter\c!width}}
+
+\def\convertscaleboxinsertscale#1#2#3#4%
+ {\scratchdimen#1\relax
+ \ifnum#3=\plusthousand
+ % == scale 1
+ \else
+ % better 1000 100 10 ranges, evt round 2sp
+ \divide\scratchdimen \plusthousand
+ \multiply\scratchdimen #3\relax
+ \fi
+ \scratchdimen-\scratchdimen % beter hier - dan in driver
+ \edef#2{\the\scratchdimen}%
+ \scratchcounter#3\relax
+ \ifnum\scratchcounter>\plustenthousand
+ \divide\scratchcounter\!!ten \scratchdimen\the\scratchcounter\points
+ \else
+ \scratchdimen\the\scratchcounter\points \divide\scratchdimen\!!ten
+ \fi
+ \edef#4{\withoutpt\the\scratchdimen}}
+
+% \startcombination
+% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {}
+% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {}
+% \stopcombination
+
+\def\doscaleboxposition
+ {\doifsomething{\scaleparameter\c!equalwidth}
+ {\scratchdimen\scaleparameter\c!equalwidth\relax
+ \ifdim\wd\nextbox<\scratchdimen
+ \setbox\nextbox\hbox to \scratchdimen{\hss\box\nextbox\hss}%
+ \fi}%
+ \doifsomething{\scaleparameter\c!equalheight}
+ {\scratchdimen\scaleparameter\c!equalheight\relax
+ \ifdim\ht\nextbox<\scratchdimen
+ \setbox\nextbox\vbox to \scratchdimen{\vss\box\nextbox\vss}%
+ \fi}}
+
+%D \macros
+%D {clip, setupclipping}
+%D
+%D Although related to figures, clipping can be applied to
+%D arbitrary content. We can use \METAPOST\ to provide a non
+%D rectangular clipping path.
+%D
+%D \starttyping
+%D \startMPclip{fun}
+%D clip currentpicture to fullcircle
+%D shifted (.5,.5) xscaled \width yscaled \height ;
+%D \stopMPclip
+%D \stoptyping
+%D
+%D We get a rectangular piece of the figure when we say:
+%D
+%D \starttyping
+%D \clip[x=2,y=1]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D When we want to clip to the oval we defined a few lines ago,
+%D we say:
+%D
+%D \starttyping
+%D \clip[nx=1,ny=1,x=1,y=1,mp=fun]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D The general characteristics of clipping can be set up with
+%D
+%D \showsetup{setupclipping}
+
+\unexpanded\def\setupclipping
+ {\dodoubleargument\getparameters[\??cp]}
+
+\def\clip
+ {\dosingleempty\doclip}
+
+\def\doclip[#1]% nb top->bottom left->right
+ {\bgroup
+ \getparameters[\??cp][#1]%
+ \doifelse\@@cpstate\v!start\dodoclip{\egroup\hbox}}
+
+\def\dodoclip
+ {\dowithnextbox
+ {\ifdim\@@cpwidth>\zeropoint
+ \!!dimena\@@cpwidth
+ \!!dimenc\@@cphoffset
+ \else
+ \!!dimena\nextboxwd
+ \divide\!!dimena \@@cpnx
+ \!!dimenc\@@cpx\!!dimena
+ \advance\!!dimenc -\!!dimena
+ \!!dimena\@@cpsx\!!dimena
+ \fi
+ \relax % sure
+ \ifdim\@@cpheight>\zeropoint
+ \!!dimenb\@@cpheight
+ \!!dimend\nextboxht
+ \advance\!!dimend -\@@cpvoffset
+ \advance\!!dimend -\!!dimenb
+ \else
+ \!!dimenb\nextboxht
+ \divide\!!dimenb \@@cpny
+ \!!dimend-\@@cpy\!!dimenb
+ \advance\!!dimend -\@@cpsy\!!dimenb
+ \advance\!!dimend \!!dimenb
+ \!!dimenb\@@cpsy\!!dimenb
+ \advance\!!dimend \nextboxht % dimend !
+ \fi
+ \setbox\nextbox\hbox % old
+ {\advance\!!dimenc -\@@cpleftoffset % new !
+ \advance\!!dimend -\@@cpbottomoffset % new ! % - added
+ \hskip-\!!dimenc\lower\!!dimend\flushnextbox}% old
+ \nextboxwd\zeropoint
+ \nextboxht\zeropoint
+ \nextboxdp\zeropoint
+ \setbox\nextbox\hbox
+ {\advance\!!dimena \@@cpleftoffset % new !
+ \advance\!!dimena \@@cprightoffset % new !
+ \advance\!!dimenb \@@cpbottomoffset % new !
+ \advance\!!dimenb \@@cptopoffset % new !
+ \dostartclipping\@@cpmp\!!dimena\!!dimenb % old
+ \flushnextbox
+ \dostopclipping}%
+ \setbox\nextbox\hbox % new !
+ {\!!dimena-\@@cpleftoffset % new !
+ \!!dimenb \@@cpbottomoffset % new ! % - removed
+ \hskip\!!dimena\lower\!!dimenb\flushnextbox}% new !
+ \nextboxwd\!!dimena
+ \nextboxht\!!dimenb
+ \nextboxdp\zeropoint
+ \flushnextbox
+ \egroup}%
+ \hbox}
+
+\setupclipping
+ [\c!state=\v!start,
+ \c!n=1, % was 2
+ \c!nx=\@@cpn,\c!x=1,\c!sx=1,
+ \c!ny=\@@cpn,\c!y=1,\c!sy=1,
+ \c!width=\!!zeropoint,
+ \c!height=\!!zeropoint,
+ \c!hoffset=\!!zeropoint,
+ \c!voffset=\!!zeropoint,
+ \c!offset=\zeropoint,
+ \c!leftoffset=\@@cpoffset, % \zeropoint,
+ \c!rightoffset=\@@cpoffset, % \zeropoint,
+ \c!topoffset=\@@cpoffset, % \zeropoint,
+ \c!bottomoffset=\@@cpoffset,% \zeropoint,
+ \c!mp=]
+
+%D \startbuffer
+%D \startuseMPgraphic{test}
+%D path p ; p := fullcircle scaled 4cm ;
+%D draw p withpen pencircle scaled 1cm ;
+%D setbounds currentpicture to boundingbox p ;
+%D \stopuseMPgraphic
+%D
+%D \hbox to \hsize \bgroup
+%D \hss
+%D \ruledhbox{\useMPgraphic{test}}%
+%D \hss
+%D \ruledhbox{\clip{\useMPgraphic{test}}}%
+%D \hss
+%D \egroup
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D Mirroring.
+
+\def\domirrorbox % \hbox/\vbox/\vtop
+ {\bgroup
+ \dowithnextbox
+ {\dontshowcomposition
+ \scratchdimen\nextboxwd
+ % better use an hbox (if no \forgetall, leftskip etc may creep in)
+ %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\nextboxwd\flushnextbox\dostopmirroring}%
+ \setbox\nextbox\hbox{\dostartmirroring\hskip-\nextboxwd\flushnextbox\dostopmirroring}%
+ \nextboxwd\scratchdimen
+ \flushnextbox
+ \egroup}}
+
+\unexpanded\def\mirror
+ {\domirrorbox\hbox}
+
+% \setbox0=\hbox{gans}
+% \ruledhbox{\copy0 \schaal[sx=2,sy=2]{\copy0}}
+% \mirror{\ruledhbox{\copy0 \schaal{\box0}}}
+
+\protect \endinput
diff --git a/tex/context/base/grph-u3d.lua b/tex/context/base/grph-u3d.lua
new file mode 100644
index 000000000..f3bf17631
--- /dev/null
+++ b/tex/context/base/grph-u3d.lua
@@ -0,0 +1,49 @@
+if not modules then modules = { } end modules ['grph-u3d'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- see lpdf-u3d.lua for comment
+
+local trace_inclusion = false trackers.register("figures.inclusion", function(v) trace_inclusion = v end)
+
+local pdfannotation = nodes.pdfannotation
+local todimen = string.todimen
+
+-- maybe todo: backends.codeinjections.insertu3d
+
+function figures.checkers.u3d(data)
+ local dr, du, ds = data.request, data.used, data.status
+ local width = todimen(dr.width or figures.defaultwidth)
+ local height = todimen(dr.height or figures.defaultheight)
+ local foundname = du.fullname
+ dr.width, dr.height = width, height
+ du.width, du.height, du.foundname = width, height, foundname
+ if trace_inclusion then
+ logs.report("figures","including u3d '%s': width %s, height %s",foundname,width,height)
+ end
+ context.startfoundexternalfigure(width .. "sp",height .. "sp")
+ context(function()
+ local annotation, preview, ref = backends.pdf.helpers.insert3d {
+ foundname = foundname,
+ width = width,
+ height = height,
+ factor = number.dimenfactors.bp,
+ display = dr.display,
+ controls = dr.controls,
+ label = dr.label,
+ }
+--~ print(annotation, preview, ref)
+ node.write(pdfannotation(width,height,0,annotation()))
+ end)
+ context.stopfoundexternalfigure()
+ return data
+end
+
+figures.includers.u3d = figures.includers.nongeneric
+
+figures.registersuffix("u3d","u3d")
+figures.registersuffix("prc","u3d")
diff --git a/tex/context/base/hand-def.mkii b/tex/context/base/hand-def.mkii
new file mode 100644
index 000000000..0a19ce270
--- /dev/null
+++ b/tex/context/base/hand-def.mkii
@@ -0,0 +1,577 @@
+%D \module
+%D [ file=hand-def, % was enco-pro
+%D version=2000.29.09,
+%D title=\CONTEXT\ Handling Macros,
+%D subtitle=Default Protruding Factors,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%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 is an experimental definition file. The protruding
+%D values we use here are those found from \THANH's thesis.
+
+\startfonthandling [pure]
+
+ \defineprotrudefactor , 0 1
+ \defineprotrudefactor . 0 1
+ \defineprotrudefactor : 0 1
+ \defineprotrudefactor ; 0 1
+ \defineprotrudefactor - 0 1
+
+ \defineprotrudefactor hyphen 0 1
+ \defineprotrudefactor endash 0 .5
+ \defineprotrudefactor emdash 0 .33 % .5
+
+\stopfonthandling
+
+\startfonthandling [punctuation]
+
+ \defineprotrudefactor ! 0 .2
+ \defineprotrudefactor ' 0 .7
+ \defineprotrudefactor ` .7 0
+ \defineprotrudefactor ( .05 0
+ \defineprotrudefactor ) 0 .05
+ \defineprotrudefactor [ .05 0
+ \defineprotrudefactor ] 0 .05
+ \defineprotrudefactor , 0 .7
+ \defineprotrudefactor - 0 .7
+ \defineprotrudefactor . 0 .7
+ \defineprotrudefactor : 0 .5
+ \defineprotrudefactor ; 0 .5
+
+ \defineprotrudefactor rightupperninequote 0 .5
+ \defineprotrudefactor leftupperninequote .5 0
+ \defineprotrudefactor endash 0 .3
+ \defineprotrudefactor emdash 0 .2
+
+ \defineprotrudefactor hyphen 0 .7
+
+\stopfonthandling
+
+\startfonthandling [alpha]
+
+ \defineprotrudefactor A .05 .05
+ \defineprotrudefactor F 0 .05
+ \defineprotrudefactor J .05 0
+ \defineprotrudefactor K 0 .05
+ \defineprotrudefactor L 0 .05
+ \defineprotrudefactor T .05 .05
+ \defineprotrudefactor V .05 .05
+ \defineprotrudefactor W .05 .05
+ \defineprotrudefactor X .05 .05
+ \defineprotrudefactor Y .05 .05
+
+ \defineprotrudefactor k 0 .05
+ \defineprotrudefactor r 0 .05
+ \defineprotrudefactor t 0 .05
+ \defineprotrudefactor v .05 .05
+ \defineprotrudefactor w .05 .05
+ \defineprotrudefactor x .05 .05
+ \defineprotrudefactor y .05 .05
+
+\stopfonthandling
+
+% ogoneks may need another treatment
+
+\startfonthandling [extended]
+
+ \inherithandling Acircumflex A
+ \inherithandling acircumflex a
+ \inherithandling Ccircumflex C
+ \inherithandling ccircumflex c
+ \inherithandling Ecircumflex E
+ \inherithandling ecircumflex e
+ \inherithandling Gcircumflex G
+ \inherithandling gcircumflex g
+ \inherithandling Hcircumflex H
+ \inherithandling hcircumflex h
+ \inherithandling Icircumflex I
+ \inherithandling icircumflex i
+ \inherithandling Jcircumflex J
+ \inherithandling jcircumflex j
+ \inherithandling Ocircumflex O
+ \inherithandling ocircumflex o
+ \inherithandling Scircumflex S
+ \inherithandling scircumflex s
+ \inherithandling Ucircumflex U
+ \inherithandling ucircumflex u
+ \inherithandling Wcircumflex W
+ \inherithandling wcircumflex w
+ \inherithandling Ycircumflex Y
+ \inherithandling ycircumflex y
+
+ \inherithandling Agrave A
+ \inherithandling agrave a
+ \inherithandling Egrave E
+ \inherithandling egrave e
+ \inherithandling Igrave I
+ \inherithandling igrave i
+ \inherithandling Ograve O
+ \inherithandling ograve o
+ \inherithandling Ugrave U
+ \inherithandling ugrave u
+ \inherithandling Ygrave Y
+ \inherithandling ygrave y
+
+ \inherithandling Atilde A
+ \inherithandling atilde a
+ \inherithandling Itilde I
+ \inherithandling itilde i
+ \inherithandling Ntilde N
+ \inherithandling ntilde n
+ \inherithandling Otilde O
+ \inherithandling otilde o
+ \inherithandling Utilde U
+ \inherithandling utilde u
+
+ \inherithandling Adiaeresis A
+ \inherithandling adiaeresis a
+ \inherithandling Ediaeresis E
+ \inherithandling ediaeresis e
+ \inherithandling Idiaeresis I
+ \inherithandling idiaeresis i
+ \inherithandling Odiaeresis O
+ \inherithandling odiaeresis o
+ \inherithandling Udiaeresis U
+ \inherithandling udiaeresis u
+ \inherithandling Ydiaeresis Y
+ \inherithandling ydiaeresis y
+
+ \inherithandling Aacute A
+ \inherithandling aacute a
+ \inherithandling Cacute C
+ \inherithandling cacute c
+ \inherithandling Eacute E
+ \inherithandling eacute e
+ \inherithandling Iacute I
+ \inherithandling iacute i
+ \inherithandling Lacute L
+ \inherithandling lacute l
+ \inherithandling Nacute N
+ \inherithandling nacute n
+ \inherithandling Oacute O
+ \inherithandling oacute o
+ \inherithandling Racute R
+ \inherithandling racute r
+ \inherithandling Sacute s
+ \inherithandling sacute s
+ \inherithandling Uacute U
+ \inherithandling uacute u
+ \inherithandling Yacute Y
+ \inherithandling yacute y
+ \inherithandling Zacute Z
+ \inherithandling zacute z
+
+ \inherithandling Dstroke D
+ \inherithandling dstroke d
+ \inherithandling Hstroke H
+ \inherithandling hstroke h
+ \inherithandling Tstroke T
+ \inherithandling tstroke t
+
+ \inherithandling Cdotaccent C
+ \inherithandling cdotaccent c
+ \inherithandling Edotaccent E
+ \inherithandling edotaccent e
+ \inherithandling Gdotaccent G
+ \inherithandling gdotaccent g
+ \inherithandling Idotaccent I
+ \inherithandling idotaccent i
+ \inherithandling Zdotaccent Z
+ \inherithandling zdotaccent z
+
+ \inherithandling Amacron A
+ \inherithandling amacron a
+ \inherithandling Emacron E
+ \inherithandling emacron e
+ \inherithandling Imacron I
+ \inherithandling imacron i
+ \inherithandling Omacron O
+ \inherithandling omacron o
+ \inherithandling Umacron U
+ \inherithandling umacron u
+
+ \inherithandling Ccedilla C
+ \inherithandling ccedilla c
+ \inherithandling Kcedilla K
+ \inherithandling kcedilla k
+ \inherithandling Lcedilla L
+ \inherithandling lcedilla l
+ \inherithandling Ncedilla N
+ \inherithandling ncedilla n
+ \inherithandling Rcedilla R
+ \inherithandling rcedilla r
+ \inherithandling Scedilla S
+ \inherithandling scedilla s
+ \inherithandling Tcedilla T
+ \inherithandling tcedilla t
+
+ \inherithandling Ohungarumlaut O
+ \inherithandling ohungarumlaut o
+ \inherithandling Uhungarumlaut U
+ \inherithandling uhungarumlaut u
+
+ \inherithandling Aogonek A
+ \inherithandling aogonek a
+ \inherithandling Eogonek E
+ \inherithandling eogonek e
+ \inherithandling Iogonek I
+ \inherithandling iogonek i
+ \inherithandling Uogonek U
+ \inherithandling uogonek u
+
+ \inherithandling Aring A
+ \inherithandling aring a
+ \inherithandling Uring U
+ \inherithandling uring u
+
+ \inherithandling Abreve A
+ \inherithandling abreve a
+ \inherithandling Ebreve E
+ \inherithandling ebreve e
+ \inherithandling Gbreve G
+ \inherithandling gbreve g
+ \inherithandling Ibreve I
+ \inherithandling ibreve i
+ \inherithandling Obreve O
+ \inherithandling obreve o
+ \inherithandling Ubreve U
+ \inherithandling ubreve u
+
+ \inherithandling Ccaron C
+ \inherithandling ccaron c
+ \inherithandling Dcaron D
+ \inherithandling dcaron d
+ \inherithandling Ecaron E
+ \inherithandling ecaron e
+ \inherithandling Lcaron L
+ \inherithandling lcaron l
+ \inherithandling Ncaron N
+ \inherithandling ncaron n
+ \inherithandling Rcaron R
+ \inherithandling rcaron r
+ \inherithandling Scaron S
+ \inherithandling scaron s
+ \inherithandling Tcaron T
+ \inherithandling tcaron t
+ \inherithandling Ycaron Y
+ \inherithandling ycaron y
+ \inherithandling Zcaron Z
+ \inherithandling zcaron z
+
+ \inherithandling AEligature E
+ \inherithandling aeligature e
+ \inherithandling Lstroke I
+ \inherithandling lstroke o
+ \inherithandling Ostroke O
+ \inherithandling ostroke o
+ \inherithandling OEligature O
+ \inherithandling oeligature o
+
+ \inherithandling Ssharp S
+ \inherithandling ssharp s
+ \inherithandling IJligature J
+ \inherithandling ijligature j
+
+ \inherithandling aumlaut a
+ \inherithandling eumlaut e
+ \inherithandling iumlaut i
+ \inherithandling oumlaut o
+ \inherithandling uumlaut u
+
+ \inherithandling Aumlaut A
+ \inherithandling Eumlaut E
+ \inherithandling Iumlaut I
+ \inherithandling Oumlaut O
+ \inherithandling Uumlaut U
+
+ \inherithandling Lslash L
+ \inherithandling lslash l
+ \inherithandling Dslash D
+ \inherithandling dslash d
+ \inherithandling Oslash O
+ \inherithandling oslash o
+
+ \inherithandling Eszett S
+ \inherithandling eszett s
+
+ \inherithandling Thorn P
+ \inherithandling thorn p
+
+ % vietnamese
+
+ \inherithandling Ahook A
+ \inherithandling ahook a
+ \inherithandling Ehook E
+ \inherithandling ehook e
+ \inherithandling Ihook I
+ \inherithandling ihook i
+ \inherithandling Ohook O
+ \inherithandling ohook o
+ \inherithandling Uhook U
+ \inherithandling uhook u
+ \inherithandling Yhook Y
+ \inherithandling yhook y
+
+ \inherithandling Acircumflexgrave A
+ \inherithandling Acircumflexacute A
+ \inherithandling Acircumflextilde A
+ \inherithandling Acircumflexhook A
+ \inherithandling acircumflexgrave a
+ \inherithandling acircumflexacute a
+ \inherithandling acircumflextilde a
+ \inherithandling acircumflexhook a
+ \inherithandling Ecircumflexgrave E
+ \inherithandling Ecircumflexacute E
+ \inherithandling Ecircumflextilde E
+ \inherithandling Ecircumflexhook E
+ \inherithandling ecircumflexgrave e
+ \inherithandling ecircumflexacute e
+ \inherithandling ecircumflextilde e
+ \inherithandling ecircumflexhook e
+ \inherithandling Ocircumflexgrave O
+ \inherithandling Ocircumflexacute O
+ \inherithandling Ocircumflextilde O
+ \inherithandling Ocircumflexhook O
+ \inherithandling ocircumflexgrave o
+ \inherithandling ocircumflexacute o
+ \inherithandling ocircumflextilde o
+ \inherithandling ocircumflexhook o
+
+ \inherithandling Abrevegrave A
+ \inherithandling Abreveacute A
+ \inherithandling Abrevetilde A
+ \inherithandling Abrevehook A
+ \inherithandling abrevegrave a
+ \inherithandling abreveacute a
+ \inherithandling abrevetilde a
+ \inherithandling abrevehook a
+
+ \inherithandling Adotbelow A
+ \inherithandling adotbelow a
+ \inherithandling Edotbelow E
+ \inherithandling edotbelow e
+ \inherithandling Idotbelow I
+ \inherithandling idotbelow i
+ \inherithandling Odotbelow O
+ \inherithandling odotbelow o
+ \inherithandling Udotbelow U
+ \inherithandling udotbelow u
+ \inherithandling Ydotbelow Y
+ \inherithandling ydotbelow y
+
+ \inherithandling Ohorndotbelow O
+ \inherithandling ohorndotbelow o
+ \inherithandling Uhorndotbelow U
+ \inherithandling uhorndotbelow u
+
+ \inherithandling Acircumflexdotbelow A
+ \inherithandling acircumflexdotbelow a
+ \inherithandling Ecircumflexdotbelow E
+ \inherithandling ecircumflexdotbelow e
+ \inherithandling Ocircumflexdotbelow O
+ \inherithandling ocircumflexdotbelow o
+
+ \inherithandling Abrevedotbelow A
+ \inherithandling abrevedotbelow a
+
+ \inherithandling Ohorn O
+ \inherithandling Ohorngrave O
+ \inherithandling Ohornacute O
+ \inherithandling Ohorntilde O
+ \inherithandling Ohornhook O
+ \inherithandling ohorn o
+ \inherithandling ohorngrave o
+ \inherithandling ohornacute o
+ \inherithandling ohorntilde o
+ \inherithandling ohornhook o
+ \inherithandling Uhorn U
+ \inherithandling Uhorngrave U
+ \inherithandling Uhornacute U
+ \inherithandling Uhorntilde U
+ \inherithandling Uhornhook U
+ \inherithandling uhorn u
+ \inherithandling uhorngrave u
+ \inherithandling uhornacute u
+ \inherithandling uhorntilde u
+ \inherithandling uhornhook u
+
+ \inherithandling Ytilde Y
+ \inherithandling ytilde y
+ \inherithandling Etilde E
+ \inherithandling etilde e
+
+\stopfonthandling
+
+\startfonthandling [hz]
+
+ \defineadjustfactor A .5
+ \defineadjustfactor B .7
+ \defineadjustfactor C .7
+ \defineadjustfactor D .5
+ \defineadjustfactor E .7
+ \defineadjustfactor F .7
+ \defineadjustfactor G .5
+ \defineadjustfactor H .7
+ \defineadjustfactor K .7
+ \defineadjustfactor M .7
+ \defineadjustfactor N .7
+ \defineadjustfactor O .5
+ \defineadjustfactor P .7
+ \defineadjustfactor Q .5
+ \defineadjustfactor R .7
+ \defineadjustfactor S .7
+ \defineadjustfactor U .7
+ \defineadjustfactor W .7
+ \defineadjustfactor Z .7
+
+ \defineadjustfactor a .7
+ \defineadjustfactor b .7
+ \defineadjustfactor c .7
+ \defineadjustfactor d .7
+ \defineadjustfactor e .7
+ \defineadjustfactor g .7
+ \defineadjustfactor h .7
+ \defineadjustfactor k .7
+ \defineadjustfactor m .7
+ \defineadjustfactor n .7
+ \defineadjustfactor o .7
+ \defineadjustfactor p .7
+ \defineadjustfactor q .7
+ \defineadjustfactor s .7
+ \defineadjustfactor u .7
+ \defineadjustfactor w .7
+ \defineadjustfactor z .7
+
+ \defineadjustfactor 2 .7
+ \defineadjustfactor 3 .7
+ \defineadjustfactor 6 .7
+ \defineadjustfactor 8 .7
+ \defineadjustfactor 9 .7
+
+% \defineadjustfactor hyphen ?
+% \defineadjustfactor endash ?
+% \defineadjustfactor emdash ?
+
+\stopfonthandling
+
+% no ligs other than fi fl etc, no --- and ''
+
+\startfonthandling[noligs]
+
+ \settagcode - {\notagcode}
+ \settagcode ' {\notagcode}
+ \settagcode ` {\notagcode}
+ \settagcode ? {\notagcode}
+ \settagcode ! {\notagcode}
+
+\stopfonthandling
+
+% \startfonthandling[noligs]
+% \dostepwiserecurse{0}{255}{1}{\expanded{\settagcode \recurselevel\space\notagcode\space}}
+% \stopfonthandling
+
+% \definefonthandling [noligs] [noligs] [type=tag]
+ % \setupfontsynonym[Serif][handling=noligs]
+% \definefont[test][Serif at 12.34pt]
+%
+% {``fi--ffl---ffi'' \test ``fi--ffl---ffi''}
+
+\unprotect
+
+% beware: extended extends the preceding vector (both protruding and
+% adjusting) but as long as the normal ascii characters are not set
+% beforehand, they default to normal
+
+% protruding variants -- slanted/italic is yet incomplete
+
+\definefonthandling [pure] [pure] [\c!type=\v!hanging]
+\definefonthandling [purebold] [pure] [\c!type=\v!hanging]
+\definefonthandling [pureslanted] [pure] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [pureitalic] [pure] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [pureboldslanted] [pure] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [purebolditalic] [pure] [\c!type=\v!hanging,\c!right=1.5]
+
+\definefonthandling [normal] [punctuation,alpha,extended] [\c!type=\v!hanging]
+\definefonthandling [normalbold] [punctuation,alpha,extended] [\c!type=\v!hanging]
+\definefonthandling [normalslanted] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [normalitalic] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [normalboldslanted] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [normalbolditalic] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+
+% for old times sake
+
+\definefonthandling [bold] [punctuation,alpha,extended] [\c!type=\v!hanging]
+\definefonthandling [slanted] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [italic] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [boldslanted] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+\definefonthandling [bolditalic] [punctuation,alpha,extended] [\c!type=\v!hanging,\c!right=1.5]
+
+% hz variants
+
+\definefonthandling [hz] [hz,extended] [\c!type=\v!hz] % min=20 max=20 step=5
+
+% combined variants
+
+\definefonthandling [quality] [hz,pure]
+\definefonthandling [highquality] [hz,normal]
+
+% noligs (xml) : \definefonthandling [default] [noligs]
+
+\definefonthandling [noligs] [noligs] [\c!type=tag]
+
+% experimental values !
+%
+% \definefontsynonym[myfont][Serif][handling=prespacing]
+% \definefont[whatever][myfont sa 1]
+% \setupalign[spacing]
+%
+% \whatever look at this: we now have a proper spacing feature and, hurray,
+% get rid of active punctuation!
+
+\startfonthandling [flexspacing]
+
+ \definespacefactor : 0 1.25 .25 .25
+
+ \definespacefactor , 0 1 .25 .25
+ \inheritspacefactor ; ,
+
+ \definespacefactor . 0 1.5 .25 .25
+ \inheritspacefactor ! .
+ \inheritspacefactor ? .
+
+\stopfonthandling
+
+\definefonthandling[flexspacing][flexspacing][\c!type=\v!spacing]
+
+\startfonthandling [prespacing] % better name needed
+
+ \definespacefactor : .25 .25 0 0
+ \inheritspacefactor ; :
+ \inheritspacefactor ! :
+ \inheritspacefactor ? :
+
+\stopfonthandling
+
+\definefonthandling[prespacing][prespacing][\c!type=\v!spacing] % factor=.5
+
+% A special case of guillemots, beware: when used ungrouped,
+% it overloads all successive (current) encoding vector
+% instances! Will be obsolete soon.
+
+\startfonthandling [glm]
+
+ \overloadcharacter guilsingleleft {\defaultcharacter\guilsingleleft }
+ \overloadcharacter guilsingleright {\defaultcharacter\guilsingleright}
+ \overloadcharacter leftguillemot {\defaultcharacter\leftguillemot }
+ \overloadcharacter rightguillemot {\defaultcharacter\rightguillemot }
+
+\stopfonthandling
+
+\definefonthandling [glm] [glm]
+
+\protect \endinput
diff --git a/tex/context/base/hand-ini.mkii b/tex/context/base/hand-ini.mkii
new file mode 100644
index 000000000..ac8a94696
--- /dev/null
+++ b/tex/context/base/hand-ini.mkii
@@ -0,0 +1,483 @@
+%D \module
+%D [ file=hand-ini, % moved from enco-ini / pro
+%D version=2000.12.27, % 1998.12.03,
+%D title=\CONTEXT\ Handling Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 {\em This module is experimental and implements font
+%D specific features, like hanging punctuation.}
+
+\unprotect
+
+\newif\iftracefonthandling % \tracefonthandlingtrue
+
+\newif\ifskiphandlingdef \skiphandlingdeffalse
+
+\newtoks\everyenablefonthandling
+
+% much in common with hz/protruding defs
+% todo: fix others
+
+\def\dosetsomehandling#1#2#3 #4 % no define since directly set
+ {\ifskiphandlingdef \else
+ \doifnumberelse{\string#2}
+ {#1{#2#3}{#4}}
+ {\doifelsenothing{#3}
+ {#1{`#2}{#4}}
+ {\let\char\empty
+ \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}}\donothing
+ \let\char\normalchar}}%
+ \fi}
+
+\def\dosetpairhandling#1#2#3 #4 #5 % no define since directly set
+ {\ifskiphandlingdef \else
+ \doifnumberelse{\string#2}
+ {#1{#2#3}{#4}{#5}}
+ {\doifelsenothing{#3}
+ {#1{`#2}{#4}{#5}}
+ {\let\char\empty
+ \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}}\donothing
+ \let\char\normalchar}}%
+ \fi}
+
+\def\dosetquartethandling#1#2#3 #4 #5 #6 #7 % no define since directly set
+ {\ifskiphandlingdef \else
+ \doifnumberelse{\string#2}
+ {#1{#2#3}{#4}{#5}{#6}{#7}}
+ {\doifelsenothing{#3}
+ {#1{`#2}{#4}{#5}{#6}{#7}}
+ {\let\char\empty
+ \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}{#6}{#7}}\donothing
+ \let\char\normalchar}}%
+ \fi}
+
+\def\doinhsomehandling#1#2#3 #4 % to be checked
+ {\ifskiphandlingdef \else
+ \if#3\relax\relax
+ #1{`#2}{`#4}%
+ \else
+ \let\char\empty
+ \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{`#4}}\donothing
+ \let\char\normalchar
+ \fi
+ \fi}
+
+% adjustspacing
+
+\newdimen\adjustdimen \let\handledfont\font
+
+\ifx\undefined\pdfadjustspacing % we don't use pdftex
+
+ \let\enableadjusting \relax
+ \let\disableadjusting \relax
+ \let\setadjusting \gobbletwoarguments
+
+ \def\defineadjustfactor #1 #2 {}
+ \def\inheritadjustfactor #1 #2 {}
+
+ \let\setfontadjusting \gobbleoneargument
+
+\else
+
+ \def\enableadjusting {\pdfadjustspacing\plustwo}
+ \def\disableadjusting {\pdfadjustspacing\zerocount}
+
+ \appendtoks \disableadjusting \to \everyforgetall % Here or not here?
+
+ \def\dododefineadjustfactor#1#2%
+ {\efcode\handledfont#1\dimexpr#2\onepoint*\plusthousand/\maxcard\relax}
+
+ \def\dodoinheritadjustfactor#1#2%
+ {\efcode\handledfont#1\efcode\handledfont#2\relax}
+
+ \def\defineadjustfactor#1 #2 %
+ {\setfonttoks
+ \let\inherithandling\inheritadjustfactor
+ \appendtoks\dosetsomehandling\dododefineadjustfactor#1 #2 \to\fonttoks}
+
+ \def\inheritadjustfactor#1 #2 %
+ {\setfonttoks
+ \appendtoks\doinhsomehandling\dodoinheritadjustfactor#1 #2 \to\fonttoks}
+
+ \ifnum\pdftexversion<120
+ \let\@@pdfexpandbonus\plusthousand
+ \else
+ \def\@@pdfexpandbonus{autoexpand}%
+ \fi
+
+ \def\setfontadjusting#1%
+ {\doifvalue{\@fha@\@fha@#1\c!type}\v!hz{\dosetfontadjusting{#1}}}
+
+ \def\dosetfontadjusting#1%
+ {\iftracefonthandling\showfontadjusting{#1}\fi
+ \pdffontexpand\handledfont
+ \csname\@fha@\@fha@#1\c!max \endcsname\space
+ \csname\@fha@\@fha@#1\c!min \endcsname\space
+ \csname\@fha@\@fha@#1\c!step\endcsname\space
+ \@@pdfexpandbonus\relax}
+
+ \def\showfontadjusting#1%
+ {\writestatus\m!handlings{[adjust]\space#1\space
+ \csname\@fha@\@fha@#1\c!max \endcsname/%
+ \csname\@fha@\@fha@#1\c!min \endcsname/%
+ \csname\@fha@\@fha@#1\c!step\endcsname\space
+ \fontname\handledfont}}
+\fi
+
+\ifx\setfontadjusting\gobbleoneargument \else
+ \appendtoks
+ \setfontadjusting\askedfonthandling
+ \to \everyenablefonthandling
+\fi
+
+% protruding
+
+\newif\ifembasedprotruding \embasedprotrudingfalse
+
+\newdimen\lproddimen \newdimen\rproddimen \let\handledfont\font
+
+\ifx\undefined\pdfprotrudechars % we don't use pdftex
+
+ \let\enableprotruding \relax
+ \let\disableprotruding \relax
+ \let\setprotrudingfactor \gobbleoneargument
+
+ \def\defineprotrudefactor #1 #2 #3 {}
+ \def\inheritprotrudefactor #1 #2 {}
+
+\else
+
+ \def\enableprotruding {\pdfprotrudechars\plustwo}
+ \def\disableprotruding{\pdfprotrudechars\zerocount}
+
+ \appendtoks \disableprotruding \to \everyforgetall % Here or not here?
+
+ \lproddimen1000\onepoint \divide\lproddimen\maxcard
+ \rproddimen1000\onepoint \divide\rproddimen\maxcard
+
+ \def\setprotrudingfactor#1%
+ {\doifvalue{\@fha@\@fha@#1\c!type}\v!hanging{\dosetprotrudingfactor{#1}}}
+
+ \def\dosetprotrudingfactor#1% no \onepoint instead of pt
+ {\lproddimen\dimexpr\csname\@fha@\@fha@#1\c!left \endcsname\onepoint*\plusthousand/\maxcard\relax
+ \rproddimen\dimexpr\csname\@fha@\@fha@#1\c!right\endcsname\onepoint*\plusthousand/\maxcard\relax
+ \iftracefonthandling\showprotrudingfactor{#1}\fi}
+
+ \def\showprotrudingfactor#1%
+ {\writestatus\m!handlings{[protrude]\space#1\space
+ \csname\@fha@\@fha@#1\c!left \endcsname\space
+ \csname\@fha@\@fha@#1\c!right\endcsname\space
+ \fontname\handledfont}}
+
+ % division before multiplication, else overflow with "sa>5"
+
+ \newdimen\protrudethreshold \protrudethreshold=36pt
+
+ \def\dododefineprotrudefactor#1#2#3%
+ {\lpcode\handledfont#1\dimexpr#2\lproddimen
+ \ifembasedprotruding \else
+ \ifdim\emwidth>\protrudethreshold
+ /\emwidth*\fontcharwd\handledfont#1%
+ \else
+ *\fontcharwd\handledfont#1/\emwidth
+ \fi
+ \fi
+ \relax
+ \rpcode\handledfont#1\dimexpr#3\rproddimen
+ \ifembasedprotruding \else
+ \ifdim\emwidth>\protrudethreshold
+ /\emwidth*\fontcharwd\handledfont#1%
+ \else
+ *\fontcharwd\handledfont#1/\emwidth
+ \fi
+ \fi
+ \relax}
+
+ \def\dodoinheritprotrudefactor#1#2%
+ {\lpcode\handledfont#1\lpcode\handledfont#2\relax
+ \rpcode\handledfont#1\rpcode\handledfont#2\relax}
+
+ \def\defineprotrudefactor#1 #2 #3 %
+ {\setfonttoks
+ \let\inherithandling\inheritprotrudefactor
+ \appendtoks\dosetpairhandling\dododefineprotrudefactor#1 #2 #3 \to\fonttoks}
+
+ \def\inheritprotrudefactor#1 #2 %
+ {\setfonttoks
+ \appendtoks\doinhsomehandling\dodoinheritprotrudefactor#1 #2 \to\fonttoks}
+
+\fi
+
+\ifx\setprotrudingfactor\gobbleoneargument \else
+ \appendtoks
+ \setprotrudingfactor\askedfonthandling
+ \to \everyenablefonthandling
+\fi
+
+% Basic support for a new pdftex feature: space factors
+%
+% \knbccode -- kern before char code
+% \knbscode -- kern before space code
+% \stbscode -- stretch before space code
+% \shbscode -- shrink before space code
+%
+% Setting \knsbcode\font`\.=200 means that if a period sits before
+% a interword space (glue), then the interword glue will be increased
+% by an amount of 1em*200/1000, i.e. the value is given in thousandths
+% of an em. (HTT)
+
+\newdimen\spfacdimen
+
+\ifx\undefined\pdfadjustinterwordglue % we don't use pdftex
+
+ \let\enablespacehandling \relax
+ \let\disablespacehandling \relax
+ \let\enablekernhandling \relax
+ \let\disablekernhandling \relax
+
+ \let\setspacehandling \gobbleoneargument
+
+ \def\definespacefactor #1 #2 #3 #4 #5 {}
+ \def\inheritspacefactor #1 #2 {}
+
+\else
+
+ \def\enablespacehandling {\pdfadjustinterwordglue\plusone }
+ \def\disablespacehandling{\pdfadjustinterwordglue\minusone}
+ \def\enablekernhandling {\pdfprependkern \plusone }
+ \def\disablekernhandling {\pdfprependkern \minusone}
+
+ \appendtoks \disablespacehandling \to \everyforgetall % Here or not here?
+
+ \def\dosetspacehandling#1%
+ {\spfacdimen\csname\@fha@\@fha@#1\c!factor\endcsname\s!pt
+ \multiply\spfacdimen\plusthousand\divide\spfacdimen\maxcard\relax}
+
+ \def\setspacehandling#1%
+ {\doifvalue{\@fha@\@fha@#1\c!type}\v!spacing{\dosetspacehandling{#1}}}
+
+ \def\dododefinespacefactor#1#2#3#4#5%
+ {\sfcode#1\plusthousand
+ \knbccode\handledfont#1\dimexpr#2\spfacdimen\relax
+ \knbscode\handledfont#1\dimexpr#3\spfacdimen\relax
+ \stbscode\handledfont#1\dimexpr#4\spfacdimen\relax
+ \shbscode\handledfont#1\dimexpr#5\spfacdimen\relax}
+
+ \def\dodoinheritspacefactor#1#2%
+ {\sfcode#1\plusthousand
+ \knbccode\handledfont#1\knbccode\handledfont#2\relax
+ \knbscode\handledfont#1\knbscode\handledfont#2\relax
+ \stbscode\handledfont#1\stbscode\handledfont#2\relax
+ \shbscode\handledfont#1\shbscode\handledfont#2\relax}
+
+ \def\definespacefactor#1 #2 #3 #4 #5 %
+ {\setfonttoks
+ \let\inherithandling\inheritspacefactor
+ \appendtoks\dosetquartethandling\dododefinespacefactor#1 #2 #3 #4 #5 \to\fonttoks}
+
+ \def\inheritspacefactor#1 #2 %
+ {\setfonttoks
+ \appendtoks\doinhsomehandling\dodoinheritspacefactor#1 #2 \to\fonttoks}
+
+\fi
+
+\ifx\setspacehandling\gobbleoneargument \else
+ \appendtoks
+ \setspacehandling\askedfonthandling
+ \to \everyenablefonthandling
+\fi
+
+% font attributes
+
+\let\notagcode\minusone
+
+\ifx\tagcode\undefined
+
+ \def\settagcode #1 #2 {}
+
+\else
+
+ \def\dodosettagcode#1#2%
+ {\tagcode\handledfont#1 #2\relax}
+
+ \def\settagcode#1 #2 %
+ {\setfonttoks
+ \appendtoks\dosetsomehandling\dodosettagcode#1 #2 \to\fonttoks}
+
+\fi
+
+% hook into font mechanism
+
+\let\fonthandling\empty
+
+\def\startfonthandling[#1]%
+ {\def\fonthandling{#1}%
+ \ifcsname\@fha@\fonthandling\endcsname\else
+ \expandafter\newtoks\csname\@fha@\fonthandling\endcsname
+ \fi
+ \setfonttoks}
+
+\def\stopfonthandling
+ {\let\fonthandling\empty}
+
+\def\setfonttoks
+ {\@EA\let\@EA\fonttoks\csname\@fha@\fonthandling\endcsname}
+
+\def\definefonthandling
+ {\dotripleempty\dodefinefonthandling}
+
+\def\dodefinefonthandling[#1][#2][#3]%
+ {\ifthirdargument
+ \setvalue{\@fha@\@fha@#1}{#2}%
+ \getparameters
+ [\@fha@\@fha@#1]
+ [\c!type=\v!hanging,%
+ \c!left=1,\c!right=1,%
+ \c!min=20,\c!max=20,\c!step=5,%
+ \c!factor=1,%
+ #3]%
+ \else
+ \setvalue{\@fha@\@fha@\@fha@#1}{#2}%
+ \fi}
+
+\def\setupfonthandling
+ {\dodoubleempty\dosetupfonthandling}
+
+\def\dosetupfonthandling[#1][#2]%
+ {\getparameters[\@fha@\@fha@#1][#2]}
+
+\def\enablehandling
+ {\dodoubleempty\doenablehandling}
+
+\def\doenablehandling[#1][#2]% handling / symbolic fontname
+ {\fastenablehandling{#1}{#2}} % for the moment the same as:
+
+\def\fastenablehandling#1#2% also gets #2 passed
+ {\edef\askedfonthandling{#1}%
+ \edef\filoffonthandling{#2}%
+ \ifcsname\@fha@\@fha@\@fha@\askedfonthandling\endcsname
+ \@EA\redofastenablehandling
+ \else\ifcsname\@fha@\@fha@\askedfonthandling\endcsname
+ \@EAEAEA\dofastenablehandling
+ \else
+ \@EAEAEA\nofastenablehandling
+ \fi\fi}
+
+\def\xfastenablehandling#1%
+ {\edef\askedfonthandling{#1}%
+ \ifcsname\@fha@\@fha@\askedfonthandling\endcsname
+ \@EA\dofastenablehandling
+ \else
+ \@EA\nofastenablehandling
+ \fi}
+
+\def\redofastenablehandling
+ {\startdirectcharacters
+ \edef\fonthandling{\csname\@fha@\@fha@\@fha@\askedfonthandling\endcsname}%
+ \rawprocesscommacommand[\fonthandling]\xfastenablehandling
+ \stopdirectcharacters}
+
+\def\dofastenablehandling
+ {\startdirectcharacters
+ \the\everyenablefonthandling
+ \edef\fonthandling{\csname\@fha@\@fha@\askedfonthandling\endcsname}%
+ \checkfonthandling\filoffonthandling
+ \rawprocesscommacommand[\fonthandling]\dodoenablehandling
+ \registerfonthandling\filoffonthandling
+ \stopdirectcharacters}
+
+\def\nofastenablehandling
+ {\the\everyenablefonthandling
+ \let\fonthandling\askedfonthandling
+ \dodoenablehandling\fonthandling}
+
+\def\dodoenablehandling#1%
+ {\ifcsname\@fha@#1\endcsname
+ \the\csname\@fha@#1\endcsname
+ \fi}
+
+%D We must not use \type {\purefontname} here (was a bug)!
+
+% not robust as long as tex reuses definitions internally
+%
+% \def\checkfonthandling#1% we need a fast compare
+% {\doifelsevalue{#1\s!handling\c!file}{\fontname\font}
+% \skiphandlingdeftrue\skiphandlingdeffalse}
+%
+% \def\registerfonthandling#1%
+% {\@EA\xdef\csname#1\s!handling\c!file\endcsname{\fontname\font}}
+
+\def\checkfonthandling #1{\skiphandlingdeffalse}
+\let\registerfonthandling \gobbleoneargument
+
+%D This one makes live easier (less definitions):
+
+\def\inherithandling #1 #2 %
+ {\inheritprotrudefactor #1 #2 %
+ \inheritadjustfactor #1 #2 }
+
+%D \macros
+%D {usehandling}
+%D
+%D Handling definitions are collected in dedicated files and
+%D loaded only once:
+%D
+%D % \showsetup{usehandling}
+
+\def\dousehandling#1% is the same as encoding
+ {\doifundefined{\c!file\f!handlingprefix#1}%
+ {\letvalueempty{\c!file\f!handlingprefix#1}%
+ \makeshortfilename[\truefilename{\f!handlingprefix#1}]%
+ \startreadingfile
+ \readsysfile{\shortfilename.mkii}
+ {\showmessage\m!handlings2{#1}}
+ {\showmessage\m!handlings3{#1}}%
+ \stopreadingfile}}
+
+\def\usehandling[#1]%
+ {\processcommalist[#1]\dousehandling}
+
+%D New:
+
+\def\overloadcharacter#1 #2 %
+ {\setfonttoks
+ \doifnumberelse{\string#2}
+ {\appendtoks\dooverloadcharacter{#1}{\char#2 }\to\fonttoks}
+ {\appendtoks\dooverloadcharacter{#1}{#2}\to\fonttoks}}
+
+\def\dooverloadcharacter#1%
+ {\setvalue{\characterencoding\string#1}}
+
+%D Let's now see if this macro works:
+
+% \setupfonthandling
+% [\s!default]
+% [\c!links=1,\c!rechts=1,\c!min=20,\c!max=20,\c!stap=5]
+
+% Beware of fonttoks:
+%
+% \startfonthandling[morespacing]
+% \appendtoks
+% \fontdimen2\handledfont=.50em
+% \fontdimen3\handledfont=.25em
+% \fontdimen4\handledfont=.25em
+% \to \fonttoks
+% \stopfonthandling
+%
+% \definefonthandling [morespacing] [morespacing]
+%
+% \definefontsynonym[xtexnansi-lmr7][texnansi-lmr7][handling=morespacing]
+% \definefont[crap][texnansi-lmr7]
+%
+% \crap \the\fontdimen2\font, \the\fontdimen3\font, \the\fontdimen4\font
+
+\usehandling [def]
+
+\protect \endinput
diff --git a/tex/context/base/hand-ini.mkiv b/tex/context/base/hand-ini.mkiv
new file mode 100644
index 000000000..0285b10cb
--- /dev/null
+++ b/tex/context/base/hand-ini.mkiv
@@ -0,0 +1,74 @@
+%D \module
+%D [ file=hand-ini,
+%D version=2008.02.12,
+%D title=\CONTEXT\ Handling Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Handling is implemented differently in \MKIV. Maybe I'll cook up
+%D some compatibility hack.
+
+% \definefontfeature[demo][default][mode=node,expansion=quality]
+% \definefontfeature[demo][default][mode=node,protrusion=pure]
+
+% experimental setup:
+%
+% \showframe \setupalign[hanging] \enabletrackers[fonts.protrusion]
+%
+% \definefontfeature[default] [default][mode=node,script=latn]
+% %definefontfeature[whatever][default][mode=node,lfbd=yes,rtbd=yes,script=latn]
+% \definefontfeature[whatever][default][mode=node,protrusion=quality]
+% \definefontfeature[whocares][default][mode=node,protrusion=yes,opbd=yes,script=latn] % left|right|yes
+%
+% \definedfont[fxlbi.otf*default] \input tufte 0123456789 \par \dorecurse{15}{1 2 3 4 5 6 7 8 9 0 } \par
+% \definedfont[fxlbi.otf*whatever] \input tufte 0123456789 \par \dorecurse{15}{1 2 3 4 5 6 7 8 9 0 } \par
+% \definedfont[fxlbi.otf*whocares] \input tufte 0123456789 \par \dorecurse{15}{1 2 3 4 5 6 7 8 9 0 } \par
+%
+% %definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
+% \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
+%
+% \definedfont[texgyrepagella-regularxx.otf*whocares] \input tufte
+
+\unprotect
+
+%D New stuff.
+
+\unexpanded\def\setupfontexpansion {\dodoubleargument\dosetupfontexpansion }
+\unexpanded\def\setupfontprotrusion{\dodoubleargument\dosetupfontprotrusion}
+
+\def\dosetupfontexpansion [#1][#2]{\ctxlua{commands.setupfontexpansion ("#1","#2")}}
+\def\dosetupfontprotrusion[#1][#2]{\ctxlua{commands.setupfontprotrusion("#1","#2")}}
+
+% \setupfontprotrusion[quality-upright][vector=quality]
+% \setupfontprotrusion[quality-slanted][vector=quality,right=1.5]
+
+%D Old stuff.
+
+\def\fonthandlingerror{\writestatus\m!fonts{font handling is replaced by features in mkiv}}
+
+\def\enableadjusting {\pdfadjustspacing\plustwo } \let\enableexpansion \enableadjusting
+\def\disableadjusting {\pdfadjustspacing\zerocount} \let\disableexpansion\disableadjusting
+\def\enableprotruding {\pdfprotrudechars\plustwo }
+\def\disableprotruding{\pdfprotrudechars\zerocount}
+
+\appendtoks \disableadjusting \to \everyforgetall % Here or not here?
+\appendtoks \disableprotruding \to \everyforgetall % Here or not here?
+
+\unexpanded\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen
+\unexpanded\def\definefonthandling {\dotripleempty\dodefinefonthandling}
+\unexpanded\def\setupfonthandling {\dodoubleempty\dosetupfonthandling }
+\def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror}
+\def\dosetupfonthandling [#1][#2]{\fonthandlingerror}
+\def\usehandling [#1]{\fonthandlingerror}
+
+%D Just to be sure, maybe users use it:
+
+\let\fonthandling\empty
+
+\protect \endinput
diff --git a/tex/context/base/java-ans.tex b/tex/context/base/java-ans.tex
new file mode 100644
index 000000000..636c894f9
--- /dev/null
+++ b/tex/context/base/java-ans.tex
@@ -0,0 +1,28 @@
+%D \module
+%D [ file=java-ans,
+%D version=1998.06.01,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Answer Analization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startJSpreamble{Do_Check_Answer} used later
+
+ function Do_Check_Answer (field, value)
+ { if (event.value.toLowerCase()==value.toLowerCase())
+ { event.target.hidden = true }
+ % { event.target.display = display.hidden }
+ return("\040") } // funny, "" does not work
+
+\stopJSpreamble
+
+\startJScode{Check_Answer} uses {Do_Check_Answer}
+ event.value = Do_Check_Answer(JS_S_1, JS_S_2) ;
+\stopJScode
+
+\endinput
diff --git a/tex/context/base/java-exa.tex b/tex/context/base/java-exa.tex
new file mode 100644
index 000000000..f40f70f84
--- /dev/null
+++ b/tex/context/base/java-exa.tex
@@ -0,0 +1,395 @@
+%D \module
+%D [ file=java-exa,
+%D version=2002.??.??,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Example Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% XFDF versus HTML
+% localhost versus remote versus set
+
+% filename | filename-nr => name
+% fakename | fakename-nr => file upload, unless localhost
+%
+% we erase the list because otherwise we end up in browser remembering
+% problems; also, it is not possible to set upload fields 'manually'
+
+\startJSpreamble request_1 used now
+
+ var example_method = "HTML" ;
+ var example_host = "" ;
+ var example_port = "" ;
+ var example_url = "" ;
+ var example_file = "" ;
+
+ var example_log = true ; % false
+
+ function stripped_exa_value( name ) {
+ f = this.getField(name) ;
+ if (f) {
+ str = f.value ;
+ if (str.indexOf(name+'-')==0) {
+ str = str.substr(name.length+1) ;
+ }
+ return str ;
+ } else {
+ return "" ;
+ }
+ }
+
+ function identify_example_url ( ) {
+ if (example_log) {
+ console.clear ;
+ console.println("base url: "+this.baseURL) ;
+ console.println("this url: "+this.URL) ;
+ }
+ if (this.baseURL != "") {
+ example_url = this.baseURL ;
+ } else {
+ if (this.URL != "") {
+ example_url = this.URL
+ }
+ }
+ if (example_url.indexOf("file://")>=0) {
+ example_url = "" ;
+ }
+ str = stripped_exa_value("examplehost") ;
+ if (str != "auto") {
+ example_host = str ;
+ if (str == "localhost") {
+ example_port = "8061"
+ }
+ }
+ str = stripped_exa_value("exampleport") ;
+ if (str != "auto") {
+ example_port = str ;
+ }
+ if (example_log) {
+ console.println("example_url: "+example_url) ;
+ console.println("example_host: "+example_host) ;
+ console.println("example_port: "+example_port) ;
+ }
+ }
+
+ function check_example_url ( url ) {
+ if (url.indexOf("file://")>=0) {
+ url = "http://localhost:8061" ;
+ console.println("file url replaced by: "+url) ;
+ } else {
+ if (url.indexOf("://")<0) {
+ url = "http://" + url ;
+ }
+ if (example_log) {
+ console.println("url before check: "+url) ;
+ }
+% url = url.replace(/(http:\\\/\\\/.+)(\\\/.*$)/, "$1") ;
+ url = url.replace(/(https*:\\\/\\\/.+?)(\\\/.*$)/, "$1/exarequest") ;
+ if (example_log) {
+ console.println("url after check: "+url) ;
+ }
+ }
+ return url ;
+ }
+
+ function set_example_xfdf ( method ) {
+ example_method = method ;
+ }
+
+ function set_example_file ( file ) {
+ example_method = file ;
+ }
+
+ function set_example_host ( host ) {
+ example_host = host ;
+ }
+
+ function set_example_port ( port ) {
+ example_host = host ;
+ }
+
+ function do_erase_example_file(tag) {
+ f = this.getField(tag) ;
+ if (f) {
+ f.value = "" ;
+ }
+ }
+
+ function do_erase_example_list(tag) {
+ for (i=1;i<=100;i++) {
+ f = this.getField(tag+"-"+i) ;
+ if (f) {
+ f.value = "" ;
+ } else {
+ return
+ }
+ }
+ }
+
+ function do_submit_example_url ( url ) {
+ if ((example_method == "XFDF" ) || (url.indexOf("localhost")>=0)) {
+ do_erase_example_file("fakename") ;
+ do_erase_example_list("fakename") ;
+ }
+ url = check_example_url(url) ;
+ if (example_log) {
+ console.println("submitting form to "+url+" using method "+example_method) ;
+ }
+ if (example_file != "") {
+ url = url + "/" + example_file ;
+ }
+ % we need the bFDF for acrobat 5
+ this.submitForm({cURL : url, bFDF : false, cSubmitAs : example_method}) ;
+ }
+
+ function submit_example_form ( ) {
+ identify_example_url() ;
+ if (example_host != "") {
+ if (example_port != "") {
+ do_submit_example_url(example_host+":"+example_port) ;
+ } else {
+ do_submit_example_url(example_host) ;
+ }
+ } else {
+ if (example_url != "") {
+ do_submit_example_url(example_url) ;
+ } else {
+ if (example_port != "") {
+ do_submit_example_url("localhost"+":"+example_port) ;
+ } else {
+ do_submit_example_url("localhost:8061") ; % local exampler
+ }
+ }
+ }
+ resetfilename () ;
+ }
+
+ function submit_form ( host, port) {
+ set_example_host(host) ;
+ set_example_post(post) ;
+ submit_example_form ;
+ }
+
+\stopJSpreamble
+
+\startJSpreamble request_2 used now
+
+ var exa_command = "" ;
+ var exa_option = "" ;
+ var exa_filename = "" ;
+ var exa_filelist = "" ;
+ var exa_registered = "" ;
+
+ function set_request (command,option) {
+ exa_command = command ;
+ if (exa_command == "") {
+ exa_option = option ;
+ } else { if (option == "") {
+ exa_option = "" ;
+ } else { if (option.indexOf("--")<0) {
+ exa_option = "--action=" + option ;
+ } else {
+ exa_option = option ;
+ } } }
+ }
+
+ function assemble_request ( ) {
+ v = this.getField('filename') ;
+ if (v) {
+ exa_filename = v.value ;
+ }
+ v = this.getField('filelist') ;
+ if (v) {
+ exa_filelist = v.value ;
+ }
+% exa_filename = exa_filename.replace(/\\\\/g,'/') ;
+% exa_filelist = exa_filelist.replace(/\\\\/g,'/') ;
+ str = "\\n" ;
+ str = str+"" ;
+ if (exa_filelist == "") {
+ exa_filelist = exa_registered ;
+ } else { if (exa_registered != "") {
+ exa_filelist = exa_filelist + "\\n" + exa_registered ;
+ } }
+ if (exa_command != "") {
+ str = str+""+exa_command+"" ;
+ }
+ if (exa_option != "") {
+ str = str+""+exa_option+"" ;
+ }
+ if (exa_filename != "") {
+ str = str+""+exa_filename+"" ;
+ }
+ var fls = "" ;
+ if (exa_filelist != "") {
+ % old method, soon obsolete
+ lst = exa_filelist.split(/\\s/) ;
+ for (i=0;i"+lst[i]+"" ;
+ }
+ } else { if (exa_multiple) {
+ for (i=1;i<=100;i++) {
+ % console.println("file field "+i) ;
+ f = this.getField("filename-"+ i) ;
+% if (f) { if (f.value != "") {
+% if (g) { if (g.value == "") {
+% fls = fls+""+f.value+"" ;
+% } else {
+% fls = fls+""+f.value+"" ;
+% } } else {
+% fls = fls+""+f.value+"" ;
+% }
+% } }
+ if (f) { if (f.value != "") {
+ fls = fls + "" ;
+ } else {
+ % console.println("b") ;
+ fls = fls + " label='" + g.value + "'>" ;
+ } } else {
+ % console.println("c") ;
+ fls = fls + ">" ;
+ }
+ fls = fls + f.value + "" ;
+ } }
+ }
+ } }
+ if (fls != "") {
+ str = str + "" + fls + "" ;
+ }
+ str = str + "" ;
+ v = this.getField('exa:request') ;
+ if (v) {
+ v.value = str ;
+ }
+ }
+
+\stopJSpreamble
+
+\startJSpreamble request_3 used now
+
+ var exa_multiple = false ;
+
+ function setfilename ( suffixes ) {
+ if (event.targetName) {
+ var name = event.targetName ;
+ var fake = name.replace(/filename/,"fakename") ;
+ } else {
+ var name = 'filename' ;
+ var fake = 'fakename' ;
+ }
+ f = this.getField(fake) ;
+ if (f) {
+ f.browseForFileToSubmit() ;
+ if ((suffixes != "") && (f.value != "")) {
+ %
+ s = suffixes.replace(/,/g,"|") ;
+ r = new RegExp() ;
+ s = "\\\\.(" + s + ")$" ;
+ r.compile(s, "i") ;
+ if (f.value.search(r)<=0) {
+ f.value = "" ;
+ app.alert('This filetype is not permitted.') ;
+ %
+ % lst = suffixes.split(/,/) ;
+ % ok = false ;
+ % for (i=0;i=0) {
+% f.value = "" ;
+% }
+% }
+ }
+ this.dirty = false ;
+ }
+
+ function addfilename () {
+ if (exa_multiple) {
+ h = this.getField("filelist") ;
+ g = this.getField("filename") ;
+ if ((g) && (h)) {
+ str = g.value ;
+ if (h.value == "") {
+ h.value = str ;
+ } else {
+ h.value = h.value + "\\n" + str ;
+ }
+ g.value = "" ;
+ this.value = "" ;
+ }
+ }
+ this.dirty = false ;
+ }
+
+ % this only works with client that assembles request
+
+ function registerfilename (str) {
+ if (str!="") {
+ h = this.getField("filelist") ;
+ if (h) {
+ if (h.value != "") {
+ h.value = h.value + "\\n" ;
+ }
+ h.value = h.value + str ;
+ } else {
+ if (exa_registered != "") {
+ exa_registered = exa_registered + "\\n" ;
+ }
+ exa_registered = exa_registered + str ;
+ }
+ }
+ console.show ;
+ console.println('registered files') ;
+ console.println("file: "+str) ;
+ console.println("list: "+exa_registered) ;
+ this.dirty = false ;
+ }
+
+ function checkfilename () {
+ }
+
+ function getfilename ( suffixes ) {
+ setfilename(suffixes) ;
+ checkfilename() ;
+ addfilename() ;
+ }
+
+ function resetfilename () {
+ do_erase_example_file("fakename") ;
+ do_erase_example_file("filename") ;
+ do_erase_example_file("filelist") ;
+ do_erase_example_list("filename") ;
+ do_erase_example_list("fakename") ;
+ }
+
+\stopJSpreamble
+
+\endinput
diff --git a/tex/context/base/java-fil.tex b/tex/context/base/java-fil.tex
new file mode 100644
index 000000000..4d79a2ace
--- /dev/null
+++ b/tex/context/base/java-fil.tex
@@ -0,0 +1,48 @@
+%D \module
+%D [ file=java-fil,
+%D version=1998.06.01,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Filing and Printing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startJSpreamble Auxiliary used now
+
+ function DocumentFileName ()
+ { var Paths = this.path.split("/") ;
+ Paths = Paths[Paths.length-1].split(".") ;
+ return(Paths[0]) }
+
+ function Print_Page_Range(From, To) % gaat mis, nog geen args mogelijk
+ { if ((Number(From)>0)&&(Number(To)>=Number(From)))
+ { var myFrom = Number(From)-1 ;
+ var myTo = Number(To)-1 ;
+ this.print(false,myFrom,myTo,true) } }
+
+ function Print_This_Page ()
+ { this.print(false,this.pageNum,this.pageNum,true) }
+
+\stopJSpreamble
+
+\definereference
+ [PrintSubPaginas]
+ [JS(Print_Page_Range{\firstsubpage,\lastsubpage})]
+
+\definereference
+ [PrintSubPages]
+ [JS(Print_Page_Range{\firstsubpage,\lastsubpage})]
+
+\definereference
+ [PrintDezePagina]
+ [JS(Print_This_Page)]
+
+\definereference
+ [PrintThisPage]
+ [JS(Print_This_Page)]
+
+\endinput
diff --git a/tex/context/base/java-fld.tex b/tex/context/base/java-fld.tex
new file mode 100644
index 000000000..3c24b7e02
--- /dev/null
+++ b/tex/context/base/java-fld.tex
@@ -0,0 +1,282 @@
+%D \module
+%D [ file=java-fld,
+%D version=1998.05.20,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Field Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% will be simplified, since we now parse functions
+
+% nu nog alles geladen, moet dus anders
+
+\startJSpreamble {Sanitize_TeX_Input} used later
+
+ function Sanitized_TeX_String (value)
+ { var v = value ;
+ v = v.replace( /\\\\oe/g,"\\234") ;
+ v = v.replace( /\\\\<>/g,"\\273") ;
+ v = v.replace( /\\\\`A/g,"\\300") ;
+ v = v.replace( /\\\\'A/g,"\\301") ;
+ v = v.replace( /\\\\^A/g,"\\302") ;
+ v = v.replace( /\\\\~A/g,"\\303") ;
+ v = v.replace( /\\\\"A/g,"\\304") ;
+ v = v.replace( /\\\\oA/g,"\\305") ;
+ v = v.replace( /\\\\AE/g,"\\306") ;
+ v = v.replace( /\\\\,C/g,"\\307") ;
+ v = v.replace( /\\\\`E/g,"\\310") ;
+ v = v.replace( /\\\\'E/g,"\\311") ;
+ v = v.replace( /\\\\^E/g,"\\312") ;
+ v = v.replace( /\\\\"E/g,"\\313") ;
+ v = v.replace( /\\\\`I/g,"\\314") ;
+ v = v.replace( /\\\\'I/g,"\\315") ;
+ v = v.replace( /\\\\^I/g,"\\316") ;
+ v = v.replace( /\\\\"I/g,"\\317") ;
+ v = v.replace( /\\\\~N/g,"\\321") ;
+ v = v.replace( /\\\\`O/g,"\\322") ;
+ v = v.replace( /\\\\'O/g,"\\323") ;
+ v = v.replace( /\\\\^O/g,"\\324") ;
+ v = v.replace( /\\\\~O/g,"\\325") ;
+ v = v.replace( /\\\\"O/g,"\\326") ;
+ v = v.replace( /\\\\`U/g,"\\331") ;
+ v = v.replace( /\\\\'U/g,"\\332") ;
+ v = v.replace( /\\\\^U/g,"\\333") ;
+ v = v.replace( /\\\\"U/g,"\\334") ;
+ v = v.replace( /\\\\'Y/g,"\\335") ;
+ v = v.replace( /\\\\ss/g,"\\337") ;
+ v = v.replace( /\\\\`a/g,"\\340") ;
+ v = v.replace( /\\\\'a/g,"\\341") ;
+ v = v.replace( /\\\\^a/g,"\\342") ;
+ v = v.replace( /\\\\~a/g,"\\343") ;
+ v = v.replace( /\\\\"a/g,"\\344") ;
+ v = v.replace( /\\\\oa/g,"\\345") ;
+ v = v.replace( /\\\\ae/g,"\\346") ;
+ v = v.replace( /\\\\,c/g,"\\347") ;
+ v = v.replace( /\\\\`e/g,"\\350") ;
+ v = v.replace( /\\\\'e/g,"\\351") ;
+ v = v.replace( /\\\\^e/g,"\\352") ;
+ v = v.replace( /\\\\"e/g,"\\353") ;
+ v = v.replace( /\\\\`i/g,"\\354") ;
+ v = v.replace( /\\\\'i/g,"\\355") ;
+ v = v.replace( /\\\\^i/g,"\\356") ;
+ v = v.replace( /\\\\"i/g,"\\357") ;
+ v = v.replace( /\\\\~n/g,"\\361") ;
+ v = v.replace( /\\\\`o/g,"\\362") ;
+ v = v.replace( /\\\\'o/g,"\\363") ;
+ v = v.replace( /\\\\^o/g,"\\364") ;
+ v = v.replace( /\\\\~o/g,"\\365") ;
+ v = v.replace( /\\\\"o/g,"\\366") ;
+ v = v.replace( /\\\\`u/g,"\\371") ;
+ v = v.replace( /\\\\'u/g,"\\372") ;
+ v = v.replace( /\\\\^u/g,"\\373") ;
+ v = v.replace( /\\\\"u/g,"\\374") ;
+ v = v.replace( /\\\\'y/g,"\\375") ;
+ v = v.replace( /\\\\"y/g,"\\377") ;
+ return(v) }
+
+ var TeX_Key_Mode = 0 ;
+
+ function Initialize_TeX_Keystroke ()
+ { TeX_Key_Char = "" ;
+ TeX_Key_Mode = 0 }
+
+ function Sanitized_TeX_Keystroke (change)
+ { if (change=="\\\\")
+ { TeX_Key_Mode = 1 ;
+ return("") }
+ else if (TeX_Key_Mode==1)
+ { TeX_Key_Mode = 2 ;
+ TeX_Key_Char = change ;
+ return("") }
+ else if (TeX_Key_Mode==2)
+ { TeX_Key_Mode = 0 ;
+ TeX_Key_Char = "\\\\"+TeX_Key_Char+change ;
+ return(Sanitized_TeX_String(TeX_Key_Char)) }
+ else
+ { TeX_Key_Mode = 0 ;
+ return(change) } }
+
+\stopJSpreamble
+
+\startJScode {Initialize_TeX_Key} uses {Sanitize_TeX_Input}
+ Initialize_TeX_Keystroke() ;
+\stopJScode
+
+\startJScode {Convert_TeX_Key} uses {Sanitize_TeX_Input}
+ if (!event.willCommit)
+ { event.change = Sanitized_TeX_Keystroke(event.change) }
+\stopJScode
+
+\startJScode{Convert_TeX_String} uses {Sanitize_TeX_Input}
+ event.value = Sanitized_TeX_String(event.value) ;
+\stopJScode
+
+\startJSpreamble fields_1 used now
+
+var visible_field = new Array() ;
+var visible_fields = 0 ;
+
+function PresetFields ( )
+ { this.syncAnnotScan() }
+
+function Preset_Fields ( )
+ { this.syncAnnotScan() }
+
+function Hide_When_Down ( )
+ { event.target.hidden = true }
+
+function Hide_Field ( Name )
+ { var v = this.getField(Name) ;
+ if (v)
+ { v.hidden = true ;
+ v.readonly = true ;
+ this.dirty = false } }
+
+function Do_Vide_Field ( Name, Closable )
+ { var v = this.getField(Name) ;
+ if (v)
+ { ++visible_fields ;
+ visible_field[visible_fields] = Name ;
+ v.hidden = false ;
+ if (Closable)
+ { v.readonly = false ;
+ v.value = "On" }
+ this.dirty = false } }
+
+function Vide_Field ( Name )
+ { Do_Vide_Field(Name,false) }
+
+function Vide_Hide_Field ( Name )
+ { Do_Vide_Field(Name,true) }
+
+function Hide_Fields ()
+ { while (visible_fields>0)
+ { Hide_Field(visible_field[visible_fields]) ;
+ --visible_fields } }
+
+function Vide_Fields ( Name )
+ { Hide_Fields () ;
+ Vide_Field ( Name) }
+
+function Vide_Hide_Fields ( Name )
+ { Hide_Fields () ;
+ Vide_Hide_Field ( Name) }
+
+function Toggle_Hide ( Name )
+ { var v = this.getField(Name) ;
+ if (v)
+ { v.hidden = !v.hidden ;
+ this.dirty = false } }
+
+function Field_On ( Name )
+ { v = this.getField(Name) ;
+ if (v) { v.value = "On" ; this.dirty = false } }
+
+function Field_Off ( Name )
+ { var v = this.getField(Name) ;
+ if (v) { v.value = "Off" ; this.dirty = false } }
+
+function Toggle_Value ( Name )
+ { var v = this.getField(Name) ;
+ if (v)
+ { if (v.value=="On")
+ { v.value = "Off" }
+ else
+ { v.value = "On" } }
+ this.dirty = false }
+
+function Toggle_Read ( Name )
+ { var v = this.getField(Name);
+ if (v) { v.readonly = !v.readonly } }
+
+function Flip_Fields ( Name )
+ { var Names = Name.split(",") ;
+ for (var i=0;i0) && (JS_R_1!=""))
+%D { gotoNamedDest(JS_R_1) };
+%D \stopJScode
+%D \stoptyping
+%D
+%D Such a piece of code is closely related to the interpreter
+%D used. Watch the last two lines, here the script adapts
+%D itself to the presence of a reference.
+%D
+%D While
+%D
+%D \starttyping
+%D \startJScode{name}
+%D name = 4 ;
+%D \stopJScode
+%D \stoptyping
+%D
+%D assumes uses no preamble or presumes that the preamble is
+%D always loaded, the next definition also tells \CONTEXT\ to
+%D actually include the preamble needed.
+%D
+%D \starttyping
+%D \startJScode{uses} uses {later}
+%D uses = 6 ;
+%D \stopJScode
+%D \stoptyping
+
+\long\def\startJScode#1 #2
+ {\doifelse{#2}{uses}
+ {\dostartJScodeA{#1}}
+ {\dostartJScodeB{#1} #2 }}
+
+\long\def\dostartJScodeA#1#2 #3\stopJScode
+ {\long\setgvalue{\r!java#1}{\do{#2}{#3}}}
+
+\long\def\dostartJScodeB#1#2\stopJScode
+ {\long\setgvalue{\r!java#1}{\do{}{#2}}}
+
+\let\stopJScode\relax
+
+%D \macros
+%D {presetJScode}
+%D
+%D The code can be retrieved by saying
+%D
+%D \starttyping
+%D \presetJScode{SomeScript}{template}
+%D \stoptyping
+%D
+%D Such a template is a comma separated list, where
+%D individual entries can optionally be transformed by
+%D \type{R{}} and \type{V{}}.
+%D
+%D After this call, the code is available in \type{\JScode}.
+
+\newif\ifdirectJScode
+
+\def\presetJScode#1#2% #1=operation #2=arguments
+ {\setverbosecscharacters
+ \def\par{\delcharacter}% was: { }
+ \scratchcounter\zerocount
+ \globallet\JScode\empty
+ \def\do##1##2%
+ {\doifelse{##2}{!}\directJScodetrue\directJScodefalse}%
+ \getvalue{\r!java#1}%
+ \edef\!!stringa{#2}%
+ \ifx\!!stringa\empty \else
+ \processcommacommand[\!!stringa]\dopresetJSvariables
+ \fi
+ \def\docommand##1%
+ {\doifundefinedelse{\r!java\r!java##1}
+ {\showmessage\m!javascript2{##1}}
+ {\useJSpreamblenow{##1}}}%
+% {\doglobal\increment\currentJSpreamble
+% \doglobal\addtocommalist{##1}\allJSpreambles}}%
+ \def\do##1##2%
+ {\xdef\JScode{\ifdirectJScode#1(\JScode)\else\JScode##2\fi}%
+ %\xdef\JScode{JS\string_N=\the\scratchcounter;\JScode}%
+ \processcommalist[##1]\docommand}%
+ \getvalue{\r!java#1}}
+
+\def\dopresetJSvariables#1%
+ {\advance\scratchcounter \plusone
+ \donefalse
+ \dodopresetJSvariables#1\end}%
+
+\def\dodopresetJSvariables
+ {\doifnextcharelse R\dodopresetJSrefvariables
+ {\doifnextcharelse V\dodopresetJSvervariables
+ {\doifnextcharelse S\dodopresetJSstrvariables
+ \dodopresetJSrawvariables}}}
+
+\def\dodopresetJSrefvariables R#1\end
+ {\doifreferencefoundelse{#1}
+ {\donetrue \dododopresetJSvariables R{\referenceprefix#1}%
+ \donefalse\dododopresetJSvariables P{\currentrealreference}}
+ {\unknownreference{#1}}%
+ \ifminimalizeJScode \else
+ \donetrue\dododopresetJSvariables S{#1}%
+ \fi}
+
+\def\dodopresetJSvervariables V#1\end
+ {\donefalse\dododopresetJSvariables V{#1}%
+ \ifminimalizeJScode \else
+ \donetrue\dododopresetJSvariables S{#1}%
+ \fi}
+
+\def\dodopresetJSstrvariables S#1\end
+ {\donetrue\dododopresetJSvariables S{#1}}
+
+\def\dodopresetJSrawvariables #1\end
+ {\donetrue\dododopresetJSvariables S{#1}}
+
+\def\JSprefix#1%
+ {JS\string_#1\string_\the\scratchcounter}
+
+\def\dododopresetJSvariables#1#2%
+ {\iftraceJScode
+ \writestatus{JavaScript}{\JSprefix#1=#2}
+ \xdef\JScode{\JScode console.println("\JSprefix#1=#2"); }%
+ \fi
+ \ifdirectJScode
+ \xdef\JScode{\ifx\JScode\empty\else\JScode,\fi\ifdone"#2"\else#2\fi}%
+ \else
+ \xdef\JScode{\JScode\JSprefix#1=\ifdone"#2"\else#2\fi; }%
+ \fi}
+
+%D \macros
+%D {startJSpreamble, flushJSpreamble}
+%D
+%D One can define insert \JAVASCRIPT\ code at the document level
+%D by using:
+%D
+%D \starttyping
+%D \startJSpreamble{oeps}
+%D oeps = 1 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D which is the same as:
+%D
+%D \starttyping
+%D \startJSpreamble{now} used now
+%D now = 2 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D while the next definition is only included when actually
+%D used.
+%D
+%D \starttyping
+%D \startJSpreamble{later} used later
+%D later = 3 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D This command may be used more that once, but always before
+%D the first page is shipped out.
+
+\newif\ifoneJSpreamble \oneJSpreamblefalse
+
+\let\allJSpreambles\empty
+\newcounter\nofJSpreambles
+\newcounter\currentJSpreamble
+
+\long\def\startJSpreamble#1 #2 %
+ {\bgroup % we need to restore the catcodes
+ \restoreendofline % just in case it happens while reading lists
+ \doifelse{#2}{used}
+ {\dostartJSpreamble#1 }
+ {\dostartJSpreamble#1 now #2 }}
+
+\long\def\dostartJSpreamble#1 #2 %
+ {\processaction
+ [#2]
+ [ later=>\chardef\JSstatus\zerocount,%
+ now=>\chardef\JSstatus\plusone ,%
+ \s!default=>\chardef\JSstatus\plustwo ,%
+ \s!unknown=>\chardef\JSstatus\plustwo ]%
+ \ifaddJSlinebreaks
+ \obeylines \let\obeyedline \normalpar
+ \obeyspaces \let\obeyedspace\normalspace
+ \fi
+ \dodostartJSpreamble{#1}}
+
+\long\def\dodostartJSpreamble#1#2\stopJSpreamble
+ {\presetJSfunctions #2function ()\end
+ \long\setgvalue{\r!java\r!java#1}{#2}%
+ \ifcase\JSstatus \else
+ \useJSpreamblenow{#1}%
+ \fi
+ \egroup}
+
+%D \macros
+%D {setJSpreamble, addtoJSpreamble}
+%D
+%D In addition to the previous preamble definitions, we can
+%D set a preamble \quote {in||line} and add tokens to a
+%D preamble.
+
+\def\setJSpreamble#1#2%
+ {\doifundefined{\r!java\r!java#1}
+ {\setgvalue{\r!java\r!java#1}{#2;}%
+ \doglobal\increment\currentJSpreamble
+ \doglobal\addtocommalist{#1}\allJSpreambles}}
+
+\def\addtoJSpreamble#1#2%
+ {\doifdefinedelse{\r!java\r!java#1}
+ {\edef\!!stringa{\r!java\r!java#1}%
+ \edef\!!stringb{\csname\!!stringa\endcsname}%
+ \@EA\setgvalue\@EA\!!stringa\@EA{\!!stringb #2;}}
+ {\setJSpreamble{#1}{#2}}}
+
+%D \macros
+%D {useJSpreamblenow}
+%D
+%D The next macro can be used to force inclusion of postponed
+%D \JAVASCRIPT\ preambles.
+
+\def\useJSpreamblenow#1%
+ {\doglobal\increment\currentJSpreamble
+ \doglobal\addtocommalist{#1}\allJSpreambles}
+
+%D Because we want to check for valid calls, we preload the
+%D functions. This means that we can call them directly as
+%D well as indirectly when defined by \type {\startJScode} etc.
+
+% \long\def\presetJSfunctions#1function #2(#3)%
+% {\doifelsenothing{#2}
+% {\long\def\presetJSfunctions##1\end{}}
+% {\stripspaces\from#2\to\ascii
+% \doifundefined{\r!java\ascii}{\setgvalue{\r!java\ascii}{\do{}{!}}}}%
+% \presetJSfunctions}
+
+\long\def\presetJSfunctions#1function#2(#3)%
+ {\doifelse{#2}\space
+ {\long\def\presetJSfunctions##1\end{}}
+ {\stripspaces\from#2\to\ascii
+ \doifundefined{\r!java\ascii}{\setgvalue{\r!java\ascii}{\do{}{!}}}}%
+ \presetJSfunctions}
+
+\def\getJSpreamble#1%
+ {\getvalue{\r!java\r!java#1}}
+
+\def\presetJSpreamble
+ {\ifx\allJSpreambles\empty\else
+ \bgroup
+ \setverbosecscharacters
+ \obeyspaces \let\obeyedspace\normalspace
+ \def\par{\delcharacter}% was: { }
+ \globallet\JSpreamble\empty
+ \def\@@collectedJSpreamble{\r!java\r!java collected}%
+ \letvalue{\@@collectedJSpreamble}=\empty
+ \def\docommand##1%
+ {\xdef\JScode{\getvalue{\r!java\r!java##1}}%
+ \ifoneJSpreamble % \global\letcdcsname
+ \@EA\setxvalue\@EA\@@collectedJSpreamble\@EA
+ {\csname\@@collectedJSpreamble\endcsname\JScode}%
+ \else
+ \setxvalue{\r!java\r!java##1}{\JScode}%
+ \fi}%
+ \processcommacommand[\allJSpreambles]\docommand
+ \ifoneJSpreamble
+ \gdef\allJSpreambles{collected}%
+ \fi
+ \globallet\presetJSpreamble\relax
+ \egroup
+ \fi}
+
+\def\flushJSpreamble
+ {\iflocation\ifx\allJSpreambles\empty\else
+ \ifcase\nofJSpreambles\else\ifnum\nofJSpreambles=\currentJSpreamble
+ \bgroup
+ \presetJSpreamble
+ \expanded{\doflushJSpreamble{\allJSpreambles}}%
+ \globallet\flushJSpreamble\relax
+ \globallet\allJSpreambles\empty
+ \egroup
+ \fi\fi
+ \fi\fi}
+
+\def\finalflushJSpreamble
+ {\iflocation
+ \flushJSpreamble
+ \ifcase\currentJSpreamble\relax\else
+ \savecurrentvalue\nofJSpreambles\currentJSpreamble
+ \globallet\currentJSpreamble\nofJSpreambles
+ \fi
+ \fi}
+
+\prependtoks \flushJSpreamble \to \everyshipout
+\prependtoks \finalflushJSpreamble \to \everylastshipout
+
+%D \macros
+%D {doPSsanitizeJScode}
+%D
+%D Before the code can be passed to the (\POSTSCRIPT\ or \PDF)
+%D output file, some precautions must be made concerning the
+%D use of \type{(} and~\type{)}. Here we use a beautiful
+%D \type{\aftergroup} trick I discovered in the \TABLE\ format.
+
+\def\doPSsanitizeJScode#1\to#2%
+ {\begingroup
+ \scratchcounter\zerocount % \aftergroup counter
+ \aftergroup\xdef
+ \aftergroup#2%
+ \aftergroup{%
+ \expanded{\defconvertedargument\noexpand\JScode{#1}}%
+ \expandafter\handletokens\JScode\with\dodoPSsanitizeJScode
+ \aftergroup}%
+ \endgroup
+ \iftraceJScode
+ \writestatus{JS trace}{#2}%
+ \fi}
+
+%D I started with:
+%D
+%D \starttyping
+%D \def\dodoPSsanitizeJScode#1%
+%D {\aftergroup\string
+%D \if#1(%
+%D \expandafter\aftergroup\csname#1\endcsname
+%D \else\if#1)%
+%D \expandafter\aftergroup\csname#1\endcsname
+%D \else\if#1;%
+%D \aftergroup;\aftergroup\string\expandafter\aftergroup\
+%D \else
+%D \expandafter\aftergroup#1%
+%D \fi\fi\fi
+%D \advance\scratchcounter by 1
+%D \ifnum\scratchcounter=500
+%D \expandafter\dododoPSsanitizeJScode
+%D \fi}
+%D \stoptyping
+%D
+%D For pretty printing purposes, we need some way to signal
+%D \TEX\ macros. Therefore we introduce a special keyword
+%D \type{TEX}. When followed by a space, this keyword is
+%D ignored, that is, filtered from the stream. Now we have:
+
+\chardef\JSisTEX \zerocount
+\chardef\JScomment\zerocount
+
+\newif\ifaddJSlinebreaks \addJSlinebreakstrue
+
+\def\flushJSisTEX
+ {\ifcase\JSisTEX
+ \or \aftergroup T%
+ \or \aftergroup T\aftergroup E%
+ \or \aftergroup T\aftergroup E\aftergroup X%
+ \fi
+ \chardef\JSisTEX\zerocount}
+
+% \def\doJSlinebreak
+% {\ifaddJSlinebreaks
+% \aftergroup\string\aftergroup\n%
+% \fi}
+%
+% \def\dodoPSsanitizeJScode#1% % input stack>500 & TEX check
+% {\if#1/%
+% \ifnum\JScomment=0
+% \chardef\JScomment\plusone
+% \else\ifnum\JScomment=1
+% \chardef\JScomment\plustwo
+% \fi\fi
+% \else
+% \ifnum\JScomment=1
+% \aftergroup/%
+% \chardef\JScomment\zerocount
+% \fi
+% \ifnum\JScomment=2
+% \if#1\delcharacter
+% \chardef\JScomment\zerocount
+% \fi
+% \else
+% \if#1\delcharacter
+% \flushJSisTEX\doJSlinebreak
+% \else\if#1(%
+% \flushJSisTEX\aftergroup\string\expandafter\aftergroup\csname#1\endcsname
+% \else\if#1)%
+% \flushJSisTEX\aftergroup\string\expandafter\aftergroup\csname#1\endcsname
+% \else\if#1;%
+% \flushJSisTEX\aftergroup;\doJSlinebreak
+% \else\if#1T%
+% \ifnum\JSisTEX=0 \chardef\JSisTEX\plusone \else\flushJSisTEX\aftergroup T\fi
+% \else\if#1E%
+% \ifnum\JSisTEX=1 \chardef\JSisTEX\plustwo \else\flushJSisTEX\aftergroup E\fi
+% \else\if#1X%
+% \ifnum\JSisTEX=2 \chardef\JSisTEX\plusthree \else\flushJSisTEX\aftergroup X\fi
+% \else\if#1\normalspace
+% \ifnum\JSisTEX=3 \chardef\JSisTEX\zerocount \else\flushJSisTEX\aftergroup#1\fi
+% \else
+% \flushJSisTEX\aftergroup\string\expandafter\aftergroup#1%
+% \fi\fi\fi\fi\fi\fi\fi\fi
+% \fi
+% \fi
+% \dododoPSsanitizeJScode}
+
+% todo: "http:\\" -> simple. maar wel \" afvangen
+%
+% use new pdftex escape mechanism or make fully expandable version, not used that often btw
+
+\chardef\JSstring\zerocount
+
+\def\doJSlinebreak
+ {\chardef\JScomment\zerocount
+ \chardef\JSstring\zerocount
+ \ifaddJSlinebreaks
+ \aftergroup\string\aftergroup\n%
+ \fi}
+
+\def\dodoPSsanitizeJScode#1% % input stack>500 & TEX check
+ {\if#1/%
+ \ifnum\JSstring=0
+ \ifnum\JScomment=0
+ \chardef\JScomment\plusone
+ \else\ifnum\JScomment=1
+ \chardef\JScomment\plustwo
+ \fi\fi
+ \else
+ \aftergroup/%
+ \fi
+ \else
+ \ifnum\JScomment=1
+ \aftergroup/%
+ \chardef\JScomment\zerocount
+ \fi
+ % is the delchar trick still needed?
+ \ifnum\JScomment=2
+ \ifnum`#1=13 % brrr
+ \doJSlinebreak
+ \else\if#1\par
+ \doJSlinebreak
+ \else\if#1\delcharacter
+ \doJSlinebreak
+ \fi\fi\fi
+ \else
+ \ifnum`#1=13 % brrr
+ \flushJSisTEX\doJSlinebreak
+ \else\if#1\par
+ \flushJSisTEX\doJSlinebreak
+ \else\if#1\delcharacter
+ \flushJSisTEX\doJSlinebreak
+ \else\if#1(%
+ \flushJSisTEX\aftergroup\string\expandafter\aftergroup\csname#1\endcsname
+ \else\if#1)%
+ \flushJSisTEX\aftergroup\string\expandafter\aftergroup\csname#1\endcsname
+ %\else\if#1;%
+ % \flushJSisTEX\aftergroup;\doJSlinebreak
+ \else\if#1T%
+ \ifnum\JSisTEX=0 \chardef\JSisTEX\plusone \else\flushJSisTEX\aftergroup T\fi
+ \else\if#1E%
+ \ifnum\JSisTEX=1 \chardef\JSisTEX\plustwo \else\flushJSisTEX\aftergroup E\fi
+ \else\if#1X%
+ \ifnum\JSisTEX=2 \chardef\JSisTEX\plusthree \else\flushJSisTEX\aftergroup X\fi
+ \else\if#1\normalspace
+ \ifnum\JSisTEX=3 \chardef\JSisTEX\zerocount \else\flushJSisTEX\aftergroup#1\fi
+ \else
+ % todo: "test\"test"
+ \if#1"%
+ \ifcase\JSstring
+ \chardef\JSstring\plusone
+ \else
+ \chardef\JSstring\zerocount
+ \fi
+ \fi
+ \flushJSisTEX\aftergroup\string\expandafter\aftergroup#1%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi % \fi
+ \fi
+ \fi
+ \dododoPSsanitizeJScode}
+
+%D Close reading learns that one line comments (\type{// ...})
+%D are removed from the stream. This permits switching in
+%D pretty printing \JAVASCRIPT\ sources as well as saves
+%D some bytes.
+
+%D The magic 500 in the next hack prevents the input stack from
+%D overflowing when large scripts are sanitized.
+
+\def\dododoPSsanitizeJScode
+ {\ifcase\JSisTEX\ifcase\JScomment
+ \advance\scratchcounter \plusone
+ \fi\fi
+ \ifnum\scratchcounter=500
+ \expandafter\dodododoPSsanitizeJScode
+ \fi}
+
+\def\dodododoPSsanitizeJScode
+ {\let\next={%
+ \aftergroup}%
+ \endgroup
+ \begingroup
+ \aftergroup\xdef
+ \aftergroup\sanitizedJScode
+ \aftergroup{%
+ \aftergroup\sanitizedJScode
+ \let\next=}}
+
+%D The macro \type{\doPSsanitizeJScode} converts its argument
+%D into the macro \type{\sanitizedJScode}, thereby prefixing
+%D each \type{(} and \type{)} by a slash.
+
+%D Hooking this mechanism into the general \CONTEXT\ reference
+%D mechanism does not take much effort:
+
+\definespecialtest{JS}%
+ {\doifdefinedelse{\r!java\currentreferenceoperation}}
+
+\definespeciallocation{JS}#1#2%
+ {\iflocation
+ \bgroup
+ \bgroup
+ \presetJScode
+ \currentreferenceoperation
+ \currentreferencearguments
+ \egroup
+ \dohandlegoto
+ {#2}%
+ {\dostartgotoJS\buttonwidth\buttonheight\JScode}%
+ {\dostopgotoJS}%
+ \egroup
+ \else
+ {#2}%
+ \fi}
+
+%D \macros
+%D {useJSscripts}
+%D
+%D In due time, users will build their collections of scripts,
+%D which can be used (loaded) when applicable. Although not all
+%D public, we will provide some general purpose scripts,
+%D collected in files with names like \type{java-...}. One can
+%D load these scripts with \type{\useJSscripts}, like:
+%D
+%D \starttyping
+%D \useJSscripts[fld]
+%D \stoptyping
+%D
+%D The not so complicated implementation of this macro is:
+
+\def\dodouseJSscripts#1%
+ {\doifelse{#1}\v!reset
+ {\let\allJSpreambles\empty}
+ {\doifundefined{\c!file\f!javascriptprefix#1}
+ {\startnointerference
+ \letgvalueempty{\c!file\f!javascriptprefix#1}%
+ \makeshortfilename[\f!javascriptprefix#1]%
+ \startreadingfile
+ \readsysfile\shortfilename{\showmessage\m!javascript1{#1}}\donothing
+ \stopreadingfile
+ \stopnointerference}}}
+
+\def\douseJSscripts[#1][#2]%
+ {\processcommalist[#1]\dodouseJSscripts
+ \processcommalist[#2]\useJSpreamblenow}
+
+\def\useJSscripts
+ {\dodoubleempty\douseJSscripts}
+
+\protect \endinput
diff --git a/tex/context/base/java-ini.mkiv b/tex/context/base/java-ini.mkiv
new file mode 100644
index 000000000..6536ced48
--- /dev/null
+++ b/tex/context/base/java-ini.mkiv
@@ -0,0 +1,164 @@
+%D \module
+%D [ file=java-ini,
+%D version=1998.01.30,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 JavaScript Macros / Initialization}
+
+\registerctxluafile{java-ini}{1.001}
+
+\unprotect
+
+%D \macros
+%D {JS*}
+%D
+%D Because \JAVASCRIPT's are activated by the user, for
+%D instance by activating on a button, their support is closely
+%D related to the referencing mechanism. Integration takes
+%D place by
+%D
+%D \starttyping
+%D \goto{calculate total}[Sum()]
+%D \stoptyping
+%D
+%D The \type{()} classify this as a script. If they are absent,
+%D the keyword is treated as a normal reference.
+%D
+%D One can pass arguments to such a script by saying:
+%D
+%D \starttyping
+%D \goto{calculate total}[Sum(1.5,2.3)]
+%D \stoptyping
+
+
+%D \macros
+%D {startJScode}
+%D
+%D A piece of \JAVASCRIPT\ code is defined by saying:
+%D
+%D \starttyping
+%D \startJScode{name}
+%D name = 4 ;
+%D \stopJScode
+%D \stoptyping
+%D
+%D This assumes uses no preamble or presumes that the preamble is
+%D always loaded, the next definition also tells \CONTEXT\ to
+%D actually include the preamble needed.
+%D
+%D \starttyping
+%D \startJScode{uses} uses {later}
+%D uses = 6 ;
+%D \stopJScode
+%D \stoptyping
+%D
+%D \macros
+%D {startJSpreamble}
+%D
+%D One can define insert \JAVASCRIPT\ code at the document level
+%D by using:
+%D
+%D \starttyping
+%D \startJSpreamble{oeps}
+%D oeps = 1 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D which is the same as:
+%D
+%D \starttyping
+%D \startJSpreamble{now} used now
+%D now = 2 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D while the next definition is only included when actually
+%D used.
+%D
+%D \starttyping
+%D \startJSpreamble{later} used later
+%D later = 3 ;
+%D \stopJSpreamble
+%D \stoptyping
+%D
+%D This command may be used more that once, but always before
+%D the first page is shipped out.
+%D
+%D \macros
+%D {setJSpreamble, addtoJSpreamble}
+%D
+%D In addition to the previous preamble definitions, we can
+%D set a preamble \quote {in||line} and add tokens to a
+%D preamble.
+%D
+%D \macros
+%D {useJSpreamblenow}
+%D
+%D This macro can be used to force inclusion of postponed
+%D \JAVASCRIPT\ preambles.
+
+\unexpanded\def\startJScode
+ {\begingroup\obeylualines\obeyluatokens\dostartJScode}
+
+\long\def\dostartJScode#1\stopJScode
+ {\normalexpanded{\endgroup\ctxlua{javascripts.storecode(\!!bs#1\!!es)}}}
+
+\let\stopJScode\relax
+
+\unexpanded\def\startJSpreamble
+ {\begingroup\obeylualines\obeyluatokens\dostartJSpreamble}
+
+\long\def\dostartJSpreamble#1\stopJSpreamble
+ {\normalexpanded{\endgroup\ctxlua{javascripts.storepreamble(\!!bs#1\!!es)}}}
+
+\let\stopJSpreamble\relax
+
+\def\setJSpreamble #1#2{\ctxlua{javascripts.storepreamble ("#1",\!!bs#2\!!es)}}
+\def\addtoJSpreamble #1#2{\ctxlua{javascripts.addtopreamble ("#1",\!!bs#2\!!es)}}
+\def\useJSpreamblenow #1{\ctxlua{javascripts.usepreamblenow("#1")}}
+\def\finalflushJSpreamble{\iflocation\ctxlua{javascripts.flushpreambles()}\fi}
+
+%D \macros
+%D {useJSscripts}
+%D
+%D In due time, users will build their collections of scripts,
+%D which can be used (loaded) when applicable. Although not all
+%D public, we will provide some general purpose scripts,
+%D collected in files with names like \type{java-...}. One can
+%D load these scripts with \type{\useJSscripts}, like:
+%D
+%D \starttyping
+%D \useJSscripts[fld]
+%D \stoptyping
+%D
+%D The not so complicated implementation of this macro is:
+
+\def\dodouseJSscripts#1%
+ {\doifelse{#1}\v!reset
+ {\let\allJSpreambles\empty}
+ {\ifcsname\c!file\f!javascriptprefix#1\endcsname \else
+ \startnointerference
+ \letgvalueempty{\c!file\f!javascriptprefix#1}%
+ \makeshortfilename[\f!javascriptprefix#1]%
+ \startreadingfile
+ \readsysfile\shortfilename{\showmessage\m!javascript1{#1}}\donothing
+ \stopreadingfile
+ \stopnointerference
+ \fi}}
+
+\def\douseJSscripts[#1][#2]%
+ {\processcommalist[#1]\dodouseJSscripts
+ \processcommalist[#2]\useJSpreamblenow}
+
+\def\useJSscripts
+ {\dodoubleempty\douseJSscripts}
+
+\protect \endinput
diff --git a/tex/context/base/java-stp.tex b/tex/context/base/java-stp.tex
new file mode 100644
index 000000000..df4fbcc2f
--- /dev/null
+++ b/tex/context/base/java-stp.tex
@@ -0,0 +1,121 @@
+%D \module
+%D [ file=java-stp,
+%D version=2004.03.15,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Stepping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% we define ocglist global, otherwise we quickly run into a memory hog (even
+% out of memory in a 512 Meg machine)
+
+% we cannot use doc_visited[this.pageNum] instead of doc_currentstep because
+% of some funny side effect (i.e. dup or so)
+
+\startJSpreamble Steps used now
+
+ var doc_ocglist = this.getOCGs() ;
+ var doc_stepname = "step" ;
+ var doc_currentstep = 0 ;
+ var doc_maxstep = 50 ;
+ var doc_visited = new Array() ;
+ var doc_busy = new Array() ;
+
+ function SetupStepper ( layername, laststep ) {
+ doc_stepname = layername ;
+ doc_maxstep = laststep ;
+ for (var i=0; i<=this.numPages; i++) {
+ doc_visited[i] = 0 ;
+ doc_busy[i] = 0 ;
+ }
+ }
+
+ for (var i=0; i<=this.numPages; i++) {
+ doc_visited[i] = 0 ;
+ doc_busy[i] = 0 ;
+ }
+
+ function GetOCG ( name ) {
+ for (var i=0; i < doc_ocglist.length; i++) {
+ if (doc_ocglist[i].name == name) {
+ return doc_ocglist[i] ;
+ }
+ }
+ return null ;
+ }
+
+ function CheckBusy ( ) {
+ var ocg = GetOCG("step:busy") ;
+ if (ocg != null) {
+ if (doc_visited[this.pageNum]==0) {
+ ocg.state = true ;
+ } else {
+ if (doc_visited[this.pageNum]Internally work with scaled point, which are
+represented by integers. However, in practice, at east at the
+ end we work with more generic units like points (pt). Going
+from scaled points (numbers) to one of those units can be
+done by using the conversion factors collected in the following
+table.
+--ldx]]--
+
+local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable
+local P, S, R, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.match
+
+number = number or { }
+
+number.tonumberf = function(n) return match(format("%.20f",n),"(.-0?)0*$") end -- one zero too much but alas
+number.tonumberg = function(n) return format("%.20g",n) end
+
+local dimenfactors = {
+ ["pt"] = 1/65536,
+ ["in"] = ( 100/ 7227)/65536,
+ ["cm"] = ( 254/ 7227)/65536,
+ ["mm"] = ( 2540/ 7227)/65536,
+ ["sp"] = 1, -- 65536 sp in 1pt
+ ["bp"] = ( 7200/ 7227)/65536,
+ ["pc"] = ( 1/ 12)/65536,
+ ["dd"] = ( 1157/ 1238)/65536,
+ ["cc"] = ( 1157/14856)/65536,
+ ["nd"] = (20320/21681)/65536,
+ ["nc"] = ( 5080/65043)/65536
+}
+
+--~ print(table.serialize(dimenfactors))
+--~
+--~ %.99g:
+--~
+--~ t={
+--~ ["bp"]=1.5201782378580324e-005,
+--~ ["cc"]=1.1883696112892098e-006,
+--~ ["cm"]=5.3628510057769479e-007,
+--~ ["dd"]=1.4260435335470516e-005,
+--~ ["em"]=0.000152587890625,
+--~ ["ex"]=6.103515625e-005,
+--~ ["in"]=2.1113586636917117e-007,
+--~ ["mm"]=5.3628510057769473e-008,
+--~ ["nc"]=1.1917446679504327e-006,
+--~ ["nd"]=1.4300936015405194e-005,
+--~ ["pc"]=1.2715657552083333e-006,
+--~ ["pt"]=1.52587890625e-005,
+--~ ["sp"]=1,
+--~ }
+--~
+--~ patched %s and tonumber
+--~
+--~ t={
+--~ ["bp"]=0.00001520178238,
+--~ ["cc"]=0.00000118836961,
+--~ ["cm"]=0.0000005362851,
+--~ ["dd"]=0.00001426043534,
+--~ ["em"]=0.00015258789063,
+--~ ["ex"]=0.00006103515625,
+--~ ["in"]=0.00000021113587,
+--~ ["mm"]=0.00000005362851,
+--~ ["nc"]=0.00000119174467,
+--~ ["nd"]=0.00001430093602,
+--~ ["pc"]=0.00000127156576,
+--~ ["pt"]=0.00001525878906,
+--~ ["sp"]=1,
+--~ }
+
+--[[ldx--
+
A conversion function that takes a number, unit (string) and optional
+format (string) is implemented using this table.
+--ldx]]--
+
+-- was:
+
+local function todimen(n,unit,fmt)
+ if type(n) == 'string' then
+ return n
+ else
+ unit = unit or 'pt'
+ return format(fmt or "%s%s",n*dimenfactors[unit],unit)
+ -- if fmt then
+ -- return format(fmt,n*dimenfactors[unit],unit)
+ -- else
+ -- return match(format("%.20f",n*dimenfactors[unit]),"(.-0?)0*$") .. unit
+ -- end
+ end
+end
+
+--[[ldx--
+
We collect a bunch of converters in the number namespace.
+--ldx]]--
+
+number.maxdimen = 1073741823
+number.todimen = todimen
+number.dimenfactors = dimenfactors
+
+function number.topoints (n) return todimen(n,"pt") end
+function number.toinches (n) return todimen(n,"in") end
+function number.tocentimeters (n) return todimen(n,"cm") end
+function number.tomillimeters (n) return todimen(n,"mm") end
+function number.toscaledpoints(n) return todimen(n,"sp") end
+function number.toscaledpoints(n) return n .. "sp" end
+function number.tobasepoints (n) return todimen(n,"bp") end
+function number.topicas (n) return todimen(n "pc") end
+function number.todidots (n) return todimen(n,"dd") end
+function number.tociceros (n) return todimen(n,"cc") end
+function number.tonewdidots (n) return todimen(n,"nd") end
+function number.tonewciceros (n) return todimen(n,"nc") end
+
+--[[ldx--
+
More interesting it to implement a (sort of) dimen datatype, one
+that permits calculations too. First we define a function that
+converts a string to scaledpoints. We use . We capture
+a number and optionally a unit. When no unit is given a constant
+capture takes place.
We use a metatable to intercept errors. When no key is found in
+the table with factors, the metatable will be consulted for an
+alternative index function.
The main (and globally) visible representation of a dimen is defined next: it is
+a one-element table. The unit that is returned from the match is normally a number
+(one of the previously defined factors) but we also accept functions. Later we will
+see why.
+--ldx]]--
+
+function dimen(a)
+ if a then
+ local ta= type(a)
+ if ta == "string" then
+ local value, unit = lpegmatch(pattern,a)
+ if type(unit) == "function" then
+ k = value/unit()
+ else
+ k = value/unit
+ end
+ a = k
+ elseif ta == "table" then
+ a = a[1]
+ end
+ return setmetatable({ a }, dimensions)
+ else
+ return setmetatable({ 0 }, dimensions)
+ end
+end
+
+--[[ldx--
+
This function return a small hash with a metatable attached. It is
+through this metatable that we can do the calculations. We could have
+shared some of the code but for reasons of speed we don't.
+--ldx]]--
+
+function dimensions.__add(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = a:todimen() elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ return setmetatable({ a + b }, dimensions)
+end
+
+function dimensions.__sub(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = a:todimen() elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ return setmetatable({ a - b }, dimensions)
+end
+
+function dimensions.__mul(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = a:todimen() elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ return setmetatable({ a * b }, dimensions)
+end
+
+function dimensions.__div(a, b)
+ local ta, tb = type(a), type(b)
+ if ta == "string" then a = a:todimen() elseif ta == "table" then a = a[1] end
+ if tb == "string" then b = b:todimen() elseif tb == "table" then b = b[1] end
+ return setmetatable({ a / b }, dimensions)
+end
+
+function dimensions.__unm(a)
+ local ta = type(a)
+ if ta == "string" then a = a:todimen() elseif ta == "table" then a = a[1] end
+ return setmetatable({ - a }, dimensions)
+end
+
+--[[ldx--
+
It makes no sense to implement the power and modulo function but
+the next two do make sense because they permits is code like:
+
+
+local a, b = dimen "10pt", dimen "11pt"
+...
+if a > b then
+ ...
+end
+
+--ldx]]--
+
+-- makes no sense: dimensions.__pow and dimensions.__mod
+
+function dimensions.__lt(a, b)
+ return a[1] < b[1]
+end
+
+function dimensions.__eq(a, b)
+ return a[1] == b[1]
+end
+
+--[[ldx--
+
We also need to provide a function for conversion to string (so that
+we can print dimensions). We print them as points, just like .
Since it does not take much code, we also provide a way to access
+a few accessors
+
+
+print(dimen().pt)
+print(dimen().sp)
+
+--ldx]]--
+
+function dimensions.__index(tab,key)
+ local d = dimenfactors[key]
+ if not d then
+ error("illegal property of dimen: " .. key)
+ d = 1
+ end
+ return 1/d
+end
+
+--[[ldx--
+
In the converter from string to dimension we support functions as
+factors. This is because in we have a few more units:
+ex and em. These are not constant factors but
+depend on the current font. They are not defined by default, but need
+an explicit function call. This is because at the moment that this code
+is loaded, the relevant tables that hold the functions needed may not
+yet be available.
+--ldx]]--
+
+function dimensions.texify() -- todo: %
+ local fti, fc = fonts and fonts.ids and fonts.ids, font and font.current
+ if fti and fc then
+ dimenfactors["ex"] = function() return fti[fc()].ex_height end
+ dimenfactors["em"] = function() return fti[fc()].quad end
+ else
+ dimenfactors["ex"] = 1/65536* 4 -- 4pt
+ dimenfactors["em"] = 1/65536*10 -- 10pt
+ end
+end
+
+--[[ldx--
+
In order to set the defaults we call this function now. At some point
+the macro package needs to make sure the function is called again.
+--ldx]]--
+
+dimensions.texify()
+
+--[[ldx--
+
The previous code is rather efficient (also thanks to ) but we
+can speed it up by caching converted dimensions. On my machine (2008) the following
+loop takes about 25.5 seconds.
When we cache converted strings this becomes 16.3 seconds. In order not
+to waste too much memory on it, we tag the values of the cache as being
+week which mean that the garbage collector will collect them in a next
+sweep. This means that in most cases the speed up is mostly affecting the
+current couple of calculations and as such the speed penalty is small.
+
+
We redefine two previous defined functions that can benefit from
+this:
+--ldx]]--
+
+local known = { } setmetatable(known, { __mode = "v" })
+
+function dimen(a)
+ if a then
+ local ta= type(a)
+ if ta == "string" then
+ local k = known[a]
+ if k then
+ a = k
+ else
+ local value, unit = lpegmatch(dimenpair,a)
+ if type(unit) == "function" then
+ k = value/unit()
+ else
+ k = value/unit
+ end
+ known[a] = k
+ a = k
+ end
+ elseif ta == "table" then
+ a = a[1]
+ end
+ return setmetatable({ a }, dimensions)
+ else
+ return setmetatable({ 0 }, dimensions)
+ end
+end
+
+function string:todimen()
+ if type(self) == "number" then
+ return self
+ else
+ local k = known[self]
+ if not k then
+ local value, unit = lpegmatch(dimenpair,self)
+ if value and unit then
+ k = value/unit
+ else
+ k = 0
+ end
+ -- print(self,value,unit)
+ known[self] = k
+ end
+ return k
+ end
+end
+
+function number.toscaled(d)
+ return format("0.5f",d/2^16)
+end
+
+--[[ldx--
+
In a similar fashion we can define a glue datatype. In that case we
+probably use a hash instead of a one-element table.
+--ldx]]--
+
+--[[ldx--
+
Goodie:s
+--ldx]]--
+
+function number.percent(n) -- will be cleaned up once luatex 0.30 is out
+ local hsize = tex.hsize
+ if type(hsize) == "string" then
+ hsize = hsize:todimen()
+ end
+ return (n/100) * hsize
+end
+
+number["%"] = number.percent
diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua
new file mode 100644
index 000000000..2643f538b
--- /dev/null
+++ b/tex/context/base/l-dir.lua
@@ -0,0 +1,363 @@
+if not modules then modules = { } end modules ['l-dir'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- dir.expand_name will be merged with cleanpath and collapsepath
+
+local type = type
+local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
+local lpegmatch = lpeg.match
+
+dir = dir or { }
+
+-- handy
+
+function dir.current()
+ return (gsub(lfs.currentdir(),"\\","/"))
+end
+
+-- optimizing for no string.find (*) does not save time
+
+local attributes = lfs.attributes
+local walkdir = lfs.dir
+
+local function glob_pattern(path,patt,recurse,action)
+ local ok, scanner
+ if path == "/" then
+ ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ else
+ ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ end
+ if ok and type(scanner) == "function" then
+ if not find(path,"/$") then path = path .. '/' end
+ for name in scanner do
+ local full = path .. name
+ local mode = attributes(full,'mode')
+ if mode == 'file' then
+ if find(full,patt) then
+ action(full)
+ end
+ elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
+ glob_pattern(full,patt,recurse,action)
+ end
+ end
+ end
+end
+
+dir.glob_pattern = glob_pattern
+
+local function collect_pattern(path,patt,recurse,result)
+ local ok, scanner
+ result = result or { }
+ if path == "/" then
+ ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ else
+ ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ end
+ if ok and type(scanner) == "function" then
+ if not find(path,"/$") then path = path .. '/' end
+ for name in scanner do
+ local full = path .. name
+ local attr = attributes(full)
+ local mode = attr.mode
+ if mode == 'file' then
+ if find(full,patt) then
+ result[name] = attr
+ end
+ elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
+ attr.list = collect_pattern(full,patt,recurse)
+ result[name] = attr
+ end
+ end
+ end
+ return result
+end
+
+dir.collect_pattern = collect_pattern
+
+local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+
+local pattern = Ct {
+ [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
+ [2] = C(((1-S("*?/"))^0 * P("/"))^0),
+ [3] = C(P(1)^0)
+}
+
+local filter = Cs ( (
+ P("**") / ".*" +
+ P("*") / "[^/]*" +
+ P("?") / "[^/]" +
+ P(".") / "%%." +
+ P("+") / "%%+" +
+ P("-") / "%%-" +
+ P(1)
+)^0 )
+
+local function glob(str,t)
+ if type(t) == "function" then
+ if type(str) == "table" then
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ elseif lfs.isfile(str) then
+ t(str)
+ else
+ local split = lpegmatch(pattern,str)
+ if split then
+ local root, path, base = split[1], split[2], split[3]
+ local recurse = find(base,"%*%*")
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
+ glob_pattern(start,result,recurse,t)
+ end
+ end
+ else
+ if type(str) == "table" then
+ local t = t or { }
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ return t
+ elseif lfs.isfile(str) then
+ local t = t or { }
+ t[#t+1] = str
+ return t
+ else
+ local split = lpegmatch(pattern,str)
+ if split then
+ local t = t or { }
+ local action = action or function(name) t[#t+1] = name end
+ local root, path, base = split[1], split[2], split[3]
+ local recurse = find(base,"%*%*")
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
+ glob_pattern(start,result,recurse,action)
+ return t
+ else
+ return { }
+ end
+ end
+ end
+end
+
+dir.glob = glob
+
+--~ list = dir.glob("**/*.tif")
+--~ list = dir.glob("/**/*.tif")
+--~ list = dir.glob("./**/*.tif")
+--~ list = dir.glob("oeps/**/*.tif")
+--~ list = dir.glob("/oeps/**/*.tif")
+
+local function globfiles(path,recurse,func,files) -- func == pattern or function
+ if type(func) == "string" then
+ local s = func -- alas, we need this indirect way
+ func = function(name) return find(name,s) end
+ end
+ files = files or { }
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ --- skip
+ else
+ local mode = attributes(name,'mode')
+ if mode == "directory" then
+ if recurse then
+ globfiles(path .. "/" .. name,recurse,func,files)
+ end
+ elseif mode == "file" then
+ if func then
+ if func(name) then
+ files[#files+1] = path .. "/" .. name
+ end
+ else
+ files[#files+1] = path .. "/" .. name
+ end
+ end
+ end
+ end
+ return files
+end
+
+dir.globfiles = globfiles
+
+-- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex")
+-- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex")
+-- t = dir.glob("c:/data/develop/context/texmf/**/*.tex")
+-- t = dir.glob("f:/minimal/tex/**/*")
+-- print(dir.ls("f:/minimal/tex/**/*"))
+-- print(dir.ls("*.tex"))
+
+function dir.ls(pattern)
+ return table.concat(glob(pattern),"\n")
+end
+
+--~ mkdirs("temp")
+--~ mkdirs("a/b/c")
+--~ mkdirs(".","/a/b/c")
+--~ mkdirs("a","b","c")
+
+local make_indeed = true -- false
+
+if string.find(os.getenv("PATH"),";") then -- os.type == "windows"
+
+ function dir.mkdirs(...)
+ local str, pth, t = "", "", { ... }
+ for i=1,#t do
+ local s = t[i]
+ if s ~= "" then
+ if str ~= "" then
+ str = str .. "/" .. s
+ else
+ str = s
+ end
+ end
+ end
+ local first, middle, last
+ local drive = false
+ first, middle, last = match(str,"^(//)(//*)(.*)$")
+ if first then
+ -- empty network path == local path
+ else
+ first, last = match(str,"^(//)/*(.-)$")
+ if first then
+ middle, last = match(str,"([^/]+)/+(.-)$")
+ if middle then
+ pth = "//" .. middle
+ else
+ pth = "//" .. last
+ last = ""
+ end
+ else
+ first, middle, last = match(str,"^([a-zA-Z]:)(/*)(.-)$")
+ if first then
+ pth, drive = first .. middle, true
+ else
+ middle, last = match(str,"^(/*)(.-)$")
+ if not middle then
+ last = str
+ end
+ end
+ end
+ end
+ for s in gmatch(last,"[^/]+") do
+ if pth == "" then
+ pth = s
+ elseif drive then
+ pth, drive = pth .. s, false
+ else
+ pth = pth .. "/" .. s
+ end
+ if make_indeed and not lfs.isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ return pth, (lfs.isdir(pth) == true)
+ end
+
+--~ print(dir.mkdirs("","","a","c"))
+--~ print(dir.mkdirs("a"))
+--~ print(dir.mkdirs("a:"))
+--~ print(dir.mkdirs("a:/b/c"))
+--~ print(dir.mkdirs("a:b/c"))
+--~ print(dir.mkdirs("a:/bbb/c"))
+--~ print(dir.mkdirs("/a/b/c"))
+--~ print(dir.mkdirs("/aaa/b/c"))
+--~ print(dir.mkdirs("//a/b/c"))
+--~ print(dir.mkdirs("///a/b/c"))
+--~ print(dir.mkdirs("a/bbb//ccc/"))
+
+ function dir.expand_name(str) -- will be merged with cleanpath and collapsepath
+ local first, nothing, last = match(str,"^(//)(//*)(.*)$")
+ if first then
+ first = dir.current() .. "/"
+ end
+ if not first then
+ first, last = match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first, last = match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d = lfs.currentdir()
+ if lfs.chdir(first) then
+ first = dir.current()
+ end
+ lfs.chdir(d)
+ end
+ end
+ if not first then
+ first, last = dir.current(), str
+ end
+ last = gsub(last,"//","/")
+ last = gsub(last,"/%./","/")
+ last = gsub(last,"^/*","")
+ first = gsub(first,"/*$","")
+ if last == "" then
+ return first
+ else
+ return first .. "/" .. last
+ end
+ end
+
+else
+
+ function dir.mkdirs(...)
+ local str, pth, t = "", "", { ... }
+ for i=1,#t do
+ local s = t[i]
+ if s ~= "" then
+ if str ~= "" then
+ str = str .. "/" .. s
+ else
+ str = s
+ end
+ end
+ end
+ str = gsub(str,"/+","/")
+ if find(str,"^/") then
+ pth = "/"
+ for s in gmatch(str,"[^/]+") do
+ local first = (pth == "/")
+ if first then
+ pth = pth .. s
+ else
+ pth = pth .. "/" .. s
+ end
+ if make_indeed and not first and not lfs.isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ else
+ pth = "."
+ for s in gmatch(str,"[^/]+") do
+ pth = pth .. "/" .. s
+ if make_indeed and not lfs.isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ end
+ return pth, (lfs.isdir(pth) == true)
+ end
+
+--~ print(dir.mkdirs("","","a","c"))
+--~ print(dir.mkdirs("a"))
+--~ print(dir.mkdirs("/a/b/c"))
+--~ print(dir.mkdirs("/aaa/b/c"))
+--~ print(dir.mkdirs("//a/b/c"))
+--~ print(dir.mkdirs("///a/b/c"))
+--~ print(dir.mkdirs("a/bbb//ccc/"))
+
+ function dir.expand_name(str) -- will be merged with cleanpath and collapsepath
+ if not find(str,"^/") then
+ str = lfs.currentdir() .. "/" .. str
+ end
+ str = gsub(str,"//","/")
+ str = gsub(str,"/%./","/")
+ return str
+ end
+
+end
+
+dir.makedirs = dir.mkdirs
diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua
new file mode 100644
index 000000000..2bfc07090
--- /dev/null
+++ b/tex/context/base/l-file.lua
@@ -0,0 +1,314 @@
+if not modules then modules = { } end modules ['l-file'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- needs a cleanup
+
+file = file or { }
+
+local concat = table.concat
+local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char
+local lpegmatch = lpeg.match
+
+function file.removesuffix(filename)
+ return (gsub(filename,"%.[%a%d]+$",""))
+end
+
+function file.addsuffix(filename, suffix)
+ if not suffix or suffix == "" then
+ return filename
+ elseif not find(filename,"%.[%a%d]+$") then
+ return filename .. "." .. suffix
+ else
+ return filename
+ end
+end
+
+function file.replacesuffix(filename, suffix)
+ return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+end
+
+function file.dirname(name,default)
+ return match(name,"^(.+)[/\\].-$") or (default or "")
+end
+
+function file.basename(name)
+ return match(name,"^.+[/\\](.-)$") or name
+end
+
+function file.nameonly(name)
+ return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$",""))
+end
+
+function file.extname(name,default)
+ return match(name,"^.+%.([^/\\]-)$") or default or ""
+end
+
+file.suffix = file.extname
+
+--~ function file.join(...)
+--~ local pth = concat({...},"/")
+--~ pth = gsub(pth,"\\","/")
+--~ local a, b = match(pth,"^(.*://)(.*)$")
+--~ if a and b then
+--~ return a .. gsub(b,"//+","/")
+--~ end
+--~ a, b = match(pth,"^(//)(.*)$")
+--~ if a and b then
+--~ return a .. gsub(b,"//+","/")
+--~ end
+--~ return (gsub(pth,"//+","/"))
+--~ end
+
+local trick_1 = char(1)
+local trick_2 = "^" .. trick_1 .. "/+"
+
+function file.join(...)
+ local lst = { ... }
+ local a, b = lst[1], lst[2]
+ if a == "" then
+ lst[1] = trick_1
+ elseif b and find(a,"^/+$") and find(b,"^/") then
+ lst[1] = ""
+ lst[2] = gsub(b,"^/+","")
+ end
+ local pth = concat(lst,"/")
+ pth = gsub(pth,"\\","/")
+ local a, b = match(pth,"^(.*://)(.*)$")
+ if a and b then
+ return a .. gsub(b,"//+","/")
+ end
+ a, b = match(pth,"^(//)(.*)$")
+ if a and b then
+ return a .. gsub(b,"//+","/")
+ end
+ pth = gsub(pth,trick_2,"")
+ return (gsub(pth,"//+","/"))
+end
+
+--~ print(file.join("//","/y"))
+--~ print(file.join("/","/y"))
+--~ print(file.join("","/y"))
+--~ print(file.join("/x/","/y"))
+--~ print(file.join("x/","/y"))
+--~ print(file.join("http://","/y"))
+--~ print(file.join("http://a","/y"))
+--~ print(file.join("http:///a","/y"))
+--~ print(file.join("//nas-1","/y"))
+
+function file.iswritable(name)
+ local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,"."))
+ return a and sub(a.permissions,2,2) == "w"
+end
+
+function file.isreadable(name)
+ local a = lfs.attributes(name)
+ return a and sub(a.permissions,1,1) == "r"
+end
+
+file.is_readable = file.isreadable
+file.is_writable = file.iswritable
+
+-- todo: lpeg
+
+--~ function file.split_path(str)
+--~ local t = { }
+--~ str = gsub(str,"\\", "/")
+--~ str = gsub(str,"(%a):([;/])", "%1\001%2")
+--~ for name in gmatch(str,"([^;:]+)") do
+--~ if name ~= "" then
+--~ t[#t+1] = gsub(name,"\001",":")
+--~ end
+--~ end
+--~ return t
+--~ end
+
+local checkedsplit = string.checkedsplit
+
+function file.split_path(str,separator)
+ str = gsub(str,"\\","/")
+ return checkedsplit(str,separator or io.pathseparator)
+end
+
+function file.join_path(tab)
+ return concat(tab,io.pathseparator) -- can have trailing //
+end
+
+-- we can hash them weakly
+
+function file.collapse_path(str)
+ str = gsub(str,"\\","/")
+ if find(str,"/") then
+ str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified
+ str = gsub(str,"/%./","/")
+ local n, m = 1, 1
+ while n > 0 or m > 0 do
+ str, n = gsub(str,"[^/%.]+/%.%.$","")
+ str, m = gsub(str,"[^/%.]+/%.%./","")
+ end
+ str = gsub(str,"([^/])/$","%1")
+ -- str = gsub(str,"^%./","") -- ./xx in qualified
+ str = gsub(str,"/%.$","")
+ end
+ if str == "" then str = "." end
+ return str
+end
+
+--~ print(file.collapse_path("/a"))
+--~ print(file.collapse_path("a/./b/.."))
+--~ print(file.collapse_path("a/aa/../b/bb"))
+--~ print(file.collapse_path("a/../.."))
+--~ print(file.collapse_path("a/.././././b/.."))
+--~ print(file.collapse_path("a/./././b/.."))
+--~ print(file.collapse_path("a/b/c/../.."))
+
+function file.robustname(str)
+ return (gsub(str,"[^%a%d%/%-%.\\]+","-"))
+end
+
+file.readdata = io.loaddata
+file.savedata = io.savedata
+
+function file.copy(oldname,newname)
+ file.savedata(newname,io.loaddata(oldname))
+end
+
+-- lpeg variants, slightly faster, not always
+
+--~ local period = lpeg.P(".")
+--~ local slashes = lpeg.S("\\/")
+--~ local noperiod = 1-period
+--~ local noslashes = 1-slashes
+--~ local name = noperiod^1
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.C(noperiod^1) * -1
+
+--~ function file.extname(name)
+--~ return lpegmatch(pattern,name) or ""
+--~ end
+
+--~ local pattern = lpeg.Cs(((period * noperiod^1 * -1)/"" + 1)^1)
+
+--~ function file.removesuffix(name)
+--~ return lpegmatch(pattern,name)
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^1 * lpeg.C(noslashes^1) * -1
+
+--~ function file.basename(name)
+--~ return lpegmatch(pattern,name) or name
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^1 * lpeg.Cp() * noslashes^1 * -1
+
+--~ function file.dirname(name)
+--~ local p = lpegmatch(pattern,name)
+--~ if p then
+--~ return sub(name,1,p-2)
+--~ else
+--~ return ""
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1
+
+--~ function file.addsuffix(name, suffix)
+--~ local p = lpegmatch(pattern,name)
+--~ if p then
+--~ return name
+--~ else
+--~ return name .. "." .. suffix
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1
+
+--~ function file.replacesuffix(name,suffix)
+--~ local p = lpegmatch(pattern,name)
+--~ if p then
+--~ return sub(name,1,p-2) .. "." .. suffix
+--~ else
+--~ return name .. "." .. suffix
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * lpeg.Cp() * ((noperiod^1 * period)^1 * lpeg.Cp() + lpeg.P(true)) * noperiod^1 * -1
+
+--~ function file.nameonly(name)
+--~ local a, b = lpegmatch(pattern,name)
+--~ if b then
+--~ return sub(name,a,b-2)
+--~ elseif a then
+--~ return sub(name,a)
+--~ else
+--~ return name
+--~ end
+--~ end
+
+--~ local test = file.extname
+--~ local test = file.basename
+--~ local test = file.dirname
+--~ local test = file.addsuffix
+--~ local test = file.replacesuffix
+--~ local test = file.nameonly
+
+--~ print(1,test("./a/b/c/abd.def.xxx","!!!"))
+--~ print(2,test("./../b/c/abd.def.xxx","!!!"))
+--~ print(3,test("a/b/c/abd.def.xxx","!!!"))
+--~ print(4,test("a/b/c/def.xxx","!!!"))
+--~ print(5,test("a/b/c/def","!!!"))
+--~ print(6,test("def","!!!"))
+--~ print(7,test("def.xxx","!!!"))
+
+--~ local tim = os.clock() for i=1,250000 do local ext = test("abd.def.xxx","!!!") end print(os.clock()-tim)
+
+-- also rewrite previous
+
+local letter = lpeg.R("az","AZ") + lpeg.S("_-+")
+local separator = lpeg.P("://")
+
+local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator + letter^1 * lpeg.P("/")
+local rootbased = lpeg.P("/") + letter*lpeg.P(":")
+
+-- ./name ../name /name c: :// name/name
+
+function file.is_qualified_path(filename)
+ return lpegmatch(qualified,filename) ~= nil
+end
+
+function file.is_rootbased_path(filename)
+ return lpegmatch(rootbased,filename) ~= nil
+end
+
+local slash = lpeg.S("\\/")
+local period = lpeg.P(".")
+local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":")
+local path = lpeg.C(((1-slash)^0 * slash)^0)
+local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1))
+local base = lpeg.C((1-suffix)^0)
+
+local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc(""))
+
+function file.splitname(str) -- returns drive, path, base, suffix
+ return lpegmatch(pattern,str)
+end
+
+-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
+--
+-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
+-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
+-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
+-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
+
+--~ -- todo:
+--~
+--~ if os.type == "windows" then
+--~ local currentdir = lfs.currentdir
+--~ function lfs.currentdir()
+--~ return (gsub(currentdir(),"\\","/"))
+--~ end
+--~ end
diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua
new file mode 100644
index 000000000..66e279309
--- /dev/null
+++ b/tex/context/base/l-io.lua
@@ -0,0 +1,187 @@
+if not modules then modules = { } end modules ['l-io'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local byte, find, gsub = string.byte, string.find, string.gsub
+
+if string.find(os.getenv("PATH"),";") then
+ io.fileseparator, io.pathseparator = "\\", ";"
+else
+ io.fileseparator, io.pathseparator = "/" , ":"
+end
+
+function io.loaddata(filename,textmode)
+ local f = io.open(filename,(textmode and 'r') or 'rb')
+ if f then
+ -- collectgarbage("step") -- sometimes makes a big difference in mem consumption
+ local data = f:read('*all')
+ -- garbagecollector.check(data)
+ f:close()
+ return data
+ else
+ return nil
+ end
+end
+
+function io.savedata(filename,data,joiner)
+ local f = io.open(filename,"wb")
+ if f then
+ if type(data) == "table" then
+ f:write(table.join(data,joiner or ""))
+ elseif type(data) == "function" then
+ data(f)
+ else
+ f:write(data or "")
+ end
+ f:close()
+ return true
+ else
+ return false
+ end
+end
+
+function io.exists(filename)
+ local f = io.open(filename)
+ if f == nil then
+ return false
+ else
+ assert(f:close())
+ return true
+ end
+end
+
+function io.size(filename)
+ local f = io.open(filename)
+ if f == nil then
+ return 0
+ else
+ local s = f:seek("end")
+ assert(f:close())
+ return s
+ end
+end
+
+function io.noflines(f)
+ local n = 0
+ for _ in f:lines() do
+ n = n + 1
+ end
+ f:seek('set',0)
+ return n
+end
+
+local nextchar = {
+ [ 4] = function(f)
+ return f:read(1,1,1,1)
+ end,
+ [ 2] = function(f)
+ return f:read(1,1)
+ end,
+ [ 1] = function(f)
+ return f:read(1)
+ end,
+ [-2] = function(f)
+ local a, b = f:read(1,1)
+ return b, a
+ end,
+ [-4] = function(f)
+ local a, b, c, d = f:read(1,1,1,1)
+ return d, c, b, a
+ end
+}
+
+function io.characters(f,n)
+ if f then
+ return nextchar[n or 1], f
+ else
+ return nil, nil
+ end
+end
+
+local nextbyte = {
+ [4] = function(f)
+ local a, b, c, d = f:read(1,1,1,1)
+ if d then
+ return byte(a), byte(b), byte(c), byte(d)
+ else
+ return nil, nil, nil, nil
+ end
+ end,
+ [2] = function(f)
+ local a, b = f:read(1,1)
+ if b then
+ return byte(a), byte(b)
+ else
+ return nil, nil
+ end
+ end,
+ [1] = function (f)
+ local a = f:read(1)
+ if a then
+ return byte(a)
+ else
+ return nil
+ end
+ end,
+ [-2] = function (f)
+ local a, b = f:read(1,1)
+ if b then
+ return byte(b), byte(a)
+ else
+ return nil, nil
+ end
+ end,
+ [-4] = function(f)
+ local a, b, c, d = f:read(1,1,1,1)
+ if d then
+ return byte(d), byte(c), byte(b), byte(a)
+ else
+ return nil, nil, nil, nil
+ end
+ end
+}
+
+function io.bytes(f,n)
+ if f then
+ return nextbyte[n or 1], f
+ else
+ return nil, nil
+ end
+end
+
+function io.ask(question,default,options)
+ while true do
+ io.write(question)
+ if options then
+ io.write(string.format(" [%s]",table.concat(options,"|")))
+ end
+ if default then
+ io.write(string.format(" [%s]",default))
+ end
+ io.write(string.format(" "))
+ local answer = io.read()
+ answer = gsub(answer,"^%s*(.*)%s*$","%1")
+ if answer == "" and default then
+ return default
+ elseif not options then
+ return answer
+ else
+ for k=1,#options do
+ if options[k] == answer then
+ return answer
+ end
+ end
+ local pattern = "^" .. answer
+ for k=1,#options do
+ local v = options[k]
+ if find(v,pattern) then
+ return v
+ end
+ end
+ end
+ end
+end
diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua
new file mode 100644
index 000000000..b107a8e64
--- /dev/null
+++ b/tex/context/base/l-lpeg.lua
@@ -0,0 +1,165 @@
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpeg = require("lpeg")
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, Ct, C, Cs, Cc, V = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.V
+local match = lpeg.match
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local utf8byte = R("\128\191")
+
+patterns.utf8byte = utf8byte
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8byte
+patterns.utf8three = R("\224\239") * utf8byte * utf8byte
+patterns.utf8four = R("\240\244") * utf8byte * utf8byte * utf8byte
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = S(" ")
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = crlf + cr + lf
+patterns.nonspace = 1 - patterns.space
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+local spacing = patterns.spacer^0 * patterns.newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+local capture = Ct(content^0)
+
+function string:splitlines()
+ return match(capture,self)
+end
+
+patterns.textline = content
+
+--~ local p = lpeg.splitat("->",false) print(match(p,"oeps->what->more")) -- oeps what more
+--~ local p = lpeg.splitat("->",true) print(match(p,"oeps->what->more")) -- oeps what->more
+--~ local p = lpeg.splitat("->",false) print(match(p,"oeps")) -- oeps
+--~ local p = lpeg.splitat("->",true) print(match(p,"oeps")) -- oeps
+
+local splitters_s, splitters_m = { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ if single then
+ local other, any = C((1 - separator)^0), P(1)
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ local other = C((1 - separator)^0)
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = Ct(splitat(separator))
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string:split(separator)
+ local c = cache[separator]
+ if not c then
+ c = Ct(splitat(separator))
+ cache[separator] = c
+ end
+ return match(c,self)
+end
+
+lpeg.splitters = cache
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string:checkedsplit(separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,self)
+end
+
+--~ function lpeg.append(list,pp)
+--~ local p = pp
+--~ for l=1,#list do
+--~ if p then
+--~ p = p + P(list[l])
+--~ else
+--~ p = P(list[l])
+--~ end
+--~ end
+--~ return p
+--~ end
+
+--~ from roberto's site:
+
+local f1 = string.byte
+
+local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
diff --git a/tex/context/base/l-math.lua b/tex/context/base/l-math.lua
new file mode 100644
index 000000000..fc8db4721
--- /dev/null
+++ b/tex/context/base/l-math.lua
@@ -0,0 +1,41 @@
+if not modules then modules = { } end modules ['l-math'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
+
+if not math.round then
+ function math.round(x)
+ return floor(x + 0.5)
+ end
+end
+
+if not math.div then
+ function math.div(n,m)
+ return floor(n/m)
+ end
+end
+
+if not math.mod then
+ function math.mod(n,m)
+ return n % m
+ end
+end
+
+local pipi = 2*math.pi/360
+
+function math.sind(d)
+ return sin(d*pipi)
+end
+
+function math.cosd(d)
+ return cos(d*pipi)
+end
+
+function math.tand(d)
+ return tan(d*pipi)
+end
diff --git a/tex/context/base/l-md5.lua b/tex/context/base/l-md5.lua
new file mode 100644
index 000000000..27955ef9b
--- /dev/null
+++ b/tex/context/base/l-md5.lua
@@ -0,0 +1,72 @@
+if not modules then modules = { } end modules ['l-md5'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This also provides file checksums and checkers.
+
+local gsub, format, byte = string.gsub, string.format, string.byte
+
+local function convert(str,fmt)
+ return (gsub(md5.sum(str),".",function(chr) return format(fmt,byte(chr)) end))
+end
+
+if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
+if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
+if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+
+--~ if not md5.HEX then
+--~ local function remap(chr) return format("%02X",byte(chr)) end
+--~ function md5.HEX(str) return (gsub(md5.sum(str),".",remap)) end
+--~ end
+--~ if not md5.hex then
+--~ local function remap(chr) return format("%02x",byte(chr)) end
+--~ function md5.hex(str) return (gsub(md5.sum(str),".",remap)) end
+--~ end
+--~ if not md5.dec then
+--~ local function remap(chr) return format("%03i",byte(chr)) end
+--~ function md5.dec(str) return (gsub(md5.sum(str),".",remap)) end
+--~ end
+
+file.needs_updating_threshold = 1
+
+function file.needs_updating(oldname,newname) -- size modification access change
+ local oldtime = lfs.attributes(oldname, modification)
+ local newtime = lfs.attributes(newname, modification)
+ if newtime >= oldtime then
+ return false
+ elseif oldtime - newtime < file.needs_updating_threshold then
+ return false
+ else
+ return true
+ end
+end
+
+function file.checksum(name)
+ if md5 then
+ local data = io.loaddata(name)
+ if data then
+ return md5.HEX(data)
+ end
+ end
+ return nil
+end
+
+function file.loadchecksum(name)
+ if md5 then
+ local data = io.loaddata(name .. ".md5")
+ return data and (gsub(data,"%s",""))
+ end
+ return nil
+end
+
+function file.savechecksum(name, checksum)
+ if not checksum then checksum = file.checksum(name) end
+ if checksum then
+ io.savedata(name .. ".md5",checksum)
+ return checksum
+ end
+ return nil
+end
diff --git a/tex/context/base/l-number.lua b/tex/context/base/l-number.lua
new file mode 100644
index 000000000..a1249f055
--- /dev/null
+++ b/tex/context/base/l-number.lua
@@ -0,0 +1,58 @@
+if not modules then modules = { } end modules ['l-number'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tostring = tostring
+local format, floor, insert, match = string.format, math.floor, table.insert, string.match
+local lpegmatch = lpeg.match
+
+number = number or { }
+
+-- a,b,c,d,e,f = number.toset(100101)
+
+function number.toset(n)
+ return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+end
+
+function number.toevenhex(n)
+ local s = format("%X",n)
+ if #s % 2 == 0 then
+ return s
+ else
+ return "0" .. s
+ end
+end
+
+-- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
+-- on
+--
+-- for i=1,1000000 do
+-- local a,b,c,d,e,f,g,h = number.toset(12345678)
+-- local a,b,c,d = number.toset(1234)
+-- local a,b,c = number.toset(123)
+-- end
+--
+-- of course dedicated "(.)(.)(.)(.)" matches are even faster
+
+local one = lpeg.C(1-lpeg.S(''))^1
+
+function number.toset(n)
+ return lpegmatch(one,tostring(n))
+end
+
+function number.bits(n,zero)
+ local t, i = { }, (zero and 0) or 1
+ while n > 0 do
+ local m = n % 2
+ if m > 0 then
+ insert(t,1,i)
+ end
+ n = floor(n/2)
+ i = i + 1
+ end
+ return t
+end
diff --git a/tex/context/base/l-os.lua b/tex/context/base/l-os.lua
new file mode 100644
index 000000000..fba2cd317
--- /dev/null
+++ b/tex/context/base/l-os.lua
@@ -0,0 +1,301 @@
+if not modules then modules = { } end modules ['l-os'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- maybe build io.flush in os.execute
+
+local find, format, gsub = string.find, string.format, string.gsub
+local random, ceil = math.random, math.ceil
+
+local execute, spawn, exec, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.flush
+
+function os.execute(...) ioflush() return execute(...) end
+function os.spawn (...) ioflush() return spawn (...) end
+function os.exec (...) ioflush() return exec (...) end
+
+function os.resultof(command)
+ ioflush() -- else messed up logging
+ local handle = io.popen(command,"r")
+ if not handle then
+ -- print("unknown command '".. command .. "' in os.resultof")
+ return ""
+ else
+ return handle:read("*all") or ""
+ end
+end
+
+--~ os.type : windows | unix (new, we already guessed os.platform)
+--~ os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
+--~ os.platform : extended os.name with architecture
+
+if not io.fileseparator then
+ if find(os.getenv("PATH"),";") then
+ io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin"
+ else
+ io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix"
+ end
+end
+
+os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
+os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
+
+if os.type == "windows" then
+ os.libsuffix, os.binsuffix = 'dll', 'exe'
+else
+ os.libsuffix, os.binsuffix = 'so', ''
+end
+
+function os.launch(str)
+ if os.type == "windows" then
+ os.execute("start " .. str) -- os.spawn ?
+ else
+ os.execute(str .. " &") -- os.spawn ?
+ end
+end
+
+if not os.times then
+ -- utime = user time
+ -- stime = system time
+ -- cutime = children user time
+ -- cstime = children system time
+ function os.times()
+ return {
+ utime = os.gettimeofday(), -- user
+ stime = 0, -- system
+ cutime = 0, -- children user
+ cstime = 0, -- children system
+ }
+ end
+end
+
+os.gettimeofday = os.gettimeofday or os.clock
+
+local startuptime = os.gettimeofday()
+
+function os.runtime()
+ return os.gettimeofday() - startuptime
+end
+
+--~ print(os.gettimeofday()-os.time())
+--~ os.sleep(1.234)
+--~ print (">>",os.runtime())
+--~ print(os.date("%H:%M:%S",os.gettimeofday()))
+--~ print(os.date("%H:%M:%S",os.time()))
+
+-- no need for function anymore as we have more clever code and helpers now
+-- this metatable trickery might as well disappear
+
+os.resolvers = os.resolvers or { }
+
+local resolvers = os.resolvers
+
+local osmt = getmetatable(os) or { __index = function(t,k) t[k] = "unset" return "unset" end } -- maybe nil
+local osix = osmt.__index
+
+osmt.__index = function(t,k)
+ return (resolvers[k] or osix)(t,k)
+end
+
+setmetatable(os,osmt)
+
+if not os.setenv then
+
+ -- we still store them but they won't be seen in
+ -- child processes although we might pass them some day
+ -- using command concatination
+
+ local env, getenv = { }, os.getenv
+
+ function os.setenv(k,v)
+ env[k] = v
+ end
+
+ function os.getenv(k)
+ return env[k] or getenv(k)
+ end
+
+end
+
+-- we can use HOSTTYPE on some platforms
+
+local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
+
+local function guess()
+ local architecture = os.resultof("uname -m") or ""
+ if architecture ~= "" then
+ return architecture
+ end
+ architecture = os.getenv("HOSTTYPE") or ""
+ if architecture ~= "" then
+ return architecture
+ end
+ return os.resultof("echo $HOSTTYPE") or ""
+end
+
+if platform ~= "" then
+
+ os.platform = platform
+
+elseif os.type == "windows" then
+
+ -- we could set the variable directly, no function needed here
+
+ function os.resolvers.platform(t,k)
+ local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ if find(architecture,"AMD64") then
+ platform = "mswin-64"
+ else
+ platform = "mswin"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "linux" then
+
+ function os.resolvers.platform(t,k)
+ -- we sometims have HOSTTYPE set so let's check that first
+ local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform = "linux-64"
+ elseif find(architecture,"ppc") then
+ platform = "linux-ppc"
+ else
+ platform = "linux"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "macosx" then
+
+ --[[
+ Identifying the architecture of OSX is quite a mess and this
+ is the best we can come up with. For some reason $HOSTTYPE is
+ a kind of pseudo environment variable, not known to the current
+ environment. And yes, uname cannot be trusted either, so there
+ is a change that you end up with a 32 bit run on a 64 bit system.
+ Also, some proper 64 bit intel macs are too cheap (low-end) and
+ therefore not permitted to run the 64 bit kernel.
+ ]]--
+
+ function os.resolvers.platform(t,k)
+ -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
+ -- if architecture == "" then
+ -- architecture = os.resultof("echo $HOSTTYPE") or ""
+ -- end
+ local platform, architecture = "", os.resultof("echo $HOSTTYPE") or ""
+ if architecture == "" then
+ -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
+ platform = "osx-intel"
+ elseif find(architecture,"i386") then
+ platform = "osx-intel"
+ elseif find(architecture,"x86_64") then
+ platform = "osx-64"
+ else
+ platform = "osx-ppc"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "sunos" then
+
+ function os.resolvers.platform(t,k)
+ local platform, architecture = "", os.resultof("uname -m") or ""
+ if find(architecture,"sparc") then
+ platform = "solaris-sparc"
+ else -- if architecture == 'i86pc'
+ platform = "solaris-intel"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "freebsd" then
+
+ function os.resolvers.platform(t,k)
+ local platform, architecture = "", os.resultof("uname -m") or ""
+ if find(architecture,"amd64") then
+ platform = "freebsd-amd64"
+ else
+ platform = "freebsd"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+elseif name == "kfreebsd" then
+
+ function os.resolvers.platform(t,k)
+ -- we sometims have HOSTTYPE set so let's check that first
+ local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform = "kfreebsd-64"
+ else
+ platform = "kfreebsd-i386"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+else
+
+ -- platform = "linux"
+ -- os.setenv("MTX_PLATFORM",platform)
+ -- os.platform = platform
+
+ function os.resolvers.platform(t,k)
+ local platform = "linux"
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform = platform
+ return platform
+ end
+
+end
+
+-- beware, we set the randomseed
+
+-- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the
+-- version number as well as two reserved bits. All other bits are set using a random or pseudorandom
+-- data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal
+-- digits x and hexadecimal digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479.
+--
+-- as we don't call this function too often there is not so much risk on repetition
+
+local t = { 8, 9, "a", "b" }
+
+function os.uuid()
+ return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
+ random(0xFFFF),random(0xFFFF),
+ random(0x0FFF),
+ t[ceil(random(4))] or 8,random(0x0FFF),
+ random(0xFFFF),
+ random(0xFFFF),random(0xFFFF),random(0xFFFF)
+ )
+end
+
+local d
+
+function os.timezone(delta)
+ d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
+ if delta then
+ if d > 0 then
+ return format("+%02i:00",d)
+ else
+ return format("-%02i:00",-d)
+ end
+ else
+ return 1
+ end
+end
diff --git a/tex/context/base/l-pdfview.lua b/tex/context/base/l-pdfview.lua
new file mode 100644
index 000000000..627477ee8
--- /dev/null
+++ b/tex/context/base/l-pdfview.lua
@@ -0,0 +1,95 @@
+if not modules then modules = { } end modules ['l-pdfview'] = {
+ version = 1.001,
+ comment = "companion to mtx-context.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, getenv = string.format, os.getenv
+
+pdfview = pdfview or { }
+
+local opencalls = {
+ ['default'] = "pdfopen --file", -- "pdfopen --back --file"
+ ['xpdf'] = "xpdfopen",
+}
+
+local closecalls= {
+ ['default'] = "pdfclose --file",
+ ['xpdf'] = nil,
+}
+
+local allcalls = {
+ ['default'] = "pdfclose --all",
+ ['xpdf'] = nil,
+}
+
+if os.type == "windows" then
+ opencalls['okular'] = 'start "test" "c:/program files/kde/bin/okular.exe" --unique' -- todo: get focus
+else
+ opencalls['okular'] = 'okular --unique'
+end
+
+pdfview.METHOD = "MTX_PDFVIEW_METHOD"
+pdfview.method = getenv(pdfview.METHOD) or 'default'
+pdfview.method = (opencalls[pdfview.method] and pdfview.method) or 'default'
+
+function pdfview.methods()
+ return table.concat(table.sortedkeys(opencalls), " ")
+end
+
+function pdfview.status()
+ return format("pdfview methods: %s, current method: %s, MTX_PDFVIEW_METHOD=%s",pdfview.methods(),pdfview.method,getenv(pdfview.METHOD) or "")
+end
+
+local openedfiles = { }
+
+local function fullname(name)
+ return file.addsuffix(name,"pdf")
+end
+
+function pdfview.open(...)
+ local opencall = opencalls[pdfview.method]
+ if opencall then
+ local t = { ... }
+ for i=1,#t do
+ local name = fullname(t[i])
+ if io.exists(name) then
+ os.execute(format('%s "%s" 2>&1', opencall, name))
+ openedfiles[name] = true
+ end
+ end
+ end
+end
+
+function pdfview.close(...)
+ local closecall = closecalls[pdfview.method]
+ if closecall then
+ local t = { ... }
+ for i=1,#t do
+ local name = fullname(t[i])
+ if openedfiles[name] then
+ os.execute(format('%s "%s" 2>&1', closecall, name))
+ openedfiles[name] = nil
+ else
+ pdfview.closeall()
+ break
+ end
+ end
+ end
+end
+
+function pdfview.closeall()
+ local allcall = allcalls[pdfview.method]
+ if allcall then
+ os.execute(format('%s 2>&1', allcall))
+ end
+ openedfiles = { }
+end
+
+--~ pdfview.open("t:/document/show-exa.pdf")
+--~ os.sleep(3)
+--~ pdfview.close("t:/document/show-exa.pdf")
+
+return pdfview
diff --git a/tex/context/base/l-set.lua b/tex/context/base/l-set.lua
new file mode 100644
index 000000000..f844d0b40
--- /dev/null
+++ b/tex/context/base/l-set.lua
@@ -0,0 +1,84 @@
+if not modules then modules = { } end modules ['l-set'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+set = set or { }
+
+local nums = { }
+local tabs = { }
+local concat = table.concat
+local next, type = next, type
+
+set.create = table.tohash
+
+function set.tonumber(t)
+ if next(t) then
+ local s = ""
+ -- we could save mem by sorting, but it slows down
+ for k, v in next, t do
+ if v then
+ -- why bother about the leading space
+ s = s .. " " .. k
+ end
+ end
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
+ end
+ return n
+ else
+ return 0
+ end
+end
+
+function set.totable(n)
+ if n == 0 then
+ return { }
+ else
+ return tabs[n] or { }
+ end
+end
+
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t = { }
+ for k, v in next, tabs[n] do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
+function set.contains(n,s)
+ if type(n) == "table" then
+ return n[s]
+ elseif n == 0 then
+ return false
+ else
+ local t = tabs[n]
+ return t and t[s]
+ end
+end
+
+--~ local c = set.create{'aap','noot','mies'}
+--~ local s = set.tonumber(c)
+--~ local t = set.totable(s)
+--~ print(t['aap'])
+--~ local c = set.create{'zus','wim','jet'}
+--~ local s = set.tonumber(c)
+--~ local t = set.totable(s)
+--~ print(t['aap'])
+--~ print(t['jet'])
+--~ print(set.contains(t,'jet'))
+--~ print(set.contains(t,'aap'))
+
diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua
new file mode 100644
index 000000000..9856d5212
--- /dev/null
+++ b/tex/context/base/l-string.lua
@@ -0,0 +1,288 @@
+if not modules then modules = { } end modules ['l-string'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
+local lpegmatch = lpeg.match
+
+-- some functions may disappear as they are not used anywhere
+
+if not string.split then
+
+ -- this will be overloaded by a faster lpeg variant
+
+ function string:split(pattern)
+ if #self > 0 then
+ local t = { }
+ for s in gmatch(self..pattern,"(.-)"..pattern) do
+ t[#t+1] = s
+ end
+ return t
+ else
+ return { }
+ end
+ end
+
+end
+
+local chr_to_esc = {
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["^"] = "%^", ["$"] = "%$",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%(", [")"] = "%)",
+ ["{"] = "%{", ["}"] = "%}"
+}
+
+string.chr_to_esc = chr_to_esc
+
+function string:esc() -- variant 2
+ return (gsub(self,"(.)",chr_to_esc))
+end
+
+function string:unquote()
+ return (gsub(self,"^([\"\'])(.*)%1$","%2"))
+end
+
+--~ function string:unquote()
+--~ if find(self,"^[\'\"]") then
+--~ return sub(self,2,-2)
+--~ else
+--~ return self
+--~ end
+--~ end
+
+function string:quote() -- we could use format("%q")
+ return format("%q",self)
+end
+
+function string:count(pattern) -- variant 3
+ local n = 0
+ for _ in gmatch(self,pattern) do
+ n = n + 1
+ end
+ return n
+end
+
+function string:limit(n,sentinel)
+ if #self > n then
+ sentinel = sentinel or " ..."
+ return sub(self,1,(n-#sentinel)) .. sentinel
+ else
+ return self
+ end
+end
+
+--~ function string:strip() -- the .- is quite efficient
+--~ -- return match(self,"^%s*(.-)%s*$") or ""
+--~ -- return match(self,'^%s*(.*%S)') or '' -- posted on lua list
+--~ return find(s,'^%s*$') and '' or match(s,'^%s*(.*%S)')
+--~ end
+
+do -- roberto's variant:
+ local space = lpeg.S(" \t\v\n")
+ local nospace = 1 - space
+ local stripper = space^0 * lpeg.C((space^0 * nospace^1)^0)
+ function string.strip(str)
+ return lpegmatch(stripper,str) or ""
+ end
+end
+
+function string:is_empty()
+ return not find(self,"%S")
+end
+
+function string:enhance(pattern,action)
+ local ok, n = true, 0
+ while ok do
+ ok = false
+ self = gsub(self,pattern, function(...)
+ ok, n = true, n + 1
+ return action(...)
+ end)
+ end
+ return self, n
+end
+
+local chr_to_hex, hex_to_chr = { }, { }
+
+for i=0,255 do
+ local c, h = char(i), format("%02X",i)
+ chr_to_hex[c], hex_to_chr[h] = h, c
+end
+
+function string:to_hex()
+ return (gsub(self or "","(.)",chr_to_hex))
+end
+
+function string:from_hex()
+ return (gsub(self or "","(..)",hex_to_chr))
+end
+
+if not string.characters then
+
+ local function nextchar(str, index)
+ index = index + 1
+ return (index <= #str) and index or nil, sub(str,index,index)
+ end
+ function string:characters()
+ return nextchar, self, 0
+ end
+ local function nextbyte(str, index)
+ index = index + 1
+ return (index <= #str) and index or nil, byte(sub(str,index,index))
+ end
+ function string:bytes()
+ return nextbyte, self, 0
+ end
+
+end
+
+-- we can use format for this (neg n)
+
+function string:rpadd(n,chr)
+ local m = n-#self
+ if m > 0 then
+ return self .. rep(chr or " ",m)
+ else
+ return self
+ end
+end
+
+function string:lpadd(n,chr)
+ local m = n-#self
+ if m > 0 then
+ return rep(chr or " ",m) .. self
+ else
+ return self
+ end
+end
+
+string.padd = string.rpadd
+
+function is_number(str) -- tonumber
+ return find(str,"^[%-%+]?[%d]-%.?[%d+]$") == 1
+end
+
+--~ print(is_number("1"))
+--~ print(is_number("1.1"))
+--~ print(is_number(".1"))
+--~ print(is_number("-0.1"))
+--~ print(is_number("+0.1"))
+--~ print(is_number("-.1"))
+--~ print(is_number("+.1"))
+
+function string:split_settings() -- no {} handling, see l-aux for lpeg variant
+ if find(self,"=") then
+ local t = { }
+ for k,v in gmatch(self,"(%a+)=([^%,]*)") do
+ t[k] = v
+ end
+ return t
+ else
+ return nil
+ end
+end
+
+local patterns_escapes = {
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["+"] = "%+",
+ ["*"] = "%*",
+ ["%"] = "%%",
+ ["("] = "%)",
+ [")"] = "%)",
+ ["["] = "%[",
+ ["]"] = "%]",
+}
+
+function string:pattesc()
+ return (gsub(self,".",patterns_escapes))
+end
+
+local simple_escapes = {
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+function string:simpleesc()
+ return (gsub(self,".",simple_escapes))
+end
+
+function string:tohash()
+ local t = { }
+ for s in gmatch(self,"([^, ]+)") do -- lpeg
+ t[s] = true
+ end
+ return t
+end
+
+local pattern = lpeg.Ct(lpeg.C(1)^0)
+
+function string:totable()
+ return lpegmatch(pattern,self)
+end
+
+--~ local t = {
+--~ "1234567123456712345671234567",
+--~ "a\tb\tc",
+--~ "aa\tbb\tcc",
+--~ "aaa\tbbb\tccc",
+--~ "aaaa\tbbbb\tcccc",
+--~ "aaaaa\tbbbbb\tccccc",
+--~ "aaaaaa\tbbbbbb\tcccccc",
+--~ }
+--~ for k,v do
+--~ print(string.tabtospace(t[k]))
+--~ end
+
+function string.tabtospace(str,tab)
+ -- we don't handle embedded newlines
+ while true do
+ local s = find(str,"\t")
+ if s then
+ if not tab then tab = 7 end -- only when found
+ local d = tab-(s-1) % tab
+ if d > 0 then
+ str = gsub(str,"\t",rep(" ",d),1)
+ else
+ str = gsub(str,"\t","",1)
+ end
+ else
+ break
+ end
+ end
+ return str
+end
+
+function string:compactlong() -- strips newlines and leading spaces
+ self = gsub(self,"[\n\r]+ *","")
+ self = gsub(self,"^ *","")
+ return self
+end
+
+function string:striplong() -- strips newlines and leading spaces
+ self = gsub(self,"^%s*","")
+ self = gsub(self,"[\n\r]+ *","\n")
+ return self
+end
+
+function string:topattern(lowercase,strict)
+ if lowercase then
+ self = lower(self)
+ end
+ self = gsub(self,".",simple_escapes)
+ if self == "" then
+ self = ".*"
+ elseif strict then
+ self = "^" .. self .. "$"
+ end
+ return self
+end
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
new file mode 100644
index 000000000..ee395d0f1
--- /dev/null
+++ b/tex/context/base/l-table.lua
@@ -0,0 +1,910 @@
+if not modules then modules = { } end modules ['l-table'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+table.join = table.concat
+
+local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
+local getmetatable, setmetatable = getmetatable, setmetatable
+local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+
+-- Starting with version 5.2 Lua no longer provide ipairs, which makes
+-- sense. As we already used the for loop and # in most places the
+-- impact on ConTeXt was not that large; the remaining ipairs already
+-- have been replaced. In a similar fashio we also hardly used pairs.
+--
+-- Just in case, we provide the fallbacks as discussed in Programming
+-- in Lua (http://www.lua.org/pil/7.3.html):
+
+if not ipairs then
+
+ -- for k, v in ipairs(t) do ... end
+ -- for k=1,#t do local v = t[k] ... end
+
+ local function iterate(a,i)
+ i = i + 1
+ local v = a[i]
+ if v ~= nil then
+ return i, v --, nil
+ end
+ end
+
+ function ipairs(a)
+ return iterate, a, 0
+ end
+
+end
+
+if not pairs then
+
+ -- for k, v in pairs(t) do ... end
+ -- for k, v in next, t do ... end
+
+ function pairs(t)
+ return next, t -- , nil
+ end
+
+end
+
+-- Also, unpack has been moved to the table table, and for compatiility
+-- reasons we provide both now.
+
+if not table.unpack then
+ table.unpack = _G.unpack
+elseif not unpack then
+ _G.unpack = table.unpack
+end
+
+-- extra functions, some might go (when not used)
+
+function table.strip(tab)
+ local lst = { }
+ for i=1,#tab do
+ local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
+ if s == "" then
+ -- skip this one
+ else
+ lst[#lst+1] = s
+ end
+ end
+ return lst
+end
+
+function table.keys(t)
+ local k = { }
+ for key, _ in next, t do
+ k[#k+1] = key
+ end
+ return k
+end
+
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
+
+local function sortedkeys(tab)
+ local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ for key,_ in next, tab do
+ srt[#srt+1] = key
+ if kind == 3 then
+ -- no further check
+ else
+ local tkey = type(key)
+ if tkey == "string" then
+ -- if kind == 2 then kind = 3 else kind = 1 end
+ kind = (kind == 2 and 3) or 1
+ elseif tkey == "number" then
+ -- if kind == 1 then kind = 3 else kind = 2 end
+ kind = (kind == 1 and 3) or 2
+ else
+ kind = 3
+ end
+ end
+ end
+ if kind == 0 or kind == 3 then
+ sort(srt,compare)
+ else
+ sort(srt)
+ end
+ return srt
+end
+
+local function sortedhashkeys(tab) -- fast one
+ local srt = { }
+ for key,_ in next, tab do
+ srt[#srt+1] = key
+ end
+ sort(srt)
+ return srt
+end
+
+table.sortedkeys = sortedkeys
+table.sortedhashkeys = sortedhashkeys
+
+function table.sortedhash(t)
+ local s = sortedhashkeys(t) -- maybe just sortedkeys
+ local n = 0
+ local function kv(s)
+ n = n + 1
+ local k = s[n]
+ return k, t[k]
+ end
+ return kv, s
+end
+
+table.sortedpairs = table.sortedhash
+
+function table.append(t, list)
+ for _,v in next, list do
+ insert(t,v)
+ end
+end
+
+function table.prepend(t, list)
+ for k,v in next, list do
+ insert(t,k,v)
+ end
+end
+
+function table.merge(t, ...) -- first one is target
+ t = t or {}
+ local lst = {...}
+ for i=1,#lst do
+ for k, v in next, lst[i] do
+ t[k] = v
+ end
+ end
+ return t
+end
+
+function table.merged(...)
+ local tmp, lst = { }, {...}
+ for i=1,#lst do
+ for k, v in next, lst[i] do
+ tmp[k] = v
+ end
+ end
+ return tmp
+end
+
+function table.imerge(t, ...)
+ local lst = {...}
+ for i=1,#lst do
+ local nst = lst[i]
+ for j=1,#nst do
+ t[#t+1] = nst[j]
+ end
+ end
+ return t
+end
+
+function table.imerged(...)
+ local tmp, lst = { }, {...}
+ for i=1,#lst do
+ local nst = lst[i]
+ for j=1,#nst do
+ tmp[#tmp+1] = nst[j]
+ end
+ end
+ return tmp
+end
+
+local function fastcopy(old) -- fast one
+ if old then
+ local new = { }
+ for k,v in next, old do
+ if type(v) == "table" then
+ new[k] = fastcopy(v) -- was just table.copy
+ else
+ new[k] = v
+ end
+ end
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
+ end
+end
+
+local function copy(t, tables) -- taken from lua wiki, slightly adapted
+ tables = tables or { }
+ local tcopy = {}
+ if not tables[t] then
+ tables[t] = tcopy
+ end
+ for i,v in next, t do -- brrr, what happens with sparse indexed
+ if type(i) == "table" then
+ if tables[i] then
+ i = tables[i]
+ else
+ i = copy(i, tables)
+ end
+ end
+ if type(v) ~= "table" then
+ tcopy[i] = v
+ elseif tables[v] then
+ tcopy[i] = tables[v]
+ else
+ tcopy[i] = copy(v, tables)
+ end
+ end
+ local mt = getmetatable(t)
+ if mt then
+ setmetatable(tcopy,mt)
+ end
+ return tcopy
+end
+
+table.fastcopy = fastcopy
+table.copy = copy
+
+-- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
+
+function table.sub(t,i,j)
+ return { unpack(t,i,j) }
+end
+
+function table.replace(a,b)
+ for k,v in next, b do
+ a[k] = v
+ end
+end
+
+-- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice)
+
+function table.is_empty(t) -- obolete, use inline code instead
+ return not t or not next(t)
+end
+
+function table.one_entry(t) -- obolete, use inline code instead
+ local n = next(t)
+ return n and not next(t,n)
+end
+
+--~ function table.starts_at(t) -- obsolete, not nice anyway
+--~ return ipairs(t,1)(t,0)
+--~ end
+
+function table.tohash(t,value)
+ local h = { }
+ if t then
+ if value == nil then value = true end
+ for _, v in next, t do -- no ipairs here
+ h[v] = value
+ end
+ end
+ return h
+end
+
+function table.fromhash(t)
+ local h = { }
+ for k, v in next, t do -- no ipairs here
+ if v then h[#h+1] = k end
+ end
+ return h
+end
+
+--~ print(table.serialize(t), "\n")
+--~ print(table.serialize(t,"name"), "\n")
+--~ print(table.serialize(t,false), "\n")
+--~ print(table.serialize(t,true), "\n")
+--~ print(table.serialize(t,"name",true), "\n")
+--~ print(table.serialize(t,"name",true,true), "\n")
+
+table.serialize_functions = true
+table.serialize_compact = true
+table.serialize_inline = true
+
+local noquotes, hexify, handle, reduce, compact, inline, functions
+
+local reserved = table.tohash { -- intercept a language flaw, no reserved words as key
+ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
+ 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
+}
+
+local function simple_table(t)
+ if #t > 0 then
+ local n = 0
+ for _,v in next, t do
+ n = n + 1
+ end
+ if n == #t then
+ local tt = { }
+ for i=1,#t do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ if hexify then
+ tt[#tt+1] = format("0x%04X",v)
+ else
+ tt[#tt+1] = tostring(v) -- tostring not needed
+ end
+ elseif tv == "boolean" then
+ tt[#tt+1] = tostring(v)
+ elseif tv == "string" then
+ tt[#tt+1] = format("%q",v)
+ else
+ tt = nil
+ break
+ end
+ end
+ return tt
+ end
+ end
+ return nil
+end
+
+-- Because this is a core function of mkiv I moved some function calls
+-- inline.
+--
+-- twice as fast in a test:
+--
+-- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) )
+
+-- problem: there no good number_to_string converter with the best resolution
+
+local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
+ depth = depth .. " "
+ if indexed then
+ handle(format("%s{",depth))
+ elseif name then
+ --~ handle(format("%s%s={",depth,key(name)))
+ if type(name) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s[0x%04X]={",depth,name))
+ else
+ handle(format("%s[%s]={",depth,name))
+ end
+ elseif noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
+ handle(format("%s%s={",depth,name))
+ else
+ handle(format("%s[%q]={",depth,name))
+ end
+ else
+ handle(format("%s{",depth))
+ end
+ end
+ -- we could check for k (index) being number (cardinal)
+ if root and next(root) then
+ local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ if compact then
+ -- NOT: for k=1,#root do (we need to quit at nil)
+ for k,v in ipairs(root) do -- can we use next?
+ if not first then first = k end
+ last = last + 1
+ end
+ end
+ local sk = sortedkeys(root)
+ for i=1,#sk do
+ local k = sk[i]
+ local v = root[k]
+ --~ if v == root then
+ -- circular
+ --~ else
+ local t = type(v)
+ if compact and first and type(k) == "number" and k >= first and k <= last then
+ if t == "number" then
+ if hexify then
+ handle(format("%s 0x%04X,",depth,v))
+ else
+ handle(format("%s %s,",depth,v)) -- %.99g
+ end
+ elseif t == "string" then
+ if reduce and tonumber(v) then
+ handle(format("%s %s,",depth,v))
+ else
+ handle(format("%s %q,",depth,v))
+ end
+ elseif t == "table" then
+ if not next(v) then
+ handle(format("%s {},",depth))
+ elseif inline then -- and #t > 0
+ local st = simple_table(v)
+ if st then
+ handle(format("%s { %s },",depth,concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ elseif t == "boolean" then
+ handle(format("%s %s,",depth,tostring(v)))
+ elseif t == "function" then
+ if functions then
+ handle(format('%s loadstring(%q),',depth,dump(v)))
+ else
+ handle(format('%s "function",',depth))
+ end
+ else
+ handle(format("%s %q,",depth,tostring(v)))
+ end
+ elseif k == "__p__" then -- parent
+ if false then
+ handle(format("%s __p__=nil,",depth))
+ end
+ elseif t == "number" then
+ --~ if hexify then
+ --~ handle(format("%s %s=0x%04X,",depth,key(k),v))
+ --~ else
+ --~ handle(format("%s %s=%s,",depth,key(k),v)) -- %.99g
+ --~ end
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ if hexify then
+ handle(format("%s %s=0x%04X,",depth,k,v))
+ else
+ handle(format("%s %s=%s,",depth,k,v)) -- %.99g
+ end
+ else
+ if hexify then
+ handle(format("%s [%q]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g
+ end
+ end
+ elseif t == "string" then
+ if reduce and tonumber(v) then
+ --~ handle(format("%s %s=%s,",depth,key(k),v))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%s,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ else
+ --~ handle(format("%s %s=%q,",depth,key(k),v))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,v))
+ else
+ handle(format("%s [%s]=%q,",depth,k,v))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%q,",depth,k,v))
+ else
+ handle(format("%s [%q]=%q,",depth,k,v))
+ end
+ end
+ elseif t == "table" then
+ if not next(v) then
+ --~ handle(format("%s %s={},",depth,key(k)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]={},",depth,k))
+ else
+ handle(format("%s [%s]={},",depth,k))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s={},",depth,k))
+ else
+ handle(format("%s [%q]={},",depth,k))
+ end
+ elseif inline then
+ local st = simple_table(v)
+ if st then
+ --~ handle(format("%s %s={ %s },",depth,key(k),concat(st,", ")))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t == "boolean" then
+ --~ handle(format("%s %s=%s,",depth,key(k),tostring(v)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%s,",depth,k,tostring(v)))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%s,",depth,k,tostring(v)))
+ end
+ elseif t == "function" then
+ if functions then
+ --~ handle(format('%s %s=loadstring(%q),',depth,key(k),dump(v)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ else
+ handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ else
+ handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
+ end
+ end
+ else
+ --~ handle(format("%s %s=%q,",depth,key(k),tostring(v)))
+ if type(k) == "number" then -- or find(k,"^%d+$") then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%q,",depth,k,tostring(v)))
+ end
+ elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
+ handle(format("%s %s=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%q,",depth,k,tostring(v)))
+ end
+ end
+ --~ end
+ end
+ end
+ if level > 0 then
+ handle(format("%s},",depth))
+ end
+end
+
+-- replacing handle by a direct t[#t+1] = ... (plus test) is not much
+-- faster (0.03 on 1.00 for zapfino.tma)
+
+local function serialize(root,name,_handle,_reduce,_noquotes,_hexify)
+ noquotes = _noquotes
+ hexify = _hexify
+ handle = _handle or print
+ reduce = _reduce or false
+ compact = table.serialize_compact
+ inline = compact and table.serialize_inline
+ functions = table.serialize_functions
+ local tname = type(name)
+ if tname == "string" then
+ if name == "return" then
+ handle("return {")
+ else
+ handle(name .. "={")
+ end
+ elseif tname == "number" then
+ if hexify then
+ handle(format("[0x%04X]={",name))
+ else
+ handle("[" .. name .. "]={")
+ end
+ elseif tname == "boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
+ end
+ else
+ handle("t={")
+ end
+ if root and next(root) then
+ do_serialize(root,name,"",0,indexed)
+ end
+ handle("}")
+end
+
+--~ name:
+--~
+--~ true : return { }
+--~ false : { }
+--~ nil : t = { }
+--~ string : string = { }
+--~ 'return' : return { }
+--~ number : [number] = { }
+
+function table.serialize(root,name,reduce,noquotes,hexify)
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ return concat(t,"\n")
+end
+
+function table.tohandle(handle,root,name,reduce,noquotes,hexify)
+ serialize(root,name,handle,reduce,noquotes,hexify)
+end
+
+-- sometimes tables are real use (zapfino extra pro is some 85M) in which
+-- case a stepwise serialization is nice; actually, we could consider:
+--
+-- for line in table.serializer(root,name,reduce,noquotes) do
+-- ...(line)
+-- end
+--
+-- so this is on the todo list
+
+table.tofile_maxtab = 2*1024
+
+function table.tofile(filename,root,name,reduce,noquotes,hexify)
+ local f = io.open(filename,'w')
+ if f then
+ local maxtab = table.tofile_maxtab
+ if maxtab > 1 then
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
+ if #t > maxtab then
+ f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
+ t = { }
+ end
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ end
+ f:close()
+ end
+end
+
+local function flatten(t,f,complete) -- is this used? meybe a variant with next, ...
+ for i=1,#t do
+ local v = t[i]
+ if type(v) == "table" then
+ if complete or type(v[1]) == "table" then
+ flatten(v,f,complete)
+ else
+ f[#f+1] = v
+ end
+ else
+ f[#f+1] = v
+ end
+ end
+end
+
+function table.flatten(t)
+ local f = { }
+ flatten(t,f,true)
+ return f
+end
+
+function table.unnest(t) -- bad name
+ local f = { }
+ flatten(t,f,false)
+ return f
+end
+
+table.flatten_one_level = table.unnest
+
+-- a better one:
+
+local function flattened(t,f)
+ if not f then
+ f = { }
+ end
+ for k, v in next, t do
+ if type(v) == "table" then
+ flattened(v,f)
+ else
+ f[k] = v
+ end
+ end
+ return f
+end
+
+table.flattened = flattened
+
+-- the next three may disappear
+
+function table.remove_value(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
+end
+
+function table.insert_before_value(t,value,str)
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,str)
+ return
+ end
+ end
+ end
+ insert(t,1,str)
+ elseif value then
+ insert(t,1,value)
+ end
+end
+
+function table.insert_after_value(t,value,str)
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,str)
+ return
+ end
+ end
+ end
+ t[#t+1] = str
+ elseif value then
+ t[#t+1] = value
+ end
+end
+
+local function are_equal(a,b,n,m) -- indexed
+ if a and b and #a == #b then
+ n = n or 1
+ m = m or #a
+ for i=n,m do
+ local ai, bi = a[i], b[i]
+ if ai==bi then
+ -- same
+ elseif type(ai)=="table" and type(bi)=="table" then
+ if not are_equal(ai,bi) then
+ return false
+ end
+ else
+ return false
+ end
+ end
+ return true
+ else
+ return false
+ end
+end
+
+local function identical(a,b) -- assumes same structure
+ for ka, va in next, a do
+ local vb = b[k]
+ if va == vb then
+ -- same
+ elseif type(va) == "table" and type(vb) == "table" then
+ if not identical(va,vb) then
+ return false
+ end
+ else
+ return false
+ end
+ end
+ return true
+end
+
+table.are_equal = are_equal
+table.identical = identical
+
+-- maybe also make a combined one
+
+function table.compact(t)
+ if t then
+ for k,v in next, t do
+ if not next(v) then
+ t[k] = nil
+ end
+ end
+ end
+end
+
+function table.contains(t, v)
+ if t then
+ for i=1, #t do
+ if t[i] == v then
+ return i
+ end
+ end
+ end
+ return false
+end
+
+function table.count(t)
+ local n, e = 0, next(t)
+ while e do
+ n, e = n + 1, next(t,e)
+ end
+ return n
+end
+
+function table.swapped(t)
+ local s = { }
+ for k, v in next, t do
+ s[v] = k
+ end
+ return s
+end
+
+--~ function table.are_equal(a,b)
+--~ return table.serialize(a) == table.serialize(b)
+--~ end
+
+function table.clone(t,p) -- t is optional or nil or table
+ if not p then
+ t, p = { }, t or { }
+ elseif not t then
+ t = { }
+ end
+ setmetatable(t, { __index = function(_,key) return p[key] end }) -- why not __index = p ?
+ return t
+end
+
+function table.hexed(t,seperator)
+ local tt = { }
+ for i=1,#t do tt[i] = format("0x%04X",t[i]) end
+ return concat(tt,seperator or " ")
+end
+
+function table.reverse_hash(h)
+ local r = { }
+ for k,v in next, h do
+ r[v] = lower(gsub(k," ",""))
+ end
+ return r
+end
+
+function table.reverse(t)
+ local tt = { }
+ if #t > 0 then
+ for i=#t,1,-1 do
+ tt[#tt+1] = t[i]
+ end
+ end
+ return tt
+end
+
+function table.insert_before_value(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+
+function table.insert_after_value(t,value,extra)
+ for i=1,#t do
+ if t[i] == extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+
diff --git a/tex/context/base/l-unicode.lua b/tex/context/base/l-unicode.lua
new file mode 100644
index 000000000..0c5a60142
--- /dev/null
+++ b/tex/context/base/l-unicode.lua
@@ -0,0 +1,199 @@
+if not modules then modules = { } end modules ['l-unicode'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not unicode then
+
+ unicode = { utf8 = { } }
+
+ local floor, char = math.floor, string.char
+
+ function unicode.utf8.utfchar(n)
+ if n < 0x80 then
+ return char(n)
+ elseif n < 0x800 then
+ return char(0xC0 + floor(n/0x40)) .. char(0x80 + (n % 0x40))
+ elseif n < 0x10000 then
+ return char(0xE0 + floor(n/0x1000)) .. char(0x80 + (floor(n/0x40) % 0x40)) .. char(0x80 + (n % 0x40))
+ elseif n < 0x40000 then
+ return char(0xF0 + floor(n/0x40000)) .. char(0x80 + floor(n/0x1000)) .. char(0x80 + (floor(n/0x40) % 0x40)) .. char(0x80 + (n % 0x40))
+ else -- wrong:
+ -- return char(0xF1 + floor(n/0x1000000)) .. char(0x80 + floor(n/0x40000)) .. char(0x80 + floor(n/0x1000)) .. char(0x80 + (floor(n/0x40) % 0x40)) .. char(0x80 + (n % 0x40))
+ return "?"
+ end
+ end
+
+end
+
+utf = utf or unicode.utf8
+
+local concat, utfchar, utfgsub = table.concat, utf.char, utf.gsub
+local char, byte, find, bytepairs = string.char, string.byte, string.find, string.bytepairs
+
+-- 0 EF BB BF UTF-8
+-- 1 FF FE UTF-16-little-endian
+-- 2 FE FF UTF-16-big-endian
+-- 3 FF FE 00 00 UTF-32-little-endian
+-- 4 00 00 FE FF UTF-32-big-endian
+
+unicode.utfname = {
+ [0] = 'utf-8',
+ [1] = 'utf-16-le',
+ [2] = 'utf-16-be',
+ [3] = 'utf-32-le',
+ [4] = 'utf-32-be'
+}
+
+-- \000 fails in <= 5.0 but is valid in >=5.1 where %z is depricated
+
+function unicode.utftype(f)
+ local str = f:read(4)
+ if not str then
+ f:seek('set')
+ return 0
+ -- elseif find(str,"^%z%z\254\255") then -- depricated
+ -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
+ elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
+ return 4
+ -- elseif find(str,"^\255\254%z%z") then -- depricated
+ -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
+ elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
+ return 3
+ elseif find(str,"^\254\255") then
+ f:seek('set',2)
+ return 2
+ elseif find(str,"^\255\254") then
+ f:seek('set',2)
+ return 1
+ elseif find(str,"^\239\187\191") then
+ f:seek('set',3)
+ return 0
+ else
+ f:seek('set')
+ return 0
+ end
+end
+
+function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
+ local result, tmp, n, m, p = { }, { }, 0, 0, 0
+ -- lf | cr | crlf / (cr:13, lf:10)
+ local function doit()
+ if n == 10 then
+ if p ~= 13 then
+ result[#result+1] = concat(tmp)
+ tmp = { }
+ p = 0
+ end
+ elseif n == 13 then
+ result[#result+1] = concat(tmp)
+ tmp = { }
+ p = n
+ else
+ tmp[#tmp+1] = utfchar(n)
+ p = 0
+ end
+ end
+ for l,r in bytepairs(str) do
+ if r then
+ if endian then
+ n = l*256 + r
+ else
+ n = r*256 + l
+ end
+ if m > 0 then
+ n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
+ m = 0
+ doit()
+ elseif n >= 0xD800 and n <= 0xDBFF then
+ m = n
+ else
+ doit()
+ end
+ end
+ end
+ if #tmp > 0 then
+ result[#result+1] = concat(tmp)
+ end
+ return result
+end
+
+function unicode.utf32_to_utf8(str, endian)
+ local result = { }
+ local tmp, n, m, p = { }, 0, -1, 0
+ -- lf | cr | crlf / (cr:13, lf:10)
+ local function doit()
+ if n == 10 then
+ if p ~= 13 then
+ result[#result+1] = concat(tmp)
+ tmp = { }
+ p = 0
+ end
+ elseif n == 13 then
+ result[#result+1] = concat(tmp)
+ tmp = { }
+ p = n
+ else
+ tmp[#tmp+1] = utfchar(n)
+ p = 0
+ end
+ end
+ for a,b in bytepairs(str) do
+ if a and b then
+ if m < 0 then
+ if endian then
+ m = a*256*256*256 + b*256*256
+ else
+ m = b*256 + a
+ end
+ else
+ if endian then
+ n = m + a*256 + b
+ else
+ n = m + b*256*256*256 + a*256*256
+ end
+ m = -1
+ doit()
+ end
+ else
+ break
+ end
+ end
+ if #tmp > 0 then
+ result[#result+1] = concat(tmp)
+ end
+ return result
+end
+
+local function little(c)
+ local b = byte(c) -- b = c:byte()
+ if b < 0x10000 then
+ return char(b%256,b/256)
+ else
+ b = b - 0x10000
+ local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+end
+
+local function big(c)
+ local b = byte(c)
+ if b < 0x10000 then
+ return char(b/256,b%256)
+ else
+ b = b - 0x10000
+ local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+end
+
+function unicode.utf8_to_utf16(str,littleendian)
+ if littleendian then
+ return char(255,254) .. utfgsub(str,".",little)
+ else
+ return char(254,255) .. utfgsub(str,".",big)
+ end
+end
diff --git a/tex/context/base/l-url.lua b/tex/context/base/l-url.lua
new file mode 100644
index 000000000..e3e6f8130
--- /dev/null
+++ b/tex/context/base/l-url.lua
@@ -0,0 +1,134 @@
+if not modules then modules = { } end modules ['l-url'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local char, gmatch, gsub = string.char, string.gmatch, string.gsub
+local tonumber, type = tonumber, type
+local lpegmatch = lpeg.match
+
+-- from the spec (on the web):
+--
+-- foo://example.com:8042/over/there?name=ferret#nose
+-- \_/ \______________/\_________/ \_________/ \__/
+-- | | | | |
+-- scheme authority path query fragment
+-- | _____________________|__
+-- / \ / \
+-- urn:example:animal:ferret:nose
+
+url = url or { }
+
+local function tochar(s)
+ return char(tonumber(s,16))
+end
+
+local colon, qmark, hash, slash, percent, endofstring = lpeg.P(":"), lpeg.P("?"), lpeg.P("#"), lpeg.P("/"), lpeg.P("%"), lpeg.P(-1)
+
+local hexdigit = lpeg.R("09","AF","af")
+local plus = lpeg.P("+")
+local escaped = (plus / " ") + (percent * lpeg.C(hexdigit * hexdigit) / tochar)
+
+-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+
+local scheme = lpeg.Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon + lpeg.Cc("")
+local authority = slash * slash * lpeg.Cs((escaped+(1- slash-qmark-hash))^0) + lpeg.Cc("")
+local path = slash * lpeg.Cs((escaped+(1- qmark-hash))^0) + lpeg.Cc("")
+local query = qmark * lpeg.Cs((escaped+(1- hash))^0) + lpeg.Cc("")
+local fragment = hash * lpeg.Cs((escaped+(1- endofstring))^0) + lpeg.Cc("")
+
+local parser = lpeg.Ct(scheme * authority * path * query * fragment)
+
+-- todo: reconsider Ct as we can as well have five return values (saves a table)
+-- so we can have two parsers, one with and one without
+
+function url.split(str)
+ return (type(str) == "string" and lpegmatch(parser,str)) or str
+end
+
+-- todo: cache them
+
+function url.hashed(str)
+ local s = url.split(str)
+ local somescheme = s[1] ~= ""
+ return {
+ scheme = (somescheme and s[1]) or "file",
+ authority = s[2],
+ path = s[3],
+ query = s[4],
+ fragment = s[5],
+ original = str,
+ noscheme = not somescheme,
+ }
+end
+
+function url.hasscheme(str)
+ return url.split(str)[1] ~= ""
+end
+
+function url.addscheme(str,scheme)
+ return (url.hasscheme(str) and str) or ((scheme or "file:///") .. str)
+end
+
+function url.construct(hash)
+ local fullurl = hash.sheme .. "://".. hash.authority .. hash.path
+ if hash.query then
+ fullurl = fullurl .. "?".. hash.query
+ end
+ if hash.fragment then
+ fullurl = fullurl .. "?".. hash.fragment
+ end
+ return fullurl
+end
+
+function url.filename(filename)
+ local t = url.hashed(filename)
+ return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
+end
+
+function url.query(str)
+ if type(str) == "string" then
+ local t = { }
+ for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
+ t[k] = v
+ end
+ return t
+ else
+ return str
+ end
+end
+
+--~ print(url.filename("file:///c:/oeps.txt"))
+--~ print(url.filename("c:/oeps.txt"))
+--~ print(url.filename("file:///oeps.txt"))
+--~ print(url.filename("file:///etc/test.txt"))
+--~ print(url.filename("/oeps.txt"))
+
+--~ from the spec on the web (sort of):
+--~
+--~ function test(str)
+--~ print(table.serialize(url.hashed(str)))
+--~ end
+--~
+--~ test("%56pass%20words")
+--~ test("file:///c:/oeps.txt")
+--~ test("file:///c|/oeps.txt")
+--~ test("file:///etc/oeps.txt")
+--~ test("file://./etc/oeps.txt")
+--~ test("file:////etc/oeps.txt")
+--~ test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
+--~ test("http://www.ietf.org/rfc/rfc2396.txt")
+--~ test("ldap://[2001:db8::7]/c=GB?objectClass?one#what")
+--~ test("mailto:John.Doe@example.com")
+--~ test("news:comp.infosystems.www.servers.unix")
+--~ test("tel:+1-816-555-1212")
+--~ test("telnet://192.0.2.16:80/")
+--~ test("urn:oasis:names:specification:docbook:dtd:xml:4.1.2")
+--~ test("/etc/passwords")
+--~ test("http://www.pragma-ade.com/spaced%20name")
+
+--~ test("zip:///oeps/oeps.zip#bla/bla.tex")
+--~ test("zip:///oeps/oeps.zip?bla/bla.tex")
diff --git a/tex/context/base/l-utils.lua b/tex/context/base/l-utils.lua
new file mode 100644
index 000000000..ebc27b8cf
--- /dev/null
+++ b/tex/context/base/l-utils.lua
@@ -0,0 +1,176 @@
+if not modules then modules = { } end modules ['l-utils'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- hm, quite unreadable
+
+local gsub = string.gsub
+local concat = table.concat
+local type, next = type, next
+
+if not utils then utils = { } end
+if not utils.merger then utils.merger = { } end
+if not utils.lua then utils.lua = { } end
+
+utils.merger.m_begin = "begin library merge"
+utils.merger.m_end = "end library merge"
+utils.merger.pattern =
+ "%c+" ..
+ "%-%-%s+" .. utils.merger.m_begin ..
+ "%c+(.-)%c+" ..
+ "%-%-%s+" .. utils.merger.m_end ..
+ "%c+"
+
+function utils.merger._self_fake_()
+ return
+ "-- " .. "created merged file" .. "\n\n" ..
+ "-- " .. utils.merger.m_begin .. "\n\n" ..
+ "-- " .. utils.merger.m_end .. "\n\n"
+end
+
+function utils.report(...)
+ print(...)
+end
+
+utils.merger.strip_comment = true
+
+function utils.merger._self_load_(name)
+ local f, data = io.open(name), ""
+ if f then
+ utils.report("reading merge from %s",name)
+ data = f:read("*all")
+ f:close()
+ else
+ utils.report("unknown file to merge %s",name)
+ end
+ if data and utils.merger.strip_comment then
+ -- saves some 20K
+ data = gsub(data,"%-%-~[^\n\r]*[\r\n]", "")
+ end
+ return data or ""
+end
+
+function utils.merger._self_save_(name, data)
+ if data ~= "" then
+ local f = io.open(name,'w')
+ if f then
+ utils.report("saving merge from %s",name)
+ f:write(data)
+ f:close()
+ end
+ end
+end
+
+function utils.merger._self_swap_(data,code)
+ if data ~= "" then
+ return (gsub(data,utils.merger.pattern, function(s)
+ return "\n\n" .. "-- "..utils.merger.m_begin .. "\n" .. code .. "\n" .. "-- "..utils.merger.m_end .. "\n\n"
+ end, 1))
+ else
+ return ""
+ end
+end
+
+--~ stripper:
+--~
+--~ data = gsub(data,"%-%-~[^\n]*\n","")
+--~ data = gsub(data,"\n\n+","\n")
+
+function utils.merger._self_libs_(libs,list)
+ local result, f, frozen = { }, nil, false
+ result[#result+1] = "\n"
+ if type(libs) == 'string' then libs = { libs } end
+ if type(list) == 'string' then list = { list } end
+ local foundpath = nil
+ for i=1,#libs do
+ local lib = libs[i]
+ for j=1,#list do
+ local pth = gsub(list[j],"\\","/") -- file.clean_path
+ utils.report("checking library path %s",pth)
+ local name = pth .. "/" .. lib
+ if lfs.isfile(name) then
+ foundpath = pth
+ end
+ end
+ if foundpath then break end
+ end
+ if foundpath then
+ utils.report("using library path %s",foundpath)
+ local right, wrong = { }, { }
+ for i=1,#libs do
+ local lib = libs[i]
+ local fullname = foundpath .. "/" .. lib
+ if lfs.isfile(fullname) then
+ -- right[#right+1] = lib
+ utils.report("merging library %s",fullname)
+ result[#result+1] = "do -- create closure to overcome 200 locals limit"
+ result[#result+1] = io.loaddata(fullname,true)
+ result[#result+1] = "end -- of closure"
+ else
+ -- wrong[#wrong+1] = lib
+ utils.report("no library %s",fullname)
+ end
+ end
+ if #right > 0 then
+ utils.report("merged libraries: %s",concat(right," "))
+ end
+ if #wrong > 0 then
+ utils.report("skipped libraries: %s",concat(wrong," "))
+ end
+ else
+ utils.report("no valid library path found")
+ end
+ return concat(result, "\n\n")
+end
+
+function utils.merger.selfcreate(libs,list,target)
+ if target then
+ utils.merger._self_save_(
+ target,
+ utils.merger._self_swap_(
+ utils.merger._self_fake_(),
+ utils.merger._self_libs_(libs,list)
+ )
+ )
+ end
+end
+
+function utils.merger.selfmerge(name,libs,list,target)
+ utils.merger._self_save_(
+ target or name,
+ utils.merger._self_swap_(
+ utils.merger._self_load_(name),
+ utils.merger._self_libs_(libs,list)
+ )
+ )
+end
+
+function utils.merger.selfclean(name)
+ utils.merger._self_save_(
+ name,
+ utils.merger._self_swap_(
+ utils.merger._self_load_(name),
+ ""
+ )
+ )
+end
+
+function utils.lua.compile(luafile, lucfile, cleanup, strip) -- defaults: cleanup=false strip=true
+ -- utils.report("compiling",luafile,"into",lucfile)
+ os.remove(lucfile)
+ local command = "-o " .. string.quote(lucfile) .. " " .. string.quote(luafile)
+ if strip ~= false then
+ command = "-s " .. command
+ end
+ local done = (os.spawn("texluac " .. command) == 0) or (os.spawn("luac " .. command) == 0)
+ if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ -- utils.report("removing",luafile)
+ os.remove(luafile)
+ end
+ return done
+end
+
diff --git a/tex/context/base/l-xml.lua b/tex/context/base/l-xml.lua
new file mode 100644
index 000000000..14e97337b
--- /dev/null
+++ b/tex/context/base/l-xml.lua
@@ -0,0 +1,23 @@
+if not modules then modules = { } end modules ['l-xml'] = {
+ version = 1.001,
+ comment = "this module is replaced by the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We asume that the helper modules l-*.lua are loaded
+-- already. But anyway if you use mtxrun to run your script
+-- all is taken care of.
+
+if not trackers then
+ require('trac-tra')
+end
+
+if not xml then
+ require('lxml-tab')
+ require('lxml-lpt')
+ require('lxml-mis')
+ require('lxml-aux')
+ require('lxml-xml')
+end
diff --git a/tex/context/base/lang-all.xml b/tex/context/base/lang-all.xml
new file mode 100644
index 000000000..503cb0ae5
--- /dev/null
+++ b/tex/context/base/lang-all.xml
@@ -0,0 +1,376 @@
+
+
+
+
+
+
+
+ bahyph.tex
+ TeX hyphenation patterns for the Basque language
+
+ 1991
+ Julio Sanchez (jsanchez@gmv.es)
+ These patterns have been derived from "On Word Division in Spanish"
+ Jos'e A. Ma~nas
+
+
+ 1997
+ Juan M. Aguirregabiria (wtpagagj@lg.ehu.es)
+ Adaption to TeX based on shyphen.sh
+
+
+
+
+ cahyph.tex
+ TeX hyphenation patterns for the Catalan language
+ Version 1.11
+
+ 1991-1995
+ Gon\c{c}al Badenes,Francina Turon
+
+
+ 1991-2003
+ Gon\c{c}al Badenes
+
+
+
+
+ cyhyph.tex
+ TeX hyphenation patterns for the Welsh Language
+ v3,GNU General Public License
+
+ 1996
+ Yannis Haralambous
+ Inputs cathyph.tex, patterns in EC/DC encoding
+
+
+
+
+ czhyphen.tex
+ TeX hyphenation patterns for the Czech language
+
+ 1991
+ Karel Horak
+ List of exceptions
+
+
+ 1995
+ Pavel Sevecek (\v{S}eve\v{c}ek) (pavel@lingea.cz)
+ Macros, adaption for TeX 2
+
+
+
+
+
+ dkspecial.tex dkcommon.tex
+ TeX hyphenation patterns for the Danish language
+
+
+
+
+ dehyphn.tex
+ TeX hyphenation patterns for the German language (new orthography)
+
+ 1988, 1991
+ Rechenzentrum der Ruhr-Universitaet Bochum
+ German hyphen patterns
+
+
+ 1993, 1994, 1999
+ Bernd Raichle/DANTE e.V.
+ Macros, adaption for TeX 2
+
+
+ 1998-2001
+ Walter Schmidt
+ Adaption to new German orthography
+
+
+
+
+ dehypht.tex
+ TeX hyphenation patterns for the German language (traditional orthography)
+
+ 1988, 1991
+ Rechenzentrum der Ruhr-Universitaet Bochum
+ German hyphen patterns
+
+
+ 1993, 1994, 1999
+ Bernd Raichle/DANTE e.V.
+ Macros, adaption for TeX 2
+
+
+
+
+ hyphen.tex
+ Plain TeX hyphenation patterns for the English language (US)
+ [NOT TO BE CHANGED IN ANY WAY!]
+
+
+
+
+ eshyph.tex
+ TeX hyphenation patterns for the Spanish language
+
+ 1993
+ Francesc Carmona (franc@porthos.bio.ub.es)
+
+
+
+
+ fihyph.tex
+ TeX hyphenation patterns for the Finnish language
+
+ 1986
+ Kauko Saarinen
+ First release
+
+
+ 1988
+ Fred Karlsson
+ Completely rewritten patterns
+
+
+ 1989
+ Fred Karlsson
+ Some vowel tripples added
+
+
+ 1995
+ Thomas Esser
+ Added \uccode and \lccode
+
+
+
+
+ frhyph.tex
+ TeX hyphenation patterns for the French language
+ V2.11
+
+ Jacques Desarmenien, Norman Buckle, Michael Ferguson, Justin Bur, Daniel Flipo and Bernard Gaulle
+
+
+ 1996
+ Bernd Raichle/DANTE e.V.
+ Adaption for TeX 3.x and MLTeX 3.x (2.x)
+
+
+
+
+ hrhyph.tex
+ TeX hyphenation patterns for the Croatian language
+
+ 1994, 1996
+ Marinovi\'c Igor (migor@student.math.hr)
+
+
+
+
+ huhyphn.tex
+ TeX hyphenation patterns for the Hungarian language
+
+
+
+ ishyph.tex
+ Plain TeX hyphenation patterns for the Icelandic language
+ [NOT TO BE CHANGED IN ANY WAY!]
+
+ 1987
+ Jorgen Pind
+
+
+
+
+ ithyph.tex
+ TeX hyphenation patterns for the Italian language
+ v4.8d
+
+ 1998, 2001
+ Claudio Beccari
+
+
+ 1993, 1994, 1999
+ Bernd Raichle/DANTE e.V.
+ Macros, adaption for TeX 2
+
+
+
+
+ lahyph.tex
+ TeX hyphenation patterns for the Latin language
+ v3.0b
+
+ 1999-2001
+ Claudio Beccari
+
+
+ 1993, 1994, 1998, 1999
+ Bernd Raichle/DANTE e.V.
+ Macro code in 'dehypht.tex'
+
+
+
+
+ nehyph96.tex
+ TeX hyphenation patterns for the Dutch language
+
+ 1996
+ Piet Tutelaers (P.T.H.Tutelaers@tue.nl)
+ 8-bit hyphenation patterns for TeX based upon the new Dutch
+ spelling, officially since 1 August 1996. These patterns follow
+ the new hyphenation rules in the `Woordenlijst Nederlandse
+ Taal, SDU Uitgevers, Den Haag 1995' (the so called `Groene
+ Boekje') described in section 5.2 (Het afbreekteken)
+
+
+
+
+
+
+ nohyph.tex
+ TeX hyphenation patterns for the Norwegian language
+
+ 2005
+ Rune Kleveland with patches from Ole Michael Selberg
+ nohyphbx.tex
+
+
+ 200+
+ Rune Kleveland
+ nohyphb.tex
+
+
+ 199+
+ Dag Langmyhr and student
+ nohyph2.tex
+
+
+ 199+
+ Ivar Aavatsmark and others
+ nohyph.tex sometimes named nohyph1.tex
+
+
+ 1992,1993
+ Ivar Aavatsmark
+ nohyphen.tex based on danhyph.tex
+
+
+ 1994
+ Preben Randhol, Jon Martin Solaas
+
+
+ 1995
+ Thomas Esser (te@dbs.uni-hannover.de)
+ Make patterns work with non-T1 encoding
+
+
+
+
+ plhyph.tex
+ TeX hyphenation patterns for the Polish language
+
+
+
+
+ pthyph.tex
+ TeX hyphenation patterns for the Portuguese language
+
+
+
+
+ rohyph.tex
+ TeX hyphenation patterns for the Romanian language
+
+
+
+
+ skhyphen.tex skhyphen.ex
+ TeX hyphenation patterns for the Slovakian language
+
+ 1992
+ Jana Chlebikova
+
+
+ 1991
+ Karel Horak
+ List of exceptions
+
+
+
+
+ sihyph.tex
+ TeX hyphenation patterns for the Slovenian language
+
+ 1990
+ TeXCeX (SLO),TeXCeH Norbert Schwarz
+
+
+ 1994
+ Leon "Zlajpah (leon.zlajpah@ijs.si)
+ Use of code page 852 in patterns
+
+
+ 1995,1997
+ Leon "Zlajpah (leon.zlajpah@ijs.si)
+ Adaptaion of Slovenian hyphenation pattens, macros
+
+
+
+
+ svhyph.tex
+ TeX hyphenation patterns for the Swedish language
+
+ 1991,1994
+ Jan Michael Rynning
+
+
+
+
+ tkhyph.tex
+ TeX hyphenation patterns for the modern Turkish language
+
+ 1996
+ Yannis Haralambous
+ A mechanically generated Turkish Hyphenation table for TeX,
+ using the University of Washington diacritical coding
+ developed by P. A. MacKay for the Ottoman Texts Project
+
+
+
+
+ ukhyphen.tex
+ TeX hyphenation patterns for the English language (UK)
+
+
+
+
+ Vietnamese needs no patterns.
+
+
+
+ grahyph4.tex
+ TeX hyphenation patterns for the ancient Greek language
+
+ 2004
+ Dimitrios Filippou
+ These hyphenation patterns are explained in "ancient.pdf".
+ Hyphenation examples are given in the file "anc-test.pdf".
+ Some doubtful patterns are marked by three question marks "???".
+
+
+
+
diff --git a/tex/context/base/lang-alt.tex b/tex/context/base/lang-alt.tex
new file mode 100644
index 000000000..f65acbda3
--- /dev/null
+++ b/tex/context/base/lang-alt.tex
@@ -0,0 +1,152 @@
+%D \module
+%D [ file=lang-alt,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Altaic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Altaic Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+
+% Uigur, Uzbek
+% Azeri/Azerbaijani, Chuvash, Turkish, Turkmen
+% Kazakh, Kazar, Kireghiz, Noghay, Talar
+% Buryat, Kalmuck, Khalkha
+%
+% Turkmen translation by Nazar Annagurban 18. March 2010
+
+\unprotect
+
+\installlanguage
+ [\s!tr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\ ,\v!month,\ ,\v!day}]
+
+\installlanguage
+ [\s!tk]
+ [\c!spacing=\v!broad,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\ ,\v!month,\ ,\v!day}
+ \s!patterns=\s!tk,
+ \s!lefthyphenmin=1,
+ \s!righthyphenmin=2]
+
+\installlanguage [turkish] [\s!tr]
+\installlanguage [turkmen] [\s!tk]
+
+\setupheadtext [\s!tr] [\v!content=Fihrist]
+\setupheadtext [\s!tk] [\v!content=Mazmuny]
+\setupheadtext [\s!tr] [\v!tables=Tablolar]
+\setupheadtext [\s!tk] [\v!tables=Tablisalar]
+\setupheadtext [\s!tr] [\v!figures=\Scedilla ekiller]
+\setupheadtext [\s!tk] [\v!figures=Suratlar]
+\setupheadtext [\s!tr] [\v!graphics=Grafikler]
+\setupheadtext [\s!tk] [\v!graphics=Grafikler]
+\setupheadtext [\s!tr] [\v!intermezzi=...]
+\setupheadtext [\s!tk] [\v!intermezzi=Arakesmeler]
+\setupheadtext [\s!tr] [\v!index=\Idotaccent ndex]
+\setupheadtext [\s!tk] [\v!index=Indeks]
+\setupheadtext [\s!tr] [\v!abbreviations=K\dotlessi saltmalar]
+\setupheadtext [\s!tk] [\v!abbreviations=Gysgaltmalar]
+\setupheadtext [\s!tr] [\v!logos=Logolar]
+\setupheadtext [\s!tk] [\v!logos=Logolar]
+\setupheadtext [\s!tr] [\v!units=Birimler]
+\setupheadtext [\s!tk] [\v!units=Birlikler]
+
+\setuplabeltext [\s!tr] [\v!table=Tablo ]
+\setuplabeltext [\s!tk] [\v!table=Tablisa]
+\setuplabeltext [\s!tr] [\v!figure=\Scedilla ekil ]
+\setuplabeltext [\s!tk] [\v!figure=Surat]
+\setuplabeltext [\s!tr] [\v!intermezzo=... ]
+\setuplabeltext [\s!tk] [\v!intermezzo=Arakesme]
+\setuplabeltext [\s!tr] [\v!graphic=Grafik]
+\setuplabeltext [\s!tk] [\v!graphic=Grafik]
+\setuplabeltext [\s!tr] [\v!chapter=]
+\setuplabeltext [\s!tk] [\v!chapter=Bap]
+\setuplabeltext [\s!tr] [\v!section=]
+\setuplabeltext [\s!tk] [\v!section=]
+\setuplabeltext [\s!tr] [\v!subsection=]
+\setuplabeltext [\s!tk] [\v!subsection=]
+\setuplabeltext [\s!tr] [\v!subsubsection=]
+\setuplabeltext [\s!tr] [\v!subsubsubsection=]
+\setuplabeltext [\s!tk] [\v!subsubsubsection=]
+\setuplabeltext [\s!tr] [\v!appendix=]
+\setuplabeltext [\s!tk] [\v!appendix=Go\scedilla ma\ccedilla a]
+\setuplabeltext [\s!tr] [\v!part=Cilt ]
+\setuplabeltext [\s!tk] [\v!part=B\odiaeresis l\udiaeresis m]
+\setuplabeltext [\s!tr] [\v!line=sat\dotlessi r ]
+\setuplabeltext [\s!tk] [\v!line=setir]
+\setuplabeltext [\s!tr] [\v!lines=sat\dotlessi rlar ]
+\setuplabeltext [\s!tk] [\v!lines=setirler]
+
+\setuplabeltext [\s!tk] [\v!january=\yacute anwar]
+\setuplabeltext [\s!tk] [\v!february=fewral]
+\setuplabeltext [\s!tk] [\v!march=mart]
+\setuplabeltext [\s!tk] [\v!april=aprel]
+\setuplabeltext [\s!tk] [\v!may=ma\yacute]
+\setuplabeltext [\s!tk] [\v!june=i\yacute un]
+\setuplabeltext [\s!tk] [\v!july=i\yacute ul]
+\setuplabeltext [\s!tk] [\v!august=awgust]
+\setuplabeltext [\s!tk] [\v!september=sent\yacute abr]
+\setuplabeltext [\s!tk] [\v!october=okt\yacute abr]
+\setuplabeltext [\s!tk] [\v!november=no\yacute abr]
+\setuplabeltext [\s!tk] [\v!december=dekabr]
+
+\setuplabeltext [\s!tr] [\v!january=ocak]
+\setuplabeltext [\s!tr] [\v!february=\Scedilla ubat]
+\setuplabeltext [\s!tr] [\v!march=mart]
+\setuplabeltext [\s!tr] [\v!april=nisan]
+\setuplabeltext [\s!tr] [\v!may=may\dotlessi s]
+\setuplabeltext [\s!tr] [\v!june=haziran]
+\setuplabeltext [\s!tr] [\v!july=temmuz]
+\setuplabeltext [\s!tr] [\v!august=a\gbreve ustos]
+\setuplabeltext [\s!tr] [\v!september=eyl\udiaeresis l]
+\setuplabeltext [\s!tr] [\v!october=ekim]
+\setuplabeltext [\s!tr] [\v!november=kas\dotlessi m]
+\setuplabeltext [\s!tr] [\v!december=aral\dotlessi k]
+
+\setuplabeltext [\s!tr] [\v!sunday=pazar]
+\setuplabeltext [\s!tr] [\v!monday=pazartesi]
+\setuplabeltext [\s!tr] [\v!tuesday=sal\dotlessi]
+\setuplabeltext [\s!tr] [\v!wednesday=\ccedilla ar\scedilla amba]
+\setuplabeltext [\s!tr] [\v!thursday=per\scedilla embe]
+\setuplabeltext [\s!tr] [\v!friday=cuma]
+\setuplabeltext [\s!tr] [\v!saturday=cumartesi]
+
+\setuplabeltext [\s!tk] [\v!sunday=dyn\ccedilla\ g\udiaeresis n]
+\setuplabeltext [\s!tk] [\v!monday=birinji g\udiaeresis n]
+\setuplabeltext [\s!tk] [\v!tuesday=ikinji g\udiaeresis n]
+\setuplabeltext [\s!tk] [\v!wednesday=\udiaeresis\ccedilla\udiaeresis nji]
+\setuplabeltext [\s!tk] [\v!thursday=d\odiaeresis rd\udiaeresis nji g\udiaeresis n]
+\setuplabeltext [\s!tk] [\v!friday=b\adiaeresis\scedilla inji g\udiaeresis n]
+\setuplabeltext [\s!tk] [\v!saturday=altynjy g\udiaeresis n]
+
+%D \ShowAllLanguageValues [\s!tr] [turkish] {Turkish} {delight} % turks fruit
+
+\protect \endinput
diff --git a/tex/context/base/lang-ana.tex b/tex/context/base/lang-ana.tex
new file mode 100644
index 000000000..c108655c4
--- /dev/null
+++ b/tex/context/base/lang-ana.tex
@@ -0,0 +1,24 @@
+%D \module
+%D [ file=lang-ana,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Anatolian Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Anatolian Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+
+\unprotect
+
+\protect \endinput
diff --git a/tex/context/base/lang-ara.mkiv b/tex/context/base/lang-ara.mkiv
new file mode 100644
index 000000000..3c4d3c522
--- /dev/null
+++ b/tex/context/base/lang-ara.mkiv
@@ -0,0 +1,150 @@
+%D \module
+%D [ file=lang-ara,
+%D version=2008.06.20,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Arabic Languages,
+%D author=Khaled Hosny,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 / Arabic Languages}
+
+\unprotect
+
+\definesystemconstant {arabic}
+\definesystemvariable {ar}
+
+\installlanguage
+ [\s!ar]
+ [\c!spacing=\v!broad,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\ ,\v!month,{،\ },\v!year}]
+
+\installlanguage [\s!arabic] [\s!ar]
+
+% Just aliases to "ar" for now
+
+\installlanguage[\s!ar-ae][\c!default=\s!ar] % U.A.E.
+\installlanguage[\s!ar-bh][\c!default=\s!ar] % Bahrain
+\installlanguage[\s!ar-eg][\c!default=\s!ar] % Egypt
+\installlanguage[\s!ar-in][\c!default=\s!ar] % India?
+\installlanguage[\s!ar-kw][\c!default=\s!ar] % Kuwait
+\installlanguage[\s!ar-ly][\c!default=\s!ar] % Libya
+\installlanguage[\s!ar-om][\c!default=\s!ar] % Oman
+\installlanguage[\s!ar-qa][\c!default=\s!ar] % Qatar
+\installlanguage[\s!ar-sa][\c!default=\s!ar] % Saudi Arabia
+\installlanguage[\s!ar-sd][\c!default=\s!ar] % Sudan
+\installlanguage[\s!ar-tn][\c!default=\s!ar] % Tunisia
+\installlanguage[\s!ar-ye][\c!default=\s!ar] % Yemen
+
+% Syriac months
+
+\installlanguage[\s!ar-sy][\c!default=\s!ar] % Syria
+\installlanguage[\s!ar-iq][\c!default=\s!ar-sy] % Iraq
+\installlanguage[\s!ar-jo][\c!default=\s!ar-sy] % Jordan
+\installlanguage[\s!ar-lb][\c!default=\s!ar-sy] % Lebanon
+
+% Maghribi months
+
+\installlanguage[\s!ar-dz][\c!default=\s!ar] % Algeria
+\installlanguage[\s!ar-ma][\c!default=\s!ar] % Morocco
+
+\setupheadtext [\s!ar] [\v!content=المحتويات]
+\setupheadtext [\s!ar] [\v!tables=الجداول]
+\setupheadtext [\s!ar] [\v!figures=الأشكال]
+\setupheadtext [\s!ar] [\v!graphics=الرسوم]
+\setupheadtext [\s!ar] [\v!intermezzi=فسح]
+\setupheadtext [\s!ar] [\v!index=الفهرس]
+\setupheadtext [\s!ar] [\v!abbreviations=الاختصارات]
+\setupheadtext [\s!ar] [\v!logos=الشعارات]
+\setupheadtext [\s!ar] [\v!units=الوحدات]
+\setuplabeltext [\s!ar] [\v!table=جدول ]
+\setuplabeltext [\s!ar] [\v!figure=شكل ]
+\setuplabeltext [\s!ar] [\v!intermezzo=فسحة ]
+\setuplabeltext [\s!ar] [\v!graphic=رسم ]
+
+%D We don't set these here. One can do that in a style.
+
+\setuplabeltext [\s!ar] [\v!chapter=] % باب
+\setuplabeltext [\s!ar] [\v!section=] % فصل or قسم
+\setuplabeltext [\s!ar] [\v!subsection=] % فصل أدنى
+\setuplabeltext [\s!ar] [\v!subsubsection=] % فصل أ دنى أدنى
+\setuplabeltext [\s!ar] [\v!subsubsubsection=] % فصل أدنى أدنى أدنى
+\setuplabeltext [\s!ar] [\v!appendix=] % ملحق
+\setuplabeltext [\s!ar] [\v!part=جزء ]
+\setuplabeltext [\s!ar] [\v!line=سطر ]
+\setuplabeltext [\s!ar] [\v!lines=السطور ]
+
+\setuplabeltext [\s!ar] [\v!january=يناير]
+\setuplabeltext [\s!ar] [\v!february=فبراير]
+\setuplabeltext [\s!ar] [\v!march=مارس]
+\setuplabeltext [\s!ar] [\v!april=أبريل]
+\setuplabeltext [\s!ar] [\v!may=مايو]
+\setuplabeltext [\s!ar] [\v!june=يونيو]
+\setuplabeltext [\s!ar] [\v!july=يوليو]
+\setuplabeltext [\s!ar] [\v!august=أغسطس]
+\setuplabeltext [\s!ar] [\v!september=سبتمبر]
+\setuplabeltext [\s!ar] [\v!october=أكتوبر]
+\setuplabeltext [\s!ar] [\v!november=نوفمبر]
+\setuplabeltext [\s!ar] [\v!december=ديسمبر]
+
+\setuplabeltext [\s!ar-sy] [\v!january=كانون الثاني]
+\setuplabeltext [\s!ar-sy] [\v!february=شباط]
+\setuplabeltext [\s!ar-sy] [\v!march=آذار]
+\setuplabeltext [\s!ar-sy] [\v!april=نيسان]
+\setuplabeltext [\s!ar-sy] [\v!may=أيار]
+\setuplabeltext [\s!ar-sy] [\v!june=حزيران]
+\setuplabeltext [\s!ar-sy] [\v!july=تموز]
+\setuplabeltext [\s!ar-sy] [\v!august=آب]
+\setuplabeltext [\s!ar-sy] [\v!september=أيلول]
+\setuplabeltext [\s!ar-sy] [\v!october=تشرين الأول]
+\setuplabeltext [\s!ar-sy] [\v!november=تشرين الثاني]
+\setuplabeltext [\s!ar-sy] [\v!december=كانون الأول]
+
+\setuplabeltext [\s!ar-ma] [\v!may=ماي]
+\setuplabeltext [\s!ar-ma] [\v!july=يوليوز]
+\setuplabeltext [\s!ar-ma] [\v!august=غشت]
+\setuplabeltext [\s!ar-ma] [\v!september=شتنبر]
+\setuplabeltext [\s!ar-ma] [\v!november=نونبر]
+\setuplabeltext [\s!ar-ma] [\v!december=دجنبر]
+
+\setuplabeltext [\s!ar-dz] [\v!january=جانفي]
+\setuplabeltext [\s!ar-dz] [\v!february=فيفري]
+\setuplabeltext [\s!ar-dz] [\v!april=أفريل]
+\setuplabeltext [\s!ar-dz] [\v!may=ماي]
+\setuplabeltext [\s!ar-dz] [\v!june=جوان]
+\setuplabeltext [\s!ar-dz] [\v!july=جويلة]
+\setuplabeltext [\s!ar-dz] [\v!august=أوت]
+
+\setuplabeltext [\s!ar] [\v!sunday=الأحد]
+\setuplabeltext [\s!ar] [\v!monday=الاثنين]
+\setuplabeltext [\s!ar] [\v!tuesday=الثلاثاء]
+\setuplabeltext [\s!ar] [\v!wednesday=الأربعاء]
+\setuplabeltext [\s!ar] [\v!thursday=الخميس]
+\setuplabeltext [\s!ar] [\v!friday=الجمعة]
+\setuplabeltext [\s!ar] [\v!saturday=السبت]
+
+%D Rather new ...
+
+\setuplabeltext [\s!ar] [\v!page=صفحة ]
+\setuplabeltext [\s!ar] [\v!atpage=في صفحة ]
+\setuplabeltext [\s!ar] [\v!hencefore=كما وضحنا سابقا]
+\setuplabeltext [\s!ar] [\v!hereafter=كما نوضح لاحقا]
+\setuplabeltext [\s!ar] [\v!see=انظر ]
+
+%D ... and to be completed!
+
+%D \ShowAllLanguageValues [\s!ar] [arabic] {Arabic} {horn} % engelse humor
+
+\protect \endinput
diff --git a/tex/context/base/lang-art.tex b/tex/context/base/lang-art.tex
new file mode 100644
index 000000000..e8be91630
--- /dev/null
+++ b/tex/context/base/lang-art.tex
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=lang--art,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Artificial Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Artificial Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+
+% Esperanto
+
+\unprotect
+
+\protect \endinput
diff --git a/tex/context/base/lang-bal.tex b/tex/context/base/lang-bal.tex
new file mode 100644
index 000000000..394e9d93c
--- /dev/null
+++ b/tex/context/base/lang-bal.tex
@@ -0,0 +1,118 @@
+%D \module
+%D [ file=lang-bal,
+%D version=2010.01.21,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Baltic Languages,
+%D author=Marius Aleknevičius,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Baltic Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D all the translations were done by Marius Aleknevičius. If
+%D you have suggestions, don't hesitate to send us an email.
+
+%D This file is in \UTF\ encoding and is meant for \MKIV.
+
+% Lettish/Latvian, Lietuvių/Lithuanian
+
+\unprotect
+
+\installlanguage
+ [\s!lt]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\lowerleftdoubleninequote,
+ \c!rightquote=\upperrightdoublesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!year,~m.,\ ,\v!month,\ ,\v!day,~d.},
+ \s!patterns=\s!lt,
+ \s!encoding=l7x,
+ \s!mapping=l7x,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2]
+
+\installlanguage [lithuanian] [\s!lt]
+
+\setupheadtext [\s!lt] [\v!content=Turinys]
+\setupheadtext [\s!lt] [\v!tables=Lentelės]
+\setupheadtext [\s!lt] [\v!figures=Iliustracijos]
+\setupheadtext [\s!lt] [\v!graphics=Graphics] % TODO what is the difference between the "graphics" and the "figures"?
+\setupheadtext [\s!lt] [\v!intermezzi=Intermezzos] % TODO what is the "intermezzi"?
+\setupheadtext [\s!lt] [\v!index=Rodyklė]
+\setupheadtext [\s!lt] [\v!abbreviations=Santrumpos]
+\setupheadtext [\s!lt] [\v!logos=Logos] % TODO where it is used?
+\setupheadtext [\s!lt] [\v!units=Units] % TODO where it is used?
+\setupheadtext [\s!lt] [pubs=Literatūra]
+
+\setuplabeltext [\s!lt] [\v!table={, lentelė.}]
+\setuplabeltext [\s!lt] [\v!figure={, pav.}]
+\setuplabeltext [\s!lt] [\v!intermezzo=Intermezzo ] % TODO
+\setuplabeltext [\s!lt] [\v!graphic=Graphic ] % TODO
+
+%\startlanguagespecifics[\s!lt]
+% \setupheads[\c!sectionstopper=.] %TODO how do I set dots after section numbers?
+%\stoplanguagespecifics
+
+\setuplabeltext [\s!lt] [\v!chapter=] % Chapter
+\setuplabeltext [\s!lt] [\v!section=]
+\setuplabeltext [\s!lt] [\v!subsection=]
+\setuplabeltext [\s!lt] [\v!subsubsection=]
+\setuplabeltext [\s!lt] [\v!subsubsubsection=]
+\setuplabeltext [\s!lt] [\v!appendix=] % Appendix
+\setuplabeltext [\s!lt] [\v!part={, dalis}]
+\setuplabeltext [\s!lt] [\v!line=line ] % TODO where it is used?
+\setuplabeltext [\s!lt] [\v!lines=lines ] % TODO where it is used?
+
+\setuplabeltext [\s!lt] [\v!january=sausio]
+\setuplabeltext [\s!lt] [\v!february=vasario]
+\setuplabeltext [\s!lt] [\v!march=kovo]
+\setuplabeltext [\s!lt] [\v!april=balandžio]
+\setuplabeltext [\s!lt] [\v!may=gegužės]
+\setuplabeltext [\s!lt] [\v!june=birželio]
+\setuplabeltext [\s!lt] [\v!july=liepos]
+\setuplabeltext [\s!lt] [\v!august=rugpjūčio]
+\setuplabeltext [\s!lt] [\v!september=rugsėjo]
+\setuplabeltext [\s!lt] [\v!october=spalio]
+\setuplabeltext [\s!lt] [\v!november=lapkričio]
+\setuplabeltext [\s!lt] [\v!december=gruodžio]
+
+\setuplabeltext [\s!lt] [\v!sunday=sekmadienis]
+\setuplabeltext [\s!lt] [\v!monday=pirmadienis]
+\setuplabeltext [\s!lt] [\v!tuesday=antradienis]
+\setuplabeltext [\s!lt] [\v!wednesday=trečiadienis]
+\setuplabeltext [\s!lt] [\v!thursday=ketvirtadienis]
+\setuplabeltext [\s!lt] [\v!friday=penktadienis]
+\setuplabeltext [\s!lt] [\v!saturday=šeštadienis]
+
+\setuplabeltext [\s!lt] [\v!page=puslapis ] % TODO how to test?
+\setuplabeltext [\s!lt] [\v!atpage=puslapyje ] % TODO how to test?
+\setuplabeltext [\s!lt] [\v!hencefore=kaip parodyta aukščiau] % TODO how to test?
+\setuplabeltext [\s!lt] [\v!hereafter=kaip parodyta žemiau] % TODO how to test?
+\setuplabeltext [\s!lt] [\v!see=žiūrėti ] % TODO how to test?
+
+\setuplabeltext [\s!lt] [\v!january :\s!mnem=jan] % I think, there is no abbreviated versions of months in lithuanian
+\setuplabeltext [\s!lt] [\v!february :\s!mnem=feb]
+\setuplabeltext [\s!lt] [\v!march :\s!mnem=mar]
+\setuplabeltext [\s!lt] [\v!april :\s!mnem=apr]
+\setuplabeltext [\s!lt] [\v!may :\s!mnem=may]
+\setuplabeltext [\s!lt] [\v!june :\s!mnem=jun]
+\setuplabeltext [\s!lt] [\v!july :\s!mnem=jul]
+\setuplabeltext [\s!lt] [\v!august :\s!mnem=aug]
+\setuplabeltext [\s!lt] [\v!september:\s!mnem=sep]
+\setuplabeltext [\s!lt] [\v!october :\s!mnem=oct]
+\setuplabeltext [\s!lt] [\v!november :\s!mnem=nov]
+\setuplabeltext [\s!lt] [\v!december :\s!mnem=dec]
+
+%D \ShowAllLanguageValues [\s!lt] [lithuanian] {Lithuanian} {doll} % What does this mean? Do I need it?
+
+\protect \endinput
diff --git a/tex/context/base/lang-cel.tex b/tex/context/base/lang-cel.tex
new file mode 100644
index 000000000..4d93957f1
--- /dev/null
+++ b/tex/context/base/lang-cel.tex
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=lang-cel,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Celtic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Celtic Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+
+% Breton, Welsh, Irish, Manx, Scottish Gaelic
+
+\unprotect
+
+\protect \endinput
diff --git a/tex/context/base/lang-chi.mkii b/tex/context/base/lang-chi.mkii
new file mode 100644
index 000000000..278e10745
--- /dev/null
+++ b/tex/context/base/lang-chi.mkii
@@ -0,0 +1,305 @@
+%D \module
+%D [ file=lang-chi,
+%D version=2002.06.25, % 1998.10.10,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Chinese,
+%D author={Hans Hagen \& Wang Lei},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Chinese}
+
+%D This module is coded using the \UNICODE\ support built in
+%D \CONTEXT. Therefore, \type {\uchar} is used instead of latin
+%D characters.
+
+\unprotect
+
+\definesystemconstant {chinese} \definesystemconstant {cn}
+
+\installlanguage
+ [\s!cn]
+ [\c!leftsentence=\cnencoding\cnleftsentence,
+ \c!rightsentence=\cnencoding\cnrightsentence,
+ \c!leftsubsentence=\cnencoding\cnleftsubsentence,
+ \c!rightsubsentence=\cnencoding\cnrightsubsentence,
+ \c!leftquote=\cnencoding\cnupperleftsinglequote,
+ \c!rightquote=\cnencoding\cnupperrightsinglequote,
+ \c!leftquotation=\cnencoding\cnupperleftdoublequote,
+ \c!rightquotation=\cnencoding\cnupperrightdoublequote,
+ \c!date={\v!year,\cnyear,\ ,\v!month,\v!day,\cnday}]
+
+\setupheadtext [\s!cn] [\v!content={\cnencoding\cnencodedcontents}]
+\setupheadtext [\s!cn] [\v!tables={\cnencoding\cnencodedtables}]
+\setupheadtext [\s!cn] [\v!figures={\cnencoding\cnencodedfigures}]
+\setupheadtext [\s!cn] [\v!graphics={\cnencoding\cnencodedgraphics}]% RG & XJF
+\setupheadtext [\s!cn] [\v!intermezzi={\cnencoding\cnencodedintermezzo}]% RG & XJF
+\setupheadtext [\s!cn] [\v!index={\cnencoding\cnencodedindex}]
+\setupheadtext [\s!cn] [\v!abbreviations={\cnencoding\cnencodedabbreviations}]
+\setupheadtext [\s!cn] [\v!logos={\cnencoding\cnencodedlogos}]
+\setupheadtext [\s!cn] [\v!units={\cnencoding\cnencodedunits}]
+
+\setuplabeltext [\s!cn] [\v!table={\cnencoding\cnencodedtable}]
+\setuplabeltext [\s!cn] [\v!figure={\cnencoding\cnencodedfigure}]
+\setuplabeltext [\s!cn] [\v!intermezzo={\cnencoding\cnencodedintermezzo}]% RG & XJF
+\setuplabeltext [\s!cn] [\v!graphic={\cnencoding\cnencodedillustration}]% RG & XJF
+\setuplabeltext [\s!cn] [\v!appendix={\cnencoding\cnencodedappendix}]% RG
+\setuplabeltext [\s!cn] [\v!part={\cnencoding\cnencodedintro,\cnencoding\cnencodedpart}]
+\setuplabeltext [\s!cn] [\v!chapter={\cnencoding\cnencodedintro,\cnencoding\cnencodedchapter}]
+\setuplabeltext [\s!cn] [\v!section={\cnencoding\cnencodedintro,\cnencoding\cnencodedsection}]
+\setuplabeltext [\s!cn] [\v!line={\cnencoding\cnencodedline}]% RG & XJF
+\setuplabeltext [\s!cn] [\v!lines={\cnencoding\cnencodedline}]% RG & XJF
+
+\setuplabeltext [\s!cn] [\v!subsection=]
+\setuplabeltext [\s!cn] [\v!subsubsection=]
+\setuplabeltext [\s!cn] [\v!subsubsubsection=]
+
+%D From this definition one can deduce that language, input
+%D encoding, font encoding, and glyph meaning form a pretty
+%D complex four dimensional space.
+
+\startlanguagespecifics[\s!cn]
+
+\setuplabeltext [\s!cn] [\v!january=\cnencoding\cnencodedjanuary ]
+\setuplabeltext [\s!cn] [\v!february=\cnencoding\cnencodedfebrary ]
+\setuplabeltext [\s!cn] [\v!march=\cnencoding\cnencodedmarch ]
+\setuplabeltext [\s!cn] [\v!april=\cnencoding\cnencodedapril ]
+\setuplabeltext [\s!cn] [\v!may=\cnencoding\cnencodedmay ]
+\setuplabeltext [\s!cn] [\v!june=\cnencoding\cnencodedjune ]
+\setuplabeltext [\s!cn] [\v!july=\cnencoding\cnencodedjuly ]
+\setuplabeltext [\s!cn] [\v!august=\cnencoding\cnencodedaugust ]
+\setuplabeltext [\s!cn] [\v!september=\cnencoding\cnencodedseptember]
+\setuplabeltext [\s!cn] [\v!october=\cnencoding\cnencodedoctober ]
+\setuplabeltext [\s!cn] [\v!november=\cnencoding\cnencodednovember ]
+\setuplabeltext [\s!cn] [\v!december=\cnencoding\cnencodeddecember ]
+
+\setuplabeltext [\s!cn] [\v!sunday=\cnencoding\cnencodedsunday ]
+\setuplabeltext [\s!cn] [\v!monday=\cnencoding\cnencodedmonday ]
+\setuplabeltext [\s!cn] [\v!tuesday=\cnencoding\cnencodedtuesday ]
+\setuplabeltext [\s!cn] [\v!wednesday=\cnencoding\cnencodedwednesday]
+\setuplabeltext [\s!cn] [\v!thursday=\cnencoding\cnencodedthursday ]
+\setuplabeltext [\s!cn] [\v!friday=\cnencoding\cnencodedfriday ]
+\setuplabeltext [\s!cn] [\v!saturday=\cnencoding\cnencodedsaturday ]
+
+\stoplanguagespecifics
+
+%D One can specify a split labeltext, as demonstrated in
+%D the definition of the \type {part} label. Unfortunately
+%D the glyphs of both part depend on the encoding. Therefore,
+%D we have an encoding section here.
+
+\unexpanded\def\cnencoding{\enableencoding[\chineseencoding]} % ugly and temporary
+
+\startencoding[cjk-uni]
+ \definecommand cnleftsentence {\uchar{32}{20}\uchar{32}{20}}
+ \definecommand cnrightsentence {\uchar{32}{20}\uchar{32}{20}}
+ \definecommand cnleftsubsentence {\uchar{32}{20}\uchar{32}{20}}
+ \definecommand cnrightsubsentence {\uchar{32}{20}\uchar{32}{20}}
+ \definecommand cnupperleftsinglequote {\uchar{32}{24}}
+ \definecommand cnupperrightsinglequote {\uchar{32}{25}}
+ \definecommand cnupperleftdoublequote {\uchar{32}{28}}
+ \definecommand cnupperrightdoublequote {\uchar{32}{29}}
+ \definecommand cnupperleftsinglequote-v {\uchar{48}{12}}
+ \definecommand cnupperrightsinglequote-v {\uchar{48}{13}}
+ \definecommand cnupperleftdoublequote-v {\uchar{48}{14}}
+ \definecommand cnupperrightdoublequote-v {\uchar{48}{15}}
+ \definecommand cnencodedcontents {\uchar{118}{238}\uchar{95}{85}}
+ \definecommand cnencodedtables {\uchar{136}{104}\uchar{104}{60}}
+ \definecommand cnencodedfigures {\uchar{86}{254}\uchar{95}{98}}
+ \definecommand cnencodedindex {\uchar{125}{34}\uchar{95}{21}}
+ \definecommand cnencodedabbreviations {\uchar{127}{41}\uchar{117}{101}\uchar{139}{237}}
+ \definecommand cnencodedlogos {\uchar{95}{189}\uchar{141}{44}}
+ \definecommand cnencodedunits {\uchar{139}{161}\uchar{145}{207}\uchar{83}{85}\uchar{79}{77}}
+ \definecommand cnencodedtable {\uchar{136}{104}}
+ \definecommand cnencodedfigure {\uchar{86}{254}}
+ \definecommand cnencodedintro {\uchar{123}{44}}
+ \definecommand cnencodedpart {\uchar{144}{232}\uchar{82}{6}}
+ \definecommand cnencodedchapter {\uchar{122}{224}}
+ \definecommand cnencodedsection {\uchar{130}{130}}
+ \definecommand cnencodedjanuary {\uchar{78}{0}\uchar{103}{8}}
+ \definecommand cnencodedfebrary {\uchar{78}{140}\uchar{103}{8}}
+ \definecommand cnencodedmarch {\uchar{78}{9}\uchar{103}{8}}
+ \definecommand cnencodedapril {\uchar{86}{219}\uchar{103}{8}}
+ \definecommand cnencodedmay {\uchar{78}{148}\uchar{103}{8}}
+ \definecommand cnencodedjune {\uchar{81}{109}\uchar{103}{8}}
+ \definecommand cnencodedjuly {\uchar{78}{3}\uchar{103}{8}}
+ \definecommand cnencodedaugust {\uchar{81}{107}\uchar{103}{8}}
+ \definecommand cnencodedseptember {\uchar{78}{93}\uchar{103}{8}}
+ \definecommand cnencodedoctober {\uchar{83}{65}\uchar{103}{8}}
+ \definecommand cnencodednovember {\uchar{83}{65}\uchar{78}{0}\uchar{103}{8}}
+ \definecommand cnencodeddecember {\uchar{83}{65}\uchar{78}{140}\uchar{103}{8}}
+ \definecommand cnencodedsunday {\uchar{102}{31}\uchar{103}{31}\uchar{101}{229}}
+ \definecommand cnencodedmonday {\uchar{102}{31}\uchar{103}{31}\uchar{78}{0}}
+ \definecommand cnencodedtuesday {\uchar{102}{31}\uchar{103}{31}\uchar{78}{140}}
+ \definecommand cnencodedwednesday {\uchar{102}{31}\uchar{103}{31}\uchar{78}{9}}
+ \definecommand cnencodedthursday {\uchar{102}{31}\uchar{103}{31}\uchar{86}{219}}
+ \definecommand cnencodedfriday {\uchar{102}{31}\uchar{103}{31}\uchar{78}{148}}
+ \definecommand cnencodedsaturday {\uchar{102}{31}\uchar{103}{31}\uchar{81}{109}}
+ % RG & XJF
+ \definecommand cnencodedgraphics {\uchar{86}{254}}
+ \definecommand cnencodedintermezzo {\uchar{210}{99}\uchar{242}{102}}
+ \definecommand cnencodedillustration {\uchar{99}{210}\uchar{86}{254}}
+ \definecommand cnencodedappendix {\uchar{150}{68}\uchar{95}{85}}
+ \definecommand cnencodedline {\uchar{136}{76}}
+ % Tobias Burnus & XJF
+ \definecommand cnyear {\uchar{94}{116}}
+ \definecommand cnmonth {\uchar{103}{8}}
+ \definecommand cnday {\uchar{101}{229}}
+\stopencoding
+
+\startencoding[gbk]
+ \definecommand cnleftsentence {\uchar{161}{170}\uchar{161}{170}}
+ \definecommand cnrightsentence {\uchar{161}{170}\uchar{161}{170}}
+ \definecommand cnleftsubsentence {\uchar{161}{170}\uchar{161}{170}}
+ \definecommand cnrightsubsentence {\uchar{161}{170}\uchar{161}{170}}
+ \definecommand cnupperleftsinglequote {\uchar{161}{174}}
+ \definecommand cnupperrightsinglequote {\uchar{161}{175}}
+ \definecommand cnupperleftdoublequote {\uchar{161}{176}}
+ \definecommand cnupperrightdoublequote {\uchar{161}{177}}
+ \definecommand cnupperleftsinglequote-v {\uchar{161}{184}}
+ \definecommand cnupperrightsinglequote-v {\uchar{161}{185}}
+ \definecommand cnupperleftdoublequote-v {\uchar{161}{186}}
+ \definecommand cnupperrightdoublequote-v {\uchar{161}{187}}
+ \definecommand cnencodedcontents {\uchar{196}{191}\uchar{194}{188}}
+ \definecommand cnencodedtables {\uchar{177}{237}\uchar{184}{241}}
+ \definecommand cnencodedfigures {\uchar{205}{188}\uchar{208}{206}}
+ \definecommand cnencodedindex {\uchar{203}{247}\uchar{210}{253}}
+ \definecommand cnencodedabbreviations {\uchar{203}{245}\uchar{194}{212}\uchar{211}{239}}
+ \definecommand cnencodedlogos {\uchar{187}{213}\uchar{177}{225}}
+ \definecommand cnencodedunits {\uchar{188}{198}\uchar{193}{191}\uchar{181}{165}\uchar{206}{187}}
+ \definecommand cnencodedtable {\uchar{177}{237}}
+ \definecommand cnencodedfigure {\uchar{205}{188}}
+ \definecommand cnencodedintro {\uchar{181}{218}}
+ \definecommand cnencodedpart {\uchar{178}{191}\uchar{183}{214}}
+ \definecommand cnencodedchapter {\uchar{213}{194}}
+ \definecommand cnencodedsection {\uchar{189}{218}}
+ \definecommand cnencodedjanuary {\uchar{210}{187}\uchar{212}{194}}
+ \definecommand cnencodedfebrary {\uchar{182}{254}\uchar{212}{194}}
+ \definecommand cnencodedmarch {\uchar{200}{253}\uchar{212}{194}}
+ \definecommand cnencodedapril {\uchar{203}{196}\uchar{212}{194}}
+ \definecommand cnencodedmay {\uchar{206}{229}\uchar{212}{194}}
+ \definecommand cnencodedjune {\uchar{193}{249}\uchar{212}{194}}
+ \definecommand cnencodedjuly {\uchar{198}{223}\uchar{212}{194}}
+ \definecommand cnencodedaugust {\uchar{176}{203}\uchar{212}{194}}
+ \definecommand cnencodedseptember {\uchar{190}{197}\uchar{212}{194}}
+ \definecommand cnencodedoctober {\uchar{202}{174}\uchar{212}{194}}
+ \definecommand cnencodednovember {\uchar{202}{174}\uchar{210}{187}\uchar{212}{194}}
+ \definecommand cnencodeddecember {\uchar{202}{174}\uchar{182}{254}\uchar{212}{194}}
+ \definecommand cnencodedsunday {\uchar{208}{199}\uchar{198}{218}\uchar{200}{213}}
+ \definecommand cnencodedmonday {\uchar{208}{199}\uchar{198}{218}\uchar{210}{187}}
+ \definecommand cnencodedtuesday {\uchar{208}{199}\uchar{198}{218}\uchar{182}{254}}
+ \definecommand cnencodedwednesday {\uchar{208}{199}\uchar{198}{218}\uchar{200}{253}}
+ \definecommand cnencodedthursday {\uchar{208}{199}\uchar{198}{218}\uchar{203}{196}}
+ \definecommand cnencodedfriday {\uchar{208}{199}\uchar{198}{218}\uchar{206}{229}}
+ \definecommand cnencodedsaturday {\uchar{208}{199}\uchar{198}{218}\uchar{193}{249}}
+ % RG & XJF
+ \definecommand cnencodedgraphics {\uchar{205}{188}}
+ \definecommand cnencodedintermezzo {\uchar{178}{229}\uchar{199}{250}}
+ \definecommand cnencodedillustration {\uchar{178}{229}\uchar{205}{188}}
+ \definecommand cnencodedappendix {\uchar{184}{189}\uchar{194}{188}}
+ \definecommand cnencodedline {\uchar{208}{208}}
+ % Tobias Burnus & XJF
+ \definecommand cnyear {\uchar{196}{234}}
+ \definecommand cnmonth {\uchar{212}{194}}
+ \definecommand cnday {\uchar{200}{213}}
+\stopencoding
+
+\startencoding[big5]
+ \definecommand cnleftsentence {\uchar{162}{119}\uchar{162}{119}}
+ \definecommand cnrightsentence {\uchar{162}{119}\uchar{162}{119}}
+ \definecommand cnleftsubsentence {\uchar{162}{119}\uchar{162}{119}}
+ \definecommand cnrightsubsentence {\uchar{162}{119}\uchar{162}{119}}
+ \definecommand cnupperleftsinglequote {\uchar{161}{165}}
+ \definecommand cnupperrightsinglequote {\uchar{161}{166}}
+ \definecommand cnupperleftdoublequote {\uchar{161}{167}}
+ \definecommand cnupperrightdoublequote {\uchar{161}{168}}
+ \definecommand cnupperleftsinglequote-v {\uchar{161}{117}}
+ \definecommand cnupperrightsinglequote-v {\uchar{161}{118}}
+ \definecommand cnupperleftdoublequote-v {\uchar{161}{121}}
+ \definecommand cnupperrightdoublequote-v {\uchar{161}{122}}
+ \definecommand cnencodecontents {\uchar{165}{216}\uchar{191}{253}}
+ \definecommand cnencodetables {\uchar{170}{237}\uchar{174}{230}}
+ \definecommand cnencodefigures {\uchar{185}{207}\uchar{167}{206}}
+ \definecommand cnencodeindex {\uchar{175}{193}\uchar{174}{222}}
+ \definecommand cnencodeabbreviations {\uchar{191}{89}\uchar{178}{164}\uchar{187}{121}}
+ \definecommand cnencodelogos {\uchar{192}{178}\uchar{188}{208}}
+ \definecommand cnencodeunits {\uchar{173}{112}\uchar{182}{113}\uchar{179}{230}\uchar{166}{236}}
+ \definecommand cnencodetable {\uchar{170}{237}}
+ \definecommand cnencodefigure {\uchar{185}{207}}
+ \definecommand cnencodedintro {\uchar{178}{196}}
+ \definecommand cnencodedpart {\uchar{179}{161}\uchar{164}{192}}
+ \definecommand cnencodedchapter {\uchar{179}{185}}
+ \definecommand cnencodedsection {\uchar{184} {96}}
+ \definecommand cnencodedjanuary {\uchar{164} {64}\uchar{164}{235}}
+ \definecommand cnencodedfebrary {\uchar{164} {71}\uchar{164}{235}}
+ \definecommand cnencodedmarch {\uchar{164} {84}\uchar{164}{235}}
+ \definecommand cnencodedapril {\uchar{165}{124}\uchar{164}{235}}
+ \definecommand cnencodedmay {\uchar{164}{173}\uchar{164}{235}}
+ \definecommand cnencodedjune {\uchar{164}{187}\uchar{164}{235}}
+ \definecommand cnencodedjuly {\uchar{164} {67}\uchar{164}{235}}
+ \definecommand cnencodedaugust {\uchar{164} {75}\uchar{164}{235}}
+ \definecommand cnencodedseptember {\uchar{164} {69}\uchar{164}{235}}
+ \definecommand cnencodedoctober {\uchar{164} {81}\uchar{164}{235}}
+ \definecommand cnencodednovember {\uchar{164} {81}\uchar{164} {64}\uchar{164}{235}}
+ \definecommand cnencodeddecember {\uchar{164} {81}\uchar{164} {71}\uchar{164}{235}}
+ \definecommand cnencodedsunday {\uchar{172} {80}\uchar{180}{193}\uchar{164}{233}}
+ \definecommand cnencodedmonday {\uchar{172} {80}\uchar{180}{193}\uchar{164} {64}}
+ \definecommand cnencodedtuesday {\uchar{172} {80}\uchar{180}{193}\uchar{164} {71}}
+ \definecommand cnencodedwednesday {\uchar{172} {80}\uchar{180}{193}\uchar{164} {84}}
+ \definecommand cnencodedthursday {\uchar{172} {80}\uchar{180}{193}\uchar{165}{124}}
+ \definecommand cnencodedfriday {\uchar{172} {80}\uchar{180}{193}\uchar{164}{173}}
+ \definecommand cnencodedsaturday {\uchar{172} {80}\uchar{180}{193}\uchar{164}{187}}
+ % Tobias Burnus &\XJF
+ \definecommand cnyear {\uchar{166}{126}}
+ \definecommand cnmonth {\uchar{164}{235}}
+ \definecommand cnday {\uchar{164}{233}}
+
+% Traditional Chinese characters (only where they differ to the
+% simplified ones) for lang-chi.tex and font-chi.tex.
+
+% \startencoding[cjk-uni]
+% \defineudigit 10000 132 44
+% \defineudigit 100000000 81 4
+
+% \definecommand cnencodedsection {\uchar{123}{192}}
+% \definecommand cnencodedfigure {\uchar{87}{22}}
+% \definecommand cnencodedunits {\uchar{138}{8}\uchar{145}{207}\uchar{85}{174}\uchar{79}{77}}
+% \definecommand cnencodedlogos {\uchar{95}{189}\uchar{140}{182}}
+% \definecommand cnencodedabbreviations {\uchar{126}{46}\uchar{117}{101}\uchar{138}{158}}
+% \definecommand cnencodedfigures {\uchar{87}{22}\uchar{95}{98}}
+% \definecommand cnencodedcontents {\uchar{118}{238}\uchar{147}{4}}
+% \stopencoding
+
+% \startencoding[gbk]
+% \defineudigit 10000 200 102
+% \defineudigit 100000000 131 124
+
+% \definecommand cnencodedsection {\uchar{185}{157}}
+% \definecommand cnencodedfigure {\uchar{136}{68}}
+% \definecommand cnencodedunits {\uchar{211}{139}\uchar{193}{191}\uchar{134}{206}\uchar{206}{187}}
+% \definecommand cnencodedlogos {\uchar{187}{213}\uchar{217}{72}
+% \definecommand cnencodedabbreviations {\uchar{191}{115}\uchar{194}{212}\uchar{213}{90}}
+% \definecommand cnencodedfigures {\uchar{136}{68}\uchar{208}{206}}
+% \definecommand cnencodedcontents {\uchar{196}{191}\uchar{228}{155}}
+% \stopencoding
+
+% \startencoding[big5]
+% \defineudigit 10000 184 85
+% \defineudigit 100000000 187 245
+
+% \definecommand cnencodedsection {\uchar{184}{96}}
+% \definecommand cnencodedfigure {\uchar{185}{207}}
+% \definecommand cnencodedunits {\uchar{173}{112}\uchar{182}{113}\uchar{179}{230}\uchar{166}{236}}
+% \definecommand cnencodedlogos {\uchar{192}{178}\uchar{182}{83}}
+% \definecommand cnencodedabbreviations {\uchar{193}{89}\uchar{178}{164}\uchar{187}{121}}
+% \definecommand cnencodedfigures {\uchar{185}{207}\uchar{167}{206}}
+% \definecommand cnencodedcontents {\uchar{165}{216}\uchar{191}{253}}
+% \stopencoding
+
+\stopencoding
+
+\protect \endinput
diff --git a/tex/context/base/lang-cjk.mkiv b/tex/context/base/lang-cjk.mkiv
new file mode 100644
index 000000000..5f736d4a1
--- /dev/null
+++ b/tex/context/base/lang-cjk.mkiv
@@ -0,0 +1,328 @@
+%D \module
+%D [ file=lang-chi,
+%D version=2009.03.02,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Chinese,
+%D author={Hans Hagen \& Wang Lei},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Derived from \MKII\ files.
+
+\writestatus{loading}{ConTeXt Language Macros / CJK}
+
+\definesystemconstant {chinese} \definesystemconstant {cn}
+\definesystemconstant {japanese} \definesystemconstant {ja}
+\definesystemconstant {korean} \definesystemconstant {kr}
+
+\unprotect
+
+% Chinese
+
+\installlanguage
+ [\s!cn]
+ [\c!leftsentence=——,
+ \c!rightsentence=——,
+ \c!leftsubsentence=——,
+ \c!rightsubsentence=——,
+ \c!leftquote=‘,
+ \c!rightquote=’,
+ \c!leftquotation=“,
+ \c!rightquotation=”,
+ \c!date={\v!year,年,\ ,\v!month,\v!day,日}]
+
+\setupheadtext [\s!cn] [\v!content=目录]
+\setupheadtext [\s!cn] [\v!tables=表格]
+\setupheadtext [\s!cn] [\v!figures=图形]
+\setupheadtext [\s!cn] [\v!graphics=图]
+\setupheadtext [\s!cn] [\v!intermezzi=퉣]
+\setupheadtext [\s!cn] [\v!index=索引]
+\setupheadtext [\s!cn] [\v!abbreviations=缩略语]
+\setupheadtext [\s!cn] [\v!logos=徽贬]
+\setupheadtext [\s!cn] [\v!units=计量单位]
+
+\setuplabeltext [\s!cn] [\v!table=表]
+\setuplabeltext [\s!cn] [\v!figure=图]
+\setuplabeltext [\s!cn] [\v!intermezzo=퉣]
+\setuplabeltext [\s!cn] [\v!graphic=插图]
+\setuplabeltext [\s!cn] [\v!appendix=附录]
+\setuplabeltext [\s!cn] [\v!part={第,部分}]
+\setuplabeltext [\s!cn] [\v!chapter={第,章}]
+\setuplabeltext [\s!cn] [\v!section={第,节}]
+\setuplabeltext [\s!cn] [\v!line=行]
+\setuplabeltext [\s!cn] [\v!lines=行]
+
+\setuplabeltext [\s!cn] [\v!subsection=]
+\setuplabeltext [\s!cn] [\v!subsubsection=]
+\setuplabeltext [\s!cn] [\v!subsubsubsection=]
+
+\setuplabeltext [\s!cn] [\v!january=一月]
+\setuplabeltext [\s!cn] [\v!february=二月]
+\setuplabeltext [\s!cn] [\v!march=三月]
+\setuplabeltext [\s!cn] [\v!april=四月]
+\setuplabeltext [\s!cn] [\v!may=五月]
+\setuplabeltext [\s!cn] [\v!june=六月]
+\setuplabeltext [\s!cn] [\v!july=七月]
+\setuplabeltext [\s!cn] [\v!august=八月]
+\setuplabeltext [\s!cn] [\v!september=九月]
+\setuplabeltext [\s!cn] [\v!october=十月]
+\setuplabeltext [\s!cn] [\v!november=十一月]
+\setuplabeltext [\s!cn] [\v!december=十二月]
+
+\setuplabeltext [\s!cn] [\v!sunday=星期日]
+\setuplabeltext [\s!cn] [\v!monday=星期一]
+\setuplabeltext [\s!cn] [\v!tuesday=星期二]
+\setuplabeltext [\s!cn] [\v!wednesday=星期三]
+\setuplabeltext [\s!cn] [\v!thursday=星期四]
+\setuplabeltext [\s!cn] [\v!friday=星期五]
+\setuplabeltext [\s!cn] [\v!saturday=星期六]
+
+%D Japanese
+
+\installlanguage
+ [\s!ja]
+ [\c!leftsentence=——,
+ \c!rightsentence=——,
+ \c!leftsubsentence=——,
+ \c!rightsubsentence=——,
+ \c!leftquote=‘,
+ \c!rightquote=’,
+ \c!leftquotation=「,
+ \c!rightquotation=」,
+ \c!date={西暦,\v!year,年,\v!month,月,\v!day,日}]
+
+\setupheadtext [\s!ja] [\v!content=目次]
+\setupheadtext [\s!ja] [\v!tables=机]
+\setupheadtext [\s!ja] [\v!figures=図]
+\setupheadtext [\s!ja] [\v!graphics=グラフ]
+\setupheadtext [\s!ja] [\v!intermezzi=間奏曲]
+\setupheadtext [\s!ja] [\v!index=目次]
+\setupheadtext [\s!ja] [\v!abbreviations=略語]
+\setupheadtext [\s!ja] [\v!logos=理性]
+\setupheadtext [\s!ja] [\v!units=ユニッツ]
+
+\setuplabeltext [\s!ja] [\v!table=表]
+\setuplabeltext [\s!ja] [\v!figure=図]
+\setuplabeltext [\s!ja] [\v!intermezzo=間奏曲]
+\setuplabeltext [\s!ja] [\v!graphic=イラスト]
+\setuplabeltext [\s!ja] [\v!appendix=付録]
+\setuplabeltext [\s!ja] [\v!part={第,パート}]
+\setuplabeltext [\s!ja] [\v!chapter={第,章}]
+\setuplabeltext [\s!ja] [\v!section={第,項}]
+\setuplabeltext [\s!ja] [\v!line=線]
+\setuplabeltext [\s!ja] [\v!lines=線]
+
+\setuplabeltext [\s!ja] [\v!subsection=]
+\setuplabeltext [\s!ja] [\v!subsubsection=]
+\setuplabeltext [\s!ja] [\v!subsubsubsection=]
+
+\setuplabeltext [\s!ja] [\v!january=1]
+\setuplabeltext [\s!ja] [\v!february=2]
+\setuplabeltext [\s!ja] [\v!march=3]
+\setuplabeltext [\s!ja] [\v!april=4]
+\setuplabeltext [\s!ja] [\v!may=5]
+\setuplabeltext [\s!ja] [\v!june=6]
+\setuplabeltext [\s!ja] [\v!july=7]
+\setuplabeltext [\s!ja] [\v!august=8]
+\setuplabeltext [\s!ja] [\v!september=9]
+\setuplabeltext [\s!ja] [\v!october=10]
+\setuplabeltext [\s!ja] [\v!november=11]
+\setuplabeltext [\s!ja] [\v!december=12]
+
+\setuplabeltext [\s!ja] [\v!monday=月曜日]
+\setuplabeltext [\s!ja] [\v!tuesday=火曜日]
+\setuplabeltext [\s!ja] [\v!wednesday=水曜日]
+\setuplabeltext [\s!ja] [\v!thursday=木曜日]
+\setuplabeltext [\s!ja] [\v!friday=金曜日]
+\setuplabeltext [\s!ja] [\v!saturday=土曜日]
+\setuplabeltext [\s!ja] [\v!sunday=日曜日]
+
+%D Korean
+
+% todo
+
+\protect \endinput
+
+cn={
+ ["abbreviations"]="缩略语",
+ ["appendix"]="附录",
+ ["april"]="四月",
+ ["august"]="八月",
+ ["chapter"]="章",
+ ["contents"]="目录",
+ ["day"]="日",
+ ["december"]="十二月",
+ ["febrary"]="二月",
+ ["figure"]="图",
+ ["figures"]="图形",
+ ["friday"]="星期五",
+ ["graphics"]="图",
+ ["illustration"]="插图",
+ ["index"]="索引",
+ ["intermezzo"]="퉣",
+ ["intro"]="第",
+ ["january"]="一月",
+ ["july"]="七月",
+ ["june"]="六月",
+ ["leftsentence"]="——",
+ ["leftsubsentence"]="——",
+ ["line"]="行",
+ ["logos"]="徽贬",
+ ["march"]="三月",
+ ["may"]="五月",
+ ["monday"]="星期一",
+ ["month"]="月",
+ ["november"]="十一月",
+ ["october"]="十月",
+ ["part"]="部分",
+ ["rightsentence"]="——",
+ ["rightsubsentence"]="——",
+ ["saturday"]="星期六",
+ ["section"]="节",
+ ["september"]="九月",
+ ["sunday"]="星期日",
+ ["table"]="表",
+ ["tables"]="表格",
+ ["thursday"]="星期四",
+ ["tuesday"]="星期二",
+ ["units"]="计量单位",
+ ["upperleftdoublequote"]="“",
+ ["upperleftdoublequote-v"]="『",
+ ["upperleftsinglequote"]="‘",
+ ["upperleftsinglequote-v"]="「",
+ ["upperrightdoublequote"]="”",
+ ["upperrightdoublequote-v"]="』",
+ ["upperrightsinglequote"]="’",
+ ["upperrightsinglequote-v"]="」",
+ ["wednesday"]="星期三",
+ ["year"]="年",
+}
+
+ja={
+ ["abbreviations"]="略語",
+ ["abstract"]="概要",
+ ["and"]="、",
+ ["answer"]="答:",
+ ["appendix"]="付録",
+ ["april"]="四月",
+ ["article"]="項目",
+ ["august"]="八月",
+ ["bibliography"]="参考文献",
+ ["book"]="ブック",
+ ["bridgehead"]="項",
+ ["bullet"]="●",
+ ["by"]=":",
+ ["caution"]="注意",
+ ["chapter"]="章",
+ ["christiandate"]="西暦",
+ ["colophon"]="奥付",
+ ["copyright"]="製作著作",
+ ["day"]="日",
+ ["december"]="十二月",
+ ["dedication"]="謝辞",
+ ["edited"]="編者",
+ ["editedby"]="編者:",
+ ["edition"]="編集",
+ ["endquote"]="」",
+ ["equation"]="式",
+ ["example"]="例",
+ ["february"]="二月",
+ ["figure"]="図",
+ ["figures"]="図",
+ ["friday"]="土曜日",
+ ["glossary"]="用語集",
+ ["glosssee"]="参照",
+ ["glossseealso"]="参照",
+ ["graphics"]="グラフ",
+ ["illustration"]="イラスト",
+ ["important"]="重要項目",
+ ["index"]="目次",
+ ["indexsymbols"]="シンボル",
+ ["intermezzo"]="間奏曲",
+ ["intermezzos"]="間奏曲",
+ ["intro"]="第",
+ ["january"]="一月",
+ ["july"]="七月",
+ ["june"]="六月",
+ ["leftsentence"]="——",
+ ["leftsubsentence"]="——",
+ ["line"]="線",
+ ["lines"]="線",
+ ["listofequations"]="式目次",
+ ["listofexamples"]="例目次",
+ ["listoffigures"]="図目次",
+ ["listoftables"]="表目次",
+ ["listofunknown"]="不明目次",
+ ["logos"]="理性",
+ ["march"]="三月",
+ ["may"]="五月",
+ ["monday"]="火曜日",
+ ["month"]="月",
+ ["msgaud"]="対象者",
+ ["msglevel"]="レベル",
+ ["msgorig"]="発信元",
+ ["navhome"]="ホーム",
+ ["navnext"]="次のページ",
+ ["navnextsibling"]="早送り",
+ ["navprev"]="前のページ",
+ ["navprevsibling"]="巻戻し",
+ ["navup"]="上に戻る",
+ ["nestedendquote"]="』",
+ ["nestedstartquote"]="『",
+ ["nonexistantelement"]="要素が存在しません",
+ ["note"]="注意",
+ ["notes"]="注意",
+ ["november"]="十一月",
+ ["october"]="十月",
+ ["pages"]="偧献",
+ ["part"]="パート",
+ ["preface"]="序文",
+ ["procedure"]="手順",
+ ["procedureformal"]="手順",
+ ["productionset"]="プロダクション",
+ ["productionsetformal"]="プロダクション",
+ ["published"]="発行",
+ ["qandadiv"]="問:、答:",
+ ["qandaentry"]="問:",
+ ["question"]="問:",
+ ["reference"]="参照",
+ ["refname"]="名前",
+ ["refsection"]="項",
+ ["refsynopsisdiv"]="概要",
+ ["revhistory"]="改訂履歴",
+ ["revision"]="改訂",
+ ["rightsentence"]="——",
+ ["rightsubsentence"]="——",
+ ["saturday"]="日曜日",
+ ["section"]="項",
+ ["see"]="参照",
+ ["seealso"]="参照",
+ ["separator"]="、",
+ ["september"]="九月",
+ ["set"]="設定",
+ ["setindex"]="目次設定",
+ ["sidebar"]="サイドバー",
+ ["simplesect"]="項",
+ ["singleendquote"]="’",
+ ["singlestartquote"]="‘",
+ ["startquote"]="「",
+ ["step"]="ステップ",
+ ["sunday"]="月曜日",
+ ["table"]="表",
+ ["tablenotes"]="注意",
+ ["tableofcontents"]="目次",
+ ["tables"]="机",
+ ["thursday"]="金曜日",
+ ["tip"]="ティップ",
+ ["tuesday"]="水曜日",
+ ["unexpectedelementname"]="不明な要素名",
+ ["units"]="ユニッツ",
+ ["unsupported"]="サポートしません",
+ ["warning"]="警告",
+ ["wednesday"]="木曜日",
+ ["year"]="年",
+}
diff --git a/tex/context/base/lang-ctx.mkii b/tex/context/base/lang-ctx.mkii
new file mode 100644
index 000000000..09f28dda1
--- /dev/null
+++ b/tex/context/base/lang-ctx.mkii
@@ -0,0 +1,53 @@
+%D \module
+%D [ file=lang-ctx,
+%D version=2005.02.12,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Generic Patterns,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Generic Patterns}
+
+\unprotect
+
+%D The \CONTEXT\ specific patterns are more generic and
+%D are more or less encoding independent. They are generated
+%D from the ones shipped with distributions using:
+%D
+%D \starttyping
+%D ctxtools --pattern --all
+%D \stoptyping
+
+%D In order to get 8 bit characters hyphenated, we need to load
+%D patterns under the right circumstances. In some countries, more
+%D than one font encoding is in use. I can add more defaults here
+%D if users let me know what encoding they use.
+
+% \installlanguage [\s!nl] [\s!mapping={texnansi,ec},\s!encoding={texnansi,ec}]
+% \installlanguage [\s!fr] [\s!mapping={texnansi,ec},\s!encoding={texnansi,ec}]
+% \installlanguage [\s!de] [\s!mapping={texnansi,ec},\s!encoding={texnansi,ec}]
+% \installlanguage [\s!it] [\s!mapping={texnansi,ec},\s!encoding={texnansi,ec}]
+% \installlanguage [\s!pt] [\s!mapping={texnansi,ec},\s!encoding={texnansi,ec}]
+% \installlanguage [\s!hr] [\s!mapping=ec,\s!encoding=ec] % no il2, misses cacute characters
+% \installlanguage [\s!pl] [\s!mapping={pl0,ec,qx},\s!encoding={pl0,ec,qx}] % pl0 may go
+% \installlanguage [\s!cs] [\s!mapping={il2,ec},\s!encoding={il2,ec}] % il2 may go
+% \installlanguage [\s!sk] [\s!mapping={il2,ec},\s!encoding={il2,ec}] % il2 may go
+% \installlanguage [\s!sl] [\s!mapping=ec,\s!encoding=ec] % il2 has gone
+% \installlanguage [\s!vi] [\s!mapping=t5,\s!encoding=t5]
+% \installlanguage [\s!ru] [\s!mapping=t2a,\s!encoding=t2a]
+
+% beware, don't use \setuplanguage here
+
+% \installlanguage[\s!gb][\s!lefthyphenmin=3,\s!righthyphenmin=3] % patterns can only handle this
+% \installlanguage[\s!us][\s!lefthyphenmin=2,\s!righthyphenmin=3] % patterns can only handle this
+
+% greek
+
+% \installlanguage[\s!agr][\s!mapping=\s!agr,\s!encoding=\s!agr]
+
+\protect \endinput
diff --git a/tex/context/base/lang-cyr.tex b/tex/context/base/lang-cyr.tex
new file mode 100644
index 000000000..470402bb1
--- /dev/null
+++ b/tex/context/base/lang-cyr.tex
@@ -0,0 +1,371 @@
+%D \module
+%D [ file=lang-cyr,
+%D version=2003.01.24,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Cyrillic Languages,
+%D author=see below,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Cyrillic Languages}
+
+%D The cyrillic languages always use a dedicated input regime.
+%D Therefore we define the labels using symbolic names.
+%D Support for cyrillic is initiated by Olga Briginets who
+%D also layed the base for the language, encoding and font
+%D definition. Later Alexander Bokovoy and Victor Figurnov
+%D improved things. I (Hans Hagen) mainly cleaned things up
+%D a bit.
+
+\unprotect
+
+\installlanguage
+ [\s!ru]
+ [\s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!spacing=\v!packed,
+ \c!leftsentence=\leftguillemot,
+ \c!rightsentence=\rightguillemot,
+ \c!leftsubsentence=\lowerleftdoubleninequote,
+ \c!rightsubsentence=\upperrightdoubleninequote,
+ \c!leftquote=\lowerleftdoubleninequote,
+ \c!rightquote=\upperrightdoubleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year},
+ \s!mapping=t2a,
+ \s!encoding=t2a]
+
+\installlanguage
+ [\s!ua]
+ [\s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!spacing=\v!packed,
+ \c!leftsentence=\leftguillemot,
+ \c!rightsentence=\rightguillemot,
+ \c!leftsubsentence=\lowerleftdoubleninequote,
+ \c!rightsubsentence=\upperrightdoubleninequote,
+ \c!leftquote=\lowerleftdoubleninequote,
+ \c!rightquote=\upperrightdoubleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year},
+ \s!patterns=\s!uk,
+ \s!mapping=t2a,
+ \s!encoding=t2a]
+
+\installlanguage [russian] [\s!ru]
+\installlanguage [ukrainian] [\s!ua]
+
+%D Labels and header texts.
+
+\setupheadtext [\s!ru] [ \v!content=\cyrillicS \cyrillico \cyrillicd
+ \cyrillice \cyrillicr \cyrilliczh
+ \cyrillica \cyrillicn \cyrillici
+ \cyrillice]
+\setupheadtext [\s!ua] [\v!content=\cyrillicZ \cyrillicm \cyrillicii
+ \cyrillics \cyrillict]
+
+\setupheadtext [\s!ru] [\v!tables=\cyrillicS \cyrillicp \cyrillici
+ \cyrillics \cyrillico \cyrillick
+ \space \cyrillict \cyrillica
+ \cyrillicb \cyrillicl \cyrillici
+ \cyrillicc]
+\setupheadtext [\s!ua] [\v!tables=\cyrillicP \cyrillice \cyrillicr
+ \cyrillice \cyrillicl \cyrillicii
+ \cyrillick \space \cyrillict
+ \cyrillica \cyrillicb \cyrillicl
+ \cyrillici \cyrillicc \cyrillicsftsn]
+
+\setupheadtext [\s!ru] [\v!figures=\cyrillicS \cyrillicp \cyrillici
+ \cyrillics \cyrillico \cyrillick
+ \space \cyrillici \cyrillicl
+ \cyrillicl \cyrillicyu\cyrillics
+ \cyrillict \cyrillicr \cyrillica
+ \cyrillicc \cyrillici \cyrillicishrt]
+\setupheadtext [\s!ua] [\v!figures=\cyrillicP \cyrillice \cyrillicr
+ \cyrillice \cyrillicl \cyrillicii
+ \cyrillick \space \cyrillicii
+ \cyrillicl \cyrillicyu\cyrillics
+ \cyrillict \cyrillicr \cyrillica
+ \cyrillicc \cyrillicii\cyrillicishrt]
+
+\setupheadtext [\s!ru] [\v!graphics=\cyrillicS \cyrillicp \cyrillici
+ \cyrillics \cyrillico \cyrillick
+ \space \cyrillicg \cyrillicr
+ \cyrillica \cyrillicf \cyrillici
+ \cyrillick \cyrillico \cyrillicv]
+\setupheadtext [\s!ua] [\v!graphics=\cyrillicP \cyrillice \cyrillicr
+ \cyrillice \cyrillicl \cyrillicii
+ \cyrillick \space \cyrillicg
+ \cyrillicr \cyrillica \cyrillicf
+ \cyrillicii\cyrillick \cyrillico
+ \cyrillicv]
+
+\setupheadtext [\s!ru] [\v!intermezzi=\cyrillicS \cyrillicp \cyrillici
+ \cyrillics \cyrillico \cyrillick
+ \space \cyrillicv \cyrillics
+ \cyrillict \cyrillica \cyrillicv
+ \cyrillico \cyrillick]
+\setupheadtext [\s!ua] [\v!intermezzi=\cyrillicP \cyrillice \cyrillicr
+ \cyrillice \cyrillicl \cyrillicii
+ \cyrillick \space \cyrillicv
+ \cyrillics \cyrillict \cyrillica
+ \cyrillicv \cyrillico \cyrillick]
+
+\setupheadtext [\s!ru] [\v!index=\cyrillicA \cyrillicl \cyrillicf
+ \cyrillica \cyrillicv \cyrillici
+ \cyrillict \cyrillicn \cyrillicery
+ \cyrillicishrt \space \cyrillicu
+ \cyrillick \cyrillica \cyrillicz
+ \cyrillica \cyrillict \cyrillice
+ \cyrillicl \cyrillicsftsn]
+\setupheadtext [\s!ua] [\v!index=\cyrillicP \cyrillico \cyrillick
+ \cyrillica \cyrilliczh\cyrillicch
+ \cyrillici \cyrillick]
+
+\setupheadtext [\s!ru] [\v!abbreviations=\cyrillicS \cyrillicp \cyrillici
+ \cyrillics \cyrillico \cyrillick
+ \space \cyrillics \cyrillico
+ \cyrillick \cyrillicr \cyrillica
+ \cyrillicshch \cyrillice
+ \cyrillicn
+ \cyrillici \cyrillicishrt]
+\setupheadtext [\s!ua] [\v!abbreviations=\cyrillicP \cyrillice \cyrillicr
+ \cyrillice \cyrillicl \cyrillicii
+ \cyrillick \space \cyrillics
+ \cyrillick \cyrillico \cyrillicr
+ \cyrillico \cyrillicch\cyrillice
+ \cyrillicn \cyrillicsftsn]
+
+\setupheadtext [\s!ru] [\v!logos=\cyrillicL \cyrillico \cyrillicg
+ \cyrillico \cyrillict \cyrillici
+ \cyrillicp \cyrillicery]
+\setupheadtext [\s!ua] [\v!logos=\cyrillicL \cyrillico \cyrillicg
+ \cyrillico \cyrillict \cyrillici
+ \cyrillicp \cyrillici]
+
+\setupheadtext [\s!ru] [\v!units=\cyrillicE \cyrillicd \cyrillici
+ \cyrillicn \cyrillici \cyrillicc
+ \cyrillicery \space \cyrillici
+ \cyrillicz \cyrillicm \cyrillice
+ \cyrillicr \cyrillice \cyrillicn
+ \cyrillici \cyrillicya]
+\setupheadtext [\s!ua] [\v!units=\cyrillicO \cyrillicd \cyrillici
+ \cyrillicn \cyrillici \cyrillicc
+ \cyrillicii\space \cyrillicv
+ \cyrillici \cyrillicm \cyrillicii
+ \cyrillicr \cyrillicu]
+
+\setuplabeltext [\s!ru] [\v!table=\cyrillicT \cyrillica \cyrillicb
+ \cyrillicl \cyrillici \cyrillicc
+ \cyrillica \space]
+\setuplabeltext [\s!ua] [\v!table=\cyrillicT \cyrillica \cyrillicb
+ \cyrillicl \cyrillici \cyrillicc
+ \cyrillicya\space]
+
+\setuplabeltext [\s!ru] [\v!figure=\cyrillicR \cyrillici \cyrillics
+ \cyrillicu \cyrillicn \cyrillico
+ \cyrillick \space]
+\setuplabeltext [\s!ua] [\v!figure=\cyrillicM \cyrillica \cyrillicl
+ \cyrillicyu\cyrillicn \cyrillico
+ \cyrillick \space]
+
+\setuplabeltext [\s!ru] [\v!intermezzo=\cyrillicV \cyrillics \cyrillict
+ \cyrillica \cyrillicv \cyrillick
+ \cyrillica \space]
+\setuplabeltext [\s!ua] [\v!intermezzo=\cyrillicV \cyrillics \cyrillict
+ \cyrillica \cyrillicv \cyrillick
+ \cyrillica \space]
+
+\setuplabeltext [\s!ru] [\v!graphic=\cyrillicG \cyrillicr \cyrillica
+ \cyrillicf \cyrillici \cyrillick
+ \space]
+\setuplabeltext [\s!ua] [\v!graphic=\cyrillicG \cyrillicr \cyrillica
+ \cyrillicf \cyrillici \cyrillick
+ \space]
+
+\setuplabeltext [\s!ru] [\v!chapter=]
+\setuplabeltext [\s!ua] [\v!chapter=]
+
+\setuplabeltext [\s!ru] [\v!section=]
+\setuplabeltext [\s!ua] [\v!section=]
+
+\setuplabeltext [\s!ru] [\v!subsection=]
+\setuplabeltext [\s!ua] [\v!subsection=]
+
+\setuplabeltext [\s!ru] [\v!subsubsection=]
+\setuplabeltext [\s!ua] [\v!subsubsection=]
+
+\setuplabeltext [\s!ru] [\v!subsubsubsection=]
+\setuplabeltext [\s!ua] [\v!subsubsubsection=]
+
+\setuplabeltext [\s!ru] [\v!appendix=]
+\setuplabeltext [\s!ua] [\v!appendix=]
+
+\setuplabeltext [\s!ru] [\v!part=\cyrillicCH\cyrillica \cyrillics
+ \cyrillict \cyrillicsftsn
+ \space]
+\setuplabeltext [\s!ua] [\v!part=\cyrillicCH\cyrillica \cyrillics
+ \cyrillict \cyrillici \cyrillicn
+ \cyrillica \space]
+
+\setuplabeltext [\s!ru] [\v!line=\cyrillics \cyrillict \cyrillicr
+ \cyrillico \cyrillick \cyrillica
+ \space]
+\setuplabeltext [\s!ua] [\v!line=\cyrillicr \cyrillicya\cyrillicd
+ \cyrillico \cyrillick \space]
+
+\setuplabeltext [\s!ru] [\v!lines=\cyrillics \cyrillict \cyrillicr
+ \cyrillico \cyrillick \cyrillici
+ \space]
+\setuplabeltext [\s!ua] [\v!lines=\cyrillicr \cyrillicya\cyrillicd
+ \cyrillick \cyrillici \space]
+
+\setuplabeltext [\s!ru] [\v!page=\cyrillics \cyrillict \cyrillicr
+ \cyrillica \cyrillicn \cyrillici
+ \cyrillicc \cyrillica \space]
+\setuplabeltext [\s!ua] [\v!page=\cyrillics \cyrillict \cyrillico
+ \cyrillicr \cyrillicii\cyrillicn
+ \cyrillick \cyrillica \space ]
+
+\setuplabeltext [\s!ru] [\v!atpage=\cyrillicn \cyrillica \space
+ \cyrillics \cyrillict \cyrillicr
+ \cyrillica \cyrillicn \cyrillici
+ \cyrillicc \cyrillice \space]
+\setuplabeltext [\s!ua] [\v!atpage=\cyrillicn \cyrillica \space
+ \cyrillics \cyrillict \cyrillico
+ \cyrillicr \cyrillicii\cyrillicn
+ \cyrillicc \cyrillicii\space ]
+
+\setuplabeltext [\s!ru] [\v!hencefore=\cyrillics \cyrillicm.\space
+ \cyrillicv \cyrillicery \cyrillicsh
+ \cyrillice]
+\setuplabeltext [\s!ua] [\v!hencefore=\cyrillicya\cyrillick \space
+ \cyrillicp \cyrillico \cyrillick
+ \cyrillica \cyrillicz \cyrillica
+ \cyrillicn \cyrillico \space
+ \cyrillicv \cyrillici \cyrillicshch
+ \cyrillice]
+
+\setuplabeltext [\s!ru] [\v!hereafter=\cyrillics \cyrillicm.\space
+ \cyrillicn \cyrillici \cyrilliczh
+ \cyrillice]
+\setuplabeltext [\s!ua] [\v!hereafter=\cyrillicya\cyrillick \space
+ \cyrillicp \cyrillico \cyrillick
+ \cyrillica \cyrillicz \cyrillica
+ \cyrillicn \cyrillico \space
+ \cyrillicn \cyrillici \cyrilliczh
+ \cyrillicch\cyrillice]
+
+\setuplabeltext [\s!ru] [\v!see=\cyrillics \cyrillicm.\space]
+\setuplabeltext [\s!ua] [\v!see=\cyrillicd \cyrillici
+ \cyrillicv.\space ]
+
+\setuplabeltext [\s!ru] [\v!january=\cyrillicya\cyrillicn \cyrillicv
+ \cyrillica \cyrillicr \cyrillicya]
+\setuplabeltext [\s!ru] [\v!february=\cyrillicf \cyrillice \cyrillicv
+ \cyrillicr \cyrillica \cyrillicl
+ \cyrillicya]
+\setuplabeltext [\s!ru] [\v!march=\cyrillicm \cyrillica \cyrillicr
+ \cyrillict \cyrillica]
+\setuplabeltext [\s!ru] [\v!april=\cyrillica \cyrillicp \cyrillicr
+ \cyrillice \cyrillicl \cyrillicya]
+\setuplabeltext [\s!ru] [\v!may=\cyrillicm \cyrillica \cyrillicya]
+\setuplabeltext [\s!ru] [\v!june=\cyrillici \cyrillicyu\cyrillicn
+ \cyrillicya]
+\setuplabeltext [\s!ru] [\v!july=\cyrillici \cyrillicyu\cyrillicl
+ \cyrillicya]
+\setuplabeltext [\s!ru] [\v!august=\cyrillica \cyrillicv \cyrillicg
+ \cyrillicu \cyrillics \cyrillict
+ \cyrillica]
+\setuplabeltext [\s!ru] [\v!september=\cyrillics \cyrillice \cyrillicn
+ \cyrillict \cyrillicya\cyrillicb
+ \cyrillicr \cyrillicya]
+\setuplabeltext [\s!ru] [\v!october=\cyrillico \cyrillick \cyrillict
+ \cyrillicya\cyrillicb \cyrillicr
+ \cyrillicya]
+\setuplabeltext [\s!ru] [\v!november=\cyrillicn \cyrillico \cyrillicya
+ \cyrillicb \cyrillicr \cyrillicya]
+\setuplabeltext [\s!ru] [\v!december=\cyrillicd \cyrillice \cyrillick
+ \cyrillica \cyrillicb \cyrillicr
+ \cyrillicya]
+
+\setuplabeltext [\s!ua] [\v!january=\cyrillics \cyrillicii\cyrillicch
+ \cyrillicn \cyrillicya]
+\setuplabeltext [\s!ua] [\v!february=\cyrillicl \cyrillicyu\cyrillict
+ \cyrillico \cyrillicg \cyrillico]
+\setuplabeltext [\s!ua] [\v!march=\cyrillicb \cyrillice \cyrillicr
+ \cyrillice \cyrillicz \cyrillicn
+ \cyrillicya]
+\setuplabeltext [\s!ua] [\v!april=\cyrillick \cyrillicv \cyrillicii
+ \cyrillict \cyrillicn \cyrillicya]
+\setuplabeltext [\s!ua] [\v!may=\cyrillict \cyrillicr \cyrillica
+ \cyrillicv \cyrillicn \cyrillicya]
+\setuplabeltext [\s!ua] [\v!june=\cyrillicch\cyrillice \cyrillicr
+ \cyrillicv \cyrillicn \cyrillicya]
+\setuplabeltext [\s!ua] [\v!july=\cyrillicl \cyrillici \cyrillicp
+ \cyrillicn \cyrillicya]
+\setuplabeltext [\s!ua] [\v!august=\cyrillics \cyrillice \cyrillicr
+ \cyrillicp \cyrillicn \cyrillicya]
+\setuplabeltext [\s!ua] [\v!september=\cyrillicv \cyrillice \cyrillicr
+ \cyrillice \cyrillics \cyrillicn
+ \cyrillicya]
+\setuplabeltext [\s!ua] [\v!october=\cyrilliczh\cyrillico \cyrillicv
+ \cyrillict \cyrillicn \cyrillicya]
+\setuplabeltext [\s!ua] [\v!november=\cyrillicl \cyrillici \cyrillics
+ \cyrillict \cyrillico \cyrillicp
+ \cyrillica \cyrillicd \cyrillica]
+\setuplabeltext [\s!ua] [\v!december=\cyrillicg \cyrillicr \cyrillicu
+ \cyrillicd \cyrillicn \cyrillicya]
+
+\setuplabeltext [\s!ru] [\v!sunday=\cyrillicv \cyrillico \cyrillics
+ \cyrillick \cyrillicr \cyrillice
+ \cyrillics \cyrillice \cyrillicn
+ \cyrillicsftsn \cyrillice]
+\setuplabeltext [\s!ru] [\v!monday=\cyrillicp \cyrillico \cyrillicn
+ \cyrillice \cyrillicd \cyrillice
+ \cyrillicl \cyrillicsftsn
+ \cyrillicn \cyrillici \cyrillick]
+\setuplabeltext [\s!ru] [\v!tuesday=\cyrillicv \cyrillict \cyrillico
+ \cyrillicr \cyrillicn \cyrillici
+ \cyrillick]
+\setuplabeltext [\s!ru] [\v!wednesday=\cyrillics \cyrillicr \cyrillice
+ \cyrillicd \cyrillica]
+\setuplabeltext [\s!ru] [\v!thursday=\cyrillicch\cyrillice \cyrillict
+ \cyrillicv \cyrillice \cyrillicr
+ \cyrillicg]
+\setuplabeltext [\s!ru] [\v!friday=\cyrillicp \cyrillicya\cyrillict
+ \cyrillicn \cyrillici \cyrillicc
+ \cyrillica]
+\setuplabeltext [\s!ru] [\v!saturday=\cyrillics \cyrillicu \cyrillicb
+ \cyrillicb \cyrillico \cyrillict
+ \cyrillica]
+
+\setuplabeltext [\s!ua] [\v!sunday=\cyrillicn \cyrillice \cyrillicd
+ \cyrillicii\cyrillicl \cyrillicya]
+\setuplabeltext [\s!ua] [\v!monday=\cyrillicp \cyrillico \cyrillicn
+ \cyrillice \cyrillicd \cyrillicii
+ \cyrillicl \cyrillico \cyrillick]
+\setuplabeltext [\s!ua] [\v!tuesday=\cyrillicv \cyrillicii\cyrillicv
+ \cyrillict \cyrillico \cyrillicr
+ \cyrillico \cyrillick]
+\setuplabeltext [\s!ua] [\v!wednesday=\cyrillics \cyrillice \cyrillicr
+ \cyrillice \cyrillicd \cyrillica]
+\setuplabeltext [\s!ua] [\v!thursday=\cyrillicch\cyrillice \cyrillict
+ \cyrillicv \cyrillice \cyrillicr]
+\setuplabeltext [\s!ua] [\v!friday=\cyrillicp'\cyrillicya\cyrillict
+ \cyrillicn \cyrillici \cyrillicc
+ \cyrillicya]
+\setuplabeltext [\s!ua] [\v!saturday=\cyrillics \cyrillicu \cyrillicb
+ \cyrillico \cyrillict \cyrillica]
+
+
+%D \ShowAllLanguageValues [\s!ru] [russian] {Russian} {doll}
+%D \ShowAllLanguageValues [\s!ua] [ukranian] {Ukranian} {dance}
+
+\protect \endinput
diff --git a/tex/context/base/lang-dis.mkii b/tex/context/base/lang-dis.mkii
new file mode 100644
index 000000000..f081bf4a9
--- /dev/null
+++ b/tex/context/base/lang-dis.mkii
@@ -0,0 +1,59 @@
+%D \module
+%D [ file=lang-dis,
+%D version=2005.02.12,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Distribution Patterns,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 code used to be part of cont-usr.tex but now that we
+%D use more generic pattern files, we decided to isolate these
+%D mappings.
+
+\writestatus{loading}{ConTeXt Language Macros / Distribution Patterns}
+
+%D Hyphenation patterns are normally sought in filed named
+%D \type {lang-xx.pat}. When present on the system, those
+%D patterns take precedence. This list will be adapted to
+%D the actual situation, given that it's noticed.
+
+%D The us/uk hyph 1/2 files will go
+
+\unprotect
+
+% \definefilefallback [lang-ca.pat] [cahyph.tex]
+% \definefilefallback [lang-da.pat] [dkhyph.tex]
+% \definefilefallback [lang-de.pat] [dehyphn.tex]
+% \definefilefallback [lang-es.pat] [eshyph.tex]
+% \definefilefallback [lang-fi.pat] [fihyph.tex]
+% \definefilefallback [lang-fr.pat] [frhyph.tex]
+% \definefilefallback [lang-hr.pat] [hrhyph.tex]
+% \definefilefallback [lang-hu.pat] [huhyph.tex]
+% \definefilefallback [lang-it.pat] [ithyph.tex]
+% \definefilefallback [lang-la.pat] [lahyph7.tex]
+% \definefilefallback [lang-no.pat] [nohyph.tex]
+% \definefilefallback [lang-pl.pat] [plhyph.tex]
+% \definefilefallback [lang-pt.pat] [pthyph.tex]
+% \definefilefallback [lang-ro.pat] [rohyph.tex]
+% \definefilefallback [lang-ru.pat] [ruenhyph.tex]
+% \definefilefallback [lang-sl.pat] [sihyph.tex,slhyph.tex]
+% \definefilefallback [lang-sv.pat] [svhyph.tex,sehyph.tex]
+% \definefilefallback [lang-tr.pat] [tkhyph.tex,trhyph.tex]
+% \definefilefallback [lang-ua.pat] [ukrenhyp.tex]
+% \definefilefallback [lang-uk.pat] [ukhyphen.tex,ukhyph.tex]
+% \definefilefallback [lang-us.pat] [ushyphmax.tex,ushyph.tex,ushyph1.tex,ushyph2.tex,hyphen.tex]
+% \definefilefallback [lang-nl.pat] [nehyph96.tex,dutch96.pat,nehyph.tex]
+% \definefilefallback [lang-cz.pat] [czhyphen.tex,czhyph.pat]
+% \definefilefallback [lang-sk.pat] [skhyphen.tex,skhyph.pat]
+% \definefilefallback [lang-deo.pat] [dehypht.tex]
+
+% \definefilesynonym [lang-af.pat] [lang-nl.pat]
+% \definefilesynonym [lang-en.pat] [lang-us.pat]
+% \definefilesynonym [lang-en.hyp] [lang-us.hyp]
+
+\protect \endinput
diff --git a/tex/context/base/lang-frd.tex b/tex/context/base/lang-frd.tex
new file mode 100644
index 000000000..6cc27080b
--- /dev/null
+++ b/tex/context/base/lang-frd.tex
@@ -0,0 +1,140 @@
+%D \module
+%D [ file=lang-frd,
+%D version=2004.01.15,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Language Frequency Table Data,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is expewrimental work!
+
+% http://www.onzetaal.nl/advies/letterfreq.html
+
+\startcharactertable[nl]
+ \charfreq a 7.47
+ \charfreq b 1.58
+ \charfreq c 1.24
+ \charfreq d 5.93
+ \charfreq e 18.91
+ \charfreq f .81
+ \charfreq g 3.4
+ \charfreq h 2.38
+ \charfreq i 6.5
+ \charfreq j 1.46
+ \charfreq k 2.25
+ \charfreq l 3.57
+ \charfreq m 2.21
+ \charfreq n 10.03
+ \charfreq o 6.06
+ \charfreq p 1.57
+ \charfreq q .009
+ \charfreq r 6.41
+ \charfreq s 3.73
+ \charfreq t 6.79
+ \charfreq u 1.99
+ \charfreq v 2.85
+ \charfreq w 1.52
+ \charfreq x .04
+ \charfreq y .035
+ \charfreq z 1.39
+\stopcharactertable
+
+% http://caislab.icu.ac.kr/course/2001/spring/ice605/down/010306.pdf
+
+% \startcharactertable[en]
+% \charfreq a 8.2
+% \charfreq b 1.5
+% \charfreq c 2.8
+% \charfreq d 4.3
+% \charfreq e 12.7
+% \charfreq f 2.2
+% \charfreq g 2
+% \charfreq h 6.1
+% \charfreq i 7
+% \charfreq j .2
+% \charfreq k .8
+% \charfreq l 4
+% \charfreq m 2.4
+% \charfreq n 6.7
+% \charfreq o 7.5
+% \charfreq p 1.9
+% \charfreq q .1
+% \charfreq r 6
+% \charfreq s 6.3
+% \charfreq t 9.1
+% \charfreq u 2.8
+% \charfreq v 1
+% \charfreq w 2.3
+% \charfreq x .1
+% \charfreq y 2
+% \charfreq z .1
+% \stopcharactertable
+
+% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm
+
+\startcharactertable[en]
+ \charfreq a 8.04
+ \charfreq b 1.54
+ \charfreq c 3.06
+ \charfreq d 3.99
+ \charfreq e 12.51
+ \charfreq f 2.3
+ \charfreq g 1.96
+ \charfreq h 5.49
+ \charfreq i 7.26
+ \charfreq j .16
+ \charfreq k .67
+ \charfreq l 4.14
+ \charfreq m 2.53
+ \charfreq n 7.09
+ \charfreq o 7.6
+ \charfreq p 2
+ \charfreq q .11
+ \charfreq r 6.12
+ \charfreq s 6.54
+ \charfreq t 9.25
+ \charfreq u 2.71
+ \charfreq v .99
+ \charfreq w 1.92
+ \charfreq x .19
+ \charfreq y 1.73
+ \charfreq z .09
+\stopcharactertable
+
+% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm
+
+\startcharactertable[de]
+ \charfreq a 6.47
+ \charfreq b 1.93
+ \charfreq c 2.68
+ \charfreq d 4.83
+ \charfreq e 17.48
+ \charfreq f 1.65
+ \charfreq g 3.06
+ \charfreq h 4.23
+ \charfreq i 7.73
+ \charfreq j .27
+ \charfreq k 1.46
+ \charfreq l 3.49
+ \charfreq m 2.58
+ \charfreq n 9.84
+ \charfreq o 2.98
+ \charfreq p .96
+ \charfreq q .02
+ \charfreq r 7.54
+ \charfreq s 6.83
+ \charfreq t 6.13
+ \charfreq u 4.17
+ \charfreq v .94
+ \charfreq w 1.48
+ \charfreq x .04
+ \charfreq y .08
+ \charfreq z 1.14
+\stopcharactertable
+
+\endinput
diff --git a/tex/context/base/lang-frq.tex b/tex/context/base/lang-frq.tex
new file mode 100644
index 000000000..773230e6c
--- /dev/null
+++ b/tex/context/base/lang-frq.tex
@@ -0,0 +1,207 @@
+%D \module
+%D [ file=lang-frq,
+%D version=2004.01.15,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Frequency Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Frequency Tables}
+
+\unprotect
+
+\ifx\s!en\undefined \def\v!en{en} \fi
+\ifx\??lg\undefined \def\??lg{@@lg} \fi
+
+%M \usemodule[layout]
+
+%D \macros
+%D {charwidthmethod}
+%D
+%D This module implements a method for determining the width of an
+%D average character in a language. It uses the dimensions of the
+%D current fonts.
+%D
+%D \def\ShwChrWd#1#2#3%
+%D {\chardef\charwidthmethod#1\relax
+%D \mainlanguage[#2#3]\the\dimexpr(\averagecharwidth)}
+%D
+%D \starttabulate[|c|c|c|c|c|c|]
+%D \HL
+%D \NC \NC\bf0=amount\NC\bf1=.5em\NC2=ex\NC\bf3=frequency\NC\bf4=list\NC\NR
+%D \HL
+%D \NC\bf en\NC\ShwChrWd0en\NC\ShwChrWd1en\NC\ShwChrWd2en\NC\ShwChrWd3en\NC\ShwChrWd4en\NC\NR
+%D \NC\bf nl\NC\ShwChrWd0nl\NC\ShwChrWd1nl\NC\ShwChrWd2nl\NC\ShwChrWd3nl\NC\ShwChrWd4nl\NC\NR
+%D \NC\bf de\NC\ShwChrWd0de\NC\ShwChrWd1de\NC\ShwChrWd2de\NC\ShwChrWd3de\NC\ShwChrWd4de\NC\NR
+%D \HL
+%D \stoptabulate
+%D
+%D Method~1 ignores the widths and assumes that each character has a
+%D width of .5em, which is true for most monospaced fonts. Method~2
+%D takes the x as starting point, and assumes that it's height kind of
+%D matches its width. Method~3 is the best one, and determines the
+%D average width based on the language specific character table.
+%D Method~4 is a mixture between the first two methods: character
+%D specific widths applied to an equal distribution. Method~0 reports
+%D the total count, which normally is~100.
+
+\chardef\charwidthmethod=3 % 0=amount 1=em 2=ex 3=frequency 4=flattened >4=ex
+
+%D \macros
+%D {charwidthlanguage}
+%D
+%D The language used for the calculations is defined as:
+
+\def\charwidthlanguage{\currentmainlanguage}
+
+%D \macros
+%D {charfreq}
+%D
+%D This method comes into action in the following macro:
+
+\def\charfreq#1 #2 % character fraction
+ {+(\ifcase\charwidthmethod
+ #2\dimexpr100\onepoint\relax
+ \or
+ #2\dimexpr.5em\relax % \emwidth/2
+ \or
+ #2\dimexpr\exheight\relax
+ \or
+ #2\fontcharwd\font`#1%
+ \or
+ \dimexpr100\fontcharwd\font`#1/\charactertsize\charwidthlanguage\relax % ugly hack
+ \else
+ #2\dimexpr\exheight\relax
+ \fi)}
+
+%D \macros
+%D {startcharactertable}
+%D
+%D A frequency table is defined with the following macro. The \type
+%D {charfreq} macro is used in this table.
+
+\def\startcharactertable[#1]#2\stopcharactertable % \dimexpr has fuzzy lookahead
+ {\startnointerference
+ \long\setgvalue{\??lg:w:#1}{#2}% the width vector
+ \scratchcounter\zerocount \def\charfreq##1 ##2 {\advance\scratchcounter\plusone} #2%
+ \long\setxvalue{\??lg:c:#1}{\the\scratchcounter}% the character count
+ \stopnointerference}
+
+%D \macros
+%D {charactertable,charactertsize}
+%D
+%D The table content as well as the number of entries can be fetched with
+%D the following two macros. The architecture of the table and calling
+%D macro permits a fully expandable application.
+
+\def\charactertable#1%
+ {\csname\??lg:w:\ifcsname\??lg:w:#1\endcsname#1\else\s!en\fi\endcsname}
+
+\def\charactertsize#1%
+ {\csname\??lg:c:\ifcsname\??lg:c:#1\endcsname#1\else\s!en\fi\endcsname}
+
+%D Although it is of hardly any use, you can inherit a character table:
+%D
+%D \starttyping
+%D \startcharactertable[cz] \charactertable{en} \stopcharactertable
+%D \stoptyping
+%D
+%D We define a default vector with 100\% x's.
+
+\startcharactertable[en] 100 x \stopcharactertable % kind of default
+
+%D \macros
+%D {averagecharwidth}
+%D
+%D This macro reports the average width for the current main
+%D language (\the \dimexpr (\averagecharwidth)).
+
+\def\averagecharwidth{\dimexpr((\zeropoint\charactertable\charwidthlanguage)/100)}
+
+\def\showcharfreq
+ {\hbox\bgroup
+ \charwidthlanguage:%
+ \dostepwiserecurse041%
+ {\chardef\charwidthmethod\recurselevel\relax
+ \enspace\recurselevel/\the\dimexpr(\averagecharwidth)}%
+ \egroup}
+
+%D Just for fun, we show a few frequency tables as graphic (\in {figure}
+%D [fig:charfreq]).
+%D
+%D \startbuffer
+%D \definepalet [charfreq] [en=darkred, nl=darkgreen, de=darkblue]
+%D
+%D \def\charfreq#1 #2 %
+%D {\startMPdrawing
+%D interim linejoin := butt ;
+%D a := ASCII "#1" ;
+%D if (a >= (ASCII "a")) and (a <= (ASCII "z")) :
+%D draw ((0,#2*.25cm)--origin--(0,#2*.5cm))
+%D shifted (a*4mm+o,0)
+%D withpen pencircle scaled .5mm
+%D withcolor c;
+%D fi ;
+%D \stopMPdrawing}
+%D
+%D \resetMPdrawing
+%D \startMPdrawing
+%D numeric a, o ; a := o := 0 ;
+%D color c ; c := .5white ;
+%D string s ; s := "" ;
+%D \stopMPdrawing
+%D
+%D \startMPdrawing o := 0mm ; c := \MPcolor{charfreq:en} ; \stopMPdrawing
+%D \charactertable{en}
+%D
+%D \startMPdrawing o := 1mm ; c := \MPcolor{charfreq:nl} ; \stopMPdrawing
+%D \charactertable{nl}
+%D
+%D \startMPdrawing o := 2mm ; c := \MPcolor{charfreq:de} ; \stopMPdrawing
+%D \charactertable{de}
+%D
+%D \startMPdrawing
+%D for a := ASCII "a" upto ASCII "z" :
+%D draw textext.bot("\strut\tttf " & char a) shifted (a*4mm+1mm,-1mm) ;
+%D endfor ;
+%D \stopMPdrawing
+%D
+%D \MPdrawingdonetrue \getMPdrawing \resetMPdrawing
+%D \stopbuffer
+%D
+%D \placefigure
+%D [here]
+%D [fig:charfreq]
+%D {The character distributions for English, Dutch and German.}
+%D {\getbuffer}
+%D
+%D A few samples of usage of this mechanism are shown below:
+%D
+%D \startbuffer
+%D {\mainlanguage[en]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D {\mainlanguage[nl]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D {\mainlanguage[de]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Although the widthts differ, the consequenes for breaking the paragraph
+%D into lines are minimal.
+
+%D \macros
+%D {freezeaveragecharacterwidth}
+%D
+%D This macro can be used to make sure that the width does not change during a
+%D page break when another font is used.
+
+\let\normalaveragecharacterwidth\averagecharacterwidth
+
+\def\freezeaveragecharacterwidth % global
+ {\xdef\averagecharacterwidth{\dimexpr(\the\normalaveragecharacterwidth)}}
+
+\protect \endinput
diff --git a/tex/context/base/lang-ger.tex b/tex/context/base/lang-ger.tex
new file mode 100644
index 000000000..1ffbb33e6
--- /dev/null
+++ b/tex/context/base/lang-ger.tex
@@ -0,0 +1,738 @@
+%D \module
+%D [ file=lang-ger,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Germanic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Germanic Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+%D
+%D \starttabulate[|lB|l|]
+%D \NC Norwegian \NC Hans Fredrik Nordhaug \NC \NR
+%D \NC Danish \NC Arne Jorgensen \NC \NR % check the o
+%D \NC Afrikaans \NC \NC \NR
+%D \stoptabulate
+
+% Danish, Faeroese, Icelandic, Norwegian, Swedish, German, Yiddish
+% Afrikaans, Dutch, English, Flemush, Frisian, Plattdeutsch
+
+\unprotect
+
+\installlanguage
+ [\s!nl]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year},
+ \s!mapping={texnansi,ec},
+ \s!encoding={texnansi,ec}]
+
+\installlanguage
+ [\s!en]
+ [\c!spacing=\v!broad,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!month,\ ,\v!day,{,\ },\v!year},
+ \s!patterns=\s!us,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3]
+
+\installlanguage
+ [\s!de]
+ [\c!spacing=\v!packed,
+ \s!lefthyphenmin=3,
+ \s!righthyphenmin=3,
+ \c!leftsentence={\hbox{--~}},
+ \c!rightsentence={\hbox{~--}},
+ \c!leftsubsentence={--},
+ \c!rightsubsentence={--},
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,{.},\ ,\v!month,\ ,\v!year},
+ \s!mapping={texnansi,ec},
+ \s!encoding={texnansi,ec}]
+
+\installlanguage
+ [\s!da]
+ [\c!spacing=\v!packed,
+ \c!leftsentence={\hbox{--\hskip.5em}},
+ \c!rightsentence={\hbox{\hskip.5em--}},
+ \c!leftsubsentence={--},
+ \c!rightsubsentence={--},
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,{.},\ ,\v!month,\ ,\v!year}]
+
+\installlanguage
+ [\s!sv]
+ [\c!spacing=\v!packed,
+ \c!leftsentence={\hbox{--~}},
+ \c!rightsentence={\hbox{~--}},
+ \c!leftsubsentence={--},
+ \c!rightsubsentence={--},
+ \c!leftquote=\upperrightsingleninequote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperrightdoubleninequote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year}]
+
+\installlanguage
+ [\s!af]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\ ,\v!month,\ ,\v!day},
+ \s!patterns=\s!nl]
+
+\installlanguage
+ [\s!nb]
+ [spacing=packed,
+ lefthyphenmin=2,
+ righthyphenmin=2,
+ leftsentence=---,
+ rightsentence=---,
+ leftsubsentence=---,
+ rightsubsentence=---,
+ leftquote=\upperleftsinglesixquote,
+ rightquote=\upperrightsingleninequote,
+ leftquotation=\leftguillemot,
+ rightquotation=\rightguillemot,
+ date={day,{.},\ ,month,\ ,year},
+ state=stop]
+
+\installlanguage
+ [\s!nn]
+ [spacing=packed,
+ lefthyphenmin=2,
+ righthyphenmin=2,
+ leftsentence=---,
+ rightsentence=---,
+ leftsubsentence=---,
+ rightsubsentence=---,
+ leftquote=\upperleftsinglesixquote,
+ rightquote=\upperrightsingleninequote,
+ leftquotation=\leftguillemot,
+ rightquotation=\rightguillemot,
+ date={day,{.},\ ,month,\ ,year},
+ state=stop]
+
+\installlanguage [\s!no] [\s!nb]
+\installlanguage [\s!norwegian] [\s!nb]
+\installlanguage [\s!bokmal] [\s!nb]
+\installlanguage [\s!nynorsk] [\s!nn]
+
+%D Extra:
+
+% \mainlanguage[en]
+% \mainlanguage[de]
+% \mainlanguage[deo]
+% \mainlanguage[de-de]
+% \mainlanguage[de-at]
+% \mainlanguage[de-ch]
+%
+% \starttext
+% Die Herren Meier\index{Meier}, Müller\index{Müller}, Huber\index{Huber}
+% und Schmidt\index{Schmidt} arbeiten in der gleichen Firma.
+%
+% \index{Mass}\index{Mas}\index{Maß}\index{Maße}\index{Masse}
+% \index{Muller}\index{Mûller}
+% \index{Hutte}\index{Hütte}\index{Huttf}
+% \index{paar}\index{Paar}
+% \index{a}\index{aa}\index{ä}\index{az}\index{aza}
+% \index{o}\index{oo}\index{ö}\index{oz}\index{oza}
+% \index{u}\index{uu}\index{ü}\index{uz}\index{uza}\index{üa}
+% \index{call}\index{chip}
+%
+% \subject{Index} \placeindex
+% \stoptext
+
+\installlanguage % old german
+ [deo]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de]
+
+\installlanguage
+ [de-de]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de]
+
+\installlanguage
+ [de-at]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de,
+ \c!leftquote=\leftguillemot,
+ \c!rightquote=\rightguillemot,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot]
+
+\installlanguage
+ [de-ch]
+ [\c!spacing=\v!packed,
+ \c!default=\s!de]
+
+%D And some alternative (but very real) english patterns:
+
+\installlanguage
+ [en-gb]
+ [\c!default=\s!en,
+ \s!patterns=\s!gb,
+ \s!lefthyphenmin=3,
+ \s!righthyphenmin=3]
+
+\installlanguage
+ [en-us]
+ [\c!default=\s!en]
+
+\installlanguage [\s!uk] [en-gb]
+\installlanguage [\s!us] [en-us]
+
+%D For compatibility reasons we also define:
+
+%installlanguage [du] [\s!de] % old times context
+%installlanguage [sp] [\s!es] % old times context /lang-ita
+
+\installlanguage [usenglish] [en-us]
+\installlanguage [ukenglish] [en-gb]
+\installlanguage [english] [en-us]
+\installlanguage [dutch] [\s!nl]
+\installlanguage [german] [\s!de]
+\installlanguage [danish] [\s!da]
+\installlanguage [swedish] [\s!sv]
+\installlanguage [afrikaans] [\s!af]
+
+\setupheadtext [\s!en] [\v!content=Contents]
+\setupheadtext [\s!nl] [\v!content=Inhoud]
+\setupheadtext [\s!de] [\v!content=Inhalt]
+\setupheadtext [\s!da] [\v!content=Indhold]
+\setupheadtext [\s!sv] [\v!content=Inneh\aring ll]
+\setupheadtext [\s!af] [\v!content=Inhoud]
+\setupheadtext [\s!nb] [\v!content=Innhold]
+\setupheadtext [\s!nn] [\v!content=Innhald]
+
+\setupheadtext [\s!en] [\v!tables=Tables]
+\setupheadtext [\s!nl] [\v!tables=Tabellen]
+\setupheadtext [\s!de] [\v!tables=Tabellen]
+\setupheadtext [\s!da] [\v!tables=Tabeller]
+\setupheadtext [\s!sv] [\v!tables=Tabeller]
+\setupheadtext [\s!af] [\v!tables=Tabelle]
+\setupheadtext [\s!nb] [\v!tables=Tabeller]
+\setupheadtext [\s!nn] [\v!tables=Tabellar]
+
+\setupheadtext [\s!en] [\v!figures=Figures]
+\setupheadtext [\s!nl] [\v!figures=Figuren]
+\setupheadtext [\s!de] [\v!figures=Abbildungen]
+\setupheadtext [\s!da] [\v!figures=Figurer]
+\setupheadtext [\s!sv] [\v!figures=Figurer]
+\setupheadtext [\s!af] [\v!figures=Figure]
+\setupheadtext [\s!nb] [\v!figures=Figurer]
+\setupheadtext [\s!nn] [\v!figures=Figurar]
+
+\setupheadtext [\s!en] [\v!graphics=Graphics]
+\setupheadtext [\s!nl] [\v!graphics=Grafieken]
+\setupheadtext [\s!de] [\v!graphics=Graphiken]
+\setupheadtext [\s!da] [\v!graphics=Grafik]
+\setupheadtext [\s!sv] [\v!graphics=Grafik]
+\setupheadtext [\s!af] [\v!graphics=Grafieke]
+\setupheadtext [\s!nb] [\v!graphics=Bilde]
+\setupheadtext [\s!nn] [\v!graphics=Bilete]
+
+\setupheadtext [\s!en] [\v!intermezzi=Intermezzos]
+\setupheadtext [\s!nl] [\v!intermezzi=Intermezzo's]
+\setupheadtext [\s!de] [\v!intermezzi=Intermezzi]
+\setupheadtext [\s!da] [\v!intermezzi=Intermezzoer]
+\setupheadtext [\s!sv] [\v!intermezzi=Intermezzon]
+\setupheadtext [\s!af] [\v!intermezzi=Intermezzos]
+\setupheadtext [\s!nb] [\v!intermezzi=Intermesso]
+\setupheadtext [\s!nn] [\v!intermezzi=Intermesso]
+
+\setupheadtext [\s!en] [\v!index=Index]
+\setupheadtext [\s!nl] [\v!index=Index]
+\setupheadtext [\s!de] [\v!index=Index]
+\setupheadtext [\s!da] [\v!index=Indeks]
+\setupheadtext [\s!sv] [\v!index=Sakregister]
+\setupheadtext [\s!af] [\v!index=Indeks]
+\setupheadtext [\s!nb] [\v!index=Register]
+\setupheadtext [\s!nn] [\v!index=Register]
+
+\setupheadtext [\s!en] [\v!abbreviations=Abbreviations]
+\setupheadtext [\s!nl] [\v!abbreviations=Afkortingen]
+\setupheadtext [\s!de] [\v!abbreviations=Abk\uumlaut rzungen]
+\setupheadtext [\s!da] [\v!abbreviations=Forkortelser]
+\setupheadtext [\s!sv] [\v!abbreviations=F\oumlaut rkortningar]
+\setupheadtext [\s!af] [\v!abbreviations=Afkortings]
+\setupheadtext [\s!nb] [\v!abbreviations=Forkortelser]
+\setupheadtext [\s!nn] [\v!abbreviations=Forkortingar]
+
+\setupheadtext [\s!en] [\v!logos=Logos]
+\setupheadtext [\s!nl] [\v!logos=Logo's]
+\setupheadtext [\s!de] [\v!logos=Logos]
+\setupheadtext [\s!da] [\v!logos=Logoer]
+\setupheadtext [\s!sv] [\v!logos=Loggor]
+\setupheadtext [\s!af] [\v!logos=Logos]
+\setupheadtext [\s!nb] [\v!logos=Logoer]
+\setupheadtext [\s!nn] [\v!logos=Logoar]
+
+\setupheadtext [\s!en] [\v!units=Units]
+\setupheadtext [\s!nl] [\v!units=Eenheden]
+\setupheadtext [\s!de] [\v!units=Einheiten]
+\setupheadtext [\s!da] [\v!units=Enheder]
+\setupheadtext [\s!sv] [\v!units=Enheter]
+\setupheadtext [\s!af] [\v!units=Eenhede]
+\setupheadtext [\s!nb] [\v!units=Enheter]
+\setupheadtext [\s!nn] [\v!units=Einingar]
+
+\setupheadtext [\s!en] [pubs=References]
+\setupheadtext [\s!nl] [pubs=Literatuur]
+\setupheadtext [\s!de] [pubs=Literatur]
+%setupheadtext [\s!da] [pubs=?]
+%setupheadtext [\s!sv] [pubs=?]
+%setupheadtext [\s!af] [pubs=?]
+%setupheadtext [\s!nb] [pubs=?]
+%setupheadtext [\s!nn] [pubs=?]
+
+\setuplabeltext [\s!en] [\v!table=Table ]
+\setuplabeltext [\s!nl] [\v!table=Tabel ]
+\setuplabeltext [\s!de] [\v!table=Tabelle ]
+\setuplabeltext [\s!da] [\v!table=Tabel ]
+\setuplabeltext [\s!sv] [\v!table=Tabell ]
+\setuplabeltext [\s!af] [\v!table=Tabel]
+\setuplabeltext [\s!nb] [\v!table=Tabell ]
+\setuplabeltext [\s!nn] [\v!table=Tabell ]
+
+\setuplabeltext [\s!en] [\v!figure=Figure ]
+\setuplabeltext [\s!nl] [\v!figure=Figuur ]
+\setuplabeltext [\s!de] [\v!figure=Abbildung ]
+\setuplabeltext [\s!da] [\v!figure=Figur ]
+\setuplabeltext [\s!sv] [\v!figure=Figur ]
+\setuplabeltext [\s!af] [\v!figure=Figuur ]
+\setuplabeltext [\s!nb] [\v!figure=Figur ]
+\setuplabeltext [\s!nn] [\v!figure=Figur ]
+
+\setuplabeltext [\s!en] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!nl] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!de] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!da] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!sv] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!af] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!nb] [\v!intermezzo=Intermesso ]
+\setuplabeltext [\s!nn] [\v!intermezzo=Intermesso ]
+
+\setuplabeltext [\s!en] [\v!graphic=Graphic ]
+\setuplabeltext [\s!nl] [\v!graphic=Grafiek ]
+\setuplabeltext [\s!de] [\v!graphic=Graphik ]
+\setuplabeltext [\s!da] [\v!graphic=Grafik ]
+\setuplabeltext [\s!sv] [\v!graphic=Grafik ]
+\setuplabeltext [\s!af] [\v!graphic=Grafiek ]
+\setuplabeltext [\s!nb] [\v!graphic=Bilde ]
+\setuplabeltext [\s!nn] [\v!graphic=Bilete ]
+
+%D We don't set these here. One can do that in a style.
+
+\setuplabeltext [\s!en] [\v!chapter=] % Chapter
+\setuplabeltext [\s!nl] [\v!chapter=]
+\setuplabeltext [\s!de] [\v!chapter=] % Kapitel
+\setuplabeltext [\s!da] [\v!chapter=]
+\setuplabeltext [\s!sv] [\v!chapter=]
+\setuplabeltext [\s!af] [\v!chapter=] % Hoofstuk
+\setuplabeltext [\s!nb] [\v!chapter=]
+\setuplabeltext [\s!nn] [\v!chapter=]
+
+\setuplabeltext [\s!en] [\v!section=]
+\setuplabeltext [\s!nl] [\v!section=]
+\setuplabeltext [\s!de] [\v!section=]
+\setuplabeltext [\s!da] [\v!section=]
+\setuplabeltext [\s!sv] [\v!section=]
+\setuplabeltext [\s!af] [\v!section=] % Paragraaf
+\setuplabeltext [\s!nb] [\v!section=]
+\setuplabeltext [\s!nn] [\v!section=]
+
+\setuplabeltext [\s!en] [\v!subsection=]
+\setuplabeltext [\s!nl] [\v!subsection=]
+\setuplabeltext [\s!de] [\v!subsection=]
+\setuplabeltext [\s!da] [\v!subsection=]
+\setuplabeltext [\s!sv] [\v!subsection=]
+\setuplabeltext [\s!af] [\v!subsection=]
+\setuplabeltext [\s!nb] [\v!subsection=]
+\setuplabeltext [\s!nn] [\v!subsection=]
+
+\setuplabeltext [\s!en] [\v!subsubsection=]
+\setuplabeltext [\s!nl] [\v!subsubsection=]
+\setuplabeltext [\s!de] [\v!subsubsection=]
+\setuplabeltext [\s!da] [\v!subsubsection=]
+\setuplabeltext [\s!sv] [\v!subsubsection=]
+\setuplabeltext [\s!af] [\v!subsubsection=]
+\setuplabeltext [\s!nb] [\v!subsubsection=]
+\setuplabeltext [\s!nn] [\v!subsubsection=]
+
+\setuplabeltext [\s!en] [\v!subsubsubsection=]
+\setuplabeltext [\s!nl] [\v!subsubsubsection=]
+\setuplabeltext [\s!de] [\v!subsubsubsection=]
+\setuplabeltext [\s!da] [\v!subsubsubsection=]
+\setuplabeltext [\s!sv] [\v!subsubsubsection=]
+\setuplabeltext [\s!af] [\v!subsubsubsection=]
+\setuplabeltext [\s!nb] [\v!subsubsubsection=]
+\setuplabeltext [\s!nn] [\v!subsubsubsection=]
+
+\setuplabeltext [\s!en] [\v!appendix=] % Appendix
+\setuplabeltext [\s!nl] [\v!appendix=]
+\setuplabeltext [\s!de] [\v!appendix=] % Anhang
+\setuplabeltext [\s!da] [\v!appendix=] % Bilag
+\setuplabeltext [\s!sv] [\v!appendix=]
+\setuplabeltext [\s!af] [\v!appendix=] % Bylae
+\setuplabeltext [\s!nb] [\v!appendix=] % Tillegg
+\setuplabeltext [\s!nn] [\v!appendix=] % Tillegg
+
+\setuplabeltext [\s!en] [\v!part=Part ]
+\setuplabeltext [\s!nl] [\v!part=Deel ]
+\setuplabeltext [\s!de] [\v!part=Teil ]
+\setuplabeltext [\s!da] [\v!part=Del ]
+\setuplabeltext [\s!sv] [\v!part=Del ]
+\setuplabeltext [\s!af] [\v!part=Deel ]
+\setuplabeltext [\s!nb] [\v!part=Del]
+\setuplabeltext [\s!nn] [\v!part=Del]
+
+\setuplabeltext [\s!en] [\v!line=line ]
+\setuplabeltext [\s!nl] [\v!line=regel ]
+\setuplabeltext [\s!de] [\v!line=Zeile ]
+\setuplabeltext [\s!da] [\v!line=linie ] % or linje
+\setuplabeltext [\s!sv] [\v!line=rad ]
+\setuplabeltext [\s!af] [\v!line=re\ediaeresis l ]
+\setuplabeltext [\s!nb] [\v!line=linje ]
+\setuplabeltext [\s!nn] [\v!line=linje ]
+
+\setuplabeltext [\s!en] [\v!lines=lines ]
+\setuplabeltext [\s!nl] [\v!lines=regels ]
+\setuplabeltext [\s!de] [\v!lines=Zeilen ]
+\setuplabeltext [\s!da] [\v!lines=linier ] % or linjer
+\setuplabeltext [\s!sv] [\v!lines=rader ]
+\setuplabeltext [\s!af] [\v!lines=re\ediaeresis ls ]
+\setuplabeltext [\s!nb] [\v!lines=linjer ]
+\setuplabeltext [\s!nn] [\v!lines=linjer ]
+
+\setuplabeltext [\s!en] [\v!january=January]
+\setuplabeltext [\s!en] [\v!february=February]
+\setuplabeltext [\s!en] [\v!march=March]
+\setuplabeltext [\s!en] [\v!april=April]
+\setuplabeltext [\s!en] [\v!may=May]
+\setuplabeltext [\s!en] [\v!june=June]
+\setuplabeltext [\s!en] [\v!july=July]
+\setuplabeltext [\s!en] [\v!august=August]
+\setuplabeltext [\s!en] [\v!september=September]
+\setuplabeltext [\s!en] [\v!october=October]
+\setuplabeltext [\s!en] [\v!november=November]
+\setuplabeltext [\s!en] [\v!december=December]
+
+\setuplabeltext [\s!nl] [\v!january=januari]
+\setuplabeltext [\s!nl] [\v!february=februari]
+\setuplabeltext [\s!nl] [\v!march=maart]
+\setuplabeltext [\s!nl] [\v!april=april]
+\setuplabeltext [\s!nl] [\v!may=mei]
+\setuplabeltext [\s!nl] [\v!june=juni]
+\setuplabeltext [\s!nl] [\v!july=juli]
+\setuplabeltext [\s!nl] [\v!august=augustus]
+\setuplabeltext [\s!nl] [\v!september=september]
+\setuplabeltext [\s!nl] [\v!october=oktober]
+\setuplabeltext [\s!nl] [\v!november=november]
+\setuplabeltext [\s!nl] [\v!december=december]
+
+\setuplabeltext [\s!de] [\v!january=Januar]
+\setuplabeltext [\s!de] [\v!february=Februar]
+\setuplabeltext [\s!de] [\v!march=M\aumlaut rz]
+\setuplabeltext [\s!de] [\v!april=April]
+\setuplabeltext [\s!de] [\v!may=Mai]
+\setuplabeltext [\s!de] [\v!june=Juni]
+\setuplabeltext [\s!de] [\v!july=Juli]
+\setuplabeltext [\s!de] [\v!august=August]
+\setuplabeltext [\s!de] [\v!september=September]
+\setuplabeltext [\s!de] [\v!october=Oktober]
+\setuplabeltext [\s!de] [\v!november=November]
+\setuplabeltext [\s!de] [\v!december=Dezember]
+
+\setuplabeltext [\s!da] [\v!january=januar]
+\setuplabeltext [\s!da] [\v!february=februar]
+\setuplabeltext [\s!da] [\v!march=marts]
+\setuplabeltext [\s!da] [\v!april=april]
+\setuplabeltext [\s!da] [\v!may=maj]
+\setuplabeltext [\s!da] [\v!june=juni]
+\setuplabeltext [\s!da] [\v!july=juli]
+\setuplabeltext [\s!da] [\v!august=august]
+\setuplabeltext [\s!da] [\v!september=september]
+\setuplabeltext [\s!da] [\v!october=oktober]
+\setuplabeltext [\s!da] [\v!november=november]
+\setuplabeltext [\s!da] [\v!december=december]
+
+\setuplabeltext [\s!sv] [\v!january=januari]
+\setuplabeltext [\s!sv] [\v!february=februari]
+\setuplabeltext [\s!sv] [\v!march=mars]
+\setuplabeltext [\s!sv] [\v!april=april]
+\setuplabeltext [\s!sv] [\v!may=maj]
+\setuplabeltext [\s!sv] [\v!june=juni]
+\setuplabeltext [\s!sv] [\v!july=juli]
+\setuplabeltext [\s!sv] [\v!august=augusti]
+\setuplabeltext [\s!sv] [\v!september=september]
+\setuplabeltext [\s!sv] [\v!october=oktober]
+\setuplabeltext [\s!sv] [\v!november=november]
+\setuplabeltext [\s!sv] [\v!december=december]
+
+\setuplabeltext [\s!af] [\v!january=januarie]
+\setuplabeltext [\s!af] [\v!february=februarie]
+\setuplabeltext [\s!af] [\v!march=maart]
+\setuplabeltext [\s!af] [\v!april=april]
+\setuplabeltext [\s!af] [\v!may=mei]
+\setuplabeltext [\s!af] [\v!june=junie]
+\setuplabeltext [\s!af] [\v!july=julie]
+\setuplabeltext [\s!af] [\v!august=augustus]
+\setuplabeltext [\s!af] [\v!september=september]
+\setuplabeltext [\s!af] [\v!october=oktober]
+\setuplabeltext [\s!af] [\v!november=november]
+\setuplabeltext [\s!af] [\v!december=desember]
+
+\setuplabeltext [\s!nb] [\v!january=januar]
+\setuplabeltext [\s!nb] [\v!february=februar]
+\setuplabeltext [\s!nb] [\v!march=mars]
+\setuplabeltext [\s!nb] [\v!april=april]
+\setuplabeltext [\s!nb] [\v!may=mai]
+\setuplabeltext [\s!nb] [\v!june=juni]
+\setuplabeltext [\s!nb] [\v!july=juli]
+\setuplabeltext [\s!nb] [\v!august=august]
+\setuplabeltext [\s!nb] [\v!september=september]
+\setuplabeltext [\s!nb] [\v!october=oktober]
+\setuplabeltext [\s!nb] [\v!november=november]
+\setuplabeltext [\s!nb] [\v!december=desember]
+
+\setuplabeltext [\s!nn] [\v!january=januar]
+\setuplabeltext [\s!nn] [\v!february=februar]
+\setuplabeltext [\s!nn] [\v!march=mars]
+\setuplabeltext [\s!nn] [\v!april=april]
+\setuplabeltext [\s!nn] [\v!may=mai]
+\setuplabeltext [\s!nn] [\v!june=juni]
+\setuplabeltext [\s!nn] [\v!july=juli]
+\setuplabeltext [\s!nn] [\v!august=august]
+\setuplabeltext [\s!nn] [\v!september=september]
+\setuplabeltext [\s!nn] [\v!october=oktober]
+\setuplabeltext [\s!nn] [\v!november=november]
+\setuplabeltext [\s!nn] [\v!december=desember]
+
+\setuplabeltext [\s!en] [\v!sunday=Sunday]
+\setuplabeltext [\s!en] [\v!monday=Monday]
+\setuplabeltext [\s!en] [\v!tuesday=Tuesday]
+\setuplabeltext [\s!en] [\v!wednesday=Wednesday]
+\setuplabeltext [\s!en] [\v!thursday=Thursday]
+\setuplabeltext [\s!en] [\v!friday=Friday]
+\setuplabeltext [\s!en] [\v!saturday=Saturday]
+
+\setuplabeltext [\s!nl] [\v!sunday=zondag]
+\setuplabeltext [\s!nl] [\v!monday=maandag]
+\setuplabeltext [\s!nl] [\v!tuesday=dinsdag]
+\setuplabeltext [\s!nl] [\v!wednesday=woensdag]
+\setuplabeltext [\s!nl] [\v!thursday=donderdag]
+\setuplabeltext [\s!nl] [\v!friday=vrijdag]
+\setuplabeltext [\s!nl] [\v!saturday=zaterdag]
+
+\setuplabeltext [\s!de] [\v!sunday=Sonntag]
+\setuplabeltext [\s!de] [\v!monday=Montag]
+\setuplabeltext [\s!de] [\v!tuesday=Dienstag]
+\setuplabeltext [\s!de] [\v!wednesday=Mittwoch]
+\setuplabeltext [\s!de] [\v!thursday=Donnerstag]
+\setuplabeltext [\s!de] [\v!friday=Freitag]
+\setuplabeltext [\s!de] [\v!saturday=Samstag]
+
+\setuplabeltext [\s!da] [\v!sunday=s\ostroke ndag]
+\setuplabeltext [\s!da] [\v!monday=mandag]
+\setuplabeltext [\s!da] [\v!tuesday=tirsdag]
+\setuplabeltext [\s!da] [\v!wednesday=onsdag]
+\setuplabeltext [\s!da] [\v!thursday=torsdag]
+\setuplabeltext [\s!da] [\v!friday=fredag]
+\setuplabeltext [\s!da] [\v!saturday=l\ostroke rdag]
+
+\setuplabeltext [\s!sv] [\v!sunday=s\oumlaut ndag]
+\setuplabeltext [\s!sv] [\v!monday=m\aring ndag]
+\setuplabeltext [\s!sv] [\v!tuesday=tisdag]
+\setuplabeltext [\s!sv] [\v!wednesday=onsdag]
+\setuplabeltext [\s!sv] [\v!thursday=torsdag]
+\setuplabeltext [\s!sv] [\v!friday=fredag]
+\setuplabeltext [\s!sv] [\v!saturday=l\oumlaut rdag]
+
+\setuplabeltext [\s!af] [\v!sunday=sondag]
+\setuplabeltext [\s!af] [\v!monday=maandag]
+\setuplabeltext [\s!af] [\v!tuesday=dinsdag]
+\setuplabeltext [\s!af] [\v!wednesday=woensdag]
+\setuplabeltext [\s!af] [\v!thursday=donderdag]
+\setuplabeltext [\s!af] [\v!friday=vrydag]
+\setuplabeltext [\s!af] [\v!saturday=saterdag]
+
+\setuplabeltext [\s!nb] [\v!sunday=s\ostroke ndag]
+\setuplabeltext [\s!nb] [\v!monday=mandag]
+\setuplabeltext [\s!nb] [\v!tuesday=tirsdag]
+\setuplabeltext [\s!nb] [\v!wednesday=onsdag]
+\setuplabeltext [\s!nb] [\v!thursday=torsdag]
+\setuplabeltext [\s!nb] [\v!friday=fredag]
+\setuplabeltext [\s!nb] [\v!saturday=l\ostroke rdag]
+
+\setuplabeltext [\s!nn] [\v!sunday=sundag]
+\setuplabeltext [\s!nn] [\v!monday=m\aring ndag]
+\setuplabeltext [\s!nn] [\v!tuesday=tysdag]
+\setuplabeltext [\s!nn] [\v!wednesday=onsdag]
+\setuplabeltext [\s!nn] [\v!thursday=torsdag]
+\setuplabeltext [\s!nn] [\v!friday=fredag]
+\setuplabeltext [\s!nn] [\v!saturday=laurdag]
+
+%D Rather new ...
+
+\setuplabeltext [\s!nl] [\v!page=pagina ]
+\setuplabeltext [\s!nl] [\v!atpage=op pagina ]
+\setuplabeltext [\s!nl] [\v!hencefore=hierboven]
+\setuplabeltext [\s!nl] [\v!hereafter=hieronder]
+\setuplabeltext [\s!nl] [\v!see=zie ]
+
+\setuplabeltext [\s!en] [\v!page=page ]
+\setuplabeltext [\s!en] [\v!atpage=at page ]
+\setuplabeltext [\s!en] [\v!hencefore=as we show above]
+\setuplabeltext [\s!en] [\v!hereafter=as we show below]
+\setuplabeltext [\s!en] [\v!see=see ]
+
+\setuplabeltext [\s!de] [\v!page=Seite ]
+\setuplabeltext [\s!de] [\v!atpage=auf Seite ]
+\setuplabeltext [\s!de] [\v!hencefore=siehe oben]
+\setuplabeltext [\s!de] [\v!hereafter=siehe unten]
+\setuplabeltext [\s!de] [\v!see=siehe ]
+
+\setuplabeltext [\s!da] [\v!page=Side ]
+\setuplabeltext [\s!da] [\v!atpage=p\aring\ side ]
+\setuplabeltext [\s!da] [\v!hencefore=se foroven]
+\setuplabeltext [\s!da] [\v!hereafter=se forneden]
+\setuplabeltext [\s!da] [\v!see=se ]
+
+\setuplabeltext [\s!sv] [\v!page=Sida ]
+\setuplabeltext [\s!sv] [\v!atpage=p\aring\ sida ]
+\setuplabeltext [\s!sv] [\v!hencefore=se ovan]
+\setuplabeltext [\s!sv] [\v!hereafter=se nedan]
+\setuplabeltext [\s!sv] [\v!see=se ]
+
+\setuplabeltext [\s!nb] [\v!page=side ]
+\setuplabeltext [\s!nb] [\v!atpage=p\aring\ side ]
+\setuplabeltext [\s!nb] [\v!hencefore=som vist over]
+\setuplabeltext [\s!nb] [\v!hereafter=som vist under]
+\setuplabeltext [\s!nb] [\v!see=se ]
+
+\setuplabeltext [\s!nn] [\v!page=side ]
+\setuplabeltext [\s!nn] [\v!atpage=p\aring\ side ]
+\setuplabeltext [\s!nn] [\v!hencefore=som vist over]
+\setuplabeltext [\s!nn] [\v!hereafter=som vist under]
+\setuplabeltext [\s!nn] [\v!see=sj\aring\ ]
+
+%D ... and to be completed!
+
+%D Next we implement couple of ordinal mumber converters:
+
+\def\enordinaldaynumber#1%
+ {#1\ifnum\lasttwodigits{#1}=11
+ \highordinalstr{th}%
+ \else\ifnum\lasttwodigits{#1}=12
+ \highordinalstr{th}%
+ \else\ifnum\lasttwodigits{#1}=13
+ \highordinalstr{th}%
+ \else\ifcase\lastdigit{#1}%
+ \highordinalstr{th}%
+ \or % 1
+ \highordinalstr{st}%
+ \or % 2
+ \highordinalstr{nd}%
+ \or % 3
+ \highordinalstr{rd}%
+ \else
+ \highordinalstr{th}%
+ \fi\fi\fi\fi}
+
+% \def\enordinaldaynumber#1%
+% {#1\ordinalstr{\ifnum\lasttwodigits{#1}=11 th\else\ifcase\lastdigit{#1}
+% th\or st\or nd\or rd\else th\fi\fi}}
+
+\def\nlordinaldaynumber#1%
+ {#1\highordinalstr{e}}
+
+%D \ShowAllLanguageValues [\s!en] [english] {English} {horn} % engelse humor
+%D \ShowAllLanguageValues [\s!nl] [dutch] {Dutch} {treat} % nederlandse zuinigheid
+%D \ShowAllLanguageValues [\s!de] [german] {German} {beer} % duitse degelijkheid
+%D \ShowAllLanguageValues [\s!da] [danish] {Danish} {pastry}
+%D \ShowAllLanguageValues [\s!sv] [swedish] {Swedish} {design}
+%D \ShowAllLanguageValues [\s!af] [afrikaans] {Afrikaaner} {boer} % afrikaanse gasvryheid
+%D \ShowAllLanguageValues [\s!nb] [bokmal] {Norwegian} {wood}
+%D \ShowAllLanguageValues [\s!nn] [nynorsk] {Norwegian} {fish}
+
+%D Extra month names:
+
+\setuplabeltext [\s!en] [\v!january :\s!mnem=jan]
+\setuplabeltext [\s!en] [\v!february :\s!mnem=feb]
+\setuplabeltext [\s!en] [\v!march :\s!mnem=mar]
+\setuplabeltext [\s!en] [\v!april :\s!mnem=apr]
+\setuplabeltext [\s!en] [\v!may :\s!mnem=may]
+\setuplabeltext [\s!en] [\v!june :\s!mnem=jun]
+\setuplabeltext [\s!en] [\v!july :\s!mnem=jul]
+\setuplabeltext [\s!en] [\v!august :\s!mnem=aug]
+\setuplabeltext [\s!en] [\v!september:\s!mnem=sep]
+\setuplabeltext [\s!en] [\v!october :\s!mnem=oct]
+\setuplabeltext [\s!en] [\v!november :\s!mnem=nov]
+\setuplabeltext [\s!en] [\v!december :\s!mnem=dec]
+
+\setuplabeltext [\s!nb] [\v!january :\s!mnem=jan.]
+\setuplabeltext [\s!nb] [\v!february :\s!mnem=feb.]
+\setuplabeltext [\s!nb] [\v!march :\s!mnem=mars]
+\setuplabeltext [\s!nb] [\v!april :\s!mnem=april]
+\setuplabeltext [\s!nb] [\v!may :\s!mnem=mai]
+\setuplabeltext [\s!nb] [\v!june :\s!mnem=juni]
+\setuplabeltext [\s!nb] [\v!july :\s!mnem=juli]
+\setuplabeltext [\s!nb] [\v!august :\s!mnem=aug.]
+\setuplabeltext [\s!nb] [\v!september:\s!mnem=sep.]
+\setuplabeltext [\s!nb] [\v!october :\s!mnem=okt.]
+\setuplabeltext [\s!nb] [\v!november :\s!mnem=nov.]
+\setuplabeltext [\s!nb] [\v!december :\s!mnem=des.]
+
+\setuplabeltext [\s!nn] [\v!january :\s!mnem=jan.]
+\setuplabeltext [\s!nn] [\v!february :\s!mnem=feb.]
+\setuplabeltext [\s!nn] [\v!march :\s!mnem=mars]
+\setuplabeltext [\s!nn] [\v!april :\s!mnem=april]
+\setuplabeltext [\s!nn] [\v!may :\s!mnem=mai]
+\setuplabeltext [\s!nn] [\v!june :\s!mnem=juni]
+\setuplabeltext [\s!nn] [\v!july :\s!mnem=juli]
+\setuplabeltext [\s!nn] [\v!august :\s!mnem=aug.]
+\setuplabeltext [\s!nn] [\v!september:\s!mnem=sep.]
+\setuplabeltext [\s!nn] [\v!october :\s!mnem=okt.]
+\setuplabeltext [\s!nn] [\v!november :\s!mnem=nov.]
+\setuplabeltext [\s!nn] [\v!december :\s!mnem=des.]
+
+\protect \endinput
diff --git a/tex/context/base/lang-grk.tex b/tex/context/base/lang-grk.tex
new file mode 100644
index 000000000..e4ba781eb
--- /dev/null
+++ b/tex/context/base/lang-grk.tex
@@ -0,0 +1,94 @@
+%D \module
+%D [ file=lang-grk,
+%D version=2003.04.01,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Uralic Languages,
+%D author=Apostolos Syropoulos
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Greek}
+
+%D The framework of this module is set up by Hans Hagen while
+%D all the translations have been done by Apostolos Syropoulos
+
+\unprotect
+
+\installlanguage
+ [\s!gr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\greekleftquot,
+ \c!rightquote=\greekrightquot,
+ \c!leftquotation=\greekleftquot,
+ \c!rightquotation=\greekrightquot,
+ \c!date={\v!day\ \v!month\ \v!year}]
+
+\installlanguage [greek] [\s!gr]
+
+\setupheadtext [\s!gr] [\v!content=\greekPi\greekepsilon\greekrho\greekiota\greekepsilon\greekchi\greekomicrontonos\greekmu\greekepsilon\greeknu\greekalpha]
+\setupheadtext [\s!gr] [\v!tables=\greekPi\greekiotatonos\greeknu\greekalpha\greekkappa\greekepsilon\greekfinalsigma]
+\setupheadtext [\s!gr] [\v!figures=\greekSigma\greekchi\greeketatonos\greekmu\greekalpha\greektau\greekalpha]
+\setupheadtext [\s!gr] [\v!graphics=\greekGamma\greekrho\greekalpha\greekphi\greekiota\greekkappa\greekalphatonos]
+\setupheadtext [\s!gr] [\v!intermezzi=\greekPi\greekalpha\greekupsilontonos\greeksigma\greekepsilon\greekiota\greekfinalsigma]
+\setupheadtext [\s!gr] [\v!index=\greekEpsilon\greekupsilon\greekrho\greekepsilon\greektau\greeketatonos\greekrho\greekiota\greekomicron]
+\setupheadtext [\s!gr] [\v!abbreviations=\greekSigma\greekupsilon\greeknu\greektau\greekomicron\greekmu\greekomicron\greekgamma\greekrho\greekalpha\greekphi\greekiotatonos\greekepsilon\greekfinalsigma]
+\setupheadtext [\s!gr] [\v!logos=\greekLambda\greekomicron\greekgamma\greekomicrontonos\greektau\greekupsilon\greekpi\greekalpha]
+\setupheadtext [\s!gr] [\v!units=\greekMu\greekomicron\greeknu\greekalphatonos\greekdelta\greekepsilon\greekfinalsigma]
+
+\setuplabeltext [\s!gr] [\v!table=\greekPi\greekiotatonos\greeknu\greekalpha\greekkappa\greekalpha\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!figure=\greekSigma\greekchi\greeketatonos\greekmu\greekalpha]
+\setuplabeltext [\s!gr] [\v!intermezzo=\greekPi\greekalpha\greekupsilontonos\greeksigma\greeketa]
+\setuplabeltext [\s!gr] [\v!graphic=\greekGamma\greekrho\greekalpha\greekphi\greekiota\greekkappa\greekomicrontonos]
+
+\setuplabeltext [\s!gr] [\v!chapter=\greekKappa\greekepsilon\greekphi\greekalphatonos\greeklambda\greekalpha\greekiota\greekomicron]
+\setuplabeltext [\s!gr] [\v!section=\greekEpsilon\greeknu\greekomicrontonos\greektau\greeketa\greektau\greekalpha]
+\setuplabeltext [\s!gr] [\v!subsection=\greekUpsilon\greekpi\greekomicrontonos\greekepsilon\greeknu\greekomicrontonos\greektau\greeketa\greektau\greekalpha]
+\setuplabeltext [\s!gr] [\v!subsubsection=]
+\setuplabeltext [\s!gr] [\v!subsubsubsection=]
+
+\setuplabeltext [\s!gr] [\v!appendix=\greekPi\greekalpha\greekrho\greekalphatonos\greekrho\greektau\greeketa\greekmu\greekalpha]
+\setuplabeltext [\s!gr] [\v!part=\greekMu\greekepsilontonos\greekrho\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!line=\greekGamma\greekrho\greekalpha\greekmu\greekmu\greeketatonos]
+\setuplabeltext [\s!gr] [\v!lines=\greekGamma\greekrho\greekalpha\greekmu\greekmu\greekepsilontonos\greekfinalsigma]
+
+\setuplabeltext [\s!gr] [\v!january=\greekIota\greekalpha\greeknu\greekomicron\greekupsilon\greekalphatonos\greekrho\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!february=\greekPhi\greekepsilon\greekbeta\greekrho\greekomicron\greekupsilon\greekalphatonos\greekrho\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!march=\greekMu\greekalphatonos\greekrho\greektau\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!april=\greekAlpha\greekpi\greekrho\greekiotatonos\greeklambda\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!may=\greekMu\greekalphatonos\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!june=\greekIota\greekomicron\greekupsilontonos\greeknu\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!july=\greekIota\greekomicron\greekupsilontonos\greeklambda\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!august=\greekAlpha\greekupsilontonos\greekgamma\greekomicron\greekupsilon\greeksigma\greektau\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!september=\greekSigma\greekepsilon\greekpi\greektau\greekepsilontonos\greekmu\greekbeta\greekrho\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!october=\greekOmicron\greekkappa\greektau\greekomegatonos\greekbeta\greekrho\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!november=\greekNu\greekomicron\greekepsilontonos\greekmu\greekbeta\greekrho\greekiota\greekomicron\greekfinalsigma]
+\setuplabeltext [\s!gr] [\v!december=\greekDelta\greekepsilon\greekkappa\greekepsilontonos\greekmu\greekbeta\greekrho\greekiota\greekomicron\greekfinalsigma]
+
+\setuplabeltext [\s!gr] [\v!sunday=\greekKappa\greekupsilon\greekrho\greekiota\greekalpha\greekkappa\greeketatonos]
+\setuplabeltext [\s!gr] [\v!monday=\greekDelta\greekepsilon\greekupsilon\greektau\greekepsilontonos\greekrho\greekalpha]
+\setuplabeltext [\s!gr] [\v!tuesday=\greekTau\greekrho\greekiotatonos\greektau\greeketa]
+\setuplabeltext [\s!gr] [\v!wednesday=\greekTau\greekepsilon\greektau\greekalphatonos\greekrho\greektau\greeketa]
+\setuplabeltext [\s!gr] [\v!thursday=\greekPi\greekepsilontonos\greekmu\greekpi\greektau\greeketa]
+\setuplabeltext [\s!gr] [\v!friday=\greekPi\greekalpha\greekrho\greekalpha\greeksigma\greekkappa\greekepsilon\greekupsilon\greeketatonos]
+\setuplabeltext [\s!gr] [\v!saturday=\greekSigma\greekalphatonos\greekbeta\greekbeta\greekalpha\greektau\greekomicron]
+
+%D % \ShowAllLanguageValues [\s!gr] [\greekEpsilon\greeklambda\greeklambda\greeketa\greeknu\greekiota\greekkappa\greekalphatonos] {Greek} {love}
+
+\installlanguage
+ [\s!agr]
+ [\s!default=\s!gr,
+ \s!patterns=\s!agr,
+ \s!mapping=\s!agr,
+ \s!encoding=\s!agr]
+
+\installlanguage [ancientgreek] [\s!agr]
+
+\protect \endinput
diff --git a/tex/context/base/lang-ind.tex b/tex/context/base/lang-ind.tex
new file mode 100644
index 000000000..9b6e5ff1d
--- /dev/null
+++ b/tex/context/base/lang-ind.tex
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=lang--ind,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Indo Iranian Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Indo-Iranian Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+
+% 34 languages
+
+\unprotect
+
+\protect \endinput
diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua
new file mode 100644
index 000000000..239e5390c
--- /dev/null
+++ b/tex/context/base/lang-ini.lua
@@ -0,0 +1,321 @@
+if not modules then modules = { } end modules ['lang-ini'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- needs a cleanup (share locals)
+
+local utf = unicode.utf8
+local utfbyte = utf.byte
+local format = string.format
+local concat = table.concat
+local lpegmatch = lpeg.match
+
+local trace_patterns = false trackers.register("languages.patterns", function(v) trace_patterns = v end)
+
+languages = languages or {}
+languages.version = 1.009
+languages.hyphenation = languages.hyphenation or { }
+languages.hyphenation.data = languages.hyphenation.data or { }
+
+local langdata = languages.hyphenation.data
+
+-- 002D : hyphen-minus (ascii)
+-- 2010 : hyphen
+-- 2011 : nonbreakable hyphen
+-- 2013 : endash (compound hyphen)
+
+--~ lang:hyphenation(string)
+--~ string =lang:hyphenation()
+--~ lang:clear_hyphenation()
+
+-- we can consider hiding data (faster access too)
+
+-- loading the 26 languages that we normally load in mkiv, the string based variant
+-- takes .84 seconds (probably due to the sub's) while the lpeg variant takes .78
+-- seconds
+--
+-- the following lpeg can probably be improved (it was one of the first I made)
+
+local leftbrace = lpeg.P("{")
+local rightbrace = lpeg.P("}")
+local spaces = lpeg.S(" \r\n\t\f")
+local spacing = spaces^0
+local validchar = 1-(spaces+rightbrace+leftbrace)
+local validword = validchar^1
+local content = spacing * leftbrace * spacing * lpeg.C((spacing * validword)^0) * spacing * rightbrace * lpeg.P(true)
+
+local command = lpeg.P("\\patterns")
+local parser = (1-command)^0 * command * content
+
+local function filterpatterns(filename)
+ if file.extname(filename) == "rpl" then
+ return io.loaddata(resolvers.find_file(filename)) or ""
+ else
+ return lpegmatch(parser,io.loaddata(resolvers.find_file(filename)) or "")
+ end
+end
+
+local command = lpeg.P("\\hyphenation")
+local parser = (1-command)^0 * command * content
+
+local function filterexceptions(filename)
+ if file.extname(filename) == "rhl" then
+ return io.loaddata(resolvers.find_file(filename)) or ""
+ else
+ return lpegmatch(parser,io.loaddata(resolvers.find_file(filename)) or {}) -- "" ?
+ end
+end
+
+local function record(tag)
+ local data = langdata[tag]
+ if not data then
+ data = lang.new()
+ langdata[tag] = data or 0
+ end
+ return data
+end
+
+languages.hyphenation.record = record
+
+function languages.hyphenation.define(tag)
+ local data = record(tag)
+ return data:id()
+end
+
+function languages.hyphenation.number(tag)
+ local d = langdata[tag]
+ return (d and d:id()) or 0
+end
+
+lang.exceptions = lang.hyphenation
+
+local function loadthem(tag, filename, filter, target)
+ statistics.starttiming(languages)
+ local data = record(tag)
+ local fullname = (filename and filename ~= "" and resolvers.find_file(filename)) or ""
+ local ok = fullname ~= ""
+ if ok then
+ if trace_patterns then
+ logs.report("languages","filtering %s for language '%s' from '%s'",target,tag,fullname)
+ end
+ lang[target](data,filterpatterns(fullname))
+ else
+ if trace_patterns then
+ logs.report("languages","no %s for language '%s' in '%s'",target,tag,filename or "?")
+ end
+ lang[target](data,"")
+ end
+ langdata[tag] = data
+ statistics.stoptiming(languages)
+ return ok
+end
+
+function languages.hyphenation.loadpatterns(tag, patterns)
+ return loadthem(tag, patterns, filterpatterns, "patterns")
+end
+
+function languages.hyphenation.loadexceptions(tag, exceptions)
+ return loadthem(tag, patterns, filterexceptions, "exceptions")
+end
+
+function languages.hyphenation.exceptions(tag, ...)
+ local data = record(tag)
+ data:hyphenation(...)
+end
+
+function languages.hyphenation.hyphenate(tag, str)
+ return lang.hyphenate(record(tag), str)
+end
+
+function languages.hyphenation.lefthyphenmin(tag, value)
+ local data = record(tag)
+ if value then data:lefthyphenmin(value) end
+ return data:lefthyphenmin()
+end
+function languages.hyphenation.righthyphenmin(tag, value)
+ local data = record(tag)
+ if value then data:righthyphenmin(value) end
+ return data:righthyphenmin()
+end
+
+function languages.hyphenation.n()
+ return table.count(langdata)
+end
+
+languages.registered = languages.registered or { }
+languages.associated = languages.associated or { }
+languages.numbers = languages.numbers or { }
+
+storage.register("languages/registered",languages.registered,"languages.registered")
+storage.register("languages/associated",languages.associated,"languages.associated")
+
+local numbers = languages.numbers
+local registered = languages.registered
+local associated = languages.associated
+
+-- we can speed this one up with locals if needed
+
+local function tolang(what)
+ local kind = type(what)
+ if kind == "number" then
+ local w = what >= 0 and what <= 0x7FFF and numbers[what]
+ return (w and langdata[w]) or 0
+ elseif kind == "string" then
+ return langdata[what]
+ else
+ return what
+ end
+end
+
+function languages.setup(what,settings)
+ what = languages.tolang(what or tex.language)
+ local lefthyphen = settings.lefthyphen
+ local righthyphen = settings.righthyphen
+ lefthyphen = lefthyphen ~= "" and lefthyphen or nil
+ righthyphen = righthyphen ~= "" and righthyphen or nil
+ lefthyphen = lefthyphen and utfbyte(lefthyphen) or 0
+ righthyphen = righthyphen and utfbyte(righthyphen) or 0
+ lang.posthyphenchar(what,lefthyphen)
+ lang.prehyphenchar (what,righthyphen)
+ lang.postexhyphenchar(what,lefthyphen)
+ lang.preexhyphenchar (what,righthyphen)
+end
+
+function languages.prehyphenchar(what)
+ return lang.prehyphenchar(tolang(what))
+end
+function languages.posthyphenchar(what)
+ return lang.posthyphenchar(tolang(what))
+end
+
+languages.tolang = tolang
+
+function languages.register(tag,parent,patterns,exceptions)
+ parent = parent or tag
+ registered[tag] = {
+ parent = parent,
+ patterns = patterns or format("lang-%s.pat",parent),
+ exceptions = exceptions or format("lang-%s.hyp",parent),
+ loaded = false,
+ number = 0,
+ }
+end
+
+function languages.associate(tag,script,language)
+ associated[tag] = { script, language }
+end
+
+function languages.association(tag)
+ if type(tag) == "number" then
+ tag = numbers[tag]
+ end
+ local lat = tag and associated[tag]
+ if lat then
+ return lat[1], lat[2]
+ else
+ return nil, nil
+ end
+end
+
+function languages.loadable(tag)
+ local l = registered[tag]
+ if l and l.patterns and resolvers.find_file(patterns) then
+ return true
+ else
+ return false
+ end
+end
+
+languages.share = false -- we don't share language numbers
+
+function languages.enable(tags)
+ -- beware: we cannot set tex.language, but need tex.normallanguage
+ for i=1,#tags do
+ local tag = tags[i]
+ local l = registered[tag]
+ if l and l ~= "" then
+ if not l.loaded then
+ local tag = l.parent
+ local number = languages.hyphenation.number(tag)
+ if languages.share and number > 0 then
+ l.number = number
+ else
+ -- we assume the same filenames
+ l.number = languages.hyphenation.define(tag)
+ languages.hyphenation.loadpatterns(tag,l.patterns)
+ languages.hyphenation.loadexceptions(tag,l.exceptions)
+ numbers[l.number] = tag
+ end
+ l.loaded = true
+ if trace_patterns then
+ logs.report("languages","assigning number %s",l.number)
+ end
+ end
+ if l.number > 0 then
+ return l.number
+ end
+ end
+ end
+ return 0
+end
+
+-- e['implementer']= 'imple{m}{-}{-}menter'
+-- e['manual'] = 'man{}{}{}'
+-- e['as'] = 'a-s'
+-- e['user-friendly'] = 'user=friend-ly'
+-- e['exceptionally-friendly'] = 'excep-tionally=friend-ly'
+
+function languages.hyphenation.loadwords(tag, filename)
+ local id = languages.hyphenation.number(tag)
+ if id > 0 then
+ local l = lang.new(id) or 0
+ statistics.starttiming(languages)
+ local data = io.loaddata(filename) or ""
+ l:hyphenation(data)
+ statistics.stoptiming(languages)
+ end
+end
+
+languages.hyphenation.define ("zerolanguage")
+languages.hyphenation.loadpatterns ("zerolanguage") -- else bug
+languages.hyphenation.loadexceptions("zerolanguage") -- else bug
+
+languages.logger = languages.logger or { }
+
+function languages.logger.report()
+ local result = { }
+ local sorted = table.sortedkeys(registered)
+ for i=1,#sorted do
+ local tag = sorted[i]
+ local l = registered[tag]
+ if l.loaded then
+ local p = (l.patterns and "pat") or '-'
+ local e = (l.exceptions and "exc") or '-'
+ result[#result+1] = format("%s:%s:%s:%s:%s", tag, l.parent, p, e, l.number)
+ end
+ end
+ return (#result > 0 and concat(result," ")) or "none"
+end
+
+-- must happen at the tex end
+
+languages.associate('en','latn','eng')
+languages.associate('uk','latn','eng')
+languages.associate('nl','latn','nld')
+languages.associate('de','latn','deu')
+languages.associate('fr','latn','fra')
+
+statistics.register("loaded patterns", function()
+ local result = languages.logger.report()
+ if result ~= "none" then
+ return result
+ end
+end)
+
+statistics.register("language load time", function()
+ return statistics.elapsedseconds(languages, format(", n=%s",languages.hyphenation.n()))
+end)
diff --git a/tex/context/base/lang-ini.mkii b/tex/context/base/lang-ini.mkii
new file mode 100644
index 000000000..91ac59847
--- /dev/null
+++ b/tex/context/base/lang-ini.mkii
@@ -0,0 +1,696 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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).
+
+%D This module implements the (for the moment still simple)
+%D multi||language support of \CONTEXT, which should not be
+%D confused with the multi||lingual interface. This support
+%D will be extended when needed.
+
+\writestatus{loading}{ConTeXt Language Macros / Initialization}
+
+\unprotect
+
+\ifx\nonfrenchspacing\undefined \let\nonfrenchspacing\relax \fi
+\ifx\frenchspacing \undefined \let\frenchspacing \relax \fi
+
+%D When loading hyphenation patterns, \TEX\ assign a number to
+%D each loaded table, starting with~0. Switching to a specific
+%D table is done by assigning the relevant number to the
+%D predefined \COUNTER\ \type{\language}.
+
+%D We keep track of the last loaded patterns by means of a
+%D pseudo \COUNTER. This just one of those situations in which
+%D we don't want to spent a real one. Language zero has no
+%D patterns, first of all because I like to start numbering
+%D at one. It 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
+%D the languages. The current langage is saved in the macro
+%D \type {\currentlanguage}. The setup macro is mainly used
+%D 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
+
+\def\setupcurrentlanguage[#1]{\setcurrentlanguage\currentmainlanguage{#1}}
+
+\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
+ {\doifsomething{#1}
+ {\ifx\currentmainlanguage\empty\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi
+ \edef\currentmainlanguage{#1}%
+ \setsystemmode{\systemmodeprefix\currentmainlanguage}}%
+ \doifsomething{#2}
+ {\ifx\currentlanguage\empty\else\resetsystemmode\currentlanguage\fi
+ \edef\currentlanguage{#2}%
+ \setsystemmode\currentlanguage}}
+
+%D The internal macros will be defined later.
+
+%D \macros
+%D {installlanguage}
+%D
+%D Hyphenation patterns can only be loaded when the format file
+%D is prepared. The next macro takes care of this loading. A
+%D language is specified with
+%D
+%D \showsetup{installlanguage}
+%D
+%D When \type {state} equals \type {start}, both patterns
+%D and additional hyphenation specifications are loaded. These
+%D files are seached for on the system path and are to be
+%D named:
+%D
+%D \starttyping
+%D \f!languageprefix-identifier.\f!patternsextension
+%D \f!languageprefix-identifier.\f!hyhensextension
+%D \stoptyping
+%D
+%D The \type{spacing} variable specifies how the spaces after
+%D punctuation has to be handled. English is by tradition more
+%D tolerant to inter||sentence spacing than other languages.
+%D
+%D This macro also defines \type {\identifier} as a shortcut
+%D switch to the language. Furthermore the command defined as
+%D being language specific, are executed. With
+%D \type {default} we can default to another language
+%D (patterns) at format generation time. This default language
+%D is overruled when the appropriate patterns are loaded (some
+%D implementations support run time addition of patterns to a
+%D preloaded format).
+
+\def\dodoinstalllanguage#1#2% #2 added
+ {\doifundefined{#1}{\setvalue{#1}{\complexlanguage[#2]}}%
+ \expanded{\noexpand\uppercase{\noexpand\edef\noexpand\ascii{#1}}}%
+ \doifundefined\ascii{\setvalue\ascii{\complexlanguage[#2]}}}
+
+%D \macros
+%D {preloadlanguages}
+%D
+%D We first try to load the files defined as file synonym
+%D for \type {lang-*.pat} and \type {lang-*.hyp}. After that we
+%D fall back on those files. The macro \type {\preloadpatterns}
+%D reports which patterns are loaded and what hyphenmin
+%D values are set.
+
+\let\installedlanguages\empty
+
+\def\doiflanguageelse#1{\doifdefinedelse{\??la#1\c!state}}
+
+\def\doloadlanguagefiles#1%
+ {\doifelsevalue{\??la#1\c!state}\v!start
+ {\edef\languagesuffix{\specificlanguageparameter{#1}\s!patterns}%
+ \ifx\languagesuffix\empty
+ \edef\languagesuffix{\defaultlanguage{#1}}%
+ \else\ifx\languagesuffix\relax
+ \edef\languagesuffix{\defaultlanguage{#1}}%
+ \fi\fi
+ \ifx\languagesuffix\empty
+ \edef\languagesuffix{#1}%
+ \fi
+ \doifundefinedelse{\??la\??la:\currentencoding:\currentmapping:\languagesuffix}
+ {\doloadpatterns{#1}\languagesuffix}
+ {\bgroup
+ \edef\loadedlanguage{\getvalue{\??la\??la:\currentencoding:\currentmapping:\languagesuffix}}%
+ %\showmessage\m!linguals1{\languagesuffix,#1,\loadedlanguage,*,*}%
+ %\showmessage\m!linguals3{\languagesuffix,#1,\loadedlanguage,*,*}%
+ \egroup}}
+ {\showmessage\m!linguals5{#1}}}
+
+\def\doinstalllanguage[#1][#2]%
+ {\doifassignmentelse{#2}
+ {\doiflanguageelse{#1}
+ {\getparameters[\??la#1][#2]}
+ {\setvalue{\l!prefix!#1}{#1}%
+ \addtocommalist{#1}\installedlanguages
+ \dodoinstalllanguage{#1}{#1}%
+ \getparameters[\??la#1][\c!state=\v!start,#2]}%
+ \doloadlanguagefiles{#1}}
+ {\setvalue{\l!prefix!#1}{#2}%
+ \getparameters[\??la#1][\s!default=#2]%
+ \dodoinstalllanguage{#1}{#2}}}
+
+\def\reallanguagetag#1%
+ {\ifcsname\l!prefix!#1\endcsname\csname\l!prefix!#1\endcsname\else#1\fi}
+
+\let\preloadedpatterns\empty
+\let\preloadedpmessage\empty
+
+\def\doshowpatterns#1#2#3#4% language number encoding mapping
+ {#1->#3:#4->#2->\specificlanguageparameter{#1}\s!lefthyphenmin:\specificlanguageparameter{#1}\s!righthyphenmin\space}
+
+\def\preloadlanguages
+ {\doifsomething\preloadedpmessage{\showmessage\m!linguals{10}\preloadedpmessage}}
+
+\def\preloadallpatterns
+ {\gdef\preloadallpatterns##1{\installlanguage[##1][\c!state=\v!start]}%
+ \processcommacommand[\installedlanguages]\preloadallpatterns
+ \global\let\preloadallpatterns\relax}
+
+% ^^ \language[#1] gave unwanted side effect of loading language specifics
+
+\def\installlanguage
+ {\dodoubleargument\doinstalllanguage}
+
+%D When the second argument is a language identifier, a
+%D synonym is created. This feature is present because we
+%D used dutch mnemonics in the dutch version, but nowadays
+%D conform a standard.
+
+\let \patternencoding \s!default
+\let \patternmapping \s!default
+
+\def\doifpatternselse#1%
+ {\expanded{\doifinsetelse{#1}{\preloadedpatterns}}}
+
+\def\doloadpatterns#1#2%
+ {\edef\askedlanguageencoding{\specificlanguageparameter{#1}\s!encoding}%
+ \edef\askedlanguagemapping {\specificlanguageparameter{#1}\s!mapping}%
+ \expanded{\getcommacommandsize[\askedlanguageencoding]}%
+ % slightly faster: \let\unicodechar\utfunihashglyph
+ \ifnum\commalistsize>0
+ %\message{[nofpatterns #2: \commalistsize/\askedlanguageencoding]}%
+ \dorecurse\commalistsize
+ {\expanded{\getfromcommacommand[\askedlanguageencoding][\recurselevel]}%
+ \let\patternencoding\commalistelement
+ \expanded{\getfromcommacommand[\askedlanguagemapping][\recurselevel]}%
+ \let\patternmapping \commalistelement
+ %\message{[patterns: #1/#2/\patternencoding/\patternmapping]}%
+ \dodoloadpatterns{#1}{#2}\patternencoding\patternmapping}%
+ \else
+ %\message{[patterns: #1/#2]}%
+ \dodoloadpatterns{#1}{#2}{}{}%
+ \fi}
+
+\ifnum\texengine=\xetexengine
+
+ \def\doloadpatterns#1#2%
+ {%\letvalue{\??la#2\s!encoding}\empty
+ %\letvalue{\??la#2\s!mapping }\empty
+ \dodoloadpatterns{#1}{#2}{}{}}
+
+\fi
+
+\def\setuphyppatencoding
+ {\pathypsettings
+ \enableregime[utf]}
+
+\def\dodoloadpatterns#1#2#3#4% beware, loaded language also incr
+ {\normallanguage\loadedlanguage % when not really needed
+ \bgroup
+ \let\synchronizepatterns\relax % needed?
+ \let\enabledmapping \empty % needed?
+ \doifelsenothing{#3}{\enableencoding[\s!default]}{\enableencoding[#3]}%
+ \doifelsenothing{#4}{\enablemapping [\s!default]}{\enablemapping [#4]}%
+ \setuphyppatencoding
+ \ifundefined{\??la\??la:\currentencoding:\currentmapping:#2}%
+ \let\doshowpatterns\relax
+ \edef\alreadyloadedlanguage
+ {\executeifdefined{\??la\??la:\currentencoding:\currentmapping:\truefilename{\f!languageprefix#2.\f!patternsextension}}\empty}%
+ \edef\alreadyloadedlanguage
+ {\executeifdefined{\??la\??la:\currentencoding:\currentmapping:\f!languageprefix#2.\f!patternsextension}\alreadyloadedlanguage}%
+ \ifx\alreadyloadedlanguage\empty
+ \letgvalue{\??la\??la:\currentencoding:\currentmapping:#2}\loadedlanguage
+ \doifundefined{\??la\??la:\s!default:\s!default:#2}{\letgvalue{\??la\??la:\s!default:\s!default:#2}\loadedlanguage}% fall back
+ \startpatternloading{\truefilename{\f!languageprefix#2.\f!patternsextension}}{#3}{#4}%
+ \readsysfile{\truefilename{\f!languageprefix#2.\f!patternsextension}}
+ {\setxvalue{\??la#1\s!patterns}{#2}%
+ \setxvalue{\??la\??la:\currentencoding:\currentmapping:\truefilename{\f!languageprefix#2.\f!patternsextension}}{\number\loadedlanguage}%
+ \xdef\preloadedpmessage{\preloadedpmessage\doshowpatterns{#2}{\number\normallanguage}{\currentencoding}{\currentmapping}}%
+ \doglobal\addtocommalist{#2}\preloadedpatterns
+ \showmessage\m!linguals1{#2,#1,\loadedlanguage,\currentencoding,\currentmapping}}
+ {\showmessage\m!linguals2{#2,#1,\loadedlanguage,\currentencoding,\currentmapping,\f!languageprefix#2.\f!patternsextension,\truefilename{\f!languageprefix#2.\f!patternsextension}}}%
+ \stoppatternloading
+ \startpatternloading{\truefilename{\f!languageprefix#2.\f!hyphensextension}}{#3}{#4}%
+ \readsysfile{\truefilename{\f!languageprefix#2.\f!hyphensextension}}
+ {\showmessage\m!linguals3{#2,#1,\loadedlanguage,\currentencoding,\currentmapping}}
+ {\showmessage\m!linguals4{#2,#1,\loadedlanguage,\currentencoding,\currentmapping}}%
+ \stoppatternloading
+ \doglobal\increment\loadedlanguage
+ % \stopencoding
+ \else % optimization, introduced 2004.08.24, while sorting out changes in tl
+ \letgvalue{\??la\??la:\currentencoding:\currentmapping:#2}\alreadyloadedlanguage
+ \doifundefined{\??la\??la:\s!default:\s!default:#2}{\letgvalue{\??la\??la:\s!default:\s!default:#2}\loadedlanguage}% fall back
+ \setxvalue{\??la#1\s!patterns}{#2}%
+ \xdef\preloadedpmessage{\preloadedpmessage\doshowpatterns{#2}{[\number\alreadyloadedlanguage]}{\currentencoding}{\currentmapping}}%
+ \doglobal\addtocommalist{#2}\preloadedpatterns
+ \showmessage\m!linguals1{#2,#1,[\alreadyloadedlanguage],\currentencoding,\currentmapping}%
+ \fi
+ \fi
+ \egroup}
+
+\fetchruntimecommand \showpatterns {\f!languageprefix\s!run.mkii}
+
+%D Since we can only load patterns in ini\TeX, we nil the
+%D loading before dumping (which saves a bit of memory, but
+%D strangely enough not in the format).
+
+\appendtoks
+ \gdef\doloadpatterns{\doglobal\increment\loadedlanguage\gobbletwoarguments}%
+ \globallet\dodoloadpatterns\gobblefourarguments
+\to \everydump
+
+%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.
+
+\unprotected \def\setuplanguage
+ {\dodoubleempty\dosetuplanguage}
+
+\def\dosetuplanguage[#1][#2]% handy patch for testing
+ {\ifsecondargument
+ \getparameters[\??la#1][#2]%
+ \doif{#1}\currentlanguage\docomplexlanguage
+ \else
+ \getparameters[\??la\currentlanguage][#1]%
+ \docomplexlanguage
+ \fi}
+
+\setuplanguage
+ [\s!default]
+ [\s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \s!patterns=,
+ \c!spacing=\v!packed,
+ \s!encoding=,
+ \s!mapping=,
+ \c!lefthyphen=,
+ \c!righthyphen=-,
+ \c!hyphen=-,
+ \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!date={\v!year,\ ,\v!month,\ ,\v!day},
+ \c!text=Ag]
+
+% rather new, split and per language
+
+\setuplanguage
+ [\s!default]
+ [\c!compoundhyphen=\compoundhyphen,
+ \c!leftcompoundhyphen=\compoundhyphen,
+ \c!rightcompoundhyphen=]
+
+%D The values \type {leftsentence} and \type
+%D {rightsentence} can be (and are) used to implement
+%D automatic subsentence boundary glyphs, like in {\fr
+%D |<|french guillemots|>|} or {\de |<|german guillemots|>|} or
+%D {\nl |<|dutch dashes|>|} like situations. Furthermore \type
+%D {leftquotation} and \type {leftquote} come into view
+%D \quotation {when we quote} or \quote {quote} something.
+
+%D \macros
+%D {currentdatespecification}
+%D
+%D Just to make things easy we can ask for the current date
+%D specification by saying:
+
+\def\currentdatespecification{\languageparameter\c!date}
+
+%D This command is not meant for users.
+
+%D Carefull reading of these macros shows that it's legal to
+%D say
+%D
+%D \starttyping
+%D \installlanguage [du] [de]
+%D \stoptyping
+
+%D \macros
+%D {language,mainlanguage}
+%D
+%D Switching to another language (actually another hyphenation
+%D pattern) is done with:
+%D
+%D \starttyping
+%D \language[identifier]
+%D \stoptyping
+%D
+%D or with \type{\identifier}. Just to be compatible with
+%D \PLAIN\ \TEX, we still support the original meaning, so
+%D
+%D \starttyping
+%D \language=1
+%D \stoptyping
+%D
+%D is a valid operation, where the relation between number
+%D and language depends on the order in installing languages.
+%D
+%D \showsetup{language}
+%D \showsetup{mainlanguage}
+%D
+%D Both commands take a predefined language identifier as
+%D argument. We can use \type{\mainlanguage[identifier]} for
+%D setting the (indeed) main language. This is the language
+%D used for translating labels like {\em figure} and {\em
+%D table}. The main language defaults to the current language.
+%D
+%D We take care of local as well as standardized language
+%D switching (fr and fa, de and du, but nl and nl).
+
+\ifx\synchronizepatterns \undefined \let\synchronizepatterns\relax \fi
+\ifx\synchronizepatternswithfont\undefined \def\synchronizepatternswithfont{\synchronizepatterns} \fi
+
+\def\setnormallanguage#1#2% current default
+ {% called quite often, so we use \csname
+ % \def\synchronizepatterns{\setnormallanguage
+ % {\csname\??la\currentlanguage\s!patterns\endcsname}}% called often
+ % of even better pre-expand in an ugly way:
+ \ifnum\normallanguage<\zerocount
+ % we've blocked hyphenation (e.g. verbatim)
+ \else
+ \edef\synchronizepatterns{\noexpand\dosetnormallanguage{\languageparameter\s!patterns}}%
+ \donefalse
+ \synchronizepatterns
+ \ifdone\else
+ \def\synchronizepatterns{\dosetnormallanguage\currentlanguage}%
+ \synchronizepatterns
+ \ifdone\else
+ \ifx\currentdefaultlanguage\empty\else
+ \edef\synchronizepatterns{\noexpand\dosetnormallanguage{\specificlanguageparameter\currentdefaultlanguage\s!patterns}}%
+ \synchronizepatterns
+ \ifdone\else
+ \dosetnormallanguage\currentdefaultlanguage
+ \synchronizepatterns
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\normallanguage\zerocount
+
+\def\dosetnormallanguage#1% #1 == \cs (no longer)
+ {\ifnum\normallanguage<\zerocount
+ % we've blocked hyphenation (e.g. verbatim)
+ \else
+ \dodosetnormallanguage{:\currentencoding:\currentmapping:}{#1}{%
+ \dodosetnormallanguage{:\currentencoding:\s!default :}{#1}{%
+ \dodosetnormallanguage{:\s!default :\currentmapping:}{#1}{%
+ \dodosetnormallanguage{:\s!default :\s!default :}{#1}\empty}}}%
+ \fi}
+
+\def\dodosetnormallanguage#1#2%
+ {\ifcsname\??la\??la#1#2\endcsname
+ \edef\thenormallanguage{\csname\??la\??la#1#2\endcsname}% can be \chardef
+ \ifx\thenormallanguage\empty
+ \@EAEAEA\firstofoneargument
+ \else
+ \donetrue
+ \@EA\xdef\csname\??la\currentlanguage\s!patterns\endcsname{#2}%
+ \normallanguage\thenormallanguage\relax % \relax is needed for lookahead problems
+ \@EAEAEA\gobbleoneargument
+ \fi
+ \else
+ \@EA\firstofoneargument
+ \fi}
+
+\newevery \everylanguage \relax
+
+\def\disablelanguagespecifics
+ {\ignorecompoundcharacter}
+
+\def\sethyphenationvariables
+ {\lefthyphenmin 0\languageparameter\s!lefthyphenmin \relax
+ \righthyphenmin0\languageparameter\s!righthyphenmin\relax
+ \lefthyphenmin \numexpr\lefthyphenmin +\hyphenminoffset\relax
+ \righthyphenmin\numexpr\righthyphenmin+\hyphenminoffset\relax}
+
+\def\docomplexlanguage% assumes that \currentlanguage is set
+ {\edef\currentdefaultlanguage{\defaultlanguage\currentlanguage}%
+ \setnormallanguage\currentlanguage\currentdefaultlanguage
+ \the\everylanguage
+ \enablelanguagespecifics[\currentlanguage]%
+ \sethyphenationvariables
+ \relax
+ % will be definable and move to core-spa !
+ \doifelse{\languageparameter\c!spacing}\v!broad\nonfrenchspacing\frenchspacing}
+
+\ifx\enablelanguagespecifics\undefined \def\enablelanguagespecifics[#1]{} \fi
+
+% The following may be a solution for the fact that one cannot
+% change catcodes of characters like : and ; inside an environment.
+
+\appendtoks
+ \enablelanguagespecifics[\currentlanguage]%
+\to \everystarttext
+
+\def\complexlanguage[#1]%
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty \else
+ \ifcsname\l!prefix!\askedlanguage\endcsname
+ \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
+ \ifx\currentlanguage\askedlanguage \else
+ \setcurrentlanguage\currentmainlanguage\askedlanguage
+ \docomplexlanguage
+ \fi
+ \else
+ \showmessage\m!linguals6{#1}%
+ \fi
+ \fi}
+
+\let\simplelanguage\normallanguage
+
+\definecomplexorsimple\language
+
+\def\mainlanguage[#1]%
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty \else
+ \ifcsname\l!prefix!\askedlanguage\endcsname
+ \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
+ \ifx\currentlanguage\askedlanguage
+ \ifx\currentmainlanguage\askedlanguage
+ \else
+ \setcurrentlanguage\askedlanguage\askedlanguage
+ \docomplexlanguage
+ \fi
+ \else
+ \setcurrentlanguage\askedlanguage\askedlanguage
+ \docomplexlanguage
+ \fi
+ \fi
+ \fi}
+
+%D \macros
+%D {defaultlanguage,languageparameter,specificlanguageparameter}
+
+\def\defaultlanguage#1%
+ {\ifcsname\??la#1\s!default\endcsname
+ \expandafter\defaultlanguage\csname\??la#1\s!default\endcsname
+ \else
+ #1%
+ \fi}
+
+\def\languageparameter#1%
+ {\ifcsname\??la\currentlanguage#1\endcsname
+ \csname\??la\currentlanguage#1\endcsname
+ \else\ifcsname\??la\currentlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\csname\??la\currentlanguage\s!default\endcsname{#1}%
+ \else\ifcsname\??la\s!default#1\endcsname
+ \csname\??la\s!default#1\endcsname
+ \fi\fi\fi}
+
+\def\specificlanguageparameter#1#2%
+ {\ifcsname\??la#1#2\endcsname
+ \csname\??la#1#2\endcsname
+ \else\ifcsname\??la#1\s!default\endcsname
+ \expandafter\specificlanguageparameter\csname\??la#1\s!default\endcsname{#2}%
+ \else\ifcsname\??la\s!default#2\endcsname
+ \csname\??la\s!default#2\endcsname
+ \fi\fi\fi}
+
+%D New (see nomarking and nolist):
+
+\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
+%D placement depends on the current language, therefore we show
+%D the defaults here.
+%D
+%D \def\ShowLanguageValues [#1] [#2] #3 #4
+%D {\blank
+%D \startlinecorrection
+%D \vbox\bgroup
+%D \language[#1]%
+%D \setbox0=\hbox to \hsize{\hss\bf#2 subsentence symbol and quotes\hss}
+%D \dp0=0pt
+%D \box0
+%D \vskip.5em
+%D \hrule
+%D \vskip.5em
+%D \let\normalbar=|
+%D \hbox to \hsize
+%D {\hfil\quotation{#3 #4}\hfil\quote{#2}\hfil
+%D \let|=\normalbar\strut|<||<|#3|>|#4|>|\hfil}
+%D \vskip.5em
+%D \hrule
+%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 [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
+%D loaded in separate files, according to their roots. Here
+%D we only take care of (postponed) setting of the current
+%D 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
+
+% \bgroup \normallanguage255 \patterns{} \egroup
+% \def\nopatterns{\normallanguage255 }
+
+\def\nopatterns{\normallanguage\minusone}
+
+%D \XETEX\ is \UNICODE:
+
+\ifnum\texengine=\xetexengine
+
+ \def\synchronizepatternswithfont{}
+ \def\doloadpatterns #1#2{\dodoloadpatterns{#1}{#2}\s!default\s!default}
+ \def\dosetnormallanguage #1{\dodosetnormallanguage{:\s!default:\s!default:}{#1}\empty}
+ \def\setuphyppatencoding {\pathypsettings}
+
+\fi
+
+%D We default to the language belonging to the interface. This
+%D is one of the few places outside the interface modules where
+%D \type{\startinterface} is used.
+
+%D We default to english:
+
+\setupcurrentlanguage[\s!en]
+
+\def\initializemainlanguage
+ {\mainlanguage[\currentlanguage]%
+ \showmessage\m!linguals9\currentlanguage}
+
+\protect \endinput
diff --git a/tex/context/base/lang-ini.mkiv b/tex/context/base/lang-ini.mkiv
new file mode 100644
index 000000000..45bb71b85
--- /dev/null
+++ b/tex/context/base/lang-ini.mkiv
@@ -0,0 +1,560 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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).
+
+%D This module implements the (for the moment still simple)
+%D multi||language support of \CONTEXT, which should not be
+%D confused with the multi||lingual interface. This support
+%D will be extended when needed.
+
+\writestatus{loading}{ConTeXt Language Macros / Initialization}
+
+\registerctxluafile{lang-ini}{1.001}
+
+\unprotect
+
+% \def\testlanguage[#1]%
+% {\start
+% \language[#1]
+% \number\normallanguage/\the\lefthyphenmin/\the\righthyphenmin:
+% \input tufte
+% \hyphenatedword{effetestenofditwerkt}
+% \par
+% \stop}
+%
+% \testlanguage[de] \testlanguage[de-de] \testlanguage[de-at] \testlanguage[de-ch] \page
+% \testlanguage[en] \testlanguage[us] \testlanguage[en-us] \testlanguage[uk] \testlanguage[en-gb] \page
+
+\ifx\nonfrenchspacing\undefined \let\nonfrenchspacing\relax \fi
+\ifx\frenchspacing \undefined \let\frenchspacing \relax \fi
+
+%D When loading hyphenation patterns, \TEX\ assign a number to
+%D each loaded table, starting with~0. Switching to a specific
+%D table is done by assigning the relevant number to the
+%D predefined \COUNTER\ \type{\language}.
+
+%D We keep track of the last loaded patterns by means of a
+%D pseudo \COUNTER. This just one of those situations in which
+%D we don't want to spent a real one. Language zero has no
+%D patterns, first of all because I like to start numbering
+%D at one. It 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
+%D the languages. The current langage is saved in the macro
+%D \type {\currentlanguage}. The setup macro is mainly used
+%D 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
+
+\unexpanded\def\setupcurrentlanguage[#1]{\setcurrentlanguage\currentmainlanguage{#1}}
+
+\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
+%D is prepared. The next macro takes care of this loading. A
+%D language is specified with
+%D
+%D \showsetup{installlanguage}
+%D
+%D When \type {state} equals \type {start}, both patterns
+%D and additional hyphenation specifications are loaded. These
+%D files are seached for on the system path and are to be
+%D named:
+%D
+%D \starttyping
+%D \f!languageprefix-identifier.\f!patternsextension
+%D \f!languageprefix-identifier.\f!hyhensextension
+%D \stoptyping
+%D
+%D The \type{spacing} variable specifies how the spaces after
+%D punctuation has to be handled. English is by tradition more
+%D tolerant to inter||sentence spacing than other languages.
+%D
+%D This macro also defines \type {\identifier} as a shortcut
+%D switch to the language. Furthermore the command defined as
+%D being language specific, are executed. With
+%D \type {default} we can default to another language
+%D (patterns) at format generation time. This default language
+%D is overruled when the appropriate patterns are loaded (some
+%D implementations support run time addition of patterns to a
+%D preloaded format).
+
+\def\dodoinstalllanguage#1#2% #2 added
+ {\expanded{\noexpand\uppercase{\noexpand\edef\noexpand\ascii{#1}}}%
+ \ifcsname #1\endcsname\else\setvalue {#1}{\complexlanguage[#2]}\fi
+ \ifcsname\ascii\endcsname\else\setvalue\ascii{\complexlanguage[#2]}\fi}
+
+%D \macros
+%D {preloadlanguages}
+%D
+%D We first try to load the files defined as file synonym
+%D for \type {lang-*.pat} and \type {lang-*.hyp}. After that we
+%D fall back on those files. The macro \type {\preloadpatterns}
+%D reports which patterns are loaded and what hyphenmin
+%D values are set.
+
+\let\installedlanguages\empty
+
+\def\doiflanguageelse#1{\doifdefinedelse{\??la#1\c!state}}
+
+\def\doloadpatterns#1#2%
+ {\ctxlua{languages.register(
+ "#1",
+ "#2",
+ "\truefilename{\f!languageprefix#2.\f!patternsextension}",
+ "\truefilename{\f!languageprefix#2.\f!hyphensextension }")
+ }}
+
+\def\doloadlanguagefiles#1%
+ {\edef\languagesuffix{\specificlanguageparameter{#1}\s!patterns}%
+ \ifx\languagesuffix\empty
+ \edef\languagesuffix{\defaultlanguage{#1}}%
+ \else\ifx\languagesuffix\relax
+ \edef\languagesuffix{\defaultlanguage{#1}}%
+ \fi\fi
+ \ifx\languagesuffix\empty
+ \edef\languagesuffix{#1}%
+ \fi
+ \doloadpatterns{#1}\languagesuffix}
+
+\def\doinstalllanguage[#1][#2]%
+ {\doifassignmentelse{#2}
+ {\doiflanguageelse{#1}
+ {\getparameters[\??la#1][#2]}
+ {\setvalue{\l!prefix!#1}{#1}%
+ \addtocommalist{#1}\installedlanguages
+ \dodoinstalllanguage{#1}{#1}%
+ \getparameters[\??la#1][\c!state=\v!start,#2]}%
+ \doloadlanguagefiles{#1}}
+ {\setvalue{\l!prefix!#1}{#2}%
+ \getparameters[\??la#1][\s!default=#2]%
+ \dodoinstalllanguage{#1}{#2}}}
+
+\def\reallanguagetag#1%
+ {\ifcsname\l!prefix!#1\endcsname\csname\l!prefix!#1\endcsname\else#1\fi}
+
+% ^^ \language[#1] gave unwanted side effect of loading language specifics
+
+\def\installlanguage
+ {\dodoubleargument\doinstalllanguage}
+
+%D When the second argument is a language identifier, a
+%D synonym is created. This feature is present because we
+%D used dutch mnemonics in the dutch version, but nowadays
+%D conform a standard.
+
+\def\doifpatternselse#1%
+ {\ctxlua{cs.testcase(languages.loadable("#1"))}}
+
+%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\dosetuplanguage}
+
+\def\dosetuplanguage[#1][#2]% handy patch for testing
+ {\ifsecondargument
+ \getparameters[\??la#1][#2]%
+ \doif{#1}\currentlanguage\docomplexlanguage
+ \else
+ \getparameters[\??la\currentlanguage][#1]%
+ \docomplexlanguage
+ \fi}
+
+\setuplanguage
+ [\s!default]
+ [\s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \s!patterns=,
+ \c!spacing=\v!packed,
+ \c!lefthyphen=,
+ \c!righthyphen=-,
+ \c!hyphen=-,
+ \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!date={\v!year,\ ,\v!month,\ ,\v!day},
+ \c!text=Ag]
+
+% rather new, split and per language
+
+\setuplanguage
+ [\s!default]
+ [\c!compoundhyphen=\compoundhyphen,
+ \c!rightcompoundhyphen=\compoundhyphen,
+ \c!leftcompoundhyphen=]
+
+%D The values \type {leftsentence} and \type
+%D {rightsentence} can be (and are) used to implement
+%D automatic subsentence boundary glyphs, like in {\fr
+%D |<|french guillemots|>|} or {\de |<|german guillemots|>|} or
+%D {\nl |<|dutch dashes|>|} like situations. Furthermore \type
+%D {leftquotation} and \type {leftquote} come into view
+%D \quotation {when we quote} or \quote {quote} something.
+
+%D \macros
+%D {currentdatespecification}
+%D
+%D Just to make things easy we can ask for the current date
+%D specification by saying:
+
+\def\currentdatespecification{\languageparameter\c!date}
+
+%D This command is not meant for users.
+
+%D Carefull reading of these macros shows that it's legal to
+%D say
+%D
+%D \starttyping
+%D \installlanguage [du] [de]
+%D \stoptyping
+
+%D \macros
+%D {language,mainlanguage}
+%D
+%D Switching to another language (actually another hyphenation
+%D pattern) is done with:
+%D
+%D \starttyping
+%D \language[identifier]
+%D \stoptyping
+%D
+%D or with \type{\identifier}. Just to be compatible with
+%D \PLAIN\ \TEX, we still support the original meaning, so
+%D
+%D \starttyping
+%D \language=1
+%D \stoptyping
+%D
+%D is a valid operation, where the relation between number
+%D and language depends on the order in installing languages.
+%D
+%D \showsetup{language}
+%D \showsetup{mainlanguage}
+%D
+%D Both commands take a predefined language identifier as
+%D argument. We can use \type{\mainlanguage[identifier]} for
+%D setting the (indeed) main language. This is the language
+%D used for translating labels like {\em figure} and {\em
+%D table}. The main language defaults to the current language.
+%D
+%D We take care of local as well as standardized language
+%D switching (fr and fa, de and du, but nl and nl).
+
+\def\dosetnormallanguage#1#2% current default
+ {\edef\askedlanguagepatterns{\specificlanguageparameter{#1}\s!patterns}%
+ \normallanguage=\ctxlua{tex.sprint(languages.enable({"\askedlanguagepatterns","#1","#2"}))}%
+ \ifproductionrun
+ \setxvalue{\??la\??la#1#2}{\number\normallanguage}%
+ \fi}
+
+\def\setnormallanguage#1#2% current default / we can freeze the number here
+ {\ifcsname\??la\??la#1#2\endcsname
+ \normallanguage\csname\??la\??la#1#2\endcsname % todo: we can set language at the lua end now
+ \else
+ \dosetnormallanguage{#1}{#2}%
+ \fi}
+
+\newtoks \everylanguage
+
+\def\sethyphenationvariables % as we can have cloning we need to set it each time, unless we move all to lua
+ {\ctxlua{languages.setup(tex.language, {
+ lefthyphen = "\languageparameter\c!lefthyphen",
+ righthyphen = "\languageparameter\c!righthyphen",
+ } )}%
+ \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax
+ \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax}
+
+\def\docomplexlanguage% assumes that \currentlanguage is set
+ {\edef\currentdefaultlanguage{\defaultlanguage\currentlanguage}%
+ \setnormallanguage\currentlanguage\currentdefaultlanguage
+ \the\everylanguage
+ \sethyphenationvariables
+ \relax
+ % will be definable and move to core-spa !
+ \doifelse{\languageparameter\c!spacing}\v!broad\nonfrenchspacing\frenchspacing}
+
+% \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\ }
+
+% The following may be a solution for the fact that one cannot
+% change catcodes of characters like : and ; inside an environment.
+
+\def\complexlanguage[#1]%
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty \else
+ \ifcsname\l!prefix!\askedlanguage\endcsname
+ \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
+ \ifx\currentlanguage\askedlanguage \else
+ \setcurrentlanguage\currentmainlanguage\askedlanguage
+ \docomplexlanguage
+ \fi
+ \else
+ \showmessage\m!linguals6{#1}%
+ \fi
+ \fi}
+
+\let\simplelanguage\normallanguage
+
+\definecomplexorsimple\language
+
+\def\mainlanguage[#1]%
+ {\edef\askedlanguage{#1}%
+ \ifx\askedlanguage\empty \else
+ \ifcsname\l!prefix!\askedlanguage\endcsname
+ \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
+ \ifx\currentlanguage\askedlanguage
+ \ifx\currentmainlanguage\askedlanguage
+ \else
+ \setcurrentlanguage\askedlanguage\askedlanguage
+ \docomplexlanguage
+ \fi
+ \else
+ \setcurrentlanguage\askedlanguage\askedlanguage
+ \docomplexlanguage
+ \fi
+ \fi
+ \fi}
+
+%D \macros
+%D {defaultlanguage,languageparameter,specificlanguageparameter}
+
+\def\defaultlanguage#1%
+ {\ifcsname\??la#1\s!default\endcsname
+ \expandafter\defaultlanguage\csname\??la#1\s!default\endcsname
+ \else
+ #1%
+ \fi}
+
+\def\languageparameter#1%
+ {\ifcsname\??la\currentlanguage#1\endcsname
+ \csname\??la\currentlanguage#1\endcsname
+ \else\ifcsname\??la\currentlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\csname\??la\currentlanguage\s!default\endcsname{#1}%
+ \else\ifcsname\??la\s!default#1\endcsname
+ \csname\??la\s!default#1\endcsname
+ \fi\fi\fi}
+
+\def\specificlanguageparameter#1#2%
+ {\ifcsname\??la#1#2\endcsname
+ \csname\??la#1#2\endcsname
+ \else\ifcsname\??la#1\s!default\endcsname
+ \expandafter\specificlanguageparameter\csname\??la#1\s!default\endcsname{#2}%
+ \else\ifcsname\??la\s!default#2\endcsname
+ \csname\??la\s!default#2\endcsname
+ \fi\fi\fi}
+
+%D New (see nomarking and nolist):
+
+\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
+%D placement depends on the current language, therefore we show
+%D the defaults here.
+%D
+%D \def\ShowLanguageValues [#1] [#2] #3 #4
+%D {\blank
+%D \startlinecorrection
+%D \vbox\bgroup
+%D \language[#1]%
+%D \setbox0=\hbox to \hsize{\hss\bf#2 subsentence symbol and quotes\hss}
+%D \dp0=0pt
+%D \box0
+%D \vskip.5em
+%D \hrule
+%D \vskip.5em
+%D \let\normalbar=|
+%D \hbox to \hsize
+%D {\hfil\quotation{#3 #4}\hfil\quote{#2}\hfil
+%D \let|=\normalbar\strut|<||<|#3|>|#4|>|\hfil}
+%D \vskip.5em
+%D \hrule
+%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 [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
+%D loaded in separate files, according to their roots. Here
+%D we only take care of (postponed) setting of the current
+%D 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
+
+% \bgroup \normallanguage255 \patterns{} \egroup
+% \def\nopatterns{\normallanguage255 }
+
+\def\nopatterns{\normallanguage\minusone}
+
+%D We default to the language belonging to the interface. This
+%D is one of the few places outside the interface modules where
+%D \type{\startinterface} is used.
+
+%D We default to english:
+
+\setupcurrentlanguage[\s!en]
+
+\def\initializemainlanguage
+ {\mainlanguage[\currentlanguage]%
+ \showmessage\m!linguals9\currentlanguage}
+
+%D Might be in use:
+
+\let\preloadallpatterns\relax % just for old times sake
+\let\preloadlanguages \relax % just for old times sake
+
+\uchyph=1
+
+\exhyphenchar=45 % to permit breaking at explicit hyphens
+
+\protect \endinput
diff --git a/tex/context/base/lang-ita.tex b/tex/context/base/lang-ita.tex
new file mode 100644
index 000000000..03efb0614
--- /dev/null
+++ b/tex/context/base/lang-ita.tex
@@ -0,0 +1,518 @@
+%D \module
+%D [ file=lang-ita,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Italic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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: replace \'.. by \namedglyph
+
+\writestatus{loading}{ConTeXt Language Macros / Italic Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+%D
+%D \starttabulate[|lB|l|]
+%D \NC Italian \NC Giuseppe Bilotta \NC \NR
+%D \NC Romanian \NC Dan Seracu \NC \NR
+%D \NC Portuguese \NC Pedro F. M. Mendon\c a \NC \NR
+%D \stoptabulate
+
+% Latin, Italian, Rhaeto-Romanic, Rumanian, Sardian
+% Catalan, French, Ladino, Portuguese, Proven\c{c}al, Spanish
+
+\unprotect
+
+\ifx\guillemotspace\undefined \let\guillemotspace\empty \fi
+\ifx\sentencespace \undefined \let\sentencespace \empty \fi
+
+\installlanguage
+ [\s!fr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\leftguillemot,
+ \c!rightquote=\rightguillemot,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day+,\v!space,\v!month,\v!space,\v!year},
+ \s!mapping={texnansi,ec},
+ \s!encoding={texnansi,ec}]
+
+\installlanguage
+ [\s!es]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year}]
+
+\installlanguage [sp] [\s!es] % old times context
+
+\installlanguage
+ [\s!ca]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year}]
+
+% Note GB left|/|right (sub)sentences are for \quote {incisi}.
+
+\installlanguage
+ [\s!it]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=--,
+ \c!rightsubsentence=--,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!leftspeech=\leftguillemot,
+ \c!middlespeech=\leftguillemot,
+ \c!rightspeech=\rightguillemot,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year},
+ \s!mapping={texnansi,ec},
+ \s!encoding={texnansi,ec}]
+
+\installlanguage % the same as italian
+ [\s!la]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\lowerrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\lowerrightdoubleninequote,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year}]
+
+\installlanguage
+ [\s!pt]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\ ,\v!month,\ ,\v!day},
+ \s!mapping={texnansi,ec},
+ \s!encoding={texnansi,ec}]
+
+\installlanguage
+ [\s!ro]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\leftguillemot,
+ \c!rightquote=\rightguillemot,
+ \c!leftquotation=\lowerrightdoubleninequote,
+ \c!rightquotation=\upperleftdoublesixquote,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year}]
+
+%D For compatibility reasons we also define:
+
+\installlanguage [fa] [\s!fr] % for dutchies only
+
+\installlanguage [french] [\s!fr]
+\installlanguage [spanish] [\s!es]
+\installlanguage [catalan] [\s!ca]
+\installlanguage [italian] [\s!it]
+\installlanguage [latin] [\s!la]
+\installlanguage [portuguese] [\s!pt]
+\installlanguage [romanian] [\s!ro]
+
+%D Labels and header texts.
+
+\setupheadtext [\s!fr] [\v!content=Table des mati\`eres]
+\setupheadtext [\s!es] [\v!content=\'Indice]
+\setupheadtext [\s!ca] [\v!content=\'Index de continguts]
+\setupheadtext [\s!it] [\v!content=Indice]
+\setupheadtext [\s!la] [\v!content=Quod in libro continetur] %Argumentum
+\setupheadtext [\s!pt] [\v!content=Conte\'udo]
+\setupheadtext [\s!ro] [\v!content=Cuprins]
+
+\setupheadtext [\s!fr] [\v!tables=Tableaux]
+\setupheadtext [\s!es] [\v!tables=Tablas]
+\setupheadtext [\s!ca] [\v!tables=Taules]
+\setupheadtext [\s!it] [\v!tables=Tabelle]
+\setupheadtext [\s!la] [\v!tables=Tabulae]
+\setupheadtext [\s!pt] [\v!tables=Tabelas]
+\setupheadtext [\s!ro] [\v!tables=Tabele]
+
+\setupheadtext [\s!fr] [\v!figures=Figures]
+\setupheadtext [\s!es] [\v!figures=Ilustraciones]
+\setupheadtext [\s!ca] [\v!figures=Figures]
+\setupheadtext [\s!it] [\v!figures=Figure]
+\setupheadtext [\s!la] [\v!figures=Imagines]
+\setupheadtext [\s!pt] [\v!figures=Figuras]
+\setupheadtext [\s!ro] [\v!figures=Figuri]
+
+\setupheadtext [\s!fr] [\v!graphics=Graphiques]
+\setupheadtext [\s!es] [\v!graphics=Gr\'aficos]
+\setupheadtext [\s!it] [\v!graphics=Grafici]
+\setupheadtext [\s!ca] [\v!graphics=Gr\`afiques]
+\setupheadtext [\s!la] [\v!graphics=Typi]
+\setupheadtext [\s!pt] [\v!graphics=Gr\'aficos]
+\setupheadtext [\s!ro] [\v!graphics=Grafice]
+
+\setupheadtext [\s!fr] [\v!intermezzi=Interm\`edes]
+\setupheadtext [\s!es] [\v!intermezzi=Intermedios]
+\setupheadtext [\s!ca] [\v!intermezzi=Intermedis]
+\setupheadtext [\s!it] [\v!intermezzi=Intermezzi]
+\setupheadtext [\s!la] [\v!intermezzi=Intermissa]
+\setupheadtext [\s!pt] [\v!intermezzi=Interm\'edios]
+\setupheadtext [\s!ro] [\v!intermezzi=Intermzzo]
+
+\setupheadtext [\s!fr] [\v!index=Index]
+\setupheadtext [\s!es] [\v!index=\'Indice alfab\'etico]
+\setupheadtext [\s!ca] [\v!index=\'Index alfab\`etic]
+\setupheadtext [\s!it] [\v!index=Indice]
+\setupheadtext [\s!la] [\v!index=Indices]
+\setupheadtext [\s!pt] [\v!index=\'Indice]
+\setupheadtext [\s!ro] [\v!index=Index]
+
+\setupheadtext [\s!fr] [\v!abbreviations=Abr\'eviations]
+\setupheadtext [\s!es] [\v!abbreviations=Abreviaturas]
+\setupheadtext [\s!ca] [\v!abbreviations=Abreviacions]
+\setupheadtext [\s!it] [\v!abbreviations=Abbreviazioni]
+\setupheadtext [\s!la] [\v!abbreviations=Notae]
+\setupheadtext [\s!pt] [\v!abbreviations=Abreviaturas]
+\setupheadtext [\s!ro] [\v!abbreviations=Abrevieri]
+
+\setupheadtext [\s!fr] [\v!logos=Logos]
+\setupheadtext [\s!es] [\v!logos=Logotipos]
+\setupheadtext [\s!ca] [\v!logos=Logotips]
+\setupheadtext [\s!it] [\v!logos=Logotipi]
+\setupheadtext [\s!la] [\v!logos=Typi negotiales]
+\setupheadtext [\s!pt] [\v!logos=Logotipos]
+\setupheadtext [\s!ro] [\v!logos=Logo-uri]
+
+\setupheadtext [\s!fr] [\v!units=Unit\'es]
+\setupheadtext [\s!es] [\v!units=Unidades]
+\setupheadtext [\s!ca] [\v!units=Unitats]
+\setupheadtext [\s!it] [\v!units=Unit\`a]
+\setupheadtext [\s!la] [\v!units=Modi]
+\setupheadtext [\s!pt] [\v!units=Unidades]
+\setupheadtext [\s!ro] [\v!units=Unit\u{a}\c{t}i]
+
+\setupheadtext [\s!fr] [pubs=Bibliographie]
+\setupheadtext [\s!es] [pubs=Bibliograf\'\ia]
+\setupheadtext [\s!ca] [pubs=Referències]
+\setupheadtext [\s!it] [pubs=Bibliografia]
+%setupheadtext [\s!la] [pubs=?]
+%setupheadtext [\s!pt] [pubs=?]
+%setupheadtext [\s!ro] [pubs=?]
+
+\setuplabeltext [\s!fr] [\v!table=Tableau ]
+\setuplabeltext [\s!es] [\v!table=Tabla ]
+\setuplabeltext [\s!ca] [\v!table=Taula ]
+\setuplabeltext [\s!it] [\v!table=Tabella ]
+\setuplabeltext [\s!la] [\v!table=Tabula ]
+\setuplabeltext [\s!pt] [\v!table=Tabela ]
+\setuplabeltext [\s!ro] [\v!table=Tabelul ]
+
+\setuplabeltext [\s!fr] [\v!figure=Figure ]
+\setuplabeltext [\s!es] [\v!figure=Ilustraci\'on ]
+\setuplabeltext [\s!ca] [\v!figure=Figura ]
+\setuplabeltext [\s!it] [\v!figure=Fig. ]
+\setuplabeltext [\s!la] [\v!figure=Imago ]
+\setuplabeltext [\s!pt] [\v!figure=Figura ]
+\setuplabeltext [\s!ro] [\v!figure=Figura ]
+
+\setuplabeltext [\s!fr] [\v!intermezzo=Interm\`ede ]
+\setuplabeltext [\s!es] [\v!intermezzo=Intermedio ]
+\setuplabeltext [\s!ca] [\v!intermezzo=Intermedi ]
+\setuplabeltext [\s!it] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!la] [\v!intermezzo=Intermissum ]
+\setuplabeltext [\s!pt] [\v!intermezzo=Interm\'edio ]
+\setuplabeltext [\s!ro] [\v!intermezzo=Intermezzo ]
+
+\setuplabeltext [\s!fr] [\v!graphic=Illustration ]
+\setuplabeltext [\s!es] [\v!graphic=Gr\'afico ]
+\setuplabeltext [\s!ca] [\v!graphic=Gr\`afica ]
+\setuplabeltext [\s!it] [\v!graphic=Grafico ]
+\setuplabeltext [\s!la] [\v!graphic=Typus ]
+\setuplabeltext [\s!pt] [\v!graphic=Gr\'afico ]
+\setuplabeltext [\s!ro] [\v!graphic=Graficul ]
+
+\setuplabeltext [\s!fr] [\v!chapter=] % Chapitre
+\setuplabeltext [\s!es] [\v!chapter=] % Cap\'\i tulo
+\setuplabeltext [\s!ca] [\v!chapter=] % Cap\'\i tol
+\setuplabeltext [\s!it] [\v!chapter=]
+\setuplabeltext [\s!la] [\v!chapter=]
+\setuplabeltext [\s!pt] [\v!chapter=]
+\setuplabeltext [\s!ro] [\v!chapter=]
+
+\setuplabeltext [\s!fr] [\v!section=] % Section
+\setuplabeltext [\s!es] [\v!section=] % Secci\'on
+\setuplabeltext [\s!ca] [\v!section=] % Secci\'o
+\setuplabeltext [\s!it] [\v!section=]
+\setuplabeltext [\s!la] [\v!section=]
+\setuplabeltext [\s!pt] [\v!section=]
+\setuplabeltext [\s!ro] [\v!section=]
+
+\setuplabeltext [\s!fr] [\v!subsection=] % Soussection
+\setuplabeltext [\s!es] [\v!subsection=] % Subsecci\'on
+\setuplabeltext [\s!ca] [\v!subsection=] % Subsecci\'o
+\setuplabeltext [\s!it] [\v!subsection=]
+\setuplabeltext [\s!la] [\v!subsection=]
+\setuplabeltext [\s!pt] [\v!subsection=]
+\setuplabeltext [\s!ro] [\v!subsection=]
+
+\setuplabeltext [\s!fr] [\v!subsubsection=] % Soussoussection
+\setuplabeltext [\s!es] [\v!subsubsection=] % Subsubsecci\'on
+\setuplabeltext [\s!ca] [\v!subsubsection=] % Subsubsecci\'o
+\setuplabeltext [\s!it] [\v!subsubsection=]
+\setuplabeltext [\s!la] [\v!subsubsection=]
+\setuplabeltext [\s!pt] [\v!subsubsection=]
+\setuplabeltext [\s!ro] [\v!subsubsection=]
+
+\setuplabeltext [\s!fr] [\v!subsubsubsection=] % Soussoussoussection
+\setuplabeltext [\s!es] [\v!subsubsubsection=] % Subsubsubsecci\'on
+\setuplabeltext [\s!ca] [\v!subsubsubsection=] % Subsubsubsecci\'o
+\setuplabeltext [\s!it] [\v!subsubsubsection=]
+\setuplabeltext [\s!la] [\v!subsubsubsection=]
+\setuplabeltext [\s!pt] [\v!subsubsubsection=]
+\setuplabeltext [\s!ro] [\v!subsubsubsection=]
+
+\setuplabeltext [\s!fr] [\v!appendix=] % Annexe
+\setuplabeltext [\s!es] [\v!appendix=] % Ap\'endice
+\setuplabeltext [\s!ca] [\v!appendix=] % Ap\`endix
+\setuplabeltext [\s!it] [\v!appendix=]
+\setuplabeltext [\s!la] [\v!appendix=]
+\setuplabeltext [\s!pt] [\v!appendix=]
+\setuplabeltext [\s!ro] [\v!appendix=]
+
+\setuplabeltext [\s!fr] [\v!part=Partie ]
+\setuplabeltext [\s!es] [\v!part=Parte ]
+\setuplabeltext [\s!ca] [\v!part=Part ]
+\setuplabeltext [\s!it] [\v!part=Parte ]
+\setuplabeltext [\s!la] [\v!part=Pars ]
+\setuplabeltext [\s!pt] [\v!part=Parte ]
+\setuplabeltext [\s!ro] [\v!part=Partea ]
+
+\setuplabeltext [\s!fr] [\v!line=ligne ]
+\setuplabeltext [\s!es] [\v!line=l\'\i nea ]
+\setuplabeltext [\s!ca] [\v!line=l\'\i nia ]
+\setuplabeltext [\s!it] [\v!line=riga ]
+\setuplabeltext [\s!la] [\v!line=versus ]
+\setuplabeltext [\s!pt] [\v!line=linha ]
+\setuplabeltext [\s!ro] [\v!line=linia ]
+
+\setuplabeltext [\s!fr] [\v!lines=lignes ]
+\setuplabeltext [\s!es] [\v!lines=l\'\i neas ]
+\setuplabeltext [\s!ca] [\v!lines=l\'\i nies ]
+\setuplabeltext [\s!it] [\v!lines=righe ]
+\setuplabeltext [\s!la] [\v!lines=versus ]
+\setuplabeltext [\s!pt] [\v!lines=linhas ]
+\setuplabeltext [\s!ro] [\v!lines=liniile ]
+
+\setuplabeltext [\s!fr] [\v!january=janvier]
+\setuplabeltext [\s!fr] [\v!february=f\'evrier]
+\setuplabeltext [\s!fr] [\v!march=mars]
+\setuplabeltext [\s!fr] [\v!april=avril]
+\setuplabeltext [\s!fr] [\v!may=mai]
+\setuplabeltext [\s!fr] [\v!june=juin]
+\setuplabeltext [\s!fr] [\v!july=juillet]
+\setuplabeltext [\s!fr] [\v!august=ao\^ut]
+\setuplabeltext [\s!fr] [\v!september=septembre]
+\setuplabeltext [\s!fr] [\v!october=octobre]
+\setuplabeltext [\s!fr] [\v!november=novembre]
+\setuplabeltext [\s!fr] [\v!december=d\'ecembre]
+
+\setuplabeltext [\s!es] [\v!january=enero]
+\setuplabeltext [\s!es] [\v!february=febrero]
+\setuplabeltext [\s!es] [\v!march=marzo]
+\setuplabeltext [\s!es] [\v!april=abril]
+\setuplabeltext [\s!es] [\v!may=mayo]
+\setuplabeltext [\s!es] [\v!june=junio]
+\setuplabeltext [\s!es] [\v!july=julio]
+\setuplabeltext [\s!es] [\v!august=agosto]
+\setuplabeltext [\s!es] [\v!september=septiembre]
+\setuplabeltext [\s!es] [\v!october=octubre]
+\setuplabeltext [\s!es] [\v!november=noviembre]
+\setuplabeltext [\s!es] [\v!december=diciembre]
+
+\setuplabeltext [\s!ca] [\v!january=gener]
+\setuplabeltext [\s!ca] [\v!february=febrer]
+\setuplabeltext [\s!ca] [\v!march=mar\c{c}]
+\setuplabeltext [\s!ca] [\v!april=abril]
+\setuplabeltext [\s!ca] [\v!may=maig]
+\setuplabeltext [\s!ca] [\v!june=juny]
+\setuplabeltext [\s!ca] [\v!july=juliol]
+\setuplabeltext [\s!ca] [\v!august=agost]
+\setuplabeltext [\s!ca] [\v!september=setembre]
+\setuplabeltext [\s!ca] [\v!october=octubre]
+\setuplabeltext [\s!ca] [\v!november=novembre]
+\setuplabeltext [\s!ca] [\v!december=desembre]
+
+\setuplabeltext [\s!it] [\v!january=gennaio]
+\setuplabeltext [\s!it] [\v!february=febbraio]
+\setuplabeltext [\s!it] [\v!march=marzo]
+\setuplabeltext [\s!it] [\v!april=aprile]
+\setuplabeltext [\s!it] [\v!may=maggio]
+\setuplabeltext [\s!it] [\v!june=giugno]
+\setuplabeltext [\s!it] [\v!july=luglio]
+\setuplabeltext [\s!it] [\v!august=agosto]
+\setuplabeltext [\s!it] [\v!september=settembre]
+\setuplabeltext [\s!it] [\v!october=ottobre]
+\setuplabeltext [\s!it] [\v!november=novembre]
+\setuplabeltext [\s!it] [\v!december=dicembre]
+
+\setuplabeltext [\s!la] [\v!january=Ianuarius]
+\setuplabeltext [\s!la] [\v!february=Februarius]
+\setuplabeltext [\s!la] [\v!march=Martius]
+\setuplabeltext [\s!la] [\v!april=Aprilis]
+\setuplabeltext [\s!la] [\v!may=Maius]
+\setuplabeltext [\s!la] [\v!june=Iunius]
+\setuplabeltext [\s!la] [\v!july=Iulius] % formerly Quintilis
+\setuplabeltext [\s!la] [\v!august=Augustus] % formerly Sextilis
+\setuplabeltext [\s!la] [\v!september=September]
+\setuplabeltext [\s!la] [\v!october=October]
+\setuplabeltext [\s!la] [\v!november=November]
+\setuplabeltext [\s!la] [\v!december=December]
+
+\setuplabeltext [\s!pt] [\v!january=janeiro]
+\setuplabeltext [\s!pt] [\v!february=fevereiro]
+\setuplabeltext [\s!pt] [\v!march=mar\c{c}o]
+\setuplabeltext [\s!pt] [\v!april=abril]
+\setuplabeltext [\s!pt] [\v!may=maio]
+\setuplabeltext [\s!pt] [\v!june=junho]
+\setuplabeltext [\s!pt] [\v!july=julho]
+\setuplabeltext [\s!pt] [\v!august=agosto]
+\setuplabeltext [\s!pt] [\v!september=setembro]
+\setuplabeltext [\s!pt] [\v!october=outubro]
+\setuplabeltext [\s!pt] [\v!november=novembro]
+\setuplabeltext [\s!pt] [\v!december=dezembro]
+
+\setuplabeltext [\s!ro] [\v!january=ianuarie]
+\setuplabeltext [\s!ro] [\v!february=februarie]
+\setuplabeltext [\s!ro] [\v!march=martie]
+\setuplabeltext [\s!ro] [\v!april=aprilie]
+\setuplabeltext [\s!ro] [\v!may=mai]
+\setuplabeltext [\s!ro] [\v!june=iunie]
+\setuplabeltext [\s!ro] [\v!july=iulie]
+\setuplabeltext [\s!ro] [\v!august=august]
+\setuplabeltext [\s!ro] [\v!september=septembrie]
+\setuplabeltext [\s!ro] [\v!october=octombrie]
+\setuplabeltext [\s!ro] [\v!november=noiembrie]
+\setuplabeltext [\s!ro] [\v!december=decembrie]
+
+\setuplabeltext [\s!fr] [\v!sunday=dimanche]
+\setuplabeltext [\s!fr] [\v!monday=lundi]
+\setuplabeltext [\s!fr] [\v!tuesday=mardi]
+\setuplabeltext [\s!fr] [\v!wednesday=mercredi]
+\setuplabeltext [\s!fr] [\v!thursday=jeudi]
+\setuplabeltext [\s!fr] [\v!friday=vendredi]
+\setuplabeltext [\s!fr] [\v!saturday=samedi]
+
+\setuplabeltext [\s!es] [\v!sunday=domingo]
+\setuplabeltext [\s!es] [\v!monday=lunes]
+\setuplabeltext [\s!es] [\v!tuesday=martes]
+\setuplabeltext [\s!es] [\v!wednesday=mi\'ercoles]
+\setuplabeltext [\s!es] [\v!thursday=jueves]
+\setuplabeltext [\s!es] [\v!friday=viernes]
+\setuplabeltext [\s!es] [\v!saturday=s\'abado]
+
+\setuplabeltext [\s!ca] [\v!sunday=diumenge]
+\setuplabeltext [\s!ca] [\v!monday=dilluns]
+\setuplabeltext [\s!ca] [\v!tuesday=dimarts]
+\setuplabeltext [\s!ca] [\v!wednesday=dimecres]
+\setuplabeltext [\s!ca] [\v!thursday=dijous]
+\setuplabeltext [\s!ca] [\v!friday=divendres]
+\setuplabeltext [\s!ca] [\v!saturday=dissabte]
+
+\setuplabeltext [\s!it] [\v!sunday=domenica]
+\setuplabeltext [\s!it] [\v!monday=luned\`\i]
+\setuplabeltext [\s!it] [\v!tuesday=marted\`\i]
+\setuplabeltext [\s!it] [\v!wednesday=mercoled\`\i]
+\setuplabeltext [\s!it] [\v!thursday=gioved\`\i]
+\setuplabeltext [\s!it] [\v!friday=venerd\`\i]
+\setuplabeltext [\s!it] [\v!saturday=sabato]
+
+\setuplabeltext [\s!la] [\v!sunday=Dies Solis]
+\setuplabeltext [\s!la] [\v!monday=Dies Lunae]
+\setuplabeltext [\s!la] [\v!tuesday=Dies Martis]
+\setuplabeltext [\s!la] [\v!wednesday=Dies Mercuri]
+\setuplabeltext [\s!la] [\v!thursday=Dies Iovis]
+\setuplabeltext [\s!la] [\v!friday=Dies Veneris]
+\setuplabeltext [\s!la] [\v!saturday=Dies Saturni]
+
+\setuplabeltext [\s!pt] [\v!sunday=domingo]
+\setuplabeltext [\s!pt] [\v!monday=segunda-feira]
+\setuplabeltext [\s!pt] [\v!tuesday=ter\c{c}a-feira]
+\setuplabeltext [\s!pt] [\v!wednesday=quarta-feira]
+\setuplabeltext [\s!pt] [\v!thursday=quinta-feira]
+\setuplabeltext [\s!pt] [\v!friday=sexta-feira]
+\setuplabeltext [\s!pt] [\v!saturday=s\'abado]
+
+\setuplabeltext [\s!ro] [\v!sunday=duminic\u{a}]
+\setuplabeltext [\s!ro] [\v!monday=luni]
+\setuplabeltext [\s!ro] [\v!tuesday=mar\c{t}i]
+\setuplabeltext [\s!ro] [\v!wednesday=miercuri]
+\setuplabeltext [\s!ro] [\v!thursday=joi]
+\setuplabeltext [\s!ro] [\v!friday=vineri]
+\setuplabeltext [\s!ro] [\v!saturday=s\^{a}mb\u{a}t\u{a}]
+
+%D Rather new \unknown
+
+\setuplabeltext [\s!it] [\v!page=pagina ]
+\setuplabeltext [\s!it] [\v!atpage=a pagina ]
+\setuplabeltext [\s!it] [\v!hencefore=come mostrato sopra]
+\setuplabeltext [\s!it] [\v!hereafter=come mostrato sotto]
+\setuplabeltext [\s!it] [\v!see=cf. ]
+
+\setuplabeltext [\s!fr] [\v!page=page ]
+\setuplabeltext [\s!fr] [\v!atpage=à la page ]
+\setuplabeltext [\s!fr] [\v!hencefore=ci-dessus]
+\setuplabeltext [\s!fr] [\v!hereafter=ci-dessous]
+\setuplabeltext [\s!fr] [\v!see=cf. ]
+
+%D Ordinal converters:
+
+\def\frordinaldaynumber#1% date is masculine
+ {\number#1\ifcase#1\or
+ \highordinalstr{er}%
+ \fi}
+
+\defineconversion [\s!fr] [\v!day+] [\frordinaldaynumber]
+
+%D \ShowAllLanguageValues [\s!fr] [french] {French} {kiss} % franse slag
+%D \ShowAllLanguageValues [\s!es] [spanish] {Spanish} {guitar} % spaans benauwd
+%D \ShowAllLanguageValues [\s!ca] [catalan] {Catalan} {cream}
+%D \ShowAllLanguageValues [\s!it] [italian] {Italian} {aria}
+%D \ShowAllLanguageValues [\s!la] [latin] {Latin} {lover} % latijnse missen
+%D \ShowAllLanguageValues [\s!pt] [portuguese] {Portuguese} {fisherman}
+%D \ShowAllLanguageValues [\s!ro] [romanian] {Romanian} {traveller}
+
+\protect \endinput
diff --git a/tex/context/base/lang-jap.mkii b/tex/context/base/lang-jap.mkii
new file mode 100644
index 000000000..05c9b1d41
--- /dev/null
+++ b/tex/context/base/lang-jap.mkii
@@ -0,0 +1,234 @@
+%D \module
+%D [ file=lang-jap,
+%D version=2006.01.13,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Japanese,
+%D author={Richard Gabriel},
+%D date=\currentdate,
+%D copyright={PRAGMA / RG}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% rgabriel@kerio.com
+
+\writestatus{loading}{ConTeXt Language Macros / Japanese}
+
+\unprotect
+
+\definesystemconstant {japanese} \definesystemconstant {ja}
+
+\installlanguage
+ [\s!ja]
+ [\c!leftsentence=\jaencoding\jaleftsentence,
+ \c!rightsentence=\jaencoding\jarightsentence,
+ \c!leftsubsentence=\jaencoding\jaleftsubsentence,
+ \c!rightsubsentence=\jaencoding\jarightsubsentence,
+ \c!leftquote=\jaencoding\jaencodedsinglestartquote,
+ \c!rightquote=\jaencoding\jaencodedsingleendquote,
+ \c!leftquotation=\jaencoding\jaencodedstartquote,
+ \c!rightquotation=\jaencoding\jaencodedendquote,
+ \c!date={\jaencodedchristiandate,\v!year,\jaencodedyear,\v!month,\jaencodedmonth,\v!day,\jaencodedday}]
+
+\setupheadtext [\s!ja] [\v!content={\jaencoding\jaencodedtableofcontents}]
+\setupheadtext [\s!ja] [\v!tables={\jaencoding\jaencodedtables}]
+\setupheadtext [\s!ja] [\v!figures={\jaencoding\jaencodedfigures}]
+\setupheadtext [\s!ja] [\v!graphics={\jaencoding\jaencodedgraphics}]
+\setupheadtext [\s!ja] [\v!intermezzi={\jaencoding\jaencodedintermezzos}]
+\setupheadtext [\s!ja] [\v!index={\jaencoding\jaencodedindex}]
+\setupheadtext [\s!ja] [\v!abbreviations={\jaencoding\jaencodedabbreviations}]
+\setupheadtext [\s!ja] [\v!logos={\jaencoding\jaencodedlogos}]
+\setupheadtext [\s!ja] [\v!units={\jaencoding\jaencodedunits}]
+
+\setuplabeltext [\s!ja] [\v!table={\jaencoding\jaencodedtable}]
+\setuplabeltext [\s!ja] [\v!figure={\jaencoding\jaencodedfigure}]
+\setuplabeltext [\s!ja] [\v!intermezzo={\jaencoding\jaencodedintermezzo}]
+\setuplabeltext [\s!ja] [\v!graphic={\jaencoding\jaencodedillustration}]
+\setuplabeltext [\s!ja] [\v!appendix={\jaencoding\jaencodedappendix}]
+\setuplabeltext [\s!ja] [\v!part={\jaencoding\jaencodedintro,\jaencoding\jaencodedpart}]
+\setuplabeltext [\s!ja] [\v!chapter={\jaencoding\jaencodedintro,\jaencoding\jaencodedchapter}]
+\setuplabeltext [\s!ja] [\v!section={\jaencoding\jaencodedintro,\jaencoding\jaencodedsection}]
+\setuplabeltext [\s!ja] [\v!line={\jaencoding\jaencodedline}]
+\setuplabeltext [\s!ja] [\v!lines={\jaencoding\jaencodedline}]
+
+\setuplabeltext [\s!ja] [\v!subsection=]
+\setuplabeltext [\s!ja] [\v!subsubsection=]
+\setuplabeltext [\s!ja] [\v!subsubsubsection=]
+
+%D Why are these languagespecifics ?
+
+\setuplabeltext [\s!ja] [\v!january=1]
+\setuplabeltext [\s!ja] [\v!february=2]
+\setuplabeltext [\s!ja] [\v!march=3]
+\setuplabeltext [\s!ja] [\v!april=4]
+\setuplabeltext [\s!ja] [\v!may=5]
+\setuplabeltext [\s!ja] [\v!june=6]
+\setuplabeltext [\s!ja] [\v!july=7]
+\setuplabeltext [\s!ja] [\v!august=8]
+\setuplabeltext [\s!ja] [\v!september=9]
+\setuplabeltext [\s!ja] [\v!october=10]
+\setuplabeltext [\s!ja] [\v!november=11]
+\setuplabeltext [\s!ja] [\v!december=12]
+
+\setuplabeltext [\s!ja] [\v!sunday=\jaencoding\jaencodedsunday ]
+\setuplabeltext [\s!ja] [\v!monday=\jaencoding\jaencodedmonday ]
+\setuplabeltext [\s!ja] [\v!tuesday=\jaencoding\jaencodedtuesday ]
+\setuplabeltext [\s!ja] [\v!wednesday=\jaencoding\jaencodedwednesday]
+\setuplabeltext [\s!ja] [\v!thursday=\jaencoding\jaencodedthursday ]
+\setuplabeltext [\s!ja] [\v!friday=\jaencoding\jaencodedfriday ]
+\setuplabeltext [\s!ja] [\v!saturday=\jaencoding\jaencodedsaturday ]
+
+% Hardcoded - \japaneseencoding should be defined similarly to \chineseencoding
+
+\unexpanded\def\jaencoding{\enableencoding[cjk-uni]}
+
+%D This list is taken from DocBook XSL stylesheets (http://docbook.sourceforge.net/).
+
+\startencoding[cjk-uni]
+
+ \definecommand jaencodedabstract {\uchar{105}{130}\uchar{137}{129}}
+ \definecommand jaencodedand {\uchar{48}{1}}
+ \definecommand jaencodedanswer {\uchar{123}{84}\uchar{255}{26}}
+ \definecommand jaencodedappendix {\uchar{78}{216}\uchar{147}{50}}
+ \definecommand jaencodedarticle {\uchar{152}{5}\uchar{118}{238}}
+ \definecommand jaencodedbibliography {\uchar{83}{194}\uchar{128}{3}\uchar{101}{135}\uchar{115}{46}}
+ \definecommand jaencodedbook {\uchar{48}{214}\uchar{48}{195}\uchar{48}{175}}
+ \definecommand jaencodedbridgehead {\uchar{152}{5}}
+ \definecommand jaencodedbullet {\uchar{37}{207}}
+ \definecommand jaencodedby {\uchar{255}{26}}
+ \definecommand jaencodedcaution {\uchar{108}{232}\uchar{97}{15}}
+ \definecommand jaencodedcolophon {\uchar{89}{101}\uchar{78}{216}}
+ \definecommand jaencodedcopyright {\uchar{136}{253}\uchar{79}{92}\uchar{132}{87}\uchar{79}{92}}
+ \definecommand jaencodeddedication {\uchar{139}{29}\uchar{143}{158}}
+ \definecommand jaencodededited {\uchar{125}{232}\uchar{128}{5}}
+ \definecommand jaencodededitedby {\uchar{125}{232}\uchar{128}{5}\uchar{255}{26}}
+ \definecommand jaencodededition {\uchar{125}{232}\uchar{150}{198}}
+ \definecommand jaencodedendquote {\uchar{48}{13}}
+ \definecommand jaencodedequation {\uchar{95}{15}}
+ \definecommand jaencodedexample {\uchar{79}{139}}
+ \definecommand jaencodedfigure {\uchar{86}{243}}
+ \definecommand jaencodedglossary {\uchar{117}{40}\uchar{138}{158}\uchar{150}{198}}
+ \definecommand jaencodedglosssee {\uchar{83}{194}\uchar{113}{103}}
+ \definecommand jaencodedglossseealso {\uchar{83}{194}\uchar{113}{103}}
+ \definecommand jaencodedchapter {\uchar{122}{224}}
+ \definecommand jaencodedimportant {\uchar{145}{205}\uchar{137}{129}\uchar{152}{5}\uchar{118}{238}}
+ \definecommand jaencodedindex {\uchar{118}{238}\uchar{107}{33}}
+ \definecommand jaencodedindexsymbols {\uchar{48}{183}\uchar{48}{243}\uchar{48}{220}\uchar{48}{235}}
+ \definecommand jaencodedintro {\uchar{123}{44}}
+ \definecommand jaencodedlistofequations {\uchar{95}{15}\uchar{118}{238}\uchar{107}{33}}
+ \definecommand jaencodedlistofexamples {\uchar{79}{139}\uchar{118}{238}\uchar{107}{33}}
+ \definecommand jaencodedlistoffigures {\uchar{86}{243}\uchar{118}{238}\uchar{107}{33}}
+ \definecommand jaencodedlistoftables {\uchar{136}{104}\uchar{118}{238}\uchar{107}{33}}
+ \definecommand jaencodedlistofunknown {\uchar{78}{13}\uchar{102}{14}\uchar{118}{238}\uchar{107}{33}}
+ \definecommand jaencodedmsgaud {\uchar{91}{254}\uchar{140}{97}\uchar{128}{5}}
+ \definecommand jaencodedmsglevel {\uchar{48}{236}\uchar{48}{217}\uchar{48}{235}}
+ \definecommand jaencodedmsgorig {\uchar{118}{122}\uchar{79}{225}\uchar{81}{67}}
+ \definecommand jaencodednavhome {\uchar{48}{219}\uchar{48}{252}\uchar{48}{224}}
+ \definecommand jaencodednavnext {\uchar{107}{33}\uchar{48}{110}\uchar{48}{218}\uchar{48}{252}\uchar{48}{184}}
+ \definecommand jaencodednavnextsibling {\uchar{101}{233}\uchar{144}{1}\uchar{48}{138}}
+ \definecommand jaencodednavprev {\uchar{82}{77}\uchar{48}{110}\uchar{48}{218}\uchar{48}{252}\uchar{48}{184}}
+ \definecommand jaencodednavprevsibling {\uchar{93}{251}\uchar{98}{59}\uchar{48}{87}}
+ \definecommand jaencodednavup {\uchar{78}{10}\uchar{48}{107}\uchar{98}{59}\uchar{48}{139}}
+ \definecommand jaencodednestedendquote {\uchar{48}{15}}
+ \definecommand jaencodednestedstartquote {\uchar{48}{14}}
+ \definecommand jaencodednonexistantelement {\uchar{137}{129}\uchar{125}{32}\uchar{48}{76}\uchar{91}{88}\uchar{87}{40}\uchar{48}{87}\uchar{48}{126}\uchar{48}{91}\uchar{48}{147}}
+ \definecommand jaencodednote {\uchar{108}{232}\uchar{97}{15}}
+ \definecommand jaencodednotes {\uchar{108}{232}\uchar{97}{15}}
+ \definecommand jaencodedpages {\uchar{80}{103}\uchar{115}{46}}
+ \definecommand jaencodedpart {\uchar{48}{209}\uchar{48}{252}\uchar{48}{200}}
+ \definecommand jaencodedpreface {\uchar{94}{143}\uchar{101}{135}}
+ \definecommand jaencodedprocedure {\uchar{98}{75}\uchar{152}{6}}
+ \definecommand jaencodedprocedureformal {\uchar{98}{75}\uchar{152}{6}}
+ \definecommand jaencodedproductionset {\uchar{48}{215}\uchar{48}{237}\uchar{48}{192}\uchar{48}{175}\uchar{48}{183}\uchar{48}{231}\uchar{48}{243}}
+ \definecommand jaencodedproductionsetformal {\uchar{48}{215}\uchar{48}{237}\uchar{48}{192}\uchar{48}{175}\uchar{48}{183}\uchar{48}{231}\uchar{48}{243}}
+ \definecommand jaencodedpublished {\uchar{118}{122}\uchar{136}{76}}
+ \definecommand jaencodedqandadiv {\uchar{85}{79}\uchar{255}{26}\uchar{48}{1}\uchar{123}{84}\uchar{255}{26}}
+ \definecommand jaencodedqandaentry {\uchar{85}{79}\uchar{255}{26}}
+ \definecommand jaencodedquestion {\uchar{85}{79}\uchar{255}{26}}
+ \definecommand jaencodedreference {\uchar{83}{194}\uchar{113}{103}}
+ \definecommand jaencodedrefname {\uchar{84}{13}\uchar{82}{77}}
+ \definecommand jaencodedrefsection {\uchar{152}{5}}
+ \definecommand jaencodedrefsynopsisdiv {\uchar{105}{130}\uchar{137}{129}}
+ \definecommand jaencodedrevhistory {\uchar{101}{57}\uchar{138}{2}\uchar{92}{101}\uchar{107}{116}}
+ \definecommand jaencodedrevision {\uchar{101}{57}\uchar{138}{2}}
+ \definecommand jaencodedsection {\uchar{152}{5}}
+ \definecommand jaencodedsee {\uchar{83}{194}\uchar{113}{103}}
+ \definecommand jaencodedseealso {\uchar{83}{194}\uchar{113}{103}}
+ \definecommand jaencodedseparator {\uchar{48}{1}}
+ \definecommand jaencodedset {\uchar{138}{45}\uchar{91}{154}}
+ \definecommand jaencodedsetindex {\uchar{118}{238}\uchar{107}{33}\uchar{138}{45}\uchar{91}{154}}
+ \definecommand jaencodedsidebar {\uchar{48}{181}\uchar{48}{164}\uchar{48}{201}\uchar{48}{208}\uchar{48}{252}}
+ \definecommand jaencodedsimplesect {\uchar{152}{5}}
+ \definecommand jaencodedsingleendquote {\uchar{32}{25}}
+ \definecommand jaencodedsinglestartquote {\uchar{32}{24}}
+ \definecommand jaencodedstartquote {\uchar{48}{12}}
+ \definecommand jaencodedstep {\uchar{48}{185}\uchar{48}{198}\uchar{48}{195}\uchar{48}{215}}
+ \definecommand jaencodedtable {\uchar{136}{104}}
+ \definecommand jaencodedtablenotes {\uchar{108}{232}\uchar{97}{15}}
+ \definecommand jaencodedtableofcontents {\uchar{118}{238}\uchar{107}{33}}
+ \definecommand jaencodedtip {\uchar{48}{198}\uchar{48}{163}\uchar{48}{195}\uchar{48}{215}}
+ \definecommand jaencodedunexpectedelementname {\uchar{78}{13}\uchar{102}{14}\uchar{48}{106}\uchar{137}{129}\uchar{125}{32}\uchar{84}{13}}
+ \definecommand jaencodedunsupported {\uchar{48}{181}\uchar{48}{221}\uchar{48}{252}\uchar{48}{200}\uchar{48}{87}\uchar{48}{126}\uchar{48}{91}\uchar{48}{147}}
+ \definecommand jaencodedwarning {\uchar{139}{102}\uchar{84}{74}}
+
+ \definecommand jaencodedyear {\uchar{94}{116}}
+ \definecommand jaencodedmonth {\uchar{103}{8}}
+ \definecommand jaencodedday {\uchar{101}{229}}
+
+\stopencoding
+
+%D Taken from Chinese (will be investigated yet...)
+
+\startencoding[cjk-uni]
+
+ \definecommand jaencodedleftsentence {\uchar{32}{20}\uchar{32}{20}}
+ \definecommand jaencodedrightsentence {\uchar{32}{20}\uchar{32}{20}}
+ \definecommand jaencodedleftsubsentence {\uchar{32}{20}\uchar{32}{20}}
+ \definecommand jaencodedrightsubsentence {\uchar{32}{20}\uchar{32}{20}}
+
+\stopencoding
+
+%D Special thanxx to Eizo Tsuchihashi (eizo@arcbrain.jp) for the following stuff
+
+\startencoding[cjk-uni]
+
+ \definecommand jaencodedchristiandate {\uchar{137}{127}\uchar{102}{166}}
+
+ \definecommand jaencodedtables {\uchar{103}{58}}
+ \definecommand jaencodedfigures {\uchar{86}{243}}
+ \definecommand jaencodedabbreviations {\uchar{117}{101}\uchar{138}{158}}
+ \definecommand jaencodedlogos {\uchar{116}{6}\uchar{96}{39}}
+ \definecommand jaencodedunits {\uchar{48}{230}\uchar{48}{203}\uchar{48}{195}\uchar{48}{196}}
+
+ \definecommand jaencodedgraphics {\uchar{48}{176}\uchar{48}{233}\uchar{48}{213}}
+ \definecommand jaencodedintermezzo {\uchar{149}{147}\uchar{89}{79}\uchar{102}{242}}
+ \definecommand jaencodedintermezzos {\uchar{149}{147}\uchar{89}{79}\uchar{102}{242}}
+ \definecommand jaencodedillustration {\uchar{48}{164}\uchar{48}{233}\uchar{48}{185}\uchar{48}{200}}
+ \definecommand jaencodedline {\uchar{125}{218}}
+ \definecommand jaencodedlines {\uchar{125}{218}}
+
+ \definecommand jaencodedjanuary {\uchar{78}{0}\uchar{103}{8}}
+ \definecommand jaencodedfebruary {\uchar{78}{140}\uchar{103}{8}}
+ \definecommand jaencodedmarch {\uchar{78}{9}\uchar{103}{8}}
+ \definecommand jaencodedapril {\uchar{86}{219}\uchar{103}{8}}
+ \definecommand jaencodedmay {\uchar{78}{148}\uchar{103}{8}}
+ \definecommand jaencodedjune {\uchar{81}{109}\uchar{103}{8}}
+ \definecommand jaencodedjuly {\uchar{78}{3}\uchar{103}{8}}
+ \definecommand jaencodedaugust {\uchar{81}{107}\uchar{103}{8}}
+ \definecommand jaencodedseptember {\uchar{78}{93}\uchar{103}{8}}
+ \definecommand jaencodedoctober {\uchar{83}{65}\uchar{103}{8}}
+ \definecommand jaencodednovember {\uchar{83}{65}\uchar{78}{0}\uchar{103}{8}}
+ \definecommand jaencodeddecember {\uchar{83}{65}\uchar{78}{140}\uchar{103}{8}}
+
+ \definecommand jaencodedsunday {\uchar{103}{8}\uchar{102}{220}\uchar{101}{229}}
+ \definecommand jaencodedmonday {\uchar{112}{107}\uchar{102}{220}\uchar{101}{229}}
+ \definecommand jaencodedtuesday {\uchar{108}{52}\uchar{102}{220}\uchar{101}{229}}
+ \definecommand jaencodedwednesday {\uchar{103}{40}\uchar{102}{220}\uchar{101}{229}}
+ \definecommand jaencodedthursday {\uchar{145}{209}\uchar{102}{220}\uchar{101}{229}}
+ \definecommand jaencodedfriday {\uchar{87}{31}\uchar{102}{220}\uchar{101}{229}}
+ \definecommand jaencodedsaturday {\uchar{101}{229}\uchar{102}{220}\uchar{101}{229}}
+
+\stopencoding
+
+\protect \endinput
diff --git a/tex/context/base/lang-lab.mkii b/tex/context/base/lang-lab.mkii
new file mode 100644
index 000000000..269ac249b
--- /dev/null
+++ b/tex/context/base/lang-lab.mkii
@@ -0,0 +1,295 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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
+
+%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
+%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
+%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 \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
+%D \showsetup{setupheadtext}
+%D \showsetup{setuplabeltext}
+%D
+%D In a few paragraphs we'll show quite a lot of examples
+%D of its use.
+
+\let\handletextprefix\relax
+
+\def\setupheadtext {\dosetupsometextprefix[\c!title]}
+\def\setuplabeltext{\dosetupsometextprefix[\c!label]}
+
+\def\dosetupsometextprefix
+ {\let\dodocommand\xdosetupsometextprefix
+ \dotripleempty\dodosetupsometextprefix}
+
+% \def\dodosetupsometextprefix[#1][#2][#3]%
+% {\ifthirdargument
+% \def\docommand##1{\dodocommand[#1#2][##1]}%
+% \processcommalist[#3]\docommand
+% \else
+% \def\docommand##1{\dodocommand[#1\currentmainlanguage][##1]}%
+% \processcommalist[#2]\docommand
+% \fi}
+
+\def\dodosetupsometextprefix[#1][#2][#3]%
+ {\ifthirdargument
+ \def\docommand##1{\expanded{\dodocommand[#1\reallanguagetag{#2}]}[##1]}%
+ \processcommalist[#3]\docommand
+ \else
+ \def\docommand##1{\expanded{\dodocommand[#1\reallanguagetag\currentmainlanguage]}[##1]}%
+ \processcommalist[#2]\docommand
+ \fi}
+
+\def\doassignsometextprefix[#1][#2,#3,#4]%
+ {\setvalue{#1}{\handletextprefix{#2}{#3}}}
+
+\def\xdosetupsometextprefix[#1][#2=#3]%
+ {\doassignsometextprefix[#1#2][#3,,]}
+
+%D By changing the meaning of \type {\handletextprefix} we
+%D can filter the left and right labeltext as well as convert
+%D labels to uppercase.
+%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.
+
+%D \macros
+%D {headtext,
+%D labeltext, leftlabeltext, rightlabeltext, labeltexts,
+%D 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 The latter one has an upcased alternative \type{\LABELTEXT}.
+
+% \def\labellanguage{\currentmainlanguage}
+% \def\headlanguage {\currentmainlanguage}
+
+% \def\labellanguage{\defaultlanguage\currentmainlanguage}
+% \def\headlanguage {\defaultlanguage\currentmainlanguage}
+
+\def\labellanguage{\reallanguagetag{\defaultlanguage\currentmainlanguage}}
+\def\headlanguage {\reallanguagetag{\defaultlanguage\currentmainlanguage}}
+
+\appendtoks \let\labellanguage\currentlanguage \to \everycurrentdate
+
+\unexpanded\def\headtext
+ {\let\handletextprefix\firstoftwoarguments
+ \let\reporttextprefixerror\doreporttextprefixerror
+ \global\labeltextdonetrue
+ \dogetupsometextprefix\headlanguage\c!title}
+
+\unexpanded\def\leftlabeltext
+ {\let\handletextprefix\firstoftwoarguments
+ \let\reporttextprefixerror\doreporttextprefixerror
+ \global\labeltextdonetrue
+ \dogetupsometextprefix\labellanguage\c!label}
+
+\unexpanded\def\rightlabeltext
+ {\let\handletextprefix\secondoftwoarguments
+ \let\reporttextprefixerror\doreporttextprefixerror
+ \global\labeltextdonetrue
+ \dogetupsometextprefix\labellanguage\c!label}
+
+\unexpanded\def\LEFTLABELTEXT
+ {\def\handletextprefix##1##2{\uppercase{##1}}\DOLABELTEXT}
+
+\unexpanded\def\RIGHTLABELTEXT
+ {\def\handletextprefix##1##2{\uppercase{##2}}\DOLABELTEXT}
+
+\def\DOLABELTEXT#1%
+ {\bgroup
+ \the\everyuppercase
+ \let\reporttextprefixerror\doreporttextprefixerror
+ \global\labeltextdonetrue
+ \dogetupsometextprefix\labellanguage\c!label{#1}% not \labeltext (see \MONTH)
+ \egroup}
+
+\let\labeltext \leftlabeltext
+\let\LABELTEXT \LEFTLABELTEXT
+
+\unexpanded\def\labeltexts#1#2{\leftlabeltext{#1}#2\rightlabeltext{#1}}
+\unexpanded\def\LABELTEXTS#1#2{\LEFTLABELTEXT{#1}#2\RIGHTLABELTEXT{#1}}
+
+\newif\iflabeltextdone % needs to be reset elsewhere
+\newif\iftracelabels % shows missing labels
+
+\def\doreporttextprefixerror#1#2#3%
+ {\iftracelabels{\tttf[#2:~#3/#1]~}\fi}
+
+\def\dosetexpandedheadlabeltext#1#2#3%
+ {\bgroup
+ \let\handletextprefix\firstoftwoarguments
+ \let\reporttextprefixerror\gobblethreearguments
+ \keepencodedtokens % test on multilingual pascal, ok in stretched
+ %\dontexpandencodedtokens % not usable in token handler
+ \expanded
+ {\egroup\noexpand\def\noexpand#2% watch out, no \edef
+ {\dogetupsometextprefix{\headlanguage}{#1}{#3}}}}
+
+\def\setexpandedheadtext {\dosetexpandedheadlabeltext\c!title}
+\def\setexpandedlabeltext{\dosetexpandedheadlabeltext\c!label}
+
+% \def\dogetupsometextprefix#1#2#3%
+% {\ifcsname#2#1#3\endcsname
+% \csname#2#1#3\endcsname \else
+% \ifcsname#2#3\endcsname
+% \csname#2#3\endcsname \else
+% \ifcsname#2\defaultlanguage#1#3\endcsname
+% \csname#2\defaultlanguage#1#3\endcsname \else
+% \ifcsname#2\s!en#3\endcsname
+% \csname#2\s!en#3\endcsname \else
+% \ifcsname#2\s!nl#3\endcsname
+% \csname#2\s!nl#3\endcsname \else
+% \reporttextprefixerror{#1}{#2}{#3}%
+% \fi\fi\fi\fi\fi}
+%
+% \def\dogetupsometextprefix#1#2#3% must be expandable !
+% {\ifcsname#2#1#3\endcsname
+% \csname#2#1#3\endcsname
+% \else\@EA\ifx\csname\??la#1\c!default\endcsname\empty
+% \ifcsname#2#3\endcsname
+% \csname#2#3\endcsname
+% \else\ifcsname#2\s!en#3\endcsname
+% \csname#2\s!en#3\endcsname
+% \else
+% \reporttextprefixerror{#1}{#2}{#3}%
+% \fi\fi
+% \else
+% \dogetupsometextprefix{\csname\??la#1\c!default\endcsname}{#2}{#3}%
+% \fi\fi}
+
+\def\dogetupsometextprefix#1#2#3% must be expandable ! #1 == language
+ {\ifcsname#2#1#3\endcsname
+ \csname#2#1#3\endcsname
+ \else\ifcsname\??la#1\s!default\endcsname
+ \expandafter\dogetupsometextprefix\csname\??la#1\s!default\endcsname{#2}{#3}%
+ \else\ifcsname#2#3\endcsname
+ \csname#2#3\endcsname
+ \else\ifcsname#1\s!en#3\endcsname
+ \csname#2\s!en#3\endcsname
+ \else
+ \reporttextprefixerror{#1}{#2}{#3}%
+ \fi\fi\fi\fi}
+
+\ifx\simplifiedcommands\undefined \newtoks\simplifiedcommands \fi
+
+\appendtoks
+ \let \headtext \firstofoneargument
+ \let \labeltext \firstofoneargument
+ \let \leftlabeltext \firstofoneargument
+ \let \rightlabeltext \firstofoneargument
+ \let \HEADTEXT \firstofoneargument
+ \let \LABELTEXT \firstofoneargument
+ \let \LEFTLABELTEXT \firstofoneargument
+ \let \RIGHTLABELTEXT \firstofoneargument
+\to \simplifiedcommands
+
+%D \macros
+%D {presetheadtext,presetlabeltext}
+%D
+%D The next two macros enable us to automatically define
+%D head and label texts without replacing predefined ones.
+%D These are internal macros.
+
+\def\xdopresetsometextprefix[#1][#2=#3]%
+ {\ifundefined{#1#2}\doassignsometextprefix[#1\reallanguagetag{#2}][#3,,]\fi}
+
+\def\dopresetsometextprefix
+ {\let\dodocommand\xdopresetsometextprefix
+ \dotripleempty\dodosetupsometextprefix}
+
+\def\presetheadtext {\dopresetsometextprefix[\c!title]}
+\def\presetlabeltext{\dopresetsometextprefix[\c!label]}
+
+%D \macros
+%D {translate}
+%D
+%D Sometismes macros contain language specific words that are to
+%D be typeset. Such macros can be made (more) language
+%D 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
+%D de current language.
+
+\def\dotranslate[#1]%
+ {\getparameters[\??lg][#1]%
+ \ifcsname\??lg\currentlanguage\endcsname
+ \csname\??lg\currentlanguage\endcsname
+ \else\ifcsname\??lg\s!en\endcsname
+ \csname\??lg\s!en\endcsname
+ \else
+ [translation #1]%
+ \fi\fi}
+
+\unexpanded\def\translate
+ {\dosingleempty\dotranslate}
+
+%D When used without argument, the last defined values are
+%D used. This enables 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
+%D translation to a macro. Its form is:
+%D
+%D \starttyping
+%D \assigntranslation[en=something,nl=iets]\to\command
+%D \stoptyping
+
+\def\assigntranslation[#1]\to#2%
+ {\getparameters[\??lg][#1]%
+ \edef#2{\csname\??lg\currentlanguage\endcsname}}
+
+\protect \endinput
diff --git a/tex/context/base/lang-lab.mkiv b/tex/context/base/lang-lab.mkiv
new file mode 100644
index 000000000..42f2db8ff
--- /dev/null
+++ b/tex/context/base/lang-lab.mkiv
@@ -0,0 +1,283 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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
+
+%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
+%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
+%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 \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
+%D \showsetup{setupheadtext}
+%D \showsetup{setuplabeltext}
+%D
+%D A regular \CONTEXT\ stores some 1500 labels at most.
+
+\let\handletextprefix\relax
+
+\newconditional\protecttextprefixes
+
+\let\currenttextprefixtag \s!unknown
+\let\currenttextprefixclass\s!unknown
+
+\unexpanded\def\setupheadtext {\setfalse\protecttextprefixes\let\currenttextprefixclass\??mh\dodoubleempty\dosetupsometextprefix}
+\unexpanded\def\setuplabeltext {\setfalse\protecttextprefixes\let\currenttextprefixclass\??ml\dodoubleempty\dosetupsometextprefix}
+\unexpanded\def\setupmathlabeltext{\setfalse\protecttextprefixes\let\currenttextprefixclass\??mm\dodoubleempty\dosetupsometextprefix}
+
+\def\dosetupsometextprefix[#1][#2]%
+ {\ifsecondargument
+ \edef\currenttextprefixtag{\reallanguagetag{#1}}%
+ \processcommalist[#2]\dodosetupsometextprefix
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \processcommalist[#1]\dodosetupsometextprefix
+ \fi}
+
+\def\dodosetupsometextprefix#1%
+ {\dododosetupsometextprefix[#1]}
+
+\def\dododosetupsometextprefix[#1=#2]%
+ {\doassignsometextprefix{#1}[#2,,]}
+
+\def\doassignsometextprefix#1%
+ {\ifconditional\protecttextprefixes
+ \ifcsname\currenttextprefixclass\currenttextprefixtag#1\endcsname
+ \expandafter\expandafter\expandafter\doassignsometextprefixnop
+ \else
+ \expandafter\expandafter\expandafter\doassignsometextprefixyes
+ \fi
+ \else
+ \expandafter\doassignsometextprefixyes
+ \fi{#1}}
+
+\ifdefined\Word\else \let\Word\relax \fi
+
+% Checking saves some 8K in the compressed format and getting rid of the embedded
+% \handletextprefix was good for another 6K. In the end the new solution is not
+% even that inefficient. And the checking is done at format generation time anyway.
+
+\def\doassignsometextprefixyes#1[#2,#3,#4]%
+ {\edef\!!stringa{#2}%
+ \edef\!!stringb{#3}%
+ \ifx\!!stringb\empty
+ \ifx\!!stringa\empty
+ \expandafter\def\csname\currenttextprefixclass\currenttextprefixtag#1\endcsname{\empty\empty}%
+ \else
+ \expandafter\def\csname\currenttextprefixclass\currenttextprefixtag#1\endcsname{{#2}\empty}%
+ \fi
+ \else
+ \expandafter\def\csname\currenttextprefixclass\currenttextprefixtag#1\endcsname{{#2}{#3}}%
+ \fi}
+
+\def\doassignsometextprefixnop#1[#2]%
+ {}
+
+%D By changing the meaning of \type {\handletextprefix} we
+%D can filter the left and right labeltext as well as convert
+%D labels to uppercase.
+%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.
+
+%D \macros
+%D {headtext,
+%D labeltext, leftlabeltext, rightlabeltext, labeltexts,
+%D 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 The latter one has an upcased alternative \type{\LABELTEXT}.
+
+\def\labellanguage {\reallanguagetag{\defaultlanguage\currentmainlanguage}}
+\def\headlanguage {\reallanguagetag{\defaultlanguage\currentmainlanguage}}
+\def\mathlabellanguage{\reallanguagetag{\defaultlanguage\currentmainlanguage}}
+
+\appendtoks \let\labellanguage\currentlanguage \to \everycurrentdate
+
+\def\dummytextprefix{\empty\empty}
+
+\def\dogetupsomelabeltext {\dodogetupsomelabeltext \labellanguage } % second argument is textlabel
+\def\dogetupsomeheadtext {\dodogetupsomeheadtext \headlanguage } % second argument is headlabel
+\def\dogetupsomemathlabeltext{\dodogetupsomemathlabeltext\mathlabellanguage } % second argument is headlabel
+
+\def\dodogetupsomelabeltext#1#2%
+ {\ifcsname\??ml#1#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??ml#1#2\endcsname
+ \else\ifcsname\??la\labellanguage\s!default\endcsname
+ \expandafter\dodogetupsomelabeltext\csname\??la\labellanguage\s!default\endcsname{#2}%
+ \else\ifcsname\??ml#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??ml#2\endcsname
+ \else\ifcsname\??ml\s!en#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??ml\s!en#2\endcsname
+ \else
+ \let\thetextprefix\dummytextprefix
+ \fi\fi\fi\fi}
+
+\def\dodogetupsomeheadtext#1#2%
+ {\ifcsname\??mh#1#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??mh#1#2\endcsname
+ \else\ifcsname\??la\headlanguage\s!default\endcsname
+ \expandafter\dodogetupsomeheadtext\csname\??la\headlanguage\s!default\endcsname{#2}%
+ \else\ifcsname\??mh#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??mh#2\endcsname
+ \else\ifcsname\??mh\s!en#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??mh\s!en#2\endcsname
+ \else
+ \let\thetextprefix\dummytextprefix
+ \fi\fi\fi\fi}
+
+\def\dodogetupsomemathlabeltext#1#2%
+ {\ifcsname\??mm#1#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??mm#1#2\endcsname
+ \else\ifcsname\??la\mathlabellanguage\s!default\endcsname
+ \expandafter\dodogetupsomemathlabeltext\csname\??la\mathlabellanguage\s!default\endcsname{#2}%
+ \else\ifcsname\??mm#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??mm#2\endcsname
+ \else\ifcsname\??mm\s!en#2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??mm\s!en#2\endcsname
+ \else
+ \let\thetextprefix\dummytextprefix
+ \fi\fi\fi\fi}
+
+% The WORD variants are a bit inefficient when #1/#2 are empty but they are
+% seldom used (one can better set the style).
+
+\let\flushleftlabeltext \firstoftwoarguments
+\let\flushrightlabeltext \secondoftwoarguments
+\let\flushleftmathlabeltext \firstoftwoarguments
+\let\flushrightmathlabeltext\secondoftwoarguments
+
+\def\flushleftlabelWORD #1#2{\WORD{#1}}
+\def\flushrightlabelWORD #1#2{\WORD{#2}}
+\def\flushbothlabeltexts #1#2#3{#1#3#2}
+\def\flushbothlabelTEXTS #1#2#3{\WORD{#1}#3\WORD{#2}}
+
+\unexpanded\def\headtext #1{\dogetupsomeheadtext {#1}\expandafter\flushleftlabeltext \thetextprefix}
+\unexpanded\def\leftlabeltext #1{\dogetupsomelabeltext {#1}\expandafter\flushleftlabeltext \thetextprefix}
+\unexpanded\def\rightlabeltext #1{\dogetupsomelabeltext {#1}\expandafter\flushrightmathlabeltext\thetextprefix}
+\unexpanded\def\LEFTLABELTEXT #1{\dogetupsomelabeltext {#1}\expandafter\flushleftlabelWORD \thetextprefix}
+\unexpanded\def\RIGHTLABELTEXT #1{\dogetupsomelabeltext {#1}\expandafter\flushrightlabelWORD \thetextprefix}
+\unexpanded\def\labeltexts #1{\dogetupsomelabeltext {#1}\expandafter\flushbothlabeltexts \thetextprefix} % #2
+\unexpanded\def\LABELTEXTS #1{\dogetupsomelabeltext {#1}\expandafter\flushbothlabelTEXTS \thetextprefix} % #2
+\unexpanded\def\leftmathlabeltext #1{\dogetupsomemathlabeltext{#1}\expandafter\flushleftmathlabeltext \thetextprefix}
+\unexpanded\def\rightmathlabeltext#1{\dogetupsomemathlabeltext{#1}\expandafter\flushrightlabeltext \thetextprefix}
+
+\let\labeltext \leftlabeltext
+\let\LABELTEXT \LEFTLABELTEXT
+\let\mathlabeltext\leftmathlabeltext
+
+\ifx\simplifiedcommands\undefined \newtoks\simplifiedcommands \fi
+
+\appendtoks
+ \let \headtext \firstofoneargument
+ \let \labeltext \firstofoneargument
+ \let \leftlabeltext \firstofoneargument
+ \let \rightlabeltext \firstofoneargument
+ \let \HEADTEXT \firstofoneargument
+ \let \LABELTEXT \firstofoneargument
+ \let \LEFTLABELTEXT \firstofoneargument
+ \let \RIGHTLABELTEXT \firstofoneargument
+ \let \mathlabeltext \firstofoneargument
+\to \simplifiedcommands
+
+%D \macros
+%D {presetheadtext,presetlabeltext}
+%D
+%D The next two macros enable us to automatically define
+%D head and label texts without replacing predefined ones.
+%D These are internal macros.
+
+\def\presetheadtext {\settrue\protecttextprefixes\let\currenttextprefixclass\??mh\dodoubleempty\dosetupsometextprefix}
+\def\presetlabeltext {\settrue\protecttextprefixes\let\currenttextprefixclass\??ml\dodoubleempty\dosetupsometextprefix}
+\def\presetmathlabeltext{\settrue\protecttextprefixes\let\currenttextprefixclass\??mm\dodoubleempty\dosetupsometextprefix}
+
+%D \macros
+%D {translate}
+%D
+%D Sometismes macros contain language specific words that are to
+%D be typeset. Such macros can be made (more) language
+%D 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
+%D de current language.
+
+\def\dotranslate[#1]%
+ {\getparameters[\??lg][#1]%
+ \ifcsname\??lg\currentlanguage\endcsname
+ \csname\??lg\currentlanguage\endcsname
+ \else\ifcsname\??lg\s!en\endcsname
+ \csname\??lg\s!en\endcsname
+ \else
+ [translation #1]%
+ \fi\fi}
+
+\unexpanded\def\translate
+ {\dosingleempty\dotranslate}
+
+%D When used without argument, the last defined values are
+%D used. This enables 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
+%D translation to a macro. Its form is:
+%D
+%D \starttyping
+%D \assigntranslation[en=something,nl=iets]\to\command
+%D \stoptyping
+
+\def\assigntranslation[#1]\to#2%
+ {\getparameters[\??lg][#1]%
+ \edef#2{\csname\??lg\currentlanguage\endcsname}}
+
+\protect \endinput
diff --git a/tex/context/base/lang-mis.mkii b/tex/context/base/lang-mis.mkii
new file mode 100644
index 000000000..eb7bb1a04
--- /dev/null
+++ b/tex/context/base/lang-mis.mkii
@@ -0,0 +1,683 @@
+%D \module
+%D [ file=lang-mis,
+%D version=1997.03.20, % used to be supp-lan.tex
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Compounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Compounds}
+
+%D \gdef\starttest
+%D {\blank
+%D \noindent
+%D \halign\bgroup\tt##\hskip2em#\hskip2em#\cr}
+%D
+%D \gdef\stoptest
+%D {\egroup
+%D \blank}
+%D
+%D \gdef\test#1%
+%D {\defconvertedargument\ascii{#1}\ascii&\hyphenatedword{#1}\cr}
+
+\unprotect
+
+%D One of \TEX's strong points in building paragraphs is the way
+%D hyphenations are handled. Although for real good hyphenation
+%D of non||english languages some extensions to the program are
+%D needed, fairly good results can be reached with the standard
+%D mechanisms and an additional macro, at least in Dutch.
+
+%D \CONTEXT\ originates in the wish to typeset educational
+%D materials, especially in a technical environment. In
+%D production oriented environments, a lot of compound words
+%D are used. Because the Dutch language poses no limits on
+%D combining words, we often favor putting dashes between those
+%D words, because it facilitates reading, at least for those
+%D who are not that accustomed to it.
+%D
+%D In \TEX\ compound words, separated by a hyphen, are not
+%D hyphenated at all. In spite of the multiple pass paragraph
+%D typesetting this can lead to parts of words sticking into
+%D the margin. The solution lays in saying \type
+%D {spoelwater||terugwinunit} instead of \type
+%D {spoelwater-terugwinunit}. By using a one character command
+%D like \type {|}, delimited by the same character \type {|},
+%D we get ourselves both a decent visualization (in \TEXEDIT\
+%D and colored verbatim we color these commands yellow) and an
+%D efficient way of combining words.
+%D
+%D The sequence \type{||} simply leads to two words connected by
+%D a hyphen. Because we want to distinguish such a hyphen from
+%D the one inserted when \TEX\ hyphenates a word, we use a bit
+%D longer one.
+%D
+%D \hyphenation {spoel-wa-ter te-rug-win-unit}
+%D
+%D \starttest
+%D \test {spoelwater||terugwinunit}
+%D \stoptest
+%D
+%D As we already said, the \type{|} is a command. This commands
+%D accepts an optional argument before it's delimiter, which is
+%D also a \type{|}.
+%D
+%D \hyphenation {po-ly-meer che-mie}
+%D
+%D \starttest
+%D \test {polymeer|*|chemie}
+%D \stoptest
+%D
+%D Arguments like \type{*} are not interpreted and inserted
+%D directly, in contrary to arguments like:
+%D
+%D \starttest
+%D \test {polymeer|~|chemie}
+%D \test {|(|polymeer|)|chemie}
+%D \test {polymeer|(|chemie|)| }
+%D \stoptest
+%D
+%D Although such situations seldom occur |<|we typeset thousands
+%D of pages before we encountered one that forced us to enhance
+%D this mechanism|>| we also have to take care of comma's.
+%D
+%D \hyphenation {uit-stel-len}
+%D
+%D \starttest
+%D \test {op||, in|| en uitstellen}
+%D \stoptest
+%D
+%D The next special case (concerning quotes) was brought to my
+%D attention by Piet Tutelaers, one of the driving forces
+%D behind rebuilding hyphenation patterns for the dutch
+%D language.\footnote{In 1996 the spelling of the dutch
+%D language has been slightly reformed which made this topic
+%D actual again.} We'll also take care of this case.
+%D
+%D \starttest
+%D \test {AOW|'|er}
+%D \test {cd|'|tje}
+%D \test {ex|-|PTT|'|er}
+%D \test {rock|-|'n|-|roller}
+%D \stoptest
+%D
+%D Tobias Burnus pointed out that I should also support
+%D something like
+%D
+%D \starttest
+%D \test {well|_|known}
+%D \stoptest
+%D
+%D to stress the compoundness of hyphenated words.
+%D
+%D Of course we also have to take care of the special case:
+%D
+%D \starttest
+%D \test {text||color and ||font}
+%D \stoptest
+
+%D \macros
+%D {installdiscretionaries}
+%D
+%D The mechanism described here is one of the older inner parts
+%D of \CONTEXT. The most recent extensions concerns some
+%D special cases as well as the possibility to install other
+%D characters as delimiters. The prefered way of specifying
+%D compound words is using \type{||}, which is installed by:
+%D
+%D \starttyping
+%D \installdiscretionaries || -
+%D \stoptyping
+%D
+%D Some alternative definitions are:
+%D
+%D \startbuffer
+%D \installdiscretionaries ** -
+%D \installdiscretionaries ++ -
+%D \installdiscretionaries // -
+%D \installdiscretionaries ~~ -
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D after which we can say:
+%D
+%D \bgroup
+%D \getbuffer
+%D \starttest
+%D \test {test**test**test}
+%D \test {test++test++test}
+%D \test {test//test//test}
+%D \test {test~~test~~test}
+%D \stoptest
+%D \egroup
+
+%D \macros
+%D {compoundhyphen,
+%D beginofsubsentence,endofsubsentence}
+%D
+%D Now let's go to the macros. First we define some variables.
+%D In the main \CONTEXT\ modules these can be tuned by a setup
+%D command. Watch the (maybe) better looking compound hyphen.
+
+\ifx\compoundhyphen \undefined \def\compoundhyphen{\hbox{-\kern-.25ex-}} \fi
+
+\ifx\beginofsubsentence \undefined \def\beginofsubsentence{\hbox{---}} \fi
+\ifx\endofsubsentence \undefined \def\endofsubsentence {\hbox{---}} \fi
+
+%D The last two variables are needed for subsentences
+%D |<|like this one|>| which we did not yet mention.
+%D
+%D We want to enable breaking but at the same time don't want
+%D compound characters like |-| or || to be separated from the
+%D words. \TEX\ hackers will recognise the next two macro's:
+
+\ifx\prewordbreak \undefined \def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi
+%ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \prewordbreak } \fi
+\ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \hskip\zeropoint\relax} \fi
+
+\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667em} \fi % language specific
+
+%D \macros
+%D {beginofsubsentencespacing,endofsubsentencespacing}
+%D
+%D In the previous macros we provided two hooks which can be
+%D used to support nested sub||sentences. In \CONTEXT\ these
+%D hooks are used to insert a small space when needed.
+
+\ifx\beginofsubsentencespacing\undefined \let\beginofsubsentencespacing\relax \fi
+\ifx\endofsubsentencespacing \undefined \let\endofsubsentencespacing \relax \fi
+
+%D The following piece of code is a torture test compound
+%D hndling. The \type {\relax} before the \type {\ifmmode} is
+%D needed because of the alignment scanner (in \ETEX\ this
+%D problem is not present because there a protected macro is
+%D not expanded. Thanks to Tobias Burnus for providing this
+%D example.
+%D
+%D \startformula
+%D \left|f(x_n)-{1\over2}\right| =
+%D {\cases{|{1\over2}-x_n| &for $0\le x_n < {1\over2}$\cr
+%D |x_n-{1\over2}| &for ${1\over2}\zeropoint
+ (\prewordbreak
+ \else
+ \prewordbreak\discretionary{}{(-}{(}\prewordbreak
+ \fi}
+
+\definetextmodediscretionary ~
+ {\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak}
+
+\definetextmodediscretionary '
+ {\prewordbreak\discretionary{-}{}{'}\postwordbreak}
+
+\definetextmodediscretionary ^
+ {\prewordbreak\discretionary{\hbox{$|$}}{}{\hbox{$|$}}%
+ \allowbreak\postwordbreak} % bugged
+
+\definetextmodediscretionary <
+ {\beginofsubsentence\prewordbreak\beginofsubsentencespacing}
+
+\definetextmodediscretionary >
+ {\endofsubsentencespacing\prewordbreak\endofsubsentence}
+
+\definetextmodediscretionary =
+ {\prewordbreak\midsentence\prewordbreak} % {\prewordbreak\compoundhyphen}
+
+% french
+
+\definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:}
+\definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};}
+\definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?}
+\definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!}
+
+\definetextmodediscretionary *
+ {\prewordbreak\discretionary{-}{}{\kern.05em}\prewordbreak}
+
+% spanish
+
+\definetextmodediscretionary ?? {\prewordbreak\questiondown}
+\definetextmodediscretionary !! {\prewordbreak\exclamdown}
+
+% \ifx\normalcompound\undefined \let\normalcompound=| \fi
+
+%D \installdiscretionary | +
+%D \installdiscretionary + =
+
+\def\defaultdiscretionaryhyphen{\compoundhyphen}
+
+\installdiscretionary | \defaultdiscretionaryhyphen % installs in ctx and prt will fall back on it
+
+%D \macros
+%D {fakecompoundhyphen}
+%D
+%D In headers and footers as well as in active pieces of text
+%D we need a dirty hack. Try to imagine what is needed to
+%D savely break the next text across a line and at the same
+%D time make the words interactive.
+%D
+%D \starttyping
+%D \goto{Some||Long||Word}
+%D \stoptyping
+
+\def\fakecompoundhyphen
+ {\def\|{\mathortext\vert\dofakecompoundhyphen}}
+
+\def\dofakecompoundhyphen
+ {\def##1|%
+ {\doifelsenothing{##1}\compoundhyphen{##1}%
+ \kern\compoundbreakpoint\allowbreak}}
+
+%D \macros
+%D {midworddiscretionary}
+%D
+%D If needed, one can add a discretionary hyphen using \type
+%D {\midworddiscretionary}. This macro does the same as
+%D \PLAIN\ \TEX's \type {\-}, but, like the ones implemented
+%D earlier, this one also looks ahead for spaces and grouping
+%D tokens.
+
+\def\midworddiscretionary
+ {\futurelet\next\domidworddiscretionary}
+
+\def\domidworddiscretionary
+ {\ifx\next\blankspace\else
+ \ifx\next\bgroup \else
+ \ifx\next\egroup \else
+ \discretionary{-}{}{}%
+ \fi\fi\fi}
+
+%D \macros
+%D {installcompoundcharacter}
+%D
+%D When Tobias Burnus started translating the dutch manual of
+%D \PPCHTEX\ into german, he suggested to let \CONTEXT\ support
+%D the \type{german.sty} method of handling compound
+%D characters, especially the umlaut. This package is meant for
+%D use with \PLAIN\ \TEX\ as well as \LATEX.
+%D
+%D I decided to implement compound character support as
+%D versatile as possible. As a result one can define his own
+%D compound character support, like:
+%D
+%D \starttyping
+%D \installcompoundcharacter "a {\"a}
+%D \installcompoundcharacter "e {\"e}
+%D \installcompoundcharacter "i {\"i}
+%D \installcompoundcharacter "u {\"u}
+%D \installcompoundcharacter "o {\"o}
+%D \installcompoundcharacter "s {\SS}
+%D \stoptyping
+%D
+%D or even
+%D
+%D \starttyping
+%D \installcompoundcharacter "ck {\discretionary {k-}{k}{ck}}
+%D \installcompoundcharacter "ff {\discretionary{ff-}{f}{ff}}
+%D \stoptyping
+%D
+%D The support is not limited to alphabetic characters, so the
+%D next definition is also valid.
+%D
+%D \starttyping
+%D \installcompoundcharacter ". {.\doifnextcharelse{\spacetoken}{}{\kern.125em}}
+%D \stoptyping
+%D
+%D The implementation looks familiar and uses the same tricks as
+%D mentioned earlier in this module. We take care of two
+%D arguments, which complicates things a bit.
+
+\def\@nc@{@nc@} % normal character
+\def\@cc@{@cc@} % compound character
+\def\@cs@{@cs@} % compound characters
+\def\@cx@{@cx@} % compound definition
+
+%D When we started working on MK IV code, we needed a different
+%D approach for defining the active character itself. In MK II as
+%D well as in MK IV we now use the catcode vectors.
+
+\chardef\compoundcharactermode\plusone
+
+\def\installcompoundcharacter #1#2#3 #4% {#4} no grouping
+ {\ifcase\compoundcharactermode
+ % ignore mode
+ \else
+ \chardef\thecompoundcharacter`#1%
+ \@EA\chardef\csname\@nc@\string#1\endcsname\thecompoundcharacter
+ \def\!!stringa{#3}%
+ \@EA\def\csname\ifx\!!stringa\empty\@cc@\else\@cs@\fi\detokenize{#1#2#3}\endcsname{#4}%
+ \setevalue{\@cx@\detokenize{#1}}{\noexpand\handlecompoundcharacter{\detokenize{#1}}}% beter nr's
+% \@EA\letcatcodecommand\@EA\prtcatcodes\@EA\thecompoundcharacter\csname\@cx@\detokenize{#1}\endcsname
+% \@EA\letcatcodecommand\@EA\texcatcodes\@EA\thecompoundcharacter\csname\@cx@\detokenize{#1}\endcsname
+ \@EA\letcatcodecommand\@EA\ctxcatcodes\@EA\thecompoundcharacter\csname\@cx@\detokenize{#1}\endcsname
+ \fi}
+
+%D In order to serve the language specific well, we will introduce
+%D a namespace:
+
+% \ifx\currentlanguage\undefined
+ \let\compoundcharacterclass\empty
+% \else
+% \def\compoundcharacterclass{\currentlanguage}
+% \fi
+
+\def\@cc@{@cc@\compoundcharacterclass} % compound character
+\def\@cs@{@cs@\compoundcharacterclass} % compound characters
+
+%D We can also ignore definitions (needed in for instance \XML). Beware,
+%D this macro is supposed to be used grouped!
+
+\def\ignorecompoundcharacter
+ {\chardef\compoundcharactermode\zerocount}
+
+\let\restorecompoundcharacter \gobbleoneargument % obsolete
+\let\enableactivediscretionaries\relax % obsolete
+
+%D In handling the compound characters we have to take care of
+%D \type{\bgroup} and \type{\egroup} tokens, so we end up with
+%D a multi||step interpretation macro. We look ahead for a
+%D \type{\bgroup}, \type{\egroup} or \type{\blankspace}. Being
+%D no user of this mechanism, the credits for testing them goes
+%D to Tobias Burnus, the first german user of \CONTEXT.
+%D
+%D We define these macros as \type{\long} because we can
+%D expect \type{\par} tokens. We need to look into the future
+%D with \type{\futurelet} to prevent spaces from
+%D disappearing.
+
+\def\handlecompoundcharacter#1%
+ {\def\xhandlecompoundcharacter{\dohandlecompoundcharacter{#1}}%
+ \futurelet\next\xhandlecompoundcharacter}
+
+\def\dohandlecompoundcharacter
+ {\ifx\next\bgroup
+ %\@EA\dodohandlecompoundcharacter % handle "{ee} -> \"ee
+ %\@EA\gobbleoneargument % forget "{ee} -> ee
+ \@EA\handlecompoundcharacterone % ignore "{ee} -> "ee
+ \else\ifx\next\egroup
+ \@EAEAEA\donohandlecompoundcharacter
+ \else\ifx\next\blankspace
+ \@EA\@EAEAEA\@EA\donohandlecompoundcharacter
+ \else
+ \@EA\@EAEAEA\@EA\dodohandlecompoundcharacter
+ \fi\fi\fi}
+
+\def\donohandlecompoundcharacter#1{\csname\@nc@\string#1\endcsname}
+
+\def\dododohandlecompoundcharacter
+ {\ifx\next\bgroup
+ \@EA\handlecompoundcharacterone
+ \else\ifx\next\egroup
+ \@EAEAEA\handlecompoundcharacterone
+ \else\ifx\next\blankspace
+ \@EA\@EAEAEA\@EA\handlecompoundcharacterone
+ \else
+ \@EA\@EAEAEA\@EA\handlecompoundcharactertwo
+ \fi\fi\fi}
+
+\def\dodohandlecompoundcharacter#1#2% preserve space
+ {\def\xdodohandlecompoundcharacter{\dododohandlecompoundcharacter#1#2}%
+ \futurelet\next\xdodohandlecompoundcharacter}
+
+%D Besides taken care of the grouping and space tokens, we have
+%D to deal with three situations. First we look if the next
+%D character equals the first one, if so, then we just insert
+%D the original. Next we look if indeed a compound character is
+%D defined. We either execute the compound character or just
+%D insert the first. So we have
+%D
+%D \starttyping
+%D
+%D \stoptyping
+%D
+%D In later modules we will see how these commands are used.
+
+\long\def\handlecompoundcharacterone#1#2%
+ {\if\string#1\string#2% was: \ifx#1#2%
+ \def\next{\csname\@nc@\string#1\endcsname}%
+ \else\ifcsname\@cc@\string#1\string#2\endcsname
+ \def\next{\csname\@cc@\string#1\string#2\endcsname}%
+ \else
+ \def\next{\csname\@nc@\string#1\endcsname#2}%
+ \fi\fi
+ \next}
+
+\long\def\handlecompoundcharactertwo#1#2#3%
+ {\if\string#1\string#2%
+ \def\next{\csname\@nc@\string#1\endcsname#3}%
+ \else\ifcsname\@cs@\string#1\string#2\string#3\endcsname
+ \def\next{\csname\@cs@\string#1\string#2\string#3\endcsname}%
+ \else\ifcsname\@cc@\string#1\string#2\endcsname
+ \def\next{\csname\@cc@\string#1\string#2\endcsname#3}%
+ \else
+ \def\next{\csname\@nc@\string#1\endcsname#2#3}%
+ \fi\fi\fi
+ \next}
+
+%D For very obscure applications (see for an application \type
+%D {lang-sla.tex}) we provide:
+
+\def\simplifiedcompoundcharacter#1#2%
+ {\ifcsname\@cc@\string#1\string#2\endcsname
+ \@EA\@EA\@EA\firstofoneargument\csname\@cc@\string#1\string#2\endcsname
+ \else
+ #2%
+ \fi}
+
+%D \macros
+%D {disablediscretionaries,disablecompoundcharacter}
+%D
+%D Occasionally we need to disable this mechanism. For the
+%D moment we assume that \type {|} is used.
+
+\let\disablediscretionaries \ignorediscretionaries
+\let\disablecompoundcharacters\ignorecompoundcharacter
+
+%D \macros
+%D {normalcompound}
+%D
+%D Handy in for instance XML. (Kind of obsolete)
+
+\ifx\normalcompound\undefined \let\normalcompound=| \fi
+
+\protect \endinput
diff --git a/tex/context/base/lang-mis.mkiv b/tex/context/base/lang-mis.mkiv
new file mode 100644
index 000000000..0df45877b
--- /dev/null
+++ b/tex/context/base/lang-mis.mkiv
@@ -0,0 +1,689 @@
+%D \module
+%D [ file=lang-mis,
+%D version=1997.03.20, % used to be supp-lan.tex
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Compounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Compounds}
+
+%D \gdef\starttest
+%D {\blank
+%D \noindent
+%D \halign\bgroup\tt##\hskip2em#\hskip2em#\cr}
+%D
+%D \gdef\stoptest
+%D {\egroup
+%D \blank}
+%D
+%D \gdef\test#1%
+%D {\defconvertedargument\ascii{#1}\ascii&\hyphenatedword{#1}\cr}
+
+\unprotect
+
+%D One of \TEX's strong points in building paragraphs is the way
+%D hyphenations are handled. Although for real good hyphenation
+%D of non||english languages some extensions to the program are
+%D needed, fairly good results can be reached with the standard
+%D mechanisms and an additional macro, at least in Dutch.
+
+%D \CONTEXT\ originates in the wish to typeset educational
+%D materials, especially in a technical environment. In
+%D production oriented environments, a lot of compound words
+%D are used. Because the Dutch language poses no limits on
+%D combining words, we often favor putting dashes between those
+%D words, because it facilitates reading, at least for those
+%D who are not that accustomed to it.
+%D
+%D In \TEX\ compound words, separated by a hyphen, are not
+%D hyphenated at all. In spite of the multiple pass paragraph
+%D typesetting this can lead to parts of words sticking into
+%D the margin. The solution lays in saying \type
+%D {spoelwater||terugwinunit} instead of \type
+%D {spoelwater-terugwinunit}. By using a one character command
+%D like \type {|}, delimited by the same character \type {|},
+%D we get ourselves both a decent visualization (in \TEXEDIT\
+%D and colored verbatim we color these commands yellow) and an
+%D efficient way of combining words.
+%D
+%D The sequence \type{||} simply leads to two words connected by
+%D a hyphen. Because we want to distinguish such a hyphen from
+%D the one inserted when \TEX\ hyphenates a word, we use a bit
+%D longer one.
+%D
+%D \hyphenation {spoel-wa-ter te-rug-win-unit}
+%D
+%D \starttest
+%D \test {spoelwater||terugwinunit}
+%D \stoptest
+%D
+%D As we already said, the \type{|} is a command. This commands
+%D accepts an optional argument before it's delimiter, which is
+%D also a \type{|}.
+%D
+%D \hyphenation {po-ly-meer che-mie}
+%D
+%D \starttest
+%D \test {polymeer|*|chemie}
+%D \stoptest
+%D
+%D Arguments like \type{*} are not interpreted and inserted
+%D directly, in contrary to arguments like:
+%D
+%D \starttest
+%D \test {polymeer|~|chemie}
+%D \test {|(|polymeer|)|chemie}
+%D \test {polymeer|(|chemie|)| }
+%D \stoptest
+%D
+%D Although such situations seldom occur |<|we typeset thousands
+%D of pages before we encountered one that forced us to enhance
+%D this mechanism|>| we also have to take care of comma's.
+%D
+%D \hyphenation {uit-stel-len}
+%D
+%D \starttest
+%D \test {op||, in|| en uitstellen}
+%D \stoptest
+%D
+%D The next special case (concerning quotes) was brought to my
+%D attention by Piet Tutelaers, one of the driving forces
+%D behind rebuilding hyphenation patterns for the dutch
+%D language.\footnote{In 1996 the spelling of the dutch
+%D language has been slightly reformed which made this topic
+%D actual again.} We'll also take care of this case.
+%D
+%D \starttest
+%D \test {AOW|'|er}
+%D \test {cd|'|tje}
+%D \test {ex|-|PTT|'|er}
+%D \test {rock|-|'n|-|roller}
+%D \stoptest
+%D
+%D Tobias Burnus pointed out that I should also support
+%D something like
+%D
+%D \starttest
+%D \test {well|_|known}
+%D \stoptest
+%D
+%D to stress the compoundness of hyphenated words.
+%D
+%D Of course we also have to take care of the special case:
+%D
+%D \starttest
+%D \test {text||color and ||font}
+%D \stoptest
+
+%D \macros
+%D {installdiscretionaries}
+%D
+%D The mechanism described here is one of the older inner parts
+%D of \CONTEXT. The most recent extensions concerns some
+%D special cases as well as the possibility to install other
+%D characters as delimiters. The prefered way of specifying
+%D compound words is using \type{||}, which is installed by:
+%D
+%D \starttyping
+%D \installdiscretionaries || -
+%D \stoptyping
+%D
+%D Some alternative definitions are:
+%D
+%D \startbuffer
+%D \installdiscretionaries ** -
+%D \installdiscretionaries ++ -
+%D \installdiscretionaries // -
+%D \installdiscretionaries ~~ -
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D after which we can say:
+%D
+%D \bgroup
+%D \getbuffer
+%D \starttest
+%D \test {test**test**test}
+%D \test {test++test++test}
+%D \test {test//test//test}
+%D \test {test~~test~~test}
+%D \stoptest
+%D \egroup
+
+%D \macros
+%D {compoundhyphen,
+%D beginofsubsentence,endofsubsentence}
+%D
+%D Now let's go to the macros. First we define some variables.
+%D In the main \CONTEXT\ modules these can be tuned by a setup
+%D command. Watch the (maybe) better looking compound hyphen.
+
+\ifx\compoundhyphen \undefined \def\compoundhyphen{\hbox{-\kern-.25ex-}} \fi
+
+\ifx\beginofsubsentence \undefined \def\beginofsubsentence{\hbox{---}} \fi
+\ifx\endofsubsentence \undefined \def\endofsubsentence {\hbox{---}} \fi
+
+%D The last two variables are needed for subsentences
+%D |<|like this one|>| which we did not yet mention.
+%D
+%D We want to enable breaking but at the same time don't want
+%D compound characters like |-| or || to be separated from the
+%D words. \TEX\ hackers will recognise the next two macro's:
+
+\ifx\prewordbreak \undefined \def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi
+%ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \prewordbreak } \fi
+\ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \hskip\zeropoint\relax} \fi
+
+\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667em} \fi % language specific
+
+%D \macros
+%D {beginofsubsentencespacing,endofsubsentencespacing}
+%D
+%D In the previous macros we provided two hooks which can be
+%D used to support nested sub||sentences. In \CONTEXT\ these
+%D hooks are used to insert a small space when needed.
+
+\ifx\beginofsubsentencespacing\undefined \let\beginofsubsentencespacing\relax \fi
+\ifx\endofsubsentencespacing \undefined \let\endofsubsentencespacing \relax \fi
+
+%D The following piece of code is a torture test compound
+%D hndling. The \type {\relax} before the \type {\ifmmode} is
+%D needed because of the alignment scanner (in \ETEX\ this
+%D problem is not present because there a protected macro is
+%D not expanded. Thanks to Tobias Burnus for providing this
+%D example.
+%D
+%D \startformula
+%D \left|f(x_n)-{1\over2}\right| =
+%D {\cases{|{1\over2}-x_n| &for $0\le x_n < {1\over2}$\cr
+%D |x_n-{1\over2}| &for ${1\over2}2xxx
+
+\def\hyphenliketextmodediscretionary#1#2%
+ {\ifconditional\spaceafterdiscretionary
+ \prewordbreak\hbox{#1}\relax
+ \else\ifconditional\punctafterdiscretionary
+ \prewordbreak\hbox{#1}\relax
+ \else
+ \prewordbreak#2\postwordbreak % was prewordbreak
+ \fi\fi}
+
+\definetextmodediscretionary {}
+ {\hyphenliketextmodediscretionary\textmodehyphen\textmodehyphendiscretionary}
+
+\definetextmodediscretionary -
+ {\hyphenliketextmodediscretionary\normalhyphen\normalhyphendiscretionary}
+
+\definetextmodediscretionary _
+ {\hyphenliketextmodediscretionary\composedhyphen\composedhyphendiscretionary}
+
+\definetextmodediscretionary )
+ {\hyphenliketextmodediscretionary{)}{\discretionary{-)}{}{)}}}
+
+\definetextmodediscretionary (
+ {\ifdim\lastskip>\zeropoint
+ (\prewordbreak
+ \else
+ \prewordbreak\discretionary{}{(-}{(}\prewordbreak
+ \fi}
+
+\definetextmodediscretionary ~
+ {\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak}
+
+\definetextmodediscretionary '
+ {\prewordbreak\discretionary{-}{}{'}\postwordbreak}
+
+\definetextmodediscretionary ^
+ {\prewordbreak\discretionary{\hbox{$|$}}{}{\hbox{$|$}}%
+ \allowbreak\postwordbreak} % bugged
+
+\definetextmodediscretionary <
+ {\beginofsubsentence\prewordbreak\beginofsubsentencespacing}
+
+\definetextmodediscretionary >
+ {\endofsubsentencespacing\prewordbreak\endofsubsentence}
+
+\definetextmodediscretionary =
+ {\prewordbreak\midsentence\prewordbreak} % {\prewordbreak\compoundhyphen}
+
+% french
+
+\definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:}
+\definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};}
+\definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?}
+\definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!}
+
+\definetextmodediscretionary *
+ {\prewordbreak\discretionary{-}{}{\kern.05em}\prewordbreak}
+
+% spanish
+
+\definetextmodediscretionary ?? {\prewordbreak\questiondown}
+\definetextmodediscretionary !! {\prewordbreak\exclamdown}
+
+% \ifx\normalcompound\undefined \let\normalcompound=| \fi
+
+%D \installdiscretionary | +
+%D \installdiscretionary + =
+
+\def\defaultdiscretionaryhyphen{\compoundhyphen}
+
+\installdiscretionary | \defaultdiscretionaryhyphen % installs in ctx and prt will fall back on it
+
+%D \macros
+%D {fakecompoundhyphen}
+%D
+%D In headers and footers as well as in active pieces of text
+%D we need a dirty hack. Try to imagine what is needed to
+%D savely break the next text across a line and at the same
+%D time make the words interactive.
+%D
+%D \starttyping
+%D \goto{Some||Long||Word}
+%D \stoptyping
+
+\def\fakecompoundhyphen
+ {\def\|{\mathortext\vert\dofakecompoundhyphen}}
+
+\def\dofakecompoundhyphen
+ {\def##1|%
+ {\doifelsenothing{##1}\compoundhyphen{##1}%
+ \kern\compoundbreakpoint\allowbreak}}
+
+%D \macros
+%D {midworddiscretionary}
+%D
+%D If needed, one can add a discretionary hyphen using \type
+%D {\midworddiscretionary}. This macro does the same as
+%D \PLAIN\ \TEX's \type {\-}, but, like the ones implemented
+%D earlier, this one also looks ahead for spaces and grouping
+%D tokens.
+
+\def\midworddiscretionary
+ {\futurelet\next\domidworddiscretionary}
+
+\def\domidworddiscretionary
+ {\ifx\next\blankspace\else
+ \ifx\next\bgroup \else
+ \ifx\next\egroup \else
+ \discretionary{-}{}{}%
+ \fi\fi\fi}
+
+%D \macros
+%D {installcompoundcharacter}
+%D
+%D When Tobias Burnus started translating the dutch manual of
+%D \PPCHTEX\ into german, he suggested to let \CONTEXT\ support
+%D the \type{german.sty} method of handling compound
+%D characters, especially the umlaut. This package is meant for
+%D use with \PLAIN\ \TEX\ as well as \LATEX.
+%D
+%D I decided to implement compound character support as
+%D versatile as possible. As a result one can define his own
+%D compound character support, like:
+%D
+%D \starttyping
+%D \installcompoundcharacter "a {\"a}
+%D \installcompoundcharacter "e {\"e}
+%D \installcompoundcharacter "i {\"i}
+%D \installcompoundcharacter "u {\"u}
+%D \installcompoundcharacter "o {\"o}
+%D \installcompoundcharacter "s {\SS}
+%D \stoptyping
+%D
+%D or even
+%D
+%D \starttyping
+%D \installcompoundcharacter "ck {\discretionary {k-}{k}{ck}}
+%D \installcompoundcharacter "ff {\discretionary{ff-}{f}{ff}}
+%D \stoptyping
+%D
+%D The support is not limited to alphabetic characters, so the
+%D next definition is also valid.
+%D
+%D \starttyping
+%D \installcompoundcharacter ". {.\doifnextcharelse{\spacetoken}{}{\kern.125em}}
+%D \stoptyping
+%D
+%D The implementation looks familiar and uses the same tricks as
+%D mentioned earlier in this module. We take care of two
+%D arguments, which complicates things a bit.
+
+\def\@nc@{@nc@} % normal character
+\def\@cc@{@cc@} % compound character
+\def\@cs@{@cs@} % compound characters
+\def\@cx@{@cx@} % compound definition
+
+%D When we started working on MK IV code, we needed a different
+%D approach for defining the active character itself. In MK II as
+%D well as in MK IV we now use the catcode vectors.
+
+\chardef\compoundcharactermode\plusone
+
+\def\installcompoundcharacter #1#2#3 #4% {#4} no grouping
+ {\ifcase\compoundcharactermode
+ % ignore mode
+ \else
+ \chardef\thecompoundcharacter`#1%
+ \@EA\chardef\csname\@nc@\string#1\endcsname\thecompoundcharacter
+ \def\!!stringa{#3}%
+ \@EA\def\csname\ifx\!!stringa\empty\@cc@\else\@cs@\fi\detokenize{#1#2#3}\endcsname{#4}%
+ \setevalue{\@cx@\detokenize{#1}}{\noexpand\handlecompoundcharacter{\detokenize{#1}}}% beter nr's
+% \@EA\letcatcodecommand\@EA\prtcatcodes\@EA\thecompoundcharacter\csname\@cx@\detokenize{#1}\endcsname
+% \@EA\letcatcodecommand\@EA\texcatcodes\@EA\thecompoundcharacter\csname\@cx@\detokenize{#1}\endcsname
+ \@EA\letcatcodecommand\@EA\ctxcatcodes\@EA\thecompoundcharacter\csname\@cx@\detokenize{#1}\endcsname
+ \fi}
+
+%D In order to serve the language specific well, we will introduce
+%D a namespace:
+
+% \ifx\currentlanguage\undefined
+ \let\compoundcharacterclass\empty
+% \else
+% \def\compoundcharacterclass{\currentlanguage}
+% \fi
+
+\def\@cc@{@cc@\compoundcharacterclass} % compound character
+\def\@cs@{@cs@\compoundcharacterclass} % compound characters
+
+%D We can also ignore definitions (needed in for instance \XML). Beware,
+%D this macro is supposed to be used grouped!
+
+\def\ignorecompoundcharacter
+ {\chardef\compoundcharactermode\zerocount}
+
+\let\restorecompoundcharacter \gobbleoneargument % obsolete
+\let\enableactivediscretionaries\relax % obsolete
+
+%D In handling the compound characters we have to take care of
+%D \type{\bgroup} and \type{\egroup} tokens, so we end up with
+%D a multi||step interpretation macro. We look ahead for a
+%D \type{\bgroup}, \type{\egroup} or \type{\blankspace}. Being
+%D no user of this mechanism, the credits for testing them goes
+%D to Tobias Burnus, the first german user of \CONTEXT.
+%D
+%D We define these macros as \type{\long} because we can
+%D expect \type{\par} tokens. We need to look into the future
+%D with \type{\futurelet} to prevent spaces from
+%D disappearing.
+
+\def\handlecompoundcharacter#1%
+ {\def\xhandlecompoundcharacter{\dohandlecompoundcharacter{#1}}%
+ \futurelet\next\xhandlecompoundcharacter}
+
+\def\dohandlecompoundcharacter
+ {\ifx\next\bgroup
+ %\@EA\dodohandlecompoundcharacter % handle "{ee} -> \"ee
+ %\@EA\gobbleoneargument % forget "{ee} -> ee
+ \@EA\handlecompoundcharacterone % ignore "{ee} -> "ee
+ \else\ifx\next\egroup
+ \@EAEAEA\donohandlecompoundcharacter
+ \else\ifx\next\blankspace
+ \@EA\@EAEAEA\@EA\donohandlecompoundcharacter
+ \else
+ \@EA\@EAEAEA\@EA\dodohandlecompoundcharacter
+ \fi\fi\fi}
+
+\def\donohandlecompoundcharacter#1{\csname\@nc@\string#1\endcsname}
+
+\def\dododohandlecompoundcharacter
+ {\ifx\next\bgroup
+ \@EA\handlecompoundcharacterone
+ \else\ifx\next\egroup
+ \@EAEAEA\handlecompoundcharacterone
+ \else\ifx\next\blankspace
+ \@EA\@EAEAEA\@EA\handlecompoundcharacterone
+ \else
+ \@EA\@EAEAEA\@EA\handlecompoundcharactertwo
+ \fi\fi\fi}
+
+\def\dodohandlecompoundcharacter#1#2% preserve space
+ {\def\xdodohandlecompoundcharacter{\dododohandlecompoundcharacter#1#2}%
+ \futurelet\next\xdodohandlecompoundcharacter}
+
+%D Besides taken care of the grouping and space tokens, we have
+%D to deal with three situations. First we look if the next
+%D character equals the first one, if so, then we just insert
+%D the original. Next we look if indeed a compound character is
+%D defined. We either execute the compound character or just
+%D insert the first. So we have
+%D
+%D \starttyping
+%D
+%D \stoptyping
+%D
+%D In later modules we will see how these commands are used.
+
+\long\def\handlecompoundcharacterone#1#2%
+ {\if\string#1\string#2% was: \ifx#1#2%
+ \def\next{\csname\@nc@\string#1\endcsname}%
+ \else\ifcsname\@cc@\string#1\string#2\endcsname
+ \def\next{\csname\@cc@\string#1\string#2\endcsname}%
+ \else
+ \def\next{\csname\@nc@\string#1\endcsname#2}%
+ \fi\fi
+ \next}
+
+\long\def\handlecompoundcharactertwo#1#2#3%
+ {\if\string#1\string#2%
+ \def\next{\csname\@nc@\string#1\endcsname#3}%
+ \else\ifcsname\@cs@\string#1\string#2\string#3\endcsname
+ \def\next{\csname\@cs@\string#1\string#2\string#3\endcsname}%
+ \else\ifcsname\@cc@\string#1\string#2\endcsname
+ \def\next{\csname\@cc@\string#1\string#2\endcsname#3}%
+ \else
+ \def\next{\csname\@nc@\string#1\endcsname#2#3}%
+ \fi\fi\fi
+ \next}
+
+%D For very obscure applications (see for an application \type
+%D {lang-sla.tex}) we provide:
+
+\def\simplifiedcompoundcharacter#1#2%
+ {\ifcsname\@cc@\string#1\string#2\endcsname
+ \@EA\@EA\@EA\firstofoneargument\csname\@cc@\string#1\string#2\endcsname
+ \else
+ #2%
+ \fi}
+
+%D \macros
+%D {disablediscretionaries,disablecompoundcharacter}
+%D
+%D Occasionally we need to disable this mechanism. For the
+%D moment we assume that \type {|} is used.
+
+\let\disablediscretionaries \ignorediscretionaries
+\let\disablecompoundcharacters\ignorecompoundcharacter
+
+%D \macros
+%D {normalcompound}
+%D
+%D Handy in for instance XML. (Kind of obsolete)
+
+\ifx\normalcompound\undefined \let\normalcompound=| \fi
+
+\protect \endinput
diff --git a/tex/context/base/lang-run.mkii b/tex/context/base/lang-run.mkii
new file mode 100644
index 000000000..4b332cfb9
--- /dev/null
+++ b/tex/context/base/lang-run.mkii
@@ -0,0 +1,36 @@
+%D \module
+%D [ file=lang-run,
+%D version=2005.09.08,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 code is hooked into the core macros and saves some
+%D format space.]
+
+\unprotect
+
+\gdef\showpatterns
+ {\bgroup
+ \def\doshowpatterns##1##2##3##4% language number encoding mapping
+ {\NC##1\NC##3\NC##4\NC##2\NC
+ \specificlanguageparameter{##1}\s!lefthyphenmin \NC
+ \specificlanguageparameter{##1}\s!righthyphenmin\NC\NR}%
+ \starttabulate[|c|c|c|c|c|c|]
+ \HL
+ \NC \bf language \NC \bf encoding \NC \bf mapping \NC \bf number \NC
+ \bf left\low{min} \NC
+ \bf right\low{min} \NC \NR
+ \HL
+ \preloadedpmessage
+ \HL
+ \stoptabulate
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/lang-sla.mkii b/tex/context/base/lang-sla.mkii
new file mode 100644
index 000000000..62483aeb6
--- /dev/null
+++ b/tex/context/base/lang-sla.mkii
@@ -0,0 +1,30 @@
+%D \module
+%D [ file=lang-sla,
+%D version=1999.09.13, % 1997.09.03
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Slavic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\def\sloveniancharacter#1%
+ {\ifcase#1\unknowncharacter
+ \or a\or b\or c\or \ccaron\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m%
+ \or n\or o\or p\or r\or s\or \scaron\or t\or u\or v\or z\or \zcaron
+ \else
+ \unknowncharacter
+ \fi}
+
+\def\slovenianCharacter#1%
+ {\ifcase#1\unknowncharacter
+ \or A\or B\or C\or \Ccaron\or D\or E\or F\or G\or H\or I\or J\or K\or L\or M%
+ \or N\or O\or P\or R\or S\or \Scaron\or T\or U\or V\or Z\or \Zcaron
+ \else
+ \unknowncharacter
+ \fi}
+
+\endinput
diff --git a/tex/context/base/lang-sla.mkiv b/tex/context/base/lang-sla.mkiv
new file mode 100644
index 000000000..479012615
--- /dev/null
+++ b/tex/context/base/lang-sla.mkiv
@@ -0,0 +1,17 @@
+%D \module
+%D [ file=lang-sla,
+%D version=2006.09.16,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Slavic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\def\sloveniancharacters#1{\ctxlua{converters.alphabetic(\number#1,"sl")}}
+\def\slovenianCharacters#1{\ctxlua{converters.Alphabetic(\number#1,"sl")}}
+
+\endinput
diff --git a/tex/context/base/lang-sla.tex b/tex/context/base/lang-sla.tex
new file mode 100644
index 000000000..2c645af5a
--- /dev/null
+++ b/tex/context/base/lang-sla.tex
@@ -0,0 +1,497 @@
+%D \module
+%D [ file=lang-sla,
+%D version=1999.09.13, % 1997.09.03
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Slavic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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: replace \'.. by \namedglyph
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+%D
+%D \starttabulate[|lB|l|]
+%D \NC Czech \NC Tom Hudec, Petr Sojka \NC \NR
+%D \NC Polish \NC Grzegorz Sapijaszko \NC \NR
+%D \NC Croatian \NC \Zcaron eljko Vrba \NC \NR
+%D \NC Slovenian \NC Mojca Miklavec \NC \NR
+%D \NC Cz and Sk \NC Richard Gabriel \NC \NR
+%D \stoptabulate
+
+% Belarussian, Russian, Ukrainian, Bulgarian, Macedonian,
+% Serbo-Croatian, Slovenian, Czech, Kushubian,
+% Lusatian/Sorbian/Wendish, Polish, Slovak, Albanian,
+% Illyrian, Armenian
+
+\writestatus{loading}{ConTeXt Language Macros / Slavic Languages}
+
+\unprotect
+
+% \unexpanded\def\textormathglue#1#2#3% submitted original
+% {\begingroup
+% \scratchdimen=#1\hspaceamount\empty{#3}%
+% \scratchskip=\zeropoint\!!plus.5\scratchdimen\!!minus.3\scratchdimen\relax
+% \ifmmode
+% \mskip#1#2%
+% \else
+% \kern#1\hspaceamount\empty{#3}%
+% \hskip\scratchskip
+% \fi
+% \endgroup}
+
+% actually we could use the new pdftex features
+
+\unexpanded\def\textormathglue#1#2#3% cleaned up one
+ {\begingroup
+ \ifmmode
+ \mskip#1#2%
+ \else
+ \scratchdimen#1\hspaceamount\empty{#3}%
+ \scratchskip\scratchdimen\!!plus.5\scratchdimen\!!minus.3\scratchdimen
+ \hskip\scratchskip
+ \fi
+ \endgroup}
+
+\def\thinglue {\textormathglue+\thinmuskip 1}
+\def\medglue {\textormathglue+\medmuskip 2}
+\def\thickglue{\textormathglue+\thickmuskip3}
+
+\installlanguage
+ [\s!pl]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,{.},\ ,\v!month,\ ,\v!year},
+ \s!mapping={pl0,ec,qx},
+ \s!encoding={pl0,ec,qx}]
+
+\installlanguage
+ [\s!cs]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\thickglue--\thickglue\penalty-20\relax, % hh, \relax added
+ \c!rightsentence=\thickglue--\thickglue\penalty-20\relax,
+ \c!leftsubsentence=~---~\penalty-20\relax,
+ \c!rightsubsentence=~---~\penalty-20\relax,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,{.\,},\v!month,\ ,\v!year},
+ \s!mapping={il2,ec},
+ \s!encoding={il2,ec}]
+
+\installlanguage
+ [\s!sk]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,{.\,},\v!month,\ ,\v!year},
+ \s!mapping={il2,ec},
+ \s!encoding={il2,ec}]
+
+\installlanguage
+ [\s!hr]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\ ,\v!month,\ ,\v!year},
+ \s!mapping=ec,
+ \s!encoding=ec]
+
+%D The default quotation marks for Slovenian were chosen as
+%D \lowerleftdoubleninequote these ones\upperrightdoublesixquote\
+%D which was probably due to the strong influence computers
+%D had on typesetting, but \rightguillemot these ones\leftguillemot\
+%D are \quotation{more correct}.
+%D
+%D If you still want the other quotation marks, use this:
+%D
+%D \starttyping
+%D \installlanguage
+%D [sl]
+%D [leftquote=\lowerleftsingleninequote,
+%D rightquote=\upperrightsinglesixquote,
+%D leftquotation=\lowerleftdoubleninequote,
+%D rightquotation=\upperrightdoublesixquote]
+%D \stoptyping
+%D
+%D If you disagree with the change, please send an email to Mojca, but
+%D best use some pretty strong arguments because she loves S{\sl love}nia
+%D to much to comprimise on this.
+%D
+%D German faces approximately the same problem. I (MM) would prefer to
+%D have something like:
+%D
+%D \starttyping
+%D \mainlanguage[sl][quotationstyle=guillemot|doublequote] % better name needed
+%D \stoptyping
+%D
+%D but users are expected to respect the rules of nice and correct
+%D typography anyway.
+
+\installlanguage
+ [\s!sl]
+ [\c!spacing=\v!packed,
+ \c!leftsentence={\hbox{--~}},
+ \c!rightsentence={\hbox{~--}},
+ \c!leftsubsentence={--},
+ \c!rightsubsentence={--},
+ %\c!leftquote=\lowerleftsingleninequote,
+ %\c!rightquote=\upperrightsinglesixquote,
+ %\c!leftquotation=\lowerleftdoubleninequote,
+ %\c!rightquotation=\upperrightdoublesixquote,
+ \c!leftquote=\guilsingleright,
+ \c!rightquote=\guilsingleleft,
+ \c!leftquotation=\rightguillemot,
+ \c!rightquotation=\leftguillemot,
+ \c!date={\v!day,{.},\ ,\v!month,\ ,\v!year},
+ \s!mapping=ec,
+ \s!encoding=ec]
+
+\installlanguage [polish] [\s!pl]
+\installlanguage [czech] [\s!cs]
+\installlanguage [slovak] [\s!sk]
+\installlanguage [croatian] [\s!hr]
+\installlanguage [slovenian] [\s!sl]
+\installlanguage [slovene] [\s!sl] % both possible (mojca: still needed?)
+
+\installlanguage [cz] [\s!cs]
+
+% labels
+
+\setupheadtext [\s!pl] [\v!content=Spis tre\sacute ci]
+\setupheadtext [\s!cs] [\v!content=Obsah]
+\setupheadtext [\s!sk] [\v!content=Obsah]
+\setupheadtext [\s!hr] [\v!content=Sadr\zcaron aj]
+\setupheadtext [\s!sl] [\v!content=Kazalo]
+
+\setupheadtext [\s!pl] [\v!tables=Tabele]
+\setupheadtext [\s!cs] [\v!tables=Tabulky]
+\setupheadtext [\s!sk] [\v!tables=Tabuliek]
+\setupheadtext [\s!hr] [\v!tables=Tablice]
+\setupheadtext [\s!sl] [\v!tables=Tabele]
+
+\setupheadtext [\s!pl] [\v!figures=Ilustracje]
+\setupheadtext [\s!cs] [\v!figures=Obr\aacute zky]
+\setupheadtext [\s!sk] [\v!figures=Obr\aacute zkov]
+\setupheadtext [\s!hr] [\v!figures=Slike]
+\setupheadtext [\s!sl] [\v!figures=Slike]
+
+\setupheadtext [\s!pl] [\v!graphics=Grafika]
+\setupheadtext [\s!cs] [\v!graphics=Grafy]
+\setupheadtext [\s!sk] [\v!graphics=Graf]
+\setupheadtext [\s!hr] [\v!graphics=Slike]
+\setupheadtext [\s!sl] [\v!graphics=Slike]
+
+\setupheadtext [\s!pl] [\v!intermezzi=Intermezza]
+\setupheadtext [\s!cs] [\v!intermezzi=Intermezza]
+\setupheadtext [\s!sk] [\v!intermezzi=Intermezz\aacute]
+\setupheadtext [\s!hr] [\v!intermezzi=Intermezza]
+\setupheadtext [\s!sl] [\v!intermezzi=Intermezzi]
+
+\setupheadtext [\s!pl] [\v!index=Indeks]
+\setupheadtext [\s!cs] [\v!index=Rejst\rcaron\iacute k]
+\setupheadtext [\s!sk] [\v!index=Zoznam]
+\setupheadtext [\s!hr] [\v!index=Indeks]
+\setupheadtext [\s!sl] [\v!index=Stvarno kazalo]
+
+\setupheadtext [\s!pl] [\v!abbreviations=Skr\oacute cenie]
+\setupheadtext [\s!cs] [\v!abbreviations=Zkratky]
+\setupheadtext [\s!sk] [\v!abbreviations=Skratky]
+\setupheadtext [\s!hr] [\v!abbreviations=Kratice]
+\setupheadtext [\s!sl] [\v!abbreviations=Kratice]
+
+\setupheadtext [\s!pl] [\v!logos=Znaki]
+\setupheadtext [\s!cs] [\v!logos=Loga]
+\setupheadtext [\s!sk] [\v!logos=Log\aacute]
+\setupheadtext [\s!hr] [\v!logos=Znakovi]
+\setupheadtext [\s!sl] [\v!logos=Logotipi]
+
+\setupheadtext [\s!pl] [\v!units=Jednostki]
+\setupheadtext [\s!cs] [\v!units=Jednotky]
+\setupheadtext [\s!sk] [\v!units=Jednotky]
+\setupheadtext [\s!hr] [\v!units=Jednostki]
+\setupheadtext [\s!sl] [\v!units=Enote]
+
+%setupheadtext [\s!pl] [pubs=?]
+\setupheadtext [\s!cs] [pubs=Literatura]
+%setupheadtext [\s!sk] [pubs=?]
+%setupheadtext [\s!hr] [pubs=?]
+\setupheadtext [\s!sl] [pubs=Literatura]
+
+\setuplabeltext [\s!pl] [\v!table=Tabela ]
+\setuplabeltext [\s!cs] [\v!table=Tabulka ]
+\setuplabeltext [\s!sk] [\v!table=Tabu\lcaron ka ]
+\setuplabeltext [\s!hr] [\v!table=T\aacute bl\aacute zat ] % [\v!table=Tablica ]
+\setuplabeltext [\s!sl] [\v!table=Tabela ]
+
+\setuplabeltext [\s!pl] [\v!figure=Ilustracja ]
+\setuplabeltext [\s!cs] [\v!figure=Obr\aacute zek ]
+\setuplabeltext [\s!sk] [\v!figure=Obr\aacute zok ]
+\setuplabeltext [\s!hr] [\v!figure=Slika ]
+\setuplabeltext [\s!sl] [\v!figure=Slika ]
+
+\setuplabeltext [\s!pl] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!cs] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!sk] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!hr] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!sl] [\v!intermezzo=Intermezzo ]
+
+\setuplabeltext [\s!pl] [\v!graphic=Grafika ]
+\setuplabeltext [\s!cs] [\v!graphic=Graf ]
+\setuplabeltext [\s!sk] [\v!graphic=Graf ]
+\setuplabeltext [\s!hr] [\v!graphic=Slika ]
+\setuplabeltext [\s!sl] [\v!graphic=Slika ]
+
+\setuplabeltext [\s!pl] [\v!chapter=] % Rozdzia\l
+\setuplabeltext [\s!cs] [\v!chapter=] % Kapitola
+\setuplabeltext [\s!sk] [\v!chapter=] % Kapitola
+\setuplabeltext [\s!hr] [\v!chapter=] % Rozdzia\l
+\setuplabeltext [\s!sl] [\v!chapter=] % Poglavje
+
+\setuplabeltext [\s!pl] [\v!section=] % Podrozdzia\l
+\setuplabeltext [\s!cs] [\v!section=] % Sekce
+\setuplabeltext [\s!sk] [\v!section=] % Sekcia
+\setuplabeltext [\s!hr] [\v!section=] % Podrozdzia\l
+\setuplabeltext [\s!sl] [\v!section=]
+
+\setuplabeltext [\s!pl] [\v!subsection=]
+\setuplabeltext [\s!cs] [\v!subsection=] % Podsekce
+\setuplabeltext [\s!sk] [\v!subsection=] % Podsekcia
+\setuplabeltext [\s!hr] [\v!subsection=]
+\setuplabeltext [\s!sl] [\v!subsection=]
+
+\setuplabeltext [\s!pl] [\v!subsubsection=]
+\setuplabeltext [\s!cs] [\v!subsubsection=] % Podpodsekce
+\setuplabeltext [\s!sk] [\v!subsubsection=] % Podpodsekcia
+\setuplabeltext [\s!hr] [\v!subsubsection=]
+\setuplabeltext [\s!sl] [\v!subsubsection=]
+
+\setuplabeltext [\s!pl] [\v!subsubsubsection=]
+\setuplabeltext [\s!cs] [\v!subsubsubsection=] % Podpodpodsekce
+\setuplabeltext [\s!sk] [\v!subsubsubsection=] % Podpodpodsekcia
+\setuplabeltext [\s!hr] [\v!subsubsubsection=]
+\setuplabeltext [\s!sl] [\v!subsubsubsection=]
+
+\setuplabeltext [\s!pl] [\v!appendix=] % Dodatek
+\setuplabeltext [\s!cs] [\v!appendix=P\rcaron\iacute loha ]
+\setuplabeltext [\s!sk] [\v!appendix=Pr\iacute loha ]
+\setuplabeltext [\s!hr] [\v!appendix=Dodatak ]
+\setuplabeltext [\s!sl] [\v!appendix=Dodatek ]
+
+\setuplabeltext [\s!pl] [\v!part=Ust\eogonek p ]
+\setuplabeltext [\s!cs] [\v!part=\Ccaron \aacute st ]
+\setuplabeltext [\s!sk] [\v!part=\Ccaron as\tcaron{} ]
+\setuplabeltext [\s!hr] [\v!part=Dio ]
+\setuplabeltext [\s!sl] [\v!part=Del ]
+
+\setuplabeltext [\s!pl] [\v!line=wiersz ]
+\setuplabeltext [\s!cs] [\v!line=\rcaron\aacute dek ]
+\setuplabeltext [\s!sk] [\v!line=riadok ]
+\setuplabeltext [\s!hr] [\v!line=red ]
+\setuplabeltext [\s!sl] [\v!line=vrstica ]
+
+\setuplabeltext [\s!pl] [\v!lines=wiersze ]
+\setuplabeltext [\s!cs] [\v!lines=\rcaron\aacute dky ]
+\setuplabeltext [\s!sk] [\v!lines=riadky ]
+\setuplabeltext [\s!hr] [\v!lines=redovi ]
+\setuplabeltext [\s!sl] [\v!lines=vrstice ]
+
+\setuplabeltext [\s!pl] [\v!january=stycznia]
+\setuplabeltext [\s!pl] [\v!february=lutego]
+\setuplabeltext [\s!pl] [\v!march=marca]
+\setuplabeltext [\s!pl] [\v!april=kwietnia]
+\setuplabeltext [\s!pl] [\v!may=maja]
+\setuplabeltext [\s!pl] [\v!june=czerwca]
+\setuplabeltext [\s!pl] [\v!july=lipca]
+\setuplabeltext [\s!pl] [\v!august=sierpnia]
+\setuplabeltext [\s!pl] [\v!september=wrze\sacute nia]
+\setuplabeltext [\s!pl] [\v!october=pa\zacute dziernika]
+\setuplabeltext [\s!pl] [\v!november=listopada]
+\setuplabeltext [\s!pl] [\v!december=grudnia]
+
+\setuplabeltext [\s!cs] [\v!january=ledna]
+\setuplabeltext [\s!cs] [\v!february=\uacute nora]
+\setuplabeltext [\s!cs] [\v!march=b\rcaron ezna]
+\setuplabeltext [\s!cs] [\v!april=dubna]
+\setuplabeltext [\s!cs] [\v!may=kv\ecaron tna]
+\setuplabeltext [\s!cs] [\v!june=\ccaron ervna]
+\setuplabeltext [\s!cs] [\v!july=\ccaron ervence]
+\setuplabeltext [\s!cs] [\v!august=srpna]
+\setuplabeltext [\s!cs] [\v!september=z\aacute\rcaron\iacute{}]
+\setuplabeltext [\s!cs] [\v!october=\rcaron\iacute jna]
+\setuplabeltext [\s!cs] [\v!november=listopadu]
+\setuplabeltext [\s!cs] [\v!december=prosince]
+
+\setuplabeltext [\s!sk] [\v!january=janu\aacute ra]
+\setuplabeltext [\s!sk] [\v!february=febru\aacute ra]
+\setuplabeltext [\s!sk] [\v!march=marca]
+\setuplabeltext [\s!sk] [\v!april=apr\iacute la]
+\setuplabeltext [\s!sk] [\v!may=m\aacute ja]
+\setuplabeltext [\s!sk] [\v!june=j\uacute na]
+\setuplabeltext [\s!sk] [\v!july=j\uacute la]
+\setuplabeltext [\s!sk] [\v!august=augusta]
+\setuplabeltext [\s!sk] [\v!september=septembra]
+\setuplabeltext [\s!sk] [\v!october=okt\oacute bra]
+\setuplabeltext [\s!sk] [\v!november=novembra]
+\setuplabeltext [\s!sk] [\v!december=decembra]
+
+\setuplabeltext [\s!hr] [\v!january=sije\ccaron anj]
+\setuplabeltext [\s!hr] [\v!february=velja\ccaron a]
+\setuplabeltext [\s!hr] [\v!march=o\zcaron ujak]
+\setuplabeltext [\s!hr] [\v!april=travanj]
+\setuplabeltext [\s!hr] [\v!may=svibanj]
+\setuplabeltext [\s!hr] [\v!june=lipanj]
+\setuplabeltext [\s!hr] [\v!july=srpanj]
+\setuplabeltext [\s!hr] [\v!august=kolovoz]
+\setuplabeltext [\s!hr] [\v!september=rujan]
+\setuplabeltext [\s!hr] [\v!october=listopad]
+\setuplabeltext [\s!hr] [\v!november=studeni]
+\setuplabeltext [\s!hr] [\v!december=prosinac]
+
+\setuplabeltext [\s!sl] [\v!january=januar]
+\setuplabeltext [\s!sl] [\v!february=februar]
+\setuplabeltext [\s!sl] [\v!march=marec]
+\setuplabeltext [\s!sl] [\v!april=april]
+\setuplabeltext [\s!sl] [\v!may=maj]
+\setuplabeltext [\s!sl] [\v!june=junij]
+\setuplabeltext [\s!sl] [\v!july=julij]
+\setuplabeltext [\s!sl] [\v!august=avgust]
+\setuplabeltext [\s!sl] [\v!september=september]
+\setuplabeltext [\s!sl] [\v!october=oktober]
+\setuplabeltext [\s!sl] [\v!november=november]
+\setuplabeltext [\s!sl] [\v!december=december]
+
+\setuplabeltext [\s!pl] [\v!sunday=niedziela]
+\setuplabeltext [\s!pl] [\v!monday=poniedzia\lstroke ek]
+\setuplabeltext [\s!pl] [\v!tuesday=wtorek]
+\setuplabeltext [\s!pl] [\v!wednesday=\sacute roda]
+\setuplabeltext [\s!pl] [\v!thursday=czwartek]
+\setuplabeltext [\s!pl] [\v!friday=pi\aogonek tek]
+\setuplabeltext [\s!pl] [\v!saturday=sobota]
+
+% new
+\setuplabeltext [\s!cs] [\v!sunday=ned\ecaron le]
+\setuplabeltext [\s!cs] [\v!monday=pond\ecaron l\iacute]
+\setuplabeltext [\s!cs] [\v!tuesday=\uacute ter\yacute]
+\setuplabeltext [\s!cs] [\v!wednesday=st\rcaron eda]
+\setuplabeltext [\s!cs] [\v!thursday=\ccaron tvrtek]
+\setuplabeltext [\s!cs] [\v!friday=p\aacute tek]
+\setuplabeltext [\s!cs] [\v!saturday=sobota]
+
+\setuplabeltext [\s!hr] [\v!sunday=nedjelja]
+\setuplabeltext [\s!hr] [\v!monday=ponedjeljak]
+\setuplabeltext [\s!hr] [\v!tuesday=utorak]
+\setuplabeltext [\s!hr] [\v!wednesday=srijeda]
+\setuplabeltext [\s!hr] [\v!thursday=\ccaron etvrtak]
+\setuplabeltext [\s!hr] [\v!friday=petak]
+\setuplabeltext [\s!hr] [\v!saturday=subota]
+
+\setuplabeltext [\s!sl] [\v!sunday=nedelja]
+\setuplabeltext [\s!sl] [\v!monday=ponedeljek]
+\setuplabeltext [\s!sl] [\v!tuesday=torek]
+\setuplabeltext [\s!sl] [\v!wednesday=sreda]
+\setuplabeltext [\s!sl] [\v!thursday=\ccaron etrtek]
+\setuplabeltext [\s!sl] [\v!friday=petek]
+\setuplabeltext [\s!sl] [\v!saturday=sobota]
+
+%D Rather new ...
+%\installlanguage
+% [\s!cs]
+% [\c!spacing=\v!packed,
+% \c!leftsentence=---,
+% \c!rightsentence=---,
+% \c!leftsubsentence=---,
+% \c!rightsubsentence=---,
+% \c!leftquote=\lowerleftsingleninequote,
+% \c!rightquote=\upperrightsinglesixquote,
+% \c!leftquotation=\lowerleftdoubleninequote,
+% \c!rightquotation=\upperrightdoublesixquote,
+% \c!date={\v!day,\ ,\v!month,\ ,\v!year}]
+
+\setuplabeltext [\s!sl] [\v!page=stran ]
+\setuplabeltext [\s!sl] [\v!atpage=na strani ]
+\setuplabeltext [\s!sl] [\v!hencefore=glej zgoraj]
+\setuplabeltext [\s!sl] [\v!hereafter=glej spodaj]
+\setuplabeltext [\s!sl] [\v!see=glej ]
+
+% new
+\setuplabeltext [\s!cs] [\v!page=strana ]
+\setuplabeltext [\s!cs] [\v!atpage=na stran\ecaron\ ]
+\setuplabeltext [\s!cs] [\v!hencefore=viz v\yacute\scaron e ]
+\setuplabeltext [\s!cs] [\v!hereafter=viz n\iacute\zcaron e ]
+\setuplabeltext [\s!cs] [\v!see=viz ]
+
+%D \ShowAllLanguageValues [\s!pl] [polish] {Polish} {furniture}
+%D \ShowAllLanguageValues [\s!cs] [czech] {Czech} {mate}
+%D \ShowAllLanguageValues [\s!sk] [slovak] {Slovakian} {face}
+%D \ShowAllLanguageValues [\s!hr] [croatian] {Croatian} {heartthrob}
+%D \ShowAllLanguageValues [\s!sl] [slovenian] {Slovenian} {mountains}
+
+%D A present from Brooks Moses and Hans Hagen for Mojca Miklavec:
+
+\def\doconvertsloveniancharacters{\dodoconvertcharacters{25}}
+
+\def\sloveniancharacters{\doconvertsloveniancharacters\sloveniancharacter}
+\def\slovenianCharacters{\doconvertsloveniancharacters\slovenianCharacter}
+
+%D Define general-purpose macros for Slovenian character enumerations:
+
+\defineconversion [sloveniancharacter] [\sloveniancharacter]
+\defineconversion [slovenianCharacter] [\slovenianCharacter]
+
+\defineconversion [sloveniancharacters] [\sloveniancharacters]
+\defineconversion [slovenianCharacters] [\slovenianCharacters]
+
+%D Define these as the general character enumeration when
+%D language is Slovenian. If you feel uncomfortable with this,
+%D mail Mojca, since she promised to to take the heat.
+
+\defineconversion [sl] [character] [\sloveniancharacter]
+\defineconversion [sl] [Character] [\slovenianCharacter]
+
+\defineconversion [sl] [characters] [\sloveniancharacters]
+\defineconversion [sl] [Characters] [\slovenianCharacters]
+
+\defineconversion [sl] [a] [\sloveniancharacters]
+\defineconversion [sl] [A] [\slovenianCharacters]
+\defineconversion [sl] [AK] [\smallcapped\sloveniancharacters]
+\defineconversion [sl] [KA] [\smallcapped\sloveniancharacters]
+
+% this will become more generic : \languagecharacters{sl}{..}
+
+\let\sloveniancharacter\gobbleoneargument
+\let\slovenianCharacter\gobbleoneargument
+
+%D Plugins:
+
+\loadmarkfile{lang-sla}
+
+\protect \endinput
diff --git a/tex/context/base/lang-spa.tex b/tex/context/base/lang-spa.tex
new file mode 100644
index 000000000..f6e22aa51
--- /dev/null
+++ b/tex/context/base/lang-spa.tex
@@ -0,0 +1,74 @@
+%D \module
+%D [ file=lang-spa,
+%D version=2002.04.17,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Spacing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Spacing}
+
+%D This module was created in the process of enhancing
+%D support for French (with the help of Daniel Flipo).
+
+\unprotect
+
+\definehspace [\s!fr] [quotation] [\flexiblespaceamount{.8}{.3}{.8}]
+\definehspace [\s!fr] [sentence] [\fixedspaceamount{1}]
+
+%definehspace [\s!fr] [quote] [\flexiblespaceamount{.8}{.3}{.8}]
+%definehspace [\s!fr] [speech] [\flexiblespaceamount{.8}{.3}{.8}]
+
+\definehspace [\s!fr] [interquotation] [\zeropoint]
+\definehspace [\s!fr] [intersentence] [\zeropoint]
+
+\definehspace [\string :] [\zeropoint]
+\definehspace [\string ;] [\zeropoint]
+\definehspace [\string !] [\zeropoint]
+\definehspace [\string ?] [\zeropoint]
+
+\definehspace [\s!fr] [\string :] [\spaceamount]
+\definehspace [\s!fr] [\string ;] [.16667em]
+\definehspace [\s!fr] [\string !] [.16667em]
+\definehspace [\s!fr] [\string ?] [.16667em]
+
+%D Alternative discretionary handlers:
+
+\definetextmodediscretionary :
+ {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{:}:}
+
+\definetextmodediscretionary ;
+ {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{;};}
+
+\definetextmodediscretionary ?
+ {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{?}?}
+
+\definetextmodediscretionary !
+ {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{!}!}
+
+%D \startbuffer
+%D \mainlanguage[en] \quotation{test \quotation{test} test}\par
+%D \mainlanguage[nl] \quotation{test \quotation{test} test}\par
+%D \mainlanguage[fr] \quotation{test \quotation{test} test}\par
+%D
+%D \mainlanguage[en] \quotation{\quotation{test} test}\par
+%D \mainlanguage[nl] \quotation{\quotation{test} test}\par
+%D \mainlanguage[fr] \quotation{\quotation{test} test}\par
+%D
+%D \mainlanguage[en] |<|test |<|test|>| test|>| \par
+%D \mainlanguage[nl] |<|test |<|test|>| test|>| \par
+%D \mainlanguage[fr] |<|test |<|test|>| test|>| \par
+%D
+%D \mainlanguage[en] |<||<|test|>| test|>| \par
+%D \mainlanguage[nl] |<||<|test|>| test|>| \par
+%D \mainlanguage[fr] |<||<|test|>| test|>| \par
+%D \stopbuffer
+%D
+%D \typebuffer {\getbuffer}
+
+\protect \endinput
diff --git a/tex/context/base/lang-spe.mkii b/tex/context/base/lang-spe.mkii
new file mode 100644
index 000000000..7911b0c95
--- /dev/null
+++ b/tex/context/base/lang-spe.mkii
@@ -0,0 +1,244 @@
+%D \module
+%D [ file=lang-spe,
+%D version=2002.05.07, % 1996.01.25,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Specifics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 code was originally placed in the language
+%D initialization module, but isolating it is clearer. Language
+%D specifics evolved out of user demands for special features,
+%D like the german active quote. After a while I decided to
+%D associate them to languages in a more general way so that we
+%D could associate all kind of things with language switching.
+%D
+%D This is a typical example of functionality that occasionally
+%D gets improved based on user input and experience. Much of the
+%D code is pretty old and could probabbly be done in better ways.
+%D It's probably also the kind of code that has been and will be
+%D written over and over again by \TEX\ users around the world,
+%D so there are probably better implementations of similar
+%D functionality around. Therefore, users are invited to pop in
+%D their own handling as long as it does not interfere with
+%D existing code. Writing the more obscure macros that deal with
+%D this is a good learning experience (catcodes, lccodes, token
+%D lists, expansion, \unknown).
+
+\writestatus{loading}{ConTeXt Language Macros / Specifics}
+
+\unprotect
+
+%D \macros
+%D {everyresetlanguagespecifics,resetlanguagespecifics}
+%D
+%D Cleanup macros.
+
+\newevery \everyresetlanguagespecifics \relax
+
+\def\resetlanguagespecifics
+ {\ifcase\protectionlevel
+ \the\everyresetlanguagespecifics
+ \else % to be translated
+ % \writestatus\m!systems{don't change language in unprotected mode!}%
+ \fi}
+
+\appendtoks
+ \resetlanguagespecifics
+\to \everycleanupfeatures
+
+%D \macros
+%D {startlanguagespecifics,enablelanguagespecifics}
+%D
+%D Each language has its own typographic pecularities. Some of
+%D those can be influenced by parameters, others are handled by
+%D the interface, but as soon as specific commands come into
+%D view we need another mechanism. In the macro that activates
+%D a language, we call \type{\enablelanguagespecifics}. This
+%D macro in return calls for the setup of language specific
+%D macros. Such specifics are defined as:
+%D
+%D \starttyping
+%D \startlanguagespecifics[de]
+%D \installcompoundcharacter "a {\"a}
+%D \installcompoundcharacter "e {\"e}
+%D \installcompoundcharacter "s {\SS}
+%D \stoplanguagespecifics
+%D \stoptyping
+%D
+%D Instead of \type{[du]} we can pass a comma separated
+%D list, like \type{[du,nl]}. Next calls to this macro add the
+%D specifics to the current list.
+%D
+%D Before we actually read the specifics, we first take some
+%D precautions that will prevent spurious spaces to creep into
+%D the list.
+
+% We should use token registers, but alas, we run out of them and
+% \ETEX\ has a bug. Well, let's use a token register now (2006).
+
+\def\startlanguagespecifics% % we use double to
+ {\bgroup
+ \catcode`\^^I=\@@ignore
+ \catcode`\^^M=\@@ignore
+ \catcode`\^^L=\@@ignore
+ \dodoubleempty\dostartlanguagespecifics} % get rid of spaces
+
+%D The main macro looks quite complicated but actually does
+%D nothing special. By embedding \type{\do} we can easily
+%D append to the lists and also execute them at will. Just to
+%D be sure, we check on spurious spaces. The second dummy
+%D argument gobbles spaces.
+
+\def\languageencoding
+ {\ifx\characterencoding\nocharacterencoding \else
+ \characterencoding-%
+ \fi}
+
+\long\def\dostartlanguagespecifics[#1][#2]#3\stoplanguagespecifics
+ {\egroup
+ \processcommalist[#1]{\dosetlanguagespecifics{#3}}}
+
+% \long\def\dosetlanguagespecifics#1#2%
+% {\ifundefined{\??la\languageencoding#2\??la}\forgetlanguagespecifics[#2]\fi
+% % the next line catches the case that specifics are enabled *before* they are defined
+% \expandafter\ifx\csname\??la\languageencoding#2\??la\endcsname\relax\forgetlanguagespecifics[#2]\fi
+% \appendvalue{\??la\languageencoding#2\??la}{#1}%
+% \bgroup
+% \setbox\scratchbox\hbox{\enablelanguagespecifics[#2]}%
+% \ifdim\wd\scratchbox>\zeropoint
+% \showmessage\m!linguals7{\currentencoding-#2,\the\wd\scratchbox\space}\wait
+% \else
+% \showmessage\m!linguals8{\currentencoding-#2}%
+% \fi
+% \egroup
+% \doif{#2}\currentmainlanguage{\enablelanguagespecifics[#2]}}
+
+\def\languagespectag#1{\??la\languageencoding#1\??la}
+
+\long\def\dosetlanguagespecifics#1#2%
+ {\edef\askedlanguagespecificstag{\languagespectag{#2}}%
+ \ifcsname\askedlanguagespecificstag\endcsname \else
+ \expandafter\newtoks\csname\askedlanguagespecificstag\endcsname
+ \fi
+ \csname\askedlanguagespecificstag\endcsname\@EA{\the\csname\askedlanguagespecificstag\endcsname#1}%
+ \bgroup
+ \setbox\scratchbox\hbox{\enablelanguagespecifics[#2]}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \showmessage\m!linguals7{\currentencoding-#2,\the\wd\scratchbox\space}\wait
+ \else
+ \showmessage\m!linguals8{\currentencoding-#2}%
+ \fi
+ \egroup
+ \doif{#2}\currentmainlanguage{\enablelanguagespecifics[#2]}}
+
+\def\forgetlanguagespecifics[#1]%
+ {\csname\languagespectag{#1}\endcsname\emptytoks}
+
+%D Enabling them is rather straightforward. We only have to
+%D define \type{\do} in such a way that \type{{ }} is removed
+%D and the language key is gobbled.
+
+% \def\enablelanguagespecifics[#1]%
+% {\the\executeifdefined{\??la
+% \@EA\ifx\csname\??la#1\c!default\endcsname\relax
+% \languageencoding
+% \else
+% \csname\??la#1\c!default\endcsname
+% \fi
+% \??la}\emptytoks
+% \the\executeifdefined{\??la#1\??la}\emptytoks
+% \the\executeifdefined{\??la\languageencoding#1\??la}\emptytoks} % dup ?
+
+\def\enablelanguagespecifics[#1]%
+ {\edef\askedlanguagespecificslanguage{\defaultlanguage{#1}}%
+ \ifcsname\??la\askedlanguagespecificslanguage\??la\endcsname
+ \the\csname\??la\askedlanguagespecificslanguage\??la\endcsname
+ \fi
+ \ifx\languageencoding\empty\else
+ \ifcsname\??la\languageencoding\askedlanguagespecificslanguage\??la\endcsname
+ \the\csname\??la\languageencoding\askedlanguagespecificslanguage\??la\endcsname
+ \fi
+ \fi}
+
+%D \macros
+%D {deactivatelanguagespecific}
+%D
+%D The next code makes it possible to disable the specifics.
+
+% \def\deactivatelanguagespecific#1%
+% {\ifundefined{l g s \string#1}%
+% \letgvalueempty{l g s \string#1}% signal to prevent dup def
+% \bgroup
+% \catcode`#1=\@@active
+% \uccode`~=`#1
+% \uppercase{\doglobal\appendtoks\dodeactivatetoken{~}\to\everyresetlanguagespecifics}%
+% \egroup
+% \expanded{\doglobal\noexpand\appendtoks{#1}{\the\catcode`#1}}\to\everyresetlanguagespecifics
+% \fi}
+
+% \def\dodeactivatetoken#1#2#3% test needed to avoid clash with \unprotect
+% {\def#1{#2}\ifnum\catcode`#2=\@@active\catcode`#2=#3\relax\fi}
+
+%D We cannot hook this into the installer since language
+%D specifics can be anything. So far, we have the following
+%D potentially active characters.
+
+%D Beware, this should happen under an unprotected regime;
+%D thanks to Giuseppe Oblomov Bilotta, who first noticed
+%D that something was wrong.
+
+\protect
+
+% \deactivatelanguagespecific "
+% \deactivatelanguagespecific /
+% \deactivatelanguagespecific :
+% \deactivatelanguagespecific ;
+% \deactivatelanguagespecific ?
+% \deactivatelanguagespecific !
+
+\unprotect
+
+% yes or no (taco wins: no)
+
+% \startlanguagespecifics[nl,cs,sk,fr]
+% \lccode`\'=`\'
+% \stoplanguagespecifics
+
+%D \macros
+%D {ordinaldaynumber, highordinalstr, ordinalstr}
+%D
+%D Efficient general ordinal number converters are sometimes
+%D difficult to implement. Fortunately dates never exceed the
+%D number~31.
+
+\ifx\high \undefined \let\high \firstofoneargument \fi % todo
+\ifx\notsmallcapped\undefined \let\notsmallcapped\firstofoneargument \fi % todo
+
+\def\highordinalstr#1{\high{\notsmallcapped{#1}}}
+\def\ordinalstr #1{\notsmallcapped{#1}}
+
+\def\ordinaldaynumber#1% \strippedcsname\ordinaldaynumber
+ {\expanded{\executeifdefined{\currentlanguage ordinaldaynumber}%
+ \noexpand\firstofoneargument{\number#1}}}
+
+%D Language specific converters have definitions like:
+%D
+%D \starttyping
+%D \def\enordinaldaynumber#1{...}
+%D \stoptyping
+%D
+%D Examples can be found in the other \type {lang} modules.
+
+% \ifprocessingXML is a nasty dependency
+
+\appendtoks
+ \ifprocessingXML \else \resetlanguagespecifics \fi
+\to \everylanguage
+
+\protect \endinput
diff --git a/tex/context/base/lang-ura.tex b/tex/context/base/lang-ura.tex
new file mode 100644
index 000000000..a2bcd3d2b
--- /dev/null
+++ b/tex/context/base/lang-ura.tex
@@ -0,0 +1,158 @@
+%D \module
+%D [ file=lang-sla,
+%D version=1997.09.03,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Uralic Languages,
+%D author=Hans Hagen / Tobias Burnus,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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: replace \'.. by \namedglyph
+
+\writestatus{loading}{ConTeXt Language Macros / Uralic Languages}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+%D
+%D \starttabulate[|lB|l|]
+%D \NC Finnish \NC \NC \NR
+%D \NC Hungarian \NC Balazs Nagy \NC \NR
+%D \stoptabulate
+
+% Cheremiss, Estonian, Finnish, Karelian, Laap, Mordvinian,
+% Permian tongues, Hungarian, Ostyak, Vogul, Samoyed
+
+\unprotect
+
+\installlanguage
+ [\s!fi]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\upperleftdoublesixquote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,\ ,\v!month,\ ,\v!day}]
+
+\installlanguage
+ [\s!hu]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!year,.,\ ,\v!month,\ ,\v!day,.},
+ \s!mapping=ec,
+ \s!encoding=ec]
+
+\installlanguage [finish] [\s!fi]
+\installlanguage [hungarian] [\s!hu]
+
+\setupheadtext [\s!fi] [\v!content=Sis\"allys]
+\setupheadtext [\s!fi] [\v!tables=Taulukkoj]
+\setupheadtext [\s!fi] [\v!figures=Kuvi]
+\setupheadtext [\s!fi] [\v!graphics=Grafiikkaoi]
+\setupheadtext [\s!fi] [\v!intermezzi=Intermezzos]
+\setupheadtext [\s!fi] [\v!index=Indeksiluku]
+\setupheadtext [\s!fi] [\v!abbreviations=Lyhennyksi]
+\setupheadtext [\s!fi] [\v!logos=Vertauskuva]
+\setupheadtext [\s!fi] [\v!units=Yksik\"ot]
+
+\setupheadtext [\s!hu] [\v!content=Tartalom]
+\setupheadtext [\s!hu] [\v!tables=T\'abl\'azatok]
+\setupheadtext [\s!hu] [\v!figures=\'Abr\'ak]
+\setupheadtext [\s!hu] [\v!graphics=Grafik\'ak]
+\setupheadtext [\s!hu] [\v!intermezzi=Intermezzok]
+\setupheadtext [\s!hu] [\v!index=Index]
+\setupheadtext [\s!hu] [\v!abbreviations=R\"ovid\'it\'esek]
+\setupheadtext [\s!hu] [\v!logos=Fejl\'ecek]
+\setupheadtext [\s!hu] [\v!units=M\'ert\'ekegys\'egek]
+
+\setuplabeltext [\s!fi] [\v!table=Taulukko ]
+\setuplabeltext [\s!fi] [\v!figure=Kuva ]
+\setuplabeltext [\s!fi] [\v!intermezzo=Intermezzo ]
+\setuplabeltext [\s!fi] [\v!graphic=Grafiikka ]
+\setuplabeltext [\s!fi] [\v!chapter=]
+\setuplabeltext [\s!fi] [\v!section=]
+\setuplabeltext [\s!fi] [\v!subsection=]
+\setuplabeltext [\s!fi] [\v!subsubsection=]
+\setuplabeltext [\s!fi] [\v!subsubsubsection=]
+\setuplabeltext [\s!fi] [\v!appendix=]
+\setuplabeltext [\s!fi] [\v!part=Osa ]
+\setuplabeltext [\s!fi] [\v!line=rivi ]
+\setuplabeltext [\s!fi] [\v!lines=rivie ]
+
+\setuplabeltext [\s!hu] [\v!table={,.~t\'abl\'azat:}]
+\setuplabeltext [\s!hu] [\v!figure={,.~\'abra:}]
+\setuplabeltext [\s!hu] [\v!intermezzo={,.~intermezzo:}]
+\setuplabeltext [\s!hu] [\v!graphic={,.~k\'ep:}]
+\setuplabeltext [\s!hu] [\v!chapter={,.~fejezet:}]
+\setuplabeltext [\s!hu] [\v!section={,.}]
+\setuplabeltext [\s!hu] [\v!subsection={,.}]
+\setuplabeltext [\s!hu] [\v!subsubsection={,.}]
+\setuplabeltext [\s!hu] [\v!subsubsubsection={,.}]
+\setuplabeltext [\s!hu] [\v!appendix=]
+\setuplabeltext [\s!hu] [\v!part={,.~r\'esz:}]
+\setuplabeltext [\s!hu] [\v!line={,.~sor:}]
+\setuplabeltext [\s!hu] [\v!lines=sorok]
+
+\setuplabeltext [\s!fi] [\v!january=tammikuu]
+\setuplabeltext [\s!fi] [\v!february=helmikuu]
+\setuplabeltext [\s!fi] [\v!march=maaliskuu]
+\setuplabeltext [\s!fi] [\v!april=huhtikuu]
+\setuplabeltext [\s!fi] [\v!may=toukokuu]
+\setuplabeltext [\s!fi] [\v!june=kes\"akuu]
+\setuplabeltext [\s!fi] [\v!july=hein\"akuu]
+\setuplabeltext [\s!fi] [\v!august=elokuu]
+\setuplabeltext [\s!fi] [\v!september=syyskuu]
+\setuplabeltext [\s!fi] [\v!october=lokakuu]
+\setuplabeltext [\s!fi] [\v!november=marraskuu]
+\setuplabeltext [\s!fi] [\v!december=joulukuu]
+
+\setuplabeltext [\s!hu] [\v!january=janu\'ar]
+\setuplabeltext [\s!hu] [\v!february=febru\'ar]
+\setuplabeltext [\s!hu] [\v!march=m\'arcius]
+\setuplabeltext [\s!hu] [\v!april=\'aprilis]
+\setuplabeltext [\s!hu] [\v!may=m\'ajus]
+\setuplabeltext [\s!hu] [\v!june=j\'unius]
+\setuplabeltext [\s!hu] [\v!july=j\'ulius]
+\setuplabeltext [\s!hu] [\v!august=augusztus]
+\setuplabeltext [\s!hu] [\v!september=szeptember]
+\setuplabeltext [\s!hu] [\v!october=okt\'ober]
+\setuplabeltext [\s!hu] [\v!november=november]
+\setuplabeltext [\s!hu] [\v!december=december]
+
+\setuplabeltext [\s!fi] [\v!sunday=sunnuntai]
+\setuplabeltext [\s!fi] [\v!monday=maanantai]
+\setuplabeltext [\s!fi] [\v!tuesday=tiistai]
+\setuplabeltext [\s!fi] [\v!wednesday=keskiviikko]
+\setuplabeltext [\s!fi] [\v!thursday=torstai]
+\setuplabeltext [\s!fi] [\v!friday=perjantai]
+\setuplabeltext [\s!fi] [\v!saturday=lauantai]
+
+\setuplabeltext [\s!hu] [\v!sunday=vas\'arnap]
+\setuplabeltext [\s!hu] [\v!monday=h\'etf\H{o}]
+\setuplabeltext [\s!hu] [\v!tuesday=kedd]
+\setuplabeltext [\s!hu] [\v!wednesday=szerda]
+\setuplabeltext [\s!hu] [\v!thursday=cs\"ut\"ort\"ok]
+\setuplabeltext [\s!hu] [\v!friday=p\'entek]
+\setuplabeltext [\s!hu] [\v!saturday=szombat]
+
+%D \ShowAllLanguageValues [\s!fi] [finnish] {Finnish} {phone}
+%D \ShowAllLanguageValues [\s!hu] [hungarian] {Hungarian} {rhapsody}
+
+\protect \endinput
diff --git a/tex/context/base/lang-url.lua b/tex/context/base/lang-url.lua
new file mode 100644
index 000000000..b0a71ec67
--- /dev/null
+++ b/tex/context/base/lang-url.lua
@@ -0,0 +1,101 @@
+if not modules then modules = { } end modules ['lang-url'] = {
+ version = 1.001,
+ comment = "companion to lang-url.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+
+local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
+local utfbyte, utfgsub = utf.byte, utf.gsub
+
+local ctxcatcodes, texsprint = tex.ctxcatcodes, tex.sprint
+
+commands = commands or { }
+
+--[[
+
Hyphenating 's is somewhat tricky and a matter of taste. I did
+consider using a dedicated hyphenation pattern or dealing with it by node
+parsing, but the following solution suits as well. After all, we're mostly
+dealing with characters.
+]]--
+
+commands.hyphenatedurl = commands.hyphenatedurl or { }
+
+local hyphenatedurl = commands.hyphenatedurl
+
+hyphenatedurl.characters = {
+ ["!"] = 1,
+ ["\""] = 1,
+ ["#"] = 1,
+ ["$"] = 1,
+ ["%"] = 1,
+ ["&"] = 1,
+ ["("] = 1,
+ ["*"] = 1,
+ ["+"] = 1,
+ [","] = 1,
+ ["-"] = 1,
+ ["."] = 1,
+ ["/"] = 1,
+ [":"] = 1,
+ [";"] = 1,
+ ["<"] = 1,
+ ["="] = 1,
+ [">"] = 1,
+ ["?"] = 1,
+ ["@"] = 1,
+ ["["] = 1,
+ ["\\"] = 1,
+ ["^"] = 1,
+ ["_"] = 1,
+ ["`"] = 1,
+ ["{"] = 1,
+ ["|"] = 1,
+ ["~"] = 1,
+
+ ["'"] = 2,
+ [")"] = 2,
+ ["]"] = 2,
+ ["}"] = 2
+}
+
+hyphenatedurl.lefthyphenmin = 2
+hyphenatedurl.righthyphenmin = 3
+hyphenatedurl.discretionary = nil
+
+local chars = hyphenatedurl.characters
+
+function hyphenatedurl.action(str, left, right, disc)
+ local n = 0
+ local b = math.max( left or hyphenatedurl.lefthyphenmin, 2)
+ local e = math.min(#str-(right or hyphenatedurl.righthyphenmin)+2,#str)
+ local d = disc or hyphenatedurl.discretionary
+ for s in utfcharacters(str) do
+ n = n + 1
+ if s == d then
+ texsprint(ctxcatcodes,"\\d{",utfbyte(s),"}")
+ else
+ local c = chars[s]
+ if not c or n<=b or n>=e then
+ texsprint(ctxcatcodes,"\\n{",utfbyte(s),"}")
+ elseif c == 1 then
+ texsprint(ctxcatcodes,"\\b{",utfbyte(s),"}")
+ elseif c == 2 then
+ texsprint(ctxcatcodes,"\\a{",utfbyte(s),"}")
+ end
+ end
+ end
+end
+
+-- todo, no interface in mkiv yet
+
+function hyphenatedurl.setcharacters(str,value) -- 1, 2 == before, after
+ for s in utfcharacters(str) do
+ chars[s] = value or 1
+ end
+end
+
+-- .hyphenatedurl.setcharacters("')]}",2)
diff --git a/tex/context/base/lang-url.mkii b/tex/context/base/lang-url.mkii
new file mode 100644
index 000000000..fdf530b45
--- /dev/null
+++ b/tex/context/base/lang-url.mkii
@@ -0,0 +1,306 @@
+%D \module
+%D [ file=lang-url,
+%D version=2008.01.22, % used to be lang-mis
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Language Options,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+%D This is rather old code. The following solution was used
+%D for a long time and is kind of built-up over the years.
+
+\ifx\\\undefined \let\\\crlf \fi
+
+%D \macros
+%D {hyphenatedurl}
+%D
+%D For those who want to put full \URL's in a text, we offer
+%D
+%D \startbuffer
+%D \hyphenatedurl{http://optimist.optimist/optimist/optimist.optimist#optimist}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D which breaks at the appropriate places. Watch the \type{#}
+%D hack.
+%D
+%D When passed as argument, like in \type {\goto}, one needs
+%D to substitute a \type {\\} for each \type{#}.
+%D
+%D \startbuffer
+%D \hyphenatedurl{http://this.is.a.rather/strange/reference#indeed}
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\ifx\urlsplitmode\undefined \chardef\urlsplitmode\plusone \fi
+
+% 0 => don't split
+% 1 => . : na, rest voor
+% 2 => alles na
+% 3 => alles voor
+
+% \bgroup \catcode`\~=\active \catcode`\/=\active
+%
+% \unexpanded\gdef\hyphenatedurl#1% {}{} handles accents
+% {\bgroup
+% \ifnum\hyphenpenalty<10000 \else
+% \def\discretionary##1##2##3{##1\allowbreak##2}%
+% \fi
+% \obeyhyphens
+% \def\splitbefore##1%
+% {\setbox\scratchbox=\hbox{##1{}{}}%
+% \ifcase\urlsplitmode
+% \box\scratchbox
+% \or
+% \postwordbreak\box\scratchbox\prewordbreak
+% \or
+% \prewordbreak\discretionary{\box\scratchbox}{}{\box\scratchbox}\prewordbreak
+% \else
+% \postwordbreak\box\scratchbox\prewordbreak
+% \fi}%
+% \def\splitafter##1%
+% {\ifcase\urlsplitmode
+% ##1{}{}%
+% \or
+% \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak
+% \or
+% \prewordbreak\discretionary{##1{}{}}{}{##1{}{}}\prewordbreak
+% \else
+% \prewordbreak\discretionary{}{##1{}{}}{##1{}{}}\prewordbreak
+% \fi}%
+% \def\splitanyway##1%
+% {\prewordbreak##1\prewordbreak}%
+% \def\flushurl%
+% {\savedurl\let\savedurl\empty}%
+% \def\\%
+% {\spliturl\#}%
+% \let\~=\lettertilde\let~=\~%
+% \let\/=\letterslash\let/=\/%
+% \let\savedurl\empty
+% \scratchcounter\zerocount % used for hyphenmethod
+% \handletokens#1\with\scanurl\savedurl
+% \egroup}
+%
+% \egroup
+
+% \chardef\urlhyphenmethod=0
+
+% \def\scanurl#1%
+% {\advance\scratchcounter\plusone
+% \ifx#1\blankspace
+% \flushurl\splitanyway\normalspace
+% \else\ifx#1\ %
+% \flushurl\splitanyway\normalspace
+% \else\ifx#1\space
+% \flushurl\splitanyway\normalspace
+% \else\ifx#1\~%
+% \flushurl\splitbefore\~%
+% \else\ifx#1\#%
+% \flushurl\splitbefore\#%
+% \else\ifx#1\&%
+% \flushurl\splitbefore\&%
+% \else\ifx#1\%%
+% \flushurl\splitbefore\%%
+% \else\ifx#1\_%
+% \flushurl\splitbefore\_%
+% \else\if\noexpand#1\relax
+% #1%
+% \else\ifnum\catcode`#1=8
+% \flushurl\splitbefore\_%
+% \else\ifnum\catcode`#1=6
+% \flushurl\splitbefore\#%
+% \else\ifnum\catcode`#1=4
+% \flushurl\splitbefore\&%
+% \else\expandafter\if\string#1\lettertilde
+% \flushurl\splitbefore\~%
+% \else\expandafter\if\string#1\letterpercent
+% \flushurl\splitbefore\%%
+% \else\expandafter\if\string#1\letterunderscore
+% \flushurl\splitbefore\_%
+% \else\expandafter\if\string#1\letterquestionmark
+% \flushurl\splitafter\letterquestionmark
+% \else\expandafter\if\string#1\letterat
+% \flushurl\splitafter\letterat
+% \else\expandafter\if\string#1\letterslash
+% \edef\savedurl{\savedurl\letterslash}%
+% \else\expandafter\if\string#1+%
+% \flushurl\splitafter+%
+% \else\expandafter\if\string#1:%
+% \flushurl\splitafter:%
+% \else\expandafter\if\string#1.%
+% \flushurl\splitafter.%
+% \else\expandafter\if\string#1(%
+% \flushurl\splitbefore(%
+% \else\expandafter\if\string#1)%
+% \flushurl\splitafter)%
+% \else
+% \ifx\savedurl\empty\else
+% \splitbefore\savedurl
+% \let\savedurl\empty
+% \fi
+% \ifcase\urlhyphenmethod
+% \string#1%
+% \else
+% \ifnum\scratchcounter>\plusthree % so, \http: will not break
+% \edef\savedurl{\string#1}%
+% \else
+% \string#1%
+% \fi
+% \fi
+% \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+
+%D The following approach takes more resources but is cleaner (after all, we now
+%D have huge \TEX's. It's is basically a \TEX\ version of the \MKIV\ variant.
+
+\newtoks\everyhyphenatedurl
+
+\appendtoks
+ \let\&\letterampersand
+ \let\#\letterhash
+ \let\~\lettertilde
+ \let\\\letterbackslash
+ \let\$\letterdollar
+ \let\^\letterhat
+ \let\_\letterunderscore
+ \let\{\letterleftbrace
+ \let\}\letterrightbrace
+ \let\|\letterbar
+ \let~=\lettertilde
+ \let|=\letterbar
+\to \everyhyphenatedurl
+
+\def\hyphenatedurlseparator{} % \periodcentered
+
+\def\dohyphenatedurlnormal#1{\char#1\relax}%
+\def\dohyphenatedurlafter #1{\char#1\discretionary{}{\hyphenatedurlseparator}{}}%
+\def\dohyphenatedurlbefore#1{\discretionary{\hyphenatedurlseparator}{}{}\char#1\relax}%
+
+% 0=normal 1=before 2=after
+
+\def\sethyphenatedurlnormal#1{\expandafter\chardef\csname url @ #1\endcsname\zerocount}
+\def\sethyphenatedurlbefore#1{\expandafter\chardef\csname url @ #1\endcsname\plusone }
+\def\sethyphenatedurlafter #1{\expandafter\chardef\csname url @ #1\endcsname\plustwo }
+
+\sethyphenatedurlbefore !
+\sethyphenatedurlbefore "
+\sethyphenatedurlbefore \letterhash
+\sethyphenatedurlbefore \letterdollar
+\sethyphenatedurlbefore \letterpercent
+\sethyphenatedurlbefore \letterampersand
+\sethyphenatedurlbefore (
+\sethyphenatedurlbefore *
+\sethyphenatedurlbefore +
+\sethyphenatedurlbefore ,
+\sethyphenatedurlbefore -
+\sethyphenatedurlbefore .
+\sethyphenatedurlbefore /
+\sethyphenatedurlbefore :
+\sethyphenatedurlbefore ;
+\sethyphenatedurlbefore <
+\sethyphenatedurlbefore =
+\sethyphenatedurlbefore >
+\sethyphenatedurlbefore ?
+\sethyphenatedurlbefore @
+\sethyphenatedurlbefore [
+\sethyphenatedurlbefore \letterbackslash
+\sethyphenatedurlbefore ^
+\sethyphenatedurlbefore _
+\sethyphenatedurlbefore `
+\sethyphenatedurlbefore \letteropenbrace
+\sethyphenatedurlbefore \letterbar
+\sethyphenatedurlbefore \lettertilde
+
+\sethyphenatedurlafter '
+\sethyphenatedurlafter )
+\sethyphenatedurlafter ]
+\sethyphenatedurlafter \letterclosebrace
+
+\unexpanded \def\hyphenatedurl#1%
+ {\dontleavehmode
+ \begingroup
+ \the\everyhyphenatedurl
+ \edef\ascii{#1}%
+ \expanded{\handletokens{\detokenize\expandafter{\ascii}}}\with\dohyphenatedurl
+ \endgroup}
+
+\def\dohyphenatedurl#1%
+ {\ifcase\executeifdefined{url @ #1}\zerocount\relax
+ \expandafter\dohyphenatedurlnormal
+ \or
+ \expandafter\dohyphenatedurlbefore
+ \or
+ \expandafter\dohyphenatedurlafter
+ \fi{\number`#1}}
+
+% maybe ... to be finished
+%
+% \def\hyphenatedstring#1%
+% {\bgroup
+% \nohyphens
+% \def\next##1{##1\doif{##1}{-}{\allowbreak}}%
+% \handletokens#1\with\next
+% \egroup}
+%
+% {\hsize1cm\hyphenatedstring{ABXXXXXXXXXXC-12345-12345}}
+
+%D \macros
+%D {hyphenatedfilename}
+%D
+%D For the moment we treat filenames in a similar way,
+%D
+%D \starttyping
+%D \hyphenatedfilename{here/there/filename.suffix}
+%D \stoptyping
+
+\ifx\hyphenatedfilename\undefined \let\hyphenatedfilename\hyphenatedurl \fi
+
+% \def\test#1%
+% {\dontleavehmode
+% \begingroup
+% \tttf
+% \hyphenatedurl {%
+% \letterampersand #1\letterampersand #1\letterampersand #1\letterampersand #1\letterampersand
+% \letterhash #1\letterhash #1\letterpercent #1\letterslash #1\letterampersand
+% }%
+% \endgroup}
+
+% \dorecurse{100}{\test{a} \test{ab} \test{abc} \test{abcd} \test{abcde} \test{abcdef}}
+
+\protect \endinput
+
+% \bgroup
+
+% \gdef\lettercolon{:}
+
+% \catcode`\:=\active
+% \catcode`\^=\active
+% \catcode`\/=\active
+% \catcode`\~=\active
+
+% \gdef\theurlcolon {\nobreak\hbox{\lettercolon}\allowbreak}
+% \gdef\theurlslash#1{\nobreak\hbox{\letterslash}\ifx#1\relax\else\ifnum`/=\expandafter`\string#1\else\allowbreak\fi#1\fi}
+% \gdef\theurlhat {\allowbreak\hbox{\letterhat}\nobreak}
+% \gdef\theurltilde {\allowbreak\hbox{\lettertilde}\nobreak}
+
+% \gdef\ForMojcaWhoLikesHacks#1%
+% {\dontleavehmode
+% \begingroup
+% \mathcode`\:="8000 \let:\theurlcolon
+% \mathcode`\^="8000 \let^\theurlhat
+% \mathcode`\/="8000 \let/\theurlslash
+% \mathcode`\~="8000 \let~\theurltilde
+% \everymath\emptytoks
+% \mathsurround\zeropoint$\tf#1\relax$%
+% \endgroup}
+% \egroup
+
+% \hsize 1mm \ForMojcaWhoLikesHacks{http://www.sil.org//silesr/}
diff --git a/tex/context/base/lang-url.mkiv b/tex/context/base/lang-url.mkiv
new file mode 100644
index 000000000..0f6b23d05
--- /dev/null
+++ b/tex/context/base/lang-url.mkiv
@@ -0,0 +1,117 @@
+%D \module
+%D [ file=lang-url,
+%D version=2008.01.22, % used to be lang-mis
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Language Options,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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{lang-url}{1.001}
+
+\unprotect
+
+%D \macros
+%D {hyphenatedurl}
+%D
+%D For those who want to put full \URL's in a text, we offer
+%D
+%D \startbuffer
+%D \hyphenatedurl{http://optimist.optimist/optimist/optimist.optimist#optimist}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D which breaks at the appropriate places. Watch the \type{#}
+%D hack.
+%D
+%D When passed as argument, like in \type {\goto}, one needs
+%D to substitute a \type {\\} for each \type{#}.
+%D
+%D \startbuffer
+%D \hyphenatedurl{http://this.is.a.rather/strange/reference#indeed}
+%D \stopbuffer
+%D
+%D \typebuffer
+
+\ifx\urlsplitmode\undefined \chardef\urlsplitmode\zerocount \fi % not supported in mkiv
+
+\newtoks\everyhyphenatedurl
+
+\appendtoks
+ \let\&\letterampersand
+ \let\#\letterhash
+ \let\~\lettertilde
+ \let\\\letterbackslash
+ \let\$\letterdollar
+ \let\^\letterhat
+ \let\_\letterunderscore
+ \let\{\letterleftbrace
+ \let\}\letterrightbrace
+ \let\|\letterbar
+ \let~=\lettertilde
+ \let|=\letterbar
+\to \everyhyphenatedurl
+
+\def\hyphenatedurlseparator{} % \periodcentered
+
+\def\dohyphenatedurlafter #1{\char#1\discretionary{}{\hyphenatedurlseparator}{}}%
+\def\dohyphenatedurlbefore#1{\discretionary{\hyphenatedurlseparator}{}{}\char#1\relax}%
+\def\dohyphenatedurlnormal#1{\char#1\relax}%
+\def\dohyphenatedurldisc #1{\discretionary{}{}{}}
+
+\def\sethyphenatedurlnormal #1{\ctxlua{commands.hyphenatedurl.setcharacters(\!!bs#1\!!es,0)}}
+\def\sethyphenatedurlbefore #1{\ctxlua{commands.hyphenatedurl.setcharacters(\!!bs#1\!!es,1)}}
+\def\sethyphenatedurlafter #1{\ctxlua{commands.hyphenatedurl.setcharacters(\!!bs#1\!!es,2)}}
+
+\def\hyphenatedurldiscretionary{}
+
+% \sethyphenatedurlafter{ABCDEF}
+
+\chardef\hyphenatedurllefthyphenmin = 3
+\chardef\hyphenatedurlrighthyphenmin = 3
+
+\unexpanded \def\hyphenatedurl#1%
+ {\dontleavehmode
+ \begingroup
+ \the\everyhyphenatedurl
+ \let\n\dohyphenatedurlnormal
+ \let\b\dohyphenatedurlbefore
+ \let\a\dohyphenatedurlafter
+ \let\d\dohyphenatedurldisc
+ \normalexpanded{\noexpand\ctxlua{commands.hyphenatedurl.action(
+ \!!bs\noexpand\detokenize{#1}\!!es,
+ \number\hyphenatedurllefthyphenmin,
+ \number\hyphenatedurlrighthyphenmin,
+ "\hyphenatedurldiscretionary"
+ )}}%
+ \endgroup}
+
+%D \macros
+%D {hyphenatedfilename}
+%D
+%D For the moment we treat filenames in a similar way,
+%D
+%D \starttyping
+%D \hyphenatedfilename{here/there/filename.suffix}
+%D \stoptyping
+
+\ifx\hyphenatedfilename\undefined \let\hyphenatedfilename\hyphenatedurl \fi
+
+% \def\test#1%
+% {\dontleavehmode
+% \begingroup
+% \tttf
+% \hyphenatedurl {%
+% \letterampersand #1\letterampersand #1\letterampersand #1\letterampersand #1\letterampersand
+% \letterhash #1\letterhash #1\letterpercent #1\letterslash #1\letterampersand
+% }%
+% \endgroup}
+
+% \dorecurse{100}{\test{a} \test{ab} \test{abc} \test{abcd} \test{abcde} \test{abcdef}}
+
+\protect \endinput
diff --git a/tex/context/base/lang-vn.tex b/tex/context/base/lang-vn.tex
new file mode 100644
index 000000000..27d2a48a1
--- /dev/null
+++ b/tex/context/base/lang-vn.tex
@@ -0,0 +1,92 @@
+%D \module
+%D [ file=lang-vn,
+%D version=2004.11.22, % 1999.12.12,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Vietnamese,
+%D author={Han The Thanh \& Adam Lindsay \& Hans Hagen},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 / Vietnamese Language}
+
+%D The framework of this module is set up by Hans Hagen while
+%D many of the first translations were done by Tobias. Later
+%D on, corrections were made by users. If you have suggestions,
+%D or feel that your name missing here, don't hesitate to send
+%D us an email.
+%D
+%D \starttabulate[|lB|l|]
+%D \NC Vietnamese \NC \THANH\ \NC \NR
+%D \stoptabulate
+
+\unprotect
+
+\installlanguage
+ [\s!vi]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=---,
+ \c!rightsentence=---,
+ \c!leftsubsentence=---,
+ \c!rightsubsentence=---,
+ \c!leftquote=\quoteleft,
+ \c!rightquote=\quoteright,
+ \c!leftquotation=\quotedblleft,
+ \c!rightquotation=\quotedblright,
+ \c!date={{ },dd,{/},mm,{/},yy},
+ \s!mapping=t5,
+ \s!encoding=t5]
+
+\installlanguage [vietnamese] [\s!vi]
+
+\setupheadtext [\s!vi] [\v!content=M\udotbelow c l\udotbelow c]
+\setupheadtext [\s!vi] [\v!tables=Danh s\aacute ch b\ahook ng]
+\setupheadtext [\s!vi] [\v!figures=Danh s\aacute ch h\igrave nh v\etilde]
+\setupheadtext [\s!vi] [\v!graphics=\Dstroke\ocircumflexgrave\ th\idotbelow]
+\setupheadtext [\s!vi] [\v!intermezzi=Intermezzos]
+\setupheadtext [\s!vi] [\v!index=Ch\ihook\ s\ocircumflexacute]
+\setupheadtext [\s!vi] [\v!abbreviations=Ch\uhorntilde\ vi\ecircumflexacute t t\abreveacute t]
+\setupheadtext [\s!vi] [\v!logos=Bi\ecircumflexhook u t\uhorn \ohorndotbelow ng]
+\setupheadtext [\s!vi] [\v!units=\Dstroke\ohorn n v\idotbelow]
+
+\setuplabeltext [\s!vi] [\v!table=B\ahook ng ]
+\setuplabeltext [\s!vi] [\v!figure=H\igrave nh ]
+\setuplabeltext [\s!vi] [\v!intermezzo=intermezzo]
+\setuplabeltext [\s!vi] [\v!graphic=\Dstroke\ocircumflexgrave\ th\idotbelow]
+\setuplabeltext [\s!vi] [\v!chapter=Ch\uhorn \ohorn ng ]
+\setuplabeltext [\s!vi] [\v!section=] % not set
+\setuplabeltext [\s!vi] [\v!subsection=] % not set
+\setuplabeltext [\s!vi] [\v!subsubsection=] % not set
+\setuplabeltext [\s!vi] [\v!subsubsubsection=] % not set
+\setuplabeltext [\s!vi] [\v!appendix=] % not set
+\setuplabeltext [\s!vi] [\v!part=Ph\acircumflexgrave n ]
+\setuplabeltext [\s!vi] [\v!line=d\ograve ng ]
+\setuplabeltext [\s!vi] [\v!lines=d\ograve ng ]
+
+\setuplabeltext [\s!vi] [\v!sunday=ch\uhook\ nh\acircumflexdotbelow t]
+\setuplabeltext [\s!vi] [\v!monday=th\uhornacute\ hai]
+\setuplabeltext [\s!vi] [\v!tuesday=th\uhornacute\ ba]
+\setuplabeltext [\s!vi] [\v!wednesday=th\uhornacute\ t\uhorn]
+\setuplabeltext [\s!vi] [\v!thursday=th\uhornacute\ n\abreve m]
+\setuplabeltext [\s!vi] [\v!friday=th\uhornacute\ s\aacute u]
+\setuplabeltext [\s!vi] [\v!saturday=th\uhornacute\ b\ahook y]
+
+\setuplabeltext [\s!vi] [\v!january=th\aacute ng gi\ecircumflex ng]
+\setuplabeltext [\s!vi] [\v!february=th\aacute ng hai]
+\setuplabeltext [\s!vi] [\v!march=th\aacute ng ba]
+\setuplabeltext [\s!vi] [\v!april=th\aacute ng t\uhorn]
+\setuplabeltext [\s!vi] [\v!may=th\aacute ng n\abreve m]
+\setuplabeltext [\s!vi] [\v!june=th\aacute ng s\aacute u]
+\setuplabeltext [\s!vi] [\v!july=th\aacute ng b\ahook y]
+\setuplabeltext [\s!vi] [\v!august=th\aacute ng t\aacute m]
+\setuplabeltext [\s!vi] [\v!september=th\aacute ng ch\iacute n]
+\setuplabeltext [\s!vi] [\v!october=th\aacute ng m\uhorn\ohorngrave i]
+\setuplabeltext [\s!vi] [\v!november=th\aacute ng m\uhorn\ohorngrave i m\ocircumflexdotbelow t]
+\setuplabeltext [\s!vi] [\v!december=th\aacute ng m\uhorn\ohorngrave i hai]
+
+%D \ShowAllLanguageValues [\s!vi] [vietnamese] {Vietnamese} {water||puppets}
+
+\protect \endinput
diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua
new file mode 100644
index 000000000..095e44443
--- /dev/null
+++ b/tex/context/base/lang-wrd.lua
@@ -0,0 +1,225 @@
+if not modules then modules = { } end modules ['lang-ini'] = {
+ version = 1.001,
+ comment = "companion to lang-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+local lower, utfchar = string.lower, utf.char
+local lpegmatch = lpeg.match
+
+languages.words = languages.words or { }
+
+local words = languages.words
+
+words.data = words.data or { }
+words.enables = false
+words.threshold = 4
+
+local set_attribute = node.set_attribute
+local unset_attribute = node.unset_attribute
+local traverse_nodes = node.traverse
+local node_id = node.id
+local wordsdata = words.data
+local chardata = characters.data
+
+local glyph_node = node_id('glyph')
+local disc_node = node_id('disc')
+local kern_node = node_id('kern')
+
+words.colors = {
+ ["known"] = "green",
+ ["unknown"] = "red",
+}
+
+local spacing = lpeg.S(" \n\r\t")
+local markup = lpeg.S("-=")
+local lbrace = lpeg.P("{")
+local rbrace = lpeg.P("}")
+local disc = (lbrace * (1-rbrace)^0 * rbrace)^1 -- or just 3 times, time this
+local word = lpeg.Cs((markup/"" + disc/"" + (1-spacing))^1)
+
+local loaded = { } -- we share lists
+
+function words.load(tag,filename)
+ local fullname = resolvers.find_file(filename,'other text file') or ""
+ if fullname ~= "" then
+ statistics.starttiming(languages)
+ local list = loaded[fullname]
+ if not list then
+ list = wordsdata[tag] or { }
+ local parser = (spacing + word/function(s) list[s] = true end)^0
+ lpegmatch(parser,io.loaddata(fullname) or "")
+ loaded[fullname] = list
+ end
+ wordsdata[tag] = list
+ statistics.stoptiming(languages)
+ else
+ logs.report("languages","missing words file '%s'",filename)
+ end
+end
+
+function words.found(id, str)
+ local tag = languages.numbers[id]
+ if tag then
+ local data = wordsdata[tag]
+ return data and (data[str] or data[lower(str)])
+ else
+ return false
+ end
+end
+
+-- The following code is an adaption of experimental code for
+-- hyphenating and spell checking.
+
+local function mark_words(head,whenfound) -- can be optimized
+ local current, start, str, language, n = head, nil, "", nil, 0
+ local function action()
+ if #str > 0 then
+ local f = whenfound(language,str)
+ if f then
+ for i=1,n do
+ f(start)
+ start = start.next
+ end
+ end
+ end
+ str, start, n = "", nil, 0
+ end
+ while current do
+ local id = current.id
+ if id == glyph_node then
+ local a = current.lang
+ if a then
+ if a ~= language then
+ if start then
+ action()
+ end
+ language = a
+ end
+ elseif start then
+ action()
+ language = a
+ end
+ local components = current.components
+ if components then
+ start = start or current
+ n = n + 1
+ for g in traverse_nodes(components) do
+ str = str .. utfchar(g.char)
+ end
+ else
+ local code = current.char
+ if chardata[code].uccode or chardata[code].lccode then
+ start = start or current
+ n = n + 1
+ str = str .. utfchar(code)
+ elseif start then
+ action()
+ end
+ end
+ elseif id == disc_node then
+ if n > 0 then
+ n = n + 1
+ end
+ elseif id == kern_node and current.subtype == 0 and start then
+ -- ok
+ elseif start then
+ action()
+ end
+ current = current.next
+ end
+ if start then
+ action()
+ end
+ return head
+end
+
+words.methods = { }
+words.method = 1
+
+local methods = words.methods
+
+methods[1] = function(head, attribute, yes, nop)
+ local right, wrong = false, false
+ if yes then right = function(n) set_attribute(n,attribute,yes) end end
+ if nop then wrong = function(n) set_attribute(n,attribute,nop) end end
+ for n in traverse_nodes(head) do
+ unset_attribute(n,attribute) -- hm, not that selective (reset color)
+ end
+ local found, done = words.found, false
+ mark_words(head, function(language,str)
+ if #str < words.threshold then
+ return false
+ elseif found(language,str) then
+ done = true
+ return right
+ else
+ done = true
+ return wrong
+ end
+ end)
+ return head, done
+end
+
+local list, dump = { }, false -- todo: per language
+
+local lower = characters.lower
+
+methods[2] = function(head, attribute)
+ dump = true
+ mark_words(head, function(language,str)
+ if #str >= words.threshold then
+ str = lower(str)
+ list[str] = (list[str] or 0) + 1
+ end
+ end)
+ return head, true
+end
+
+words.used = list
+
+function words.dump_used_words(name)
+ if dump then
+ logs.report("languages","saving list of used words in '%s'",name)
+ io.savedata(name,table.serialize(list))
+ end
+end
+
+local color = attributes.private('color')
+
+function words.check(head)
+ if words.enabled and head.next then
+ local colors = words.colors
+ local alc = attributes.list[color]
+ return methods[words.method](head, color, alc[colors.known], alc[colors.unknown])
+ else
+ return head, false
+ end
+end
+
+function words.enable(method)
+ tasks.enableaction("processors","languages.words.check")
+ words.method = method or words.method or 1
+ words.enabled = true
+end
+
+function words.disable()
+ words.enabled = false
+end
+
+-- for the moment we hook it into the attribute handler
+
+--~ languagehacks = { }
+
+--~ function languagehacks.process(namespace,attribute,head)
+--~ return languages.check(head)
+--~ end
+
+--~ chars.plugins[chars.plugins+1] = {
+--~ name = "language",
+--~ namespace = languagehacks,
+--~ processor = languagehacks.process
+--~ }
diff --git a/tex/context/base/lang-wrd.mkiv b/tex/context/base/lang-wrd.mkiv
new file mode 100644
index 000000000..b6fc6a9d3
--- /dev/null
+++ b/tex/context/base/lang-wrd.mkiv
@@ -0,0 +1,54 @@
+%D \module
+%D [ file=lang-wrd,
+%D version=2006.XX.XX,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Experimental.
+
+\writestatus{loading}{ConTeXt Language Macros / Checking}
+
+\registerctxluafile{lang-wrd}{1.001}
+
+\unprotect
+
+% \loadspellchecklist[en][words-en.txt]
+% \loadspellchecklist[us][words-en.txt]
+% \loadspellchecklist[nl][words-nl.txt]
+% \setupspellchecking[state=start,method=1]
+%
+% \setupspellchecking[state=start,method=2]
+% ...
+% \typefile{\jobname.words}
+
+\def\loadspellchecklist
+ {\dodoubleempty\doloadspellchecklist}
+
+\def\doloadspellchecklist[#1][#2]%
+ {\ctxlua{languages.words.load("#1","#2")}}
+
+\unexpanded\def\setupspellchecking
+ {\dosingleargument\dosetupspellchecking}
+
+\unexpanded\def\setupspellchecking[#1]% todo colors
+ {\getparameters[\??wl][#1]%
+ \doifelse\@@wlstate\v!start
+ {\ctxlua{languages.words.enable(\@@wlmethod)}}
+ {\ctxlua{languages.words.disable()}}}
+
+\setupspellchecking
+ [\c!state=\v!stop,
+ \c!method=1]
+
+\appendtoks
+ \ctxlua{languages.words.dump_used_words("\jobname.words")}%
+\to \everybye
+
+\protect \endinput
diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua
new file mode 100644
index 000000000..e9e67e163
--- /dev/null
+++ b/tex/context/base/lpdf-ano.lua
@@ -0,0 +1,589 @@
+if not modules then modules = { } end modules ['lpdf-ano'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tostring, format, rep = tostring, string.rep, string.format
+local texcount = tex.count
+
+local trace_references = false trackers.register("references.references", function(v) trace_references = v end)
+local trace_destinations = false trackers.register("references.destinations", function(v) trace_destinations = v end)
+local trace_bookmarks = false trackers.register("references.bookmarks", function(v) trace_bookmarks = v end)
+
+local variables = interfaces.variables
+local constants = interfaces.constants
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+jobreferences = jobreferences or { }
+jobreferences.runners = jobreferences.runners or { }
+jobreferences.specials = jobreferences.specials or { }
+jobreferences.handlers = jobreferences.handlers or { }
+jobreferences.executers = jobreferences.executers or { }
+
+local runners = jobreferences.runners
+local specials = jobreferences.specials
+local handlers = jobreferences.handlers
+local executers = jobreferences.executers
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfconstant = lpdf.constant
+local pdfflushobject = lpdf.flushobject
+local pdfreserveobject = lpdf.reserveobject
+local pdfannotation = nodes.pdfannotation
+local pdfdestination = nodes.pdfdestination
+
+local pdfpagereference = tex.pdfpageref
+
+local pdf_uri = pdfconstant("URI")
+local pdf_gotor = pdfconstant("GoToR")
+local pdf_goto = pdfconstant("GoTo")
+local pdf_launch = pdfconstant("Launch")
+local pdf_javascript = pdfconstant("JavaScript")
+local pdf_link = pdfconstant("Link")
+local pdf_n = pdfconstant("N")
+local pdf_t = pdfconstant("T")
+local pdf_border = pdfarray { 0, 0, 0 }
+
+local cache = { }
+
+local function pagedest(n)
+ local pd = cache[n]
+ if not pd then
+ local a = pdfarray {
+ pdfreference(pdfpagereference(n)),
+ pdfconstant("Fit")
+ }
+ pd = pdfreference(pdfflushobject(a))
+ cache[n] = pd
+ end
+ return pd
+end
+
+lpdf.pagedest = pagedest
+
+local defaultdestination = pdfarray { 0, pdfconstant("Fit") }
+
+local function link(url,filename,destination,page,actions)
+ if filename and filename ~= "" then
+ if file.basename(filename) == tex.jobname then
+ return false
+ else
+ filename = file.addsuffix(filename,"pdf")
+ end
+ end
+ if url and url ~= "" then
+ if filename and filename ~= "" then
+ if destination and destination ~= "" then
+ url = file.join(url,filename).."#"..destination
+ else
+ url = file.join(url,filename)
+ end
+ end
+ return pdfdictionary {
+ S = pdf_uri,
+ URI = url,
+ }
+ elseif filename and filename ~= "" then
+ return pdfdictionary {
+ S = pdf_gotor, -- can also be pdf_launch
+ F = filename,
+ D = (destination and destination ~= "" and destination), -- or defaultdestination,
+ NewWindow = (actions.newwindow and true) or nil,
+ }
+ elseif destination and destination ~= "" then
+ local realpage, p = texcount.realpageno, tonumber(page)
+ if not p then
+ -- sorry
+ elseif p > realpage then
+ texcount.referencepagestate = 3
+ elseif p < realpage then
+ texcount.referencepagestate = 2
+ else
+ texcount.referencepagestate = 1
+ end
+ return pdfdictionary {
+ S = pdf_goto,
+ D = destination,
+ }
+ elseif page and page ~= "" then
+ local realpage, p = texcount.realpageno, tonumber(page)
+ if p then
+ if p > realpage then
+ texcount.referencepagestate = 3
+ elseif p < realpage then
+ texcount.referencepagestate = 2
+ else
+ texcount.referencepagestate = 1
+ end
+ return pdfdictionary {
+ S = pdf_goto,
+ D = pagedest(p),
+ }
+ else
+ commands.writestatus("references","invalid page reference: %s",page or "?")
+ end
+ end
+ return false
+end
+
+lpdf.link = link
+
+function lpdf.launch(program,parameters)
+ if program and program ~= "" then
+ local d = pdfdictionary {
+ S = pdf_launch,
+ F = program,
+ D = ".",
+ }
+ if parameters and parameters ~= "" then
+ d.P = parameters
+ end
+ return d
+ end
+end
+
+function lpdf.javascript(name,arguments)
+ local script = javascripts.code(name,arguments) -- make into object (hash)
+ if script then
+ return pdfdictionary {
+ S = pdf_javascript,
+ JS = script,
+ }
+ end
+end
+
+local function pdfaction(actions)
+ local nofactions = #actions
+ texcount.referencepagestate = 0 -- goodie, as we do all in the backend, we need to set it here too
+ if nofactions > 0 then
+ local a = actions[1]
+ local action = runners[a.kind]
+ if action then
+ action = action(a,actions)
+ end
+ if action then
+ local first = action
+ for i=2,nofactions do
+ local a = actions[i]
+ local what = runners[a.kind]
+ if what then
+ what = what(a,actions)
+ end
+ if what then
+ action.next = what
+ action = what
+ else
+ -- error
+ return nil
+ end
+ end
+ return first
+ end
+ end
+end
+
+lpdf.pdfaction = pdfaction
+
+function codeinjections.prerollreference(actions)
+ local main = actions and pdfaction(actions)
+ if main then
+ main = pdfdictionary {
+ Subtype = pdf_link,
+ Border = pdf_border,
+ H = (not actions.highlight and pdf_n) or nil,
+ A = main,
+ -- does not work at all in spite of specification
+ -- OC = (actions.layer and lpdf.layerreferences[actions.layer]) or nil,
+ -- OC = backends.pdf.layerreference(actions.layer),
+ }
+ return main("A") -- todo: cache this, maybe weak
+ end
+end
+
+-- local cache = { } -- no real gain in thsi
+--
+-- function codeinjections.prerollreference(actions)
+-- local main = actions and pdfaction(actions)
+-- if main then
+-- main = pdfdictionary {
+-- Subtype = pdf_link,
+-- Border = pdf_border,
+-- H = (not actions.highlight and pdf_n) or nil,
+-- A = main,
+-- }
+-- local cm = cache[main]
+-- if not cm then
+-- cm = "/A ".. tostring(pdfreference(pdfflushobject(main))
+-- cache[main] = cm
+-- end
+-- return cm
+-- end
+-- end
+
+function nodeinjections.reference(width,height,depth,prerolled)
+ if prerolled then
+ if swapdir then
+ width = - width
+ end
+ if trace_references then
+ logs.report("references","w=%s, h=%s, d=%s, a=%s",width,height,depth,prerolled)
+ end
+ return pdfannotation(width,height,depth,prerolled)
+ end
+end
+
+function nodeinjections.destination(width,height,depth,name,view)
+ if swapdir then
+ width = - width
+ end
+ if trace_destinations then
+ logs.report("destinations","w=%s, h=%s, d=%s, n=%s, v=%s",width,height,depth,name,view or "no view")
+ end
+ return pdfdestination(width,height,depth,name,view)
+end
+
+-- runners and specials
+
+local method = "internal"
+
+runners["inner"] = function(var,actions)
+ if method == "internal" then
+ local vir = var.i.references
+ local internal = vir and vir.internal
+ if internal then
+ var.inner = "aut:"..internal
+ end
+ end
+ return link(nil,nil,var.inner,var.r,actions)
+end
+
+runners["inner with arguments"] = function(var,actions)
+ logs.report("references","todo: inner with arguments")
+ return false
+end
+
+runners["outer"] = function(var,actions)
+ local file, url = jobreferences.checkedfileorurl(var.outer,var.outer)
+ return link(url,file,var.arguments,nil,actions)
+end
+
+runners["outer with inner"] = function(var,actions)
+ local file = jobreferences.checkedfile(var.f)
+ return link(nil,file,var.inner,var.r,actions)
+end
+
+runners["special outer with operation"] = function(var,actions)
+ local handler = specials[var.special]
+ return handler and handler(var,actions)
+end
+
+runners["special outer"] = function(var,actions)
+ logs.report("references","todo: special outer")
+ return false
+end
+
+runners["special"] = function(var,actions)
+ local handler = specials[var.special]
+ return handler and handler(var,actions)
+end
+
+runners["outer with inner with arguments"] = function(var,actions)
+ logs.report("references","todo: outer with inner with arguments")
+ return false
+end
+
+runners["outer with special and operation and arguments"] = function(var,actions)
+ logs.report("references","todo: outer with special and operation and arguments")
+ return false
+end
+
+runners["outer with special"] = function(var,actions)
+ logs.report("references","todo: outer with special")
+ return false
+end
+
+runners["outer with special and operation"] = function(var,actions)
+ logs.report("references","todo: outer with special and operation")
+ return false
+end
+
+runners["special operation"] = runners["special"]
+runners["special operation with arguments"] = runners["special"]
+
+function specials.internal(var,actions) -- better resolve in strc-ref
+ local i = tonumber(var.operation)
+ local v = jobreferences.internals[i]
+ if not v then
+ -- error
+ elseif method == "internal" then
+ -- named
+ return link(nil,nil,"aut:"..i,v.references.realpage,actions)
+ else
+ -- page
+ return link(nil,nil,nil,v.references.realpage,actions)
+ end
+end
+
+specials.i = specials.internal
+
+function specials.page(var,actions) -- better resolve in strc-ref
+ local file = var.f
+ if file then
+ file = jobreferences.checkedfile(file)
+ return link(nil,file,nil,p or var.operation,actions)
+ else
+ local p = jobreferences.pages[var.operation]
+ if type(p) == "function" then
+ p = p()
+ end
+ return link(nil,nil,nil,p or var.operation,actions)
+ end
+end
+
+-- todo, do this in references namespace ordered instead (this is an experiment)
+
+local splitter = lpeg.splitat(":")
+
+function specials.order(var,actions) -- jobreferences.specials !
+ local operation = var.operation
+ if operation then
+ local kind, name, n = lpegmatch(splitter,operation)
+ local order = lists.ordered[kind]
+ order = order and order[name]
+ local v = order[tonumber(n)]
+ local r = v and v.references.realpage
+ if r then
+ var.operation = r -- brrr, but test anyway
+ return specials.page(var,actions)
+ end
+ end
+end
+
+function specials.url(var,actions)
+ local url = jobreferences.checkedurl(var.operation)
+ return link(url,nil,var.arguments,nil,actions)
+end
+
+function specials.file(var,actions)
+ local file = jobreferences.checkedfile(var.operation)
+ return link(nil,file,var.arguments,nil,actions)
+end
+
+function specials.fileorurl(var,actions)
+ local file, url = jobreferences.checkedfileorurl(var.operation,var.operation)
+ return link(url,file,var.arguments,nil,actions)
+end
+
+function specials.program(var,content)
+ local program = jobreferences.checkedprogram(var.operation)
+ return lpdf.launch(program,var.arguments)
+end
+
+function specials.javascript(var)
+ return lpdf.javascript(var.operation,var.arguments)
+end
+
+specials.JS = specials.javascript
+
+local pdf_named = pdfconstant("Named")
+
+executers.importform = pdfdictionary { S = pdf_named, N = pdfconstant("AcroForm:ImportFDF") }
+executers.exportform = pdfdictionary { S = pdf_named, N = pdfconstant("AcroForm:ExportFDF") }
+executers.first = pdfdictionary { S = pdf_named, N = pdfconstant("FirstPage") }
+executers.previous = pdfdictionary { S = pdf_named, N = pdfconstant("PrevPage") }
+executers.next = pdfdictionary { S = pdf_named, N = pdfconstant("NextPage") }
+executers.last = pdfdictionary { S = pdf_named, N = pdfconstant("LastPage") }
+executers.backward = pdfdictionary { S = pdf_named, N = pdfconstant("GoBack") }
+executers.forward = pdfdictionary { S = pdf_named, N = pdfconstant("GoForward") }
+executers.print = pdfdictionary { S = pdf_named, N = pdfconstant("Print") }
+executers.exit = pdfdictionary { S = pdf_named, N = pdfconstant("Quit") }
+executers.close = pdfdictionary { S = pdf_named, N = pdfconstant("Close") }
+executers.save = pdfdictionary { S = pdf_named, N = pdfconstant("Save") }
+executers.savenamed = pdfdictionary { S = pdf_named, N = pdfconstant("SaveAs") }
+executers.opennamed = pdfdictionary { S = pdf_named, N = pdfconstant("Open") }
+executers.help = pdfdictionary { S = pdf_named, N = pdfconstant("HelpUserGuide") }
+executers.toggle = pdfdictionary { S = pdf_named, N = pdfconstant("FullScreen") }
+executers.search = pdfdictionary { S = pdf_named, N = pdfconstant("Find") }
+executers.searchagain = pdfdictionary { S = pdf_named, N = pdfconstant("FindAgain") }
+executers.gotopage = pdfdictionary { S = pdf_named, N = pdfconstant("GoToPage") }
+executers.query = pdfdictionary { S = pdf_named, N = pdfconstant("AcroSrch:Query") }
+executers.queryagain = pdfdictionary { S = pdf_named, N = pdfconstant("AcroSrch:NextHit") }
+executers.fitwidth = pdfdictionary { S = pdf_named, N = pdfconstant("FitWidth") }
+executers.fitheight = pdfdictionary { S = pdf_named, N = pdfconstant("FitHeight") }
+
+local function fieldset(arguments)
+ -- [\dogetfieldset{#1}]
+ return nil
+end
+
+function executers.resetform(arguments)
+ arguments = (type(arguments) == "table" and arguments) or aux.settings_to_array(arguments)
+ return pdfdictionary {
+ S = pdfconstant("ResetForm"),
+ Field = fieldset(arguments[1])
+ }
+end
+
+local formmethod = "post" -- "get" "post"
+local formformat = "xml" -- "xml" "html" "fdf"
+
+-- bit 3 = html bit 6 = xml bit 4 = get
+
+local flags = {
+ get = {
+ html = 12, fdf = 8, xml = 40,
+ },
+ post = {
+ html = 4, fdf = 0, xml = 32,
+ }
+}
+
+function executers.submitform(arguments)
+ arguments = (type(arguments) == "table" and arguments) or aux.settings_to_array(arguments)
+ local flag = flags[formmethod] or flags.post
+ flag = (flag and (flag[formformat] or flag.xml)) or 32 -- default: post, xml
+ return pdfdictionary {
+ S = pdfconstant("ResetForm"),
+ F = fieldset(arguments[1]),
+ Field = fieldset(arguments[2]),
+ Flags = flag,
+ -- \PDFsubmitfiller
+ }
+end
+
+function executers.hide(arguments)
+ return pdfdictionary {
+ S = pdfconstant("Hide"),
+ H = true,
+ T = arguments,
+ }
+end
+
+function executers.show(arguments)
+ return pdfdictionary {
+ S = pdfconstant("Hide"),
+ H = false,
+ T = arguments,
+ }
+end
+
+local pdf_movie = pdfconstant("Movie")
+local pdf_start = pdfconstant("Start")
+local pdf_stop = pdfconstant("Stop")
+local pdf_resume = pdfconstant("Resume")
+local pdf_pause = pdfconstant("Pause")
+
+local function movie_or_sound(operation,arguments)
+ arguments = (type(arguments) == "table" and arguments) or aux.settings_to_array(arguments)
+ return pdfdictionary {
+ S = pdf_movie,
+ T = format("movie %s",arguments[1] or "noname"),
+ Operation = operation,
+ }
+end
+
+function executers.startmovie (arguments) return movie_or_sound(pdf_start ,arguments) end
+function executers.stopmovie (arguments) return movie_or_sound(pdf_stop ,arguments) end
+function executers.resumemovie(arguments) return movie_or_sound(pdf_resume,arguments) end
+function executers.pausemovie (arguments) return movie_or_sound(pdf_pause ,arguments) end
+
+function executers.startsound (arguments) return movie_or_sound(pdf_start ,arguments) end
+function executers.stopsound (arguments) return movie_or_sound(pdf_stop ,arguments) end
+function executers.resumesound(arguments) return movie_or_sound(pdf_resume,arguments) end
+function executers.pausesound (arguments) return movie_or_sound(pdf_pause ,arguments) end
+
+function specials.action(var)
+ local operation = var.operation
+ if var.operation and operation ~= "" then
+ local e = executers[operation]
+ if type(e) == "table" then
+ return e
+ elseif type(e) == "function" then
+ return e(var.arguments)
+ end
+ end
+end
+
+--~ entry.A = pdfdictionary {
+--~ S = pdfconstant("GoTo"),
+--~ D = ....
+--~ }
+
+local function build(levels,start,parent,method)
+ local startlevel = levels[start][1]
+ local i, n = start, 0
+ local child, entry, m, prev, first, last, f, l
+-- to be tested: i can be nil
+ while i and i <= #levels do
+ local li = levels[i]
+ local level, title, reference, open = li[1], li[2], li[3], li[4]
+ if level == startlevel then
+ if trace_bookmarks then
+ logs.report("bookmark","%3i %s%s %s",reference.realpage,rep(" ",level-1),(open and "+") or "-",title)
+ end
+ local prev = child
+ child = pdfreserveobject()
+ if entry then
+ entry.Next = child and pdfreference(child)
+ pdfflushobject(prev,entry)
+ end
+ entry = pdfdictionary {
+ Title = pdfunicode(title),
+ Parent = parent,
+ Prev = prev and pdfreference(prev),
+ }
+ if method == "internal" then
+ entry.Dest = "aut:" .. reference.internal
+ else -- if method == "page" then
+ entry.Dest = pagedest(reference.realpage)
+ end
+ if not first then first, last = child, child end
+ prev = child
+ last = prev
+ n = n + 1
+ i = i + 1
+ elseif level < startlevel then
+ pdfflushobject(child,entry)
+ return i, n, first, last
+ elseif i < #levels and level > startlevel then
+ i, m, f, l = build(levels,i,pdfreference(child),method)
+ entry.Count = (open and m) or -m
+ if m > 0 then
+ entry.First, entry.Last = pdfreference(f), pdfreference(l)
+ end
+ else
+ -- missing intermediate level but ok
+ i, m, f, l = build(levels,i,pdfreference(child),method)
+ entry.Count = (open and m) or -m
+ if m > 0 then
+ entry.First, entry.Last = pdfreference(f), pdfreference(l)
+ end
+ pdfflushobject(child,entry)
+ return i, n, first, last
+ end
+ end
+ pdfflushobject(child,entry)
+ return nil, n, first, last
+end
+
+function codeinjections.addbookmarks(levels,method)
+ local parent = pdfreserveobject()
+ local _, m, first, last = build(levels,1,pdfreference(parent),method or "internal")
+ local dict = pdfdictionary {
+ Type = pdfconstant("Outlines"),
+ First = pdfreference(first),
+ Last = pdfreference(last),
+ Count = m,
+ }
+ pdfflushobject(parent,dict)
+ lpdf.addtocatalog("Outlines",lpdf.reference(parent))
+end
diff --git a/tex/context/base/lpdf-col.lua b/tex/context/base/lpdf-col.lua
new file mode 100644
index 000000000..18aa848ff
--- /dev/null
+++ b/tex/context/base/lpdf-col.lua
@@ -0,0 +1,150 @@
+if not modules then modules = { } end modules ['lpdf-mis'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type = type
+local format, gsub = string.format, string.gsub
+
+-- colors = colors or { }
+-- transparencies = transparencies or { }
+
+local registercolor = colors.register
+local registertransparancy = transparencies.register
+local colorsvalue = colors.value
+local transparenciesvalue = transparencies.value
+
+-- Literals needed to inject code in the mp stream, we cannot use attributes there
+-- since literals may have qQ's, much may go away once we have mplib code in place.
+--
+-- This module assumes that some functions are defined in the colors namespace
+-- which mostlikely will be loaded later.
+
+function lpdf.color(model,ca,default) -- todo: use gray when no color
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ local s = cv[2]
+ return format("%s g %s G",s,s)
+ elseif model == 3 then
+ local r, g, b = cv[3], cv[4], cv[5]
+ return format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)
+ elseif model == 4 then
+ local c, m, y, k = cv[6],cv[7],cv[8],cv[9]
+ return format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)
+ else
+ local n,f,d,p = cv[10],cv[11],cv[12],cv[13]
+ if type(p) == "string" then
+ p = gsub(p,","," ") -- brr misuse of spot
+ end
+ return format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)
+ end
+ else
+ return format("%s g %s G",default or 0,default or 0)
+ end
+end
+
+function lpdf.transparency(ct,default) -- kind of overlaps with transparencycode
+ -- beware, we need this hack because normally transparencies are not
+ -- yet registered and therefore the number is not not known ... we
+ -- might use the attribute number itself in the future
+ local ct = transparenciesvalue(ct)
+ if ct then
+ return format("/Tr%s gs",registertransparancy(nil,ct[1],ct[2],true))
+ else
+ return "/Tr0 gs"
+ end
+end
+
+function lpdf.colorvalue(model,ca,default)
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return format("%s",cv[2])
+ elseif model == 3 then
+ return format("%s %s %s",cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("%s %s %s %s",cv[6],cv[7],cv[8],cv[9])
+ else
+ return format("%s",cv[13])
+ end
+ else
+ return format("%s",default or 0)
+ end
+end
+
+function lpdf.fdfcolor(model,ca,default)
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return format("[%s]",cv[2])
+ elseif model == 3 then
+ return format("[%s %s %s]",cv[3],cv[4],cv[5])
+ elseif model == 4 then
+ return format("[%s %s %s %s]",cv[6],cv[7],cv[8],cv[9])
+ elseif model == 4 then
+ return format("[%s]",cv[13])
+ end
+ else
+ return format("[%s]",default or 0)
+ end
+end
+
+function lpdf.colorspace(model,ca)
+ local cv = colorsvalue(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return "DeviceGray"
+ elseif model == 3 then
+ return "DeviceRGB"
+ elseif model == 4 then
+ return "DeviceCMYK"
+ end
+ end
+ return "DeviceGRAY"
+end
+
+-- by registering we getconversion for free (ok, at the cost of overhead)
+
+local intransparency = false
+local pdfcolor = lpdf.color
+
+function lpdf.rgbcode(model,r,g,b)
+ return pdfcolor(model,registercolor(nil,'rgb',r,g,b))
+end
+function lpdf.cmykcode(model,c,m,y,k)
+ return pdfcolor(model,registercolor(nil,'cmyk',c,m,y,k))
+end
+function lpdf.graycode(model,s)
+ return pdfcolor(model,registercolor(nil,'gray',s))
+end
+function lpdf.spotcode(model,n,f,d,p)
+ return pdfcolor(model,registercolor(nil,'spot',n,f,d,p)) -- incorrect
+end
+function lpdf.transparencycode(a,t)
+ intransparency = true
+ return format("/Tr%s gs",registertransparancy(nil,a,t,true)) -- true forces resource
+end
+function lpdf.finishtransparencycode()
+ if intransparency then
+ intransparency = false
+ return "/Tr0 gs" -- we happen to know this -)
+ else
+ return ""
+ end
+end
diff --git a/tex/context/base/lpdf-fld.lua b/tex/context/base/lpdf-fld.lua
new file mode 100644
index 000000000..c034aec6c
--- /dev/null
+++ b/tex/context/base/lpdf-fld.lua
@@ -0,0 +1,885 @@
+if not modules then modules = { } end modules ['lpdf-fld'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- cleaned up, e.g. no longer older viewers
+-- always kids so no longer explicit main / clone / copy
+-- some optimizations removed (will come bakc if needed)
+
+local gmatch, lower, format = string.gmatch, string.lower, string.format
+local lpegmatch = lpeg.match
+
+local trace_fields = false trackers.register("widgets.fields", function(v) trace_fields = v end)
+
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+
+local variables = interfaces.variables
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local registeredsymbol = codeinjections.registeredsymbol
+
+local pdfstream = lpdf.stream
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfstring = lpdf.string
+local pdfconstant = lpdf.constant
+local pdftoeight = lpdf.toeight
+local pdfflushobject = lpdf.flushobject
+local pdfreserveobject = lpdf.reserveobject
+local pdfannotation = nodes.pdfannotation
+
+local submitoutputformat = 0 -- 0=unknown 1=HTML 2=FDF 3=XML => not yet used, needs to be checked
+
+local splitter = lpeg.splitat("=>")
+
+local formats = {
+ html = 1, fdf = 2, xml = 3,
+}
+
+function codeinjections.setformsmethod(name)
+ submitoutputformat = formats[lower(name)] or 3
+end
+
+local flag = {
+ MultiLine = 4096, -- 13
+ NoToggleToOff = 16384, -- 15
+ Radio = 32768, -- 16
+ PushButton = 65536, -- 17
+ PopUp = 131072, -- 18
+ Edit = 262144, -- 19
+ RadiosInUnison = 33554432, -- 26
+ DoNotSpellCheck = 4194304, -- 23
+ DoNotScroll = 8388608, -- 24
+ ReadOnly = 1, -- 1
+ Required = 2, -- 2
+ NoExport = 4, -- 3
+ Password = 8192, -- 14
+ Sort = 524288, -- 20
+ FileSelect = 1048576, -- 21
+}
+
+local plus = {
+ Invisible = 1, -- 1
+ Hidden = 2, -- 2
+ Printable = 4, -- 3
+ NoView = 32, -- 6
+ ToggleNoView = 256, -- 9
+ AutoView = 256, -- 288 (6+9)
+}
+
+-- todo: check what is interfaced
+
+flag.readonly = flag.ReadOnly
+flag.required = flag.Required
+flag.protected = flag.Password
+flag.sorted = flag.Sort
+flag.unavailable = flag.NoExport
+flag.nocheck = flag.DoNotSpellCheck
+flag.fixed = flag.DoNotScroll
+flag.file = flag.FileSelect
+
+plus.hidden = plus.Hidden
+plus.printable = plus.Printable
+plus.auto = plus.AutoView
+
+-- some day .. lpeg with function or table
+
+local function fieldflag(specification)
+ local o, n = specification.options, 0
+ if o and o ~= "" then
+ for f in gmatch(o,"[^, ]+") do
+ n = n + (flag[f] or 0)
+ end
+ end
+ return n
+end
+
+local function fieldplus(specification)
+ local o, n = specification.options, 0
+ if o and o ~= "" then
+ for p in gmatch(o,"[^, ]+") do
+ n = n + (plus[p] or 0)
+ end
+ end
+ return n
+end
+
+
+local function checked(what)
+ if what and what ~= "" then
+ local set, bug = jobreferences.identify("",what)
+ return not bug and #set > 0 and lpdf.pdfaction(set)
+ end
+end
+
+local function fieldactions(specification) -- share actions
+--~ print(table.serialize(specification))
+ local d, a = { }, nil
+ a = specification.mousedown if a and a ~= "" then d.D = checked(a) end
+ a = specification.mouseup if a and a ~= "" then d.U = checked(a) end
+ a = specification.regionin if a and a ~= "" then d.E = checked(a) end -- Enter
+ a = specification.regionout if a and a ~= "" then d.X = checked(a) end -- eXit
+ a = specification.afterkeystroke if a and a ~= "" then d.K = checked(a) end
+ a = specification.formatresult if a and a ~= "" then d.F = checked(a) end
+ a = specification.validateresult if a and a ~= "" then d.V = checked(a) end
+ a = specification.calculatewhatever if a and a ~= "" then d.C = checked(a) end
+ a = specification.focusin if a and a ~= "" then d.Fo = checked(a) end
+ a = specification.focusout if a and a ~= "" then d.Bl = checked(a) end
+ -- a = specification.openpage if a and a ~= "" then d.PO = checked(a) end
+ -- a = specification.closepage if a and a ~= "" then d.PC = checked(a) end
+ -- a = specification.visiblepage if a and a ~= "" then d.PV = checked(a) end
+ -- a = specification.invisiblepage if a and a ~= "" then d.PI = checked(a) end
+ return next(d) and pdfdictionary(d)
+end
+
+-- fonts and color
+
+local fontnames = {
+ rm = {
+ tf = "Times-Roman",
+ bf = "Times-Bold",
+ it = "Times-Italic",
+ sl = "Times-Italic",
+ bi = "Times-BoldItalic",
+ bs = "Times-BoldItalic",
+ },
+ ss = {
+ tf = "Helvetica",
+ bf = "Helvetica-Bold",
+ it = "Helvetica-Oblique",
+ sl = "Helvetica-Oblique",
+ bi = "Helvetica-BoldOblique",
+ bs = "Helvetica-BoldOblique",
+ },
+ tt = {
+ tf = "Courier",
+ bf = "Courier-Bold",
+ it = "Courier-Oblique",
+ sl = "Courier-Oblique",
+ bi = "Courier-BoldOblique",
+ bs = "Courier-BoldOblique",
+ }
+}
+
+local usedfonts = { }
+
+local function fieldsurrounding(specification)
+ local size = specification.fontsize or "12pt"
+ local style = specification.fontstyle or "rm"
+ local alternative = specification.fontalternative or "tf"
+ local s = fontnames[style]
+ if not s then
+ style, s = "rm", fontnames.rm
+ end
+ local a = s[alternative]
+ if not a then
+ alternative, a = "tf", s.tf
+ end
+ local tag = style .. alternative
+ size = string.todimen(size)
+ local stream = pdfstream {
+ pdfconstant(tag),
+ format("%0.4f Tf",(size and (number.dimenfactors.bp * size)) or 12),
+ }
+ usedfonts[tag] = a -- the name
+ -- add color to stream: 0 g
+ -- move up with "x.y Ts"
+ return tostring(stream)
+end
+
+local function registerfonts()
+ if next(usedfonts) then
+ local d = pdfdictionary()
+ for tag, name in next, usedfonts do
+ local f = pdfdictionary {
+ Type = pdfconstant("Font"),
+ Subtype = pdfconstant("Type1"), -- todo
+ Name = pdfconstant(tag),
+ BaseFont = pdfconstant(name),
+ }
+ d[tag] = pdfreference(pdfflushobject(f))
+ end
+ return d
+ end
+end
+
+-- cache
+
+local function fieldattributes(specification)
+--~ return pdfarray {
+--~ -- BG = -- backgroundcolor
+--~ -- BC = -- framecolor
+--~ }
+ return nil
+end
+
+-- symbols
+
+local function fieldappearances(specification)
+ -- todo: caching
+ local values = specification.values
+ local default = specification.default -- todo
+ if not values then
+ -- error
+ return
+ end
+ local v = aux.settings_to_array(values)
+ local n, r, d
+ if #v == 1 then
+ n, r, d = v[1], v[1], v[1]
+ elseif #v == 2 then
+ n, r, d = v[1], v[1], v[2]
+ else
+ n, r, d = v[1], v[2], v[3]
+ end
+ local appearance = pdfdictionary { -- cache this one
+ N = registeredsymbol(n), R = registeredsymbol(r), D = registeredsymbol(d),
+ }
+ return lpdf.sharedobj(tostring(appearance))
+end
+
+local function fieldstates(specification,forceyes,values,default)
+ -- we don't use Opt here (too messy for radio buttons)
+ local values, default = values or specification.values, default or specification.default
+ if not values then
+ -- error
+ return
+ end
+ local v = aux.settings_to_array(values)
+ local yes, off
+ if #v == 1 then
+ yes, off = v[1], v[1]
+ else
+ yes, off = v[1], v[2]
+ end
+ local yesshown, yesvalue = lpegmatch(splitter,yes)
+ if not (yesshown and yesvalue) then
+ yesshown = yes, yes
+ end
+ yes = aux.settings_to_array(yesshown)
+ local offshown, offvalue = lpegmatch(splitter,off)
+ if not (offshown and offvalue) then
+ offshown = off, off
+ end
+ off = aux.settings_to_array(offshown)
+ if #yes == 1 then
+ yesn, yesr, yesd = yes[1], yes[1], yes[1]
+ elseif #yes == 2 then
+ yesn, yesr, yesd = yes[1], yes[1], yes[2]
+ else
+ yesn, yesr, yesd = yes[1], yes[2], yes[3]
+ end
+ if #off == 1 then
+ offn, offr, offd = off[1], off[1], off[1]
+ elseif #off == 2 then
+ offn, offr, offd = off[1], off[1], off[2]
+ else
+ offn, offr, offd = off[1], off[2], off[3]
+ end
+ if not yesvalue then
+ yesvalue = yesn
+ end
+ if not offvalue then
+ offvalue = offn
+ end
+ if forceyes == true then
+ forceyes = forceyes and "On" -- spec likes Yes more but we've used On for ages now
+ else
+ -- false or string
+ end
+ if default == yesn then
+ default = pdfconstant(forceyes or yesn)
+ else
+ default = pdfconstant("Off")
+ end
+ local appearance = pdfdictionary { -- maybe also cache components
+ N = pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) },
+ R = pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) },
+ D = pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }
+ }
+ local appearanceref = lpdf.sharedobj(tostring(appearance))
+ return appearanceref, default
+end
+
+local function fieldoptions(specification)
+ local values = specification.values
+ local default = specification.default
+ if values then
+ local v = aux.settings_to_array(values)
+ for i=1,#v do
+ local vi = v[i]
+ local shown, value = lpegmatch(splitter,vi)
+ if shown and value then
+ v[i] = pdfarray { pdfunicode(value), shown }
+ else
+ v[i] = pdfunicode(v[i])
+ end
+ end
+ return pdfarray(v)
+ end
+end
+
+local function radiodefault(parent,field,forceyes)
+ local default, values = parent.default, parent.values
+ if not default or default == "" then
+ values = aux.settings_to_array(values)
+ default = values[1]
+ end
+ local name = field.name
+ local fieldvalues = aux.settings_to_array(field.values)
+ local yes, off = fieldvalues[1], fieldvalues[2] or fieldvalues[1]
+ if not default then
+ return pdfconstant((forceyes and "On") or yes)
+ elseif default == name then
+ return pdfconstant((forceyes and "On") or default)
+ else
+ return pdfconstant("Off")
+ end
+end
+
+-- layers
+
+local function fieldlayer(specification) -- we can move this in line
+ local layer = specification.layer
+ return (layer and lpdf.layerreferences[layer]) or nil
+end
+
+-- defining
+
+local fields, radios, clones, fieldsets, calculationset = { }, { }, { }, { }, nil
+
+function codeinjections.definefieldset(tag,list)
+ fieldsets[tag] = list
+end
+
+function codeinjections.getfieldset(tag)
+ return fieldsets[tag]
+end
+
+local function fieldsetlist(tag)
+ if tag then
+ local ft = fieldsets[tag]
+ if ft then
+ local a = pdfarray()
+ for name in gmatch(list,"[^, ]+") do
+ local f = field[name]
+ if f and f.pobj then
+ a[#a+1] = pdfreference(f.pobj)
+ end
+ end
+ return a
+ end
+ end
+end
+
+function codeinjections.setfieldcalculationset(tag)
+ calculationset = tag
+end
+
+local function predefinesymbols(specification)
+ local values = specification.values
+ if values then
+ local symbols = aux.settings_to_array(values)
+ for i=1,#symbols do
+ local symbol = symbols[i]
+ local a, b = lpegmatch(splitter,symbol)
+ codeinjections.presetsymbol(a or symbol)
+ end
+ end
+end
+
+function codeinjections.getdefaultfieldvalue(name)
+ local f = fields[name]
+ if f then
+ local values = f.values
+ local default = f.default
+ if not default or default == "" then
+ local symbols = aux.settings_to_array(values)
+ local symbol = symbols[1]
+ if symbol then
+ local a, b = lpegmatch(splitter,symbol) -- splits at =>
+ default = a or symbol
+ end
+ end
+ if default then
+ tex.sprint(ctxcatcodes,default)
+ end
+ end
+end
+
+function codeinjections.definefield(specification)
+ local n = specification.name
+ local f = fields[n]
+ if not f then
+ local kind = specification.kind
+ if not kind then
+ if trace_fields then
+ logs.report("fields","invalid definition of '%s': unknown type",n)
+ end
+ elseif kind == "radio" then
+ local values = specification.values
+ if values and values ~= "" then
+ values = aux.settings_to_array(values)
+ for v=1,#values do
+ radios[values[v]] = { parent = n }
+ end
+ fields[n] = specification
+ if trace_fields then
+ logs.report("fields","defining '%s' as radio",n or "?")
+ end
+ elseif trace_fields then
+ logs.report("fields","invalid definition of radio '%s': missing values",n)
+ end
+ elseif kind == "sub" then
+ -- not in main field list !
+ local radio = radios[n]
+ if radio then
+ -- merge specification
+ for key, value in next, specification do
+ radio[key] = value
+ end
+ if trace_fields then
+ local p = radios[n] and radios[n].parent
+ logs.report("fields","defining '%s' as sub of radio '%s'",n or "?",p or "?")
+ end
+ elseif trace_fields then
+ logs.report("fields","invalid definition of radio sub '%s': no parent",n)
+ end
+ predefinesymbols(specification)
+ elseif kind == "text" or kind == "line" then
+ fields[n] = specification
+ if trace_fields then
+ logs.report("fields","defining '%s' as %s",n,kind)
+ end
+ if specification.values ~= "" and specification.default == "" then
+ specification.default, specification.values = specification.values, nil
+ end
+ else
+ fields[n] = specification
+ if trace_fields then
+ logs.report("fields","defining '%s' as %s",n,kind)
+ end
+ predefinesymbols(specification)
+ end
+ elseif trace_fields then
+ logs.report("fields","invalid definition of '%s': already defined",n)
+ end
+end
+
+function codeinjections.clonefield(specification)
+ local p, c, v = specification.parent, specification.children, specification.variant
+ if not p or not c then
+ if trace_fields then
+ logs.report("fields","invalid clone: children: '%s', parent '%s', variant: '%s'",p or "?",c or "?", v or "?")
+ end
+ else
+ for n in gmatch(c,"[^, ]+") do
+ local f, r, c, x = fields[n], radios[n], clones[n], fields[p]
+ if f or r or c then
+ if trace_fields then
+ logs.report("fields","already cloned: child: '%s', parent '%s', variant: '%s'",p or "?",n or "?", v or "?")
+ end
+ elseif x then
+ if trace_fields then
+ logs.report("fields","invalid clone: child: '%s', variant: '%s', no parent",n or "?", v or "?")
+ end
+ else
+ if trace_fields then
+ logs.report("fields","cloning: child: '%s', parent '%s', variant: '%s'",p or "?",n or "?", v or "?")
+ end
+ clones[n] = specification
+ predefinesymbols(specification)
+ end
+ end
+ end
+end
+
+function codeinjections.getfieldgroup(name)
+ local f = fields[name] or radios[name] or clones[name]
+ local g = f and f.group
+ if not g or g == "" then
+ local v, p, k = f.variant, f.parent, f.kind
+ if v == "clone" or v == "copy" then
+ f = fields[p] or radios[p]
+ g = f and f.group
+ elseif k == "sub" then
+ f = fields[p]
+ g = f and f.group
+ end
+ end
+ if g then
+ texsprint(ctxcatcodes,g)
+ end
+end
+
+--
+
+function codeinjections.doiffieldset(tag)
+ commands.testcase(fieldsets[tag])
+end
+
+function codeinjections.doiffieldelse(name)
+ commands.testcase(fields[name])
+end
+
+--
+
+local alignments = {
+ flushleft = 0, right = 0,
+ center = 1, middle = 1,
+ flushright = 2, left = 2,
+}
+
+local function fieldalignment(specification)
+ return alignments[specification.align] or 0
+end
+
+local function enhance(specification,option)
+ local so = specification.options
+ if so and so ~= "" then
+ specification.options = so .. "," .. option
+ else
+ specification.options = option
+ end
+ return specification
+end
+
+-- finish
+
+local collected = pdfarray()
+
+local function finishfields()
+ for name, field in next, fields do
+ local kids = field.kids
+ if kids then
+ pdfflushobject(field.kobj,kids)
+ end
+ local pobj = field.pobj
+ end
+ for name, field in next, radios do
+ local kids = field.kids
+ if kids then
+ pdfflushobject(field.kobj,kids)
+ end
+ end
+ if #collected > 0 then
+ usedfonts.tttf = fontnames.tt.tf
+ local acroform = pdfdictionary {
+ NeedAppearances = true,
+ Fields = pdfreference(pdfflushobject(collected)),
+ DR = pdfdictionary { Font = registerfonts() },
+ CO = fieldsetlist(calculationset),
+ DA = "/tttf 12 Tf 0 g",
+ }
+ lpdf.addtocatalog("AcroForm",pdfreference(pdfflushobject(acroform)))
+ end
+end
+
+lpdf.registerdocumentfinalizer(finishfields)
+
+local pdf_widget = pdfconstant("Widget")
+local pdf_tx = pdfconstant("Tx")
+local pdf_ch = pdfconstant("Ch")
+local pdf_btn = pdfconstant("Btn")
+local pdf_yes = pdfconstant("Yes")
+local pdf_p = pdfconstant("P") -- None Invert Outline Push
+local pdf_n = pdfconstant("N") -- None Invert Outline Push
+--
+local pdf_no_rect = pdfarray { 0, 0, 0, 0 }
+
+local methods = { }
+
+function codeinjections.typesetfield(name,specification)
+ local field = fields[name] or radios[name] or clones[name]
+ if not field then
+ logs.report("fields", "unknown child '%s'",name)
+ -- unknown field
+ return
+ end
+ local variant, parent = field.variant, field.parent
+ if variant == "copy" or variant == "clone" then -- only in clones
+ field = fields[parent] or radios[parent]
+ end
+ local method = methods[field.kind]
+ if method then
+ method(name,specification,variant)
+ else
+ logs.report("fields", "unknown method '%s' for child '%s'",field.kind,name)
+ end
+end
+
+-- can be optional multipass optimization (share objects)
+
+local function save_parent(field,specification,d)
+ local kn = pdfreserveobject()
+ d.Kids = pdfreference(kn)
+ field.kobj = kn
+ field.kids = pdfarray()
+ local pn = pdfflushobject(d)
+ field.pobj = pn
+ collected[#collected+1] = pdfreference(pn)
+end
+
+local function save_kid(field,specification,d)
+ local kn = pdfreserveobject()
+ field.kids[#field.kids+1] = pdfreference(kn)
+ node.write(pdfannotation(specification.width,specification.height,0,d(),kn))
+end
+
+function methods.line(name,specification,variant,extras)
+ local field = fields[name]
+ if variant == "copy" or variant == "clone" then
+ logs.report("fields","todo: clones of text fields")
+ end
+ local kind = field.kind
+ if not field.pobj then
+ if trace_fields then
+ logs.report("fields","using parent text '%s'",name)
+ end
+ if extras then
+ enhance(specification,extras)
+ end
+ local text = pdfunicode(field.default)
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ MK = fieldsurrounding(specification), -- needed ?
+ DA = fieldsurrounding(specification),
+ AA = fieldactions(specification),
+ FT = pdf_tx,
+ Q = fieldalignment(specification),
+ MaxLen = (specification.length == 0 and 1000) or specification.length,
+ DV = text,
+ V = text,
+ }
+ save_parent(field,specification,d)
+ field.specification = specification
+ end
+ specification = field.specification or { } -- todo: radio spec
+ if trace_fields then
+ logs.report("fields","using child text '%s'",name)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(field.pobj),
+ F = fieldplus(specification),
+ DA = fieldattributes(specification),
+ OC = fieldlayer(specification),
+ MK = fieldsurrounding(specification),
+ DA = fieldsurrounding(specification),
+ AA = fieldactions(specification),
+ Q = fieldalignment(specification),
+ }
+ save_kid(field,specification,d)
+end
+
+function methods.text(name,specification,variant)
+ methods.line(name,specification,variant,"MultiLine")
+end
+
+function methods.choice(name,specification,variant,extras)
+ local field = fields[name]
+ if variant == "copy" or variant == "clone" then
+ logs.report("fields","todo: clones of choice fields")
+ end
+ local kind = field.kind
+ local d
+ if not field.pobj then
+ if trace_fields then
+ logs.report("fields","using parent choice '%s'",name)
+ end
+ if extras then
+ enhance(specification,extras)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ FT = pdf_ch,
+ Opt = fieldoptions(field),
+ }
+ save_parent(field,specification,d)
+ field.specification = specification
+ end
+ specification = field.specification or { }
+ if trace_fields then
+ logs.report("fields","using child choice '%s'",name)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(field.pobj),
+ F = fieldplus(specification),
+ DA = fieldattributes(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ }
+ save_kid(field,specification,d)
+end
+
+function methods.popup(name,specification,variant)
+ methods.choice(name,specification,variant,"PopUp")
+end
+function methods.combo(name,specification,variant)
+ methods.choice(name,specification,variant,"PopUp,Edit")
+end
+
+-- Probably no default appearance needed for first kid and no javascripts for the
+-- parent ... I will look into it when I have to make a complex document.
+
+function methods.check(name,specification,variant)
+ -- no /Opt because (1) it's messy - see pdf spec, (2) it discouples kids and
+ -- contrary to radio there is no way to associate then
+ local field = fields[name]
+ if variant == "copy" or variant == "clone" then
+ logs.report("fields","todo: clones of check fields")
+ end
+ local kind = field.kind
+ local appearance, default = fieldstates(field,true)
+ if not field.pobj then
+ if trace_fields then
+ logs.report("fields","using parent check '%s'",name)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ FT = pdf_btn,
+ DV = default,
+ V = default,
+ AS = default,
+ AP = appearance,
+ H = pdf_n,
+ }
+ save_parent(field,specification,d)
+ field.specification = specification
+ end
+ specification = field.specification or { } -- todo: radio spec
+ if trace_fields then
+ logs.report("fields","using child check '%s'",name)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(field.pobj),
+ F = fieldplus(specification),
+ DA = fieldattributes(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ DV = default,
+ V = default,
+ AS = default,
+ AP = appearance,
+ H = pdf_n,
+ }
+ save_kid(field,specification,d)
+end
+
+function methods.push(name,specification,variant)
+ local field = fields[name]
+ if variant == "copy" or variant == "clone" then
+ logs.report("fields","todo: clones of push fields")
+ end
+ local kind = field.kind
+ if not field.pobj then
+ if trace_fields then
+ logs.report("fields","using parent push '%s'",name)
+ end
+ enhance(specification,"PushButton")
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ T = pdfunicode(specification.title),
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ FT = pdf_btn,
+ AP = fieldappearances(field),
+ H = pdf_p,
+ }
+ save_parent(field,specification,d)
+ field.specification = specification
+ end
+ specification = field.specification or { } -- todo: radio spec
+ if trace_fields then
+ logs.report("fields","using child push '%s'",name)
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(field.pobj),
+ F = fieldplus(specification),
+ DA = fieldattributes(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ AP = fieldappearances(field),
+ H = pdf_p,
+ }
+ save_kid(field,specification,d)
+end
+
+function methods.sub(name,specification,variant)
+ local field = radios[name] or fields[name] or clones[name] -- fields in case of a clone, maybe use dedicated clones
+ local values
+ if variant == "copy" or variant == "clone" then
+ name = field.parent
+ values = field.values -- clone only, copy has nil so same as parent
+ field = radios[name]
+ else
+ values = field.values
+ end
+ local parent = fields[field.parent]
+ if not parent then
+ return
+ end
+ local appearance = fieldstates(field,name,values) -- we need to force the 'On' name
+ local default = radiodefault(parent,field)
+ if not parent.pobj then
+ if trace_fields then
+ logs.report("fields","using parent '%s' of radio '%s' with values '%s' and default '%s'",parent.name,name,parent.values or "?",parent.default or "?")
+ end
+ local specification = parent.specification or { }
+ -- enhance(specification,"Radio,RadiosInUnison")
+ enhance(specification,"RadiosInUnison") -- maybe also PushButton as acrobat does
+ local d = pdfdictionary {
+ T = parent.name,
+ FT = pdf_btn,
+ Rect = pdf_no_rect,
+ F = fieldplus(specification),
+ Ff = fieldflag(specification),
+ H = pdf_n,
+ V = default,
+ }
+ save_parent(parent,specification,d)
+ end
+ if trace_fields then
+ logs.report("fields","using child radio '%s' with values '%s'",name,values or "?")
+ end
+ local d = pdfdictionary {
+ Subtype = pdf_widget,
+ Parent = pdfreference(parent.pobj),
+ F = fieldplus(specification),
+ DA = fieldattributes(specification),
+ OC = fieldlayer(specification),
+ AA = fieldactions(specification),
+ AS = default,
+ AP = appearance,
+ H = pdf_n,
+ }
+ save_kid(parent,specification,d)
+end
diff --git a/tex/context/base/lpdf-grp.lua b/tex/context/base/lpdf-grp.lua
new file mode 100644
index 000000000..ad01e4d4f
--- /dev/null
+++ b/tex/context/base/lpdf-grp.lua
@@ -0,0 +1,68 @@
+if not modules then modules = { } end modules ['lpdf-grp'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+
+local function shade(stype,name,domain,color_a,color_b,n,colorspace,coordinates)
+ local f = pdfdictionary {
+ FunctionType = 2,
+ Domain = pdfarray(domain), -- domain is actually a string
+ C0 = pdfarray(color_a),
+ C1 = pdfarray(color_b),
+ N = tonumber(n),
+ }
+ local s = pdfdictionary {
+ ShadingType = stype,
+ ColorSpace = pdfconstant(colorspace),
+ Function = pdfreference(pdfflushobject(f)),
+ Coords = pdfarray(coordinates),
+ Extend = pdfarray { true, true },
+ }
+ lpdf.adddocumentshade(name,pdfreference(pdfflushobject(s)))
+end
+
+function lpdf.circularshade(name,domain,color_a,color_b,n,colorspace,coordinates)
+ shade(3,name,domain,color_a,color_b,n,colorspace,coordinates)
+end
+
+function lpdf.linearshade(name,domain,color_a,color_b,n,colorspace,coordinates)
+ shade(2,name,domain,color_a,color_b,n,colorspace,coordinates)
+end
+
+function lpdf.colorspec(model,ca,default)
+ if ca and ca > 0 then
+ local cv = colors.value(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return pdfarray { cv[2] }
+ elseif model == 3 then
+ return pdfarray { cv[3],cv[4],cv[5] }
+ elseif model == 4 then
+ return pdfarray { cv[6],cv[7],cv[8],cv[9] }
+ elseif model == 5 then
+ return pdfarray { cv[13] }
+ end
+ end
+ end
+ if default then
+ return default
+ end
+end
diff --git a/tex/context/base/lpdf-ini.lua b/tex/context/base/lpdf-ini.lua
new file mode 100644
index 000000000..e0ffd4052
--- /dev/null
+++ b/tex/context/base/lpdf-ini.lua
@@ -0,0 +1,670 @@
+if not modules then modules = { } end modules ['lpdf-ini'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setmetatable, getmetatable, type, next, tostring, tonumber, rawset = setmetatable, getmetatable, type, next, tostring, tonumber, rawset
+local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string.byte, string.format, string.gsub, table.concat, string.match, string.sub, string.gmatch
+local utfvalues = string.utfvalues
+local texwrite, texset, texsprint, ctxcatcodes = tex.write, tex.set, tex.sprint, tex.ctxcatcodes
+local sind, cosd = math.sind, math.cosd
+local lpegmatch = lpeg.match
+
+local pdfreserveobj = pdf and pdf.reserveobj or function() return 1 end -- for testing
+local pdfimmediateobj = pdf and pdf.immediateobj or function() return 2 end -- for testing
+
+local trace_finalizers = false trackers.register("backend.finalizers", function(v) trace_finalizers = v end)
+local trace_resources = false trackers.register("backend.resources", function(v) trace_resources = v end)
+local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end)
+local trace_detail = false trackers.register("backend.detail", function(v) trace_detail = v end)
+
+lpdf = lpdf or { }
+
+local function tosixteen(str)
+ if not str or str == "" then
+ return "()"
+ else
+ local r = { ""
+ return concat(r)
+ end
+end
+
+lpdf.tosixteen = tosixteen
+
+-- lpeg is some 5 times faster than gsub (in test) on escaping
+
+-- local escapes = {
+-- ["\\"] = "\\\\",
+-- ["/"] = "\\/", ["#"] = "\\#",
+-- ["<"] = "\\<", [">"] = "\\>",
+-- ["["] = "\\[", ["]"] = "\\]",
+-- ["("] = "\\(", [")"] = "\\)",
+-- }
+--
+-- local escaped = lpeg.Cs(lpeg.Cc("(") * (lpeg.S("\\/#<>[]()")/escapes + lpeg.P(1))^0 * lpeg.Cc(")"))
+--
+-- local function toeight(str)
+-- if not str or str == "" then
+-- return "()"
+-- else
+-- return lpegmatch(escaped,str)
+-- end
+-- end
+--
+-- -- no need for escaping .. just use unicode instead
+
+-- \0 \t \n \r \f ( ) [ ] { } / %
+
+local function toeight(str)
+ return "(" .. str .. ")"
+end
+
+lpdf.toeight = toeight
+
+--~ local escaped = lpeg.Cs((lpeg.S("\0\t\n\r\f ()[]{}/%")/"#" + lpeg.P(1))^0)
+--~
+--~ local function cleaned(str)
+--~ return (str and str ~= "" and lpegmatch(escaped,str)) or ""
+--~ end
+--~
+--~ lpdf.cleaned = cleaned -- not public yet
+
+local function merge_t(a,b)
+ local t = { }
+ for k,v in next, a do t[k] = v end
+ for k,v in next, b do t[k] = v end
+ return setmetatable(t,getmetatable(a))
+end
+
+local tostring_a, tostring_d
+
+tostring_d = function(t,contentonly,key)
+ if not next(t) then
+ if contentonly then
+ return ""
+ else
+ return "<< >>"
+ end
+ else
+ local r = { }
+ for k, v in next, t do
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("/%s %s",k,toeight(v))
+ elseif tv == "unicode" then
+ r[#r+1] = format("/%s %s",k,tosixteen(v))
+ elseif tv == "table" then
+ local mv = getmetatable(v)
+ if mv and mv.__lpdftype then
+ r[#r+1] = format("/%s %s",k,tostring(v))
+ elseif v[1] then
+ r[#r+1] = format("/%s %s",k,tostring_a(v))
+ else
+ r[#r+1] = format("/%s %s",k,tostring_d(v))
+ end
+ else
+ r[#r+1] = format("/%s %s",k,tostring(v))
+ end
+ end
+ if contentonly then
+ return concat(r, " ")
+ elseif key then
+ return format("/%s << %s >>", key, concat(r, " "))
+ else
+ return format("<< %s >>", concat(r, " "))
+ end
+ end
+end
+
+tostring_a = function(t,contentonly,key)
+ if #t == 0 then
+ if contentonly then
+ return ""
+ else
+ return "[ ]"
+ end
+ else
+ local r = { }
+ for k, v in next, t do
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = toeight(v)
+ elseif tv == "unicode" then
+ r[#r+1] = tosixteen(v)
+ elseif tv == "table" then
+ local mv = getmetatable(v)
+ local mt = mv and mv.__lpdftype
+ if mt then
+ r[#r+1] = tostring(v)
+ elseif v[1] then
+ r[#r+1] = tostring_a(v)
+ else
+ r[#r+1] = tostring_d(v)
+ end
+ else
+ r[#r+1] = tostring(v)
+ end
+ end
+ if contentonly then
+ return concat(r, " ")
+ elseif key then
+ return format("/%s [ %s ]", key, concat(r, " "))
+ else
+ return format("[ %s ]", concat(r, " "))
+ end
+ end
+end
+
+local tostring_x = function(t) return concat(t, " ") end
+local tostring_s = function(t) return toeight(t[1]) end
+local tostring_u = function(t) return tosixteen(t[1]) end
+local tostring_n = function(t) return tostring(t[1]) end -- tostring not needed
+local tostring_c = function(t) return t[1] end -- already prefixed (hashed)
+local tostring_z = function() return "null" end
+local tostring_t = function() return "true" end
+local tostring_f = function() return "false" end
+local tostring_r = function(t) return t[1] .. " 0 R" end
+
+local tostring_v = function(t)
+ local s = t[1]
+ if type(s) == "table" then
+ return concat(s,"")
+ else
+ return s
+ end
+end
+
+local function value_x(t) return t end -- the call is experimental
+local function value_s(t,key) return t[1] end -- the call is experimental
+local function value_u(t,key) return t[1] end -- the call is experimental
+local function value_n(t,key) return t[1] end -- the call is experimental
+local function value_c(t) return sub(t[1],2) end -- the call is experimental
+local function value_d(t) return tostring_d(t,true,key) end -- the call is experimental
+local function value_a(t) return tostring_a(t,true,key) end -- the call is experimental
+local function value_z() return nil end -- the call is experimental
+local function value_t(t) return t.value or true end -- the call is experimental
+local function value_f(t) return t.value or false end -- the call is experimental
+local function value_r() return t[1] end -- the call is experimental
+local function value_v() return t[1] end -- the call is experimental
+
+local function add_x(t,k,v) rawset(t,k,tostring(v)) end
+
+local mt_x = { __lpdftype = "stream", __tostring = tostring_x, __call = value_x, __newindex = add_x }
+local mt_d = { __lpdftype = "dictionary", __tostring = tostring_d, __call = value_d }
+local mt_a = { __lpdftype = "array", __tostring = tostring_a, __call = value_a }
+local mt_u = { __lpdftype = "unicode", __tostring = tostring_u, __call = value_u }
+local mt_s = { __lpdftype = "string", __tostring = tostring_s, __call = value_s }
+local mt_n = { __lpdftype = "number", __tostring = tostring_n, __call = value_n }
+local mt_c = { __lpdftype = "constant", __tostring = tostring_c, __call = value_c }
+local mt_z = { __lpdftype = "null", __tostring = tostring_z, __call = value_z }
+local mt_t = { __lpdftype = "true", __tostring = tostring_t, __call = value_t }
+local mt_f = { __lpdftype = "false", __tostring = tostring_f, __call = value_f }
+local mt_r = { __lpdftype = "reference", __tostring = tostring_r, __call = value_r }
+local mt_v = { __lpdftype = "verbose", __tostring = tostring_v, __call = value_v }
+
+local function pdfstream(t) -- we need to add attrbutes
+ if t then
+ for i=1,#t do
+ t[i] = tostring(t[i])
+ end
+ end
+ return setmetatable(t or { },mt_x)
+end
+
+local function pdfdictionary(t)
+ return setmetatable(t or { },mt_d)
+end
+
+local function pdfarray(t)
+ if type(t) == "string" then
+ return setmetatable({ t },mt_a)
+ else
+ return setmetatable(t or { },mt_a)
+ end
+end
+
+local function pdfstring(str,default)
+ return setmetatable({ str or default or "" },mt_s)
+end
+
+local function pdfunicode(str,default)
+ return setmetatable({ str or default or "" },mt_u)
+end
+
+local cache = { } -- can be weak
+
+local function pdfnumber(n,default) -- 0-10
+ n = n or default
+ local c = cache[n]
+ if not c then
+ c = setmetatable({ n },mt_n)
+ -- cache[n] = c -- too many numbers
+ end
+ return c
+end
+
+for i=-1,9 do cache[i] = pdfnumber(i) end
+
+local cache = { } -- can be weak
+
+local forbidden, replacements = "\0\t\n\r\f ()[]{}/%%#\\", { } -- table faster than function
+
+for s in gmatch(forbidden,".") do
+ replacements[s] = format("#%02x",byte(s))
+end
+
+local escaped = lpeg.Cs(lpeg.Cc("/") * (lpeg.S(forbidden)/replacements + lpeg.P(1))^0)
+
+local function pdfconstant(str,default)
+ str = str or default or ""
+ local c = cache[str]
+ if not c then
+ -- c = setmetatable({ "/" .. str },mt_c)
+ c = setmetatable({ lpegmatch(escaped,str) },mt_c)
+ cache[str] = c
+ end
+ return c
+end
+
+local p_null = { } setmetatable(p_null, mt_z)
+local p_true = { } setmetatable(p_true, mt_t)
+local p_false = { } setmetatable(p_false,mt_f)
+
+local function pdfnull()
+ return p_null
+end
+
+--~ print(pdfboolean(false),pdfboolean(false,false),pdfboolean(false,true))
+--~ print(pdfboolean(true),pdfboolean(true,false),pdfboolean(true,true))
+--~ print(pdfboolean(nil,true),pdfboolean(nil,false))
+
+local function pdfboolean(b,default)
+ if type(b) == "boolean" then
+ return b and p_true or p_false
+ else
+ return default and p_true or p_false
+ end
+end
+
+local function pdfreference(r)
+ return setmetatable({ r or 0 },mt_r)
+end
+
+local function pdfverbose(t) -- maybe check for type
+ return setmetatable({ t or "" },mt_v)
+end
+
+lpdf.stream = pdfstream
+lpdf.dictionary = pdfdictionary
+lpdf.array = pdfarray
+lpdf.string = pdfstring
+lpdf.unicode = pdfunicode
+lpdf.number = pdfnumber
+lpdf.constant = pdfconstant
+lpdf.null = pdfnull
+lpdf.boolean = pdfboolean
+lpdf.reference = pdfreference
+lpdf.verbose = pdfverbose
+
+-- n = pdf.obj(n, str)
+-- n = pdf.obj(n, "file", filename)
+-- n = pdf.obj(n, "stream", streamtext, attrtext)
+-- n = pdf.obj(n, "streamfile", filename, attrtext)
+
+-- we only use immediate objects
+
+-- todo: tracing
+
+local names, cache = { }, { }
+
+function lpdf.reserveobject(name)
+ local r = pdfreserveobj()
+ if name then
+ names[name] = r
+ if trace_objects then
+ logs.report("backends", "reserving object number %s under name '%s'",r,name)
+ end
+ elseif trace_objects then
+ logs.report("backends", "reserving object number %s",r)
+ end
+ return r
+end
+
+--~ local pdfreserveobject = lpdf.reserveobject
+
+function lpdf.flushobject(name,data)
+ if data then
+ name = names[name] or name
+ if name then
+ if trace_objects then
+ if trace_detail then
+ logs.report("backends", "flushing object data to reserved object with name '%s' -> %s",name,tostring(data))
+ else
+ logs.report("backends", "flushing object data to reserved object with name '%s'",name)
+ end
+ end
+ return pdfimmediateobj(name,tostring(data))
+ else
+ if trace_objects then
+ if trace_detail then
+ logs.report("backends", "flushing object data to reserved object with number %s -> %s",name,tostring(data))
+ else
+ logs.report("backends", "flushing object data to reserved object with number %s",name)
+ end
+ end
+ return pdfimmediateobj(tostring(data))
+ end
+ else
+ if trace_objects and trace_detail then
+ logs.report("backends", "flushing object data -> %s",tostring(name))
+ end
+ return pdfimmediateobj(tostring(name))
+ end
+end
+
+function lpdf.sharedobj(content)
+ local r = cache[content]
+ if not r then
+ r = pdfreference(pdfimmediateobj(content))
+ cache[content] = r
+ end
+ return r
+end
+
+--~ local d = lpdf.dictionary()
+--~ local e = lpdf.dictionary { ["e"] = "abc", x = lpdf.dictionary { ["f"] = "ABC" } }
+--~ local f = lpdf.dictionary { ["f"] = "ABC" }
+--~ local a = lpdf.array { lpdf.array { lpdf.string("xxx") } }
+
+--~ print(a)
+--~ os.exit()
+
+--~ d["test"] = lpdf.string ("test")
+--~ d["more"] = "more"
+--~ d["bool"] = true
+--~ d["numb"] = 1234
+--~ d["oeps"] = lpdf.dictionary { ["hans"] = "ton" }
+--~ d["whow"] = lpdf.array { lpdf.string("ton") }
+
+--~ a[#a+1] = lpdf.string("xxx")
+--~ a[#a+1] = lpdf.string("yyy")
+
+--~ d.what = a
+
+--~ print(e)
+
+--~ local d = lpdf.dictionary()
+--~ d["abcd"] = { 1, 2, 3, "test" }
+--~ print(d)
+--~ print(d())
+
+--~ local d = lpdf.array()
+--~ d[#d+1] = 1
+--~ d[#d+1] = 2
+--~ d[#d+1] = 3
+--~ d[#d+1] = "test"
+--~ print(d)
+
+--~ local d = lpdf.array()
+--~ d[#d+1] = { 1, 2, 3, "test" }
+--~ print(d)
+
+--~ local d = lpdf.array()
+--~ d[#d+1] = { a=1, b=2, c=3, d="test" }
+--~ print(d)
+
+--~ local s = lpdf.constant("xx")
+--~ print(s) -- fails somehow
+--~ print(s()) -- fails somehow
+
+--~ local s = lpdf.boolean(false)
+--~ s.value = true
+--~ print(s)
+--~ print(s())
+
+-- three priority levels, default=2
+
+local pagefinalizers, documentfinalizers = { { }, { }, { } }, { { }, { }, { } }
+
+local pageresources, pageattributes, pagesattributes
+
+local function resetpageproperties()
+ pageresources = pdfdictionary()
+ pageattributes = pdfdictionary()
+ pagesattributes = pdfdictionary()
+end
+
+local function setpageproperties()
+--~ texset("global", "pdfpageresources", pageresources ())
+--~ texset("global", "pdfpageattr", pageattributes ())
+--~ texset("global", "pdfpagesattr", pagesattributes())
+ pdf.pageresources = pageresources ()
+ pdf.pageattributes = pageattributes ()
+ pdf.pagesattributes = pagesattributes()
+end
+
+function lpdf.addtopageresources (k,v) pageresources [k] = v end
+function lpdf.addtopageattributes (k,v) pageattributes [k] = v end
+function lpdf.addtopagesattributes(k,v) pagesattributes[k] = v end
+
+local function set(where,f,when,what)
+ when = when or 2
+ local w = where[when]
+ w[#w+1] = f
+ if trace_finalizers then
+ logs.report("backend","%s set: [%s,%s]",what,when,#w)
+ end
+end
+
+local function run(where,what)
+ for i=1,#where do
+ local w = where[i]
+ for j=1,#w do
+ if trace_finalizers then
+ logs.report("backend","%s finalizer: [%s,%s]",what,i,j)
+ end
+ w[j]()
+ end
+ end
+end
+
+function lpdf.registerpagefinalizer(f,when)
+ set(pagefinalizers,f,when,"page")
+end
+
+function lpdf.registerdocumentfinalizer(f,when)
+ set(documentfinalizers,f,when,"document")
+end
+
+function lpdf.finalizepage()
+ if not environment.initex then
+ resetpageproperties()
+ run(pagefinalizers,"page")
+ setpageproperties()
+ end
+end
+
+function lpdf.finalizedocument()
+ if not environment.initex then
+ run(documentfinalizers,"document")
+ function lpdf.finalizedocument()
+ logs.report("backend","serious error: the document is finalized multiple times")
+ function lpdf.finalizedocument() end
+ end
+ end
+end
+
+-- some minimal tracing, handy for checking the order
+
+local function trace_set(what,key)
+ if trace_resources then
+ logs.report("backend", "setting key '%s' in '%s'",key,what)
+ end
+end
+local function trace_flush(what)
+ if trace_resources then
+ logs.report("backend", "flushing '%s'",what)
+ end
+end
+
+lpdf.protectresources = true
+
+local catalog, info, names = pdfdictionary(), pdfdictionary(), pdfdictionary()
+
+local function flushcatalog() if not environment.initex then trace_flush("catalog") pdf.catalog = catalog() end end
+local function flushinfo () if not environment.initex then trace_flush("info") pdf.info = info () end end
+local function flushnames () if not environment.initex then trace_flush("names") pdf.names = names () end end
+
+function lpdf.addtocatalog(k,v) if not (lpdf.protectresources and catalog[k]) then trace_set("catalog",k) catalog[k] = v end end
+function lpdf.addtoinfo (k,v) if not (lpdf.protectresources and info [k]) then trace_set("info", k) info [k] = v end end
+function lpdf.addtonames (k,v) if not (lpdf.protectresources and names [k]) then trace_set("names", k) names [k] = v end end
+
+local dummy = pdfreserveobj() -- else bug in hvmd due so some internal luatex conflict
+
+local r_extgstates, d_extgstates = pdfreserveobj(), pdfdictionary() local p_extgstates = pdfreference(r_extgstates)
+local r_colorspaces, d_colorspaces = pdfreserveobj(), pdfdictionary() local p_colorspaces = pdfreference(r_colorspaces)
+local r_patterns, d_patterns = pdfreserveobj(), pdfdictionary() local p_patterns = pdfreference(r_patterns)
+local r_shades, d_shades = pdfreserveobj(), pdfdictionary() local p_shades = pdfreference(r_shades)
+
+local function checkextgstates () if next(d_extgstates ) then lpdf.addtopageresources("ExtGState", p_extgstates ) end end
+local function checkcolorspaces() if next(d_colorspaces) then lpdf.addtopageresources("ColorSpace",p_colorspaces) end end
+local function checkpatterns () if next(d_patterns ) then lpdf.addtopageresources("Pattern", p_patterns ) end end
+local function checkshades () if next(d_shades ) then lpdf.addtopageresources("Shading", p_shades ) end end
+
+local function flushextgstates () if next(d_extgstates ) then trace_flush("extgstates") pdfimmediateobj(r_extgstates, tostring(d_extgstates )) end end
+local function flushcolorspaces() if next(d_colorspaces) then trace_flush("colorspaces") pdfimmediateobj(r_colorspaces,tostring(d_colorspaces)) end end
+local function flushpatterns () if next(d_patterns ) then trace_flush("patterns") pdfimmediateobj(r_patterns, tostring(d_patterns )) end end
+local function flushshades () if next(d_shades ) then trace_flush("shades") pdfimmediateobj(r_shades, tostring(d_shades )) end end
+
+local collected = pdfdictionary {
+ ExtGState = p_extgstates,
+ ColorSpace = p_colorspaces,
+ Pattern = p_patterns,
+ Shading = p_shades,
+} ; collected = collected()
+
+function lpdf.collectedresources()
+ tex.sprint(tex.ctxcatcodes,collected)
+end
+
+function lpdf.adddocumentextgstate (k,v) d_extgstates [k] = v end
+function lpdf.adddocumentcolorspace(k,v) d_colorspaces[k] = v end
+function lpdf.adddocumentpattern (k,v) d_patterns [k] = v end
+function lpdf.adddocumentshade (k,v) d_shades [k] = v end
+
+lpdf.registerdocumentfinalizer(flushextgstates,3)
+lpdf.registerdocumentfinalizer(flushcolorspaces,3)
+lpdf.registerdocumentfinalizer(flushpatterns,3)
+lpdf.registerdocumentfinalizer(flushshades,3)
+
+lpdf.registerdocumentfinalizer(flushcatalog,3)
+lpdf.registerdocumentfinalizer(flushinfo,3)
+lpdf.registerdocumentfinalizer(flushnames,3)
+
+lpdf.registerpagefinalizer(checkextgstates,3)
+lpdf.registerpagefinalizer(checkcolorspaces,3)
+lpdf.registerpagefinalizer(checkpatterns,3)
+lpdf.registerpagefinalizer(checkshades,3)
+
+-- in strc-bkm: lpdf.registerdocumentfinalizer(function() structure.bookmarks.place() end,1)
+
+function lpdf.rotationcm(a)
+ local s, c = sind(a), cosd(a)
+ texwrite(format("%s %s %s %s 0 0 cm",c,s,-s,c))
+end
+
+-- ! -> universaltime
+
+local timestamp = os.date("%Y-%m-%dT%X") .. os.timezone(true)
+
+function lpdf.timestamp()
+ return timestamp
+end
+
+function lpdf.pdftimestamp(str)
+ local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$")
+ return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm)
+end
+
+function lpdf.id()
+ return format("%s.%s",tex.jobname,timestamp)
+end
+
+function lpdf.checkedkey(t,key,kind)
+ local pn = t[key]
+ if pn then
+ local tn = type(pn)
+ if tn == kind then
+ if kind == "string" then
+ return pn ~= "" and pn
+ elseif kind == "table" then
+ return next(pn) and pn
+ else
+ return pn
+ end
+ elseif tn == "string" and kind == "number" then
+ return tonumber(pn)
+ end
+ end
+end
+
+function lpdf.checkedvalue(value,kind) -- code not shared
+ if value then
+ local tv = type(value)
+ if tv == kind then
+ if kind == "string" then
+ return value ~= "" and value
+ elseif kind == "table" then
+ return next(value) and value
+ else
+ return value
+ end
+ elseif tv == "string" and kind == "number" then
+ return tonumber(value)
+ end
+ end
+end
+
+function lpdf.limited(n,min,max,default)
+ if not n then
+ return default
+ else
+ n = tonumber(n)
+ if not n then
+ return default
+ elseif n > max then
+ return max
+ elseif n < min then
+ return min
+ else
+ return n
+ end
+ end
+end
+
+-- lpdf.addtoinfo("ConTeXt.Version", tex.contextversiontoks)
+-- lpdf.addtoinfo("ConTeXt.Time", os.date("%Y.%m.%d %H:%M")) -- :%S
+-- lpdf.addtoinfo("ConTeXt.Jobname", tex.jobname)
+-- lpdf.addtoinfo("ConTeXt.Url", "www.pragma-ade.com")
+
+-- saves definitions later on
+
+backends = backends or { }
+backends.pdf = backends.pdf or {
+ comment = "backend for directly generating pdf output",
+ nodeinjections = { },
+ codeinjections = { },
+ registrations = { },
+ helpers = { },
+}
diff --git a/tex/context/base/lpdf-ini.mkiv b/tex/context/base/lpdf-ini.mkiv
new file mode 100644
index 000000000..7c7dce3ef
--- /dev/null
+++ b/tex/context/base/lpdf-ini.mkiv
@@ -0,0 +1,271 @@
+%D \module
+%D [ file=lpdf-ini,
+%D version=2009.04.15,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=PDF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 / PDF}
+
+\registerctxluafile{lpdf-ini}{1.001}
+\registerctxluafile{lpdf-xmp}{1.001}
+\registerctxluafile{lpdf-nod}{1.001}
+%registerctxluafile{lpdf-col}{1.001} % will be loaded later
+\registerctxluafile{lpdf-mis}{1.001}
+\registerctxluafile{lpdf-ano}{1.001}
+\registerctxluafile{lpdf-ren}{1.001}
+\registerctxluafile{lpdf-grp}{1.001}
+\registerctxluafile{lpdf-wid}{1.001}
+\registerctxluafile{lpdf-fld}{1.001}
+\registerctxluafile{lpdf-u3d}{1.001}
+\registerctxluafile{lpdf-swf}{1.001}
+
+\unprotect
+
+% for the moment here
+
+%D \macros
+%D {doovalbox}
+%D
+%D Drawing frames with round corners is inherited from the
+%D main module.
+%D
+%D For drawing ovals we use quite raw \PDF\ code. The next
+%D implementation does not differ that much from the one
+%D implemented in the \POSTSCRIPT\ driver. This code is
+%D somewhat obsolete as we now have metapost embedded.
+
+\def\doPDFovalcalc#1#2#3%
+ {\PointsToBigPoints{\dimexpr#1+#2\relax}#3}
+
+\def\doovalbox#1#2#3#4#5#6#7#8% todo: \scratchdimen/\scatchbox
+ {\forcecolorhack
+ \bgroup
+ \dimen0=#4\divide\dimen0 \plustwo
+ \doPDFovalcalc{0pt}{+\dimen0}\xmin
+ \doPDFovalcalc{#1}{-\dimen0}\xmax
+ \doPDFovalcalc{#2}{-\dimen0}\ymax
+ \doPDFovalcalc{-#3}{+\dimen0}\ymin
+ \advance\dimen0 by #5%
+ \doPDFovalcalc{0pt}{+\dimen0}\xxmin
+ \doPDFovalcalc{#1}{-\dimen0}\xxmax
+ \doPDFovalcalc{#2}{-\dimen0}\yymax
+ \doPDFovalcalc{-#3}{+\dimen0}\yymin
+ \doPDFovalcalc{#4}{\zeropoint}\stroke
+ \doPDFovalcalc{#5}{\zeropoint}\radius
+ \edef\dostroke{#6}%
+ \edef\dofill{#7}%
+ \edef\mode{\number#8 \space}%
+ % no \ifcase, else \relax in pdfcode
+ \setbox\scratchbox\hbox
+ {\ifnum\dostroke\dofill>\zerocount
+ \pdfliteral
+ {q
+ \stroke\space w
+ \ifcase\mode
+ \xxmin\space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or % 1
+ \xxmin\space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \ymax \space l
+ \xmin \space \ymax \space l
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or % 2
+ \xxmin\space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \ymax \space l
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or % 3
+ \xmin \space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \ymin \space l
+ h
+ \or % 4
+ \xmin \space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xmin \space \ymax \space l
+ \xmin \space \ymin\space l
+ h
+ \or % 5
+ \xmin \space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax\space \ymax \space y
+ \xmin \space \ymax \space l
+ \xmin \space \ymin \space l
+ h
+ \or % 6
+ \xmin \space \ymin \space m
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \ymax \space l
+ \xmin \space \ymax \space l
+ \xmin \space \ymin \space l
+ h
+ \or
+ \xxmin\space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \ymax \space l
+ \xmin \space \ymax \space l
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ h
+ \or
+ \xmin \space \ymin \space m
+ \xmax \space \ymin \space l
+ \xmax \space \ymax \space l
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \ymin \space l
+ h
+ \or % 9 top open
+ \xmin \space \ymax \space m
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ \xxmax\space \ymin \space l
+ \xmax \space \ymin \space \xmax \space \yymin\space y
+ \xmax \space \ymax \space l
+ \or % 10 right open
+ \xmax \space \ymax \space m
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \yymin\space l
+ \xmin \space \ymin \space \xxmin\space \ymin \space y
+ \xmax\space \ymin \space l
+ \or % 11 bottom open
+ \xmax \space \ymin \space m
+ \xmax \space \yymax\space l
+ \xmax \space \ymax \space \xxmax \space \ymax\space y
+ \xxmin\space \ymax \space l
+ \xmin \space \ymax \space \xmin \space \yymax\space y
+ \xmin \space \ymin \space l
+ \or % 12 left open
+ \xmin \space \ymax \space m
+ \xxmax\space \ymax \space l
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax \space \yymin\space l
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xmin \space \ymin \space l
+ \or % 13
+ \xmin \space \ymax \space m
+ \xxmax\space \ymax \space l
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax\space \ymin \space l
+ \or % 14
+ \xmax \space \ymax \space m
+ \xmax \space \yymin\space l
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xmin \space \ymin \space l
+ \or % 15
+ \xmax \space \ymin \space m
+ \xxmin\space \ymin \space l
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \xmin \space \ymax \space l
+ \or % 16
+ \xmin \space \ymin \space m
+ \xmin \space \yymax\space l
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \xmax \space \ymax \space l
+ \or % 17
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \or % 18
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \or % 19
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \or % 20
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 21
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 22
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \or % 23
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \or % 24
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 25
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 26
+ \xmax \space \yymin\space m
+ \xmax \space \ymin \space \xxmax\space \ymin \space y
+ \xmin \space \yymax\space m
+ \xmin \space \ymax \space \xxmin\space \ymax \space y
+ \or % 27
+ \xxmax\space \ymax \space m
+ \xmax \space \ymax \space \xmax \space \yymax\space y
+ \xxmin\space \ymin \space m
+ \xmin \space \ymin \space \xmin \space \yymin\space y
+ \or % 28
+ \fi
+ \ifnum\mode>8
+ S
+ \else
+ \ifnum\dostroke=\plusone S \fi
+ \ifnum\dofill =\plusone f \fi
+ \fi
+ Q}%
+ \fi}%
+ \wd\scratchbox#1\ht\scratchbox#2\dp\scratchbox#3\box\scratchbox
+ \egroup}
+
+\unexpanded\def\pdfactualtext#1#2%
+ {\pdfliteral direct{/Span <> BDC}%
+ #1%
+ \pdfliteral direct{EMC}}
+
+% \starttext
+% text \pdfactualtext{Meier}{Müller} text
+% \stoptext
+
+\protect \endinput
diff --git a/tex/context/base/lpdf-mis.lua b/tex/context/base/lpdf-mis.lua
new file mode 100644
index 000000000..a68c7b487
--- /dev/null
+++ b/tex/context/base/lpdf-mis.lua
@@ -0,0 +1,292 @@
+if not modules then modules = { } end modules ['lpdf-mis'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Although we moved most pdf handling to the lua end, we didn't change
+-- the overall approach. For instance we share all resources i.e. we
+-- don't make subsets for each xform or page. The current approach is
+-- quite efficient. A big difference between MkII and MkIV is that we
+-- now use forward references. In this respect the MkII code shows that
+-- it evolved over a long period, when backends didn't provide forward
+-- referencing and references had to be tracked in multiple passes. Of
+-- course there are a couple of more changes.
+
+local next, tostring = next, tostring
+local format = string.format
+local texsprint, texset = tex.sprint, tex.set
+local ctxcatcodes = tex.ctxcatcodes
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local copy_node = node.copy
+
+local pdfliteral, register = nodes.pdfliteral, nodes.register
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfboolean = lpdf.boolean
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfverbose = lpdf.verbose
+local pdfstring = lpdf.string
+local pdfflushobject = lpdf.flushobject
+
+local pdfimmediateobj = pdf.immediateobj
+
+local tobasepoints = number.tobasepoints
+local variables = interfaces.variables
+
+--
+
+local positive = register(pdfliteral("/GSpositive gs"))
+local negative = register(pdfliteral("/GSnegative gs"))
+local overprint = register(pdfliteral("/GSoverprint gs"))
+local knockout = register(pdfliteral("/GSknockout gs"))
+
+local function initializenegative()
+ local a = pdfarray { 0, 1 }
+ local g = pdfconstant("ExtGState")
+ local d = pdfdictionary {
+ FunctionType = 4,
+ Range = a,
+ Domain = a,
+ }
+ local negative = pdfdictionary { Type = g, TR = pdfreference(pdf.immediateobj("stream","1 exch sub",d())) }
+ local positive = pdfdictionary { Type = g, TR = pdfconstant("Identity") }
+ lpdf.adddocumentextgstate("GSnegative", pdfreference(pdfflushobject(negative)))
+ lpdf.adddocumentextgstate("GSPositive", pdfreference(pdfflushobject(positive)))
+ initializenegative = nil
+end
+
+local function initializeoverprint()
+ local g = pdfconstant("ExtGState")
+ local knockout = pdfdictionary { Type = g, OP = false, OPM = 0 }
+ local overprint = pdfdictionary { Type = g, OP = true, OPM = 1 }
+ lpdf.adddocumentextgstate("GSknockout", pdfreference(pdfflushobject(knockout)))
+ lpdf.adddocumentextgstate("GSoverprint", pdfreference(pdfflushobject(overprint)))
+ initializeoverprint = nil
+end
+
+function nodeinjections.overprint()
+ if initializeoverprint then initializeoverprint() end
+ return copy_node(overprint)
+end
+function nodeinjections.knockout ()
+ if initializeoverprint then initializeoverprint() end
+ return copy_node(knockout)
+end
+
+function nodeinjections.positive()
+ if initializenegative then initializenegative() end
+ return copy_node(positive)
+end
+function nodeinjections.negative()
+ if initializenegative then initializenegative() end
+ return copy_node(negative)
+end
+
+--
+
+function codeinjections.addtransparencygroup()
+ -- png: /CS /DeviceRGB /I true
+ local d = pdfdictionary {
+ S = pdfconstant("Transparency"),
+ I = true,
+ K = true,
+ }
+ lpdf.registerpagefinalizer(function() lpdf.addtopageattributes("Group",d) end) -- hm
+end
+
+-- actions (todo: store and update when changed)
+
+local openpage, closepage, opendocument, closedocument
+
+function codeinjections.flushdocumentactions(open,close)
+ opendocument, closedocument = open, close
+end
+
+function codeinjections.flushpageactions(open,close)
+ openpage, closepage = open, close
+end
+
+local function flushdocumentactions()
+ if opendocument then
+ lpdf.addtocatalog("OpenAction",lpdf.pdfaction(opendocument))
+ end
+ if closedocument then
+ lpdf.addtocatalog("CloseAction",lpdf.pdfaction(closedocument))
+ end
+end
+
+local function flushpageactions()
+ if openpage or closepage then
+ local d = pdfdictionary()
+ if openpage then
+ d.O = lpdf.pdfaction(openpage)
+ end
+ if closepage then
+ d.C = lpdf.pdfaction(closepage)
+ end
+ lpdf.addtopageattributes("AA",d)
+ end
+end
+
+lpdf.registerpagefinalizer(flushpageactions)
+lpdf.registerdocumentfinalizer(flushdocumentactions)
+
+--- info
+
+function codeinjections.setupidentity(specification)
+ local title = specification.title or ""
+ if title ~= "" then
+ lpdf.addtoinfo("Title", pdfunicode(title), title)
+ end
+ local subject = specification.subject or ""
+ if subject ~= "" then
+ lpdf.addtoinfo("Subject", pdfunicode(subject), subject)
+ end
+ local author = specification.author or ""
+ if author ~= "" then
+ lpdf.addtoinfo("Author", pdfunicode(author), author) -- '/Author' in /Info, 'Creator' in XMP
+ end
+ local creator = specification.creator or ""
+ if creator ~= "" then
+ lpdf.addtoinfo("Creator", pdfunicode(creator), creator) -- '/Creator' in /Info, 'CreatorTool' in XMP
+ end
+ lpdf.addtoinfo("CreationDate", pdfstring(lpdf.pdftimestamp(lpdf.timestamp())))
+ local date = specification.date or ""
+ local pdfdate = lpdf.pdftimestamp(date)
+ if pdfdate then
+ lpdf.addtoinfo("ModDate", pdfstring(pdfdate), date)
+ else
+ -- users should enter the date in 2010-01-19T23:27:50+01:00 format
+ -- and if not provided that way we use the creation time instead
+ date = lpdf.timestamp()
+ lpdf.addtoinfo("ModDate", pdfstring(lpdf.pdftimestamp(date)), date)
+ end
+ local keywords = specification.keywords or ""
+ if keywords ~= "" then
+ keywords = string.gsub(keywords, "[%s,]+", " ")
+ lpdf.addtoinfo("Keywords",pdfunicode(keywords), keywords)
+ end
+ local id = lpdf.id()
+ lpdf.addtoinfo("ID", pdfstring(id), id) -- needed for pdf/x
+end
+
+local function flushjavascripts()
+ local t = javascripts.flushpreambles()
+ if #t > 0 then
+ local a = pdfarray()
+ local pdf_javascript = pdfconstant("JavaScript")
+ for i=1,#t do
+ local name, script = t[i][1], t[i][2]
+ local j = pdfdictionary {
+ S = pdf_javascript,
+ JS = pdfreference(pdfimmediateobj("stream",script)),
+ }
+ a[#a+1] = pdfstring(name)
+ a[#a+1] = pdfreference(pdfflushobject(j))
+ end
+ lpdf.addtonames("JavaScript",pdfreference(pdfflushobject(pdfdictionary{ Names = a })))
+ end
+end
+
+lpdf.registerdocumentfinalizer(flushjavascripts)
+
+-- -- --
+
+local pagespecs = {
+ [variables.max] = { "FullScreen", false, false },
+ [variables.bookmark] = { "UseOutlines", false, false },
+ [variables.fit] = { "UseNone", false, true },
+ [variables.doublesided] = { "UseNone", "TwoColumnRight", true },
+ [variables.singlesided] = { "UseNone", false, false },
+ [variables.default] = { "UseNone", "auto", false },
+ [variables.auto] = { "UseNone", "auto", false },
+ [variables.none] = { false, false, false },
+}
+
+local pagespec, topoffset, leftoffset, height, width, doublesided = "default", 0, 0, 0, 0, false
+
+function codeinjections.setupcanvas(specification)
+ local paperheight = specification.paperheight
+ local paperwidth = specification.paperwidth
+ local paperdouble = specification.doublesided
+ if paperheight then
+ texset('global','pdfpageheight',paperheight)
+ end
+ if paperwidth then
+ texset('global','pdfpagewidth',paperwidth)
+ end
+ pagespec = specification.mode or pagespec
+ topoffset = specification.topoffset or 0
+ leftoffset = specification.leftoffset or 0
+ height = specification.height or tex.pdfpageheight
+ width = specification.width or tex.pdfpagewidth
+ if paperdouble ~= nil then
+ doublesided = paperdouble
+ end
+end
+
+local function documentspecification()
+ local spec = pagespecs[pagespec] or pagespecs[variables.default]
+ if spec then
+ local mode, layout, fit = spec[1], spec[2], spec[3]
+ if layout == variables.auto then
+ if doublesided then
+ spec = pagespecs[variables.doublesided] -- to be checked voor interfaces
+ if spec then
+ mode, layout, fit = spec[1], spec[2], spec[3]
+ end
+ else
+ layout = false
+ end
+ end
+ mode = mode and pdfconstant(mode)
+ layout = layout and pdfconstant(layout)
+ fit = fit and pdfdictionary { FitWindow = true }
+ if layout then
+ lpdf.addtocatalog("PageLayout",layout)
+ end
+ if mode then
+ lpdf.addtocatalog("PageMode",mode)
+ end
+ if fit then
+ lpdf.addtocatalog("ViewerPreferences",fit)
+ end
+ lpdf.addtoinfo ("Trapped", pdfconstant("False")) -- '/Trapped' in /Info, 'Trapped' in XMP
+ lpdf.addtocatalog("Version", pdfconstant(format("1.%s",tex.pdfminorversion)))
+ end
+end
+
+-- temp hack: the mediabox is not under our control and has a precision of 4 digits
+
+local factor = number.dimenfactors.bp
+
+local function boxvalue(n) -- we could share them
+ return pdfverbose(format("%0.4f",factor * n))
+end
+
+local function pagespecification()
+ local pageheight = tex.pdfpageheight
+ local box = pdfarray { -- can be cached
+ boxvalue(leftoffset),
+ boxvalue(pageheight-topoffset-height),
+ boxvalue(width-leftoffset),
+ boxvalue(pageheight-topoffset),
+ }
+ lpdf.addtopageattributes("CropBox",box) -- mandate for rendering
+ lpdf.addtopageattributes("TrimBox",box) -- mandate for pdf/x
+ -- lpdf.addtopageattributes("BleedBox",box)
+ -- lpdf.addtopageattributes("ArtBox",box)
+end
+
+lpdf.registerpagefinalizer(pagespecification)
+lpdf.registerdocumentfinalizer(documentspecification)
diff --git a/tex/context/base/lpdf-nod.lua b/tex/context/base/lpdf-nod.lua
new file mode 100644
index 000000000..0ae900123
--- /dev/null
+++ b/tex/context/base/lpdf-nod.lua
@@ -0,0 +1,53 @@
+if not modules then modules = { } end modules ['lpdf-nod'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local copy_node, new_node = node.copy, node.new
+
+local pdfliteral = nodes.register(new_node("whatsit", 8)) pdfliteral.mode = 1
+local pdfdest = nodes.register(new_node("whatsit",19)) pdfdest.named_id = 1 -- xyz_zoom untouched
+local pdfannot = nodes.register(new_node("whatsit",15))
+
+local variables = interfaces.variables
+
+local views = { -- beware, we do support the pdf keys but this is *not* official
+ xyz = 0, [variables.standard] = 0,
+ fit = 1, [variables.fit] = 1,
+ fith = 2, [variables.width] = 2,
+ fitv = 3, [variables.height] = 3,
+ fitb = 4,
+ fitbh = 5, [variables.minwidth] = 5,
+ fitbv = 6, [variables.minheight] = 6,
+ fitr = 7,
+}
+
+function nodes.pdfliteral(str)
+ local t = copy_node(pdfliteral)
+ t.data = str
+ return t
+end
+
+function nodes.pdfannotation(w,h,d,data,n)
+ local t = copy_node(pdfannot)
+ if w and w ~= 0 then t.width = w end
+ if h and h ~= 0 then t.height = h end
+ if d and d ~= 0 then t.depth = d end
+ if n then t.objnum = n end
+ if data and data ~= "" then t.data = data end
+ return t
+end
+
+function nodes.pdfdestination(w,h,d,name,view,n)
+ local t = copy_node(pdfdest)
+ if w and w ~= 0 then t.width = w end
+ if h and h ~= 0 then t.height = h end
+ if d and d ~= 0 then t.depth = d end
+ if n then t.objnum = n end
+ t.dest_id = name
+ t.dest_type = views[view] or view or 1 -- fit is default
+ return t
+end
diff --git a/tex/context/base/lpdf-pdx.lua b/tex/context/base/lpdf-pdx.lua
new file mode 100644
index 000000000..0a440c1e6
--- /dev/null
+++ b/tex/context/base/lpdf-pdx.lua
@@ -0,0 +1,139 @@
+if not modules then modules = { } end modules ['lpdf-pdx'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Peter Rold and Hans Hagen",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local codeinjections = backends.codeinjections -- normally it is registered
+local variables = interfaces.variables
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+local pdfstring = lpdf.string
+local pdfverbose = lpdf.verbose
+
+local lower, gmatch = string.lower, string.gmatch
+
+local channels = {
+ gray = 1,
+ grey = 1,
+ rgb = 3,
+ cmyk = 4,
+}
+
+local prefixes = {
+ gray = "DefaultGray",
+ grey = "DefaultGray",
+ rgb = "DefaultRGB",
+ cmyk = "DefaultCMYK",
+}
+
+local profiles = { }
+local defaults = { }
+local intents = pdfarray()
+local lastprofile = nil
+
+function codeinjections.useinternalICCprofile(colorspace,filename)
+ local name = lower(file.basename(filename))
+ local profile = profiles[name]
+ if not profile then
+ local colorspace = lower(colorspace)
+ local filename = resolvers.findctxfile(filename) or ""
+ local channel = channels[colorspace]
+ if channel and filename ~= "" then
+ local a = pdfdictionary { N = channel }
+ profile = pdf.obj {
+ compresslevel = 0,
+ immediate = true,
+ type = "stream",
+ file = filename,
+ attr = a(),
+ }
+ profiles[name] = profile
+ end
+ end
+ lastprofile = profile
+ return profile
+end
+
+function codeinjections.useexternalICCprofile(colorspace,name,urls,checksum,version)
+ local profile = profiles[name]
+ if not profile then
+ local u = pdfarray()
+ for url in gmatch(urls,"([^, ]+)") do
+ u[#u+1] = pdfdictionary {
+ FS = pdfconstant("URL"),
+ F = pdfstring(url),
+ }
+ end
+ local d = pdfdictionary {
+ ProfileName = name, -- not file name!
+ ProfileCS = colorspace,
+ URLs = u, -- array containing at least one URL
+ CheckSum = pdfverbose { "<", checksum, ">" }, -- 16byte MD5 hash
+ ICCVersion = pdfverbose { "<", version, ">" }, -- bytes 8..11 from the header of the ICC profile, as a hex string
+ }
+ local n = pdfflushobject(d)
+ profiles[name] = n
+ lastprofile = n
+ return n
+ end
+end
+
+local function embedprofile(colorspace,filename)
+ local colorspace = lower(colorspace)
+ local n = codeinjections.useinternaliccprofile(colorspace,filename)
+ if n then
+ local a = pdfarray {
+ pdfconstant("ICCBased"),
+ pdfreference(n),
+ }
+ lpdf.adddocumentcolorspace(prefixes[colorspace],pdfreference(pdfflushobject(a))) -- part of page /Resources
+ defaults[lower(colorspace)] = filename
+ end
+end
+
+
+function codeinjections.useICCdefaultprofile(colorspace,filename)
+ defaults[lower(colorspace)] = filename
+end
+
+local function flushembeddedprofiles()
+ for colorspace, filename in next, defaults do
+ embedprofile(colorspace,filename)
+ end
+end
+
+function codeinjections.usePDFXoutputintent(id,name,reference,outputcondition,info)
+ local d = {
+ Type = pdfconstant("OutputIntent"),
+ S = pdfconstant("GTS_PDFX"),
+ OutputConditionIdentifier = id,
+ RegistryName = name,
+ OutputCondition = outputcondition,
+ Info = info,
+ }
+ local icc = lastprofile
+ if reference == variables.yes then
+ d["DestOutputProfileRef"] = pdfreference(icc)
+ else
+ d["DestOutputProfile"] = pdfreference(icc)
+ end
+ -- intents[#intents+1] = pdfdictionary(d)
+ intents[#intents+1] = pdfreference(pdfflushobject(pdfdictionary(d))) -- nicer as separate object
+end
+
+local function flushoutputintents()
+ if #intents > 0 then
+ lpdf.addtocatalog("OutputIntents",pdfreference(pdfflushobject(intents)))
+ end
+end
+
+
+lpdf.registerdocumentfinalizer(flushoutputintents,1)
+lpdf.registerdocumentfinalizer(flushembeddedprofiles,1)
diff --git a/tex/context/base/lpdf-pdx.mkiv b/tex/context/base/lpdf-pdx.mkiv
new file mode 100644
index 000000000..ffb7f5269
--- /dev/null
+++ b/tex/context/base/lpdf-pdx.mkiv
@@ -0,0 +1,71 @@
+%D \module
+%D [ file=lpdf-pdx,
+%D version=2010.02.11,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=PDF-X,
+%D author=Peter Rolf \& Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA] % and peter
+%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 / PDF-X}
+
+\unprotect
+
+% declare default color space
+% all device based entries of the same CS are mapped to the defined ICCprofile then;
+% i.e. /DeviceRGB --> /ICCBased RGB profile
+% TODO: allow multiple default profiles (one per CS)
+%
+% external ICC profile dictionary (PDF/X-4p and PDF/X-5p)
+%
+% - ProfileName (not file name!)
+% - URLs (array containing at least one URL); the keyword FSA is wrong!
+% - CheckSum (16byte MD5 hash)
+% - ProfileCS (GRAY,RGB,CMYK)
+% - ICCVersion (bytes 8..11 from the header of the ICC profile, as a hex string)
+
+\registerctxluafile{lpdf-pdx} {}
+
+% \def\embedICCprofile#1#2% colorspace, name
+% {\ctxlua{backends.codeinjections.addiccprofile("#1","#2")}}
+
+\def\douseinternalICCprofile[#1]%
+ {\getparameters[\??ic][colorspace=,filename=,#1]%
+ \ctxlua{backends.codeinjections.useinternalICCprofile(
+ "\@@iccolorspace","\@@icfilename")}}
+
+% create a dictionary for an external ICC profile (PDF/X-4p and PDF/X-5pg only)
+% the referenced ICC profile is not embedded
+
+\def\douseexternalICCprofile[#1]%
+ {\getparameters[\??ic][colorspace=,name=,url=,checksum=,version=,#1]%
+ \ctxlua{backends.codeinjections.useexternalICCprofile(
+ "\@@iccolorspace","\@@icname","\@@icurl","\@@icchecksum","\@@icversion")}}
+
+% use an ICC profile as default colorspace for all device dependend colors;
+% all device based entries of the same CS are mapped to the defined ICCprofile then;
+% i.e. /DeviceRGB --> /ICCBased RGB profile always embed the profile!
+
+\def\douseICCdefaultprofile[#1]%
+ {\getparameters[\??ic][colorspace=,filename=,#1]%
+ \ctxlua{backends.codeinjections.useICCdefaultprofile(
+ "\@@iccolorspace","\@@icfilename")}}
+
+% embedding rules for output intent profile differ for the PDF/X versions
+
+\def\dousePDFXoutputintent[#1]%
+ {\getparameters[\??ic][reference=\v!yes,outputcondition=,info=,id=,name=,#1]%
+ \ctxlua{backends.codeinjections.usePDFXoutputintent(
+ "\@@icid","\@@icname","\@@icreference","\@@icoutputcondition","\@@icinfo")}}
+
+\def\useinternalICCprofile{\dosingleempty\douseinternalICCprofile}
+\def\useexternalICCprofile{\dosingleempty\douseexternalICCprofile}
+\def\useICCdefaultprofile {\dosingleempty\douseICCdefaultprofile }
+\def\usePDFXoutputintent {\dosingleempty\dousePDFXoutputintent }
+
+\protect \endinput
+
diff --git a/tex/context/base/lpdf-ren.lua b/tex/context/base/lpdf-ren.lua
new file mode 100644
index 000000000..e6bbd67fe
--- /dev/null
+++ b/tex/context/base/lpdf-ren.lua
@@ -0,0 +1,207 @@
+if not modules then modules = { } end modules ['lpdf-ren'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- rendering
+
+local tostring, tonumber, next = tostring, tonumber, next
+local format = string.format
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+jobreferences = jobreferences or { }
+--~ jobreferences.runners = jobreferences.runners or { }
+--~ jobreferences.specials = jobreferences.specials or { }
+--~ jobreferences.handlers = jobreferences.handlers or { }
+jobreferences.executers = jobreferences.executers or { }
+
+--~ local runners = jobreferences.runners
+--~ local specials = jobreferences.specials
+--~ local handlers = jobreferences.handlers
+local executers = jobreferences.executers
+
+local variables = interfaces.variables
+
+local pdfconstant = lpdf.constant
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+
+local pdf_ocg = pdfconstant("OCG")
+local pdf_ocmd = pdfconstant("OCMD")
+local pdf_off = pdfconstant("OFF")
+local pdf_on = pdfconstant("ON")
+local pdf_toggle = pdfconstant("Toggle")
+local pdf_setocgstate = pdfconstant("SetOCGState")
+
+local lpdf_usage = pdfdictionary { Print = pdfdictionary { PrintState = pdfconstant("OFF") } }
+
+local pdfln, pdfld = { }, { }
+local textlayers, hidelayers, videlayers = pdfarray(), pdfarray(), pdfarray()
+local pagelayers = pdfdictionary()
+
+lpdf.layerreferences = pdfln
+
+function backends.pdf.layerreference(name)
+ return pdfln[name]
+end
+
+function codeinjections.defineviewerlayer(specification)
+ if textlayers then
+ local tag = specification.tag
+ -- todo: reserve
+ local n = pdfdictionary {
+ Type = pdf_ocg,
+ Name = specification.title or "unknown",
+ Intent = ((specification.kind > 0) and pdf_design) or nil, -- disable layer hiding by user
+ Usage = ((specification.printable == variables.no) and lpdf_usage) or nil , -- printable or not
+ }
+ local nr = pdfreference(pdfflushobject(n))
+ pdfln[tag] = nr -- was n
+ local d = pdfdictionary {
+ Type = pdf_ocmd,
+ OCGs = pdfarray { nr },
+ }
+ local dr = pdfreference(pdfflushobject(d))
+ pdfld[tag] = dr
+ textlayers[#textlayers+1] = nr
+ if specification.visible == variables.start then
+ videlayers[#videlayers+1] = nr
+ else
+ hidelayers[#hidelayers+1] = nr
+ end
+ pagelayers[tag] = dr -- check
+ end
+end
+
+local function flushtextlayers()
+ if textlayers and #textlayers > 0 then
+ local d = pdfdictionary {
+ OCGs = textlayers,
+ D = pdfdictionary {
+ Order = textlayers,
+ ON = videlayers,
+ OFF = hidelayers,
+ },
+ }
+ lpdf.addtocatalog("OCProperties",d)
+ textlayers = nil
+ end
+end
+
+local function flushpagelayers()
+ if next(pagelayers) then
+ lpdf.addtopageresources("Properties",pagelayers)
+ end
+end
+
+lpdf.registerpagefinalizer (flushpagelayers)
+lpdf.registerdocumentfinalizer(flushtextlayers)
+
+local function setlayer(what,arguments)
+ -- maybe just a gmatch of even better, earlier in lpeg
+ arguments = (type(arguments) == "table" and arguments) or aux.settings_to_array(arguments)
+ local state = pdfarray { what }
+ for i=1,#arguments do
+ local p = pdfln[arguments[i]]
+ if p then
+ state[#state+1] = p
+ end
+ end
+ return pdfdictionary {
+ S = pdf_setocgstate,
+ State = state,
+ }
+end
+
+function executers.hidelayer (arguments) setlayer(pdf_off, arguments) end
+function executers.videlayer (arguments) setlayer(pdf_on, arguments) end
+function executers.togglelayer(arguments) setlayer(pdf_toggle,arguments) end
+
+-- transitions
+
+local pagetransitions = {
+ {"split","in","vertical"}, {"split","in","horizontal"},
+ {"split","out","vertical"}, {"split","out","horizontal"},
+ {"blinds","horizontal"}, {"blinds","vertical"},
+ {"box","in"}, {"box","out"},
+ {"wipe","east"}, {"wipe","west"}, {"wipe","north"}, {"wipe","south"},
+ {"dissolve"},
+ {"glitter","east"}, {"glitter","south"},
+ {"fly","in","east"}, {"fly","in","west"}, {"fly","in","north"}, {"fly","in","south"},
+ {"fly","out","east"}, {"fly","out","west"}, {"fly","out","north"}, {"fly","out","south"},
+ {"push","east"}, {"push","west"}, {"push","north"}, {"push","south"},
+ {"cover","east"}, {"cover","west"}, {"cover","north"}, {"cover","south"},
+ {"uncover","east"}, {"uncover","west"}, {"uncover","north"}, {"uncover","south"},
+ {"fade"},
+}
+
+local mapping = {
+ split = { "S" , pdfconstant("Split") },
+ blinds = { "S" , pdfconstant("Blinds") },
+ box = { "S" , pdfconstant("Box") },
+ wipe = { "S" , pdfconstant("Wipe") },
+ dissolve = { "S" , pdfconstant("Dissolve") },
+ glitter = { "S" , pdfconstant("Glitter") },
+ replace = { "S" , pdfconstant("R") },
+ fly = { "S" , pdfconstant("Fly") },
+ push = { "S" , pdfconstant("Push") },
+ cover = { "S" , pdfconstant("Cover") },
+ uncover = { "S" , pdfconstant("Uncover") },
+ fade = { "S" , pdfconstant("Fade") },
+ horizontal = { "Dm" , pdfconstant("H") },
+ vertical = { "Dm" , pdfconstant("V") },
+ ["in"] = { "M" , pdfconstant("I") },
+ out = { "M" , pdfconstant("O") },
+ east = { "Di" , 0 },
+ north = { "Di" , 90 },
+ west = { "Di" , 180 },
+ south = { "Di" , 270 },
+}
+
+local last = 0
+
+-- n: number, "stop", "reset", "random", "a,b,c" delay: number, "none"
+
+function codeinjections.setpagetransition(specification)
+ local n, delay = specification.n, specification.delay
+ if n == variables.auto then
+ if last >= #pagetransitions then
+ last = 0
+ end
+ n = last + 1
+ elseif n == variables.stop then
+ return
+ elseif n == variables.reset then
+ last = 0
+ return
+ elseif n == variables.random then
+ n = math.random(1,#pagetransitions)
+ else
+ n = tonumber(n)
+ end
+ local t = n and pagetransitions[n] or pagetransitions[1]
+ if not t then
+ t = aux.settings_to_array(n)
+ end
+ if t and #t > 0 then
+ local d = pdfdictionary()
+ for i=1,#t do
+ local m = mapping[t[i]]
+ d[m[1]] = m[2]
+ end
+ delay = tonumber(delay)
+ if delay and delay > 0 then
+ lpdf.addtopageattributes("Dur",delay)
+ end
+ lpdf.addtopageattributes("Trans",d)
+ end
+end
diff --git a/tex/context/base/lpdf-swf.lua b/tex/context/base/lpdf-swf.lua
new file mode 100644
index 000000000..9fe0cd09f
--- /dev/null
+++ b/tex/context/base/lpdf-swf.lua
@@ -0,0 +1,109 @@
+if not modules then modules = { } end modules ['lpdf-swf'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The following code is based on tests by Luigi Scarso. His prototype
+-- was using tex code. This is the official implementation.
+
+local format = string.format
+
+local pdfconstant = lpdf.constant
+local pdfboolean = lpdf.boolean
+local pdfstring = lpdf.string
+local pdfunicode = lpdf.unicode
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfnull = lpdf.null
+local pdfreference = lpdf.reference
+
+function backends.pdf.helpers.insertswf(spec)
+
+ local width, height, filename = spec.width, spec.height, spec.foundname
+
+ local eref = backends.codeinjections.embedfile(filename)
+
+ local flash = pdfdictionary {
+ Subtype = pdfconstant("Flash"),
+ Instances = pdfarray {
+ pdfdictionary {
+ Asset = eref,
+ Params = pdfdictionary {
+ Binding = pdfconstant("Foreground")
+ }
+ },
+ },
+ }
+
+ local fref = pdfreference(pdf.immediateobj(tostring(flash)))
+
+ local configuration = pdfdictionary {
+ Configurations = pdfarray { fref },
+ Assets = pdfdictionary {
+ Names = pdfarray {
+ pdfstring(filename),
+ eref,
+ }
+ },
+ }
+
+ local cref = pdfreference(pdf.immediateobj(tostring(configuration)))
+
+ local activation = pdfdictionary {
+ Activation = pdfdictionary {
+ Type = pdfconstant("RichMediaActivation"),
+ Condition = pdfconstant("PO"),
+ Configuration = fref,
+ Animation = pdfdictionary {
+ Subtype = pdfconstant("Linear"),
+ Speed = 1,
+ Playcount = 1,
+ },
+ Deactivation = pdfdictionary {
+ Type = pdfconstant("RichMediaDeactivation"),
+ Condition = pdfconstant("XD"),
+ },
+ Presentation = pdfdictionary {
+ PassContextClick = false,
+ Style = pdfconstant("Embedded"),
+ Toolbar = false,
+ NavigationPane = false,
+ Transparent = true,
+ Window = pdfdictionary {
+ Type = pdfconstant("RichMediaWindow"),
+ Width = pdfdictionary {
+ Default = 100,
+ Min = 100,
+ Max = 100,
+ },
+ Height = pdfdictionary {
+ Default = 100,
+ Min = 100,
+ Max = 100,
+ },
+ Position = pdfdictionary {
+ Type = pdfconstant("RichMediaPosition"),
+ HAlign = pdfconstant("Near"),
+ VAlign = pdfconstant("Near"),
+ HOffset = 0,
+ VOffset = 0,
+ }
+ }
+ }
+ }
+ }
+
+ local aref = pdfreference(pdf.immediateobj(tostring(activation)))
+
+ local annotation = pdfdictionary {
+ Subtype = pdfconstant("RichMedia"),
+ RichMediaContent = cref,
+ RichMediaSettings = aref,
+ }
+
+ return annotation, nil, nil
+
+end
diff --git a/tex/context/base/lpdf-u3d.lua b/tex/context/base/lpdf-u3d.lua
new file mode 100644
index 000000000..f7a62c6c9
--- /dev/null
+++ b/tex/context/base/lpdf-u3d.lua
@@ -0,0 +1,474 @@
+if not modules then modules = { } end modules ['lpdf-u3d'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The following code is based on a working prototype provided
+-- by Michael Vidiassov. It is rewritten using the lpdf library
+-- and different checking is used. The macro calls are adapted
+-- (and will eventually be removed). The user interface needs
+-- an overhaul. There are some messy leftovers that will be
+-- removed in future versions.
+
+local format, find = string.format, string.find
+local cos, sin, sqrt, pi, atan2, abs = math.cos, math.sin, math.sqrt, math.pi, math.atan2, math.abs
+
+local pdfconstant = lpdf.constant
+local pdfboolean = lpdf.boolean
+local pdfnumber = lpdf.number
+local pdfunicode = lpdf.unicode
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfnull = lpdf.null
+local pdfreference = lpdf.reference
+
+local pdfimmediateobj = pdf.immediateobj
+
+local checkedkey = lpdf.checkedkey
+local limited = lpdf.limited
+
+local schemes = table.tohash {
+ "Artwork", "None", "White", "Day", "Night", "Hard",
+ "Primary", "Blue", "Red", "Cube", "CAD", "Headlamp",
+}
+
+local modes = table.tohash {
+ "Solid", "SolidWireframe", "Transparent", "TransparentWireframe", "BoundingBox",
+ "TransparentBoundingBox", "TransparentBoundingBoxOutline", "Wireframe",
+ "ShadedWireframe", "HiddenWireframe", "Vertices", "ShadedVertices", "Illustration",
+ "SolidOutline", "ShadedIllustration",
+}
+
+local function normalize(x, y, z)
+ local modulo = sqrt(x*x + y*y + z*z);
+ if modulo ~= 0 then
+ return x/modulo, y/modulo, z/modulo
+ else
+ return x, y, z
+ end
+end
+
+local function rotate(vect_x,vect_y,vect_z, tet, axis_x,axis_y,axis_z)
+ -- rotate vect by tet about axis counterclockwise
+ local c, s = cos(tet*pi/180), sin(tet*pi/180)
+ local r = 1 - c
+ local n = sqrt(axis_x*axis_x+axis_y*axis_y+axis_z*axis_z)
+ axis_x, axis_y, axis_z = axis_x/n, axis_y/n, axis_z/n
+ return
+ (axis_x*axis_x*r+c )*vect_x + (axis_x*axis_y*r-axis_z*s)*vect_y + (axis_x*axis_z*r+axis_y*s)*vect_z,
+ (axis_x*axis_y*r+axis_z*s)*vect_x + (axis_y*axis_y*r+c )*vect_y + (axis_y*axis_z*r-axis_x*s)*vect_z,
+ (axis_x*axis_z*r-axis_y*s)*vect_x + (axis_y*axis_z*r+axis_x*s)*vect_y + (axis_z*axis_z*r+c )*vect_z
+end
+
+local function make3dview(view)
+
+ local name = view.name
+ local name = pdfunicode(name ~= "" and name or "unknown view")
+
+ local viewdict = pdfdictionary {
+ Type = pdfconstant("3DView"),
+ XN = name,
+ IN = name,
+ NR = true,
+ }
+
+ local bg = checkedkey(view,"bg","table")
+ if bg then
+ viewdict.BG = pdfdictionary {
+ Type = pdfconstant("3DBG"),
+ C = pdfarray { limited(bg[1],1,1,1), limited(bg[2],1,1,1), limited(bg[3],1,1,1) },
+ }
+ end
+
+ local lights = checkedkey(view,"lights","string")
+ if lights and schemes[lights] then
+ viewdict.LS = pdfdictionary {
+ Type = pdfconstant("3DLightingScheme"),
+ Subtype = pdfconstant(lights),
+ }
+ end
+
+ -- camera position is taken from 3d model
+
+ local u3dview = checkedkey(view, "u3dview", "string")
+ if u3dview then
+ viewdict.MS = pdfconstant("U3D")
+ viewdict.U3DPath = u3dview
+ end
+
+ -- position the camera as given
+
+ local c2c = checkedkey(view, "c2c", "table")
+ local coo = checkedkey(view, "coo", "table")
+ local roo = checkedkey(view, "roo", "number")
+ local azimuth = checkedkey(view, "azimuth", "number")
+ local altitude = checkedkey(view, "altitude", "number")
+
+ if c2c or coo or roo or azimuth or altitude then
+
+ local pos = checkedkey(view, "pos", "table")
+ local dir = checkedkey(view, "dir", "table")
+ local upv = checkedkey(view, "upv", "table")
+ local roll = checkedkey(view, "roll", "table")
+
+ local coo_x, coo_y, coo_z = 0, 0, 0
+ local dir_x, dir_y, dir_z = 0, 0, 0
+ local trans_x, trans_y, trans_z = 0, 0, 0
+ local left_x, left_y, left_z = 0, 0, 0
+ local up_x, up_y, up_z = 0, 0, 0
+
+ -- point camera is aimed at
+
+ if coo then
+ coo_x, coo_y, coo_z = tonumber(coo[1]) or 0, tonumber(coo[2]) or 0, tonumber(coo[3]) or 0
+ end
+
+ -- distance from camera to target
+
+ if roo then
+ roo = abs(roo)
+ end
+ if not roo or roo == 0 then
+ roo = 0.000000000000000001
+ end
+
+ -- set it via camera position
+
+ if pos then
+ dir_x = coo_x - (tonumber(pos[1]) or 0)
+ dir_y = coo_y - (tonumber(pos[2]) or 0)
+ dir_z = coo_z - (tonumber(pos[3]) or 0)
+ if not roo then
+ roo = sqrt(dir_x*dir_x + dir_y*dir_y + dir_z*dir_z)
+ end
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+ dir_x, dir_y, dir_z = normalize(dir_x,dir_y,dir_z)
+ end
+
+ -- set it directly
+
+ if dir then
+ dir_x, dir_y, dir_z = tonumber(dir[1] or 0), tonumber(dir[2] or 0), tonumber(dir[3] or 0)
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+ dir_x, dir_y, dir_z = normalize(dir_x,dir_y,dir_z)
+ end
+
+ -- set it movie15 style with vector from target to camera
+
+ if c2c then
+ dir_x, dir_y, dir_z = - tonumber(c2c[1] or 0), - tonumber(c2c[2] or 0), - tonumber(c2c[3] or 0)
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+ dir_x, dir_y, dir_z = normalize(dir_x,dir_y,dir_z)
+ end
+
+ -- set it with azimuth and altitutde
+
+ if altitude or azimuth then
+ dir_x, dir_y, dir_z = -1, 0, 0
+ if altitude then dir_x, dir_y, dir_z = rotate(dir_x,dir_y,dir_z, -altitude, 0,1,0) end
+ if azimuth then dir_x, dir_y, dir_z = rotate(dir_x,dir_y,dir_z, azimuth, 0,0,1) end
+ end
+
+ -- set it with rotation like in MathGL
+
+ if rot then
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_z = -1 end
+ dir_x,dir_y,dir_z = rotate(dir_x,dir_y,dir_z, tonumber(rot[1]) or 0, 1,0,0)
+ dir_x,dir_y,dir_z = rotate(dir_x,dir_y,dir_z, tonumber(rot[2]) or 0, 0,1,0)
+ dir_x,dir_y,dir_z = rotate(dir_x,dir_y,dir_z, tonumber(rot[3]) or 0, 0,0,1)
+ end
+
+ -- set it with default movie15 orientation looking up y axis
+
+ if dir_x == 0 and dir_y == 0 and dir_z == 0 then dir_y = 1 end
+
+ -- left-vector
+ -- up-vector
+
+ if upv then
+ up_x, up_y, up_z = tonumber(upv[1]) or 0, tonumber(upv[2]) or 0, tonumber(upv[3]) or 0
+ else
+ -- set default up-vector
+ if abs(dir_x) == 0 and abs(dir_y) == 0 then
+ if dir_z < 0 then
+ up_y = 1 -- top view
+ else
+ up_y = -1 -- bottom view
+ end
+ else
+ -- other camera positions than top and bottom, up-vector = up_world - (up_world dot dir) dir
+ up_x, up_y, up_z = - dir_z*dir_x, - dir_z*dir_y, - dir_z*dir_z + 1
+ end
+ end
+
+ -- normalize up-vector
+
+ up_x, up_y, up_z = normalize(up_x,up_y,up_z)
+
+ -- left vector = up x dir
+
+ left_x, left_y, left_z = dir_z*up_y - dir_y*up_z, dir_x*up_z - dir_z*up_x, dir_y*up_x - dir_x*up_y
+
+ -- normalize left vector
+
+ left_x, left_y, left_z = normalize(left_x,left_y,left_z)
+
+ -- apply camera roll
+
+ if roll then
+ local sinroll = sin((roll/180.0)*pi)
+ local cosroll = cos((roll/180.0)*pi)
+ left_x = left_x*cosroll + up_x*sinroll
+ left_y = left_y*cosroll + up_y*sinroll
+ left_z = left_z*cosroll + up_z*sinroll
+ up_x = up_x*cosroll + left_x*sinroll
+ up_y = up_y*cosroll + left_y*sinroll
+ up_z = up_z*cosroll + left_z*sinroll
+ end
+
+ -- translation vector
+
+ trans_x, trans_y, trans_z = coo_x - roo*dir_x, coo_y - roo*dir_y, coo_z - roo*dir_z
+
+ viewdict.MS = pdfconstant("M")
+ viewdict.CO = roo
+ viewdict.C2W = pdfarray {
+ left_x, left_y, left_z,
+ up_x, up_y, up_z,
+ dir_x, dir_y, dir_z,
+ trans_x, trans_y, trans_z,
+ }
+
+ end
+
+ local aac = tonumber(view.aac) -- perspective projection
+ local mag = tonumber(view.mag) -- ortho projection
+
+ if aac and aac > 0 and aac < 180 then
+ viewdict.P = pdfdictionary {
+ Subtype = pdfconstant("P"),
+ PS = pdfconstant("Min"),
+ FOV = aac,
+ }
+ elseif mag and mag > 0 then
+ viewdict.P = pdfdictionary {
+ Subtype = pdfconstant("O"),
+ OS = mag,
+ }
+ end
+
+ local mode = modes[view.rendermode]
+ if mode then
+ pdfdictionary {
+ Type = pdfconstant("3DRenderMode"),
+ Subtype = pdfconstant(mode),
+ }
+ end
+
+ -- crosssection
+
+ local crosssection = checkedkey(view,"crosssection","table")
+ if crosssection then
+ local crossdict = pdfdictionary {
+ Type = pdfconstant("3DCrossSection")
+ }
+
+ local c = checkedkey(crosssection,"point","table") or checkedkey(crosssection,"center","table")
+ if c then
+ crossdict.C = pdfarray { tonumber(c[1]) or 0, tonumber(c[2]) or 0, tonumber(c[3]) or 0 }
+ end
+
+ local normal = checkedkey(crosssection,"normal","table")
+ if normal then
+ local x, y, z = tonumber(normal[1] or 0), tonumber(normal[2] or 0), tonumber(normal[3] or 0)
+ if sqrt(x*x + y*y + z*z) == 0 then
+ x, y, z = 1, 0, 0
+ end
+ crossdict.O = pdfarray {
+ pdfnull,
+ atan2(-z,sqrt(x*x + y*y))*180/pi,
+ atan2(y,x)*180/pi,
+ }
+ end
+
+ local orient = checkedkey(crosssection,"orient","table")
+ if orient then
+ crossdict.O = pdfarray {
+ tonumber(orient[1]) or 1,
+ tonumber(orient[2]) or 0,
+ tonumber(orient[3]) or 0,
+ }
+ end
+
+ crossdict.IV = cross.intersection or false
+ crossdict.ST = cross.transparent or false
+
+ viewdict.SA = next(crossdict) and pdfarray { crossdict } -- maybe test if # > 1
+ end
+
+ local nodes = checkedkey(view,"nodes","table")
+ if nodes then
+ local nodelist = pdfarray()
+ for i=1,#nodes do
+ local node = checkedkey(nodes,i,"table")
+ if node then
+ local position = checkedkey(node,"position","table")
+ nodelist[#nodelist+1] = pdfdictionary {
+ Type = pdfconstant("3DNode"),
+ N = node.name or ("node_" .. i), -- pdfunicode ?
+ M = position and #position == 12 and pdfarray(position),
+ V = node.visible or true,
+ O = node.opacity or 0,
+ RM = pdfdictionary {
+ Type = pdfconstant("3DRenderMode"),
+ Subtype = pdfconstant(node.rendermode or "Solid"),
+ },
+ }
+ end
+ end
+ viewdict.NA = nodelist
+ end
+
+ return viewdict
+
+end
+
+local stored_js, stored_3d, stored_pr, streams = { }, { }, { }, { }
+
+function backends.pdf.helpers.insert3d(spec) -- width, height, factor, display, controls, label, foundname
+
+ local width, height, factor = spec.width, spec.height, spec.factor or number.dimenfactors.bp
+ local display, controls, label, foundname = spec.display, spec.controls, spec.label, spec.foundname
+
+ local param = (display and parametersets[display]) or { }
+ local streamparam = (controls and parametersets[controls]) or { }
+ local name = "3D Artwork " .. (param.name or label or "Unknown")
+
+ local activationdict = pdfdictionary {
+ TB = pdfboolean(param.toolbar,true),
+ NP = pdfboolean(param.tree,false),
+ }
+
+ local stream = streams[label]
+ if not stream then
+
+ local subtype, subdata = "U3D", io.loaddata(foundname) or ""
+ if find(subdata,"^PRC") then
+ subtype = "PRC"
+ elseif find(subdata,"^U3D") then
+ subtype = "U3D"
+ elseif file.extname(foundname) == "prc" then
+ subtype = "PRC"
+ end
+
+ local attr = pdfdictionary {
+ Type = pdfconstant("3D"),
+ Subtype = pdfconstant(subtype),
+ }
+ local streamviews = checkedkey(streamparam, "views", "table")
+ if streamviews then
+ local list = pdfarray()
+ for i=1,#streamviews do
+ local v = checkedkey(streamviews, i, "table")
+ if v then
+ list[#list+1] = make3dview(v)
+ end
+ end
+ attr.VA = list
+ end
+ if checkedkey(streamparam, "view", "table") then
+ attr.DV = make3dview(streamparam.view)
+ elseif checkedkey(streamparam, "view", "string") then
+ attr.DV = streamparam.view
+ end
+ local js = checkedkey(streamparam, "js", "string")
+ if js then
+ local jsref = stored_js[js]
+ if not jsref then
+ jsref = pdfimmediateobj("streamfile",js)
+ stored_js[js] = jsref
+ end
+ attr.OnInstantiate = pdfreference(jsref)
+ end
+ stored_3d[label] = pdfimmediateobj("streamfile",foundname,attr())
+ stream = 1
+ else
+ stream = stream + 1
+ end
+ streams[label] = stream
+
+ local name = pdfunicode(name)
+
+ local annot = pdfdictionary {
+ Subtype = pdfconstant("3D"),
+ T = name,
+ Contents = name,
+ NM = name,
+ ["3DD"] = pdfreference(stored_3d[label]),
+ ["3DA"] = activationdict,
+ }
+ if checkedkey(param,"view","table") then
+ annot["3DV"] = make3dview(param.view)
+ elseif checkedkey(param,"view","string") then
+ annot["3DV"] = param.view
+ end
+
+ local preview = checkedkey(param,"preview","string")
+ if preview then
+ activationdict.A = pdfconstant("XA")
+ local tag = format("%s:%s:%s",label,stream,preview)
+ local ref = stored_pr[tag]
+ if not ref then
+ local figure = img.immediatewrite {
+ filename = preview,
+ width = width,
+ height = height
+ }
+ -- local figure = img.immediatewrite {
+ -- stream = ".5 .75 .75 rg 0 0 20 10 re f",
+ -- bbox = { 0, 0, 20, 10 }
+ -- }
+ ref = figure.objnum
+ stored_pr[tag] = ref
+ end
+ if ref then
+ local zero, one = pdfnumber(0), pdfnumber(1) -- not really needed
+ local pw = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Form"),
+ FormType = one,
+ BBox = pdfarray { zero, zero, pdfnumber(factor*width), pdfnumber(factor*height) },
+ Matrix = pdfarray { one, zero, zero, one, zero, zero },
+ Resources = pdfdictionary {
+ XObject = pdfdictionary {
+ IM = pdfreference(ref)
+ }
+ },
+ ExtGState = pdfdictionary {
+ GS = pdfdictionary {
+ Type = pdfconstant("ExtGState"),
+ CA = one,
+ ca = one,
+ }
+ },
+ ProcSet = pdfarray { pdfconstant("PDF"), pdfconstant("ImageC") },
+ }
+ local pwd = pdfimmediateobj(
+ "stream",
+ format("q /GS gs %s 0 0 %s 0 0 cm /IM Do Q",
+ factor*width,factor*height),
+ pw()
+ )
+ annot.AP = pdfdictionary {
+ N = pdfreference(pwd)
+ }
+ end
+ return annot, figure, ref
+ else
+ activationdict.A = pdfconstant("PV")
+ return annot, nil, nil
+ end
+end
diff --git a/tex/context/base/lpdf-wid.lua b/tex/context/base/lpdf-wid.lua
new file mode 100644
index 000000000..40a81e7d4
--- /dev/null
+++ b/tex/context/base/lpdf-wid.lua
@@ -0,0 +1,355 @@
+if not modules then modules = { } end modules ['lpdf-wid'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, gmatch, gsub, find = string.format, string.gmatch, string.gsub, string.find
+local texsprint, ctxcatcodes, texbox, texcount = tex.sprint, tex.ctxcatcodes, tex.box, tex.count
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local executers = jobreferences.executers
+local variables = interfaces.variables
+
+local pdfconstant = lpdf.constant
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfstring = lpdf.string
+local pdfcolorspec = lpdf.colorspec
+local pdfflushobject = lpdf.flushobject
+local pdfreserveobject = lpdf.reserveobject
+
+local pdfreserveobj = pdf.reserveobj
+local pdfimmediateobj = pdf.immediateobj
+
+local pdfannotation = nodes.pdfannotation
+
+local hpack_node, write_node = node.hpack, node.write
+
+-- symbols
+
+local presets = { } -- xforms
+
+function codeinjections.registersymbol(name,n)
+ presets[name] = pdfreference(n)
+end
+
+function codeinjections.registeredsymbol(name)
+ return presets[name]
+end
+
+function codeinjections.presetsymbol(symbol)
+ if not presets[symbol] then
+ texsprint(ctxcatcodes,format("\\predefinesymbol[%s]",symbol))
+ end
+end
+
+function codeinjections.presetsymbollist(list)
+ if list then
+ for symbol in gmatch(list,"[^, ]+") do
+ codeinjections.presetsymbol(symbol)
+ end
+ end
+end
+
+-- comments
+
+local symbols = {
+ New = pdfconstant("Insert"),
+ Insert = pdfconstant("Insert"),
+ Balloon = pdfconstant("Comment"),
+ Comment = pdfconstant("Comment"),
+ Text = pdfconstant("Note"),
+ Addition = pdfconstant("NewParagraph"),
+ NewParagraph = pdfconstant("NewParagraph"),
+ Help = pdfconstant("Help"),
+ Paragraph = pdfconstant("Paragraph"),
+ Key = pdfconstant("Key"),
+ Graph = pdfconstant("Graph"),
+ Paperclip = pdfconstant("Paperclip"),
+ Attachment = pdfconstant("Attachment"),
+ Tag = pdfconstant("Tag"),
+}
+
+symbols[variables.normal] = pdfconstant("Note")
+
+local nofcomments, usepopupcomments, stripleading = 0, true, true
+
+local function analyzesymbol(symbol)
+ if not symbol or symbol == "" then
+ return symbols.normal, nil
+ elseif symbols[symbol] then
+ return symbols[symbol], nil
+ else
+ local set = aux.settings_to_array(symbol)
+ local normal, down = set[1], set[2]
+ if normal then
+ normal = codeinjections.registeredsymbol(down or normal)
+ end
+ if down then
+ down = codeinjections.registeredsymbol(normal)
+ end
+ if down or normal then
+ return nil, pdfdictionary {
+ N = normal,
+ D = down,
+ }
+ end
+ end
+end
+
+local function analyzelayer(layer)
+ -- todo: (specification.layer ~= "" and pdfreference(specification.layer)) or nil, -- todo: ref to layer
+end
+
+function codeinjections.registercomment(specification)
+ nofcomments = nofcomments + 1
+ local text = buffers.collect(specification.buffer)
+ if stripleading then
+ text = gsub(text,"[\n\r] *","\n")
+ end
+ local name, appearance = analyzesymbol(specification.symbol)
+ local d = pdfdictionary {
+ Subtype = pdfconstant("Text"),
+ Open = specification.open,
+ Contents = pdfunicode(text),
+ T = (specification.title ~= "" and pdfunicode(specification.title)) or nil,
+ C = pdfcolorspec(specification.colormodel,specification.colorvalue),
+ OC = analyzelayer(specification.layer),
+ Name = name,
+ AP = appearance,
+ }
+ -- watch the nice feed back to tex hack
+ if usepopupcomments then
+ local nd = pdfreserveobject()
+ local nc = pdfreserveobject()
+ local c = pdfdictionary {
+ Subtype = pdfconstant("Popup"),
+ Parent = pdfreference(nd),
+ }
+ d.Popup = pdfreference(nc)
+ texbox["commentboxone"] = hpack_node(pdfannotation(0,0,0,d(),nd)) -- current dir
+ texbox["commentboxtwo"] = hpack_node(pdfannotation(specification.width,specification.height,0,c(),nc)) -- current dir
+ else
+ texbox["commentboxone"] = hpack_node(pdfannotation(0,0,0,d())) -- current dir
+ texbox["commentboxtwo"] = nil
+ end
+end
+
+--
+
+local nofattachments, attachments, filestreams = 0, { }, { }
+
+function codeinjections.embedfile(filename)
+ local r = filestreams[filename]
+ if r == false then
+ return nil
+ elseif r then
+ return r
+ elseif not lfs.isfile(filename) then
+ interfaces.showmessage("interactions",5,filename)
+ filestreams[filename] = false
+ return nil
+ else
+ local basename = file.basename(filename)
+ local a = pdfdictionary { Type = pdfconstant("EmbeddedFile") }
+ local f = pdfimmediateobj("streamfile",filename,a())
+ local d = pdfdictionary {
+ Type = pdfconstant("Filespec"),
+ F = pdfstring(newname or basename),
+ UF = pdfstring(newname or basename),
+ EF = pdfdictionary { F = pdfreference(f) },
+ }
+ local r = pdfreference(pdfflushobject(d))
+ filestreams[filename] = r
+ return r
+ end
+end
+
+function codeinjections.attachfile(specification)
+ local attachment = interactions.attachment(specification.label)
+ if not attachment then
+ -- todo: message
+ return
+ end
+ local filename = attachment.filename
+ if not filename or filename == "" then
+ -- todo: message
+ return
+ end
+ nofattachments = nofattachments + 1
+ local label = attachment.label or ""
+ local title = attachment.title or ""
+ local newname = attachment.newname or ""
+ if label == "" then label = filename end
+ if title == "" then title = label end
+ if newname == "" then newname = filename end
+ local aref = attachments[label]
+ if not aref then
+ aref = codeinjections.embedfile(filename,newname)
+ attachments[label] = aref
+ end
+ local name, appearance = analyzesymbol(specification.symbol)
+ local d = pdfdictionary {
+ Subtype = pdfconstant("FileAttachment"),
+ FS = aref,
+ Contents = pdfunicode(title),
+ Name = name,
+ AP = appearance,
+ OC = analyzelayer(specification.layer),
+ C = pdfcolorspec(specification.colormodel,specification.colorvalue),
+ }
+ -- as soon as we can ask for the dimensions of an xform we can
+ -- use them here
+ local width = specification.width or 0
+ local height = specification.height or 0
+ local depth = specification.depth or 0
+ write_node(pdfannotation(width,height,depth,d()))
+end
+
+function codeinjections.attachmentid(filename)
+ return filestreams[filename]
+end
+
+-- rendering stuff
+--
+-- object_1 -> <> >>
+-- object_2 -> <> >>
+-- rendering -> <>
+--
+-- we only work foreward here
+-- annotation is to be packed at the tex end
+
+-- aiff audio/aiff
+-- au audio/basic
+-- avi video/avi
+-- mid audio/midi
+-- mov video/quicktime
+-- mp3 audio/x-mp3 (mpeg)
+-- mp4 audio/mp4
+-- mp4 video/mp4
+-- mpeg video/mpeg
+-- smil application/smil
+-- swf application/x-shockwave-flash
+
+local ms, mu, mf = { }, { }, { }
+
+local delayed = { }
+
+local function insertrenderingwindow(label,width,height,specification)
+ if options == variables.auto then
+ if openpageaction then
+ -- \handlereferenceactions{\v!StartRendering{#2}}
+ end
+ if closepageaction then
+ -- \handlereferenceactions{\v!StopRendering {#2}}
+ end
+ end
+ local actions = nil
+ if openpage or closepage then
+ actions = pdfdictionary {
+ PO = (openpage and lpdf.pdfaction(openpage )) or nil,
+ PC = (closepage and lpdf.pdfaction(closepage)) or nil,
+ }
+ end
+ local page = tonumber(specification.page) or texcount.realpageno
+ local d = pdfdictionary {
+ Subtype = pdfconstant("Screen"),
+ P = pdfreference(tex.pdfpageref(page)),
+ A = mf[label],
+ Border = pdfarray { 0, 0, 0 } ,
+ AA = actions,
+ }
+ local r = pdfreserveobj("annot")
+ write_node(pdfannotation(width,height,0,d(),r)) -- save ref
+ return pdfreference(r)
+end
+
+local function insertrendering(specification)
+ local label = specification.label
+ if not mf[label] then
+ local filename = specification.filename
+ local isurl = find(filename,"://")
+ local d = pdfdictionary {
+ Type = pdfconstant("Rendition"),
+ S = pdfconstant("MR"),
+ C = pdfdictionary {
+ Type = pdfconstant("MediaClip"),
+ S = pdfconstant("MCD"),
+ N = label,
+ CT = specification.mime,
+ Alt = pdfarray {
+ "", "file not found", -- language id + message
+ },
+ D = pdfdictionary {
+ Type = pdfconstant("Filespec"),
+ F = filename,
+ FS = (isurl and pdfconstant("URL")) or nil,
+ }
+ }
+ }
+ mf[label] = pdfreference(pdfflushobject(d))
+ if not ms[label] then
+ mu[label] = insertrenderingwindow(label,0,0,specification.options)
+ end
+ end
+end
+
+local function insertrenderingobject(specification)
+ local label = specification.label
+ if not mf[label] then
+ local d = pdfdictionary {
+ Type = pdfconstant("Rendition"),
+ S = pdfconstant("MR"),
+ C = pdfdictionary {
+ Type = pdfconstant("MediaClip"),
+ S = pdfconstant("MCD"),
+ N = label,
+ D = pdfreference(unknown), -- not label but objectname, hm
+ }
+ }
+ mf[label] = pdfreference(pdfflushobject(d))
+ if ms[label] then
+ insertrenderingwindow(label,0,0,specification)
+ end
+ end
+end
+
+function codeinjections.insertrenderingwindow(specification)
+ local label = specification.label
+ codeinjections.processrendering(label) -- was check at tex end
+ ms[label] = insertrenderingwindow(label,specification.width,specification.height,specification)
+end
+
+function codeinjections.processrendering(label)
+ local specification = interactions.rendering(label)
+ if specification then
+ if specification.kind == "external" then
+ insertrendering(specification)
+ else
+ insertrenderingobject(specification)
+ end
+ end
+end
+
+local function set(operation,arguments)
+ codeinjections.processrendering(arguments) -- was check at the tex end
+ return pdfdictionary {
+ S = pdfconstant("Rendition"),
+ OP = operation,
+ R = mf[arguments],
+ AN = ms[arguments] or mu[arguments],
+ }
+end
+
+function executers.startrendering (arguments) return set(0,arguments) end
+function executers.stoprendering (arguments) return set(1,arguments) end
+function executers.pauserendering (arguments) return set(2,arguments) end
+function executers.resumerendering(arguments) return set(3,arguments) end
diff --git a/tex/context/base/lpdf-xmp.lua b/tex/context/base/lpdf-xmp.lua
new file mode 100644
index 000000000..c8e7b2b57
--- /dev/null
+++ b/tex/context/base/lpdf-xmp.lua
@@ -0,0 +1,165 @@
+if not modules then modules = { } end modules ['lpdf-xmp'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "with help from Peter Rolf",
+}
+
+local format, random, char, gsub, concat = string.format, math.random, string.char, string.gsub, table.concat
+local xmlfillin = xml.fillin
+
+local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end)
+
+local pdfdictionary = lpdf.dictionary
+local pdfconstant = lpdf.constant
+
+-- i wonder why this begin end is empty / w (no time now to look into it)
+
+local xpacket = [[
+
+
+%s
+
+]]
+
+local mapping = {
+ -- user defined keys (pdfx:)
+ ["ConTeXt.Jobname"] = "rdf:Description/pdfx:ConTeXt.Jobname",
+ ["ConTeXt.Time"] = "rdf:Description/pdfx:ConTeXt.Time",
+ ["ConTeXt.Url"] = "rdf:Description/pdfx:ConTeXt.Url",
+ ["ConTeXt.Version"] = "rdf:Description/pdfx:ConTeXt.Version",
+ ["ID"] = "rdf:Description/pdfx:ID",
+ ["PTEX.Fullbanner"] = "rdf:Description/pdfx:PTEX.Fullbanner",
+ -- Adobe PDF schema
+ ["Keywords"] = "rdf:Description/pdf:Keywords",
+ ["Producer"] = "rdf:Description/pdf:Producer",
+ -- ["Trapped"] = "rdf:Description/pdf:Trapped", -- '/False' in /Info, but 'False' in XMP
+ -- Dublin Core schema
+ ["Author"] = "rdf:Description/dc:creator/rdf:Seq/rdf:li",
+ ["Format"] = "rdf:Description/dc:format", -- optional, but nice to have
+ ["Subject"] = "rdf:Description/dc:description",
+ ["Title"] = "rdf:Description/dc:title/rdf:Alt/rdf:li",
+ -- XMP Basic schema
+ ["CreateDate"] = "rdf:Description/xmp:CreateDate",
+ ["Creator"] = "rdf:Description/xmp:CreatorTool",
+ ["MetadataDate"] = "rdf:Description/xmp:MetadataDate",
+ ["ModifyDate"] = "rdf:Description/xmp:ModifyDate",
+ -- XMP Media Management schema
+ ["DocumentID"] = "rdf:Description/xmpMM:DocumentID",
+ ["InstanceID"] = "rdf:Description/xmpMM:InstanceID",
+ ["RenditionClass"] = "rdf:Description/xmpMM:RenditionClass", -- PDF/X-4
+ ["VersionID"] = "rdf:Description/xmpMM:VersionID", -- PDF/X-4
+ -- additional entries
+ -- PDF/X
+ ["GTS_PDFXVersion"] = "rdf:Description/pdfxid:GTS_PDFXVersion",
+ -- optional entries
+ -- all what is visible in the 'document properties --> additional metadata' window
+ -- XMP Rights Management schema (optional)
+ ["Marked"] = "rdf:Description/xmpRights:Marked",
+ -- ["Owner"] = "rdf:Description/xmpRights:Owner/rdf:Bag/rdf:li", -- maybe useful (not visible)
+ -- ["UsageTerms"] = "rdf:Description/xmpRights:UsageTerms", -- maybe useful (not visible)
+ ["WebStatement"] = "rdf:Description/xmpRights:WebStatement",
+ -- Photoshop PDF schema (optional)
+ ["AuthorsPosition"] = "rdf:Description/photoshop:AuthorsPosition",
+ ["Copyright"] = "rdf:Description/photoshop:Copyright",
+ ["CaptionWriter"] = "rdf:Description/photoshop:CaptionWriter",
+}
+
+-- maybe some day we will load the xmp file at runtime
+
+local xmp, xmpfile, xmpname = nil, nil, "lpdf-xmp.xml"
+
+function lpdf.setxmpfile(name)
+ xmpfile = resolvers.findctxfile(name) or ""
+ if xmpfile == "" then
+ xmpfile = nil
+ end
+end
+
+local function valid_xmp()
+ if not xmp then
+ local xmpfile = xmpfile or resolvers.find_file(xmpname) or ""
+ local xmpdata = (xmpfile ~= "" and io.loaddata(xmpfile)) or ""
+ xmp = xml.convert(xmpdata)
+ end
+ return xmp
+end
+
+function lpdf.addxmpinfo(tag,value,check)
+ local pattern = mapping[tag]
+ if pattern then
+ xmlfillin(xmp or valid_xmp(),pattern,value,check)
+ end
+end
+
+-- redefined
+
+local addtoinfo = lpdf.addtoinfo
+local addxmpinfo = lpdf.addxmpinfo
+
+function lpdf.addtoinfo(tag,pdfvalue,strvalue)
+ addtoinfo(tag,pdfvalue)
+ addxmpinfo(tag,strvalue or gsub(tostring(pdfvalue),"^%((.*)%)$","%1")) -- hack
+end
+
+-- for the do-it-yourselvers
+
+function lpdf.insertxmpinfo(pattern,whatever,prepend)
+ xml.insert(xmp or valid_xmp(),pattern,whatever,prepend)
+end
+
+function lpdf.injectxmpinfo(pattern,whatever,prepend)
+ xml.inject(xmp or valid_xmp(),pattern,whatever,prepend)
+end
+
+-- flushing
+
+local t = { } for i=1,24 do t[i] = random() end
+
+local function flushxmpinfo()
+
+ commands.freezerandomseed(os.clock()) -- hack
+
+ local t = { } for i=1,24 do t[i] = char(96 + random(26)) end
+ local packetid = concat(t)
+ local time = lpdf.timestamp()
+ addxmpinfo("Producer",format("LuaTeX-%0.2f.%s",tex.luatexversion/100,tex.luatexrevision))
+ addxmpinfo("DocumentID",format("uuid:%s",os.uuid()))
+ addxmpinfo("InstanceID",format("uuid:%s",os.uuid()))
+ addxmpinfo("CreatorTool","LuaTeX + ConTeXt MkIV")
+ addxmpinfo("CreateDate",time)
+ addxmpinfo("ModifyDate",time)
+ addxmpinfo("MetadataDate",time)
+ addxmpinfo("PTEX.Fullbanner", tex.pdftexbanner)
+ local blob = xml.tostring(xml.first(xmp or valid_xmp(),"/x:xmpmeta"))
+ local md = pdfdictionary {
+ Subtype = pdfconstant("XML"),
+ Type = pdfconstant("Metadata"),
+ }
+ if trace_xmp then
+ commands.writestatus("system","xmp data flushed (see log file)")
+ texio.write_nl("log","")
+ texio.write("log","\n% ",(gsub(blob,"[\r\n]","\n%% ")),"\n")
+ end
+ blob = format(xpacket,packetid,blob)
+ if tex.pdfcompresslevel > 0 then
+ blob = gsub(blob,">%s+<","><")
+ end
+ local r = pdf.obj {
+ immediate = true,
+ compresslevel = 0,
+ type = "stream",
+ string = blob,
+ attr = md(),
+ }
+ lpdf.addtocatalog("Metadata",lpdf.reference(r))
+
+ commands.defrostrandomseed() -- hack
+
+end
+
+-- his will be enabled when we can inhibit compression for a stream at the lua end
+
+lpdf.registerdocumentfinalizer(flushxmpinfo,1)
diff --git a/tex/context/base/lpdf-xmp.xml b/tex/context/base/lpdf-xmp.xml
new file mode 100644
index 000000000..2947211bd
--- /dev/null
+++ b/tex/context/base/lpdf-xmp.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+ application/pdf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+
+
+
+
+
diff --git a/tex/context/base/luat-bas.mkiv b/tex/context/base/luat-bas.mkiv
new file mode 100644
index 000000000..581a5d95a
--- /dev/null
+++ b/tex/context/base/luat-bas.mkiv
@@ -0,0 +1,65 @@
+%D \module
+%D [ file=luat-bas, % moved from luat-lib,
+%D version=2006.09.11,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Basic \LUA\ Libraries,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Lua Macros / Basic Lua Libraries}
+
+%D This will move cq. become configurable. The XML like output is just
+%D an example.
+
+% todo \let\normaleverytoks\everytoks \newtoks\everytoke \normaleverytoks{\the\everytoks}
+
+\chardef\statuswidth=15
+\chardef\statuswrite=16
+
+\newtoks\everywritestring
+
+\def\writedirect {\immediate\write\statuswrite}
+\def\writeline {\writedirect{}}
+\def\writestring#1{\begingroup\the\everywritestring\writedirect{#1}\endgroup}
+
+\ifx\normalwritestatus\undefined \def\normalwritestatus#1#2{\writedirect{#1 : #2}} \fi
+
+% Because all libs are also on bytecodes we can start without stub. However,
+% some initializations need to take place before the \TEX\ engine itself
+% kicks in, especially memory settings and so. In due time we might make the
+% stub smaller and just create a configuration startup file.
+
+\registerctxluafile{l-string} {1.001}
+\registerctxluafile{l-lpeg} {1.001}
+\registerctxluafile{l-boolean}{1.001}
+\registerctxluafile{l-number} {1.001}
+\registerctxluafile{l-math} {1.001}
+\registerctxluafile{l-table} {1.001}
+\registerctxluafile{l-aux} {1.001}
+\registerctxluafile{l-io} {1.001}
+\registerctxluafile{l-os} {1.001}
+\registerctxluafile{l-file} {1.001}
+\registerctxluafile{l-md5} {1.001}
+\registerctxluafile{l-dir} {1.001}
+\registerctxluafile{l-unicode}{1.001}
+\registerctxluafile{l-utils} {1.001}
+\registerctxluafile{l-dimen} {1.001}
+\registerctxluafile{l-url} {1.001}
+\registerctxluafile{l-set} {1.001}
+\registerctxluafile{l-dimen} {1.001}
+
+% \registerctxluafile{socket.lua}{}
+% \registerctxluafile{ltn12.lua} {}
+% \registerctxluafile{mime.lua} {}
+% \registerctxluafile{http.lua} {}
+% \registerctxluafile{url.lua} {}
+% \registerctxluafile{tp.lua} {}
+% \registerctxluafile{ftp.lua} {}
+% %registerctxluafile{smtp.lua} {}
+
+\endinput
diff --git a/tex/context/base/luat-cbk.lua b/tex/context/base/luat-cbk.lua
new file mode 100644
index 000000000..3cb63ad6e
--- /dev/null
+++ b/tex/context/base/luat-cbk.lua
@@ -0,0 +1,247 @@
+if not modules then modules = { } end modules ['luat-cbk'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local insert, remove, find = table.insert, table.remove, string.find
+local collectgarbage, type, next = collectgarbage, type, next
+local round = math.round
+
+local trace_checking = false trackers.register("memory.checking", function(v) trace_checking = v end)
+
+--[[ldx--
+
Callbacks are the real asset of . They permit you to hook
+your own code into the engine. Here we implement a few handy
+auxiliary functions.
When you (temporarily) want to install a callback function, and after a
+while wants to revert to the original one, you can use the following two
+functions.
+--ldx]]--
+
+local trace_callbacks = false trackers.register("system.callbacks", function(v) trace_callbacks = v end)
+
+local register_callback, find_callback = callback.register, callback.find
+local frozen, stack = { }, { }
+
+callback.original_register_callback = register_callback
+
+local function frozen_message(what,name)
+ logs.report("callbacks","not %s frozen '%s' (%s)",what,name,frozen[name])
+end
+
+local function frozen_callback(name)
+ return nil, format("callback '%s' is frozen (%s)",name,frozen[name])
+end
+
+local function state(name)
+ local f = find_callback(name)
+ if f == false then
+ return "disabled"
+ elseif f then
+ return "enabled"
+ else
+ return "undefined"
+ end
+end
+
+function callbacks.report()
+ local list = callback.list()
+ for name, func in table.sortedhash(list) do
+ local str = frozen[name]
+ if str then
+ logs.report("callbacks","%s: %s -> %s",state(name),name,str)
+ else
+ logs.report("callbacks","%s: %s",state(name),name)
+ end
+ end
+end
+
+function callbacks.table()
+ local NC, NR, verbatim = context.NC, context.NR, context.type
+ context.starttabulate { "|l|l|p|" }
+ for name, func in table.sortedhash(callback.list()) do
+ NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR()
+ end
+ context.stoptabulate()
+end
+
+function callbacks.freeze(name,freeze)
+ freeze = type(freeze) == "string" and freeze
+--~ print(name)
+ if find(name,"%*") then
+ local pattern = name -- string.simpleesc(name)
+ local list = callback.list()
+ for name, func in next, list do
+ if find(name,pattern) then
+ frozen[name] = freeze or frozen[name] or "frozen"
+ end
+ end
+ else
+ frozen[name] = freeze or frozen[name] or "frozen"
+ end
+end
+
+function callbacks.register(name,func,freeze)
+ if frozen[name] then
+ if trace_callbacks then
+ frozen_message("registering",name)
+ end
+ return frozen_callback(name)
+ elseif freeze then
+ frozen[name] = (type(freeze) == "string" and freeze) or "registered"
+ end
+ return register_callback(name,func)
+end
+
+function callback.register(name,func) -- original
+ if not frozen[name] then
+ return register_callback(name,func)
+ elseif trace_callbacks then
+ frozen_message("registering",name)
+ end
+ return frozen_callback(name)
+end
+
+function callbacks.push(name, func)
+ if not frozen[name] then
+ local sn = stack[name]
+ if not sn then
+ sn = { }
+ stack[name] = sn
+ end
+ insert(sn,find_callback(name))
+ register_callback(name, func)
+ elseif trace_callbacks then
+ frozen_message("pushing",name)
+ end
+end
+
+function callbacks.pop(name)
+ if not frozen[name] then
+ local sn = stack[name]
+ if not sn or #sn == 0 then
+ -- some error
+ register_callback(name, nil) -- ! really needed
+ else
+ -- this fails: register_callback(name, remove(stack[name]))
+ local func = remove(sn)
+ register_callback(name, func)
+ end
+ end
+end
+
+--~ -- somehow crashes later on
+--~
+--~ callbacks.freeze("find_.*_file","finding file")
+--~ callbacks.freeze("read_.*_file","reading file")
+--~ callbacks.freeze("open_.*_file","opening file")
+
+--[[ldx--
+
Callbacks may result in doing some hard work
+which takes time and above all resourses. Sometimes it makes
+sense to disable or tune the garbage collector in order to
+keep the use of resources acceptable.
+
+
At some point in the development we did some tests with counting
+nodes (in this case 121049).
+
+
+
setstepmul
seconds
megabytes
+
200
24.0
80.5
+
175
21.0
78.2
+
150
22.0
74.6
+
160
22.0
74.6
+
165
21.0
77.6
+
125
21.5
89.2
+
100
21.5
88.4
+
+
+
The following code is kind of experimental. In the documents
+that describe the development of we report
+on speed tests. One observation is thta it sometimes helps to
+restart the collector. Okay, experimental code has been removed,
+because messing aroudn with the gc is too unpredictable.
+--ldx]]--
+
+garbagecollector = garbagecollector or { }
+
+garbagecollector.enabled = false
+garbagecollector.criterium = 4*1024*1024
+
+-- Lua allocates up to 12 times the amount of memory needed for
+-- handling a string, and for large binary chunks (like chinese otf
+-- files) we get a prominent memory consumption. Even when a variable
+-- is nilled, there is some delay in freeing the associated memory (the
+-- hashed string) because if we do the same thing directly afterwards,
+-- we see only a slight increase in memory. For that reason it makes
+-- sense to do a collector pass after a huge file.
+--
+-- test file:
+--
+-- function test()
+-- local b = collectgarbage("count")
+-- local s = io.loaddata("some font table, e.g. a big tmc file")
+-- local a = collectgarbage("count")
+-- print(">>> STATUS",b,a,a-b,#s,1000*(a-b)/#s)
+-- end
+--
+-- test() test() test() test() collectgarbage("collect") test() test() test() test()
+--
+-- As a result of this, LuaTeX now uses an optimized version of f:read("*a"),
+-- one that does not use the 4K allocations but allocates in one step.
+
+function garbagecollector.check(size,criterium)
+ if garbagecollector.enabled then
+ criterium = criterium or garbagecollector.criterium
+ if not size or (criterium and criterium > 0 and size > criterium) then
+ if trace_checking then
+ local b = collectgarbage("count")
+ collectgarbage("collect")
+ local a = collectgarbage("count")
+ logs.report("memory","forced sweep, collected: %s MB, used: %s MB",round((b-a)/1000),round(a/1000))
+ else
+ collectgarbage("collect")
+ end
+ end
+ end
+end
diff --git a/tex/context/base/luat-cnf.lua b/tex/context/base/luat-cnf.lua
new file mode 100644
index 000000000..e45aceb79
--- /dev/null
+++ b/tex/context/base/luat-cnf.lua
@@ -0,0 +1,115 @@
+if not modules then modules = { } end modules ['luat-cnf'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, concat, find = string.format, table.concat, string.find
+
+luatex = luatex or { }
+
+luatex.variablenames = {
+ 'main_memory', 'extra_mem_bot', 'extra_mem_top',
+ 'buf_size','expand_depth',
+ 'font_max', 'font_mem_size',
+ 'hash_extra', 'max_strings', 'pool_free', 'pool_size', 'string_vacancies',
+ 'obj_tab_size', 'pdf_mem_size', 'dest_names_size',
+ 'nest_size', 'param_size', 'save_size', 'stack_size','expand_depth',
+ 'trie_size', 'hyph_size', 'max_in_open',
+ 'ocp_stack_size', 'ocp_list_size', 'ocp_buf_size',
+ 'max_print_line',
+}
+
+function luatex.variables()
+ local t, x = { }, nil
+ for _,v in next, luatex.variablenames do
+ x = resolvers.var_value(v)
+ if x and find(x,"^%d+$") then
+ t[v] = tonumber(x)
+ end
+ end
+ return t
+end
+
+if not luatex.variables_set then
+ for k, v in next, luatex.variables() do
+ texconfig[k] = v
+ end
+ luatex.variables_set = true
+end
+
+local stub = [[
+-- checking
+
+storage = storage or { }
+luatex = luatex or { }
+
+-- we provide our own file handling
+
+texconfig.kpse_init = false
+texconfig.shell_escape = 't'
+
+-- as soon as possible
+
+luatex.starttime = os.gettimeofday()
+
+-- this will happen after the format is loaded
+
+function texconfig.init()
+
+ -- shortcut and helper
+
+ local b = lua.bytecode
+
+ local function init(start)
+ local i = start
+ while b[i] do
+ b[i]() ; b[i] = nil ; i = i + 1
+ -- collectgarbage('step')
+ end
+ return i - start
+ end
+
+ -- the stored tables and modules
+
+ storage.noftables = init(0)
+ storage.nofmodules = init(%s)
+
+end
+
+-- we provide a qualified path
+
+callback.register('find_format_file',function(name)
+ texconfig.formatname = name
+ return name
+end)
+
+-- done, from now on input and callbacks are internal
+]]
+
+function luatex.dumpstate(name,firsttable)
+ if tex and tex.luatexversion < 38 then
+ os.remove(name)
+ elseif true then
+ local t = {
+ "-- this file is generated, don't change it\n",
+ "-- configuration (can be overloaded later)\n"
+ }
+ for _,v in next, luatex.variablenames do
+ local tv = texconfig[v]
+ if tv then
+ t[#t+1] = format("texconfig.%s=%s",v,tv)
+ end
+ end
+ io.savedata(name,format("%s\n\n%s",concat(t,"\n"),format(stub,firsttable or 501)))
+ else
+ io.savedata(name,format(stub,firsttable or 501))
+ end
+end
+
+texconfig.kpse_init = false
+texconfig.max_print_line = 100000
+texconfig.max_in_open = 127
+texconfig.shell_escape = 't'
diff --git a/tex/context/base/luat-cod.mkiv b/tex/context/base/luat-cod.mkiv
new file mode 100644
index 000000000..d3b37d0e1
--- /dev/null
+++ b/tex/context/base/luat-cod.mkiv
@@ -0,0 +1,161 @@
+%D \module
+%D [ file=luat-cod,
+%D version=2005.05.26,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Code,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Lua Macros / Code}
+
+%D Originally we compiled the lua files externally and loaded
+%D then at runtime, but when the amount grew, we realized that
+%D we needed away to store them in the format, which is what
+%D bytecode arrays do. And so the following is obsolete:
+%D
+%D \starttyping
+%D \chardef\ctxluaembeddingmode \plusone
+%D
+%D 0 = external compilation and loading
+%D 1 = runtime compilation and embedding
+%D \stoptyping
+%D
+%D Allocation of \LUA\ engines has changed too. The original idea
+%D was to have multiple \LUA\ instances and it worked that way for
+%D several years. Hoewver in practice we used only one engine because
+%D scripts need to share data anyway. So eventually \LUATEX\ got only
+%D one instance. Because each call is reentrant there is not much
+%D danger for crashes.
+
+\def\ctxdirectlua{\directlua\zerocount}
+\def\ctxlatelua {\latelua \zerocount}
+
+%D Take your choice \unknown
+
+\let\ctxlua \ctxdirectlua
+\let\luacode \ctxdirectlua
+\let\lateluacode \ctxlatelua
+\let\directluacode\ctxdirectlua
+
+%D Reporting the version of \LUA\ that we use is done as follows:
+
+\edef\luaversion{\ctxlua{tex.print(_VERSION)}}
+
+%D We want to define \LUA\ related things in the format but
+%D need to reload code because \LUA\ instances themselves are
+%D not dumped into the format.
+
+\newtoks\everyloadluacode
+\newtoks\everyfinalizeluacode
+
+\normaleveryjob{\the\everyloadluacode\the\everyfinalizeluacode\the\everyjob}
+
+\newif\ifproductionrun
+
+%D Here we operate in the \TEX\ catcode regime as we haven't yet defined
+%D catcode regimes. A chicken or egg problem.
+
+\normalprotected\long\def\startruntimeluacode#1\stopruntimeluacode % only simple code (load +init)
+ {\ifproductionrun
+ \global\let\startruntimeluacode\relax
+ \global\let\stopruntimeluacode \relax
+ \else
+ \global\everyloadluacode\expandafter{\the\everyloadluacode#1}%
+ \fi
+ #1} % maybe no interference
+
+\normalprotected\long\def\startruntimectxluacode#1\stopruntimectxluacode
+ {\startruntimeluacode\ctxlua{#1}\stopruntimeluacode}
+
+%D Next we load the initialization code.
+
+\startruntimectxluacode
+ environment = environment or { }
+ environment.jobname = "\jobname" % tex.jobname
+ environment.initex = \ifproductionrun false \else true \fi % tex.formatname == ""
+ environment.version = "\fmtversion"
+\stopruntimectxluacode
+
+% we start at 500, below this, we store predefined data (dumps)
+
+\newcount\luabytecodecounter \luabytecodecounter=500
+
+\startruntimectxluacode
+ lua.bytedata = lua.bytedata or { }
+\stopruntimectxluacode
+
+%D Handy when we expand:
+
+\let\stopruntimeluacode \relax
+\let\stopruntimectxluacode\relax
+
+\long\def\lastexpanded{} % todo: elsewhere we use \@@expanded
+
+\long\def\expanded#1{\long\xdef\lastexpanded{\noexpand#1}\lastexpanded}
+
+%D More code:
+
+% \def\ctxluabytecode#1% executes an already loaded chunk
+% {\ctxlua {
+% local str = ''
+% if lua.bytedata[#1] then
+% str = " from file " .. lua.bytedata[#1][1] .. " version " .. lua.bytedata[#1][2]
+% end
+% if lua.bytecode[#1] then
+% if environment.initex then
+% texio.write_nl("bytecode: executing blob " .. "#1" .. str)
+% assert(lua.bytecode[#1])()
+% else
+% texio.write_nl("bytecode: initializing blob " .. "#1" .. str)
+% assert(lua.bytecode[#1])()
+% lua.bytecode[#1] = nil
+% end
+% else
+% texio.write_nl("bytecode: invalid blob " .. "#1" .. str)
+% end
+% }}
+
+\def\ctxluabytecode#1% executes an already loaded chunk
+ {\ctxlua {
+ local lbc = lua.bytecode
+ if lbc[#1] then
+ assert(lbc[#1])()
+ if not environment.initex then
+ lbc[#1] = nil
+ end
+ end
+ }}
+
+\def\ctxluabyteload#1#2% registers and compiles chunk
+ {\global\advance\luabytecodecounter \plusone
+ \normalexpanded{\startruntimectxluacode
+ lua.bytedata[\the\luabytecodecounter] = { "#1", "#2" }
+ \stopruntimectxluacode}%
+ \ctxlua {
+ lua.bytedata[\the\luabytecodecounter] = { "#1", "#2" }
+ lua.bytecode[\the\luabytecodecounter] = environment.luafilechunk("#1")
+ }}
+
+\def\ctxloadluafile#1#2% load a (either not compiled) chunk at runtime
+ {\doifelsenothing{#2}
+ {\ctxlua{environment.loadluafile("#1")}}
+ {\ctxlua{environment.loadluafile("#1",#2)}}}
+
+\def\registerctxluafile#1#2% name version (modules and core code)
+ {\ifproductionrun
+ \ctxloadluafile{#1}{#2}%
+ \else
+ \ctxluabyteload{#1}{#2}% can go away
+ \fi
+ \global\everyloadluacode\expandafter\expandafter\expandafter{\expandafter\the\expandafter\everyloadluacode
+ \expandafter\ctxluabytecode\expandafter{\the\luabytecodecounter}}%
+ \ctxluabytecode{\the\luabytecodecounter}}
+
+\everydump\expandafter{\the\everydump\ctxlua{luatex.dumpstate(environment.jobname..".lui",501)}}
+
+\endinput
diff --git a/tex/context/base/luat-dum.lua b/tex/context/base/luat-dum.lua
new file mode 100644
index 000000000..4530c2ef3
--- /dev/null
+++ b/tex/context/base/luat-dum.lua
@@ -0,0 +1,126 @@
+if not modules then modules = { } end modules ['luat-dum'] = {
+ version = 1.001,
+ comment = "companion to luatex-*.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local dummyfunction = function() end
+
+statistics = {
+ register = dummyfunction,
+ starttiming = dummyfunction,
+ stoptiming = dummyfunction,
+}
+directives = {
+ register = dummyfunction,
+ enable = dummyfunction,
+ disable = dummyfunction,
+}
+trackers = {
+ register = dummyfunction,
+ enable = dummyfunction,
+ disable = dummyfunction,
+}
+experiments = {
+ register = dummyfunction,
+ enable = dummyfunction,
+ disable = dummyfunction,
+}
+storage = {
+ register = dummyfunction,
+ shared = { },
+}
+logs = {
+ report = dummyfunction,
+ simple = dummyfunction,
+}
+tasks = {
+ new = dummyfunction,
+ actions = dummyfunction,
+ appendaction = dummyfunction,
+ prependaction = dummyfunction,
+}
+callbacks = {
+ register = function(n,f) return callback.register(n,f) end,
+}
+
+-- we need to cheat a bit here
+
+texconfig.kpse_init = true
+
+resolvers = resolvers or { } -- no fancy file helpers used
+
+local remapper = {
+ otf = "opentype fonts",
+ ttf = "truetype fonts",
+ ttc = "truetype fonts",
+ dfont = "truetype dictionary",
+ cid = "cid maps",
+ fea = "font feature files",
+}
+
+function resolvers.find_file(name,kind)
+ name = string.gsub(name,"\\","\/")
+ kind = string.lower(kind)
+ return kpse.find_file(name,(kind and kind ~= "" and (remapper[kind] or kind)) or file.extname(name,"tex"))
+end
+
+function resolvers.findbinfile(name,kind)
+ if not kind or kind == "" then
+ kind = file.extname(name) -- string.match(name,"%.([^%.]-)$")
+ end
+ return resolvers.find_file(name,(kind and remapper[kind]) or kind)
+end
+
+-- Caches ... I will make a real stupid version some day when I'm in the
+-- mood. After all, the generic code does not need the more advanced
+-- ConTeXt features. Cached data is not shared between ConTeXt and other
+-- usage as I don't want any dependency at all. Also, ConTeXt might have
+-- different needs and tricks added.
+
+caches = { }
+
+--~ containers.usecache = true
+
+function caches.setpath(category,subcategory)
+ local root = kpse.var_value("TEXMFCACHE") or ""
+ if root == "" then
+ root = kpse.var_value("VARTEXMF") or ""
+ end
+ if root ~= "" then
+ root = file.join(root,category)
+ lfs.mkdir(root)
+ root = file.join(root,subcategory)
+ lfs.mkdir(root)
+ return lfs.isdir(root) and root
+ end
+end
+
+local function makefullname(path,name)
+ if path and path ~= "" then
+ name = "temp-" and name -- clash prevention
+ return file.addsuffix(file.join(path,name),"lua")
+ end
+end
+
+function caches.iswritable(path,name)
+ local fullname = makefullname(path,name)
+ return fullname and file.iswritable(fullname)
+end
+
+function caches.loaddata(path,name)
+ local fullname = makefullname(path,name)
+ if fullname then
+ local data = loadfile(fullname)
+ return data and data()
+ end
+end
+
+function caches.savedata(path,name,data)
+ local fullname = makefullname(path,name)
+ if fullname then
+ table.tofile(fullname,data,'return',false,true,false)
+ end
+end
diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua
new file mode 100644
index 000000000..0e21fca31
--- /dev/null
+++ b/tex/context/base/luat-env.lua
@@ -0,0 +1,283 @@
+if not modules then modules = { } end modules ['luat-env'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A former version provided functionality for non embeded core
+-- scripts i.e. runtime library loading. Given the amount of
+-- Lua code we use now, this no longer makes sense. Much of this
+-- evolved before bytecode arrays were available and so a lot of
+-- code has disappeared already.
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
+local unquote, quote = string.unquote, string.quote
+
+-- precautions
+
+os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
+
+function os.setlocale()
+ -- no way you can mess with it
+end
+
+-- dirty tricks
+
+if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+ arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
+end
+
+if profiler and os.env["MTX_PROFILE_RUN"] == "YES" then
+ profiler.start("luatex-profile.log")
+end
+
+-- environment
+
+environment = environment or { }
+environment.arguments = { }
+environment.files = { }
+environment.sortedflags = nil
+
+if not environment.jobname or environment.jobname == "" then if tex then environment.jobname = tex.jobname end end
+if not environment.version or environment.version == "" then environment.version = "unknown" end
+if not environment.jobname then environment.jobname = "unknown" end
+
+function environment.initialize_arguments(arg)
+ local arguments, files = { }, { }
+ environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
+ for index=1,#arg do
+ local argument = arg[index]
+ if index > 0 then
+ local flag, value = match(argument,"^%-+(.-)=(.-)$")
+ if flag then
+ arguments[flag] = unquote(value or "")
+ else
+ flag = match(argument,"^%-+(.+)")
+ if flag then
+ arguments[flag] = true
+ else
+ files[#files+1] = argument
+ end
+ end
+ end
+ end
+ environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
+end
+
+function environment.setargument(name,value)
+ environment.arguments[name] = value
+end
+
+-- todo: defaults, better checks e.g on type (boolean versus string)
+--
+-- tricky: too many hits when we support partials unless we add
+-- a registration of arguments so from now on we have 'partial'
+
+function environment.argument(name,partial)
+ local arguments, sortedflags = environment.arguments, environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ elseif partial then
+ if not sortedflags then
+ sortedflags = table.sortedkeys(arguments)
+ for k=1,#sortedflags do
+ sortedflags[k] = "^" .. sortedflags[k]
+ end
+ environment.sortedflags = sortedflags
+ end
+ -- example of potential clash: ^mode ^modefile
+ for k=1,#sortedflags do
+ local v = sortedflags[k]
+ if find(name,v) then
+ return arguments[sub(v,2,#v)]
+ end
+ end
+ end
+ return nil
+end
+
+environment.argument("x",true)
+
+function environment.split_arguments(separator) -- rather special, cut-off before separator
+ local done, before, after = false, { }, { }
+ local original_arguments = environment.original_arguments
+ for k=1,#original_arguments do
+ local v = original_arguments[k]
+ if not done and v == separator then
+ done = true
+ elseif done then
+ after[#after+1] = v
+ else
+ before[#before+1] = v
+ end
+ end
+ return before, after
+end
+
+function environment.reconstruct_commandline(arg,noquote)
+ arg = arg or environment.original_arguments
+ if noquote and #arg == 1 then
+ local a = arg[1]
+ a = resolvers.resolve(a)
+ a = unquote(a)
+ return a
+ elseif #arg > 0 then
+ local result = { }
+ for i=1,#arg do
+ local a = arg[i]
+ a = resolvers.resolve(a)
+ a = unquote(a)
+ a = gsub(a,'"','\\"') -- tricky
+ if find(a," ") then
+ result[#result+1] = quote(a)
+ else
+ result[#result+1] = a
+ end
+ end
+ return table.join(result," ")
+ else
+ return ""
+ end
+end
+
+if arg then
+
+ -- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
+ local newarg, instring = { }, false
+
+ for index=1,#arg do
+ local argument = arg[index]
+ if find(argument,"^\"") then
+ newarg[#newarg+1] = gsub(argument,"^\"","")
+ if not find(argument,"\"$") then
+ instring = true
+ end
+ elseif find(argument,"\"$") then
+ newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","")
+ instring = false
+ elseif instring then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument
+ else
+ newarg[#newarg+1] = argument
+ end
+ end
+ for i=1,-5,-1 do
+ newarg[i] = arg[i]
+ end
+
+ environment.initialize_arguments(newarg)
+ environment.original_arguments = newarg
+ environment.raw_arguments = arg
+
+ arg = { } -- prevent duplicate handling
+
+end
+
+-- weird place ... depends on a not yet loaded module
+
+function environment.texfile(filename)
+ return resolvers.find_file(filename,'tex')
+end
+
+function environment.luafile(filename)
+ local resolved = resolvers.find_file(filename,'tex') or ""
+ if resolved ~= "" then
+ return resolved
+ end
+ resolved = resolvers.find_file(filename,'texmfscripts') or ""
+ if resolved ~= "" then
+ return resolved
+ end
+ return resolvers.find_file(filename,'luatexlibs') or ""
+end
+
+environment.loadedluacode = loadfile -- can be overloaded
+
+--~ function environment.loadedluacode(name)
+--~ if os.spawn("texluac -s -o texluac.luc " .. name) == 0 then
+--~ local chunk = loadstring(io.loaddata("texluac.luc"))
+--~ os.remove("texluac.luc")
+--~ return chunk
+--~ else
+--~ environment.loadedluacode = loadfile -- can be overloaded
+--~ return loadfile(name)
+--~ end
+--~ end
+
+function environment.luafilechunk(filename) -- used for loading lua bytecode in the format
+ filename = file.replacesuffix(filename, "lua")
+ local fullname = environment.luafile(filename)
+ if fullname and fullname ~= "" then
+ if trace_locating then
+ logs.report("fileio","loading file %s", fullname)
+ end
+ return environment.loadedluacode(fullname)
+ else
+ if trace_locating then
+ logs.report("fileio","unknown file %s", filename)
+ end
+ return nil
+ end
+end
+
+-- the next ones can use the previous ones / combine
+
+function environment.loadluafile(filename, version)
+ local lucname, luaname, chunk
+ local basename = file.removesuffix(filename)
+ if basename == filename then
+ lucname, luaname = basename .. ".luc", basename .. ".lua"
+ else
+ lucname, luaname = nil, basename -- forced suffix
+ end
+ -- when not overloaded by explicit suffix we look for a luc file first
+ local fullname = (lucname and environment.luafile(lucname)) or ""
+ if fullname ~= "" then
+ if trace_locating then
+ logs.report("fileio","loading %s", fullname)
+ end
+ chunk = loadfile(fullname) -- this way we don't need a file exists check
+ end
+ if chunk then
+ assert(chunk)()
+ if version then
+ -- we check of the version number of this chunk matches
+ local v = version -- can be nil
+ if modules and modules[filename] then
+ v = modules[filename].version -- new method
+ elseif versions and versions[filename] then
+ v = versions[filename] -- old method
+ end
+ if v == version then
+ return true
+ else
+ if trace_locating then
+ logs.report("fileio","version mismatch for %s: lua=%s, luc=%s", filename, v, version)
+ end
+ environment.loadluafile(filename)
+ end
+ else
+ return true
+ end
+ end
+ fullname = (luaname and environment.luafile(luaname)) or ""
+ if fullname ~= "" then
+ if trace_locating then
+ logs.report("fileio","loading %s", fullname)
+ end
+ chunk = loadfile(fullname) -- this way we don't need a file exists check
+ if not chunk then
+ if trace_locating then
+ logs.report("fileio","unknown file %s", filename)
+ end
+ else
+ assert(chunk)()
+ return true
+ end
+ end
+ return false
+end
diff --git a/tex/context/base/luat-exe.lua b/tex/context/base/luat-exe.lua
new file mode 100644
index 000000000..ca3b75162
--- /dev/null
+++ b/tex/context/base/luat-exe.lua
@@ -0,0 +1,71 @@
+if not modules then modules = { } end modules ['luat-exe'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local match, find = string.match, string.find
+local concat = table.concat
+
+if not executer then executer = { } end
+
+executer.permitted = { }
+executer.execute = os.execute
+
+function executer.register(...)
+ local ep = executer.permitted
+ local t = { ... }
+ for k=1,#t do
+ local v = t[k]
+ ep[#ep+1] = (v == "*" and ".*") or v
+ end
+end
+
+function executer.finalize() -- todo: os.exec, todo: report ipv print
+ local execute = os.execute
+ function executer.execute(...)
+ local t, name, arguments = {...}, "", ""
+ if #t == 1 then
+ if type(t[1]) == 'table' then
+ name, arguments = t[1], concat(t," ",2,#t)
+ else
+ name, arguments = match(t[1],"^(.-)%s+(.+)$")
+ if not (name and arguments) then
+ name, arguments = t[1], ""
+ end
+ end
+ else
+ name, arguments = t[1], concat(t," ",2,#t)
+ end
+ local permitted = executer.permitted
+ for k=1,#permitted do
+ local v = permitted[k]
+ if find(name,v) then
+ execute(name .. " " .. arguments)
+ -- print("executed: " .. name .. " " .. arguments)
+ else
+ print("not permitted: " .. name .. " " .. arguments)
+ end
+ end
+ end
+ function executer.finalize()
+ print("executer is already finalized")
+ end
+ function executer.register(name)
+ print("executer is already finalized")
+ end
+ os.execute = executer.execute
+end
+
+--~ executer.register('.*')
+--~ executer.register('*')
+--~ executer.register('dir','ls')
+--~ executer.register('dir')
+
+--~ executer.finalize()
+--~ executer.execute('dir',"*.tex")
+--~ executer.execute("dir *.tex")
+--~ executer.execute("ls *.tex")
+--~ os.execute('ls')
diff --git a/tex/context/base/luat-fio.lua b/tex/context/base/luat-fio.lua
new file mode 100644
index 000000000..0d1bd1808
--- /dev/null
+++ b/tex/context/base/luat-fio.lua
@@ -0,0 +1,83 @@
+if not modules then modules = { } end modules ['luat-fio'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local texiowrite_nl = (texio and texio.write_nl) or print
+local texiowrite = (texio and texio.write) or print
+
+local format = string.format
+
+texconfig.kpse_init = false
+texconfig.trace_file_names = true -- also influences pdf fonts reporting .. todo
+texconfig.max_print_line = 100000
+
+kpse = { } setmetatable(kpse, { __index = function(k,v) return input[v] end } )
+
+-- if still present, we overload kpse (put it off-line so to say)
+
+if not resolvers.instance then
+
+ resolvers.reset()
+
+ resolvers.instance.progname = 'context'
+ resolvers.instance.engine = 'luatex'
+ resolvers.instance.validfile = resolvers.validctxfile
+
+ resolvers.load()
+
+ if callback then
+
+ callback.register('find_read_file' , function(id,name) return resolvers.findtexfile(name) end)
+ callback.register('open_read_file' , function( name) return resolvers.opentexfile(name) end)
+
+ callback.register('find_data_file' , function(name) return resolvers.findbinfile(name,"tex") end)
+ callback.register('find_enc_file' , function(name) return resolvers.findbinfile(name,"enc") end)
+ callback.register('find_font_file' , function(name) return resolvers.findbinfile(name,"tfm") end)
+ callback.register('find_format_file' , function(name) return resolvers.findbinfile(name,"fmt") end)
+ callback.register('find_image_file' , function(name) return resolvers.findbinfile(name,"tex") end)
+ callback.register('find_map_file' , function(name) return resolvers.findbinfile(name,"map") end)
+ callback.register('find_ocp_file' , function(name) return resolvers.findbinfile(name,"ocp") end)
+ callback.register('find_opentype_file' , function(name) return resolvers.findbinfile(name,"otf") end)
+ callback.register('find_output_file' , function(name) return name end)
+ callback.register('find_pk_file' , function(name) return resolvers.findbinfile(name,"pk") end)
+ callback.register('find_sfd_file' , function(name) return resolvers.findbinfile(name,"sfd") end)
+ callback.register('find_truetype_file' , function(name) return resolvers.findbinfile(name,"ttf") end)
+ callback.register('find_type1_file' , function(name) return resolvers.findbinfile(name,"pfb") end)
+ callback.register('find_vf_file' , function(name) return resolvers.findbinfile(name,"vf") end)
+
+ callback.register('read_data_file' , function(file) return resolvers.loadbinfile(file,"tex") end)
+ callback.register('read_enc_file' , function(file) return resolvers.loadbinfile(file,"enc") end)
+ callback.register('read_font_file' , function(file) return resolvers.loadbinfile(file,"tfm") end)
+ -- format
+ -- image
+ callback.register('read_map_file' , function(file) return resolvers.loadbinfile(file,"map") end)
+ callback.register('read_ocp_file' , function(file) return resolvers.loadbinfile(file,"ocp") end)
+ -- output
+ callback.register('read_pk_file' , function(file) return resolvers.loadbinfile(file,"pk") end) -- 600dpi/manfnt.720pk
+ callback.register('read_sfd_file' , function(file) return resolvers.loadbinfile(file,"sfd") end)
+ callback.register('read_vf_file' , function(file) return resolvers.loadbinfile(file,"vf" ) end)
+
+ callback.register('find_font_file' , function(name) return resolvers.findbinfile(name,"ofm") end)
+ callback.register('find_vf_file' , function(name) return resolvers.findbinfile(name,"ovf") end)
+
+ callback.register('read_font_file' , function(file) return resolvers.loadbinfile(file,"ofm") end)
+ callback.register('read_vf_file' , function(file) return resolvers.loadbinfile(file,"ovf") end)
+
+ -- callback.register('read_opentype_file' , function(file) return resolvers.loadbinfile(file,"otf") end)
+ -- callback.register('read_truetype_file' , function(file) return resolvers.loadbinfile(file,"ttf") end)
+ -- callback.register('read_type1_file' , function(file) return resolvers.loadbinfile(file,"pfb") end)
+
+ callback.register('find_write_file' , function(id,name) return name end)
+ callback.register('find_format_file' , function(name) return name end)
+
+ end
+
+end
+
+statistics.register("input load time", function()
+ return format("%s seconds", statistics.elapsedtime(resolvers.instance))
+end)
diff --git a/tex/context/base/luat-ini.lua b/tex/context/base/luat-ini.lua
new file mode 100644
index 000000000..e6a715c07
--- /dev/null
+++ b/tex/context/base/luat-ini.lua
@@ -0,0 +1,162 @@
+if not modules then modules = { } end modules ['luat-ini'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--~ local ctxcatcodes = tex.ctxcatcodes
+
+--[[ldx--
+
We cannot load anything yet. However what we will do us reserve a fewtables.
+These can be used for runtime user data or third party modules and will not be
+cluttered by macro package code.
+--ldx]]--
+
+userdata = userdata or { } -- might be used
+thirddata = thirddata or { } -- might be used
+moduledata = moduledata or { } -- might be used
+document = document or { }
+parametersets = parametersets or { } -- experimental
+
+--[[ldx--
+
These can be used/set by the caller program; mtx-context.lua does it.
+--ldx]]--
+
+document.arguments = document.arguments or { }
+document.files = document.files or { }
+
+--[[ldx--
+
Please create a namespace within these tables before using them!
We could cook up a readonly model for global tables but it
+makes more sense to invite users to use one of the predefined
+namespaces. One can redefine the protector. After all, it's
+just a lightweight suggestive system, not a watertight
+one.
+--ldx]]--
+
+local debug = require "debug"
+
+local string, table, lpeg, math, io, system = string, table, lpeg, math, io, system
+local next, setfenv = next, setfenv or debug.setfenv
+local format = string.format
+
+local global = _G
+
+global.global = global
+
+local dummy = function() end
+
+local protected = {
+ -- global table
+ global = global,
+ -- user tables
+ userdata = userdata,
+ moduledata = moduledata,
+ thirddata = thirddata,
+ document = document,
+ -- reserved
+ protect = dummy,
+ unprotect = dummy,
+ -- luatex
+ tex = tex,
+ -- lua
+ string = string,
+ table = table,
+ lpeg = lpeg,
+ math = math,
+ io = io,
+ system = system,
+}
+
+userdata, thirddata, moduledata = nil, nil, nil
+
+if not setfenv then
+ texio.write_nl("warning: we need to fix setfenv by using 'load in' or '_ENV'")
+end
+
+function protect(name)
+ if name == "isolateddata" then
+ local t = { }
+ for k, v in next, protected do
+ t[k] = v
+ end
+ setfenv(2,t)
+ else
+ if not name then
+ name = "shareddata"
+ end
+ local t = global[name]
+ if not t then
+ t = { }
+ for k, v in next, protected do
+ t[k] = v
+ end
+ global[name] = t
+ end
+ setfenv(2,t)
+ end
+end
+
+lua.numbers = { }
+lua.messages = { }
+
+function lua.registername(name,message)
+ local lnn = lua.numbers[name]
+ if not lnn then
+ lnn = #lua.messages + 1
+ lua.messages[lnn] = message
+ lua.numbers[name] = lnn
+ end
+ lua.name[lnn] = message
+ tex.write(lnn)
+end
+
+--~ function lua.checknames()
+--~ lua.name[0] = "ctx"
+--~ for k, v in next, lua.messages do
+--~ lua.name[k] = v
+--~ end
+--~ end
+
+storage.register("lua/numbers", lua.numbers, "lua.numbers")
+storage.register("lua/messages", lua.messages, "lua.messages")
+
+--~ local arguments, files = document.arguments, document.files -- set later
+
+function document.setargument(key,value)
+ document.arguments[key] = value
+end
+
+function document.setdefaultargument(key,default)
+ local v = document.arguments[key]
+ if v == nil or v == "" then
+ document.arguments[key] = default
+ end
+end
+
+function document.getargument(key,default)
+ local v = document.arguments[key]
+ if type(v) == "boolean" then
+ v = (v and "yes") or "no"
+ document.arguments[key] = v
+ end
+ tex.sprint(tex.ctxcatcodes,v or default or "")
+end
+
+function document.setfilename(i,name)
+ document.files[tonumber(i)] = name
+end
+
+function document.getfilename(i)
+ tex.sprint(tex.ctxcatcodes,document.files[i] or "")
+end
diff --git a/tex/context/base/luat-ini.mkiv b/tex/context/base/luat-ini.mkiv
new file mode 100644
index 000000000..c9d88bf4f
--- /dev/null
+++ b/tex/context/base/luat-ini.mkiv
@@ -0,0 +1,243 @@
+%D \module
+%D [ file=luat-ini,
+%D version=2005.08.11,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Lua Macros / Initialization}
+
+\unprotect
+
+%D Loading lua code can be done using \type {startup.lua}. The following
+%D method uses the \TEX\ input file locator of kpse. At least we need to
+%D use that way of loading when we haven't yet define our own code, which
+%D we keep outside the format. We will keep code outside \TEX\ files as
+%D much as possible.
+
+\ifx\setnaturalcatcodes\undefined \let\setnaturalcatcodes\relax \fi
+\ifx\obeylualines \undefined \let\obeylualines \relax \fi
+\ifx\obeyluatokens \undefined \let\obeyluatokens \relax \fi
+
+%D A few more goodies:
+
+\long\def\dostartlua
+ {\begingroup
+ \obeylualines
+ \dodostartlua}
+
+\long\def\dodostartlua#1\stoplua
+ {\normalexpanded{\endgroup\noexpand\directlua\zerocount{#1}}}
+
+\long\def\dostartluacode
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \dodostartluacode}
+
+\long\def\dodostartluacode#1\stopluacode
+ {\normalexpanded{\endgroup\noexpand\directlua\zerocount{#1}}}
+
+\unexpanded\def\startlua {\dostartlua } % tex catcodes
+\unexpanded\def\startluacode{\dostartluacode} % lua catcodes
+
+%D Some delayed definitions:
+
+\ifx\obeylines \undefined \let\obeylines \relax \fi
+\ifx\obeyedline \undefined \let\obeyedline \relax \fi
+\ifx\obeyspaces \undefined \let\obeyspaces \relax \fi
+\ifx\obeyedspace \undefined \let\obeyedspace \relax \fi
+\ifx\outputnewlinechar\undefined \let\outputnewlinechar\relax \fi
+
+%D A previous version used a bit less code and no catcode table,
+%D simply becaus ethey were not around at the time of writing.
+%
+% we keep it around for archival purposes
+%
+% \def\obeylualines
+% {\obeylines \let\obeyedline \outputnewlinechar
+% \obeyspaces \let\obeyedspace\space}
+%
+% \def\obeyluatokens % todo: make this a proper catcode table, use let's
+% {\catcode`\%=12 \catcode`\#=12
+% \catcode`\_=12 \catcode`\^=12
+% \catcode`\&=12 \catcode`\|=12
+% \catcode`\{=12 \catcode`\}=12
+% \catcode`\~=12 \catcode`\$=12
+% \def\\{\string\\}\def\|{\string\|}\def\-{\string\-}%
+% \def\({\string\(}\def\){\string\)}\def\{{\string\{}\def\}{\string\}}%
+% \def\'{\string\'}\def\"{\string\"}%
+% \def\n{\string\n}\def\r{\string\r}\def\f{\string\f}\def\t{\string\t}%
+% \def\a{\string\a}\def\b{\string\b}\def\v{\string\v}\def\s{\string\s}%
+% \def\1{\string\1}\def\2{\string\2}\def\3{\string\3}\def\4{\string\4}\def\5{\string\5}%
+% \def\6{\string\6}\def\7{\string\7}\def\8{\string\8}\def\9{\string\9}\def\0{\string\0}}
+
+\let\obeylualines\relax
+
+\newtoks\everyluacode
+
+\edef\lualetterbackslash{\string\\}
+\edef\lualetterbar {\string\|} \edef\lualetterdash {\string\-}
+\edef\lualetterlparent {\string\(} \edef\lualetterrparent {\string\)}
+\edef\lualetterlbrace {\string\{} \edef\lualetterrbrace {\string\}}
+\edef\lualettersquote {\string\'} \edef\lualetterdquote {\string\"}
+\edef\lualettern {\string\n} \edef\lualetterr {\string\r}
+\edef\lualetterf {\string\f} \edef\lualettert {\string\t}
+\edef\lualettera {\string\a} \edef\lualetterb {\string\b}
+\edef\lualetterv {\string\v} \edef\lualetters {\string\s}
+\edef\lualetterone {\string\1} \edef\lualettertwo {\string\2}
+\edef\lualetterthree {\string\3} \edef\lualetterfour {\string\4}
+\edef\lualetterfive {\string\5} \edef\lualettersix {\string\6}
+\edef\lualetterseven {\string\7} \edef\lualettereight {\string\8}
+\edef\lualetternine {\string\9} \edef\lualetterzero {\string\0}
+
+\appendtoks
+ \let\\\lualetterbackslash
+ \let\|\lualetterbar \let\-\lualetterdash
+ \let\(\lualetterlparent \let\)\lualetterrparent
+ \let\{\lualetterlbrace \let\}\lualetterrbrace
+ \let\'\lualettersquote \let\"\lualetterdquote
+ \let\n\lualettern \let\r\lualetterr
+ \let\f\lualetterf \let\t\lualettert
+ \let\a\lualettera \let\b\lualetterb
+ \let\v\lualetterv \let\s\lualetters
+ \let\1\lualetterone \let\2\lualettertwo
+ \let\3\lualetterthree \let\4\lualetterfour
+ \let\5\lualetterfive \let\6\lualettersix
+ \let\7\lualetterseven \let\8\lualettereight
+ \let\9\lualetternine \let\0\lualetterzero
+\to \everyluacode
+
+\def\obeyluatokens
+ {\setcatcodetable \luacatcodes
+ \the\everyluacode}
+
+%D \macros
+%D {definenamedlua}
+%D
+%D We provide an interface for defining instances:
+
+\def\s!lua{lua} \def\v!code{code} \def\!!name{name} \def\s!data{data}
+
+%D Beware: because \type {\expanded} is een convert command, the error
+%D message will show \type{} as part of the message.
+
+\long\def\dostartnamedluacode#1%
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \csname dodostartnamed#1\v!code\endcsname}
+
+\unexpanded\def\definenamedlua[#1]#2[#3]% no optional arg handling here yet
+ {\scratchcounter\ctxlua{lua.registername("#1","#3")}%
+ \normalexpanded{\long\edef\csname dodostartnamed#1\v!code\endcsname##1\csname\e!stop#1\v!code\endcsname}%
+ {\endgroup\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}%
+ \long\expandafter\def \csname\e!start#1\v!code\endcsname {\dostartnamedluacode{#1}}%
+ \long\expandafter\edef\csname #1\v!code\endcsname##1{\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}}
+
+%D We predefine a few.
+
+\definenamedlua[user] [private user instance]
+\definenamedlua[third] [third party module instance]
+\definenamedlua[module] [module instance]
+\definenamedlua[isolated][isolated instance]
+
+%D In practice this works out as follows:
+%D
+%D \startbuffer
+%D \startluacode
+%D tex.print("LUA")
+%D \stopluacode
+%D
+%D \startusercode
+%D global.tex.print("USER 1")
+%D tex.print("USER 2")
+%D if characters then
+%D tex.print("ACCESS")
+%D else
+%D tex.print("NO ACCESS")
+%D end
+%D \stopusercode
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D We need a way to pass strings safely to \LUA\ without the
+%D need for tricky escaping. Compare:
+%D
+%D \starttyping
+%D \ctxlua {something("anything tricky can go here")}
+%D \ctxlua {something([\luastringsep[anything tricky can go here]\luastringsep])}
+%D \stoptyping
+
+\def\luastringsep{===} % this permits \typefile{self} otherwise nested b/e sep problems
+
+\edef\!!bs{[\luastringsep[}
+\edef\!!es{]\luastringsep]}
+
+%D We have a the following available as primitive so there is no need
+%D for it:
+%D
+%D \starttyping
+%D \long\edef\luaescapestring#1{\!!bs#1\!!es}
+%D \stoptyping
+
+\def\setdocumentfilename #1#2{\ctxlua{document.setfilename(#1,"#2")}}
+\def\setdocumentargument #1#2{\ctxlua{document.setargument("#1","#2")}}
+\def\setdocumentargumentdefault#1#2{\ctxlua{document.setdefaultargument("#1","#2")}}
+\def\getdocumentfilename #1{\ctxlua{document.getfilename("#1")}}
+\def\getdocumentargument #1{\ctxlua{document.getargument("#1")}}
+\def\getdocumentargumentdefault#1#2{\ctxlua{document.getargument("#1","#2")}}
+\def\doifdocumentargumentelse #1{\doifsomethingelse{\getdocumentargument{#1}}}
+\def\doifdocumentargument #1{\doifsomething {\getdocumentargument{#1}}}
+\def\doifnotdocumentargument #1{\doifnothing {\getdocumentargument{#1}}}
+\def\doifdocumentfilenameelse #1{\doifsomethingelse{\getdocumentfilename{#1}}}
+\def\doifdocumentfilename #1{\doifsomething {\getdocumentfilename{#1}}}
+\def\doifnotdocumentfilename #1{\doifnothing {\getdocumentfilename{#1}}}
+
+\let\doifelsedocumentargument\doifdocumentargumentelse
+
+%D A handy helper:
+
+\def\luaexpanded#1{\luaescapestring\expandafter{\normalexpanded{#1}}}
+
+%D Experimental:
+
+\unexpanded\def\startluaparameterset[#1]%
+ {\begingroup
+ \obeylualines
+ \obeyluatokens
+ \dostartluaparameterset{#1}}
+
+\long\def\dostartluaparameterset#1#2\stopluaparameterset
+ {\ctxlua{parametersets["#1"]={#2}}%
+ \endgroup}
+
+\def\luaparameterset#1#2{\ctxlua{parametersets["#1"]={#2} tex.sprint("#1")}}
+
+% todo: \mergeparameterset
+
+% usage:
+%
+% \startluaparameterset [u3d:myset:display:1]
+% toolbar=false,
+% tree=true
+% \stopluaparameterset
+%
+% options=u3d:myset:display:1
+%
+% or:
+%
+% options=\luaparameterset{u3d:myset:display:1}{toolbar=false,tree=true}
+
+%D A Handy helper:
+
+\def\luaconditional#1{\ifcase#1tru\else fals\fi e}
+
+\protect \endinput
diff --git a/tex/context/base/luat-iop.lua b/tex/context/base/luat-iop.lua
new file mode 100644
index 000000000..e5722d2bd
--- /dev/null
+++ b/tex/context/base/luat-iop.lua
@@ -0,0 +1,148 @@
+if not modules then modules = { } end modules ['luat-iop'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this paranoid stuff in web2c ... we cannot hook checks into the
+-- input functions because one can always change the callback but
+-- we can feed back specific patterns and paths into the next
+-- mechanism
+
+local lower, find, sub = string.lower, string.find, string.sub
+
+local ioinp = io.inp if not ioinp then ioinp = { } io.inp = ioinp end
+local ioout = io.out if not ioout then ioout = { } io.out = ioout end
+
+ioinp.modes, ioout.modes = { }, { } -- functions
+
+local inp_blocked, inp_permitted = { }, { }
+local out_blocked, out_permitted = { }, { }
+
+local function i_inhibit(name) inp_blocked [#inp_blocked +1] = name end
+local function o_inhibit(name) out_blocked [#out_blocked +1] = name end
+local function i_permit (name) inp_permitted[#inp_permitted+1] = name end
+local function o_permit (name) out_permitted[#out_permitted+1] = name end
+
+ioinp.inhibit, ioinp.permit = i_inhibit, o_permit
+ioout.inhibit, ioout.permit = o_inhibit, o_permit
+
+local blocked_openers = { } -- *.open(name,method)
+
+function io.register_opener(func)
+ blocked_openers[#blocked_openers+1] = func
+end
+
+local function checked(name,blocked,permitted)
+ local n = lower(name)
+ for _,b in next, blocked do
+ if find(n,b) then
+ for _,p in next, permitted do
+ if find(n,p) then
+ return true
+ end
+ end
+ return false
+ end
+ end
+ return true
+end
+
+function io.finalize_openers(func)
+ if #out_blocked > 0 or #inp_blocked > 0 then
+ local open = func -- why not directly?
+ return function(name,method)
+ if method and find(method,'[wa]') then
+ if #out_blocked > 0 and not checked(name,out_blocked,out_permitted) then
+ -- print("writing to " .. name .. " is not permitted")
+ return nil
+ end
+ else
+ if #inp_blocked > 0 and not checked(name,inp_blocked,inp_permitted) then
+ -- print("reading from " .. name .. " is not permitted")
+ return nil
+ end
+ end
+ return open(name,method)
+ end
+ else
+ return func
+ end
+end
+
+--~ io.inp.inhibit('^%.')
+--~ io.inp.inhibit('^/etc')
+--~ io.inp.inhibit('/windows/')
+--~ io.inp.inhibit('/winnt/')
+--~ io.inp.permit('c:/windows/wmsetup.log')
+
+--~ io.open = io.finalize_openers(io.open)
+
+--~ f = io.open('.tex') print(f)
+--~ f = io.open('tufte.tex') print(f)
+--~ f = io.open('t:/sources/tufte.tex') print(f)
+--~ f = io.open('/etc/passwd') print(f)
+--~ f = io.open('c:/windows/crap.log') print(f)
+--~ f = io.open('c:/windows/wmsetup.log') print(f)
+
+local inpout = { 'inp', 'out' }
+
+function io.set_opener_modes(i,o)
+ local first = sub(i,1,1)
+ for k=1,#inpout do
+ local iov = io[inpout[k]]
+ local f = iov[i] or iov[first]
+ if f then f() end
+ end
+ io.open = io.finalize_openers(io.open)
+end
+
+-- restricted
+
+function ioinp.modes.restricted()
+ i_inhibit('^%.[%a]')
+end
+
+function ioout.modes.restricted()
+ o_inhibit('^%.[%a]')
+end
+
+-- paranoid
+
+function ioinp.modes.paranoid()
+ i_inhibit('.*')
+ i_inhibit('%.%.')
+ i_permit('^%./')
+ i_permit('[^/]')
+ resolvers.do_with_path('TEXMF',i_permit)
+end
+
+function ioout.modes.paranoid()
+ o_inhibit('.*')
+ resolvers.do_with_path('TEXMFOUTPUT',o_permit)
+end
+
+-- handy
+
+function ioinp.modes.handy()
+ i_inhibit('%.%.')
+ if os.type == 'windows' then
+ i_inhibit('/windows/')
+ i_inhibit('/winnt/')
+ else
+ i_inhibit('^/etc')
+ end
+end
+
+function ioout.modes.handy()
+ o_inhibit('.*')
+ o_permit('%./')
+ o_permit('^%./')
+ o_permit('[^/]')
+end
+
+--~ io.set_opener_modes('p','p')
+--~ io.set_opener_modes('r','r')
+--~ io.set_opener_modes('h','h')
diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv
new file mode 100644
index 000000000..91ddec0aa
--- /dev/null
+++ b/tex/context/base/luat-lib.mkiv
@@ -0,0 +1,70 @@
+%D \module
+%D [ file=luat-lib,
+%D version=2006.09.11,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Libraries,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Lua Macros / Libraries}
+
+\registerctxluafile{trac-inf} {1.001}
+\registerctxluafile{trac-tra} {1.001}
+\registerctxluafile{trac-log} {1.001}
+
+\registerctxluafile{luat-cbk} {1.001}
+
+\registerctxluafile{data-res} {1.001}
+\registerctxluafile{data-tmp} {1.001}
+\registerctxluafile{data-pre} {1.001}
+\registerctxluafile{data-inp} {1.001}
+\registerctxluafile{data-out} {1.001}
+\registerctxluafile{data-tex} {1.001}
+\registerctxluafile{data-bin} {1.001}
+\registerctxluafile{data-zip} {1.001}
+%registerctxluafile{data-crl} {1.001}
+\registerctxluafile{data-sch} {1.001}
+\registerctxluafile{data-tre} {1.001}
+\registerctxluafile{data-lua} {1.001}
+\registerctxluafile{data-ctx} {1.001}
+\registerctxluafile{data-con} {1.001}
+\registerctxluafile{data-use} {1.001}
+
+\registerctxluafile{luat-run} {1.001}
+\registerctxluafile{luat-fio} {1.001} % not needed, part of startup file
+\registerctxluafile{luat-cnf} {1.001} % not needed, part of startup file
+\registerctxluafile{luat-lua} {1.001}
+\registerctxluafile{luat-sto} {1.001}
+\registerctxluafile{luat-ini} {1.001}
+\registerctxluafile{luat-env} {1.001}
+
+\registerctxluafile{lxml-tab} {1.001}
+\registerctxluafile{lxml-lpt} {1.001}
+\registerctxluafile{lxml-xml} {1.001}
+\registerctxluafile{lxml-aux} {1.001}
+\registerctxluafile{lxml-mis} {1.001}
+
+\startruntimeluacode
+ \edef\asciia{\ctxlua{tex.sprint(logs.mode)}}
+ \edef\asciib{xml}
+ \ifx\asciia\asciib % brrr
+ \long\def\writebanner #1{\writestring {#1}}
+ \long\def\writestatus#1#2{\writestring {#2}}
+ \long\def\message #1{\normalmessage{#1}}
+ \else
+ \let\writebanner\writestring
+ %\let\writestatus\normalwritestatus
+ \let\message \normalmessage
+ \fi
+\stopruntimeluacode
+
+%registerctxluafile{luat-tmp}{1.001}
+\registerctxluafile{luat-exe}{1.001}
+\registerctxluafile{luat-iop}{1.001}
+
+\endinput
diff --git a/tex/context/base/luat-lua.lua b/tex/context/base/luat-lua.lua
new file mode 100644
index 000000000..b964bf8e8
--- /dev/null
+++ b/tex/context/base/luat-lua.lua
@@ -0,0 +1,43 @@
+if not modules then modules = { } end modules ['luat-lua'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if lua then do
+
+ local delayed = { }
+
+ function lua.delay(f)
+ delayed[#delayed+1] = f
+ end
+
+ function lua.flush_delayed(...)
+ local t = delayed
+ delayed = { }
+ for i=1, #t do
+ t[i](...)
+ end
+ end
+
+ function lua.flush(...)
+ tex.sprint("\\directlua0{lua.flush_delayed(",table.concat({...},','),")}")
+ end
+
+end end
+
+--~ See mk.pdf for an explanation of the following code:
+--~
+--~ function test(n)
+--~ lua.delay(function(...)
+--~ tex.sprint(string.format("pi: %s %s %s\\par",...))
+--~ end)
+--~ lua.delay(function(...)
+--~ tex.sprint(string.format("more pi: %s %s %s\\par",...))
+--~ end)
+--~ tex.sprint(string.format("\\setbox0=\\hbox{%s}",math.pi*n))
+--~ local box = tex.box[0]
+--~ lua.flush(box.width,box.height,box.depth)
+--~ end
diff --git a/tex/context/base/luat-run.lua b/tex/context/base/luat-run.lua
new file mode 100644
index 000000000..b64a99fc6
--- /dev/null
+++ b/tex/context/base/luat-run.lua
@@ -0,0 +1,74 @@
+if not modules then modules = { } end modules ['luat-run'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, rpadd = string.format, string.rpadd
+
+main = main or { }
+
+local start_actions = { }
+local stop_actions = { }
+
+function main.register_start_actions(...) table.insert(start_actions, ...) end
+function main.register_stop_actions (...) table.insert(stop_actions, ...) end
+
+main.show_tex_stat = main.show_tex_stat or function() end
+main.show_job_stat = main.show_job_stat or statistics.show_job_stat
+
+function main.start()
+ if logs.start_run then
+ logs.start_run()
+ end
+ for _, action in next, start_actions do
+ action()
+ end
+end
+
+function main.stop()
+ for _, action in next, stop_actions do
+ action()
+ end
+ if main.show_job_stat then
+ statistics.show(logs.report_job_stat)
+ end
+ if main.show_tex_stat then
+ for k,v in next, status.list() do
+ logs.report_tex_stat(k,v)
+ end
+ end
+ if logs.stop_run then
+ logs.stop_run()
+ end
+end
+
+function main.start_shipout_page()
+ logs.start_page_number()
+end
+
+function main.stop_shipout_page()
+ logs.stop_page_number()
+end
+
+function main.report_output_pages()
+end
+
+function main.report_output_log()
+end
+
+-- this can be done later
+
+callbacks.register('start_run', main.start, "actions performed at the beginning of a run")
+callbacks.register('stop_run', main.stop, "actions performed at the end of a run")
+
+callbacks.register('report_output_pages', main.report_output_pages, "actions performed when reporting pages")
+callbacks.register('report_output_log', main.report_output_log, "actions performed when reporting log file")
+
+callbacks.register('start_page_number', main.start_shipout_page, "actions performed at the beginning of a shipout")
+callbacks.register('stop_page_number', main.stop_shipout_page, "actions performed at the end of a shipout")
+
+callbacks.register('process_input_buffer', false, "actions performed when reading data")
+callbacks.register('process_output_buffer', false, "actions performed when writing data")
diff --git a/tex/context/base/luat-soc.lua b/tex/context/base/luat-soc.lua
new file mode 100644
index 000000000..1095ed087
--- /dev/null
+++ b/tex/context/base/luat-soc.lua
@@ -0,0 +1,11 @@
+-- This is just a loader. The package handler knows about the TEX tree.
+
+--~ require "luatex/lua/socket.lua"
+--~ require "luatex/lua/ltn12.lua"
+--~ require "luatex/lua/mime.lua"
+--~ require "luatex/lua/socket/http.lua"
+--~ require "luatex/lua/socket/url.lua"
+--~ require "luatex/lua/socket/tp.lua"
+--~ require "luatex/lua/socket/ftp.lua"
+
+-- "luatex/lua/socket/smtp.lua"
diff --git a/tex/context/base/luat-sta.lua b/tex/context/base/luat-sta.lua
new file mode 100644
index 000000000..a81b0c206
--- /dev/null
+++ b/tex/context/base/luat-sta.lua
@@ -0,0 +1,196 @@
+if not modules then modules = { } end modules ['luat-sta'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this code is used in the updater
+
+local gmatch, match = string.gmatch, string.match
+local type = type
+
+states = states or { }
+states.data = states.data or { }
+states.hash = states.hash or { }
+states.tag = states.tag or ""
+states.filename = states.filename or ""
+
+function states.save(filename,tag)
+ tag = tag or states.tag
+ filename = file.addsuffix(filename or states.filename,'lus')
+ io.savedata(filename,
+ "-- generator : luat-sta.lua\n" ..
+ "-- state tag : " .. tag .. "\n\n" ..
+ table.serialize(states.data[tag or states.tag] or {},true)
+ )
+end
+
+function states.load(filename,tag)
+ states.filename = filename
+ states.tag = tag or "whatever"
+ states.filename = file.addsuffix(states.filename,'lus')
+ states.data[states.tag], states.hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { }
+end
+
+function states.set_by_tag(tag,key,value,default,persistent)
+ local d, h = states.data[tag], states.hash[tag]
+ if d then
+ if type(d) == "table" then
+ local dkey, hkey = key, key
+ local pre, post = match(key,"(.+)%.([^%.]+)$")
+ if pre and post then
+ for k in gmatch(pre,"[^%.]+") do
+ local dk = d[k]
+ if not dk then
+ dk = { }
+ d[k] = dk
+ elseif type(dk) == "string" then
+ -- invalid table, unable to upgrade structure
+ -- hope for the best or delete the state file
+ break
+ end
+ d = dk
+ end
+ dkey, hkey = post, key
+ end
+ if type(value) == nil then
+ value = value or default
+ elseif persistent then
+ value = value or d[dkey] or default
+ else
+ value = value or default
+ end
+ d[dkey], h[hkey] = value, value
+ elseif type(d) == "string" then
+ -- weird
+ states.data[tag], states.hash[tag] = value, value
+ end
+ end
+end
+
+function states.get_by_tag(tag,key,default)
+ local h = states.hash[tag]
+ if h and h[key] then
+ return h[key]
+ else
+ local d = states.data[tag]
+ if d then
+ for k in gmatch(key,"[^%.]+") do
+ local dk = d[k]
+ if dk then
+ d = dk
+ else
+ return default
+ end
+ end
+ return d or default
+ end
+ end
+end
+
+function states.set(key,value,default,persistent)
+ states.set_by_tag(states.tag,key,value,default,persistent)
+end
+
+function states.get(key,default)
+ return states.get_by_tag(states.tag,key,default)
+end
+
+--~ states.data.update = {
+--~ ["version"] = {
+--~ ["major"] = 0,
+--~ ["minor"] = 1,
+--~ },
+--~ ["rsync"] = {
+--~ ["server"] = "contextgarden.net",
+--~ ["module"] = "minimals",
+--~ ["repository"] = "current",
+--~ ["flags"] = "-rpztlv --stats",
+--~ },
+--~ ["tasks"] = {
+--~ ["update"] = true,
+--~ ["make"] = true,
+--~ ["delete"] = false,
+--~ },
+--~ ["platform"] = {
+--~ ["host"] = true,
+--~ ["other"] = {
+--~ ["mswin"] = false,
+--~ ["linux"] = false,
+--~ ["linux-64"] = false,
+--~ ["osx-intel"] = false,
+--~ ["osx-ppc"] = false,
+--~ ["sun"] = false,
+--~ },
+--~ },
+--~ ["context"] = {
+--~ ["available"] = {"current", "beta", "alpha", "experimental"},
+--~ ["selected"] = "current",
+--~ },
+--~ ["formats"] = {
+--~ ["cont-en"] = true,
+--~ ["cont-nl"] = true,
+--~ ["cont-de"] = false,
+--~ ["cont-cz"] = false,
+--~ ["cont-fr"] = false,
+--~ ["cont-ro"] = false,
+--~ },
+--~ ["engine"] = {
+--~ ["pdftex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["pdftex"] = true,
+--~ },
+--~ },
+--~ ["luatex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ },
+--~ },
+--~ ["xetex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["xetex"] = false,
+--~ },
+--~ },
+--~ ["metapost"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["mpost"] = true,
+--~ ["metafun"] = true,
+--~ },
+--~ },
+--~ },
+--~ ["fonts"] = {
+--~ },
+--~ ["doc"] = {
+--~ },
+--~ ["modules"] = {
+--~ ["f-urwgaramond"] = false,
+--~ ["f-urwgothic"] = false,
+--~ ["t-bnf"] = false,
+--~ ["t-chromato"] = false,
+--~ ["t-cmscbf"] = false,
+--~ ["t-cmttbf"] = false,
+--~ ["t-construction-plan"] = false,
+--~ ["t-degrade"] = false,
+--~ ["t-french"] = false,
+--~ ["t-lettrine"] = false,
+--~ ["t-lilypond"] = false,
+--~ ["t-mathsets"] = false,
+--~ ["t-tikz"] = false,
+--~ ["t-typearea"] = false,
+--~ ["t-vim"] = false,
+--~ },
+--~ }
+
+--~ states.save("teststate", "update")
+--~ states.load("teststate", "update")
+
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
+--~ states.set_by_tag("update","rsync.server","oeps")
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
+--~ states.save("teststate", "update")
+--~ states.load("teststate", "update")
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
diff --git a/tex/context/base/luat-sto.lua b/tex/context/base/luat-sto.lua
new file mode 100644
index 000000000..08da735db
--- /dev/null
+++ b/tex/context/base/luat-sto.lua
@@ -0,0 +1,135 @@
+if not modules then modules = { } end modules ['luat-sto'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next = type, next
+local gmatch, format, write_nl = string.gmatch, string.format, texio.write_nl
+
+storage = storage or { }
+storage.min = 0 -- 500
+storage.max = storage.min - 1
+storage.noftables = storage.noftables or 0
+storage.nofmodules = storage.nofmodules or 0
+storage.data = { }
+storage.evaluators = { }
+
+local evaluators = storage.evaluators -- (evaluate,message,names)
+local data = storage.data
+
+function storage.register(...)
+ data[#data+1] = { ... }
+end
+
+-- evaluators .. messy .. to be redone
+
+function storage.evaluate(name)
+ evaluators[#evaluators+1] = name
+end
+
+function storage.finalize() -- we can prepend the string with "evaluate:"
+ for i=1,#evaluators do
+ local t = evaluators[i]
+ for i, v in next, t do
+ local tv = type(v)
+ if tv == "string" then
+ t[i] = loadstring(v)()
+ elseif tv == "table" then
+ for _, vv in next, v do
+ if type(vv) == "string" then
+ t[i] = loadstring(vv)()
+ end
+ end
+ elseif tv == "function" then
+ t[i] = v()
+ end
+ end
+ end
+end
+
+function storage.dump()
+ for i=1,#data do
+ local d = data[i]
+ local message, original, target, evaluate = d[1], d[2] ,d[3] ,d[4]
+ local name, initialize, finalize, code = nil, "", "", ""
+ for str in gmatch(target,"([^%.]+)") do
+ if name then
+ name = name .. "." .. str
+ else
+ name = str
+ end
+ initialize = format("%s %s = %s or {} ", initialize, name, name)
+ end
+ if evaluate then
+ finalize = "storage.evaluate(" .. name .. ")"
+ end
+ storage.max = storage.max + 1
+ if trace_storage then
+ logs.report('storage','saving %s in slot %s',message,storage.max)
+ code =
+ initialize ..
+ format("logs.report('storage','restoring %s from slot %s') ",message,storage.max) ..
+ table.serialize(original,name) ..
+ finalize
+ else
+ code = initialize .. table.serialize(original,name) .. finalize
+ end
+ lua.bytecode[storage.max] = loadstring(code)
+ collectgarbage("step")
+ end
+end
+
+-- we also need to count at generation time (nicer for message)
+
+if lua.bytecode then -- from 0 upwards
+ local i, b = storage.min, lua.bytecode
+ while b[i] do
+ storage.noftables = i
+ b[i]()
+ b[i] = nil
+ i = i + 1
+ end
+end
+
+statistics.register("stored bytecode data", function()
+ local modules = (storage.nofmodules > 0 and storage.nofmodules) or (status.luabytecodes - 500)
+ local dumps = (storage.noftables > 0 and storage.noftables) or storage.max-storage.min + 1
+ return format("%s modules, %s tables, %s chunks",modules,dumps,modules+dumps)
+end)
+
+if lua.bytedata then
+ storage.register("lua/bytedata",lua.bytedata,"lua.bytedata")
+end
+
+-- wrong place, kind of forward reference
+
+function statistics.report_storage(whereto)
+ whereto = whereto or "term and log"
+ write_nl(whereto," ","stored tables:"," ")
+ for k,v in table.sortedhash(storage.data) do
+ write_nl(whereto,format("%03i %s",k,v[1]))
+ end
+ write_nl(whereto," ","stored modules:"," ")
+ for k,v in table.sortedhash(lua.bytedata) do
+ write_nl(whereto,format("%03i %s %s",k,v[2],v[1]))
+ end
+ write_nl(whereto," ","stored attributes:"," ")
+ for k,v in table.sortedhash(attributes.names) do
+ write_nl(whereto,format("%03i %s",k,v))
+ end
+ write_nl(whereto," ","stored catcodetables:"," ")
+ for k,v in table.sortedhash(catcodes.names) do
+ write_nl(whereto,format("%03i %s",k,table.concat(v," ")))
+ end
+ write_nl(whereto," ")
+end
+
+storage.shared = storage.shared or { }
+
+-- Because the storage mechanism assumes tables, we define a table for storing
+-- (non table) values.
+
+storage.register("storage/shared", storage.shared, "storage.shared")
diff --git a/tex/context/base/lxml-aux.lua b/tex/context/base/lxml-aux.lua
new file mode 100644
index 000000000..00f791909
--- /dev/null
+++ b/tex/context/base/lxml-aux.lua
@@ -0,0 +1,543 @@
+if not modules then modules = { } end modules ['lxml-aux'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- not all functions here make sense anymore vbut we keep them for
+-- compatibility reasons
+
+local trace_manipulations = false trackers.register("lxml.manipulations", function(v) trace_manipulations = v end)
+
+local xmlparseapply, xmlconvert, xmlcopy, xmlname = xml.parse_apply, xml.convert, xml.copy, xml.name
+local xmlinheritedconvert = xml.inheritedconvert
+
+local type = type
+local insert, remove = table.insert, table.remove
+local gmatch, gsub = string.gmatch, string.gsub
+
+local function report(what,pattern,c,e)
+ logs.report("xml","%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
+end
+
+local function withelements(e,handle,depth)
+ if e and handle then
+ local edt = e.dt
+ if edt then
+ depth = depth or 0
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "table" then
+ handle(e,depth)
+ withelements(e,handle,depth+1)
+ end
+ end
+ end
+ end
+end
+
+xml.withelements = withelements
+
+function xml.withelement(e,n,handle) -- slow
+ if e and n ~= 0 and handle then
+ local edt = e.dt
+ if edt then
+ if n > 0 then
+ for i=1,#edt do
+ local ei = edt[i]
+ if type(ei) == "table" then
+ if n == 1 then
+ handle(ei)
+ return
+ else
+ n = n - 1
+ end
+ end
+ end
+ elseif n < 0 then
+ for i=#edt,1,-1 do
+ local ei = edt[i]
+ if type(ei) == "table" then
+ if n == -1 then
+ handle(ei)
+ return
+ else
+ n = n + 1
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+xml.elements_only = xml.collected
+
+function xml.each_element(root,pattern,handle,reverse)
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
+ end
+ return collected
+ end
+end
+
+xml.process_elements = xml.each_element
+
+function xml.process_attributes(root,pattern,handle)
+ local collected = xmlparseapply({ root },pattern)
+ if collected and handle then
+ for c=1,#collected do
+ handle(collected[c].at)
+ end
+ end
+ return collected
+end
+
+--[[ldx--
+
The following functions collect elements and texts.
+--ldx]]--
+
+-- are these still needed -> lxml-cmp.lua
+
+function xml.collect_elements(root, pattern)
+ return xmlparseapply({ root },pattern)
+end
+
+function xml.collect_texts(root, pattern, flatten) -- todo: variant with handle
+ local collected = xmlparseapply({ root },pattern)
+ if collected and flatten then
+ local xmltostring = xml.tostring
+ for c=1,#collected do
+ collected[c] = xmltostring(collected[c].dt)
+ end
+ end
+ return collected or { }
+end
+
+function xml.collect_tags(root, pattern, nonamespace)
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ local t = { }
+ for c=1,#collected do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ if nonamespace then
+ t[#t+1] = tg
+ elseif ns == "" then
+ t[#t+1] = tg
+ else
+ t[#t+1] = ns .. ":" .. tg
+ end
+ end
+ return t
+ end
+end
+
+--[[ldx--
+
We've now arrived at the functions that manipulate the tree.
+--ldx]]--
+
+local no_root = { no_root = true }
+
+function xml.redo_ni(d)
+ for k=1,#d do
+ local dk = d[k]
+ if type(dk) == "table" then
+ dk.ni = k
+ end
+ end
+end
+
+local function xmltoelement(whatever,root)
+ if not whatever then
+ return nil
+ end
+ local element
+ if type(whatever) == "string" then
+ element = xmlinheritedconvert(whatever,root)
+ else
+ element = whatever -- we assume a table
+ end
+ if element.error then
+ return whatever -- string
+ end
+ if element then
+ --~ if element.ri then
+ --~ element = element.dt[element.ri].dt
+ --~ else
+ --~ element = element.dt
+ --~ end
+ end
+ return element
+end
+
+xml.toelement = xmltoelement
+
+local function copiedelement(element,newparent)
+ if type(element) == "string" then
+ return element
+ else
+ element = xmlcopy(element).dt
+ if newparent and type(element) == "table" then
+ element.__p__ = newparent
+ end
+ return element
+ end
+end
+
+function xml.delete_element(root,pattern)
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ xml.redo_ni(d) -- can be made faster and inlined
+ end
+ end
+ end
+end
+
+function xml.replace_element(root,pattern,whatever)
+ local element = root and xmltoelement(whatever,root)
+ local collected = element and xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('replacing',pattern,c,e)
+ end
+ local d = p.dt
+ d[e.ni] = copiedelement(element,p)
+ xml.redo_ni(d) -- probably not needed
+ end
+ end
+ end
+end
+
+local function inject_element(root,pattern,whatever,prepend)
+ local element = root and xmltoelement(whatever,root)
+ local collected = element and xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
+ end
+ for i=1,#af do
+ be[#be+1] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ xml.redo_ni(d)
+ end
+ end
+ end
+end
+
+local function insert_element(root,pattern,whatever,before) -- todo: element als functie
+ local element = root and xmltoelement(whatever,root)
+ local collected = element and xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ xml.redo_ni(d)
+ end
+ end
+end
+
+xml.insert_element = insert_element
+xml.insert_element_after = insert_element
+xml.insert_element_before = function(r,p,e) insert_element(r,p,e,true) end
+xml.inject_element = inject_element
+xml.inject_element_after = inject_element
+xml.inject_element_before = function(r,p,e) inject_element(r,p,e,true) end
+
+local function include(xmldata,pattern,attribute,recursive,loaddata)
+ -- parse="text" (default: xml), encoding="" (todo)
+ -- attribute = attribute or 'href'
+ pattern = pattern or 'include'
+ loaddata = loaddata or io.loaddata
+ local collected = xmlparseapply({ xmldata },pattern)
+ if collected then
+ for c=1,#collected do
+ local ek = collected[c]
+ local name = nil
+ local ekdt = ek.dt
+ local ekat = ek.at
+ local epdt = ek.__p__.dt
+ if not attribute or attribute == "" then
+ name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- ckeck, probably always tab or str
+ end
+ if not name then
+ for a in gmatch(attribute or "href","([^|]+)") do
+ name = ekat[a]
+ if name then break end
+ end
+ end
+ local data = (name and name ~= "" and loaddata(name)) or ""
+ if data == "" then
+ epdt[ek.ni] = "" -- xml.empty(d,k)
+ elseif ekat["parse"] == "text" then
+ -- for the moment hard coded
+ epdt[ek.ni] = xml.escaped(data) -- d[k] = xml.escaped(data)
+ else
+--~ local settings = xmldata.settings
+--~ settings.parent_root = xmldata -- to be tested
+--~ local xi = xmlconvert(data,settings)
+ local xi = xmlinheritedconvert(data,xmldata)
+ if not xi then
+ epdt[ek.ni] = "" -- xml.empty(d,k)
+ else
+ if recursive then
+ include(xi,pattern,attribute,recursive,loaddata)
+ end
+ epdt[ek.ni] = xml.body(xi) -- xml.assign(d,k,xi)
+ end
+ end
+ end
+ end
+end
+
+xml.include = include
+
+--~ local function manipulate(xmldata,pattern,manipulator) -- untested and might go away
+--~ local collected = xmlparseapply({ xmldata },pattern)
+--~ if collected then
+--~ local xmltostring = xml.tostring
+--~ for c=1,#collected do
+--~ local e = collected[c]
+--~ local data = manipulator(xmltostring(e))
+--~ if data == "" then
+--~ epdt[e.ni] = ""
+--~ else
+--~ local xi = xmlinheritedconvert(data,xmldata)
+--~ if not xi then
+--~ epdt[e.ni] = ""
+--~ else
+--~ epdt[e.ni] = xml.body(xi) -- xml.assign(d,k,xi)
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+
+--~ xml.manipulate = manipulate
+
+function xml.strip_whitespace(root, pattern, nolines) -- strips all leading and trailing space !
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ for i=1,#collected do
+ local e = collected[i]
+ local edt = e.dt
+ if edt then
+ local t = { }
+ for i=1,#edt do
+ local str = edt[i]
+ if type(str) == "string" then
+ if str == "" then
+ -- stripped
+ else
+ if nolines then
+ str = gsub(str,"[ \n\r\t]+"," ")
+ end
+ if str == "" then
+ -- stripped
+ else
+ t[#t+1] = str
+ end
+ end
+ else
+ --~ str.ni = i
+ t[#t+1] = str
+ end
+ end
+ e.dt = t
+ end
+ end
+ end
+end
+
+function xml.strip_whitespace(root, pattern, nolines, anywhere) -- strips all leading and trailing spacing
+ local collected = xmlparseapply({ root },pattern) -- beware, indices no longer are valid now
+ if collected then
+ for i=1,#collected do
+ local e = collected[i]
+ local edt = e.dt
+ if edt then
+ if anywhere then
+ local t = { }
+ for e=1,#edt do
+ local str = edt[e]
+ if type(str) ~= "string" then
+ t[#t+1] = str
+ elseif str ~= "" then
+ -- todo: lpeg for each case
+ if nolines then
+ str = gsub(str,"%s+"," ")
+ end
+ str = gsub(str,"^%s*(.-)%s*$","%1")
+ if str ~= "" then
+ t[#t+1] = str
+ end
+ end
+ end
+ e.dt = t
+ else
+ -- we can assume a regular sparse xml table with no successive strings
+ -- otherwise we should use a while loop
+ if #edt > 0 then
+ -- strip front
+ local str = edt[1]
+ if type(str) ~= "string" then
+ -- nothing
+ elseif str == "" then
+ remove(edt,1)
+ else
+ if nolines then
+ str = gsub(str,"%s+"," ")
+ end
+ str = gsub(str,"^%s+","")
+ if str == "" then
+ remove(edt,1)
+ else
+ edt[1] = str
+ end
+ end
+ end
+ if #edt > 1 then
+ -- strip end
+ local str = edt[#edt]
+ if type(str) ~= "string" then
+ -- nothing
+ elseif str == "" then
+ remove(edt)
+ else
+ if nolines then
+ str = gsub(str,"%s+"," ")
+ end
+ str = gsub(str,"%s+$","")
+ if str == "" then
+ remove(edt)
+ else
+ edt[#edt] = str
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local function rename_space(root, oldspace, newspace) -- fast variant
+ local ndt = #root.dt
+ for i=1,ndt or 0 do
+ local e = root[i]
+ if type(e) == "table" then
+ if e.ns == oldspace then
+ e.ns = newspace
+ if e.rn then
+ e.rn = newspace
+ end
+ end
+ local edt = e.dt
+ if edt then
+ rename_space(edt, oldspace, newspace)
+ end
+ end
+ end
+end
+
+xml.rename_space = rename_space
+
+function xml.remap_tag(root, pattern, newtg)
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].tg = newtg
+ end
+ end
+end
+
+function xml.remap_namespace(root, pattern, newns)
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].ns = newns
+ end
+ end
+end
+
+function xml.check_namespace(root, pattern, newns)
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ if (not e.rn or e.rn == "") and e.ns == "" then
+ e.rn = newns
+ end
+ end
+ end
+end
+
+function xml.remap_name(root, pattern, newtg, newns, newrn)
+ local collected = xmlparseapply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ e.tg, e.ns, e.rn = newtg, newns, newrn
+ end
+ end
+end
+
+--[[ldx--
+
Here are a few synonyms.
+--ldx]]--
+
+xml.each = xml.each_element
+xml.process = xml.process_element
+xml.strip = xml.strip_whitespace
+xml.collect = xml.collect_elements
+xml.all = xml.collect_elements
+
+xml.insert = xml.insert_element_after
+xml.inject = xml.inject_element_after
+xml.after = xml.insert_element_after
+xml.before = xml.insert_element_before
+xml.delete = xml.delete_element
+xml.replace = xml.replace_element
diff --git a/tex/context/base/lxml-ctx.lua b/tex/context/base/lxml-ctx.lua
new file mode 100644
index 000000000..765754953
--- /dev/null
+++ b/tex/context/base/lxml-ctx.lua
@@ -0,0 +1,131 @@
+if not modules then modules = { } end modules ['lxml-ctx'] = {
+ version = 1.001,
+ comment = "companion to lxml-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- is this still used?
+
+xml.ctx = { }
+xml.ctx.enhancers = { }
+
+-- hashen
+
+function xml.ctx.enhancers.compound(root,lpath,before,tokens,after) -- todo lpeg
+ local before = before or "[%a%d][%a%d][%a%d]"
+ local tokens = tokens or "[%/%-]"
+ local after = after or "[%a%d][%a%d][%a%d]"
+ local pattern = "(" .. before .. ")(" .. tokens .. ")(" .. after .. ")"
+ local action = function(a,b,c)
+ return a .. "" .. c
+ end
+ xml.enhance(root,lpath,pattern,action) -- still present?
+end
+
+local loaded = { }
+
+local nodesettostring = xml.nodesettostring
+
+-- maybe use detokenize instead of \type
+
+function xml.ctx.tshow(specification)
+ local pattern = specification.pattern
+ local xmlroot = specification.xmlroot
+ local attribute = specification.attribute
+ if context then
+ local xmlpattern = pattern
+ if not string.find(xmlpattern,"^[%a]+://") then
+ xmlpattern = "xml://" .. pattern
+ end
+ parsed = xml.parse_pattern(xmlpattern)
+ titlecommand = specification.title or "type"
+ if parsed.state then
+ context[titlecommand]("pattern: " .. pattern .. " (".. parsed.state .. ")")
+ else
+ context[titlecommand]("pattern: " .. pattern)
+ end
+ context.starttabulate({ "|Tr|Tl|Tp|" } )
+ if specification.warning then
+ local comment = parsed.comment
+ if comment then
+ for k=1,#comment do
+ context.NC()
+ context("!")
+ context.NC()
+ context.rlap(comment[k])
+ context.NR()
+ end
+ context.TB()
+ end
+ end
+ for p=1,#parsed do
+ local pp = parsed[p]
+ local kind = pp.kind
+ context.NC()
+ context(p)
+ context.NC()
+ context(kind)
+ context.NC()
+ if kind == "axis" then
+ context(pp.axis)
+ elseif kind == "nodes" then
+ context(nodesettostring(pp.nodes,pp.nodetest))
+ elseif kind == "expression" then
+--~ context("%s => %s",pp.expression,pp.converted)
+ context(pp.expression)
+ elseif kind == "finalizer" then
+ context("%s(%s)",pp.name,pp.arguments)
+ elseif kind == "error" and pp.error then
+ context(pp.error)
+ end
+ context.NC()
+ context.NR()
+ end
+ context.stoptabulate()
+ if xmlroot and xmlroot ~= "" then
+ if not loaded[xmlroot] then
+ loaded[xmlroot] = { xml.convert(buffers.content(xmlroot) or "") }
+ end
+ local collected = xml.parse_apply(loaded[xmlroot],xmlpattern)
+ if collected then
+ local tc = type(collected)
+ if not tc then
+ -- skip
+ else
+ context.blank()
+ context.type("result : ")
+ if tc == "string" then
+ context.type(collected)
+ elseif tc == "table" then
+ if collected.tg then
+ collected = { collected }
+ end
+ for c=1,#collected do
+ local cc = collected[c]
+ if attribute and attribute ~= "" then
+ local ccat = cc.at
+ local a = ccat and ccat[attribute]
+ if a and a ~= "" then
+ context.type(a)
+ context.type(">")
+ end
+ end
+ local ccns = cc.ns
+ if ccns == "" then
+ context.type(cc.tg)
+ else
+ context.type(ccns .. ":" .. cc.tg)
+ end
+ context.space()
+ end
+ else
+ context.type(tostring(tc))
+ end
+ context.blank()
+ end
+ end
+ end
+ end
+end
diff --git a/tex/context/base/lxml-ctx.mkiv b/tex/context/base/lxml-ctx.mkiv
new file mode 100644
index 000000000..73d082d0d
--- /dev/null
+++ b/tex/context/base/lxml-ctx.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=lxml-ini,
+%D version=2007.08.17,
+%D title=\CONTEXT\ \XML\ Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Experimental. This might change! Also, it might become a module
+%D instead if core code.
+
+\writestatus{loading}{ConTeXt XML Support / Goodies}
+
+\registerctxluafile{lxml-ctx}{1.001}
+
+\unprotect
+
+% the letterbar is a messy hack and is needed for the tabulate
+
+\settrue \xmllshowbuffer
+\setfalse\xmllshowtitle
+\settrue \xmllshowwarning
+
+\definehead[lshowtitle][subsubsubsubsubject]
+\setuphead[lshowtitle][style=\tta]
+
+% \unexpanded\def\setuplxmlshow[#1]%
+% {\dodoubleargument\getparameters[\??xl]}
+
+\def\xmllshow#1%
+ {\begingroup
+ \let|=\letterbar
+ \ctxlua{xml.ctx.tshow {
+ pattern = \!!bs#1\!!es,
+ \ifconditional\xmllshowtitle
+ title = "lshowtitle",
+ \fi
+ \ifconditional\xmllshowwarning
+ warning = true,
+ \fi
+ } }%
+ \endgroup}
+
+\def\xmllshowbuffer#1#2#3%
+ {\begingroup
+ \let|=\letterbar
+ \ctxlua{xml.ctx.tshow {
+ pattern = \!!bs#2\!!es,
+ \ifconditional\xmllshowbuffer
+ xmlroot = "#1",
+ attribute = "#3",
+ \fi
+ \ifconditional\xmllshowwarning
+ warning = true,
+ \fi
+ } }%
+ \endgroup}
+
+\protect
diff --git a/tex/context/base/lxml-dir.lua b/tex/context/base/lxml-dir.lua
new file mode 100644
index 000000000..617ce3e20
--- /dev/null
+++ b/tex/context/base/lxml-dir.lua
@@ -0,0 +1,112 @@
+if not modules then modules = { } end modules ['lxml-dir'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, gsub = string.format, string.gsub
+local get_id = lxml.id
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+local xmlparseapply = xml.parse_apply
+
+--~
+--~
+--~
+--~
+--~
+--~
+--~
+
+
+
+lxml.directives = lxml.directives or { }
+
+local directives = lxml.directives
+
+local data = {
+ setup = { },
+ before = { },
+ after = { }
+}
+
+local function load_setup(filename)
+ local fullname = resolvers.findtexfile(filename) or ""
+ if fullname ~= "" then
+ filename = fullname
+ end
+ local collection = xmlparseapply({ get_id(xml.load(filename)) },"directive")
+ if collection then
+ local valid = 0
+ for i=1,#collection do
+ local at = collection[i].at
+ local attribute, value, element = at.attribute or "", at.value or "", at.element or '*'
+ local setup, before, after = at.setup or "", at.before or "", at.after or ""
+ if attribute ~= "" and value ~= "" then
+ local key = format("%s::%s::%s",element,attribute,value)
+ local t = data[key] or { }
+ if setup ~= "" then t.setup = setup end
+ if before ~= "" then t.before = before end
+ if after ~= "" then t.after = after end
+ data[key] = t
+ valid = valid + 1
+ end
+ end
+ commands.writestatus("lxml","%s directives found in '%s', %s valid",#collection,filename,valid)
+ else
+ commands.writestatus("lxml","no directives found in '%s'",filename)
+ end
+end
+
+local function handle_setup(category,root,attribute,element)
+ root = get_id(root)
+ if attribute then
+ local value = root.at[attribute]
+ if value then
+ if not element then
+ local ns, tg = root.rn or root.ns, root.tg
+ if ns == "" then
+ element = tg
+ else
+ element = ns .. ':' .. tg
+ end
+ end
+ local setup = data[format("%s::%s::%s",element,attribute,value)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ texsprint(ctxcatcodes,"\\directsetup{",setup,"}")
+ else
+ setup = data[format("%s::%s::*",element,attribute)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ texsprint(ctxcatcodes,"\\directsetup{",gsub(setup,'%*',value),"}")
+ end
+ end
+ end
+ end
+end
+
+directives.load = load_setup
+directives.handle = handle_setup
+
+function directives.setup(root,attribute,element)
+ handle_setup('setup',root,attribute,element)
+end
+function directives.before(root,attribute,element)
+ handle_setup('before',root,attribute,element)
+end
+function directives.after(root,attribute,element)
+ handle_setup('after',root,attribute,element)
+end
diff --git a/tex/context/base/lxml-ent.lua b/tex/context/base/lxml-ent.lua
new file mode 100644
index 000000000..193611937
--- /dev/null
+++ b/tex/context/base/lxml-ent.lua
@@ -0,0 +1,69 @@
+if not modules then modules = { } end modules ['lxml-ent'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next, tonumber = type, next, tonumber
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+local utf = unicode.utf8
+local byte, format = string.byte, string.format
+local utfupper, utfchar = utf.upper, utf.char
+local lpegmatch = lpeg.match
+
+--[[ldx--
+
We provide (at least here) two entity handlers. The more extensive
+resolver consults a hash first, tries to convert to next,
+and finaly calls a handler when defines. When this all fails, the
+original entity is returned.
+
+
We do things different now but it's still somewhat experimental
+--ldx]]--
+
+local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
+
+xml.entities = xml.entities or { } -- xml.entity_handler == function
+
+storage.register("xml/entities",xml.entities,"xml.entities") -- this will move to lxml
+
+local entities = xml.entities -- this is a shared hash
+
+xml.unknown_any_entity_format = nil -- has to be per xml
+
+local parsedentity = xml.parsedentitylpeg
+
+function xml.register_entity(key,value)
+ entities[key] = value
+ if trace_entities then
+ logs.report("xml","registering entity '%s' as: %s",key,value)
+ end
+end
+
+function xml.resolved_entity(str)
+ local e = entities[str]
+ if e then
+ local te = type(e)
+ if te == "function" then
+ e(str)
+ elseif e then
+ texsprint(ctxcatcodes,e)
+ end
+ else
+ -- resolve hex and dec, todo: escape # & etc for ctxcatcodes
+ -- normally this is already solved while loading the file
+ local chr, err = lpegmatch(parsedentity,str)
+ if chr then
+ texsprint(ctxcatcodes,chr)
+ elseif err then
+ texsprint(ctxcatcodes,err)
+ else
+ texsprint(ctxcatcodes,"\\xmle{",str,"}{",utfupper(str),"}") -- we need to use our own upper
+ end
+ end
+end
+
+entities.amp = function() tex.write("&") end
+entities.lt = function() tex.write("<") end
+entities.gt = function() tex.write(">") end
diff --git a/tex/context/base/lxml-inf.lua b/tex/context/base/lxml-inf.lua
new file mode 100644
index 000000000..629c869ec
--- /dev/null
+++ b/tex/context/base/lxml-inf.lua
@@ -0,0 +1,53 @@
+if not modules then modules = { } end modules ['lxml-inf'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This file will be loaded runtime by x-pending.tex.
+
+local status, stack
+
+local function get(e,d)
+ local ns, tg = e.ns, e.tg
+ local name = tg
+ if ns ~= "" then name = ns .. ":" .. tg end
+ stack[d] = name
+ local ec = e.command
+ if ec == true then
+ ec = "system: text"
+ elseif ec == false then
+ ec = "system: skip"
+ elseif ec == nil then
+ ec = "system: not set"
+ elseif type(ec) == "string" then
+ ec = "setup: " .. ec
+ else -- function
+ ec = tostring(ec)
+ end
+ local tag = concat(stack," => ",1,d)
+ local s = status[tag]
+ if not s then
+ s = { }
+ status[tag] = s
+ end
+ s[ec] = (s[ec] or 0) + 1
+end
+
+local function get_command_status(id)
+ status, stack = {}, {}
+ if id then
+ xmlwithelements(get_id(id),get)
+ return status
+ else
+ local t = { }
+ for id, _ in next, loaded do
+ t[id] = get_command_status(id)
+ end
+ return t
+ end
+end
+
+lxml.get_command_status = get_command_status
diff --git a/tex/context/base/lxml-ini.mkiv b/tex/context/base/lxml-ini.mkiv
new file mode 100644
index 000000000..0f04d0488
--- /dev/null
+++ b/tex/context/base/lxml-ini.mkiv
@@ -0,0 +1,414 @@
+%D \module
+%D [ file=lxml-ini,
+%D version=2007.08.17,
+%D title=\CONTEXT\ \XML\ Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D Todo: auto apply setups (manage at lua end)
+
+\writestatus{loading}{ConTeXt XML Support / Initialization}
+
+%registerctxluafile{lxml-tab}{1.001} % loader
+%registerctxluafile{lxml-lpt}{1.001} % parser
+%registerctxluafile{lxml-xml}{1.001} % xml finalizers
+%registerctxluafile{lxml-aux}{1.001} % extras using parser
+%registerctxluafile{lxml-mis}{1.001} % extras independent of parser
+\registerctxluafile{lxml-ent}{1.001} % entity hacks
+\registerctxluafile{lxml-tex}{1.001} % tex finalizers
+\registerctxluafile{lxml-dir}{1.001} % ctx hacks
+
+\unprotect
+
+\def\c!entities{entities} % to be internationalized
+
+\def\xmlmain #1{\ctxlua{lxml.main("#1")}}
+\def\xmlmatch #1{\ctxlua{lxml.match("#1")}}
+\def\xmlall #1#2{\ctxlua{lxml.all("#1","#2")}}
+\def\xmlatt #1#2{\ctxlua{lxml.att("#1","#2")}}
+\def\xmlattdef #1#2#3{\ctxlua{lxml.att("#1","#2","#3")}}
+\def\xmlchainatt #1#2{\ctxlua{lxml.chainattribute("#1","/","#2")}}
+\def\xmlchainattdef #1#2#3{\ctxlua{lxml.chainattribute("#1","/","#2","#3")}}
+\def\xmlattribute #1#2#3{\ctxlua{lxml.attribute("#1","#2","#3")}}
+\def\xmlattributedef #1#2#3#4{\ctxlua{lxml.attribute("#1","#2","#3","#4")}}
+\def\xmlcommand #1#2#3{\ctxlua{lxml.command("#1","#2","#3")}}
+\def\xmlconcat #1#2#3{\ctxlua{lxml.concat("#1","#2",[[\detokenize{#3}]])}}
+\def\xmlconcatrange#1#2#3#4#5{\ctxlua{lxml.concatrange("#1","#2","#3","#4",[[\detokenize{#5}]])}}
+\def\xmlcount #1#2{\ctxlua{lxml.count("#1","#2")}}
+\def\xmldelete #1#2{\ctxlua{lxml.delete("#1","#2")}}
+\def\xmldirectives #1{\ctxlua{lxml.directives.setup("#1")}}
+\def\xmldirectivesbefore #1{\ctxlua{lxml.directives.before("#1")}}
+\def\xmldirectivesafter #1{\ctxlua{lxml.directives.after("#1")}}
+\def\xmlfilter #1#2{\ctxlua{lxml.filter("#1",\!!bs#2\!!es)}}
+\def\xmlfilterlist #1#2{\ctxlua{lxml.filterlist("#1",\!!bs#2\!!es)}}
+\def\xmlfunction #1#2{\ctxlua{lxml["function"]("#1",\!!bs#2\!!es)}}
+\def\xmlfirst #1#2{\ctxlua{lxml.first("#1","#2")}}
+\def\xmlflush #1{\ctxlua{lxml.flush("#1")}}
+%def\xmlcontent #1{\ctxlua{lxml.content("#1")}}
+%def\xmlflushstripped #1{\ctxlua{lxml.strip("#1",true)}}
+\def\xmldirect #1{\ctxlua{lxml.direct("#1")}} % in loops, not dt but root
+\def\xmlidx #1#2#3{\ctxlua{lxml.idx("#1","#2",\number#3)}}
+\def\xmlinclude #1#2#3{\ctxlua{lxml.include("#1","#2","#3",true)}}
+\def\xmlindex #1#2#3{\ctxlua{lxml.index("#1","#2",\number#3)}}
+\def\xmlinfo #1{\hbox{\ttxx[\ctxlua{lxml.info("#1")}]}}
+\def\xmlshow #1{\startpacked\ttx\xmlverbatim{#1}\stoppacked}
+\def\xmllast #1#2{\ctxlua{lxml.last("#1","#2")}}
+\def\xmlname #1{\ctxlua{lxml.name("#1")}}
+\def\xmlnamespace #1{\ctxlua{lxml.namespace("#1")}}
+\def\xmlnonspace #1#2{\ctxlua{lxml.nonspace("#1","#2")}}
+\def\xmlraw #1#2{\ctxlua{lxml.raw("#1","#2")}}
+\def\xmlcontext #1#2{\ctxlua{lxml.context("#1","#2")}}
+\def\xmlflushcontext #1{\ctxlua{lxml.context("#1")}}
+\def\xmlsnippet #1#2{\ctxlua{lxml.snippet("#1",#2)}}
+\def\xmlelement #1#2{\ctxlua{lxml.element("#1",#2)}}
+\def\xmlregisterns #1#2{\ctxlua{xml.registerns("#1","#2")}} % document
+\def\xmlremapname #1#2#3#4{\ctxlua{xml.remapname(lxml.id("#1"),"#2","#3","#4")}} % element
+\def\xmlremapnamespace #1#2#3{\ctxlua{xml.rename_space(lxml.id("#1"),"#2","#3")}} % document
+\def\xmlchecknamespace #1#2#3{\ctxlua{xml.check_namespace(lxml.id("#1"),"#2","#3")}} % element
+\def\xmlsetfunction #1#2#3{\ctxlua{lxml.setaction("#1","#2",#3)}}
+\def\xmlsetsetup #1#2#3{\ctxlua{lxml.setsetup("#1","#2","#3")}}
+\def\xmlstrip #1#2{\ctxlua{lxml.strip("#1","#2")}}
+\def\xmlstripnolines #1#2{\ctxlua{lxml.strip("#1","#2",true)}}
+\def\xmlstripanywhere #1#2{\ctxlua{lxml.strip("#1","#2",true,true)}}
+\def\xmlstripped #1#2{\ctxlua{lxml.stripped("#1","#2")}}
+\def\xmlstrippednolines #1#2{\ctxlua{lxml.stripped("#1","#2",true)}}
+\def\xmltag #1{\ctxlua{lxml.tag("#1")}}
+\def\xmltext #1#2{\ctxlua{lxml.text("#1","#2")}}
+\def\xmlverbatim #1{\ctxlua{lxml.verbatim("#1")}}
+\def\xmldisplayverbatim #1{\ctxlua{lxml.displayverbatim("#1")}}
+\def\xmlinlineverbatim #1{\ctxlua{lxml.inlineverbatim("#1")}}
+
+\def\xmlload #1#2{\ctxlua{lxml.load("#1","#2","\@@xmentities","\@@xmcompress")}}
+\def\xmlloadbuffer #1#2{\ctxlua{lxml.loadbuffer("#1","#2","\@@xmentities","\@@xmcompress")}}
+\def\xmlloaddata #1#2{\ctxlua{lxml.loaddata("#1",\!!bs#2\!!es,"\@@xmentities","\@@xmcompress")}}
+\def\xmlloadregistered #1#2{\ctxlua{lxml.loadregistered("#1","\@@xmentities","\@@xmcompress")}}
+\def\xmlloaddirectives #1{\ctxlua{lxml.directives.load("any:///#1")}}
+\def\xmlpos #1{\ctxlua{lxml.pos("#1")}}
+
+%def\xmldoifelse #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",false))}}
+%def\xmldoifelsetext #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",true ))}}
+
+% kind of special:
+
+\def\xmlstartraw{\ctxlua{lxml.startraw()}}
+\def\xmlstopraw {\ctxlua{lxml.stopraw()}}
+
+% todo: \xmldoifelseattribute
+
+\def\xmldoif #1#2{\ctxlua{lxml.doif (\!!bs#1\!!es,\!!bs#2\!!es)}}
+\def\xmldoifnot #1#2{\ctxlua{lxml.doifnot (\!!bs#1\!!es,\!!bs#2\!!es)}}
+\def\xmldoifelse #1#2{\ctxlua{lxml.doifelse (\!!bs#1\!!es,\!!bs#2\!!es)}}
+\def\xmldoiftext #1#2{\ctxlua{lxml.doiftext (\!!bs#1\!!es,\!!bs#2\!!es)}}
+\def\xmldoifnottext #1#2{\ctxlua{lxml.doifnottext (\!!bs#1\!!es,\!!bs#2\!!es)}}
+\def\xmldoifelsetext #1#2{\ctxlua{lxml.doifelsetext(\!!bs#1\!!es,\!!bs#2\!!es)}}
+
+%def\xmldoifelseempty #1#2{\ctxlua{lxml.doifelseempty("#1","#2")}} % #2, "*" or "" == self not yet implemented
+%def\xmldoifelseselfempty #1{\ctxlua{lxml.doifelseempty("#1")}}
+
+% \startxmlsetups xml:include
+% \xmlinclude{main}{include}{filename|href}
+% \stopxmlsetups
+%
+% \xmlprependsetup{xml:include}
+
+\let\xmlgrab\xmlsetsetup % obsolete
+\let\xmlself\s!unknown % obsolete
+
+\def\xmlsetup#1#2{\setupwithargument{#2}{#1}}
+
+\let\xmls\xmlsetup
+\let\xmlw\setupwithargument
+
+\newtoks \registeredxmlsetups
+
+% todo: 1:xml:whatever always before 3:xml:something
+
+\def\xmlprependsetup #1{\ctxlua{lxml.installsetup(1,"*","#1")}}
+\def\xmlappendsetup #1{\ctxlua{lxml.installsetup(2,"*","#1")}}
+\def\xmlbeforesetup #1#2{\ctxlua{lxml.installsetup(3,"*","#1","#2"))}}
+\def\xmlaftersetup #1#2{\ctxlua{lxml.installsetup(4,"*","#1","#2"))}}
+
+\def\xmlprependdocumentsetup #1#2{\ctxlua{lxml.installsetup(1,"#1","#2")}}
+\def\xmlappenddocumentsetup #1#2{\ctxlua{lxml.installsetup(2,"#1","#2")}}
+\def\xmlbeforedocumentsetup#1#2#3{\ctxlua{lxml.installsetup(3,"#1","#2","#3"))}}
+\def\xmlafterdocumentsetup #1#2#3{\ctxlua{lxml.installsetup(4,"#1","#2","#3"))}}
+
+\def\xmlremovesetup #1{\ctxlua{lxml.removesetup("*","#1")}}
+\def\xmlremovedocumentsetup #1#2{\ctxlua{lxml.removesetup("#1","#2")}}
+
+\def\xmlflushdocumentsetups #1#2{\ctxlua{lxml.flushsetups("#1","*","#2")}} % #1 == id where to apply * and #2
+\def\xmlresetdocumentsetups #1{\ctxlua{lxml.resetsetups("#1")}}
+
+\let\xmlregistersetup \xmlappendsetup
+\let\xmlregisterdocumentsetup\xmlappenddocumentsetup
+
+\def\xmldocument{main}
+
+\def\xmlregisteredsetups
+ {\xmlstarttiming
+ \xmlflushsetups
+ \xmldefaulttotext\xmldocument % after include
+ \xmlstoptiming}
+
+\def\xmlregistereddocumentsetups#1#2% id setups
+ {\xmlstarttiming
+ % todo: test for duplicates !
+ \xmlflushdocumentsetups{#1}{#2}%
+ \xmldefaulttotext{#1}% after include
+ \xmlstoptiming}
+
+\def\xmlstarttiming{\ctxlua{statistics.starttiming(lxml)}}
+\def\xmlstoptiming {\ctxlua{statistics.stoptiming (lxml)}}
+
+\def\doxmlprocess#1#2#3#4#5% flag \loader id name what initializersetup
+ {\begingroup
+ \edef\xmldocument{#3}% #2 can be \xmldocument and set as such
+ %xmlpushdocument{#3}%
+ #2{#3}{#4}%
+ \setcatcodetable\notcatcodes
+ \doifelsenothing{#5}
+ {\xmlsetup{#3}{xml:process}}
+ {\xmlsetup{#3}{#5}}%
+ %xmlpopdocument
+ \endgroup}
+
+\def\xmlprocessfile {\doxmlprocess\plusone \xmlload}
+\def\xmlprocessdata {\doxmlprocess\zerocount\xmlloaddata}
+\def\xmlprocessbuffer {\doxmlprocess\zerocount\xmlloadbuffer}
+\def\xmlprocessregistered{\doxmlprocess\zerocount\xmlloadregistered}
+\let\xmlprocess \xmlprocessfile
+
+\startxmlsetups xml:flush
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:process
+ \xmlregistereddocumentsetups{#1}{#1}
+ \xmlmain{#1}
+\stopxmlsetups
+
+\def\xmlloadonly#1#2#3%
+ {\xmlload{#1}{#2}%
+ \xmlregistereddocumentsetups{#1}{#3}}
+
+% beware: \xmlmain takes the real root, so also processing
+% instructions preceding the root element; well, in some
+% sense that is the root
+
+\long\def\xmlconnect#1#2#3% inefficient
+ {\scratchcounter\xmlcount{#1}{#2}\relax
+ \ifcase\scratchcounter \or
+ \xmlall{#1}{#2}%
+ \else
+ \dorecurse \scratchcounter
+ {\ifnum\recurselevel>\plusone#3\fi
+ \xmlidx{#1}{#2}\recurselevel}%
+ \fi}
+
+\def\xmlcdataobeyedline {\obeyedline}
+\def\xmlcdataobeyedspace{\strut\obeyedspace}
+\def\xmlcdatabefore {\bgroup\tt}
+\def\xmlcdataafter {\egroup}
+
+% verbatim (dodo:pre/post whitespace, maybe splot verbatim and
+% cdata commands), experimental:
+%
+% \xmlsetfunction{main}{verbatim}{lxml.displayverbatim}
+% \xmlsetfunction{main}{verb} {lxml.inlineverbatim}
+
+% \unexpanded\def\startxmldisplayverbatim[#1]{}
+% \unexpanded\def\stopxmldisplayverbatim {}
+% \unexpanded\def\startxmlinlineverbatim [#1]{}
+% \unexpanded\def\stopxmlinlineverbatim {}
+
+% we use an xml: namespace so one has to define a suitable verbatim, say
+%
+% \definetyping[xml:verbatim][typing]
+%
+% this is experimental!
+
+\unexpanded\def\startxmldisplayverbatim[#1]%
+ {\startpacked % \begingroup
+ \let\currenttypingclass\??tp
+ \edef\currenttyping{xml:#1}%
+ \unexpanded\def\stopxmldisplayverbatim
+ {\endofverbatimlines
+ \stoppacked} % \endgroup
+ \doinitializeverbatim
+ \beginofverbatimlines}
+
+\unexpanded\def\startxmlinlineverbatim[#1]%
+ {\begingroup
+ \let\currenttypingclass\??ty
+ \edef\currenttyping{xml:#1}%
+ \let\stopxmldisplayverbatim\endgroup
+ \doinitializeverbatim}
+
+% will move but is developed for xml
+
+\newtoks \collectingtoks
+
+\unexpanded\def\startcollect#1\stopcollect
+ {\collectingtoks\@EA{\the\collectingtoks#1}}
+
+\unexpanded\def\startexpandedcollect#1\stopexpandedcollect
+ {\normalexpanded{\collectingtoks{\the\collectingtoks#1}}}
+
+\unexpanded\def\startcollecting{\collectingtoks\emptytoks}
+\unexpanded\def\stopcollecting {\the\collectingtoks}
+
+\def\inlinemessage #1{\dontleavehmode{\tttf#1}}
+\def\displaymessage#1{\blank\inlinemessage{#1}\blank}
+
+\def\xmltraceentities
+ {\ctxlua{xml.set_text_cleanup(lxml.trace_text_entities)}%
+ \appendtoks\ctxlua{lxml.show_text_entities()}\to\everygoodbye}
+
+% processing instructions
+
+\def\xmlcontextdirective#1% kind class key value
+ {\executeifdefined{xml#1directive}\gobblethreearguments}
+
+% setting up xml:
+%
+% \setupxml[\c!default=] % mkiv only == text
+% \setupxml[\c!default=\v!none] % mkiv only, undefined -> hidden
+% \setupxml[\c!default=\v!text] % mkiv only, undefined -> text
+
+% \def\xmlctxdirective#1#2#3{\doif{#1}{clue}{\doif{#2}{page}}{\page[#3]}}
+
+\chardef\xmlprocessingmode=0 % 0=unset, 1=text, 2=hidden
+
+\newtoks\everysetupxml
+
+\unexpanded\def\setupxml[#1]{\getparameters[\??xm][#1]\the\everysetupxml}
+
+
+\letvalue{\??xm:\s!default:\v!normal}\zerocount
+\letvalue{\??xm:\s!default:\v!none }\zerocount
+\letvalue{\??xm:\s!default:\v!text }\plusone
+\letvalue{\??xm:\s!default:\v!hidden}\plustwo
+
+\def\xmldefaulttotext#1%
+ {\ifcase\xmlprocessingmode
+ % unset
+ \or
+ \ctxlua{lxml.set_command_to_text("#1")}% 1
+ \or
+ \ctxlua{lxml.set_command_to_none("#1")}% 2
+ \else
+ % unset
+ \fi}
+
+\appendtoks
+ \chardef\xmlprocessingmode\executeifdefined{\??xm:\s!default:\@@xmdefault}\plusone
+\to \everysetupxml
+
+\def\xmlinitialize{\the\everysetupxml}
+
+\setupxml
+ [\c!default=, % flush all
+ \c!compress=\v!no, % strip comment
+ \c!entities=\v!yes] % replace entities
+
+% \defineXMLenvironment[y]{(}{)}
+%
+% \startxmlsetups x
+% /\xmlflush{#1}/
+% \stopxmlsetups
+%
+% \startxmlsetups xx
+% \xmlsetsetup{main}{x}{*}
+% \stopxmlsetups
+%
+% \xmlregistersetup{xx}
+%
+% \startbuffer
+% a <&>{b} c
+% \stopbuffer
+%
+% mkii: [\processXMLbuffer]\quad mkiv: [\xmlprocessbuffer{main}{}{}]
+
+\def\xmlmapvalue #1#2#3{\setvalue{\??xm:v:#1:#2}{#3}} % keep #3 to grab spaces
+\def\xmlvalue #1#2#3{\executeifdefined{\??xm:v:#1:#2}{#3}}
+%def\xmlvalue #1#2{\ifcsname\??xm:v:#1:#2\endcsname\csname\??xm:v:#1:#2\expandafter\expandafter\gobbleoneargument\expandafter\endcsname\else\expandafter\firstofoneargument\fi}
+\def\xmldoifelsevalue #1#2{\ifcsname\??xm:v:#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+
+\let\xmlmapval\xmlmapvalue
+\let\xmlval \xmlvalue
+
+%D Experimental:
+
+\def\xmlgetindex #1{\ctxlua{lxml.getindex("\xmldocument","#1")}}
+\def\xmlrawindex #1{\ctxlua{lxml.rawindex("#1")}}
+\def\xmlwithindex #1#2{\ctxlua{lxml.withindex("\xmldocument","#1","#2")}}
+\def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}}
+
+%D Entities:
+
+\chardef\xmlautoentities=1 % 0=off, 1=upper, 2=upper,lower
+
+\let\isolatedentity\firstofoneargument
+
+\def\xmlsetentity#1#2{\ctxlua{xml.register_entity('#1',\!!bs\detokenize{#2}\!!es)}}
+\def\xmltexentity#1#2{\ctxlua{xml.register_entity('#1',\!!bs\detokenize{\isolatedentity{#2}}\!!es)}}
+
+% \xmlsetentity{tex}{\TEX{}} % {} needed
+
+\unexpanded\def\xmle
+ {\ifcase\xmlautoentities
+ \expandafter\xmle@none
+ \or
+ \expandafter\xmle@upper
+ \or
+ \expandafter\xmle@upperlower
+ \else
+ \expandafter\xmle@none
+ \fi}
+
+\def\xmle@none#1#2% safe
+ {#1}
+
+\def\xmle@upper#1#2% can be abbreviation
+ {\ifcsname#2\endcsname
+ \csname#2\expandafter\endcsname
+ \else
+ #1%
+ \fi}
+
+\def\xmle@upperlower#1#2% can be anything, so unsafe
+ {\ifcsname#2\endcsname
+ \csname#2\expandafter\endcsname
+ \else\ifcsname#1\endcsname
+ \csname#1\expandafter\expandafter\expandafter\endcsname
+ \else
+ #1%
+ \fi\fi}
+
+\protect \endinput
+
+% \newcount\charactersactiveoffset \charactersactiveoffset="10000
+%
+% \startextendcatcodetable\ctxcatcodes
+% \catcode\numexpr\charactersactiveoffset+`<\relax=13
+% \catcode\numexpr\charactersactiveoffset+`&\relax=13
+% \catcode\numexpr\charactersactiveoffset+`>\relax=13
+% \stopextendcatcodetable
+%
+% \startextendcatcodetable\xmlcatcodes % not needed
+% \catcode\numexpr\charactersactiveoffset+`<\relax=13
+% \catcode\numexpr\charactersactiveoffset+`&\relax=13
+% \catcode\numexpr\charactersactiveoffset+`>\relax=13
+% \stopextendcatcodetable
+%
+% \ctxlua { % entities are remembered in the format
+% characters.remapentity("<",characters.active_offset + utf.byte("<"))
+% characters.remapentity("&",characters.active_offset + utf.byte("&"))
+% characters.remapentity(">",characters.active_offset + utf.byte(">"))
+% }
diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua
new file mode 100644
index 000000000..bddbe4868
--- /dev/null
+++ b/tex/context/base/lxml-lpt.lua
@@ -0,0 +1,1259 @@
+if not modules then modules = { } end modules ['lxml-pth'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- e.ni is only valid after a filter run
+
+local concat, remove, insert = table.concat, table.remove, table.insert
+local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
+local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
+local lpegmatch = lpeg.match
+
+-- beware, this is not xpath ... e.g. position is different (currently) and
+-- we have reverse-sibling as reversed preceding sibling
+
+--[[ldx--
+
This module can be used stand alone but also inside in
+which case it hooks into the tracker code. Therefore we provide a few
+functions that set the tracers. Here we overload a previously defined
+function.
+
If I can get in the mood I will make a variant that is XSLT compliant
+but I wonder if it makes sense.
+--ldx]]--
+
+--[[ldx--
+
Expecially the lpath code is experimental, we will support some of xpath, but
+only things that make sense for us; as compensation it is possible to hook in your
+own functions. Apart from preprocessing content for we also need
+this module for process management, like handling and
+files.
+
+
+a/b/c /*/c
+a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
+a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
+
+--ldx]]--
+
+local trace_lpath = false if trackers then trackers.register("xml.path", function(v) trace_lpath = v end) end
+local trace_lparse = false if trackers then trackers.register("xml.parse", function(v) trace_lparse = v end) end
+local trace_lprofile = false if trackers then trackers.register("xml.profile", function(v) trace_lpath = v trace_lparse = v trace_lprofile = v end) end
+
+--[[ldx--
+
We've now arrived at an interesting part: accessing the tree using a subset
+of and since we're not compatible we call it . We
+will explain more about its usage in other documents.
+--ldx]]--
+
+local lpathcalls = 0 function xml.lpathcalls () return lpathcalls end
+local lpathcached = 0 function xml.lpathcached() return lpathcached end
+
+xml.functions = xml.functions or { } -- internal
+xml.expressions = xml.expressions or { } -- in expressions
+xml.finalizers = xml.finalizers or { } -- fast do-with ... (with return value other than collection)
+xml.specialhandler = xml.specialhandler or { }
+
+local functions = xml.functions
+local expressions = xml.expressions
+local finalizers = xml.finalizers
+
+finalizers.xml = finalizers.xml or { }
+finalizers.tex = finalizers.tex or { }
+
+local function fallback (t, name)
+ local fn = finalizers[name]
+ if fn then
+ t[name] = fn
+ else
+ logs.report("xml","unknown sub finalizer '%s'",tostring(name))
+ fn = function() end
+ end
+ return fn
+end
+
+setmetatable(finalizers.xml, { __index = fallback })
+setmetatable(finalizers.tex, { __index = fallback })
+
+xml.defaultprotocol = "xml"
+
+-- as xsl does not follow xpath completely here we will also
+-- be more liberal especially with regards to the use of | and
+-- the rootpath:
+--
+-- test : all 'test' under current
+-- /test : 'test' relative to current
+-- a|b|c : set of names
+-- (a|b|c) : idem
+-- ! : not
+--
+-- after all, we're not doing transformations but filtering. in
+-- addition we provide filter functions (last bit)
+--
+-- todo: optimizer
+--
+-- .. : parent
+-- * : all kids
+-- / : anchor here
+-- // : /**/
+-- ** : all in between
+--
+-- so far we had (more practical as we don't transform)
+--
+-- {/test} : kids 'test' under current node
+-- {test} : any kid with tag 'test'
+-- {//test} : same as above
+
+-- evaluator (needs to be redone, for the moment copied)
+
+-- todo: apply_axis(list,notable) and collection vs single
+
+local apply_axis = { }
+
+apply_axis['root'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ local rt = ll
+ while ll do
+ ll = ll.__p__
+ if ll then
+ rt = ll
+ end
+ end
+ collected[#collected+1] = rt
+ end
+ return collected
+end
+
+apply_axis['self'] = function(list)
+--~ local collected = { }
+--~ for l=1,#list do
+--~ collected[#collected+1] = list[l]
+--~ end
+--~ return collected
+ return list
+end
+
+apply_axis['child'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ local dt = ll.dt
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ collected[#collected+1] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ end
+ end
+ ll.en = en
+ end
+ return collected
+end
+
+local function collect(list,collected)
+ local dt = list.dt
+ if dt then
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ collected[#collected+1] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ collect(dk,collected)
+ end
+ end
+ list.en = en
+ end
+end
+apply_axis['descendant'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ collect(list[l],collected)
+ end
+ return collected
+end
+
+local function collect(list,collected)
+ local dt = list.dt
+ if dt then
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ collected[#collected+1] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ collect(dk,collected)
+ end
+ end
+ list.en = en
+ end
+end
+apply_axis['descendant-or-self'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ if ll.special ~= true then -- catch double root
+ collected[#collected+1] = ll
+ end
+ collect(ll,collected)
+ end
+ return collected
+end
+
+apply_axis['ancestor'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ while ll do
+ ll = ll.__p__
+ if ll then
+ collected[#collected+1] = ll
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['ancestor-or-self'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ collected[#collected+1] = ll
+ while ll do
+ ll = ll.__p__
+ if ll then
+ collected[#collected+1] = ll
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['parent'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local pl = list[l].__p__
+ if pl then
+ collected[#collected+1] = pl
+ end
+ end
+ return collected
+end
+
+apply_axis['attribute'] = function(list)
+ return { }
+end
+
+apply_axis['namespace'] = function(list)
+ return { }
+end
+
+apply_axis['following'] = function(list) -- incomplete
+--~ local collected = { }
+--~ for l=1,#list do
+--~ local ll = list[l]
+--~ local p = ll.__p__
+--~ local d = p.dt
+--~ for i=ll.ni+1,#d do
+--~ local di = d[i]
+--~ if type(di) == "table" then
+--~ collected[#collected+1] = di
+--~ break
+--~ end
+--~ end
+--~ end
+--~ return collected
+ return { }
+end
+
+apply_axis['preceding'] = function(list) -- incomplete
+--~ local collected = { }
+--~ for l=1,#list do
+--~ local ll = list[l]
+--~ local p = ll.__p__
+--~ local d = p.dt
+--~ for i=ll.ni-1,1,-1 do
+--~ local di = d[i]
+--~ if type(di) == "table" then
+--~ collected[#collected+1] = di
+--~ break
+--~ end
+--~ end
+--~ end
+--~ return collected
+ return { }
+end
+
+apply_axis['following-sibling'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ local p = ll.__p__
+ local d = p.dt
+ for i=ll.ni+1,#d do
+ local di = d[i]
+ if type(di) == "table" then
+ collected[#collected+1] = di
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['preceding-sibling'] = function(list)
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ local p = ll.__p__
+ local d = p.dt
+ for i=1,ll.ni-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ collected[#collected+1] = di
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['reverse-sibling'] = function(list) -- reverse preceding
+ local collected = { }
+ for l=1,#list do
+ local ll = list[l]
+ local p = ll.__p__
+ local d = p.dt
+ for i=ll.ni-1,1,-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ collected[#collected+1] = di
+ end
+ end
+ end
+ return collected
+end
+
+apply_axis['auto-descendant-or-self'] = apply_axis['descendant-or-self']
+apply_axis['auto-descendant'] = apply_axis['descendant']
+apply_axis['auto-child'] = apply_axis['child']
+apply_axis['auto-self'] = apply_axis['self']
+apply_axis['initial-child'] = apply_axis['child']
+
+local function apply_nodes(list,directive,nodes)
+ -- todo: nodes[1] etc ... negated node name in set ... when needed
+ -- ... currently ignored
+ local maxn = #nodes
+ if maxn == 3 then --optimized loop
+ local nns, ntg = nodes[2], nodes[3]
+ if not nns and not ntg then -- wildcard
+ if directive then
+ return list
+ else
+ return { }
+ end
+ else
+ local collected, m, p = { }, 0, nil
+ if not nns then -- only check tag
+ for l=1,#list do
+ local ll = list[l]
+ local ltg = ll.tg
+ if ltg then
+ if directive then
+ if ntg == ltg then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ elseif ntg ~= ltg then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ end
+ end
+ elseif not ntg then -- only check namespace
+ for l=1,#list do
+ local ll = list[l]
+ local lns = ll.rn or ll.ns
+ if lns then
+ if directive then
+ if lns == nns then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ elseif lns ~= nns then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ end
+ end
+ else -- check both
+ for l=1,#list do
+ local ll = list[l]
+ local ltg = ll.tg
+ if ltg then
+ local lns = ll.rn or ll.ns
+ local ok = ltg == ntg and lns == nns
+ if directive then
+ if ok then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ elseif not ok then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ end
+ end
+ end
+ return collected
+ end
+ else
+ local collected, m, p = { }, 0, nil
+ for l=1,#list do
+ local ll = list[l]
+ local ltg = ll.tg
+ if ltg then
+ local lns = ll.rn or ll.ns
+ local ok = false
+ for n=1,maxn,3 do
+ local nns, ntg = nodes[n+1], nodes[n+2]
+ ok = (not ntg or ltg == ntg) and (not nns or lns == nns)
+ if ok then
+ break
+ end
+ end
+ if directive then
+ if ok then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ elseif not ok then
+ local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ collected[#collected+1], ll.mi = ll, m
+ end
+ end
+ end
+ return collected
+ end
+end
+
+local quit_expression = false
+
+local function apply_expression(list,expression,order)
+ local collected = { }
+ quit_expression = false
+ for l=1,#list do
+ local ll = list[l]
+ if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
+ collected[#collected+1] = ll
+ end
+ if quit_expression then
+ break
+ end
+ end
+ return collected
+end
+
+local P, V, C, Cs, Cc, Ct, R, S, Cg, Cb = lpeg.P, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cb
+
+local spaces = S(" \n\r\t\f")^0
+local lp_space = S(" \n\r\t\f")
+local lp_any = P(1)
+local lp_noequal = P("!=") / "~=" + P("<=") + P(">=") + P("==")
+local lp_doequal = P("=") / "=="
+local lp_or = P("|") / " or "
+local lp_and = P("&") / " and "
+
+local lp_builtin = P (
+ P("firstindex") / "1" +
+ P("lastindex") / "(#ll.__p__.dt or 1)" +
+ P("firstelement") / "1" +
+ P("lastelement") / "(ll.__p__.en or 1)" +
+ P("first") / "1" +
+ P("last") / "#list" +
+ P("rootposition") / "order" +
+ P("position") / "l" + -- is element in finalizer
+ P("order") / "order" +
+ P("element") / "(ll.ei or 1)" +
+ P("index") / "(ll.ni or 1)" +
+ P("match") / "(ll.mi or 1)" +
+ P("text") / "(ll.dt[1] or '')" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("ns") / "ll.ns"
+ ) * ((spaces * P("(") * spaces * P(")"))/"")
+
+local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * R("az","AZ","--","__")^1 * Cc("'])")
+local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
+local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
+local lp_fastpos = lp_fastpos_n + lp_fastpos_p
+local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
+
+local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
+ return t .. "("
+end
+
+local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
+ if expressions[t] then
+ return "expr." .. t .. "("
+ else
+ return "expr.error("
+ end
+end
+
+local lparent = lpeg.P("(")
+local rparent = lpeg.P(")")
+local noparent = 1 - (lparent+rparent)
+local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
+local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+
+local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
+local lp_number = S("+-") * R("09")^1
+local lp_string = Cc("'") * R("az","AZ","--","__")^1 * Cc("'")
+local lp_content = (P("'") * (1-P("'"))^0 * P("'") + P('"') * (1-P('"'))^0 * P('"'))
+
+local cleaner
+
+local lp_special = (C(P("name")+P("text")+P("tag")+P("count")+P("child"))) * value / function(t,s)
+ if expressions[t] then
+ s = s and s ~= "" and lpegmatch(cleaner,s)
+ if s and s ~= "" then
+ return "expr." .. t .. "(ll," .. s ..")"
+ else
+ return "expr." .. t .. "(ll)"
+ end
+ else
+ return "expr.error(" .. t .. ")"
+ end
+end
+
+local content =
+ lp_builtin +
+ lp_attribute +
+ lp_special +
+ lp_noequal + lp_doequal +
+ lp_or + lp_and +
+ lp_reserved +
+ lp_lua_function + lp_function +
+ lp_content + -- too fragile
+ lp_child +
+ lp_any
+
+local converter = Cs (
+ lp_fastpos + (P { lparent * (V(1))^0 * rparent + content } )^0
+)
+
+cleaner = Cs ( (
+--~ lp_fastpos +
+ lp_reserved +
+ lp_number +
+ lp_string +
+1 )^1 )
+
+
+--~ expr
+
+local template_e = [[
+ local expr = xml.expressions
+ return function(list,ll,l,order)
+ return %s
+ end
+]]
+
+local template_f_y = [[
+ local finalizer = xml.finalizers['%s']['%s']
+ return function(collection)
+ return finalizer(collection,%s)
+ end
+]]
+
+local template_f_n = [[
+ return xml.finalizers['%s']['%s']
+]]
+
+--
+
+local register_self = { kind = "axis", axis = "self" } -- , apply = apply_axis["self"] }
+local register_parent = { kind = "axis", axis = "parent" } -- , apply = apply_axis["parent"] }
+local register_descendant = { kind = "axis", axis = "descendant" } -- , apply = apply_axis["descendant"] }
+local register_child = { kind = "axis", axis = "child" } -- , apply = apply_axis["child"] }
+local register_descendant_or_self = { kind = "axis", axis = "descendant-or-self" } -- , apply = apply_axis["descendant-or-self"] }
+local register_root = { kind = "axis", axis = "root" } -- , apply = apply_axis["root"] }
+local register_ancestor = { kind = "axis", axis = "ancestor" } -- , apply = apply_axis["ancestor"] }
+local register_ancestor_or_self = { kind = "axis", axis = "ancestor-or-self" } -- , apply = apply_axis["ancestor-or-self"] }
+local register_attribute = { kind = "axis", axis = "attribute" } -- , apply = apply_axis["attribute"] }
+local register_namespace = { kind = "axis", axis = "namespace" } -- , apply = apply_axis["namespace"] }
+local register_following = { kind = "axis", axis = "following" } -- , apply = apply_axis["following"] }
+local register_following_sibling = { kind = "axis", axis = "following-sibling" } -- , apply = apply_axis["following-sibling"] }
+local register_preceding = { kind = "axis", axis = "preceding" } -- , apply = apply_axis["preceding"] }
+local register_preceding_sibling = { kind = "axis", axis = "preceding-sibling" } -- , apply = apply_axis["preceding-sibling"] }
+local register_reverse_sibling = { kind = "axis", axis = "reverse-sibling" } -- , apply = apply_axis["reverse-sibling"] }
+
+local register_auto_descendant_or_self = { kind = "axis", axis = "auto-descendant-or-self" } -- , apply = apply_axis["auto-descendant-or-self"] }
+local register_auto_descendant = { kind = "axis", axis = "auto-descendant" } -- , apply = apply_axis["auto-descendant"] }
+local register_auto_self = { kind = "axis", axis = "auto-self" } -- , apply = apply_axis["auto-self"] }
+local register_auto_child = { kind = "axis", axis = "auto-child" } -- , apply = apply_axis["auto-child"] }
+
+local register_initial_child = { kind = "axis", axis = "initial-child" } -- , apply = apply_axis["initial-child"] }
+
+local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } }
+
+local skip = { }
+
+local function errorrunner_e(str,cnv)
+ if not skip[str] then
+ logs.report("lpath","error in expression: %s => %s",str,cnv)
+ skip[str] = cnv or str
+ end
+ return false
+end
+local function errorrunner_f(str,arg)
+ logs.report("lpath","error in finalizer: %s(%s)",str,arg or "")
+ return false
+end
+
+local function register_nodes(nodetest,nodes)
+ return { kind = "nodes", nodetest = nodetest, nodes = nodes }
+end
+
+local function register_expression(expression)
+ local converted = lpegmatch(converter,expression)
+ local runner = loadstring(format(template_e,converted))
+ runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
+ return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
+end
+
+local function register_finalizer(protocol,name,arguments)
+ local runner
+ if arguments and arguments ~= "" then
+ runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ else
+ runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
+ end
+ runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
+ return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
+end
+
+local expression = P { "ex",
+ ex = "[" * C((V("sq") + V("dq") + (1 - S("[]")) + V("ex"))^0) * "]",
+ sq = "'" * (1 - S("'"))^0 * "'",
+ dq = '"' * (1 - S('"'))^0 * '"',
+}
+
+local arguments = P { "ar",
+ ar = "(" * Cs((V("sq") + V("dq") + V("nq") + P(1-P(")")))^0) * ")",
+ nq = ((1 - S("),'\""))^1) / function(s) return format("%q",s) end,
+ sq = P("'") * (1 - P("'"))^0 * P("'"),
+ dq = P('"') * (1 - P('"'))^0 * P('"'),
+}
+
+-- todo: better arg parser
+
+local function register_error(str)
+ return { kind = "error", error = format("unparsed: %s",str) }
+end
+
+-- there is a difference in * and /*/ and so we need to catch a few special cases
+
+local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes) -- last one not needed
+local special_2 = P("/") * Cc(register_auto_self)
+local special_3 = P("") * Cc(register_auto_self)
+
+local parser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+
+ patterns = spaces * V("protocol") * spaces * (
+ ( V("special") * spaces * P(-1) ) +
+ ( V("initial") * spaces * V("step") * spaces * (P("/") * spaces * V("step") * spaces)^0 )
+ ),
+
+ protocol = Cg(V("letters"),"protocol") * P("://") + Cg(Cc(nil),"protocol"),
+
+ -- the / is needed for // as descendant or self is somewhat special
+ -- step = (V("shortcuts") + V("axis") * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
+ step = ((V("shortcuts") + P("/") + V("axis")) * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
+
+ axis = V("descendant") + V("child") + V("parent") + V("self") + V("root") + V("ancestor") +
+ V("descendant_or_self") + V("following_sibling") + V("following") +
+ V("reverse_sibling") + V("preceding_sibling") + V("preceding") + V("ancestor_or_self") +
+ #(1-P(-1)) * Cc(register_auto_child),
+
+ special = special_1 + special_2 + special_3,
+
+ initial = (P("/") * spaces * Cc(register_initial_child))^-1,
+
+ error = (P(1)^1) / register_error,
+
+ shortcuts_a = V("s_descendant_or_self") + V("s_descendant") + V("s_child") + V("s_parent") + V("s_self") + V("s_root") + V("s_ancestor"),
+
+ shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
+
+ s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
+ -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
+ s_descendant = P("**") * Cc(register_descendant),
+ s_child = P("*") * #(1-P(":")) * Cc(register_child ),
+-- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_parent = P("..") * Cc(register_parent ),
+ s_self = P("." ) * Cc(register_self ),
+ s_root = P("^^") * Cc(register_root ),
+ s_ancestor = P("^") * Cc(register_ancestor ),
+
+ descendant = P("descendant::") * Cc(register_descendant ),
+ child = P("child::") * Cc(register_child ),
+ parent = P("parent::") * Cc(register_parent ),
+ self = P("self::") * Cc(register_self ),
+ root = P('root::') * Cc(register_root ),
+ ancestor = P('ancestor::') * Cc(register_ancestor ),
+ descendant_or_self = P('descendant-or-self::') * Cc(register_descendant_or_self ),
+ ancestor_or_self = P('ancestor-or-self::') * Cc(register_ancestor_or_self ),
+ -- attribute = P('attribute::') * Cc(register_attribute ),
+ -- namespace = P('namespace::') * Cc(register_namespace ),
+ following = P('following::') * Cc(register_following ),
+ following_sibling = P('following-sibling::') * Cc(register_following_sibling ),
+ preceding = P('preceding::') * Cc(register_preceding ),
+ preceding_sibling = P('preceding-sibling::') * Cc(register_preceding_sibling ),
+ reverse_sibling = P('reverse-sibling::') * Cc(register_reverse_sibling ),
+
+ nodes = (V("nodefunction") * spaces * P("(") * V("nodeset") * P(")") + V("nodetest") * V("nodeset")) / register_nodes,
+
+ expressions = expression / register_expression,
+
+ letters = R("az")^1,
+ name = (1-lpeg.S("/[]()|:*!"))^1,
+ negate = P("!") * Cc(false),
+
+ nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
+ nodetest = V("negate") + Cc(true),
+ nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
+
+ finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
+
+}
+
+local cache = { }
+
+local function nodesettostring(set,nodetest)
+ local t = { }
+ for i=1,#set,3 do
+ local directive, ns, tg = set[i], set[i+1], set[i+2]
+ if not ns or ns == "" then ns = "*" end
+ if not tg or tg == "" then tg = "*" end
+ tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[#t+1] = (directive and tg) or format("not(%s)",tg)
+ end
+ if nodetest == false then
+ return format("not(%s)",concat(t,"|"))
+ else
+ return concat(t,"|")
+ end
+end
+
+local function tagstostring(list)
+ if #list == 0 then
+ return "no elements"
+ else
+ local t = { }
+ for i=1, #list do
+ local li = list[i]
+ local ns, tg = li.ns, li.tg
+ if not ns or ns == "" then ns = "*" end
+ if not tg or tg == "" then tg = "*" end
+ t[#t+1] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
+ end
+ return concat(t," ")
+ end
+end
+
+xml.nodesettostring = nodesettostring
+
+local parse_pattern -- we have a harmless kind of circular reference
+
+local function lshow(parsed)
+ if type(parsed) == "string" then
+ parsed = parse_pattern(parsed)
+ end
+ local s = table.serialize_functions -- ugly
+ table.serialize_functions = false -- ugly
+ logs.report("lpath","%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,false))
+ table.serialize_functions = s -- ugly
+end
+
+xml.lshow = lshow
+
+local function add_comment(p,str)
+ local pc = p.comment
+ if not pc then
+ p.comment = { str }
+ else
+ pc[#pc+1] = str
+ end
+end
+
+parse_pattern = function (pattern) -- the gain of caching is rather minimal
+ lpathcalls = lpathcalls + 1
+ if type(pattern) == "table" then
+ return pattern
+ else
+ local parsed = cache[pattern]
+ if parsed then
+ lpathcached = lpathcached + 1
+ else
+ parsed = lpegmatch(parser,pattern)
+ if parsed then
+ parsed.pattern = pattern
+ local np = #parsed
+ if np == 0 then
+ parsed = { pattern = pattern, register_self, state = "parsing error" }
+ logs.report("lpath","parsing error in '%s'",pattern)
+ lshow(parsed)
+ else
+ -- we could have done this with a more complex parser but this
+ -- is cleaner
+ local pi = parsed[1]
+ if pi.axis == "auto-child" then
+ if false then
+ add_comment(parsed, "auto-child replaced by auto-descendant-or-self")
+ parsed[1] = register_auto_descendant_or_self
+ else
+ add_comment(parsed, "auto-child replaced by auto-descendant")
+ parsed[1] = register_auto_descendant
+ end
+ elseif pi.axis == "initial-child" and np > 1 and parsed[2].axis then
+ add_comment(parsed, "initial-child removed") -- we could also make it a auto-self
+ remove(parsed,1)
+ end
+ local np = #parsed -- can have changed
+ if np > 1 then
+ local pnp = parsed[np]
+ if pnp.kind == "nodes" and pnp.nodetest == true then
+ local nodes = pnp.nodes
+ if nodes[1] == true and nodes[2] == false and nodes[3] == false then
+ add_comment(parsed, "redundant final wildcard filter removed")
+ remove(parsed,np)
+ end
+ end
+ end
+ end
+ else
+ parsed = { pattern = pattern }
+ end
+ cache[pattern] = parsed
+ if trace_lparse and not trace_lprofile then
+ lshow(parsed)
+ end
+ end
+ return parsed
+ end
+end
+
+-- we can move all calls inline and then merge the trace back
+-- technically we can combine axis and the next nodes which is
+-- what we did before but this a bit cleaner (but slower too)
+-- but interesting is that it's not that much faster when we
+-- go inline
+--
+-- beware: we need to return a collection even when we filter
+-- else the (simple) cache gets messed up
+
+-- caching found lookups saves not that much (max .1 sec on a 8 sec run)
+-- and it also messes up finalizers
+
+-- watch out: when there is a finalizer, it's always called as there
+-- can be cases that a finalizer returns (or does) something in case
+-- there is no match; an example of this is count()
+
+local profiled = { } xml.profiled = profiled
+
+local function profiled_apply(list,parsed,nofparsed,order)
+ local p = profiled[parsed.pattern]
+ if p then
+ p.tested = p.tested + 1
+ else
+ p = { tested = 1, matched = 0, finalized = 0 }
+ profiled[parsed.pattern] = p
+ end
+ local collected = list
+ for i=1,nofparsed do
+ local pi = parsed[i]
+ local kind = pi.kind
+ if kind == "axis" then
+ collected = apply_axis[pi.axis](collected)
+ elseif kind == "nodes" then
+ collected = apply_nodes(collected,pi.nodetest,pi.nodes)
+ elseif kind == "expression" then
+ collected = apply_expression(collected,pi.evaluator,order)
+ elseif kind == "finalizer" then
+ collected = pi.finalizer(collected)
+ p.matched = p.matched + 1
+ p.finalized = p.finalized + 1
+ return collected
+ end
+ if not collected or #collected == 0 then
+ local pn = i < nofparsed and parsed[nofparsed]
+ if pn and pn.kind == "finalizer" then
+ collected = pn.finalizer(collected)
+ p.finalized = p.finalized + 1
+ return collected
+ end
+ return nil
+ end
+ end
+ if collected then
+ p.matched = p.matched + 1
+ end
+ return collected
+end
+
+local function traced_apply(list,parsed,nofparsed,order)
+ if trace_lparse then
+ lshow(parsed)
+ end
+ logs.report("lpath", "collecting : %s",parsed.pattern)
+ logs.report("lpath", " root tags : %s",tagstostring(list))
+ logs.report("lpath", " order : %s",order or "unset")
+ local collected = list
+ for i=1,nofparsed do
+ local pi = parsed[i]
+ local kind = pi.kind
+ if kind == "axis" then
+ collected = apply_axis[pi.axis](collected)
+ logs.report("lpath", "% 10i : ax : %s",(collected and #collected) or 0,pi.axis)
+ elseif kind == "nodes" then
+ collected = apply_nodes(collected,pi.nodetest,pi.nodes)
+ logs.report("lpath", "% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest))
+ elseif kind == "expression" then
+ collected = apply_expression(collected,pi.evaluator,order)
+ logs.report("lpath", "% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted)
+ elseif kind == "finalizer" then
+ collected = pi.finalizer(collected)
+ logs.report("lpath", "% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
+ return collected
+ end
+ if not collected or #collected == 0 then
+ local pn = i < nofparsed and parsed[nofparsed]
+ if pn and pn.kind == "finalizer" then
+ collected = pn.finalizer(collected)
+ logs.report("lpath", "% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "")
+ return collected
+ end
+ return nil
+ end
+ end
+ return collected
+end
+
+local function normal_apply(list,parsed,nofparsed,order)
+ local collected = list
+ for i=1,nofparsed do
+ local pi = parsed[i]
+ local kind = pi.kind
+ if kind == "axis" then
+ local axis = pi.axis
+ if axis ~= "self" then
+ collected = apply_axis[axis](collected)
+ end
+ elseif kind == "nodes" then
+ collected = apply_nodes(collected,pi.nodetest,pi.nodes)
+ elseif kind == "expression" then
+ collected = apply_expression(collected,pi.evaluator,order)
+ elseif kind == "finalizer" then
+ return pi.finalizer(collected)
+ end
+ if not collected or #collected == 0 then
+ local pf = i < nofparsed and parsed[nofparsed].finalizer
+ if pf then
+ return pf(collected) -- can be anything
+ end
+ return nil
+ end
+ end
+ return collected
+end
+
+local function parse_apply(list,pattern)
+ -- we avoid an extra call
+ local parsed = cache[pattern]
+ if parsed then
+ lpathcalls = lpathcalls + 1
+ lpathcached = lpathcached + 1
+ elseif type(pattern) == "table" then
+ lpathcalls = lpathcalls + 1
+ parsed = pattern
+ else
+ parsed = parse_pattern(pattern) or pattern
+ end
+ if not parsed then
+ return
+ end
+ local nofparsed = #parsed
+ if nofparsed == 0 then
+ return -- something is wrong
+ end
+ local one = list[1]
+ if not one then
+ return -- something is wrong
+ elseif not trace_lpath then
+ return normal_apply(list,parsed,nofparsed,one.mi)
+ elseif trace_lprofile then
+ return profiled_apply(list,parsed,nofparsed,one.mi)
+ else
+ return traced_apply(list,parsed,nofparsed,one.mi)
+ end
+end
+
+-- internal (parsed)
+
+expressions.child = function(e,pattern)
+ return parse_apply({ e },pattern) -- todo: cache
+end
+expressions.count = function(e,pattern)
+ local collected = parse_apply({ e },pattern) -- todo: cache
+ return (collected and #collected) or 0
+end
+
+-- external
+
+expressions.oneof = function(s,...) -- slow
+ local t = {...} for i=1,#t do if s == t[i] then return true end end return false
+end
+expressions.error = function(str)
+ xml.error_handler("unknown function in lpath expression",tostring(str or "?"))
+ return false
+end
+expressions.undefined = function(s)
+ return s == nil
+end
+
+expressions.quit = function(s)
+ if s or s == nil then
+ quit_expression = true
+ end
+ return true
+end
+
+expressions.print = function(...)
+ print(...)
+ return true
+end
+
+expressions.contains = find
+expressions.find = find
+expressions.upper = upper
+expressions.lower = lower
+expressions.number = tonumber
+expressions.boolean = toboolean
+
+-- user interface
+
+local function traverse(root,pattern,handle)
+ logs.report("xml","use 'xml.selection' instead for '%s'",pattern)
+ local collected = parse_apply({ root },pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local r = e.__p__
+ handle(r,r.dt,e.ni)
+ end
+ end
+end
+
+local function selection(root,pattern,handle)
+ local collected = parse_apply({ root },pattern)
+ if collected then
+ if handle then
+ for c=1,#collected do
+ handle(collected[c])
+ end
+ else
+ return collected
+ end
+ end
+end
+
+xml.parse_parser = parser
+xml.parse_pattern = parse_pattern
+xml.parse_apply = parse_apply
+xml.traverse = traverse -- old method, r, d, k
+xml.selection = selection -- new method, simple handle
+
+local lpath = parse_pattern
+
+xml.lpath = lpath
+
+function xml.cached_patterns()
+ return cache
+end
+
+-- generic function finalizer (independant namespace)
+
+local function dofunction(collected,fnc)
+ if collected then
+ local f = functions[fnc]
+ if f then
+ for c=1,#collected do
+ f(collected[c])
+ end
+ else
+ logs.report("xml","unknown function '%s'",fnc)
+ end
+ end
+end
+
+xml.finalizers.xml["function"] = dofunction
+xml.finalizers.tex["function"] = dofunction
+
+-- functions
+
+expressions.text = function(e,n)
+ local rdt = e.__p__.dt
+ return (rdt and rdt[n]) or ""
+end
+
+expressions.name = function(e,n) -- ns + tg
+ local found = false
+ n = tonumber(n) or 0
+ if n == 0 then
+ found = type(e) == "table" and e
+ elseif n < 0 then
+ local d, k = e.__p__.dt, e.ni
+ for i=k-1,1,-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == -1 then
+ found = di
+ break
+ else
+ n = n + 1
+ end
+ end
+ end
+ else
+ local d, k = e.__p__.dt, e.ni
+ for i=k+1,#d,1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == 1 then
+ found = di
+ break
+ else
+ n = n - 1
+ end
+ end
+ end
+ end
+ if found then
+ local ns, tg = found.rn or found.ns or "", found.tg
+ if ns ~= "" then
+ return ns .. ":" .. tg
+ else
+ return tg
+ end
+ else
+ return ""
+ end
+end
+
+expressions.tag = function(e,n) -- only tg
+ if not e then
+ return ""
+ else
+ local found = false
+ n = tonumber(n) or 0
+ if n == 0 then
+ found = (type(e) == "table") and e -- seems to fail
+ elseif n < 0 then
+ local d, k = e.__p__.dt, e.ni
+ for i=k-1,1,-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == -1 then
+ found = di
+ break
+ else
+ n = n + 1
+ end
+ end
+ end
+ else
+ local d, k = e.__p__.dt, e.ni
+ for i=k+1,#d,1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == 1 then
+ found = di
+ break
+ else
+ n = n - 1
+ end
+ end
+ end
+ end
+ return (found and found.tg) or ""
+ end
+end
+
+--[[ldx--
+
This is the main filter function. It returns whatever is asked for.
+--ldx]]--
+
+function xml.filter(root,pattern) -- no longer funny attribute handling here
+ return parse_apply({ root },pattern)
+end
+
+--[[ldx--
+
Often using an iterators looks nicer in the code than passing handler
+functions. The book describes how to use coroutines for that
+purpose (). This permits
+code like:
+
+
+for r, d, k in xml.elements(xml.load('text.xml'),"title") do
+ print(d[k]) -- old method
+end
+for e in xml.collected(xml.load('text.xml'),"title") do
+ print(e) -- new one
+end
+
+--ldx]]--
+
+local wrap, yield = coroutine.wrap, coroutine.yield
+
+function xml.elements(root,pattern,reverse) -- r, d, k
+ local collected = parse_apply({ root },pattern)
+ if collected then
+ if reverse then
+ return wrap(function() for c=#collected,1,-1 do
+ local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
+ end end)
+ else
+ return wrap(function() for c=1,#collected do
+ local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
+ end end)
+ end
+ end
+ return wrap(function() end)
+end
+
+function xml.collected(root,pattern,reverse) -- e
+ local collected = parse_apply({ root },pattern)
+ if collected then
+ if reverse then
+ return wrap(function() for c=#collected,1,-1 do yield(collected[c]) end end)
+ else
+ return wrap(function() for c=1,#collected do yield(collected[c]) end end)
+ end
+ end
+ return wrap(function() end)
+end
diff --git a/tex/context/base/lxml-mis.lua b/tex/context/base/lxml-mis.lua
new file mode 100644
index 000000000..9fd4270af
--- /dev/null
+++ b/tex/context/base/lxml-mis.lua
@@ -0,0 +1,99 @@
+if not modules then modules = { } end modules ['lxml-mis'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local concat = table.concat
+local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
+local format, gsub, match = string.format, string.gsub, string.match
+local lpegmatch = lpeg.match
+
+--[[ldx--
+
The following helper functions best belong to the lxml-ini
+module. Some are here because we need then in the mk
+document and other manuals, others came up when playing with
+this module. Since this module is also used in we've
+put them here instead of loading mode modules there then needed.
+--ldx]]--
+
+local function xmlgsub(t,old,new) -- will be replaced
+ local dt = t.dt
+ if dt then
+ for k=1,#dt do
+ local v = dt[k]
+ if type(v) == "string" then
+ dt[k] = gsub(v,old,new)
+ else
+ xmlgsub(v,old,new)
+ end
+ end
+ end
+end
+
+--~ xml.gsub = xmlgsub
+
+function xml.strip_leading_spaces(dk,d,k) -- cosmetic, for manual
+ if d and k then
+ local dkm = d[k-1]
+ if dkm and type(dkm) == "string" then
+ local s = match(dkm,"\n(%s+)")
+ xmlgsub(dk,"\n"..rep(" ",#s),"\n")
+ end
+ end
+end
+
+--~ xml.escapes = { ['&'] = '&', ['<'] = '<', ['>'] = '>', ['"'] = '"' }
+--~ xml.unescapes = { } for k,v in next, xml.escapes do xml.unescapes[v] = k end
+
+--~ function xml.escaped (str) return (gsub(str,"(.)" , xml.escapes )) end
+--~ function xml.unescaped(str) return (gsub(str,"(&.-;)", xml.unescapes)) end
+--~ function xml.cleansed (str) return (gsub(str,"<.->" , '' )) end -- "%b<>"
+
+local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Cs
+
+-- 100 * 2500 * "oeps< oeps> oeps&" : gsub:lpeg|lpeg|lpeg
+--
+-- 1021:0335:0287:0247
+
+-- 10 * 1000 * "oeps< oeps> oeps& asfjhalskfjh alskfjh alskfjh alskfjh ;al J;LSFDJ"
+--
+-- 1559:0257:0288:0190 (last one suggested by roberto)
+
+-- escaped = Cs((S("<&>") / xml.escapes + 1)^0)
+-- escaped = Cs((S("<")/"<" + S(">")/">" + S("&")/"&" + 1)^0)
+local normal = (1 - S("<&>"))^0
+local special = P("<")/"<" + P(">")/">" + P("&")/"&"
+local escaped = Cs(normal * (special * normal)^0)
+
+-- 100 * 1000 * "oeps< oeps> oeps&" : gsub:lpeg == 0153:0280:0151:0080 (last one by roberto)
+
+local normal = (1 - S"&")^0
+local special = P("<")/"<" + P(">")/">" + P("&")/"&"
+local unescaped = Cs(normal * (special * normal)^0)
+
+-- 100 * 5000 * "oeps oeps oeps " : gsub:lpeg == 623:501 msec (short tags, less difference)
+
+local cleansed = Cs(((P("<") * (1-P(">"))^0 * P(">"))/"" + 1)^0)
+
+xml.escaped_pattern = escaped
+xml.unescaped_pattern = unescaped
+xml.cleansed_pattern = cleansed
+
+function xml.escaped (str) return lpegmatch(escaped,str) end
+function xml.unescaped(str) return lpegmatch(unescaped,str) end
+function xml.cleansed (str) return lpegmatch(cleansed,str) end
+
+-- this might move
+
+function xml.fillin(root,pattern,str,check)
+ local e = xml.first(root,pattern)
+ if e then
+ local n = #e.dt
+ if not check or n == 0 or (n == 1 and e.dt[1] == "") then
+ e.dt = { str }
+ end
+ end
+end
diff --git a/tex/context/base/lxml-sor.lua b/tex/context/base/lxml-sor.lua
new file mode 100644
index 000000000..e220bfad6
--- /dev/null
+++ b/tex/context/base/lxml-sor.lua
@@ -0,0 +1,158 @@
+if not modules then modules = { } end modules ['lxml-sor'] = {
+ version = 1.001,
+ comment = "companion to lxml-sor.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, concat = string.format, table.concat
+local lpegmatch = lpeg.match
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+
+lxml.sorters = lxml.sorters or { }
+
+if not lxml.splitid then
+ local splitter = lpeg.C((1-lpeg.P(":"))^1) * lpeg.P("::") * lpeg.C(lpeg.P(1)^1)
+ function lxml.splitid(id)
+ local d, i = lpegmatch(splitter,id)
+ if d then
+ return d, i
+ else
+ return "", id
+ end
+ end
+end
+
+local lists = { }
+
+function lxml.sorters.reset(name)
+ lists[name] = {
+ sorted = false,
+ entries = { },
+ reverse = { },
+ results = { },
+ }
+end
+
+function lxml.sorters.add(name,n,key)
+ local list = lists[name]
+ if list.sorted then
+ -- reverse is messed up, we could regenerate it and go on
+ else
+ local entries = list and list.entries
+ if entries then
+ local reverse = list.reverse
+ local e = reverse[n]
+ if e then
+ local keys = entries[e][2]
+ keys[#keys+1] = key
+ else
+ entries[#entries+1] = { n, { key } }
+ reverse[n] = #entries
+ end
+ end
+ end
+end
+
+function lxml.sorters.show(name)
+ local list = lists[name]
+ local entries = list and list.entries
+ local NC, NR, bold = context.NC, context.NR, context.bold -- somehow bold is not working
+ if entries then
+ local maxn = 1
+ for i=1,#entries do
+ if #entries[i][2] > maxn then maxn = #entries[i][2] end
+ end
+ context.starttabulate { "|Tr|Tr|" .. string.rep("Tlp|",maxn) }
+ NC() bold("n")
+ NC() bold("id")
+ if maxn > 1 then
+ for i=1,maxn do
+ NC() bold("entry " .. i)
+ end
+ else
+ NC() bold("entry")
+ end
+ NC() NR()
+ context.HL()
+ for i=1,#entries do
+ local entry = entries[i]
+ local document, node = lxml.splitid(entry[1])
+ NC() context(i)
+ NC() context(node)
+ local e = entry[2]
+ for i=1,#e do
+ NC() context.detokenize(e[i])
+ end
+ NC() NR()
+ end
+ context.stoptabulate()
+ end
+end
+
+lxml.sorters.compare = sorters.comparers.basic -- (a,b)
+
+function lxml.sorters.sort(name)
+ local list = lists[name]
+ local entries = list and list.entries
+ if entries then
+ -- filtering
+ local results = { }
+ list.results = results
+ for i=1,#entries do
+ local entry = entries[i]
+ results[i] = {
+ entry = entry[1],
+ key = concat(entry[2], " "),
+ }
+ end
+ -- preparation
+ local strip = sorters.strip
+ local splitter = sorters.splitters.utf
+ local firstofsplit = sorters.firstofsplit
+ for i=1, #results do
+ local r = results[i]
+ r.split = splitter(strip(r.key))
+ end
+ -- sorting
+ sorters.sort(results,lxml.sorters.compare)
+ -- finalizing
+ list.nofsorted = #results
+ local split = { }
+ for k=1,#results do -- rather generic so maybe we need a function
+ local v = results[k]
+ local entry, tag = firstofsplit(v)
+ local s = split[entry] -- keeps track of change
+ if not s then
+ s = { tag = tag, data = { } }
+ split[entry] = s
+ end
+ s.data[#s.data+1] = v
+ end
+ list.results = split
+ -- done
+ list.sorted = true
+ end
+end
+
+function lxml.sorters.flush(name,setup)
+ local list = lists[name]
+ local results = list and list.results
+ local xmlw = context.xmlw
+ if results and next(results) then
+ for key, result in next, results do
+ local tag, data = result.tag, result.data
+ for d=1,#data do
+ xmlw(setup,data[d].entry)
+ end
+ end
+ else
+ local entries = list and list.entries
+ if entries then
+ for i=1,#entries do
+ xmlw(setup,entries[i][1])
+ end
+ end
+ end
+end
diff --git a/tex/context/base/lxml-sor.mkiv b/tex/context/base/lxml-sor.mkiv
new file mode 100644
index 000000000..14425967b
--- /dev/null
+++ b/tex/context/base/lxml-sor.mkiv
@@ -0,0 +1,94 @@
+%D \module
+%D [ file=lxml-sor,
+%D version=2009.08.24,
+%D title=\CONTEXT\ \XML\ Support,
+%D subtitle=Sorting,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 IS VERY EXPERIMENTAL!
+
+\writestatus{loading}{ConTeXt XML Support / Sorting}
+
+\registerctxluafile{lxml-sor}{1.001}
+
+\unprotect
+
+\def\xmlresetsorter #1{\ctxlua{lxml.sorters.reset("#1")}}
+\def\xmladdsortentry#1#2#3{\ctxlua{lxml.sorters.add("#1","#2",\!!bs#3\!!es)}}
+\def\xmlshowsorter #1{\ctxlua{lxml.sorters.show("#1")}}
+\def\xmlflushsorter #1#2{\ctxlua{lxml.sorters.flush("#1","#2")}}
+\def\xmlsortentries #1{\ctxlua{lxml.sorters.sort("#1")}}
+
+\protect \endinput
+
+\startbuffer[test]
+
+
+ one
+ alpha
+ alpha indeed
+
+
+ one
+ gamma
+ gamma indeed
+
+
+ one
+ beta
+ beta indeed
+
+
+ two
+ alpha
+ alpha again
+
+
+ two
+ gamma
+ gamma again
+
+
+ two
+ beta
+ beta again
+
+
+\stopbuffer
+
+\startxmlsetups xml:mysetups
+ \xmlsetsetup{\xmldocument}{demo|entry|content}{xml:*}
+\stopxmlsetups
+
+\xmlregistersetup{xml:mysetups}
+
+\startxmlsetups xml:demo
+ \xmlresetsorter{demo}
+ \xmlfilter{#1}{entry/command(xml:entry:getkeys)}
+ \blank sortkeys: \blank\xmlshowsorter{demo}\blank
+ \xmlsortentries{demo}
+ \xmlflushsorter{demo}{xml:entry:flush}
+\stopxmlsetups
+
+\startxmlsetups xml:entry:getkeys
+ \xmladdsortentry{demo}{#1}{\xmltext{#1}{category}}
+ \xmladdsortentry{demo}{#1}{\xmltext{#1}{key|entry}}
+\stopxmlsetups
+
+\startxmlsetups xml:entry:flush
+ \xmltext{#1}{content}\par
+\stopxmlsetups
+
+\startxmlsetups xml:entry
+ \xmltext{#1}{content}\par
+\stopxmlsetups
+
+\starttext
+ \xmlprocessbuffer{main}{test}{}
+\stoptext
diff --git a/tex/context/base/lxml-tab.lua b/tex/context/base/lxml-tab.lua
new file mode 100644
index 000000000..23cd1cf04
--- /dev/null
+++ b/tex/context/base/lxml-tab.lua
@@ -0,0 +1,1174 @@
+if not modules then modules = { } end modules ['lxml-tab'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this module needs a cleanup: check latest lpeg, passing args, (sub)grammar, etc etc
+-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
+-- trouble
+
+local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
+
+--[[ldx--
+
The parser used here is inspired by the variant discussed in the lua book, but
+handles comment and processing instructions, has a different structure, provides
+parent access; a first version used different trickery but was less optimized to we
+went this route. First we had a find based parser, now we have an based one.
+The find based parser can be found in l-xml-edu.lua along with other older code.
+
+
Beware, the interface may change. For instance at, ns, tg, dt may get more
+verbose names. Once the code is stable we will also remove some tracing and
+optimize the code.
First a hack to enable namespace resolving. A namespace is characterized by
+a . The following function associates a namespace prefix with a
+pattern. We use , which in this case is more than twice as fast as a
+find based solution where we loop over an array of patterns. Less code and
+much cleaner.
The next function associates a namespace prefix with an . This
+normally happens independent of parsing.
+
+
+xml.registerns("mml","mathml")
+
+--ldx]]--
+
+function xml.registerns(namespace, pattern) -- pattern can be an lpeg
+ check = check + C(P(lower(pattern))) / namespace
+ parse = P { P(check) + 1 * V(1) }
+end
+
+--[[ldx--
+
The next function also registers a namespace, but this time we map a
+given namespace prefix onto a registered one, using the given
+. This used for attributes like xmlns:m.
+
+
+xml.checkns("m","http://www.w3.org/mathml")
+
+--ldx]]--
+
+function xml.checkns(namespace,url)
+ local ns = lpegmatch(parse,lower(url))
+ if ns and namespace ~= ns then
+ xml.xmlns[namespace] = ns
+ end
+end
+
+--[[ldx--
+
Next we provide a way to turn an into a registered
+namespace. This used for the xmlns attribute.
A namespace in an element can be remapped onto the registered
+one efficiently by using the xml.xmlns table.
+--ldx]]--
+
+--[[ldx--
+
This version uses . We follow the same approach as before, stack and top and
+such. This version is about twice as fast which is mostly due to the fact that
+we don't have to prepare the stream for cdata, doctype etc etc. This variant is
+is dedicated to Luigi Scarso, who challenged me with 40 megabyte files that
+took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
+the implementation we got that down to less 7.3 seconds. Loading the 14
+ interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.
+
+
Next comes the parser. The rather messy doctype definition comes in many
+disguises so it is no surprice that later on have to dedicate quite some
+ code to it.
+
+
+
+
+
+
+
+
+
+
+
The code may look a bit complex but this is mostly due to the fact that we
+resolve namespaces and attach metatables. There is only one public function:
+
+
+local x = xml.convert(somestring)
+
+
+
An optional second boolean argument tells this function not to create a root
+element.
+
+
Valid entities are:
+
+
+
+
+
+
+--ldx]]--
+
+-- not just one big nested table capture (lpeg overflow)
+
+local nsremap, resolvens = xml.xmlns, xml.resolvens
+
+local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
+local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
+local dcache, hcache, acache = { }, { }, { }
+
+local mt = { }
+
+function initialize_mt(root)
+ mt = { __index = root } -- will be redefined later
+end
+
+function xml.setproperty(root,k,v)
+ getmetatable(root).__index[k] = v
+end
+
+function xml.check_error(top,toclose)
+ return ""
+end
+
+local function add_attribute(namespace,tag,value)
+ if cleanup and #value > 0 then
+ value = cleanup(value) -- new
+ end
+ if tag == "xmlns" then
+ xmlns[#xmlns+1] = resolvens(value)
+ at[tag] = value
+ elseif namespace == "" then
+ at[tag] = value
+ elseif namespace == "xmlns" then
+ xml.checkns(tag,value)
+ at["xmlns:" .. tag] = value
+ else
+ -- for the moment this way:
+ at[namespace .. ":" .. tag] = value
+ end
+end
+
+local function add_empty(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
+ top = stack[#stack]
+ dt = top.dt
+ local t = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = top }
+ dt[#dt+1] = t
+ setmetatable(t, mt)
+ if at.xmlns then
+ remove(xmlns)
+ end
+ at = { }
+end
+
+local function add_begin(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
+ top = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = stack[#stack] }
+ setmetatable(top, mt)
+ dt = top.dt
+ stack[#stack+1] = top
+ at = { }
+end
+
+local function add_end(spacing, namespace, tag)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ local toclose = remove(stack)
+ top = stack[#stack]
+ if #stack < 1 then
+ errorstr = format("nothing to close with %s %s", tag, xml.check_error(top,toclose) or "")
+ elseif toclose.tg ~= tag then -- no namespace check
+ errorstr = format("unable to close %s with %s %s", toclose.tg, tag, xml.check_error(top,toclose) or "")
+ end
+ dt = top.dt
+ dt[#dt+1] = toclose
+ -- dt[0] = top -- nasty circular reference when serializing table
+ if toclose.at.xmlns then
+ remove(xmlns)
+ end
+end
+
+local function add_text(text)
+ if cleanup and #text > 0 then
+ dt[#dt+1] = cleanup(text)
+ else
+ dt[#dt+1] = text
+ end
+end
+
+local function add_special(what, spacing, text)
+ if #spacing > 0 then
+ dt[#dt+1] = spacing
+ end
+ if strip and (what == "@cm@" or what == "@dt@") then
+ -- forget it
+ else
+ dt[#dt+1] = { special=true, ns="", tg=what, dt={ text } }
+ end
+end
+
+local function set_message(txt)
+ errorstr = "garbage at the end of the file: " .. gsub(txt,"([ \n\r\t]*)","")
+end
+
+local reported_attribute_errors = { }
+
+local function attribute_value_error(str)
+ if not reported_attribute_errors[str] then
+ logs.report("xml","invalid attribute value: %q",str)
+ reported_attribute_errors[str] = true
+ at._error_ = str
+ end
+ return str
+end
+local function attribute_specification_error(str)
+ if not reported_attribute_errors[str] then
+ logs.report("xml","invalid attribute specification: %q",str)
+ reported_attribute_errors[str] = true
+ at._error_ = str
+ end
+ return str
+end
+
+function xml.unknown_dec_entity_format(str) return (str == "" and "&error;") or format("&%s;",str) end
+function xml.unknown_hex_entity_format(str) return format("%s;",str) end
+function xml.unknown_any_entity_format(str) return format("%s;",str) end
+
+local function fromhex(s)
+ local n = tonumber(s,16)
+ if n then
+ return utfchar(n)
+ else
+ return format("h:%s",s), true
+ end
+end
+
+local function fromdec(s)
+ local n = tonumber(s)
+ if n then
+ return utfchar(n)
+ else
+ return format("d:%s",s), true
+ end
+end
+
+-- one level expansion (simple case), no checking done
+
+local rest = (1-P(";"))^0
+local many = P(1)^0
+
+local parsedentity =
+ P("&") * (P("#x")*(rest/fromhex) + P("#")*(rest/fromdec)) * P(";") * P(-1) +
+ (P("#x")*(many/fromhex) + P("#")*(many/fromdec))
+
+-- parsing in the xml file
+
+local predefined_unified = {
+ [38] = "&",
+ [42] = """,
+ [47] = "'",
+ [74] = "<",
+ [76] = "&gr;",
+}
+
+local predefined_simplified = {
+ [38] = "&", amp = "&",
+ [42] = '"', quot = '"',
+ [47] = "'", apos = "'",
+ [74] = "<", lt = "<",
+ [76] = ">", gt = ">",
+}
+
+local function handle_hex_entity(str)
+ local h = hcache[str]
+ if not h then
+ local n = tonumber(str,16)
+ h = unify_predefined and predefined_unified[n]
+ if h then
+ if trace_entities then
+ logs.report("xml","utfize, converting hex entity %s; into %s",str,h)
+ end
+ elseif utfize then
+ h = (n and utfchar(n)) or xml.unknown_hex_entity_format(str) or ""
+ if not n then
+ logs.report("xml","utfize, ignoring hex entity %s;",str)
+ elseif trace_entities then
+ logs.report("xml","utfize, converting hex entity %s; into %s",str,h)
+ end
+ else
+ if trace_entities then
+ logs.report("xml","found entity %s;",str)
+ end
+ h = "" .. str .. ";"
+ end
+ hcache[str] = h
+ end
+ return h
+end
+
+local function handle_dec_entity(str)
+ local d = dcache[str]
+ if not d then
+ local n = tonumber(str)
+ d = unify_predefined and predefined_unified[n]
+ if d then
+ if trace_entities then
+ logs.report("xml","utfize, converting dec entity %s; into %s",str,d)
+ end
+ elseif utfize then
+ d = (n and utfchar(n)) or xml.unknown_dec_entity_format(str) or ""
+ if not n then
+ logs.report("xml","utfize, ignoring dec entity %s;",str)
+ elseif trace_entities then
+ logs.report("xml","utfize, converting dec entity %s; into %s",str,h)
+ end
+ else
+ if trace_entities then
+ logs.report("xml","found entity %s;",str)
+ end
+ d = "" .. str .. ";"
+ end
+ dcache[str] = d
+ end
+ return d
+end
+
+xml.parsedentitylpeg = parsedentity
+
+local function handle_any_entity(str)
+ if resolve then
+ local a = acache[str] -- per instance ! todo
+ if not a then
+ a = resolve_predefined and predefined_simplified[str]
+ if a then
+ -- one of the predefined
+ elseif type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
+ end
+ if a then
+ if trace_entities then
+ logs.report("xml","resolved entity &%s; -> %s (internal)",str,a)
+ end
+ a = lpegmatch(parsedentity,a) or a
+ else
+ if xml.unknown_any_entity_format then
+ a = xml.unknown_any_entity_format(str) or ""
+ end
+ if a then
+ if trace_entities then
+ logs.report("xml","resolved entity &%s; -> %s (external)",str,a)
+ end
+ else
+ if trace_entities then
+ logs.report("xml","keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
+ end
+ end
+ acache[str] = a
+ elseif trace_entities then
+ if not acache[str] then
+ logs.report("xml","converting entity &%s; into %s",str,a)
+ acache[str] = a
+ end
+ end
+ return a
+ else
+ local a = acache[str]
+ if not a then
+ if trace_entities then
+ logs.report("xml","found entity &%s;",str)
+ end
+ a = resolve_predefined and predefined_simplified[str]
+ if a then
+ -- one of the predefined
+ acache[str] = a
+ elseif str == "" then
+ a = "&error;"
+ acache[str] = a
+ else
+ a = "&" .. str .. ";"
+ acache[str] = a
+ end
+ end
+ return a
+ end
+end
+
+local function handle_end_entity(chr)
+ logs.report("xml","error in entity, %q found instead of ';'",chr)
+end
+
+local space = S(' \r\n\t')
+local open = P('<')
+local close = P('>')
+local squote = S("'")
+local dquote = S('"')
+local equal = P('=')
+local slash = P('/')
+local colon = P(':')
+local semicolon = P(';')
+local ampersand = P('&')
+local valid = R('az', 'AZ', '09') + S('_-.')
+local name_yes = C(valid^1) * colon * C(valid^1)
+local name_nop = C(P(true)) * C(valid^1)
+local name = name_yes + name_nop
+local utfbom = lpeg.patterns.utfbom -- no capture
+local spacing = C(space^0)
+
+----- entitycontent = (1-open-semicolon)^0
+local anyentitycontent = (1-open-semicolon-space-close)^0
+local hexentitycontent = R("AF","af","09")^0
+local decentitycontent = R("09")^0
+local parsedentity = P("#")/"" * (
+ P("x")/"" * (hexentitycontent/handle_hex_entity) +
+ (decentitycontent/handle_dec_entity)
+ ) + (anyentitycontent/handle_any_entity)
+local entity = ampersand/"" * parsedentity * ( (semicolon/"") + #(P(1)/handle_end_entity))
+
+local text_unparsed = C((1-open)^1)
+local text_parsed = Cs(((1-open-ampersand)^1 + entity)^1)
+
+local somespace = space^1
+local optionalspace = space^0
+
+----- value = (squote * C((1 - squote)^0) * squote) + (dquote * C((1 - dquote)^0) * dquote) -- ampersand and < also invalid in value
+local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dquote * Cs((entity + (1 - dquote))^0) * dquote) -- ampersand and < also invalid in value
+
+local endofattributes = slash * close + close -- recovery of flacky html
+local whatever = space * name * optionalspace * equal
+local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
+----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
+local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
+
+local attributevalue = value + wrongvalue
+
+local attribute = (somespace * name * optionalspace * equal * optionalspace * attributevalue) / add_attribute
+----- attributes = (attribute)^0
+
+local attributes = (attribute + somespace^-1 * (((1-endofattributes)^1)/attribute_specification_error))^0
+
+local parsedtext = text_parsed / add_text
+local unparsedtext = text_unparsed / add_text
+local balanced = P { "[" * ((1 - S"[]") + V(1))^0 * "]" } -- taken from lpeg manual, () example
+
+local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
+local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
+local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
+
+local begincomment = open * P("!--")
+local endcomment = P("--") * close
+local begininstruction = open * P("?")
+local endinstruction = P("?") * close
+local begincdata = open * P("![CDATA[")
+local endcdata = P("]]") * close
+
+local someinstruction = C((1 - endinstruction)^0)
+local somecomment = C((1 - endcomment )^0)
+local somecdata = C((1 - endcdata )^0)
+
+local function normalentity(k,v ) entities[k] = v end
+local function systementity(k,v,n) entities[k] = v end
+local function publicentity(k,v,n) entities[k] = v end
+
+local begindoctype = open * P("!DOCTYPE")
+local enddoctype = close
+local beginset = P("[")
+local endset = P("]")
+local doctypename = C((1-somespace-close)^0)
+local elementdoctype = optionalspace * P(" &
+ cleanup = settings.text_cleanup
+ stack, top, at, xmlns, errorstr, result, entities = { }, { }, { }, { }, nil, nil, settings.entities or { }
+ acache, hcache, dcache = { }, { }, { } -- not stored
+ reported_attribute_errors = { }
+ if settings.parent_root then
+ mt = getmetatable(settings.parent_root)
+ else
+ initialize_mt(top)
+ end
+ stack[#stack+1] = top
+ top.dt = { }
+ dt = top.dt
+ if not data or data == "" then
+ errorstr = "empty xml file"
+ elseif utfize or resolve then
+ if lpegmatch(grammar_parsed_text,data) then
+ errorstr = ""
+ else
+ errorstr = "invalid xml file - parsed text"
+ end
+ elseif type(data) == "string" then
+ if lpegmatch(grammar_unparsed_text,data) then
+ errorstr = ""
+ else
+ errorstr = "invalid xml file - unparsed text"
+ end
+ else
+ errorstr = "invalid xml file - no text at all"
+ end
+ if errorstr and errorstr ~= "" then
+ result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={ }, er = true } } }
+ setmetatable(stack, mt)
+ local error_handler = settings.error_handler
+ if error_handler == false then
+ -- no error message
+ else
+ error_handler = error_handler or xml.error_handler
+ if error_handler then
+ xml.error_handler("load",errorstr)
+ end
+ end
+ else
+ result = stack[1]
+ end
+ if not settings.no_root then
+ result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={ }, entities = entities, settings = settings }
+ setmetatable(result, mt)
+ local rdt = result.dt
+ for k=1,#rdt do
+ local v = rdt[k]
+ if type(v) == "table" and not v.special then -- always table -)
+ result.ri = k -- rootindex
+v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ break
+ end
+ end
+ end
+ if errorstr and errorstr ~= "" then
+ result.error = true
+ end
+ return result
+end
+
+xml.convert = xmlconvert
+
+function xml.inheritedconvert(data,xmldata)
+ local settings = xmldata.settings
+ settings.parent_root = xmldata -- to be tested
+ -- settings.no_root = true
+ local xc = xmlconvert(data,settings)
+ -- xc.settings = nil
+ -- xc.entities = nil
+ -- xc.special = nil
+ -- xc.ri = nil
+ -- print(xc.tg)
+ return xc
+end
+
+--[[ldx--
+
Packaging data in an xml like table is done with the following
+function. Maybe it will go away (when not used).
+--ldx]]--
+
+function xml.is_valid(root)
+ return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
+end
+
+function xml.package(tag,attributes,data)
+ local ns, tg = match(tag,"^(.-):?([^:]+)$")
+ local t = { ns = ns, tg = tg, dt = data or "", at = attributes or {} }
+ setmetatable(t, mt)
+ return t
+end
+
+function xml.is_valid(root)
+ return root and not root.error
+end
+
+xml.error_handler = (logs and logs.report) or (input and logs.report) or print
+
+--[[ldx--
+
We cannot load an from a filehandle so we need to load
+the whole file first. The function accepts a string representing
+a filename or a file handle.
+--ldx]]--
+
+function xml.load(filename,settings)
+ local data = ""
+ if type(filename) == "string" then
+ -- local data = io.loaddata(filename) - -todo: check type in io.loaddata
+ local f = io.open(filename,'r')
+ if f then
+ data = f:read("*all")
+ f:close()
+ end
+ elseif filename then -- filehandle
+ data = filename:read("*all")
+ end
+ return xmlconvert(data,settings)
+end
+
+--[[ldx--
+
When we inject new elements, we need to convert strings to
+valid trees, which is what the next function does.
+--ldx]]--
+
+local no_root = { no_root = true }
+
+function xml.toxml(data)
+ if type(data) == "string" then
+ local root = { xmlconvert(data,no_root) }
+ return (#root > 1 and root) or root[1]
+ else
+ return data
+ end
+end
+
+--[[ldx--
+
For copying a tree we use a dedicated function instead of the
+generic table copier. Since we know what we're dealing with we
+can speed up things a bit. The second argument is not to be used!
+--ldx]]--
+
+local function copy(old,tables)
+ if old then
+ tables = tables or { }
+ local new = { }
+ if not tables[old] then
+ tables[old] = new
+ end
+ for k,v in next, old do
+ new[k] = (type(v) == "table" and (tables[v] or copy(v, tables))) or v
+ end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
+ end
+end
+
+xml.copy = copy
+
+--[[ldx--
+
In serializing the tree or parts of the tree is a major
+actitivity which is why the following function is pretty optimized resulting
+in a few more lines of code than needed. The variant that uses the formatting
+function for all components is about 15% slower than the concatinating
+alternative.
+--ldx]]--
+
+-- todo: add when not present
+
+function xml.checkbom(root) -- can be made faster
+ if root.ri then
+ local dt, found = root.dt, false
+ for k=1,#dt do
+ local v = dt[k]
+ if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
+ found = true
+ break
+ end
+ end
+ if not found then
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
+ end
+ end
+end
+
+--[[ldx--
+
At the cost of some 25% runtime overhead you can first convert the tree to a string
+and then handle the lot.
+--ldx]]--
+
+-- new experimental reorganized serialize
+
+local function verbose_element(e,handlers)
+ local handle = handlers.handle
+ local serialize = handlers.serialize
+ local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
+ local ats = eat and next(eat) and { }
+ if ats then
+ for k,v in next, eat do
+ ats[#ats+1] = format('%s=%q',k,v)
+ end
+ end
+ if ern and trace_remap and ern ~= ens then
+ ens = ern
+ end
+ if ens ~= "" then
+ if edt and #edt > 0 then
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),">")
+ else
+ handle("<",ens,":",etg,">")
+ end
+ for i=1,#edt do
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(e)
+ else
+ serialize(e,handlers)
+ end
+ end
+ handle("",ens,":",etg,">")
+ else
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",ens,":",etg,"/>")
+ end
+ end
+ else
+ if edt and #edt > 0 then
+ if ats then
+ handle("<",etg," ",concat(ats," "),">")
+ else
+ handle("<",etg,">")
+ end
+ for i=1,#edt do
+ local ei = edt[i]
+ if type(ei) == "string" then
+ handle(ei)
+ else
+ serialize(ei,handlers)
+ end
+ end
+ handle("",etg,">")
+ else
+ if ats then
+ handle("<",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",etg,"/>")
+ end
+ end
+ end
+end
+
+local function verbose_pi(e,handlers)
+ handlers.handle("",e.dt[1],"?>")
+end
+
+local function verbose_comment(e,handlers)
+ handlers.handle("")
+end
+
+local function verbose_cdata(e,handlers)
+ handlers.handle("")
+end
+
+local function verbose_doctype(e,handlers)
+ handlers.handle("")
+end
+
+local function verbose_root(e,handlers)
+ handlers.serialize(e.dt,handlers)
+end
+
+local function verbose_text(e,handlers)
+ handlers.handle(e)
+end
+
+local function verbose_document(e,handlers)
+ local serialize = handlers.serialize
+ local functions = handlers.functions
+ for i=1,#e do
+ local ei = e[i]
+ if type(ei) == "string" then
+ functions["@tx@"](ei,handlers)
+ else
+ serialize(ei,handlers)
+ end
+ end
+end
+
+local function serialize(e,handlers,...)
+ local initialize = handlers.initialize
+ local finalize = handlers.finalize
+ local functions = handlers.functions
+ if initialize then
+ local state = initialize(...)
+ if not state == true then
+ return state
+ end
+ end
+ local etg = e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ -- elseif type(e) == "string" then
+ -- functions["@tx@"](e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+ if finalize then
+ return finalize()
+ end
+end
+
+local function xserialize(e,handlers)
+ local functions = handlers.functions
+ local etg = e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ -- elseif type(e) == "string" then
+ -- functions["@tx@"](e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+end
+
+local handlers = { }
+
+local function newhandlers(settings)
+ local t = table.copy(handlers.verbose or { }) -- merge
+ if settings then
+ for k,v in next, settings do
+ if type(v) == "table" then
+ tk = t[k] if not tk then tk = { } t[k] = tk end
+ for kk,vv in next, v do
+ tk[kk] = vv
+ end
+ else
+ t[k] = v
+ end
+ end
+ if settings.name then
+ handlers[settings.name] = t
+ end
+ end
+ return t
+end
+
+local nofunction = function() end
+
+function xml.sethandlersfunction(handler,name,fnc)
+ handler.functions[name] = fnc or nofunction
+end
+
+function xml.gethandlersfunction(handler,name)
+ return handler.functions[name]
+end
+
+function xml.gethandlers(name)
+ return handlers[name]
+end
+
+newhandlers {
+ name = "verbose",
+ initialize = false, -- faster than nil and mt lookup
+ finalize = false, -- faster than nil and mt lookup
+ serialize = xserialize,
+ handle = print,
+ functions = {
+ ["@dc@"] = verbose_document,
+ ["@dt@"] = verbose_doctype,
+ ["@rt@"] = verbose_root,
+ ["@el@"] = verbose_element,
+ ["@pi@"] = verbose_pi,
+ ["@cm@"] = verbose_comment,
+ ["@cd@"] = verbose_cdata,
+ ["@tx@"] = verbose_text,
+ }
+}
+
+--[[ldx--
+
How you deal with saving data depends on your preferences. For a 40 MB database
+file the timing on a 2.3 Core Duo are as follows (time in seconds):
+
+
+1.3 : load data from file to string
+6.1 : convert string into tree
+5.3 : saving in file using xmlsave
+6.8 : converting to string using xml.tostring
+3.6 : saving converted string in file
+
+
+
Beware, these were timing with the old routine but measurements will not be that
+much different I guess.
+--ldx]]--
+
+-- maybe this will move to lxml-xml
+
+local result
+
+local xmlfilehandler = newhandlers {
+ name = "file",
+ initialize = function(name) result = io.open(name,"wb") return result end,
+ finalize = function() result:close() return true end,
+ handle = function(...) result:write(...) end,
+}
+
+-- no checking on writeability here but not faster either
+--
+-- local xmlfilehandler = newhandlers {
+-- initialize = function(name) io.output(name,"wb") return true end,
+-- finalize = function() io.close() return true end,
+-- handle = io.write,
+-- }
+
+
+function xml.save(root,name)
+ serialize(root,xmlfilehandler,name)
+end
+
+local result
+
+local xmlstringhandler = newhandlers {
+ name = "string",
+ initialize = function() result = { } return result end,
+ finalize = function() return concat(result) end,
+ handle = function(...) result[#result+1] = concat { ... } end
+}
+
+local function xmltostring(root) -- 25% overhead due to collecting
+ if root then
+ if type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
+ end
+ end
+ return ""
+end
+
+local function xmltext(root) -- inline
+ return (root and xmltostring(root)) or ""
+end
+
+function initialize_mt(root)
+ mt = { __tostring = xmltext, __index = root }
+end
+
+xml.defaulthandlers = handlers
+xml.newhandlers = newhandlers
+xml.serialize = serialize
+xml.tostring = xmltostring
+
+--[[ldx--
+
The next function operated on the content only and needs a handle function
+that accepts a string.
+--ldx]]--
+
+local function xmlstring(e,handle)
+ if not handle or (e.special and e.tg ~= "@rt@") then
+ -- nothing
+ elseif e.tg then
+ local edt = e.dt
+ if edt then
+ for i=1,#edt do
+ xmlstring(edt[i],handle)
+ end
+ end
+ else
+ handle(e)
+ end
+end
+
+xml.string = xmlstring
+
+--[[ldx--
+
A few helpers:
+--ldx]]--
+
+--~ xmlsetproperty(root,"settings",settings)
+
+function xml.settings(e)
+ while e do
+ local s = e.settings
+ if s then
+ return s
+ else
+ e = e.__p__
+ end
+ end
+ return nil
+end
+
+function xml.root(e)
+ local r = e
+ while e do
+ e = e.__p__
+ if e then
+ r = e
+ end
+ end
+ return r
+end
+
+function xml.parent(root)
+ return root.__p__
+end
+
+function xml.body(root)
+ return (root.ri and root.dt[root.ri]) or root -- not ok yet
+end
+
+function xml.name(root)
+ if not root then
+ return ""
+ elseif root.ns == "" then
+ return root.tg
+ else
+ return root.ns .. ":" .. root.tg
+ end
+end
+
+--[[ldx--
+
The next helper erases an element but keeps the table as it is,
+and since empty strings are not serialized (effectively) it does
+not harm. Copying the table would take more time. Usage:
+--ldx]]--
+
+function xml.erase(dt,k)
+ if dt then
+ if k then
+ dt[k] = ""
+ else for k=1,#dt do
+ dt[1] = { "" }
+ end end
+ end
+end
+
+--[[ldx--
+
The next helper assigns a tree (or string). Usage:
+
+
+dt[k] = xml.assign(root) or xml.assign(dt,k,root)
+
+--ldx]]--
+
+function xml.assign(dt,k,root)
+ if dt and k then
+ dt[k] = (type(root) == "table" and xml.body(root)) or root
+ return dt[k]
+ else
+ return xml.body(root)
+ end
+end
+
+-- the following helpers may move
+
+--[[ldx--
+
The next helper assigns a tree (or string). Usage:
+
+xml.tocdata(e)
+xml.tocdata(e,"error")
+
+--ldx]]--
+
+function xml.tocdata(e,wrapper)
+ local whatever = xmltostring(e.dt)
+ if wrapper then
+ whatever = format("<%s>%s%s>",wrapper,whatever,wrapper)
+ end
+ local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
+ setmetatable(t,getmetatable(e))
+ e.dt = { t }
+end
+
+function xml.makestandalone(root)
+ if root.ri then
+ local dt = root.dt
+ for k=1,#dt do
+ local v = dt[k]
+ if type(v) == "table" and v.special and v.tg == "@pi@" then
+ local txt = v.dt[1]
+ if find(txt,"xml.*version=") then
+ v.dt[1] = txt .. " standalone='yes'"
+ break
+ end
+ end
+ end
+ end
+end
diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua
new file mode 100644
index 000000000..aaa90217f
--- /dev/null
+++ b/tex/context/base/lxml-tex.lua
@@ -0,0 +1,1410 @@
+if not modules then modules = { } end modules ['lxml-tst'] = {
+ version = 1.001,
+ comment = "companion to lxml-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+
+local utfchar = utf.char
+local concat, insert, remove, gsub, find = table.concat, table.insert, table.remove
+local format, sub, gsub, find, gmatch, match = string.format, string.sub, string.gsub, string.find, string.gmatch, string.match
+local type, next, tonumber, tostring = type, next, tonumber, tostring
+local lpegmatch = lpeg.match
+local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc
+
+if not tex and not tex.sprint then
+ tex = {
+ sprint = function(catcodes,...) texio.write(table.concat{...}) end,
+ print = function(catcodes,...) texio.write(table.concat{...}) end,
+ write = function( ...) texio.write(table.concat{...}) end,
+ }
+ commands = {
+ writestatus = logs.report
+ }
+ resolvers.loadbinfile = function(filename) return true, io.loaddata(filename) end
+end
+
+local texsprint, texprint, texwrite = tex.sprint, tex.print, tex.write
+local texcatcodes, ctxcatcodes, vrbcatcodes, notcatcodes = tex.texcatcodes, tex.ctxcatcodes, tex.vrbcatcodes, tex.notcatcodes
+
+local xmlelements, xmlcollected, xmlsetproperty = xml.elements, xml.collected, xml.setproperty
+local xmlparseapply, xmlwithelements = xml.parse_apply, xml.withelements
+local xmlserialize, xmlcollect, xmltext, xmltostring = xml.serialize, xml.collect, xml.text, xml.tostring
+
+local variables = (interfaces and interfaces.variables) or { }
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+local trace_setups = false trackers.register("lxml.setups", function(v) trace_setups = v end)
+local trace_loading = false trackers.register("lxml.loading", function(v) trace_loading = v end)
+local trace_access = false trackers.register("lxml.access", function(v) trace_access = v end)
+local trace_comments = false trackers.register("lxml.comments", function(v) trace_comments = v end)
+
+lxml = lxml or { }
+lxml.loaded = lxml.loaded or { }
+
+local loaded = lxml.loaded
+
+-- print(contextdirective("context-mathml-directive function reduction yes "))
+-- print(contextdirective("context-mathml-directive function "))
+
+xml.defaultprotocol = "tex"
+
+local finalizers = xml.finalizers
+
+finalizers.xml = finalizers.xml or { }
+finalizers.tex = finalizers.tex or { }
+
+-- this might look inefficient but it's actually rather efficient
+-- because we avoid tokenization of leading spaces and xml can be
+-- rather verbose (indented)
+
+local newline = lpeg.patterns.newline
+local space = lpeg.patterns.spacer
+local ampersand = P("&")
+local semicolon = P(";")
+local spacing = newline * space^0
+local content = C((1-spacing-ampersand)^1)
+local verbose = C((1-(space+newline))^1)
+local entity = ampersand * C((1-semicolon)^1) * semicolon
+
+local xmltextcapture = (
+ space^0 * newline^2 * Cc("") / texprint + -- better ^-2 ?
+ space^0 * newline * space^0 * Cc(" ") / texsprint +
+ content / function(str) return texsprint(notcatcodes,str) end + -- was just texsprint, current catcodes regime is notcatcodes
+ entity / xml.resolved_entity
+)^0
+
+local ctxtextcapture = (
+ space^0 * newline^2 * Cc("") / texprint + -- better ^-2 ?
+ space^0 * newline * space^0 * Cc(" ") / texsprint +
+ content / function(str) return texsprint(ctxcatcodes,str) end + -- was just texsprint, current catcodes regime is notcatcodes
+ entity / xml.resolved_entity
+)^0
+
+local forceraw, rawroot = false, nil
+
+function lxml.startraw()
+ forceraw = true
+end
+
+function lxml.stopraw()
+ forceraw = false
+end
+
+function lxml.rawroot()
+ return rawroot
+end
+
+--~ function lxml.rawpath(rootid)
+--~ if rawroot and type(rawroot) == "table" then
+--~ local text, path, rp
+--~ if not rawroot.dt then
+--~ text, path, rp = "text", "", rawroot[0]
+--~ else
+--~ path, rp = "tree", "", rawroot.__p__
+--~ end
+--~ while rp do
+--~ local rptg = rp.tg
+--~ if rptg then
+--~ path = rptg .. "/" .. path
+--~ end
+--~ rp = rp.__p__
+--~ end
+--~ return { rootid, "/" .. path, text }
+--~ end
+--~ end
+
+-- cdata
+
+local linecommand = "\\obeyedline"
+local spacecommand = "\\obeyedspace" -- "\\strut\\obeyedspace"
+local beforecommand = ""
+local aftercommand = ""
+
+local xmlverbosecapture = (
+ newline / function( ) texsprint(texcatcodes,linecommand,"{}") end +
+ verbose / function(s) texsprint(vrbcatcodes,s) end +
+ space / function( ) texsprint(texcatcodes,spacecommand,"{}") end
+)^0
+
+local function toverbatim(str)
+ if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end
+ lpegmatch(xmlverbosecapture,str)
+ if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end
+end
+
+function lxml.set_verbatim(before,after,obeyedline,obeyedspace)
+ beforecommand, aftercommand, linecommand, spacecommand = before, after, obeyedline, obeyedspace
+end
+
+local obeycdata = true
+
+function lxml.set_cdata()
+ obeycdata = true
+end
+
+function lxml.reset_cdata()
+ obeycdata = false
+end
+
+-- cdata and verbatim
+
+lxml.set_verbatim("\\xmlcdatabefore", "\\xmlcdataafter", "\\xmlcdataobeyedline", "\\xmlcdataobeyedspace")
+
+-- local capture = (space^0*newline)^0 * capture * (space+newline)^0 * -1
+
+function lxml.toverbatim(str)
+ if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end
+ -- todo: add this to capture
+ str = gsub(str,"^[ \t]+[\n\r]+","")
+ str = gsub(str,"[ \t\n\r]+$","")
+ lpegmatch(xmlverbosecapture,str)
+ if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end
+end
+
+-- storage
+
+function lxml.store(id,root,filename)
+ loaded[id] = root
+ xmlsetproperty(root,"name",id)
+ if filename then
+ xmlsetproperty(root,"filename",filename)
+ end
+end
+
+local splitter = lpeg.splitat("::")
+
+lxml.idsplitter = splitter
+
+function lxml.splitid(id)
+ local d, i = lpegmatch(splitter,id)
+ if d then
+ return d, i
+ else
+ return "", id
+ end
+end
+
+local function get_id(id, qualified)
+ if id then
+ local lid = loaded[id]
+ if lid then
+ return lid
+ elseif type(id) == "table" then
+ return id
+ else
+ local d, i = lpegmatch(splitter,id)
+ if d then
+ local ld = loaded[d]
+ if ld then
+ local ldi = ld.index
+ if ldi then
+ local root = ldi[tonumber(i)]
+ if root then
+ if qualified then -- we need this else two args that confuse others
+ return root, d
+ else
+ return root
+ end
+ elseif trace_access then
+ logs.report("lxml","'%s' has no index entry '%s'",d,i)
+ end
+ elseif trace_access then
+ logs.report("lxml","'%s' has no index",d)
+ end
+ elseif trace_access then
+ logs.report("lxml","'%s' is not loaded",d)
+ end
+ elseif trace_access then
+ logs.report("lxml","'%s' is not loaded",i)
+ end
+ end
+ elseif trace_access then
+ logs.report("lxml","invalid id (nil)")
+ end
+end
+
+lxml.id = get_id
+lxml.get_id = get_id
+
+function lxml.root(id)
+ return loaded[id]
+end
+
+-- index
+
+local nofindices = 0
+
+local function addindex(name,check_sum,force)
+ local root = get_id(name)
+ if root and (not root.index or force) then -- weird, only called once
+ local n, index, maxindex, check = 0, root.index or { }, root.maxindex or 0, root.check or { }
+ local function nest(root)
+ local dt = root.dt
+ if not root.ix then
+ maxindex = maxindex + 1
+ root.ix = maxindex
+ check[maxindex] = root.tg -- still needed ?
+ index[maxindex] = root
+ n = n + 1
+ end
+ if dt then
+ for k=1,#dt do
+ local dk = dt[k]
+ if type(dk) == "table" then
+ nest(dk)
+ end
+ end
+ end
+ end
+ nest(root)
+ nofindices = nofindices + n
+ --
+ if type(name) ~= "string" then
+ name = "unknown"
+ end
+ root.index = index
+ root.maxindex = maxindex
+ if trace_access then
+ logs.report("lxml","%s indexed, %s nodes",tostring(name),maxindex)
+ end
+ end
+end
+
+lxml.addindex = addindex
+
+-- another cache
+
+local function lxmlparseapply(id,pattern) -- better inline, saves call
+ return xmlparseapply({ get_id(id) }, pattern)
+end
+
+lxml.filter = lxmlparseapply
+
+function lxml.filterlist(list,pattern)
+ for s in gmatch(list,"[^, ]+") do -- we could cache a table
+ lxmlparseapply(s,pattern)
+ end
+end
+
+lxml["function"] = function(id,name)
+ local f = xml.functions[name]
+ return f and f(get_id(id))
+end
+
+-- rather new, indexed storage (backward refs), maybe i will merge this
+
+function lxml.checkindex(name)
+ local root = get_id(name)
+ return (root and root.index) or 0
+end
+
+function lxml.withindex(name,n,command) -- will change as name is always there now
+ local i, p = lpegmatch(splitter,n)
+ if p then
+ texsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}")
+ else
+ texsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}")
+ end
+end
+
+function lxml.getindex(name,n) -- will change as name is always there now
+ local i, p = lpegmatch(splitter,n)
+ if p then
+ texsprint(ctxcatcodes,n)
+ else
+ texsprint(ctxcatcodes,name,"::",n)
+ end
+end
+
+-- loading (to be redone, no overload)
+
+xml.originalload = xml.originalload or xml.load
+
+local noffiles, nofconverted = 0, 0
+
+function xml.load(filename,settings)
+ noffiles, nofconverted = noffiles + 1, nofconverted + 1
+ starttiming(xml)
+ local ok, data = resolvers.loadbinfile(filename)
+ local xmltable = xml.convert((ok and data) or "",settings)
+ stoptiming(xml)
+ return xmltable
+end
+
+local entities = xml.entities
+
+local function entityconverter(id,str)
+ return entities[str] and "&"..str..";" -- feed back into tex end later
+end
+
+function lxml.convert(id,data,entities,compress)
+ local settings = {
+ unify_predefined_entities = true,
+ }
+ if compress and compress == variables.yes then
+ settings.strip_cm_and_dt = true
+ end
+ if entities and entities == variables.yes then
+ settings.utfize_entities = true
+ settings.resolve_entities = function (str) return entityconverter(id,str) end
+ end
+ return xml.convert(data,settings)
+end
+
+function lxml.load(id,filename,compress,entities)
+ filename = commands.preparedfile(filename)
+ if trace_loading then
+ commands.writestatus("lxml","loading file '%s' as '%s'",filename,id)
+ end
+ noffiles, nofconverted = noffiles + 1, nofconverted + 1
+ -- local xmltable = xml.load(filename)
+ local ok, data = resolvers.loadbinfile(filename)
+ local xmltable = lxml.convert(id,(ok and data) or "",compress,entities)
+ lxml.store(id,xmltable,filename)
+ return xmltable, filename
+end
+
+function lxml.register(id,xmltable,filename)
+ lxml.store(id,xmltable,filename)
+ return xmltable
+end
+
+function lxml.include(id,pattern,attribute,recurse)
+ starttiming(xml)
+ local root = get_id(id)
+ xml.include(root,pattern,attribute,recurse,function(filename)
+ if filename then
+ filename = commands.preparedfile(filename)
+ if file.dirname(filename) == "" and root.filename then
+ local dn = file.dirname(root.filename)
+ if dn ~= "" then
+ filename = file.join(dn,filename)
+ end
+ end
+ if trace_loading then
+ commands.writestatus("lxml","including file: %s",filename)
+ end
+ noffiles, nofconverted = noffiles + 1, nofconverted + 1
+ return resolvers.loadtexfile(filename) or ""
+ else
+ return ""
+ end
+ end)
+ stoptiming(xml)
+end
+
+function xml.getbuffer(name,compress,entities) -- we need to make sure that commands are processed
+ if not name or name == "" then
+ name = tex.jobname
+ end
+ nofconverted = nofconverted + 1
+ xmltostring(lxml.convert(name,concat(buffers.data[name] or {},""),compress,entities))
+end
+
+function lxml.loadbuffer(id,name,compress,entities)
+ if not name or name == "" then
+ name = tex.jobname
+ end
+ starttiming(xml)
+ nofconverted = nofconverted + 1
+ local xmltable = lxml.convert(id,buffers.collect(name or id,"\n"),compress,entities)
+ lxml.store(id,xmltable)
+ stoptiming(xml)
+ return xmltable, name or id
+end
+
+function lxml.loaddata(id,str,compress,entities)
+ starttiming(xml)
+ nofconverted = nofconverted + 1
+ local xmltable = lxml.convert(id,str or "",compress,entities)
+ lxml.store(id,xmltable)
+ stoptiming(xml)
+ return xmltable, id
+end
+
+function lxml.loadregistered(id)
+ return loaded[id], id
+end
+
+-- e.command:
+--
+-- string : setup
+-- true : text (no )
+-- false : ignore
+-- function : call
+
+local function tex_doctype(e,handlers)
+ -- ignore
+end
+
+local function tex_comment(e,handlers)
+ if trace_comments then
+ logs.report("lxml","comment: %s",e.dt[1])
+ end
+end
+
+local default_element_handler = xml.gethandlers("verbose").functions["@el@"]
+
+local function tex_element(e,handlers)
+ local command = e.command
+ if command == nil then
+ default_element_handler(e,handlers)
+ elseif command == true then
+ -- text (no ) / so, no mkii fallback then
+ handlers.serialize(e.dt,handlers)
+ elseif command == false then
+ -- ignore
+ else
+ local tc = type(command)
+ if tc == "string" then
+ local rootname, ix = e.name, e.ix
+ if rootname then
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ texsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}")
+ else
+ logs.report("lxml", "fatal error: no index for '%s'",command)
+ texsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}")
+ end
+ elseif tc == "function" then
+ command(e)
+ end
+ end
+end
+
+local pihandlers = { } xml.pihandlers = pihandlers
+
+local kind = P("context-") * C((1-P("-"))^1) * P("-directive")
+local space = S(" \n\r")
+local spaces = space^0
+local class = C((1-space)^0)
+local key = class
+local value = C(P(1-(space * -1))^0)
+
+local parser = kind * spaces * class * spaces * key * spaces * value
+
+pihandlers[#pihandlers+1] = function(str)
+-- local kind, class, key, value = lpegmatch(parser,str)
+ if str then
+ local a, b, c, d = lpegmatch(parser,str)
+ if d then
+ texsprint(ctxcatcodes,"\\xmlcontextdirective{",a",}{",b,"}{",c,"}{",d,"}")
+ end
+ end
+end
+
+local function tex_pi(e,handlers)
+ local str = e.dt[1]
+ for i=1,#pihandlers do
+ pihandlers[i](str)
+ end
+end
+
+local function tex_cdata(e,handlers)
+ if obeycdata then
+ toverbatim(e.dt[1])
+ end
+end
+
+local function tex_text(e)
+ lpegmatch(xmltextcapture,e)
+end
+
+local function ctx_text(e)
+ lpegmatch(ctxtextcapture,e)
+end
+
+local function tex_handle(...)
+-- logs.report("lxml", "error while flushing: %s", concat { ... })
+ texsprint(...) -- notcatcodes is active anyway
+end
+
+local xmltexhandler = xml.newhandlers {
+ name = "tex",
+ handle = tex_handle,
+ functions = {
+ -- ["@dc@"] = tex_document,
+ ["@dt@"] = tex_doctype,
+ -- ["@rt@"] = tex_root,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_text,
+ }
+}
+
+lxml.xmltexhandler = xmltexhandler
+
+function lxml.serialize(root)
+ xmlserialize(root,xmltexhandler)
+end
+
+function lxml.setaction(id,pattern,action)
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].command = action
+ end
+ end
+end
+
+local function sprint(root)
+ if root then
+ local tr = type(root)
+ if tr == "string" then -- can also be result of lpath
+ -- rawroot = false
+ lpegmatch(xmltextcapture,root)
+ elseif tr == "table" then
+ if forceraw then
+ rawroot = root
+ texwrite(xmltostring(root))
+ else
+ xmlserialize(root,xmltexhandler)
+ end
+ end
+ end
+end
+
+local function tprint(root) -- we can move sprint inline
+ local tr = type(root)
+ if tr == "table" then
+ local n = #root
+ if n == 0 then
+ -- skip
+ else
+ for i=1,n do
+ sprint(root[i])
+ end
+ end
+ elseif tr == "string" then
+ lpegmatch(xmltextcapture,root)
+ end
+end
+
+local function cprint(root) -- content
+ if not root then
+ -- rawroot = false
+ -- quit
+ elseif type(root) == 'string' then
+ -- rawroot = false
+ lpegmatch(xmltextcapture,root)
+ else
+ local rootdt = root.dt
+ if forceraw then
+ rawroot = root
+ texwrite(xmltostring(rootdt or root))
+ else
+ xmlserialize(rootdt or root,xmltexhandler)
+ end
+ end
+end
+
+xml.sprint = sprint local xmlsprint = sprint -- redo these names
+xml.tprint = tprint local xmltprint = tprint
+xml.cprint = cprint local xmlcprint = cprint
+
+-- now we can flush
+
+function lxml.main(id)
+ xmlserialize(get_id(id),xmltexhandler) -- the real root (@rt@)
+end
+
+--~ -- lines (untested)
+--~
+--~ local buffer = { }
+--~
+--~ local xmllinescapture = (
+--~ newline^2 / function() buffer[#buffer+1] = "" end +
+--~ newline / function() buffer[#buffer] = buffer[#buffer] .. " " end +
+--~ content / function(s) buffer[#buffer] = buffer[#buffer] .. s end
+--~ )^0
+--~
+--~ local xmllineshandler = table.copy(xmltexhandler)
+--~
+--~ xmllineshandler.handle = function(...) lpegmatch(xmllinescapture,concat{ ... }) end
+--~
+--~ function lines(root)
+--~ if not root then
+--~ -- rawroot = false
+--~ -- quit
+--~ elseif type(root) == 'string' then
+--~ -- rawroot = false
+--~ lpegmatch(xmllinescapture,root)
+--~ elseif next(root) then -- tr == 'table'
+--~ xmlserialize(root,xmllineshandler)
+--~ end
+--~ end
+--~
+--~ function xml.lines(root) -- used at all?
+--~ buffer = { "" }
+--~ lines(root)
+--~ return result
+--~ end
+
+local function to_text(e)
+ if e.command == nil then
+ local etg = e.tg
+ if etg and e.special and etg ~= "@rt@" then
+ e.command = false -- i.e. skip
+ else
+ e.command = true -- i.e. no
+ end
+ end
+end
+
+local function to_none(e)
+ if e.command == nil then
+ e.command = false -- i.e. skip
+ end
+end
+
+-- setups
+
+local setups = { }
+
+function lxml.set_command_to_text(id)
+ xmlwithelements(get_id(id),to_text)
+end
+
+function lxml.set_command_to_none(id)
+ xmlwithelements(get_id(id),to_none)
+end
+
+function lxml.installsetup(what,document,setup,where)
+ document = document or "*"
+ local sd = setups[document]
+ if not sd then sd = { } setups[document] = sd end
+ for k=1,#sd do
+ if sd[k] == setup then sd[k] = nil break end
+ end
+ if what == 1 then
+ if trace_loading then
+ commands.writestatus("lxml","prepending setup %s for %s",setup,document)
+ end
+ insert(sd,1,setup)
+ elseif what == 2 then
+ if trace_loading then
+ commands.writestatus("lxml","appending setup %s for %s",setup,document)
+ end
+ insert(sd,setup)
+ elseif what == 3 then
+ if trace_loading then
+ commands.writestatus("lxml","inserting setup %s for %s before %s",setup,document,where)
+ end
+ table.insert_before_value(sd,setup,where)
+ elseif what == 4 then
+ if trace_loading then
+ commands.writestatus("lxml","inserting setup %s for %s after %s",setup,document,where)
+ end
+ table.insert_after_value(sd,setup,where)
+ end
+end
+
+function lxml.flushsetups(id,...)
+ local done, list = { }, { ... }
+ for i=1,#list do
+ local document = list[i]
+ local sd = setups[document]
+ if sd then
+ for k=1,#sd do
+ local v= sd[k]
+ if not done[v] then
+ if trace_loading then
+ commands.writestatus("lxml","applying setup %02i = %s to %s",k,v,document)
+ end
+ texsprint(ctxcatcodes,"\\xmlsetup{",id,"}{",v,"}")
+ done[v] = true
+ end
+ end
+ elseif trace_loading then
+ commands.writestatus("lxml","no setups for %s",document)
+ end
+ end
+end
+
+function lxml.resetsetups(document)
+ if trace_loading then
+ commands.writestatus("lxml","resetting all setups for %s",document)
+ end
+ setups[document] = { }
+end
+
+function lxml.removesetup(document,setup)
+ local s = setups[document]
+ if s then
+ for i=1,#s do
+ if s[i] == setup then
+ if trace_loading then
+ commands.writestatus("lxml","removing setup %s for %s",setup,document)
+ end
+ remove(t,i)
+ break
+ end
+ end
+ end
+end
+
+function lxml.setsetup(id,pattern,setup)
+ if not setup or setup == "" or setup == "*" or setup == "-" or setup == "+" then
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ if trace_setups then
+ for c=1, #collected do
+ local e = collected[c]
+ local ix = e.ix or 0
+ if setup == "-" then
+ e.command = false
+ logs.report("lxml","lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup)
+ elseif setup == "+" then
+ e.command = true
+ logs.report("lxml","lpath matched (b) %5i: %s = %s -> text",c,ix,setup)
+ else
+ local tg = e.tg
+ if tg then -- to be sure
+ e.command = tg
+ local ns = e.rn or e.ns
+ if ns == "" then
+ logs.report("lxml","lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg)
+ else
+ logs.report("lxml","lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg)
+ end
+ end
+ end
+ end
+ else
+ for c=1, #collected do
+ local e = collected[c]
+ if setup == "-" then
+ e.command = false
+ elseif setup == "+" then
+ e.command = true
+ else
+ e.command = e.tg
+ end
+ end
+ end
+ elseif trace_setups then
+ logs.report("lxml","no lpath matches for %s",pattern)
+ end
+ else
+ local a, b = match(setup,"^(.+:)([%*%-])$")
+ if a and b then
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ if trace_setups then
+ for c=1, #collected do
+ local e = collected[c]
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if b == "-" then
+ e.command = false
+ if ns == "" then
+ logs.report("lxml","lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg)
+ else
+ logs.report("lxml","lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg)
+ end
+ elseif b == "+" then
+ e.command = true
+ if ns == "" then
+ logs.report("lxml","lpath matched (g) %5i: %s = %s -> text",c,ix,tg)
+ else
+ logs.report("lxml","lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg)
+ end
+ else
+ e.command = a .. tg
+ if ns == "" then
+ logs.report("lxml","lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command)
+ else
+ logs.report("lxml","lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command)
+ end
+ end
+ end
+ else
+ for c=1, #collected do
+ local e = collected[c]
+ if b == "-" then
+ e.command = false
+ elseif b == "+" then
+ e.command = true
+ else
+ e.command = a .. e.tg
+ end
+ end
+ end
+ elseif trace_setups then
+ logs.report("lxml","no lpath matches for %s",pattern)
+ end
+ else
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ if trace_setups then
+ for c=1, #collected do
+ local e = collected[c]
+ e.command = setup
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if ns == "" then
+ logs.report("lxml","lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup)
+ else
+ logs.report("lxml","lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup)
+ end
+ end
+ else
+ for c=1, #collected do
+ collected[c].command = setup
+ end
+ end
+ elseif trace_setups then
+ logs.report("lxml","no lpath matches for %s",pattern)
+ end
+ end
+ end
+end
+
+-- finalizers
+
+local finalizers = xml.finalizers.tex
+
+local function first(collected)
+ if collected then
+ xmlsprint(collected[1])
+ end
+end
+
+local function last(collected)
+ if collected then
+ xmlsprint(collected[#collected])
+ end
+end
+
+local function all(collected)
+ if collected then
+ for c=1,#collected do
+ xmlsprint(collected[c])
+ end
+ end
+end
+
+local function reverse(collected)
+ if collected then
+ for c=#collected,1,-1 do
+ xmlsprint(collected[c])
+ end
+ end
+end
+
+local function count(collected)
+ texwrite((collected and #collected) or 0)
+end
+
+local function position(collected,n)
+ -- todo: if not n then == match
+ if collected then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = #collected + n + 1
+ end
+ if n > 0 then
+ xmlsprint(collected[n])
+ end
+ end
+end
+
+local function match(collected) -- is match in preceding collected, never change, see bibxml
+ texwrite((collected and collected[1].mi) or 0)
+end
+
+local function index(collected,n)
+ if collected then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = #collected + n + 1
+ end
+ if n > 0 then
+ texwrite(collected[n].ni or 0)
+ end
+ end
+end
+
+local function command(collected,cmd)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local ix = e.ix
+ if not ix then
+ lxml.addindex(e.name,false,true)
+ ix = e.ix
+ end
+ texsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",e.name,"::",ix,"}")
+ end
+ end
+end
+
+local function attribute(collected,a,default)
+ if collected and #collected > 0 then
+ local at = collected[1].at
+ local str = (at and at[a]) or default
+ if str and str ~= "" then
+ texsprint(notcatcodes,str)
+ end
+ elseif default then
+ texsprint(notcatcodes,default)
+ end
+end
+
+local function chainattribute(collected,arguments) -- todo: optional levels
+ if collected then
+ local e = collected[1]
+ while e do
+ local at = e.at
+ if at then
+ local a = at[arguments]
+ if a then
+ texsprint(notcatcodes,a)
+ end
+ else
+ break -- error
+ end
+ e = e.__p__
+ end
+ end
+end
+
+local function text(collected)
+ if collected then
+ local nc = #collected
+ if nc == 1 then -- hardly any gain so this will go
+ cprint(collected[1])
+ else for c=1,nc do
+ cprint(collected[c])
+ end end
+ end
+end
+
+local function ctxtext(collected)
+ if collected then
+ for c=1,#collected do
+ texsprint(ctxcatcodes,collected[1].dt)
+ end
+ end
+end
+
+local lowerchars, upperchars = characters.lower, characters.upper
+
+local function lower(collected)
+ if collected then
+ for c=1,#collected do
+ texsprint(ctxcatcodes,lowerchars(collected[1].dt[1]))
+ end
+ end
+end
+
+local function upper(collected)
+ if collected then
+ for c=1,#collected do
+ texsprint(ctxcatcodes,upperchars(collected[1].dt[1]))
+ end
+ end
+end
+
+local function number(collected)
+ if collected then
+ local n = 0
+ for c=1,#collected do
+ n = n + tonumber(collected[c].dt[1] or 0)
+ end
+ texwrite(n)
+ end
+end
+
+local function concatrange(collected,start,stop,separator,lastseparator,textonly) -- test this on mml
+ if collected then
+ local nofcollected = #collected
+ local separator = separator or ""
+ local lastseparator = lastseparator or separator or ""
+ start, stop = (start == "" and 1) or tonumber(start) or 1, (stop == "" and nofcollected) or tonumber(stop) or nofcollected
+ if stop < 0 then stop = nofcollected + stop end -- -1 == last-1
+ for i=start,stop do
+ if textonly then
+ xmlcprint(collected[i])
+ else
+ xmlsprint(collected[i])
+ end
+ if i == nofcollected then
+ -- nothing
+ elseif i == nofcollected-1 and lastseparator ~= "" then
+ texsprint(ctxcatcodes,lastseparator)
+ elseif separator ~= "" then
+ texsprint(ctxcatcodes,separator)
+ end
+ end
+ end
+end
+
+local function concat(collected,separator,lastseparator,textonly) -- test this on mml
+ concatrange(collected,false,false,separator,lastseparator,textonly)
+end
+
+finalizers.first = first
+finalizers.last = last
+finalizers.all = all
+finalizers.reverse = reverse
+finalizers.count = count
+finalizers.command = command
+finalizers.attribute = attribute
+finalizers.text = text
+finalizers.lower = lower
+finalizers.upper = upper
+finalizers.ctxtext = ctxtext
+finalizers.context = ctxtext
+finalizers.position = position
+finalizers.match = match
+finalizers.index = index
+finalizers.concat = concat
+finalizers.concatrange = concatrange
+finalizers.chainattribute = chainattribute
+finalizers.default = all -- !!
+
+local concat = table.concat
+
+function finalizers.tag(collected)
+ if collected then
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[#collected-n+1]
+ end
+ if c then
+ texsprint(c.tg)
+ end
+ end
+end
+
+function finalizers.name(collected)
+ if collected then
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[#collected-n+1]
+ end
+ if c then
+ if c.ns == "" then
+ texsprint(c.tg)
+ else
+ texsprint(c.ns,":",c.tg)
+ end
+ end
+ end
+end
+
+function finalizers.tags(collected,nonamespace)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ if nonamespace or ns == "" then
+ texsprint(tg)
+ else
+ texsprint(ns,":",tg)
+ end
+ end
+ end
+end
+
+--
+
+local function verbatim(id,before,after)
+ local root = get_id(id)
+ if root then
+ if before then texsprint(ctxcatcodes,before,"[",root.tg or "?","]") end
+ lxml.toverbatim(xmltostring(root.dt))
+ if after then texsprint(ctxcatcodes,after) end
+ end
+end
+function lxml.inlineverbatim(id)
+ verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim")
+end
+function lxml.displayverbatim(id)
+ verbatim(id,"\\startxmldisplayverbatim","\\stopxmldisplayverbatim")
+end
+
+lxml.verbatim = verbatim
+
+-- helpers
+
+function lxml.first(id,pattern)
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ first(collected)
+ end
+end
+
+function lxml.last(id,pattern)
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ last(collected)
+ end
+end
+
+function lxml.all(id,pattern)
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ all(collected)
+ end
+end
+
+function lxml.count(id,pattern)
+ -- always needs to produce a result so no test here
+ count(lxmlparseapply(id,pattern))
+end
+
+function lxml.attribute(id,pattern,a,default)
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ attribute(collected,a,default)
+ end
+end
+
+function lxml.raw(id,pattern) -- the content, untouched by commands
+ local collected = (pattern and lxmlparseapply(id,pattern)) or get_id(id)
+ if collected then
+ texsprint(xmltostring(collected[1].dt))
+ end
+end
+
+function lxml.context(id,pattern) -- the content, untouched by commands
+ if not pattern then
+ local collected = get_id(id)
+ -- texsprint(ctxcatcodes,collected.dt[1])
+ ctx_text(collected.dt[1])
+ else
+ local collected = lxmlparseapply(id,pattern) or get_id(id)
+ if collected and #collected > 0 then
+ texsprint(ctxcatcodes,collected[1].dt)
+ end
+ end
+end
+
+function lxml.text(id,pattern)
+ local collected = (pattern and lxmlparseapply(id,pattern)) or get_id(id)
+ if collected then
+ text(collected)
+ end
+end
+
+lxml.content = text
+
+function lxml.position(id,pattern,n)
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ position(collected,n)
+ end
+end
+
+function lxml.chainattribute(id,pattern,a,default)
+ local collected = lxmlparseapply(id,pattern)
+ if collected then
+ chainattribute(collected,a,default)
+ end
+end
+
+function lxml.concatrange(id,pattern,start,stop,separator,lastseparator,textonly) -- test this on mml
+ concatrange(lxmlparseapply(id,pattern),start,stop,separator,lastseparator,textonly)
+end
+
+function lxml.concat(id,pattern,separator,lastseparator,textonly)
+ concatrange(lxmlparseapply(id,pattern),false,false,separator,lastseparator,textonly)
+end
+
+function lxml.element(id,n)
+ position(lxmlparseapply(id,"/*"),n)
+end
+
+lxml.index = lxml.position
+
+function lxml.pos(id)
+ local root = get_id(id)
+ texwrite((root and root.ni) or 0)
+end
+
+function lxml.att(id,a,default)
+ local root = get_id(id)
+ if root then
+ local at = root.at
+ local str = (at and at[a]) or default
+ if str and str ~= "" then
+ texsprint(notcatcodes,str)
+ end
+ elseif default then
+ texsprint(notcatcodes,default)
+ end
+end
+
+function lxml.name(id) -- or remapped name? -> lxml.info, combine
+ local r = get_id(id)
+ local ns = r.rn or r.ns or ""
+ if ns ~= "" then
+ texsprint(ns,":",r.tg)
+ else
+ texsprint(r.tg)
+ end
+end
+
+function lxml.match(id) -- or remapped name? -> lxml.info, combine
+ texsprint(get_id(id).mi or 0)
+end
+
+function lxml.tag(id) -- tag vs name -> also in l-xml tag->name
+ texsprint(get_id(id).tg or "")
+end
+
+function lxml.namespace(id) -- or remapped name?
+ local root = get_id(id)
+ texsprint(root.rn or root.ns or "")
+end
+
+function lxml.flush(id)
+ id = get_id(id)
+ local dt = id and id.dt
+ if dt then
+ xmlsprint(dt)
+ end
+end
+
+function lxml.snippet(id,i)
+ local e = get_id(id)
+ if e then
+ local edt = e.dt
+ if edt then
+ xmlsprint(edt[i])
+ end
+ end
+end
+
+function lxml.direct(id)
+ xmlsprint(get_id(id))
+end
+
+function lxml.command(id,pattern,cmd)
+ local i, p = get_id(id,true)
+ local collected = lxmlparseapply(i,pattern)
+ if collected then
+ local rootname = p or i.name
+ for c=1,#collected do
+ local e = collected[c]
+ local ix = e.ix
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ texsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
+ end
+ end
+end
+
+-- loops
+
+function lxml.collected(id,pattern,reverse)
+ return xmlcollected(get_id(id),pattern,reverse)
+end
+
+function lxml.elements(id,pattern,reverse)
+ return xmlelements(get_id(id),pattern,reverse)
+end
+
+-- obscure ones
+
+lxml.info = lxml.name
+
+-- testers
+
+local found, empty = xml.found, xml.empty
+
+local doif, doifnot, doifelse = commands.doif, commands.doifnot, commands.doifelse
+
+function lxml.doif (id,pattern) doif (found(get_id(id),pattern)) end
+function lxml.doifnot (id,pattern) doifnot (found(get_id(id),pattern)) end
+function lxml.doifelse (id,pattern) doifelse(found(get_id(id),pattern)) end
+function lxml.doiftext (id,pattern) doif (not empty(get_id(id),pattern)) end
+function lxml.doifnottext (id,pattern) doifnot (not empty(get_id(id),pattern)) end
+function lxml.doifelsetext (id,pattern) doifelse(not empty(get_id(id),pattern)) end
+
+-- special case: "*" and "" -> self else lpath lookup
+
+--~ function lxml.doifelseempty(id,pattern) doifelse(isempty(get_id(id),pattern ~= "" and pattern ~= nil)) end -- not yet done, pattern
+
+-- status info
+
+statistics.register("xml load time", function()
+ if noffiles > 0 or nofconverted > 0 then
+ return format("%s seconds, %s files, %s converted", statistics.elapsedtime(xml), noffiles, nofconverted)
+ else
+ return nil
+ end
+end)
+
+statistics.register("lxml preparation time", function()
+ local calls, cached = xml.lpathcalls(), xml.lpathcached()
+ if calls > 0 or cached > 0 then
+ return format("%s seconds, %s nodes, %s lpath calls, %s cached calls",
+ statistics.elapsedtime(lxml), nofindices, calls, cached)
+ else
+ return nil
+ end
+end)
+
+statistics.register("lxml lpath profile", function()
+ local p = xml.profiled
+ if p and next(p) then
+ local s = table.sortedkeys(p)
+ local tested, matched, finalized = 0, 0, 0
+ texio.write_nl("log","\nbegin of lxml profile\n")
+ texio.write_nl("log","\n tested matched finalized pattern\n\n")
+ for i=1,#s do
+ local pattern = s[i]
+ local pp = p[pattern]
+ local t, m, f = pp.tested, pp.matched, pp.finalized
+ tested, matched, finalized = tested + t, matched + m, finalized + f
+ texio.write_nl("log",format("%9i %9i %9i %s",t,m,f,pattern))
+ end
+ texio.write_nl("log","\nend of lxml profile\n")
+ return format("%s patterns, %s tested, %s matched, %s finalized (see log for details)",#s,tested,matched,finalized)
+ else
+ return nil
+ end
+end)
+
+-- misc
+
+function lxml.nonspace(id,pattern) -- slow, todo loop
+ xmltprint(xmlcollect(get_id(id),pattern,true))
+end
+
+function lxml.strip(id,pattern,nolines,anywhere)
+ xml.strip(get_id(id),pattern,nolines,anywhere)
+end
+
+function lxml.stripped(id,pattern,nolines)
+ local str = xmltext(get_id(id),pattern) or ""
+ str = gsub(str,"^%s*(.-)%s*$","%1")
+ if nolines then
+ str = gsub(str,"%s+"," ")
+ end
+ xmlsprint(str)
+end
+
+function lxml.delete(id,pattern)
+ xml.delete(get_id(id),pattern)
+end
diff --git a/tex/context/base/lxml-xml.lua b/tex/context/base/lxml-xml.lua
new file mode 100644
index 000000000..f791ec0f8
--- /dev/null
+++ b/tex/context/base/lxml-xml.lua
@@ -0,0 +1,288 @@
+if not modules then modules = { } end modules ['lxml-xml'] = {
+ version = 1.001,
+ comment = "this module is the basis for the lxml-* ones",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+
+local function first(collected) -- wrong ?
+ return collected and collected[1]
+end
+
+local function last(collected)
+ return collected and collected[#collected]
+end
+
+local function all(collected)
+ return collected
+end
+
+local function reverse(collected)
+ if collected then
+ local reversed = { }
+ for c=#collected,1,-1 do
+ reversed[#reversed+1] = collected[c]
+ end
+ return reversed
+ end
+end
+
+local function attribute(collected,name)
+ if collected and #collected > 0 then
+ local at = collected[1].at
+ return at and at[name]
+ end
+end
+
+local function att(id,name)
+ local at = id.at
+ return at and at[name]
+end
+
+local function count(collected)
+ return (collected and #collected) or 0
+end
+
+local function position(collected,n)
+ if collected then
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[#collected + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
+ end
+ end
+end
+
+local function match(collected)
+ return (collected and collected[1].mi) or 0 -- match
+end
+
+local function index(collected)
+ if collected then
+ return collected[1].ni
+ end
+end
+
+local function attributes(collected,arguments)
+ if collected then
+ local at = collected[1].at
+ if arguments then
+ return at[arguments]
+ elseif next(at) then
+ return at -- all of them
+ end
+ end
+end
+
+local function chainattribute(collected,arguments) -- todo: optional levels
+ if collected then
+ local e = collected[1]
+ while e do
+ local at = e.at
+ if at then
+ local a = at[arguments]
+ if a then
+ return a
+ end
+ else
+ break -- error
+ end
+ e = e.__p__
+ end
+ end
+ return ""
+end
+
+local function raw(collected) -- hybrid
+ if collected then
+ local e = collected[1] or collected
+ return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ else
+ return ""
+ end
+end
+
+local function text(collected) -- hybrid
+ if collected then
+ local e = collected[1] or collected
+ return (e and xmltostring(e.dt)) or ""
+ else
+ return ""
+ end
+end
+
+local function texts(collected)
+ if collected then
+ local t = { }
+ for c=1,#collected do
+ local e = collection[c]
+ if e and e.dt then
+ t[#t+1] = e.dt
+ end
+ end
+ return t
+ end
+end
+
+local function tag(collected,n)
+ if collected then
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[#collected-n+1]
+ end
+ return c and c.tg
+ end
+end
+
+local function name(collected,n)
+ if collected then
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[#collected-n+1]
+ end
+ if c then
+ if c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
+ end
+ end
+ end
+end
+
+local function tags(collected,nonamespace)
+ if collected then
+ local t = { }
+ for c=1,#collected do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ if nonamespace or ns == "" then
+ t[#t+1] = tg
+ else
+ t[#t+1] = ns .. ":" .. tg
+ end
+ end
+ return t
+ end
+end
+
+local function empty(collected)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then -- maybe an extra tester for spacing only
+ return false
+ end
+ elseif n > 1 then
+ return false
+ end
+ end
+ end
+ end
+ end
+ return true
+end
+
+finalizers.first = first
+finalizers.last = last
+finalizers.all = all
+finalizers.reverse = reverse
+finalizers.elements = all
+finalizers.default = all
+finalizers.attribute = attribute
+finalizers.att = att
+finalizers.count = count
+finalizers.position = position
+finalizers.match = match
+finalizers.index = index
+finalizers.attributes = attributes
+finalizers.chainattribute = chainattribute
+finalizers.text = text
+finalizers.texts = texts
+finalizers.tag = tag
+finalizers.name = name
+finalizers.tags = tags
+finalizers.empty = empty
+
+-- shortcuts -- we could support xmlfilter(id,pattern,first)
+
+function xml.first(id,pattern)
+ return first(xmlfilter(id,pattern))
+end
+
+function xml.last(id,pattern)
+ return last(xmlfilter(id,pattern))
+end
+
+function xml.count(id,pattern)
+ return count(xmlfilter(id,pattern))
+end
+
+function xml.attribute(id,pattern,a,default)
+ return attribute(xmlfilter(id,pattern),a,default)
+end
+
+function xml.raw(id,pattern)
+ if pattern then
+ return raw(xmlfilter(id,pattern))
+ else
+ return raw(id)
+ end
+end
+
+function xml.text(id,pattern)
+ if pattern then
+ -- return text(xmlfilter(id,pattern))
+ local collected = xmlfilter(id,pattern)
+ return (collected and xmltostring(collected[1].dt)) or ""
+ elseif id then
+ -- return text(id)
+ return xmltostring(id.dt) or ""
+ else
+ return ""
+ end
+end
+
+xml.content = text
+
+function xml.position(id,pattern,n) -- element
+ return position(xmlfilter(id,pattern),n)
+end
+
+function xml.match(id,pattern) -- number
+ return match(xmlfilter(id,pattern))
+end
+
+function xml.empty(id,pattern)
+ return empty(xmlfilter(id,pattern))
+end
+
+xml.all = xml.filter
+xml.index = xml.position
+xml.found = xml.filter
diff --git a/tex/context/base/m-arabtex.tex b/tex/context/base/m-arabtex.tex
new file mode 100644
index 000000000..61e56e93a
--- /dev/null
+++ b/tex/context/base/m-arabtex.tex
@@ -0,0 +1,450 @@
+%D \module
+%D [ file=m-arabtex, % was font-arb,
+%D version=2003.02.22, % 1999.11.06,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Arabic,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% I still need to hook in some features into the setup
+% macro. I also have to (re)define farsi etc. in ways
+% similar to arab, so that we have dedicated environments.
+%
+% keywords needed: vocalize transscribe
+%
+% \startarabic[option=vocalize] % or vocalize=yes
+% ......
+% \stoparabic
+
+\writestatus{loading}{ConTeXt Font Macros / ArabTeX support}
+
+%D At the \NTG\ 10\high{th} anniversary meeting Klaus Lagally
+%D introduced the audience to arabic typesetting, and after
+%D that I knew that some day I really had to look into his
+%D generic package. And then, sort of simultaniously Maarten
+%D Wisse and Imran Ahsan Nyazee asked me if \CONTEXT\ could
+%D support \ARABTEX, a package that provides right to left
+%D typesetting of (several variants of) arab and hebrew.
+%D Having implemented support for chinese a few weeks before,
+%D I could not resist to build in support for arab and hebrew
+%D too. Writing support for languages that don't give me any
+%D cue on how to pronounce their script, is kind of special.
+
+%D This is a beta version, since I still have to take care of some
+%D macros that conflict with existing stuff.
+
+\unprotect
+
+\definesystemvariable{ARABTEX}
+
+\def\setupARABTEX
+ {\getparameters[\??ARABTEX]}
+
+\setupARABTEX
+ [\s!rscale=1.2,
+ \c!before=,
+ \c!after=,
+ \c!inner=\setarab,
+ \c!style=\setarabicfont\fontstylesuffix]
+
+%D A few (maybe too) simple hooks into the font mechanism. The
+%D hook into the language module is not yet done.
+
+% \unexpanded\def\setarabicfont#1% rscale
+% {\scratchdimen\@@ARABTEXrscale\bodyfontsize
+% \font\arbfont\truefontname{Arabic#1} at \currentfontscale\scratchdimen
+% \setx@skels
+% \newfonttrue
+% \arbfont}
+%
+% more modern
+%
+% \unexpanded\def\setarabicfont#1% rscale
+% {\definefont[arbfont][Arabic#1 sa \@@ARABTEXrscale]%
+% \setx@skels
+% \newfonttrue
+% \arbfont}
+%
+% more efficient
+
+\unexpanded\def\setarabicfont#1%
+ {\setx@skels
+ \newfonttrue
+ \definedfont[Arabic#1 sa \ARABTEXparameter\s!rscale]}
+
+%D Just to be compatible with Arab\TEX\ we define:
+
+\unexpanded\def\nash {\setarabicfont\s!Regular}
+\unexpanded\def\nashbf {\setarabicfont\s!Bold }
+\unexpanded\def\pnash {\setarabicfont\s!Regular}
+\unexpanded\def\pnashbf{\setarabicfont\s!Bold }
+\unexpanded\def\xnash {\setarabicfont\s!Regular}
+\unexpanded\def\xnashbf{\setarabicfont\s!Bold }
+
+%D The display arabic environment (will be an installable
+%D object) uses a few conditionals. Let's do it the
+%D \CONTEXT\ way and define an anvironment that we later can
+%D adapt.
+
+\newif\if@ignore
+\newif\if@endpe
+
+\def\setupARABTEXalternative[#1]%
+ {\dodoubleempty\getparameters[\??ARABTEX#1]}
+
+\def\defineARABTEXalternative
+ {\dodoubleempty\dodefineARABTEXalternative}
+
+\def\dodefineARABTEXalternative[#1][#2]%
+ {\iffirstargument % \startarab is defined but used already
+ \getparameters
+ [\??ARABTEX#1]
+ [\c!before=\@@ARABTEXbefore,
+ \c!after=\@@ARABTEXafter,
+ \c!inner=\@@ARABTEXinner,
+ \c!style=\@@ARABTEXstyle,
+ \s!rscale=\@@ARABTEXrscale,
+ #2]%
+ \setvalue {\e!start#1}{\displayARABTEXalternative{#1}}%
+ \unexpanded\setvalue{#1}{\inlineARABTEXalternative {#1}}%
+ \unexpanded\def\RL{\getvalue{#1}}%
+ \unexpanded\def\LR{\a@LR}%
+ \let\R=\RL
+ \let\L=\LR
+ \expandafter\all@wcmd\csname\e!stop#1\endcsname
+ \else
+ \defineARABTEXalternative[arabic]%
+ \fi}
+
+\def\initializeARABTEXinternals
+ {\ARABTEXparameter\c!inner
+ \the\everyARABTEXpreset}
+
+\newtoks \everyARABTEXpreset
+
+\let\currentARABTEXalternative\empty
+
+\def\ARABTEXparameter#1%
+ {\csname\??ARABTEX\currentARABTEXalternative#1\endcsname}
+
+\def\inlineARABTEXalternative#1#2%
+ {\bgroup
+ \edef\currentARABTEXalternative{#1}%
+ \initializeARABTEXinternals
+ \a@RL{#2}%
+ \egroup}
+
+\def\displayARABTEXalternative#1%
+ {\dodoubleempty\dostartARABTEXalternative[#1]}
+
+\def\dostartARABTEXalternative[#1][#2]%
+ {\begingroup
+ \edef\currentARABTEXalternative{#1}%
+ \getparameters[\??ARABTEX\currentARABTEXalternative][#2]%
+ \ifnum1<0\ARABTEXparameter\c!n\relax
+ \startcolumns
+ \else
+ \ARABTEXparameter\c!before
+ \fi
+ \initializeARABTEXinternals
+ \initializeARABTEXend
+ \arabtext
+ \initializeARABTEXalternative}
+
+\def\initializeARABTEXalternative
+ {\ARABTEXparameter\c!style}
+
+\def\initializeARABTEXend% \CONTEXT\ does use \end quite differently
+ {\long\def\end##1%
+ {\endarabtext
+ \ifnum1<0\ARABTEXparameter\c!n\relax
+ \stopcolumns
+ \else
+ \ARABTEXparameter\c!after
+ \fi
+ \endgroup}%
+ \let\a@l@end\end
+ \letvalue{\e!stop\currentARABTEXalternative}=\end
+ \long\def\end##1%
+ {\endarabtext
+ \endgroup
+ \if@ignore\global\@ignorefalse\expandafter\ignorespaces\fi}}
+
+%D Arabic verbatim.
+
+\def\typearab{\a@@verb}
+
+%D Some \LATEX\ macros.
+
+\def \makeatletter{\unprotect}
+\def \makeatother {\protect}
+\def \typeout {\writestatus{arabtex}}
+
+%D We have to save some macros.
+
+\let\ARABTEXversion=\empty
+
+\def\startloadingARABTEX% ugly hacks
+ {\catcode`!=12
+ \catcode`?=12
+ \pushmacro\output \let \output \scratchtoks
+ \pushmacro\LaTeX \let \LaTeX \undefined
+ \pushmacro\CJK \let \CJK \undefined
+% \pushmacro\peek@token \let \peek@token \undefined
+% \pushmacro\edmacloaded \let \edmacloaded \undefined
+ \pushmacro\year \let \year \normalyear
+ \pushmacro\month \let \month \normalmonth
+ \pushmacro\day \let \day \normalday
+ \pushmacro\input \def \input ##1 {\normalinput ##1 }
+ \pushmacro\linewidth
+ \pushmacro\datum \def\datum {\toks0}
+ \pushmacro\version \def\version {\toks2}
+ \pushmacro\theversion \let\theversion \ARABTEXversion
+ \pushmacro\emphasize
+ \pushmacro\cap}
+
+\def\stoploadingARABTEX
+ {\catcode`!=11
+ \catcode`?=11
+ \popmacro\cap
+ \popmacro\emphasize
+ \popmacro\theversion
+ \popmacro\version
+ \popmacro\datum
+ \popmacro\linewidth
+ \popmacro\input
+ \popmacro\day
+ \popmacro\month
+ \popmacro\year
+% \popmacro\edmacloaded
+% \popmacro\peek@token
+ \popmacro\CJK
+ \popmacro\LaTeX
+ \popmacro\output}
+
+%D We save some macros:
+
+\startloadingARABTEX
+
+%D When loading \ARABTEX\ we have to set back the~! and~?.
+
+\input arabtex.sty
+
+%D Since \ARABTEX\ has its own \type {\cap}, we save the
+%D new meaning. We also redefine some \PLAIN\ macros, which
+%D happen to have a different meaning in \LATEX.
+
+\let\ARABTEXversion\theversion
+\let\ARABTEXcap \cap
+
+\appendtoks
+ \let\cap\ARABTEXcap
+\to \everyARABTEXpreset
+
+\def\ARABTEXsh@ft#1%
+ {\dimen@.00#1ex
+ \multiply\dimen@\slantperpoint
+ \kern-.0156\dimen@}
+
+\appendtoks
+ \let\sh@ft\ARABTEXsh@ft
+\to \everyARABTEXpreset
+
+\def\ARABTEXd#1%
+ {{\o@lign{\relax#1\crcr\hidewidth\sh@ft{10}%
+ .\hidewidth}}}
+
+\def\ARABTEXb#1%
+ {{\o@lign{\relax#1\crcr\hidewidth\sh@ft{29}%
+ \vbox to.2ex{\hbox{\char22}\vss}\hidewidth}}}
+
+\appendtoks
+ \let\b\ARABTEXb
+ \let\d\ARABTEXd
+\to \everyARABTEXpreset
+
+\def \ARABTEXbreakA {\hfill\break}
+\def \ARABTEXbreakB {\break}
+\edef\ARABTEXbar {\string|}
+\def \ARABTEXcomma {\relax\ifmmode\mskip\thinmuskip\else\thinspace\fi}
+
+\appendtoks
+ \let\\=\ARABTEXbreakA
+ \let\|=\ARABTEXbreakB
+ \let |=\ARABTEXbar
+ \let\,=\ARABTEXcomma
+\to \everyARABTEXpreset
+
+\let\ARABTEXprotect\relax
+
+\appendtoks
+ \let\protect\ARABTEXprotect
+\to \everyARABTEXpreset
+
+%D Now we can pop the saved macros.
+
+\stoploadingARABTEX
+
+%D Ah, we have to get rid of some \type {\protect} stuff but
+%D to permit testing we add it in the \CONTEXT\ way.
+
+% \bgroup
+% \catcode`\<=\@other
+% \unexpanded\gdef\a@ins
+% {\ifmmode
+% \expandafter<%
+% \else
+% \dontleavehmode \bgroup
+% \arab@codes \set@arabfont \@waslafalse \@wasfalse
+% \expandafter\arab@insert
+% \fi}
+% \unexpanded\gdef\<{\a@ins}
+% \catcode`\<=\active
+% \global\let<=\a@ins
+% \egroup
+%
+% cleaner:
+
+\defineactivecharacter < {\a@ins} \unexpanded\gdef\<{\a@ins}%
+
+\def\normal@a@ins
+ {\dontleavehmode % context prefers this instead of \leavevmode
+ \bgroup
+ \arab@codes
+ \set@arabfont
+ \@waslafalse
+ \@wasfalse
+ \arab@insert}
+
+\unexpanded\gdef\a@ins
+ {\mathortext<\normal@a@ins}
+
+%D We also need to register a few macros:
+
+\all@wcmd\initializeARABTEXalternative % no argument, internal command
+\all@wcmd\tx % no argument, small font
+\all@wcmd\txx % no argument, smaller font
+
+%D We also hook it into the presetter.
+
+\appendtoks
+ \let\normaltx \tx \def\tx {\normaltx \setarabicfont\fontstylesuffix}%
+ \let\normaltxx\txx\def\txx{\normaltxx\setarabicfont\fontstylesuffix}%
+\to \everyARABTEXpreset
+
+%D The main definitions are:
+
+\definefontsynonym [ArabicRegular] [xnsh14]
+\definefontsynonym [ArabicBold] [xnsh14bf]
+
+\defineARABTEXalternative
+ [arabic]
+ [\c!inner=\setarab,
+ \c!style=\setarabicfont\fontstylesuffix]
+
+\defineARABTEXalternative
+ [farsi]
+ [\c!inner=\setfarsi,
+ \c!style=\setarabicfont\fontstylesuffix]
+
+\defineARABTEXalternative
+ [urdu]
+ [\c!inner=\seturdu,
+ \c!style=\setarabicfont\fontstylesuffix]
+
+\defineARABTEXalternative
+ [maghribi]
+ [\c!inner=\setmaghribi,
+ \c!style=\setarabicfont\fontstylesuffix]
+
+%D Apart from such definitions, one can adapt the settings
+%D using \type {\setupARABTEXalternative}.
+%D
+%D A few years ago at the Holland Festivities, I attended {\em
+%D The Cave}, one of the most impressive combinations of music
+%D and video I know. This composition of Steve Reich (music)
+%D and .. (video) concentrates on the common grounds of arabs
+%D and jews: their ancestor Abram. Listening to the \CDROM's
+%D of {\em The Cave}, provided me the right ambiance for
+%D filling in the details of this module. In {\em The Cave},
+%D interviews, music, and |<|believe it or not|>| rhythmic
+%D typography are the cornerstones. Remembering those big
+%D screens, it strikes me that like music, \TEX\ too is a
+%D perfect instrument to cross cultural and linguistic
+%D borders. So, let's load Hebrew support as well:
+
+\unexpanded\def\sethebrewfont#1%
+ {\setx@skels
+ \newfonttrue
+ \definedfont[Hebrew#1 sa \ARABTEXparameter\s!rscale]}
+
+% \let \setheb \sethebrew
+
+\unexpanded\def\pheb {\sethebrewfont\s!Regular}
+\unexpanded\def\phebbf{\sethebrewfont\s!Bold}
+
+% \startloadingARABTEX
+
+% \ReadFile{hebtex.sty}
+% \ReadFile{apatch.sty}
+% \ReadFile{hepatch.sty}
+
+% \stoploadingARABTEX
+
+\definefontsynonym [HebrewRegular] [hclassic]
+\definefontsynonym [HebrewBold] [hcaption]
+
+\defineARABTEXalternative
+ [hebrew]
+ [\c!inner=\sethebrew,
+ \c!style=\sethebrewfont\fontstylesuffix]
+
+%D Now we're done:
+
+\protect \endinput
+
+% everyoutput : \charsubdefmax \arab@charsubdefmax
+
+% \defineconversion [abjad] [\abj@d]
+%
+% voetnoten verbatim lijsten indexen tabellen uitlijnen
+%
+% \v!hoofdstuk=al-fa.slu
+% \v!inhoud=al-mu.htawayAtu
+% \v!figuren=qA'imaTu al-.suwaru
+% \v!tabellen=qA'imaTu al-^gadAwilu
+% \v!grafieken=qA'imaTu al-rusUmu
+% \v!index=al-fihrisu
+% \v!bijlage=al-mul.haqu
+
+% \usemodule[arabtex]
+%
+% \usetypescript[postscript] \switchtotypeface[postscript]
+%
+% \setarab \novocalize
+%
+% \starttext
+%
+% \placecontent
+%
+% \section{\} % short arabic use \< .. >
+% \section{\} % short arabic use \< .. >
+%
+% \startarabic
+% mu.hammad 'i_d q"aAm zay"d" + i_d yaqUm zyd + A_d zyd q"aAm
+%
+% mu.hammad 'i_d q"aAm zay"d" + i_d yaqUm zyd + A_d zyd q"aAm
+% \stoparabic
+%
+% \section{\}
+%
+% \startarabic
+% mu.hammad 'i_d q"aAm zay"d" + i_d yaqUm zyd + A_d zyd q"aAm
+% \stoparabic
+%
+% \stoptext
diff --git a/tex/context/base/m-barcodes.mkiv b/tex/context/base/m-barcodes.mkiv
new file mode 100644
index 000000000..b0eae1485
--- /dev/null
+++ b/tex/context/base/m-barcodes.mkiv
@@ -0,0 +1,122 @@
+%D \module
+%D [ file=m-pstricks,
+%D version=2010.03.14,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Barcodes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% \startTEXpage
+% \startPSTRICKS
+% \pspicture(-4mm,-1mm)(38mm,26mm)
+% \psbarcode{9781860742712}{includetext guardwhitespace}{ean13}%
+% \endpspicture
+% \stopPSTRICKS
+% \stopTEXpage
+
+% 978-94-90688-01-1
+%
+% 978 = ean isbn identifier (979 also)
+% 94 = country code
+% 90688 = publisher code
+% 01 = title 1
+% 1 = checksum
+
+\usemodule[pstricks]
+
+\usePSTRICKSmodule[pst-barcode]
+
+\definefont[barcodefont][file:ocrb10]
+% \definefont[barcodefont][file:texgyreheros-regular]
+
+\startluacode
+plugins.barcodes = { }
+
+local function split(code)
+ local t = { string.byte(code,1,#code) }
+ if #t >= 12 then
+ local s = 0
+ for i=1,11,2 do
+ s = s + (t[i]-48)
+ end
+ for i=2,12,2 do
+ s = s + 3 * (t[i]-48)
+ end
+ local m = s % 10
+ local c = (m > 0 and (10 - m)) or 0
+ return t, s, m, c
+ end
+end
+
+function plugins.barcodes.isbn_1(original)
+ local code = string.gsub(original,"%-","")
+ local t, s, m, c = split(code)
+ if t then
+ if #t == 13 then
+ local e = ((c == t[13] - 48) and "correct") or "wrong"
+ logs.report("isbn code","code=%s, sum=%s, checksum=%s, modulo=%s, status=%s",original,s,m,c,e)
+ else
+ logs.report("isbn code","code=%s, sum=%s, checksum=%s, modulo=%s",original,s,m,c)
+ code= code .. c
+ end
+ end
+ tex.sprint(code)
+end
+
+function plugins.barcodes.isbn_2(original)
+ local code = string.gsub(original,"%-","")
+ local t, s, m, c = split(code)
+ if t and #t == 12 then
+ original = original .. "-" .. c
+ end
+ tex.sprint(original)
+end
+\stopluacode
+
+\startsetups barcode:isbn
+ \scale
+ [width=5cm]
+ {
+ \vbox {
+ \hbox {
+ \hskip3.7mm
+ \scale[width=34mm]{\barcodefont ISBN \ctxlua{plugins.barcodes.isbn_2("\getvariable{barcode}{code}")}}
+ }
+ \par
+ \normalexpanded { \noexpand \setPSTRICKS {
+ \noexpand \pspicture(-4mm,-1mm)(38mm,26mm)
+ \noexpand \psbarcode {
+ \ctxlua{plugins.barcodes.isbn_1("\getvariable{barcode}{code}")}
+ } {
+ includetext guardwhitespace
+ } {
+ ean13
+ }
+ \noexpand \endpspicture
+ }
+ \noexpand \processPSTRICKS }
+ }
+ }
+\stopsetups
+
+\def\barcode[#1]%
+ {\bgroup
+ \setvariables[barcode][type=isbn,#1]%
+ \directsetup{barcode:\getvariable{barcode}{type}}%
+ \egroup}
+
+% \usemodule[barcodes]
+%
+% \starttext
+% \startTEXpage
+% \barcode[type=isbn,code=978-94-90688-01-1]
+% \stopTEXpage
+% \stoptext
+
+\endinput
+
diff --git a/tex/context/base/m-chart.mkii b/tex/context/base/m-chart.mkii
new file mode 100644
index 000000000..2554fa2d4
--- /dev/null
+++ b/tex/context/base/m-chart.mkii
@@ -0,0 +1,48 @@
+%D \module
+%D [ file=m-chart,
+%D version=1998.10.10,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Flow Charts,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 \XML\ interface:
+
+\unprotect
+
+\startXMLdefinitions flowchart
+
+\defineXMLargument [flowchartdefinition]
+ {\defineFLOWchart[\XMLpar{flowchartdefinition}{identifier}{unknown}]}
+
+\defineXMLpickup [flowcell]
+ {\startFLOWcell
+ \defineXMLargument[name]{\unspaceafter\name}%
+ \defineXMLargument[shape]{\unspaceafter\shape}%
+ \defineXMLnestedargument[text]{\text}}
+ {\stopFLOWcell}
+
+\defineXMLenvironment [location] % global unspace/store
+ {\bgroup\defineXMLpush[x]\defineXMLpush[y]}
+ {\XMLunspace{x}\XMLunspace{y}%
+ \expanded{\egroup\noexpand\location{\XMLpop{x},\XMLpop{y}}}}
+
+\defineXMLenvironment [connection]
+ {\bgroup\defineXMLpush[type]\defineXMLpush[name]}%
+ {\XMLunspace{type}\XMLunspace{name}%
+ \expanded{\egroup\noexpand\connection[\XMLpop{type}]{\XMLpop{name}}}}
+
+\defineXMLsingular [flowchart]
+ {\expanded{\FLOWchart[\XMLpar{flowchart}{identifier}{unknown}]}}
+
+\defineXMLdirective [flowchart] [shapes] \setupFLOWshapes
+\defineXMLdirective [flowchart] [lines] \setupFLOWlines
+
+\stopXMLdefinitions
+
+\protect \endinput
diff --git a/tex/context/base/m-chart.mkiv b/tex/context/base/m-chart.mkiv
new file mode 100644
index 000000000..4c008a5ee
--- /dev/null
+++ b/tex/context/base/m-chart.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=m-chart,
+%D version=1998.10.10,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Flow Charts,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 \XML\ interface:
+
+\unprotect
+
+\writestatus\m!systems{The chart mkiv xml interface is not yet defined!}
+
+\protect \endinput
diff --git a/tex/context/base/m-chart.tex b/tex/context/base/m-chart.tex
new file mode 100644
index 000000000..5ccf4c2ad
--- /dev/null
+++ b/tex/context/base/m-chart.tex
@@ -0,0 +1,1285 @@
+%D \module
+%D [ file=m-chart,
+%D version=1998.10.10,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Flow Charts,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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: \localpushmacro/\localpopmacro (dohandleflowchart etc)
+% todo: make mkiv variant
+% todo: use dimexpr/numspr
+
+% will be redone with layers and dimexpr or even better, by just using
+% textext .. a nice example of old code
+
+%D This is an experimental module. Pieces of code will be moved
+%D to other modules. More features are possible but will be
+%D interfaces later.
+%D
+%D When finished this module will be documented. The main macro
+%D is still a rather big one and there is some redundant and
+%D slow code that needs a clean up.
+
+% arrow, dash
+% crossing
+% \goto -> \normalgoto
+% class -> class:name (ref prefix)
+% c, automatisch geen overlap zoeken
+% eind eerder chart connecties
+% relateren aan korps
+% check op bestaan naam, bestaan shape
+% auto als extern figuur
+% subchart
+% pijlen
+% focus
+% ook nog \MPmessage
+% areapath -> krappe vlak
+% clippath -> gehele vlak
+%
+% offset : clip offset
+% breedte : breedte cel
+% hoogte : hoogte cel
+% dx : halve afstand in breedte (grid breedte = breedte + 2dx)
+% dy : halve afstand in hoogte (grid hoogte = hoogte + 2dy)
+% x : x offset (clipping)
+% y : y offset (clipping)
+% nx : minimaal aantal cellen horizontaal
+% ny : minimaal aantal cellen vertikaal
+%
+% shape none en geen equivalent maken
+%
+% kaderkleur achtergrondkleur
+% lijnkleur lijndikte
+% focus focuskaderkleur focusachtergrondkleur
+% richting
+%
+% focus koppelen aan kleur
+
+\unprotect
+
+\definesorting [flowchart] [flowcharts] [\v!none] % no access
+\setupsorting [flowchart] [\c!state=\v!stop] % off by default
+
+\def\@FLOW@{@FLOW@}
+\def\@FLOC@{@FLOC@}
+\def\@FLOX@{@FLOX@}
+
+\def\@@FLOW{@@FLOW}
+\def\@@FLOL{@@FLOL}
+\def\@@FLOS{@@FLOS}
+\def\@@FLOF{@@FLOF}
+\def\@@FLOT{@@FLOT}
+\def\@@FLOX{@@FLOX}
+
+\def\@@MPx {@@MPx}
+\def\@@MPy {@@MPy}
+
+\def\FLOWbufferprefix{flw-}
+
+\def\processFLOWbuffer#1{\getbuffer[\FLOWbufferprefix#1]}
+\def\typeFLOWbuffer #1{\typebuffer[\FLOWbufferprefix#1]}
+
+\def\setFLOWname#1#2% funny hack that makes sure that we get
+ {\bgroup % names that are acceptable for METAPOST
+ \lccode`0=`a\lccode`1=`b\lccode`2=`c\lccode`3=`d\lccode`4=`e%
+ \lccode`5=`f\lccode`6=`g\lccode`7=`h\lccode`8=`i\lccode`9=`j%
+ \lccode` =`\_\lccode`-=`\_\lccode`_=`\_%
+ \lowercase{\gdef#1{#2}}%
+ \egroup}
+
+% een gobble als default is sneller, en dan alleen setten als
+% nodig
+
+\def\resetFLOWcell
+ {% variables
+ \global\let\FLOWname \empty
+ \global\let\FLOWalign \empty
+ \global\let\FLOWshape \empty
+ \global\let\FLOWlocation \empty
+ \global\let\FLOWtext \empty
+ \global\let\FLOWhelp \empty
+ \global\let\FLOWdestination\empty
+ \global\let\FLOWoverlay \empty
+ \global\let\FLOWfocus \empty
+ \global\let\tFLOWlabel \empty
+ \global\let\bFLOWlabel \empty
+ \global\let\lFLOWlabel \empty
+ \global\let\rFLOWlabel \empty
+ \global\let\bcFLOWlabel \empty
+ \global\let\tcFLOWlabel \empty
+ \global\let\lcFLOWlabel \empty
+ \global\let\rcFLOWlabel \empty
+ \global\let\tFLOWexit \empty
+ \global\let\bFLOWexit \empty
+ \global\let\lFLOWexit \empty
+ \global\let\rFLOWexit \empty
+ % commands
+ \let\name \doFLOWname
+ \let\shape \doFLOWshape
+ \let\destination\doFLOWdestination
+ \let\location \doFLOWlocation
+ \let\focus \doFLOWfocus
+ \let\overlay \doFLOWoverlay
+ \let\figure \doFLOWfigure
+ \let\text \doFLOWtext
+ \let\comment \doFLOWcomment
+ \let\label \doFLOWlabel
+ \let\help \doFLOWhelp
+ \let\connection \doFLOWconnection
+ \let\exit \doFLOWexit
+ % convenience commands
+ \let\locate \doFLOWlocate
+ \let\connect \doFLOWconnect}
+
+\let\FLOWcell \s!unknown
+\let\FLOWshape \s!unknown
+\let\FLOWdestination\s!unknown
+\let\FLOWfocus \s!unknown
+\let\FLOWoverlay \empty
+\let\FLOWtext \empty
+
+\def\doFLOWname#1%
+ {\def\FLOWcell{#1}\setFLOWname\FLOWname{name_#1}\ignorespaces}
+
+\def\doFLOWshape#1%
+ {\gdef\FLOWshape{#1}\ignorespaces}
+
+\def\doFLOWdestination#1%
+ {\gdef\FLOWdestination{#1}\ignorespaces}
+
+\def\doFLOWlocation#1%
+ {\setFLOWlocation#1\end\ignorespaces}
+
+\def\doFLOWfocus#1%
+ {\gdef\FLOWfocus{#1}\ignorespaces}
+
+\def\doFLOWoverlay#1%
+ {\gdef\FLOWoverlay{#1}\ignorespaces}
+
+\def\doFLOWfigure#1%
+ {\defineoverlay[\s!dummy][\overlayfigure{#1}]%
+ \overlay\s!dummy}
+
+\def\doFLOWtext
+ {\dosingleempty\dodoFLOWtext}
+
+\def\dodoFLOWtext[#1]% % #2%
+ {\gdef\FLOWalign{#1}\gdef\FLOWtext}% {#2}}
+
+\def\doFLOWcomment[#1]#2%
+ {\ignorespaces\dogobblesingleempty}
+
+\def\doFLOWlabel[#1]#2% wordt dit gebruikt ?
+ {\setgvalue{#1FLOWlabel}{#2}\ignorespaces}
+
+\def\doFLOWhelp#1%
+ {\gdef\FLOWhelp{#1}\ignorespaces}
+
+\def\doFLOWconnection
+ {\dodoubleempty\dodoFLOWconnection}
+
+\def\dodoFLOWconnection[#1][#2]#3%
+ {\ignorespaces}
+
+\def\doFLOWconnect
+ {\connection}
+
+\def\doFLOWlocate
+ {\location}
+
+\def\doFLOWexit[#1]#2%
+ {\setgvalue{#1FLOWexit}{#2}\ignorespaces}
+
+\def\startFLOWchart
+ {\bgroup
+ \let\stopFLOWchart\egroup
+ \obeylines % lelijk, buffers nog eens fatsoeneren
+ \dodoubleempty\dostartFLOWchart}
+
+\def\dostartFLOWchart[#1][#2]%
+ {\preparenextFLOWchart{#1}{#2}%
+ \dostartbuffer[\FLOWbufferprefix\nofFLOWcharts][startFLOWchart][stopFLOWchart]}
+
+\def\defineFLOWchart%
+ {\dodoubleempty\dodefineFLOWchart}
+
+\long\def\dodefineFLOWchart[#1][#2]#3%
+ {\preparenextFLOWchart{#1}{#2}%
+ \setbuffer[\FLOWbufferprefix\nofFLOWcharts]#3\endbuffer}
+
+\def\preparenextFLOWchart#1#2%
+ {\doglobal\increment\nofFLOWcharts
+ \flowchart{#1}%
+ \setxvalue{\@FLOW@-#1}{\noexpand\dohandleflowchart[\nofFLOWcharts][#2]}}
+
+\def\setupFLOWcharts{\dodoubleargument\getparameters[\@@FLOW]}
+\def\setupFLOWlines {\dodoubleargument\getparameters[\@@FLOL]}
+\def\setupFLOWshapes{\dodoubleargument\getparameters[\@@FLOS]}
+\def\setupFLOWfocus {\dodoubleargument\getparameters[\@@FLOF]}
+\def\setupFLOWsets {\dodoubleargument\getparameters[\@@FLOX]}
+
+\setupFLOWcharts
+ [\c!option=,
+ \c!bodyfont=,
+ \c!dot=, % private option
+ \c!width=12\bodyfontsize,
+ \c!height=7\bodyfontsize,
+ \c!maxwidth=,
+ \c!maxheight=,
+ \c!offset=\v!standard, % == auto offset
+ \c!dx=2\bodyfontsize,
+ \c!dy=2\bodyfontsize,
+ \c!nx=0, % 1,
+ \c!ny=0, % 1,
+ \c!x=1,
+ \c!y=1,
+ \c!autofocus=,
+ \c!focus=,
+ \c!background=, % \v!color,
+ \c!backgroundcolor=\s!white,
+ \c!rulethickness=\linewidth,
+ \c!frame=\v!off,
+ \c!framecolor=]
+
+\setupFLOWlines
+ [\c!corner=\v!round,
+ \c!arrow=\v!yes,
+ \c!dash=\v!no,
+ \c!radius=.375\bodyfontsize, % 2.5\c!rulethickness
+ \c!color=FLOWlinecolor,
+ \c!rulethickness=.15\bodyfontsize, % 2pt,
+ \c!offset=\v!none]
+
+\setupFLOWshapes
+ [\c!default=action,
+ \c!framecolor=FLOWframecolor,
+ \c!background=\v!color,
+ \c!backgroundcolor=FLOWbackgroundcolor,
+ \c!backgroundscreen=\@@rsscreen,
+ \c!rulethickness=.15\bodyfontsize, % 2pt,
+ \c!offset=.5\bodyfontsize]
+
+\setupFLOWfocus
+ [\c!framecolor=FLOWfocuscolor,
+ \c!background=\@@FLOSbackground,
+ \c!backgroundcolor=\@@FLOSbackgroundcolor,
+ \c!backgroundscreen=\@@FLOSbackgroundscreen,
+ \c!rulethickness=\@@FLOSrulethickness,
+ \c!offset=\@@FLOSoffset]
+
+\definecolor [FLOWfocuscolor] [s=.2]
+\definecolor [FLOWlinecolor] [s=.5]
+\definecolor [FLOWframecolor] [s=.7]
+\definecolor [FLOWbackgroundcolor] [s=.9]
+
+\newcounter\includeFLOWx
+\newcounter\includeFLOWy
+
+\def\includeFLOWchart
+ {\dodoubleempty\doincludeFLOWchart}
+
+\def\doincludeFLOWchart[#1][#2]%
+ {\pushmacro\includeFLOWx
+ \pushmacro\includeFLOWy
+ \getparameters[FLOWi][x=1,y=1,#2]%
+ \increment(\includeFLOWx,0\FLOWix)\decrement\includeFLOWx
+ \increment(\includeFLOWy,0\FLOWiy)\decrement\includeFLOWy
+ \def\dodoincludeFLOWchart##1%
+ {\doifdefined{\@FLOW@-##1}
+ {\globalpushmacro\dohandleflowchart % was local
+ \gdef\dohandleflowchart[####1][####2]%
+ {\globalpopmacro\dohandleflowchart % was local
+ \resetFLOWlocation
+ \processFLOWbuffer{####1}}%
+ \getvalue{\@FLOW@-##1}}}%
+ \processcommalist[#1]\dodoincludeFLOWchart
+ \popmacro\includeFLOWx
+ \popmacro\includeFLOWy}
+
+\def\resetFLOWlocation
+ {\globallet\lastFLOWx\!!zerocount
+ \globallet\lastFLOWy\!!zerocount}
+
+\def\dosetFLOWlocation[#1#2]#3#4%
+ {\processaction
+ [#1#2]
+ [ +=>\scratchcounter\numexpr#4+ 1+#3\relax,
+ -=>\scratchcounter\numexpr#4- 1+#3\relax,
+ +#2=>\scratchcounter\numexpr#4+#2+#3\relax,
+ -#2=>\scratchcounter\numexpr#4-#2+#3\relax,
+ \s!default=>\scratchcounter\numexpr#4 +#3\relax,
+ \s!unknown=>\scratchcounter\numexpr0#1#2+#3\relax]%
+ \xdef#4{\the\scratchcounter}}
+
+\def\setFLOWlocation#1,#2\end
+ {\dosetFLOWlocation[#1\empty]\includeFLOWx\lastFLOWx
+ \dosetFLOWlocation[#2\empty]\includeFLOWy\lastFLOWy
+ \xdef\FLOWlocation{\lastFLOWx,\lastFLOWy}}
+
+\def\FLOWshapes
+ {node, action, procedure, product, decision, archive,
+ loop, wait, subprocedure, singledocument, multidocument,
+ sub procedure, single document, multi document, up, down,
+ left, right}
+
+\def\FLOWlines
+ {up, down, left, right}
+
+\def\FLOWsetconnect#1%
+ {\donefalse
+ \let\cFLOWfrom\empty
+ \let\cFLOWto\empty
+ \let\zFLOWfrom\!!zerocount
+ \let\zFLOWto\!!zerocount
+ \handletokens#1\with\doFLOWsetconnect
+ \ifx\cFLOWto\empty\let\cFLOWfrom\empty\fi}
+
+\def\doFLOWsetconnect#1%
+ {\ifx #1p%
+ \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
+ \else\ifx#1+%
+ \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
+ \else\ifx#1n%
+ \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
+ \else\ifx#1-%
+ \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
+ \else\ifdone
+ \edef\cFLOWto{\FLOWconnector#1}%
+ \else
+ \edef\cFLOWfrom{\FLOWconnector#1}%
+ \donetrue
+ \fi\fi\fi\fi\fi}
+
+\def\FLOWconnector#1%
+ {\if#1bbottom\else\if#1ttop\else\if#1lleft\else\if#1rright\fi\fi\fi\fi}
+
+\newif\ifFLOWscaling \FLOWscalingtrue
+
+\def\@@FLOW@@offset{\@@FLOWoffset}
+
+\def\getFLOWchart
+ {\dodoubleempty\dogetFLOWchart}
+
+\def\dogetFLOWchart[#1][#2]%
+ {\doifundefinedelse{\@FLOW@-#1}
+ {\writestatus{FLOW}{unknown chart #1}%
+ \framed
+ [\c!width=12\bodyfontsize,\c!height=8\bodyfontsize]
+ {\tttf [chart #1]}}
+ {\dodogetFLOWchart[#1][#2]}}
+
+\def\dodogetFLOWchart[#1][#2]% to be split a bit more
+ {\vbox\bgroup
+ \insidefloattrue
+ \forgetall
+ \dontcomplain
+ % \offinterlineskip % we now explicitly use \nointerlineskip later on
+ \def\dohandleflowchart[##1][##2]%
+ {\def\currentFLOWnumber{##1}%
+ \getparameters[\@@FLOW][##2]}%
+ \getvalue{\@FLOW@-#1}%
+ \getparameters[\@@FLOW][#2]% dubbelop ?
+ \doifsomething{\@@FLOWautofocus}
+ {\checkFLOWautofocus}%
+ %\message{AUTOSHAPE 3: (\@@FLOWx,\@@FLOWy)->(\@@FLOWnx,\@@FLOWny)}\wait
+ \global\let\FLOWwidth \@@FLOWnx
+ \global\let\FLOWheight\@@FLOWny
+ \let\startFLOWcell\startFLOWcellA
+ \resetFLOWlocation
+ \processFLOWbuffer\currentFLOWnumber
+ \ifcase\@@FLOWnx\relax \let\@@FLOWnx\FLOWwidth \fi
+ \ifcase\@@FLOWny\relax \let\@@FLOWny\FLOWheight \fi
+ \doifnothing{\@@FLOWmaxwidth\@@FLOWmaxheight}{\FLOWscalingfalse}%
+ \ifFLOWscaling
+ \doifnothing{\@@FLOWmaxwidth }{\let\@@FLOWmaxwidth \maxdimen}%
+ \doifnothing{\@@FLOWmaxheight}{\let\@@FLOWmaxheight\maxdimen}%
+ \scratchcounter\bodyfontpoints
+ \doloop % NOG FONTSWITCH OM EX EN EM TE LATEN WERKEN
+ {\ifnum\scratchcounter>1 % NU DIMENSIONS IN TERMS OF BODYFONTSIZE
+ \bodyfontsize=\the\scratchcounter pt
+ \dimen0=\@@FLOWmaxwidth
+ \dimen2=\@@FLOWwidth
+ \dimen4=\@@FLOWdx
+ \advance\dimen2 2\dimen4
+ \dimen2=\@@FLOWnx\dimen2
+ \advance\dimen2 2\dimen4
+ \ifdim\dimen2>\dimen0
+ \advance\scratchcounter \minusone
+ \else
+ \dimen0=\@@FLOWmaxheight
+ \dimen2=\@@FLOWheight
+ \dimen4=\@@FLOWdy
+ \advance\dimen2 2\dimen4
+ \dimen2=\@@FLOWny\dimen2
+ \advance\dimen2 2\dimen4
+ \ifdim\dimen2>\dimen0
+ \advance\scratchcounter \minusone
+ \else
+ \exitloop
+ \fi
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \expanded{\switchtobodyfont[\the\scratchcounter pt]}%
+ \forgetall
+ % \offinterlineskip % needed ?
+ \else\ifx\@@FLOWbodyfont\empty\else
+ \expanded{\switchtobodyfont[\@@FLOWbodyfont]}% \expanded ?
+ \fi\fi
+ \global\let\FLOWcells\empty
+ \dimen0=\@@FLOWwidth
+ \edef\FLOWshapewidth{\the\dimen0}%
+ \dimen2=\@@FLOWdx
+ \advance\dimen0 2\dimen2
+ \edef\FLOWgridwidth{\the\dimen0}%
+ \dimen0=\@@FLOWheight
+ \edef\FLOWshapeheight{\the\dimen0}%
+ \dimen2=\@@FLOWdy
+ \advance\dimen0 2\dimen2
+ \edef\FLOWgridheight{\the\dimen0}%
+ \scratchdimen=\@@FLOSrulethickness
+ \edef\@@FLOSrulethickness{\the\scratchdimen}%
+ \scratchdimen=\@@FLOFrulethickness
+ \edef\@@FLOFrulethickness{\the\scratchdimen}%
+ \scratchdimen=\@@FLOLrulethickness
+ \edef\@@FLOLrulethickness{\the\scratchdimen}%
+ \ifdim\@@FLOLradius<2.5\scratchdimen
+ \scratchdimen=2.5\scratchdimen
+ \edef\@@FLOLradius{\the\scratchdimen}%
+ \ifdim\@@FLOLradius>\@@FLOWdx
+ \scratchdimen=\@@FLOWdx
+ \edef\@@FLOLradius{\the\scratchdimen}%
+ \fi
+ \ifdim\@@FLOLradius>\@@FLOWdy
+ \scratchdimen=\@@FLOWdy
+ \edef\@@FLOLradius{\the\scratchdimen}%
+ \fi
+ \else
+ \scratchdimen=\@@FLOLradius
+ \edef\@@FLOLradius{\the\scratchdimen}%
+ \fi
+ \processaction % magic 2.5
+ [\@@FLOWoffset]
+ [ \v!none=>\scratchdimen=-2.5\scratchdimen,
+ \v!overlay=>\scratchdimen=-2.5\scratchdimen,
+ \v!standard=>\scratchdimen=\scratchdimen,
+ \s!unknown=>\scratchdimen=\@@FLOWoffset,
+ \s!default=>\scratchdimen=-2.5\scratchdimen]%
+ \edef\@@FLOW@@offset{\the\scratchdimen}%
+ \forgetall
+ \offinterlineskip
+ \resetMPdrawing
+ \doglobal\newcounter\FLOWcomment
+ \startMPdrawing
+ if unknown context_char : input mp-char.mp ; fi ;
+ grid_width := \FLOWgridwidth ;
+ grid_height := \FLOWgridheight ;
+ shape_width := \FLOWshapewidth ;
+ shape_height := \FLOWshapeheight ;
+ connection_line_width := \@@FLOLrulethickness ;
+ connection_smooth_size := \@@FLOLradius ;
+ connection_arrow_size := \@@FLOLradius ;
+ connection_dash_size := \@@FLOLradius ;
+ currentpicture := nullpicture ;
+ begin_chart(0,\FLOWwidth,\FLOWheight);
+ reverse_y := true ;
+ chart_offset := \@@FLOW@@offset ;
+ \stopMPdrawing
+ \doifelsenothing\@@FLOWbackgroundcolor
+ {\startMPdrawing
+ chart_background_color := white ;
+ \stopMPdrawing}
+ {\startMPdrawing
+ chart_background_color := \MPcolor{\@@FLOWbackgroundcolor} ;
+ \stopMPdrawing}%
+ \doif\@@FLOWoption\v!test
+ {\startMPdrawing
+ show_con_points := true ;
+ show_mid_points := true ;
+ show_all_points := true ;
+ \stopMPdrawing}%
+ \processaction % private
+ [\@@FLOWdot]
+ [ \v!yes=>\startMPdrawing
+ show_con_points := true ;
+ show_mid_points := true ;
+ show_all_points := true ;
+ \stopMPdrawing,
+ \s!unknown=>\startMPdrawing
+ show_\@@FLOWdot_points := true ;
+ \stopMPdrawing]%
+\doglobal\newcounter\FLOWcomment
+ \let\startFLOWcell\startFLOWcellB
+ \resetFLOWlocation
+ \processFLOWbuffer\currentFLOWnumber
+\doglobal\newcounter\FLOWcomment
+ \let\startFLOWcell\startFLOWcellC
+ \resetFLOWlocation
+ \processFLOWbuffer\currentFLOWnumber
+ \startMPdrawing
+ clip_chart(\@@FLOWx,\@@FLOWy,\@@FLOWnx,\@@FLOWny) ;
+ end_chart ;
+ \stopMPdrawing
+ \MPdrawingdonetrue
+ \setbox0\hbox
+ {\MPstaticgraphictrue
+ \MPshiftdrawingfalse
+ \getMPdrawing}%
+ \def\MPmessage##1%
+ {\writestatus{MP charts}{##1}}%
+ \def\MPposition##1##2##3%
+ {\setvalue{\@@MPx##1}{##2}\setvalue{\@@MPy##1}{##3}}%
+ \def\MPclippath##1##2##3##4%
+ {\def\clipMPllx{##1bp}\def\clipMPlly{##2bp}%
+ \def\clipMPurx{##3bp}\def\clipMPury{##4bp}}%
+ \def\MPareapath##1##2##3##4%
+ {\def\areaMPllx{##1bp}\def\areaMPlly{##2bp}%
+ \def\areaMPurx{##3bp}\def\areaMPury{##4bp}}%
+ \getMPdata
+ \doglobal\newcounter\FLOWcomment
+ \let\startFLOWcell\startFLOWcellD
+ \setbox2\vbox to \ht0
+ {\forgetall % \offinterlineskip
+ \resetFLOWlocation
+ \processFLOWbuffer\currentFLOWnumber\vss}%
+ \setbox2\hbox
+ {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box2}%
+ \wd2\wd0\ht2\ht0\dp2\dp0
+ \let\startFLOWcell\startFLOWcellE
+ \setbox4\vbox to \ht0
+ {\forgetall % \offinterlineskip
+ \resetFLOWlocation
+ \processFLOWbuffer\currentFLOWnumber\vss}%
+ \setbox4\hbox
+ {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box4}%
+ \wd4\wd0\ht4\ht0\dp4\dp0
+ \doifelse\@@FLOWoption\v!test
+ {\setbox6\vbox
+ {\forgetall
+ \vskip\@@FLOW@@offset
+ \hskip\@@FLOW@@offset
+ \basegrid
+ [\c!x=\@@FLOWx,\c!nx=\@@FLOWnx,\c!dx=\withoutpt\FLOWgridwidth,
+ \c!y=\@@FLOWy,\c!ny=\@@FLOWny,\c!dy=\withoutpt\FLOWgridheight,
+ \c!xstep=1,\c!ystep=1,
+ \c!unit=pt,\c!location=\v!middle]}%
+ \wd6\wd0\ht6\ht0\dp6\dp0
+ \setbox8\vbox
+ {\forgetall
+ \offinterlineskip
+ \vskip\@@FLOW@@offset
+ \dostepwiserecurse\@@FLOWy\@@FLOWny\plusone
+ {\vbox to \FLOWgridheight
+ {\vfill
+ \hskip\@@FLOW@@offset
+ \hbox
+ {\dostepwiserecurse\@@FLOWx\@@FLOWnx\plusone
+ {\hbox to \FLOWgridwidth
+ {\hfill
+ \framed
+ [\c!framecolor=red,
+ \c!width=\FLOWshapewidth,
+ \c!height=\FLOWshapeheight]
+ {}%
+ \hfill}}}
+ \vfill}}}%
+ \wd8\wd0\ht8\ht0\dp8\dp0
+ \framed
+ [\c!offset=\v!overlay,\c!framecolor=green]
+ {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2\hskip-\wd6\box6\hskip-\wd8\box8}}}
+ {\framed
+ [\c!offset=\v!overlay,
+ \c!frame=\@@FLOWframe,
+ \c!rulethickness=\@@FLOWrulethickness,
+ \c!framecolor=\@@FLOWframecolor,
+ \c!background=\@@FLOWbackground,
+ \c!backgroundcolor=\@@FLOWbackgroundcolor]
+ {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2}}}%
+ %\message{[\FLOWcells]}\wait
+ \egroup}
+
+% Pass A
+
+\long\def\startFLOWcellA#1\stopFLOWcell%
+ {\resetFLOWcell
+ \ignorespaces#1\unskip
+ \expandafter\getFLOWlocationA\FLOWlocation\end
+ \ignorespaces}
+
+\def\getFLOWlocationA#1,#2\end
+ {\ifnum0#1>\FLOWwidth \xdef\FLOWwidth {#1}\fi
+ \ifnum0#2>\FLOWheight\xdef\FLOWheight{#2}\fi}
+
+% Pass B
+%
+% beware: the - after \@FLOC@ is needed since name can be
+% empty and we don't want to redefine \@FLOC@ itself by
+% mistake
+
+\long\def\startFLOWcellB#1\stopFLOWcell
+ {\resetFLOWcell\ignorespaces#1\unskip
+ \setxvalue{\@FLOC@-\FLOWname}{\FLOWlocation}% kost veel cs's
+ \ifx\FLOWshape\empty
+ \global\let\FLOWshape\@@FLOSdefault
+ \fi
+ \doifnot\FLOWshape{none} % {\v!none}
+ {\ExpandBothAfter\doifinsetelse{\FLOWshape}{\FLOWshapes}
+ {\edef\FLOWshapetag{shape_\FLOWshape}% beter \expanded
+ \@EA\setFLOWname\@EA\FLOWshapetag\@EA{\FLOWshapetag}}
+ {\doifnumberelse\FLOWshape
+ {\let\FLOWshapetag\FLOWshape}
+ {\let\FLOWshapetag\empty}}%
+ \ifx\FLOWshapetag\empty \else
+ \ExpandBothAfter\doifinsetelse{\FLOWshape}{\FLOWlines}
+ {\chardef\FLOWstate0 }
+ {\ExpandBothAfter\doifcommonelse{\FLOWcell,\FLOWfocus}{\@@FLOWfocus}
+ {\chardef\FLOWstate1 }
+ {\chardef\FLOWstate2 }}%
+ \startMPdrawing
+ begin_sub_chart ;
+ \ifcase\FLOWstate
+ shape_line_color := \MPcolor{\@@FLOLcolor} ;
+ shape_fill_color := \MPcolor{\@@FLOLcolor} ;
+ shape_line_width := \@@FLOLrulethickness ;
+ \or
+ shape_line_color := \MPcolor{\@@FLOFframecolor} ;
+ shape_fill_color := \MPcolor{\@@FLOFbackgroundcolor} ;
+ shape_line_width := \@@FLOFrulethickness ;
+ \or
+ shape_line_color := \MPcolor{\@@FLOSframecolor} ;
+ shape_fill_color := \MPcolor{\@@FLOSbackgroundcolor} ;
+ shape_line_width := \@@FLOSrulethickness ;
+ \fi
+ %\ifx\FLOWoverlay\empty
+ % peepshape := false ;
+ %\else
+ % peepshape := true ;
+ %\fi
+ peepshape := \ifx\FLOWoverlay\empty false \else true \fi ;
+ new_shape(\FLOWlocation,\FLOWshapetag) ;
+ end_sub_chart ;
+ \stopMPdrawing
+ \fi}%
+ \ignorespaces}
+
+% Pass C
+
+\long\def\startFLOWcellC#1\stopFLOWcell%
+ {\resetFLOWcell
+\pushmacro\lastFLOWx
+\pushmacro\lastFLOWy
+ \ignorespaces#1\unskip % makes sure that vars are set
+\popmacro\lastFLOWy
+\popmacro\lastFLOWx
+ \let\connection\doFLOWconnectionC
+ \ignorespaces#1\unskip}
+
+\def\FLOWorigin{0,0}
+
+\def\doFLOWdisplace[#1,#2,#3]% experiment
+ {dsp_x := #1 ; dsp_y := #2 ;}
+
+\def\doFLOWconnectionC
+ {\dodoubleempty\dodoFLOWconnectionC}
+
+\def\dodoFLOWconnectionC[#1][#2]#3%
+ {\doglobal\increment\FLOWcomment
+ \setFLOWname\otherFLOWname{name_#3}%
+ \doifdefinedelse{\@FLOC@-\FLOWname}
+ {\edef\FLOWfrom{\getvalue{\@FLOC@-\FLOWname}}}
+ {\let \FLOWfrom \FLOWorigin}%
+ \ifx\FLOWfrom\FLOWorigin \else
+ \doifdefinedelse{\@FLOC@-\otherFLOWname}
+ {\edef\FLOWto {\getvalue{\@FLOC@-\otherFLOWname}}}
+ {\let \FLOWto \FLOWorigin}%
+ \ifx\FLOWto\FLOWorigin \else
+ \FLOWsetconnect{#1}%
+ \ifx\cFLOWfrom\empty \else
+ \doifelse\@@FLOLcorner\v!round
+ {\startMPdrawing smooth := true ; \stopMPdrawing}
+ {\startMPdrawing smooth := false ; \stopMPdrawing}%
+ \doifelse\@@FLOLdash\v!yes
+ {\startMPdrawing dashline := true ; \stopMPdrawing}
+ {\startMPdrawing dashline := false ; \stopMPdrawing}%
+ \doifelse\@@FLOLarrow\v!yes
+ {\startMPdrawing arrowtip := true ; \stopMPdrawing}
+ {\startMPdrawing arrowtip := false ; \stopMPdrawing}%
+ \doifelse\@@FLOLoffset\v!none
+ {\startMPdrawing touchshape := true ; \stopMPdrawing}
+ {\startMPdrawing touchshape := false ; \stopMPdrawing}%
+%\doifsomething{#2}
+% {\startMPdrawing
+% \doFLOWdisplace[0#2,0,0]%
+% \stopMPdrawing}%
+ \startMPdrawing
+\doFLOWdisplace[0#2,0,0]%
+ connection_line_color := \MPcolor{\@@FLOLcolor} ;
+ connection_line_width := \@@FLOLrulethickness ;
+ connect_\cFLOWfrom_\cFLOWto (\FLOWfrom,\zFLOWfrom) (\FLOWto,\zFLOWto) ;
+\doFLOWdisplace[0,0,0]%
+ \stopMPdrawing
+ \fi
+ \fi
+ \fi
+ \ignorespaces}
+
+% Pass D
+
+\long\def\startFLOWcellD#1\stopFLOWcell
+ {\resetFLOWcell
+\pushmacro\lastFLOWx
+\pushmacro\lastFLOWy
+ \ignorespaces#1\unskip % presets vars
+\popmacro\lastFLOWy
+\popmacro\lastFLOWx
+ \let\doprocessFLOWcell\doprocessFLOWcellD
+ \expandafter\doprocessFLOWcellD\FLOWlocation\end
+ \let\connection\doFLOWconnectionD
+ \let\comment\doFLOWcommentD
+ \ignorespaces#1\unskip\ignorespaces}
+
+\def\doFLOWconnectionD
+ {\dodoubleempty\dodoFLOWconnectionD}
+
+\def\dodoFLOWconnectionD[#1][#2]#3%
+ {\doglobal\increment\FLOWcomment
+ \ignorespaces}
+
+\def\doFLOWcommentD[#1]#2%
+ {\bgroup
+ \let\FLOW \middlebox
+ \let\FLOWb \bottombox
+ \let\FLOWbl\bottomleftbox
+ \let\FLOWbr\bottomrightbox
+ \let\FLOWt \topbox
+ \let\FLOWtl\topleftbox
+ \let\FLOWtr\toprightbox
+ \let\FLOWl \leftbox
+ \let\FLOWlt\lefttopbox
+ \let\FLOWlb\leftbottombox
+ \let\FLOWr \rightbox
+ \let\FLOWrt\righttopbox
+ \let\FLOWrb\rightbottombox
+ \let\FLOWc \middlebox
+%\ifdefined{FLOW#1}%
+ \ifcase0\getvalue{\@@MPx\FLOWcomment}\getvalue{\@@MPy\FLOWcomment}\relax
+ \else
+ \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp<\areaMPllx\relax\else
+ \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp>\areaMPurx\relax\else
+ \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp<\areaMPlly\relax\else
+ \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp>\areaMPury\relax\else
+ \dimen0=\getvalue{\@@MPx\FLOWcomment}\s!bp
+ \advance\dimen0 -\@@FLOW@@offset
+ \advance\dimen0 -\clipMPllx
+ \dimen2=\clipMPury
+ \advance\dimen2 -\@@FLOW@@offset
+ \advance\dimen2 -\getvalue{\@@MPy\FLOWcomment}\s!bp
+ \setbox\scratchbox\hbox{\strut#2}%
+ \boxoffset.5\bodyfontsize
+ \setbox\scratchbox\hbox{\hskip\dimen0\lower\dimen2\getvalue{FLOW#1}{\box\scratchbox}}%
+ \smashbox\scratchbox
+ \box\scratchbox
+ \boxoffset\zeropoint
+ \nointerlineskip % really needed
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+%\fi
+ \egroup
+ \ignorespaces}
+
+% pass D
+
+\def\dophaseoneFLOWcellX#1#2%
+ {\!!counta#1\relax
+ \!!countb#2\relax
+ \!!countc\@@FLOWx
+ \!!countd\@@FLOWy
+ \advance\!!countc \@@FLOWnx
+ \advance\!!countd \@@FLOWny
+ \advance\!!countc \minusone
+ \advance\!!countd \minusone
+ \ifnum\!!counta<\@@FLOWx\relax \donefalse
+ \else\ifnum\!!counta>\!!countc \donefalse
+ \else\ifnum\!!countb<\@@FLOWy\relax \donefalse
+ \else\ifnum\!!countb>\!!countd \donefalse
+ \else \donetrue
+ \fi\fi\fi\fi}
+
+\def\dophasetwoFLOWcellX
+ {\advance\!!counta -\@@FLOWx
+ \advance\!!counta \plusone
+ \advance\!!countb -\@@FLOWy
+ \advance\!!countb \plusone
+ \dimen0=\FLOWgridwidth
+ \dimen0=\!!counta\dimen0
+ \advance\dimen0 -\FLOWgridwidth
+ \dimen4=\FLOWgridwidth
+ \advance\dimen4 -\FLOWshapewidth
+ \advance\dimen0 .5\dimen4
+ \dimen2=\FLOWgridheight
+ \dimen2=\!!countb\dimen2
+ \dimen4=\FLOWgridheight
+ \advance\dimen4 -\FLOWshapeheight
+ \advance\dimen2 -.5\dimen4
+ \edef\FLOWdx{\the\dimen0}%
+ \edef\FLOWdy{\the\dimen2}}
+
+\def\positionFLOWzero% assumes \FLOWdx and \FLOWdy are set
+ {\setbox0\hbox{\hskip\FLOWdx\lower\FLOWdy\box0}%
+ \smashbox0\box0
+ \nointerlineskip} % new, needed since we somehow reset that
+
+\def\doFLOWtlabel#1#2#3%
+ {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
+ \setbox0\hbox{\hskip\dimen2\raise\scratchdimen
+ \hbox{\raise\dimen4\hbox{#1{\strut#3}}}}%
+ \positionFLOWzero}%
+
+\def\doFLOWblabel#1#2#3%
+ {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
+ \setbox0\hbox{\hskip\dimen2\raise-\scratchdimen
+ \hbox{#1{\strut#3}}}%
+ \positionFLOWzero}%
+
+\def\doFLOWllabel#1#2#3%
+ {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
+ \setbox0\hbox{\hskip-\scratchdimen\raise\dimen6
+ \hbox{#1{\strut#3}}}%
+ \positionFLOWzero}%
+
+\def\doFLOWrlabel#1#2#3%
+ {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
+ \setbox0\hbox{\hskip\dimen0\hskip\scratchdimen
+ \hbox{\raise\dimen6\hbox{#1{\strut#3}}}}%
+ \positionFLOWzero}
+
+\def\doprocessFLOWcellD#1,#2\end
+ {\dophaseoneFLOWcellX{#1}{#2}%
+ \ifdone
+ \dophasetwoFLOWcellX
+ \doglobal\addtocommalist\FLOWcell\FLOWcells
+ \def\FLOWx{#1}%
+ \def\FLOWy{#2}%
+ \directsetup{flowcell}%
+ \setbox0\hbox
+ {\ifx\FLOWalign\empty\else
+ \setupframed
+ [\c!align=\v!normal,\c!bottom=\vfill,\c!top=\vfill]%
+ \@EA\processallactionsinset\@EA
+ [\FLOWalign]
+ [t=>{\setupframed[\c!bottom=\vfill,\c!top=]},
+ b=>{\setupframed[\c!bottom=,\c!top=\vfill]},
+ l=>{\setupframed[\c!align=\v!right]},
+ r=>{\setupframed[\c!align=\v!left]},
+ m=>{\setupframed[\c!align=\v!middle]},
+ c=>{\setupframed[\c!align=\v!middle]}]%
+ \fi
+ \doifelse\FLOWshape{none} % {\v!none}
+ {\setupframed[\c!offset=\v!overlay]}
+ {\setupframed[\c!offset=\@@FLOSoffset]}%
+ \framed
+ [\c!frame=\v!off,\c!background=flowcell,
+ \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
+ {\FLOWtext}}%
+ \showFLOWhelp0
+ \ifx\FLOWdestination\empty\else
+ \setbox0\hbox
+ {\setupinteraction[\c!color=,\c!contrastcolor=]%
+ \gotobox{\box0}[\FLOWdestination]}%
+ \fi
+ \positionFLOWzero
+ \dimen0=\FLOWshapewidth \dimen2=.5\dimen0
+ \dimen4=\FLOWshapeheight\dimen6=.5\dimen4
+ \boxoffset.5\bodyfontsize
+ \doFLOWtlabel \righttopbox0\tFLOWlabel
+ \doFLOWblabel\rightbottombox0\bFLOWlabel
+ \doFLOWllabel \lefttopbox0\lFLOWlabel
+ \doFLOWrlabel \righttopbox0\rFLOWlabel
+ \doFLOWtlabel \topbox0\tcFLOWlabel % for me only
+ \doFLOWblabel \bottombox0\bcFLOWlabel % for me only
+ \doFLOWllabel \leftbox0\lcFLOWlabel % for me only
+ \doFLOWrlabel \rightbox0\rcFLOWlabel % for me only
+ \ifnum#1=\@@FLOWx\relax \doFLOWllabel \leftbox1\lFLOWexit \fi
+ \ifnum#1=\!!countc \doFLOWrlabel \rightbox1\rFLOWexit \fi
+ \ifnum#2=\@@FLOWy\relax \doFLOWtlabel \topbox1\tFLOWexit \fi
+ \ifnum#2=\!!countd \doFLOWblabel \bottombox1\bFLOWexit \fi
+ \boxoffset\zeropoint
+ \fi}
+
+% For Willy Egger:
+%
+% \startsetups flowcell
+% \definelayer
+% [flowcell]
+% [width=\FLOWshapewidth,
+% height=\FLOWshapeheight]
+% \setlayerframed
+% [flowcell]
+% [preset=rightbottom,offset=1ex]
+% [frame=off]
+% {\tx(\FLOWx,\FLOWy)}
+% \stopsetups
+
+% Pass E
+
+\long\def\startFLOWcellE#1\stopFLOWcell
+ {\resetFLOWcell
+ \ignorespaces#1\unskip
+ \let\doprocessFLOWcell\doprocessFLOWcellE
+ \expandafter\doprocessFLOWcell\FLOWlocation\end}
+
+\def\doprocessFLOWcellE#1,#2\end % redundant
+ {\ifx\FLOWoverlay\empty \else
+ \dophaseoneFLOWcellX{#1}{#2}%
+ \ifdone
+ \dophasetwoFLOWcellX
+ \edef\FLOWdx{\the\dimen0}%
+ \edef\FLOWdy{\the\dimen2}%
+ \setbox0\hbox
+ {\framed
+ [%\c!frame=\v!off,
+ \c!background={\@@FLOWbackground,\FLOWoverlay},
+ \c!backgroundcolor=\@@FLOSbackgroundcolor,
+ \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
+ {}}%
+ \positionFLOWzero
+ \fi
+ \fi}
+
+% Pass F
+
+\def\checkFLOWautofocus
+ {\def\@@FLOWminx{100}\let\@@FLOWminy\@@FLOWminx
+ \def\@@FLOWmaxx {0}\let\@@FLOWmaxy\@@FLOWmaxx
+ \def\@@FLOWabsx {0}\let\@@FLOWabsy\@@FLOWabsx
+ \let\startFLOWcell\startFLOWcellF
+ \resetFLOWlocation
+ \processFLOWbuffer\currentFLOWnumber
+ %\message{AUTOSHAPE 1: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
+ \ifnum\@@FLOWabsx<\@@FLOWmaxx\let\@@FLOWmaxx\@@FLOWabsx\fi
+ \ifnum\@@FLOWabsy<\@@FLOWmaxy\let\@@FLOWmaxy\@@FLOWabsy\fi
+ %\message{AUTOSHAPE 2: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
+ \donetrue
+ \ifnum\@@FLOWminx=100 \donefalse\fi
+ \ifnum\@@FLOWminy=100 \donefalse\fi
+ \ifnum\@@FLOWmaxx=0 \donefalse\fi
+ \ifnum\@@FLOWmaxy=0 \donefalse\fi
+ \doFLOWcheckF\@@FLOWx\@@FLOWminx\@@FLOWmaxx\@@FLOWnx
+ \doFLOWcheckF\@@FLOWy\@@FLOWminy\@@FLOWmaxy\@@FLOWny}
+
+\def\startFLOWcellF#1\stopFLOWcell%
+ {\resetFLOWcell
+ \ignorespaces#1\unskip
+ \expandafter\doFLOWlocationF\FLOWlocation\end}%
+
+\def\doFLOWlocationF#1,#2\end%
+ {\ifnum#1>\@@FLOWabsx\def\@@FLOWabsx{#1}\fi
+ \ifnum#2>\@@FLOWabsy\def\@@FLOWabsy{#2}\fi
+ \ExpandBothAfter\doifinset{\FLOWcell}{\@@FLOWautofocus}
+ {\dodoFLOWlocationF{#1}<-\@@FLOWminx
+ \dodoFLOWlocationF{#1}>+\@@FLOWmaxx
+ \dodoFLOWlocationF{#2}<-\@@FLOWminy
+ \dodoFLOWlocationF{#2}>+\@@FLOWmaxy}}
+
+\def\dodoFLOWlocationF#1#2#3#4%
+ {\ifnum#1#2#4\relax
+ \!!counta=#1\advance\!!counta #31\relax
+ \edef#4{\ifnum\!!counta<1 1\else\the\!!counta\fi}%
+ \fi}
+
+\def\doFLOWcheckF#1#2#3#4%
+ {\ifdone
+ \let#1=#2%
+ \!!counta=#3%
+ \advance\!!counta \plusone\advance\!!counta -#2\relax
+ \ifnum\!!counta<1 \!!counta=1 \fi
+ \edef#4{\the\!!counta}%
+ \else
+ \let#1\!!plusone
+ \let#4\!!zerocount % no {1}
+ \fi}
+
+% \useFLOWchart[name][parent][setting,setting][additional settings]
+% \useFLOWchart[name][parent][additional settings]
+
+\let\currentFLOWchart\empty
+
+\def\useFLOWchart
+ {\doquadrupleempty\douseFLOWchart}
+
+\def\douseFLOWchart[#1][#2][#3][#4]% name parent sets mainsettings
+ {\iffourthargument
+ \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][#4,##1]}%
+ \else
+ \checkparameters[#3]%
+ \ifparameters
+ \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][][#3,##1]}%
+ \else
+ \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][##1]}%
+ \fi
+ \fi}
+
+\def\setgetFLOWchart[#1][#2][#3]%
+ {\def\docommand##1{}% cell line focus ?
+ \processcommalist[#2]\docommand
+ \getFLOWchart[#1][#3]}
+
+\def\doFLOWchart[#1][#2]%
+ {\hbox\bgroup\vbox\bgroup % vmode suppresses spaces
+\def\currentFLOWchart{#1}%
+ \doifundefinedelse{\@FLOW@--#1}
+ {\getFLOWchart[#1][#2]}
+ {\getvalue{\@FLOW@--#1}[#2]}%
+ \egroup\egroup}
+
+\def\FLOWchart%
+ {\dodoubleempty\doFLOWchart}
+
+%D A hook into the help system.
+
+\def\showFLOWhelp#1%
+ {\doifhelpinfo\FLOWhelp
+ {\setbox#1=\hbox
+ {\setbox\scratchbox=\hbox{\lower\@@FLOWdy\hbox
+ {\helpbutton
+ [\c!width=\wd0,\c!color=,\c!height=\@@FLOWdy,\c!frame=\v!no]%
+ [\FLOWhelp]}}%
+ \smashbox\scratchbox
+ \setbox#1=\vbox
+ {\forgetall\offinterlineskip\box#1\box\scratchbox}%
+ \box#1}}}
+
+%D The next section is dedicated to splitting up charts.
+
+\def\getFLOWsize[#1]%
+ {\bgroup\let\dodogetFLOWchart\dogetFLOWsize\FLOWchart[#1]\egroup}
+
+\def\dogetFLOWsize[#1][#2]%
+ {\setbox\scratchbox=\vbox
+ {\globallet\FLOWmaxwidth \!!zerocount
+ \globallet\FLOWmaxheight\!!zerocount
+ \def\getFLOWlocation##1,##2\end
+ {\ifnum0##1>\FLOWmaxwidth \xdef\FLOWmaxwidth {##1}\fi
+ \ifnum0##2>\FLOWmaxheight\xdef\FLOWmaxheight{##2}\fi}%
+ \resetFLOWcell
+ \long\def\startFLOWcell##1\stopFLOWcell
+ {{##1\expandafter\getFLOWlocation\FLOWlocation\end}}%
+ \def\dohandleflowchart[##1][##2]%
+ {\resetFLOWlocation
+ \processFLOWbuffer{##1}}%
+ \getvalue{\@FLOW@-#1}}}
+
+\def\setupFLOWsplit%
+ {\dodoubleargument\getparameters[\@@FLOT]}
+
+\setupFLOWsplit%
+ [\c!nx=3,\c!ny=3,
+ \c!dx=1,\c!dy=1,
+ \c!command=,
+ \c!marking=\v!on,
+ \c!before=,\c!after=]
+
+\def\FLOWsplitx {1}
+\def\FLOWsplity {1}
+\def\FLOWsplitnx{1}
+\def\FLOWsplitny{1}
+
+\def\FLOWcharts%
+ {\dodoubleempty\doFLOWcharts}
+
+%D While splitting, the following variables are available:
+%D
+%D \starttyping
+%D \FLOWsplitnx \FLOWsplitny \FLOWsplitx \FLOWsplity
+%D \stoptyping
+
+\def\doFLOWcharts[#1][#2]%
+ {\bgroup
+ \getFLOWsize[#1]%
+ \dodoFLOWcharts\relax
+ \global\let\FLOWsplitnx\FLOWsplitx
+ \global\let\FLOWsplitny\FLOWsplity
+ \dodoFLOWcharts{\dododoFLOWcharts[#1][#2]}%
+ \egroup}
+
+\def\dodoFLOWcharts#1%
+ {\def\@@FLOTx{1}%
+ \global\let\FLOWsplitx\@@FLOTx
+ \doloop
+ {\def\@@FLOTy{1}%
+ \global\let\FLOWsplity\@@FLOTy
+ \doloop
+ {\bgroup
+ \scratchcounter\FLOWmaxwidth
+ \advance\scratchcounter -\@@FLOTx
+ \advance\scratchcounter \plusone
+ \ifnum\scratchcounter<\@@FLOTnx\edef\@@FLOTnx{\the\scratchcounter}\fi
+ \scratchcounter\FLOWmaxheight
+ \advance\scratchcounter -\@@FLOTy
+ \advance\scratchcounter \plusone
+ \ifnum\scratchcounter<\@@FLOTny\edef\@@FLOTny{\the\scratchcounter}\fi
+ #1% does something with the float, or not
+ \egroup
+ \increment(\@@FLOTy,\@@FLOTny)%
+ \ifnum\@@FLOTy>\FLOWmaxheight
+ \exitloop
+ \else
+ \doglobal\increment\FLOWsplity
+ \decrement(\@@FLOTy,\@@FLOTdy)%
+ \fi}%
+ \increment(\@@FLOTx,\@@FLOTnx)%
+ \ifnum\@@FLOTx>\FLOWmaxwidth
+ \exitloop
+ \else
+ \doglobal\increment\FLOWsplitx
+ \decrement(\@@FLOTx,\@@FLOTdx)%
+ \fi}}
+
+\def\dododoFLOWcharts[#1][#2]%
+ {\bgroup
+ \@@FLOTbefore
+ \doifnot\@@FLOTmarking\v!on{\let\cuthbox\hbox}%
+ \cuthbox
+ {\@@FLOTcommand
+ {\FLOWchart[#1][#2,
+ \c!x=\@@FLOTx,\c!nx=\@@FLOTnx,
+ \c!y=\@@FLOTy,\c!ny=\@@FLOTny]}}%
+ \@@FLOTafter
+ \egroup}
+
+%D An example of splitting is given below:
+%D
+%D \starttyping
+%D \setupFLOWsplit
+%D [nx=5,ny=10,
+%D dx=0,dy=0,
+%D before=,
+%D after=\page]
+%D
+%D \FLOWcharts[mybigflow]
+%D \stoptyping
+%D
+%D Or, one can say:
+%D
+%D \starttyping
+%D \splitfloat
+%D {\placefigure{What a big flowchart this is!}}
+%D {\FLOWcharts[mybigflow]}
+%D \stoptyping
+
+%D \macros
+%D {typeFLOWchart}
+%D
+%D For documentation purposes the following macro is
+%D provided. Watch the use of the first and last line hooks,
+%D which is needed because the start and stop commands are
+%D not part of the buffer.
+
+\def\typeFLOWchart[#1]%
+ {\bgroup
+ \def\dohandleflowchart[##1][##2]{\typeFLOWbuffer{##1}}%
+ \defconvertedargument\firstverbatimfileline{\startFLOWchart[#1]}%
+ \defconvertedargument\lastverbatimfileline {\stopFLOWchart}%
+ \getvalue{\@FLOW@-#1}
+ \egroup}
+
+%D New:
+%D
+%D \starttyping
+%D \setupFLOWcharts[command=\Whow]
+%D
+%D \startFLOWset[convert-en] % [tag][convert-en]
+%D \subFLOWchart[a][x=1,y=1,nx=3,ny=3]
+%D \subFLOWchart[b][x=1,y=2,nx=3,ny=3]
+%D \subFLOWchart[c][x=2,y=1,nx=3,ny=3]
+%D \stopFLOWset
+%D
+%D \def\Whow#1%
+%D {\ifnum\currentFLOWset=1 \framed{Some Chart}\fi}
+%D
+%D \FLOWset[convert-en] % [tag]
+%D
+%D \def\Whow#1%
+%D {\setuphead[state=high]
+%D \startstandardmakeup
+%D \centerbox{#1}
+%D \stopstandardmakeup}
+%D
+%D \FLOWset[convert-en] % [tag]
+%D \stoptyping
+
+\def\startFLOWset
+ {\dodoubleempty\dostartFLOWset}
+
+\def\dostartFLOWset[#1][#2]#3\stopFLOWset % tag name data
+ {\ifsecondargument
+ \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#2}{#3}}%
+ \else
+ \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#1}{#3}}%
+ \fi}
+
+\long\def\dohandleFLOWset#1#2#3% tag name data
+ {\bgroup
+ \def\subFLOWchart
+ {\dodoubleempty\dosubFLOWchart}%
+ \def\dosubFLOWchart[##1][##2]% subtag settings
+ {\ifsecondargument
+ \dodohandleFLOWset{#1}{##1}{#2}{##2}%
+ \else
+ \subFLOWchart[][##1]%
+ \fi}%
+ #3%
+ \egroup}
+
+\def\dodohandleFLOWset#1#2#3#4% tag subtag name settings
+ {\increment\currentFLOWset
+ \bgroup
+ \@@FLOXcommand
+ {\ifnum\currentFLOWset=1 \pagereference[#1]\fi
+ \doifsomething{#2}
+ {\setupreferencing[\c!prefix=]%
+ \pagereference[#1:#2]% -:#1:#2
+ \setupreferencing[\c!prefix=#1:#2]}%
+ \FLOWchart[#3][#4]}%
+ \egroup}
+
+\def\FLOWset[#1]%
+ {\newcounter\currentFLOWset
+ \doifdefinedelse{\@FLOX@#1}
+ {\getvalue{\@FLOX@#1}}
+ {\dodohandleFLOWset{#1}{}{#1}{}}}
+
+\newcounter\currentFLOWset
+
+\setupFLOWsets
+ [\c!command=]
+
+%D This will be an option:
+
+% \def\startFLOWchart%
+% {\dodoubleempty\dostartFLOWchart}
+%
+% \long\def\dostartFLOWchart[#1][#2]#3\stopFLOWchart
+% {\preparenextFLOWchart{#1}{#2}%
+% \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
+%
+% \long\def\dodefineFLOWchart[#1][#2]#3%
+% {\preparenextFLOWchart{#1}{#2}%
+% \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
+%
+% \def\processFLOWbuffer#1{\getvalue{\FLOWbufferprefix#1}}
+% \def\typeFLOWbuffer #1{[Sorry, no verbatim chart #1 available.]}
+
+\loadmarkfile{m-chart}
+
+\protect \endinput
diff --git a/tex/context/base/m-chemic.mkii b/tex/context/base/m-chemic.mkii
new file mode 100644
index 000000000..e6980e1ff
--- /dev/null
+++ b/tex/context/base/m-chemic.mkii
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=ppchtex (m-chemic),
+%D version=1997.03.19,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\PPCHTEX\ (Plain Pictex Context cHemie \TEX),
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten},
+%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifx\psaxes\undefined \ifx\beginpicture\undefined
+ \usemodule[pictex]
+\fi \fi
+
+\input ppchtex.mkii \relax
+
+\endinput
diff --git a/tex/context/base/m-chemic.mkiv b/tex/context/base/m-chemic.mkiv
new file mode 100644
index 000000000..bd4cb093e
--- /dev/null
+++ b/tex/context/base/m-chemic.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=ppchtex (m-chemic),
+%D version=1997.03.19,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\PPCHTEX\ (Plain Pictex Context cHemie \TEX),
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten},
+%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}]
+%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{ppchtex}{not loaded as support for chemistry in now built in}
+
+% \usemodule[pictex] % we will get rid of this
+% \input ppchtex.mkiv \relax
+
+\endinput
diff --git a/tex/context/base/m-chemic.tex b/tex/context/base/m-chemic.tex
new file mode 100644
index 000000000..7bacf4a90
--- /dev/null
+++ b/tex/context/base/m-chemic.tex
@@ -0,0 +1,17 @@
+%D \module
+%D [ file=ppchtex (m-chemic),
+%D version=1997.03.19,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\PPCHTEX\ (Plain Pictex Context cHemie \TEX),
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten},
+%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\loadmarkfile{m-chemic}
+
+\endinput
diff --git a/tex/context/base/m-cweb.tex b/tex/context/base/m-cweb.tex
new file mode 100644
index 000000000..c416c9b36
--- /dev/null
+++ b/tex/context/base/m-cweb.tex
@@ -0,0 +1,1371 @@
+%D \module
+%D [ file=m-cweb,
+%D version=1997.01.15,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\CWEB\ Pretty Printing Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 First some auxiliary stuff, to be moved to system module.
+
+\def\dodofindfirstcharacter#1%
+ {\ifx#1\relax
+ \let\next=\egroup
+ \else
+ \handlecase
+ {\expandafter\ifnum\expandafter\catcode\expandafter`#1=11
+ \def\next##1\relax{\egroup\def\firstcharacter{#1}}%
+ \fi}%
+ \fi
+ \next}
+
+\def\dofindfirstcharacter#1#2%
+ {\def\firstcharacter{}%
+ \bgroup
+ \defconvertedargument\ascii{#2}%
+ \let\next\dodofindfirstcharacter
+ \let\handlecase#1%
+ \expandafter\next\ascii\relax}
+
+\def\normalcase#1%
+ {#1}
+
+\def\findfirstcharacter%
+ {\dofindfirstcharacter\lowercase}
+
+\def\FindFirstCharacter%
+ {\dofindfirstcharacter\normalcase}
+
+\def\FINDFIRSTCHARACTER%
+ {\dofindfirstcharacter\uppercase}
+
+% nog doen:
+%
+% \deactivateCWEB in output routine
+% status info
+% gelinkte entries
+% parskip en parindent
+
+%D \gdef\CWEBquote#1.{{\em Quote :}\ #1.} % checks the .
+
+%D This module (re)implements the \CWEB\ macros as defined in
+%D the file \type{cwebmac.tex}.
+%D
+%D \CWEB\ uses short, often one character long, names for
+%D macros. This is no real problem because no one is supposed
+%D to read and understand the files generated by \CWEB. The
+%D standard macros are meant for \PLAIN\ \TEX\ users. In
+%D \CONTEXT\ and other macro packages however, there is a
+%D potential conflict with format specific or user defined
+%D commands. Furthermore, the \CWEB\ macros implement their own
+%D output routines. When integrating \CWEB\ documents in
+%D another environment, the \CWEB\ specific macros have to be
+%D made local. The first part of this module is dedicated to
+%D this feature.
+%D
+%D Instead of using \type{\def} and \type{\let} for defining
+%D macros, we use:
+%D
+%D \starttyping
+%D \defCEBmacro arguments {meaning}
+%D \letCEBmacro arguments {meaning}
+%D \stoptyping
+%D
+%D \CWEB files contain implicit calls to macros that generate
+%D the table of contents, the lists of sections and the index.
+%D Because we want to be much more flexible, we implemented our
+%D own alternatives, and therefore have to bypass the original
+%D ones. The next macro is used for defining these obsolete
+%D \CWEB\ macros. The dummies take care of arguments.
+%D
+%D \starttyping
+%D \defCEBdummy arguments {meaning}
+%D \stoptyping
+%D
+%D The list of \CWEB\ specific macro names is saved in a
+%D \TOKENLIST. This serves two purposes. First it enables us to
+%D activate the \CWEB\ macros, which are saved under a
+%D different name, second it can be used to temporary restore
+%D the meanings, for instance when the output routine builds
+%D the page.
+
+\newtoks\CWEBmacros
+
+%D Activating and deactivating is done by means of:
+%D
+%D \starttyping
+%D \activateCWEB
+%D \deactivateCWEB
+%D \stoptyping
+%D
+%D Which are implemented as:
+
+\def\activateCWEB%
+ {\let\doCWEB=\activateCWEBmacro
+ \the\CWEBmacros}
+
+\def\deactivateCWEB%
+ {\let\doCWEB=\deactivateCWEBmacro
+ \the\CWEBmacros}
+
+%D The three definition macros append the name of the macro to
+%D the list. The first two macros save the meaning, the last one
+%D assigns \type{{}} to the macro and gobbles original meaning.
+
+\long\def\defCWEBmacro#1%
+ {\appendtoks\doCWEB#1\to\CWEBmacros
+ \setvalue{newCWEB\string#1}}
+
+\long\def\letCWEBmacro#1%
+ {\appendtoks\doCWEB#1\to\CWEBmacros
+ \letvalue{newCWEB\string#1}}
+
+\long\def\defCWEBdummy#1#2#%
+ {\appendtoks\doCWEB#1\to\CWEBmacros
+ \setvalue{newCWEB\string#1}#2{}%
+ \gobbleoneargument}
+
+%D The macro \type{\defCWEBdummy} of course takes care of the
+%D argument. This leaves the two (de|)|activating macros:
+
+\def\CWEBmacro#1%
+ {\getvalue{newCWEB\string#1}}
+
+\def\activateCWEBmacro#1%
+ {\letvalue{oldCWEB\string#1}=#1%
+ \def#1{\CWEBmacro#1}}
+
+\def\deactivateCWEBmacro#1%
+ {\expandafter\let\expandafter#1\expandafter=\csname oldCWEB\string#1\endcsname}
+
+%D I did consider loading the \CWEB\ macros using temporary
+%D substitutes of \type{\def}, \type{\font}, \type{\newbox} etc.
+%D The main problem is that the file contains more than
+%D definitions and taking all kind of assignments into account
+%D too would not make things easier. So I decided to stick to
+%D the method as just described.
+
+%D Now we're ready for the real job. What follows is a partial
+%D adaption of the file \type{cwebmac.tex}, version 3.1, dated
+%D September 1994 and written by Levy and Knuth. When possible
+%D we kept the original meaning, but we've granted ourselves
+%D the freedom to reformat the macro's for readibility.
+%D
+%D We'll only present the macros we actually use. The source
+%D however contains the original implementation.
+
+% standard macros for CWEB listings (in addition to plain.tex)
+% Version 3.1 --- September 1994.
+%
+% \ifx\documentstyle\undefined\else\endinput\fi % LaTeX will use other macros
+%
+% \xdef\fmtversion{\fmtversion+CWEB3.1}
+
+%D \macros{.}{}
+%D
+%D \CWEBquote preserve a way to get the dot accent (all
+%D other accents will still work as usual).
+
+\letCWEBmacro\: = \.
+
+% \parskip = 0pt % no stretch between paragraphs
+% \parindent = 1em % for paragraphs and for the first line of C text
+
+% \font\ninerm = cmr9
+% \let\mc = \ninerm % medium caps
+% \font\eightrm = cmr8
+% \let\sc = \eightrm % small caps (NOT a caps-and-small-caps font)
+% \let\mainfont = \tenrm
+% \let\cmntfont = \tenrm
+% \font\tenss = cmss10
+% \let\cmntfont = \tenss % alternative comment font
+% \font\titlefont = cmr7 scaled \magstep4 % title on the contents page
+% \font\ttitlefont = cmtt10 scaled \magstep2 % typewriter type in title
+% \font\tentex = cmtex10 % TeX extended character set (used in strings)
+% \fontextraspace\tentex = 0pt % no double space after sentences
+
+%D \macros{mc,sc,cmntfont,eightrm}{}
+%D
+%D The naming of the fonts in in line with those in \PLAIN\
+%D \TEX. Although \CONTEXT\ implements its own scheme, there is
+%D still support for the \PLAIN\ ones. We keep the original
+%D names, but change their meaning. That way the macros obey
+%D switching to other sizes or styles.
+
+\defCWEBmacro\mc {\tx}
+\defCWEBmacro\sc {\txx}
+\defCWEBmacro\cmntfont {\ss}
+\defCWEBmacro\eightrm {\tx}
+
+%D \macros{tentex,sevenrm,sevensy,teni}{}
+%D
+%D The next one uses a temporary solution. The \type{cmtex10}
+%D font is not part of the default mechanism. We make use of
+%D the \CONTEXT\ variables \type{\textface}, \type{\scriptface}
+%D and \type{\scriptscriptface}, which hold the current
+%D sizes.
+
+\defCWEBmacro\tentex%
+ {\font\next=cmtex10 at \textface
+ \fontextraspace\next\zeropoint
+ \next}
+
+\defCWEBmacro\sevenrm {\getvalue{\scriptface rmtf}}
+\defCWEBmacro\sevensy {\getvalue{\scriptface mmsy}}
+\defCWEBmacro\teni {\getvalue{\textface mmmi}}
+
+%D \macros{CWEBpt}{}
+%D
+%D The original macros are based on a 10~point bodyfont size. We
+%D therefore have to specify dimension in points a bit
+%D different. Specifications like .6pt are changed to
+%D \type{.06} times \type{\bodyfontsize}.
+
+\defCWEBmacro\CWEBpt {\bodyfontsize} % still dutch
+
+%D \macros{CEE,UNIX,TEX,CPLUSPLUS}{}
+%D
+%D Next come some logo's. It does not make much sense to use
+%D the \CONTEXT\ logo mechanism here, so we simply say:
+
+\defCWEBmacro \CEE/{{\mc C\spacefactor1000}}
+\defCWEBmacro \UNIX/{{\mc U\kern-.05emNIX\spacefactor1000}}
+\defCWEBmacro \TEX/{\TeX}
+\defCWEBmacro\CPLUSPLUS/{{\mc C\PP\spacefactor1000}}
+\defCWEBmacro \Cee{\CEE/} % for backward compatibility
+
+%D \macros{\ }{}
+%D
+%D Now we come to the real work: the short commands that make
+%D up the typography.
+%D
+%D \CWEBquote italic type for identifiers.
+
+\defCWEBmacro\\#1%
+ {\leavevmode\hbox{\it#1\/\kern.05em}}
+
+%D \macros{\string|}{}
+%D
+%D \CWEBquote one letter identifiers look better this way.
+
+\defCWEBmacro\|#1%
+ {\leavevmode\hbox{$#1$}}
+
+%D \macros{\string\&}{}
+%D
+%D \CWEBquote boldface type for reserved words.
+
+\defCWEBmacro\%
+ {\leavevmode
+ \hbox
+ {\def\_%
+ {\kern.04em
+ \vbox{\hrule width.3em height .06\CWEBpt}% .6pt}%
+ \kern.08em}%
+ \bf#1\/\kern.05em}}
+
+%D \macros{.}{}
+%D
+%D Here we use the previously saved period. This macro
+%D takes care of special characters in strings.
+
+\defCWEBmacro\.#1%
+ {\leavevmode
+ \hbox
+ {\tentex % typewriter type for strings
+ \let\\=\BS % backslash in a string
+ \let\{=\LB % left brace in a string
+ \let\}=\RB % right brace in a string
+ \let\~=\TL % tilde in a string
+ \let\ =\SP % space in a string
+ \let\_=\UL % underline in a string
+ \let\&=\AM % ampersand in a string
+ \let\^=\CF % circumflex in a string
+ #1\kern.05em}}
+
+%D \macros{)}{}
+%D
+%D Some discretionary hack.
+
+\defCWEBmacro\)%
+ {\discretionary{\hbox{\tentex\BS}}{}{}}
+
+%D \macros{AT}{}
+%D
+%D \CWEBquote at sign for control text (not needed in versions
+%D $>=$ 2.9).
+
+\defCWEBmacro\AT{@}
+
+%D \macros{ATL,postATL,NOATL}{}
+%D
+%D A two step macro that handles whatever.
+
+\defCWEBmacro\ATL%
+ {\par
+ \noindent
+ \bgroup
+ \catcode`\_=12
+ \postATL}
+
+\defCWEBmacro\postATL#1 #2 %
+ {\bf letter \\{\uppercase{\char"#1}} tangles as \tentex "#2"%
+ \egroup
+ \par}
+
+\defCWEBmacro\noATL#1 #2 %
+ {}
+
+%D \macros{noatl}{}
+%D
+%D \CWEBquote suppress output from \type{@l}.
+
+\defCWEBmacro\noatl%
+ {\let\ATL=\noATL}
+
+% \defCWEBmacro\ATH%
+% {\X\kern-.5em:Preprocessor definitions\X}
+
+%D \macros{PB}
+%D
+%D \CWEBquote hook for program brackets {\tttf\string|...\string|}
+%D in TeX part or section name.
+
+\defCWEBmacro\PB%
+ {\relax}
+
+% \chardef\AM = `\& % ampersand character in a string
+% \chardef\BS = `\\ % backslash in a string
+% \chardef\LB = `\{ % left brace in a string
+% \chardef\RB = `\} % right brace in a string
+% \chardef\TL = `\~ % tilde in a string
+% \chardef\UL = `\_ % underline character in a string
+% \chardef\CF = `\^ % circumflex character in a string
+
+\defCWEBmacro\AM {\char`\&} % ampersand character in a string
+\defCWEBmacro\BS {\char`\\} % backslash in a string
+\defCWEBmacro\LB {\char`\{} % left brace in a string
+\defCWEBmacro\RB {\char`\}} % right brace in a string
+\defCWEBmacro\TL {\char`\~} % tilde in a string
+\defCWEBmacro\UL {\char`\_} % underline character in a string
+\defCWEBmacro\CF {\char`\^} % circumflex character in a string
+
+\defCWEBmacro\SP {{\tt\char`\ }} % (visible) space in a string
+
+% \newbox\PPbox \setbox\PPbox=\hbox
+% {\kern.5pt\raise1pt\hbox{\sevenrm+\kern-1pt+}\kern.5pt}
+% \newbox\MMbox \setbox\MMbox=\hbox
+% {\kern.5pt\raise1pt\hbox{\sevensy\char0\kern-1pt\char0}\kern.5pt}
+% \newbox\MGbox \setbox\MGbox=\hbox % symbol for ->
+% {\kern-2pt\lower3pt\hbox{\teni\char'176}\kern1pt}
+% \newbox\MODbox \setbox\MODbox=\hbox
+% {\eightrm\%}
+%
+% \def\PP {\copy\PPbox}
+% \def\MM {\copy\MMbox}
+% \def\MG {\copy\MGbox}
+% \def\MOD {\mathbin{\copy\MODbox}}
+
+\defCWEBmacro\PP% symbol for ++
+ {\kern.05\CWEBpt
+ \raise.1\CWEBpt\hbox{\sevenrm+\kern-.1\CWEBpt+}%
+ \kern.05\CWEBpt}
+
+\defCWEBmacro\MM%
+ {\kern.05\CWEBpt
+ \raise.1\CWEBpt\hbox{\sevensy\char0\kern-.1\CWEBpt\char0}%
+ \kern.05\CWEBpt}
+
+\defCWEBmacro\MG%
+ {\kern-.2\CWEBpt
+ \lower.3\CWEBpt\hbox{\teni\char'176}%
+ \kern .1\CWEBpt}
+
+\defCWEBmacro\MRL#1%
+ {\mathrel{\let\K==#1}}
+
+% \def\MRL#1%
+% {\KK#1}
+% \def\KK#1#2%
+% {\buildrel\;#1\over{#2}}
+
+\letCWEBmacro\GG = \gg
+\letCWEBmacro\LL = \ll
+\letCWEBmacro\NULL = \Lambda
+
+% \mathchardef\AND = "2026 % bitwise and; also \& (unary operator)
+
+\defCWEBmacro\AND% redefines itself (funny)
+ {\mathchardef\AND="2026 \AND} % bitwise and; also \& (unary operator)
+
+\letCWEBmacro\OR = \mid % bitwise or
+\letCWEBmacro\XOR = \oplus % bitwise exclusive or
+\defCWEBmacro\CM {{\sim}} % bitwise complement
+\defCWEBmacro\MOD {\mathbin{\eightrm\%}}
+\defCWEBmacro\DC {\kern.1em{::}\kern.1em} % symbol for ::
+\defCWEBmacro\PA {\mathbin{.*}} % symbol for .*
+\defCWEBmacro\MGA {\mathbin{\MG*}} % symbol for ->*
+\defCWEBmacro\this {\&{this}}
+
+% \newbox \bak % backspace one em
+% \newbox \bakk % backspace two ems
+%
+% \setbox\bak =\hbox to -1em{}
+% \setbox\bakk=\hbox to -2em{}
+
+\newcount\CWEBind % current indentation in ems
+
+\defCWEBmacro\1% indent one more notch
+ {\global\advance\CWEBind by 1
+ \hangindent\CWEBind em}
+
+\defCWEBmacro\2% indent one less notch
+ {\global\advance\CWEBind by -1 }
+
+\defCWEBmacro\3#1% optional break within a statement
+ {\hfil
+ \penalty#10
+ \hfilneg}
+
+\defCWEBmacro\4% backspace one notch
+ {\hbox to -1em{}}
+
+\defCWEBmacro\5% optional break
+ {\hfil
+ \penalty-1
+ \hfilneg
+ \kern2.5em
+ \hbox to -2em{}%
+ \ignorespaces}
+
+\defCWEBmacro\6% forced break
+ {\ifmmode
+ \else
+ \par
+ \hangindent\CWEBind em
+ \noindent
+ \kern\CWEBind em
+ \hbox to -2em{}%
+ \ignorespaces
+ \fi}
+
+\defCWEBmacro\7% forced break and a little extra space
+ {\Y
+ \6}
+
+\defCWEBmacro\8% no indentation
+ {\hskip-\CWEBind em
+ \hskip 2em}
+
+\defCWEBmacro\9#1%
+ {}
+
+\newcount\gdepth % depth of current major group, plus one
+\newcount\secpagedepth
+\secpagedepth=3 % page breaks will occur for depths -1, 0, and 1
+
+% \newtoks\gtitle % title of current major group
+% \newskip\intersecskip
+% \intersecskip=12pt minus 3pt % space between sections
+
+% \let\yskip=\smallskip
+
+\defCWEBmacro\?%
+ {\mathrel?}
+
+% \def\note#1#2.%
+% {\Y\noindent
+% {\hangindent2em\baselineskip10pt\eightrm#1~#2.\par}}
+
+\defCWEBmacro\lapstar%
+ {\rlap{*}}
+
+% \def\stsec%
+% {\rightskip=0pt % get out of C mode (cf. \B)
+% \sfcode`;=1500
+% \pretolerance 200
+% \hyphenpenalty 50
+% \exhyphenpenalty 50
+% \noindent{\let\*=\lapstar\bf\secstar.\quad}}
+%
+% \let\startsection=\stsec
+
+\defCWEBmacro\defin#1%
+ {\global\advance\CWEBind by 2 \1\&{#1 } } % begin `define' or `format'
+
+% \def\A% xref for doubly defined section name
+% {\note{See also section}}
+%
+% \def\As% xref for multiply defined section name
+% {\note{See also sections}}
+
+\defCWEBmacro\B%
+ {\rightskip=0pt plus 100pt minus 10pt % go into C mode
+ \sfcode`;=3000
+ \pretolerance 10000
+ \hyphenpenalty 1000 % so strings can be broken (discretionary \ is inserted)
+ \exhyphenpenalty 10000
+ \global\CWEBind=2 \1\ \unskip}
+
+\defCWEBmacro\C#1%
+ {\5\5\quad$/\ast\,${\cmntfont #1}$\,\ast/$}
+
+% \let\SHC\C % "// short comments" treated like "/* ordinary comments */"
+
+\defCWEBmacro\SHC#1%
+ {\5\5\quad$//\,${\cmntfont#1}}
+
+% \def\C#1{\5\5\quad$\triangleright\,${\cmntfont#1}$\,\triangleleft$}
+% \def\SHC#1{\5\5\quad$\diamond\,${\cmntfont#1}}
+
+\defCWEBmacro\D% macro definition
+ {\defin{\#define}}
+
+\letCWEBmacro\E=\equiv % equivalence sign
+
+% \def\ET% conjunction between two section numbers
+% { and~}
+%
+% \def\ETs% conjunction between the last two of several section numbers
+% {, and~}
+
+\defCWEBmacro\F% format definition
+ {\defin{format}}
+
+\letCWEBmacro\G = \ge % greater than or equal sign
+
+% \H is long Hungarian umlaut accent
+
+\letCWEBmacro\I = \ne % unequal sign
+
+\defCWEBmacro\J% TANGLE's join operation
+ {\.{@\&}}
+
+% \let\K== % assignment operator
+
+\letCWEBmacro\K = \leftarrow % "honest" alternative to standard assignment operator
+
+% \L is Polish letter suppressed-L
+
+% \outer\def\M#1%
+% {\MN{#1}%
+% \ifon
+% \vfil
+% \penalty-100
+% \vfilneg % beginning of section
+% \vskip\intersecskip
+% \startsection
+% \ignorespaces}
+%
+% \outer\def\N#1#2#3.%
+% {\gdepth=#1%
+% \gtitle={#3}%
+% \MN{#2}% beginning of starred section
+% \ifon
+% \ifnum#1<\secpagedepth
+% \vfil
+% \eject % force page break if depth is small
+% \else
+% \vfil
+% \penalty-100
+% \vfilneg
+% \vskip\intersecskip
+% \fi
+% \fi
+% \message{*\secno}% progress report
+% \edef\next%
+% {\write\cont % write to contents file
+% {\ZZ{#3}{#1}{\secno}{\noexpand\the\pageno}}}%
+% \next % \ZZ{title}{depth}{sec}{page}
+% \ifon
+% \startsection
+% {\bf#3.\quad}%
+% \ignorespaces}
+%
+% \def\MN#1%
+% {\par % common code for \M, \N
+% {\xdef\secstar{#1}%
+% \let\*=\empty
+% \xdef\secno{#1}}% remove \* from section name
+% \ifx\secno\secstar
+% \onmaybe
+% \else
+% \ontrue
+% \fi
+% \mark{{{\tensy x}\secno}{\the\gdepth}{\the\gtitle}}}
+%
+% each \mark is {section reference or null}{depth plus 1}{group title}
+
+% \O is Scandinavian letter O-with-slash
+% \P is paragraph sign
+
+\defCWEBmacro\Q {\note{This code is cited in section}} % xref for mention of a section
+\defCWEBmacro\Qs {\note{This code is cited in sections}} % xref for mentions of a section
+
+% \S is section sign
+
+\defCWEBmacro\T#1%
+ {\leavevmode % octal, hex or decimal constant
+ \hbox
+ {$\def\?{\kern.2em}%
+ \def\$##1{\egroup_{\,\rm##1}\bgroup}% suffix to constant
+ \def\_{\cdot 10^{\aftergroup}}% power of ten (via dirty trick)
+ \let\~=\oct
+ \let\^=\hex
+ {#1}$}}
+
+\defCWEBmacro\U {\note{This code is used in section}} % xref for use of a section
+\defCWEBmacro\Us {\note{This code is used in sections}} % xref for uses of a section
+
+\letCWEBmacro\R = \lnot % logical not
+\letCWEBmacro\V = \lor % logical or
+\letCWEBmacro\W = \land % logical and
+
+% defined later on
+%
+% \def\X#1:#2\X%
+% {\ifmmode
+% \gdef\XX{\null$\null}%
+% \else
+% \gdef\XX{}%
+% \fi % section name
+% \XX$\langle\,${#2\eightrm\kern.5em#1}$\,\rangle$\XX}
+
+\unprotect
+
+\def\theCWEByskip {\blank[\v!small]}
+\def\theCWEBvskip {\blank[\v!big]}
+
+\protect
+
+\defCWEBmacro\Y%
+ {\par
+ \yskip}
+
+\defCWEBmacro\yskip%
+ {\theCWEByskip}
+
+\letCWEBmacro\Z = \le
+% \letCWEBmacro\ZZ = \let % now you can \write the control sequence \ZZ
+\letCWEBmacro\* = *
+
+\defCWEBmacro\oct%
+ {\hbox{$^\circ$\kern-.1em\it\aftergroup\?\aftergroup}}
+
+\defCWEBmacro\hex%
+ {\hbox{$^{\scriptscriptstyle\#}$\tt\aftergroup}}
+
+\defCWEBmacro\vb#1%
+ {\leavevmode
+ \hbox
+ {\kern.2\CWEBpt
+ \vrule
+ \vtop
+ {\vbox
+ {\hrule
+ \hbox{\strut\kern.2\CWEBpt\.{#1}\kern.2\CWEBpt}}
+ \hrule}%
+ \vrule
+ \kern.2\CWEBpt}} % verbatim string
+
+\def\onmaybe%
+ {\let\ifon=\maybe}
+
+\let\maybe=\iftrue
+
+\newif\ifon
+
+% \newif\iftitle
+% \newif\ifpagesaved
+%
+% \def\lheader%
+% {\mainfont
+% \the\pageno
+% \eightrm
+% \qquad
+% \grouptitle
+% \hfill
+% \title
+% \qquad
+% \mainfont
+% \topsecno} % top line on left-hand pages
+%
+% \def\rheader%
+% {\mainfont
+% \topsecno
+% \eightrm
+% \qquad
+% \title
+% \hfill
+% \grouptitle
+% \qquad
+% \mainfont
+% \the\pageno} % top line on right-hand pages
+%
+% \def\grouptitle
+% {\let\i=I
+% \let\j=J
+% \uppercase\expandafter{\expandafter\takethree\topmark}}
+%
+% \def\topsecno%
+% {\expandafter\takeone\topmark}
+%
+% \def\takeone #1#2#3{#1}
+% \def\taketwo #1#2#3{#2}
+% \def\takethree #1#2#3{#3}
+%
+% \def\nullsec%
+% {\eightrm
+% \kern-2em} % the \kern-2em cancels \qquad in headers
+%
+% \let\page=\pagebody % \def\page {\box255 }
+% \raggedbottom % \normalbottom % faster, but loses plain TeX footnotes
+%
+% \def\normaloutput#1#2#3%
+% {\shipout\vbox
+% {\ifodd
+% \pageno
+% \hoffset=\pageshift
+% \fi
+% \vbox to \fullpageheight
+% {\iftitle
+% \global\titlefalse
+% \else
+% \hbox to \pagewidth
+% {\vbox to 10pt{}%
+% \ifodd\pageno #3\else#2\fi}
+% \fi
+% \vfill#1}} % parameter #1 is the page itself
+% \global\advance\pageno by 1}
+%
+% \gtitle={\.{CWEB} output} % this running head is reset by starred sections
+%
+% \mark{\noexpand\nullsec0{\the\gtitle}}
+%
+% \def\title%
+% {\expandafter\uppercase\expandafter{\jobname}}
+%
+% \def\topofcontents%
+% {\centerline{\titlefont\title}
+% \vskip.7in
+% \vfill} % this material will start the table of contents page
+
+\def\botofcontents%
+ {\vfill
+ \centerline{\covernote}} % this material will end the table of contents page
+
+\def\covernote%
+ {}
+
+% some leftover
+
+\defCWEBmacro\contentspagenumber{0} % default page number for table of contents
+
+% \newdimen\pagewidth \pagewidth = 158mm % the width of each page
+% \newdimen\pageheight \pageheight = 223mm % the height of each page
+% \newdimen\fullpageheight \fullpageheight = 240mm % page height including headlines
+% \newdimen\pageshift \pageshift = 0in % shift righthand pages wrt lefthand ones
+%
+% \def\magnify#1%
+% {\mag=#1
+% \pagewidth=6.5truein
+% \pageheight=8.7truein
+% \fullpageheight=9truein
+% \setpage}
+%
+% \def\setpage%
+% {\hsize\pagewidth
+% \vsize\pageheight} % use after changing page size
+%
+% \def\contentsfile {\jobname.toc} % file that gets table of contents info
+% \def\readcontents {\input \contentsfile}
+% \def\readindex {\input \jobname.idx}
+% \def\readsections {\input \jobname.scn}
+%
+% \newwrite\cont
+% \output{\setbox0=\page % the first page is garbage
+% \openout\cont=\contentsfile
+% \write\cont{\catcode `\noexpand\@=11\relax} % \makeatletter
+% \global\output{\normaloutput\page\lheader\rheader}}
+% \setpage
+% \vbox to \vsize{} % the first \topmark won't be null
+
+\defCWEBdummy\magnify#1% magnify the page
+ {}
+
+\defCWEBmacro\ch%
+ {\note{The following sections were changed by the change file:}
+ \let\*=\relax}
+
+% \newbox\sbox % saved box preceding the index
+% \newbox\lbox % lefthand column in the index
+%
+% \def\inx%
+% {\par\vskip6pt plus 1fil % we are beginning the index
+% \def\page{\box255 }
+% \normalbottom
+% \write\cont{} % ensure that the contents file isn't empty
+% \write\cont{\catcode `\noexpand\@=12\relax} % \makeatother
+% \closeout\cont % the contents information has been fully gathered
+% \output
+% {\ifpagesaved
+% \normaloutput{\box\sbox}\lheader\rheader
+% \fi
+% \global\setbox\sbox=\page
+% \global\pagesavedtrue}
+% \pagesavedfalse
+% \eject % eject the page-so-far and predecessors
+% \setbox\sbox\vbox{\unvbox\sbox} % take it out of its box
+% \vsize=\pageheight
+% \advance\vsize by -\ht\sbox % the remaining height
+% \hsize=.5\pagewidth
+% \advance\hsize by -10pt
+% % column width for the index (20pt between cols)
+% \parfillskip 0pt plus .6\hsize % try to avoid almost empty lines
+% \def\lr{L} % this tells whether the left or right column is next
+% \output
+% {\if L\lr
+% \global\setbox\lbox=\page
+% \gdef\lr{R}
+% \else
+% \normaloutput
+% {\vbox to\pageheight
+% {\box\sbox
+% \vss
+% \hbox to\pagewidth{\box\lbox\hfil\page}}}
+% \lheader
+% \rheader
+% \global\vsize\pageheight\gdef\lr{L}\global\pagesavedfalse\fi}
+% \message{Index:}
+% \parskip 0pt plus .5pt
+% \outer\def\I##1, {\par\hangindent2em\noindent##1:\kern1em} % index entry
+% \def\[##1]{$\underline{##1}$} % underlined index item
+% \rm
+% \rightskip0pt plus 2.5em
+% \tolerance 10000
+% \let\*=\lapstar
+% \hyphenpenalty 10000
+% \parindent0pt
+% \readindex}
+%
+% \def\fin%
+% {\par\vfill\eject % this is done when we are ending the index
+% \ifpagesaved\null\vfill\eject\fi % output a null index column
+% \if L\lr\else\null\vfill\eject\fi % finish the current page
+% \parfillskip 0pt plus 1fil
+% \def\grouptitle{NAMES OF THE SECTIONS}
+% \let\topsecno=\nullsec
+% \message{Section names:}
+% \output={\normaloutput\page\lheader\rheader}
+% \setpage
+% \def\note##1##2.{\quad{\eightrm##1~##2.}}
+% \def\Q{\note{Cited in section}} % crossref for mention of a section
+% \def\Qs{\note{Cited in sections}} % crossref for mentions of a section
+% \def\U{\note{Used in section}} % crossref for use of a section
+% \def\Us{\note{Used in sections}} % crossref for uses of a section
+% \def\I{\par\hangindent 2em}\let\*=*
+% \readsections}
+%
+% \def\con%
+% {\par\vfill\eject % finish the section names
+% %\ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers
+% \rightskip = 0pt
+% \hyphenpenalty = 50
+% \tolerance = 200
+% \setpage
+% \output={\normaloutput\page\lheader\rheader}
+% \titletrue % prepare to output the table of contents
+% \pageno=\contentspagenumber
+% \def\grouptitle{TABLE OF CONTENTS}
+% \message{Table of contents:}
+% \topofcontents
+% \line{\hfil Section\hbox to3em{\hss Page}}
+% \let\ZZ=\contentsline
+% \readcontents\relax % read the contents info
+% \botofcontents
+% \end} % print the contents page(s) and terminate
+%
+% \def\contentsline#1#2#3#4%
+% {\ifnum#2=0
+% \smallbreak
+% \fi
+% \line{\consetup{#2}#1
+% \rm\leaders\hbox to .5em{.\hfil}\hfil\ #3\hbox to3em{\hss#4}}}
+%
+
+\defCWEBmacro\consetup#1%
+ {\ifcase#1 \bf % depth -1 (@**)
+ \or % depth 0 (@*)
+ \or \hskip2em % depth 1 (@*1)
+ \or \hskip4em % depth 2 (@*2)
+ \or \hskip6em % depth 3 (@*3)
+ \or \hskip8em % depth 4 (@*4)
+ \or \hskip10em % depth 5 (@*5)
+ \else \hskip12em
+ \fi} % depth 6 or more
+
+\defCWEBdummy \inx {} % index
+\defCWEBdummy \fin {} % finish
+\defCWEBdummy \con {} % table of contents and finish
+
+\defCWEBdummy \noinx {} % no indexes or table of contents
+\defCWEBdummy \nosecs {} % no index of section names or table of contents
+\defCWEBdummy \nocon {} % no table of contents
+
+\defCWEBmacro\,%
+ {\relax
+ \ifmmode
+ \mskip\thinmuskip
+ \else
+ \thinspace
+ \fi}
+
+% \def\noinx%
+% {\let\inx=\end}
+%
+% \def\nosecs%
+% {\let\FIN=\fin
+% \def\fin%
+% {\let\parfillskip=\end
+% \FIN}}
+%
+% \def\nocon%
+% {\let\con=\end}
+%
+% \newcount\twodigits
+%
+% \def\hours%
+% {\twodigits=\time
+% \divide\twodigits by 60
+% \printtwodigits
+% \multiply\twodigits by -60
+% \advance\twodigits by \time
+% :\printtwodigits}
+%
+% \def\gobbleone1{}
+%
+% \def\printtwodigits%
+% {\advance\twodigits by 100
+% \expandafter\gobbleone\number\twodigits
+% \advance\twodigits by -100 }
+%
+% \def\today%
+% {\ifcase\month
+% \or January\or February\or March\or April\or May\or June%
+% \or July\or August\or September\or October\or November\or December%
+% \fi
+% \space
+% \number\day, \number\year}
+%
+% \def\datethis%
+% {\def\startsection%
+% {\leftline{\sc\today\ at \hours}
+% \bigskip
+% \let\startsection=\stsec
+% \stsec}}
+%
+% \def\datecontentspage%
+% {\def\topofcontents%
+% {\leftline{\sc\today\ at \hours}
+% \bigskip
+% \centerline{\titlefont\title}
+% \vfill}}
+
+\defCWEBdummy\datethis {} % say `\datethis' in limbo, to get your listing timestamped before section 1
+\defCWEBdummy\datecontentspage {} % timestamps the contents page
+
+\defCWEBmacro\TeX%
+ {{\ifmmode\it\fi
+ \leavevmode
+ \hbox{T\kern-.1667em\lower.424ex\hbox{E}\hskip-.125em X}}}
+
+% alternative implementation
+
+\newif\ifCWEBnotes
+
+\defCWEBmacro\Q {\CWEBnotesfalse \note{This code is cited in section}} % xref for mention of a section
+\defCWEBmacro\Qs {\CWEBnotestrue \note{This code is cited in sections}} % xref for mentions of a section
+
+\defCWEBmacro\U {\CWEBnotesfalse \note{This code is used in section}} % xref for use of a section
+\defCWEBmacro\Us {\CWEBnotestrue \note{This code is used in sections}} % xref for uses of a section
+
+\defCWEBmacro\A {\CWEBnotesfalse \note{See also section}} % xref for doubly defined section name
+\defCWEBmacro\As {\CWEBnotestrue \note{See also sections}} % xref for multiply defined section name
+
+\defCWEBmacro\ET% conjunction between two section numbers
+ { and~}
+
+\defCWEBmacro\ETs% conjunction between the last two of several section numbers
+ {, and~}
+
+%\def\processCWEBsectionnumbers[#1]%
+% {\bgroup
+% \def\CWEBcomma%
+% {\def\CWEBcomma{, }}%
+% \def\docommand##1%
+% {\bgroup
+% \def\[####1]{####1}%
+% \xdef\CWEBreference{##1}%
+% \egroup
+% \CWEBcomma{\naar{\donottest{##1}}[web:\CWEBreference]}}%
+% \processcommalist[{#1}]\docommand
+% \egroup}
+
+% \def\processCWEBsectionnumbers[#1]%
+% {\bgroup
+% \def\CWEBcomma%
+% {\def\CWEBcomma{, }}%
+% \def\docommand##1%
+% {\bgroup
+% \def\(####1){####1}%
+% \xdef\CWEBreference{##1}%
+% \egroup
+% \CWEBcomma
+% {\localcolortrue\naar{\donottest{##1}}[web:\CWEBreference]}}%
+% \bgroup
+% \def\[##1]{\(##1)}\let\(=\relax\xdef\CWEBreferences{#1}%
+% \egroup
+% \unexpanded\def\(##1){\[##1]}%
+% \processcommacommand[\CWEBreferences]\docommand
+% \egroup}
+
+\def\processCWEBsectionnumbers[#1]%
+ {\bgroup
+ \def\CWEBcomma%
+ {\def\CWEBcomma{, }}%
+ \def\docommand##1%
+ {\bgroup
+ \def\[####1]{####1}%
+ \xdef\CWEBreference{##1}%
+ \egroup
+ \CWEBcomma{\localcolortrue\goto{\donottest{##1}}[web:\CWEBreference]}}%
+ \processlist{(}{)}{,}\docommand(#1)
+ \egroup}
+
+\def\processCWEBsectionnotes%
+ {\catcode`\s=12
+ \doprocessCWEBsectionnotes}
+
+\def\doprocessCWEBsectionnotes#1.%
+ {\ifCWEBnotes
+ \def\next##1\ET##2##3.%
+ {\processCWEBsectionnumbers[##1]%
+ \if##2s%
+ {, and~\goto{##3}[web:##3]}%
+ \else
+ { and~\goto{##2##3}[web:##2##3]}%
+ \fi}%
+ \next#1.%
+ \else
+ \goto{#1}[web:#1]%
+ \fi
+ \afterCWEBnote % inside group!
+ \egroup}
+
+\let\afterCWEBnote=\relax
+
+\defCWEBmacro\note#1%
+ {\bgroup
+ \Y\noindent
+ \def\afterCWEBnote{\par}%
+ \hangindent2em
+ %\baselineskip10pt
+ \eightrm#1~\processCWEBsectionnotes}
+
+\def\oldCWEBmacroX#1:#2\X% original
+ {\ifmmode
+ \gdef\XX{\null$\null}%
+ \else
+ \gdef\XX{}%
+ \fi % section name
+ \XX$\langle\,${#2\eightrm\kern.5em#1}$\,\rangle$\XX}
+
+\defCWEBmacro\ATH%
+ {\oldCWEBmacroX\kern-.5em:Preprocessor definitions\X}
+
+\def\newCWEBmacroX#1:#2\X% original
+ {\ifmmode
+ \gdef\XX{\null$\null}%
+ \else
+ \gdef\XX{}%
+ \fi % section name
+ \XX$\langle\,$%
+ {#2\eightrm\kern.5em\processCWEBsectionnumbers[{#1}]}%
+ $\,\rangle$\XX}
+
+\defCWEBmacro\X#1:#2\X%
+ {\newCWEBmacroX#1:#2\X}
+
+\definemarking[CWEBfilename]
+\definemarking[CWEBsectiontitle]
+\definemarking[CWEBsectionnumber]
+\definemarking[CWEBsectiondepth]
+
+\defCWEBmacro\M#1%
+ {\MN{#1}%
+ \ifon
+ \vfil
+ \penalty-100
+ \vfilneg % beginning of section
+ \theCWEBvskip
+ \startsection
+ \pagereference[web:#1]%
+ \expanded{\marking[CWEBsectionnumber]{\secno}}%
+ \expanded{\marking[CWEBsectiondepth]{\the\gdepth}}%
+ \ignorespaces}
+
+\defCWEBmacro\N#1#2#3.%
+ {\gdepth=#1%
+ \MN{#2}% beginning of starred section
+ \ifon
+ \ifnum#1<\secpagedepth
+ \vfil
+ \eject % force page break if depth is small
+ \else
+ \vfil
+ \penalty-100
+ \vfilneg
+ \theCWEBvskip
+ \fi
+ \fi
+ \message{*\secno}% progress report
+ \makesectionformat % context
+ \defconvertedargument\ascii{#3}%
+ \edef\next%
+ {\write\CWEBcont % write to contents file
+ {\string\ZZ{\ascii}{#1}{\secno}%
+ {\sectionformat::\noexpand\userfolio}{\noexpand\realfolio}}}%
+ \next % \ZZ{title}{depth}{sec}{page}
+ \ifon
+ \startsection
+ \pagereference[web:#2]%
+ \marking[CWEBsectiontitle] {#3}%
+ \expanded{\marking[CWEBsectionnumber]{\secno}}%
+ \expanded{\marking[CWEBsectiondepth]{\the\gdepth}}%
+ {\bf#3.\quad}%
+ \ignorespaces}
+
+\defCWEBmacro\MN#1%
+ {\par % common code for \M, \N
+ {\xdef\secstar{#1}%
+ \let\*=\empty
+ \xdef\secno{#1}}% remove \* from section name
+ \ifx\secno\secstar
+ \onmaybe
+ \else
+ \ontrue
+ \fi}
+
+\newif\iflinktoCWEBfile
+
+\def\setCWEBlinkfile#1%
+ {\linktoCWEBfiletrue
+ \def\otherCWEBfile{#1}}
+
+\unprotect
+
+\def\gotoCWEBsection#1[#2]%
+ {\iflinktoCWEBfile
+ \bgroup
+ \setupinteraction[\c!color=,\c!style=]%
+ \let\savedreferenceprefix=\referenceprefix
+ \localcolortrue
+ \goto{#1}[\otherCWEBfile::\savedreferenceprefix web:#2]%
+ \egroup
+ \else
+ #1%
+ \fi}
+
+\protect
+
+\defCWEBmacro\startsection%
+ {\rightskip=0pt % get out of C mode (cf. \B)
+ \sfcode`;=1500
+ \pretolerance 200
+ \hyphenpenalty 50
+ \exhyphenpenalty 50
+ \noindent
+ \bgroup
+ \let\*=\lapstar
+ \gotoCWEBsection{\bf\secstar.\quad}[\secno]%
+ \egroup}
+
+\def\ignoreCWEBinput%
+ {\let\normalinput=\input
+ \def\input ##1 %
+ {\let\input=\normalinput}}
+
+\def\loadCWEBmacros#1%
+ {\let\oldN=\N
+ \def\N{\bgroup\setbox0=\vbox\bgroup\endinput}%
+ \ignoreCWEBinput
+ \ReadFile{#1.tex}%
+ \egroup\egroup
+ \let\N=\oldN}
+
+\def\resetCWEBcontext%
+ {\catcode`\|=12 % used in context discretionaries
+ \everypar{} % used for context indentation and floats
+ \parskip=0pt % no stretch between cweb paragraphs
+ \parindent=1em} % is related to cweb backspace etc
+
+\newwrite\CWEBcont
+
+\def\processCWEBsource #1 %
+ {\bgroup
+ \resetCWEBcontext
+ \activateCWEB
+ \ignoreCWEBinput
+ \immediate\openout\CWEBcont=#1.toc
+ \write\CWEBcont{\noexpand\unprotect}
+ \message{Source:}
+ \marking[CWEBfilename]{#1}
+ \ReadFile{#1.tex}\relax
+ \write\CWEBcont{\noexpand\protect}
+ \closeout\CWEBcont
+ \par
+ \egroup}
+
+\def\resetCWEBindexentry%
+ {\xdef\currentCWEBindexentry{}}
+
+\def\showCWEBindexentry#1% can be redefined
+ {\theCWEBvskip
+ \vskip3\lineheight
+ \goodbreak
+ \vskip-3\lineheight
+ {\pagereference[web:#1]\bf#1}%
+ \theCWEBvskip}
+
+\def\checkCWEBindexentry#1%
+ {\bgroup
+ \def\\##1{##1}% a dummy that also removes the {}
+ \def\|##1{##1}% another dummy
+ \def\.##1{*##1}% and another (the typewriter one)
+ \def\#1{##1}% and a last one
+ \def\9##1{##1}% hold this one
+ \catcode`*=11
+ \expandafter\def\expandafter\entry\expandafter{#1}%
+ \defconvertedcommand\ascii\entry
+ \expanded{\FINDFIRSTCHARACTER{\ascii}}%
+ \doifnot{\currentCWEBindexentry}{\firstcharacter}
+ {\doifnot{\firstcharacter}{*} % signal for \firstbunch
+ {\global\let\currentCWEBindexentry=\firstcharacter
+ \showCWEBindexentry{\currentCWEBindexentry}}}%
+ \egroup}
+
+\def\theCWEBbeforeindex {\startcolumns}
+\def\theCWEBafterindex {\stopcolumns}
+
+\def\processCWEBindex #1 %
+ {\bgroup
+ \resetCWEBcontext
+ \activateCWEB
+ \resetCWEBindexentry
+ \def\I##1, %
+ {\par
+ \checkCWEBindexentry{##1}%
+ \hangindent2em
+ \noindent##1:\kern1em%
+ \def\next####1.%
+ {\processCWEBsectionnumbers[{####1}]}%
+ \next}%
+ \def\[##1]%
+ {$\underline{##1}$}%
+ \let\*=\lapstar
+ \parfillskip 0pt plus .6\hsize % try to avoid almost empty lines
+% \parskip 0pt plus .5pt
+ \rightskip0pt plus 2.5em
+ \tolerance 10000
+ \hyphenpenalty 10000
+ \parindent0pt
+ \message{Index:}
+ \marking[CWEBfilename] {#1}
+ \marking[CWEBsectiontitle] {index}
+ \marking[CWEBsectionnumber]{}
+ \marking[CWEBsectiondepth]{}
+ \loadCWEBmacros{#1}
+ \theCWEBbeforeindex
+ \ReadFile{#1.idx}\relax
+ \theCWEBafterindex
+ \par
+ \egroup}
+
+\def\processCWEBsections #1 %
+ {\bgroup
+ \resetCWEBcontext
+ \activateCWEB
+ \loadCWEBmacros{#1}
+ \parfillskip = 0pt plus 1fil
+ \parindent = 0pt
+ \let\topsecno=\nullsec
+ \def\note##1%
+ {\quad
+ \bgroup
+ \eightrm
+ ##1~\processCWEBsectionnotes}
+ \def\Q {\CWEBnotesfalse \note{Cited in section}} % crossref for mention of a section
+ \def\Qs{\CWEBnotestrue \note{Cited in sections}} % crossref for mentions of a section
+ \def\U {\CWEBnotesfalse \note{Used in section}} % crossref for use of a section
+ \def\Us{\CWEBnotestrue \note{Used in sections}} % crossref for uses of a section
+ \def\I {\par\hangindent 2em}%
+ \let\*=*
+ \message{Section names:}
+ \marking[CWEBfilename] {#1}
+ \marking[CWEBsectiontitle] {sections}
+ \marking[CWEBsectionnumber]{}
+ \marking[CWEBsectiondepth]{}
+ \loadCWEBmacros{#1}
+ \ReadFile{#1.scn}\relax
+ \par
+ \botofcontents
+ \par
+ \egroup}
+
+\def\processCWEBcontents #1 %
+ {\bgroup
+ \resetCWEBcontext
+ \activateCWEB
+ \loadCWEBmacros{#1}
+ \rightskip = 0pt
+ \hyphenpenalty = 50
+ \tolerance = 200
+ \parindent = 0pt
+ \line{\hfil Section\hbox to3em{\hss Page}}
+ \let\ZZ=\contentsline
+ \message{Table of contents:}
+ \marking[CWEBfilename] {#1}
+ \marking[CWEBsectiontitle] {table of contents}
+ \marking[CWEBsectionnumber]{}
+ \marking[CWEBsectiondepth]{}
+ \loadCWEBmacros{#1}
+ \ReadFile{#1.toc}\relax
+ \par
+ \egroup}
+
+\defCWEBmacro\contentsline#1#2#3#4#5%
+ {\ifnum#2=0
+ \smallbreak
+ \fi
+ \line{\consetup{#2}#1
+ \rm
+ \leaders\hbox to .5em{.\hfil}\hfil\
+ {\localcolortrue\goto{#3}[web:#3]}% below: \gotorealpage ? should be changed
+ \hbox to3em{\localcolortrue\hss\gotorealpage{}{}{#5}{\translatednumber[#4]\presetgoto}}}}
+
+%D A last hack, needed because a file can overload of the
+%D above. (Some day: a check like \type{\ifx#1\CWEBdefined}.)
+
+\def\outer#1#2%
+ {\ifx#2\undefined
+ \expandafter#1\expandafter#2%
+ \else
+ \expandafter#1\expandafter\ThrowAway
+ \fi}
+
+\endinput
diff --git a/tex/context/base/m-database.tex b/tex/context/base/m-database.tex
new file mode 100644
index 000000000..3bb050f14
--- /dev/null
+++ b/tex/context/base/m-database.tex
@@ -0,0 +1,421 @@
+%D \module
+%D [ file=m-database,
+%D version=2006.04.23,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Database Thingies,
+%D author=Hans Hagen\& Taco Hoekwater,
+%D date=\currentdate,
+%D copyright=PRAGMA
+%D ]
+
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+% % % to be added to mult-* files
+%
+% % % todo: \dontcollectseparatedlist via k/v
+
+\definesystemvariable{ls}
+
+\def\c!first {first}
+\def\c!last {last}
+\def\c!quotechar {quotechar}
+
+\let\@NX\noexpand
+
+%D {processquotedlist}
+%D
+%D An even more general list processing macro is the
+%D following one:
+%D
+%D \starttyping
+%D \processquotedlist{beginsym}{endsym}{separator}\docommand list
+%D \stoptyping
+%D
+%D This one supports arbitrary open and close symbols as well
+%D as user defined separators.
+%D
+%D \starttyping
+%D \processquotedlist(){,}{"}\docommand(a=>b=>c=>d)
+%D \stoptyping
+
+\def\processquotedlist#1#2#3#4#5%
+ {\def\csvquotechar{#4}%
+ \edef\doconvertcsvquoteditem#4##1#4##2%
+ {\@NX\ifx##2#3%
+ \let\@NX\next\@NX\doconvertcsvlist
+ \def\@NX\arg{#3}%
+ \edef\@NX\temp{##1}%
+ \@NX\expanded{\@NX#5{\@NX\temp}}%
+ \@NX\else
+ \let\@NX\next\@NX\redoconvertcsvquoteditem
+ \def\@NX\arg{##1\@NX\csvquotechar}%
+ \@NX\fi
+ \@NX\expandafter\@NX\next\@NX\arg}%
+ \edef\redoconvertcsvquoteditem##1#4##2%
+ {\@NX\ifx##2#3%
+ \let\@NX\next\@NX\doconvertcsvlist
+ \def\@NX\arg{#3}%
+ \edef\@NX\temp{##1}%
+ \@NX\expanded{\@NX#5{\@NX\temp}}%
+ \@NX\else
+ \let\@NX\next\@NX\redoconvertcsvquoteditem
+ \def\@NX\arg{##1\@NX\csvquotechar}%
+ \@NX\fi
+ \@NX\expandafter\@NX\next\@NX\arg}%
+ \edef\doconvertcsvitem##1#3%
+ {\edef\@NX\temp{##1}%
+ \@NX\expanded{\@NX#5{\@NX\temp}}%
+ \@NX\doconvertcsvlist#3}%
+ \edef\doconvertcsvlist#3##1%
+ {\@NX\ifx##1\@NX#2%
+ \let\@NX\next \@NX\gobbleoneargument
+ \@NX\else\@NX\ifx##1#4%
+ \let\@NX\next \@NX\doconvertcsvquoteditem
+ \@NX\else
+ \let\@NX\next \@NX\doconvertcsvitem
+ \@NX\fi\@NX\fi \@NX\next##1}%
+ \doconvertcsvitem}
+
+\gdef\doprocessseparatedquoteditem#1%
+ {\appendseparatedlistparameter\c!left%
+ \appendseparatedlistcontent{#1}%
+ \appendseparatedlistparameter\c!right}
+
+% a version more robust with regard to {a a} b c d situations:
+
+\edef\detokenizedrelax{\detokenize{\relax}}
+
+\edef\processseplistseparator{\detokenize{,}}%
+
+\def\dodefineprocessseplist#1#2% separator \docommand
+ {\edef\processseplistseparator{\detokenize{#1}}%
+ \def\dodoprocessseplist##1##2#1%
+ {\edef\!!stringa{\detokenize{##1}}%
+ \ifx\detokenizedrelax\!!stringa
+ \expandafter\nodoprocessseplist
+ % \else\ifx\!!stringa#1%
+ \else\ifx\!!stringa\processseplistseparator
+ #2{}%
+ #2{##2}%
+ \expandafter\expandafter\expandafter\dodoprocessseplist
+ \else
+ #2{##1##2}%
+ \expandafter\expandafter\expandafter\dodoprocessseplist
+ \fi\fi}%
+ \def\doprocessseplist##1\relax
+ {\dodoprocessseplist##1#1\relax#1\relax\relax\end}}
+
+\def\nodoprocessseplist#1\end
+ {}
+
+\long\def\processseplist#1#2#3\relax raw version
+ {\dodefineprocessseplist{#1}{#2}%
+ \dodoprocessseplist#3#1\relax#1\relax\relax\end}
+
+% \dodefineprocessseplist{,}\test
+% \dodoprocessseplist{,}a,b,c\relax,\relax\relax\end
+% \doprocessseplista,b,c\relax
+
+% \def\test#1{[#1]}
+% \startlines
+% \processseplist{,}\test ,2,,\relax
+% \processseplist{,}\test ,,,44\relax
+% \processseplist{,}\test ,,33,44\relax
+% \processseplist{,}\test 11,,33,44\relax
+% \processseplist{,}\test 1,2,3,4\relax
+% \stoplines
+
+\newtoks\separatedlistdata
+
+\def\appendseparatedlistparameter#1%
+ {\@EAEAEA\appendtoks\csname\??ls\currentseparatedlist#1\endcsname\to\separatedlistdata}
+
+\def\appendseparatedlistcontent#1%
+ {\appendtoks#1\to\separatedlistdata}
+
+\def\flushseparatedlistdata
+ {\the\separatedlistdata
+ \separatedlistdata\emptytoks}
+
+\def\initializeseparatedlistdata
+ {\separatedlistdata{\egroup}}
+
+\def\dontcollectseparatedlist
+ {\def\dodoprocessseparatedfileline
+ {\the\separatedlistdata
+ \separatedlistdata\emptytoks
+ \doprocessseparatedfileline}%
+ \def\dodoprocessseparatedline
+ {\the\separatedlistdata
+ \separatedlistdata\emptytoks
+ \doprocessseparatedline}%
+ \let\flushseparatedlistdata\egroup
+ \let\initializeseparatedlistdata\donothing}
+
+\chardef\separatedlistmode\zerocount
+
+\def\setcurrentlistseparator
+ {\edef\currentlistseparator
+ {\executeifdefined
+ {\??ls::\csname\??ls\currentseparatedlist\c!separator\endcsname}%
+ {\csname\??ls\currentseparatedlist\c!separator\endcsname}}%
+ \doifvalue{\??ls\currentseparatedlist\c!separator}{tab}
+ {\catcode`\^^I=12\relax}%
+ \ifx\currentlistseparator\empty\def\currentlistseparator{,}\fi}
+
+\bgroup \catcode`\^^I=12
+ \setgvalue{\??ls::tab}{ }
+ \setgvalue{\??ls::space}{ }
+ \setgvalue{\??ls::comma}{,}
+\egroup
+
+\def\doprocessseparatedfileline
+ {\ifeof\scratchread
+ \ifcase\separatedlistmode\appendseparatedlistparameter\c!after\fi
+ \immediate\closein\scratchread
+ \expandafter\flushseparatedlistdata
+ \else\ifx\line\empty
+ % skip, can be comment
+ \read\scratchread to\line
+ \@EA\dodoprocessseparatedfileline
+ \else
+ \appendseparatedlistparameter{\ifcase\separatedlistmode\c!first\else\c!command\fi}%
+ \ifx\currentlistquotechar\empty%
+ \expandafter\doprocessseplist\line\relax
+ \else
+ \expanded{\processquotedlist{}{\noexpand\end}%
+ {\currentlistseparator}{\currentlistquotechar}%
+ \noexpand\doprocessseparatedquoteditem \line\currentlistseparator\noexpand\end}%
+ \fi
+ \ifcase\separatedlistmode\appendseparatedlistparameter\c!last\fi
+ \read\scratchread to\line
+ \@EAEAEA\dodoprocessseparatedfileline
+ \fi\fi}
+
+\def\dodoprocessseparatedfileline
+ {\doprocessseparatedfileline}
+
+\def\doprocessseparatedfile[#1][#2]%
+ {\bgroup
+ \edef\currentseparatedlist{#1}%
+ \doifdefined{\??ls\currentseparatedlist\c!command}{\chardef\separatedlistmode\plusone}%
+ \setcurrentlistseparator
+ \edef\currentlistquotechar{\csname\??ls\currentseparatedlist\c!quotechar\endcsname}%
+ \expandafter\dodefineprocessseplist\expandafter{\currentlistseparator}\doprocessseparateditem
+ \initializeseparatedlistdata
+ \directsetup{\currentseparatedlist:\executeifdefined{\??ls\currentseparatedlist\c!setups}\s!default}%
+ \ifcase\separatedlistmode\appendseparatedlistparameter\c!before\fi
+ \endlinechar\minusone
+ \ignorelines
+ \catcode`\#\@@comment
+ \immediate\openin\scratchread=#2\relax % todo: \doopenin
+ \read\scratchread to\line
+ \doprocessseparatedfileline}
+
+\def\dostartseparatedlist#1[#2]%
+ {\bgroup
+ \edef\currentseparatedlist{#2}%
+ \doifdefined{\??ls\currentseparatedlist\c!command}{\chardef\separatedlistmode\plusone}%
+ \obeylines
+ \let#1\relax
+ \def\separateslistend{#1}%
+ \setcurrentlistseparator
+ \edef\currentlistquotechar{\csname\??ls\currentseparatedlist\c!quotechar\endcsname}%
+ \expandafter\dodefineprocessseplist\expandafter{\currentlistseparator}\doprocessseparateditem
+ \directsetup{\currentseparatedlist:\executeifdefined{\??ls\currentseparatedlist\c!setups}\s!default}%
+ \initializeseparatedlistdata
+ \ifcase\separatedlistmode\appendseparatedlistparameter\c!before\fi
+ \dodostartseparatedlist}
+
+\def\redoprocessseparatedline#1%
+ {\def\!!stringa{#1}%
+ \ifx\!!stringa\separateslistend
+ \ifcase\separatedlistmode\appendseparatedlistparameter\c!after\fi
+ \expandafter\flushseparatedlistdata
+ \else%
+ \appendseparatedlistparameter{\ifcase\separatedlistmode\c!first\else\c!command\fi}%
+ \ifx\currentlistquotechar\empty%
+ \doprocessseplist#1\relax
+ \else%
+ \defconvertedargument\csvdata{#1}%
+ \expanded{\processquotedlist{}{\noexpand\end}%
+ {\currentlistseparator}{\currentlistquotechar}%
+ \noexpand\doprocessseparatedquoteditem \csvdata\currentlistseparator\noexpand\end}%
+ \fi
+ \ifcase\separatedlistmode\appendseparatedlistparameter\c!last\fi
+ \expandafter\dodoprocessseparatedline
+ \fi}
+
+\def\doprocessseparatedline
+ {\doifnextbgroupelse\xdoprocessseparatedline\ydoprocessseparatedline}
+
+\def\dodoprocessseparatedline
+ {\doprocessseparatedline}
+
+\def\doprocessseparateditem#1%
+ {\ifcase\separatedlistmode
+ \appendseparatedlistparameter\c!left
+ \appendseparatedlistcontent{#1}%
+ \appendseparatedlistparameter\c!right
+ \else
+ \appendseparatedlistcontent{{#1}}%
+ \fi}
+
+
+\bgroup \obeylines
+
+ \gdef\dodostartseparatedlist#1
+ {\doprocessseparatedline}
+
+ \gdef\xdoprocessseparatedline#1#2
+ {\redoprocessseparatedline{{{#1}}#2}}
+
+ \gdef\ydoprocessseparatedline#1
+ {\redoprocessseparatedline{#1}}
+
+\egroup
+
+\startsetups CSV:unix
+ \catcode`\#=\@@comment
+\stopsetups
+
+\def\defineseparatedlist
+ {\dodoubleempty\dodefineseparatedlist}
+
+\def\dodefineseparatedlist[#1][#2]%
+ {\setvalue{\e!start#1}{\expandafter\dostartseparatedlist\csname\e!stop#1\endcsname[#1]}%
+ \getparameters
+ [\??ls#1]
+ [\c!separator=,
+ \c!quotechar=,
+ \c!first=,
+ \c!left=,
+ \c!before=,
+ \c!right=,
+ \c!last=,
+ \c!after=,
+% \c!command=,
+ #2]}
+
+\def\setupseparatedlist
+ {\dodoubleempty\dosetupseparatedlist}
+
+\def\dosetupseparatedlist[#1]% [#2]
+ {\getparameter[\??ls#1]} % [#2]
+
+\def\startseparatedlist[#1]%
+ {\dostartseparatedlist\stopseparatedlist[#1]}
+
+\def\processseparatedfile
+ {\dodoubleargument\doprocessseparatedfile}
+
+\protect \doifnotmode{demo}{\endinput}
+
+\defineseparatedlist
+ [CSV]
+ [separator={,},
+ first=\bTR,last=\eTR,
+ left=\bTD,right=\eTD,
+ before=\bTABLE,after=\eTABLE]
+
+\startseparatedlist[CSV]
+a,b,c
+d,e,f
+\stopseparatedlist
+
+\startCSV
+a,b,c
+d,e,f
+\stopCSV
+
+\defineseparatedlist
+ [CSV]
+ [separator={,},
+ quotechar={"},
+ first=\NC,last=\NR,
+ left=,right=\NC,
+ before={\starttabulate[|l|l|l|]},after=\stoptabulate]
+
+\startCSV
+a,b,"c,d"
+d,"""",f
+\stopCSV
+
+\defineseparatedlist
+ [CSV]
+ [separator={ },
+ first=\NC,last=\NR,
+ left=,right=\NC,
+ before={\starttabulate[|l|l|l|]},after=\stoptabulate]
+
+\startCSV
+a b c
+d e f
+\stopCSV
+
+\defineseparatedlist
+ [CSV]
+ [setups=unix,
+ first=\NC,last=\NR,
+ left=,right=\NC,
+ before={\starttabulate[|l|l|l|]},after=\stoptabulate]
+
+% \startsetups CSV:unix
+% \catcode`\#=\@@comment
+% \stopsetups
+
+% %1,2,3
+% 1,2,3
+% # 4,5,6
+% 4,5,6
+
+\processseparatedfile[CSV][test.dat]
+
+\defineseparatedlist
+ [CSVX]
+ [command=\Whatever,
+ separator={,},
+ first=\bTR,last=\eTR,
+ left=\bTD,right=\eTD,
+ before=\bTABLE,after=\eTABLE]
+
+\def\Whatever#1#2#3{[#1][#2][#3]\endgraf}
+
+\startseparatedlist[CSVX]
+a,b,c
+d,e,f
+\stopseparatedlist
+
+\defineseparatedlist[CSV]
+ [separator=comma,
+ before=\bTABLE, after=\eTABLE,
+ first=\bTR, last=\eTR,
+ left=\bTD, right=\eTD]
+
+\startCSV
+a,b,c,č
+d,e,f,š
+\stopCSV
+
+\enableregime[utf]
+
+\defineseparatedlist[X][separator=X,left=(,right=),first=\endgraf,last=\endgraf]
+\defineseparatedlist[Y][separator=Y,left=(,right=),first=\endgraf,last=\endgraf]
+
+\startX
+aXb
+Xc
+čXš
+\stopX
+
+\startY
+aYb
+Yc
+čYš
+\stopY
+
+\stoptext
diff --git a/tex/context/base/m-datastrc.tex b/tex/context/base/m-datastrc.tex
new file mode 100644
index 000000000..4a6faa66b
--- /dev/null
+++ b/tex/context/base/m-datastrc.tex
@@ -0,0 +1,228 @@
+%D \module
+%D [ file=m-datastrc, % was: core-dat % was core-02a
+%D version=1999.08.10, % 1997.03.31,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Database Support, % 2A
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Database Support}
+
+\unprotect
+
+%D This module is a (limited) rewrite of the original \type
+%D {core-02a} module, the module that dealt with managing a
+%D database of addresses. The principles and methods have not
+%D changed; they are only generalized.
+%D
+%D A database file |<|in most cases such a base is generated
+%D from another one|>| is structured as follows:
+%D
+%D \starttyping
+%D \startrecord{tag}
+%D \memberofgroup{grouplist}
+%D \setrecordentry{name}{...}
+%D ....
+%D \stoprecord
+%D \stoptyping
+%D
+%D The interface to such a database is defined as follows:
+%D
+%D \starttyping
+%D \definerecord[class][settings]
+%D \setuprecord[class][settings]
+%D \definerecordentry[class][name]
+%D \stoptyping
+%D
+%D and processed by
+%D
+%D \starttyping
+%D \processrecords[file list][tag and/or group list]
+%D \stoptyping
+%D
+%D The actual processing is done by a macro assigned to \type
+%D {command}:
+%D
+%D \starttyping
+%D \setuprecord[class][command=\DoWithRecord]
+%D \stoptyping
+%D
+%D Given that one can ask for a field with
+%D
+%D \starttyping
+%D \getrecordentry{name}
+%D \stoptyping
+%D
+%D such a command can look like:
+%D
+%D \starttyping
+%D \def\DoWithRecord#1%
+%D {\startpacked
+%D \let\\=\quad
+%D name: \getrecordentry{name}~\getrecordentry{family name}\par
+%D address: \getrecordentry{postal address}\par
+%D \stoppacked}
+%D \stoptyping
+%D
+%D The argument passed is the tag. The database can look like:
+%D
+%D \starttyping
+%D \startrecord{hagenj}
+%D \memberofgroup{a,b}
+%D \setrecordentry{naam}{Hans}
+%D \setrecordentry{family name}{Hagen}
+%D \setrecordentry{postal address}{J. Hagen\\Ridderstraat 29\\Hasselt NL}
+%D \stoprecord
+%D
+%D \startrecord{ottenaf}
+%D \memberofgroup{a}
+%D \setrecordentry{name}{Ton}
+%D \setrecordentry{family name}{Otten}
+%D \setrecordentry{postal address}{A.F. Otten\\Prinsengracht 17\\Hasselt NL}
+%D \stoprecord
+%D \stoptyping
+%D
+%D The definition of this database looks like:
+%D
+%D \starttyping
+%D \definerecord[address][command=\DoWithRecord]
+%D
+%D \definerecordentry[address][name]
+%D \definerecordentry[address][family name]
+%D \definerecordentry[address][postal address]
+%D \stoptyping
+%D
+%D The actual processing is now done by (for instance):
+%D
+%D \starttyping
+%D \processrecords[datafile][hagenj]
+%D \processrecords[datafile][hagenj,offenaf]
+%D \processrecords[datafile][all]
+%D \processrecords[datafile][a]
+%D \processrecords[datafile][b]
+%D \stoptyping
+%D
+%D Of course one can reassign the command used to handle the
+%D records in between.
+
+% \??kt ->
+% \??kw ->
+
+\def\??db {@@db}
+\def\c!velden{velden}
+
+%\newevery \everyrecord \EveryRecord
+
+\def\definerecord
+ {\dodoubleempty\dodefinerecord}
+
+\def\dodefinerecord[#1][#2]%
+ {\getparameters
+ [\??db#1]
+ [\c!velden=,
+ \c!command=\gobbleoneargument,
+ #2]}
+
+\def\setuprecord
+ {\dodoubleargument\dosetuprecord}
+
+\def\dosetuprecord[#1][#2]%
+ {\getparameters[\??db#1][#2]}%
+
+\def\definerecordentry[#1][#2]%
+ {\edef\recordentries{\getvalue{\??db#1\c!velden}}%
+ \addtocommalist{#2}\recordentries
+ \letvalue{\??db#1\c!velden}\recordentries}
+
+%D Watch out: the entries are defined global! While
+%D processing a record, no grouping is applied.
+
+\def\getrecordentry #1{\getvalue {\??db:#1}}
+\def\resetrecordentry #1{\letgvalueempty{\??db:#1}}
+\def\assignrecordentry#1{\setgvalue {\??db:#1}}
+
+\long\def\skiprecord#1\stoprecord
+ {\egroup}
+
+\newif\ifrecordok
+
+\newtoks\resetrecordlist
+
+\def\processrecords
+ {\dotripleargument\doprocessrecords}
+
+\def\doprocessrecords[#1][#2][#3]%
+ {\bgroup
+ \ifx\\\undefined\let\\\relax\fi
+ \def\docommand##1%
+ {\resetrecordentry{##1}%
+ \appendtoks\resetrecordentry{##1}\to\resetrecordlist}%
+ \processcommacommand[\getvalue{\??db#1\c!velden}]\docommand
+ \let\setrecordentry\skiprecord
+ \the\resetrecordlist
+ \doifelse{#2}\v!all % 't Is nu eenmaal alles
+ \recordoktrue
+ {\doifelsenothing{#2} % of niets
+ \recordoktrue
+ \recordokfalse}% % zullen we maar zeggen.
+ \ifrecordok
+ \let\askedrecords\v!all
+ \else
+ \makerawcommalist[#2]\askedrecords
+ \fi
+ \def\checkrecord##1%
+ {\rawdoifinsetelse{##1}{\askedrecords}{\recordoktrue}{}}%
+ \def\presetrecord##1%
+ {\let\setrecordentry\assignrecordentry
+ \let\memberofgroup\gobbleoneargument
+ \the\resetrecordlist
+ \def\stoprecord{\dostoprecord{##1}}}%
+ \def\memberofgroup##1%
+ {\doifsomething{##1}
+ {\rawprocesscommalist[##1]\checkrecord}%
+ \ifrecordok
+ \presetrecord{##1}%
+ \else
+ \expandafter\skiprecord
+ \fi}%
+ \def\startrecord##1%
+ {\bgroup
+ \ifrecordok
+ \presetrecord{##1}%
+ \else
+ \checkrecord{##1}%
+ \ifrecordok
+ \presetrecord{##1}%
+ \fi
+ \fi}%
+ \def\dostoprecord##1%
+ {\relax
+ \egroup
+ %\the\everyrecord
+ \getvalue{\??db#1\c!command}{##1}}%
+ \showmessage\m!databases1\askedrecords
+ \def\doprocessrecords##1%
+ {\readjobfile{##1}
+ {\showmessage\m!databases2{(job)}}
+ {\readsysfile{##1}
+ {\showmessage\m!databases3{(sys)}}
+ {\showmessage\m!databases4{}}}}%
+ \processcommalist[#3]\doprocessrecords
+ \egroup}
+
+%D While writing the original implementation, I did some
+%D experiments with \type {%} before each entry and changing
+%D the category code of the comment char. Because \TEX\ scans
+%D the line anyway |<|this is needed because the end of line
+%D character can be non standard|>| this is not faster.
+%D
+%D Although this mechanism could have been combined with the
+%D block moving mechanism, the current implementation is
+%D prefered out of speed reasons.
+
+\protect \endinput
diff --git a/tex/context/base/m-directives.tex b/tex/context/base/m-directives.tex
new file mode 100644
index 000000000..c958f6cad
--- /dev/null
+++ b/tex/context/base/m-directives.tex
@@ -0,0 +1,5 @@
+\doifnotmode{mkiv} {\endinput}
+
+\starttext
+ \showdirectives
+\stoptext
diff --git a/tex/context/base/m-dratex.tex b/tex/context/base/m-dratex.tex
new file mode 100644
index 000000000..6c088daf9
--- /dev/null
+++ b/tex/context/base/m-dratex.tex
@@ -0,0 +1,21 @@
+%D \module
+%D [ file=m-dratex,
+%D version=2005.11.25,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\DRATEX\ Loading Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details
+
+\readfile{DraTex.sty}{}{\readfile{dratex.sty}{}{\endinput}}
+
+\letvalue{:NewCount}\newcount
+\letvalue{:NewDimen}\newdimen
+
+\readfile{AlDraTex.sty}{}{\readfile{aldratex.sty}{}{\endinput}}
+
+\endinput
diff --git a/tex/context/base/m-edtsnc.tex b/tex/context/base/m-edtsnc.tex
new file mode 100644
index 000000000..0926f4488
--- /dev/null
+++ b/tex/context/base/m-edtsnc.tex
@@ -0,0 +1,207 @@
+%D \module
+%D [ file=m-editsnc,
+%D version=2003.12.23,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Editor Synchronization,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.edit for
+%C details.
+
+% \enablemode[demo]
+
+% This file is a variation of the file m-pdfsync. This time we do it
+% in a more abstract way and prepare ourselves for support in dvi
+% output.
+
+% \enableeditsync
+% \disableeditsync
+% \editsync
+% \editsynctext {string}
+% \editsyncnode {char}
+% \editsynctracemode [chardef: 0-4]
+
+\writestatus{editsync}{loading and enabling editor synchronization support}
+
+\unprotect % not really needed
+
+\ifx\pdfoutput\undefined
+ \donefalse
+\else\ifcase\pdfoutput
+ \donefalse
+\else\ifx\pdfsavepos\undefined
+ \donefalse
+\else
+ \donetrue
+\fi\fi\fi
+
+\chardef \editsyncstate \zerocount
+\chardef \editsynctracemode \zerocount
+\newcount \editsynccounter
+\newwrite \editsyncwrite
+
+\def\enableeditsync {\chardef\editsyncstate\plusone}
+\def\disableeditsync{\chardef\editsyncstate\zerocount}
+
+% The following definitions can go into the special drivers, but
+% for the moment we do it this way.
+
+\ifdone
+
+ \def\dostarteditsync
+ {\immediate\openout\editsyncwrite\jobname.pdfsync
+ \immediate\write\editsyncwrite{\jobname}%
+ \immediate\write\editsyncwrite{version 0}}
+
+ \def\dostopeditsync
+ {\closeout\editsyncwrite}
+
+ \def\doeditsyncregisterpage#1{\immediate\write\editsyncwrite{s\space\number#1}}
+ \def\doeditsyncopenfile #1{\immediate\write\editsyncwrite{(\space#1}}
+ \def\doeditsyncclosefile #1{\immediate\write\editsyncwrite{)}}
+
+ \def\doregistereditsyncnode#1#2#3% tag counter linenumber
+ {\pdfsavepos
+ \immediate\write\editsyncwrite{l\space\number#2\space\number#3}%
+ \expanded{\write\editsyncwrite{p\ifnum#1=\plusone*\fi\space\number#2\space\noexpand\the\pdflastxpos\space\noexpand\the\pdflastypos}}}
+
+\else
+
+ \let\dostarteditsync \relax
+ \let\dostopeditsync \relax
+
+ \let\doeditsyncregisterpage\gobbleoneargument
+ \let\doeditsyncopenfile \gobbleoneargument
+ \let\doeditsyncclosefile \gobbleoneargument
+ \let\doregistereditsyncnode\gobblethreearguments
+
+ % These specials could be filtered by a dvitopdf backend and
+ % written to a jobname.pdfsync file. In that case, the x and
+ % y coordinates have to be to be resolved by driver.
+
+ % \def\doeditsyncregisterpage#1{\special{pdfsync: s\space\number#1}}
+ % \def\doeditsyncopenfile #1{\special{pdfsync: ( #1}}
+ % \def\doeditsyncclosefile #1{\special{pdfsync: )}}
+
+ % \def\doregistereditsyncnode#1#2#3%
+ % {\special{pdfsync: l the\editsynccounter\space\number#3}%
+ % \special{pdfsync: p\ifnum#1=\plusone*\fi\space\number#2}}
+
+\fi
+
+\let\editsynctracer\gobbleoneargument
+
+\editsynccounter\minusone % counting starts at zero and we increment beforehand
+
+\def\registereditsyncnode#1% we assume #1 is one token
+ {\ifcase\editsyncstate
+ \expandafter\gobbleoneargument
+ \else
+ \global\advance\editsynccounter\plusone
+ \doregistereditsyncnode#1\editsynccounter\inputlineno
+ \expandafter\editsynctracer
+ \fi}
+
+\def\editsync {\registereditsyncnode\plusone *}
+\def\editsyncnode{\registereditsyncnode\zerocount}
+\def\editsynctext{\registereditsyncnode\plusone }
+
+\appendtoks \dostarteditsync \to \everystarttext
+%appendtoks \dostopeditsync \to \everystoptext
+\appendtoks \doeditsyncregisterpage\realfolio \to \everyshipout
+\appendtoks \doeditsyncopenfile\readfilename \to \everybeforereadfile
+\appendtoks \doeditsyncclosefile\readfilename \to \everyafterreadfile
+
+\appendtoks \enableeditsync \to \everystarttext
+\appendtoks \disableeditsync \to \everypagebody
+
+\def\editsynctracer#1%
+ {\ifcase\editsynctracemode\else
+ \begingroup
+ \forgetall
+ \disableeditsync
+ \ifcase\editsynctracemode\or % could be done more efficient, box around ifcase
+ \setbox\scratchbox\hbox to \zeropoint{\hss\infofont#1\hss}% 1
+ \else
+ \setbox\scratchbox\hbox to \zeropoint{\hss\traceboxplacementtrue\boxcursor\hss}% 2/3/4
+ \fi
+ \smashbox\scratchbox\box\scratchbox
+ \ifcase\editsynctracemode\or\or\or
+ \setbox\scratchbox\hbox to \zeropoint{\hss\raise1.25ex\hbox{\infofont#1}\hss}% 3
+ \smashbox\scratchbox\box\scratchbox
+ \or
+ \setbox\scratchbox\hbox to \zeropoint{\hss\lower1.25ex\hbox{\infofont#1}\hss}% 4
+ \smashbox\scratchbox\box\scratchbox
+ \fi
+ \endgroup
+ \fi}
+
+% \def\editsynctracer#1% more efficient but unreadable
+% {\ifcase\editsynctracemode\else
+% \ifcase\editsyncstate\else
+% \begingroup
+% \forgetall
+% \disableeditsync
+% \setbox\scratchbox\hbox to \zeropoint
+% {\hss
+% \ifcase\editsynctracemode\or
+% \infofont#1% 1
+% \else
+% \traceboxplacementtrue\boxcursor% 2/3/4
+% \fi
+% \hss}%
+% \smashbox\scratchbox\box\scratchbox
+% \setbox\scratchbox\hbox to \zeropoint
+% {\hss
+% \ifcase\editsynctracemode\or\or\or
+% \raise1.25ex\hbox{\infofont#1}% 3
+% \or
+% \lower1.25ex\hbox{\infofont#1}% 4
+% \fi
+% \hss}%
+% \smashbox\scratchbox\box\scratchbox
+% \endgroup
+% \fi
+% \fi}
+
+% beware, adding nodes this way will interfere with the typesetting
+
+\appendtoks \editsyncnode p\to \everypar
+\appendtoks \editsyncnode m\to \everymath
+\appendtoks \editsyncnode d\to \everydisplay
+\appendtoks \editsyncnode h\to \everyhbox
+
+% For compatibility with 'pdfsync4context' we provide:
+
+\let\pdfsyncstart\enableeditsync
+\let\pdfsyncstop \disablepdfsync
+\let\pdfsync \editsync
+
+\protect
+
+\doifnotmode{demo}{\endinput}
+
+\chardef\editsynctracemode=3
+
+\starttext
+
+\chapter{Test}
+
+\processfile{tufte}
+
+\startitemize
+\item first
+\item second
+\stopitemize
+
+\processfile{tufte}
+
+\startlines
+some local \editsync sync and \editsynctext{here}a marked point
+some local \editsync sync and \editsyncnode{here}a marked point
+\stoplines
+
+\stoptext
diff --git a/tex/context/base/m-educat.tex b/tex/context/base/m-educat.tex
new file mode 100644
index 000000000..ddfb72ff4
--- /dev/null
+++ b/tex/context/base/m-educat.tex
@@ -0,0 +1,217 @@
+%D \module
+%D [ file=m-educat,
+%D version=2003.03.05,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Educational Extras,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 will collect a few macros cq.\ definitions
+%D meant for educational use. Most of the code has been laying
+%D around for some time and has been (or is still) used in
+%D \PRAGMA\ projects.
+
+\unprotect
+
+\definesystemvariable{iv}
+
+\definecolor [answerareacolor] [s=.90]
+\definecolor [answerlinecolor] [white]
+
+\definetextbackground
+ [\v!answerarea]
+ [\c!location=\v!text,
+ \c!n=0,
+ \c!frame=\v!off,
+ \c!framecolor=answerlinecolor,
+ \c!rulethickness=2pt,
+ \c!background=\v!color,
+ \c!backgroundcolor=answerareacolor,
+ \c!alternative=2] % betweenline
+
+% n=gedwongen
+% m=extra auto
+
+\def\setupanswerarea
+ {\setuptextbackground[\v!answerarea]}
+
+\setvalue\e!answerspace
+ {\dosingleempty\doanswerspace}
+
+\def\doanswerspace[#1]%
+ {\begingroup
+ \dontcomplain
+ \setupanswerarea
+ [\c!n=0,\c!m=,#1,\c!location=\v!text]%
+ \doifelsenothing{\backgroundvariable\c!m}
+ {\expandafter\donoanswerspace}
+ {\expandafter\dodoanswerspace}%
+ [#1]}
+
+\def\donoanswerspace[#1]#2%
+ {\setupthinrules
+ [\c!alternative=\backgroundvariable\c!alternative,
+ \c!color=\backgroundvariable\c!framecolor,
+ \c!background=\backgroundvariable\c!background,
+ \c!backgroundcolor=\backgroundvariable\c!backgroundcolor,
+ \c!rulethickness=\backgroundvariable\c!rulethickness]%
+ \doifelse{\backgroundvariable\c!n}{*}
+ {\thinrule
+ \par}
+ {\scratchcounter0\backgroundvariable\c!n\relax
+ % tricky, guess
+ \def\processisolatedword##1%
+ {\setbox\scratchbox=\hbox{##1}%
+ \vbox{\hsize\wd\scratchbox\thinrule
+ \ifcase\scratchcounter\else
+ \setbox\scratchbox=\hbox{\space}%
+ \nobreak\hskip\zeropoint \!!minus \wd\scratchbox
+ \vbox{\hsize\wd\scratchbox\thinrule}%
+ \fi}}%
+ \processisolatedwords{#2}\processisolatedword
+ % so far
+ \ifcase\scratchcounter \else \ifnum\scratchcounter<3
+ \nobreak \vbox{\hsize\scratchcounter em\thinrule}%
+ \else % more
+ \advance \scratchcounter -2
+ \dorecurse\scratchcounter{\allowbreak\vbox{\hsize1em\thinrule}}%
+ \nobreak \vbox{\hsize2em\thinrule}%
+ \fi \fi}%
+ \endgroup}
+
+\def\dodoanswerspace[#1]#2% m case
+ {\getvalue{\e!start\v!answerarea}%
+ #2%
+ \doifelse{\backgroundvariable\c!m}{*}
+ {\hfill\strut
+ \getvalue{\e!stop\v!answerarea}%
+ \par}
+ {\scratchcounter0\backgroundvariable\c!m\relax
+ \ifcase\scratchcounter \else \ifnum\scratchcounter<3
+ \nobreak \hbox to \scratchcounter em{\strut\hss}%
+ \else % more
+ \advance \scratchcounter -2
+ \dorecurse\scratchcounter{\allowbreak\hbox to 1em{\strut\hss}}%
+ \nobreak \hbox to 2em{\strut\hss}%
+ \fi \fi
+ \getvalue{\e!stop\v!answerarea}}%
+ \endgroup}
+
+\setvalue{\e!start\e!answerlines}%
+ {\dosingleempty\dostartanswerlines}
+
+\def\dostartanswerlines[#1]%
+ {\begingroup
+ \dontcomplain
+ \setupanswerarea
+ [\c!n=0,\c!m=,#1,\c!location=\v!text]%
+ \doifnot{\backgroundvariable\c!option}\v!joinedup\softbreak
+ \doifelsenothing{\backgroundvariable\c!m}
+ {\expandafter\donostartanswerlines}
+ {\expandafter\dodostartanswerlines}%
+ [#1]}
+
+\def\donostartanswerlines[#1]%
+ {\setupthinrules
+ [\c!alternative=\backgroundvariable\c!alternative,
+ \c!color=\backgroundvariable\c!framecolor,
+ \c!background=\backgroundvariable\c!background,
+ \c!backgroundcolor=\backgroundvariable\c!backgroundcolor,
+ \c!rulethickness=\backgroundvariable\c!rulethickness]%
+ \thinrules[\c!n=\backgroundvariable\c!n]\par
+ \endgroup
+ \grabuntil{\e!stop\e!answerlines}}
+
+\def\dodostartanswerlines[#1]%
+ {\begingroup
+ \getvalue{\e!start\v!answerarea}%
+ \ignorespaces}
+
+\setvalue{\e!stop\e!answerlines}%
+ {\scratchcounter0\backgroundvariable\c!m\relax
+ % a \softbreak is more efficient in pos dan \par
+ \ifcase\scratchcounter
+ % nothing
+ \or
+ \softbreak
+ \else
+ \softbreak
+ \advance \scratchcounter \minusone
+ \dorecurse\scratchcounter{\strut\hfill\strut\softbreak}%
+ \fi
+ \strut\hfill\strut
+ \getvalue{\e!stop\v!answerarea}%
+ \par\endgroup\endgroup}
+
+\setvalue\e!answerlines
+ {\dosingleempty\doanswerlines}
+
+\def\doanswerlines[#1]#2%
+ {\getvalue{\e!start\e!answerlines}[#1]%
+ #2%
+ \getvalue{\e!stop\e!answerlines}}
+
+\protect \doifnotmode{demo}{\endinput}
+
+%D Test materiaal.
+
+\starttext
+
+\startnotmode[answers]
+
+ \setupanswerarea[level=+1]
+
+\stopnotmode
+
+\setupcolors[state=start]
+
+test test test \answerspace [n=10] {Whow}. test test test
+test tets test test \answerspace [n=10] {Whow}. test test
+test test tets test test \answerspace [n=10] {Whow}. test
+test test test tets test test \answerspace [n=10] {Whow}.
+test test test test test test \answerspace [n=*] {Whow.}
+
+test test test test test test test \startanswerlines
+[n=3] What A Junk Answer \stopanswerlines
+
+test test test test test test test \startanswerlines
+[n=3,alternative=0] What A Junk Answer \stopanswerlines
+
+test test test test test test test \startanswerlines
+[n=3,alternative=1] What A Junk Answer \stopanswerlines
+
+test test test test test test test \startanswerlines
+[n=3,alternative=2] What A Junk Answer \stopanswerlines
+
+\startitemize[paragraph]
+\item \startanswerlines [option=seried,n=2] xxx \stopanswerlines
+\stopitemize
+
+test test test \answerspace [m=10] {Whow}. test test test
+test tets test test \answerspace [m=10] {Whow}. test test
+test test tets test test \answerspace [m=10] {Whow}. test
+test test test tets test test \answerspace [m=10] {Whow}.
+test test test test test test \answerspace [m=*] {Whow.}
+
+test test test test test test test \startanswerlines
+[m=2] What A Junk Answer \stopanswerlines
+
+test test test test test test test \startanswerlines
+[m=2,alternative=0] What A Junk Answer \stopanswerlines
+
+test test test test test test test \startanswerlines
+[m=2,alternative=1] What A Junk Answer \stopanswerlines
+
+test test test test test test test \startanswerlines
+[m=2,alternative=2] What A Junk Answer \stopanswerlines
+
+\startitemize[paragraph]
+\item \startanswerlines [option=seried,m=2] xxx \stopanswerlines
+\stopitemize
+
+\stoptext
diff --git a/tex/context/base/m-format.tex b/tex/context/base/m-format.tex
new file mode 100644
index 000000000..0f274b236
--- /dev/null
+++ b/tex/context/base/m-format.tex
@@ -0,0 +1,409 @@
+%D \module
+%D [ file=m-formay,
+%D version=ancient,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Ancient Formatting Code,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Here is some code that I had laying around and had forgotten
+%D about. Let's make it a module and see if there is interest in
+%D such things.
+
+% \defineformatblock [poem]
+% \defineformatsegment [verse] % [poem]
+% \defineformatline [line] % [verse]
+%
+% \startpoem [title] [author]
+% \startverse [ref]
+% \startline [ref]
+%
+% block : voor na tussen *tekstletter *tekstkleur
+%
+% segment : voor na tussen *tekstletter *tekstkleur
+% : links rechts linkeroffset rechteroffset
+% : ?marge *evenmarge *onevenmarge breedte
+% : nummer *nummercommando *conversie
+% : nummerletter nummerkleur *label
+%
+% line : voor na tussen *tekstletter *tekstkleur
+% : nummer *nummercommando *conversie
+% : nummerletter nummerkleur *label
+%
+% * = todo
+
+\unprotect
+
+\definesystemvariable {fx} % format block
+\definesystemvariable {fy} % format segment
+\definesystemvariable {fz} % format line
+
+\def\defineformatblock
+ {\dodoubleempty\dodefineformatblock}
+
+\def\dodefineformatblock[#1][#2]%
+ {\setupformatblock
+ [#1]
+ [\c!before=\blank,\c!after=\blank,\c!inbetween=\blank,
+ \c!textstyle=,\c!textcolor=,#2]%
+ \setvalue{\e!start#1}{\startformatblock[#1]}%
+ \setvalue{\e!stop #1}{\stopformatblock}}
+
+\def\setupformatblock
+ {\dodoubleempty\dosetupformatblock}
+
+\def\setupformatblock[#1]%
+ {\getparameters[\??fx#1]}
+
+\def\startformatblock[#1]%
+ {\dotriplegroupempty\dostartformatblock{#1}}
+
+\def\dostartformatblock#1#2#3
+ {\bgroup
+ \getvalue{\??fx#1\c!before}
+ \doglobal\newcounter\formatsegmentcounter
+ \doglobal\newcounter\formatlinecounter
+ \doglobal\newcounter\formatlinesubcounter
+ \doglobal\newcounter\formatlinemaxcounter
+ \doifsomething{#2}{\leftaligned{#2}\getvalue{\??fx#1\c!inbetween}}
+ \def\stopformatblock%
+ {\doifsomething{#3}{\getvalue{\??fx#1\c!inbetween}\leftaligned{#3}}
+ \getvalue{\??fx#1\c!after}
+ \egroup}}
+
+\def\defineformatsegment
+ {\dodoubleempty\dodefineformatsegment}
+
+\def\dodefineformatsegment[#1][#2]%
+ {\setupformatsegment
+ [#1]
+ [\c!before=\blank,\c!after=\blank,\c!inbetween=\blank,
+ \c!textstyle=,\c!textcolor=,\c!left=,\c!right=,
+ \c!leftoffset=\!!zeropoint,\c!rightoffset=\!!zeropoint,
+ %\c!margin=\!!zeropoint,\c!evenmargin=\!!zeropoint,\c!oddmargin=\hsize,
+ \c!width=\hsize,\c!numberstyle=,\c!numbercolor=,\c!number=\v!no,
+ \c!numbercommand=,\c!conversion=,\c!label=,
+ #2]%
+ \setvalue{\e!start#1}{\startformatsegment[#1]}%
+ \setvalue{\e!stop #1}{\stopformatsegment}}
+
+\def\setupformatsegment
+ {\dodoubleempty\dosetupformatsegment}
+
+\def\setupformatsegment[#1]%
+ {\getparameters[\??fy#1]}
+
+\def\placeformatsegmentcounter
+ {\formatsegmentcounter\quad\hphantom{\placeformatlinecounter}}
+
+\def\placeformatlinecounter
+ {\formatlinecounter}
+
+\def\startformatsegment[#1]%
+ {\bgroup
+ \doifelsevalue{\??fy#1\c!number}\v!yes
+ {\def\doplaceformatsegmentcounter
+ {\inleftmargin
+ {\doattributes{\??fy#1}\c!numberstyle\c!numbercolor
+ {\placeformatsegmentcounter}}}}
+ {\let\doplaceformatsegmentcounter\relax}%
+ \getvalue{\??fy#1\c!before}
+ \doglobal\increment\formatsegmentcounter
+ \def\formatrightoffset{\getvalue{\??fy#1\c!rightoffset}}
+ \def\formatleftoffset {\getvalue{\??fy#1\c!leftoffset}}
+ \def\formatminwidth {\getvalue{\??fy#1\c!minwidth}}
+ \def\formatwidth {\getvalue{\??fy#1\c!width}}
+ %\def\formatmargin {\getvalue{\??fy#1\c!margin}}
+ \def\formatbefore {\getvalue{\??fy#1\c!before}}
+ \def\formatinbetween {\getvalue{\??fy#1\c!inbetween}}
+ \def\formatafter {\getvalue{\??fy#1\c!after}}
+ \def\formatleft {\getvalue{\??fy#1\c!left}}
+ \def\formatright {\getvalue{\??fy#1\c!right}}
+ \@@segmentvarianta
+ \getvalue{@@segmentvariant\getvalue{\??fy#1\c!alternative}}
+ \def\stopformatsegment
+ {\getvalue{\??fy#1\c!after}
+ \egroup}}
+
+\newif\iftraceformatblock
+
+\def\@@segmentvarianta % ragged right, symbols
+ {\let\formatraggedness\raggedright
+ \let\dostartformatline\dostartformatlineab
+ \let\formatleftfirst\relax \let\formatrightfirst\hfill
+ \let\formatleftnext \hfill \let\formatrightnext \relax}
+
+\def\@@segmentvariantb % ragged right, equal parts, symbols
+ {\let\formatraggedness\raggedcenter
+ \let\dostartformatline\dostartformatlineab
+ \let\formatleftfirst\relax \let\formatrightfirst\hfill
+ \let\formatleftnext \hfill \let\formatrightnext \relax}
+
+\def\@@segmentvariantc % ragged right
+ {\let\formatraggedness\veryraggedright
+ \let\dostartformatline\dostartformatlinecde
+ \let\formatleftnext\relax \let\formatrightnext\hfill}
+
+\def\@@segmentvariantd % ragged center
+ {\let\formatraggedness\veryraggedcenter
+ \let\dostartformatline\dostartformatlinecde
+ \let\formatleftnext\hfill \let\formatrightnext\hfill}
+
+\def\@@segmentvariante % ragged left
+ {\let\formatraggedness\veryraggedleft
+ \let\dostartformatline\dostartformatlinecde
+ \let\formatleftnext\hfill \let\formatrightnext\relax}
+
+\def\defineformatline
+ {\dodoubleempty\dodefineformatline}
+
+\def\dodefineformatline[#1][#2]%
+ {\setupformatline
+ [#1]
+ [\c!before=\blank,\c!after=\blank,\c!inbetween=\blank,
+ \c!textstyle=,\c!textcolor=,
+ \c!number=\v!no,\c!numbercommand=,\c!conversion=,
+ \c!numberstyle=,\c!numbercolor=,\c!label=,
+ #2]%
+ \setvalue{\e!start#1}{\startformatline[#1]}%
+ \setvalue{\e!stop #1}{\stopformatline}}
+
+\def\setupformatline
+ {\dodoubleempty\dosetupformatline}
+
+\def\setupformatline[#1]%
+ {\getparameters[\??fz#1]}
+
+\newconditional\formatforcedbreak
+
+\def\startformatline[#1]%
+ {\bgroup
+ \doifelsevalue{\??fz#1\c!number}\v!yes
+ {\def\doplaceformatlinecounter
+ {\inleftmargin
+ {\doattributes{\??fz#1}\c!numberstyle\c!numbercolor
+ {\placeformatlinecounter}}}}
+ {\let\doplaceformatlinecounter\relax}%
+ \global\setfalse\formatforcedbreak
+ \def\\{\break\global\settrue\formatforcedbreak}%
+ \hsize\formatwidth
+ \doglobal\increment\formatlinecounter
+ \par
+ \nobreak
+ \def\stopformatline
+ {\unskip\unskip\unskip\unskip\unskip\egroup
+ \let\doplaceformatsegmentcounter\relax}
+ \postponenotes
+ \dowithnextbox{\dostartformatline}\hbox\bgroup\ignorespaces}
+
+\def\dostartformatlineab
+ {%\dosetleftskipadaption\formatmargin
+ %\advance\hsize-\leftskipadaption\relax
+ \ifdim\nextboxwd>\hsize
+ \beginofshapebox
+ \forgetall
+ \hangafter\plusone
+ \hangindent\formatleftoffset
+ \formatraggedness
+ \hskip\formatrightoffset
+ \unhbox\nextbox\par
+ \endofshapebox
+ %\advance\hsize \leftskipadaption
+ \doglobal\newcounter\formatlinesubcounter
+ \reshapebox
+ {\doglobal\increment\formatlinesubcounter}
+ \global\let\formatlinemaxcounter\formatlinesubcounter
+ \reshapebox
+ {\doglobal\decrement\formatlinesubcounter
+ \ifnum\formatlinesubcounter=\zerocount
+ \doplaceformatsegmentcounter
+ \doplaceformatlinecounter
+ \hskip-\formatrightoffset
+ %\hskip\leftskipadaption
+ \formatleftfirst
+ \unhbox\shapebox
+ \ifnum\formatlinemaxcounter>\plusone
+ \ifx\formatright\empty\else
+ \shapedhbox to \zeropoint{\formatright\hss}%
+ \fi
+ \fi
+ \formatrightfirst
+ \iftraceformatblock
+ \ruledhskip\formatrightoffset\hskip-\formatrightoffset
+ \fi
+ \else
+ %\hskip\leftskipadaption
+ \iftraceformatblock
+ \ruledhskip\formatleftoffset\hskip-\formatleftoffset
+ \fi
+ \formatleftnext
+ \ifx\formatleft\empty\else
+ \shapedhbox to \zeropoint{\hss\formatleft}%
+ \fi
+ \unhbox\shapebox
+ \formatrightnext
+ \fi}
+ \flushshapebox
+ \else
+ \dontleavehmode\hbox
+ {\doplaceformatsegmentcounter
+ \doplaceformatlinecounter
+ %\hskip\leftskipadaption
+ \formatleftfirst
+ \unhbox\nextbox
+ \formatrightfirst}
+ \fi
+ \par
+ \egroup}
+
+\def\dostartformatlinecde
+ {%\dosetleftskipadaption\formatmargin
+ %\advance\hsize -\leftskipadaption\relax
+ \dimen0=\hsize
+ \ifconditional\formatforcedbreak\else
+ \ifdim\formatminwidth>\zeropoint\relax
+ \ifdim\nextboxwd>\hsize
+ \doloop
+ {\global\dimen1=\dimen0
+ \beginofshapebox
+ \hsize\dimen0
+ \forgetall
+ \formatraggedness
+ \unhcopy\nextbox\par
+ \endofshapebox
+ \reshapebox
+ {\setbox\scratchbox=\hbox{\unhbox\shapebox}%
+ \ifdim\wd\scratchbox<\dimen1
+ \global\dimen1=\wd\scratchbox
+ \fi}
+ \ifdim\dimen1<\formatminwidth\relax
+ \advance\dimen0 by -.25em
+ \else
+ \exitloop
+ \fi
+ \ifdim\dimen0<10em
+ \dimen0=\hsize
+ \exitloop
+ \fi}
+ \fi
+ \fi
+ \fi
+ \beginofshapebox
+ \hsize\dimen0
+ \forgetall
+ \formatraggedness
+ \unhcopy\nextbox\par
+ \endofshapebox
+ %\advance\hsize \leftskipadaption
+ \doglobal\newcounter\formatlinesubcounter
+ \reshapebox
+ {\doglobal\increment\formatlinesubcounter}%
+ \global\let\formatlinemaxcounter\formatlinesubcounter
+ \reshapebox
+ {\doglobal\decrement\formatlinesubcounter
+ \ifnum\formatlinesubcounter=\zerocount
+ \doplaceformatsegmentcounter
+ \doplaceformatlinecounter
+ \fi
+ %\hskip\leftskipadaption
+ \formatleftnext
+ \unhbox\shapebox
+ \formatrightnext\strut}% strut prevents unskip
+ \flushshapebox
+ \par
+ \egroup}
+
+\defineformatblock[poem]
+ [\c!before=\blank,
+ \c!inbetween={\blank[\v!medium]},
+ \c!after=\blank]
+
+\defineformatsegment[verse]
+ [\c!alternative=\v!left,
+ \c!width=\hsize,
+ %\c!margin=\!!zeropoint,
+ \c!before={\blank[\v!medium]},
+ \c!after={\blank[\v!medium]},
+ \c!inbetween={\blank[\v!medium]},
+ \c!leftoffset=3em,
+ \c!rightoffset=2em,
+ \c!minwidth=5em,
+ \c!left={$[$\enspace},
+ \c!right={\enspace$]$}]
+
+\defineformatline[line]
+ []
+
+\protect \doifnotmode{demo} {\endinput}
+
+% evt defineblank[formatbefore,formatinbetween,formatafter]
+
+%\showframe \traceformatblocktrue
+
+\usemodule[visual]
+
+\setuplayout[height=middle,topspace=1cm,header=0pt,footer=0pt]
+\setupbodyfont[10pt]
+
+% All interfaces supported, but testing with english; todo:
+% more options, more alternatives, inheritance and mixed
+% definitions, and so.
+
+\starttext
+
+\startbuffer
+\startbuffer[poem]
+\startpoem{A Random Poem}{Hans Hagen}
+ \startverse
+ \startline \fakewords{4}{8} \stopline
+ \startline \fakewords{4}{8} \stopline
+ \startline \fakewords{4}{8} \stopline
+ \startline \fakewords{4}{8} \stopline
+ \stopverse
+ \startverse
+ \startline \fakewords{4}{8} \stopline
+ \startline \fakewords{4}{8} \stopline
+ \startline \fakewords{4}{8} \stopline
+ \startline \fakewords{4}{8} \stopline
+ \stopverse
+\stoppoem
+\stopbuffer
+
+\setupformatsegment[verse][width=.4\hsize,number=yes,numberstyle=slanted]
+\setupformatline [line] [number=yes,numberstyle=smallslanted]
+
+\startbuffer[x]
+\setupformatsegment[verse][leftoffset=0pt,rightoffset=0pt,left=,right=]
+\stopbuffer
+
+\section{Alternative A}
+
+\setupformatsegment[verse][alternative=a] {\getbuffer[poem]}
+\setupformatsegment[verse][alternative=a] {\getbuffer[x,poem]}
+
+\section{Alternative B}
+
+\setupformatsegment[verse][alternative=b] {\getbuffer[poem]}
+\setupformatsegment[verse][alternative=b] {\getbuffer[x,poem]}
+
+\section{Alternative C}
+
+\setupformatsegment[verse][alternative=c] {\getbuffer[poem]}
+
+\section{Alternative D}
+
+\setupformatsegment[verse][alternative=d] {\getbuffer[poem]}
+
+\section{Alternative E}
+
+\setupformatsegment[verse][alternative=e] {\getbuffer[poem]}
+\stopbuffer
+
+\typebuffer \getbuffer
+
+\stoptext
diff --git a/tex/context/base/m-graph.mkii b/tex/context/base/m-graph.mkii
new file mode 100644
index 000000000..db7538e98
--- /dev/null
+++ b/tex/context/base/m-graph.mkii
@@ -0,0 +1,72 @@
+%D \module
+%D [ file=m-graph,
+%D version=2000.08.06,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\METAPOST\ graph module support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 I finally finished graph support, if only because I could
+%D not stand the idea that Karel Wesseling would revert to
+%D \PiCTeX.
+
+% pre 2000.08.06 version
+%
+% \forceMPTEXgraphictrue
+%
+% \startMPinitializations
+% initialize_numbers ; % make sure that pseudo typesetting is set up
+% input graph ; % load the graph package
+% Autoform := "@g" ; % change the % template char into @
+% \stopMPinitializations
+
+%D The latest version does things more automatically (and
+%D efficiently when no text processing is needed). For
+%D definitions embedded in your document, you need to
+%D use \type {@} as template character, in external files,
+%D \type {%} is also supported.
+
+\startMPinclusions
+ input graph ;
+\stopMPinclusions
+
+%D Graphics that have \type {begingraph} in them are
+%D recognized as such and force handling of embedded \TEX\
+%D code.
+
+\forceMPTEXcheck{begingraph}
+
+%D If you run into troubles, try:
+%D
+%D \starttyping
+%D \forceMPTEXgraphictrue
+%D \stoptyping
+%D
+%D A demo can be run with:
+%D
+%D \starttyping
+%D texexec --mode=demo --pdf m-graph
+%D \stoptyping
+
+\startMPinclusions
+ % @# is X_ or Y_; $ is Gxcvlin_ or Gycvlin_; l and h are numeric or string
+ % It would not be OK to set (@#low,@#high) to a pair expression because $ might
+ % try to rescale @#low when evaluating the right-hand side for @#high.
+ vardef Gsetr_@\#(suffix $)(expr l, h) =
+ Gclbnds_@\# ;
+ if @\#ctyp>0 :
+ @\#low = if abs @\#ctyp<>log: $ fi Mlog_Str l ;
+ @\#high = if abs @\#ctyp<>log: $ fi Mlog_Str h ;
+ else :
+ -@\#high = if abs @\#ctyp<>log: $ fi Mlog_Str l ;
+ -@\#low = if abs @\#ctyp<>log: $ fi Mlog_Str h ;
+ fi
+ enddef ;
+\stopMPinclusions
+
+\endinput
diff --git a/tex/context/base/m-graph.mkiv b/tex/context/base/m-graph.mkiv
new file mode 100644
index 000000000..c92234884
--- /dev/null
+++ b/tex/context/base/m-graph.mkiv
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=m-graph,
+%D version=2008.09.08,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\METAPOST\ graph module support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% We just assume lua specification instead of the graph ones that
+% are limited by what mp can do. We support @ as replacement for
+% the percent symbol. We also add a specifier when no one is given.
+
+\startluacode
+ local function strip(s)
+ return "\\times10^{"..(s:gsub("%+*0*","")).."}"
+ end
+ function metapost.format_n(fmt,str)
+ fmt = fmt:gsub("@","%%")
+ local initial, format, final = fmt:match("^(.-)(%%.-[%a])(.-)$")
+ if format then
+ str = fmt:format(str)
+ str = str:gsub("e(.-)$",strip)
+ str = ("%s\\mathematics{%s}%s"):format(initial,str,final)
+ elseif not fmt:find("%%") then
+ str = ("%"..fmt):format(str)
+ str = str:gsub("e(.-)$",strip)
+ str = ("\\mathematics{%s}"):format(str)
+ end
+ tex.sprint(str)
+ end
+\stopluacode
+
+\unexpanded\long\def\MPgraphformat#1#2{\ctxlua{metapost.format_n("#1","#2")}}
+
+\startMPinclusions
+ input graph.mp ;
+ vardef escaped_format(expr s) =
+ "" for n=1 upto length(s) : &
+ if ASCII substring (n,n+1) of s = 37 :
+ "@"
+ else :
+ substring (n,n+1) of s
+ fi
+ endfor
+ enddef ;
+ vardef dofmt_@\#(expr f, x) =
+ textext("\MPgraphformat{"&escaped_format(f)&"}{"&(if string x : x else: decimal x fi)&"}")
+ enddef ;
+
+ % vardef format(expr f, x) =
+ % textext("\MPgraphformatN{"&escaped_format(f)&"}{"&(if string x : x else: decimal x fi)&"}")
+ % enddef;
+ % vardef Mformat(expr f, x) =
+ % format(f,x)
+ % enddef;
+\stopMPinclusions
+
+\endinput
diff --git a/tex/context/base/m-graph.tex b/tex/context/base/m-graph.tex
new file mode 100644
index 000000000..6f71cca3c
--- /dev/null
+++ b/tex/context/base/m-graph.tex
@@ -0,0 +1,175 @@
+%D \module
+%D [ file=m-graph,
+%D version=2000.08.06,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\METAPOST\ graph module support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\loadmarkfile{m-graph}
+
+\doifnotmode {demo} {\endinput}
+
+%D You need to have the data files in your path,
+%D otherwise the run is aborted.
+
+\doiffileelse {agepop91.d} {} {\writestatus{graph}{no data files found}\wait\end}
+
+%D The test:
+
+\starttext
+
+\startMPpage
+draw begingraph(3in,2in);
+ gdraw "agepop91.d";
+ endgraph;
+\stopMPpage
+
+\startMPpage
+draw begingraph(3in,2in);
+ gdraw "agepop91.d" plot btex$\bullet$etex;
+ endgraph;
+\stopMPpage
+
+\startMPpage
+draw begingraph(3in,2in);
+ glabel.lft(btex \vbox{\hbox{Population} \hbox{in millions}} etex, OUT);
+ glabel.bot(btex Age in years etex, OUT);
+ gdraw "agepopm.d";
+ endgraph;
+\stopMPpage
+
+\startMPpage
+draw begingraph(3in,2in);
+ glabel.lft(btex \vbox{\hbox{Population} \hbox{in millions}} etex, OUT);
+ glabel.bot(btex Age in years etex, OUT);
+ setrange(origin, whatever,whatever);
+ gdraw "agepopm.d";
+ endgraph;
+\stopMPpage
+
+\startMPpage
+draw begingraph(2.3in,2in);
+ setcoords(log,log);
+ glabel.lft(btex Seconds etex,OUT);
+ glabel.bot(btex Matrix size etex,
+ OUT);
+ gdraw "matmul.d" dashed evenly;
+ glabel.ulft(btex Standard etex,8);
+ gdraw "matmul.d";
+ glabel.lrt(btex Strassen etex,7);
+ endgraph;
+\stopMPpage
+
+\startMPpage
+draw begingraph(6.5cm,4.5cm);
+ setrange(80,0, 90,whatever);
+ glabel.bot(btex Year etex, OUT);
+ glabel.lft(btex \vbox{\hbox{Emissions in} \hbox{thousands of}
+ \hbox{metric tons} \hbox{(heavy line)}}etex, OUT);
+ gdraw "lead.d" withpen pencircle scaled 1.5pt;
+ autogrid(,otick.lft);
+ setcoords(linear,linear);
+ setrange(80,0, 90,whatever);
+ glabel.rt(btex \vbox{\hbox{Micrograms} \hbox{per cubic}
+ \hbox{meter of air} \hbox{(thin line)}}etex, OUT);
+ gdraw "lead.d";
+ autogrid(otick.bot,otick.rt);
+ endgraph;
+\stopMPpage
+
+\stoptext
+
+% No longer needed, since John will fix it.
+%
+% %D For the moment we need the following patch. Adam T. Lindsay
+% %D found out that the following code produced an error:
+% %D
+% %D \starttyping
+% %D \startMPcode
+% %D draw begingraph(130mm,35mm);
+% %D setrange(0,0,10,22000);
+% %D glabel.lft(btex {correct 0--22000} etex rotated 90, OUT);
+% %D autogrid(itick.bot,grid.lft) withcolor .75white ;
+% %D endgraph;
+% %D \stopMPcode
+% %D
+% %D \startMPcode
+% %D draw begingraph(130mm,35mm);
+% %D setrange(0,50,10,22000);
+% %D glabel.lft(btex {wrong 50--22000} etex rotated 90, OUT);
+% %D autogrid(itick.bot,grid.lft) withcolor .75white ;
+% %D endgraph;
+% %D \stopMPcode
+% %D
+% %D \startMPcode
+% %D draw begingraph(130mm,35mm);
+% %D setrange(0,110,10,30000);
+% %D glabel.lft(btex {failed 110--22000} etex rotated 90, OUT);
+% %D autogrid(itick.bot,grid.lft) withcolor .75white ;
+% %D endgraph;
+% %D \stopMPcode
+% %D \stoptyping
+% %D
+% %D The bug is a rather nasty one and needs some tweaking in
+% %D the low level graph code. John Hobby suggested for the
+% %D moment to initialize \type {setrange} as follows:
+% %D
+% %D \starttyping
+% %D setrange(0,0,"22000","22000")
+% %D \stoptyping
+% %D
+% %D Folowing this suggesion, I provide the following
+% %D extension:
+
+% def begingraph(expr w, h) =
+% begingroup
+% save X_, Y_, Gfin_, Gcur_, Gcbb_, Gneedgr_, Gneedfr_, Gdidsc_;
+% save Gdpic_, Gppic_, Ggl_, Garw_;
+% picture Gfin_, Gcur_, Gcbb_, Gdpic_, Gppic_, Ggl_[];
+% boolean Gneedgr_, Gneedfr_, Gdidsc_;
+% Gfin_ = nullpicture;
+% Gcur_ = nullpicture;
+% Gcbb_ = nullpicture;
+% X_.ctyp = Y_.ctyp = linear;
+% Z_.gdim = (w,h);
+% X_.sc = Y_.sc = 0;
+% Gneedgr_ = true;
+% Gneedfr_ = true;
+% Gdidsc_ = false;
+% Gdpic_ = nullpicture;
+% Garw_ = 0;
+% scantokens everybegingraph ;
+% enddef;
+%
+% boolean fixsetrange ; fixsetrange := true ;
+%
+% vardef dosetrange(text t) =
+% interim warningcheck:=0;
+% save r_; r_=0;
+% string r_[]s;
+% for x_=
+% for p_=t: if pair p_: xpart p_, ypart fi p_, endfor:
+% r_[incr r_] if string x_: s fi = x_;
+% if r_>2:
+% Gsetr_ if r_=3: X_(Gxcvlin_) else: Y_(Gycvlin_) fi(
+% r_[r_-2] if unknown r_[r_-2]: s fi, x_);
+% fi
+% exitif r_=4;
+% endfor
+% enddef;
+%
+% vardef setrange(text t) =
+% if fixsetrange : dosetrange(0,0,20000,20000) ; fi ;
+% dosetrange(t) ;
+% enddef ;
+%
+% if unknown everybegingraph :
+% string everybegingraph ;
+% % everybegingraph := "setrange(0,0,20000,20000)" ;
+% fi ;
diff --git a/tex/context/base/m-layout.tex b/tex/context/base/m-layout.tex
new file mode 100644
index 000000000..0ee71da47
--- /dev/null
+++ b/tex/context/base/m-layout.tex
@@ -0,0 +1,102 @@
+%D \module
+%D [ file=m-layout,
+%D version=2004.01.16,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Additional Layouts,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA ADE/ Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% layout-preset - thf th tf
+
+%D This is a preliminary module, don't depend on these dimensions yet.
+
+\readsysfile{lang-frq}\donothing\donothing
+\readsysfile{lang-frd}\donothing\donothing
+
+\unprotect
+
+% \def\layouthwratio{\withoutpt\the\dimexpr8\paperheight/\dimexpr(\paperwidth/ 8192)\relax}
+% \def\layouthwratio{\withoutpt\the\dimexpr4\paperheight/\dimexpr(\paperwidth/16384)\relax}
+% \def\layouthwratio{\withoutpt\the\dimexpr2\paperheight/\dimexpr(\paperwidth/32768)\relax}
+
+\def\layouthwratio
+ {\withoutpt\the\dimexpr2\paperheight/(\paperwidth/32768)\relax}
+
+\def\layouthfheight
+ {\dimexpr\layoutparameter\c!header+\layoutparameter\c!headerdistance+
+ \layoutparameter\c!footer+\layoutparameter\c!footerdistance\relax}
+
+\startsetups[preset-1]
+
+ \xdef\layoutwidth {\dimexpr\layoutparameter\c!width\relax}
+ \gdef\layoutheight{\dimexpr\layouthwratio\dimexpr\layoutwidth\relax+\layouthfheight\relax}
+
+\stopsetups
+
+\definelayout
+ [preset-1-1]
+ [\c!preset=preset-1,
+ \c!backspace=\dimexpr(\paperwidth-\layoutwidth)/2\relax,
+ \c!width=\dimexpr2\paperwidth/3\relax,
+ \c!cutspace=\dimexpr(\paperwidth-\layoutwidth)/2\relax,
+ \c!margin=\dimexpr(\paperwidth-\layoutwidth)/3\relax,
+ \c!header=2\lineheight,
+ \c!headerdistance=\lineheight,
+ \c!height=\v!middle, % \layoutheight
+ \c!footerdistance=\layoutparameter\c!headerdistance, % \lineheight,
+ \c!footer=\layoutparameter\c!header, % 2\lineheight,
+ \c!topspace=\dimexpr1\dimexpr\paperheight-(\layoutheight+\layouthfheight)\relax/3\relax,
+ \c!bottomspace=\dimexpr2\dimexpr\paperheight-(\layoutheight+\layouthfheight)\relax/3\relax]
+
+\startsetups[preset-2]
+
+ \gdef\layouthstep{\dimexpr\paperwidth /\layoutparameter\c!columns\relax}
+ \gdef\layoutvstep{\dimexpr\paperheight/\layoutparameter\c!columns\relax}
+
+\stopsetups
+
+\definelayout
+ [preset-2-1]
+ [\c!preset=preset-2,
+ \c!columns=12,
+ \c!backspace=\layouthstep,
+ \c!width=\v!middle,
+ \c!cutspace=2\layouthstep,
+ \c!margin=\layouthstep,
+ \c!header=2\lineheight,
+ \c!headerdistance=\lineheight,
+ \c!height=\v!middle, % \layoutheight
+ \c!footerdistance=\layoutparameter\c!headerdistance,
+ \c!footer=\layoutparameter\c!header,
+ \c!topspace=\dimexpr\layoutvstep-\layoutparameter\c!header-\layoutparameter\c!headerdistance\relax,
+ \c!bottomspace=\dimexpr(2\layoutvstep)-\layoutparameter\c!header-\layoutparameter\c!headerdistance\relax]
+
+\definelayout
+ [preset-2-2]
+ [\c!preset=preset-2,
+ \c!columns=12,
+ \c!backspace=\layouthstep,
+ \c!width=\v!middle,
+ \c!cutspace=2\layouthstep,
+ \c!margin=\layouthstep,
+ \c!header=2\lineheight,
+ \c!headerdistance=\lineheight,
+ \c!height=\v!middle, % \layoutheight
+ \c!footerdistance=\layoutparameter\c!headerdistance,
+ \c!footer=\layoutparameter\c!header,
+ \c!topspace=\layoutvstep,
+ \c!bottomspace=\layoutvstep] % maybe 1.5
+
+% \setuplayout[preset-1-1] test \showframe \page
+% \setuplayout[preset-1-1][width=65\averagecharwidth] \setuplayout[preset-1-1] test \showframe \page
+% \setuplayout[preset-2-1] test \showframe \page
+% \setuplayout[preset-2-1][columns=10] \setuplayout[preset-2-1] test \showframe \page
+% \setuplayout[preset-2-2] test \showframe \page
+% \setuplayout[preset-2-2][columns=10] \setuplayout[preset-2-2] test \showframe \page
+
+\protect \endinput
diff --git a/tex/context/base/m-level.tex b/tex/context/base/m-level.tex
new file mode 100644
index 000000000..67d598733
--- /dev/null
+++ b/tex/context/base/m-level.tex
@@ -0,0 +1,94 @@
+%D \module
+%D [ file=level,
+%D version=2002.10.20,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Catching Nesting Errors,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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
+
+\newcount\currentnesting
+
+\def\startnesting#1%
+ {\global\advance\currentnesting\plusone
+ \setxvalue{level::\number\currentnesting}{#1}}
+
+\def\stopnesting#1%
+ {\edef\nestingstring{#1}%
+ \relax\ifnum\currentnesting>\zerocount
+ \doifelsevalue{level::\number\currentnesting}\nestingstring
+ {\global\advance\currentnesting\minusone}
+ {\@EA\reportnestingerror\@EA\stoptext}
+ \else
+ \@EA\reportnestingerror\@EA\stoptext
+ \fi}
+
+\def\checknesting
+ {\relax\ifnum\currentnesting>\zerocount
+ \def\nestingstring{end of document}%
+ \@EA\reportnestingerror
+ \fi}
+
+\def\reportnestingerror
+ {\endgraf
+ \global\let\checknesting\relax
+ \bgroup \definedfont[Mono at 18pt]\incolortrue
+ \setupinterlinespace
+ \raggedright
+ \bgroup \red
+ \ifnum\currentnesting>\plusone
+ wrong end level
+ \else
+ too many end levels
+ \fi
+ at \nestingstring\space in line \number\inputlineno
+ \ifnum\currentnesting>\zerocount, stack:\fi\endgraf
+ \egroup
+ \dostepwiserecurse\currentnesting\plusone\minusone
+ {\space\getvalue{level::\recurselevel}}
+ \endgraf
+ \egroup
+ \writestatus\m!systems{quitting due to level error}\wait
+ \batchmode}
+
+\prependtoks
+ \checknesting
+\to \everystoptext
+
+\protect \doifnotmode{demo}{\endinput}
+
+\starttext
+
+% \startnesting{eerste}
+% \startnesting{tweede}
+% \startnesting{derde}
+% \startnesting{vierde}
+% test
+% \stopnesting{vierde}
+% \stopnesting{eerste}
+
+% \startnesting{eerste}
+% \startnesting{tweede}
+% test
+% \stopnesting{vierde}
+% \stopnesting{derde}
+% \stopnesting{tweede}
+% \stopnesting{eerste}
+
+\startnesting{eerste}
+ \startnesting{tweede}
+ \startnesting{derde}
+ \startnesting{vierde}
+ test
+ \stopnesting{vierde}
+ \stopnesting{derde}
+ \stopnesting{tweede}
+\stopnesting{eerste}
+
+\stoptext
diff --git a/tex/context/base/m-mkii.mkiv b/tex/context/base/m-mkii.mkiv
new file mode 100644
index 000000000..cb0da6fcb
--- /dev/null
+++ b/tex/context/base/m-mkii.mkiv
@@ -0,0 +1,21 @@
+% todo
+
+\unprotect
+
+\writestatus\m!systems{loading some mkii compatibility hacks}
+
+% Compatibility for font-ini
+
+\let\normalxi=\xi
+
+\definebodyfontswitch [xii] [\!!twelvepoint]
+\definebodyfontswitch [xi] [\!!elevenpoint]
+\definebodyfontswitch [x] [\!!tenpoint]
+\definebodyfontswitch [ix] [\!!ninepoint]
+\definebodyfontswitch [viii] [\!!eightpoint]
+\definebodyfontswitch [vii] [\!!sevenpoint]
+\definebodyfontswitch [vi] [\!!sixpoint]
+
+\unexpanded\def\xi{\ifmmode\normalxi\else\elevenpoint\fi}
+
+\protect \endinput
diff --git a/tex/context/base/m-mkivhacks.tex b/tex/context/base/m-mkivhacks.tex
new file mode 100644
index 000000000..f47658739
--- /dev/null
+++ b/tex/context/base/m-mkivhacks.tex
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=m-mkivhacks,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Temporary Compatilibility Hacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\doifnotmode{mkiv}{\endinput}
+
+%D For Aditya, who needed it for his thesis.
+
+\startluacode
+ -- -- a lot or work
+ --
+ -- mathematics.slots.euler = {
+ -- [0x03B1] = { "mr", 0x0B }, -- alpha
+ -- }
+ --
+ -- mathematics.slots.euler = table.merge(mathematics.slots.traditional,mathematics.slots.euler)
+ --
+ -- versus a quick hack
+
+ document.hacks = document.hacks or { }
+
+ function document.hacks()
+ mathematics.families.lcgreek = mathematics.families.mr
+ mathematics.families.ucgreek = mathematics.families.mr
+ mathematics.families.vargreek = mathematics.families.mr
+
+ mathematics.define(mathematics.slots.euler)
+ end
+\stopluacode
+
+% \usemodule[mkivhacks] \setups{eulermath}
+% \definetypeface[modern][mm][math][euler][default]
+% \usemathcollection[eul]
+% \switchtobodyfont[modern,11pt]
+% \starttext
+% $\alpha$
+% \stoptext
+
+\startsetups eulermath
+ \ctxlua{document.hacks()}
+\stopsetups
+
+\endinput
diff --git a/tex/context/base/m-narrowtt.tex b/tex/context/base/m-narrowtt.tex
new file mode 100644
index 000000000..2e11b99ad
--- /dev/null
+++ b/tex/context/base/m-narrowtt.tex
@@ -0,0 +1,39 @@
+%D \module
+%D [ file=m-narrowtt,
+%D version=2005.09.08,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Narrow Verbatim,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Test file
+%D
+%D \starttyping
+%D \startTEX
+%D \usemodule[narrowtt]
+%D \starttext
+%D \starttyping
+%D Test test test.
+%D \stoptyping
+%D test \type {test} test \type{test} test
+%D \starttyping
+%D Test test test.
+%D \stoptyping
+%D \stoptext
+%D \stopTEX
+
+\unprotect
+
+\definetypeface
+ [narrowtt] [tt]
+ [mono] [modern-condensed] [default] [encoding=\defaultencoding]
+
+\definetyping[n\v!typing] \setuptyping[n\v!typing][style=\narrowtt]
+\definetype [n\v!type] \setuptype [n\v!type] [style=\narrowtt]
+
+\protect \endinput
diff --git a/tex/context/base/m-newmat.tex b/tex/context/base/m-newmat.tex
new file mode 100644
index 000000000..08ce33b4c
--- /dev/null
+++ b/tex/context/base/m-newmat.tex
@@ -0,0 +1,337 @@
+%D \module
+%D [ file=m-newmat,
+%D version=2000.11.16,
+%D title=\CONTEXT\ Math Module,
+%D subtitle=AMS-like math extensions,
+%D author={Taco Hoekwater \& Hans Hagen},
+%D date=\currentdate,
+%D copyright={PRAGMA / Taco Hoekwater}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D This module collects macros that \TEX\ users kind of expect
+%D to be available when typesetting math. Most of them
+%D originate in the \AMS\ macro packages. We have taken the
+%D freedom to adapt them to \CONTEXT. This module is derived
+%D from the \type {m-math} module by Taco Hoekwater (partially
+%D derived from AMS math modules) and adapted|/|extended by
+%D Hans Hagen.
+
+%D Here we will add code on demand. So, just let us know what
+%D should go in here.
+
+%M \usemodule[newmat]
+
+\unprotect
+
+%D \macros
+%D {qedsymbol}
+%D
+%D [HH] The general Quod Erat Domonstrandum symbol is defined
+%D in such a way that we can configure it. Because this symbol
+%D is also used in text mode, we make it a normal text symbol
+%D with special behavior.
+
+\def\qedsymbol#1%
+ {\ifhmode
+ \unskip~\hfill#1\par
+ \else\ifmmode
+ \eqno#1\relax % Do we really need the \eqno here?
+ \else
+ \leavevmode\hbox{}\hfill#1\par
+ \fi\fi}
+
+\definesymbol [qed] [\qedsymbol{\mathematics{\square}}]
+
+%D \macros
+%D {QED}
+%D
+%D [HH] For compatbility reasons we also provide the \type
+%D {\QED} command. In case this command is overloaded, we still
+%D have the symbol available. \symbol[qed]
+
+\def\QED{\symbol[qed]}
+
+%D \macros
+%D {genfrac}
+%D
+%D [TH] The definition of \type {\genfrac} \& co. is not
+%D trivial, because it allows some flexibility. This is
+%D supposed to be a user||level command, but will fail quite
+%D desparately if called outside math mode (\CONTEXT\ redefines
+%D \type {\over})
+%D
+%D [HH] We clean up this macro a bit and (try) to make it
+%D understandable. The expansion is needed for generating
+%D the second argument to \type {\dogenfrac}, which is to
+%D be a control sequence like \type {\over}.
+
+\unexpanded\def\genfrac#1#2#3#4%
+ {\edef\!!stringa
+ {#1#2}%
+ \expanded
+ {\dogenfrac{#4}%
+ \csname
+ \ifx @#3@%
+ \ifx\!!stringa\empty
+ \strippedcsname\normalover
+ \else
+ \strippedcsname\normaloverwithdelims
+ \fi
+ \else
+ \ifx\!!stringa\empty
+ \strippedcsname\normalabove
+ \else
+ \strippedcsname\normalabovewithdelims
+ \fi
+ \fi
+ \endcsname}%
+ {#1#2#3}}
+
+\def\dogenfrac#1#2#3#4#5%
+ {{#1{\begingroup#4\endgroup#2#3\relax#5}}}
+
+%D \macros
+%D {dfrac, tfrac, frac, dbinom, tbinom, binom}
+%D
+%D [TH] No need to make these \type {\unexpanded} as well.
+
+%\def\dfrac {\genfrac\empty\empty\empty\displaystyle}
+%\def\tfrac {\genfrac\empty\empty\empty\textstyle}
+%\def\frac {\genfrac\empty\empty\empty\donothing}
+
+\def\dfrac {\genfrac\empty\empty{}\displaystyle}
+\def\tfrac {\genfrac\empty\empty{}\textstyle}
+\def\frac {\genfrac\empty\empty{}\donothing}
+
+\def\dbinom{\genfrac()\zeropoint\displaystyle}
+\def\tbinom{\genfrac()\zeropoint\textstyle}
+\def\binom {\genfrac()\zeropoint\donothing}
+
+\def\xfrac {\genfrac\empty\empty{}\scriptstyle}
+\def\xxfrac{\genfrac\empty\empty{}\scriptscriptstyle}
+
+%D Better:
+
+\unexpanded\def\frac#1#2{\mathematics{\genfrac\empty\empty{}\donothing{#1}{#2}}}
+
+%D [HH] This shows up as:
+%D
+%D \startbuffer
+%D $\dfrac {1}{2} \tfrac {1}{2} \frac {1}{2}$
+%D $\dbinom{1}{2} \tbinom{1}{2} \binom{1}{2}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+%D \macros
+%D {text}
+%D
+%D [TH] \type {\text} is a command to typeset more or less
+%D ordinary text inside of super- and sub|-|scripts. It has to
+%D do a full font switch to get the sides right, so it will be
+%D quite slow. \type {\text} kind of replaces \CONTEXT's \type
+%D {\mathstyle} command.
+
+%D [HH] This macro is now also moved to the core, but we
+%D keep it here as well for completeness.
+%D
+%D \starttyping
+%D \unexpanded\def\mathtext
+%D {\mathortext\domathtext\hbox} % {\ifmmode\@EA\dotext\else\@EA\hbox\fi}
+%D
+%D \def\domathtext#1%
+%D {\mathchoice
+%D {\dodomathtext\displaystyle\textface {#1}}%
+%D {\dodomathtext\textstyle \textface {#1}}%
+%D {\dodomathtext\textstyle \scriptface {#1}}%
+%D {\dodomathtext\textstyle \scriptscriptface{#1}}}
+%D
+%D \def\dodomathtext#1#2#3% no \everymath !
+%D %{\hbox{\everymath{#1}\switchtobodyfont [#2]#3}} % 15 sec
+%D {\hbox{\everymath{#1}\setcurrentfontbody{#2}#3}} % 3 sec (no math)
+%D \stoptyping
+
+%D [HH] We use the following indirectness because \type {\text}
+%D is a natural candidate for user macros (actually, it is
+%D used in some modules).
+%D
+%D \starttyping
+%D \let\text\mathtext
+%D \stoptyping
+
+%D [HH] Actually, the font switch is not that slow when
+%D typefaces are used. If needed this macro can be sped up.
+%D
+%D \startbuffer
+%D ordinary text $x^{\text{extra ordinary text}}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+%D \macros
+%D {mathhexbox}
+%D
+%D [TH] \type {\mathhexbox} is also user||level (already
+%D defined in Plain \TEX). It allows to get a math character
+%D inserted as if it was a text character.
+
+\gdef\mathhexbox#1#2#3{\mathtext{$\mathsurround\zeropoint\mathchar"#1#2#3$}}
+
+%D \macros
+%D {boxed}
+%D
+%D [HH] Another macro that users expect (slightly adapted):
+
+\def\boxed
+ {\ifmmode\expandafter\mframed\else\expandafter\framed\fi}
+
+%D \macros
+%D {cfrac}
+%D
+%D [HH] Now let us see what this one does:
+%D
+%D \startbuffer
+%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$
+%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+\definecomplexorsimple\cfrac
+
+\def\simplecfrac
+ {\complexcfrac[c]}
+
+\def\complexcfrac[#1]#2#3%
+ {{\displaystyle
+ \frac
+ {\strut\ifx r#1\hfill\fi#2\ifx l#1\hfill\fi}%
+ {#3}}%
+ \kern-\nulldelimiterspace}
+
+%D [HH] The next alternative is nicer:
+
+\def\simplecfrac {\docfrac[cc]}
+\def\complexcfrac[#1]{\docfrac[#1cc]}
+
+\def\docfrac[#1#2#3]#4#5%
+ {{\displaystyle
+ \frac
+ {\strut
+ \ifx r#1\hfill\fi#4\ifx l#1\hfill\fi}%
+ {\ifx r#2\hfill\fi#5\ifx l#2\hfill\fi}%
+ \kern-\nulldelimiterspace}}
+
+%D [HH] Now we can align every combination we want:
+%D
+%D \startbuffer
+%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$
+%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$
+%D $\cfrac[cl]{12}{3} \cfrac[cc]{12}{3} \cfrac[cr]{12}{3}$
+%D $\cfrac[lc]{1}{23} \cfrac[cc]{1}{23} \cfrac[rc]{1}{23}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+%D \macros
+%D {splitfrac, splitdfrac}
+%D
+%D Occasionally one needs to typeset multi||line fractions.
+%D These commands use \tex{genfrac} to create such fractions.
+%D
+%D \startbuffer
+%D \startformula
+%D a=\frac{
+%D \splitfrac{xy + xy + xy + xy + xy}
+%D {+ xy + xy + xy + xy}
+%D }
+%D {z}
+%D =\frac{
+%D \splitdfrac{xy + xy + xy + xy + xy}
+%D {+ xy + xy + xy + xy}
+%D }
+%D {z}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D These macros are based on Michael J.~Downes posting on
+%D comp.text.tex on 2001/12/06
+
+\def\splitfrac#1#2%
+ {\genfrac\empty\empty\zeropoint\textstyle%
+ {\textstyle#1\quad\hfill}%
+ {\textstyle\hfill\quad\mathstrut#2}}
+
+\def\splitdfrac#1#2%
+ {\genfrac\empty\empty\zeropoint\displaystyle%
+ {#1\quad\hfill}
+ {\hfill\quad\mathstrut #2}}
+
+\protect \endinput
+
+%D \macros
+%D {startsubarray,substack,startsmallmatrix}
+%D
+%D [HH] I wonder what these are supposed to do. An example
+%D will be inserted later. Contrary to the original we
+%D support an optional argument between either \type {{}} or
+%D \type {[]}.
+
+\def\startsubarray
+ {\doifnextcharelse\bgroup
+ \simplestartsubarray{\dosingleempty\complexstartsubarray}}
+
+\def\complexstartsubarray[#1]%
+ {\simplestartsubarray{#1}}
+
+\def\simplestartsubarray#1%
+ {\vcenter\bgroup
+ \baselineskip\fontdimen10 \scriptfont\plustwo
+ \advance\baselineskip\fontdimen12 \scriptfont\plustwo
+ \lineskip\plusthree\fontdimen8 \scriptfont\plusthree
+ \lineskiplimit\lineskip
+ \ialign\bgroup\ifx c#1\hfil\fi$\mathsurround\zeropoint\scriptstyle##$\hfil\crcr}
+
+\def\stopsubarray
+ {\crcr\egroup
+ \egroup}
+
+\def\startsubstack
+ {\doifnextcharelse\bgroup
+ \simplestartsubstack{\dosingleempty\complexstartsubstack}}
+
+\def\complexstartsubstack[#1]%
+ {\simplestartsubstack{#1}}
+
+\def\simplesubstack#1%
+ {\startsubarray[c]#1\stopsubarray}
+
+\def\startsmallmatrix
+ {\null
+ \,%
+ \vcenter\bgroup
+ \baselineskip6\ex@
+ \lineskip1.5\ex@
+ \lineskiplimit\lineskip
+ \ialign\bgroup\hfil$\mathsurround\zeropoint\scriptstyle##$\hfil&&\thickspace\hfil
+ $\mathsurround\zeropoint\scriptstyle##$\hfil\crcr}
+
+\def\stopsmallmatrix
+ {\crcr\egroup
+ \egroup
+ \,}
+
+\protect \endinput
diff --git a/tex/context/base/m-obsolete.tex b/tex/context/base/m-obsolete.tex
new file mode 100644
index 000000000..a97002cf6
--- /dev/null
+++ b/tex/context/base/m-obsolete.tex
@@ -0,0 +1,5 @@
+\unprotect
+
+\writestatus\m!systems{skipping obsolete module}
+
+\protect \endinput
diff --git a/tex/context/base/m-pdfsnc.tex b/tex/context/base/m-pdfsnc.tex
new file mode 100644
index 000000000..da59ab5d8
--- /dev/null
+++ b/tex/context/base/m-pdfsnc.tex
@@ -0,0 +1,200 @@
+%D \module
+%D [ file=m-pdfsnc,
+%D version=2003.12.23,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Editor Synchronization,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% \enablemode[demo]
+
+% This file is a variation of the file pdfsync4context.tex that ships
+% with the pdfsync package (used by iTeXMac and TeXShop) by Piero
+% D'Ancona and Jrme Laurens. I made the macros a bit more efficient
+% and added some basic tracing options as well as a few more options.
+% I made this one while playing a bit with the Mac and TeX). Maybe I'll
+% add a bit of support to the kernel in in order to get rid of redundant
+% markers. Also, this had better be rewritten in a bit less \pdf
+% dependent way so that it can also be supported by dvipdfmx. I could
+% write a generic file as well, but since there is already support for
+% other packages I'll not do that (now).
+
+% compatible commands:
+%
+% \pdfsyncstart \pdfsyncstop \pdfsync
+%
+% extra commands:
+%
+% \enablepdfsync \disablepdfsync \pdfsynctext \pdfsyncnode \pdfsynctracemode
+
+\ifx\pdfoutput\undefined
+ \donefalse
+\else\ifcase\pdfoutput
+ \donefalse
+\else\ifx\pdfsavepos\undefined
+ \donefalse
+\else
+ \donetrue
+\fi\fi\fi
+
+\chardef \pdfsyncstate \zerocount
+\chardef \pdfsynctracemode \zerocount
+
+\ifdone
+
+ \writestatus{pdfsync}{loading and enabling synchronization support}
+
+\else
+
+ \writestatus{pdfsync}{synchronization is only available with pdftex}
+
+ \let \pdfsyncstart \relax % brr, not per se symmetrically used, so
+ \let \pdfsyncstop \relax % enable and disable are better names
+ \let \pdfsync \relax
+
+ \let \pdfsynctext \gobbleoneargument
+ \let \pdfsyncnode \gobbleoneargument
+
+ \let \enablepdfsync \pdfsyncstart
+ \let \disablepdfsync \pdfsyncstop
+
+ \expandafter\endinput
+\fi
+
+\unprotect % not really needed
+
+\newcount \pdfsynccounter
+\newwrite \pdfsyncwrite
+
+\def\pdfsyncstart{\chardef\pdfsyncstate\plusone} \let\enablepdfsync \pdfsyncstart
+\def\pdfsyncstop {\chardef\pdfsyncstate\zerocount} \let\disablepdfsync\pdfsyncstop
+
+\def\dostartpdfsync
+ {\immediate\openout\pdfsyncwrite\jobname.pdfsync
+ \immediate\write\pdfsyncwrite{\jobname}%
+ \immediate\write\pdfsyncwrite{version 0}}
+
+\def\dostoppdfsync
+ {\immediate\closeout\pdfsyncwrite}
+
+\def\doregisterpdfsyncpage
+ {\immediate\write\pdfsyncwrite{s\space\realfolio}}
+
+\def\dopdfsyncopenfile
+ {\immediate\write\pdfsyncwrite{(\space\readfilename}}
+
+\def\dopdfsyncclosefile
+ {\immediate\write\pdfsyncwrite{)}}
+
+\def\doregisterpdfsyncnode#1%
+ {\ifcase\pdfsyncstate\else
+ \pdfsavepos
+ \immediate\write\pdfsyncwrite{l\space\the\pdfsynccounter\space\the\inputlineno}%
+ \expanded{\write\pdfsyncwrite{p\ifnum#1=\plusone*\fi\space\the\pdfsynccounter\space\noexpand\the\pdflastxpos\space\noexpand\the\pdflastypos}}%
+ \global\advance\pdfsynccounter\plusone
+ \fi}
+
+\let\pdfsynctracer\gobbleoneargument
+
+\def\pdfsync {\doregisterpdfsyncnode\plusone \pdfsynctracer*}
+\def\pdfsyncnode{\doregisterpdfsyncnode\zerocount\pdfsynctracer}
+\def\pdfsynctext{\doregisterpdfsyncnode\plusone \pdfsynctracer}
+
+\appendtoks \dostartpdfsync \to \everystarttext
+%appendtoks \dostoppdfsync \to \everystoptext
+\appendtoks \doregisterpdfsyncpage \to \everyshipout
+\appendtoks \dopdfsyncopenfile \to \everybeforereadfile
+\appendtoks \dopdfsyncclosefile \to \everyafterreadfile
+
+\appendtoks \enablepdfsync \to \everystarttext
+\appendtoks \disablepdfsync \to \everypagebody
+
+% beware, adding nodes this way will interfere with the typesetting
+
+\appendtoks \pdfsyncnode p\to \everypar
+\appendtoks \pdfsyncnode m\to \everymath
+\appendtoks \pdfsyncnode h\to \everyhbox
+
+% just for fun
+
+\def\pdfsynctracer#1%
+ {\ifcase\pdfsynctracemode\else
+ \ifcase\pdfsyncstate\else
+ \begingroup
+ \forgetall
+ \disablepdfsync
+ \ifcase\pdfsynctracemode\or % could be done more efficient, box around ifcase
+ \setbox\scratchbox\hbox to \zeropoint{\hss\infofont#1\hss}% 1
+ \else
+ \setbox\scratchbox\hbox to \zeropoint{\hss\traceboxplacementtrue\boxcursor\hss}% 2/3/4
+ \fi
+ \smashbox\scratchbox\box\scratchbox
+ \ifcase\pdfsynctracemode\or\or\or
+ \setbox\scratchbox\hbox to \zeropoint{\hss\raise1.25ex\hbox{\infofont#1}\hss}% 3
+ \smashbox\scratchbox\box\scratchbox
+ \or
+ \setbox\scratchbox\hbox to \zeropoint{\hss\lower1.25ex\hbox{\infofont#1}\hss}% 4
+ \smashbox\scratchbox\box\scratchbox
+ \fi
+ \endgroup
+ \fi
+ \fi}
+
+% \def\pdfsynctracer#1% more efficient but unreadable
+% {\ifcase\pdfsynctracemode\else
+% \ifcase\pdfsyncstate\else
+% \begingroup
+% \forgetall
+% \disablepdfsync
+% \setbox\scratchbox\hbox to \zeropoint
+% {\hss
+% \ifcase\pdfsynctracemode\or
+% \infofont#1% 1
+% \else
+% \traceboxplacementtrue\boxcursor% 2/3/4
+% \fi
+% \hss}%
+% \smashbox\scratchbox\box\scratchbox
+% \setbox\scratchbox\hbox to \zeropoint
+% {\hss
+% \ifcase\pdfsynctracemode\or\or\or
+% \raise1.25ex\hbox{\infofont#1}% 3
+% \or
+% \lower1.25ex\hbox{\infofont#1}% 4
+% \fi
+% \hss}%
+% \smashbox\scratchbox\box\scratchbox
+% \endgroup
+% \fi
+% \fi}
+
+\protect
+
+\doifnotmode{demo}{\endinput}
+
+\chardef\pdfsynctracemode=3
+
+\starttext
+
+\chapter{Test}
+
+\processfile{tufte}
+
+\startitemize
+\item first
+\item second
+\stopitemize
+
+\processfile{tufte}
+
+\startlines
+some local \pdfsync sync and \pdfsynctext{here}a marked point
+some local \pdfsync sync and \pdfsyncnode{here}a marked point
+\stoplines
+
+\stoptext
diff --git a/tex/context/base/m-pictex.tex b/tex/context/base/m-pictex.tex
new file mode 100644
index 000000000..abb81b76e
--- /dev/null
+++ b/tex/context/base/m-pictex.tex
@@ -0,0 +1,255 @@
+%D \module
+%D [ file=m-pictex,
+%D version=1997.01.15,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\PICTEX\ Loading Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is one big hack. This hack is not needed when
+%D using \ETEX, so there we simply load \PICTEX\ and quit.
+
+%D Not every package defines \type{\fiverm}, \PICTEX's pixel,
+%D so let's take care of that omision here. The actual loading
+%D of \PICTEX\ depends on the package. For \LATEX\ users we
+%D take care of loading the auxiliary ones too.
+
+\def\loadpictex
+ {\ifx\grid\undefined \else \let\normalgrid\grid \fi
+ \ifx\axis\undefined \else \let\normalaxis\axis \fi
+ \ifx\undefined\fiverm
+ \font\fiverm=cmr5
+ \fi
+ \ifx\beginpicture\undefined
+ \ifx\newenvironment\undefined
+ \readfile{thrd-pic.tex}{}{}
+ \else
+ \input prepictex.tex \relax
+ \input pictex.tex \relax
+ \input postpictex.tex \relax
+ \fi
+ \fi
+ \ifx\normalgrid\undefined \else
+ \let\pictexgrid\grid
+ \let\grid\normalgrid
+ \fi
+ \ifx\normalaxis\undefined \else
+ \let\pictexaxis\axis
+ \let\axis\normalaxis
+ \fi}
+
+\ifx\eTeXversion\undefined \else \loadpictex \expandafter \endinput \fi
+
+%D When not in \ETEX\ and not in \CONTEXT, we load a few
+%D auxiliary macros.
+
+\ifx \undefined \writestatus \input supp-mis.tex \relax \fi
+
+\unprotect
+
+%D \TEX\ provides 256 \DIMENSIONS\ and 256 \SKIPS. In \CONTEXT\
+%D this is no problem, but in packages that have many
+%D authors, one can be quite sure that a lot of \DIMENSIONS\ are
+%D allocated. Packages that use \PICTEX\ can therefore run out
+%D of \DIMENSIONS\ quite fast. This module was written as a
+%D reaction to persistent problems with loading \PPCHTEX\ in
+%D \LATEX\ and \PICTEX\ deserves a solution. I therefore
+%D dedicate this module to Tobias Burnus and Dirk Kuypers, who
+%D use \PPCHTEX\ in a \LATEX\ environment and suggested a lot
+%D of extensions to the repertoire of \PPCHTEX\ commands.
+%D
+%D This module presents a solution that is quite effective: all
+%D \DIMENSIONS\ are drawn from the pool of \DIMENSIONS\ and
+%D \SKIPS, depending on the availability. This is possible
+%D because \DIMENSIONS\ are \SKIPS\ without a glue component.
+%D Therefore we can use \SKIPS\ as \DIMENSIONS. However, some
+%D incompatibility can result from assignments that look like:
+%D
+%D \starttyping
+%D \somedimen=\someskip
+%D \stoptyping
+%D
+%D In such cases the \DIMENSION\ equals the fixed part of the
+%D \SKIP\ or in other words: this assignment strips off the
+%D glue. Because \PICTEX\ uses no glue components, I thought
+%D I could interchange both register types without problems,
+%D but alas, this didn't hold for all \DIMENSIONS.
+
+%D In \PLAIN\ \TEX\ the allocation macros are defined with (as)
+%D \type{\outer}. This means that they cannot appear inside
+%D macros, not even in an indirect way. We therefore have to
+%D redefine both \type{\newdimen} and \type{\newskip} to
+%D non||\type{\outer} alternatives. In most macro packages this
+%D redefinition already took place. We save the original
+%D meanings, so we can restores them afterwards.
+
+% \def\temporarynewdimen {\alloc@1\dimen\dimendef\insc@unt}
+% \def\temporarynewskip {\alloc@2\skip \skipdef \insc@unt}
+
+\let\normalnewdimen \newdimen
+\let\normalnewskip \newskip
+
+\let\temporarynewdimen\newdimen
+\let\temporarynewskip \newskip
+
+%D Here comes the trick. Depending on how many \DIMENSIONS\ and
+%D \SKIPS\ are allocated, the \type{\newdimen} assigns a
+%D \DIMENSIONS\ or \SKIP. \PLAIN\ \TEX\ allocates 15 \DIMENSIONS\
+%D and 17 \SKIPS. After loading \PICTEX, 71 \DIMENSIONS\ and
+%D and 71 \SKIPS\ are allocated. Indeed, \PICTEX\ needs 110
+%D \DIMENSIONS !
+%D
+%D \starttyping
+%D \def\newdimen
+%D {\ifnum\count11>\count12
+%D \let\next\temporarynewskip
+%D \else
+%D \let\next\temporarynewdimen
+%D \fi
+%D \next}
+%D \stoptyping
+%D
+%D When I was testing a new version of \PPCHTEX\ in \PLAIN\
+%D \TEX\ I had to find out that this exchange of registers
+%D sometimes leads to unwanted results. It took me some hours
+%D to find out that the source of errors originated in
+%D constructions like:
+%D
+%D \starttyping
+%D \ifdim\DimenOne<\DimenTwo whatever you want \else or not \fi
+%D \stoptyping
+%D
+%D When \type{\DimenOne} is a \SKIP\ and \type{\DimenTwo} is a
+%D \DIMENSION, \TEX\ scans for some optional glue component,
+%D like in:
+%D
+%D \starttyping
+%D \skip0=\dimen0 plus 10pt minus 5pt
+%D \stoptyping
+%D
+%D The most robust solution to this problem is:
+%D
+%D \starttyping
+%D \ifdim\DimenOne<\DimenTwo\relax right \else wrong \fi
+%D \stoptyping
+%D
+%D Some close reading of the \PICTEX\ source however learned me
+%D that this problem could be solved best by just honoring the
+%D allocation of \DIMENSIONS\ when the name of the macro
+%D explictly stated the character sequence \type{dimen}. A next
+%D implementation therefore automatically declared all
+%D \DIMENSIONS\ with this sequence in their names with
+%D \type{\dimen}. Again I was too optimistic, so now we do it
+%D this way (the comments are from \PICTEX, which like \TABLE,
+%D is an example of a well documented package):
+
+\temporarynewdimen\!dimenA %.AW.X.DVEUL..OYQRST
+\temporarynewdimen\!dimenB %....X.DVEU...O.QRS.
+\temporarynewdimen\!dimenC %..W.X.DVEU......RS.
+\temporarynewdimen\!dimenD %..W.X.DVEU....Y.RS.
+\temporarynewdimen\!dimenE %..W........G..YQ.S.
+\temporarynewdimen\!dimenF %...........G..YQ.S.
+\temporarynewdimen\!dimenG %...........G..YQ.S.
+\temporarynewdimen\!dimenH %...........G..Y..S.
+\temporarynewdimen\!dimenI %...BX.........Y....
+\temporarynewdimen\!dxpos %..W......U..P....S.
+\temporarynewdimen\!dypos %..WB.....U..P......
+\temporarynewdimen\!xloc %..WB.....U.......S.
+\temporarynewdimen\!xpos %..........L.P..Q.ST
+\temporarynewdimen\!yloc %..WB.....U.......S.
+\temporarynewdimen\!ypos %..........L.P..Q.ST
+\temporarynewdimen\!zpt %.AWBX.DVEULGP.YQ.ST
+
+%D Tobias tested this module in all kind of \LATEX\ dialects
+%D so we were able to find out that we also needed to declare:
+
+\temporarynewdimen\linethickness
+
+%D After all, the new definition of \type{\newdimen} became:
+
+\def\newdimen#1%
+ {\ifx#1\undefined
+ \ifnum\count11>\count12\relax
+ \temporarynewskip#1\relax
+ \else
+ \temporarynewdimen#1\relax
+ \fi
+ %\edef\ascii{\meaning#1}%
+ %\immediate\write20{\string#1 becomes \ascii}%
+ \else
+ %\edef\ascii{\meaning#1}%
+ %\immediate\write20{\string#1 already is \ascii}%
+ \fi}
+
+% \def\newdimen#1%
+% {\bgroup
+% \escapechar=-1
+% \def\next##1##2%
+% {\def\next####1##1####2####3\next%
+% {\egroup
+% \if####2@
+% \temporarynewdimen#1\relax
+% \ifnum\count11>\count12
+% \temporarynewskip#1\relax
+% \else
+% \temporarynewdimen#1\relax
+% \fi\fi}%
+% \expandafter\next\string##2##1@@\next}%
+% \expandafter\next\expandafter{\string\dimen}#1}
+%
+% This macro is as unreadable, inefficient and as compact as
+% can be, but uses no extra hash entries, which sometimes are
+% scarce too. A more readable alternative, that also takes
+% explicit \SKIPS\ into account, is included in the source.
+%
+% \def\doifregisterpreferenceelse#1#2#3#4%
+% {\def\dodoifregisterpreferenceelse##1#1##2##3\war{\if##2@}%
+% \expandafter\dodoifregisterpreferenceelse\string#2#1@@\war
+% #4%
+% \else
+% #3%
+% \fi}
+%
+% \def\newdimen#1%
+% {\bgroup
+% \escapechar=-1
+% \expandafter\doifregisterpreferenceelse\expandafter{\string\dimen}#1
+% {\egroup
+% \temporarynewdimen#1}
+% {\expandafter\doifregisterpreferenceelse\expandafter{\string\skip}#1
+% {\egroup
+% \temporarynewskip#1}
+% {\egroup
+% \ifnum\count11>\count12
+% \temporarynewskip#1\relax
+% \else
+% \temporarynewdimen#1\relax
+% \fi}}}
+
+%D Curious readers can still find the previous solution in
+%D the source. The next macro is used instead of
+%D \type{\input}. This macro also reports some statistics.
+
+\def\dimeninput#1 %
+ {\message{[before: d=\the\count11,s=\the\count12]}%
+ \input #1 \relax
+ \message{[after: d=\the\count11,s=\the\count12]}}%
+
+%D Now we can load \PICTEX:
+
+\loadpictex
+
+%D Finally we restore the old definitions of \type{\newdimen}
+%D and \type{\newskip}:
+
+\let\newdimen=\normalnewdimen
+\let\newskip =\normalnewskip
+
+%D and just hope for the best.
+
+\protect \endinput
diff --git a/tex/context/base/m-plus.tex b/tex/context/base/m-plus.tex
new file mode 100644
index 000000000..312d9f931
--- /dev/null
+++ b/tex/context/base/m-plus.tex
@@ -0,0 +1,30 @@
+%D \module
+%D [ file=m-plus,
+%D version=2003.03.16,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Loading extra features,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 Somewhere in 2001 I started collecting new functionality
+%D in a module \type {m-yesno}. As the name suggests, I was
+%D not entirely sure if this functionality belonged in the
+%D kernel. When (again) on the \CONTEXT\ list a request for
+%D side bars was posted, I decided to move such code to plus
+%D modules. Users who want this additional functionality can
+%D put the following call in their \type {cont-sys.tex} file:
+%D
+%D \starttyping
+%D \usemodule[plus]
+%D \stoptyping
+
+% \readfile {plus-rul} \donothing \donothing
+% \readfile {page-str} \donothing \donothing
+% \readfile {page-plg} \donothing \donothing
+
+\endinput
diff --git a/tex/context/base/m-pstricks.lua b/tex/context/base/m-pstricks.lua
new file mode 100644
index 000000000..35cae93f6
--- /dev/null
+++ b/tex/context/base/m-pstricks.lua
@@ -0,0 +1,73 @@
+if not modules then modules = { } end modules ['m-pstricks'] = {
+ version = 1.001,
+ comment = "companion to m-pstricks.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The following will be done when I need ps tricks figures
+-- in large quantities:
+--
+-- + hash graphics and only process them once
+-- + save md5 checksums in tuc file
+--
+-- It's no big deal but has a low priority.
+
+local format, lower, concat, gmatch = string.format, string.lower, table.concat, string.gmatch
+local variables = interfaces.variables
+
+plugins = plugins or { }
+plugins.pstricks = plugins.pstricks or { }
+
+local template = [[
+\starttext
+ \pushcatcodetable
+ \setcatcodetable\texcatcodes
+ \usemodule[pstric]
+ %s
+ \popcatcodetable
+ \startTEXpage
+ \hbox\bgroup
+ \ignorespaces
+ %s
+ \removeunwantedspaces
+ \egroup
+ \obeydepth %% temp hack as we need to figure this out
+ \stopTEXpage
+\stoptext
+]]
+
+local modules = { }
+local graphics = 0
+
+function plugins.pstricks.usemodule(names)
+ for name in gmatch(names,"([^%s,]+)") do
+ modules[#modules+1] = format([[\readfile{%s}{}{}]],name)
+ end
+end
+
+function plugins.pstricks.process(n)
+ graphics = graphics + 1
+ local name = string.format("%s-pstricks-%04i",tex.jobname,graphics)
+ local data = buffers.collect("def-"..n)
+ local tmpfile = name .. ".tmp"
+ local epsfile = name .. ".ps"
+ local pdffile = name .. ".pdf"
+ local modules = concat(modules,"\n")
+ os.remove(epsfile)
+ os.remove(pdffile)
+ io.savedata(tmpfile,format(template,modules,data))
+ os.execute(format("mtxrun --script texexec %s --once --dvips",tmpfile))
+ if lfs.isfile(epsfile) then
+ os.execute(format("ps2pdf %s %s",epsfile,pdffile))
+ -- todo: direct call but not now
+ if lfs.isfile(pdffile) then
+ context.externalfigure( { pdffile }, { object = variables.no } )
+ else
+ logs.report("plugins","pstricks run failed, no pdf file")
+ end
+ else
+ logs.report("plugins","pstricks run failed, no ps file")
+ end
+end
diff --git a/tex/context/base/m-pstricks.mkii b/tex/context/base/m-pstricks.mkii
new file mode 100644
index 000000000..3ada9e07e
--- /dev/null
+++ b/tex/context/base/m-pstricks.mkii
@@ -0,0 +1,127 @@
+%D \module
+%D [ file=m-pstricks,
+%D version=1997.01.15,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\PSTRICKS\ Connections,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% pstricks is not supported in context mkii (it's no problem doing that
+% but as we also need to support latex it would become quite messy so for
+% context we use metapost and for latex pstricks)
+
+%M \usemodule[pstric]
+
+\letvalue{@unused}\plussixteen
+\letvalue{alloc@}\gobblefivearguments
+
+\chardef\oldbarcode\the\catcode`\| \catcode`\|=12
+
+\def\loadpstrickscolors#1%
+ {\pushmacro\dodefinecolor
+ \pushmacro\dodefinepalet
+ \pushmacro\dodefinecolorgroup
+ \def\dodefinecolor[##1][##2]%
+ {\doifassignmentelse{##2}
+ {\getparameters[pstricks][r=0,g=0,b=0,##2]%
+ \expanded{\newrgbcolor{##1}{{\pstricksr} {\pstricksg} {\pstricksb}}}}%
+ {}}%
+ \def\dodefinepalet [##1][##2]{}%
+ \def\dodefinecolorgroup[##1][##2][##3]{}%
+ \writestatus{pstricks}{loading colors from #1}%
+ \input #1 \relax
+ \popmacro\dodefinecolorgroup
+ \popmacro\dodefinepalet
+ \popmacro\dodefinecolor}
+
+\doifelse{\jobsuffix}{dvi}
+ {\input multido \relax
+ \input pstricks \relax
+ \input pst-plot \relax
+ \loadpstrickscolors{colo-rgb}}
+ {\writestatus{pstricks}{using indirect method; enable write18}}
+
+\catcode`\|=\oldbarcode
+
+\def\loadpstricksmodule[#1]%
+ {\chardef\oldbarcode\the\catcode`\|
+ \catcode`\|=12
+ \readfile{#1}{}{}%
+ \catcode`\|=\oldbarcode}
+
+%D The next piece of code is for John Culleton who suggested to
+%D handle \PSTRICKS\ in a similar fashion as \METAPOST, i.e.\
+%D using a child process. For the moment there is no support
+%D for passing environments, so these should be called
+%D explicitly inside this environment.
+
+\unprotect
+
+%D \startPSTRICKS[offset=2pt] ... \stopPSTRICKS
+%D
+%D works in both dvi and pdf mode
+%D
+%D % \usemodule[pstric]
+%D
+%D \startPSTRICKS
+%D \pspicture(0,0)(10,10)
+%D \dorecurse{10}{\psline(0,0)(\recurselevel,10)}
+%D \dorecurse{10}{\psline(0,0)(10,\recurselevel)}
+%D \endpspicture
+%D \stopPSTRICKS
+
+\def\startPSTRICKS
+ {\dosingleempty\dostartPSTRICKS}
+
+% \ifx\startTEXapplication\undefined
+%
+% \long\def\dostartPSTRICKS[#1]#2\stopPSTRICKS
+% {\doifelse{\jobsuffix}{dvi}
+% {#2}
+% {\bgroup
+% \setbuffer[pstricks]%
+% \usemodule[pstric]%
+% \setbox\scratchbox\hbox{#2}%
+% % There is probably a nicer way to handle this
+% \immediate\openout\scratchwrite=\bufferprefix dim.tmp
+% \immediate\write\scratchwrite{\dimen0=\the\ht\scratchbox}%
+% \immediate\write\scratchwrite{\dimen2=\the\wd\scratchbox}%
+% \immediate\closeout\scratchwrite
+% % Quick and dirty
+% \startTEXpage[#1]\box\scratchbox\stopTEXpage
+% \endbuffer
+% % Here we go!
+% %\immediate\write18{texexec \bufferprefix pstricks.tmp --once --batch}%
+% %\immediate\write18{dvips -G0 -Ppdf \bufferprefix pstricks -o}%
+% %\immediate\write18{ps2pdf \bufferprefix pstricks.ps \bufferprefix pstricks.pdf}%
+% \executesystemcommand{texexec \bufferprefix pstricks.tmp --once --batch}%
+% \executesystemcommand{dvips -G0 -Ppdf \bufferprefix pstricks -o}%
+% \executesystemcommand{texmfstart pstopdf \bufferprefix pstricks.ps \bufferprefix pstricks.pdf}%
+% % We pick up the dimensions from the scratch file.
+% \readlocfile{\bufferprefix pstricks-dim.tmp}{}{}%
+% % Since the graphic is put on a page (sigh) by dvips/gs
+% % we need to shift it around a bit.
+% \setbox\scratchbox\hbox
+% {\externalfigure[\bufferprefix pstricks.pdf][\c!object=\v!no]}%
+% \setbox\scratchbox\hbox
+% {\lower\ht\scratchbox\hbox{\raise\dimen2\box\scratchbox}}%
+% \wd\scratchbox\dimen0
+% \ht\scratchbox\dimen2
+% \dp\scratchbox\zeropoint
+% \box\scratchbox
+% \egroup}}
+%
+% \fi
+
+\long\def\dostartPSTRICKS[#1]#2\stopPSTRICKS
+ {\doifelse{\jobsuffix}{dvi} % will some day move to app as switch
+ {\hbox{#2}}
+% {\startTEXapplication[#1]{\usemodule[pstric]}#2\stopTEXapplication}}
+ {\startTEXapplication[#1]{}#2\stopTEXapplication}}
+
+\protect \endinput
diff --git a/tex/context/base/m-pstricks.mkiv b/tex/context/base/m-pstricks.mkiv
new file mode 100644
index 000000000..c800ec199
--- /dev/null
+++ b/tex/context/base/m-pstricks.mkiv
@@ -0,0 +1,66 @@
+%D \module
+%D [ file=m-pstricks,
+%D version=2010.03.14,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\PSTRICKS\ Connections,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ctxloadluafile{m-pstricks}{}
+
+%D \startbuffer
+%D \usePSTRICKSmodule[pst-barcode]
+%D
+%D \startPSTRICKS
+%D \pspicture(-4mm,-1mm)(38mm,26mm)
+%D \psbarcode{9781860742712}{includetext guardwhitespace}{ean13}%
+%D \endpspicture
+%D \stopPSTRICKS
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+
+\unprotect
+
+% best we can make a special colors module
+%
+% \let\@unused\plussixteen
+% \let\alloc@ \gobblefivearguments
+%
+% \def\loadpstrickscolors#1%
+% {\pushmacro\dodefinecolor
+% \pushmacro\dodefinepalet
+% \pushmacro\dodefinecolorgroup
+% \def\dodefinecolor[##1][##2]%
+% {\doifassignmentelse{##2}
+% {\getparameters[pstricks][r=0,g=0,b=0,##2]%
+% \expanded{\newrgbcolor{##1}{{\pstricksr} {\pstricksg} {\pstricksb}}}}%
+% {}}%
+% \def\dodefinepalet [##1][##2]{}%
+% \def\dodefinecolorgroup[##1][##2][##3]{}%
+% \writestatus{pstricks}{loading colors from #1}%
+% \input #1 \relax
+% \popmacro\dodefinecolorgroup
+% \popmacro\dodefinepalet
+% \popmacro\dodefinecolor}
+%
+% \input multido \relax
+% \input pstricks \relax
+% \input pst-plot \relax
+%
+% \loadpstrickscolors{colo-rgb}
+
+\definebuffer[PSTRICKS]
+
+\unexpanded\def\processPSTRICKS {\ctxlua{plugins.pstricks.process(\thebuffernumber{PSTRICKS})}}
+\unexpanded\def\usePSTRICKSmodule[#1]{\ctxlua{plugins.pstricks.usemodule("#1")}}
+\unexpanded\def\setPSTRICKS #1{\setbuffer[def-\thebuffernumber{PSTRICKS}]#1\endbuffer}
+
+\let\stopPSTRICKS\processPSTRICKS
+
+\protect \endinput
diff --git a/tex/context/base/m-pstricks.tex b/tex/context/base/m-pstricks.tex
new file mode 100644
index 000000000..28bc9f30f
--- /dev/null
+++ b/tex/context/base/m-pstricks.tex
@@ -0,0 +1,16 @@
+%D \module
+%D [ file=m-pstricks,
+%D version=1997.01.15,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=\PSTRICKS\ Connections,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\loadmarkfile{m-pstricks}
+
+\endinput
diff --git a/tex/context/base/m-punk.mkiv b/tex/context/base/m-punk.mkiv
new file mode 100644
index 000000000..65bf03974
--- /dev/null
+++ b/tex/context/base/m-punk.mkiv
@@ -0,0 +1,243 @@
+%D \module
+%D [ file=m-punk,
+%D version=2008.04.15,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Punk Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifx\luaversion\undefined \endinput \fi
+
+% At some point the font generation code will move into the
+% ConTeXt MkIV kernel.
+
+\startluacode
+do
+ local concat = table.concat
+ local chardata = characters.data
+ local fontdata = fonts.ids
+
+ fonts.mp = fonts.mp or { }
+
+ fonts.mp.version = fonts.mp.version or 1.11
+ fonts.mp.inline = true
+ fonts.mp.cache = containers.define("fonts", "mp", fonts.mp.version, true)
+
+ metapost.characters = metapost.characters or { }
+
+-- todo: use table share as in otf
+
+ local characters, descriptions = { }, { }
+ local factor, l, n, w, h, d, total, variants = 100, { }, 0, 0, 0, 0, 0, 0, true
+
+ -- A next version of mplib will provide the tfm font information which
+ -- gives better glyph dimensions, plus additional kerning information.
+
+ local flusher = {
+ startfigure = function(chrnum,llx,lly,urx,ury)
+ l, n = { }, chrnum
+ w, h, d = urx - llx, ury, -lly
+ total = total + 1
+ inline = fonts.mp.inline
+ end,
+ flushfigure = function(t)
+ for i=1, #t do
+ l[#l+1] = t[i]
+ end
+ end,
+ stopfigure = function()
+ local cd = chardata[n]
+ if inline then
+ descriptions[n] = {
+ -- unicode = n,
+ name = cd and cd.adobename,
+ width = w*100,
+ height = h*100,
+ depth = d*100,
+ boundingbox = { 0, -d, w, h },
+ }
+ characters[n] = {
+ commands = { -- todo: xforms, should happen in backend
+ { "special", "pdf: " .. concat(l," ") },
+ }
+ }
+ else
+ descriptions[n] = {
+ -- unicode = n,
+ name = cd and cd.adobename,
+ width = w*100,
+ height = h*100,
+ depth = d*100,
+ boundingbox = { 0, -d, w, h },
+ }
+ characters[n] = {
+ commands = {
+ { "image", { stream = concat(l," "), bbox = { 0, -d*65536, w*65536, h*65536 } } },
+ }
+ }
+ end
+ end
+ }
+
+ metapost.characters.instances = metapost.characters.instances or 10
+
+ function metapost.characters.process(mpxformat, name, instances, scalefactor)
+ statistics.starttiming(metapost.characters)
+ scalefactor = scalefactor or 1
+ instances = instances or metapost.characters.instances or 10
+ local fontname = file.removesuffix(file.basename(name))
+ local hash = file.robustname(string.format("%s %05i %03i", fontname, scalefactor*1000, instances))
+ local lists = containers.read(fonts.mp.cache(), hash)
+ if not lists then
+ statistics.starttiming(flusher)
+ -- we can use a format per font
+ local data = io.loaddata(resolvers.find_file(name))
+ metapost.reset(mpxformat)
+ metapost.set_outer_color(2) -- no outer color and no reset either
+ lists = { }
+ for i=1,instances do
+ list = { }
+ characters, descriptions = { }, { }
+ metapost.process(
+ mpxformat,
+ {
+ "randomseed := " .. i*10 .. ";",
+ "scale_factor := " .. scalefactor .. " ;",
+ data
+ },
+ false,
+ flusher
+ )
+ lists[i] = {
+ designsize = 655360,
+ name = string.format("%s-%03i",hash,i),
+ parameters = {
+ slant = 0,
+ space = 333 * scalefactor,
+ space_stretch = 166.5 * scalefactor,
+ space_shrink = 111 * scalefactor,
+ x_height = 431 * scalefactor,
+ quad =1000 * scalefactor,
+ extra_space = 0
+ },
+ ["type"] = "virtual",
+ characters = characters,
+ descriptions = descriptions,
+ -- embedding = "subset",
+ -- mkiv:
+ spacer = "space",
+ unit = 1000,
+ shared = { },
+ unique = { },
+ }
+ end
+ metapost.reset(mpxformat) -- saves memory
+ lists = containers.write(fonts.mp.cache(), hash, lists)
+ statistics.stoptiming(flusher)
+ end
+ variants = variants + #lists
+ statistics.stoptiming(metapost.characters)
+ return lists
+ end
+
+ function fonts.vf.aux.combine.commands.metafont(g,v)
+ local size = g.specification.size
+ local data = metapost.characters.process(v[2],v[3],v[4],size/655360)
+ local list, t = { }, { }
+ for d=1,#data do
+ t = data[d]
+ t = fonts.tfm.scale(t, -1000)
+ local id = font.nextid()
+ t.fonts = { { id = id } }
+ fontdata[id] = t
+ fonts.vf.aux.compose_characters(t)
+ list[d] = font.define(t)
+ end
+ for k=1,#t do
+ g[k] = t[k] -- kind of replace, when not present, make nil
+ end
+ g.virtualized = true
+ g.variants = list
+ end
+
+ fonts.define.methods.install( "punk", {
+ { "metafont", "mfplain", "punkfont.mp", 10 },
+ } )
+
+ cases.actions[99] = function(current)
+ local used = fontdata[current.font].variants
+ if used then
+ local f = math.random(1,#used)
+ current.font = used[f]
+ return current, true
+ else
+ return current, false
+ end
+ end
+
+ metapost.characters.flusher = flusher
+
+ statistics.register("metapost font generation", function()
+ local time = statistics.elapsedtime(flusher)
+ if total > 0 then
+ return string.format("%i glyphs, %.3f seconds runtime, %i glyphs/second", total, time, total/time)
+ else
+ return string.format("%i glyphs, %.3f seconds runtime", total, time)
+ end
+ end)
+
+ statistics.register("metapost font loading",function()
+ local time = statistics.elapsedtime(metapost.characters)
+ if variants > 0 then
+ return string.format("%.3f seconds, %i instances, %0.3f instances/second", time, variants, variants/time)
+ else
+ return string.format("%.3f seconds, %i instances", time, variants)
+ end
+ end)
+
+end
+\stopluacode
+
+\unexpanded\def\EnableRandomPunk {\setcharactercasing[99]}
+\unexpanded\def\RandomPunk {\groupedcommand\EnableRandomPunk\donothing}
+\unexpanded\def\StartRandomPunk {\begingroup\EnableRandomPunk}
+\unexpanded\def\StopRandomPunk {\endgroup}
+
+\starttypescript [serif] [punk] [default]
+ \setups[font:fallback:serif] % no style variants yet
+ \definefontsynonym [Serif] [demo@punk]
+\stoptypescript
+
+\starttypescript [punk]
+ \definetypeface [punk] [rm] [serif] [punk] [default]
+\stoptypescript
+
+\definefontfeature[punknova][mode=node,script=latn,rand=yes,kern=yes,liga=yes,tlig=yes]
+
+\starttypescript [serif] [punknova]
+ \setups[font:fallback:serif] % no style variants yet, actually it's a sans
+ \definefontsynonym [Serif] [file:punknova] [features=punknova]
+\stoptypescript
+
+\starttypescript [punknova]
+ \definetypeface [punknova] [rm] [serif] [punknova] [default]
+\stoptypescript
+
+\endinput
+
+\usetypescript[punk]
+
+\setupbodyfont[punk,14pt]
+
+\starttext
+ \definedfont[demo@punk at 10pt]hello world\par
+ \definedfont[demo@punk at 12pt]hello world\par
+ \definedfont[demo@punk at 16pt]hello world\par
+ \definedfont[demo@punk at 20pt]hello world\par
+\stoptext
+
diff --git a/tex/context/base/m-punk.tex b/tex/context/base/m-punk.tex
new file mode 100644
index 000000000..fe7ec85cc
--- /dev/null
+++ b/tex/context/base/m-punk.tex
@@ -0,0 +1,3 @@
+% this file will disasppear but we need it as it is still in tex live
+
+\loadmarkfile{m-punk}
diff --git a/tex/context/base/m-quest.tex b/tex/context/base/m-quest.tex
new file mode 100644
index 000000000..d20c86c93
--- /dev/null
+++ b/tex/context/base/m-quest.tex
@@ -0,0 +1,232 @@
+%D \module
+%D [ file=m-invull,
+%D version=1995.01.10,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Exercise,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%I Invuloefeningen kunnen worden vormgegeven met het
+%I de commando's:
+%I
+%I \definieerinvulwoord[trefwoord]{woord,woord}
+%I \invulwoord[trefwoord]
+%I \invulwoord{woord,woord,...}
+%I
+%I Daarbij kan het een en ander worden ingesteld met
+%I
+%I \stelinvullenin[status=,nummer=,links=,rechts=,letter=]
+%P
+%I Er zijn drie manieren om woorden in te vullen. De meest
+%I eenvoudige is die waarbij de in te vullen woorden in de
+%I tekst staan.
+%I
+%I bla bla \invulwoord{een,alfa} bla bla bla bla bla bla
+%I bla bla bla bla bla bla bla bla \invulwoord{twee,beta}.
+%I
+%I De gezette tekst hangt af van de instellingen:
+%I
+%I [status=leeg] ________
+%I [status=vol,nummer=1] 'een' respectievelijk 'twee'
+%I [status=vol,nummer=2] 'alfa' respectievelijk 'beta'
+%I
+%I Het nummer heeft dus betrekking op het volgnummer in de
+%I opgegeven reeks.
+%P
+%I Bij de tweede manier worden eerste de alternatieven
+%I gedefinieerd:
+%I
+%I \definieerinvulwoord{een,alfa}
+%I \definieerinvulwoord{twee,beta}
+%I
+%I die vervolgens worden opgeroepen:
+%I
+%I bla \invulwoord[+] bla bla bla bla bla bla bla bla bla
+%I bla bla bla bla bla bla bla bla bla bla \invulwoord[+].
+%I
+%I De mogelijke instellingen komen overeen met die van de
+%I eerste manier.
+%P
+%I De derde manier is een variant op de tweede. Bij grote
+%I teksten kan men het overzicht kwijtraken. Het is daarom
+%I mogelijk 'logische' namen toe te kennen aan woorden.
+%I
+%I \definieerinvulwoord[a]{een,alfa}
+%I \definieerinvulwoord[b]{twee,beta}
+%I
+%I die vervolgens worden opgeroepen:
+%I
+%I bla \invulwoord[a] bla bla bla bla bla bla bla bla bla
+%I bla bla bla bla bla bla bla bla bla bla \invulwoord[b].
+%I
+%I Dit maakt het bovendien mogelijk woorden meerdere malen
+%I (in een willekeurige volgorde op te roepen:
+%I
+%I bla \invulwoord[a] bla \invulwoord[b] bla bla bla bla
+%I bla bla bla bla \invulwoord[b] bla bla \invulwoord[a].
+%P
+%I Bij [status=leeg] wordt een streep gezet die in breedte
+%I overeenkomt met het woord dat er eigenlijk hoort te
+%I staan. De ingevulde tekst komt visueel daardoor overeen
+%I met de in te vullen tekst, wat vergelijken vereenvoudigd.
+%I
+%I Met [status=reset] worden enkele tellers weer op 0 gezet.
+%I Dit kan nodig zijn als meerdere invuloefeningen in een
+%I tekst worden gezet.
+%I
+%I Als \versie[voorlopig] is ingesteld, worden bij invullers
+%I zonder logische namen tussen haakjes de volgnummers
+%I getoond.
+
+%S \startsetup
+%S \command
+%S [stelinvullenin]
+%S \type
+%S [\c!vars!]
+%S \variable
+%S [\c!letter]
+%S [\v!normaal,\v!vet,\v!schuin,\v!vetschuin,\v!type,\v!kap,
+%S \v!klein...,\c!command!]
+%S [\v!vet]
+%S \variable
+%S [\c!links]
+%S [\c!text!]
+%S []
+%S \variable
+%S [\c!rechts]
+%S [\c!text!]
+%S []
+%S \variable
+%S [\c!status]
+%S [\v!leeg,\v!vol,\v!reset]
+%S [\v!vol]
+%S \variable
+%S [\c!nummer]
+%S [\c!number!]
+%S [1]
+%S \variable
+%S [\c!lijn]
+%S [\v!aan,\v!uit]
+%S [\v!aan]
+%S \stopsetup
+
+%S \startsetup
+%S \command
+%S [invulwoord]
+%S \type
+%S [\c!ref!,\c!opt!\c!val!\c!opt!\c!args!]
+%S \value
+%S [\c!text!]
+%S \stopsetup
+
+%S \startsetup
+%S \command
+%S [definieerinvulwoord]
+%S \type
+%S [\c!ref!,\c!opt!\c!val!\c!args!]
+%S \value
+%S [\c!text!]
+%S \stopsetup
+
+% Mogelijke uitbreidingen
+%
+% - [breedte=,passend,ruim]
+% - invullijst met nummers
+% - weergeven lijst tijdens definitie blokkeren
+% - door elkaar definieren
+
+\unprotect
+
+\definesystemvariable {iv}
+
+\definereferenceconstant {fillin} {:iv:}
+
+\newcount\invulteller \newcount\invulput \newcount\invulget
+
+\def\stelinvullenin
+ {\dosingleargument\dostelinvullenin}
+
+\def\dostelinvullenin[#1]%
+ {\getparameters[\??iv][#1]%
+ \doif\@@ivstate\v!reset
+ {\global\invulput\zerocount
+ \global\invulget\zerocount
+ \let\@@ivstate\empty}}
+
+\def\definieerinvulwoord
+ {\dosingleempty\dodefinieerinvulwoord}
+
+\def\dodefinieerinvulwoord[#1]#2%
+ {\iffirstargument
+ \setgvalue{\r!fillin#1}{\simpleinvulwoord{#2}}%
+ \else
+ \global\advance\invulput \plusone
+ \setgvalue{\r!fillin\the\invulput}{\simpleinvulwoord{#2}}%
+ \fi
+ \doifconcepttracing
+ {\ifnum\invulput>\zerocount
+ \setbox\scratchbox\hbox{~\ttx(\the\invulput)}%
+ \wd\scratchbox\zeropoint
+ \box\scratchbox
+ \par
+ \fi}}
+
+\def\dosimpleinvulwoord#1%
+ {\ifnum\@@ivnumber>\zerocount \advance\invulteller \plusone \fi
+ \ifnum\invulteller=\@@ivnumber\relax
+ \bgroup
+ \doconvertfont\@@ivstyle
+ {\@@ivleft
+ \doifelse\@@ivstate\v!empty
+ {\doifelse\@@ivrule\v!on\leeginvulwoord\geeninvulwoord}
+ {\doifelse\@@ivrule\v!on\underbar \firstofoneargument}%
+ {#1}%
+ \@@ivright}%
+ \egroup
+ \fi}%
+
+\def\simpleinvulwoord#1%
+ {\ifnum\@@ivnumber>0
+ \invulteller\zerocount
+ \processcommalist[#1]\dosimpleinvulwoord
+ \else
+ \dosimpleinvulwoord{#1}%
+ \fi}
+
+\def\complexinvulwoord[#1]%
+ {\bgroup
+ \doifsomething{#1}
+ {\global\advance\invulget \plusone
+ \doconvertfont\@@ivstyle
+ {\@@ivleft\getvalue{\r!fillin\the\invulget}\@@ivright}}
+ {\doconvertfont\@@ivstyle
+ {\@@ivleft\getvalue{\r!fillin #1}\@@ivright}}%
+ \egroup}
+
+\definecomplexorsimple\invulwoord
+
+\def\leeginvulwoord#1%
+ {{\let\redounderbar\dodounderbar
+ \def\dodounderbar##1{\redounderbar{\hphantom{##1}}}%
+ \underbar{#1}}}
+
+\def\geeninvulwoord#1%
+ {{\def\dodounderbar##1{\hphantom{##1}}%
+ \underbar{#1}}}
+
+% when nummer > 0, then commalist processing; beware of $(1,2)$, use { } there
+
+\stelinvullenin
+ [\c!number=0,
+ \c!style=\v!bold,
+ \c!rule=\v!on,
+ \c!left=,
+ \c!right=,
+ \c!state=]
+
+\protect \endinput
diff --git a/tex/context/base/m-r.tex b/tex/context/base/m-r.tex
new file mode 100644
index 000000000..bf7b07a14
--- /dev/null
+++ b/tex/context/base/m-r.tex
@@ -0,0 +1,174 @@
+%D \module
+%D [ file=m-r,
+%D version=2006.06.06,
+%D title=\CONTEXT\ Modules,
+%D subtitle=R Support,
+%D author={Johan Sandblom \& Hans Hagen},
+%D date=\currentdate,
+%D copyright={PRAGMA / Johan Sandblom}]
+%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
+
+%D The following R-processor is a variation on Johan Sandblom's
+%D prototype.
+%D
+%D We can combine both variants in one macro definition. Also, we
+%D can minimize the number of runs by checking for a change.
+
+%D JS: The call to R has \type {-q} in order to prevent banner,
+%D \type {--save} to make sure it saves the workspace after the run,
+%D \type {--restore} to make sure it reads any workspace from a
+%D previous session.
+
+%D An easier and better solution is to use the buffering mechanisms:
+
+\def\Rbufferprefix{r-}
+
+\newcounter\nofRfiles
+
+\def\Rfile{\TEXbufferfile{\Rbufferprefix\nofRfiles}}%
+
+\def\startR
+ {\doglobal\increment\nofRfiles
+ \dostartbuffer[\Rbufferprefix\nofRfiles][startR][stopR]}
+
+\def\stopR
+ {\doifmode{*\v!first}\runR
+ \typefile{\Rfile.out}}
+
+\def\startRhidden
+ {\doglobal\increment\nofRfiles
+ \dostartbuffer[\Rbufferprefix\nofRfiles][startRhidden][stopRhidden]}
+
+\def\stopRhidden
+ {\doifmode{*\v!first}\runR}
+
+\def\runR
+ {\executesystemcommand{texmfstart
+ --ifchanged=\Rfile\space --direct R
+ CMD BATCH -q --save --restore \Rfile\space \Rfile.out}}
+
+\protect \doifnotmode{demo}{\endinput}
+
+% Johan's test file:
+
+\usemodule[r]
+
+\def\R{R}
+
+\setupcolors[state=start]
+
+\setuptyping
+ [Rtype]
+ [color=darkgreen]
+
+\starttext
+
+First a test of whether the workspace is persistent:
+bla
+
+\startR
+a <- "bla"
+b <- "blabla"
+ls()
+\stopR
+
+One \R run ends, another begins.
+
+\startR
+ls()
+\stopR
+
+Now follows a hidden \R run which cleans the R workspace
+
+\startRhidden
+rm(list=ls())
+save.image()
+\stopRhidden
+
+What is in the workspace now?
+
+\startR
+ls()
+\stopR
+
+Then a small test of generating a graphic, in this case a pdf
+\startR
+ushape <- c(rexp(500000), 12-rexp(500000))
+pdf("ushape.pdf")
+par(mfrow=c(1,2))
+hist(ushape)
+plot(density(ushape), main="Density")
+dev.off()
+\stopR
+
+The graphic \type{ushape.pdf} can be included in the standard \CONTEXT\ way
+\startbuffer
+\placefigure{An ugly distribution}{\externalfigure[ushape]}
+\stopbuffer
+\typebuffer
+\getbuffer
+
+\startR
+x <- rnorm(900)
+y <- rexp(900)
+# test comment
+f <- gl(9,9,900)
+summary(aov(y~x+Error(f)))
+library(lattice)
+pdf("lattice.pdf")
+xyplot(y~x|f)
+dev.off()
+\stopR
+
+With \type{Sweave} lattice graphics calls must be enclosed in
+\type{print()} statements but that is not necessary here.
+
+\startbuffer
+\placefigure[here]{Lattice graphics}{\externalfigure[lattice]}
+\stopbuffer
+\typebuffer
+\getbuffer
+
+A test string with nasty characters. In \R, the result of a statement
+is not printed by default. Enclosing the statement in parentheses,
+however causes the parser to see only the value of the statement and
+applying the \type{print()} method.
+\startR
+(test <- ".*\\\\ [[{[{]{[{[{}\]\}=?!+%#|<|>@$")
+cat(test)
+\stopR
+
+A combination
+\startbuffer
+\placefigure{A combination of two previously used graphics}{
+\startcombination[2*1]
+ {\externalfigure[ushape][width=.4\textwidth]}{The first graphic, rescaled}
+ {\externalfigure[lattice][width=.4\textwidth]}{The second graphic, rescaled}}
+\stopcombination
+\stopbuffer
+\typebuffer
+\getbuffer
+
+Testing a function definition.
+
+\startR
+a.df <- data.frame(a=1:2, b=rnorm(2))
+a.df$a
+testfunction <- function(a=NULL, ...) {
+ for(i in 1:length(a)) {
+ gsub(a[[i]], "([a-r]|[A-R])", "bla")}
+ print(a)}
+\stopR
+
+What is in the workspace now?
+
+\startR
+ls()
+\stopR
+
+\stoptext
diff --git a/tex/context/base/m-steps.mkii b/tex/context/base/m-steps.mkii
new file mode 100644
index 000000000..3e1f86312
--- /dev/null
+++ b/tex/context/base/m-steps.mkii
@@ -0,0 +1,83 @@
+%D \module
+%D [ file=m-steps,
+%D version=2001.05.28,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Step Charts \& Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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 \XML\ interface:
+
+\unprotect
+
+\defineXMLdirective [stepchart] [charts] \setupSTEPcharts
+\defineXMLdirective [stepchart] [cells] \setupSTEPcells
+\defineXMLdirective [stepchart] [texts] \setupSTEPtexts
+\defineXMLdirective [stepchart] [lines] \setupSTEPlines
+
+\defineXMLdirective [steptable] [tables] \setupSTEPtables
+\defineXMLdirective [steptable] [cells] \setupSTEPcells
+\defineXMLdirective [steptable] [texts] \setupSTEPtexts
+\defineXMLdirective [steptable] [lines] \setupSTEPlines
+
+\defineXMLpickup[stepchart][@@STPC]
+ {\bgroup
+ \defineXMLpush[top]%
+ \defineXMLpush[bot]%
+ \defineXMLenvironment[lines][@@STEL]
+ {\expanded{\startlines[\theXMLarguments{@@STEL}]}}
+ {\stoplines}%
+ \defineXMLenvironment[cells][@@STEC]
+ {\XMLerase{top}\XMLerase{bot}}
+ {\expanded{\cells[\theXMLarguments{@@STEC}]{\XMLpop{top}}{\XMLpop{bot}}}}%
+ \defineXMLenvironment[texts][@@STET]
+ {\XMLerase{top}\XMLerase{bot}}
+ {\expanded{\texts[\theXMLarguments{@@STET}]{\XMLpop{top}}{\XMLpop{bot}}}}%
+ \defineXMLenvironmentpush[cell][@@STEC]
+ {\XMLerase{cell}}
+ {\expanded{\cell [\theXMLarguments{@@STEC}]{\XMLpop{cell}}}}%
+ \defineXMLenvironmentpush [text] [@@STET]
+ {\XMLerase{text}}
+ {\expanded{\text [\theXMLarguments{@@STET}]{\XMLpop{text}}}}%
+ \expanded{\startSTEPchart[\theXMLarguments{@@STPC}]}}
+ {\stopSTEPchart
+ \egroup}
+
+\defineXMLpickup[steptable][@@STPT]
+ {\bgroup
+ \defineXMLenvironment[lines][@@STEL]
+ {\expanded{\startlines[\theXMLarguments{@@STEL}]}}
+ {\stoplines}%
+ \defineXMLargument[cell][@@STEC]
+ {\expanded{\cell[\theXMLarguments{@@STEC}]}}%
+ \defineXMLargument[text][@@STET]
+ {\expanded{\text[\theXMLarguments{@@STET}]}}%
+ \defineXMLargument[prep]
+ {\prep}%
+ \expanded{\startSTEPtable[\theXMLarguments{@@STPT}]}}
+ {\stopSTEPtable
+ \egroup}
+
+\defineXMLpickup[stepaligntable][@@STPT]
+ {\bgroup
+ \defineXMLenvironment[lines][@@STEL]
+ {\expanded{\setupSTEPlines[\theXMLarguments{@@STEL}]}}
+ {}%
+ \defineXMLpush[c1]\defineXMLpush[c2]\defineXMLpush[c3]%
+ \defineXMLenvironment[cells][@@STEC]
+ {\XMLerase{c1}\XMLerase{c1}\XMLerase{c3}}
+ {\expanded{\cells[\theXMLarguments{@@STEC}]{\XMLpop{c1}}{\XMLpop{c2}}{\XMLpop{c3}}}}%
+ \defineXMLargument[text][@@STET]
+ {\expanded{\text[\theXMLarguments{@@STET}]}}%
+ \defineXMLargument[prep]
+ {\prep}%
+ \expanded{\startSTEPaligntable[\theXMLarguments{@@STPT}]}}
+ {\stopSTEPaligntable
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/m-steps.mkiv b/tex/context/base/m-steps.mkiv
new file mode 100644
index 000000000..9bb56c532
--- /dev/null
+++ b/tex/context/base/m-steps.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=m-steps,
+%D version=2001.05.28,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Step Charts \& Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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 \XML\ interface:
+
+\unprotect
+
+\writestatus\m!systems{The steps mkiv xml interface is not yet defined!}
+
+\protect \endinput
diff --git a/tex/context/base/m-steps.tex b/tex/context/base/m-steps.tex
new file mode 100644
index 000000000..1f6a37403
--- /dev/null
+++ b/tex/context/base/m-steps.tex
@@ -0,0 +1,835 @@
+%D \module
+%D [ file=m-steps,
+%D version=2001.05.28,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Step Charts \& Tables,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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 When I need this module, I will reimplement it by using the new
+%D sometxt macro. Anyhow, it reflects the state of 2001.
+
+\unprotect
+
+% temp hack :
+
+% \ifx\v!kleinkorps\undefined \let\v!kleinkorps\setsmallbodyfont \fi
+
+% end of hack
+
+\definecolor [STEPlinecolor] [s=.5]
+\definecolor [STEPframecolor] [s=.7]
+\definecolor [STEPbackgroundcolor] [s=.9]
+
+\def\@@STPF{@@STPF} % frames
+
+\def\@@STPC{@@STPC} % charts
+\def\@@STPT{@@STPT} % tables
+
+\def\@@STEC{@@STEC} % cells
+\def\@@STET{@@STET} % tables
+\def\@@STEL{@@STEL} % lines
+
+\def\setupSTEPcharts{\dodoubleargument\getparameters[\@@STPC]}
+\def\setupSTEPtables{\dodoubleargument\getparameters[\@@STPT]}
+\def\setupSTEPcells {\dodoubleargument\getparameters[\@@STEC]}
+\def\setupSTEPtexts {\dodoubleargument\getparameters[\@@STET]}
+\def\setupSTEPlines {\dodoubleargument\getparameters[\@@STEL]}
+
+\setupSTEPcharts
+ [\c!before=\blank,
+ \c!after=\blank,
+ %\c!distance=.25em, % nvt
+ \c!hoffset=1em,
+ \c!voffset=1ex,
+ \c!method=1,
+ \c!height=2ex,
+ \c!offset=.15\bodyfontsize]
+
+\setupSTEPtables
+ [\c!before=\blank,
+ \c!after=\blank,
+ \c!distance=.25em,
+ %\c!hoffset=1em, % nvt
+ \c!voffset=1ex,
+ \c!method=1,
+ \c!width=4em,
+ \c!offset=.15\bodyfontsize]
+
+\setupSTEPcells
+ [\c!alternative=24,
+ \c!background=\v!color,
+ \c!backgroundcolor=STEPbackgroundcolor,
+ \c!rulethickness=.1\bodyfontsize,
+ \c!framecolor=STEPframecolor,
+ \c!offset=.25\bodyfontsize,
+ \c!style=,
+ \c!color=]
+
+\setupSTEPtexts
+ [\c!alternative=24,
+ \c!background=\v!color,
+ \c!backgroundcolor=STEPbackgroundcolor,
+ \c!rulethickness=.1\bodyfontsize,
+ \c!framecolor=STEPframecolor,
+ \c!offset=.25\bodyfontsize,
+ \c!style=\v!smallbodyfont,
+ \c!color=]
+
+\setupSTEPlines
+ [\c!alternative=1,
+ \c!rulethickness=.15\bodyfontsize,
+ \c!color=STEPlinecolor]
+
+\def\initializeSTEP
+ {\initializeSTET \initializeSTEC \initializeSTEL}
+
+\def\initializeSTPC
+ {\freezedimenmacro\@@STPCoffset
+ \startMPdrawing
+ line_v_offset := \@@STPCoffset ;
+ line_method := \@@STPCmethod ; % only charts
+ \stopMPdrawing}
+
+\def\initializeSTPT
+ {\freezedimenmacro\@@STPToffset
+ \startMPdrawing
+ line_h_offset := \@@STPToffset ;
+ line_method := \@@STPTmethod ; % only charts
+ \stopMPdrawing}
+
+\def\initializeSTET
+ {\freezedimenmacro\@@STETrulethickness
+ \freezedimenmacro\@@STEToffset}
+
+\def\initializeSTEC
+ {\freezedimenmacro\@@STECrulethickness
+ \freezedimenmacro\@@STECoffset}
+
+\def\initializeSTEL
+ {\freezedimenmacro\@@STELrulethickness}
+
+%D ...
+
+\presetlocalframed[\@@STPF]
+
+\def\@@stepcell#1%
+ {\doattributes\@@STEC\c!style\c!color
+ {\localframed
+ [\@@STPF][\c!offset=\@@STECoffset,\c!frame=\v!off]
+ {\ignorespaces#1\unskip}}}
+
+\def\@@stepfake#1%
+ {\doattributes\@@STEC\c!style\c!color
+ {\ignorespaces#1\unskip}}
+
+\def\@@steptext#1%
+ {\doattributes\@@STET\c!style\c!color
+ {\localframed
+ [\@@STPF][\c!offset=\@@STEToffset,\c!frame=\v!off]
+ {\ignorespaces#1\unskip}}}
+
+%D The first attempt was purely \METAPOST\ based and spawned
+%D the typesetting to the \METAFUN\ handler. This method
+%D collects the cells, and directly passes them on to
+%D \METAPOST. This method is the cleanest, but has the
+%D disadvantage that one cannot embed hyperlinks or document
+%D dependent definitions in the cells. The implementation
+%D roughly looks as follows:
+%D
+%D \starttyping
+%D \def\startSTEPchart%
+%D {\bgroup
+%D \startMPdrawing
+%D input mp-step ; begin_step_chart ;
+%D \stopMPdrawing
+%D \initializeSTEP
+%D \let\cells\stepchartcells \def\cell{\cells{}}%
+%D \let\texts\stepcharttexts \def\text{\texts{}}}
+%D
+%D \def\stepchartcells#1#2%
+%D {\setMPtext{tdummy}{\strut\ignorespaces#1\unskip}% beter etex/btex
+%D \setMPtext{bdummy}{\strut\ignorespaces#2\unskip}% beter etex/btex
+%D \startMPdrawing
+%D set_step_chart_cells(\MPstring{tdummy},\MPstring{bdummy}) ;
+%D \stopMPdrawing}
+%D
+%D \def\stepcharttexts#1#2%
+%D {\setMPtext{tdummy}{\strut\ignorespaces#1\unskip}% beter etex/btex
+%D \setMPtext{bdummy}{\strut\ignorespaces#2\unskip}% beter etex/btex
+%D \startMPdrawing
+%D set_step_chart_texts(\MPstring{tdummy},\MPstring{bdummy}) ;
+%D \stopMPdrawing}
+%D
+%D \def\stopSTEPchart
+%D {\startMPdrawing
+%D end_step_chart ;
+%D \stopMPdrawing
+%D \MPdrawingdonetrue
+%D \getMPdrawing
+%D \resetMPdrawing
+%D \egroup}
+%D \stoptyping
+%D
+%D This method has the advantage that it does the job in
+%D (virtually) one pass, while the next methods need multiple
+%D passes: one to build the table, another to synchronize the
+%D positions, and a third one beause the dimensions may have
+%D changed. The last pass is a result from the fact that
+%D positions are related to the page.
+%D
+%D The second attempt was based on tabulations and used the
+%D build in position tracking mechanism, which uses two
+%D position nodes per cell.
+%D
+%D This method collects the content in token list registers
+%D and build a table from them. In the collecting pass, the
+%D graphics are build stepwise. We need to collect because the
+%D order of definitions is not the same as the order of
+%D typesetting. We show this alternative too because it
+%D demonstrates how to apply backgrounds to table cells.
+%D
+%D \starttyping
+%D \newtoks\stepsonetop \newtoks\stepstwotop
+%D \newtoks\stepsonebot \newtoks\stepstwobot
+%D \stoptyping
+%D
+%D During the collecting phase, we temporarily have to
+%D increment the name space counter.
+%D
+%D \starttyping
+%D \def\startSTEPchart%
+%D {\bgroup
+%D \resetMPdrawing
+%D \advance\noftabpositions\plusone % begin of preroll
+%D \startMPdrawing
+%D input mp-step ;
+%D begin_step_chart ;
+%D \stopMPdrawing
+%D \initializeSTEP
+%D \newcounter\cellcounter
+%D \stepsonetop\emptytoks \chardef\somesteponetop=1
+%D \stepsonebot\emptytoks \chardef\somesteponebot=1
+%D \stepstwotop\emptytoks \chardef\somesteptwotop=1
+%D \stepstwobot\emptytoks \chardef\somesteptwobot=1
+%D \let\cells\stepchartcells \def\cell{\cells{}}%
+%D \let\texts\stepcharttexts \def\text{\texts{}}}
+%D \stoptyping
+%D
+%D Now we collect the steps and texts, and in the process the
+%D graphic is built. Then we continue with building the table.
+%D
+%D Watch how we anchor the graphic to the main table box. This
+%D is needed since the graphic may be larger than the table
+%D itself. Actually, these small point took me the most time to
+%D digest, even with the right tools (anchors) already in
+%D place.
+%D
+%D \starttyping
+%D \def\stopSTEPchart
+%D {\splittabulatefalse
+%D \insidefloattrue
+%D \startMPdrawing
+%D nofcells := \cellcounter ;
+%D end_step_chart ;
+%D anchor_box(\MPpos{\tbPOSprefix origin}) ;
+%D \stopMPdrawing
+%D \MPdrawingdonetrue
+%D \advance\noftabpositions\minusone % end of preroll
+%D \setbox0=\vbox
+%D {\getMPdrawing}
+%D \resetMPdrawing
+%D \increment(\cellcounter,\cellcounter)\decrement\cellcounter
+%D \setbox2=\vbox
+%D {\definetabulate[chart][|*{\cellcounter}{ck0|}] % k0 nills space
+%D \startchart
+%D \ifcase\somesteptwotop \the\stepstwotop \NC \NR \noalign{\kern2ex} \fi
+%D \ifcase\somesteponetop \the\stepsonetop \NC \NR \noalign{\kern2ex} \fi
+%D \ifcase\somesteponebot \the\stepsonebot \NC \NR \noalign{\kern2ex} \fi
+%D \ifcase\somesteptwobot \the\stepstwobot \NC \NR \noalign{\kern2ex} \fi
+%D \noalign{\kern-2ex}%
+%D \stopchart}
+%D \hbox
+%D {\scratchdimen\wd0
+%D \advance\scratchdimen \MPllx bp
+%D \raise\MPlly bp\box0
+%D \hskip-\scratchdimen
+%D \hpos{\tbPOSprefix origin}{\box2}}
+%D \egroup}
+%D \stoptyping
+%D
+%D The steps and texts fill the (at most 4) lines that make up
+%D the table. We also feed the (automatically registerd) cell
+%D dimensions to the graphic backend.
+%D
+%D \starttyping
+%D \newcounter\cellcounter
+%D \newcounter\textcounter
+%D
+%D \def\stepchartcells#1#2%
+%D {\doloop
+%D {\ifnum\cellcounter>\textcounter
+%D \stepcharttexts{}{}%
+%D \else
+%D \exitloop
+%D \fi}%
+%D \increment\cellcounter
+%D \doifelsenothing{#1}
+%D {\startMPdrawing
+%D cells[t][\cellcounter] := origin ;
+%D \stopMPdrawing
+%D \appendtoks\NC\NC\to\stepsonetop}
+%D {\chardef\somesteponetop=0
+%D \edef\stepidentifier{\cellcounter-t-c}%
+%D \startMPdrawing
+%D initialize_area(\MPpos{b:\tbPOSprefix\stepidentifier},
+%D \MPpos{e:\tbPOSprefix\stepidentifier}) ;
+%D cells[t][\cellcounter] := pxy ;
+%D \stopMPdrawing
+%D \@EA\appendtoks\@EA\stepidentifierposition\@EA{\stepidentifier}#1\NC\to\stepsonetop}%
+%D \doifelsenothing{#2}
+%D {\startMPdrawing
+%D cells[b][\cellcounter] := origin ;
+%D \stopMPdrawing
+%D \appendtoks\NC\NC\to\stepsonebot}
+%D {\chardef\somesteponebot=0
+%D \edef\stepidentifier{\cellcounter-b-c}%
+%D \startMPdrawing
+%D initialize_area(\MPpos{b:\tbPOSprefix\stepidentifier},
+%D \MPpos{e:\tbPOSprefix\stepidentifier}) ;
+%D cells[b][\cellcounter] := pxy ;
+%D \stopMPdrawing
+%D \@EA\appendtoks\@EA\stepidentifierposition\@EA{\stepidentifier}#2\NC\to\stepsonebot}}
+%D
+%D \def\stepcharttexts#1#2% \cellcounter = nofcells
+%D {\increment\textcounter
+%D \doifelsenothing{#1}
+%D {\startMPdrawing
+%D texts[t][\cellcounter][\textcounter] := origin ;
+%D \stopMPdrawing
+%D \appendtoks\NC\NC\to\stepstwotop}
+%D {\chardef\somesteptwotop=0
+%D \edef\stepidentifier{\cellcounter-\textcounter-t-t}%
+%D \startMPdrawing
+%D initialize_area(\MPpos{b:\tbPOSprefix\stepidentifier},
+%D \MPpos{e:\tbPOSprefix\stepidentifier}) ;
+%D texts[t][\cellcounter][\textcounter] := pxy ;
+%D \stopMPdrawing
+%D \@EA\appendtoks\@EA\NC\@EA\textcellposition\@EA{\stepidentifier}#1\to\stepstwotop}%
+%D \doifelsenothing{#2}
+%D {\startMPdrawing
+%D texts[b][\cellcounter][\textcounter] := origin ;
+%D \stopMPdrawing
+%D \appendtoks\NC\NC\to\stepstwobot}
+%D {\chardef\somesteptwobot=0
+%D \edef\stepidentifier{\cellcounter-\textcounter-b-t}%
+%D \startMPdrawing
+%D initialize_area(\MPpos{b:\tbPOSprefix\stepidentifier},
+%D \MPpos{e:\tbPOSprefix\stepidentifier}) ;
+%D texts[b][\cellcounter][\textcounter] := pxy ;
+%D \stopMPdrawing
+%D \@EA\appendtoks\@EA\NC\@EA\textcellposition\@EA{\stepidentifier}#2\to\stepstwobot}}
+%D \stoptyping
+%D
+%D Here are the hooks that take care of calculating the cell
+%D dimensions.
+%D
+%D \starttyping
+%D \def\textcellposition#1{\GSC[#1:text]}
+%D \def\stepidentifierposition#1{\GSC[#1:step]}
+%D \stoptyping
+%D
+%D We abandoned this method after some testing and went for
+%D a third one. It was this third method that evolved into the
+%D current mechanism.
+%D
+%D Since this method was not that efficient, a third one was
+%D implemented, which used one position per cell. So,
+%D
+%D \blank {\bf Here starts the real implementation!} \blank
+%D
+%D Because we want to build one graphic only we need to store
+%D the graphic directives. We also need to collect the cells,
+%D which are not defined in the order they show up. This
+%D solution uses multiple passes over the definitions. First
+%D the cells and texts are processed and the associated
+%D graphics are defined in the \METAPOST\ file. Next the
+%D lines are flushed. We need to do that in a second pass,
+%D because in order to determine the nature of the line,
+%D \METAPOST\ needs to know if the start and end cells exist.
+%D This need comes from the fact that we store the shapes
+%D and lines kind of directly with their associated colors and
+%D types, so that we can change the settings in between. So,
+%D changing for instance the line color, can take place
+%D locally.
+
+\newbox\stepboxone \newbox\stepboxtwo
+\newbox\textboxone \newbox\textboxtwo
+
+%D We need to define a dedicated name space counter.
+
+\newcounter\currentstepchart
+
+\def\stepchartprefix{@sc@-\currentstepchart-}
+
+%D Next we define the initialization part of the macros.
+
+\newcounter\cellcounter
+\newcounter\textcounter
+
+\def\startSTEPchart
+ {\dosingleempty\dostartSTEPchart}
+
+\long\def\dostartSTEPchart[#1]#2\stopSTEPchart
+ {\ifinsidefloat
+ \else
+ \whitespace
+ \@@STPCbefore
+ \startbaselinecorrection
+ \setlocalhsize
+ \noindent
+ \fi
+ \vbox\bgroup
+ \setupSTEPcharts[#1]%
+ \forgetall
+ \pushMPdrawing
+ \resetMPdrawing
+ \doglobal\increment\currentstepchart
+ \startMPdrawing
+ input mp-step ;
+ begin_step_chart ;
+ \stopMPdrawing
+ \initializeSTEP
+ \initializeSTPC
+ \global\chardef\somestepboxone\plusone
+ \global\chardef\sometextboxone\plusone
+ \global\chardef\somestepboxtwo\somestepboxone
+ \global\chardef\sometextboxtwo\sometextboxone
+ \def\startlines{\bgroup\setupSTEPlines}%
+ \def\stoplines {\egroup}%
+ \def\cells{\dosingleempty\dostepchartcells}
+ \def\texts{\dosingleempty\dostepcharttexts}
+ \def\cell {\dosingleempty\docell}%
+ \def\text {\dosingleempty\dotext}%
+ \def\docell[##1]{\dostepchartcells[##1]{}}%
+ \def\dotext[##1]{\dostepcharttexts[##1]{}}
+ \doglobal\newcounter\cellcounter
+ \doglobal\newcounter\textcounter
+ \let\dostepchartcells\doSTEPchartcellsA
+ \let\dostepcharttexts\doSTEPcharttextsA
+ {#2} % pass one: cells and texts {} keeps setting local
+ \startMPdrawing
+ nofcells := \cellcounter ;
+ analyze_step_chart ;
+ \stopMPdrawing
+ \doglobal\newcounter\cellcounter
+ \doglobal\newcounter\textcounter
+ \let\dostepchartcells\doSTEPchartcellsB
+ \let\dostepcharttexts\doSTEPcharttextsB
+ {#2} % pass two: lines
+ \startMPdrawing
+ end_step_chart ;
+ % if box_found(\MPpos{\stepchartprefix origin}) :
+ % initialize_box(\MPpos{\stepchartprefix origin}) ;
+ % draw pxy ;
+ % fi ;
+ anchor_box(\MPpos{\stepchartprefix origin}) ;
+ \stopMPdrawing
+ \MPdrawingdonetrue
+ \doifelse\@@STPCmethod{0}
+ {\setbox0\null}
+ {\setbox0\vbox{\MPstaticgraphictrue\getMPdrawing}}%
+ \resetMPdrawing
+ \setbox2\vbox
+ {\offinterlineskip
+ \scratchdimen\@@STPCheight
+ \advance\scratchdimen\@@STPCoffset
+ \advance\scratchdimen\@@STPCoffset
+ \ifcase\sometextboxone \box\textboxone \vskip\scratchdimen \fi
+ \ifcase\somestepboxone \box\stepboxone \vskip\@@STPCvoffset \fi
+ \ifcase\somestepboxtwo \box\stepboxtwo \vskip\scratchdimen \fi
+ \ifcase\sometextboxtwo \box\textboxtwo \vskip\@@STPCvoffset \fi
+ \global\resetbox\stepboxone \global\resetbox\stepboxtwo % needed indeed
+ \global\resetbox\textboxone \global\resetbox\textboxtwo % needed indeed
+ %\kern-\scratchdimen % no, instead:
+ \vskip-\lastskip}
+ \hbox
+ {\scratchdimen\wd0
+ \advance\scratchdimen \MPllx bp
+ \raise\MPlly bp\box0
+ \hskip-\scratchdimen
+ \hpos{\stepchartprefix origin}{\box2}}%
+ \popMPdrawing
+ \egroup
+ \ifinsidefloat \else \stopbaselinecorrection \@@STPCafter \fi}
+
+%D The next macro looks more complicated than it is. We collect
+%D the cells in boxes. Before adding a new step cell, we padd
+%D the text rows. After adding the step cells, we flush text
+%D cells that are defined but not yet processed.
+
+\def\doSTEPchartcellsA[#1]#2#3%
+ {% synchronize texts
+ \doSTEPchartcellsAB[#1]{#2}{#3}%
+ % package steps
+ \setbox0\hbox{\doifsomething{#2}{\@@stepcell{#2}}}%
+ \setbox2\hbox{\doifsomething{#3}{\@@stepcell{#3}}}%
+ \ifdim\wd0>\zeropoint \!!doneafalse \else \!!doneatrue \fi
+ \ifdim\wd2>\zeropoint \!!donebfalse \else \!!donebtrue \fi
+ \ifdim\wd0>\wd2
+ \setbox2\hbox to \wd0{\hss\box2\hss}%
+ \else
+ \setbox0\hbox to \wd2{\hss\box0\hss}%
+ \fi
+ \if!!donea
+ \startMPdrawing
+ cells[t][\cellcounter] := nullpicture ;
+ \stopMPdrawing
+ \else
+ \global\chardef\somestepboxone\zerocount
+ \edef\stepidentifier{\stepchartprefix\cellcounter-t-c}%
+ \setbox0\hbox{\hpos{\stepidentifier}{\box0}}%
+ \bgroup
+ \iffirstargument\setupSTEPcells[#1]\fi\initializeSTEC
+ \startMPdrawing
+ initialize_box(\MPpos{\stepidentifier}) ;
+ cells[t][\cellcounter] := \MPcellsgraphic ;
+ \stopMPdrawing
+ \egroup
+ \fi
+ \if!!doneb
+ \startMPdrawing
+ cells[b][\cellcounter] := nullpicture ;
+ \stopMPdrawing
+ \else
+ \global\chardef\somestepboxtwo\zerocount
+ \edef\stepidentifier{\stepchartprefix\cellcounter-b-c}%
+ \setbox2\hbox{\hpos{\stepidentifier}{\box2}}%
+ \bgroup
+ \iffirstargument\setupSTEPcells[#1]\fi\initializeSTEC
+ \startMPdrawing
+ initialize_box(\MPpos{\stepidentifier}) ;
+ cells[b][\cellcounter] := \MPcellsgraphic ;
+ \stopMPdrawing
+ \egroup
+ \fi
+ \global\setbox\stepboxone\hbox
+ {\ifdim\wd\stepboxone>\zeropoint
+ \box\stepboxone\hskip\@@STPChoffset\else
+ \fi\box0}%
+ \global\setbox\stepboxtwo\hbox
+ {\ifdim\wd\stepboxtwo>\zeropoint
+ \box\stepboxtwo\hskip\@@STPChoffset\else
+ \fi\box2}%
+ % flush saved texts
+ \doSTEPchartcellsBA}
+
+\def\doSTEPchartcellsB[#1]#2#3%
+ {\doSTEPchartcellsAB[#1]{#2}{#3}%
+ \doSTEPchartcellsBA}
+
+\def\doSTEPchartcellsAB[#1]#2#3%
+ {\doloop
+ {\ifnum\cellcounter>\textcounter
+ \texts{}{}\else\exitloop
+ \fi}%
+ \doglobal\increment\cellcounter}
+
+\def\doSTEPchartcellsBA
+ {\scratchtoks\stepchartbuffer
+ \stepchartbuffer\emptytoks
+ \the\scratchtoks}
+
+\def\MPcellsgraphic
+ {image ( drawshape (
+ \@@STECalternative, pxy enlarged (-.5*\@@STECoffset),
+ \@@STECrulethickness, \MPcolor{\@@STECframecolor},
+ \MPcolor{\@@STECbackgroundcolor} ) )}
+
+%D Although each step can have only one associated text, the
+%D place where the text is defined determines the starting
+%D point of the connecting arrow. Although several methods are
+%D possible, we've chosen a funny collector that flushes one
+%D step text at a time.
+
+\newtoks\stepchartbuffer
+
+\def\doSTEPcharttextsA[#1]% #2 #3
+ {\dodoSTEPcharttextsA{\cellcounter}{#1}}
+
+\def\dodoSTEPcharttextsA#1#2#3#4% #1=number #2=setup
+ {\dodoSTEPcharttextsAB{#1}{#2}{#3}{#4}\dodoSTEPcharttextsA
+ \ifnum\textcounter>\cellcounter\relax
+ \doglobal\decrement\textcounter\relax
+ \else
+ \setbox0\hbox{\doifsomething{#3}{\@@steptext{#3}}}%
+ \setbox2\hbox{\doifsomething{#4}{\@@steptext{#4}}}%
+ \ifdim\wd0>\zeropoint \!!doneafalse \else \!!doneatrue \fi
+ \ifdim\wd2>\zeropoint \!!donebfalse \else \!!donebtrue \fi
+ \if!!donea
+ \setbox0\hbox to \@@STPChoffset{\hss}%
+ \startMPdrawing
+ texts[t][#1][\textcounter] := nullpicture ;
+ \stopMPdrawing
+ \else
+ \global\chardef\sometextboxone\zerocount
+ \edef\stepidentifier{\stepchartprefix#1-\textcounter-t-t}%
+ \setbox0\hbox to \@@STPChoffset
+ {\hss\hpos{\stepidentifier}{\box0}\hss}%
+ \bgroup
+ \setupSTEPtexts[#2]\initializeSTET
+ \startMPdrawing
+ initialize_box(\MPpos{\stepidentifier}) ;
+ texts[t][#1][\textcounter] := \MPtextsgraphic ;
+ \stopMPdrawing
+ \egroup
+ \fi
+ \if!!doneb
+ \setbox2\hbox to \@@STPChoffset{\hss}%
+ \startMPdrawing
+ texts[b][#1][\textcounter] := nullpicture ;
+ \stopMPdrawing
+ \else
+ \global\chardef\sometextboxtwo\zerocount
+ \edef\stepidentifier{\stepchartprefix#1-\textcounter-b-t}%
+ \setbox2\hbox to \@@STPChoffset
+ {\hss\hpos{\stepidentifier}{\box2}\hss}%
+ \bgroup
+ \setupSTEPtexts[#2]\initializeSTET
+ \startMPdrawing
+ initialize_box(\MPpos{\stepidentifier}) ;
+ texts[b][#1][\textcounter] := \MPtextsgraphic ;
+ \stopMPdrawing
+ \egroup
+ \fi
+ \global\setbox\textboxone\hbox
+ {\hbox to \wd\stepboxone{\box\textboxone\hss}\box0}
+ \global\setbox\textboxtwo\hbox
+ {\hbox to \wd\stepboxtwo{\box\textboxtwo\hss}\box2}
+ \fi}
+
+\def\doSTEPcharttextsB[#1]% #2 #3
+ {\dodoSTEPcharttextsB{\cellcounter}{#1}}
+
+\def\dodoSTEPcharttextsB#1#2#3#4% #1=number #2=setup
+ {\dodoSTEPcharttextsAB{#1}{#2}{#3}{#4}\dodoSTEPcharttextsB
+ \ifnum\textcounter>\cellcounter\relax
+ \doglobal\decrement\textcounter\relax
+ \else
+ \bgroup
+ \initializeSTEL
+ \startMPdrawing
+ lines[t][#1][\textcounter] := \MPcharttoplinesgraphic{#1}\textcounter ;
+ lines[b][#1][\textcounter] := \MPchartbotlinesgraphic{#1}\textcounter ;
+ \stopMPdrawing
+ \egroup
+ \fi}
+
+\def\dodoSTEPcharttextsAB#1#2#3#4#5% #1=number #2=setup
+ {\doglobal\increment\textcounter\relax
+ \ifnum\textcounter>\cellcounter\relax
+ \@EA\appendtoks\@EA#5\@EA{#1}{#2}{#3}{#4}\to\stepchartbuffer
+ \fi}
+
+\def\MPtextsgraphic
+ {image(drawshape(
+ \@@STETalternative, pxy enlarged (-.5*\@@STEToffset),
+ \@@STETrulethickness, \MPcolor{\@@STETframecolor},
+ \MPcolor{\@@STETbackgroundcolor} ) )}
+
+\def\MPcharttoplinesgraphic#1#2%
+ {image(drawline(
+ \@@STELalternative, get_step_chart_top_line(#1,#2),
+ \@@STELrulethickness, \MPcolor{\@@STELcolor} ) )}
+
+\def\MPchartbotlinesgraphic#1#2%
+ {image(drawline(
+ \@@STELalternative, get_step_chart_bot_line(#1,#2),
+ \@@STELrulethickness, \MPcolor{\@@STELcolor} ) )}
+
+%D Step tables are the vertical counterpart of stepcharts.
+
+\newcounter\currentsteptable
+
+\def\steptableprefix{@st@-\currentsteptable-}
+
+\def\startSTEPtable
+ {\dosingleempty\dostartSTEPtable}
+
+\def\dostartSTEPtable[#1]#2\stopSTEPtable
+ {\dostartSTEPaligntable[0][#1]#2\stopSTEPaligntable}
+
+\def\startSTEPaligntable
+ {\dodoubleempty\dostartSTEPaligntable[1]}
+
+\def\dostartSTEPaligntable[#1][#2]#3\stopSTEPaligntable % flag settings data
+ {\ifinsidefloat
+ \else
+ \whitespace
+ \@@STPTbefore
+ \startbaselinecorrection
+ \setlocalhsize
+ \noindent
+ \fi
+ \vbox\bgroup
+ \setupSTEPtables[#2]%
+ \forgetall
+ \pushMPdrawing
+ \doglobal\increment\currentsteptable
+ \startMPdrawing
+ input mp-step ;
+ begin_step_table ;
+ \stopMPdrawing
+ \initializeSTEP
+ \initializeSTPT
+ \def\startlines{\bgroup\setupSTEPlines}%
+ \def\stoplines {\egroup}%
+ \def\prep##1{\ignorespaces##1\unskip\enspace\ignorespaces}%
+ \def\cell {\dosingleempty\docell}%
+ \def\cells {\dosingleempty\docells}%
+ \def\text {\dosingleempty\dotext}%
+ % first graphic pass, also trial pass
+ \global\dimen1\zeropoint
+ \global\dimen3\zeropoint
+ \global\dimen5\zeropoint
+ \def\docell[##1]%
+ {\docells[##1]{}{}}%
+ \def\docells[##1]##2##3##4%
+ {\doglobal\increment\cellcounter
+ \bgroup
+ \iffirstargument\setupSTEPcells[##1]\fi
+ \initializeSTEC
+ \startMPdrawing
+ if box_found(\MPpos{\steptableprefix\cellcounter-c}) :
+ initialize_box(\MPpos{\steptableprefix\cellcounter-c}) ;
+ cells[\cellcounter] := \MPcellsgraphic ;
+ fi ;
+ \stopMPdrawing
+ \egroup
+ \def\do####1####2%
+ {\setbox\scratchbox\hbox{\@@stepfake{####2}}%
+ \ifdim\wd\scratchbox>\dimen####1\global\dimen####1=\wd\scratchbox\fi}%
+ \ifcase#1\else\do1{##2}\do3{##3}\fi\do5{##4}}%
+ \def\dotext[##1]##2%
+ {\bgroup
+ \iffirstargument\setupSTEPtexts[##1]\fi
+ \initializeSTET
+ \startMPdrawing
+ if box_found(\MPpos{\steptableprefix\cellcounter-t}) :
+ initialize_box(\MPpos{\steptableprefix\cellcounter-t}) ;
+ texts[\cellcounter] := \MPtextsgraphic ;
+ fi ;
+ \stopMPdrawing
+ \egroup}
+ \doglobal\newcounter\cellcounter#3
+ % second graphic pass pass, drawing lines
+ \def\docells[##1]##2##3##4%
+ {\doglobal\increment\cellcounter}
+ \def\dotext[##1]##2%
+ {\bgroup
+ \initializeSTEL
+ \startMPdrawing
+ lines[\cellcounter] := \MPtablelinesgraphic ;
+ \stopMPdrawing
+ \egroup}
+ \doglobal\newcounter\cellcounter#3
+ % finishing graphic touch
+ \startMPdrawing
+ nofcells := \cellcounter ;
+ end_step_table ;
+ anchor_box(\MPpos{\steptableprefix origin}) ;
+ \stopMPdrawing
+ \MPdrawingdonetrue
+ \doifelse\@@STPTmethod{0}
+ {\setbox0\null}
+ {\setbox0\vbox{\MPstaticgraphictrue\getMPdrawing}}%
+ \resetMPdrawing
+ % typesetting pass
+ \dimen6=\@@STPTdistance \dimen6=2\dimen6
+ % cell width
+ \dimen8=\dimen1
+ \advance\dimen8\dimen3
+ \advance\dimen8\dimen5
+ % offset width
+ \ifcase#1\else \advance\dimen8 \dimen6 \fi
+ % arrow width
+ \advance\dimen8 \@@STPTwidth
+ \advance\dimen8 \@@STPToffset
+ \advance\dimen8 \@@STPToffset
+ \def\docells[##1]##2##3##4%
+ {\doglobal\increment\cellcounter
+ \def\do####1####2####3####4% % strut really needed there !
+ {\hbox to \dimen####1{####2\@@stepfake{####3}\strut####4}}%
+ \setbox8\hbox
+ {\ifcase#1\else
+ \do1\hss{##2}\relax \hskip\@@STPTdistance
+ \do3\hss{##3}\hss \hskip\@@STPTdistance
+ \fi
+ \do5\relax{##4}\hss}%
+ \hpos{\steptableprefix\cellcounter-c}{\@@stepcell{\box8}}
+ \endgraf
+ \nointerlineskip
+ \kern\@@STPTvoffset}
+ \def\dotext[##1]##2%
+ {\bgroup
+ \hskip\dimen8
+ \advance\hsize-\dimen8
+ \advance\hsize-\dimen6 % twice the offset
+ \setbox0\hbox{\@@steptext{##2}}%
+% to do
+% \ifdim\wd0>\hsize
+% \setbox0=\vbox{\@@steptext{##2}}%
+% \fi
+% align
+ \hpos{\steptableprefix\cellcounter-t}{\box0}%
+ \endgraf
+ \egroup
+ \nointerlineskip
+ \kern\@@STPTvoffset}
+ \setbox2\vbox
+ {\doglobal\newcounter\cellcounter
+ #3\kern-\@@STPTvoffset}
+ \hbox
+ {\scratchdimen\wd0
+ \advance\scratchdimen \MPllx bp
+ \raise\MPlly bp\box0
+ \hskip-\scratchdimen
+ \hpos{\steptableprefix origin}{\box2}}
+ \popMPdrawing
+ \egroup
+ \ifinsidefloat \else \stopbaselinecorrection \@@STPTafter \fi}
+
+\def\MPtablelinesgraphic
+ {image ( drawline (
+ \@@STELalternative, get_step_table_line(\cellcounter),
+ \@@STELrulethickness, \MPcolor{\@@STELcolor} ) )}
+
+\protect \endinput
+
+% A simple paragraph-flow test:
+
+\starttext
+
+\startbuffer
+\startSTEPchart
+\cells {A} {B}
+\cells {one} {five} \texts{$+2$}{$-2$}
+\cells {two} {four} \texts{$+3$}{$-3$}
+\cells {three} {three} \texts{$+4$}{$-4$}
+\cells {four} {two} \texts{$+5$}{$-5$}
+\cells {five} {one}
+\stopSTEPchart
+\stopbuffer
+
+\getbuffer
+
+\startnarrower \getbuffer \stopnarrower
+
+\placefigure[left]{}{} \getbuffer
+
+\stoptext
diff --git a/tex/context/base/m-streams.tex b/tex/context/base/m-streams.tex
new file mode 100644
index 000000000..9d7e8d7dd
--- /dev/null
+++ b/tex/context/base/m-streams.tex
@@ -0,0 +1,446 @@
+%D \module
+%D [ file=m-streams,
+%D version=2006.03.21,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Streams,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 First we implement a simple left||right synchronization
+%D mechanism, which we may perfect and extend over time.
+
+\unprotect
+
+\defineoutputstream [\v!left]
+\defineoutputstream [\v!right]
+
+\definemarknote[\v!left]
+\definemarknote[\v!right]
+
+\startsetups stream:\v!left:bottom
+ \flushmarknotes[\v!left]
+\stopsetups
+\startsetups stream:\v!right:bottom
+ \flushmarknotes[\v!right]
+\stopsetups
+\startsetups stream:\v!left:reset
+ \erasemarknotes[\v!left]
+\stopsetups
+\startsetups stream:\v!right:reset
+ \erasemarknotes[\v!right]
+\stopsetups
+
+\def\LeftNote {\setmarknote [\v!left]} % {#1}
+\def\RightNote {\setmarknote [\v!right]} % {#1}
+\def\SwitchToLeft {\enableoutputstream [\v!left]}
+\def\SwitchToRight {\enableoutputstream [\v!right]}
+\def\SwitchToNormal {\enableoutputstream [\s!default]}
+\def\SynchronizeLeftAndRight{\synchronizeoutputstreams[\v!left,\v!right]}
+\def\FlushLeftAndRight {\flushoutputstreampages [\v!left,\v!right]}
+
+\protect
+
+% \topskip \strutheight
+% \splittopskip\strutheight
+
+%D Example of usage:
+%D
+%D \starttyping
+%D \nopenalties \setupinterlinespace[top=height] \setupcolors[state=start]
+%D
+%D \showgrid \showstruts
+%D
+%D \starttext
+%D
+%D \title{Whatever} \page
+%D
+%D \dorecurse {5} {
+%D \let\RecurseLevel\recurselevel
+%D \SwitchToLeft \dorecurse{10}{\dontleavehmode{\tf\RecurseLevel:l \begstrut \input tufte \endstrut \endgraf}}
+%D \SwitchToRight \dorecurse{10}{\dontleavehmode{\sl\RecurseLevel:r \begstrut \input knuth \endstrut \endgraf}}
+%D \SwitchToNormal \SynchronizeLeftAndRight
+%D \SwitchToLeft \dorecurse{10}{\dontleavehmode{\bf\RecurseLevel:l \begstrut \input zapf \endstrut \endgraf}}
+%D \SwitchToRight \dorecurse{10}{\dontleavehmode{\bs\RecurseLevel:r \begstrut \input davis \endstrut \endgraf}}
+%D \SwitchToNormal \SynchronizeLeftAndRight
+%D }
+%D
+%D \FlushLeftAndRight
+%D
+%D \stoptext
+%D \stoptyping
+%D
+%D Another example:
+%D
+%D \starttyping
+%D \nopenalties \setupinterlinespace[top=height] \setupcolors[state=start]
+%D
+%D \showgrid \showstruts
+%D
+%D \starttext
+%D
+%D \SwitchToNormal \FlushLeftAndRight \page
+%D
+%D \def\StartCouple{\page\SwitchToNormal}
+%D \def\StopCouple {\SwitchToNormal \SynchronizeLeftAndRight \FlushLeftAndRight}
+%D
+%D \def\Original {\SwitchToNormal\SynchronizeLeftAndRight\SwitchToLeft}
+%D \def\Translation{\SwitchToRight}
+%D
+%D \StartCouple
+%D \dorecurse{10} {
+%D \Original o: \begstrut \inright{\blackrule}\input tufte \endstrut \LeftNote {tufte} \endgraf
+%D \Translation t: \begstrut \inleft {\blackrule}\input zapf \endstrut \RightNote{zapf} \endgraf
+%D \Original o: \begstrut \inright{\blackrule}\input knuth \endstrut \LeftNote {knuth} \endgraf
+%D \Translation t: \begstrut \inleft {\blackrule}\input davis \endstrut \RightNote{davis} \endgraf
+%D \Original o: \begstrut \inright{\blackrule}\input douglas \endstrut \LeftNote {douglas} \endgraf
+%D \Translation t: \begstrut \inleft {\blackrule}\input bryson \endstrut \RightNote{bryson} \endgraf
+%D }
+%D \StopCouple
+%D \stoptext
+%D \stoptyping
+
+%D Next we implement stream layers.
+
+\unprotect
+
+\def\overloadtextwidth#1%
+ {\makeupwidth#1\relax
+ \textwidth\makeupwidth
+ \hsize\makeupwidth}
+
+\startsetups streamlayer:default:settings
+ % set hsize etc, like \overloadtextwidth{12cm}
+\stopsetups
+
+\startsetups streamlayer:default:extras
+ % flush goodies, like local floats
+\stopsetups
+
+\startsetups streamlayer:default:place
+ \setlayer
+ [\currentstreamlayer]
+ [\c!preset=\v!left\v!top]
+ {\outputstreambox[\currentstreamlayer]}%
+\stopsetups
+
+\startsetups streamlayer:default:copy
+ \setlayer
+ [\currentstreamlayer]
+ [\c!preset=\v!left\v!top]
+ {\outputstreamcopy[\currentstreamlayer]}%
+\stopsetups
+
+\startsetups streamlayer:default:reset
+ \outputstreambox[\currentstreamlayer]
+\stopsetups
+
+\startsetups streamlayer:default:flush
+ \tightlayer[\currentstreamlayer]
+\stopsetups
+
+\def\definestreamlayer
+ {\dodoubleempty\dodefinestreamlayer}
+
+\def\dodefinestreamlayer[#1][#2]%
+ {\defineoutputstream[#1]%
+ \defineoutputstream[main]%
+ \definelayer[#1][\c!method=\v!fit,\c!width=\textwidth,#2]}
+
+\def\dostreamsetups#1%
+ {\doifsetupselse{streamlayer:\currentstreamlayer:#1}
+ {\directsetup{streamlayer:\currentstreamlayer:#1}}
+ {\directsetup{streamlayer:\s!default:#1}}}
+
+\def\startstreamlayer[#1]%
+ {\bgroup
+% \def\startstreamlayer[##1]{\bgroup\let\stopstreamlayer\egroup}%
+ \edef\currentstreamlayer{#1}%
+ \enableoutputstream[main]%
+ \synchronizeoutput
+ \enableoutputstream[\currentstreamlayer]%
+ \bgroup
+ \dostreamsetups{settings}}
+
+\def\stopstreamlayer
+ {\endgraf
+ \egroup
+ \disableoutputstream % \enableoutputstream[\s!default]%
+ \outputstreambox[main]%
+% \dostreamsetups{place}%
+% \dostreamsetups{extras}%
+% \dostreamsetups{flush}%
+ \egroup}
+
+\def\preparestreamlayer{\dosingleempty\dopreparestreamlayer}
+\def\flushstreamlayer {\dosingleempty\doflushstreamlayer }
+\def\placestreamlayer {\dosingleempty\doplacestreamlayer }
+
+\def\dopreparestreamlayer[#1]%
+ {\bgroup
+ \edef\currentstreamlayer{\iffirstargument#1\else\currentstreamlayer\fi}%
+ \dostreamsetups{place}%
+ \dostreamsetups{extras}%
+% \dostreamsetups{flush}%
+ \egroup}
+
+\def\doflushstreamlayer[#1]%
+ {\bgroup
+ \edef\currentstreamlayer{\iffirstargument#1\else\currentstreamlayer\fi}%
+ \dostreamsetups{flush}%
+ \egroup}
+
+\def\doplacestreamlayer[#1]%
+ {\preparestreamlayer[#1]%
+ \flushstreamlayer[#1]}
+
+\protect
+
+%D Usage:
+
+%D \starttyping
+%D \setupinterlinespace[top=height]
+%D
+%D \setupcolors[state=start]
+%D
+%D \definestreamlayer[block]
+%D
+%D \definemeasure[localtextwidth] [\dimexpr.7\textwidth\relax]
+%D \definemeasure[localfloatwidth][\dimexpr.3\textwidth-2\bodyfontsize\relax]
+%D
+%D \startsetups streamlayer:block:settings
+%D \hsize=\measure{localtextwidth}
+%D \setupfloat[figure][maxwidth=\measure{localfloatwidth}]
+%D \stopsetups
+%D
+%D \startsetups streamlayer:block:extras
+%D \setuplocalfloats
+%D [before=\blank,
+%D after=\blank,
+%D inbetween=\blank]
+%D \setbox\scratchbox\vbox{\hsize\measure{localfloatwidth}\getlocalfloats}
+%D \ifdim\ht\scratchbox>\thelayerheight\currentstreamlayer\relax
+%D % more float than text
+%D \setlayerframed
+%D [\currentstreamlayer]
+%D [preset=righttop]
+%D [frame=off,
+%D offset=overlay]
+%D {\box\scratchbox}
+%D \else
+%D % more text than float
+%D \setuplocalfloats
+%D [before=\vfill,
+%D after=\removedepth\vfill,
+%D inbetween=\removedepth\vfill]
+%D \setlayerframed
+%D [\currentstreamlayer]
+%D [preset=righttop]
+%D [frame=off,
+%D offset=overlay]
+%D {\vbox to \thelayerheight\currentstreamlayer {\hsize\measure{localfloatwidth}\getlocalfloats}}
+%D \fi
+%D \resetlocalfloats
+%D \stopsetups
+%D
+%D \startsetups streamlayer:block:place
+%D \setlayerframed
+%D [\currentstreamlayer]
+%D [preset=lefttop]
+%D [frame=off,
+%D offset=overlay]
+%D {\outputstreambox[\currentstreamlayer]}%
+%D \stopsetups
+%D
+%D \startsetups streamlayer:block:flush
+%D \framed
+%D [offset=overlay,
+%D frame=off,
+%D background=color,
+%D backgroundcolor=red]
+%D {\tightlayer[\currentstreamlayer]}
+%D \stopsetups
+%D
+%D \setupbodyfont[small]
+%D
+%D \starttext
+%D
+%D \dorecurse {10} {
+%D \startstreamlayer[block]
+%D \title{Sample \recurselevel}
+%D \input tufte \endgraf
+%D \placefigure[local]{}{}
+%D \placefigure[local]{}{}
+%D \ifodd\recurselevel\relax \placefigure[local]{}{} \fi
+%D \startitemize[columns]
+%D \item xxx
+%D \item xxx
+%D \item xxx
+%D \item xxx
+%D \item xxx
+%D \stopitemize
+%D \stopstreamlayer
+%D \placestreamlayer[block]
+%D }
+%D
+%D \dorecurse {10} {
+%D \startstreamlayer[block]
+%D \title{Sample \recurselevel}
+%D \startcolumns
+%D \input tufte
+%D \stopcolumns
+%D \stopstreamlayer
+%D \placestreamlayer[block]
+%D }
+%D
+%D \stoptext
+%D \stoptyping
+
+\def\starttextstreamlayer
+ {\startstreamlayer}
+
+\def\stoptextstreamlayer
+ {\endgraf
+ % maybe depth if no proper depth and no skip
+ \removelastskip
+ \stopstreamlayer}
+
+\def\placetextstreamlayer{\placestreamlayer}
+
+%D \starttyping
+%D \definestreamlayer[whatever][width=12cm]
+%D
+%D \startstreamlayer[whatever]
+%D \startitemize[columns,two][after=]
+%D \item one
+%D \item two
+%D \item three
+%D \item four
+%D \stopitemize
+%D \stopstreamlayer
+%D
+%D \framed[strut=no,align=normal]{\placestreamlayer[whatever]\obeydepth}
+%D
+%D \starttextstreamlayer[whatever]
+%D \startitemize[columns,two]
+%D \item one
+%D \item two
+%D \item three
+%D \item four
+%D \stopitemize
+%D \stoptextstreamlayer
+%D
+%D \framed[strut=no]{\placetextstreamlayer[whatever]}
+%D \stoptyping
+
+\endinput
+
+\setupinterlinespace[top=height]
+
+\setupcolors[state=start]
+
+\definestreamlayer[block]
+
+\definemeasure[localtextwidth] [\dimexpr.7\textwidth\relax]
+\definemeasure[localfloatwidth][\dimexpr.3\textwidth-2\bodyfontsize\relax]
+
+\startsetups streamlayer:block:settings
+ \hsize=\measure{localtextwidth}
+ \setupfloat[figure][maxwidth=\measure{localfloatwidth}]
+\stopsetups
+
+\startsetups streamlayer:block:extras
+ \setuplocalfloats
+ [before=\whitespace\blank,
+ after=\whitespace\blank,
+ inbetween=\whitespace\blank]
+ \setbox\scratchbox\vbox{\hsize\measure{localfloatwidth}\getlocalfloats}
+ \ifdim\ht\scratchbox>\thelayerheight\currentstreamlayer\relax
+ % more float than text
+ \setlayerframed
+ [\currentstreamlayer]
+ [preset=righttop]
+ [frame=off,
+ offset=overlay]
+ {\box\scratchbox}
+ \else
+ % more text than float
+ \setuplocalfloats
+ [before=\vfill,
+ after=\removedepth\vfill,
+ inbetween=\removedepth\vfill]
+ \setlayerframed
+ [\currentstreamlayer]
+ [preset=righttop]
+ [frame=off,
+ offset=overlay]
+ {\vbox to \thelayerheight\currentstreamlayer {\hsize\measure{localfloatwidth}\getlocalfloats}}
+ \fi
+ \resetlocalfloats
+\stopsetups
+
+\startsetups streamlayer:block:place
+ \setlayerframed
+ [\currentstreamlayer]
+ [preset=lefttop]
+ [frame=off,
+ offset=overlay]
+ {\outputstreambox[\currentstreamlayer]}%
+\stopsetups
+
+\startsetups streamlayer:block:flush
+ \framed
+ [offset=overlay,
+ frame=off,
+ background=color,
+ backgroundcolor=red]
+ {\tightlayer[\currentstreamlayer]}
+\stopsetups
+
+\setupbodyfont[small]
+
+\starttext
+
+% \definestreamlayer[block]
+%
+% \startstreamlayer[block]
+% \title{Sample \recurselevel}
+% \startcolumns
+% \dorecurse{4}{\input tufte \par}
+% \stopcolumns
+% \stopstreamlayer
+% \placestreamlayer[block]
+
+\dorecurse {10} {
+ \startstreamlayer[block]
+ \title{Sample \recurselevel}
+ \input tufte \endgraf
+ \placefigure[local]{}{}
+ \placefigure[local]{}{}
+ \ifodd\recurselevel\relax \placefigure[local]{}{} \fi
+ \startitemize[columns]
+ \item xxx
+ \item xxx
+ \item xxx
+ \item xxx
+ \item xxx
+ \stopitemize
+ \stopstreamlayer
+ \placestreamlayer[block]
+}
+
+\dorecurse {10} {
+ \startstreamlayer[block]
+ \title{Sample \recurselevel}
+ \startcolumns
+ \input tufte
+ \stopcolumns
+ \stopstreamlayer
+ \placestreamlayer[block]
+}
+
+\stoptext
diff --git a/tex/context/base/m-subsub.tex b/tex/context/base/m-subsub.tex
new file mode 100644
index 000000000..4395ded8a
--- /dev/null
+++ b/tex/context/base/m-subsub.tex
@@ -0,0 +1,76 @@
+%D \module
+%D [ file=m-subsub,
+%D version=2000.12.14,
+%D title=\CONTEXT\ Private Modules,
+%D subtitle=More Section Levels,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. This module is not public.
+
+\unprotect
+
+\definesection[\s!section-8]
+\definesection[\s!section-9]
+\definesection[\s!section-10]
+\definesection[\s!section-11]
+\definesection[\s!section-12]
+
+\definehead
+ [\v!subsubsubsubsubsection]
+ [\c!section=\s!section-8,
+ \c!default=\v!subsubsubsubsection]
+
+\definehead
+ [\v!subsubsubsubsubsubsection]
+ [\c!section=\s!section-9,
+ \c!default=\v!subsubsubsubsubsection]
+
+\definehead
+ [\v!subsubsubsubsubsubsubsection]
+ [\c!section=\s!section-10,
+ \c!default=\v!subsubsubsubsubsubsection]
+
+\definehead
+ [\v!subsubsubsubsubsubsubsubsection]
+ [\c!section=\s!section-11,
+ \c!default=\v!subsubsubsubsubsubsubsection]
+
+\definehead
+ [\v!subsubsubsubsubsubsubsubsubsection]
+ [\c!section=\s!section-12,
+ \c!default=\v!subsubsubsubsubsubsubsubsection]
+
+\definehead
+ [\v!subsubsubsubsubsubject]
+ [\c!coupling=\v!subsubsubsubsubsection,
+ \c!default=\v!subsubsubsubsubsection,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubsubsubsubsubsubject]
+ [\c!coupling=\v!subsubsubsubsubsubsection,
+ \c!default=\v!subsubsubsubsubsubsection,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubsubsubsubsubsubsubject]
+ [\c!coupling=\v!subsubsubsubsubsubsubsection,
+ \c!default=\v!subsubsubsubsubsubsubsection,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubsubsubsubsubsubsubsubject]
+ [\c!coupling=\v!subsubsubsubsubsubsubsubsection,
+ \c!default=\v!subsubsubsubsubsubsubsubsection,
+ \c!incrementnumber=\v!no]
+
+\definehead
+ [\v!subsubsubsubsubsubsubsubsubsubject]
+ [\c!coupling=\v!subsubsubsubsubsubsubsubsubsection,
+ \c!default=\v!subsubsubsubsubsubsubsubsubsection,
+ \c!incrementnumber=\v!no]
+
+\protect \endinput
diff --git a/tex/context/base/m-tex4ht.tex b/tex/context/base/m-tex4ht.tex
new file mode 100644
index 000000000..8a3dc9dbb
--- /dev/null
+++ b/tex/context/base/m-tex4ht.tex
@@ -0,0 +1,9 @@
+%D Preliminaty module
+
+\input tex4ht.sty
+
+\appendtoks
+ \Preamble{\env{ht-1},\env{ht-2},html}\EndPreamble
+\to \everystarttext
+
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/m-timing.tex b/tex/context/base/m-timing.tex
new file mode 100644
index 000000000..f02a90087
--- /dev/null
+++ b/tex/context/base/m-timing.tex
@@ -0,0 +1,102 @@
+%D \module
+%D [ file=m-timing,
+%D version=2007.12.23,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Timing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\doifnotmode{mkiv}{\endinput}
+
+\ifx\ShowNamedUsage\undefined \else \endinput \fi
+
+%D Written at the end of 2007, this module is dedicated to Taco. Reaching this
+%D point in \LUATEX\ was a non trivial effort. By visualizing a bit what happens
+%D when pages come out of \LUATEX, you may get an idea what is involved. It took
+%D much time an dedication to reach this point in the development. Add to that
+%D those daily Skype intense discussion, testing and debugging moments. Time flies
+%D but progress is impressive. The motto of this module could be: what you see
+%D is what you get. An there is much more to come \unknown.
+
+% \usemodule[timing]
+% \setupcolors[state=start]
+% \starttext
+% \dorecurse{200}{\input tufte \par} \ShowUsage{}
+% \stoptext
+
+\definecolor[usage:line] [darkred]
+\definecolor[usage:time] [darkblue]
+\definecolor[usage:frame][darkgray]
+
+\ctxloadluafile{trac-tim}{}
+
+\startluacode
+local progress = plugins.progress
+
+function progress.show(filename,parameters,nodes,other)
+ for n, name in pairs(parameters or progress.parameters(filename)) do
+ tex.sprint(tex.ctxcatcodes,string.format("\\ShowNamedUsage{%s}{%s}{%s}",filename or progress.defaultfilename,name,other or ""))
+ end
+ for n, name in pairs(nodes or progress.nodes(filename)) do
+ tex.sprint(tex.ctxcatcodes,string.format("\\ShowNamedUsage{%s}{%s}{%s}",filename or progress.defaultfilename,name,other or ""))
+ end
+end
+\stopluacode
+
+% \everyfirstshipout
+
+\startnotmode[no-timing]
+ \appendtoks\ctxlua{plugins.progress.store()}\to\everystarttext
+ \appendtoks\ctxlua{plugins.progress.store()}\to\everyshipout
+ \ctxlua{main.register_stop_actions(function() plugins.progress.save() end)}
+\stopnotmode
+
+\def\ShowNamedUsage#1#2#3%
+ {\setbox\scratchbox\vbox\bgroup\startMPcode
+ begingroup ; save p, q, b, h, w ;
+ path p, q, b ; numeric h, w ;
+ p := \ctxlua{tex.sprint(plugins.progress.path("#1","#2"))} ;
+% p := p shifted -llcorner p ;
+ if bbwidth(p) > 1 :
+ h := 100 ; w := 2 * h ;
+ w := \the\textwidth-3pt ; % correct for pen
+ p := p xstretched w ;
+ b := boundingbox (llcorner p -- llcorner p shifted (w,h)) ;
+ pickup pencircle scaled 3pt ; linecap := butt ;
+ draw b withcolor \MPcolor{usage:frame} ;
+ draw p withcolor \MPcolor{usage:line} ;
+ if ("#3" <> "") and ("#3" <> "#2") :
+ q := \ctxlua{tex.sprint(plugins.progress.path("#1","#3"))} ;
+% q := q shifted -llcorner q ;
+ if bbwidth(q) > 1 :
+ q := q xstretched w ;
+ pickup pencircle scaled 1.5pt ; linecap := butt ;
+ draw q withcolor \MPcolor{usage:time} ;
+ fi ;
+ fi ;
+ fi ;
+ endgroup ;
+ \stopMPcode\egroup
+ \scratchdimen\wd\scratchbox
+ \ifdim\scratchdimen>\zeropoint
+ \startlinecorrection
+ \box\scratchbox \endgraf
+ \hbox to \scratchdimen{\tttf\strut\detokenize{#2}\hss
+ min:\ctxlua{tex.sprint(plugins.progress.bot("#1","\detokenize{#2}"))}, %
+ max:\ctxlua{tex.sprint(plugins.progress.top("#1","\detokenize{#2}"))}, %
+ pages:\ctxlua{tex.sprint(plugins.progress.pages("#1"))}%
+ }%
+ \stoplinecorrection
+ \fi}
+
+\def\LoadUsage #1{\ctxlua{plugins.progress.convert("#1")}}
+\def\ShowUsage #1{\ctxlua{plugins.progress.show("#1",nil,nil,"elapsed_time")}}
+\def\ShowMemoryUsage#1{\ctxlua{plugins.progress.show("#1",nil,{}, "elapsed_time")}}
+\def\ShowNodeUsage #1{\ctxlua{plugins.progress.show("#1",{},nil, "elapsed_time")}}
+
+\endinput
diff --git a/tex/context/base/m-trackers.tex b/tex/context/base/m-trackers.tex
new file mode 100644
index 000000000..cfcbbabff
--- /dev/null
+++ b/tex/context/base/m-trackers.tex
@@ -0,0 +1,5 @@
+\doifnotmode{mkiv} {\endinput}
+
+\starttext
+ \showtrackers
+\stoptext
diff --git a/tex/context/base/m-translate.tex b/tex/context/base/m-translate.tex
new file mode 100644
index 000000000..9c550eca7
--- /dev/null
+++ b/tex/context/base/m-translate.tex
@@ -0,0 +1,88 @@
+%D \module
+%D [ file=m-translate,
+%D version=2008.10.09,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Translations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\doifnotmode{mkiv}{\endinput}
+
+%D We can make this module more clever (wildcards and such) but since
+%D it's only a demo we stick to the simple case for now. After all, it's
+%D better to fix your source.
+
+\startluacode
+ translators = { }
+
+ local compiled, list = nil, nil
+
+ function translators.register(from,to)
+ local l = lpeg.P(from)/to
+ if not list then
+ list = l
+ else
+ list = list + l
+ end
+ compiled = nil
+ end
+
+ function translators.translate(s)
+ if list then
+ if not compiled then
+ compiled = lpeg.Cs((list + lpeg.P(1))^0)
+ end
+ return compiled:match(s)
+ else
+ return s
+ end
+ end
+
+ function translators.reset(s)
+ resolvers.install_text_filter("user",nil)
+ list, compiled = nil, nil
+ end
+ function translators.enable(s)
+ resolvers.install_text_filter("user",translators.translate)
+ end
+ function translators.disable(s)
+ resolvers.install_text_filter("user",nil)
+ end
+\stopluacode
+
+\unprotect
+
+\def\translateinput{\dodoubleargument\dotranslateinput}
+
+\def\dotranslateinput[#1][#2]{\ctxlua{translators.register(\!!bs#1\!!es,\!!bs#2\!!es)}}
+
+\def\resetinputtranslation {\ctxlua{translators.reset()}}
+\def\enableinputtranslation {\ctxlua{translators.enable()}}
+\def\disableinputtranslation{\ctxlua{translators.disable()}}
+
+\def\readtranslatedfile#1%
+ {\enableinputtranslation
+ \readfile{#1}\donothing\donothing
+ \disableinputtranslation}
+
+\protect
+
+\doifnotmode{demo}{\endinput}
+
+\starttext
+
+ \translateinput[Moica][Mojca]
+ \translateinput[Idris][Idris (aka ادريس)]
+
+ \enableinputtranslation
+
+ Well, it's not that hard to satisfy Idris and Moica.
+
+ \readtranslatedfile{tufte}
+
+\stoptext
diff --git a/tex/context/base/m-tryout.tex b/tex/context/base/m-tryout.tex
new file mode 100644
index 000000000..4aa50376d
--- /dev/null
+++ b/tex/context/base/m-tryout.tex
@@ -0,0 +1,55 @@
+%D \module
+%D [ file=m-tryout,
+%D version=2002.05.10,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Tryout Features,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\endinput
+
+\unprotect
+
+%D The following macros make sure that active colons work well
+%D in French, a feature enabled with:
+%D
+%D \starttyping
+%D \useencoding[ffr] \mainlanguage[fr]
+%D \stoptyping
+%D
+%D This trick will disappear when proved robust.
+
+\startmode[activecolon]
+
+% this is now default
+
+\gdef\sectionseparator{-}
+
+\gdef\@@filterfirstpart [#1--#2]{#1}
+\gdef\@@filtersecondpart [#1--#2]{#2}
+
+\gdef\@@filterblockpart [#1--#2--#3]{#1}
+\gdef\@@filternumberpart [#1--#2--#3]{#2}
+\gdef\@@filterpagepart [#1--#2--#3]{#3}
+\gdef\@@filterblocknumberpart[#1--#2--#3]{#1--#2}
+
+\gdef\@@filterheadpart[#1]{\@EA\@@dofilterheadpart\@EA[#1-0]}
+\gdef\@@filtertailpart[#1]{\@EA\@@dofiltertailpart\@EA[#1-0]}
+
+\gdef\@@dofilterheadpart[#1-#2]{#1}
+\gdef\@@dofiltertailpart[#1-#2]{#2}
+
+\gdef\@@filterlevelpart[#1--#2--#3]{\@@dofilterlevelpart[#2-0-0-0-0]}
+
+\gdef\@@dofilterlevelpart[#1-0-0-0-#2]{#1}
+
+\reopenutilities
+
+\stopmode
+
+\protect \endinput
diff --git a/tex/context/base/m-units.tex b/tex/context/base/m-units.tex
new file mode 100644
index 000000000..d186c542b
--- /dev/null
+++ b/tex/context/base/m-units.tex
@@ -0,0 +1,825 @@
+%D \module
+%D [ file=m-units,
+%D version=1997.03.19,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Scientific Units,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Scientific units can be typeset in math mode pretty well,
+%D but occasionally one has to take care of spacing.
+%D Furthermore, entering these units is not that natural as
+%D wanted. Therefore this module presents a more natural way of
+%D doing things, like:
+%D
+%D \starttyping
+%D 1.23 \Cubic \Meter \Per \Second
+%D \stoptyping
+%D
+%D This example shows that we use the order in which we say
+%D things, instead of typeset things. There is a separate
+%D manual for this module.
+
+%D Message number~1 deals with overruling the \type {\Degrees}
+%D macro defined in the core modules. Let's say that this is
+%D an upward compatibility issue.
+
+\startmessages dutch library: units
+ title: eenheden
+ 1: gebruik \string\Degrees\space\string\Celsius\space in plaats van \string\Celsius !
+\stopmessages
+
+\startmessages english library: units
+ title: units
+ 1: use \string\Degrees\space\string\Celsius\space instead of \string\Celsius !
+\stopmessages
+
+\startmessages german library: units
+ title: Einheiten
+ 1: Verwende \string\Degrees\space\string\Celsius\space statt \string\Celsius !
+\stopmessages
+
+\startmessages italian library: units
+ title: unita
+ 1: usare \string\Degrees\space\string\Celsius\space invece di \string\Celsius !
+\stopmessages
+
+\startmessages norwegian library: units
+ title: enheter
+ 1: bruk \string\Degrees\space\string\Celsius\space istedenfor \string\Celsius !
+\stopmessages
+
+\startmessages romanian library: units
+ title: unitati
+ 1: folositi \string\Degrees\space\string\Celsius\space in locul \string\Celsius !
+\stopmessages
+
+\startmessages french library: units
+ title: unitas
+ 1: utilisez \string\Degrees\space\string\Celsius\space A la place de \string\Celsius !
+\stopmessages
+
+\unprotect
+
+%D This runtime loadable module implements a way of defining
+%D units. The core macro is \type {\dimension}, a rather clever
+%D one that is able to cooperate with some other dimension
+%D related macros. As said, this module enables user to enter:
+%D
+%D \startbuffer
+%D some 10 \Square \Meter \Per \Second or more
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D as:
+%D
+%D \typebuffer
+%D
+%D The units itself are implemented as synonyms.
+%D
+%D \starttyping
+%D \definesynonyms [unit] [units] [\unitmeaning]
+%D \setupsynonyms [unit] [textstyle=\dimension]
+%D \stoptyping
+%D
+%D This definition means that we can ask for the meaning of a
+%D unit using \type {\unitmeaning} and get a list of used
+%D units by saying \type {\placelistofunits}
+%D
+%D We have to use the command \type {\unitmeaning} instead
+%D of \type {\meaning}, simply because the latter is a \TEX\
+%D primitive we don't want to loose. We use the label text
+%D mechanism for translations.
+
+%D \macros
+%D {dimension}
+%D
+%D The core of this module is the low level macro \type
+%D {\dimension}. Before presenting this macro, it's best to
+%D look at some applications, because it's supposed to show
+%D some intelligence that can beter be understood from the
+%D context.
+%D
+%D The next useless examples show some of the cases we want
+%D to handle in a proper way.
+%D
+%D \startbuffer
+%D ... 10 \Square \Meter \Per \Volt \
+%D ... 10 \Square \Meter \Volt \
+%D ... 10 \Meter \Volt \
+%D ... 10 \Milli \Square \Meter \Per \Volt \
+%D ... 10 \Square \Milli \Meter \Per \Volt \
+%D ... 10 \Meter \Times \Meter \
+%D ... 10 \Square \Meter \Times \Meter \
+%D ... 10 \Square \Milli \Meter \Times \Meter \
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Becomes:
+%D
+%D \getbuffer
+
+%D \macros
+%D {mathematicstypeface, dimensiontypeface,
+%D dimensionhalfspace, dimensionbackspace}
+%D
+%D There are some low level constants, that can be changed
+%D when needed. Some day I will write a decent setup command.
+
+\def\mathematicstypeface{\rm}
+\def\dimensiontypeface {\tf}
+
+\def\dimensionhalfspace {\ifmmode\,\else\hskip+.1em\relax\fi}
+\def\dimensionbackspace {\ifmmode\!\else\hskip-.1em\relax\fi}
+
+%D \macros
+%D {smashdimensionpower}
+%D
+%D Sometimes the baseline distance is not enough to provide
+%D for superscripts, so we smash their height by default.
+
+\newif\ifsmashdimensionpower \smashdimensionpowertrue
+
+%D The dimension mechanism uses a lot of signals to keep
+%D track if the current state.
+
+\newsignal\dimensionsignal
+\newsignal\dimensionpowersignal
+\newsignal\dimensionmidfixsignal
+\newsignal\dimensionaddfixsignal
+
+\let\thedimensionprefix = \empty
+\let\thedimensionpower = \empty
+
+%D \macros
+%D {spaceddimensions,textdimensions}
+%D
+%D The actual definition of \type {\dimension} overruled the
+%D one in the core modules. The boolean can be used to
+%D force spacing between units. Vergelijk {\Newton \Meter}
+%D eens met {\spaceddimensionstrue \Newton \Meter}. The
+%D rather ugly test prevents problems with nested dimensions.
+
+\newif\ifspaceddimensions \spaceddimensionsfalse % user switch
+\newif\iftextdimensions \textdimensionsfalse % user switch
+
+%D You can see the consequence of forcing text dimensions
+%D when you compare the following code:
+%D
+%D \starttyping
+%D {\rm test \Square \Meter \Per \Second\ ziezo\Degrees} \par
+%D {\ss test \Square \Meter \Per \Second\ ziezo} \par
+%D {\tt test \Square \Meter \Per \Second\ ziezo}
+%D
+%D \textdimensionstrue
+%D
+%D {\rm test \Square \Meter \Per \Second\ ziezo} \par
+%D {\ss test \Square \Meter \Per \Second\ ziezo} \par
+%D {\tt test \Square \Meter \Per \Second\ ziezo}
+%D \stoptyping
+
+\newif\ifnesteddimension \nesteddimensionfalse % local switch
+
+\def\dodimensionpower#1%
+ {\iftextdimensions\expandafter\high\else\expandafter^\fi{#1}}
+
+\def\ustartmathmode {\iftextdimensions\else\expandafter\startmathmode \fi}
+\def\ustopmathmode {\iftextdimensions\else\expandafter\stopmathmode \fi}
+\def\umathematicstypeface{\iftextdimensions\else\expandafter\mathematicstypeface\fi}
+
+%D In forced text mode, we ignore spacing in monospaced fonts.
+
+\def\udimensionhalfspace {\dodimensionspace\dimensionhalfspace}
+\def\udimensionbackspace {\dodimensionspace\dimensionbackspace}
+
+\def\dodimensionspace
+ {\iftextdimensions
+ \begingroup
+ \setbox0\hbox{i}%
+ \setbox2\hbox{m}%
+ \ifdim\wd0=\wd2
+ \endgroup
+ \@EAEAEA\gobbleoneargument
+ \else
+ \endgroup
+ \fi
+ \fi}
+
+\unexpanded\def\dimension#1%
+ {\begingroup
+ \global\let\savedthedimensionprefix\thedimensionprefix
+ \global\let\savedthedimensionpower\thedimensionpower
+ \unexpanded\def\dimension##1{\global\nesteddimensiontrue}%
+ \let\dimensionprefix\dimension
+ \let\dimensionmidfix\dimension
+ \let\dimensionsuffix\dimension
+ \let\dimensionpower \dimension
+ \global\nesteddimensionfalse
+ \setbox\scratchbox\hbox{\ustartmathmode#1\ustopmathmode}% pre-roll
+ \global\let\thedimensionprefix\savedthedimensionprefix
+ \global\let\thedimensionpower \savedthedimensionpower
+ \endgroup
+ \ifnesteddimension#1\else\dodimension{#1}\fi}
+
+\def\dodimension#1%
+ {\dontbreakdimension
+ \ifdim\scratchdimen=\zeropoint\relax
+ \ifmmode
+ \udimensionhalfspace
+ \udimensionhalfspace
+ \fi
+ \ustartmathmode\dimensiontypeface
+ \else
+ \ustartmathmode\dimensiontypeface
+ \ifspaceddimensions
+ \ifdim\scratchdimen=\dimensionsignal\relax
+ \udimensionhalfspace
+ \else\ifdim\scratchdimen=\dimensionpowersignal\relax
+ \udimensionhalfspace
+ \fi
+ \fi
+ \fi
+ \fi
+ \umathematicstypeface\thedimensionprefix#1%
+ \ifx\thedimensionpower\empty
+ \else\ifsmashdimensionpower
+ \setbox\scratchbox=\hbox
+ {\iftextdimensions
+ \tx\thedimensionpower
+ \else
+ $\scriptstyle\thedimensionpower$%
+ \fi}%
+ \ht\scratchbox=\zeropoint
+ \dodimensionpower{\box\scratchbox}%
+ \else
+ \dodimensionpower{\thedimensionpower}%
+ \fi\fi
+ \ustopmathmode
+ % otherwise nobreak before space in 2 \Milli \Meter\ blabla
+ \doifnotmode{atpragma}{\nobreak}% this was always \nobreak
+ % only test this at pragma
+ \ifx\thedimensionpower\empty
+ \hskip\dimensionsignal
+ \else
+ \hskip\dimensionpowersignal
+ \fi
+ \global\let\thedimensionprefix\empty
+ \global\let\thedimensionpower\empty}
+
+%D \macros
+%D {dontbreakdimension,
+%D dimensionprefix, dimensionaddfix,
+%D dimensionnopfix, dimensionmidfix,
+%D dimensionpower}
+%D
+%D Here are some auxilliary macros.
+
+\def\dontbreakdimension
+ {\scratchdimen\lastskip
+ \unskip
+ \nobreak
+ \hskip\scratchdimen
+ \nobreak}
+
+\def\dimensionprefix#1%
+ {\gdef\thedimensionprefix{#1}}
+
+\def\dimensionaddfix#1%
+ {\unskip
+ %\mathematics{\umathematicstypeface#1}%
+ \ustartmathmode\umathematicstypeface#1\ustopmathmode
+ \nobreak
+ \hskip\dimensionaddfixsignal}
+
+\def\dimensionnopfix#1%
+ {\dontbreakdimension
+ \ifdim\scratchdimen=\dimensionpowersignal\relax
+ \ustartmathmode
+ \else
+ \ustartmathmode
+ \udimensionhalfspace
+ \nobreak
+ \fi
+ \umathematicstypeface#1%
+ \ustopmathmode
+ \nobreak
+ \hskip\dimensionsignal}
+
+\def\dimensionmidfix#1%
+ {\dontbreakdimension
+ \ifdim\scratchdimen=\dimensionpowersignal\relax
+ \ustartmathmode
+ \udimensionbackspace
+ \nobreak
+ \else
+ \ustartmathmode
+ \fi
+ \umathematicstypeface#1%
+ \ustopmathmode
+ \nobreak
+ \hskip\dimensionmidfixsignal}
+
+\def\dimensionpower#1%
+ {\gdef\thedimensionpower{#1}}
+
+%D \macros
+%D {SIunits, noSI, doSI}
+%D
+%D Some low level unit switching macros:
+
+\newif\ifSIunits \SIunitstrue
+
+\def\noSI#1{\begingroup\SIunitsfalse#1\endgroup}
+\def\doSI#1{\begingroup\SIunitstrue #1\endgroup}
+
+%D \macros
+%D {Degrees}
+%D
+%D We can fake the degrees symbol with:
+
+\def\Degrees{\dimensionaddfix{\mathematics{^\circ}}}
+
+%D \macros
+%D {Unit, NoUnit}
+%D
+%D When a dimension has no leading number, we can use \type
+%D {\Unit}, and when no unit is appended, \type {\NoUnit} is
+%D to be used, just to prevent the prefix migrating to the
+%D next occasion.
+
+\def\Unit {\hskip\dimensionsignal}
+\def\NoUnit {\dimension{}}
+
+%D The mechanism described at the top of this module, depends
+%D on several dimensional components, like prefixes:
+
+\def\Atto {\dimensionprefix{a}}
+\def\Femto {\dimensionprefix{f}}
+\def\Pico {\dimensionprefix{p}}
+\def\Nano {\dimensionprefix{n}}
+\def\Micro {\dimensionprefix{\iftextdimensions u\else\mu\fi}}
+\def\Milli {\dimensionprefix{m}}
+\def\Centi {\dimensionprefix{c}}
+\def\Deci {\dimensionprefix{d}}
+\def\Hecto {\dimensionprefix{h}}
+\def\Kilo {\dimensionprefix{k}}
+\def\Mega {\dimensionprefix{M}}
+\def\Giga {\dimensionprefix{G}}
+\def\Terra {\dimensionprefix{T}} % for old times sake
+\def\Tera {\dimensionprefix{T}}
+\def\Peta {\dimensionprefix{P}}
+\def\Exa {\dimensionprefix{E}}
+
+%D and operators:
+
+\def\Times {\dimensionnopfix{\iftextdimensions.\else\cdot\fi}}
+\def\Solidus {\dimensionmidfix{/}}
+\def\Per {\dimensionmidfix{/}}
+\def\OutOf {\dimensionnopfix{:}}
+
+%D and suffixes:
+
+\def\Linear {\dimensionpower{1}}
+\def\Square {\dimensionpower{2}}
+\def\Cubic {\dimensionpower{3}}
+
+\def\Inverse {\dimensionpower{-1}}
+\def\ILinear {\dimensionpower{-1}}
+\def\ISquare {\dimensionpower{-2}}
+\def\ICubic {\dimensionpower{-3}}
+
+%D Apart from these components, the units themselves are
+%D defined using the synonym mechanism. First we define some
+%D length and volume related units.
+
+\getvalue{\v!unit} [Meter] {m} {meter}
+\getvalue{\v!unit} [pMeter] {\Pico \Meter} {picometer}
+\getvalue{\v!unit} [nMeter] {\Nano \Meter} {nanometer}
+\getvalue{\v!unit} [uMeter] {\Micro \Meter} {micrometer}
+\getvalue{\v!unit} [mMeter] {\Milli \Meter} {millimeter}
+\getvalue{\v!unit} [cMeter] {\Centi \Meter} {centimeter}
+\getvalue{\v!unit} [dMeter] {\Deci \Meter} {decimeter}
+\getvalue{\v!unit} [hMeter] {\Hecto \Meter} {hectometer}
+\getvalue{\v!unit} [kMeter] {\Kilo \Meter} {kilometer}
+
+%D After some discussion on the \CONTEXT\ mailing list in
+%D february 2002 it was decided to go from L to l for liters
+%D (Karel Wesselings alternative: \mathematics{\ell}).
+
+\getvalue{\v!unit} [Liter] {l} {liter}
+\getvalue{\v!unit} [mLiter] {\Milli \Liter} {milliliter}
+\getvalue{\v!unit} [cLiter] {\Centi \Liter} {centiliter}
+\getvalue{\v!unit} [dLiter] {\Deci \Liter} {deciliter}
+
+%D Next we define time related units (\type {\ifSI} still dutch only).
+
+\getvalue{\v!unit} [Sec] {s} {\labeltext{u:sec}}
+\getvalue{\v!unit} [fSec] {\Femto \Sec} {\labeltext{u:fsec}}
+\getvalue{\v!unit} [pSec] {\Pico \Sec} {\labeltext{u:psec}}
+\getvalue{\v!unit} [nSec] {\Nano \Sec} {\labeltext{u:nsec}}
+\getvalue{\v!unit} [uSec] {\Micro \Sec} {\labeltext{u:usec}}
+\getvalue{\v!unit} [mSec] {\Milli \Sec} {\labeltext{u:msec}}
+\getvalue{\v!unit} [Year] {\ifSIunits a \else j\fi} {\labeltext{u:year}}
+\getvalue{\v!unit} [Month] {m} {\labeltext{u:month}}
+\getvalue{\v!unit} [Week] {w} {\labeltext{u:week}}
+\getvalue{\v!unit} [Day] {d} {\labeltext{u:day}}
+\getvalue{\v!unit} [Hour] {\ifSIunits h \else u\fi} {\labeltext{u:hour}}
+\getvalue{\v!unit} [Min] {min} {\labeltext{u:min}}
+
+\setuplabeltext
+ [\s!nl]
+ [u:sec=seconde,
+ u:psec=picoseconde,
+ u:fsec=femtoseconde,
+ u:nsec=nanoseconde,
+ u:usec=microseconde,
+ u:msec=milliseconde,
+ u:year=jaar,
+ u:month=maand,
+ u:week=week,
+ u:day=dag,
+ u:hour=uur,
+ u:min=minuten]
+
+\setuplabeltext
+ [\s!en]
+ [u:sec=second,
+ u:fsec=femtosecond,
+ u:psec=picosecond,
+ u:nsec=nanosecond,
+ u:usec=microsecond,
+ u:msec=millisecond,
+ u:year=year,
+ u:month=month,
+ u:week=week,
+ u:day=day,
+ u:hour=hour,
+ u:min=minutes]
+
+\setuplabeltext
+ [\s!de]
+ [u:sec=Sekunde,
+ u:fsec=Femtosekunde,
+ u:psec=Picosekunde,
+ u:nsec=Nanosekunde,
+ u:usec=Microsekunde,
+ u:msec=Millisekunde,
+ u:year=Jahr,
+ u:month=Monat,
+ u:week=Woche,
+ u:day=Tag,
+ u:hour=Stunde,
+ u:min=Minuten]
+
+\setuplabeltext
+ [\s!it]
+ [u:sec=secondo,
+ u:fsec=femtosecondo,
+ u:psec=picosecondo,
+ u:nsec=nanosecondo,
+ u:usec=microsecondo,
+ u:msec=millisecondo,
+ u:year=anno,
+ u:month=mese,
+ u:week=settimana,
+ u:day=giorno,
+ u:hour=ora,
+ u:min=minuti]
+
+%D Then we define some angles.
+
+\getvalue{\v!unit} [Rad] {rad} {\labeltext{u:rad}}
+\getvalue{\v!unit} [Deg] {{\mathematics{^\circ}}} {\labeltext{u:deg}}
+
+\setuplabeltext
+ [\s!nl]
+ [u:rad=hoek radialen,
+ u:deg=hoek graden]
+
+\setuplabeltext
+ [\s!en]
+ [u:rad=angle radians,
+ u:deg=angle degrees]
+
+\setuplabeltext
+ [\s!de]
+ [u:rad=Bogenma\SS,
+ u:deg=Gradma\SS]
+
+\setuplabeltext
+ [\s!it]
+ [u:rad=radianti,
+ u:deg=angoli sessagesimali]
+
+%D Rotation and frequency related units are defined by:
+
+\getvalue{\v!unit} [Hertz] {Hz} {Hertz}
+\getvalue{\v!unit} [kHertz] {\Kilo \Hertz} {kilo Hertz}
+\getvalue{\v!unit} [MHertz] {\Mega \Hertz} {mega Hertz}
+\getvalue{\v!unit} [GHertz] {\Giga \Hertz} {giga Hertz}
+\getvalue{\v!unit} [THertz] {\Tera \Hertz} {tera Hertz}
+\getvalue{\v!unit} [mHertz] {\Milli \Hertz} {milli Hertz}
+
+\getvalue{\v!unit} [RevPerSec] {RPS} {\labeltext{u:rps}}
+\getvalue{\v!unit} [RevPerMin] {RPM} {\labeltext{u:rpm}}
+
+\setuplabeltext
+ [\s!nl]
+ [u:rps=omwentelingen per seconde,
+ u:rpm=omwentelingen per minuut]
+
+\setuplabeltext
+ [\s!en]
+ [u:rps=revolutions per second,
+ u:rpm=revolutions per minute]
+
+\setuplabeltext
+ [\s!de]
+ [u:rps=Umdrehungen pro Sekunde,
+ u:rpm=Umdrehungen pro Minute]
+
+\setuplabeltext
+ [\s!it]
+ [u:rps=giri al secondo,
+ u:rpm=giri al minuto]
+
+%D Mass and force:
+
+\getvalue{\v!unit} [Gram] {g} {gram}
+\getvalue{\v!unit} [uGram] {\Micro \Gram} {microgram}
+\getvalue{\v!unit} [mGram] {\Milli \Gram} {milligram}
+\getvalue{\v!unit} [kGram] {\Kilo \Gram} {kilogram}
+\getvalue{\v!unit} [Atom] {u} {\labeltext{u:u}}
+
+\getvalue{\v!unit} [Newton] {N} {Newton}
+\getvalue{\v!unit} [kNewton] {\Kilo \Newton} {kilo Newton}
+
+\getvalue{\v!unit} [Pascal] {Pa} {Pascal}
+\getvalue{\v!unit} [mPascal] {\Milli \Pascal} {milli Pascal}
+\getvalue{\v!unit} [kPascal] {\Kilo \Pascal} {kilo Pascal}
+
+\setuplabeltext
+ [\s!nl]
+ [u:u=atomaire massa eenheid]
+
+\setuplabeltext
+ [\s!en]
+ [u:u=atom mass unit]
+
+\setuplabeltext
+ [\s!de]
+ [u:u=Atomare Masseneinheit]
+
+\setuplabeltext
+ [\s!it]
+ [u:u=unit\`a di massa atomica]
+
+%D Energy units comes in two alternatives:
+
+\getvalue{\v!unit} [Joule] {J} {Joule}
+\getvalue{\v!unit} [mJoule] {\Milli \Joule} {milli Joule}
+\getvalue{\v!unit} [kJoule] {\Kilo \Joule} {kilo Joule}
+\getvalue{\v!unit} [MJoule] {\Mega \Joule} {mega Joule}
+\getvalue{\v!unit} [GJoule] {\Giga \Joule} {giga Joule}
+
+\getvalue{\v!unit} [Watt] {W} {Watt}
+\getvalue{\v!unit} [mWatt] {\Milli \Watt} {milli Watt}
+\getvalue{\v!unit} [kWatt] {\Kilo \Watt} {kilo Watt}
+\getvalue{\v!unit} [MWatt] {\Mega \Watt} {mega Watt}
+\getvalue{\v!unit} [GWatt] {\Giga \Watt} {giga Watt}
+\getvalue{\v!unit} [TWatt] {\Tera \Watt} {tera Watt}
+
+%D Although Celsius is no longer permitted, we define it by
+%D saying:
+
+\getvalue{\v!unit} [Celsius] {C} {Celsius}
+\getvalue{\v!unit} [Kelvin] {K} {Kelvin}
+\getvalue{\v!unit} [Fahrenheit] {F} {Fahrenheit}
+
+%D Some chemic related units are:
+
+\getvalue{\v!unit} [Mol] {mol} {mol}
+\getvalue{\v!unit} [mMol] {\Milli \Mol} {millimol}
+\getvalue{\v!unit} [kMol] {\Kilo \Mol} {kilomol}
+\getvalue{\v!unit} [Molair] {M} {molair (\Mol \Per \Liter)}
+\getvalue{\v!unit} [Equivalent] {eq} {equivalent}
+\getvalue{\v!unit} [mEquivalent] {\Milli \Equivalent} {milli equivalent}
+
+%D There are quite a lot units related to electricity and
+%D magnetism:
+
+\getvalue{\v!unit} [Farad] {F} {Farad}
+\getvalue{\v!unit} [pFarad] {\Pico \Farad} {pico Farad}
+\getvalue{\v!unit} [nFarad] {\Nano \Farad} {nano Farad}
+\getvalue{\v!unit} [uFarad] {\Micro \Farad} {micro Farad}
+\getvalue{\v!unit} [mFarad] {\Milli \Farad} {milli Farad}
+
+\getvalue{\v!unit} [Ohm] {\Omega} {Ohm}
+\getvalue{\v!unit} [kOhm] {\Kilo \Ohm} {kilo Ohm}
+
+\getvalue{\v!unit} [Siemens] {S} {Siemens}
+
+\getvalue{\v!unit} [Ampere] {A} {Amp\`ere}
+\getvalue{\v!unit} [mAmpere] {\Milli \Ampere} {milli Amp\`ere}
+
+\getvalue{\v!unit} [Coulomb] {C} {Coulomb}
+
+\getvalue{\v!unit} [Volt] {V} {Volt}
+\getvalue{\v!unit} [mVolt] {\Milli \Volt} {milli Volt}
+\getvalue{\v!unit} [kVolt] {\Kilo \Volt} {kilo Volt}
+\getvalue{\v!unit} [eVolt] {eV} {electronvolt}
+\getvalue{\v!unit} [keVolt] {\Kilo \eVolt} {kilo electronvolt}
+\getvalue{\v!unit} [MeVolt] {\Mega \eVolt} {mega electronvolt}
+
+\getvalue{\v!unit} [Tesla] {T} {Tesla}
+
+\getvalue{\v!unit} [VoltAC] {V_{\xbox{ac}}} {\labeltext{u:vac}}
+\getvalue{\v!unit} [VoltDC] {V_{\xbox{dc}}} {\labeltext{u:vdc}}
+
+\setuplabeltext
+ [\s!nl]
+ [u:vac=wisselspanning,
+ u:vdc=gelijkspanning]
+
+\setuplabeltext
+ [\s!en]
+ [u:vac=alternating current,
+ u:vdc=direct current]
+
+\setuplabeltext
+ [\s!de]
+ [u:vac=Wechselspannung,
+ u:vdc=Gleichspannung]
+
+\setuplabeltext
+ [\s!it]
+ [u:vac=corrente alternata,
+ u:vdc=corrente continua]
+
+%D Computer memory is specified in Bytes:
+
+\getvalue{\v!unit} [Baud] {Baud} {Baud (Bit/s)}
+\getvalue{\v!unit} [Bit] {Bit} {Bit}
+
+\getvalue{\v!unit} [Byte] {Byte} {Byte}
+\getvalue{\v!unit} [kByte] {\Kilo \Byte} {kilo Byte}
+\getvalue{\v!unit} [MByte] {\Mega \Byte} {mega Byte}
+\getvalue{\v!unit} [GByte] {\Giga \Byte} {giga Byte}
+\getvalue{\v!unit} [TByte] {\Tera \Byte} {tera Byte}
+
+%D Some radiation related units:
+
+\getvalue{\v!unit} [Bequerel] {Bq} {Bequerel}
+\getvalue{\v!unit} [MBequerel] {\Mega \Bequerel} {Bequerel}
+\getvalue{\v!unit} [Sievert] {Sv} {Sievert}
+\getvalue{\v!unit} [mSievert] {\Milli \Sievert} {milli Sievert}
+
+%D Light:
+
+\getvalue{\v!unit} [Candela] {cd} {Candela}
+
+%D and some sound ones:
+
+\getvalue{\v!unit} [Bell] {B} {Bell}
+\getvalue{\v!unit} [dBell] {\Deci \Bell} {decibel}
+
+%D We also define some non||regular, sometimes even forbidden,
+%D units:
+
+\getvalue{\v!unit} [At] {at} {\labeltext{u:at}}
+\getvalue{\v!unit} [Atm] {atm} {\labeltext{u:atm}}
+\getvalue{\v!unit} [Bar] {bar} {bar (100 \Kilo \Pascal)}
+\getvalue{\v!unit} [EVolt] {eV} {electronvolt}
+\getvalue{\v!unit} [Foot] {ft} {\labeltext{u:ft}}
+\getvalue{\v!unit} [Inch] {inch} {inch}
+\getvalue{\v!unit} [Cal] {cal} {\labeltext{u:cal}}
+\getvalue{\v!unit} [Force] {f} {\labeltext{u:f}}
+\getvalue{\v!unit} [kCal] {\Kilo \Cal} {\labeltext{u:kcal}}
+\getvalue{\v!unit} [Lux] {lux} {lux}
+
+
+\def\xPercent {\dimensionaddfix{\percent }}
+\def\xPromille{\dimensionaddfix{\promille}}
+
+\getvalue{\v!unit} [Percent] {\xPercent } {percent}
+\getvalue{\v!unit} [Permille] {\xPromille} {promille}
+\getvalue{\v!unit} [Promille] {\xPromille} {promille}
+
+%D Some more, thanks to Tobias:
+
+\getvalue{\v!unit} [Gray] {Gr} {Gray}
+\getvalue{\v!unit} [Weber] {Wb} {Weber}
+\getvalue{\v!unit} [Henry] {H} {Henry}
+\getvalue{\v!unit} [Sterant] {sr} {Sterant}
+\getvalue{\v!unit} [Angstrom] {\hbox{\Aring}} {\Aring ngstr\"om}
+\getvalue{\v!unit} [Gauss] {G} {Gauss}
+
+\setuplabeltext
+ [\s!nl]
+ [u:at=technische atmosfeer,
+ u:atm=fysische atmosfeer,
+ u:ft=voet,
+ u:cal=calorie,
+ u:f=kracht (force),
+ u:kcal=kilocalorie]
+
+\setuplabeltext
+ [\s!en]
+ [u:at=technical atmosferic pressure,
+ u:atm=physical atmosferic pressure,
+ u:ft=foot,
+ u:cal=calory,
+ u:f=force,
+ u:kcal=kilocalory]
+
+\setuplabeltext
+ [\s!de]
+ [u:at=Technischer atmosph\"arischer Druck,
+ u:atm=physkalischer atmosph\"arischer Druck
+ u:ft=Fu\SS,
+ u:cal=Kalorien,
+ u:f=Force,
+ u:kcal=Kilokalorien]
+
+\setuplabeltext
+ [\s!it]
+ [u:at=pressione atmosferica tecnica,
+ u:atm=pressione atmosfera fisica,
+ u:ft=piede,
+ u:cal=caloria,
+ u:f=forza,
+ u:kcal=chilocaloria]
+
+%D Here are some old ones, still there for compatibility
+%D reasons. These will probably be obsolete in a few years.
+
+\def\MeterTwee {\Square \Meter}
+\def\mMeterTwee {\Square \Milli \Meter}
+\def\cMeterTwee {\Square \Centi \Meter}
+\def\dMeterTwee {\Square \Deci \Meter}
+\def\kMeterTwee {\Square \Kilo \Meter}
+
+\def\MeterDrie {\Cubic \Meter}
+\def\mMeterDrie {\Cubic \Milli \Meter}
+\def\cMeterDrie {\Kubic \Centi \Meter}
+\def\dMeterDrie {\Cubic \Deci \Meter}
+\def\kMeterDrie {\Cubic \Kilo \Meter}
+
+\def\LiterTwee {\Square \Liter}
+\def\SecTwee {\Square \Sec}
+\def\SecMinEen {\Inverse \Sec}
+
+%D To make ourselves happy, we define some dutch specific
+%D units:
+
+\startinterface dutch
+
+ \getvalue{\v!unit} [PaardenKracht] {pk} {paardenkracht}
+ \getvalue{\v!unit} [Duits] {D} {duits}
+ \getvalue{\v!unit} [Kwik] {Hg} {kwikkolom}
+ \getvalue{\v!unit} [Hectare] {ha} {hectare}
+ \getvalue{\v!unit} [kGramForce] {\Kilo \Gram \Force} {kilogramforce}
+ \getvalue{\v!unit} [kWattUur] {\Kilo \Watt \Uur} {kilowattuur}
+ \getvalue{\v!unit} [MeterKwik] {\Meter \Kwik} {meter kwikkolom}
+ \getvalue{\v!unit} [Waterkolom] {WK} {waterkolom}
+ \getvalue{\v!unit} [MeterWater] {\Meter \Waterkolom} {meter waterkolom}
+ \getvalue{\v!unit} [DrogeStof] {ds} {droge stof}
+ \getvalue{\v!unit} [Normaal] {N} {normaal}
+
+ \getvalue{\v!unit} [Ton] {t} {ton}
+ \getvalue{\v!unit} [kTon] {\Kilo \Ton} {kiloton}
+
+ \let \OmwPerSec \RevPerSec
+ \let \OmwPerMin \RevPerMin
+ \let \Graden \Deg
+ \let \PaardeKracht \PaardenKracht
+ \let \Atoom \Atom
+ \let \Heure \Hour
+ \let \Jaar \Year
+ \let \Maand \Month
+ \let \Dag \Day
+ \let \Uur \Hour
+
+\stopinterface
+
+%D Finally we define some equivalents. By using \type {\let}
+%D we can be sure that they don't end up double in the lists of
+%D units.
+
+\let \Second \Sec
+\let \Kubic \Cubic
+\let \IKubic \ICubic
+
+%D Option:
+
+% \def\Micro{\dimensionprefix{\iftextdimensions\mathematics\mu \else\mu \fi}}
+% \def\Times{\dimensionnopfix{\iftextdimensions\mathematics\cdot\else\cdot\fi}}
+
+\protect \endinput
diff --git a/tex/context/base/m-visual.tex b/tex/context/base/m-visual.tex
new file mode 100644
index 000000000..d78455190
--- /dev/null
+++ b/tex/context/base/m-visual.tex
@@ -0,0 +1,316 @@
+%D \module
+%D [ file=m-visual,
+%D version=2000.01.10,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Visualization and Faking,
+%D author={Hans Hagen \& Ton Otten},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+%D This module collect a few more visual debugger features. I
+%D needed them for manuals and styles. The macros are documented
+%D in a my way document.
+
+%D For Mojca:
+%D
+%D \starttyping
+%D \def\simplethesis
+%D {\setupsystem[random=1234]
+%D \title{\fakewords{3}{4}}
+%D \placelist[chapter,section]
+%D \dorecurse{6}
+%D {\chapter{\fakewords{5}{10}}
+%D \dorecurse{5}
+%D {\section{\fakewords{2}{5}}
+%D \dorecurse{2}
+%D {\dorecurse{3}{\fakewords{100}{200}\endgraf}
+%D \placefigure{\fakewords{8}{15}}{\fakefigure{5cm}{3cm}{10cm}{5cm}}
+%D \dorecurse{2}{\fakewords{100}{200}\endgraf}}}}}
+%D
+%D \starttext
+%D \simplethesis
+%D \stoptext
+%D \stoptyping
+
+\definecolor[fakerulecolor] [black]
+\definecolor[fakebaselinecolor] [green]
+\definecolor[fakeparindentcolor][blue]
+
+\newif\iffakebaseline \fakebaselinetrue
+
+\def\fakerule#1%
+ {\strut
+ \startcolor[fakerulecolor]%
+ \iffakebaseline
+ \vrule\!!height1.25ex\!!depth-.05ex\!!width#1%
+ \kern-#1%
+ \vrule\!!height-.05ex\!!depth .25ex\!!width#1%
+ \else
+ \vrule\!!height1.25ex\!!depth .25ex\!!width#1%
+ \fi
+ \stopcolor
+ \allowbreak}
+
+\def\dorandomrecurse#1%
+ {\getrandomcount\scratchcounter{1}{#1}%
+ \dorecurse\scratchcounter}
+
+% can be used in hbox, so %'s are really needed
+
+\unexpanded\def\fakelines#1#2% min max / 3 10
+ {\fakeparindent
+ \scratchdimen\hsize
+ \ifindentation
+ \advance\scratchdimen -\parindent
+ \fi
+ \fakerule\scratchdimen\break
+ \getrandomcount\scratchcounter{\ifcase0#1 3\else#1\fi}{\ifcase0#2 10\else#2\fi}%
+ \dorecurse\scratchcounter{\fakerule\hsize}%
+ \getrandomdimen\scratchdimen{.25\hsize}\hsize
+ \fakerule\scratchdimen
+ \par} % indeed
+
+\unexpanded\def\fakewords
+ {\ifvmode\fakeparindent\fi\onlyfakewords}
+
+\definepalet
+ [fakerule]
+ [fr1c=darkred,
+ fr2c=darkgreen,
+ fr3c=darkblue,
+ fr4c=darkyellow,
+ fr5c=darkgray]
+
+\unexpanded\def\onlyfakewords#1#2% min max / 10 40
+ {\getrandomcount\scratchcounter{\ifcase0#1 10\else#1\fi}{\ifcase0#2 40\else#2\fi}%
+ \dofakewords\scratchcounter
+ } % no \par
+
+\unexpanded\def\fakenwords#1#2% words seed
+ {\fakeparindent
+ \getrandomseed\fakedwordseed
+ \setrandomseed{\ifcase0#2 #1\else#2\fi}%
+ \dofakewords{#1}%
+ \setrandomseed\fakedwordseed
+ } % no \par
+
+\def\dofakewords#1%
+ {\bgroup
+ \dorecurse{#1}
+ {\getrandomcount\scratchcounter{1}{5}%
+ \dorecurse\scratchcounter
+ {\getrandomdimen\scratchdimen{.5em}{1.25em}%
+ \fakerule\scratchdimen}%
+ \space}%
+ \removeunwantedspaces
+ \egroup}
+
+\def\doshowfakewords#1%
+ {\bgroup
+ \setuppalet[fakerule]%
+ \definecolor[fakerulecolor]%
+ \dorecurse{#1}
+ {\getrandomcount\scratchcounter{1}{5}%
+ \dorecurse\scratchcounter
+ {\getrandomdimen\scratchdimen{.5em}{1.25em}%
+ \color[fr\recurselevel c]{\fakerule\scratchdimen}}%
+ \space}%
+ \removeunwantedspaces
+ \egroup}
+
+\def\showfakewords{\let\dofakewords\doshowfakewords}
+
+\def\fakeword
+ {\fakewords{1}{1}} % no \plusone
+
+\def\fakeparindent
+ {\noindent
+ \ifindentation
+ \ifx\dofakedroppedcaps\relax
+ {\fakeparindentcolor
+ \vrule
+ \!!height \strutheight % not longer .5ex
+ \!!depth \strutdepth % not longer 0pt
+ \!!width \parindent}%
+ \else
+ \dofakedroppedcaps \let\dofakedroppedcaps\relax
+ \fi
+% \else
+% \dontleavehmode
+ \fi}
+
+\let\dofakedroppedcaps\relax
+
+\unexpanded\def\fakedroppedcaps#1%
+ {\ifnum#1>0
+ \def\dofakedroppedcaps
+ {\setbox\scratchbox\hbox
+ {\setbox\scratchbox\hbox{W}%
+ \scratchdimen#1\lineheight
+ \advance\scratchdimen -\lineheight
+ \advance\scratchdimen \dp\strutbox
+ \vrule
+ \!!width#1\wd\scratchbox
+ \!!height\ht\scratchbox
+ \!!depth\scratchdimen}%
+ \ht\scratchbox\ht\strutbox
+ \dp\scratchbox\dp\strutbox
+ \hangindent\wd\scratchbox
+ \advance\hangindent .5em
+ \wd\scratchbox\hangindent
+ \hangafter-#1\noindent
+ \llap{\fakeparindentcolor\box\scratchbox}}%
+ \fi}
+
+\newcounter\noffakedfigures
+
+\unexpanded\def\showfakefigure
+ {\donetrue\dodoubleempty\dofakefigure}
+
+\unexpanded\def\fakefigure
+ {\donefalse\dodoubleempty\dofakefigure}
+
+\def\dofakefigure[#1][#2]#3#4#5#6% [] [] minwidth maxwidth minheight maxheight
+ {\doglobal\increment\noffakedfigures
+ \ifdone
+ \endgraf
+ \hbox to \hsize
+ {\hss\fakeparindentcolor
+ \strut\bf Figure \noffakedfigures
+ \doifsomething{#1}{\space(#1)}%
+ \hss}
+ \endgraf
+ \fi
+ \getvalue{\e!place\v!figure}
+ [#1][#2]%
+ {\freezerandomseed
+ \let\endstrut\relax
+ \let\begstrut\relax
+ \doifinsetelse{#1}{\v!left,\v!right}
+ {\fakewords{2}{4}}
+ {\fakewords{4}{10}}}%
+ {\getrandomdimen{\dimen0}{#3}{#4}%
+ \getrandomdimen{\dimen2}{#5}{#6}%
+ \doifinset{#1}{\v!left,\v!right}
+ {\dimen0=.75\dimen0
+ \ifdim\dimen0>.6\hsize \dimen0=.5\hsize\fi
+ \ifdim\dimen0<.3\hsize \dimen0=.3\hsize\fi}%
+ \framed
+ [\c!width=\dimen0,
+ \c!height=\dimen2,
+ \c!frame=\ifincolor\v!off\else\v!on\fi,
+ \c!background=\v!color,
+ \c!backgroundcolor=fakeparindentcolor]
+ {\bf\white#1}}%
+ \defrostrandomseed}
+
+\def\fakeformula
+ {\dimen0\zeropoint
+ \getrandomcount\scratchcounter{3}{6}%
+ \dorecurse\scratchcounter
+ {\getrandomdimen\scratchdimen{1em}{3em}%
+ \mathinner{\red\fakerule\scratchdimen}%
+ \ifnum\recurselevel<\scratchcounter+\fi
+ \advance\scratchdimen\dimen0}%
+ =\mathinner{\red\fakerule\scratchdimen}}
+
+\def\fakespacingformula
+ {\color[fakebaselinecolor]{\ruledbaseline}\fakeformula}
+
+%D test \type{\bodyfontgrid}\space test
+%D test \type{\emexgrid} \space test
+
+
+\def\smashedgrid
+ {\dosingleempty\dosmashedgrid}
+
+\def\dosmashedgrid[#1]%
+ {\hsmashed
+ {\setbox\scratchbox=\hbox
+ {\basegrid
+ [\c!nx=10,\c!ny=10,\c!dx=1,\c!dy=1,
+ \c!unit=\bodyfontsize,#1]}%
+ \hbox to \zeropoint
+ {\hss\lower.5\ht\scratchbox\box\scratchbox\hss}%
+ \hbox to \zeropoint
+ {\hss
+ \black\vrule\!!width6\linewidth\!!height3\linewidth\!!depth3\linewidth
+ \hss}}}
+
+\def\bodyfontgrid
+ {\hbox
+ {{\linewidth.1pt\yellow\smashedgrid[\c!nx=30,\c!ny=30,\c!scale=.3333]}%
+ {\linewidth.2pt\green \smashedgrid[\c!nx=20,\c!ny=20,\c!scale=.5]}%
+ {\linewidth.3pt\red \smashedgrid[\c!nx=10,\c!ny=10,\c!scale=1]}}}
+
+\def\emexgrid
+ {\hbox
+ {{\linewidth.15pt\green\smashedgrid[\c!nx=20,\c!ny=20,\c!unit=ex]}%
+ {\linewidth.15pt\red \smashedgrid[\c!nx=10,\c!ny=10,\c!unit=em]}}}
+
+%D The next few macros are not really public and kind of low
+%D level. They are obscure and a bit perverse.
+
+\definecolor[llblack][s=0.01]
+
+\def\lowlevelstream#1#2#3%
+ {\ifinotr \else
+ \dontleavehmode
+ \prewordbreak
+ \bgroup\bgroup % make sure aftergroup stuff is handled
+ %\let#1#2\optimizetransparencyfalse\black
+ \infofont\clap{\vl}\ignorespaces#3\unskip\clap{\vl}%
+ \egroup\egroup
+ \prewordbreak
+ \fi
+ #2{#3}}
+
+\let\normalPDFcode\PDFcode
+
+\def\showlowlevelstream
+ {\def\PDFcode{\lowlevelstream\PDFcode\normalPDFcode}%
+ \def\special{\lowlevelstream\special\normalspecial}}
+
+\def\showlowlevelstreamonly
+ {\def\PDFcode{\lowlevelstream\PDFcode\gobbleoneargument}%
+ \def\special{\lowlevelstream\special\gobbleoneargument}}
+
+\startnotmode[mkiv]
+
+ \let\normaldostartgraymode \dostartgraymode
+ \let\normaldostartgraycolormode\dostartgraycolormode
+ \let\normaldostartrgbcolormode \dostartrgbcolormode
+ \let\normaldostartcmykcolormode\dostartcmykcolormode
+ \let\normaldostartspotcolormode\dostartspotcolormode
+
+ \def\traceddostartgraymode#1%
+ {#1\normaldostartgraymode{#1}}
+
+ \def\traceddostartgraycolormode#1%
+ {#1\normaldostartgraycolormode{#1}}
+
+ \def\traceddostartrgbcolormode#1#2#3%
+ {#1 #2 #3\normaldostartrgbcolormode{#1}{#2}{#3}}
+
+ \def\traceddostartcmykcolormode#1#2#3#4%
+ {#1 #2 #3 #4\normaldostartcmykcolormode{#1}{#2}{#3}{#4}}
+
+ \def\traceddostartspotcolormode#1#2%
+ {#1 #2\normaldostartspotcolormode{#1}{#2}}
+
+ \def\showcolormodes
+ {\let\dostartgraymode \traceddostartgraymode
+ \let\dostartgraycolormode\traceddostartgraycolormode
+ \let\dostartrgbcolormode \traceddostartrgbcolormode
+ \let\dostartcmykcolormode\traceddostartcmykcolormode
+ \let\dostartspotcolormode\traceddostartspotcolormode}
+
+\stopnotmode
+
+\protect \endinput
diff --git a/tex/context/base/math-ali.mkiv b/tex/context/base/math-ali.mkiv
new file mode 100644
index 000000000..31f71219a
--- /dev/null
+++ b/tex/context/base/math-ali.mkiv
@@ -0,0 +1,1296 @@
+%D \module
+%D [ file=math-ali,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Math Alignments,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE / Hans Hagen]
+%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 Math Macros / Math Alignments}
+
+\unprotect
+
+%D The code here has been moved from other files. Beware: the \MKII\ and
+%D \MKIV\ code is not gathered in files with the same name.
+
+%D \macros
+%D {definemathalignment, setupmathalignment, startmathalignment}
+%D
+%D Modules may provide additional alignment features. The following
+%D mechanisms are provided by the core.
+
+% n>1 #### needed, strange # interaction in recurse
+
+\def\presetdisplaymath{\displ@y} % some day i will relocate the plain stuff
+
+\def\buildeqalign
+ {\scratchtoks\emptytoks
+ \dorecurse{\mathalignmentparameter\c!m}
+ {\ifnum\recurselevel>\plusone
+ \appendtoks
+ \tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint
+ \to\scratchtoks
+ \fi
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksa}}%
+ \dorecurse{\numexpr\mathalignmentparameter\c!n-\plusone\relax}
+ {\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}}%
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc}}}
+
+\def\forgetalign
+ {\tabskip\zeropoint\everycr\emptytoks}
+
+\let\firstineqalign\empty
+\let\nextineqalign \empty
+\let\leftofeqalign \empty
+\let\rightofeqalign\empty
+
+\def\mathineqalign#1{$\forgetalign\displaystyle{{}#1{}}$}
+\def\textineqalign#1{$\forgetalign#1$}
+
+\def\eqalign#1% why no halign here, probably because of displaywidth
+ {\null\,\vcenter
+ {\openup.25\bodyfontsize% was: \openup\jot
+ \mathsurround\zeropoint
+ \ialign{\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##{}}$\hfil\crcr#1\crcr}%
+ }\,}
+
+% preamble is scanned for tabskips so we need the span to prevent an error message
+
+\chardef\eqalignmode\plusone
+
+\def\preparereqalignno
+ {\!!toksa{\strut\firstineqalign\hfil\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
+ \!!toksb{&\nextineqalign\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
+ \ifnum\mathraggedstatus=\plusone
+ \!!toksc{\hfil&\span\textineqalign{##}\tabskip\zeropoint}%
+ \else\ifnum\mathraggedstatus=\plusthree
+ \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\span\textineqalign{##}\tabskip\zeropoint}%
+ \else
+ \!!toksc{\hfil\tabskip\centering&\llap{\span\textineqalign{##}}\tabskip\zeropoint}%
+ \fi\fi
+ \global\chardef\mathnumberstatus\zerocount
+ \buildeqalign
+ \presetdisplaymath
+ \tabskip\centering}
+
+\def\prepareleqalignno
+ {\!!toksa{\strut\firstineqalign\hfil\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
+ \!!toksb{&\nextineqalign\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
+ % problem: number is handled after rest and so ends up in the margin
+ \ifnum\mathraggedstatus=\plusone
+ \!!toksc{\hfil&\kern-\displaywidth\rlap{\span\textineqalign{##}}\tabskip\displaywidth}%
+ \else\ifnum\mathraggedstatus=\plusthree
+ \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\kern-\displaywidth\span\mrlap{\span\textineqalign{##}}\tabskip\displaywidth}%
+ \else
+ \!!toksc{\hfil\tabskip\centering&\kern-\displaywidth\rlap{\span\textineqalign{##}}\tabskip\displaywidth}%
+ \fi\fi
+ \global\chardef\mathnumberstatus\zerocount
+ \buildeqalign
+ \presetdisplaymath
+ \tabskip\centering}
+
+\def\dobotheqalignno#1#2%
+ {\ifmmode
+ \displ@y % \let\doplaceformulanumber\relax % strange hack
+ \vcenter\bgroup
+ \let\finishalignno\egroup
+ \else
+ \let\finishalignno\relax
+ \fi
+ #1%
+ \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA {\the\scratchtoks\crcr#2\crcr}%
+ \finishalignno}
+
+\def\dobothaligneqalignno#1%
+ {\ifmmode
+ \displ@y
+ \global\chardef\mathnumberstatus\plusone
+ \ifcase\mathraggedstatus
+ \def\finishalignno{\crcr\egroup}%
+ \else
+ % we're in a mathbox
+ \vcenter\bgroup
+ \def\finishalignno{\crcr\egroup\egroup}%
+ \fi
+ \fi
+ #1%
+ \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA \bgroup\the\scratchtoks\crcr}
+
+\def\mrlap#1%
+ {\setbox\scratchbox\hbox{#1}%
+ \ifdim\wd\scratchbox>\mathnumbercorrection
+ \xdef\mathnumbercorrection{\the\wd\scratchbox}%
+ \fi
+ \box\scratchbox
+ \global\chardef\mathnumberstatus\plustwo}
+
+% \def\dobothaligneqalignno#1%
+% {\ifmmode
+% \displ@y
+% \global\chardef\mathnumberstatus\plusone
+% we're in a mathbox
+% \vcenter\bgroup
+% \def\finishalignno{\crcr\egroup\egroup}%
+% \else
+% \def\finishalignno{\crcr\egroup}%
+% \fi
+% #1%
+% \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA \bgroup\the\scratchtoks\crcr}
+
+\def\reqalignno {\dobotheqalignno \preparereqalignno}
+\def\leqalignno {\dobotheqalignno \prepareleqalignno}
+\def\alignreqalignno{\dobothaligneqalignno\preparereqalignno}
+\def\alignleqalignno{\dobothaligneqalignno\prepareleqalignno}
+\def\finishalignno {\crcr\egroup}
+
+\let \equalignno \reqalignno
+\let\aligneqalignno\alignreqalignno
+
+%D Here we implement the user interface part.
+
+\unexpanded\def\setupmathalignment
+ {\dodoubleempty\dosetupmathalignment}
+
+\def\dosetupmathalignment[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??eq#1][#2]%
+ \else
+ \getparameters[\??eq][#1]%
+ \fi}
+
+\let\currentmathalignment\empty
+
+\def\mathalignmentparameter#1%
+ {\executeifdefined{\??eq\currentmathalignment#1}{\executeifdefined{\??eq#1}\empty}}
+
+\setupmathalignment
+ [\c!n=2,
+ \c!m=1,
+ \c!distance=1em]
+
+\def\numberedeqalign
+ {\doifelse{\formulaparameter\c!location}\v!left\alignleqalignno\alignreqalignno}
+
+\def\doxxdoubleempty#1#2%
+ {\ifx#2[\expandafter\dodoxxdoubleempty\else\expandafter\noxxdoubleempty\fi#1#2}
+
+\def\dodoxxdoubleempty#1[#2]#3%
+ {\ifx#3[\else\expandafter\nonoxxdoubleempty\fi#1[#2]#3}
+
+\def\noxxdoubleempty #1{#1[][]}
+\def\nonoxxdoubleempty#1[#2]{#1[#2][]}
+
+\newcount\eqaligncolumn
+
+\def\firstineqalign{\global\eqaligncolumn\plusone}
+\def\nextineqalign {\global\advance\eqaligncolumn\plusone}
+\def\leftofeqalign {\getvalue{\??eq:\v!left :\number\eqaligncolumn}}
+\def\rightofeqalign{\getvalue{\??eq:\v!right:\number\eqaligncolumn}}
+
+\def\doseteqaligncolumn#1%
+ {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\empty
+ \letvalue{\??eq:\v!right:\number\eqaligncolumn}\empty
+ \doif{#1}\v!left {\letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfill}%
+ \doif{#1}\v!right {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfill}%
+ \doif{#1}\v!middle{\letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfill
+ \letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfill}}
+
+\def\dodoalignNC
+ {\gdef\doalignNC##1{#1}}
+
+\def\doalignNR[#1][#2]%
+ {\donestedformulanumber{#1}{#2}\crcr}
+
+%D \starttyping
+%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0]
+%D \placeformula[eqn1]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn1]
+%D \placeformula \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2]
+%D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+] \stopalign \stopformula See \in[eqn3]
+%D \stoptyping
+
+% todo: pop in cell
+
+\def\dostartmathalignment[#1][#2]%
+ {% \begingroup not permitted ($$...assignments...\halign... )
+ \pushmacro\doalignNC
+ \edef\currentmathalignment{#1}%
+ \doifassignmentelse{#2}{\setupmathalignment[#1][#2]}\donothing
+ \def\NC{\doalignNC}%
+ \global\let\doalignNC\dodoalignNC
+ \def\EQ{&=}%
+ \def\NR{&\global\let\doalignNC\dodoalignNC\doxxdoubleempty\doalignNR}%
+ % amstex compatibility mode: (ugly, will disappear)
+ \def\notag{\def\\{&\crcr}}%
+ \doifelse{#2}{*}{\def\\{&\crcr}}{\def\\{&\doalignNR[+][]\crcr}}%
+ % end of compatibility mode
+ \eqaligncolumn\zerocount
+ \processcommacommand
+ [\mathalignmentparameter\c!align]
+ {\advance\eqaligncolumn\plusone\doseteqaligncolumn}% takes argument
+ % the real action
+ \global\eqaligncolumn\plusone
+ \numberedeqalign}
+
+\def\dostopmathalignment
+ {\finishalignno
+ \popmacro\doalignNC}
+
+\unexpanded\def\definemathalignment
+ {\dodoubleempty\dodefinemathalignment}
+
+\def\dodefinemathalignment[#1]% [#2]%
+ {\setvalue{\e!start#1}{\dodoubleempty\dostartmathalignment[#1]}%
+ \setvalue{\e!stop #1}{\dostopmathalignment}%
+ \setupmathalignment[#1]}% [#2]
+
+%D For the moment we only provide english commands.
+
+\definemathalignment[align] % default case (this is what amstex users expect)
+\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing)
+
+%D \startbuffer
+%D \placeformula \startformula \eqalignno {
+%D a &= b & \formulanumber \cr
+%D c &= d \cr
+%D &= e \cr
+%D &= f & \formulanumber
+%D } \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \EQ b \NR[+]
+%D \NC c \EQ d \NR
+%D \NC \EQ f \NR[for:demo-a-1]
+%D \NC \EQ g \NR[for:demo-a-2][a]
+%D \NC \EQ h \NR[for:demo-a-3][b]
+%D \NC \EQ i \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \EQ b \NR[+]
+%D \NC c \EQ d \NR
+%D \NC \EQ f \NR
+%D \NC \EQ g \NR
+%D \NC \EQ h \NR
+%D \NC \EQ i \NR[+]
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D a &= b \\
+%D c &= d \notag \\
+%D &= e \notag \\
+%D &= f \\
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D \NC a \NC \eq b \NR[+]
+%D \NC c \NC \neq d \NR
+%D \NC \NC \neq f \NR[for:demo-b-1]
+%D \NC \NC \geq g \NR[for:demo-b-2][a]
+%D \NC \NC \leq h \NR[for:demo-b-3][b]
+%D \NC \NC \neq i \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[*]
+%D a &= b \\
+%D c &= d \\
+%D &= e \\
+%D &= f \\
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign
+%D x &= y \\
+%D a &= b \\
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[m=3]
+%D x &= y & x &= y & z &= t \\
+%D a &= b & p &= q & w &= s \\
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[m=3,distance=0pt]
+%D x &= y &= x &= y &= z &= t \\
+%D a &= b &= p &= q &= w &= s \\
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=5,distance=0pt]
+%D x &= yy &= xx &= yy &= zz \\
+%D a &= b &= p &= q &= w \\
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={left,middle,right}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={right,middle,left}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}]
+%D \NC l \NC = \NC r \NR
+%D \NC left \NC = \NC right \NR
+%D \stopalign \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformula
+%D \startalign[n=3,align={middle,middle,middle}]
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformulas
+%D \setupmathalignment[n=3,align={middle,middle,middle}]%
+%D \startformula
+%D \startalign
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \startformula
+%D \startalign
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula
+%D \stopformulas
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula
+%D \startformulas
+%D \dorecurse{5}{\startformula
+%D \startalign[n=3,align={middle,middle,middle}]
+%D \NC a \NC = \NC b \NR[+]
+%D \NC 2a \NC = \NC 2b \NR
+%D \stopalign
+%D \stopformula}
+%D \stopformulas
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {definemathcases, setupmathcases, startmathcases}
+%D
+%D Another wish \unknown
+
+\unexpanded\def\setupmathcases
+ {\dodoubleempty\dosetupmathcases}
+
+\def\dosetupmathcases[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??ce#1][#2]%
+ \else
+ \getparameters[\??ce][#1]%
+ \fi}
+
+\let\currentmathcases\empty
+
+\def\mathcasesparameter#1%
+ {\executeifdefined{\??ce\currentmathcases#1}{\executeifdefined{\??ce#1}\empty}}
+
+\setupmathcases
+ [\c!distance=1em,
+ \c!numberdistance=2.5em,
+ \c!left={\left\{\,},
+ \c!right={\right.}]
+
+\def\dodocasesNC
+ {\gdef\docasesNC{\endmath&}}
+
+\let\docasesNR\doalignNR
+
+\def\dostartmathcases[#1][#2]%
+ {\begingroup
+ \edef\currentmathcases{#1}%
+ \doifassignmentelse{#2}{\setupmathcases[#1][#2]}\donothing
+ \mathcasesparameter\c!left
+ \vcenter\bgroup
+ \pushmacro\docasesNC
+ \let\endmath\relax
+ \def\NC{\docasesNC}%
+ \def\MC{\docasesNC\ifmmode\else$\def\endmath{$}\fi}%
+ \global\let\docasesNC\dodocasesNC
+ \def\NR{\unskip\endmath&\global\let\docasesNC\dodocasesNC\doxxdoubleempty\docasesNR}%
+ \normalbaselines
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \global\eqaligncolumn\plusone
+ \halign\bgroup
+ $\mathcasesparameter\c!style##$\hfil
+ &\hskip\mathcasesparameter\c!distance\relax
+ \popmacro\docasesNC##\hfil
+ &\hskip\mathcasesparameter\c!numberdistance\relax
+ \let\formuladistance\!!zeropoint
+ \span\textineqalign{##}%
+ \crcr} % todo: number
+
+\def\dostopmathcases
+ {\crcr
+ \egroup
+ \popmacro\docasesNC
+ \egroup
+ \mathcasesparameter\c!right
+ \endgroup}
+
+\unexpanded\def\definemathcases
+ {\dodoubleempty\dodefinemathcases}
+
+\def\dodefinemathcases[#1]% [#2]%
+ {\setvalue{\e!start#1}{\dodoubleempty\dostartmathcases[#1]}%
+ \setvalue{\e!stop #1}{\dostopmathcases}%
+ \setupmathcases[#1]}% [#2]
+
+\definemathcases[cases]
+\definemathcases[\v!mathcases]
+
+%D \startbuffer
+%D \placeformula \startformula \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR[+]
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula x \startcases
+%D \NC 2 \NC $ y > 0 $ \NR[+]
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \placeformula \startformula x \startcases
+%D \NC 2 \NC $ y > 0 $ \NR
+%D \NC 7 \NC $ x = 7 $ \NR
+%D \NC 4 \NC otherwise \NR
+%D \stopcases \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {definemathmatrix, setupmathmatrix, startmathmatrix}
+%D
+%D Yet another one \unknown
+
+\unexpanded\def\setupmathmatrix
+ {\dodoubleempty\dosetupmathmatrix}
+
+\def\dosetupmathmatrix[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??mx#1][#2]%
+ \else
+ \getparameters[\??mx][#1]%
+ \fi}
+
+\let\currentmathmatrix\empty
+
+\def\mathmatrixparameter#1%
+ {\executeifdefined{\??mx\currentmathmatrix#1}{\executeifdefined{\??mx#1}\empty}}
+
+\setupmathmatrix
+ [\c!distance=1em,
+ \c!left=,
+ \c!right=,
+ \c!align=\v!middle]
+
+\def\dosetmatrixcolumn#1% hh: todo: \definematrixalign
+ {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfil
+ \letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfil
+ \doif{#1}\v!left {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\relax
+ \letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfil}%
+ \doif{#1}\v!right {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfil
+ \letvalue{\??eq:\v!right:\number\eqaligncolumn}\relax }%
+ \doif{#1}\v!middle{\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfil
+ \letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfil}}
+
+\def\buildmathmatrix % beware: etex only
+ {\scratchtoks\emptytoks
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksa}}%
+ \dorecurse{\numexpr\scratchcounter-\plusone\relax}
+ {\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}%
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc }}}
+
+\def\preparemathmatrix
+ {\!!toksa{\strut \firstineqalign\leftofeqalign \span
+ \textineqalign{\mathmatrixparameter\c!style ##}\rightofeqalign}%
+ \!!toksb{&\hskip\mathmatrixparameter\c!distance
+ \nextineqalign\leftofeqalign \span
+ \textineqalign{\mathmatrixparameter\c!style ##}\rightofeqalign}%
+ \!!toksc{&&\hskip\mathmatrixparameter\c!distance
+ \leftofeqalign \span
+ \textineqalign{\mathmatrixparameter\c!style ##}\rightofeqalign}%
+ \buildmathmatrix
+ \halign \@EA \bgroup\the\scratchtoks \crcr}
+
+\unexpanded\def\definemathmatrix
+ {\dodoubleempty\dodefinemathmatrix}
+
+\def\dodefinemathmatrix[#1]% [#2]%
+ {\setuvalue{\e!start#1}{\dodoubleempty\dostartmathmatrix[#1]}%
+ \setuvalue{\e!stop #1}{\dostopmathmatrix}%
+ \setupmathmatrix[#1]}% [#2]
+
+\definemathmatrix[matrix]
+\definemathmatrix[\v!mathmatrix]
+
+\unexpanded\def\dodomatrixNC
+ {\gdef\domatrixNC{\endmath&}}
+
+\def\installmathmatrixhandler#1#2%
+ {\setvalue{\??mx:#1}{#2}}
+
+% First alternative:
+%
+% \def\processlowhighmathmatrix#1%
+% {\def\mathmatrixleft
+% {\setbox\nextbox}
+% \def\mathmatrixright
+% {#1.5\dimexpr\nextboxdp-\nextboxht\relax
+% \hbox{$\mathmatrixparameter\c!left
+% \vcenter{\unvbox\nextbox}%
+% \mathmatrixparameter\c!right$}}%
+% \let\mathmatrixbox\vbox}
+%
+% \installmathmatrixhandler\v!high {\processlowhighmathmatrix\raise}
+% \installmathmatrixhandler\v!low {\processlowhighmathmatrix\lower}
+%
+% \installmathmatrixhandler\v!top {\processlowhighmathmatrix\raise}
+% \installmathmatrixhandler\v!bottom{\processlowhighmathmatrix\lower}
+%
+% \installmathmatrixhandler\v!lohi
+% {\def\mathmatrixleft {\mathmatrixparameter\c!left}%
+% \def\mathmatrixright{\mathmatrixparameter\c!right}%
+% \let\mathmatrixbox\vcenter}
+%
+% An alternative
+%
+% \let\mathmatrixleft \empty
+% \let\mathmatrixright\empty
+%
+% \def\processlowhighmathmatrix#1%
+% {\dowithnextbox
+% {#1.5\dimexpr\nextboxdp-\nextboxht\relax
+% \hbox{$\mathmatrixparameter\c!left
+% \vcenter{\unvbox\nextbox}%
+% \mathmatrixparameter\c!right$}}%
+% \vbox}
+%
+% \def\processlohimathmatrix
+% {\dowithnextbox
+% {\mathmatrixparameter\c!left
+% \vcenter{\unvbox\nextbox}%
+% \mathmatrixparameter\c!right}%
+% \vbox}
+%
+% \installmathmatrixhandler\v!high {\def\mathmatrixbox{\processlowhighmathmatrix\raise}}
+% \installmathmatrixhandler\v!low {\def\mathmatrixbox{\processlowhighmathmatrix\lower}}
+% \installmathmatrixhandler\v!top {\def\mathmatrixbox{\processlowhighmathmatrix\raise}}
+% \installmathmatrixhandler\v!bottom{\def\mathmatrixbox{\processlowhighmathmatrix\lower}}
+% \installmathmatrixhandler\v!lohi {\let\mathmatrixbox \processlohimathmatrix}
+%
+% Final version
+
+\let\mathmatrixleft \empty % experimental hook
+\let\mathmatrixright\empty % experimental hook
+
+\def\processlowhighmathmatrix#1#2%
+ {\dowithnextbox
+ {\scratchdimen\dimexpr(\nextboxdp-\nextboxht)/2 \ifcase#2\or+\mathaxisheight\textfont2\fi\relax
+ \ifcase#1\relax\or\lower\scratchdimen\or\or\raise\scratchdimen\fi
+ \hbox{$\mathmatrixparameter\c!left
+ \vcenter{\unvbox\nextbox}%
+ \mathmatrixparameter\c!right$}}%
+ \vbox}
+
+\installmathmatrixhandler\v!top {\def\mathmatrixbox{\processlowhighmathmatrix\plusthree\plusone }}
+\installmathmatrixhandler\v!high {\def\mathmatrixbox{\processlowhighmathmatrix\plusthree\zerocount}}
+\installmathmatrixhandler\v!lohi {\def\mathmatrixbox{\processlowhighmathmatrix\plustwo \zerocount}}
+\installmathmatrixhandler\v!low {\def\mathmatrixbox{\processlowhighmathmatrix\plusone \zerocount}}
+\installmathmatrixhandler\v!bottom{\def\mathmatrixbox{\processlowhighmathmatrix\plusone \plusone }}
+
+\def\dostartmathmatrix[#1][#2]%
+ {\begingroup
+ \edef\currentmathmatrix{#1}%
+ \doifassignmentelse{#2}{\setupmathmatrix[#1][#2]}\donothing
+ \null
+ \executeifdefined{\??mx:\mathmatrixparameter\c!location}{\getvalue{\??mx:\v!lohi}}%
+ \mathmatrixleft
+ \mathmatrixbox\bgroup
+ \pushmacro\domatrixNC
+ \let\endmath\relax
+ \def\NC{\domatrixNC}%
+ \def\MC{\domatrixNC\ifmmode\else$\def\endmath{$}\fi}%
+ \global\let\domatrixNC\dodomatrixNC
+ \def\NR{\endmath\global\let\domatrixNC\dodomatrixNC\crcr}%
+ \normalbaselines
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \tabskip\zeropoint
+ \eqaligncolumn\zerocount % could be \scratchcounter
+ \processcommacommand[\mathmatrixparameter\c!align]{\advance\eqaligncolumn\plusone\dosetmatrixcolumn}%
+ \scratchcounter=\ifnum\eqaligncolumn>\zerocount \eqaligncolumn \else \plusone \fi
+ \global\eqaligncolumn\plusone
+ \preparemathmatrix } % uses scratchcounter
+
+\def\dostopmathmatrix
+ {\crcr
+ \mathstrut\crcr
+ \noalign{\kern-\baselineskip}%
+ \egroup
+ \popmacro\domatrixNC
+ \egroup
+ \mathmatrixright
+ \endgroup}
+
+%D \startbuffer
+%D \placeformula \startformula[-] \startmatrix
+%D \NC 1 \NC x \NC a \NR
+%D \NC 2 \NC y \NC b \NR
+%D \NC 3 \NC z \NC c \NR
+%D \stopmatrix \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \definemathmatrix[bmatrix][left={\left[\,},right={\,\right]}]
+%D
+%D \startbuffer
+%D \placeformula \startformula[-] \startbmatrix
+%D \NC 1 \NC x \NC a \NR
+%D \NC 2 \NC y \NC b \NR
+%D \NC 3 \NC z \NC c \NR
+%D \stopbmatrix \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Taco added some code (dedicated to Aditya Mahajan) that gives more
+%D control over aligments:
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix
+%D \NC a + x \NC = \NC a + d \NR
+%D \NC y \NC = \NC d \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix [distance=3pt,align={right,left}]
+%D \NC a + x \NC = a + d \NR
+%D \NC y \NC = d \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix [left=\left(,right=\right)]
+%D \NC a + x \NR
+%D \NC y \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D A bit more complex code:
+%D
+%D \startbuffer
+%D \startformula
+%D \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}}
+%D \left\{ (R_1, R_2) :
+%D \startmatrix[distance=1em,align={left,left,right}]
+%D \NC R_1 \NC < I(X_1 ; Y \mid X_2) \NC R_1 \NR
+%D \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1) \NC R_2 \NR
+%D \NC R_1 + R_2 \NC < I(X_1 ; Y) \NC R_1 + R_2 \NR
+%D \stopmatrix
+%D \right\}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {startmatrices}
+%D
+%D Just a handy keystroke safer:
+
+\unexpanded\def\startmatrices
+ {\begingroup
+ \setupmathmatrix}
+
+\unexpanded\def\stopmatrices
+ {\endgroup}
+
+%D \startbuffer
+%D \startformula
+%D \startmatrix[left={\left(},right={\right)}]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[left={\left(},right={\right)},location=low]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[left={\left(},right={\right)},location=high]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D \startformula
+%D \startmatrices[left={\left(},right={\right)}]
+%D \startmatrix
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[location=bottom]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D =
+%D \startmatrix[location=top]
+%D \NC A \NC B \NR \NC C \NC D \NR
+%D \stopmatrix
+%D \stopmatrices
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % does not run well: \getbuffer
+
+%D \macros
+%D {startintertext}
+%D
+%D Preliminary feature:
+%D
+%D {\em example code}
+
+\unexpanded\def\startintertext#1\stopintertext
+ {\noalign{\dointertext{#1}}}
+
+\def\intertext#1%
+ {\noalign{\dointertext{#1}}}
+
+\unexpanded\def\dointertext#1%
+ {\penalty\postdisplaypenalty
+ \afterdisplayspace
+ \vbox{\forgetall\noindent#1\par}%
+ \penalty\predisplaypenalty
+ \beforedisplayspace}
+
+% %D \macros
+% %D {substack}
+% %D
+% %D Preliminary code:
+% %D
+% %D \starttyping
+% %D \startformula
+% %D \sum_{%
+% %D \startsubstack
+% %D i = 1 \NR
+% %D i \neq n \NR
+% %D i \neq m
+% %D \stopsubstack
+% %D }a_i
+% %D \stopformula
+% %D \stoptyping
+
+% \unexpanded\def\startsubstack
+% {\begingroup
+% \null
+% \vcenter\bgroup
+% \pushmacro\domatrixNC
+% \let\stopmathmode\relax
+% \def\NC{\domatrixNC}%
+% \def\MC{\domatrixNC\startmathmode}%
+% \global\let\domatrixNC\dodomatrixNC
+% \def\NR
+% {\stopmathmode
+% \global\let\domatrixNC\dodomatrixNC
+% \crcr\noalign{\nointerlineskip}}%
+% \mathsurround\zeropoint
+% \everycr\emptytoks
+% \halign\bgroup\hfil$\scriptstyle\mathstrut##$\hfil\crcr}
+
+% \unexpanded\def\stopsubstack
+% {\crcr
+% \egroup
+% \popmacro\domatrixNC
+% \egroup
+% \endgroup}
+
+%D \macros
+%D {substack}
+%D
+%D Preliminary code:
+%D
+%D \startbuffer
+%D \startformula
+%D \sum_{%
+%D \startsubstack
+%D i = 1 \NR
+%D i \neq n \NR
+%D i \neq m
+%D \stopsubstack
+%D }a_i
+%D \stopformula
+%D \stopbuffer
+%D
+%D \getbuffer which was typed as \typebuffer
+%D
+%D Notice that these macros give the correct spacing for
+%D subscripts. Compare for example
+%D
+%D \startbuffer
+%D \startformula
+%D \sum_{\startsubstack a \NR b \NR \stopsubstack}
+%D \text{ and }
+%D \sum_{\scriptstyle a \atop \scriptstyle}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer which gives \getbuffer
+
+\unexpanded\def\startsubstack
+ {\begingroup
+ \vcenter\bgroup
+ \baselineskip\mathstacktotal
+ \lineskip\mathstackvgap
+ \lineskiplimit\lineskip
+ \let\stopmathmode\relax
+ \def\NC{\domatrixNC}%
+ \def\MC{\domatrixNC\startmathmode}%
+ \global\let\domatrixNC\dodomatrixNC
+ \def\NR
+ {\stopmathmode
+ \global\let\domatrixNC\dodomatrixNC
+ \crcr}%
+ \mathsurround\zeropoint
+ \everycr\emptytoks
+ \halign\bgroup\hfil$\scriptstyle##$\hfil\crcr}
+
+\unexpanded\def\stopsubstack
+ {\crcr
+ \egroup
+ \egroup
+ \endgroup}
+
+%D \macros
+%D {bordermatrix}
+%D
+%D In \PLAIN\ \TEX\ the width of a parenthesis is stored in
+%D the \DIMENSION\ \type{\mathparentwd}. This value is derived from
+%D the width of \type{\tenrm B}, so let's take care of it now:
+
+\ifx\mathparentwd\undefined \newdimen\mathparentwd \fi
+
+\let\normalbordermatrix\bordermatrix
+
+\def\bordermatrix
+ {\begingroup
+ \setbox\scratchbox\hbox{\mr\char"239C}%
+ \global\mathparentwd\wd\scratchbox\relax
+ \endgroup
+ \normalbordermatrix}
+
+% to be tested
+%
+% \def\bordermatrix
+% {\begingroup\mr\global\mathparentwd\fontcharwd\font"239C\relax\endgroup
+% \normalbordermatrix}
+
+%D \macros{overset, underset}
+%D
+%D The macros \type{\overset} and \type{\underset} are provided by
+%D \AMS\ packages in \LATEX. These macro allows you to place a symbol
+%D above or below another symbol, irrespective of whether the other
+%D symbol is a relation or something else, and without influencing the
+%D spacing. For most cases there is a better way to do such things
+%D (declaring a math command with limop option, or using accents), but
+%D occasionally these macros can be useful, for example:
+%D
+%D \startbuffer
+%D \startformula
+%D \overset{*}{X} \underset{*}{X}
+%D \stopformula
+%D \stopbuffer
+%D \typebuffer \getbuffer
+%D
+%D Use these macros sparingly. Remember, \TEX\ was designed for
+%D mathematics, so there is usually a proper method for typesetting
+%D common math notation.
+
+%D These macros are a clearer version of \type{\binrel@} and
+%D \type{\binrel@@} macros in \AMSTEX\ packages.
+
+\def\preparebinrel#1%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\thinmuskip 0mu
+ \medmuskip -1mu
+ \thickmuskip -1mu
+ \setbox\scratchbox\hbox{$#1\mathsurround\zeropoint$}%
+ \kern-\wd\scratchbox
+ ${}#1{}\mathsurround\zeropoint$}%
+ \normalexpanded
+ {\endgroup
+ \let\noexpand\currentbinrel
+ \ifdim\wd\scratchbox<\zeropoint
+ \mathbin
+ \else\ifdim\wd\scratchbox>\zeropoint
+ \mathrel
+ \else
+ \relax
+ \fi\fi}}
+
+\unexpanded\def\overset#1#2%
+ {\preparebinrel{#2}%
+ \currentbinrel{\mathop{\kern\zeropoint#2}\limits^{#1}}}
+
+\unexpanded\def\underset#1#2%
+ {\preparebinrel{#2}%
+ \currentbinrel{\mathop{\kern\zeropoint#2}\limits_{#1}}}
+
+%D The following code comes from \type {math-str.mkiv}.
+
+%D Here we implement a basic math alignment mechanism. Numbers
+%D are also handled. The macros \type {\startinnermath} and
+%D \type {\stopinnermath} can be overloaded in specialized
+%D modules.
+
+\unexpanded\def\startinnermath
+ {\getvalue{\e!start\??fm\formulaparameter\c!align}}
+
+\unexpanded\def\stopinnermath
+ {\getvalue{\e!stop \??fm\formulaparameter\c!align}}
+
+\def\mathinnerstrut
+ {\doif{\formulaparameter\c!strut}\v!yes\strut}
+
+\long\unexpanded\def\defineinnermathhandler#1#2#3%
+ {\setvalue{\e!start\??fm#1}{#2}%
+ \setvalue{\e!stop \??fm#1}{#3}}
+
+\newif\iftracemath
+
+\def\mathhbox
+ {\iftracemath\ruledhbox\else\hbox\fi}
+
+\chardef\mathraggedstatus=0 % normal left center right
+\chardef\mathnumberstatus=0 % nothing normal shift_right
+\let\mathnumbercorrection\!!zeropoint
+
+\unexpanded\def\startmathbox#1%
+ {\hsize\displaywidth
+ \global\chardef\mathnumberstatus\plusone
+ \chardef\mathraggedstatus#1\relax
+ \let\mathnumbercorrection\!!zeropoint
+ \global\let\@eqno \empty \def\eqno {\gdef\@eqno }%
+ \global\let\@leqno\empty \def\leqno{\gdef\@leqno}%
+ % added
+ \let\normalreqno\eqno
+ \let\normalleqno\leqno
+ % added
+ \doplaceformulanumber
+ \setbox\scratchbox\mathhbox to \displaywidth\bgroup
+ \mathinnerstrut
+ $%
+ \displaystyle
+ \ifcase\mathraggedstatus\or\hfill\or\hfill\fi}
+
+\def\llappedmathno
+ {\ifcase\mathraggedstatus\or
+ \@eqno
+ \or
+ \llap{\@eqno}%
+ \or
+ \llap{\@eqno}%
+ \fi}
+
+\def\rlappedmathno
+ {\ifcase\mathraggedstatus\or
+ \rlap{\@leqno}%
+ \or
+ \rlap{\@leqno}%
+ \or
+ \@leqno
+ \fi}
+
+\unexpanded\def\stopmathbox
+ {$%
+ \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi
+ \egroup
+ \setbox0\hbox{\unhcopy\scratchbox}%
+ \scratchdimen\wd0
+ \ifdim\scratchdimen>\displaywidth
+ \donetrue
+ \else
+ \donefalse
+ \fi
+ \hbox to \displaywidth\bgroup
+ \ifcase\mathnumberstatus
+ \box\scratchbox
+ \or
+ \ifx\@leqno\empty
+ \ifx\@eqno\empty
+ \box\scratchbox
+ \else
+ \ifdone
+ \vbox{\box\scratchbox\hbox to \displaywidth{\hss\llappedmathno}}%
+ \else
+ \hss\box\scratchbox\llappedmathno % hss makes room for number
+ \fi
+ \fi
+ \else
+ \ifdone
+ \vbox{\hbox to \displaywidth{\rlappedmathno\hss}\box\scratchbox}%
+ \else
+ \rlappedmathno\box\scratchbox\hss % hss makes room for number
+ \fi
+ \fi
+ \or
+ \hskip\mathnumbercorrection
+ \box\scratchbox
+ \hss
+ \else
+ \box\scratchbox
+ \fi
+ \egroup}
+
+\defineinnermathhandler\v!left {\startmathbox\plusone }{\stopmathbox}
+\defineinnermathhandler\v!middle {\startmathbox\plustwo }{\stopmathbox}
+\defineinnermathhandler\v!right {\startmathbox\plusthree}{\stopmathbox}
+\defineinnermathhandler\v!flushleft {\startmathbox\plusthree}{\stopmathbox}
+\defineinnermathhandler\v!center {\startmathbox\plustwo }{\stopmathbox}
+\defineinnermathhandler\v!flushright{\startmathbox\plusone }{\stopmathbox}
+
+%D [The examples below are in english and don't process in the
+%D documentation style, which will be english some day.]
+%D
+%D Normally a formula is centered, but in case you want to
+%D align it left or right, you can set up formulas to behave
+%D that way. Normally a formula will adapt is left indentation
+%D to the environment:
+%D
+%D \startbuffer
+%D \fakewords{20}{40}\epar
+%D \startitemize
+%D \item \fakewords{20}{40}\epar
+%D \placeformula \startformula \fakeformula \stopformula
+%D \item \fakewords{20}{40}\epar
+%D \stopitemize
+%D \fakewords{20}{40}\epar
+%D \stopbuffer
+%D
+%D % \getbuffer
+%D
+%D In the next examples we explicitly align formulas to the
+%D left (\type {\raggedleft}), center and right (\type
+%D {\raggedright}):
+%D
+%D \startbuffer
+%D \setupformulas[align=left]
+%D \startformula\fakeformula\stopformula
+%D \setupformulas[align=middle]
+%D \startformula\fakeformula\stopformula
+%D \setupformulas[align=right]
+%D \startformula\fakeformula\stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Or in print:
+%D
+%D % {\getbuffer}
+%D
+%D With formula numbers these formulas look as follows:
+%D
+%D \startbuffer
+%D \setupformulas[align=left]
+%D \placeformula \startformula\fakeformula\stopformula
+%D \setupformulas[align=middle]
+%D \placeformula \startformula\fakeformula\stopformula
+%D \setupformulas[align=right]
+%D \placeformula \startformula\fakeformula\stopformula
+%D \stopbuffer
+%D
+%D % {\getbuffer}
+%D
+%D This was keyed in as:
+%D
+%D \typebuffer
+%D
+%D When tracing is turned on (\type {\tracemathtrue}) you can
+%D visualize the bounding box of the formula,
+%D
+%D % {\tracemathtrue\getbuffer}
+%D
+%D As you can see, the dimensions are the natural ones, but if
+%D needed you can force a normalized line:
+%D
+%D \startbuffer
+%D \setupformulas[strut=yes]
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This time we get a more spacy result.
+%D
+%D % {\tracemathtrue\getbuffer}
+%D
+%D We will now show a couple of more settings and combinations
+%D of settings. In centered formulas, the number takes no space
+%D
+%D \startbuffer
+%D \setupformulas[align=middle]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+%D
+%D You can influence the placement of the whole box with the
+%D parameters \type {leftmargin} and \type {rightmargin}.
+%D
+%D \startbuffer
+%D \setupformulas[align=right,leftmargin=3em]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D
+%D \setupformulas[align=left,rightmargin=1em]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+%D
+%D You can also inherit the margin from the environment.
+%D
+%D \startbuffer
+%D \setupformulas[align=right,margin=standard]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+%D
+%D The distance between the formula and the number is only
+%D applied when the formula is left or right aligned.
+%D
+%D \startbuffer
+%D \setupformulas[align=left,distance=2em]
+%D \startformula \fakeformula \stopformula
+%D \placeformula \startformula \fakeformula \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer % {\tracemathtrue\getbuffer}
+
+\protect \endinput
+
+% \placeformula \startformula[-] \startmatrix
+% \NC 1 \NC x \NC a \NR
+% \NC 2 \NC y \NC b \NR
+% \NC 3 \NC z \NC c \NR
+% \stopmatrix \stopformula
+
+% \definemathmatrix[bordermatrix][left={\left[\,},right={\,\right]}]
+
+% \placeformula \startformula[-] \startbordermatrix
+% \NC 1 \NC x \NC a \NR
+% \NC 2 \NC y \NC b \NR
+% \NC 3 \NC z \NC c \NR
+% \stopbordermatrix \stopformula
diff --git a/tex/context/base/math-ams.mkii b/tex/context/base/math-ams.mkii
new file mode 100644
index 000000000..83070d01a
--- /dev/null
+++ b/tex/context/base/math-ams.mkii
@@ -0,0 +1,336 @@
+%D \module
+%D [ file=math-ams,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=AMS Specials,
+%D author={Hans Hagen \& Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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
+
+% maybe we should just include these into the default tex one
+
+\definefamilysynonym [default] [blackboard] [mb]
+
+\startmathcollection [default]
+
+\definemathsymbol [varGamma] [ord] [letters] ["00]
+\definemathsymbol [varDelta] [ord] [letters] ["01]
+\definemathsymbol [varTheta] [ord] [letters] ["02]
+\definemathsymbol [varLambda] [ord] [letters] ["03]
+\definemathsymbol [varXi] [ord] [letters] ["04]
+\definemathsymbol [varPi] [ord] [letters] ["05]
+\definemathsymbol [varSigma] [ord] [letters] ["06]
+\definemathsymbol [varUpsilon] [ord] [letters] ["07]
+\definemathsymbol [varPhi] [ord] [letters] ["08]
+\definemathsymbol [varPsi] [ord] [letters] ["09]
+\definemathsymbol [varOmega] [ord] [letters] ["0A]
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [internalAnd] [rel] [operators] ["26]
+
+\stopmathcollection
+
+\startmathcollection [default]
+
+\definemathsymbol [boxdot] [bin] [ma] ["00]
+\definemathsymbol [boxplus] [bin] [ma] ["01]
+\definemathsymbol [boxtimes] [bin] [ma] ["02]
+\definemathsymbol [square] [ord] [ma] ["03]
+\definemathsymbol [Box] [ord] [ma] ["03] % square
+\definemathsymbol [blacksquare] [ord] [ma] ["04]
+\definemathsymbol [centerdot] [bin] [ma] ["05]
+\definemathsymbol [Diamond] [ord] [ma] ["06]
+\definemathsymbol [lozenge] [ord] [ma] ["06] % Diamond
+\definemathsymbol [blacklozenge] [ord] [ma] ["07]
+\definemathsymbol [circlearrowright] [rel] [ma] ["08]
+\definemathsymbol [circlearrowleft] [rel] [ma] ["09]
+\definemathsymbol [rightleftharpoons] [rel] [ma] ["0A]
+\definemathsymbol [leftrightharpoons] [rel] [ma] ["0B]
+\definemathsymbol [boxminus] [bin] [ma] ["0C]
+\definemathsymbol [Vdash] [rel] [ma] ["0D]
+\definemathsymbol [Vvdash] [rel] [ma] ["0E]
+\definemathsymbol [vDash] [rel] [ma] ["0F]
+\definemathsymbol [twoheadrightarrow] [rel] [ma] ["10]
+\definemathsymbol [twoheadleftarrow] [rel] [ma] ["11]
+\definemathsymbol [leftleftarrows] [rel] [ma] ["12]
+\definemathsymbol [rightrightarrows] [rel] [ma] ["13]
+\definemathsymbol [upuparrows] [rel] [ma] ["14]
+\definemathsymbol [downdownarrows] [rel] [ma] ["15]
+\definemathsymbol [upharpoonright] [rel] [ma] ["16]
+\definemathsymbol [restriction] [rel] [ma] ["16]
+\definemathsymbol [downharpoonright] [rel] [ma] ["17]
+\definemathsymbol [upharpoonleft] [rel] [ma] ["18]
+\definemathsymbol [downharpoonleft] [rel] [ma] ["19]
+\definemathsymbol [rightarrowtail] [rel] [ma] ["1A]
+\definemathsymbol [leftarrowtail] [rel] [ma] ["1B]
+\definemathsymbol [leftrightarrows] [rel] [ma] ["1C]
+\definemathsymbol [rightleftarrows] [rel] [ma] ["1D]
+\definemathsymbol [Lsh] [rel] [ma] ["1E]
+\definemathsymbol [Rsh] [rel] [ma] ["1F]
+\definemathsymbol [rightsquigarrow] [rel] [ma] ["20]
+\definemathsymbol [leadsto] [rel] [ma] ["20] % rightsquigarrow
+\definemathsymbol [leftrightsquigarrow] [rel] [ma] ["21]
+\definemathsymbol [looparrowleft] [rel] [ma] ["22]
+\definemathsymbol [looparrowright] [rel] [ma] ["23]
+\definemathsymbol [circeq] [rel] [ma] ["24]
+\definemathsymbol [succsim] [rel] [ma] ["25]
+\definemathsymbol [gtrsim] [rel] [ma] ["26]
+\definemathsymbol [gtrapprox] [rel] [ma] ["27]
+\definemathsymbol [multimap] [rel] [ma] ["28]
+\definemathsymbol [therefore] [rel] [ma] ["29]
+\definemathsymbol [because] [rel] [ma] ["2A]
+\definemathsymbol [doteqdot] [rel] [ma] ["2B]
+\definemathsymbol [Doteq] [rel] [ma] ["2B] % doteqdot
+\definemathsymbol [triangleq] [rel] [ma] ["2C]
+\definemathsymbol [precsim] [rel] [ma] ["2D]
+\definemathsymbol [lesssim] [rel] [ma] ["2E]
+\definemathsymbol [lessapprox] [rel] [ma] ["2F]
+\definemathsymbol [eqslantless] [rel] [ma] ["30]
+\definemathsymbol [eqslantgtr] [rel] [ma] ["31]
+\definemathsymbol [curlyeqprec] [rel] [ma] ["32]
+\definemathsymbol [curlyeqsucc] [rel] [ma] ["33]
+\definemathsymbol [preccurlyeq] [rel] [ma] ["34]
+\definemathsymbol [leqq] [rel] [ma] ["35]
+\definemathsymbol [leqslant] [rel] [ma] ["36]
+\definemathsymbol [lessgtr] [rel] [ma] ["37]
+\definemathsymbol [backprime] [ord] [ma] ["38]
+\definemathsymbol [dabar@] [ord] [ma] ["39] % @
+\definemathsymbol [risingdotseq] [rel] [ma] ["3A]
+\definemathsymbol [fallingdotseq] [rel] [ma] ["3B]
+\definemathsymbol [succcurlyeq] [rel] [ma] ["3C]
+\definemathsymbol [geqq] [rel] [ma] ["3D]
+\definemathsymbol [geqslant] [rel] [ma] ["3E]
+\definemathsymbol [gtrless] [rel] [ma] ["3F]
+\definemathsymbol [sqsubset] [rel] [ma] ["40]
+\definemathsymbol [sqsupset] [rel] [ma] ["41]
+\definemathsymbol [vartriangleright] [rel] [ma] ["42]
+\definemathsymbol [rhd] [bin] [ma] ["42]
+\definemathsymbol [lhd] [bin] [ma] ["43]
+\definemathsymbol [vartriangleleft] [rel] [ma] ["43]
+\definemathsymbol [trianglerighteq] [rel] [ma] ["44]
+\definemathsymbol [unrhd] [bin] [ma] ["44] % trianglerighteq
+\definemathsymbol [trianglelefteq] [rel] [ma] ["45]
+\definemathsymbol [unlhd] [bin] [ma] ["45] % trianglelefteq
+\definemathsymbol [bigstar] [ord] [ma] ["46]
+\definemathsymbol [between] [rel] [ma] ["47]
+\definemathsymbol [blacktriangledown] [ord] [ma] ["48]
+\definemathsymbol [blacktriangleright] [rel] [ma] ["49]
+\definemathsymbol [blacktriangleleft] [rel] [ma] ["4A]
+\definemathsymbol [vartriangle] [rel] [ma] ["4D]
+\definemathsymbol [triangleup] [ord] [ma] ["4D] % vartriangle
+\definemathsymbol [blacktriangle] [ord] [ma] ["4E]
+\definemathsymbol [triangledown] [ord] [ma] ["4F]
+\definemathsymbol [eqcirc] [rel] [ma] ["50]
+\definemathsymbol [lesseqgtr] [rel] [ma] ["51]
+\definemathsymbol [gtreqless] [rel] [ma] ["52]
+\definemathsymbol [lesseqqgtr] [rel] [ma] ["53]
+\definemathsymbol [gtreqqless] [rel] [ma] ["54]
+\definemathsymbol [Rrightarrow] [rel] [ma] ["56]
+\definemathsymbol [Lleftarrow] [rel] [ma] ["57]
+\definemathsymbol [veebar] [bin] [ma] ["59]
+\definemathsymbol [barwedge] [bin] [ma] ["5A]
+\definemathsymbol [doublebarwedge] [bin] [ma] ["5B]
+\definemathsymbol [angle] [ord] [ma] ["5C]
+\definemathsymbol [measuredangle] [ord] [ma] ["5D]
+\definemathsymbol [sphericalangle] [ord] [ma] ["5E]
+\definemathsymbol [varpropto] [rel] [ma] ["5F]
+\definemathsymbol [smallsmile] [rel] [ma] ["60]
+\definemathsymbol [smallfrown] [rel] [ma] ["61]
+\definemathsymbol [Subset] [rel] [ma] ["62]
+\definemathsymbol [Supset] [rel] [ma] ["63]
+\definemathsymbol [Cup] [bin] [ma] ["64]
+\definemathsymbol [doublecup] [bin] [ma] ["64] % Cup
+\definemathsymbol [Cap] [bin] [ma] ["65]
+\definemathsymbol [doublecap] [bin] [ma] ["65]
+\definemathsymbol [curlywedge] [bin] [ma] ["66]
+\definemathsymbol [curlyvee] [bin] [ma] ["67]
+\definemathsymbol [leftthreetimes] [bin] [ma] ["68]
+\definemathsymbol [rightthreetimes] [bin] [ma] ["69]
+\definemathsymbol [subseteqq] [rel] [ma] ["6A]
+\definemathsymbol [supseteqq] [rel] [ma] ["6B]
+\definemathsymbol [bumpeq] [rel] [ma] ["6C]
+\definemathsymbol [Bumpeq] [rel] [ma] ["6D]
+\definemathsymbol [llless] [rel] [ma] ["6E]
+\definemathsymbol [lll] [rel] [ma] ["6E] % llless
+\definemathsymbol [gggtr] [rel] [ma] ["6F]
+\definemathsymbol [ggg] [rel] [ma] ["6F] % gggtr
+\definemathsymbol [ulcorner] [open] [ma] ["70] [ma] ["70]
+\definemathsymbol [urcorner] [close] [ma] ["71] [ma] ["71]
+\definemathsymbol [circledS] [ord] [ma] ["73]
+\definemathsymbol [pitchfork] [rel] [ma] ["74]
+\definemathsymbol [dotplus] [bin] [ma] ["75]
+\definemathsymbol [backsim] [rel] [ma] ["76]
+\definemathsymbol [backsimeq] [rel] [ma] ["77]
+\definemathsymbol [llcorner] [open] [ma] ["78] [ma] ["78]
+\definemathsymbol [lrcorner] [close] [ma] ["79] [ma] ["79]
+\definemathsymbol [complement] [ord] [ma] ["7B]
+\definemathsymbol [intercal] [bin] [ma] ["7C]
+\definemathsymbol [circledcirc] [bin] [ma] ["7D]
+\definemathsymbol [circledast] [bin] [ma] ["7E]
+\definemathsymbol [circleddash] [bin] [ma] ["7F]
+
+\stopmathcollection
+
+\startmathcollection [default]
+
+\definemathcommand [integers] {\blackboard{Z}}
+\definemathcommand [reals] {\blackboard{R}}
+\definemathcommand [rationals] {\blackboard{Q}}
+\definemathcommand [naturalnumbers] {\blackboard{N}}
+\definemathcommand [complexes] {\blackboard{C}}
+\definemathcommand [primes] {\blackboard{P}}
+
+\stopmathcollection
+
+\startmathcollection [default]
+
+\definemathsymbol [lvertneqq] [rel] [mb] ["00]
+\definemathsymbol [gvertneqq] [rel] [mb] ["01]
+\definemathsymbol [nleq] [rel] [mb] ["02]
+\definemathsymbol [ngeq] [rel] [mb] ["03]
+\definemathsymbol [nless] [rel] [mb] ["04]
+\definemathsymbol [ngtr] [rel] [mb] ["05]
+\definemathsymbol [nprec] [rel] [mb] ["06]
+\definemathsymbol [nsucc] [rel] [mb] ["07]
+\definemathsymbol [lneqq] [rel] [mb] ["08]
+\definemathsymbol [gneqq] [rel] [mb] ["09]
+\definemathsymbol [nleqslant] [rel] [mb] ["0A]
+\definemathsymbol [ngeqslant] [rel] [mb] ["0B]
+\definemathsymbol [lneq] [rel] [mb] ["0C]
+\definemathsymbol [gneq] [rel] [mb] ["0D]
+\definemathsymbol [npreceq] [rel] [mb] ["0E]
+\definemathsymbol [nsucceq] [rel] [mb] ["0F]
+\definemathsymbol [precnsim] [rel] [mb] ["10]
+\definemathsymbol [succnsim] [rel] [mb] ["11]
+\definemathsymbol [lnsim] [rel] [mb] ["12]
+\definemathsymbol [gnsim] [rel] [mb] ["13]
+\definemathsymbol [nleqq] [rel] [mb] ["14]
+\definemathsymbol [ngeqq] [rel] [mb] ["15]
+\definemathsymbol [precneqq] [rel] [mb] ["16]
+\definemathsymbol [succneqq] [rel] [mb] ["17]
+\definemathsymbol [precnapprox] [rel] [mb] ["18]
+\definemathsymbol [succnapprox] [rel] [mb] ["19]
+\definemathsymbol [lnapprox] [rel] [mb] ["1A]
+\definemathsymbol [gnapprox] [rel] [mb] ["1B]
+\definemathsymbol [nsim] [rel] [mb] ["1C]
+\definemathsymbol [ncong] [rel] [mb] ["1D]
+\definemathsymbol [diagup] [ord] [mb] ["1E]
+\definemathsymbol [diagdown] [ord] [mb] ["1F]
+\definemathsymbol [varsubsetneq] [rel] [mb] ["20]
+\definemathsymbol [varsupsetneq] [rel] [mb] ["21]
+\definemathsymbol [nsubseteqq] [rel] [mb] ["22]
+\definemathsymbol [nsupseteqq] [rel] [mb] ["23]
+\definemathsymbol [subsetneqq] [rel] [mb] ["24]
+\definemathsymbol [supsetneqq] [rel] [mb] ["25]
+\definemathsymbol [varsubsetneqq] [rel] [mb] ["26]
+\definemathsymbol [varsupsetneqq] [rel] [mb] ["27]
+\definemathsymbol [subsetneq] [rel] [mb] ["28]
+\definemathsymbol [supsetneq] [rel] [mb] ["29]
+\definemathsymbol [nsubseteq] [rel] [mb] ["2A]
+\definemathsymbol [nsupseteq] [rel] [mb] ["2B]
+\definemathsymbol [nparallel] [rel] [mb] ["2C]
+\definemathsymbol [nmid] [rel] [mb] ["2D]
+\definemathsymbol [nshortmid] [rel] [mb] ["2E]
+\definemathsymbol [nshortparallel] [rel] [mb] ["2F]
+\definemathsymbol [nvdash] [rel] [mb] ["30]
+\definemathsymbol [nVdash] [rel] [mb] ["31]
+\definemathsymbol [nvDash] [rel] [mb] ["32]
+\definemathsymbol [nVDash] [rel] [mb] ["33]
+\definemathsymbol [ntrianglerighteq] [rel] [mb] ["34]
+\definemathsymbol [ntrianglelefteq] [rel] [mb] ["35]
+\definemathsymbol [ntriangleleft] [rel] [mb] ["36]
+\definemathsymbol [ntriangleright] [rel] [mb] ["37]
+\definemathsymbol [nleftarrow] [rel] [mb] ["38]
+\definemathsymbol [nrightarrow] [rel] [mb] ["39]
+\definemathsymbol [nLeftarrow] [rel] [mb] ["3A]
+\definemathsymbol [nRightarrow] [rel] [mb] ["3B]
+\definemathsymbol [nLeftrightarrow] [rel] [mb] ["3C]
+\definemathsymbol [nleftrightarrow] [rel] [mb] ["3D]
+\definemathsymbol [divideontimes] [bin] [mb] ["3E]
+\definemathsymbol [varnothing] [ord] [mb] ["3F]
+\definemathsymbol [nexists] [ord] [mb] ["40]
+\definemathsymbol [Finv] [ord] [mb] ["60]
+\definemathsymbol [Game] [ord] [mb] ["61]
+\definemathsymbol [mho] [ord] [mb] ["66]
+\definemathsymbol [eth] [ord] [mb] ["67]
+\definemathsymbol [eqsim] [rel] [mb] ["68]
+\definemathsymbol [beth] [ord] [mb] ["69]
+\definemathsymbol [gimel] [ord] [mb] ["6A]
+\definemathsymbol [daleth] [ord] [mb] ["6B]
+\definemathsymbol [lessdot] [bin] [mb] ["6C]
+\definemathsymbol [gtrdot] [bin] [mb] ["6D]
+\definemathsymbol [ltimes] [bin] [mb] ["6E]
+\definemathsymbol [rtimes] [bin] [mb] ["6F]
+\definemathsymbol [shortmid] [rel] [mb] ["70]
+\definemathsymbol [shortparallel] [rel] [mb] ["71]
+\definemathsymbol [smallsetminus] [bin] [mb] ["72]
+\definemathsymbol [thicksim] [rel] [mb] ["73]
+\definemathsymbol [thickapprox] [rel] [mb] ["74]
+\definemathsymbol [approxeq] [rel] [mb] ["75]
+\definemathsymbol [succapprox] [rel] [mb] ["76]
+\definemathsymbol [precapprox] [rel] [mb] ["77]
+\definemathsymbol [curvearrowleft] [rel] [mb] ["78]
+\definemathsymbol [curvearrowright] [rel] [mb] ["79]
+\definemathsymbol [digamma] [ord] [mb] ["7A]
+\definemathsymbol [varkappa] [ord] [mb] ["7B]
+\definemathsymbol [Bbbk] [ord] [mb] ["7C]
+\definemathsymbol [hslash] [ord] [mb] ["7D]
+\definemathsymbol [hbar] [ord] [mb] ["7E]
+\definemathsymbol [backepsilon] [rel] [mb] ["7F]
+
+\stopmathcollection
+
+\startmathcollection [default]
+
+\definemathcommand [yen] [nothing] {\mathhexbox{\hexmafam}55}
+\definemathcommand [checkmark] [nothing] {\mathhexbox{\hexmafam}58}
+\definemathcommand [circledR] [nothing] {\mathhexbox{\hexmafam}72}
+\definemathcommand [maltese] [nothing] {\mathhexbox{\hexmafam}7A}
+
+\stopmathcollection
+
+\startmathcollection [default]
+
+\definemathcommand [dashrightarrow] [rel] {\dabar@\dabar@ \mathchar"0C4B}
+\definemathcommand [dashleftarrow] [rel] {\mathchar"0C4C\dabar@ \dabar@}
+\definemathcommand [dasharrow] [rel] {\dabar@\dabar@ \mathchar"0C4B}
+\definemathcommand [Join] [rel] {\mathchar"0D6F\mkern-13.8mu\mathchar"0D6E}
+\definemathcommand [implies] [rel] {\;\Longrightarrow\;}
+\definemathcommand [impliedby] [rel] {\;\Longleftarrow\;}
+\definemathcommand [And] [rel] {\;\internalAnd\;}
+
+\stopmathcollection
+
+\def\AMSwidehat#1%
+ {\setbox\scratchbox\hbox{$\mathsurround\zeropoint#1$}%
+ \ifdim\wd\scratchbox>2em
+ \mathaccent"0\purefamilyhex{mb}5B{#1}%
+ \else
+ \mathaccent"0\purefamilyhex{ex}62{#1}%
+ \fi}
+
+\def\AMSwidetilde#1%
+ {\setbox\scratchbox\hbox{$\mathsurround\zeropoint#1$}%
+ \ifdim\wd\scratchbox>2em
+ \mathaccent"0\purefamilyhex{mb}5D{#1}%
+ \else
+ \mathaccent"0\purefamilyhex{ex}65{#1}%
+ \fi}
+
+\startmathcollection [default]
+
+\definemathcommand [widehat] {\AMSwidehat}
+\definemathcommand [widetilde] {\AMSwidetilde}
+
+\stopmathcollection
+
+\protect \endinput
diff --git a/tex/context/base/math-arr.mkii b/tex/context/base/math-arr.mkii
new file mode 100644
index 000000000..3b9abaa91
--- /dev/null
+++ b/tex/context/base/math-arr.mkii
@@ -0,0 +1,391 @@
+%D \module
+%D [ file=math-ext,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Arrows,
+%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Arrows}
+
+\unprotect
+
+%D These will be generalized! Is it still needed in \MKIV?
+
+%D We next define extensible arrows. Extensible arrows are arrows that
+%D change their length according to the width of the text to be placed
+%D above and below the arrow. Since we need to define a lot of arrows,
+%D we first define some helper macros. The basic idea is to measure
+%D the width of the box to be placed above and below the arrow, and
+%D make the \quotation{body} of the arrow as long as the bigger of the
+%D two widths.
+
+\def\mtharrfactor{1}
+\def\mtharrextra {0}
+
+\def\domthxarr#1#2#3#4#5% hm, looks like we do a double mathrel
+ {\begingroup
+ \def\mtharrfactor{1}%
+ \def\mtharrextra {0}%
+ \processaction[#1] % will be sped up
+ [ \v!none=>\def\mtharrfactor{0},
+ \v!small=>\def\mtharrextra{10},
+ \v!medium=>\def\mtharrextra{15},
+ \v!big=>\def\mtharrextra{20},
+ \v!normal=>,
+ \v!default=>,
+ \v!unknown=>\doifnumberelse{#1}{\def\mtharrextra{#1}}\donothing]%
+ \mathsurround\zeropoint
+ \muskip0=\thirdoffourarguments #2mu
+ \muskip2=\fourthoffourarguments #2mu
+ \muskip4=\firstoffourarguments #2mu
+ \muskip6=\secondoffourarguments #2mu
+ \muskip0=\mtharrfactor\muskip0 \advance\muskip0 \mtharrextra mu
+ \muskip2=\mtharrfactor\muskip2 \advance\muskip2 \mtharrextra mu
+ \setbox0\hbox{$\scriptstyle
+ \mkern\muskip4\relax
+ \mkern\muskip0\relax
+ #5\relax
+ \mkern\muskip2\relax
+ \mkern\muskip6\relax
+ $}%
+ \setbox4\hbox{#3\displaystyle}%
+ \dimen0\wd0
+ \ifdim\wd4>\dimen0 \dimen0\wd4 \fi
+ \setbox2\hbox{$\scriptstyle
+ \mkern\muskip4\relax
+ \mkern\muskip0\relax
+ #4\relax
+ \mkern\muskip2\relax
+ \mkern\muskip6\relax
+ $}%
+ \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
+ \setbox4\hbox to \dimen0{#3\displaystyle}%
+ \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits^{\box0}_{\box2}}
+ \endgroup}
+
+\let\domthxarrsingle\domthxarr
+
+%D There are some arrows which are created by stacking two arrows. The next
+%D macro helps in defining such \quotation{double arrows}.
+
+\def\domthxarrdouble#1#2#3#4#5#6#7% opt l r sp rs top bot
+ {\mathrel
+ {\scratchdimen.32ex\relax % was .22, todo: make configurable
+ \setbox0\hbox{$\domthxarr{#1}{#2}{#4}{\phantom{#6}}{#7}$}%
+ \setbox2\hbox{$\domthxarr{#1}{#3}{#5}{#6}{\phantom{#7}}$}%
+ \raise\scratchdimen\box0
+ \kern-\wd2
+ \lower\scratchdimen\box2}}
+
+%D \macros{definematharrow}
+%D
+%D Macro for defining new arrows. We can define two types of
+%D arrows|<|single arrows and double arrows. Single arrows are defined
+%D as
+%D
+%D \starttyping
+%D \definematharrow [xrightarrow] [0359] [\rightarrowfill]
+%D \stoptyping
+%D
+%D The first argument is the name of the arrow (\tex{xrightarrow} in
+%D this case.) The second argument consists of a set of 4 numbers and
+%D specify the spacing correction in math units~\type{mu}. These
+%D numbers define:
+%D
+%D \startlines
+%D 1st number: arrow||tip correction
+%D 2nd number: arrow||tip correction
+%D 3rd number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
+%D 4th number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
+%D \stoplines
+%D
+%D The third argument is the name of the extensible fill. The third
+%D argument is optional when the arrow is redefined later (this is
+%D useful for font specific tweaking of the skips.) For example,
+%D
+%D \startbuffer
+%D \math{\xrightarrow{above}}
+%D \definematharrow[xrightarrow][0000]
+%D \math{\xrightarrow{above}}
+%D \definematharrow[xrightarrow][55{50}{50}]
+%D \math{\xrightarrow{above}}
+%D \stopbuffer
+%D \typebuffer gives {\getbuffer}
+%D
+%D The double arrows are defined as follows
+%D
+%D \starttyping
+%D \definematharrow [xrightleftharpoons] [3095,0359]
+%D [\rightharpoonupfill,\leftharpoondownfill]
+%D \stoptyping
+%D
+%D The second and the third set of arguments consist of comma
+%D separated values. The first element of the second argument
+%D (\type{3095}) corresponds to the spacing correction of top arrow
+%D fill (\tex{rightarrowupfill}). Similarly, \type{0359} corresponds
+%D to bottom arrow fill \tex{leftharpoondownfill}). Stacking them on
+%D top of each other we get $\xrightleftharpoons[big]{above}{below}$.
+%D The following math arrows are defined
+%D
+%D \placetable[none]{}{\starttable[|l|m|]
+%D \NC \tex{xrightarrow } \NC \xrightarrow [big] \NC \NR
+%D \NC \tex{xleftarrow } \NC \xleftarrow [big] \NC \NR
+%D \NC \tex{xequal } \NC \xequal [big] \NC \NR
+%D \NC \tex{xRightarrow } \NC \xRightarrow [big] \NC \NR
+%D \NC \tex{xLeftarrow } \NC \xLeftarrow [big] \NC \NR
+%D \NC \tex{xLeftrightarrow } \NC \xLeftrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightarrow } \NC \xleftrightarrow [big] \NC \NR
+%D \NC \tex{xmapsto } \NC \xmapsto [big] \NC \NR
+%D \NC \tex{xtwoheadrightarrow } \NC \xtwoheadrightarrow [big] \NC \NR
+%D \NC \tex{xtwoheadleftarrow } \NC \xtwoheadleftarrow [big] \NC \NR
+%D \NC \tex{xrightharpoondown } \NC \xrightharpoondown [big] \NC \NR
+%D \NC \tex{xrightharpoonup } \NC \xrightharpoonup [big] \NC \NR
+%D \NC \tex{xleftharpoondown } \NC \xleftharpoondown [big] \NC \NR
+%D \NC \tex{xleftharpoonup } \NC \xleftharpoonup [big] \NC \NR
+%D \NC \tex{xhookleftarrow } \NC \xhookleftarrow [big] \NC \NR
+%D \NC \tex{xhookrightarrow } \NC \xhookrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightharpoons } \NC \xleftrightharpoons [big] \NC \NR
+%D \NC \tex{xrightleftharpoons } \NC \xrightleftharpoons [big] \NC \NR
+%D \stoptable}
+
+\def\definematharrow
+ {\doquadrupleargument\dodefinematharrow}
+
+\def\dodefinematharrow[#1][#2][#3][#4]% name type[none|both] template command
+ {\iffourthargument
+ \executeifdefined{dodefine#2arrow}\gobblethreearguments{#1}{#3}{#4}%
+ \else\ifthirdargument
+ \dodefinebotharrow{#1}{#2}{#3}%
+ \else\ifsecondargument
+ \redefinebotharrow{#1}{#2}{#3}%
+ \fi\fi\fi}
+
+\def\redefinebotharrow#1#2#3% real dirty, this overload!
+ {\doifdefined{#1}
+ {\pushmacro\dohandlemtharrow
+ \def\dohandlemtharrow[##1][##2]{\setvalue{#1}{\dohandlemtharrow[#2][##2]}}%
+ % == \def\dohandlemtharrow[##1][##2]{\dodefinebotharrow{#1}{#2}{##2}}%
+ \getvalue{#1}%
+ \popmacro\dohandlemtharrow}}
+
+\def\dodefinebotharrow#1#2#3%
+ {\setvalue{#1}{\dohandlemtharrow[#2][#3]}}
+
+\def\dohandlemtharrow
+ {\dotripleempty\doxmtharrow}
+
+\def\doxmtharrow[#1][#2][#3]% #3 == optional arg
+ {\def\dodoxmtharrow{\dododoxmtharrow[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2}
+ \dodoublegroupempty\dodoxmtharrow}
+
+\def\dododoxmtharrow[#1,#2,#3][#4,#5,#6][#7]#8#9% [3] is the optional arg
+ {\edef\!!stringa{#2}%
+ \ifx\!!stringa\empty
+ \ifsecondargument
+ \mathrel{\domthxarrsingle{#7}{#1}{#4}{#8}{#9}}%
+ \else
+ \mathrel{\domthxarrsingle{#7}{#1}{#4}{}{#8}}%
+ \fi
+ \else
+ \ifsecondargument
+ \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{#8}{#9}}%
+ \else
+ \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{}{#8}}%
+ \fi
+ \fi}
+
+% Adapted from amsmath.
+
+%D \macros{mtharrowfill,defaultmtharrowfill}
+%D
+%D To extend the arrows we need to define a \quotation{math arrow
+%D fill}. This command takes 8 arguments: the first four correspond
+%D the second argument of \tex{definematharrow} explained above. The
+%D other three specify the tail, body and head of the arrow. The last
+%D argument specifies the math-mode in which the arrow is drawn.
+%D \tex{defaultmtharrowfill} has values tweaked to match Latin Modern
+%D fonts. For fonts that are significantly different (e.g. cows) a
+%D different set of values need to be determined.
+
+\def\mtharrowfill#1#2#3#4#5#6#7#8%
+ {$\mathsurround 0pt
+ \thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
+ \relax#8#5%
+ \mkern-#1mu
+ \cleaders\hbox{$#8\mkern -#2mu#6\mkern -#3mu$}\hfill
+ \mkern-#4mu#7$}
+
+\def\defaultmtharrowfill{\mtharrowfill 7227}
+
+%D We now define some arrow fills that will be used for defining the
+%D arrows. Plain \TEX\ already defines \tex{leftarrowfill} and
+%D \tex{rightarrowfill}. The \tex{defaultmtharrowfill} command defines an
+%D arrowfill that takes an argument (so that it can also be used
+%D with over and under arrows). However the Plain \TEX\ definitions of
+%D \tex{leftarrowfill} and \tex{rightarrowfill} do not take this extra
+%D argument. To be backward compatible with Plain \TEX, we define two
+%D arrowfills: \tex{specrightarrowfill} which takes an extra argument, and
+%D \tex{rightarrowfill} which does not.
+
+\def\specrightarrowfill {\defaultmtharrowfill \relbar \relbar \rightarrow}
+\def\specleftarrowfill {\defaultmtharrowfill \leftarrow \relbar \relbar}
+
+\def\rightarrowfill {\specrightarrowfill \textstyle}
+\def\leftarrowfill {\specleftarrowfill \textstyle}
+
+\def\equalfill {\defaultmtharrowfill \Relbar \Relbar \Relbar}
+\def\Rightarrowfill {\defaultmtharrowfill \Relbar \Relbar \Rightarrow}
+\def\Leftarrowfill {\defaultmtharrowfill \Leftarrow \Relbar \Relbar}
+\def\Leftrightarrowfill {\defaultmtharrowfill \Leftarrow \Relbar \Rightarrow}
+\def\leftrightarrowfill {\defaultmtharrowfill \leftarrow \relbar \rightarrow}
+\def\mapstofill {\defaultmtharrowfill{\mapstochar\relbar} \relbar \rightarrow}
+\def\twoheadrightarrowfill{\defaultmtharrowfill \relbar \relbar \twoheadrightarrow}
+\def\twoheadleftarrowfill {\defaultmtharrowfill \twoheadleftarrow \relbar \relbar}
+\def\rightharpoondownfill {\defaultmtharrowfill \relbar \relbar \rightharpoondown}
+\def\rightharpoonupfill {\defaultmtharrowfill \relbar \relbar \rightharpoonup}
+\def\leftharpoondownfill {\defaultmtharrowfill \leftharpoondown \relbar \relbar}
+\def\leftharpoonupfill {\defaultmtharrowfill \leftharpoonup \relbar \relbar}
+\def\hookleftfill {\defaultmtharrowfill \leftarrow \relbar{\relbar\joinrel\rhook}}
+\def\hookrightfill {\defaultmtharrowfill{\lhook\joinrel\relbar}\relbar \rightarrow}
+\def\relfill {\defaultmtharrowfill \relbar \relbar \relbar}
+
+\def\triplerelbar {\mathrel\equiv}
+\def\triplerelfill{\defaultmtharrowfill\triplerelbar\triplerelbar\triplerelbar}
+
+\def\singlebond{{\xrel}} % or \def\singlebond{{\xrel[2]}}
+\def\doublebond{{\xequal}}
+\def\triplebond{{\xtriplerel}}
+
+%D Now we define most commonly used arrows. These include arrows
+%D defined in \filename{amsmath.sty}, \filename{extarrows.sty},
+%D \filename{extpfel.sty} and \filename{mathtools.sty} packages for
+%D \LATEX\ (plus a few more).
+
+\definematharrow [xrightarrow] [0359] [\specrightarrowfill]
+\definematharrow [xleftarrow] [3095] [\specleftarrowfill]
+\definematharrow [xequal] [0099] [\equalfill]
+\definematharrow [xRightarrow] [0359] [\Rightarrowfill]
+\definematharrow [xLeftarrow] [3095] [\Leftarrowfill]
+\definematharrow [xLeftrightarrow] [0099] [\Leftrightarrowfill]
+\definematharrow [xleftrightarrow] [0099] [\leftrightarrowfill]
+\definematharrow [xmapsto] [3599] [\mapstofill]
+\definematharrow [xtwoheadrightarrow] [5009] [\twoheadrightarrowfill]
+\definematharrow [xtwoheadleftarrow] [0590] [\twoheadleftarrowfill]
+\definematharrow [xrightharpoondown] [0359] [\rightharpoondownfill]
+\definematharrow [xrightharpoonup] [0359] [\rightharpoonupfill]
+\definematharrow [xleftharpoondown] [3095] [\leftharpoondownfill]
+\definematharrow [xleftharpoonup] [3095] [\leftharpoonupfill]
+\definematharrow [xhookleftarrow] [3095] [\hookleftfill]
+\definematharrow [xhookrightarrow] [0395] [\hookrightfill]
+\definematharrow [xrel] [0099] [\relfill]
+\definematharrow [xtriplerel] [0099] [\triplerelfill]
+\definematharrow [xrightoverleftarrow] [0359,3095] [\specrightarrowfill,\specleftarrowfill]
+\definematharrow [xleftrightharpoons] [3399,3399] [\leftharpoonupfill,\rightharpoondownfill]
+\definematharrow [xrightleftharpoons] [3399,3399] [\rightharpoonupfill,\leftharpoondownfill]
+
+%D These arrows can be used as follows:
+%D
+%D \startbuffer
+%D \startformula \xrightarrow{stuff on top}\stopformula
+%D \startformula \xrightarrow{}{stuff on top}\stopformula
+%D \startformula \xrightarrow{stuff below}{}\stopformula
+%D \startformula \xrightarrow{stuff below}{stuff on top}\stopformula
+%D
+%D \startformula \xleftarrow [none]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [small]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [medium]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [big]{stuff below}{stuff on top}\stopformula
+%D \stopbuffer
+%D
+%D \typebuffer which gives \getbuffer
+
+%D \macros{definemathoverarrow,defineunderarrow}
+%D
+%D These macros for define math-overarrows are adapted from
+%D \filename{amsmath.sty}
+
+\def\definemathoverarrow
+ {\dotripleargument\dodefinemathoverarrow}
+
+\def\dodefinemathoverarrow[#1][#2][#3]%
+ {\ifthirdargument
+ \setvalue{#1}{\dohandlemathoverarrow[#2][#3]}%
+ \else
+ \setvalue{#1}{\dohandlemathoverarrow[\zeropoint][#2]}%
+ \fi}
+
+\def\dohandlemathoverarrow[#1][#2]%
+ {\mathpalette{\dodohandlemathoverarrow{#1}{#2}}}
+
+%D Note: \filename{math-pln.tex} has \type{\kern-\onepoint} and
+%D \filename{amsmath.sty} does not. We keep the kern amount
+%D configurable. This is useful for harpoons.
+
+\def\dodohandlemathoverarrow#1#2#3#4%
+ {\vbox{\ialign{##\crcr
+ #2#3\crcr
+ \noalign{\kern#1\nointerlineskip}%
+ $\mathsurround\zeropoint\hfil#3#4\hfil$\crcr}}}
+
+%D Now the under arrows
+
+\def\definemathunderarrow
+ {\dotripleargument\dodefinemathunderarrow}
+
+%D For underarrows the default kern is 0.3ex
+
+\def\dodefinemathunderarrow[#1][#2][#3]%
+ {\ifthirdargument
+ \setvalue{#1}{\dohandlemathunderarrow[#2][#3]}%
+ \else
+ \setvalue{#1}{\dohandlemathunderarrow[0.3ex][#2]}%
+ \fi}
+
+\def\dohandlemathunderarrow[#1][#2]%
+ {\mathpalette{\dodohandlemathunderarrow{#1}{#2}}}
+
+\def\dodohandlemathunderarrow#1#2#3#4%
+ {\vtop{\ialign{##\crcr
+ $\mathsurround\zeropoint\hfil#3#4\hfil$\crcr
+ \noalign{\nointerlineskip\kern#1}%
+ #2#3\crcr}}}
+
+%D Now we define the arrows
+
+\definemathoverarrow [overleftarrow] [\specleftarrowfill]
+\definemathoverarrow [overrightarrow] [\specrightarrowfill]
+\definemathoverarrow [overleftrightarrow] [\leftrightarrowfill]
+\definemathoverarrow [overtwoheadrightarrow] [\twoheadrightarrowfill]
+\definemathoverarrow [overtwoheadleftarrow] [\twoheadleftarrowfill]
+\definemathoverarrow [overrightharpoondown] [1pt] [\rightharpoondownfill]
+\definemathoverarrow [overrightharpoonup] [\rightharpoonupfill]
+\definemathoverarrow [overleftharpoondown] [1pt] [\leftharpoondownfill]
+\definemathoverarrow [overleftharpoonup] [\leftharpoonupfill]
+
+\definemathunderarrow [underleftarrow] [\specleftarrowfill]
+\definemathunderarrow [underrightarrow] [\specrightarrowfill]
+\definemathunderarrow [underleftrightarrow] [\leftrightarrowfill]
+\definemathunderarrow [undertwoheadrightarrow][\twoheadrightarrowfill]
+\definemathunderarrow [undertwoheadleftarrow] [\twoheadleftarrowfill]
+\definemathunderarrow [underrightharpoondown] [\rightharpoondownfill]
+\definemathunderarrow [underrightharpoonup] [\rightharpoonupfill]
+\definemathunderarrow [underleftharpoondown] [\leftharpoondownfill]
+\definemathunderarrow [underleftharpoonup] [\leftharpoonupfill]
+
+%D These can be used as follows:
+%D
+%D \startbuffer
+%D $\overleftarrow{A}$ $\overleftarrow{ABC}$
+%D $a_{\overleftarrow{A}}$ $b_{\overleftarrow{ABC}}$
+%D \stopbuffer
+%D \typebuffer which gives \getbuffer
+
+%D TODO: Possibly have a single arrow command define all the arrows.
+
+\protect \endinput
diff --git a/tex/context/base/math-arr.mkiv b/tex/context/base/math-arr.mkiv
new file mode 100644
index 000000000..389112b16
--- /dev/null
+++ b/tex/context/base/math-arr.mkiv
@@ -0,0 +1,439 @@
+%D \module
+%D [ file=math-arr,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Arrows,
+%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Arrows}
+
+\unprotect
+
+%D These will be generalized! Is it still needed in \MKIV?
+
+\def\exmthfont#1{\symbolicsizedfont#1\plusone{MathExtension}}
+
+\def\domthfrac#1#2#3#4#5#6#7%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox0\hbox{$#1 #6$}%
+ \setbox2\hbox{$#1 #7$}%
+ \dimen0\wd0
+ \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
+ \setbox4\hbox to \dimen0{\exmthfont#2#3\leaders\hbox{#4}\hss#5}%
+ \mathord{\vcenter{{\offinterlineskip
+ \hbox to \dimen0{\hss\box0\hss}%
+ \kern \ht4%
+ \hbox to \dimen0{\hss\copy4\hss}%
+ \kern \ht4%
+ \hbox to \dimen0{\hss\box2\hss}}}}%
+ \endgroup}
+
+\def\domthsqrt#1#2#3#4#5%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox0\hbox{$#1 #5$}%
+ \dimen0=1.05\ht0 \advance\dimen0 1pt \ht0 \dimen0
+ \dimen0=1.05\dp0 \advance\dimen0 1pt \dp0 \dimen0
+ \dimen0\wd0
+ \setbox4\hbox to \dimen0{\exmthfont#2\leaders\hbox{#3}\hfill#4}%
+ \delimitershortfall=0pt
+ \nulldelimiterspace=0pt
+ \setbox2\hbox{$\left\delimiter"0270370 \vrule height\ht0 depth \dp0 width0pt
+ \right.$}%
+ \mathord{\vcenter{\hbox{\copy2
+ \rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
+ \endgroup}
+
+\def\mthfrac#1#2#3#4#5{\mathchoice
+ {\domthfrac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}
+
+\def\mthsqrt#1#2#3{\mathchoice
+ {\domthsqrt\displaystyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\textstyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\scriptstyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\scriptscriptstyle\textface {#1}{#2}{#3}}}
+
+% temp here
+
+%D We next define extensible arrows. Extensible arrows are arrows that
+%D change their length according to the width of the text to be placed
+%D above and below the arrow. Since we need to define a lot of arrows,
+%D we first define some helper macros. The basic idea is to measure
+%D the width of the box to be placed above and below the arrow, and
+%D make the \quotation{body} of the arrow as long as the bigger of the
+%D two widths.
+
+\def\mtharrfactor{1}
+\def\mtharrextra {0}
+
+\def\domthxarr#1#2#3#4#5% hm, looks like we do a double mathrel
+ {\begingroup
+ \def\mtharrfactor{1}%
+ \def\mtharrextra {0}%
+ \processaction[#1] % will be sped up
+ [ \v!none=>\def\mtharrfactor{0},
+ \v!small=>\def\mtharrextra{10},
+ \v!medium=>\def\mtharrextra{15},
+ \v!big=>\def\mtharrextra{20},
+ \v!normal=>,
+ \v!default=>,
+ \v!unknown=>\doifnumberelse{#1}{\def\mtharrextra{#1}}\donothing]%
+ \mathsurround\zeropoint
+ \muskip0=\thirdoffourarguments #2mu
+ \muskip2=\fourthoffourarguments #2mu
+ \muskip4=\firstoffourarguments #2mu
+ \muskip6=\secondoffourarguments #2mu
+ \muskip0=\mtharrfactor\muskip0 \advance\muskip0 \mtharrextra mu
+ \muskip2=\mtharrfactor\muskip2 \advance\muskip2 \mtharrextra mu
+ \setbox0\hbox{$\scriptstyle
+ \mkern\muskip4\relax
+ \mkern\muskip0\relax
+ #5\relax
+ \mkern\muskip2\relax
+ \mkern\muskip6\relax
+ $}%
+ \setbox4\hbox{#3\displaystyle}%
+ \dimen0\wd0
+ \ifdim\wd4>\dimen0 \dimen0\wd4 \fi
+ \setbox2\hbox{$\scriptstyle
+ \mkern\muskip4\relax
+ \mkern\muskip0\relax
+ #4\relax
+ \mkern\muskip2\relax
+ \mkern\muskip6\relax
+ $}%
+ \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
+ \setbox4\hbox to \dimen0{#3\displaystyle}%
+ \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits^{\box0}_{\box2}}
+ \endgroup}
+
+\let\domthxarrsingle\domthxarr
+
+%D There are some arrows which are created by stacking two arrows. The next
+%D macro helps in defining such \quotation{double arrows}.
+
+\def\domthxarrdouble#1#2#3#4#5#6#7% opt l r sp rs top bot
+ {\mathrel
+ {\scratchdimen.32ex\relax % was .22, todo: make configurable
+ \setbox0\hbox{$\domthxarr{#1}{#2}{#4}{\phantom{#6}}{#7}$}%
+ \setbox2\hbox{$\domthxarr{#1}{#3}{#5}{#6}{\phantom{#7}}$}%
+ \raise\scratchdimen\box0
+ \kern-\wd2
+ \lower\scratchdimen\box2}}
+
+%D \macros{definematharrow}
+%D
+%D Macro for defining new arrows. We can define two types of
+%D arrows|<|single arrows and double arrows. Single arrows are defined
+%D as
+%D
+%D \starttyping
+%D \definematharrow [xrightarrow] [0359] [\rightarrowfill]
+%D \stoptyping
+%D
+%D The first argument is the name of the arrow (\tex{xrightarrow} in
+%D this case.) The second argument consists of a set of 4 numbers and
+%D specify the spacing correction in math units~\type{mu}. These
+%D numbers define:
+%D
+%D \startlines
+%D 1st number: arrow||tip correction
+%D 2nd number: arrow||tip correction
+%D 3rd number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
+%D 4th number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
+%D \stoplines
+%D
+%D The third argument is the name of the extensible fill. The third
+%D argument is optional when the arrow is redefined later (this is
+%D useful for font specific tweaking of the skips.) For example,
+%D
+%D \startbuffer
+%D \math{\xrightarrow{above}}
+%D \definematharrow[xrightarrow][0000]
+%D \math{\xrightarrow{above}}
+%D \definematharrow[xrightarrow][55{50}{50}]
+%D \math{\xrightarrow{above}}
+%D \stopbuffer
+%D \typebuffer gives {\getbuffer}
+%D
+%D The double arrows are defined as follows
+%D
+%D \starttyping
+%D \definematharrow [xrightleftharpoons] [3095,0359]
+%D [\rightharpoonupfill,\leftharpoondownfill]
+%D \stoptyping
+%D
+%D The second and the third set of arguments consist of comma
+%D separated values. The first element of the second argument
+%D (\type{3095}) corresponds to the spacing correction of top arrow
+%D fill (\tex{rightarrowupfill}). Similarly, \type{0359} corresponds
+%D to bottom arrow fill \tex{leftharpoondownfill}). Stacking them on
+%D top of each other we get $\xrightleftharpoons[big]{above}{below}$.
+%D The following math arrows are defined
+%D
+%D \placetable[none]{}{\starttable[|l|m|]
+%D \NC \tex{xrightarrow } \NC \xrightarrow [big] \NC \NR
+%D \NC \tex{xleftarrow } \NC \xleftarrow [big] \NC \NR
+%D \NC \tex{xequal } \NC \xequal [big] \NC \NR
+%D \NC \tex{xRightarrow } \NC \xRightarrow [big] \NC \NR
+%D \NC \tex{xLeftarrow } \NC \xLeftarrow [big] \NC \NR
+%D \NC \tex{xLeftrightarrow } \NC \xLeftrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightarrow } \NC \xleftrightarrow [big] \NC \NR
+%D \NC \tex{xmapsto } \NC \xmapsto [big] \NC \NR
+%D \NC \tex{xtwoheadrightarrow } \NC \xtwoheadrightarrow [big] \NC \NR
+%D \NC \tex{xtwoheadleftarrow } \NC \xtwoheadleftarrow [big] \NC \NR
+%D \NC \tex{xrightharpoondown } \NC \xrightharpoondown [big] \NC \NR
+%D \NC \tex{xrightharpoonup } \NC \xrightharpoonup [big] \NC \NR
+%D \NC \tex{xleftharpoondown } \NC \xleftharpoondown [big] \NC \NR
+%D \NC \tex{xleftharpoonup } \NC \xleftharpoonup [big] \NC \NR
+%D \NC \tex{xhookleftarrow } \NC \xhookleftarrow [big] \NC \NR
+%D \NC \tex{xhookrightarrow } \NC \xhookrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightharpoons } \NC \xleftrightharpoons [big] \NC \NR
+%D \NC \tex{xrightleftharpoons } \NC \xrightleftharpoons [big] \NC \NR
+%D \stoptable}
+
+\unexpanded\def\definematharrow
+ {\doquadrupleargument\dodefinematharrow}
+
+\def\dodefinematharrow[#1][#2][#3][#4]% name type[none|both] template command
+ {\iffourthargument
+ \executeifdefined{dodefine#2arrow}\gobblethreearguments{#1}{#3}{#4}%
+ \else\ifthirdargument
+ \dodefinebotharrow{#1}{#2}{#3}%
+ \else\ifsecondargument
+ \redefinebotharrow{#1}{#2}{#3}%
+ \fi\fi\fi}
+
+\def\redefinebotharrow#1#2#3% real dirty, this overload!
+ {\doifdefined{#1}
+ {\pushmacro\dohandlemtharrow
+ \def\dohandlemtharrow[##1][##2]{\setuvalue{#1}{\dohandlemtharrow[#2][##2]}}%
+ % == \def\dohandlemtharrow[##1][##2]{\dodefinebotharrow{#1}{#2}{##2}}%
+ \getvalue{#1}%
+ \popmacro\dohandlemtharrow}}
+
+\def\dodefinebotharrow#1#2#3%
+ {\setuvalue{#1}{\dohandlemtharrow[#2][#3]}}
+
+\def\dohandlemtharrow
+ {\dotripleempty\doxmtharrow}
+
+\def\doxmtharrow[#1][#2][#3]% #3 == optional arg
+ {\def\dodoxmtharrow{\dododoxmtharrow[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2}
+ \dodoublegroupempty\dodoxmtharrow}
+
+\def\dododoxmtharrow[#1,#2,#3][#4,#5,#6][#7]#8#9% [3] is the optional arg
+ {\edef\!!stringa{#2}%
+ \ifx\!!stringa\empty
+ \ifsecondargument
+ \mathrel{\domthxarrsingle{#7}{#1}{#4}{#8}{#9}}%
+ \else
+ \mathrel{\domthxarrsingle{#7}{#1}{#4}{}{#8}}%
+ \fi
+ \else
+ \ifsecondargument
+ \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{#8}{#9}}%
+ \else
+ \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{}{#8}}%
+ \fi
+ \fi}
+
+% Adapted from amsmath.
+
+%D \macros{mtharrowfill,defaultmtharrowfill}
+%D
+%D To extend the arrows we need to define a \quotation{math arrow
+%D fill}. This command takes 8 arguments: the first four correspond
+%D the second argument of \tex{definematharrow} explained above. The
+%D other three specify the tail, body and head of the arrow. The last
+%D argument specifies the math-mode in which the arrow is drawn.
+%D \tex{defaultmtharrowfill} has values tweaked to match Latin Modern
+%D fonts. For fonts that are significantly different (e.g. cows) a
+%D different set of values need to be determined.
+
+\def\mtharrowfill#1#2#3#4#5#6#7#8%
+ {$\mathsurround 0pt
+ \thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
+ \relax#8#5%
+ \mkern-#1mu
+ \cleaders\hbox{$#8\mkern -#2mu#6\mkern -#3mu$}\hfill
+ \mkern-#4mu#7$}
+
+\def\defaultmtharrowfill{\mtharrowfill 7227}
+
+%D We now define some arrow fills that will be used for defining the
+%D arrows. Plain \TEX\ already defines \tex{leftarrowfill} and
+%D \tex{rightarrowfill}. The \tex{defaultmtharrowfill} command defines an
+%D arrowfill that takes an argument (so that it can also be used
+%D with over and under arrows). However the Plain \TEX\ definitions of
+%D \tex{leftarrowfill} and \tex{rightarrowfill} do not take this extra
+%D argument. To be backward compatible with Plain \TEX, we define two
+%D arrowfills: \tex{specrightarrowfill} which takes an extra argument, and
+%D \tex{rightarrowfill} which does not.
+
+\unexpanded\def\specrightarrowfill {\defaultmtharrowfill \relbar \relbar \rightarrow}
+\unexpanded\def\specleftarrowfill {\defaultmtharrowfill \leftarrow \relbar \relbar}
+
+\unexpanded\def\rightarrowfill {\specrightarrowfill \textstyle}
+\unexpanded\def\leftarrowfill {\specleftarrowfill \textstyle}
+
+\unexpanded\def\equalfill {\defaultmtharrowfill \Relbar \Relbar \Relbar}
+\unexpanded\def\Rightarrowfill {\defaultmtharrowfill \Relbar \Relbar \Rightarrow}
+\unexpanded\def\Leftarrowfill {\defaultmtharrowfill \Leftarrow \Relbar \Relbar}
+\unexpanded\def\Leftrightarrowfill {\defaultmtharrowfill \Leftarrow \Relbar \Rightarrow}
+\unexpanded\def\leftrightarrowfill {\defaultmtharrowfill \leftarrow \relbar \rightarrow}
+\unexpanded\def\mapstofill {\defaultmtharrowfill{\mapstochar\relbar} \relbar \rightarrow}
+\unexpanded\def\twoheadrightarrowfill{\defaultmtharrowfill \relbar \relbar \twoheadrightarrow}
+\unexpanded\def\twoheadleftarrowfill {\defaultmtharrowfill \twoheadleftarrow \relbar \relbar}
+\unexpanded\def\rightharpoondownfill {\defaultmtharrowfill \relbar \relbar \rightharpoondown}
+\unexpanded\def\rightharpoonupfill {\defaultmtharrowfill \relbar \relbar \rightharpoonup}
+\unexpanded\def\leftharpoondownfill {\defaultmtharrowfill \leftharpoondown \relbar \relbar}
+\unexpanded\def\leftharpoonupfill {\defaultmtharrowfill \leftharpoonup \relbar \relbar}
+\unexpanded\def\hookleftfill {\defaultmtharrowfill \leftarrow \relbar{\relbar\joinrel\rhook}}
+\unexpanded\def\hookrightfill {\defaultmtharrowfill{\lhook\joinrel\relbar}\relbar \rightarrow}
+\unexpanded\def\relfill {\defaultmtharrowfill \relbar \relbar \relbar}
+
+\unexpanded\def\triplerelbar {\mathrel\equiv}
+\unexpanded\def\triplerelfill{\defaultmtharrowfill\triplerelbar\triplerelbar\triplerelbar}
+
+\unexpanded\def\singlebond{{\xrel}} % or \def\singlebond{{\xrel[2]}}
+\unexpanded\def\doublebond{{\xequal}}
+\unexpanded\def\triplebond{{\xtriplerel}}
+
+%D Now we define most commonly used arrows. These include arrows
+%D defined in \filename{amsmath.sty}, \filename{extarrows.sty},
+%D \filename{extpfel.sty} and \filename{mathtools.sty} packages for
+%D \LATEX\ (plus a few more).
+
+\definematharrow [xrightarrow] [0359] [\specrightarrowfill]
+\definematharrow [xleftarrow] [3095] [\specleftarrowfill]
+\definematharrow [xequal] [0099] [\equalfill]
+\definematharrow [xRightarrow] [0359] [\Rightarrowfill]
+\definematharrow [xLeftarrow] [3095] [\Leftarrowfill]
+\definematharrow [xLeftrightarrow] [0099] [\Leftrightarrowfill]
+\definematharrow [xleftrightarrow] [0099] [\leftrightarrowfill]
+\definematharrow [xmapsto] [3599] [\mapstofill]
+\definematharrow [xtwoheadrightarrow] [5009] [\twoheadrightarrowfill]
+\definematharrow [xtwoheadleftarrow] [0590] [\twoheadleftarrowfill]
+\definematharrow [xrightharpoondown] [0359] [\rightharpoondownfill]
+\definematharrow [xrightharpoonup] [0359] [\rightharpoonupfill]
+\definematharrow [xleftharpoondown] [3095] [\leftharpoondownfill]
+\definematharrow [xleftharpoonup] [3095] [\leftharpoonupfill]
+\definematharrow [xhookleftarrow] [3095] [\hookleftfill]
+\definematharrow [xhookrightarrow] [0395] [\hookrightfill]
+\definematharrow [xrel] [0099] [\relfill]
+\definematharrow [xtriplerel] [0099] [\triplerelfill]
+\definematharrow [xrightoverleftarrow] [0359,3095] [\specrightarrowfill,\specleftarrowfill]
+\definematharrow [xleftrightharpoons] [3399,3399] [\leftharpoonupfill,\rightharpoondownfill]
+\definematharrow [xrightleftharpoons] [3399,3399] [\rightharpoonupfill,\leftharpoondownfill]
+
+%D These arrows can be used as follows:
+%D
+%D \startbuffer
+%D \startformula \xrightarrow{stuff on top}\stopformula
+%D \startformula \xrightarrow{}{stuff on top}\stopformula
+%D \startformula \xrightarrow{stuff below}{}\stopformula
+%D \startformula \xrightarrow{stuff below}{stuff on top}\stopformula
+%D
+%D \startformula \xleftarrow [none]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [small]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [medium]{stuff below}{stuff on top}\stopformula
+%D \startformula \xleftarrow [big]{stuff below}{stuff on top}\stopformula
+%D \stopbuffer
+%D
+%D \typebuffer which gives \getbuffer
+
+%D \macros{definemathoverarrow,defineunderarrow}
+%D
+%D These macros for define math-overarrows are adapted from
+%D \filename{amsmath.sty}
+
+\unexpanded\def\definemathoverarrow
+ {\dotripleargument\dodefinemathoverarrow}
+
+\def\dodefinemathoverarrow[#1][#2][#3]%
+ {\ifthirdargument
+ \setuvalue{#1}{\dohandlemathoverarrow[#2][#3]}%
+ \else
+ \setuvalue{#1}{\dohandlemathoverarrow[\zeropoint][#2]}%
+ \fi}
+
+\def\dohandlemathoverarrow[#1][#2]%
+ {\mathpalette{\dodohandlemathoverarrow{#1}{#2}}}
+
+%D Note: \filename{math-pln.tex} has \type{\kern-\onepoint} and
+%D \filename{amsmath.sty} does not. We keep the kern amount
+%D configurable. This is useful for harpoons.
+
+\def\dodohandlemathoverarrow#1#2#3#4%
+ {\vbox{\ialign{##\crcr
+ #2#3\crcr
+ \noalign{\kern#1\nointerlineskip}%
+ $\mathsurround\zeropoint\hfil#3#4\hfil$\crcr}}}
+
+%D Now the under arrows
+
+\unexpanded\def\definemathunderarrow
+ {\dotripleargument\dodefinemathunderarrow}
+
+%D For underarrows the default kern is 0.3ex
+
+\def\dodefinemathunderarrow[#1][#2][#3]%
+ {\ifthirdargument
+ \setuvalue{#1}{\dohandlemathunderarrow[#2][#3]}%
+ \else
+ \setuvalue{#1}{\dohandlemathunderarrow[0.3ex][#2]}%
+ \fi}
+
+\def\dohandlemathunderarrow[#1][#2]%
+ {\mathpalette{\dodohandlemathunderarrow{#1}{#2}}}
+
+\def\dodohandlemathunderarrow#1#2#3#4%
+ {\vtop{\ialign{##\crcr
+ $\mathsurround\zeropoint\hfil#3#4\hfil$\crcr
+ \noalign{\nointerlineskip\kern#1}%
+ #2#3\crcr}}}
+
+%D Now we define the arrows
+
+\definemathoverarrow [overleftarrow] [\specleftarrowfill]
+\definemathoverarrow [overrightarrow] [\specrightarrowfill]
+\definemathoverarrow [overleftrightarrow] [\leftrightarrowfill]
+\definemathoverarrow [overtwoheadrightarrow] [\twoheadrightarrowfill]
+\definemathoverarrow [overtwoheadleftarrow] [\twoheadleftarrowfill]
+\definemathoverarrow [overrightharpoondown] [1pt] [\rightharpoondownfill]
+\definemathoverarrow [overrightharpoonup] [\rightharpoonupfill]
+\definemathoverarrow [overleftharpoondown] [1pt] [\leftharpoondownfill]
+\definemathoverarrow [overleftharpoonup] [\leftharpoonupfill]
+
+\definemathunderarrow [underleftarrow] [\specleftarrowfill]
+\definemathunderarrow [underrightarrow] [\specrightarrowfill]
+\definemathunderarrow [underleftrightarrow] [\leftrightarrowfill]
+\definemathunderarrow [undertwoheadrightarrow][\twoheadrightarrowfill]
+\definemathunderarrow [undertwoheadleftarrow] [\twoheadleftarrowfill]
+\definemathunderarrow [underrightharpoondown] [\rightharpoondownfill]
+\definemathunderarrow [underrightharpoonup] [\rightharpoonupfill]
+\definemathunderarrow [underleftharpoondown] [\leftharpoondownfill]
+\definemathunderarrow [underleftharpoonup] [\leftharpoonupfill]
+
+%D These can be used as follows:
+%D
+%D \startbuffer
+%D $\overleftarrow{A}$ $\overleftarrow{ABC}$
+%D $a_{\overleftarrow{A}}$ $b_{\overleftarrow{ABC}}$
+%D \stopbuffer
+%D \typebuffer which gives \getbuffer
+
+%D TODO: Possibly have a single arrow command define all the arrows.
+
+\protect \endinput
diff --git a/tex/context/base/math-cow.mkii b/tex/context/base/math-cow.mkii
new file mode 100644
index 000000000..f0fc811c8
--- /dev/null
+++ b/tex/context/base/math-cow.mkii
@@ -0,0 +1,31 @@
+%D \module
+%D [ file=math-cow,
+%D version=2006.06.23,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Cow Math,
+%D author={Hans Hagen \& Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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
+
+\def\COWsqrt {\mthsqrt{\char"7A}{\char"7B}}
+\def\COWfrac {\mthfrac{\char"7C}{\char"7A}{\char"7B}}
+\def\COWarrowfill{\mtharrowfill 1001}
+
+\startmathcollection [cow]
+ % todo
+\stopmathcollection
+
+\startrawmathcollection[cow]
+ \definemathcommand [frac] {\COWfrac}
+ \definemathcommand [sqrt] {\COWsqrt}
+ %definemathcommand [r@@t] {\COWroot}
+ %definemathcommand [matrix] {\COWmatrix}
+\stoprawmathcollection
+
+\protect \endinput
diff --git a/tex/context/base/math-def.mkiv b/tex/context/base/math-def.mkiv
new file mode 100644
index 000000000..50c9902dd
--- /dev/null
+++ b/tex/context/base/math-def.mkiv
@@ -0,0 +1,374 @@
+%D \module
+%D [ file=math-tex,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Definitions,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Definitions}
+
+\unprotect
+
+\ifx\mrfam\undefined \chardef\mrfam\plusone \fi
+
+\startluacode
+ mathematics.define()
+ mathematics.register_xml_entities()
+\stopluacode
+
+% special .. todo
+
+\mathcode`\ ="8000 \mathcode`\_="8000 \mathcode`\'="8000
+
+% will be attributes
+
+\setfalse \automathpunctuation
+
+\def\enablemathpunctuation {\settrue \automathpunctuation}
+\def\disablemathpunctuation{\setfalse\automathpunctuation}
+
+\def\v!autopunctuation{autopunctuation}
+
+\appendtoks
+ \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\enablemathpunctuation\disablemathpunctuation
+\to \everysetupmathematics
+
+% \appendtoks
+% \ifconditional\automathpunctuation\attribute\mathpunctuationattribute\plusone\fi
+% \to \everymathematics
+
+\setupmathematics[\v!autopunctuation=\v!yes]
+
+% will go to math-ext
+
+\Umathchardef\braceld=0 \mrfam "FF07A
+\Umathchardef\bracerd=0 \mrfam "FF07B
+\Umathchardef\bracelu=0 \mrfam "FF07C
+\Umathchardef\braceru=0 \mrfam "FF07D
+
+% ctx specific
+
+\def\|{|} % still letter
+
+% The \mfunction macro is an alternative for \hbox with a
+% controlable font switch.
+
+\definemathcommand [arccos] [nolop] {\mfunctionlabeltext{arccos}}
+\definemathcommand [arcsin] [nolop] {\mfunctionlabeltext{arcsin}}
+\definemathcommand [arctan] [nolop] {\mfunctionlabeltext{arctan}}
+\definemathcommand [arg] [nolop] {\mfunctionlabeltext{arg}}
+\definemathcommand [cosh] [nolop] {\mfunctionlabeltext{cosh}}
+\definemathcommand [cos] [nolop] {\mfunctionlabeltext{cos}}
+\definemathcommand [coth] [nolop] {\mfunctionlabeltext{coth}}
+\definemathcommand [cot] [nolop] {\mfunctionlabeltext{cot}}
+\definemathcommand [csc] [nolop] {\mfunctionlabeltext{csc}}
+\definemathcommand [deg] [nolop] {\mfunctionlabeltext{deg}}
+\definemathcommand [det] [limop] {\mfunctionlabeltext{det}}
+\definemathcommand [dim] [nolop] {\mfunctionlabeltext{dim}}
+\definemathcommand [exp] [nolop] {\mfunctionlabeltext{exp}}
+\definemathcommand [gcd] [limop] {\mfunctionlabeltext{gcd}}
+\definemathcommand [hom] [nolop] {\mfunctionlabeltext{hom}}
+\definemathcommand [inf] [limop] {\mfunctionlabeltext{inf}}
+\definemathcommand [injlim] [limop] {\mfunctionlabeltext{injlim}}
+\definemathcommand [ker] [nolop] {\mfunctionlabeltext{ker}}
+\definemathcommand [lg] [nolop] {\mfunctionlabeltext{lg}}
+\definemathcommand [liminf] [limop] {\mfunctionlabeltext{liminf}}
+\definemathcommand [limsup] [limop] {\mfunctionlabeltext{limsup}}
+\definemathcommand [lim] [limop] {\mfunctionlabeltext{lim}}
+\definemathcommand [ln] [nolop] {\mfunctionlabeltext{ln}}
+\definemathcommand [log] [nolop] {\mfunctionlabeltext{log}}
+\definemathcommand [median] [limop] {\mfunctionlabeltext{median}}
+\definemathcommand [max] [limop] {\mfunctionlabeltext{max}}
+\definemathcommand [min] [limop] {\mfunctionlabeltext{min}}
+\definemathcommand [mod] [limop] {\mfunctionlabeltext{mod}}
+%definemathcommand [div] [limop] {\mfunctionlabeltext{div}} % overloads \div symbol
+\definemathcommand [projlim] [limop] {\mfunctionlabeltext{projlim}}
+\definemathcommand [Pr] [limop] {\mfunctionlabeltext{Pr}}
+\definemathcommand [sec] [nolop] {\mfunctionlabeltext{sec}}
+\definemathcommand [sinh] [nolop] {\mfunctionlabeltext{sinh}}
+\definemathcommand [sin] [nolop] {\mfunctionlabeltext{sin}}
+\definemathcommand [sup] [limop] {\mfunctionlabeltext{sup}}
+\definemathcommand [tanh] [nolop] {\mfunctionlabeltext{tanh}}
+\definemathcommand [tan] [nolop] {\mfunctionlabeltext{tan}}
+
+\definemathcommand [integers] {{\mathblackboard Z}}
+\definemathcommand [reals] {{\mathblackboard R}}
+\definemathcommand [rationals] {{\mathblackboard Q}}
+\definemathcommand [naturalnumbers]{{\mathblackboard N}}
+\definemathcommand [complexes] {{\mathblackboard C}}
+\definemathcommand [primes] {{\mathblackboard P}}
+
+\let\normalmatharg\arg % todo: maybe automatically
+
+% using attributes
+
+\chardef\bigmathdelimitermethod\plusone
+
+\def\plainbigdelimiters % traditional method
+ {\chardef\bigmathdelimitermethod\plustwo}
+
+\def\doplainbigmath#1#2%
+ {{\hbox{$%
+ \nulldelimiterspace\zeropoint\relax
+ \mathsurround\zeropoint
+ $}}}
+
+\def\doleftbigmath #1{\ifx#1\relax\else\left#1\expandafter\doleftbigmath \fi}
+\def\dorightbigmath#1{\ifx#1\relax\else\right.\expandafter\dorightbigmath\fi}
+
+\def\choosemathbig#1#2% so we accent \big{||} as well
+ {{\hbox{$%
+ \ifcase\bigmathdelimitermethod
+ \doleftbigmath#2\relax
+ \dorightbigmath#2\relax
+ \or
+ \attribute\mathsizeattribute#1\relax
+ \doleftbigmath#2\relax
+ \dorightbigmath#2\relax
+ \else
+ \doleftbigmath#2\relax
+ \vbox\!!to\getvalue{\??mm:b:\number#1}\bodyfontsize{}%
+ \dorightbigmath#2\relax
+ \fi
+ \nulldelimiterspace\zeropoint\relax
+ \mathsurround\zeropoint
+ $}}}
+
+\definemathcommand [big] {\choosemathbig\plusone } \setvalue{\??mm:b:1}{0.85}
+\definemathcommand [Big] {\choosemathbig\plustwo } \setvalue{\??mm:b:2}{1.15}
+\definemathcommand [bigg] {\choosemathbig\plusthree} \setvalue{\??mm:b:3}{1.45}
+\definemathcommand [Bigg] {\choosemathbig\plusfour } \setvalue{\??mm:b:4}{1.75}
+
+\definemathcommand [bigl] [open] [one] {\big}
+\definemathcommand [bigm] [rel] [one] {\big}
+\definemathcommand [bigr] [close] [one] {\big}
+\definemathcommand [Bigl] [open] [one] {\Big}
+\definemathcommand [Bigm] [rel] [one] {\Big}
+\definemathcommand [Bigr] [close] [one] {\Big}
+\definemathcommand [biggl] [open] [one] {\bigg}
+\definemathcommand [biggm] [rel] [one] {\bigg}
+\definemathcommand [biggr] [close] [one] {\bigg}
+\definemathcommand [Biggl] [open] [one] {\Bigg}
+\definemathcommand [Biggm] [rel] [one] {\Bigg}
+\definemathcommand [Biggr] [close] [one] {\Bigg}
+
+% special
+
+%AM: Optimize this! Add similar options for sums.
+
+\def\setoperatorlimits#1#2% operator limits
+ {\savenormalmeaning{#1}%
+ \def#1{\csname normal\strippedcsname#1\endcsname#2}}
+
+\setoperatorlimits\int \intlimits
+\setoperatorlimits\iint \intlimits
+\setoperatorlimits\iiint \intlimits
+\setoperatorlimits\oint \intlimits
+\setoperatorlimits\oiint \intlimits
+\setoperatorlimits\oiiint \intlimits
+\setoperatorlimits\intclockwise \intlimits
+\setoperatorlimits\ointclockwise \intlimits
+\setoperatorlimits\ointctrclockwise \intlimits
+
+%D This is a temporary hack until we figure out how to do this correctly.
+
+\unexpanded\def\implies {\mathrel{\;\Longrightarrow\;}}
+\unexpanded\def\impliedby{\mathrel{\;\Longleftarrow\;}}
+\unexpanded\def\And {\mathrel{\;\internalAnd\;}}
+\unexpanded\def\iff {\;\Longleftrightarrow\;}
+
+% todo: virtual in math-vfu
+
+% \definemathcommand [mapsto] {\mapstochar\rightarrow}
+% \definemathcommand [hookrightarrow] {\lhook\joinrel\rightarrow}
+% \definemathcommand [hookleftarrow] {\leftarrow\joinrel\rhook}
+% \definemathcommand [bowtie] {\mathrel\triangleright\joinrel\mathrel\triangleleft}
+% \definemathcommand [models] {\mathrel|\joinrel=}
+% \definemathcommand [iff] {\;\Longleftrightarrow\;}
+
+% hm
+
+% ldots = 2026
+% vdots = 22EE
+% cdots = 22EF
+% ddots = 22F1
+% udots = 22F0
+
+% \def\PLAINldots{\ldotp\ldotp\ldotp}
+% \def\PLAINcdots{\cdotp\cdotp\cdotp}
+
+% \def\PLAINvdots
+% {\vbox{\baselineskip.4\bodyfontsize\lineskiplimit\zeropoint\kern.6\bodyfontsize\hbox{.}\hbox{.}\hbox{.}}}
+
+% \def\PLAINddots
+% {\mkern1mu%
+% \raise.7\bodyfontsize\vbox{\kern.7\bodyfontsize\hbox{.}}%
+% \mkern2mu%
+% \raise.4\bodyfontsize\relax\hbox{.}%
+% \mkern2mu%
+% \raise.1\bodyfontsize\hbox{.}%
+% \mkern1mu}
+
+% \definemathcommand [ldots] [inner] {\PLAINldots}
+% \definemathcommand [cdots] [inner] {\PLAINcdots}
+% \definemathcommand [vdots] [nothing] {\PLAINvdots}
+% \definemathcommand [ddots] [inner] {\PLAINddots}
+
+%D \starttyping
+%D $\sqrt[3]{10}$
+%D \stoptyping
+
+\def\rootradical{\Uroot 0 "221A } % can be done in char-def
+
+\def\root#1\of{\rootradical{#1}} % #2
+
+\unexpanded\def\sqrt{\doifnextoptionalelse\rootwithdegree\rootwithoutdegree}
+
+\def\rootwithdegree [#1]{\rootradical{#1}}
+\def\rootwithoutdegree {\rootradical {}}
+
+\def\PLAINmatrix#1%
+ {\null\,\vcenter{\normalbaselines\mathsurround\zeropoint
+ \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
+ \mathstrut\crcr\noalign{\kern-\baselineskip}
+ #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,}
+
+\definemathcommand [mathstrut] {\vphantom{(}}
+\definemathcommand [joinrel] {\mathrel{\mkern-3mu}}
+
+% \definemathcommand [matrix] {\PLAINmatrix}
+% \definemathcommand [over] {\normalover} % hack, to do
+
+\unexpanded\def\{{\mathortext\lbrace\letterleftbrace }
+\unexpanded\def\}{\mathortext\rbrace\letterrightbrace}
+
+%D The following colon related definitions are provided by Aditya
+%D Mahajan who derived them from \type {mathtools.sty} and \type
+%D {colonequals.sty}.
+
+%D \macros
+%D {centercolon, colonminus, minuscolon, colonequals, equalscolon,
+%D colonapprox, approxcolon, colonsim, simcolon, coloncolon,
+%D coloncolonminus, minuscoloncolon, coloncolonequals,
+%D equalscoloncolon, coloncolonapprox, approxcoloncolon,
+%D colonsim, simcoloncolon}
+%D
+%D In $a := b$ the colon is not vertically centered with the equal
+%D to. Also the distance between colon and equal to is a bit large.
+%D So, we define a vertically centered colon \tex {centercolon} and
+%D a few macros for colon and double colon relation symbols.
+%D
+%D \startlines
+%D \formula {A \centercolon B}
+%D \formula {A \colonminus B}
+%D \formula {A \minuscolon B}
+%D \formula {A \colonequals B}
+%D \formula {A \equalscolon B}
+%D \formula {A \colonapprox B}
+%D \formula {A \approxcolon B}
+%D \formula {A \colonsim B}
+%D \formula {A \simcolon B}
+%D \formula {A \coloncolon B}
+%D \formula {A \coloncolonminus B}
+%D \formula {A \minuscoloncolon B}
+%D \formula {A \coloncolonequals B}
+%D \formula {A \equalscoloncolon B}
+%D \formula {A \coloncolonapprox B}
+%D \formula {A \approxcoloncolon B}
+%D \formula {A \colonsim B}
+%D \formula {A \simcoloncolon B}
+%D \stoplines
+
+%D The next macros take care of the space between the colon and the
+%D relation symbol.
+
+\definemathcommand [colonsep] {\mkern-1.2mu}
+\definemathcommand [doublecolonsep] {\mkern-0.9mu}
+
+%D The next macro vertically centeres its contents.
+
+\def\@center@math#1%
+ {\vcenter{\hbox{$\mathsurround\zeropoint#1$}}}
+
+\def\@center@colon
+ {\mathpalette\@center@math{\colon}}
+
+%D Now we define all the colon relations.
+
+\definemathcommand [centercolon] [rel] {\@center@colon}
+\definemathcommand [colonminus] [rel] {\centercolon\colonsep\mathrel{-}}
+\definemathcommand [minuscolon] [rel] {\mathrel{-}\colonsep\centercolon}
+\definemathcommand [colonequals] [rel] {\centercolon\colonsep=}
+\definemathcommand [equalscolon] [rel] {=\centercolon\colonsep}
+\definemathcommand [colonapprox] [rel] {\centercolon\colonsep\approx}
+\definemathcommand [approxcolon] [rel] {\approx\centercolon\colonsep}
+\definemathcommand [colonsim] [rel] {\centercolon\colonsep\sim}
+\definemathcommand [simcolon] [rel] {\sim\centercolon\colonsep}
+
+\definemathcommand [coloncolon] [rel] {\centercolon\doublecolonsep\centercolon}
+\definemathcommand [coloncolonminus] [rel] {\coloncolon\colonsep\mathrel{-}}
+\definemathcommand [minuscoloncolon] [rel] {\mathrel{-}\colonsep\coloncolon}
+\definemathcommand [coloncolonequals] [rel] {\coloncolon\colonsep=}
+\definemathcommand [equalscoloncolon] [rel] {=\coloncolon\colonsep}
+\definemathcommand [coloncolonapprox] [rel] {\coloncolon\colonsep\approx}
+\definemathcommand [approxcoloncolon] [rel] {\approx\coloncolon\colonsep}
+\definemathcommand [colonsim] [rel] {\coloncolon\colonsep\sim}
+\definemathcommand [simcoloncolon] [rel] {\sim\coloncolon\colonsep}
+
+%D Goodies. We might move this elsewhere.
+
+\def\underleftarrow #1{\mathop{\Uunderdelimiter 0 "2190 {#1}}}
+\def\overleftarrow #1{\mathop{\Uoverdelimiter 0 "2190 {#1}}}
+\def\underrightarrow#1{\mathop{\Uunderdelimiter 0 "2192 {#1}}}
+\def\overrightarrow #1{\mathop{\Uoverdelimiter 0 "2192 {#1}}}
+
+% todo: \Udelimiterover, \Udelimiterunder
+
+\def\normaldoublebrace {\Umathaccents 0 0 "23DE 0 0 "23DF }
+\def\normaldoubleparent{\Umathaccents 0 0 "23DC 0 0 "23DD }
+
+\let\normaloverbrace \overbrace
+\let\normalunderbrace \underbrace
+\let\normaloverparent \overparent
+\let\normalunderparent \underparent
+\let\normalunderleftarrow \underleftarrow
+\let\normaloverleftarrow \overleftarrow
+\let\normalunderrightarrow\underrightarrow
+\let\normaloverrightarrow \overrightarrow
+
+\unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
+\unexpanded\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}}
+
+\unexpanded\def\overbrace {\mathopwithlimits\normaloverbrace }
+\unexpanded\def\underbrace {\mathopwithlimits\normalunderbrace }
+\unexpanded\def\doublebrace {\mathopwithlimits\normaldoublebrace }
+\unexpanded\def\overparent {\mathopwithlimits\normaloverparent }
+\unexpanded\def\underparent {\mathopwithlimits\normalunderparent }
+\unexpanded\def\doubleparent {\mathopwithlimits\normaldoubleparent }
+\unexpanded\def\underleftarrow {\mathopwithlimits\normalunderleftarrow }
+\unexpanded\def\overleftarrow {\mathopwithlimits\normaloverleftarrow }
+\unexpanded\def\underrightarrow{\mathopwithlimits\normalunderrightarrow}
+\unexpanded\def\overrightarrow {\mathopwithlimits\normaloverrightarrow }
+
+\let\normalsurd\surd
+
+\unexpanded\def\surd{\normalsurd{}}
+
+% todo mathclass=punctuation ord
+
+% \Umathcode"02C="6 "0 "02C
+% \Umathcode"02E="0 "0 "02E
+
+% tricky .. todo
+
+% \appendtoks
+% \def\over{\primitive\over}%
+% \to \everymathematics
+
+\protect \endinput
diff --git a/tex/context/base/math-del.mkiv b/tex/context/base/math-del.mkiv
new file mode 100644
index 000000000..5ffda1919
--- /dev/null
+++ b/tex/context/base/math-del.mkiv
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=math-del,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Delimiters,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Delimiters}
+
+\unprotect
+
+%D \macros
+%D {checkdelimiters, fakeleftdelimiter, fakerightdelimiter}
+%D
+%D Handy for non matching situations (as with mathml):
+%D
+%D \starttyping
+%D \checkdelimiters{... bla bla ...}
+%D \fakeleftdelimiter
+%D ... bla bla ...
+%D \fakerightdelimiter
+%D \stoptyping
+
+\newcount\delimitercount
+
+\def\leftfakedelimiter {\advance\delimitercount\minusone\gobbleoneargument}%
+\def\rightfakedelimiter{\advance\delimitercount\plusone \gobbleoneargument}%
+
+\def\checkdelimiters#1%
+ {\delimitercount\zerocount
+ \setbox\scratchbox\hbox\bgroup
+ \let\left \leftfakedelimiter
+ \let\right\rightfakedelimiter
+ $#1\expandafter$\expandafter
+ \egroup
+ \expandafter\delimitercount\the\delimitercount\relax}
+
+\def\fakeleftdelimiter {\ifnum\delimitercount>\zerocount\left .\fi}
+\def\fakerightdelimiter{\ifnum\delimitercount<\zerocount\right.\fi}
+
+%D The following macros are used in the MathML interpreter, so
+%D there is a good change of them never being documented for
+%D other usage.
+
+\let\normalordelimiter\secondoftwoarguments
+\let\normalorfiller \firstoftwoarguments
+
+\def\enabledelimiter {\let\normalordelimiter\secondoftwoarguments}
+\def\disabledelimiter{\let\normalordelimiter\firstoftwoarguments}
+
+\def\enablefiller {\let\normalorfiller\secondoftwoarguments}
+\def\disablefiller {\let\normalorfiller\firstoftwoarguments}
+
+\def\mathopnolimits#1{\mathop{\mr#1}\nolimits} % was \rm, which follows text fonts (used in mml parser)
+\def\mathopdolimits#1{\mathop{\mr#1}} % was \rm, which follows text fonts (used in mml parser)
+
+\protect \endinput
diff --git a/tex/context/base/math-dim.lua b/tex/context/base/math-dim.lua
new file mode 100644
index 000000000..62d805126
--- /dev/null
+++ b/tex/context/base/math-dim.lua
@@ -0,0 +1,313 @@
+if not modules then modules = { } end modules ['math-dim'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Beware: only Taco really understands in depth what these dimensions do so
+-- if you run into problems ...
+
+local abs, next = math.abs, next
+
+mathematics = mathematics or { }
+
+local defaults = {
+ ['axis']={
+ ['default']={ "AxisHeight", "axis_height" },
+ },
+ ['accent_base_height']={
+ ['default']={ "AccentBaseHeight", "x_height" },
+ },
+ ['fraction_del_size']={
+ ['default']={ "FractionDelimiterSize", "delim2" },
+ ['cramped_display_style']={ "FractionDelimiterDisplayStyleSize", "delim1" },
+ ['display_style']={ "FractionDelimiterDisplayStyleSize", "delim1" },
+ },
+ ['fraction_denom_down']={
+ ['default']={ "FractionDenominatorShiftDown", "denom2" },
+ ['cramped_display_style']={ "FractionDenominatorDisplayStyleShiftDown", "denom1" },
+ ['display_style']={ "FractionDenominatorDisplayStyleShiftDown", "denom1" },
+ },
+ ['fraction_denom_vgap']={
+ ['default']={ "FractionDenominatorGapMin", "default_rule_thickness" },
+ ['cramped_display_style']={ "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" },
+ ['display_style']={ "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" },
+ },
+ ['fraction_num_up']={
+ ['default']={ "FractionNumeratorShiftUp", "num2" },
+ ['cramped_display_style']={ "FractionNumeratorDisplayStyleShiftUp", "num1" },
+ ['display_style']={ "FractionNumeratorDisplayStyleShiftUp", "num1" },
+ },
+ ['fraction_num_vgap']={
+ ['default']={ "FractionNumeratorGapMin", "default_rule_thickness" },
+ ['cramped_display_style']={ "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" },
+ ['display_style']={ "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" },
+ },
+ ['fraction_rule']={
+ ['default']={ "FractionRuleThickness", "default_rule_thickness" },
+ },
+ ['limit_above_bgap']={
+ ['default']={ "UpperLimitBaselineRiseMin", "big_op_spacing3" },
+ },
+ ['limit_above_kern']={
+ ['default']={ "0", "big_op_spacing5" },
+ },
+ ['limit_above_vgap']={
+ ['default']={ "UpperLimitGapMin", "big_op_spacing1" },
+ },
+ ['limit_below_bgap']={
+ ['default']={ "LowerLimitBaselineDropMin", "big_op_spacing4" },
+ },
+ ['limit_below_kern']={
+ ['default']={ "0", "big_op_spacing5" },
+ },
+ ['limit_below_vgap']={
+ ['default']={ "LowerLimitGapMin", "big_op_spacing2" },
+ },
+
+--~ ['....']={
+--~ ['default']={ "DisplayOperatorMinHeight", "....." },
+--~ },
+
+ ['overbar_kern']={
+ ['default']={ "OverbarExtraAscender", "default_rule_thickness" },
+ },
+ ['overbar_rule']={
+ ['default']={ "OverbarRuleThickness", "default_rule_thickness" },
+ },
+ ['overbar_vgap']={
+ ['default']={ "OverbarVerticalGap", "3*default_rule_thickness" },
+ },
+ ['quad']={
+ ['default']={ "font_size(f)", "math_quad" },
+ },
+ ['radical_kern']={
+ ['default']={ "RadicalExtraAscender", "default_rule_thickness" },
+ },
+ ['radical_rule']={
+ ['default']={ "RadicalRuleThickness", "" },
+ },
+ ['radical_vgap']={
+ ['default']={ "RadicalVerticalGap", "default_rule_thickness+(abs(default_rule_thickness)/4)" },
+ ['display_style']={ "RadicalDisplayStyleVerticalGap", "default_rule_thickness+(abs(math_x_height)/4)" },
+ },
+ ['space_after_script']={
+ ['default']={ "SpaceAfterScript", "script_space" },
+ },
+ ['stack_denom_down']={
+ ['default']={ "StackBottomShiftDown", "denom2" },
+ ['cramped_display_style']={ "StackBottomDisplayStyleShiftDown", "denom1" },
+ ['display_style']={ "StackBottomDisplayStyleShiftDown", "denom1" },
+ },
+ ['stack_num_up']={
+ ['default']={ "StackTopShiftUp", "num3" },
+ ['cramped_display_style']={ "StackTopDisplayStyleShiftUp", "num1" },
+ ['display_style']={ "StackTopDisplayStyleShiftUp", "num1" },
+ },
+ ['stack_vgap']={
+ ['default']={ "StackGapMin", "3*default_rule_thickness" },
+ ['cramped_display_style']={ "StackDisplayStyleGapMin", "7*default_rule_thickness" },
+ ['display_style']={ "StackDisplayStyleGapMin", "7*default_rule_thickness" },
+ },
+ ['sub_shift_down']={
+ ['default']={ "SubscriptShiftDown", "sub1" },
+ },
+ ['sub_shift_drop']={
+ ['default']={ "SubscriptBaselineDropMin", "sub_drop" },
+ },
+ ['sub_sup_shift_down']={
+ ['default']={ "SubscriptShiftDown", "sub2" }, -- todo
+ },
+ ['sub_top_max']={
+ ['default']={ "SubscriptTopMax", "abs(math_x_height*4)/5" },
+ },
+ ['subsup_vgap']={
+ ['default']={ "SubSuperscriptGapMin", "4*default_rule_thickness" },
+ },
+ ['sup_bottom_min']={
+ ['default']={ "SuperscriptBottomMin", "abs(math_x_height)/4" },
+ },
+ ['sup_shift_drop']={
+ ['default']={ "SuperscriptBaselineDropMax", "sup_drop" },
+ },
+ ['sup_shift_up']={
+ ['cramped_display_style']={ "SuperscriptShiftUpCramped", "sup3" },
+ ['cramped_script_script_style']={ "SuperscriptShiftUpCramped", "sup3" },
+ ['cramped_script_style']={ "SuperscriptShiftUpCramped", "sup3" },
+ ['cramped_text_style']={ "SuperscriptShiftUpCramped", "sup3" },
+ ['display_style']={ "SuperscriptShiftUp", "sup1" },
+ ['script_script_style']={ "SuperscriptShiftUp", "sup2" },
+ ['script_style']={ "SuperscriptShiftUp", "sup2" },
+ ['text_style']={ "SuperscriptShiftUp", "sup2" },
+ },
+ ['sup_sub_bottom_max']={
+ ['default']={ "SuperscriptBottomMaxWithSubscript", "abs(math_x_height*4)/5" },
+ },
+ ['underbar_kern']={
+ ['default']={ "UnderbarExtraDescender", "0" },
+ },
+ ['underbar_rule']={
+ ['default']={ "UnderbarRuleThickness", "default_rule_thickness" },
+ },
+ ['underbar_vgap']={
+ ['default']={ "UnderbarVerticalGap", "3*default_rule_thickness" },
+ },
+ ['connector_overlap_min']={
+ ['default']={ "MinConnectorOverlap", "0.25*default_rule_thickness" },
+ },
+ ['over_delimiter_vgap']={
+ ['default']={ "StretchStackGapBelowMin", "big_op_spacing1" },
+ },
+ ['over_delimiter_bgap']={
+ ['default']={ "StretchStackTopShiftUp", "big_op_spacing3" },
+ },
+ ['under_delimiter_vgap']={
+ ['default']={ "StretchStackGapAboveMin", "big_op_spacing2" },
+ },
+ ['under_delimiter_bgap']={
+ ['default']={ "StretchStackBottomShiftDown", "big_op_spacing4" },
+ },
+ ['radical_degree_before']={
+ ['default']={ "RadicalKernBeforeDegree", "(5/18)*quad" },
+ },
+ ['radical_degree_after']={
+ ['default']={ "RadicalKernAfterDegree", "(-10/18)*quad" },
+ },
+ ['radical_degree_raise']={
+ ['default']={ "RadicalDegreeBottomRaisePercent", "60" },
+ },
+}
+
+local styles = {
+ 'cramped_display_style',
+ 'cramped_script_script_style',
+ 'cramped_script_style',
+ 'cramped_text_style',
+ 'display_style',
+ 'script_script_style',
+ 'script_style',
+ 'text_style',
+}
+
+for k, v in next, defaults do
+ for _, s in next, styles do
+ if not v[s] then
+ v[s] = v.default
+ end
+ end
+end
+
+-- we cannot use a metatable because we do a copy (takes a bit more work)
+--
+-- local mt = { } setmetatable(defaults,mt)
+--
+-- mt.__index = function(t,s)
+-- return t.default or t.text_style or 0
+-- end
+
+function mathematics.dimensions(dimens)
+ if dimens.SpaceAfterScript then
+ dimens.SubscriptShiftDownWithSuperscript = dimens.SubscriptShiftDown * 1.5
+ return { }, table.fastcopy(dimens)
+ elseif dimens.AxisHeight or dimens.axis_height then
+ local t = { }
+ local math_x_height = dimens.x_height or 10*65526
+ local math_quad = dimens.quad or 10*65526
+ local default_rule_thickness = dimens.FractionDenominatorGapMin or dimens.default_rule_thickness or 0.4*65526
+ dimens["0"] = 0
+ dimens["60"] = 60
+ dimens["0.25*default_rule_thickness"] = default_rule_thickness / 4
+ dimens["3*default_rule_thickness"] = 3 * default_rule_thickness
+ dimens["4*default_rule_thickness"] = 4 * default_rule_thickness
+ dimens["7*default_rule_thickness"] = 7 * default_rule_thickness
+ dimens["(5/18)*quad"] = (math_quad * 5) / 18
+ dimens["(-10/18)*quad"] = - (math_quad * 10) / 18
+ dimens["abs(math_x_height*4)/5"] = abs(math_x_height * 4) / 5
+ dimens["default_rule_thickness+(abs(default_rule_thickness)/4)"] = default_rule_thickness+(abs(default_rule_thickness) / 4)
+ dimens["default_rule_thickness+(abs(math_x_height)/4)"] = default_rule_thickness+(abs(math_x_height) / 4)
+ dimens["abs(math_x_height)/4"] = abs(math_x_height) / 4
+ dimens["abs(math_x_height*4)/5"] = abs(math_x_height * 4) / 5
+ dimens[""] = false
+ dimens["script_space"] = false -- at macro level
+ for variable, styles in next, defaults do
+ local tt = { }
+ for style, default in next, styles do
+ local one, two = default[1], default[2]
+ local value = dimens[one]
+ if value then
+ tt[style] = value
+ else
+ value = dimens[two]
+ if value == false then
+ tt[style] = nil
+ else
+ tt[style] = value or 0
+ end
+ end
+ end
+ t[variable] = tt
+ end
+--~ logs.report("warning", "version 0.47 is needed for proper delimited math")
+ local d = {
+ AxisHeight = t . axis . text_style,
+ AccentBaseHeight = t . accent_base_height . text_style,
+ FractionDenominatorDisplayStyleGapMin = t . fraction_denom_vgap . display_style,
+ FractionDenominatorDisplayStyleShiftDown = t . fraction_denom_down . display_style,
+ FractionDenominatorGapMin = t . fraction_denom_vgap . text_style,
+ FractionDenominatorShiftDown = t . fraction_denom_down . text_style,
+ FractionNumeratorDisplayStyleGapMin = t . fraction_num_vgap . display_style,
+ FractionNumeratorDisplayStyleShiftUp = t . fraction_num_up . display_style,
+ FractionNumeratorGapMin = t . fraction_num_vgap . text_style,
+ FractionNumeratorShiftUp = t . fraction_num_up . text_style,
+ FractionRuleThickness = t . fraction_rule . text_style,
+ FractionDelimiterSize = t . fraction_del_size . text_style,
+ FractionDelimiterDisplayStyleSize = t . fraction_del_size . display_style,
+ LowerLimitBaselineDropMin = t . limit_below_bgap . text_style,
+ LowerLimitGapMin = t . limit_below_vgap . text_style,
+ OverbarExtraAscender = t . overbar_kern . text_style,
+ OverbarRuleThickness = t . overbar_rule . text_style,
+ OverbarVerticalGap = t . overbar_vgap . text_style,
+ RadicalDisplayStyleVerticalGap = t . radical_vgap . display_style,
+ RadicalExtraAscender = t . radical_kern . text_style,
+ RadicalRuleThickness = t . radical_rule . text_style,
+ RadicalVerticalGap = t . radical_vgap . text_style,
+ RadicalKernBeforeDegree = t . radical_degree_before . display_style,
+ RadicalKernAfterDegree = t . radical_degree_after . display_style,
+ RadicalDegreeBottomRaisePercent = t . radical_degree_raise . display_style,
+ SpaceAfterScript = t . space_after_script . text_style,
+ StackBottomDisplayStyleShiftDown = t . stack_denom_down . display_style,
+ StackBottomShiftDown = t . stack_denom_down . text_style,
+ StackDisplayStyleGapMin = t . stack_vgap . display_style,
+ StackGapMin = t . stack_vgap . text_style,
+ StackTopDisplayStyleShiftUp = t . stack_num_up . display_style,
+ StackTopShiftUp = t . stack_num_up . text_style,
+ SubscriptBaselineDropMin = t . sub_shift_drop . text_style,
+ SubscriptShiftDown = t . sub_shift_down . text_style,
+ SubscriptShiftDownWithSuperscript = t . sub_sup_shift_down . text_style,
+ SubscriptTopMax = t . sub_top_max . text_style,
+ SubSuperscriptGapMin = t . subsup_vgap . text_style,
+ SuperscriptBaselineDropMax = t . sup_shift_drop . text_style,
+ SuperscriptBottomMaxWithSubscript = t . sup_sub_bottom_max . text_style,
+ SuperscriptBottomMin = t . sup_bottom_min . text_style,
+ SuperscriptShiftUp = t . sup_shift_up . text_style,
+ SuperscriptShiftUpCramped = t . sup_shift_up . cramped_text_style,
+ UnderbarExtraDescender = t . underbar_kern . text_style,
+ UnderbarRuleThickness = t . underbar_rule . text_style,
+ UnderbarVerticalGap = t . underbar_vgap . text_style,
+ UpperLimitBaselineRiseMin = t . limit_above_bgap . text_style,
+ UpperLimitGapMin = t . limit_above_vgap . text_style,
+ MinConnectorOverlap = t . connector_overlap_min . text_style,
+ StretchStackGapBelowMin = t . over_delimiter_vgap . text_style,
+ StretchStackTopShiftUp = t . over_delimiter_bgap . text_style,
+ StretchStackGapAboveMin = t . under_delimiter_vgap . text_style,
+ StretchStackBottomShiftDown = t . under_delimiter_bgap . text_style,
+ }
+ d.AccentBaseHeight = 0
+ return t, d -- this might change
+ else
+ return { }, { }
+ end
+end
+
diff --git a/tex/context/base/math-dis.mkiv b/tex/context/base/math-dis.mkiv
new file mode 100644
index 000000000..3eed2b162
--- /dev/null
+++ b/tex/context/base/math-dis.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=math-ali,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Display,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE / Hans Hagen]
+%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 Math Macros / Display}
+
+\unprotect
+
+% display spacing code will move here
+
+\protect \endinput
diff --git a/tex/context/base/math-ent.lua b/tex/context/base/math-ent.lua
new file mode 100644
index 000000000..e5e5b98f0
--- /dev/null
+++ b/tex/context/base/math-ent.lua
@@ -0,0 +1,2102 @@
+if not modules then modules = { } end modules ['math-ent'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "derived from the mathml 2.0 specification",
+}
+
+mathematics.entities={
+ ["Aacute"]=0x000C1,
+ ["aacute"]=0x000E1,
+ ["Abreve"]=0x00102,
+ ["abreve"]=0x00103,
+ ["ac"]=0x0223E,
+ ["acd"]=0x0223F,
+ ["acE"]=0x0223E,
+ ["Acirc"]=0x000C2,
+ ["acirc"]=0x000E2,
+ ["acute"]=0x000B4,
+ ["Acy"]=0x00410,
+ ["acy"]=0x00430,
+ ["AElig"]=0x000C6,
+ ["aelig"]=0x000E6,
+ ["af"]=0x02061,
+ ["Afr"]=0x1D504,
+ ["afr"]=0x1D51E,
+ ["Agrave"]=0x000C0,
+ ["agrave"]=0x000E0,
+ ["aleph"]=0x02135,
+ ["alpha"]=0x003B1,
+ ["Amacr"]=0x00100,
+ ["amacr"]=0x00101,
+ ["amalg"]=0x02A3F,
+ ["amp"]=0x00026,
+ ["And"]=0x02A53,
+ ["and"]=0x02227,
+ ["andand"]=0x02A55,
+ ["andd"]=0x02A5C,
+ ["andslope"]=0x02A58,
+ ["andv"]=0x02A5A,
+ ["ang"]=0x02220,
+ ["ange"]=0x029A4,
+ ["angle"]=0x02220,
+ ["angmsd"]=0x02221,
+ ["angmsdaa"]=0x029A8,
+ ["angmsdab"]=0x029A9,
+ ["angmsdac"]=0x029AA,
+ ["angmsdad"]=0x029AB,
+ ["angmsdae"]=0x029AC,
+ ["angmsdaf"]=0x029AD,
+ ["angmsdag"]=0x029AE,
+ ["angmsdah"]=0x029AF,
+ ["angrt"]=0x0221F,
+ ["angrtvb"]=0x022BE,
+ ["angrtvbd"]=0x0299D,
+ ["angsph"]=0x02222,
+ ["angst"]=0x0212B,
+ ["angzarr"]=0x0237C,
+ ["Aogon"]=0x00104,
+ ["aogon"]=0x00105,
+ ["Aopf"]=0x1D538,
+ ["aopf"]=0x1D552,
+ ["ap"]=0x02248,
+ ["apacir"]=0x02A6F,
+ ["apE"]=0x02A70,
+ ["ape"]=0x0224A,
+ ["apid"]=0x0224B,
+ ["apos"]=0x00027,
+ ["ApplyFunction"]=0x02061,
+ ["approx"]=0x02248,
+ ["approxeq"]=0x0224A,
+ ["Aring"]=0x000C5,
+ ["aring"]=0x000E5,
+ ["Ascr"]=0x1D49C,
+ ["ascr"]=0x1D4B6,
+ ["Assign"]=0x02254,
+ ["ast"]=0x0002A,
+ ["asymp"]=0x02248,
+ ["asympeq"]=0x0224D,
+ ["Atilde"]=0x000C3,
+ ["atilde"]=0x000E3,
+ ["Auml"]=0x000C4,
+ ["auml"]=0x000E4,
+ ["awconint"]=0x02233,
+ ["awint"]=0x02A11,
+ ["backcong"]=0x0224C,
+ ["backepsilon"]=0x003F6,
+ ["backprime"]=0x02035,
+ ["backsim"]=0x0223D,
+ ["backsimeq"]=0x022CD,
+ ["Backslash"]=0x02216,
+ ["Barv"]=0x02AE7,
+ ["barvee"]=0x022BD,
+ ["Barwed"]=0x02306,
+ ["barwed"]=0x02305,
+ ["barwedge"]=0x02305,
+ ["bbrk"]=0x023B5,
+ ["bbrktbrk"]=0x023B6,
+ ["bcong"]=0x0224C,
+ ["Bcy"]=0x00411,
+ ["bcy"]=0x00431,
+ ["becaus"]=0x02235,
+ ["Because"]=0x02235,
+ ["because"]=0x02235,
+ ["bemptyv"]=0x029B0,
+ ["bepsi"]=0x003F6,
+ ["bernou"]=0x0212C,
+ ["Bernoullis"]=0x0212C,
+ ["beta"]=0x003B2,
+ ["beth"]=0x02136,
+ ["between"]=0x0226C,
+ ["Bfr"]=0x1D505,
+ ["bfr"]=0x1D51F,
+ ["bigcap"]=0x022C2,
+ ["bigcirc"]=0x025EF,
+ ["bigcup"]=0x022C3,
+ ["bigodot"]=0x02A00,
+ ["bigoplus"]=0x02A01,
+ ["bigotimes"]=0x02A02,
+ ["bigsqcup"]=0x02A06,
+ ["bigstar"]=0x02605,
+ ["bigtriangledown"]=0x025BD,
+ ["bigtriangleup"]=0x025B3,
+ ["biguplus"]=0x02A04,
+ ["bigvee"]=0x022C1,
+ ["bigwedge"]=0x022C0,
+ ["bkarow"]=0x0290D,
+ ["blacklozenge"]=0x029EB,
+ ["blacksquare"]=0x025AA,
+ ["blacktriangle"]=0x025B4,
+ ["blacktriangledown"]=0x025BE,
+ ["blacktriangleleft"]=0x025C2,
+ ["blacktriangleright"]=0x025B8,
+ ["blank"]=0x02423,
+ ["blk12"]=0x02592,
+ ["blk14"]=0x02591,
+ ["blk34"]=0x02593,
+ ["block"]=0x02588,
+ ["bne"]=0x0003D,
+ ["bnequiv"]=0x02261,
+ ["bNot"]=0x02AED,
+ ["bnot"]=0x02310,
+ ["Bopf"]=0x1D539,
+ ["bopf"]=0x1D553,
+ ["bot"]=0x022A5,
+ ["bottom"]=0x022A5,
+ ["bowtie"]=0x022C8,
+ ["boxbox"]=0x029C9,
+ ["boxDL"]=0x02557,
+ ["boxDl"]=0x02556,
+ ["boxdL"]=0x02555,
+ ["boxdl"]=0x02510,
+ ["boxDR"]=0x02554,
+ ["boxDr"]=0x02553,
+ ["boxdR"]=0x02552,
+ ["boxdr"]=0x0250C,
+ ["boxH"]=0x02550,
+ ["boxh"]=0x02500,
+ ["boxHD"]=0x02566,
+ ["boxHd"]=0x02564,
+ ["boxhD"]=0x02565,
+ ["boxhd"]=0x0252C,
+ ["boxHU"]=0x02569,
+ ["boxHu"]=0x02567,
+ ["boxhU"]=0x02568,
+ ["boxhu"]=0x02534,
+ ["boxminus"]=0x0229F,
+ ["boxplus"]=0x0229E,
+ ["boxtimes"]=0x022A0,
+ ["boxUL"]=0x0255D,
+ ["boxUl"]=0x0255C,
+ ["boxuL"]=0x0255B,
+ ["boxul"]=0x02518,
+ ["boxUR"]=0x0255A,
+ ["boxUr"]=0x02559,
+ ["boxuR"]=0x02558,
+ ["boxur"]=0x02514,
+ ["boxV"]=0x02551,
+ ["boxv"]=0x02502,
+ ["boxVH"]=0x0256C,
+ ["boxVh"]=0x0256B,
+ ["boxvH"]=0x0256A,
+ ["boxvh"]=0x0253C,
+ ["boxVL"]=0x02563,
+ ["boxVl"]=0x02562,
+ ["boxvL"]=0x02561,
+ ["boxvl"]=0x02524,
+ ["boxVR"]=0x02560,
+ ["boxVr"]=0x0255F,
+ ["boxvR"]=0x0255E,
+ ["boxvr"]=0x0251C,
+ ["bprime"]=0x02035,
+ ["Breve"]=0x002D8,
+ ["breve"]=0x002D8,
+ ["brvbar"]=0x000A6,
+ ["Bscr"]=0x0212C,
+ ["bscr"]=0x1D4B7,
+ ["bsemi"]=0x0204F,
+ ["bsim"]=0x0223D,
+ ["bsime"]=0x022CD,
+ ["bsol"]=0x0005C,
+ ["bsolb"]=0x029C5,
+ ["bsolhsub"]=0x0005C,
+ ["bull"]=0x02022,
+ ["bullet"]=0x02022,
+ ["bump"]=0x0224E,
+ ["bumpE"]=0x02AAE,
+ ["bumpe"]=0x0224F,
+ ["Bumpeq"]=0x0224E,
+ ["bumpeq"]=0x0224F,
+ ["Cacute"]=0x00106,
+ ["cacute"]=0x00107,
+ ["Cap"]=0x022D2,
+ ["cap"]=0x02229,
+ ["capand"]=0x02A44,
+ ["capbrcup"]=0x02A49,
+ ["capcap"]=0x02A4B,
+ ["capcup"]=0x02A47,
+ ["capdot"]=0x02A40,
+ ["CapitalDifferentialD"]=0x02145,
+ ["caps"]=0x02229,
+ ["caret"]=0x02041,
+ ["caron"]=0x002C7,
+ ["Cayleys"]=0x0212D,
+ ["ccaps"]=0x02A4D,
+ ["Ccaron"]=0x0010C,
+ ["ccaron"]=0x0010D,
+ ["Ccedil"]=0x000C7,
+ ["ccedil"]=0x000E7,
+ ["Ccirc"]=0x00108,
+ ["ccirc"]=0x00109,
+ ["Cconint"]=0x02230,
+ ["ccups"]=0x02A4C,
+ ["ccupssm"]=0x02A50,
+ ["Cdot"]=0x0010A,
+ ["cdot"]=0x0010B,
+ ["cedil"]=0x000B8,
+ ["Cedilla"]=0x000B8,
+ ["cemptyv"]=0x029B2,
+ ["cent"]=0x000A2,
+ ["CenterDot"]=0x000B7,
+ ["centerdot"]=0x000B7,
+ ["Cfr"]=0x0212D,
+ ["cfr"]=0x1D520,
+ ["CHcy"]=0x00427,
+ ["chcy"]=0x00447,
+ ["check"]=0x02713,
+ ["checkmark"]=0x02713,
+ ["chi"]=0x003C7,
+ ["cir"]=0x025CB,
+ ["circ"]=0x002C6,
+ ["circeq"]=0x02257,
+ ["circlearrowleft"]=0x021BA,
+ ["circlearrowright"]=0x021BB,
+ ["circledast"]=0x0229B,
+ ["circledcirc"]=0x0229A,
+ ["circleddash"]=0x0229D,
+ ["CircleDot"]=0x02299,
+ ["circledR"]=0x000AE,
+ ["circledS"]=0x024C8,
+ ["CircleMinus"]=0x02296,
+ ["CirclePlus"]=0x02295,
+ ["CircleTimes"]=0x02297,
+ ["cirE"]=0x029C3,
+ ["cire"]=0x02257,
+ ["cirfnint"]=0x02A10,
+ ["cirmid"]=0x02AEF,
+ ["cirscir"]=0x029C2,
+ ["ClockwiseContourIntegral"]=0x02232,
+ ["CloseCurlyDoubleQuote"]=0x0201D,
+ ["CloseCurlyQuote"]=0x02019,
+ ["clubs"]=0x02663,
+ ["clubsuit"]=0x02663,
+ ["Colon"]=0x02237,
+ ["colon"]=0x0003A,
+ ["Colone"]=0x02A74,
+ ["colone"]=0x02254,
+ ["coloneq"]=0x02254,
+ ["comma"]=0x0002C,
+ ["commat"]=0x00040,
+ ["comp"]=0x02201,
+ ["compfn"]=0x02218,
+ ["complement"]=0x02201,
+ ["complexes"]=0x02102,
+ ["cong"]=0x02245,
+ ["congdot"]=0x02A6D,
+ ["Congruent"]=0x02261,
+ ["Conint"]=0x0222F,
+ ["conint"]=0x0222E,
+ ["ContourIntegral"]=0x0222E,
+ ["Copf"]=0x02102,
+ ["copf"]=0x1D554,
+ ["coprod"]=0x02210,
+ ["Coproduct"]=0x02210,
+ ["copy"]=0x000A9,
+ ["copysr"]=0x02117,
+ ["CounterClockwiseContourIntegral"]=0x02233,
+ ["Cross"]=0x02A2F,
+ ["cross"]=0x02717,
+ ["Cscr"]=0x1D49E,
+ ["cscr"]=0x1D4B8,
+ ["csub"]=0x02ACF,
+ ["csube"]=0x02AD1,
+ ["csup"]=0x02AD0,
+ ["csupe"]=0x02AD2,
+ ["ctdot"]=0x022EF,
+ ["cudarrl"]=0x02938,
+ ["cudarrr"]=0x02935,
+ ["cuepr"]=0x022DE,
+ ["cuesc"]=0x022DF,
+ ["cularr"]=0x021B6,
+ ["cularrp"]=0x0293D,
+ ["Cup"]=0x022D3,
+ ["cup"]=0x0222A,
+ ["cupbrcap"]=0x02A48,
+ ["CupCap"]=0x0224D,
+ ["cupcap"]=0x02A46,
+ ["cupcup"]=0x02A4A,
+ ["cupdot"]=0x0228D,
+ ["cupor"]=0x02A45,
+ ["cups"]=0x0222A,
+ ["curarr"]=0x021B7,
+ ["curarrm"]=0x0293C,
+ ["curlyeqprec"]=0x022DE,
+ ["curlyeqsucc"]=0x022DF,
+ ["curlyvee"]=0x022CE,
+ ["curlywedge"]=0x022CF,
+ ["curren"]=0x000A4,
+ ["curvearrowleft"]=0x021B6,
+ ["curvearrowright"]=0x021B7,
+ ["cuvee"]=0x022CE,
+ ["cuwed"]=0x022CF,
+ ["cwconint"]=0x02232,
+ ["cwint"]=0x02231,
+ ["cylcty"]=0x0232D,
+ ["Dagger"]=0x02021,
+ ["Dagger"]=0x02021,
+ ["dagger"]=0x02020,
+ ["dagger"]=0x02020,
+ ["daleth"]=0x02138,
+ ["Darr"]=0x021A1,
+ ["dArr"]=0x021D3,
+ ["darr"]=0x02193,
+ ["dash"]=0x02010,
+ ["Dashv"]=0x02AE4,
+ ["dashv"]=0x022A3,
+ ["dbkarow"]=0x0290F,
+ ["dblac"]=0x002DD,
+ ["Dcaron"]=0x0010E,
+ ["dcaron"]=0x0010F,
+ ["Dcy"]=0x00414,
+ ["dcy"]=0x00434,
+ ["DD"]=0x02145,
+ ["dd"]=0x02146,
+ ["ddagger"]=0x02021,
+ ["ddarr"]=0x021CA,
+ ["DDotrahd"]=0x02911,
+ ["ddotseq"]=0x02A77,
+ ["deg"]=0x000B0,
+ ["Del"]=0x02207,
+ ["Delta"]=0x00394,
+ ["delta"]=0x003B4,
+ ["demptyv"]=0x029B1,
+ ["dfisht"]=0x0297F,
+ ["Dfr"]=0x1D507,
+ ["dfr"]=0x1D521,
+ ["dHar"]=0x02965,
+ ["dharl"]=0x021C3,
+ ["dharr"]=0x021C2,
+ ["DiacriticalAcute"]=0x000B4,
+ ["DiacriticalDot"]=0x002D9,
+ ["DiacriticalDoubleAcute"]=0x002DD,
+ ["DiacriticalGrave"]=0x00060,
+ ["DiacriticalTilde"]=0x002DC,
+ ["diam"]=0x022C4,
+ ["Diamond"]=0x022C4,
+ ["diamond"]=0x022C4,
+ ["diamondsuit"]=0x02666,
+ ["diams"]=0x02666,
+ ["die"]=0x000A8,
+ ["DifferentialD"]=0x02146,
+ ["digamma"]=0x003DD,
+ ["disin"]=0x022F2,
+ ["div"]=0x000F7,
+ ["divide"]=0x000F7,
+ ["divideontimes"]=0x022C7,
+ ["divonx"]=0x022C7,
+ ["DJcy"]=0x00402,
+ ["djcy"]=0x00452,
+ ["dlcorn"]=0x0231E,
+ ["dlcrop"]=0x0230D,
+ ["dollar"]=0x00024,
+ ["Dopf"]=0x1D53B,
+ ["dopf"]=0x1D555,
+ ["Dot"]=0x000A8,
+ ["dot"]=0x002D9,
+ ["DotDot"]=0x020DC,
+ ["doteq"]=0x02250,
+ ["doteqdot"]=0x02251,
+ ["DotEqual"]=0x02250,
+ ["dotminus"]=0x02238,
+ ["dotplus"]=0x02214,
+ ["dotsquare"]=0x022A1,
+ ["doublebarwedge"]=0x02306,
+ ["DoubleContourIntegral"]=0x0222F,
+ ["DoubleDot"]=0x000A8,
+ ["DoubleDownArrow"]=0x021D3,
+ ["DoubleLeftArrow"]=0x021D0,
+ ["DoubleLeftRightArrow"]=0x021D4,
+ ["DoubleLeftTee"]=0x02AE4,
+ ["DoubleLongLeftArrow"]=0x027F8,
+ ["DoubleLongLeftRightArrow"]=0x027FA,
+ ["DoubleLongRightArrow"]=0x027F9,
+ ["DoubleRightArrow"]=0x021D2,
+ ["DoubleRightTee"]=0x022A8,
+ ["DoubleUpArrow"]=0x021D1,
+ ["DoubleUpDownArrow"]=0x021D5,
+ ["DoubleVerticalBar"]=0x02225,
+ ["DownArrow"]=0x02193,
+ ["Downarrow"]=0x021D3,
+ ["downarrow"]=0x02193,
+ ["DownArrowBar"]=0x02913,
+ ["DownArrowUpArrow"]=0x021F5,
+ ["DownBreve"]=0x00311,
+ ["downdownarrows"]=0x021CA,
+ ["downharpoonleft"]=0x021C3,
+ ["downharpoonright"]=0x021C2,
+ ["DownLeftRightVector"]=0x02950,
+ ["DownLeftTeeVector"]=0x0295E,
+ ["DownLeftVector"]=0x021BD,
+ ["DownLeftVectorBar"]=0x02956,
+ ["DownRightTeeVector"]=0x0295F,
+ ["DownRightVector"]=0x021C1,
+ ["DownRightVectorBar"]=0x02957,
+ ["DownTee"]=0x022A4,
+ ["DownTeeArrow"]=0x021A7,
+ ["drbkarow"]=0x02910,
+ ["drcorn"]=0x0231F,
+ ["drcrop"]=0x0230C,
+ ["Dscr"]=0x1D49F,
+ ["dscr"]=0x1D4B9,
+ ["DScy"]=0x00405,
+ ["dscy"]=0x00455,
+ ["dsol"]=0x029F6,
+ ["Dstrok"]=0x00110,
+ ["dstrok"]=0x00111,
+ ["dtdot"]=0x022F1,
+ ["dtri"]=0x025BF,
+ ["dtrif"]=0x025BE,
+ ["duarr"]=0x021F5,
+ ["duhar"]=0x0296F,
+ ["dwangle"]=0x029A6,
+ ["DZcy"]=0x0040F,
+ ["dzcy"]=0x0045F,
+ ["dzigrarr"]=0x027FF,
+ ["Eacute"]=0x000C9,
+ ["eacute"]=0x000E9,
+ ["easter"]=0x02A6E,
+ ["Ecaron"]=0x0011A,
+ ["ecaron"]=0x0011B,
+ ["ecir"]=0x02256,
+ ["Ecirc"]=0x000CA,
+ ["ecirc"]=0x000EA,
+ ["ecolon"]=0x02255,
+ ["Ecy"]=0x0042D,
+ ["ecy"]=0x0044D,
+ ["eDDot"]=0x02A77,
+ ["Edot"]=0x00116,
+ ["eDot"]=0x02251,
+ ["edot"]=0x00117,
+ ["ee"]=0x02147,
+ ["efDot"]=0x02252,
+ ["Efr"]=0x1D508,
+ ["efr"]=0x1D522,
+ ["eg"]=0x02A9A,
+ ["Egrave"]=0x000C8,
+ ["egrave"]=0x000E8,
+ ["egs"]=0x02A96,
+ ["egsdot"]=0x02A98,
+ ["el"]=0x02A99,
+ ["Element"]=0x02208,
+ ["elinters"]=0x0FFFD,
+ ["ell"]=0x02113,
+ ["els"]=0x02A95,
+ ["elsdot"]=0x02A97,
+ ["Emacr"]=0x00112,
+ ["emacr"]=0x00113,
+ ["empty"]=0x02205,
+ ["emptyset"]=0x02205,
+ ["EmptySmallSquare"]=0x025FB,
+ ["emptyv"]=0x02205,
+ ["EmptyVerySmallSquare"]=0x025AB,
+ ["emsp"]=0x02003,
+ ["emsp13"]=0x02004,
+ ["emsp14"]=0x02005,
+ ["ENG"]=0x0014A,
+ ["eng"]=0x0014B,
+ ["ensp"]=0x02002,
+ ["Eogon"]=0x00118,
+ ["eogon"]=0x00119,
+ ["Eopf"]=0x1D53C,
+ ["eopf"]=0x1D556,
+ ["epar"]=0x022D5,
+ ["eparsl"]=0x029E3,
+ ["eplus"]=0x02A71,
+ ["epsi"]=0x003F5,
+ ["epsiv"]=0x003B5,
+ ["eqcirc"]=0x02256,
+ ["eqcolon"]=0x02255,
+ ["eqsim"]=0x02242,
+ ["eqslantgtr"]=0x02A96,
+ ["eqslantless"]=0x02A95,
+ ["Equal"]=0x02A75,
+ ["equals"]=0x0003D,
+ ["EqualTilde"]=0x02242,
+ ["equest"]=0x0225F,
+ ["Equilibrium"]=0x021CC,
+ ["equiv"]=0x02261,
+ ["equivDD"]=0x02A78,
+ ["eqvparsl"]=0x029E5,
+ ["erarr"]=0x02971,
+ ["erDot"]=0x02253,
+ ["Escr"]=0x02130,
+ ["escr"]=0x0212F,
+ ["esdot"]=0x02250,
+ ["Esim"]=0x02A73,
+ ["esim"]=0x02242,
+ ["eta"]=0x003B7,
+ ["ETH"]=0x000D0,
+ ["eth"]=0x000F0,
+ ["Euml"]=0x000CB,
+ ["euml"]=0x000EB,
+ ["excl"]=0x00021,
+ ["exist"]=0x02203,
+ ["Exists"]=0x02203,
+ ["expectation"]=0x02130,
+ ["ExponentialE"]=0x02147,
+ ["exponentiale"]=0x02147,
+ ["fallingdotseq"]=0x02252,
+ ["Fcy"]=0x00424,
+ ["fcy"]=0x00444,
+ ["female"]=0x02640,
+ ["ffilig"]=0x0FB03,
+ ["fflig"]=0x0FB00,
+ ["ffllig"]=0x0FB04,
+ ["Ffr"]=0x1D509,
+ ["ffr"]=0x1D523,
+ ["filig"]=0x0FB01,
+ ["FilledSmallSquare"]=0x025FC,
+ ["FilledVerySmallSquare"]=0x025AA,
+ ["flat"]=0x0266D,
+ ["fllig"]=0x0FB02,
+ ["fltns"]=0x025B1,
+ ["fnof"]=0x00192,
+ ["Fopf"]=0x1D53D,
+ ["fopf"]=0x1D557,
+ ["ForAll"]=0x02200,
+ ["forall"]=0x02200,
+ ["fork"]=0x022D4,
+ ["forkv"]=0x02AD9,
+ ["Fouriertrf"]=0x02131,
+ ["fpartint"]=0x02A0D,
+ ["frac12"]=0x000BD,
+ ["frac13"]=0x02153,
+ ["frac14"]=0x000BC,
+ ["frac15"]=0x02155,
+ ["frac16"]=0x02159,
+ ["frac18"]=0x0215B,
+ ["frac23"]=0x02154,
+ ["frac25"]=0x02156,
+ ["frac34"]=0x000BE,
+ ["frac35"]=0x02157,
+ ["frac38"]=0x0215C,
+ ["frac45"]=0x02158,
+ ["frac56"]=0x0215A,
+ ["frac58"]=0x0215D,
+ ["frac78"]=0x0215E,
+ ["frown"]=0x02322,
+ ["Fscr"]=0x02131,
+ ["fscr"]=0x1D4BB,
+ ["gacute"]=0x001F5,
+ ["Gamma"]=0x00393,
+ ["gamma"]=0x003B3,
+ ["Gammad"]=0x003DC,
+ ["gammad"]=0x003DD,
+ ["gap"]=0x02A86,
+ ["Gbreve"]=0x0011E,
+ ["gbreve"]=0x0011F,
+ ["Gcedil"]=0x00122,
+ ["Gcirc"]=0x0011C,
+ ["gcirc"]=0x0011D,
+ ["Gcy"]=0x00413,
+ ["gcy"]=0x00433,
+ ["Gdot"]=0x00120,
+ ["gdot"]=0x00121,
+ ["gE"]=0x02267,
+ ["ge"]=0x02265,
+ ["gEl"]=0x02A8C,
+ ["gel"]=0x022DB,
+ ["geq"]=0x02265,
+ ["geqq"]=0x02267,
+ ["geqslant"]=0x02A7E,
+ ["ges"]=0x02A7E,
+ ["gescc"]=0x02AA9,
+ ["gesdot"]=0x02A80,
+ ["gesdoto"]=0x02A82,
+ ["gesdotol"]=0x02A84,
+ ["gesl"]=0x022DB,
+ ["gesles"]=0x02A94,
+ ["Gfr"]=0x1D50A,
+ ["gfr"]=0x1D524,
+ ["Gg"]=0x022D9,
+ ["gg"]=0x0226B,
+ ["ggg"]=0x022D9,
+ ["gimel"]=0x02137,
+ ["GJcy"]=0x00403,
+ ["gjcy"]=0x00453,
+ ["gl"]=0x02277,
+ ["gla"]=0x02AA5,
+ ["glE"]=0x02A92,
+ ["glj"]=0x02AA4,
+ ["gnap"]=0x02A8A,
+ ["gnapprox"]=0x02A8A,
+ ["gnE"]=0x02269,
+ ["gne"]=0x02A88,
+ ["gneq"]=0x02A88,
+ ["gneqq"]=0x02269,
+ ["gnsim"]=0x022E7,
+ ["Gopf"]=0x1D53E,
+ ["gopf"]=0x1D558,
+ ["grave"]=0x00060,
+ ["GreaterEqual"]=0x02265,
+ ["GreaterEqualLess"]=0x022DB,
+ ["GreaterFullEqual"]=0x02267,
+ ["GreaterGreater"]=0x02AA2,
+ ["GreaterLess"]=0x02277,
+ ["GreaterSlantEqual"]=0x02A7E,
+ ["GreaterTilde"]=0x02273,
+ ["Gscr"]=0x1D4A2,
+ ["gscr"]=0x0210A,
+ ["gsim"]=0x02273,
+ ["gsime"]=0x02A8E,
+ ["gsiml"]=0x02A90,
+ ["Gt"]=0x0226B,
+ ["gt"]=0x0003E,
+ ["gtcc"]=0x02AA7,
+ ["gtcir"]=0x02A7A,
+ ["gtdot"]=0x022D7,
+ ["gtlPar"]=0x02995,
+ ["gtquest"]=0x02A7C,
+ ["gtrapprox"]=0x02A86,
+ ["gtrarr"]=0x02978,
+ ["gtrdot"]=0x022D7,
+ ["gtreqless"]=0x022DB,
+ ["gtreqqless"]=0x02A8C,
+ ["gtrless"]=0x02277,
+ ["gtrsim"]=0x02273,
+ ["gvertneqq"]=0x02269,
+ ["gvnE"]=0x02269,
+ ["Hacek"]=0x002C7,
+ ["hairsp"]=0x0200A,
+ ["half"]=0x000BD,
+ ["hamilt"]=0x0210B,
+ ["HARDcy"]=0x0042A,
+ ["hardcy"]=0x0044A,
+ ["hArr"]=0x021D4,
+ ["harr"]=0x02194,
+ ["harrcir"]=0x02948,
+ ["harrw"]=0x021AD,
+ ["Hat"]=0x0005E,
+ ["hbar"]=0x0210F,
+ ["Hcirc"]=0x00124,
+ ["hcirc"]=0x00125,
+ ["hearts"]=0x02665,
+ ["heartsuit"]=0x02665,
+ ["hellip"]=0x02026,
+ ["hercon"]=0x022B9,
+ ["Hfr"]=0x0210C,
+ ["hfr"]=0x1D525,
+ ["HilbertSpace"]=0x0210B,
+ ["hksearow"]=0x02925,
+ ["hkswarow"]=0x02926,
+ ["hoarr"]=0x021FF,
+ ["homtht"]=0x0223B,
+ ["hookleftarrow"]=0x021A9,
+ ["hookrightarrow"]=0x021AA,
+ ["Hopf"]=0x0210D,
+ ["hopf"]=0x1D559,
+ ["horbar"]=0x02015,
+ ["HorizontalLine"]=0x02500,
+ ["Hscr"]=0x0210B,
+ ["hscr"]=0x1D4BD,
+ ["hslash"]=0x0210F,
+ ["Hstrok"]=0x00126,
+ ["hstrok"]=0x00127,
+ ["HumpDownHump"]=0x0224E,
+ ["HumpEqual"]=0x0224F,
+ ["hybull"]=0x02043,
+ ["hyphen"]=0x02010,
+ ["Iacute"]=0x000CD,
+ ["iacute"]=0x000ED,
+ ["ic"]=0x02063,
+ ["Icirc"]=0x000CE,
+ ["icirc"]=0x000EE,
+ ["Icy"]=0x00418,
+ ["icy"]=0x00438,
+ ["Idot"]=0x00130,
+ ["IEcy"]=0x00415,
+ ["iecy"]=0x00435,
+ ["iexcl"]=0x000A1,
+ ["iff"]=0x021D4,
+ ["Ifr"]=0x02111,
+ ["ifr"]=0x1D526,
+ ["Igrave"]=0x000CC,
+ ["igrave"]=0x000EC,
+ ["ii"]=0x02148,
+ ["iiiint"]=0x02A0C,
+ ["iiint"]=0x0222D,
+ ["iinfin"]=0x029DC,
+ ["iiota"]=0x02129,
+ ["IJlig"]=0x00132,
+ ["ijlig"]=0x00133,
+ ["Im"]=0x02111,
+ ["Imacr"]=0x0012A,
+ ["imacr"]=0x0012B,
+ ["image"]=0x02111,
+ ["ImaginaryI"]=0x02148,
+ ["imagline"]=0x02110,
+ ["imagpart"]=0x02111,
+ ["imath"]=0x00131,
+ ["imof"]=0x022B7,
+ ["imped"]=0x001B5,
+ ["Implies"]=0x021D2,
+ ["in"]=0x02208,
+ ["incare"]=0x02105,
+ ["infin"]=0x0221E,
+ ["infintie"]=0x029DD,
+ ["inodot"]=0x00131,
+ ["Int"]=0x0222C,
+ ["int"]=0x0222B,
+ ["intcal"]=0x022BA,
+ ["integers"]=0x02124,
+ ["Integral"]=0x0222B,
+ ["intercal"]=0x022BA,
+ ["Intersection"]=0x022C2,
+ ["intlarhk"]=0x02A17,
+ ["intprod"]=0x02A3C,
+ ["InvisibleComma"]=0x02063,
+ ["InvisibleTimes"]=0x02062,
+ ["IOcy"]=0x00401,
+ ["iocy"]=0x00451,
+ ["Iogon"]=0x0012E,
+ ["iogon"]=0x0012F,
+ ["Iopf"]=0x1D540,
+ ["iopf"]=0x1D55A,
+ ["iota"]=0x003B9,
+ ["iprod"]=0x02A3C,
+ ["iquest"]=0x000BF,
+ ["Iscr"]=0x02110,
+ ["iscr"]=0x1D4BE,
+ ["isin"]=0x02208,
+ ["isindot"]=0x022F5,
+ ["isinE"]=0x022F9,
+ ["isins"]=0x022F4,
+ ["isinsv"]=0x022F3,
+ ["isinv"]=0x02208,
+ ["it"]=0x02062,
+ ["Itilde"]=0x00128,
+ ["itilde"]=0x00129,
+ ["Iukcy"]=0x00406,
+ ["iukcy"]=0x00456,
+ ["Iuml"]=0x000CF,
+ ["iuml"]=0x000EF,
+ ["Jcirc"]=0x00134,
+ ["jcirc"]=0x00135,
+ ["Jcy"]=0x00419,
+ ["jcy"]=0x00439,
+ ["Jfr"]=0x1D50D,
+ ["jfr"]=0x1D527,
+ ["jmath"]=0x0006A,
+ ["Jopf"]=0x1D541,
+ ["jopf"]=0x1D55B,
+ ["Jscr"]=0x1D4A5,
+ ["jscr"]=0x1D4BF,
+ ["Jsercy"]=0x00408,
+ ["jsercy"]=0x00458,
+ ["Jukcy"]=0x00404,
+ ["jukcy"]=0x00454,
+ ["kappa"]=0x003BA,
+ ["kappav"]=0x003F0,
+ ["Kcedil"]=0x00136,
+ ["kcedil"]=0x00137,
+ ["Kcy"]=0x0041A,
+ ["kcy"]=0x0043A,
+ ["Kfr"]=0x1D50E,
+ ["kfr"]=0x1D528,
+ ["kgreen"]=0x00138,
+ ["KHcy"]=0x00425,
+ ["khcy"]=0x00445,
+ ["KJcy"]=0x0040C,
+ ["kjcy"]=0x0045C,
+ ["Kopf"]=0x1D542,
+ ["kopf"]=0x1D55C,
+ ["Kscr"]=0x1D4A6,
+ ["kscr"]=0x1D4C0,
+ ["lAarr"]=0x021DA,
+ ["Lacute"]=0x00139,
+ ["lacute"]=0x0013A,
+ ["laemptyv"]=0x029B4,
+ ["lagran"]=0x02112,
+ ["Lambda"]=0x0039B,
+ ["lambda"]=0x003BB,
+ ["Lang"]=0x0300A,
+ ["lang"]=0x02329,
+ ["langd"]=0x02991,
+ ["langle"]=0x02329,
+ ["lap"]=0x02A85,
+ ["Laplacetrf"]=0x02112,
+ ["laquo"]=0x000AB,
+ ["Larr"]=0x0219E,
+ ["lArr"]=0x021D0,
+ ["larr"]=0x02190,
+ ["larrb"]=0x021E4,
+ ["larrbfs"]=0x0291F,
+ ["larrfs"]=0x0291D,
+ ["larrhk"]=0x021A9,
+ ["larrlp"]=0x021AB,
+ ["larrpl"]=0x02939,
+ ["larrsim"]=0x02973,
+ ["larrtl"]=0x021A2,
+ ["lat"]=0x02AAB,
+ ["lAtail"]=0x0291B,
+ ["latail"]=0x02919,
+ ["late"]=0x02AAD,
+ ["lates"]=0x02AAD,
+ ["lBarr"]=0x0290E,
+ ["lbarr"]=0x0290C,
+ ["lbbrk"]=0x03014,
+ ["lbrace"]=0x0007B,
+ ["lbrack"]=0x0005B,
+ ["lbrke"]=0x0298B,
+ ["lbrksld"]=0x0298F,
+ ["lbrkslu"]=0x0298D,
+ ["Lcaron"]=0x0013D,
+ ["lcaron"]=0x0013E,
+ ["Lcedil"]=0x0013B,
+ ["lcedil"]=0x0013C,
+ ["lceil"]=0x02308,
+ ["lcub"]=0x0007B,
+ ["Lcy"]=0x0041B,
+ ["lcy"]=0x0043B,
+ ["ldca"]=0x02936,
+ ["ldquo"]=0x0201C,
+ ["ldquor"]=0x0201E,
+ ["ldrdhar"]=0x02967,
+ ["ldrushar"]=0x0294B,
+ ["ldsh"]=0x021B2,
+ ["lE"]=0x02266,
+ ["le"]=0x02264,
+ ["LeftAngleBracket"]=0x02329,
+ ["LeftArrow"]=0x02190,
+ ["Leftarrow"]=0x021D0,
+ ["leftarrow"]=0x02190,
+ ["LeftArrowBar"]=0x021E4,
+ ["LeftArrowRightArrow"]=0x021C6,
+ ["leftarrowtail"]=0x021A2,
+ ["LeftCeiling"]=0x02308,
+ ["LeftDoubleBracket"]=0x0301A,
+ ["LeftDownTeeVector"]=0x02961,
+ ["LeftDownVector"]=0x021C3,
+ ["LeftDownVectorBar"]=0x02959,
+ ["LeftFloor"]=0x0230A,
+ ["leftharpoondown"]=0x021BD,
+ ["leftharpoonup"]=0x021BC,
+ ["leftleftarrows"]=0x021C7,
+ ["LeftRightArrow"]=0x02194,
+ ["Leftrightarrow"]=0x021D4,
+ ["leftrightarrow"]=0x02194,
+ ["leftrightarrows"]=0x021C6,
+ ["leftrightharpoons"]=0x021CB,
+ ["leftrightsquigarrow"]=0x021AD,
+ ["LeftRightVector"]=0x0294E,
+ ["LeftTee"]=0x022A3,
+ ["LeftTeeArrow"]=0x021A4,
+ ["LeftTeeVector"]=0x0295A,
+ ["leftthreetimes"]=0x022CB,
+ ["LeftTriangle"]=0x022B2,
+ ["LeftTriangleBar"]=0x029CF,
+ ["LeftTriangleEqual"]=0x022B4,
+ ["LeftUpDownVector"]=0x02951,
+ ["LeftUpTeeVector"]=0x02960,
+ ["LeftUpVector"]=0x021BF,
+ ["LeftUpVectorBar"]=0x02958,
+ ["LeftVector"]=0x021BC,
+ ["LeftVectorBar"]=0x02952,
+ ["lEg"]=0x02A8B,
+ ["leg"]=0x022DA,
+ ["leq"]=0x02264,
+ ["leqq"]=0x02266,
+ ["leqslant"]=0x02A7D,
+ ["les"]=0x02A7D,
+ ["lescc"]=0x02AA8,
+ ["lesdot"]=0x02A7F,
+ ["lesdoto"]=0x02A81,
+ ["lesdotor"]=0x02A83,
+ ["lesg"]=0x022DA,
+ ["lesges"]=0x02A93,
+ ["lessapprox"]=0x02A85,
+ ["lessdot"]=0x022D6,
+ ["lesseqgtr"]=0x022DA,
+ ["lesseqqgtr"]=0x02A8B,
+ ["LessEqualGreater"]=0x022DA,
+ ["LessFullEqual"]=0x02266,
+ ["LessGreater"]=0x02276,
+ ["lessgtr"]=0x02276,
+ ["LessLess"]=0x02AA1,
+ ["lesssim"]=0x02272,
+ ["LessSlantEqual"]=0x02A7D,
+ ["LessTilde"]=0x02272,
+ ["lfisht"]=0x0297C,
+ ["lfloor"]=0x0230A,
+ ["Lfr"]=0x1D50F,
+ ["lfr"]=0x1D529,
+ ["lg"]=0x02276,
+ ["lgE"]=0x02A91,
+ ["lHar"]=0x02962,
+ ["lhard"]=0x021BD,
+ ["lharu"]=0x021BC,
+ ["lharul"]=0x0296A,
+ ["lhblk"]=0x02584,
+ ["LJcy"]=0x00409,
+ ["ljcy"]=0x00459,
+ ["Ll"]=0x022D8,
+ ["ll"]=0x0226A,
+ ["llarr"]=0x021C7,
+ ["llcorner"]=0x0231E,
+ ["Lleftarrow"]=0x021DA,
+ ["llhard"]=0x0296B,
+ ["lltri"]=0x025FA,
+ ["Lmidot"]=0x0013F,
+ ["lmidot"]=0x00140,
+ ["lmoust"]=0x023B0,
+ ["lmoustache"]=0x023B0,
+ ["lnap"]=0x02A89,
+ ["lnapprox"]=0x02A89,
+ ["lnE"]=0x02268,
+ ["lne"]=0x02A87,
+ ["lneq"]=0x02A87,
+ ["lneqq"]=0x02268,
+ ["lnsim"]=0x022E6,
+ ["loang"]=0x03018,
+ ["loarr"]=0x021FD,
+ ["lobrk"]=0x0301A,
+ ["LongLeftArrow"]=0x027F5,
+ ["Longleftarrow"]=0x027F8,
+ ["longleftarrow"]=0x027F5,
+ ["LongLeftRightArrow"]=0x027F7,
+ ["Longleftrightarrow"]=0x027FA,
+ ["longleftrightarrow"]=0x027F7,
+ ["longmapsto"]=0x027FC,
+ ["LongRightArrow"]=0x027F6,
+ ["Longrightarrow"]=0x027F9,
+ ["longrightarrow"]=0x027F6,
+ ["looparrowleft"]=0x021AB,
+ ["looparrowright"]=0x021AC,
+ ["lopar"]=0x02985,
+ ["Lopf"]=0x1D543,
+ ["lopf"]=0x1D55D,
+ ["loplus"]=0x02A2D,
+ ["lotimes"]=0x02A34,
+ ["lowast"]=0x02217,
+ ["lowbar"]=0x0005F,
+ ["LowerLeftArrow"]=0x02199,
+ ["LowerRightArrow"]=0x02198,
+ ["loz"]=0x025CA,
+ ["lozenge"]=0x025CA,
+ ["lozf"]=0x029EB,
+ ["lpar"]=0x00028,
+ ["lparlt"]=0x02993,
+ ["lrarr"]=0x021C6,
+ ["lrcorner"]=0x0231F,
+ ["lrhar"]=0x021CB,
+ ["lrhard"]=0x0296D,
+ ["lrtri"]=0x022BF,
+ ["Lscr"]=0x02112,
+ ["lscr"]=0x1D4C1,
+ ["Lsh"]=0x021B0,
+ ["lsh"]=0x021B0,
+ ["lsim"]=0x02272,
+ ["lsime"]=0x02A8D,
+ ["lsimg"]=0x02A8F,
+ ["lsqb"]=0x0005B,
+ ["lsquo"]=0x02018,
+ ["lsquor"]=0x0201A,
+ ["Lstrok"]=0x00141,
+ ["lstrok"]=0x00142,
+ ["Lt"]=0x0226A,
+ ["lt"]=0x0003C,
+ ["ltcc"]=0x02AA6,
+ ["ltcir"]=0x02A79,
+ ["ltdot"]=0x022D6,
+ ["lthree"]=0x022CB,
+ ["ltimes"]=0x022C9,
+ ["ltlarr"]=0x02976,
+ ["ltquest"]=0x02A7B,
+ ["ltri"]=0x025C3,
+ ["ltrie"]=0x022B4,
+ ["ltrif"]=0x025C2,
+ ["ltrPar"]=0x02996,
+ ["lurdshar"]=0x0294A,
+ ["luruhar"]=0x02966,
+ ["lvertneqq"]=0x02268,
+ ["lvnE"]=0x02268,
+ ["macr"]=0x000AF,
+ ["male"]=0x02642,
+ ["malt"]=0x02720,
+ ["maltese"]=0x02720,
+ ["Map"]=0x02905,
+ ["map"]=0x021A6,
+ ["mapsto"]=0x021A6,
+ ["mapstodown"]=0x021A7,
+ ["mapstoleft"]=0x021A4,
+ ["mapstoup"]=0x021A5,
+ ["marker"]=0x025AE,
+ ["mcomma"]=0x02A29,
+ ["Mcy"]=0x0041C,
+ ["mcy"]=0x0043C,
+ ["mdash"]=0x02014,
+ ["mDDot"]=0x0223A,
+ ["measuredangle"]=0x02221,
+ ["MediumSpace"]=0x0205F,
+ ["Mellintrf"]=0x02133,
+ ["Mfr"]=0x1D510,
+ ["mfr"]=0x1D52A,
+ ["mho"]=0x02127,
+ ["micro"]=0x000B5,
+ ["mid"]=0x02223,
+ ["midast"]=0x0002A,
+ ["midcir"]=0x02AF0,
+ ["middot"]=0x000B7,
+ ["minus"]=0x02212,
+ ["minusb"]=0x0229F,
+ ["minusd"]=0x02238,
+ ["minusdu"]=0x02A2A,
+ ["MinusPlus"]=0x02213,
+ ["mlcp"]=0x02ADB,
+ ["mldr"]=0x02026,
+ ["mnplus"]=0x02213,
+ ["models"]=0x022A7,
+ ["Mopf"]=0x1D544,
+ ["mopf"]=0x1D55E,
+ ["mp"]=0x02213,
+ ["Mscr"]=0x02133,
+ ["mscr"]=0x1D4C2,
+ ["mstpos"]=0x0223E,
+ ["mu"]=0x003BC,
+ ["multimap"]=0x022B8,
+ ["mumap"]=0x022B8,
+ ["nabla"]=0x02207,
+ ["Nacute"]=0x00143,
+ ["nacute"]=0x00144,
+ ["nang"]=0x02220,
+ ["nap"]=0x02249,
+ ["napE"]=0x02A70,
+ ["napid"]=0x0224B,
+ ["napos"]=0x00149,
+ ["napprox"]=0x02249,
+ ["natur"]=0x0266E,
+ ["natural"]=0x0266E,
+ ["naturals"]=0x02115,
+ ["nbsp"]=0x000A0,
+ ["nbump"]=0x0224E,
+ ["nbumpe"]=0x0224F,
+ ["ncap"]=0x02A43,
+ ["Ncaron"]=0x00147,
+ ["ncaron"]=0x00148,
+ ["Ncedil"]=0x00145,
+ ["ncedil"]=0x00146,
+ ["ncong"]=0x02247,
+ ["ncongdot"]=0x02A6D,
+ ["ncup"]=0x02A42,
+ ["Ncy"]=0x0041D,
+ ["ncy"]=0x0043D,
+ ["ndash"]=0x02013,
+ ["ne"]=0x02260,
+ ["nearhk"]=0x02924,
+ ["neArr"]=0x021D7,
+ ["nearr"]=0x02197,
+ ["nearrow"]=0x02197,
+ ["nedot"]=0x02250,
+ ["NegativeMediumSpace"]=0x0200B,
+ ["NegativeThickSpace"]=0x0200B,
+ ["NegativeThinSpace"]=0x0200B,
+ ["NegativeVeryThinSpace"]=0x0200B,
+ ["nequiv"]=0x02262,
+ ["nesear"]=0x02928,
+ ["nesim"]=0x02242,
+ ["NestedGreaterGreater"]=0x0226B,
+ ["NestedLessLess"]=0x0226A,
+ ["NewLine"]=0x0000A,
+ ["nexist"]=0x02204,
+ ["nexists"]=0x02204,
+ ["Nfr"]=0x1D511,
+ ["nfr"]=0x1D52B,
+ ["ngE"]=0x02267,
+ ["nge"]=0x02271,
+ ["ngeq"]=0x02271,
+ ["ngeqq"]=0x02267,
+ ["ngeqslant"]=0x02A7E,
+ ["nges"]=0x02A7E,
+ ["nGg"]=0x022D9,
+ ["ngsim"]=0x02275,
+ ["nGt"]=0x0226B,
+ ["ngt"]=0x0226F,
+ ["ngtr"]=0x0226F,
+ ["nGtv"]=0x0226B,
+ ["nhArr"]=0x021CE,
+ ["nharr"]=0x021AE,
+ ["nhpar"]=0x02AF2,
+ ["ni"]=0x0220B,
+ ["nis"]=0x022FC,
+ ["nisd"]=0x022FA,
+ ["niv"]=0x0220B,
+ ["NJcy"]=0x0040A,
+ ["njcy"]=0x0045A,
+ ["nlArr"]=0x021CD,
+ ["nlarr"]=0x0219A,
+ ["nldr"]=0x02025,
+ ["nlE"]=0x02266,
+ ["nle"]=0x02270,
+ ["nLeftarrow"]=0x021CD,
+ ["nleftarrow"]=0x0219A,
+ ["nLeftrightarrow"]=0x021CE,
+ ["nleftrightarrow"]=0x021AE,
+ ["nleq"]=0x02270,
+ ["nleqq"]=0x02266,
+ ["nleqslant"]=0x02A7D,
+ ["nles"]=0x02A7D,
+ ["nless"]=0x0226E,
+ ["nLl"]=0x022D8,
+ ["nlsim"]=0x02274,
+ ["nLt"]=0x0226A,
+ ["nlt"]=0x0226E,
+ ["nltri"]=0x022EA,
+ ["nltrie"]=0x022EC,
+ ["nLtv"]=0x0226A,
+ ["nmid"]=0x02224,
+ ["NoBreak"]=0x02060,
+ ["NonBreakingSpace"]=0x000A0,
+ ["Nopf"]=0x02115,
+ ["nopf"]=0x1D55F,
+ ["Not"]=0x02AEC,
+ ["not"]=0x000AC,
+ ["NotCongruent"]=0x02262,
+ ["NotCupCap"]=0x0226D,
+ ["NotDoubleVerticalBar"]=0x02226,
+ ["NotElement"]=0x02209,
+ ["NotEqual"]=0x02260,
+ ["NotEqualTilde"]=0x02242,
+ ["NotExists"]=0x02204,
+ ["NotGreater"]=0x0226F,
+ ["NotGreaterEqual"]=0x02271,
+ ["NotGreaterFullEqual"]=0x02266,
+ ["NotGreaterGreater"]=0x0226B,
+ ["NotGreaterLess"]=0x02279,
+ ["NotGreaterSlantEqual"]=0x02A7E,
+ ["NotGreaterTilde"]=0x02275,
+ ["NotHumpDownHump"]=0x0224E,
+ ["NotHumpEqual"]=0x0224F,
+ ["notin"]=0x02209,
+ ["notindot"]=0x022F5,
+ ["notinE"]=0x022F9,
+ ["notinva"]=0x02209,
+ ["notinvb"]=0x022F7,
+ ["notinvc"]=0x022F6,
+ ["NotLeftTriangle"]=0x022EA,
+ ["NotLeftTriangleBar"]=0x029CF,
+ ["NotLeftTriangleEqual"]=0x022EC,
+ ["NotLess"]=0x0226E,
+ ["NotLessEqual"]=0x02270,
+ ["NotLessGreater"]=0x02278,
+ ["NotLessLess"]=0x0226A,
+ ["NotLessSlantEqual"]=0x02A7D,
+ ["NotLessTilde"]=0x02274,
+ ["NotNestedGreaterGreater"]=0x02AA2,
+ ["NotNestedLessLess"]=0x02AA1,
+ ["notni"]=0x0220C,
+ ["notniva"]=0x0220C,
+ ["notnivb"]=0x022FE,
+ ["notnivc"]=0x022FD,
+ ["NotPrecedes"]=0x02280,
+ ["NotPrecedesEqual"]=0x02AAF,
+ ["NotPrecedesSlantEqual"]=0x022E0,
+ ["NotReverseElement"]=0x0220C,
+ ["NotRightTriangle"]=0x022EB,
+ ["NotRightTriangleBar"]=0x029D0,
+ ["NotRightTriangleEqual"]=0x022ED,
+ ["NotSquareSubset"]=0x0228F,
+ ["NotSquareSubsetEqual"]=0x022E2,
+ ["NotSquareSuperset"]=0x02290,
+ ["NotSquareSupersetEqual"]=0x022E3,
+ ["NotSubset"]=0x02282,
+ ["NotSubsetEqual"]=0x02288,
+ ["NotSucceeds"]=0x02281,
+ ["NotSucceedsEqual"]=0x02AB0,
+ ["NotSucceedsSlantEqual"]=0x022E1,
+ ["NotSucceedsTilde"]=0x0227F,
+ ["NotSuperset"]=0x02283,
+ ["NotSupersetEqual"]=0x02289,
+ ["NotTilde"]=0x02241,
+ ["NotTildeEqual"]=0x02244,
+ ["NotTildeFullEqual"]=0x02247,
+ ["NotTildeTilde"]=0x02249,
+ ["NotVerticalBar"]=0x02224,
+ ["npar"]=0x02226,
+ ["nparallel"]=0x02226,
+ ["nparsl"]=0x02AFD,
+ ["npart"]=0x02202,
+ ["npolint"]=0x02A14,
+ ["npr"]=0x02280,
+ ["nprcue"]=0x022E0,
+ ["npre"]=0x02AAF,
+ ["nprec"]=0x02280,
+ ["npreceq"]=0x02AAF,
+ ["nrArr"]=0x021CF,
+ ["nrarr"]=0x0219B,
+ ["nrarrc"]=0x02933,
+ ["nrarrw"]=0x0219D,
+ ["nRightarrow"]=0x021CF,
+ ["nrightarrow"]=0x0219B,
+ ["nrtri"]=0x022EB,
+ ["nrtrie"]=0x022ED,
+ ["nsc"]=0x02281,
+ ["nsccue"]=0x022E1,
+ ["nsce"]=0x02AB0,
+ ["Nscr"]=0x1D4A9,
+ ["nscr"]=0x1D4C3,
+ ["nshortmid"]=0x02224,
+ ["nshortparallel"]=0x02226,
+ ["nsim"]=0x02241,
+ ["nsime"]=0x02244,
+ ["nsimeq"]=0x02244,
+ ["nsmid"]=0x02224,
+ ["nspar"]=0x02226,
+ ["nsqsube"]=0x022E2,
+ ["nsqsupe"]=0x022E3,
+ ["nsub"]=0x02284,
+ ["nsubE"]=0x02AC5,
+ ["nsube"]=0x02288,
+ ["nsubset"]=0x02282,
+ ["nsubseteq"]=0x02288,
+ ["nsubseteqq"]=0x02AC5,
+ ["nsucc"]=0x02281,
+ ["nsucceq"]=0x02AB0,
+ ["nsup"]=0x02285,
+ ["nsupE"]=0x02AC6,
+ ["nsupe"]=0x02289,
+ ["nsupset"]=0x02283,
+ ["nsupseteq"]=0x02289,
+ ["nsupseteqq"]=0x02AC6,
+ ["ntgl"]=0x02279,
+ ["Ntilde"]=0x000D1,
+ ["ntilde"]=0x000F1,
+ ["ntlg"]=0x02278,
+ ["ntriangleleft"]=0x022EA,
+ ["ntrianglelefteq"]=0x022EC,
+ ["ntriangleright"]=0x022EB,
+ ["ntrianglerighteq"]=0x022ED,
+ ["nu"]=0x003BD,
+ ["num"]=0x00023,
+ ["numero"]=0x02116,
+ ["numsp"]=0x02007,
+ ["nvap"]=0x0224D,
+ ["nVDash"]=0x022AF,
+ ["nVdash"]=0x022AE,
+ ["nvDash"]=0x022AD,
+ ["nvdash"]=0x022AC,
+ ["nvge"]=0x02265,
+ ["nvgt"]=0x0003E,
+ ["nvHarr"]=0x02904,
+ ["nvinfin"]=0x029DE,
+ ["nvlArr"]=0x02902,
+ ["nvle"]=0x02264,
+ ["nvlt"]=0x0003C,
+ ["nvltrie"]=0x022B4,
+ ["nvrArr"]=0x02903,
+ ["nvrtrie"]=0x022B5,
+ ["nvsim"]=0x0223C,
+ ["nwarhk"]=0x02923,
+ ["nwArr"]=0x021D6,
+ ["nwarr"]=0x02196,
+ ["nwarrow"]=0x02196,
+ ["nwnear"]=0x02927,
+ ["Oacute"]=0x000D3,
+ ["oacute"]=0x000F3,
+ ["oast"]=0x0229B,
+ ["ocir"]=0x0229A,
+ ["Ocirc"]=0x000D4,
+ ["ocirc"]=0x000F4,
+ ["Ocy"]=0x0041E,
+ ["ocy"]=0x0043E,
+ ["odash"]=0x0229D,
+ ["Odblac"]=0x00150,
+ ["odblac"]=0x00151,
+ ["odiv"]=0x02A38,
+ ["odot"]=0x02299,
+ ["odsold"]=0x029BC,
+ ["OElig"]=0x00152,
+ ["oelig"]=0x00153,
+ ["ofcir"]=0x029BF,
+ ["Ofr"]=0x1D512,
+ ["ofr"]=0x1D52C,
+ ["ogon"]=0x002DB,
+ ["Ograve"]=0x000D2,
+ ["ograve"]=0x000F2,
+ ["ogt"]=0x029C1,
+ ["ohbar"]=0x029B5,
+ ["ohm"]=0x02126,
+ ["oint"]=0x0222E,
+ ["olarr"]=0x021BA,
+ ["olcir"]=0x029BE,
+ ["olcross"]=0x029BB,
+ ["olt"]=0x029C0,
+ ["Omacr"]=0x0014C,
+ ["omacr"]=0x0014D,
+ ["Omega"]=0x003A9,
+ ["omega"]=0x003C9,
+ ["omid"]=0x029B6,
+ ["ominus"]=0x02296,
+ ["Oopf"]=0x1D546,
+ ["oopf"]=0x1D560,
+ ["opar"]=0x029B7,
+ ["OpenCurlyDoubleQuote"]=0x0201C,
+ ["OpenCurlyQuote"]=0x02018,
+ ["operp"]=0x029B9,
+ ["oplus"]=0x02295,
+ ["Or"]=0x02A54,
+ ["or"]=0x02228,
+ ["orarr"]=0x021BB,
+ ["ord"]=0x02A5D,
+ ["order"]=0x02134,
+ ["orderof"]=0x02134,
+ ["ordf"]=0x000AA,
+ ["ordm"]=0x000BA,
+ ["origof"]=0x022B6,
+ ["oror"]=0x02A56,
+ ["orslope"]=0x02A57,
+ ["orv"]=0x02A5B,
+ ["oS"]=0x024C8,
+ ["Oscr"]=0x1D4AA,
+ ["oscr"]=0x02134,
+ ["Oslash"]=0x000D8,
+ ["oslash"]=0x000F8,
+ ["osol"]=0x02298,
+ ["Otilde"]=0x000D5,
+ ["otilde"]=0x000F5,
+ ["Otimes"]=0x02A37,
+ ["otimes"]=0x02297,
+ ["otimesas"]=0x02A36,
+ ["Ouml"]=0x000D6,
+ ["ouml"]=0x000F6,
+ ["ovbar"]=0x0233D,
+ ["OverBar"]=0x000AF,
+ ["OverBrace"]=0x0FE37,
+ ["OverBracket"]=0x023B4,
+ ["OverParenthesis"]=0x0FE35,
+ ["par"]=0x02225,
+ ["para"]=0x000B6,
+ ["parallel"]=0x02225,
+ ["parsim"]=0x02AF3,
+ ["parsl"]=0x02AFD,
+ ["part"]=0x02202,
+ ["PartialD"]=0x02202,
+ ["Pcy"]=0x0041F,
+ ["pcy"]=0x0043F,
+ ["percnt"]=0x00025,
+ ["period"]=0x0002E,
+ ["permil"]=0x02030,
+ ["perp"]=0x022A5,
+ ["pertenk"]=0x02031,
+ ["Pfr"]=0x1D513,
+ ["pfr"]=0x1D52D,
+ ["Phi"]=0x003A6,
+ ["phi"]=0x003D5,
+ ["phiv"]=0x003C6,
+ ["phmmat"]=0x02133,
+ ["phone"]=0x0260E,
+ ["Pi"]=0x003A0,
+ ["pi"]=0x003C0,
+ ["pitchfork"]=0x022D4,
+ ["piv"]=0x003D6,
+ ["planck"]=0x0210F,
+ ["planckh"]=0x0210E,
+ ["plankv"]=0x0210F,
+ ["plus"]=0x0002B,
+ ["plusacir"]=0x02A23,
+ ["plusb"]=0x0229E,
+ ["pluscir"]=0x02A22,
+ ["plusdo"]=0x02214,
+ ["plusdu"]=0x02A25,
+ ["pluse"]=0x02A72,
+ ["PlusMinus"]=0x000B1,
+ ["plusmn"]=0x000B1,
+ ["plussim"]=0x02A26,
+ ["plustwo"]=0x02A27,
+ ["pm"]=0x000B1,
+ ["Poincareplane"]=0x0210C,
+ ["pointint"]=0x02A15,
+ ["Popf"]=0x02119,
+ ["popf"]=0x1D561,
+ ["pound"]=0x000A3,
+ ["Pr"]=0x02ABB,
+ ["pr"]=0x0227A,
+ ["prap"]=0x02AB7,
+ ["prcue"]=0x0227C,
+ ["prE"]=0x02AB3,
+ ["pre"]=0x02AAF,
+ ["prec"]=0x0227A,
+ ["precapprox"]=0x02AB7,
+ ["preccurlyeq"]=0x0227C,
+ ["Precedes"]=0x0227A,
+ ["PrecedesEqual"]=0x02AAF,
+ ["PrecedesSlantEqual"]=0x0227C,
+ ["PrecedesTilde"]=0x0227E,
+ ["preceq"]=0x02AAF,
+ ["precnapprox"]=0x02AB9,
+ ["precneqq"]=0x02AB5,
+ ["precnsim"]=0x022E8,
+ ["precsim"]=0x0227E,
+ ["Prime"]=0x02033,
+ ["prime"]=0x02032,
+ ["primes"]=0x02119,
+ ["prnap"]=0x02AB9,
+ ["prnE"]=0x02AB5,
+ ["prnsim"]=0x022E8,
+ ["prod"]=0x0220F,
+ ["Product"]=0x0220F,
+ ["profalar"]=0x0232E,
+ ["profline"]=0x02312,
+ ["profsurf"]=0x02313,
+ ["prop"]=0x0221D,
+ ["Proportion"]=0x02237,
+ ["Proportional"]=0x0221D,
+ ["propto"]=0x0221D,
+ ["prsim"]=0x0227E,
+ ["prurel"]=0x022B0,
+ ["Pscr"]=0x1D4AB,
+ ["pscr"]=0x1D4C5,
+ ["Psi"]=0x003A8,
+ ["psi"]=0x003C8,
+ ["puncsp"]=0x02008,
+ ["Qfr"]=0x1D514,
+ ["qfr"]=0x1D52E,
+ ["qint"]=0x02A0C,
+ ["Qopf"]=0x0211A,
+ ["qopf"]=0x1D562,
+ ["qprime"]=0x02057,
+ ["Qscr"]=0x1D4AC,
+ ["qscr"]=0x1D4C6,
+ ["quaternions"]=0x0210D,
+ ["quatint"]=0x02A16,
+ ["quest"]=0x0003F,
+ ["questeq"]=0x0225F,
+ ["quot"]=0x00022,
+ ["rAarr"]=0x021DB,
+ ["race"]=0x029DA,
+ ["Racute"]=0x00154,
+ ["racute"]=0x00155,
+ ["radic"]=0x0221A,
+ ["raemptyv"]=0x029B3,
+ ["Rang"]=0x0300B,
+ ["rang"]=0x0232A,
+ ["rangd"]=0x02992,
+ ["range"]=0x029A5,
+ ["rangle"]=0x0232A,
+ ["raquo"]=0x000BB,
+ ["Rarr"]=0x021A0,
+ ["rArr"]=0x021D2,
+ ["rarr"]=0x02192,
+ ["rarrap"]=0x02975,
+ ["rarrb"]=0x021E5,
+ ["rarrbfs"]=0x02920,
+ ["rarrc"]=0x02933,
+ ["rarrfs"]=0x0291E,
+ ["rarrhk"]=0x021AA,
+ ["rarrlp"]=0x021AC,
+ ["rarrpl"]=0x02945,
+ ["rarrsim"]=0x02974,
+ ["Rarrtl"]=0x02916,
+ ["rarrtl"]=0x021A3,
+ ["rarrw"]=0x0219D,
+ ["rAtail"]=0x0291C,
+ ["ratail"]=0x0291A,
+ ["ratio"]=0x02236,
+ ["rationals"]=0x0211A,
+ ["RBarr"]=0x02910,
+ ["rBarr"]=0x0290F,
+ ["rbarr"]=0x0290D,
+ ["rbbrk"]=0x03015,
+ ["rbrace"]=0x0007D,
+ ["rbrack"]=0x0005D,
+ ["rbrke"]=0x0298C,
+ ["rbrksld"]=0x0298E,
+ ["rbrkslu"]=0x02990,
+ ["Rcaron"]=0x00158,
+ ["rcaron"]=0x00159,
+ ["Rcedil"]=0x00156,
+ ["rcedil"]=0x00157,
+ ["rceil"]=0x02309,
+ ["rcub"]=0x0007D,
+ ["Rcy"]=0x00420,
+ ["rcy"]=0x00440,
+ ["rdca"]=0x02937,
+ ["rdldhar"]=0x02969,
+ ["rdquo"]=0x0201D,
+ ["rdquor"]=0x0201D,
+ ["rdsh"]=0x021B3,
+ ["Re"]=0x0211C,
+ ["real"]=0x0211C,
+ ["realine"]=0x0211B,
+ ["realpart"]=0x0211C,
+ ["reals"]=0x0211D,
+ ["rect"]=0x025AD,
+ ["reg"]=0x000AE,
+ ["ReverseElement"]=0x0220B,
+ ["ReverseEquilibrium"]=0x021CB,
+ ["ReverseUpEquilibrium"]=0x0296F,
+ ["rfisht"]=0x0297D,
+ ["rfloor"]=0x0230B,
+ ["Rfr"]=0x0211C,
+ ["rfr"]=0x1D52F,
+ ["rHar"]=0x02964,
+ ["rhard"]=0x021C1,
+ ["rharu"]=0x021C0,
+ ["rharul"]=0x0296C,
+ ["rho"]=0x003C1,
+ ["rhov"]=0x003F1,
+ ["RightAngleBracket"]=0x0232A,
+ ["RightArrow"]=0x02192,
+ ["Rightarrow"]=0x021D2,
+ ["rightarrow"]=0x02192,
+ ["RightArrowBar"]=0x021E5,
+ ["RightArrowLeftArrow"]=0x021C4,
+ ["rightarrowtail"]=0x021A3,
+ ["RightCeiling"]=0x02309,
+ ["RightDoubleBracket"]=0x0301B,
+ ["RightDownTeeVector"]=0x0295D,
+ ["RightDownVector"]=0x021C2,
+ ["RightDownVectorBar"]=0x02955,
+ ["RightFloor"]=0x0230B,
+ ["rightharpoondown"]=0x021C1,
+ ["rightharpoonup"]=0x021C0,
+ ["rightleftarrows"]=0x021C4,
+ ["rightleftharpoons"]=0x021CC,
+ ["rightrightarrows"]=0x021C9,
+ ["rightsquigarrow"]=0x0219D,
+ ["RightTee"]=0x022A2,
+ ["RightTeeArrow"]=0x021A6,
+ ["RightTeeVector"]=0x0295B,
+ ["rightthreetimes"]=0x022CC,
+ ["RightTriangle"]=0x022B3,
+ ["RightTriangleBar"]=0x029D0,
+ ["RightTriangleEqual"]=0x022B5,
+ ["RightUpDownVector"]=0x0294F,
+ ["RightUpTeeVector"]=0x0295C,
+ ["RightUpVector"]=0x021BE,
+ ["RightUpVectorBar"]=0x02954,
+ ["RightVector"]=0x021C0,
+ ["RightVectorBar"]=0x02953,
+ ["ring"]=0x002DA,
+ ["risingdotseq"]=0x02253,
+ ["rlarr"]=0x021C4,
+ ["rlhar"]=0x021CC,
+ ["rmoust"]=0x023B1,
+ ["rmoustache"]=0x023B1,
+ ["rnmid"]=0x02AEE,
+ ["roang"]=0x03019,
+ ["roarr"]=0x021FE,
+ ["robrk"]=0x0301B,
+ ["ropar"]=0x02986,
+ ["Ropf"]=0x0211D,
+ ["ropf"]=0x1D563,
+ ["roplus"]=0x02A2E,
+ ["rotimes"]=0x02A35,
+ ["RoundImplies"]=0x02970,
+ ["rpar"]=0x00029,
+ ["rpargt"]=0x02994,
+ ["rppolint"]=0x02A12,
+ ["rrarr"]=0x021C9,
+ ["Rrightarrow"]=0x021DB,
+ ["Rscr"]=0x0211B,
+ ["rscr"]=0x1D4C7,
+ ["Rsh"]=0x021B1,
+ ["rsh"]=0x021B1,
+ ["rsqb"]=0x0005D,
+ ["rsquo"]=0x02019,
+ ["rsquor"]=0x02019,
+ ["rthree"]=0x022CC,
+ ["rtimes"]=0x022CA,
+ ["rtri"]=0x025B9,
+ ["rtrie"]=0x022B5,
+ ["rtrif"]=0x025B8,
+ ["rtriltri"]=0x029CE,
+ ["RuleDelayed"]=0x029F4,
+ ["ruluhar"]=0x02968,
+ ["rx"]=0x0211E,
+ ["Sacute"]=0x0015A,
+ ["sacute"]=0x0015B,
+ ["Sc"]=0x02ABC,
+ ["sc"]=0x0227B,
+ ["scap"]=0x02AB8,
+ ["Scaron"]=0x00160,
+ ["scaron"]=0x00161,
+ ["sccue"]=0x0227D,
+ ["scE"]=0x02AB4,
+ ["sce"]=0x02AB0,
+ ["Scedil"]=0x0015E,
+ ["scedil"]=0x0015F,
+ ["Scirc"]=0x0015C,
+ ["scirc"]=0x0015D,
+ ["scnap"]=0x02ABA,
+ ["scnE"]=0x02AB6,
+ ["scnsim"]=0x022E9,
+ ["scpolint"]=0x02A13,
+ ["scsim"]=0x0227F,
+ ["Scy"]=0x00421,
+ ["scy"]=0x00441,
+ ["sdot"]=0x022C5,
+ ["sdotb"]=0x022A1,
+ ["sdote"]=0x02A66,
+ ["searhk"]=0x02925,
+ ["seArr"]=0x021D8,
+ ["searr"]=0x02198,
+ ["searrow"]=0x02198,
+ ["sect"]=0x000A7,
+ ["semi"]=0x0003B,
+ ["seswar"]=0x02929,
+ ["setminus"]=0x02216,
+ ["setmn"]=0x02216,
+ ["sext"]=0x02736,
+ ["Sfr"]=0x1D516,
+ ["sfr"]=0x1D530,
+ ["sfrown"]=0x02322,
+ ["sharp"]=0x0266F,
+ ["SHCHcy"]=0x00429,
+ ["shchcy"]=0x00449,
+ ["SHcy"]=0x00428,
+ ["shcy"]=0x00448,
+ ["ShortDownArrow"]=0x02193,
+ ["ShortLeftArrow"]=0x02190,
+ ["shortmid"]=0x02223,
+ ["shortparallel"]=0x02225,
+ ["ShortRightArrow"]=0x02192,
+ ["ShortUpArrow"]=0x02191,
+ ["shy"]=0x000AD,
+ ["Sigma"]=0x003A3,
+ ["sigma"]=0x003C3,
+ ["sigmav"]=0x003C2,
+ ["sim"]=0x0223C,
+ ["simdot"]=0x02A6A,
+ ["sime"]=0x02243,
+ ["simeq"]=0x02243,
+ ["simg"]=0x02A9E,
+ ["simgE"]=0x02AA0,
+ ["siml"]=0x02A9D,
+ ["simlE"]=0x02A9F,
+ ["simne"]=0x02246,
+ ["simplus"]=0x02A24,
+ ["simrarr"]=0x02972,
+ ["slarr"]=0x02190,
+ ["SmallCircle"]=0x02218,
+ ["smallsetminus"]=0x02216,
+ ["smashp"]=0x02A33,
+ ["smeparsl"]=0x029E4,
+ ["smid"]=0x02223,
+ ["smile"]=0x02323,
+ ["smt"]=0x02AAA,
+ ["smte"]=0x02AAC,
+ ["smtes"]=0x02AAC,
+ ["SOFTcy"]=0x0042C,
+ ["softcy"]=0x0044C,
+ ["sol"]=0x0002F,
+ ["solb"]=0x029C4,
+ ["solbar"]=0x0233F,
+ ["Sopf"]=0x1D54A,
+ ["sopf"]=0x1D564,
+ ["spades"]=0x02660,
+ ["spadesuit"]=0x02660,
+ ["spar"]=0x02225,
+ ["sqcap"]=0x02293,
+ ["sqcaps"]=0x02293,
+ ["sqcup"]=0x02294,
+ ["sqcups"]=0x02294,
+ ["Sqrt"]=0x0221A,
+ ["sqsub"]=0x0228F,
+ ["sqsube"]=0x02291,
+ ["sqsubset"]=0x0228F,
+ ["sqsubseteq"]=0x02291,
+ ["sqsup"]=0x02290,
+ ["sqsupe"]=0x02292,
+ ["sqsupset"]=0x02290,
+ ["sqsupseteq"]=0x02292,
+ ["squ"]=0x025A1,
+ ["Square"]=0x025A1,
+ ["square"]=0x025A1,
+ ["SquareIntersection"]=0x02293,
+ ["SquareSubset"]=0x0228F,
+ ["SquareSubsetEqual"]=0x02291,
+ ["SquareSuperset"]=0x02290,
+ ["SquareSupersetEqual"]=0x02292,
+ ["SquareUnion"]=0x02294,
+ ["squarf"]=0x025AA,
+ ["squf"]=0x025AA,
+ ["srarr"]=0x02192,
+ ["Sscr"]=0x1D4AE,
+ ["sscr"]=0x1D4C8,
+ ["ssetmn"]=0x02216,
+ ["ssmile"]=0x02323,
+ ["sstarf"]=0x022C6,
+ ["Star"]=0x022C6,
+ ["star"]=0x02606,
+ ["starf"]=0x02605,
+ ["straightepsilon"]=0x003F5,
+ ["straightphi"]=0x003D5,
+ ["strns"]=0x000AF,
+ ["Sub"]=0x022D0,
+ ["sub"]=0x02282,
+ ["subdot"]=0x02ABD,
+ ["subE"]=0x02AC5,
+ ["sube"]=0x02286,
+ ["subedot"]=0x02AC3,
+ ["submult"]=0x02AC1,
+ ["subnE"]=0x02ACB,
+ ["subne"]=0x0228A,
+ ["subplus"]=0x02ABF,
+ ["subrarr"]=0x02979,
+ ["Subset"]=0x022D0,
+ ["subset"]=0x02282,
+ ["subseteq"]=0x02286,
+ ["subseteqq"]=0x02AC5,
+ ["SubsetEqual"]=0x02286,
+ ["subsetneq"]=0x0228A,
+ ["subsetneqq"]=0x02ACB,
+ ["subsim"]=0x02AC7,
+ ["subsub"]=0x02AD5,
+ ["subsup"]=0x02AD3,
+ ["succ"]=0x0227B,
+ ["succapprox"]=0x02AB8,
+ ["succcurlyeq"]=0x0227D,
+ ["Succeeds"]=0x0227B,
+ ["SucceedsEqual"]=0x02AB0,
+ ["SucceedsSlantEqual"]=0x0227D,
+ ["SucceedsTilde"]=0x0227F,
+ ["succeq"]=0x02AB0,
+ ["succnapprox"]=0x02ABA,
+ ["succneqq"]=0x02AB6,
+ ["succnsim"]=0x022E9,
+ ["succsim"]=0x0227F,
+ ["SuchThat"]=0x0220B,
+ ["Sum"]=0x02211,
+ ["sum"]=0x02211,
+ ["sung"]=0x0266A,
+ ["Sup"]=0x022D1,
+ ["sup"]=0x02283,
+ ["sup1"]=0x000B9,
+ ["sup2"]=0x000B2,
+ ["sup3"]=0x000B3,
+ ["supdot"]=0x02ABE,
+ ["supdsub"]=0x02AD8,
+ ["supE"]=0x02AC6,
+ ["supe"]=0x02287,
+ ["supedot"]=0x02AC4,
+ ["Superset"]=0x02283,
+ ["SupersetEqual"]=0x02287,
+ ["suphsol"]=0x02283,
+ ["suphsub"]=0x02AD7,
+ ["suplarr"]=0x0297B,
+ ["supmult"]=0x02AC2,
+ ["supnE"]=0x02ACC,
+ ["supne"]=0x0228B,
+ ["supplus"]=0x02AC0,
+ ["Supset"]=0x022D1,
+ ["supset"]=0x02283,
+ ["supseteq"]=0x02287,
+ ["supseteqq"]=0x02AC6,
+ ["supsetneq"]=0x0228B,
+ ["supsetneqq"]=0x02ACC,
+ ["supsim"]=0x02AC8,
+ ["supsub"]=0x02AD4,
+ ["supsup"]=0x02AD6,
+ ["swarhk"]=0x02926,
+ ["swArr"]=0x021D9,
+ ["swarr"]=0x02199,
+ ["swarrow"]=0x02199,
+ ["swnwar"]=0x0292A,
+ ["szlig"]=0x000DF,
+ ["Tab"]=0x00009,
+ ["target"]=0x02316,
+ ["tau"]=0x003C4,
+ ["tbrk"]=0x023B4,
+ ["Tcaron"]=0x00164,
+ ["tcaron"]=0x00165,
+ ["Tcedil"]=0x00162,
+ ["tcedil"]=0x00163,
+ ["Tcy"]=0x00422,
+ ["tcy"]=0x00442,
+ ["tdot"]=0x020DB,
+ ["telrec"]=0x02315,
+ ["Tfr"]=0x1D517,
+ ["tfr"]=0x1D531,
+ ["there4"]=0x02234,
+ ["Therefore"]=0x02234,
+ ["therefore"]=0x02234,
+ ["Theta"]=0x00398,
+ ["theta"]=0x003B8,
+ ["thetav"]=0x003D1,
+ ["thickapprox"]=0x02248,
+ ["thicksim"]=0x0223C,
+ ["ThickSpace"]=0x02009,
+ ["thinsp"]=0x02009,
+ ["ThinSpace"]=0x02009,
+ ["thkap"]=0x02248,
+ ["thksim"]=0x0223C,
+ ["THORN"]=0x000DE,
+ ["thorn"]=0x000FE,
+ ["Tilde"]=0x0223C,
+ ["tilde"]=0x002DC,
+ ["TildeEqual"]=0x02243,
+ ["TildeFullEqual"]=0x02245,
+ ["TildeTilde"]=0x02248,
+ ["times"]=0x000D7,
+ ["timesb"]=0x022A0,
+ ["timesbar"]=0x02A31,
+ ["timesd"]=0x02A30,
+ ["tint"]=0x0222D,
+ ["toea"]=0x02928,
+ ["top"]=0x022A4,
+ ["topbot"]=0x02336,
+ ["topcir"]=0x02AF1,
+ ["Topf"]=0x1D54B,
+ ["topf"]=0x1D565,
+ ["topfork"]=0x02ADA,
+ ["tosa"]=0x02929,
+ ["tprime"]=0x02034,
+ ["trade"]=0x02122,
+ ["triangle"]=0x025B5,
+ ["triangledown"]=0x025BF,
+ ["triangleleft"]=0x025C3,
+ ["trianglelefteq"]=0x022B4,
+ ["triangleq"]=0x0225C,
+ ["triangleright"]=0x025B9,
+ ["trianglerighteq"]=0x022B5,
+ ["tridot"]=0x025EC,
+ ["trie"]=0x0225C,
+ ["triminus"]=0x02A3A,
+ ["TripleDot"]=0x020DB,
+ ["triplus"]=0x02A39,
+ ["trisb"]=0x029CD,
+ ["tritime"]=0x02A3B,
+ ["trpezium"]=0x0FFFD,
+ ["Tscr"]=0x1D4AF,
+ ["tscr"]=0x1D4C9,
+ ["TScy"]=0x00426,
+ ["tscy"]=0x00446,
+ ["TSHcy"]=0x0040B,
+ ["tshcy"]=0x0045B,
+ ["Tstrok"]=0x00166,
+ ["tstrok"]=0x00167,
+ ["twixt"]=0x0226C,
+ ["twoheadleftarrow"]=0x0219E,
+ ["twoheadrightarrow"]=0x021A0,
+ ["Uacute"]=0x000DA,
+ ["uacute"]=0x000FA,
+ ["Uarr"]=0x0219F,
+ ["uArr"]=0x021D1,
+ ["uarr"]=0x02191,
+ ["Uarrocir"]=0x02949,
+ ["Ubrcy"]=0x0040E,
+ ["ubrcy"]=0x0045E,
+ ["Ubreve"]=0x0016C,
+ ["ubreve"]=0x0016D,
+ ["Ucirc"]=0x000DB,
+ ["ucirc"]=0x000FB,
+ ["Ucy"]=0x00423,
+ ["ucy"]=0x00443,
+ ["udarr"]=0x021C5,
+ ["Udblac"]=0x00170,
+ ["udblac"]=0x00171,
+ ["udhar"]=0x0296E,
+ ["ufisht"]=0x0297E,
+ ["Ufr"]=0x1D518,
+ ["ufr"]=0x1D532,
+ ["Ugrave"]=0x000D9,
+ ["ugrave"]=0x000F9,
+ ["uHar"]=0x02963,
+ ["uharl"]=0x021BF,
+ ["uharr"]=0x021BE,
+ ["uhblk"]=0x02580,
+ ["ulcorn"]=0x0231C,
+ ["ulcorner"]=0x0231C,
+ ["ulcrop"]=0x0230F,
+ ["ultri"]=0x025F8,
+ ["Umacr"]=0x0016A,
+ ["umacr"]=0x0016B,
+ ["uml"]=0x000A8,
+ ["UnderBar"]=0x00332,
+ ["UnderBrace"]=0x0FE38,
+ ["UnderBracket"]=0x023B5,
+ ["UnderParenthesis"]=0x0FE36,
+ ["Union"]=0x022C3,
+ ["UnionPlus"]=0x0228E,
+ ["Uogon"]=0x00172,
+ ["uogon"]=0x00173,
+ ["Uopf"]=0x1D54C,
+ ["uopf"]=0x1D566,
+ ["UpArrow"]=0x02191,
+ ["Uparrow"]=0x021D1,
+ ["uparrow"]=0x02191,
+ ["UpArrowBar"]=0x02912,
+ ["UpArrowDownArrow"]=0x021C5,
+ ["UpDownArrow"]=0x02195,
+ ["Updownarrow"]=0x021D5,
+ ["updownarrow"]=0x02195,
+ ["UpEquilibrium"]=0x0296E,
+ ["upharpoonleft"]=0x021BF,
+ ["upharpoonright"]=0x021BE,
+ ["uplus"]=0x0228E,
+ ["UpperLeftArrow"]=0x02196,
+ ["UpperRightArrow"]=0x02197,
+ ["Upsi"]=0x003D2,
+ ["upsi"]=0x003C5,
+ ["Upsilon"]=0x003A5,
+ ["upsilon"]=0x003C5,
+ ["UpTee"]=0x022A5,
+ ["UpTeeArrow"]=0x021A5,
+ ["upuparrows"]=0x021C8,
+ ["urcorn"]=0x0231D,
+ ["urcorner"]=0x0231D,
+ ["urcrop"]=0x0230E,
+ ["Uring"]=0x0016E,
+ ["uring"]=0x0016F,
+ ["urtri"]=0x025F9,
+ ["Uscr"]=0x1D4B0,
+ ["uscr"]=0x1D4CA,
+ ["utdot"]=0x022F0,
+ ["Utilde"]=0x00168,
+ ["utilde"]=0x00169,
+ ["utri"]=0x025B5,
+ ["utrif"]=0x025B4,
+ ["uuarr"]=0x021C8,
+ ["Uuml"]=0x000DC,
+ ["uuml"]=0x000FC,
+ ["uwangle"]=0x029A7,
+ ["vangrt"]=0x0299C,
+ ["varepsilon"]=0x003B5,
+ ["varkappa"]=0x003F0,
+ ["varnothing"]=0x02205,
+ ["varphi"]=0x003C6,
+ ["varpi"]=0x003D6,
+ ["varpropto"]=0x0221D,
+ ["vArr"]=0x021D5,
+ ["varr"]=0x02195,
+ ["varrho"]=0x003F1,
+ ["varsigma"]=0x003C2,
+ ["varsubsetneq"]=0x0228A,
+ ["varsubsetneqq"]=0x02ACB,
+ ["varsupsetneq"]=0x0228B,
+ ["varsupsetneqq"]=0x02ACC,
+ ["vartheta"]=0x003D1,
+ ["vartriangleleft"]=0x022B2,
+ ["vartriangleright"]=0x022B3,
+ ["Vbar"]=0x02AEB,
+ ["vBar"]=0x02AE8,
+ ["vBarv"]=0x02AE9,
+ ["Vcy"]=0x00412,
+ ["vcy"]=0x00432,
+ ["VDash"]=0x022AB,
+ ["Vdash"]=0x022A9,
+ ["vDash"]=0x022A8,
+ ["vdash"]=0x022A2,
+ ["Vdashl"]=0x02AE6,
+ ["Vee"]=0x022C1,
+ ["vee"]=0x02228,
+ ["veebar"]=0x022BB,
+ ["veeeq"]=0x0225A,
+ ["vellip"]=0x022EE,
+ ["Verbar"]=0x02016,
+ ["verbar"]=0x0007C,
+ ["Vert"]=0x02016,
+ ["vert"]=0x0007C,
+ ["VerticalBar"]=0x02223,
+ ["VerticalLine"]=0x0007C,
+ ["VerticalSeparator"]=0x02758,
+ ["VerticalTilde"]=0x02240,
+ ["VeryThinSpace"]=0x0200A,
+ ["Vfr"]=0x1D519,
+ ["vfr"]=0x1D533,
+ ["vltri"]=0x022B2,
+ ["vnsub"]=0x02282,
+ ["vnsup"]=0x02283,
+ ["Vopf"]=0x1D54D,
+ ["vopf"]=0x1D567,
+ ["vprop"]=0x0221D,
+ ["vrtri"]=0x022B3,
+ ["Vscr"]=0x1D4B1,
+ ["vscr"]=0x1D4CB,
+ ["vsubnE"]=0x02ACB,
+ ["vsubne"]=0x0228A,
+ ["vsupnE"]=0x02ACC,
+ ["vsupne"]=0x0228B,
+ ["Vvdash"]=0x022AA,
+ ["vzigzag"]=0x0299A,
+ ["Wcirc"]=0x00174,
+ ["wcirc"]=0x00175,
+ ["wedbar"]=0x02A5F,
+ ["Wedge"]=0x022C0,
+ ["wedge"]=0x02227,
+ ["wedgeq"]=0x02259,
+ ["weierp"]=0x02118,
+ ["Wfr"]=0x1D51A,
+ ["wfr"]=0x1D534,
+ ["Wopf"]=0x1D54E,
+ ["wopf"]=0x1D568,
+ ["wp"]=0x02118,
+ ["wr"]=0x02240,
+ ["wreath"]=0x02240,
+ ["Wscr"]=0x1D4B2,
+ ["wscr"]=0x1D4CC,
+ ["xcap"]=0x022C2,
+ ["xcirc"]=0x025EF,
+ ["xcup"]=0x022C3,
+ ["xdtri"]=0x025BD,
+ ["Xfr"]=0x1D51B,
+ ["xfr"]=0x1D535,
+ ["xhArr"]=0x027FA,
+ ["xharr"]=0x027F7,
+ ["Xi"]=0x0039E,
+ ["xi"]=0x003BE,
+ ["xlArr"]=0x027F8,
+ ["xlarr"]=0x027F5,
+ ["xmap"]=0x027FC,
+ ["xnis"]=0x022FB,
+ ["xodot"]=0x02A00,
+ ["Xopf"]=0x1D54F,
+ ["xopf"]=0x1D569,
+ ["xoplus"]=0x02A01,
+ ["xotime"]=0x02A02,
+ ["xrArr"]=0x027F9,
+ ["xrarr"]=0x027F6,
+ ["Xscr"]=0x1D4B3,
+ ["xscr"]=0x1D4CD,
+ ["xsqcup"]=0x02A06,
+ ["xuplus"]=0x02A04,
+ ["xutri"]=0x025B3,
+ ["xvee"]=0x022C1,
+ ["xwedge"]=0x022C0,
+ ["Yacute"]=0x000DD,
+ ["yacute"]=0x000FD,
+ ["YAcy"]=0x0042F,
+ ["yacy"]=0x0044F,
+ ["Ycirc"]=0x00176,
+ ["ycirc"]=0x00177,
+ ["Ycy"]=0x0042B,
+ ["ycy"]=0x0044B,
+ ["yen"]=0x000A5,
+ ["Yfr"]=0x1D51C,
+ ["yfr"]=0x1D536,
+ ["YIcy"]=0x00407,
+ ["yicy"]=0x00457,
+ ["Yopf"]=0x1D550,
+ ["yopf"]=0x1D56A,
+ ["Yscr"]=0x1D4B4,
+ ["yscr"]=0x1D4CE,
+ ["YUcy"]=0x0042E,
+ ["yucy"]=0x0044E,
+ ["Yuml"]=0x00178,
+ ["yuml"]=0x000FF,
+ ["Zacute"]=0x00179,
+ ["zacute"]=0x0017A,
+ ["Zcaron"]=0x0017D,
+ ["zcaron"]=0x0017E,
+ ["Zcy"]=0x00417,
+ ["zcy"]=0x00437,
+ ["Zdot"]=0x0017B,
+ ["zdot"]=0x0017C,
+ ["zeetrf"]=0x02128,
+ ["ZeroWidthSpace"]=0x0200B,
+ ["zeta"]=0x003B6,
+ ["Zfr"]=0x02128,
+ ["zfr"]=0x1D537,
+ ["ZHcy"]=0x00416,
+ ["zhcy"]=0x00436,
+ ["zigrarr"]=0x021DD,
+ ["Zopf"]=0x02124,
+ ["zopf"]=0x1D56B,
+ ["Zscr"]=0x1D4B5,
+ ["zscr"]=0x1D4CF,
+
+ ["plusminus"]=0x000B1,
+ ["minusplus"]=0x02213,
+ ["cdots"]=0x2026,
+
+}
diff --git a/tex/context/base/math-eul.mkii b/tex/context/base/math-eul.mkii
new file mode 100644
index 000000000..7552957a8
--- /dev/null
+++ b/tex/context/base/math-eul.mkii
@@ -0,0 +1,277 @@
+%D \module
+%D [ file=math-eul,
+%D version=2003.02.03,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Virtual Euler Specials,
+%D author={Hans Hagen \& Taco Hoekwater \& Adam Lindsay},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details. Further modified by Adam Lindsay.
+
+\unprotect
+
+%D We follow the following mappings from type-eul:
+%D
+%D mr [MathRoman] [Euler-Roman] [zeurm10]
+
+%D mi [MathItalic] [Euler-Italic] [eufm10]
+
+%D ex [MathExtension] [Euler-Extension] [zeuex10]
+%D sy [MathSymbol] [Euler-Symbol] [zeusm10]
+
+%D mb [MathBeta] [Charter-Roman] [bchr8r] XXX
+%D mc [MathGamma] [Euler-Fraktur] [eufm10] XXX
+%D
+%D The inclusion of Bitstream Charter was originally for the text accents.
+%D Obviously, it's not a proper ``MathBeta'' font.
+
+%D The varrho and varsigma characters don't exist in eulervm,
+%D so we point at the normal types.
+
+\definefamilysynonym [eul] [calligraphic] [sy]
+\definefamilysynonym [eul] [oldstyle] [mi]
+\definefamilysynonym [eul] [gothic] [mi]
+\definefamilysynonym [eul] [fraktur] [mi]
+
+\definefamilysynonym [eul] [lcgreek] [mr]
+\definefamilysynonym [eul] [ucgreek] [mr]
+\definefamilysynonym [eul] [vargreek] [mr]
+
+%% Well, you don't know until you try!
+%\definefamilysynonym [eul] [accents] [Serif]
+
+\startmathcollection [eul]
+
+\definemathsymbol [varrho] [nothing] [vargreek] ["1A]
+\definemathsymbol [varsigma] [nothing] [vargreek] ["1B]
+
+%D Changes necessitated by collapsing mr \& mi into one:
+\definemathsymbol [imath] [nothing] [mr] ["7B]
+\definemathsymbol [jmath] [nothing] [mr] ["7C]
+\definemathsymbol [ell] [nothing] [mr] ["60]
+\definemathsymbol [wp] [nothing] [mr] ["7D]
+\definemathsymbol [partial] [nothing] [mr] ["40]
+
+\definemathsymbol [flat] [ord] [mr] ["5B]
+\definemathsymbol [natural] [ord] [mr] ["5C]
+\definemathsymbol [sharp] [ord] [mr] ["5D]
+
+\definemathsymbol [triangleleft] [bin] [mr] ["2F]
+\definemathsymbol [triangleright][bin] [mr] ["2E]
+
+\definemathsymbol [star] [bin] [mr] ["3F]
+
+\definemathsymbol [smile] [rel] [mr] ["5E]
+\definemathsymbol [frown] [rel] [mr] ["5F]
+\definemathsymbol [leftharpoonup] [rel] [mr] ["28]
+\definemathsymbol [leftharpoondown] [rel] [mr] ["29]
+\definemathsymbol [rightharpoonup] [rel] [mr] ["2A]
+\definemathsymbol [rightharpoondown] [rel] [mr] ["2B]
+\definemathsymbol [lhook] [rel] [mr] ["2C]
+\definemathsymbol [rhook] [rel] [mr] ["2D]
+
+\definemathsymbol [mathperiod] [ord] [mr] ["3A]
+\definemathsymbol [textperiod] [punct] [mr] ["3A]
+
+\definemathsymbol [mathcomma] [ord] [mr] ["3B]
+\definemathsymbol [textcomma] [punct] [mr] ["3B]
+
+\definemathsymbol [ldotp] [punct] [mr] ["3A]
+
+% extras from AMS:
+\definemathsymbol [hslash] [ord] [mr] ["80] %beauty over truth
+
+\stopmathcollection
+
+\startmathcollection [eul]
+% Ugh. no way around this to keep it compact in the font defs.
+
+\definemathcharacter [a] [alpha] [mr] ["61]
+\definemathcharacter [b] [alpha] [mr] ["62]
+\definemathcharacter [c] [alpha] [mr] ["63]
+\definemathcharacter [d] [alpha] [mr] ["64]
+\definemathcharacter [e] [alpha] [mr] ["65]
+\definemathcharacter [f] [alpha] [mr] ["66]
+\definemathcharacter [g] [alpha] [mr] ["67]
+\definemathcharacter [h] [alpha] [mr] ["68]
+\definemathcharacter [i] [alpha] [mr] ["69]
+\definemathcharacter [j] [alpha] [mr] ["6A]
+\definemathcharacter [k] [alpha] [mr] ["6B]
+\definemathcharacter [l] [alpha] [mr] ["6C]
+\definemathcharacter [m] [alpha] [mr] ["6D]
+\definemathcharacter [n] [alpha] [mr] ["6E]
+\definemathcharacter [o] [alpha] [mr] ["6F]
+\definemathcharacter [p] [alpha] [mr] ["70]
+\definemathcharacter [q] [alpha] [mr] ["71]
+\definemathcharacter [r] [alpha] [mr] ["72]
+\definemathcharacter [s] [alpha] [mr] ["73]
+\definemathcharacter [t] [alpha] [mr] ["74]
+\definemathcharacter [u] [alpha] [mr] ["75]
+\definemathcharacter [v] [alpha] [mr] ["76]
+\definemathcharacter [w] [alpha] [mr] ["77]
+\definemathcharacter [x] [alpha] [mr] ["78]
+\definemathcharacter [y] [alpha] [mr] ["79]
+\definemathcharacter [z] [alpha] [mr] ["7A]
+
+\definemathcharacter [A] [alpha] [mr] ["41]
+\definemathcharacter [B] [alpha] [mr] ["42]
+\definemathcharacter [C] [alpha] [mr] ["43]
+\definemathcharacter [D] [alpha] [mr] ["44]
+\definemathcharacter [E] [alpha] [mr] ["45]
+\definemathcharacter [F] [alpha] [mr] ["46]
+\definemathcharacter [G] [alpha] [mr] ["47]
+\definemathcharacter [H] [alpha] [mr] ["48]
+\definemathcharacter [I] [alpha] [mr] ["49]
+\definemathcharacter [J] [alpha] [mr] ["4A]
+\definemathcharacter [K] [alpha] [mr] ["4B]
+\definemathcharacter [L] [alpha] [mr] ["4C]
+\definemathcharacter [M] [alpha] [mr] ["4D]
+\definemathcharacter [N] [alpha] [mr] ["4E]
+\definemathcharacter [O] [alpha] [mr] ["4F]
+\definemathcharacter [P] [alpha] [mr] ["50]
+\definemathcharacter [Q] [alpha] [mr] ["51]
+\definemathcharacter [R] [alpha] [mr] ["52]
+\definemathcharacter [S] [alpha] [mr] ["53]
+\definemathcharacter [T] [alpha] [mr] ["54]
+\definemathcharacter [U] [alpha] [mr] ["55]
+\definemathcharacter [V] [alpha] [mr] ["56]
+\definemathcharacter [W] [alpha] [mr] ["57]
+\definemathcharacter [X] [alpha] [mr] ["58]
+\definemathcharacter [Y] [alpha] [mr] ["59]
+\definemathcharacter [Z] [alpha] [mr] ["5A]
+
+\stopmathcollection
+
+\startmathcollection [eul]
+
+\definemathcharacter [!] [close] [sy] ["A1]
+\definemathcharacter [(] [open] [sy] ["A8]
+\definemathcharacter [)] [close] [sy] ["A9]
+\definemathcharacter [+] [bin] [sy] ["AB]
+\definemathcharacter [:] [rel] [sy] ["BA]
+\definemathcharacter [;] [punct] [sy] ["BB]
+\definemathcharacter [=] [rel] [sy] ["BD]
+\definemathcharacter [?] [close] [sy] ["BF]
+\definemathcharacter [91] [open] [sy] ["DB] % [
+\definemathcharacter [93] [close] [sy] ["DD] % ]
+
+\definemathcharacter [,] [punct] [mr] ["3B]
+\definemathcharacter [.] [ord] [mr] ["3A]
+\definemathcharacter [/] [ord] [mr] ["3D]
+\definemathcharacter [<] [rel] [mr] ["3C]
+\definemathcharacter [>] [rel] [mr] ["3E]
+
+\stopmathcollection
+
+\startmathcollection [eul]
+
+\definemathcharacter [(] [nothing] [sy] ["A8] [ex] ["00]
+\definemathcharacter [)] [nothing] [sy] ["A9] [ex] ["01]
+\definemathcharacter [91] [nothing] [sy] ["DB] [ex] ["02] % [
+\definemathcharacter [93] [nothing] [sy] ["DD] [ex] ["03] % ]
+\definemathcharacter [/] [nothing] [mr] ["3D] [ex] ["0E]
+
+\stopmathcollection
+
+\startmathcollection [eul]
+
+\definemathsymbol [hbar] [nothing] [mr] ["80]
+
+\stopmathcollection
+
+\startmathcollection [eul]
+
+\definemathsymbol [ddagger] [bin] [sy] ["7A]
+\definemathsymbol [dagger] [bin] [sy] ["79]
+
+\stopmathcollection
+
+\startmathcollection [eul]
+
+\definemathsymbol [colon] [punct] [sy] ["BA]
+
+\stopmathcollection
+
+%D This used to be very hackish; it brought in text
+%D accents from the well-matched Bitstream Charter.
+
+%D But now, these characters don't exist. I would prefer to pull
+%D them from the text font, but I don't know how.
+%D Instead, I'm just pointing to null characters!
+
+\startmathcollection [eul]
+
+\definemathsymbol [acute] [accent] [mr] ["90]
+\definemathsymbol [grave] [accent] [mr] ["91]
+\definemathsymbol [ddot] [accent] [mr] ["92]
+\definemathsymbol [tilde] [accent] [mr] ["93]
+\definemathsymbol [bar] [accent] [mr] ["94]
+\definemathsymbol [breve] [accent] [mr] ["95]
+\definemathsymbol [check] [accent] [mr] ["96]
+\definemathsymbol [hat] [accent] [mr] ["97]
+\definemathsymbol [dot] [accent] [mr] ["98]
+%\definemathsymbol [acute] [accent] [accents] ["B4]
+%\definemathsymbol [grave] [accent] [accents] ["1E]
+%\definemathsymbol [ddot] [accent] [accents] ["A8]
+%\definemathsymbol [tilde] [accent] [accents] ["98]
+%\definemathsymbol [bar] [accent] [accents] ["AF]
+%\definemathsymbol [breve] [accent] [accents] ["0B]
+%\definemathsymbol [check] [accent] [accents] ["10]
+%\definemathsymbol [hat] [accent] [accents] ["5E]
+%\definemathsymbol [dot] [accent] [accents] ["01]
+
+\definemathsymbol [vec] [accent] [mr] ["7E] % [ord]
+\definemathsymbol [hat] [accent] [sy] ["DE]
+
+\stopmathcollection
+
+\startmathcollection [eul]
+
+\definemathsymbol [lgroup] [open] [sy] ["A8] [ex] ["3A] % ?
+\definemathsymbol [rgroup] [close] [sy] ["A9] [ex] ["3B] % ?
+
+\stopmathcollection
+
+\startmathcollection [eul]
+
+\definemathsymbol [dag] [box] [sy] ["79]
+\definemathsymbol [ddag] [box] [sy] ["7A]
+\definemathsymbol [S] [box] [sy] ["78]
+\definemathsymbol [P] [box] [sy] ["7B]
+
+\stopmathcollection
+
+%D Aditya's additionl definitions:
+
+\startmathcollection[eul:texnansi]
+ \definemathsymbol [acute] [accent] [tf] ["13]
+ \definemathsymbol [grave] [accent] [tf] ["12]
+ \definemathsymbol [ddot] [accent] [tf] ["A8]
+ \definemathsymbol [tilde] [accent] [tf] ["98]
+ \definemathsymbol [bar] [accent] [tf] ["16]
+ \definemathsymbol [breve] [accent] [tf] ["15]
+ \definemathsymbol [check] [accent] [tf] ["14]
+ \definemathsymbol [hat] [accent] [tf] ["88]
+ \definemathsymbol [dot] [accent] [tf] ["5]
+ % Why is mathring not defined??
+ \definemathsymbol [mathring] [accent] [tf] ["17]
+\stopmathcollection
+
+\startmathcollection[eul:ec]
+ \definemathsymbol [acute] [accent] [tf] ["1]
+ \definemathsymbol [grave] [accent] [tf] ["0]
+ \definemathsymbol [ddot] [accent] [tf] ["4]
+ \definemathsymbol [tilde] [accent] [tf] ["3]
+ \definemathsymbol [bar] [accent] [tf] ["9]
+ \definemathsymbol [breve] [accent] [tf] ["8]
+ \definemathsymbol [check] [accent] [tf] ["7]
+ \definemathsymbol [hat] [accent] [tf] ["2]
+ \definemathsymbol [dot] [accent] [tf] ["A]
+ % Why is mathring not defined??
+ \definemathsymbol [mathring] [accent] [tf] ["6]
+\stopmathcollection
+
+\protect \endinput
diff --git a/tex/context/base/math-ext.lua b/tex/context/base/math-ext.lua
new file mode 100644
index 000000000..673103677
--- /dev/null
+++ b/tex/context/base/math-ext.lua
@@ -0,0 +1,154 @@
+if not modules then modules = { } end modules ['math-ext'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
+
+mathematics = mathematics or { }
+characters = characters or { }
+
+mathematics.extras = mathematics.extras or { }
+characters.math = characters.math or { }
+
+local chardata = characters.data
+local mathdata = characters.math
+
+function mathematics.extras.add(unicode,t)
+ local min, max = mathematics.extrabase, mathematics.privatebase - 1
+ if unicode >= min and unicode <= max then
+ mathdata[unicode], chardata[unicode] = t, t
+ else
+ logs.report("math extra","extra U+%04X should be in range U+%04X - U+%04X",unicode,min,max)
+ end
+end
+
+function mathematics.extras.copy(tfmdata)
+ local math_parameters = tfmdata.math_parameters
+ local MathConstants = tfmdata.MathConstants
+ if (math_parameters and next(math_parameters)) or (MathConstants and next(MathConstants)) then
+ local characters = tfmdata.characters
+ for unicode, extradesc in next, mathdata do
+ -- always, because in an intermediate step we can have a non math font
+ local extrachar = characters[unicode]
+ local nextinsize = extradesc.nextinsize
+ if nextinsize then
+ for i=1,#nextinsize do
+ local nextslot = nextinsize[i]
+ local nextbase = characters[nextslot]
+ if nextbase then
+ local nextnext = nextbase and nextbase.next
+ if nextnext then
+ local nextchar = characters[nextnext]
+ if nextchar then
+ if trace_virtual then
+ logs.report("math extra","extra U+%04X in %s at %s maps on U+%04X (class: %s, name: %s)",unicode,file.basename(tfmdata.fullname),tfmdata.size,nextslot,extradesc.mathclass or "?",extradesc.mathname or "?")
+ end
+ characters[unicode] = nextchar
+ break
+ end
+ end
+ end
+ end
+ if not characters[unicode] then
+ for i=1,#nextinsize do
+ local nextbase = characters[nextinsize[i]]
+ if nextbase then
+ characters[unicode] = nextchar
+ break
+ end
+ end
+ end
+ end
+ end
+ else
+ -- let's not waste time on non-math
+ end
+end
+
+table.insert(fonts.tfm.mathactions,mathematics.extras.copy)
+
+-- 0xFE302 -- 0xFE320 for accents
+
+mathematics.extras.add(0xFE302, {
+ category="mn",
+ description="WIDE MATHEMATICAL HAT",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="accent",
+ mathname="widehat",
+ mathstretch="h",
+ unicodeslot=0xFE302,
+ nextinsize={ 0x00302, 0x0005E },
+} )
+
+mathematics.extras.add(0xFE303, {
+ category="mn",
+ cjkwd="a",
+ description="WIDE MATHEMATICAL TILDE",
+ direction="nsm",
+ linebreak="cm",
+ mathclass="accent",
+ mathname="widetilde",
+ mathstretch="h",
+ unicodeslot=0xFE303,
+ nextinsize={ 0x00303, 0x0007E },
+} )
+
+-- 0xFE321 -- 0xFE340 for missing characters
+
+mathematics.extras.add(0xFE321, {
+ category="sm",
+ description="MATHEMATICAL SHORT BAR",
+-- direction="on",
+-- linebreak="nu",
+ mathclass="relation",
+ mathname="mapstochar",
+ unicodeslot=0xFE321,
+} )
+
+mathematics.extras.add(0xFE322, {
+ category="sm",
+ description="MATHEMATICAL LEFT HOOK",
+ mathclass="relation",
+ mathname="lhook",
+ unicodeslot=0xFE322,
+} )
+
+mathematics.extras.add(0xFE323, {
+ category="sm",
+ description="MATHEMATICAL RIGHT HOOK",
+ mathclass="relation",
+ mathname="rhook",
+ unicodeslot=0xFE323,
+} )
+
+--~ mathematics.extras.add(0xFE304, {
+--~ category="sm",
+--~ description="TOP AND BOTTOM PARENTHESES",
+--~ direction="on",
+--~ linebreak="al",
+--~ mathclass="doubleaccent",
+--~ mathname="doubleparent",
+--~ unicodeslot=0xFE304,
+--~ accents={ 0x023DC, 0x023DD },
+--~ } )
+
+--~ mathematics.extras.add(0xFE305, {
+--~ category="sm",
+--~ description="TOP AND BOTTOM BRACES",
+--~ direction="on",
+--~ linebreak="al",
+--~ mathclass="doubleaccent",
+--~ mathname="doublebrace",
+--~ unicodeslot=0xFE305,
+--~ accents={ 0x023DE, 0x023DF },
+--~ } )
+
+--~ \Umathchardef\braceld="0 "1 "FF07A
+--~ \Umathchardef\bracerd="0 "1 "FF07B
+--~ \Umathchardef\bracelu="0 "1 "FF07C
+--~ \Umathchardef\braceru="0 "1 "FF07D
diff --git a/tex/context/base/math-for.mkiv b/tex/context/base/math-for.mkiv
new file mode 100644
index 000000000..e33276d53
--- /dev/null
+++ b/tex/context/base/math-for.mkiv
@@ -0,0 +1,79 @@
+%D \module
+%D [ file=strc-mat,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Math Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE / Hans Hagen]
+%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 / Math Formulas}
+
+%D This module only provides the code for defining formulas and
+%D fetching parameters. The action takes place later.
+
+\unprotect
+
+\let\currentformula\s!unknown
+
+\def\formulaparameter #1{\csname\doformulaparameter{\??fm\currentformula}#1\endcsname}
+\def\formulaparameterhash#1{\doformulaparameterhash {\??fm\currentformula}#1}
+
+\def\doformulaparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doformulaparentparameter \csname#1\s!parent\endcsname#2\fi}
+\def\doformulaparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doformulaparentparameterhash\csname#1\s!parent\endcsname#2\fi}
+
+\def\detokenizedformulaparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??fm\currentformula#1\endcsname}}
+
+\def\doformulaparentparameter #1#2{\ifx#1\relax\s!empty\else\doformulaparameter #1#2\fi}
+\def\doformulaparentparameterhash#1#2{\ifx#1\relax \else\doformulaparameterhash#1#2\fi}
+
+\def\dosetformulaattributes#1#2% style color
+ {\edef\fontattributehash {\formulaparameterhash#1}%
+ \edef\colorattributehash{\formulaparameterhash#2}%
+ \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
+ \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
+
+\def\getformulaparameters{\getparameters[\??fm]}
+
+%D \macros
+%D {setupformulas}
+
+\newtoks \everysetupformulas
+
+\unexpanded\def\setupformulas
+ {\dodoubleempty\dosetupformulas}
+
+\def\dosetupformulas[#1][#2]%
+ {\ifsecondargument
+ \edef\currentformula{#1}%
+ \getparameters[\??fm#1][#2]%
+ \else
+% \let\currentformula\v!formula % hm
+ \let\currentformula\empty
+ \getparameters[\??fm][#1]%
+ \fi
+ \the\everysetupformulas
+ \let\currentformula\empty}
+
+%D Not yet cleanup up:
+
+%D \macros
+%D {setuptextformulas}
+%D
+%D This command sets up in||line math. Most features deals
+%D with grid snapping and are experimental.
+
+\newtoks \everysetuptextformulas
+
+\unexpanded\def\setuptextformulas
+ {\dosingleempty\dosetuptextformulas}
+
+\def\dosetuptextformulas[#1]%
+ {\getparameters[\??mt][#1]%
+ \the\everysetuptextformulas}
+
+\protect \endinput
diff --git a/tex/context/base/math-fou.mkii b/tex/context/base/math-fou.mkii
new file mode 100644
index 000000000..8a72f1288
--- /dev/null
+++ b/tex/context/base/math-fou.mkii
@@ -0,0 +1,196 @@
+%D \module
+%D [ file=math-fou,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Fourier Specials,
+%D author={Michel Biovani \& Hans Hagen},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% see end of file for todo
+
+\unprotect
+
+\startmathcollection [fou]
+
+ \definemathsymbol [Gamma] [alpha] [mi] ["00]
+ \definemathsymbol [Delta] [alpha] [mi] ["01]
+ \definemathsymbol [Theta] [alpha] [mi] ["02]
+ \definemathsymbol [Lambda] [alpha] [mi] ["03]
+ \definemathsymbol [Xi] [alpha] [mi] ["04]
+ \definemathsymbol [Pi] [alpha] [mi] ["05]
+ \definemathsymbol [Sigma] [alpha] [mi] ["06]
+ \definemathsymbol [Upsilon] [alpha] [mi] ["07]
+ \definemathsymbol [Phi] [alpha] [mi] ["08]
+ \definemathsymbol [Psi] [alpha] [mi] ["09]
+ \definemathsymbol [Omega] [alpha] [mi] ["0A]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathcharacter [+] [bin] [sy] ["80]
+ \definemathcharacter [=] [rel] [sy] ["81]
+ \definemathcharacter [<] [rel] [sy] ["82]
+ \definemathcharacter [>] [rel] [sy] ["83]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathsymbol [leqslant] [rel] [sy] ["84]
+ \definemathsymbol [geqslant] [rel] [sy] ["85]
+ \definemathsymbol [parallelslant] [rel] [sy] ["86]
+ \definemathsymbol [thething] [ord] [sy] ["87]
+ \definemathsymbol [vDash] [rel] [sy] ["88]
+ \definemathsymbol [blacktriangleleft] [rel] [sy] ["89]
+ \definemathsymbol [blacktriangleright] [rel] [sy] ["8A]
+ \definemathsymbol [nleqslant] [rel] [sy] ["8B]
+ \definemathsymbol [ngeqslant] [rel] [sy] ["8C]
+ \definemathsymbol [parallel] [rel] [sy] ["8D]
+ \definemathsymbol [nparallel] [rel] [sy] ["8E]
+ \definemathsymbol [nparallelslant] [rel] [sy] ["8F]
+ \definemathsymbol [nvDash] [rel] [sy] ["90]
+ \definemathsymbol [intercal] [bin] [sy] ["91]
+ \definemathsymbol [hslash] [ord] [sy] ["92]
+ \definemathsymbol [nexists] [ord] [sy] ["93]
+ \definemathsymbol [varsubsetneq] [rel] [sy] ["93]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathcharacter [(] [nothing] [mr] ["28] [ex] ["A1]
+ \definemathcharacter [)] [nothing] [mr] ["29] [ex] ["A2]
+ \definemathcharacter [91] [nothing] [mr] ["5B] [ex] ["A3] % [
+ \definemathcharacter [93] [nothing] [mr] ["5D] [ex] ["A4] % ]
+ \definemathcharacter [/] [nothing] [mr] ["2F] [ex] ["B1]
+
+ \definemathcharacter [124] [nothing] [sy] ["6A] [ex] ["AF] % |
+ \definemathcharacter [92] [nothing] [sy] ["6E] [ex] ["B2] % \
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathsymbol [Vert] [nothing] [sy] ["6B] [ex] ["B0]
+ \definemathsymbol [vert] [nothing] [sy] ["6A] [ex] ["AF]
+ \definemathsymbol [VERT] [nothing] [sy] ["98] [ex] ["93]
+ \definemathsymbol [Downarrow] [rel] [sy] ["2B] [ex] ["C4]
+ \definemathsymbol [backslash] [nothing] [sy] ["6E] [ex] ["B2]
+ \definemathsymbol [rangle] [close] [sy] ["69] [ex] ["AE]
+ \definemathsymbol [langle] [open] [sy] ["68] [ex] ["AD]
+ \definemathsymbol [rbrace] [close] [sy] ["67] [ex] ["AA]
+ \definemathsymbol [lbrace] [open] [sy] ["66] [ex] ["A9]
+ \definemathsymbol [rceil] [close] [sy] ["65] [ex] ["A8]
+ \definemathsymbol [lceil] [open] [sy] ["64] [ex] ["A7]
+ \definemathsymbol [rfloor] [close] [sy] ["63] [ex] ["A6]
+ \definemathsymbol [lfloor] [open] [sy] ["62] [ex] ["A5]
+ \definemathsymbol [dblbrackleft] [open] [sy] ["99] [ex] ["85]
+ \definemathsymbol [dblbrackright] [close] [sy] ["9A] [ex] ["86]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathsymbol [varkappa] [ord] [mi] ["80] % check this
+ \definemathsymbol [varvarrho] [ord] [mi] ["81] % check this
+ \definemathsymbol [xswordsup] [ord] [sy] ["96]
+ \definemathsymbol [xswordsdown] [ord] [sy] ["97]
+ \definemathsymbol [notowns] [rel] [sy] ["9C]
+ \definemathsymbol [hbar] [ord] [sy] ["9D]
+ \definemathsymbol [smallsetminus] [bin] [sy] ["9E]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathsymbol [notin] [rel] [sy] ["9B]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathsymbol [iintop] [op] [ex] ["CE]
+ \definemathsymbol [iiintop] [op] [ex] ["D0]
+ \definemathsymbol [oiintop] [op] [ex] ["D2]
+ \definemathsymbol [oiiintop] [op] [ex] ["D4]
+ \definemathsymbol [slashintop] [op] [ex] ["D6]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathcommand [iint] {\iintop \nolimits}
+ \definemathcommand [iiint] {\iiintop \nolimits}
+ \definemathcommand [oiint] {\oiintop \nolimits}
+ \definemathcommand [oiiint] {\oiiintop \nolimits}
+ \definemathcommand [slashint] {\slashintop\nolimits}
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathsymbol [acute] [accent] [mr] ["1]
+ \definemathsymbol [grave] [accent] [mr] ["0]
+ \definemathsymbol [ddot] [accent] [mr] ["4]
+ \definemathsymbol [tilde] [accent] [mr] ["3]
+ \definemathsymbol [bar] [accent] [mr] ["9]
+ \definemathsymbol [breve] [accent] [mr] ["8]
+ \definemathsymbol [check] [accent] [mr] ["7]
+ \definemathsymbol [hat] [accent] [mr] ["2]
+ \definemathsymbol [dot] [accent] [mr] ["A]
+ \definemathsymbol [mathring] [accent] [mr] ["6]
+
+\stopmathcollection
+
+\startmathcollection [fou]
+
+ \definemathsymbol [otheralpha] [ord] [mi] ["0B]
+ \definemathsymbol [otherbeta] [ord] [mi] ["0C]
+ \definemathsymbol [othergamma] [ord] [mi] ["0D]
+ \definemathsymbol [otherdelta] [ord] [mi] ["0E]
+ \definemathsymbol [otherepsilon] [ord] [mi] ["0F]
+ \definemathsymbol [otherzeta] [ord] [mi] ["10]
+
+\stopmathcollection
+
+\protect \endinput
+
+% from a mail of Michel B / todo
+
+% \definemathsymbol [acute] [accent] [operators] ["1]
+% \definemathsymbol [grave] [accent] [operators] ["0]
+% \definemathsymbol [ddot] [accent] [operators] ["4]
+% \definemathsymbol [tilde] [accent] [operators] ["3]
+% \definemathsymbol [bar] [accent] [operators] ["9]
+% \definemathsymbol [breve] [accent] [operators] ["8]
+% \definemathsymbol [check] [accent] [operators] ["7]
+% \definemathsymbol [hat] [accent] [operators] ["2]
+% \definemathsymbol [dot] [accent] [operators] ["A]
+% \definemathsymbol [mathring] [accent] [operators] ["6]
+
+% \definemathsymbol [wideparen] [ord] [largesymbols] ["94]
+% \definemathsymbol [widearc] [accent] [largesymbols] ["D8]
+
+% check for definition of \overset (ams)
+
+% \def\FOUwidering#1%
+% {\overset{\smash{\vbox to .2ex{\hbox{$\mathring{}$}}}}{\wideparen{#1}}}
+
+% \startmathcollection [default] % [ams]
+%
+% \definemathcommand [widering] {\FOUwidering}
+%
+% \stopmathcollection
+
+% \definemathsymbol [otheralpha] [ord] [otherletters] ["0B]
+% \definemathsymbol [otherbeta] [ord] [otherletters] ["0C]
+% \definemathsymbol [othergamma] [ord] [otherletters] ["0D]
+% \definemathsymbol [otherdelta] [ord] [otherletters] ["0E]
+% \definemathsymbol [otherepsilon] [ord] [otherletters] ["0F]
+% \definemathsymbol [otherzeta] [ord] [otherletters] ["10]
diff --git a/tex/context/base/math-frc.mkii b/tex/context/base/math-frc.mkii
new file mode 100644
index 000000000..fa319bc4a
--- /dev/null
+++ b/tex/context/base/math-frc.mkii
@@ -0,0 +1,66 @@
+%D \module
+%D [ file=math-frc,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Fractions,
+%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Fractions}
+
+\unprotect
+
+\def\exmthfont#1{\symbolicsizedfont#1\plusone{MathExtension}}
+
+\def\domthfrac#1#2#3#4#5#6#7%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox0\hbox{$#1 #6$}%
+ \setbox2\hbox{$#1 #7$}%
+ \dimen0\wd0
+ \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
+ \setbox4\hbox to \dimen0{\exmthfont#2#3\leaders\hbox{#4}\hss#5}%
+ \mathord{\vcenter{{\offinterlineskip
+ \hbox to \dimen0{\hss\box0\hss}%
+ \kern \ht4%
+ \hbox to \dimen0{\hss\copy4\hss}%
+ \kern \ht4%
+ \hbox to \dimen0{\hss\box2\hss}}}}%
+ \endgroup}
+
+\def\domthsqrt#1#2#3#4#5%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox0\hbox{$#1 #5$}%
+ \dimen0=1.05\ht0 \advance\dimen0 1pt \ht0 \dimen0
+ \dimen0=1.05\dp0 \advance\dimen0 1pt \dp0 \dimen0
+ \dimen0\wd0
+ \setbox4\hbox to \dimen0{\exmthfont#2\leaders\hbox{#3}\hfill#4}%
+ \delimitershortfall=0pt
+ \nulldelimiterspace=0pt
+ \setbox2\hbox{$\left\delimiter"0270370 \vrule height\ht0 depth \dp0 width0pt
+ \right.$}%
+ \mathord{\vcenter{\hbox{\copy2
+ \rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
+ \endgroup}
+
+\def\mthfrac#1#2#3#4#5{\mathchoice
+ {\domthfrac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}
+
+\def\mthsqrt#1#2#3{\mathchoice
+ {\domthsqrt\displaystyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\textstyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\scriptstyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\scriptscriptstyle\textface {#1}{#2}{#3}}}
+
+% temp here
+
+\protect \endinput
diff --git a/tex/context/base/math-frc.mkiv b/tex/context/base/math-frc.mkiv
new file mode 100644
index 000000000..2305cec30
--- /dev/null
+++ b/tex/context/base/math-frc.mkiv
@@ -0,0 +1,209 @@
+%D \module
+%D [ file=math-frc,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Fractions,
+%D author={Hans Hagen \& Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Fractions}
+
+\unprotect
+
+%D \macros
+%D {frac, xfrac, xxfrac}
+%D
+%D This is another one Tobias asked for. It replaces the
+%D primitive \type {\over}. We also take the opportunity to
+%D handle math style restoring, which makes sure units and
+%D chemicals come out ok.
+%D The \type {\frac} macro kind of replaces the awkward \type
+%D {\over} primitive. Say that we have the following formulas:
+%D
+%D \startbuffer[sample]
+%D test $\frac {1}{2}$ test $$1 + \frac {1}{2} = 1.5$$
+%D test $\xfrac {1}{2}$ test $$1 + \xfrac {1}{2} = 1.5$$
+%D test $\xxfrac{1}{2}$ test $$1 + \xxfrac{1}{2} = 1.5$$
+%D \stopbuffer
+%D
+%D \typebuffer[sample]
+%D
+%D With the most straightforward definitions, we get:
+%D
+%D \startbuffer[code]
+%D \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}}
+%D
+%D \def\frac {\dofrac\mathstyle}
+%D \def\xfrac {\dofrac\scriptstyle}
+%D \def\xxfrac{\dofrac\scriptscriptstyle}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D Since this does not work well, we can try:
+%D
+%D \startbuffer[code]
+%D \def\xfrac #1#2{\hbox{$\dofrac\scriptstyle {#1}{#2}$}}
+%D \def\xxfrac#1#2{\hbox{$\dofrac\scriptscriptstyle{#1}{#2}$}}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D This for sure looks better than:
+%D
+%D \startbuffer[code]
+%D \def\xfrac #1#2{{\scriptstyle \dofrac\relax{#1}{#2}}}
+%D \def\xxfrac#1#2{{\scriptscriptstyle\dofrac\relax{#1}{#2}}}
+%D \stopbuffer
+%D
+%D \typebuffer[code] \getbuffer[code,sample]
+%D
+%D So we stick to the next definitions (watch the local
+%D overloading of \type {\xfrac}).
+
+% \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}}
+
+\def\dofrac#1#2#3{\relax\mathematics{\Ustack{{#1{#2}}\normalover{#1{#3}}}}}
+\def\nofrac #1#2{\relax\mathematics{\Ustack{{#1}\normalover{#2}}}}
+
+% \chardef\mathfracmode=0 $\frac{1}{2}$
+% \chardef\mathfracmode=1 $\frac{1}{2}$
+% \chardef\mathfracmode=2 $\frac{1}{2}$
+% \chardef\mathfracmode=3 $\frac{1}{2}$
+% \chardef\mathfracmode=4 $\frac{1}{2}$
+% \chardef\mathfracmode=5 $\frac{1}{2}$
+
+\chardef\mathfracmode=0 % 0=auto, 1=displaystyle, 2=textstyle, 3=scriptstyle, 4=scriptscriptstyle, 5=mathstyle
+
+\unexpanded\def\frac
+ {\ifcase\mathfracmode
+ \expandafter\nofrac
+ \or
+ \expandafter\dofrac\expandafter\displaystyle
+ \or
+ \expandafter\dofrac\expandafter\textstyle
+ \or
+ \expandafter\dofrac\expandafter\scriptstyle
+ \or
+ \expandafter\dofrac\expandafter\scriptscriptstyle
+ \else
+ \expandafter\dofrac\expandafter\mathstyle
+ \fi}
+
+\unexpanded\def\xfrac#1#2%
+ {\begingroup
+ \let\xfrac\xxfrac
+ \dofrac\scriptstyle{#1}{#2}%
+ \endgroup}
+
+\unexpanded\def\xxfrac#1#2%
+ {\begingroup
+ \dofrac\scriptscriptstyle{#1}{#2}%
+ \endgroup}
+
+%D The \type {xx} variant looks still ugly, so maybe it's
+%D best to say:
+
+\unexpanded\def\xxfrac#1#2%
+ {\begingroup
+ \dofrac\scriptscriptstyle{#1}{\raise.25ex\hbox{$\scriptscriptstyle#2$}}%
+ \endgroup}
+
+%D Something low level for scientific calculator notation:
+
+\unexpanded\def\scinot#1#2%
+ {#1\times10^{#2}}
+
+%D The next macro, \type {\ch}, is \PPCHTEX\ aware. In
+%D formulas one can therefore best use \type {\ch} instead of
+%D \type {\chemical}, especially in fractions.
+
+% let's see who complains ... \mathstyle is now a primitive
+%
+% \unexpanded\def\ch#1%
+% {\ifdefined\@@chemicalletter
+% \dosetsubscripts
+% \mathstyle{\@@chemicalletter{#1}}%
+% \doresetsubscripts
+% \else
+% \mathstyle{\rm#1}%
+% \fi}
+
+% \unexpanded\def\ch#1%
+% {\ifdefined\@@chemicalletter
+% \dosetsubscripts
+% \mathematics{\@@chemicalletter{#1}}%
+% \doresetsubscripts
+% \else
+% \mathematics{\rm#1}%
+% \fi}
+
+%D \macros
+%D {/}
+%D
+%D Just to be sure, we restore the behavior of some typical
+%D math characters.
+
+\bgroup
+
+\catcode`\/=\@@other \global \let\normalforwardslash/
+\catcode`\/=\@@active \doglobal\appendtoks\let/\normalforwardslash\to\everymathematics
+
+\egroup
+
+% to be checked:
+
+\def\exmthfont#1{\symbolicsizedfont#1\plusone{MathExtension}}
+
+\def\domthfrac#1#2#3#4#5#6#7%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox0\hbox{$#1 #6$}%
+ \setbox2\hbox{$#1 #7$}%
+ \dimen0\wd0
+ \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
+ \setbox4\hbox to \dimen0{\exmthfont#2#3\leaders\hbox{#4}\hss#5}%
+ \mathord{\vcenter{{\offinterlineskip
+ \hbox to \dimen0{\hss\box0\hss}%
+ \kern \ht4%
+ \hbox to \dimen0{\hss\copy4\hss}%
+ \kern \ht4%
+ \hbox to \dimen0{\hss\box2\hss}}}}%
+ \endgroup}
+
+\def\domthsqrt#1#2#3#4#5%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox0\hbox{$#1 #5$}%
+ \dimen0=1.05\ht0 \advance\dimen0 1pt \ht0 \dimen0
+ \dimen0=1.05\dp0 \advance\dimen0 1pt \dp0 \dimen0
+ \dimen0\wd0
+ \setbox4\hbox to \dimen0{\exmthfont#2\leaders\hbox{#3}\hfill#4}%
+ \delimitershortfall=0pt
+ \nulldelimiterspace=0pt
+ \setbox2\hbox{$\left\delimiter"0270370 \vrule height\ht0 depth \dp0 width0pt
+ \right.$}%
+ \mathord{\vcenter{\hbox{\copy2
+ \rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
+ \endgroup}
+
+\def\mthfrac#1#2#3#4#5{\mathchoice
+ {\domthfrac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}
+ {\domthfrac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}
+
+\def\mthsqrt#1#2#3{\mathchoice
+ {\domthsqrt\displaystyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\textstyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\scriptstyle \textface {#1}{#2}{#3}}
+ {\domthsqrt\scriptscriptstyle\textface {#1}{#2}{#3}}}
+
+% temp here
+
+\protect \endinput
diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua
new file mode 100644
index 000000000..63d7cad38
--- /dev/null
+++ b/tex/context/base/math-ini.lua
@@ -0,0 +1,340 @@
+if not modules then modules = { } end modules ['math-ext'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- if needed we can use the info here to set up xetex definition files
+-- the "8000 hackery influences direct characters (utf) as indirect \char's
+
+local utf = unicode.utf8
+
+local texsprint, format, utfchar, utfbyte = tex.sprint, string.format, utf.char, utf.byte
+
+local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end)
+
+mathematics = mathematics or { }
+
+mathematics.extrabase = 0xFE000 -- here we push some virtuals
+mathematics.privatebase = 0xFF000 -- here we push the ex
+
+local families = {
+ tf = 0, it = 1, sl = 2, bf = 3, bi = 4, bs = 5, -- virtual fonts or unicode otf
+}
+
+local classes = {
+ ord = 0, -- mathordcomm mathord
+ op = 1, -- mathopcomm mathop
+ bin = 2, -- mathbincomm mathbin
+ rel = 3, -- mathrelcomm mathrel
+ open = 4, -- mathopencomm mathopen
+ close = 5, -- mathclosecomm mathclose
+ punct = 6, -- mathpunctcomm mathpunct
+ alpha = 7, -- mathalphacomm firstofoneargument
+ accent = 8, -- class 0
+ radical = 9,
+ xaccent = 10, -- class 3
+ topaccent = 11, -- class 0
+ botaccent = 12, -- class 0
+ under = 13,
+ over = 14,
+ delimiter = 15,
+ inner = 0, -- mathinnercomm mathinner
+ nothing = 0, -- mathnothingcomm firstofoneargument
+ choice = 0, -- mathchoicecomm @@mathchoicecomm
+ box = 0, -- mathboxcomm @@mathboxcomm
+ limop = 1, -- mathlimopcomm @@mathlimopcomm
+ nolop = 1, -- mathnolopcomm @@mathnolopcomm
+}
+
+mathematics.families = families
+mathematics.classes = classes
+
+classes.alphabetic = classes.alpha
+classes.unknown = classes.nothing
+classes.default = classes.nothing
+classes.punctuation = classes.punct
+classes.normal = classes.nothing
+classes.opening = classes.open
+classes.closing = classes.close
+classes.binary = classes.bin
+classes.relation = classes.rel
+classes.fence = classes.unknown
+classes.diacritic = classes.accent
+classes.large = classes.op
+classes.variable = classes.alphabetic
+classes.number = classes.alphabetic
+
+-- there will be proper functions soon (and we will move this code in-line)
+-- no need for " in class and family (saves space)
+
+local function delcode(target,family,slot)
+ return format('\\Udelcode%s="%X "%X ',target,family,slot)
+end
+local function mathchar(class,family,slot)
+ return format('\\Umathchar "%X "%X "%X ',class,family,slot)
+end
+local function mathaccent(class,family,slot)
+ return format('\\Umathaccent "%X "%X "%X ',0,family,slot) -- no class
+end
+local function delimiter(class,family,slot)
+ return format('\\Udelimiter "%X "%X "%X ',class,family,slot)
+end
+local function radical(family,slot)
+ return format('\\Uradical "%X "%X ',family,slot)
+end
+local function mathchardef(name,class,family,slot)
+ return format('\\Umathchardef\\%s "%X "%X "%X ',name,class,family,slot)
+end
+local function mathcode(target,class,family,slot)
+ return format('\\Umathcode%s="%X "%X "%X ',target,class,family,slot)
+end
+local function mathtopaccent(class,family,slot)
+ return format('\\Umathaccent "%X "%X "%X ',0,family,slot) -- no class
+end
+local function mathbotaccent(class,family,slot)
+ return format('\\Umathbotaccent "%X "%X "%X ',0,family,slot) -- no class
+end
+local function mathtopdelimiter(class,family,slot)
+ return format('\\Uoverdelimiter "%X "%X ',0,family,slot) -- no class
+end
+local function mathbotdelimiter(class,family,slot)
+ return format('\\Uunderdelimiter "%X "%X ',0,family,slot) -- no class
+end
+
+local escapes = characters.filters.utf.private.escapes
+
+local function setmathsymbol(name,class,family,slot)
+ if class == classes.accent then
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathaccent(class,family,slot)))
+ elseif class == classes.topaccent then
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathtopaccent(class,family,slot)))
+ elseif class == classes.botaccent then
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathbotaccent(class,family,slot)))
+ elseif class == classes.over then
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathtopdelimiter(class,family,slot)))
+ elseif class == classes.under then
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathbotdelimiter(class,family,slot)))
+ elseif class == classes.open or class == classes.close then
+ texsprint(delcode(slot,family,slot))
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,delimiter(class,family,slot)))
+ elseif class == classes.delimiter then
+ texsprint(delcode(slot,family,slot))
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,delimiter(0,family,slot)))
+ elseif class == classes.radical then
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,radical(family,slot)))
+ else
+ -- beware, open/close and other specials should not end up here
+--~ local ch = utfchar(slot)
+--~ if escapes[ch] then
+--~ texsprint(format("\\xdef\\%s{\\char%s }",name,slot))
+--~ else
+ texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathchar(class,family,slot)))
+--~ end
+ end
+end
+
+local function setmathcharacter(class,family,slot,unicode,firsttime)
+ if not firsttime and class <= 7 then
+ texsprint(mathcode(slot,class,family,unicode or slot))
+ end
+end
+
+local function setmathsynonym(class,family,slot,unicode,firsttime)
+ if not firsttime and class <= 7 then
+ texsprint(mathcode(slot,class,family,unicode))
+ end
+ if class == classes.open or class == classes.close then
+ texsprint(delcode(slot,family,unicode))
+ end
+end
+
+local function report(class,family,unicode,name)
+ local nametype = type(name)
+ if nametype == "string" then
+ logs.report("mathematics","%s:%s %s U+%05X (%s) => %s",classname,class,family,unicode,utfchar(unicode),name)
+ elseif nametype == "number" then
+ logs.report("mathematics","%s:%s %s U+%05X (%s) => U+%05X",classname,class,family,unicode,utfchar(unicode),name)
+ else
+ logs.report("mathematics","%s:%s %s U+%05X (%s)", classname,class,family,unicode,utfchar(unicode))
+ end
+end
+
+-- there will be a combined \(math)chardef
+
+function mathematics.define(slots,family)
+ family = family or 0
+ family = families[family] or family
+ local data = characters.data
+ for unicode, character in next, data do
+ local symbol = character.mathsymbol
+ if symbol then
+ local other = data[symbol]
+ local class = other.mathclass
+ if class then
+ class = classes[class] or class -- no real checks needed
+ if trace_defining then
+ report(class,family,unicode,symbol)
+ end
+ setmathsynonym(class,family,unicode,symbol)
+ end
+ local spec = other.mathspec
+ if spec then
+ for i, m in next, spec do
+ local class = m.class
+ if class then
+ class = classes[class] or class -- no real checks needed
+ setmathsynonym(class,family,unicode,symbol,i)
+ end
+ end
+ end
+ end
+ local mathclass = character.mathclass
+ local mathspec = character.mathspec
+ if mathspec then
+ for i, m in next, mathspec do
+ local name = m.name
+ local class = m.class
+ if not class then
+ class = mathclass
+ elseif not mathclass then
+ mathclass = class
+ end
+ if class then
+ class = classes[class] or class -- no real checks needed
+ if name then
+ if trace_defining then
+ report(class,family,unicode,name)
+ end
+ setmathsymbol(name,class,family,unicode)
+ -- setmathcharacter(class,family,unicode,unicode,i)
+ else
+ name = class == classes.variable or class == classes.number and character.adobename
+ if name then
+ if trace_defining then
+ report(class,family,unicode,name)
+ end
+ -- setmathcharacter(class,family,unicode,unicode,i)
+ end
+ end
+ setmathcharacter(class,family,unicode,unicode,i)
+ end
+ end
+ end
+ if mathclass then
+ local name = character.mathname
+ local class = classes[mathclass] or mathclass -- no real checks needed
+ if name == false then
+ if trace_defining then
+ report(class,family,unicode,name)
+ end
+ setmathcharacter(class,family,unicode)
+ else
+ name = name or character.contextname
+ if name then
+ if trace_defining then
+ report(class,family,unicode,name)
+ end
+ setmathsymbol(name,class,family,unicode)
+ else
+ if trace_defining then
+ report(class,family,unicode,character.adobename)
+ end
+ end
+ setmathcharacter(class,family,unicode,unicode)
+ end
+ end
+ end
+end
+
+-- needed for mathml analysis
+
+function mathematics.utfmathclass(chr, default)
+ local cd = characters.data[utfbyte(chr)]
+ return (cd and cd.mathclass) or default or "unknown"
+end
+function mathematics.utfmathstretch(chr, default) -- "h", "v", "b", ""
+ local cd = characters.data[utfbyte(chr)]
+ return (cd and cd.mathstretch) or default or ""
+end
+function mathematics.utfmathcommand(chr, default)
+ local cd = characters.data[utfbyte(chr)]
+ local cmd = cd and cd.mathname
+ tex.sprint(cmd or default or "")
+end
+function mathematics.utfmathfiller(chr, default)
+ local cd = characters.data[utfbyte(chr)]
+ local cmd = cd and (cd.mathfiller or cd.mathname)
+ tex.sprint(cmd or default or "")
+end
+
+mathematics.entities = mathematics.entities or { }
+
+function mathematics.register_xml_entities()
+ local entities = xml.entities
+ for name, unicode in next, mathematics.entities do
+ if not entities[name] then
+ entities[name] = utfchar(unicode)
+ end
+ end
+end
+
+-- helpers
+
+function mathematics.big(tfmdata,unicode,n)
+ local t = tfmdata.characters
+ local c = t[unicode]
+ if c then
+ local vv = c.vert_variants or c.next and t[c.next].vert_variants
+ if vv then
+ local vvn = vv[n]
+ return vvn and vvn.glyph or vv[#vv].glyph or unicode
+ else
+ local next = c.next
+ while next do
+ if n <= 1 then
+ return next
+ else
+ n = n - 1
+ local tn = t[next].next
+ if tn then
+ next = tn
+ else
+ return next
+ end
+ end
+ end
+ end
+ end
+ return unicode
+end
+
+-- plugins
+
+local hvars = table.tohash {
+ --~ "RadicalKernBeforeDegree",
+ --~ "RadicalKernAfterDegree",
+}
+
+function mathematics.scaleparameters(t,tfmtable,delta,hdelta,vdelta)
+ local math_parameters = tfmtable.math_parameters
+ if math_parameters and next(math_parameters) then
+ delta = delta or 1
+ hdelta, vdelta = hdelta or delta, vdelta or delta
+ local _, mp = mathematics.dimensions(math_parameters)
+ for name, value in next, mp do
+ if name == "RadicalDegreeBottomRaisePercent" then
+ mp[name] = value
+ elseif hvars[name] then
+ mp[name] = hdelta * value
+ else
+ mp[name] = vdelta * value
+ end
+ end
+ t.MathConstants = mp
+ end
+end
+
+table.insert(fonts.tfm.mathactions,mathematics.scaleparameters)
diff --git a/tex/context/base/math-ini.mkii b/tex/context/base/math-ini.mkii
new file mode 100644
index 000000000..f9dd859c4
--- /dev/null
+++ b/tex/context/base/math-ini.mkii
@@ -0,0 +1,684 @@
+%D \module
+%D [ file=math-ini,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Initializations,
+%D author={Hans Hagen \& Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Initializations}
+
+% todo: make all definitions global since file loaded only once
+
+%D This module provides namespaces for math fonts, thereby
+%D permitting mixed usage of math fonts. Although not strictly
+%D needed, we also provide a family name mapping mechanism as
+%D used in the (original) AMS math definition files, but here
+%D these names can recursively be remapped and if needed,
+%D dynamically be changed. We've tried to minimize the number
+%D of definition commands and use plain \TEX\ definitions as
+%D fallback. We've tried to follow a couple of conventions
+%D from plain and AMS math in order to achieve backward
+%D compatinility. We also kept an eye on future usage of these
+%D modules in the perspective of MathML and unicode fonts.
+
+\unprotect
+
+\def\@ml@{@ml@} % math list (used for collection)
+\def\@mf@{@mf@} % math family
+%def\@mh@{@mh@} % math handler (not used)
+\def\@mt@{@mt@} % math token
+\def\@mc@{@mc@} % math collection
+
+\def\@@mathlimopcomm#1{\mathop{#1}} %no \limits
+\def\@@mathnolopcomm#1{\mathop{#1}\nolimits}
+\def\@@mathboxcomm #1{\dontleavehmode\hbox{$\mathsurround\zeropoint#1$}}
+
+\chardef\mathordcode = 0 \let\mathordcomm \mathord
+\chardef\mathopcode = 1 \let\mathopcomm \mathop
+\chardef\mathbincode = 2 \let\mathbincomm \mathbin
+\chardef\mathrelcode = 3 \let\mathrelcomm \mathrel
+\chardef\mathopencode = 4 \let\mathopencomm \mathopen
+\chardef\mathclosecode = 5 \let\mathclosecomm \mathclose
+\chardef\mathpunctcode = 6 \let\mathpunctcomm \mathpunct
+\chardef\mathalphacode = 7 \let\mathalphacomm \firstofoneargument
+\chardef\mathinnercode = 0 \let\mathinnercomm \mathinner
+\chardef\mathnothingcode= 0 \let\mathnothingcomm \firstofoneargument
+\chardef\mathlimopcode = 1 \let\mathlimopcomm \@@mathlimopcomm
+\chardef\mathnolopcode = 1 \let\mathnolopcomm \@@mathnolopcomm
+\chardef\mathchoicecode = 0 \let\mathchoicecomm \@@mathchoicecomm
+\chardef\mathboxcode = 0 \let\mathboxcomm \@@mathboxcomm
+
+\chardef\mathaccentcode = 8
+\chardef\mathradicalcode= 9
+
+\def\@@mathchoicecomm#1{[todo #1]}
+
+\def\puremathcode#1{\the\csname math#1code\endcsname}
+\def\puremathcomm#1{\csname math#1comm\endcsname}
+
+\newif\iftracemathcollection
+
+% Simple variant:
+%
+% \def\dohandlemathtoken#1%
+% {\csname\@mt@
+% \ifcsname\@mt@\mathcollection#1\endcsname
+% \mathcollection
+% \else\ifcsname\@mt@\nomathcollection#1\endcsname
+% \nomathcollection
+% \fi\fi
+% #1\endcsname}
+
+%D Because a command can have a different meaning in math
+%D and in text mode, we provide a selector. We also provide
+%D the pure alternatives as \type {\mathcharacter} and \type
+%D {\textcharacter}.
+
+% \ifx\dohandlecommand\undefined \wait \fi % troubles ! but not in mkiv so ...
+
+\let\mathcharacter\dohandlemathtoken
+\let\textcharacter\dohandlecommand % better \dohandletexttoken
+
+% More clever layout:
+%
+% \def\dohandlemathtoken#1%
+% {\csname
+% \ifmmode
+% \ifcsname\@mt@\mathcollection#1\endcsname
+% \@mt@\mathcollection
+% \else\ifcsname\@mt@\nomathcollection#1\endcsname
+% \@mt@\nomathcollection
+% \else\ifcsname\characterencoding#1\endcsname
+% \characterencoding
+% \else
+% \nocharacterencoding
+% \fi\fi\fi
+% \else
+% \ifcsname\characterencoding#1\endcsname
+% \characterencoding
+% \else
+% \nocharacterencoding
+% \fi
+% \fi
+% #1\endcsname}
+%
+% fallback to math when in text mode (handy for unicode vectors)
+
+\def\dohandlemathtoken#1%
+ {\csname
+ \ifmmode
+ \ifcsname\@mt@\mathcollection#1\endcsname
+ \@mt@\mathcollection
+ \else\ifcsname\@mt@\nomathcollection#1\endcsname
+ \@mt@\nomathcollection
+ \else\ifcsname\characterencoding#1\endcsname
+ \characterencoding
+ \else
+ \nocharacterencoding
+ \fi\fi\fi
+ \else
+ \ifcsname\characterencoding#1\endcsname
+ \characterencoding
+ \else\ifcsname\nocharacterencoding#1\endcsname
+ \nocharacterencoding
+ \else\ifcsname\@mt@\mathcollection#1\endcsname
+ \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\mathcollection
+ \else\ifcsname\@mt@\nomathcollection#1\endcsname
+ \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\nomathcollection
+ \else
+ \nocharacterencoding
+ \fi\fi\fi\fi
+ \fi
+ #1\endcsname}
+
+%D Now we redefine the text encoding handler.
+
+%D A better fallback:
+
+% Just ETEX which is the default nowadays.
+
+\def\dohandlemathtoken#1%
+ {\csname
+ \ifmmode
+ \ifcsname\@mt@\mathcollection:\outerencoding#1\endcsname
+ \@mt@\mathcollection:\outerencoding
+ \else\ifcsname\@mt@\mathcollection#1\endcsname
+ \@mt@\mathcollection
+ \else\ifcsname\@mt@\nomathcollection#1\endcsname
+ \@mt@\nomathcollection
+ \else\ifcsname\characterencoding#1\endcsname
+ \characterencoding
+ \else
+ \nocharacterencoding
+ \fi\fi\fi\fi
+ \else
+ \ifcsname\characterencoding#1\endcsname
+ \characterencoding
+ \else\ifcsname\nocharacterencoding#1\endcsname
+ \nocharacterencoding
+ \else\ifcsname\@mt@\mathcollection:\outerencoding#1\endcsname
+ \@mt@\mathcollection:\outerencoding
+ \else\ifcsname\@mt@\mathcollection#1\endcsname
+ \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\mathcollection
+ \else\ifcsname\@mt@\nomathcollection#1\endcsname
+ \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\nomathcollection
+ \else
+ \nocharacterencoding
+ \fi\fi\fi\fi\fi
+ \fi
+ #1\endcsname}
+
+\let\dohandlecommand\dohandlemathtoken
+
+\def\definefamilysynonym
+ {\dotripleempty\dodefinefamilysynonym}
+
+\def\dodefinefamilysynonym[#1][#2][#3]% [mathcollection] [] []
+ {\ifthirdargument
+ \setvalue{\@mf@#1#2}{#3}%
+ \else
+ \setvalue{\@mf@ #1}{#2}%
+ \fi}
+
+\let\mathsubfamily\empty
+
+\def\purefamily #1{\csname \truefamily{#1}\mathsubfamily\s!fam\endcsname}
+\def\purefamilyhex#1{\csname hex\truefamily{#1}\mathsubfamily\s!fam\endcsname}
+
+\def\truefamily#1%
+ {\ifcsname\@mf@\mathcollection#1\endcsname
+ \@EA\truefamily\csname\@mf@\mathcollection#1\endcsname
+ \else\ifcsname\@mf@#1\endcsname
+ \@EA\truefamily\csname\@mf@#1\endcsname
+ \else\ifcsname\@mf@\nomathcollection#1\endcsname
+ \@EA\truefamily\csname\@mf@\nomathcollection#1\endcsname
+ \else
+ #1%
+ \fi\fi\fi}
+
+\newif\ifdynamicmathfamilies \dynamicmathfamiliestrue % true per 2003.11.25; needed for mixed bold math
+
+\let\normalpurefamilyhex\purefamilyhex
+
+% todo: reset collection (tok legen) en opnieuw laden met true
+
+\def\definemathsymbol
+ {\dosixtupleempty\dodefinemathsymbol}
+
+\def\dodefinemathsymbol[#1][#2][#3][#4][#5][#6]%
+ {\unexpanded\setgvalue{#1}{\dohandlemathtoken{#1}}%
+ \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
+ \setevalue{\@mt@\mathcollection#1}%
+ {\ifsixthargument
+ \ifnum\puremathcode{#2}=\mathradicalcode
+ \radical"%
+ \else
+ \delimiter"%
+ \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
+ \fi
+ \purefamilyhex{#3}\uchexnumbers{#4}%
+ \purefamilyhex{#5}\uchexnumbers{#6}\space
+ \else\iffourthargument
+ \ifnum\puremathcode{#2}=\mathaccentcode
+ \mathaccent\else\mathchar
+ \fi
+ "\ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
+ \purefamilyhex{#3}\uchexnumbers{#4}\space
+ \fi\fi}%
+ \let\purefamilyhex\normalpurefamilyhex
+ \tracemathsymbol{#1}}
+
+\def\tracemathsymbol#1%
+ {\iftracemathcollection
+ {\endgraf
+ \hbox{\tex{#1}~:~{\mathematics{\getvalue{#1}{}}}}
+ \endgraf}%
+ \fi}
+
+\def\definemathcharacter
+ {\dosixtupleempty\dodefinemathcharacter}
+
+% \def\dodefinemathcharacter[#1][#2][#3][#4][#5][#6]%
+% {\setmathtoks
+% \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
+% \doifnumberelse{#1}
+% {\scratchcounter#1}
+% {\scratchcounter\@EA`\string#1}%
+% \appendetoks
+% \ifsixthargument
+% \delcode\the\scratchcounter="%
+% \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
+% \purefamilyhex{#3}\uchexnumbers{#4}%
+% \purefamilyhex{#5}\uchexnumbers{#6}\space
+% \else\iffourthargument
+% \mathcode\the\scratchcounter="%
+% \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
+% \purefamilyhex{#3}\uchexnumbers{#4}\space
+% \fi\fi\to\mathtoks
+% \let\purefamilyhex\normalpurefamilyhex
+% \tracemathcharacter{#1}}
+
+\newtoks\mathscratchtoks
+
+\def\definemathcharacter
+ {\chardef\mathcharactermode\zerocount
+ \dosixtupleempty\dodefinemathcharacter}
+
+\def\redefinemathcharacter
+ {\chardef\mathcharactermode\plusone
+ \dosixtupleempty\dodefinemathcharacter}
+
+\def\dodefinemathcharacter[#1][#2][#3][#4][#5][#6]%
+ {\ifcase\mathcharactermode
+ \setmathtoks
+ \or
+ \let\mathtoks\mathscratchtoks \mathtoks\emptytoks
+ \fi
+ \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
+ \doifnumberelse{#1}
+ {\scratchcounter#1}
+ {\scratchcounter\@EA`\string#1}%
+ \appendetoks
+ \ifsixthargument
+ \delcode\the\scratchcounter="%
+ \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
+ \purefamilyhex{#3}\uchexnumbers{#4}%
+ \purefamilyhex{#5}\uchexnumbers{#6}\space
+ \else\iffourthargument
+ \mathcode\the\scratchcounter="%
+ \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
+ \purefamilyhex{#3}\uchexnumbers{#4}\space
+ \fi\fi
+ \to \mathtoks
+ \let\purefamilyhex\normalpurefamilyhex
+ \ifcase\mathcharactermode
+ \expandafter\tracemathcharacter
+ \or
+ \the\mathtoks
+ \mathtoks\emptytoks
+ \expandafter\gobbleoneargument
+ \fi{#1}} % maybe lookahead
+
+\def\tracemathcharacter#1%
+ {\iftracemathcollection
+ {\endgraf
+ \doifnumberelse{#1}
+ {\hbox{\tttf\rawcharacter{#1}~:~{\mathematics{\rawcharacter{#1}}}}}
+ {\hbox{\type{#1}~:~{\mathematics{#1}}}}
+ \endgraf}%
+ \fi}
+
+\def\definemathcommand
+ {\dotripleempty\dodefinemathcommand}
+
+\def\dodefinemathcommand[#1][#2][#3]#4% command class args meaning
+ {\unexpanded\setgvalue{#1}{\dohandlemathtoken{#1}}%
+ \ifthirdargument
+ \processaction
+ [#3]
+ [one=>\setvalue{\@mt@\mathcollection#1}##1{\puremathcomm{#2}{#4{##1}}},
+ two=>\setvalue{\@mt@\mathcollection#1}##1##2{\puremathcomm{#2}{#4{##1}{##2}}}]%
+ \else\ifsecondargument
+ \setvalue{\@mt@\mathcollection#1}{\puremathcomm{#2}{#4}}%
+ \else
+ \setvalue{\@mt@\mathcollection#1}{\puremathcomm{nothing}{#4}}%
+ \fi\fi
+ \tracemathcommand{#1}}
+
+\def\tracemathcommand#1%
+ {\iftracemathcollection
+ \endgraf\hbox{\tex{#1}~:~{\mathematics{\getvalue{#1}{}}}}\endgraf
+ \fi}
+
+\def\startmathcollection[#1]%
+ {\pushmacro\mathcollection
+ \setmathcollection{#1}}
+
+\def\setmathcollection#1%
+ {\edef\mathcollection{#1}%
+ \doifundefined{\@ml@\mathcollection}
+ {\expandafter\newtoks\csname\@ml@\mathcollection\endcsname}}
+
+\def\stopmathcollection
+ {\popmacro\mathcollection}
+
+\def\startrawmathcollection
+ {\startmathcollection}
+
+\def\stoprawmathcollection
+ {\stopmathcollection}
+
+\newtoks\mathtoks
+
+\def\setmathtoks
+ {\@EA\let\@EA\mathtoks\csname\@ml@\mathcollection\endcsname}
+
+\def\currentmathcollection{\mathcollection}
+
+\let\nomathcollection\s!default
+
+\def\enablemathcollection[#1]%
+ {\doifnot{#1}\s!default
+ {\setmathcollection\s!default
+ \the\csname\@ml@\mathcollection\endcsname}%
+ \setmathcollection{#1}%
+ \the\csname\@ml@\mathcollection\endcsname}
+
+% hook 'm into the font mechanism
+
+\definefilesynonym[\f!mathprefix\s!default][\f!mathprefix tex]
+
+\def\usemathcollection
+ {\dodoubleempty\dousemathcollection}
+
+\def\dousemathcollection[#1][#2]%
+ {\pushmacro\fontclass
+ \pushmacro\mathclass
+ \ifsecondargument
+ \edef\fontclass{#1}%
+ \edef\mathclass{#2}%
+ \else
+ \edef\mathclass{#1}%
+ \fi
+ \doinputonce{\truefilename{\f!mathprefix\mathclass}.mkii}%
+ \doifsomething\fontclass{\setevalue{\@mc@\fontclass\@mc@}{\mathclass}}%
+ \popmacro\mathclass
+ \popmacro\fontclass}
+
+\let\mathclass\nomathcollection
+
+\letvalue{\@mc@\@mc@}\nomathcollection
+
+% \def\autoenablemathcollection
+% {\doifdefinedelse{\@mc@\fontclass\@mc@}
+% {\enablemathcollection[\getvalue{\@mc@\fontclass\@mc@}]}
+% {\enablemathcollection[\s!default]}} % ? ? ?
+
+\def\autoenablemathcollection
+ {\expanded{\enablemathcollection[\executeifdefined{\@mc@\fontclass\@mc@}\nomathcollection]}}
+
+\appendtoks\autoenablemathcollection\to\mathstrategies
+
+\fetchruntimecommand \showmathcharacters {\f!mathprefix\s!run.mkii}
+\fetchruntimecommand \showmathtoken {\f!mathprefix\s!run.mkii}
+
+\def\resetmathcollection[#1]%
+ {\def\mathcollection{#1}%
+ \forgetdoingonce{\f!mathprefix\mathcollection.mkii}%
+ \setmathtoks
+ \ifx\mathtoks\relax\else\mathtoks\emptytoks\fi}
+
+%D \macros
+%D {ifmathpunctuation, enablemathpunctuation,
+%D definemathpunctuation}
+%D
+%D This will replace periods by comma's:
+%D
+%D \starttyping
+%D \definemathpunctuation . textcomma textperiod
+%D \definemathpunctuation , textcomma textcomma
+%D
+%D \appendtoks
+%D \redefinemathcharacter [.] [ord] [mi] ["3B]%
+%D \to \everymathpunctuation
+%D \stoptyping
+
+% \newif\ifmathpunctuation
+%
+% \def\enablemathpunctuation{\mathpunctuationtrue}
+%
+% \def\definemathpunctuation #1 #2 #3 %
+% {\appendtoks
+% \initializemathpunctuation{#1}{#2}{#3}%
+% \to\everymathematics}
+%
+% \def\initializemathpunctuation#1#2#3% sloowww
+% {\ifmathpunctuation % hm move this test to everymath, or better a separate token list
+% \mathcode`#1="8000
+% \defineactivecharacter #1 {\dohandlemathpunctuation{#2}{#3}}%
+% \fi}
+%
+% \unexpanded\def\dohandlemathpunctuation#1#2% \if fails in mathml interval
+% {\def\next{\csname\ifx\space\nexttoken#2\else#1\fi\endcsname}%
+% \futurelet\nexttoken\next}
+
+\newtoks\everymathpunctuation
+
+\def\enablemathpunctuation % can be called inside math, so after \everymathematics
+ {\relax
+ \ifmmode
+ \the\everymathpunctuation
+ \fi
+ \appendtoksonce
+ \the\everymathpunctuation
+ \to\everymathematics}
+
+\def\definemathpunctuation #1 #2 #3 %
+ {\appendtoks
+ \initializemathpunctuation{#1}{#2}{#3}%
+ \to\everymathpunctuation}
+
+\def\initializemathpunctuation#1#2#3% sloowww
+ {\mathcode`#1="8000
+ \defineactivecharacter #1 {\dohandlemathpunctuation{#2}{#3}}}
+
+\unexpanded\def\dohandlemathpunctuation#1#2% \if fails in mathml interval
+ {\def\next{\csname\ifx\space\nexttoken#2\else#1\fi\endcsname}%
+ \futurelet\nexttoken\next}
+
+%D \startbuffer
+%D \enablemathpunctuation$(1,2) (1, 2) (1{,}2) \hbox{foo, not bar}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \blank{\getbuffer}\blank
+
+%D needed for sin, cos etc
+
+\def\mfunction #1{{\mr#1}}
+
+% \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}}
+% \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}}
+
+%D Taco posted this solution as response to a mail by Olivier, so
+%D let's integrate it here.
+
+% \def\setmathfunctionstyle#1% rm ss tt
+% {\def\mfunction##1% no families, just scaling a la text
+% {\mathchoice
+% {\hbox{\csname#1\endcsname\tf ##1}}
+% {\hbox{\csname#1\endcsname\tf ##1}}
+% {\hbox{\csname#1\endcsname\tfx ##1}}
+% {\hbox{\csname#1\endcsname\tfxx##1}}}}
+
+\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
+
+\def\setmathfunctionstyle#1% rm ss tt
+ {\doifsomething{#1}
+ {\def\currentmscaledstyle{#1}%
+ \def\mathopnolimits##1{\mathop{\mscaledtext{##1}}\nolimits}%
+ \def\mfunction##1{\mscaledtext{##1}}}}
+
+\def\mscaledtext#1%
+ {\mathchoice
+ {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}}
+
+%D We can force the way functions are typeset by manipulating the text
+%D option:
+%D
+%D \starttyping
+%D \definetypeface[iwona][ss][sans][iwona][default][encoding=texnansi]
+%D \definetypeface[iwona][mm][math][iwona][default][encoding=texnansi,text=ss]
+%D \stoptyping
+%D
+%D This hooks into the math handler with:
+
+\appendtoks
+ \setmathfunctionstyle\currentmathtextstyle
+\to \everybodyfont
+
+%D Usage:
+%D
+%D \starttyping
+%D \setmathfunctionstyle\fontstyle % or {rm} or {ss} or ..
+%D \rm test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \ss test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \tt test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \stoptyping
+
+\edef\hexmrfam {0} \edef\hexbsfam {8}
+\edef\hexmifam {1} \edef\hexbifam {9}
+\edef\hexsyfam {2} \edef\hexscfam {A}
+\edef\hexexfam {3} \edef\hextffam {B}
+\edef\hexitfam {4} \edef\hexmafam {C}
+\edef\hexslfam {5} \edef\hexmbfam {D}
+\edef\hexbffam {6} \edef\hexmcfam {E}
+\edef\hexnnfam {7} \edef\hexmdfam {F}
+
+\definefamilysynonym [default] [letters] [mr]
+\definefamilysynonym [default] [operators] [sy]
+\definefamilysynonym [default] [lcgreek] [mi]
+\definefamilysynonym [default] [ucgreek] [mr]
+\definefamilysynonym [default] [vargreek] [mi]
+\definefamilysynonym [default] [mitfamily] [mi]
+\definefamilysynonym [default] [calfamily] [sy]
+
+\definefamilysynonym [default] [0] [mr]
+\definefamilysynonym [default] [1] [mi]
+\definefamilysynonym [default] [2] [sy]
+\definefamilysynonym [default] [3] [ex]
+
+\enablemathcollection[default]
+
+\usemathcollection [default] [tex]
+\usemathcollection [default] [ams]
+\usemathcollection [default] [uni]
+
+\enablemathcollection[default]
+
+%D Some goodies:
+
+\def\Angstrom{\nomathematics{\Aring}}
+
+%D Bold math:
+%D
+%D \starttyping
+%D \usetypescript [lucida] [texnansi]
+%D
+%D \definetypeface [boldmath] [rm] [serif]
+%D [lucida] [default] [encoding=texnansi]
+%D \definetypeface [boldmath] [tt] [mono]
+%D [lucida] [default] [encoding=texnansi]
+%D \definetypeface [boldmath] [ss] [sans]
+%D [lucida] [default] [encoding=texnansi]
+%D \definetypeface [boldmath] [mm] [boldmath]
+%D [lucida] [default] [encoding=texnansi]
+%D
+%D \switchtobodyfont[lucida,10pt]
+%D
+%D \showmathtoken{Gamma} $\Gamma \Delta \alpha \delta \zeta$
+%D
+%D \switchtobodyfont[boldmath,10pt]
+%D
+%D \showmathtoken{Gamma} $\Gamma \Delta \alpha \delta \zeta$
+%D \stoptyping
+
+%D \macros
+%D {nonknuthmode, donknuthmode}
+%D
+%D The underscore is frequently used in manuals but unfortunately \TEX\ prefers
+%D it to be a math specific character. And since computer modern fonts didn't
+%D have an underscore, one had to use commands to fake one. Nowadays we do
+%D have underscores in latin modern, and since all other fonts have them, we
+%D decided to get away from the restriction to use the underscore character in
+%D text mode.
+%D
+%D \starttyping
+%D \def\test#1{#1}
+%D
+%D \nonknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
+%D
+%D \donknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
+%D \stoptyping
+%D
+%D The result is as expected: the first line typesets ok, while the second
+%D one triggers an error message.
+
+\bgroup
+
+ \ifx\normalsuber\undefined \def\normalsuber{_} \fi
+ \ifx\normalsuper\undefined \def\normalsuper{^} \fi
+
+ \catcode`_=\active
+ \catcode`^=\active
+
+ \gdef\nonknuthmode
+ {\appendtoks\let_\normalsuber\let^\normalsuper\to\everymathematics
+ \mathcode`_="8000
+ \mathcode`^="8000
+ \catcode`_=\@@other
+ \catcode`^=\@@other
+ \let\nonknuthmode\relax}
+
+ \gdef\donknuthmode
+ {\catcode`_=\@@subscript
+ \catcode`^=\@@superscript}
+
+\egroup
+
+%D \macros
+%D {checkdelimiters, fakeleftdelimiter, fakerightdelimiter}
+%D
+%D Handy for non matching situations (as with mathml):
+%D
+%D \starttyping
+%D \checkdelimiters{... bla bla ...}
+%D \fakeleftdelimiter
+%D ... bla bla ...
+%D \fakerightdelimiter
+%D \stoptyping
+
+\newcount\delimitercount
+
+\def\leftfakedelimiter {\advance\delimitercount\minusone\gobbleoneargument}%
+\def\rightfakedelimiter{\advance\delimitercount\plusone \gobbleoneargument}%
+
+\def\checkdelimiters#1%
+ {\delimitercount\zerocount
+ \setbox\scratchbox\hbox\bgroup
+ \let\left \leftfakedelimiter
+ \let\right\rightfakedelimiter
+ $#1\expandafter$\expandafter
+ \egroup
+ \expandafter\delimitercount\the\delimitercount\relax}
+
+\def\fakeleftdelimiter {\ifnum\delimitercount>\zerocount\left .\fi}
+\def\fakerightdelimiter{\ifnum\delimitercount<\zerocount\right.\fi}
+
+%D Needed for unicode:
+
+\def\nulloperator{\mathortext{\mathop{\null}}{\null}}
+
+%D To be dealt with ...
+
+\mathcode`\ ="8000 % \space
+\mathcode`\'="8000 % ^\prime
+\mathcode`\_="8000 % \_
+
+\protect \endinput
+
+\tracemathcollectiontrue
+ \input math-tex \page
+\setupbodyfont[ams] \enablemathcollection[default] \input math-ams \page
+\setupbodyfont[lbr] \enablemathcollection[lbr] \input math-lbr \page
+\setupbodyfont[eul] \enablemathcollection[eul] \input math-eul \stoptext
diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv
new file mode 100644
index 000000000..828a6eccb
--- /dev/null
+++ b/tex/context/base/math-ini.mkiv
@@ -0,0 +1,657 @@
+%D \module
+%D [ file=math-ini,
+%D version=2008.01.02,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Initializations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Math Macros / Initializations}
+
+%D This module provides namespaces for math fonts, thereby
+%D permitting mixed usage of math fonts. Although not strictly
+%D needed, we also provide a family name mapping mechanism as
+%D used in the (original) AMS math definition files, but here
+%D these names can recursively be remapped and if needed,
+%D dynamically be changed. We've tried to minimize the number
+%D of definition commands and use plain \TEX\ definitions as
+%D fallback. We've tried to follow a couple of conventions
+%D from plain and AMS math in order to achieve backward
+%D compatinility. We also kept an eye on future usage of these
+%D modules in the perspective of MathML and unicode fonts.
+
+\unprotect
+
+\ifx\v!compact\undefined \def\v!compact{compact} \fi
+
+%D New:
+
+\let\startimath\Ustartmath \let\stopimath \Ustopmath
+\let\startdmath\Ustartdisplaymath \let\stopdmath \Ustopmath
+
+%D We move these definitions into the format:
+
+% test [[\char948 \ctxlua{tex.sprint(utf.char(948))}]]
+% test $[[\char948 \ctxlua{tex.sprint(utf.char(948))}]]$
+
+\registerctxluafile{math-ini}{1.001}
+\registerctxluafile{math-dim}{1.001}
+\registerctxluafile{math-ent}{1.001}
+\registerctxluafile{math-ext}{1.001}
+\registerctxluafile{math-vfu}{1.001}
+\registerctxluafile{math-map}{1.001}
+\registerctxluafile{math-noa}{1.001}
+
+\definesystemattribute[mathalphabet] \chardef\mathalphabetattribute \dogetattributeid{mathalphabet}
+\definesystemattribute[mathsize] \chardef\mathsizeattribute \dogetattributeid{mathsize}
+\definesystemattribute[mathpunctuation] \chardef\mathpunctuationattribute \dogetattributeid{mathpunctuation}
+\definesystemattribute[mathgreek] \chardef\mathgreekattribute \dogetattributeid{mathgreek}
+
+% todo: only in mmode
+
+\unexpanded\def\mathgreekupright{\attribute\mathgreekattribute11 }
+\unexpanded\def\mathgreekitalic {\attribute\mathgreekattribute22 }
+\unexpanded\def\mathgreekdefault{\attribute\mathgreekattribute\attributeunsetvalue}
+
+\let\mathgreeknormal\mathgreekupright
+\let\mathgreeknone \mathgreekdefault
+
+\def\setmathattribute#1#2{\ifmmode\ctxlua{mathematics.sync_a_both ("#1","#2")}\fi}
+\def\setmathalphabet #1{\ifmmode\ctxlua{mathematics.sync_a_name ("#1")}\fi}
+\def\setmathstyle #1{\ifmmode\ctxlua{mathematics.sync_a_style("#1")}\fi}
+
+\unexpanded\def\mr {\setmathattribute{regular}{tf}}
+
+\unexpanded\def\mathdefault {\setmathattribute{regular}{it}}
+\unexpanded\def\mathscript {\setmathalphabet{script}}
+\unexpanded\def\mathfraktur {\setmathalphabet{fraktur}}
+\unexpanded\def\mathblackboard{\setmathalphabet{blackboard}}
+
+\unexpanded\def\mathrm{\setmathattribute{rm}{tf}}
+\unexpanded\def\mathss{\setmathattribute{ss}{tf}}
+\unexpanded\def\mathtt{\setmathattribute{tt}{tf}}
+
+\unexpanded\def\mathtf{\setmathstyle{tf}}
+\unexpanded\def\mathbf{\setmathstyle{bf}}
+\unexpanded\def\mathsl{\setmathstyle{sl}}
+\unexpanded\def\mathit{\setmathstyle{it}}
+\unexpanded\def\mathbs{\setmathstyle{bs}}
+\unexpanded\def\mathbi{\setmathstyle{bi}}
+
+\let\tfmath\mathtf % maybe a grouped command
+\let\bfmath\mathbf
+\let\slmath\mathsl
+\let\itmath\mathit
+\let\bsmath\mathbs
+\let\bimath\mathbi
+
+\let\Bbb\mathblackboard
+
+\unexpanded\def\frak {\ifmmode\expandafter\mathfraktur \fi}
+\unexpanded\def\cal {\ifmmode\expandafter\mathscript \fi}
+\unexpanded\def\bbd {\ifmmode\expandafter\mathblackboard\fi}
+\unexpanded\def\blackboard{\ifmmode\expandafter\mathblackboard\fi}
+\unexpanded\def\fraktur {\ifmmode\expandafter\mathfraktur \fi}
+\unexpanded\def\gothic {\ifmmode\expandafter\mathfraktur \fi}
+
+\unexpanded\def\mathcal #1{{\mathscript #1}} % for AMS compatibility
+\unexpanded\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility
+\unexpanded\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility
+
+\let\normalmr\mr
+
+% \prependtoks
+% \let\mr\normalmr
+% \let\rm\mathrm \let\ss\mathss \let\tt\mathtt
+% \let\tf\mathtf \let\bf\mathbf \let\it\mathit \let\sl\mathsl \let\bi\mathbi \let\bs\mathbs
+% \let\frak\mathfraktur \let\cal\mathscript \let\bbd\mathblackboard
+% \mathdefault
+% \to \everymathematics
+
+\let\normaltf\tf \unexpanded\def\tf{\ifmmode\mathtf\else\normaltf\fi}
+\let\normalbf\bf \unexpanded\def\bf{\ifmmode\mathbf\else\normalbf\fi}
+\let\normalit\it \unexpanded\def\it{\ifmmode\mathit\else\normalit\fi}
+\let\normalsl\sl \unexpanded\def\sl{\ifmmode\mathsl\else\normalsl\fi}
+\let\normalbi\bi \unexpanded\def\bi{\ifmmode\mathbi\else\normalbi\fi}
+\let\normalbs\bs \unexpanded\def\bs{\ifmmode\mathbs\else\normalbs\fi}
+
+\let\normalrm\rm \unexpanded\def\rm{\ifmmode\mathrm\else\normalrm\fi}
+\let\normalss\ss \unexpanded\def\ss{\ifmmode\mathss\else\normalss\fi}
+\let\normaltt\tt \unexpanded\def\tt{\ifmmode\mathtt\else\normaltt\fi}
+ \unexpanded\def\mr{\ifmmode \normalmr\fi}
+
+\prependtoks
+% \let\mr\normalmr
+% \let\rm\mathrm \let\ss\mathss \let\tt\mathtt
+% \let\tf\mathtf \let\bf\mathbf \let\it\mathit \let\sl\mathsl \let\bi\mathbi \let\bs\mathbs
+% \let\frak\mathfraktur \let\cal\mathscript \let\bbd\mathblackboard
+ \mathdefault
+\to \everymathematics
+
+%D \macros
+%D {boldsymbol}
+%D
+%D To be done.
+
+\let\mathboldsymbol\relax % yet unsupported, will be
+
+\def\boldsymbol
+ {\mathortext\mathboldsymbol\bold}
+
+%D Helpers:
+
+\def\utfmathclass #1{\ctxlua{tex.sprint(mathematics.utfmathclass ("#1"))}}
+\def\utfmathstretch#1{\ctxlua{tex.sprint(mathematics.utfmathstretch("#1"))}}
+\def\utfmathcommand#1{\ctxlua{tex.sprint(mathematics.utfmathcommand("#1"))}}
+\def\utfmathfiller #1{\ctxlua{tex.sprint(mathematics.utfmathfiller ("#1"))}}
+
+% \def\utfmathclassdefault #1#2{\ctxlua{
+% tex.sprint(mathematics.utfmathclass("#1","#2"))
+% }}
+%
+% \def\utfmathcommanddefault#1#2#3{\ctxlua{
+% local cmd = mathematics.utfmathcommand("#1","") or ""
+% if cmd == "" then
+% commands.cs("#2","#3")
+% else
+% commands.cs(cmd)
+% end}}
+
+% % %
+
+\def\@@mathlimopcomm #1{\mathop{#1}} %no \limits
+\def\@@mathnolopcomm #1{\mathop{#1}\nolimits}
+\def\@@mathboxcomm #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
+\def\@@mathchoicecomm#1{[todo #1]}
+
+\chardef\mathordcode = 0 \let\mathordcomm \mathord
+\chardef\mathopcode = 1 \let\mathopcomm \mathop
+\chardef\mathbincode = 2 \let\mathbincomm \mathbin
+\chardef\mathrelcode = 3 \let\mathrelcomm \mathrel
+\chardef\mathopencode = 4 \let\mathopencomm \mathopen
+\chardef\mathclosecode = 5 \let\mathclosecomm \mathclose
+\chardef\mathpunctcode = 6 \let\mathpunctcomm \mathpunct
+\chardef\mathalphacode = 7 \let\mathalphacomm \firstofoneargument
+\chardef\mathinnercode = 0 \let\mathinnercomm \mathinner
+\chardef\mathnothingcode= 0 \let\mathnothingcomm \firstofoneargument
+\chardef\mathlimopcode = 1 \let\mathlimopcomm \@@mathlimopcomm
+\chardef\mathnolopcode = 1 \let\mathnolopcomm \@@mathnolopcomm
+\chardef\mathchoicecode = 0 \let\mathchoicecomm \@@mathchoicecomm
+\chardef\mathboxcode = 0 \let\mathboxcomm \@@mathboxcomm
+
+\chardef\mathaccentcode = 8
+\chardef\mathradicalcode= 9
+
+\def\puremathcode#1{\the\csname math#1code\endcsname}
+\def\puremathcomm#1{\csname math#1comm\endcsname}
+
+% \startlines
+% $\mathopnolimits{\rm d}x$
+% $\mathopnolimits{\kern\zeropoint \rm d}x$
+% $\puremathcomm{nolop}{\rm d}x$
+% $\puremathcomm{nolop}{\kern\zeropoint\rm d}x$
+% \blank
+% $\puremathcomm{nolop}{\mr d}x$
+% $\puremathcomm{nolop}{\kern\zeropoint\mr d}x$
+% $\mathop{\kern\zeropoint\mr d}x$
+% $\mathopnolimits{\kern\zeropoint d}x$
+% \stoplines
+
+% this will be sorted out:
+
+\let\mathcharacter \getvalue
+\let\textcharacter \getvalue
+\unexpanded\def\definefamilysynonym {\dotripleempty\dodefinefamilysynonym}
+\def\dodefinefamilysynonym [#1][#2][#3]{}
+\unexpanded\def\definemathsymbol {\dosixtupleempty\dodefinemathsymbol}
+\def\dodefinemathsymbol [#1][#2][#3][#4][#5][#6]{}
+\unexpanded\def\definemathcharacter {\dosixtupleempty\dodefinemathcharacter}
+\def\dodefinemathcharacter [#1][#2][#3][#4][#5][#6]{}
+
+\unexpanded\def\definemathcommand
+ {\dotripleempty\dodefinemathcommand}
+
+\def\dodefinemathcommand[#1][#2][#3]#4% command class args meaning
+ {\ifthirdargument
+ \processaction
+ [#3]
+ [one=>\setuvalue{#1}##1{\puremathcomm{#2}{#4{##1}}},
+ two=>\setuvalue{#1}##1##2{\puremathcomm{#2}{#4{##1}{##2}}}]%
+ \else\ifsecondargument
+ \setuvalue{#1}{\puremathcomm{#2}{#4}}%
+ \else
+ \setuvalue{#1}{\puremathcomm{nothing}{#4}}%
+ \fi\fi}
+
+%D Moved from font-ini.mkiv:
+%D
+%D \macros
+%D {mf,mbox,enablembox,mathop}
+%D
+%D Todo:
+
+\unexpanded\def\mf
+ {\csname\fontalternative\endcsname}
+
+\let\normalmathop\mathop
+
+\unexpanded\def\mathop
+ {\normalmathop
+ \bgroup
+ \let\rm\mf
+ \let\next=}
+
+\def\normalmbox
+ {\normalhbox\bgroup\mf
+ \dowithnextbox{\flushnextbox\egroup}\normalhbox}
+
+\def\mbox
+ {\ifmmode\normalmbox\else\normalhbox\fi}
+
+\def\enablembox
+ {\appendtoks
+ \ifx\normalhbox\undefined\let\normalhbox\hbox\fi
+ \let\hbox\mbox
+ \to\everymathematics}
+
+%D needed for sin, cos etc
+
+\let\mathfunction\firstofoneargument
+
+\def\mfunction #1{{\mr#1}}
+\def\mfunctionlabeltext#1{{\mr\mathlabeltext{#1}}}
+
+% \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}}
+% \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}}
+
+%D Taco posted this solution as response to a mail by Olivier, so
+%D let's integrate it here.
+
+\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
+
+\unexpanded\def\do@mathopnolimits #1{\mathop{\mscaledtext{#1}}\nolimits}
+\unexpanded\def\do@mfunction #1{\mscaledtext{#1}}
+\unexpanded\def\do@mfunctionlabeltext#1{\mscaledtext{\mathlabeltext{#1}}}
+
+\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
+ {\doifsomething{#1}
+ {\def\currentmscaledstyle{#1}%
+ \let\mathopnolimits \do@mathopnolimits
+ \let\mfunction \do@mfunction
+ \let\mfunctionlabeltext\do@mfunctionlabeltext}}
+
+\def\mscaledtext#1%
+ {\mathchoice
+ {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}}
+ {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}}
+
+%D We can force the way functions are typeset by manipulating the text
+%D option:
+%D
+%D \starttyping
+%D \definetypeface[iwona][ss][sans][iwona][default][encoding=texnansi]
+%D \definetypeface[iwona][mm][math][iwona][default][encoding=texnansi,text=ss]
+%D \stoptyping
+%D
+%D This hooks into the math handler with:
+
+% no longer supported this way, has to be done with \setupmathematics
+%
+% \appendtoks
+% \setmathfunctionstyle\currentmathtextstyle
+% \to \everybodyfont
+
+%D Usage:
+%D
+%D \starttyping
+%D \setmathfunctionstyle\fontstyle % or {rm} or {ss} or ..
+%D \rm test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \ss test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \tt test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
+%D \stoptyping
+
+%D Some goodies:
+
+\def\Angstrom{\nomathematics{\Aring}}
+
+%D \macros
+%D {nonknuthmode, donknuthmode}
+%D
+%D The underscore is frequently used in manuals but unfortunately \TEX\ prefers
+%D it to be a math specific character. And since computer modern fonts didn't
+%D have an underscore, one had to use commands to fake one. Nowadays we do
+%D have underscores in latin modern, and since all other fonts have them, we
+%D decided to get away from the restriction to use the underscore character in
+%D text mode.
+%D
+%D \starttyping
+%D \def\test#1{#1}
+%D
+%D \nonknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
+%D
+%D \donknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
+%D \stoptyping
+%D
+%D The result is as expected: the first line typesets ok, while the second
+%D one triggers an error message.
+
+\newtoks\everydonknuthmode
+\newtoks\everynonknuthmode
+
+\def\nonknuthmode{\the\everynonknuthmode\let\nonknuthmode\relax}
+\def\donknuthmode{\the\everydonknuthmode}
+
+\ifdefined\normalsuber\else \def\normalsuber{_} \fi
+\ifdefined\normalsuper\else \def\normalsuper{^} \fi
+\ifdefined\normalaltab\else \def\normalaltab{&} \fi
+
+\bgroup
+
+ \catcode`_=\active
+ \catcode`^=\active
+ \catcode`&=\active
+
+ \global \everynonknuthmode {\appendtoks
+ \let_\normalsuber
+ \let^\normalsuper
+ \let&\normalaltab
+ \to \everymathematics}
+
+\egroup
+
+\appendtoks
+ \mathcode`_="8000
+ \mathcode`^="8000
+ \mathcode`&="8000
+ \catcode`_=\@@other
+ \catcode`^=\@@other
+ \catcode`&=\@@other
+\to \everynonknuthmode
+
+\appendtoks
+ \catcode`_=\@@subscript
+ \catcode`^=\@@superscript
+ \catcode`&=\@@alignment
+\to \everydonknuthmode
+
+\appendtoks
+ \startextendcatcodetable\ctxcatcodes
+ \catcode`_=\@@other
+ \catcode`^=\@@other
+ \catcode`&=\@@other
+ \stopextendcatcodetable
+\to \everynonknuthmode
+
+\appendtoks
+ \startextendcatcodetable\ctxcatcodes
+ \catcode`_=\@@subscript
+ \catcode`^=\@@superscript
+ \catcode`&=\@@alignment
+ \stopextendcatcodetable
+\to \everydonknuthmode
+
+%D Needed for unicode:
+
+\def\nulloperator{\mathortext{\mathop{\null}}{\null}}
+
+%D To be dealt with ...
+
+\mathcode`\ ="8000 % \space
+\mathcode`\'="8000 % ^\prime
+\mathcode`\_="8000 % \_
+
+%D \macros
+%D {setupmathematics}
+%D
+%D Configuration for integrals. (If needed we can speed this up and make it
+%D installable; no processaction is needed then).
+
+\newtoks\everysetupmathematics
+
+\unexpanded\def\setupmathematics
+ {\dosingleargument\dosetupmathematics}
+
+\def\dosetupmathematics[#1]%
+ {\getparameters[\??mo][#1]%
+ \the\everysetupmathematics}
+
+\def\mathematicsparameter#1{\ifcsname\??mo#1\endcsname\csname\??mo#1\endcsname\fi}
+
+%D Memory saver:
+
+\appendtoks
+ \doifelse{\mathematicsparameter\v!compact}\v!yes
+ {\ctxlua{fonts.vf.math.optional=true}}
+ {\ctxlua{fonts.vf.math.optional=false}}%
+\to \everysetupmathematics
+
+\setupmathematics
+ [\v!compact=no]
+
+%D Delayed: greek.
+%D
+%D \starttyping
+%D \usetypescript[cambria]\setupbodyfont[cambria]
+%D \startTEXpage
+%D $\alpha \mathgreekupright \alpha \mathgreekitalic \alpha$
+%D \stopTEXpage
+%D \stoptyping
+
+% [lc uc] normal (upright) = 2, italic = 3, none = 0/1
+
+\setevalue{\??mo:greek:\v!normal :\v!normal}{\attribute\mathgreekattribute22 }
+\setevalue{\??mo:greek:\v!normal :\v!italic}{\attribute\mathgreekattribute23 }
+\setevalue{\??mo:greek:\v!normal :\v!none }{\attribute\mathgreekattribute21 }
+
+\setevalue{\??mo:greek:\v!italic :\v!normal}{\attribute\mathgreekattribute32 }
+\setevalue{\??mo:greek:\v!italic :\v!italic}{\attribute\mathgreekattribute33 }
+\setevalue{\??mo:greek:\v!italic :\v!none }{\attribute\mathgreekattribute31 }
+
+\setevalue{\??mo:greek:\v!none :\v!normal}{\attribute\mathgreekattribute12 }
+\setevalue{\??mo:greek:\v!none :\v!italic}{\attribute\mathgreekattribute13 }
+\setevalue{\??mo:greek:\v!none :\v!none }{\attribute\mathgreekattribute\attributeunsetvalue}
+
+\appendtoks
+ \csname\??mo:greek:\@@molcgreek:\@@moucgreek\endcsname
+\to \everymathematics
+
+\setupmathematics
+ [lcgreek=\v!italic,
+ ucgreek=\v!normal] % was: none
+
+%D \macros
+%D {enablemathpunctuation,disablemathpunctuation}
+%D
+%D \startbuffer
+%D \enablemathpunctuation$(1,2) (1, 2) (1{,}2) \hbox{foo, not bar}$
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \blank{\getbuffer}\blank
+
+\setfalse \automathpunctuation
+
+\def\enablemathpunctuation {\settrue \automathpunctuation}
+\def\disablemathpunctuation{\setfalse\automathpunctuation}
+
+\ifx\v!autopunctuation\undefined \def\v!autopunctuation{autopunctuation} \fi
+
+\appendtoks
+ \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\enablemathpunctuation\disablemathpunctuation
+\to \everysetupmathematics
+
+\appendtoks
+ \ifconditional\automathpunctuation\attribute\mathpunctuationattribute\plusone\fi
+\to \everymathematics
+
+\setupmathematics
+ [\v!autopunctuation=\v!no]
+
+%D \macros
+%D {mathstyle}
+%D
+%D If one want to be sure that something is typeset in the
+%D appropriate style, \type {\mathstyle} can be used:
+%D
+%D \starttyping
+%D \mathstyle{something}
+%D \stoptyping
+
+% \def\mathstyle#1%
+% {\mathchoice
+% {\displaystyle #1}%
+% {\textstyle #1}%
+% {\scriptstyle #1}%
+% {\scriptscriptstyle#1}}
+%
+% We now have a primitive operation for this. As the
+% macro overloads a new primitive introduced in \LUATEX,
+% we need to use \type {\normalmathstyle} when we consult
+% the current math style.
+%
+% \let \mathstyle \Ustack % spoils cramped
+%
+% \let \mathstyle \firstofoneargument
+%
+% 0 = display
+% 1 = crampeddisplay
+% 2 = text
+% 3 = crampedtext
+% 4 = script
+% 5 = crampedscript
+% 6 = scriptscript
+% 7 = crampedscriptscript
+
+\def\uncramped#1%
+ {{\ifcase\normalmathstyle
+ \or \displaystyle \or
+ \or \textstyle \or
+ \or \scriptstyle \or
+ \or \scriptscriptstyle \fi
+ #1}}
+
+\def\cramped#1%
+ {{\ifcase\normalmathstyle
+ \crampeddisplaystyle \or \or % 0 -> 1
+ \crampedtextstyle \or \or % 2 -> 3
+ \crampedscriptstyle \or \or % 4 -> 5
+ \crampedscriptscriptstyle \fi % 6 -> 7
+ #1}}
+
+\def\triggermathstyle#1% #1 is number
+ {\ifcase#1\relax
+ \displaystyle \or
+ \crampeddisplaystyle \or
+ \textstyle \or
+ \crampedtextstyle \or
+ \scriptstyle \or
+ \crampedscriptstyle \or
+ \scriptscriptstyle \or
+ \crampedscriptscriptstyle \else
+ % error
+ \fi}
+
+\def\cramped#1%
+ {{\ifcase\normalmathstyle
+ \crampeddisplaystyle \or \or % 0 -> 1
+ \crampedtextstyle \or \or % 2 -> 3
+ \crampedscriptstyle \or \or % 4 -> 5
+ \crampedscriptscriptstyle \fi % 6 -> 7
+ #1}}
+
+\def\mathstylefont#1% #1 is number (\normalmathstyle)
+ {\ifcase#1\relax
+ \textfont \or
+ \textfont \or
+ \textfont \or
+ \textfont \or
+ \scriptfont \or
+ \scriptfont \or
+ \scriptscriptfont \or
+ \scriptscriptfont \else
+ \textfont
+ \fi\zerocount}
+
+%D Something similar can be used in the (re|)|definition
+%D of \type {\text}. This version is a variation on the one
+%D in the math module (see \type{m-math} and|/|or \type
+%D {m-newmat}).
+
+\unexpanded\def\mathtext
+ {\mathortext\domathtext\hbox}
+
+\def\domathtext#1%
+ {\mathchoice
+ {\dodomathtext\displaystyle\textface {#1}}%
+ {\dodomathtext\textstyle \textface {#1}}%
+ {\dodomathtext\textstyle \scriptface {#1}}%
+ {\dodomathtext\textstyle \scriptscriptface{#1}}}
+
+\def\dodomathtext#1#2#3% no \everymath !
+ %{\hbox{\everymath{#1}\switchtobodyfont [#2]#3}} % 15 sec
+ {\hbox{\everymath{#1}\setcurrentfontbody{#2}#3}} % 3 sec (no math)
+
+%D Safeguard against redefinitions:
+
+\appendtoks
+ \let\_\normalunderscore % is textunderscore or fakeunderscore
+\to \everymathematics
+
+%D Because we may overload \type {\text} in other (structuring)
+%D macros, we say:
+
+\appendtoks \let\text\mathtext \to \everymathematics
+
+%D The next code is derived from plain \TEX.
+
+\newcount\interdisplaylinepenalty \interdisplaylinepenalty=100
+
+\newif\ifdt@p
+
+\def\displ@y
+ {\global\dt@ptrue
+ \openup\displayopenupvalue % was \openup\jot
+ \everycr
+ {\noalign
+ {\ifdt@p
+ \global\dt@pfalse
+ \ifdim\prevdepth>-\thousandpoint
+ \vskip-\lineskiplimit
+ \vskip\normallineskiplimit
+ \fi
+ \else
+ \penalty\interdisplaylinepenalty
+ \fi}}}
+
+\let\normaldispl@y\displ@y
+
+\def\displ@y{\resetdisplaymatheq\normaldispl@y}
+
+\def\m@th{\mathsurround\zeropoint} % obsolete
+
+%D Text in math:
+
+\def\mathortext
+ {\ifmmode
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+% \defineactivecharacter _ {\mathortext{_}{\_}} text_text $a^2$
+
+% force text mode, will be overloaded later
+
+\ifx\text\undefined \let\text\hbox \fi
+
+\def\mathoptext#1{\mathop{\text{#1}}}
+
+\protect \endinput
diff --git a/tex/context/base/math-inl.mkiv b/tex/context/base/math-inl.mkiv
new file mode 100644
index 000000000..89de0242b
--- /dev/null
+++ b/tex/context/base/math-inl.mkiv
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=math-inl,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Inline,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE / Hans Hagen]
+%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 Math Macros / Inline}
+
+\unprotect
+
+% Obsolete, as we do snapping differently now.
+
+\def\snappedinlineformula {\dosingleempty\dosnappedinlineformula}
+\def\dosnappedinlineformula[#1]#2{\mathematics{#2}}
+\let\tform \mathematics
+\let\gform \snappedinlineformula
+\let\enableautomath \relax
+
+\protect \endinput
diff --git a/tex/context/base/math-int.mkiv b/tex/context/base/math-int.mkiv
new file mode 100644
index 000000000..2af471b5c
--- /dev/null
+++ b/tex/context/base/math-int.mkiv
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=math-int,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Scripts,
+%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Integrals}
+
+\unprotect
+
+%D \startbuffer
+%D $\int_a^b f(x) dx$ and also
+%D $\iint_a^b f(x,y) dxdy$, $\iiint_a^b f(x,y) dxdy$,
+%D $\iiiint_a^b f(x) dx$
+%D \startformula
+%D \int_a^b f(x) dx \quad
+%D \iint_a^b f(x) dx \quad
+%D \iiint_a^b f(x) dx \quad
+%D \iiiint_a^b f(x) dx \quad
+%D \stopformula
+%D \stopbuffer
+%D
+%D Default: \getbuffer
+%D
+%D Displaylimits: \setupmathematics[integral=displaylimits] \getbuffer
+%D
+%D Limits: \setupmathematics[integral=limits] \getbuffer
+
+\chardef\intlimitcode\zerocount % 0 nolimits 1 displaylimits 2 limits
+
+\def\intlimits
+ {\ifcase\intlimitcode \nolimits \or \displaylimits \or \limits \fi}
+
+\ifx\v!integral\undefined \def\v!integral{integral} \fi
+
+\appendtoks
+ \processaction
+ [\mathematicsparameter\v!integral]
+ [ nolimits=>\chardef\intlimitcode\zerocount,
+ displaylimits=>\chardef\intlimitcode\plusone,
+ limits=>\chardef\intlimitcode\plustwo]%
+\to \everysetupmathematics
+
+\setupmathematics
+ [\v!integral=nolimits]
+
+%D More integrals (AM):
+
+\definemathcommand [iint] {\repeatintegral\plusone }
+\definemathcommand [iiint] {\repeatintegral\plustwo }
+\definemathcommand [iiiint] {\repeatintegral\plusthree}
+
+%def\integralrepeatsymbol{\intop}
+\def\integralrepeatsymbol{{\int}}
+
+\def\repeatintegral#1%
+ {\scratchtoks\emptytoks
+ \let\dointlimits\donothing
+ \let\dodointlimits\intlimits
+ \dorecurse{#1}{\appendtoks \integralrepeatsymbol \dointkern \to \scratchtoks}
+ \appendtoks \intop \dointlimits \dodointlimits \to \scratchtoks
+ \edef\dodorepeatintegral{\the\scratchtoks}%
+ \futurelet\next\dorepeatintegral}
+
+%D If the \type{\limits} option is used after \type{\iint}, use
+%D \type{\mathop} and fudge the left hand space a bit to make the
+%D subscript visually centered.
+
+\def\dointkern
+ {\mkern-6mu\mathchoice{\mkern-3mu}{}{}{}}
+
+\def\dorepeatintegral
+ {\ifx\next\limits \dointlimitcorrection \else
+ \ifx\next\displaylimits \dointlimitcorrection \else
+ \ifx\next\nolimits \donothing \else
+ \ifcase\intlimitcode\else \dointlimitcorrection \fi\fi\fi\fi
+ \dodorepeatintegral}
+
+\def\dointlimitcorrection
+ {\mkern-7mu\mathchoice{\mkern-2mu}{}{}{}%
+ \mathop\bgroup\mkern7mu\mathchoice{\mkern2mu}{}{}{}\let\dointlimits\egroup}
+
+\protect \endinput
diff --git a/tex/context/base/math-lan.mkiv b/tex/context/base/math-lan.mkiv
new file mode 100644
index 000000000..1d3132578
--- /dev/null
+++ b/tex/context/base/math-lan.mkiv
@@ -0,0 +1,67 @@
+%D \module
+%D [ file=math-lan,
+%D version=2009.03.10,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Language Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Math Macros / Language Support}
+
+\unprotect
+
+\setupmathlabeltext [\s!en] [arccos=arccos]
+\setupmathlabeltext [\s!en] [arcsin=arcsin]
+\setupmathlabeltext [\s!en] [arctan=arctan]
+\setupmathlabeltext [\s!en] [arg=arg]
+\setupmathlabeltext [\s!en] [cosh=cosh]
+\setupmathlabeltext [\s!en] [cos=cos]
+\setupmathlabeltext [\s!en] [coth=coth]
+\setupmathlabeltext [\s!en] [cot=cot]
+\setupmathlabeltext [\s!en] [csc=csc]
+\setupmathlabeltext [\s!en] [deg=deg]
+\setupmathlabeltext [\s!en] [det=det]
+\setupmathlabeltext [\s!en] [dim=dim]
+\setupmathlabeltext [\s!en] [exp=exp]
+\setupmathlabeltext [\s!en] [gcd=gcd]
+\setupmathlabeltext [\s!en] [hom=hom]
+\setupmathlabeltext [\s!en] [inf=inf]
+\setupmathlabeltext [\s!en] [injlim=inj\,lim]
+\setupmathlabeltext [\s!en] [ker=ker]
+\setupmathlabeltext [\s!en] [lg=lg]
+\setupmathlabeltext [\s!en] [liminf=lim\,inf]
+\setupmathlabeltext [\s!en] [limsup=lim\,sup]
+\setupmathlabeltext [\s!en] [lim=lim]
+\setupmathlabeltext [\s!en] [ln=ln]
+\setupmathlabeltext [\s!en] [log=log]
+\setupmathlabeltext [\s!en] [median=median]
+\setupmathlabeltext [\s!en] [max=max]
+\setupmathlabeltext [\s!en] [min=min]
+\setupmathlabeltext [\s!en] [mod=mod]
+\setupmathlabeltext [\s!en] [projlim=proj\,lim]
+\setupmathlabeltext [\s!en] [Pr=Pr]
+\setupmathlabeltext [\s!en] [sec=sec]
+\setupmathlabeltext [\s!en] [sinh=sinh]
+\setupmathlabeltext [\s!en] [sin=sin]
+\setupmathlabeltext [\s!en] [sup=sup]
+\setupmathlabeltext [\s!en] [tanh=tanh]
+\setupmathlabeltext [\s!en] [tan=tan]
+
+\setupmathlabeltext [\s!pl] [tg=tg]
+\setupmathlabeltext [\s!pl] [cot=ctg]
+\setupmathlabeltext [\s!pl] [ctg=ctg]
+\setupmathlabeltext [\s!pl] [arcsin=arc\,sin]
+\setupmathlabeltext [\s!pl] [arccos=arc\,cos]
+\setupmathlabeltext [\s!pl] [arctan=arc\,tg]
+\setupmathlabeltext [\s!pl] [arctg=arc\,tg]
+\setupmathlabeltext [\s!pl] [arcctg=arc\,ctg]
+
+\setupmathlabeltext [\s!nl] [gcd=ggd]
+\setupmathlabeltext [\s!nl] [lcm=kgv]
+
+\protect \endinput
diff --git a/tex/context/base/math-lbr.mkii b/tex/context/base/math-lbr.mkii
new file mode 100644
index 000000000..cf69eec1f
--- /dev/null
+++ b/tex/context/base/math-lbr.mkii
@@ -0,0 +1,481 @@
+%D \module
+%D [ file=math-lbr,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Lucida Specials,
+%D author={Hans Hagen \& Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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
+
+\definefamilysynonym [lbr] [calligraphy] [sy]
+\definefamilysynonym [lbr] [oldstyle] [mi]
+
+\definefamilysynonym [lbr] [blackboard] [ma]
+\definefamilysynonym [lbr] [ucgreek] [mb]
+\definefamilysynonym [lbr] [vargreek] [mi]
+
+\startmathcollection[lbr]
+
+\definemathsymbol [boxdot] [bin] [sy] ["ED]
+\definemathsymbol [boxplus] [bin] [sy] ["EA]
+\definemathsymbol [boxtimes] [bin] [sy] ["EC]
+\definemathsymbol [square] [ord] [ma] ["02]
+\definemathsymbol [Box] [ord] [ma] ["02] % square
+\definemathsymbol [blacksquare] [ord] [ma] ["03]
+\definemathsymbol [centerdot] [bin] [ma] ["E1] % [sy] ["01]
+\definemathsymbol [Diamond] [ord] [sy] ["05]
+\definemathsymbol [lozenge] [ord] [sy] ["05] % Diamond
+\definemathsymbol [blacklozenge] [ord] [ma] ["09]
+\definemathsymbol [circlearrowright] [rel] [ma] ["8C]
+\definemathsymbol [circlearrowleft] [rel] [ma] ["8B]
+\definemathsymbol [rightleftharpoons] [rel] [sy] ["8E]
+\definemathsymbol [leftrightharpoons] [rel] [sy] ["8D]
+\definemathsymbol [boxminus] [bin] [sy] ["EB]
+\definemathsymbol [Vdash] [rel] [sy] ["F0]
+\definemathsymbol [Vvdash] [rel] [mb] ["D3]
+\definemathsymbol [vDash] [rel] [mb] ["D6]
+\definemathsymbol [twoheadrightarrow] [rel] [ma] ["25]
+\definemathsymbol [twoheadleftarrow] [rel] [ma] ["23]
+\definemathsymbol [leftleftarrows] [rel] [ma] ["71]
+\definemathsymbol [rightrightarrows] [rel] [ma] ["73]
+\definemathsymbol [upuparrows] [rel] [ma] ["72]
+\definemathsymbol [downdownarrows] [rel] [ma] ["74]
+\definemathsymbol [upharpoonright] [rel] [ma] ["75]
+\definemathsymbol [restriction] [rel] [ma] ["77]
+\definemathsymbol [downharpoonright] [rel] [ma] ["77]
+\definemathsymbol [upharpoonleft] [rel] [ma] ["76]
+\definemathsymbol [downharpoonleft] [rel] [ma] ["78]
+\definemathsymbol [rightarrowtail] [rel] [ma] ["29]
+\definemathsymbol [leftarrowtail] [rel] [ma] ["28]
+\definemathsymbol [leftrightarrows] [rel] [ma] ["6E]
+\definemathsymbol [rightleftarrows] [rel] [ma] ["6D]
+\definemathsymbol [Lsh] [rel] [ma] ["7B]
+\definemathsymbol [Rsh] [rel] [ma] ["7D]
+\definemathsymbol [rightsquigarrow] [rel] [ma] ["8E]
+\definemathsymbol [leadsto] [rel] [ma] ["8E] % rightsquigarrow
+\definemathsymbol [leftrightsquigarrow] [rel] [ma] ["91]
+\definemathsymbol [looparrowleft] [rel] [ma] ["3F]
+\definemathsymbol [looparrowright] [rel] [ma] ["40]
+\definemathsymbol [circeq] [rel] [sy] ["D0]
+\definemathsymbol [succsim] [rel] [sy] ["E1]
+\definemathsymbol [gtrsim] [rel] [sy] ["DD]
+\definemathsymbol [gtrapprox] [rel] [mb] ["DB]
+\definemathsymbol [multimap] [rel] [mb] ["C7]
+\definemathsymbol [therefore] [rel] [sy] ["90]
+\definemathsymbol [because] [rel] [sy] ["91]
+\definemathsymbol [doteqdot] [rel] [sy] ["CA]
+\definemathsymbol [Doteq] [rel] [sy] ["CA] % doteqdot
+\definemathsymbol [triangleq] [rel] [sy] ["D5]
+\definemathsymbol [precsim] [rel] [sy] ["E0]
+\definemathsymbol [lesssim] [rel] [sy] ["DC]
+\definemathsymbol [lessapprox] [rel] [mb] ["DA]
+\definemathsymbol [eqslantless] [rel] [mb] ["E2]
+\definemathsymbol [eqslantgtr] [rel] [mb] ["E3]
+\definemathsymbol [curlyeqprec] [rel] [mb] ["E6]
+\definemathsymbol [curlyeqsucc] [rel] [mb] ["E7]
+\definemathsymbol [preccurlyeq] [rel] [mb] ["E4]
+\definemathsymbol [leqq] [rel] [sy] ["DA]
+\definemathsymbol [leqslant] [rel] [mb] ["E0]
+\definemathsymbol [lessgtr] [rel] [sy] ["DE]
+\definemathsymbol [backprime] [ord] [mb] ["C8]
+\definemathsymbol [dabar@] [ord] [ma] ["03] % !! @
+\definemathsymbol [risingdotseq] [rel] [sy] ["CC]
+\definemathsymbol [fallingdotseq] [rel] [sy] ["CB]
+\definemathsymbol [succcurlyeq] [rel] [mb] ["E5]
+\definemathsymbol [geqq] [rel] [sy] ["DB]
+\definemathsymbol [geqslant] [rel] [mb] ["E1]
+\definemathsymbol [gtrless] [rel] [sy] ["DF]
+\definemathsymbol [sqsubset] [rel] [sy] ["E4]
+\definemathsymbol [sqsupset] [rel] [sy] ["E5]
+\definemathsymbol [vartriangleright] [rel] [mb] ["2E]
+\definemathsymbol [rhd] [bin] [mb] ["2E]
+\definemathsymbol [lhd] [bin] [mb] ["2F]
+\definemathsymbol [vartriangleleft] [rel] [mb] ["2F]
+\definemathsymbol [trianglerighteq] [rel] [sy] ["F5]
+\definemathsymbol [unrhd] [bin] [sy] ["F5] % trianglerighteq
+\definemathsymbol [trianglelefteq] [rel] [sy] ["F4]
+\definemathsymbol [unlhd] [bin] [sy] ["F4] % trianglelefteq
+\definemathsymbol [bigstar] [ord] [ma] ["AB]
+\definemathsymbol [between] [rel] [mb] ["F2]
+\definemathsymbol [blacktriangledown] [ord] [ma] ["07]
+\definemathsymbol [blacktriangleright] [rel] [mb] ["F1]
+\definemathsymbol [blacktriangleleft] [rel] [mb] ["F0]
+\definemathsymbol [vartriangle] [rel] [ma] ["04]
+\definemathsymbol [triangleup] [ord] [ma] ["04] % vartriangle
+\definemathsymbol [blacktriangle] [ord] [ma] ["05]
+\definemathsymbol [triangledown] [ord] [ma] ["06]
+\definemathsymbol [eqcirc] [rel] [sy] ["CF]
+\definemathsymbol [lesseqgtr] [rel] [mb] ["E8]
+\definemathsymbol [gtreqless] [rel] [mb] ["E9]
+\definemathsymbol [lesseqqgtr] [rel] [mb] ["EA]
+\definemathsymbol [gtreqqless] [rel] [mb] ["EB]
+\definemathsymbol [Rrightarrow] [rel] [ma] ["6C]
+\definemathsymbol [Lleftarrow] [rel] [ma] ["6A]
+\definemathsymbol [veebar] [bin] [mb] ["D2]
+\definemathsymbol [barwedge] [bin] [sy] ["F6]
+\definemathsymbol [doublebarwedge] [bin] [sy] ["D4]
+\definemathsymbol [angle] [ord] [sy] ["8B]
+\definemathsymbol [measuredangle] [ord] [sy] ["8C]
+\definemathsymbol [sphericalangle] [ord] [sy] ["8D]
+\definemathsymbol [varpropto] [rel] [sy] ["2F]
+\definemathsymbol [smallsmile] [rel] [mb] ["5E]
+\definemathsymbol [smallfrown] [rel] [mb] ["5F]
+\definemathsymbol [Subset] [rel] [sy] ["F8]
+\definemathsymbol [Supset] [rel] [sy] ["F9]
+\definemathsymbol [Cup] [bin] [sy] ["FA]
+\definemathsymbol [doublecup] [bin] [sy] ["FA] % Cup
+\definemathsymbol [Cap] [bin] [sy] ["FB]
+\definemathsymbol [doublecap] [bin] [sy] ["FB]
+\definemathsymbol [curlywedge] [bin] [sy] ["84]
+\definemathsymbol [curlyvee] [bin] [sy] ["85]
+\definemathsymbol [leftthreetimes] [bin] [mb] ["D0]
+\definemathsymbol [rightthreetimes] [bin] [mb] ["D1]
+\definemathsymbol [subseteqq] [rel] [mb] ["EE]
+\definemathsymbol [supseteqq] [rel] [mb] ["EF]
+\definemathsymbol [bumpeq] [rel] [sy] ["C8]
+\definemathsymbol [Bumpeq] [rel] [sy] ["C7]
+\definemathsymbol [llless] [rel] [mb] ["DE]
+\definemathsymbol [lll] [rel] [mb] ["DE] % llless
+\definemathsymbol [gggtr] [rel] [mb] ["DF]
+\definemathsymbol [ggg] [rel] [mb] ["DF] % gggtr
+\definemathsymbol [ulcorner] [open] [ma] ["5B] [ma] ["5B]
+\definemathsymbol [urcorner] [close] [ma] ["5C] [ma] ["5C]
+\definemathsymbol [circledS] [ord] [mb] ["CA]
+\definemathsymbol [pitchfork] [rel] [ma] ["F3]
+\definemathsymbol [dotplus] [bin] [sy] ["89]
+\definemathsymbol [backsim] [rel] [sy] ["24]
+\definemathsymbol [backsimeq] [rel] [sy] ["27]
+\definemathsymbol [llcorner] [open] [ma] ["5D] [ma] ["5D]
+\definemathsymbol [lrcorner] [close] [ma] ["5E] [ma] ["5E]
+\definemathsymbol [complement] [ord] [mb] ["94]
+\definemathsymbol [intercal] [bin] [ma] ["03] % !!
+\definemathsymbol [circledcirc] [bin] [sy] ["E6]
+\definemathsymbol [circledast] [bin] [sy] ["E7]
+\definemathsymbol [circleddash] [bin] [mb] ["CC]
+
+\stopmathcollection
+
+\startmathcollection [lbr]
+
+\definemathsymbol [lvertneqq] [rel] [ma] ["DE]
+\definemathsymbol [gvertneqq] [rel] [ma] ["DE]
+\definemathsymbol [nleq] [rel] [ma] ["9C]
+\definemathsymbol [ngeq] [rel] [ma] ["9D]
+\definemathsymbol [nless] [rel] [ma] ["9A]
+\definemathsymbol [ngtr] [rel] [ma] ["9B]
+\definemathsymbol [nprec] [rel] [ma] ["E5]
+\definemathsymbol [nsucc] [rel] [ma] ["E6]
+\definemathsymbol [lneqq] [rel] [ma] ["DC]
+\definemathsymbol [gneqq] [rel] [ma] ["DE]
+\definemathsymbol [nleqslant] [rel] [ma] ["D6]
+\definemathsymbol [ngeqslant] [rel] [ma] ["D7]
+\definemathsymbol [lneq] [rel] [ma] ["DA]
+\definemathsymbol [gneq] [rel] [ma] ["DB]
+\definemathsymbol [npreceq] [rel] [ma] ["E7]
+\definemathsymbol [nsucceq] [rel] [ma] ["E8]
+\definemathsymbol [precnsim] [rel] [ma] ["EB]
+\definemathsymbol [succnsim] [rel] [ma] ["EC]
+\definemathsymbol [lnsim] [rel] [ma] ["E0]
+\definemathsymbol [gnsim] [rel] [ma] ["E2]
+\definemathsymbol [nleqq] [rel] [ma] ["D8]
+\definemathsymbol [ngeqq] [rel] [ma] ["D9]
+\definemathsymbol [precneqq] [rel] [ma] ["E9]
+\definemathsymbol [succneqq] [rel] [ma] ["EA]
+\definemathsymbol [precnapprox] [rel] [ma] ["ED]
+\definemathsymbol [succnapprox] [rel] [ma] ["EE]
+\definemathsymbol [lnapprox] [rel] [ma] ["E4]
+\definemathsymbol [gnapprox] [rel] [ma] ["E3]
+\definemathsymbol [nsim] [rel] [ma] ["96]
+\definemathsymbol [ncong] [rel] [ma] ["99]
+\definemathsymbol [diagup] [ord] [mb] ["CD]
+\definemathsymbol [diagdown] [ord] [mb] ["D8]
+\definemathsymbol [varsubsetneq] [rel] [ma] ["D0]
+\definemathsymbol [varsupsetneq] [rel] [ma] ["D1]
+\definemathsymbol [nsubseteqq] [rel] [ma] ["CA]
+\definemathsymbol [nsupseteqq] [rel] [ma] ["CB]
+\definemathsymbol [subsetneqq] [rel] [ma] ["CE]
+\definemathsymbol [supsetneqq] [rel] [ma] ["CF]
+\definemathsymbol [varsubsetneqq] [rel] [ma] ["D2]
+\definemathsymbol [varsupsetneqq] [rel] [ma] ["D3]
+\definemathsymbol [subsetneq] [rel] [ma] ["CC]
+\definemathsymbol [supsetneq] [rel] [ma] ["CD]
+\definemathsymbol [nsubseteq] [rel] [ma] ["C8]
+\definemathsymbol [nsupseteq] [rel] [ma] ["C9]
+\definemathsymbol [nparallel] [rel] [ma] ["F7]
+\definemathsymbol [nmid] [rel] [ma] ["F6]
+\definemathsymbol [nshortmid] [rel] [ma] ["F4]
+\definemathsymbol [nshortparallel] [rel] [ma] ["F5]
+\definemathsymbol [nvdash] [rel] [ma] ["F8]
+\definemathsymbol [nVdash] [rel] [ma] ["F9]
+\definemathsymbol [nvDash] [rel] [ma] ["FA]
+\definemathsymbol [nVDash] [rel] [ma] ["FB]
+\definemathsymbol [ntrianglerighteq] [rel] [ma] ["F2]
+\definemathsymbol [ntrianglelefteq] [rel] [ma] ["F1]
+\definemathsymbol [ntriangleleft] [rel] [ma] ["EF]
+\definemathsymbol [ntriangleright] [rel] [ma] ["F0]
+\definemathsymbol [nleftarrow] [rel] [ma] ["32]
+\definemathsymbol [nrightarrow] [rel] [ma] ["33]
+\definemathsymbol [nLeftarrow] [rel] [ma] ["66]
+\definemathsymbol [nRightarrow] [rel] [ma] ["68]
+\definemathsymbol [nLeftrightarrow] [rel] [ma] ["67]
+\definemathsymbol [nleftrightarrow] [rel] [ma] ["34]
+\definemathsymbol [divideontimes] [bin] [mb] ["F7]
+\definemathsymbol [varnothing] [ord] [sy] ["53]
+\definemathsymbol [nexists] [ord] [ma] ["20]
+\definemathsymbol [Finv] [ord] [mb] ["90]
+\definemathsymbol [Game] [ord] [mb] ["91]
+\definemathsymbol [mho] [ord] [mb] ["92]
+\definemathsymbol [eth] [ord] [ma] ["03] % !!
+\definemathsymbol [eqsim] [rel] [sy] ["99]
+\definemathsymbol [beth] [ord] [mb] ["95]
+\definemathsymbol [gimel] [ord] [mb] ["96]
+\definemathsymbol [daleth] [ord] [mb] ["97]
+\definemathsymbol [lessdot] [bin] [mb] ["DC]
+\definemathsymbol [gtrdot] [bin] [mb] ["DD]
+\definemathsymbol [ltimes] [bin] [mb] ["CF]
+\definemathsymbol [rtimes] [bin] [mb] ["CE]
+\definemathsymbol [shortmid] [rel] [mb] ["F4]
+\definemathsymbol [shortparallel] [rel] [mb] ["F5]
+\definemathsymbol [smallsetminus] [bin] [mb] ["D8]
+\definemathsymbol [thicksim] [rel] [sy] ["18] % not that thick
+\definemathsymbol [thickapprox] [rel] [sy] ["19] % not that thick
+\definemathsymbol [approxeq] [rel] [sy] ["9D]
+\definemathsymbol [succapprox] [rel] [mb] ["ED]
+\definemathsymbol [precapprox] [rel] [mb] ["EC]
+\definemathsymbol [curvearrowleft] [rel] [ma] ["87]
+\definemathsymbol [curvearrowright] [rel] [ma] ["88]
+\definemathsymbol [digamma] [ord] [ma] ["03] % !!
+\definemathsymbol [varkappa] [ord] [mb] ["9B]
+\definemathsymbol [Bbbk] [ord] [ma] ["6B]
+\definemathsymbol [hslash] [ord] [mb] ["9D]
+\definemathsymbol [hbar] [ord] [ma] ["1B]
+\definemathsymbol [backepsilon] [rel] [ma] ["03] % !!
+
+\stopmathcollection
+
+\startmathcollection [lbr]
+
+\definemathsymbol [yen] [nothing] [ma] ["03] % !!
+\definemathsymbol [checkmark] [nothing] [ma] ["AC]
+\definemathsymbol [circledR] [nothing] [mb] ["C9]
+\definemathsymbol [maltese] [nothing] [mb] ["CB]
+
+\stopmathcollection
+
+\startmathcollection [lbr]
+
+\definemathsymbol [dashrightarrow] [rel] [ma] ["3A]
+\definemathsymbol [dashleftarrow] [rel] [ma] ["38]
+\definemathcommand [dasharrow] [rel] {\dashleftarrow\mkern-15.8mu\dashrightarrow}
+%definemathcommand [Join] [rel] {\mathchar"0D6F\mkern-15.8mu\mathchar"0D6E} % !!
+
+\stopmathcollection
+
+\startmathcollection[lbr]
+
+\definemathcharacter [91] [open] [mi] ["86]
+\definemathcharacter [93] [close] [mi] ["87]
+\definemathcharacter [(] [open] [mi] ["84]
+\definemathcharacter [)] [close] [mi] ["85]
+\definemathcharacter [/] [nothing] [mi] ["3D]
+\definemathcharacter [=] [rel] [sy] ["83]
+\definemathcharacter [+] [bin] [sy] ["82]
+
+\definemathcharacter [91] [nothing] [mi] ["86] [ex] ["02]
+\definemathcharacter [93] [nothing] [mi] ["87] [ex] ["03]
+\definemathcharacter [(] [nothing] [mi] ["84] [ex] ["00]
+\definemathcharacter [)] [nothing] [mi] ["85] [ex] ["01]
+\definemathcharacter [/] [nothing] [mi] ["3D] [ex] ["0E]
+
+\stopmathcollection
+
+% \startmathcollection[lbr]
+%
+% \definemathcharacter [:] [punct] [tf] ["3A] % unbelievable
+% \definemathcharacter [;] [punct] [tf] ["3B] % unbelievable
+%
+% \stopmathcollection
+
+\startmathcollection[lbr]
+
+\definemathsymbol [ldbrack] [open] [mi] ["82] [ex] ["82]
+\definemathsymbol [rdbrack] [close] [mi] ["83] [ex] ["83]
+\definemathsymbol [surfintop] [op] [ex] ["90]
+\definemathsymbol [midintop] [op] [ex] ["92]
+\definemathsymbol [midointop] [op] [ex] ["93]
+\definemathsymbol [midsurfintop] [op] [ex] ["94]
+\definemathsymbol [largeint] [op] [ex] ["5A] [ex] ["95]
+
+% \definemathcommand [surfint] [nolop] {\surfintop}
+% \definemathcommand [midint] [nolop] {\midintop}
+% \definemathcommand [midoint] [nolop] {\midointop}
+% \definemathcommand [midsurfint] [nolop] {\midsurfintop}
+
+\definemathsymbol [surfint] [nolop] [ex] ["90]
+\definemathsymbol [midint] [nolop] [ex] ["92]
+\definemathsymbol [midoint] [nolop] [ex] ["93]
+\definemathsymbol [midsurfint] [nolop] [ex] ["94]
+
+\definemathsymbol [dblint] [ord] [mi] ["88]
+\definemathsymbol [trplint] [ord] [mi] ["89]
+\definemathsymbol [contint] [ord] [mi] ["8A]
+\definemathsymbol [surfint] [ord] [mi] ["8B]
+\definemathsymbol [volint] [ord] [mi] ["8C]
+\definemathsymbol [clwint] [ord] [mi] ["8D]
+\definemathsymbol [cclwcint] [ord] [mi] ["8E]
+\definemathsymbol [clwcint] [ord] [mi] ["8F]
+\definemathsymbol [bowtie] [rel] [mi] ["F6]
+\definemathsymbol [models] [rel] [sy] ["EE]
+\definemathsymbol [doteq] [rel] [sy] ["C9]
+\definemathsymbol [cong] [rel] [sy] ["9B]
+\definemathsymbol [hbar] [ord] [mi] ["9D]
+\definemathsymbol [neq] [rel] [ma] ["94]
+\definemathsymbol [rightleftharpoons] [rel] [ma] ["7A]
+\definemathsymbol [leftrightharpoons] [rel] [ma] ["79]
+\definemathsymbol [hookleftarrow] [rel] [ma] ["3C]
+\definemathsymbol [hookrightarrow] [rel] [ma] ["3E]
+\definemathsymbol [mapsto] [rel] [ma] ["2C]
+
+\definemathcommand [longmapsto] {\mapstochar\longrightarrow}
+
+\stopmathcollection
+
+\startmathcollection[lbr]
+
+\definemathsymbol [Gamma] [alpha] [ucgreek] ["00]
+\definemathsymbol [Delta] [alpha] [ucgreek] ["01]
+\definemathsymbol [Theta] [alpha] [ucgreek] ["02]
+\definemathsymbol [Lambda] [alpha] [ucgreek] ["03]
+\definemathsymbol [Xi] [alpha] [ucgreek] ["04]
+\definemathsymbol [Pi] [alpha] [ucgreek] ["05]
+\definemathsymbol [Sigma] [alpha] [ucgreek] ["06]
+\definemathsymbol [Upsilon] [alpha] [ucgreek] ["07]
+\definemathsymbol [Phi] [alpha] [ucgreek] ["08]
+\definemathsymbol [Psi] [alpha] [ucgreek] ["09]
+\definemathsymbol [Omega] [alpha] [ucgreek] ["0A]
+
+\definemathsymbol [varGamma] [ord] [vargreek] ["00]
+\definemathsymbol [varDelta] [ord] [vargreek] ["01]
+\definemathsymbol [varTheta] [ord] [vargreek] ["02]
+\definemathsymbol [varLambda] [ord] [vargreek] ["03]
+\definemathsymbol [varXi] [ord] [vargreek] ["04]
+\definemathsymbol [varPi] [ord] [vargreek] ["05]
+\definemathsymbol [varSigma] [ord] [vargreek] ["06]
+\definemathsymbol [varUpsilon] [ord] [vargreek] ["07]
+\definemathsymbol [varPhi] [ord] [vargreek] ["08]
+\definemathsymbol [varPsi] [ord] [vargreek] ["09]
+\definemathsymbol [varOmega] [ord] [vargreek] ["0A]
+
+\stopmathcollection
+
+% we define the whole lot, although only a few differ (esp dot)
+
+% \startmathcollection[lbr]
+%
+% \definemathsymbol [acute] [accent] [tf] ["13] % mr -> tf
+% \definemathsymbol [grave] [accent] [tf] ["12] % mr -> tf
+% \definemathsymbol [ddot] [accent] [tf] ["7F] % mr -> tf
+% \definemathsymbol [tilde] [accent] [tf] ["7E] % mr -> tf
+% \definemathsymbol [bar] [accent] [tf] ["16] % mr -> tf
+% \definemathsymbol [breve] [accent] [tf] ["15] % mr -> tf
+% \definemathsymbol [check] [accent] [tf] ["14] % mr -> tf
+% \definemathsymbol [hat] [accent] [tf] ["5E] % mr -> tf
+% \definemathsymbol [vec] [accent] [mi] ["7E] % [ord]
+% \definemathsymbol [dot] [accent] [tf] ["05] % mr -> tf, 5F -> 05
+% \definemathsymbol [widetilde] [accent] [ex] ["65] % [ord]
+% \definemathsymbol [widehat] [accent] [ex] ["62] % [ord]
+%
+% \stopmathcollection
+
+\startmathcollection[lbr:texnansi]
+ \definemathsymbol [acute] [accent] [tf] ["13]
+ \definemathsymbol [grave] [accent] [tf] ["12]
+ \definemathsymbol [ddot] [accent] [tf] ["7F]
+ %definemathsymbol [ddot] [accent] [tf] ["A8] % both is OK
+ \definemathsymbol [tilde] [accent] [tf] ["7E]
+ %definemathsymbol [tilde] [accent] [tf] ["98] % both is OK
+ \definemathsymbol [bar] [accent] [tf] ["16]
+ \definemathsymbol [breve] [accent] [tf] ["15]
+ \definemathsymbol [check] [accent] [tf] ["14]
+ \definemathsymbol [hat] [accent] [tf] ["5E]
+ %definemathsymbol [hat] [accent] [tf] ["88] % both is OK
+ \definemathsymbol [dot] [accent] [tf] ["05]
+ % Why is mathring not defined??
+ \definemathsymbol [mathring] [accent] [tf] ["17]
+\stopmathcollection
+
+\startmathcollection[lbr:ec]
+ \definemathsymbol [acute] [accent] [tf] ["01]
+ \definemathsymbol [grave] [accent] [tf] ["00]
+ \definemathsymbol [ddot] [accent] [tf] ["04]
+ \definemathsymbol [tilde] [accent] [tf] ["03]
+ \definemathsymbol [bar] [accent] [tf] ["09]
+ \definemathsymbol [breve] [accent] [tf] ["08]
+ \definemathsymbol [check] [accent] [tf] ["07]
+ \definemathsymbol [hat] [accent] [tf] ["02]
+ \definemathsymbol [dot] [accent] [tf] ["0A]
+ % Why is mathring not defined??
+ \definemathsymbol [mathring] [accent] [tf] ["06]
+\stopmathcollection
+
+\def\LBRroot#1#2%
+ {\setbox\zerocount\hbox{$\mathsurround\zeropoint#1\sqrt{#2}$}
+ \dimen@\ht\zerocount \advance\dimen@-\dp\zerocount
+ \mkern5mu\raise.6\dimen@\copy\rootbox \mkern-7.5mu \box\zerocount}
+
+\def\LBRmatrix#1%
+ {\null\,\vcenter{\normalbaselines\mathsurround\zeropoint
+ \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
+ \mathstrut\crcr\noalign{\kern-0.9\baselineskip}
+ #1\crcr\mathstrut\crcr\noalign{\kern-0.9\baselineskip}}}\,}
+
+\startrawmathcollection[lbr]
+
+\definemathcommand [mathstrut] {\vphantom{f}}
+\definemathcommand [joinrel] {\mathrel{\mkern-4mu}}
+\definemathcommand [r@@t] {\LBRroot}
+\definemathcommand [matrix] {\LBRmatrix}
+
+\stoprawmathcollection
+
+\def\LBRbig {\@@dobig{8.20}}
+\def\LBRBig {\@@dobig{10.80}}
+\def\LBRbigg {\@@dobig{13.42}}
+\def\LBRBigg {\@@dobig{16.03}}
+\def\LBRbiggg{\@@dobig{17.72}}
+\def\LBRBiggg{\@@dobig{21.25}}
+
+% \def\LBRbig {\@@dobig{0.820}}
+% \def\LBRBig {\@@dobig{1.080}}
+% \def\LBRbigg {\@@dobig{1.342}}
+% \def\LBRBigg {\@@dobig{1.603}}
+% \def\LBRbiggg{\@@dobig{1.772}}
+% \def\LBRBiggg{\@@dobig{2.125}}
+
+\startrawmathcollection[lbr]
+
+\definemathcommand [big] {\LBRbig}
+\definemathcommand [Big] {\LBRBig}
+\definemathcommand [bigg] {\LBRbigg}
+\definemathcommand [Bigg] {\LBRBigg}
+\definemathcommand [biggg] {\LBRbiggg}
+\definemathcommand [Biggg] {\LBRBiggg}
+
+\stoprawmathcollection
+
+\startrawmathcollection[lbr]
+
+\definemathcommand [bigggl] [open] {\biggg}
+\definemathcommand [bigggr] [close] {\biggg}
+\definemathcommand [Bigggl] [open] {\Biggg}
+\definemathcommand [Bigggr] [close] {\Biggg}
+
+\stoprawmathcollection
+
+\protect \endinput
diff --git a/tex/context/base/math-map.lua b/tex/context/base/math-map.lua
new file mode 100644
index 000000000..2d34dc1c3
--- /dev/null
+++ b/tex/context/base/math-map.lua
@@ -0,0 +1,440 @@
+if not modules then modules = { } end modules ['math-map'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
Remapping mathematics alphabets.
+--ldx]]--
+
+-- oldstyle: not really mathematics but happened to be part of
+-- the mathematics fonts in cmr
+--
+-- persian: we will also provide mappers for other
+-- scripts
+
+-- todo: alphabets namespace
+-- maybe: script/scriptscript dynamic,
+
+local type, next = type, next
+local floor = math.floor
+
+local texattribute = tex.attribute
+
+local trace_greek = false trackers.register("math.greek", function(v) trace_greek = v end)
+
+mathematics = mathematics or { }
+
+-- we could use one level less and have tf etc be tables directly but the
+-- following approach permits easier remapping of a-a, A-Z and 0-9 to
+-- fallbacks; symbols is currently mostly greek
+
+mathematics.alphabets = {
+ regular = {
+ tf = {
+ digits = 0x00030,
+ ucletters = 0x00041,
+ lcletters = 0x00061,
+ ucgreek = {
+ [0x0391]=0x0391, [0x0392]=0x0392, [0x0393]=0x0393, [0x0394]=0x0394, [0x0395]=0x0395,
+ [0x0396]=0x0396, [0x0397]=0x0397, [0x0398]=0x0398, [0x0399]=0x0399, [0x039A]=0x039A,
+ [0x039B]=0x039B, [0x039C]=0x039C, [0x039D]=0x039D, [0x039E]=0x039E, [0x039F]=0x039F,
+ [0x03A0]=0x03A0, [0x03A1]=0x03A1, [0x03A3]=0x03A3, [0x03A4]=0x03A4, [0x03A5]=0x03A5,
+ [0x03A6]=0x03A6, [0x03A7]=0x03A7, [0x03A8]=0x03A8, [0x03A9]=0x03A9,
+ },
+ lcgreek = {
+ [0x03B1]=0x03B1, [0x03B2]=0x03B2, [0x03B3]=0x03B3, [0x03B4]=0x03B4, [0x03B5]=0x03B5,
+ [0x03B6]=0x03B6, [0x03B7]=0x03B7, [0x03B8]=0x03B8, [0x03B9]=0x03B9, [0x03BA]=0x03BA,
+ [0x03BB]=0x03BB, [0x03BC]=0x03BC, [0x03BD]=0x03BD, [0x03BE]=0x03BE, [0x03BF]=0x03BF,
+ [0x03C0]=0x03C0, [0x03C1]=0x03C1, [0x03C2]=0x03C2, [0x03C3]=0x03C3, [0x03C4]=0x03C4,
+ [0x03C5]=0x03C5, [0x03C6]=0x03C6, [0x03C7]=0x03C7, [0x03C8]=0x03C8, [0x03C9]=0x03C9,
+ [0x03D1]=0x03D1, [0x03D5]=0x03D5, [0x03D6]=0x03D6, [0x03F0]=0x03F0, [0x03F1]=0x03F1,
+ [0x03F4]=0x03F4, [0x03F5]=0x03F5,
+ },
+ symbols = {
+ [0x2202]=0x2202, [0x2207]=0x2207,
+ },
+ },
+ it = {
+ ucletters = 0x1D434,
+ lcletters = { -- H
+ [0x00061]=0x1D44E, [0x00062]=0x1D44F, [0x00063]=0x1D450, [0x00064]=0x1D451, [0x00065]=0x1D452,
+ [0x00066]=0x1D453, [0x00067]=0x1D454, [0x00068]=0x0210E, [0x00069]=0x1D456, [0x0006A]=0x1D457,
+ [0x0006B]=0x1D458, [0x0006C]=0x1D459, [0x0006D]=0x1D45A, [0x0006E]=0x1D45B, [0x0006F]=0x1D45C,
+ [0x00070]=0x1D45D, [0x00071]=0x1D45E, [0x00072]=0x1D45F, [0x00073]=0x1D460, [0x00074]=0x1D461,
+ [0x00075]=0x1D462, [0x00076]=0x1D463, [0x00077]=0x1D464, [0x00078]=0x1D465, [0x00079]=0x1D466,
+ [0x0007A]=0x1D467,
+ },
+ ucgreek = {
+ [0x0391]=0x1D6E2, [0x0392]=0x1D6E3, [0x0393]=0x1D6E4, [0x0394]=0x1D6E5, [0x0395]=0x1D6E6,
+ [0x0396]=0x1D6E7, [0x0397]=0x1D6E8, [0x0398]=0x1D6E9, [0x0399]=0x1D6EA, [0x039A]=0x1D6EB,
+ [0x039B]=0x1D6EC, [0x039C]=0x1D6ED, [0x039D]=0x1D6EE, [0x039E]=0x1D6EF, [0x039F]=0x1D6F0,
+ [0x03A0]=0x1D6F1, [0x03A1]=0x1D6F2, [0x03A3]=0x1D6F4, [0x03A4]=0x1D6F5, [0x03A5]=0x1D6F6,
+ [0x03A6]=0x1D6F7, [0x03A7]=0x1D6F8, [0x03A8]=0x1D6F9, [0x03A9]=0x1D6FA,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D6FC, [0x03B2]=0x1D6FD, [0x03B3]=0x1D6FE, [0x03B4]=0x1D6FF, [0x03B5]=0x1D700,
+ [0x03B6]=0x1D701, [0x03B7]=0x1D702, [0x03B8]=0x1D703, [0x03B9]=0x1D704, [0x03BA]=0x1D705,
+ [0x03BB]=0x1D706, [0x03BC]=0x1D707, [0x03BD]=0x1D708, [0x03BE]=0x1D709, [0x03BF]=0x1D70A,
+ [0x03C0]=0x1D70B, [0x03C1]=0x1D70C, [0x03C2]=0x1D70D, [0x03C3]=0x1D70E, [0x03C4]=0x1D70F,
+ [0x03C5]=0x1D710, [0x03C6]=0x1D711, [0x03C7]=0x1D712, [0x03C8]=0x1D713, [0x03C9]=0x1D714,
+ [0x03D1]=0x1D717, [0x03D5]=0x1D719, [0x03D6]=0x1D71B, [0x03F0]=0x1D718, [0x03F1]=0x1D71A,
+ [0x03F4]=0x1D6F3, [0x03F5]=0x1D716,
+ },
+ symbols = {
+ [0x2202]=0x1D715, [0x2207]=0x1D6FB,
+ },
+ },
+ bf= {
+ digits = 0x1D7CE,
+ ucletters = 0x1D400,
+ lcletters = 0x1D41A,
+ ucgreek = {
+ [0x0391]=0x1D6A8, [0x0392]=0x1D6A9, [0x0393]=0x1D6AA, [0x0394]=0x1D6AB, [0x0395]=0x1D6AC,
+ [0x0396]=0x1D6AD, [0x0397]=0x1D6AE, [0x0398]=0x1D6AF, [0x0399]=0x1D6B0, [0x039A]=0x1D6B1,
+ [0x039B]=0x1D6B2, [0x039C]=0x1D6B3, [0x039D]=0x1D6B4, [0x039E]=0x1D6B5, [0x039F]=0x1D6B6,
+ [0x03A0]=0x1D6B7, [0x03A1]=0x1D6B8, [0x03A3]=0x1D6BA, [0x03A4]=0x1D6BB, [0x03A5]=0x1D6BC,
+ [0x03A6]=0x1D6BD, [0x03A7]=0x1D6BE, [0x03A8]=0x1D6BF, [0x03A9]=0x1D6C0,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D6C2, [0x03B2]=0x1D6C3, [0x03B3]=0x1D6C4, [0x03B4]=0x1D6C5, [0x03B5]=0x1D6C6,
+ [0x03B6]=0x1D6C7, [0x03B7]=0x1D6C8, [0x03B8]=0x1D6C9, [0x03B9]=0x1D6CA, [0x03BA]=0x1D6CB,
+ [0x03BB]=0x1D6CC, [0x03BC]=0x1D6CD, [0x03BD]=0x1D6CE, [0x03BE]=0x1D6CF, [0x03BF]=0x1D6D0,
+ [0x03C0]=0x1D6D1, [0x03C1]=0x1D6D2, [0x03C2]=0x1D6D3, [0x03C3]=0x1D6D4, [0x03C4]=0x1D6D5,
+ [0x03C5]=0x1D6D6, [0x03C6]=0x1D6D7, [0x03C7]=0x1D6D8, [0x03C8]=0x1D6D9, [0x03C9]=0x1D6DA,
+ [0x03D1]=0x1D6DD, [0x03D5]=0x1D6DF, [0x03D6]=0x1D6E1, [0x03F0]=0x1D6DE, [0x03F1]=0x1D6E0,
+ [0x03F4]=0x1D6B9, [0x03F5]=0x1D6DC,
+ },
+ symbols = {
+ [0x2202]=0x1D6DB, [0x2207]=0x1D6C1,
+ },
+ },
+ bi = {
+ ucletters = 0x1D468,
+ lcletters = 0x1D482,
+ ucgreek = {
+ [0x0391]=0x1D71C, [0x0392]=0x1D71D, [0x0393]=0x1D71E, [0x0394]=0x1D71F, [0x0395]=0x1D720,
+ [0x0396]=0x1D721, [0x0397]=0x1D722, [0x0398]=0x1D723, [0x0399]=0x1D724, [0x039A]=0x1D725,
+ [0x039B]=0x1D726, [0x039C]=0x1D727, [0x039D]=0x1D728, [0x039E]=0x1D729, [0x039F]=0x1D72A,
+ [0x03A0]=0x1D72B, [0x03A1]=0x1D72C, [0x03A3]=0x1D72E, [0x03A4]=0x1D72F, [0x03A5]=0x1D730,
+ [0x03A6]=0x1D731, [0x03A7]=0x1D732, [0x03A8]=0x1D733, [0x03A9]=0x1D734,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D736, [0x03B2]=0x1D737, [0x03B3]=0x1D738, [0x03B4]=0x1D739, [0x03B5]=0x1D73A,
+ [0x03B6]=0x1D73B, [0x03B7]=0x1D73C, [0x03B8]=0x1D73D, [0x03B9]=0x1D73E, [0x03BA]=0x1D73F,
+ [0x03BB]=0x1D740, [0x03BC]=0x1D741, [0x03BD]=0x1D742, [0x03BE]=0x1D743, [0x03BF]=0x1D744,
+ [0x03C0]=0x1D745, [0x03C1]=0x1D746, [0x03C2]=0x1D747, [0x03C3]=0x1D748, [0x03C4]=0x1D749,
+ [0x03C5]=0x1D74A, [0x03C6]=0x1D74B, [0x03C7]=0x1D74C, [0x03C8]=0x1D74D, [0x03C9]=0x1D74E,
+ [0x03D1]=0x1D751, [0x03D5]=0x1D753, [0x03D6]=0x1D755, [0x03F0]=0x1D752, [0x03F1]=0x1D754,
+ [0x03F4]=0x1D72D, [0x03F5]=0x1D750,
+ },
+ symbols = {
+ [0x2202]=0x1D74F, [0x2207]=0x1D735,
+ },
+ },
+ },
+ sansserif = {
+ tf = {
+ digits = 0x1D7E2,
+ ucletters = 0x1D5A0,
+ lcletters = 0x1D5BA,
+ },
+ it = {
+ ucletters = 0x1D608,
+ lcletters = 0x1D622,
+ },
+ bf = {
+ digits = 0x1D7EC,
+ ucletters = 0x1D5D4,
+ lcletters = 0x1D5EE,
+ ucgreek = {
+ [0x0391]=0x1D756, [0x0392]=0x1D757, [0x0393]=0x1D758, [0x0394]=0x1D759, [0x0395]=0x1D75A,
+ [0x0396]=0x1D75B, [0x0397]=0x1D75C, [0x0398]=0x1D75D, [0x0399]=0x1D75E, [0x039A]=0x1D75F,
+ [0x039B]=0x1D760, [0x039C]=0x1D761, [0x039D]=0x1D762, [0x039E]=0x1D763, [0x039F]=0x1D764,
+ [0x03A0]=0x1D765, [0x03A1]=0x1D766, [0x03A3]=0x1D768, [0x03A4]=0x1D769, [0x03A5]=0x1D76A,
+ [0x03A6]=0x1D76B, [0x03A7]=0x1D76C, [0x03A8]=0x1D76D, [0x03A9]=0x1D76E,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D770, [0x03B2]=0x1D771, [0x03B3]=0x1D772, [0x03B4]=0x1D773, [0x03B5]=0x1D774,
+ [0x03B6]=0x1D775, [0x03B7]=0x1D776, [0x03B8]=0x1D777, [0x03B9]=0x1D778, [0x03BA]=0x1D779,
+ [0x03BB]=0x1D77A, [0x03BC]=0x1D77B, [0x03BD]=0x1D77C, [0x03BE]=0x1D77D, [0x03BF]=0x1D77E,
+ [0x03C0]=0x1D77F, [0x03C1]=0x1D780, [0x03C2]=0x1D781, [0x03C3]=0x1D782, [0x03C4]=0x1D783,
+ [0x03C5]=0x1D784, [0x03C6]=0x1D785, [0x03C7]=0x1D786, [0x03C8]=0x1D787, [0x03C9]=0x1D788,
+ [0x03D1]=0x1D78B, [0x03D5]=0x1D78D, [0x03D6]=0x1D78F, [0x03F0]=0x1D78C, [0x03F1]=0x1D78E,
+ [0x03F4]=0x1D767, [0x03F5]=0x1D78A,
+ },
+ symbols = {
+ [0x2202]=0x1D789, [0x2207]=0x1D76F,
+ },
+ },
+ bi = {
+ ucletters = 0x1D63C,
+ lcletters = 0x1D656,
+ ucgreek = {
+ [0x0391]=0x1D790, [0x0392]=0x1D791, [0x0393]=0x1D792, [0x0394]=0x1D793, [0x0395]=0x1D794,
+ [0x0396]=0x1D795, [0x0397]=0x1D796, [0x0398]=0x1D797, [0x0399]=0x1D798, [0x039A]=0x1D799,
+ [0x039B]=0x1D79A, [0x039C]=0x1D79B, [0x039D]=0x1D79C, [0x039E]=0x1D79D, [0x039F]=0x1D79E,
+ [0x03A0]=0x1D79F, [0x03A1]=0x1D7A0, [0x03A3]=0x1D7A2, [0x03A4]=0x1D7A3, [0x03A5]=0x1D7A4,
+ [0x03A6]=0x1D7A5, [0x03A7]=0x1D7A6, [0x03A8]=0x1D7A7, [0x03A9]=0x1D7A8,
+ },
+ lcgreek = {
+ [0x03B1]=0x1D7AA, [0x03B2]=0x1D7AB, [0x03B3]=0x1D7AC, [0x03B4]=0x1D7AD, [0x03B5]=0x1D7AE,
+ [0x03B6]=0x1D7AF, [0x03B7]=0x1D7B0, [0x03B8]=0x1D7B1, [0x03B9]=0x1D7B2, [0x03BA]=0x1D7B3,
+ [0x03BB]=0x1D7B4, [0x03BC]=0x1D7B5, [0x03BD]=0x1D7B6, [0x03BE]=0x1D7B7, [0x03BF]=0x1D7B8,
+ [0x03C0]=0x1D7B9, [0x03C1]=0x1D7BA, [0x03C2]=0x1D7BB, [0x03C3]=0x1D7BC, [0x03C4]=0x1D7BD,
+ [0x03C5]=0x1D7BE, [0x03C6]=0x1D7BF, [0x03C7]=0x1D7C0, [0x03C8]=0x1D7C1, [0x03C9]=0x1D7C2,
+ [0x03D1]=0x1D7C5, [0x03D5]=0x1D7C7, [0x03D6]=0x1D7C9, [0x03F0]=0x1D7C6, [0x03F1]=0x1D7C8,
+ [0x03F4]=0x1D7A1, [0x03F5]=0x1D7C4,
+ },
+ symbols = {
+ [0x2202]=0x1D7C3, [0x2207]=0x1D7A9,
+ },
+ },
+ },
+ monospaced = {
+ tf = {
+ digits = 0x1D7F6,
+ ucletters = 0x1D670,
+ lcletters = 0x1D68A,
+ },
+ },
+ blackboard = { -- ok
+ tf = {
+ digits = 0x1D7D8,
+ ucletters = { -- C H N P Q R Z
+ [0x00041]=0x1D538, [0x00042]=0x1D539, [0x00043]=0x02102, [0x00044]=0x1D53B, [0x00045]=0x1D53C,
+ [0x00046]=0x1D53D, [0x00047]=0x1D53E, [0x00048]=0x0210D, [0x00049]=0x1D540, [0x0004A]=0x1D541,
+ [0x0004B]=0x1D542, [0x0004C]=0x1D543, [0x0004D]=0x1D544, [0x0004E]=0x02115, [0x0004F]=0x1D546,
+ [0x00050]=0x02119, [0x00051]=0x0211A, [0x00052]=0x0211D, [0x00053]=0x1D54A, [0x00054]=0x1D54B,
+ [0x00055]=0x1D54C, [0x00056]=0x1D54D, [0x00057]=0x1D54E, [0x00058]=0x1D54F, [0x00059]=0x1D550,
+ [0x0005A]=0x02124,
+ },
+ lcletters = 0x1D552,
+ lcgreek = { -- gamma pi
+ [0x03B3]=0x0213C, [0x03C0]=0x0213D,
+ },
+ ucgreek = { -- Gamma pi
+ [0x0393]=0x0213E, [0x03A0]=0x0213F,
+ },
+ symbols = { -- sum
+ [0x2211]=0x02140,
+ },
+ },
+ },
+ fraktur = { -- ok
+ tf= {
+ ucletters = { -- C H I R Z
+ [0x00041]=0x1D504, [0x00042]=0x1D505, [0x00043]=0x0212D, [0x00044]=0x1D507, [0x00045]=0x1D508,
+ [0x00046]=0x1D509, [0x00047]=0x1D50A, [0x00048]=0x0210C, [0x00049]=0x02111, [0x0004A]=0x1D50D,
+ [0x0004B]=0x1D50E, [0x0004C]=0x1D50F, [0x0004D]=0x1D510, [0x0004E]=0x1D511, [0x0004F]=0x1D512,
+ [0x00050]=0x1D513, [0x00051]=0x1D514, [0x00052]=0x0211C, [0x00053]=0x1D516, [0x00054]=0x1D517,
+ [0x00055]=0x1D518, [0x00056]=0x1D519, [0x00057]=0x1D51A, [0x00058]=0x1D51B, [0x00059]=0x1D51C,
+ [0x0005A]=0x02128,
+ },
+ lcletters = 0x1D51E,
+ },
+ bf = {
+ ucletters = 0x1D56C,
+ lcletters = 0x1D586,
+ },
+ },
+ script = {
+ tf= {
+ ucletters = { -- B E F H I L M R -- P 2118
+ [0x00041]=0x1D49C, [0x00042]=0x0212C, [0x00043]=0x1D49E, [0x00044]=0x1D49F, [0x00045]=0x02130,
+ [0x00046]=0x02131, [0x00047]=0x1D4A2, [0x00048]=0x0210B, [0x00049]=0x02110, [0x0004A]=0x1D4A5,
+ [0x0004B]=0x1D4A6, [0x0004C]=0x02112, [0x0004D]=0x02133, [0x0004E]=0x1D4A9, [0x0004F]=0x1D4AA,
+ [0x00050]=0x1D4AB, [0x00051]=0x1D4AC, [0x00052]=0x0211B, [0x00053]=0x1D4AE, [0x00054]=0x1D4AF,
+ [0x00055]=0x1D4B0, [0x00056]=0x1D4B1, [0x00057]=0x1D4B2, [0x00058]=0x1D4B3, [0x00059]=0x1D4B4,
+ [0x0005A]=0x1D4B5,
+ },
+ lcletters = { -- E G O -- L 2113
+ [0x00061]=0x1D4B6, [0x00062]=0x1D4B7, [0x00063]=0x1D4B8, [0x00064]=0x1D4B9, [0x00065]=0x0212F,
+ [0x00066]=0x1D4BB, [0x00067]=0x0210A, [0x00068]=0x1D4BD, [0x00069]=0x1D4BE, [0x0006A]=0x1D4BF,
+ [0x0006B]=0x1D4C0, [0x0006C]=0x1D4C1, [0x0006D]=0x1D4C2, [0x0006E]=0x1D4C3, [0x0006F]=0x02134,
+ [0x00070]=0x1D4C5, [0x00071]=0x1D4C6, [0x00072]=0x1D4C7, [0x00073]=0x1D4C8, [0x00074]=0x1D4C9,
+ [0x00075]=0x1D4CA, [0x00076]=0x1D4CB, [0x00077]=0x1D4CC, [0x00078]=0x1D4CD, [0x00079]=0x1D4CE,
+ [0x0007A]=0x1D4CF,
+ }
+ },
+ bf = {
+ ucletters = 0x1D4D0,
+ lcletters = 0x1D4EA,
+ },
+ },
+}
+
+local alphabets = mathematics.alphabets
+local mathremap = { }
+
+for alphabet, styles in next, alphabets do
+ for style, data in next, styles do
+ -- let's keep the long names (for tracing)
+ local n = #mathremap + 1
+ data.attribute = n
+ data.alphabet = alphabet
+ data.style = style
+ mathremap[n] = data
+ end
+end
+
+-- beware, these are shared tables (no problem since they're not
+-- in unicode)
+
+alphabets.regular.it.digits = alphabets.regular.tf.digits
+alphabets.regular.bi.digits = alphabets.regular.bf.digits
+
+alphabets.sansserif.tf.symbols = alphabets.regular.tf.symbols
+alphabets.sansserif.tf.lcgreek = alphabets.regular.tf.lcgreek
+alphabets.sansserif.tf.ucgreek = alphabets.regular.tf.ucgreek
+alphabets.sansserif.tf.digits = alphabets.regular.tf.digits
+alphabets.sansserif.it.symbols = alphabets.regular.tf.symbols
+alphabets.sansserif.it.lcgreek = alphabets.regular.tf.lcgreek
+alphabets.sansserif.it.ucgreek = alphabets.regular.tf.ucgreek
+alphabets.sansserif.bi.digits = alphabets.regular.bf.digits
+
+alphabets.monospaced.tf.symbols = alphabets.sansserif.tf.symbols
+alphabets.monospaced.tf.lcgreek = alphabets.sansserif.tf.lcgreek
+alphabets.monospaced.tf.ucgreek = alphabets.sansserif.tf.ucgreek
+alphabets.monospaced.it = alphabets.sansserif.tf
+alphabets.monospaced.bf = alphabets.sansserif.tf
+alphabets.monospaced.bi = alphabets.sansserif.bf
+
+alphabets.blackboard.tf.symbols = table.merge(alphabets.regular.tf.symbols, alphabets.blackboard.tf.symbols)
+alphabets.blackboard.tf.lcgreek = table.merge(alphabets.regular.tf.lcgreek, alphabets.blackboard.tf.lcgreek)
+alphabets.blackboard.tf.ucgreek = table.merge(alphabets.regular.tf.ucgreek, alphabets.blackboard.tf.ucgreek)
+
+alphabets.blackboard.it = alphabets.blackboard.tf
+alphabets.blackboard.bf = alphabets.blackboard.tf
+alphabets.blackboard.bi = alphabets.blackboard.bf
+
+alphabets.fraktur.tf.digits = alphabets.regular.tf.digits
+alphabets.fraktur.tf.symbols = alphabets.regular.tf.symbols
+alphabets.fraktur.tf.lcgreek = alphabets.regular.tf.lcgreek
+alphabets.fraktur.tf.ucgreek = alphabets.regular.tf.ucgreek
+alphabets.fraktur.bf.digits = alphabets.regular.bf.digits
+alphabets.fraktur.bf.symbols = alphabets.regular.bf.symbols
+alphabets.fraktur.bf.lcgreek = alphabets.regular.bf.lcgreek
+alphabets.fraktur.bf.ucgreek = alphabets.regular.bf.ucgreek
+alphabets.fraktur.it = alphabets.fraktur.tf
+alphabets.fraktur.bi = alphabets.fraktur.bf
+
+alphabets.script.tf.digits = alphabets.regular.tf.digits
+alphabets.script.tf.symbols = alphabets.regular.tf.symbols
+alphabets.script.tf.lcgreek = alphabets.regular.tf.lcgreek
+alphabets.script.tf.ucgreek = alphabets.regular.tf.ucgreek
+alphabets.script.bf.digits = alphabets.regular.bf.digits
+alphabets.script.bf.symbols = alphabets.regular.bf.symbols
+alphabets.script.bf.lcgreek = alphabets.regular.bf.lcgreek
+alphabets.script.bf.ucgreek = alphabets.regular.bf.ucgreek
+alphabets.script.it = alphabets.script.tf
+alphabets.script.bi = alphabets.script.bf
+
+alphabets.tt = alphabets.monospaced
+alphabets.ss = alphabets.sansserif
+alphabets.rm = alphabets.regular
+alphabets.bb = alphabets.blackboard
+alphabets.fr = alphabets.fraktur
+alphabets.sr = alphabets.script
+
+alphabets.serif = alphabets.regular
+alphabets.type = alphabets.monospaced
+alphabets.teletype = alphabets.monospaced
+
+function mathematics.to_a_style(attribute)
+ local r = mathremap[attribute]
+ return r and r.style or "tf"
+end
+
+function mathematics.to_a_name(attribute)
+ local r = mathremap[attribute]
+ return r and r.alphabet or "regular"
+end
+
+-- of course we could do some div/mod trickery instead
+
+local mathalphabet = attributes.private("mathalphabet")
+
+function mathematics.sync_a_both(alphabet,style)
+ local data = alphabets[alphabet or "regular"] or alphabets.regular
+ data = data[style or "tf"] or data.tf
+ texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
+end
+
+function mathematics.sync_a_style(style)
+--~ local r = mathremap[mathalphabet]
+ local r = mathremap[texattribute[mathalphabet]]
+ local alphabet = r and r.alphabet or "regular"
+ local data = alphabets[alphabet][style]
+ texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
+end
+
+function mathematics.sync_a_name(alphabet)
+--~ local r = mathremap[mathalphabet]
+ local r = mathremap[texattribute[mathalphabet]]
+ local style = r and r.style or "tf"
+ local data = alphabets[alphabet][style]
+ texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
+end
+
+local issymbol = mathematics.alphabets.regular.tf.symbols
+local islcgreek = mathematics.alphabets.regular.tf.lcgreek
+local isucgreek = mathematics.alphabets.regular.tf.ucgreek
+
+local remapping = {
+ [1] = { what = "unchanged" }, -- upright
+ [2] = { what = "upright", it = "tf", bi = "bf" }, -- upright
+ [3] = { what = "italic", tf = "it", bf = "bi" }, -- italic
+}
+
+function mathematics.remap_alphabets(char,mathalphabet,mathgreek)
+ if mathgreek > 0 then
+ local lc, uc = floor(mathgreek/10), mathgreek % 10 -- 2 == upright 3 == italic
+ if lc > 1 or uc > 1 then
+ local islc, isuc = islcgreek[char] and lc, isucgreek[char] and uc
+ if islc or isuc then
+ local r = mathremap[mathalphabet] -- what if 0
+ local alphabet = r and r.alphabet or "regular"
+ local style = r and r.style or "tf"
+ if trace_greek then
+ logs.report("math","before: char: %05X, alphabet: %s %s, lcgreek: %s, ucgreek: %s",char,alphabet,style,remapping[lc].what,remapping[uc].what)
+ end
+ local s = remapping[islc or isuc][style]
+ if s then
+ local data = alphabets[alphabet][s]
+ mathalphabet, style = data and data.attribute or mathalphabet, s
+ end
+ if trace_greek then
+ logs.report("math","after : char: %05X, alphabet: %s %s, lcgreek: %s, ucgreek: %s",char,alphabet,style,remapping[lc].what,remapping[uc].what)
+ end
+ end
+ end
+ end
+ if mathalphabet > 0 then
+ local newchar
+ local offset = mathremap[mathalphabet]
+ if not offset then
+ -- nothing to remap
+ elseif char >= 0x030 and char <= 0x039 then
+ local o = offset.digits
+ newchar = (type(o) == "table" and (o[char] or char)) or (char - 0x030 + o)
+ elseif char >= 0x041 and char <= 0x05A then
+ local o = offset.ucletters
+ newchar = (type(o) == "table" and (o[char] or char)) or (char - 0x041 + o)
+ elseif char >= 0x061 and char <= 0x07A then
+ local o = offset.lcletters
+ newchar = (type(o) == "table" and (o[char] or char)) or (char - 0x061 + o)
+ elseif islcgreek[char] then
+ newchar = offset.lcgreek[char]
+ elseif isucgreek[char] then
+ newchar = offset.ucgreek[char]
+ elseif issymbol[char] then
+ newchar = offset.symbols[char]
+ end
+ return newchar ~= char and newchar
+ end
+ return nil
+end
diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua
new file mode 100644
index 000000000..02bbe0a62
--- /dev/null
+++ b/tex/context/base/math-noa.lua
@@ -0,0 +1,369 @@
+if not modules then modules = { } end modules ['math-noa'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- beware: this is experimental code and there will be a more
+-- generic (attribute value driven) interface too but for the
+-- moment this is ok
+
+local utf = unicode.utf8
+
+local set_attribute = node.set_attribute
+local has_attribute = node.has_attribute
+local mlist_to_hlist = node.mlist_to_hlist
+local font_of_family = node.family_font
+local fontdata = fonts.identifiers
+
+local format, rep = string.format, string.rep
+local utfchar, utfbyte = utf.char, utf.byte
+
+noads = noads or { }
+
+local trace_remapping = false trackers.register("math.remapping", function(v) trace_remapping = v end)
+local trace_processing = false trackers.register("math.processing", function(v) trace_processing = v end)
+local trace_analyzing = false trackers.register("math.analyzing", function(v) trace_analyzing = v end)
+
+local noad_ord = 0
+local noad_op_displaylimits = 1
+local noad_op_limits = 2
+local noad_op_nolimits = 3
+local noad_bin = 4
+local noad_rel = 5
+local noad_open = 6
+local noad_close = 7
+local noad_punct = 8
+local noad_inner = 9
+local noad_under = 10
+local noad_over = 11
+local noad_vcenter = 12
+
+-- obsolete:
+--
+-- math_ord = node.id("ord") -- attr nucleus sub sup
+-- math_op = node.id("op") -- attr nucleus sub sup subtype
+-- math_bin = node.id("bin") -- attr nucleus sub sup
+-- math_rel = node.id("rel") -- attr nucleus sub sup
+-- math_punct = node.id("punct") -- attr nucleus sub sup
+--
+-- math_open = node.id("open") -- attr nucleus sub sup
+-- math_close = node.id("close") -- attr nucleus sub sup
+--
+-- math_inner = node.id("inner") -- attr nucleus sub sup
+-- math_vcenter = node.id("vcenter") -- attr nucleus sub sup
+-- math_under = node.id("under") -- attr nucleus sub sup
+-- math_over = node.id("over") -- attr nucleus sub sup
+
+local math_noad = node.id("noad") -- attr nucleus sub sup
+
+local math_accent = node.id("accent") -- attr nucleus sub sup accent
+local math_radical = node.id("radical") -- attr nucleus sub sup left degree
+local math_fraction = node.id("fraction") -- attr nucleus sub sup left right
+
+local math_box = node.id("sub_box") -- attr list
+local math_sub = node.id("sub_mlist") -- attr list
+local math_char = node.id("math_char") -- attr fam char
+local math_text_char = node.id("math_text_char") -- attr fam char
+local math_delim = node.id("delim") -- attr small_fam small_char large_fam large_char
+local math_style = node.id("style") -- attr style
+local math_choice = node.id("choice") -- attr display text script scriptscript
+local math_fence = node.id("fence") -- attr subtype
+
+local simple_noads = table.tohash {
+ math_noad,
+}
+
+local all_noads = {
+ math_noad,
+ math_box, math_sub,
+ math_char, math_text_char, math_delim, math_style,
+ math_accent, math_radical, math_fraction, math_choice, math_fence,
+}
+
+noads.processors = noads.processors or { }
+
+local function process(start,what,n)
+ if n then n = n + 1 else n = 0 end
+ while start do
+ if trace_processing then
+ logs.report("math","%s%s",rep(" ",n or 0),tostring(start))
+ end
+ local id = start.id
+ local proc = what[id]
+ if proc then
+ proc(start,what,n)
+ elseif id == math_char or id == math_text_char or id == math_delim then
+ break
+ elseif id == math_style then
+ -- has a next
+ elseif id == math_noad then
+ local noad = start.nucleus if noad then process(noad,what,n) end -- list
+ noad = start.sup if noad then process(noad,what,n) end -- list
+ noad = start.sub if noad then process(noad,what,n) end -- list
+ elseif id == math_box or id == math_sub then
+ local noad = start.list if noad then process(noad,what,n) end -- list
+ elseif id == math_fraction then
+ local noad = start.num if noad then process(noad,what,n) end -- list
+ noad = start.denom if noad then process(noad,what,n) end -- list
+ noad = start.left if noad then process(noad,what,n) end -- delimiter
+ noad = start.right if noad then process(noad,what,n) end -- delimiter
+ elseif id == math_choice then
+ local noad = start.display if noad then process(noad,what,n) end -- list
+ noad = start.text if noad then process(noad,what,n) end -- list
+ noad = start.script if noad then process(noad,what,n) end -- list
+ noad = start.scriptscript if noad then process(noad,what,n) end -- list
+ elseif id == math_fence then
+ local noad = start.delim if noad then process(noad,what,n) end -- delimiter
+ elseif id == math_radical then
+ local noad = start.nucleus if noad then process(noad,what,n) end -- list
+ noad = start.sup if noad then process(noad,what,n) end -- list
+ noad = start.sub if noad then process(noad,what,n) end -- list
+ noad = start.left if noad then process(noad,what,n) end -- delimiter
+ noad = start.degree if noad then process(noad,what,n) end -- list
+ elseif id == math_accent then
+ local noad = start.nucleus if noad then process(noad,what,n) end -- list
+ noad = start.sup if noad then process(noad,what,n) end -- list
+ noad = start.sub if noad then process(noad,what,n) end -- list
+ noad = start.accent if noad then process(noad,what,n) end -- list
+ noad = start.bot_accent if noad then process(noad,what,n) end -- list
+ else
+ -- glue, penalty, etc
+ end
+ start = start.next
+ end
+end
+
+noads.process = process
+
+-- character remapping
+
+local mathalphabet = attributes.private("mathalphabet")
+local mathgreek = attributes.private("mathgreek")
+
+noads.processors.relocate = { }
+
+local function report_remap(tag,id,old,new,extra)
+ logs.report("math","remapping %s in font %s from U+%04X (%s) to U+%04X (%s)%s",tag,id,old,utfchar(old),new,utfchar(new),extra or "")
+end
+
+local remap_alphabets = mathematics.remap_alphabets
+local fcs = fonts.color.set
+
+-- we can have a global famdata == fonts.famdata and chrdata == fonts.chrdata
+
+--~ This does not work out well, as there are no fallbacks. Ok, we could
+--~ define a poor mans simplify mechanism.
+--~
+--~ local function checked(pointer)
+--~ local char = pointer.char
+--~ local fam = pointer.fam
+--~ local id = font_of_family(fam)
+--~ local tfmdata = fontdata[id]
+--~ local tc = tfmdata and tfmdata.characters
+--~ if not tc[char] then
+--~ local specials = characters.data[char].specials
+--~ if specials and (specials[1] == "char" or specials[1] == "font") then
+--~ newchar = specials[#specials]
+--~ if trace_remapping then
+--~ report_remap("fallback",id,char,newchar)
+--~ end
+--~ if trace_analyzing then
+--~ fcs(pointer,"font:isol")
+--~ end
+--~ pointer.char = newchar
+--~ return true
+--~ end
+--~ end
+--~ end
+
+noads.processors.relocate[math_char] = function(pointer)
+ local g = has_attribute(pointer,mathgreek) or 0
+ local a = has_attribute(pointer,mathalphabet) or 0
+ if a > 0 or g > 0 then
+ if a > 0 then
+ set_attribute(pointer,mathgreek,0)
+ end
+ if g > 0 then
+ set_attribute(pointer,mathalphabet,0)
+ end
+ local char = pointer.char
+ local newchar = remap_alphabets(char,a,g)
+ if newchar then
+ local fam = pointer.fam
+ local id = font_of_family(fam)
+ local tfmdata = fontdata[id]
+ if tfmdata and tfmdata.characters[newchar] then -- we could probably speed this up
+ if trace_remapping then
+ report_remap("char",id,char,newchar)
+ end
+ if trace_analyzing then
+ fcs(pointer,"font:isol")
+ end
+ pointer.char = newchar
+ return true
+ elseif trace_remapping then
+ report_remap("char",id,char,newchar," fails")
+ end
+ else
+ -- return checked(pointer)
+ end
+ else
+ -- return checked(pointer)
+ end
+ if trace_analyzing then
+ fcs(pointer,"font:medi")
+ end
+end
+
+noads.processors.relocate[math_text_char] = function(pointer)
+ if trace_analyzing then
+ fcs(pointer,"font:init")
+ end
+end
+
+noads.processors.relocate[math_delim] = function(pointer)
+ if trace_analyzing then
+ fcs(pointer,"font:fina")
+ end
+end
+
+function noads.relocate_characters(head,style,penalties)
+ process(head,noads.processors.relocate)
+ return true
+end
+
+-- some resize options (this works ok because the content is
+-- empty and no larger next will be forced)
+--
+-- beware: we don't use \delcode but \Udelcode and as such have
+-- no large_fam; also, we need to check for subtype and/or
+-- small_fam not being 0 because \. sits in 0,0 by default
+--
+-- todo: just replace the character by an ord noad
+-- and remove the right delimiter as well
+
+local mathsize = attributes.private("mathsize")
+
+noads.processors.resize = { }
+
+noads.processors.resize[math_fence] = function(pointer)
+ if pointer.subtype == 1 then -- left
+ local a = has_attribute(pointer,mathsize)
+ if a and a > 0 then
+ set_attribute(pointer,mathsize,0)
+ local d = pointer.delim
+ local df = d.small_fam
+ local id = font_of_family(df)
+ if id > 0 then
+ local ch = d.small_char
+ d.small_char = mathematics.big(fontdata[id],ch,a)
+ end
+ end
+ end
+end
+
+function noads.resize_characters(head,style,penalties)
+ process(head,noads.processors.resize)
+ return true
+end
+
+-- respacing
+
+local mathpunctuation = attributes.private("mathpunctuation")
+
+noads.processors.respace = { }
+
+local chardata = characters.data
+
+-- only [nd,ll,ul][po][nd,ll,ul]
+
+noads.processors.respace[math_noad] = function(pointer)
+ if pointer.subtype == noad_ord then
+ local a = has_attribute(pointer,mathpunctuation)
+ if a and a > 0 then
+ set_attribute(pointer,mathpunctuation,0)
+ local current_nucleus = pointer.nucleus
+ if current_nucleus.id == math_char then
+ local current_char = current_nucleus.char
+ local fc = chardata[current_char]
+ fc = fc and fc.category
+ if fc == "nd" or fc == "ll" or fc == "lu" then
+ local next_noad = pointer.next
+ if next_noad and next_noad.id == math_noad and next_noad.subtype == noad_punct then
+ local next_nucleus = next_noad.nucleus
+ if next_nucleus.id == math_char then
+ local next_char = next_nucleus.char
+ local nc = chardata[next_char]
+ nc = nc and nc.category
+ if nc == "po" then
+ local last_noad = next_noad.next
+ if last_noad and last_noad.id == math_noad and last_noad.subtype == noad_ord then
+ local last_nucleus = last_noad.nucleus
+ if last_nucleus.id == math_char then
+ local last_char = last_nucleus.char
+ local lc = chardata[last_char]
+ lc = lc and lc.category
+ if lc == "nd" or lc == "ll" or lc == "lu" then
+ local ord = node.new(math_noad) -- todo: pool
+ ord.subtype, ord.nucleus, ord.sub, ord.sup, ord.attr = noad_ord, next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr
+ -- next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr = nil, nil, nil, nil
+ next_noad.nucleus, next_noad.sub, next_noad.sup = nil, nil, nil -- else crash with attributes ref count
+ --~ next_noad.attr = nil
+ ord.next = last_noad
+ pointer.next = ord
+ node.free(next_noad)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+
+function noads.respace_characters(head,style,penalties)
+ noads.process(head,noads.processors.respace)
+ return true
+end
+
+-- the normal builder
+
+function noads.mlist_to_hlist(head,style,penalties)
+ return mlist_to_hlist(head,style,penalties), true
+end
+
+tasks.new (
+ "math",
+ {
+ "before",
+ "normalizers",
+ "builders",
+ "after",
+ }
+)
+
+local actions = tasks.actions("math",2) -- head, style, penalties
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+function nodes.processors.mlist_to_hlist(head,style,penalties)
+ starttiming(noads)
+ local head, done = actions(head,style,penalties)
+ stoptiming(noads)
+ return head, done
+end
+
+callbacks.register('mlist_to_hlist',nodes.processors.mlist_to_hlist,"preprocessing math list")
+
+-- tracing
+
+statistics.register("math processing time", function()
+ return statistics.elapsedseconds(noads)
+end)
diff --git a/tex/context/base/math-pln.mkii b/tex/context/base/math-pln.mkii
new file mode 100644
index 000000000..f2f3ff183
--- /dev/null
+++ b/tex/context/base/math-pln.mkii
@@ -0,0 +1,360 @@
+%D \module
+%D [ file=math-pln,
+%D version=2001.11.16,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Plain Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% \points should become \bodyfontsize
+
+%D This is a temporary module, some of this code will move to
+%D the other math modules.
+
+\writestatus{loading}{ConTeXt Math Macros / Plain Helpers}
+
+\unprotect
+
+\ifx\displ@y\undefined \let\displ@y\relax\fi
+
+\newbox\rootbox
+
+\def\root#1\of
+ {\setbox\rootbox\hbox{$\mathsurround\zeropoint\scriptscriptstyle{#1}$}%
+ \mathpalette\r@@t}
+
+\def\r@@t#1#2% will be overloaded
+ {\setbox\zerocount\hbox{$\mathsurround\zeropoint#1\sqrt{#2}$}\dimen@\ht\zerocount
+ \advance\dimen@-\dp\zerocount
+ \mkern5mu\raise.6\dimen@\copy\rootbox
+ \mkern-10mu\box\zerocount}
+
+\def\mathhexbox#1#2#3%
+ {\leavevmode
+ \hbox{$\mathsurround\zeropoint\mathchar"#1#2#3$}}
+
+\def\oalign#1%
+ {\leavevmode
+ \vtop
+ {\baselineskip\zeroskip \lineskip.25ex%
+ \ialign{##\crcr#1\crcr}}}
+
+\def\o@lign
+ {\lineskiplimit\zeropoint \oalign}
+
+\def\ooalign % chars over each other
+ {\lineskiplimit-\maxdimen
+ \oalign}
+
+\def\sh@ft#1% kern by #1 times the current slant
+ {\dimen@#1%
+ \kern\expandafter\withoutpt\the\slantperpoint
+ \dimen@}
+
+\def\dots
+ {\relax\ifmmode\ldots\else$\mathsurround\zeropoint\ldots\,$\fi}
+
+\def\hrulefill
+ {\leaders\hrule\hfill}
+
+\def\dotfill
+ {\cleaders\hbox{$\mathsurround\zeropoint \mkern1.5mu.\mkern1.5mu$}\hfill}
+
+\def\rightarrowfill
+ {$\mathsurround\zeropoint\smash-\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\mathord\rightarrow$}
+
+\def\leftarrowfill
+ {$\mathsurround\zeropoint\mathord\leftarrow\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\smash-$}
+
+% must go to math-tex
+
+\ifx\braceld\undefined
+ % mkii values
+ \mathchardef\braceld="37A
+ \mathchardef\bracerd="37B
+ \mathchardef\bracelu="37C
+ \mathchardef\braceru="37D
+\fi
+
+\def\downbracefill
+ {$\mathsurround\zeropoint\setbox\zerocount\hbox{$\braceld$}%
+ \braceld\leaders\vrule\!!height\ht\zerocount\!!depth\zeropoint\hfill\braceru
+ \bracelu\leaders\vrule\!!height\ht\zerocount\!!depth\zeropoint\hfill\bracerd$}
+
+\def\upbracefill
+ {$\mathsurround\zeropoint\setbox\zerocount\hbox{$\braceld$}%
+ \bracelu\leaders\vrule\!!height\ht\zerocount\!!depth\zeropoint\hfill\bracerd
+ \braceld\leaders\vrule\!!height\ht\zerocount\!!depth\zeropoint\hfill\braceru$}
+
+% hm, shouldn't that be \kern3\bodyfontsize
+
+\def\overbrace#1%
+ {\mathop{\vbox{\mathsurround\zeropoint\ialign{##\crcr\noalign{\kern3\points}
+ \downbracefill\crcr\noalign{\kern3\points\nointerlineskip}
+ $\hfil\displaystyle{#1}\hfil$\crcr}}}\limits}
+
+\def\underbrace#1%
+ {\mathop{\vtop{\mathsurround\zeropoint\ialign{##\crcr
+ $\hfil\displaystyle{#1}\hfil$\crcr\noalign{\kern3\points\nointerlineskip}
+ \upbracefill\crcr\noalign{\kern3\points}}}}\limits}
+
+\let\sp=^ % will become obsolete
+\let\sb=_ % will become obsolete
+
+\ifx\,\undefined \def\,{\mskip \thinmuskip } \fi
+\ifx\>\undefined \def\>{\mskip \medmuskip } \fi
+\ifx\;\undefined \def\;{\mskip \thickmuskip} \fi
+\ifx\!\undefined \def\!{\mskip-\thinmuskip } \fi
+\ifx\*\undefined \def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
+
+% {\catcode`\'=\active \gdef'{^\bgroup\prim@s}}
+
+\def\activemathquote{^\bgroup\prim@s}
+
+\def\prim@s
+ {\prime\futurelet\next\pr@m@s}
+
+\def\pr@m@s
+ {\ifx'\next
+ \@EA\pr@@@s
+ \else\ifx^\next
+ \@EAEAEA\pr@@@t
+ \else
+ \@EAEAEA\egroup
+ \fi\fi}
+
+\def\pr@@@s#1%
+ {\prim@s}
+
+\def\pr@@@t#1#2%
+ {#2\egroup}
+
+% {\catcode`\_=\active \global\let_=\_} % _ in math is either subscript or \_
+
+\let\activemathunderscore\_
+
+\def\relbar {\mathrel{\smash-}} % - has the same height as +
+\def\Relbar {\mathrel=}
+
+\def\Longrightarrow {\Relbar\joinrel\Rightarrow}
+\def\longrightarrow {\relbar\joinrel\rightarrow}
+\def\longleftarrow {\leftarrow\joinrel\relbar}
+\def\Longleftarrow {\Leftarrow\joinrel\Relbar}
+\def\longmapsto {\mapstochar\longrightarrow}
+\def\longleftrightarrow{\leftarrow\joinrel\rightarrow}
+\def\Longleftrightarrow{\Leftarrow\joinrel\Rightarrow}
+
+\def\overrightarrow#1%
+ {\vbox{\mathsurround\zeropoint\ialign{##\crcr
+ \rightarrowfill\crcr\noalign{\kern-\onepoint\nointerlineskip}
+ $\hfil\displaystyle{#1}\hfil$\crcr}}}
+
+\def\overleftarrow#1%
+ {\vbox{\mathsurround\zeropoint\ialign{##\crcr
+ \leftarrowfill\crcr\noalign{\kern-\onepoint\nointerlineskip}
+ $\hfil\displaystyle{#1}\hfil$\crcr}}}
+
+\def\skew#1#2#3%
+ {{\muskip\zerocount#1mu\divide\muskip\zerocount\plustwo \mkern\muskip\zerocount
+ #2{\mkern-\muskip\zerocount{#3}\mkern\muskip\zerocount}\mkern-\muskip\zerocount}{}}
+
+\def\choose{\atopwithdelims()}
+\def\brack {\atopwithdelims[]}
+\def\brace {\atopwithdelims\{\}}
+
+\def\mathpalette#1#2%
+ {\mathchoice
+ {#1\displaystyle {#2}}%
+ {#1\textstyle {#2}}%
+ {#1\scriptstyle {#2}}%
+ {#1\scriptscriptstyle{#2}}}
+
+\def\cong
+ {\mathrel{\mathpalette\@vereq\sim}} % congruence sign
+
+\def\@vereq#1#2%
+ {\lower.5\points\vbox{\lineskiplimit\maxdimen\lineskip-.5\points
+ \ialign{$\mathsurround\zeropoint#1\hfil##\hfil$\crcr#2\crcr=\crcr}}}
+
+\def\notin% can be mkiv'd
+ {\mathrel{\mathpalette\c@ncel\in}}
+
+\def\c@ncel#1#2%
+ {\mathsurround\zeropoint\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
+
+\def\rightleftharpoons%
+ {\mathrel{\mathpalette\rlh@{}}}
+
+\def\rlh@#1%
+ {\vcenter
+ {\mathsurround\zeropoint
+ \hbox
+ {\ooalign
+ {\raise2pt\hbox{$#1\rightharpoonup$}\crcr
+ $#1\leftharpoondown$}}}}
+
+\def\buildrel#1\over#2%
+ {\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}}
+
+\def\doteq
+ {\buildrel\textstyle.\over=}
+
+\ifx\mfunction\undefined \def\mfunction#1{\mathbin{\rm#1}} \fi
+
+\def\bmod
+ {\nonscript
+ \mskip-\medmuskip
+ \mkern5mu
+ \mfunction{mod}%
+ \penalty900
+ \mkern5mu
+ \nonscript
+ \mskip-\medmuskip}
+
+\def\pmod#1%
+ {\allowbreak
+ \mkern18mu
+ (\mfunction{mod}\,\,#1)}
+
+\def\cases#1%
+ {\left\{%
+ \,%
+ \vcenter
+ {\normalbaselines
+ \mathsurround\zeropoint
+ \ialign{$##\hfil$&\quad##\hfil\crcr#1\crcr}}%
+ \right.}
+
+\def\matrix#1%
+ {\null
+ \,%
+ \vcenter
+ {\normalbaselines\mathsurround\zeropoint
+ \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
+ \mathstrut\crcr\noalign{\kern-\baselineskip}
+ #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}%
+ \,}
+
+\def\pmatrix#1%
+ {\left(\matrix{#1}\right)}
+
+\newdimen\mathparentwd
+
+% \setbox0=\hbox{\tenex B} \mathparentwd=\wd0 % width of the big left (
+
+\def\bordermatrix#1%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox\zerocount\vbox
+ {\def\cr{\crcr\noalign{\kern2\points\global\let\cr\endline}}%
+ \ialign{$##$\hfil\kern2\points\kern\mathparentwd&\thinspace\hfil$##$\hfil
+ &&\quad\hfil$##$\hfil\crcr
+ \omit\strut\hfil\crcr\noalign{\kern-\baselineskip}%
+ #1\crcr\omit\strut\cr}}%
+ \setbox\plustwo\vbox
+ {\unvcopy\zerocount\global\setbox\plusone\lastbox}%
+ \setbox\plustwo\hbox
+ {\unhbox\plusone\unskip\global\setbox\plusone\lastbox}%
+ \setbox\plustwo\hbox
+ {$\kern\wd\plusone\kern-\mathparentwd\left(\kern-\wd\plusone
+ \global\setbox\plusone\vbox{\box\plusone\kern2\points}%
+ \vcenter{\kern-\ht\plusone\unvbox\zerocount\kern-\baselineskip}\,\right)$}%
+ \null
+ \;%
+ \vbox{\kern\ht\plusone\box\plustwo}%
+ \endgroup}
+
+% \def\openup{\afterassignment\@penup\dimen@=}
+%
+% \def\@penup{\advance\lineskip\dimen@
+% \advance\baselineskip\dimen@
+% \advance\lineskiplimit\dimen@}
+
+\def\openup
+ {\afterassignment\doopenup\scratchdimen=}
+
+\def\doopenup
+ {\advance\lineskip \scratchdimen
+ \advance\baselineskip \scratchdimen
+ \advance\lineskiplimit\scratchdimen}
+
+% \def\jot{.25\bodyfontsize} % plain tex: 3 pt (todo: better name and configurable)
+
+\def\displayopenupvalue{.25\bodyfontsize}
+
+\def\eqalign#1%
+ {\null
+ \,%
+ \vcenter
+ {\openup\displayopenupvalue % was \openup\jot
+ \mathsurround\zeropoint
+ \ialign
+ {\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##}$\hfil\crcr
+ #1\crcr}}%
+ \,}
+
+\def\@lign % restore inside \displ@y
+ {\tabskip\zeroskip
+ \everycr{}}
+
+\def\displaylines#1%
+ {\displ@y
+ \tabskip\zeroskip
+ \halign
+ {\hbox to \displaywidth{$\@lign\hfil\displaystyle##\hfil$}\crcr
+ #1\crcr}}
+
+\def\eqalignno#1%
+ {\displ@y
+ \tabskip\centering
+ \halign to \displaywidth
+ {\hfil$\@lign\displaystyle{##}$\tabskip\zeroskip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\llap{$\@lign##$}\tabskip\zeroskip\crcr
+ #1\crcr}}
+
+\def\leqalignno#1%
+ {\displ@y
+ \tabskip\centering
+ \halign to \displaywidth
+ {\hfil$\@lign\displaystyle{##}$\tabskip\zeroskip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\kern-\displaywidth\rlap{$\@lign##$}\tabskip\displaywidth\crcr
+ #1\crcr}}
+
+% temporary here
+
+% \startcatcodetable \mthcatcodes
+% \setcatcodetable\ctxcatcodes
+% \catcode`\_ = 13
+% \catcode`\' = 13
+% \stopcatcodetable
+%
+% \letcatcodecommand \mthcatcodes `\_ \activemathunderscore
+% \letcatcodecommand \mthcatcodes `\' \activemathquote
+
+% \appendtoks \setcatcodetable\mthcatcodes \to \everymath : spoils xml
+
+% tricky, but some day we will reimplement math
+
+\bgroup
+ \catcode`\_ = 13
+ \catcode`\' = 13
+ \doglobal\appendtoks
+ \let_\activemathunderscore
+ \let'\activemathquote
+ \to \everymathematics
+\egroup
+
+% so far
+
+\protect \endinput
diff --git a/tex/context/base/math-pln.mkiv b/tex/context/base/math-pln.mkiv
new file mode 100644
index 000000000..ab584f10a
--- /dev/null
+++ b/tex/context/base/math-pln.mkiv
@@ -0,0 +1,298 @@
+%D \module
+%D [ file=math-pln,
+%D version=2001.11.16,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Plain Helpers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 is a temporary module, some of this code will move to
+%D the other math modules. Much is copied from Plain \TEX.
+
+% \points should become \bodyfontsize
+
+\writestatus{loading}{ConTeXt Math Macros / Plain Helpers}
+
+\unprotect
+
+\ifx\displ@y\undefined \let\displ@y\relax\fi
+
+\def\oalign#1%
+ {\leavevmode
+ \vtop
+ {\baselineskip\zeroskip \lineskip.25ex%
+ \ialign{##\crcr#1\crcr}}}
+
+\def\o@lign
+ {\lineskiplimit\zeropoint \oalign}
+
+\def\ooalign % chars over each other
+ {\lineskiplimit-\maxdimen
+ \oalign}
+
+\def\sh@ft#1% kern by #1 times the current slant
+ {\dimen@#1%
+ \kern\expandafter\withoutpt\the\slantperpoint
+ \dimen@}
+
+\def\dots
+ {\relax\ifmmode\ldots\else$\mathsurround\zeropoint\ldots\,$\fi}
+
+\def\hrulefill
+ {\leaders\hrule\hfill}
+
+\def\dotfill
+ {\cleaders\hbox{$\mathsurround\zeropoint \mkern1.5mu.\mkern1.5mu$}\hfill}
+
+\def\rightarrowfill
+ {$\mathsurround\zeropoint\smash-\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\mathord\rightarrow$}
+
+\def\leftarrowfill
+ {$\mathsurround\zeropoint\mathord\leftarrow\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\smash-$}
+
+\let\sp=^ % will become obsolete
+\let\sb=_ % will become obsolete
+
+\ifx\,\undefined \def\,{\mskip \thinmuskip } \fi
+\ifx\>\undefined \def\>{\mskip \medmuskip } \fi
+\ifx\;\undefined \def\;{\mskip \thickmuskip} \fi
+\ifx\!\undefined \def\!{\mskip-\thinmuskip } \fi
+\ifx\*\undefined \def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
+
+% {\catcode`\'=\active \gdef'{^\bgroup\prim@s}}
+
+\def\activemathquote{^\bgroup\prim@s}
+
+\def\prim@s
+ {\prime\futurelet\next\pr@m@s}
+
+\def\pr@m@s
+ {\ifx'\next
+ \@EA\pr@@@s
+ \else\ifx^\next
+ \@EAEAEA\pr@@@t
+ \else
+ \@EAEAEA\egroup
+ \fi\fi}
+
+\def\pr@@@s#1%
+ {\prim@s}
+
+\def\pr@@@t#1#2%
+ {#2\egroup}
+
+% {\catcode`\_=\active \global\let_=\_} % _ in math is either subscript or \_
+
+\let\activemathunderscore\_
+
+\def\relbar {\mathrel{\smash-}} % - has the same height as +
+\def\Relbar {\mathrel=}
+
+\def\Longrightarrow {\Relbar\joinrel\Rightarrow} % beware, this overloades cambria native
+\def\longrightarrow {\relbar\joinrel\rightarrow}
+\def\longleftarrow {\leftarrow\joinrel\relbar}
+\def\Longleftarrow {\Leftarrow\joinrel\Relbar}
+\def\longmapsto {\mapstochar\longrightarrow}
+\def\longleftrightarrow{\leftarrow\joinrel\rightarrow}
+\def\Longleftrightarrow{\Leftarrow\joinrel\Rightarrow}
+
+\def\choose{\atopwithdelims()}
+\def\brack {\atopwithdelims[]}
+\def\brace {\atopwithdelims\{\}}
+
+\def\mathpalette#1#2%
+ {\mathchoice
+ {#1\displaystyle {#2}}%
+ {#1\textstyle {#2}}%
+ {#1\scriptstyle {#2}}%
+ {#1\scriptscriptstyle{#2}}}
+
+\def\cong
+ {\mathrel{\mathpalette\@vereq\sim}} % congruence sign
+
+\def\@vereq#1#2%
+ {\lower.5\points\vbox{\lineskiplimit\maxdimen\lineskip-.5\points
+ \ialign{$\mathsurround\zeropoint#1\hfil##\hfil$\crcr#2\crcr=\crcr}}}
+
+\def\notin
+ {\mathrel{\mathpalette\c@ncel\in}}
+
+\def\c@ncel#1#2%
+ {\mathsurround\zeropoint\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
+
+\def\rightleftharpoons
+ {\mathrel{\mathpalette\rlh@{}}}
+
+\def\rlh@#1%
+ {\vcenter
+ {\mathsurround\zeropoint
+ \hbox
+ {\ooalign
+ {\raise2pt\hbox{$#1\rightharpoonup$}\crcr
+ $#1\leftharpoondown$}}}}
+
+\def\buildrel#1\over#2%
+ {\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}}
+
+\def\doteq
+ {\buildrel\textstyle.\over=}
+
+\ifx\mfunction\undefined \def\mfunction#1{\mathbin{\rm#1}} \fi
+
+\def\bmod
+ {\nonscript
+ \mskip-\medmuskip
+ \mkern5mu
+ \mfunction{mod}%
+ \penalty900
+ \mkern5mu
+ \nonscript
+ \mskip-\medmuskip}
+
+\def\pmod#1%
+ {\allowbreak
+ \mkern18mu
+ (\mfunction{mod}\,\,#1)}
+
+\def\cases#1%
+ {\left\{%
+ \,%
+ \vcenter
+ {\normalbaselines
+ \mathsurround\zeropoint
+ \ialign{$##\hfil$&\quad##\hfil\crcr#1\crcr}}%
+ \right.}
+
+\def\matrix#1%
+ {\null
+ \,%
+ \vcenter
+ {\normalbaselines\mathsurround\zeropoint
+ \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
+ \mathstrut\crcr\noalign{\kern-\baselineskip}
+ #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}%
+ \,}
+
+\def\pmatrix#1%
+ {\left(\matrix{#1}\right)}
+
+\newdimen\mathparentwd
+
+% \setbox0=\hbox{\tenex B} \mathparentwd=\wd0 % width of the big left (
+
+\def\bordermatrix#1%
+ {\begingroup
+ \mathsurround\zeropoint
+ \setbox\zerocount\vbox
+ {\def\cr{\crcr\noalign{\kern2\points\global\let\cr\endline}}%
+ \ialign{$##$\hfil\kern2\points\kern\mathparentwd&\thinspace\hfil$##$\hfil
+ &&\quad\hfil$##$\hfil\crcr
+ \omit\strut\hfil\crcr\noalign{\kern-\baselineskip}%
+ #1\crcr\omit\strut\cr}}%
+ \setbox\plustwo\vbox
+ {\unvcopy\zerocount\global\setbox\plusone\lastbox}%
+ \setbox\plustwo\hbox
+ {\unhbox\plusone\unskip\global\setbox\plusone\lastbox}%
+ \setbox\plustwo\hbox
+ {$\kern\wd\plusone\kern-\mathparentwd\left(\kern-\wd\plusone
+ \global\setbox\plusone\vbox{\box\plusone\kern2\points}%
+ \vcenter{\kern-\ht\plusone\unvbox\zerocount\kern-\baselineskip}\,\right)$}%
+ \null
+ \;%
+ \vbox{\kern\ht\plusone\box\plustwo}%
+ \endgroup}
+
+% \def\openup{\afterassignment\@penup\dimen@=}
+%
+% \def\@penup{\advance\lineskip\dimen@
+% \advance\baselineskip\dimen@
+% \advance\lineskiplimit\dimen@}
+
+\def\openup
+ {\afterassignment\doopenup\scratchdimen=}
+
+\def\doopenup
+ {\advance\lineskip \scratchdimen
+ \advance\baselineskip \scratchdimen
+ \advance\lineskiplimit\scratchdimen}
+
+% \def\jot{.25\bodyfontsize} % plain tex: 3 pt (todo: better name and configurable)
+
+\def\displayopenupvalue{.25\bodyfontsize}
+
+\def\eqalign#1%
+ {\null
+ \,%
+ \vcenter
+ {\openup\displayopenupvalue % was \openup\jot
+ \mathsurround\zeropoint
+ \ialign
+ {\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##}$\hfil\crcr
+ #1\crcr}}%
+ \,}
+
+\def\@lign % restore inside \displ@y
+ {\tabskip\zeroskip
+ \everycr{}}
+
+\def\displaylines#1%
+ {\displ@y
+ \tabskip\zeroskip
+ \halign
+ {\hbox to \displaywidth{$\@lign\hfil\displaystyle##\hfil$}\crcr
+ #1\crcr}}
+
+\def\eqalignno#1%
+ {\displ@y
+ \tabskip\centering
+ \halign to \displaywidth
+ {\hfil$\@lign\displaystyle{##}$\tabskip\zeroskip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\llap{$\@lign##$}\tabskip\zeroskip\crcr
+ #1\crcr}}
+
+\def\leqalignno#1%
+ {\displ@y
+ \tabskip\centering
+ \halign to \displaywidth
+ {\hfil$\@lign\displaystyle{##}$\tabskip\zeroskip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\kern-\displaywidth\rlap{$\@lign##$}\tabskip\displaywidth\crcr
+ #1\crcr}}
+
+% temporary here (weird code)
+
+% \startcatcodetable \mthcatcodes
+% \setcatcodetable\ctxcatcodes
+% \catcode`\_ = 13
+% \catcode`\' = 13
+% \stopcatcodetable
+%
+% \letcatcodecommand \mthcatcodes `\_ \activemathunderscore
+% \letcatcodecommand \mthcatcodes `\' \activemathquote
+
+% \appendtoks \setcatcodetable\mthcatcodes \to \everymath : spoils xml
+
+% tricky, but some day we will reimplement math
+
+\bgroup
+ \catcode`\_ = 13
+ \catcode`\' = 13
+ \doglobal\appendtoks
+ \let_\activemathunderscore
+ \let'\activemathquote
+ \to \everymathematics
+\egroup
+
+% so far
+
+\protect \endinput
diff --git a/tex/context/base/math-run.mkii b/tex/context/base/math-run.mkii
new file mode 100644
index 000000000..6bc4bf4d5
--- /dev/null
+++ b/tex/context/base/math-run.mkii
@@ -0,0 +1,105 @@
+%D \module
+%D [ file=math-run,
+%D version=2001.23.04,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen \& Ton Otten]
+%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 Math Macros / Runtime Macros}
+
+\unprotect
+
+\ifx\showmathmodern\undefined \global\chardef\showmathmodern\zerocount \fi
+
+\gdef\showmathcharacters% nearly \showcharacters
+ {\par
+ \bgroup
+ \ifcase\showmathmodern\or\ifx\modern\undefined\chardef\showmathmodern\zerocount\fi\fi
+ \setuptextrules[\c!bodyfont=,\c!style=]
+ \starttextrule{math characters -- \currentmathcollection}
+ \whitespace
+ \dontcomplain
+ \forgetall
+ \def\startmathcollection[##1]{}
+ \let\stopmathcollection\relax
+ \dimen0\zeropoint
+ \dimen2\zeropoint
+ \def\definemathsymbol {\dosixtupleempty\dodefinemathsymbol}
+ \def\definemathcharacter{\dosixtupleempty\dodefinemathcharacter}
+ \def\definemathcommand {\dotripleempty \dodefinemathcommand}
+ %\newcounter\mathcolor
+ \def\dodefinemathsymbol[##1][##2][##3][##4][##5][##6]%
+ {%\doifcolorelse{math \purefamilyhex{##3}}{}
+ % {\increment\mathcolor
+ % \definecolor[math \purefamilyhex{##3}][\mathcolor]}%
+ \setbox0\hbox spread 1em{\mathematics{\getvalue{##1}{}{}{}}}%
+ \ifdim\wd0>\dimen0 \dimen0=\wd0 \fi
+ \setbox2\hbox spread 1em{\hbox to 1em{\tttf\purefamilyhex{##3}\hss}\box0 ##1}%
+ \ifdim\wd2>\dimen2 \dimen2=\wd2 \fi}
+ \def\dodefinemathcharacter[##1][##2][##3][##4][##5][##6]{}
+ \def\dodefinemathcommand [##1][##2][##3]##4{}
+ \readsysfile{\f!mathprefix tex.mkii}\!!doneatrue\!!doneafalse
+ \readsysfile{\f!mathprefix ams.mkii}\!!donebtrue\!!donebfalse
+ \if!!donea
+ \if!!doneb
+ \edef\encwidth{\the\dimen0}
+ \dimen0=\hsize
+ \advance\dimen0 2em
+ \advance\dimen2 2em
+ \ifcase\showmathmodern\or\advance\dimen2 4em\fi
+ \divide \dimen0 by \dimen2 \advance\dimen0 1sp
+ \edef\enccols{\number\dimen0}
+ \startcolumns[\c!n=\enccols,\c!distance=2em]
+ \def\dodefinemathsymbol[##1][##2][##3][##4][##5][##6]%
+ {%\localcolortrue
+ %\color
+ % [math \purefamilyhex{##3}]
+ {\hbox
+ {\ifcase\showmathmodern\or
+ \hbox to \encwidth{\modern\let\mathcollection\nomathcollection\mathematics{\getvalue{##1}{}{}{}}\hss}%
+ \fi
+ \hbox to \encwidth{\mathematics{\getvalue{##1}{}{}{}}\hss}%
+ \hbox to 1em{\tttf\purefamilyhex{##3}\hss}##1}\par}}
+ \readsysfile{\f!mathprefix tex.mkii}\donothing\donothing
+ \readsysfile{\f!mathprefix ams.mkii}\donothing\donothing
+ \stopcolumns
+ \else
+ \par \tttf no chars in \f!mathprefix ams\par
+ \fi
+ \else
+ \par \tttf no chars in \f!mathprefix tex\par
+ \fi
+ \stoptextrule
+ \egroup}
+
+% \definecolor[math \purefamilyhex{mr}] [darkred]
+% \definecolor[math \purefamilyhex{mi}] [darkgreen]
+% \definecolor[math \purefamilyhex{sy}] [darkblue]
+% \definecolor[math \purefamilyhex{ex}] [darkmagenta]
+% \definecolor[math \purefamilyhex{nn}] [darkyellow]
+% \definecolor[math \purefamilyhex{ma}] [lightred]
+% \definecolor[math \purefamilyhex{mb}] [lightgreen]
+% \definecolor[math \purefamilyhex{mc}] [lightblue]
+% \definecolor[math \purefamilyhex{md}] [lightmagenta]
+
+\gdef\showmathtoken#1%
+ {\starttabulate[|lT|lT|lT|l|]
+ \NC token \NC #1 \NC \NR
+ \NC collection \NC \ifcsname\@mt@\mathcollection#1\endcsname
+ \mathcollection
+ \else\ifcsname\@mt@\nomathcollection#1\endcsname
+ \nomathcollection
+ \else
+ ?%
+ \fi\fi \NC \NR
+ \NC visualization \NC \mathematics{\getvalue{#1}} \NC \NR
+ \NC definition \NC \tttf \@EA\defconvertedcommand\@EA\ascii\csname\@mt@\mathcollection#1\endcsname \ascii \NC \NR
+ \stoptabulate}
+
+\protect \endinput
diff --git a/tex/context/base/math-scr.mkiv b/tex/context/base/math-scr.mkiv
new file mode 100644
index 000000000..eb1db4714
--- /dev/null
+++ b/tex/context/base/math-scr.mkiv
@@ -0,0 +1,135 @@
+%D \module
+%D [ file=math-scr,
+%D version=2007.07.19,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Scripts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Math Macros / Scripts}
+
+\unprotect
+
+%D \macros
+%D {super, sub}
+%D
+%D \TEX\ uses \type{^} and \type{_} for entering super- and
+%D subscript mode. We want however a bit more control than
+%D normally provided, and therefore provide \type {\super}
+%D and \type{sub}.
+%D
+%D The grid snapping has been removed.
+
+\global\let\normalsuper=^
+\global\let\normalsuber=_
+
+\ifdefined\supersubmode \else \newcount\supersubmode \fi
+\ifdefined\newevery \else \everysupersub \EverySuperSub \fi
+
+\appendtoks \advance\supersubmode \plusone \to \everysupersub
+
+\setuptextformulas
+ [\c!size=\v!normal]
+
+\def\normalsupsub#1#2%
+ {^{\the\everysupersub#1}_{\the\everysupersub#2}}
+
+\def\super#1{^{\the\everysupersub#1}}
+\def\suber#1{_{\the\everysupersub#1}}
+\def\supsub#1#2{\super{#1}\suber{#2}}
+\def\subsup#1#2{\suber{#1}\super{#2}}
+
+%D \macros
+%D {enablesupersub,enablesimplesupersub}
+%D
+%D We can let \type {^} and \type {_} act like \type {\super}
+%D and \type {\sub} by saying \type {\enablesupersub}.
+
+\bgroup
+\catcode`\^=\@@active
+\catcode`\_=\@@active
+\gdef\enablesupersub
+ {\catcode`\^=\@@active
+ \def^{\ifmmode\expandafter\super\else\expandafter\normalsuper\fi}%
+ \catcode`\_=\@@active
+ \def_{\ifmmode\expandafter\suber\else\expandafter\normalsuber\fi}}
+\egroup
+
+%D \macros
+%D {restoremathstyle}
+%D
+%D We can pick up the current math style by calling \type
+%D {\restoremathstyle}.
+
+\def\restoremathstyle
+ {\ifmmode
+ \ifcase\supersubmode
+ \textstyle
+ \or
+ \scriptstyle
+ \else
+ \scriptscriptstyle
+ \fi
+ \fi}
+
+%D These macros were first needed by Frits Spijker (also
+%D known as Gajes) for typesetting the minus sign that is
+%D keyed into scientific calculators.
+
+% This is the first alternative, which works okay for the
+% minus, but less for the plus.
+%
+% \def\dodoraisedmathord#1#2#3%
+% {\mathord{{#2\raise.#1ex\hbox{#2#3}}}}
+%
+% \def\doraisedmathord#1%
+% {\mathchoice
+% {\dodoraisedmathord5\tf #1}%
+% {\dodoraisedmathord5\tf #1}%
+% {\dodoraisedmathord4\tfx #1}%
+% {\dodoraisedmathord3\tfxx#1}}
+%
+% \def\negative{\doraisedmathord-}
+% \def\positive{\doraisedmathord+}
+%
+% So, now we use the monospaced signs, that we also
+% define as symbol, so that they can be overloaded.
+
+\def\dodoraisedmathord#1#2#3%
+ {\mathord{{#2\raise.#1ex\hbox{#2\symbol[#3]}}}}
+
+\def\doraisedmathord#1%
+ {\mathchoice
+ {\dodoraisedmathord5\tf {#1}}%
+ {\dodoraisedmathord5\tf {#1}}%
+ {\dodoraisedmathord4\tx {#1}}%
+ {\dodoraisedmathord3\txx{#1}}}
+
+\def\dodonumbermathord#1#2%
+ {\setbox\scratchbox\hbox{0}%
+ \mathord{\hbox to \wd\scratchbox{\hss#1\symbol[#2]\hss}}}
+
+\def\donumbermathord#1%
+ {\mathchoice
+ {\dodonumbermathord\tf {#1}}%
+ {\dodonumbermathord\tf {#1}}%
+ {\dodonumbermathord\tx {#1}}%
+ {\dodonumbermathord\txx{#1}}}
+
+\definesymbol[positive] [\getglyph{Mono}{+}]
+\definesymbol[negative] [\getglyph{Mono}{-}]
+\definesymbol[zeroamount][\getglyph{Mono}{-}]
+
+\def\negative {\doraisedmathord{negative}}
+\def\positive {\doraisedmathord{positive}}
+\def\zeroamount{\donumbermathord{zeroamount}}
+
+%D How negative such a symbol looks is demonstrated in:
+%D $\negative 10^{\negative 10^{\negative 10}}$.
+
+\protect \endinput
diff --git a/tex/context/base/math-tex.mkii b/tex/context/base/math-tex.mkii
new file mode 100644
index 000000000..8f34a190e
--- /dev/null
+++ b/tex/context/base/math-tex.mkii
@@ -0,0 +1,720 @@
+%D \module
+%D [ file=math-tex,
+%D version=2001.04.12,
+%D subtitle=Plain Specials,
+%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% beware: in mkiv we will do it differently
+
+\unprotect
+
+\mathcode`\ ="8000 \mathcode`\_="8000 \mathcode`\'="8000
+
+\definefamilysynonym [default] [calligraphic] [sy]
+\definefamilysynonym [default] [oldstyle] [mi]
+\definefamilysynonym [default] [blackboard] [mr]
+\definefamilysynonym [default] [gothic] [mr]
+\definefamilysynonym [default] [fraktur] [mr]
+
+\definefamilysynonym [default] [lcgreek] [mi]
+\definefamilysynonym [default] [ucgreek] [mr]
+\definefamilysynonym [default] [vargreek] [mi]
+
+
+%D \macros
+%D {\setupmathematics}
+%D
+%D Configuration for integrals. (If needed we can speed this up and make it
+%D installable; no processaction is needed then).
+
+\chardef\intlimitcode\zerocount % 0 nolimits 1 displaylimits 2 limits
+
+\def\intlimits
+ {\ifcase\intlimitcode \nolimits \or \displaylimits \or \limits \fi}
+
+\def\setupmathematics
+ {\dosingleargument\dosetupmathematics}
+
+\def\dosetupmathematics[#1]%
+ {\getparameters[\??mo][#1]
+ \processaction[\@@mointegral]
+ [ nolimits=>\chardef\intlimitcode\zerocount,
+ displaylimits=>\chardef\intlimitcode\plusone,
+ limits=>\chardef\intlimitcode\plustwo]}
+
+%D \startbuffer
+%D $\int_a^b f(x) dx$ and also
+%D $\iint_a^b f(x,y) dxdy$, $\iiint_a^b f(x,y) dxdy$,
+%D $\iiiint_a^b f(x) dx$
+%D \startformula
+%D \int_a^b f(x) dx \quad
+%D \iint_a^b f(x) dx \quad
+%D \iiint_a^b f(x) dx \quad
+%D \iiiint_a^b f(x) dx \quad
+%D \stopformula
+%D \stopbuffer
+%D
+%D Default: \getbuffer
+%D
+%D Displaylimits: \setupmathematics[integral=displaylimits] \getbuffer
+%D
+%D Limits: \setupmathematics[integral=limits] \getbuffer
+
+\startmathcollection [default]
+
+\definemathsymbol [alpha] [nothing] [lcgreek] ["0B]
+\definemathsymbol [beta] [nothing] [lcgreek] ["0C]
+\definemathsymbol [gamma] [nothing] [lcgreek] ["0D]
+\definemathsymbol [delta] [nothing] [lcgreek] ["0E]
+\definemathsymbol [epsilon] [nothing] [lcgreek] ["0F]
+\definemathsymbol [zeta] [nothing] [lcgreek] ["10]
+\definemathsymbol [eta] [nothing] [lcgreek] ["11]
+\definemathsymbol [theta] [nothing] [lcgreek] ["12]
+\definemathsymbol [iota] [nothing] [lcgreek] ["13]
+\definemathsymbol [kappa] [nothing] [lcgreek] ["14]
+\definemathsymbol [lambda] [nothing] [lcgreek] ["15]
+\definemathsymbol [mu] [nothing] [lcgreek] ["16]
+\definemathsymbol [nu] [nothing] [lcgreek] ["17]
+\definemathsymbol [xi] [nothing] [lcgreek] ["18]
+\definemathsymbol [omicron] [nothing] [lcgreek] ["6F]
+\definemathsymbol [pi] [nothing] [lcgreek] ["19]
+\definemathsymbol [rho] [nothing] [lcgreek] ["1A]
+\definemathsymbol [sigma] [nothing] [lcgreek] ["1B]
+\definemathsymbol [tau] [nothing] [lcgreek] ["1C]
+\definemathsymbol [upsilon] [nothing] [lcgreek] ["1D]
+\definemathsymbol [phi] [nothing] [lcgreek] ["1E]
+\definemathsymbol [chi] [nothing] [lcgreek] ["1F]
+\definemathsymbol [psi] [nothing] [lcgreek] ["20]
+\definemathsymbol [omega] [nothing] [lcgreek] ["21]
+
+\stopmathcollection
+
+\startmathcollection [default]
+
+\definemathsymbol [varepsilon] [nothing] [vargreek] ["22]
+\definemathsymbol [vartheta] [nothing] [vargreek] ["23]
+\definemathsymbol [varpi] [nothing] [vargreek] ["24]
+\definemathsymbol [varrho] [nothing] [vargreek] ["25]
+\definemathsymbol [varsigma] [nothing] [vargreek] ["26]
+\definemathsymbol [varphi] [nothing] [vargreek] ["27]
+
+\stopmathcollection
+
+\startmathcollection [default]
+
+\definemathsymbol [Alpha] [alpha] [ucgreek] ["41] % A
+\definemathsymbol [Beta] [alpha] [ucgreek] ["42] % B
+\definemathsymbol [Gamma] [alpha] [ucgreek] ["00]
+\definemathsymbol [Delta] [alpha] [ucgreek] ["01]
+\definemathsymbol [Epsilon] [alpha] [ucgreek] ["45] % E
+\definemathsymbol [Zeta] [alpha] [ucgreek] ["5A] % Z
+\definemathsymbol [Eta] [alpha] [ucgreek] ["48] % H
+\definemathsymbol [Theta] [alpha] [ucgreek] ["02]
+\definemathsymbol [Iota] [alpha] [ucgreek] ["49] % I
+\definemathsymbol [Kappa] [alpha] [ucgreek] ["4B] % K
+\definemathsymbol [Lambda] [alpha] [ucgreek] ["03]
+\definemathsymbol [Mu] [alpha] [ucgreek] ["4D] % M
+\definemathsymbol [Nu] [alpha] [ucgreek] ["4E] % N
+\definemathsymbol [Xi] [alpha] [ucgreek] ["04]
+\definemathsymbol [Omicron] [alpha] [ucgreek] ["4F] % O
+\definemathsymbol [Pi] [alpha] [ucgreek] ["05]
+\definemathsymbol [Rho] [alpha] [ucgreek] ["52] % R
+\definemathsymbol [Sigma] [alpha] [ucgreek] ["06]
+\definemathsymbol [Tau] [alpha] [ucgreek] ["54] % T
+\definemathsymbol [Upsilon] [alpha] [ucgreek] ["07]
+\definemathsymbol [Phi] [alpha] [ucgreek] ["08]
+\definemathsymbol [Chi] [alpha] [ucgreek] ["58] % X
+\definemathsymbol [Psi] [alpha] [ucgreek] ["09]
+\definemathsymbol [Omega] [alpha] [ucgreek] ["0A]
+
+\stopmathcollection
+
+% The \mfunction macro is an alternative for \hbox with a
+% controlable font switch.
+
+\startmathcollection[default]
+
+\definemathcommand [arccos] [nolop] {\mfunction{arccos}}
+\definemathcommand [arcsin] [nolop] {\mfunction{arcsin}}
+\definemathcommand [arctan] [nolop] {\mfunction{arctan}}
+\definemathcommand [arg] [nolop] {\mfunction{arg}}
+\definemathcommand [cosh] [nolop] {\mfunction{cosh}}
+\definemathcommand [cos] [nolop] {\mfunction{cos}}
+\definemathcommand [coth] [nolop] {\mfunction{coth}}
+\definemathcommand [cot] [nolop] {\mfunction{cot}}
+\definemathcommand [csc] [nolop] {\mfunction{csc}}
+\definemathcommand [deg] [nolop] {\mfunction{deg}}
+\definemathcommand [det] [limop] {\mfunction{det}}
+\definemathcommand [dim] [nolop] {\mfunction{dim}}
+\definemathcommand [exp] [nolop] {\mfunction{exp}}
+\definemathcommand [gcd] [limop] {\mfunction{gcd}}
+\definemathcommand [hom] [nolop] {\mfunction{hom}}
+\definemathcommand [inf] [limop] {\mfunction{inf}}
+\definemathcommand [injlim] [limop] {\mfunction{inj\,lim}}
+\definemathcommand [ker] [nolop] {\mfunction{ker}}
+\definemathcommand [lg] [nolop] {\mfunction{lg}}
+\definemathcommand [liminf] [limop] {\mfunction{lim\,inf}}
+\definemathcommand [limsup] [limop] {\mfunction{lim\,sup}}
+\definemathcommand [lim] [limop] {\mfunction{lim}}
+\definemathcommand [ln] [nolop] {\mfunction{ln}}
+\definemathcommand [log] [nolop] {\mfunction{log}}
+\definemathcommand [median] [limop] {\mfunction{median}}
+\definemathcommand [max] [limop] {\mfunction{max}}
+\definemathcommand [min] [limop] {\mfunction{min}}
+\definemathcommand [mod] [limop] {\mfunction{mod}}
+\definemathcommand [div] [limop] {\mfunction{div}}
+\definemathcommand [projlim] [limop] {\mfunction{proj\,lim}}
+\definemathcommand [Pr] [limop] {\mfunction{Pr}}
+\definemathcommand [sec] [nolop] {\mfunction{sec}}
+\definemathcommand [sinh] [nolop] {\mfunction{sinh}}
+\definemathcommand [sin] [nolop] {\mfunction{sin}}
+\definemathcommand [sup] [limop] {\mfunction{sup}}
+\definemathcommand [tanh] [nolop] {\mfunction{tanh}}
+\definemathcommand [tan] [nolop] {\mfunction{tan}}
+
+\stopmathcollection
+
+\let\normalmatharg\arg % todo: maybe automatically
+
+\startmathcollection[default]
+
+\definemathcommand [integers] {\mfunction{Z}}
+\definemathcommand [reals] {\mfunction{R}}
+\definemathcommand [rationals] {\mfunction{Q}}
+\definemathcommand [naturalnumbers] {\mfunction{N}}
+\definemathcommand [complexes] {\mfunction{C}}
+\definemathcommand [primes] {\mfunction{P}}
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathcharacter [!] [close] [mr] ["21]
+\definemathcharacter [(] [open] [mr] ["28]
+\definemathcharacter [)] [close] [mr] ["29]
+\definemathcharacter [*] [bin] [sy] ["03]
+\definemathcharacter [+] [bin] [mr] ["2B]
+\definemathcharacter [,] [punct] [mi] ["3B]
+\definemathcharacter [-] [bin] [sy] ["00]
+\definemathcharacter [.] [ord] [mi] ["3A]
+\definemathcharacter [/] [ord] [mi] ["3D]
+\definemathcharacter [:] [rel] [mr] ["3A]
+\definemathcharacter [;] [punct] [mr] ["3B]
+\definemathcharacter [<] [rel] [mi] ["3C]
+\definemathcharacter [=] [rel] [mr] ["3D]
+\definemathcharacter [>] [rel] [mi] ["3E]
+\definemathcharacter [?] [close] [mr] ["3F]
+\definemathcharacter [91] [open] [mr] ["5B] % [
+\definemathcharacter [92] [ord] [sy] ["6E] % \
+\definemathcharacter [93] [close] [mr] ["5D] % ]
+\definemathcharacter [123] [open] [sy] ["66] % {
+\definemathcharacter [124] [ord] [sy] ["6A] % |
+\definemathcharacter [125] [close] [sy] ["67] % }
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathcharacter [(] [nothing] [mr] ["28] [ex] ["00]
+\definemathcharacter [)] [nothing] [mr] ["29] [ex] ["01]
+\definemathcharacter [91] [nothing] [mr] ["5B] [ex] ["02] % [
+\definemathcharacter [93] [nothing] [mr] ["5D] [ex] ["03] % ]
+\definemathcharacter [<] [nothing] [sy] ["68] [ex] ["0A]
+\definemathcharacter [>] [nothing] [sy] ["69] [ex] ["0B]
+\definemathcharacter [/] [nothing] [mr] ["2F] [ex] ["0E]
+\definemathcharacter [124] [nothing] [sy] ["6A] [ex] ["0C] % |
+\definemathcharacter [92] [nothing] [sy] ["6E] [ex] ["0F] % \
+
+\stopmathcollection
+
+\def\PLAINangle
+ {{\vbox{\ialign{$\mathsurround\zeropoint\scriptstyle##$\crcr
+ \not\mathrel{\mkern14mu}\crcr
+ \noalign{\nointerlineskip}
+ \mkern2.5mu\leaders\hrule height.34pt\hfill\mkern2.5mu\crcr}}}}
+
+\startmathcollection[default]
+
+\definemathsymbol [aleph] [nothing] [sy] ["40]
+\definemathsymbol [imath] [nothing] [mi] ["7B]
+\definemathsymbol [jmath] [nothing] [mi] ["7C]
+\definemathsymbol [ell] [nothing] [mi] ["60]
+\definemathsymbol [wp] [nothing] [mi] ["7D]
+\definemathsymbol [Re] [nothing] [sy] ["3C]
+\definemathsymbol [Im] [nothing] [sy] ["3D]
+\definemathsymbol [partial] [nothing] [mi] ["40]
+\definemathsymbol [infty] [nothing] [sy] ["31]
+\definemathsymbol [prime] [nothing] [sy] ["30]
+\definemathsymbol [emptyset] [nothing] [sy] ["3B]
+\definemathsymbol [nabla] [nothing] [sy] ["72]
+\definemathsymbol [top] [nothing] [sy] ["3E]
+\definemathsymbol [bot] [nothing] [sy] ["3F]
+
+\definemathcommand [hbar] {{\mathchar'26\mkern-9muh}}
+\definemathcommand [surd] {{\mathchar"1270}} % ?
+\definemathcommand [angle] {\PLAINangle}
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [triangle] [ord] [sy] ["34]
+\definemathsymbol [forall] [ord] [sy] ["38]
+\definemathsymbol [exists] [ord] [sy] ["39]
+\definemathsymbol [neg] [ord] [sy] ["3A]
+\definemathsymbol [flat] [ord] [mi] ["5B]
+\definemathsymbol [natural] [ord] [mi] ["5C]
+\definemathsymbol [sharp] [ord] [mi] ["5D]
+\definemathsymbol [clubsuit] [ord] [sy] ["7C]
+\definemathsymbol [diamondsuit] [ord] [sy] ["7D]
+\definemathsymbol [heartsuit] [ord] [sy] ["7E]
+\definemathsymbol [spadesuit] [ord] [sy] ["7F]
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathcommand [square] {\hbox{\hsmash{$\sqcup$}$\sqcap$}}
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [coprod] [op] [ex] ["60]
+\definemathsymbol [bigvee] [op] [ex] ["57]
+\definemathsymbol [bigwedge] [op] [ex] ["56]
+\definemathsymbol [biguplus] [op] [ex] ["55]
+\definemathsymbol [bigcap] [op] [ex] ["54]
+\definemathsymbol [bigcup] [op] [ex] ["53]
+\definemathsymbol [intop] [op] [ex] ["52]
+\definemathsymbol [prod] [op] [ex] ["51]
+\definemathsymbol [sum] [op] [ex] ["50]
+\definemathsymbol [bigotimes] [op] [ex] ["4E]
+\definemathsymbol [bigoplus] [op] [ex] ["4C]
+\definemathsymbol [bigodot] [op] [ex] ["4A]
+\definemathsymbol [ointop] [op] [ex] ["48]
+\definemathsymbol [bigsqcup] [op] [ex] ["46]
+\definemathsymbol [smallint] [op] [sy] ["73]
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [triangleleft] [bin] [mi] ["2F]
+\definemathsymbol [triangleright] [bin] [mi] ["2E]
+\definemathsymbol [bigtriangleup] [bin] [sy] ["34]
+\definemathsymbol [bigtriangledown] [bin] [sy] ["35]
+\definemathsymbol [wedge] [bin] [sy] ["5E]
+\definemathsymbol [vee] [bin] [sy] ["5F]
+\definemathsymbol [cap] [bin] [sy] ["5C]
+\definemathsymbol [cup] [bin] [sy] ["5B]
+\definemathsymbol [ddagger] [bin] [sy] ["7A]
+\definemathsymbol [dagger] [bin] [sy] ["79]
+\definemathsymbol [sqcap] [bin] [sy] ["75]
+\definemathsymbol [sqcup] [bin] [sy] ["74]
+\definemathsymbol [uplus] [bin] [sy] ["5D]
+\definemathsymbol [amalg] [bin] [sy] ["71]
+\definemathsymbol [diamond] [bin] [sy] ["05]
+\definemathsymbol [bullet] [bin] [sy] ["0F]
+\definemathsymbol [wr] [bin] [sy] ["6F]
+\definemathsymbol [div] [bin] [sy] ["04]
+\definemathsymbol [odot] [bin] [sy] ["0C]
+\definemathsymbol [oslash] [bin] [sy] ["0B]
+\definemathsymbol [otimes] [bin] [sy] ["0A]
+\definemathsymbol [ominus] [bin] [sy] ["09]
+\definemathsymbol [oplus] [bin] [sy] ["08]
+\definemathsymbol [mp] [bin] [sy] ["07]
+\definemathsymbol [pm] [bin] [sy] ["06]
+\definemathsymbol [circ] [bin] [sy] ["0E]
+\definemathsymbol [bigcirc] [bin] [sy] ["0D]
+\definemathsymbol [setminus] [bin] [sy] ["6E]
+\definemathsymbol [cdot] [bin] [sy] ["01]
+\definemathsymbol [ast] [bin] [sy] ["03]
+\definemathsymbol [times] [bin] [sy] ["02]
+\definemathsymbol [star] [bin] [mi] ["3F]
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [propto] [rel] [sy] ["2F]
+\definemathsymbol [sqsubseteq] [rel] [sy] ["76]
+\definemathsymbol [sqsupseteq] [rel] [sy] ["77]
+\definemathsymbol [parallel] [rel] [sy] ["6B]
+\definemathsymbol [mid] [rel] [sy] ["6A]
+\definemathsymbol [dashv] [rel] [sy] ["61]
+\definemathsymbol [vdash] [rel] [sy] ["60]
+\definemathsymbol [nearrow] [rel] [sy] ["25]
+\definemathsymbol [searrow] [rel] [sy] ["26]
+\definemathsymbol [nwarrow] [rel] [sy] ["2D]
+\definemathsymbol [swarrow] [rel] [sy] ["2E]
+\definemathsymbol [Leftrightarrow] [rel] [sy] ["2C]
+\definemathsymbol [Leftarrow] [rel] [sy] ["28]
+\definemathsymbol [Rightarrow] [rel] [sy] ["29]
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathcommand [lnot] {\neg}
+\definemathcommand [int] {\intop \intlimits}
+\definemathcommand [oint] {\ointop\intlimits}
+\definemathcommand [land] {\wedge}
+\definemathcommand [lor] {\vee}
+\definemathcommand [neq] {\not=}
+\definemathcommand [ne] {\neq}
+\definemathcommand [le] {\leq}
+\definemathcommand [ge] {\geq}
+\definemathcommand [eq] {=}
+\definemathcommand [gt] {>}
+\definemathcommand [lt] {<}
+\definemathcommand [gets] {\leftarrow}
+\definemathcommand [owns] {\ni}
+\definemathcommand [to] {\rightarrow}
+\definemathcommand [mapsto] {\mapstochar\rightarrow}
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [leq] [rel] [sy] ["14]
+\definemathsymbol [geq] [rel] [sy] ["15]
+\definemathsymbol [succ] [rel] [sy] ["1F]
+\definemathsymbol [prec] [rel] [sy] ["1E]
+\definemathsymbol [approx] [rel] [sy] ["19]
+\definemathsymbol [succeq] [rel] [sy] ["17]
+\definemathsymbol [preceq] [rel] [sy] ["16]
+\definemathsymbol [supset] [rel] [sy] ["1B]
+\definemathsymbol [subset] [rel] [sy] ["1A]
+\definemathsymbol [supseteq] [rel] [sy] ["13]
+\definemathsymbol [subseteq] [rel] [sy] ["12]
+\definemathsymbol [in] [rel] [sy] ["32]
+\definemathsymbol [ni] [rel] [sy] ["33]
+\definemathsymbol [gg] [rel] [sy] ["1D]
+\definemathsymbol [ll] [rel] [sy] ["1C]
+\definemathsymbol [not] [rel] [sy] ["36]
+\definemathsymbol [leftrightarrow] [rel] [sy] ["24]
+\definemathsymbol [leftarrow] [rel] [sy] ["20]
+\definemathsymbol [rightarrow] [rel] [sy] ["21]
+\definemathsymbol [mapstochar] [rel] [sy] ["37]
+\definemathsymbol [sim] [rel] [sy] ["18]
+\definemathsymbol [simeq] [rel] [sy] ["27]
+\definemathsymbol [perp] [rel] [sy] ["3F]
+\definemathsymbol [equiv] [rel] [sy] ["11]
+\definemathsymbol [asymp] [rel] [sy] ["10]
+\definemathsymbol [smile] [rel] [mi] ["5E]
+\definemathsymbol [frown] [rel] [mi] ["5F]
+\definemathsymbol [leftharpoonup] [rel] [mi] ["28]
+\definemathsymbol [leftharpoondown] [rel] [mi] ["29]
+\definemathsymbol [rightharpoonup] [rel] [mi] ["2A]
+\definemathsymbol [rightharpoondown] [rel] [mi] ["2B]
+\definemathsymbol [lhook] [rel] [mi] ["2C]
+\definemathsymbol [rhook] [rel] [mi] ["2D]
+
+\stopmathcollection
+
+\def\PLAINldots
+ {\ldotp\ldotp\ldotp}
+
+\def\PLAINcdots
+ {\cdotp\cdotp\cdotp}
+
+\def\PLAINvdots
+ {\vbox{\baselineskip.4\bodyfontsize\lineskiplimit\zeropoint
+ \kern.6\bodyfontsize\hbox{.}\hbox{.}\hbox{.}}}
+
+\def\PLAINddots
+ {\mkern1mu\raise.7\bodyfontsize\vbox{\kern.7\bodyfontsize\hbox{.}}\mkern2mu
+ \raise.4\bodyfontsize\hbox{.}\mkern2mu\raise.1\bodyfontsize\hbox{.}\mkern1mu}
+
+\startmathcollection[default]
+
+\definemathcommand [hookrightarrow] {\lhook\joinrel\rightarrow}
+\definemathcommand [hookleftarrow] {\leftarrow\joinrel\rhook}
+\definemathcommand [bowtie] {\mathrel\triangleright\joinrel\mathrel\triangleleft}
+\definemathcommand [models] {\mathrel|\joinrel=}
+\definemathcommand [iff] {\;\Longleftrightarrow\;}
+
+\definemathsymbol [ldotp] [punct] [mi] ["3A]
+\definemathsymbol [cdotp] [punct] [sy] ["01]
+\definemathsymbol [colon] [punct] [mr] ["3A]
+
+\definemathcommand [ldots] [inner] {\PLAINldots}
+\definemathcommand [cdots] [inner] {\PLAINcdots}
+\definemathcommand [vdots] [nothing] {\PLAINvdots}
+\definemathcommand [ddots] [inner] {\PLAINddots}
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [acute] [accent] [mr] ["13]
+\definemathsymbol [grave] [accent] [mr] ["12]
+\definemathsymbol [ddot] [accent] [mr] ["7F]
+\definemathsymbol [tilde] [accent] [mr] ["7E]
+\definemathsymbol [mathring] [accent] [mr] ["17]
+\definemathsymbol [bar] [accent] [mr] ["16]
+\definemathsymbol [breve] [accent] [mr] ["15]
+\definemathsymbol [check] [accent] [mr] ["14]
+\definemathsymbol [hat] [accent] [mr] ["5E]
+\definemathsymbol [vec] [accent] [mi] ["7E] % [ord]
+\definemathsymbol [dot] [accent] [mr] ["5F]
+\definemathsymbol [widetilde] [accent] [ex] ["65] % [ord]
+\definemathsymbol [widehat] [accent] [ex] ["62] % [ord]
+
+\stopmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [lmoustache] [open] [ex] ["7A] [ex] ["40]
+\definemathsymbol [rmoustache] [close] [ex] ["7B] [ex] ["41]
+\definemathsymbol [lgroup] [open] [mr] ["28] [ex] ["3A] % ?
+\definemathsymbol [rgroup] [close] [mr] ["29] [ex] ["3B] % ?
+\definemathsymbol [arrowvert] [nothing] [sy] ["6A] [ex] ["3C]
+\definemathsymbol [Arrowvert] [nothing] [sy] ["6B] [ex] ["3D]
+\definemathsymbol [bracevert] [nothing] [ex] ["3E] % ?
+\definemathsymbol [Vert] [nothing] [sy] ["6B] [ex] ["0D]
+\definemathsymbol [vert] [nothing] [sy] ["6A] [ex] ["0C]
+\definemathsymbol [uparrow] [rel] [sy] ["22] [ex] ["78]
+\definemathsymbol [downarrow] [rel] [sy] ["23] [ex] ["79]
+\definemathsymbol [updownarrow] [rel] [sy] ["6C] [ex] ["3F]
+\definemathsymbol [Uparrow] [rel] [sy] ["2A] [ex] ["7E]
+\definemathsymbol [Downarrow] [rel] [sy] ["2B] [ex] ["7F]
+\definemathsymbol [Updownarrow] [rel] [sy] ["6D] [ex] ["77]
+\definemathsymbol [backslash] [nothing] [sy] ["6E] [ex] ["0F]
+\definemathsymbol [langle] [open] [sy] ["68] [ex] ["0A]
+\definemathsymbol [rangle] [close] [sy] ["69] [ex] ["0B]
+\definemathsymbol [lbrace] [open] [sy] ["66] [ex] ["08]
+\definemathsymbol [rbrace] [close] [sy] ["67] [ex] ["09]
+\definemathsymbol [lceil] [open] [sy] ["64] [ex] ["06]
+\definemathsymbol [rceil] [close] [sy] ["65] [ex] ["07]
+\definemathsymbol [lfloor] [open] [sy] ["62] [ex] ["04]
+\definemathsymbol [rfloor] [close] [sy] ["63] [ex] ["05]
+
+\definemathsymbol [sqrt] [radical] [sy] ["70] [ex] ["70]
+
+\stopmathcollection
+
+%D By request:
+
+\startmathcollection[default]
+
+\definemathsymbol [lvert] [open] [sy] ["6A] [ex] ["0C]
+\definemathsymbol [rvert] [close] [sy] ["6A] [ex] ["0C]
+
+\definemathsymbol [lVert] [open] [sy] ["6B] [ex] ["0D]
+\definemathsymbol [rVert] [close] [sy] ["6B] [ex] ["0D]
+
+\stopmathcollection
+
+%D For brooks:
+%D
+%D \starttyping
+%D $\sqrt[3]{10}$
+%D \stoptyping
+
+\ifx\normalsqrt\undefined \let\normalsqrt\sqrt \fi % just set to: \dohandlemathtoken {sqrt}
+
+\def\notsosqrt[#1]{\root#1\of}
+
+\unexpanded\def\sqrt{\doifnextoptionalelse\notsosqrt\normalsqrt}
+
+\def\PLAINbig {\@@dobig{0.85}}
+\def\PLAINBig {\@@dobig{1.15}}
+\def\PLAINbigg{\@@dobig{1.45}}
+\def\PLAINBigg{\@@dobig{1.75}}
+
+\startrawmathcollection [default]
+
+\definemathcommand [bigl] [open] [one] {\big}
+\definemathcommand [bigm] [rel] [one] {\big}
+\definemathcommand [bigr] [close] [one] {\big}
+\definemathcommand [Bigl] [open] [one] {\Big}
+\definemathcommand [Bigm] [rel] [one] {\Big}
+\definemathcommand [Bigr] [close] [one] {\Big}
+\definemathcommand [biggl] [open] [one] {\bigg}
+\definemathcommand [biggm] [rel] [one] {\bigg}
+\definemathcommand [biggr] [close] [one] {\bigg}
+\definemathcommand [Biggl] [open] [one] {\Bigg}
+\definemathcommand [Biggm] [rel] [one] {\Bigg}
+\definemathcommand [Biggr] [close] [one] {\Bigg}
+
+\definemathcommand [big] {\PLAINbig}
+\definemathcommand [Big] {\PLAINBig}
+\definemathcommand [bigg] {\PLAINbigg}
+\definemathcommand [Bigg] {\PLAINBigg}
+
+\stoprawmathcollection
+
+\startmathcollection[default]
+
+\definemathsymbol [dag] [box] [sy] ["79]
+\definemathsymbol [ddag] [box] [sy] ["7A]
+\definemathsymbol [S] [box] [sy] ["78]
+\definemathsymbol [P] [box] [sy] ["7B]
+\definemathsymbol [Orb] [box] [sy] ["0D]
+
+\stopmathcollection
+
+\def\PLAINroot#1#2%
+ {\setbox\zerocount\hbox{$\mathsurround\zeropoint#1\sqrt{#2}$}\dimen@\ht\zerocount
+ \advance\dimen@-\dp\zerocount
+ \mkern5mu\raise.6\dimen@\copy\rootbox \mkern-10mu\box\zerocount}
+
+\def\PLAINmatrix#1%
+ {\null\,\vcenter{\normalbaselines\mathsurround\zeropoint
+ \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
+ \mathstrut\crcr\noalign{\kern-\baselineskip}
+ #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,}
+
+\startrawmathcollection[default]
+
+\definemathcommand [mathstrut] {\vphantom{(}}
+\definemathcommand [joinrel] {\mathrel{\mkern-3mu}}
+\definemathcommand [r@@t] {\PLAINroot}
+\definemathcommand [matrix] {\PLAINmatrix}
+
+\definemathcommand [over] {\normalover} % hack, to do
+
+\stoprawmathcollection
+
+\def\{{\lbrace}
+\def\}{\rbrace}
+
+%def\bbd{\fam\purefamily{blackboard}}
+%def\cal{\fam\purefamily{calfamily}}
+
+\def\mit{\fam\purefamily{mitfamily}}
+
+\def\Bbb{\blackboard} % conforming amstex
+
+\startmathcollection[default]
+
+ \definemathsymbol [mathperiod] [ord] [mi] ["3A]
+ \definemathsymbol [textperiod] [punct] [mi] ["3A]
+
+ \definemathsymbol [mathcomma] [ord] [mi] ["3B]
+ \definemathsymbol [textcomma] [punct] [mi] ["3B]
+
+\stopmathcollection
+
+\definemathpunctuation . mathperiod textperiod
+\definemathpunctuation , mathcomma textcomma
+
+%D The following colon related definitions are provided by Aditya
+%D Mahajan who derived them from \type {mathtools.sty} and \type
+%D {colonequals.sty}.
+
+%D \macros
+%D {centercolon, colonminus, minuscolon, colonequals, equalscolon,
+%D colonapprox, approxcolon, colonsim, simcolon, coloncolon,
+%D coloncolonminus, minuscoloncolon, coloncolonequals,
+%D equalscoloncolon, coloncolonapprox, approxcoloncolon,
+%D colonsim, simcoloncolon}
+%D
+%D In $a := b$ the colon is not vertically centered with the equal
+%D to. Also the distance between colon and equal to is a bit large.
+%D So, we define a vertically centered colon \tex {centercolon} and
+%D a few macros for colon and double colon relation symbols.
+%D
+%D \startlines
+%D \formula {A \centercolon B}
+%D \formula {A \colonminus B}
+%D \formula {A \minuscolon B}
+%D \formula {A \colonequals B}
+%D \formula {A \equalscolon B}
+%D \formula {A \colonapprox B}
+%D \formula {A \approxcolon B}
+%D \formula {A \colonsim B}
+%D \formula {A \simcolon B}
+%D \formula {A \coloncolon B}
+%D \formula {A \coloncolonminus B}
+%D \formula {A \minuscoloncolon B}
+%D \formula {A \coloncolonequals B}
+%D \formula {A \equalscoloncolon B}
+%D \formula {A \coloncolonapprox B}
+%D \formula {A \approxcoloncolon B}
+%D \formula {A \colonsim B}
+%D \formula {A \simcoloncolon B}
+%D \stoplines
+
+%D The next macros take care of the space between the colon and the
+%D relation symbol.
+
+\definemathcommand [colonsep] {\mkern-1.2mu}
+\definemathcommand [doublecolonsep] {\mkern-0.9mu}
+
+%D The next macro vertically centeres its contents.
+
+\def\@center@math#1%
+ {\vcenter{\hbox{$\mathsurround\zeropoint#1$}}}
+
+\def\@center@colon
+ {\mathpalette\@center@math{\colon}}
+
+%D Now we define all the colon relations.
+
+\definemathcommand [centercolon] [rel] {\@center@colon}
+\definemathcommand [colonminus] [rel] {\centercolon\colonsep\mathrel{-}}
+\definemathcommand [minuscolon] [rel] {\mathrel{-}\colonsep\centercolon}
+\definemathcommand [colonequals] [rel] {\centercolon\colonsep=}
+\definemathcommand [equalscolon] [rel] {=\centercolon\colonsep}
+\definemathcommand [colonapprox] [rel] {\centercolon\colonsep\approx}
+\definemathcommand [approxcolon] [rel] {\approx\centercolon\colonsep}
+\definemathcommand [colonsim] [rel] {\centercolon\colonsep\sim}
+\definemathcommand [simcolon] [rel] {\sim\centercolon\colonsep}
+
+\definemathcommand [coloncolon] [rel] {\centercolon\doublecolonsep\centercolon}
+\definemathcommand [coloncolonminus] [rel] {\coloncolon\colonsep\mathrel{-}}
+\definemathcommand [minuscoloncolon] [rel] {\mathrel{-}\colonsep\coloncolon}
+\definemathcommand [coloncolonequals] [rel] {\coloncolon\colonsep=}
+\definemathcommand [equalscoloncolon] [rel] {=\coloncolon\colonsep}
+\definemathcommand [coloncolonapprox] [rel] {\coloncolon\colonsep\approx}
+\definemathcommand [approxcoloncolon] [rel] {\approx\coloncolon\colonsep}
+\definemathcommand [colonsim] [rel] {\coloncolon\colonsep\sim}
+\definemathcommand [simcoloncolon] [rel] {\sim\coloncolon\colonsep}
+
+%D More integrals (AM):
+
+\def\dointkern{\mkern-6mu\mathchoice{\mkern-3mu}{}{}{}}
+
+\definemathcommand [iint] {\repeatintegral\plusone }
+\definemathcommand [iiint] {\repeatintegral\plustwo }
+\definemathcommand [iiiint] {\repeatintegral\plusthree}
+
+\def\repeatintegral#1%
+ {\scratchtoks\emptytoks
+ \let\dointlimits\donothing
+ \let\dodointlimits\intlimits
+ \dorecurse{#1}{\appendtoks \intop \dointkern \to \scratchtoks}
+ \appendtoks \intop \dointlimits \dodointlimits \to \scratchtoks
+ \edef\dodorepeatintegral{\the\scratchtoks}%
+ \futurelet\next\dorepeatintegral}
+
+%D If the \type{\limits} option is used after \type{\iint}, use
+%D \type{\mathop} and fudge the left hand space a bit to make the
+%D subscript visually centered.
+
+\def\dorepeatintegral
+ {\ifx\next\limits \dointlimitcorrection \else
+ \ifx\next\displaylimits \dointlimitcorrection \else
+ \ifx\next\nolimits \donothing \else
+ \ifcase\intlimitcode\else \dointlimitcorrection \fi\fi\fi\fi
+ \dodorepeatintegral}
+
+\def\dointlimitcorrection
+ {\mkern-7mu\mathchoice{\mkern-2mu}{}{}{}%
+ \mathop\bgroup
+ \mkern7mu\mathchoice{\mkern2mu}{}{}{}%
+ \let\dointlimits\egroup}
+
+\setupmathematics
+ [integral=nolimits]
+
+\protect \endinput
diff --git a/tex/context/base/math-tim.mkii b/tex/context/base/math-tim.mkii
new file mode 100644
index 000000000..3b9aea103
--- /dev/null
+++ b/tex/context/base/math-tim.mkii
@@ -0,0 +1,371 @@
+%D \module
+%D [ file=math-tim,
+%D version=2001.04.12,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=Mathtime Specials,
+%D author={Hans Hagen \& Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\endinput % i will clean this up after taco has gone over it
+
+%D With thanks to Berthold Horn from YandY for providing me
+%D evaluation copies of the MathTimePlus fonts.
+
+% version 0 : Michael Spivak
+% version 1 : Taco Hoekwater
+% version 2 : Hans Hagen
+% version 3 : etc etc etc
+
+\unprotect
+
+%D We use the predefined spare families \type {\mcfam} and
+%D \type {\mdfam}.
+
+\let\cafam\mcfam \let\hexcafam\hexmcfam
+\let\gbfam\mdfam \let\hexgbfam\hexmdfam
+\let\gkfam\mdfam \let\hexgkfam\hexmdfam
+
+% Why is this needed?
+
+% \font\tenmd =mtgu at 10pt
+% \font\sevenmd=mtgu at 7.6pt
+% \font\fivemd =mtgu at 6pt
+% \font\tenmc =mtms at 10pt
+% \font\sevenmc=mtms at 7.6pt
+% \font\fivemc =mtms at 6pt
+%
+% \textfont \mcfam\tenmc \textfont \mdfam\tenmd
+% \scriptfont \mcfam\sevenmc \scriptfont \mdfam\sevenmd
+% \scriptscriptfont\mcfam\fivemc \scriptscriptfont\mdfam\fivemd
+
+% \addtocommalist{gk}\familylist
+% \addtocommalist{gb}\familylist
+%
+% \defineinterfaceconstant {ca} {ca} % boohoo!
+% \defineinterfaceconstant {gk} {gk} % boohoo!
+% \defineinterfaceconstant {gb} {gb} % boohoo!
+
+% \definealternativestyle[script] [\ca][\ca]
+% \definealternativestyle[greek] [\gk][\gk]
+% \definealternativestyle[boldgreek][\gb][\gb]
+
+% \definebodyfont
+% [5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt] [rm]
+% [ca=mtms sa 1,
+% gk=mtgu sa 1,
+% gb=mtgub sa 1]
+
+%D Since a font size is a rather fuzzy thing, it will be no
+%D surprise that the Math Times fonts have different specs
+%D than the Computer Modern Roman fonts.
+%D
+%D \starttabulate[|Bl|c|c|c|c|c|c|c|c|c|c|]
+%D \NC Computer Modern\NC
+%D 5 \NC6 \NC7 \NC8 \NC9 \NC10 \NC11 \NC12 \NC14 \NC18\NC\NR
+%D \NC Math Times \NC
+%D 6.0\NC6.8\NC7.6\NC8.4\NC9.2\NC10.0\NC10.8\NC11.6\NC13.2\NC--\NC\NR
+%D \stoptabulate
+%D
+%D The following definitions presume the existence of \type
+%D {tio} and \type {tibio} font alternatives. Definitions for
+%D \type {\tf.} etc and \type {\sc} are left as they are.
+
+%D moved code
+
+%D The next lines set up coding dependant versions of math
+%D accents (for \type {texnansi} of course). These are needed
+%D in commands like \type {\bf} and \type {\it} (which use the
+%D text font encoding) a opposed to \type {_no spec_} and
+%D \type {mi} that use the math font encoding. This stuff
+%D should be made more general!
+
+% \daghex, \ddaghex and \dothex were wrong in my version of mtmacs
+
+\def\daghex {86} % to do
+\def\ddaghex {87}
+\def\Shex {A7}
+\def\Phex {B6}
+\def\barhex {16}
+\def\gravehex{12}
+\def\acutehex{13}
+\def\checkhex{14}
+\def\brevehex{15}
+\def\hathex {5E}
+\def\dothex {05}
+\def\tildehex{7E}
+\def\ddothex {7F}
+
+%D The \type {mtex} fonts need a recalculation of \type
+%D {\p@renwd}, which in \CONTEXT\ is done automatically.
+
+%D The following definitions are mostly copied from the file
+%D \type {mtmacs.tex}, which banner said:
+%D
+%D \starttyping
+%D MTMACS.TEX VERSION 1.1.1 (1996 Dec 8)
+%D COPYRIGHT (C) 1992, 1993, 1996 BY THE TEXPLORATORS CORPORATION
+%D ALL RIGHTS RESERVED
+%D \stoptyping
+%D
+%D We reformatted the macros and changed a few bits and
+%D pieces. A further cleanup with regards to the scratch
+%D registers will be done later.
+
+\mathchardef\Gamma = "0130
+\mathchardef\Delta = "0131
+\mathchardef\Theta = "0132
+\mathchardef\Lambda = "0133
+\mathchardef\Xi = "0134
+\mathchardef\Pi = "0135
+\mathchardef\Sigma = "0136
+\mathchardef\Upsilon = "0137
+\mathchardef\Phi = "0138
+\mathchardef\Psi = "0139
+\mathchardef\Omega = "017F
+\mathchardef\varGamma = "0100
+\mathchardef\varDelta = "0101
+\mathchardef\varTheta = "0102
+\mathchardef\varLambda = "0103
+\mathchardef\varXi = "0104
+\mathchardef\varPi = "0105
+\mathchardef\varSigma = "0106
+\mathchardef\varUpsilon = "0107
+\mathchardef\varPhi = "0108
+\mathchardef\varPsi = "0109
+\mathchardef\varOmega = "010A
+\mathchardef\varkappa = "017E
+
+\mathchardef\ldotp = "613A
+
+\mathchardef\triangleleft = "2247
+\mathchardef\triangleright = "2246
+\mathchardef\comp = "2242
+
+\mathchardef\Relbar = "3248
+\mathchardef\dagger = "20\daghex % to do
+\mathchardef\ddagger = "20\ddaghex % to do
+\mathchardef\dotacc = "0250
+
+\mathcode`\( = "412E
+\mathcode`\) = "512F
+\mathcode`\. = "013A
+\mathcode`\, = "613B
+\mathcode`\+ = "2243
+\mathcode`\= = "3244
+\mathcode`\; = "6249
+
+\delcode `\( = "12E300
+\delcode `\) = "12F301
+
+\let\mit=\undefined % to do
+
+\def\vec{\mathaccent"0245 }
+\def\t#1{{\edef\next{\the\font}\the\textfont2\accent"41\next#1}}
+
+% fam equals -1 unless the user has said something
+% like \rm (cf. the texbook page 290)
+
+\def\ifdefaultfamelse#1#2%
+ {\ifnum\fam=\minusone\mathaccent#1\else\mathaccent#2\fi}
+
+\let\noaccents@\relax
+
+\def\grave {\ifdefaultfamelse{"024A}{"70\gravehex}}
+\def\acute {\ifdefaultfamelse{"024B}{"70\acutehex}}
+\def\check {\ifdefaultfamelse{"024C}{"70\checkhex}}
+\def\breve {\ifdefaultfamelse{"024D}{"70\brevehex}}
+\def\bar {\ifdefaultfamelse{"024E}{"70\barhex }}
+\def\hat {\ifdefaultfamelse{"024F}{"70\hathex }}
+\def\dot {\ifdefaultfamelse{"0250}{"70\dothex }}
+\def\tilde {\ifdefaultfamelse{"0251}{"70\tildehex}}
+\def\ddot {\ifdefaultfamelse{"0252}{"70\ddothex }}
+
+\def\widebar{\mathaccent"0253 }
+
+\def\mathhexbox@#1#2#3%
+ {\relax
+ \ifmmode
+ \mathpalette{}{\mathsurround\zeropoint\rm\mathchar"#1#2#3}%
+ \else
+ \leavevmode
+ \hbox{$\mathsurround\zeropoint\rm\mathchar"#1#2#3$}%
+ \fi}
+
+\def\dag {\edef\next@{0\daghex }\expandafter\mathhexbox@\next@}
+\def\ddag{\edef\next@{0\ddaghex}\expandafter\mathhexbox@\next@}
+
+\def\S{\edef\next@{0\Shex}\expandafter\mathhexbox@\next@}
+\def\P{\edef\next@{0\Phex}\expandafter\mathhexbox@\next@}
+
+\def\vdots%
+ {\vbox
+ {\baselineskip4\points
+ \lineskiplimit\zeropoint
+ \kern6\points\hbox{$\mathsurround\zeropoint.$}\hbox{$\mathsurround\zeropoint.$}\hbox{$\mathsurround\zeropoint.$}}}
+
+\def\ddots%
+ {\mathinner
+ {\mkern1mu
+ \raise7\points\vbox{\kern 7\points\hbox{$\mathsurround\zeropoint.$}}\mkern2mu
+ \raise4\points\hbox{$\mathsurround\zeropoint.$}\mkern2mu
+ \raise \points\hbox{$\mathsurround\zeropoint.$}\mkern1mu}}
+
+\def\hbar
+ {{\mathchoice
+ {\hbox{\lower.07em \hbox{$\mathchar"\barhex$}}}
+ {\hbox{\lower.07em \hbox{$\mathchar"\barhex$}}}
+ {\hbox{\lower.049em\hbox{$\scriptstyle\mathchar"\barhex$}}}
+ {\hbox{\lower.035em\hbox{$\scriptscriptstyle\mathchar"\barhex$}}}%
+ \mkern-6.3muh}}
+
+\def\angle%
+ {{\vbox{\ialign{$\mathsurround\zeropoint\scriptstyle##$\crcr
+ \not\mathrel{\mkern14mu}\crcr
+ \noalign{\nointerlineskip}
+ \mkern2.5mu\leaders\hrule height.48\points\hfill\mkern2.5mu\crcr}}}}
+
+\newdimen\amstexex
+
+\amstexex = .2326ex
+
+\def\varinjlim%
+ {\mathop{\vtop{\ialign{##\crcr
+ \hfil\the\textfont\zerocount lim\hfil\crcr
+ \noalign{\nointerlineskip}\rightarrowfill\crcr
+ \noalign{\nointerlineskip\kern-\amstexex}\crcr}}}}
+
+\def\varprojlim%
+ {\mathop{\vtop{\ialign{##\crcr
+ \hfil\the\textfont\zerocount lim\hfil\crcr
+ \noalign{\nointerlineskip}\leftarrowfill\crcr
+ \noalign{\nointerlineskip\kern-\amstexex}\crcr}}}}
+
+\def\varliminf{\mathop{\underbar {lim}}} % context-ified
+\def\varlimsup{\mathop{\overstrike{lim}}} % context-ified
+
+\def\spdot {^{\hbox{\raise\amstexex\hbox{\the\textfont\zerocount .}}}}
+\def\spddot {^{\hbox{\raise\amstexex\hbox{\the\textfont\zerocount ..}}}}
+\def\spdddot {^{\hbox{\raise\amstexex\hbox{\the\textfont\zerocount ...}}}}
+\def\spddddot{^{\hbox{\raise\amstexex\hbox{\the\textfont\zerocount....}}}}
+
+%D Here some code is merged in order to save strings.
+
+\def\domultidot#1#2%
+ {\setbox0\hbox{$#1#2$}%
+ \setbox2\hbox{$#1\infty$}%
+ \dimen0\ht2
+ \ifdim\ht0<\dimen0 \dimen0\ht0 \fi
+ \setbox2\hbox{$#1#2\mathchar"012D$}%
+ \dimen2\wd2
+ \advance\dimen2-\wd0
+ \setbox0\hbox{$#1\rhook$}%
+ \advance\dimen2-\wd0
+ \vbox
+ {\offinterlineskip
+ \ialign{\hfil$#1##$\hfil\cr
+ \kern\dimen2\dotacc\mkern-2.5mu\dotacc\mkern-2.5mu\dotacc\thirddot\cr
+ \noalign{\vskip-\dimen0}%
+ #2\cr}}}
+
+\def\dddot%
+ {\def\thirddot{}%
+ \mathpalette\domultidot}
+
+\def\ddddot%
+ {\def\thirddot{\mkern-2.5mu\dotacc}%
+ \mathpalette\domultidot}
+
+\newcount\uproot@
+\newcount\leftroot@
+
+\def\nonmatherr#1%
+ {\errmessage{\noexpand#1allowed only in math mode}}
+
+\def\uproot#1%
+ {\relax
+ \ifmmode
+ \uproot@#1\relax
+ \else
+ \nonmatherr\uproot
+ \fi}
+
+\def\leftroot#1%
+ {\relax
+ \ifmmode
+ \leftroot@#1\relax
+ \else
+ \nonmatherr\leftroot
+ \fi}
+
+\def\root#1\of#2%
+ {\setbox\rootbox=\hbox{$\mathsurround\zeropoint\scriptscriptstyle{#1}$}%
+ \mathpalette\r@@t{#2}}
+
+\def\r@@t#1#2%
+ {\setbox\zerocount\hbox{$\uproot@\zerocount\leftroot\zerocount\mathsurround\zeropoint#1\sqrt{#2}$}%
+ \dimen@\ht\zerocount\advance\dimen@-\dp\zerocount
+ \dimen@ii\dimen@
+ \ifdim\dimen@>30\points \advance\dimen@ii-16\points \else
+ \ifdim\dimen@>24\points \advance\dimen@ii -8\points \else
+ \ifdim\dimen@>18\points \advance\dimen@ii -6\points \else
+ \ifdim\dimen@>12\points \advance\dimen@ii -4\points \else
+ \ifdim\dimen@>10\points \advance\dimen@ii -2\points \fi\fi\fi\fi\fi
+ \setbox\plustwo=\hbox{$\mathsurround\zeropoint#1\mskip\uproot@ mu$}%
+ \advance\dimen@ii by1.667\wd\plustwo
+ \mkern-\leftroot@ mu\mkern5mu\raise.6\dimen@ii\copy\rootbox
+ \mkern-8mu\mkern\leftroot@ mu\box\zerocount\leftroot\zerocount\uproot\zerocount}
+
+\def\space@.{\futurelet\space@\relax} \space@. % really needed ?
+
+\def\jadjust%
+ {\mkern-\plustwo mu}
+
+%D For the moment the following code is left unchanged. It is
+%D not used anyway.
+
+\newif\ifsubscriptcorrection \subscriptcorrectionfalse
+
+\ifsubscriptcorrection
+
+ \expandafter\let\csname subscript character \string_\endcsname_
+
+ \catcode`\_=\active
+
+ \def_%
+ {\ifmmode
+ \expandafter\sb@
+ \else
+ \expandafter\csname subscript character \string_\endcsname
+ \fi}
+
+ \let\sb_
+
+ \ifnum\catcode`\^^A=8 \catcode`\^^A\active\let^^A_\fi
+
+ \def\sb@#1%
+ {\csname subscript character \string_\endcsname
+ {\futurelet\next\sb@@#1}}
+
+ \def\sb@@%
+ {\ifx\next\space@
+ \def\next@. %
+ {\futurelet\next\sb@@}%
+ \else
+ \def\next@.%
+ {\ifx\next j%
+ \mkern-\plustwo mu\else
+ \ifx\next f%
+ \mkern-\plustwo mu\else
+ \ifx\next p%
+ \mkern-\plusone mu\fi\fi\fi}%
+ \fi
+ \next@.}
+
+\fi
+
+\protect
diff --git a/tex/context/base/math-uni.mkii b/tex/context/base/math-uni.mkii
new file mode 100644
index 000000000..e8fd3f05d
--- /dev/null
+++ b/tex/context/base/math-uni.mkii
@@ -0,0 +1,237 @@
+%D \module
+%D [ file=math-uni,
+%D version=2005.06.11,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=unicode support,
+%D author={Nikolai Weibull \& Taco Hoekwater},
+%D date=\currentdate,
+%D copyright=PRAGMA]
+
+\unprotect
+
+% needed for unic-032 % TH
+
+\startmathcollection[default]
+
+ \definemathcommand [unic@doubleverticalline] {\mathord{\parallel}}
+ \definemathcommand [unic@doublelowline] {\underline{\textunderscore}}
+
+ \definemathcommand [unic@doubleprime] {''}
+ \definemathcommand [unic@tripleprime] {'''}
+
+ \definemathcommand [unic@reverseddoubleprime] {\mathord{\backprime\backprime}}
+ \definemathcommand [unic@reversedtripleprime] {\mathord{\backprime\backprime\backprime}}
+
+ \definemathcommand [unic@fractionslash] {\vulgarfraction{}{}}
+ \definemathcommand [unic@lowasterisk] {\mathord{\lower-.2em\hbox{$\ast$}}}
+
+ \definemathcommand [unic@functionapplication] {\mathop{}}
+ \definemathcommand [unic@invisibletimes] {\mathbin{}}
+ \definemathcommand [unic@invisibleseparator] {\mathpunct{}}
+
+\stopmathcollection
+
+% needed for unic-033 % TH
+
+\def\unic@vulgarfraction#1#2%
+ {\hbox
+ {\high{{\tfx\it #1}\kern -.2em}%
+ \symbol[vulgarfraction]%
+ \kern -.2em\low{{\tfx\it #2}}}}
+
+\startmathcollection[default]
+
+ \definemathcommand [unic@accountof] {\unic@vulgarfraction{a}{c}}
+ \definemathcommand [unic@addressedtothesubject] {\unic@vulgarfraction{a}{s}}
+ \definemathcommand [unic@doublestruckC] {{\Bbb C}}
+ \definemathcommand [unic@degreecelsius] {{\textdegree \tf C}}
+ \definemathcommand [unic@centrelinesymbol] {\unknownchar}
+ \definemathcommand [unic@careof] {\unic@vulgarfraction{c}{o}}
+ \definemathcommand [unic@cadauna] {\unic@vulgarfraction{c}{u}}
+ \definemathcommand [unic@eulerconstant] {{\rm e}}
+ \definemathcommand [unic@scruple] {\unknownchar}
+ \definemathcommand [unic@degreefahrenheit] {{\textdegree \tf F}}
+ \definemathcommand [unic@scriptg] {\unknownchar}
+ \definemathcommand [unic@scriptH] {{\cal H}}
+ \definemathcommand [unic@blackletterH] {{\fraktur H}}
+ \definemathcommand [unic@doublestruckH] {{\Bbb H}}
+ \definemathcommand [unic@planckconstant] {h}
+ \definemathcommand [unic@planckconstantovertwopi] {\hslash}
+ \definemathcommand [unic@scriptI] {{\cal I}}
+ \definemathcommand [unic@blackletterI] {{\fraktur I}}
+ \definemathcommand [unic@scriptL] {{\cal L}}
+ \definemathcommand [unic@scriptl] {\ell}
+ \definemathcommand [unic@lbbarsymbol] {\unknownchar}
+ \definemathcommand [unic@doublestruckN] {{\Bbb N}}
+ \definemathcommand [unic@numerosign] {\hbox{\symbol[numero]}}
+ \definemathcommand [unic@soundrecordingcopyright] {\encircled{{\tfx P}}}
+ \definemathcommand [unic@scriptP] {{\cal P}}
+ \definemathcommand [unic@doublestruckP] {{\Bbb P}}
+ \definemathcommand [unic@doublestruckQ] {{\Bbb Q}}
+ \definemathcommand [unic@scriptR] {{\cal R}}
+ \definemathcommand [unic@blackletterR] {{\fraktur R}}
+ \definemathcommand [unic@doublestruckR] {{\Bbb R}}
+ \definemathcommand [unic@prescriptiontake] {\unknownchar}
+ \definemathcommand [unic@response] {\unknownchar}
+ \definemathcommand [unic@servicemark] {\high{\txx SM}}
+ \definemathcommand [unic@telephonesign] {\high{\txx TEL}}
+ \definemathcommand [unic@trademarksign] {\trademark}
+ \definemathcommand [unic@versickle] {\unknownchar}
+ \definemathcommand [unic@doublestruckZ] {{\Bbb Z}}
+ \definemathcommand [unic@ouncesign] {\unknownchar}
+ \definemathcommand [unic@ohmsign] {\Omega}
+ \definemathcommand [unic@invertedohmsign] {\rotate[\c!rotation=180]{\Omega}}
+ \definemathcommand [unic@blackletterZ] {{\fraktur Z}}
+ \definemathcommand [unic@turnedgreekletteriota] {\rotate[\c!rotation=180]{\iota}}
+ \definemathcommand [unic@kelvinsign] {{\tf K}}
+ \definemathcommand [unic@angstromsign] {\Angstrom}
+ \definemathcommand [unic@scriptB] {{\cal B}}
+ \definemathcommand [unic@blackletterC] {{\fraktur C}}
+ \definemathcommand [unic@estimatedsymbol] {\unknownchar}
+ \definemathcommand [unic@scripte] {\unknownchar}
+ \definemathcommand [unic@scriptE] {{\cal E}}
+ \definemathcommand [unic@scriptF] {{\cal F}}
+ \definemathcommand [unic@turnedF] {\rotate[\c!rotation=180]{{\tf F}}}
+ \definemathcommand [unic@scriptM] {{\cal M}}
+ \definemathcommand [unic@scripto] {\unknownchar}
+
+ \definemathcommand [unic@informationsource] {{\bf i}}
+ \definemathcommand [unic@rotatedQ] {\rotate[\c!rotation=90]{{\tf Q}}}
+ \definemathcommand [unic@facsimilesign] {\unknownchar}
+ \definemathcommand [unic@doublestruckpi] {\pi}%{\unknownchar}
+ \definemathcommand [unic@doublestruckgamma] {\gamma}%{\unknownchar}
+ \definemathcommand [unic@doublestruckGamma] {\Gamma}%{\unknownchar}
+ \definemathcommand [unic@doublestruckPi] {\Pi}%{\unknownchar}
+ \definemathcommand [unic@doublestrucknarysummation] {\unknownchar}
+ \definemathcommand [unic@turnedsansserifG] {\rotate[\c!rotation=180]{{\ss G}}}
+ \definemathcommand [unic@turnedsansserifL] {\rotate[\c!rotation=180]{{\ss L}}}
+ \definemathcommand [unic@reversedsansserifL] {\mirror{{\ss L}}}
+ \definemathcommand [unic@turnedsansserifY] {\rotate[\c!rotation=180]{{\ss Y}}}
+ \definemathcommand [unic@doublestruckitalicD] {D}%{\unknownchar}
+ \definemathcommand [unic@doublestruckitalicd] {d}%{\unknownchar}
+ \definemathcommand [unic@doublestruckitalice] {e}%{\unknownchar}
+ \definemathcommand [unic@doublestruckitalici] {i}%{\unknownchar}
+ \definemathcommand [unic@doublestruckitalicj] {j}%{\unknownchar}
+ \definemathcommand [unic@propertyline] {\unknownchar}
+ \definemathcommand [unic@turnedampersand] {\rotate[\c!rotation=180]{\&}}
+ \definemathcommand [unic@persign] {\unknownchar}
+
+ \definemathcommand [unic@fractiononethird] {\vulgarfraction{1}{3}}
+ \definemathcommand [unic@fractiontwothirds] {\vulgarfraction{2}{3}}
+ \definemathcommand [unic@fractiononefifth] {\vulgarfraction{1}{5}}
+ \definemathcommand [unic@fractiontwofifths] {\vulgarfraction{2}{5}}
+ \definemathcommand [unic@fractionthreefifths] {\vulgarfraction{3}{5}}
+ \definemathcommand [unic@fractionfourfifths] {\vulgarfraction{4}{5}}
+ \definemathcommand [unic@fractiononesixth] {\vulgarfraction{1}{6}}
+ \definemathcommand [unic@fractionfivesixths] {\vulgarfraction{5}{6}}
+ \definemathcommand [unic@fractiononeeighth] {\vulgarfraction{1}{8}}
+ \definemathcommand [unic@fractionthreeeighths] {\vulgarfraction{3}{8}}
+ \definemathcommand [unic@fractionfiveeighths] {\vulgarfraction{5}{8}}
+ \definemathcommand [unic@fractionseveneighths] {\vulgarfraction{7}{8}}
+ \definemathcommand [unic@fractionnumeratorone] {\vulgarfraction{1}{}}
+ \definemathcommand [unic@romannumeralOne] {{\tf I}}
+ \definemathcommand [unic@romannumeralTwo] {{\tf II}}
+ \definemathcommand [unic@romannumeralThree] {{\tf III}}
+ \definemathcommand [unic@romannumeralFour] {{\tf IV}}
+ \definemathcommand [unic@romannumeralFive] {{\tf V}}
+ \definemathcommand [unic@romannumeralSix] {{\tf VI}}
+ \definemathcommand [unic@romannumeralSeven] {{\tf VII}}
+ \definemathcommand [unic@romannumeralEight] {{\tf VIII}}
+ \definemathcommand [unic@romannumeralNine] {{\tf IX}}
+ \definemathcommand [unic@romannumeralTen] {{\tf X}}
+ \definemathcommand [unic@romannumeralEleven] {{\tf XI}}
+ \definemathcommand [unic@romannumeralTwelve] {{\tf XII}}
+ \definemathcommand [unic@romannumeralFifty] {{\tf L}}
+ \definemathcommand [unic@romannumeralOnehundred] {{\tf C}}
+ \definemathcommand [unic@romannumeralFivehundred] {{\tf D}}
+ \definemathcommand [unic@romannumeralOnethousand] {{\tf M}}
+ \definemathcommand [unic@romannumeralone] {{\tf i}}
+ \definemathcommand [unic@romannumeraltwo] {{\tf ii}}
+ \definemathcommand [unic@romannumeralthree] {{\tf iii}}
+ \definemathcommand [unic@romannumeralfour] {{\tf iv}}
+ \definemathcommand [unic@romannumeralfive] {{\tf v}}
+ \definemathcommand [unic@romannumeralsix] {{\tf vi}}
+ \definemathcommand [unic@romannumeralseven] {{\tf vii}}
+ \definemathcommand [unic@romannumeraleight] {{\tf viii}}
+ \definemathcommand [unic@romannumeralnine] {{\tf ix}}
+ \definemathcommand [unic@romannumeralten] {{\tf x}}
+ \definemathcommand [unic@romannumeraleleven] {{\tf xi}}
+ \definemathcommand [unic@romannumeraltwelve] {{\tf xii}}
+ \definemathcommand [unic@romannumeralfifty] {{\tf l}}
+ \definemathcommand [unic@romannumeralonehundred] {{\tf c}}
+ \definemathcommand [unic@romannumeralfivehundred] {{\tf d}}
+ \definemathcommand [unic@romannumeralonethousand] {{\tf m}}
+ \definemathcommand [unic@romannumeralonethousandCD] {\unknownchar}
+ \definemathcommand [unic@romannumeralfivethousand] {\unknownchar}
+ \definemathcommand [unic@romannumeraltenthousand] {\unknownchar}
+ \definemathcommand [unic@romannumeralreversedonehundred] {\mirror{C}}
+
+\stopmathcollection
+
+% needed for unic-033 % NW
+
+\startmathcollection[default]
+
+ \definemathcommand [unic@leftarrowtobar] {\mapstochar\leftarrow}
+
+\stopmathcollection
+
+% needed for unic-034 % NW
+
+\startmathcollection[default]
+
+ \definemathcommand [unic@in] {\in}
+ \definemathcommand [unic@nin] {\not\in}
+ \definemathcommand [unic@nni] {\not\ni}
+ \definemathcommand [unic@minus] {-}
+ \definemathcommand [unic@divisionslash] {/}
+ \definemathcommand [unic@sqrt] {\sqrt{}}
+ \definemathcommand [unic@cubesqrt] {\root 3 \of {}}
+ \definemathcommand [unic@fourthsqrt] {\root 4 \of {}}
+ \definemathcommand [unic@divides] [op] {|} % TODO
+ \definemathcommand [unic@ndivides] [rel] {\mathop{\not|}} % TODO: horrible
+ \definemathcommand [unic@cap] {\cap}
+ \definemathcommand [unic@dblint] {\int\!\!\!\int}
+ \definemathcommand [unic@triint] {\int\!\!\!\int\!\!\!\int}
+ \definemathcommand [unic@ratio] [rel] {:}
+ \definemathcommand [unic@proportion] [rel] {::}
+ \definemathcommand [unic@excess] [op] {-\!\!:}
+ \definemathcommand [unic@geomprop] [op] {:\!\!\!-\!\!\!:}
+ \definemathcommand [unic@homothetic] [op] {\sim\!\!\!:}
+ \definemathcommand [unic@nsimeq] {\not\simeq}
+ \definemathcommand [unic@cong] {\cong}
+ \definemathcommand [unic@napproxeq] {\not\approxeq}
+ \definemathcommand [unic@napprox] {\not\approx}
+ \definemathcommand [unic@doteq] {\doteq}
+ \definemathcommand [unic@correspondsto] {\buildrel \frown \over =}
+ \definemathcommand [unic@estimates] {\buildrel \wedge \over =}
+ \definemathcommand [unic@equiangularto] {\buildrel \vee \over =}
+ \definemathcommand [unic@stareq] {\buildrel \star \over =}
+ \definemathcommand [unic@eqbydef] {\buildrel \rm def \over =}
+ \definemathcommand [unic@measuredby] {\buildrel \rm m \over =}
+ \definemathcommand [unic@questionedeq] {\buildrel \rm ? \over =}
+ \definemathcommand [unic@nequiv] {\not\equiv}
+ \definemathcommand [unic@nasymp] {\not\asymp}
+ \definemathcommand [unic@nlesssim] {\not\lesssim}
+ \definemathcommand [unic@ngtrsim] {\not\gtrsim}
+ \definemathcommand [unic@nlessgtr] {\not\lessgtr}
+ \definemathcommand [unic@ngtrless] {\not\gtrless}
+ \definemathcommand [unic@nsubset] {\not\subset}
+ \definemathcommand [unic@nsupset] {\not\supset}
+ \definemathcommand [unic@nsqsubseteq] {\not\sqsubseteq}
+ \definemathcommand [unic@nsqsupseteq] {\not\sqsupseteq}
+
+\stopmathcollection
+
+% needed for unic-039 % NW
+
+\startmathcollection[default]
+
+ \definemathcommand [unic@Lbracket] [open] {[\![}
+ \definemathcommand [unic@Rbracket] [close] {]\!]}
+ \definemathcommand [unic@Langle] [open] {\langle\!\langle}
+ \definemathcommand [unic@Rangle] [close] {\rangle\!\rangle}
+
+\stopmathcollection
+
+\protect \endinput
diff --git a/tex/context/base/math-vfu.lua b/tex/context/base/math-vfu.lua
new file mode 100644
index 000000000..5023e6b4d
--- /dev/null
+++ b/tex/context/base/math-vfu.lua
@@ -0,0 +1,1379 @@
+if not modules then modules = { } end modules ['math-vfu'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- All these math vectors .. thanks to Aditya and Mojca they become
+-- better and better. If you have problems with math fonts or miss
+-- characters report it to the ConTeXt mailing list.
+
+local type, next = type, next
+
+local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
+local trace_timings = false trackers.register("math.timings", function(v) trace_timings = v end)
+
+fonts.enc.math = fonts.enc.math or { }
+
+local shared = { }
+
+fonts.vf.math = fonts.vf.math or { }
+fonts.vf.math.optional = false
+
+local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 }
+
+local function negate(main,characters,id,size,unicode,basecode)
+ if not characters[unicode] then
+ local basechar = characters[basecode]
+ if basechar then
+ local ht, wd = basechar.height, basechar.width
+ characters[unicode] = {
+ width = wd,
+ height = ht,
+ depth = basechar.depth,
+ italic = basechar.italic,
+ kerns = basechar.kerns,
+ commands = {
+ { "slot", 1, basecode },
+ push,
+ { "down", ht/5},
+ { "right", - wd/2},
+ back,
+ push,
+ }
+ }
+ end
+ end
+end
+
+--~ \Umathchardef\braceld="0 "1 "FF07A
+--~ \Umathchardef\bracerd="0 "1 "FF07B
+--~ \Umathchardef\bracelu="0 "1 "FF07C
+--~ \Umathchardef\braceru="0 "1 "FF07D
+
+local function brace(main,characters,id,size,unicode,first,rule,left,right,rule,last)
+ if not characters[unicode] then
+ characters[unicode] = {
+ horiz_variants = {
+ { extender = 0, glyph = first },
+ { extender = 1, glyph = rule },
+ { extender = 0, glyph = left },
+ { extender = 0, glyph = right },
+ { extender = 1, glyph = rule },
+ { extender = 0, glyph = last },
+ }
+ }
+ end
+end
+
+local function arrow(main,characters,id,size,unicode,arrow,minus,isleft)
+ if characters[unicode] then
+ if isleft then
+ t = {
+ { extender = 0, glyph = arrow },
+ { extender = 1, glyph = minus },
+ }
+ else
+ t = {
+ { extender = 0, glyph = minus },
+ { extender = 1, glyph = arrow },
+ }
+ end
+ --~ main.characters[unicode] = { horiz_variants = t }
+ characters[unicode].horiz_variants = t
+ end
+end
+
+local function parent(main,characters,id,size,unicode,first,rule,last)
+ if not characters[unicode] then
+ characters[unicode] = {
+ horiz_variants = {
+ { extender = 0, glyph = first },
+ { extender = 1, glyph = rule },
+ { extender = 0, glyph = last },
+ }
+ }
+ end
+end
+
+local push, pop, step = { "push" }, { "pop" }, 0.2 -- 0.1 is nicer but gives larger files
+
+local function make(main,characters,id,size,n,m)
+ local old = 0xFF000+n
+ local c = characters[old]
+ if c then
+ local upslot, dnslot, uprule, dnrule = 0xFF100+n, 0xFF200+n, 0xFF300+m, 0xFF400+m
+ local xu = main.parameters.x_height + 0.3*size
+ local xd = 0.3*size
+ local w, h, d = c.width, c.height, c.depth
+ local thickness = h - d
+ local rulewidth = step*size -- we could use an overlap
+ local slot = { "slot", id, old }
+ local rule = { "rule", thickness, rulewidth }
+ local up = { "down", -xu }
+ local dn = { "down", xd }
+ local ht, dp = xu + 3*thickness, 0
+ if not characters[uprule] then
+ characters[uprule] = { width = rulewidth, height = ht, depth = dp, commands = { push, up, rule, pop } }
+ end
+ characters[upslot] = { width = w, height = ht, depth = dp, commands = { push, up, slot, pop } }
+ local ht, dp = 0, xd + 3*thickness
+ if not characters[dnrule] then
+ characters[dnrule] = { width = rulewidth, height = ht, depth = dp, commands = { push, dn, rule, pop } }
+ end
+ characters[dnslot] = { width = w, height = ht, depth = dp, commands = { push, dn, slot, pop } }
+ end
+end
+
+local function minus(main,characters,id,size,unicode)
+ local minus = characters[0x002D]
+ if minus then
+ local mu = size/18
+ local width = minus.width - 5*mu
+ characters[unicode] = {
+ width = width, height = minus.height, depth = minus.depth,
+ commands = { push, { "right", -3*mu }, { "slot", id, 0x002D }, pop }
+ }
+ end
+end
+
+local function dots(main,characters,id,size,unicode)
+ local c = characters[0x002E]
+ if c then
+ local w, h, d = c.width, c.height, c.depth
+ local mu = size/18
+ local right3mu = { "right", 3*mu }
+ local right1mu = { "right", 1*mu }
+ local up1size = { "down", -.1*size }
+ local up4size = { "down", -.4*size }
+ local up7size = { "down", -.7*size }
+ local right2muw = { "right", 2*mu + w }
+ local slot = { "slot", id, 0x002E }
+ if unicode == 0x22EF then
+ local c = characters[0x022C5]
+ if c then
+ local w, h, d = c.width, c.height, c.depth
+ local slot = { "slot", id, 0x022C5 }
+ characters[unicode] = {
+ width = 3*w + 2*3*mu, height = h, depth = d,
+ commands = { push, slot, right3mu, slot, right3mu, slot, pop }
+ }
+ end
+ elseif unicode == 0x22EE then
+ -- weird height !
+ characters[unicode] = {
+ width = w, height = h+(1.4)*size, depth = 0,
+ commands = { push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop }
+ }
+ elseif unicode == 0x22F1 then
+ characters[unicode] = {
+ width = 3*w + 6*size/18, height = 1.5*size, depth = 0,
+ commands = {
+ push,
+ right1mu,
+ push, up7size, slot, pop,
+ right2muw,
+ push, up4size, slot, pop,
+ right2muw,
+ push, up1size, slot, pop,
+ right1mu,
+ pop
+ }
+ }
+ elseif unicode == 0x22F0 then
+ characters[unicode] = {
+ width = 3*w + 6*size/18, height = 1.5*size, depth = 0,
+ commands = {
+ push,
+ right1mu,
+ push, up1size, slot, pop,
+ right2muw,
+ push, up4size, slot, pop,
+ right2muw,
+ push, up7size, slot, pop,
+ right1mu,
+ pop
+ }
+ }
+ else
+ characters[unicode] = {
+ width = 3*w + 2*3*mu, height = h, depth = d,
+ commands = { push, slot, right3mu, slot, right3mu, slot, pop }
+ }
+ end
+ end
+end
+
+local function vertbar(main,characters,id,size,parent,scale,unicode)
+ local cp = characters[parent]
+ if cp then
+ local sc = scale * size
+ local pc = { "slot", id, parent }
+ characters[unicode] = {
+ width = cp.width,
+ height = cp.height + sc,
+ depth = cp.depth + sc,
+ commands = {
+ push, { "down", -sc }, pc, pop,
+ push, { "down", sc }, pc, pop,
+ pc,
+ },
+ next = cp.next -- can be extensible
+ }
+ cp.next = unicode
+ end
+end
+
+function fonts.vf.math.alas(main,id,size)
+ local characters = main.characters
+ for i=0x7A,0x7D do
+ make(main,characters,id,size,i,1)
+ end
+ brace (main,characters,id,size,0x23DE,0xFF17A,0xFF301,0xFF17D,0xFF17C,0xFF301,0xFF17B)
+ brace (main,characters,id,size,0x23DF,0xFF27C,0xFF401,0xFF27B,0xFF27A,0xFF401,0xFF27D)
+ parent (main,characters,id,size,0x23DC,0xFF17A,0xFF301,0xFF17B)
+ parent (main,characters,id,size,0x23DD,0xFF27C,0xFF401,0xFF27D)
+ negate (main,characters,id,size,0x2260,0x003D)
+ dots (main,characters,id,size,0x2026) -- ldots
+ dots (main,characters,id,size,0x22EE) -- vdots
+ dots (main,characters,id,size,0x22EF) -- cdots
+ dots (main,characters,id,size,0x22F1) -- ddots
+ dots (main,characters,id,size,0x22F0) -- udots
+ minus (main,characters,id,size,0xFF501)
+ arrow (main,characters,id,size,0x2190,0xFE190,0xFF501,true) -- left
+ arrow (main,characters,id,size,0x2192,0xFE192,0xFF501,false) -- right
+ vertbar(main,characters,id,size,0x0007C,0.10,0xFF601) -- big : 0.85 bodyfontsize
+ vertbar(main,characters,id,size,0xFF601,0.30,0xFF602) -- Big : 1.15 bodyfontsize
+ vertbar(main,characters,id,size,0xFF602,0.30,0xFF603) -- bigg : 1.45 bodyfontsize
+ vertbar(main,characters,id,size,0xFF603,0.30,0xFF604) -- Bigg : 1.75 bodyfontsize
+ vertbar(main,characters,id,size,0x02225,0.10,0xFF605)
+ vertbar(main,characters,id,size,0xFF605,0.30,0xFF606)
+ vertbar(main,characters,id,size,0xFF606,0.30,0xFF607)
+ vertbar(main,characters,id,size,0xFF607,0.30,0xFF608)
+end
+
+local unique = 0 -- testcase: \startTEXpage \math{!\text{-}\text{-}\text{-}} \stopTEXpage
+
+function fonts.basecopy(tfmtable,name)
+ local characters, parameters, fullname = tfmtable.characters, tfmtable.parameters, tfmtable.fullname
+ local t, c, p = { }, { }, { }
+ for k, v in next, tfmtable do
+ t[k] = v
+ end
+ if characters then
+ for k, v in next, characters do
+ c[k] = v
+ end
+ t.characters = c
+ else
+ logs.report("math virtual","font %s has no characters",name)
+ end
+ if parameters then
+ for k, v in next, parameters do
+ p[k] = v
+ end
+ t.parameters = p
+ else
+ logs.report("math virtual","font %s has no parameters",name)
+ end
+ -- tricky ... what if fullname does not exist
+ if fullname then
+ unique = unique + 1
+ t.fullname = fullname .. "-" .. unique
+ end
+ return t
+end
+
+local reported = { }
+local reverse -- index -> unicode
+
+function fonts.vf.math.define(specification,set)
+ if not reverse then
+ reverse = { }
+ for k, v in next, fonts.enc.math do
+ local r = { }
+ for u, i in next, v do
+ r[i] = u
+ end
+ reverse[k] = r
+ end
+ end
+ local name = specification.name -- symbolic name
+ local size = specification.size -- given size
+ local fnt, lst, main = { }, { }, nil
+ local start = (trace_virtual or trace_timings) and os.clock()
+ local okset, n = { }, 0
+ for s=1,#set do
+ local ss = set[s]
+ local ssname = ss.name
+ if ss.optional and fonts.vf.math.optional then
+ if trace_virtual then
+ logs.report("math virtual","loading font %s subfont %s with name %s at %s is skipped",name,s,ssname,size)
+ end
+ else
+ if ss.features then ssname = ssname .. "*" .. ss.features end
+ if ss.main then main = s end
+ local f, id = fonts.tfm.read_and_define(ssname,size)
+ if not f then
+ logs.report("math virtual","loading font %s subfont %s with name %s at %s is skipped, not found",name,s,ssname,size)
+ else
+ n = n + 1
+ okset[n] = ss
+ fnt[n] = f
+ lst[n] = { id = id, size = size }
+ if not shared[s] then shared[n] = { } end
+ if trace_virtual then
+ logs.report("math virtual","loading font %s subfont %s with name %s at %s as id %s using encoding %s",name,s,ssname,size,id,ss.vector or "none")
+ end
+ end
+ end
+ end
+ -- beware, fnt[1] is already passed to tex (we need to make a simple copy then .. todo)
+ main = fonts.basecopy(fnt[1],name)
+ main.name, main.fonts, main.virtualized, main.math_parameters = name, lst, true, { }
+ local characters, descriptions = main.characters, main.descriptions
+ local mp = main.parameters
+ if mp then
+ mp.x_height = mp.x_height or 0
+ end
+ local already_reported = false
+ for s=1,n do
+ local ss, fs = okset[s], fnt[s]
+ if not fs then
+ -- skip, error
+ elseif ss.optional and fonts.vf.math.optional then
+ -- skip, redundant
+ else
+ local mm, fp = main.math_parameters, fs.parameters
+ if mm and fp and mp then
+ if ss.extension then
+ mm.math_x_height = fp.x_height or 0 -- math_x_height height of x
+ mm.default_rule_thickness = fp[ 8] or 0 -- default_rule_thickness thickness of \over bars
+ mm.big_op_spacing1 = fp[ 9] or 0 -- big_op_spacing1 minimum clearance above a displayed op
+ mm.big_op_spacing2 = fp[10] or 0 -- big_op_spacing2 minimum clearance below a displayed op
+ mm.big_op_spacing3 = fp[11] or 0 -- big_op_spacing3 minimum baselineskip above displayed op
+ mm.big_op_spacing4 = fp[12] or 0 -- big_op_spacing4 minimum baselineskip below displayed op
+ mm.big_op_spacing5 = fp[13] or 0 -- big_op_spacing5 padding above and below displayed limits
+ -- logs.report("math virtual","loading and virtualizing font %s at size %s, setting ex parameters",name,size)
+ elseif ss.parameters then
+ mp.x_height = fp.x_height or mp.x_height
+ mm.x_height = mm.x_height or fp.x_height or 0 -- x_height height of x
+ mm.num1 = fp[ 8] or 0 -- num1 numerator shift-up in display styles
+ mm.num2 = fp[ 9] or 0 -- num2 numerator shift-up in non-display, non-\atop
+ mm.num3 = fp[10] or 0 -- num3 numerator shift-up in non-display \atop
+ mm.denom1 = fp[11] or 0 -- denom1 denominator shift-down in display styles
+ mm.denom2 = fp[12] or 0 -- denom2 denominator shift-down in non-display styles
+ mm.sup1 = fp[13] or 0 -- sup1 superscript shift-up in uncramped display style
+ mm.sup2 = fp[14] or 0 -- sup2 superscript shift-up in uncramped non-display
+ mm.sup3 = fp[15] or 0 -- sup3 superscript shift-up in cramped styles
+ mm.sub1 = fp[16] or 0 -- sub1 subscript shift-down if superscript is absent
+ mm.sub2 = fp[17] or 0 -- sub2 subscript shift-down if superscript is present
+ mm.sup_drop = fp[18] or 0 -- sup_drop superscript baseline below top of large box
+ mm.sub_drop = fp[19] or 0 -- sub_drop subscript baseline below bottom of large box
+ mm.delim1 = fp[20] or 0 -- delim1 size of \atopwithdelims delimiters in display styles
+ mm.delim2 = fp[21] or 0 -- delim2 size of \atopwithdelims delimiters in non-displays
+ mm.axis_height = fp[22] or 0 -- axis_height height of fraction lines above the baseline
+ -- logs.report("math virtual","loading and virtualizing font %s at size %s, setting sy parameters",name,size)
+ end
+ else
+ logs.report("math virtual","font %s, no parameters set",name)
+ end
+ local vectorname = ss.vector
+ if vectorname then
+ local offset = 0xFF000
+ local vector = fonts.enc.math[vectorname]
+ local rotcev = reverse[vectorname]
+ if vector then
+ local fc, fd, si = fs.characters, fs.descriptions, shared[s]
+ local skewchar = ss.skewchar
+ for unicode, index in next, vector do
+ local fci = fc[index]
+ if not fci then
+ local fontname = fs.name or "unknown"
+ local rf = reported[fontname]
+ if not rf then rf = { } reported[fontname] = rf end
+ local rv = rf[vectorname]
+ if not rv then rv = { } rf[vectorname] = rv end
+ local ru = rv[unicode]
+ if not ru then
+ if trace_virtual then
+ logs.report("math virtual", "unicode point U+%05X has no index %04X in vector %s for font %s",unicode,index,vectorname,fontname)
+ elseif not already_reported then
+ logs.report("math virtual", "the mapping is incomplete for '%s' at %s",name,number.topoints(size))
+ already_reported = true
+ end
+ rv[unicode] = true
+ end
+ else
+ local ref = si[index]
+ if not ref then
+ ref = { { 'slot', s, index } }
+ si[index] = ref
+ end
+ local kerns = fci.kerns
+ if kerns then
+ local width = fci.width
+ local krn = { }
+ for k=1,#kerns do
+ local rk = rotcev[k]
+ if rk then
+ krn[rk] = kerns[k]
+ end
+ end
+ if not next(krn) then
+ krn = nil
+ end
+ local t = {
+ width = width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = fci.italic,
+ kerns = krn,
+ commands = ref,
+ }
+ if skewchar and kerns then
+ local k = kerns[skewchar]
+ if k then
+ t.top_accent = width/2 + k
+ end
+ end
+ characters[unicode] = t
+ else
+ characters[unicode] = {
+ width = fci.width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = fci.italic,
+ commands = ref,
+ }
+ end
+ end
+ end
+ if ss.extension then
+ -- todo: if multiple ex, then 256 offsets per instance
+ local extension = fonts.enc.math["large-to-small"]
+ local variants_done = fs.variants_done
+ for index, fci in next, fc do -- the raw ex file
+ if type(index) == "number" then
+ local ref = si[index]
+ if not ref then
+ ref = { { 'slot', s, index } }
+ si[index] = ref
+ end
+ local t = {
+ width = fci.width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = fci.italic,
+ commands = ref,
+ }
+ local n = fci.next
+ if n then
+ t.next = offset + n
+ elseif variants_done then
+ local vv = fci.vert_variants
+ if vv then
+ t.vert_variants = vv
+ end
+ local hv = fci.horiz_variants
+ if hv then
+ t.horiz_variants = hv
+ end
+ else
+ local vv = fci.vert_variants
+ if vv then
+ for i=1,#vv do
+ local vvi = vv[i]
+ vvi.glyph = vvi.glyph + offset
+ end
+ t.vert_variants = vv
+ end
+ local hv = fci.horiz_variants
+ if hv then
+ for i=1,#hv do
+ local hvi = hv[i]
+ hvi.glyph = hvi.glyph + offset
+ end
+ t.horiz_variants = hv
+ end
+ end
+ characters[offset + index] = t
+ end
+ end
+ fs.variants_done = true
+ for unicode, index in next, extension do
+ local cu = characters[unicode]
+ if cu then
+ cu.next = offset + index
+ --~ local n, c, d = unicode, cu, { }
+ --~ print("START", unicode)
+ --~ while n do
+ --~ n = c.next
+ --~ if n then
+ --~ print("NEXT", n)
+ --~ c = characters[n]
+ --~ if not c then
+ --~ print("EXIT")
+ --~ elseif d[n] then
+ --~ print("LOOP")
+ --~ break
+ --~ end
+ --~ d[n] = true
+ --~ end
+ --~ end
+ else
+ local fci = fc[index]
+ if not fci then
+--~ characters[unicode] = {
+--~ width = 0,
+--~ height = 0,
+--~ depth = 0,
+--~ index = 0,
+--~ }
+ else
+ local ref = si[index]
+ if not ref then
+ ref = { { 'slot', s, index } }
+ si[index] = ref
+ end
+ local kerns = fci.kerns
+ if kerns then
+ local krn = { }
+ for k=1,#kerns do
+ krn[offset + k] = kerns[k]
+ end
+ characters[unicode] = {
+ width = fci.width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = fci.italic,
+ commands = ref,
+ kerns = krn,
+ next = offset + index,
+ }
+ else
+ characters[unicode] = {
+ width = fci.width,
+ height = fci.height,
+ depth = fci.depth,
+ italic = fci.italic,
+ commands = ref,
+ next = offset + index,
+ }
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ mathematics.extras.copy(main) --not needed here (yet)
+ end
+ end
+ lst[#lst+1] = { id = font.nextid(), size = size }
+ if mp then -- weak catch
+ fonts.vf.math.alas(main,#lst,size)
+ end
+ if trace_virtual or trace_timings then
+ logs.report("math virtual","loading and virtualizing font %s at size %s took %0.3f seconds",name,size,os.clock()-start)
+ end
+ main.has_italic = true
+ main.type = "virtual" -- not needed
+ mathematics.scaleparameters(main,main,1)
+ main.nomath = false
+--~ print(table.serialize(characters[0x222B]))
+--~ print(main.fontname,table.serialize(main.MathConstants))
+ return main
+end
+
+function mathematics.make_font(name, set)
+ fonts.define.methods[name] = function(specification)
+ return fonts.vf.math.define(specification,set)
+ end
+end
+
+-- varphi is part of the alphabet, contrary to the other var*s'
+
+fonts.enc.math["large-to-small"] = {
+ [0x00028] = 0x00, -- (
+ [0x00029] = 0x01, -- )
+ [0x0005B] = 0x02, -- [
+ [0x0005D] = 0x03, -- ]
+ [0x0230A] = 0x04, -- lfloor
+ [0x0230B] = 0x05, -- rfloor
+ [0x02308] = 0x06, -- lceil
+ [0x02309] = 0x07, -- rceil
+ [0x0007B] = 0x08, -- {
+ [0x0007D] = 0x09, -- }
+ [0x027E8] = 0x0A, -- <
+ [0x027E9] = 0x0B, -- >
+ [0x0007C] = 0x0C, -- |
+--~ [0x0] = 0x0D, -- lVert rVert Vert
+-- [0x0002F] = 0x0E, -- /
+ [0x0005C] = 0x0F, -- \
+--~ [0x0] = 0x3A, -- lgroup
+--~ [0x0] = 0x3B, -- rgroup
+--~ [0x0] = 0x3C, -- arrowvert
+--~ [0x0] = 0x3D, -- Arrowvert
+ [0x02195] = 0x3F, -- updownarrow
+--~ [0x0] = 0x40, -- lmoustache
+--~ [0x0] = 0x41, -- rmoustache
+ [0x0221A] = 0x70, -- sqrt
+ [0x021D5] = 0x77, -- Updownarrow
+ [0x02191] = 0x78, -- uparrow
+ [0x02193] = 0x79, -- downarrow
+ [0x021D1] = 0x7E, -- Uparrow
+ [0x021D3] = 0x7F, -- Downarrow
+ [0x0220F] = 0x59, -- prod
+ [0x02210] = 0x61, -- coprod
+ [0x02211] = 0x58, -- sum
+ [0x0222B] = 0x5A, -- intop
+ [0x0222E] = 0x49, -- ointop
+ [0xFE302] = 0x62, -- widehat
+ [0xFE303] = 0x65, -- widetilde
+ [0x022C0] = 0x5E, -- bigwedge
+ [0x022C1] = 0x5F, -- bigvee
+ [0x022C2] = 0x5C, -- bigcap
+ [0x022C3] = 0x5B, -- bigcup
+ [0x02044] = 0x0E, -- /
+}
+
+fonts.enc.math["tex-ex"] = {
+ [0x0220F] = 0x51, -- prod
+ [0x0222B] = 0x52, -- intop
+ [0x02210] = 0x60, -- coprod
+ [0x02211] = 0x50, -- sum
+ [0x022C0] = 0x56, -- bigwedge
+ [0x022C1] = 0x57, -- bigvee
+ [0x022C2] = 0x54, -- bigcap
+ [0x022C3] = 0x53, -- bigcup
+ [0x02A04] = 0x55, -- biguplus
+ [0x02A02] = 0x4E, -- bigotimes
+ [0x02A01] = 0x4C, -- bigoplus
+ [0x02A03] = 0x4A, -- bigodot
+ [0x0222E] = 0x48, -- ointop
+ [0x02A06] = 0x46, -- bigsqcup
+}
+
+-- only math stuff is needed, since we always use an lm or gyre
+-- font as main font
+
+fonts.enc.math["tex-mr"] = {
+ [0x00393] = 0x00, -- Gamma
+ [0x00394] = 0x01, -- Delta
+ [0x00398] = 0x02, -- Theta
+ [0x0039B] = 0x03, -- Lambda
+ [0x0039E] = 0x04, -- Xi
+ [0x003A0] = 0x05, -- Pi
+ [0x003A3] = 0x06, -- Sigma
+ [0x003A5] = 0x07, -- Upsilon
+ [0x003A6] = 0x08, -- Phi
+ [0x003A8] = 0x09, -- Psi
+ [0x003A9] = 0x0A, -- Omega
+-- [0x00060] = 0x12, -- [math]grave
+-- [0x000B4] = 0x13, -- [math]acute
+-- [0x002C7] = 0x14, -- [math]check
+-- [0x002D8] = 0x15, -- [math]breve
+-- [0x000AF] = 0x16, -- [math]bar
+-- [0x00021] = 0x21, -- !
+-- [0x00028] = 0x28, -- (
+-- [0x00029] = 0x29, -- )
+-- [0x0002B] = 0x2B, -- +
+-- [0x0002F] = 0x2F, -- /
+-- [0x0003A] = 0x3A, -- :
+-- [0x02236] = 0x3A, -- colon
+-- [0x0003B] = 0x3B, -- ;
+-- [0x0003C] = 0x3C, -- <
+-- [0x0003D] = 0x3D, -- =
+-- [0x0003E] = 0x3E, -- >
+-- [0x0003F] = 0x3F, -- ?
+ [0x00391] = 0x41, -- Alpha
+ [0x00392] = 0x42, -- Beta
+ [0x02145] = 0x44,
+ [0x00395] = 0x45, -- Epsilon
+ [0x00397] = 0x48, -- Eta
+ [0x00399] = 0x49, -- Iota
+ [0x0039A] = 0x4B, -- Kappa
+ [0x0039C] = 0x4D, -- Mu
+ [0x0039D] = 0x4E, -- Nu
+ [0x0039F] = 0x4F, -- Omicron
+ [0x003A1] = 0x52, -- Rho
+ [0x003A4] = 0x54, -- Tau
+ [0x003A7] = 0x58, -- Chi
+ [0x00396] = 0x5A, -- Zeta
+-- [0x0005B] = 0x5B, -- [
+-- [0x0005D] = 0x5D, -- ]
+-- [0x0005E] = 0x5E, -- [math]hat -- the text one
+ [0x00302] = 0x5E, -- [math]hat -- the real math one
+-- [0x002D9] = 0x5F, -- [math]dot
+ [0x02146] = 0x64,
+ [0x02147] = 0x65,
+-- [0x002DC] = 0x7E, -- [math]tilde -- the text one
+ [0x00303] = 0x7E, -- [math]tilde -- the real one
+-- [0x000A8] = 0x7F, -- [math]ddot
+}
+
+fonts.enc.math["tex-mr-missing"] = {
+ [0x02236] = 0x3A, -- colon
+}
+
+fonts.enc.math["tex-mi"] = {
+ [0x1D6E4] = 0x00, -- Gamma
+ [0x1D6E5] = 0x01, -- Delta
+ [0x1D6E9] = 0x02, -- Theta
+ [0x1D6F3] = 0x02, -- varTheta (not present in TeX)
+ [0x1D6EC] = 0x03, -- Lambda
+ [0x1D6EF] = 0x04, -- Xi
+ [0x1D6F1] = 0x05, -- Pi
+ [0x1D6F4] = 0x06, -- Sigma
+ [0x1D6F6] = 0x07, -- Upsilon
+ [0x1D6F7] = 0x08, -- Phi
+ [0x1D6F9] = 0x09, -- Psi
+ [0x1D6FA] = 0x0A, -- Omega
+ [0x1D6FC] = 0x0B, -- alpha
+ [0x1D6FD] = 0x0C, -- beta
+ [0x1D6FE] = 0x0D, -- gamma
+ [0x1D6FF] = 0x0E, -- delta
+ [0x1D716] = 0x0F, -- epsilon TODO: 1D716
+ [0x1D701] = 0x10, -- zeta
+ [0x1D702] = 0x11, -- eta
+ [0x1D703] = 0x12, -- theta TODO: 1D703
+ [0x1D704] = 0x13, -- iota
+ [0x1D705] = 0x14, -- kappa
+ [0x1D718] = 0x14, -- varkappa, not in tex fonts
+ [0x1D706] = 0x15, -- lambda
+ [0x1D707] = 0x16, -- mu
+ [0x1D708] = 0x17, -- nu
+ [0x1D709] = 0x18, -- xi
+ [0x1D70B] = 0x19, -- pi
+ [0x1D70C] = 0x1A, -- rho
+ [0x1D70E] = 0x1B, -- sigma
+ [0x1D70F] = 0x1C, -- tau
+ [0x1D710] = 0x1D, -- upsilon
+ [0x1D719] = 0x1E, -- phi
+ [0x1D712] = 0x1F, -- chi
+ [0x1D713] = 0x20, -- psi
+ [0x1D714] = 0x21, -- omega
+ [0x1D700] = 0x22, -- varepsilon (the other way around)
+ [0x1D717] = 0x23, -- vartheta
+ [0x1D71B] = 0x24, -- varpi
+ [0x1D71A] = 0x25, -- varrho
+ [0x1D70D] = 0x26, -- varsigma
+ [0x1D711] = 0x27, -- varphi (the other way around)
+ [0x021BC] = 0x28, -- leftharpoonup
+ [0x021BD] = 0x29, -- leftharpoondown
+ [0x021C0] = 0x2A, -- rightharpoonup
+ [0x021C1] = 0x2B, -- rightharpoondown
+ [0xFE322] = 0x2C, -- lhook (hook for combining arrows)
+ [0xFE323] = 0x2D, -- rhook (hook for combining arrows)
+ [0x022B3] = 0x2E, -- triangleright (TODO: which one is right?)
+ [0x022B2] = 0x2F, -- triangleleft (TODO: which one is right?)
+-- [0x00041] = 0x30, -- 0
+-- [0x00041] = 0x31, -- 1
+-- [0x00041] = 0x32, -- 2
+-- [0x00041] = 0x33, -- 3
+-- [0x00041] = 0x34, -- 4
+-- [0x00041] = 0x35, -- 5
+-- [0x00041] = 0x36, -- 6
+-- [0x00041] = 0x37, -- 7
+-- [0x00041] = 0x38, -- 8
+-- [0x00041] = 0x39, -- 9
+--~ [0x0002E] = 0x3A, -- .
+ [0x0002C] = 0x3B, -- ,
+ [0x0003C] = 0x3C, -- <
+-- [0x0002F] = 0x3D, -- /, slash, solidus
+ [0x02044] = 0x3D, -- / AM: Not sure
+ [0x0003E] = 0x3E, -- >
+ [0x022C6] = 0x3F, -- star
+ [0x02202] = 0x40, -- partial
+--
+ [0x0266D] = 0x5B, -- flat
+ [0x0266E] = 0x5C, -- natural
+ [0x0266F] = 0x5D, -- sharp
+ [0x02323] = 0x5E, -- smile
+ [0x02322] = 0x5F, -- frown
+ [0x02113] = 0x60, -- ell
+--
+ [0x1D6A4] = 0x7B, -- imath (TODO: also 0131)
+ [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237)
+ [0x02118] = 0x7D, -- wp
+ [0x020D7] = 0x7E, -- vec (TODO: not sure)
+-- 0x7F, -- (no idea what that could be)
+}
+
+
+fonts.enc.math["tex-it"] = {
+-- [0x1D434] = 0x41, -- A
+ [0x1D6E2] = 0x41, -- Alpha
+-- [0x1D435] = 0x42, -- B
+ [0x1D6E3] = 0x42, -- Beta
+-- [0x1D436] = 0x43, -- C
+-- [0x1D437] = 0x44, -- D
+-- [0x1D438] = 0x45, -- E
+ [0x1D6E6] = 0x45, -- Epsilon
+-- [0x1D439] = 0x46, -- F
+-- [0x1D43A] = 0x47, -- G
+-- [0x1D43B] = 0x48, -- H
+ [0x1D6E8] = 0x48, -- Eta
+-- [0x1D43C] = 0x49, -- I
+ [0x1D6EA] = 0x49, -- Iota
+-- [0x1D43D] = 0x4A, -- J
+-- [0x1D43E] = 0x4B, -- K
+ [0x1D6EB] = 0x4B, -- Kappa
+-- [0x1D43F] = 0x4C, -- L
+-- [0x1D440] = 0x4D, -- M
+ [0x1D6ED] = 0x4D, -- Mu
+-- [0x1D441] = 0x4E, -- N
+ [0x1D6EE] = 0x4E, -- Nu
+-- [0x1D442] = 0x4F, -- O
+ [0x1D6F0] = 0x4F, -- Omicron
+-- [0x1D443] = 0x50, -- P
+ [0x1D6F2] = 0x50, -- Rho
+-- [0x1D444] = 0x51, -- Q
+-- [0x1D445] = 0x52, -- R
+-- [0x1D446] = 0x53, -- S
+-- [0x1D447] = 0x54, -- T
+ [0x1D6F5] = 0x54, -- Tau
+-- [0x1D448] = 0x55, -- U
+-- [0x1D449] = 0x56, -- V
+-- [0x1D44A] = 0x57, -- W
+-- [0x1D44B] = 0x58, -- X
+ [0x1D6F8] = 0x58, -- Chi
+-- [0x1D44C] = 0x59, -- Y
+-- [0x1D44D] = 0x5A, -- Z
+--
+-- [0x1D44E] = 0x61, -- a
+-- [0x1D44F] = 0x62, -- b
+-- [0x1D450] = 0x63, -- c
+-- [0x1D451] = 0x64, -- d
+-- [0x1D452] = 0x65, -- e
+-- [0x1D453] = 0x66, -- f
+-- [0x1D454] = 0x67, -- g
+-- [0x1D455] = 0x68, -- h
+ [0x0210E] = 0x68, -- Planck constant (h)
+-- [0x1D456] = 0x69, -- i
+-- [0x1D457] = 0x6A, -- j
+-- [0x1D458] = 0x6B, -- k
+-- [0x1D459] = 0x6C, -- l
+-- [0x1D45A] = 0x6D, -- m
+-- [0x1D45B] = 0x6E, -- n
+-- [0x1D45C] = 0x6F, -- o
+ [0x1D70A] = 0x6F, -- omicron
+-- [0x1D45D] = 0x70, -- p
+-- [0x1D45E] = 0x71, -- q
+-- [0x1D45F] = 0x72, -- r
+-- [0x1D460] = 0x73, -- s
+-- [0x1D461] = 0x74, -- t
+-- [0x1D462] = 0x75, -- u
+-- [0x1D463] = 0x76, -- v
+-- [0x1D464] = 0x77, -- w
+-- [0x1D465] = 0x78, -- x
+-- [0x1D466] = 0x79, -- y
+-- [0x1D467] = 0x7A, -- z
+}
+
+fonts.enc.math["tex-ss"] = { }
+fonts.enc.math["tex-tt"] = { }
+fonts.enc.math["tex-bf"] = { }
+fonts.enc.math["tex-bi"] = { }
+fonts.enc.math["tex-fraktur"] = { }
+fonts.enc.math["tex-fraktur-bold"] = { }
+
+function fonts.vf.math.set_letters(font_encoding, name, uppercase, lowercase)
+ local enc = font_encoding[name]
+ for i = 0,25 do
+ enc[uppercase+i] = i + 0x41
+ enc[lowercase+i] = i + 0x61
+ end
+end
+
+function fonts.vf.math.set_digits(font_encoding, name, digits)
+ local enc = font_encoding[name]
+ for i = 0,9 do
+ enc[digits+i] = i + 0x30
+ end
+end
+
+fonts.enc.math["tex-sy"] = {
+ [0x0002D] = 0x00, -- -
+ [0x02212] = 0x00, -- -
+-- [0x02201] = 0x00, -- complement
+-- [0x02206] = 0x00, -- increment
+-- [0x02204] = 0x00, -- not exists
+--~ [0x000B7] = 0x01, -- cdot
+ [0x022C5] = 0x01, -- cdot
+ [0x000D7] = 0x02, -- times
+ [0x0002A] = 0x03, -- *
+ [0x02217] = 0x03, -- *
+ [0x000F7] = 0x04, -- div
+ [0x022C4] = 0x05, -- diamond
+ [0x000B1] = 0x06, -- pm
+ [0x02213] = 0x07, -- mp
+ [0x02295] = 0x08, -- oplus
+ [0x02296] = 0x09, -- ominus
+ [0x02297] = 0x0A, -- otimes
+ [0x02298] = 0x0B, -- oslash
+ [0x02299] = 0x0C, -- odot
+ [0x025EF] = 0x0D, -- bigcirc, Orb (either 25EF or 25CB) -- todo
+ [0x02218] = 0x0E, -- circ
+ [0x02219] = 0x0F, -- bullet
+ [0x02022] = 0x0F, -- bullet
+ [0x0224D] = 0x10, -- asymp
+ [0x02261] = 0x11, -- equiv
+ [0x02286] = 0x12, -- subseteq
+ [0x02287] = 0x13, -- supseteq
+ [0x02264] = 0x14, -- leq
+ [0x02265] = 0x15, -- geq
+ [0x02AAF] = 0x16, -- preceq
+-- [0x0227C] = 0x16, -- preceq, AM:No see 2AAF
+ [0x02AB0] = 0x17, -- succeq
+-- [0x0227D] = 0x17, -- succeq, AM:No see 2AB0
+ [0x0223C] = 0x18, -- sim
+ [0x02248] = 0x19, -- approx
+ [0x02282] = 0x1A, -- subset
+ [0x02283] = 0x1B, -- supset
+ [0x0226A] = 0x1C, -- ll
+ [0x0226B] = 0x1D, -- gg
+ [0x0227A] = 0x1E, -- prec
+ [0x0227B] = 0x1F, -- succ
+ [0x02190] = 0x20, -- leftarrow
+ [0x02192] = 0x21, -- rightarrow
+--~ [0xFE190] = 0x20, -- leftarrow
+--~ [0xFE192] = 0x21, -- rightarrow
+ [0x02191] = 0x22, -- uparrow
+ [0x02193] = 0x23, -- downarrow
+ [0x02194] = 0x24, -- leftrightarrow
+ [0x02197] = 0x25, -- nearrow
+ [0x02198] = 0x26, -- searrow
+ [0x02243] = 0x27, -- simeq
+ [0x021D0] = 0x28, -- Leftarrow
+ [0x021D2] = 0x29, -- Rightarrow
+ [0x021D1] = 0x2A, -- Uparrow
+ [0x021D3] = 0x2B, -- Downarrow
+ [0x021D4] = 0x2C, -- Leftrightarrow
+ [0x02196] = 0x2D, -- nwarrow
+ [0x02199] = 0x2E, -- swarrow
+ [0x0221D] = 0x2F, -- propto
+ [0x02032] = 0x30, -- prime
+ [0x0221E] = 0x31, -- infty
+ [0x02208] = 0x32, -- in
+ [0x0220B] = 0x33, -- ni
+ [0x025B3] = 0x34, -- triangle, bigtriangleup
+ [0x025BD] = 0x35, -- bigtriangledown
+ [0x00338] = 0x36, -- not
+-- 0x37, -- (beginning of arrow)
+ [0x02200] = 0x38, -- forall
+ [0x02203] = 0x39, -- exists
+ [0x000AC] = 0x3A, -- neg, lnot
+ [0x02205] = 0x3B, -- empty set
+ [0x0211C] = 0x3C, -- Re
+ [0x02111] = 0x3D, -- Im
+ [0x022A4] = 0x3E, -- top
+ [0x022A5] = 0x3F, -- bot, perp
+ [0x02135] = 0x40, -- aleph
+ [0x1D49C] = 0x41, -- script A
+ [0x0212C] = 0x42, -- script B
+ [0x1D49E] = 0x43, -- script C
+ [0x1D49F] = 0x44, -- script D
+ [0x02130] = 0x45, -- script E
+ [0x02131] = 0x46, -- script F
+ [0x1D4A2] = 0x47, -- script G
+ [0x0210B] = 0x48, -- script H
+ [0x02110] = 0x49, -- script I
+ [0x1D4A5] = 0x4A, -- script J
+ [0x1D4A6] = 0x4B, -- script K
+ [0x02112] = 0x4C, -- script L
+ [0x02133] = 0x4D, -- script M
+ [0x1D4A9] = 0x4E, -- script N
+ [0x1D4AA] = 0x4F, -- script O
+ [0x1D4AB] = 0x50, -- script P
+ [0x1D4AC] = 0x51, -- script Q
+ [0x0211B] = 0x52, -- script R
+ [0x1D4AE] = 0x53, -- script S
+ [0x1D4AF] = 0x54, -- script T
+ [0x1D4B0] = 0x55, -- script U
+ [0x1D4B1] = 0x56, -- script V
+ [0x1D4B2] = 0x57, -- script W
+ [0x1D4B3] = 0x58, -- script X
+ [0x1D4B4] = 0x59, -- script Y
+ [0x1D4B5] = 0x5A, -- script Z
+ [0x0222A] = 0x5B, -- cup
+ [0x02229] = 0x5C, -- cap
+ [0x0228E] = 0x5D, -- uplus
+ [0x02227] = 0x5E, -- wedge, land
+ [0x02228] = 0x5F, -- vee, lor
+ [0x022A2] = 0x60, -- vdash
+ [0x022A3] = 0x61, -- dashv
+ [0x0230A] = 0x62, -- lfloor
+ [0x0230B] = 0x63, -- rfloor
+ [0x02308] = 0x64, -- lceil
+ [0x02309] = 0x65, -- rceil
+ [0x0007B] = 0x66, -- {, lbrace
+ [0x0007D] = 0x67, -- }, rbrace
+ [0x027E8] = 0x68, -- <, langle
+ [0x027E9] = 0x69, -- >, rangle
+ [0x0007C] = 0x6A, -- |, mid, lvert, rvert
+ [0x02225] = 0x6B, -- parallel, Vert, lVert, rVert, arrowvert
+ [0x02195] = 0x6C, -- updownarrow
+ [0x021D5] = 0x6D, -- Updownarrow
+ [0x0005C] = 0x6E, -- \, backslash, setminus
+ [0x02216] = 0x6E, -- setminus
+ [0x02240] = 0x6F, -- wr
+ [0x0221A] = 0x70, -- sqrt. AM: Check surd??
+ [0x02A3F] = 0x71, -- amalg
+ [0x1D6FB] = 0x72, -- nabla
+-- [0x0222B] = 0x73, -- smallint (TODO: what about intop?)
+ [0x02294] = 0x74, -- sqcup
+ [0x02293] = 0x75, -- sqcap
+ [0x02291] = 0x76, -- sqsubseteq
+ [0x02292] = 0x77, -- sqsupseteq
+ [0x000A7] = 0x78, -- S
+ [0x02020] = 0x79, -- dagger, dag
+ [0x02021] = 0x7A, -- ddagger, ddag
+ [0x000B6] = 0x7B, -- P
+ [0x02663] = 0x7C, -- clubsuit
+ [0x02662] = 0x7D, -- diamondsuit
+ [0x02661] = 0x7E, -- heartsuit
+ [0x02660] = 0x7F, -- spadesuit
+ [0xFE321] = 0x37, -- mapstochar
+}
+
+-- The names in masm10.enc can be trusted best and are shown in the first
+-- column, while in the second column we show the tex/ams names. As usual
+-- it costs hours to figure out such a table.
+
+fonts.enc.math["tex-ma"] = {
+ [0x022A1] = 0x00, -- squaredot \boxdot
+ [0x0229E] = 0x01, -- squareplus \boxplus
+ [0x022A0] = 0x02, -- squaremultiply \boxtimes
+ [0x025A1] = 0x03, -- square \square \Box
+ [0x025A0] = 0x04, -- squaresolid \blacksquare
+ [0x000B7] = 0x05, -- squaresmallsolid \centerdot
+ [0x022C4] = 0x06, -- diamond \Diamond \lozenge
+ [0x029EB] = 0x07, -- diamondsolid \blacklozenge
+ [0x021BA] = 0x08, -- clockwise \circlearrowright
+ [0x021BB] = 0x09, -- anticlockwise \circlearrowleft
+ [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons
+ [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons
+ [0x0229F] = 0x0C, -- squareminus \boxminus
+ [0x022A9] = 0x0D, -- forces \Vdash
+ [0x022AA] = 0x0E, -- forcesbar \Vvdash
+ [0x022A8] = 0x0F, -- satisfies \vDash
+ [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow
+ [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow
+ [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows
+ [0x021C9] = 0x13, -- dblarrowright \rightrightarrows
+ [0x021C8] = 0x14, -- dblarrowup \upuparrows
+ [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows
+ [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction
+ [0x021C2] = 0x17, -- harpoondownright \downharpoonright
+ [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft
+ [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft
+ [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail
+ [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail
+ [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows
+-- [0x021C5] = 0x00, -- \updownarrows (missing in lm)
+ [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows
+ [0x021B0] = 0x1E, -- shiftleft \Lsh
+ [0x021B1] = 0x1F, -- shiftright \Rsh
+ [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow
+ [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow
+ [0x021AB] = 0x22, -- curlyleft \looparrowleft
+ [0x021AC] = 0x23, -- curlyright \looparrowright
+ [0x02257] = 0x24, -- circleequal \circeq
+ [0x0227F] = 0x25, -- followsorequal \succsim
+ [0x02273] = 0x26, -- greaterorsimilar \gtrsim
+ [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox
+ [0x022B8] = 0x28, -- multimap \multimap
+ [0x02234] = 0x29, -- therefore \therefore
+ [0x02235] = 0x2A, -- because \because
+ [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot
+ [0x0225C] = 0x2C, -- defines \triangleq
+ [0x0227E] = 0x2D, -- precedesorequal \precsim
+ [0x02272] = 0x2E, -- lessorsimilar \lesssim
+ [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox
+ [0x02A95] = 0x30, -- equalorless \eqslantless
+ [0x02A96] = 0x31, -- equalorgreater \eqslantgtr
+ [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec
+ [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc
+ [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq
+ [0x02266] = 0x35, -- lessdblequal \leqq
+ [0x02A7D] = 0x36, -- lessorequalslant \leqslant
+ [0x02276] = 0x37, -- lessorgreater \lessgtr
+ [0x02035] = 0x38, -- primereverse \backprime
+ -- [0x0] = 0x39, -- axisshort \dabar
+ [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq
+ [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq
+ [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq
+ [0x02267] = 0x3D, -- greaterdblequal \geqq
+ [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant
+ [0x02277] = 0x3F, -- greaterorless \gtrless
+ [0x0228F] = 0x40, -- squareimage \sqsubset
+ [0x02290] = 0x41, -- squareoriginal \sqsupset
+ -- wrong:
+ [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright
+ [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft
+ [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq
+ [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq
+ --
+ [0x02605] = 0x46, -- star \bigstar
+ [0x0226C] = 0x47, -- between \between
+ [0x025BC] = 0x48, -- triangledownsld \blacktriangledown
+ [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright
+ [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft
+ -- [0x0] = 0x4B, -- arrowaxisright
+ -- [0x0] = 0x4C, -- arrowaxisleft
+ [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle
+ [0x025B2] = 0x4E, -- trianglesolid \blacktriangle
+ [0x025BC] = 0x4F, -- triangleinv \triangledown
+ [0x02256] = 0x50, -- ringinequal \eqcirc
+ [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr
+ [0x022DB] = 0x52, -- greaterlessequal \gtreqless
+ [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr
+ [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless
+ [0x000A5] = 0x55, -- Yen \yen
+ [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow
+ [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow
+ [0x02713] = 0x58, -- check \checkmark
+ [0x022BB] = 0x59, -- orunderscore \veebar
+ [0x022BC] = 0x5A, -- nand \barwedge
+ [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge
+ [0x02220] = 0x5C, -- angle \angle
+ [0x02221] = 0x5D, -- measuredangle \measuredangle
+ [0x02222] = 0x5E, -- sphericalangle \sphericalangle
+ -- [0x0] = 0x5F, -- proportional \varpropto
+ -- [0x0] = 0x60, -- smile \smallsmile
+ -- [0x0] = 0x61, -- frown \smallfrown
+ [0x022D0] = 0x62, -- subsetdbl \Subset
+ [0x022D1] = 0x63, -- supersetdbl \Supset
+ [0x022D3] = 0x64, -- uniondbl \doublecup \Cup
+ [0x00100] = 0x65, -- intersectiondbl \doublecap \Cap
+ [0x022CF] = 0x66, -- uprise \curlywedge
+ [0x022CE] = 0x67, -- downfall \curlyvee
+ [0x022CB] = 0x68, -- multiopenleft \leftthreetimes
+ [0x022CC] = 0x69, -- multiopenright \rightthreetimes
+ [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq
+ [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq
+ [0x0224F] = 0x6C, -- difference \bumpeq
+ [0x0224E] = 0x6D, -- geomequivalent \Bumpeq
+ [0x022D8] = 0x6E, -- muchless \lll \llless
+ [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr
+ [0x0231C] = 0x70, -- rightanglenw \ulcorner
+ [0x0231D] = 0x71, -- rightanglene \urcorner
+ [0x024C7] = 0x72, -- circleR \circledR
+ [0x024C8] = 0x73, -- circleS \circledS
+ [0x022D4] = 0x74, -- fork \pitchfork
+ [0x02245] = 0x75, -- dotplus \dotplus
+ [0x0223D] = 0x76, -- revsimilar \backsim
+ [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq.
+ [0x0231E] = 0x78, -- rightanglesw \llcorner
+ [0x0231F] = 0x79, -- rightanglese \lrcorner
+ [0x02720] = 0x7A, -- maltesecross \maltese
+ [0x02201] = 0x7B, -- complement \complement
+ [0x022BA] = 0x7C, -- intercal \intercal
+ [0x0229A] = 0x7D, -- circlering \circledcirc
+ [0x0229B] = 0x7E, -- circleasterisk \circledast
+ [0x0229D] = 0x7F, -- circleminus \circleddash
+}
+
+fonts.enc.math["tex-mb"] = {
+ -- [0x0] = 0x00, -- lessornotequal \lvertneqq
+ -- [0x0] = 0x01, -- greaterornotequal \gvertneqq
+ [0x02270] = 0x02, -- notlessequal \nleq
+ [0x02271] = 0x03, -- notgreaterequal \ngeq
+ [0x0226E] = 0x04, -- notless \nless
+ [0x0226F] = 0x05, -- notgreater \ngtr
+ [0x02280] = 0x06, -- notprecedes \nprec
+ [0x02281] = 0x07, -- notfollows \nsucc
+ [0x02268] = 0x08, -- lessornotdbleql \lneqq
+ [0x02269] = 0x09, -- greaterornotdbleql \gneqq
+ -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant
+ -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant
+ [0x02A87] = 0x0C, -- lessnotequal \lneq
+ [0x02A88] = 0x0D, -- greaternotequal \gneq
+ -- [0x0] = 0x0E, -- notprecedesoreql \npreceq
+ -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq
+ [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim
+ [0x022E9] = 0x11, -- followornoteqvlnt \succnsim
+ [0x022E6] = 0x12, -- lessornotsimilar \lnsim
+ [0x022E7] = 0x13, -- greaterornotsimilar \gnsim
+ -- [0x0] = 0x14, -- notlessdblequal \nleqq
+ -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq
+ [0x02AB5] = 0x16, -- precedenotslnteql \precneqq
+ [0x02AB6] = 0x17, -- follownotslnteql \succneqq
+ [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox
+ [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox
+ [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox
+ [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox
+ [0x02241] = 0x1C, -- notsimilar \nsim
+ [0x02247] = 0x1D, -- notapproxequal \ncong
+ -- [0x0] = 0x1E, -- upslope \diagup
+ -- [0x0] = 0x1F, -- downslope \diagdown
+ -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq
+ -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq
+ -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq
+ -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq
+ [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq
+ [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq
+ -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq
+ -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq
+ [0x0228A] = 0x28, -- subsetnoteql \subsetneq
+ [0x0228B] = 0x29, -- supersetnoteql \supsetneq
+ [0x02288] = 0x2A, -- notsubseteql \nsubseteq
+ [0x02289] = 0x2B, -- notsuperseteql \nsupseteq
+ [0x02226] = 0x2C, -- notparallel \nparallel
+ [0x02224] = 0x2D, -- notbar \nmid \ndivides
+ -- [0x0] = 0x2E, -- notshortbar \nshortmid
+ -- [0x0] = 0x2F, -- notshortparallel \nshortparallel
+ [0x022AC] = 0x30, -- notturnstile \nvdash
+ [0x022AE] = 0x31, -- notforces \nVdash
+ [0x022AD] = 0x32, -- notsatisfies \nvDash
+ [0x022AF] = 0x33, -- notforcesextra \nVDash
+ [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq
+ [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq
+ [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft
+ [0x022EB] = 0x37, -- nottriangleright \ntriangleright
+ [0x0219A] = 0x38, -- notarrowleft \nleftarrow
+ [0x0219B] = 0x39, -- notarrowright \nrightarrow
+ [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow
+ [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow
+ [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow
+ [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow
+ [0x022C7] = 0x3E, -- dividemultiply \divideontimes
+ [0x02300] = 0x3F, -- diametersign \varnothing
+ [0x02204] = 0x40, -- notexistential \nexists
+ [0x1D538] = 0x41, -- A (blackboard A)
+ [0x1D539] = 0x42, -- B
+ [0x02102] = 0x43, -- C
+ [0x1D53B] = 0x44, -- D
+ [0x1D53C] = 0x45, -- E
+ [0x1D53D] = 0x46, -- F
+ [0x1D53E] = 0x47, -- G
+ [0x0210D] = 0x48, -- H
+ [0x1D540] = 0x49, -- I
+ [0x1D541] = 0x4A, -- J
+ [0x1D542] = 0x4B, -- K
+ [0x1D543] = 0x4C, -- L
+ [0x1D544] = 0x4D, -- M
+ [0x02115] = 0x4E, -- N
+ [0x1D546] = 0x4F, -- O
+ [0x02119] = 0x50, -- P
+ [0x0211A] = 0x51, -- Q
+ [0x0211D] = 0x52, -- R
+ [0x1D54A] = 0x53, -- S
+ [0x1D54B] = 0x54, -- T
+ [0x1D54C] = 0x55, -- U
+ [0x1D54D] = 0x56, -- V
+ [0x1D54E] = 0x57, -- W
+ [0x1D54F] = 0x58, -- X
+ [0x1D550] = 0x59, -- Y
+ [0x02124] = 0x5A, -- Z (blackboard Z)
+ [0x02132] = 0x60, -- hatwide \Finv
+ [0x02141] = 0x61, -- hatwider \Game
+ -- [0x0] = 0x62, tildewide
+ -- [0x0] = 0x63, tildewider
+ -- [0x0] = 0x64, Finv
+ -- [0x0] = 0x65, Gmir
+ [0x02127] = 0x66, -- Omegainv \mho
+ [0x000F0] = 0x67, -- eth \eth
+ [0x02242] = 0x68, -- equalorsimilar \eqsim
+ [0x02136] = 0x69, -- beth \beth
+ [0x02137] = 0x6A, -- gimel \gimel
+ [0x02138] = 0x6B, -- daleth \daleth
+ [0x022D6] = 0x6C, -- lessdot \lessdot
+ [0x022D7] = 0x6D, -- greaterdot \gtrdot
+ [0x022C9] = 0x6E, -- multicloseleft \ltimes
+ [0x022CA] = 0x6F, -- multicloseright \rtimes
+ -- [0x0] = 0x70, -- barshort \shortmid
+ -- [0x0] = 0x71, -- parallelshort \shortparallel
+ -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy
+ -- [0x0] = 0x73, -- similar \thicksim
+ -- [0x0] = 0x74, -- approxequal \thickapprox
+ [0x0224A] = 0x75, -- approxorequal \approxeq
+ [0x02AB8] = 0x76, -- followsorequal \succapprox
+ [0x02AB7] = 0x77, -- precedesorequal \precapprox
+ [0x021B6] = 0x78, -- archleftdown \curvearrowleft
+ [0x021B7] = 0x79, -- archrightdown \curvearrowright
+ [0x003DC] = 0x7A, -- Digamma \digamma
+ [0x003F0] = 0x7B, -- kappa \varkappa
+ [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k)
+ [0x0210F] = 0x7D, -- planckover2pi \hslash
+ [0x00127] = 0x7E, -- planckover2pi1 \hbar
+ [0x003F6] = 0x7F, -- epsiloninv \backepsilon
+}
+
+fonts.enc.math["tex-fraktur"] = {
+-- [0x1D504] = 0x41, -- A (fraktur A)
+-- [0x1D505] = 0x42, -- B
+ [0x0212D] = 0x43, -- C
+-- [0x1D507] = 0x44, -- D
+-- [0x1D508] = 0x45, -- E
+-- [0x1D509] = 0x46, -- F
+-- [0x1D50A] = 0x47, -- G
+ [0x0210C] = 0x48, -- H
+ [0x02111] = 0x49, -- I
+-- [0x1D50D] = 0x4A, -- J
+-- [0x1D50E] = 0x4B, -- K
+-- [0x1D50F] = 0x4C, -- L
+-- [0x1D510] = 0x4D, -- M
+-- [0x1D511] = 0x4E, -- N
+-- [0x1D512] = 0x4F, -- O
+-- [0x1D513] = 0x50, -- P
+-- [0x1D514] = 0x51, -- Q
+ [0x0211C] = 0x52, -- R
+-- [0x1D516] = 0x53, -- S
+-- [0x1D517] = 0x54, -- T
+-- [0x1D518] = 0x55, -- U
+-- [0x1D519] = 0x56, -- V
+-- [0x1D51A] = 0x57, -- W
+-- [0x1D51B] = 0x58, -- X
+-- [0x1D51C] = 0x59, -- Y
+ [0x02128] = 0x5A, -- Z (fraktur Z)
+-- [0x1D51E] = 0x61, -- a (fraktur a)
+-- [0x1D51F] = 0x62, -- b
+-- [0x1D520] = 0x63, -- c
+-- [0x1D521] = 0x64, -- d
+-- [0x1D522] = 0x65, -- e
+-- [0x1D523] = 0x66, -- f
+-- [0x1D524] = 0x67, -- g
+-- [0x1D525] = 0x68, -- h
+-- [0x1D526] = 0x69, -- i
+-- [0x1D527] = 0x6A, -- j
+-- [0x1D528] = 0x6B, -- k
+-- [0x1D529] = 0x6C, -- l
+-- [0x1D52A] = 0x6D, -- m
+-- [0x1D52B] = 0x6E, -- n
+-- [0x1D52C] = 0x6F, -- o
+-- [0x1D52D] = 0x70, -- p
+-- [0x1D52E] = 0x71, -- q
+-- [0x1D52F] = 0x72, -- r
+-- [0x1D530] = 0x73, -- s
+-- [0x1D531] = 0x74, -- t
+-- [0x1D532] = 0x75, -- u
+-- [0x1D533] = 0x76, -- v
+-- [0x1D534] = 0x77, -- w
+-- [0x1D535] = 0x78, -- x
+-- [0x1D536] = 0x79, -- y
+-- [0x1D537] = 0x7A, -- z
+}
+
+-- now that all other vectors are defined ...
+
+fonts.vf.math.set_letters(fonts.enc.math, "tex-it", 0x1D434, 0x1D44E)
+fonts.vf.math.set_letters(fonts.enc.math, "tex-ss", 0x1D5A0, 0x1D5BA)
+fonts.vf.math.set_letters(fonts.enc.math, "tex-tt", 0x1D670, 0x1D68A)
+fonts.vf.math.set_letters(fonts.enc.math, "tex-bf", 0x1D400, 0x1D41A)
+fonts.vf.math.set_letters(fonts.enc.math, "tex-bi", 0x1D468, 0x1D482)
+fonts.vf.math.set_letters(fonts.enc.math, "tex-fraktur", 0x1D504, 0x1D51E)
+fonts.vf.math.set_letters(fonts.enc.math, "tex-fraktur-bold", 0x1D56C, 0x1D586)
+
+fonts.vf.math.set_digits (fonts.enc.math, "tex-ss", 0x1D7E2)
+fonts.vf.math.set_digits (fonts.enc.math, "tex-tt", 0x1D7F6)
+fonts.vf.math.set_digits (fonts.enc.math, "tex-bf", 0x1D7CE)
+
+-- fonts.vf.math.set_digits (fonts.enc.math, "tex-bi", 0x1D7CE)
+
+-- todo: add ss, tt, bf etc vectors
+-- todo: we can make ss tt etc an option
diff --git a/tex/context/base/meta-clp.tex b/tex/context/base/meta-clp.tex
new file mode 100644
index 000000000..be2506b19
--- /dev/null
+++ b/tex/context/base/meta-clp.tex
@@ -0,0 +1,164 @@
+%D \module
+%D [ file=meta-clp,
+%D version=2000.07.06,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Clipping,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 In this library, we define a bunch of clipping paths that
+%D can be fed to \type {\clip}.
+
+\startMPclip{ellipse}
+ clip currentpicture to unitcircle
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{negellipse}
+ clip currentpicture to (unitcircle peepholed unitsquare)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{urellipse}
+ clip currentpicture to urcircle scaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{ulellipse}
+ clip currentpicture to ulcircle scaled 2 shifted (1,0)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{llellipse}
+ clip currentpicture to llcircle scaled 2 shifted (1,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lrellipse}
+ clip currentpicture to lrcircle scaled 2 shifted (0,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{tellipse}
+ clip currentpicture to tcircle shifted (.5,0) yscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{bellipse}
+ clip currentpicture to bcircle shifted (.5,.5) yscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lellipse}
+ clip currentpicture to lcircle shifted (.5,.5) xscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{rellipse}
+ clip currentpicture to rcircle shifted (0,.5) xscaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{diamond}
+ clip currentpicture to unitdiamond
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{negdiamond}
+ clip currentpicture to (unitdiamond peepholed unitsquare)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{urtriangle}
+ clip currentpicture to urtriangle scaled 2
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{ultriangle}
+ clip currentpicture to ultriangle scaled 2 shifted (1,0)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lltriangle}
+ clip currentpicture to lltriangle scaled 2 shifted (1,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+\startMPclip{lrtriangle}
+ clip currentpicture to lrtriangle scaled 2 shifted (0,1)
+ xscaled \width yscaled \height ;
+\stopMPclip
+
+% More efficient:
+%
+% \def\dosimpleMPclip#1
+% {clip currentpicture to (#1) xscaled \width yscaled \height ;}
+%
+% \def\simpleMPclip#1#2%
+% {\startMPclip{#1}\dosimpleMPclip{#2}\stopMPclip}
+%
+% \simpleMPclip {ellipse} {unitcircle}
+% \simpleMPclip {diamond} {unitdiamond}
+%
+% \simpleMPclip {negellipse} {unitcircle peepholed unitsquare}
+% \simpleMPclip {negdiamond} {unitdiamond peepholed unitsquare}
+%
+% \simpleMPclip {urellipse} {urcircle scaled 2 shifted (0,0)}
+% \simpleMPclip {ulellipse} {ulcircle scaled 2 shifted (1,0)}
+% \simpleMPclip {llellipse} {llcircle scaled 2 shifted (1,1)}
+% \simpleMPclip {lrellipse} {lrcircle scaled 2 shifted (0,1)}
+%
+% \simpleMPclip {tellipse} {tcircle shifted (.5,0) yscaled 2}
+% \simpleMPclip {bellipse} {bcircle shifted (.5,.5) yscaled 2}
+% \simpleMPclip {lellipse} {lcircle shifted (.5,.5) xscaled 2}
+% \simpleMPclip {rellipse} {rcircle shifted (0,.5) xscaled 2}
+%
+% \simpleMPclip {urtriangle} {urtriangle scaled 2 shifted (0,0)}
+% \simpleMPclip {ultriangle} {ultriangle scaled 2 shifted (1,0)}
+% \simpleMPclip {lltriangle} {lltriangle scaled 2 shifted (1,1)}
+% \simpleMPclip {lrtriangle} {lrtriangle scaled 2 shifted (0,1)}
+
+%D \in {Figure} [fig:clipping paths] shows which paths are
+%D predefined. When applied to a whole picture, their usage
+%D is:
+%D
+%D \starttyping
+%D \clip[nx=1,ny=1,mp=ellipse]{some clippable content}
+%D \stoptyping
+%D
+%D \startbuffer
+%D \setupclipping [nx=1,ny=1,x=1,y=1]
+%D \setupblackrules[width=2cm,height=1cm]
+%D \startcombination[6*3] % \startcombination[6*3]
+%D {\clip[mp=urellipse] {\blackrule}} {urellipse}
+%D {\clip[mp=ulellipse] {\blackrule}} {ulellipse}
+%D {\clip[mp=llellipse] {\blackrule}} {llellipse}
+%D {\clip[mp=lrellipse] {\blackrule}} {lrellipse}
+%D {\clip[mp=ellipse] {\blackrule}} {ellipse}
+%D {\clip[mp=negellipse]{\blackrule}} {negellipse}
+%D {\clip[mp=tellipse] {\blackrule}} {tellipse}
+%D {\clip[mp=bellipse] {\blackrule}} {bellipse}
+%D {\clip[mp=lellipse] {\blackrule}} {lellipse}
+%D {\clip[mp=rellipse] {\blackrule}} {rellipse}
+%D {} {}
+%D {} {}
+%D {\clip[mp=urtriangle]{\blackrule}} {urtriangle}
+%D {\clip[mp=ultriangle]{\blackrule}} {ultriangle}
+%D {\clip[mp=lltriangle]{\blackrule}} {lltriangle}
+%D {\clip[mp=lrtriangle]{\blackrule}} {lrtriangle}
+%D {\clip[mp=diamond] {\blackrule}} {diamond}
+%D {\clip[mp=negdiamond]{\blackrule}} {negdiamond}
+%D \stopcombination % \stopcombination
+%D \stopbuffer
+%D
+%D \placefigure % \placefigure
+%D [here][fig:clipping paths]
+%D {The predefined clipping paths.}
+%D {\getbuffer} % {\getbuffer}
+
+\endinput
diff --git a/tex/context/base/meta-dum.tex b/tex/context/base/meta-dum.tex
new file mode 100644
index 000000000..bc19f3c5f
--- /dev/null
+++ b/tex/context/base/meta-dum.tex
@@ -0,0 +1,123 @@
+%D \module
+%D [ file=meta-dum,
+%D version=2003.03.21,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Dummy (External) Graphics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+%D This library overloads the normal external figure
+%D placeholder by a nicer one.
+%D
+%D \startbuffer
+%D \useMPlibrary[dum]
+%D
+%D \startlinecorrection
+%D \externalfigure[unknown-a][width=3cm,height=1cm]
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \externalfigure[unknown-b][width=4cm,height=5cm]
+%D \stoplinecorrection
+%D \stopbuffer
+%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
+
+\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
+
+\definepalet
+ [placeholder]
+ [1=red,2=green,3=blue,4=cyan,5=magenta,6=yellow]
+
+% \newcounter \figurereplacementcycle
+
+\let\figurereplacementcycle\relax
+
+\setupexternalfigures
+ [\c!reduction=0,
+ \c!text=\v!yes]
+
+\let\normalexternalfigurereplacement\externalfigurereplacement
+
+\def\externalfigurereplacement#1#2#3%
+ {\getpaletsize[placeholder]%
+ \ifx\figurereplacementcycle\relax
+ \getrandomnumber \figurereplacementcycle \!!plusone \paletsize
+ \globallet \figurereplacementcycle \figurereplacementcycle
+ \else
+ \doglobal\increment\figurereplacementcycle
+ \fi
+ \ifnum\figurereplacementcycle>\paletsize
+ \globallet\figurereplacementcycle\!!plusone
+ \fi
+ \weightGRAYfalse % monochrome anyway
+ \MPcmykcolorsfalse
+ \MPspotcolorsfalse
+ \defineoverlay
+ [\s!dummy]
+ [\useMPgraphic
+ {placeholder}%
+ {width=\figurewidth,
+ height=\figureheight,
+ reduction=\@@efreduction,
+ color=placeholder:\figurereplacementcycle}]%
+ \expanded{\localframed
+ [\??ef]
+ [\c!width=\figurewidth,
+ \c!height=\figureheight,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!background=\s!dummy,
+ \c!foregroundcolor=\s!white]}%
+ {\doif\@@eftext\v!yes
+ {\infofont \setupinterlinespace \dohyphens % \nohyphens
+ \doifelse{#1}\s!dummy \!!doneafalse\!!doneatrue
+ \doifelse{#2}\s!dummy \!!donebfalse\!!donebtrue
+ \doifelse{#3}\s!unknown\!!donecfalse\!!donectrue
+ \if!!donea
+ name: \expanded{\verbatimstring{#1}}\strut\endgraf
+ \fi
+ \if!!doneb
+ \if!!donea file: \else \if!!donec file: \fi \fi
+ \expanded{\verbatimstring{#2}}\strut\endgraf
+ \fi
+ \if!!donec
+ state: \expanded{\verbatimstring{#3}}\strut\endgraf
+ \fi}}}
+
+\def\dummyfigure{\externalfigure[placeholder]}
+
+\protect \endinput
diff --git a/tex/context/base/meta-fig.mkii b/tex/context/base/meta-fig.mkii
new file mode 100644
index 000000000..3edd73b57
--- /dev/null
+++ b/tex/context/base/meta-fig.mkii
@@ -0,0 +1,89 @@
+%D \module
+%D [ file=meta-fig,
+%D version=2000.09.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Stand Alone Graphics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphics / Stand Alone Graphics}
+
+\unprotect
+
+%D This module implements a method for defining
+%D stand||alone||graphics, that is, each graphic gets is own
+%D page. Because graphics are wrapped in a \type {\framed},
+%D you can add overlays to the graphic directly, and since the
+%D whole \CONTEXT\ machinery is available, you can also add
+%D page backgrounds.
+%D
+%D \starttyping
+%D \setupMPpage
+%D [offset=1pt,
+%D background=color,
+%D backgroundcolor=green]
+%D
+%D \startMPpage
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopMPpage
+%D
+%D \startMPpage
+%D fill fullsquare rotated 45 scaled 8cm withcolor blue ;
+%D \stopMPpage
+%D \stoptyping
+%D
+%D Although this is hardly of any use, you can mix these
+%D definitions with the text flow, since all settings are
+%D kept local. The page is clipped to the image size.
+
+\presetlocalframed[\??mg]
+
+\def\setupMPpage
+ {\dodoubleargument\getparameters[\??mg]}
+
+\def\startMPpage
+ {\dodoubleempty\dostartMPpage}
+
+\long\def\dostartMPpage[#1][#2]% second arg gobbles space
+ {\dostartfittingpage[\??mg][#1]%
+ \obeyMPlines
+ \dodostartMPpage}
+
+\long\def\dodostartMPpage#1\stopMPpage
+ {\startuseMPgraphic{@@}#1\stopuseMPgraphic
+ \useMPgraphic{@@}%
+ \dostopfittingpage}
+
+\let\stopMPpage \relax % so that we can use it in \expanded
+
+\setupMPpage
+ [\c!scale=1000,
+ \c!strut=\v!no,
+ \c!align=,
+ \c!offset=\v!overlay,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!frame=\v!off]
+
+%D \macros
+%D {MPfigure}
+%D
+%D A bit out of place, here but nevertheless:
+
+\def\MPfigure#1#2% test for dup figure
+ {\bgroup
+ \getfiguredimensionsonly[#1]% [\c!object=\v!no] already set
+ \startMPcode
+ externalfigure "#1"
+ xscaled \figurewidth\space
+ yscaled \figureheight\space
+ #2 ;
+ \stopMPcode
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/meta-fig.mkiv b/tex/context/base/meta-fig.mkiv
new file mode 100644
index 000000000..4738316da
--- /dev/null
+++ b/tex/context/base/meta-fig.mkiv
@@ -0,0 +1,84 @@
+%D \module
+%D [ file=meta-fig,
+%D version=2000.09.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Stand Alone Graphics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphics / Stand Alone Graphics}
+
+\unprotect
+
+%D This module implements a method for defining
+%D stand||alone||graphics, that is, each graphic gets is own
+%D page. Because graphics are wrapped in a \type {\framed},
+%D you can add overlays to the graphic directly, and since the
+%D whole \CONTEXT\ machinery is available, you can also add
+%D page backgrounds.
+%D
+%D \starttyping
+%D \setupMPpage
+%D [offset=1pt,
+%D background=color,
+%D backgroundcolor=green]
+%D
+%D \startMPpage
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopMPpage
+%D
+%D \startMPpage
+%D fill fullsquare rotated 45 scaled 8cm withcolor blue ;
+%D \stopMPpage
+%D \stoptyping
+%D
+%D Although this is hardly of any use, you can mix these
+%D definitions with the text flow, since all settings are
+%D kept local. The page is clipped to the image size.
+
+\presetlocalframed[\??mg]
+
+\unexpanded\def\setupMPpage
+ {\dodoubleargument\getparameters[\??mg]}
+
+\def\startMPpage
+ {\dodoubleempty\dostartMPpage}
+
+\long\def\dostartMPpage[#1][#2]#3\stopMPpage % second arg gobbles space
+ {\dostartfittingpage[\??mg][#1]%
+ \processMPgraphic{#3}%
+ \dostopfittingpage}
+
+\let\stopMPpage \relax % so that we can use it in \expanded
+
+\setupMPpage
+ [\c!scale=1000,
+ \c!strut=\v!no,
+ \c!align=,
+ \c!offset=\v!overlay,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!frame=\v!off]
+
+%D \macros
+%D {MPfigure}
+%D
+%D A bit out of place, here but nevertheless:
+
+\def\MPfigure#1#2% test for dup figure, can be replaced by a textext
+ {\bgroup
+ \getfiguredimensionsonly[#1]% [\c!object=\v!no] already set
+ \startMPcode
+ externalfigure "#1"
+ xscaled \the\dimexpr\figurewidth \relax\space % must be points
+ yscaled \the\dimexpr\figureheight\relax\space % must be points
+ #2 ;
+ \stopMPcode
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/meta-fun.lua b/tex/context/base/meta-fun.lua
new file mode 100644
index 000000000..fef2aa12b
--- /dev/null
+++ b/tex/context/base/meta-fun.lua
@@ -0,0 +1,55 @@
+if not modules then modules = { } end modules ['meta-fun'] = {
+ version = 1.001,
+ comment = "companion to meta-fun.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- very experimental, actually a joke ... see metafun manual for usage
+
+local format, loadstring, type = string.format, loadstring, type
+local texwrite = tex.write
+
+metafun = metafun or { }
+
+function metafun.topath(t,connector)
+ tex.write("(")
+ if #t > 0 then
+ for i=1,#t do
+ if i > 1 then
+ texwrite(connector or "..")
+ end
+ local ti = t[i]
+ if type(ti) == "string" then
+ texwrite(ti)
+ else
+ texwrite(format("(%s,%s)",ti.x or ti[1] or 0,ti.y or ti[2] or 0))
+ end
+ end
+ else
+ texwrite("origin")
+ end
+ texwrite(")")
+end
+
+function metafun.interpolate(f,b,e,s,c)
+ local done = false
+ tex.write("(")
+ for i=b,e,(e-b)/s do
+ local d = loadstring(format("return function(x) return %s end",f))
+ if d then
+ d = d()
+ if done then
+ texwrite(c or "...")
+ else
+ done = true
+ end
+ texwrite(format("(%s,%s)",i,d(i)))
+ end
+ end
+ if not done then
+ texwrite("origin")
+ end
+ texwrite(")")
+end
diff --git a/tex/context/base/meta-fun.mkiv b/tex/context/base/meta-fun.mkiv
new file mode 100644
index 000000000..a43ffefff
--- /dev/null
+++ b/tex/context/base/meta-fun.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=meta-fun,
+%D version=2009.06.02,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Goodies,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Graphics / Goodies}
+
+\registerctxluafile{meta-fun}{1.001}
+
+\unprotect
+
+\protect \endinput
diff --git a/tex/context/base/meta-ini.mkii b/tex/context/base/meta-ini.mkii
new file mode 100644
index 000000000..e7c6d218e
--- /dev/null
+++ b/tex/context/base/meta-ini.mkii
@@ -0,0 +1,1054 @@
+%D \module
+%D [ file=meta-ini,
+%D version=1999.07.10,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% currently the running color influences the mp graphic in
+% pdftex, but this will change [i.e. become optional]; one
+% problem is that pdf has no grouping with regards to the
+% color
+
+\writestatus{loading}{MetaPost Graphics / Initializations}
+
+\unprotect
+
+%D This module extends the functionality of the support module
+%D \type {supp-mps}, the module that is responsible for
+%D \METAPOST\ inclusion in \CONTEXT. Some basic macros will be
+%D extended. Since some support is depends on \METAPOST\
+%D macros. so let's first preload a few auxiliary \METAPOST\
+%D files.
+
+\maxnofMPgraphics = 4000 % metafun disables the 4K boundary
+
+\appendtoks \flushMPgraphics \to \everygoodbye % \everylastshipout
+
+\def\@@MPG{@MPG@}
+
+\startMPextensions
+ if unknown context_tool: input mp-tool; fi;
+ if unknown context_spec: input mp-spec; fi;
+ if unknown context_grph: input mp-grph; fi;
+\stopMPextensions
+
+%D Since we want lables to follow the document settings, we
+%D also set the font related variables.
+
+\ifnum\texengine=\xetexengine
+ \startMPinitializations % scale is not yet ok
+ defaultfont:="rm-lmtt10";
+ defaultscale:=\the\bodyfontsize/10pt;
+ \stopMPinitializations
+\else
+ \startMPinitializations % scale is not yet ok
+ defaultfont:="\truefontname{Regular}";
+ defaultscale:=\the\bodyfontsize/10pt;
+ \stopMPinitializations
+\fi
+
+%D In order to support fancy text features (like outline
+%D fonts), we set:
+
+\startMPextensions
+ graphictextformat:="context";
+ graphictextdirective "\the\everyMPTEXgraphic";
+\stopMPextensions
+
+% \startMPextensions
+% textextdirective "\the\everyMPTEXgraphic";
+% \stopMPextensions
+
+%D A signal that we're in combines \CONTEXT||\METAFUN mode:
+
+\startMPextensions
+ string contextversion;
+ contextversion:="\contextversion";
+\stopMPextensions
+
+%D Some safeguards:
+%D
+%D \starttyping
+%D \appendtoks \cleanupfeatures \to \everyMPgraphic
+%D \stoptyping
+%D
+%D No, we don't want that (else we loose UTF etc).
+
+%D Another one:
+
+\prependtoks \MPstaticgraphictrue \to \everyoverlay
+\prependtoks \MPstaticgraphictrue \to \everypagebody
+
+%D We save the number of graphics for the sake of \TEXEXEC.
+
+\newcounter\totalnofMPgraphics
+
+\def\thenofMPgraphics{\the\nofMPgraphics} % from supp-mps
+
+\appendtoks
+ \savecurrentvalue\totalnofMPgraphics\thenofMPgraphics
+\to \everybye
+
+%D \macros
+%D {setupMPvariables}
+%D
+%D When we build collections of \METAPOST\ graphics, like
+%D background and buttons, the need for passing settings
+%D arises. By (mis|)|using the local prefix that belongs to
+%D \type {\framed}, we get a rather natural interface to
+%D backgrounds. To prevent conflicts, we will use the \type
+%D {-} in \METAPOST\ specific variables, like:
+%D
+%D \starttyping
+%D \setupMPvariables[meta:button][size=20pt]
+%D \stoptyping
+
+\def\@@meta{meta:}
+
+\def\setupMPvariables
+ {\dodoubleempty\dosetupMPvariables}
+
+\def\dosetupMPvariables[#1][#2]%
+ {\ifsecondargument
+ \getrawparameters[#1:][#2]% brr, todo: [\@@meta#1:]
+ \else
+ \getrawparameters[\@@meta][#1]%
+ \fi}
+
+\let\@@framed\s!unknown
+
+\def\MPvariable#1%
+ {\csname
+ \ifcsname\@@framed\@@meta#1\endcsname\@@framed\fi\@@meta#1%
+ \endcsname}
+
+\let\MPvar\MPvariable
+
+\let\setMPvariables\setupMPvariables
+
+\def\MPrawvar#1#2{\csname#1:#2\endcsname}
+
+\def\presetMPvariable
+ {\dodoubleargument\dopresetMPvariable}
+
+\def\dopresetMPvariable[#1][#2=#3]%
+ {\doifundefined{#1:#2}{\setvalue{#1:#2}{#3}}}
+
+\def\useMPvariables
+ {\dodoubleargument\douseMPvariables}
+
+\def\douseMPvariables[#1][#2]%
+ {\def\@@meta{#1:}%
+ \prepareMPvariables{#2}}
+
+%D \macros
+%D {startuniqueMPgraphic, uniqueMPgraphic}
+%D
+%D This macros is probably of most use to myself, since I like
+%D to use graphics that adapt themselves. The next \METAPOST\
+%D kind of graphic is both unique and reused when possible.
+%D
+%D \starttyping
+%D \defineoverlay[example][\uniqueMPgraphic{test}]
+%D
+%D \startuniqueMPgraphic {test}
+%D draw unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D \stopuniqueMPgraphic
+%D \stoptyping
+
+%D For educational purposes, we show the original version
+%D first. This one used a rather simple method for determining
+%D the uniqueness.
+%D
+%D \starttyping
+%D \long\def\startuniqueMPgraphic#1#2\stopuniqueMPgraphic%
+%D {\setvalue{\@@MPG#1}%
+%D {\startreusableMPgraphic{\overlaystamp:#1}#2\stopreusableMPgraphic
+%D \reuseMPgraphic{\overlaystamp:#1}}}
+%D
+%D \def\uniqueMPgraphic#1%
+%D {\getvalue{\@@MPG#1}}
+%D \stoptyping
+
+%\def\overlaystamp % watch the \MPcolor, since colors can be redefined
+% {\overlaywidth:\overlayheight:\overlaydepth
+% :\MPcolor{\overlaycolor}:\MPcolor{\overlaylinecolor}}
+
+\def\overlaystamp % watch the \MPcolor, since colors can be redefined
+ {\overlaywidth:\overlayheight:\overlaydepth
+ :\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+%D A better approach is to let additional variables play a role
+%D in determining the uniqueness. In the next macro, the
+%D second, optional, argument is used to guarantee the
+%D uniqueness, as well as prepare variables for passing them to
+%D \METAPOST.
+%D
+%D \starttyping
+%D \startuniqueMPgraphic{meta:hash}{gap,angle,...}
+%D \stoptyping
+%D
+%D The calling macro also accepts a second argument. For
+%D convenient use in overlay definitions, we use \type {{}}
+%D instead of \type {[]}.
+%D
+%D \starttyping
+%D \uniqueMPgraphic{meta:hash}{gap=10pt,angle=30}
+%D \stoptyping
+
+\long\def\handleuniqueMPgraphic#1#2#3%
+ {\blabelgroup
+ \def\@@meta{#1:}%
+ \extendMPoverlaystamp{#2}% incl prepare
+ \ifundefined{\@@MPG\overlaystamp:#1}%
+ \enableincludeMPgraphics
+ \startMPgraphic#3\stopMPgraphic
+ \doifobjectssupportedelse\donothing\useMPboxfalse
+ \ifuseMPbox
+ \@EA\douseMPbox
+ \else
+ \@EA\nouseMPbox
+ \fi {\@@MPG\overlaystamp:#1}%
+ \fi
+ \getvalue{\@@MPG\overlaystamp:#1}%
+ \elabelgroup}
+
+\long\def\startuniqueMPgraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartuniqueMPgraphic}
+
+\long\def\dostartuniqueMPgraphic
+ {\obeyMPlines
+ \dodostartuniqueMPgraphic}
+
+\long\def\dodostartuniqueMPgraphic#1#2#3\stopuniqueMPgraphic%
+ {\long\setgvalue{\@@MPG#1}{\handleuniqueMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\unexpanded\def\uniqueMPgraphic
+ {\dodoublegroupempty\douniqueMPgraphic}
+
+\def\douniqueMPgraphic#1#2%
+ {\blabelgroup
+ \setupMPvariables[#1][#2]%
+ \getvalue{\@@MPG#1}{}%
+ \elabelgroup}
+
+\let\stopuniqueMPcode \relax % so that we can use it in \expanded
+
+\def\includeMPgraphic#1%
+ {\executeifdefined{\@@MPG#1};} % ; if not found
+
+\long\def\handleuseMPgraphic#1#2#3%
+ {\blabelgroup
+ \def\@@meta{#1:}%
+ \prepareMPvariables{#2}%
+ \enableincludeMPgraphics
+ \startMPgraphic#3\stopMPgraphic
+ \ifMPrun \else % see mfun-004 : processing buffer
+ \loadMPgraphic{\MPgraphicfile.\the\currentMPgraphic}{}%
+ \placeMPgraphic
+ \fi
+ \deallocateMPslot\currentMPgraphic
+ \elabelgroup}
+
+\long\def\startuseMPgraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartuseMPgraphic}
+
+\long\def\dostartuseMPgraphic
+ {\obeyMPlines
+ \dodostartuseMPgraphic}
+
+\long\def\dodostartuseMPgraphic#1#2#3\stopuseMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\long\def\startusableMPgraphic % redundant but handy
+ {\blabelgroup
+ \dodoublegroupempty\dostartusableMPgraphic}
+
+\long\def\dostartusableMPgraphic % redundant but handy
+ {\obeyMPlines
+ \dodostartusableMPgraphic}
+
+\long\def\dodostartusableMPgraphic#1#2#3\stopusableMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\long\def\handlereusableMPgraphic#1#2#3%
+ {\blabelgroup
+ \def\@@meta{#1:}%
+ \prepareMPvariables{#2}%
+ \enableincludeMPgraphics
+ \startMPgraphic#3\stopMPgraphic
+ \doifobjectssupportedelse\donothing\useMPboxfalse
+ \ifuseMPbox
+ \@EA\douseMPbox
+ \else
+ \@EA\nouseMPbox
+ \fi {\@@MPG#1}%
+ \getvalue{\@@MPG#1}%
+ \elabelgroup}
+
+\long\def\startreusableMPgraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartreusableMPgraphic}
+
+\def\dostartreusableMPgraphic
+ {\obeyMPlines
+ \dodostartreusableMPgraphic}
+
+\long\def\dodostartreusableMPgraphic#1#2#3\stopreusableMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}{#3}}%
+ \elabelgroup}
+
+\unexpanded\def\useMPgraphic
+ {\dodoublegroupempty\douseMPgraphic}
+
+\def\douseMPgraphic#1#2%
+ {\blabelgroup
+ \setupMPvariables[#1][#2]%
+ \getvalue{\@@MPG#1}{}%
+ \elabelgroup}
+
+\let\reuseMPgraphic\useMPgraphic
+
+\let\stopuseMPcode \relax % so that we can use it in \expanded
+\let\stopusableMPcode \relax % so that we can use it in \expanded
+\let\stopreusableMPcode \relax % so that we can use it in \expanded
+\let\stopuniqueMPcode \relax % so that we can use it in \expanded
+
+\def\enableincludeMPgraphics
+ {\let\handleuseMPgraphic \thirdofthreearguments
+ \let\handlereusableMPgraphic\thirdofthreearguments}
+
+% todo: each code/page/buffer a var class
+
+%D \macros
+%D {startuniqueMPpagegraphic,uniqueMPpagegraphic}
+%D
+%D Experimental.
+
+\def\MPpageprefix{\doifoddpageelse oe:}
+
+\def\overlaypagestamp
+ {\MPpageprefix\overlaywidth:\overlayheight:\overlaydepth
+ :\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+\long\def\startuniqueMPpagegraphic
+ {\blabelgroup
+ \dodoublegroupempty\dostartuniqueMPpagegraphic}
+
+\long\def\dostartuniqueMPpagegraphic
+ {\obeyMPlines
+ \dodostartuniqueMPpagegraphic}
+
+\long\def\dodostartuniqueMPpagegraphic#1#2#3\stopuniqueMPpagegraphic
+ {\long\setgvalue{\@@MPG o:#1}{\handleuniqueMPgraphic{o:#1}{#2}{#3}}%
+ \long\setgvalue{\@@MPG e:#1}{\handleuniqueMPgraphic{e:#1}{#2}{#3}}%
+ \elabelgroup}
+
+\unexpanded\def\uniqueMPpagegraphic
+ {\dodoublegroupempty\douniqueMPpagegraphic}
+
+% \def\douniqueMPpagegraphic#1#2%
+% {\blabelgroup
+% \let\overlaystamp\overlaypagestamp
+% \setupMPvariables[#1][#2]%
+% \getvalue{\@@MPG\MPpageprefix#1}{}%
+% \elabelgroup}
+
+\def\douniqueMPpagegraphic#1#2%
+ {\blabelgroup
+ \let\overlaystamp\overlaypagestamp
+ \setupMPvariables[\MPpageprefix#1][#2]% prefix is new here
+ \getvalue{\@@MPG\MPpageprefix#1}{}%
+ \elabelgroup}
+
+%D One way of defining a stamp is:
+%D
+%D \starttyping
+%D \def\extendMPoverlaystamp#1%
+%D {\def\docommand##1%
+%D {\edef\overlaystamp{\overlaystamp:\MPvariable{##1}}}%
+%D \processcommalist[#1]\docommand}
+%D \stoptyping
+
+%D Since we need to feed \METAPOST\ with expanded dimensions,
+%D we introduce a dedicated expansion engine.
+
+\def\prepareMPvariable#1%
+ {\ifundefined{\@@framed\@@meta#1}%
+ \doprepareMPvariable{\@@meta#1}%
+ \else
+ \doprepareMPvariable{\@@framed\@@meta#1}%
+ \fi}
+
+% \startlines
+% \def\xxx{\lineheight} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2pt} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{\scratchcounter} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{red} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{0.4} \doprepareMPvariable{xxx} \xxx
+% \stoplines
+
+\def\doprepareMPvariable#1%
+ {\edef\theMPvariable{\getvalue{#1}}%
+ \doifelsenothing\theMPvariable
+ {\setevalue{#1}{\MPcolor{black}}}
+ {\defconvertedcommand\ascii\theMPvariable % otherwise problems
+ \doifcolorelse \ascii % with 2\bodyfontsize
+ {\setevalue{#1}{\MPcolor\theMPvariable}}
+ {% can be aux macro
+ \setbox\scratchbox\hbox{\scratchdimen\theMPvariable sp}%
+ \ifdim\wd\scratchbox=\zeropoint
+ % \scratchcounter\theMPvariable
+ % \setevalue{#1}{\the\scratchcounter}%
+ % also accepts 0.number :
+ \setevalue{#1}{\number\theMPvariable}%
+ \else
+ \scratchdimen\theMPvariable
+ \setevalue{#1}{\the\scratchdimen}%
+ \fi}}}
+
+%D We redefine \type {\extendMPoverlaystamp} to preprocess
+%D variables using \type {\prepareMPvariable}.
+
+\def\doextendMPoverlaystamp#1%
+ {\prepareMPvariable{#1}%
+ \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
+
+\def\extendMPoverlaystamp#1%
+ {\processcommalist[#1]\doextendMPoverlaystamp}
+
+\def\prepareMPvariables#1%
+ {\processcommalist[#1]\prepareMPvariable}
+
+%D \macros
+%D {MPdatafile}
+%D
+%D We redefine a macro from \type {supp-mps.tex}:
+
+\def\MPdatafile
+ {\bufferprefix mpd-\the\currentMPgraphic.mpd}
+
+%D \macros
+%D {MPrunfile}
+%D
+%D This one is more abstract and does not assume knowledge
+%D of buffer prefixes.
+
+\def\MPrunfile#1%
+ {\bufferprefix mprun.#1}
+
+%D \macros
+%D {getMPdata}
+%D
+%D When we collect graphics in one file, we run into
+%D troubles, since \METAPOST\ has a built in limit (of 4)
+%D on the number of files it can handle. It's therefore
+%D better to collect all data in one file and filter it.
+
+\def\MPdataMPDfile{\jobname-mpgraph.mpd}
+\def\MPdataMPOfile{\jobname-mpgraph.mpo}
+\def\MPdataMPYfile{\jobname-mpgraph.mpy}
+
+\startMPextensions
+ boolean collapse_data; collapse_data:=true;
+ def data_mpd_file = "\MPdataMPDfile" enddef ;
+ def data_mpo_file = "\MPdataMPOfile" enddef ;
+ def data_mpy_file = "\MPdataMPYfile" enddef ;
+\stopMPextensions
+
+\def\getMPdata
+ {\long\def\MPdata##1##2{\ifnum##1=\currentMPgraphic\relax##2\fi}%
+ \startreadingfile
+ % \startnointerference % no, else we need to do all data global
+ \readlocfile\MPdataMPDfile\donothing\donothing
+ % \stopnointerference
+ \stopreadingfile}
+
+%D We have to enable this mechanism with:
+
+\startMPextensions
+\stopMPextensions
+
+%D For the moment, the next one is a private macro:
+
+\def\processMPbuffer
+ {\dosingleempty\doprocessMPbuffer}
+
+\def\doprocessMPbuffer[#1]%
+ {\doifelsenothing{#1}
+ {\doprocessMPbuffer[\jobname]}
+ {\bgroup
+ \setnormalcatcodes
+ \obeyMPlines
+ %\let\par\empty % oeps, this makes dvi mode graphics hang when not found
+ \!!toksa\emptytoks
+ \def\copyMPbufferline{\expandafter\appendtoks\fileline\to\!!toksa}%
+ \def\dodoprocessMPbuffer##1%
+ {\doprocessfile\scratchread{\TEXbufferfile{##1}}\copyMPbufferline}%
+ \processcommalist[#1]\dodoprocessMPbuffer
+ \@EA\startMPcode\the\!!toksa\stopMPcode % more efficient
+ \egroup}}
+
+\def\runMPbuffer
+ {\dosingleempty\dorunMPbuffer}
+
+\def\dorunMPbuffer[#1]% processing only
+ {{\MPruntrue\doprocessMPbuffer[#1]}}
+
+%D \macros
+%D {startMPenvironment, resetMPenvironment}
+%D
+%D In order to synchronize the main \TEX\ run and the runs
+%D local to \METAPOST, environments can be passed.
+
+\ifx\everyMPTEXgraphic\undefined
+ \newtoks\everyMPTEXgraphic
+\fi
+
+%D A more general way of passing environments is:
+
+\def\startMPenvironment % second arg gobbles spaces, so that reset gives \emptytoks
+ {\bgroup
+ \catcode`\^^M=\@@space
+ \dodoubleempty\dostartMPenvironment}
+
+\long\def\dostartMPenvironment[#1][#2]#3\stopMPenvironment
+ {\egroup
+ \doif{#1}\s!reset\resetMPenvironment % reset mp toks
+ \doif{#1}\v!global{#3}% % use in main doc too
+ \doif{#1}+{#3}% % use in main doc too
+ \defconvertedargument\ascii{#3}%
+ \expandafter\appendtoks\ascii\to\everyMPTEXgraphic}
+
+\def\resetMPenvironment
+ {\everyMPTEXgraphic\emptytoks % = is really needed !
+ \startMPenvironment
+ \global\loadfontfileoncetrue
+ \stopMPenvironment}
+
+\resetMPenvironment
+
+\def\useMPenvironmentbuffer[#1]%
+ {\expanded{\startMPenvironment\noexpand\readfile{\TEXbufferfile{\jobname}}{}{}}\stopMPenvironment}
+
+% \useMPenvironmentbuffer[mp] % what was this?
+
+%D This command takes \type {[reset]} as optional
+%D argument.
+%D
+%D \starttyping
+%D \startMPenvironment
+%D \setupbodyfont[pos,14.4pt]
+%D \stopMPenvironment
+%D
+%D \startMPcode
+%D draw btex \sl Hans Hagen etex scaled 5 ;
+%D \stopMPcode
+%D \stoptyping
+%D
+%D The \type {\resetMPenvironment} is a quick way to erase
+%D the token list.
+%D
+%D You should be aware of independencies. For instance, if you use a font
+%D in a graphic that is not used in the main document, you need to load the
+%D typescript at the outer level (either directly or by using the global
+%D option).
+%D
+%D \starttyping
+%D \usetypescript[palatino][texnansi]
+%D
+%D \startMPenvironment
+%D \usetypescript[palatino][texnansi]
+%D \enableregime[utf]
+%D \setupbodyfont[palatino]
+%D \stopMPenvironment
+%D
+%D \startMPpage
+%D draw btex aap‒noot coördinatie – één etex ;
+%D \stopMPpage
+%D \stoptyping
+
+%D We don't want spurious files, do we?
+
+%\def\initializeMPgraphics
+% {%\ifx\bufferprefix\empty \else
+% \immediate\openout\MPwrite\MPgraphicfile.mp
+% \immediate\write\MPwrite{end.}%
+% \immediate\closeout\MPwrite
+% }%\fi}
+
+% strange :
+
+% \def\initializeMPgraphicfile
+% {\bgroup
+% \doinitializeMPgraphicfile
+% \MPruntrue
+% \doinitializeMPgraphicfile
+% \egroup}
+
+% \def\doinitializeMPgraphicfile
+% {\immediate\openout\scratchwrite\MPgraphicfile.mp
+% \immediate\write\scratchwrite{end.}%
+% \immediate\closeout\scratchwrite}
+
+\def\initializeMPgraphicfile
+ {\immediate\openout\scratchwrite\MPgraphicfile.mp
+ \immediate\write\scratchwrite{end.}%
+ \immediate\closeout\scratchwrite}
+
+\def\initializeMPgraphics
+ {\bgroup
+ \initializeMPgraphicfile
+ \ifx\bufferprefix\empty\else
+ \let\bufferprefix\empty
+ \initializeMPgraphicfile
+ \fi
+ \egroup}
+
+%D Loading specific \METAPOST\ related definitions is
+%D accomplished by:
+
+\def\douseMPlibrary#1%
+ {\ifundefined{\c!file\f!metapostprefix#1}%
+ \letvalueempty{\c!file\f!metapostprefix#1}%
+ \makeshortfilename[\truefilename{\f!metapostprefix#1}]%
+ \startreadingfile
+ \readsysfile\shortfilename{\showmessage\m!metapost1{#1}}\donothing
+ \stopreadingfile
+ \fi}
+
+\def\useMPlibrary[#1]%
+ {\processcommalist[#1]\douseMPlibrary}
+
+%D \macros
+%D {setMPtext, MPtext, MPstring, MPbetex}
+%D
+%D To be documented:
+%D
+%D \starttyping
+%D \setMPtext{identifier}{text}
+%D
+%D \MPtext {identifier}
+%D \MPstring{identifier}
+%D \MPbetex {identifier}
+%D \stoptyping
+
+\def\@@MPT{@MPT@}
+
+\def\forceMPTEXgraphic
+ {\long\def\checkMPTEXgraphic##1{\global\MPTEXgraphictrue}}
+
+\def\setMPtext#1#2% todo : #1 must be made : safe
+ {%\forceMPTEXgraphic
+ \defconvertedargument\ascii{#2}%
+ \dodoglobal\letvalue{\@@MPT#1}\ascii}
+
+% \def\MPtext #1{\getvalue{\@@MPT#1}}
+% \def\MPstring #1{"\getvalue{\@@MPT#1}"}
+% \def\MPbetex #1{btex \getvalue{\@@MPT#1} etex}
+
+\def\MPtext #1{\executeifdefined{\@@MPT#1}\empty}
+\def\MPstring #1{"\executeifdefined{\@@MPT#1}\empty"}
+\def\MPbetex #1{btex \executeifdefined{\@@MPT#1}\empty\space etex}
+
+%D Unfortunately \METAPOST\ does not have \CMYK\ support
+%D built in, but by means of specials we can supply the
+%D information needed to handle them naturaly.
+
+\newif\ifMPcmykcolors \MPcmykcolorstrue
+\newif\ifMPspotcolors \MPspotcolorstrue
+
+\startMPinitializations
+ cmykcolors:=\ifMPcmykcolors true\else false\fi;
+ spotcolors:=\ifMPspotcolors true\else false\fi;
+\stopMPinitializations
+
+%D In order to communicate conveniently with the \TEX\
+%D engine, we introduce some typesetting variables.
+
+% todo : backgroundoffsets
+
+\startMPextensions
+ color OverlayColor,OverlayLineColor;
+\stopMPextensions
+
+\startMPinitializations
+ OverlayWidth:=\overlaywidth;
+ OverlayHeight:=\overlayheight;
+ OverlayDepth:=\overlayheight;
+ OverlayColor:=\MPcolor{\overlaycolor};
+ OverlayLineWidth:=\overlaylinewidth;
+ OverlayLineColor:=\MPcolor{\overlaylinecolor};
+ %
+ BaseLineSkip:=\the\baselineskip;
+ LineHeight:=\the\baselineskip;
+ BodyFontSize:=\the\bodyfontsize;
+ %
+ TopSkip:=\the\topskip;
+ StrutHeight:=\strutheight;
+ StrutDepth:=\strutdepth;
+ %
+ CurrentWidth:=\the\hsize;
+ CurrentHeight:=\the\vsize;
+ %
+ EmWidth:=\the\emwidth;
+ ExHeight:=\the\exheight;
+ %
+ PageNumber:=\the\pageno;
+ RealPageNumber:=\the\realpageno;
+ LastPageNumber:= \lastpage;
+\stopMPinitializations
+
+\appendtoks
+ \disablediscretionaries
+ \disablecompoundcharacters
+\to\everyMPgraphic
+
+% New, experimental (if complaints than only in enco-ffr.mkii), well
+% Mojca complained that it does not work with utf-8 and textext, see
+% ** in meta-tex.
+
+\appendtoks
+ \chardef\activecharactermode\zerocount
+\to\everyMPgraphic
+
+\appendtoks
+ \expanded{\definecolor[currentcolor][\currentcolorname]}%
+\to \everyMPgraphic
+
+\appendtoks
+ \baselineskip1\baselineskip
+ \lineheight 1\lineheight
+ \topskip 1\topskip
+\to \everyMPgraphic
+
+%D Alas, the prologue settings differ per driver.
+
+\ifx\undefined\MPprologues \def\MPprologues{0} \fi
+
+\startMPinitializations
+ prologues:=\MPprologues;
+ mpprocset:=1;
+\stopMPinitializations
+
+\appendtoks
+ \def\MPprologues{0}%
+ \def\MPOSTdriver{dvips}%
+\to \everyresetspecials
+
+%D \macros
+%D {PDFMPformoffset}
+%D
+%D In \PDF, forms are clipped and therefore we have to take
+%D precautions to get this right. Since this is related to
+%D objects, we use the same offset as used there.
+
+\def\PDFMPformoffset{\objectoffset}
+
+%D \macros
+%D {insertMPfile}
+%D
+%D Bypassing the special driver and figure mechanism is not
+%D that nice but saves upto 5\% time in embedding \METAPOST\
+%D graphics by using the low level \PDF\ converter directly,
+%D given of course that we use \PDFTEX. As a result we need to
+%D fool around with the object trigger.
+
+\newtoks\everyinsertMPfile
+
+%D First we present the reasonable fast alternative that we
+%D happily used for some time.
+%D
+%D \starttyping
+%D \def\insertMPfile#1#2%
+%D {\ifx\undefined\externalfigure
+%D \message{[insert file #1 here]}%
+%D \else
+%D \bgroup
+%D \the\everyinsertMPfile
+%D \externalfigure
+%D [#1]
+%D [\c!type=\c!mps,\c!object=\v!no,%
+%D \c!symbol=\v!yes,\c!reset=\v!yes,%
+%D \c!maxwidth=,\c!maxheight=,%
+%D \c!frame=\v!off,\c!background=,%
+%D #2]%
+%D \egroup
+%D \fi}
+%D \stoptyping
+%D
+%D However, on a 1 Gig Pentium, the next alternative saves
+%D us 20 seconds run time for the 300 page \METAFUN\ manual:
+
+\let\insertMPfileARG\insertMPfile
+
+\def\insertMPfile#1#2% in context #2 is empty
+ {\doifelsenothing{#2}{\doinsertMPfile{#1}}{\insertMPfileARG{#1}{#2}}}
+
+\def\includeMPasEPS#1% untested !!
+ {\bgroup
+ \message{[MP as EPS #1]}%
+ \the\everyinsertMPfile
+ \dogetEPSboundingbox{#1}\!!widtha\!!heighta\!!widthb\!!heightb
+ \setbox\scratchbox\vbox to \!!heightb
+ {\vfill
+ \let \@@DriverImageType \c!mps
+ \def \@@DriverImageFile {#1}%
+ \edef\@@DriverImageWidth {\the\!!widthb }%
+ \edef\@@DriverImageHeight{\the\!!heightb}%
+ \doinsertfile}%
+ \wd\scratchbox\!!widthb
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \egroup}
+
+\def\includeMPasPDF#1%
+ {\bgroup
+ \the\everyinsertMPfile
+ \ifinobject \else \chardef\makeMPintoPDFobject\plustwo \fi % when needed
+ \convertMPtoPDF{#1}{1}{1}% no \plusone !
+ \egroup}
+
+%D So, using a low level approach (thereby avoiding the slower
+%D figure analysis macros) pays off. This kind of
+%D optimizations are a bit tricky since we must make sure that
+%D special resources end up in the (PDF) files. Because the
+%D \METAPOST\ to \PDF\ can handle objects itself, it is not
+%D that complicated.
+
+%D We hook a couple of initializations into the graphic
+%D macros.
+
+\appendtoks
+ \let\figuretypes\c!mps
+ \runutilityfilefalse
+ \consultutilityfilefalse
+\to \everyinsertMPfile
+
+%D One more: (still needed?)
+
+\startMPextensions
+ def initialize_form_numbers =
+ do_initialize_numbers;
+ enddef;
+\stopMPextensions
+
+\startMPinitializations
+ HSize:=\the\hsize ;
+ VSize:=\the\vsize ;
+\stopMPinitializations
+
+\startMPextensions
+ vardef ForegroundBox =
+ unitsquare xysized(HSize,VSize)
+ enddef ;
+ vardef PageFraction =
+ if \lastpage>1: (\realfolio-1)/(\lastpage-1) else: 1 fi
+ enddef ;
+\stopMPextensions
+
+%D And some more. These are not really needed since we
+%D don't use the normal figure inclusion macros any longer.
+
+\appendtoks
+ \externalfigurepostprocessors\emptytoks % safeguard
+\to \everyinsertMPfile
+
+%D We also take care of disabling fancy figure features, that
+%D can terribly interfere when dealing with symbols,
+%D background graphics and running (postponed) graphics.
+%D You won't believe me if I tell you what funny side effects
+%D can occur. One took me over a day to uncover when
+%D processing the screen version of the \METAFUN\ manual.
+
+%D For my eyes only:
+
+\def\doifelseMPgraphic#1{\doifdefinedelse{\@@MPG#1}}
+
+%D \macros
+%D {startMPcolor}
+%D
+%D The following time consuming method uses \METAPOST\ to
+%D calculate a color. This enables a match between colors
+%D resulting from a complex calculation (e.g. for a title
+%D page) and those in the text.
+
+% \startuseMPgraphic{somecolors}
+% color c[] ; c[1] := .7[red,green] ; c[2] := .7[blue,yellow] ;
+% \stopuseMPgraphic
+
+% \startMPcolor[shade-1][t=.2,a=1]
+% \includeMPgraphic{somecolors} ; fill fullcircle withcolor c[1] ;
+% \stopMPcolor
+
+% \startMPcolor[shade-2][t=.2,a=1]
+% \includeMPgraphic{somecolors} ; fill fullcircle withcolor c[2] ;
+% \stopMPcolor
+
+% \blackrule[width=\hsize,height=4cm,color=shade-1]
+% \blackrule[width=\hsize,height=4cm,color=shade-2]
+
+\def\startMPcolor
+ {\dodoubleempty\dostartMPcolor}
+
+\long\def\dostartMPcolor[#1][#2]#3\stopMPcolor % slow but sometimes handy
+ {\startnointerference
+ \def\handleMPgraycolor{\expanded{\defineglobalcolor[#1][s=\!MPgMPa1,#2]}}%
+ \def\handleMPrgbcolor {\expanded{\defineglobalcolor[#1][r=\!MPgMPa1,g=\!MPgMPa2,b=\!MPgMPa3,#2]}}%
+ \def\handleMPcmykcolor{\expanded{\defineglobalcolor[#1][c=\!MPgMPa1,m=\!MPgMPa2,y=\!MPgMPa3,k=\!MPgMPa4,#2]}}%
+ \startMPcode#3\stopMPcode
+ \stopnointerference}
+
+%D New:
+
+\definelayerpreset % no dx,dy - else nasty non-mp placement
+ [mp]
+ [\c!y=-\MPury bp,
+ \c!x=\MPllx bp,
+ \c!method=\v!fit]
+
+\definelayer
+ [mp]
+ [\c!preset=mp]
+
+%D Usage:
+%D
+%D \starttyping
+%D \defineproperty[one][layer][state=start]
+%D \defineproperty[two][layer][state=stop]
+%D
+%D \startuseMPgraphic{step-1}
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopuseMPgraphic
+%D
+%D \startuseMPgraphic{step-2}
+%D fill fullcircle scaled 5cm withcolor green ;
+%D \stopuseMPgraphic
+%D
+%D \setlayer[mp]{\property[one]{\useMPgraphic{step-1}}}
+%D \setlayer[mp]{\property[two]{\useMPgraphic{step-2}}}
+%D
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+%D
+%D Reusing graphics is also possible (now):
+%D
+%D \starttyping
+%D \startreusableMPgraphic{axis}
+%D tickstep := 1cm ; ticklength := 2mm ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D tickstep := tickstep/2 ; ticklength := ticklength/2 ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D \stopreusableMPgraphic
+%D
+%D \startuseMPgraphic{demo}
+%D drawpoint "1cm,1.5cm" ;
+%D \stopuseMPgraphic
+%D
+%D \definelayer[mp][preset=mp]
+%D \setlayer[mp]{\reuseMPgraphic{axis}}
+%D \setlayer[mp]{\useMPgraphic{demo}}
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+
+%D \macros
+%D {startstaticMPfigure,useMPstaticfigure}
+%D
+%D Static figures are processed only when there has been
+%D something changed. Here is Aditya Mahajan's testcase:
+%D
+%D \startbuffer
+%D \startstaticMPfigure{circle}
+%D fill fullcircle scaled 1cm withcolor blue;
+%D \stopstaticMPfigure
+%D
+%D \startstaticMPfigure{axis}
+%D drawarrow (0,0)--(2cm,0) ;
+%D drawarrow (0,0)--(0,2cm) ;
+%D label.llft(textext("(0,0)") ,origin) ;
+%D \stopstaticMPfigure
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\usestaticMPfigure[#1]%
+ {\dodoubleempty\externalfigure[\jobname-#1.pdf]}
+
+\def\startstaticMPfigure
+ {\begingroup
+ \obeyMPlines
+ \dostartstaticMPfigure}
+
+\def\dostartstaticMPfigure#1#2\stopstaticMPfigure
+ {\startstaticMPgraphic{\jobname-#1}#2\stopstaticMPgraphic
+ \endgroup}
+
+% faster, but more tricky
+%
+% \def\startstaticMPfigure
+% {\doifmodeelse{*\v!first}
+% {\begingroup
+% \obeyMPlines
+% \dostartstaticMPfigure}
+% {\gobbleuntil\stopstaticMPfigure}}
+%
+% \def\dostartstaticMPfigure#1#2\stopstaticMPfigure
+% {\startMPstaticgraphic{\jobname-#1}#2\stopMPstaticgraphic
+% % dirty trick, don't register, so no second main run of texexec:
+% \global\advance\nofMPgraphics \minusone
+% \endgroup}}
+
+%D New:
+
+% \appendtoks \closeMPgraphicfiles \to \everystoptext
+
+%D New:
+
+\newconditional\manyMPspecials % when set to true, > 1000 specials can be used
+
+\settrue \manyMPspecials % per 1/4/2006
+
+\prependtoks
+ _special_div_ := 1000\ifconditional\manyMPspecials0\fi ;
+\to \MPextensions
+
+%D Needed (will become default):
+
+\prependtoks
+ \resetlanguagespecifics
+\to \everyMPgraphic
+
+%D Goody for preventing overflows:
+
+\def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax}
+
+%D Done.
+
+\protect \endinput
+
+%D Experimental:
+
+\appendtoks
+ \ifrunMPgraphics \ifcase\systemcommandmode \or
+ \runMPgraphicsfalse
+ \fi \fi
+\to \everyjob
+
+% also:
+%
+% linecap := rounded ;
+% linejoin := rounded ;
+% drawoptions () ;
diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv
new file mode 100644
index 000000000..61acbca32
--- /dev/null
+++ b/tex/context/base/meta-ini.mkiv
@@ -0,0 +1,1275 @@
+%D \module
+%D [ file=meta-ini,
+%D version=2008.03.25,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Graphics / Initializations}
+
+\unprotect
+
+%D Instead of sharing code with \MKII, I decided to copy
+%D the code. Otherwise maintainance becomes a pain and after all,
+%D the \MKII\ code will not change.
+
+\let \useMETAFUNformattrue\relax \let \useMETAFUNformatfalse\relax
+\let \longMPlinestrue\relax \let \longMPlinesfalse\relax
+\let \runMPgraphicstrue\relax \let \runMPgraphicsfalse\relax
+\let \runMPTEXgraphicstrue\relax \let \runMPTEXgraphicsfalse\relax
+\let \MPstaticgraphictrue\relax \let \MPstaticgraphicfalse\relax
+\let\forceMPTEXgraphictrue\relax \let\forceMPTEXgraphicfalse\relax
+
+\let \obeyMPlines\relax
+\let \forceMPTEXcheck\gobbleoneargument
+\let\maxnofMPgraphics\scratchcounter
+
+\newtoks \MPextensions % mp, once
+\newtoks \MPinitializations % tex, each
+\newtoks \MPuserinclusions % mp, user
+\newtoks \MPfinalizations % mp, user
+\newtoks \everyMPgraphic % mp
+\newtoks \everyMPTEXgraphic % tex
+
+\newif\ifMPrun
+\def\MPruntimefile{mprun}
+
+% The next command is, of course, dedicated to Mojca, who
+% needs it for gnuplot. Anyway, the whole multiple engine
+% mechanism is to keep her gnuplot from interfering.
+
+\def\startMPdefinitions
+ {\dosinglegroupempty\dostartMPdefinitions}
+
+\long\def\dostartMPdefinitions#1#2\stopMPdefinitions
+ {\edef\currentMPgraphicinstance{#1}%
+ \ifx\currentMPgraphicinstance\empty
+ \let\currentMPgraphicinstance\defaultMPgraphicinstance
+ \fi
+ \global\MPinstancetoks\expandafter{\the\MPinstancetoks#2}}
+
+\long\def\startMPextensions#1\stopMPextensions
+ {\global\MPextensions\expandafter{\the\MPextensions#1}}
+
+\long\def\startMPinitializations#1\stopMPinitializations
+ {\global\MPinitializations\expandafter{\the\MPinitializations#1}}
+
+\long\def\startMPinclusions
+ {\dosingleempty\dostartMPinclusions}
+
+\long\def\dostartMPinclusions[#1]#2\stopMPinclusions
+ {\doifnot{#1}{+}{\global\MPuserinclusions\emptytoks}%
+ \global\MPuserinclusions\expandafter{\the\MPuserinclusions#2}}
+
+\def\MPinclusions
+ {\dosingleempty\doMPinclusions}
+
+\long\def\doMPinclusions[#1]#2%
+ {\doifnot{#1}{+}{\global\MPuserinclusions\emptytoks}%
+ \global\MPuserinclusions\expandafter{\the\MPuserinclusions#2}}
+
+\def\presetMPdefinitions
+ {\edef\overlaywidth {\overlaywidth \space}%
+ \edef\overlayheight {\overlayheight \space}%
+ \edef\overlaylinewidth{\overlaylinewidth\space}%
+ \edef\currentwidth {\the\hsize \space}%
+ \edef\currentheight {\the\vsize \space}}
+
+\def\currentMPformat{metafun}
+
+\def\@@MPF{@MPF@}
+
+\def\MPinstancetoks{\csname\@@MPF::\currentMPgraphicinstance\endcsname}
+
+\unexpanded\def\defineMPinstance
+ {\dodoubleargument\dodefineMPinstance}
+
+\def\dodefineMPinstance[#1][#2]%
+ {\ifcsname\@@MPF::#1\endcsname\else\expandafter\newtoks\csname\@@MPF::#1\endcsname\fi
+ \MPinstancetoks\emptytoks % in case we redefine
+ \getparameters[\@@MPF#1][\s!format=mpost,\s!extensions=\v!no,\s!initializations=\v!no,#2]}
+
+\def\resetMPinstance[#1]%
+ {\writestatus\m!metapost{reset will be implemented when needed}}
+
+\def\defaultMPgraphicinstance{metafun}
+
+\def\splitMPgraphicname[#1]%
+ {\dosplitMPgraphicname[#1::::]}
+
+\def\dosplitMPgraphicname[#1::#2::#3]% instance ::
+ {\edef\currentMPgraphicname{#2}%
+ \ifx\currentMPgraphicname\empty
+ \edef\currentMPgraphicname{#1}%
+ \let\currentMPgraphicinstance\defaultMPgraphicinstance
+ \else
+ \edef\currentMPgraphicinstance{#1}%
+ \fi
+ \edef\currentMPgraphicformat
+ {\ifcsname\@@MPF\currentMPgraphicinstance\s!format\endcsname
+ \csname\@@MPF\currentMPgraphicinstance\s!format\endcsname
+ \else
+ \defaultMPgraphicinstance
+ \fi}}
+
+\def\currentMPgraphicinstance{\defaultMPgraphicinstance}
+\def\currentMPgraphicformat {\currentMPgraphicinstance}
+
+\defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
+\defineMPinstance[extrafun][\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
+\defineMPinstance[mprun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
+\defineMPinstance[metapost][\s!format=mpost]
+\defineMPinstance[nofun] [\s!format=mpost]
+
+\def\beginMPgraphicgroup#1%
+ {\begingroup
+ \splitMPgraphicname[#1]}
+
+\def\endMPgraphicgroup
+ {\endgroup}
+
+\newconditional \METAFUNinitialized
+
+\def\MPaskedfigure{false}
+
+\def\currentMPinitializations
+ {\ifconditional\includeMPinitializations\the\MPinitializations;\fi\theMPrandomseed;}
+
+\def\currentMPpreamble
+ {\ifconditional\includeMPextensions\the\MPextensions;\the\MPuserinclusions;\fi\the\MPinstancetoks;}
+
+\def\dostartcurrentMPgraphic
+ {\begingroup
+ \enableincludeMPgraphics
+ \the\everyMPgraphic
+ \presetMPdefinitions
+ \setMPrandomseed % this has to change
+ % we need to preexpand the token lists
+ \doifelsevalue{\@@MPF\currentMPgraphicinstance\s!extensions}\v!yes
+ {\settrue \includeMPextensions\letgvalue{\@@MPF\currentMPgraphicinstance\s!extensions}\v!no}
+ {\setfalse\includeMPextensions}%
+ \doifelsevalue{\@@MPF\currentMPgraphicinstance\s!initializations}\v!yes
+ {\settrue \includeMPinitializations}%
+ {\setfalse\includeMPinitializations}}
+
+\def\dostopcurrentMPgraphic
+ {\global\MPinstancetoks\emptytoks
+ \global\settrue\METAFUNinitialized % becomes obsolete
+ \endgroup}
+
+\unexpanded\long\def\processMPgraphic#1% todo: extensions and inclusions outside beginfig
+ {\dostartcurrentMPgraphic
+ \forgetall
+ \setbox\MPgraphicbox\hbox\bgroup
+ \normalexpanded{\noexpand\ctxlua{metapost.graphic(
+ "\currentMPgraphicinstance",
+ "\currentMPgraphicformat",
+ \!!bs#1\!!es,
+ \!!bs\currentMPinitializations\!!es,
+ \!!bs\currentMPpreamble\!!es,
+ \MPaskedfigure
+ )}}%
+ \egroup
+ \placeMPgraphic
+ \dostopcurrentMPgraphic}
+
+\newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default
+
+\def\setMPrandomseed
+ {\let\theMPrandomseed\empty
+ \ifsetMPrandomseed \ifx\getrandomnumber\undefined \else
+ \getrandomnumber\localMPseed\zerocount{4095}%
+ \def\theMPrandomseed{randomseed:=\localMPseed}%
+ \fi\fi}
+
+%D To be integrated
+
+\def\@@MPG{@MPG@}
+
+\def\doifMPgraphicelse#1%
+ {\ifcsname\@@MPG#1\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+
+\def\includeMPgraphic#1%
+ {\executeifdefined{\@@MPG#1};} % ; if not found
+
+\def\enableincludeMPgraphics
+ {\let\handleuseMPgraphic \thirdofthreearguments
+ \let\handlereusableMPgraphic\thirdofthreearguments}
+
+\let\MPdrawingdata\empty
+
+\newif\ifMPdrawingdone \MPdrawingdonefalse
+
+\def\resetMPdrawing
+ {\globallet\MPdrawingdata\empty
+ \global\MPdrawingdonefalse}
+
+\def\pushMPdrawing
+ {\globalpushmacro\MPdrawingdata
+ \globallet\MPdrawingdata\empty}
+
+\def\popMPdrawing
+ {\globalpopmacro\MPdrawingdata}
+
+\def\getMPdrawing{\dosinglegroupempty\dogetMPdrawing}
+
+\def\startMPdrawing
+ {\dosingleempty\dostartMPdrawing}
+
+\long\def\dostartMPdrawing[#1]#2\stopMPdrawing
+ {\relax
+ \bgroup
+ \enableincludeMPgraphics
+ \presetMPdefinitions % in case #2 has measures
+ \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}%
+ \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}%
+ \egroup}
+
+\let\stopMPdrawing\relax
+
+\let\MPdrawingdata\empty
+
+\newif\ifMPshiftdrawing \MPshiftdrawingfalse
+
+\def\resetMPdrawing
+ {\globallet\MPdrawingdata\empty
+ \global\MPdrawingdonefalse}
+
+\def\pushMPdrawing
+ {\globalpushmacro\MPdrawingdata
+ \globallet\MPdrawingdata\empty}
+
+\def\popMPdrawing
+ {\globalpopmacro\MPdrawingdata}
+
+\def\getMPdrawing
+ {\ifMPdrawingdone
+ \expandafter\processMPgraphic\expandafter{\MPdrawingdata}% is this expansion still needed?
+ \fi}
+
+\def\startMPdrawing
+ {\dosingleempty\dostartMPdrawing}
+
+\long\def\dostartMPdrawing[#1]#2\stopMPdrawing
+ {\relax
+ \bgroup
+ \enableincludeMPgraphics
+ \presetMPdefinitions % in case #2 has measures
+ \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}%
+ \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}%
+ \egroup}
+
+\let\stopMPdrawing\relax
+
+\let\stopMPclip\relax
+
+\long\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less
+ {\long\setgvalue{MPC:#1}{#2}}
+
+\def\grabMPclippath#1#2#3#4#5% #5 is alternative
+ {\begingroup
+ \edef\width {#3\space}\let\overlaywidth \width
+ \edef\height{#4\space}\let\overlayheight\height
+ \ifcsname MPC:#1\endcsname
+ \dostartcurrentMPgraphic
+ \xdef\MPclippath{\normalexpanded{\noexpand\ctxlua{metapost.theclippath(
+ "\currentMPgraphicinstance",
+ "\currentMPgraphicformat",
+ \!!bs\getvalue{MPC:#1}\!!es,
+ \!!bs\currentMPinitializations\!!es,
+ \!!bs\currentMPpreamble\!!es
+ )}}}%
+ \dostopcurrentMPgraphic
+ \ifx\MPclippath\empty\xdef\MPclippath{#5}\fi
+ \else
+ \xdef\MPclippath{#5}%
+ \fi
+ % #2 : method is obsolete, only pdf now, we can always
+ % gsub the result to ps
+ \endgroup}
+
+%D Next we will use these support macros.
+
+\startMPextensions
+ if unknown context_tool: input mp-tool; fi;
+ if unknown context_spec: input mp-spec; fi;
+ if unknown context_grph: input mp-grph; fi;
+\stopMPextensions
+
+%D Since we want lables to follow the document settings, we
+%D also set the font related variables.
+
+\startMPinitializations % scale is not yet ok
+ defaultfont:="\truefontname{Regular}";
+ defaultscale:=\the\bodyfontsize/10pt;
+\stopMPinitializations
+
+% watch out, this is a type1 font because mp can only handle 8 bit fonts
+
+\startMPinitializations % scale is not yet ok
+ defaultfont:="rm-lmtt10";
+\stopMPinitializations
+
+%D A signal that we're in combines \CONTEXT||\METAFUN mode:
+
+\startMPextensions
+ string contextversion;
+ contextversion:="\contextversion";
+\stopMPextensions
+
+%D Some safeguards:
+%D
+%D \starttyping
+%D \appendtoks \cleanupfeatures \to \everyMPgraphic
+%D \stoptyping
+%D
+%D No, we don't want that (else we loose UTF etc).
+
+%D Another one:
+
+\prependtoks \MPstaticgraphictrue \to \everyoverlay
+\prependtoks \MPstaticgraphictrue \to \everypagebody
+
+%D \macros
+%D {setupMPvariables}
+%D
+%D When we build collections of \METAPOST\ graphics, like
+%D background and buttons, the need for passing settings
+%D arises. By (mis|)|using the local prefix that belongs to
+%D \type {\framed}, we get a rather natural interface to
+%D backgrounds. To prevent conflicts, we will use the \type
+%D {-} in \METAPOST\ specific variables, like:
+%D
+%D \starttyping
+%D \setupMPvariables[meta:button][size=20pt]
+%D \stoptyping
+
+\def\@@meta{meta:}
+
+\unexpanded\def\setupMPvariables
+ {\dodoubleempty\dosetupMPvariables}
+
+\def\dosetupMPvariables[#1][#2]%
+ {\ifsecondargument
+ \getrawparameters[#1:][#2]% brr, todo: [\@@meta#1:]
+ \else
+ \getrawparameters[\@@meta][#1]%
+ \fi}
+
+\let\@@framed\s!unknown
+
+\def\MPvariable#1%
+ {\csname
+ \ifcsname\@@framed\@@meta#1\endcsname\@@framed\fi\@@meta#1%
+ \endcsname}
+
+\let\MPvar\MPvariable
+
+\let\setMPvariables\setupMPvariables
+
+\def\MPrawvar#1#2{\csname#1:#2\endcsname}
+
+\def\presetMPvariable
+ {\dodoubleargument\dopresetMPvariable}
+
+\def\dopresetMPvariable[#1][#2=#3]%
+ {\ifcsname#1:#2\endcsname\else\setvalue{#1:#2}{#3}\fi}
+
+\def\useMPvariables
+ {\dodoubleargument\douseMPvariables}
+
+\def\douseMPvariables[#1][#2]%
+ {\def\@@meta{#1:}%
+ \prepareMPvariables{#2}}
+
+%D \macros
+%D {startuniqueMPgraphic, uniqueMPgraphic}
+%D
+%D This macros is probably of most use to myself, since I like
+%D to use graphics that adapt themselves. The next \METAPOST\
+%D kind of graphic is both unique and reused when possible.
+%D
+%D \starttyping
+%D \defineoverlay[example][\uniqueMPgraphic{test}]
+%D
+%D \startuniqueMPgraphic {test}
+%D draw unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D \stopuniqueMPgraphic
+%D \stoptyping
+
+\def\overlaystamp % watch the \MPcolor, since colors can be redefined
+ {\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+%D A better approach is to let additional variables play a role
+%D in determining the uniqueness. In the next macro, the
+%D second, optional, argument is used to guarantee the
+%D uniqueness, as well as prepare variables for passing them to
+%D \METAPOST.
+%D
+%D \starttyping
+%D \startuniqueMPgraphic{meta:hash}{gap,angle,...}
+%D \stoptyping
+%D
+%D The calling macro also accepts a second argument. For
+%D convenient use in overlay definitions, we use \type {{}}
+%D instead of \type {[]}.
+%D
+%D \starttyping
+%D \uniqueMPgraphic{meta:hash}{gap=10pt,angle=30}
+%D \stoptyping
+
+\newcount\MPobjectcounter
+\newbox \MPgraphicbox
+
+\chardef\MPboxmode\zerocount
+
+\def\doobeyMPboxdepth % mode = 1
+ {\setbox\MPgraphicbox\hbox{\hskip\MPllx\onebasepoint\raise\MPlly\onebasepoint\box\MPgraphicbox}}
+
+\def\doignoreMPboxdepth % mode = 2
+ {\normalexpanded
+ {\noexpand\doobeyMPboxdepth
+ \wd\MPgraphicbox\the\wd\MPgraphicbox
+ \ht\MPgraphicbox\the\ht\MPgraphicbox
+ \dp\MPgraphicbox\the\dp\MPgraphicbox}}
+
+\def\obeyMPboxdepth {\chardef\MPboxmode\plusone}
+\def\ignoreMPboxdepth{\chardef\MPboxmode\plustwo}
+\def\normalMPboxdepth{\chardef\MPboxmode\zerocount}
+
+% compatibility hack:
+
+\let\MPshiftdrawingtrue \ignoreMPboxdepth
+\let\MPshiftdrawingfalse\normalMPboxdepth
+
+\unexpanded\def\placeMPgraphic
+ {\ifcase\MPboxmode
+ \or % 1
+ \doobeyMPboxdepth
+ \or % 2
+ \doignoreMPboxdepth
+ \fi
+ \box\MPgraphicbox}
+
+\def\reuseMPbox#1#2#3#4#5% space delimiting would save some tokens
+ {\xdef\MPllx{#2}% but it's not worth the effort and looks
+ \xdef\MPlly{#3}% ugly as well
+ \xdef\MPurx{#4}%
+ \xdef\MPury{#5}%
+ \hbox{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent
+
+\long\def\handleuniqueMPgraphic#1#2#3%
+ {\begingroup
+ \def\@@meta{#1:}%
+ \extendMPoverlaystamp{#2}% incl prepare
+ \ifcsname\@@MPG\overlaystamp:#1\endcsname\else
+ \enableincludeMPgraphics % redundant
+ \global\advance\MPobjectcounter\plusone
+ \setobject{MP}{\number\MPobjectcounter}\hbox{\processMPgraphic{#3}}% was vbox, graphic must end up as hbox
+ \setxvalue{\@@MPG\overlaystamp:#1}{\noexpand\reuseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}%
+ \fi
+ \getvalue{\@@MPG\overlaystamp:#1}%
+ \endgroup}
+
+\long\unexpanded\def\startuniqueMPgraphic
+ {\dodoublegroupempty\dostartuniqueMPgraphic}
+
+\long\def\dostartuniqueMPgraphic#1#2#3\stopuniqueMPgraphic%
+ {\long\setgvalue{\@@MPG#1}{\handleuniqueMPgraphic{#1}{#2}{#3}}}
+
+\unexpanded\def\uniqueMPgraphic
+ {\dodoublegroupempty\douniqueMPgraphic}
+
+\def\douniqueMPgraphic#1#2%
+ {\beginMPgraphicgroup{#1}%
+ \setupMPvariables[\currentMPgraphicname][#2]%
+ \getvalue{\@@MPG\currentMPgraphicname}\empty
+ \endMPgraphicgroup}
+
+\let\stopuniqueMPcode \relax % so that we can use it in \expanded
+
+\long\def\handleuseMPgraphic#1#2#3%
+ {\begingroup
+ \def\@@meta{#1:}%
+ \prepareMPvariables{#2}%
+ \enableincludeMPgraphics % redundant
+ \processMPgraphic{#3}%
+ \endgroup}
+
+\long\unexpanded\def\startuseMPgraphic
+ {\dodoublegroupempty\dostartuseMPgraphic}
+
+\long\def\dostartuseMPgraphic#1#2#3\stopuseMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}}
+
+\long\unexpanded\def\startusableMPgraphic % redundant but handy
+ {\dodoublegroupempty\dostartusableMPgraphic}
+
+\long\def\dostartusableMPgraphic#1#2#3\stopusableMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}}
+
+\let\stopuseMPgraphic \relax % so that we can use it in \expanded
+\let\stopusableMPgraphic \relax % so that we can use it in \expanded
+
+\long\def\handlereusableMPgraphic#1#2#3%
+ {\begingroup
+ \def\@@meta{#1:}%
+ \prepareMPvariables{#2}%
+ \enableincludeMPgraphics % redundant
+ \global\advance\MPobjectcounter\plusone
+ \setobject{MP}{\number\MPobjectcounter}\hbox{\processMPgraphic{#3}}% was vbox, graphic must end up as hbox
+ \setxvalue{\@@MPG#1}{\noexpand\reuseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}%
+ \getvalue{\@@MPG#1}%
+ \endgroup}
+
+\long\unexpanded\def\startreusableMPgraphic
+ {\dodoublegroupempty\dostartreusableMPgraphic}
+
+\long\def\dostartreusableMPgraphic#1#2#3\stopreusableMPgraphic
+ {\long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}{#3}}}
+
+\let\stopreusableMPgraphic \relax % so that we can use it in \expanded
+
+\unexpanded\def\useMPgraphic
+ {\dodoublegroupempty\douseMPgraphic}
+
+\def\douseMPgraphic#1#2%
+ {\beginMPgraphicgroup{#1}%
+ \doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}%
+ \getvalue{\@@MPG\currentMPgraphicname}\empty
+ \endMPgraphicgroup}
+
+\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed
+\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed
+
+\let\stopuseMPcode \relax % so that we can use it in \expanded
+\let\stopusableMPcode \relax % so that we can use it in \expanded
+\let\stopreusableMPcode \relax % so that we can use it in \expanded
+\let\stopuniqueMPcode \relax % so that we can use it in \expanded
+
+\def\enableincludeMPgraphics
+ {\let\handleuseMPgraphic \thirdofthreearguments
+ \let\handlereusableMPgraphic\thirdofthreearguments}
+
+%D \macros
+%D {startuniqueMPpagegraphic,uniqueMPpagegraphic}
+%D
+%D Experimental.
+
+\def\MPpageprefix{\doifoddpageelse oe:}
+
+\def\overlaypagestamp
+ {\MPpageprefix\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+\long\unexpanded\def\startuniqueMPpagegraphic
+ {\dodoublegroupempty\dostartuniqueMPpagegraphic}
+
+\long\def\dostartuniqueMPpagegraphic#1#2#3\stopuniqueMPpagegraphic
+ {\long\setgvalue{\@@MPG o:#1}{\handleuniqueMPgraphic{o:#1}{#2}{#3}}%
+ \long\setgvalue{\@@MPG e:#1}{\handleuniqueMPgraphic{e:#1}{#2}{#3}}}
+
+\unexpanded\def\uniqueMPpagegraphic
+ {\dodoublegroupempty\douniqueMPpagegraphic}
+
+\def\douniqueMPpagegraphic#1#2%
+ {\beginMPgraphicgroup{#1}%
+ \let\overlaystamp\overlaypagestamp
+ \setupMPvariables[\MPpageprefix\currentMPgraphicname][#2]% prefix is new here
+ \getvalue{\@@MPG\MPpageprefix\currentMPgraphicname}{}%
+ \endMPgraphicgroup}
+
+%D One way of defining a stamp is:
+%D
+%D \starttyping
+%D \def\extendMPoverlaystamp#1%
+%D {\def\docommand##1%
+%D {\edef\overlaystamp{\overlaystamp:\MPvariable{##1}}}%
+%D \processcommalist[#1]\docommand}
+%D \stoptyping
+
+%D Since we need to feed \METAPOST\ with expanded dimensions,
+%D we introduce a dedicated expansion engine.
+
+\def\prepareMPvariable#1%
+ {\ifcsname\@@framed\@@meta#1\endcsname
+ \doprepareMPvariable{\@@framed\@@meta#1}%
+ \else
+ \doprepareMPvariable{\@@meta#1}%
+ \fi}
+
+% \startlines
+% \def\xxx{\lineheight} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2pt} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{\scratchcounter} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{red} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{0.4} \doprepareMPvariable{xxx} \xxx
+% \stoplines
+
+\def\doprepareMPvariable#1%
+ {\edef\theMPvariable{\getvalue{#1}}%
+ \doifelsenothing\theMPvariable
+ {\setevalue{#1}{\MPcolor{black}}}
+ {\defconvertedcommand\ascii\theMPvariable % otherwise problems
+ \doifcolorelse \ascii % with 2\bodyfontsize
+ {\setevalue{#1}{\MPcolor\theMPvariable}}
+ {% can be aux macro
+ \setbox\scratchbox\hbox{\scratchdimen\theMPvariable sp}%
+ \ifdim\wd\scratchbox=\zeropoint
+ % \scratchcounter\theMPvariable
+ % \setevalue{#1}{\the\scratchcounter}%
+ % also accepts 0.number :
+ \setevalue{#1}{\number\theMPvariable}%
+ \else
+ \scratchdimen\theMPvariable
+ \setevalue{#1}{\the\scratchdimen}%
+ \fi}}}
+
+%D We redefine \type {\extendMPoverlaystamp} to preprocess
+%D variables using \type {\prepareMPvariable}.
+
+\def\doextendMPoverlaystamp#1%
+ {\prepareMPvariable{#1}%
+ \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
+
+\def\extendMPoverlaystamp#1%
+ {\processcommalist[#1]\doextendMPoverlaystamp}
+
+\def\prepareMPvariables#1%
+ {\processcommalist[#1]\prepareMPvariable}
+
+%D \macros
+%D {MPdatafile}
+%D
+%D We redefine a macro from \type {supp-mps.tex}:
+
+\def\MPdataMPDfile{\jobname-mpgraph.mpd}
+\def\MPdataMPOfile{\jobname-mpgraph.mpo}
+\def\MPdataMPYfile{\jobname-mpgraph.mpy}
+
+\startMPextensions
+ boolean collapse_data; collapse_data:=true;
+ def data_mpd_file = "\MPdataMPDfile" enddef ;
+ def data_mpo_file = "\MPdataMPOfile" enddef ;
+ def data_mpy_file = "\MPdataMPYfile" enddef ;
+\stopMPextensions
+
+\chardef\currentMPgraphic\plusone
+
+\def\getMPdata
+ {\let\MPdata\secondoftwoarguments
+ \startreadingfile
+ % \startnointerference % no, else we need to do all data global
+ \readlocfile\MPdataMPDfile\donothing\donothing
+ % \stopnointerference
+ \stopreadingfile}
+
+%D \macros
+%D {MPrunfile}
+%D
+%D This one is more abstract and does not assume knowledge
+%D of buffer prefixes.
+
+\def\MPrunfile#1%
+ {\bufferprefix mprun.#1}
+
+%D For the moment, the next one is a private macro:
+
+\def\processMPbuffer
+ {\dosingleempty\doprocessMPbuffer}
+
+\def\doprocessMPbuffer[#1]%
+ {\doifelsenothing{#1}
+ {\dodoprocessMPbuffer{\jobname}}
+ {\dodoprocessMPbuffer{#1}}}
+
+% we need to go via a toks because we have no multiline print in
+% luatex (i.e. tex.sprint does not interpret lines) and therefore
+% omits all after a comment token
+
+\newtoks\mpbuffertoks
+
+\def\doprocessMPbuffer[#1]%
+ {\doifelsenothing{#1}
+ {\doprocessMPbuffer[\jobname]}
+ {\beginMPgraphicgroup{#1}%
+ % we need this trick because tex.sprint does not interprets newlines and the scanner
+ % stops at a newline; also, we do need to flush the buffer under a normal catcode
+ % regime in order to expand embedded tex macros; #1 can be a list
+ \processMPgraphic{\ctxlua{buffers.feedback("\currentMPgraphicname")}}%
+ \endMPgraphicgroup}}
+
+\def\runMPbuffer
+ {\dosingleempty\dorunMPbuffer}
+
+\def\dorunMPbuffer[#1]% processing only
+ {\startnointerference\doprocessMPbuffer[#1]\stopnointerference}
+
+%D \macros
+%D {startMPenvironment, resetMPenvironment}
+%D
+%D In order to synchronize the main \TEX\ run and the runs
+%D local to \METAPOST, environments can be passed.
+
+\ifx\everyMPTEXgraphic\undefined
+ \newtoks\everyMPTEXgraphic
+\fi
+
+%D A more general way of passing environments is:
+
+\def\startMPenvironment % second arg gobbles spaces, so that reset gives \emptytoks
+ {\dodoubleempty\dostartMPenvironment}
+
+\long\def\dostartMPenvironment[#1][#2]#3\stopMPenvironment
+ {\doif{#1}\s!reset\resetMPenvironment % reset mp toks
+ \doif{#1}\v!global{#3}% % use in main doc too
+ \doif{#1}+{#3}% % use in main doc too
+ \ctxlua{metapost.tex.set(\!!bs\detokenize{#3}\!!es)}}
+
+\def\resetMPenvironment
+ {\ctxlua{metapost.tex.reset()}}
+
+\resetMPenvironment
+
+\def\useMPenvironmentbuffer[#1]%
+ {\ctxlua{metapost.tex.set(buffers.content("#1"))}}
+
+%D This command takes \type {[reset]} as optional
+%D argument.
+%D
+%D \starttyping
+%D \startMPenvironment
+%D \setupbodyfont[pos,14.4pt]
+%D \stopMPenvironment
+%D
+%D \startMPcode
+%D draw btex \sl Hans Hagen etex scaled 5 ;
+%D \stopMPcode
+%D \stoptyping
+%D
+%D The most simple case:
+
+\def\startMPcode{\dosinglegroupempty\dostartMPcode}
+
+\def\dostartMPcode
+ {\iffirstargument
+ \expandafter\dodostartMPcode
+ \else
+ \expandafter\nodostartMPcode
+ \fi}
+
+\def\dodostartMPcode#1#2\stopMPcode
+ {\beginMPgraphicgroup{#1::\s!dummy}% name does not matter
+ \processMPgraphic{#2}%
+ \endMPgraphicgroup}
+
+\def\nodostartMPcode#1#2\stopMPcode
+ {\processMPgraphic{#2}}
+
+\let\stopMPcode\relax
+
+% a bit nasty (also needed for compatibility:
+
+% \startMPrun input mp-www.mp ; \stopMPrun
+% \externalfigure[mprun.3][width=10cm,height=8cm]
+
+% \startMPrun{mprun} input mp-www.mp ; \stopMPrun % instance
+% \externalfigure[mprun.4][width=10cm,height=8cm]
+
+\let\MPruninstance\defaultMPgraphicinstance
+
+\def\useMPrun#1#2% name n
+ {\begingroup
+ \def\MPaskedfigure{#2}%
+ \doifelsenothing{#1}
+ {\useMPgraphic{mprun}}%
+ {\useMPgraphic{#1}}%
+ \endgroup}
+
+\def\startMPrun
+ {\dosinglegroupempty\dostartMPrun}
+
+\long\def\dostartMPrun#1#2\stopMPrun
+ {\iffirstargument
+ \startuseMPgraphic{#1}#2\stopuseMPgraphic
+ \else
+ \startuseMPgraphic{mprun}#2\stopuseMPgraphic
+ \fi}
+
+% for old time sake
+
+\def\dostartMPgraphic
+ {\iffirstargument
+ \expandafter\dodostartMPgraphic
+ \else
+ \expandafter\nodostartMPgraphic
+ \fi}
+
+\def\dodostartMPgraphic#1#2\stopMPgraphic
+ {\beginMPgraphicgroup{#1::\s!dummy}% name does not matter
+ \processMPgraphic{#2}%
+ \endMPgraphicgroup}
+
+\def\nodostartMPgraphic#1#2\stopMPcode
+ {\processMPgraphic{#2}}
+
+\let\stopMPcode\relax
+
+%D The \type {\resetMPenvironment} is a quick way to erase
+%D the token list.
+%D
+%D You should be aware of independencies. For instance, if you use a font
+%D in a graphic that is not used in the main document, you need to load the
+%D typescript at the outer level (either directly or by using the global
+%D option).
+%D
+%D \starttyping
+%D \usetypescript[palatino][texnansi]
+%D
+%D \startMPenvironment
+%D \usetypescript[palatino][texnansi]
+%D \enableregime[utf]
+%D \setupbodyfont[palatino]
+%D \stopMPenvironment
+%D
+%D \startMPpage
+%D draw btex aap‒noot coördinatie – één etex ;
+%D \stopMPpage
+%D \stoptyping
+
+%D Loading specific \METAPOST\ related definitions is
+%D accomplished by:
+
+\def\douseMPlibrary#1%
+ {\ifcsname\c!file\f!metapostprefix#1\endcsname\else
+ \letvalueempty{\c!file\f!metapostprefix#1}%
+ \makeshortfilename[\truefilename{\f!metapostprefix#1}]%
+ \startreadingfile
+ \readsysfile\shortfilename{\showmessage\m!metapost1{#1}}\donothing
+ \stopreadingfile
+ \fi}
+
+\def\useMPlibrary[#1]%
+ {\processcommalist[#1]\douseMPlibrary}
+
+%D \macros
+%D {setMPtext, MPtext, MPstring, MPbetex}
+%D
+%D To be documented:
+%D
+%D \starttyping
+%D \setMPtext{identifier}{text}
+%D
+%D \MPtext {identifier}
+%D \MPstring{identifier}
+%D \MPbetex {identifier}
+%D \stoptyping
+
+\def\@@MPT{@MPT@}
+
+\def\forceMPTEXgraphic
+ {\long\def\checkMPTEXgraphic##1{\global\MPTEXgraphictrue}}
+
+\def\setMPtext#1#2% todo : #1 must be made : safe
+ {%\forceMPTEXgraphic
+ \defconvertedargument\ascii{#2}%
+ \dodoglobal\letvalue{\@@MPT#1}\ascii}
+
+\def\MPtext #1{\executeifdefined{\@@MPT#1}\empty}
+\def\MPstring #1{"\executeifdefined{\@@MPT#1}\empty"}
+\def\MPbetex #1{btex \executeifdefined{\@@MPT#1}\empty\space etex}
+
+%D Unfortunately \METAPOST\ does not have \CMYK\ support
+%D built in, but by means of specials we can supply the
+%D information needed to handle them naturaly.
+
+% \newif\ifMPcmykcolors \MPcmykcolorstrue
+% \newif\ifMPspotcolors \MPspotcolorstrue
+
+\startMPinitializations
+ cmykcolors:=\ifMPcmykcolors true\else false\fi;
+ spotcolors:=\ifMPspotcolors true\else false\fi;
+\stopMPinitializations
+
+%D In order to communicate conveniently with the \TEX\
+%D engine, we introduce some typesetting variables.
+
+\startMPextensions
+ color OverlayColor,OverlayLineColor;
+\stopMPextensions
+
+\startMPinitializations
+ OverlayWidth:=\overlaywidth;
+ OverlayHeight:=\overlayheight;
+ OverlayDepth:=\overlayheight;
+ OverlayColor:=\MPcolor{\overlaycolor};
+ OverlayLineWidth:=\overlaylinewidth;
+ OverlayLineColor:=\MPcolor{\overlaylinecolor};
+ %
+ BaseLineSkip:=\the\baselineskip;
+ LineHeight:=\the\baselineskip;
+ BodyFontSize:=\the\bodyfontsize;
+ %
+ TopSkip:=\the\topskip;
+ StrutHeight:=\strutheight;
+ StrutDepth:=\strutdepth;
+ %
+ CurrentWidth:=\the\hsize;
+ CurrentHeight:=\the\vsize;
+ %
+ EmWidth:=\the\emwidth;
+ ExHeight:=\the\exheight;
+ %
+ PageNumber:=\the\pageno;
+ RealPageNumber:=\the\realpageno;
+ LastPageNumber:= \lastpage;
+\stopMPinitializations
+
+\appendtoks
+ \disablediscretionaries
+ \disablecompoundcharacters
+\to \everyMPgraphic
+
+\appendtoks % before color
+ %\normalexpanded{\noexpand\definecolor[currentcolor][\currentcolorname]}%
+ \doregistercolor{currentcolor}\currentcolorname
+\to \everyMPgraphic
+
+% \color[green]{abc \startMPcode
+% fill fullcircle scaled 3cm withoutcolor;
+% fill fullcircle scaled 2cm withcolor \MPcolor{currentcolor} ;
+% fill fullcircle scaled 1cm withcolor \MPcolor{red} ;
+% \stopMPcode def}
+
+% \appendtoks
+% \doactivatecolor\s!black\forcecolorhack % we can also move this to the backend
+% \to \everyMPgraphic
+
+\appendtoks
+ \baselineskip1\baselineskip
+ \lineheight 1\lineheight
+ \topskip 1\topskip
+\to \everyMPgraphic
+
+\appendtoks
+ \let \# \letterhash
+ \let \_ \letterunderscore
+ \let \& \letterampersand
+ \let \{ \letteropenbrace
+ \let \} \letterclosebrace
+\to \everyMPgraphic
+
+\startMPinitializations
+ prologues:=0;
+ mpprocset:=1;
+\stopMPinitializations
+
+%D \macros
+%D {PDFMPformoffset}
+%D
+%D In \PDF, forms are clipped and therefore we have to take
+%D precautions to get this right. Since this is related to
+%D objects, we use the same offset as used there.
+
+\def\PDFMPformoffset{\objectoffset}
+
+% %D \macros
+% %D {insertMPfile}
+% %D
+% %D Bypassing the special driver and figure mechanism is not
+% %D that nice but saves upto 5\% time in embedding \METAPOST\
+% %D graphics by using the low level \PDF\ converter directly,
+% %D given of course that we use \PDFTEX. As a result we need to
+% %D fool around with the object trigger.
+
+\newtoks\everyinsertMPfile
+
+% removed in backend:
+%
+% \def\doinsertMPfile#1%
+% {\doiffileelse{./#1}{\includeMPasPDF{./#1}}{\message{[MP #1]}}}
+%
+% \let\insertMPfileARG\insertMPfile
+%
+% \def\insertMPfile#1#2% in context #2 is empty
+% {\doifelsenothing{#2}{\doinsertMPfile{#1}}{\insertMPfileARG{#1}{#2}}}
+%
+% \def\includeMPasEPS#1% untested !!
+% {\bgroup
+% \message{[MP as EPS #1]}%
+% \the\everyinsertMPfile
+% \dogetEPSboundingbox{#1}\!!widtha\!!heighta\!!widthb\!!heightb
+% \setbox\scratchbox\vbox to \!!heightb
+% {\vfill
+% \let \@@DriverImageType \c!mps
+% \def \@@DriverImageFile {#1}%
+% \edef\@@DriverImageWidth {\the\!!widthb }%
+% \edef\@@DriverImageHeight{\the\!!heightb}%
+% \doinsertfile}%
+% \wd\scratchbox\!!widthb
+% \dp\scratchbox\zeropoint
+% \box\scratchbox
+% \egroup}
+%
+% \def\includeMPasPDF#1%
+% {\bgroup
+% \the\everyinsertMPfile
+% \ifinobject \else \chardef\makeMPintoPDFobject\plustwo \fi % when needed
+% \convertMPtoPDF{#1}{1}{1}% no \plusone !
+% \egroup}
+%
+% %D So, using a low level approach (thereby avoiding the slower
+% %D figure analysis macros) pays off. This kind of
+% %D optimizations are a bit tricky since we must make sure that
+% %D special resources end up in the (PDF) files. Because the
+% %D \METAPOST\ to \PDF\ can handle objects itself, it is not
+% %D that complicated.
+%
+% %D We hook a couple of initializations into the graphic
+% %D macros.
+%
+% \appendtoks
+% \let\figuretypes\c!mps
+% \runutilityfilefalse
+% \consultutilityfilefalse
+% \to \everyinsertMPfile
+%
+% %D One more: (still needed?)
+
+\startMPextensions
+ def initialize_form_numbers =
+ do_initialize_numbers;
+ enddef;
+\stopMPextensions
+
+\startMPinitializations
+ HSize:=\the\hsize ;
+ VSize:=\the\vsize ;
+\stopMPinitializations
+
+\startMPextensions
+ vardef ForegroundBox =
+ unitsquare xysized(HSize,VSize)
+ enddef ;
+ vardef PageFraction =
+ if \lastpage>1: (\realfolio-1)/(\lastpage-1) else: 1 fi
+ enddef ;
+\stopMPextensions
+
+%D And some more. These are not really needed since we
+%D don't use the normal figure inclusion macros any longer.
+
+\appendtoks
+ \externalfigurepostprocessors\emptytoks % safeguard
+\to \everyinsertMPfile
+
+%D We also take care of disabling fancy figure features, that
+%D can terribly interfere when dealing with symbols,
+%D background graphics and running (postponed) graphics.
+%D You won't believe me if I tell you what funny side effects
+%D can occur. One took me over a day to uncover when
+%D processing the screen version of the \METAFUN\ manual.
+
+%D For my eyes only:
+
+\def\doifelseMPgraphic#1{\doifdefinedelse{\@@MPG#1}}
+
+%D \macros
+%D {startMPcolor}
+
+\long\unexpanded\def\startMPcolor#1\stopMPcolor
+ {\writestatus \m!metapost % eventually this placeholder will go away
+ {\string\startMPcolor...\stopMPcolor\space is obsolete,\space
+ use \string\defineintermediatecolor\space instead}}
+
+\let\stopMPcolor\relax
+
+%D New:
+
+\definelayerpreset % no dx,dy - else nasty non-mp placement
+ [mp]
+ [\c!y=-\MPury bp,
+ \c!x=\MPllx bp,
+ \c!method=\v!fit]
+
+\definelayer
+ [mp]
+ [\c!preset=mp]
+
+%D Usage:
+%D
+%D \starttyping
+%D \defineproperty[one][layer][state=start]
+%D \defineproperty[two][layer][state=stop]
+%D
+%D \startuseMPgraphic{step-1}
+%D fill fullcircle scaled 10cm withcolor red ;
+%D \stopuseMPgraphic
+%D
+%D \startuseMPgraphic{step-2}
+%D fill fullcircle scaled 5cm withcolor green ;
+%D \stopuseMPgraphic
+%D
+%D \setlayer[mp]{\property[one]{\useMPgraphic{step-1}}}
+%D \setlayer[mp]{\property[two]{\useMPgraphic{step-2}}}
+%D
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+%D
+%D Reusing graphics is also possible (now):
+%D
+%D \starttyping
+%D \startreusableMPgraphic{axis}
+%D tickstep := 1cm ; ticklength := 2mm ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D tickstep := tickstep/2 ; ticklength := ticklength/2 ;
+%D drawticks unitsquare xscaled 4cm yscaled 3cm shifted (-1cm,-1cm) ;
+%D \stopreusableMPgraphic
+%D
+%D \startuseMPgraphic{demo}
+%D drawpoint "1cm,1.5cm" ;
+%D \stopuseMPgraphic
+%D
+%D \definelayer[mp][preset=mp]
+%D \setlayer[mp]{\reuseMPgraphic{axis}}
+%D \setlayer[mp]{\useMPgraphic{demo}}
+%D \ruledhbox{\flushlayer[mp]}
+%D \stoptyping
+
+%D \macros
+%D {startstaticMPfigure,useMPstaticfigure}
+%D
+%D Static figures are processed only when there has been
+%D something changed. Here is Aditya Mahajan's testcase:
+%D
+%D \startbuffer
+%D \startstaticMPfigure{circle}
+%D fill fullcircle scaled 1cm withcolor blue;
+%D \stopstaticMPfigure
+%D
+%D \startstaticMPfigure{axis}
+%D drawarrow (0,0)--(2cm,0) ;
+%D drawarrow (0,0)--(0,2cm) ;
+%D label.llft(textext("(0,0)") ,origin) ;
+%D \stopstaticMPfigure
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\def\usestaticMPfigure
+ {\dodoubleempty\dousestaticMPfigure}
+
+\def\dousestaticMPfigure[#1][#2]%
+ {\ifsecondargument
+ \scale[#2]{\reuseMPgraphic{\@@MPG#1@S@}}%
+ \else
+ \reuseMPgraphic{\@@MPG#1@S@}%
+ \fi}
+
+\unexpanded\def\startstaticMPfigure#1#2\stopstaticMPfigure
+ {\startreusableMPgraphic{\@@MPG#1@S@}#2\stopreusableMPgraphic}
+
+\long\unexpanded\def\startstaticMPgraphic
+ {\dodoublegroupempty\dostartstaticMPgraphic}
+
+\long\def\dostartstaticMPgraphic#1#2#3\stopstaticMPgraphic
+ {\long\setgvalue{\@@MPG#1@S@}{\handlereusableMPgraphic{#1}{#2}{#3}}}
+
+%D New:
+
+\newconditional\manyMPspecials % when set to true, > 1000 specials can be used
+
+\settrue \manyMPspecials % per 1/4/2006
+
+\prependtoks
+ _special_div_ := 1000\ifconditional\manyMPspecials0\fi ;
+\to \MPextensions
+
+%D Needed too.
+
+\let\initializeMPgraphics\relax
+
+%D Goody for preventing overflows:
+
+\def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax}
+
+%D There is no way to distinguish the black color that you get when
+%D you issue a \type {draw} without color specification from a color
+%D that has an explicit black specification unless you set the
+%D variable \type {defaultcolormodel} to 1. Hoewever, in that case
+%D you cannot distinguish that draw from one with a \type
+%D {withoutcolor} specification. This means that we have to provide
+%D multiple variants of inheritance.
+%D
+%D In any case we need to tell the converter what the inherited color
+%D is to start with. Case~3 is kind of unpredictable as it closely
+%D relates to the order in which paths are flushed. If you want to
+%Dinherit automatically from the surrounding, you can best stick to
+%D variant 1. Variant 0 (an isolated graphic) is the default.
+%D
+%D \startbuffer
+%D \startuseMPgraphic{test}
+%D drawoptions(withpen pencircle scaled 1pt) ;
+%D def shift_cp = currentpicture := currentpicture shifted (-15pt,0) ; enddef ;
+%D draw fullcircle scaled 10pt withoutcolor ; shift_cp ;
+%D fill fullcircle scaled 10pt ; shift_cp ;
+%D draw fullcircle scaled 10pt withoutcolor ; shift_cp ;
+%D fill fullcircle scaled 10pt withcolor red ; shift_cp ;
+%D draw fullcircle scaled 10pt withoutcolor ; shift_cp ;
+%D fill fullcircle scaled 10pt ; shift_cp ;
+%D \stopuseMPgraphic
+%D
+%D \starttabulate
+%D \NC 0\quad \NC \chardef\MPcolormethod0 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \NC 1\quad \NC \chardef\MPcolormethod1 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \NC 2\quad \NC \chardef\MPcolormethod2 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \NC 3\quad \NC \chardef\MPcolormethod3 \green XX\quad \useMPgraphic{test}\quad XX \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\chardef\MPcolormethod\zerocount
+
+% can be faster, just
+
+\appendtoks
+ \ctxlua{metapost.set_outer_color(\number\MPcolormethod,\number\currentcolormodel,\number\dogetattribute{color},\number\dogetattribute{transparency})}%
+\to \everyMPgraphic
+
+\startMPinitializations
+ defaultcolormodel := \ifcase\MPcolormethod1\or1\or3\else3\fi;
+\stopMPinitializations
+
+%D \macros
+%D {setupMPgraphics}
+%D
+%D Here is a generic setup command:
+
+\newtoks \everysetupMPgraphics
+
+\unexpanded\def\setupMPgraphics[#1]%
+ {\getparameters[\??mp][#1]%
+ \the\everysetupMPgraphics}
+
+%D Here we hook in the outer color. When \type {color} is set to \type
+%D {global} we get the outer color automatically. If you change this
+%D setting, you should do it grouped in order not to make other graphics
+%D behave in unexpected ways.
+
+\appendtoks
+ \doifelse\@@mpcolor\v!global{\chardef\MPcolormethod\plusone}{\chardef\MPcolormethod\zerocount}%
+\to \everysetupMPgraphics
+
+\setupMPgraphics
+ [\c!color=\v!local]
+
+%D Done.
+
+\protect \endinput
diff --git a/tex/context/base/meta-mis.tex b/tex/context/base/meta-mis.tex
new file mode 100644
index 000000000..29ab43007
--- /dev/null
+++ b/tex/context/base/meta-mis.tex
@@ -0,0 +1,54 @@
+%D \module
+%D [ file=meta-mis,
+%D version=2006.06.06,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Misc Test Graphics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+% p/s 1/false 1/true 2/false 2/true
+%
+% MKII 8.5 8.0 8.8 8.5
+% MKIV 16.1 7.2 16.3 7.4
+
+\startuseMPgraphic{mptopdf-test}
+ prologues := 2;
+ mpprocset := 1 ;
+ fill fullcircle scaled 3cm withcolor red ;
+ fill fullcircle scaled 2cm withcolor green ;
+ fill fullcircle scaled 1cm withcolor blue ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ;
+ fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ;
+ fill fullcircle scaled 1cm withcolor cmyk(1,0,0,0) ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ draw fullcircle scaled 3cm dashed evenly ;
+ draw fullcircle scaled 2cm dashed withdots ;
+ draw origin withpen pencircle scaled 3mm;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red);
+ fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red);
+ fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green);
+ fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5));
+ currentpicture := currentpicture shifted (12cm,-4cm) ;
+ draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ % bug: shift
+ draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30 ;
+ draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ;
+ filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ;
+ currentpicture := currentpicture shifted (-4cm,0) ;
+ % shade cannot handle shift
+ circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ;
+ circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ;
+ filldraw boundingbox currentpicture enlarged (-bbheight(currentpicture)/2+2.5mm) withpen pencircle scaled 1pt withcolor .5white ;
+\stopuseMPgraphic
+
+\protect \endinput
diff --git a/tex/context/base/meta-nav.tex b/tex/context/base/meta-nav.tex
new file mode 100644
index 000000000..9c1cbb4db
--- /dev/null
+++ b/tex/context/base/meta-nav.tex
@@ -0,0 +1,65 @@
+%D \module
+%D [ file=meta-nav,
+%D version=2003.03.28,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Navigational Graphics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startuniqueMPgraphic{navplus}{size,color,type,mode}
+ color c ; numeric s, t ; path p ;
+ t := \MPvar{type} ; c := \MPvar{color} ; s := \MPvar{size} ;
+ if \MPvar{mode} = 1 : c := .5[c,white] fi ;
+ if t = 1 :
+ p := ((0,0)--(1/2,0)--(1,1/3)--(1,1)--(0,1)--(0,0)--cycle)
+ xyscaled (3,4) ;
+ elseif t = 2 :
+ p := ((0,0)--(1,0)--(1,1)--(0,1)--(1/2,2/5)--(1,1)--(0,1)--cycle)
+ xyscaled (4,3) ;
+ else :
+ p := fullsquare xyscaled (3,3) ;
+ fi ;
+ draw p withpen pencircle scaled (1/2) withcolor .75white ;
+ fill p withcolor c ;
+ draw p withpen pencircle scaled (1/3) withcolor .5c ;
+ currentpicture := currentpicture scaled s ;
+ currentpicture := currentpicture shifted -center currentpicture ;
+\stopuniqueMPgraphic
+
+\setupMPvariables
+ [navplus]
+ [size=1ex,
+ color=black,
+ type=1,
+ mode=0]
+
+\definepalet
+ [navplus]
+ [attach=darkred,
+ comment=darkblue]
+
+\definesymbol
+ [comment-normal]
+ [\uniqueMPgraphic{navplus}{type=1,color=navplus:comment}]
+\definesymbol
+ [comment-down]
+ [\uniqueMPgraphic{navplus}{type=1,color=navplus:comment,mode=1}]
+
+\definesymbol
+ [attach-normal]
+ [\uniqueMPgraphic{navplus}{type=2,color=navplus:attach}]
+\definesymbol
+ [attach-down]
+ [\uniqueMPgraphic{navplus}{type=2,color=navplus:attach,mode=1}]
+
+\unprotect
+
+\setupcomment [\c!symbol={comment-normal,comment-down}]
+\setupattachments[\c!symbol={attach-normal,attach-down}]
+
+\protect \endinput
diff --git a/tex/context/base/meta-pag.mkii b/tex/context/base/meta-pag.mkii
new file mode 100644
index 000000000..000e56a2e
--- /dev/null
+++ b/tex/context/base/meta-pag.mkii
@@ -0,0 +1,226 @@
+%D \module
+%D [ file=meta-pag,
+%D version=1999.07.10,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 These definitions used to be part of the old \type
+%D {core-mps} file, later changed into \type {meta-ini}, but
+%D keeping them separate is cleaner.
+
+\writestatus{loading}{MetaPost Graphics / Page Data Management}
+
+\unprotect
+
+\startMPextensions
+ if unknown context_page: input mp-page; fi;
+\stopMPextensions
+
+%D The next few macros tell \METAPOST\ how the \CONTEXT\
+%D pagebody looks.
+
+\startMPextensions
+ boolean PageStateAvailable,OnRightPage,InPageBody;
+ PageStateAvailable:=true;
+\stopMPextensions
+
+\startMPinitializations
+ OnRightPage:=true;
+ InPageBody:=\ifinpagebody true \else false \fi;
+\stopMPinitializations
+
+\startMPinitializations
+ def LoadPageState =
+ OnRightPage:=\MPonrightpage;
+ OnOddPage:=\MPonoddpage;
+ RealPageNumber:=\the\realpageno;
+ PageNumber:=\the\pageno;
+ NOfPages:=\lastpage;
+ PaperHeight:=\the\paperheight;
+ PaperWidth:=\the\paperwidth;
+ PrintPaperHeight:=\the\printpaperheight;
+ PrintPaperWidth:=\the\printpaperwidth;
+ TopSpace:=\the\topspace;
+ BottomSpace:=\the\bottomspace;
+ BackSpace:=\the\backspace;
+ CutSpace:=\the\cutspace;
+ MakeupHeight:=\the\makeupheight;
+ MakeupWidth:=\the\makeupwidth;
+ TopHeight:=\the\topheight;
+ TopDistance:=\the\topdistance;
+ HeaderHeight:=\the\headerheight;
+ HeaderDistance:=\the\headerdistance;
+ TextHeight:=\the\textheight;
+ FooterDistance:=\the\footerdistance;
+ FooterHeight:=\the\footerheight;
+ BottomDistance:=\the\bottomdistance;
+ BottomHeight:=\the\bottomheight;
+ LeftEdgeWidth:=\the\leftedgewidth;
+ LeftEdgeDistance:=\the\leftedgedistance;
+ LeftMarginWidth:=\the\leftmarginwidth;
+ LeftMarginDistance:=\the\leftmargindistance;
+ TextWidth:=\the\textwidth ;
+ RightMarginDistance:=\the\rightmargindistance;
+ RightMarginWidth:=\the\rightmarginwidth;
+ RightEdgeDistance:=\the\rightedgedistance;
+ RightEdgeWidth:=\the\rightedgewidth;
+ InnerMarginDistance:=\the\innermargindistance;
+ InnerMarginWidth:=\the\innermarginwidth;
+ OuterMarginDistance:=\the\outermargindistance;
+ OuterMarginWidth:=\the\outermarginwidth;
+ InnerEdgeDistance:=\the\inneredgedistance;
+ InnerEdgeWidth:=\the\inneredgewidth;
+ OuterEdgeDistance:=\the\outeredgedistance;
+ OuterEdgeWidth:=\the\outeredgewidth;
+ PageOffset:=\the\pageoffset;
+ PageDepth:=\the\pagedepth;
+ LayoutColumns:=\the\layoutcolumns;
+ LayoutColumnDistance:=\the\layoutcolumndistance;
+ LayoutColumnWidth:=\the\layoutcolumnwidth;
+ enddef;
+\stopMPinitializations
+
+\def\MPonrightpage{true}
+\def\MPonoddpage {true}
+
+\def\freezeMPpagelayout
+ {\doifbothsides
+ {\def\MPonrightpage{true}}
+ {\def\MPonrightpage{true}}
+ {\def\MPonrightpage{false}}%
+ \edef\MPonoddpage{\doifoddpageelse{true}{false}}}
+
+\let\freezeMPlayout\relax % obsolete
+
+%D We need to freeze the pagelayout before the backgrounds
+%D are build, because the overlay will temporarily become
+%D zero (overlay).
+
+\appendtoks
+ \freezeMPpagelayout
+\to \everybeforepagebody
+
+%D By freezing these value every graphic, we can use layout
+%D variables that change halfways a page, whatever use that
+%D has.
+
+\prependtoks
+ \calculatereducedvsizes % this is really needed
+ \freezeMPpagelayout
+ \freezeMPlayout % to be used grouped
+\to \everyMPgraphic
+
+%D The next feature provides information about for instance
+%D column positions. This is an experimental feature,
+%D introduced when we needed backgrounds in columns (fill||in
+%D questions as implemented in a private module).
+%D
+%D See \type {mp-page.mp} for the definition of the macros:
+%D
+%D \starttabulate[|tl|l|p|]
+%D \NC ResetTextAreas \NC no arguments \NC
+%D reset areas on page \NC \NR
+%D \NC RegisterTextArea \NC x, y, w, h \NC
+%D adds area to the list \NC \NR
+%D \NC TextAreaX,Y,W,H,XY,WH \NC x and/or y \NC
+%D reports offsets and dimensions \NC \NR
+%D \stoptabulate
+%D
+%D The \type {TextArea*} macros can be used to determine
+%D overlap.
+
+\newcount\currentMPtextareadata
+
+\newtoks\MPsavedtextareadata
+\newtoks\MPtextareadata
+\newtoks\MPlocaltextareadata
+
+% optimaliseren voor herhaling
+
+\def\registerMPtextarea#1%
+ {\ifpositioning
+ \bgroup
+ \global\advance\currentMPtextareadata\plusone
+ %\hpos{gbd:\the\currentMPtextareadata}{#1}%
+ \hpos{gbd:\the\currentMPtextareadata}%
+ {\iftracetextareas\boxrulewidth1.5pt\ruledhbox\fi{#1}}%
+ \edef\!!stringa{gbd:\the\currentMPtextareadata}%
+ \edef\!!stringa{RegisterTextArea(%
+ \MPx\!!stringa,\MPy\!!stringa,%
+ \MPw\!!stringa,\MPh\!!stringa,\MPd\!!stringa);}%
+ \@EA \doglobal \@EA \appendtoks \!!stringa \to \MPtextareadata
+ \egroup
+ \else
+ \hbox{#1}%
+ \fi}
+
+\def\registerMPlocaltextarea#1%
+ {\ifpositioning
+ \bgroup
+ \global\advance\currentMPtextareadata\plusone
+ %\hpos{gbd:\the\currentMPtextareadata}{#1}%
+ \hpos{gbd:\the\currentMPtextareadata}%
+ {\iftracetextareas\boxrulewidth3pt\ruledhbox\fi{#1}}%
+ \edef\!!stringa{gbd:\the\currentMPtextareadata}%
+ \edef\!!stringa{RegisterLocalTextArea(%
+ \MPx\!!stringa,\MPy\!!stringa,%
+ \MPw\!!stringa,\MPh\!!stringa,\MPd\!!stringa);}%
+ \global\MPlocaltextareadata\@EA{\!!stringa}%
+ \egroup
+ \else
+ \hbox{#1}%
+ \fi}
+
+% better, so that we can force a key and share with e.g. renumbering
+%
+% \let\namedtextarea\empty
+%
+% \def\registerMPlocaltextarea#1%
+% {\ifpositioning
+% \bgroup
+% \ifx\namedtextarea\empty
+% \global\advance\currentMPtextareadata\plusone
+% \edef\namedtextarea{gbd:\the\currentMPtextareadata}%
+% \fi
+% \hpos\namedtextarea{\iftracetextareas\boxrulewidth3pt\ruledhbox\fi{#1}}%
+% \edef\ascii{RegisterLocalTextArea(%
+% \MPx\namedtextarea,\MPy\namedtextarea,%
+% \MPw\namedtextarea,\MPh\namedtextarea,\MPd\namedtextarea);}%
+% \global\MPlocaltextareadata\@EA{\ascii}%
+% \egroup
+% \else
+% \hbox{#1}%
+% \fi}
+
+\def\resetMPlocaltextarea
+ {\global\MPlocaltextareadata\emptytoks}
+
+\startMPextensions
+ path PlainTextArea;
+\stopMPextensions
+
+\startMPinitializations
+ ResetTextAreas;
+ \the\MPsavedtextareadata;
+ SaveTextAreas;
+ ResetTextAreas;
+ \the\MPtextareadata;
+ \the\MPlocaltextareadata;
+ PlainTextArea:=boundingbox(\MPxy{text:\realfolio}--\MPxy{text:\realfolio}
+ shifted (\MPw{text:\realfolio},\MPh{text:\realfolio}));
+\stopMPinitializations
+
+\appendtoks
+ \global\MPsavedtextareadata\MPtextareadata
+ \global\MPtextareadata \emptytoks
+ \global\MPlocaltextareadata\emptytoks
+\to \everyshipout
+
+\protect \endinput
diff --git a/tex/context/base/meta-pag.mkiv b/tex/context/base/meta-pag.mkiv
new file mode 100644
index 000000000..ef3817721
--- /dev/null
+++ b/tex/context/base/meta-pag.mkiv
@@ -0,0 +1,223 @@
+%D \module
+%D [ file=meta-pag,
+%D version=1999.07.10,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 These definitions used to be part of the old \type
+%D {core-mps} file, later changed into \type {meta-ini}, but
+%D keeping them separate is cleaner.
+
+\writestatus{loading}{MetaPost Graphics / Page Data Management}
+
+\unprotect
+
+\startMPextensions
+ if unknown context_page: input mp-page; fi;
+\stopMPextensions
+
+%D The next few macros tell \METAPOST\ how the \CONTEXT\
+%D pagebody looks.
+
+\startMPextensions
+ boolean PageStateAvailable,OnRightPage,InPageBody;
+ PageStateAvailable:=true;
+\stopMPextensions
+
+\startMPinitializations
+ OnRightPage:=true;
+ InPageBody:=\ifinpagebody true \else false \fi;
+\stopMPinitializations
+
+\startMPinitializations
+ def LoadPageState =
+ OnRightPage:=\MPonrightpage;
+ OnOddPage:=\MPonoddpage;
+ RealPageNumber:=\the\realpageno;
+ PageNumber:=\the\pageno;
+ NOfPages:=\lastpage;
+ PaperHeight:=\the\paperheight;
+ PaperWidth:=\the\paperwidth;
+ PrintPaperHeight:=\the\printpaperheight;
+ PrintPaperWidth:=\the\printpaperwidth;
+ TopSpace:=\the\topspace;
+ BottomSpace:=\the\bottomspace;
+ BackSpace:=\the\backspace;
+ CutSpace:=\the\cutspace;
+ MakeupHeight:=\the\makeupheight;
+ MakeupWidth:=\the\makeupwidth;
+ TopHeight:=\the\topheight;
+ TopDistance:=\the\topdistance;
+ HeaderHeight:=\the\headerheight;
+ HeaderDistance:=\the\headerdistance;
+ TextHeight:=\the\textheight;
+ FooterDistance:=\the\footerdistance;
+ FooterHeight:=\the\footerheight;
+ BottomDistance:=\the\bottomdistance;
+ BottomHeight:=\the\bottomheight;
+ LeftEdgeWidth:=\the\leftedgewidth;
+ LeftEdgeDistance:=\the\leftedgedistance;
+ LeftMarginWidth:=\the\leftmarginwidth;
+ LeftMarginDistance:=\the\leftmargindistance;
+ TextWidth:=\the\textwidth ;
+ RightMarginDistance:=\the\rightmargindistance;
+ RightMarginWidth:=\the\rightmarginwidth;
+ RightEdgeDistance:=\the\rightedgedistance;
+ RightEdgeWidth:=\the\rightedgewidth;
+ InnerMarginDistance:=\the\innermargindistance;
+ InnerMarginWidth:=\the\innermarginwidth;
+ OuterMarginDistance:=\the\outermargindistance;
+ OuterMarginWidth:=\the\outermarginwidth;
+ InnerEdgeDistance:=\the\inneredgedistance;
+ InnerEdgeWidth:=\the\inneredgewidth;
+ OuterEdgeDistance:=\the\outeredgedistance;
+ OuterEdgeWidth:=\the\outeredgewidth;
+ PageOffset:=\the\pageoffset;
+ PageDepth:=\the\pagedepth;
+ LayoutColumns:=\the\layoutcolumns;
+ LayoutColumnDistance:=\the\layoutcolumndistance;
+ LayoutColumnWidth:=\the\layoutcolumnwidth;
+ enddef;
+\stopMPinitializations
+
+\def\MPonrightpage{true}
+\def\MPonoddpage {true}
+
+\def\freezeMPpagelayout
+ {\edef\MPonrightpage{\doifbothsides {tru}{tru}{fals}e}%
+ \edef\MPonoddpage {\doifoddpageelse {tru}{fals}e}}
+
+\let\freezeMPlayout\relax % obsolete
+
+%D We need to freeze the pagelayout before the backgrounds
+%D are build, because the overlay will temporarily become
+%D zero (overlay).
+
+\appendtoks
+ \freezeMPpagelayout
+\to \everybeforepagebody
+
+%D By freezing these value every graphic, we can use layout
+%D variables that change halfways a page, whatever use that
+%D has.
+
+\prependtoks
+ \calculatereducedvsizes % this is really needed
+ \freezeMPpagelayout
+ \freezeMPlayout % to be used grouped
+\to \everyMPgraphic
+
+%D The next feature provides information about for instance
+%D column positions. This is an experimental feature,
+%D introduced when we needed backgrounds in columns (fill||in
+%D questions as implemented in a private module).
+%D
+%D See \type {mp-page.mp} for the definition of the macros:
+%D
+%D \starttabulate[|tl|l|p|]
+%D \NC ResetTextAreas \NC no arguments \NC
+%D reset areas on page \NC \NR
+%D \NC RegisterTextArea \NC x, y, w, h \NC
+%D adds area to the list \NC \NR
+%D \NC TextAreaX,Y,W,H,XY,WH \NC x and/or y \NC
+%D reports offsets and dimensions \NC \NR
+%D \stoptabulate
+%D
+%D The \type {TextArea*} macros can be used to determine
+%D overlap.
+
+\newcount\currentMPtextareadata
+
+\newtoks\MPsavedtextareadata
+\newtoks\MPtextareadata
+\newtoks\MPlocaltextareadata
+
+% optimaliseren voor herhaling
+
+\def\registerMPtextarea#1%
+ {\ifpositioning
+ \bgroup
+ \global\advance\currentMPtextareadata\plusone
+ %\hpos{gbd:\the\currentMPtextareadata}{#1}%
+ \hpos{gbd:\the\currentMPtextareadata}%
+ {\iftracetextareas\boxrulewidth1.5pt\ruledhbox\fi{#1}}%
+ \edef\!!stringa{gbd:\the\currentMPtextareadata}%
+ \edef\!!stringa{RegisterTextArea(%
+ \MPx\!!stringa,\MPy\!!stringa,%
+ \MPw\!!stringa,\MPh\!!stringa,\MPd\!!stringa);}%
+ \@EA \doglobal \@EA \appendtoks \!!stringa \to \MPtextareadata
+ \egroup
+ \else
+ \hbox{#1}%
+ \fi}
+
+\def\registerMPlocaltextarea#1%
+ {\ifpositioning
+ \bgroup
+ \global\advance\currentMPtextareadata\plusone
+ %\hpos{gbd:\the\currentMPtextareadata}{#1}%
+ \hpos{gbd:\the\currentMPtextareadata}%
+ {\iftracetextareas\boxrulewidth3pt\ruledhbox\fi{#1}}%
+ \edef\!!stringa{gbd:\the\currentMPtextareadata}%
+ \edef\!!stringa{RegisterLocalTextArea(%
+ \MPx\!!stringa,\MPy\!!stringa,%
+ \MPw\!!stringa,\MPh\!!stringa,\MPd\!!stringa);}%
+ \global\MPlocaltextareadata\@EA{\!!stringa}%
+ \egroup
+ \else
+ \hbox{#1}%
+ \fi}
+
+% better, so that we can force a key and share with e.g. renumbering
+%
+% \let\namedtextarea\empty
+%
+% \def\registerMPlocaltextarea#1%
+% {\ifpositioning
+% \bgroup
+% \ifx\namedtextarea\empty
+% \global\advance\currentMPtextareadata\plusone
+% \edef\namedtextarea{gbd:\the\currentMPtextareadata}%
+% \fi
+% \hpos\namedtextarea{\iftracetextareas\boxrulewidth3pt\ruledhbox\fi{#1}}%
+% \edef\ascii{RegisterLocalTextArea(%
+% \MPx\namedtextarea,\MPy\namedtextarea,%
+% \MPw\namedtextarea,\MPh\namedtextarea,\MPd\namedtextarea);}%
+% \global\MPlocaltextareadata\@EA{\ascii}%
+% \egroup
+% \else
+% \hbox{#1}%
+% \fi}
+
+\def\resetMPlocaltextarea
+ {\global\MPlocaltextareadata\emptytoks}
+
+\startMPextensions
+ path PlainTextArea;
+\stopMPextensions
+
+\startMPinitializations
+ ResetTextAreas;
+ \the\MPsavedtextareadata;
+ SaveTextAreas;
+ ResetTextAreas;
+ \the\MPtextareadata;
+ \the\MPlocaltextareadata;
+ PlainTextArea:=boundingbox(\MPxy{text:\realfolio}--\MPxy{text:\realfolio}
+ shifted (\MPw{text:\realfolio},\MPh{text:\realfolio}));
+\stopMPinitializations
+
+\appendtoks
+ \global\MPsavedtextareadata\MPtextareadata
+ \global\MPtextareadata \emptytoks
+ \global\MPlocaltextareadata\emptytoks
+\to \everyshipout
+
+\protect \endinput
diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua
new file mode 100644
index 000000000..23f8d4de0
--- /dev/null
+++ b/tex/context/base/meta-pdf.lua
@@ -0,0 +1,553 @@
+if not modules then modules = { } end modules ['meta-pdf'] = {
+ version = 1.001,
+ comment = "companion to meta-pdf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Finally we used an optimized version. The test code can be found in
+-- meta-pdh.lua but since we no longer want to overload functione we use
+-- more locals now. This module keeps changing as it is also a testbed.
+
+local concat, format, gsub, find, byte, gmatch, match = table.concat, string.format, string.gsub, string.find, string.byte, string.gmatch, string.match
+local lpegmatch = lpeg.match
+local round = math.round
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+
+local pdfrgbcode = lpdf.rgbcode
+local pdfcmykcode = lpdf.cmykcode
+local pdfgraycode = lpdf.graycode
+local pdfspotcode = lpdf.spotcode
+local pdftransparencycode = lpdf.transparencycode
+local pdffinishtransparencycode = lpdf.finishtransparencycode
+
+mptopdf = { }
+mptopdf.n = 0
+
+local m_path, m_stack, m_texts, m_version, m_date, m_shortcuts = { }, { }, { }, 0, 0, false
+
+local m_stack_close, m_stack_path, m_stack_concat = false, { }, nil
+local extra_path_code, ignore_path = nil, false
+local specials = { }
+
+local function resetpath()
+ m_stack_close, m_stack_path, m_stack_concat = false, { }, nil
+end
+
+local function resetall()
+ m_path, m_stack, m_texts, m_version, m_shortcuts = { }, { }, { }, 0, false
+ extra_path_code, ignore_path = nil, false
+ specials = { }
+ resetpath()
+end
+
+resetall()
+
+-- todo: collect and flush packed using pdfliteral node injection but we're
+-- in no hurry as this kind of conversion does not happen that often in mkiv
+
+local function pdfcode(str) -- could be a node.write instead
+ texsprint(ctxcatcodes,"\\pdfliteral{",str,"}")
+end
+
+local function texcode(str)
+ texsprint(ctxcatcodes,str)
+end
+
+function mpscode(str)
+ if ignore_path then
+ pdfcode("h W n")
+ if extra_path_code then
+ pdfcode(extra_path_code)
+ extra_path_code = nil
+ end
+ ignore_path = false
+ else
+ pdfcode(str)
+ end
+end
+
+-- auxiliary functions
+
+local function flushconcat()
+ if m_stack_concat then
+ mpscode(concat(m_stack_concat," ") .. " cm")
+ m_stack_concat = nil
+ end
+end
+
+local function flushpath(cmd)
+ if #m_stack_path > 0 then
+ local path = { }
+ if m_stack_concat then
+ local sx, sy = m_stack_concat[1], m_stack_concat[4]
+ local rx, ry = m_stack_concat[2], m_stack_concat[3]
+ local tx, ty = m_stack_concat[5], m_stack_concat[6]
+ local d = (sx*sy) - (rx*ry)
+ for k=1,#m_stack_path do
+ local v = m_stack_path[k]
+ local px, py = v[1], v[2] ; v[1], v[2] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[1],v[2])
+ if #v == 7 then
+ local px, py = v[3], v[4] ; v[3], v[4] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[3],v[4])
+ local px, py = v[5], v[6] ; v[5], v[6] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[5],v[6])
+ end
+ path[#path+1] = concat(v," ")
+ end
+ else
+ for k=1,#m_stack_path do
+ path[#path+1] = concat(m_stack_path[k]," ")
+ end
+ end
+ flushconcat()
+ pdfcode(concat(path," "))
+ if m_stack_close then
+ mpscode("h " .. cmd)
+ else
+ mpscode(cmd)
+ end
+ end
+ resetpath()
+end
+
+-- mp interface
+
+mps = mps or { }
+
+function mps.creator(a, b, c)
+ m_version = tonumber(b)
+end
+
+function mps.creationdate(a)
+ m_date = a
+end
+
+function mps.newpath()
+ m_stack_path = { }
+end
+
+function mps.boundingbox(llx, lly, urx, ury)
+ texcode("\\MPSboundingbox{" .. llx .. "}{" .. lly .. "}{" .. urx .. "}{" .. ury .. "}")
+end
+
+function mps.moveto(x,y)
+ m_stack_path[#m_stack_path+1] = {x,y,"m"}
+end
+
+function mps.curveto(ax, ay, bx, by, cx, cy)
+ m_stack_path[#m_stack_path+1] = {ax,ay,bx,by,cx,cy,"c"}
+end
+
+function mps.lineto(x,y)
+ m_stack_path[#m_stack_path+1] = {x,y,"l"}
+end
+
+function mps.rlineto(x,y)
+ local dx, dy = 0, 0
+ if #m_stack_path > 0 then
+ dx, dy = m_stack_path[#m_stack_path][1], m_stack_path[#m_stack_path][2]
+ end
+ m_stack_path[#m_stack_path+1] = {dx,dy,"l"}
+end
+
+function mps.translate(tx,ty)
+ mpscode("1 0 0 0 1 " .. tx .. " " .. ty .. " cm")
+end
+
+function mps.scale(sx,sy)
+ m_stack_concat = {sx,0,0,sy,0,0}
+end
+
+function mps.concat(sx, rx, ry, sy, tx, ty)
+ m_stack_concat = {sx,rx,ry,sy,tx,ty}
+end
+
+function mps.setlinejoin(d)
+ mpscode(d .. " j")
+end
+
+function mps.setlinecap(d)
+ mpscode(d .. " J")
+end
+
+function mps.setmiterlimit(d)
+ mpscode(d .. " M")
+end
+
+function mps.gsave()
+ mpscode("q")
+end
+
+function mps.grestore()
+ mpscode("Q")
+end
+
+function mps.setdash(...) -- can be made faster, operate on t = { ... }
+ local n = select("#",...)
+ mpscode("[" .. concat({...}," ",1,n-1) .. "] " .. select(n,...) .. " d")
+end
+
+function mps.resetdash()
+ mpscode("[ ] 0 d")
+end
+
+function mps.setlinewidth(d)
+ mpscode(d .. " w")
+end
+
+function mps.closepath()
+ m_stack_close = true
+end
+
+function mps.fill()
+ flushpath('f')
+end
+
+function mps.stroke()
+ flushpath('S')
+end
+
+function mps.both()
+ flushpath('B')
+end
+
+function mps.clip()
+ flushpath('W n')
+end
+
+function mps.textext(font, scale, str) -- old parser
+ local dx, dy = 0, 0
+ if #m_stack_path > 0 then
+ dx, dy = m_stack_path[1][1], m_stack_path[1][2]
+ end
+ flushconcat()
+ texcode("\\MPStextext{"..font.."}{"..scale.."}{"..str.."}{"..dx.."}{"..dy.."}")
+ resetpath()
+end
+
+local handlers = { }
+
+handlers[1] = function(s)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfcmykcode(mps.colormodel,s[3],s[4],s[5],s[6]))
+end
+handlers[2] = function(s)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfspotcode(mps.colormodel,s[3],s[4],s[5],s[6]))
+end
+handlers[3] = function(s)
+ pdfcode(pdfrgbcode(mps.colormodel,s[4],s[5],s[6]))
+ pdfcode(pdftransparencycode(s[2],s[3]))
+end
+handlers[4] = function(s)
+ pdfcode(pdfcmykcode(mps.colormodel,s[4],s[5],s[6],s[7]))
+ pdfcode(pdftransparencycode(s[2],s[3]))
+end
+handlers[5] = function(s)
+ pdfcode(pdfspotcode(mps.colormodel,s[4],s[5],s[6],s[7]))
+ pdfcode(pdftransparencycode(s[2],s[3]))
+end
+
+-- todo: color conversion
+
+local nofshades, tn = 0, tonumber
+
+local function linearshade(colorspace,domain,ca,cb,coordinates)
+ pdfcode(pdffinishtransparencycode())
+ nofshades = nofshades + 1
+ local name = format("MpsSh%s",nofshades)
+ lpdf.linearshade(name,domain,ca,cb,1,colorspace,coordinates)
+ extra_path_code, ignore_path = format("/%s sh Q",name), true
+ pdfcode("q /Pattern cs")
+end
+
+local function circularshade(colorspace,domain,ca,cb,coordinates)
+ pdfcode(pdffinishtransparencycode())
+ nofshades = nofshades + 1
+ local name = format("MpsSh%s",nofshades)
+ lpdf.circularshade(name,domain,ca,cb,1,colorspace,coordinates)
+ extra_path_code, ignore_path = format("/%s sh Q",name), true
+ pdfcode("q /Pattern cs")
+end
+
+handlers[30] = function(s)
+ linearshade("DeviceRGB", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]) }, { tn(s[10]), tn(s[11]), tn(s[12]) },
+ { tn(s[ 8]), tn(s[ 9]), tn(s[13]), tn(s[14]) } )
+end
+
+handlers[31] = function(s)
+ circularshade("DeviceRGB", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]) }, { tn(s[11]), tn(s[12]), tn(s[13]) },
+ { tn(s[ 8]), tn(s[ 9]), tn(s[10]), tn(s[14]), tn(s[15]), tn(s[16]) } )
+end
+
+handlers[32] = function(s)
+ linearshade("DeviceCMYK", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]), tn(s[ 8]) }, { tn(s[11]), tn(s[12]), tn(s[13]), tn(s[14]) },
+ { tn(s[ 9]), tn(s[10]), tn(s[15]), tn(s[16]) } )
+end
+
+handlers[33] = function(s)
+ circularshade("DeviceCMYK", { tn(s[ 2]), tn(s[ 3]) },
+ { tn(s[ 5]), tn(s[ 6]), tn(s[ 7]), tn(s[ 8]) }, { tn(s[12]), tn(s[13]), tn(s[14]), tn(s[15]) },
+ { tn(s[ 9]), tn(s[10]), tn(s[11]), tn(s[16]), tn(s[17]), tn(s[18]) } )
+end
+
+handlers[34] = function(s) -- todo (after further cleanup)
+ linearshade("DeviceGray", { tn(s[ 2]), tn(s[ 3]) }, { 0 }, { 1 }, { tn(s[9]), tn(s[10]), tn(s[15]), tn(s[16]) } )
+end
+
+handlers[35] = function(s) -- todo (after further cleanup)
+ circularshade("DeviceGray", { tn(s[ 2]), tn(s[ 3]) }, { 0 }, { 1 }, { tn(s[9]), tn(s[10]), tn(s[15]), tn(s[16]) } )
+end
+
+-- not supported in mkiv , use mplib instead
+
+handlers[10] = function() logs.report("mptopdf","skipping special %s",10) end
+handlers[20] = function() logs.report("mptopdf","skipping special %s",20) end
+handlers[50] = function() logs.report("mptopdf","skipping special %s",50) end
+
+--end of not supported
+
+function mps.setrgbcolor(r,g,b) -- extra check
+ r, g = tonumber(r), tonumber(g) -- needed when we use lpeg
+ if r == 0.0123 and g < 0.1 then
+ g, b = round(g*10000), round(b*10000)
+ local s = specials[b]
+ local h = round(s[#s])
+ local handler = handlers[h]
+ if handler then
+ handler(s)
+ else
+ logs.report("mptopdf","unknown special handler %s (1)",h)
+ end
+ elseif r == 0.123 and g < 0.1 then
+ g, b = round(g*1000), round(b*1000)
+ local s = specials[b]
+ local h = round(s[#s])
+ local handler = handlers[h]
+ if handler then
+ handler(s)
+ else
+ logs.report("mptopdf","unknown special handler %s (2)",h)
+ end
+ else
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfrgbcode(mps.colormodel,r,g,b))
+ end
+end
+
+function mps.setcmykcolor(c,m,y,k)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfcmykcode(mps.colormodel,c,m,y,k))
+end
+
+function mps.setgray(s)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode(pdfgrayliteral(mps.colormodel,s))
+end
+
+function mps.specials(version,signal,factor) -- 2.0 123 1000
+end
+
+function mps.special(...) -- 7 1 0.5 1 0 0 1 3
+ local t = { ... }
+ local n = tonumber(t[#t-1])
+ specials[n] = t
+end
+
+function mps.begindata()
+end
+
+function mps.enddata()
+end
+
+function mps.showpage()
+end
+
+-- lpeg parser
+
+-- The lpeg based parser is rather optimized for the kind of output
+-- that MetaPost produces. It's my first real lpeg code, which may
+-- show. Because the parser binds to functions, we define it last.
+
+local lpegP, lpegR, lpegS, lpegC, lpegCc, lpegCs = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs
+
+local digit = lpegR("09")
+local eol = lpegS('\r\n')^1
+local sp = lpegP(' ')^1
+local space = lpegS(' \r\n')^1
+local number = lpegS('0123456789.-+')^1
+local nonspace = lpegP(1-lpegS(' \r\n'))^1
+
+local spec = digit^2 * lpegP("::::") * digit^2
+local text = lpegCc("{") * (
+ lpegP("\\") * ( (digit * digit * digit) / function(n) return "c" .. tonumber(n,8) end) +
+ lpegP(" ") / function(n) return "\\c32" end + -- never in new mp
+ lpegP(1) / function(n) return "\\c" .. byte(n) end
+ ) * lpegCc("}")
+local package = lpegCs(spec + text^0)
+
+function mps.fshow(str,font,scale) -- lpeg parser
+ mps.textext(font,scale,lpegmatch(package,str))
+end
+
+local cnumber = lpegC(number)
+local cstring = lpegC(nonspace)
+
+local specials = (lpegP("%%MetaPostSpecials:") * sp * (cstring * sp^0)^0 * eol) / mps.specials
+local special = (lpegP("%%MetaPostSpecial:") * sp * (cstring * sp^0)^0 * eol) / mps.special
+local boundingbox = (lpegP("%%BoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+local highresboundingbox = (lpegP("%%HiResBoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+
+local setup = lpegP("%%BeginSetup") * (1 - lpegP("%%EndSetup") )^1
+local prolog = lpegP("%%BeginProlog") * (1 - lpegP("%%EndProlog"))^1
+local comment = lpegP('%')^1 * (1 - eol)^1
+
+local curveto = ((cnumber * sp)^6 * lpegP("curveto") ) / mps.curveto
+local lineto = ((cnumber * sp)^2 * lpegP("lineto") ) / mps.lineto
+local rlineto = ((cnumber * sp)^2 * lpegP("rlineto") ) / mps.rlineto
+local moveto = ((cnumber * sp)^2 * lpegP("moveto") ) / mps.moveto
+local setrgbcolor = ((cnumber * sp)^3 * lpegP("setrgbcolor") ) / mps.setrgbcolor
+local setcmykcolor = ((cnumber * sp)^4 * lpegP("setcmykcolor") ) / mps.setcmykcolor
+local setgray = ((cnumber * sp)^1 * lpegP("setgray") ) / mps.setgray
+local newpath = ( lpegP("newpath") ) / mps.newpath
+local closepath = ( lpegP("closepath") ) / mps.closepath
+local fill = ( lpegP("fill") ) / mps.fill
+local stroke = ( lpegP("stroke") ) / mps.stroke
+local clip = ( lpegP("clip") ) / mps.clip
+local both = ( lpegP("gsave fill grestore")) / mps.both
+local showpage = ( lpegP("showpage") )
+local setlinejoin = ((cnumber * sp)^1 * lpegP("setlinejoin") ) / mps.setlinejoin
+local setlinecap = ((cnumber * sp)^1 * lpegP("setlinecap") ) / mps.setlinecap
+local setmiterlimit = ((cnumber * sp)^1 * lpegP("setmiterlimit") ) / mps.setmiterlimit
+local gsave = ( lpegP("gsave") ) / mps.gsave
+local grestore = ( lpegP("grestore") ) / mps.grestore
+
+local setdash = (lpegP("[") * (cnumber * sp^0)^0 * lpegP("]") * sp * cnumber * sp * lpegP("setdash")) / mps.setdash
+local concat = (lpegP("[") * (cnumber * sp^0)^6 * lpegP("]") * sp * lpegP("concat") ) / mps.concat
+local scale = ( (cnumber * sp^0)^6 * sp * lpegP("concat") ) / mps.concat
+
+local fshow = (lpegP("(") * lpegC((1-lpegP(")"))^1) * lpegP(")") * space * cstring * space * cnumber * space * lpegP("fshow")) / mps.fshow
+local fshow = (lpegP("(") * lpegCs( ( lpegP("\\(")/"\\050" + lpegP("\\)")/"\\051" + (1-lpegP(")")) )^1 )
+ * lpegP(")") * space * cstring * space * cnumber * space * lpegP("fshow")) / mps.fshow
+
+local setlinewidth_x = (lpegP("0") * sp * cnumber * sp * lpegP("dtransform truncate idtransform setlinewidth pop")) / mps.setlinewidth
+local setlinewidth_y = (cnumber * sp * lpegP("0 dtransform exch truncate exch idtransform pop setlinewidth") ) / mps.setlinewidth
+
+local c = ((cnumber * sp)^6 * lpegP("c") ) / mps.curveto -- ^6 very inefficient, ^1 ok too
+local l = ((cnumber * sp)^2 * lpegP("l") ) / mps.lineto
+local r = ((cnumber * sp)^2 * lpegP("r") ) / mps.rlineto
+local m = ((cnumber * sp)^2 * lpegP("m") ) / mps.moveto
+local vlw = ((cnumber * sp)^1 * lpegP("vlw")) / mps.setlinewidth
+local hlw = ((cnumber * sp)^1 * lpegP("hlw")) / mps.setlinewidth
+
+local R = ((cnumber * sp)^3 * lpegP("R") ) / mps.setrgbcolor
+local C = ((cnumber * sp)^4 * lpegP("C") ) / mps.setcmykcolor
+local G = ((cnumber * sp)^1 * lpegP("G") ) / mps.setgray
+
+local lj = ((cnumber * sp)^1 * lpegP("lj") ) / mps.setlinejoin
+local ml = ((cnumber * sp)^1 * lpegP("ml") ) / mps.setmiterlimit
+local lc = ((cnumber * sp)^1 * lpegP("lc") ) / mps.setlinecap
+
+local n = lpegP("n") / mps.newpath
+local p = lpegP("p") / mps.closepath
+local S = lpegP("S") / mps.stroke
+local F = lpegP("F") / mps.fill
+local B = lpegP("B") / mps.both
+local W = lpegP("W") / mps.clip
+local P = lpegP("P") / mps.showpage
+
+local q = lpegP("q") / mps.gsave
+local Q = lpegP("Q") / mps.grestore
+
+local sd = (lpegP("[") * (cnumber * sp^0)^0 * lpegP("]") * sp * cnumber * sp * lpegP("sd")) / mps.setdash
+local rd = ( lpegP("rd")) / mps.resetdash
+
+local s = ( (cnumber * sp^0)^2 * lpegP("s") ) / mps.scale
+local t = (lpegP("[") * (cnumber * sp^0)^6 * lpegP("]") * sp * lpegP("t") ) / mps.concat
+
+-- experimental
+
+local preamble = (
+ prolog + setup +
+ boundingbox + highresboundingbox + specials + special +
+ comment
+)
+
+local procset = (
+ lj + ml + lc +
+ c + l + m + n + p + r +
+ R + C + G +
+ S + F + B + W +
+ vlw + hlw +
+ Q + q +
+ sd + rd +
+ t + s +
+ fshow +
+ P
+)
+
+local verbose = (
+ curveto + lineto + moveto + newpath + closepath + rlineto +
+ setrgbcolor + setcmykcolor + setgray +
+ setlinejoin + setmiterlimit + setlinecap +
+ stroke + fill + clip + both +
+ setlinewidth_x + setlinewidth_y +
+ gsave + grestore +
+ concat + scale +
+ fshow +
+ setdash + -- no resetdash
+ showpage
+)
+
+-- order matters in terms of speed / we could check for procset first
+
+local captures_old = ( space + verbose + preamble )^0
+--~ local captures_new = ( space + procset + preamble + verbose )^0
+local captures_new = ( space + verbose + procset + preamble )^0
+
+local function parse(m_data)
+ if find(m_data,"%%%%BeginResource: procset mpost") then
+ lpegmatch(captures_new,m_data)
+ else
+ lpegmatch(captures_old,m_data)
+ end
+end
+
+-- main converter
+
+local a_colorspace = attributes.private('colormodel')
+
+function mptopdf.convertmpstopdf(name)
+ resetall()
+ local ok, m_data, n = resolvers.loadbinfile(name, 'tex') -- we need a binary load !
+ if ok then
+ mps.colormodel = tex.attribute[a_colorspace]
+ statistics.starttiming(mptopdf)
+ mptopdf.n = mptopdf.n + 1
+ pdfcode(format("\\letterpercent\\space mptopdf begin: n=%s, file=%s",mptopdf.n,file.basename(name)))
+ pdfcode("q 1 0 0 1 0 0 cm")
+ parse(m_data)
+ pdfcode(pdffinishtransparencycode())
+ pdfcode("Q")
+ pdfcode("\\letterpercent\\space mptopdf end")
+ resetall()
+ statistics.stoptiming(mptopdf)
+ else
+ commands.writestatus("mptopdf","file '%s' not found",name)
+ end
+end
+
+
+-- status info
+
+statistics.register("mps conversion time",function()
+ local n = mptopdf.n
+ if n > 0 then
+ return format("%s seconds, %s conversions", statistics.elapsedtime(mptopdf),n)
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/meta-pdf.mkii b/tex/context/base/meta-pdf.mkii
new file mode 100644
index 000000000..2099b0d37
--- /dev/null
+++ b/tex/context/base/meta-pdf.mkii
@@ -0,0 +1,2761 @@
+%D \module
+%D [ file=meta-pdf,
+%D version=2006.06.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Conversion to \PDF,
+%D author=Hans Hagen \& others (see text),
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Formerly known as supp-pdf.tex and supp-mpe.tex.
+
+%D We will clean up the color mess later.
+
+%D These macros are written as generic as possible. Some
+%D general support macro's are loaded from a small module
+%D especially made for non \CONTEXT\ use. In this module I
+%D use a matrix transformation macro written by Tanmoy
+%D Bhattacharya. Thanks to extensive testing by Sebastian
+%D Ratz I was able to complete this module within reasonable
+%D time. This module has support for \METAPOST\ extensions
+%D built in.
+%D
+%D Daniel H. Luecking came up with a better (more precise)
+%D transformation method. You can recognize his comment by
+%D his initials. (We keep the old code around because it's a
+%D nice illustration on how a module like this evolves.)
+
+% Beware, we cannot use 0pt here by defaukt since it may be
+% defined in the range \dimen 0 - 20 which we happen to use
+% as scratch registers; for this reason we start allocating
+% scratch registers > 20
+
+%D This module handles some \PDF\ conversion and insertions
+%D topics. By default, the macros use the \PDFTEX\ primitive
+%D \type{\pdfliteral} when available. Since \PDFTEX\ is now the
+%D default engine for \TEX\ distributions, we need a more complex
+%D test.
+
+\writestatus{loading}{MetaPost Graphics / MPS to PDF}
+
+\unprotect
+
+\ifx\PDFcode \undefined \let\PDFcode \gobbleoneargument \fi
+\ifx\PDFcomment\undefined \def\PDFcomment#1{\PDFcode{\letterpercent\space#1}} \fi
+
+%D First we define a handy constant:
+
+\bgroup \catcode`\%=\@@other \xdef\letterpercent{\string%} \egroup
+
+%D \macros
+%D {pdfimage,pdfimages,pdfclippedimage}
+%D
+%D Starting with pdftex version 14, images are included more
+%D natural to the form embedding. This enables alternative
+%D images to be embedded.
+%D
+%D \starttyping
+%D \pdfimage {file}
+%D \pdfimages {high res file} {low res file}
+%D \stoptyping
+%D
+%D The first one replaces the pre||version||14 original,
+%D while the latter provides alternative images.
+%D
+%D The next macro is dedicated to Maarten Gelderman, who
+%D needed to paste prepared \PDF\ pages into conference
+%D proceedings.
+%D
+%D \starttyping
+%D \pdfclippedimage {file} {l} {r} {t} {b}
+%D \stoptyping
+
+\ifx\pdftexversion\undefined \else \ifnum\pdftexversion>13 % still relevant?
+
+ \def\pdfimage#1#%
+ {\dopdfimage{#1}}
+
+ \def\dopdfimage#1#2%
+ {\immediate\pdfximage#1{#2}%
+ \pdfrefximage\pdflastximage}
+
+ \def\pdfimages#1#%
+ {\dopdfimages{#1}}
+
+ \def\dopdfimages#1#2#3%
+ {\immediate\pdfximage#1{#2}%
+ \immediate\pdfobj{[ << /Image \the\pdflastximage\space0 R /DefaultForPrinting true >> ]}%
+ \immediate\pdfximage#1 attr {/Alternates \the\pdflastobj\space0 R}{#3}%
+ \pdfrefximage\pdflastximage}
+
+ \def\pdfclippedimage#1#% specs {file}{left}{right}{top}{bottom}
+ {\dopdfclippedimage{#1}}
+
+ \def\dopdfclippedimage#1#2#3#4#5#6%
+ {\bgroup
+ \pdfximage#1{#2}%
+ \setbox\scratchbox\hbox{\pdfrefximage\pdflastximage}%
+ \hsize\dimexpr\wd\scratchbox-#3-#4\relax
+ \vsize\dimexpr\ht\scratchbox-#5-#6\relax
+ \setbox\scratchbox\vbox to \vsize
+ {\vskip-#5\hbox to \hsize{\hskip-#3\box\scratchbox\hss}}%
+ \pdfxform\scratchbox
+ \pdfrefxform\pdflastxform
+ \egroup}
+
+\fi \fi
+
+%D \macros
+%D {convertMPtoPDF}
+%D
+%D The next set of macros implements \METAPOST\ to \PDF\
+%D conversion. The traditional method is in the MkII file.
+
+%D The main conversion command is:
+%D
+%D \starttyping
+%D \convertMPtoPDF {filename} {x scale} {y scale}
+%D \stoptyping
+%D
+%D The dimensions are derived from the bounding box. So we
+%D only have to say:
+%D
+%D \starttyping
+%D \convertMPtoPDF{mp-pra-1.eps}{1}{1}
+%D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5}
+%D \stoptyping
+
+%D \macros
+%D {makeMPintoPDFobject,lastPDFMPobject}
+%D
+%D For experts there are a few more options. When attributes
+%D are to be added, the code must be embedded in an object
+%D accompanied with the appropriate directives. One can
+%D influence this process with \type {\makeMPintoPDFobject}.
+%D
+%D This option defaults to~0, because \CONTEXT\ takes care
+%D of objects at another level, which saves some bytes.
+%D
+%D \starttabulate[|l|l|p|]
+%D \NC 0 \NC never \NC don't use an object \NC\NR
+%D \NC 1 \NC always \NC always use an object \NC\NR
+%D \NC 2 \NC optional \NC use object when needed \NC\NR
+%D \stoptabulate
+%D
+%D The last object number used is avaliable in the macro
+%D \type {\lastPDFMPobject}.
+
+\ifx\makeMPintoPDFobject \undefined \chardef\makeMPintoPDFobject \zerocount \fi
+\ifx\blackoutMPgraphic \undefined \chardef\blackoutMPgraphic \plusone \fi
+\ifx\everyMPtoPDFconversion\undefined \newtoks\everyMPtoPDFconversion \fi
+
+\let\lastPDFMPobject \!!zerocount
+\let\currentPDFresources\empty
+\let\setMPextensions \relax
+
+\def\PDFMPformoffset
+ {\ifx\objectoffset\undefined\zeropoint\else\objectoffset\fi}
+
+\def\resetMPvariables#1#2#3%
+ {\global\let\MPwidth \!!zeropoint
+ \global\let\MPheight\!!zeropoint
+ \global\let\MPllx \!!zerocount
+ \global\let\MPlly \!!zerocount
+ \global\let\MPurx \!!zerocount
+ \global\let\MPury \!!zerocount
+ \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi
+ \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi
+ \xdef\MPfilename {#1}}
+
+%D The main macro:
+
+\def\convertMPtoPDF#1#2#3%
+ {\resetMPvariables{#1}{#2}{#3}%
+ \vbox\bgroup
+ \forgetall
+ \offinterlineskip
+ \ifx\pdfdecimaldigits\undefined\else \pdfdecimaldigits=5 \fi % new
+ \global\let\MPheight\!!zeropoint
+ \global\let\MPwidth \!!zeropoint
+ \setbox\scratchbox\vbox\bgroup
+ \message{[MP to PDF]}%
+ \startMPresources
+ \PDFcomment{mps begin}%
+ \PDFcode{q}%
+ \PDFcode{1 0 0 1 0 0 cm}%
+ \ifcase\blackoutMPgraphic\or\PDFcode{0 g 0 G}\fi
+ \doprocessMPtoPDFfile}
+
+\def\processMPtoPDFfile#1#2#3% obsolete
+ {\resetMPvariables{#1}{#2}{#3}%
+ \bgroup
+ \let\finishMPgraphic\egroup
+ \doprocessMPtoPDFfile}
+
+\def\doprocessMPtoPDFfile
+ {\setMPspecials
+ \setMPextensions
+ \the\everyMPtoPDFconversion
+ \catcode`\^^M=\@@endofline
+ \startMPscanning
+ \let\do\empty
+ \donefalse
+ \let\handleMPsequence\dohandleMPsequence
+ \input\MPfilename\relax}
+
+\def\finishMPgraphic
+ {\PDFcode{Q}%
+ \PDFcomment{mps end}%
+ \stopMPresources
+ \egroup
+ \setbox\scratchbox\hbox\bgroup
+ \hskip-\MPllx\onebasepoint
+ \raise-\MPlly\onebasepoint
+ \box\scratchbox
+ \egroup
+ \setbox\scratchbox\vbox to \MPheight\bgroup
+ \vfill
+ \hsize\MPwidth
+ \smashbox\scratchbox
+ \box\scratchbox
+ \egroup
+ \wd\scratchbox\MPwidth
+ \ht\scratchbox\MPheight
+ \dopackageMPgraphic\scratchbox
+ \egroup
+ \endinput}
+
+%D A common hook.
+
+\let\MPfshowcommand\empty
+
+%D Objects.
+
+\def\dopackageMPgraphic#1% #1 = boxregister
+ {\ifcase\makeMPintoPDFobject\or\or\ifx\currentPDFresources\empty\else
+ % an existing value of 2 signals object support (set elsewhere)
+ \chardef\makeMPintoPDFobject\plusone
+ \fi\fi
+ \ifcase\makeMPintoPDFobject
+ \box#1%
+ \or
+ \scratchdimen\PDFMPformoffset\relax
+ \ifdim\scratchdimen>\zeropoint % compensate for error
+ \setbox#1\vbox spread 2\scratchdimen
+ {\forgetall\vss\hbox spread 2\scratchdimen{\hss\box#1\hss}\vss}%
+ \fi
+ \setMPPDFobject{\currentPDFresources}{#1}%
+ \ifdim\scratchdimen>\zeropoint % compensate for error
+ \vbox to \MPheight
+ {\forgetall\vss\hbox to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
+ \else
+ \getMPPDFobject
+ \fi
+ \global\let\currentPDFresources\empty
+ \else
+ \box#1%
+ \fi}
+
+\def\setMPPDFobject#1#2% resources boxnumber
+ {\ifx\pdfxform\undefined
+ \def\getMPPDFobject{\box#2}%
+ \else\ifx\pdftexversion\undefined
+ \def\getMPPDFobject{\box#2}%
+ \else\ifnum\pdftexversion<14
+ \def\getMPPDFobject{\box#2}%
+ \else
+ \ifx\everyPDFxform\undefined\else\the\everyPDFxform\fi
+ \immediate\pdfxform resources{#1}#2%
+ \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}%
+ \fi\fi\fi}
+
+\let\getMPPDFobject\relax
+
+%D \macros
+%D {deleteMPgraphic,
+%D startMPresources,
+%D stopMPresources}
+
+\ifx\deleteMPgraphic\undefined
+ \def\deleteMPgraphic#1{}
+\fi
+
+\ifx\startMPresources\undefined
+ \let\startMPresources\relax
+ \let\stopMPresources\relax
+\fi
+
+%D We implement extensions by using the \METAPOST\ special
+%D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones
+%D are flushed before or after the graphic data, but thereby
+%D are no longer connected to a position.
+%D
+%D We implement specials by overloading the \type {fill}
+%D operator. By counting the fills, we can let the converter
+%D treat the appropriate fill in a special way. The
+%D specification of the speciality can have two forms,
+%D determined by the setting of a boolean variable:
+%D
+%D \starttyping
+%D _inline_specials_ := false ; % comment like code (default)
+%D _inline_specials_ := true ; % command like code
+%D \stoptyping
+%D
+%D When the specification is embedded as comment, it looks
+%D like:
+%D
+%D \starttyping
+%D %%MetaPostSpecial
+%D \stoptyping
+%D
+%D The in||line alternative is more tuned for \POSTSCRIPT,
+%D since it permits us to define a macro \type {special}.
+%D
+%D \starttyping
+%D inline : special
+%D \stoptyping
+%D
+%D The \type {identifier} determines what to do, and the data
+%D can be used to accomplish this. A type~2 shading function
+%D has identifier~2. Alltogether, the number of parameters is
+%D specified in \type {size}. The \type {number} is the number
+%D of the fill that needs the special treatment. For a type~2
+%D and~3 shaded fill, the datablock contains the following
+
+%D data:
+%D
+%D \starttyping
+%D from to n inner_r g b x y outer_r g b x y
+%D from to n inner_r g b x y radius outer_r g b x y radius
+%D \stoptyping
+
+\newconditional\manyMPspecials \settrue\manyMPspecials
+
+%D In case of \PDF, we need to prepare resourcs.
+
+\newtoks\MPstartresources
+\newtoks\MPstopresources
+
+\def\startMPresources
+ {\the\MPstartresources}
+
+\def\stopMPresources
+ {\the\MPstopresources}
+
+%D Some day we may consider collecting local resources.
+
+\appendtoks
+ \global\let\currentPDFresources\empty % kind of redundant
+\to \MPstartresources
+
+% \appendtoks
+% \collectPDFresources
+% \global\let\currentPDFresources\collectedPDFresources
+% \to \MPstopresources
+
+\appendtoksonce
+ \the\everyPDFxform
+\to \MPstopresources
+
+%D Since colors are not subjected to transformations, we can
+%D only use colors as signal. In our case, we use a dummy colored
+%D path with a red color component of \type {0.n}, so \type
+%D {0.001} is the first path and \type {0.010} the tenth. Since
+%D \METAPOST strips trailing zeros, we have to padd the string.
+
+\newif\ifMPcmykcolors
+\newif\ifMPspotcolors
+
+\def\dohandleMPrgb #1#2#3{\revokeMPtransparencyspecial\execcolorR #1:#2:#3:0:0\od}
+\def\dohandleMPcmyk#1#2#3#4{\revokeMPtransparencyspecial\execcolorC#1:#2:#3:#4:0:0\od}
+\def\dohandleMPgray #1{\revokeMPtransparencyspecial\execcolorS #1:0:0\od}
+\def\dohandleMPspot#1#2#3#4{\revokeMPtransparencyspecial\execcolorP#1:#2:#3:#4:0:0\od}
+
+%D Specials:
+
+\settrue \manyMPspecials \newcount\nofMParguments \let\extraMPpathcode\empty
+
+\def\@@MP {@@MP}
+\def\@@MPSK{@MPSK@}
+
+\def\MPspecial{\@@MPSK\@@MPSK\gMPs\nofMParguments}
+
+\def\defineMPspecial#1#2%
+ {\setvalue{\@@MPSK\@@MPSK#1}{#2}}
+
+%D Special number~1 is dedicated to \CMYK\ support. If you
+%D want to know why: look at this:
+%D
+%D \startbuffer[mp]
+%D fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ;
+%D \stopbuffer
+%D
+%D \startbuffer[cmyk]
+%D \startcombination[4*1]
+%D {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3}
+%D {\definecolor[test][c=.9,y=.15] \processMPbuffer[mp]} {c=.9 y=.15}
+%D {\definecolor[test][c=.25,y=.8] \processMPbuffer[mp]} {c=.25 y=.8}
+%D {\definecolor[test][c=.45,y=.1] \processMPbuffer[mp]} {c=.45 y=.1}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \placefigure
+%D {\CMYK\ support disabled,
+%D conversion to \RGB.}
+%D {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no support in \METAPOST.}
+%D {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no conversion to \RGB,
+%D support in \METAPOST}
+%D {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]}
+
+\defineMPspecial{1}
+ {\ifMPcmykcolors
+ \setxvalue{\@@MPSK\gMPs6}{\noexpand\dohandleMPcmykcolor{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}}%
+ \fi}
+
+\defineMPspecial{2}
+ {\ifMPspotcolors
+ \setxvalue{\@@MPSK\gMPs6}{\noexpand\dohandleMPspotcolor{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}}%
+% \checkMPspot{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}%
+ \fi}
+
+% \def\checkMPspot#1#2#3#4%
+% {\expanded{\resolveMPspotcolor#1 #2 #3 #4}\end
+% \ifx\MPspotspace\MPresolvedspace
+% \edef\MPspotspacespec{/\MPspotspace\space}%
+% \doifinstringelse\MPspotspacespec\currentMPcolorspaces
+% \donothing\registerMPcolorspace
+% \fi}
+
+\let\revokeMPtransparencyspecial\relax
+
+\def\dohandleMPrgbcolor #1#2#3{\revokeMPtransparencyspecial\execcolorR #1:#2:#3:0:0\od}
+\def\dohandleMPcmykcolor#1#2#3#4{\revokeMPtransparencyspecial\execcolorC#1:#2:#3:#4:0:0\od}
+\def\dohandleMPgraycolor #1{\revokeMPtransparencyspecial\execcolorS #1:0:0\od}
+\def\dohandleMPspotcolor#1#2#3#4{\revokeMPtransparencyspecial\execcolorP#1:#2:#3:#4:0:0\od}
+
+%D Transparency support used specials 60 (rgb) and 61
+%D (cmyk).
+%D
+%D \startbufferFshade
+
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor transparent(1,.5,yellow) ;
+%D fill p rotated 210 withcolor transparent(1,.5,green) ;
+%D fill p rotated 330 withcolor transparent(1,.5,blue) ;
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+%D
+%D One can also communicate colors between \CONTEXT\ and
+%D \METAPOST:
+%D
+%D \startbuffer
+%D \definecolor[tcyan] [c=1,k=.2,t=.5]
+%D \definecolor[tmagenta][m=1,k=.2,t=.5]
+%D \definecolor[tyellow] [y=1,k=.2,t=.5]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor \MPcolor{tcyan} ;
+%D fill p rotated 210 withcolor \MPcolor{tmagenta} ;
+%D fill p rotated 330 withcolor \MPcolor{tyellow} ;
+%D \stopbuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+%D
+%D We save all the three components needed in one macro,
+%D just to save hash space.
+
+\def\dohandleMPrgbtransparency #1#2#3#4#5{\execcolorR #1:#2:#3:#4:#5\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial}
+\def\dohandleMPcmyktransparency#1#2#3#4#5#6{\execcolorC#1:#2:#3:#4:#5:#6\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial}
+\def\dohandleMPgraytransparency #1#2#3{\execcolorS #1:#2:#3\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial}
+\def\dohandleMPspottransparency#1#2#3#4#5#6{\execcolorP#1:#2:#3:#4:#5:#6\od\let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial}
+
+\def\dorevokeMPtransparencyspecial
+ {\PDFcode{\PDFtransparencyresetidentifier\space gs}%
+ \let\revokeMPtransparencyspecial\relax}
+
+\defineMPspecial{3} % rgb
+ {\setxvalue{\@@MPSK\gMPs6}{\noexpand\dohandleMPrgbtransparency{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs1}{\gMPs2}}}
+
+\defineMPspecial{4} % cmyk
+ {\setxvalue{\@@MPSK\gMPs7}{\noexpand\dohandleMPcmyktransparency{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs1}{\gMPs2}}}
+
+\defineMPspecial{5} % spot
+ {\setxvalue{\@@MPSK\gMPs7}{\noexpand\dohandleMPspottransparency{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs1}{\gMPs2}}%
+ }%\checkMPspot{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}}
+
+%D Shading is an example of a more advanced graphic feature,
+%D but users will seldom encounter those complications. Here
+%D we only show a few simple examples, but many other
+%D alternatives are possible by setting up the functions built
+%D in \PDF\ in the appropriate way.
+%D
+%D Shading has to do with interpolation between two or more
+%D points or user supplied ranges. In \PDF, the specifications
+%D of a shade has to be encapsulated in objects and passed on
+%D as resources. This is a \PDF\ level 1.3. feature. One can
+%D simulate three dimensional shades as well and define simple
+%D functions using a limited set of \POSTSCRIPT\ primitives.
+%D Given the power of \METAPOST\ and these \PDF\ features, we
+%D can achieve superb graphic effects.
+%D
+%D Since everything is hidden in \TEX\ and \METAPOST\ graphics,
+%D we can stick to high level \CONTEXT\ command, as shown in
+%D the following exmples.
+%D
+%D \startbuffer
+%D \startuniqueMPgraphic{CircularShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D circular_shade(p,0,.2red,.9red) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{LinearShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D linear_shade(p,0,.2blue,.9blue) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{DuotoneShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D linear_shade(p,2,.5green,.5red) ;
+%D \stopuniqueMPgraphic
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D These graphics can be hooked into the overlay mechanism,
+%D which is available in many commands.
+%D
+%D \startbuffer
+%D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}]
+%D \defineoverlay[demo 2][\uniqueMPgraphic {LinearShade}]
+%D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D These backgrounds can for instance be applied to \type
+%D {\framed}:
+%D
+%D \startbuffer
+%D \setupframed[width=3cm,height=2cm,frame=off]
+%D \startcombination[3*1]
+%D {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {}
+%D {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {}
+%D {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D There are a few more alternatives, determined by the second
+%D parameter passed to \type {circular_shade} and alike.
+%D
+%D \def\SomeShade#1#2#3#4#5%
+%D {\startuniqueMPgraphic{Shade-#1}
+%D width := \overlaywidth ;
+%D height := \overlayheight ;
+%D path p ; p := unitsquare xscaled width yscaled height ;
+%D #2_shade(p,#3,#4,#5) ;
+%D \stopuniqueMPgraphic
+%D \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]%
+%D \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}}
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0}
+%D {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1}
+%D {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2}
+%D {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3}
+%D {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0}
+%D {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1}
+%D {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2}
+%D {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3}
+%D {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D \startlinecorrection
+%D \startcombination[4*1]
+%D {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0}
+%D {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1}
+%D {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2}
+%D {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D These macros closely cooperate with the \METAPOST\ module
+%D \type {mp-spec.mp}, which is part of the \CONTEXT\
+%D distribution.
+%D
+%D The low level (\PDF) implementation is based on the \TEX\
+%D based \METAPOST\ to \PDF\ converter. Shading is supported
+%D by overloading the \type {fill} operator as implemented
+%D earlier. In \PDF\ type~2 and~3 shading functions are
+%D specified in terms of:
+%D
+%D \starttabulate[|Tl|l|]
+%D \NC /Domain \NC sort of meeting range \NC \NR
+%D \NC /C0 \NC inner shade \NC \NR
+%D \NC /C1 \NC outer shade \NC \NR
+%D \NC /N \NC smaller values, bigger inner circles \NC \NR
+%D \stoptabulate
+
+\newcount\currentPDFshade % 0 % global (document wide) counter
+
+% \def\dosetMPsomePDFshade#1#2% generic but needs refs
+% {\global\advance\currentPDFshade \plusone
+% \doPDFdictionaryobject{FDF}{ftn:Sh:\the\currentPDFshade}
+% {/FunctionType 2
+% /Domain [\gMPs1 \gMPs2]
+% /C0 [\MPshadeA]
+% /C1 [\MPshadeB]
+% /N \gMPs3}%
+% \doPDFgetobjectreference{FDF}{ftn:Sh:\the\currentPDFshade}\PDFobjectreference
+% \doPDFdictionaryobject{FDF}{obj:Sh:\the\currentPDFshade}
+% {/ShadingType #1
+% /ColorSpace /\MPresolvedspace
+% /Function \PDFobjectreference\space
+% /Coords [\MPshadeC]
+% /Extend [true true]}%
+% \doPDFgetobjectreference{FDF}{obj:Sh:\the\currentPDFshade}\PDFobjectreference
+% \appendtoPDFdocumentshades{/Sh\the\currentPDFshade\space\PDFobjectreference}%
+% \setxvalue{\@@MPSK#2}{\noexpand\dohandleMPshade{\the\currentPDFshade}}}
+
+\def\dosetMPsomePDFshade#1#2%
+ {\immediate\pdfobj
+ {<>}%
+ \immediate\pdfobj
+ {<>}%
+ \global\advance\currentPDFshade \plusone
+ \appendtoPDFdocumentshades{/Sh\the\currentPDFshade\space\the\pdflastobj\space0 R }%
+ \setxvalue{\@@MPSK#2}{\noexpand\dohandleMPshade{\the\currentPDFshade}}}
+
+\def\dosetMPlinearshade {\dosetMPsomePDFshade2}% #1
+\def\dosetMPcircularshade{\dosetMPsomePDFshade3}% #1
+
+\defineMPspecial{30}
+ {\expanded{\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
+ \expanded{\resolveMPrgbcolor{\gMPs{9}}{\gMPs{10}}{\gMPs{11}}}\to\MPshadeB
+ \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs{12} \gMPs{13}}%
+ \dosetMPlinearshade{\gMPs{14}}}
+
+\defineMPspecial{31}
+ {\expanded{\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
+ \expanded{\resolveMPrgbcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}}\to\MPshadeB
+ \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs9 \gMPs{13} \gMPs{14} \gMPs{15}}%
+ \dosetMPcircularshade{\gMPs{16}}}
+
+\defineMPspecial{32}
+ {\expanded{\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+ \expanded{\resolveMPcmykcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
+ \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
+ \dosetMPlinearshade{\gMPs{16}}}
+
+\defineMPspecial{33}
+ {\expanded{\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+ \expanded{\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB
+ \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}%
+ \dosetMPcircularshade{\gMPs{18}}}
+
+\defineMPspecial{34}
+ {\expanded{\resolveMPspotcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+ \expanded{\resolveMPspotcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
+ \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
+ \dosetMPlinearshade{\gMPs{16}}}
+
+\defineMPspecial{35}
+ {\expanded{\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+ \expanded{\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB
+ \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}%
+ \dosetMPcircularshade{\gMPs{18}}}
+
+
+\newconditional\ignoreMPpath
+
+\def\dohandleMPshade#1%
+ {\revokeMPtransparencyspecial
+ \settrue\ignoreMPpath
+ \def\extraMPpathcode{/Sh#1 sh Q}%
+ \chardef\finiMPpath\zerocount
+ \PDFcode{q /Pattern cs}}
+
+%D Figure inclusion is kind of strange to \METAPOST, but when
+%D Santiago Muelas started discussing this with me, I was able
+%D to cook up a solution using specials.
+
+\defineMPspecial{10}
+ {\setxvalue{\@@MPSK\gMPs8}%
+ {\noexpand\handleMPfigurespecial{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}{\gMPs8}}}
+
+\def\handleMPfigurespecial#1#2#3#4#5#6#7#8% todo : combine with ext fig
+ {\global\letvalue{\@@MPSK#8}\empty
+ \vbox to \zeropoint
+ {\vss
+ \hbox to \zeropoint
+ {\ifcase\pdfoutput\or % will be hooked into the special driver
+ \doiffileelse{#7}
+ {\doifundefinedelse{mps:x:#7}
+ {\immediate\pdfximage\!!width\onebasepoint\!!height\onebasepoint{#7}%
+ \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}%
+ {\message{[reusing figure #7]}}%
+ \PDFcode{q #1 #2 #3 #4 #5 #6 cm}%
+ \rlap{\getvalue{mps:x:#7}}%
+ \PDFcode{Q}}
+ {\message{[unknown figure #7]}}%
+ \fi
+ \hss}}}
+
+%D An example of using both special features is the
+%D following.
+%D
+%D \starttyping
+%D \startMPpage
+%D externalfigure "hakker1b.png" scaled 22cm rotated 10 shifted (-2cm,0cm);
+%D externalfigure "hakker1b.png" scaled 10cm rotated -10 ;
+%D externalfigure "hakker1b.png" scaled 7cm rotated 45 shifted (8cm,12cm) ;
+%D path p ; p := unitcircle xscaled 15cm yscaled 20cm;
+%D path q ; q := p rotatedaround(center p,90) ;
+%D path r ; r := buildcycle(p,q) ; clip currentpicture to r ;
+%D path s ; s := boundingbox currentpicture enlarged 5mm ;
+%D picture c ; c := currentpicture ; currentpicture := nullpicture ;
+%D circular_shade(s,0,.2red,.9red) ;
+%D addto currentpicture also c ;
+%D \stopMPpage
+%D \stoptyping
+
+%D This is some experimental hyperlink driver that I wrote
+%D for Mark Wicks.
+
+\defineMPspecial{20}
+ {\setxvalue{\@@MPSK\gMPs6}%
+ {\noexpand\handleMPhyperlink{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}}}
+
+\def\handleMPhyperlink#1#2#3#4#5#6%
+ {\global\letvalue{\@@MPSK#6}\empty
+ \setbox\scratchbox\hbox
+ {\setbox\scratchbox\null
+ \wd\scratchbox\dimexpr-#1\onebasepoint+#3\onebasepoint\relax
+ \ht\scratchbox\dimexpr-#2\onebasepoint+#4\onebasepoint\relax
+ \incolorfalse
+ \gotobox{\box\scratchbox}[#5]}%
+ \setbox\scratchbox\hbox
+ {\hskip\dimexpr\MPxoffset\onebasepoint+#1\onebasepoint\relax
+ \raise\dimexpr\MPyoffset\onebasepoint+#2\onebasepoint\relax
+ \box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox}
+
+%D This special (number 50) passes positions to a tex file.
+%D This method uses a two||pass approach an (mis|)|used the
+%D context positioning macros. In \type {core-pos} we will
+%D implement the low level submacro needed.
+%D
+%D \startbuffer
+%D \definelayer[test]
+%D
+%D \setlayer
+%D [test]
+%D [x=\MPx{somepos-1},y=\MPy{somepos-1}]
+%D {Whatever we want here!}
+%D
+%D \setlayer
+%D [test]
+%D [x=\MPx{somepos-2},y=\MPy{somepos-2}]
+%D {Whatever we need there!}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 6cm withcolor red ;
+%D register ("somepos-1",1cm,2cm,center currentpicture) ;
+%D register ("somepos-2",4cm,3cm,(-1cm,-2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \framed[background=test,offset=overlay]{\useMPgraphic{oeps}}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here the width and height are not realy used, but one can
+%D imagine situations where tex has to work with values
+%D calculated by \METAPOST.
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D Later we will implement a more convenient macro:
+%D
+%D \starttyping
+%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
+%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
+%D \stoptyping
+
+\defineMPspecial{50} % x y width height label
+ {\dosavepositionwhd
+ {\gMPs5}%
+ {0}%
+ {\the\dimexpr-\MPllx\onebasepoint+\gMPs1\onebasepoint\relax}
+ {\the\dimexpr\gMPs2\onebasepoint-\scratchdimen+\MPury\onebasepoint\relax}%
+ {\the\dimexpr\gMPs3\onebasepoint\relax}%
+ {\the\dimexpr\gMPs4\onebasepoint\relax}%
+ {0pt}}
+
+%D A few auxiliary macros. This will move to colo-ini.
+
+\def\MPgrayspace{DeviceGray}
+\def\MPrgbspace {DeviceRGB}
+\def\MPcmykspace{DeviceCMYK}
+\let\MPspotspace\MPgrayspace
+
+\def\MPcmykBlack{0 0 0 0}
+\def\MPcmykWhite{0 0 0 1}
+
+\def\startMPcolorresolve
+ {\bgroup
+ \def\dostartgraycolormode##1%
+ {\global\let\MPresolvedspace\MPgrayspace
+ \xdef\MPresolvedcolor{##1}}%
+ \def\dostartrgbcolormode ##1##2##3%
+ {\global\let\MPresolvedspace\MPrgbspace
+ \xdef\MPresolvedcolor{##1 ##2 ##3}}%
+ \def\dostartcmykcolormode##1##2##3##4%
+ {\global\let\MPresolvedspace\MPcmykspace
+ \xdef\MPresolvedcolor{##1 ##2 ##3 ##4}}%
+ \def\dostartspotcolormode##1##2%
+ {\global\let\MPspotspace\empty % left over ?
+ \xdef\MPresolvedspace{##1}%
+ \xdef\MPresolvedcolor{##2}%
+ \global\let\MPspotspace\MPresolvedspace}% signal
+ \dostartgraycolormode\!!zerocount} % kind of hackery initialization
+
+\let\stopMPcolorresolve\egroup
+
+\def\resolveMPrgbcolor#1#2#3\to#4%
+ {\startMPcolorresolve
+ \execcolorR#1:#2:#3:0:0\od
+ \stopMPcolorresolve
+ \let#4\MPresolvedcolor}
+
+\def\resolveMPcmykcolor#1#2#3#4\to#5%
+ {\startMPcolorresolve
+ \execcolorC#1:#2:#3:#4:0:0\od
+ \stopMPcolorresolve
+ \let#5\MPresolvedcolor}
+
+\def\resolveMPgraycolor#1\end\to#2%
+ {\startMPcolorresolve
+ \execcolorS#1:0:0\od
+ \stopMPcolorresolve
+ \let#2\MPresolvedcolor}
+
+\def\resolveMPspotcolor#1#2#3#4\end\to#5%
+ {\startMPcolorresolve
+ \ifnum#2>\plusone
+ \checkmultitonecolor{#1}%
+ \fi
+ \execcolorP#1:#2:#3:#4:0:0\od
+ \stopMPcolorresolve
+ \let#5\MPresolvedcolor}
+
+%D \macros
+%D {dogetPDFmediabox}
+%D
+%D The next macro can be used to find the mediabox of a \PDF\
+%D illustration.
+%D
+%D \starttyping
+%D \dogetPDFmediabox
+%D {filename}
+%D {new dimen}{new dimen}{new dimen}{new dimen}
+%D \stoptyping
+%D
+%D Beware of dimen clashes: this macro uses the 5~default
+%D scratch registers! When no file or mediabox is found, the
+%D dimensions are zeroed.
+
+\def\dogetPDFmediabox#1#2#3#4#5%
+ {\bgroup
+ \def\PDFxscale{1}%
+ \def\PDFyscale{1}%
+ \uncatcodespecials
+ \endlinechar\minusone
+ \def\checkPDFtypepage##1/Type /Page##2##3\done%
+ {\ifx##2\relax
+ \else\if##2s% accept /Page and /Pages
+ \let\doprocessPDFline\findPDFmediabox
+ \else
+ \let\doprocessPDFline\findPDFmediabox
+ \fi\fi}%
+ \def\findPDFtypepage
+ {\expandafter\checkPDFtypepage\fileline/Type /Page\relax\done}%
+ \def\checkPDFmediabox##1/MediaBox##2##3\done%
+ {\ifx##2\relax \else
+ \setPDFmediabox##2##3\done
+ \fileprocessedtrue
+ \fi}%
+ \def\findPDFmediabox
+ {\expandafter\checkPDFmediabox\fileline/MediaBox\relax\done}%
+ \let\doprocessPDFline\findPDFtypepage
+ \doprocessfile\scratchread{#1}\doprocessPDFline
+ \egroup
+ \ifx\PDFxoffset\undefined
+ #2=\zeropoint
+ #3=\zeropoint
+ #4=\zeropoint
+ #5=\zeropoint
+ \else
+ #2=\PDFxoffset\onebasepoint
+ #3=\PDFyoffset\onebasepoint
+ #4=\PDFwidth
+ #5=\PDFheight
+ \fi}
+
+\def\setPDFboundingbox#1#2#3#4#5#6%
+ {\dimen0=#1\dimen0=#5\dimen0
+ \ScaledPointsToBigPoints{\number\dimen0}\PDFxoffset
+ \dimen0=#3\dimen0=#5\dimen0
+ \xdef\PDFwidth{\the\dimen0}%
+ \dimen0=#2\dimen0=#6\dimen0
+ \ScaledPointsToBigPoints{\number\dimen0}\PDFyoffset
+ \dimen0=#4\dimen0=#6\dimen0
+ \xdef\PDFheight{\the\dimen0}%
+ \global\let\PDFxoffset\PDFxoffset
+ \global\let\PDFyoffset\PDFyoffset}
+
+\def\setPDFmediabox#1[#2 #3 #4 #5]#6\done
+ {\dimen2=#2\onebasepoint\dimen2=-\dimen2 % \dimen2=-#2\onebasepoint also works since tex handles --
+ \dimen4=#3\onebasepoint\dimen4=-\dimen4 % \dimen4=-#3\onebasepoint also works since tex handles --
+ \dimen6=#4\onebasepoint\advance\dimen6 \dimen2
+ \dimen8=#5\onebasepoint\advance\dimen8 \dimen4
+ \setPDFboundingbox{\dimen2}{\dimen4}{\dimen6}{\dimen8}\PDFxscale\PDFyscale}
+
+%D End of soon obsolete code.
+
+\startMPinitializations
+ mp_shade_version := 2 ;
+\stopMPinitializations
+
+%D Here comes the traditional \MKII\ converter.
+%D
+%D Because we want to test as fast as possible, we first
+%D define the \POSTSCRIPT\ operators that \METAPOST\ uses.
+%D We don't define irrelevant ones, because these are
+%D skipped anyway.
+%D
+%D The converter can be made a bit faster by replacing the
+%D two test macros (the ones with the many \type {\if's}) by
+%D a call to named branch macros (something \typ {\getvalue
+%D {xPSmoveto}}. For everyday documents with relatively
+%D small graphics the gain in speed can be neglected.
+
+\def \PScurveto {curveto}
+\def \PSlineto {lineto}
+\def \PSmoveto {moveto}
+\def \PSshowpage {showpage}
+\def \PSnewpath {newpath}
+\def \PSfshow {fshow}
+\def \PSclosepath {closepath}
+\def \PSfill {fill}
+\def \PSstroke {stroke}
+\def \PSclip {clip}
+\def \PSrlineto {rlineto}
+\def \PSsetlinejoin {setlinejoin}
+\def \PSsetlinecap {setlinecap}
+\def \PSsetmiterlimit {setmiterlimit}
+\def \PSsetgray {setgray}
+\def \PSsetrgbcolor {setrgbcolor}
+\def \PSsetcmykcolor {setcmykcolor}
+\def \PSsetdash {setdash}
+\def \PSgsave {gsave}
+\def \PSgrestore {grestore}
+\def \PStranslate {translate}
+\def \PSscale {scale}
+\def \PSconcat {concat}
+\def \PSdtransform {dtransform}
+\def \PSsetlinewidth {setlinewidth}
+\def \PSpop {pop}
+
+\def \PSnfont {nfont} % was needed for TUG98 proceedings
+\def \PSspecial {special} % extensions to MetaPost
+
+%D A previous version set \type {%} to ignore, which
+%D simplified the following definitions. At the start of
+%D conversion the percent character was made active again.
+%D Because the whole graphic is one paragraph (there are no
+%D empty lines) this does not give the desired effect. This
+%D went unnoticed untill Scott Pakin sent me a test file
+%D percent characters in a string. So, from now on we have
+%D to prefix the following strings with percentages.
+
+%D Some day I'll figure out a better solution (line by line reading
+%D using \ETEX).
+
+\edef \PSBoundingBox {\letterpercent\letterpercent BoundingBox:}
+\edef \PSHiResBoundingBox {\letterpercent\letterpercent HiResBoundingBox:}
+\edef \PSExactBoundingBox {\letterpercent\letterpercent ExactBoundingBox:}
+\edef \PSMetaPostSpecial {\letterpercent\letterpercent MetaPostSpecial:}
+\edef \PSMetaPostSpecials {\letterpercent\letterpercent MetaPostSpecials:}
+\edef \PSPage {\letterpercent\letterpercent Page:}
+\edef \PSBeginProlog {\letterpercent\letterpercent BeginProlog}
+\edef \PSEndProlog {\letterpercent\letterpercent EndProlog}
+\edef \PSEof {\letterpercent\letterpercent EOF}
+
+%D By the way, the \type {setcmykcolor} operator is not
+%D output by \METAPOST\ but can result from converting the
+%D \cap{RGB} color specifications, as implemented in
+%D \type{supp-mps}.
+
+%D In \POSTSCRIPT\ arguments precede the operators. Due to the
+%D fact that in some translations we need access to those
+%D arguments, and also because sometimes we have to skip them,
+%D we stack them up. The stack is one||dimensional for non path
+%D operators and two||dimensional for operators inside a path.
+%D This is because we have to save the whole path for
+%D (optional) postprocessing. Values are pushed onto the stack
+%D by:
+%D
+%D \starttyping
+%D \setMPargument {value}
+%D \stoptyping
+%D
+%D They can be retrieved by the short named macros:
+%D
+%D \starttyping
+%D \gMPa {number}
+%D \gMPs {number}
+%D \stoptyping
+%D
+%D When scanning a path specification, we also save the
+%D operator, using
+%D
+%D \starttyping
+%D \setMPkeyword {n}
+%D \stoptyping
+%D
+%D The path drawing operators are coded for speed: \type{clip},
+%D \type{stroke}, \type{fill} and \type{fillstroke} become
+%D 1, 2, 3 and~4.
+%D
+%D When processing the path this code can be retrieved
+%D using
+%D
+%D \starttyping
+%D \getMPkeyword % {n}
+%D \stoptyping
+%D
+%D When setting an argument, the exact position on the stack
+%D depends on the current value of the \COUNTERS\
+%D \type{\nofMPsegments} and \type{\nofMParguments}.
+
+\newcount\nofMPsegments
+\newcount\nofMParguments
+
+%D These variables hold the coordinates. The argument part of
+%D the stack is reset by:
+%D
+%D \starttyping
+%D \resetMPstack
+%D \stoptyping
+%D
+%D We use the prefix \type{@@MP} to keep the stack from
+%D conflicting with existing macros. To speed up things a bit
+%D more, we use the constant \type{\@@MP}.
+
+\def\@@MP{@@MP}
+
+\def\setMPargument% #1%
+ {\advance\nofMParguments \plusone
+ \expandafter\def\csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname} % {#1}
+
+\def\letMPargument
+ {\advance\nofMParguments \plusone
+ \expandafter\let\csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname}
+
+\def\setMPsequence#1 %
+ {\advance\nofMParguments \plusone
+ \expandafter\def\csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname{#1}%
+ \handleMPsequence}
+
+\def\gMPa#1%
+ {\csname\@@MP0\number#1\endcsname}
+
+\def\gMPs#1%
+ {\csname\@@MP\the\nofMPsegments\number#1\endcsname}
+
+\def\dogMPa#1%
+ {\@EAEAEA\do\csname\@@MP0\number#1\endcsname}
+
+\def\setMPkeyword#1 %
+ {\expandafter\def\csname\@@MP\the\nofMPsegments0\endcsname{#1}%
+ \advance\nofMPsegments \plusone
+ \nofMParguments\zerocount}
+
+\def\getMPkeyword% #1%
+ {\csname\@@MP\the\nofMPsegments0\endcsname} % {\csname\@@MP#10\endcsname}
+
+\def\docleanupMPargument#1% we need this because args can have [ or ] pre/appended
+ {\expandafter\edef\csname\@@MP\the\nofMPsegments\number#1\endcsname
+ {\csname\@@MP\the\nofMPsegments\number#1\endcsname}}
+
+%D When we reset the stack, we can assume that all further
+%D comment is to be ignored and handled in strings.
+%D By redefining the reset macro after the first call, we
+%D save some run time. Only use this macro after all
+%D comments are processed and use the simple alternative
+%D when dealing with comments.
+
+\def\doresetMPstack
+ {\nofMParguments\zerocount}
+
+\def\resetMPstack
+ {\let\handleMPgraphic\handleMPendgraphic
+ \let\resetMPstack\doresetMPstack
+ \resetMPstack}
+
+%D The arguments are saved with the preceding command
+%D \type{\do}. By default this command expands to nothing, but
+%D when we deal with strings it's used to strip off the
+%D \type{(} and \type{)}.
+%D
+%D Strings are kind of tricky, because characters can be
+%D passed verbatim \type{(hello)}, by octal number
+%D \type{(\005)} or as command \type{(\()}. We therefore
+%D cannot simply ignore \type{(} and \type{)}, the way we do
+%D with \type{[} and \type{]}. Another complication is that
+%D strings may contain characters that normally have a
+%D special meaning in \TEX, like \type{$} and \type{{}}.
+%D
+%D A previous solution made \type{\} an active character and
+%D let it look ahead for a number or characters. We had to
+%D abandon this scheme because of the need for verbatim
+%D support. The next solution involved some \CATCODE\
+%D trickery but works well.
+
+\def\octalMPcharacter#1#2#3%
+ {\char'#1#2#3\relax}
+
+%D curly braces and squarly brackets are stored in the argument stack
+%D as part of strings, for instance in:
+%D
+%D \starttyping
+%D /fshow {exch findfont exch scalefont setfont show}bind def
+%D [3 3 ] 0 setdash
+%D \stoptyping
+%D
+%D but we need to keep them in situation like
+%D
+%D \starttyping
+%D ([bla bla] bla bla) ec-lmr10 9.96265 fshow
+%D ({bla bla} bla bla) ec-lmr10 9.96265 fshow
+%D \stoptyping
+%D
+%D So, when we store the snippets, we keep the special tokens, and
+%D when needed we either ignore or obey them
+
+%D We could use a catcodetable here.
+
+\bgroup
+\catcode`\|=\@@comment
+\catcode`\%=\@@active
+\catcode`\[=\@@active
+\catcode`\]=\@@active
+\catcode`\{=\@@active
+\catcode`\}=\@@active
+\catcode`B=\@@begingroup
+\catcode`E=\@@endgroup
+\gdef\keepMPspecials|
+ B\let%\letterpercent|
+ \def[B\noexpand[E|
+ \def]B\noexpand]E|
+ \def{B\noexpand{E|
+ \def}B\noexpand}EE
+\gdef\ignoreMPspecials|
+ B\let%\letterpercent|
+ \def[BE|
+ \def]BE|
+ \def{BE|
+ \def}BEE
+\gdef\obeyMPspecials|
+ B\def%B\char 37\relax E|
+ \def[B\char 91\relax E|
+ \def]B\char 93\relax E|
+ \def{B\char123\relax E|
+ \def}B\char125\relax EE
+\gdef\setMPspecials|
+ B\setnaturalcatcodes
+ \catcode`\\=\@@escape
+ \catcode`\%=\@@active
+ \catcode`\[=\@@active
+ \catcode`\]=\@@active
+ \catcode`\{=\@@active
+ \catcode`\}=\@@active
+ \lccode`\-=0 | latex sets this to `\-
+ \lccode`\%=`\%| otherwise it's seen as a number
+ \def\(B\char40\relax E|
+ \def\)B\char41\relax E|
+ \def\\B\char92\relax E|
+ \def\0B\octalMPcharacter0E|
+ \def\1B\octalMPcharacter1E|
+ \def\2B\octalMPcharacter2E|
+ \def\3B\octalMPcharacter3E|
+ \def\4B\octalMPcharacter4E|
+ \def\5B\octalMPcharacter5E|
+ \def\6B\octalMPcharacter6E|
+ \def\7B\octalMPcharacter7E|
+ \def\8B\octalMPcharacter8E|
+ \def\9B\octalMPcharacter9EE
+\egroup
+
+%D We use the comment symbol as a sort of trigger. Beware!
+%D The whole graphic is seen as on eparagraph, which means
+%D that we cannot change the catcodes in between.
+
+\bgroup
+\catcode`\%=\@@active
+\gdef\startMPscanning{\let%=\startMPconversion}
+\egroup
+
+%D In earlier versions we used the sequence
+%D
+%D \starttyping
+%D \expandafter\handleMPsequence\input filename\relax
+%D \stoptyping
+%D
+%D Persistent problems in \LATEX\ however forced us to use a
+%D different scheme. Every \POSTSCRIPT\ file starts with a
+%D \type{%}, so we temporary make this an active character
+%D that starts the scanning and redefines itself. (The problem
+%D originates in the redefinition by \LATEX\ of the
+%D \type{\input} primitive.)
+
+\def\startMPconversion
+ {\keepMPspecials
+ \handleMPsequence}
+
+%D Here comes the main loop. Most arguments are numbers. This
+%D means that they can be recognized by their \type{\lccode}.
+%D This method saves a lot of processing time. We could
+%D speed up the conversion by handling the \type{path}
+%D seperately.
+
+\def\dohandleMPsequence#1%
+ {\ifdone
+ \ifcase\lccode`#1\relax
+ \@EAEAEA\dohandleMPsequenceA
+ \else
+ \@EAEAEA\dohandleMPsequenceB
+ \fi
+ \else
+ \@EA\dohandleMPsequenceC
+ \fi#1}
+
+\let\dohandleMPsequenceA\setMPsequence
+
+\def\installMPSkeywordN#1#2%
+ {\expandafter\def\csname\@@MP:N:#1\endcsname{#2}}
+
+\def\installMPSshortcutN#1#2% todo: \let
+ {\expandafter\let\csname\@@MP:N:#1\expandafter\endcsname\csname\@@MP:N:#2\endcsname}
+
+\def\dohandleMPsequenceB#1 %
+ {\edef\somestring{#1}%
+ \executeifdefined{\@@MP:N:\somestring}\handleMPgraphic
+ \handleMPsequence}
+
+\installMPSkeywordN \PSmoveto
+ {\edef\lastMPmoveX{\gMPa1}%
+ \edef\lastMPmoveY{\gMPa2}%
+ \resetMPstack}
+\installMPSkeywordN \PSnewpath
+ {\let\handleMPsequence\handleMPpath}
+\installMPSkeywordN \PSgsave
+ {\PDFcode{q}%
+ \resetMPstack}
+\installMPSkeywordN \PSgrestore
+ {\PDFcode{Q}%
+ \resetMPstack}
+\installMPSkeywordN \PSdtransform % == setlinewidth
+ {\let\handleMPsequence\handleMPdtransform}
+ % after that we will encounter more tokens until setlinewidth+pop
+ % or pop+setlinewidth which we catch next; we explicitly need to
+ % reset the stack since [] n setdash may follow; a more clever
+ % approach would be to read on till the condition is met, but it's
+ % the only pop / setlinewidth we will encounter so ...
+\installMPSkeywordN \PSsetlinewidth
+ {% already handled in dtransform
+ \resetMPstack}
+\installMPSkeywordN \PSpop
+ {% already handled in dtransform
+ \resetMPstack}
+\installMPSkeywordN \PSconcat
+ {\cleanupMPconcat
+ \PDFcode{\gMPa1 \gMPa2 \gMPa3 \gMPa4 \gMPa5 \gMPa6 cm}%
+ \resetMPstack}
+\installMPSkeywordN \PSsetrgbcolor
+ {\handleMPrgbcolor
+ \resetMPstack}
+\installMPSkeywordN \PSsetcmykcolor
+ {\handleMPcmykcolor
+ \resetMPstack}
+\installMPSkeywordN \PSsetgray
+ {\handleMPgraycolor
+ \resetMPstack}
+\installMPSkeywordN \PStranslate
+ {\PDFcode{1 0 0 1 \gMPa1 \gMPa2 cm}%
+ \resetMPstack}
+\installMPSkeywordN \PSsetdash
+ {\handleMPsetdash
+ \resetMPstack}
+\installMPSkeywordN \PSsetlinejoin
+ {\PDFcode{\gMPa1 j}%
+ \resetMPstack}
+\installMPSkeywordN \PSsetmiterlimit
+ {\PDFcode{\gMPa1 M}%
+ \resetMPstack}
+\installMPSkeywordN \PSfshow
+ {%\PDFcode{n}% removed !
+ \handleMPfshow
+ \resetMPstack}
+\installMPSkeywordN \PSsetlinecap
+ {\PDFcode{\gMPa1 J}%
+ \resetMPstack}
+\installMPSkeywordN \PSrlineto
+ {\flushMPmoveto
+ \PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l S}%
+ \resetMPmoveto
+ \resetMPstack}
+\installMPSkeywordN \PSscale
+ {\PDFcode{\gMPa1 0 0 \gMPa2 0 0 cm}%
+ \resetMPstack}
+\installMPSkeywordN \PSspecial
+ {\handleMPspecialcommand
+ \resetMPstack}
+
+\installMPSshortcutN {n} \PSnewpath
+\installMPSshortcutN {p} \PSclosepath
+\installMPSshortcutN {l} \PSlineto
+\installMPSshortcutN {r} \PSrlineto
+\installMPSshortcutN {m} \PSmoveto
+\installMPSshortcutN {c} \PScurveto
+\installMPSshortcutN {C} \PSsetcmykcolor
+\installMPSshortcutN {G} \PSsetgray
+\installMPSshortcutN {R} \PSsetrgbcolor
+\installMPSshortcutN {lj} \PSsetlinejoin
+\installMPSshortcutN {ml} \PSsetmiterlimit
+\installMPSshortcutN {lc} \PSsetlinecap
+\installMPSshortcutN {sd} \PSsetdash
+\installMPSshortcutN {S} \PSstroke
+\installMPSshortcutN {F} \PSfill
+\installMPSshortcutN {W} \PSclip
+
+\installMPSshortcutN {q} \PSgsave
+\installMPSshortcutN {Q} \PSgrestore
+
+\installMPSshortcutN {s} \PSscale
+\installMPSshortcutN {t} \PSconcat
+\installMPSshortcutN {P} \PSshowpage
+
+\installMPSkeywordN {hlw} {\PDFcode{\gMPa1 w}\resetMPstack}
+\installMPSkeywordN {vlw} {\PDFcode{\gMPa1 w}\resetMPstack}
+\installMPSkeywordN {rd} {\PDFcode{[] 0 d}\resetMPstack}
+
+\def\dohandleMPsequenceC#1 %
+ {\edef\somestring{#1}%
+ \handleMPgraphic
+ \handleMPsequence}
+
+%D Since colors are not sensitive to transformations, they
+%D are sometimes used for signaling. Therefore, we handle them
+%D separately. The next macro can be redefined if needed.
+
+\def\handleMPrgbcolor
+ {\PDFcode{\!MPgMPa1 \!MPgMPa2 \!MPgMPa3 rg
+ \!MPgMPa1 \!MPgMPa2 \!MPgMPa3 RG}}
+
+\def\handleMPcmykcolor
+ {\PDFcode{\!MPgMPa1 \!MPgMPa2 \!MPgMPa3 \!MPgMPa4 k
+ \!MPgMPa1 \!MPgMPa2 \!MPgMPa3 \!MPgMPa4 K}}
+
+\def\handleMPgraycolor
+ {\PDFcode{\!MPgMPa1 g
+ \!MPgMPa1 G}}
+
+\def\handleMPspotcolor
+ {\PDFcode{0 g
+ 0 G}}
+
+%D Beginning and ending the graphics is taken care of by the
+%D macro \type{\handleMPgraphic}, which is redefined when
+%D the first graphics operator is met.
+
+\def\handleMPendgraphic % #1%
+ {\ifx\somestring\PSshowpage
+ \let\handleMPsequence\finishMPgraphic
+ \else\ifx\somestring\PSEof
+ \let\handleMPsequence\finishMPgraphic
+ \else
+ \letMPargument\somestring % {#1}%
+ \fi\fi}
+
+\def\handleMPbegingraphic % #1%
+ {\ifx\somestring\PSBoundingBox
+ \def\handleMPsequence{\handleMPboundingbox1}%
+ \else\ifx\somestring\PSHiResBoundingBox
+ \def\handleMPsequence{\handleMPboundingbox2}%
+ \else\ifx\somestring\PSExactBoundingBox
+ \def\handleMPsequence{\handleMPboundingbox3}%
+ \else\ifx\somestring\PSshowpage
+ \let\handleMPsequence\finishMPgraphic
+ \else\ifx\somestring\PSEof
+ \let\handleMPsequence\finishMPgraphic
+ \else\ifx\somestring\PSPage
+ \let\handleMPsequence\handleMPpage
+ \else\ifx\somestring\PSMetaPostSpecials
+ \let\handleMPsequence\handleMPspecialscomment
+ \else\ifx\somestring\PSMetaPostSpecial
+ \let\handleMPsequence\handleMPspecialcomment
+ \else\ifx\somestring\PSBeginProlog
+ \let\handleMPsequence\handleMPprolog
+ \else
+ \letMPargument\somestring % {#1}%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi}
+
+\let\handleMPgraphic=\handleMPbegingraphic
+
+%D New: we can best filter the prolog because nowdays it can contain
+%D quite some code.
+
+% hm, catcode mess, so we need to tweak %'s catcode here
+% \long\expandafter\def\expandafter\handleMPprolog\expandafter#\expandafter1\PSEndProlog%
+% but today i'm not in the mood for ugly stuff
+
+\long\def\handleMPprolog#1EndProlog %
+ {\doresetMPstack
+ \let\handleMPsequence\dohandleMPsequence
+ \handleMPsequence}
+
+%D We check for three kind of bounding boxes: the normal one
+%D and two high precision ones:
+%D
+%D \starttyping
+%D BoundingBox: llx lly ucx ucy
+%D HiResBoundingBox: llx lly ucx ucy
+%D ExactBoundingBox: llx lly ucx ucy
+%D \stoptyping
+%D
+%D The original as well as the recalculated dimensions are
+%D saved for later use.
+
+\newif\ifskipemptyMPgraphic \skipemptyMPgraphicfalse
+
+\chardef\currentMPboundingbox=0
+
+\def\handleMPboundingbox#1#2 #3 #4 #5
+ {\ifnum#1>\currentMPboundingbox
+ \chardef\currentMPboundingbox#1\relax
+ \xdef\MPllx {#2}%
+ \xdef\MPlly {#3}%
+ \xdef\MPurx {#4}%
+ \xdef\MPury {#5}%
+ \xdef\MPwidth {\the\dimexpr\MPurx\onebasepoint-\MPllx\onebasepoint\relax}%
+ \xdef\MPheight{\the\dimexpr\MPury\onebasepoint-\MPlly\onebasepoint\relax}%
+ \fi
+ \doresetMPstack
+ \let\handleMPsequence\dohandleMPsequence
+ \let\next\handleMPsequence
+ \ifskipemptyMPgraphic
+ \ifdim\MPheight=\zeropoint\ifdim\MPwidth=\zeropoint
+ \def\next{\endinput\finishMPgraphic}%
+ \fi\fi
+ \fi
+ \next}
+
+%D Unless defined otherwise, we simply ignore specialcomments.
+
+\def\handleMPspecialcomment
+ {\doresetMPstack
+ \let\handleMPsequence\dohandleMPsequence
+ \handleMPsequence}
+
+\let\handleMPspecialscomment\handleMPspecialcomment
+
+%D We use the \type{page} comment as a signal that
+%D stackbuilding can be started.
+
+\def\handleMPpage #1 #2
+ {\doresetMPstack
+ \donetrue
+ \let\handleMPsequence\dohandleMPsequence
+ \handleMPsequence}
+
+%D The same applies to the special extensions.
+
+\def\handleMPspecialcommand
+ {\doresetMPstack
+ \let\handleMPsequence\dohandleMPsequence
+ \handleMPsequence}
+
+%D \METAPOST\ draws its dots by moving to a location and
+%D invoking \type{0 0 rlineto}. This operator is not
+%D available in \PDF. Our solution is straightforward: we draw
+%D a line from $(current\_x, current\_y)$ to itself. This
+%D means that the arguments of the preceding \type{moveto} have
+%D to be saved.
+
+%D These saved coordinates are also used when we handle the
+%D texts. Text handling proved to be a bit of a nuisance, but
+%D finally I saw the light. It proved that we also had to
+%D take care of \type{(split arguments)}.
+
+% \startMPcode
+% draw btex Ga toch effe f\kern0ptietsen?{}` etex ;
+% \stopMPcode
+
+\newtoks \everyMPshowfont
+
+\def\setMPfshowfont#1#2%
+ {\font\temp=#1\space at #2\relax\temp
+ \the\everyMPshowfont}
+
+\let\MPfshowcommand\empty
+
+\def\dohandleMPfshow
+ {\setbox\scratchbox\hbox
+ {\obeyMPspecials
+ \edef\MPtextsize{\gMPa\nofMParguments}%
+ \def\do(##1){##1}% only works in latest mp
+ \edef\MPtextdata{\dogMPa1}% beware, stack can have more
+ \handleMPtext}%
+ \setbox\scratchbox\hbox
+ {\hskip\lastMPmoveX\onebasepoint
+ \raise\lastMPmoveY\onebasepoint
+ \box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox}
+
+\def\handleMPtext {\handleMPtextnormal} % so we can overload this one later
+\def\handleMPfshow{\dohandleMPfshow } % so we can overload this one later
+
+\def\handleMPtext
+ {\ifnum\nofMParguments>\plusthree
+ \handleMPtextnormal
+ \else
+ \defconvertedcommand\MPtextdata\MPtextdata
+ \expanded{\splitstring\MPtextdata}\at::::\to\MPtexttag\and\MPtextnumber
+ \executeifdefined{handleMPtext\MPtexttag}\handleMPtextnormal
+ \fi}
+
+% elsewhere we will implement \handleMPtextmptxt
+
+\def\doflushMPtext#1%
+ {\edef\!!stringa{#1}%
+ \@EA\dodoflushMPtext\!!stringa\relax}
+
+\def\dodoflushMPtext
+ {\afterassignment\dododoflushMPtext\let\nexttoken=}
+
+\def\dododoflushMPtext
+ {\ifx\nexttoken\relax
+ % done
+ \else\ifx\nexttoken\char
+ \@EA\@EA\@EA\dodododoflushMPtext
+ \else
+ {\nexttoken}%
+ \@EA\@EA\@EA\dodoflushMPtext
+ \fi\fi}
+
+\def\dodododoflushMPtext
+ {\afterassignment\dododododoflushMPtext\scratchcounter}
+
+\def\dododododoflushMPtext
+ {{\char\scratchcounter}\let\next\dodoflushMPtext}
+
+\def\handleMPtextnormal
+ {\let\ \relax % mp breaks long lines and appends a \
+ \ifx\MPtextsize\PSnfont % round font size (to pt)
+ \advance\nofMParguments \minusone
+ \expandafter\scratchdimen\gMPa\nofMParguments\onepoint\relax
+ \ifdim\scratchdimen<\onepoint
+ \def\MPtextsize{1pt}%
+ \else
+ \advance\scratchdimen .5\onepoint
+ \def\MPtextsize##1.##2\relax{\def\MPtextsize{##1pt}}%
+ \expandafter\MPtextsize\the\scratchdimen\relax
+ \fi
+ \else
+ \edef\MPtextsize{\MPtextsize bp}%
+ \fi
+ \advance\nofMParguments \minusone
+ \setMPfshowfont{\gMPa\nofMParguments}\MPtextsize
+ \advance\nofMParguments \minusone
+ \temp
+ \MPfshowcommand
+ {\ifnum\nofMParguments=\plusone
+ \def\do(##1){##1}%
+ \doflushMPtext{\dogMPa1}%
+ \else % can't happen anymore in mp version 1+
+ % we need to catch ( a ) (a a a) (\123 \123 \123) etc
+ \scratchcounter\plusone
+ \def\dodo##1% Andreas Fieger's bug: (\304...)
+ {\edef\!!stringa{##1\empty\empty}% and another one: ( 11) -> \ifx 11
+ \ifx\!!stringa\MPspacechar\MPspacechar\else\expandafter##1\fi}%
+ \def\do(##1{\dodo{##1}}%
+ \dogMPa\scratchcounter\MPspacechar
+ \let\do\relax
+ \loop
+ \advance\scratchcounter \plusone
+ \ifnum\scratchcounter<\nofMParguments\relax
+ \gMPa\scratchcounter\MPspacechar
+ \repeat
+ \def\do##1){\dodo{##1}}%
+ \dogMPa\scratchcounter
+ \fi
+ \unskip}}
+
+%D You could consider the following definition to be the most
+%D natural one.
+
+% \def\MPspacechar{\space} % normal case
+
+\def\MPspacechar{\char32\relax} % old solution does not work with math
+
+%D However, the following implementation is more robust, since
+%D some fonts have funny visible spaces in the space slot. This
+%D gives a mismatch between the space that \METAPOST\ took into
+%D account and the \quote {natural} space. This only happens in
+%D labels, since \type {btex}||\type {etex} thingies don't have
+%D spaces. This phenomena showed up when preparing the
+%D \METAFUN\ manual, where Palatino fonts are used. We can
+%D safely assume that \METAPOST\ considers \type {\char32} to
+%D be the space.
+
+\def\MPspacechar{\setbox\scratchbox\hbox{\char32}\kern\wd\scratchbox}
+
+%D Well, this does not work with math fonts, so:
+
+\def\MPspacechar{\char32\relax}
+
+%D Most operators are just converted and keep their
+%D arguments. Dashes however need a bit different treatment,
+%D otherwise \PDF\ viewers complain loudly. Another
+%D complication is that one argument comes after the \type{]}.
+%D When reading the data, we simply ignore the array boundary
+%D characters. We save ourselves some redundant newlines and
+%D at the same time keep the output readable by packing the
+%D literals.
+
+\def\handleMPsetdash
+ {\bgroup
+ \ignoreMPspecials
+ \let\somestring\empty
+ \scratchcounter\plusone
+ \loop
+ \ifnum\scratchcounter<\nofMParguments
+ \edef\somestring{\somestring\space\gMPa\scratchcounter}%
+ \advance\scratchcounter \plusone
+ \repeat
+ \edef\somestring{[\somestring]\space\gMPa\scratchcounter\space d}%
+ \PDFcode{\somestring}%
+ \egroup}
+
+%D The \type{setlinewidth} commands looks a bit complicated. There are
+%D two alternatives, that result in a similar look in both
+%D $x$- and $y$-dorection. As John Hobby says:
+%D
+%D \startnarrower \switchtobodyfont[ss]
+%D \starttyping
+%D x 0 dtransform exch truncate exch idtransform pop setlinewidth
+%D 0 y dtransform truncate idtransform setlinewidth pop
+%D \stoptyping
+%D
+%D These are just fancy versions of \type{x setlinewidth} and
+%D \type{y setlinewidth}. The \type{x 0 ...} form is used if
+%D the path is {\em primarily vertical}. It rounds the width
+%D so that vertical lines come out an integer number of pixels
+%D wide in device space. The \type{0 y ...} form does the same
+%D for paths that are {\em primarily horizontal}. The reason
+%D why I did this is Knuth insists on getting exactly the
+%D widths \TEX\ intends for the horizontal and vertical rules
+%D in \type{btex...etex} output. (Note that PostScript scan
+%D conversion rules cause a horizontal or vertical line of
+%D integer width $n$ in device space to come out $n+1$ pixels
+%D wide, regardless of the phase relative to the pixel grid.)
+%D \stopnarrower
+%D
+%D The common operator in these sequences is \type{dtransform},
+%D so we can use this one to trigger setting the linewidth.
+
+\def\handleMPdtransform
+ {\ifdim\gMPa1\onepoint>\zeropoint
+ \PDFcode{\gMPa1 w}%
+ \def\next##1 ##2 ##3 ##4 ##5 ##6 {\handleMPsequence}%
+ \else
+ \PDFcode{\gMPa2 w}%
+ \def\next##1 ##2 ##3 ##4 {\handleMPsequence}%
+ \fi
+ \let\handleMPsequence\dohandleMPsequence
+ \resetMPstack
+ \next}
+
+%D The most complicated command is \type{concat}. \METAPOST\
+%D applies this operator to \type{stroke}. At that moment the
+%D points set by \type{curveto} and \type{moveto}, are already
+%D fixed. In \PDF\ however the \type{cm} operator affects the
+%D points as well as the pen (stroke). Like more \PDF\
+%D operators, \type{cm} is defined in a bit ambiguous way.
+%D The only save route for non||circular penshapes, is saving
+%D the path, recalculating the points and applying the
+%D transformation matrix in such a way that we can be sure
+%D that its behavior is well defined. This comes down to
+%D inverting the path and applying \type{cm} to that path as
+%D well as the pen. This all means that we have to save the
+%D path.
+
+%D In \METAPOST\ there are three ways to handle a path $p$:
+%D
+%D \starttyping
+%D draw p; fill p; filldraw p;
+%D \stoptyping
+%D
+%D The last case outputs a \type{gsave fill grestore} before
+%D \type{stroke}. Handling the path outside the main loops
+%D saves about 40\% run time.\footnote{We can save some more by
+%D following the \METAPOST\ output routine, but for the moment
+%D we keep things simple.} Switching between the main loop and
+%D the path loop is done by means of the recursely called
+%D macro \type{\handleMPsequence}.
+
+\def\handleMPpath
+ {\chardef\finiMPpath\zerocount
+ \let\closeMPpath\relax
+ \let\flushMPpath\flushnormalMPpath
+ \resetMPstack
+ \nofMPsegments\plusone
+ \let\handleMPsequence\dohandleMPpath
+ \dohandleMPpath}
+
+%D Most paths are drawn with simple round pens. Therefore we've
+%D split up the routine in two.
+
+\def\resetMPmoveto
+ {\let\lastMPmoveX\empty
+ \let\lastMPmoveY\empty}
+
+\resetMPmoveto
+
+\def\flushMPmoveto
+ {\ifx\lastMPmoveX\empty \else
+ \PDFcode{\!MP\lastMPmoveX\space \!MP\lastMPmoveY\space m}%
+ \fi}
+
+\def\flushnormalMPsegment
+ {\ifcase\getMPkeyword\relax
+ \flushMPmoveto
+ \resetMPmoveto
+ \PDFcode{\!MPgMPs1 \!MPgMPs2 l}%
+ \or
+ \flushMPmoveto
+ \resetMPmoveto
+ \PDFcode{\!MPgMPs1 \!MPgMPs2 \!MPgMPs3 \!MPgMPs4 \!MPgMPs5 \!MPgMPs6 c}%
+ \or
+ \ifx\lastMPmoveX\empty \else % we assume 0,0 rlineto
+ \flushMPmoveto
+ \PDFcode{\!MP\lastMPmoveX\space \!MP\lastMPmoveY\space l}%
+ \resetMPmoveto
+ \fi
+ \or
+ % \flushMPmoveto
+ % \resetMPmoveto
+ \fi}
+
+\def\flushMPconcatmoveto
+ {\ifx\lastMPmoveX\empty\else
+ \doMPconcat\lastMPmoveX\lastMPmoveX\lastMPmoveY\lastMPmoveY
+ \flushMPmoveto
+ \fi}
+
+\def\flushconcatMPsegment
+ {\ifcase\getMPkeyword\relax
+ \flushMPconcatmoveto
+ \resetMPmoveto
+ \doMPconcat{\gMPs1}\a{\gMPs2}\b%
+ \PDFcode{\!MP\a\space\!MP\b\space l}%
+ \or
+ \flushMPconcatmoveto
+ \resetMPmoveto
+ \doMPconcat{\gMPs1}\a{\gMPs2}\b%
+ \doMPconcat{\gMPs3}\c{\gMPs4}\d%
+ \doMPconcat{\gMPs5}\e{\gMPs6}\f%
+ \PDFcode{\!MP\a\space\!MP\b\space
+ \!MP\c\space\!MP\d\space
+ \!MP\e\space\!MP\f\space c}%
+ \or % rather mp specific ... rline always has 0,0
+ \bgroup
+ \noMPtranslate
+ \flushMPconcatmoveto
+ % next should be \lastMPmoveX+\a,\lastMPmoveY+\b but we know it's 0,0
+ \PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l S}%
+ \resetMPmoveto
+ \egroup
+ \or
+% \flushMPconcatmoveto
+% \resetMPmoveto
+ \fi}
+
+\def\doflushsomeMPpath
+ {\dodoflushsomeMPpath
+ \advance\nofMPsegments \plusone
+ \ifnum\nofMPsegments<\scratchcounter
+ \expandafter\doflushsomeMPpath
+ \fi}
+
+\def\flushsomeMPpath
+ {\scratchcounter\nofMPsegments
+ \nofMPsegments\plusone
+ \doflushsomeMPpath}
+
+\def\flushnormalMPpath{\let\dodoflushsomeMPpath\flushnormalMPsegment\flushsomeMPpath}
+
+%OLD \def\flushconcatMPpath{\let\dodoflushsomeMPpath\flushconcatMPsegment\flushsomeMPpath}
+
+%NEW pre-calculate 1/D so it needn't be repeated for each control point.
+
+\def\flushconcatMPpath
+ {\MPreciprocaldeterminant
+ \let\dodoflushsomeMPpath\flushconcatMPsegment\flushsomeMPpath}
+
+%D The transformation of the coordinates is handled by one of
+%D the macros Tanmoy posted to the \PDFTEX\ mailing list.
+%D I rewrote and optimized the original macro to suit the other
+%D macros in this module.
+%D
+%D \starttyping
+%D \doMPconcat {x position} \xresult {y position} \yresult
+%D \stoptyping
+%D
+%D By setting the auxiliary \DIMENSIONS\ \type{\dimen0} upto
+%D \type{\dimen10} only once per path, we save over 20\% run
+%D time. Some more speed was gained by removing some parameter
+%D passing. These macros can be optimized a bit more by using
+%D more constants. There is however not much need for further
+%D optimization because penshapes usually are round and
+%D therefore need no transformation. Nevertheless we move the
+%D factor to the outer level and use a bit different \type{pt}
+%D removal macro. Although the values represent base points,
+%D we converted them to pure points, simply because those can
+%D be converted back.
+
+%OLD \mathchardef\MPconcatfactor=256 % beware don't remove spaces before it
+
+%OLD \def\doMPreducedimen#1
+%OLD {\count0\MPconcatfactor
+%OLD \advance\dimen#1 \ifdim\dimen#1>\zeropoint .5\else -.5\fi\count0
+%OLD \divide\dimen#1 \count0\relax}
+
+%OLD % too inaccurate (see old pragma logo)
+%OLD
+%OLD \def\doMPreducedimen#1
+%OLD {\count0=\MPconcatfactor
+%OLD \divide\dimen#1 \count0\relax}
+
+%OLD \def\doMPreducedimen#1
+%OLD {\advance\dimen#1 \ifdim\dimen#1>\zeropoint .5\else -.5\fi\MPconcatfactor
+%OLD \divide\dimen#1 \MPconcatfactor}
+
+%D The transformation code is rewritten by Daniel H. Luecking who
+%D describes his patch as follows:
+%D
+%D We would like to divide 1 by $X$, but all divisions are integer so
+%D for accuracy we want to convert to large integers and make sure the
+%D integer quotient has as many significant digits as possible. Thus we
+%D need to replace $1/X$ with $M/N$ where $N$ is as large as possible
+%D and $M/N$ is as large as possible. Also for simplicity $M$ should be
+%D a power of 2. So we make $M = 2^{30}$ \footnote{$2^{31} - 1$ is the
+%D largest legal integer. Using it (and simply ignoring the inaccuracy
+%D caused by $-1$) turns out to be at least as accurate in all cases,
+%D and more accurate in some.} (largest legal power of 2) and adjust
+%D $X$ downward (if necessary) to the the range $1-2^{16}$. This gives
+%D at least 15 significant binary digits, (almost as accurate as
+%D \METAPOST\ for numbers near 1) or almost 5 significant figures
+%D (decimal).
+
+\newcount\MPscratchCnt
+\newdimen\MPscratchDim % will be assigned global
+
+\def\MPadjustdimen % sets \MPscratchDim and \MPscratchCnt
+ {\MPscratchCnt\zerocount
+ \doMPadjustdimen}
+
+\def\doMPadjustdimen
+ {\ifdim\MPscratchDim>\onepoint
+ \divide \MPscratchDim\plustwo
+ \advance\MPscratchCnt\plusone
+ \expandafter\doMPadjustdimen
+ \fi}
+
+%OLD \def\doMPexpanddimen#1
+%OLD {\multiply\dimen#1 \MPconcatfactor\relax}
+
+%D DHL: When viewed as an integer, $1 \hbox{pt}=2^{16}$ so $2^{32}/X$
+%D is the right way to do $(1 \hbox{pt})/(X \hbox{pt})$ and get the
+%D answer in points. But we are limited to $2^{30}/X$. However, we
+%D actually do $[ 2^{30} / (X/2^K) ]*2^{2-K}$ where $K$ is the number
+%D of halvings it takes to bring $X$ below $1 \hbox{pt}$. If $K$ is 0
+%D or 1 we readjust by multiplying by 4 or 2, otherwise by halving
+%D $(K-2)$ times \type {\MPscratchCnt} holds the value of $K$ from
+%D \type {\MPadjustdimen}.
+
+\def\MPreadjustdimen % acts on \MPscratchDim and MPscratchCnt
+ {\ifcase\MPscratchCnt
+ \multiply\scratchdimen \plusfour
+ \or
+ \multiply\scratchdimen \plustwo
+ \else
+ \expandafter\doMPreadjustdimen
+ \fi}
+
+\def\doMPreadjustdimen
+ {\ifnum\MPscratchCnt>\plustwo
+ \divide \scratchdimen\plustwo
+ \advance\MPscratchCnt\minusone
+ \expandafter\doMPreadjustdimen
+ \fi}
+
+\def\MPreciprocaldeterminant
+ {\scratchdimen\withoutpt\the\dimen0 \dimen6 % s_x*s_y
+ \advance\scratchdimen -\withoutpt\the\dimen2 \dimen4 % s_x*s_y - r_x*r_y
+ \ifdim\scratchdimen<\zeropoint % we need a positive dimension
+ \scratchdimen-\scratchdimen % for \MPadjustdimen (?)
+ \doMPreciprocal
+ \scratchdimen-\scratchdimen
+ \else
+ \doMPreciprocal
+ \fi
+ \edef\MPreciprocal{\withoutpt\the\scratchdimen}}
+
+\newcount\MPnumerator \MPnumerator = 1073741824 % 2^{30}
+
+% todo: dimexpr
+
+\def\doMPreciprocal % replace \scratchdimen with its reciprocal
+ {\ifdim\scratchdimen=\onepoint \else
+ \MPadjustdimen
+ \scratchcounter\MPnumerator
+ \divide\scratchcounter\scratchdimen
+ \scratchdimen1\scratchcounter % 1 needed
+ \MPreadjustdimen
+ \fi}
+
+%OLD \def\presetMPconcat
+%OLD {\dimen 0=\gMPs1\onepoint \doMPreducedimen 0 % r_x
+%OLD \dimen 2=\gMPs2\onepoint \doMPreducedimen 2 % s_x
+%OLD \dimen 4=\gMPs3\onepoint \doMPreducedimen 4 % s_y
+%OLD \dimen 6=\gMPs4\onepoint \doMPreducedimen 6 % r_y
+%OLD \dimen 8=\gMPs5\onepoint \doMPreducedimen 8 % t_x
+%OLD \dimen10=\gMPs6\onepoint \doMPreducedimen10 } % t_y
+%OLD
+%OLD \def\presetMPscale
+%OLD {\dimen 0=\gMPs1\onepoint \doMPreducedimen 0
+%OLD \dimen 2 \zeropoint
+%OLD \dimen 4 \zeropoint
+%OLD \dimen 6=\gMPs2\onepoint \doMPreducedimen 6
+%OLD \dimen 8 \zeropoint
+%OLD \dimen10 \zeropoint}
+
+\def\cleanupMPconcat
+ {\ignoreMPspecials
+ \docleanupMPargument1%
+ \docleanupMPargument6%
+ \keepMPspecials}
+
+\def\presetMPconcat
+ {\dimen 0=\gMPs1\onepoint % s_x
+ \dimen 2=\gMPs2\onepoint % r_x
+ \dimen 4=\gMPs3\onepoint % r_y
+ \dimen 6=\gMPs4\onepoint % s_y
+ \dimen 8=\gMPs5\onepoint % t_x
+ \dimen10=\gMPs6\onepoint} % t_y
+
+\def\presetMPscale
+ {\dimen 0=\gMPs1\onepoint
+ \dimen 2 \zeropoint
+ \dimen 4 \zeropoint
+ \dimen 6=\gMPs2\onepoint
+ \dimen 8 \zeropoint
+ \dimen10 \zeropoint}
+
+\def\noMPtranslate % use this one grouped
+ {\dimen 8 \zeropoint % t_x
+ \dimen10 \zeropoint} % t_y
+
+%D \starttyping
+%D \def\doMPconcat#1#2#3#4%
+%D {\dimen12=#1 pt \doMPreducedimen12 % p_x
+%D \dimen14=#3 pt \doMPreducedimen14 % p_y
+%D %
+%D \dimen16 \dimen 0
+%D \multiply \dimen16 \dimen 6
+%D \dimen20 \dimen 2
+%D \multiply \dimen20 \dimen 4
+%D \advance \dimen16 -\dimen20
+%D %
+%D \dimen18 \dimen12
+%D \multiply \dimen18 \dimen 6
+%D \dimen20 \dimen14
+%D \multiply \dimen20 \dimen 4
+%D \advance \dimen18 -\dimen20
+%D \dimen20 \dimen 4
+%D \multiply \dimen20 \dimen10
+%D \advance \dimen18 \dimen20
+%D \dimen20 \dimen 6
+%D \multiply \dimen20 \dimen 8
+%D \advance \dimen18 -\dimen20
+%D %
+%D \multiply \dimen12 -\dimen 2
+%D \multiply \dimen14 \dimen 0
+%D \advance \dimen12 \dimen14
+%D \dimen20 \dimen 2
+%D \multiply \dimen20 \dimen 8
+%D \advance \dimen12 \dimen20
+%D \dimen20 \dimen 0
+%D \multiply \dimen20 \dimen10
+%D \advance \dimen12 -\dimen20
+%D %
+%D \doMPreducedimen16
+%D \divide \dimen18 \dimen16 \doMPexpanddimen18
+%D \divide \dimen12 \dimen16 \doMPexpanddimen12
+%D %
+%D \edef#2{\withoutpt\the\dimen18}% % p_x^\prime
+%D \edef#4{\withoutpt\the\dimen12}} % p_y^\prime
+%D \stoptyping
+
+%D The following optimization resulted from some tests by
+%D and email exchanges with Sanjoy Mahajan.
+%D
+%D \starttyping
+%D \def\doMPconcat#1#2#3#4%
+%D {\dimen12=#1 pt \doMPreducedimen12 % p_x
+%D \dimen14=#3 pt \doMPreducedimen14 % p_y
+%D %
+%D \dimen16 \dimen 0
+%D \multiply \dimen16 \dimen 6
+%D \dimen20 \dimen 2
+%D \multiply \dimen20 \dimen 4
+%D \advance \dimen16 -\dimen20
+%D %
+%D \dimen18 \dimen12
+%D \multiply \dimen18 \dimen 6
+%D \dimen20 \dimen14
+%D \multiply \dimen20 \dimen 4
+%D \advance \dimen18 -\dimen20
+%D \dimen20 \dimen 4
+%D \multiply \dimen20 \dimen10
+%D \advance \dimen18 \dimen20
+%D \dimen20 \dimen 6
+%D \multiply \dimen20 \dimen 8
+%D \advance \dimen18 -\dimen20
+%D %
+%D \multiply \dimen12 -\dimen 2
+%D \multiply \dimen14 \dimen 0
+%D \advance \dimen12 \dimen14
+%D \dimen20 \dimen 2
+%D \multiply \dimen20 \dimen 8
+%D \advance \dimen12 \dimen20
+%D \dimen20 \dimen 0
+%D \multiply \dimen20 \dimen10
+%D \advance \dimen12 -\dimen20
+%D %
+%D %\ifdim\dimen16>\onepoint % oeps, can be < 1pt too
+%D \ifdim\dimen16=\onepoint \else
+%D \ifdim\dimen16>\MPconcatfactor pt
+%D \doMPreducedimen16
+%D \divide \dimen18 \dimen16 \doMPexpanddimen18
+%D \divide \dimen12 \dimen16 \doMPexpanddimen12
+%D \else
+%D \divide \dimen18 \dimen16 \doMPexpanddimen18 \doMPexpanddimen18
+%D \divide \dimen12 \dimen16 \doMPexpanddimen12 \doMPexpanddimen12
+%D \fi
+%D \fi
+%D %
+%D \edef#2{\withoutpt\the\dimen18}% % p_x^\prime
+%D \edef#4{\withoutpt\the\dimen12}} % p_y^\prime
+%D \stoptyping
+%D
+%D But, this one is still too inaccurate, so we now have:
+
+%D DHL: Ideally, $r_x$, $r_y$, $s_x$, $s_y$ should be in macros, not
+%D dimensions (they are scalar quantities after all, not lengths). I
+%D suppose the authors decided to do calculations with integer
+%D arithmetic instead of using real factors because it's faster.
+%D However, the actual macros test slower, possibly because I've
+%D omitted three nested loops. In my test files, my approach is more
+%D accurate. It is also far simpler and overflow does not seem to be a
+%D significant concern. The scale factors written by Metapost are (?)
+%D always $<=1$ (it scales coordinates internally) and coordinates are
+%D always likely to be less than \type {\maxdimen}.
+%D
+%D If this should ever cause problems, the scale factors can be reduced.
+
+% the original:
+%
+% \def\doMPconcat#1#2#3#4%
+% {\dimen12=#1\onepoint% p_x % #1\onepoint
+% \dimen14=#3\onepoint% p_y % #3\onepoint
+% \advance\dimen12 -\dimen8 % p_x - t_x
+% \advance\dimen14 -\dimen10 % p_y - t_y
+% \dimen18=\withoutpt\the\dimen6 \dimen12 % s_y(p_x - t_x)
+% \advance\dimen18 -\withoutpt\the\dimen4 \dimen14 % - r_y(p_y-t_y)
+% \dimen14=\withoutpt\the\dimen0 \dimen14 % s_x(p_y-t_y)
+% \advance\dimen14 -\withoutpt\the\dimen2 \dimen12 % - r_x(p_x-t_x)
+% % \MPreciprocal contains precomputed 1/D:
+% \dimen18=\MPreciprocal\dimen18
+% \dimen14=\MPreciprocal\dimen14
+% \edef#2{\withoutpt\the\dimen18}% % p_x^\prime
+% \edef#4{\withoutpt\the\dimen14}} % p_y^\prime
+%
+% faster but not that often used
+
+\def\doMPconcat#1#2#3#4%
+ {\dimen12\dimexpr#1\points-\dimen 8\relax % p_x-t_x
+ \dimen14\dimexpr#3\points-\dimen10\relax % p_y-t_y
+ \dimen18\dimexpr\withoutpt\the\dimen6\dimen12-\withoutpt\the\dimen4\dimen14\relax % s_y(p_x-t_x)-r_y(p_y-t_y)
+ \dimen14\dimexpr\withoutpt\the\dimen0\dimen14-\withoutpt\the\dimen2\dimen12\relax % s_x(p_y-t_y)-r_x(p_x-t_x)
+ \edef#2{\withoutpt\the\dimexpr\MPreciprocal\dimen18\relax}% % p_x^\prime
+ \edef#4{\withoutpt\the\dimexpr\MPreciprocal\dimen14\relax}} % p_y^\prime
+
+%D One reason for Daniel to write this patch was that at small sizes
+%D the accuracy was less than optimal. Here is a test that demonstrates
+%D that his alternative is pretty good:
+%D
+%D \startlinecorrection
+%D \startMPcode
+%D for i = 5cm,1cm,5mm,1mm,.5mm,.1mm,.01mm :
+%D draw fullcircle scaled i withpen pencircle xscaled (i/10) yscaled (i/20) rotated 45 ;
+%D endfor ;
+%D \stopMPcode
+%D \stoplinecorrection
+
+%D The following explanation of the conversion process was
+%D posted to the \PDFTEX\ mailing list by Tanmoy. The original
+%D macro was part of a set of macro's that included sinus and
+%D cosinus calculations as well as scaling and translating. The
+%D \METAPOST\ to \PDF\ conversion however only needs
+%D transformation.
+
+%M \start \switchtobodyfont [ss]
+
+%D Given a point $(U_x, U_y)$ in user coordinates, the business
+%D of \POSTSCRIPT\ is to convert it to device space. Let us say
+%D that the device space coordinates are $(D_x, D_y)$. Then, in
+%D \POSTSCRIPT\ $(D_x, D_y)$ can be written in terms of
+%D $(U_x, U_y)$ in matrix notation, either as
+%D
+%D \placeformula
+%D \startformula
+%D \pmatrix{D_x&D_y&1\cr} = \pmatrix{U_x&U_y&1\cr}
+%D \pmatrix{s_x&r_x&0\cr
+%D r_y&s_y&0\cr
+%D t_x&t_y&1\cr}
+%D \stopformula
+%D
+%D or
+%D
+%D \placeformula
+%D \startformula
+%D \pmatrix{D_x\cr D_y\cr 1} = \pmatrix{s_x&r_y&t_x\cr
+%D r_x&s_y&t_y\cr
+%D 0 &0 &1 \cr}
+%D \pmatrix{U_x\cr
+%D U_y\cr
+%D 1 \cr}
+%D \stopformula
+%D
+%D both of which is a shorthand for the same set of equations:
+%D
+%D \placeformula
+%D \startformula
+%D D_x = s_x U_x + r_y U_y + t_x
+%D \stopformula
+%D
+%D \placeformula
+%D \startformula
+%D D_y = r_x U_x + s_y U_y + t_y
+%D \stopformula
+%D
+%D which define what is called an `affine transformation'.
+%D
+%D \POSTSCRIPT\ represents the `transformation matrix' as a
+%D six element matrix instead of a $3\times 3$ array because
+%D three of the elements are always~0, 0 and~1. Thus the above
+%D transformation is written in postscript as $[s_x\, r_x\,
+%D r_y\, s_y\, t_x\, t_y]$. However, when doing any
+%D calculations, it is useful to go back to the original
+%D matrix notation (whichever: I will use the second) and
+%D continue from there.
+%D
+%D As an example, if the current transformation matrix is
+%D $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$ and you say \typ{[a b
+%D c d e f] concat}, this means:
+%D
+%D \startnarrower
+%D Take the user space coordinates and transform them to an
+%D intermediate set of coordinates using array $[a\, b\, c\, d\,
+%D e\, f]$ as the transformation matrix.
+%D
+%D Take the intermediate set of coordinates and change them to
+%D device coordinates using array $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$
+%D as the transformation matrix.
+%D \stopnarrower
+%D
+%D Well, what is the net effect? In matrix notation, it is
+%D
+%D \placeformula
+%D \startformula
+%D \pmatrix{I_x\cr I_y\cr 1\cr} = \pmatrix{a&c&e\cr
+%D b&d&f\cr
+%D 0&0&1\cr}
+%D \pmatrix{U_x\cr
+%D U_y\cr
+%D 1 \cr}
+%D \stopformula
+%D
+%D \placeformula
+%D \startformula
+%D \pmatrix{D_y\cr D_y\cr 1\cr} = \pmatrix{s_x&r_y&t_x\cr
+%D r_x&s_y&t_y\cr
+%D 0 &0 &1 \cr}
+%D \pmatrix{I_x\cr
+%D I_y\cr
+%D 1 \cr}
+%D \stopformula
+%D
+%D where $(I_x, I_y)$ is the intermediate coordinate.
+%D
+%D Now, the beauty of the matrix notation is that when there is
+%D a chain of such matrix equations, one can always compose
+%D them into one matrix equation using the standard matrix
+%D composition law. The composite matrix from two matrices can
+%D be derived very easily: the element in the $i$\high{th}
+%D horizontal row and $j$\high{th} vertical column is
+%D calculated by`multiplying' the $i$\high{th} row of the first
+%D matrix and the $j$\high{th} column of the second matrix (and
+%D summing over the elements). Thus, in the above:
+%D
+%D \placeformula
+%D \startformula
+%D \pmatrix{D_x\cr D_y\cr 1} = \pmatrix{s_x^\prime&r_y^\prime&t_x^\prime\cr
+%D r_x^\prime&s_y^\prime&t_y^\prime\cr
+%D 0 &0 &0 \cr}
+%D \pmatrix{U_x\cr
+%D U_y\cr
+%D 1 \cr}
+%D \stopformula
+%D
+%D with
+%D
+%D \placeformula
+%D \startformula
+%D \eqalign
+%D {s_x^\prime & = s_x a + r_y b \cr
+%D r_x^\prime & = r_x a + s_y b \cr
+%D r_y^\prime & = s_x c + r_y d \cr
+%D s_y^\prime & = r_x c + s_y d \cr
+%D t_x^\prime & = s_x e + r_y f + t_x \cr
+%D t_y^\prime & = r_x e + s_y f + t_y \cr}
+%D \stopformula
+
+%D In fact, the same rule is true not only when one is going
+%D from user coordinates to device coordinates, but whenever
+%D one is composing two `transformations' together
+%D (transformations are `associative'). Note that the formula
+%D is not symmetric: you have to keep track of which
+%D transformation existed before (i.e.\ the equivalent of
+%D $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$) and which was
+%D specified later (i.e.\ the equivalent of $[a\, b\, c\, d\,
+%D e\, f]$). Note also that the language can be rather
+%D confusing: the one specified later `acts earlier',
+%D converting the user space coordinates to intermediate
+%D coordinates, which are then acted upon by the pre||existing
+%D transformation. The important point is that order of
+%D transformation matrices cannot be flipped (transformations
+%D are not `commutative').
+%D
+%D Now what does it mean to move a transformation matrix
+%D before a drawing? What it means is that given a point
+%D $(P_x, P_y)$ we need a different set of coordinates
+%D $(P_x^\prime, P_y^\prime)$ such that if the transformation
+%D acts on $(P_x^\prime, P_y^\prime)$, they produce $(P_x,
+%D P_y)$. That is we need to solve the set of equations:
+%D
+%D \placeformula
+%D \startformula
+%D \pmatrix{P_x\cr P_y\cr 1\cr} = \pmatrix{s_x&r_y&t_x\cr
+%D r_x&s_y&t_y\cr
+%D 0 &0 &1 \cr}
+%D \pmatrix{P_x^\prime\cr
+%D P_y^\prime\cr
+%D 1 \cr}
+%D \stopformula
+%D
+%D Again matrix notation comes in handy (i.e. someone has
+%D already solved the problem for us): we need the inverse
+%D transformation matrix. The inverse transformation matrix can
+%D be calculated very easily:
+%D
+%D \placeformula
+%D \startformula
+%D \pmatrix{P_x^\prime\cr P_y^\prime\cr 1\cr} =
+%D \pmatrix{s_x^\prime&r_y^\prime&t_x^\prime\cr
+%D r_x^\prime&s_y^\prime&t_y^\prime\cr
+%D 0 &0 &1 \cr}
+%D \pmatrix{P_x\cr
+%D P_y\cr
+%D 1 \cr}
+%D \stopformula
+%D
+%D where, the inverse transformation matrix is given by
+%D
+%D \placeformula
+%D \startformula
+%D \eqalign
+%D {D & = s_x s_y - r_x r_y \cr
+%D s_x^\prime & = s_y / D \cr
+%D s_y^\prime & = s_x / D \cr
+%D r_x^\prime & = - r_x / D \cr
+%D r_y^\prime & = - r_y / D \cr
+%D t_x^\prime & = ( - s_y t_x + r_y t_y ) / D \cr
+%D t_y^\prime & = ( r_x t_x - s_x t_y ) / D \cr}
+%D \stopformula
+%D
+%D And you can see that when expanded out, this does
+%D give the formulas:
+%D
+%D \placeformula
+%D \startformula
+%D P_x^\prime = { { s_y(p_x-t_x) + r_y(t_y-p_y) } \over
+%D { s_x s_y-r_x r_y } }
+%D \stopformula
+%D
+%D \placeformula
+%D \startformula
+%D P_y^\prime = { { s_x(p_y-t_y) + r_x(t_x-p_x) } \over
+%D { s_x*s_y-r_x*r_y } }
+%D \stopformula
+%D
+%D The code works by representing a real number by converting
+%D it to a dimension to be put into a \DIMENSION\ register: 2.3 would
+%D be represented as 2.3pt for example. In this scheme,
+%D multiplying two numbers involves multiplying the \DIMENSION\
+%D registers and dividing by 65536. Accuracy demands that the
+%D division be done as late as possible, but overflow
+%D considerations need early division.
+%D
+%D Division involves dividing the two \DIMENSION\ registers and
+%D multiplying the result by 65536. Again, accuracy would
+%D demand that the numerator be multiplied (and|/|or the
+%D denominator divided) early: but that can lead to overflow
+%D which needs to be avoided.
+%D
+%D If nothing is known about the numbers to start with (in
+%D concat), I have chosen to divide the 65536 as a 256 in each
+%D operand. However, in the series calculating the sine and
+%D cosine, I know that the terms are small (because I never
+%D have an angle greater than 45 degrees), so I chose to
+%D apportion the factor in a different way.
+
+%M \stop
+
+%D The path is output using the values saved on the stack. If
+%D needed, all coordinates are recalculated.
+
+\def\finishMPpath
+ {\PDFcode{\ifcase\finiMPpath W n\or S\or f\or B\fi}}
+
+\def\processMPpath
+ {\checkMPpath
+ \ifcase\nofMPsegments\else
+ \flushMPpath
+ \closeMPpath
+ \finishMPpath
+ \fi
+ \let\handleMPsequence\dohandleMPsequence
+ \resetMPstack
+ \nofMPsegments\zerocount
+ \handleMPsequence}
+
+%D The following \METAPOST\ code is quite valid but, when
+%D processed and converted to \PDF, will make a file
+%D unprintable on a Hewlett Packard printer (from Acrobat
+%D $v<=5$). Who is to blame, the driver of the OS layer in
+%D between, is hard to determine, so we add an additional
+%D check.
+%D
+%D \starttyping
+%D clip currentpicture to origin -- cycle ;
+%D setbounds currentpicture to fullsquare scaled 5cm ;
+%D \stoptyping
+
+\def\checkMPpath
+ {\ifcase\finiMPpath
+ \ifnum\nofMPsegments<\plusthree % n is one ahead
+ \message{omitting zero clip path}%
+ \nofMPsegments\zerocount
+ \fi
+ \fi}
+
+%D In \PDF\ the \type{cm} operator must precede the path
+%D specification. We therefore can output the \type{cm} at
+%D the moment we encounter it.
+
+\def\handleMPpathconcat
+ {\presetMPconcat
+ \PDFcode{\gMPs1 \gMPs2 \gMPs3 \gMPs4 \gMPs5 \gMPs6 cm}%
+ \resetMPstack}
+
+\def\handleMPpathscale
+ {\presetMPscale
+ \PDFcode{\gMPs1 0 0 \gMPs2 0 0 cm}%
+ \resetMPstack}
+
+%D This macro interprets the path and saves it as compact as
+%D possible.
+
+\def\dohandleMPpath#1%
+ {\ifcase\lccode`#1\relax
+ \@EA\dohandleMPpathA
+ \else
+ \@EA\dohandleMPpathB
+ \fi#1}
+
+\let\dohandleMPpathA\setMPsequence
+
+\def\installMPSkeywordP#1#2%
+ {\expandafter\def\csname\@@MP:P:#1\endcsname{#2}}
+
+\def\installMPSshortcutP#1#2% todo: \let
+ {\expandafter\let\csname\@@MP:P:#1\expandafter\endcsname\csname\@@MP:P:#2\endcsname}
+
+\def\dohandleMPpathB#1 %
+ {\def\somestring{#1}%
+ \executeifdefined{\@@MP:P:\somestring}\relax
+ \handleMPsequence}
+
+\installMPSkeywordP \PSlineto
+ {\setMPkeyword0 }
+\installMPSkeywordP \PScurveto
+ {\setMPkeyword1 }
+\installMPSkeywordP \PSrlineto
+ {\setMPkeyword2 }
+\installMPSkeywordP \PSmoveto
+ {\edef\lastMPmoveX{\gMPs1}%
+ \edef\lastMPmoveY{\gMPs2}%
+ \resetMPstack
+ \setMPkeyword3 }
+\installMPSkeywordP \PSclip
+ {% \chardef\finiMPpath\zerocount % already
+ \let\handleMPsequence\processMPpath}
+\installMPSkeywordP \PSgsave
+ {\chardef\finiMPpath\plusthree}
+\installMPSkeywordP \PSgrestore
+ {}
+\installMPSkeywordP \PSfill
+ {\ifcase\finiMPpath
+ \chardef\finiMPpath\plustwo
+ \let\handleMPsequence\processMPpath
+ \fi}
+\installMPSkeywordP \PSstroke
+ {\ifcase\finiMPpath
+ \chardef\finiMPpath\plusone
+ \fi
+ \let\handleMPsequence\processMPpath}
+\installMPSkeywordP \PSclosepath
+ {\def\closeMPpath{\PDFcode{h}}}
+\installMPSkeywordP \PSconcat
+ {\cleanupMPconcat
+ \let\flushMPpath\flushconcatMPpath
+ \handleMPpathconcat}
+\installMPSkeywordP \PSscale
+ {\let\flushMPpath\flushconcatMPpath
+ \handleMPpathscale}
+
+\installMPSshortcutP {l} \PSlineto
+\installMPSshortcutP {r} \PSrlineto
+\installMPSshortcutP {m} \PSmoveto
+\installMPSshortcutP {c} \PScurveto
+
+\installMPSshortcutP {q} \PSgsave
+\installMPSshortcutP {Q} \PSgrestore
+\installMPSshortcutP {S} \PSstroke
+\installMPSshortcutP {F} \PSfill
+\installMPSshortcutP {B} \PSgsave
+\installMPSshortcutP {W} \PSclip
+\installMPSshortcutP {p} \PSclosepath
+
+\installMPSshortcutP {s} \PSscale
+\installMPSshortcutP {t} \PSconcat
+
+%D \macros
+%D {twodigitMPoutput}
+%D
+%D We can limit the precision to two digits after the comma
+%D by saying:
+%D
+%D \starttyping
+%D \twodigitMPoutput
+%D \stoptyping
+%D
+%D This option only works in \CONTEXT\ combined with \ETEX.
+
+\def\twodigitMPoutput
+ {\let\!MP \twodigitrounding
+ \def\!MPgMPs##1{\twodigitrounding{\gMPs##1}}%
+ \def\!MPgMPa##1{\twodigitrounding{\gMPa##1}}}
+
+\let\!MP \empty
+\let\!MPgMPa\gMPa
+\let\!MPgMPs\gMPs
+
+%D Here comes the special-specific code:
+
+\def\setMPextensions
+ {\ifconditional\manyMPspecials
+ \def\MPrgbnumber##1{\expandafter\doMPrgbnumber##10000.00000\relax}%
+ \def\doMPrgbnumber##1.##2##3##4##5##6\relax{##2##3##4##5}%
+ \else
+ \def\MPrgbnumber##1{\expandafter\doMPrgbnumber##1000.0000\relax}%
+ \def\doMPrgbnumber##1.##2##3##4##5\relax{##2##3##4}%
+ \fi}
+
+% \settrue\manyMPspecials \setMPextensions
+
+%D This macro handles the special definitions that are
+%D passed as comment.
+
+%D The implementation below saves the data on the stack in
+%D a way similar to the macros in \type {supp-pdf.tex}, and
+%D just overload a few already defined handlers. That way,
+%D the existing macros are still generic. \footnote {Actually,
+%D the macros here are just as generic.}
+%D
+%D Currently the only extension concerns shading, which is
+%D accomplished by handling yet another value of \type
+%D {\finiMPpath}. The recource disctionary is stored and
+%D later picked up by the general \CONTEXT\ figure inclusion
+%D macros.
+
+%D The \type {%%MetaPostSpecials: version.revision signal} line
+%D triggers this module into handling color specifications kind
+%D of special. We need this safeguard for non||special
+%D usage.
+
+%D When defined inline, we use another macro to handle the
+%D definitions. Actually, this macro is called by the
+%D previous ones.
+
+\chardef\MPspecialversion = 0 % specials when >1
+\chardef\MPspecialrevision = 0 % specials when >1
+\chardef\MPspecialsignal = 0 % passed on by graphic
+
+\chardef\inlineMPspecials = 1 % only needed for stack resetting
+
+\def\dohandleMPspecialcomment#1
+ {\setMPargument{#1}%
+ \advance\scratchcounter \minusone
+ \ifcase\scratchcounter
+ \handleMPspecialcommand
+ \donetrue
+ \doresetMPstack
+ \let\handleMPsequence\dohandleMPsequence
+ \expandafter\handleMPsequence
+ \else
+ \expandafter\dohandleMPspecialcomment
+ \fi}
+
+\def\handleMPspecialcomment #1 % number of arguments
+ {\doresetMPstack
+ \scratchcounter#1\relax
+ \ifcase\scratchcounter % when zero, inline shading is used
+ \chardef\inlineMPspecials\plusone
+ \let\handleMPsequence\dohandleMPsequence
+ \expandafter\handleMPsequence
+ \else
+ \chardef\inlineMPspecials\zerocount
+ \expandafter\dohandleMPspecialcomment
+ \fi}
+
+%D When defined inline, we use another macro to handle the
+%D definitions. Actually, this macro is called by the
+%D previous ones.
+
+\def\handleMPspecialcommand
+ {\ifcase\inlineMPspecials\or
+ \advance\nofMParguments \minusone % pop the size
+ \fi
+ \ifundefined\MPspecial % beware, no real \if
+ \message{[unknown \MPspecial]}%
+ \else
+ \csname\MPspecial\endcsname
+ \fi
+ \ifcase\inlineMPspecials
+ \doresetMPstack % 0
+ \else
+ \resetMPstack % 1
+ \fi}
+
+\def\handleMPspecialscomment #1.#2 #3 % version.revision signal #4=div=1000|10000
+ {\doresetMPstack
+ \chardef\MPspecialversion #1%
+ \chardef\MPspecialrevision#2%
+ \chardef\MPspecialsignal #3%
+ \let\handleMPsequence\dohandleMPsequence
+ \ifnum#1=\plusone
+ \expandafter\handleMPsequence
+ \else
+ \expandafter\handleMPspecialscommentx
+ \fi}
+
+\def\handleMPspecialscommentx #1 % version 2
+ {\ifnum10000=0#1\relax
+ \settrue \manyMPspecials
+ \else
+ \setfalse\manyMPspecials
+ \fi
+ \setMPextensions
+ \handleMPsequence}
+
+\def\handleMPrgbcolor
+ {\edef\lastMPrvalue{\csname\@@MP01\endcsname}%{\gMPs1}%
+ \edef\lastMPgvalue{\csname\@@MP02\endcsname}%{\gMPs2}%
+ \edef\lastMPbvalue{\csname\@@MP03\endcsname}%{\gMPs3}%
+ \ifnum\MPrgbnumber\lastMPrvalue=123\relax
+ \csname\@@MPSK\number\MPrgbnumber\lastMPbvalue\endcsname
+ \else
+ \dohandleMPrgb\lastMPrvalue\lastMPgvalue\lastMPbvalue
+ \fi}
+
+\def\handleMPgraycolor{\dohandleMPgray{\gMPs1}}
+\def\handleMPcmykcolor{\dohandleMPcmyk{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}}
+\def\handleMPspotcolor{\dohandleMPspot{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}}
+
+% \newcontitional\ignoreMPpath
+
+\def\finishMPpath
+ {\ifconditional\ignoreMPpath
+ \PDFcode{W n\space}%
+ \else
+ \PDFcode{\ifcase\finiMPpath W n\or S\or f\or B\else W n\fi}%
+ \fi
+ \ifx\extraMPpathcode\empty\else
+ \PDFcode{\extraMPpathcode}%
+ \let\extraMPpathcode\empty
+ \fi
+ \setfalse\ignoreMPpath}
+
+\def\processMPpath
+ {\checkMPpath % !
+ \flushMPpath
+ \closeMPpath
+ \finishMPpath
+ \let\handleMPsequence\dohandleMPsequence
+ \resetMPstack
+ \nofMPsegments\zerocount
+ \handleMPsequence}
+
+\protect \endinput
+
+% When i'm bored ...
+
+% \newcatcodetable\mpscatcodes
+
+% \startcatcodetable \mpscatcodes
+% \catcode`\| \@@comment
+% \catcode`\% \@@active
+% \catcode`\[ \@@active
+% \catcode`\] \@@active
+% \catcode`\{ \@@active
+% \catcode`\} \@@active
+% \stopcatcodetable
+
+% \def\keepMPspecials
+% {\setcatcodecommand \mpscatcodes `\% \letterpercent
+% \setcatcodecommand \mpscatcodes `\[ \letterleftbracket
+% \setcatcodecommand \mpscatcodes `\] \letterrightbracket
+% \setcatcodecommand \mpscatcodes `\{ \letterleftbrace
+% \setcatcodecommand \mpscatcodes `\} \letterrightbrace}
+
+% \def\ignoreMPspecials
+% {\setcatcodecommand \mpscatcodes `\% \letterpercent
+% \setcatcodecommand \mpscatcodes `\[ \empty
+% \setcatcodecommand \mpscatcodes `\] \empty
+% \setcatcodecommand \mpscatcodes `\{ \empty
+% \setcatcodecommand \mpscatcodes `\} \empty}
+
+% \def\obeyMPspecials
+% {\setcatcodecommand \mpscatcodes `\% \letterpercent
+% \setcatcodecommand \mpscatcodes `\[ \letterleftbracket
+% \setcatcodecommand \mpscatcodes `\] \letterrightbracket
+% \setcatcodecommand \mpscatcodes `\{ \letterleftbrace
+% \setcatcodecommand \mpscatcodes `\} \letterrightbrace}
+
+% \gdef\setMPspecials|
+% {\setcatcodetable\mpscatcodes
+% \lccode`\-=\zerocount % to be sure, it could be a letter
+% \lccode`\%=`\%% % otherwise it's seen as a number
+% \def\({\char40\relax }%
+% \def\){\char41\relax }%
+% \def\\{\char92\relax }%
+% \def\0{\octalMPcharacter0}%
+% \def\1{\octalMPcharacter1}%
+% \def\2{\octalMPcharacter2}%
+% \def\3{\octalMPcharacter3}%
+% \def\4{\octalMPcharacter4}%
+% \def\5{\octalMPcharacter5}%
+% \def\6{\octalMPcharacter6}%
+% \def\7{\octalMPcharacter7}%
+% \def\8{\octalMPcharacter8}%
+% \def\9{\octalMPcharacter9}}
diff --git a/tex/context/base/meta-pdf.mkiv b/tex/context/base/meta-pdf.mkiv
new file mode 100644
index 000000000..fa9627fbe
--- /dev/null
+++ b/tex/context/base/meta-pdf.mkiv
@@ -0,0 +1,474 @@
+%D \module
+%D [ file=meta-pdf,
+%D version=2006.06.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Conversion to \PDF,
+%D author=Hans Hagen \& others (see text),
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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{meta-pdf}{1.003}
+
+%D We will clean up the color mess later.
+
+\writestatus{loading}{MetaPost Graphics / MPS to PDF}
+
+\unprotect
+
+%D \macros
+%D {convertMPtoPDF}
+%D
+%D The next set of macros implements \METAPOST\ to \PDF\
+%D conversion. The traditional method is in the MkII file.
+%D
+%D The main conversion command is:
+%D
+%D \starttyping
+%D \convertMPtoPDF {filename} {x scale} {y scale}
+%D \stoptyping
+%D
+%D The dimensions are derived from the bounding box. So we
+%D only have to say:
+%D
+%D \starttyping
+%D \convertMPtoPDF{mp-pra-1.eps}{1}{1}
+%D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5}
+%D \stoptyping
+
+\def\PDFMPformoffset
+ {\ifdefined\objectoffset\objectoffset\else\zeropoint\fi}
+
+%D The main macro:
+
+\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 ignored)
+ {\vbox\bgroup
+ \message{[MP to PDF]}%
+ \xdef\MPfilename{#1}%
+ \glet\MPwidth \!!zeropoint
+ \glet\MPheight\!!zeropoint
+ \glet\MPllx \!!zerocount
+ \glet\MPlly \!!zerocount
+ \glet\MPurx \!!zerocount
+ \glet\MPury \!!zerocount
+ \forgetall
+ \offinterlineskip
+ \setbox\scratchbox\vbox\bgroup
+ \ctxlua{mptopdf.convertmpstopdf("\MPfilename")}\removeunwantedspaces
+ \egroup
+ \setbox\scratchbox\hbox\bgroup
+ \hskip-\MPllx\onebasepoint
+ \raise-\MPlly\onebasepoint
+ \box\scratchbox
+ \egroup
+ \setbox\scratchbox\vbox to \MPheight\bgroup
+ \vfill
+ \hsize\MPwidth
+ \smashbox\scratchbox
+ \box\scratchbox
+ \egroup
+ \wd\scratchbox\MPwidth
+ \ht\scratchbox\MPheight
+ \dopackageMPgraphic\scratchbox
+ \egroup}
+
+%D Objects (move all to backend)
+
+% \def\dopackageMPgraphic#1% #1 = boxregister
+% {\scratchdimen\PDFMPformoffset\relax
+% \ifdim\scratchdimen>\zeropoint % compensate for error
+% \setbox#1\vbox spread 2\scratchdimen
+% {\forgetall\vss\hbox spread 2\scratchdimen{\hss\box#1\hss}\vss}%
+% \fi
+% \setMPPDFobject{#1}%
+% \ifdim\scratchdimen>\zeropoint % compensate for error
+% \vbox to \MPheight
+% {\forgetall\vss\hbox to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
+% \else
+% \getMPPDFobject
+% \fi}
+%
+% \def\setMPPDFobject#1% boxnumber
+% {\the\pdfbackendeveryxform
+% \finalizeobjectbox{#1}%
+% \immediate\pdfxform resources{\pdfcurrentresources}#1%
+% \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}}
+%
+% \let\getMPPDFobject\relax
+
+% we don't need to package as each page has all resources anyway
+
+\let\dopackageMPgraphic\box
+
+%D \macros
+%D {deleteMPgraphic,
+%D startMPresources,
+%D stopMPresources}
+
+\ifx\deleteMPgraphic\undefined
+ \def\deleteMPgraphic#1{}
+\fi
+
+\ifx\startMPresources\undefined
+ \let\startMPresources\relax
+ \let\stopMPresources\relax
+\fi
+
+%D We implement extensions by using the \METAPOST\ special
+%D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones
+%D are flushed before or after the graphic data, but thereby
+%D are no longer connected to a position.
+%D
+%D We implement specials by overloading the \type {fill}
+%D operator. By counting the fills, we can let the converter
+%D treat the appropriate fill in a special way. The
+%D specification of the speciality can have two forms,
+%D determined by the setting of a boolean variable:
+%D
+%D \starttyping
+%D _inline_specials_ := false ; % comment like code (default)
+%D _inline_specials_ := true ; % command like code
+%D \stoptyping
+%D
+%D When the specification is embedded as comment, it looks
+%D like:
+%D
+%D \starttyping
+%D %%MetaPostSpecial
+%D \stoptyping
+%D
+%D The in||line alternative is more tuned for \POSTSCRIPT,
+%D since it permits us to define a macro \type {special}.
+%D
+%D \starttyping
+%D inline : special
+%D \stoptyping
+%D
+%D The \type {identifier} determines what to do, and the data
+%D can be used to accomplish this. A type~2 shading function
+%D has identifier~2. Alltogether, the number of parameters is
+%D specified in \type {size}. The \type {number} is the number
+%D of the fill that needs the special treatment. For a type~2
+%D and~3 shaded fill, the datablock contains the following
+
+%D data:
+%D
+%D \starttyping
+%D from to n inner_r g b x y outer_r g b x y
+%D from to n inner_r g b x y radius outer_r g b x y radius
+%D \stoptyping
+
+\newconditional\manyMPspecials \settrue\manyMPspecials
+
+%D Since colors are not subjected to transformations, we can
+%D only use colors as signal. In our case, we use a dummy colored
+%D path with a red color component of \type {0.n}, so \type
+%D {0.001} is the first path and \type {0.010} the tenth. Since
+%D \METAPOST strips trailing zeros, we have to padd the string.
+
+\newif\ifMPcmykcolors
+\newif\ifMPspotcolors
+
+%D We support specials but assume that the files are somewhat simple
+%D ones wo we have dropped a few. The reason is that runtime \METAPOST\
+%D processing now uses \MPLIB\ so we only need to deal with the
+%D conversion here. See meta-pdh.mkiv (and older files) for more
+%D details. Here we just give a few examples.
+%D
+%D \startbuffer[mp]
+%D fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ;
+%D \stopbuffer
+%D
+%D \startbuffer[cmyk]
+%D \startcombination[4*1]
+%D {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3}
+%D {\definecolor[test][c=.9,y=.15] \processMPbuffer[mp]} {c=.9 y=.15}
+%D {\definecolor[test][c=.25,y=.8] \processMPbuffer[mp]} {c=.25 y=.8}
+%D {\definecolor[test][c=.45,y=.1] \processMPbuffer[mp]} {c=.45 y=.1}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \placefigure
+%D {\CMYK\ support disabled,
+%D conversion to \RGB.}
+%D {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no support in \METAPOST.}
+%D {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no conversion to \RGB,
+%D support in \METAPOST}
+%D {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]}
+%D
+%D Transparency support used specials 60 (rgb) and 61
+%D (cmyk).
+%D
+%D \startbuffer
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor transparent(1,.5,yellow) ;
+%D fill p rotated 210 withcolor transparent(1,.5,green) ;
+%D fill p rotated 330 withcolor transparent(1,.5,blue) ;
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+%D
+%D One can also communicate colors between \CONTEXT\ and
+%D \METAPOST:
+%D
+%D \startbuffer
+%D \definecolor[tcyan] [c=1,k=.2,t=.5]
+%D \definecolor[tmagenta][m=1,k=.2,t=.5]
+%D \definecolor[tyellow] [y=1,k=.2,t=.5]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor \MPcolor{tcyan} ;
+%D fill p rotated 210 withcolor \MPcolor{tmagenta} ;
+%D fill p rotated 330 withcolor \MPcolor{tyellow} ;
+%D \stopbuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+%D
+%D Shading is an example of a more advanced graphic feature,
+%D but users will seldom encounter those complications. Here
+%D we only show a few simple examples, but many other
+%D alternatives are possible by setting up the functions built
+%D in \PDF\ in the appropriate way.
+%D
+%D Shading has to do with interpolation between two or more
+%D points or user supplied ranges. In \PDF, the specifications
+%D of a shade has to be encapsulated in objects and passed on
+%D as resources. This is a \PDF\ level 1.3. feature. One can
+%D simulate three dimensional shades as well and define simple
+%D functions using a limited set of \POSTSCRIPT\ primitives.
+%D Given the power of \METAPOST\ and these \PDF\ features, we
+%D can achieve superb graphic effects.
+%D
+%D Since everything is hidden in \TEX\ and \METAPOST\ graphics,
+%D we can stick to high level \CONTEXT\ command, as shown in
+%D the following exmples.
+%D
+%D \startbuffer
+%D \startuniqueMPgraphic{CircularShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D circular_shade(p,0,.2red,.9red) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{LinearShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D linear_shade(p,0,.2blue,.9blue) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{DuotoneShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D linear_shade(p,2,.5green,.5red) ;
+%D \stopuniqueMPgraphic
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D These graphics can be hooked into the overlay mechanism,
+%D which is available in many commands.
+%D
+%D \startbuffer
+%D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}]
+%D \defineoverlay[demo 2][\uniqueMPgraphic {LinearShade}]
+%D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D These backgrounds can for instance be applied to \type
+%D {\framed}:
+%D
+%D \startbuffer
+%D \setupframed[width=3cm,height=2cm,frame=off]
+%D \startcombination[3*1]
+%D {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {}
+%D {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {}
+%D {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D There are a few more alternatives, determined by the second
+%D parameter passed to \type {circular_shade} and alike.
+%D
+%D \def\SomeShade#1#2#3#4#5%
+%D {\startuniqueMPgraphic{Shade-#1}
+%D width := \overlaywidth ;
+%D height := \overlayheight ;
+%D path p ; p := unitsquare xscaled width yscaled height ;
+%D #2_shade(p,#3,#4,#5) ;
+%D \stopuniqueMPgraphic
+%D \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]%
+%D \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}}
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0}
+%D {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1}
+%D {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2}
+%D {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3}
+%D {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0}
+%D {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1}
+%D {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2}
+%D {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3}
+%D {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \startcombination[4*1]
+%D {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0}
+%D {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1}
+%D {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2}
+%D {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D These macros closely cooperate with the \METAPOST\ module
+%D \type {mp-spec.mp}, which is part of the \CONTEXT\
+%D distribution.
+%D
+%D The low level (\PDF) implementation is based on the \TEX\
+%D based \METAPOST\ to \PDF\ converter. Shading is supported
+%D by overloading the \type {fill} operator as implemented
+%D earlier. In \PDF\ type~2 and~3 shading functions are
+%D specified in terms of:
+%D
+%D \starttabulate[|Tl|l|]
+%D \NC /Domain \NC sort of meeting range \NC \NR
+%D \NC /C0 \NC inner shade \NC \NR
+%D \NC /C1 \NC outer shade \NC \NR
+%D \NC /N \NC smaller values, bigger inner circles \NC \NR
+%D \stoptabulate
+%D
+%D An example of using both special features is the
+%D following.
+%D
+%D \starttyping
+%D \startMPpage
+%D externalfigure "hakker1b.png" scaled 22cm rotated 10 shifted (-2cm,0cm);
+%D externalfigure "hakker1b.png" scaled 10cm rotated -10 ;
+%D externalfigure "hakker1b.png" scaled 7cm rotated 45 shifted (8cm,12cm) ;
+%D path p ; p := unitcircle xscaled 15cm yscaled 20cm;
+%D path q ; q := p rotatedaround(center p,90) ;
+%D path r ; r := buildcycle(p,q) ; clip currentpicture to r ;
+%D path s ; s := boundingbox currentpicture enlarged 5mm ;
+%D picture c ; c := currentpicture ; currentpicture := nullpicture ;
+%D circular_shade(s,0,.2red,.9red) ;
+%D addto currentpicture also c ;
+%D \stopMPpage
+%D \stoptyping
+
+\startMPinitializations
+ mp_shade_version := 2 ;
+\stopMPinitializations
+
+%D This is done much cleaner in \MPLIB.
+
+% %D A common hook.
+%
+% \let\MPfshowcommand\empty
+%
+% \def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
+% {\def\MPtextdata{#3}% % delegate the splitter to lua + redesign
+% \def\MPtextsize{#2}%
+% \def\lastMPmoveX{#4}%
+% \def\lastMPmoveY{#5}%
+% \defconvertedcommand\MPtextdata\MPtextdata % no edef
+% \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
+% \executeifdefined{handleMPtext\MPtexttag}
+% {\setbox\scratchbox\hbox
+% {\font\temp=#1\space at #2\onebasepoint
+% \let\c\char
+% \temp
+% \MPfshowcommand{#3}}%
+% \setbox\scratchbox\hbox
+% {\hskip#4\onebasepoint
+% \raise#5\onebasepoint
+% \box\scratchbox}%
+% \smashbox\scratchbox
+% \box\scratchbox}}
+
+\unexpanded\def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
+ {\setbox\scratchbox\hbox
+ {\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}%
+ \setbox\scratchbox\hbox
+ {\hskip#4\onebasepoint \raise#5\onebasepoint \box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox}
+
+%D The boundingbox.
+
+\def\MPSboundingbox#1#2#3#4%
+ {\xdef\MPllx{#1}\xdef\MPlly{#2}\xdef\MPurx{#3}\xdef\MPury{#4}%
+ \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
+ \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}
+
+\MPSboundingbox0000
+
+%D Test code:
+%D
+%D \startbuffer
+%D \startMPcode
+%D fill fullcircle scaled 3cm withcolor red ;
+%D fill fullcircle scaled 2cm withcolor green ;
+%D fill fullcircle scaled 1cm withcolor blue ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ;
+%D fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ;
+%D fill fullcircle scaled 1cm withcolor cmyk(0,0,1,0) ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D draw fullcircle scaled 3cm dashed evenly ;
+%D draw fullcircle scaled 2cm dashed withdots ;
+%D draw origin withpen pencircle scaled 3mm;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red);
+%D fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red);
+%D fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green);
+%D fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5));
+%D currentpicture := currentpicture shifted (12cm,-4cm) ;
+%D draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D % bug: shift
+%D draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30 ;
+%D draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ;
+%D filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ;
+%D currentpicture := currentpicture shifted (-4cm,0) ;
+%D % shade cannot handle shift
+%D circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ;
+%D circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ;
+%D filldraw boundingbox currentpicture enlarged -3cm withpen pencircle scaled 1pt withcolor .5white ;
+%D \stopMPcode
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+
+\protect \endinput
diff --git a/tex/context/base/meta-pdh.lua b/tex/context/base/meta-pdh.lua
new file mode 100644
index 000000000..05cdfc176
--- /dev/null
+++ b/tex/context/base/meta-pdh.lua
@@ -0,0 +1,602 @@
+if not modules then modules = { } end modules ['meta-pdf'] = {
+ version = 1.001,
+ comment = "companion to meta-pdf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This file contains the history of the converter. We keep it around as it
+-- relates to the development of luatex.
+
+-- This is the third version. Version 1 converted to Lua code,
+-- version 2 gsubbed the file into TeX code, and version 3 uses
+-- the new lpeg functionality and streams the result into TeX.
+
+-- We will move old stuff to edu.
+
+--~ old lpeg 0.4 lpeg 0.5
+--~ 100 times test graphic 2.45 (T:1.07) 0.72 (T:0.24) 0.580 (0.560 no table) -- 0.54 optimized for one space (T:0.19)
+--~ 100 times big graphic 10.44 4.30/3.35 nogb 2.914 (2.050 no table) -- 1.99 optimized for one space (T:0.85)
+--~ 500 times test graphic T:1.29 T:1.16 (T:1.10 no table) -- T:1.10
+
+-- only needed for mp output on disk
+
+local concat, format, find, gsub, gmatch = table.concat, string.format, string.find, string.gsub, string.gmatch
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+local tostring, tonumber, select = tostring, tonumber, select
+local lpegmatch = lpeg.match
+
+mptopdf = { }
+mptopdf.parsers = { }
+mptopdf.parser = 'none'
+mptopdf.n = 0
+
+function mptopdf.reset()
+ mptopdf.data = ""
+ mptopdf.path = { }
+ mptopdf.stack = { }
+ mptopdf.texts = { }
+ mptopdf.version = 0
+ mptopdf.shortcuts = false
+ mptopdf.resetpath()
+end
+
+function mptopdf.resetpath()
+ mptopdf.stack.close = false
+ mptopdf.stack.path = { }
+ mptopdf.stack.concat = nil
+ mptopdf.stack.special = false
+end
+
+mptopdf.reset()
+
+function mptopdf.parsers.none()
+ -- no parser set
+end
+
+function mptopdf.parse()
+ mptopdf.parsers[mptopdf.parser]()
+end
+
+-- old code
+
+mptopdf.steps = { }
+
+mptopdf.descapes = {
+ ['('] = "\\\\char40 ",
+ [')'] = "\\\\char41 ",
+ ['"'] = "\\\\char92 "
+}
+
+function mptopdf.descape(str)
+ str = gsub(str,"\\(%d%d%d)",function(n)
+ return "\\char" .. tonumber(n,8) .. " "
+ end)
+ return gsub(str,"\\([%(%)\\])",mptopdf.descapes)
+end
+
+function mptopdf.steps.descape(str)
+ str = gsub(str,"\\(%d%d%d)",function(n)
+ return "\\\\char" .. tonumber(n,8) .. " "
+ end)
+ return gsub(str,"\\([%(%)\\])",mptopdf.descapes)
+end
+
+function mptopdf.steps.strip() -- .3 per expr
+ mptopdf.data = gsub(mptopdf.data,"^(.-)%%+Page:.-%c+(.*)%s+%a+%s+%%+EOF.*$", function(preamble, graphic)
+ local bbox = "0 0 0 0"
+ for b in gmatch(preamble,"%%%%%a+oundingBox: +(.-)%c+") do
+ bbox = b
+ end
+ local name, version = gmatch(preamble,"%%%%Creator: +(.-) +(.-) ")
+ mptopdf.version = tostring(version or "0")
+ if find(preamble,"/hlw{0 dtransform") then
+ mptopdf.shortcuts = true
+ end
+ -- the boundingbox specification needs to come before data, well, not really
+ return bbox .. " boundingbox\n" .. "\nbegindata\n" .. graphic .. "\nenddata\n"
+ end, 1)
+ mptopdf.data = gsub(mptopdf.data,"%%%%MetaPostSpecials: +(.-)%c+", "%1 specials\n", 1)
+ mptopdf.data = gsub(mptopdf.data,"%%%%MetaPostSpecial: +(.-)%c+", "%1 special\n")
+ mptopdf.data = gsub(mptopdf.data,"%%.-%c+", "")
+end
+
+function mptopdf.steps.cleanup()
+ if not mptopdf.shortcuts then
+ mptopdf.data = gsub(mptopdf.data,"gsave%s+fill%s+grestore%s+stroke", "both")
+ mptopdf.data = gsub(mptopdf.data,"([%d%.]+)%s+([%d%.]+)%s+dtransform%s+exch%s+truncate%s+exch%s+idtransform%s+pop%s+setlinewidth", function(wx,wy)
+ if tonumber(wx) > 0 then return wx .. " setlinewidth" else return wy .. " setlinewidth" end
+ end)
+ mptopdf.data = gsub(mptopdf.data,"([%d%.]+)%s+([%d%.]+)%s+dtransform%s+truncate%s+idtransform%s+setlinewidth%s+pop", function(wx,wy)
+ if tonumber(wx) > 0 then return wx .. " setlinewidth" else return wy .. " setlinewidth" end
+ end)
+ end
+end
+
+function mptopdf.steps.convert()
+ mptopdf.data = gsub(mptopdf.data,"%c%((.-)%) (.-) (.-) fshow", function(str,font,scale)
+ mptopdf.texts[mptopdf.texts+1] = {mptopdf.steps.descape(str), font, scale}
+ return "\n" .. #mptopdf.texts .. " textext"
+ end)
+ mptopdf.data = gsub(mptopdf.data,"%[%s*(.-)%s*%]", function(str)
+ return gsub(str,"%s+"," ")
+ end)
+ local t
+ mptopdf.data = gsub(mptopdf.data,"%s*([^%a]-)%s*(%a+)", function(args,cmd)
+ if cmd == "textext" then
+ t = mptopdf.texts[tonumber(args)]
+ return "mps.textext(" .. "\"" .. t[2] .. "\"," .. t[3] .. ",\"" .. t[1] .. "\")\n"
+ else
+ return "mps." .. cmd .. "(" .. gsub(args," +",",") .. ")\n"
+ end
+ end)
+end
+
+function mptopdf.steps.process()
+ assert(loadstring(mptopdf.data))() -- () runs the loaded chunk
+end
+
+function mptopdf.parsers.gsub()
+ mptopdf.steps.strip()
+ mptopdf.steps.cleanup()
+ mptopdf.steps.convert()
+ mptopdf.steps.process()
+end
+
+-- end of old code
+
+-- from lua to tex
+
+function mptopdf.pdfcode(str)
+ texsprint(ctxcatcodes,"\\pdfliteral{" .. str .. "}") -- \\MPScode
+end
+
+function mptopdf.texcode(str)
+ texsprint(ctxcatcodes,str)
+end
+
+-- auxiliary functions
+
+function mptopdf.flushconcat()
+ if mptopdf.stack.concat then
+ mptopdf.pdfcode(concat(mptopdf.stack.concat," ") .. " cm")
+ mptopdf.stack.concat = nil
+ end
+end
+
+function mptopdf.flushpath(cmd)
+ -- faster: no local function and loop
+ if #mptopdf.stack.path > 0 then
+ local path = { }
+ if mptopdf.stack.concat then
+ local sx, sy = mptopdf.stack.concat[1], mptopdf.stack.concat[4]
+ local rx, ry = mptopdf.stack.concat[2], mptopdf.stack.concat[3]
+ local tx, ty = mptopdf.stack.concat[5], mptopdf.stack.concat[6]
+ local d = (sx*sy) - (rx*ry)
+ local function mpconcat(px, py)
+ return (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d
+ end
+ local stackpath = mptopdf.stack.path
+ for k=1,#stackpath do
+ local v = stackpath[k]
+ v[1],v[2] = mpconcat(v[1],v[2])
+ if #v == 7 then
+ v[3],v[4] = mpconcat(v[3],v[4])
+ v[5],v[6] = mpconcat(v[5],v[6])
+ end
+ path[#path+1] = concat(v," ")
+ end
+ else
+ local stackpath = mptopdf.stack.path
+ for k=1,#stackpath do
+ path[#path+1] = concat(stackpath[k]," ")
+ end
+ end
+ mptopdf.flushconcat()
+ mptopdf.texcode("\\MPSpath{" .. concat(path," ") .. "}")
+ if mptopdf.stack.close then
+ mptopdf.texcode("\\MPScode{h " .. cmd .. "}")
+ else
+ mptopdf.texcode("\\MPScode{" .. cmd .."}")
+ end
+ end
+ mptopdf.resetpath()
+end
+
+function mptopdf.loaded(name)
+ local ok, n
+ mptopdf.reset()
+ ok, mptopdf.data, n = resolvers.loadbinfile(name, 'tex') -- we need a binary load !
+ return ok
+end
+
+if not mptopdf.parse then
+ function mptopdf.parse() end -- forward declaration
+end
+
+function mptopdf.convertmpstopdf(name)
+ if mptopdf.loaded(name) then
+ mptopdf.n = mptopdf.n + 1
+ statistics.starttiming(mptopdf)
+ mptopdf.parse()
+ mptopdf.reset()
+ statistics.stoptiming(mptopdf)
+ else
+ tex.print("file " .. name .. " not found")
+ end
+end
+
+-- mp interface
+
+mps = mps or { }
+
+function mps.creator(a, b, c)
+ mptopdf.version = tonumber(b)
+end
+
+function mps.creationdate(a)
+ mptopdf.date= a
+end
+
+function mps.newpath()
+ mptopdf.stack.path = { }
+end
+
+function mps.boundingbox(llx, lly, urx, ury)
+ mptopdf.texcode("\\MPSboundingbox{" .. llx .. "}{" .. lly .. "}{" .. urx .. "}{" .. ury .. "}")
+end
+
+function mps.moveto(x,y)
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {x,y,"m"}
+end
+
+function mps.curveto(ax, ay, bx, by, cx, cy)
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {ax,ay,bx,by,cx,cy,"c"}
+end
+
+function mps.lineto(x,y)
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {x,y,"l"}
+end
+
+function mps.rlineto(x,y)
+ local dx, dy = 0, 0
+ if #mptopdf.stack.path > 0 then
+ dx, dy = mptopdf.stack.path[#mptopdf.stack.path][1], mptopdf.stack.path[#mptopdf.stack.path][2]
+ end
+ mptopdf.stack.path[#mptopdf.stack.path+1] = {dx,dy,"l"}
+end
+
+function mps.translate(tx,ty)
+ mptopdf.pdfcode("1 0 0 0 1 " .. tx .. " " .. ty .. " cm")
+end
+
+function mps.scale(sx,sy)
+ mptopdf.stack.concat = {sx,0,0,sy,0,0}
+end
+
+function mps.concat(sx, rx, ry, sy, tx, ty)
+ mptopdf.stack.concat = {sx,rx,ry,sy,tx,ty}
+end
+
+function mps.setlinejoin(d)
+ mptopdf.pdfcode(d .. " j")
+end
+
+function mps.setlinecap(d)
+ mptopdf.pdfcode(d .. " J")
+end
+
+function mps.setmiterlimit(d)
+ mptopdf.pdfcode(d .. " M")
+end
+
+function mps.gsave()
+ mptopdf.pdfcode("q")
+end
+
+function mps.grestore()
+ mptopdf.pdfcode("Q")
+end
+
+function mps.setdash(...)
+ local n = select("#",...)
+ mptopdf.pdfcode("[" .. concat({...}," ",1,n-1) .. "] " .. select(n,...) .. " d")
+end
+
+function mps.resetdash()
+ mptopdf.pdfcode("[ ] 0 d")
+end
+
+function mps.setlinewidth(d)
+ mptopdf.pdfcode(d .. " w")
+end
+
+function mps.closepath()
+ mptopdf.stack.close = true
+end
+
+function mps.fill()
+ mptopdf.flushpath('f')
+end
+
+function mps.stroke()
+ mptopdf.flushpath('S')
+end
+
+function mps.both()
+ mptopdf.flushpath('B')
+end
+
+function mps.clip()
+ mptopdf.flushpath('W n')
+end
+
+function mps.textext(font, scale, str) -- old parser
+ local dx, dy = 0, 0
+ if #mptopdf.stack.path > 0 then
+ dx, dy = mptopdf.stack.path[1][1], mptopdf.stack.path[1][2]
+ end
+ mptopdf.flushconcat()
+ mptopdf.texcode("\\MPStextext{"..font.."}{"..scale.."}{"..str.."}{"..dx.."}{"..dy.."}")
+ mptopdf.resetpath()
+end
+
+--~ function mps.handletext(font,scale.str,dx,dy)
+--~ local one, two = string.match(str, "^(%d+)::::(%d+)")
+--~ if one and two then
+--~ mptopdf.texcode("\\MPTOPDFtextext{"..font.."}{"..scale.."}{"..one.."}{"..two.."}{"..dx.."}{"..dy.."}")
+--~ else
+--~ mptopdf.texcode("\\MPTOPDFtexcode{"..font.."}{"..scale.."}{"..str.."}{"..dx.."}{"..dy.."}")
+--~ end
+--~ end
+
+function mps.setrgbcolor(r,g,b) -- extra check
+ r, g = tonumber(r), tonumber(g) -- needed when we use lpeg
+ if r == 0.0123 and g < 0.1 then
+ mptopdf.texcode("\\MPSspecial{" .. g*10000 .. "}{" .. b*10000 .. "}")
+ elseif r == 0.123 and g < 0.1 then
+ mptopdf.texcode("\\MPSspecial{" .. g* 1000 .. "}{" .. b* 1000 .. "}")
+ else
+ mptopdf.texcode("\\MPSrgb{" .. r .. "}{" .. g .. "}{" .. b .. "}")
+ end
+end
+
+function mps.setcmykcolor(c,m,y,k)
+ mptopdf.texcode("\\MPScmyk{" .. c .. "}{" .. m .. "}{" .. y .. "}{" .. k .. "}")
+end
+
+function mps.setgray(s)
+ mptopdf.texcode("\\MPSgray{" .. s .. "}")
+end
+
+function mps.specials(version,signal,factor) -- 2.0 123 1000
+end
+
+function mps.special(...) -- 7 1 0.5 1 0 0 1 3
+ local n = select("#",...)
+ mptopdf.texcode("\\MPSbegin\\MPSset{" .. concat({...},"}\\MPSset{",2,n) .. "}\\MPSend")
+end
+
+function mps.begindata()
+end
+
+function mps.enddata()
+end
+
+function mps.showpage()
+end
+
+mps.n = mps.newpath -- n
+mps.p = mps.closepath -- h
+mps.l = mps.lineto -- l
+mps.r = mps.rlineto -- r
+mps.m = mps.moveto -- m
+mps.c = mps.curveto -- c
+mps.hlw = mps.setlinewidth
+mps.vlw = mps.setlinewidth
+
+mps.C = mps.setcmykcolor -- k
+mps.G = mps.setgray -- g
+mps.R = mps.setrgbcolor -- rg
+
+mps.lj = mps.setlinejoin -- j
+mps.ml = mps.setmiterlimit -- M
+mps.lc = mps.setlinecap -- J
+mps.sd = mps.setdash -- d
+mps.rd = mps.resetdash
+
+mps.S = mps.stroke -- S
+mps.F = mps.fill -- f
+mps.B = mps.both -- B
+mps.W = mps.clip -- W
+
+mps.q = mps.gsave -- q
+mps.Q = mps.grestore -- Q
+
+mps.s = mps.scale -- (not in pdf)
+mps.t = mps.concat -- (not the same as pdf anyway)
+
+mps.P = mps.showpage
+
+-- experimental
+
+function mps.attribute(id,value)
+ mptopdf.texcode("\\attribute " .. id .. "=" .. value .. " ")
+-- mptopdf.texcode("\\dompattribute{" .. id .. "}{" .. value .. "}")
+end
+
+-- lpeg parser
+
+-- The lpeg based parser is rather optimized for the kind of output
+-- that MetaPost produces. It's my first real lpeg code, which may
+-- show. Because the parser binds to functions, we define it last.
+
+do -- assumes \let\c\char
+
+ local byte = string.byte
+ local digit = lpeg.R("09")
+ local spec = digit^2 * lpeg.P("::::") * digit^2
+ local text = lpeg.Cc("{") * (
+ lpeg.P("\\") * ( (digit * digit * digit) / function(n) return "c" .. tonumber(n,8) end) +
+ lpeg.P(" ") / function(n) return "\\c32" end + -- never in new mp
+ lpeg.P(1) / function(n) return "\\c" .. byte(n) end
+ ) * lpeg.Cc("}")
+ local package = lpeg.Cs(spec + text^0)
+
+ function mps.fshow(str,font,scale) -- lpeg parser
+ mps.textext(font,scale,lpegmatch(package,str))
+ end
+
+end
+
+do
+
+ local eol = lpeg.S('\r\n')^1
+ local sp = lpeg.P(' ')^1
+ local space = lpeg.S(' \r\n')^1
+ local number = lpeg.S('0123456789.-+')^1
+ local nonspace = lpeg.P(1-lpeg.S(' \r\n'))^1
+
+ local cnumber = lpeg.C(number)
+ local cstring = lpeg.C(nonspace)
+
+ local specials = (lpeg.P("%%MetaPostSpecials:") * sp * (cstring * sp^0)^0 * eol) / mps.specials
+ local special = (lpeg.P("%%MetaPostSpecial:") * sp * (cstring * sp^0)^0 * eol) / mps.special
+ local boundingbox = (lpeg.P("%%BoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+ local highresboundingbox = (lpeg.P("%%HiResBoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox
+
+ local setup = lpeg.P("%%BeginSetup") * (1 - lpeg.P("%%EndSetup") )^1
+ local prolog = lpeg.P("%%BeginProlog") * (1 - lpeg.P("%%EndProlog"))^1
+ local comment = lpeg.P('%')^1 * (1 - eol)^1
+
+ local curveto = ((cnumber * sp)^6 * lpeg.P("curveto") ) / mps.curveto
+ local lineto = ((cnumber * sp)^2 * lpeg.P("lineto") ) / mps.lineto
+ local rlineto = ((cnumber * sp)^2 * lpeg.P("rlineto") ) / mps.rlineto
+ local moveto = ((cnumber * sp)^2 * lpeg.P("moveto") ) / mps.moveto
+ local setrgbcolor = ((cnumber * sp)^3 * lpeg.P("setrgbcolor") ) / mps.setrgbcolor
+ local setcmykcolor = ((cnumber * sp)^4 * lpeg.P("setcmykcolor") ) / mps.setcmykcolor
+ local setgray = ((cnumber * sp)^1 * lpeg.P("setgray") ) / mps.setgray
+ local newpath = ( lpeg.P("newpath") ) / mps.newpath
+ local closepath = ( lpeg.P("closepath") ) / mps.closepath
+ local fill = ( lpeg.P("fill") ) / mps.fill
+ local stroke = ( lpeg.P("stroke") ) / mps.stroke
+ local clip = ( lpeg.P("clip") ) / mps.clip
+ local both = ( lpeg.P("gsave fill grestore")) / mps.both
+ local showpage = ( lpeg.P("showpage") )
+ local setlinejoin = ((cnumber * sp)^1 * lpeg.P("setlinejoin") ) / mps.setlinejoin
+ local setlinecap = ((cnumber * sp)^1 * lpeg.P("setlinecap") ) / mps.setlinecap
+ local setmiterlimit = ((cnumber * sp)^1 * lpeg.P("setmiterlimit") ) / mps.setmiterlimit
+ local gsave = ( lpeg.P("gsave") ) / mps.gsave
+ local grestore = ( lpeg.P("grestore") ) / mps.grestore
+
+ local setdash = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("setdash")) / mps.setdash
+ local concat = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("concat") ) / mps.concat
+ local scale = ( (cnumber * sp^0)^6 * sp * lpeg.P("concat") ) / mps.concat
+
+ local fshow = (lpeg.P("(") * lpeg.C((1-lpeg.P(")"))^1) * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mps.fshow
+ local fshow = (lpeg.P("(") *
+ lpeg.Cs( ( lpeg.P("\\(")/"\\050" + lpeg.P("\\)")/"\\051" + (1-lpeg.P(")")) )^1 )
+ * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mps.fshow
+
+ local setlinewidth_x = (lpeg.P("0") * sp * cnumber * sp * lpeg.P("dtransform truncate idtransform setlinewidth pop")) / mps.setlinewidth
+ local setlinewidth_y = (cnumber * sp * lpeg.P("0 dtransform exch truncate exch idtransform pop setlinewidth") ) / mps.setlinewidth
+
+ local c = ((cnumber * sp)^6 * lpeg.P("c") ) / mps.curveto -- ^6 very inefficient, ^1 ok too
+ local l = ((cnumber * sp)^2 * lpeg.P("l") ) / mps.lineto
+ local r = ((cnumber * sp)^2 * lpeg.P("r") ) / mps.rlineto
+ local m = ((cnumber * sp)^2 * lpeg.P("m") ) / mps.moveto
+ local vlw = ((cnumber * sp)^1 * lpeg.P("vlw")) / mps.setlinewidth
+ local hlw = ((cnumber * sp)^1 * lpeg.P("hlw")) / mps.setlinewidth
+
+ local R = ((cnumber * sp)^3 * lpeg.P("R") ) / mps.setrgbcolor
+ local C = ((cnumber * sp)^4 * lpeg.P("C") ) / mps.setcmykcolor
+ local G = ((cnumber * sp)^1 * lpeg.P("G") ) / mps.setgray
+
+ local lj = ((cnumber * sp)^1 * lpeg.P("lj") ) / mps.setlinejoin
+ local ml = ((cnumber * sp)^1 * lpeg.P("ml") ) / mps.setmiterlimit
+ local lc = ((cnumber * sp)^1 * lpeg.P("lc") ) / mps.setlinecap
+
+ local n = lpeg.P("n") / mps.newpath
+ local p = lpeg.P("p") / mps.closepath
+ local S = lpeg.P("S") / mps.stroke
+ local F = lpeg.P("F") / mps.fill
+ local B = lpeg.P("B") / mps.both
+ local W = lpeg.P("W") / mps.clip
+ local P = lpeg.P("P") / mps.showpage
+
+ local q = lpeg.P("q") / mps.gsave
+ local Q = lpeg.P("Q") / mps.grestore
+
+ local sd = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("sd")) / mps.setdash
+ local rd = ( lpeg.P("rd")) / mps.resetdash
+
+ local s = ( (cnumber * sp^0)^2 * lpeg.P("s") ) / mps.scale
+ local t = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("t") ) / mps.concat
+
+ -- experimental
+
+ local attribute = ((cnumber * sp)^2 * lpeg.P("attribute")) / mps.attribute
+ local A = ((cnumber * sp)^2 * lpeg.P("A")) / mps.attribute
+
+ local preamble = (
+ prolog + setup +
+ boundingbox + highresboundingbox + specials + special +
+ comment
+ )
+
+ local procset = (
+ lj + ml + lc +
+ c + l + m + n + p + r +
+ A +
+ R + C + G +
+ S + F + B + W +
+ vlw + hlw +
+ Q + q +
+ sd + rd +
+ t + s +
+ fshow +
+ P
+ )
+
+ local verbose = (
+ curveto + lineto + moveto + newpath + closepath + rlineto +
+ setrgbcolor + setcmykcolor + setgray +
+ attribute +
+ setlinejoin + setmiterlimit + setlinecap +
+ stroke + fill + clip + both +
+ setlinewidth_x + setlinewidth_y +
+ gsave + grestore +
+ concat + scale +
+ fshow +
+ setdash + -- no resetdash
+ showpage
+ )
+
+ -- order matters in terms of speed / we could check for procset first
+
+ local captures_old = ( space + verbose + preamble )^0
+ local captures_new = ( space + procset + preamble + verbose )^0
+
+ function mptopdf.parsers.lpeg()
+ if find(mptopdf.data,"%%%%BeginResource: procset mpost") then
+ lpegmatch(captures_new,mptopdf.data)
+ else
+ lpegmatch(captures_old,mptopdf.data)
+ end
+ end
+
+end
+
+mptopdf.parser = 'lpeg'
+
+-- status info
+
+statistics.register("mps conversion time",function()
+ local n = mptopdf.n
+ if n > 0 then
+ return format("%s seconds, %s conversions", statistics.elapsedtime(mptopdf),n)
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/meta-pdh.mkiv b/tex/context/base/meta-pdh.mkiv
new file mode 100644
index 000000000..7cdd1471f
--- /dev/null
+++ b/tex/context/base/meta-pdh.mkiv
@@ -0,0 +1,780 @@
+%D \module
+%D [ file=meta-pdf,
+%D version=2006.06.07,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Conversion to \PDF,
+%D author=Hans Hagen \& others (see text),
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Formerly known as supp-pdf.tex and supp-mpe.tex and meta-pdf.mkiv.
+%D
+%D Beware: this file is not used but kept for historic purposed!
+
+% \useMPgraphic{1}
+% \testfeatureonce{250}{\setbox0\hbox{\convertMPtoPDF{test-mps-mpgraph.1}{1}{1}}}
+%
+% 8.4 : mkii, direct parsing by tex
+% 11.8 : mkiv, dirty conversion (10.8 with dirty tricks)
+% 14.5 : mkiv, clean conversion
+% 7.4 : mkiv, simulated clean direct lua from mp
+% 0.3 : time taken by tex to handle converted code
+%
+% timings may differ now that we revamped the backend
+
+\registerctxluafile{meta-pdf}{1.003}
+
+%D We will clean up the color mess later.
+
+\writestatus{loading}{MetaPost Graphics / MPS to PDF}
+
+\unprotect
+
+%D First we define a handy constant:
+
+\bgroup \catcode`\%=\@@other \xdef\letterpercent{\string%} \egroup
+
+%D \macros
+%D {convertMPtoPDF}
+%D
+%D The next set of macros implements \METAPOST\ to \PDF\
+%D conversion. The traditional method is in the MkII file.
+%D
+%D The main conversion command is:
+%D
+%D \starttyping
+%D \convertMPtoPDF {filename} {x scale} {y scale}
+%D \stoptyping
+%D
+%D The dimensions are derived from the bounding box. So we
+%D only have to say:
+%D
+%D \starttyping
+%D \convertMPtoPDF{mp-pra-1.eps}{1}{1}
+%D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5}
+%D \stoptyping
+
+%D \macros
+%D {makeMPintoPDFobject,lastPDFMPobject}
+%D
+%D For experts there are a few more options. When attributes
+%D are to be added, the code must be embedded in an object
+%D accompanied with the appropriate directives. One can
+%D influence this process with \type {\makeMPintoPDFobject}.
+%D
+%D This option defaults to~0, because \CONTEXT\ takes care
+%D of objects at another level, which saves some bytes.
+%D
+%D \starttabulate[|l|l|p|]
+%D \NC 0 \NC never \NC don't use an object \NC\NR
+%D \NC 1 \NC always \NC always use an object \NC\NR
+%D \NC 2 \NC optional \NC use object when needed \NC\NR
+%D \stoptabulate
+%D
+%D The last object number used is avaliable in the macro
+%D \type {\lastPDFMPobject}.
+
+\ifx\makeMPintoPDFobject \undefined \chardef\makeMPintoPDFobject \zerocount \fi
+\ifx\everyMPtoPDFconversion\undefined \newtoks\everyMPtoPDFconversion \fi
+
+\let\lastPDFMPobject \!!zerocount
+\let\currentPDFresources\empty
+\let\setMPextensions \relax
+
+\def\PDFMPformoffset
+ {\ifx\objectoffset\undefined\zeropoint\else\objectoffset\fi}
+
+\def\resetMPvariables#1#2#3%
+ {\global\let\MPwidth \!!zeropoint
+ \global\let\MPheight\!!zeropoint
+ \global\let\MPllx \!!zerocount
+ \global\let\MPlly \!!zerocount
+ \global\let\MPurx \!!zerocount
+ \global\let\MPury \!!zerocount
+ \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi
+ \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi
+ \xdef\MPfilename {#1}}
+
+%D The main macro:
+
+\def\convertMPtoPDF#1#2#3% watch the transparency reset
+ {\resetMPvariables{#1}{#2}{#3}%
+ \vbox\bgroup
+ \forgetall
+ \offinterlineskip
+ \setbox\scratchbox\vbox\bgroup
+ \setnormalcatcodes % we can be in verbatim or so
+ \message{[MP to PDF]}%
+ \startMPresources
+ \pdfliteral{\letterpercent\space mps begin}%
+ \pdfliteral{q 1 0 0 1 0 0 cm}%
+ \ctxlua{mptopdf.convertmpstopdf("\MPfilename")}\removeunwantedspaces
+ \pdfliteral{Q}%
+ \pdfliteral{\letterpercent\space mps end}%
+ \stopMPresources
+ \egroup
+ \setbox\scratchbox\hbox\bgroup
+ \hskip-\MPllx\onebasepoint
+ \raise-\MPlly\onebasepoint
+ \box\scratchbox
+ \egroup
+ \setbox\scratchbox\vbox to \MPheight\bgroup
+ \vfill
+ \hsize\MPwidth
+ \smashbox\scratchbox
+ \box\scratchbox
+ \egroup
+ \wd\scratchbox\MPwidth
+ \ht\scratchbox\MPheight
+ \dopackageMPgraphic\scratchbox
+ \egroup}
+
+\let\processMPtoPDFfile\convertMPtoPDF
+
+%D A common hook.
+
+\let\MPfshowcommand\empty
+
+%D Objects.
+
+\def\dopackageMPgraphic#1% #1 = boxregister
+ {\ifcase\makeMPintoPDFobject\or\or\ifx\currentPDFresources\empty\else
+ % an existing value of 2 signals object support (set elsewhere)
+ \chardef\makeMPintoPDFobject\plusone
+ \fi\fi
+ \ifcase\makeMPintoPDFobject
+ \box#1%
+ \or
+ \scratchdimen\PDFMPformoffset\relax
+ \ifdim\scratchdimen>\zeropoint % compensate for error
+ \setbox#1\vbox spread 2\scratchdimen
+ {\forgetall\vss\hbox spread 2\scratchdimen{\hss\box#1\hss}\vss}%
+ \fi
+ \setMPPDFobject{\currentPDFresources}{#1}%
+ \ifdim\scratchdimen>\zeropoint % compensate for error
+ \vbox to \MPheight
+ {\forgetall\vss\hbox to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
+ \else
+ \getMPPDFobject
+ \fi
+ \global\let\currentPDFresources\empty
+ \else
+ \box#1%
+ \fi}
+
+\def\setMPPDFobject#1#2% resources boxnumber
+ {\ifx\everyPDFxform\undefined\else\the\everyPDFxform\fi
+ \immediate\pdfxform resources{#1}#2%
+ \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}}
+
+\let\getMPPDFobject\relax
+
+%D \macros
+%D {deleteMPgraphic,
+%D startMPresources,
+%D stopMPresources}
+
+\ifx\deleteMPgraphic\undefined
+ \def\deleteMPgraphic#1{}
+\fi
+
+\ifx\startMPresources\undefined
+ \let\startMPresources\relax
+ \let\stopMPresources\relax
+\fi
+
+%D We implement extensions by using the \METAPOST\ special
+%D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones
+%D are flushed before or after the graphic data, but thereby
+%D are no longer connected to a position.
+%D
+%D We implement specials by overloading the \type {fill}
+%D operator. By counting the fills, we can let the converter
+%D treat the appropriate fill in a special way. The
+%D specification of the speciality can have two forms,
+%D determined by the setting of a boolean variable:
+%D
+%D \starttyping
+%D _inline_specials_ := false ; % comment like code (default)
+%D _inline_specials_ := true ; % command like code
+%D \stoptyping
+%D
+%D When the specification is embedded as comment, it looks
+%D like:
+%D
+%D \starttyping
+%D %%MetaPostSpecial
+%D \stoptyping
+%D
+%D The in||line alternative is more tuned for \POSTSCRIPT,
+%D since it permits us to define a macro \type {special}.
+%D
+%D \starttyping
+%D inline : special
+%D \stoptyping
+%D
+%D The \type {identifier} determines what to do, and the data
+%D can be used to accomplish this. A type~2 shading function
+%D has identifier~2. Alltogether, the number of parameters is
+%D specified in \type {size}. The \type {number} is the number
+%D of the fill that needs the special treatment. For a type~2
+%D and~3 shaded fill, the datablock contains the following
+
+%D data:
+%D
+%D \starttyping
+%D from to n inner_r g b x y outer_r g b x y
+%D from to n inner_r g b x y radius outer_r g b x y radius
+%D \stoptyping
+
+\newconditional\manyMPspecials \settrue\manyMPspecials
+
+%D In case of \PDF, we need to prepare resourcs.
+
+\newtoks\MPstartresources
+\newtoks\MPstopresources
+
+\def\startMPresources
+ {\the\MPstartresources}
+
+\def\stopMPresources
+ {\the\MPstopresources}
+
+%D Some day we may consider collecting local resources.
+
+\appendtoks
+ \global\let\currentPDFresources\empty % kind of redundant
+\to \MPstartresources
+
+% \appendtoks
+% \collectPDFresources
+% \global\let\currentPDFresources\collectedPDFresources
+% \to \MPstopresources
+
+\appendtoksonce
+ \the\everyPDFxform
+\to \MPstopresources
+
+%D Since colors are not subjected to transformations, we can
+%D only use colors as signal. In our case, we use a dummy colored
+%D path with a red color component of \type {0.n}, so \type
+%D {0.001} is the first path and \type {0.010} the tenth. Since
+%D \METAPOST strips trailing zeros, we have to padd the string.
+
+\newif\ifMPcmykcolors
+\newif\ifMPspotcolors
+
+%D Specials:
+
+% \settrue \manyMPspecials \newcount\nofMParguments \let\extraMPpathcode\empty
+%
+% \def\@@MP {@@MP}
+% \def\@@MPSK{@MPSK@}
+%
+% \def\MPspecial{\@@MPSK\@@MPSK\gMPs\nofMParguments}
+%
+% \unexpanded\def\defineMPspecial#1#2%
+% {\setvalue{\@@MPSK\@@MPSK#1}{#2}}
+
+%D Special number~1 is dedicated to \CMYK\ support. If you
+%D want to know why: look at this:
+%D
+%D \startbuffer[mp]
+%D fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ;
+%D \stopbuffer
+%D
+%D \startbuffer[cmyk]
+%D \startcombination[4*1]
+%D {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3}
+%D {\definecolor[test][c=.9,y=.15] \processMPbuffer[mp]} {c=.9 y=.15}
+%D {\definecolor[test][c=.25,y=.8] \processMPbuffer[mp]} {c=.25 y=.8}
+%D {\definecolor[test][c=.45,y=.1] \processMPbuffer[mp]} {c=.45 y=.1}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \placefigure
+%D {\CMYK\ support disabled,
+%D conversion to \RGB.}
+%D {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no support in \METAPOST.}
+%D {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]}
+%D
+%D \placefigure
+%D {\CMYK\ support enabled,
+%D no conversion to \RGB,
+%D support in \METAPOST}
+%D {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]}
+
+% \let\revokeMPtransparencyspecial\relax
+
+%D Transparency support used specials 60 (rgb) and 61
+%D (cmyk).
+%D
+%D \startbuffer
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor transparent(1,.5,yellow) ;
+%D fill p rotated 210 withcolor transparent(1,.5,green) ;
+%D fill p rotated 330 withcolor transparent(1,.5,blue) ;
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+%D
+%D One can also communicate colors between \CONTEXT\ and
+%D \METAPOST:
+%D
+%D \startbuffer
+%D \definecolor[tcyan] [c=1,k=.2,t=.5]
+%D \definecolor[tmagenta][m=1,k=.2,t=.5]
+%D \definecolor[tyellow] [y=1,k=.2,t=.5]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D \startbuffer
+%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
+%D
+%D fill p rotated 90 withcolor \MPcolor{tcyan} ;
+%D fill p rotated 210 withcolor \MPcolor{tmagenta} ;
+%D fill p rotated 330 withcolor \MPcolor{tyellow} ;
+%D \stopbuffer
+%D
+%D \startlinecorrection \processMPbuffer \stoplinecorrection
+
+%D Shading is an example of a more advanced graphic feature,
+%D but users will seldom encounter those complications. Here
+%D we only show a few simple examples, but many other
+%D alternatives are possible by setting up the functions built
+%D in \PDF\ in the appropriate way.
+%D
+%D Shading has to do with interpolation between two or more
+%D points or user supplied ranges. In \PDF, the specifications
+%D of a shade has to be encapsulated in objects and passed on
+%D as resources. This is a \PDF\ level 1.3. feature. One can
+%D simulate three dimensional shades as well and define simple
+%D functions using a limited set of \POSTSCRIPT\ primitives.
+%D Given the power of \METAPOST\ and these \PDF\ features, we
+%D can achieve superb graphic effects.
+%D
+%D Since everything is hidden in \TEX\ and \METAPOST\ graphics,
+%D we can stick to high level \CONTEXT\ command, as shown in
+%D the following exmples.
+%D
+%D \startbuffer
+%D \startuniqueMPgraphic{CircularShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D circular_shade(p,0,.2red,.9red) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{LinearShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D linear_shade(p,0,.2blue,.9blue) ;
+%D \stopuniqueMPgraphic
+%D
+%D \startuniqueMPgraphic{DuotoneShade}
+%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
+%D linear_shade(p,2,.5green,.5red) ;
+%D \stopuniqueMPgraphic
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D These graphics can be hooked into the overlay mechanism,
+%D which is available in many commands.
+%D
+%D \startbuffer
+%D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}]
+%D \defineoverlay[demo 2][\uniqueMPgraphic {LinearShade}]
+%D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D These backgrounds can for instance be applied to \type
+%D {\framed}:
+%D
+%D \startbuffer
+%D \setupframed[width=3cm,height=2cm,frame=off]
+%D \startcombination[3*1]
+%D {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {}
+%D {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {}
+%D {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {}
+%D \stopcombination
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D There are a few more alternatives, determined by the second
+%D parameter passed to \type {circular_shade} and alike.
+%D
+%D \def\SomeShade#1#2#3#4#5%
+%D {\startuniqueMPgraphic{Shade-#1}
+%D width := \overlaywidth ;
+%D height := \overlayheight ;
+%D path p ; p := unitsquare xscaled width yscaled height ;
+%D #2_shade(p,#3,#4,#5) ;
+%D \stopuniqueMPgraphic
+%D \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]%
+%D \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}}
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0}
+%D {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1}
+%D {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2}
+%D {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3}
+%D {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D \startlinecorrection
+%D \startcombination[5*1]
+%D {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0}
+%D {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1}
+%D {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2}
+%D {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3}
+%D {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D \blank
+%D
+%D \startlinecorrection
+%D \startcombination[4*1]
+%D {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0}
+%D {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1}
+%D {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2}
+%D {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3}
+%D \stopcombination
+%D \stoplinecorrection
+%D
+%D These macros closely cooperate with the \METAPOST\ module
+%D \type {mp-spec.mp}, which is part of the \CONTEXT\
+%D distribution.
+%D
+%D The low level (\PDF) implementation is based on the \TEX\
+%D based \METAPOST\ to \PDF\ converter. Shading is supported
+%D by overloading the \type {fill} operator as implemented
+%D earlier. In \PDF\ type~2 and~3 shading functions are
+%D specified in terms of:
+%D
+%D \starttabulate[|Tl|l|]
+%D \NC /Domain \NC sort of meeting range \NC \NR
+%D \NC /C0 \NC inner shade \NC \NR
+%D \NC /C1 \NC outer shade \NC \NR
+%D \NC /N \NC smaller values, bigger inner circles \NC \NR
+%D \stoptabulate
+
+% \newcount\currentPDFshade % 0 % global (document wide) counter
+%
+% \def\dosetMPsomePDFshade#1#2%
+% {\immediate\pdfobj
+% {<>}%
+% \immediate\pdfobj
+% {<>}%
+% \global\advance\currentPDFshade \plusone
+% \ctxlua{lpdf.adddocumentshade("Sh\the\currentPDFshade",lpdf.reference(\the\pdflastobj))}%
+% \setxvalue{\@@MPSK#2}{\noexpand\dohandleMPshade{\the\currentPDFshade}}}
+%
+% \def\dosetMPlinearshade {\dosetMPsomePDFshade2}% #1
+% \def\dosetMPcircularshade{\dosetMPsomePDFshade3}% #1
+%
+% \defineMPspecial{30}
+% {\normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs{9}}{\gMPs{10}}{\gMPs{11}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs{12} \gMPs{13}}%
+% \dosetMPlinearshade{\gMPs{14}}}
+%
+% \defineMPspecial{31}
+% {\normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs4}{\gMPs5}{\gMPs6}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPrgbcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs7 \gMPs8 \gMPs9 \gMPs{13} \gMPs{14} \gMPs{15}}%
+% \dosetMPcircularshade{\gMPs{16}}}
+%
+% \defineMPspecial{32}
+% {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
+% \dosetMPlinearshade{\gMPs{16}}}
+%
+% \defineMPspecial{33}
+% {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}%
+% \dosetMPcircularshade{\gMPs{18}}}
+%
+% \defineMPspecial{34}
+% {\normalexpanded{\noexpand\resolveMPspotcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPspotcolor{\gMPs{10}}{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{14} \gMPs{15}}%
+% \dosetMPlinearshade{\gMPs{16}}}
+%
+% \defineMPspecial{35}
+% {\normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}}\to\MPshadeA
+% \normalexpanded{\noexpand\resolveMPcmykcolor{\gMPs{11}}{\gMPs{12}}{\gMPs{13}}{\gMPs{14}}}\to\MPshadeB
+% \edef\MPshadeC{\gMPs8 \gMPs9 \gMPs{10} \gMPs{15} \gMPs{16} \gMPs{17}}%
+% \dosetMPcircularshade{\gMPs{18}}}
+%
+% \newconditional\ignoreMPpath
+%
+% \def\dohandleMPshade#1%
+% {\revokeMPtransparencyspecial
+% \settrue\ignoreMPpath
+% \def\extraMPpathcode{/Sh#1 sh Q}%
+% \pdfliteral{q /Pattern cs}}
+%
+% \defineMPspecial{10}
+% {\setxvalue{\@@MPSK\gMPs8}%
+% {\noexpand\handleMPfigurespecial{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}{\gMPs8}}}
+%
+% \def\handleMPfigurespecial#1#2#3#4#5#6#7#8% todo : combine with ext fig
+% {\global\letvalue{\@@MPSK#8}\empty
+% \vbox to \zeropoint
+% {\vss
+% \hbox to \zeropoint
+% {\ifcase\pdfoutput\or % will be hooked into the special driver
+% \doiffileelse{#7}
+% {\doifundefinedelse{mps:x:#7}
+% {\immediate\pdfximage\!!width\onebasepoint\!!height\onebasepoint{#7}%
+% \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}%
+% {\message{[reusing figure #7]}}%
+% \pdfliteral{q #1 #2 #3 #4 #5 #6 cm}%
+% \rlap{\getvalue{mps:x:#7}}%
+% \pdfliteral{Q}}
+% {\message{[unknown figure #7]}}%
+% \fi
+% \hss}}}
+
+%D An example of using both special features is the
+%D following.
+%D
+%D \starttyping
+%D \startMPpage
+%D externalfigure "hakker1b.png" scaled 22cm rotated 10 shifted (-2cm,0cm);
+%D externalfigure "hakker1b.png" scaled 10cm rotated -10 ;
+%D externalfigure "hakker1b.png" scaled 7cm rotated 45 shifted (8cm,12cm) ;
+%D path p ; p := unitcircle xscaled 15cm yscaled 20cm;
+%D path q ; q := p rotatedaround(center p,90) ;
+%D path r ; r := buildcycle(p,q) ; clip currentpicture to r ;
+%D path s ; s := boundingbox currentpicture enlarged 5mm ;
+%D picture c ; c := currentpicture ; currentpicture := nullpicture ;
+%D circular_shade(s,0,.2red,.9red) ;
+%D addto currentpicture also c ;
+%D \stopMPpage
+%D \stoptyping
+
+% \defineMPspecial{20}
+% {\setxvalue{\@@MPSK\gMPs6}%
+% {\noexpand\handleMPhyperlink{\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}}}
+%
+% \def\handleMPhyperlink#1#2#3#4#5#6%
+% {\global\letvalue{\@@MPSK#6}\empty
+% \setbox\scratchbox\hbox
+% {\setbox\scratchbox\null
+% \wd\scratchbox\dimexpr-#1\onebasepoint+#3\onebasepoint\relax
+% \ht\scratchbox\dimexpr-#2\onebasepoint+#4\onebasepoint\relax
+% \gotobox{\box\scratchbox}[#5]}%
+% \setbox\scratchbox\hbox
+% {\hskip\dimexpr\MPxoffset\onebasepoint+#1\onebasepoint\relax
+% \raise\dimexpr\MPyoffset\onebasepoint+#2\onebasepoint\relax
+% \box\scratchbox}%
+% \smashbox\scratchbox
+% \box\scratchbox}
+
+%D This special (number 50) passes positions to a tex file.
+%D This method uses a two||pass approach an (mis|)|used the
+%D context positioning macros. In \type {core-pos} we will
+%D implement the low level submacro needed.
+%D
+%D \startbuffer
+%D \definelayer[test]
+%D
+%D \setlayer
+%D [test]
+%D [x=\MPx{somepos-1},y=\MPy{somepos-1}]
+%D {Whatever we want here!}
+%D
+%D \setlayer
+%D [test]
+%D [x=\MPx{somepos-2},y=\MPy{somepos-2}]
+%D {Whatever we need there!}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 6cm withcolor red ;
+%D register ("somepos-1",1cm,2cm,center currentpicture) ;
+%D register ("somepos-2",4cm,3cm,(-1cm,-2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \framed[background=test,offset=overlay]{\useMPgraphic{oeps}}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here the width and height are not realy used, but one can
+%D imagine situations where tex has to work with values
+%D calculated by \METAPOST.
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D Later we will implement a more convenient macro:
+%D
+%D \starttyping
+%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
+%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
+%D \stoptyping
+
+% \defineMPspecial{50} % x y width height label
+% {\dosavepositionwhd
+% {\gMPs5}%
+% {0}%
+% {\the\dimexpr-\MPllx\onebasepoint+\gMPs1\onebasepoint\relax}
+% {\the\dimexpr\gMPs2\onebasepoint-\scratchdimen+\MPury\onebasepoint\relax}% scratchdimen ?
+% {\the\dimexpr\gMPs3\onebasepoint\relax}%
+% {\the\dimexpr\gMPs4\onebasepoint\relax}%
+% {0pt}}
+
+\startMPinitializations
+ mp_shade_version := 2 ;
+\stopMPinitializations
+
+%D This is done much cleaner in \MPLIB.
+
+\def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
+ {\def\MPtextdata{#3}% % delegate the splitter to lua + redesign
+ \def\MPtextsize{#2}%
+ \def\lastMPmoveX{#4}%
+ \def\lastMPmoveY{#5}%
+ \defconvertedcommand\MPtextdata\MPtextdata % no edef
+ \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
+ \executeifdefined{handleMPtext\MPtexttag}
+ {\setbox\scratchbox\hbox
+ {\font\temp=#1\space at #2\onebasepoint
+ \let\c\char
+ \temp
+ \MPfshowcommand{#3}}%
+ \setbox\scratchbox\hbox
+ {\hskip#4\onebasepoint
+ \raise#5\onebasepoint
+ \box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox}}
+
+%D We save the special variables on a stack. It's not that
+%D fast, but it make implementing the special more convenient.
+
+% \def\MPSbegin
+% {\nofMParguments\zerocount}
+%
+% \def\MPSend
+% {\csname\MPspecial\endcsname}
+%
+% \def\MPSset
+% {\advance\nofMParguments\plusone
+% \expandafter\def\csname\@@MP\number\nofMParguments\endcsname}
+%
+% \def\gMPs#1{\csname\@@MP\number#1\endcsname}
+
+%D The boundingbox.
+
+\def\MPSboundingbox#1#2#3#4%
+ {\xdef\MPllx{#1}\xdef\MPlly{#2}\xdef\MPurx{#3}\xdef\MPury{#4}%
+ \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
+ \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}
+
+\MPSboundingbox0000
+
+% \def\MPSspecial#1#2%
+% {\csname\@@MPSK#2\endcsname}
+
+%D A path is (in most cases) just a sequence of \PDF\ commands.
+
+% \newconditional\ignoreMPpath
+
+% \def\MPSpath
+% {\pdfliteral}
+
+% \def\MPScode % hack, will be improved
+% {\ifconditional\ignoreMPpath
+% \pdfliteral{h W n}%
+% \ifx\extraMPpathcode\empty\else
+% \pdfliteral{\extraMPpathcode}%
+% \let\extraMPpathcode\empty
+% \fi
+% \setfalse\ignoreMPpath
+% \expandafter\gobbleoneargument
+% \else
+% \expandafter\pdfliteral
+% \fi}
+
+%D Test code:
+
+% \startMPcode
+% fill fullcircle scaled 3cm withcolor red ;
+% fill fullcircle scaled 2cm withcolor green ;
+% fill fullcircle scaled 1cm withcolor blue ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ;
+% fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ;
+% fill fullcircle scaled 1cm withcolor cmyk(0,0,1,0) ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% draw fullcircle scaled 3cm dashed evenly ;
+% draw fullcircle scaled 2cm dashed withdots ;
+% draw origin withpen pencircle scaled 3mm;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red);
+% fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red);
+% fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green);
+% fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5));
+% currentpicture := currentpicture shifted (12cm,-4cm) ;
+% draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% % bug: shift
+% draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30 ;
+% draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ;
+% filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ;
+% currentpicture := currentpicture shifted (-4cm,0) ;
+% % shade cannot handle shift
+% circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ;
+% circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ;
+% filldraw boundingbox currentpicture enlarged -3cm withpen pencircle scaled 1pt withcolor .5white ;
+% \stopMPcode
+
+% We cannot use attributes for switching colors in mp literals because
+% grouping (qQ) interferes.
+
+% \def\dohandleMPshade#1%
+% {\revokeMPtransparencyspecial
+% \settrue\ignoreMPpath
+% \def\extraMPpathcode{/#1 sh Q}%
+% \pdfliteral{q /Pattern cs}}
+
+\protect \endinput
diff --git a/tex/context/base/meta-pre.tex b/tex/context/base/meta-pre.tex
new file mode 100644
index 000000000..cb861ff20
--- /dev/null
+++ b/tex/context/base/meta-pre.tex
@@ -0,0 +1,68 @@
+%D \module
+%D [ file=meta-pre,
+%D version=2001.03.21,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Predefined Goodies,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 In this library, we define a couple of handy graphics.
+
+% todo: use the predefine grid macros, mp code will move to
+% mp-* file
+
+\startuseMPgraphic{pagegrid}
+ StartPage ;
+ drawoptions(withcolor .8white) ;
+ fill Field[Text][Text] ;
+ drawoptions(withcolor .65white) ;
+ fill Field[Footer][Text] ;
+ fill Field[Header][Text] ;
+ fill Field[LeftMargin][Text] ;
+ fill Field[RightMargin][Text] ;
+ drawoptions(withcolor .65yellow) ;
+ fill Field[LeftEdge][Text] ;
+ fill Field[RightEdge][Text] ;
+ fill Field[Bottom][Text] ;
+ fill Field[Top][Text] ;
+ drawoptions(withpen pencircle scaled .3pt withcolor .65white) ;
+ for i=-3cm step 1cm until PaperWidth+3cm :
+ draw (i,-3cm)--(i,PaperHeight+3cm) ;
+ endfor ;
+ for i=PaperHeight+3cm step -1cm until -3cm :
+ draw (-3cm,i)--(PaperWidth+3cm,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled .15pt) ;
+ for i=.5cm-3cm step 1cm until PaperWidth+3cm :
+ draw (i,-3cm)--(i,PaperHeight+3cm) ;
+ endfor ;
+ for i=PaperHeight-.5cm+3cm step -1cm until -3cm :
+ draw (-3cm,i)--(PaperWidth+3cm,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled .3pt withcolor .65red) ;
+ for i=0 step 1cm until PaperWidth :
+ draw (i,0)--(i,PaperHeight) ;
+ endfor ;
+ for i=PaperHeight step -1cm until 0 :
+ draw (0,i)--(PaperWidth,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled .15pt withcolor .65red) ;
+ for i=.5cm step 1cm until PaperWidth :
+ draw (i,0)--(i,PaperHeight) ;
+ endfor ;
+ for i=PaperHeight-.5cm step -1cm until 0 :
+ draw (0,i)--(PaperWidth,i) ;
+ endfor ;
+ drawoptions(withpen pencircle scaled 5pt withcolor .65red) ;
+ draw ulcorner Page ;
+ StopPage ;
+\stopuseMPgraphic
+
+\defineoverlay[pagegrid][\useMPgraphic{pagegrid}]
+
+\endinput
diff --git a/tex/context/base/meta-tex.mkii b/tex/context/base/meta-tex.mkii
new file mode 100644
index 000000000..190a694d9
--- /dev/null
+++ b/tex/context/base/meta-tex.mkii
@@ -0,0 +1,350 @@
+%D \module
+%D [ file=meta-tex,
+%D version=2006.06.07,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=\METAPOST\ fast text insertion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Many thanks to Fabrice Popineau and Taco Hoekwater in helping me
+%D figure out some aspects of the text inclusion method implemented
+%D here. The following code is derived from a more advanced (and to
+%D be used) mechanism where \TEX, \METAPOST\ and \LUA\ play together.
+
+%D Much of this mechanism was written with running live DVD's of
+%D the Dave Matthews band in the background (or the corner of my
+%D screen).
+
+% todo: testmacro for empty pic
+
+\unprotect
+
+\newwrite\TeXtextwrite
+
+\def\openTeXtexts {\immediate\openout \TeXtextwrite\currentTeXtext.mpb\relax}
+\def\closeTeXtexts{\immediate\closeout\TeXtextwrite}
+
+\def\currentTeXtext {\jobname-mpgraph}
+\def\currentTeXstack{mpgtxt}
+
+\initializeboxstack\currentTeXstack
+
+\newtoks\collectedmptexts
+\newtoks\everyTeXtexts
+
+\chardef\TeXtextsmode\zerocount % no inheritance
+
+\long\def\startTeXtexts#1\stopTeXtexts
+ {\global\collectedmptexts\expandafter{\the\collectedmptexts#1}}
+
+\def\dostartTeXtexts
+ {\global\setfalse\TeXtextdone
+ \startnointerference
+ \openTeXtexts
+ \ifcase\TeXtextsmode
+ % normally there is no need for this (faster anyway)
+ \or
+ \scantokens\expandafter{\the\everyMPTEXgraphic}% brr
+ \or
+ \the\everyTeXtexts
+ \fi
+ \ifrunMPgraphics
+ \initializeboxstack\currentTeXstack
+ \else
+ \global\let\openTeXtexts\relax
+ \global\let\finishTeXtexts\closeTeXtexts
+ \fi}
+
+\def\dostopTeXtexts
+ {\ifrunMPgraphics
+ \closeTeXtexts
+ \fi
+ \stopnointerference}
+
+\let\finishTeXtexts\relax
+
+\appendtoks
+ \finishTeXtexts
+\to \everystoptext
+
+\newconditional\TeXtextdone
+
+% \long\def\TeXtext#1%
+% {\dowithnextboxcontent
+% {\setnormalcatcodes}
+% {\global\settrue\TeXtextdone
+% \immediate\write\TeXtextwrite{savetxt(#1,\the\wd\nextbox,\the\ht\nextbox,\the\dp\nextbox);}%
+% \savebox\currentTeXstack{#1}{\box\nextbox}}
+% \hbox}
+
+\long\def\TeXtext
+ {\dosingleempty\doTeXtext}
+
+% currently, colors in the converter don't use the color stack
+%
+% 0 = nothing, withcolor works ok, but nested colors fail
+% 1 = local color stack ok
+% 2 = obey color stack (not yet supported)
+
+\chardef\TeXtextcolormode\plusone
+
+\def\definetextext[#1]#2{\setvalue{textext@@#1}{#2}}
+
+% \definetextext[framed]{\framed}
+%
+% \startMPcode
+% draw \sometxt[framed]{black} rotated 45 ;
+% \stopMPcode
+
+\long\def\doTeXtext[#1]#2#3%
+ {\begingroup
+ \setnormalcatcodes
+ \chardef\activecharactermode\plusone % compensates ** in meta-ini.mkii
+ \endlinechar\minusone
+ \everyeof\emptytoks
+ %\def\ascii{#3}\scantokens\expandafter{\ascii}}%
+ \setbox\nextbox\hbox
+ {\ifcase\TeXtextcolormode
+ \scantokens{\executeifdefined{textext@@#1}\firstofoneargument{#3}}%
+ \else
+ \localcolortrue
+ \startcurrentcolor
+ \scantokens{\executeifdefined{textext@@#1}\firstofoneargument{#3}}%
+ \stopcurrentcolor
+ \fi}%
+ \global\settrue\TeXtextdone
+ \edef\currenttextxt{\number#2}%
+ \executeifdefined{textext::#1}{\getvalue{textext::depth}}%
+ \savebox\currentTeXstack\currenttextxt{\box\nextbox}%
+ \endgroup}
+
+\setvalue{textext::depth}{\immediate\write\TeXtextwrite{savetxt(\currenttextxt,\the\nextboxwd,\the\nextboxht,\the\nextboxdp) shifted (0,-\the\nextboxdp);}}
+\setvalue{textext::nodepth}{\immediate\write\TeXtextwrite{savetxt(\currenttextxt,\the\nextboxwd,\the\nextboxht,\the\nextboxdp);}}
+
+\setvalue{textext::d}{\getvalue{textext::depth}}
+\setvalue{textext::n}{\getvalue{textext::nodepth}}
+
+\newbox\mptextbox
+
+% \loadmapfile[lm-texnansi.map] % the font is not really used, i.e. nothing ends up in the file
+\definefontsynonym[MPtxtfont][texnansi-lmtt10]
+\definefont[localMPtxtfont][MPtxtfont at 10bp]
+
+\ifx\getTeXtext\undefined
+
+ % this took a while to figure out
+
+ \let\MPtextdata\empty
+
+ \def\getTeXtext
+ {\ifx\MPtextdata\empty\else
+ \localMPtxtfont
+ \setbox\mptextbox\hbox{\foundbox\currentTeXstack{\number\nofTeXtexts}}%
+ \setbox\scratchbox\hbox{\MPtextdata}% set in meta-pdf.mkii/mkiv
+ \edef\mpwd{\the\dimexpr\MPtextsize\dimexpr\wd\scratchbox/10\relax\relax}%
+ \edef\mpht{\the\dimexpr\MPtextsize\dimexpr\ht\scratchbox/10\relax\relax}%
+ \setbox\mptextbox\hbox{\raise\dp\mptextbox\box\mptextbox}%
+ \dp\mptextbox\zeropoint
+ \scale[\c!width=\mpwd,\c!height=\mpht]{\box\mptextbox}%
+ \fi}
+
+\fi
+
+\let\nofTeXtexts\!!zerocount
+
+\setvalue{handleMPtext00001}% only height in tag (00001)
+ {\setbox\scratchbox\hbox
+ {\obeyMPspecials
+ \edef\nofTeXtexts{\number\MPtextnumber}%
+ \getTeXtext}%
+ \setbox\scratchbox\hbox
+ {\hskip\lastMPmoveX\onebasepoint\raise\lastMPmoveY\onebasepoint
+ \box\scratchbox}%
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\zeropoint
+ \box\scratchbox}
+
+\startMPextensions
+ string txtfile ; txtfile := "\currentTeXtext.mpb" ;
+ string txtfont ; txtfont := "\truefontname{MPtxtfont}" ;
+ string txtpref ; txtpref := "00001::::" ;
+\stopMPextensions
+
+\newcount\metatxtcounter
+
+\long\def\dodofiltersometxt#1#2#3%
+ {\ifx#2\empty
+ \else
+ \advance\metatxtcounter\plusone
+ \TeXtext{\the\metatxtcounter}{#1}%
+ \expandafter\filtersometxt
+ \fi#2#3}
+
+\long\def\redofiltersometxt[#1]#2%
+ {\advance\metatxtcounter\plusone
+ \TeXtext[#1]{\the\metatxtcounter}{#2}%
+ \filtersometxt}
+
+\long\def\filtersometxt#1\sometxt
+ {\doifnextoptionalelse\redofiltersometxt\dodofiltersometxt}
+
+% cleaner in mkiv
+%
+% \filtersometxt abc\sometxt{def};hij\sometxt{klm};\sometxt{}\empty\relax
+
+\long\def\flushTeXtexts#1%
+ {\metatxtcounter\zerocount
+ \dostartTeXtexts
+ \the\collectedmptexts
+ \filtersometxt#1\sometxt{}\empty\relax
+ \dostopTeXtexts
+ \ifconditional\TeXtextdone
+ \immediate\write\MPwrite{loadtxts ; txtnext := 0 ;}%
+ \global\collectedmptexts\emptytoks
+ \fi
+ \metatxtcounter\zerocount}
+
+% \long\def\sometxt#1{sometxt(nexttxt)} % to be used in mp definitions, no ; here
+
+\long\def\sometxt #1#{\dosometxt} % grab optional [args]
+\long\def\dosometxt#1{sometxt(nexttxt)} % to be used in mp definitions, no ; here
+
+% we redefine the writer:
+
+\long\def\writecheckedMPgraphic#1%
+ {\ifforceMPTEXgraphic
+ \global\MPTEXgraphictrue
+ \else
+ \global\MPTEXgraphicfalse
+ \edef\ascii{#1}\defconvertedcommand\MPascii\ascii
+ \the\MPTEXgraphicchecks\relax % \relax is end condition!
+ \fi
+ \flushMPTEXgraphic% % verbatimtex etc
+ \flushTeXtexts{#1}% added
+ \writeMPgraphic{#1}} % potential optimization: pass \ascii
+
+\protect \endinput
+
+% torture test (will move)
+
+\startMPpage
+ numeric a_b_c ;
+ picture p ; pickup pencircle scaled .1pt ;
+ p := \sometxt{Just a \color[blue]{simple} example text.} ;
+ p := image(draw p; draw boundingbox p withcolor red; ) ;
+ p := p rotatedaround(center p, 360*(5/100)) ;
+ draw p ; draw boundingbox p withcolor blue ;
+ currentpicture := currentpicture scaled 20 ;
+ draw boundingbox currentpicture withcolor .5white ;
+ setbounds currentpicture to boundingbox currentpicture enlarged 10pt ;
+\stopMPpage
+
+\startMPpage
+ picture p ;
+ p := \sometxt{\framed[width=fit,align=middle]{\input tufte\relax}} ;
+ draw p rotatedaround(center p, 30) ;
+\stopMPpage
+
+\startMPpage
+ picture p ;
+ p := \sometxt{\framed[width=fit,align=middle]{\input tufte\relax}} ;
+ draw p slanted .5 ;
+\stopMPpage
+
+\dorecurse{10} {
+ \startTeXtexts
+ \TeXtext{\recurselevel}{\ruledhbox{I must be {\green crazy} to implement this}}
+ \stopTeXtexts
+ \startMPpage
+ picture p ; pickup pencircle scaled .1pt ;
+ numeric i ; i := \recurselevel ;
+ p := sometxt(i) ;
+ p := p rotatedaround(center p, 360*(i*5/100)) ;
+ draw p ; draw boundingbox p withcolor blue ;
+ currentpicture := currentpicture scaled 20 ;
+ draw boundingbox currentpicture withcolor .5white ;
+ \stopMPpage
+}
+
+\startTeXtexts
+ \dorecurse{100}{\TeXtext{\recurselevel}{\ruledhbox{\strut interesting \recurselevel}}}
+\stopTeXtexts
+
+\startMPpage
+ picture p ; pickup pencircle scaled .1pt ;
+ for i = 1 upto 100:
+ p := sometxt(i) ;
+ p := p rotatedaround(center p, 360*(i*5/100)) ;
+ draw p ; draw boundingbox p withcolor blue ;
+ endfor ;
+ currentpicture := currentpicture scaled 20 ;
+ draw boundingbox currentpicture withcolor .5white ;
+\stopMPpage
+
+\startTeXtexts
+ \dorecurse{100}{\TeXtext{\recurselevel}{\ruledhbox{\strut interesting \recurselevel}}}
+\stopTeXtexts
+
+\startMPpage
+ picture p ; pickup pencircle scaled .1pt ;
+ for i = 1 step 5 until 100 :
+ p := sometxt(i) ;
+ p := p rotatedaround(center p, 360*(i/100)) ;
+ draw p ; draw boundingbox p withcolor blue ;
+ endfor ;
+ currentpicture := currentpicture scaled 20 ;
+ draw boundingbox currentpicture withcolor .5white ;
+\stopMPpage
+
+\startTeXtexts
+ \dorecurse{20}{\TeXtext{\recurselevel}{\externalfigure[t:/sources/cow.pdf][width=1cm]}}
+\stopTeXtexts
+
+\startMPpage
+ picture p ; pickup pencircle scaled .1pt ;
+ for i = 1 upto 20 :
+ p := sometxt(i) ;
+ p := p shifted (2.5cm,0) rotated (360*(i/20)) ;
+ draw p ; draw boundingbox p withcolor blue ;
+ endfor ;
+ currentpicture := currentpicture scaled 10 ;
+ draw boundingbox currentpicture withcolor .5white ;
+\stopMPpage
+
+\startTeXtexts
+ \dorecurse{200}{\TeXtext{\recurselevel}{\ruledhbox{\strut I must be {\green crazy} \recurselevel}}}
+\stopTeXtexts
+
+\startMPpage
+ picture p ; pickup pencircle scaled .1pt ;
+ numeric i ; i := 100 ;
+ p := sometxt(i) ;
+ p := p rotatedaround(center p, 360*(i*36/100)) ;
+ draw p ; draw boundingbox p withcolor blue ;
+ currentpicture := currentpicture scaled 20 ;
+ draw boundingbox currentpicture withcolor .5white ;
+\stopMPpage
+
+\dorecurse{10}{
+ \startTeXtexts
+ \dorecurse{200}{\TeXtext{\recurselevel}{\ruledhbox{\strut I must be {\green crazy} \recurselevel}}}
+ \stopTeXtexts
+ \startMPpage
+ picture p ; pickup pencircle scaled .1pt ;
+ j := 10*\recurselevel-9;
+ k := 10*\recurselevel;
+ for i = j upto k:
+ p := sometxt(i) ;
+ p := p rotatedaround(center p, 360*(i/100)) ;
+ draw p ; draw boundingbox p withcolor blue ;
+ endfor ;
+ currentpicture := currentpicture scaled 20 ;
+ draw boundingbox currentpicture withcolor red ;
+ \stopMPpage
+}
diff --git a/tex/context/base/meta-tex.mkiv b/tex/context/base/meta-tex.mkiv
new file mode 100644
index 000000000..e35f95385
--- /dev/null
+++ b/tex/context/base/meta-tex.mkiv
@@ -0,0 +1,72 @@
+%D \module
+%D [ file=meta-tex,
+%D version=2006.06.07,
+%D title=\CONTEXT\ Support Macros,
+%D subtitle=\METAPOST\ fast text insertion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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
+
+% Ok, we support this in MkIV because Mojca kept the pressure on. It
+% looks a bit like a hack.
+
+\long\def\startTeXtexts#1\stopTeXtexts
+ {#1}
+
+\long\def\TeXtext
+ {\dosingleempty\doTeXtext}
+
+\long\def\doTeXtext[#1]#2#3% contrary to mkii we don't process yet but we do expand
+ {\long\setxvalue{@@st@@::#2}{\noexpand\dodoTeXtext{#1}{#3}}}
+
+\long\def\dodoTeXtext#1#2%
+ {\begingroup
+ \setbox\nextbox\hbox{\executeifdefined{textext@@#1}\firstofoneargument{#2}}%
+ \executeifdefined{textext::#1}{\getvalue{textext::depth}}%
+ \box\nextbox
+ \endgroup}
+
+\def\getTeXtext#1%
+ {\getvalue{@@st@@::#1}}
+
+\setvalue{textext::d}{\setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}} % unchecked
+\setvalue{textext::n}{} % unchecked
+
+\setvalue {textext::depth}{\getvalue{textext::d}}
+\setvalue{textext::nodepth}{\getvalue{textext::n}}
+
+% \definetextext[framed]{\framed}
+%
+% \startMPcode
+% draw \sometxt[framed]{black} rotated 45 ;
+% \stopMPcode
+
+\unexpanded\def\definetextext[#1]#2{\setvalue{@@st@@[#1]}{#2}\setvalue{@@st@@[#1] }{#2}} % we don't grab spaces after [#1]
+
+\long\def\sometxt#1#{\dosometxt{#1}} % grab optional [args]
+
+\long\def\dosometxt#1#2%
+ {textext.drt("\ifcsname @@st@@#1\endcsname\csname @@st@@#1\endcsname{#2}\else#2\fi")}
+
+% Best use the mp macro instead since it provides positioning.
+%
+% \startuseMPgraphic{testgraphic}
+% draw \sometxt{\ruledhbox{\strut hans hagen}} scaled 3;
+% % draw textext.drt("\ruledhbox{\strut hans hagen}") scaled 3;
+% % draw textext.dlft("\ruledhbox{\strut hans hagen}") scaled 3;
+% % draw textext.lft("\ruledhbox{\strut hans hagen}") scaled 3;
+% draw llcorner currentpicture -- urcorner currentpicture withcolor yellow;
+% draw lrcorner currentpicture -- ulcorner currentpicture withcolor yellow;
+% draw boundingbox currentpicture withcolor blue ;
+% draw origin withcolor red withpen pencircle scaled 1pt;
+% \stopuseMPgraphic
+%
+% {\showstruts\useMPgraphic{testgraphic}}
+
+\protect \endinput
diff --git a/tex/context/base/meta-txt.tex b/tex/context/base/meta-txt.tex
new file mode 100644
index 000000000..474253a40
--- /dev/null
+++ b/tex/context/base/meta-txt.tex
@@ -0,0 +1,304 @@
+%D \module
+%D [ file=meta-txt,
+%D version=2000.07.06,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Text Tricks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 In this library some handy text manipulations are
+%D defined. Some can and will be improved as soon as the
+%D \TEX||\METAPOST\ interface is stable. Some of the
+%D solutions may look weird, which is entirely my fault,
+%D since I implemented them in the process of getting grip
+%D on this kind of manipulations. Undoubtly better
+%D \METAPOST\ code is possible, but my way of learning
+%D this kind of trickery happens to be by \quote {trial
+%D and error} and \quote {look and feel} (as well as
+%D identifying tricks in Hobby's code).
+
+% textext ipv btex ... etex
+
+% we need a proper prefix here
+
+\unprotect
+
+\startMPextensions
+ if unknown context_text: input mp-text; fi;
+\stopMPextensions
+
+%%%%%%%
+
+% \def\newchar#1{\chardef#1=0 }
+
+\ifdefined\MPtoks \else \newtoks\MPtoks \fi
+\ifdefined\MPbox \else \newbox \MPbox \fi
+
+\ifdefined\parwidth \else \newdimen\parwidth \fi
+\ifdefined\parheight \else \newdimen\parheight \fi
+\ifdefined\parvoffset \else \newdimen\parvoffset \fi
+\ifdefined\parhoffset \else \newdimen\parhoffset \fi
+\ifdefined\parlines \else \newcount\parlines \fi
+\ifdefined\partoks \else \newtoks \partoks \fi
+\ifdefined\shapetextbox \else \newbox \shapetextbox \fi
+ \newif \ifparseries
+\ifdefined\parfirst \else \chardef \parfirst=0 \fi
+
+\def\startshapetext[#1]%
+ {\global\newcounter\currentshapetext
+ \global\setbox\shapetextbox\vbox\bgroup
+ \expanded{\switchtobodyfont[\@@shbodyfont]}%
+ \dontcomplain
+ \hsize\parwidth
+ \setuptolerance[\v!verytolerant,\v!stretch]%
+ \!!counta\zerocount
+ \!!toksa\emptytoks
+ \def\docommand##1%
+ {\setbox\scratchbox\hbox{\useMPgraphic{##1}}%
+ \global\chardef\parfirst\zerocount
+ \getMPdata % \readlocfile{\MPdatafile}{}{}%
+ \setshapecharacteristics
+ \advance\!!counta by \parlines
+ \expandafter\appendtoks\the\partoks\to\!!toksa}%
+ \processcommalist[#1]\docommand
+ \global\parseriestrue
+ \xdef\totalparlines{\the\!!counta}%
+ \global\partoks\!!toksa
+ %\ifx\partoks\emptytoks\else % safeguard
+ \expanded{\parshape \the\!!counta \the\!!toksa}%
+ %\fi
+ \setshapecharacteristics % extra dummy
+ \ifparseries\def\par{\endgraf\adaptparshape}\fi
+ \EveryPar{\begstrut}}
+
+\def\stopshapetext
+ {\endstrut
+ %\removebottomthings
+ \egroup
+ \global\newcounter\currentshapetext
+ \getshapecharacteristics}
+
+\def\adaptparshape%
+ {\def\docommand##1%
+ {\ifcase\!!counta
+ \expandafter\appendtoks\space##1 \to\!!toksa
+ \else
+ \advance\!!counta \minusone
+ \fi}%
+ \!!counta\prevgraf
+ \doglobal\decrement(\totalparlines,\!!counta)%
+ \multiply\!!counta \plustwo
+ \!!toksa\emptytoks
+ \expanded{\processseparatedlist[\the\partoks][\space]}\docommand
+ \global\partoks\!!toksa
+ %\ifx\partoks\emptytoks\else % safeguard
+ \expanded{\parshape\totalparlines\the\partoks}%
+ }%\fi}
+
+\def\getshapecharacteristics%
+ {\doglobal\increment\currentshapetext
+ \doifdefinedelse{parlines:\currentshapetext}
+ {\global\parlines \getvalue{parlines:\currentshapetext}%
+ \global\chardef\parfirst \getvalue{parfirst:\currentshapetext}%
+ \global\parvoffset \getvalue{parvoffset:\currentshapetext}%
+ \global\parhoffset \getvalue{parhoffset:\currentshapetext}%
+ \global\parwidth \getvalue{parwidth:\currentshapetext}%
+ \global\parheight \getvalue{parheight:\currentshapetext}}
+ {\global\parlines \plusone
+ \global\chardef\parfirst \zerocount
+ \global\parvoffset \zeropoint
+ \global\parhoffset \zeropoint
+ \global\parwidth \hsize
+ \global\parheight \vsize}}
+
+\def\setshapecharacteristics%
+ {\doglobal\increment\currentshapetext
+ \setxvalue{parlines:\currentshapetext }{\the\parlines}%
+ \setxvalue{parfirst:\currentshapetext }{\the\parfirst}%
+ \setxvalue{parvoffset:\currentshapetext}{\the\parvoffset}%
+ \setxvalue{parhoffset:\currentshapetext}{\the\parhoffset}%
+ \setxvalue{parwidth:\currentshapetext }{\the\parwidth}%
+ \setxvalue{parheight:\currentshapetext }{\the\parheight}}
+
+\def\getshapetext% option: unvbox
+ {\vbox\bgroup
+ \forgetall
+ \setbox\scratchbox\vbox to \parheight
+ {\expanded{\switchtobodyfont[\@@shbodyfont]}% evt strutheight en
+ \splittopskip\strutheight % lineheight opslaan
+ \vskip\parvoffset % scheelt switch en
+ \ifcase\parfirst\or\vskip\lineheight\fi % is ook veiliger
+ \hskip\parhoffset
+ \hbox{\vsplit\shapetextbox to \parlines\lineheight}}%
+ \wd\scratchbox\parwidth
+ \ht\scratchbox\parheight
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \getshapecharacteristics
+ \egroup}
+
+\def\setupshapetexts%
+ {\dodoubleempty\getparameters[\??sh]}
+
+\setupshapetexts%
+ [\c!bodyfont=]
+
+%%%%%%% rotfont nog definieren
+
+\doifundefined{RotFont}{\definefont[RotFont][RegularBold]}
+
+\def\processfollowingtoken#1% strut toegevoegd
+ {\appendtoks#1\to\MPtoks
+ \setbox\MPbox=\hbox{\RotFont\setstrut\strut\the\MPtoks}%
+ \startMPdrawing
+ n := n + 1 ; len[n] := \the\wd\MPbox ;
+ \stopMPdrawing
+ \startMPdrawing[-]
+ % pic[n] := textext{\RotFont\setstrut\strut#1} ; % btex \RotFont\setstrut\strut#1 etex ;
+ pic[n] := btex \RotFont\setstrut\strut#1 etex ;
+ pic[n] := pic[n] shifted - llcorner pic[n] ;
+ \stopMPdrawing}
+
+\startuseMPgraphic{followtokens}
+ % we default to nothing
+\stopuseMPgraphic
+
+\def\followtokens#1%
+ {\vbox\bgroup
+ \forgetall
+ \dontcomplain
+ \startMPenvironment
+ \doifundefined{RotFont}{\definefont[RotFont][RegularBold]}
+ \stopMPenvironment
+ \MPtoks\emptytoks
+ \resetMPdrawing
+ \startMPdrawing
+ \includeMPgraphic{followtokens} ;
+ picture pic[] ; numeric len[], n ; n := 0 ;
+ \stopMPdrawing
+ \handletokens#1\with\processfollowingtoken
+ \startMPdrawing
+ if unknown RotPath : path RotPath ; RotPath := origin ; fi ;
+ if unknown RotColor : color RotColor ; RotColor := black ; fi ;
+ if unknown TraceRot : boolean TraceRot ; TraceRot := false ; fi ;
+ if unknown ExtraRot : numeric ExtraRot ; ExtraRot := 0 ; fi ;
+ numeric al, at, pl, wid, pos ; pair ap, ad ;
+ al := arclength RotPath ;
+ if al=0 :
+ al := len[n] + ExtraRot ;
+ RotPath := origin -- (al,0) ;
+ fi ;
+ if al1 : (n-1) else : 1 fi) ;
+ if TraceRot :
+ draw RotPath withpen pencircle scaled 1pt withcolor blue ;
+ fi ;
+ for i=1 upto n :
+ wid := abs(xpart urcorner pic[i] - xpart llcorner pic[i]) ;
+ pos := len[i]-wid/2 + (i-1)*pl ;
+ at := arctime pos of RotPath ;
+ ap := point at of RotPath ;
+ ad := direction at of RotPath ;
+ draw pic[i] shifted (-wid/2,0) rotated(angle(ad)) shifted ap
+ withcolor RotColor ;
+ if TraceRot :
+ draw boundingbox
+ pic[i] shifted (-wid/2,0) rotated(angle(ad)) shifted ap
+ withpen pencircle scaled .25pt withcolor red ;
+ draw ap
+ withpen pencircle scaled .50pt withcolor green ;
+ fi ;
+ endfor ;
+ \stopMPdrawing
+ \MPdrawingdonetrue
+ \getMPdrawing
+ \resetMPdrawing
+ \egroup}
+
+% \followtokens
+% {This is just a dummy text, kerned by T{\kern
+% -.1667em\lower .5ex\hbox {E}}{\kern -.125emX} and typeset
+% in a circle using {\setMFPfont M}{\setMFPfont
+% E}{\setMFPfont T}{\setMFPfont A}{\setMFPfont
+% P}{\setMFPfont O}{\setMFPfont S}{\setMFPfont T}.\quad}
+
+\startuseMPgraphic{fuzzycount}
+ begingroup
+ save height, span, drift, d, cp ;
+ height := 3/ 5 * \baselinedistance ;
+ span := 1/ 3 * height ;
+ drift := 1/10 * height ;
+ pickup pencircle scaled (1/12 * height) ;
+ def d = (uniformdeviate drift) enddef ;
+ for i := 1 upto \MPvar{n} :
+ draw
+ if (i mod 5)=0 : ((-d-4.5span,d)--(+d-0.5span,height-d))
+ else : ((-d,+d)--(+d,height-d)) fi
+ shifted (span*i,d-drift) ;
+ endfor;
+ picture cp ; cp := currentpicture ; % for readability
+ setbounds currentpicture to
+ (llcorner cp shifted (0,-ypart llcorner cp) --
+ lrcorner cp shifted (0,-ypart lrcorner cp) --
+ urcorner cp -- ulcorner cp -- cycle) ;
+ endgroup ;
+\stopuseMPgraphic
+
+\setupMPvariables
+ [fuzzycount]
+ [n=10]
+
+\def\fuzzycount#1%
+ {{\tx\useMPgraphic{fuzzycount}{n=#1}}}
+
+\defineconversion[fuzzy][\fuzzycount]
+
+%%%%%%%
+
+\setupMPvariables
+ [EnglishRule]
+ [height=1ex,
+ width=\the\localhsize, % without \the, problems in non e-tex
+ color=darkgray]
+
+\defineblank
+ [EnglishRule]
+ [medium]
+
+\startuniqueMPgraphic{EnglishRule}{height,width,color}
+ height = \MPvar{height} ;
+ x1 = 0 ; x3 = \MPvar{width} ; x2 = x4 = .5x3 ;
+ y1 = y3 = 0 ; y2 = -y4 = height/2 ;
+ fill z1..z2..z3 & z3..z4..z1 & cycle withcolor \MPvar{color} ;
+\stopuniqueMPgraphic
+
+\def\EnglishRule%
+ {\startlinecorrection[EnglishRule]
+ \setlocalhsize \noindent \reuseMPgraphic{EnglishRule}
+ \stoplinecorrection}
+
+%D The following macro returns a tight bound character
+%D sequence.
+%D
+%D \useMPlibrary[txt]
+%D
+%D \startlinecorrection
+%D \TightText{\ss\bf 123}{0cm}{3cm}{red}
+%D \stoplinecorrection
+
+\def\TightText#1#2#3#4%
+ {\hbox % \ruledhbox
+ {\startMPcode
+ picture p ; p := image (graphictext "#1" withfillcolor red) ;
+ draw p xsized #2 ysized #3 withcolor \MPcolor{#4} ;
+ \stopMPcode}}
+
+\protect \endinput
diff --git a/tex/context/base/meta-xml.tex b/tex/context/base/meta-xml.tex
new file mode 100644
index 000000000..f6f81f767
--- /dev/null
+++ b/tex/context/base/meta-xml.tex
@@ -0,0 +1,29 @@
+%D \module
+%D [ file=meta-xml,
+%D version=2002.11.27,
+%D title=\METAPOST\ Graphics,
+%D subtitle=XML Hacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphics / XML Hacks}
+
+%D When we are dealing with XML, we need to make sure that
+%D \METAPOST\ knows about it. The next macro expands its
+%D argument (think of widget XFDF) into \type {\getXMLentity}
+%D calls.
+
+\unprotect
+
+\def\setMPtextXML#1#2%
+ {\bgroup
+ \enableXML
+ \expanded{\defconvertedcommand\noexpand\ascii{#2}}%
+ \expanded{\egroup\noexpand\dodoglobal\noexpand\setvalue{\@@MPT#1}{\ascii}}}
+
+\protect \endinput
diff --git a/tex/context/base/metatex.tex b/tex/context/base/metatex.tex
new file mode 100644
index 000000000..e90af709c
--- /dev/null
+++ b/tex/context/base/metatex.tex
@@ -0,0 +1,154 @@
+%D \module
+%D [ file=metatex,
+%D version=2008.10.10,
+%D title=\METATEX,
+%D subtitle=\METATEX\ Format Generation,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=Hans Hagen / \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 can experiment here with runtime loading, id est no longer
+%D use a format. However, we still need a stub then but it could
+%D as well be luatools (mtxrun) itself then.
+
+%D This format is just a minimal layer on top of the \LUATEX\
+%D engine and will not provide high level functionality. It can
+%D be used as basis for dedicated (specialized) macro packages.
+%D
+%D A format is generated with the command;
+%D
+%D \starttyping
+%D luatools --make --compile metatex
+%D \stoptyping
+%D
+%D Remark: this is far from complete. We will gradually add
+%D more. Also, it's not yet clean what exactly will be part
+%D of it. This is a prelude to a configureable macro package.
+
+\catcode`\{=1 \catcode`\}=2 \catcode`\#=6
+
+\edef\metatexformat {\jobname}
+\edef\metatexversion{2007.04.03 13:01}
+
+\let\fmtname \metatexformat
+\let\fmtversion\metatexversion
+
+\ifx\normalinput\undefined \let\normalinput\input \fi
+
+\def\loadcorefile#1{\normalinput#1.tex \relax}
+\def\loadmarkfile#1{\normalinput#1.mkiv\relax}
+
+\loadcorefile{syst-ini}
+
+\ifnum\luatexversion<60 % also change message
+ \writestatus{!!!!}{Your luatex binary is too old, you need at least version 0.60!}
+ \expandafter\end
+\fi
+
+\newtoks\metatexversiontoks \metatexversiontoks\expandafter{\metatexversion} % at the lua end
+
+\loadcorefile{syst-pln} % plain tex initializations of internal registers (no further code)
+
+\loadmarkfile{luat-cod} %
+\loadmarkfile{luat-bas} %
+\loadmarkfile{luat-lib} %
+
+% needs stripping:
+
+\loadmarkfile{catc-ini} % catcode table management
+\loadcorefile{catc-act} % active character definition mechanisms
+\loadcorefile{catc-def} % some generic catcode tables
+\loadcorefile{catc-ctx} % a couple of context specific tables but expected by later modules
+\loadcorefile{catc-sym} % some definitions related to \letter
+
+% helpers, maybe less
+
+\loadmarkfile{syst-aux} % a whole lot of auxiliary macros
+%loadmarkfile{syst-lua} % some helpers using lua instead
+%loadmarkfile{syst-con} % some rather basic conversions
+%loadmarkfile{syst-fnt}
+%loadmarkfile{syst-str}
+%loadmarkfile{syst-rtp}
+
+% not needed
+
+% \loadmarkfile{supp-fil}
+% \loadmarkfile{supp-dir}
+
+% characters
+
+\loadmarkfile{char-utf}
+\loadmarkfile{char-ini}
+\loadmarkfile{char-enc} % \registerctxluafile{char-enc}{1.001}
+
+% nodes
+
+\loadmarkfile{node-ini}
+%loadmarkfile{node-fin}
+%loadmarkfile{node-par}
+
+% attributes, not needed:
+
+%loadmarkfile{attr-ini}
+
+% regimes
+
+% \loadmarkfile{regi-ini}
+% \loadcorefile{regi-syn}
+
+% languages
+
+% fonts
+
+% \loadcorefile{enco-ini.mkiv}
+% \loadcorefile{hand-ini.mkiv}
+
+\registerctxluafile{font-ini}{1.001}
+
+\registerctxluafile{node-fnt}{1.001}
+
+\registerctxluafile{font-enc}{1.001}
+\registerctxluafile{font-map}{1.001}
+\registerctxluafile{font-syn}{1.001}
+\registerctxluafile{font-tfm}{1.001}
+\registerctxluafile{font-afm}{1.001}
+\registerctxluafile{font-cid}{1.001}
+\registerctxluafile{font-ott}{1.001}
+\registerctxluafile{font-otf}{1.001}
+\registerctxluafile{font-otb}{1.001}
+\registerctxluafile{font-otn}{1.001}
+\registerctxluafile{font-ota}{1.001}
+\registerctxluafile{font-otp}{1.001}
+\registerctxluafile{font-otc}{1.001}
+%registerctxluafile{font-vf} {1.001}
+\registerctxluafile{font-def}{1.001}
+%registerctxluafile{font-ctx}{1.001}
+\registerctxluafile{font-xtx}{1.001}
+%registerctxluafile{font-fbk}{1.001}
+%registerctxluafile{font-ext}{1.001}
+\registerctxluafile{font-pat}{1.001}
+%registerctxluafile{font-chk}{1.001}
+
+%registerctxluafile{math-ini}{1.001}
+%registerctxluafile{math-dim}{1.001}
+%registerctxluafile{math-ent}{1.001}
+%registerctxluafile{math-ext}{1.001}
+%registerctxluafile{math-vfu}{1.001}
+%registerctxluafile{math-map}{1.001}
+%registerctxluafile{math-noa}{1.001}
+
+\registerctxluafile{task-ini}{1.001}
+
+%registerctxluafile{l-xml}{1.001} % needed for font database
+
+% why not ...
+
+\pdfoutput\plusone
+
+% done
+
+\errorstopmode \dump \endinput
diff --git a/tex/context/base/mlib-ctx.lua b/tex/context/base/mlib-ctx.lua
new file mode 100644
index 000000000..cc5682e6f
--- /dev/null
+++ b/tex/context/base/mlib-ctx.lua
@@ -0,0 +1,84 @@
+if not modules then modules = { } end modules ['mlib-ctx'] = {
+ 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",
+}
+
+-- todo
+
+local format, join = string.format, table.concat
+local sprint = tex.sprint
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+metapost = metapost or {}
+metapost.defaultformat = "metafun"
+
+function metapost.graphic(instance,mpsformat,str,initializations,preamble,askedfig)
+ local mpx = metapost.format(instance,mpsformat or metapost.defaultformat)
+ metapost.graphic_base_pass(mpx,str,initializations,preamble,askedfig)
+end
+
+function metapost.getclippath(instance,mpsformat,data,initializations,preamble)
+ local mpx = metapost.format(instance,mpsformat or metapost.defaultformat)
+ if mpx and data then
+ starttiming(metapost)
+ starttiming(metapost.exectime)
+ local result = mpx:execute(format("%s;beginfig(1);%s;%s;endfig;",preamble or "",initializations or "",data))
+ stoptiming(metapost.exectime)
+ if result.status > 0 then
+ logs.report("metafun", "%s: %s", result.status, result.error or result.term or result.log)
+ result = nil
+ else
+ result = metapost.filterclippath(result)
+ end
+ stoptiming(metapost)
+ return result
+ end
+end
+
+function metapost.filterclippath(result)
+ if result then
+ local figures = result.fig
+ if figures and #figures > 0 then
+ local figure = figures[1]
+ local objects = figure:objects()
+ if objects then
+ local lastclippath
+ for o=1,#objects do
+ local object = objects[o]
+ if object.type == "start_clip" then
+ lastclippath = object.path
+ end
+ end
+ return lastclippath
+ end
+ end
+ end
+end
+
+function metapost.theclippath(...)
+ local result = metapost.getclippath(...)
+ if result then -- we could just print the table
+ result = join(metapost.flushnormalpath(result),"\n")
+ sprint(result)
+ end
+end
+
+statistics.register("metapost processing time", function()
+ local n = metapost.n
+ if n > 0 then
+ local e, t = metapost.externals.n, statistics.elapsedtime
+ local str = format("%s seconds, loading: %s seconds, execution: %s seconds, n: %s",
+ t(metapost), t(mplib), t(metapost.exectime), n)
+ if e > 0 then
+ return format("%s, external: %s seconds (%s calls)", str, t(metapost.externals), e)
+ else
+ return str
+ end
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/mlib-ctx.mkiv b/tex/context/base/mlib-ctx.mkiv
new file mode 100644
index 000000000..6f56b7e68
--- /dev/null
+++ b/tex/context/base/mlib-ctx.mkiv
@@ -0,0 +1,81 @@
+%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]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This file contains the \MPLIB\ variants of the by now ancient
+%D \MPTOPDF\ code.
+
+\writestatus{loading}{MetaPost Library Graphics / Initializations}
+
+\registerctxluafile{mlib-run}{1.001}
+\registerctxluafile{mlib-ctx}{1.001}
+
+\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/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua
new file mode 100644
index 000000000..352070408
--- /dev/null
+++ b/tex/context/base/mlib-pdf.lua
@@ -0,0 +1,530 @@
+if not modules then modules = { } end modules ['mlib-pdf'] = {
+ 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 format, concat, gsub = string.format, table.concat, string.gsub
+local texsprint = tex.sprint
+local abs, sqrt, round = math.abs, math.sqrt, math.round
+
+local copy_node, write_node = node.copy, node.write
+
+local ctxcatcodes = tex.ctxcatcodes
+
+metapost = metapost or { }
+metapost.multipass = false
+metapost.n = 0
+metapost.optimize = true -- false
+
+--~ Because in MKiV we always have two passes, we save the objects. When an extra
+--~ mp run is done (due to for instance texts identifier in the parse pass), we
+--~ get a new result table and the stored objects are forgotten. Otherwise they
+--~ are reused.
+
+local function getobjects(result,figure,f)
+ if metapost.optimize then
+ local objects = result.objects
+ if not objects then
+ result.objects = { }
+ end
+ objects = result.objects[f]
+ if not objects then
+ objects = figure:objects()
+ result.objects[f] = objects
+ end
+ return objects
+ else
+ return figure:objects()
+ end
+end
+
+function metapost.convert(result, trialrun, flusher, multipass, askedfig)
+ if trialrun then
+ metapost.multipass = false
+ metapost.parse(result, askedfig)
+ if multipass and not metapost.multipass and metapost.optimize then
+ metapost.flush(result, flusher, askedfig) -- saves a run
+ else
+ return false
+ end
+ else
+ metapost.flush(result, flusher, askedfig)
+ end
+ return true -- done
+end
+
+metapost.flushers = { }
+metapost.flushers.pdf = { }
+
+local savedliterals = nil
+
+local mpsliteral = nodes.register(node.new("whatsit",8))
+
+function metapost.flush_literal(d) -- \def\MPLIBtoPDF#1{\ctxlua{metapost.flush_literal(#1)}}
+ if savedliterals then
+ local literal = copy_node(mpsliteral)
+ literal.data = savedliterals[d]
+ write_node(literal)
+ else
+ logs.report("metapost","problem flushing literal %s",d)
+ end
+end
+
+function metapost.flush_reset()
+ savedliterals = nil
+end
+
+function metapost.flushers.pdf.comment(message)
+ if message then
+ message = format("%% mps graphic %s: %s", metapost.n, message)
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = message
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{",last,"}")
+ else
+ savedliterals = { message }
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{1}")
+ end
+ end
+end
+
+function metapost.flushers.pdf.startfigure(n,llx,lly,urx,ury,message)
+ savedliterals = nil
+ metapost.n = metapost.n + 1
+ texsprint(ctxcatcodes,format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
+ if message then metapost.flushers.pdf.comment(message) end
+end
+
+function metapost.flushers.pdf.stopfigure(message)
+ if message then metapost.flushers.pdf.comment(message) end
+ texsprint(ctxcatcodes,"\\stopMPLIBtoPDF")
+ texsprint(ctxcatcodes,"\\ctxlua{metapost.flush_reset()}") -- maybe just at the beginning
+end
+
+function metapost.flushers.pdf.flushfigure(pdfliterals) -- table
+ if #pdfliterals > 0 then
+ pdfliterals = concat(pdfliterals,"\n")
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = pdfliterals
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{",last,"}")
+ else
+ savedliterals = { pdfliterals }
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{1}")
+ end
+ end
+end
+
+function metapost.flushers.pdf.textfigure(font,size,text,width,height,depth) -- we could save the factor
+ text = gsub(text,".","\\hbox{%1}") -- kerning happens in metapost (i have to check if this is true for mplib)
+ texsprint(ctxcatcodes,format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-number.dimenfactors.bp*depth))
+end
+
+local bend_tolerance = 131/65536
+
+local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+
+local function pen_characteristics(object)
+ if mplib.pen_info then
+ local t = mplib.pen_info(object)
+ rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
+ divider = sx*sy - rx*ry
+ return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
+ else
+ rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+ return false, 1
+ end
+end
+
+local function mpconcat(px, py) -- no tx, ty here / we can move this one inline if needed
+ return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
+end
+
+local function curved(ith,pth)
+ local d = pth.left_x - ith.right_x
+ if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then
+ d = pth.left_y - ith.right_y
+ if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then
+ return false
+ end
+ end
+ return true
+end
+
+local function flushnormalpath(path, t, open)
+ t = t or { }
+ local pth, ith
+ for i=1,#path do
+ pth = path[i]
+ if not ith then
+ t[#t+1] = format("%f %f m",pth.x_coord,pth.y_coord)
+ elseif curved(ith,pth) then
+ t[#t+1] = format("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
+ else
+ t[#t+1] = format("%f %f l",pth.x_coord,pth.y_coord)
+ end
+ ith = pth
+ end
+ if not open then
+ local one = path[1]
+ if curved(pth,one) then
+ t[#t+1] = format("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
+ else
+ t[#t+1] = format("%f %f l",one.x_coord,one.y_coord)
+ end
+ elseif #path == 1 then
+ -- special case .. draw point
+ local one = path[1]
+ t[#t+1] = format("%f %f l",one.x_coord,one.y_coord)
+ end
+ return t
+end
+
+local function flushconcatpath(path, t, open)
+ t = t or { }
+ t[#t+1] = format("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
+ local pth, ith
+ for i=1,#path do
+ pth = path[i]
+ if not ith then
+ t[#t+1] = format("%f %f m",mpconcat(pth.x_coord,pth.y_coord))
+ elseif curved(ith,pth) then
+ local a, b = mpconcat(ith.right_x,ith.right_y)
+ local c, d = mpconcat(pth.left_x,pth.left_y)
+ t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(pth.x_coord,pth.y_coord))
+ else
+ t[#t+1] = format("%f %f l",mpconcat(pth.x_coord, pth.y_coord))
+ end
+ ith = pth
+ end
+ if not open then
+ local one = path[1]
+ if curved(pth,one) then
+ local a, b = mpconcat(pth.right_x,pth.right_y)
+ local c, d = mpconcat(one.left_x,one.left_y)
+ t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(one.x_coord, one.y_coord))
+ else
+ t[#t+1] = format("%f %f l",mpconcat(one.x_coord,one.y_coord))
+ end
+ elseif #path == 1 then
+ -- special case .. draw point
+ local one = path[1]
+ t[#t+1] = format("%f %f l",mpconcat(one.x_coord,one.y_coord))
+ end
+ return t
+end
+
+metapost.flushnormalpath = flushnormalpath
+
+metapost.specials = metapost.specials or { }
+
+-- we have two extension handlers, one for pre and postscripts, and one for colors
+
+-- the flusher is pdf based, if another backend is used, we need to overload the
+-- flusher; this is beta code, the organization will change
+
+function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan concat is sneller, 1 literal
+ if result then
+ local figures = result.fig
+ if figures then
+ flusher = flusher or metapost.flushers.pdf
+ local colorconverter = metapost.colorconverter() -- function !
+ local colorhandler = metapost.colorhandler
+ for f=1, #figures do
+ local figure = figures[f]
+ local objects = getobjects(result,figure,f)
+ local fignum = figure:charcode() or 0
+ if not askedfig or (askedfig == fignum) then
+ local t = { }
+ local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
+ local bbox = figure:boundingbox()
+ local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
+ metapost.llx = llx
+ metapost.lly = lly
+ metapost.urx = urx
+ metapost.ury = ury
+ if urx < llx then
+ -- invalid
+ flusher.startfigure(fignum,0,0,0,0,"invalid",figure)
+ flusher.stopfigure()
+ else
+ flusher.startfigure(fignum,llx,lly,urx,ury,"begin",figure)
+ t[#t+1] = "q"
+ if objects then
+ t[#t+1] = metapost.colorinitializer()
+ -- once we have multiple prescripts we can do more tricky things like
+ -- text and special colors at the same time
+ for o=1,#objects do
+ local object = objects[o]
+ local objecttype = object.type
+ if objecttype == "start_bounds" or objecttype == "stop_bounds" then
+ -- skip
+ elseif objecttype == "start_clip" then
+ t[#t+1] = "q"
+ flushnormalpath(object.path,t,false)
+ t[#t+1] = "W n"
+ elseif objecttype == "stop_clip" then
+ t[#t+1] = "Q"
+ miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
+ elseif objecttype == "special" then
+ metapost.specials.register(object.prescript)
+ elseif objecttype == "text" then
+ t[#t+1] = "q"
+ local ot = object.transform -- 3,4,5,6,1,2
+ t[#t+1] = format("%f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: format("%f %f m %f %f %f %f 0 0 cm",unpack(ot))
+ flusher.flushfigure(t) -- flush accumulated literals
+ t = { }
+ flusher.textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
+ t[#t+1] = "Q"
+ else
+ -- alternatively we can pass on the stack, could be a helper
+ -- can be optimized with locals
+ local currentobject = { -- not needed when no extensions
+ type = object.type,
+ miterlimit = object.miterlimit,
+ linejoin = object.linejoin,
+ linecap = object.linecap,
+ color = object.color,
+ dash = object.dash,
+ path = object.path,
+ htap = object.htap,
+ pen = object.pen,
+ prescript = object.prescript,
+ postscript = object.postscript,
+ }
+ --
+ local before, inbetween, after = nil, nil, nil
+ --
+ local cs, cr = currentobject.color, nil
+ -- todo document why ...
+ if cs and colorhandler and #cs > 0 and round(cs[1]*10000) == 123 then -- test in function
+ currentobject, cr = colorhandler(cs,currentobject,t,colorconverter)
+ objecttype = currentobject.type
+ end
+ --
+ local prescript = currentobject.prescript
+ if prescript and prescript ~= "" then
+ -- move test to function
+ local special = metapost.specials[prescript]
+ if special then
+ currentobject, before, inbetween, after = special(currentobject.postscript,currentobject,t,flusher)
+ objecttype = currentobject.type
+ end
+ end
+ --
+ cs = currentobject.color
+ if cs and #cs > 0 then
+ t[#t+1], cr = colorconverter(cs)
+ end
+ --
+ if before then currentobject, t = before() end
+ local ml = currentobject.miterlimit
+ if ml and ml ~= miterlimit then
+ miterlimit = ml
+ t[#t+1] = format("%f M",ml)
+ end
+ local lj = currentobject.linejoin
+ if lj and lj ~= linejoin then
+ linejoin = lj
+ t[#t+1] = format("%i j",lj)
+ end
+ local lc = currentobject.linecap
+ if lc and lc ~= linecap then
+ linecap = lc
+ t[#t+1] = format("%i J",lc)
+ end
+ local dl = currentobject.dash
+ if dl then
+ local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset)
+ if d ~= dashed then
+ dashed = d
+ t[#t+1] = dashed
+ end
+ elseif dashed then
+ t[#t+1] = "[] 0 d"
+ dashed = false
+ end
+ if inbetween then currentobject, t = inbetween() end
+ local path = currentobject.path
+ local transformed, penwidth = false, 1
+ local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point"
+ local pen = currentobject.pen
+ if pen then
+ if pen.type == 'elliptical' then
+ transformed, penwidth = pen_characteristics(object) -- boolean, value
+ t[#t+1] = format("%f w",penwidth) -- todo: only if changed
+ if objecttype == 'fill' then
+ objecttype = 'both'
+ end
+ else -- calculated by mplib itself
+ objecttype = 'fill'
+ end
+ end
+ if transformed then
+ t[#t+1] = "q"
+ end
+ if path then
+ if transformed then
+ flushconcatpath(path,t,open)
+ else
+ flushnormalpath(path,t,open)
+ end
+ if objecttype == "fill" then
+ t[#t+1] = "h f"
+ elseif objecttype == "outline" then
+ t[#t+1] = (open and "S") or "h S"
+ elseif objecttype == "both" then
+ t[#t+1] = "h B"
+ end
+ end
+ if transformed then
+ t[#t+1] = "Q"
+ end
+ local path = currentobject.htap
+ if path then
+ if transformed then
+ t[#t+1] = "q"
+ end
+ if transformed then
+ flushconcatpath(path,t,open)
+ else
+ flushnormalpath(path,t,open)
+ end
+ if objecttype == "fill" then
+ t[#t+1] = "h f"
+ elseif objecttype == "outline" then
+ t[#t+1] = (open and "S") or "h S"
+ elseif objecttype == "both" then
+ t[#t+1] = "h B"
+ end
+ if transformed then
+ t[#t+1] = "Q"
+ end
+ end
+ if cr then
+ t[#t+1] = cr
+ end
+ if after then currentobject, t = after() end
+ end
+ end
+ end
+ t[#t+1] = "Q"
+ flusher.flushfigure(t)
+ flusher.stopfigure("end")
+ end
+ if askedfig then
+ break
+ end
+ end
+ end
+ end
+ end
+end
+
+function metapost.parse(result,askedfig)
+ if result then
+ local figures = result.fig
+ if figures then
+ for f=1, #figures do
+ local figure = figures[f]
+ local fignum = figure:charcode() or 0
+ if not askedfig or (askedfig == fignum) then
+ local bbox = figure:boundingbox()
+ local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
+ metapost.llx = llx
+ metapost.lly = lly
+ metapost.urx = urx
+ metapost.ury = ury
+ local objects = getobjects(result,figure,f)
+ if objects then
+ for o=1,#objects do
+ local object = objects[o]
+ if object.type == "outline" then
+ local prescript = object.prescript
+ if prescript then
+ local special = metapost.specials[prescript]
+ if special then
+ special(object.postscript,object)
+ end
+ end
+ end
+ end
+ end
+ break
+ end
+ end
+ end
+ end
+end
+
+-- tracing:
+
+local t = { }
+
+local flusher = {
+ startfigure = function()
+ t = { }
+ texsprint(ctxcatcodes,"\\startnointerference")
+ end,
+ flushfigure = function(literals)
+ for i=1, #literals do
+ t[#t+1] = literals[i]
+ end
+ end,
+ stopfigure = function()
+ texsprint(ctxcatcodes,"\\stopnointerference")
+ end
+}
+
+function metapost.pdfliterals(result)
+ metapost.flush(result,flusher)
+ return t
+end
+
+-- so far
+
+function metapost.totable(result)
+ local figure = result and result.fig and result.fig[1]
+ if figure then
+ local t = { }
+ local objects = figure:objects()
+ for o=1,#objects do
+ local object = objects[o]
+ local tt = { }
+ local fields = mplib.fields(object)
+ for f=1,#fields do
+ local field = fields[f]
+ tt[field] = object[field]
+ end
+ t[#t+1] = tt
+ end
+ local b = figure:boundingbox()
+ return {
+ boundingbox = { llx = b[1], lly = b[2], urx = b[3], ury = b[4] },
+ objects = t
+ }
+ else
+ return nil
+ end
+end
+
+-- will be overloaded later
+
+function metapost.colorconverter()
+ return function(cr)
+ local n = #cr
+ if n == 4 then
+ local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G"
+ elseif n == 3 then
+ local r, g, b = cr[1], cr[2], cr[3]
+ return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G"
+ else
+ local s = cr[1]
+ return format("%.3f g %.3f G",s,s), "0 g 0 G"
+ end
+ end
+end
diff --git a/tex/context/base/mlib-pdf.mkiv b/tex/context/base/mlib-pdf.mkiv
new file mode 100644
index 000000000..2681b0810
--- /dev/null
+++ b/tex/context/base/mlib-pdf.mkiv
@@ -0,0 +1,91 @@
+%D \module
+%D [ file=mlib-pdf,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Conversion to PDF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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
+
+\registerctxluafile{mlib-pdf}{1.001}
+
+\def\MPLIBtoPDF#1{\ctxlua{metapost.flush_literal(#1)}}
+
+\def\MPLIBboundingbox#1#2#3#4%
+ {\xdef\MPllx{#1}%
+ \xdef\MPlly{#2}%
+ \xdef\MPurx{#3}%
+ \xdef\MPury{#4}%
+ \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
+ \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}
+
+\def\startMPLIBtoPDF#1#2#3#4% watch the transparency reset
+ {\naturalhbox\bgroup
+ \doactivatecolor\s!black\forcecolorhack
+ \MPLIBboundingbox{#1}{#2}{#3}{#4}%
+ %\forgetall % done already elsewhere
+ \setbox\scratchbox\vbox\bgroup
+ \noindent % this is really needed in order to force tex into proper cm's
+ \startMPresources}
+
+\def\stopMPLIBtoPDF % watch the transparency reset
+ {%\dohandleMPresettransparency % not needed
+ \stopMPresources
+ \egroup
+ \setbox\scratchbox\hbox\bgroup
+ \hskip-\MPllx\onebasepoint
+ \raise-\MPlly\onebasepoint
+ \box\scratchbox
+ \egroup
+ \setbox\scratchbox\vbox to \MPheight\bgroup
+ \vfill
+ \hsize\MPwidth
+ \smashbox\scratchbox
+ \box\scratchbox
+ \egroup
+ \wd\scratchbox\MPwidth
+ \ht\scratchbox\MPheight
+ \dopackageMPgraphic\scratchbox
+ \egroup}
+
+% \def\MPLIBtextext#1#2#3#4#5%
+% {\begingroup
+% \def\MPtextdata{#3}% delegate the splitter to lua
+% \defconvertedcommand\MPtextdata\MPtextdata % no edef
+% \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
+% \executeifdefined{handleMPtext\MPtexttag}
+% {\setbox\scratchbox\hbox
+% {\font\temp=#1\space at #2\onebasepoint
+% \let\c\char
+% \temp
+% \MPfshowcommand{#3}}%
+% \setbox\scratchbox\hbox
+% {\hskip#4\onebasepoint
+% \raise#5\onebasepoint
+% \box\scratchbox}%
+% \smashbox\scratchbox
+% \box\scratchbox}%
+% \endgroup}
+
+\def\MPLIBtextext#1#2#3#4#5%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\font\temp=#1\space at #2\onebasepoint
+ \let\c\char
+ \temp
+ #3}%
+ \setbox\scratchbox\hbox
+ {\hskip#4\onebasepoint
+ \raise#5\onebasepoint
+ \box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+\protect \endinput
diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua
new file mode 100644
index 000000000..8b36660d3
--- /dev/null
+++ b/tex/context/base/mlib-pps.lua
@@ -0,0 +1,897 @@
+if not modules then modules = { } end modules ['mlib-pps'] = { -- prescript, postscripts and specials
+ 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",
+}
+
+-- current limitation: if we have textext as well as a special color then due to
+-- prescript/postscript overload we can have problems
+--
+-- todo: report max textexts
+
+local format, gmatch, concat, round, match = string.format, string.gmatch, table.concat, math.round, string.match
+local sprint = tex.sprint
+local tonumber, type = tonumber, type
+local lpegmatch = lpeg.match
+local texbox = tex.box
+local copy_list = node.copy_list
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+local ctxcatcodes = tex.ctxcatcodes
+
+local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end)
+
+colors = colors or { }
+
+local rgbtocmyk = colors.rgbtocmyk or function() return 0,0,0,1 end
+local cmyktorgb = colors.cmyktorgb or function() return 0,0,0 end
+local rgbtogray = colors.rgbtogray or function() return 0 end
+local cmyktogray = colors.cmyktogray or function() return 0 end
+
+metapost = metapost or { }
+metapost.specials = metapost.specials or { }
+metapost.specials.data = metapost.specials.data or { }
+metapost.externals = metapost.externals or { n = 0 }
+
+local data = metapost.specials.data
+
+local colordata = { {}, {}, {}, {}, {} }
+
+--~ (r,g,b) => cmyk : r=123 g= 1 b=hash
+--~ => spot : r=123 g= 2 b=hash
+--~ => transparent rgb : r=123 g= 3 b=hash
+--~ => transparent cmyk : r=123 g= 4 b=hash
+--~ => transparent spot : r=123 g= 5 b=hash
+--~ => rest : r=123 g=n>10 b=whatever
+
+local nooutercolor = "0 g 0 G"
+local nooutertransparency = "/Tr0 gs" -- only when set
+local outercolormode = 0
+local outercolor = nooutercolor
+local outertransparency = nooutertransparency
+local innercolor = nooutercolor
+local innertransparency = nooutertransparency
+
+local pdfcolor, pdftransparency = lpdf.color, lpdf.transparency
+local registercolor, registerspotcolor = colors.register, colors.registerspotcolor
+local registertransparency = transparencies.register
+
+function metapost.set_outer_color(mode,colormodel,colorattribute,transparencyattribute)
+ -- has always to be called before conversion
+ -- todo: transparency (not in the mood now)
+ outercolormode = mode
+ if mode == 1 or mode == 3 then
+ -- inherit from outer (registered color)
+ outercolor = pdfcolor(colormodel,colorattribute) or nooutercolor
+ outertransparency = pdftransparency(transparencyattribute) or nooutertransparency
+ elseif mode == 2 then
+ -- stand alone (see m-punk.tex)
+ outercolor = ""
+ outertransparency = ""
+ else -- 0
+ outercolor = nooutercolor
+ outertransparency = nooutertransparency
+ end
+ innercolor = outercolor
+ innertransparency = outertransparency -- not yet used
+end
+
+local function checked_color_pair(color)
+ if not color then
+ return innercolor, outercolor
+ elseif outercolormode == 3 then
+ innercolor = color
+ return innercolor, innercolor
+ else
+ return color, outercolor
+ end
+end
+
+metapost.checked_color_pair = checked_color_pair
+
+function metapost.colorinitializer()
+ innercolor = outercolor
+ innertransparency = outertransparency
+ return outercolor, outertransparency
+end
+
+function metapost.specials.register(str) -- only colors
+ local size, content, n, class = match(str,"^%%%%MetaPostSpecial: (%d+) (.*) (%d+) (%d+)$")
+ if class then
+ -- use lpeg splitter
+ local data = { }
+ for s in gmatch(content,"[^ ]+") do
+ data[#data+1] = s
+ end
+ class, n = tonumber(class), tonumber(n)
+ if class == 3 or class == 4 or class == 5 then
+ -- hm, weird
+ else
+ n = tonumber(data[1])
+ end
+ if n then
+ local cc = colordata[class]
+ if cc then
+ cc[n] = data
+ else
+ logs.report("mplib","problematic special: %s (no colordata class %s)", str or "?",class)
+ end
+ else
+ -- there is some bug to be solved, so we issue a message
+ logs.report("mplib","problematic special: %s", str or "?")
+ end
+ end
+--~ if match(str,"^%%%%MetaPostOption: multipass") then
+--~ metapost.multipass = true
+--~ end
+end
+
+local function spotcolorconverter(parent, n, d, p)
+ registerspotcolor(parent)
+ return pdfcolor(colors.model,registercolor(nil,'spot',parent,n,d,p))
+end
+
+function metapost.colorhandler(cs, object, result, colorconverter) -- handles specials
+ local cr = outercolor
+ local what = round(cs[2]*10000)
+ local data = colordata[what]
+ if data then
+ data = data[round(cs[3]*10000)]
+ end
+ if not data then
+ --
+ elseif what == 1 then
+ result[#result+1], cr = colorconverter({ data[2], data[3], data[4], data[5] })
+ elseif what == 2 then
+ result[#result+1] = spotcolorconverter(data[2],data[3],data[4],data[5])
+ else
+ if what == 3 then
+ result[#result+1], cr = colorconverter({ data[3], data[4], data[5]})
+ elseif what == 4 then
+ result[#result+1], cr = colorconverter({ data[3], data[4], data[5], data[6]})
+ elseif what == 5 then
+ result[#result+1] = spotcolorconverter(data[3],data[4],data[5],data[6])
+ end
+ object.prescript = "tr"
+ object.postscript = data[1] .. "," .. data[2]
+ end
+ object.color = nil
+ return object, cr
+end
+
+function metapost.colorspec(cs) -- used for shades ... returns table (for checking) or string (spot)
+ local what = round(cs[2]*10000)
+ local data = colordata[what][round(cs[3]*10000)]
+ if not data then
+ return { 0 }
+ elseif what == 1 then
+ return { tonumber(data[2]), tonumber(data[3]), tonumber(data[4]), tonumber(data[5]) }
+ elseif what == 2 then
+ return spotcolorconverter(data[2],data[3],data[4],data[5])
+ elseif what == 3 then
+ return { tonumber(data[3]), tonumber(data[4]), tonumber(data[5]) }
+ elseif what == 4 then
+ return { tonumber(data[3]), tonumber(data[4]), tonumber(data[5]), tonumber(data[6]) }
+ elseif what == 5 then
+ return spotcolorconverter(data[3],data[4],data[5],data[6])
+ end
+end
+
+function metapost.specials.tr(specification,object,result)
+ local a, t = match(specification,"^(.+),(.+)$")
+ local before = a and t and function()
+ result[#result+1] = format("/Tr%s gs",registertransparency(nil,a,t,true)) -- maybe nil instead of 'mp'
+ return object, result
+ end
+ local after = before and function()
+ result[#result+1] = outertransparency -- here we could revert to the outer color
+ return object, result
+ end
+ return object, before, nil, after
+end
+
+local specificationsplitter = lpeg.Ct(lpeg.splitat(" "))
+local colorsplitter = lpeg.Ct(lpeg.splitat(":"))
+local colorsplitter = lpeg.Ct(lpeg.splitter(":",tonumber))
+
+-- Unfortunately we cannot use cmyk colors natively because there is no
+-- generic color allocation primitive ... it's just an rgbcolor color.. This
+-- means that we cannot pass colors in either cmyk or rgb form.
+--
+-- def cmyk(expr c,m,y,k) =
+-- 1 withprescript "cc" withpostscript ddddecimal (c,m,y,k)
+-- enddef ;
+--
+-- This is also an example of a simple plugin.
+
+--~ function metapost.specials.cc(specification,object,result)
+--~ object.color = lpegmatch(specificationsplitter,specification)
+--~ return object, nil, nil, nil
+--~ end
+--~ function metapost.specials.cc(specification,object,result)
+--~ local c = lpegmatch(specificationsplitter,specification)
+--~ local o = object.color[1]
+--~ c[1],c[2],c[3],c[4] = o*c[1],o*c[2],o*c[3],o*c[4]
+--~ return object, nil, nil, nil
+--~ end
+
+-- thanks to taco's reading of the postscript manual:
+--
+-- x' = sx * x + ry * y + tx
+-- y' = rx * x + sy * y + ty
+
+function metapost.specials.fg(specification,object,result,flusher) -- graphics
+ local op = object.path
+ local first, second, fourth = op[1], op[2], op[4]
+ local tx, ty = first.x_coord , first.y_coord
+ local sx, sy = second.x_coord - tx, fourth.y_coord - ty
+ local rx, ry = second.y_coord - ty, fourth.x_coord - tx
+ if sx == 0 then sx = 0.00001 end
+ if sy == 0 then sy = 0.00001 end
+ local before = specification and function()
+ flusher.flushfigure(result)
+ sprint(ctxcatcodes,format("\\MPLIBfigure{%f}{%f}{%f}{%f}{%f}{%f}{%s}",sx,rx,ry,sy,tx,ty,specification))
+ object.path = nil
+ return object, { }
+ end
+ return { } , before, nil, nil -- replace { } by object for tracing
+end
+
+function metapost.specials.ps(specification,object,result) -- positions
+ local op = object.path
+ local first, third = op[1], op[3]
+ local x, y = first.x_coord, first.y_coord
+ local w, h = third.x_coord - x, third.y_coord - y
+ local label = specification
+ x = x - metapost.llx
+ y = metapost.ury - y
+ -- logs.report("mplib", "todo: position '%s' at (%s,%s) with (%s,%s)",label,x,y,w,h)
+ sprint(ctxcatcodes,format("\\dosavepositionwhd{%s}{0}{%sbp}{%sbp}{%sbp}{%sbp}{0pt}",label,x,y,w,h))
+ return { }, nil, nil, nil
+end
+
+local nofshades = 0 -- todo: hash resources, start at 1000 in order not to clash with older
+
+local function normalize(ca,cb)
+ if #cb == 1 then
+ if #ca == 4 then
+ cb[1], cb[2], cb[3], cb[4] = 0, 0, 0, 1-cb[1]
+ else
+ cb[1], cb[2], cb[3] = cb[1], cb[1], cb[1]
+ end
+ elseif #cb == 3 then
+ if #ca == 4 then
+ cb[1], cb[2], cb[3], cb[4] = rgbtocmyk(cb[1],cb[2],cb[3])
+ else
+ cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4])
+ end
+ end
+end
+
+-- todo: check for the same colorspace (actually a backend issue), now we can
+-- have several similar resources
+--
+-- normalize(ca,cb) fails for spotcolors
+
+function metapost.specials.cs(specification,object,result,flusher) -- spot colors?
+ -- a mess, not dynamic anyway
+ nofshades = nofshades + 1
+ flusher.flushfigure(result)
+ result = { }
+ local t = lpegmatch(specificationsplitter,specification)
+ -- we need a way to move/scale
+ local ca = lpegmatch(colorsplitter,t[4])
+ local cb = lpegmatch(colorsplitter,t[8])
+ if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end
+ if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end
+ local name = format("MplSh%s",nofshades)
+ local domain = { tonumber(t[1]), tonumber(t[2]) }
+ local coordinates = { tonumber(t[5]), tonumber(t[6]), tonumber(t[7]), tonumber(t[9]), tonumber(t[10]), tonumber(t[11]) }
+ if type(ca) == "string" then
+ -- backend specific (will be renamed)
+ lpdf.circularshade(name,domain,{ 0 },{ 1 },1,"DeviceGray",coordinates)
+ else
+ if #ca > #cb then
+ normalize(ca,cb)
+ elseif #ca < #cb then
+ normalize(cb,ca)
+ end
+ local model = colors.model
+ if model == "all" then
+ model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray"
+ end
+ if model == "rgb" then
+ if #ca == 4 then
+ ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4])
+ cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4])
+ ca[4], cb[4] = nil, nil
+ elseif #ca == 1 then
+ local a, b = 1-ca[1], 1-cb[1]
+ ca[1], ca[2], ca[3] = a, a, a
+ cb[1], cb[2], cb[3] = b, b, b
+ end
+ -- backend specific (will be renamed)
+ lpdf.circularshade(name,domain,ca,cb,1,"DeviceRGB",coordinates)
+ elseif model == "cmyk" then
+ if #ca == 3 then
+ ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3])
+ cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3])
+ elseif #ca == 1 then
+ ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1]
+ cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1]
+ end
+ -- backend specific (will be renamed)
+ lpdf.circularshade(name,domain,ca,cb,1,"DeviceCMYK",coordinates)
+ else
+ if #ca == 4 then
+ ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4])
+ cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4])
+ elseif #ca == 3 then
+ ca[1] = rgbtogray(ca[1],ca[2],ca[3])
+ cb[1] = rgbtogray(cb[1],cb[2],cb[3])
+ end
+ -- backend specific (will be renamed)
+ lpdf.circularshade(name,domain,ca,cb,1,"DeviceGRAY",coordinates)
+ end
+ end
+ local before = function()
+ result[#result+1] = "q /Pattern cs"
+ return object, result
+ end
+ local after = function()
+ result[#result+1] = format("W n /%s sh Q", name)
+ return object, result
+ end
+ object.color, object.type = nil, nil
+ return object, before, nil, after
+end
+
+function metapost.specials.ls(specification,object,result,flusher)
+ nofshades = nofshades + 1
+ flusher.flushfigure(result)
+ result = { }
+ local t = lpegmatch(specificationsplitter,specification)
+ -- we need a way to move/scale
+ local ca = lpegmatch(colorsplitter,t[4])
+ local cb = lpegmatch(colorsplitter,t[7])
+ if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end
+ if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end
+ local name = format("MpSh%s",nofshades)
+ local domain = { tonumber(t[1]), tonumber(t[2]) }
+ local coordinates = { tonumber(t[5]), tonumber(t[6]), tonumber(t[8]), tonumber(t[9]) }
+ if type(ca) == "string" then
+ -- backend specific (will be renamed)
+ lpdf.linearshade(name,domain,{ 0 },{ 1 },1,"DeviceGray",coordinates)
+ else
+ if #ca > #cb then
+ normalize(ca,cb)
+ elseif #ca < #cb then
+ normalize(cb,ca)
+ end
+ local model = colors.model
+ if model == "all" then
+ model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray"
+ end
+ if model == "rgb" then
+ if #ca == 4 then
+ ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4])
+ cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4])
+ elseif #ca == 1 then
+ local a, b = 1-ca[1], 1-cb[1]
+ ca[1], ca[2], ca[3] = a, a, a
+ cb[1], cb[2], cb[3] = b, b, b
+ end
+ -- backend specific (will be renamed)
+ lpdf.linearshade(name,domain,ca,cb,1,"DeviceRGB",coordinates)
+ elseif model == "cmyk" then
+ if #ca == 3 then
+ ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3])
+ cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3])
+ elseif #ca == 1 then
+ ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1]
+ cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1]
+ end
+ -- backend specific (will be renamed)
+ lpdf.linearshade(name,domain,ca,cb,1,"DeviceCMYK",coordinates)
+ else
+ if #ca == 4 then
+ ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4])
+ cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4])
+ elseif #ca == 3 then
+ ca[1] = rgbtogray(ca[1],ca[2],ca[3])
+ cb[1] = rgbtogray(cb[1],cb[2],cb[3])
+ end
+ -- backend specific (will be renamed)
+ lpdf.linearshade(name,domain,ca,cb,1,"DeviceGRAY",coordinates)
+ end
+ end
+ local before = function()
+ result[#result+1] = "q /Pattern cs"
+ return object, result
+ end
+ local after = function()
+ result[#result+1] = format("W n /%s sh Q", name)
+ return object, result
+ end
+ object.color, object.type = nil, nil
+ return object, before, nil, after
+end
+
+-- no need for a before here
+
+local current_format, current_graphic, current_initializations
+
+-- metapost.first_box = metapost.first_box or 1000
+-- metapost.last_box = metapost.last_box or 1100
+--~ metapost.textext_current = metapost.first_box
+metapost.multipass = false
+
+local textexts = { }
+
+function metapost.free_boxes() -- todo: mp direct list ipv box
+ -- for i = metapost.first_box,metapost.last_box do
+ -- local b = texbox[i]
+ -- if b then
+ -- texbox[i] = nil -- no node.flush_list(b) needed, else double free error
+ -- else
+ -- break
+ -- end
+ -- end
+ for n, box in next, textexts do
+ local tn = textexts[n]
+ if tn then
+ -- somehow not flushed (used)
+ textexts[n] = nil
+ end
+ end
+ textexts = { }
+end
+
+function metapost.settext(box,slot)
+ textexts[slot] = copy_list(texbox[box])
+ texbox[box] = nil
+ -- this will become
+ -- textexts[slot] = texbox[box]
+ -- unsetbox(box)
+end
+
+function metapost.gettext(box,slot)
+ texbox[box] = copy_list(textexts[slot])
+-- textexts[slot] = nil -- no, pictures can be placed several times
+end
+
+function metapost.specials.tf(specification,object)
+--~ print("setting", metapost.textext_current)
+ local n, str = match(specification,"^(%d+):(.+)$")
+ if n and str then
+ n = tonumber(n)
+ -- if metapost.textext_current < metapost.last_box then
+ -- metapost.textext_current = metapost.first_box + n - 1
+ -- end
+ if trace_textexts then
+ -- logs.report("metapost","first pass: order %s, box %s",n,metapost.textext_current)
+ logs.report("metapost","first pass: order %s",n)
+ end
+ -- sprint(ctxcatcodes,format("\\MPLIBsettext{%s}{%s}",metapost.textext_current,str))
+ sprint(ctxcatcodes,format("\\MPLIBsettext{%s}{%s}",n,str))
+ metapost.multipass = true
+ end
+ return { }, nil, nil, nil
+end
+
+function metapost.specials.ts(specification,object,result,flusher)
+ -- print("getting", metapost.textext_current)
+ local n, str = match(specification,"^(%d+):(.+)$")
+ if n and str then
+ n = tonumber(n)
+ if trace_textexts then
+ -- logs.report("metapost","second pass: order %s, box %s",n,metapost.textext_current)
+ logs.report("metapost","second pass: order %s",n)
+ end
+ local op = object.path
+ local first, second, fourth = op[1], op[2], op[4]
+ local tx, ty = first.x_coord , first.y_coord
+ local sx, sy = second.x_coord - tx, fourth.y_coord - ty
+ local rx, ry = second.y_coord - ty, fourth.x_coord - tx
+ if sx == 0 then sx = 0.00001 end
+ if sy == 0 then sy = 0.00001 end
+ if not trace_textexts then
+ object.path = nil
+ end
+ local before = function() -- no need for before function (just do it directly)
+ --~ flusher.flushfigure(result)
+ --~ sprint(ctxcatcodes,format("\\MPLIBgettext{%f}{%f}{%f}{%f}{%f}{%f}{%s}",sx,rx,ry,sy,tx,ty,metapost.textext_current))
+ --~ result = { }
+ result[#result+1] = format("q %f %f %f %f %f %f cm", sx,rx,ry,sy,tx,ty)
+ flusher.flushfigure(result)
+ -- if metapost.textext_current < metapost.last_box then
+ -- metapost.textext_current = metapost.first_box + n - 1
+ -- end
+ -- local b = metapost.textext_current
+ -- local box = texbox[b]
+ local box = textexts[n]
+ if box then
+ -- sprint(ctxcatcodes,format("\\MPLIBgettextscaled{%s}{%s}{%s}",b,metapost.sxsy(box.width,box.height,box.depth)))
+ sprint(ctxcatcodes,format("\\MPLIBgettextscaled{%s}{%s}{%s}",n,metapost.sxsy(box.width,box.height,box.depth)))
+ else
+ -- error
+ end
+ result = { "Q" }
+ return object, result
+ end
+ return { }, before, nil, nil -- replace { } by object for tracing
+ else
+ return { }, nil, nil, nil -- replace { } by object for tracing
+ end
+end
+
+-- rather generic pdf, so use this elsewhere too it no longer pays
+-- off to distinguish between outline and fill (we now have both
+-- too, e.g. in arrows)
+
+metapost.reducetogray = true
+
+local models = { }
+
+function models.all(cr)
+ local n = #cr
+ if n == 0 then
+ return checked_color_pair()
+ elseif metapost.reducetogray then
+ if n == 1 then
+ local s = cr[1]
+ return checked_color_pair(format("%.3f g %.3f G",s,s))
+ elseif n == 3 then
+ local r, g, b = cr[1], cr[2], cr[3]
+ if r == g and g == b then
+ return checked_color_pair(format("%.3f g %.3f G",r,r))
+ else
+ return checked_color_pair(format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b))
+ end
+ else
+ local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ if c == m and m == y and y == 0 then
+ k = 1 - k
+ return checked_color_pair(format("%.3f g %.3f G",k,k))
+ else
+ return checked_color_pair(format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k))
+ end
+ end
+ elseif n == 1 then
+ local s = cr[1]
+ return checked_color_pair(format("%.3f g %.3f G",s,s))
+ elseif n == 3 then
+ local r, g, b = cr[1], cr[2], cr[3]
+ return checked_color_pair(format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b))
+ else
+ local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ return checked_color_pair(format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k))
+ end
+end
+
+function models.rgb(cr)
+ local n = #cr
+ if n == 0 then
+ return checked_color_pair()
+ elseif metapost.reducetogray then
+ if n == 1 then
+ local s = cr[1]
+ checked_color_pair(format("%.3f g %.3f G",s,s))
+ elseif n == 3 then
+ local r, g, b = cr[1], cr[2], cr[3]
+ if r == g and g == b then
+ return checked_color_pair(format("%.3f g %.3f G",r,r))
+ else
+ return checked_color_pair(format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b))
+ end
+ else
+ local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ if c == m and m == y and y == 0 then
+ k = 1 - k
+ return checked_color_pair(format("%.3f g %.3f G",k,k))
+ else
+ local r, g, b = cmyktorgb(c,m,y,k)
+ return checked_color_pair(format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b))
+ end
+ end
+ elseif n == 1 then
+ local s = cr[1]
+ return checked_color_pair(format("%.3f g %.3f G",s,s))
+ else
+ local r, g, b
+ if n == 3 then
+ r, g, b = cmyktorgb(cr[1],cr[2],cr[3],cr[4])
+ else
+ r, g, b = cr[1], cr[2], cr[3]
+ end
+ return checked_color_pair(format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b))
+ end
+end
+
+function models.cmyk(cr)
+ local n = #cr
+ if n == 0 then
+ return checked_color_pair()
+ elseif metapost.reducetogray then
+ if n == 1 then
+ local s = cr[1]
+ return checked_color_pair(format("%.3f g %.3f G",s,s))
+ elseif n == 3 then
+ local r, g, b = cr[1], cr[2], cr[3]
+ if r == g and g == b then
+ return checked_color_pair(format("%.3f g %.3f G",r,r))
+ else
+ local c, m, y, k = rgbtocmyk(r,g,b)
+ return checked_color_pair(format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k))
+ end
+ else
+ local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ if c == m and m == y and y == 0 then
+ k = 1 - k
+ return checked_color_pair(format("%.3f g %.3f G",k,k))
+ else
+ return checked_color_pair(format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k))
+ end
+ end
+ elseif n == 1 then
+ local s = cr[1]
+ return checked_color_pair(format("%.3f g %.3f G",s,s))
+ else
+ local c, m, y, k
+ if n == 3 then
+ c, m, y, k = rgbtocmyk(cr[1],cr[2],cr[3])
+ else
+ c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ end
+ return checked_color_pair(format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k))
+ end
+end
+
+function models.gray(cr)
+ local n, s = #cr, 0
+ if n == 0 then
+ return checked_color_pair()
+ elseif n == 4 then
+ s = cmyktogray(cr[1],cr[2],cr[3],cr[4])
+ elseif n == 3 then
+ s = rgbtogray(cr[1],cr[2],cr[3])
+ else
+ s = cr[1]
+ end
+ return checked_color_pair(format("%.3f g %.3f G",s,s))
+end
+
+function metapost.colorconverter()
+ return models[colors.model] or gray
+end
+
+do
+
+ local P, S, V, Cs = lpeg.P, lpeg.S, lpeg.V, lpeg.Cs
+
+ local btex = P("btex")
+ local etex = P(" etex")
+ local vtex = P("verbatimtex")
+ local ttex = P("textext")
+ local gtex = P("graphictext")
+ local multipass = P("forcemultipass")
+ local spacing = S(" \n\r\t\v")^0
+ local dquote = P('"')
+
+ local found, forced = false, false
+
+ local function convert(str)
+ found = true
+ return "rawtextext(\"" .. str .. "\")" -- centered
+ end
+ local function ditto(str)
+ return "\" & ditto & \""
+ end
+ local function register()
+ found = true
+ end
+ local function force()
+ forced = true
+ end
+
+ local texmess = (dquote/ditto + (1 - etex))^0
+
+ local function ignore(s)
+ logs.report("mplib","ignoring verbatim tex: %s",s)
+ return ""
+ end
+
+ local parser = P {
+ [1] = Cs((V(2)/register + V(4)/ignore + V(3)/convert + V(5)/force + 1)^0),
+ [2] = ttex + gtex,
+ [3] = btex * spacing * Cs(texmess) * etex,
+ [4] = vtex * spacing * Cs(texmess) * etex,
+ [5] = multipass, -- experimental, only for testing
+ }
+
+ -- currently a a one-liner produces less code
+
+ local parser = Cs((
+ (ttex + gtex)/register
+ + (btex * spacing * Cs(texmess) * etex)/convert
+ + (vtex * spacing * Cs(texmess) * etex)/ignore
+ + 1
+ )^0)
+
+ function metapost.check_texts(str)
+ found, forced = false, false
+ return lpegmatch(parser,str), found, forced
+ end
+
+end
+
+local factor = 65536*(7227/7200)
+
+function metapost.edefsxsy(wd,ht,dp) -- helper for figure
+ local hd = ht + dp
+ commands.edef("sx",(wd ~= 0 and factor/wd) or 0)
+ commands.edef("sy",(hd ~= 0 and factor/hd) or 0)
+end
+
+function metapost.sxsy(wd,ht,dp) -- helper for text
+ local hd = ht + dp
+ return (wd ~= 0 and factor/wd) or 0, (hd ~= 0 and factor/hd) or 0
+end
+
+local no_trial_run = "_trial_run_ := false ;"
+local do_trial_run = "if unknown _trial_run_ : boolean _trial_run_ fi ; _trial_run_ := true ;"
+local text_data_template = "_tt_w_[%i]:=%f;_tt_h_[%i]:=%f;_tt_d_[%i]:=%f;"
+local do_begin_fig = "; beginfig(1); "
+local do_end_fig = "; endfig ;"
+local do_safeguard = ";"
+
+function metapost.text_texts_data()
+ local t, n = { }, 0
+--~ for i = metapost.first_box, metapost.last_box do
+--~ n = n + 1
+--~ local box = texbox[i]
+ for n, box in next, textexts do
+ if trace_textexts then
+ logs.report("metapost","passed data: order %s, box %s",n,i)
+ end
+ if box then
+ t[#t+1] = format(text_data_template,n,box.width/factor,n,box.height/factor,n,box.depth/factor)
+ else
+ break
+ end
+ end
+--~ print(table.serialize(t))
+ return t
+end
+
+metapost.intermediate = metapost.intermediate or {}
+metapost.intermediate.actions = metapost.intermediate.actions or {}
+metapost.intermediate.needed = false
+
+metapost.method = 1 -- 1:dumb 2:clever
+
+function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,askedfig)
+ local nofig = (askedfig and "") or false
+ local done_1, done_2, forced_1, forced_2
+ str, done_1, forced_1 = metapost.check_texts(str)
+ if not preamble or preamble == "" then
+ preamble, done_2, forced_2 = "", false, false
+ else
+ preamble, done_2, forced_2 = metapost.check_texts(preamble)
+ end
+ -- metapost.textext_current = metapost.first_box
+ metapost.intermediate.needed = false
+ metapost.multipass = false -- no needed here
+ current_format, current_graphic, current_initializations = mpsformat, str, initializations or ""
+ if metapost.method == 1 or (metapost.method == 2 and (done_1 or done_2)) then
+ -- first true means: trialrun, second true means: avoid extra run if no multipass
+ local flushed = metapost.process(mpsformat, {
+ preamble,
+ nofig or do_begin_fig,
+ do_trial_run,
+ current_initializations,
+ do_safeguard,
+ current_graphic,
+ nofig or do_end_fig
+ -- }, true, nil, true )
+ }, true, nil, not (forced_1 or forced_2), false, askedfig)
+ if metapost.intermediate.needed then
+ for _, action in next, metapost.intermediate.actions do
+ action()
+ end
+ end
+ if not flushed or not metapost.optimize then
+ -- tricky, we can only ask once for objects and therefore
+ -- we really need a second run when not optimized
+ sprint(ctxcatcodes,format("\\ctxlua{metapost.graphic_extra_pass(%s)}",askedfig or "false"))
+ end
+ else
+ metapost.process(mpsformat, {
+ preamble,
+ nofig or do_begin_fig,
+ no_trial_run,
+ current_initializations,
+ do_safeguard,
+ current_graphic,
+ nofig or do_end_fig
+ }, false, nil, false, false, askedfig )
+ end
+ -- here we could free the textext boxes
+ metapost.free_boxes()
+end
+
+function metapost.graphic_extra_pass(askedfig)
+ local nofig = (askedfig and "") or false
+ -- metapost.textext_current = metapost.first_box
+ metapost.process(current_format, {
+ nofig or do_begin_fig,
+ no_trial_run,
+ concat(metapost.text_texts_data()," ;\n"),
+ current_initializations,
+ do_safeguard,
+ current_graphic,
+ nofig or do_end_fig
+ }, false, nil, false, true, askedfig )
+end
+
+metapost.tex = metapost.tex or { }
+
+do -- only used in graphictexts
+
+ local environments = { }
+
+ function metapost.tex.set(str)
+ environments[#environments+1] = str
+ end
+ function metapost.tex.reset()
+ environments = { }
+ end
+ function metapost.tex.get()
+ return concat(environments,"\n")
+ end
+
+end
+
+local graphics = { }
+local start = [[\starttext]]
+local preamble = [[\long\def\MPLIBgraphictext#1{\startTEXpage[scale=10000]#1\stopTEXpage}]]
+local stop = [[\stoptext]]
+
+function metapost.specials.gt(specification,object) -- number, so that we can reorder
+ graphics[#graphics+1] = format("\\MPLIBgraphictext{%s}",specification)
+ metapost.intermediate.needed = true
+ metapost.multipass = true
+ return { }, nil, nil, nil
+end
+
+function metapost.intermediate.actions.makempy()
+ if #graphics > 0 then
+ local externals = metapost.externals
+ externals.n = externals.n + 1
+ starttiming(externals)
+ local mpofile = tex.jobname .. "-mpgraph"
+ local mpyfile = file.replacesuffix(mpofile,"mpy")
+ local pdffile = file.replacesuffix(mpofile,"pdf")
+ local texfile = file.replacesuffix(mpofile,"tex")
+ io.savedata(texfile, { start, preamble, metapost.tex.get(), concat(graphics,"\n"), stop }, "\n")
+ local command = format("context --once %s %s", (tex.interactionmode == 0 and "--batchmode") or "", texfile)
+ os.execute(command)
+ if io.exists(pdffile) then
+ command = format("pstoedit -ssp -dt -f mpost %s %s", pdffile, mpyfile)
+ os.execute(command)
+ local result = { }
+ if io.exists(mpyfile) then
+ local data = io.loaddata(mpyfile)
+ for figure in gmatch(data,"beginfig(.-)endfig") do
+ result[#result+1] = format("begingraphictextfig%sendgraphictextfig ;\n", figure)
+ end
+ io.savedata(mpyfile,concat(result,""))
+ end
+ end
+ stoptiming(externals)
+ graphics = { } -- ?
+ end
+end
diff --git a/tex/context/base/mlib-pps.mkiv b/tex/context/base/mlib-pps.mkiv
new file mode 100644
index 000000000..0a78a8704
--- /dev/null
+++ b/tex/context/base/mlib-pps.mkiv
@@ -0,0 +1,70 @@
+%D \module
+%D [ file=mlib-pps,
+%D version=2008.03.25,
+%D title=\METAPOST\ Integrated Graphics,
+%D subtitle=Basics,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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
+
+\registerctxluafile{mlib-pps}{1.001}
+
+%D Todo: catch nested graphics like external figures with dummies.
+
+% \newtoks\everyMPLIBtext % not yet used
+
+% \appendtoks
+% \let\handleuseMPgraphic \thirdofthreearguments
+% \let\handlereusableMPgraphic\thirdofthreearguments
+% \to \everyMPLIBtext
+
+% this will move !
+
+% Instead of preallocated boxes we now use a table of lists so that we
+% have no limitation. Typically an example of a next version solution
+% due to \LUATEX\ evolving.
+
+\newbox \MPtextbox
+\newtoks\everyMPLIBsettext
+
+\def\MPLIBfigure#1#2#3#4#5#6#7% todo: move Q q to lua
+ {\setbox\scratchbox\hbox{\externalfigure[#7]}%
+ \ctxlua{metapost.edefsxsy(\number\wd\scratchbox,\number\ht\scratchbox,0)}%
+ \pdfliteral direct{q #1 #2 #3 #4 #5 #6 cm}% no direct
+ \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[sx=\sx,sy=\sy]{\box\scratchbox}\hss}}%
+ \pdfliteral direct{Q}}
+
+\def\MPLIBsettext#1% #2%
+ {\dowithnextbox{\ctxlua{metapost.settext(\number\nextbox,#1)}}\hbox}
+
+\def\MPLIBgettextscaled#1#2#3% why a copy
+ {\ctxlua{metapost.gettext(\number\MPtextbox,#1)}%
+ \vbox to \zeropoint{\vss\hbox to \zeropoint{\black\scale[sx=#2,sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\hss}}}
+
+\def\MPLIBgraphictext#1%
+ {\startTEXpage[\c!scale=10000]#1\stopTEXpage}
+
+\protect \endinput
+
+% \def\MPLIBsettext#1% #2% we could as well store in hlists at the lua end i.e. just one box
+% {\global\setbox#1\hbox}
+%
+% \def\MPLIBfreetext#1%
+% {\global\setbox#1\emptybox}
+%
+% \def\MPLIBgettextscaled#1#2#3% why a copy
+% {\vbox to \zeropoint{\vss\hbox to \zeropoint{\black\scale[sx=#2,sy=#3]{\raise\dp#1\copy#1}\hss}}}
+%
+% \def\MPLIBallocate#1%
+% {\newbox\MPLIBfirst
+% \dorecurse{\numexpr#1-1\relax}{\let\MPLIBlast\relax\newbox\MPLIBlast}%
+% \MPLIBregister}
+%
+% \def\MPLIBregister % after allocate!
+% {\ctxlua{metapost.first_box, metapost.last_box = \number\MPLIBfirst, \number\MPLIBlast}}
diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua
new file mode 100644
index 000000000..f352e1db1
--- /dev/null
+++ b/tex/context/base/mlib-run.lua
@@ -0,0 +1,379 @@
+if not modules then modules = { } end modules ['mlib-run'] = {
+ 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",
+}
+
+--~ cmyk -> done, native
+--~ spot -> done, but needs reworking (simpler)
+--~ multitone ->
+--~ shade -> partly done, todo: cm
+--~ figure -> done
+--~ hyperlink -> low priority, easy
+
+-- new * run
+-- or
+-- new * execute^1 * finish
+
+-- a*[b,c] == b + a * (c-b)
+
+--[[ldx--
+
The directional helpers and pen analysis are more or less translated from the
+ code. It really helps that Taco know that source so well. Taco and I spent
+quite some time on speeding up the and code. There is not
+much to gain, especially if one keeps in mind that when integrated in
+only a part of the time is spent in . Of course an integrated
+approach is way faster than an external and processing time
+nears zero.
+--ldx]]--
+
+local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end)
+
+local format, gsub, match = string.format, string.gsub, string.match
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+metapost = metapost or { }
+
+metapost.showlog = false
+metapost.lastlog = ""
+
+function metapost.resetlastlog()
+ metapost.lastlog = ""
+end
+
+local function finder(name, mode, ftype)
+ if mode=="w" then
+ return name
+ elseif file.is_qualified_path(name) then
+ return name
+ else
+ return resolvers.find_file(name,ftype)
+ end
+end
+
+metapost.finder = finder
+
+metapost.parameters = {
+ hash_size = 100000,
+ main_memory = 4000000,
+ max_in_open = 50,
+ param_size = 100000,
+}
+
+metapost.exectime = metapost.exectime or { } -- hack
+
+local preamble = [[
+boolean mplib; string mp_parent_version;
+mplib := true;
+mp_parent_version := "%s";
+input %s ; dump ;
+]]
+
+function metapost.make(name, target, version)
+ starttiming(mplib)
+ target = file.replacesuffix(target or name, "mem")
+ local mpx = mplib.new ( table.merged (
+ metapost.parameters,
+ {
+ ini_version = true,
+ find_file = finder,
+ job_name = file.removesuffix(target),
+ }
+ ) )
+ if mpx then
+ starttiming(metapost.exectime)
+ local result = mpx:execute(format(preamble,version or "unknown",name))
+ stoptiming(metapost.exectime)
+ mpx:finish()
+ end
+ stoptiming(mplib)
+end
+
+function metapost.load(name)
+ starttiming(mplib)
+ local mpx = mplib.new ( table.merged (
+ metapost.parameters,
+ {
+ ini_version = false,
+ mem_name = file.replacesuffix(name,"mem"),
+ find_file = finder,
+ -- job_name = "mplib",
+ }
+ ) )
+ local result
+ if not mpx then
+ result = { status = 99, error = "out of memory"}
+ end
+ stoptiming(mplib)
+ return mpx, result
+end
+
+function metapost.unload(mpx)
+ starttiming(mplib)
+ if mpx then
+ mpx:finish()
+ end
+ stoptiming(mplib)
+end
+
+function metapost.reporterror(result)
+ if not result then
+ metapost.report("mp error: no result object returned")
+ elseif result.status > 0 then
+ local t, e, l = result.term, result.error, result.log
+ if t and t ~= "" then
+ metapost.report("mp terminal: %s",t)
+ end
+ if e then
+ metapost.report("mp error: %s",(e=="" and "?") or e)
+ end
+ if not t and not e and l then
+ metapost.lastlog = metapost.lastlog .. "\n" .. l
+ metapost.report("mp log: %s",l)
+ else
+ metapost.report("mp error: unknown, no error, terminal or log messages")
+ end
+ else
+ return false
+ end
+ return true
+end
+
+function metapost.checkformat(mpsinput, mpsformat, dirname)
+ mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
+ mpsformat = file.removesuffix(file.basename(mpsformat or texconfig.formatname or (tex and tex.formatname) or mpsinput))
+ local mpsbase = file.removesuffix(file.basename(mpsinput))
+ if mpsbase ~= mpsformat then
+ mpsformat = mpsformat .. "-" .. mpsbase
+ end
+ mpsformat = file.addsuffix(mpsformat, "mem")
+ local pth = dirname or file.dirname(texconfig.formatname or "")
+ if pth ~= "" then
+ mpsformat = file.join(pth,mpsformat)
+ end
+ local the_version = environment.version or "unset version"
+ if lfs.isfile(mpsformat) then
+ commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat)
+ local mpx, result = metapost.load(mpsformat)
+ if mpx then
+ local result = mpx:execute("show mp_parent_version ;")
+ if not result.log then
+ metapost.reporterror(result)
+ else
+ local version = match(result.log,">> *(.-)[\n\r]") or "unknown"
+ version = gsub(version,"[\'\"]","")
+ if version ~= the_version then
+ commands.writestatus("mplib","version mismatch: %s <> %s", version or "unknown", the_version)
+ else
+ return mpx
+ end
+ end
+ else
+ commands.writestatus("mplib","error in loading '%s' from '%s'", mpsinput, mpsformat)
+ metapost.reporterror(result)
+ end
+ end
+ commands.writestatus("mplib","making '%s' into '%s'", mpsinput, mpsformat)
+ metapost.make(mpsinput,mpsformat,the_version) -- somehow return ... fails here
+ if lfs.isfile(mpsformat) then
+ commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat)
+ return metapost.load(mpsformat)
+ else
+ commands.writestatus("mplib","problems with '%s' from '%s'", mpsinput, mpsformat)
+ end
+end
+
+local mpxformats = { }
+
+function metapost.format(instance,name)
+ name = name or instance
+ local mpx = mpxformats[instance]
+ if not mpx then
+ commands.writestatus("mplib","initializing instance '%s' using format '%s'",instance,name)
+ mpx = metapost.checkformat(name)
+ mpxformats[instance] = mpx
+ end
+ return mpx
+end
+
+function metapost.reset(mpx)
+ if not mpx then
+ -- nothing
+ elseif type(mpx) == "string" then
+ if mpxformats[mpx] then
+ mpxformats[mpx]:finish()
+ mpxformats[mpx] = nil
+ end
+ else
+ for name, instance in next, mpxformats do
+ if instance == mpx then
+ mpx:finish()
+ mpxformats[name] = nil
+ break
+ end
+ end
+ end
+end
+
+local mp_inp, mp_log, mp_tag = { }, { }, 0
+
+function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig)
+ local converted, result = false, {}
+ if type(mpx) == "string" then
+ mpx = metapost.format(mpx) -- goody
+ end
+ if mpx and data then
+ starttiming(metapost)
+ if trace_graphics then
+ if not mp_inp[mpx] then
+ mp_tag = mp_tag + 1
+ mp_inp[mpx] = io.open(format("%s-mplib-run-%03i.mp", tex.jobname,mp_tag),"w")
+ mp_log[mpx] = io.open(format("%s-mplib-run-%03i.log",tex.jobname,mp_tag),"w")
+ end
+ local banner = format("%% begin graphic: n=%s, trialrun=%s, multipass=%s, isextrapass=%s\n\n", metapost.n, tostring(trialrun), tostring(multipass), tostring(isextrapass))
+ mp_inp[mpx]:write(banner)
+ mp_log[mpx]:write(banner)
+ end
+ if type(data) == "table" then
+ for i=1,#data do
+ local d = data[i]
+ if d then
+ if trace_graphics then
+ mp_inp[mpx]:write(d)
+ end
+ starttiming(metapost.exectime)
+ result = mpx:execute(d)
+ stoptiming(metapost.exectime)
+ if trace_graphics and result then
+ local str = result.log or result.error
+ if str and str ~= "" then
+ mp_log[mpx]:write(str)
+ end
+ end
+ if not metapost.reporterror(result) then
+ if metapost.showlog then
+ local str = (result.term ~= "" and result.term) or "no terminal output"
+ if not str:is_empty() then
+ metapost.lastlog = metapost.lastlog .. "\n" .. str
+ metapost.report("mp log: %s",str)
+ end
+ end
+ if result.fig then
+ converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
+ end
+ end
+ else
+ metapost.report("mp error: invalid graphic component %s",i)
+ end
+ end
+ else
+ if trace_graphics then
+ mp_inp:write(data)
+ end
+ starttiming(metapost.exectime)
+ result = mpx[mpx]:execute(data)
+ stoptiming(metapost.exectime)
+ if trace_graphics and result then
+ local str = result.log or result.error
+ if str and str ~= "" then
+ mp_log[mpx]:write(str)
+ end
+ end
+ -- todo: error message
+ if not result then
+ metapost.report("mp error: no result object returned")
+ elseif result.status > 0 then
+ metapost.report("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+ else
+ if metapost.showlog then
+ metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+ metapost.report("mp info: %s",result.term or "no-term")
+ end
+ if result.fig then
+ converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
+ end
+ end
+ end
+ if trace_graphics then
+ local banner = "\n% end graphic\n\n"
+ mp_inp[mpx]:write(banner)
+ mp_log[mpx]:write(banner)
+ end
+ stoptiming(metapost)
+ end
+ return converted, result
+end
+
+function metapost.convert()
+ metapost.report('mp warning: no converter set')
+end
+
+function metapost.report(...)
+ logs.report("mplib",...)
+end
+
+-- handy
+
+function metapost.directrun(formatname,filename,outputformat,astable,mpdata)
+ local fullname = file.addsuffix(filename,"mp")
+ local data = mpdata or io.loaddata(fullname)
+ if outputformat ~= "svg" then
+ outputformat = "mps"
+ end
+ if not data then
+ logs.simple("unknown file '%s'",filename or "?")
+ else
+ local mpx = metapost.checkformat(formatname,formatname,caches.setpath("formats"))
+ if not mpx then
+ logs.simple("unknown format '%s'",formatname or "?")
+ else
+ logs.simple("processing '%s'",(mpdata and (filename or "data")) or fullname)
+ local result = mpx:execute(data)
+ if not result then
+ logs.simple("error: no result object returned")
+ elseif result.status > 0 then
+ logs.simple("error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+ else
+ if metapost.showlog then
+ metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+ logs.simple("info: %s",result.term or "no-term")
+ end
+ local figures = result.fig
+ if figures then
+ local sorted = table.sortedkeys(figures)
+ if astable then
+ local result = { }
+ logs.simple("storing %s figures in table",#sorted)
+ for k=1,#sorted do
+ local v = sorted[k]
+ if outputformat == "mps" then
+ result[v] = figures[v]:postscript()
+ else
+ result[v] = figures[v]:svg() -- (3) for prologues
+ end
+ end
+ return result
+ else
+ local basename = file.removesuffix(file.basename(filename))
+ for k=1,#sorted do
+ local v = sorted[k]
+ local output
+ if outputformat == "mps" then
+ output = figures[v]:postscript()
+ else
+ output = figures[v]:svg() -- (3) for prologues
+ end
+ local outname = format("%s-%s.%s",basename,v,outputformat)
+ logs.simple("saving %s bytes in '%s'",#output,outname)
+ io.savedata(outname,output)
+ end
+ return #sorted
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/tex/context/base/mtx-context-arrange.tex b/tex/context/base/mtx-context-arrange.tex
new file mode 100644
index 000000000..73431567d
--- /dev/null
+++ b/tex/context/base/mtx-context-arrange.tex
@@ -0,0 +1,111 @@
+% engine=luatex
+
+%D \module
+%D [ file=mtx-context-arrange,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Arrange Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=arrange [options] list-of-files
+%
+% --sort : sort filenames first
+% --paperoffset=dimension : left-top-offset
+% --noduplex : singlesided (doublesided is default)
+% --backspace=dimension : extra left offset
+% --topspace=dimension : extra top offset
+% --marking : add cutmarks
+% --addempty=list : add empty pages at/after (comma separated list)
+% --printformat : 2UP, etc
+%
+% end help
+
+\doifdocumentargument {paperoffset} {
+ \definepapersize
+ [offset=\getdocumentargument{paperoffset}]
+}
+
+\doifdocumentargumentelse {noduplex} {yes} {
+ \setuppagenumbering
+ [alternative=doublesided]
+ \setdocumentargument{sided}{doublesided}
+} {
+ \setdocumentargument{sided}{singlesided}
+}
+
+\setdefaultdocumentargument {textwidth} {0cm}
+\setdefaultdocumentargument {backspace} {0cm}
+\setdefaultdocumentargument {topspace} {0cm}
+
+\setuplayout
+ [backspace=\getdocumentargument{backspace},
+ topspace=\getdocumentargument{topspace},
+ width=middle,
+ height=middle,
+ location=middle,
+ header=0pt,
+ footer=0pt]
+
+\doifdocumentargument {marking} {yes} {
+ \setuplayout
+ [marking=on]
+}
+
+\startluacode
+ local printformat = document.arguments.printformat or ""
+ if printformat == "" then
+ printformat = "normal"
+ elseif string.find(printformat,".*up") then
+ printformat = "2UP,\\v!rotated"
+ elseif string.find(printformat,".*down") then
+ printformat = "2DOWN,\\v!rotated"
+ elseif string.find(printformat,".*side") then
+ printformat = "2SIDE,\\v!rotated"
+ end
+ document.setargument("printformat",printformat)
+\stopluacode
+
+\setuparranging
+ [\getdocumentargument{sided},
+ \getdocumentargument{printformat}]
+
+\starttext
+
+\startluacode
+ local format = string.format
+ local fprint = function(...) tex.sprint(tex.ctxcatcodes,format(...)) end
+
+ if #document.files > 0 then
+ if document.arguments.sort then
+ table.sort(document.files)
+ end
+ local emptypages = document.arguments.addempty or ""
+ local textwidth = document.arguments.textwidth or "0cm"
+ for _, filename in ipairs(document.files) do
+ if not string.find(filename,"^mtx%-context%-") then
+ context.insertpages (
+ { filename },
+ { emptypages },
+ { width = textwidth }
+ )
+ end
+ end
+ else
+ fprint("no files given")
+ end
+\stopluacode
+
+\stoptext
+
+
+
diff --git a/tex/context/base/mtx-context-combine.tex b/tex/context/base/mtx-context-combine.tex
new file mode 100644
index 000000000..8a861ab83
--- /dev/null
+++ b/tex/context/base/mtx-context-combine.tex
@@ -0,0 +1,116 @@
+%D \module
+%D [ file=mtx-context-combine,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Combine Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=combine [options] list-of-files
+%
+% --sort : sort filenames first
+% --paperoffset=dimension : left-top-offset
+% --nobanner : no footer etc
+% --combination : h*v or hxv
+% --paperformat=spec : paper*print or paperxprint
+% --nobanner : no footerlines
+% --bannerheight=dimension : height of banner
+% --bannerstring=dimension : height of bannerstring
+%
+% end help
+
+\input mtx-context-common.tex
+
+\doifdocumentargumentelse {paperoffset} {
+
+ \setuplayout
+ [topspace=\getdocumentargument{paperoffset},
+ backspace=\getdocumentargument{paperoffset}]
+
+} {
+
+ \setuplayout
+ [topspace=0pt,
+ backspace=0pt]
+
+}
+
+\setuplayout
+ [header=0pt,
+ footer=0pt,
+ width=middle,
+ height=middle]
+
+\setuppapersize
+ [\getdocumentargument{paperformat_paper}]
+ [\getdocumentargument{paperformat_print}]
+
+\doifnotdocumentargument {bannerheight} {
+ \setuplayout
+ [footer=1cm]
+}
+
+\doifelse {\getdocumentargument{nobanner}} {yes} {
+ \setuplayout
+ [footer=0cm]
+ \setupbackgrounds
+ [page]
+ [background=]
+} {
+ \definelayer
+ [page]
+ [width=\paperwidth,
+ height=\paperheight]
+
+ \setupbackgrounds
+ [page]
+ [background=page]
+}
+
+\setupexternalfigures
+ [directory=]
+
+\starttext
+
+\startluacode
+ local format = string.format
+
+ if #document.files > 0 then
+ if document.arguments["sort"] then
+ table.sort(document.files)
+ end
+ local dobanner = not document.arguments["nobanner"]
+ local bannerheight = document.arguments["bannerheight"]
+ local nx = document.arguments.combination_nx or 2
+ local ny = document.arguments.combination_ny or 2
+ for _, filename in ipairs(document.files) do
+ if not string.find(filename,"^mtx%-context%-") then
+ -- could be a macro
+ local bannerstring = format("\\tttf\\detokenize{%s}\\quad\\quad\\currentdate\\quad\\quad\\pagenumber",file.basename(filename))
+ if dobanner then
+ if bannerheight then
+ context("\\setuptexttexts[{\\setlayerframed[page][preset=middlebottom][frame=off,height=%s]{%s}}]",bannerheight,bannerstring)
+ else
+ context("\\setupfootertexts[{%s}]",bannerstring)
+ end
+ end
+ context("\\combinepages[%s][nx=%s,ny=%s]",filename,nx,ny)
+ context("\\page")
+ end
+ end
+ else
+ context("no files given")
+ end
+\stopluacode
+
+\stoptext
+
diff --git a/tex/context/base/mtx-context-common.tex b/tex/context/base/mtx-context-common.tex
new file mode 100644
index 000000000..8327dd28d
--- /dev/null
+++ b/tex/context/base/mtx-context-common.tex
@@ -0,0 +1,43 @@
+%D \module
+%D [ file=mtx-context-common,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Common Stuff,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\startluacode
+ local combination = document.arguments['combination'] or '2*2'
+ local nx, ny = string.match(combination,"^(%d+)%s*[%*x]%s*(%d+)$")
+ if not nx then
+ nx, ny = 2, 2
+ elseif not ny then
+ nx = tonumber(combination) or 2
+ ny = nx
+ else
+ nx = tonumber(nx) or 2
+ ny = tonumber(ny) or nx or 2
+ end
+ document.setargument("combination_nx",nx)
+ document.setargument("combination_ny",ny)
+\stopluacode
+
+\startluacode
+ local paperformat = document.arguments['paperformat'] or 'A4*A4'
+ paperformat = string.upper(paperformat)
+ local f, t = string.match(paperformat,"^(.-)%s*[%*xX]%s*(.-)$")
+ if not f then
+ f, t = "A4", "A4"
+ elseif not t then
+ t = f
+ end
+ document.setargument("paperformat_paper",f)
+ document.setargument("paperformat_print",t)
+\stopluacode
+
+\endinput
diff --git a/tex/context/base/mtx-context-ideas.tex b/tex/context/base/mtx-context-ideas.tex
new file mode 100644
index 000000000..24d11a5b5
--- /dev/null
+++ b/tex/context/base/mtx-context-ideas.tex
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=mtx-context-ideas,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Placeholder File,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% The hard coded goodies in texexec are now external. We also use this
+% opportunity to explore mixed tex/lua user interfacing so you will see
+% some old and new tricks here that might disappear or become extended.
+%
+% if users want to add their own ... go ahead but use a different
+% namespace:
+%
+% mtx-context-third-somename.tex
+% mtx-context-user-somename.tex
+
+% \startluacode
+% -- some day we might move the whole ui to lua
+% context = context or { }
+% function interfaces.tosetups(setups)
+% if not setups then
+% return ""
+% elseif type(setups) == "table" then
+% local t = { }
+% for k,v in next, setups do
+% t[k] = "{" .. v .. "}"
+% end
+% return table.concat(t,",")
+% else
+% return setups
+% end
+% end
+% function context.setuplayout(category,setups)
+% setups = setups or category
+% tex.sprint(string.format("\\setuplayout[%s]",interfaces.tosetups(setups))
+% end
+% local topspace = document.arguments["topspace"] or 0
+% if dimen(topspace) > dimen(0) then
+% context.setuplayout { topspace = dimen(topspace) }
+% end
+% local backspace = document.arguments["backspace"] or 0
+% if dimen(topspace) > dimen(0) then
+% context.setuplayout { backspace = dimen(backspace) }
+% end
+% \stopluacode
diff --git a/tex/context/base/mtx-context-listing.tex b/tex/context/base/mtx-context-listing.tex
new file mode 100644
index 000000000..d0dbcbba0
--- /dev/null
+++ b/tex/context/base/mtx-context-listing.tex
@@ -0,0 +1,100 @@
+%D \module
+%D [ file=mtx-context-listing,
+%D version=2008.11.10, % about that time i started playing with this
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Listing Files,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 is a \TEXEXEC\ features that has been moved to \MKIV.
+
+% begin help
+%
+% usage: context --extra=listing [options] list-of-files
+%
+% --sort : sort filenames first
+% --topspace=dimension : distance above first line
+% --backspace=dimension : distance before left margin
+% --pretty : pretty print comform suffix (temporarily disabled)
+% --bodyfont=list : additional bodyfont settings
+% --paperformat=spec : paper*print or paperxprint
+%
+% end help
+
+\input mtx-context-common.tex
+
+\setupbodyfont
+ [11pt,tt,\getdocumentargument{bodyfont}]
+
+\setuptyping
+ [lines=yes]
+
+\setuplayout
+ [header=0cm,
+ footer=1.5cm,
+ topspace=\getdocumentargumentdefault{topspace}{1.5cm},
+ backspace=\getdocumentargumentdefault{backspace}{1.5cm},
+ width=middle,
+ height=middle]
+
+\setuppapersize
+ [\getdocumentargument{paperformat_paper}]
+ [\getdocumentargument{paperformat_print}]
+
+% \startluacode
+% -- syntax check
+% local topspace = dimen(document.arguments.topspace or 0)
+% local backspace = dimen(document.arguments.backspace or 0)
+% local zeropoint = dimen(0)
+% if topspace > zeropoint then
+% context.setuplayout { topspace = tostring(topspace) }
+% end
+% if backspace > zeropoint then
+% context.setuplayout { backspace = tostring(backspace) }
+% end
+% \stopluacode
+
+\starttext
+
+\startluacode
+ local types = {
+ mkiv = "tex",
+ mkii = "tex",
+ cld = "lua",
+ lfg = "lua",
+ }
+
+ if #document.files > 0 then
+ if document.arguments.sort then
+ table.sort(document.files)
+ end
+ for _, filename in ipairs(document.files) do
+ if not string.find(filename,"^mtx%-context%-") then
+ local pretty = document.arguments.pretty
+ if pretty == true then
+ pretty = file.extname(filename) or ""
+ elseif pretty == false then
+ pretty = ""
+ else
+ -- forced
+ end
+ context.page()
+ context.setupfootertexts( -- return true: we need to keep this entry
+ { function() context.detokenize(file.basename(filename)) return true end },
+ { function() context.pagenumber() return true end }
+ )
+ context.setuptyping { option = types[pretty] or pretty }
+ context.typefile(filename)
+ end
+ end
+ else
+ context("no files given")
+ end
+\stopluacode
+
+\stoptext
diff --git a/tex/context/base/mtx-context-timing.tex b/tex/context/base/mtx-context-timing.tex
new file mode 100644
index 000000000..b788d4b63
--- /dev/null
+++ b/tex/context/base/mtx-context-timing.tex
@@ -0,0 +1,44 @@
+%D \module
+%D [ file=mtx-context-timing,
+%D version=2009.03.21,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Timing Runs,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% begin help
+%
+% usage: context --extra=timing filename
+%
+% end help
+
+\enablemode[no-timing] \usemodule[timing]
+
+\setuplayout
+ [topspace=1cm,
+ bottomspace=.5cm,
+ header=0pt,
+ width=middle,
+ height=middle,
+ style=\tt]
+
+\setupfootertexts
+ [\getdocumentfilename{1}-luatex-progress.lut -- \pagenumber]
+
+\setupcolors
+ [state=start]
+
+\starttext
+
+ \doifsomething {\getdocumentfilename{1}} {
+ \LoadUsage{\getdocumentfilename{1}-luatex-progress}
+ \ShowUsage{\getdocumentfilename{1}-luatex-progress}
+ }
+
+\stoptext
+
diff --git a/tex/context/base/mult-chk.lua b/tex/context/base/mult-chk.lua
new file mode 100644
index 000000000..bdbd1dd22
--- /dev/null
+++ b/tex/context/base/mult-chk.lua
@@ -0,0 +1,66 @@
+if not modules then modules = { } end modules ['mult-chk'] = {
+ version = 1.001,
+ comment = "companion to mult-chk.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local lpegmatch = lpeg.match
+local type = type
+local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+
+interfaces = interfaces or { }
+
+interfaces.syntax = {
+ test = { keys = table.tohash { "a","b","c","d","e","f","g" } }
+}
+
+function interfaces.invalidkey(kind,key)
+ commands.writestatus("syntax","invalid key '%s' for '%s' in line %s",key,kind,tex.inputlineno)
+end
+
+function interfaces.setvalidkeys(kind,list)
+ local s = interfaces.syntax[kind]
+ if not s then
+ interfaces.syntax[kind] = {
+ keys = aux.settings_to_set(list)
+ }
+ else
+ s.keys = aux.settings_to_set(list)
+ end
+end
+
+function interfaces.addvalidkeys(kind,list)
+ local s = interfaces.syntax[kind]
+ if not s then
+ interfaces.syntax[kind] = {
+ keys = aux.settings_to_set(list)
+ }
+ else
+ aux.settings_to_set(list,s.keys)
+ end
+end
+
+local prefix, kind, keys
+
+local function set(key,value)
+ if keys and not keys[key] then
+ interfaces.invalidkey(kind,key)
+ else
+ texsprint(ctxcatcodes,format("\\setsomevalue{%s}{%s}{%s}",prefix,key,value))
+ end
+end
+
+local pattern = aux.make_settings_to_hash_pattern(set,"tolerant")
+
+function commands.getcheckedparameters(k,p,s)
+ if s and s ~= "" then
+ prefix, kind = p, k
+ keys = k and k ~= "" and interfaces.syntax[k].keys
+ lpegmatch(pattern,s)
+ end
+end
+
+_gcp_ = commands.getcheckedparameters
diff --git a/tex/context/base/mult-chk.mkii b/tex/context/base/mult-chk.mkii
new file mode 100644
index 000000000..60f568a1e
--- /dev/null
+++ b/tex/context/base/mult-chk.mkii
@@ -0,0 +1,29 @@
+%D \module
+%D [ file=mult-chk,
+%D version=2009.04.13,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Multilingual Macros / Checking}
+
+%D No checking in \MKII.
+
+\def\gobbleparameters{\doquadrupleempty\dogobbleparameters} % todo: 1,2,3,4 case
+\def\dogobbleparameters[#1][#2][#3][#4]{}
+
+\def\setvalidparameterkeys{\gobbleparameters} % forward reference, so no \let
+\def\addvalidparameterkeys{\gobbleparameters} % forward reference, so no \let
+
+\let\enablecheckparameters \relax
+\let\disablecheckparameters\relax
+
+\def\getcheckedparameters[#1]{\getparameters} % just ignore the checking
+
+\endinput
diff --git a/tex/context/base/mult-chk.mkiv b/tex/context/base/mult-chk.mkiv
new file mode 100644
index 000000000..7b40bd64a
--- /dev/null
+++ b/tex/context/base/mult-chk.mkiv
@@ -0,0 +1,103 @@
+%D \module
+%D [ file=mult-chk,
+%D version=2009.04.13,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Checking,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=\PRAGMA]
+%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 Multilingual Macros / Checking}
+
+%D This is very experimental code that eventually might be used
+%D once we have split the whole code base.
+
+%D \startbuffer
+%D \getcheckedparameters[MyTest][MyNamespace][a=1,b=2,c=3,d=4,crap=whatever]
+%D
+%D \MyNamespacea\quad
+%D \MyNamespaceb\quad
+%D \MyNamespacec\quad
+%D \MyNamespaced\quad
+%D crap is \ifdefined\MyNamespacecrap\else un\fi defined
+%D \stopbuffer
+%D
+%D \enablecheckparameters
+%D
+%D \setvalidparameterkeys[MyTest][a,b,c,d] \getbuffer \par
+%D \addvalidparameterkeys[MyTest][crap] \getbuffer \par
+
+\unprotect
+
+\registerctxluafile{mult-chk}{1.001}
+
+\def\setvalidparameterkeys{\dodoubleargument\dosetvalidparameterkeys}
+\def\addvalidparameterkeys{\dodoubleargument\doaddvalidparameterkeys}
+
+\def\dosetvalidparameterkeys[#1][#2]{\ctxlua{interfaces.setvalidkeys("#1",\!!bs#2\!!es)}}
+\def\doaddvalidparameterkeys[#1][#2]{\ctxlua{interfaces.addvalidkeys("#1",\!!bs#2\!!es)}}
+
+\def\getcheckedparametersyes[#1]#2[#3]#4[#5%
+ {\if\noexpand#5]%
+ \expandafter\gobblethreearguments
+ \else
+ \let\setsomevalue\dosetvalue
+ \expandafter\dogetcheckedparametersyes
+ \fi{#1}{#3}#5}
+
+\def\dogetcheckedparametersyes#1#2#3]%
+ {\ctxlua{_gcp_("#1","#2",\!!bs\detokenize{#3}\!!es)}}
+
+\def\getcheckedparametersnop[#1]#2[#3]#4[#5%
+ {\if\noexpand#5]%
+ \expandafter\gobbletwoarguments
+ \else
+ \let\setsomevalue\dosetvalue
+ \expandafter\dogetcheckedparametersnop
+ \fi{#3}#5}
+
+\def\dogetcheckedparametersnop#1#2]%
+ {\def\p!dogetparameter{\p!doassign#1}%
+ \xprocesscommaitem#2,],\@relax@}
+
+\def\disablecheckparameters{\let\getcheckedparameters\getcheckedparametersnop}
+\def\enablecheckparameters {\let\getcheckedparameters\getcheckedparametersyes}
+
+\disablecheckparameters
+
+\protect \endinput
+
+\starttext
+
+\testfeatureonce{10000}{\getcheckedparameters[test][xx][a=b,c= d, e = f]} % 0.20 seconds
+
+\enablecheckparameters
+
+\testfeatureonce{10000}{\getcheckedparameters[test][xx][a=b,c= d, e = f]} % 0.35 seconds
+
+\getcheckedparameters[test][xx][a=a]
+\getcheckedparameters[test][xx][b= b]
+\getcheckedparameters[test][xx][c = c]
+\getcheckedparameters[test][xx][d = d d , e = e ,f = f ]
+\getcheckedparameters[test][xx][g={oeps {oeps}}]
+\getcheckedparameters[test][xx][crap=whatever]
+
+\startlines
+[a:\getvalue{xxa}][a]
+[b:\getvalue{xxb}][b]
+[c:\getvalue{xxc}][c]
+[d:\getvalue{xxd}][d d ]
+[e:\getvalue{xxe}][e ]
+[f:\getvalue{xxf}][f ]
+[g:\getvalue{xxg}][\detokenize\expandafter{\xxg}]
+\stoplines
+
+\setvalidparameterkeys[test][crap]
+
+\getcheckedparameters[test][xx][crap=whatever]
+
+\stoptext
diff --git a/tex/context/base/mult-cld.lua b/tex/context/base/mult-cld.lua
new file mode 100644
index 000000000..81038b68b
--- /dev/null
+++ b/tex/context/base/mult-cld.lua
@@ -0,0 +1,212 @@
+if not modules then modules = { } end modules ['mult-cld'] = {
+ version = 1.001,
+ comment = "companion to mult-cld.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is an experiment: generating context code at the lua end. After all
+-- it is surprisingly simple to implement due to metatables. I was wondering
+-- if there was a more natural way to deal with commands at the lua end.
+-- Of course it's a bit slower but often more readable when mixed with lua
+-- code. It can also be handy when generating documents from databases or
+-- when constructing large tables or so.
+--
+-- Todo: optional checking against interface
+-- Todo: coroutine trickery
+
+context = context or { }
+
+local format, concat = string.format, table.concat
+local next, type = next, type
+local texsprint, texiowrite, ctxcatcodes = tex.sprint, texio.write, tex.ctxcatcodes
+
+local flush = texsprint or function(cct,...) print(table.concat{...}) end
+
+local _stack_, _n_ = { }, 0
+
+local function _store_(ti)
+ _n_ = _n_ + 1
+ _stack_[_n_] = ti
+ return _n_
+end
+
+local function _flush_(n)
+ if not _stack_[n]() then
+ _stack_[n] = nil
+ else
+ -- keep, beware, that way the stack can grow
+ end
+end
+
+context._stack_ = _stack_
+context._store_ = _store_
+context._flush_ = _flush_
+
+function tex.fprint(...) -- goodie
+ texsprint(ctxcatcodes,format(...))
+end
+
+function context.trace(intercept)
+ local normalflush = flush
+ flush = function(c,...)
+ logs.report("context",concat({...}))
+ if not intercept then
+ normalflush(c,...)
+ end
+ end
+ context.trace = function() end
+end
+
+trackers.register("context.flush", function(v) if v then context.trace() end end)
+trackers.register("context.intercept", function(v) if v then context.trace(true) end end)
+
+local function writer(k,...)
+ if k then
+ flush(ctxcatcodes,k)
+ local t = { ... }
+ local nt = #t
+ if nt > 0 then
+ for i=1,nt do
+ local ti = t[i]
+ local typ = type(ti)
+ if ti == nil then
+ -- next
+ elseif typ == "function" then
+ flush(ctxcatcodes,"{\\mkivflush{" .. _store_(ti) .. "}}")
+ elseif typ == "string" or typ == "number" then
+ flush(ctxcatcodes,"{",ti,"}")
+ elseif typ == "table" then
+ local tn = #ti
+ if tn > 0 then
+ for j=1,tn do
+ local tj = ti[j]
+ if type(tj) == "function" then
+ ti[j] = "\\mkivflush{" .. _store_(tj) .. "}"
+ end
+ end
+ flush(ctxcatcodes,"[",concat(ti,","),"]")
+ else
+ flush(ctxcatcodes,"[")
+ local done = false
+ for k, v in next, ti do
+ if done then
+ flush(ctxcatcodes,",",k,'=',v)
+ else
+ flush(ctxcatcodes,k,'=',v)
+ done = true
+ end
+ end
+ flush(ctxcatcodes,"]")
+ end
+ -- elseif typ == "boolean" then
+ -- flush(ctxcatcodes,"\n")
+ elseif ti == true then
+ flush(ctxcatcodes,"\n")
+ elseif typ == false then
+ -- if force == "direct" then
+ flush(ctxcatcodes,tostring(ti))
+ -- end
+ elseif typ == "thread" then
+ logs.report("interfaces","coroutines not supported as we cannot yeild across boundaries")
+ else
+ logs.report("interfaces","error: %s gets a weird argument %s",k,tostring(ti))
+ end
+ end
+ end
+ end
+end
+
+-- -- --
+
+local function indexer(t,k)
+ local c = "\\" .. k .. " "
+ local f = function(...) return writer(c,...) end
+ t[k] = f
+ return f
+end
+
+local function caller(t,f,a,...)
+ if a then
+ flush(ctxcatcodes,format(f,a,...))
+ elseif type(f) == "function" then
+ flush(ctxcatcodes,"{\\mkivflush{" .. _store_(f) .. "}}")
+ elseif f then
+ flush(ctxcatcodes,f)
+ else
+ flush(ctxcatcodes,"\n")
+ end
+end
+
+setmetatable(context, { __index = indexer, __call = caller } )
+
+-- the only non macro:
+
+local trace_cld = false
+
+function context.runfile(filename)
+ filename = resolvers.findtexfile(filename) or ""
+ if filename ~= "" then
+ local ok = dofile(filename)
+ if type(ok) == "function" then
+ if trace_cld then
+ commands.writestatus("cld","begin of file '%s' (function call)",filename)
+ end
+ ok()
+ if trace_cld then
+ commands.writestatus("cld","end of file '%s' (function call)",filename)
+ end
+ elseif ok then
+ commands.writestatus("cld","file '%s' is processed and returns true",filename)
+ else
+ commands.writestatus("cld","file '%s' is processed and returns nothing",filename)
+ end
+ else
+ commands.writestatus("cld","unknown file '%s'",filename)
+ end
+end
+
+-- tracking is using the regular mechanism; we need to define
+-- these 'macro' functions explictly as otherwise they are are
+-- delayed (as all commands print back to tex, so that tracing
+-- would be enabled afterwards)
+
+trackers.register("cld.print", function(v)
+ trace_cld = v
+ if v then
+ flush = function(c,...)
+ texiowrite(...)
+ texsprint(c,...)
+ end
+ else
+ flush = texsprint
+ end
+end)
+
+function context.enabletrackers (str) trackers.enable (str) end
+function context.disabletrackers(str) trackers.disable(str) end
+
+-- see demo-cld.cld for an example
+
+-- context.starttext(true)
+-- context.chapter({ "label" }, "title", true)
+-- context.chapter(function() return { "label" } end, "title", true)
+--
+-- context.startchapter({ title = "test" }, { more = "oeps" }, true)
+--
+-- context.bTABLE(true)
+-- for i=1,10 do
+-- context.bTR()
+-- for i=1,10 do
+-- context.bTD()
+-- context("%#2i",math.random(99))
+-- context.eTD()
+-- end
+-- context.eTR(true)
+-- end
+-- context.eTABLE(true)
+--
+-- context.stopchapter(true)
+--
+-- context.stoptext(true)
diff --git a/tex/context/base/mult-cld.mkiv b/tex/context/base/mult-cld.mkiv
new file mode 100644
index 000000000..1c5ebd34a
--- /dev/null
+++ b/tex/context/base/mult-cld.mkiv
@@ -0,0 +1,29 @@
+%D \module
+%D [ file=mult-ini,
+%D version=2008.10.22, % 1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is just an idea, maybe a bad one.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Lua}
+
+\registerctxluafile{mult-cld}{1.001}
+\registerctxluafile{mult-clm}{1.001}
+
+\unprotect
+
+\def\defmkivstart#1{\unexpanded\expandafter\def\csname\e!start#1\endcsname}
+\def\defmkivstop #1{\unexpanded\def\csname\e!stop #1\endcsname}
+\def\defmkiv #1{\unexpanded\def\csname #1\endcsname}
+
+\def\mkivflush #1{\ctxlua{context._flush_(#1)}}
+
+\protect \endinput
diff --git a/tex/context/base/mult-clm.lua b/tex/context/base/mult-clm.lua
new file mode 100644
index 000000000..8838ea532
--- /dev/null
+++ b/tex/context/base/mult-clm.lua
@@ -0,0 +1,184 @@
+if not modules then modules = { } end modules ['mult-clm'] = {
+ version = 1.001,
+ comment = "companion to mult-clm.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- another experiment
+-- todo: multilingual
+
+local texsprint, ctxcatcodes, vrbcatcodes = tex.sprint, tex.ctxcatcodes, tex.vrbcatcodes
+local format, insert, remove, concat = string.format, table.insert, table.remove, table.concat
+local unpack = unpack or table.unpack
+
+local trace_define = false trackers.register("context.define", function(v) trace_define = v end)
+
+mkiv = mkiv or { }
+
+mkiv.h, mkiv.a = aux.settings_to_hash, aux.settings_to_array
+
+local starters, stoppers, macros, stack = { }, { }, { }, { }
+
+local checkers = {
+ "\\dosingleempty",
+ "\\dodoubleempty",
+ "\\dotripleempty",
+ "\\doquadrupleempty",
+ "\\doquintupleempty",
+ "\\dosixtupleempty",
+}
+
+function mkiv.m(name,...)
+ macros[name](...)
+end
+
+function mkiv.b(name,...)
+ local sn = stack[name]
+ insert(sn,{...})
+ starters[name](...)
+end
+
+function mkiv.e(name)
+ local sn = stack[name]
+ local sv = remove(sn)
+ if sv then
+ stoppers[name](unpack(sv))
+ else
+ -- nesting error
+ end
+end
+
+mkiv.n = tonumber
+
+function mkiv.define(name,specification) -- name is optional
+ if type(name) == "table" then
+ specification = name
+ name = specification.name
+ end
+ if name and specification then
+ local arguments = specification.arguments
+ local na = (arguments and #arguments) or 0
+ local environment = specification.environment
+ if na == 0 then
+ if environment then
+ texsprint(ctxcatcodes,"\\defmkstart{",name,"}{\\ctxlua{mkiv.b('",name,"')}}")
+ texsprint(ctxcatcodes,"\\defmkstop{", name,"}{\\ctxlua{mkiv.b('",name,"')}}")
+ else
+ texsprint(ctxcatcodes,"\\defmkiv{", name,"}{\\ctxlua{mkiv.m('",name,"')}}")
+ end
+ else
+ stack[name] = { }
+ local opt, done = 0, false
+ local mkivdo = "\\mkivdo" .. name
+ texsprint(ctxcatcodes,"\\def",mkivdo)
+ for i=1,na do
+ local a = arguments[i]
+ local kind = a[1]
+ if kind == "option" then
+ texsprint(ctxcatcodes,"[#",i,"]")
+ if not done then
+ opt = opt + 1
+ end
+ else
+ done = true -- no more optional checking after this
+ texsprint(ctxcatcodes,"#",i)
+ end
+ end
+ if environment then
+ texsprint(ctxcatcodes,"{\\ctxlua{mkiv.b('",name,"'")
+ else
+ texsprint(ctxcatcodes,"{\\ctxlua{mkiv.m('",name,"'")
+ end
+ for i=1,na do
+ local a = arguments[i]
+ local kind = a[2]
+ if kind == "list" then
+ texsprint(ctxcatcodes,",mkiv.a([[#",i,"]])")
+ elseif kind == "hash" then
+ texsprint(ctxcatcodes,",mkiv.h([[#",i,"]])")
+ elseif kind == "number" then
+ texsprint(ctxcatcodes,",mkiv.n([[#",i,"]])")
+ else
+ texsprint(ctxcatcodes,",[[#",i,"]]")
+ end
+ end
+ texsprint(ctxcatcodes,")}}")
+ if environment then
+ texsprint(ctxcatcodes,"\\defmkivstop{" ,name,"}{\\ctxlua{mkiv.e('",name,"')}}")
+ texsprint(ctxcatcodes,"\\defmkivstart{",name,"}{",checkers[opt],mkivdo,"}")
+ else
+ texsprint(ctxcatcodes,"\\defmkiv{", name,"}{",checkers[opt],mkivdo,"}")
+ end
+ end
+ if environment then
+ starters[name] = specification.starter
+ stoppers[name] = specification.stopper
+ else
+ macros[name] = specification.macro
+ end
+ end
+end
+
+function mkiv.tolist(t)
+ local r = { }
+ for i=1,#t do
+ r[i] = t[i]
+ end
+ for k,v in table.sortedhash(t) do
+ if type(k) ~= "number" then
+ r[#r+1] = k .. "=" .. v
+ end
+ end
+ return concat(r,", ")
+end
+
+--~ \startluacode
+--~ function test(opt_1, opt_2, arg_1)
+--~ context.startnarrower()
+--~ context("options 1: %s",mkiv.tolist(opt_1))
+--~ context.par()
+--~ context("options 2: %s",mkiv.tolist(opt_2))
+--~ context.par()
+--~ context("argument 1: %s",arg_1)
+--~ context.stopnarrower()
+--~ end
+
+--~ mkiv.define {
+--~ name = "test",
+--~ arguments = {
+--~ { "option", "list" },
+--~ { "option", "hash" },
+--~ { "content", "string" },
+--~ },
+--~ macro = test,
+--~ }
+--~ \stopluacode
+
+--~ test: \test[1][a=3]{whatever}
+
+--~ \startluacode
+--~ local function startmore(opt_1)
+--~ context.startnarrower()
+--~ context("start more, options: %s",mkiv.tolist(opt_1))
+--~ context.startnarrower()
+--~ end
+
+--~ local function stopmore(opt_1)
+--~ context.stopnarrower()
+--~ context("stop more, options: %s",mkiv.tolist(opt_1))
+--~ context.stopnarrower()
+--~ end
+
+--~ mkiv.define ( "more", {
+--~ environment = true,
+--~ arguments = {
+--~ { "option", "list" },
+--~ },
+--~ starter = startmore,
+--~ stopper = stopmore,
+--~ } )
+--~ \stopluacode
+
+--~ more: \startmore[1] one \startmore[2] two \stopmore one \stopmore
diff --git a/tex/context/base/mult-com.tex b/tex/context/base/mult-com.tex
new file mode 100644
index 000000000..118616837
--- /dev/null
+++ b/tex/context/base/mult-com.tex
@@ -0,0 +1,31 @@
+%D \module
+%D [ file=mult-com,
+%D version=1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Commands,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D This file has been replaced by \type {mult-def.lua} from which we
+%D generate separate interface definition files.
+
+% obsolete:
+%
+% \startcommands dutch english
+% german czech
+% italian romanian
+% french
+%
+% language: taal language
+% sprache jazyk
+% lingua limba
+% langue
+%
+% \stopcommands
+
+\endinput
diff --git a/tex/context/base/mult-con.tex b/tex/context/base/mult-con.tex
new file mode 100644
index 000000000..62e97d567
--- /dev/null
+++ b/tex/context/base/mult-con.tex
@@ -0,0 +1,53 @@
+%D \module
+%D [ file=mult-con,
+%D version=2000.09.12,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Constants,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This file has been replaced by \type {mult-def.lua} from which we
+%D generate separate interface definition files.
+
+% obsolete:
+%
+%
+% \startvariables dutch english
+% german czech
+% italian romanian
+% french
+%
+% one: een one
+% eins jedna
+% uno unu
+% un
+% \stopvariables
+%
+% \startconstants dutch english
+% german czech
+% italian romanian
+% french
+%
+% sorttype: sortering sorttype
+% sorttype sorttype
+% sorttype sorttype
+% sorttype
+% \stopconstants
+%
+% \startelements dutch english
+% german czech
+% italian romanian
+% french
+%
+% begin: beginvan begin
+% anfang zacatek
+% inizio inceput
+% debut
+% \stopelements
+
+\endinput
diff --git a/tex/context/base/mult-de.tex b/tex/context/base/mult-de.tex
new file mode 100644
index 000000000..f6f4f3bf9
--- /dev/null
+++ b/tex/context/base/mult-de.tex
@@ -0,0 +1,1693 @@
+% this file is auto-generated, don't edit this file
+%
+% definitions for interface variables for language de
+%
+\setinterfacevariable{Addition}{Zusatz}
+\setinterfacevariable{Balloon}{Ballon}
+\setinterfacevariable{Character}{Buchstabe}
+\setinterfacevariable{Characters}{Buchstaben}
+\setinterfacevariable{CloseDocument}{SchliesseDokument}
+\setinterfacevariable{ExitViewer}{BeendeViewer}
+\setinterfacevariable{FirstPage}{ErsteSeite}
+\setinterfacevariable{FitHeight}{HoehePassend}
+\setinterfacevariable{FitWidth}{BreitePassend}
+\setinterfacevariable{GotoPage}{GotoPage}
+\setinterfacevariable{Greek}{Griechisch}
+\setinterfacevariable{Help}{Hilfe}
+\setinterfacevariable{HideField}{VerbergeFeld}
+\setinterfacevariable{HideLayer}{HideLayer}
+\setinterfacevariable{Key}{Schluessel}
+\setinterfacevariable{LastPage}{LetzteSeite}
+\setinterfacevariable{LoadForm}{LadeFormular}
+\setinterfacevariable{MONTH}{MONAT}
+\setinterfacevariable{New}{Neu}
+\setinterfacevariable{NextJump}{NaechsterSprung}
+\setinterfacevariable{NextPage}{FolgendeSeite}
+\setinterfacevariable{Numbers}{Ziffern}
+\setinterfacevariable{OpenNamedDocument}{OpenNamedDocument}
+\setinterfacevariable{Paragraph}{Absatz}
+\setinterfacevariable{PauseMovie}{PauseFilm}
+\setinterfacevariable{PauseRendering}{PauseRendering}
+\setinterfacevariable{PauseSound}{PauseSound}
+\setinterfacevariable{PreviousJump}{VorigerSprung}
+\setinterfacevariable{PreviousPage}{VorigeSeite}
+\setinterfacevariable{PrintDocument}{DruckeDokument}
+\setinterfacevariable{Query}{Query}
+\setinterfacevariable{QueryAgain}{QueryAgain}
+\setinterfacevariable{ResetForm}{ZuruecksetzenFormular}
+\setinterfacevariable{ResumeMovie}{FortsetzenFilm}
+\setinterfacevariable{ResumeRendering}{ResumeRendering}
+\setinterfacevariable{ResumeSound}{ResumeSound}
+\setinterfacevariable{Romannumerals}{Roemischezahlen}
+\setinterfacevariable{SaveDocument}{SpeichereDokument}
+\setinterfacevariable{SaveForm}{SpeicheFormular}
+\setinterfacevariable{SaveNamedDocument}{SaveNamedDocument}
+\setinterfacevariable{SearchAgain}{WeiterSuchen}
+\setinterfacevariable{SearchDocument}{DokumentDurchsuchen}
+\setinterfacevariable{ShowBookmarks}{ShowBookmarks}
+\setinterfacevariable{ShowField}{ZeigeFeld}
+\setinterfacevariable{ShowThumbs}{ShowThumbs}
+\setinterfacevariable{StartMovie}{StartFilm}
+\setinterfacevariable{StartRendering}{StartRendering}
+\setinterfacevariable{StartSound}{StartSound}
+\setinterfacevariable{StopMovie}{StopFilm}
+\setinterfacevariable{StopRendering}{StopRendering}
+\setinterfacevariable{StopSound}{StopSound}
+\setinterfacevariable{SubmitForm}{VersendeFormular}
+\setinterfacevariable{ToggleLayer}{ToggleLayer}
+\setinterfacevariable{ToggleViewer}{WechseleViewer}
+\setinterfacevariable{URL}{URL}
+\setinterfacevariable{VideLayer}{VideLayer}
+\setinterfacevariable{ViewerHelp}{ViewerHilfe}
+\setinterfacevariable{WEEKDAY}{WOCHENTAG}
+\setinterfacevariable{WORD}{WORT}
+\setinterfacevariable{abbreviation}{abkuerzung}
+\setinterfacevariable{abbreviations}{abkuerzungen}
+\setinterfacevariable{absolute}{absolut}
+\setinterfacevariable{action}{aktion}
+\setinterfacevariable{after}{nach}
+\setinterfacevariable{all}{alles}
+\setinterfacevariable{always}{immer}
+\setinterfacevariable{answerarea}{answerarea}
+\setinterfacevariable{appendices}{anhaenge}
+\setinterfacevariable{appendix}{anhang}
+\setinterfacevariable{april}{April}
+\setinterfacevariable{atmargin}{amrand}
+\setinterfacevariable{atpage}{aufseite}
+\setinterfacevariable{august}{August}
+\setinterfacevariable{author}{autor}
+\setinterfacevariable{auto}{auto}
+\setinterfacevariable{autointro}{autointro}
+\setinterfacevariable{back}{zurueck}
+\setinterfacevariable{background}{hintergrund}
+\setinterfacevariable{backmatter}{epiloge}
+\setinterfacevariable{backpart}{epilog}
+\setinterfacevariable{backspace}{rumpfspatium}
+\setinterfacevariable{backward}{rueckwaerts}
+\setinterfacevariable{bbl}{bbl}
+\setinterfacevariable{before}{vor}
+\setinterfacevariable{begin}{begin}
+\setinterfacevariable{bib}{bib}
+\setinterfacevariable{big}{gross}
+\setinterfacevariable{bigbodyfont}{bigbodyfont}
+\setinterfacevariable{bigpreference}{grosszuegig}
+\setinterfacevariable{blank}{blanko}
+\setinterfacevariable{blockquote}{blockquote}
+\setinterfacevariable{bodymatter}{haupttexte}
+\setinterfacevariable{bodypart}{haupttext}
+\setinterfacevariable{bold}{fett}
+\setinterfacevariable{bolditalic}{fettitalic}
+\setinterfacevariable{boldslanted}{fettgeneigt}
+\setinterfacevariable{bookmark}{bookmark}
+\setinterfacevariable{both}{beide}
+\setinterfacevariable{bottom}{unten}
+\setinterfacevariable{brief}{brief}
+\setinterfacevariable{broad}{breit}
+\setinterfacevariable{buffer}{puffer}
+\setinterfacevariable{by}{pro}
+\setinterfacevariable{calligraphic}{kalligraphie}
+\setinterfacevariable{cap}{kap}
+\setinterfacevariable{capital}{versalien}
+\setinterfacevariable{center}{center}
+\setinterfacevariable{chapter}{kapitel}
+\setinterfacevariable{character}{buchstabe}
+\setinterfacevariable{characters}{buchstaben}
+\setinterfacevariable{cite}{cite}
+\setinterfacevariable{color}{farbe}
+\setinterfacevariable{column}{column}
+\setinterfacevariable{columns}{spalten}
+\setinterfacevariable{command}{befehl}
+\setinterfacevariable{commands}{befehle}
+\setinterfacevariable{comment}{kommentar}
+\setinterfacevariable{component}{komponente}
+\setinterfacevariable{concept}{konzept}
+\setinterfacevariable{content}{inhalt}
+\setinterfacevariable{contents}{inhalte}
+\setinterfacevariable{continue}{fortsetzten}
+\setinterfacevariable{controls}{controls}
+\setinterfacevariable{conversion}{konversion}
+\setinterfacevariable{current}{aktuell}
+\setinterfacevariable{cutspace}{cutspace}
+\setinterfacevariable{date}{datum}
+\setinterfacevariable{day}{tag}
+\setinterfacevariable{december}{Dezember}
+\setinterfacevariable{default}{default}
+\setinterfacevariable{depth}{tiefe}
+\setinterfacevariable{description}{beschreibung}
+\setinterfacevariable{disable}{sperren}
+\setinterfacevariable{display}{bildschirm}
+\setinterfacevariable{dot}{punkt}
+\setinterfacevariable{doublesided}{doppelseitig}
+\setinterfacevariable{down}{down}
+\setinterfacevariable{each}{jede}
+\setinterfacevariable{edge}{kante}
+\setinterfacevariable{empty}{leer}
+\setinterfacevariable{end}{end}
+\setinterfacevariable{endnote}{endnote}
+\setinterfacevariable{enumeration}{nummerierung}
+\setinterfacevariable{environment}{umgebung}
+\setinterfacevariable{even}{gerade}
+\setinterfacevariable{external}{extern}
+\setinterfacevariable{fact}{gegeben}
+\setinterfacevariable{february}{Februar}
+\setinterfacevariable{figure}{abbildung}
+\setinterfacevariable{figures}{abbildungen}
+\setinterfacevariable{file}{datei}
+\setinterfacevariable{final}{endfassung}
+\setinterfacevariable{first}{erste}
+\setinterfacevariable{firstcolumn}{firstcolumn}
+\setinterfacevariable{firstpage}{ersteseite}
+\setinterfacevariable{firstsubpage}{ersteunterseite}
+\setinterfacevariable{fit}{passend}
+\setinterfacevariable{five}{fuenf}
+\setinterfacevariable{fix}{stellewiederher}
+\setinterfacevariable{fixed}{fest}
+\setinterfacevariable{flexible}{flexibel}
+\setinterfacevariable{float}{gleitobjekt}
+\setinterfacevariable{flushinner}{flushinner}
+\setinterfacevariable{flushleft}{flushleft}
+\setinterfacevariable{flushouter}{flushouter}
+\setinterfacevariable{flushright}{flushright}
+\setinterfacevariable{footer}{fusszeile}
+\setinterfacevariable{footnote}{fussnote}
+\setinterfacevariable{force}{zwinge}
+\setinterfacevariable{foreground}{vordergrund}
+\setinterfacevariable{formeel}{formeel}
+\setinterfacevariable{formula}{formel}
+\setinterfacevariable{formulae}{formeln}
+\setinterfacevariable{forward}{vorwaerts}
+\setinterfacevariable{four}{vier}
+\setinterfacevariable{frame}{rahmen}
+\setinterfacevariable{framedtext}{umrahmtertext}
+\setinterfacevariable{friday}{freitag}
+\setinterfacevariable{frontmatter}{einleitungen}
+\setinterfacevariable{frontpart}{einleitung}
+\setinterfacevariable{global}{global}
+\setinterfacevariable{graphic}{grafik}
+\setinterfacevariable{graphics}{grafiken}
+\setinterfacevariable{gray}{grau}
+\setinterfacevariable{greek}{griechisch}
+\setinterfacevariable{grid}{gritter}
+\setinterfacevariable{halfline}{halbezeile}
+\setinterfacevariable{handwritten}{handschrift}
+\setinterfacevariable{hang}{haengend}
+\setinterfacevariable{hanging}{haengend}
+\setinterfacevariable{head}{kopf}
+\setinterfacevariable{header}{kopfzeile}
+\setinterfacevariable{height}{hoehe}
+\setinterfacevariable{helptext}{hilfetext}
+\setinterfacevariable{hencefore}{vorher}
+\setinterfacevariable{here}{hier}
+\setinterfacevariable{hereafter}{nachher}
+\setinterfacevariable{hidden}{versteckt}
+\setinterfacevariable{hiding}{verbergen}
+\setinterfacevariable{high}{hoch}
+\setinterfacevariable{horizontal}{horizontal}
+\setinterfacevariable{hyphenated}{hyphenate}
+\setinterfacevariable{hz}{hz}
+\setinterfacevariable{inbetween}{zwischen}
+\setinterfacevariable{index}{index}
+\setinterfacevariable{indices}{indizies}
+\setinterfacevariable{informeel}{informeel}
+\setinterfacevariable{inherit}{inherit}
+\setinterfacevariable{inleft}{imlinken}
+\setinterfacevariable{inmargin}{imrand}
+\setinterfacevariable{inner}{innen}
+\setinterfacevariable{inneredge}{inneredge}
+\setinterfacevariable{innermargin}{innermargin}
+\setinterfacevariable{inright}{imrechten}
+\setinterfacevariable{interaction}{interaktion}
+\setinterfacevariable{interactionmenu}{interaktionsmenue}
+\setinterfacevariable{intermezzi}{intermezzi}
+\setinterfacevariable{intermezzo}{intermezzo}
+\setinterfacevariable{intext}{imtext}
+\setinterfacevariable{intro}{intro}
+\setinterfacevariable{italic}{italic}
+\setinterfacevariable{italicbold}{italicfett}
+\setinterfacevariable{item}{pos}
+\setinterfacevariable{itemize}{aufzaehlung}
+\setinterfacevariable{its}{its}
+\setinterfacevariable{january}{Januar}
+\setinterfacevariable{joinedup}{keinabstand}
+\setinterfacevariable{july}{Juli}
+\setinterfacevariable{june}{Juni}
+\setinterfacevariable{keep}{behalte}
+\setinterfacevariable{knockout}{knockout}
+\setinterfacevariable{label}{label}
+\setinterfacevariable{landscape}{querformat}
+\setinterfacevariable{last}{letzte}
+\setinterfacevariable{lastcolumn}{lastcolumn}
+\setinterfacevariable{lastpage}{letzteseite}
+\setinterfacevariable{lastpagenumber}{lastpagenumber}
+\setinterfacevariable{lastsubpage}{letzteunterseite}
+\setinterfacevariable{layer}{layer}
+\setinterfacevariable{left}{links}
+\setinterfacevariable{leftedge}{linkekante}
+\setinterfacevariable{lefthanging}{lefthanging}
+\setinterfacevariable{leftmargin}{linkerrand}
+\setinterfacevariable{leftpage}{linkerseite}
+\setinterfacevariable{lefttoright}{lefttoright}
+\setinterfacevariable{legend}{legende}
+\setinterfacevariable{lesshyphenation}{lesshyphenation}
+\setinterfacevariable{line}{zeile}
+\setinterfacevariable{linenote}{linenote}
+\setinterfacevariable{lines}{zeilen}
+\setinterfacevariable{list}{liste}
+\setinterfacevariable{local}{lokal}
+\setinterfacevariable{localenvironment}{lokaleumgebung}
+\setinterfacevariable{logo}{logo}
+\setinterfacevariable{logos}{logos}
+\setinterfacevariable{lohi}{hoti}
+\setinterfacevariable{loose}{lose}
+\setinterfacevariable{low}{tief}
+\setinterfacevariable{ls}{ls}
+\setinterfacevariable{makeup}{umbruch}
+\setinterfacevariable{mar}{mar}
+\setinterfacevariable{march}{Maerz}
+\setinterfacevariable{margin}{marginalie}
+\setinterfacevariable{marginedge}{marginalkante}
+\setinterfacevariable{margintitle}{marginaltitel}
+\setinterfacevariable{marking}{beschriftung}
+\setinterfacevariable{mathalignment}{mathalignment}
+\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathmatrix}{mathmatrix}
+\setinterfacevariable{max}{max}
+\setinterfacevariable{maxdepth}{maxdepth}
+\setinterfacevariable{maxheight}{maxheight}
+\setinterfacevariable{maxwidth}{maxwidth}
+\setinterfacevariable{may}{Mai}
+\setinterfacevariable{mediaeval}{mittelalterlich}
+\setinterfacevariable{medium}{mittel}
+\setinterfacevariable{middle}{mittig}
+\setinterfacevariable{min}{min}
+\setinterfacevariable{mindepth}{mindepth}
+\setinterfacevariable{minheight}{minhoehe}
+\setinterfacevariable{minwidth}{minbreite}
+\setinterfacevariable{mirrored}{gespiegelt}
+\setinterfacevariable{monday}{montag}
+\setinterfacevariable{mono}{mono}
+\setinterfacevariable{month}{monat}
+\setinterfacevariable{morehyphenation}{morehyphenation}
+\setinterfacevariable{name}{name}
+\setinterfacevariable{narrow}{schmall}
+\setinterfacevariable{negative}{negativ}
+\setinterfacevariable{never}{nie}
+\setinterfacevariable{new}{neu}
+\setinterfacevariable{next}{folgende}
+\setinterfacevariable{nextevenpage}{naechstegeradeseite}
+\setinterfacevariable{nextoddpage}{naechsteungeradeseite}
+\setinterfacevariable{nextpage}{folgendeseite}
+\setinterfacevariable{nextsubpage}{folgendeunterseite}
+\setinterfacevariable{no}{nein}
+\setinterfacevariable{nocheck}{nocheck}
+\setinterfacevariable{nofit}{nofit}
+\setinterfacevariable{nogrid}{nogrid}
+\setinterfacevariable{nohz}{nohz}
+\setinterfacevariable{nomarking}{keinebeschriftung}
+\setinterfacevariable{none}{kein}
+\setinterfacevariable{nonumber}{nonumber}
+\setinterfacevariable{normal}{normal}
+\setinterfacevariable{nospacing}{nospacing}
+\setinterfacevariable{not}{nicht}
+\setinterfacevariable{note}{note}
+\setinterfacevariable{nothanging}{nothanging}
+\setinterfacevariable{nothyphenated}{nothyphenated}
+\setinterfacevariable{november}{November}
+\setinterfacevariable{nowhere}{nirgens}
+\setinterfacevariable{nowhite}{keinweiss}
+\setinterfacevariable{number}{nummer}
+\setinterfacevariable{numbers}{ziffern}
+\setinterfacevariable{october}{Oktober}
+\setinterfacevariable{odd}{ungerade}
+\setinterfacevariable{off}{aus}
+\setinterfacevariable{offset}{offset}
+\setinterfacevariable{old}{old}
+\setinterfacevariable{on}{an}
+\setinterfacevariable{one}{eins}
+\setinterfacevariable{opposite}{gegenueber}
+\setinterfacevariable{outer}{aussen}
+\setinterfacevariable{outeredge}{outeredge}
+\setinterfacevariable{outermargin}{outermargin}
+\setinterfacevariable{overbar}{ueberstrichen}
+\setinterfacevariable{overbars}{ueberstreichen}
+\setinterfacevariable{overlay}{overlay}
+\setinterfacevariable{overprint}{overprint}
+\setinterfacevariable{overstrike}{durchgestrichen}
+\setinterfacevariable{overstrikes}{durchstreichen}
+\setinterfacevariable{packed}{gepackt}
+\setinterfacevariable{page}{seite}
+\setinterfacevariable{pagecomment}{pagecomment}
+\setinterfacevariable{pagenumber}{seitennummer}
+\setinterfacevariable{paper}{papier}
+\setinterfacevariable{paragraph}{absatz}
+\setinterfacevariable{part}{teil}
+\setinterfacevariable{positive}{positiv}
+\setinterfacevariable{postponing}{verschieben}
+\setinterfacevariable{postscript}{postscript}
+\setinterfacevariable{preference}{einstellung}
+\setinterfacevariable{preview}{vorschau}
+\setinterfacevariable{previous}{vorig}
+\setinterfacevariable{previousevenpage}{vorigegeradeseite}
+\setinterfacevariable{previousoddpage}{vorigeungeradeseite}
+\setinterfacevariable{previouspage}{vorigeseite}
+\setinterfacevariable{previoussubpage}{vorigeunterseite}
+\setinterfacevariable{printable}{druckbar}
+\setinterfacevariable{process}{process}
+\setinterfacevariable{product}{produkt}
+\setinterfacevariable{program}{programm}
+\setinterfacevariable{project}{projekt}
+\setinterfacevariable{protected}{geschuetzt}
+\setinterfacevariable{quadruple}{viertel}
+\setinterfacevariable{quotation}{zitat}
+\setinterfacevariable{quote}{zitieren}
+\setinterfacevariable{ran}{ran}
+\setinterfacevariable{random}{zufaellig}
+\setinterfacevariable{readonly}{nurlesbar}
+\setinterfacevariable{rectangular}{rechteckig}
+\setinterfacevariable{referral}{merkmal}
+\setinterfacevariable{register}{register}
+\setinterfacevariable{regular}{regular}
+\setinterfacevariable{rekening}{rekening}
+\setinterfacevariable{relative}{relativ}
+\setinterfacevariable{repeat}{wiederholen}
+\setinterfacevariable{required}{obligatorisch}
+\setinterfacevariable{reset}{zuruecksetzten}
+\setinterfacevariable{reverse}{reverse}
+\setinterfacevariable{right}{rechts}
+\setinterfacevariable{rightedge}{rechterkante}
+\setinterfacevariable{righthanging}{righthanging}
+\setinterfacevariable{rightmargin}{rechterrand}
+\setinterfacevariable{rightpage}{rechterseite}
+\setinterfacevariable{righttoleft}{righttoleft}
+\setinterfacevariable{roman}{antiqua}
+\setinterfacevariable{romannumerals}{roemischezahlen}
+\setinterfacevariable{rotate}{drehe}
+\setinterfacevariable{rotated}{gedreht}
+\setinterfacevariable{round}{rund}
+\setinterfacevariable{row}{row}
+\setinterfacevariable{rule}{linie}
+\setinterfacevariable{samepage}{selbeseite}
+\setinterfacevariable{sans}{sans}
+\setinterfacevariable{sansbold}{sansfett}
+\setinterfacevariable{sansserif}{grotesk}
+\setinterfacevariable{saturday}{samstag}
+\setinterfacevariable{screen}{raster}
+\setinterfacevariable{section}{absatz}
+\setinterfacevariable{sectionblockenvironment}{sectionblockenvironment}
+\setinterfacevariable{sectionnumber}{abschnittsnummer}
+\setinterfacevariable{see}{sieh}
+\setinterfacevariable{september}{September}
+\setinterfacevariable{serif}{serif}
+\setinterfacevariable{serried}{kleinerabstand}
+\setinterfacevariable{setups}{impostazioni}
+\setinterfacevariable{sheet}{sheet}
+\setinterfacevariable{short}{kurz}
+\setinterfacevariable{singlesided}{einzelseitig}
+\setinterfacevariable{slanted}{geneigt}
+\setinterfacevariable{slantedbold}{geneigtfett}
+\setinterfacevariable{small}{klein}
+\setinterfacevariable{smallbodyfont}{smallbodyfont}
+\setinterfacevariable{smallbold}{kleinfett}
+\setinterfacevariable{smallbolditalic}{kleinfettitalic}
+\setinterfacevariable{smallboldslanted}{kleinfettgeneigt}
+\setinterfacevariable{smallcaps}{smallcaps}
+\setinterfacevariable{smallitalic}{kleinitalic}
+\setinterfacevariable{smallitalicbold}{kleinitalicfett}
+\setinterfacevariable{smallnormal}{kleinnormal}
+\setinterfacevariable{smallslanted}{kleingeneigt}
+\setinterfacevariable{smallslantedbold}{kleingeneigtfett}
+\setinterfacevariable{smalltype}{kleintippen}
+\setinterfacevariable{somewhere}{irgendwo}
+\setinterfacevariable{sorted}{sortiert}
+\setinterfacevariable{space}{spatium}
+\setinterfacevariable{spacing}{spatiumausgleich}
+\setinterfacevariable{speech}{speech}
+\setinterfacevariable{split}{split}
+\setinterfacevariable{spot}{spot}
+\setinterfacevariable{standard}{standard}
+\setinterfacevariable{start}{start}
+\setinterfacevariable{starter}{starter}
+\setinterfacevariable{sticker}{sticker}
+\setinterfacevariable{stop}{stop}
+\setinterfacevariable{stopper}{trenner}
+\setinterfacevariable{stretch}{strecken}
+\setinterfacevariable{strict}{streng}
+\setinterfacevariable{strong}{strong}
+\setinterfacevariable{strut}{strut}
+\setinterfacevariable{sub}{unter}
+\setinterfacevariable{subbackward}{unterrueckwaerts}
+\setinterfacevariable{subformula}{subformel}
+\setinterfacevariable{subforward}{untervorwaerts}
+\setinterfacevariable{subject}{thema}
+\setinterfacevariable{subpage}{unterseite}
+\setinterfacevariable{subsection}{unterabsatz}
+\setinterfacevariable{subsubject}{unterthema}
+\setinterfacevariable{subsubsection}{unterunterabsatz}
+\setinterfacevariable{subsubsubject}{unterunterthema}
+\setinterfacevariable{subsubsubsection}{unterunterunterabsatz}
+\setinterfacevariable{subsubsubsubject}{unterunterunterthema}
+\setinterfacevariable{subsubsubsubsection}{unterunterunterunterabsatz}
+\setinterfacevariable{subsubsubsubsubject}{unterunterunterunterthema}
+\setinterfacevariable{subsubsubsubsubsection}{unterunterunterunterunterabsatz}
+\setinterfacevariable{subsubsubsubsubsubject}{unterunterunterunterunterthema}
+\setinterfacevariable{subsubsubsubsubsubsection}{unterunterunterunterunterunterabsatz}
+\setinterfacevariable{subsubsubsubsubsubsubject}{unterunterunterunterunterunterthema}
+\setinterfacevariable{subsubsubsubsubsubsubsection}{unterunterunterunterunterunterunterabsatz}
+\setinterfacevariable{subsubsubsubsubsubsubsubject}{unterunterunterunterunterunterunterthema}
+\setinterfacevariable{subsubsubsubsubsubsubsubsection}{unterunterunterunterunterunterunterunterabsatz}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubject}{unterunterunterunterunterunterunterunterthema}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsection}{unterunterunterunterunterunterunterunterunterabsatz}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsubject}{unterunterunterunterunterunterunterunterunterthema}
+\setinterfacevariable{sunday}{sonntag}
+\setinterfacevariable{support}{support}
+\setinterfacevariable{sym}{sym}
+\setinterfacevariable{symbol}{symbol}
+\setinterfacevariable{synchronize}{synchronize}
+\setinterfacevariable{system}{systeme}
+\setinterfacevariable{table}{tabelle}
+\setinterfacevariable{tablehead}{tabellenueberschrift}
+\setinterfacevariable{tables}{tabellen}
+\setinterfacevariable{tabletail}{tabellenende}
+\setinterfacevariable{tabulate}{tabulator}
+\setinterfacevariable{tabulatehead}{tabulatehead}
+\setinterfacevariable{tabulatetail}{tabulatetail}
+\setinterfacevariable{tall}{lang}
+\setinterfacevariable{teletype}{fernschreiber}
+\setinterfacevariable{temporary}{temporaer}
+\setinterfacevariable{test}{test}
+\setinterfacevariable{text}{text}
+\setinterfacevariable{three}{drei}
+\setinterfacevariable{thursday}{donnerstag}
+\setinterfacevariable{title}{titel}
+\setinterfacevariable{toggle}{toggle}
+\setinterfacevariable{tolerant}{tolerant}
+\setinterfacevariable{top}{oben}
+\setinterfacevariable{tuesday}{dienstag}
+\setinterfacevariable{two}{zwei}
+\setinterfacevariable{txt}{txt}
+\setinterfacevariable{type}{tippen}
+\setinterfacevariable{typing}{tippen}
+\setinterfacevariable{unavailable}{nichtverfuegbar}
+\setinterfacevariable{underbar}{unterstrichen}
+\setinterfacevariable{underbars}{unterstreichen}
+\setinterfacevariable{unit}{einheit}
+\setinterfacevariable{units}{einheiten}
+\setinterfacevariable{unknown}{unbekannt}
+\setinterfacevariable{unpacked}{ungepackt}
+\setinterfacevariable{up}{up}
+\setinterfacevariable{url}{url}
+\setinterfacevariable{used}{verwende}
+\setinterfacevariable{value}{wert}
+\setinterfacevariable{vertical}{vertikal}
+\setinterfacevariable{very}{sehr}
+\setinterfacevariable{verystrict}{sehrstreng}
+\setinterfacevariable{verytolerant}{sehrtolerant}
+\setinterfacevariable{weak}{weak}
+\setinterfacevariable{wednesday}{mittwoch}
+\setinterfacevariable{week}{woche}
+\setinterfacevariable{weekday}{wochentag}
+\setinterfacevariable{white}{weiss}
+\setinterfacevariable{wide}{breit}
+\setinterfacevariable{width}{breite}
+\setinterfacevariable{xml}{xml}
+\setinterfacevariable{year}{jahr}
+\setinterfacevariable{yes}{ja}
+% definitions for interface constants for language de
+%
+\setinterfaceconstant{action}{aktion}
+\setinterfaceconstant{address}{adresse}
+\setinterfaceconstant{after}{nach}
+\setinterfaceconstant{afterhead}{nachkopf}
+\setinterfaceconstant{afterkey}{nachtaste}
+\setinterfaceconstant{align}{ausrichtung}
+\setinterfaceconstant{aligncharacter}{aligncharacter}
+\setinterfaceconstant{alignmentcharacter}{alignmentcharacter}
+\setinterfaceconstant{alignsymbol}{alignsymbol}
+\setinterfaceconstant{aligntitle}{titelausrichten}
+\setinterfaceconstant{alternative}{alternative}
+\setinterfaceconstant{andtext}{andtext}
+\setinterfaceconstant{apa}{apa}
+\setinterfaceconstant{arrow}{pfeil}
+\setinterfaceconstant{artauthor}{artauthor}
+\setinterfaceconstant{artauthoretaldisplay}{artauthoretaldisplay}
+\setinterfaceconstant{artauthoretallimit}{artauthoretallimit}
+\setinterfaceconstant{artauthoretaltext}{artauthoretaltext}
+\setinterfaceconstant{at}{bei}
+\setinterfaceconstant{author}{autor}
+\setinterfaceconstant{authoretaldisplay}{authoretaldisplay}
+\setinterfaceconstant{authoretallimit}{authoretallimit}
+\setinterfaceconstant{authoretaltext}{authoretaltext}
+\setinterfaceconstant{auto}{auto}
+\setinterfaceconstant{autofile}{autofile}
+\setinterfaceconstant{autofocus}{autofocus}
+\setinterfaceconstant{autohang}{autohang}
+\setinterfaceconstant{autostrut}{autostrut}
+\setinterfaceconstant{autowidth}{autobreite}
+\setinterfaceconstant{axis}{achsen}
+\setinterfaceconstant{background}{hintergrund}
+\setinterfaceconstant{backgroundcolor}{hintergrundfarbe}
+\setinterfaceconstant{backgroundcorner}{hintergrundwinkel}
+\setinterfaceconstant{backgrounddepth}{hintergrundtiefe}
+\setinterfaceconstant{backgroundoffset}{hintergrundoffset}
+\setinterfaceconstant{backgroundradius}{hintergrundradius}
+\setinterfaceconstant{backgroundscreen}{hintergrundraster}
+\setinterfaceconstant{backspace}{rumpfspatium}
+\setinterfaceconstant{balance}{ausgleichen}
+\setinterfaceconstant{before}{vor}
+\setinterfaceconstant{beforehead}{vorkopf}
+\setinterfaceconstant{bet}{bet}
+\setinterfaceconstant{big}{gross}
+\setinterfaceconstant{blank}{blanko}
+\setinterfaceconstant{blockway}{blockauf}
+\setinterfaceconstant{bodyfont}{fliesstext}
+\setinterfaceconstant{bookmark}{bookmark}
+\setinterfaceconstant{bottom}{unten}
+\setinterfaceconstant{bottomafter}{bottomafter}
+\setinterfaceconstant{bottombefore}{bottombefore}
+\setinterfaceconstant{bottomdistance}{abstandunten}
+\setinterfaceconstant{bottomframe}{untenrahmen}
+\setinterfaceconstant{bottomoffset}{untenoffset}
+\setinterfaceconstant{bottomspace}{bottomspace}
+\setinterfaceconstant{bottomstate}{untenstatus}
+\setinterfaceconstant{cache}{cache}
+\setinterfaceconstant{calculate}{berechnen}
+\setinterfaceconstant{ccommand}{cbefehl}
+\setinterfaceconstant{click}{klick}
+\setinterfaceconstant{clickin}{klickin}
+\setinterfaceconstant{clickout}{klickaus}
+\setinterfaceconstant{clipoffset}{clipoffset}
+\setinterfaceconstant{closeaction}{schliessenaktion}
+\setinterfaceconstant{closecommand}{closecommand}
+\setinterfaceconstant{closepageaction}{closepageaction}
+\setinterfaceconstant{closesymbol}{closesymbol}
+\setinterfaceconstant{color}{farbe}
+\setinterfaceconstant{column}{spalte}
+\setinterfaceconstant{columndistance}{spaltenabstand}
+\setinterfaceconstant{columns}{spalten}
+\setinterfaceconstant{command}{befehl}
+\setinterfaceconstant{commandafter}{zumbefehl}
+\setinterfaceconstant{commandbefore}{vorbefehl}
+\setinterfaceconstant{commands}{befehle}
+\setinterfaceconstant{component}{component}
+\setinterfaceconstant{compoundhyphen}{compoundhyphen}
+\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{connector}{connector}
+\setinterfaceconstant{continue}{fortsetzen}
+\setinterfaceconstant{contrastcolor}{kontrastfarbe}
+\setinterfaceconstant{controls}{controls}
+\setinterfaceconstant{conversion}{konversion}
+\setinterfaceconstant{convertfile}{konvertieredatei}
+\setinterfaceconstant{corner}{winkel}
+\setinterfaceconstant{coupling}{verknuepfung}
+\setinterfaceconstant{couplingway}{verkopplungsart}
+\setinterfaceconstant{criterium}{kriterium}
+\setinterfaceconstant{current}{aktuell}
+\setinterfaceconstant{cutspace}{cutspace}
+\setinterfaceconstant{dash}{strich}
+\setinterfaceconstant{dat}{dat}
+\setinterfaceconstant{database}{database}
+\setinterfaceconstant{date}{datum}
+\setinterfaceconstant{deepnumbercommand}{deepnumbercommand}
+\setinterfaceconstant{deeptextcommand}{deeptextcommand}
+\setinterfaceconstant{default}{default}
+\setinterfaceconstant{delay}{wartezeit}
+\setinterfaceconstant{depth}{tiefe}
+\setinterfaceconstant{depthcorrection}{tiefekorrektur}
+\setinterfaceconstant{direction}{richtung}
+\setinterfaceconstant{directory}{verzeichnis}
+\setinterfaceconstant{display}{bildschirm}
+\setinterfaceconstant{distance}{abstand}
+\setinterfaceconstant{dot}{punkt}
+\setinterfaceconstant{doublesided}{doppelseitig}
+\setinterfaceconstant{dummy}{dummy}
+\setinterfaceconstant{dx}{dx}
+\setinterfaceconstant{dy}{dy}
+\setinterfaceconstant{edge}{kante}
+\setinterfaceconstant{edgedistance}{kantenabstand}
+\setinterfaceconstant{editor}{editor}
+\setinterfaceconstant{editoretaldisplay}{editoretaldisplay}
+\setinterfaceconstant{editoretallimit}{editoretallimit}
+\setinterfaceconstant{editoretaltext}{editoretaltext}
+\setinterfaceconstant{empty}{leer}
+\setinterfaceconstant{equalheight}{equalheight}
+\setinterfaceconstant{equalwidth}{equalwidth}
+\setinterfaceconstant{escape}{escape}
+\setinterfaceconstant{evenmargin}{geraderand}
+\setinterfaceconstant{expansion}{expansion}
+\setinterfaceconstant{export}{export}
+\setinterfaceconstant{extras}{extras}
+\setinterfaceconstant{factor}{faktor}
+\setinterfaceconstant{fallback}{fallback}
+\setinterfaceconstant{family}{familie}
+\setinterfaceconstant{fieldbackgroundcolor}{feldhintergrundfarbe}
+\setinterfaceconstant{fieldframecolor}{feldrahmenfarbe}
+\setinterfaceconstant{fieldlayer}{fieldlayer}
+\setinterfaceconstant{fieldoffset}{feldoffset}
+\setinterfaceconstant{file}{datei}
+\setinterfaceconstant{filtercommand}{filtercommand}
+\setinterfaceconstant{finalnamesep}{finalnamesep}
+\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{focus}{focus}
+\setinterfaceconstant{focusin}{focusin}
+\setinterfaceconstant{focusout}{focusout}
+\setinterfaceconstant{footer}{fusszeile}
+\setinterfaceconstant{footerdistance}{fusszeilenabstand}
+\setinterfaceconstant{footerstate}{fusszeilenstatus}
+\setinterfaceconstant{foregroundcolor}{foregroundcolor}
+\setinterfaceconstant{foregroundstyle}{foregroundstyle}
+\setinterfaceconstant{format}{formatieren}
+\setinterfaceconstant{frame}{rahmen}
+\setinterfaceconstant{framecolor}{rahmenfarbe}
+\setinterfaceconstant{framecorner}{rahmenwinkel}
+\setinterfaceconstant{framedepth}{rahmentiefe}
+\setinterfaceconstant{frameoffset}{rahmenoffset}
+\setinterfaceconstant{frameradius}{rahmenradius}
+\setinterfaceconstant{frames}{umrahmen}
+\setinterfaceconstant{from}{von}
+\setinterfaceconstant{get}{hole}
+\setinterfaceconstant{global}{global}
+\setinterfaceconstant{grid}{gritter}
+\setinterfaceconstant{hang}{haengend}
+\setinterfaceconstant{headalign}{headalign}
+\setinterfaceconstant{headcolor}{kopffarbe}
+\setinterfaceconstant{headcommand}{headcommand}
+\setinterfaceconstant{headconversion}{headconversion}
+\setinterfaceconstant{header}{kopfzeile}
+\setinterfaceconstant{headerdistance}{kopfzeilenabstand}
+\setinterfaceconstant{headerstate}{kopfzeilenstatus}
+\setinterfaceconstant{headlabel}{headlabel}
+\setinterfaceconstant{headnumber}{kopfnummer}
+\setinterfaceconstant{headstyle}{kopfstil}
+\setinterfaceconstant{height}{hoehe}
+\setinterfaceconstant{hfactor}{hfaktor}
+\setinterfaceconstant{hfil}{hfil}
+\setinterfaceconstant{hidenumber}{hidenumber}
+\setinterfaceconstant{hoffset}{hoffset}
+\setinterfaceconstant{horoffset}{rumpfabstand}
+\setinterfaceconstant{hyphen}{hyphen}
+\setinterfaceconstant{icommand}{ibefehl}
+\setinterfaceconstant{in}{in}
+\setinterfaceconstant{inbetween}{zwischen}
+\setinterfaceconstant{increment}{erhoehen}
+\setinterfaceconstant{incrementnumber}{nummererhoehen}
+\setinterfaceconstant{indenting}{einziehen}
+\setinterfaceconstant{indentnext}{ziehefolgendeein}
+\setinterfaceconstant{indicator}{indikator}
+\setinterfaceconstant{inner}{innen}
+\setinterfaceconstant{innermargin}{innermargin}
+\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{intent}{intent}
+\setinterfaceconstant{interaction}{interaktion}
+\setinterfaceconstant{interlinespace}{zeilenabstande}
+\setinterfaceconstant{itemalign}{itemalign}
+\setinterfaceconstant{items}{posten}
+\setinterfaceconstant{juniorsep}{juniorsep}
+\setinterfaceconstant{ken}{ken}
+\setinterfaceconstant{keyexpansion}{keyexpansion}
+\setinterfaceconstant{keyword}{keyword}
+\setinterfaceconstant{label}{label}
+\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{left}{links}
+\setinterfaceconstant{leftcolor}{linkerfarbe}
+\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
+\setinterfaceconstant{leftedge}{linkekante}
+\setinterfaceconstant{leftedgedistance}{linkerkantenabstand}
+\setinterfaceconstant{leftframe}{linkerrahmen}
+\setinterfaceconstant{lefthyphen}{lefthyphen}
+\setinterfaceconstant{leftmargin}{linkerrand}
+\setinterfaceconstant{leftmargindistance}{linkerrandabstand}
+\setinterfaceconstant{leftoffset}{linkeroffset}
+\setinterfaceconstant{leftquotation}{linkerzitat}
+\setinterfaceconstant{leftquote}{linkerzitieren}
+\setinterfaceconstant{leftsentence}{linkersatz}
+\setinterfaceconstant{leftspeech}{leftspeech}
+\setinterfaceconstant{leftstyle}{linkerstil}
+\setinterfaceconstant{leftsubsentence}{linkersubsatz}
+\setinterfaceconstant{lefttext}{linkertext}
+\setinterfaceconstant{leftwidth}{linkerbreite}
+\setinterfaceconstant{level}{niveau}
+\setinterfaceconstant{levels}{niveaus}
+\setinterfaceconstant{limittext}{limittext}
+\setinterfaceconstant{line}{zeile}
+\setinterfaceconstant{linecorrection}{zeilekorrektur}
+\setinterfaceconstant{lines}{zeilen}
+\setinterfaceconstant{list}{liste}
+\setinterfaceconstant{listtext}{listtext}
+\setinterfaceconstant{local}{lokal}
+\setinterfaceconstant{location}{platz}
+\setinterfaceconstant{logo}{logo}
+\setinterfaceconstant{logos}{logos}
+\setinterfaceconstant{marcolor}{beschrfarbe}
+\setinterfaceconstant{margin}{marginalie}
+\setinterfaceconstant{margindistance}{marginalabstand}
+\setinterfaceconstant{marginedge}{marginalkante}
+\setinterfaceconstant{marginedgetext}{marginalkantetext}
+\setinterfaceconstant{margintext}{marginaltext}
+\setinterfaceconstant{marking}{beschriftung}
+\setinterfaceconstant{marstyle}{beschrstil}
+\setinterfaceconstant{max}{max}
+\setinterfaceconstant{maxdepth}{maxdepth}
+\setinterfaceconstant{maxheight}{maxhoehe}
+\setinterfaceconstant{maxwidth}{maxbreite}
+\setinterfaceconstant{maybeyear}{maybeyear}
+\setinterfaceconstant{menu}{menue}
+\setinterfaceconstant{method}{methode}
+\setinterfaceconstant{middle}{mittig}
+\setinterfaceconstant{middlespeech}{middlespeech}
+\setinterfaceconstant{middletext}{mittigertext}
+\setinterfaceconstant{midsentence}{midsentence}
+\setinterfaceconstant{min}{min}
+\setinterfaceconstant{mindepth}{mindepth}
+\setinterfaceconstant{minheight}{minhoehe}
+\setinterfaceconstant{minwidth}{minbreite}
+\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{n}{n}
+\setinterfaceconstant{name}{name}
+\setinterfaceconstant{namesep}{namesep}
+\setinterfaceconstant{nbottom}{nunten}
+\setinterfaceconstant{nc}{nc}
+\setinterfaceconstant{next}{folgende}
+\setinterfaceconstant{nl}{nl}
+\setinterfaceconstant{nleft}{nlinks}
+\setinterfaceconstant{nlines}{zzeile}
+\setinterfaceconstant{norm}{norm}
+\setinterfaceconstant{nr}{nr}
+\setinterfaceconstant{nright}{nrechts}
+\setinterfaceconstant{ntop}{noben}
+\setinterfaceconstant{number}{nummer}
+\setinterfaceconstant{numbercolor}{nummernfarbe}
+\setinterfaceconstant{numbercommand}{nummerbefehl}
+\setinterfaceconstant{numberconversion}{numberconversion}
+\setinterfaceconstant{numberconversionset}{numberconversionset}
+\setinterfaceconstant{numberdistance}{numberdistance}
+\setinterfaceconstant{numbering}{nummerierung}
+\setinterfaceconstant{numberorder}{numberorder}
+\setinterfaceconstant{numberprefix}{numberprefix}
+\setinterfaceconstant{numbersegments}{numbersegments}
+\setinterfaceconstant{numberseparator}{nummernseperator}
+\setinterfaceconstant{numberseparatorset}{numberseparatorset}
+\setinterfaceconstant{numberset}{numberset}
+\setinterfaceconstant{numberstarter}{numberstarter}
+\setinterfaceconstant{numberstopper}{numberstopper}
+\setinterfaceconstant{numberstyle}{nummernstil}
+\setinterfaceconstant{numberwidth}{numberwidth}
+\setinterfaceconstant{nx}{nx}
+\setinterfaceconstant{ny}{ny}
+\setinterfaceconstant{object}{objekt}
+\setinterfaceconstant{obstruction}{gesperrt}
+\setinterfaceconstant{oddmargin}{ungeraderand}
+\setinterfaceconstant{offset}{offset}
+\setinterfaceconstant{openaction}{oeffenaktion}
+\setinterfaceconstant{openpageaction}{openpageaction}
+\setinterfaceconstant{option}{option}
+\setinterfaceconstant{order}{order}
+\setinterfaceconstant{orientation}{orientation}
+\setinterfaceconstant{otherstext}{otherstext}
+\setinterfaceconstant{outermargin}{outermargin}
+\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownnumber}{eigenenummer}
+\setinterfaceconstant{page}{seite}
+\setinterfaceconstant{pageboundaries}{seitenbegrenzung}
+\setinterfaceconstant{pagecolor}{seitenfarbe}
+\setinterfaceconstant{pagecommand}{seitenbefehl}
+\setinterfaceconstant{pageconversion}{pageconversion}
+\setinterfaceconstant{pageconversionset}{pageconversionset}
+\setinterfaceconstant{pagenumber}{seitennummer}
+\setinterfaceconstant{pageprefix}{pageprefix}
+\setinterfaceconstant{pageprefixconnector}{pageprefixconnector}
+\setinterfaceconstant{pageprefixconversion}{pageprefixconversion}
+\setinterfaceconstant{pageprefixconversionset}{pageprefixconversionset}
+\setinterfaceconstant{pageprefixsegments}{pageprefixsegments}
+\setinterfaceconstant{pageprefixseparatorset}{pageprefixseparatorset}
+\setinterfaceconstant{pageprefixset}{pageprefixset}
+\setinterfaceconstant{pageprefixstarter}{pageprefixstarter}
+\setinterfaceconstant{pageprefixstopper}{pageprefixstopper}
+\setinterfaceconstant{pagesegments}{pagesegments}
+\setinterfaceconstant{pageseparatorset}{pageseparatorset}
+\setinterfaceconstant{pageset}{pageset}
+\setinterfaceconstant{pagestarter}{pagestarter}
+\setinterfaceconstant{pagestate}{pagestate}
+\setinterfaceconstant{pagestopper}{pagestopper}
+\setinterfaceconstant{pagestyle}{seitenstil}
+\setinterfaceconstant{palet}{palette}
+\setinterfaceconstant{paper}{papier}
+\setinterfaceconstant{paragraph}{absatz}
+\setinterfaceconstant{place}{platziere}
+\setinterfaceconstant{placehead}{setzekopf}
+\setinterfaceconstant{placestopper}{setzetrenner}
+\setinterfaceconstant{position}{position}
+\setinterfaceconstant{prefix}{prefix}
+\setinterfaceconstant{prefixconnector}{prefixconnector}
+\setinterfaceconstant{prefixconversion}{prefixconversion}
+\setinterfaceconstant{prefixconversionset}{prefixconversionset}
+\setinterfaceconstant{prefixsegments}{prefixsegments}
+\setinterfaceconstant{prefixseparatorset}{prefixseparatorset}
+\setinterfaceconstant{prefixset}{prefixset}
+\setinterfaceconstant{prefixstarter}{prefixstarter}
+\setinterfaceconstant{prefixstopper}{prefixstopper}
+\setinterfaceconstant{preset}{voreinstellung}
+\setinterfaceconstant{preview}{vorschau}
+\setinterfaceconstant{previous}{vorige}
+\setinterfaceconstant{previousnumber}{vorigenummer}
+\setinterfaceconstant{process}{process}
+\setinterfaceconstant{pubsep}{pubsep}
+\setinterfaceconstant{radius}{radius}
+\setinterfaceconstant{random}{zufaellig}
+\setinterfaceconstant{range}{range}
+\setinterfaceconstant{reduction}{reduktion}
+\setinterfaceconstant{ref}{ref}
+\setinterfaceconstant{refcommand}{refcommand}
+\setinterfaceconstant{reference}{referenz}
+\setinterfaceconstant{referenceprefix}{referenceprefix}
+\setinterfaceconstant{referencing}{referieren}
+\setinterfaceconstant{regionin}{regionin}
+\setinterfaceconstant{regionout}{regionaus}
+\setinterfaceconstant{repeat}{wiederholen}
+\setinterfaceconstant{reset}{reset}
+\setinterfaceconstant{resetnumber}{resetnumber}
+\setinterfaceconstant{resolution}{aufloesung}
+\setinterfaceconstant{right}{rechts}
+\setinterfaceconstant{rightcolor}{rechterfarbe}
+\setinterfaceconstant{rightcompoundhyphen}{rightcompoundhyphen}
+\setinterfaceconstant{rightedge}{rechtekante}
+\setinterfaceconstant{rightedgedistance}{rechterkantenabstand}
+\setinterfaceconstant{rightframe}{rechterrahmen}
+\setinterfaceconstant{righthyphen}{righthyphen}
+\setinterfaceconstant{rightmargin}{rechterrand}
+\setinterfaceconstant{rightmargindistance}{rechterrandabstand}
+\setinterfaceconstant{rightoffset}{rechterabstand}
+\setinterfaceconstant{rightquotation}{rechterzitat}
+\setinterfaceconstant{rightquote}{rechterzitieren}
+\setinterfaceconstant{rightsentence}{rechtersatz}
+\setinterfaceconstant{rightspeech}{rightspeech}
+\setinterfaceconstant{rightstyle}{rechterstil}
+\setinterfaceconstant{rightsubsentence}{rechtersubsatz}
+\setinterfaceconstant{righttext}{rechtertext}
+\setinterfaceconstant{rightwidth}{rechterbreite}
+\setinterfaceconstant{rotation}{rotation}
+\setinterfaceconstant{rule}{linie}
+\setinterfaceconstant{rulecolor}{linienfarbe}
+\setinterfaceconstant{rulethickness}{liniendicke}
+\setinterfaceconstant{samepage}{selbeseite}
+\setinterfaceconstant{sample}{muster}
+\setinterfaceconstant{samplesize}{samplesize}
+\setinterfaceconstant{saveinlist}{saveinlist}
+\setinterfaceconstant{scale}{format}
+\setinterfaceconstant{scope}{bereich}
+\setinterfaceconstant{screen}{raster}
+\setinterfaceconstant{section}{abschnitt}
+\setinterfaceconstant{sectionconversion}{sectionconversion}
+\setinterfaceconstant{sectionconversionset}{sectionconversionset}
+\setinterfaceconstant{sectionnumber}{abschnittsnummer}
+\setinterfaceconstant{sectionresetset}{sectionresetset}
+\setinterfaceconstant{sectionsegments}{sectionsegments}
+\setinterfaceconstant{sectionseparatorset}{sectionseparatorset}
+\setinterfaceconstant{sectionset}{sectionset}
+\setinterfaceconstant{sectionstarter}{sectionstarter}
+\setinterfaceconstant{sectionstopper}{sectionstopper}
+\setinterfaceconstant{separator}{seperator}
+\setinterfaceconstant{set}{set}
+\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{side}{objektabstand}
+\setinterfaceconstant{sidealign}{sidealign}
+\setinterfaceconstant{sidemethod}{sidemethod}
+\setinterfaceconstant{sidespaceafter}{nebennachspatium}
+\setinterfaceconstant{sidespacebefore}{nebenvorspatium}
+\setinterfaceconstant{sign}{zeichen}
+\setinterfaceconstant{size}{groesse}
+\setinterfaceconstant{small}{klein}
+\setinterfaceconstant{sort}{sort}
+\setinterfaceconstant{sorttype}{sorttype}
+\setinterfaceconstant{source}{quelle}
+\setinterfaceconstant{space}{spatium}
+\setinterfaceconstant{spaceafter}{nachspatium}
+\setinterfaceconstant{spacebefore}{vorspatium}
+\setinterfaceconstant{spaceinbetween}{spaceinbetween}
+\setinterfaceconstant{spacing}{spatiumausgleich}
+\setinterfaceconstant{split}{split}
+\setinterfaceconstant{splitcolor}{splitcolor}
+\setinterfaceconstant{splitmethod}{splitmethod}
+\setinterfaceconstant{splitoffset}{splitoffset}
+\setinterfaceconstant{spot}{spot}
+\setinterfaceconstant{stack}{stack}
+\setinterfaceconstant{start}{start}
+\setinterfaceconstant{starter}{starter}
+\setinterfaceconstant{state}{status}
+\setinterfaceconstant{step}{schritt}
+\setinterfaceconstant{stop}{stop}
+\setinterfaceconstant{stopper}{abschnitttrenner}
+\setinterfaceconstant{stretch}{strecken}
+\setinterfaceconstant{strip}{strip}
+\setinterfaceconstant{strut}{strut}
+\setinterfaceconstant{style}{stil}
+\setinterfaceconstant{sub}{unter}
+\setinterfaceconstant{subtitle}{untertitel}
+\setinterfaceconstant{suffix}{suffix}
+\setinterfaceconstant{surnamesep}{surnamesep}
+\setinterfaceconstant{sx}{sx}
+\setinterfaceconstant{sy}{sy}
+\setinterfaceconstant{symalign}{symausrichtung}
+\setinterfaceconstant{symbol}{symbol}
+\setinterfaceconstant{symbolset}{symbolset}
+\setinterfaceconstant{symcolor}{symfarbe}
+\setinterfaceconstant{symstyle}{symstil}
+\setinterfaceconstant{synonym}{synonym}
+\setinterfaceconstant{synonymcolor}{synonymfarbe}
+\setinterfaceconstant{synonymcommand}{synonymbefehl}
+\setinterfaceconstant{synonymstyle}{synonymstil}
+\setinterfaceconstant{tab}{tab}
+\setinterfaceconstant{text}{text}
+\setinterfaceconstant{textcolor}{textfarbe}
+\setinterfaceconstant{textcommand}{textbefehl}
+\setinterfaceconstant{textdistance}{textdistance}
+\setinterfaceconstant{textlayer}{textlayer}
+\setinterfaceconstant{textmargin}{textmargin}
+\setinterfaceconstant{textmethod}{textmethod}
+\setinterfaceconstant{textseparator}{textseparator}
+\setinterfaceconstant{textsize}{textgroesse}
+\setinterfaceconstant{textstate}{textstatus}
+\setinterfaceconstant{textstyle}{textstil}
+\setinterfaceconstant{textwidth}{textbreite}
+\setinterfaceconstant{title}{titel}
+\setinterfaceconstant{titlecolor}{titelfarbe}
+\setinterfaceconstant{titlecommand}{titlecommand}
+\setinterfaceconstant{titledistance}{titelabstand}
+\setinterfaceconstant{titleleft}{titleleft}
+\setinterfaceconstant{titleright}{titleright}
+\setinterfaceconstant{titlestyle}{titelstil}
+\setinterfaceconstant{to}{zu}
+\setinterfaceconstant{tolerance}{toleranz}
+\setinterfaceconstant{top}{oben}
+\setinterfaceconstant{topdistance}{obenabstand}
+\setinterfaceconstant{topframe}{obenrahmen}
+\setinterfaceconstant{topoffset}{obenoffset}
+\setinterfaceconstant{topspace}{kopfspatium}
+\setinterfaceconstant{topstate}{statusoben}
+\setinterfaceconstant{totalnumber}{totalnumber}
+\setinterfaceconstant{type}{typ}
+\setinterfaceconstant{unit}{einheit}
+\setinterfaceconstant{unknownreference}{unbekantereferenz}
+\setinterfaceconstant{urlalternative}{urlalternative}
+\setinterfaceconstant{urlspace}{urlspatium}
+\setinterfaceconstant{validate}{validieren}
+\setinterfaceconstant{vcommand}{vbefehl}
+\setinterfaceconstant{veroffset}{kopfoffset}
+\setinterfaceconstant{vfil}{vfil}
+\setinterfaceconstant{voffset}{voffset}
+\setinterfaceconstant{vonsep}{vonsep}
+\setinterfaceconstant{way}{art}
+\setinterfaceconstant{wfactor}{bfaktor}
+\setinterfaceconstant{white}{weiss}
+\setinterfaceconstant{width}{breite}
+\setinterfaceconstant{xfactor}{xfaktor}
+\setinterfaceconstant{xmax}{xmax}
+\setinterfaceconstant{xoffset}{xoffset}
+\setinterfaceconstant{xscale}{xformat}
+\setinterfaceconstant{xstep}{xschritt}
+\setinterfaceconstant{yfactor}{yfaktor}
+\setinterfaceconstant{ymax}{ymax}
+\setinterfaceconstant{yoffset}{yoffset}
+\setinterfaceconstant{yscale}{yformat}
+\setinterfaceconstant{ystep}{yschritt}
+% definitions for interface elements for language de
+%
+\setinterfaceelement{answerlines}{answerlines}
+\setinterfaceelement{answerspace}{answerspace}
+\setinterfaceelement{begin}{anfang}
+\setinterfaceelement{complete}{vollende}
+\setinterfaceelement{coupled}{verknuepft}
+\setinterfaceelement{currentlocal}{aktuelllokal}
+\setinterfaceelement{emptyone}{vuoto}
+\setinterfaceelement{emptytwo}{leer}
+\setinterfaceelement{end}{ende}
+\setinterfaceelement{endsetup}{ein}
+\setinterfaceelement{get}{get}
+\setinterfaceelement{increment}{erhoehen}
+\setinterfaceelement{list}{auflisten}
+\setinterfaceelement{listof}{auflistenvon}
+\setinterfaceelement{load}{laden}
+\setinterfaceelement{local}{lokal}
+\setinterfaceelement{makeup}{umbruch}
+\setinterfaceelement{next}{folgende}
+\setinterfaceelement{place}{platziere}
+\setinterfaceelement{previous}{vorige}
+\setinterfaceelement{previouslocal}{voriglokal}
+\setinterfaceelement{reserve}{reservieren}
+\setinterfaceelement{see}{sieh}
+\setinterfaceelement{setup}{stelle}
+\setinterfaceelement{start}{start}
+\setinterfaceelement{stop}{stop}
+\setinterfaceelement{text}{text}
+\setinterfaceelement{type}{type}
+% definitions for interface commands for language de
+%
+\setinterfacecommand{CAPPED}{KAP}
+\setinterfacecommand{Character}{Buchstabe}
+\setinterfacecommand{Characters}{Buchstaben}
+\setinterfacecommand{LABELTEXT}{LABELTEXT}
+\setinterfacecommand{MONTH}{MONAT}
+\setinterfacecommand{Numbers}{Ziffern}
+\setinterfacecommand{Romannumerals}{Roemischezahlen}
+\setinterfacecommand{SmallCapped}{Kap}
+\setinterfacecommand{SmallCaps}{Kaps}
+\setinterfacecommand{WEEKDAY}{WOCHENTAG}
+\setinterfacecommand{WORD}{WORT}
+\setinterfacecommand{WORDS}{WOERTER}
+\setinterfacecommand{Word}{Wort}
+\setinterfacecommand{Words}{Woerter}
+\setinterfacecommand{about}{ueber}
+\setinterfacecommand{adaptlayout}{passelayoutan}
+\setinterfacecommand{arg}{arg}
+\setinterfacecommand{at}{bei}
+\setinterfacecommand{atleftmargin}{atleftmargin}
+\setinterfacecommand{atpage}{aufseite}
+\setinterfacecommand{atrightmargin}{atrightmargin}
+\setinterfacecommand{background}{hintergrund}
+\setinterfacecommand{backspace}{rumpfweite}
+\setinterfacecommand{blackrule}{rechteck}
+\setinterfacecommand{blackrules}{rechtecke}
+\setinterfacecommand{blank}{blanko}
+\setinterfacecommand{bookmark}{bookmark}
+\setinterfacecommand{bottomdistance}{abstandunten}
+\setinterfacecommand{bottomheight}{hoeheunten}
+\setinterfacecommand{bottomspace}{bottomspace}
+\setinterfacecommand{but}{but}
+\setinterfacecommand{button}{knopf}
+\setinterfacecommand{bypassblocks}{bypassblocks}
+\setinterfacecommand{character}{buchstabe}
+\setinterfacecommand{characters}{buchstaben}
+\setinterfacecommand{chem}{chem}
+\setinterfacecommand{clip}{ausschnitt}
+\setinterfacecommand{clonefield}{klonierefeld}
+\setinterfacecommand{color}{farbe}
+\setinterfacecommand{colorbar}{farbbalken}
+\setinterfacecommand{colorvalue}{farbewert}
+\setinterfacecommand{column}{spalte}
+\setinterfacecommand{comment}{kommentar}
+\setinterfacecommand{comparecolorgroup}{vergleichefarbengruppe}
+\setinterfacecommand{comparepalet}{vergleichepalette}
+\setinterfacecommand{completepagenumber}{completepagenumber}
+\setinterfacecommand{completeregister}{completeregister}
+\setinterfacecommand{component}{komponente}
+\setinterfacecommand{convertnumber}{konvertierezahl}
+\setinterfacecommand{copyfield}{kopierefeld}
+\setinterfacecommand{correctwhitespace}{korrigierezwischenraum}
+\setinterfacecommand{coupledocument}{verknuepfedokument}
+\setinterfacecommand{couplemarking}{verknuepfebeschriftung}
+\setinterfacecommand{couplepage}{doppelseite}
+\setinterfacecommand{couplepaper}{doppelseitigespapier}
+\setinterfacecommand{coupleregister}{verknuepfregister}
+\setinterfacecommand{crlf}{crlf}
+\setinterfacecommand{currentdate}{heutigesdatum}
+\setinterfacecommand{currentheadnumber}{heutigeskopfnummer}
+\setinterfacecommand{cutspace}{cutspace}
+\setinterfacecommand{date}{datum}
+\setinterfacecommand{decouplemarking}{entknuepfebeschriftung}
+\setinterfacecommand{decrementnumber}{decrementnumber}
+\setinterfacecommand{define}{definieren}
+\setinterfacecommand{defineaccent}{definiereakzent}
+\setinterfacecommand{defineblank}{definiereblanko}
+\setinterfacecommand{defineblock}{definiereblock}
+\setinterfacecommand{definebodyfont}{definierefliesstext}
+\setinterfacecommand{definebodyfontenvironment}{definierefliesstextumgebung}
+\setinterfacecommand{definebuffer}{definierepuffer}
+\setinterfacecommand{definecharacter}{definierezeichen}
+\setinterfacecommand{definecolor}{definierefarbe}
+\setinterfacecommand{definecolorgroup}{definierefarbengruppe}
+\setinterfacecommand{definecolumnbreak}{definecolumnbreak}
+\setinterfacecommand{definecolumnset}{definecolumnset}
+\setinterfacecommand{definecombination}{definecombination}
+\setinterfacecommand{definecombinedlist}{definierezusammengestellteliste}
+\setinterfacecommand{definecommand}{definierebefehl}
+\setinterfacecommand{defineconversion}{definierekonversion}
+\setinterfacecommand{definedescription}{definierebeschreibung}
+\setinterfacecommand{defineenumeration}{definierenummerierung}
+\setinterfacecommand{definefield}{definierefeld}
+\setinterfacecommand{definefieldstack}{definierefeldstapel}
+\setinterfacecommand{definefiguresymbol}{definiereabbsymbol}
+\setinterfacecommand{definefloat}{definieregleitobjekt}
+\setinterfacecommand{definefont}{definiereschrift}
+\setinterfacecommand{definefontstyle}{definiereschriftstil}
+\setinterfacecommand{definefontsynonym}{defineschriftsynonym}
+\setinterfacecommand{defineframed}{definiereumrahmt}
+\setinterfacecommand{defineframedtext}{definiereumrahmtertext}
+\setinterfacecommand{definehbox}{definierehbox}
+\setinterfacecommand{definehead}{definiereueberschrift}
+\setinterfacecommand{defineindenting}{definiereeinzug}
+\setinterfacecommand{defineinmargin}{defineinmargin}
+\setinterfacecommand{defineinteractionmenu}{definiereinteraktionsmenue}
+\setinterfacecommand{defineitemgroup}{defineitemgroup}
+\setinterfacecommand{definelabel}{definierelabel}
+\setinterfacecommand{definelayer}{definelayer}
+\setinterfacecommand{definelayout}{definelayout}
+\setinterfacecommand{definelist}{definiereliste}
+\setinterfacecommand{definelogo}{definierelogo}
+\setinterfacecommand{definemainfield}{definierehauptfeld}
+\setinterfacecommand{definemakeup}{definiereumbruch}
+\setinterfacecommand{definemarking}{definierebeschriftung}
+\setinterfacecommand{definemathalignment}{definemathalignment}
+\setinterfacecommand{defineoutput}{defineoutput}
+\setinterfacecommand{defineoverlay}{definiereoverlay}
+\setinterfacecommand{definepagebreak}{definepagebreak}
+\setinterfacecommand{definepalet}{definierepalette}
+\setinterfacecommand{definepapersize}{definierepapierformat}
+\setinterfacecommand{defineparagraphs}{definiereabsaetze}
+\setinterfacecommand{defineplacement}{defineplacement}
+\setinterfacecommand{defineprofile}{definiereprofil}
+\setinterfacecommand{defineprogram}{definiereprogramme}
+\setinterfacecommand{definerawfont}{definerawfont}
+\setinterfacecommand{definereference}{definierereferenz}
+\setinterfacecommand{definereferenceformat}{definierereferenzformat}
+\setinterfacecommand{definereferencelist}{definierereferenzliste}
+\setinterfacecommand{defineregister}{definiereregister}
+\setinterfacecommand{definerule}{definerule}
+\setinterfacecommand{definesection}{definiereabschnitt}
+\setinterfacecommand{definesectionblock}{definiereabschnittsblock}
+\setinterfacecommand{definesorting}{definieresortieren}
+\setinterfacecommand{definestartstop}{definierestartstop}
+\setinterfacecommand{definestyle}{definierestil}
+\setinterfacecommand{definesubfield}{definieresubfeld}
+\setinterfacecommand{definesymbol}{definieresymbol}
+\setinterfacecommand{definesynonyms}{definieresynonyme}
+\setinterfacecommand{definetabletemplate}{definieretabellenvorlage}
+\setinterfacecommand{definetabulate}{definieretabulator}
+\setinterfacecommand{definetext}{definieretext}
+\setinterfacecommand{definetextposition}{definetextposition}
+\setinterfacecommand{definetextvariable}{definetextvariable}
+\setinterfacecommand{definetype}{definetype}
+\setinterfacecommand{definetyping}{definieretippen}
+\setinterfacecommand{defineversion}{definiereversion}
+\setinterfacecommand{determineheadnumber}{bestimmekopfnummer}
+\setinterfacecommand{determinelistcharacteristics}{bestimmelistencharakeristika}
+\setinterfacecommand{determineregistercharacteristics}{bestimmeregistercharakteristika}
+\setinterfacecommand{dimension}{dimension}
+\setinterfacecommand{disableinteractionmenu}{inaktiviereinteraktionsmenue}
+\setinterfacecommand{domicile}{wohnort}
+\setinterfacecommand{donttest}{keintest}
+\setinterfacecommand{edgedistance}{randabstand}
+\setinterfacecommand{edgewidth}{randbreite}
+\setinterfacecommand{emptylines}{emptylines}
+\setinterfacecommand{environment}{umgebung}
+\setinterfacecommand{externalfigure}{externeabbildung}
+\setinterfacecommand{fact}{geg}
+\setinterfacecommand{field}{feld}
+\setinterfacecommand{fieldstack}{feldstapel}
+\setinterfacecommand{fillinfield}{ausfuellfeld}
+\setinterfacecommand{fillinline}{gefuelltezeile}
+\setinterfacecommand{fillinrules}{gefuelltesrechteck}
+\setinterfacecommand{fillintext}{ausfuelltext}
+\setinterfacecommand{fitfield}{passendfeld}
+\setinterfacecommand{fixedspace}{festesspatium}
+\setinterfacecommand{fixedspaces}{festesspatium}
+\setinterfacecommand{followprofile}{folgeprofil}
+\setinterfacecommand{followprofileversion}{folgeprofilversion}
+\setinterfacecommand{followversion}{folgeversion}
+\setinterfacecommand{footerdistance}{fusszeileabstand}
+\setinterfacecommand{footerheight}{fusszeilenhoehe}
+\setinterfacecommand{footnote}{fussnote}
+\setinterfacecommand{footnotetext}{footnotetext}
+\setinterfacecommand{forceblocks}{forceblocks}
+\setinterfacecommand{formulanumber}{formelnummer}
+\setinterfacecommand{fraction}{bruch}
+\setinterfacecommand{framed}{umrahmt}
+\setinterfacecommand{from}{von}
+\setinterfacecommand{getbuffer}{holepuffer}
+\setinterfacecommand{getmarking}{holebeschriftung}
+\setinterfacecommand{getnumber}{getnumber}
+\setinterfacecommand{godown}{nachunten}
+\setinterfacecommand{goto}{zu}
+\setinterfacecommand{gotobox}{zurbox}
+\setinterfacecommand{gotopage}{zurseite}
+\setinterfacecommand{graycolor}{graufarbe}
+\setinterfacecommand{greyvalue}{grauwert}
+\setinterfacecommand{grid}{gitter}
+\setinterfacecommand{hairline}{haarlinie}
+\setinterfacecommand{head}{kopf}
+\setinterfacecommand{headerdistance}{kopfzeilenabstand}
+\setinterfacecommand{headerheight}{kopfzeilenhoehe}
+\setinterfacecommand{headlevel}{kopfniveau}
+\setinterfacecommand{headnumber}{kopfnummer}
+\setinterfacecommand{headsym}{headsym}
+\setinterfacecommand{headtext}{ueberschrifttext}
+\setinterfacecommand{hideblocks}{verbergebloecke}
+\setinterfacecommand{high}{hoch}
+\setinterfacecommand{hl}{hl}
+\setinterfacecommand{immediatebetweenlist}{immediatebetweenlist}
+\setinterfacecommand{immediatetolist}{immediatetolist}
+\setinterfacecommand{in}{in}
+\setinterfacecommand{incrementnumber}{nummererhoehen}
+\setinterfacecommand{indenting}{einziehen}
+\setinterfacecommand{inframed}{imumriss}
+\setinterfacecommand{infull}{volleswort}
+\setinterfacecommand{ininner}{ininner}
+\setinterfacecommand{inleft}{imlinken}
+\setinterfacecommand{inleftedge}{imlinkenrand}
+\setinterfacecommand{inleftmargin}{inlinkermarginale}
+\setinterfacecommand{inline}{inzeile}
+\setinterfacecommand{inmargin}{inmarginalie}
+\setinterfacecommand{inmframed}{immaumrise}
+\setinterfacecommand{inneredgedistance}{inneredgedistance}
+\setinterfacecommand{inneredgewidth}{inneredgewidth}
+\setinterfacecommand{innermargindistance}{innermargindistance}
+\setinterfacecommand{innermarginwidth}{innermarginwidth}
+\setinterfacecommand{inothermargin}{inanderermarginale}
+\setinterfacecommand{inouter}{inouter}
+\setinterfacecommand{inright}{imrechten}
+\setinterfacecommand{inrightedge}{imrechtenrand}
+\setinterfacecommand{inrightmargin}{inrechtermarginale}
+\setinterfacecommand{installlanguage}{installieresprache}
+\setinterfacecommand{interactionbar}{interaktionsbalken}
+\setinterfacecommand{interactionbuttons}{interaktionsknopfe}
+\setinterfacecommand{interactionmenu}{interaktionsmenue}
+\setinterfacecommand{item}{pos}
+\setinterfacecommand{items}{posten}
+\setinterfacecommand{its}{its}
+\setinterfacecommand{keepblocks}{behaltebloecke}
+\setinterfacecommand{label}{label}
+\setinterfacecommand{labels}{labels}
+\setinterfacecommand{labeltext}{labeltext}
+\setinterfacecommand{language}{sprache}
+\setinterfacecommand{leftaligned}{linksbuendig}
+\setinterfacecommand{leftedgedistance}{abstandlinkerrand}
+\setinterfacecommand{leftedgewidth}{breitelinkerrand}
+\setinterfacecommand{leftmargindistance}{linkemarginalafstand}
+\setinterfacecommand{leftmarginwidth}{linkemarginalbreite}
+\setinterfacecommand{leg}{leg}
+\setinterfacecommand{linewidth}{liniendicke}
+\setinterfacecommand{listheight}{listenhoehe}
+\setinterfacecommand{listlength}{listenlaenge}
+\setinterfacecommand{listsymbol}{listsymbol}
+\setinterfacecommand{listwidth}{listenbreite}
+\setinterfacecommand{logfields}{registrierefelder}
+\setinterfacecommand{lohi}{tiho}
+\setinterfacecommand{low}{tief}
+\setinterfacecommand{macroname}{name}
+\setinterfacecommand{mainlanguage}{hauptsprache}
+\setinterfacecommand{makeupheight}{satzhoehe}
+\setinterfacecommand{makeupwidth}{satzbreite}
+\setinterfacecommand{mar}{mar}
+\setinterfacecommand{margindistance}{marginalafstand}
+\setinterfacecommand{marginrule}{marginallinie}
+\setinterfacecommand{margintext}{marginaltext}
+\setinterfacecommand{margintitle}{marginaltitel}
+\setinterfacecommand{marginwidth}{marginalbreite}
+\setinterfacecommand{marginword}{marginalwort}
+\setinterfacecommand{marking}{beschriftung}
+\setinterfacecommand{markversion}{beschrifteversion}
+\setinterfacecommand{mathematics}{mathematik}
+\setinterfacecommand{menubutton}{menueknopf}
+\setinterfacecommand{mframed}{maumrise}
+\setinterfacecommand{midaligned}{zentriert}
+\setinterfacecommand{mirror}{spiegeln}
+\setinterfacecommand{month}{monat}
+\setinterfacecommand{moveformula}{moveformula}
+\setinterfacecommand{moveongrid}{amgitterneuausrichten}
+\setinterfacecommand{movesidefloat}{movesidefloat}
+\setinterfacecommand{navigating}{navigating}
+\setinterfacecommand{nodimension}{keindimension}
+\setinterfacecommand{noheaderandfooterlines}{keinekopfundfusszeilen}
+\setinterfacecommand{noindenting}{nichteinziehen}
+\setinterfacecommand{nolist}{keineliste}
+\setinterfacecommand{nomarking}{keinebeschriftung}
+\setinterfacecommand{nomoreblocks}{keinebloeckemehr}
+\setinterfacecommand{nomorefiles}{keinedateienmehr}
+\setinterfacecommand{nop}{nop}
+\setinterfacecommand{nospace}{keinspatium}
+\setinterfacecommand{note}{notiz}
+\setinterfacecommand{notopandbottomlines}{keinzeilenobenundunten}
+\setinterfacecommand{notsmallcapped}{nokap}
+\setinterfacecommand{nowhitespace}{keinzwischenraum}
+\setinterfacecommand{numberofsubpages}{numberofsubpages}
+\setinterfacecommand{numbers}{ziffern}
+\setinterfacecommand{outeredgedistance}{outeredgedistance}
+\setinterfacecommand{outeredgewidth}{outeredgewidth}
+\setinterfacecommand{outermargindistance}{outermargindistance}
+\setinterfacecommand{outermarginwidth}{outermarginwidth}
+\setinterfacecommand{packed}{kleinerdurchschuss}
+\setinterfacecommand{page}{seite}
+\setinterfacecommand{pagedepth}{pagedepth}
+\setinterfacecommand{pagenumber}{seitenummer}
+\setinterfacecommand{pageoffset}{pageoffset}
+\setinterfacecommand{pagereference}{seitenreferenz}
+\setinterfacecommand{pagetype}{seitentyp}
+\setinterfacecommand{paperheight}{papierhoehe}
+\setinterfacecommand{paperwidth}{papierbreite}
+\setinterfacecommand{periods}{punkt}
+\setinterfacecommand{plaatsruwelijst}{placerawlist}
+\setinterfacecommand{placebookmarks}{platzierebookmarks}
+\setinterfacecommand{placecombinedlist}{platzierezusammengestellteliste}
+\setinterfacecommand{placefloat}{placefloat}
+\setinterfacecommand{placefootnotes}{platzierefussnoten}
+\setinterfacecommand{placeformula}{platziereformel}
+\setinterfacecommand{placeheadnumber}{placeheadnumber}
+\setinterfacecommand{placeheadtext}{placeheadtext}
+\setinterfacecommand{placelegend}{platzierelegende}
+\setinterfacecommand{placelist}{platziereliste}
+\setinterfacecommand{placelocalfootnotes}{platzierelokalefussnoten}
+\setinterfacecommand{placelogos}{platzierelogo}
+\setinterfacecommand{placeongrid}{amgitterausrichten}
+\setinterfacecommand{placeontopofeachother}{platziereuntereinander}
+\setinterfacecommand{placepagenumber}{placepagenumber}
+\setinterfacecommand{placereferencelist}{placereferencelist}
+\setinterfacecommand{placeregister}{platziereregister}
+\setinterfacecommand{placerule}{placerule}
+\setinterfacecommand{placesidebyside}{platzierenebeneinander}
+\setinterfacecommand{placesubformula}{platziereunterformel}
+\setinterfacecommand{placetextvariable}{placetextvariable}
+\setinterfacecommand{position}{position}
+\setinterfacecommand{positiontext}{positiontext}
+\setinterfacecommand{printpaperheight}{printpapierhoehe}
+\setinterfacecommand{printpaperwidth}{printpapierbreite}
+\setinterfacecommand{processblocks}{bearbeitebloecke}
+\setinterfacecommand{processpage}{bearbeiteseite}
+\setinterfacecommand{product}{produkt}
+\setinterfacecommand{program}{programm}
+\setinterfacecommand{project}{projekt}
+\setinterfacecommand{publication}{publikation}
+\setinterfacecommand{quotation}{zitat}
+\setinterfacecommand{quote}{zitieren}
+\setinterfacecommand{ran}{ran}
+\setinterfacecommand{redo}{wiederholen}
+\setinterfacecommand{ref}{ref}
+\setinterfacecommand{reference}{referenz}
+\setinterfacecommand{referral}{verweis}
+\setinterfacecommand{referraldate}{verweisdatum}
+\setinterfacecommand{referring}{referieren}
+\setinterfacecommand{remark}{bemerkung}
+\setinterfacecommand{reset}{ruecksetzten}
+\setinterfacecommand{resetmarking}{ruecksetztenbeschriftung}
+\setinterfacecommand{resetnumber}{resetnumber}
+\setinterfacecommand{resettext}{resettextcontent}
+\setinterfacecommand{rightaligned}{rechtsbuendig}
+\setinterfacecommand{rightedgedistance}{abstandrechterrand}
+\setinterfacecommand{rightedgewidth}{breiterechterrand}
+\setinterfacecommand{rightmargindistance}{rechtemarginalafstand}
+\setinterfacecommand{rightmarginwidth}{rechtemarginalbreite}
+\setinterfacecommand{romannumerals}{roemischezahlen}
+\setinterfacecommand{rotate}{drehen}
+\setinterfacecommand{scale}{format}
+\setinterfacecommand{screen}{bildschirm}
+\setinterfacecommand{selectblocks}{waehlebloeckeaus}
+\setinterfacecommand{selectpaper}{waehlepapieraus}
+\setinterfacecommand{selectversion}{waehleversionaus}
+\setinterfacecommand{setnumber}{setnumber}
+\setinterfacecommand{settextcontent}{settext}
+\setinterfacecommand{settextvariable}{settextvariable}
+\setinterfacecommand{setupalign}{stelleausrichtungein}
+\setinterfacecommand{setupanswerarea}{setupanswerarea}
+\setinterfacecommand{setuparranging}{stelleanordnenein}
+\setinterfacecommand{setupbackground}{stellehintergrundein}
+\setinterfacecommand{setupbackgrounds}{stellehintergruendeein}
+\setinterfacecommand{setupblackrules}{stellerechteckein}
+\setinterfacecommand{setupblank}{stelleblankoein}
+\setinterfacecommand{setupblock}{stelleblockein}
+\setinterfacecommand{setupbodyfont}{stellefliesstextein}
+\setinterfacecommand{setupbodyfontenvironment}{stellefliesstextumgebungein}
+\setinterfacecommand{setupbottom}{stelleuntenein}
+\setinterfacecommand{setupbottomtexts}{stelletextuntenein}
+\setinterfacecommand{setupbuffer}{stellepufferein}
+\setinterfacecommand{setupbuttons}{stelleknopfein}
+\setinterfacecommand{setupcapitals}{stelleversalienein}
+\setinterfacecommand{setupcaption}{stellebildunterschriftein}
+\setinterfacecommand{setupcaptions}{stellebilderunterschriftein}
+\setinterfacecommand{setupclipping}{stelleausschnittein}
+\setinterfacecommand{setupcolor}{stellefarbeein}
+\setinterfacecommand{setupcolors}{stellefarbenein}
+\setinterfacecommand{setupcolumns}{stellespaltenein}
+\setinterfacecommand{setupcolumnset}{setupcolumnset}
+\setinterfacecommand{setupcolumnsetlines}{setupcolumnsetlines}
+\setinterfacecommand{setupcolumnsetstart}{setupcolumnsetstart}
+\setinterfacecommand{setupcombinations}{stellekombinationein}
+\setinterfacecommand{setupcombinedlist}{stellezusammengestelltelisteein}
+\setinterfacecommand{setupcomment}{stellekommentarein}
+\setinterfacecommand{setupdescriptions}{definierebeschreibungen}
+\setinterfacecommand{setupenumerations}{stellebeschreibungein}
+\setinterfacecommand{setupexternalfigures}{stelleexterneabbildungenein}
+\setinterfacecommand{setupfield}{stellefeldein}
+\setinterfacecommand{setupfields}{stellefelderin}
+\setinterfacecommand{setupfillinlines}{stellegefuelltezeileein}
+\setinterfacecommand{setupfillinrules}{stellegefuelltesrechteckein}
+\setinterfacecommand{setupfloat}{stellegleitobjektein}
+\setinterfacecommand{setupfloats}{stellegleitobjekteein}
+\setinterfacecommand{setupfloatsplitting}{stelleplatziegeteiltegleitobjekt}
+\setinterfacecommand{setupfooter}{stellefusszeileein}
+\setinterfacecommand{setupfootertexts}{stellefusszeilentextein}
+\setinterfacecommand{setupfootnotedefinition}{stellefussnotendefinitionein}
+\setinterfacecommand{setupfootnotes}{stellefussnotenein}
+\setinterfacecommand{setupforms}{setupforms}
+\setinterfacecommand{setupformulas}{stelleformelnein}
+\setinterfacecommand{setupframed}{stelleumrahmtein}
+\setinterfacecommand{setupframedtexts}{stelleumrahmtetexteein}
+\setinterfacecommand{setuphead}{stelleueberschriftein}
+\setinterfacecommand{setupheader}{stellekopfzeileein}
+\setinterfacecommand{setupheadertexts}{stellekopfzeilentextein}
+\setinterfacecommand{setupheadnumber}{stellekopfzahlein}
+\setinterfacecommand{setupheads}{stelleueberschriftenein}
+\setinterfacecommand{setupheadtext}{stelleueberschrifttextein}
+\setinterfacecommand{setuphyphenmark}{stellebindestrichein}
+\setinterfacecommand{setupindentations}{stelleeinzuegein}
+\setinterfacecommand{setupindenting}{stelleeinziehenein}
+\setinterfacecommand{setupinmargin}{stelleinmarginalieein}
+\setinterfacecommand{setupinteraction}{stelleinteraktionein}
+\setinterfacecommand{setupinteractionbar}{stelleinteraktionsbalkenein}
+\setinterfacecommand{setupinteractionmenu}{stelleinteraktionsmenueein}
+\setinterfacecommand{setupinteractionscreen}{stelleinteraktionsbildschirmein}
+\setinterfacecommand{setupinterlinespace}{stellezeilenabstandein}
+\setinterfacecommand{setupitemgroup}{setupitemgroup}
+\setinterfacecommand{setupitemgroups}{stelleaufzaehlungenein}
+\setinterfacecommand{setupitems}{stellepostenein}
+\setinterfacecommand{setuplabeltext}{stellelabeltextein}
+\setinterfacecommand{setuplanguage}{stellespracheein}
+\setinterfacecommand{setuplayout}{stellelayoutein}
+\setinterfacecommand{setuplegend}{stellelegendeein}
+\setinterfacecommand{setuplinenumbering}{stellezeilennumerierungein}
+\setinterfacecommand{setuplines}{stellezeilenein}
+\setinterfacecommand{setuplinewidth}{stellelinienbreiteein}
+\setinterfacecommand{setuplist}{stellelisteein}
+\setinterfacecommand{setupmakeup}{stelleumbruchein}
+\setinterfacecommand{setupmarginblocks}{stellemarginalblockein}
+\setinterfacecommand{setupmarginrules}{stellemarginallinieein}
+\setinterfacecommand{setupmarking}{stellebeschriftungein}
+\setinterfacecommand{setupmathalignment}{setupmathalignment}
+\setinterfacecommand{setupnarrower}{stelleengerein}
+\setinterfacecommand{setupnumber}{setupnumber}
+\setinterfacecommand{setupnumbering}{stellenummerierungein}
+\setinterfacecommand{setupoppositeplacing}{stellegegenueberplatzierenein}
+\setinterfacecommand{setupoutput}{stelleausgabeein}
+\setinterfacecommand{setuppagecomment}{stelleseitenkommentarein}
+\setinterfacecommand{setuppagenumber}{stelleseitennummerein}
+\setinterfacecommand{setuppagenumbering}{stelleseitennummeriernungein}
+\setinterfacecommand{setuppagetransitions}{stelleseitenuebergangein}
+\setinterfacecommand{setuppalet}{stellepaletteein}
+\setinterfacecommand{setuppaper}{setuppaper}
+\setinterfacecommand{setuppapersize}{stellepapierformatein}
+\setinterfacecommand{setupparagraphnumbering}{stelleabsatznummerierungein}
+\setinterfacecommand{setupparagraphs}{stelleabsaetzeein}
+\setinterfacecommand{setupplacement}{setupplacement}
+\setinterfacecommand{setuppositioning}{stellepositionierenein}
+\setinterfacecommand{setupprofiles}{stelleprofilein}
+\setinterfacecommand{setupprograms}{stelleprogrammein}
+\setinterfacecommand{setuppublications}{stellepublikationein}
+\setinterfacecommand{setupquote}{stellezitierenein}
+\setinterfacecommand{setupreferencelist}{stellereferenzlisteein}
+\setinterfacecommand{setupreferencing}{stellereferenzierenein}
+\setinterfacecommand{setupregister}{stelleregisterein}
+\setinterfacecommand{setuprotate}{stelledrehenein}
+\setinterfacecommand{setuprule}{setuprule}
+\setinterfacecommand{setups}{einstellungen}
+\setinterfacecommand{setupscreens}{stellerasterein}
+\setinterfacecommand{setupsection}{stelleabschnittein}
+\setinterfacecommand{setupsectionblock}{stelleabschnittsblockein}
+\setinterfacecommand{setupsorting}{stellesortierenein}
+\setinterfacecommand{setupspacing}{stellespatiumein}
+\setinterfacecommand{setupstartstop}{setupstartstop}
+\setinterfacecommand{setupstrut}{setupstrut}
+\setinterfacecommand{setupsubpagenumber}{stelleunterseitennummerein}
+\setinterfacecommand{setupsymbolset}{stellesymbolsetein}
+\setinterfacecommand{setupsynchronization}{stellesynchronisationein}
+\setinterfacecommand{setupsynchronizationbar}{stellesynchronisationsbalkenein}
+\setinterfacecommand{setupsynonyms}{stellesynonymein}
+\setinterfacecommand{setupsystem}{stellesystemein}
+\setinterfacecommand{setuptab}{stelletabein}
+\setinterfacecommand{setuptables}{stelletabellenein}
+\setinterfacecommand{setuptabulate}{stelletabulatorein}
+\setinterfacecommand{setuptext}{stelletextein}
+\setinterfacecommand{setuptextposition}{setuptextposition}
+\setinterfacecommand{setuptextrules}{stelletextumrissein}
+\setinterfacecommand{setuptexttexts}{stelletexttexteein}
+\setinterfacecommand{setuptextvariable}{setuptextvariable}
+\setinterfacecommand{setupthinrules}{stelleduennerumrissein}
+\setinterfacecommand{setuptolerance}{stelletoleranzein}
+\setinterfacecommand{setuptop}{stellenobenein}
+\setinterfacecommand{setuptoptexts}{stelletextobenein}
+\setinterfacecommand{setuptype}{stelletipein}
+\setinterfacecommand{setuptyping}{stelletippenein}
+\setinterfacecommand{setupunderbar}{stelleunterstreichenein}
+\setinterfacecommand{setupurl}{stelleurlein}
+\setinterfacecommand{setupversions}{stelleversionein}
+\setinterfacecommand{setupwhitespace}{stellezwischenraumein}
+\setinterfacecommand{showbodyfont}{zeigefliesstext}
+\setinterfacecommand{showbodyfontenvironment}{zeigefliesstextumgebung}
+\setinterfacecommand{showcolor}{zeigefarbe}
+\setinterfacecommand{showcolorgroup}{zeigefarbengruppe}
+\setinterfacecommand{showexternalfigures}{zeigeexterneabbildungen}
+\setinterfacecommand{showfields}{zeigefelder}
+\setinterfacecommand{showframe}{zeigerahmen}
+\setinterfacecommand{showgrid}{zeigegitter}
+\setinterfacecommand{showlayout}{zeigelayout}
+\setinterfacecommand{showmakeup}{zeigeumbruch}
+\setinterfacecommand{showpalet}{zeigepalette}
+\setinterfacecommand{showprint}{zeigedruck}
+\setinterfacecommand{showsetups}{zeigeeinstellungen}
+\setinterfacecommand{showstruts}{zeigestruts}
+\setinterfacecommand{showsymbolset}{showsymbolset}
+\setinterfacecommand{smallcapped}{kap}
+\setinterfacecommand{someline}{einezeile}
+\setinterfacecommand{somewhere}{irgendwo}
+\setinterfacecommand{space}{spatium}
+\setinterfacecommand{splitfloat}{teilegleitobjekt}
+\setinterfacecommand{startalignment}{startausrichtung}
+\setinterfacecommand{startbackground}{starthintergrund}
+\setinterfacecommand{startcoding}{startkodierung}
+\setinterfacecommand{startcolor}{startfarbe}
+\setinterfacecommand{startcolumnmakeup}{startcolumnmakeup}
+\setinterfacecommand{startcolumns}{startspalten}
+\setinterfacecommand{startcolumnset}{startcolumnset}
+\setinterfacecommand{startcombination}{startkombination}
+\setinterfacecommand{startcomponent}{startkomponente}
+\setinterfacecommand{startdocument}{startdokument}
+\setinterfacecommand{startenvironment}{startumgebung}
+\setinterfacecommand{startfigure}{startabbildung}
+\setinterfacecommand{startglobal}{startglobal}
+\setinterfacecommand{startline}{startzeile}
+\setinterfacecommand{startlinecorrection}{startzeilenkorrektur}
+\setinterfacecommand{startlinenumbering}{startzeilennumerierung}
+\setinterfacecommand{startlines}{startzeilen}
+\setinterfacecommand{startlocal}{startlokal}
+\setinterfacecommand{startlocalfootnotes}{startlokalefussnoten}
+\setinterfacecommand{startmakeup}{startumbruch}
+\setinterfacecommand{startmarginblock}{startmarginalblock}
+\setinterfacecommand{startmarginrule}{startmarginallinie}
+\setinterfacecommand{startnarrower}{startenger}
+\setinterfacecommand{startopposite}{startgegenueber}
+\setinterfacecommand{startoverlay}{startoverlay}
+\setinterfacecommand{startoverzicht}{startueberblick}
+\setinterfacecommand{startpacked}{startkleinerdurchschuss}
+\setinterfacecommand{startpositioning}{startpositionieren}
+\setinterfacecommand{startproduct}{startprodukt}
+\setinterfacecommand{startprofile}{startprofil}
+\setinterfacecommand{startproject}{startprojekt}
+\setinterfacecommand{startquotation}{startzitat}
+\setinterfacecommand{startraster}{startraster}
+\setinterfacecommand{startsymbolset}{startsymbolset}
+\setinterfacecommand{startsynchronization}{startsynchronisation}
+\setinterfacecommand{starttable}{starttabelle}
+\setinterfacecommand{starttables}{starttabellen}
+\setinterfacecommand{starttext}{starttext}
+\setinterfacecommand{starttextrule}{starttextlinie}
+\setinterfacecommand{startunpacked}{startgrosserdurchschuss}
+\setinterfacecommand{startversion}{startversion}
+\setinterfacecommand{stopalignment}{stopausrichtung}
+\setinterfacecommand{stopbackground}{stophintergrund}
+\setinterfacecommand{stopcoding}{stopkodierung}
+\setinterfacecommand{stopcolor}{stopfarbe}
+\setinterfacecommand{stopcolumnmakeup}{stopcolumnmakeup}
+\setinterfacecommand{stopcolumns}{stopspalten}
+\setinterfacecommand{stopcolumnset}{stopcolumnset}
+\setinterfacecommand{stopcombination}{stopkombination}
+\setinterfacecommand{stopcomponent}{stopkomponente}
+\setinterfacecommand{stopdocument}{stopdokument}
+\setinterfacecommand{stopenvironment}{stopumgebung}
+\setinterfacecommand{stopglobal}{stopglobal}
+\setinterfacecommand{stopline}{stopzeile}
+\setinterfacecommand{stoplinecorrection}{stopzeilenkorrektur}
+\setinterfacecommand{stoplinenumbering}{stopzeilennumerierung}
+\setinterfacecommand{stoplines}{stopzeilen}
+\setinterfacecommand{stoplocal}{stoplokal}
+\setinterfacecommand{stoplocalfootnotes}{stoplokalefussnoten}
+\setinterfacecommand{stopmakeup}{stopumbruch}
+\setinterfacecommand{stopmarginblock}{stopmarginalblock}
+\setinterfacecommand{stopmarginrule}{stopmarginallinie}
+\setinterfacecommand{stopnarrower}{stopenger}
+\setinterfacecommand{stopopposite}{stopgegenueber}
+\setinterfacecommand{stopoverlay}{stopoverlay}
+\setinterfacecommand{stopoverzicht}{stopueberblick}
+\setinterfacecommand{stoppacked}{stopkleinerdurchschuss}
+\setinterfacecommand{stoppositioning}{stoppositionieren}
+\setinterfacecommand{stopproduct}{stopprodukt}
+\setinterfacecommand{stopprofile}{stopprofil}
+\setinterfacecommand{stopproject}{stopprojekt}
+\setinterfacecommand{stopquotation}{stopzitat}
+\setinterfacecommand{stopraster}{stopraster}
+\setinterfacecommand{stopsynchronization}{stopsynchronisation}
+\setinterfacecommand{stoptable}{stoptabelle}
+\setinterfacecommand{stoptables}{stoptabellen}
+\setinterfacecommand{stoptext}{stoptext}
+\setinterfacecommand{stoptextrule}{stoptextlinie}
+\setinterfacecommand{stopunpacked}{stopgrosserdurchschuss}
+\setinterfacecommand{stopversion}{stopversion}
+\setinterfacecommand{stretched}{gestreckt}
+\setinterfacecommand{subformulanumber}{unterformelnummer}
+\setinterfacecommand{subpagenumber}{subpagenumber}
+\setinterfacecommand{switchtobodyfont}{wechselezumfliesstext}
+\setinterfacecommand{switchtorawfont}{switchtorawfont}
+\setinterfacecommand{sym}{sym}
+\setinterfacecommand{symbol}{symbol}
+\setinterfacecommand{synchronizationbar}{synchronisationsbalken}
+\setinterfacecommand{synchronize}{synchronisieren}
+\setinterfacecommand{tab}{tab}
+\setinterfacecommand{testcolumn}{testcolumn}
+\setinterfacecommand{testpage}{testpage}
+\setinterfacecommand{tex}{tex}
+\setinterfacecommand{textheight}{texthoehe}
+\setinterfacecommand{textreference}{textreferenz}
+\setinterfacecommand{textrule}{textlinie}
+\setinterfacecommand{textvariable}{textvariable}
+\setinterfacecommand{textwidth}{textbreite}
+\setinterfacecommand{thinrule}{duennelinie}
+\setinterfacecommand{thinrules}{duennerumriss}
+\setinterfacecommand{tooltip}{tooltip}
+\setinterfacecommand{topdistance}{abstandoben}
+\setinterfacecommand{topheight}{hoeheoben}
+\setinterfacecommand{topspace}{kopfweite}
+\setinterfacecommand{totalnumberofpages}{gesamtseitenanzahl}
+\setinterfacecommand{translate}{uebersetzten}
+\setinterfacecommand{txt}{txt}
+\setinterfacecommand{typ}{tip}
+\setinterfacecommand{type}{tippen}
+\setinterfacecommand{typebuffer}{tippepuffer}
+\setinterfacecommand{typefile}{tippedatei}
+\setinterfacecommand{unitmeaning}{bedeutung}
+\setinterfacecommand{unknown}{unbekant}
+\setinterfacecommand{useJSscripts}{verwendeJSscript}
+\setinterfacecommand{useURL}{verwendeURL}
+\setinterfacecommand{useXMLfilter}{useXMLfilter}
+\setinterfacecommand{useblocks}{verwendebloecke}
+\setinterfacecommand{usecommands}{verwendebefehl}
+\setinterfacecommand{useencoding}{benutzekodierung}
+\setinterfacecommand{useexternaldocument}{verwendeexteresdokument}
+\setinterfacecommand{useexternalfigure}{verwendeexterneabbildung}
+\setinterfacecommand{useexternalfile}{verwendeexternedatei}
+\setinterfacecommand{useexternalfiles}{verwendeexternedateien}
+\setinterfacecommand{useexternalsoundtrack}{verwendeexternestonstueck}
+\setinterfacecommand{usemodule}{verwendemodul}
+\setinterfacecommand{usemodules}{verwendemodule}
+\setinterfacecommand{usepath}{benutzeverzeichnis}
+\setinterfacecommand{usereferences}{verwendereferenzen}
+\setinterfacecommand{usespecials}{benutzespezielles}
+\setinterfacecommand{usesymbols}{verwendesymbole}
+\setinterfacecommand{usetypescript}{usetypescript}
+\setinterfacecommand{usetypescriptfile}{usetypescriptfile}
+\setinterfacecommand{useurl}{verwendeurl}
+\setinterfacecommand{version}{version}
+\setinterfacecommand{vl}{vl}
+\setinterfacecommand{weekday}{wochentag}
+\setinterfacecommand{whitespace}{zwischenraum}
+\setinterfacecommand{wordright}{wortrechts}
+\setinterfacecommand{writebetweenlist}{schreibezwischenliste}
+\setinterfacecommand{writetolist}{schreibezurliste}
+\setinterfacecommand{writetoreferencelist}{schreibezurreferenzliste}
+\setinterfacecommand{writetoregister}{schreibezumregister}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-def.lua b/tex/context/base/mult-def.lua
new file mode 100644
index 000000000..ce5af2bba
--- /dev/null
+++ b/tex/context/base/mult-def.lua
@@ -0,0 +1,16149 @@
+if not modules then modules = { } end modules ['mult-def'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return {
+ ["commands"]={
+ ["CAPPED"]={
+ ["cs"]="KAP",
+ ["de"]="KAP",
+ ["en"]="CAP",
+ ["fr"]="CAP",
+ ["it"]="CAP",
+ ["nl"]="KAP",
+ ["pe"]="CAP",
+ ["ro"]="KAP",
+ },
+ ["Character"]={
+ ["cs"]="Znak",
+ ["de"]="Buchstabe",
+ ["en"]="Character",
+ ["fr"]="Caractere",
+ ["it"]="Lettera",
+ ["nl"]="Letter",
+ ["pe"]="Character",
+ ["ro"]="Litera",
+ },
+ ["Characters"]={
+ ["cs"]="Znaky",
+ ["de"]="Buchstaben",
+ ["en"]="Characters",
+ ["fr"]="Caracteres",
+ ["it"]="Lettere",
+ ["nl"]="Letters",
+ ["pe"]="Characters",
+ ["ro"]="Litere",
+ },
+ ["LABELTEXT"]={
+ ["cs"]="TEXTPOPISKU",
+ ["de"]="LABELTEXT",
+ ["en"]="LABELTEXT",
+ ["fr"]="LABELTEXTE",
+ ["it"]="TESTOETICHETTA",
+ ["nl"]="LABELTEKST",
+ ["pe"]="LABELTEXT",
+ ["ro"]="TEXTETICHETA",
+ },
+ ["MONTH"]={
+ ["cs"]="MESIC",
+ ["de"]="MONAT",
+ ["en"]="MONTH",
+ ["fr"]="MOIS",
+ ["it"]="MESE",
+ ["nl"]="MAAND",
+ ["pe"]="MONTH",
+ ["ro"]="LUNA",
+ },
+ ["Numbers"]={
+ ["cs"]="Cisla",
+ ["de"]="Ziffern",
+ ["en"]="Numbers",
+ ["fr"]="Numeros",
+ ["it"]="Numeri",
+ ["nl"]="Cijfers",
+ ["pe"]="Numbers",
+ ["ro"]="Numere",
+ },
+ ["Romannumerals"]={
+ ["cs"]="Rimskecislice",
+ ["de"]="Roemischezahlen",
+ ["en"]="Romannumerals",
+ ["fr"]="Chiffresromains",
+ ["it"]="Numeriromani",
+ ["nl"]="Romeins",
+ ["pe"]="Romannumerals",
+ ["ro"]="Numereromane",
+ },
+ ["SmallCapped"]={
+ ["cs"]="Kap",
+ ["de"]="Kap",
+ ["en"]="Cap",
+ ["fr"]="Cap",
+ ["it"]="Cap",
+ ["nl"]="Kap",
+ ["pe"]="Cap",
+ ["ro"]="Kap",
+ },
+ ["SmallCaps"]={
+ ["cs"]="Kaps",
+ ["de"]="Kaps",
+ ["en"]="Caps",
+ ["fr"]="Caps",
+ ["it"]="Caps",
+ ["nl"]="Kaps",
+ ["pe"]="Caps",
+ ["ro"]="Kaps",
+ },
+ ["WEEKDAY"]={
+ ["cs"]="VSEDNIDEN",
+ ["de"]="WOCHENTAG",
+ ["en"]="WEEKDAY",
+ ["fr"]="JOURSEMAINE",
+ ["it"]="GIORNOSETTIMANA",
+ ["nl"]="WEEKDAG",
+ ["pe"]="WEEKDAY",
+ ["ro"]="ZIDINSAPTAMANA",
+ },
+ ["WORD"]={
+ ["cs"]="SLOVO",
+ ["de"]="WORT",
+ ["en"]="WORD",
+ ["fr"]="MOT",
+ ["it"]="PAROLA",
+ ["nl"]="WOORD",
+ ["pe"]="WORD",
+ ["ro"]="CUVANT",
+ },
+ ["WORDS"]={
+ ["cs"]="SLOVA",
+ ["de"]="WOERTER",
+ ["en"]="WORDS",
+ ["fr"]="MOTS",
+ ["it"]="PAROLE",
+ ["nl"]="WOORDEN",
+ ["pe"]="WORDS",
+ ["ro"]="CUVINTE",
+ },
+ ["Word"]={
+ ["cs"]="Slovo",
+ ["de"]="Wort",
+ ["en"]="Word",
+ ["fr"]="Mot",
+ ["it"]="Parola",
+ ["nl"]="Woord",
+ ["pe"]="Word",
+ ["ro"]="Cuvant",
+ },
+ ["Words"]={
+ ["cs"]="Slova",
+ ["de"]="Woerter",
+ ["en"]="Words",
+ ["fr"]="Mots",
+ ["it"]="Parole",
+ ["nl"]="Woorden",
+ ["pe"]="Words",
+ ["ro"]="Cuvinte",
+ },
+ ["about"]={
+ ["cs"]="oref",
+ ["de"]="ueber",
+ ["en"]="about",
+ ["fr"]="concernant",
+ ["it"]="intorno",
+ ["nl"]="about",
+ ["pe"]="درمورد",
+ ["ro"]="despre",
+ },
+ ["adaptlayout"]={
+ ["cs"]="prizpusobvzhled",
+ ["de"]="passelayoutan",
+ ["en"]="adaptlayout",
+ ["fr"]="adaptedisposition",
+ ["it"]="adattalayout",
+ ["nl"]="paslayoutaan",
+ ["pe"]="تنظیمطرحبندی",
+ ["ro"]="adapteazaaspect",
+ },
+ ["adding"]={},
+ ["arg"]={
+ ["cs"]="arg",
+ ["de"]="arg",
+ ["en"]="arg",
+ ["fr"]="arg",
+ ["it"]="arg",
+ ["nl"]="arg",
+ ["pe"]="افزودن",
+ ["ro"]="arg",
+ },
+ ["at"]={
+ ["cs"]="pref",
+ ["de"]="bei",
+ ["en"]="at",
+ ["fr"]="a",
+ ["it"]="al",
+ ["nl"]="op",
+ ["pe"]="در",
+ ["ro"]="la",
+ },
+ ["atleftmargin"]={
+ ["cs"]="atleftmargin",
+ ["de"]="atleftmargin",
+ ["en"]="atleftmargin",
+ ["fr"]="atleftmargin",
+ ["it"]="atleftmargin",
+ ["nl"]="oplinkermarge",
+ ["pe"]="درحاشیهچپ",
+ ["ro"]="atleftmargin",
+ },
+ ["atpage"]={
+ ["cs"]="nastrane",
+ ["de"]="aufseite",
+ ["en"]="atpage",
+ ["fr"]="alapage",
+ ["it"]="apagina",
+ ["nl"]="oppagina",
+ ["pe"]="درصفحه",
+ ["ro"]="lapagina",
+ },
+ ["atrightmargin"]={
+ ["cs"]="atrightmargin",
+ ["de"]="atrightmargin",
+ ["en"]="atrightmargin",
+ ["fr"]="atrightmargin",
+ ["it"]="atrightmargin",
+ ["nl"]="oprechtermarge",
+ ["pe"]="درحاشیهراست",
+ ["ro"]="atrightmargin",
+ },
+ ["background"]={
+ ["cs"]="pozadi",
+ ["de"]="hintergrund",
+ ["en"]="background",
+ ["fr"]="arriereplan",
+ ["it"]="sfondo",
+ ["nl"]="achtergrond",
+ ["pe"]="پسزمینه",
+ ["ro"]="fundal",
+ },
+ ["backspace"]={
+ ["cs"]="odsazenizleva",
+ ["de"]="rumpfweite",
+ ["en"]="backspace",
+ ["fr"]="retourarriere",
+ ["it"]="spaziodietro",
+ ["nl"]="rugwit",
+ ["pe"]="فاصلهپشت",
+ ["ro"]="spatiuspate",
+ },
+ ["blackrule"]={
+ ["cs"]="cernalinka",
+ ["de"]="rechteck",
+ ["en"]="blackrule",
+ ["fr"]="lignenoire",
+ ["it"]="lineanera",
+ ["nl"]="blokje",
+ ["pe"]="خطسیاه",
+ ["ro"]="linieneagra",
+ },
+ ["blackrules"]={
+ ["cs"]="cernelinky",
+ ["de"]="rechtecke",
+ ["en"]="blackrules",
+ ["fr"]="lignesnoires",
+ ["it"]="lineenere",
+ ["nl"]="blokjes",
+ ["pe"]="خطهایسیاه",
+ ["ro"]="liniinegre",
+ },
+ ["blank"]={
+ ["cs"]="preskoc",
+ ["de"]="blanko",
+ ["en"]="blank",
+ ["fr"]="vide",
+ ["it"]="rigovuoto",
+ ["nl"]="blanko",
+ ["pe"]="خالی",
+ ["ro"]="blanc",
+ },
+ ["bookmark"]={
+ ["cs"]="zalozka",
+ ["de"]="bookmark",
+ ["en"]="bookmark",
+ ["fr"]="marquepage",
+ ["it"]="segnalibro",
+ ["nl"]="bookmark",
+ ["pe"]="چوبخط",
+ ["ro"]="semncarte",
+ },
+ ["bottomdistance"]={
+ ["cs"]="vzdalenostspodku",
+ ["de"]="abstandunten",
+ ["en"]="bottomdistance",
+ ["fr"]="distanceinf",
+ ["it"]="distanzafondo",
+ ["nl"]="onderafstand",
+ ["pe"]="فاصلهپایین",
+ ["ro"]="distantajos",
+ },
+ ["bottomheight"]={
+ ["cs"]="vyskaspodku",
+ ["de"]="hoeheunten",
+ ["en"]="bottomheight",
+ ["fr"]="hauteurinf",
+ ["it"]="altezzafondo",
+ ["nl"]="onderhoogte",
+ ["pe"]="ارتفاعپایین",
+ ["ro"]="inaltimejos",
+ },
+ ["bottomspace"]={
+ ["cs"]="bottomspace",
+ ["de"]="bottomspace",
+ ["en"]="bottomspace",
+ ["fr"]="espaceinf",
+ ["it"]="spaziofondo",
+ ["nl"]="bodemwit",
+ ["pe"]="فضایپایین",
+ ["ro"]="spatiujos",
+ },
+ ["but"]={
+ ["cs"]="spodek",
+ ["de"]="but",
+ ["en"]="but",
+ ["fr"]="but",
+ ["it"]="fondo",
+ ["nl"]="but",
+ ["pe"]="اما",
+ ["ro"]="but",
+ },
+ ["button"]={
+ ["cs"]="tlacitko",
+ ["de"]="knopf",
+ ["en"]="button",
+ ["fr"]="bouton",
+ ["it"]="pulsante",
+ ["nl"]="button",
+ ["pe"]="دکمه",
+ ["ro"]="buton",
+ },
+ ["bypassblocks"]={
+ ["cs"]="bypassblocks",
+ ["de"]="bypassblocks",
+ ["en"]="bypassblocks",
+ ["fr"]="sauteblocs",
+ ["it"]="saltablocchi",
+ ["nl"]="passeerblokken",
+ ["pe"]="عبوربلوکها",
+ ["ro"]="saripesteblocuri",
+ },
+ ["character"]={
+ ["cs"]="znak",
+ ["de"]="buchstabe",
+ ["en"]="character",
+ ["fr"]="caractere",
+ ["it"]="lettera",
+ ["nl"]="letter",
+ ["pe"]="حرف",
+ ["ro"]="litera",
+ },
+ ["characters"]={
+ ["cs"]="znaky",
+ ["de"]="buchstaben",
+ ["en"]="characters",
+ ["fr"]="caracteres",
+ ["it"]="lettere",
+ ["nl"]="letters",
+ ["pe"]="حرفها",
+ ["ro"]="litere",
+ },
+ ["chem"]={
+ ["cs"]="chem",
+ ["de"]="chem",
+ ["en"]="chem",
+ ["fr"]="chem",
+ ["it"]="chim",
+ ["nl"]="chem",
+ ["pe"]="chem",
+ ["ro"]="chem",
+ },
+ ["clip"]={
+ ["cs"]="orez",
+ ["de"]="ausschnitt",
+ ["en"]="clip",
+ ["fr"]="clip",
+ ["it"]="clip",
+ ["nl"]="clip",
+ ["pe"]="گیره",
+ ["ro"]="clip",
+ },
+ ["clonefield"]={
+ ["cs"]="klonujpole",
+ ["de"]="klonierefeld",
+ ["en"]="clonefield",
+ ["fr"]="clonechamp",
+ ["it"]="clonacampo",
+ ["nl"]="kloonveld",
+ ["pe"]="میدانشبیهسازی",
+ ["ro"]="cloneazacamp",
+ },
+ ["color"]={
+ ["cs"]="barva",
+ ["de"]="farbe",
+ ["en"]="color",
+ ["fr"]="couleur",
+ ["it"]="colore",
+ ["nl"]="kleur",
+ ["pe"]="رنگ",
+ ["ro"]="culoare",
+ },
+ ["colorbar"]={
+ ["cs"]="barevnalista",
+ ["de"]="farbbalken",
+ ["en"]="colorbar",
+ ["fr"]="barrecouleur",
+ ["it"]="barracolori",
+ ["nl"]="kleurenbalk",
+ ["pe"]="میلهرنگ",
+ ["ro"]="baraculoare",
+ },
+ ["colorvalue"]={
+ ["cs"]="hodnotabarvy",
+ ["de"]="farbewert",
+ ["en"]="colorvalue",
+ ["fr"]="valeurcouleur",
+ ["it"]="valorecolore",
+ ["nl"]="kleurwaarde",
+ ["pe"]="مقداررنگ",
+ ["ro"]="valoareculoare",
+ },
+ ["column"]={
+ ["cs"]="sloupec",
+ ["de"]="spalte",
+ ["en"]="column",
+ ["fr"]="colonne",
+ ["it"]="colonna",
+ ["nl"]="kolom",
+ ["pe"]="ستون",
+ ["ro"]="coloana",
+ },
+ ["comment"]={
+ ["cs"]="komentar",
+ ["de"]="kommentar",
+ ["en"]="comment",
+ ["fr"]="commentaire",
+ ["it"]="commento",
+ ["nl"]="commentaar",
+ ["pe"]="توضیح",
+ ["ro"]="comentariu",
+ },
+ ["comparecolorgroup"]={
+ ["cs"]="porovnejskupinubarev",
+ ["de"]="vergleichefarbengruppe",
+ ["en"]="comparecolorgroup",
+ ["fr"]="comparegroupecouleur",
+ ["it"]="confrontagruppocolori",
+ ["nl"]="vergelijkkleurgroep",
+ ["pe"]="مقایسهگروهرنگ",
+ ["ro"]="comparagrupculoare",
+ },
+ ["comparepalet"]={
+ ["cs"]="porovnejpaletu",
+ ["de"]="vergleichepalette",
+ ["en"]="comparepalet",
+ ["fr"]="comparepalette",
+ ["it"]="confrontatavolozza",
+ ["nl"]="vergelijkpalet",
+ ["pe"]="لوحمقایسه",
+ ["ro"]="comparapaleta",
+ },
+ ["completepagenumber"]={
+ ["cs"]="completepagenumber",
+ ["de"]="completepagenumber",
+ ["en"]="completepagenumber",
+ ["fr"]="completenumeropage",
+ ["it"]="numeropaginacompleto",
+ ["nl"]="volledigepaginanummer",
+ ["pe"]="شمارهصفحهکامل",
+ ["ro"]="completeazanumarpagina",
+ },
+ ["completeregister"]={
+ ["cs"]="completeregister",
+ ["de"]="completeregister",
+ ["en"]="completeregister",
+ ["fr"]="completeregistre",
+ ["it"]="completeregister",
+ ["nl"]="volledigregister",
+ ["pe"]="ثبتکامل",
+ ["ro"]="completeregister",
+ },
+ ["component"]={
+ ["cs"]="komponenta",
+ ["de"]="komponente",
+ ["en"]="component",
+ ["fr"]="composant",
+ ["it"]="componenet",
+ ["nl"]="onderdeel",
+ ["pe"]="مولفه",
+ ["ro"]="componenta",
+ },
+ ["convertnumber"]={
+ ["cs"]="konvertujcislo",
+ ["de"]="konvertierezahl",
+ ["en"]="convertnumber",
+ ["fr"]="convertitnumero",
+ ["it"]="convertinumero",
+ ["nl"]="converteernummer",
+ ["pe"]="شمارهمبدل",
+ ["ro"]="convertestenumar",
+ },
+ ["copyfield"]={
+ ["cs"]="kopirujpole",
+ ["de"]="kopierefeld",
+ ["en"]="copyfield",
+ ["fr"]="copitchamp",
+ ["it"]="copiacampo",
+ ["nl"]="copieerveld",
+ ["pe"]="میدانکپی",
+ ["ro"]="copiazacamp",
+ },
+ ["correctwhitespace"]={
+ ["cs"]="korekcebilehomista",
+ ["de"]="korrigierezwischenraum",
+ ["en"]="correctwhitespace",
+ ["fr"]="corrigeespaceblanc",
+ ["it"]="correggispaziobianco",
+ ["nl"]="corrigeerwitruimte",
+ ["pe"]="فضایسفیدصحیح",
+ ["ro"]="corecteazaspatiualb",
+ },
+ ["coupledocument"]={
+ ["cs"]="propojenydokument",
+ ["de"]="verknuepfedokument",
+ ["en"]="coupledocument",
+ ["fr"]="coupledocument",
+ ["it"]="accoppiadocumento",
+ ["nl"]="koppeldocument",
+ ["pe"]="نوشتارزوج",
+ ["ro"]="cupleazadocument",
+ },
+ ["couplemarking"]={
+ ["cs"]="propojeneznaceni",
+ ["de"]="verknuepfebeschriftung",
+ ["en"]="couplemarking",
+ ["fr"]="couplemarquage",
+ ["it"]="accoppiamarcatura",
+ ["nl"]="koppelmarkering",
+ ["pe"]="نشانهگذاریزوج",
+ ["ro"]="cupleazamarcaje",
+ },
+ ["couplepage"]={
+ ["cs"]="parovastrana",
+ ["de"]="doppelseite",
+ ["en"]="couplepage",
+ ["fr"]="pagedouble",
+ ["it"]="accoppiapagina",
+ ["nl"]="koppelpagina",
+ ["pe"]="صفحهزوج",
+ ["ro"]="paginadubla",
+ },
+ ["couplepaper"]={
+ ["cs"]="dvoustrannypapir",
+ ["de"]="doppelseitigespapier",
+ ["en"]="couplepaper",
+ ["fr"]="couplepapier",
+ ["it"]="accoppiacarta",
+ ["nl"]="koppelpapier",
+ ["pe"]="کاغذزوج",
+ ["ro"]="hartiedubla",
+ },
+ ["coupleregister"]={
+ ["cs"]="propojenyrejstrik",
+ ["de"]="verknuepfregister",
+ ["en"]="coupleregister",
+ ["fr"]="coupleregistre",
+ ["it"]="accoppiaregistro",
+ ["nl"]="koppelregister",
+ ["pe"]="ثبتزوج",
+ ["ro"]="cupleazaregistru",
+ },
+ ["crlf"]={
+ ["cs"]="crlf",
+ ["de"]="crlf",
+ ["en"]="crlf",
+ ["fr"]="crlf",
+ ["it"]="crlf",
+ ["nl"]="crlf",
+ ["pe"]="crlf",
+ ["ro"]="crlf",
+ },
+ ["currentdate"]={
+ ["cs"]="aktualnidatum",
+ ["de"]="heutigesdatum",
+ ["en"]="currentdate",
+ ["fr"]="datecourante",
+ ["it"]="datadioggi",
+ ["nl"]="huidigedatum",
+ ["pe"]="تاریخجاری",
+ ["ro"]="datacurenta",
+ },
+ ["currentheadnumber"]={
+ ["cs"]="aktualnicislonadpisu",
+ ["de"]="heutigeskopfnummer",
+ ["en"]="currentheadnumber",
+ ["fr"]="numerotetecourant",
+ ["it"]="numerotestacorrente",
+ ["nl"]="huidigekopnummer",
+ ["pe"]="شمارهسرجاری",
+ ["ro"]="numartitlucurent",
+ },
+ ["cutspace"]={
+ ["cs"]="cutspace",
+ ["de"]="cutspace",
+ ["en"]="cutspace",
+ ["fr"]="cutspace",
+ ["it"]="cutspace",
+ ["nl"]="snijwit",
+ ["pe"]="فضایبرش",
+ ["ro"]="cutspace",
+ },
+ ["date"]={
+ ["cs"]="datum",
+ ["de"]="datum",
+ ["en"]="date",
+ ["fr"]="date",
+ ["it"]="data",
+ ["nl"]="datum",
+ ["pe"]="تاریخ",
+ ["ro"]="data",
+ },
+ ["decouplemarking"]={
+ ["cs"]="rozpojeneznaceni",
+ ["de"]="entknuepfebeschriftung",
+ ["en"]="decouplemarking",
+ ["fr"]="decouplemarquage",
+ ["it"]="separamarcatura",
+ ["nl"]="ontkoppelmarkering",
+ ["pe"]="جداسازینشانهگذاری",
+ ["ro"]="decupleazamarcaje",
+ },
+ ["decrementnumber"]={
+ ["cs"]="decrementnumber",
+ ["de"]="decrementnumber",
+ ["en"]="decrementnumber",
+ ["fr"]="decrementenumero",
+ ["it"]="decrementnumber",
+ ["nl"]="verlaagnummer",
+ ["pe"]="شمارهکاهش",
+ ["ro"]="decrementnumber",
+ },
+ ["define"]={
+ ["cs"]="definuj",
+ ["de"]="definieren",
+ ["en"]="define",
+ ["fr"]="definit",
+ ["it"]="definisci",
+ ["nl"]="definieer",
+ ["pe"]="تعریف",
+ ["ro"]="defineste",
+ },
+ ["defineaccent"]={
+ ["cs"]="definujakcent",
+ ["de"]="definiereakzent",
+ ["en"]="defineaccent",
+ ["fr"]="definitaccent",
+ ["it"]="definisciaccento",
+ ["nl"]="definieeraccent",
+ ["pe"]="تعریفلهجه",
+ ["ro"]="definesteaccent",
+ },
+ ["defineblank"]={
+ ["cs"]="definujpreskok",
+ ["de"]="definiereblanko",
+ ["en"]="defineblank",
+ ["fr"]="definitvide",
+ ["it"]="definiscirigovuoto",
+ ["nl"]="definieerblanko",
+ ["pe"]="تعریفخالی",
+ ["ro"]="definesteblanc",
+ },
+ ["defineblock"]={
+ ["cs"]="definujblok",
+ ["de"]="definiereblock",
+ ["en"]="defineblock",
+ ["fr"]="definitbloc",
+ ["it"]="definisciblocco",
+ ["nl"]="definieerblok",
+ ["pe"]="تعریفبلوک",
+ ["ro"]="definestebloc",
+ },
+ ["definebodyfont"]={
+ ["cs"]="definujzakladnifont",
+ ["de"]="definierefliesstext",
+ ["en"]="definebodyfont",
+ ["fr"]="definitpolicecorps",
+ ["it"]="definiscifontdeltesto",
+ ["nl"]="definieerkorps",
+ ["pe"]="تعریفقلممتن",
+ ["ro"]="definestefonttext",
+ },
+ ["definebodyfontenvironment"]={
+ ["cs"]="definujprostredizakladnihofontu",
+ ["de"]="definierefliesstextumgebung",
+ ["en"]="definebodyfontenvironment",
+ ["fr"]="definitenvironnementpolicecorps",
+ ["it"]="definisciambientefontdeltesto",
+ ["nl"]="definieerkorpsomgeving",
+ ["pe"]="تعریفمحیطقلمبدنه",
+ ["ro"]="definestemediulfonttext",
+ },
+ ["definebuffer"]={
+ ["cs"]="definujbuffer",
+ ["de"]="definierepuffer",
+ ["en"]="definebuffer",
+ ["fr"]="definitbuffer",
+ ["it"]="definiscibuffer",
+ ["nl"]="definieerbuffer",
+ ["pe"]="تعریفبافر",
+ ["ro"]="definestebuffer",
+ },
+ ["definecharacter"]={
+ ["cs"]="definujznak",
+ ["de"]="definierezeichen",
+ ["en"]="definecharacter",
+ ["fr"]="definicaractere",
+ ["it"]="definiscicarattere",
+ ["nl"]="definieerkarakter",
+ ["pe"]="تعریفحرف",
+ ["ro"]="definestecaracter",
+ },
+ ["definecolor"]={
+ ["cs"]="definujbarvu",
+ ["de"]="definierefarbe",
+ ["en"]="definecolor",
+ ["fr"]="definitcouleur",
+ ["it"]="definiscicolore",
+ ["nl"]="definieerkleur",
+ ["pe"]="تعریفرنگ",
+ ["ro"]="definesteculoare",
+ },
+ ["definecolorgroup"]={
+ ["cs"]="definujskupinubarev",
+ ["de"]="definierefarbengruppe",
+ ["en"]="definecolorgroup",
+ ["fr"]="definitgroupecouleur",
+ ["it"]="definiscigruppocolori",
+ ["nl"]="definieerkleurgroep",
+ ["pe"]="تعریفگروهرنگ",
+ ["ro"]="definestegrupculori",
+ },
+ ["definecolumnbreak"]={
+ ["cs"]="definecolumnbreak",
+ ["de"]="definecolumnbreak",
+ ["en"]="definecolumnbreak",
+ ["fr"]="definitsautdecolonne",
+ ["it"]="definecolumnbreak",
+ ["nl"]="definieerkolomovergang",
+ ["pe"]="تعریفشکستنستون",
+ ["ro"]="definecolumnbreak",
+ },
+ ["definecolumnset"]={
+ ["cs"]="definecolumnset",
+ ["de"]="definecolumnset",
+ ["en"]="definecolumnset",
+ ["fr"]="definitjeucolonne",
+ ["it"]="definiscigruppocolonne",
+ ["nl"]="definieerkolomgroep",
+ ["pe"]="تعریفمجموعهستون",
+ ["ro"]="definecolumnset",
+ },
+ ["definecombination"]={
+ ["cs"]="definecombination",
+ ["de"]="definecombination",
+ ["en"]="definecombination",
+ ["fr"]="definecombination",
+ ["it"]="definecombination",
+ ["nl"]="definieercombinatie",
+ ["pe"]="تعریفترکیب",
+ ["ro"]="definecombination",
+ },
+ ["definecombinedlist"]={
+ ["cs"]="definujkombinovanyseznam",
+ ["de"]="definierezusammengestellteliste",
+ ["en"]="definecombinedlist",
+ ["fr"]="definitlisteimbriquee",
+ ["it"]="definiscielencocombinato",
+ ["nl"]="definieersamengesteldelijst",
+ ["pe"]="تعریفلیستترکیبی",
+ ["ro"]="definestelistacombinata",
+ },
+ ["definecommand"]={
+ ["cs"]="definujprikaz",
+ ["de"]="definierebefehl",
+ ["en"]="definecommand",
+ ["fr"]="definitcommande",
+ ["it"]="definiscicomando",
+ ["nl"]="definieercommando",
+ ["pe"]="تعریففرمان",
+ ["ro"]="definestecomanda",
+ },
+ ["defineconversion"]={
+ ["cs"]="definujkonverzi",
+ ["de"]="definierekonversion",
+ ["en"]="defineconversion",
+ ["fr"]="definitconversion",
+ ["it"]="definisciconversione",
+ ["nl"]="definieerconversie",
+ ["pe"]="تعریفتبدیل",
+ ["ro"]="definesteconversie",
+ },
+ ["definedescription"]={
+ ["cs"]="definujpopis",
+ ["de"]="definierebeschreibung",
+ ["en"]="definedescription",
+ ["fr"]="definitdescription",
+ ["it"]="definiscidescrizione",
+ ["nl"]="doordefinieren",
+ ["pe"]="تعریفشرح",
+ ["ro"]="definestedescriere",
+ },
+ ["defineenumeration"]={
+ ["cs"]="definujvycet",
+ ["de"]="definierenummerierung",
+ ["en"]="defineenumeration",
+ ["fr"]="definitenumeration",
+ ["it"]="definiscienumerazione",
+ ["nl"]="doornummeren",
+ ["pe"]="تعریفشمارهبندی",
+ ["ro"]="definesteenumerare",
+ },
+ ["definefield"]={
+ ["cs"]="definujpole",
+ ["de"]="definierefeld",
+ ["en"]="definefield",
+ ["fr"]="definitchamp",
+ ["it"]="definiscicampo",
+ ["nl"]="definieerveld",
+ ["pe"]="تعریفمیدان",
+ ["ro"]="definestecamp",
+ },
+ ["definefieldstack"]={
+ ["cs"]="definujzasobnikpoli",
+ ["de"]="definierefeldstapel",
+ ["en"]="definefieldstack",
+ ["fr"]="definitpilechamp",
+ ["it"]="definiscistackcampi",
+ ["nl"]="definieerveldstapel",
+ ["pe"]="تعریفتودهمیدان",
+ ["ro"]="definestestivacampuri",
+ },
+ ["definefiguresymbol"]={
+ ["cs"]="definujobrazeksymbol",
+ ["de"]="definiereabbsymbol",
+ ["en"]="definefiguresymbol",
+ ["fr"]="definitsymbolefigure",
+ ["it"]="definiscifigurasimbolo",
+ ["nl"]="definieerfiguursymbool",
+ ["pe"]="تعریفنمادشکل",
+ ["ro"]="definestesimbolfigura",
+ },
+ ["definefloat"]={
+ ["cs"]="definujplvouciobjekt",
+ ["de"]="definieregleitobjekt",
+ ["en"]="definefloat",
+ ["fr"]="definitflottant",
+ ["it"]="definiscioggettomobile",
+ ["nl"]="definieerplaatsblok",
+ ["pe"]="تعریفشناور",
+ ["ro"]="definestefloat",
+ },
+ ["definefont"]={
+ ["cs"]="definujfont",
+ ["de"]="definiereschrift",
+ ["en"]="definefont",
+ ["fr"]="definitpolice",
+ ["it"]="definiscifont",
+ ["nl"]="definieerfont",
+ ["pe"]="تعریفقلم",
+ ["ro"]="definestefont",
+ },
+ ["definefontstyle"]={
+ ["cs"]="definujstylfontu",
+ ["de"]="definiereschriftstil",
+ ["en"]="definefontstyle",
+ ["fr"]="definitstylepolice",
+ ["it"]="definiscistilefont",
+ ["nl"]="definieerfontstijl",
+ ["pe"]="تعریفسبکقلم",
+ ["ro"]="definestestilfont",
+ },
+ ["definefontsynonym"]={
+ ["cs"]="definujsynonumumfontu",
+ ["de"]="defineschriftsynonym",
+ ["en"]="definefontsynonym",
+ ["fr"]="definitsynonymepolice",
+ ["it"]="definiscisinonimofont",
+ ["nl"]="definieerfontsynoniem",
+ ["pe"]="تعریفمترادفقلم",
+ ["ro"]="definestesinonimfont",
+ },
+ ["defineframed"]={
+ ["cs"]="definujoramovani",
+ ["de"]="definiereumrahmt",
+ ["en"]="defineframed",
+ ["fr"]="defineframed",
+ ["it"]="definisciincorniciato",
+ ["nl"]="definieeromlijnd",
+ ["pe"]="تعریفقالبی",
+ ["ro"]="definesteinconjurare",
+ },
+ ["defineframedtext"]={
+ ["cs"]="definujoramovanytext",
+ ["de"]="definiereumrahmtertext",
+ ["en"]="defineframedtext",
+ ["fr"]="defineframedtext",
+ ["it"]="definiscitestoincorniciato",
+ ["nl"]="definieerkadertekst",
+ ["pe"]="تعریفمتنقالبی",
+ ["ro"]="definestetextinconjurat",
+ },
+ ["definehbox"]={
+ ["cs"]="definujhbox",
+ ["de"]="definierehbox",
+ ["en"]="definehbox",
+ ["fr"]="definithbox",
+ ["it"]="definiscihbox",
+ ["nl"]="definieerhbox",
+ ["pe"]="تعریفجعبهافقی",
+ ["ro"]="definestehbox",
+ },
+ ["definehead"]={
+ ["cs"]="definujnadpis",
+ ["de"]="definiereueberschrift",
+ ["en"]="definehead",
+ ["fr"]="definittete",
+ ["it"]="definiscitesta",
+ ["nl"]="definieerkop",
+ ["pe"]="تعریفسر",
+ ["ro"]="definesteantet",
+ },
+ ["defineindenting"]={
+ ["cs"]="definujodsazovani",
+ ["de"]="definiereeinzug",
+ ["en"]="defineindenting",
+ ["fr"]="definitcompoalinea",
+ ["it"]="definiscirientro",
+ ["nl"]="doorspringen",
+ ["pe"]="تعریفتورفتگی",
+ ["ro"]="definestealiat",
+ },
+ ["defineinmargin"]={
+ ["cs"]="defineinmargin",
+ ["de"]="defineinmargin",
+ ["en"]="defineinmargin",
+ ["fr"]="definitdansmarge",
+ ["it"]="defineinmargin",
+ ["nl"]="definieerinmarge",
+ ["pe"]="تعریفدرونحاشیه",
+ ["ro"]="defineinmargin",
+ },
+ ["defineinteractionmenu"]={
+ ["cs"]="definujinterakcnimenu",
+ ["de"]="definiereinteraktionsmenue",
+ ["en"]="defineinteractionmenu",
+ ["fr"]="definitmenuinteraction",
+ ["it"]="definiscimenuinterazione",
+ ["nl"]="definieerinteractiemenu",
+ ["pe"]="تعریفمنویپانل",
+ ["ro"]="definestemeniuinteractiune",
+ },
+ ["defineitemgroup"]={
+ ["cs"]="defineitemgroup",
+ ["de"]="defineitemgroup",
+ ["en"]="defineitemgroup",
+ ["fr"]="defineitemgroup",
+ ["it"]="defineitemgroup",
+ ["nl"]="definieeritemgroep",
+ ["pe"]="تعریفگروهآیتم",
+ ["ro"]="defineitemgroup",
+ },
+ ["definelabel"]={
+ ["cs"]="definujpopisek",
+ ["de"]="definierelabel",
+ ["en"]="definelabel",
+ ["fr"]="definitetiquette",
+ ["it"]="definiscietichetta",
+ ["nl"]="doorlabelen",
+ ["pe"]="تعریفبرچسب",
+ ["ro"]="definesteeticheta",
+ },
+ ["definelayer"]={
+ ["cs"]="definelayer",
+ ["de"]="definelayer",
+ ["en"]="definelayer",
+ ["fr"]="definitcalque",
+ ["it"]="definelayer",
+ ["nl"]="definieerlayer",
+ ["pe"]="تعریفلایه",
+ ["ro"]="definelayer",
+ },
+ ["definelayout"]={
+ ["cs"]="definelayout",
+ ["de"]="definelayout",
+ ["en"]="definelayout",
+ ["fr"]="definitdisposition",
+ ["it"]="definiscilayout",
+ ["nl"]="definieerlayout",
+ ["pe"]="تعریفطرحبندی",
+ ["ro"]="definelayout",
+ },
+ ["definelist"]={
+ ["cs"]="definujseznam",
+ ["de"]="definiereliste",
+ ["en"]="definelist",
+ ["fr"]="definitliste",
+ ["it"]="definiscielenco",
+ ["nl"]="definieerlijst",
+ ["pe"]="تعریفلیست",
+ ["ro"]="definestelista",
+ },
+ ["definelogo"]={
+ ["cs"]="definujlogo",
+ ["de"]="definierelogo",
+ ["en"]="definelogo",
+ ["fr"]="definitlogo",
+ ["it"]="definiscilogo",
+ ["nl"]="definieerbeeldmerk",
+ ["pe"]="تعریفآرم",
+ ["ro"]="definestelogo",
+ },
+ ["definemainfield"]={
+ ["cs"]="definujhlavnipole",
+ ["de"]="definierehauptfeld",
+ ["en"]="definemainfield",
+ ["fr"]="definitchampprincipal",
+ ["it"]="definiscicampoprincipale",
+ ["nl"]="definieerhoofdveld",
+ ["pe"]="تعریفمیداناصلی",
+ ["ro"]="definestecampprincipal",
+ },
+ ["definemakeup"]={
+ ["cs"]="definujupravu",
+ ["de"]="definiereumbruch",
+ ["en"]="definemakeup",
+ ["fr"]="definitmakeup",
+ ["it"]="definiscimakeup",
+ ["nl"]="definieeropmaak",
+ ["pe"]="تعریفآرایش",
+ ["ro"]="definestemakeup",
+ },
+ ["definemarking"]={
+ ["cs"]="definujznaceni",
+ ["de"]="definierebeschriftung",
+ ["en"]="definemarking",
+ ["fr"]="definitmarquage",
+ ["it"]="definiscimarcatura",
+ ["nl"]="definieermarkering",
+ ["pe"]="تعریفنشانهگذاری",
+ ["ro"]="definestemarcaje",
+ },
+ ["definemathalignment"]={
+ ["cs"]="definemathalignment",
+ ["de"]="definemathalignment",
+ ["en"]="definemathalignment",
+ ["fr"]="definemathalignment",
+ ["it"]="definemathalignment",
+ ["nl"]="definieerwiskundeuitlijnen",
+ ["pe"]="تعریفتنظیمریاضی",
+ ["ro"]="definemathalignment",
+ },
+ ["defineoutput"]={
+ ["cs"]="definujvystup",
+ ["de"]="defineoutput",
+ ["en"]="defineoutput",
+ ["fr"]="definitsortie",
+ ["it"]="definiscioutput",
+ ["nl"]="definieeruitvoer",
+ ["pe"]="تعریفخروجی",
+ ["ro"]="definesteoutput",
+ },
+ ["defineoverlay"]={
+ ["cs"]="definujprekryv",
+ ["de"]="definiereoverlay",
+ ["en"]="defineoverlay",
+ ["fr"]="definitrevetement",
+ ["it"]="definiscisovrapposizione",
+ ["nl"]="definieeroverlay",
+ ["pe"]="تعریفپوشش",
+ ["ro"]="definesteoverlay",
+ },
+ ["definepagebreak"]={
+ ["cs"]="definepagebreak",
+ ["de"]="definepagebreak",
+ ["en"]="definepagebreak",
+ ["fr"]="definitsautdepage",
+ ["it"]="definepagebreak",
+ ["nl"]="definieerpaginaovergang",
+ ["pe"]="تعریفشکستصفحه",
+ ["ro"]="definepagebreak",
+ },
+ ["definepalet"]={
+ ["cs"]="definujpaletu",
+ ["de"]="definierepalette",
+ ["en"]="definepalet",
+ ["fr"]="definitpalette",
+ ["it"]="definiscitavolozza",
+ ["nl"]="definieerpalet",
+ ["pe"]="تعریفلوح",
+ ["ro"]="definestepaleta",
+ },
+ ["definepapersize"]={
+ ["cs"]="definujvelikostpapiru",
+ ["de"]="definierepapierformat",
+ ["en"]="definepapersize",
+ ["fr"]="definittaillepapier",
+ ["it"]="definiscidimensionicarta",
+ ["nl"]="definieerpapierformaat",
+ ["pe"]="تعریفاندازهبرگ",
+ ["ro"]="definestedimensiunehartie",
+ },
+ ["defineparagraphs"]={
+ ["cs"]="definujodstavce",
+ ["de"]="definiereabsaetze",
+ ["en"]="defineparagraphs",
+ ["fr"]="definitparagraphes",
+ ["it"]="definiscicapoversi",
+ ["nl"]="definieeralineas",
+ ["pe"]="تعریفپاراگرافها",
+ ["ro"]="definesteparagraf",
+ },
+ ["defineplacement"]={
+ ["cs"]="defineplacement",
+ ["de"]="defineplacement",
+ ["en"]="defineplacement",
+ ["fr"]="defineplacement",
+ ["it"]="defineplacement",
+ ["nl"]="definieerplaats",
+ ["pe"]="تعریفجانشانی",
+ ["ro"]="defineplacement",
+ },
+ ["defineprofile"]={
+ ["cs"]="definujprofil",
+ ["de"]="definiereprofil",
+ ["en"]="defineprofile",
+ ["fr"]="definitprofil",
+ ["it"]="definisciprofilo",
+ ["nl"]="definieerprofiel",
+ ["pe"]="تعریفپروفایل",
+ ["ro"]="definesteprofil",
+ },
+ ["defineprogram"]={
+ ["cs"]="definujprogram",
+ ["de"]="definiereprogramme",
+ ["en"]="defineprogram",
+ ["fr"]="definitprogramme",
+ ["it"]="definisciprogramma",
+ ["nl"]="definieerprogramma",
+ ["pe"]="تعریفبرنامه",
+ ["ro"]="definesteprogram",
+ },
+ ["definerawfont"]={
+ ["cs"]="definerawfont",
+ ["de"]="definerawfont",
+ ["en"]="definerawfont",
+ ["fr"]="definitpolicebrute",
+ ["it"]="definiscifontgrezzo",
+ ["nl"]="definerawfont",
+ ["pe"]="تعریفقلمخام",
+ ["ro"]="definestefontraw",
+ },
+ ["definereference"]={
+ ["cs"]="definujodkaz",
+ ["de"]="definierereferenz",
+ ["en"]="definereference",
+ ["fr"]="definitreference",
+ ["it"]="definisciriferimento",
+ ["nl"]="definieerreferentie",
+ ["pe"]="تعریفمرجع",
+ ["ro"]="definestereferinte",
+ },
+ ["definereferenceformat"]={
+ ["cs"]="definujformatodkazu",
+ ["de"]="definierereferenzformat",
+ ["en"]="definereferenceformat",
+ ["fr"]="definitformatreference",
+ ["it"]="definisciformatoriferimento",
+ ["nl"]="definieerreferentieformaat",
+ ["pe"]="تعریفشمایلمرجع",
+ ["ro"]="definesteformatreferinte",
+ },
+ ["definereferencelist"]={
+ ["cs"]="definujseznamodkazu",
+ ["de"]="definierereferenzliste",
+ ["en"]="definereferencelist",
+ ["fr"]="definitlistereference",
+ ["it"]="definiscilistariferimenti",
+ ["nl"]="definieerreferentielijst",
+ ["pe"]="تعریفلیستمرجع",
+ ["ro"]="definestelistareferinte",
+ },
+ ["defineregister"]={
+ ["cs"]="definujrejstrik",
+ ["de"]="definiereregister",
+ ["en"]="defineregister",
+ ["fr"]="definitregistre",
+ ["it"]="definisciregistro",
+ ["nl"]="definieerregister",
+ ["pe"]="تعریفثبت",
+ ["ro"]="definesteregistru",
+ },
+ ["definerule"]={
+ ["cs"]="definerule",
+ ["de"]="definerule",
+ ["en"]="definerule",
+ ["fr"]="definitregle",
+ ["it"]="definiscilinea",
+ ["nl"]="definieerlijn",
+ ["pe"]="تعریفخطحائل",
+ ["ro"]="definesterigla",
+ },
+ ["definesection"]={
+ ["cs"]="definujsekci",
+ ["de"]="definiereabschnitt",
+ ["en"]="definesection",
+ ["fr"]="definitsection",
+ ["it"]="definiscisezione",
+ ["nl"]="definieersectie",
+ ["pe"]="تعریفبخش",
+ ["ro"]="definestesectiune",
+ },
+ ["definesectionblock"]={
+ ["cs"]="definujbloksekce",
+ ["de"]="definiereabschnittsblock",
+ ["en"]="definesectionblock",
+ ["fr"]="definitblocsection",
+ ["it"]="definiscibloccosezione",
+ ["nl"]="definieersectieblok",
+ ["pe"]="تعریفبلوکبخش",
+ ["ro"]="definesteblocsectiune",
+ },
+ ["definesorting"]={
+ ["cs"]="definujtrideni",
+ ["de"]="definieresortieren",
+ ["en"]="definesorting",
+ ["fr"]="definittri",
+ ["it"]="definisciordinamento",
+ ["nl"]="definieersorteren",
+ ["pe"]="تعریفترتیب",
+ ["ro"]="definestesortare",
+ },
+ ["definestartstop"]={
+ ["cs"]="definujstartstop",
+ ["de"]="definierestartstop",
+ ["en"]="definestartstop",
+ ["fr"]="definitdemarrestoppe",
+ ["it"]="definisciiniziatermina",
+ ["nl"]="definieerstartstop",
+ ["pe"]="تعریفشروعپایان",
+ ["ro"]="definestestartstop",
+ },
+ ["definestyle"]={
+ ["cs"]="definujstyl",
+ ["de"]="definierestil",
+ ["en"]="definestyle",
+ ["fr"]="definitstyle",
+ ["it"]="definiscistile",
+ ["nl"]="definieerletter",
+ ["pe"]="تعریفسبک",
+ ["ro"]="definestestil",
+ },
+ ["definesubfield"]={
+ ["cs"]="definujpodpole",
+ ["de"]="definieresubfeld",
+ ["en"]="definesubfield",
+ ["fr"]="definitsouschamp",
+ ["it"]="definiscisottocampo",
+ ["nl"]="definieersubveld",
+ ["pe"]="تعریفزیرمیدان",
+ ["ro"]="definestesubcamp",
+ },
+ ["definesymbol"]={
+ ["cs"]="definujsymbol",
+ ["de"]="definieresymbol",
+ ["en"]="definesymbol",
+ ["fr"]="definitsymbole",
+ ["it"]="definiscisimbolo",
+ ["nl"]="definieersymbool",
+ ["pe"]="تعریفنماد",
+ ["ro"]="definestesimbol",
+ },
+ ["definesynonyms"]={
+ ["cs"]="definujsynonyma",
+ ["de"]="definieresynonyme",
+ ["en"]="definesynonyms",
+ ["fr"]="definitsynonymes",
+ ["it"]="definiscisinonimi",
+ ["nl"]="definieersynoniemen",
+ ["pe"]="تعریفمترادفها",
+ ["ro"]="definestesinonim",
+ },
+ ["definetabletemplate"]={
+ ["cs"]="definujsablonutabulky",
+ ["de"]="definieretabellenvorlage",
+ ["en"]="definetabletemplate",
+ ["fr"]="definittrametableau",
+ ["it"]="definiscimodellotabella",
+ ["nl"]="definieertabelvorm",
+ ["pe"]="تعریفالگویجدول",
+ ["ro"]="definestesablontabel",
+ },
+ ["definetabulate"]={
+ ["cs"]="definujtabelaci",
+ ["de"]="definieretabulator",
+ ["en"]="definetabulate",
+ ["fr"]="definittabulation",
+ ["it"]="definiscitabulato",
+ ["nl"]="definieertabulatie",
+ ["pe"]="تعریفجدولبندی",
+ ["ro"]="definestetabulatori",
+ },
+ ["definetext"]={
+ ["cs"]="definujtext",
+ ["de"]="definieretext",
+ ["en"]="definetext",
+ ["fr"]="definittexte",
+ ["it"]="definiscitesto",
+ ["nl"]="definieertekst",
+ ["pe"]="تعریفمتن",
+ ["ro"]="definestetext",
+ },
+ ["definetextposition"]={
+ ["cs"]="definetextposition",
+ ["de"]="definetextposition",
+ ["en"]="definetextposition",
+ ["fr"]="definitpositiontexte",
+ ["it"]="definisciposizionetesto",
+ ["nl"]="definieertekstpositie",
+ ["pe"]="تعریفمکانمتن",
+ ["ro"]="definestepozitietext",
+ },
+ ["definetextvariable"]={
+ ["cs"]="definetextvariable",
+ ["de"]="definetextvariable",
+ ["en"]="definetextvariable",
+ ["fr"]="definitvariabletexte",
+ ["it"]="definiscivariabiletesto",
+ ["nl"]="definieertekstvariabele",
+ ["pe"]="تعریفمتغیرمتن",
+ ["ro"]="definestevariabilatext",
+ },
+ ["definetype"]={
+ ["cs"]="definetype",
+ ["de"]="definetype",
+ ["en"]="definetype",
+ ["fr"]="definittype",
+ ["it"]="definiscitype",
+ ["nl"]="definieertype",
+ ["pe"]="تعریفتایپ",
+ ["ro"]="definetype",
+ },
+ ["definetyping"]={
+ ["cs"]="definujopis",
+ ["de"]="definieretippen",
+ ["en"]="definetyping",
+ ["fr"]="definitdactylo",
+ ["it"]="definiscityping",
+ ["nl"]="definieertypen",
+ ["pe"]="تعریفتایپکردن",
+ ["ro"]="definestetyping",
+ },
+ ["defineversion"]={
+ ["cs"]="definujverzi",
+ ["de"]="definiereversion",
+ ["en"]="defineversion",
+ ["fr"]="definitversion",
+ ["it"]="definisciversion",
+ ["nl"]="definieerversie",
+ ["pe"]="تعریفنسخه",
+ ["ro"]="definesteversiune",
+ },
+ ["determineheadnumber"]={
+ ["cs"]="stanovcislonadpisu",
+ ["de"]="bestimmekopfnummer",
+ ["en"]="determineheadnumber",
+ ["fr"]="determinenumerotete",
+ ["it"]="determinanumerotesta",
+ ["nl"]="bepaalkopnummer",
+ ["pe"]="تعیینشمارهسر",
+ ["ro"]="determinanumartitlu",
+ },
+ ["determinelistcharacteristics"]={
+ ["cs"]="stanovcharakteristickuseznamu",
+ ["de"]="bestimmelistencharakeristika",
+ ["en"]="determinelistcharacteristics",
+ ["fr"]="determinecaracteristiqueliste",
+ ["it"]="determinacarattersticheelenco",
+ ["nl"]="bepaallijstkenmerken",
+ ["pe"]="تعیینمشخصاتلیست",
+ ["ro"]="determinacaracteristicilelistei",
+ },
+ ["determineregistercharacteristics"]={
+ ["cs"]="urcicharakteristikurejstriku",
+ ["de"]="bestimmeregistercharakteristika",
+ ["en"]="determineregistercharacteristics",
+ ["fr"]="determinecaracteristiquesregistre",
+ ["it"]="determinacaratteristicheregistro",
+ ["nl"]="bepaalregisterkenmerken",
+ ["pe"]="تعیینمشخصاتثبت",
+ ["ro"]="determinacaracteristiciregistru",
+ },
+ ["dimension"]={
+ ["cs"]="rozmer",
+ ["de"]="dimension",
+ ["en"]="dimension",
+ ["fr"]="dimension",
+ ["it"]="dimensione",
+ ["nl"]="dimensie",
+ ["pe"]="بعد",
+ ["ro"]="dimensiune",
+ },
+ ["disableinteractionmenu"]={
+ ["cs"]="zablokujinterakcnimenu",
+ ["de"]="inaktiviereinteraktionsmenue",
+ ["en"]="disableinteractionmenu",
+ ["fr"]="inhibemenuinteraction",
+ ["it"]="disabilitamenuinterazione",
+ ["nl"]="blokkeerinteractiemenu",
+ ["pe"]="ازکارانداختنمنویپانل",
+ ["ro"]="dezactiveazameniuinteractiune",
+ },
+ ["domicile"]={
+ ["cs"]="bydliste",
+ ["de"]="wohnort",
+ ["en"]="domicile",
+ ["fr"]="domicile",
+ ["it"]="domicilio",
+ ["nl"]="woonplaats",
+ ["pe"]="مسکن",
+ ["ro"]="domiciliu",
+ },
+ ["donttest"]={
+ ["cs"]="zadnytest",
+ ["de"]="keintest",
+ ["en"]="donttest",
+ ["fr"]="sanstest",
+ ["it"]="notest",
+ ["nl"]="geentest",
+ ["pe"]="امتحاننکن",
+ ["ro"]="nutesta",
+ },
+ ["edgedistance"]={
+ ["cs"]="vzdalenostokraje",
+ ["de"]="randabstand",
+ ["en"]="edgedistance",
+ ["fr"]="distancebord",
+ ["it"]="distanzabordo",
+ ["nl"]="randafstand",
+ ["pe"]="فاصلهلبه",
+ ["ro"]="distantacolt",
+ },
+ ["edgewidth"]={
+ ["cs"]="sirkaokraje",
+ ["de"]="randbreite",
+ ["en"]="edgewidth",
+ ["fr"]="largeurbord",
+ ["it"]="ampiezzabordo",
+ ["nl"]="randbreedte",
+ ["pe"]="عرضلبه",
+ ["ro"]="latimecolturi",
+ },
+ ["emptylines"]={
+ ["cs"]="emptylines",
+ ["de"]="emptylines",
+ ["en"]="emptylines",
+ ["fr"]="emptylines",
+ ["it"]="emptylines",
+ ["nl"]="legeregels",
+ ["pe"]="خطهاخالی",
+ ["ro"]="emptylines",
+ },
+ ["environment"]={
+ ["cs"]="prostredi",
+ ["de"]="umgebung",
+ ["en"]="environment",
+ ["fr"]="environement",
+ ["it"]="ambiente",
+ ["nl"]="omgeving",
+ ["pe"]="محیط",
+ ["ro"]="mediu",
+ },
+ ["externalfigure"]={
+ ["cs"]="externiobraz",
+ ["de"]="externeabbildung",
+ ["en"]="externalfigure",
+ ["fr"]="figureexterne",
+ ["it"]="figuraesterna",
+ ["nl"]="externfiguur",
+ ["pe"]="شکلخارجی",
+ ["ro"]="figuraexterna",
+ },
+ ["fact"]={
+ ["cs"]="fakt",
+ ["de"]="geg",
+ ["en"]="fact",
+ ["fr"]="fait",
+ ["it"]="fatto",
+ ["nl"]="geg",
+ ["pe"]="حقیقت",
+ ["ro"]="fact",
+ },
+ ["field"]={
+ ["cs"]="pole",
+ ["de"]="feld",
+ ["en"]="field",
+ ["fr"]="champ",
+ ["it"]="campi",
+ ["nl"]="veld",
+ ["pe"]="میدان",
+ ["ro"]="camp",
+ },
+ ["fieldstack"]={
+ ["cs"]="zasobnikpoli",
+ ["de"]="feldstapel",
+ ["en"]="fieldstack",
+ ["fr"]="pilechamp",
+ ["it"]="stackcampi",
+ ["nl"]="veldstapel",
+ ["pe"]="میدانپشته",
+ ["ro"]="stivacampuri",
+ },
+ ["fillinfield"]={
+ ["cs"]="vyplnovepole",
+ ["de"]="ausfuellfeld",
+ ["en"]="fillinfield",
+ ["fr"]="remplitchamp",
+ ["it"]="camporiempimento",
+ ["nl"]="invulveld",
+ ["pe"]="درجدرمیدان",
+ ["ro"]="campumplere",
+ },
+ ["fillinline"]={
+ ["cs"]="vyplnovyradek",
+ ["de"]="gefuelltezeile",
+ ["en"]="fillinline",
+ ["fr"]="remplitligne",
+ ["it"]="rigariempimento",
+ ["nl"]="invulregel",
+ ["pe"]="درجدرخط",
+ ["ro"]="linieumplere",
+ },
+ ["fillinrules"]={
+ ["cs"]="vyplnovelinky",
+ ["de"]="gefuelltesrechteck",
+ ["en"]="fillinrules",
+ ["fr"]="remplitlignesreglees",
+ ["it"]="lineeriempimento",
+ ["nl"]="invullijnen",
+ ["pe"]="درجدرخطها",
+ ["ro"]="rigleumplere",
+ },
+ ["fillintext"]={
+ ["cs"]="vyplnenytext",
+ ["de"]="ausfuelltext",
+ ["en"]="fillintext",
+ ["fr"]="remplittexte",
+ ["it"]="testoriempimento",
+ ["nl"]="invultekst",
+ ["pe"]="درجدرمتن",
+ ["ro"]="textumplere",
+ },
+ ["fitfield"]={
+ ["cs"]="prizpusobivepole",
+ ["de"]="passendfeld",
+ ["en"]="fitfield",
+ ["fr"]="ajustechamp",
+ ["it"]="adattacampo",
+ ["nl"]="passendveld",
+ ["pe"]="پرکردنمیدان",
+ ["ro"]="potrivestecamp",
+ },
+ ["fixedspace"]={
+ ["cs"]="tvrdamezera",
+ ["de"]="festesspatium",
+ ["en"]="fixedspace",
+ ["fr"]="espacefixe",
+ ["it"]="spaziofisso",
+ ["nl"]="vastespatie",
+ ["pe"]="فضایثابت",
+ ["ro"]="spatiufixat",
+ },
+ ["fixedspaces"]={
+ ["cs"]="tvrdemezery",
+ ["de"]="festesspatium",
+ ["en"]="fixedspaces",
+ ["fr"]="espacesfixes",
+ ["it"]="spazifissi",
+ ["nl"]="vastespaties",
+ ["pe"]="فضاهایثابت",
+ ["ro"]="spatiifixate",
+ },
+ ["followprofile"]={
+ ["cs"]="dodrzujprofil",
+ ["de"]="folgeprofil",
+ ["en"]="followprofile",
+ ["fr"]="suivantprofil",
+ ["it"]="seguiprofilo",
+ ["nl"]="volgprofiel",
+ ["pe"]="پیرویپروفایل",
+ ["ro"]="urmeazaprofil",
+ },
+ ["followprofileversion"]={
+ ["cs"]="dodrzujverziprofilu",
+ ["de"]="folgeprofilversion",
+ ["en"]="followprofileversion",
+ ["fr"]="suivantversionprofil",
+ ["it"]="seguiversioneprofilo",
+ ["nl"]="volgprofielversie",
+ ["pe"]="پیروینسخهپروفایل",
+ ["ro"]="urmeazaversiuneprofil",
+ },
+ ["followversion"]={
+ ["cs"]="dodrzujverzi",
+ ["de"]="folgeversion",
+ ["en"]="followversion",
+ ["fr"]="suivantversion",
+ ["it"]="seguiversione",
+ ["nl"]="volgversie",
+ ["pe"]="پیروینسخه",
+ ["ro"]="urmeazaversiune",
+ },
+ ["footerdistance"]={
+ ["cs"]="vzdalenostupati",
+ ["de"]="fusszeileabstand",
+ ["en"]="footerdistance",
+ ["fr"]="distancepdp",
+ ["it"]="distanzapdp",
+ ["nl"]="voetafstand",
+ ["pe"]="فاصلهتهبرگ",
+ ["ro"]="distantasubsol",
+ },
+ ["footerheight"]={
+ ["cs"]="vyskaupati",
+ ["de"]="fusszeilenhoehe",
+ ["en"]="footerheight",
+ ["fr"]="hauteurpdp",
+ ["it"]="altezzapdp",
+ ["nl"]="voethoogte",
+ ["pe"]="ارتفاعتهبرگ",
+ ["ro"]="inaltimesubsol",
+ },
+ ["footnote"]={
+ ["cs"]="poznamkapodcarou",
+ ["de"]="fussnote",
+ ["en"]="footnote",
+ ["fr"]="notepdp",
+ ["it"]="notapdp",
+ ["nl"]="voetnoot",
+ ["pe"]="پانوشت",
+ ["ro"]="notasubsol",
+ },
+ ["footnotetext"]={
+ ["cs"]="footnotetext",
+ ["de"]="footnotetext",
+ ["en"]="footnotetext",
+ ["fr"]="textenotepdp",
+ ["it"]="testonotapdp",
+ ["nl"]="voetnoottekst",
+ ["pe"]="متنپانوشت",
+ ["ro"]="footnotetext",
+ },
+ ["forceblocks"]={
+ ["cs"]="forceblocks",
+ ["de"]="forceblocks",
+ ["en"]="forceblocks",
+ ["fr"]="forceblocs",
+ ["it"]="forzablocchi",
+ ["nl"]="forceerblokken",
+ ["pe"]="اجباربلوکها",
+ ["ro"]="forteazablocuri",
+ },
+ ["formulanumber"]={
+ ["cs"]="cislorovnice",
+ ["de"]="formelnummer",
+ ["en"]="formulanumber",
+ ["fr"]="numeroformule",
+ ["it"]="numeroformula",
+ ["nl"]="formulenummer",
+ ["pe"]="شمارهفرمول",
+ ["ro"]="numarformula",
+ },
+ ["fraction"]={
+ ["cs"]="zlomek",
+ ["de"]="bruch",
+ ["en"]="fraction",
+ ["fr"]="fraction",
+ ["it"]="frazione",
+ ["nl"]="breuk",
+ ["pe"]="کسر",
+ ["ro"]="fractie",
+ },
+ ["framed"]={
+ ["cs"]="oramovani",
+ ["de"]="umrahmt",
+ ["en"]="framed",
+ ["fr"]="framed",
+ ["it"]="incorniciato",
+ ["nl"]="omlijnd",
+ ["pe"]="قالبی",
+ ["ro"]="framed",
+ },
+ ["from"]={
+ ["cs"]="zref",
+ ["de"]="von",
+ ["en"]="from",
+ ["fr"]="de",
+ ["it"]="da",
+ ["nl"]="uit",
+ ["pe"]="از",
+ ["ro"]="din",
+ },
+ ["getbuffer"]={
+ ["cs"]="ziskejbuffer",
+ ["de"]="holepuffer",
+ ["en"]="getbuffer",
+ ["fr"]="prendbuffer",
+ ["it"]="prendibuffer",
+ ["nl"]="haalbuffer",
+ ["pe"]="دریافتبافر",
+ ["ro"]="adubuffer",
+ },
+ ["getmarking"]={
+ ["cs"]="ziskejznaceni",
+ ["de"]="holebeschriftung",
+ ["en"]="getmarking",
+ ["fr"]="obtientmarquage",
+ ["it"]="prendimarcatura",
+ ["nl"]="haalmarkering",
+ ["pe"]="دریافتنشانه",
+ ["ro"]="adumarcaje",
+ },
+ ["getnumber"]={
+ ["cs"]="getnumber",
+ ["de"]="getnumber",
+ ["en"]="getnumber",
+ ["fr"]="getnumber",
+ ["it"]="getnumber",
+ ["nl"]="haalnummer",
+ ["pe"]="دریافتشماره",
+ ["ro"]="getnumber",
+ },
+ ["godown"]={
+ ["cs"]="jdidolu",
+ ["de"]="nachunten",
+ ["en"]="godown",
+ ["fr"]="vaenbas",
+ ["it"]="vaigiu",
+ ["nl"]="omlaag",
+ ["pe"]="بروپایین",
+ ["ro"]="injos",
+ },
+ ["goto"]={
+ ["cs"]="jdina",
+ ["de"]="zu",
+ ["en"]="goto",
+ ["fr"]="va",
+ ["it"]="vaia",
+ ["nl"]="naar",
+ ["pe"]="بروبه",
+ ["ro"]="dute",
+ },
+ ["gotobox"]={
+ ["cs"]="jdinabox",
+ ["de"]="zurbox",
+ ["en"]="gotobox",
+ ["fr"]="vaalaboite",
+ ["it"]="vaiabox",
+ ["nl"]="naarbox",
+ ["pe"]="بروبهجعبه",
+ ["ro"]="dutebox",
+ },
+ ["gotopage"]={
+ ["cs"]="jdinastranu",
+ ["de"]="zurseite",
+ ["en"]="gotopage",
+ ["fr"]="vaalapage",
+ ["it"]="vaiapagina",
+ ["nl"]="naarpagina",
+ ["pe"]="بروبهصفحه",
+ ["ro"]="dutepagina",
+ },
+ ["graycolor"]={
+ ["cs"]="sedabarva",
+ ["de"]="graufarbe",
+ ["en"]="graycolor",
+ ["fr"]="couleurgrise",
+ ["it"]="coloregrigio",
+ ["nl"]="grijskleur",
+ ["pe"]="رنگخاکستری",
+ ["ro"]="culoaregri",
+ },
+ ["greyvalue"]={
+ ["cs"]="hodnotasedi",
+ ["de"]="grauwert",
+ ["en"]="greyvalue",
+ ["fr"]="valeurgris",
+ ["it"]="valoregrigio",
+ ["nl"]="grijswaarde",
+ ["pe"]="مقدارخاکستری",
+ ["ro"]="valoaregri",
+ },
+ ["grid"]={
+ ["cs"]="mrizka",
+ ["de"]="gitter",
+ ["en"]="grid",
+ ["fr"]="grille",
+ ["it"]="griglia",
+ ["nl"]="rooster",
+ ["pe"]="توری",
+ ["ro"]="grid",
+ },
+ ["hairline"]={
+ ["cs"]="vlasovalinka",
+ ["de"]="haarlinie",
+ ["en"]="hairline",
+ ["fr"]="ligneh",
+ ["it"]="capello",
+ ["nl"]="haarlijn",
+ ["pe"]="خطمو",
+ ["ro"]="firdepar",
+ },
+ ["head"]={
+ ["cs"]="nadpis",
+ ["de"]="kopf",
+ ["en"]="head",
+ ["fr"]="tete",
+ ["it"]="testa",
+ ["nl"]="kop",
+ ["pe"]="سر",
+ ["ro"]="titlu",
+ },
+ ["headerdistance"]={
+ ["cs"]="vzdalenostzahlavi",
+ ["de"]="kopfzeilenabstand",
+ ["en"]="headerdistance",
+ ["fr"]="distanceentete",
+ ["it"]="distanzaintestazione",
+ ["nl"]="hoofdafstand",
+ ["pe"]="فاصلهسربرگ",
+ ["ro"]="distantaantet",
+ },
+ ["headerheight"]={
+ ["cs"]="vyskazahlavi",
+ ["de"]="kopfzeilenhoehe",
+ ["en"]="headerheight",
+ ["fr"]="hauteurentete",
+ ["it"]="altezzaintestazione",
+ ["nl"]="hoofdhoogte",
+ ["pe"]="ارتفاعسربرگ",
+ ["ro"]="inaltimeantet",
+ },
+ ["headlevel"]={
+ ["cs"]="hlavniuroven",
+ ["de"]="kopfniveau",
+ ["en"]="headlevel",
+ ["fr"]="niveautete",
+ ["it"]="livellotesta",
+ ["nl"]="kopniveau",
+ ["pe"]="مرحلهسر",
+ ["ro"]="niveltitlu",
+ },
+ ["headnumber"]={
+ ["cs"]="cislonadpisu",
+ ["de"]="kopfnummer",
+ ["en"]="headnumber",
+ ["fr"]="numerotete",
+ ["it"]="numerotesta",
+ ["nl"]="kopnummer",
+ ["pe"]="شمارهسر",
+ ["ro"]="numartitlu",
+ },
+ ["headsym"]={
+ ["cs"]="headsym",
+ ["de"]="headsym",
+ ["en"]="headsym",
+ ["fr"]="headsym",
+ ["it"]="headsym",
+ ["nl"]="kopsym",
+ ["pe"]="نمادسر",
+ ["ro"]="headsym",
+ },
+ ["headtext"]={
+ ["cs"]="texthlavicky",
+ ["de"]="ueberschrifttext",
+ ["en"]="headtext",
+ ["fr"]="textetete",
+ ["it"]="testoinstestazioni",
+ ["nl"]="koptekst",
+ ["pe"]="متنسر",
+ ["ro"]="texttitlu",
+ },
+ ["hideblocks"]={
+ ["cs"]="schovejbloky",
+ ["de"]="verbergebloecke",
+ ["en"]="hideblocks",
+ ["fr"]="cacheblocs",
+ ["it"]="nascondiblocchi",
+ ["nl"]="verbergblokken",
+ ["pe"]="بلوکهاپنهان",
+ ["ro"]="ascundeblocuri",
+ },
+ ["high"]={
+ ["cs"]="vysoky",
+ ["de"]="hoch",
+ ["en"]="high",
+ ["fr"]="haut",
+ ["it"]="ap",
+ ["nl"]="hoog",
+ ["pe"]="بلند",
+ ["ro"]="inalt",
+ },
+ ["hl"]={
+ ["cs"]="hl",
+ ["de"]="hl",
+ ["en"]="hl",
+ ["fr"]="hl",
+ ["it"]="hl",
+ ["nl"]="hl",
+ ["pe"]="خا",
+ ["ro"]="hl",
+ },
+ ["immediatebetweenlist"]={
+ ["cs"]="immediatebetweenlist",
+ ["de"]="immediatebetweenlist",
+ ["en"]="immediatebetweenlist",
+ ["fr"]="immediatebetweenlist",
+ ["it"]="immediatebetweenlist",
+ ["nl"]="directtussenlijst",
+ ["pe"]="فوریبینلیست",
+ ["ro"]="immediatebetweenlist",
+ },
+ ["immediatetolist"]={
+ ["cs"]="immediatetolist",
+ ["de"]="immediatetolist",
+ ["en"]="immediatetolist",
+ ["fr"]="immediatetolist",
+ ["it"]="immediatetolist",
+ ["nl"]="directnaarlijst",
+ ["pe"]="فوریبهلیست",
+ ["ro"]="immediatetolist",
+ },
+ ["in"]={
+ ["cs"]="tref",
+ ["de"]="in",
+ ["en"]="in",
+ ["fr"]="dans",
+ ["it"]="in",
+ ["nl"]="in",
+ ["pe"]="درون",
+ ["ro"]="in",
+ },
+ ["incrementnumber"]={
+ ["cs"]="zvysujicicislo",
+ ["de"]="nummererhoehen",
+ ["en"]="incrementnumber",
+ ["fr"]="incrementenumero",
+ ["it"]="incrementanumero",
+ ["nl"]="verhoognummer",
+ ["pe"]="شمارهافزایش",
+ ["ro"]="numarincrement",
+ },
+ ["indenting"]={
+ ["cs"]="odsazovani",
+ ["de"]="einziehen",
+ ["en"]="indenting",
+ ["fr"]="composeenalinea",
+ ["it"]="rientro",
+ ["nl"]="inspringen",
+ ["pe"]="تورفتگی",
+ ["ro"]="aliniat",
+ },
+ ["inframed"]={
+ ["cs"]="zaramovani",
+ ["de"]="imumriss",
+ ["en"]="inframed",
+ ["fr"]="inframed",
+ ["it"]="circondato",
+ ["nl"]="inlijnd",
+ ["pe"]="درقالبی",
+ ["ro"]="inframed",
+ },
+ ["infull"]={
+ ["cs"]="plnezneni",
+ ["de"]="volleswort",
+ ["en"]="infull",
+ ["fr"]="infull",
+ ["it"]="perlungo",
+ ["nl"]="voluit",
+ ["pe"]="درپر",
+ ["ro"]="pelung",
+ },
+ ["ininner"]={
+ ["cs"]="ininner",
+ ["de"]="ininner",
+ ["en"]="ininner",
+ ["fr"]="ininner",
+ ["it"]="ininner",
+ ["nl"]="inbinnen",
+ ["pe"]="درداخلی",
+ ["ro"]="ininner",
+ },
+ ["inleft"]={
+ ["cs"]="vlevo",
+ ["de"]="imlinken",
+ ["en"]="inleft",
+ ["fr"]="dansgauche",
+ ["it"]="insinistra",
+ ["nl"]="inlinker",
+ ["pe"]="درچپ",
+ ["ro"]="instanga",
+ },
+ ["inleftedge"]={
+ ["cs"]="nalevo",
+ ["de"]="imlinkenrand",
+ ["en"]="inleftedge",
+ ["fr"]="dansbordgauche",
+ ["it"]="inlatosinistro",
+ ["nl"]="inlinkerrand",
+ ["pe"]="درلبهچپ",
+ ["ro"]="inparteastanga",
+ },
+ ["inleftmargin"]={
+ ["cs"]="nalevyokraj",
+ ["de"]="inlinkermarginale",
+ ["en"]="inleftmargin",
+ ["fr"]="dansmargegauche",
+ ["it"]="inmarginesinistro",
+ ["nl"]="inlinkermarge",
+ ["pe"]="درحاشیهچپ",
+ ["ro"]="inmargineastanga",
+ },
+ ["inline"]={
+ ["cs"]="vradku",
+ ["de"]="inzeile",
+ ["en"]="inline",
+ ["fr"]="alaligne",
+ ["it"]="inriga",
+ ["nl"]="inregel",
+ ["pe"]="درخط",
+ ["ro"]="inlinie",
+ },
+ ["inmargin"]={
+ ["cs"]="naokraj",
+ ["de"]="inmarginalie",
+ ["en"]="inmargin",
+ ["fr"]="dansmarge",
+ ["it"]="inmargine",
+ ["nl"]="inmarge",
+ ["pe"]="درحاشیه",
+ ["ro"]="marginal",
+ },
+ ["inmframed"]={
+ ["cs"]="mazaramovani",
+ ["de"]="immaumrise",
+ ["en"]="inmaframed",
+ ["fr"]="inmframed",
+ ["it"]="inmaframed",
+ ["nl"]="inwilijnd",
+ ["pe"]="inmframed",
+ ["ro"]="inmaframed",
+ },
+ ["inneredgedistance"]={
+ ["cs"]="inneredgedistance",
+ ["de"]="inneredgedistance",
+ ["en"]="inneredgedistance",
+ ["fr"]="inneredgedistance",
+ ["it"]="inneredgedistance",
+ ["nl"]="binnenrandafstand",
+ ["pe"]="فاصلهلبهداخلی",
+ ["ro"]="inneredgedistance",
+ },
+ ["inneredgewidth"]={
+ ["cs"]="inneredgewidth",
+ ["de"]="inneredgewidth",
+ ["en"]="inneredgewidth",
+ ["fr"]="inneredgewidth",
+ ["it"]="inneredgewidth",
+ ["nl"]="binnenrandbreedte",
+ ["pe"]="عرضلبهداخلی",
+ ["ro"]="inneredgewidth",
+ },
+ ["innermargindistance"]={
+ ["cs"]="innermargindistance",
+ ["de"]="innermargindistance",
+ ["en"]="innermargindistance",
+ ["fr"]="innermargindistance",
+ ["it"]="innermargindistance",
+ ["nl"]="binnenmargeafstand",
+ ["pe"]="فاصلهحاشیهداخلی",
+ ["ro"]="innermargindistance",
+ },
+ ["innermarginwidth"]={
+ ["cs"]="innermarginwidth",
+ ["de"]="innermarginwidth",
+ ["en"]="innermarginwidth",
+ ["fr"]="innermarginwidth",
+ ["it"]="innermarginwidth",
+ ["nl"]="binnenmargebreedte",
+ ["pe"]="عرضحاشیهداخلی",
+ ["ro"]="innermarginwidth",
+ },
+ ["inothermargin"]={
+ ["cs"]="nadruhyokraj",
+ ["de"]="inanderermarginale",
+ ["en"]="inothermargin",
+ ["fr"]="dansautremarge",
+ ["it"]="inaltromargine",
+ ["nl"]="inanderemarge",
+ ["pe"]="درحاشیهدیگر",
+ ["ro"]="inaltamargine",
+ },
+ ["inouter"]={
+ ["cs"]="inouter",
+ ["de"]="inouter",
+ ["en"]="inouter",
+ ["fr"]="inouter",
+ ["it"]="inouter",
+ ["nl"]="inbuiten",
+ ["pe"]="درخارجی",
+ ["ro"]="inouter",
+ },
+ ["inright"]={
+ ["cs"]="vpravo",
+ ["de"]="imrechten",
+ ["en"]="inright",
+ ["fr"]="dansdroite",
+ ["it"]="indestra",
+ ["nl"]="inrechter",
+ ["pe"]="درراست",
+ ["ro"]="indreapta",
+ },
+ ["inrightedge"]={
+ ["cs"]="napravo",
+ ["de"]="imrechtenrand",
+ ["en"]="inrightedge",
+ ["fr"]="dansborddroit",
+ ["it"]="inlatodestro",
+ ["nl"]="inrechterrand",
+ ["pe"]="درلبهراست",
+ ["ro"]="inparteadreapta",
+ },
+ ["inrightmargin"]={
+ ["cs"]="napravyokraj",
+ ["de"]="inrechtermarginale",
+ ["en"]="inrightmargin",
+ ["fr"]="dansmargedroite",
+ ["it"]="inmarginedestro",
+ ["nl"]="inrechtermarge",
+ ["pe"]="درحاشیهراست",
+ ["ro"]="inmargineadreapta",
+ },
+ ["installlanguage"]={
+ ["cs"]="instalacejazyka",
+ ["de"]="installieresprache",
+ ["en"]="installlanguage",
+ ["fr"]="installelangue",
+ ["it"]="installalingua",
+ ["nl"]="installeertaal",
+ ["pe"]="نصبزبان",
+ ["ro"]="instalarelimba",
+ },
+ ["interactionbar"]={
+ ["cs"]="interakcnilista",
+ ["de"]="interaktionsbalken",
+ ["en"]="interactionbar",
+ ["fr"]="barreinteraction",
+ ["it"]="barrainterazione",
+ ["nl"]="interactiebalk",
+ ["pe"]="میلهپانل",
+ ["ro"]="barainteractiune",
+ },
+ ["interactionbuttons"]={
+ ["cs"]="interakcnitlacitka",
+ ["de"]="interaktionsknopfe",
+ ["en"]="interactionbuttons",
+ ["fr"]="boutonsinteraction",
+ ["it"]="pulsantinterazione",
+ ["nl"]="interactiebuttons",
+ ["pe"]="دکمهپانل",
+ ["ro"]="butoaneinteractiune",
+ },
+ ["interactionmenu"]={
+ ["cs"]="interaktivnimenu",
+ ["de"]="interaktionsmenue",
+ ["en"]="interactionmenu",
+ ["fr"]="menuinteraction",
+ ["it"]="menuinterattivo",
+ ["nl"]="interactiemenu",
+ ["pe"]="منویپانل",
+ ["ro"]="meniuinteractiune",
+ },
+ ["item"]={
+ ["cs"]="polozka",
+ ["de"]="pos",
+ ["en"]="item",
+ ["fr"]="element",
+ ["it"]="elemento",
+ ["nl"]="som",
+ ["pe"]="آیتم",
+ ["ro"]="element",
+ },
+ ["items"]={
+ ["cs"]="polozky",
+ ["de"]="posten",
+ ["en"]="items",
+ ["fr"]="elements",
+ ["it"]="elementi",
+ ["nl"]="items",
+ ["pe"]="آیتمها",
+ ["ro"]="element",
+ },
+ ["its"]={
+ ["cs"]="pol",
+ ["de"]="its",
+ ["en"]="its",
+ ["fr"]="el",
+ ["it"]="el",
+ ["nl"]="its",
+ ["pe"]="its",
+ ["ro"]="el",
+ },
+ ["keepblocks"]={
+ ["cs"]="zachovejbloky",
+ ["de"]="behaltebloecke",
+ ["en"]="keepblocks",
+ ["fr"]="gardeblocs",
+ ["it"]="tieniblocchi",
+ ["nl"]="handhaafblokken",
+ ["pe"]="حفظبلوکها",
+ ["ro"]="pastreazablocuri",
+ },
+ ["label"]={
+ ["cs"]="poppisek",
+ ["de"]="label",
+ ["en"]="label",
+ ["fr"]="etiquette",
+ ["it"]="etichetta",
+ ["nl"]="label",
+ ["pe"]="برچسب",
+ ["ro"]="eticheta",
+ },
+ ["labels"]={
+ ["cs"]="popisky",
+ ["de"]="labels",
+ ["en"]="labels",
+ ["fr"]="etiquettes",
+ ["it"]="etichette",
+ ["nl"]="labels",
+ ["pe"]="برچسبها",
+ ["ro"]="etichete",
+ },
+ ["labeltext"]={
+ ["cs"]="textpopisku",
+ ["de"]="labeltext",
+ ["en"]="labeltext",
+ ["fr"]="labeltexte",
+ ["it"]="testoetichetta",
+ ["nl"]="labeltekst",
+ ["pe"]="متنبرچسب",
+ ["ro"]="texteticheta",
+ },
+ ["language"]={
+ ["cs"]="jazyk",
+ ["de"]="sprache",
+ ["en"]="language",
+ ["fr"]="langue",
+ ["it"]="lingua",
+ ["nl"]="taal",
+ ["pe"]="زبان",
+ ["ro"]="limba",
+ },
+ ["leftaligned"]={
+ ["cs"]="zarovnanovlevo",
+ ["de"]="linksbuendig",
+ ["en"]="leftaligned",
+ ["fr"]="aligneagauche",
+ ["it"]="allineasinistra",
+ ["nl"]="regellinks",
+ ["pe"]="چپچین",
+ ["ro"]="aliniatstanga",
+ },
+ ["leftedgedistance"]={
+ ["cs"]="vzdalenostlevehookraje",
+ ["de"]="abstandlinkerrand",
+ ["en"]="leftedgedistance",
+ ["fr"]="distancebordgauche",
+ ["it"]="distanzabordosinistro",
+ ["nl"]="linkerrandafstand",
+ ["pe"]="فاصلهلبهچپ",
+ ["ro"]="distantacoltstanga",
+ },
+ ["leftedgewidth"]={
+ ["cs"]="sirkalevehookraje",
+ ["de"]="breitelinkerrand",
+ ["en"]="leftedgewidth",
+ ["fr"]="largeurbordgauche",
+ ["it"]="ampiezzabordosinistro",
+ ["nl"]="linkerrandbreedte",
+ ["pe"]="عرضلبهچپ",
+ ["ro"]="latimecoltstanga",
+ },
+ ["leftmargindistance"]={
+ ["cs"]="vzdalenostlevemarginalie",
+ ["de"]="linkemarginalafstand",
+ ["en"]="leftmargindistance",
+ ["fr"]="distancemargegauche",
+ ["it"]="distanzamarginesinistro",
+ ["nl"]="linkermargeafstand",
+ ["pe"]="فاصلهحاشیهچپ",
+ ["ro"]="distantamarginestanga",
+ },
+ ["leftmarginwidth"]={
+ ["cs"]="sirkalevemarginalie",
+ ["de"]="linkemarginalbreite",
+ ["en"]="leftmarginwidth",
+ ["fr"]="largeurmargegauche",
+ ["it"]="ampiezzamarginesinistro",
+ ["nl"]="linkermargebreedte",
+ ["pe"]="عرضحاشیهچپ",
+ ["ro"]="latimemarginestanga",
+ },
+ ["leg"]={
+ ["cs"]="leg",
+ ["de"]="leg",
+ ["en"]="leg",
+ ["fr"]="leg",
+ ["it"]="leg",
+ ["nl"]="leg",
+ ["pe"]="پا",
+ ["ro"]="leg",
+ },
+ ["linewidth"]={
+ ["cs"]="tloustkacary",
+ ["de"]="liniendicke",
+ ["en"]="linethickness",
+ ["fr"]="largeurligne",
+ ["it"]="spessoreriga",
+ ["nl"]="lijndikte",
+ ["pe"]="عرضخط",
+ ["ro"]="grosimelinie",
+ },
+ ["listheight"]={
+ ["cs"]="vyskaseznamu",
+ ["de"]="listenhoehe",
+ ["en"]="listheight",
+ ["fr"]="hauteurliste",
+ ["it"]="altezzaelenco",
+ ["nl"]="lijsthoogte",
+ ["pe"]="ارتفاعخط",
+ ["ro"]="inaltimelista",
+ },
+ ["listlength"]={
+ ["cs"]="delkaseznamu",
+ ["de"]="listenlaenge",
+ ["en"]="listlength",
+ ["fr"]="llongueurliste",
+ ["it"]="lunghezzaelenco",
+ ["nl"]="lijstlengte",
+ ["pe"]="طوللیست",
+ ["ro"]="lungimelista",
+ },
+ ["listsymbol"]={
+ ["cs"]="listsymbol",
+ ["de"]="listsymbol",
+ ["en"]="listsymbol",
+ ["fr"]="listesymbole",
+ ["it"]="listsymbol",
+ ["nl"]="lijstsymbool",
+ ["pe"]="نمادلیست",
+ ["ro"]="listsymbol",
+ },
+ ["listwidth"]={
+ ["cs"]="sirkaseznamu",
+ ["de"]="listenbreite",
+ ["en"]="listwidth",
+ ["fr"]="largeurliste",
+ ["it"]="ampiezzaelenco",
+ ["nl"]="lijstbreedte",
+ ["pe"]="عرضلیست",
+ ["ro"]="latimelista",
+ },
+ ["logfields"]={
+ ["cs"]="zaznamovepole",
+ ["de"]="registrierefelder",
+ ["en"]="logfields",
+ ["fr"]="logchamp",
+ ["it"]="logcampi",
+ ["nl"]="registreervelden",
+ ["pe"]="میدانهایگزارش",
+ ["ro"]="logcampuri",
+ },
+ ["lohi"]={
+ ["cs"]="nivy",
+ ["de"]="tiho",
+ ["en"]="lohi",
+ ["fr"]="baha",
+ ["it"]="pedap",
+ ["nl"]="laho",
+ ["pe"]="پابا",
+ ["ro"]="jossus",
+ },
+ ["low"]={
+ ["cs"]="nizky",
+ ["de"]="tief",
+ ["en"]="low",
+ ["fr"]="bas",
+ ["it"]="ped",
+ ["nl"]="laag",
+ ["pe"]="پایین",
+ ["ro"]="jos",
+ },
+ ["macroname"]={
+ ["cs"]="jmeno",
+ ["de"]="name",
+ ["en"]="name",
+ ["fr"]="nommacro",
+ ["it"]="nome",
+ ["nl"]="naam",
+ ["pe"]="نامماکرو",
+ ["ro"]="nume",
+ },
+ ["mainlanguage"]={
+ ["cs"]="hlavnijazyk",
+ ["de"]="hauptsprache",
+ ["en"]="mainlanguage",
+ ["fr"]="langueprincipale",
+ ["it"]="linguaprincipale",
+ ["nl"]="hoofdtaal",
+ ["pe"]="زباناصلی",
+ ["ro"]="limbaprincipala",
+ },
+ ["makeupheight"]={
+ ["cs"]="vyskasazby",
+ ["de"]="satzhoehe",
+ ["en"]="makeupheight",
+ ["fr"]="hauteurmakeup",
+ ["it"]="altezzamakeup",
+ ["nl"]="zethoogte",
+ ["pe"]="ارتفاعآرایش",
+ ["ro"]="inaltimemakeup",
+ },
+ ["makeupwidth"]={
+ ["cs"]="sirkasazby",
+ ["de"]="satzbreite",
+ ["en"]="makeupwidth",
+ ["fr"]="largeurmakeup",
+ ["it"]="ampiezzamakeup",
+ ["nl"]="zetbreedte",
+ ["pe"]="عرضآرایش",
+ ["ro"]="latimemakeup",
+ },
+ ["mar"]={
+ ["cs"]="okr",
+ ["de"]="mar",
+ ["en"]="mar",
+ ["fr"]="mar",
+ ["it"]="mar",
+ ["nl"]="mar",
+ ["pe"]="حاش",
+ ["ro"]="mar",
+ },
+ ["margindistance"]={
+ ["cs"]="vzdalenostmarginalie",
+ ["de"]="marginalafstand",
+ ["en"]="margindistance",
+ ["fr"]="distancemarge",
+ ["it"]="distanzamargine",
+ ["nl"]="margeafstand",
+ ["pe"]="فاصلهحاشیه",
+ ["ro"]="distantamargine",
+ },
+ ["marginrule"]={
+ ["cs"]="marginalnilinka",
+ ["de"]="marginallinie",
+ ["en"]="marginrule",
+ ["fr"]="margereglee",
+ ["it"]="lineamargine",
+ ["nl"]="kantlijn",
+ ["pe"]="خطحاشیه",
+ ["ro"]="liniemargine",
+ },
+ ["margintext"]={
+ ["cs"]="marginalnitext",
+ ["de"]="marginaltext",
+ ["en"]="margintext",
+ ["fr"]="textemarge",
+ ["it"]="testoinmargine",
+ ["nl"]="margetekst",
+ ["pe"]="متنحاشیه",
+ ["ro"]="textmarginal",
+ },
+ ["margintitle"]={
+ ["cs"]="marginalninadpis",
+ ["de"]="marginaltitel",
+ ["en"]="margintitle",
+ ["fr"]="titremarge",
+ ["it"]="titoloinmargine",
+ ["nl"]="margetitel",
+ ["pe"]="عنوانحاشیه",
+ ["ro"]="titlumarginal",
+ },
+ ["marginwidth"]={
+ ["cs"]="sirkamarginalie",
+ ["de"]="marginalbreite",
+ ["en"]="marginwidth",
+ ["fr"]="largeurmarge",
+ ["it"]="ampiezzamargine",
+ ["nl"]="margebreedte",
+ ["pe"]="عرضحاشیه",
+ ["ro"]="latimemargine",
+ },
+ ["marginword"]={
+ ["cs"]="marginalnislovo",
+ ["de"]="marginalwort",
+ ["en"]="marginword",
+ ["fr"]="motmarge",
+ ["it"]="parolainmargine",
+ ["nl"]="margewoord",
+ ["pe"]="کلمهحاشیه",
+ ["ro"]="cuvantmarginal",
+ },
+ ["marking"]={
+ ["cs"]="znaceni",
+ ["de"]="beschriftung",
+ ["en"]="marking",
+ ["fr"]="marquage",
+ ["it"]="marcatura",
+ ["nl"]="markeer",
+ ["pe"]="نشانهگذاری",
+ ["ro"]="marcaje",
+ },
+ ["markversion"]={
+ ["cs"]="oznacverzi",
+ ["de"]="beschrifteversion",
+ ["en"]="markversion",
+ ["fr"]="marquageversion",
+ ["it"]="marcaversione",
+ ["nl"]="markeerversie",
+ ["pe"]="نسخهنشانه",
+ ["ro"]="marcheazaversiune",
+ },
+ ["mathematics"]={
+ ["cs"]="matematika",
+ ["de"]="mathematik",
+ ["en"]="mathematics",
+ ["fr"]="mathematique",
+ ["it"]="matematica",
+ ["nl"]="wiskunde",
+ ["pe"]="ریاضی",
+ ["ro"]="matematica",
+ },
+ ["menubutton"]={
+ ["cs"]="tlacitkomenu",
+ ["de"]="menueknopf",
+ ["en"]="menubutton",
+ ["fr"]="boutonmenu",
+ ["it"]="pulsantemenu",
+ ["nl"]="menubutton",
+ ["pe"]="دکمهمنو",
+ ["ro"]="butonmeniu",
+ },
+ ["mframed"]={
+ ["cs"]="maoramovani",
+ ["de"]="maumrise",
+ ["en"]="maframed",
+ ["fr"]="mframed",
+ ["it"]="maframed",
+ ["nl"]="wilijnd",
+ ["pe"]="mframed",
+ ["ro"]="maframed",
+ },
+ ["midaligned"]={
+ ["cs"]="zarovnanonastred",
+ ["de"]="zentriert",
+ ["en"]="midaligned",
+ ["fr"]="aligneaumilieu",
+ ["it"]="allineacentro",
+ ["nl"]="regelmidden",
+ ["pe"]="تنظیموسط",
+ ["ro"]="aliniatcentru",
+ },
+ ["mirror"]={
+ ["cs"]="zrcadlit",
+ ["de"]="spiegeln",
+ ["en"]="mirror",
+ ["fr"]="reflete",
+ ["it"]="riflessione",
+ ["nl"]="spiegel",
+ ["pe"]="آینه",
+ ["ro"]="reflexie",
+ },
+ ["month"]={
+ ["cs"]="mesic",
+ ["de"]="monat",
+ ["en"]="month",
+ ["fr"]="mois",
+ ["it"]="mese",
+ ["nl"]="maand",
+ ["pe"]="ماه",
+ ["ro"]="luna",
+ },
+ ["moveformula"]={
+ ["cs"]="moveformula",
+ ["de"]="moveformula",
+ ["en"]="moveformula",
+ ["fr"]="deplaceformule",
+ ["it"]="spostaformula",
+ ["nl"]="verplaatsformule",
+ ["pe"]="انتقالفرمول",
+ ["ro"]="moveformula",
+ },
+ ["moveongrid"]={
+ ["cs"]="premistinamrizku",
+ ["de"]="amgitterneuausrichten",
+ ["en"]="moveongrid",
+ ["fr"]="deplacesurgrille",
+ ["it"]="spostaagriglia",
+ ["nl"]="verplaatsopgrid",
+ ["pe"]="انتقالبهتوری",
+ ["ro"]="mutapegrid",
+ },
+ ["movesidefloat"]={
+ ["cs"]="movesidefloat",
+ ["de"]="movesidefloat",
+ ["en"]="movesidefloat",
+ ["fr"]="movesidefloat",
+ ["it"]="movesidefloat",
+ ["nl"]="verplaatszijblok",
+ ["pe"]="انتقالکنارشناور",
+ ["ro"]="movesidefloat",
+ },
+ ["navigating"]={
+ ["cs"]="navigating",
+ ["de"]="navigating",
+ ["en"]="navigating",
+ ["fr"]="navigating",
+ ["it"]="navigating",
+ ["nl"]="navigerend",
+ ["pe"]="هدایت",
+ ["ro"]="navigating",
+ },
+ ["nodimension"]={
+ ["cs"]="zadnyrozmer",
+ ["de"]="keindimension",
+ ["en"]="nodimension",
+ ["fr"]="sansdimension",
+ ["it"]="nientedimensioni",
+ ["nl"]="geendimensie",
+ ["pe"]="بدونبعد",
+ ["ro"]="faradimensiune",
+ },
+ ["noheaderandfooterlines"]={
+ ["cs"]="zadnezahlaviaupati",
+ ["de"]="keinekopfundfusszeilen",
+ ["en"]="noheaderandfooterlines",
+ ["fr"]="sanslignesenteteetpdp",
+ ["it"]="nientelineintestazionepdp",
+ ["nl"]="geenhoofdenvoetregels",
+ ["pe"]="بدونخطسروتهبرگ",
+ ["ro"]="faraliniiantetsisubsol",
+ },
+ ["noindenting"]={
+ ["cs"]="zadneodsazovani",
+ ["de"]="nichteinziehen",
+ ["en"]="noindenting",
+ ["fr"]="sansalinea",
+ ["it"]="nienterientro",
+ ["nl"]="nietinspringen",
+ ["pe"]="بدونتورفتگی",
+ ["ro"]="faraaliniat",
+ },
+ ["nolist"]={
+ ["cs"]="zadnyseznam",
+ ["de"]="keineliste",
+ ["en"]="nolist",
+ ["fr"]="sansliste",
+ ["it"]="nienteelenco",
+ ["nl"]="geenlijst",
+ ["pe"]="بدونلیست",
+ ["ro"]="faralista",
+ },
+ ["nomarking"]={
+ ["cs"]="zadneznaceni",
+ ["de"]="keinebeschriftung",
+ ["en"]="nomarking",
+ ["fr"]="sansmarquage",
+ ["it"]="nientemarcatura",
+ ["nl"]="geenmarkering",
+ ["pe"]="بدوننشانهگذاری",
+ ["ro"]="faramarcaje",
+ },
+ ["nomoreblocks"]={
+ ["cs"]="zadnedalsibloky",
+ ["de"]="keinebloeckemehr",
+ ["en"]="nomoreblocks",
+ ["fr"]="pasplusdeblocs",
+ ["it"]="bastablocchi",
+ ["nl"]="geenblokkenmeer",
+ ["pe"]="بدونبلوکهایبیشتر",
+ ["ro"]="gatablocuri",
+ },
+ ["nomorefiles"]={
+ ["cs"]="zadnedalsisoubory",
+ ["de"]="keinedateienmehr",
+ ["en"]="nomorefiles",
+ ["fr"]="pasplusdefichiers",
+ ["it"]="bastafile",
+ ["nl"]="geenfilesmeer",
+ ["pe"]="بدونفایلهایبیشتر",
+ ["ro"]="farafisiere",
+ },
+ ["nop"]={
+ ["cs"]="nop",
+ ["de"]="nop",
+ ["en"]="nop",
+ ["fr"]="nop",
+ ["it"]="nop",
+ ["nl"]="nop",
+ ["pe"]="منفی",
+ ["ro"]="nop",
+ },
+ ["nospace"]={
+ ["cs"]="zadnamezera",
+ ["de"]="keinspatium",
+ ["en"]="nospace",
+ ["fr"]="sansespace",
+ ["it"]="nientespazio",
+ ["nl"]="geenspatie",
+ ["pe"]="بدونفضا",
+ ["ro"]="faraspatiu",
+ },
+ ["note"]={
+ ["cs"]="poznamka",
+ ["de"]="notiz",
+ ["en"]="note",
+ ["fr"]="note",
+ ["it"]="nota",
+ ["nl"]="noot",
+ ["pe"]="یادداشت",
+ ["ro"]="nota",
+ },
+ ["notopandbottomlines"]={
+ ["cs"]="zadnehorniadolniradky",
+ ["de"]="keinzeilenobenundunten",
+ ["en"]="notopandbottomlines",
+ ["fr"]="sanslignessupetinf",
+ ["it"]="nientelineecimafondo",
+ ["nl"]="geenbovenenonderregels",
+ ["pe"]="بدونخطبالاوپایین",
+ ["ro"]="faraliniisussijos",
+ },
+ ["notsmallcapped"]={
+ ["cs"]="nokap",
+ ["de"]="nokap",
+ ["en"]="nocap",
+ ["fr"]="nocap",
+ ["it"]="nocap",
+ ["nl"]="nokap",
+ ["pe"]="سرپوشکوچکنه",
+ ["ro"]="nokap",
+ },
+ ["nowhitespace"]={
+ ["cs"]="zadnebilemisto",
+ ["de"]="keinzwischenraum",
+ ["en"]="nowhitespace",
+ ["fr"]="sansespaceblanc",
+ ["it"]="nientespaziobianco",
+ ["nl"]="geenwitruimte",
+ ["pe"]="بدونفضایسفید",
+ ["ro"]="faraspatiualb",
+ },
+ ["numberofsubpages"]={
+ ["cs"]="numberofsubpages",
+ ["de"]="numberofsubpages",
+ ["en"]="numberofsubpages",
+ ["fr"]="nombredesouspages",
+ ["it"]="numberofsubpages",
+ ["nl"]="aantalsubpaginas",
+ ["pe"]="شمارهزیرصفحه",
+ ["ro"]="numberofsubpages",
+ },
+ ["numbers"]={
+ ["cs"]="cisla",
+ ["de"]="ziffern",
+ ["en"]="numbers",
+ ["fr"]="numeros",
+ ["it"]="numeri",
+ ["nl"]="cijfers",
+ ["pe"]="شمارهها",
+ ["ro"]="numere",
+ },
+ ["outeredgedistance"]={
+ ["cs"]="outeredgedistance",
+ ["de"]="outeredgedistance",
+ ["en"]="outeredgedistance",
+ ["fr"]="outeredgedistance",
+ ["it"]="outeredgedistance",
+ ["nl"]="buitenrandafstand",
+ ["pe"]="فاصلهلبهخارجی",
+ ["ro"]="outeredgedistance",
+ },
+ ["outeredgewidth"]={
+ ["cs"]="outeredgewidth",
+ ["de"]="outeredgewidth",
+ ["en"]="outeredgewidth",
+ ["fr"]="outeredgewidth",
+ ["it"]="outeredgewidth",
+ ["nl"]="buitenrandbreedte",
+ ["pe"]="عرضلبهخارجی",
+ ["ro"]="outeredgewidth",
+ },
+ ["outermargindistance"]={
+ ["cs"]="outermargindistance",
+ ["de"]="outermargindistance",
+ ["en"]="outermargindistance",
+ ["fr"]="outermargindistance",
+ ["it"]="outermargindistance",
+ ["nl"]="buitenmargeafstand",
+ ["pe"]="فاصلهحاشیهخارجی",
+ ["ro"]="outermargindistance",
+ },
+ ["outermarginwidth"]={
+ ["cs"]="outermarginwidth",
+ ["de"]="outermarginwidth",
+ ["en"]="outermarginwidth",
+ ["fr"]="outermarginwidth",
+ ["it"]="outermarginwidth",
+ ["nl"]="buitenmargebreedte",
+ ["pe"]="عرضحاشیهخارجی",
+ ["ro"]="outermarginwidth",
+ },
+ ["packed"]={
+ ["cs"]="zhustene",
+ ["de"]="kleinerdurchschuss",
+ ["en"]="packed",
+ ["fr"]="groupe",
+ ["it"]="impaccato",
+ ["nl"]="opelkaar",
+ ["pe"]="فشرده",
+ ["ro"]="impachetat",
+ },
+ ["page"]={
+ ["cs"]="strana",
+ ["de"]="seite",
+ ["en"]="page",
+ ["fr"]="page",
+ ["it"]="pagina",
+ ["nl"]="pagina",
+ ["pe"]="صفحه",
+ ["ro"]="pagina",
+ },
+ ["pagedepth"]={
+ ["cs"]="pagedepth",
+ ["de"]="pagedepth",
+ ["en"]="pagedepth",
+ ["fr"]="pagedepth",
+ ["it"]="pagedepth",
+ ["nl"]="paginadiepte",
+ ["pe"]="عمقصفحه",
+ ["ro"]="pagedepth",
+ },
+ ["pagenumber"]={
+ ["cs"]="cislostrany",
+ ["de"]="seitenummer",
+ ["en"]="pagenumber",
+ ["fr"]="numeropage",
+ ["it"]="numeropagina",
+ ["nl"]="paginanummer",
+ ["pe"]="شمارهصفحه",
+ ["ro"]="numarpagina",
+ },
+ ["pageoffset"]={
+ ["cs"]="pageoffset",
+ ["de"]="pageoffset",
+ ["en"]="pageoffset",
+ ["fr"]="pageoffset",
+ ["it"]="pageoffset",
+ ["nl"]="paginaoffset",
+ ["pe"]="آفستصفحه",
+ ["ro"]="pageoffset",
+ },
+ ["pagereference"]={
+ ["cs"]="odkaznastranu",
+ ["de"]="seitenreferenz",
+ ["en"]="pagereference",
+ ["fr"]="referencepage",
+ ["it"]="riferimentopagina",
+ ["nl"]="paginareferentie",
+ ["pe"]="مرجعصفحه",
+ ["ro"]="referintapagina",
+ },
+ ["pagetype"]={
+ ["cs"]="typstrany",
+ ["de"]="seitentyp",
+ ["en"]="pagetype",
+ ["fr"]="tapepage",
+ ["it"]="tipopagina",
+ ["nl"]="soortpagina",
+ ["pe"]="نوعصفحه",
+ ["ro"]="tippagina",
+ },
+ ["paperheight"]={
+ ["cs"]="vyskapapiru",
+ ["de"]="papierhoehe",
+ ["en"]="paperheight",
+ ["fr"]="hauteurpapier",
+ ["it"]="altezzacarta",
+ ["nl"]="papierhoogte",
+ ["pe"]="ارتفاعبرگ",
+ ["ro"]="inaltimehartie",
+ },
+ ["paperwidth"]={
+ ["cs"]="sirkapapiru",
+ ["de"]="papierbreite",
+ ["en"]="paperwidth",
+ ["fr"]="largeurpapier",
+ ["it"]="ampiezzacarta",
+ ["nl"]="papierbreedte",
+ ["pe"]="عرضبرگ",
+ ["ro"]="latimehartie",
+ },
+ ["periods"]={
+ ["cs"]="tecky",
+ ["de"]="punkt",
+ ["en"]="periods",
+ ["fr"]="periodes",
+ ["it"]="punti",
+ ["nl"]="punten",
+ ["pe"]="نقطهها",
+ ["ro"]="puncte",
+ },
+ ["plaatsruwelijst"]={
+ ["cs"]="placerawlist",
+ ["de"]="placerawlist",
+ ["en"]="placerawlist",
+ ["fr"]="placerawlist",
+ ["it"]="placerawlist",
+ ["nl"]="plaatsruwelijst",
+ ["pe"]="درجلیستخام",
+ ["ro"]="placerawlist",
+ },
+ ["placebookmarks"]={
+ ["cs"]="umistizalozky",
+ ["de"]="platzierebookmarks",
+ ["en"]="placebookmarks",
+ ["fr"]="placemarquespages",
+ ["it"]="mettisegnalibro",
+ ["nl"]="plaatsbookmarks",
+ ["pe"]="درجچوبخط",
+ ["ro"]="plaseazasemnecarte",
+ },
+ ["placecombinedlist"]={
+ ["cs"]="umistikombinovanyseznam",
+ ["de"]="platzierezusammengestellteliste",
+ ["en"]="placecombinedlist",
+ ["fr"]="placelisteinmbriquee",
+ ["it"]="mettielencocombinato",
+ ["nl"]="plaatssamengesteldelijst",
+ ["pe"]="درجلیستمختلط",
+ ["ro"]="punelistacombinata",
+ },
+ ["placefloat"]={
+ ["cs"]="placefloat",
+ ["de"]="placefloat",
+ ["en"]="placefloat",
+ ["fr"]="placeflottant",
+ ["it"]="placefloat",
+ ["nl"]="plaatsplaatsblok",
+ ["pe"]="درجشناور",
+ ["ro"]="placefloat",
+ },
+ ["placefootnotes"]={
+ ["cs"]="umistipoznamkypodcarou",
+ ["de"]="platzierefussnoten",
+ ["en"]="placefootnotes",
+ ["fr"]="placenotespdp",
+ ["it"]="mettinotepdp",
+ ["nl"]="plaatsvoetnoten",
+ ["pe"]="درجپانوشتها",
+ ["ro"]="punenotesubsol",
+ },
+ ["placeformula"]={
+ ["cs"]="umistirovnici",
+ ["de"]="platziereformel",
+ ["en"]="placeformula",
+ ["fr"]="placeformule",
+ ["it"]="mettiformula",
+ ["nl"]="plaatsformule",
+ ["pe"]="درجفرمول",
+ ["ro"]="puneformula",
+ },
+ ["placeheadnumber"]={
+ ["cs"]="placeheadnumber",
+ ["de"]="placeheadnumber",
+ ["en"]="placeheadnumber",
+ ["fr"]="placenumerotete",
+ ["it"]="posizionanumerotesta",
+ ["nl"]="plaatskopnummer",
+ ["pe"]="درجشمارهسر",
+ ["ro"]="placeheadnumber",
+ },
+ ["placeheadtext"]={
+ ["cs"]="placeheadtext",
+ ["de"]="placeheadtext",
+ ["en"]="placeheadtext",
+ ["fr"]="placetextetete",
+ ["it"]="posizionatestotesta",
+ ["nl"]="plaatskoptekst",
+ ["pe"]="درجمتنسر",
+ ["ro"]="placeheadtext",
+ },
+ ["placelegend"]={
+ ["cs"]="umistilegendu",
+ ["de"]="platzierelegende",
+ ["en"]="placelegend",
+ ["fr"]="placelegende",
+ ["it"]="mettilegenda",
+ ["nl"]="plaatslegenda",
+ ["pe"]="درجراهنما",
+ ["ro"]="punelegenda",
+ },
+ ["placelist"]={
+ ["cs"]="umistiseznam",
+ ["de"]="platziereliste",
+ ["en"]="placelist",
+ ["fr"]="placeliste",
+ ["it"]="mettielenco",
+ ["nl"]="plaatslijst",
+ ["pe"]="درجلیست",
+ ["ro"]="punelista",
+ },
+ ["placelocalfootnotes"]={
+ ["cs"]="umistilokalnipoznamkypodcarou",
+ ["de"]="platzierelokalefussnoten",
+ ["en"]="placelocalfootnotes",
+ ["fr"]="placenotespdplocales",
+ ["it"]="mettinotepdplocali",
+ ["nl"]="plaatslokalevoetnoten",
+ ["pe"]="درجپانوشتهایموضعی",
+ ["ro"]="punenotesubsollocale",
+ },
+ ["placelogos"]={
+ ["cs"]="umistiloga",
+ ["de"]="platzierelogo",
+ ["en"]="placelogos",
+ ["fr"]="placelogos",
+ ["it"]="mettiloghi",
+ ["nl"]="plaatsbeeldmerken",
+ ["pe"]="درجآرمها",
+ ["ro"]="punelogouri",
+ },
+ ["placeongrid"]={
+ ["cs"]="umistinamrizku",
+ ["de"]="amgitterausrichten",
+ ["en"]="placeongrid",
+ ["fr"]="placesurgrille",
+ ["it"]="mettiingriglia",
+ ["nl"]="plaatsopgrid",
+ ["pe"]="درجدرتوری",
+ ["ro"]="plaseazapegrid",
+ },
+ ["placeontopofeachother"]={
+ ["cs"]="umistinadsebe",
+ ["de"]="platziereuntereinander",
+ ["en"]="placeontopofeachother",
+ ["fr"]="placelesunsaudessusdesautres",
+ ["it"]="mettiunosullaltro",
+ ["nl"]="plaatsonderelkaar",
+ ["pe"]="درجدربالاییکدیگر",
+ ["ro"]="punedeasuprafiecareia",
+ },
+ ["placepagenumber"]={
+ ["cs"]="placepagenumber",
+ ["de"]="placepagenumber",
+ ["en"]="placepagenumber",
+ ["fr"]="placenumeropage",
+ ["it"]="mettinumeropagina",
+ ["nl"]="plaatspaginanummer",
+ ["pe"]="درجشمارهصفحه",
+ ["ro"]="punenumarpagina",
+ },
+ ["placereferencelist"]={
+ ["cs"]="placereferencelist",
+ ["de"]="placereferencelist",
+ ["en"]="placereferencelist",
+ ["fr"]="placelistereference",
+ ["it"]="placereferencelist",
+ ["nl"]="plaatsreferentielijst",
+ ["pe"]="درجلیستمرجع",
+ ["ro"]="placereferencelist",
+ },
+ ["placeregister"]={
+ ["cs"]="umistirejstrik",
+ ["de"]="platziereregister",
+ ["en"]="placeregister",
+ ["fr"]="placeregistre",
+ ["it"]="mettiregistro",
+ ["nl"]="plaatsregister",
+ ["pe"]="درجثبت",
+ ["ro"]="puneregistru",
+ },
+ ["placerule"]={
+ ["cs"]="placerule",
+ ["de"]="placerule",
+ ["en"]="placerule",
+ ["fr"]="placeregle",
+ ["it"]="mettilinea",
+ ["nl"]="plaatslijn",
+ ["pe"]="درجخط",
+ ["ro"]="punerigla",
+ },
+ ["placesidebyside"]={
+ ["cs"]="umistivedlesebe",
+ ["de"]="platzierenebeneinander",
+ ["en"]="placesidebyside",
+ ["fr"]="placecoteacote",
+ ["it"]="mettifiancoafianco",
+ ["nl"]="plaatsnaastelkaar",
+ ["pe"]="درجکناربهکنار",
+ ["ro"]="punefatainfata",
+ },
+ ["placesubformula"]={
+ ["cs"]="umistipodrovnici",
+ ["de"]="platziereunterformel",
+ ["en"]="placesubformula",
+ ["fr"]="placesousformule",
+ ["it"]="mettisottoformula",
+ ["nl"]="plaatssubformule",
+ ["pe"]="درجزیرفرمول",
+ ["ro"]="punesubformula",
+ },
+ ["placetextvariable"]={
+ ["cs"]="placetextvariable",
+ ["de"]="placetextvariable",
+ ["en"]="placetextvariable",
+ ["fr"]="placevariabletexte",
+ ["it"]="mettivariabiletesto",
+ ["nl"]="plaatstekstvariabele",
+ ["pe"]="درجمتغیرمتن",
+ ["ro"]="punevariabilatext",
+ },
+ ["position"]={
+ ["cs"]="pozice",
+ ["de"]="position",
+ ["en"]="position",
+ ["fr"]="position",
+ ["it"]="posizione",
+ ["nl"]="positioneer",
+ ["pe"]="مکان",
+ ["ro"]="pozitie",
+ },
+ ["positiontext"]={
+ ["cs"]="positiontext",
+ ["de"]="positiontext",
+ ["en"]="positiontext",
+ ["fr"]="positionnetexte",
+ ["it"]="posizionatesto",
+ ["nl"]="positioneertekst",
+ ["pe"]="مکانمتن",
+ ["ro"]="pozitietext",
+ },
+ ["printpaperheight"]={
+ ["cs"]="vyskatiskpapiru",
+ ["de"]="printpapierhoehe",
+ ["en"]="printpaperheight",
+ ["fr"]="hauteureditionpapier",
+ ["it"]="altezzacartastampa",
+ ["nl"]="printpapierhoogte",
+ ["pe"]="چاپارتفاعبرگ",
+ ["ro"]="inaltimehartieimprimanta",
+ },
+ ["printpaperwidth"]={
+ ["cs"]="sirkatiskpapiru",
+ ["de"]="printpapierbreite",
+ ["en"]="printpaperwidth",
+ ["fr"]="largeureditionpapier",
+ ["it"]="ampiezzacartastampa",
+ ["nl"]="printpapierbreedte",
+ ["pe"]="چاپعرضبرگ",
+ ["ro"]="latimehartieimprimanta",
+ },
+ ["processblocks"]={
+ ["cs"]="zpracujbloky",
+ ["de"]="bearbeitebloecke",
+ ["en"]="processblocks",
+ ["fr"]="traiteblocs",
+ ["it"]="elaborablocchi",
+ ["nl"]="verwerkblokken",
+ ["pe"]="بلوکهایپردازش",
+ ["ro"]="proceseazabloc",
+ },
+ ["processpage"]={
+ ["cs"]="zpracujstranu",
+ ["de"]="bearbeiteseite",
+ ["en"]="processpage",
+ ["fr"]="traitepage",
+ ["it"]="elaborapagina",
+ ["nl"]="verwerkpagina",
+ ["pe"]="صفحهپردازش",
+ ["ro"]="proceseazapagina",
+ },
+ ["product"]={
+ ["cs"]="produkt",
+ ["de"]="produkt",
+ ["en"]="product",
+ ["fr"]="produit",
+ ["it"]="prodotto",
+ ["nl"]="produkt",
+ ["pe"]="تولید",
+ ["ro"]="produs",
+ },
+ ["program"]={
+ ["cs"]="program",
+ ["de"]="programm",
+ ["en"]="program",
+ ["fr"]="programme",
+ ["it"]="programma",
+ ["nl"]="programma",
+ ["pe"]="برنامه",
+ ["ro"]="program",
+ },
+ ["project"]={
+ ["cs"]="projekt",
+ ["de"]="projekt",
+ ["en"]="project",
+ ["fr"]="projet",
+ ["it"]="progetto",
+ ["nl"]="projekt",
+ ["pe"]="پروژه",
+ ["ro"]="proiect",
+ },
+ ["publication"]={
+ ["cs"]="publikace",
+ ["de"]="publikation",
+ ["en"]="publication",
+ ["fr"]="publication",
+ ["it"]="pubblicazione",
+ ["nl"]="publicatie",
+ ["pe"]="نشر",
+ ["ro"]="publicatie",
+ },
+ ["quotation"]={
+ ["cs"]="citace",
+ ["de"]="zitat",
+ ["en"]="quotation",
+ ["fr"]="citation",
+ ["it"]="citazione",
+ ["nl"]="citaat",
+ ["pe"]="نقلقول",
+ ["ro"]="citat",
+ },
+ ["quote"]={
+ ["cs"]="citovat",
+ ["de"]="zitieren",
+ ["en"]="quote",
+ ["fr"]="citer",
+ ["it"]="menzione",
+ ["nl"]="citeer",
+ ["pe"]="نقل",
+ ["ro"]="minicitat",
+ },
+ ["ran"]={
+ ["cs"]="ran",
+ ["de"]="ran",
+ ["en"]="ran",
+ ["fr"]="ran",
+ ["it"]="ran",
+ ["nl"]="ran",
+ ["pe"]="ran",
+ ["ro"]="ran",
+ },
+ ["redo"]={
+ ["cs"]="opakovat",
+ ["de"]="wiederholen",
+ ["en"]="redo",
+ ["fr"]="refait",
+ ["it"]="rifai",
+ ["nl"]="herhaal",
+ ["pe"]="انجامدوباره",
+ ["ro"]="refa",
+ },
+ ["ref"]={
+ ["cs"]="ref",
+ ["de"]="ref",
+ ["en"]="ref",
+ ["fr"]="ref",
+ ["it"]="rif",
+ ["nl"]="ref",
+ ["pe"]="رج",
+ ["ro"]="ref",
+ },
+ ["reference"]={
+ ["cs"]="odkaz",
+ ["de"]="referenz",
+ ["en"]="reference",
+ ["fr"]="reference",
+ ["it"]="riferimento",
+ ["nl"]="referentie",
+ ["pe"]="مرجع",
+ ["ro"]="referinta",
+ },
+ ["referral"]={
+ ["cs"]="odkaz",
+ ["de"]="verweis",
+ ["en"]="referral",
+ ["fr"]="recommandation",
+ ["it"]="referral",
+ ["nl"]="kenmerk",
+ ["pe"]="رجوع",
+ ["ro"]="referit",
+ },
+ ["referraldate"]={
+ ["cs"]="odkaznadatum",
+ ["de"]="verweisdatum",
+ ["en"]="referraldate",
+ ["fr"]="daterecommandation",
+ ["it"]="datareferral",
+ ["nl"]="kenmerkdatum",
+ ["pe"]="تاریخرجوع",
+ ["ro"]="datareferit",
+ },
+ ["referring"]={
+ ["cs"]="odkazujici",
+ ["de"]="referieren",
+ ["en"]="referring",
+ ["fr"]="faitreference",
+ ["it"]="referring",
+ ["nl"]="refereer",
+ ["pe"]="مراجعه",
+ ["ro"]="referring",
+ },
+ ["remark"]={
+ ["cs"]="oznaceni",
+ ["de"]="bemerkung",
+ ["en"]="remark",
+ ["fr"]="commentaire",
+ ["it"]="commento",
+ ["nl"]="toelichting",
+ ["pe"]="توجه",
+ ["ro"]="remarca",
+ },
+ ["reset"]={
+ ["cs"]="reset",
+ ["de"]="ruecksetzten",
+ ["en"]="reset",
+ ["fr"]="raz",
+ ["it"]="reimposta",
+ ["nl"]="reset",
+ ["pe"]="بازنشانی",
+ ["ro"]="reset",
+ },
+ ["resetmarking"]={
+ ["cs"]="resetznaceni",
+ ["de"]="ruecksetztenbeschriftung",
+ ["en"]="resetmarking",
+ ["fr"]="razmarquage",
+ ["it"]="reimpostamarcatura",
+ ["nl"]="resetmarkering",
+ ["pe"]="بازنشانینشانهگذاری",
+ ["ro"]="reseteazamarcaje",
+ },
+ ["resetnumber"]={
+ ["cs"]="resetnumber",
+ ["de"]="resetnumber",
+ ["en"]="resetnumber",
+ ["fr"]="raznumero",
+ ["it"]="resetnumber",
+ ["nl"]="resetnummer",
+ ["pe"]="بازنشانیشماره",
+ ["ro"]="resetnumber",
+ },
+ ["resettext"]={
+ ["cs"]="resettextcontent",
+ ["de"]="resettextcontent",
+ ["en"]="resettextcontent",
+ ["fr"]="resettextcontent",
+ ["it"]="resettextcontent",
+ ["nl"]="resettekstinhoud",
+ ["pe"]="بازنشانیمتن",
+ ["ro"]="resettextcontent",
+ },
+ ["rightaligned"]={
+ ["cs"]="zarovnanovpravo",
+ ["de"]="rechtsbuendig",
+ ["en"]="rightaligned",
+ ["fr"]="aligneadroite",
+ ["it"]="allineadestra",
+ ["nl"]="regelrechts",
+ ["pe"]="تنظیمراست",
+ ["ro"]="aliniatdreapta",
+ },
+ ["rightedgedistance"]={
+ ["cs"]="vzdalenostpravehookraje",
+ ["de"]="abstandrechterrand",
+ ["en"]="rightedgedistance",
+ ["fr"]="distanceborddroit",
+ ["it"]="distanzabordodestro",
+ ["nl"]="rechterrandafstand",
+ ["pe"]="فاصلهلبهراست",
+ ["ro"]="distantacoltdreapta",
+ },
+ ["rightedgewidth"]={
+ ["cs"]="sirkapravehookraje",
+ ["de"]="breiterechterrand",
+ ["en"]="rightedgewidth",
+ ["fr"]="largeurborddroit",
+ ["it"]="ampiezzabordodestro",
+ ["nl"]="rechterrandbreedte",
+ ["pe"]="عرضلبهراست",
+ ["ro"]="latimecoltdreapta",
+ },
+ ["rightmargindistance"]={
+ ["cs"]="vzdalenostpravemarginalie",
+ ["de"]="rechtemarginalafstand",
+ ["en"]="rightmargindistance",
+ ["fr"]="distancemargedroite",
+ ["it"]="distanzamarginedestro",
+ ["nl"]="rechtermargeafstand",
+ ["pe"]="فاصلهحاشیهراست",
+ ["ro"]="distantamarginedreapta",
+ },
+ ["rightmarginwidth"]={
+ ["cs"]="sirkapravemarginalie",
+ ["de"]="rechtemarginalbreite",
+ ["en"]="rightmarginwidth",
+ ["fr"]="largeurmargedroite",
+ ["it"]="ampiezzamarginedestro",
+ ["nl"]="rechtermargebreedte",
+ ["pe"]="عرضحاشیهراست",
+ ["ro"]="latimemarginedreapta",
+ },
+ ["romannumerals"]={
+ ["cs"]="rimskecislice",
+ ["de"]="roemischezahlen",
+ ["en"]="romannumerals",
+ ["fr"]="chiffresromains",
+ ["it"]="numeriromani",
+ ["nl"]="romeins",
+ ["pe"]="اعدادلاتین",
+ ["ro"]="numereromane",
+ },
+ ["rotate"]={
+ ["cs"]="otocit",
+ ["de"]="drehen",
+ ["en"]="rotate",
+ ["fr"]="oriente",
+ ["it"]="ruota",
+ ["nl"]="roteer",
+ ["pe"]="دوران",
+ ["ro"]="roteste",
+ },
+ ["scale"]={
+ ["cs"]="meritko",
+ ["de"]="format",
+ ["en"]="scale",
+ ["fr"]="echelle",
+ ["it"]="scala",
+ ["nl"]="schaal",
+ ["pe"]="مقیاس",
+ ["ro"]="scala",
+ },
+ ["screen"]={
+ ["cs"]="obrazovka",
+ ["de"]="bildschirm",
+ ["en"]="screen",
+ ["fr"]="ecran",
+ ["it"]="schermo",
+ ["nl"]="scherm",
+ ["pe"]="پرده",
+ ["ro"]="ecran",
+ },
+ ["selectblocks"]={
+ ["cs"]="vyberbloky",
+ ["de"]="waehlebloeckeaus",
+ ["en"]="selectblocks",
+ ["fr"]="selectionneblocs",
+ ["it"]="selezionablocchi",
+ ["nl"]="selecteerblokken",
+ ["pe"]="انتخاببلوکها",
+ ["ro"]="selecteazablocuri",
+ },
+ ["selectpaper"]={
+ ["cs"]="vyberpapir",
+ ["de"]="waehlepapieraus",
+ ["en"]="selectpaper",
+ ["fr"]="selectionnepapier",
+ ["it"]="selezionacarta",
+ ["nl"]="selecteerpapier",
+ ["pe"]="انتخاببرگ",
+ ["ro"]="selecteazahartie",
+ },
+ ["selectversion"]={
+ ["cs"]="vyberverzi",
+ ["de"]="waehleversionaus",
+ ["en"]="selectversion",
+ ["fr"]="selectionneversion",
+ ["it"]="selezionaversione",
+ ["nl"]="selecteerversie",
+ ["pe"]="انتخابنسخه",
+ ["ro"]="selecteazaversiune",
+ },
+ ["setnumber"]={
+ ["cs"]="setnumber",
+ ["de"]="setnumber",
+ ["en"]="setnumber",
+ ["fr"]="affectenumero",
+ ["it"]="setnumber",
+ ["nl"]="setnummer",
+ ["pe"]="تعیینشماره",
+ ["ro"]="setnumber",
+ },
+ ["settextcontent"]={
+ ["cs"]="settextcontent",
+ ["de"]="settext",
+ ["en"]="settextcontent",
+ ["fr"]="settext",
+ ["it"]="settext",
+ ["nl"]="steltekstinhoudin",
+ ["pe"]="تعیینمحتوایمتن",
+ ["ro"]="settextcontent",
+ },
+ ["settextvariable"]={
+ ["cs"]="settextvariable",
+ ["de"]="settextvariable",
+ ["en"]="settextvariable",
+ ["fr"]="affectevariabletexte",
+ ["it"]="setvariabiletesto",
+ ["nl"]="kentekstvariabeletoe",
+ ["pe"]="تعیینمتغیرمتن",
+ ["ro"]="setvariabilatext",
+ },
+ ["setupalign"]={
+ ["cs"]="nastavzarovnani",
+ ["de"]="stelleausrichtungein",
+ ["en"]="setupalign",
+ ["fr"]="reglealignement",
+ ["it"]="impostaallineamento",
+ ["nl"]="steluitlijnenin",
+ ["pe"]="بارگذاریتنظیم",
+ ["ro"]="seteazaalinierea",
+ },
+ ["setupanswerarea"]={
+ ["cs"]="setupanswerarea",
+ ["de"]="setupanswerarea",
+ ["en"]="setupanswerarea",
+ ["fr"]="setupanswerarea",
+ ["it"]="setupanswerarea",
+ ["nl"]="stelantwoordgebiedin",
+ ["pe"]="setupanswerarea",
+ ["ro"]="setupanswerarea",
+ },
+ ["setuparranging"]={
+ ["cs"]="nastavusporadani",
+ ["de"]="stelleanordnenein",
+ ["en"]="setuparranging",
+ ["fr"]="reglearrangement",
+ ["it"]="impostaparranging",
+ ["nl"]="stelarrangerenin",
+ ["pe"]="بارگذاریترتیب",
+ ["ro"]="seteazaaranjareapag",
+ },
+ ["setupbackground"]={
+ ["cs"]="nastavpozadi",
+ ["de"]="stellehintergrundein",
+ ["en"]="setupbackground",
+ ["fr"]="reglearriereplan",
+ ["it"]="impostasfondo",
+ ["nl"]="stelachtergrondin",
+ ["pe"]="بارگذاریپسزمینه",
+ ["ro"]="seteazafundal",
+ },
+ ["setupbackgrounds"]={
+ ["cs"]="nastavpozadi",
+ ["de"]="stellehintergruendeein",
+ ["en"]="setupbackgrounds",
+ ["fr"]="reglearriereplans",
+ ["it"]="impostasfondi",
+ ["nl"]="stelachtergrondenin",
+ ["pe"]="بارگذاریپسزمینهها",
+ ["ro"]="seteazafundaluri",
+ },
+ ["setupblackrules"]={
+ ["cs"]="nastavcernelinky",
+ ["de"]="stellerechteckein",
+ ["en"]="setupblackrules",
+ ["fr"]="reglelignesnoires",
+ ["it"]="impostalineenere",
+ ["nl"]="stelblokjesin",
+ ["pe"]="بارگذاریخطهایسیاه",
+ ["ro"]="seteazaliniinegre",
+ },
+ ["setupblank"]={
+ ["cs"]="nastavpreskok",
+ ["de"]="stelleblankoein",
+ ["en"]="setupblank",
+ ["fr"]="definitvide",
+ ["it"]="impostarigovuoto",
+ ["nl"]="stelblankoin",
+ ["pe"]="بارگذاریخالی",
+ ["ro"]="seteazablanc",
+ },
+ ["setupblock"]={
+ ["cs"]="nastavblok",
+ ["de"]="stelleblockein",
+ ["en"]="setupblock",
+ ["fr"]="reglebloc",
+ ["it"]="impostablocco",
+ ["nl"]="stelblokin",
+ ["pe"]="بارگذاریبلوک",
+ ["ro"]="seteazabloc",
+ },
+ ["setupbodyfont"]={
+ ["cs"]="nastavzakladnifont",
+ ["de"]="stellefliesstextein",
+ ["en"]="setupbodyfont",
+ ["fr"]="reglepolicecorps",
+ ["it"]="impostafontdeltesto",
+ ["nl"]="stelkorpsin",
+ ["pe"]="بارگذاریقلممتن",
+ ["ro"]="seteazafonttext",
+ },
+ ["setupbodyfontenvironment"]={
+ ["cs"]="nastavprostredizakladnihofontu",
+ ["de"]="stellefliesstextumgebungein",
+ ["en"]="setupbodyfontenvironment",
+ ["fr"]="regleenvironnementpolicecorps",
+ ["it"]="impostaambientefontdeltesto",
+ ["nl"]="stelkorpsomgevingin",
+ ["pe"]="بارگذاریمحیطقلممتن",
+ ["ro"]="seteazamediulfonttext",
+ },
+ ["setupbottom"]={
+ ["cs"]="nastavspodek",
+ ["de"]="stelleuntenein",
+ ["en"]="setupbottom",
+ ["fr"]="regleinf",
+ ["it"]="impostafondo",
+ ["nl"]="stelonderin",
+ ["pe"]="بارگذاریپایین",
+ ["ro"]="seteazajos",
+ },
+ ["setupbottomtexts"]={
+ ["cs"]="nastavdolnitexty",
+ ["de"]="stelletextuntenein",
+ ["en"]="setupbottomtexts",
+ ["fr"]="regletextesinf",
+ ["it"]="impostatestifondo",
+ ["nl"]="stelondertekstenin",
+ ["pe"]="بارگذاریمتنپایین",
+ ["ro"]="seteazatextejos",
+ },
+ ["setupbuffer"]={
+ ["cs"]="nastavbuffer",
+ ["de"]="stellepufferein",
+ ["en"]="setupbuffer",
+ ["fr"]="reglebuffer",
+ ["it"]="impostabuffer",
+ ["nl"]="stelbufferin",
+ ["pe"]="بارگذاریبافر",
+ ["ro"]="seteazabuffer",
+ },
+ ["setupbuttons"]={
+ ["cs"]="nastavtlacitka",
+ ["de"]="stelleknopfein",
+ ["en"]="setupbuttons",
+ ["fr"]="regleboutons",
+ ["it"]="impostapulsanti",
+ ["nl"]="stelbuttonsin",
+ ["pe"]="بارگذاریدکمهها",
+ ["ro"]="seteazabutoane",
+ },
+ ["setupcapitals"]={
+ ["cs"]="nastavkapitalky",
+ ["de"]="stelleversalienein",
+ ["en"]="setupcapitals",
+ ["fr"]="reglecapitales",
+ ["it"]="impostamaiuscole",
+ ["nl"]="stelkapitalenin",
+ ["pe"]="setupcapitals",
+ ["ro"]="seteazamajuscule",
+ },
+ ["setupcaption"]={
+ ["cs"]="nastavpopisek",
+ ["de"]="stellebildunterschriftein",
+ ["en"]="setupcaption",
+ ["fr"]="regleintitule",
+ ["it"]="impostacaption",
+ ["nl"]="stelblokkopjein",
+ ["pe"]="بارگذاریشرح",
+ ["ro"]="seteazalegenda",
+ },
+ ["setupcaptions"]={
+ ["cs"]="nastavpopisky",
+ ["de"]="stellebilderunterschriftein",
+ ["en"]="setupcaptions",
+ ["fr"]="regleintitules",
+ ["it"]="impostacaptions",
+ ["nl"]="stelblokkopjesin",
+ ["pe"]="بارگذاریشرحها",
+ ["ro"]="seteazalegendele",
+ },
+ ["setupclipping"]={
+ ["cs"]="nastavorez",
+ ["de"]="stelleausschnittein",
+ ["en"]="setupclipping",
+ ["fr"]="regleclipping",
+ ["it"]="impostaclippling",
+ ["nl"]="stelclipin",
+ ["pe"]="بارگذاریچیدن",
+ ["ro"]="seteazaclipping",
+ },
+ ["setupcolor"]={
+ ["cs"]="nastavbarvu",
+ ["de"]="stellefarbeein",
+ ["en"]="setupcolor",
+ ["fr"]="reglecouleur",
+ ["it"]="impostacolore",
+ ["nl"]="stelkleurin",
+ ["pe"]="بارگذاریرنگ",
+ ["ro"]="seteazaculoare",
+ },
+ ["setupcolors"]={
+ ["cs"]="nastavbarvy",
+ ["de"]="stellefarbenein",
+ ["en"]="setupcolors",
+ ["fr"]="reglecouleurs",
+ ["it"]="impostacolori",
+ ["nl"]="stelkleurenin",
+ ["pe"]="بارگذاریرنگها",
+ ["ro"]="seteazaculori",
+ },
+ ["setupcolumns"]={
+ ["cs"]="nastavsloupce",
+ ["de"]="stellespaltenein",
+ ["en"]="setupcolumns",
+ ["fr"]="reglecolonnes",
+ ["it"]="impostacolonne",
+ ["nl"]="stelkolommenin",
+ ["pe"]="بارگذاریستونها",
+ ["ro"]="seteazacoloane",
+ },
+ ["setupcolumnset"]={
+ ["cs"]="setupcolumnset",
+ ["de"]="setupcolumnset",
+ ["en"]="setupcolumnset",
+ ["fr"]="reglejeucolonne",
+ ["it"]="impostagruppocolonne",
+ ["nl"]="stelkolomgroepin",
+ ["pe"]="بارگذاریمجموعهستون",
+ ["ro"]="setupcolumnset",
+ },
+ ["setupcolumnsetlines"]={
+ ["cs"]="setupcolumnsetlines",
+ ["de"]="setupcolumnsetlines",
+ ["en"]="setupcolumnsetlines",
+ ["fr"]="setupcolumnsetlines",
+ ["it"]="setupcolumnsetlines",
+ ["nl"]="stelkolomgroepregelsin",
+ ["pe"]="بارگذاریخطهایمجموعهستون",
+ ["ro"]="setupcolumnsetlines",
+ },
+ ["setupcolumnsetstart"]={
+ ["cs"]="setupcolumnsetstart",
+ ["de"]="setupcolumnsetstart",
+ ["en"]="setupcolumnsetstart",
+ ["fr"]="setupcolumnsetstart",
+ ["it"]="setupcolumnsetstart",
+ ["nl"]="stelkolomgroepstartin",
+ ["pe"]="بارگذاریشروعمجموعهستون",
+ ["ro"]="setupcolumnsetstart",
+ },
+ ["setupcombinations"]={
+ ["cs"]="nastavspojeni",
+ ["de"]="stellekombinationein",
+ ["en"]="setupcombinations",
+ ["fr"]="reglecombinaisons",
+ ["it"]="impostacombinazioni",
+ ["nl"]="stelcombinatiesin",
+ ["pe"]="بارگذاریترکیبها",
+ ["ro"]="seteazacombinari",
+ },
+ ["setupcombinedlist"]={
+ ["cs"]="nastavkombinovanyseznam",
+ ["de"]="stellezusammengestelltelisteein",
+ ["en"]="setupcombinedlist",
+ ["fr"]="reglelisteimbriquee",
+ ["it"]="impostaelencocombinato",
+ ["nl"]="stelsamengesteldelijstin",
+ ["pe"]="بارگذاریلیستترکیبی",
+ ["ro"]="seteazalistacombinata",
+ },
+ ["setupcomment"]={
+ ["cs"]="nastavkomentar",
+ ["de"]="stellekommentarein",
+ ["en"]="setupcomment",
+ ["fr"]="reglecommentaire",
+ ["it"]="impostacommento",
+ ["nl"]="stelcommentaarin",
+ ["pe"]="بارگذاریتوضیح",
+ ["ro"]="seteazacomentariu",
+ },
+ ["setupdescriptions"]={
+ ["cs"]="nastavpopisy",
+ ["de"]="definierebeschreibungen",
+ ["en"]="setupdescriptions",
+ ["fr"]="regledescriptions",
+ ["it"]="impostadescrizioni",
+ ["nl"]="steldoordefinierenin",
+ ["pe"]="بارگذاریشرح",
+ ["ro"]="seteazadescriere",
+ },
+ ["setupenumerations"]={
+ ["cs"]="nastavvycty",
+ ["de"]="stellebeschreibungein",
+ ["en"]="setupenumerations",
+ ["fr"]="regleenumerations",
+ ["it"]="impostaenumerazioni",
+ ["nl"]="steldoornummerenin",
+ ["pe"]="بارگذاریشمارهگذاریها",
+ ["ro"]="seteazaenumerare",
+ },
+ ["setupexternalfigures"]={
+ ["cs"]="nastavexterniobrazy",
+ ["de"]="stelleexterneabbildungenein",
+ ["en"]="setupexternalfigures",
+ ["fr"]="reglefiguresexternes",
+ ["it"]="impostafigureesterne",
+ ["nl"]="stelexternefigurenin",
+ ["pe"]="بارگذاریشکلهایخارجی",
+ ["ro"]="seteazafiguriexterne",
+ },
+ ["setupfield"]={
+ ["cs"]="nastavpole",
+ ["de"]="stellefeldein",
+ ["en"]="setupfield",
+ ["fr"]="reglechamp",
+ ["it"]="impostacampo",
+ ["nl"]="stelveldin",
+ ["pe"]="بارگذاریمیدان",
+ ["ro"]="seteazacamp",
+ },
+ ["setupfields"]={
+ ["cs"]="nastavvsechnapole",
+ ["de"]="stellefelderin",
+ ["en"]="setupfields",
+ ["fr"]="reglechamps",
+ ["it"]="impostacampi",
+ ["nl"]="stelveldenin",
+ ["pe"]="بارگذاریمیدانها",
+ ["ro"]="seteazacampuri",
+ },
+ ["setupfillinlines"]={
+ ["cs"]="nastavvyplnoveradky",
+ ["de"]="stellegefuelltezeileein",
+ ["en"]="setupfillinlines",
+ ["fr"]="regleremplitligne",
+ ["it"]="impostarigheriempimento",
+ ["nl"]="stelinvulregelsin",
+ ["pe"]="بارگذاریپرکردنخطها",
+ ["ro"]="seteazaliniiumplere",
+ },
+ ["setupfillinrules"]={
+ ["cs"]="nastavvyplnovelinky",
+ ["de"]="stellegefuelltesrechteckein",
+ ["en"]="setupfillinrules",
+ ["fr"]="regleremplitlignesreglees",
+ ["it"]="impostalineeriempimento",
+ ["nl"]="stelinvullijnenin",
+ ["pe"]="بارگذاریدرجدرخطها",
+ ["ro"]="seteazarigleumplere",
+ },
+ ["setupfloat"]={
+ ["cs"]="nastavplvouciobjekt",
+ ["de"]="stellegleitobjektein",
+ ["en"]="setupfloat",
+ ["fr"]="regleflottant",
+ ["it"]="impostaoggettomobile",
+ ["nl"]="stelplaatsblokin",
+ ["pe"]="بارگذاریشناور",
+ ["ro"]="seteazafloat",
+ },
+ ["setupfloats"]={
+ ["cs"]="nastavplvouciobjekty",
+ ["de"]="stellegleitobjekteein",
+ ["en"]="setupfloats",
+ ["fr"]="regleflottants",
+ ["it"]="impostaoggettimobili",
+ ["nl"]="stelplaatsblokkenin",
+ ["pe"]="بارگذاریشناورها",
+ ["ro"]="seteazafloats",
+ },
+ ["setupfloatsplitting"]={
+ ["cs"]="nastavdeleniplvoucichobjektu",
+ ["de"]="stelleplatziegeteiltegleitobjekt",
+ ["en"]="setupfloatsplitting",
+ ["fr"]="regleseparationflottant",
+ ["it"]="impostaspezzamentooggettomobile",
+ ["nl"]="stelplaatsbloksplitsenin",
+ ["pe"]="بارگذاریشکافتنشناورها",
+ ["ro"]="seteazaimpartireafloat",
+ },
+ ["setupfooter"]={
+ ["cs"]="nastavupati",
+ ["de"]="stellefusszeileein",
+ ["en"]="setupfooter",
+ ["fr"]="reglepdp",
+ ["it"]="impostapdp",
+ ["nl"]="stelvoetin",
+ ["pe"]="بارگذاریتهبرگ",
+ ["ro"]="seteazasubsol",
+ },
+ ["setupfootertexts"]={
+ ["cs"]="nastavtextyupati",
+ ["de"]="stellefusszeilentextein",
+ ["en"]="setupfootertexts",
+ ["fr"]="regletextespdp",
+ ["it"]="impostatestipdp",
+ ["nl"]="stelvoettekstenin",
+ ["pe"]="بارگذاریمتنپانوشت",
+ ["ro"]="seteazatextesubsol",
+ },
+ ["setupfootnotedefinition"]={
+ ["cs"]="nastavdefinicipoznamekpodcarou",
+ ["de"]="stellefussnotendefinitionein",
+ ["en"]="setupfootnotedefinition",
+ ["fr"]="definitnotepdp",
+ ["it"]="impostadefinizionenotepdp",
+ ["nl"]="stelvoetnootdefinitiein",
+ ["pe"]="بارگذاریتعریفپانوشت",
+ ["ro"]="seteazadefinireanotasubsol",
+ },
+ ["setupfootnotes"]={
+ ["cs"]="nastavpoznamkypodcarou",
+ ["de"]="stellefussnotenein",
+ ["en"]="setupfootnotes",
+ ["fr"]="reglenotepdp",
+ ["it"]="impostanotepdp",
+ ["nl"]="stelvoetnotenin",
+ ["pe"]="بارگذاریپانوشتها",
+ ["ro"]="seteazanotasubsol",
+ },
+ ["setupforms"]={
+ ["cs"]="setupforms",
+ ["de"]="setupforms",
+ ["en"]="setupforms",
+ ["fr"]="regleformulaires",
+ ["it"]="impostaforms",
+ ["nl"]="stelformulierenin",
+ ["pe"]="بارگذاریطرح",
+ ["ro"]="seteazaformulare",
+ },
+ ["setupformulas"]={
+ ["cs"]="nastavrovnice",
+ ["de"]="stelleformelnein",
+ ["en"]="setupformulae",
+ ["fr"]="regleformules",
+ ["it"]="impostaformule",
+ ["nl"]="stelformulesin",
+ ["pe"]="بارگذاریفرمولها",
+ ["ro"]="seteazaformule",
+ },
+ ["setupframed"]={
+ ["cs"]="nastavoramovani",
+ ["de"]="stelleumrahmtein",
+ ["en"]="setupframed",
+ ["fr"]="regleencadre",
+ ["it"]="impostaincorniciato",
+ ["nl"]="stelomlijndin",
+ ["pe"]="بارگذاریقالبی",
+ ["ro"]="seteazainconjurat",
+ },
+ ["setupframedtexts"]={
+ ["cs"]="nastavoramovanetexty",
+ ["de"]="stelleumrahmtetexteein",
+ ["en"]="setupframedtexts",
+ ["fr"]="setupframedtexts",
+ ["it"]="impostatestiincorniciati",
+ ["nl"]="stelkadertekstenin",
+ ["pe"]="بارگذاریمتنقالبی",
+ ["ro"]="definestetexteinconjurate",
+ },
+ ["setuphead"]={
+ ["cs"]="nastavnadpis",
+ ["de"]="stelleueberschriftein",
+ ["en"]="setuphead",
+ ["fr"]="regletete",
+ ["it"]="impostatesta",
+ ["nl"]="stelkopin",
+ ["pe"]="بارگذاریسر",
+ ["ro"]="seteazatitlu",
+ },
+ ["setupheader"]={
+ ["cs"]="nastavzahlavi",
+ ["de"]="stellekopfzeileein",
+ ["en"]="setupheader",
+ ["fr"]="regleentete",
+ ["it"]="impostainstestazione",
+ ["nl"]="stelhoofdin",
+ ["pe"]="بارگذاریسربرگ",
+ ["ro"]="seteazaantet",
+ },
+ ["setupheadertexts"]={
+ ["cs"]="nastavtextyzahlavi",
+ ["de"]="stellekopfzeilentextein",
+ ["en"]="setupheadertexts",
+ ["fr"]="regletextesentete",
+ ["it"]="impostatestiintestazioni",
+ ["nl"]="stelhoofdtekstenin",
+ ["pe"]="بارگذاریمتنسربرگ",
+ ["ro"]="seteazatexteantet",
+ },
+ ["setupheadnumber"]={
+ ["cs"]="nastavcislonadpisu",
+ ["de"]="stellekopfzahlein",
+ ["en"]="setupheadnumber",
+ ["fr"]="reglenumerotete",
+ ["it"]="impostanumerotesta",
+ ["nl"]="stelkopnummerin",
+ ["pe"]="بارگذاریشمارهسر",
+ ["ro"]="seteazanumartitlu",
+ },
+ ["setupheads"]={
+ ["cs"]="nastavnadpisy",
+ ["de"]="stelleueberschriftenein",
+ ["en"]="setupheads",
+ ["fr"]="regletetes",
+ ["it"]="impostateste",
+ ["nl"]="stelkoppenin",
+ ["pe"]="بارگذاریسرها",
+ ["ro"]="seteazatitluri",
+ },
+ ["setupheadtext"]={
+ ["cs"]="nastavtexthlavicky",
+ ["de"]="stelleueberschrifttextein",
+ ["en"]="setupheadtext",
+ ["fr"]="regletextetete",
+ ["it"]="impostatestointestazioni",
+ ["nl"]="stelkoptekstin",
+ ["pe"]="بارگذاریمتنسر",
+ ["ro"]="seteazatexttitlu",
+ },
+ ["setuphyphenmark"]={
+ ["cs"]="nastavdelitko",
+ ["de"]="stellebindestrichein",
+ ["en"]="setuphyphenmark",
+ ["fr"]="reglemarquagehyphenation",
+ ["it"]="impostasegnosillabazione",
+ ["nl"]="stelkoppeltekenin",
+ ["pe"]="بارگذارینشانهشکستن",
+ ["ro"]="seteazaliniesilabe",
+ },
+ ["setupindentations"]={
+ ["cs"]="nastavodsazeni",
+ ["de"]="stelleeinzuegein",
+ ["en"]="setupindentations",
+ ["fr"]="reglealineas",
+ ["it"]="impostarientri",
+ ["nl"]="steldoorspringenin",
+ ["pe"]="بارگذاریتورفتگیها",
+ ["ro"]="seteazaaliniate",
+ },
+ ["setupindenting"]={
+ ["cs"]="nastavodsazovani",
+ ["de"]="stelleeinziehenein",
+ ["en"]="setupindenting",
+ ["fr"]="reglecomposeenalinea",
+ ["it"]="impostarientro",
+ ["nl"]="stelinspringenin",
+ ["pe"]="بارگذاریتورفتگی",
+ ["ro"]="seteazaaliniat",
+ },
+ ["setupinmargin"]={
+ ["cs"]="nastavmarginalie",
+ ["de"]="stelleinmarginalieein",
+ ["en"]="setupinmargin",
+ ["fr"]="regledansmarge",
+ ["it"]="impostainmargine",
+ ["nl"]="stelinmargein",
+ ["pe"]="بارگذاریدرونحاشیه",
+ ["ro"]="seteazamarginal",
+ },
+ ["setupinteraction"]={
+ ["cs"]="nastavinterakci",
+ ["de"]="stelleinteraktionein",
+ ["en"]="setupinteraction",
+ ["fr"]="regleinteraction",
+ ["it"]="impostainterazione",
+ ["nl"]="stelinteractiein",
+ ["pe"]="بارگذاریپانل",
+ ["ro"]="seteazainteractiunea",
+ },
+ ["setupinteractionbar"]={
+ ["cs"]="nastavinterakcnilistu",
+ ["de"]="stelleinteraktionsbalkenein",
+ ["en"]="setupinteractionbar",
+ ["fr"]="reglebarreinteraction",
+ ["it"]="impostabarrainterazione",
+ ["nl"]="stelinteractiebalkin",
+ ["pe"]="بارگذاریمیلهپانل",
+ ["ro"]="seteazabarainteractiune",
+ },
+ ["setupinteractionmenu"]={
+ ["cs"]="nastavinterakcnimenu",
+ ["de"]="stelleinteraktionsmenueein",
+ ["en"]="setupinteractionmenu",
+ ["fr"]="reglemenuinteraction",
+ ["it"]="impostamenuinterazione",
+ ["nl"]="stelinteractiemenuin",
+ ["pe"]="بارگذاریمنویپانل",
+ ["ro"]="seteazameniuinteractiune",
+ },
+ ["setupinteractionscreen"]={
+ ["cs"]="nastavinterakcniobrazovku",
+ ["de"]="stelleinteraktionsbildschirmein",
+ ["en"]="setupinteractionscreen",
+ ["fr"]="regleecraninteraction",
+ ["it"]="impostaschermointerazione",
+ ["nl"]="stelinteractieschermin",
+ ["pe"]="بارگذاریپردهپانل",
+ ["ro"]="seteazaecraninteractiune",
+ },
+ ["setupinterlinespace"]={
+ ["cs"]="nastavmeziradkovoumezeru",
+ ["de"]="stellezeilenabstandein",
+ ["en"]="setupinterlinespace",
+ ["fr"]="regleespacementinterligne",
+ ["it"]="impostainterlinea",
+ ["nl"]="stelinterliniein",
+ ["pe"]="بارگذاریفاصلهبینخط",
+ ["ro"]="seteazaspatiuinterliniar",
+ },
+ ["setupitemgroup"]={
+ ["cs"]="setupitemgroup",
+ ["de"]="setupitemgroup",
+ ["en"]="setupitemgroup",
+ ["fr"]="setupitemgroup",
+ ["it"]="setupitemgroup",
+ ["nl"]="stelitemgroepin",
+ ["pe"]="بارگذاریگروهآیتم",
+ ["ro"]="setupitemgroup",
+ },
+ ["setupitemgroups"]={
+ ["cs"]="nastavvycty",
+ ["de"]="stelleaufzaehlungenein",
+ ["en"]="setupitemizations",
+ ["fr"]="reglegroupeselements",
+ ["it"]="impostaelencazioni",
+ ["nl"]="stelopsommingenin",
+ ["pe"]="بارگذاریگروههایآیتم",
+ ["ro"]="setareitemization",
+ },
+ ["setupitems"]={
+ ["cs"]="nastavpolozky",
+ ["de"]="stellepostenein",
+ ["en"]="setupitems",
+ ["fr"]="regleelements",
+ ["it"]="impostaelementi",
+ ["nl"]="stelitemsin",
+ ["pe"]="بارگذاریآیتمها",
+ ["ro"]="seteazaelemente",
+ },
+ ["setuplabeltext"]={
+ ["cs"]="nastavtextpopisku",
+ ["de"]="stellelabeltextein",
+ ["en"]="setuplabeltext",
+ ["fr"]="reglelabeltexte",
+ ["it"]="impostatestoetichette",
+ ["nl"]="stellabeltekstin",
+ ["pe"]="باگذاریمتنبرچسب",
+ ["ro"]="seteazatexteticheta",
+ },
+ ["setuplanguage"]={
+ ["cs"]="nastavjazyk",
+ ["de"]="stellespracheein",
+ ["en"]="setuplanguage",
+ ["fr"]="reglelangue",
+ ["it"]="impostalingua",
+ ["nl"]="steltaalin",
+ ["pe"]="بارگذاریزبان",
+ ["ro"]="setarelimba",
+ },
+ ["setuplayout"]={
+ ["cs"]="nastavvzhled",
+ ["de"]="stellelayoutein",
+ ["en"]="setuplayout",
+ ["fr"]="regledisposition",
+ ["it"]="impostalayout",
+ ["nl"]="stellayoutin",
+ ["pe"]="بارگذاریطرحبندی",
+ ["ro"]="seteazaaspect",
+ },
+ ["setuplegend"]={
+ ["cs"]="nastavlegendu",
+ ["de"]="stellelegendeein",
+ ["en"]="setuplegend",
+ ["fr"]="reglelegende",
+ ["it"]="impostalegenda",
+ ["nl"]="stellegendain",
+ ["pe"]="بارگذاریراهنما",
+ ["ro"]="seteazalegenda",
+ },
+ ["setuplinenumbering"]={
+ ["cs"]="nastavcislovaniradku",
+ ["de"]="stellezeilennumerierungein",
+ ["en"]="setuplinenumbering",
+ ["fr"]="reglenumerotationligne",
+ ["it"]="impostanumerazionerighe",
+ ["nl"]="stelregelnummerenin",
+ ["pe"]="بارگذاریشمارهگذاریخط",
+ ["ro"]="seteazanumerotarelinii",
+ },
+ ["setuplines"]={
+ ["cs"]="nastavradky",
+ ["de"]="stellezeilenein",
+ ["en"]="setuplines",
+ ["fr"]="reglelignes",
+ ["it"]="impostarighe",
+ ["nl"]="stelregelsin",
+ ["pe"]="بارگذاریخطها",
+ ["ro"]="seteazalinii",
+ },
+ ["setuplinewidth"]={
+ ["cs"]="nastavsirkucary",
+ ["de"]="stellelinienbreiteein",
+ ["en"]="setuplinewidth",
+ ["fr"]="regleepaisseurligne",
+ ["it"]="impostaampiezzariga",
+ ["nl"]="stellijndiktein",
+ ["pe"]="بارگذاریعرضخط",
+ ["ro"]="seteazagrosimelinie",
+ },
+ ["setuplist"]={
+ ["cs"]="nastavseznam",
+ ["de"]="stellelisteein",
+ ["en"]="setuplist",
+ ["fr"]="regleliste",
+ ["it"]="impostaelenco",
+ ["nl"]="stellijstin",
+ ["pe"]="بارگذاریلیست",
+ ["ro"]="seteazalista",
+ },
+ ["setupmakeup"]={
+ ["cs"]="nastavupravu",
+ ["de"]="stelleumbruchein",
+ ["en"]="setupmakeup",
+ ["fr"]="reglemakeup",
+ ["it"]="impostamakeup",
+ ["nl"]="stelopmaakin",
+ ["pe"]="بارگذاریآرایش",
+ ["ro"]="seteazamakeup",
+ },
+ ["setupmarginblocks"]={
+ ["cs"]="nastavmarginalniblok",
+ ["de"]="stellemarginalblockein",
+ ["en"]="setupmarginblocks",
+ ["fr"]="regleblocmarge",
+ ["it"]="impostablocchimargine",
+ ["nl"]="stelmargeblokkenin",
+ ["pe"]="بارگذاریبلوکهایحاشیه",
+ ["ro"]="seteazablocurimarginale",
+ },
+ ["setupmarginrules"]={
+ ["cs"]="nastavmarginalnilinky",
+ ["de"]="stellemarginallinieein",
+ ["en"]="setupmarginrules",
+ ["fr"]="reglemargereglee",
+ ["it"]="impostalineemargine",
+ ["nl"]="stelkantlijnin",
+ ["pe"]="بارگذاریخطهایحاشیه",
+ ["ro"]="seteazaliniimargine",
+ },
+ ["setupmarking"]={
+ ["cs"]="nastavznaceni",
+ ["de"]="stellebeschriftungein",
+ ["en"]="setupmarking",
+ ["fr"]="reglemarquage",
+ ["it"]="impostamarcatura",
+ ["nl"]="stelmarkeringin",
+ ["pe"]="بارگذارینشانهگذاری",
+ ["ro"]="seteazamarcaje",
+ },
+ ["setupmathalignment"]={
+ ["cs"]="setupmathalignment",
+ ["de"]="setupmathalignment",
+ ["en"]="setupmathalignment",
+ ["fr"]="setupmathalignment",
+ ["it"]="setupmathalignment",
+ ["nl"]="stelwiskundeuitlijnenin",
+ ["pe"]="بارگذاریتنظیمریاضی",
+ ["ro"]="setupmathalignment",
+ },
+ ["setupnarrower"]={
+ ["cs"]="nastavzuzeni",
+ ["de"]="stelleengerein",
+ ["en"]="setupnarrower",
+ ["fr"]="reglecompoetroite",
+ ["it"]="impostapiustretto",
+ ["nl"]="stelsmallerin",
+ ["pe"]="بارگذاریباریکتر",
+ ["ro"]="seteazaingust",
+ },
+ ["setupnumber"]={
+ ["cs"]="setupnumber",
+ ["de"]="setupnumber",
+ ["en"]="setupnumber",
+ ["fr"]="reglenumero",
+ ["it"]="impostanumerazione",
+ ["nl"]="stelnummerin",
+ ["pe"]="بارگذاریشماره",
+ ["ro"]="setupnumber",
+ },
+ ["setupnumbering"]={
+ ["cs"]="nastavcislovani",
+ ["de"]="stellenummerierungein",
+ ["en"]="setupnumbering",
+ ["fr"]="reglenumerotation",
+ ["it"]="impostanumerazione",
+ ["nl"]="stelnummerenin",
+ ["pe"]="بارگذاریشمارهگذاری",
+ ["ro"]="seteazanumerotare",
+ },
+ ["setupoppositeplacing"]={
+ ["cs"]="nastavumisteniprotejsku",
+ ["de"]="stellegegenueberplatzierenein",
+ ["en"]="setupoppositeplacing",
+ ["fr"]="regleplacementopposition",
+ ["it"]="impostaposizionamentoopposti",
+ ["nl"]="stelnaastplaatsenin",
+ ["pe"]="بارگذاریدرجمخالف",
+ ["ro"]="seteazaplasareaopozita",
+ },
+ ["setupoutput"]={
+ ["cs"]="nastavvystup",
+ ["de"]="stelleausgabeein",
+ ["en"]="setupoutput",
+ ["fr"]="reglesortie",
+ ["it"]="impostaoutput",
+ ["nl"]="steluitvoerin",
+ ["pe"]="بارگذاریخروجی",
+ ["ro"]="setareoutput",
+ },
+ ["setuppagecomment"]={
+ ["cs"]="nastavkomentarstrany",
+ ["de"]="stelleseitenkommentarein",
+ ["en"]="setuppagecomment",
+ ["fr"]="reglecommentairepage",
+ ["it"]="impostacommentopagina",
+ ["nl"]="stelpaginacommentaarin",
+ ["pe"]="بارگذاریتوضیحصفحه",
+ ["ro"]="seteazacomentariupagina",
+ },
+ ["setuppagenumber"]={
+ ["cs"]="nastavcislostrany",
+ ["de"]="stelleseitennummerein",
+ ["en"]="setuppagenumber",
+ ["fr"]="reglenumeropage",
+ ["it"]="impostanumeropagina",
+ ["nl"]="stelpaginanummerin",
+ ["pe"]="بارگذاریشمارهصفحه",
+ ["ro"]="seteazanumarpagina",
+ },
+ ["setuppagenumbering"]={
+ ["cs"]="nastavcislovanistran",
+ ["de"]="stelleseitennummeriernungein",
+ ["en"]="setuppagenumbering",
+ ["fr"]="reglenumerotationpage",
+ ["it"]="impostanumerazionepagina",
+ ["nl"]="stelpaginanummeringin",
+ ["pe"]="بارگذاریشمارهگذاریصفحه",
+ ["ro"]="seteazanumerotarepagina",
+ },
+ ["setuppagetransitions"]={
+ ["cs"]="nastavprechodstrany",
+ ["de"]="stelleseitenuebergangein",
+ ["en"]="setuppagetransitions",
+ ["fr"]="regletransitionspage",
+ ["it"]="impostatransizionepagina",
+ ["nl"]="stelpaginaovergangenin",
+ ["pe"]="بارگذاریگذارصفحه",
+ ["ro"]="seteazatranzitiepagina",
+ },
+ ["setuppalet"]={
+ ["cs"]="nastavpaletu",
+ ["de"]="stellepaletteein",
+ ["en"]="setuppalet",
+ ["fr"]="reglepalette",
+ ["it"]="impostatavolozza",
+ ["nl"]="stelpaletin",
+ ["pe"]="بارگذاریلوح",
+ ["ro"]="seteazapaleta",
+ },
+ ["setuppaper"]={
+ ["cs"]="setuppaper",
+ ["de"]="setuppaper",
+ ["en"]="setuppaper",
+ ["fr"]="reglepapier",
+ ["it"]="setuppaper",
+ ["nl"]="stelpapierin",
+ ["pe"]="بارگذاریبرگ",
+ ["ro"]="setuppaper",
+ },
+ ["setuppapersize"]={
+ ["cs"]="nastavvelikostpapiru",
+ ["de"]="stellepapierformatein",
+ ["en"]="setuppapersize",
+ ["fr"]="regletaillepapier",
+ ["it"]="impostadimensionicarta",
+ ["nl"]="stelpapierformaatin",
+ ["pe"]="بارگذاریاندازهبرگ",
+ ["ro"]="seteazadimensiunihartie",
+ },
+ ["setupparagraphnumbering"]={
+ ["cs"]="nastavcislovaniodstavcu",
+ ["de"]="stelleabsatznummerierungein",
+ ["en"]="setupparagraphnumbering",
+ ["fr"]="reglenumerotationparagraphe",
+ ["it"]="impostanumerazionecapoversi",
+ ["nl"]="stelparagraafnummerenin",
+ ["pe"]="بارگذاریشمارهگذاریپاراگراف",
+ ["ro"]="seteazanumerotareparagrafe",
+ },
+ ["setupparagraphs"]={
+ ["cs"]="nastavodstavce",
+ ["de"]="stelleabsaetzeein",
+ ["en"]="setupparagraphs",
+ ["fr"]="regleparagraphes",
+ ["it"]="impostacapoversi",
+ ["nl"]="stelalineasin",
+ ["pe"]="بارگذاریپاراگرافها",
+ ["ro"]="seteazaparagrafe",
+ },
+ ["setupplacement"]={
+ ["cs"]="setupplacement",
+ ["de"]="setupplacement",
+ ["en"]="setupplacement",
+ ["fr"]="setupplacement",
+ ["it"]="setupplacement",
+ ["nl"]="stelplaatsin",
+ ["pe"]="بارگذاریجانشانی",
+ ["ro"]="setupplacement",
+ },
+ ["setuppositioning"]={
+ ["cs"]="nastavumistovani",
+ ["de"]="stellepositionierenein",
+ ["en"]="setuppositioning",
+ ["fr"]="reglepositionnement",
+ ["it"]="impostaposizionamento",
+ ["nl"]="stelpositionerenin",
+ ["pe"]="بارگذاریمکانگذاری",
+ ["ro"]="setarepozitie",
+ },
+ ["setupprofiles"]={
+ ["cs"]="nastavprofily",
+ ["de"]="stelleprofilein",
+ ["en"]="setupprofiles",
+ ["fr"]="regleprofils",
+ ["it"]="impostaprofili",
+ ["nl"]="stelprofielenin",
+ ["pe"]="بارگذاریپروفایلها",
+ ["ro"]="seteazaprofile",
+ },
+ ["setupprograms"]={
+ ["cs"]="nastavprogramy",
+ ["de"]="stelleprogrammein",
+ ["en"]="setupprograms",
+ ["fr"]="regleprogrammes",
+ ["it"]="impostaprogrammi",
+ ["nl"]="stelprogrammasin",
+ ["pe"]="بارگذاریبرنامهها",
+ ["ro"]="seteazaprograme",
+ },
+ ["setuppublications"]={
+ ["cs"]="nastavpublikace",
+ ["de"]="stellepublikationein",
+ ["en"]="setuppublications",
+ ["fr"]="reglepublications",
+ ["it"]="impostapubblicazioni",
+ ["nl"]="stelpublicatiesin",
+ ["pe"]="بارگذارینشرها",
+ ["ro"]="seteazapublicatii",
+ },
+ ["setupquote"]={
+ ["cs"]="nastavcitaci",
+ ["de"]="stellezitierenein",
+ ["en"]="setupquote",
+ ["fr"]="demarreciter",
+ ["it"]="impostamenzione",
+ ["nl"]="stelciterenin",
+ ["pe"]="بارگذارینقل",
+ ["ro"]="seteazaminicitat",
+ },
+ ["setupreferencelist"]={
+ ["cs"]="nastavseznamodkazu",
+ ["de"]="stellereferenzlisteein",
+ ["en"]="setupreferencelist",
+ ["fr"]="reglelistereference",
+ ["it"]="impostalistariferimenti",
+ ["nl"]="stelreferentielijstin",
+ ["pe"]="بارگذاریلیستمرجع",
+ ["ro"]="seteazalistareferinte",
+ },
+ ["setupreferencing"]={
+ ["cs"]="nastavodkazovani",
+ ["de"]="stellereferenzierenein",
+ ["en"]="setupreferencing",
+ ["fr"]="reglereferencage",
+ ["it"]="impostariferimento",
+ ["nl"]="stelrefererenin",
+ ["pe"]="بارگذاریارجاع",
+ ["ro"]="seteazareferinte",
+ },
+ ["setupregister"]={
+ ["cs"]="nastavrejstrik",
+ ["de"]="stelleregisterein",
+ ["en"]="setupregister",
+ ["fr"]="regleregistre",
+ ["it"]="impostaregistro",
+ ["nl"]="stelregisterin",
+ ["pe"]="بارگذاریثبت",
+ ["ro"]="seteazaregistru",
+ },
+ ["setuprotate"]={
+ ["cs"]="nastavotoceni",
+ ["de"]="stelledrehenein",
+ ["en"]="setuprotate",
+ ["fr"]="regleoriente",
+ ["it"]="impostarotazione",
+ ["nl"]="stelroterenin",
+ ["pe"]="بارگذاریدوران",
+ ["ro"]="seteazarotare",
+ },
+ ["setuprule"]={
+ ["cs"]="setuprule",
+ ["de"]="setuprule",
+ ["en"]="setuprule",
+ ["fr"]="regleregle",
+ ["it"]="impostalinea",
+ ["nl"]="stellijnin",
+ ["pe"]="بارگذاریخط",
+ ["ro"]="seteazarigla",
+ },
+ ["setups"]={
+ ["cs"]="nastaveni",
+ ["de"]="einstellungen",
+ ["en"]="setups",
+ ["fr"]="reglages",
+ ["it"]="impostazioni",
+ ["nl"]="instellingen",
+ ["pe"]="بارگذاریها",
+ ["ro"]="setari",
+ },
+ ["setupscreens"]={
+ ["cs"]="nastavrastr",
+ ["de"]="stellerasterein",
+ ["en"]="setupscreens",
+ ["fr"]="regleecrans",
+ ["it"]="impostaschermi",
+ ["nl"]="stelrastersin",
+ ["pe"]="بارگذاریپردهها",
+ ["ro"]="seteazaecrane",
+ },
+ ["setupsection"]={
+ ["cs"]="nastavsekci",
+ ["de"]="stelleabschnittein",
+ ["en"]="setupsection",
+ ["fr"]="reglesection",
+ ["it"]="impostasezione",
+ ["nl"]="stelsectiein",
+ ["pe"]="بارگذاریبخش",
+ ["ro"]="seteazasectiune",
+ },
+ ["setupsectionblock"]={
+ ["cs"]="nastavbloksekce",
+ ["de"]="stelleabschnittsblockein",
+ ["en"]="setupsectionblock",
+ ["fr"]="regleblocsection",
+ ["it"]="impostabloccosezione",
+ ["nl"]="stelsectieblokin",
+ ["pe"]="بارگذاریبلوکبخش",
+ ["ro"]="seteazablocsectiune",
+ },
+ ["setupsorting"]={
+ ["cs"]="nastavtrideni",
+ ["de"]="stellesortierenein",
+ ["en"]="setupsorting",
+ ["fr"]="regletri",
+ ["it"]="impostaordinamento",
+ ["nl"]="stelsorterenin",
+ ["pe"]="بارگذاریترتیب",
+ ["ro"]="seteazasortare",
+ },
+ ["setupspacing"]={
+ ["cs"]="nastavradkovani",
+ ["de"]="stellespatiumein",
+ ["en"]="setupspacing",
+ ["fr"]="regleespacement",
+ ["it"]="impostaspaziatura",
+ ["nl"]="stelspatieringin",
+ ["pe"]="بارگذاریفضاگذاری",
+ ["ro"]="seteazaspatiu",
+ },
+ ["setupstartstop"]={
+ ["cs"]="setupstartstop",
+ ["de"]="setupstartstop",
+ ["en"]="setupstartstop",
+ ["fr"]="regledemarrestoppe",
+ ["it"]="impostainiziatermina",
+ ["nl"]="stelstartstopin",
+ ["pe"]="بارگذاریشروعپایان",
+ ["ro"]="setupstartstop",
+ },
+ ["setupstrut"]={
+ ["cs"]="setupstrut",
+ ["de"]="setupstrut",
+ ["en"]="setupstrut",
+ ["fr"]="reglestrut",
+ ["it"]="impostastrut",
+ ["nl"]="stelstrutin",
+ ["pe"]="بارگذاریبست",
+ ["ro"]="seteazastrut",
+ },
+ ["setupsubpagenumber"]={
+ ["cs"]="nastavpodcislostrany",
+ ["de"]="stelleunterseitennummerein",
+ ["en"]="setupsubpagenumber",
+ ["fr"]="reglesousnumeropage",
+ ["it"]="impostanumerosottopagina",
+ ["nl"]="stelsubpaginanummerin",
+ ["pe"]="بارگذاریشمارهزیرصفحه",
+ ["ro"]="seteazanumarsubpagina",
+ },
+ ["setupsymbolset"]={
+ ["cs"]="nastavsadusymbolu",
+ ["de"]="stellesymbolsetein",
+ ["en"]="setupsymbolset",
+ ["fr"]="reglejeusymboles",
+ ["it"]="impostasetsimboli",
+ ["nl"]="stelsymboolsetin",
+ ["pe"]="بارگذاریمجموعهنماد",
+ ["ro"]="seteazasimbol",
+ },
+ ["setupsynchronization"]={
+ ["cs"]="nastavsynchronizaci",
+ ["de"]="stellesynchronisationein",
+ ["en"]="setupsynchronization",
+ ["fr"]="reglesynchronisation",
+ ["it"]="impostasincronizzazione",
+ ["nl"]="stelsynchronisatiein",
+ ["pe"]="بارگذاریتطابق",
+ ["ro"]="setaresincronizare",
+ },
+ ["setupsynchronizationbar"]={
+ ["cs"]="nastavsynchronizacnilistu",
+ ["de"]="stellesynchronisationsbalkenein",
+ ["en"]="setupsynchronizationbar",
+ ["fr"]="reglebarresynchronisation",
+ ["it"]="impostabarrasincronizzazione",
+ ["nl"]="stelsynchronisatiebalkin",
+ ["pe"]="بارگذاریمیلهتطابق",
+ ["ro"]="setarebarasincronizare",
+ },
+ ["setupsynonyms"]={
+ ["cs"]="nastavsynonyma",
+ ["de"]="stellesynonymein",
+ ["en"]="setupsynonyms",
+ ["fr"]="reglesynonymes",
+ ["it"]="impostasinonimi",
+ ["nl"]="stelsynoniemenin",
+ ["pe"]="بارگذاریمترادفها",
+ ["ro"]="seteazasinonime",
+ },
+ ["setupsystem"]={
+ ["cs"]="nastavsystem",
+ ["de"]="stellesystemein",
+ ["en"]="setupsystem",
+ ["fr"]="reglesysteme",
+ ["it"]="impostasistema",
+ ["nl"]="stelsysteemin",
+ ["pe"]="بارگذاریسیستم",
+ ["ro"]="seteazasistem",
+ },
+ ["setuptab"]={
+ ["cs"]="nastavtab",
+ ["de"]="stelletabein",
+ ["en"]="setuptab",
+ ["fr"]="regletab",
+ ["it"]="impostatab",
+ ["nl"]="steltabin",
+ ["pe"]="بارگذاریتب",
+ ["ro"]="seteazatab",
+ },
+ ["setuptables"]={
+ ["cs"]="nastavtabulky",
+ ["de"]="stelletabellenein",
+ ["en"]="setuptables",
+ ["fr"]="regletableaux",
+ ["it"]="impostatabelle",
+ ["nl"]="steltabellenin",
+ ["pe"]="بارگذاریجدولها",
+ ["ro"]="seteazatabele",
+ },
+ ["setuptabulate"]={
+ ["cs"]="nastavtabelaci",
+ ["de"]="stelletabulatorein",
+ ["en"]="setuptabulate",
+ ["fr"]="regletabulation",
+ ["it"]="impostatabulato",
+ ["nl"]="steltabulatiein",
+ ["pe"]="بارگذاریجدولبندی",
+ ["ro"]="seteazatabulatori",
+ },
+ ["setuptext"]={
+ ["cs"]="nastavtext",
+ ["de"]="stelletextein",
+ ["en"]="setuptext",
+ ["fr"]="regletexte",
+ ["it"]="impostatesto",
+ ["nl"]="steltekstin",
+ ["pe"]="بارگذاریمتن",
+ ["ro"]="seteazatext",
+ },
+ ["setuptextposition"]={
+ ["cs"]="setuptextposition",
+ ["de"]="setuptextposition",
+ ["en"]="setuptextposition",
+ ["fr"]="reglepositiontexte",
+ ["it"]="impostaposizionetesto",
+ ["nl"]="steltekstpositiein",
+ ["pe"]="بارگذاریمکانمتن",
+ ["ro"]="seteazapozitietext",
+ },
+ ["setuptextrules"]={
+ ["cs"]="nastavtextovelinky",
+ ["de"]="stelletextumrissein",
+ ["en"]="setuptextrules",
+ ["fr"]="reglelignesreglestexte",
+ ["it"]="impostalineetesto",
+ ["nl"]="steltekstlijnenin",
+ ["pe"]="بارگذاریخطهایمتن",
+ ["ro"]="seteazarigletext",
+ },
+ ["setuptexttexts"]={
+ ["cs"]="nastavtexttexty",
+ ["de"]="stelletexttexteein",
+ ["en"]="setuptexttexts",
+ ["fr"]="regletextestexte",
+ ["it"]="impostatestotesti",
+ ["nl"]="stelteksttekstenin",
+ ["pe"]="بارگذاریمتنمتنها",
+ ["ro"]="seteazatextetext",
+ },
+ ["setuptextvariable"]={
+ ["cs"]="setuptextvariable",
+ ["de"]="setuptextvariable",
+ ["en"]="setuptextvariable",
+ ["fr"]="reglevariabletexte",
+ ["it"]="impostavariabiletesto",
+ ["nl"]="steltekstvariabelein",
+ ["pe"]="بارگذاریمتغیرمتن",
+ ["ro"]="seteazavariabilatext",
+ },
+ ["setupthinrules"]={
+ ["cs"]="nastavtenkelinky",
+ ["de"]="stelleduennerumrissein",
+ ["en"]="setupthinrules",
+ ["fr"]="regletraitsfins",
+ ["it"]="impostalineesottili",
+ ["nl"]="steldunnelijnenin",
+ ["pe"]="بارگذاریخطهاینازک",
+ ["ro"]="seteazaliniesubtire",
+ },
+ ["setuptolerance"]={
+ ["cs"]="nastavtoleranci",
+ ["de"]="stelletoleranzein",
+ ["en"]="setuptolerance",
+ ["fr"]="regletolerance",
+ ["it"]="impostatolleranza",
+ ["nl"]="steltolerantiein",
+ ["pe"]="بارگذاریبردباری",
+ ["ro"]="seteazatoleranta",
+ },
+ ["setuptop"]={
+ ["cs"]="nastavhorejsek",
+ ["de"]="stellenobenein",
+ ["en"]="setuptop",
+ ["fr"]="reglesup",
+ ["it"]="impostacima",
+ ["nl"]="stelbovenin",
+ ["pe"]="بارگذاریبالا",
+ ["ro"]="seteazasus",
+ },
+ ["setuptoptexts"]={
+ ["cs"]="nastavhornitexty",
+ ["de"]="stelletextobenein",
+ ["en"]="setuptoptexts",
+ ["fr"]="regletextessup",
+ ["it"]="impostatesticima",
+ ["nl"]="stelboventekstenin",
+ ["pe"]="بارگذاریمتنهایبالا",
+ ["ro"]="seteazatextesus",
+ },
+ ["setuptype"]={
+ ["cs"]="nastavtype",
+ ["de"]="stelletipein",
+ ["en"]="setuptype",
+ ["fr"]="regletype",
+ ["it"]="impostatype",
+ ["nl"]="steltypein",
+ ["pe"]="بارگذاریتایپ",
+ ["ro"]="seteazatype",
+ },
+ ["setuptyping"]={
+ ["cs"]="nastavopis",
+ ["de"]="stelletippenein",
+ ["en"]="setuptyping",
+ ["fr"]="regledactylo",
+ ["it"]="impostatyping",
+ ["nl"]="steltypenin",
+ ["pe"]="بارگذاریتایپکردن",
+ ["ro"]="seteazatyping",
+ },
+ ["setupunderbar"]={
+ ["cs"]="nastavpodtrzeni",
+ ["de"]="stelleunterstreichenein",
+ ["en"]="setupunderbar",
+ ["fr"]="reglesouslignage",
+ ["it"]="impostasottolinea",
+ ["nl"]="stelonderstrepenin",
+ ["pe"]="بارگذاریمیلهزیر",
+ ["ro"]="seteazasublinie",
+ },
+ ["setupurl"]={
+ ["cs"]="nastavurl",
+ ["de"]="stelleurlein",
+ ["en"]="setupurl",
+ ["fr"]="regleurl",
+ ["it"]="impostaurl",
+ ["nl"]="stelurlin",
+ ["pe"]="setupurl",
+ ["ro"]="seteazaurl",
+ },
+ ["setupversions"]={
+ ["cs"]="nastavverze",
+ ["de"]="stelleversionein",
+ ["en"]="setupversions",
+ ["fr"]="regleversions",
+ ["it"]="impostaversioni",
+ ["nl"]="stelversiesin",
+ ["pe"]="بارگذارینسخهها",
+ ["ro"]="seteazaversiuni",
+ },
+ ["setupwhitespace"]={
+ ["cs"]="nastavbilamista",
+ ["de"]="stellezwischenraumein",
+ ["en"]="setupwhitespace",
+ ["fr"]="regleespaceblanc",
+ ["it"]="impostaspaziobianco",
+ ["nl"]="stelwitruimtein",
+ ["pe"]="بارگذاریفضایسفید",
+ ["ro"]="seteazaspatiualb",
+ },
+ ["showbodyfont"]={
+ ["cs"]="ukazzakladnifont",
+ ["de"]="zeigefliesstext",
+ ["en"]="showbodyfont",
+ ["fr"]="montrepolicecorps",
+ ["it"]="mostrafontdeltesto",
+ ["nl"]="toonkorps",
+ ["pe"]="نمایشقلمبدنه",
+ ["ro"]="afiseazafonttext",
+ },
+ ["showbodyfontenvironment"]={
+ ["cs"]="ukazpostredizakladnihofontu",
+ ["de"]="zeigefliesstextumgebung",
+ ["en"]="showbodyfontenvironment",
+ ["fr"]="montreenvironnementpolicecorps",
+ ["it"]="mostraambientefontdeltesto",
+ ["nl"]="toonkorpsomgeving",
+ ["pe"]="نمایشمحیطقلمبدنه",
+ ["ro"]="afiseazamediufonttext",
+ },
+ ["showcolor"]={
+ ["cs"]="ukazbarvu",
+ ["de"]="zeigefarbe",
+ ["en"]="showcolor",
+ ["fr"]="montrecouleur",
+ ["it"]="mostracolore",
+ ["nl"]="toonkleur",
+ ["pe"]="نمایشرنگ",
+ ["ro"]="afiseazaculoare",
+ },
+ ["showcolorgroup"]={
+ ["cs"]="ukazskupinubarev",
+ ["de"]="zeigefarbengruppe",
+ ["en"]="showcolorgroup",
+ ["fr"]="montregroupecouleur",
+ ["it"]="mostragruppocolori",
+ ["nl"]="toonkleurgroep",
+ ["pe"]="نمایشگروهرنگ",
+ ["ro"]="afiseazagrupculoare",
+ },
+ ["showexternalfigures"]={
+ ["cs"]="ukazexterniobrazy",
+ ["de"]="zeigeexterneabbildungen",
+ ["en"]="showexternalfigures",
+ ["fr"]="montrefiguresexternes",
+ ["it"]="mostrafiguresterne",
+ ["nl"]="toonexternefiguren",
+ ["pe"]="نمایششکلهایخارجی",
+ ["ro"]="afiseazafiguriexterne",
+ },
+ ["showfields"]={
+ ["cs"]="ukazpole",
+ ["de"]="zeigefelder",
+ ["en"]="showfields",
+ ["fr"]="montrechamps",
+ ["it"]="mostracampi",
+ ["nl"]="toonvelden",
+ ["pe"]="نمایشمیدانها",
+ ["ro"]="afiseazacampuri",
+ },
+ ["showframe"]={
+ ["cs"]="ukazramecek",
+ ["de"]="zeigerahmen",
+ ["en"]="showframe",
+ ["fr"]="montrecadre",
+ ["it"]="mostracornice",
+ ["nl"]="toonkader",
+ ["pe"]="نمایشقالب",
+ ["ro"]="afiseazarama",
+ },
+ ["showgrid"]={
+ ["cs"]="ukazmrizku",
+ ["de"]="zeigegitter",
+ ["en"]="showgrid",
+ ["fr"]="montregrille",
+ ["it"]="mostragriglia",
+ ["nl"]="toongrid",
+ ["pe"]="نمایشتوری",
+ ["ro"]="afiseazagrid",
+ },
+ ["showlayout"]={
+ ["cs"]="ukazvzhled",
+ ["de"]="zeigelayout",
+ ["en"]="showlayout",
+ ["fr"]="montredisposition",
+ ["it"]="mostralyout",
+ ["nl"]="toonlayout",
+ ["pe"]="نمایشطرحبندی",
+ ["ro"]="afiseazaaspect",
+ },
+ ["showmakeup"]={
+ ["cs"]="ukazupravu",
+ ["de"]="zeigeumbruch",
+ ["en"]="showmakeup",
+ ["fr"]="montremakeup",
+ ["it"]="mostramakeup",
+ ["nl"]="toonopmaak",
+ ["pe"]="نمایشآرایش",
+ ["ro"]="afiseazamakeup",
+ },
+ ["showpalet"]={
+ ["cs"]="ukazpaletu",
+ ["de"]="zeigepalette",
+ ["en"]="showpalet",
+ ["fr"]="montrepalette",
+ ["it"]="mostratavolozza",
+ ["nl"]="toonpalet",
+ ["pe"]="نمایشلوح",
+ ["ro"]="afiseazapaleta",
+ },
+ ["showprint"]={
+ ["cs"]="ukazvytisk",
+ ["de"]="zeigedruck",
+ ["en"]="showprint",
+ ["fr"]="montreedition",
+ ["it"]="mostrastampa",
+ ["nl"]="toonprint",
+ ["pe"]="نمایشچاپ",
+ ["ro"]="afiseazatiparire",
+ },
+ ["showsetups"]={
+ ["cs"]="ukaznastaveni",
+ ["de"]="zeigeeinstellungen",
+ ["en"]="showsetups",
+ ["fr"]="montrereglages",
+ ["it"]="mostraimpostazioni",
+ ["nl"]="tooninstellingen",
+ ["pe"]="نمایشبارگذاریها",
+ ["ro"]="afiseazasetari",
+ },
+ ["showstruts"]={
+ ["cs"]="ukazpodpery",
+ ["de"]="zeigestruts",
+ ["en"]="showstruts",
+ ["fr"]="montrestruts",
+ ["it"]="mostrastruts",
+ ["nl"]="toonstruts",
+ ["pe"]="نمایشبستها",
+ ["ro"]="afiseazastruts",
+ },
+ ["showsymbolset"]={
+ ["cs"]="ukazsadusymbolu",
+ ["de"]="showsymbolset",
+ ["en"]="showsymbolset",
+ ["fr"]="montrejeusymboles",
+ ["it"]="mostrasetsimboli",
+ ["nl"]="toonsymboolset",
+ ["pe"]="نمایشمجموعهعلامت",
+ ["ro"]="afiseazasetsimboluri",
+ },
+ ["smallcapped"]={
+ ["cs"]="kap",
+ ["de"]="kap",
+ ["en"]="cap",
+ ["fr"]="cap",
+ ["it"]="cap",
+ ["nl"]="kap",
+ ["pe"]="cap",
+ ["ro"]="kap",
+ },
+ ["someline"]={
+ ["cs"]="nejakyradek",
+ ["de"]="einezeile",
+ ["en"]="someline",
+ ["fr"]="uneligne",
+ ["it"]="qualcheriga",
+ ["nl"]="eenregel",
+ ["pe"]="یکخط",
+ ["ro"]="olinie",
+ },
+ ["somewhere"]={
+ ["cs"]="nekde",
+ ["de"]="irgendwo",
+ ["en"]="somewhere",
+ ["fr"]="qqpart",
+ ["it"]="daqualcheparte",
+ ["nl"]="ergens",
+ ["pe"]="یکجا",
+ ["ro"]="undeva",
+ },
+ ["space"]={
+ ["cs"]="mezera",
+ ["de"]="spatium",
+ ["en"]="space",
+ ["fr"]="espace",
+ ["it"]="spazio",
+ ["nl"]="spatie",
+ ["pe"]="فضا",
+ ["ro"]="spatiu",
+ },
+ ["splitfloat"]={
+ ["cs"]="rozdelplvouciobjekt",
+ ["de"]="teilegleitobjekt",
+ ["en"]="splitfloat",
+ ["fr"]="separeflottant",
+ ["it"]="spezzaoggettomobile",
+ ["nl"]="splitsplaatsblok",
+ ["pe"]="شکافتنشناور",
+ ["ro"]="impartefloat",
+ },
+ ["startalignment"]={
+ ["cs"]="startzarovnavani",
+ ["de"]="startausrichtung",
+ ["en"]="startalignment",
+ ["fr"]="demarrealignement",
+ ["it"]="iniziaallineamento",
+ ["nl"]="startuitlijnen",
+ ["pe"]="شروعتنظیم",
+ ["ro"]="startaliniere",
+ },
+ ["startbackground"]={
+ ["cs"]="startpozadi",
+ ["de"]="starthintergrund",
+ ["en"]="startbackground",
+ ["fr"]="demarrearriereplan",
+ ["it"]="iniziasfondo",
+ ["nl"]="startachtergrond",
+ ["pe"]="شروعپسزمینه",
+ ["ro"]="startfundal",
+ },
+ ["startcoding"]={
+ ["cs"]="startkodovani",
+ ["de"]="startkodierung",
+ ["en"]="startcoding",
+ ["fr"]="demarrecodage",
+ ["it"]="iniziacodifica",
+ ["nl"]="startcodering",
+ ["pe"]="شروعکد",
+ ["ro"]="startcodificare",
+ },
+ ["startcolor"]={
+ ["cs"]="startbarva",
+ ["de"]="startfarbe",
+ ["en"]="startcolor",
+ ["fr"]="demarrecouleur",
+ ["it"]="iniziacolore",
+ ["nl"]="startkleur",
+ ["pe"]="شروعرنگ",
+ ["ro"]="startculoare",
+ },
+ ["startcolumnmakeup"]={
+ ["cs"]="startcolumnmakeup",
+ ["de"]="startcolumnmakeup",
+ ["en"]="startcolumnmakeup",
+ ["fr"]="startcolumnmakeup",
+ ["it"]="startcolumnmakeup",
+ ["nl"]="startkolomopmaak",
+ ["pe"]="شروعآرایشستون",
+ ["ro"]="startcolumnmakeup",
+ },
+ ["startcolumns"]={
+ ["cs"]="startsloupce",
+ ["de"]="startspalten",
+ ["en"]="startcolumns",
+ ["fr"]="demarrecolonnes",
+ ["it"]="iniziacolonne",
+ ["nl"]="startkolommen",
+ ["pe"]="شروعستونها",
+ ["ro"]="startcoloane",
+ },
+ ["startcolumnset"]={
+ ["cs"]="startcolumnset",
+ ["de"]="startcolumnset",
+ ["en"]="startcolumnset",
+ ["fr"]="demarrejeucolonne",
+ ["it"]="iniziagruppocolonne",
+ ["nl"]="startkolomgroep",
+ ["pe"]="شروعمجموعهستون",
+ ["ro"]="startcolumnset",
+ },
+ ["startcombination"]={
+ ["cs"]="startspojeni",
+ ["de"]="startkombination",
+ ["en"]="startcombination",
+ ["fr"]="demarrecombinaison",
+ ["it"]="iniziacombinazione",
+ ["nl"]="startcombinatie",
+ ["pe"]="شروعترکیب",
+ ["ro"]="startcombinare",
+ },
+ ["startcomponent"]={
+ ["cs"]="startkomponenta",
+ ["de"]="startkomponente",
+ ["en"]="startcomponent",
+ ["fr"]="demarrecomposant",
+ ["it"]="iniziacomponente",
+ ["nl"]="startonderdeel",
+ ["pe"]="شروعمولفه",
+ ["ro"]="startcomponenta",
+ },
+ ["startdocument"]={
+ ["cs"]="startdokument",
+ ["de"]="startdokument",
+ ["en"]="startdocument",
+ ["fr"]="demarredocument",
+ ["it"]="iniziadocumento",
+ ["nl"]="startdocument",
+ ["pe"]="شروعنوشتار",
+ ["ro"]="startdocument",
+ },
+ ["startenvironment"]={
+ ["cs"]="startprostredi",
+ ["de"]="startumgebung",
+ ["en"]="startenvironment",
+ ["fr"]="demarreenvironement",
+ ["it"]="iniziaambiente",
+ ["nl"]="startomgeving",
+ ["pe"]="شروعمحیط",
+ ["ro"]="startmediu",
+ },
+ ["startfigure"]={
+ ["cs"]="startobraz",
+ ["de"]="startabbildung",
+ ["en"]="startfigure",
+ ["fr"]="demarrefigure",
+ ["it"]="iniziafigura",
+ ["nl"]="startfiguur",
+ ["pe"]="شروعشکل",
+ ["ro"]="startfigura",
+ },
+ ["startglobal"]={
+ ["cs"]="startglobalni",
+ ["de"]="startglobal",
+ ["en"]="startglobal",
+ ["fr"]="demarreglobal",
+ ["it"]="iniziaglobale",
+ ["nl"]="startglobaal",
+ ["pe"]="شروعسراسری",
+ ["ro"]="startglobal",
+ },
+ ["startline"]={
+ ["cs"]="startradek",
+ ["de"]="startzeile",
+ ["en"]="startline",
+ ["fr"]="demarreligne",
+ ["it"]="iniziariga",
+ ["nl"]="startregel",
+ ["pe"]="شروعخط",
+ ["ro"]="startlinie",
+ },
+ ["startlinecorrection"]={
+ ["cs"]="startkorekceradku",
+ ["de"]="startzeilenkorrektur",
+ ["en"]="startlinecorrection",
+ ["fr"]="demarrecorrectionligne",
+ ["it"]="iniziacorrezioneriga",
+ ["nl"]="startregelcorrectie",
+ ["pe"]="شروعتصحیحخط",
+ ["ro"]="startcorectielinie",
+ },
+ ["startlinenumbering"]={
+ ["cs"]="startcislovaniradku",
+ ["de"]="startzeilennumerierung",
+ ["en"]="startlinenumbering",
+ ["fr"]="demarrenumerotationligne",
+ ["it"]="inizianumerazionerighe",
+ ["nl"]="startregelnummeren",
+ ["pe"]="شروعشمارهگذاریخط",
+ ["ro"]="startnumerotarelinii",
+ },
+ ["startlines"]={
+ ["cs"]="startradky",
+ ["de"]="startzeilen",
+ ["en"]="startlines",
+ ["fr"]="demarrelignes",
+ ["it"]="iniziarighe",
+ ["nl"]="startregels",
+ ["pe"]="شروعخطها",
+ ["ro"]="startlinii",
+ },
+ ["startlocal"]={
+ ["cs"]="startlokalni",
+ ["de"]="startlokal",
+ ["en"]="startlocal",
+ ["fr"]="demarrelocal",
+ ["it"]="inizialocale",
+ ["nl"]="startlokaal",
+ ["pe"]="شروعموضعی",
+ ["ro"]="startlocal",
+ },
+ ["startlocalfootnotes"]={
+ ["cs"]="startlokalnipoznamkypodcarou",
+ ["de"]="startlokalefussnoten",
+ ["en"]="startlocalfootnotes",
+ ["fr"]="demarrenotespdplocales",
+ ["it"]="inizianotepdplocali",
+ ["nl"]="startlokalevoetnoten",
+ ["pe"]="شروعپانوشتهایموضعی",
+ ["ro"]="startnotesubsollocale",
+ },
+ ["startmakeup"]={
+ ["cs"]="startuprava",
+ ["de"]="startumbruch",
+ ["en"]="startmakeup",
+ ["fr"]="demarremakeup",
+ ["it"]="iniziamakeup",
+ ["nl"]="startopmaak",
+ ["pe"]="شروعآرایش",
+ ["ro"]="startmakeup",
+ },
+ ["startmarginblock"]={
+ ["cs"]="startmarginalniblok",
+ ["de"]="startmarginalblock",
+ ["en"]="startmarginblock",
+ ["fr"]="demarreblocmarge",
+ ["it"]="iniziabloccomargine",
+ ["nl"]="startmargeblok",
+ ["pe"]="شروعبلوکحاشیه",
+ ["ro"]="startblocmarginal",
+ },
+ ["startmarginrule"]={
+ ["cs"]="startmarginalnilinka",
+ ["de"]="startmarginallinie",
+ ["en"]="startmarginrule",
+ ["fr"]="demarremargereglee",
+ ["it"]="inizialineamargine",
+ ["nl"]="startkantlijn",
+ ["pe"]="شروعخطحاشیه",
+ ["ro"]="startliniemargine",
+ },
+ ["startnarrower"]={
+ ["cs"]="startzuzeni",
+ ["de"]="startenger",
+ ["en"]="startnarrower",
+ ["fr"]="demarrecompoetroite",
+ ["it"]="iniziapiustretto",
+ ["nl"]="startsmaller",
+ ["pe"]="شروعباریکتر",
+ ["ro"]="startingust",
+ },
+ ["startopposite"]={
+ ["cs"]="startprotejsek",
+ ["de"]="startgegenueber",
+ ["en"]="startopposite",
+ ["fr"]="demarreopposition",
+ ["it"]="iniziaopposto",
+ ["nl"]="startnaast",
+ ["pe"]="شروعمخالف",
+ ["ro"]="startopozit",
+ },
+ ["startoverlay"]={
+ ["cs"]="startprekryv",
+ ["de"]="startoverlay",
+ ["en"]="startoverlay",
+ ["fr"]="demarrerevetement",
+ ["it"]="iniziasovrapposizione",
+ ["nl"]="startoverlay",
+ ["pe"]="شروعپوشش",
+ ["ro"]="startoverlay",
+ },
+ ["startoverzicht"]={
+ ["cs"]="startprehled",
+ ["de"]="startueberblick",
+ ["en"]="startoverview",
+ ["fr"]="demarrevuedensemble",
+ ["it"]="iniziaoverview",
+ ["nl"]="startoverzicht",
+ ["pe"]="شروعبازبینی",
+ ["ro"]="startoverview",
+ },
+ ["startpacked"]={
+ ["cs"]="startzhustene",
+ ["de"]="startkleinerdurchschuss",
+ ["en"]="startpacked",
+ ["fr"]="demarregroupe",
+ ["it"]="iniziaimpaccato",
+ ["nl"]="startopelkaar",
+ ["pe"]="شروعفشرده",
+ ["ro"]="startimpachetat",
+ },
+ ["startpositioning"]={
+ ["cs"]="startumistovani",
+ ["de"]="startpositionieren",
+ ["en"]="startpositioning",
+ ["fr"]="demarrepositionnement",
+ ["it"]="iniziaposizionamento",
+ ["nl"]="startpositioneren",
+ ["pe"]="شروعمکانگذاری",
+ ["ro"]="startpozitionare",
+ },
+ ["startproduct"]={
+ ["cs"]="startprodukt",
+ ["de"]="startprodukt",
+ ["en"]="startproduct",
+ ["fr"]="demarreproduit",
+ ["it"]="iniziaprodotto",
+ ["nl"]="startprodukt",
+ ["pe"]="شروعتولید",
+ ["ro"]="startprodus",
+ },
+ ["startprofile"]={
+ ["cs"]="startprofil",
+ ["de"]="startprofil",
+ ["en"]="startprofile",
+ ["fr"]="demarreprofil",
+ ["it"]="iniziaprofilo",
+ ["nl"]="startprofiel",
+ ["pe"]="شروعپروفایل",
+ ["ro"]="startprofil",
+ },
+ ["startproject"]={
+ ["cs"]="startprojekt",
+ ["de"]="startprojekt",
+ ["en"]="startproject",
+ ["fr"]="demarreprojet",
+ ["it"]="iniziaprogetto",
+ ["nl"]="startprojekt",
+ ["pe"]="شروعپروژه",
+ ["ro"]="startproiect",
+ },
+ ["startquotation"]={
+ ["cs"]="startcitace",
+ ["de"]="startzitat",
+ ["en"]="startquotation",
+ ["fr"]="demarrecitation",
+ ["it"]="iniziacitazione",
+ ["nl"]="startcitaat",
+ ["pe"]="شروعنقلقول",
+ ["ro"]="startcitat",
+ },
+ ["startraster"]={
+ ["cs"]="startrastr",
+ ["de"]="startraster",
+ ["en"]="startraster",
+ ["fr"]="demarreraster",
+ ["it"]="iniziaraster",
+ ["nl"]="startraster",
+ ["pe"]="startraster",
+ ["ro"]="startraster",
+ },
+ ["startsymbolset"]={
+ ["cs"]="startsadasymbolu",
+ ["de"]="startsymbolset",
+ ["en"]="startsymbolset",
+ ["fr"]="demarrejeusymboles",
+ ["it"]="iniziasetsimboli",
+ ["nl"]="startsymboolset",
+ ["pe"]="شروعمجموعهنماد",
+ ["ro"]="startsetsimboluri",
+ },
+ ["startsynchronization"]={
+ ["cs"]="startsynchronizace",
+ ["de"]="startsynchronisation",
+ ["en"]="startsynchronization",
+ ["fr"]="demarresynchronisation",
+ ["it"]="iniziasincronizzazione",
+ ["nl"]="startsynchronisatie",
+ ["pe"]="شروعتطابق",
+ ["ro"]="startsincronizare",
+ },
+ ["starttable"]={
+ ["cs"]="starttabulka",
+ ["de"]="starttabelle",
+ ["en"]="starttable",
+ ["fr"]="demarretableau",
+ ["it"]="iniziatabella",
+ ["nl"]="starttabel",
+ ["pe"]="شروعجدول",
+ ["ro"]="starttabel",
+ },
+ ["starttables"]={
+ ["cs"]="starttabulky",
+ ["de"]="starttabellen",
+ ["en"]="starttables",
+ ["fr"]="demarretableaux",
+ ["it"]="iniziatabelle",
+ ["nl"]="starttabellen",
+ ["pe"]="شروعجدولها",
+ ["ro"]="starttabele",
+ },
+ ["starttext"]={
+ ["cs"]="starttext",
+ ["de"]="starttext",
+ ["en"]="starttext",
+ ["fr"]="demarretexte",
+ ["it"]="iniziatesto",
+ ["nl"]="starttekst",
+ ["pe"]="شروعمتن",
+ ["ro"]="starttext",
+ },
+ ["starttextrule"]={
+ ["cs"]="starttextovalinka",
+ ["de"]="starttextlinie",
+ ["en"]="starttextrule",
+ ["fr"]="demarreligneregleetexte",
+ ["it"]="inizialineatesto",
+ ["nl"]="starttekstlijn",
+ ["pe"]="شروعخطمتن",
+ ["ro"]="startriglatext",
+ },
+ ["startunpacked"]={
+ ["cs"]="startnezhustene",
+ ["de"]="startgrosserdurchschuss",
+ ["en"]="startunpacked",
+ ["fr"]="demarredegroupe",
+ ["it"]="iniziaunpacked",
+ ["nl"]="startvanelkaar",
+ ["pe"]="شروعغیرفشرده",
+ ["ro"]="startneimpachetat",
+ },
+ ["startversion"]={
+ ["cs"]="startverze",
+ ["de"]="startversion",
+ ["en"]="startversion",
+ ["fr"]="demarreversion",
+ ["it"]="iniziaversione",
+ ["nl"]="startversie",
+ ["pe"]="شروعنسخه",
+ ["ro"]="startversiune",
+ },
+ ["stopalignment"]={
+ ["cs"]="stopzarovnavani",
+ ["de"]="stopausrichtung",
+ ["en"]="stopalignment",
+ ["fr"]="stoppealignement",
+ ["it"]="terminaallineamento",
+ ["nl"]="stopuitlijnen",
+ ["pe"]="پایانتنظیم",
+ ["ro"]="stopaliniere",
+ },
+ ["stopbackground"]={
+ ["cs"]="stoppozadi",
+ ["de"]="stophintergrund",
+ ["en"]="stopbackground",
+ ["fr"]="stoppearriereplan",
+ ["it"]="terminasfondo",
+ ["nl"]="stopachtergrond",
+ ["pe"]="پایانپسزمینه",
+ ["ro"]="stopfundal",
+ },
+ ["stopcoding"]={
+ ["cs"]="stopkodovani",
+ ["de"]="stopkodierung",
+ ["en"]="stopcoding",
+ ["fr"]="stoppecodage",
+ ["it"]="terminacodifica",
+ ["nl"]="stopcodering",
+ ["pe"]="پایانکد",
+ ["ro"]="stopcodificare",
+ },
+ ["stopcolor"]={
+ ["cs"]="stopbarva",
+ ["de"]="stopfarbe",
+ ["en"]="stopcolor",
+ ["fr"]="stoppecouleur",
+ ["it"]="terminacolore",
+ ["nl"]="stopkleur",
+ ["pe"]="پایانرنگ",
+ ["ro"]="stopculoare",
+ },
+ ["stopcolumnmakeup"]={
+ ["cs"]="stopcolumnmakeup",
+ ["de"]="stopcolumnmakeup",
+ ["en"]="stopcolumnmakeup",
+ ["fr"]="stopcolumnmakeup",
+ ["it"]="stopcolumnmakeup",
+ ["nl"]="stopkolomopmaak",
+ ["pe"]="پایانآرایشستون",
+ ["ro"]="stopcolumnmakeup",
+ },
+ ["stopcolumns"]={
+ ["cs"]="stopsloupce",
+ ["de"]="stopspalten",
+ ["en"]="stopcolumns",
+ ["fr"]="stoppecolonnes",
+ ["it"]="terminacolonne",
+ ["nl"]="stopkolommen",
+ ["pe"]="پایانستونها",
+ ["ro"]="stopcoloane",
+ },
+ ["stopcolumnset"]={
+ ["cs"]="stopcolumnset",
+ ["de"]="stopcolumnset",
+ ["en"]="stopcolumnset",
+ ["fr"]="stoppejeucolonne",
+ ["it"]="terminagruppocolonne",
+ ["nl"]="stopkolomgroep",
+ ["pe"]="پایانمجموعهستون",
+ ["ro"]="stopcolumnset",
+ },
+ ["stopcombination"]={
+ ["cs"]="stopspojeni",
+ ["de"]="stopkombination",
+ ["en"]="stopcombination",
+ ["fr"]="stoppecombinaison",
+ ["it"]="terminacombinazione",
+ ["nl"]="stopcombinatie",
+ ["pe"]="پایانترکیب",
+ ["ro"]="stopcombinare",
+ },
+ ["stopcomponent"]={
+ ["cs"]="stopkomponenta",
+ ["de"]="stopkomponente",
+ ["en"]="stopcomponent",
+ ["fr"]="stoppecomposant",
+ ["it"]="terminacomponente",
+ ["nl"]="stoponderdeel",
+ ["pe"]="پایانمولفه",
+ ["ro"]="stopcomponenta",
+ },
+ ["stopdocument"]={
+ ["cs"]="stopdokument",
+ ["de"]="stopdokument",
+ ["en"]="stopdocument",
+ ["fr"]="stoppedocument",
+ ["it"]="terminadocumento",
+ ["nl"]="stopdocument",
+ ["pe"]="پایاننوشتار",
+ ["ro"]="stopdocument",
+ },
+ ["stopenvironment"]={
+ ["cs"]="stopprostredi",
+ ["de"]="stopumgebung",
+ ["en"]="stopenvironment",
+ ["fr"]="stoppeenvironement",
+ ["it"]="terminaambiente",
+ ["nl"]="stopomgeving",
+ ["pe"]="پایانمحیط",
+ ["ro"]="stopmediu",
+ },
+ ["stopglobal"]={
+ ["cs"]="stopglobalni",
+ ["de"]="stopglobal",
+ ["en"]="stopglobal",
+ ["fr"]="stoppeglobal",
+ ["it"]="terminaglobale",
+ ["nl"]="stopglobaal",
+ ["pe"]="پایانسراسری",
+ ["ro"]="stopblobal",
+ },
+ ["stopline"]={
+ ["cs"]="stopradek",
+ ["de"]="stopzeile",
+ ["en"]="stopline",
+ ["fr"]="stoppeligne",
+ ["it"]="terminariga",
+ ["nl"]="stopregel",
+ ["pe"]="پایانخط",
+ ["ro"]="stoplinie",
+ },
+ ["stoplinecorrection"]={
+ ["cs"]="stopkorekceradku",
+ ["de"]="stopzeilenkorrektur",
+ ["en"]="stoplinecorrection",
+ ["fr"]="stoppecorrectionligne",
+ ["it"]="terminacorrezioneriga",
+ ["nl"]="stopregelcorrectie",
+ ["pe"]="پایانتصحیحخط",
+ ["ro"]="stopcorectielinie",
+ },
+ ["stoplinenumbering"]={
+ ["cs"]="stopcislovaniradku",
+ ["de"]="stopzeilennumerierung",
+ ["en"]="stoplinenumbering",
+ ["fr"]="stoppenumerotationligne",
+ ["it"]="terminanumerazionerighe",
+ ["nl"]="stopregelnummeren",
+ ["pe"]="پایانشمارهگذاریخط",
+ ["ro"]="stopnumerotarelinii",
+ },
+ ["stoplines"]={
+ ["cs"]="stopradky",
+ ["de"]="stopzeilen",
+ ["en"]="stoplines",
+ ["fr"]="stoppelignes",
+ ["it"]="terminarighe",
+ ["nl"]="stopregels",
+ ["pe"]="پایانخطها",
+ ["ro"]="stoplinii",
+ },
+ ["stoplocal"]={
+ ["cs"]="stoplokalni",
+ ["de"]="stoplokal",
+ ["en"]="stoplocal",
+ ["fr"]="stoppelocal",
+ ["it"]="terminalocale",
+ ["nl"]="stoplokaal",
+ ["pe"]="پایانموضعی",
+ ["ro"]="stoplocal",
+ },
+ ["stoplocalfootnotes"]={
+ ["cs"]="stoplokalnipoznamkypodcarou",
+ ["de"]="stoplokalefussnoten",
+ ["en"]="stoplocalfootnotes",
+ ["fr"]="stoppenotespdplocales",
+ ["it"]="terminanotepdplocali",
+ ["nl"]="stoplokalevoetnoten",
+ ["pe"]="پایانپانوشتهایموضعی",
+ ["ro"]="stopnotesubsollocale",
+ },
+ ["stopmakeup"]={
+ ["cs"]="stopuprava",
+ ["de"]="stopumbruch",
+ ["en"]="stopmakeup",
+ ["fr"]="stoppemakeup",
+ ["it"]="terminamakeup",
+ ["nl"]="stopopmaak",
+ ["pe"]="پایانآرایش",
+ ["ro"]="stopmakeup",
+ },
+ ["stopmarginblock"]={
+ ["cs"]="stopmarginalniblok",
+ ["de"]="stopmarginalblock",
+ ["en"]="stopmarginblock",
+ ["fr"]="stoppeblocmarge",
+ ["it"]="terminabloccomargine",
+ ["nl"]="stopmargeblok",
+ ["pe"]="پایانبلوکحاشیه",
+ ["ro"]="stopblocmarginal",
+ },
+ ["stopmarginrule"]={
+ ["cs"]="stopmarginalnilinka",
+ ["de"]="stopmarginallinie",
+ ["en"]="stopmarginrule",
+ ["fr"]="stoppemargereglee",
+ ["it"]="terminalineamargine",
+ ["nl"]="stopkantlijn",
+ ["pe"]="پایانخطحاشیه",
+ ["ro"]="stopliniemargine",
+ },
+ ["stopnarrower"]={
+ ["cs"]="stopzuzeni",
+ ["de"]="stopenger",
+ ["en"]="stopnarrower",
+ ["fr"]="stopcompoetroite",
+ ["it"]="terminapiustretto",
+ ["nl"]="stopsmaller",
+ ["pe"]="پایاننازکتر",
+ ["ro"]="stopingust",
+ },
+ ["stopopposite"]={
+ ["cs"]="stopprotejsek",
+ ["de"]="stopgegenueber",
+ ["en"]="stopopposite",
+ ["fr"]="stoppeopposition",
+ ["it"]="terminaopposto",
+ ["nl"]="stopnaast",
+ ["pe"]="پایانمخالف",
+ ["ro"]="stopopozit",
+ },
+ ["stopoverlay"]={
+ ["cs"]="stopprekryv",
+ ["de"]="stopoverlay",
+ ["en"]="stopoverlay",
+ ["fr"]="stopperevetement",
+ ["it"]="terminasovrapposizione",
+ ["nl"]="stopoverlay",
+ ["pe"]="پایانپوشش",
+ ["ro"]="stopoverlay",
+ },
+ ["stopoverzicht"]={
+ ["cs"]="stopprehled",
+ ["de"]="stopueberblick",
+ ["en"]="stopoverview",
+ ["fr"]="stoppevuedensemble",
+ ["it"]="terminaoverview",
+ ["nl"]="stopoverzicht",
+ ["pe"]="پایانبازبینی",
+ ["ro"]="stopoverview",
+ },
+ ["stoppacked"]={
+ ["cs"]="stopzhustene",
+ ["de"]="stopkleinerdurchschuss",
+ ["en"]="stoppacked",
+ ["fr"]="stoppegroupe",
+ ["it"]="terminaimpaccato",
+ ["nl"]="stopopelkaar",
+ ["pe"]="پایانفشرده",
+ ["ro"]="stopimpachetat",
+ },
+ ["stoppositioning"]={
+ ["cs"]="stopumistovani",
+ ["de"]="stoppositionieren",
+ ["en"]="stoppositioning",
+ ["fr"]="stoppepositionnement",
+ ["it"]="terminaposizionamento",
+ ["nl"]="stoppositioneren",
+ ["pe"]="پایانمکانگذاری",
+ ["ro"]="stoppozitionare",
+ },
+ ["stopproduct"]={
+ ["cs"]="stopprodukt",
+ ["de"]="stopprodukt",
+ ["en"]="stopproduct",
+ ["fr"]="stoppeproduit",
+ ["it"]="terminaprodotto",
+ ["nl"]="stopprodukt",
+ ["pe"]="پایانتولید",
+ ["ro"]="stopprodus",
+ },
+ ["stopprofile"]={
+ ["cs"]="stopprofil",
+ ["de"]="stopprofil",
+ ["en"]="stopprofile",
+ ["fr"]="stoppeprofil",
+ ["it"]="terminaprofili",
+ ["nl"]="stopprofiel",
+ ["pe"]="پایانپروفایل",
+ ["ro"]="stopprofil",
+ },
+ ["stopproject"]={
+ ["cs"]="stopprojekt",
+ ["de"]="stopprojekt",
+ ["en"]="stopproject",
+ ["fr"]="stoppeprojet",
+ ["it"]="terminaprogetto",
+ ["nl"]="stopprojekt",
+ ["pe"]="پایانپروژه",
+ ["ro"]="stopproiect",
+ },
+ ["stopquotation"]={
+ ["cs"]="stopcitace",
+ ["de"]="stopzitat",
+ ["en"]="stopquotation",
+ ["fr"]="stoppecitation",
+ ["it"]="terminacitazione",
+ ["nl"]="stopcitaat",
+ ["pe"]="پایاننقلقول",
+ ["ro"]="stopcitat",
+ },
+ ["stopraster"]={
+ ["cs"]="stoprastr",
+ ["de"]="stopraster",
+ ["en"]="stopraster",
+ ["fr"]="stopperaster",
+ ["it"]="terminaraster",
+ ["nl"]="stopraster",
+ ["pe"]="stopraster",
+ ["ro"]="stopraster",
+ },
+ ["stopsynchronization"]={
+ ["cs"]="stopsynchronizace",
+ ["de"]="stopsynchronisation",
+ ["en"]="stopsynchronization",
+ ["fr"]="stoppesynchronisation",
+ ["it"]="terminasincronizzazione",
+ ["nl"]="stopsynchronisatie",
+ ["pe"]="پایانتطابق",
+ ["ro"]="stopsincronizare",
+ },
+ ["stoptable"]={
+ ["cs"]="stoptabulka",
+ ["de"]="stoptabelle",
+ ["en"]="stoptable",
+ ["fr"]="stoppetableau",
+ ["it"]="terminatabella",
+ ["nl"]="stoptabel",
+ ["pe"]="پایانجدول",
+ ["ro"]="stoptabel",
+ },
+ ["stoptables"]={
+ ["cs"]="stoptabulky",
+ ["de"]="stoptabellen",
+ ["en"]="stoptables",
+ ["fr"]="stoppetableaux",
+ ["it"]="terminatabelle",
+ ["nl"]="stoptabellen",
+ ["pe"]="پایانجدولها",
+ ["ro"]="stoptabele",
+ },
+ ["stoptext"]={
+ ["cs"]="stoptext",
+ ["de"]="stoptext",
+ ["en"]="stoptext",
+ ["fr"]="stoppetexte",
+ ["it"]="terminatesto",
+ ["nl"]="stoptekst",
+ ["pe"]="پایانمتن",
+ ["ro"]="stoptext",
+ },
+ ["stoptextrule"]={
+ ["cs"]="stoptextovalinka",
+ ["de"]="stoptextlinie",
+ ["en"]="stoptextrule",
+ ["fr"]="stoppeligneregleetexte",
+ ["it"]="terminalineatesto",
+ ["nl"]="stoptekstlijn",
+ ["pe"]="پایانخطمتن",
+ ["ro"]="stopriglatext",
+ },
+ ["stopunpacked"]={
+ ["cs"]="stopnezhustene",
+ ["de"]="stopgrosserdurchschuss",
+ ["en"]="stopunpacked",
+ ["fr"]="stoppedegroupe",
+ ["it"]="terminaunpacked",
+ ["nl"]="stopvanelkaar",
+ ["pe"]="پایانغیرفشرده",
+ ["ro"]="stopneimpachetat",
+ },
+ ["stopversion"]={
+ ["cs"]="stopverze",
+ ["de"]="stopversion",
+ ["en"]="stopversion",
+ ["fr"]="stoppeversion",
+ ["it"]="terminaversioni",
+ ["nl"]="stopversie",
+ ["pe"]="پایاننسخه",
+ ["ro"]="stopversiune",
+ },
+ ["stretched"]={
+ ["cs"]="roztazene",
+ ["de"]="gestreckt",
+ ["en"]="stretched",
+ ["fr"]="etire",
+ ["it"]="stirato",
+ ["nl"]="uitgerekt",
+ ["pe"]="کشیده",
+ ["ro"]="intins",
+ },
+ ["subformulanumber"]={
+ ["cs"]="cislopodrovnice",
+ ["de"]="unterformelnummer",
+ ["en"]="subformulanumber",
+ ["fr"]="numerosousformule",
+ ["it"]="numerosottoformula",
+ ["nl"]="subformulenummer",
+ ["pe"]="شمارهزیرفرمول",
+ ["ro"]="numarsubformula",
+ },
+ ["subpagenumber"]={
+ ["cs"]="subpagenumber",
+ ["de"]="subpagenumber",
+ ["en"]="subpagenumber",
+ ["fr"]="sousnumeropage",
+ ["it"]="subpagenumber",
+ ["nl"]="subpaginanummer",
+ ["pe"]="شمارهزیرصفحه",
+ ["ro"]="subpagenumber",
+ },
+ ["switchtobodyfont"]={
+ ["cs"]="prepninazakladnifont",
+ ["de"]="wechselezumfliesstext",
+ ["en"]="switchtobodyfont",
+ ["fr"]="changepolicecorps",
+ ["it"]="cambiaafontdeltesto",
+ ["nl"]="switchnaarkorps",
+ ["pe"]="تغییربهقلمبدنه",
+ ["ro"]="trecilafonttext",
+ },
+ ["switchtorawfont"]={
+ ["cs"]="switchtorawfont",
+ ["de"]="switchtorawfont",
+ ["en"]="switchtorawfont",
+ ["fr"]="changepolicebrute",
+ ["it"]="passaafontgrezzo",
+ ["nl"]="switchtorawfont",
+ ["pe"]="تغییربهقلمخام",
+ ["ro"]="trecilafontraw",
+ },
+ ["sym"]={
+ ["cs"]="sym",
+ ["de"]="sym",
+ ["en"]="sym",
+ ["fr"]="sym",
+ ["it"]="sim",
+ ["nl"]="sym",
+ ["pe"]="نم",
+ ["ro"]="sim",
+ },
+ ["symbol"]={
+ ["cs"]="symbol",
+ ["de"]="symbol",
+ ["en"]="symbol",
+ ["fr"]="symbole",
+ ["it"]="simbolo",
+ ["nl"]="symbool",
+ ["pe"]="نماد",
+ ["ro"]="simbol",
+ },
+ ["synchronizationbar"]={
+ ["cs"]="synchronizacnilista",
+ ["de"]="synchronisationsbalken",
+ ["en"]="synchronizationbar",
+ ["fr"]="barresynchronisation",
+ ["it"]="barrasincronizzazione",
+ ["nl"]="synchronisatiebalk",
+ ["pe"]="میلهتطابق",
+ ["ro"]="barasincronizare",
+ },
+ ["synchronize"]={
+ ["cs"]="synchronizovat",
+ ["de"]="synchronisieren",
+ ["en"]="synchronize",
+ ["fr"]="synchronise",
+ ["it"]="sincronizza",
+ ["nl"]="synchroniseer",
+ ["pe"]="تطابق",
+ ["ro"]="sincronizeaza",
+ },
+ ["tab"]={
+ ["cs"]="tab",
+ ["de"]="tab",
+ ["en"]="tab",
+ ["fr"]="tab",
+ ["it"]="tab",
+ ["nl"]="tab",
+ ["pe"]="تب",
+ ["ro"]="tab",
+ },
+ ["testcolumn"]={
+ ["cs"]="testcolumn",
+ ["de"]="testcolumn",
+ ["en"]="testcolumn",
+ ["fr"]="testcolumn",
+ ["it"]="testcolumn",
+ ["nl"]="testkolom",
+ ["pe"]="ستونامتحان",
+ ["ro"]="testcolumn",
+ },
+ ["testpage"]={
+ ["cs"]="testpage",
+ ["de"]="testpage",
+ ["en"]="testpage",
+ ["fr"]="testpage",
+ ["it"]="testpage",
+ ["nl"]="testpagina",
+ ["pe"]="صفحهتست",
+ ["ro"]="testpage",
+ },
+ ["tex"]={
+ ["cs"]="tex",
+ ["de"]="tex",
+ ["en"]="tex",
+ ["fr"]="tex",
+ ["it"]="tex",
+ ["nl"]="tex",
+ ["pe"]="تک",
+ ["ro"]="tex",
+ },
+ ["textheight"]={
+ ["cs"]="vyskatextu",
+ ["de"]="texthoehe",
+ ["en"]="textheight",
+ ["fr"]="hauteurtexte",
+ ["it"]="altezzatesto",
+ ["nl"]="teksthoogte",
+ ["pe"]="ارتفاعمتن",
+ ["ro"]="inaltimetext",
+ },
+ ["textreference"]={
+ ["cs"]="odkaznatext",
+ ["de"]="textreferenz",
+ ["en"]="textreference",
+ ["fr"]="referencetexte",
+ ["it"]="riferimentotesto",
+ ["nl"]="tekstreferentie",
+ ["pe"]="مرجعمتن",
+ ["ro"]="referintatext",
+ },
+ ["textrule"]={
+ ["cs"]="textovalinka",
+ ["de"]="textlinie",
+ ["en"]="textrule",
+ ["fr"]="ligneregleetexte",
+ ["it"]="lineatesto",
+ ["nl"]="tekstlijn",
+ ["pe"]="خطمتن",
+ ["ro"]="riglatext",
+ },
+ ["textvariable"]={
+ ["cs"]="textvariable",
+ ["de"]="textvariable",
+ ["en"]="textvariable",
+ ["fr"]="variabletexte",
+ ["it"]="variabiletesto",
+ ["nl"]="tekstvariabele",
+ ["pe"]="متغیر متن",
+ ["ro"]="variabilatext",
+ },
+ ["textwidth"]={
+ ["cs"]="sirkatextu",
+ ["de"]="textbreite",
+ ["en"]="textwidth",
+ ["fr"]="largeurtexte",
+ ["it"]="ampiezzatesto",
+ ["nl"]="tekstbreedte",
+ ["pe"]="عرضمتن",
+ ["ro"]="latimetext",
+ },
+ ["thinrule"]={
+ ["cs"]="tenkalinka",
+ ["de"]="duennelinie",
+ ["en"]="thinrule",
+ ["fr"]="traitfin",
+ ["it"]="lineasottile",
+ ["nl"]="dunnelijn",
+ ["pe"]="خطنازک",
+ ["ro"]="liniesubtire",
+ },
+ ["thinrules"]={
+ ["cs"]="tenkelinky",
+ ["de"]="duennerumriss",
+ ["en"]="thinrules",
+ ["fr"]="traitsfins",
+ ["it"]="lineesottili",
+ ["nl"]="dunnelijnen",
+ ["pe"]="خطهاینازک",
+ ["ro"]="liniisubtiri",
+ },
+ ["tooltip"]={
+ ["cs"]="bublinkovanapoveda",
+ ["de"]="tooltip",
+ ["en"]="tooltip",
+ ["fr"]="suggestion",
+ ["it"]="tooltip",
+ ["nl"]="suggestie",
+ ["pe"]="tooltip",
+ ["ro"]="tooltip",
+ },
+ ["topdistance"]={
+ ["cs"]="vzdalenosthorejsku",
+ ["de"]="abstandoben",
+ ["en"]="topdistance",
+ ["fr"]="distancesup",
+ ["it"]="distanzacima",
+ ["nl"]="bovenafstand",
+ ["pe"]="فاصلهبالا",
+ ["ro"]="distantasus",
+ },
+ ["topheight"]={
+ ["cs"]="vyskahorejsku",
+ ["de"]="hoeheoben",
+ ["en"]="topheight",
+ ["fr"]="hauteursup",
+ ["it"]="altezzacima",
+ ["nl"]="bovenhoogte",
+ ["pe"]="ارتفاعبالا",
+ ["ro"]="inaltimesus",
+ },
+ ["topspace"]={
+ ["cs"]="odsazenishora",
+ ["de"]="kopfweite",
+ ["en"]="topspace",
+ ["fr"]="espacesup",
+ ["it"]="spaziocima",
+ ["nl"]="kopwit",
+ ["pe"]="فضایبالا",
+ ["ro"]="spatiusus",
+ },
+ ["totalnumberofpages"]={
+ ["cs"]="celkovypocetstran",
+ ["de"]="gesamtseitenanzahl",
+ ["en"]="totalnumberofpages",
+ ["fr"]="nombretotaldepages",
+ ["it"]="numerototaledipagine",
+ ["nl"]="totaalaantalpaginas",
+ ["pe"]="شمارهکلصفحهها",
+ ["ro"]="numartotalpagini",
+ },
+ ["translate"]={
+ ["cs"]="prelozit",
+ ["de"]="uebersetzten",
+ ["en"]="translate",
+ ["fr"]="traduire",
+ ["it"]="traduci",
+ ["nl"]="vertaal",
+ ["pe"]="ترجمه",
+ ["ro"]="traduce",
+ },
+ ["txt"]={
+ ["cs"]="txt",
+ ["de"]="txt",
+ ["en"]="txt",
+ ["fr"]="txt",
+ ["it"]="txt",
+ ["nl"]="txt",
+ ["pe"]="txt",
+ ["ro"]="txt",
+ },
+ ["typ"]={
+ ["cs"]="pis",
+ ["de"]="tip",
+ ["en"]="typ",
+ ["fr"]="typ",
+ ["it"]="typ",
+ ["nl"]="typ",
+ ["pe"]="typ",
+ ["ro"]="typ",
+ },
+ ["type"]={
+ ["cs"]="opis",
+ ["de"]="tippen",
+ ["en"]="type",
+ ["fr"]="dactylographier",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ ["typebuffer"]={
+ ["cs"]="typebuffer",
+ ["de"]="tippepuffer",
+ ["en"]="typebuffer",
+ ["fr"]="tapebuffer",
+ ["it"]="typebuffer",
+ ["nl"]="typebuffer",
+ ["pe"]="تایپبافر",
+ ["ro"]="scriebuffer",
+ },
+ ["typefile"]={
+ ["cs"]="opissoubor",
+ ["de"]="tippedatei",
+ ["en"]="typefile",
+ ["fr"]="fichierdactylo",
+ ["it"]="typefile",
+ ["nl"]="typefile",
+ ["pe"]="تایپپرونده",
+ ["ro"]="typefile",
+ },
+ ["unitmeaning"]={
+ ["cs"]="vyznam",
+ ["de"]="bedeutung",
+ ["en"]="unitmeaning",
+ ["fr"]="sensunite",
+ ["it"]="nomeunita",
+ ["nl"]="betekenis",
+ ["pe"]="معنیواحد",
+ ["ro"]="numeunitate",
+ },
+ ["unknown"]={
+ ["cs"]="neznamo",
+ ["de"]="unbekant",
+ ["en"]="unknown",
+ ["fr"]="inconnu",
+ ["it"]="ignoto",
+ ["nl"]="onbekend",
+ ["pe"]="ناشناس",
+ ["ro"]="necunoscut",
+ },
+ ["useJSscripts"]={
+ ["cs"]="uzijJSscripts",
+ ["de"]="verwendeJSscript",
+ ["en"]="useJSscripts",
+ ["fr"]="utiliseJSscripts",
+ ["it"]="usaJSscripts",
+ ["nl"]="gebruikJSscripts",
+ ["pe"]="useJSscripts",
+ ["ro"]="folosestescriptJS",
+ },
+ ["useURL"]={
+ ["cs"]="uzijURL",
+ ["de"]="verwendeURL",
+ ["en"]="useURL",
+ ["fr"]="utiliseURL",
+ ["it"]="usaURL",
+ ["nl"]="gebruikURL",
+ ["pe"]="useURL",
+ ["ro"]="folosesteURL",
+ },
+ ["useXMLfilter"]={
+ ["cs"]="useXMLfilter",
+ ["de"]="useXMLfilter",
+ ["en"]="useXMLfilter",
+ ["fr"]="useXMLfilter",
+ ["it"]="useXMLfilter",
+ ["nl"]="gebruikXMLfilter",
+ ["pe"]="useXMLfilter",
+ ["ro"]="useXMLfilter",
+ },
+ ["useblocks"]={
+ ["cs"]="uzijbloky",
+ ["de"]="verwendebloecke",
+ ["en"]="useblocks",
+ ["fr"]="utiliseblocs",
+ ["it"]="usablocco",
+ ["nl"]="gebruikblokken",
+ ["pe"]="استفادهبلوکها",
+ ["ro"]="folosestebloc",
+ },
+ ["usecommands"]={
+ ["cs"]="uzijprikazy",
+ ["de"]="verwendebefehl",
+ ["en"]="usecommands",
+ ["fr"]="utilisecommandes",
+ ["it"]="usacomandi",
+ ["nl"]="gebruikcommandos",
+ ["pe"]="استفادهفرمانها",
+ ["ro"]="folosestecomenzi",
+ },
+ ["useencoding"]={
+ ["cs"]="uzijkodovani",
+ ["de"]="benutzekodierung",
+ ["en"]="useencoding",
+ ["fr"]="utiliseencodage",
+ ["it"]="usacodifica",
+ ["nl"]="usecodering",
+ ["pe"]="استفادهرمزینه",
+ ["ro"]="folosestecodificarea",
+ },
+ ["useexternaldocument"]={
+ ["cs"]="uzijexternidokument",
+ ["de"]="verwendeexteresdokument",
+ ["en"]="useexternaldocument",
+ ["fr"]="utilisedocumentexterne",
+ ["it"]="usadocumentoesterno",
+ ["nl"]="gebruikexterndocument",
+ ["pe"]="استفادهنوشتارخارجی",
+ ["ro"]="folosestedocumentextern",
+ },
+ ["useexternalfigure"]={
+ ["cs"]="uzijexterniobraz",
+ ["de"]="verwendeexterneabbildung",
+ ["en"]="useexternalfigure",
+ ["fr"]="utilisefigureexterne",
+ ["it"]="usafiguraesterna",
+ ["nl"]="gebruikexternfiguur",
+ ["pe"]="استفادهشکلخارجی",
+ ["ro"]="folosestefiguraexterna",
+ },
+ ["useexternalfile"]={
+ ["cs"]="uzijexternisoubor",
+ ["de"]="verwendeexternedatei",
+ ["en"]="useexternalfile",
+ ["fr"]="utilisefichierexterne",
+ ["it"]="usafileesterno",
+ ["nl"]="gebruikexternefile",
+ ["pe"]="استفادهپروندهخارجی",
+ ["ro"]="folosestefisierextern",
+ },
+ ["useexternalfiles"]={
+ ["cs"]="uzijexternisoubory",
+ ["de"]="verwendeexternedateien",
+ ["en"]="useexternalfiles",
+ ["fr"]="utilisefichiersexternes",
+ ["it"]="usafileesterni",
+ ["nl"]="gebruikexternefiles",
+ ["pe"]="استفادهپروندههایخارجی",
+ ["ro"]="folosestefisiereexterne",
+ },
+ ["useexternalsoundtrack"]={
+ ["cs"]="uzijexternizvuk",
+ ["de"]="verwendeexternestonstueck",
+ ["en"]="useexternalsoundtrack",
+ ["fr"]="utilisepsiteaudioexterne",
+ ["it"]="usacolonnasonoraesterna",
+ ["nl"]="gebruikexterngeluidsfragment",
+ ["pe"]="استفادهقطعهموزیکخارجی",
+ ["ro"]="folosestemuzicaexterna",
+ },
+ ["usemodule"]={
+ ["cs"]="uzijmodul",
+ ["de"]="verwendemodul",
+ ["en"]="usemodule",
+ ["fr"]="utilisemodule",
+ ["it"]="usamodulo",
+ ["nl"]="gebruikmodule",
+ ["pe"]="استفادهمدول",
+ ["ro"]="folosestemodul",
+ },
+ ["usemodules"]={
+ ["cs"]="uzijmoduly",
+ ["de"]="verwendemodule",
+ ["en"]="usemodules",
+ ["fr"]="utilisemodules",
+ ["it"]="usamoduli",
+ ["nl"]="gebruikmodules",
+ ["pe"]="استفادهمدولها",
+ ["ro"]="folosestemodule",
+ },
+ ["usepath"]={
+ ["cs"]="uzijadresar",
+ ["de"]="benutzeverzeichnis",
+ ["en"]="usedirectory",
+ ["fr"]="utilisechemin",
+ ["it"]="usacartella",
+ ["nl"]="gebruikgebied",
+ ["pe"]="استفادهمسیر",
+ ["ro"]="folosestedirector",
+ },
+ ["usereferences"]={
+ ["cs"]="uzijodkazy",
+ ["de"]="verwendereferenzen",
+ ["en"]="usereferences",
+ ["fr"]="utilisereferences",
+ ["it"]="usariferimenti",
+ ["nl"]="gebruikreferenties",
+ ["pe"]="استفادهمرجعها",
+ ["ro"]="folosestereferinte",
+ },
+ ["usespecials"]={
+ ["cs"]="uzijspeciality",
+ ["de"]="benutzespezielles",
+ ["en"]="usespecials",
+ ["fr"]="utilisespecialites",
+ ["it"]="usaspecialita",
+ ["nl"]="gebruikspecials",
+ ["pe"]="استفادهویژگیها",
+ ["ro"]="folosestespeciale",
+ },
+ ["usesymbols"]={
+ ["cs"]="uzijsymbol",
+ ["de"]="verwendesymbole",
+ ["en"]="usesymbols",
+ ["fr"]="utilisesymboles",
+ ["it"]="usasimboli",
+ ["nl"]="gebruiksymbolen",
+ ["pe"]="استفادهنمادها",
+ ["ro"]="folosestesimboluri",
+ },
+ ["usetypescript"]={
+ ["cs"]="usetypescript",
+ ["de"]="usetypescript",
+ ["en"]="usetypescript",
+ ["fr"]="usetypescript",
+ ["it"]="usetypescript",
+ ["nl"]="gebruiktypescript",
+ ["pe"]="استفادهدستخطتایپ",
+ ["ro"]="usetypescript",
+ },
+ ["usetypescriptfile"]={
+ ["cs"]="usetypescriptfile",
+ ["de"]="usetypescriptfile",
+ ["en"]="usetypescriptfile",
+ ["it"]="usetypescriptfile",
+ ["nl"]="gebruiktypescriptfile",
+ ["pe"]="استفادهپروندهدستخطتایپ",
+ ["ro"]="usetypescriptfile",
+ },
+ ["useurl"]={
+ ["cs"]="uzijurl",
+ ["de"]="verwendeurl",
+ ["en"]="useurl",
+ ["fr"]="utiliseurl",
+ ["it"]="usaurl",
+ ["nl"]="gebruikurl",
+ ["pe"]="useurl",
+ ["ro"]="folosesteurl",
+ },
+ ["version"]={
+ ["cs"]="verze",
+ ["de"]="version",
+ ["en"]="version",
+ ["fr"]="version",
+ ["it"]="versione",
+ ["nl"]="versie",
+ ["pe"]="نسخه",
+ ["ro"]="versiune",
+ },
+ ["vl"]={
+ ["cs"]="vl",
+ ["de"]="vl",
+ ["en"]="vl",
+ ["fr"]="vl",
+ ["it"]="vl",
+ ["nl"]="vl",
+ ["pe"]="خع",
+ ["ro"]="vl",
+ },
+ ["weekday"]={
+ ["cs"]="vsedniden",
+ ["de"]="wochentag",
+ ["en"]="weekday",
+ ["fr"]="joursemaine",
+ ["it"]="giornosettimana",
+ ["nl"]="weekdag",
+ ["pe"]="روزهفته",
+ ["ro"]="zidinsaptamana",
+ },
+ ["whitespace"]={
+ ["cs"]="bilemisto",
+ ["de"]="zwischenraum",
+ ["en"]="whitespace",
+ ["fr"]="espaceblanc",
+ ["it"]="spaziobianco",
+ ["nl"]="witruimte",
+ ["pe"]="فضایسفید",
+ ["ro"]="spatiualb",
+ },
+ ["wordright"]={
+ ["cs"]="slovovpravo",
+ ["de"]="wortrechts",
+ ["en"]="wordright",
+ ["fr"]="motdroit",
+ ["it"]="paroladestra",
+ ["nl"]="woordrechts",
+ ["pe"]="کلمهراست",
+ ["ro"]="cuvantdreapta",
+ },
+ ["writebetweenlist"]={
+ ["cs"]="zapismeziseznam",
+ ["de"]="schreibezwischenliste",
+ ["en"]="writebetweenlist",
+ ["fr"]="ecritentreliste",
+ ["it"]="scrividentroelenco",
+ ["nl"]="schrijftussenlijst",
+ ["pe"]="بنویسبینلیست",
+ ["ro"]="scrieintreliste",
+ },
+ ["writetolist"]={
+ ["cs"]="zapisdoseznamu",
+ ["de"]="schreibezurliste",
+ ["en"]="writetolist",
+ ["fr"]="ecritdansliste",
+ ["it"]="scriviinelenco",
+ ["nl"]="schrijfnaarlijst",
+ ["pe"]="بنویسدرلیست",
+ ["ro"]="scrieinlista",
+ },
+ ["writetoreferencelist"]={
+ ["cs"]="zapisdoseznamuodkazu",
+ ["de"]="schreibezurreferenzliste",
+ ["en"]="writetoreferencelist",
+ ["fr"]="ecritdanslistereference",
+ ["it"]="scriviinlistariferimenti",
+ ["nl"]="schrijfnaarreferentielijst",
+ ["pe"]="بنویسدرلیستمرجع",
+ ["ro"]="scrieinlistareferinte",
+ },
+ ["writetoregister"]={
+ ["cs"]="zapisdorejstriku",
+ ["de"]="schreibezumregister",
+ ["en"]="writetoregister",
+ ["fr"]="ecritregistre",
+ ["it"]="scriviinregistro",
+ ["nl"]="schrijfnaarregister",
+ ["pe"]="بنویسدرثبت",
+ ["ro"]="scrieinregistru",
+ },
+ },
+ ["constants"]={
+ ["strip"]={
+ ["en"]="strip",
+ },
+ ["order"]={
+ ["en"]="order",
+ },
+ ["headalign"]={
+ ["en"]="headalign",
+ ["nl"]="kopuitlijnen",
+ },
+ ["alignsymbol"]={
+ ["en"]="alignsymbol",
+ },
+ ["export"]={
+ ["en"]="export",
+ ["nl"]="exporteer",
+ },
+ ["database"]={
+ ["en"]="database",
+ },
+ ["artauthor"]={
+ ["en"]="artauthor",
+ },
+ ["editor"]={
+ ["en"]="editor",
+ },
+ ["authoretallimit"]={
+ ["en"]="authoretallimit",
+ },
+ ["artauthoretallimit"]={
+ ["en"]="artauthoretallimit",
+ },
+ ["editoretallimit"]={
+ ["en"]="editoretallimit",
+ },
+ ["authoretaldisplay"]={
+ ["en"]="authoretaldisplay",
+ },
+ ["artauthoretaldisplay"]={
+ ["en"]="artauthoretaldisplay",
+ },
+ ["editoretaldisplay"]={
+ ["en"]="editoretaldisplay",
+ },
+ ["authoretaltext"]={
+ ["en"]="authoretaltext",
+ },
+ ["artauthoretaltext"]={
+ ["en"]="artauthoretaltext",
+ },
+ ["editoretaltext"]={
+ ["en"]="editoretaltext",
+ },
+ ["otherstext"]={
+ ["en"]="otherstext",
+ },
+ ["andtext"]={
+ ["en"]="andtext",
+ },
+ ["totalnumber"]={
+ ["en"]="totalnumber",
+ },
+ ["firstnamesep"]={
+ ["en"]="firstnamesep",
+ },
+ ["vonsep"]={
+ ["en"]="vonsep",
+ },
+ ["juniorsep"]={
+ ["en"]="juniorsep",
+ },
+ ["surnamesep"]={
+ ["en"]="surnamesep",
+ },
+ ["lastnamesep"]={
+ ["en"]="lastnamesep",
+ },
+ ["finalnamesep"]={
+ ["en"]="finalnamesep",
+ },
+ ["namesep"]={
+ ["en"]="namesep",
+ },
+ ["pubsep"]={
+ ["en"]="pubsep",
+ },
+ ["lastpubsep"]={
+ ["en"]="lastpubsep",
+ },
+ ["refcommand"]={
+ ["en"]="refcommand",
+ },
+ ["samplesize"]={
+ ["en"]="samplesize",
+ },
+ ["maybeyear"]={
+ ["en"]="maybeyear",
+ },
+ ["action"]={
+ ["cs"]="akce",
+ ["de"]="aktion",
+ ["en"]="action",
+ ["fr"]="action",
+ ["it"]="azione",
+ ["nl"]="actie",
+ ["pe"]="کنش",
+ ["ro"]="actiune",
+ },
+ ["address"]={
+ ["cs"]="adresa",
+ ["de"]="adresse",
+ ["en"]="address",
+ ["fr"]="adresse",
+ ["it"]="indirizzo",
+ ["nl"]="adres",
+ ["pe"]="نشانی",
+ ["ro"]="adresa",
+ },
+ ["after"]={
+ ["cs"]="po",
+ ["de"]="nach",
+ ["en"]="after",
+ ["fr"]="apres",
+ ["it"]="dopo",
+ ["nl"]="na",
+ ["pe"]="بعداز",
+ ["ro"]="dupa",
+ },
+ ["afterhead"]={
+ ["cs"]="pohlavicce",
+ ["de"]="nachkopf",
+ ["en"]="afterhead",
+ ["fr"]="aprestete",
+ ["it"]="dopotesta",
+ ["nl"]="kopna",
+ ["pe"]="بعدازسر",
+ ["ro"]="dupatitlu",
+ },
+ ["afterkey"]={
+ ["cs"]="klavesapo",
+ ["de"]="nachtaste",
+ ["en"]="afterkey",
+ ["fr"]="aprescle",
+ ["it"]="dopotasto",
+ ["nl"]="natoets",
+ ["pe"]="بعدازکلید",
+ ["ro"]="dupatasta",
+ },
+ ["align"]={
+ ["cs"]="zarovnani",
+ ["de"]="ausrichtung",
+ ["en"]="align",
+ ["fr"]="alignement",
+ ["it"]="allinea",
+ ["nl"]="uitlijnen",
+ ["pe"]="تنظیم",
+ ["ro"]="aliniere",
+ },
+ ["aligncharacter"]={
+ ["cs"]="aligncharacter",
+ ["de"]="aligncharacter",
+ ["en"]="aligncharacter",
+ ["fr"]="caracterealigne",
+ ["it"]="allineacarattere",
+ ["nl"]="karakteruitlijnen",
+ ["pe"]="حرفتنظیم",
+ ["ro"]="aliniazacaracter",
+ },
+ ["alignmentcharacter"]={
+ ["cs"]="alignmentcharacter",
+ ["de"]="alignmentcharacter",
+ ["en"]="alignmentcharacter",
+ ["fr"]="alignementcaractere",
+ ["it"]="carattereallineamento",
+ ["nl"]="uitlijnkarakter",
+ ["pe"]="حرفتنظیمکردن",
+ ["ro"]="alierecaracter",
+ },
+ ["aligntitle"]={
+ ["cs"]="zarovnejtitul",
+ ["de"]="titelausrichten",
+ ["en"]="aligntitle",
+ ["fr"]="alignementtitre",
+ ["it"]="allineatitolo",
+ ["nl"]="titeluitlijnen",
+ ["pe"]="عنوانتنظیم",
+ ["ro"]="alinieretitlu",
+ },
+ ["alternative"]={
+ ["cs"]="alternativa",
+ ["de"]="alternative",
+ ["en"]="alternative",
+ ["fr"]="alternative",
+ ["it"]="alternativa",
+ ["nl"]="variant",
+ ["pe"]="جایگزین",
+ ["ro"]="alternativ",
+ },
+ ["apa"]={
+ ["cs"]="apa",
+ ["de"]="apa",
+ ["en"]="apa",
+ ["fr"]="apa",
+ ["it"]="apa",
+ ["nl"]="apa",
+ ["pe"]="apa",
+ ["ro"]="apa",
+ },
+ ["arrow"]={
+ ["cs"]="sipka",
+ ["de"]="pfeil",
+ ["en"]="arrow",
+ ["fr"]="fleche",
+ ["it"]="freccia",
+ ["nl"]="pijl",
+ ["pe"]="پیکان",
+ ["ro"]="sageata",
+ },
+ ["at"]={
+ ["cs"]="u",
+ ["de"]="bei",
+ ["en"]="at",
+ ["fr"]="a",
+ ["it"]="ad",
+ ["nl"]="op",
+ ["pe"]="در",
+ ["ro"]="la",
+ },
+ ["author"]={
+ ["cs"]="autor",
+ ["de"]="autor",
+ ["en"]="author",
+ ["fr"]="auteur",
+ ["it"]="autore",
+ ["nl"]="auteur",
+ ["pe"]="نویسنده",
+ ["ro"]="autor",
+ },
+ ["auto"]={
+ ["cs"]="auto",
+ ["de"]="auto",
+ ["en"]="auto",
+ ["fr"]="auto",
+ ["it"]="auto",
+ ["nl"]="auto",
+ ["pe"]="خودکار",
+ ["ro"]="auto",
+ },
+ ["autofile"]={
+ ["cs"]="autofile",
+ ["de"]="autofile",
+ ["en"]="autofile",
+ ["fr"]="autofile",
+ ["it"]="autofile",
+ ["nl"]="autofile",
+ ["pe"]="پروندهخودکار",
+ ["ro"]="autofile",
+ },
+ ["autofocus"]={
+ ["cs"]="autoostreni",
+ ["de"]="autofocus",
+ ["en"]="autofocus",
+ ["fr"]="autofocus",
+ ["it"]="autofocus",
+ ["nl"]="autofocus",
+ ["pe"]="تمرکزخودکار",
+ ["ro"]="autofocus",
+ },
+ ["autohang"]={
+ ["cs"]="autohang",
+ ["de"]="autohang",
+ ["en"]="autohang",
+ ["fr"]="autohang",
+ ["it"]="autohang",
+ ["nl"]="autohang",
+ ["pe"]="آویزانخودکار",
+ ["ro"]="autohang",
+ },
+ ["autostrut"]={
+ ["cs"]="autostrut",
+ ["de"]="autostrut",
+ ["en"]="autostrut",
+ ["fr"]="autostrut",
+ ["it"]="autostrut",
+ ["nl"]="autostrut",
+ ["pe"]="بستخودکار",
+ ["ro"]="autostrut",
+ },
+ ["autowidth"]={
+ ["cs"]="autosirka",
+ ["de"]="autobreite",
+ ["en"]="autowidth",
+ ["fr"]="autolargeur",
+ ["it"]="autoampiezza",
+ ["nl"]="autobreedte",
+ ["pe"]="عرضخودکار",
+ ["ro"]="autolatime",
+ },
+ ["axis"]={
+ ["cs"]="osa",
+ ["de"]="achsen",
+ ["en"]="axis",
+ ["fr"]="axe",
+ ["it"]="asse",
+ ["nl"]="assenstelsel",
+ ["pe"]="محورها",
+ ["ro"]="axa",
+ },
+ ["background"]={
+ ["cs"]="pozadi",
+ ["de"]="hintergrund",
+ ["en"]="background",
+ ["fr"]="arriereplan",
+ ["it"]="sfondo",
+ ["nl"]="achtergrond",
+ ["pe"]="پسزمینه",
+ ["ro"]="fundal",
+ },
+ ["backgroundcolor"]={
+ ["cs"]="barvapozadi",
+ ["de"]="hintergrundfarbe",
+ ["en"]="backgroundcolor",
+ ["fr"]="couleurarriereplan",
+ ["it"]="coloresfondo",
+ ["nl"]="achtergrondkleur",
+ ["pe"]="رنگپسزمینه",
+ ["ro"]="culoarefundal",
+ },
+ ["backgroundcorner"]={
+ ["cs"]="rohpozadi",
+ ["de"]="hintergrundwinkel",
+ ["en"]="backgroundcorner",
+ ["fr"]="coinarriereplan",
+ ["it"]="angolosfondo",
+ ["nl"]="achtergrondhoek",
+ ["pe"]="گوشهپسزمینه",
+ ["ro"]="coltfundal",
+ },
+ ["backgrounddepth"]={
+ ["cs"]="hloubkapozadi",
+ ["de"]="hintergrundtiefe",
+ ["en"]="backgrounddepth",
+ ["fr"]="profondeurarriereplan",
+ ["it"]="profonditasfondo",
+ ["nl"]="achtergronddiepte",
+ ["pe"]="عمقپسزمینه",
+ ["ro"]="adancimefundal",
+ },
+ ["backgroundoffset"]={
+ ["cs"]="offsetpozadi",
+ ["de"]="hintergrundoffset",
+ ["en"]="backgroundoffset",
+ ["fr"]="decalagearriereplan",
+ ["it"]="offsetsfondo",
+ ["nl"]="achtergrondoffset",
+ ["pe"]="آفستپسزمینه",
+ ["ro"]="offsetfundal",
+ },
+ ["backgroundradius"]={
+ ["cs"]="polomerpozadi",
+ ["de"]="hintergrundradius",
+ ["en"]="backgroundradius",
+ ["fr"]="rayonarriereplan",
+ ["it"]="raggiosfondo",
+ ["nl"]="achtergrondstraal",
+ ["pe"]="شعاعپسزمینه",
+ ["ro"]="razafundal",
+ },
+ ["backgroundscreen"]={
+ ["cs"]="rastrpozadi",
+ ["de"]="hintergrundraster",
+ ["en"]="backgroundscreen",
+ ["fr"]="ecranarriereplan",
+ ["it"]="schermosfondo",
+ ["nl"]="achtergrondraster",
+ ["pe"]="پردهپسزمینه",
+ ["ro"]="ecranfundal",
+ },
+ ["backspace"]={
+ ["cs"]="zpetnamezera",
+ ["de"]="rumpfspatium",
+ ["en"]="backspace",
+ ["fr"]="retour",
+ ["it"]="backspace",
+ ["nl"]="rugwit",
+ ["pe"]="فضایپس",
+ ["ro"]="spatiuspate",
+ },
+ ["balance"]={
+ ["cs"]="rovnovaha",
+ ["de"]="ausgleichen",
+ ["en"]="balance",
+ ["fr"]="equilibre",
+ ["it"]="bilanciamento",
+ ["nl"]="balanceren",
+ ["pe"]="تعادل",
+ ["ro"]="balanta",
+ },
+ ["before"]={
+ ["cs"]="pred",
+ ["de"]="vor",
+ ["en"]="before",
+ ["fr"]="avant",
+ ["it"]="prima",
+ ["nl"]="voor",
+ ["pe"]="قبلاز",
+ ["ro"]="inainte",
+ },
+ ["beforehead"]={
+ ["cs"]="predhlavickou",
+ ["de"]="vorkopf",
+ ["en"]="beforehead",
+ ["fr"]="avanttete",
+ ["it"]="primaditesta",
+ ["nl"]="kopvoor",
+ ["pe"]="قبلازسر",
+ ["ro"]="inaintetitlu",
+ },
+ ["bet"]={
+ ["cs"]="bet",
+ ["de"]="bet",
+ ["en"]="bet",
+ ["fr"]="bet",
+ ["it"]="bet",
+ ["nl"]="bet",
+ ["pe"]="bet",
+ ["ro"]="bet",
+ },
+ ["big"]={
+ ["cs"]="velky",
+ ["de"]="gross",
+ ["en"]="big",
+ ["fr"]="grand",
+ ["it"]="grande",
+ ["nl"]="groot",
+ ["pe"]="بزرگ",
+ ["ro"]="mare",
+ },
+ ["blank"]={
+ ["cs"]="prazdny",
+ ["de"]="blanko",
+ ["en"]="blank",
+ ["fr"]="vide",
+ ["it"]="rigovuoto",
+ ["nl"]="blanko",
+ ["pe"]="خالی",
+ ["ro"]="blanc",
+ },
+ ["blockway"]={
+ ["cs"]="dobloku",
+ ["de"]="blockauf",
+ ["en"]="blockway",
+ ["fr"]="blockway",
+ ["it"]="blockway",
+ ["nl"]="blokwijze",
+ ["pe"]="راهبلوک",
+ ["ro"]="blockway",
+ },
+ ["bodyfont"]={
+ ["cs"]="zakladnifont",
+ ["de"]="fliesstext",
+ ["en"]="bodyfont",
+ ["fr"]="policecorps",
+ ["it"]="fonttesto",
+ ["nl"]="korps",
+ ["pe"]="قلمبدنه",
+ ["ro"]="fonttext",
+ },
+ ["bookmark"]={
+ ["cs"]="zalozka",
+ ["de"]="bookmark",
+ ["en"]="bookmark",
+ ["fr"]="marquepage",
+ ["it"]="segnalibro",
+ ["nl"]="bookmark",
+ ["pe"]="چوبخط",
+ ["ro"]="semncarte",
+ },
+ ["bottom"]={
+ ["cs"]="spodek",
+ ["de"]="unten",
+ ["en"]="bottom",
+ ["fr"]="inf",
+ ["it"]="fondo",
+ ["nl"]="onder",
+ ["pe"]="پایین",
+ ["ro"]="jos",
+ },
+ ["bottomafter"]={
+ ["en"]="bottomafter",
+ },
+ ["bottombefore"]={
+ ["en"]="bottombefore",
+ },
+ ["bottomdistance"]={
+ ["cs"]="vzdalenostspodku",
+ ["de"]="abstandunten",
+ ["en"]="bottomdistance",
+ ["fr"]="distanceinf",
+ ["it"]="distanzafondo",
+ ["nl"]="onderafstand",
+ ["pe"]="فاصلهپایین",
+ ["ro"]="distantajos",
+ },
+ ["bottomframe"]={
+ ["cs"]="ramecekdole",
+ ["de"]="untenrahmen",
+ ["en"]="bottomframe",
+ ["fr"]="cadreinf",
+ ["it"]="cornicefondo",
+ ["nl"]="onderkader",
+ ["pe"]="قالبپایین",
+ ["ro"]="framejos",
+ },
+ ["bottomoffset"]={
+ ["cs"]="offsetspodku",
+ ["de"]="untenoffset",
+ ["en"]="bottomoffset",
+ ["fr"]="decalageinf",
+ ["it"]="offsetfondo",
+ ["nl"]="onderoffset",
+ ["pe"]="آفستپایین",
+ ["ro"]="offsetjos",
+ },
+ ["bottomspace"]={
+ ["cs"]="bottomspace",
+ ["de"]="bottomspace",
+ ["en"]="bottomspace",
+ ["fr"]="espaceinf",
+ ["it"]="spaziofondo",
+ ["nl"]="bodemwit",
+ ["pe"]="فضایپایین",
+ ["ro"]="spatiujos",
+ },
+ ["bottomstate"]={
+ ["cs"]="statusspodku",
+ ["de"]="untenstatus",
+ ["en"]="bottomstate",
+ ["fr"]="etatinf",
+ ["it"]="statofondo",
+ ["nl"]="onderstatus",
+ ["pe"]="وضعیتپایین",
+ ["ro"]="starejos",
+ },
+ ["cache"]={
+ ["cs"]="cache",
+ ["de"]="cache",
+ ["en"]="cache",
+ ["fr"]="cache",
+ ["it"]="cache",
+ ["nl"]="cache",
+ ["pe"]="میانگیر",
+ ["ro"]="cache",
+ },
+ ["calculate"]={
+ ["cs"]="pocitat",
+ ["de"]="berechnen",
+ ["en"]="calculate",
+ ["fr"]="calculer",
+ ["it"]="calcola",
+ ["nl"]="bereken",
+ ["pe"]="محاسبه",
+ ["ro"]="calculeaza",
+ },
+ ["ccommand"]={
+ ["cs"]="cprikaz",
+ ["de"]="cbefehl",
+ ["en"]="ccommand",
+ ["fr"]="ccommande",
+ ["it"]="ccomando",
+ ["nl"]="ccommando",
+ ["pe"]="فرمان",
+ ["ro"]="comandac",
+ },
+ ["click"]={
+ ["cs"]="klik",
+ ["de"]="klick",
+ ["en"]="click",
+ ["fr"]="clic",
+ ["it"]="click",
+ ["nl"]="klik",
+ ["pe"]="فشردن",
+ ["ro"]="click",
+ },
+ ["clickin"]={
+ ["cs"]="klikuvnitr",
+ ["de"]="klickin",
+ ["en"]="clickin",
+ ["fr"]="clicinterieur",
+ ["it"]="clickdentro",
+ ["nl"]="klikin",
+ ["pe"]="فشردنداخل",
+ ["ro"]="clickintru",
+ },
+ ["clickout"]={
+ ["cs"]="klikvne",
+ ["de"]="klickaus",
+ ["en"]="clickout",
+ ["fr"]="clicexterieur",
+ ["it"]="clickfuori",
+ ["nl"]="klikuit",
+ ["pe"]="فشردنخارج",
+ ["ro"]="clickies",
+ },
+ ["clipoffset"]={
+ ["cs"]="clipoffset",
+ ["de"]="clipoffset",
+ ["en"]="clipoffset",
+ ["fr"]="clipoffset",
+ ["it"]="clipoffset",
+ ["nl"]="clipoffset",
+ ["pe"]="آفستکلیپ",
+ ["ro"]="clipoffset",
+ },
+ ["closeaction"]={
+ ["cs"]="zavriakci",
+ ["de"]="schliessenaktion",
+ ["en"]="closeaction",
+ ["fr"]="actionfermeture",
+ ["it"]="azionechiudi",
+ ["nl"]="sluitactie",
+ ["pe"]="بستنکنش",
+ ["ro"]="actiuneinchidere",
+ },
+ ["closecommand"]={
+ ["cs"]="closecommand",
+ ["de"]="closecommand",
+ ["en"]="closecommand",
+ ["fr"]="closecommand",
+ ["it"]="closecommand",
+ ["nl"]="sluitcommando",
+ ["pe"]="بستنفرمان",
+ ["ro"]="closecommand",
+ },
+ ["closepageaction"]={
+ ["cs"]="akcezavrenistranky",
+ ["de"]="closepageaction",
+ ["en"]="closepageaction",
+ ["fr"]="actionfermeturepage",
+ ["it"]="azionechiudipagina",
+ ["nl"]="sluitpaginaactie",
+ ["pe"]="بستنعملصفحه",
+ ["ro"]="actiuneinchiderepagina",
+ },
+ ["closesymbol"]={
+ ["cs"]="closesymbol",
+ ["de"]="closesymbol",
+ ["en"]="closesymbol",
+ ["fr"]="closesymbol",
+ ["it"]="closesymbol",
+ ["nl"]="sluitsymbool",
+ ["pe"]="بستننماد",
+ ["ro"]="closesymbol",
+ },
+ ["color"]={
+ ["cs"]="barva",
+ ["de"]="farbe",
+ ["en"]="color",
+ ["fr"]="couleur",
+ ["it"]="colore",
+ ["nl"]="kleur",
+ ["pe"]="رنگ",
+ ["ro"]="culoare",
+ },
+ ["intent"]={
+ ["en"]="intent",
+ },
+ ["column"]={
+ ["cs"]="sloupec",
+ ["de"]="spalte",
+ ["en"]="column",
+ ["fr"]="colonne",
+ ["it"]="colonna",
+ ["nl"]="kolom",
+ ["pe"]="ستون",
+ ["ro"]="coloana",
+ },
+ ["columndistance"]={
+ ["cs"]="vzdalenostsloupcu",
+ ["de"]="spaltenabstand",
+ ["en"]="columndistance",
+ ["fr"]="distancecolonne",
+ ["it"]="distanzacolonne",
+ ["nl"]="kolomafstand",
+ ["pe"]="فاصلهستون",
+ ["ro"]="distantacoloane",
+ },
+ ["columns"]={
+ ["cs"]="sloupce",
+ ["de"]="spalten",
+ ["en"]="columns",
+ ["fr"]="colonnes",
+ ["it"]="colonne",
+ ["nl"]="kolommen",
+ ["pe"]="ستونها",
+ ["ro"]="coloane",
+ },
+ ["command"]={
+ ["cs"]="prikaz",
+ ["de"]="befehl",
+ ["en"]="command",
+ ["fr"]="commande",
+ ["it"]="comando",
+ ["nl"]="commando",
+ ["pe"]="فرمان",
+ ["ro"]="comanda",
+ },
+ ["commandafter"]={
+ ["cs"]="prikazpo",
+ ["de"]="zumbefehl",
+ ["en"]="commandafter",
+ ["fr"]="commandeapres",
+ ["it"]="comdandodopo",
+ ["nl"]="nacommando",
+ ["pe"]="فرمانبعداز",
+ ["ro"]="comandadupa",
+ },
+ ["commandbefore"]={
+ ["cs"]="predchoziprikaz",
+ ["de"]="vorbefehl",
+ ["en"]="commandbefore",
+ ["fr"]="commandeavant",
+ ["it"]="comandoprima",
+ ["nl"]="voorcommando",
+ ["pe"]="فرمانقبلاز",
+ ["ro"]="comandainainte",
+ },
+ ["commands"]={
+ ["cs"]="prikazy",
+ ["de"]="befehle",
+ ["en"]="commands",
+ ["fr"]="commandes",
+ ["it"]="comandi",
+ ["nl"]="commandos",
+ ["pe"]="فرمانها",
+ ["ro"]="comenzi",
+ },
+ ["component"]={
+ ["cs"]="component",
+ ["de"]="component",
+ ["en"]="component",
+ ["fr"]="composant",
+ ["it"]="component",
+ ["nl"]="component",
+ ["pe"]="مولفه",
+ ["ro"]="component",
+ },
+ ["compoundhyphen"]={
+ ["cs"]="compoundhyphen",
+ ["de"]="compoundhyphen",
+ ["en"]="compoundhyphen",
+ ["fr"]="compoundhyphen",
+ ["it"]="compoundhyphen",
+ ["nl"]="koppelteken",
+ ["pe"]="compoundhyphen",
+ ["ro"]="compoundhyphen",
+ },
+ ["compress"]={
+ ["cs"]="compress",
+ ["de"]="compress",
+ ["en"]="compress",
+ ["fr"]="compress",
+ ["it"]="compress",
+ ["nl"]="comprimeren",
+ ["pe"]="فشردن",
+ ["ro"]="compress",
+ },
+ ["connector"]={
+ ["en"]="connector",
+ },
+ ["continue"]={
+ ["cs"]="pokracovat",
+ ["de"]="fortsetzen",
+ ["en"]="continue",
+ ["fr"]="continue",
+ ["it"]="continua",
+ ["nl"]="doorgaan",
+ ["pe"]="ادامه",
+ ["ro"]="continua",
+ },
+ ["contrastcolor"]={
+ ["cs"]="kontrastnibarva",
+ ["de"]="kontrastfarbe",
+ ["en"]="contrastcolor",
+ ["fr"]="coleurcontraste",
+ ["it"]="colorecontrasto",
+ ["nl"]="contrastkleur",
+ ["pe"]="contrastcolor",
+ ["ro"]="culoarecontrast",
+ },
+ ["controls"]={
+ ["cs"]="controls",
+ ["de"]="controls",
+ ["en"]="controls",
+ ["fr"]="controles",
+ ["it"]="controlli",
+ ["nl"]="sturing",
+ ["pe"]="کنترلها",
+ ["ro"]="controale",
+ },
+ ["conversion"]={
+ ["cs"]="konverze",
+ ["de"]="konversion",
+ ["en"]="conversion",
+ ["fr"]="conversion",
+ ["it"]="conversione",
+ ["nl"]="conversie",
+ ["pe"]="تبدیل",
+ ["ro"]="conversie",
+ },
+ ["convertfile"]={
+ ["cs"]="konverzesouboru",
+ ["de"]="konvertieredatei",
+ ["en"]="convertfile",
+ ["fr"]="conversionfichier",
+ ["it"]="convertifile",
+ ["nl"]="converteerfile",
+ ["pe"]="پروندهتبدیل",
+ ["ro"]="convertestefisier",
+ },
+ ["corner"]={
+ ["cs"]="roh",
+ ["de"]="winkel",
+ ["en"]="corner",
+ ["fr"]="coin",
+ ["it"]="angolo",
+ ["nl"]="hoek",
+ ["pe"]="گوشه",
+ ["ro"]="colt",
+ },
+ ["coupling"]={
+ ["cs"]="propojeni",
+ ["de"]="verknuepfung",
+ ["en"]="coupling",
+ ["fr"]="couplage",
+ ["it"]="accoppiamento",
+ ["nl"]="koppeling",
+ ["pe"]="تزویج",
+ ["ro"]="cuplare",
+ },
+ ["couplingway"]={
+ ["cs"]="zpusobpropojeni",
+ ["de"]="verkopplungsart",
+ ["en"]="couplingway",
+ ["fr"]="modecouplage",
+ ["it"]="modoaccoppiamento",
+ ["nl"]="koppelwijze",
+ ["pe"]="روشتزویج",
+ ["ro"]="modcuplare",
+ },
+ ["criterium"]={
+ ["cs"]="kriterium",
+ ["de"]="kriterium",
+ ["en"]="criterium",
+ ["fr"]="critere",
+ ["it"]="criterio",
+ ["nl"]="criterium",
+ ["pe"]="criterium",
+ ["ro"]="criteriu",
+ },
+ ["current"]={
+ ["cs"]="aktualni",
+ ["de"]="aktuell",
+ ["en"]="current",
+ ["fr"]="courant",
+ ["it"]="corrente",
+ ["nl"]="huidige",
+ ["pe"]="جاری",
+ ["ro"]="curent",
+ },
+ ["cutspace"]={
+ ["cs"]="cutspace",
+ ["de"]="cutspace",
+ ["en"]="cutspace",
+ ["fr"]="cutspace",
+ ["it"]="cutspace",
+ ["nl"]="snijwit",
+ ["pe"]="فضایبرش",
+ ["ro"]="cutspace",
+ },
+ ["dash"]={
+ ["cs"]="pomlcka",
+ ["de"]="strich",
+ ["en"]="dash",
+ ["fr"]="pointille",
+ ["it"]="dash",
+ ["nl"]="streep",
+ ["pe"]="دش",
+ ["ro"]="dash",
+ },
+ ["dat"]={
+ ["cs"]="dat",
+ ["de"]="dat",
+ ["en"]="dat",
+ ["fr"]="dat",
+ ["it"]="dat",
+ ["nl"]="dat",
+ ["pe"]="dat",
+ ["ro"]="dat",
+ },
+ ["date"]={
+ ["cs"]="datum",
+ ["de"]="datum",
+ ["en"]="date",
+ ["fr"]="date",
+ ["it"]="data",
+ ["nl"]="datum",
+ ["pe"]="تاریخ",
+ ["ro"]="data",
+ },
+ ["deepnumbercommand"]={
+ ["cs"]="deepnumbercommand",
+ ["de"]="deepnumbercommand",
+ ["en"]="deepnumbercommand",
+ ["fr"]="deepnumbercommand",
+ ["it"]="deepnumbercommand",
+ ["nl"]="diepnummercommando",
+ ["pe"]="فرمانشمارهعمیق",
+ ["ro"]="deepnumbercommand",
+ },
+ ["deeptextcommand"]={
+ ["cs"]="deeptextcommand",
+ ["de"]="deeptextcommand",
+ ["en"]="deeptextcommand",
+ ["fr"]="deeptextcommand",
+ ["it"]="deeptextcommand",
+ ["nl"]="dieptekstcommando",
+ ["pe"]="فرمانمتنعمیق",
+ ["ro"]="deeptextcommand",
+ },
+ ["default"]={
+ ["cs"]="implicitni",
+ ["de"]="default",
+ ["en"]="default",
+ ["fr"]="defaut",
+ ["it"]="implicito",
+ ["nl"]="default",
+ ["pe"]="پیشفرض",
+ ["ro"]="implicit",
+ },
+ ["delay"]={
+ ["cs"]="prodleva",
+ ["de"]="wartezeit",
+ ["en"]="delay",
+ ["fr"]="delai",
+ ["it"]="attesa",
+ ["nl"]="wachttijd",
+ ["pe"]="تاخیر",
+ ["ro"]="intarziere",
+ },
+ ["depth"]={
+ ["cs"]="hloubka",
+ ["de"]="tiefe",
+ ["en"]="depth",
+ ["fr"]="profondeur",
+ ["it"]="profondita",
+ ["nl"]="diepte",
+ ["pe"]="عمق",
+ ["ro"]="inaltime",
+ },
+ ["depthcorrection"]={
+ ["cs"]="korekcehloubky",
+ ["de"]="tiefekorrektur",
+ ["en"]="depthcorrection",
+ ["fr"]="correctionprofondeur",
+ ["it"]="correzioneprofondita",
+ ["nl"]="dieptecorrectie",
+ ["pe"]="تصحیحعمق",
+ ["ro"]="corectieadancime",
+ },
+ ["direction"]={
+ ["cs"]="smer",
+ ["de"]="richtung",
+ ["en"]="direction",
+ ["fr"]="direction",
+ ["it"]="direzione",
+ ["nl"]="richting",
+ ["pe"]="جهت",
+ ["ro"]="directie",
+ },
+ ["directory"]={
+ ["cs"]="adresar",
+ ["de"]="verzeichnis",
+ ["en"]="directory",
+ ["fr"]="repertoire",
+ ["it"]="directory",
+ ["nl"]="gebied",
+ ["pe"]="پوشه",
+ ["ro"]="director",
+ },
+ ["display"]={
+ ["cs"]="obrazovka",
+ ["de"]="bildschirm",
+ ["en"]="display",
+ ["fr"]="affichage",
+ ["it"]="display",
+ ["nl"]="scherm",
+ ["pe"]="نمایش",
+ ["ro"]="display",
+ },
+ ["distance"]={
+ ["cs"]="vzdalenost",
+ ["de"]="abstand",
+ ["en"]="distance",
+ ["fr"]="distance",
+ ["it"]="distanza",
+ ["nl"]="afstand",
+ ["pe"]="فاصله",
+ ["ro"]="distanta",
+ },
+ ["dot"]={
+ ["cs"]="tecka",
+ ["de"]="punkt",
+ ["en"]="dot",
+ ["fr"]="point",
+ ["it"]="punto",
+ ["nl"]="punt",
+ ["pe"]="نقطه",
+ ["ro"]="punct",
+ },
+ ["doublesided"]={
+ ["cs"]="oboustranne",
+ ["de"]="doppelseitig",
+ ["en"]="doublesided",
+ ["fr"]="rectoverso",
+ ["it"]="doppiafaccia",
+ ["nl"]="dubbelzijdig",
+ ["pe"]="دورو",
+ ["ro"]="douafete",
+ },
+ ["dummy"]={
+ ["cs"]="dummy",
+ ["de"]="dummy",
+ ["en"]="dummy",
+ ["fr"]="dummy",
+ ["it"]="dummy",
+ ["nl"]="dummy",
+ ["pe"]="مصنوعی",
+ ["ro"]="dummy",
+ },
+ ["dx"]={
+ ["cs"]="dx",
+ ["de"]="dx",
+ ["en"]="dx",
+ ["fr"]="dx",
+ ["it"]="dx",
+ ["nl"]="dx",
+ ["pe"]="dx",
+ ["ro"]="dx",
+ },
+ ["dy"]={
+ ["cs"]="dy",
+ ["de"]="dy",
+ ["en"]="dy",
+ ["fr"]="dy",
+ ["it"]="dy",
+ ["nl"]="dy",
+ ["pe"]="dy",
+ ["ro"]="dy",
+ },
+ ["edge"]={
+ ["cs"]="hrana",
+ ["de"]="kante",
+ ["en"]="edge",
+ ["fr"]="bord",
+ ["it"]="bordo",
+ ["nl"]="rand",
+ ["pe"]="لبه",
+ ["ro"]="bordura",
+ },
+ ["edgedistance"]={
+ ["cs"]="vzdalenosthrany",
+ ["de"]="kantenabstand",
+ ["en"]="edgedistance",
+ ["fr"]="distancebord",
+ ["it"]="distanzabordo",
+ ["nl"]="randafstand",
+ ["pe"]="فاصلهلبه",
+ ["ro"]="distantabordura",
+ },
+ ["empty"]={
+ ["cs"]="prazdne",
+ ["de"]="leer",
+ ["en"]="empty",
+ ["fr"]="vide",
+ ["it"]="vuoto",
+ ["nl"]="leeg",
+ ["pe"]="تهی",
+ ["ro"]="gol",
+ },
+ ["equalheight"]={
+ ["cs"]="equalheight",
+ ["de"]="equalheight",
+ ["en"]="equalheight",
+ ["fr"]="equalheight",
+ ["it"]="equalheight",
+ ["nl"]="equalheight",
+ ["pe"]="ارتفاعیکسان",
+ ["ro"]="equalheight",
+ },
+ ["equalwidth"]={
+ ["cs"]="equalwidth",
+ ["de"]="equalwidth",
+ ["en"]="equalwidth",
+ ["fr"]="equalwidth",
+ ["it"]="equalwidth",
+ ["nl"]="equalwidth",
+ ["pe"]="عرضیکسان",
+ ["ro"]="equalwidth",
+ },
+ ["escape"]={
+ ["cs"]="escape",
+ ["de"]="escape",
+ ["en"]="escape",
+ ["fr"]="escape",
+ ["it"]="escape",
+ ["nl"]="escape",
+ ["pe"]="فرار",
+ ["ro"]="escape",
+ },
+ ["evenmargin"]={
+ ["cs"]="sudamarginalie",
+ ["de"]="geraderand",
+ ["en"]="evenmargin",
+ ["fr"]="margepaire",
+ ["it"]="marginepari",
+ ["nl"]="evenmarge",
+ ["pe"]="حاشیهزوج",
+ ["ro"]="marginepara",
+ },
+ ["expansion"]={
+ ["cs"]="expanzen",
+ ["de"]="expansion",
+ ["en"]="expansion",
+ ["fr"]="expansion",
+ ["it"]="espansione",
+ ["nl"]="expansie",
+ ["pe"]="گسترش",
+ ["ro"]="expansiune",
+ },
+ ["extras"]={
+ ["cs"]="extras",
+ ["de"]="extras",
+ ["en"]="extras",
+ ["fr"]="extras",
+ ["it"]="extras",
+ ["nl"]="extras",
+ ["pe"]="extras",
+ ["ro"]="extras",
+ },
+ ["factor"]={
+ ["cs"]="faktor",
+ ["de"]="faktor",
+ ["en"]="factor",
+ ["fr"]="facteur",
+ ["it"]="fattore",
+ ["nl"]="factor",
+ ["pe"]="عامل",
+ ["ro"]="factor",
+ },
+ ["fallback"]={
+ ["cs"]="fallback",
+ ["de"]="fallback",
+ ["en"]="fallback",
+ ["fr"]="fallback",
+ ["it"]="fallback",
+ ["nl"]="terugval",
+ ["pe"]="عقبریختن",
+ ["ro"]="fallback",
+ },
+ ["family"]={
+ ["cs"]="rodina",
+ ["de"]="familie",
+ ["en"]="family",
+ ["fr"]="famille",
+ ["it"]="famiglia",
+ ["nl"]="soort",
+ ["pe"]="خانواده",
+ ["ro"]="familie",
+ },
+ ["fieldbackgroundcolor"]={
+ ["cs"]="barvapozadipole",
+ ["de"]="feldhintergrundfarbe",
+ ["en"]="fieldbackgroundcolor",
+ ["fr"]="couleurarrierreplanchamp",
+ ["it"]="coloresfondocampo",
+ ["nl"]="veldachtergrondkleur",
+ ["pe"]="رنگپسزمینهمیدان",
+ ["ro"]="culoarefundalcamp",
+ },
+ ["fieldframecolor"]={
+ ["cs"]="barvarameckupole",
+ ["de"]="feldrahmenfarbe",
+ ["en"]="fieldframecolor",
+ ["fr"]="couleurcadrechamp",
+ ["it"]="colorecornicecampo",
+ ["nl"]="veldkaderkleur",
+ ["pe"]="رنگقالبمیدان",
+ ["ro"]="culoareframecamp",
+ },
+ ["fieldlayer"]={
+ ["cs"]="fieldlayer",
+ ["de"]="fieldlayer",
+ ["en"]="fieldlayer",
+ ["fr"]="calquechamp",
+ ["it"]="fieldlayer",
+ ["nl"]="veldlaag",
+ ["pe"]="لایهمیدان",
+ ["ro"]="fieldlayer",
+ },
+ ["fieldoffset"]={
+ ["cs"]="offsetpole",
+ ["de"]="feldoffset",
+ ["en"]="fieldoffset",
+ ["fr"]="offsetchamp",
+ ["it"]="offsetcampo",
+ ["nl"]="veldoffset",
+ ["pe"]="آفستمیدان",
+ ["ro"]="offsetcamp",
+ },
+ ["file"]={
+ ["cs"]="soubor",
+ ["de"]="datei",
+ ["en"]="file",
+ ["fr"]="fichier",
+ ["it"]="file",
+ ["nl"]="file",
+ ["pe"]="پرونده",
+ ["ro"]="fisier",
+ },
+ ["filtercommand"]={
+ ["en"]="filtercommand",
+ },
+ ["focus"]={
+ ["cs"]="zaostreni",
+ ["de"]="focus",
+ ["en"]="focus",
+ ["fr"]="focus",
+ ["it"]="focus",
+ ["nl"]="focus",
+ ["pe"]="تمرکز",
+ ["ro"]="focus",
+ },
+ ["focusin"]={
+ ["cs"]="focusin",
+ ["de"]="focusin",
+ ["en"]="focusin",
+ ["fr"]="focusin",
+ ["it"]="focusin",
+ ["nl"]="focusin",
+ ["pe"]="تمرکزدرون",
+ ["ro"]="focusin",
+ },
+ ["focusout"]={
+ ["cs"]="focusout",
+ ["de"]="focusout",
+ ["en"]="focusout",
+ ["fr"]="focusout",
+ ["it"]="focusout",
+ ["nl"]="focusuit",
+ ["pe"]="تمرکزبیرون",
+ ["ro"]="focusout",
+ },
+ ["footer"]={
+ ["cs"]="upati",
+ ["de"]="fusszeile",
+ ["en"]="footer",
+ ["fr"]="pdp",
+ ["it"]="piedipagina",
+ ["nl"]="voet",
+ ["pe"]="تهبرگ",
+ ["ro"]="subsol",
+ },
+ ["footerdistance"]={
+ ["cs"]="vzdalenostupati",
+ ["de"]="fusszeilenabstand",
+ ["en"]="footerdistance",
+ ["fr"]="dsitancepdp",
+ ["it"]="distanzapdp",
+ ["nl"]="voetafstand",
+ ["pe"]="فاصلهتهبرگ",
+ ["ro"]="distantasubsol",
+ },
+ ["footerstate"]={
+ ["cs"]="statusupati",
+ ["de"]="fusszeilenstatus",
+ ["en"]="footerstate",
+ ["fr"]="etatpdp",
+ ["it"]="statopdp",
+ ["nl"]="voetstatus",
+ ["pe"]="وضعیتتهبرگ",
+ ["ro"]="staresubsol",
+ },
+ ["foregroundcolor"]={
+ ["cs"]="foregroundcolor",
+ ["de"]="foregroundcolor",
+ ["en"]="foregroundcolor",
+ ["fr"]="couleurpremierplan",
+ ["it"]="coloreprimopiano",
+ ["nl"]="voorgrondkleur",
+ ["pe"]="رنگپیشزمینه",
+ ["ro"]="foregroundcolor",
+ },
+ ["foregroundstyle"]={
+ ["cs"]="foregroundstyle",
+ ["de"]="foregroundstyle",
+ ["en"]="foregroundstyle",
+ ["fr"]="stylepremierplan",
+ ["it"]="foregroundstyle",
+ ["nl"]="voorgrondletter",
+ ["pe"]="سبکپیشزمینه",
+ ["ro"]="foregroundstyle",
+ },
+ ["format"]={
+ ["cs"]="formatovat",
+ ["de"]="formatieren",
+ ["en"]="format",
+ ["fr"]="formatter",
+ ["it"]="format",
+ ["nl"]="formatteer",
+ ["pe"]="شمایل",
+ ["ro"]="format",
+ },
+ ["frame"]={
+ ["cs"]="ramecek",
+ ["de"]="rahmen",
+ ["en"]="frame",
+ ["fr"]="cadre",
+ ["it"]="cornice",
+ ["nl"]="kader",
+ ["pe"]="قالب",
+ ["ro"]="frame",
+ },
+ ["framecolor"]={
+ ["cs"]="barvaramecku",
+ ["de"]="rahmenfarbe",
+ ["en"]="framecolor",
+ ["fr"]="couleurcadre",
+ ["it"]="colorecornice",
+ ["nl"]="kaderkleur",
+ ["pe"]="رنگقالب",
+ ["ro"]="culoareframe",
+ },
+ ["framecorner"]={
+ ["cs"]="rohramecku",
+ ["de"]="rahmenwinkel",
+ ["en"]="framecorner",
+ ["fr"]="coincadre",
+ ["it"]="angolocornice",
+ ["nl"]="kaderhoek",
+ ["pe"]="گوشهقالب",
+ ["ro"]="coltframe",
+ },
+ ["framedepth"]={
+ ["cs"]="hloubkaramecku",
+ ["de"]="rahmentiefe",
+ ["en"]="framedepth",
+ ["fr"]="profondeurcadre",
+ ["it"]="profonditacornice",
+ ["nl"]="kaderdiepte",
+ ["pe"]="عمققالب",
+ ["ro"]="adancimeframe",
+ },
+ ["frameoffset"]={
+ ["cs"]="offsetramecku",
+ ["de"]="rahmenoffset",
+ ["en"]="frameoffset",
+ ["fr"]="decalagecadre",
+ ["it"]="offsetcornice",
+ ["nl"]="kaderoffset",
+ ["pe"]="آفستقالب",
+ ["ro"]="offsetframe",
+ },
+ ["frameradius"]={
+ ["cs"]="polomerramecku",
+ ["de"]="rahmenradius",
+ ["en"]="frameradius",
+ ["fr"]="rayoncadre",
+ ["it"]="raggiocornice",
+ ["nl"]="kaderstraal",
+ ["pe"]="شعاعقالب",
+ ["ro"]="razaframe",
+ },
+ ["frames"]={
+ ["cs"]="ramecky",
+ ["de"]="umrahmen",
+ ["en"]="frames",
+ ["fr"]="cadres",
+ ["it"]="cornici",
+ ["nl"]="hokjes",
+ ["pe"]="قالبها",
+ ["ro"]="frames",
+ },
+ ["from"]={
+ ["cs"]="z",
+ ["de"]="von",
+ ["en"]="from",
+ ["fr"]="de",
+ ["it"]="da",
+ ["nl"]="van",
+ ["pe"]="از",
+ ["ro"]="dela",
+ },
+ ["get"]={
+ ["cs"]="ziskat",
+ ["de"]="hole",
+ ["en"]="get",
+ ["fr"]="obtient",
+ ["it"]="prendi",
+ ["nl"]="haal",
+ ["pe"]="بگیر",
+ ["ro"]="adu",
+ },
+ ["global"]={
+ ["cs"]="globalne",
+ ["de"]="global",
+ ["en"]="global",
+ ["fr"]="global",
+ ["it"]="globale",
+ ["nl"]="globaal",
+ ["pe"]="سراسری",
+ ["ro"]="global",
+ },
+ ["grid"]={
+ ["cs"]="mrizka",
+ ["de"]="gritter",
+ ["en"]="grid",
+ ["fr"]="grille",
+ ["it"]="griglia",
+ ["nl"]="grid",
+ ["pe"]="توری",
+ ["ro"]="grid",
+ },
+ ["hang"]={
+ ["cs"]="zaveseni",
+ ["de"]="haengend",
+ ["en"]="hang",
+ ["fr"]="suspend",
+ ["it"]="sospendi",
+ ["nl"]="hang",
+ ["pe"]="بیاویز",
+ ["ro"]="suspenda",
+ },
+ ["headcolor"]={
+ ["cs"]="barvahlavicky",
+ ["de"]="kopffarbe",
+ ["en"]="headcolor",
+ ["fr"]="couleurtete",
+ ["it"]="coloretesta",
+ ["nl"]="kopkleur",
+ ["pe"]="رنگسر",
+ ["ro"]="culoaretitlu",
+ },
+ ["headcommand"]={
+ ["cs"]="headcommand",
+ ["de"]="headcommand",
+ ["en"]="headcommand",
+ ["fr"]="commandetete",
+ ["it"]="headcommand",
+ ["nl"]="kopcommando",
+ ["pe"]="فرمانسر",
+ ["ro"]="headcommand",
+ },
+ ["headconversion"]={
+ ["cs"]="konverzehlavicky",
+ ["de"]="headconversion",
+ ["en"]="headconversion",
+ ["fr"]="conversiontete",
+ ["it"]="conversionetesta",
+ ["nl"]="kopconversie",
+ ["pe"]="تبدیلسر",
+ ["ro"]="conversietitlu",
+ },
+ ["header"]={
+ ["cs"]="zahlavi",
+ ["de"]="kopfzeile",
+ ["en"]="header",
+ ["fr"]="entete",
+ ["it"]="intestazione",
+ ["nl"]="hoofd",
+ ["pe"]="سربرگ",
+ ["ro"]="antet",
+ },
+ ["headerdistance"]={
+ ["cs"]="vzdalenostzahlavi",
+ ["de"]="kopfzeilenabstand",
+ ["en"]="headerdistance",
+ ["fr"]="distanceentete",
+ ["it"]="distanzaintestazione",
+ ["nl"]="hoofdafstand",
+ ["pe"]="فاصلهسربرگ",
+ ["ro"]="distantaantet",
+ },
+ ["headerstate"]={
+ ["cs"]="statuszahlavi",
+ ["de"]="kopfzeilenstatus",
+ ["en"]="headerstate",
+ ["fr"]="etatentete",
+ ["it"]="statointestazione",
+ ["nl"]="hoofdstatus",
+ ["pe"]="وضعیتسربرگ",
+ ["ro"]="stareantet",
+ },
+ ["headlabel"]={
+ ["cs"]="popisekhlavicky",
+ ["de"]="headlabel",
+ ["en"]="headlabel",
+ ["fr"]="etiquettetete",
+ ["it"]="etichettatesta",
+ ["nl"]="koplabel",
+ ["pe"]="برچسبسر",
+ ["ro"]="etichetatitlu",
+ },
+ ["headnumber"]={
+ ["cs"]="cislonadpisu",
+ ["de"]="kopfnummer",
+ ["en"]="headnumber",
+ ["fr"]="numerotete",
+ ["it"]="numerotesta",
+ ["nl"]="kopnummer",
+ ["pe"]="شمارهسر",
+ ["ro"]="numartitlu",
+ },
+ ["headstyle"]={
+ ["cs"]="stylhlavicky",
+ ["de"]="kopfstil",
+ ["en"]="headstyle",
+ ["fr"]="styletete",
+ ["it"]="stiletesta",
+ ["nl"]="kopletter",
+ ["pe"]="سبکسر",
+ ["ro"]="stiltitlu",
+ },
+ ["height"]={
+ ["cs"]="vyska",
+ ["de"]="hoehe",
+ ["en"]="height",
+ ["fr"]="hauteur",
+ ["it"]="altezza",
+ ["nl"]="hoogte",
+ ["pe"]="ارتفاع",
+ ["ro"]="inaltime",
+ },
+ ["hfactor"]={
+ ["cs"]="vfaktor",
+ ["de"]="hfaktor",
+ ["en"]="hfactor",
+ ["fr"]="facteurhauteur",
+ ["it"]="hfactor",
+ ["nl"]="hfactor",
+ ["pe"]="عاملارتفاع",
+ ["ro"]="hfactor",
+ },
+ ["hfil"]={
+ ["cs"]="hfil",
+ ["de"]="hfil",
+ ["en"]="hfil",
+ ["fr"]="hfil",
+ ["it"]="hfil",
+ ["nl"]="hfil",
+ ["pe"]="پرکردنارتفاع",
+ ["ro"]="hfil",
+ },
+ ["hidenumber"]={
+ ["en"]="hidenumber",
+ },
+ ["hoffset"]={
+ ["cs"]="hoffset",
+ ["de"]="hoffset",
+ ["en"]="hoffset",
+ ["fr"]="decalagehauteur",
+ ["it"]="hoffset",
+ ["nl"]="hoffset",
+ ["pe"]="آفستا",
+ ["ro"]="hoffset",
+ },
+ ["horoffset"]={
+ ["cs"]="horoffset",
+ ["de"]="rumpfabstand",
+ ["en"]="horoffset",
+ ["fr"]="horoffset",
+ ["it"]="horoffset",
+ ["nl"]="rugoffset",
+ ["pe"]="آفستافق",
+ ["ro"]="offsetoriz",
+ },
+ ["hyphen"]={
+ ["cs"]="hyphen",
+ ["de"]="hyphen",
+ ["en"]="hyphen",
+ ["fr"]="hyphen",
+ ["it"]="hyphen",
+ ["nl"]="hyphen",
+ ["pe"]="شکستن",
+ ["ro"]="hyphen",
+ },
+ ["icommand"]={
+ ["cs"]="iprikaz",
+ ["de"]="ibefehl",
+ ["en"]="icommand",
+ ["fr"]="icommande",
+ ["it"]="icomando",
+ ["nl"]="icommando",
+ ["pe"]="icommand",
+ ["ro"]="comandai",
+ },
+ ["in"]={
+ ["cs"]="v",
+ ["de"]="in",
+ ["en"]="in",
+ ["fr"]="in",
+ ["it"]="in",
+ ["nl"]="in",
+ ["pe"]="درون",
+ ["ro"]="in",
+ },
+ ["inbetween"]={
+ ["cs"]="mezi",
+ ["de"]="zwischen",
+ ["en"]="inbetween",
+ ["fr"]="entre",
+ ["it"]="tra",
+ ["nl"]="tussen",
+ ["pe"]="دربین",
+ ["ro"]="intre",
+ },
+ ["increment"]={
+ ["cs"]="zvysit",
+ ["de"]="erhoehen",
+ ["en"]="increment",
+ ["fr"]="incremente",
+ ["it"]="incremento",
+ ["nl"]="verhoog",
+ ["pe"]="افزایش",
+ ["ro"]="increment",
+ },
+ ["incrementnumber"]={
+ ["cs"]="zvysujicicislo",
+ ["de"]="nummererhoehen",
+ ["en"]="incrementnumber",
+ ["fr"]="incrementenumero",
+ ["it"]="incrementanumero",
+ ["nl"]="verhoognummer",
+ ["pe"]="شمارهافزایش",
+ ["ro"]="numarincrement",
+ },
+ ["indenting"]={
+ ["cs"]="odsazovani",
+ ["de"]="einziehen",
+ ["en"]="indenting",
+ ["fr"]="composeenalinea",
+ ["it"]="rientro",
+ ["nl"]="inspringen",
+ ["pe"]="تورفتگی",
+ ["ro"]="aliniat",
+ },
+ ["indentnext"]={
+ ["cs"]="odsadpristi",
+ ["de"]="ziehefolgendeein",
+ ["en"]="indentnext",
+ ["fr"]="indentesuivant",
+ ["it"]="rientrasuccessivo",
+ ["nl"]="springvolgendein",
+ ["pe"]="متنتورفته",
+ ["ro"]="aliniaturmator",
+ },
+ ["indicator"]={
+ ["cs"]="indikator",
+ ["de"]="indikator",
+ ["en"]="indicator",
+ ["fr"]="indicateur",
+ ["it"]="indicatore",
+ ["nl"]="aanduiding",
+ ["pe"]="اندیکاتور",
+ ["ro"]="indicator",
+ },
+ ["inner"]={
+ ["cs"]="vnitrni",
+ ["de"]="innen",
+ ["en"]="inner",
+ ["fr"]="interieur",
+ ["it"]="interno",
+ ["nl"]="binnen",
+ ["pe"]="داخلی",
+ ["ro"]="intern",
+ },
+ ["innermargin"]={
+ ["cs"]="innermargin",
+ ["de"]="innermargin",
+ ["en"]="innermargin",
+ ["fr"]="margeinterieure",
+ ["it"]="margineinterno",
+ ["nl"]="binnenmarge",
+ ["pe"]="حاشیهداخلی",
+ ["ro"]="innermargin",
+ },
+ ["inputfile"]={
+ ["cs"]="inputfile",
+ ["de"]="inputfile",
+ ["en"]="inputfile",
+ ["fr"]="fichierentree",
+ ["it"]="inputfile",
+ ["nl"]="inputfile",
+ ["pe"]="پروندهورودی",
+ ["ro"]="inputfile",
+ },
+ ["interaction"]={
+ ["cs"]="interakce",
+ ["de"]="interaktion",
+ ["en"]="interaction",
+ ["fr"]="interaction",
+ ["it"]="interazione",
+ ["nl"]="interactie",
+ ["pe"]="پانل",
+ ["ro"]="interactiune",
+ },
+ ["interlinespace"]={
+ ["cs"]="meziradkovamezera",
+ ["de"]="zeilenabstande",
+ ["en"]="interlinespace",
+ ["fr"]="espaceinterligne",
+ ["it"]="interlinea",
+ ["nl"]="interlinie",
+ ["pe"]="فضایبینخط",
+ ["ro"]="spatiereinterliniara",
+ },
+ ["itemalign"]={
+ ["cs"]="itemalign",
+ ["de"]="itemalign",
+ ["en"]="itemalign",
+ ["fr"]="itemalign",
+ ["it"]="itemalign",
+ ["nl"]="itemuitlijnen",
+ ["pe"]="تنظیمآیتم",
+ ["ro"]="itemalign",
+ },
+ ["items"]={
+ ["cs"]="polozky",
+ ["de"]="posten",
+ ["en"]="items",
+ ["fr"]="elements",
+ ["it"]="elementi",
+ ["nl"]="items",
+ ["pe"]="آیتمها",
+ ["ro"]="elemente",
+ },
+ ["ken"]={
+ ["cs"]="ken",
+ ["de"]="ken",
+ ["en"]="ken",
+ ["fr"]="ken",
+ ["it"]="ken",
+ ["nl"]="ken",
+ ["pe"]="ken",
+ ["ro"]="ken",
+ },
+ ["keyexpansion"]={
+ ["cs"]="keyexpansion",
+ ["de"]="keyexpansion",
+ ["en"]="keyexpansion",
+ ["fr"]="keyexpansion",
+ ["it"]="keyexpansion",
+ ["nl"]="sleutelexpansie",
+ ["pe"]="گسترشکلید",
+ ["ro"]="keyexpansion",
+ },
+ ["keyword"]={
+ ["cs"]="keyword",
+ ["de"]="keyword",
+ ["en"]="keyword",
+ ["fr"]="motcle",
+ ["it"]="parolachiave",
+ ["nl"]="trefwoord",
+ ["pe"]="کلیدواژه",
+ ["ro"]="keyword",
+ },
+ ["label"]={
+ ["cs"]="popisek",
+ ["de"]="label",
+ ["en"]="label",
+ ["fr"]="etiquette",
+ ["it"]="etichetta",
+ ["nl"]="label",
+ ["pe"]="برچسب",
+ ["ro"]="eticheta",
+ },
+ ["left"]={
+ ["cs"]="vlevo",
+ ["de"]="links",
+ ["en"]="left",
+ ["fr"]="gauche",
+ ["it"]="sinistra",
+ ["nl"]="links",
+ ["pe"]="چپ",
+ ["ro"]="stanga",
+ },
+ ["leftcolor"]={
+ ["cs"]="barvavlevo",
+ ["de"]="linkerfarbe",
+ ["en"]="leftcolor",
+ ["fr"]="couleurgauche",
+ ["it"]="coloresinistra",
+ ["nl"]="linkerkleur",
+ ["pe"]="رنگچپ",
+ ["ro"]="culoarestanga",
+ },
+ ["leftcompoundhyphen"]={
+ ["cs"]="leftcompoundhyphen",
+ ["de"]="leftcompoundhyphen",
+ ["en"]="leftcompoundhyphen",
+ ["fr"]="leftcompoundhyphen",
+ ["it"]="leftcompoundhyphen",
+ ["nl"]="linkerkoppelteken",
+ ["pe"]="leftcompoundhyphen",
+ ["ro"]="leftcompoundhyphen",
+ },
+ ["leftedge"]={
+ ["cs"]="levahrana",
+ ["de"]="linkekante",
+ ["en"]="leftedge",
+ ["fr"]="bordgauche",
+ ["it"]="bordosinistro",
+ ["nl"]="linkerrand",
+ ["pe"]="لبهچپ",
+ ["ro"]="bordurastanga",
+ },
+ ["leftedgedistance"]={
+ ["cs"]="vzdalenostlevehrany",
+ ["de"]="linkerkantenabstand",
+ ["en"]="leftedgedistance",
+ ["fr"]="distancebordgauche",
+ ["it"]="distanzabordosinistro",
+ ["nl"]="linkerrandafstand",
+ ["pe"]="فاصلهلبهچپ",
+ ["ro"]="distantabordurastanga",
+ },
+ ["leftframe"]={
+ ["cs"]="ramecekvlevo",
+ ["de"]="linkerrahmen",
+ ["en"]="leftframe",
+ ["fr"]="cadregauche",
+ ["it"]="cornicesinistra",
+ ["nl"]="linkerkader",
+ ["pe"]="قالبچپ",
+ ["ro"]="framestanga",
+ },
+ ["lefthyphen"]={
+ ["cs"]="lefthyphen",
+ ["de"]="lefthyphen",
+ ["en"]="lefthyphen",
+ ["fr"]="lefthyphen",
+ ["it"]="lefthyphen",
+ ["nl"]="lefthyphen",
+ ["pe"]="شکستچپ",
+ ["ro"]="lefthyphen",
+ },
+ ["leftmargin"]={
+ ["cs"]="levyokraj",
+ ["de"]="linkerrand",
+ ["en"]="leftmargin",
+ ["fr"]="margegauche",
+ ["it"]="marginesinistro",
+ ["nl"]="linkermarge",
+ ["pe"]="حاشیهچپ",
+ ["ro"]="marginestanga",
+ },
+ ["leftmargindistance"]={
+ ["cs"]="vzdalenostlevehookraje",
+ ["de"]="linkerrandabstand",
+ ["en"]="leftmargindistance",
+ ["fr"]="distancemargegauche",
+ ["it"]="distanzamarginesinistro",
+ ["nl"]="linkermargeafstand",
+ ["pe"]="فاصلهحاشیهچپ",
+ ["ro"]="distantamarginestanga",
+ },
+ ["leftoffset"]={
+ ["cs"]="levyoffset",
+ ["de"]="linkeroffset",
+ ["en"]="leftoffset",
+ ["fr"]="decalagegauche",
+ ["it"]="offsetsinistro",
+ ["nl"]="linkeroffset",
+ ["pe"]="آفستچپ",
+ ["ro"]="offsetstanga",
+ },
+ ["leftquotation"]={
+ ["cs"]="citacevlevo",
+ ["de"]="linkerzitat",
+ ["en"]="leftquotation",
+ ["fr"]="citationgauche",
+ ["it"]="citazionesinistra",
+ ["nl"]="linkercitaat",
+ ["pe"]="نقلقولچپ",
+ ["ro"]="citatstanga",
+ },
+ ["leftquote"]={
+ ["cs"]="citovatvlevo",
+ ["de"]="linkerzitieren",
+ ["en"]="leftquote",
+ ["fr"]="citergauche",
+ ["it"]="menzionesinistra",
+ ["nl"]="linkerciteer",
+ ["pe"]="نقلچپ",
+ ["ro"]="minicitatstanga",
+ },
+ ["leftsentence"]={
+ ["cs"]="vetavlevo",
+ ["de"]="linkersatz",
+ ["en"]="leftsentence",
+ ["fr"]="phrasegauche",
+ ["it"]="frasesinistra",
+ ["nl"]="linkerzin",
+ ["pe"]="جملهچپ",
+ ["ro"]="propozitiestanga",
+ },
+ ["leftspeech"]={
+ ["cs"]="leftspeech",
+ ["de"]="leftspeech",
+ ["en"]="leftspeech",
+ ["fr"]="leftspeech",
+ ["it"]="leftspeech",
+ ["nl"]="linkeruitspraak",
+ ["pe"]="سخنرانیچپ",
+ ["ro"]="leftspeech",
+ },
+ ["leftstyle"]={
+ ["cs"]="stylvlevo",
+ ["de"]="linkerstil",
+ ["en"]="leftstyle",
+ ["fr"]="leftstyle",
+ ["it"]="stilesinistra",
+ ["nl"]="linkerletter",
+ ["pe"]="سبکچپ",
+ ["ro"]="stilstanga",
+ },
+ ["leftsubsentence"]={
+ ["cs"]="podvetavlevo",
+ ["de"]="linkersubsatz",
+ ["en"]="leftsubsentence",
+ ["fr"]="sousphrasegauche",
+ ["it"]="sottofrasesinistra",
+ ["nl"]="linkersubzin",
+ ["pe"]="زیرجملهچپ",
+ ["ro"]="subpropozitiestanga",
+ },
+ ["lefttext"]={
+ ["cs"]="textvlevo",
+ ["de"]="linkertext",
+ ["en"]="lefttext",
+ ["fr"]="textegauche",
+ ["it"]="testosinistro",
+ ["nl"]="linkertekst",
+ ["pe"]="متنچپ",
+ ["ro"]="textstanga",
+ },
+ ["leftwidth"]={
+ ["cs"]="sirkavlevo",
+ ["de"]="linkerbreite",
+ ["en"]="leftwidth",
+ ["fr"]="largeurgauche",
+ ["it"]="ampiezzasinistra",
+ ["nl"]="linkerbreedte",
+ ["pe"]="عرضخط",
+ ["ro"]="latimestanga",
+ },
+ ["level"]={
+ ["cs"]="uroven",
+ ["de"]="niveau",
+ ["en"]="level",
+ ["fr"]="niveau",
+ ["it"]="livello",
+ ["nl"]="niveau",
+ ["pe"]="مرحله",
+ ["ro"]="nivel",
+ },
+ ["levels"]={
+ ["cs"]="urovne",
+ ["de"]="niveaus",
+ ["en"]="levels",
+ ["fr"]="niveaux",
+ ["it"]="livelli",
+ ["nl"]="niveaus",
+ ["pe"]="مرحلهها",
+ ["ro"]="nivele",
+ },
+ ["limittext"]={
+ ["cs"]="limittext",
+ ["de"]="limittext",
+ ["en"]="limittext",
+ ["fr"]="limittext",
+ ["it"]="limittext",
+ ["nl"]="limiettekst",
+ ["pe"]="مرزمتن",
+ ["ro"]="limittext",
+ },
+ ["line"]={
+ ["cs"]="radek",
+ ["de"]="zeile",
+ ["en"]="line",
+ ["fr"]="ligne",
+ ["it"]="riga",
+ ["nl"]="regel",
+ ["pe"]="خط",
+ ["ro"]="linie",
+ },
+ ["linecorrection"]={
+ ["cs"]="korekceradku",
+ ["de"]="zeilekorrektur",
+ ["en"]="linecorrection",
+ ["fr"]="correctionligne",
+ ["it"]="correzioneriga",
+ ["nl"]="regelcorrectie",
+ ["pe"]="تصحیحخط",
+ ["ro"]="corectielinie",
+ },
+ ["lines"]={
+ ["cs"]="radky",
+ ["de"]="zeilen",
+ ["en"]="lines",
+ ["fr"]="lignes",
+ ["it"]="righe",
+ ["nl"]="regels",
+ ["pe"]="خطها",
+ ["ro"]="linii",
+ },
+ ["list"]={
+ ["cs"]="seznam",
+ ["de"]="liste",
+ ["en"]="list",
+ ["fr"]="liste",
+ ["it"]="elenco",
+ ["nl"]="lijst",
+ ["pe"]="لیست",
+ ["ro"]="lista",
+ },
+ ["listtext"]={
+ ["cs"]="listtext",
+ ["de"]="listtext",
+ ["en"]="listtext",
+ ["fr"]="texteliste",
+ ["it"]="listtext",
+ ["nl"]="lijsttekst",
+ ["pe"]="متنلیست",
+ ["ro"]="listtext",
+ },
+ ["local"]={
+ ["cs"]="lokalne",
+ ["de"]="lokal",
+ ["en"]="local",
+ ["fr"]="local",
+ ["it"]="locale",
+ ["nl"]="lokaal",
+ ["pe"]="موضعی",
+ ["ro"]="local",
+ },
+ ["location"]={
+ ["cs"]="misto",
+ ["de"]="platz",
+ ["en"]="location",
+ ["fr"]="emplacement",
+ ["it"]="luogo",
+ ["nl"]="plaats",
+ ["pe"]="مکان",
+ ["ro"]="locatie",
+ },
+ ["logo"]={
+ ["cs"]="logo",
+ ["de"]="logo",
+ ["en"]="logo",
+ ["fr"]="logo",
+ ["it"]="logo",
+ ["nl"]="logo",
+ ["pe"]="آرم",
+ ["ro"]="logo",
+ },
+ ["logos"]={
+ ["cs"]="loga",
+ ["de"]="logos",
+ ["en"]="logos",
+ ["fr"]="logos",
+ ["it"]="loghi",
+ ["nl"]="logos",
+ ["pe"]="آرمها",
+ ["ro"]="logos",
+ },
+ ["marcolor"]={
+ ["cs"]="barvaznacky",
+ ["de"]="beschrfarbe",
+ ["en"]="marcolor",
+ ["fr"]="couleurmarquage",
+ ["it"]="coloremarcatura",
+ ["nl"]="markleur",
+ ["pe"]="رنگحاش",
+ ["ro"]="culoaremarcaj",
+ },
+ ["margin"]={
+ ["cs"]="marginalie",
+ ["de"]="marginalie",
+ ["en"]="margin",
+ ["fr"]="marge",
+ ["it"]="margine",
+ ["nl"]="marge",
+ ["pe"]="حاشیه",
+ ["ro"]="margine",
+ },
+ ["margindistance"]={
+ ["cs"]="vzdalenostokraje",
+ ["de"]="marginalabstand",
+ ["en"]="margindistance",
+ ["fr"]="distancemarge",
+ ["it"]="distanzamargine",
+ ["nl"]="margeafstand",
+ ["pe"]="فاصلهحاشیه",
+ ["ro"]="distantamargine",
+ },
+ ["marginedge"]={
+ ["cs"]="textovahrana",
+ ["de"]="marginalkante",
+ ["en"]="marginedge",
+ ["fr"]="bordmarge",
+ ["it"]="bordomargine",
+ ["nl"]="kantlijn",
+ ["pe"]="لبهحاشیه",
+ ["ro"]="coltbordura",
+ },
+ ["marginedgetext"]={
+ ["cs"]="textmarginalnihookraje",
+ ["de"]="marginalkantetext",
+ ["en"]="marginedgetext",
+ ["fr"]="textebordmarge",
+ ["it"]="testobordomargine",
+ ["nl"]="kantlijntekst",
+ ["pe"]="متنلبهحاشیه",
+ ["ro"]="textcoltbordura",
+ },
+ ["margintext"]={
+ ["cs"]="textmarginalie",
+ ["de"]="marginaltext",
+ ["en"]="margintext",
+ ["fr"]="textemarge",
+ ["it"]="testomargine",
+ ["nl"]="margetekst",
+ ["pe"]="متنحاشیه",
+ ["ro"]="textmargine",
+ },
+ ["marking"]={
+ ["cs"]="znaceni",
+ ["de"]="beschriftung",
+ ["en"]="marking",
+ ["fr"]="marquage",
+ ["it"]="marcatura",
+ ["nl"]="markering",
+ ["pe"]="نشانهگذاری",
+ ["ro"]="marcaje",
+ },
+ ["marstyle"]={
+ ["cs"]="stylsnacky",
+ ["de"]="beschrstil",
+ ["en"]="marstyle",
+ ["fr"]="stylemarquage",
+ ["it"]="stilemarcatura",
+ ["nl"]="marletter",
+ ["pe"]="سبکحاش",
+ ["ro"]="stilmarcaj",
+ },
+ ["max"]={
+ ["cs"]="max",
+ ["de"]="max",
+ ["en"]="max",
+ ["fr"]="max",
+ ["it"]="max",
+ ["nl"]="max",
+ ["pe"]="بیشترین",
+ ["ro"]="max",
+ },
+ ["maxheight"]={
+ ["cs"]="maxvyska",
+ ["de"]="maxhoehe",
+ ["en"]="maxheight",
+ ["fr"]="hauteurmax",
+ ["it"]="altezzamax",
+ ["nl"]="maxhoogte",
+ ["pe"]="بیشترینارتفاع",
+ ["ro"]="inaltimemaxima",
+ },
+ ["maxdepth"]={
+ ["en"]="maxdepth",
+ },
+ ["maxwidth"]={
+ ["cs"]="maxsirka",
+ ["de"]="maxbreite",
+ ["en"]="maxwidth",
+ ["fr"]="largeurmax",
+ ["it"]="ampiezzamax",
+ ["nl"]="maxbreedte",
+ ["pe"]="بیشترینعرض",
+ ["ro"]="latimemaxima",
+ },
+ ["menu"]={
+ ["cs"]="menu",
+ ["de"]="menue",
+ ["en"]="menu",
+ ["fr"]="menu",
+ ["it"]="menu",
+ ["nl"]="menu",
+ ["pe"]="منو",
+ ["ro"]="meniu",
+ },
+ ["method"]={
+ ["cs"]="metoda",
+ ["de"]="methode",
+ ["en"]="method",
+ ["fr"]="methode",
+ ["it"]="metodo",
+ ["nl"]="methode",
+ ["pe"]="روش",
+ ["ro"]="metoda",
+ },
+ ["middle"]={
+ ["cs"]="stredni",
+ ["de"]="mittig",
+ ["en"]="middle",
+ ["fr"]="milieu",
+ ["it"]="centro",
+ ["nl"]="midden",
+ ["pe"]="میان",
+ ["ro"]="mijloc",
+ },
+ ["middlespeech"]={
+ ["cs"]="middlespeech",
+ ["de"]="middlespeech",
+ ["en"]="middlespeech",
+ ["fr"]="middlespeech",
+ ["it"]="middlespeech",
+ ["nl"]="middenuitspraak",
+ ["pe"]="سخنرانیمیانی",
+ ["ro"]="middlespeech",
+ },
+ ["middletext"]={
+ ["cs"]="strednitext",
+ ["de"]="mittigertext",
+ ["en"]="middletext",
+ ["fr"]="textecentre",
+ ["it"]="testocentro",
+ ["nl"]="middentekst",
+ ["pe"]="متنمیانی",
+ ["ro"]="textmijloc",
+ },
+ ["midsentence"]={
+ ["cs"]="midsentence",
+ ["de"]="midsentence",
+ ["en"]="midsentence",
+ ["fr"]="midsentence",
+ ["it"]="midsentence",
+ ["nl"]="middenzin",
+ ["pe"]="جملهمیانی",
+ ["ro"]="midsentence",
+ },
+ ["min"]={
+ ["cs"]="min",
+ ["de"]="min",
+ ["en"]="min",
+ ["fr"]="min",
+ ["it"]="min",
+ ["nl"]="min",
+ ["pe"]="کمترین",
+ ["ro"]="min",
+ },
+ ["mindepth"]={
+ ["cs"]="mindepth",
+ ["de"]="mindepth",
+ ["en"]="mindepth",
+ ["fr"]="profondeurmin",
+ ["it"]="mindeoth",
+ ["nl"]="mindiepte",
+ ["pe"]="کمترینعمق",
+ ["ro"]="mindepth",
+ },
+ ["minheight"]={
+ ["cs"]="minvyska",
+ ["de"]="minhoehe",
+ ["en"]="minheight",
+ ["fr"]="hauteurmin",
+ ["it"]="altezzamin",
+ ["nl"]="minhoogte",
+ ["pe"]="کمترینارتفاع",
+ ["ro"]="inaltimeminima",
+ },
+ ["minwidth"]={
+ ["cs"]="minsirka",
+ ["de"]="minbreite",
+ ["en"]="minwidth",
+ ["fr"]="largeurmin",
+ ["it"]="ampiezzamin",
+ ["nl"]="minbreedte",
+ ["pe"]="کمترینعرض",
+ ["ro"]="latimeminima",
+ },
+ ["monthconversion"]={
+ ["en"]="monthconversion",
+ ["nl"]="maandconversie",
+ },
+ ["n"]={
+ ["cs"]="n",
+ ["de"]="n",
+ ["en"]="n",
+ ["fr"]="n",
+ ["it"]="n",
+ ["nl"]="n",
+ ["pe"]="n",
+ ["ro"]="n",
+ },
+ ["name"]={
+ ["cs"]="jmeno",
+ ["de"]="name",
+ ["en"]="name",
+ ["fr"]="nom",
+ ["it"]="nome",
+ ["nl"]="naam",
+ ["pe"]="نام",
+ ["ro"]="nume",
+ },
+ ["nbottom"]={
+ ["cs"]="nspodek",
+ ["de"]="nunten",
+ ["en"]="nbottom",
+ ["fr"]="ninf",
+ ["it"]="nfondo",
+ ["nl"]="nonder",
+ ["pe"]="nbottom",
+ ["ro"]="njos",
+ },
+ ["nc"]={
+ ["cs"]="nc",
+ ["de"]="nc",
+ ["en"]="nc",
+ ["fr"]="nc",
+ ["it"]="nc",
+ ["nl"]="nc",
+ ["pe"]="nc",
+ ["ro"]="nc",
+ },
+ ["next"]={
+ ["cs"]="dalsi",
+ ["de"]="folgende",
+ ["en"]="next",
+ ["fr"]="suivant",
+ ["it"]="successivo",
+ ["nl"]="volgende",
+ ["pe"]="بعدی",
+ ["ro"]="urmatorul",
+ },
+ ["nl"]={
+ ["cs"]="nl",
+ ["de"]="nl",
+ ["en"]="nl",
+ ["fr"]="nl",
+ ["it"]="nl",
+ ["nl"]="nl",
+ ["pe"]="nl",
+ ["ro"]="nl",
+ },
+ ["nleft"]={
+ ["cs"]="nvlevo",
+ ["de"]="nlinks",
+ ["en"]="nleft",
+ ["fr"]="ngauche",
+ ["it"]="nsinistra",
+ ["nl"]="nlinks",
+ ["pe"]="nleft",
+ ["ro"]="nstanga",
+ },
+ ["nlines"]={
+ ["cs"]="nradky",
+ ["de"]="zzeile",
+ ["en"]="nlines",
+ ["fr"]="nlignes",
+ ["it"]="nrighe",
+ ["nl"]="nregels",
+ ["pe"]="nlines",
+ ["ro"]="nlinii",
+ },
+ ["norm"]={
+ ["cs"]="norm",
+ ["de"]="norm",
+ ["en"]="norm",
+ ["fr"]="norme",
+ ["it"]="norma",
+ ["nl"]="norm",
+ ["pe"]="norm",
+ ["ro"]="norm",
+ },
+ ["nr"]={
+ ["cs"]="nr",
+ ["de"]="nr",
+ ["en"]="nr",
+ ["fr"]="nr",
+ ["it"]="nr",
+ ["nl"]="nr",
+ ["pe"]="nr",
+ ["ro"]="nr",
+ },
+ ["nright"]={
+ ["cs"]="nvpravo",
+ ["de"]="nrechts",
+ ["en"]="nright",
+ ["fr"]="ndroite",
+ ["it"]="ndestra",
+ ["nl"]="nrechts",
+ ["pe"]="nright",
+ ["ro"]="ndreapta",
+ },
+ ["ntop"]={
+ ["cs"]="nvrsek",
+ ["de"]="noben",
+ ["en"]="ntop",
+ ["fr"]="nsup",
+ ["it"]="ncima",
+ ["nl"]="nboven",
+ ["pe"]="ntop",
+ ["ro"]="nsus",
+ },
+ ["number"]={
+ ["cs"]="cislo",
+ ["de"]="nummer",
+ ["en"]="number",
+ ["fr"]="numero",
+ ["it"]="numero",
+ ["nl"]="nummer",
+ ["pe"]="شماره",
+ ["ro"]="numar",
+ },
+ ["numbercolor"]={
+ ["cs"]="barvacisla",
+ ["de"]="nummernfarbe",
+ ["en"]="numbercolor",
+ ["fr"]="couleurnumero",
+ ["it"]="colorenumero",
+ ["nl"]="nummerkleur",
+ ["pe"]="رنگشماره",
+ ["ro"]="culoarenumar",
+ },
+ ["numbercommand"]={
+ ["cs"]="ciselnyprikaz",
+ ["de"]="nummerbefehl",
+ ["en"]="numbercommand",
+ ["fr"]="commandenumero",
+ ["it"]="comandonumero",
+ ["nl"]="nummercommando",
+ ["pe"]="فرمانشماره",
+ ["ro"]="comandanumar",
+ },
+ ["numberconversion"]={
+ ["en"]="numberconversion",
+ },
+ ["numberconversionset"]={
+ ["en"]="numberconversionset",
+ },
+ ["numberdistance"]={
+ ["cs"]="numberdistance",
+ ["de"]="numberdistance",
+ ["en"]="numberdistance",
+ ["fr"]="numberdistance",
+ ["it"]="numberdistance",
+ ["nl"]="nummerafstand",
+ ["pe"]="فاصلهشماره",
+ ["ro"]="numberdistance",
+ },
+ ["numbering"]={
+ ["cs"]="cislovani",
+ ["de"]="nummerierung",
+ ["en"]="numbering",
+ ["fr"]="numerotation",
+ ["it"]="numerazione",
+ ["nl"]="nummeren",
+ ["pe"]="شمارهگذاری",
+ ["ro"]="numerotare",
+ },
+ ["numberorder"]={
+ ["en"]="numberorder",
+ },
+ ["numberprefix"]={
+ ["en"]="numberprefix",
+ },
+ ["numbersegments"]={
+ ["en"]="numbersegments",
+ },
+ ["numberseparator"]={
+ ["cs"]="oddelovaccisla",
+ ["de"]="nummernseperator",
+ ["en"]="numberseparator",
+ ["fr"]="separateurnumbero",
+ ["it"]="separatorenumero",
+ ["nl"]="nummerscheider",
+ ["pe"]="جداکنندهشماره",
+ ["ro"]="separatornumar",
+ },
+ ["numberseparatorset"]={
+ ["en"]="numberseparatorset",
+ },
+ ["numberset"]={
+ ["en"]="numberset",
+ },
+ ["numberstopper"]={
+ ["en"]="numberstopper",
+ },
+ ["numberstarter"]={
+ ["en"]="numberstarter",
+ },
+ ["numberstyle"]={
+ ["cs"]="stylcisla",
+ ["de"]="nummernstil",
+ ["en"]="numberstyle",
+ ["fr"]="stylenumero",
+ ["it"]="stilenumero",
+ ["nl"]="nummerletter",
+ ["pe"]="سبکشماره",
+ ["ro"]="stilnumar",
+ },
+ ["numberwidth"]={
+ ["cs"]="numberwidth",
+ ["de"]="numberwidth",
+ ["en"]="numberwidth",
+ ["fr"]="numberwidth",
+ ["it"]="numberwidth",
+ ["nl"]="nummerbreedte",
+ ["pe"]="عرضشماره",
+ ["ro"]="numberwidth",
+ },
+ ["nx"]={
+ ["cs"]="nx",
+ ["de"]="nx",
+ ["en"]="nx",
+ ["fr"]="nx",
+ ["it"]="nx",
+ ["nl"]="nx",
+ ["pe"]="nx",
+ ["ro"]="nx",
+ },
+ ["ny"]={
+ ["cs"]="ny",
+ ["de"]="ny",
+ ["en"]="ny",
+ ["fr"]="ny",
+ ["it"]="ny",
+ ["nl"]="ny",
+ ["pe"]="ny",
+ ["ro"]="ny",
+ },
+ ["object"]={
+ ["cs"]="objekt",
+ ["de"]="objekt",
+ ["en"]="object",
+ ["fr"]="objet",
+ ["it"]="oggetto",
+ ["nl"]="object",
+ ["pe"]="شیئ",
+ ["ro"]="obiect",
+ },
+ ["obstruction"]={
+ ["cs"]="prekazka",
+ ["de"]="gesperrt",
+ ["en"]="obstruction",
+ ["fr"]="obstruction",
+ ["it"]="ostruzione",
+ ["nl"]="blokkade",
+ ["pe"]="انسداد",
+ ["ro"]="obstructie",
+ },
+ ["oddmargin"]={
+ ["cs"]="lichyokraj",
+ ["de"]="ungeraderand",
+ ["en"]="oddmargin",
+ ["fr"]="margepaire",
+ ["it"]="marginedispari",
+ ["nl"]="onevenmarge",
+ ["pe"]="حاشیهفرد",
+ ["ro"]="margineimpara",
+ },
+ ["offset"]={
+ ["cs"]="offset",
+ ["de"]="offset",
+ ["en"]="offset",
+ ["fr"]="offset",
+ ["it"]="offset",
+ ["nl"]="offset",
+ ["pe"]="آفست",
+ ["ro"]="offset",
+ },
+ ["openaction"]={
+ ["cs"]="otevriakci",
+ ["de"]="oeffenaktion",
+ ["en"]="openaction",
+ ["fr"]="actionouverture",
+ ["it"]="azioneapri",
+ ["nl"]="openactie",
+ ["pe"]="عملباز",
+ ["ro"]="actiunedeschidere",
+ },
+ ["openpageaction"]={
+ ["cs"]="akceotevrenistranky",
+ ["de"]="openpageaction",
+ ["en"]="openpageaction",
+ ["fr"]="actionouverturepage",
+ ["it"]="azioneapripagina",
+ ["nl"]="openpaginaactie",
+ ["pe"]="عملصفحهباز",
+ ["ro"]="actiunedeschiderepagina",
+ },
+ ["option"]={
+ ["cs"]="volba",
+ ["de"]="option",
+ ["en"]="option",
+ ["fr"]="option",
+ ["it"]="opzione",
+ ["nl"]="optie",
+ ["pe"]="گزینه",
+ ["ro"]="optiune",
+ },
+ ["orientation"]={
+ ["cs"]="orientation",
+ ["de"]="orientation",
+ ["en"]="orientation",
+ ["fr"]="orientation",
+ ["it"]="orientation",
+ ["nl"]="orientatie",
+ ["pe"]="جهتدهی",
+ ["ro"]="orientation",
+ },
+ ["outermargin"]={
+ ["cs"]="outermargin",
+ ["de"]="outermargin",
+ ["en"]="outermargin",
+ ["fr"]="margeexterieure",
+ ["it"]="margineesterno",
+ ["nl"]="buitenmarge",
+ ["pe"]="حاشیهخارجی",
+ ["ro"]="outermargin",
+ },
+ ["overprint"]={
+ ["cs"]="overprint",
+ ["de"]="overprint",
+ ["en"]="overprint",
+ ["fr"]="overprint",
+ ["it"]="overprint",
+ ["nl"]="overprint",
+ ["pe"]="overprint",
+ ["ro"]="overprint",
+ },
+ ["ownnumber"]={
+ ["cs"]="vlastnicislo",
+ ["de"]="eigenenummer",
+ ["en"]="ownnumber",
+ ["fr"]="numeroproprio",
+ ["it"]="numeroproprio",
+ ["nl"]="eigennummer",
+ ["pe"]="شمارهخود",
+ ["ro"]="numarpropriu",
+ },
+ ["page"]={
+ ["cs"]="stranka",
+ ["de"]="seite",
+ ["en"]="page",
+ ["fr"]="page",
+ ["it"]="pagina",
+ ["nl"]="pagina",
+ ["pe"]="صفحه",
+ ["ro"]="pagina",
+ },
+ ["pageboundaries"]={
+ ["cs"]="hranicestranky",
+ ["de"]="seitenbegrenzung",
+ ["en"]="pageboundaries",
+ ["fr"]="limitespage",
+ ["it"]="limitipagina",
+ ["nl"]="paginaovergangen",
+ ["pe"]="مرزهایصفحه",
+ ["ro"]="marginipagina",
+ },
+ ["pagecolor"]={
+ ["cs"]="barvastranky",
+ ["de"]="seitenfarbe",
+ ["en"]="pagecolor",
+ ["fr"]="couleurpage",
+ ["it"]="colorepagina",
+ ["nl"]="paginakleur",
+ ["pe"]="رنگصفحه",
+ ["ro"]="culoarepagina",
+ },
+ ["pagecommand"]={
+ ["cs"]="strankovyprikaz",
+ ["de"]="seitenbefehl",
+ ["en"]="pagecommand",
+ ["fr"]="commandepage",
+ ["it"]="comandopagina",
+ ["nl"]="paginacommando",
+ ["pe"]="فرمانصفحه",
+ ["ro"]="comandapagina",
+ },
+ ["pageconversion"]={
+ ["en"]="pageconversion",
+ },
+ ["pageconversionset"]={
+ ["en"]="pageconversionset",
+ },
+ ["pagenumber"]={
+ ["cs"]="cislostranky",
+ ["de"]="seitennummer",
+ ["en"]="pagenumber",
+ ["fr"]="numeropage",
+ ["it"]="numeropagina",
+ ["nl"]="paginanummer",
+ ["pe"]="شمارهصفحه",
+ ["ro"]="numarpagina",
+ },
+ ["pageprefix"]={
+ ["en"]="pageprefix",
+ },
+ ["pageprefixconnector"]={
+ ["en"]="pageprefixconnector",
+ },
+ ["pageprefixconversion"]={
+ ["en"]="pageprefixconversion",
+ },
+ ["pageprefixconversionset"]={
+ ["en"]="pageprefixconversionset",
+ },
+ ["pageprefixsegments"]={
+ ["en"]="pageprefixsegments",
+ },
+ ["pageprefixseparatorset"]={
+ ["en"]="pageprefixseparatorset",
+ },
+ ["pageprefixset"]={
+ ["en"]="pageprefixset",
+ },
+ ["pageprefixstopper"]={
+ ["en"]="pageprefixstopper",
+ },
+ ["pageprefixstarter"]={
+ ["en"]="pageprefixstarter",
+ },
+ ["pagesegments"]={
+ ["en"]="pagesegments",
+ },
+ ["pageseparatorset"]={
+ ["en"]="pageseparatorset",
+ },
+ ["pageset"]={
+ ["en"]="pageset",
+ },
+ ["pagestate"]={
+ ["cs"]="pagestate",
+ ["de"]="pagestate",
+ ["en"]="pagestate",
+ ["fr"]="etatpage",
+ ["it"]="statopagina",
+ ["nl"]="paginastatus",
+ ["pe"]="وضعیتصفحه",
+ ["ro"]="pagestate",
+ },
+ ["pagestopper"]={
+ ["en"]="pagestopper",
+ },
+ ["pagestarter"]={
+ ["en"]="pagestarter",
+ },
+ ["pagestyle"]={
+ ["cs"]="stylstranky",
+ ["de"]="seitenstil",
+ ["en"]="pagestyle",
+ ["fr"]="stylepage",
+ ["it"]="stilepagina",
+ ["nl"]="paginaletter",
+ ["pe"]="سبکصفحه",
+ ["ro"]="stilpagina",
+ },
+ ["palet"]={
+ ["cs"]="paleta",
+ ["de"]="palette",
+ ["en"]="palet",
+ ["fr"]="palette",
+ ["it"]="tavolozza",
+ ["nl"]="palet",
+ ["pe"]="لوح",
+ ["ro"]="paleta",
+ },
+ ["paper"]={
+ ["cs"]="papir",
+ ["de"]="papier",
+ ["en"]="paper",
+ ["fr"]="papier",
+ ["it"]="carta",
+ ["nl"]="papier",
+ ["pe"]="برگ",
+ ["ro"]="hartie",
+ },
+ ["paragraph"]={
+ ["cs"]="odstavec",
+ ["de"]="absatz",
+ ["en"]="paragraph",
+ ["fr"]="paragraphe",
+ ["it"]="capoverso",
+ ["nl"]="alinea",
+ ["pe"]="پاراگراف",
+ ["ro"]="paragraf",
+ },
+ ["place"]={
+ ["cs"]="umistit",
+ ["de"]="platziere",
+ ["en"]="place",
+ ["fr"]="place",
+ ["it"]="metti",
+ ["nl"]="plaatsen",
+ ["pe"]="بگذار",
+ ["ro"]="pune",
+ },
+ ["placehead"]={
+ ["cs"]="umistihlavicku",
+ ["de"]="setzekopf",
+ ["en"]="placehead",
+ ["fr"]="placetete",
+ ["it"]="mettitesta",
+ ["nl"]="plaatskop",
+ ["pe"]="بگذارسر",
+ ["ro"]="punetitlu",
+ },
+ ["placestopper"]={
+ ["cs"]="predelmista",
+ ["de"]="setzetrenner",
+ ["en"]="placestopper",
+ ["fr"]="emplacementstopper",
+ ["it"]="mettistopper",
+ ["nl"]="plaatsafsluiter",
+ ["pe"]="بگذارایست",
+ ["ro"]="punestopper",
+ },
+ ["position"]={
+ ["cs"]="position",
+ ["de"]="position",
+ ["en"]="position",
+ ["fr"]="position",
+ ["it"]="posizione",
+ ["nl"]="positie",
+ ["pe"]="موقعیت",
+ ["ro"]="pozitie",
+ },
+ ["prefix"]={
+ ["cs"]="prefix",
+ ["de"]="prefix",
+ ["en"]="prefix",
+ ["fr"]="prefixe",
+ ["it"]="prefisso",
+ ["nl"]="prefix",
+ ["pe"]="پیشوند",
+ ["ro"]="prefix",
+ },
+ ["prefixconnector"]={
+ ["en"]="prefixconnector",
+ },
+ ["prefixconversion"]={
+ ["en"]="prefixconversion",
+ },
+ ["prefixconversionset"]={
+ ["en"]="prefixconversionset",
+ },
+ ["prefixsegments"]={
+ ["en"]="prefixsegments",
+ },
+ ["prefixseparatorset"]={
+ ["en"]="prefixseparatorset",
+ },
+ ["prefixset"]={
+ ["en"]="prefixset",
+ },
+ ["prefixstopper"]={
+ ["en"]="prefixstopper",
+ },
+ ["prefixstarter"]={
+ ["en"]="prefixstarter",
+ },
+ ["preset"]={
+ ["cs"]="prednastaveni",
+ ["de"]="voreinstellung",
+ ["en"]="preset",
+ ["fr"]="prereglage",
+ ["it"]="preimpostato",
+ ["nl"]="preset",
+ ["pe"]="preset",
+ ["ro"]="preset",
+ },
+ ["preview"]={
+ ["cs"]="nahled",
+ ["de"]="vorschau",
+ ["en"]="preview",
+ ["fr"]="previsualisation",
+ ["it"]="anteprima",
+ ["nl"]="preview",
+ ["pe"]="پیشدید",
+ ["ro"]="previzualizare",
+ },
+ ["previous"]={
+ ["cs"]="predchozi",
+ ["de"]="vorige",
+ ["en"]="previous",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="vorige",
+ ["pe"]="قبلی",
+ ["ro"]="precendent",
+ },
+ ["previousnumber"]={
+ ["cs"]="predchozicislo",
+ ["de"]="vorigenummer",
+ ["en"]="previousnumber",
+ ["fr"]="numeroprecedent",
+ ["it"]="numeroprecedente",
+ ["nl"]="vorigenummer",
+ ["pe"]="شمارهقبلی",
+ ["ro"]="numarprecedent",
+ },
+ ["process"]={
+ ["cs"]="process",
+ ["de"]="process",
+ ["en"]="process",
+ ["fr"]="process",
+ ["it"]="process",
+ ["nl"]="proces",
+ ["pe"]="پردازش",
+ ["ro"]="process",
+ },
+ ["radius"]={
+ ["cs"]="polomer",
+ ["de"]="radius",
+ ["en"]="radius",
+ ["fr"]="rayon",
+ ["it"]="raggio",
+ ["nl"]="straal",
+ ["pe"]="شعاع",
+ ["ro"]="raza",
+ },
+ ["random"]={
+ ["cs"]="nahodne",
+ ["de"]="zufaellig",
+ ["en"]="random",
+ ["fr"]="aleatoire",
+ ["it"]="casuale",
+ ["nl"]="willekeur",
+ ["pe"]="تصادفی",
+ ["ro"]="aleator",
+ },
+ ["range"]={
+ ["en"]="range",
+ ["nl"]="bereik",
+ },
+ ["reduction"]={
+ ["cs"]="redukce",
+ ["de"]="reduktion",
+ ["en"]="reduction",
+ ["fr"]="reduction",
+ ["it"]="riduzione",
+ ["nl"]="reductie",
+ ["pe"]="کاهش",
+ ["ro"]="reducere",
+ },
+ ["ref"]={
+ ["cs"]="ref",
+ ["de"]="ref",
+ ["en"]="ref",
+ ["fr"]="ref",
+ ["it"]="ref",
+ ["nl"]="ref",
+ ["pe"]="رج",
+ ["ro"]="ref",
+ },
+ ["reference"]={
+ ["cs"]="odkaz",
+ ["de"]="referenz",
+ ["en"]="reference",
+ ["fr"]="reference",
+ ["it"]="riferimento",
+ ["nl"]="verwijzing",
+ ["pe"]="مرجع",
+ ["ro"]="referinta",
+ },
+ ["referenceprefix"]={
+ ["en"]="referenceprefix",
+ },
+ ["referencing"]={
+ ["cs"]="odkazujici",
+ ["de"]="referieren",
+ ["en"]="referencing",
+ ["fr"]="referencing",
+ ["it"]="referencing",
+ ["nl"]="refereren",
+ ["pe"]="مراجعه",
+ ["ro"]="referinta",
+ },
+ ["regionin"]={
+ ["cs"]="oblastuvnitr",
+ ["de"]="regionin",
+ ["en"]="regionin",
+ ["fr"]="entreregion",
+ ["it"]="entraregione",
+ ["nl"]="gebiedin",
+ ["pe"]="ناحیهدرون",
+ ["ro"]="regiuneintrare",
+ },
+ ["regionout"]={
+ ["cs"]="oblastvne",
+ ["de"]="regionaus",
+ ["en"]="regionout",
+ ["fr"]="regionexterieure",
+ ["it"]="esciregione",
+ ["nl"]="gebieduit",
+ ["pe"]="ناحیهبیرون",
+ ["ro"]="regiuneiesire",
+ },
+ ["repeat"]={
+ ["cs"]="opakovat",
+ ["de"]="wiederholen",
+ ["en"]="repeat",
+ ["fr"]="repete",
+ ["it"]="ripeti",
+ ["nl"]="herhaal",
+ ["pe"]="تکرار",
+ ["ro"]="repeta",
+ },
+ ["reset"]={
+ ["cs"]="reset",
+ ["de"]="reset",
+ ["en"]="reset",
+ ["fr"]="reset",
+ ["it"]="reset",
+ ["nl"]="reset",
+ ["pe"]="بازنشانی",
+ ["ro"]="reset",
+ },
+ ["resetnumber"]={
+ ["cs"]="resetnumber",
+ ["de"]="resetnumber",
+ ["en"]="resetnumber",
+ ["fr"]="raznumero",
+ ["it"]="resetnumber",
+ ["nl"]="resetnummer",
+ ["pe"]="بازنشانیشماره",
+ ["ro"]="resetnumber",
+ },
+ ["resolution"]={
+ ["cs"]="rozliseni",
+ ["de"]="aufloesung",
+ ["en"]="resolution",
+ ["fr"]="resolution",
+ ["it"]="risoluzione",
+ ["nl"]="resolutie",
+ ["pe"]="کیفیت",
+ ["ro"]="rezolutie",
+ },
+ ["right"]={
+ ["cs"]="vpravo",
+ ["de"]="rechts",
+ ["en"]="right",
+ ["fr"]="droite",
+ ["it"]="destra",
+ ["nl"]="rechts",
+ ["pe"]="راست",
+ ["ro"]="dreapta",
+ },
+ ["rightcolor"]={
+ ["cs"]="barvavpravo",
+ ["de"]="rechterfarbe",
+ ["en"]="rightcolor",
+ ["fr"]="couleurdroite",
+ ["it"]="coloredestra",
+ ["nl"]="rechterkleur",
+ ["pe"]="رنگراست",
+ ["ro"]="culoaredreapta",
+ },
+ ["rightcompoundhyphen"]={
+ ["cs"]="rightcompoundhyphen",
+ ["de"]="rightcompoundhyphen",
+ ["en"]="rightcompoundhyphen",
+ ["fr"]="rightcompoundhyphen",
+ ["it"]="rightcompoundhyphen",
+ ["nl"]="rechterkoppelteken",
+ ["pe"]="rightcompoundhyphen",
+ ["ro"]="rightcompoundhyphen",
+ },
+ ["rightedge"]={
+ ["cs"]="pravahrana",
+ ["de"]="rechtekante",
+ ["en"]="rightedge",
+ ["fr"]="borddroit",
+ ["it"]="bordodestro",
+ ["nl"]="rechterrand",
+ ["pe"]="لبهراست",
+ ["ro"]="borduradreapta",
+ },
+ ["rightedgedistance"]={
+ ["cs"]="vzdalenostpravehrany",
+ ["de"]="rechterkantenabstand",
+ ["en"]="rightedgedistance",
+ ["fr"]="distanceborddroit",
+ ["it"]="distanzabordodestro",
+ ["nl"]="rechterrandafstand",
+ ["pe"]="فاصلهلبهراست",
+ ["ro"]="distantacoltdreapta",
+ },
+ ["rightframe"]={
+ ["cs"]="ramecekvpravo",
+ ["de"]="rechterrahmen",
+ ["en"]="rightframe",
+ ["fr"]="cadredroit",
+ ["it"]="cornicedestra",
+ ["nl"]="rechterkader",
+ ["pe"]="قالبراست",
+ ["ro"]="framedreapta",
+ },
+ ["righthyphen"]={
+ ["cs"]="righthyphen",
+ ["de"]="righthyphen",
+ ["en"]="righthyphen",
+ ["fr"]="righthyphen",
+ ["it"]="righthyphen",
+ ["nl"]="righthyphen",
+ ["pe"]="righthyphen",
+ ["ro"]="righthyphen",
+ },
+ ["rightmargin"]={
+ ["cs"]="pravyokraj",
+ ["de"]="rechterrand",
+ ["en"]="rightmargin",
+ ["fr"]="margedroite",
+ ["it"]="marginedestro",
+ ["nl"]="rechtermarge",
+ ["pe"]="حاشیهراست",
+ ["ro"]="marginedreapta",
+ },
+ ["rightmargindistance"]={
+ ["cs"]="vzdalenostpravehookraje",
+ ["de"]="rechterrandabstand",
+ ["en"]="rightmargindistance",
+ ["fr"]="distancemargedroite",
+ ["it"]="distanzamarginedestro",
+ ["nl"]="rechtermargeafstand",
+ ["pe"]="فاصلهحاشیهراست",
+ ["ro"]="distantamarginedreapta",
+ },
+ ["rightoffset"]={
+ ["cs"]="pravyoffset",
+ ["de"]="rechterabstand",
+ ["en"]="rightoffset",
+ ["fr"]="rightoffset",
+ ["it"]="offsetdestro",
+ ["nl"]="rechteroffset",
+ ["pe"]="آفستراست",
+ ["ro"]="offsetdreapta",
+ },
+ ["rightquotation"]={
+ ["cs"]="citacevpravo",
+ ["de"]="rechterzitat",
+ ["en"]="rightquotation",
+ ["fr"]="citationdroite",
+ ["it"]="citazionedestra",
+ ["nl"]="rechtercitaat",
+ ["pe"]="نقلقولراست",
+ ["ro"]="citatdreapta",
+ },
+ ["rightquote"]={
+ ["cs"]="citovatvpravo",
+ ["de"]="rechterzitieren",
+ ["en"]="rightquote",
+ ["fr"]="citerdroite",
+ ["it"]="menzionedestra",
+ ["nl"]="rechterciteer",
+ ["pe"]="نقلراست",
+ ["ro"]="minicitatdreapta",
+ },
+ ["rightsentence"]={
+ ["cs"]="vetavpravo",
+ ["de"]="rechtersatz",
+ ["en"]="rightsentence",
+ ["fr"]="phrasedroite",
+ ["it"]="frasedestra",
+ ["nl"]="rechterzin",
+ ["pe"]="جملهراست",
+ ["ro"]="propozitiedreapta",
+ },
+ ["rightspeech"]={
+ ["cs"]="rightspeech",
+ ["de"]="rightspeech",
+ ["en"]="rightspeech",
+ ["fr"]="rightspeech",
+ ["it"]="rightspeech",
+ ["nl"]="rechteruitspraak",
+ ["pe"]="سخنرانیراست",
+ ["ro"]="rightspeech",
+ },
+ ["rightstyle"]={
+ ["cs"]="stylvpravo",
+ ["de"]="rechterstil",
+ ["en"]="rightstyle",
+ ["fr"]="styledroit",
+ ["it"]="stiledestra",
+ ["nl"]="rechterletter",
+ ["pe"]="سبکراست",
+ ["ro"]="stildreapta",
+ },
+ ["rightsubsentence"]={
+ ["cs"]="podvetavpravo",
+ ["de"]="rechtersubsatz",
+ ["en"]="rightsubsentence",
+ ["fr"]="sousphrasedroite",
+ ["it"]="sottofrasedestra",
+ ["nl"]="rechtersubzin",
+ ["pe"]="زیرجملهراست",
+ ["ro"]="subpropozitiedreapta",
+ },
+ ["righttext"]={
+ ["cs"]="textvpravo",
+ ["de"]="rechtertext",
+ ["en"]="righttext",
+ ["fr"]="textedroit",
+ ["it"]="testodestro",
+ ["nl"]="rechtertekst",
+ ["pe"]="متنراست",
+ ["ro"]="textdreapta",
+ },
+ ["rightwidth"]={
+ ["cs"]="sirkavpravo",
+ ["de"]="rechterbreite",
+ ["en"]="rightwidth",
+ ["fr"]="largeurdroite",
+ ["it"]="ampiezzadestra",
+ ["nl"]="rechterbreedte",
+ ["pe"]="عرضراست",
+ ["ro"]="marginedreapta",
+ },
+ ["rotation"]={
+ ["cs"]="rotace",
+ ["de"]="rotation",
+ ["en"]="rotation",
+ ["fr"]="rotation",
+ ["it"]="rotazione",
+ ["nl"]="rotatie",
+ ["pe"]="دوران",
+ ["ro"]="rotatie",
+ },
+ ["rule"]={
+ ["cs"]="linka",
+ ["de"]="linie",
+ ["en"]="rule",
+ ["fr"]="ligne",
+ ["it"]="linea",
+ ["nl"]="lijn",
+ ["pe"]="خط",
+ ["ro"]="rigla",
+ },
+ ["rulecolor"]={
+ ["cs"]="barvalinky",
+ ["de"]="linienfarbe",
+ ["en"]="rulecolor",
+ ["fr"]="couleurligne",
+ ["it"]="colorelinea",
+ ["nl"]="lijnkleur",
+ ["pe"]="رنگخط",
+ ["ro"]="culoarerigla",
+ },
+ ["rulethickness"]={
+ ["cs"]="tloustkalinky",
+ ["de"]="liniendicke",
+ ["en"]="rulethickness",
+ ["fr"]="epaisseurligne",
+ ["it"]="spessorelinea",
+ ["nl"]="lijndikte",
+ ["pe"]="ضخامتخط",
+ ["ro"]="grosimerigla",
+ },
+ ["samepage"]={
+ ["cs"]="stejnastranka",
+ ["de"]="selbeseite",
+ ["en"]="samepage",
+ ["fr"]="memepage",
+ ["it"]="stessapagina",
+ ["nl"]="zelfdepagina",
+ ["pe"]="همانصفحه",
+ ["ro"]="aceeasipagina",
+ },
+ ["sample"]={
+ ["cs"]="vzor",
+ ["de"]="muster",
+ ["en"]="sample",
+ ["fr"]="echantillon",
+ ["it"]="campione",
+ ["nl"]="monster",
+ ["pe"]="نمونه",
+ ["ro"]="exemplu",
+ },
+ ["saveinlist"]={
+ ["en"]="saveinlist",
+ },
+ ["scale"]={
+ ["cs"]="meritko",
+ ["de"]="format",
+ ["en"]="scale",
+ ["fr"]="echelle",
+ ["it"]="scala",
+ ["nl"]="schaal",
+ ["pe"]="مقیاس",
+ ["ro"]="scala",
+ },
+ ["scope"]={
+ ["cs"]="rozsah",
+ ["de"]="bereich",
+ ["en"]="scope",
+ ["fr"]="scope",
+ ["it"]="scope",
+ ["nl"]="scope",
+ ["pe"]="طرح",
+ ["ro"]="scop",
+ },
+ ["screen"]={
+ ["cs"]="rastr",
+ ["de"]="raster",
+ ["en"]="screen",
+ ["fr"]="ecran",
+ ["it"]="schermo",
+ ["nl"]="raster",
+ ["pe"]="پرده",
+ ["ro"]="ecran",
+ },
+ ["section"]={
+ ["cs"]="oddil",
+ ["de"]="abschnitt",
+ ["en"]="section",
+ ["fr"]="section",
+ ["it"]="sezione",
+ ["nl"]="sectie",
+ ["pe"]="بخش",
+ ["ro"]="sectiune",
+ },
+ ["sectionconversion"]={
+ ["en"]="sectionconversion",
+ },
+ ["sectionconversionset"]={
+ ["en"]="sectionconversionset",
+ },
+ ["sectionnumber"]={
+ ["cs"]="cislooddilu",
+ ["de"]="abschnittsnummer",
+ ["en"]="sectionnumber",
+ ["fr"]="numerosection",
+ ["it"]="numerosezione",
+ ["nl"]="sectienummer",
+ ["pe"]="شمارهبخش",
+ ["ro"]="numarsectiune",
+ },
+ ["sectionresetset"]={
+ ["en"]="sectionresetset",
+ },
+ ["sectionsegments"]={
+ ["en"]="sectionsegments",
+ },
+ ["sectionseparatorset"]={
+ ["en"]="sectionseparatorset",
+ },
+ ["sectionset"]={
+ ["en"]="sectionset",
+ },
+ ["sectionstopper"]={
+ ["en"]="sectionstopper",
+ },
+ ["sectionstarter"]={
+ ["en"]="sectionstarter",
+ },
+ ["separator"]={
+ ["cs"]="oddelovac",
+ ["de"]="seperator",
+ ["en"]="separator",
+ ["fr"]="separateur",
+ ["it"]="separatore",
+ ["nl"]="scheider",
+ ["pe"]="جداکننده",
+ ["ro"]="separator",
+ },
+ ["set"]={
+ ["cs"]="set",
+ ["de"]="set",
+ ["en"]="set",
+ ["fr"]="set",
+ ["it"]="set",
+ ["nl"]="set",
+ ["pe"]="قراربده",
+ ["ro"]="set",
+ },
+ ["setups"]={
+ ["cs"]="setups",
+ ["de"]="setups",
+ ["en"]="setups",
+ ["fr"]="reglages",
+ ["it"]="setups",
+ ["nl"]="setups",
+ ["pe"]="بارگذاریها",
+ ["ro"]="setups",
+ },
+ ["side"]={
+ ["cs"]="pocitat",
+ ["de"]="objektabstand",
+ ["en"]="side",
+ ["fr"]="cote",
+ ["it"]="lato",
+ ["nl"]="zij",
+ ["pe"]="کنار",
+ ["ro"]="parte",
+ },
+ ["sidealign"]={
+ ["cs"]="sidealign",
+ ["de"]="sidealign",
+ ["en"]="sidealign",
+ ["fr"]="sidealign",
+ ["it"]="sidealign",
+ ["nl"]="zijuitlijnen",
+ ["pe"]="تنظیمکنار",
+ ["ro"]="sidealign",
+ },
+ ["sidemethod"]={
+ ["cs"]="sidemethod",
+ ["de"]="sidemethod",
+ ["en"]="sidemethod",
+ ["fr"]="sidemethod",
+ ["it"]="sidemethod",
+ ["nl"]="zijmethode",
+ ["pe"]="روشکنار",
+ ["ro"]="sidemethod",
+ },
+ ["sidespaceafter"]={
+ ["cs"]="bocnimezeraza",
+ ["de"]="nebennachspatium",
+ ["en"]="sidespaceafter",
+ ["fr"]="espacelateralapres",
+ ["it"]="spaziolateraledopo",
+ ["nl"]="zijnawit",
+ ["pe"]="فضایکناریبعد",
+ ["ro"]="spatiulateraldupa",
+ },
+ ["sidespacebefore"]={
+ ["cs"]="bocnimezerapred",
+ ["de"]="nebenvorspatium",
+ ["en"]="sidespacebefore",
+ ["fr"]="espacelateralavant",
+ ["it"]="spaziolateraleprima",
+ ["nl"]="zijvoorwit",
+ ["pe"]="فضایکناریقبل",
+ ["ro"]="spatiulateralinainte",
+ },
+ ["sign"]={
+ ["cs"]="znak",
+ ["de"]="zeichen",
+ ["en"]="sign",
+ ["fr"]="signe",
+ ["it"]="segno",
+ ["nl"]="teken",
+ ["pe"]="علامت",
+ ["ro"]="semn",
+ },
+ ["size"]={
+ ["cs"]="velikost",
+ ["de"]="groesse",
+ ["en"]="size",
+ ["fr"]="dimension",
+ ["it"]="dimensione",
+ ["nl"]="formaat",
+ ["pe"]="اندازه",
+ ["ro"]="dimensiune",
+ },
+ ["small"]={
+ ["cs"]="male",
+ ["de"]="klein",
+ ["en"]="small",
+ ["fr"]="petit",
+ ["it"]="piccolo",
+ ["nl"]="klein",
+ ["pe"]="کوچک",
+ ["ro"]="mic",
+ },
+ ["sort"]={
+ ["en"]="sort",
+ },
+ ["sorttype"]={
+ ["cs"]="sorttype",
+ ["de"]="sorttype",
+ ["en"]="sorttype",
+ ["fr"]="sorttype",
+ ["it"]="sorttype",
+ ["nl"]="sortering",
+ ["pe"]="ترتیبتایپ",
+ ["ro"]="sorttype",
+ },
+ ["source"]={
+ ["cs"]="zdroj",
+ ["de"]="quelle",
+ ["en"]="source",
+ ["fr"]="origine",
+ ["it"]="origine",
+ ["nl"]="bron",
+ ["pe"]="منبع",
+ ["ro"]="sursa",
+ },
+ ["space"]={
+ ["cs"]="mezera",
+ ["de"]="spatium",
+ ["en"]="space",
+ ["fr"]="espace",
+ ["it"]="spazio",
+ ["nl"]="spatie",
+ ["pe"]="فضا",
+ ["ro"]="spatiu",
+ },
+ ["spaceafter"]={
+ ["cs"]="mezeraza",
+ ["de"]="nachspatium",
+ ["en"]="spaceafter",
+ ["fr"]="espaceapres",
+ ["it"]="spaziodopo",
+ ["nl"]="nawit",
+ ["pe"]="فضابعداز",
+ ["ro"]="spatiudupa",
+ },
+ ["spacebefore"]={
+ ["cs"]="mezerapred",
+ ["de"]="vorspatium",
+ ["en"]="spacebefore",
+ ["fr"]="espaceavant",
+ ["it"]="spazioprima",
+ ["nl"]="voorwit",
+ ["pe"]="فضاقبلاز",
+ ["ro"]="spatiuinainte",
+ },
+ ["spaceinbetween"]={
+ ["cs"]="spaceinbetween",
+ ["de"]="spaceinbetween",
+ ["en"]="spaceinbetween",
+ ["fr"]="spaceinbetween",
+ ["it"]="spaceinbetween",
+ ["nl"]="tussenwit",
+ ["pe"]="فضادربین",
+ ["ro"]="spaceinbetween",
+ },
+ ["spacing"]={
+ ["cs"]="mezerovani",
+ ["de"]="spatiumausgleich",
+ ["en"]="spacing",
+ ["fr"]="espacement",
+ ["it"]="spaziatura",
+ ["nl"]="spatiering",
+ ["pe"]="فضاگذاری",
+ ["ro"]="spatiere",
+ },
+ ["split"]={
+ ["cs"]="split",
+ ["de"]="split",
+ ["en"]="split",
+ ["fr"]="split",
+ ["it"]="separa",
+ ["nl"]="splitsen",
+ ["pe"]="شکافتن",
+ ["ro"]="split",
+ },
+ ["splitcolor"]={
+ ["cs"]="splitcolor",
+ ["de"]="splitcolor",
+ ["en"]="splitcolor",
+ ["fr"]="splitcolor",
+ ["it"]="splitcolor",
+ ["nl"]="splitskleur",
+ ["pe"]="شکافتنرنگ",
+ ["ro"]="splitcolor",
+ },
+ ["splitmethod"]={
+ ["cs"]="splitmethod",
+ ["de"]="splitmethod",
+ ["en"]="splitmethod",
+ ["fr"]="splitmethod",
+ ["it"]="splitmethod",
+ ["nl"]="splitsmethode",
+ ["pe"]="روششکافتن",
+ ["ro"]="splitmethod",
+ },
+ ["splitoffset"]={
+ ["cs"]="splitoffset",
+ ["de"]="splitoffset",
+ ["en"]="splitoffset",
+ ["fr"]="splitoffset",
+ ["it"]="splitoffset",
+ ["nl"]="splitsoffset",
+ ["pe"]="شکافتنآفست",
+ ["ro"]="splitoffset",
+ },
+ ["spot"]={
+ ["cs"]="spot",
+ ["de"]="spot",
+ ["en"]="spot",
+ ["fr"]="spot",
+ ["it"]="spot",
+ ["nl"]="spot",
+ ["pe"]="لکه",
+ ["ro"]="spot",
+ },
+ ["stack"]={
+ ["cs"]="stack",
+ ["de"]="stack",
+ ["en"]="stack",
+ ["fr"]="stack",
+ ["it"]="stack",
+ ["nl"]="stapel",
+ ["pe"]="توده",
+ ["ro"]="stack",
+ },
+ ["start"]={
+ ["cs"]="start",
+ ["de"]="start",
+ ["en"]="start",
+ ["fr"]="demarre",
+ ["it"]="inizia",
+ ["nl"]="start",
+ ["pe"]="شروع",
+ ["ro"]="start",
+ },
+ ["state"]={
+ ["cs"]="status",
+ ["de"]="status",
+ ["en"]="state",
+ ["fr"]="etat",
+ ["it"]="stato",
+ ["nl"]="status",
+ ["pe"]="وضعیت",
+ ["ro"]="stare",
+ },
+ ["step"]={
+ ["cs"]="krok",
+ ["de"]="schritt",
+ ["en"]="step",
+ ["fr"]="pas",
+ ["it"]="passo",
+ ["nl"]="stap",
+ ["pe"]="گام",
+ ["ro"]="pas",
+ },
+ ["stop"]={
+ ["cs"]="stop",
+ ["de"]="stop",
+ ["en"]="stop",
+ ["fr"]="stoppe",
+ ["it"]="termina",
+ ["nl"]="stop",
+ ["pe"]="پایان",
+ ["ro"]="stop",
+ },
+ ["stopper"]={
+ ["cs"]="predel",
+ ["de"]="abschnitttrenner",
+ ["en"]="stopper",
+ ["fr"]="taquet",
+ ["it"]="stopper",
+ ["nl"]="afsluiter",
+ ["pe"]="ایست",
+ ["ro"]="stopper",
+ },
+ ["starter"]={
+ ["en"]="starter",
+ ["nl"]="opener",
+ },
+ ["stretch"]={
+ ["cs"]="natahnout",
+ ["de"]="strecken",
+ ["en"]="stretch",
+ ["fr"]="etire",
+ ["it"]="dilata",
+ ["nl"]="rek",
+ ["pe"]="کشیدن",
+ ["ro"]="dilatat",
+ },
+ ["strut"]={
+ ["cs"]="strut",
+ ["de"]="strut",
+ ["en"]="strut",
+ ["fr"]="strut",
+ ["it"]="strut",
+ ["nl"]="strut",
+ ["pe"]="بست",
+ ["ro"]="strut",
+ },
+ ["style"]={
+ ["cs"]="pismeno",
+ ["de"]="stil",
+ ["en"]="style",
+ ["fr"]="style",
+ ["it"]="stile",
+ ["nl"]="letter",
+ ["pe"]="سبک",
+ ["ro"]="stil",
+ },
+ ["sub"]={
+ ["cs"]="pod",
+ ["de"]="unter",
+ ["en"]="sub",
+ ["fr"]="sous",
+ ["it"]="sotto",
+ ["nl"]="sub",
+ ["pe"]="زیر",
+ ["ro"]="sub",
+ },
+ ["subtitle"]={
+ ["cs"]="podtitulek",
+ ["de"]="untertitel",
+ ["en"]="subtitle",
+ ["fr"]="soustitre",
+ ["it"]="sottotitolo",
+ ["nl"]="subtitel",
+ ["pe"]="زیرعنوان",
+ ["ro"]="subtitlu",
+ },
+ ["suffix"]={
+ ["cs"]="suffix",
+ ["de"]="suffix",
+ ["en"]="suffix",
+ ["fr"]="suffix",
+ ["it"]="suffix",
+ ["nl"]="suffix",
+ ["pe"]="پسوند",
+ ["ro"]="suffix",
+ },
+ ["sx"]={
+ ["cs"]="sx",
+ ["de"]="sx",
+ ["en"]="sx",
+ ["fr"]="sx",
+ ["it"]="sx",
+ ["nl"]="sx",
+ ["pe"]="sx",
+ ["ro"]="sx",
+ },
+ ["sy"]={
+ ["cs"]="sy",
+ ["de"]="sy",
+ ["en"]="sy",
+ ["fr"]="sy",
+ ["it"]="sy",
+ ["nl"]="sy",
+ ["pe"]="sy",
+ ["ro"]="sy",
+ },
+ ["symalign"]={
+ ["cs"]="symzarovnani",
+ ["de"]="symausrichtung",
+ ["en"]="symalign",
+ ["fr"]="symalignement",
+ ["it"]="symallinea",
+ ["nl"]="symuitlijnen",
+ ["pe"]="تنظیمنماد",
+ ["ro"]="symaliniere",
+ },
+ ["symbol"]={
+ ["cs"]="symbol",
+ ["de"]="symbol",
+ ["en"]="symbol",
+ ["fr"]="symbole",
+ ["it"]="simbolo",
+ ["nl"]="symbool",
+ ["pe"]="نماد",
+ ["ro"]="simbol",
+ },
+ ["symbolset"]={
+ ["cs"]="sadasymbolu",
+ ["de"]="symbolset",
+ ["en"]="symbolset",
+ ["fr"]="jeusymbole",
+ ["it"]="setsimboli",
+ ["nl"]="symboolset",
+ ["pe"]="مجموعهنماد",
+ ["ro"]="setsimbol",
+ },
+ ["symcolor"]={
+ ["cs"]="barvasymbolu",
+ ["de"]="symfarbe",
+ ["en"]="symcolor",
+ ["fr"]="couleursym",
+ ["it"]="coloresimbolo",
+ ["nl"]="symkleur",
+ ["pe"]="رنگنماد",
+ ["ro"]="culoaresimbol",
+ },
+ ["symstyle"]={
+ ["cs"]="stylsymboly",
+ ["de"]="symstil",
+ ["en"]="symstyle",
+ ["fr"]="stylesym",
+ ["it"]="stilesimbolo",
+ ["nl"]="symletter",
+ ["pe"]="سبکنماد",
+ ["ro"]="stilsimbol",
+ },
+ ["synonym"]={
+ ["cs"]="synonymum",
+ ["de"]="synonym",
+ ["en"]="synonym",
+ ["fr"]="synonyme",
+ ["it"]="sinonimo",
+ ["nl"]="synoniem",
+ ["pe"]="مترادف",
+ ["ro"]="sinonim",
+ },
+ ["synonymcolor"]={
+ ["cs"]="barvasynonyma",
+ ["de"]="synonymfarbe",
+ ["en"]="synonymcolor",
+ ["fr"]="couleursynonyme",
+ ["it"]="coloresinonimi",
+ ["nl"]="synoniemkleur",
+ ["pe"]="رنگمترادف",
+ ["ro"]="culoaresinonim",
+ },
+ ["synonymcommand"]={
+ ["cs"]="synonymcommand",
+ ["de"]="synonymbefehl",
+ ["en"]="synonymcommand",
+ ["fr"]="synonymcommand",
+ ["it"]="synonymcommand",
+ ["nl"]="synoniemcommando",
+ ["pe"]="synonymcommand",
+ ["ro"]="synonymcommand",
+ },
+ ["synonymstyle"]={
+ ["cs"]="stylsynonyma",
+ ["de"]="synonymstil",
+ ["en"]="synonymstyle",
+ ["fr"]="stylesynonyme",
+ ["it"]="stilesinonimi",
+ ["nl"]="synoniemletter",
+ ["pe"]="سبکمترادف",
+ ["ro"]="stilsinonim",
+ },
+ ["tab"]={
+ ["cs"]="tab",
+ ["de"]="tab",
+ ["en"]="tab",
+ ["fr"]="tab",
+ ["it"]="tab",
+ ["nl"]="tab",
+ ["pe"]="تب",
+ ["ro"]="tab",
+ },
+ ["text"]={
+ ["cs"]="text",
+ ["de"]="text",
+ ["en"]="text",
+ ["fr"]="texte",
+ ["it"]="testo",
+ ["nl"]="tekst",
+ ["pe"]="متن",
+ ["ro"]="text",
+ },
+ ["textcolor"]={
+ ["cs"]="barvatextu",
+ ["de"]="textfarbe",
+ ["en"]="textcolor",
+ ["fr"]="couleurtexte",
+ ["it"]="coloretesto",
+ ["nl"]="tekstkleur",
+ ["pe"]="رنگمتن",
+ ["ro"]="culoaretext",
+ },
+ ["textcommand"]={
+ ["cs"]="textovyprikaz",
+ ["de"]="textbefehl",
+ ["en"]="textcommand",
+ ["fr"]="commandetexte",
+ ["it"]="comandotesto",
+ ["nl"]="tekstcommando",
+ ["pe"]="فرمانمتن",
+ ["ro"]="comandatext",
+ },
+ ["textdistance"]={
+ ["cs"]="textdistance",
+ ["de"]="textdistance",
+ ["en"]="textdistance",
+ ["fr"]="distancetexte",
+ ["it"]="distanzatesto",
+ ["nl"]="tekstafstand",
+ ["pe"]="فاصلهمتن",
+ ["ro"]="textdistance",
+ },
+ ["textlayer"]={
+ ["cs"]="textlayer",
+ ["de"]="textlayer",
+ ["en"]="textlayer",
+ ["fr"]="calquetexte",
+ ["it"]="textlayer",
+ ["nl"]="tekstlaag",
+ ["pe"]="لایهمتن",
+ ["ro"]="textlayer",
+ },
+ ["textmargin"]={
+ ["cs"]="textmargin",
+ ["de"]="textmargin",
+ ["en"]="textmargin",
+ ["fr"]="margetexte",
+ ["it"]="textmargin",
+ ["nl"]="tekstmarge",
+ ["pe"]="حاشیهمتن",
+ ["ro"]="textmargin",
+ },
+ ["textmethod"]={
+ ["cs"]="textmethod",
+ ["de"]="textmethod",
+ ["en"]="textmethod",
+ ["fr"]="textmethod",
+ ["it"]="textmethod",
+ ["nl"]="tekstmethode",
+ ["pe"]="روشمتن",
+ ["ro"]="textmethod",
+ },
+ ["textseparator"]={
+ ["cs"]="oddelovactextu",
+ ["de"]="textseparator",
+ ["en"]="textseparator",
+ ["fr"]="separateurtexte",
+ ["it"]="separatoretesto",
+ ["nl"]="tekstscheider",
+ ["pe"]="جداکنندهمتن",
+ ["ro"]="separatortext",
+ },
+ ["textsize"]={
+ ["cs"]="velikosttextu",
+ ["de"]="textgroesse",
+ ["en"]="textsize",
+ ["fr"]="tailletexte",
+ ["it"]="dimensionetesto",
+ ["nl"]="tekstformaat",
+ ["pe"]="اندازهمتن",
+ ["ro"]="dimensiunetext",
+ },
+ ["textstate"]={
+ ["cs"]="statustextu",
+ ["de"]="textstatus",
+ ["en"]="textstate",
+ ["fr"]="etattexte",
+ ["it"]="statotesto",
+ ["nl"]="tekststatus",
+ ["pe"]="وضعیتمتن",
+ ["ro"]="staretext",
+ },
+ ["textstyle"]={
+ ["cs"]="styltextu",
+ ["de"]="textstil",
+ ["en"]="textstyle",
+ ["fr"]="styletexte",
+ ["it"]="stiletesto",
+ ["nl"]="tekstletter",
+ ["pe"]="سبکمتن",
+ ["ro"]="stiltext",
+ },
+ ["textwidth"]={
+ ["cs"]="sirkatextu",
+ ["de"]="textbreite",
+ ["en"]="textwidth",
+ ["fr"]="largeurtexte",
+ ["it"]="ampiezzatesto",
+ ["nl"]="tekstbreedte",
+ ["pe"]="عرضمتن",
+ ["ro"]="latimetext",
+ },
+ ["title"]={
+ ["cs"]="titul",
+ ["de"]="titel",
+ ["en"]="title",
+ ["fr"]="titre",
+ ["it"]="titolo",
+ ["nl"]="titel",
+ ["pe"]="عنوان",
+ ["ro"]="titlu",
+ },
+ ["titlecolor"]={
+ ["cs"]="barvatitulek",
+ ["de"]="titelfarbe",
+ ["en"]="titlecolor",
+ ["fr"]="couleurtitre",
+ ["it"]="coloretitolo",
+ ["nl"]="titelkleur",
+ ["pe"]="رنگعنوان",
+ ["ro"]="culoaretitlu",
+ },
+ ["titlecommand"]={
+ ["cs"]="titlecommand",
+ ["de"]="titlecommand",
+ ["en"]="titlecommand",
+ ["fr"]="titlecommand",
+ ["it"]="titlecommand",
+ ["nl"]="titelcommando",
+ ["pe"]="فرمانعنوان",
+ ["ro"]="titlecommand",
+ },
+ ["titledistance"]={
+ ["cs"]="vzdalenosttitulek",
+ ["de"]="titelabstand",
+ ["en"]="titledistance",
+ ["fr"]="distancetitre",
+ ["it"]="distanzatitolo",
+ ["nl"]="titelafstand",
+ ["pe"]="فاصلهعنوان",
+ ["ro"]="distantatitlu",
+ },
+ ["titleleft"]={
+ ["cs"]="titleleft",
+ ["de"]="titleleft",
+ ["en"]="titleleft",
+ ["fr"]="titleleft",
+ ["it"]="titleleft",
+ ["nl"]="titellinks",
+ ["pe"]="عنوانچپ",
+ ["ro"]="titleleft",
+ },
+ ["titleright"]={
+ ["cs"]="titleright",
+ ["de"]="titleright",
+ ["en"]="titleright",
+ ["fr"]="titleright",
+ ["it"]="titleright",
+ ["nl"]="titelrechts",
+ ["pe"]="عنوانراست",
+ ["ro"]="titleright",
+ },
+ ["titlestyle"]={
+ ["cs"]="styltitulek",
+ ["de"]="titelstil",
+ ["en"]="titlestyle",
+ ["fr"]="styletitre",
+ ["it"]="stiletitolo",
+ ["nl"]="titelletter",
+ ["pe"]="سبکعنوان",
+ ["ro"]="stiltitlu",
+ },
+ ["to"]={
+ ["cs"]="na",
+ ["de"]="zu",
+ ["en"]="to",
+ ["fr"]="vers",
+ ["it"]="verso",
+ ["nl"]="aan",
+ ["pe"]="به",
+ ["ro"]="catre",
+ },
+ ["tolerance"]={
+ ["cs"]="tolerance",
+ ["de"]="toleranz",
+ ["en"]="tolerance",
+ ["fr"]="tolerance",
+ ["it"]="tolleranza",
+ ["nl"]="tolerantie",
+ ["pe"]="بردباری",
+ ["ro"]="toleranta",
+ },
+ ["top"]={
+ ["cs"]="vrsek",
+ ["de"]="oben",
+ ["en"]="top",
+ ["fr"]="sup",
+ ["it"]="cima",
+ ["nl"]="boven",
+ ["pe"]="بالا",
+ ["ro"]="sus",
+ },
+ ["topdistance"]={
+ ["cs"]="vzdalenostvrsku",
+ ["de"]="obenabstand",
+ ["en"]="topdistance",
+ ["fr"]="distancesup",
+ ["it"]="distanzacima",
+ ["nl"]="bovenafstand",
+ ["pe"]="فاصلهبالا",
+ ["ro"]="distantasus",
+ },
+ ["topframe"]={
+ ["cs"]="rameceknahore",
+ ["de"]="obenrahmen",
+ ["en"]="topframe",
+ ["fr"]="cadresup",
+ ["it"]="cornicecima",
+ ["nl"]="bovenkader",
+ ["pe"]="قالبراست",
+ ["ro"]="framesus",
+ },
+ ["topoffset"]={
+ ["cs"]="offsetvrsku",
+ ["de"]="obenoffset",
+ ["en"]="topoffset",
+ ["fr"]="decalagesup",
+ ["it"]="offsetcima",
+ ["nl"]="bovenoffset",
+ ["pe"]="آفستبالا",
+ ["ro"]="offsetsus",
+ },
+ ["topspace"]={
+ ["cs"]="svrchnimezera",
+ ["de"]="kopfspatium",
+ ["en"]="topspace",
+ ["fr"]="espacesup",
+ ["it"]="spaziocima",
+ ["nl"]="kopwit",
+ ["pe"]="فضایبالا",
+ ["ro"]="spatiusus",
+ },
+ ["topstate"]={
+ ["cs"]="statusvrsku",
+ ["de"]="statusoben",
+ ["en"]="topstate",
+ ["fr"]="etatsup",
+ ["it"]="statocima",
+ ["nl"]="bovenstatus",
+ ["pe"]="وضعیتبالا",
+ ["ro"]="staresus",
+ },
+ ["type"]={
+ ["cs"]="typ",
+ ["de"]="typ",
+ ["en"]="type",
+ ["fr"]="type",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ ["unit"]={
+ ["cs"]="jednotka",
+ ["de"]="einheit",
+ ["en"]="unit",
+ ["fr"]="unite",
+ ["it"]="unita",
+ ["nl"]="eenheid",
+ ["pe"]="واحد",
+ ["ro"]="unitate",
+ },
+ ["unknownreference"]={
+ ["cs"]="neznamyodkaz",
+ ["de"]="unbekantereferenz",
+ ["en"]="unknownreference",
+ ["fr"]="referenceinconnue",
+ ["it"]="riferimentoingoto",
+ ["nl"]="onbekendeverwijzing",
+ ["pe"]="مرجعناشناس",
+ ["ro"]="referintanecunoscuta",
+ },
+ ["urlalternative"]={
+ ["cs"]="urlalternativa",
+ ["de"]="urlalternative",
+ ["en"]="urlalternative",
+ ["fr"]="alternativeurl",
+ ["it"]="alternativaurl",
+ ["nl"]="urlvariant",
+ ["pe"]="urlalternative",
+ ["ro"]="urlalternativ",
+ },
+ ["urlspace"]={
+ ["cs"]="prostorurl",
+ ["de"]="urlspatium",
+ ["en"]="urlspace",
+ ["fr"]="espaceurl",
+ ["it"]="spaziourl",
+ ["nl"]="urlspatie",
+ ["pe"]="urlspace",
+ ["ro"]="spatiuurl",
+ },
+ ["validate"]={
+ ["cs"]="validovat",
+ ["de"]="validieren",
+ ["en"]="validate",
+ ["fr"]="valider",
+ ["it"]="verifica",
+ ["nl"]="valideer",
+ ["pe"]="تاییداعتبار",
+ ["ro"]="verifica",
+ },
+ ["vcommand"]={
+ ["cs"]="vprikaz",
+ ["de"]="vbefehl",
+ ["en"]="vcommand",
+ ["fr"]="vcommande",
+ ["it"]="vcomando",
+ ["nl"]="vcommando",
+ ["pe"]="vcommand",
+ ["ro"]="comandav",
+ },
+ ["veroffset"]={
+ ["cs"]="offsethlavicky",
+ ["de"]="kopfoffset",
+ ["en"]="veroffset",
+ ["fr"]="veroffset",
+ ["it"]="veroffset",
+ ["nl"]="kopoffset",
+ ["pe"]="آفستعم",
+ ["ro"]="veroffset",
+ },
+ ["vfil"]={
+ ["cs"]="vfil",
+ ["de"]="vfil",
+ ["en"]="vfil",
+ ["fr"]="vfil",
+ ["it"]="vfil",
+ ["nl"]="vfil",
+ ["pe"]="vfil",
+ ["ro"]="vfil",
+ },
+ ["voffset"]={
+ ["cs"]="voffset",
+ ["de"]="voffset",
+ ["en"]="voffset",
+ ["fr"]="voffset",
+ ["it"]="voffset",
+ ["nl"]="voffset",
+ ["pe"]="آفستع",
+ ["ro"]="voffset",
+ },
+ ["way"]={
+ ["cs"]="zpusob",
+ ["de"]="art",
+ ["en"]="way",
+ ["fr"]="mode",
+ ["it"]="modo",
+ ["nl"]="wijze",
+ ["pe"]="راه",
+ ["ro"]="mod",
+ },
+ ["wfactor"]={
+ ["cs"]="sfaktor",
+ ["de"]="bfaktor",
+ ["en"]="wfactor",
+ ["fr"]="facteurlargeur",
+ ["it"]="wfactor",
+ ["nl"]="bfactor",
+ ["pe"]="wfactor",
+ ["ro"]="factorw",
+ },
+ ["white"]={
+ ["cs"]="bily",
+ ["de"]="weiss",
+ ["en"]="white",
+ ["fr"]="blanc",
+ ["it"]="bianco",
+ ["nl"]="wit",
+ ["pe"]="سفید",
+ ["ro"]="alb",
+ },
+ ["width"]={
+ ["cs"]="sirka",
+ ["de"]="breite",
+ ["en"]="width",
+ ["fr"]="largeur",
+ ["it"]="ampiezza",
+ ["nl"]="breedte",
+ ["pe"]="عرض",
+ ["ro"]="latime",
+ },
+ ["xfactor"]={
+ ["cs"]="xfaktor",
+ ["de"]="xfaktor",
+ ["en"]="xfactor",
+ ["fr"]="xfactor",
+ ["it"]="xfactor",
+ ["nl"]="xfactor",
+ ["pe"]="فاکتورایکس",
+ ["ro"]="xfactor",
+ },
+ ["xmax"]={
+ ["cs"]="xmax",
+ ["de"]="xmax",
+ ["en"]="xmax",
+ ["fr"]="xmax",
+ ["it"]="xmax",
+ ["nl"]="xmax",
+ ["pe"]="xmax",
+ ["ro"]="xmax",
+ },
+ ["xoffset"]={
+ ["cs"]="xoffset",
+ ["de"]="xoffset",
+ ["en"]="xoffset",
+ ["fr"]="xoffset",
+ ["it"]="xoffset",
+ ["nl"]="xoffset",
+ ["pe"]="آفستایکس",
+ ["ro"]="xoffset",
+ },
+ ["xscale"]={
+ ["cs"]="xmeritko",
+ ["de"]="xformat",
+ ["en"]="xscale",
+ ["fr"]="xscale",
+ ["it"]="xscale",
+ ["nl"]="xschaal",
+ ["pe"]="مقیاسایکس",
+ ["ro"]="xscala",
+ },
+ ["xstep"]={
+ ["cs"]="xkrok",
+ ["de"]="xschritt",
+ ["en"]="xstep",
+ ["fr"]="xstep",
+ ["it"]="xstep",
+ ["nl"]="xstap",
+ ["pe"]="گامایکس",
+ ["ro"]="xstep",
+ },
+ ["yfactor"]={
+ ["cs"]="yfaktor",
+ ["de"]="yfaktor",
+ ["en"]="yfactor",
+ ["fr"]="yfactor",
+ ["it"]="yfactor",
+ ["nl"]="yfactor",
+ ["pe"]="فاکتوروای",
+ ["ro"]="yfactor",
+ },
+ ["ymax"]={
+ ["cs"]="ymax",
+ ["de"]="ymax",
+ ["en"]="ymax",
+ ["fr"]="ymax",
+ ["it"]="ymax",
+ ["nl"]="ymax",
+ ["pe"]="ymax",
+ ["ro"]="ymax",
+ },
+ ["yoffset"]={
+ ["cs"]="yoffset",
+ ["de"]="yoffset",
+ ["en"]="yoffset",
+ ["fr"]="yoffset",
+ ["it"]="yoffset",
+ ["nl"]="yoffset",
+ ["pe"]="آفستوای",
+ ["ro"]="yoffset",
+ },
+ ["yscale"]={
+ ["cs"]="ymeritko",
+ ["de"]="yformat",
+ ["en"]="yscale",
+ ["fr"]="yscale",
+ ["it"]="yscale",
+ ["nl"]="yschaal",
+ ["pe"]="مقیاسوای",
+ ["ro"]="yscala",
+ },
+ ["ystep"]={
+ ["cs"]="ykrok",
+ ["de"]="yschritt",
+ ["en"]="ystep",
+ ["fr"]="ystep",
+ ["it"]="ystep",
+ ["nl"]="ystap",
+ ["pe"]="گاموای",
+ ["ro"]="ystep",
+ },
+ },
+ ["elements"]={
+ ["answerlines"]={
+ ["cs"]="answerlines",
+ ["de"]="answerlines",
+ ["en"]="answerlines",
+ ["fr"]="answerlines",
+ ["it"]="answerlines",
+ ["nl"]="antwoordregels",
+ ["pe"]="answerlines",
+ ["ro"]="answerlines",
+ },
+ ["answerspace"]={
+ ["cs"]="answerspace",
+ ["de"]="answerspace",
+ ["en"]="answerspace",
+ ["fr"]="answerspace",
+ ["it"]="answerspace",
+ ["nl"]="antwoordruimte",
+ ["pe"]="answerspace",
+ ["ro"]="answerspace",
+ },
+ ["begin"]={
+ ["cs"]="zacatek",
+ ["de"]="anfang",
+ ["en"]="begin",
+ ["fr"]="debut",
+ ["it"]="inizio",
+ ["nl"]="beginvan",
+ ["pe"]="عنصرها",
+ ["ro"]="inceput",
+ },
+ ["complete"]={
+ ["cs"]="uplny",
+ ["de"]="vollende",
+ ["en"]="complete",
+ ["fr"]="complete",
+ ["it"]="completo",
+ ["nl"]="volledige",
+ ["pe"]="کامل",
+ ["ro"]="complet",
+ },
+ ["coupled"]={
+ ["cs"]="propojene",
+ ["de"]="verknuepft",
+ ["en"]="coupled",
+ ["fr"]="couple",
+ ["it"]="accoppiato",
+ ["nl"]="gekoppelde",
+ ["pe"]="مزدوج",
+ ["ro"]="cuplat",
+ },
+ ["currentlocal"]={
+ ["cs"]="aktualnelokalni",
+ ["de"]="aktuelllokal",
+ ["en"]="currentlocal",
+ ["fr"]="localcourant",
+ ["it"]="correntelocale",
+ ["nl"]="huidigelokale",
+ ["pe"]="موضعیجاری",
+ ["ro"]="localcurent",
+ },
+ ["emptyone"]={
+ ["cs"]="leer",
+ ["de"]="vuoto",
+ ["en"]="empty",
+ ["fr"]="vide",
+ ["it"]="prazdne",
+ ["nl"]="leeg",
+ ["pe"]="یکخالی",
+ ["ro"]="gol",
+ },
+ ["emptytwo"]={
+ ["cs"]="prazdne",
+ ["de"]="leer",
+ ["en"]="empty",
+ ["fr"]="vide",
+ ["it"]="vuoti",
+ ["nl"]="lege",
+ ["pe"]="دوخالی",
+ ["ro"]="gol",
+ },
+ ["end"]={
+ ["cs"]="konec",
+ ["de"]="ende",
+ ["en"]="end",
+ ["fr"]="fin",
+ ["it"]="fine",
+ ["nl"]="eindvan",
+ ["pe"]="انتها",
+ ["ro"]="sfarsit",
+ },
+ ["endsetup"]={
+ ["cs"]="",
+ ["de"]="ein",
+ ["en"]="",
+ ["fr"]="",
+ ["it"]="",
+ ["nl"]="in",
+ ["pe"]="انتهایبارگذاری",
+ ["ro"]="",
+ },
+ ["get"]={
+ ["cs"]="ziskat",
+ ["de"]="get",
+ ["en"]="get",
+ ["fr"]="obtient",
+ ["it"]="prendi",
+ ["nl"]="haal",
+ ["pe"]="بگیر",
+ ["ro"]="get",
+ },
+ ["increment"]={
+ ["cs"]="zvysit",
+ ["de"]="erhoehen",
+ ["en"]="increment",
+ ["fr"]="incremente",
+ ["it"]="incrementa",
+ ["nl"]="verhoog",
+ ["pe"]="افزایش",
+ ["ro"]="increment",
+ },
+ ["list"]={
+ ["cs"]="seznam",
+ ["de"]="auflisten",
+ ["en"]="list",
+ ["fr"]="liste",
+ ["it"]="elenco",
+ ["nl"]="lijst",
+ ["pe"]="لیست",
+ ["ro"]="lista",
+ },
+ ["listof"]={
+ ["cs"]="seznam",
+ ["de"]="auflistenvon",
+ ["en"]="listof",
+ ["fr"]="listede",
+ ["it"]="elencodi",
+ ["nl"]="lijstmet",
+ ["pe"]="لیستاز",
+ ["ro"]="listade",
+ },
+ ["load"]={
+ ["cs"]="nacist",
+ ["de"]="laden",
+ ["en"]="load",
+ ["fr"]="charge",
+ ["it"]="carica",
+ ["nl"]="laad",
+ ["pe"]="بارگذاشتن",
+ ["ro"]="incarca",
+ },
+ ["local"]={
+ ["cs"]="lokalne",
+ ["de"]="lokal",
+ ["en"]="local",
+ ["fr"]="local",
+ ["it"]="locale",
+ ["nl"]="lokale",
+ ["pe"]="موضعی",
+ ["ro"]="local",
+ },
+ ["makeup"]={
+ ["cs"]="zlom",
+ ["de"]="umbruch",
+ ["en"]="makeup",
+ ["fr"]="makeup",
+ ["it"]="makeup",
+ ["nl"]="opmaak",
+ ["pe"]="آرایش",
+ ["ro"]="makeup",
+ },
+ ["next"]={
+ ["cs"]="dalsi",
+ ["de"]="folgende",
+ ["en"]="next",
+ ["fr"]="suivant",
+ ["it"]="successivo",
+ ["nl"]="volgende",
+ ["pe"]="بعدی",
+ ["ro"]="urmatorul",
+ },
+ ["place"]={
+ ["cs"]="umisti",
+ ["de"]="platziere",
+ ["en"]="place",
+ ["fr"]="place",
+ ["it"]="metti",
+ ["nl"]="plaats",
+ ["pe"]="مکان",
+ ["ro"]="pune",
+ },
+ ["previous"]={
+ ["cs"]="predchozi",
+ ["de"]="vorige",
+ ["en"]="previous",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="vorige",
+ ["pe"]="قبلی",
+ ["ro"]="precedent",
+ },
+ ["previouslocal"]={
+ ["cs"]="predchozilokalni",
+ ["de"]="voriglokal",
+ ["en"]="previouslocal",
+ ["fr"]="localprecedent",
+ ["it"]="precedentelocale",
+ ["nl"]="vorigelokale",
+ ["pe"]="موضعقبلی",
+ ["ro"]="precedentlocal",
+ },
+ ["reserve"]={
+ ["cs"]="rezervovat",
+ ["de"]="reservieren",
+ ["en"]="reserve",
+ ["fr"]="reserver",
+ ["it"]="riserva",
+ ["nl"]="reserveer",
+ ["pe"]="رزرو",
+ ["ro"]="rezervat",
+ },
+ ["see"]={
+ ["cs"]="viz",
+ ["de"]="sieh",
+ ["en"]="see",
+ ["fr"]="voit",
+ ["it"]="vedi",
+ ["nl"]="zie",
+ ["pe"]="ببینید",
+ ["ro"]="vezi",
+ },
+ ["setup"]={
+ ["cs"]="nastaveni",
+ ["de"]="stelle",
+ ["en"]="setup",
+ ["fr"]="regle",
+ ["it"]="imposta",
+ ["nl"]="stel",
+ ["pe"]="بارگذاری",
+ ["ro"]="setare",
+ },
+ ["start"]={
+ ["cs"]="start",
+ ["de"]="start",
+ ["en"]="start",
+ ["fr"]="demarre",
+ ["it"]="inizia",
+ ["nl"]="start",
+ ["pe"]="شروع",
+ ["ro"]="start",
+ },
+ ["stop"]={
+ ["cs"]="stop",
+ ["de"]="stop",
+ ["en"]="stop",
+ ["fr"]="stoppe",
+ ["it"]="termina",
+ ["nl"]="stop",
+ ["pe"]="پایان",
+ ["ro"]="stop",
+ },
+ ["text"]={
+ ["cs"]="text",
+ ["de"]="text",
+ ["en"]="text",
+ ["fr"]="texte",
+ ["it"]="testo",
+ ["nl"]="tekst",
+ ["pe"]="متن",
+ ["ro"]="text",
+ },
+ ["type"]={
+ ["cs"]="opis",
+ ["de"]="type",
+ ["en"]="type",
+ ["fr"]="type",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ },
+ ["variables"]={
+ ["end"]={
+ ["en"]="end",
+ ["nl"]="eind",
+ },
+ ["begin"]={
+ ["en"]="begin",
+ ["nl"]="begin",
+ },
+ ["down"]={
+ ["en"]="down",
+ ["nl"]="omlaag",
+ },
+ ["up"]={
+ ["en"]="up",
+ ["nl"]="omhoog",
+ },
+ ["underbar"]={
+ ["cs"]="podtrzeno",
+ ["de"]="unterstrichen",
+ ["en"]="underbar",
+ ["fr"]="souslignetout",
+ ["it"]="sottolinea",
+ ["nl"]="onderstreep",
+ ["pe"]="میلهزیر",
+ ["ro"]="sublinie",
+ },
+ ["underbars"]={
+ ["cs"]="podtrzeni",
+ ["de"]="unterstreichen",
+ ["en"]="underbars",
+ ["fr"]="sousligne",
+ ["it"]="sottolinee",
+ ["nl"]="onderstrepen",
+ ["pe"]="میلههایزیر",
+ ["ro"]="sublinii",
+ },
+ ["overbar"]={
+ ["cs"]="nadtrzeno",
+ ["de"]="ueberstrichen",
+ ["en"]="overbar",
+ ["fr"]="overbar",
+ ["it"]="sopralinea",
+ ["nl"]="overstreep",
+ ["pe"]="میلهرو",
+ ["ro"]="barasus",
+ },
+ ["overbars"]={
+ ["cs"]="nadtrzeni",
+ ["de"]="ueberstreichen",
+ ["en"]="overbars",
+ ["fr"]="overbars",
+ ["it"]="sopralinee",
+ ["nl"]="overstrepen",
+ ["pe"]="میلههارو",
+ ["ro"]="supralinie",
+ },
+ ["overstrike"]={
+ ["cs"]="preskrtnuto",
+ ["de"]="durchgestrichen",
+ ["en"]="overstrike",
+ ["fr"]="surlignetout",
+ ["it"]="sbarrato",
+ ["nl"]="doorstreep",
+ ["pe"]="خطزدن",
+ ["ro"]="liniepeste",
+ },
+ ["overstrikes"]={
+ ["cs"]="preskrtnuti",
+ ["de"]="durchstreichen",
+ ["en"]="overstrikes",
+ ["fr"]="surligne",
+ ["it"]="sbarrati",
+ ["nl"]="doorstrepen",
+ ["pe"]="خطزدنها",
+ ["ro"]="liniipeste",
+ },
+ ["maxheight"]={
+ ["en"]="maxheight",
+ },
+ ["maxdepth"]={
+ ["en"]="maxdepth",
+ },
+ ["maxwidth"]={
+ ["en"]="maxwidth",
+ },
+ ["minheight"]={
+ ["en"]="minheight",
+ },
+ ["mindepth"]={
+ ["en"]="mindepth",
+ },
+ ["minwidth"]={
+ ["en"]="minwidth",
+ },
+ ["short"]={
+ ["nl"]="kort",
+ ["en"]="short",
+ ["de"]="kurz",
+ ["cs"]="short",
+ ["it"]="short",
+ ["ro"]="short",
+ ["fr"]="short",
+ },
+ ["cite"]={
+ ["en"]="cite",
+ },
+ ["bbl"]={
+ ["en"]="bbl",
+ },
+ ["bib"]={
+ ["en"]="bib",
+ },
+ ["author"]={
+ ["nl"]="auteur",
+ ["en"]="author",
+ ["de"]="autor",
+ ["cs"]="autor",
+ ["it"]="autore",
+ ["ro"]="autor",
+ ["fr"]="auteur",
+ },
+ ["Addition"]={
+ ["cs"]="Pridavek",
+ ["de"]="Zusatz",
+ ["en"]="Addition",
+ ["fr"]="Ajout",
+ ["it"]="Aggiunta",
+ ["nl"]="Toevoeging",
+ ["pe"]="جمع",
+ ["ro"]="Adaugare",
+ },
+ ["Balloon"]={
+ ["cs"]="Bublinka",
+ ["de"]="Ballon",
+ ["en"]="Balloon",
+ ["fr"]="Ballon",
+ ["it"]="Pallone",
+ ["nl"]="Ballon",
+ ["pe"]="بادکنک",
+ ["ro"]="Balon",
+ },
+ ["Character"]={
+ ["cs"]="Pismeno",
+ ["de"]="Buchstabe",
+ ["en"]="Character",
+ ["fr"]="Caratere",
+ ["it"]="Lettera",
+ ["nl"]="Letter",
+ ["pe"]="Character",
+ ["ro"]="Caracter",
+ },
+ ["Characters"]={
+ ["cs"]="Pismena",
+ ["de"]="Buchstaben",
+ ["en"]="Characters",
+ ["fr"]="Caracteres",
+ ["it"]="Lettere",
+ ["nl"]="Letters",
+ ["pe"]="Characters",
+ ["ro"]="Caractere",
+ },
+ ["CloseDocument"]={
+ ["cs"]="ZavritDokument",
+ ["de"]="SchliesseDokument",
+ ["en"]="CloseDocument",
+ ["fr"]="FermeDocument",
+ ["it"]="ChiudiDocumento",
+ ["nl"]="SluitDocument",
+ ["pe"]="بستننوشتار",
+ ["ro"]="InchideDocument",
+ },
+ ["ExitViewer"]={
+ ["cs"]="UkoncitProhlizec",
+ ["de"]="BeendeViewer",
+ ["en"]="ExitViewer",
+ ["fr"]="SortVisualisateur",
+ ["it"]="EsciVisualizzatore",
+ ["nl"]="VerlaatViewer",
+ ["pe"]="خروجنمایشگر",
+ ["ro"]="IesireVizualizator",
+ },
+ ["FirstPage"]={
+ ["cs"]="PrvniStrana",
+ ["de"]="ErsteSeite",
+ ["en"]="FirstPage",
+ ["fr"]="PremierePage",
+ ["it"]="PrimaPagina",
+ ["nl"]="EerstePagina",
+ ["pe"]="صفحهاول",
+ ["ro"]="PrimaPagina",
+ },
+ ["FitHeight"]={
+ ["cs"]="FitHeight",
+ ["de"]="HoehePassend",
+ ["en"]="FitHeight",
+ ["fr"]="AjusteHauteur",
+ ["it"]="FitHeight",
+ ["nl"]="HoogtePassend",
+ ["pe"]="پرکردنارتفاع",
+ ["ro"]="AjustatInaltime",
+ },
+ ["FitWidth"]={
+ ["cs"]="FitWidth",
+ ["de"]="BreitePassend",
+ ["en"]="FitWidth",
+ ["fr"]="AjusteLargeur",
+ ["it"]="FitWidth",
+ ["nl"]="BreedtePassend",
+ ["pe"]="پرکردنعرض",
+ ["ro"]="AjustatLatime",
+ },
+ ["GotoPage"]={
+ ["cs"]="JdiNaStranku",
+ ["de"]="GotoPage",
+ ["en"]="GotoPage",
+ ["fr"]="VaalaPage",
+ ["it"]="VaiAPagina",
+ ["nl"]="GaNaarPagina",
+ ["pe"]="بروبهصفحه",
+ ["ro"]="LaPagina",
+ },
+ ["Greek"]={
+ ["cs"]="Recky",
+ ["de"]="Griechisch",
+ ["en"]="Greek",
+ ["fr"]="Grec",
+ ["it"]="Greco",
+ ["nl"]="Grieks",
+ ["pe"]="یونانی",
+ ["ro"]="Grec",
+ },
+ ["Help"]={
+ ["cs"]="Napoveda",
+ ["de"]="Hilfe",
+ ["en"]="Help",
+ ["fr"]="Aide",
+ ["it"]="Aiuto",
+ ["nl"]="Help",
+ ["pe"]="کمک",
+ ["ro"]="Ajutor",
+ },
+ ["HideField"]={
+ ["cs"]="SkryjPole",
+ ["de"]="VerbergeFeld",
+ ["en"]="HideField",
+ ["fr"]="CacheChamp",
+ ["it"]="NascondiCampo",
+ ["nl"]="VerbergVeld",
+ ["pe"]="پنهانمیدان",
+ ["ro"]="AscundeCamp",
+ },
+ ["HideLayer"]={
+ ["cs"]="HideLayer",
+ ["de"]="HideLayer",
+ ["en"]="HideLayer",
+ ["fr"]="CacheCalque",
+ ["it"]="HideLayer",
+ ["nl"]="VerbergLaag",
+ ["pe"]="پنهانلایه",
+ ["ro"]="HideLayer",
+ },
+ ["Key"]={
+ ["cs"]="Klavesa",
+ ["de"]="Schluessel",
+ ["en"]="Key",
+ ["fr"]="Cle",
+ ["it"]="Tasto",
+ ["nl"]="Sleutel",
+ ["pe"]="کلید",
+ ["ro"]="Cheie",
+ },
+ ["LastPage"]={
+ ["cs"]="PosledniStrana",
+ ["de"]="LetzteSeite",
+ ["en"]="LastPage",
+ ["fr"]="DernierePage",
+ ["it"]="UltimaPagina",
+ ["nl"]="LaatstePagina",
+ ["pe"]="صفحهآخر",
+ ["ro"]="UltimaPagina",
+ },
+ ["LoadForm"]={
+ ["cs"]="NacistFormular",
+ ["de"]="LadeFormular",
+ ["en"]="LoadForm",
+ ["fr"]="ChargeForm",
+ ["it"]="CaricaForm",
+ ["nl"]="LaadFormulier",
+ ["pe"]="بارگذاشتنفرم",
+ ["ro"]="IncarcaFormular",
+ },
+ ["MONTH"]={
+ ["cs"]="MESIC",
+ ["de"]="MONAT",
+ ["en"]="MONTH",
+ ["fr"]="MOIS",
+ ["it"]="MESE",
+ ["nl"]="MAAND",
+ ["pe"]="ماه",
+ ["ro"]="LUNA",
+ },
+ ["New"]={
+ ["cs"]="Novy",
+ ["de"]="Neu",
+ ["en"]="New",
+ ["fr"]="Nouveau",
+ ["it"]="Nuovo",
+ ["nl"]="Nieuw",
+ ["pe"]="جدید",
+ ["ro"]="Nou",
+ },
+ ["NextJump"]={
+ ["cs"]="NasledujiciSkok",
+ ["de"]="NaechsterSprung",
+ ["en"]="NextJump",
+ ["fr"]="SautSuivant",
+ ["it"]="SaltoSuccessivo",
+ ["nl"]="VolgendeSprong",
+ ["pe"]="پرشبعدی",
+ ["ro"]="SaltUrmator",
+ },
+ ["NextPage"]={
+ ["cs"]="DalsiStrana",
+ ["de"]="FolgendeSeite",
+ ["en"]="NextPage",
+ ["fr"]="PageSuivante",
+ ["it"]="PaginaSuccessiva",
+ ["nl"]="VolgendePagina",
+ ["pe"]="صفحهبعدی",
+ ["ro"]="PaginaUrmatoare",
+ },
+ ["Numbers"]={
+ ["cs"]="Cisla",
+ ["de"]="Ziffern",
+ ["en"]="Numbers",
+ ["fr"]="Numeros",
+ ["it"]="Numeri",
+ ["nl"]="Cijfers",
+ ["pe"]="شمارهها",
+ ["ro"]="Numere",
+ },
+ ["OpenNamedDocument"]={
+ ["cs"]="OpenNamedDocument",
+ ["de"]="OpenNamedDocument",
+ ["en"]="OpenNamedDocument",
+ ["fr"]="OuvreDocumentNomme",
+ ["it"]="OpenNamedDocument",
+ ["nl"]="OpenDocumentOpNaam",
+ ["pe"]="بازکردننوشتارذخیرهشده",
+ ["ro"]="OpenNamedDocument",
+ },
+ ["Paragraph"]={
+ ["cs"]="Odstavec",
+ ["de"]="Absatz",
+ ["en"]="Paragraph",
+ ["fr"]="Paragraphe",
+ ["it"]="Capoverso",
+ ["nl"]="Paragraaf",
+ ["pe"]="پاراگراف",
+ ["ro"]="Paragraf",
+ },
+ ["PauseMovie"]={
+ ["cs"]="PozastavitFilm",
+ ["de"]="PauseFilm",
+ ["en"]="PauseMovie",
+ ["fr"]="PauseFilm",
+ ["it"]="PausaFilm",
+ ["nl"]="PauzeerFilm",
+ ["pe"]="ایستفیلم",
+ ["ro"]="PauzaFilm",
+ },
+ ["PauseRendering"]={
+ ["cs"]="PauseRendering",
+ ["de"]="PauseRendering",
+ ["en"]="PauseRendering",
+ ["fr"]="PauseRendering",
+ ["it"]="PauseRendering",
+ ["nl"]="PauzeerRendering",
+ ["pe"]="توقفتعبیر",
+ ["ro"]="PauseRendering",
+ },
+ ["PauseSound"]={
+ ["cs"]="PozastavitZvuk",
+ ["de"]="PauseSound",
+ ["en"]="PauseSound",
+ ["fr"]="PauseSon",
+ ["it"]="PausaSuono",
+ ["nl"]="PauzeerGeluid",
+ ["pe"]="ایستصدا",
+ ["ro"]="PauzaSunet",
+ },
+ ["PreviousJump"]={
+ ["cs"]="PredchoziSkok",
+ ["de"]="VorigerSprung",
+ ["en"]="PreviousJump",
+ ["fr"]="SautPrecedent",
+ ["it"]="SaltoPrecedente",
+ ["nl"]="VorigeSprong",
+ ["pe"]="پرشقبلی",
+ ["ro"]="SaltPrecedent",
+ },
+ ["PreviousPage"]={
+ ["cs"]="PredchoziStrana",
+ ["de"]="VorigeSeite",
+ ["en"]="PreviousPage",
+ ["fr"]="PagePrecedente",
+ ["it"]="PaginaPrecedente",
+ ["nl"]="VorigePagina",
+ ["pe"]="صفحهقبلی",
+ ["ro"]="PaginaPrecedenta",
+ },
+ ["PrintDocument"]={
+ ["cs"]="VytisknoutDokument",
+ ["de"]="DruckeDokument",
+ ["en"]="PrintDocument",
+ ["fr"]="ImprimeDocument",
+ ["it"]="StampaDocumento",
+ ["nl"]="PrintDocument",
+ ["pe"]="چاپنوشتار",
+ ["ro"]="TiparesteDocument",
+ },
+ ["Query"]={
+ ["cs"]="Query",
+ ["de"]="Query",
+ ["en"]="Query",
+ ["fr"]="Query",
+ ["it"]="Richiesta",
+ ["nl"]="RaadpleegDocument",
+ ["pe"]="پرسش",
+ ["ro"]="Query",
+ },
+ ["QueryAgain"]={
+ ["cs"]="QueryAgain",
+ ["de"]="QueryAgain",
+ ["en"]="QueryAgain",
+ ["fr"]="QueryAgain",
+ ["it"]="RinnovaRichiesta",
+ ["nl"]="HerhaalRaadplegen",
+ ["pe"]="پرسشدوباره",
+ ["ro"]="QueryAgain",
+ },
+ ["ResetForm"]={
+ ["cs"]="ResetFormulare",
+ ["de"]="ZuruecksetzenFormular",
+ ["en"]="ResetForm",
+ ["fr"]="RazForm",
+ ["it"]="ReimpostaForm",
+ ["nl"]="ResetFormulier",
+ ["pe"]="دوبارهنشانیفرم",
+ ["ro"]="ResetareFormular",
+ },
+ ["ResumeMovie"]={
+ ["cs"]="PokracovatFilm",
+ ["de"]="FortsetzenFilm",
+ ["en"]="ResumeMovie",
+ ["fr"]="ReprendFilm",
+ ["it"]="RiprendiFilm",
+ ["nl"]="HervatFilm",
+ ["pe"]="ادامهفیلم",
+ ["ro"]="RepornesteFilm",
+ },
+ ["ResumeRendering"]={
+ ["cs"]="ResumeRendering",
+ ["de"]="ResumeRendering",
+ ["en"]="ResumeRendering",
+ ["fr"]="ResumeRendering",
+ ["it"]="ResumeRendering",
+ ["nl"]="HervatRendering",
+ ["pe"]="ادامهتعبیر",
+ ["ro"]="ResumeRendering",
+ },
+ ["ResumeSound"]={
+ ["cs"]="PokracovatZvuk",
+ ["de"]="ResumeSound",
+ ["en"]="ResumeSound",
+ ["fr"]="ReprendSon",
+ ["it"]="RiprendiSuono",
+ ["nl"]="HervatGeluid",
+ ["pe"]="ادامهصدا",
+ ["ro"]="RepornesteSunet",
+ },
+ ["Romannumerals"]={
+ ["cs"]="Rimskecislice",
+ ["de"]="Roemischezahlen",
+ ["en"]="Romannumerals",
+ ["fr"]="Chiffresromains",
+ ["it"]="Numeriromani",
+ ["nl"]="Romeins",
+ ["pe"]="اعدادبزرگلاتین",
+ ["ro"]="Numereromane",
+ },
+ ["SaveDocument"]={
+ ["cs"]="UlozitDokument",
+ ["de"]="SpeichereDokument",
+ ["en"]="SaveDocument",
+ ["fr"]="SauvegardeDocument",
+ ["it"]="SalvaDocumento",
+ ["nl"]="BewaarDocument",
+ ["pe"]="ذخیرهنوشتار",
+ ["ro"]="SalvareDocument",
+ },
+ ["SaveForm"]={
+ ["cs"]="UlozitFormular",
+ ["de"]="SpeicheFormular",
+ ["en"]="SaveForm",
+ ["fr"]="SauvegardeForm",
+ ["it"]="SalvaForm",
+ ["nl"]="BewaarFormulier",
+ ["pe"]="ذخیرهفرم",
+ ["ro"]="SalveazaFormular",
+ },
+ ["SaveNamedDocument"]={
+ ["cs"]="SaveNamedDocument",
+ ["de"]="SaveNamedDocument",
+ ["en"]="SaveNamedDocument",
+ ["fr"]="SauvegardeDocumentNomme",
+ ["it"]="SaveNamedDocument",
+ ["nl"]="BewaarDocumentOpNaam",
+ ["pe"]="ذخیرهنوشتاربانام",
+ ["ro"]="SaveNamedDocument",
+ },
+ ["SearchAgain"]={
+ ["cs"]="HledatZnovu",
+ ["de"]="WeiterSuchen",
+ ["en"]="SearchAgain",
+ ["fr"]="RechercheSuivant",
+ ["it"]="CercaAncora",
+ ["nl"]="HerhaalZoeken",
+ ["pe"]="جستجویدوباره",
+ ["ro"]="CautaDinNou",
+ },
+ ["SearchDocument"]={
+ ["cs"]="ProhledatDokument",
+ ["de"]="DokumentDurchsuchen",
+ ["en"]="SearchDocument",
+ ["fr"]="RechercheDocument",
+ ["it"]="CercaDocumento",
+ ["nl"]="DoorzoekDocument",
+ ["pe"]="جستجوینوشتار",
+ ["ro"]="CautaDocument",
+ },
+ ["ShowBookmarks"]={
+ ["cs"]="UkazZalozky",
+ ["de"]="ShowBookmarks",
+ ["en"]="ShowBookmarks",
+ ["fr"]="ShowBookmarks",
+ ["it"]="MostraSegnalibro",
+ ["nl"]="ShowBookmarks",
+ ["pe"]="نمایشچوبخط",
+ ["ro"]="ShowBookmarks",
+ },
+ ["ShowField"]={
+ ["cs"]="UkazPole",
+ ["de"]="ZeigeFeld",
+ ["en"]="ShowField",
+ ["fr"]="MontreChamp",
+ ["it"]="MostraCampo",
+ ["nl"]="ToonVeld",
+ ["pe"]="نمایشمیدان",
+ ["ro"]="AfiseazaCamp",
+ },
+ ["ShowThumbs"]={
+ ["cs"]="UkazNahledy",
+ ["de"]="ShowThumbs",
+ ["en"]="ShowThumbs",
+ ["fr"]="ShowThumbs",
+ ["it"]="MostraThumbs",
+ ["nl"]="ShowThumbs",
+ ["pe"]="نمایششصت",
+ ["ro"]="ShowThumbs",
+ },
+ ["StartMovie"]={
+ ["cs"]="SpustitFilm",
+ ["de"]="StartFilm",
+ ["en"]="StartMovie",
+ ["fr"]="DemarreFilm",
+ ["it"]="IniziaFilm",
+ ["nl"]="StartFilm",
+ ["pe"]="شروعفیلم",
+ ["ro"]="StartFilm",
+ },
+ ["StartRendering"]={
+ ["cs"]="StartRendering",
+ ["de"]="StartRendering",
+ ["en"]="StartRendering",
+ ["fr"]="StartRendering",
+ ["it"]="StartRendering",
+ ["nl"]="StartRendering",
+ ["pe"]="شروعتعبیر",
+ ["ro"]="StartRendering",
+ },
+ ["StartSound"]={
+ ["cs"]="StartZvuk",
+ ["de"]="StartSound",
+ ["en"]="StartSound",
+ ["fr"]="DemarreSon",
+ ["it"]="IniziaSuono",
+ ["nl"]="StartGeluid",
+ ["pe"]="شروعصدا",
+ ["ro"]="StartSunet",
+ },
+ ["StopMovie"]={
+ ["cs"]="ZastavitFilm",
+ ["de"]="StopFilm",
+ ["en"]="StopMovie",
+ ["fr"]="StoppeFilm",
+ ["it"]="FermaFilm",
+ ["nl"]="StopFilm",
+ ["pe"]="پایانفیلم",
+ ["ro"]="StopFilm",
+ },
+ ["StopRendering"]={
+ ["cs"]="StopRendering",
+ ["de"]="StopRendering",
+ ["en"]="StopRendering",
+ ["fr"]="StopRendering",
+ ["it"]="StopRendering",
+ ["nl"]="StopRendering",
+ ["pe"]="پایانتعبیر",
+ ["ro"]="StopRendering",
+ },
+ ["StopSound"]={
+ ["cs"]="StopZvuk",
+ ["de"]="StopSound",
+ ["en"]="StopSound",
+ ["fr"]="StoppeSon",
+ ["it"]="FermaSuono",
+ ["nl"]="StopGeluid",
+ ["pe"]="پایانصدا",
+ ["ro"]="StopSunet",
+ },
+ ["SubmitForm"]={
+ ["cs"]="PoslatFormular",
+ ["de"]="VersendeFormular",
+ ["en"]="SubmitForm",
+ ["fr"]="SoumettreForm",
+ ["it"]="MandaForm",
+ ["nl"]="VerzendFormulier",
+ ["pe"]="تسلیمفرم",
+ ["ro"]="TrimiteFormular",
+ },
+ ["ToggleLayer"]={
+ ["cs"]="ToggleLayer",
+ ["de"]="ToggleLayer",
+ ["en"]="ToggleLayer",
+ ["fr"]="ToggleLayer",
+ ["it"]="ToggleLayer",
+ ["nl"]="WisselLaag",
+ ["pe"]="تغییرلایه",
+ ["ro"]="ToggleLayer",
+ },
+ ["ToggleViewer"]={
+ ["cs"]="ZmenitProhlizec",
+ ["de"]="WechseleViewer",
+ ["en"]="ToggleViewer",
+ ["fr"]="ChangeVisualisateur",
+ ["it"]="ScambiaVisualizzatore",
+ ["nl"]="WisselViewer",
+ ["pe"]="تغییرنمایشگر",
+ ["ro"]="SchimbaVizualizator",
+ },
+ ["URL"]={
+ ["cs"]="URL",
+ ["de"]="URL",
+ ["en"]="URL",
+ ["fr"]="URL",
+ ["it"]="URL",
+ ["nl"]="URL",
+ ["pe"]="URL",
+ ["ro"]="URL",
+ },
+ ["VideLayer"]={
+ ["cs"]="VideLayer",
+ ["de"]="VideLayer",
+ ["en"]="VideLayer",
+ ["fr"]="VideLayer",
+ ["it"]="VideLayer",
+ ["nl"]="ToonLaag",
+ ["pe"]="VideLayer",
+ ["ro"]="VideLayer",
+ },
+ ["ViewerHelp"]={
+ ["cs"]="NapovedaProhlizece",
+ ["de"]="ViewerHilfe",
+ ["en"]="ViewerHelp",
+ ["fr"]="AideVisualisateur",
+ ["it"]="AiutoVisualizzatore",
+ ["nl"]="ViewerHelp",
+ ["pe"]="کمکنمایشگر",
+ ["ro"]="AjutorVizualizator",
+ },
+ ["WEEKDAY"]={
+ ["cs"]="VSEDNIDEN",
+ ["de"]="WOCHENTAG",
+ ["en"]="WEEKDAY",
+ ["fr"]="JOURSEMAINE",
+ ["it"]="GIORNOSETTIMANA",
+ ["nl"]="WEEKDAG",
+ ["pe"]="روزهفته",
+ ["ro"]="ZISAPTAMANA",
+ },
+ ["WORD"]={
+ ["cs"]="SLOVO",
+ ["de"]="WORT",
+ ["en"]="WORD",
+ ["fr"]="MOT",
+ ["it"]="PAROLA",
+ ["nl"]="WOORD",
+ ["pe"]="کلمه",
+ ["ro"]="CUVANT",
+ },
+ ["abbreviation"]={
+ ["cs"]="zkratka",
+ ["de"]="abkuerzung",
+ ["en"]="abbreviation",
+ ["fr"]="abreviation",
+ ["it"]="abbreviazione",
+ ["nl"]="afkorting",
+ ["pe"]="اختصار",
+ ["ro"]="abreviere",
+ },
+ ["abbreviations"]={
+ ["cs"]="zkratky",
+ ["de"]="abkuerzungen",
+ ["en"]="abbreviations",
+ ["fr"]="abreviations",
+ ["it"]="abbreviazioni",
+ ["nl"]="afkortingen",
+ ["pe"]="اختصارات",
+ ["ro"]="abrevieri",
+ },
+ ["absolute"]={
+ ["cs"]="absolutni",
+ ["de"]="absolut",
+ ["en"]="absolute",
+ ["fr"]="absolute",
+ ["it"]="assoluto",
+ ["nl"]="absoluut",
+ ["pe"]="قطعی",
+ ["ro"]="absolut",
+ },
+ ["action"]={
+ ["cs"]="akce",
+ ["de"]="aktion",
+ ["en"]="action",
+ ["fr"]="action",
+ ["it"]="azione",
+ ["nl"]="actie",
+ ["pe"]="کنش",
+ ["ro"]="actiune",
+ },
+ ["after"]={
+ ["cs"]="po",
+ ["de"]="nach",
+ ["en"]="after",
+ ["fr"]="apres",
+ ["it"]="dopo",
+ ["nl"]="na",
+ ["pe"]="بعداز",
+ ["ro"]="dupa",
+ },
+ ["all"]={
+ ["cs"]="vse",
+ ["de"]="alles",
+ ["en"]="all",
+ ["fr"]="tout",
+ ["it"]="tutti",
+ ["nl"]="alles",
+ ["pe"]="همه",
+ ["ro"]="tot",
+ },
+ ["always"]={
+ ["cs"]="vzdy",
+ ["de"]="immer",
+ ["en"]="always",
+ ["fr"]="toujours",
+ ["it"]="sempre",
+ ["nl"]="altijd",
+ ["pe"]="همواره",
+ ["ro"]="totdeauna",
+ },
+ ["answerarea"]={
+ ["cs"]="answerarea",
+ ["de"]="answerarea",
+ ["en"]="answerarea",
+ ["fr"]="answerarea",
+ ["it"]="answerarea",
+ ["nl"]="antwoordgebied",
+ ["pe"]="answerarea",
+ ["ro"]="answerarea",
+ },
+ ["appendices"]={
+ ["cs"]="dodatky",
+ ["de"]="anhaenge",
+ ["en"]="appendices",
+ ["fr"]="annexes",
+ ["it"]="appendici",
+ ["nl"]="bijlagen",
+ ["pe"]="پیوستها",
+ ["ro"]="apendixuri",
+ },
+ ["appendix"]={
+ ["cs"]="dodatek",
+ ["de"]="anhang",
+ ["en"]="appendix",
+ ["fr"]="annexe",
+ ["it"]="appendice",
+ ["nl"]="bijlage",
+ ["pe"]="پیوست",
+ ["ro"]="apendix",
+ },
+ ["april"]={
+ ["cs"]="duben",
+ ["de"]="April",
+ ["en"]="April",
+ ["fr"]="avril",
+ ["it"]="aprile",
+ ["nl"]="april",
+ ["pe"]="آوریل",
+ ["ro"]="aprilie",
+ },
+ ["atmargin"]={
+ ["cs"]="naokraji",
+ ["de"]="amrand",
+ ["en"]="atmargin",
+ ["fr"]="alamarge",
+ ["it"]="almargine",
+ ["nl"]="opmarge",
+ ["pe"]="درحاشیه",
+ ["ro"]="lamargine",
+ },
+ ["atpage"]={
+ ["cs"]="nastrance",
+ ["de"]="aufseite",
+ ["en"]="atpage",
+ ["fr"]="alapage",
+ ["it"]="apagina",
+ ["nl"]="oppagina",
+ ["pe"]="درصفحه",
+ ["ro"]="lapagina",
+ },
+ ["august"]={
+ ["cs"]="srpen",
+ ["de"]="August",
+ ["en"]="August",
+ ["fr"]="aout",
+ ["it"]="agosto",
+ ["nl"]="augustus",
+ ["pe"]="آگوست",
+ ["ro"]="august",
+ },
+ ["auto"]={
+ ["cs"]="auto",
+ ["de"]="auto",
+ ["en"]="auto",
+ ["fr"]="auto",
+ ["it"]="auto",
+ ["nl"]="auto",
+ ["pe"]="خودکار",
+ ["ro"]="auto",
+ },
+ ["autointro"]={
+ ["cs"]="autouvod",
+ ["de"]="autointro",
+ ["en"]="autointro",
+ ["fr"]="autointro",
+ ["it"]="autointro",
+ ["nl"]="autointro",
+ ["pe"]="پیشگفتارخودکار",
+ ["ro"]="autointro",
+ },
+ ["back"]={
+ ["cs"]="zpet",
+ ["de"]="zurueck",
+ ["en"]="back",
+ ["fr"]="retour",
+ ["it"]="dietro",
+ ["nl"]="terug",
+ ["pe"]="پشت",
+ ["ro"]="inapot",
+ },
+ ["background"]={
+ ["cs"]="pozadi",
+ ["de"]="hintergrund",
+ ["en"]="background",
+ ["fr"]="arriereplan",
+ ["it"]="sfondo",
+ ["nl"]="achtergrond",
+ ["pe"]="پسزمینه",
+ ["ro"]="fundal",
+ },
+ ["backmatter"]={
+ ["cs"]="epilogy",
+ ["de"]="epiloge",
+ ["en"]="backmatter",
+ ["fr"]="epilogue",
+ ["it"]="postambolo",
+ ["nl"]="uitleidingen",
+ ["pe"]="پسمطلب",
+ ["ro"]="epilogul",
+ },
+ ["backpart"]={
+ ["cs"]="epilog",
+ ["de"]="epilog",
+ ["en"]="backpart",
+ ["fr"]="postface",
+ ["it"]="postfazione",
+ ["nl"]="uitleiding",
+ ["pe"]="پسقسمت",
+ ["ro"]="epilog",
+ },
+ ["backspace"]={
+ ["cs"]="zpetnamezera",
+ ["de"]="rumpfspatium",
+ ["en"]="backspace",
+ ["fr"]="retourarriere",
+ ["it"]="backspace",
+ ["nl"]="rugwit",
+ ["pe"]="فضایپشت",
+ ["ro"]="spatiuspate",
+ },
+ ["backward"]={
+ ["cs"]="zpet",
+ ["de"]="rueckwaerts",
+ ["en"]="backward",
+ ["fr"]="retourarriere",
+ ["it"]="indietro",
+ ["nl"]="achteruit",
+ ["pe"]="عقبگرد",
+ ["ro"]="inapoi",
+ },
+ ["before"]={
+ ["cs"]="pred",
+ ["de"]="vor",
+ ["en"]="before",
+ ["fr"]="avant",
+ ["it"]="prima",
+ ["nl"]="voor",
+ ["pe"]="قبلاز",
+ ["ro"]="inainte",
+ },
+ ["big"]={
+ ["cs"]="velke",
+ ["de"]="gross",
+ ["en"]="big",
+ ["fr"]="grand",
+ ["it"]="grande",
+ ["nl"]="groot",
+ ["pe"]="بزرگ",
+ ["ro"]="mare",
+ },
+ ["bigbodyfont"]={
+ ["cs"]="bigbodyfont",
+ ["de"]="bigbodyfont",
+ ["en"]="bigbodyfont",
+ ["fr"]="grandepolicecorp",
+ ["it"]="grossofontdeltesto",
+ ["nl"]="grootkorps",
+ ["pe"]="قلمبدنهبزرگ",
+ ["ro"]="bigbodyfont",
+ },
+ ["bigpreference"]={
+ ["cs"]="vysokapriorita",
+ ["de"]="grosszuegig",
+ ["en"]="bigpreference",
+ ["fr"]="grandepreference",
+ ["it"]="grandepreferenza",
+ ["nl"]="grotevoorkeur",
+ ["pe"]="اولویتبزرگ",
+ ["ro"]="preferintamare",
+ },
+ ["blank"]={
+ ["cs"]="prazdny",
+ ["de"]="blanko",
+ ["en"]="blank",
+ ["fr"]="vide",
+ ["it"]="rigovuoto",
+ ["nl"]="blanko",
+ ["pe"]="خالی",
+ ["ro"]="blank",
+ },
+ ["blockquote"]={
+ ["cs"]="blockquote",
+ ["de"]="blockquote",
+ ["en"]="blockquote",
+ ["fr"]="blockquote",
+ ["it"]="blockquote",
+ ["nl"]="blokcitaat",
+ ["pe"]="نقلبلوک",
+ ["ro"]="blockquote",
+ },
+ ["bodymatter"]={
+ ["cs"]="hlavnicasti",
+ ["de"]="haupttexte",
+ ["en"]="bodymatter",
+ ["fr"]="texteprincipal",
+ ["it"]="testiprincipali",
+ ["nl"]="hoofdteksten",
+ ["pe"]="مطلببدنه",
+ ["ro"]="principalul",
+ },
+ ["bodypart"]={
+ ["cs"]="hlavnicast",
+ ["de"]="haupttext",
+ ["en"]="bodypart",
+ ["fr"]="corpsdetexte",
+ ["it"]="testoprincipale",
+ ["nl"]="hoofdtekst",
+ ["pe"]="قسمتبدنه",
+ ["ro"]="principal",
+ },
+ ["bold"]={
+ ["cs"]="tucne",
+ ["de"]="fett",
+ ["en"]="bold",
+ ["fr"]="gras",
+ ["it"]="grassetto",
+ ["nl"]="vet",
+ ["pe"]="مشکی",
+ ["ro"]="aldin",
+ },
+ ["bolditalic"]={
+ ["cs"]="tucnekurzivni",
+ ["de"]="fettitalic",
+ ["en"]="bolditalic",
+ ["fr"]="italiquegras",
+ ["it"]="grassettocorsivo",
+ ["nl"]="vetitalic",
+ ["pe"]="ایتالیکمشکی",
+ ["ro"]="aldinitalic",
+ },
+ ["boldslanted"]={
+ ["cs"]="tucnesklonene",
+ ["de"]="fettgeneigt",
+ ["en"]="boldslanted",
+ ["fr"]="inclinegras",
+ ["it"]="grassettoinclinato",
+ ["nl"]="vetschuin",
+ ["pe"]="خوابیدهمشکی",
+ ["ro"]="aldininclinat",
+ },
+ ["bookmark"]={
+ ["cs"]="zalozka",
+ ["de"]="bookmark",
+ ["en"]="bookmark",
+ ["fr"]="marquepage",
+ ["it"]="segnalibro",
+ ["nl"]="bookmark",
+ ["pe"]="چوبخط",
+ ["ro"]="semncarte",
+ },
+ ["both"]={
+ ["cs"]="obe",
+ ["de"]="beide",
+ ["en"]="both",
+ ["fr"]="lesdeux",
+ ["it"]="entrambi",
+ ["nl"]="beide",
+ ["pe"]="هردو",
+ ["ro"]="ambele",
+ },
+ ["bottom"]={
+ ["cs"]="spodek",
+ ["de"]="unten",
+ ["en"]="bottom",
+ ["fr"]="inf",
+ ["it"]="fondo",
+ ["nl"]="onder",
+ ["pe"]="پایین",
+ ["ro"]="subsol",
+ },
+ ["brief"]={
+ ["cs"]="brief",
+ ["de"]="brief",
+ ["en"]="brief",
+ ["fr"]="brief",
+ ["it"]="brief",
+ ["nl"]="brief",
+ ["pe"]="مختصر",
+ ["ro"]="brief",
+ },
+ ["broad"]={
+ ["cs"]="siroky",
+ ["de"]="breit",
+ ["en"]="broad",
+ ["fr"]="large",
+ ["it"]="ampio",
+ ["nl"]="ruim",
+ ["pe"]="گسترده",
+ ["ro"]="broad",
+ },
+ ["buffer"]={
+ ["cs"]="buffer",
+ ["de"]="puffer",
+ ["en"]="buffer",
+ ["fr"]="buffer",
+ ["it"]="buffer",
+ ["nl"]="buffer",
+ ["pe"]="بافر",
+ ["ro"]="buffer",
+ },
+ ["by"]={
+ ["cs"]="skrz",
+ ["de"]="pro",
+ ["en"]="by",
+ ["fr"]="par",
+ ["it"]="da",
+ ["nl"]="per",
+ ["pe"]="بوسیله",
+ ["ro"]="de",
+ },
+ ["calligraphic"]={
+ ["cs"]="kaligraficke",
+ ["de"]="kalligraphie",
+ ["en"]="calligraphic",
+ ["fr"]="calligraphique",
+ ["it"]="calligrafico",
+ ["nl"]="calligrafie",
+ ["pe"]="خوشنویسی",
+ ["ro"]="caligrafic",
+ },
+ ["cap"]={
+ ["cs"]="kap",
+ ["de"]="kap",
+ ["en"]="cap",
+ ["fr"]="cap",
+ ["it"]="cap",
+ ["nl"]="kap",
+ ["pe"]="cap",
+ ["ro"]="cap",
+ },
+ ["capital"]={
+ ["cs"]="kapitalky",
+ ["de"]="versalien",
+ ["en"]="capital",
+ ["fr"]="capitale",
+ ["it"]="maiuscolo",
+ ["nl"]="kapitaal",
+ ["pe"]="capital",
+ ["ro"]="majuscula",
+ },
+ ["center"]={
+ ["cs"]="center",
+ ["de"]="center",
+ ["en"]="center",
+ ["fr"]="center",
+ ["it"]="center",
+ ["nl"]="centreer",
+ ["pe"]="مرکز",
+ ["ro"]="center",
+ },
+ ["chapter"]={
+ ["cs"]="kapitola",
+ ["de"]="kapitel",
+ ["en"]="chapter",
+ ["fr"]="chapitre",
+ ["it"]="capitolo",
+ ["nl"]="hoofdstuk",
+ ["pe"]="فصل",
+ ["ro"]="capitol",
+ },
+ ["character"]={
+ ["cs"]="pismeno",
+ ["de"]="buchstabe",
+ ["en"]="character",
+ ["fr"]="caractere",
+ ["it"]="lettera",
+ ["nl"]="letter",
+ ["pe"]="حرف",
+ ["ro"]="caracter",
+ },
+ ["characters"]={
+ ["cs"]="pismena",
+ ["de"]="buchstaben",
+ ["en"]="characters",
+ ["fr"]="caracteres",
+ ["it"]="lettere",
+ ["nl"]="letters",
+ ["pe"]="حرفها",
+ ["ro"]="caractere",
+ },
+ ["color"]={
+ ["cs"]="barevne",
+ ["de"]="farbe",
+ ["en"]="color",
+ ["fr"]="couleur",
+ ["it"]="colore",
+ ["nl"]="kleur",
+ ["pe"]="رنگ",
+ ["ro"]="culoare",
+ },
+ ["column"]={
+ ["cs"]="column",
+ ["de"]="column",
+ ["en"]="column",
+ ["fr"]="colonne",
+ ["it"]="colonna",
+ ["nl"]="kolom",
+ ["pe"]="ستون",
+ ["ro"]="coloana",
+ },
+ ["columns"]={
+ ["cs"]="sloupce",
+ ["de"]="spalten",
+ ["en"]="columns",
+ ["fr"]="colonnes",
+ ["it"]="colonne",
+ ["nl"]="kolommen",
+ ["pe"]="ستونها",
+ ["ro"]="coloane",
+ },
+ ["command"]={
+ ["cs"]="prikaz",
+ ["de"]="befehl",
+ ["en"]="command",
+ ["fr"]="commande",
+ ["it"]="comando",
+ ["nl"]="commando",
+ ["pe"]="فرمان",
+ ["ro"]="comanda",
+ },
+ ["commands"]={
+ ["cs"]="prikazy",
+ ["de"]="befehle",
+ ["en"]="commands",
+ ["fr"]="commandes",
+ ["it"]="comandi",
+ ["nl"]="commandos",
+ ["pe"]="فرمانها",
+ ["ro"]="comenzi",
+ },
+ ["comment"]={
+ ["cs"]="komentar",
+ ["de"]="kommentar",
+ ["en"]="comment",
+ ["fr"]="commentaire",
+ ["it"]="commento",
+ ["nl"]="commentaar",
+ ["pe"]="توضیح",
+ ["ro"]="comentariu",
+ },
+ ["component"]={
+ ["cs"]="komponenta",
+ ["de"]="komponente",
+ ["en"]="component",
+ ["fr"]="composant",
+ ["it"]="componente",
+ ["nl"]="onderdeel",
+ ["pe"]="مولفه",
+ ["ro"]="componenta",
+ },
+ ["concept"]={
+ ["cs"]="koncept",
+ ["de"]="konzept",
+ ["en"]="concept",
+ ["fr"]="concept",
+ ["it"]="concetto",
+ ["nl"]="concept",
+ ["pe"]="مفهوم",
+ ["ro"]="concept",
+ },
+ ["content"]={
+ ["cs"]="obsah",
+ ["de"]="inhalt",
+ ["en"]="content",
+ ["fr"]="contenu",
+ ["it"]="indice",
+ ["nl"]="inhoud",
+ ["pe"]="محتوا",
+ ["ro"]="cuprins",
+ },
+ ["contents"]={
+ ["cs"]="obsah",
+ ["de"]="inhalte",
+ ["en"]="contents",
+ ["fr"]="contenus",
+ ["it"]="indici",
+ ["nl"]="inhouden",
+ ["pe"]="محتویات",
+ ["ro"]="cuprinsuri",
+ },
+ ["continue"]={
+ ["cs"]="pokracovat",
+ ["de"]="fortsetzten",
+ ["en"]="continue",
+ ["fr"]="continue",
+ ["it"]="continua",
+ ["nl"]="verder",
+ ["pe"]="ادامه",
+ ["ro"]="continuu",
+ },
+ ["controls"]={
+ ["cs"]="controls",
+ ["de"]="controls",
+ ["en"]="controls",
+ ["fr"]="controles",
+ ["it"]="controlli",
+ ["nl"]="sturing",
+ ["pe"]="کنترلها",
+ ["ro"]="controale",
+ },
+ ["conversion"]={
+ ["cs"]="konverze",
+ ["de"]="konversion",
+ ["en"]="conversion",
+ ["fr"]="conversion",
+ ["it"]="coversione",
+ ["nl"]="conversie",
+ ["pe"]="تبدیل",
+ ["ro"]="conversie",
+ },
+ ["current"]={
+ ["cs"]="aktualni",
+ ["de"]="aktuell",
+ ["en"]="current",
+ ["fr"]="courant",
+ ["it"]="corrente",
+ ["nl"]="huidige",
+ ["pe"]="جاری",
+ ["ro"]="curent",
+ },
+ ["cutspace"]={
+ ["cs"]="cutspace",
+ ["de"]="cutspace",
+ ["en"]="cutspace",
+ ["fr"]="cutspace",
+ ["it"]="cutspace",
+ ["nl"]="snijwit",
+ ["pe"]="فضایبرش",
+ ["ro"]="cutspace",
+ },
+ ["date"]={
+ ["cs"]="datum",
+ ["de"]="datum",
+ ["en"]="date",
+ ["fr"]="date",
+ ["it"]="data",
+ ["nl"]="datum",
+ ["pe"]="تاریخ",
+ ["ro"]="data",
+ },
+ ["day"]={
+ ["cs"]="den",
+ ["de"]="tag",
+ ["en"]="day",
+ ["fr"]="jour",
+ ["it"]="giorno",
+ ["nl"]="dag",
+ ["pe"]="روز",
+ ["ro"]="zi",
+ },
+ ["december"]={
+ ["cs"]="prosinec",
+ ["de"]="Dezember",
+ ["en"]="December",
+ ["fr"]="decembre",
+ ["it"]="dicembre",
+ ["nl"]="december",
+ ["pe"]="دسامبر",
+ ["ro"]="decembrie",
+ },
+ ["default"]={
+ ["cs"]="implicitni",
+ ["de"]="default",
+ ["en"]="default",
+ ["fr"]="defaut",
+ ["it"]="implicito",
+ ["nl"]="default",
+ ["pe"]="پیشفرض",
+ ["ro"]="implicit",
+ },
+ ["depth"]={
+ ["cs"]="podlehloubky",
+ ["de"]="tiefe",
+ ["en"]="depth",
+ ["fr"]="profondeur",
+ ["it"]="profondita",
+ ["nl"]="diepte",
+ ["pe"]="عمق",
+ ["ro"]="adancime",
+ },
+ ["description"]={
+ ["cs"]="popis",
+ ["de"]="beschreibung",
+ ["en"]="description",
+ ["fr"]="description",
+ ["it"]="descrizione",
+ ["nl"]="doordefinitie",
+ ["pe"]="شرح",
+ ["ro"]="descriere",
+ },
+ ["disable"]={
+ ["cs"]="zablokovat",
+ ["de"]="sperren",
+ ["en"]="disable",
+ ["fr"]="desactiver",
+ ["it"]="disattiva",
+ ["nl"]="blokkeer",
+ ["pe"]="ناتوان",
+ ["ro"]="dezactivat",
+ },
+ ["display"]={
+ ["cs"]="obrazovka",
+ ["de"]="bildschirm",
+ ["en"]="display",
+ ["fr"]="affichage",
+ ["it"]="schermo",
+ ["nl"]="scherm",
+ ["pe"]="نمایش",
+ ["ro"]="display",
+ },
+ ["dot"]={
+ ["cs"]="tecka",
+ ["de"]="punkt",
+ ["en"]="dot",
+ ["fr"]="point",
+ ["it"]="punto",
+ ["nl"]="punt",
+ ["pe"]="نقطه",
+ ["ro"]="punct",
+ },
+ ["doublesided"]={
+ ["cs"]="dvoustranny",
+ ["de"]="doppelseitig",
+ ["en"]="doublesided",
+ ["fr"]="rectoverso",
+ ["it"]="doppiafaccia",
+ ["nl"]="dubbelzijdig",
+ ["pe"]="دورو",
+ ["ro"]="douafete",
+ },
+ ["each"]={
+ ["cs"]="kazdy",
+ ["de"]="jede",
+ ["en"]="each",
+ ["fr"]="chaque",
+ ["it"]="ogni",
+ ["nl"]="elk",
+ ["pe"]="هر",
+ ["ro"]="fiecare",
+ },
+ ["edge"]={
+ ["cs"]="hrana",
+ ["de"]="kante",
+ ["en"]="edge",
+ ["fr"]="bord",
+ ["it"]="bordo",
+ ["nl"]="rand",
+ ["pe"]="لبه",
+ ["ro"]="bordura",
+ },
+ ["empty"]={
+ ["cs"]="prazdne",
+ ["de"]="leer",
+ ["en"]="empty",
+ ["fr"]="vide",
+ ["it"]="vuoto",
+ ["nl"]="leeg",
+ ["pe"]="تهی",
+ ["ro"]="gol",
+ },
+ ["endnote"]={
+ ["cs"]="endnote",
+ ["de"]="endnote",
+ ["en"]="endnote",
+ ["fr"]="notefin",
+ ["it"]="endnote",
+ ["nl"]="eindnoot",
+ ["pe"]="تهنوشت",
+ ["ro"]="endnote",
+ },
+ ["enumeration"]={
+ ["cs"]="vycet",
+ ["de"]="nummerierung",
+ ["en"]="enumeration",
+ ["fr"]="enumeration",
+ ["it"]="enumerazione",
+ ["nl"]="doornummering",
+ ["pe"]="شمارهبندی",
+ ["ro"]="enumerare",
+ },
+ ["environment"]={
+ ["cs"]="prostredi",
+ ["de"]="umgebung",
+ ["en"]="environment",
+ ["fr"]="environement",
+ ["it"]="ambiente",
+ ["nl"]="omgeving",
+ ["pe"]="محیط",
+ ["ro"]="mediu",
+ },
+ ["even"]={
+ ["cs"]="sude",
+ ["de"]="gerade",
+ ["en"]="even",
+ ["fr"]="paire",
+ ["it"]="pari",
+ ["nl"]="even",
+ ["pe"]="زوج",
+ ["ro"]="par",
+ },
+ ["external"]={
+ ["cs"]="externi",
+ ["de"]="extern",
+ ["en"]="external",
+ ["fr"]="external",
+ ["it"]="esterno",
+ ["nl"]="extern",
+ ["pe"]="خارجی",
+ ["ro"]="extern",
+ },
+ ["fact"]={
+ ["cs"]="fakt",
+ ["de"]="gegeben",
+ ["en"]="fact",
+ ["fr"]="fait",
+ ["it"]="fatto",
+ ["nl"]="gegeven",
+ ["pe"]="fact",
+ ["ro"]="fapt",
+ },
+ ["february"]={
+ ["cs"]="unor",
+ ["de"]="Februar",
+ ["en"]="February",
+ ["fr"]="fevrier",
+ ["it"]="febbraio",
+ ["nl"]="februari",
+ ["pe"]="فوریه",
+ ["ro"]="februarie",
+ },
+ ["figure"]={
+ ["cs"]="obrazek",
+ ["de"]="abbildung",
+ ["en"]="figure",
+ ["fr"]="figure",
+ ["it"]="figura",
+ ["nl"]="figuur",
+ ["pe"]="شکل",
+ ["ro"]="figura",
+ },
+ ["figures"]={
+ ["cs"]="obrazky",
+ ["de"]="abbildungen",
+ ["en"]="figures",
+ ["fr"]="figures",
+ ["it"]="figure",
+ ["nl"]="figuren",
+ ["pe"]="شکلها",
+ ["ro"]="figure",
+ },
+ ["file"]={
+ ["cs"]="soubor",
+ ["de"]="datei",
+ ["en"]="file",
+ ["fr"]="fichier",
+ ["it"]="file",
+ ["nl"]="file",
+ ["pe"]="پرونده",
+ ["ro"]="fisier",
+ },
+ ["final"]={
+ ["cs"]="finalni",
+ ["de"]="endfassung",
+ ["en"]="final",
+ ["fr"]="final",
+ ["it"]="finale",
+ ["nl"]="definitief",
+ ["pe"]="نهایی",
+ ["ro"]="final",
+ },
+ ["first"]={
+ ["cs"]="prvni",
+ ["de"]="erste",
+ ["en"]="first",
+ ["fr"]="premier",
+ ["it"]="primo",
+ ["nl"]="eerste",
+ ["pe"]="اولی",
+ ["ro"]="primul",
+ },
+ ["firstcolumn"]={
+ ["cs"]="firstcolumn",
+ ["de"]="firstcolumn",
+ ["en"]="firstcolumn",
+ ["fr"]="premierecolonne",
+ ["it"]="firstcolumn",
+ ["nl"]="eerstekolom",
+ ["pe"]="ستوناول",
+ ["ro"]="firstcolumn",
+ },
+ ["firstpage"]={
+ ["cs"]="prvnistranka",
+ ["de"]="ersteseite",
+ ["en"]="firstpage",
+ ["fr"]="premierepage",
+ ["it"]="primapagina",
+ ["nl"]="eerstepagina",
+ ["pe"]="صفحهاول",
+ ["ro"]="primapagina",
+ },
+ ["firstsubpage"]={
+ ["cs"]="prvnipodstranka",
+ ["de"]="ersteunterseite",
+ ["en"]="firstsubpage",
+ ["fr"]="premieresouspage",
+ ["it"]="primasottopagina",
+ ["nl"]="eerstesubpagina",
+ ["pe"]="زیرصفحهاول",
+ ["ro"]="primasubpagina",
+ },
+ ["fit"]={
+ ["cs"]="prizpusobive",
+ ["de"]="passend",
+ ["en"]="fit",
+ ["fr"]="adapte",
+ ["it"]="adatta",
+ ["nl"]="passend",
+ ["pe"]="پرکردن",
+ ["ro"]="ajustat",
+ },
+ ["five"]={
+ ["cs"]="pet",
+ ["de"]="fuenf",
+ ["en"]="five",
+ ["fr"]="cinq",
+ ["it"]="cinque",
+ ["nl"]="vijf",
+ ["pe"]="پنج",
+ ["ro"]="cinci",
+ },
+ ["fix"]={
+ ["cs"]="fixuj",
+ ["de"]="stellewiederher",
+ ["en"]="fix",
+ ["fr"]="fixe",
+ ["it"]="fisso",
+ ["nl"]="herstel",
+ ["pe"]="ثابتکن",
+ ["ro"]="fix",
+ },
+ ["fixed"]={
+ ["cs"]="fixne",
+ ["de"]="fest",
+ ["en"]="fixed",
+ ["fr"]="fixe",
+ ["it"]="fisso",
+ ["nl"]="vast",
+ ["pe"]="ثابت",
+ ["ro"]="fixat",
+ },
+ ["flexible"]={
+ ["cs"]="prizpusobive",
+ ["de"]="flexibel",
+ ["en"]="flexible",
+ ["fr"]="flexible",
+ ["it"]="flessibile",
+ ["nl"]="flexibel",
+ ["pe"]="انعطافپذیر",
+ ["ro"]="flexibil",
+ },
+ ["float"]={
+ ["cs"]="plvouciobjekt",
+ ["de"]="gleitobjekt",
+ ["en"]="float",
+ ["fr"]="flottant",
+ ["it"]="oggettomobile",
+ ["nl"]="blok",
+ ["pe"]="شناور",
+ ["ro"]="obiectmobil",
+ },
+ ["flushinner"]={
+ ["cs"]="flushinner",
+ ["de"]="flushinner",
+ ["en"]="flushinner",
+ ["fr"]="flushinner",
+ ["it"]="flushinner",
+ ["nl"]="lijnbinnen",
+ ["pe"]="پمپداخلی",
+ ["ro"]="flushinner",
+ },
+ ["flushleft"]={
+ ["cs"]="flushleft",
+ ["de"]="flushleft",
+ ["en"]="flushleft",
+ ["fr"]="flushleft",
+ ["it"]="flushleft",
+ ["nl"]="lijnlinks",
+ ["pe"]="پمپچپ",
+ ["ro"]="flushleft",
+ },
+ ["flushouter"]={
+ ["cs"]="flushouter",
+ ["de"]="flushouter",
+ ["en"]="flushouter",
+ ["fr"]="flushouter",
+ ["it"]="flushouter",
+ ["nl"]="lijnbuiten",
+ ["pe"]="پمپخارجی",
+ ["ro"]="flushouter",
+ },
+ ["flushright"]={
+ ["cs"]="flushright",
+ ["de"]="flushright",
+ ["en"]="flushright",
+ ["fr"]="flushright",
+ ["it"]="flushright",
+ ["nl"]="lijnrechts",
+ ["pe"]="پمپراست",
+ ["ro"]="flushright",
+ },
+ ["footer"]={
+ ["cs"]="upati",
+ ["de"]="fusszeile",
+ ["en"]="footer",
+ ["fr"]="pdp",
+ ["it"]="piedipagina",
+ ["nl"]="voet",
+ ["pe"]="تهبرگ",
+ ["ro"]="subsol",
+ },
+ ["footnote"]={
+ ["cs"]="poznamkapodcarou",
+ ["de"]="fussnote",
+ ["en"]="footnote",
+ ["fr"]="notepdp",
+ ["it"]="notapdp",
+ ["nl"]="voetnoot",
+ ["pe"]="پانوشت",
+ ["ro"]="notasubsol",
+ },
+ ["force"]={
+ ["cs"]="sila",
+ ["de"]="zwinge",
+ ["en"]="force",
+ ["fr"]="force",
+ ["it"]="forza",
+ ["nl"]="forceer",
+ ["pe"]="اجبار",
+ ["ro"]="fortat",
+ },
+ ["foreground"]={
+ ["cs"]="popredi",
+ ["de"]="vordergrund",
+ ["en"]="foreground",
+ ["fr"]="premierplan",
+ ["it"]="foreground",
+ ["nl"]="voorgrond",
+ ["pe"]="پیشزمینه",
+ ["ro"]="primplan",
+ },
+ ["formeel"]={
+ ["cs"]="formeel",
+ ["de"]="formeel",
+ ["en"]="formeel",
+ ["fr"]="formeel",
+ ["it"]="formeel",
+ ["nl"]="formeel",
+ ["pe"]="formeel",
+ ["ro"]="formeel",
+ },
+ ["formula"]={
+ ["cs"]="rovnice",
+ ["de"]="formel",
+ ["en"]="formula",
+ ["fr"]="formule",
+ ["it"]="formula",
+ ["nl"]="formule",
+ ["pe"]="فرمول",
+ ["ro"]="formula",
+ },
+ ["formulae"]={
+ ["cs"]="rovnice",
+ ["de"]="formeln",
+ ["en"]="formulae",
+ ["fr"]="formules",
+ ["it"]="formule",
+ ["nl"]="formules",
+ ["pe"]="فرمولها",
+ ["ro"]="formule",
+ },
+ ["forward"]={
+ ["cs"]="vpred",
+ ["de"]="vorwaerts",
+ ["en"]="forward",
+ ["fr"]="avance",
+ ["it"]="avanti",
+ ["nl"]="vooruit",
+ ["pe"]="بهجلو",
+ ["ro"]="avans",
+ },
+ ["four"]={
+ ["cs"]="ctyri",
+ ["de"]="vier",
+ ["en"]="four",
+ ["fr"]="quatre",
+ ["it"]="quattro",
+ ["nl"]="vier",
+ ["pe"]="چهار",
+ ["ro"]="patru",
+ },
+ ["frame"]={
+ ["cs"]="ramecek",
+ ["de"]="rahmen",
+ ["en"]="frame",
+ ["fr"]="cadre",
+ ["it"]="cornice",
+ ["nl"]="kader",
+ ["pe"]="قالب",
+ ["ro"]="incadrat",
+ },
+ ["framedtext"]={
+ ["cs"]="oramovanytext",
+ ["de"]="umrahmtertext",
+ ["en"]="framedtext",
+ ["fr"]="texteencadre",
+ ["it"]="testoincorniciato",
+ ["nl"]="kadertekst",
+ ["pe"]="متنقالبی",
+ ["ro"]="textinconjurat",
+ },
+ ["friday"]={
+ ["cs"]="patek",
+ ["de"]="freitag",
+ ["en"]="friday",
+ ["fr"]="vendredi",
+ ["it"]="venerdi",
+ ["nl"]="vrijdag",
+ ["pe"]="جمعه",
+ ["ro"]="vineri",
+ },
+ ["frontmatter"]={
+ ["cs"]="prednicasti",
+ ["de"]="einleitungen",
+ ["en"]="frontmatter",
+ ["fr"]="preambule",
+ ["it"]="preambolo",
+ ["nl"]="inleidingen",
+ ["pe"]="پیشمطلب",
+ ["ro"]="prologul",
+ },
+ ["frontpart"]={
+ ["cs"]="prednicast",
+ ["de"]="einleitung",
+ ["en"]="frontpart",
+ ["fr"]="preface",
+ ["it"]="prefazione",
+ ["nl"]="inleiding",
+ ["pe"]="پیشقسمت",
+ ["ro"]="prolog",
+ },
+ ["global"]={
+ ["cs"]="globalne",
+ ["de"]="global",
+ ["en"]="global",
+ ["fr"]="global",
+ ["it"]="globale",
+ ["nl"]="globaal",
+ ["pe"]="سراسری",
+ ["ro"]="global",
+ },
+ ["graphic"]={
+ ["cs"]="graf",
+ ["de"]="grafik",
+ ["en"]="graphic",
+ ["fr"]="graphique",
+ ["it"]="grafico",
+ ["nl"]="grafiek",
+ ["pe"]="گرافیک",
+ ["ro"]="graficul",
+ },
+ ["graphics"]={
+ ["cs"]="grafy",
+ ["de"]="grafiken",
+ ["en"]="graphics",
+ ["fr"]="graphiques",
+ ["it"]="grafici",
+ ["nl"]="grafieken",
+ ["pe"]="گرافیکها",
+ ["ro"]="graficele",
+ },
+ ["gray"]={
+ ["cs"]="seda",
+ ["de"]="grau",
+ ["en"]="gray",
+ ["fr"]="gris",
+ ["it"]="grigio",
+ ["nl"]="grijs",
+ ["pe"]="خاکستری",
+ ["ro"]="gri",
+ },
+ ["greek"]={
+ ["cs"]="recky",
+ ["de"]="griechisch",
+ ["en"]="greek",
+ ["fr"]="grec",
+ ["it"]="greco",
+ ["nl"]="grieks",
+ ["pe"]="یونانی",
+ ["ro"]="grec",
+ },
+ ["grid"]={
+ ["cs"]="mrizka",
+ ["de"]="gritter",
+ ["en"]="grid",
+ ["fr"]="grille",
+ ["it"]="griglia",
+ ["nl"]="grid",
+ ["pe"]="توری",
+ ["ro"]="grila",
+ },
+ ["halfline"]={
+ ["cs"]="pulradku",
+ ["de"]="halbezeile",
+ ["en"]="halfline",
+ ["fr"]="demiligne",
+ ["it"]="mezzariga",
+ ["nl"]="halveregel",
+ ["pe"]="نیمخط",
+ ["ro"]="jumatatelinie",
+ },
+ ["handwritten"]={
+ ["cs"]="rukopisne",
+ ["de"]="handschrift",
+ ["en"]="handwritten",
+ ["fr"]="manuscript",
+ ["it"]="grafiamanuale",
+ ["nl"]="handschrift",
+ ["pe"]="دستنوشته",
+ ["ro"]="scrismanual",
+ },
+ ["hang"]={
+ ["cs"]="zaveseni",
+ ["de"]="haengend",
+ ["en"]="hang",
+ ["fr"]="suspend",
+ ["it"]="sospendi",
+ ["nl"]="hang",
+ ["pe"]="بیاویز",
+ ["ro"]="suspenda",
+ },
+ ["hanging"]={
+ ["cs"]="visici",
+ ["de"]="haengend",
+ ["en"]="hanging",
+ ["fr"]="suspend",
+ ["it"]="sospeso",
+ ["nl"]="hangend",
+ ["pe"]="آویزان",
+ ["ro"]="suspendat",
+ },
+ ["head"]={
+ ["cs"]="hlavicka",
+ ["de"]="kopf",
+ ["en"]="head",
+ ["fr"]="tete",
+ ["it"]="testa",
+ ["nl"]="kop",
+ ["pe"]="سر",
+ ["ro"]="antet",
+ },
+ ["header"]={
+ ["cs"]="zahlavi",
+ ["de"]="kopfzeile",
+ ["en"]="header",
+ ["fr"]="entete",
+ ["it"]="intestazione",
+ ["nl"]="hoofd",
+ ["pe"]="سربرگ",
+ ["ro"]="antet",
+ },
+ ["height"]={
+ ["cs"]="vyska",
+ ["de"]="hoehe",
+ ["en"]="height",
+ ["fr"]="hauteur",
+ ["it"]="altezza",
+ ["nl"]="hoogte",
+ ["pe"]="ارتفاع",
+ ["ro"]="inaltime",
+ },
+ ["helptext"]={
+ ["cs"]="textnapovedy",
+ ["de"]="hilfetext",
+ ["en"]="helptext",
+ ["fr"]="texteaide",
+ ["it"]="testoaiuto",
+ ["nl"]="helptekst",
+ ["pe"]="متنکمکی",
+ ["ro"]="textajutator",
+ },
+ ["hencefore"]={
+ ["cs"]="vyse",
+ ["de"]="vorher",
+ ["en"]="hencefore",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="hierboven",
+ ["pe"]="hencefore",
+ ["ro"]="precedent",
+ },
+ ["here"]={
+ ["cs"]="zde",
+ ["de"]="hier",
+ ["en"]="here",
+ ["fr"]="ici",
+ ["it"]="qui",
+ ["nl"]="hier",
+ ["pe"]="اینجا",
+ ["ro"]="aici",
+ },
+ ["hereafter"]={
+ ["cs"]="nize",
+ ["de"]="nachher",
+ ["en"]="hereafter",
+ ["fr"]="suivant",
+ ["it"]="seguente",
+ ["nl"]="hieronder",
+ ["pe"]="ازاینبهبعد",
+ ["ro"]="urmator",
+ },
+ ["hidden"]={
+ ["cs"]="skryte",
+ ["de"]="versteckt",
+ ["en"]="hidden",
+ ["fr"]="cache",
+ ["it"]="nascosto",
+ ["nl"]="verborgen",
+ ["pe"]="پنهانی",
+ ["ro"]="ascuns",
+ },
+ ["hiding"]={
+ ["cs"]="skryt",
+ ["de"]="verbergen",
+ ["en"]="hiding",
+ ["fr"]="cache",
+ ["it"]="nascondere",
+ ["nl"]="verbergen",
+ ["pe"]="پنهانکردن",
+ ["ro"]="ascundere",
+ },
+ ["high"]={
+ ["cs"]="vysoko",
+ ["de"]="hoch",
+ ["en"]="high",
+ ["fr"]="haut",
+ ["it"]="alto",
+ ["nl"]="hoog",
+ ["pe"]="بلند",
+ ["ro"]="inalt",
+ },
+ ["horizontal"]={
+ ["cs"]="horizontalne",
+ ["de"]="horizontal",
+ ["en"]="horizontal",
+ ["fr"]="horizontale",
+ ["it"]="orizzontale",
+ ["nl"]="horizontaal",
+ ["pe"]="افقی",
+ ["ro"]="orizontal",
+ },
+ ["hyphenated"]={
+ ["cs"]="hyphenated",
+ ["de"]="hyphenate",
+ ["en"]="hyphenated",
+ ["fr"]="hyphenated",
+ ["it"]="sillabato",
+ ["nl"]="afgebroken",
+ ["pe"]="شکسته",
+ ["ro"]="despsilabe",
+ },
+ ["hz"]={
+ ["cs"]="hz",
+ ["de"]="hz",
+ ["en"]="hz",
+ ["fr"]="hz",
+ ["it"]="hz",
+ ["nl"]="hz",
+ ["pe"]="hz",
+ ["ro"]="hz",
+ },
+ ["inbetween"]={
+ ["cs"]="mezi",
+ ["de"]="zwischen",
+ ["en"]="inbetween",
+ ["fr"]="entre",
+ ["it"]="tra",
+ ["nl"]="tussen",
+ ["pe"]="دربین",
+ ["ro"]="intre",
+ },
+ ["index"]={
+ ["cs"]="rejstrik",
+ ["de"]="index",
+ ["en"]="index",
+ ["fr"]="index",
+ ["it"]="indiceanalitico",
+ ["nl"]="index",
+ ["pe"]="نمایه",
+ ["ro"]="index",
+ },
+ ["indices"]={
+ ["cs"]="rejstriky",
+ ["de"]="indizies",
+ ["en"]="indices",
+ ["fr"]="indices",
+ ["it"]="indicianalitici",
+ ["nl"]="indices",
+ ["pe"]="نمایهها",
+ ["ro"]="indexuri",
+ },
+ ["informeel"]={
+ ["cs"]="informeel",
+ ["de"]="informeel",
+ ["en"]="informeel",
+ ["fr"]="informeel",
+ ["it"]="informeel",
+ ["nl"]="informeel",
+ ["pe"]="informeel",
+ ["ro"]="informeel",
+ },
+ ["inherit"]={
+ ["cs"]="inherit",
+ ["de"]="inherit",
+ ["en"]="inherit",
+ ["fr"]="herite",
+ ["it"]="inherit",
+ ["nl"]="erf",
+ ["pe"]="ارثبردن",
+ ["ro"]="inherit",
+ },
+ ["inleft"]={
+ ["cs"]="vlevo",
+ ["de"]="imlinken",
+ ["en"]="inleft",
+ ["fr"]="dansgauche",
+ ["it"]="insinistra",
+ ["nl"]="inlinker",
+ ["pe"]="درونچپ",
+ ["ro"]="instanga",
+ },
+ ["inmargin"]={
+ ["cs"]="naokraji",
+ ["de"]="imrand",
+ ["en"]="inmargin",
+ ["fr"]="dansmarge",
+ ["it"]="inmargine",
+ ["nl"]="inmarge",
+ ["pe"]="درونحاشیه",
+ ["ro"]="inmargine",
+ },
+ ["inner"]={
+ ["cs"]="uvnitr",
+ ["de"]="innen",
+ ["en"]="inner",
+ ["fr"]="interieur",
+ ["it"]="interno",
+ ["nl"]="binnen",
+ ["pe"]="داخلی",
+ ["ro"]="intern",
+ },
+ ["inneredge"]={
+ ["cs"]="inneredge",
+ ["de"]="inneredge",
+ ["en"]="inneredge",
+ ["fr"]="bordinterieur",
+ ["it"]="bordointerno",
+ ["nl"]="binnenrand",
+ ["pe"]="لبهداخلی",
+ ["ro"]="inneredge",
+ },
+ ["innermargin"]={
+ ["cs"]="innermargin",
+ ["de"]="innermargin",
+ ["en"]="innermargin",
+ ["fr"]="margeinterieure",
+ ["it"]="margineinterno",
+ ["nl"]="binnenmarge",
+ ["pe"]="حاشیهداخلی",
+ ["ro"]="innermargin",
+ },
+ ["inright"]={
+ ["cs"]="vpravo",
+ ["de"]="imrechten",
+ ["en"]="inright",
+ ["fr"]="dansdroit",
+ ["it"]="indestra",
+ ["nl"]="inrechter",
+ ["pe"]="درونراست",
+ ["ro"]="indreapta",
+ },
+ ["interaction"]={
+ ["cs"]="interakce",
+ ["de"]="interaktion",
+ ["en"]="interaction",
+ ["fr"]="interaction",
+ ["it"]="interazione",
+ ["nl"]="interactie",
+ ["pe"]="پانل",
+ ["ro"]="interactiune",
+ },
+ ["interactionmenu"]={
+ ["cs"]="interaktivnimenu",
+ ["de"]="interaktionsmenue",
+ ["en"]="interactionmenu",
+ ["fr"]="menuinteraction",
+ ["it"]="menuinterattivo",
+ ["nl"]="interactiemenu",
+ ["pe"]="منویپانل",
+ ["ro"]="meniuinteractiune",
+ },
+ ["intermezzi"]={
+ ["cs"]="intermezzi",
+ ["de"]="intermezzi",
+ ["en"]="intermezzi",
+ ["fr"]="intermezzi",
+ ["it"]="intermezzi",
+ ["nl"]="intermezzos",
+ ["pe"]="میانپردهها",
+ ["ro"]="intermezzi",
+ },
+ ["intermezzo"]={
+ ["cs"]="intermezzo",
+ ["de"]="intermezzo",
+ ["en"]="intermezzo",
+ ["fr"]="intermezzo",
+ ["it"]="intermezzo",
+ ["nl"]="intermezzo",
+ ["pe"]="میانپرده",
+ ["ro"]="intermezzo",
+ },
+ ["intext"]={
+ ["cs"]="dotextu",
+ ["de"]="imtext",
+ ["en"]="intext",
+ ["fr"]="danstexte",
+ ["it"]="intesto",
+ ["nl"]="intekst",
+ ["pe"]="درونمتن",
+ ["ro"]="intext",
+ },
+ ["intro"]={
+ ["cs"]="uvod",
+ ["de"]="intro",
+ ["en"]="intro",
+ ["fr"]="intro",
+ ["it"]="intro",
+ ["nl"]="intro",
+ ["pe"]="پیشگفتار",
+ ["ro"]="intro",
+ },
+ ["italic"]={
+ ["cs"]="kurziva",
+ ["de"]="italic",
+ ["en"]="italic",
+ ["fr"]="italique",
+ ["it"]="corsivo",
+ ["nl"]="italic",
+ ["pe"]="ایتالیک",
+ ["ro"]="italic",
+ },
+ ["italicbold"]={
+ ["cs"]="kurzivnitucne",
+ ["de"]="italicfett",
+ ["en"]="italicbold",
+ ["fr"]="grasitalique",
+ ["it"]="corsivograssetto",
+ ["nl"]="italicvet",
+ ["pe"]="مشکیایتالیک",
+ ["ro"]="italicaldin",
+ },
+ ["item"]={
+ ["cs"]="polozka",
+ ["de"]="pos",
+ ["en"]="item",
+ ["fr"]="element",
+ ["it"]="elemento",
+ ["nl"]="som",
+ ["pe"]="آیتم",
+ ["ro"]="element",
+ },
+ ["itemize"]={
+ ["cs"]="vycet",
+ ["de"]="aufzaehlung",
+ ["en"]="itemize",
+ ["fr"]="lister",
+ ["it"]="elenco",
+ ["nl"]="opsomming",
+ ["pe"]="آیتمبندی",
+ ["ro"]="enumerare",
+ },
+ ["its"]={
+ ["cs"]="pol",
+ ["de"]="its",
+ ["en"]="its",
+ ["fr"]="its",
+ ["it"]="its",
+ ["nl"]="its",
+ ["pe"]="آیم",
+ ["ro"]="propriu",
+ },
+ ["january"]={
+ ["cs"]="leden",
+ ["de"]="Januar",
+ ["en"]="January",
+ ["fr"]="janvier",
+ ["it"]="gennaio",
+ ["nl"]="januari",
+ ["pe"]="ژانویه",
+ ["ro"]="ianuarie",
+ },
+ ["joinedup"]={
+ ["cs"]="spojeno",
+ ["de"]="keinabstand",
+ ["en"]="joinedup",
+ ["fr"]="joinedup",
+ ["it"]="unito",
+ ["nl"]="aansluitend",
+ ["pe"]="متصلبالا",
+ ["ro"]="unit",
+ },
+ ["july"]={
+ ["cs"]="cervenec",
+ ["de"]="Juli",
+ ["en"]="July",
+ ["fr"]="juillet",
+ ["it"]="luglio",
+ ["nl"]="juli",
+ ["pe"]="ژولای",
+ ["ro"]="iulie",
+ },
+ ["june"]={
+ ["cs"]="cerven",
+ ["de"]="Juni",
+ ["en"]="June",
+ ["fr"]="juin",
+ ["it"]="giugno",
+ ["nl"]="juni",
+ ["pe"]="ژوئن",
+ ["ro"]="iunie",
+ },
+ ["keep"]={
+ ["cs"]="drzet",
+ ["de"]="behalte",
+ ["en"]="keep",
+ ["fr"]="maintient",
+ ["it"]="mantieni",
+ ["nl"]="handhaaf",
+ ["pe"]="نگهدار",
+ ["ro"]="mentine",
+ },
+ ["knockout"]={
+ ["cs"]="knockout",
+ ["de"]="knockout",
+ ["en"]="knockout",
+ ["fr"]="knockout",
+ ["it"]="knockout",
+ ["nl"]="knockout",
+ ["pe"]="knockout",
+ ["ro"]="knockout",
+ },
+ ["label"]={
+ ["cs"]="popisek",
+ ["de"]="label",
+ ["en"]="label",
+ ["fr"]="etiquette",
+ ["it"]="etichetta",
+ ["nl"]="label",
+ ["pe"]="برچسب",
+ ["ro"]="eticheta",
+ },
+ ["landscape"]={
+ ["cs"]="nasirku",
+ ["de"]="querformat",
+ ["en"]="landscape",
+ ["fr"]="paysage",
+ ["it"]="orizzontale",
+ ["nl"]="liggend",
+ ["pe"]="صفحهگسترده",
+ ["ro"]="vedere",
+ },
+ ["last"]={
+ ["cs"]="posledni",
+ ["de"]="letzte",
+ ["en"]="last",
+ ["fr"]="dernier",
+ ["it"]="ultimo",
+ ["nl"]="laatste",
+ ["pe"]="آخرین",
+ ["ro"]="ultim",
+ },
+ ["lastcolumn"]={
+ ["cs"]="lastcolumn",
+ ["de"]="lastcolumn",
+ ["en"]="lastcolumn",
+ ["fr"]="dernierecolonne",
+ ["it"]="lastcolumn",
+ ["nl"]="laatstekolom",
+ ["pe"]="آخرینستون",
+ ["ro"]="lastcolumn",
+ },
+ ["lastpage"]={
+ ["cs"]="poslednistrana",
+ ["de"]="letzteseite",
+ ["en"]="lastpage",
+ ["fr"]="dernierepage",
+ ["it"]="ultimapagina",
+ ["nl"]="laatstepagina",
+ ["pe"]="صفحهآخر",
+ ["ro"]="ultimapagina",
+ },
+ ["lastpagenumber"]={
+ ["cs"]="lastpagenumber",
+ ["de"]="lastpagenumber",
+ ["en"]="lastpagenumber",
+ ["fr"]="derniernumeropage",
+ ["it"]="lastpagenumber",
+ ["nl"]="laatstepaginanummer",
+ ["pe"]="شماهصفحهآخر",
+ ["ro"]="lastpagenumber",
+ },
+ ["lastsubpage"]={
+ ["cs"]="poslaednipodstranka",
+ ["de"]="letzteunterseite",
+ ["en"]="lastsubpage",
+ ["fr"]="dernieresouspage",
+ ["it"]="ultimasottopagina",
+ ["nl"]="laatstesubpagina",
+ ["pe"]="زیرصفحهآخر",
+ ["ro"]="ultimasubpagina",
+ },
+ ["layer"]={
+ ["cs"]="layer",
+ ["de"]="layer",
+ ["en"]="layer",
+ ["fr"]="layer",
+ ["it"]="layer",
+ ["nl"]="layer",
+ ["pe"]="layer",
+ ["ro"]="layer",
+ },
+ ["left"]={
+ ["cs"]="vlevo",
+ ["de"]="links",
+ ["en"]="left",
+ ["fr"]="gauche",
+ ["it"]="sinistra",
+ ["nl"]="links",
+ ["pe"]="چپ",
+ ["ro"]="stanga",
+ },
+ ["leftedge"]={
+ ["cs"]="levahrana",
+ ["de"]="linkekante",
+ ["en"]="leftedge",
+ ["fr"]="bordgauche",
+ ["it"]="bordosinistro",
+ ["nl"]="linkerrand",
+ ["pe"]="لبهچپ",
+ ["ro"]="bordurastanga",
+ },
+ ["lefthanging"]={
+ ["cs"]="lefthanging",
+ ["de"]="lefthanging",
+ ["en"]="lefthanging",
+ ["fr"]="lefthanging",
+ ["it"]="lefthanging",
+ ["nl"]="linkshangend",
+ ["pe"]="آویزانچپ",
+ ["ro"]="lefthanging",
+ },
+ ["leftmargin"]={
+ ["cs"]="levyokraj",
+ ["de"]="linkerrand",
+ ["en"]="leftmargin",
+ ["fr"]="margegauche",
+ ["it"]="marginesinistro",
+ ["nl"]="linkermarge",
+ ["pe"]="حاشیهچپ",
+ ["ro"]="marginestanga",
+ },
+ ["leftpage"]={
+ ["cs"]="levastranka",
+ ["de"]="linkerseite",
+ ["en"]="leftpage",
+ ["fr"]="pagegauche",
+ ["it"]="paginasinistra",
+ ["nl"]="linkerpagina",
+ ["pe"]="صفحهچپ",
+ ["ro"]="paginastanga",
+ },
+ ["lefttoright"]={
+ ["cs"]="lefttoright",
+ ["de"]="lefttoright",
+ ["en"]="lefttoright",
+ ["fr"]="lefttoright",
+ ["it"]="lefttoright",
+ ["nl"]="lefttoright",
+ ["pe"]="lefttoright",
+ ["ro"]="lefttoright",
+ },
+ ["legend"]={
+ ["cs"]="legenda",
+ ["de"]="legende",
+ ["en"]="legend",
+ ["fr"]="legende",
+ ["it"]="legenda",
+ ["nl"]="legenda",
+ ["pe"]="راهنما",
+ ["ro"]="legenda",
+ },
+ ["lesshyphenation"]={
+ ["cs"]="lesshyphenation",
+ ["de"]="lesshyphenation",
+ ["en"]="lesshyphenation",
+ ["fr"]="lesshyphenation",
+ ["it"]="lesshyphenation",
+ ["nl"]="lesshyphenation",
+ ["pe"]="شکستکلماتکمتر",
+ ["ro"]="lesshyphenation",
+ },
+ ["line"]={
+ ["cs"]="radek",
+ ["de"]="zeile",
+ ["en"]="line",
+ ["fr"]="ligne",
+ ["it"]="riga",
+ ["nl"]="regel",
+ ["pe"]="خط",
+ ["ro"]="linie",
+ },
+ ["linenote"]={
+ ["cs"]="linenote",
+ ["de"]="linenote",
+ ["en"]="linenote",
+ ["fr"]="noteligne",
+ ["it"]="linenote",
+ ["nl"]="regelnoot",
+ ["pe"]="خطنوشت",
+ ["ro"]="linenote",
+ },
+ ["lines"]={
+ ["cs"]="radky",
+ ["de"]="zeilen",
+ ["en"]="lines",
+ ["fr"]="lignes",
+ ["it"]="righe",
+ ["nl"]="regels",
+ ["pe"]="خطها",
+ ["ro"]="linii",
+ },
+ ["list"]={
+ ["cs"]="seznam",
+ ["de"]="liste",
+ ["en"]="list",
+ ["fr"]="liste",
+ ["it"]="elenco",
+ ["nl"]="lijst",
+ ["pe"]="لیست",
+ ["ro"]="lista",
+ },
+ ["local"]={
+ ["cs"]="lokalne",
+ ["de"]="lokal",
+ ["en"]="local",
+ ["fr"]="local",
+ ["it"]="locale",
+ ["nl"]="lokaal",
+ ["pe"]="موضعی",
+ ["ro"]="local",
+ },
+ ["localenvironment"]={
+ ["cs"]="lokalnihoprostredi",
+ ["de"]="lokaleumgebung",
+ ["en"]="localenvironment",
+ ["fr"]="environementlocal",
+ ["it"]="ambientelocale",
+ ["nl"]="deelomgeving",
+ ["pe"]="محیطموضعی",
+ ["ro"]="mediulocal",
+ },
+ ["logo"]={
+ ["cs"]="logo",
+ ["de"]="logo",
+ ["en"]="logo",
+ ["fr"]="logo",
+ ["it"]="logo",
+ ["nl"]="logo",
+ ["pe"]="آرم",
+ ["ro"]="logo",
+ },
+ ["logos"]={
+ ["cs"]="loga",
+ ["de"]="logos",
+ ["en"]="logos",
+ ["fr"]="logos",
+ ["it"]="loghi",
+ ["nl"]="logos",
+ ["pe"]="آرمها",
+ ["ro"]="logos",
+ },
+ ["lohi"]={
+ ["cs"]="nivy",
+ ["de"]="hoti",
+ ["en"]="lohi",
+ ["fr"]="baha",
+ ["it"]="pedap",
+ ["nl"]="laho",
+ ["pe"]="پابا",
+ ["ro"]="lohi",
+ },
+ ["loose"]={
+ ["cs"]="uvolnene",
+ ["de"]="lose",
+ ["en"]="loose",
+ ["fr"]="perte",
+ ["it"]="lento",
+ ["nl"]="los",
+ ["pe"]="شل",
+ ["ro"]="larg",
+ },
+ ["low"]={
+ ["cs"]="nizko",
+ ["de"]="tief",
+ ["en"]="low",
+ ["fr"]="bas",
+ ["it"]="basso",
+ ["nl"]="laag",
+ ["pe"]="پایین",
+ ["ro"]="jos",
+ },
+ ["ls"]={
+ ["cs"]="ls",
+ ["de"]="ls",
+ ["en"]="ls",
+ ["fr"]="ls",
+ ["it"]="ls",
+ ["nl"]="ls",
+ ["pe"]="ls",
+ ["ro"]="ls",
+ },
+ ["makeup"]={
+ ["cs"]="zlom",
+ ["de"]="umbruch",
+ ["en"]="makeup",
+ ["fr"]="makeup",
+ ["it"]="makeup",
+ ["nl"]="opmaak",
+ ["pe"]="آرایش",
+ ["ro"]="marcaj",
+ },
+ ["mar"]={
+ ["cs"]="mar",
+ ["de"]="mar",
+ ["en"]="mar",
+ ["fr"]="mar",
+ ["it"]="mar",
+ ["nl"]="mar",
+ ["pe"]="حاش",
+ ["ro"]="mar",
+ },
+ ["march"]={
+ ["cs"]="brezen",
+ ["de"]="Maerz",
+ ["en"]="March",
+ ["fr"]="mars",
+ ["it"]="marzo",
+ ["nl"]="maart",
+ ["pe"]="مارس",
+ ["ro"]="martie",
+ },
+ ["margin"]={
+ ["cs"]="marginalie",
+ ["de"]="marginalie",
+ ["en"]="margin",
+ ["fr"]="marge",
+ ["it"]="margine",
+ ["nl"]="marge",
+ ["pe"]="حاشیه",
+ ["ro"]="margine",
+ },
+ ["marginedge"]={
+ ["cs"]="textovahrana",
+ ["de"]="marginalkante",
+ ["en"]="marginedge",
+ ["fr"]="bordmarge",
+ ["it"]="bordomargine",
+ ["nl"]="kantlijn",
+ ["pe"]="لبهحاشیه",
+ ["ro"]="marginebordura",
+ },
+ ["margintitle"]={
+ ["cs"]="titulmarginalie",
+ ["de"]="marginaltitel",
+ ["en"]="margintitle",
+ ["fr"]="titremarge",
+ ["it"]="titoloinmargine",
+ ["nl"]="margetitel",
+ ["pe"]="عنوانحاشیه",
+ ["ro"]="titlumarginal",
+ },
+ ["marking"]={
+ ["cs"]="znaceni",
+ ["de"]="beschriftung",
+ ["en"]="marking",
+ ["fr"]="marquage",
+ ["it"]="marcatura",
+ ["nl"]="markering",
+ ["pe"]="نشانهگذاری",
+ ["ro"]="marcaje",
+ },
+ ["mathalignment"]={
+ ["cs"]="mathalignment",
+ ["de"]="mathalignment",
+ ["en"]="mathalignment",
+ ["fr"]="mathalignment",
+ ["it"]="mathalignment",
+ ["nl"]="wiskundeuitlijnen",
+ ["pe"]="تنظیمریاضی",
+ ["ro"]="mathalignment",
+ },
+ ["mathcases"]={
+ ["cs"]="mathcases",
+ ["de"]="mathcases",
+ ["en"]="mathcases",
+ ["fr"]="mathcases",
+ ["it"]="mathcases",
+ ["nl"]="mathcases",
+ ["pe"]="حالتهایریاضی",
+ ["ro"]="mathcases",
+ },
+ ["mathmatrix"]={
+ ["cs"]="mathmatrix",
+ ["de"]="mathmatrix",
+ ["en"]="mathmatrix",
+ ["fr"]="mathmatrix",
+ ["it"]="mathmatrix",
+ ["nl"]="wiskundematrix",
+ ["pe"]="ماتریشریاضی",
+ ["ro"]="mathmatrix",
+ },
+ ["max"]={
+ ["cs"]="max",
+ ["de"]="max",
+ ["en"]="max",
+ ["fr"]="max",
+ ["it"]="max",
+ ["nl"]="max",
+ ["pe"]="بیشترین",
+ ["ro"]="max",
+ },
+ ["may"]={
+ ["cs"]="kveten",
+ ["de"]="Mai",
+ ["en"]="May",
+ ["fr"]="mai",
+ ["it"]="maggio",
+ ["nl"]="mei",
+ ["pe"]="مه",
+ ["ro"]="mai",
+ },
+ ["mediaeval"]={
+ ["cs"]="stredoveky",
+ ["de"]="mittelalterlich",
+ ["en"]="mediaeval",
+ ["fr"]="medieval",
+ ["it"]="medievale",
+ ["nl"]="mediaeval",
+ ["pe"]="mediaeval",
+ ["ro"]="medieval",
+ },
+ ["medium"]={
+ ["cs"]="stredni",
+ ["de"]="mittel",
+ ["en"]="medium",
+ ["fr"]="moyen",
+ ["it"]="medio",
+ ["nl"]="middel",
+ ["pe"]="متوسط",
+ ["ro"]="mediu",
+ },
+ ["middle"]={
+ ["cs"]="nastred",
+ ["de"]="mittig",
+ ["en"]="middle",
+ ["fr"]="milieu",
+ ["it"]="centro",
+ ["nl"]="midden",
+ ["pe"]="میان",
+ ["ro"]="centru",
+ },
+ ["min"]={
+ ["cs"]="min",
+ ["de"]="min",
+ ["en"]="min",
+ ["fr"]="min",
+ ["it"]="min",
+ ["nl"]="min",
+ ["pe"]="کمترین",
+ ["ro"]="min",
+ },
+ ["minheight"]={
+ ["cs"]="minvyska",
+ ["de"]="minhoehe",
+ ["en"]="minheight",
+ ["fr"]="hauteurmin",
+ ["it"]="altezzamin",
+ ["nl"]="minhoogte",
+ ["pe"]="کمترینارتفاع",
+ ["ro"]="inaltimeminima",
+ },
+ ["minwidth"]={
+ ["cs"]="minsirka",
+ ["de"]="minbreite",
+ ["en"]="minwidth",
+ ["fr"]="largeurmin",
+ ["it"]="ampiezzamin",
+ ["nl"]="minbreedte",
+ ["pe"]="کمترینعرض",
+ ["ro"]="latimeminima",
+ },
+ ["mirrored"]={
+ ["cs"]="zrcadleno",
+ ["de"]="gespiegelt",
+ ["en"]="mirrored",
+ ["fr"]="reflete",
+ ["it"]="riflesso",
+ ["nl"]="gespiegeld",
+ ["pe"]="منعکس",
+ ["ro"]="oglindit",
+ },
+ ["monday"]={
+ ["cs"]="pondeli",
+ ["de"]="montag",
+ ["en"]="monday",
+ ["fr"]="lundi",
+ ["it"]="lunedi",
+ ["nl"]="maandag",
+ ["pe"]="دوشنبه",
+ ["ro"]="luni",
+ },
+ ["mono"]={
+ ["cs"]="mono",
+ ["de"]="mono",
+ ["en"]="mono",
+ ["fr"]="mono",
+ ["it"]="mono",
+ ["nl"]="mono",
+ ["pe"]="مونو",
+ ["ro"]="mono",
+ },
+ ["month"]={
+ ["cs"]="mesic",
+ ["de"]="monat",
+ ["en"]="month",
+ ["fr"]="mois",
+ ["it"]="mese",
+ ["nl"]="maand",
+ ["pe"]="ماه",
+ ["ro"]="luna",
+ },
+ ["morehyphenation"]={
+ ["cs"]="morehyphenation",
+ ["de"]="morehyphenation",
+ ["en"]="morehyphenation",
+ ["fr"]="morehyphenation",
+ ["it"]="morehyphenation",
+ ["nl"]="morehyphenation",
+ ["pe"]="شکستکلماتبیشتر",
+ ["ro"]="morehyphenation",
+ },
+ ["name"]={
+ ["cs"]="jmeno",
+ ["de"]="name",
+ ["en"]="name",
+ ["fr"]="nom",
+ ["it"]="nome",
+ ["nl"]="naam",
+ ["pe"]="نام",
+ ["ro"]="nume",
+ },
+ ["narrow"]={
+ ["cs"]="uzky",
+ ["de"]="schmall",
+ ["en"]="narrow",
+ ["fr"]="etroit",
+ ["it"]="stretto",
+ ["nl"]="smal",
+ ["pe"]="نازک",
+ ["ro"]="ingust",
+ },
+ ["negative"]={
+ ["cs"]="negativ",
+ ["de"]="negativ",
+ ["en"]="negative",
+ ["fr"]="negatif",
+ ["it"]="negativo",
+ ["nl"]="negatief",
+ ["pe"]="منفی",
+ ["ro"]="negativ",
+ },
+ ["never"]={
+ ["cs"]="nikdy",
+ ["de"]="nie",
+ ["en"]="never",
+ ["fr"]="jamais",
+ ["it"]="mai",
+ ["nl"]="nooit",
+ ["pe"]="هیچگاه",
+ ["ro"]="niciodata",
+ },
+ ["new"]={
+ ["cs"]="novy",
+ ["de"]="neu",
+ ["en"]="new",
+ ["fr"]="nouveau",
+ ["it"]="nuovo",
+ ["nl"]="nieuw",
+ ["pe"]="جدید",
+ ["ro"]="nou",
+ },
+ ["next"]={
+ ["cs"]="dalsi",
+ ["de"]="folgende",
+ ["en"]="next",
+ ["fr"]="prochain",
+ ["it"]="successivo",
+ ["nl"]="volgende",
+ ["pe"]="بعدی",
+ ["ro"]="urmatorul",
+ },
+ ["nextevenpage"]={
+ ["cs"]="dalsisudastranka",
+ ["de"]="naechstegeradeseite",
+ ["en"]="nextevenpage",
+ ["fr"]="pagepairesuivante",
+ ["it"]="paginaparisuccessiva",
+ ["nl"]="volgendeevenpagina",
+ ["pe"]="صفحهزوجبعدی",
+ ["ro"]="paginaparaurmatoarea",
+ },
+ ["nextoddpage"]={
+ ["cs"]="dalsilichastranka",
+ ["de"]="naechsteungeradeseite",
+ ["en"]="nextoddpage",
+ ["fr"]="pageimpairesuivante",
+ ["it"]="paginadisparisuccessiva",
+ ["nl"]="volgendeonevenpagina",
+ ["pe"]="صفحهفردبعدی",
+ ["ro"]="paginaimparaurmatoarea",
+ },
+ ["nextpage"]={
+ ["cs"]="dalsistranka",
+ ["de"]="folgendeseite",
+ ["en"]="nextpage",
+ ["fr"]="pagesuivante",
+ ["it"]="paginasuccessiva",
+ ["nl"]="volgendepagina",
+ ["pe"]="صفحهبعدی",
+ ["ro"]="paginaurmatoare",
+ },
+ ["nextsubpage"]={
+ ["cs"]="dalsipodstranka",
+ ["de"]="folgendeunterseite",
+ ["en"]="nextsubpage",
+ ["fr"]="souspagesuivante",
+ ["it"]="sottopaginasuccessiva",
+ ["nl"]="volgendesubpagina",
+ ["pe"]="زیرصفحهبعدی",
+ ["ro"]="urmatoareasubpagina",
+ },
+ ["no"]={
+ ["cs"]="ne",
+ ["de"]="nein",
+ ["en"]="no",
+ ["fr"]="non",
+ ["it"]="no",
+ ["nl"]="nee",
+ ["pe"]="نه",
+ ["ro"]="nu",
+ },
+ ["nocheck"]={
+ ["cs"]="nocheck",
+ ["de"]="nocheck",
+ ["en"]="nocheck",
+ ["fr"]="nonverifie",
+ ["it"]="nocheck",
+ ["nl"]="geencontrole",
+ ["pe"]="بدونبررسی",
+ ["ro"]="nocheck",
+ },
+ ["nofit"]={
+ ["cs"]="nofit",
+ ["de"]="nofit",
+ ["en"]="nofit",
+ ["fr"]="nofit",
+ ["it"]="nofit",
+ ["nl"]="nietpassend",
+ ["pe"]="بدونپرکردن",
+ ["ro"]="nofit",
+ },
+ ["nogrid"]={
+ ["cs"]="nogrid",
+ ["de"]="nogrid",
+ ["en"]="nogrid",
+ ["fr"]="nogrid",
+ ["it"]="nogrid",
+ ["nl"]="geengrid",
+ ["pe"]="بدونتوری",
+ ["ro"]="nogrid",
+ },
+ ["nohz"]={
+ ["cs"]="nohz",
+ ["de"]="nohz",
+ ["en"]="nohz",
+ ["fr"]="nohz",
+ ["it"]="nohz",
+ ["nl"]="geenhz",
+ ["pe"]="nohz",
+ ["ro"]="nohz",
+ },
+ ["nomarking"]={
+ ["cs"]="zadneznaceni",
+ ["de"]="keinebeschriftung",
+ ["en"]="nomarking",
+ ["fr"]="sansmarquage",
+ ["it"]="nomarcature",
+ ["nl"]="geenmarkering",
+ ["pe"]="بدوننشانهگذاری",
+ ["ro"]="faramarcare",
+ },
+ ["none"]={
+ ["cs"]="zadny",
+ ["de"]="kein",
+ ["en"]="none",
+ ["fr"]="rien",
+ ["it"]="nessuno",
+ ["nl"]="geen",
+ ["pe"]="هیچکدام",
+ ["ro"]="niciunul",
+ },
+ ["nonumber"]={
+ ["cs"]="nonumber",
+ ["de"]="nonumber",
+ ["en"]="nonumber",
+ ["fr"]="sansnumero",
+ ["it"]="nonumber",
+ ["nl"]="geennummer",
+ ["pe"]="بدونشماره",
+ ["ro"]="nonumber",
+ },
+ ["normal"]={
+ ["cs"]="normalni",
+ ["de"]="normal",
+ ["en"]="normal",
+ ["fr"]="normal",
+ ["it"]="normale",
+ ["nl"]="normaal",
+ ["pe"]="نرمال",
+ ["ro"]="normal",
+ },
+ ["nospacing"]={
+ ["cs"]="nospacing",
+ ["de"]="nospacing",
+ ["en"]="nospacing",
+ ["fr"]="sansespacement",
+ ["it"]="nospacing",
+ ["nl"]="geenspatiering",
+ ["pe"]="بدونفضاگذاری",
+ ["ro"]="nospacing",
+ },
+ ["not"]={
+ ["cs"]="ne",
+ ["de"]="nicht",
+ ["en"]="not",
+ ["fr"]="pas",
+ ["it"]="non",
+ ["nl"]="niet",
+ ["pe"]="بدون",
+ ["ro"]="nu",
+ },
+ ["note"]={
+ ["en"]="note",
+ },
+ ["nothanging"]={
+ ["cs"]="nothanging",
+ ["de"]="nothanging",
+ ["en"]="nothanging",
+ ["fr"]="nonsuspendu",
+ ["it"]="nonsospeso",
+ ["nl"]="niethangend",
+ ["pe"]="بدونآویزانکردن",
+ ["ro"]="nothanging",
+ },
+ ["nothyphenated"]={
+ ["cs"]="nothyphenated",
+ ["de"]="nothyphenated",
+ ["en"]="nothyphenated",
+ ["fr"]="nothyphenated",
+ ["it"]="nonsillabato",
+ ["nl"]="nietafgebroken",
+ ["pe"]="بدونشکست",
+ ["ro"]="nedespsilabe",
+ },
+ ["november"]={
+ ["cs"]="listopad",
+ ["de"]="November",
+ ["en"]="November",
+ ["fr"]="novembre",
+ ["it"]="novembre",
+ ["nl"]="november",
+ ["pe"]="نوامبر",
+ ["ro"]="noiembrie",
+ },
+ ["nowhere"]={
+ ["cs"]="nikde",
+ ["de"]="nirgens",
+ ["en"]="nowhere",
+ ["fr"]="nulpart",
+ ["it"]="danessunaparte",
+ ["nl"]="nergens",
+ ["pe"]="هیچحا",
+ ["ro"]="niciunde",
+ },
+ ["nowhite"]={
+ ["cs"]="zadnabila",
+ ["de"]="keinweiss",
+ ["en"]="nowhite",
+ ["fr"]="sansblanc",
+ ["it"]="nobianco",
+ ["nl"]="geenwit",
+ ["pe"]="سفیدنه",
+ ["ro"]="faraalb",
+ },
+ ["number"]={
+ ["cs"]="cislo",
+ ["de"]="nummer",
+ ["en"]="number",
+ ["fr"]="numero",
+ ["it"]="numero",
+ ["nl"]="nummer",
+ ["pe"]="شماره",
+ ["ro"]="numar",
+ },
+ ["numbers"]={
+ ["cs"]="cisla",
+ ["de"]="ziffern",
+ ["en"]="numbers",
+ ["fr"]="numeros",
+ ["it"]="numeri",
+ ["nl"]="cijfers",
+ ["pe"]="شمارهها",
+ ["ro"]="numere",
+ },
+ ["october"]={
+ ["cs"]="rijen",
+ ["de"]="Oktober",
+ ["en"]="October",
+ ["fr"]="octobre",
+ ["it"]="ottobre",
+ ["nl"]="oktober",
+ ["pe"]="اکتبر",
+ ["ro"]="octombrie",
+ },
+ ["odd"]={
+ ["cs"]="liche",
+ ["de"]="ungerade",
+ ["en"]="odd",
+ ["fr"]="impair",
+ ["it"]="dispari",
+ ["nl"]="oneven",
+ ["pe"]="فرد",
+ ["ro"]="impar",
+ },
+ ["off"]={
+ ["cs"]="vyp",
+ ["de"]="aus",
+ ["en"]="off",
+ ["fr"]="desactive",
+ ["it"]="disattivo",
+ ["nl"]="uit",
+ ["pe"]="خاموش",
+ ["ro"]="dezactivat",
+ },
+ ["offset"]={
+ ["cs"]="offset",
+ ["de"]="offset",
+ ["en"]="offset",
+ ["fr"]="offset",
+ ["it"]="offset",
+ ["nl"]="offset",
+ ["pe"]="آفست",
+ ["ro"]="offset",
+ },
+ ["old"]={
+ ["cs"]="old",
+ ["de"]="old",
+ ["en"]="old",
+ ["fr"]="old",
+ ["it"]="old",
+ ["nl"]="oud",
+ ["pe"]="قدیمی",
+ ["ro"]="old",
+ },
+ ["on"]={
+ ["cs"]="zap",
+ ["de"]="an",
+ ["en"]="on",
+ ["fr"]="actif",
+ ["it"]="attivo",
+ ["nl"]="aan",
+ ["pe"]="روی",
+ ["ro"]="on",
+ },
+ ["one"]={
+ ["cs"]="jedna",
+ ["de"]="eins",
+ ["en"]="one",
+ ["fr"]="un",
+ ["it"]="uno",
+ ["nl"]="een",
+ ["pe"]="یک",
+ ["ro"]="unu",
+ },
+ ["opposite"]={
+ ["cs"]="naproti",
+ ["de"]="gegenueber",
+ ["en"]="opposite",
+ ["fr"]="opposition",
+ ["it"]="opposto",
+ ["nl"]="naast",
+ ["pe"]="مخالف",
+ ["ro"]="opus",
+ },
+ ["outer"]={
+ ["cs"]="vnejsi",
+ ["de"]="aussen",
+ ["en"]="outer",
+ ["fr"]="exterieur",
+ ["it"]="esterno",
+ ["nl"]="buiten",
+ ["pe"]="خارجی",
+ ["ro"]="extern",
+ },
+ ["outeredge"]={
+ ["cs"]="outeredge",
+ ["de"]="outeredge",
+ ["en"]="outeredge",
+ ["fr"]="bordexterieur",
+ ["it"]="bordoesterno",
+ ["nl"]="buitenrand",
+ ["pe"]="لبهخارجی",
+ ["ro"]="outeredge",
+ },
+ ["outermargin"]={
+ ["cs"]="outermargin",
+ ["de"]="outermargin",
+ ["en"]="outermargin",
+ ["fr"]="margeexterieure",
+ ["it"]="margineesterno",
+ ["nl"]="buitenmarge",
+ ["pe"]="حاشیهخارجی",
+ ["ro"]="outermargin",
+ },
+ ["overlay"]={
+ ["cs"]="prekryv",
+ ["de"]="overlay",
+ ["en"]="overlay",
+ ["fr"]="revetement",
+ ["it"]="sovrapponi",
+ ["nl"]="overlay",
+ ["pe"]="پوشش",
+ ["ro"]="overlay",
+ },
+ ["overprint"]={
+ ["cs"]="overprint",
+ ["de"]="overprint",
+ ["en"]="overprint",
+ ["fr"]="overprint",
+ ["it"]="overprint",
+ ["nl"]="overprint",
+ ["pe"]="overprint",
+ ["ro"]="overprint",
+ },
+ ["packed"]={
+ ["cs"]="zhustene",
+ ["de"]="gepackt",
+ ["en"]="packed",
+ ["fr"]="groupe",
+ ["it"]="impaccato",
+ ["nl"]="opelkaar",
+ ["pe"]="فشرده",
+ ["ro"]="impachetat",
+ },
+ ["page"]={
+ ["cs"]="stranka",
+ ["de"]="seite",
+ ["en"]="page",
+ ["fr"]="page",
+ ["it"]="pagina",
+ ["nl"]="pagina",
+ ["pe"]="صفحه",
+ ["ro"]="pagina",
+ },
+ ["pagecomment"]={
+ ["cs"]="komentarstranky",
+ ["de"]="pagecomment",
+ ["en"]="pagecomment",
+ ["fr"]="commentairepage",
+ ["it"]="commentopagina",
+ ["nl"]="paginacommentaar",
+ ["pe"]="توضیحصفحه",
+ ["ro"]="comentariupagina",
+ },
+ ["pagenumber"]={
+ ["cs"]="cislostranky",
+ ["de"]="seitennummer",
+ ["en"]="pagenumber",
+ ["fr"]="numeropage",
+ ["it"]="numeropagina",
+ ["nl"]="paginanummer",
+ ["pe"]="شمارهصفحه",
+ ["ro"]="numarpagina",
+ },
+ ["paper"]={
+ ["cs"]="papir",
+ ["de"]="papier",
+ ["en"]="paper",
+ ["fr"]="papier",
+ ["it"]="carta",
+ ["nl"]="papier",
+ ["pe"]="برگ",
+ ["ro"]="foaie",
+ },
+ ["paragraph"]={
+ ["cs"]="odstavec",
+ ["de"]="absatz",
+ ["en"]="paragraph",
+ ["fr"]="paragraphe",
+ ["it"]="capoverso",
+ ["nl"]="alinea",
+ ["pe"]="پاراگراف",
+ ["ro"]="paragraf",
+ },
+ ["part"]={
+ ["cs"]="cast",
+ ["de"]="teil",
+ ["en"]="part",
+ ["fr"]="partie",
+ ["it"]="parte",
+ ["nl"]="deel",
+ ["pe"]="قسمت",
+ ["ro"]="parte",
+ },
+ ["positive"]={
+ ["cs"]="positiv",
+ ["de"]="positiv",
+ ["en"]="positive",
+ ["fr"]="positif",
+ ["it"]="positivo",
+ ["nl"]="positief",
+ ["pe"]="مثبت",
+ ["ro"]="positiv",
+ },
+ ["postponing"]={
+ ["cs"]="odlozit",
+ ["de"]="verschieben",
+ ["en"]="postponing",
+ ["fr"]="postponing",
+ ["it"]="posporre",
+ ["nl"]="uitstellen",
+ ["pe"]="تاخیر",
+ ["ro"]="postponing",
+ },
+ ["postscript"]={
+ ["cs"]="postscript",
+ ["de"]="postscript",
+ ["en"]="postscript",
+ ["fr"]="postscript",
+ ["it"]="postscript",
+ ["nl"]="postscript",
+ ["pe"]="پستاسکریپت",
+ ["ro"]="postscript",
+ },
+ ["preference"]={
+ ["cs"]="nastaveni",
+ ["de"]="einstellung",
+ ["en"]="preference",
+ ["fr"]="preference",
+ ["it"]="preferenza",
+ ["nl"]="voorkeur",
+ ["pe"]="ترجیح",
+ ["ro"]="preferinta",
+ },
+ ["preview"]={
+ ["cs"]="nahled",
+ ["de"]="vorschau",
+ ["en"]="preview",
+ ["fr"]="previsualisation",
+ ["it"]="anteprima",
+ ["nl"]="preview",
+ ["pe"]="پیشدید",
+ ["ro"]="previzualizare",
+ },
+ ["previous"]={
+ ["cs"]="predchozi",
+ ["de"]="vorig",
+ ["en"]="previous",
+ ["fr"]="precedent",
+ ["it"]="precedente",
+ ["nl"]="vorige",
+ ["pe"]="قبلی",
+ ["ro"]="precedent",
+ },
+ ["previousevenpage"]={
+ ["cs"]="predchozisudastranka",
+ ["de"]="vorigegeradeseite",
+ ["en"]="previousevenpage",
+ ["fr"]="pagepaireprecedente",
+ ["it"]="paginapariprecedente",
+ ["nl"]="vorigeevenpagina",
+ ["pe"]="صفحهزوجقبلی",
+ ["ro"]="paginaparaprecedenta",
+ },
+ ["previousoddpage"]={
+ ["cs"]="predchozilichastranka",
+ ["de"]="vorigeungeradeseite",
+ ["en"]="previousoddpage",
+ ["fr"]="pageimpaireprecedente",
+ ["it"]="paginadispariprecedente",
+ ["nl"]="vorigeonevenpagina",
+ ["pe"]="صفحهفردقبلی",
+ ["ro"]="paginaimparaprecedenta",
+ },
+ ["previouspage"]={
+ ["cs"]="predchozistranka",
+ ["de"]="vorigeseite",
+ ["en"]="previouspage",
+ ["fr"]="pageprecedente",
+ ["it"]="paginaprecedente",
+ ["nl"]="vorigepagina",
+ ["pe"]="صفحهقبلی",
+ ["ro"]="paginaanterioara",
+ },
+ ["previoussubpage"]={
+ ["cs"]="predchozipodstranka",
+ ["de"]="vorigeunterseite",
+ ["en"]="previoussubpage",
+ ["fr"]="souspageprecedente",
+ ["it"]="sottopaginaprecedente",
+ ["nl"]="vorigesubpagina",
+ ["pe"]="زیرصفحهقبلی",
+ ["ro"]="subpaginaanterioara",
+ },
+ ["printable"]={
+ ["cs"]="tisknutelne",
+ ["de"]="druckbar",
+ ["en"]="printable",
+ ["fr"]="editable",
+ ["it"]="stampabile",
+ ["nl"]="printbaar",
+ ["pe"]="قابلچاپ",
+ ["ro"]="tiparibil",
+ },
+ ["process"]={
+ ["cs"]="process",
+ ["de"]="process",
+ ["en"]="process",
+ ["fr"]="process",
+ ["it"]="process",
+ ["nl"]="proces",
+ ["pe"]="پردازش",
+ ["ro"]="process",
+ },
+ ["product"]={
+ ["cs"]="produkt",
+ ["de"]="produkt",
+ ["en"]="product",
+ ["fr"]="produit",
+ ["it"]="prodotto",
+ ["nl"]="produkt",
+ ["pe"]="محصول",
+ ["ro"]="produs",
+ },
+ ["program"]={
+ ["cs"]="program",
+ ["de"]="programm",
+ ["en"]="program",
+ ["fr"]="programme",
+ ["it"]="programma",
+ ["nl"]="programma",
+ ["pe"]="برنامه",
+ ["ro"]="program",
+ },
+ ["project"]={
+ ["cs"]="projekt",
+ ["de"]="projekt",
+ ["en"]="project",
+ ["fr"]="projet",
+ ["it"]="progetto",
+ ["nl"]="project",
+ ["pe"]="پروژه",
+ ["ro"]="proiect",
+ },
+ ["protected"]={
+ ["cs"]="chranene",
+ ["de"]="geschuetzt",
+ ["en"]="protected",
+ ["fr"]="protege",
+ ["it"]="protetto",
+ ["nl"]="beschermd",
+ ["pe"]="حفاظتشده",
+ ["ro"]="protejat",
+ },
+ ["quadruple"]={
+ ["cs"]="ctyrnasobny",
+ ["de"]="viertel",
+ ["en"]="quadruple",
+ ["fr"]="quadruple",
+ ["it"]="quadruplo",
+ ["nl"]="viertal",
+ ["pe"]="quadruple",
+ ["ro"]="cvadrupul",
+ },
+ ["quotation"]={
+ ["cs"]="citace",
+ ["de"]="zitat",
+ ["en"]="quotation",
+ ["fr"]="citation",
+ ["it"]="citazione",
+ ["nl"]="citaat",
+ ["pe"]="نقلقول",
+ ["ro"]="citat",
+ },
+ ["quote"]={
+ ["cs"]="citovat",
+ ["de"]="zitieren",
+ ["en"]="quote",
+ ["fr"]="citer",
+ ["it"]="menzione",
+ ["nl"]="citeer",
+ ["pe"]="نقل",
+ ["ro"]="minicitat",
+ },
+ ["ran"]={
+ ["cs"]="rozsah",
+ ["de"]="ran",
+ ["en"]="ran",
+ ["fr"]="cours",
+ ["it"]="corse",
+ ["nl"]="ran",
+ ["pe"]="برد",
+ ["ro"]="rulat",
+ },
+ ["random"]={
+ ["cs"]="nahodny",
+ ["de"]="zufaellig",
+ ["en"]="random",
+ ["fr"]="aleatoire",
+ ["it"]="casuale",
+ ["nl"]="willekeurig",
+ ["pe"]="تصادفی",
+ ["ro"]="aleator",
+ },
+ ["readonly"]={
+ ["cs"]="pouzeprocteni",
+ ["de"]="nurlesbar",
+ ["en"]="readonly",
+ ["fr"]="lectureseule",
+ ["it"]="solalettura",
+ ["nl"]="alleenleesbaar",
+ ["pe"]="تنهاخواندنی",
+ ["ro"]="readonly",
+ },
+ ["rectangular"]={
+ ["cs"]="pravouhly",
+ ["de"]="rechteckig",
+ ["en"]="rectangular",
+ ["fr"]="rectangulaire",
+ ["it"]="rettangolare",
+ ["nl"]="recht",
+ ["pe"]="چهارگوشه",
+ ["ro"]="rectangular",
+ },
+ ["referral"]={
+ ["cs"]="znacka",
+ ["de"]="merkmal",
+ ["en"]="referral",
+ ["fr"]="referral",
+ ["it"]="referral",
+ ["nl"]="kenmerk",
+ ["pe"]="مراجعه",
+ ["ro"]="referinta",
+ },
+ ["register"]={
+ ["cs"]="rejstrik",
+ ["de"]="register",
+ ["en"]="register",
+ ["fr"]="registre",
+ ["it"]="registro",
+ ["nl"]="register",
+ ["pe"]="ثبت",
+ ["ro"]="registru",
+ },
+ ["regular"]={
+ ["cs"]="pravidelne",
+ ["de"]="regular",
+ ["en"]="regular",
+ ["fr"]="regulier",
+ ["it"]="regolare",
+ ["nl"]="regular",
+ ["pe"]="منظم",
+ ["ro"]="regular",
+ },
+ ["rekening"]={
+ ["cs"]="rekening",
+ ["de"]="rekening",
+ ["en"]="rekening",
+ ["fr"]="rekening",
+ ["it"]="rekening",
+ ["nl"]="rekening",
+ ["pe"]="rekening",
+ ["ro"]="rekening",
+ },
+ ["relative"]={
+ ["cs"]="relativni",
+ ["de"]="relativ",
+ ["en"]="relative",
+ ["fr"]="relatif",
+ ["it"]="relativo",
+ ["nl"]="relatief",
+ ["pe"]="نسبی",
+ ["ro"]="relativ",
+ },
+ ["repeat"]={
+ ["cs"]="opakovat",
+ ["de"]="wiederholen",
+ ["en"]="repeat",
+ ["fr"]="repete",
+ ["it"]="ripeti",
+ ["nl"]="herhaal",
+ ["pe"]="تکرار",
+ ["ro"]="repetat",
+ },
+ ["required"]={
+ ["cs"]="pozadovane",
+ ["de"]="obligatorisch",
+ ["en"]="required",
+ ["fr"]="recquis",
+ ["it"]="richiestp",
+ ["nl"]="verplicht",
+ ["pe"]="موردنیاز",
+ ["ro"]="obligatoriu",
+ },
+ ["reset"]={
+ ["cs"]="reset",
+ ["de"]="zuruecksetzten",
+ ["en"]="reset",
+ ["fr"]="raz",
+ ["it"]="reimposta",
+ ["nl"]="reset",
+ ["pe"]="بازنشانی",
+ ["ro"]="reset",
+ },
+ ["reverse"]={
+ ["cs"]="reverse",
+ ["de"]="reverse",
+ ["en"]="reverse",
+ ["fr"]="inverse",
+ ["it"]="invertito",
+ ["nl"]="omgekeerd",
+ ["pe"]="برعکس",
+ ["ro"]="reverse",
+ },
+ ["right"]={
+ ["cs"]="vpravo",
+ ["de"]="rechts",
+ ["en"]="right",
+ ["fr"]="droite",
+ ["it"]="destra",
+ ["nl"]="rechts",
+ ["pe"]="راست",
+ ["ro"]="dreapta",
+ },
+ ["rightedge"]={
+ ["cs"]="pravahrana",
+ ["de"]="rechterkante",
+ ["en"]="rightedge",
+ ["fr"]="borddroit",
+ ["it"]="bordodestro",
+ ["nl"]="rechterrand",
+ ["pe"]="لبهراست",
+ ["ro"]="borduradreapta",
+ },
+ ["righthanging"]={
+ ["cs"]="righthanging",
+ ["de"]="righthanging",
+ ["en"]="righthanging",
+ ["fr"]="righthanging",
+ ["it"]="righthanging",
+ ["nl"]="rechtshangend",
+ ["pe"]="آویزانکردنراست",
+ ["ro"]="righthanging",
+ },
+ ["rightmargin"]={
+ ["cs"]="pravyokraj",
+ ["de"]="rechterrand",
+ ["en"]="rightmargin",
+ ["fr"]="margedroite",
+ ["it"]="marginedestro",
+ ["nl"]="rechtermarge",
+ ["pe"]="حاشیهراست",
+ ["ro"]="marginedreapta",
+ },
+ ["rightpage"]={
+ ["cs"]="pravastranka",
+ ["de"]="rechterseite",
+ ["en"]="rightpage",
+ ["fr"]="pagedroite",
+ ["it"]="paginadestra",
+ ["nl"]="rechterpagina",
+ ["pe"]="صفحهراست",
+ ["ro"]="paginadreapta",
+ },
+ ["righttoleft"]={
+ ["cs"]="righttoleft",
+ ["de"]="righttoleft",
+ ["en"]="righttoleft",
+ ["fr"]="righttoleft",
+ ["it"]="righttoleft",
+ ["nl"]="righttoleft",
+ ["pe"]="righttoleft",
+ ["ro"]="righttoleft",
+ },
+ ["roman"]={
+ ["cs"]="antikva",
+ ["de"]="antiqua",
+ ["en"]="roman",
+ ["fr"]="roman",
+ ["it"]="roman",
+ ["nl"]="romaan",
+ ["pe"]="رومن",
+ ["ro"]="roman",
+ },
+ ["romannumerals"]={
+ ["cs"]="rimskecislice",
+ ["de"]="roemischezahlen",
+ ["en"]="romannumerals",
+ ["fr"]="chiffresromains",
+ ["it"]="numeriromani",
+ ["nl"]="romeins",
+ ["pe"]="شمارهلاتین",
+ ["ro"]="numereromane",
+ },
+ ["rotate"]={
+ ["cs"]="otoc",
+ ["de"]="drehe",
+ ["en"]="rotate",
+ ["fr"]="oriente",
+ ["it"]="ruota",
+ ["nl"]="roteer",
+ ["pe"]="دوران",
+ ["ro"]="rotit",
+ },
+ ["rotated"]={
+ ["cs"]="otoceno",
+ ["de"]="gedreht",
+ ["en"]="rotated",
+ ["fr"]="tourne",
+ ["it"]="ruotato",
+ ["nl"]="geroteerd",
+ ["pe"]="دورانیافته",
+ ["ro"]="rotat",
+ },
+ ["round"]={
+ ["cs"]="zaobleny",
+ ["de"]="rund",
+ ["en"]="round",
+ ["fr"]="rond",
+ ["it"]="rotondo",
+ ["nl"]="rond",
+ ["pe"]="گرد",
+ ["ro"]="rotund",
+ },
+ ["row"]={
+ ["cs"]="row",
+ ["de"]="row",
+ ["en"]="row",
+ ["fr"]="rang",
+ ["it"]="row",
+ ["nl"]="rij",
+ ["pe"]="سطر",
+ ["ro"]="rand",
+ },
+ ["rule"]={
+ ["cs"]="linka",
+ ["de"]="linie",
+ ["en"]="rule",
+ ["fr"]="regle",
+ ["it"]="linea",
+ ["nl"]="lijn",
+ ["pe"]="خط",
+ ["ro"]="rigla",
+ },
+ ["samepage"]={
+ ["cs"]="stejnastranka",
+ ["de"]="selbeseite",
+ ["en"]="samepage",
+ ["fr"]="memepage",
+ ["it"]="stessapagina",
+ ["nl"]="zelfdepagina",
+ ["pe"]="همانصفحه",
+ ["ro"]="aceeasipagina",
+ },
+ ["sans"]={
+ ["cs"]="sans",
+ ["de"]="sans",
+ ["en"]="sans",
+ ["fr"]="sans",
+ ["it"]="sans",
+ ["nl"]="sans",
+ ["pe"]="سانز",
+ ["ro"]="sans",
+ },
+ ["sansbold"]={
+ ["cs"]="sanstucne",
+ ["de"]="sansfett",
+ ["en"]="sansbold",
+ ["fr"]="sansgras",
+ ["it"]="sansgrassetto",
+ ["nl"]="sansvet",
+ ["pe"]="مشکیسانز",
+ ["ro"]="sansaldin",
+ },
+ ["sansserif"]={
+ ["cs"]="bezserifu",
+ ["de"]="grotesk",
+ ["en"]="sansserif",
+ ["fr"]="sansserif",
+ ["it"]="sansserif",
+ ["nl"]="schreefloos",
+ ["pe"]="سانزسریف",
+ ["ro"]="sansserif",
+ },
+ ["saturday"]={
+ ["cs"]="sobota",
+ ["de"]="samstag",
+ ["en"]="saturday",
+ ["fr"]="samedi",
+ ["it"]="sabato",
+ ["nl"]="zaterdag",
+ ["pe"]="شنبه",
+ ["ro"]="sambata",
+ },
+ ["screen"]={
+ ["cs"]="rastr",
+ ["de"]="raster",
+ ["en"]="screen",
+ ["fr"]="ecran",
+ ["it"]="schermo",
+ ["nl"]="raster",
+ ["pe"]="پرده",
+ ["ro"]="ecran",
+ },
+ ["section"]={
+ ["cs"]="sekce",
+ ["de"]="absatz",
+ ["en"]="section",
+ ["fr"]="section",
+ ["it"]="capoverso",
+ ["nl"]="paragraaf",
+ ["pe"]="بخش",
+ ["ro"]="sectiune",
+ },
+ ["sectionblockenvironment"]={
+ ["cs"]="sectionblockenvironment",
+ ["de"]="sectionblockenvironment",
+ ["en"]="sectionblockenvironment",
+ ["fr"]="environementblocsection",
+ ["it"]="ambientebloccosezione",
+ ["nl"]="sectieblokomgeving",
+ ["pe"]="محیطبلوکبخش",
+ ["ro"]="blocsectiuneambient",
+ },
+ ["sectionnumber"]={
+ ["cs"]="cislooddilu",
+ ["de"]="abschnittsnummer",
+ ["en"]="sectionnumber",
+ ["fr"]="numerosection",
+ ["it"]="numerosezione",
+ ["nl"]="sectienummer",
+ ["pe"]="شمارهبخش",
+ ["ro"]="numarsetiune",
+ },
+ ["see"]={
+ ["cs"]="viz",
+ ["de"]="sieh",
+ ["en"]="see",
+ ["fr"]="voit",
+ ["it"]="vedi",
+ ["nl"]="zie",
+ ["pe"]="ببینید",
+ ["ro"]="vezi",
+ },
+ ["september"]={
+ ["cs"]="zari",
+ ["de"]="September",
+ ["en"]="September",
+ ["fr"]="septembre",
+ ["it"]="settembre",
+ ["nl"]="september",
+ ["pe"]="سپتامبر",
+ ["ro"]="septembrie",
+ },
+ ["serif"]={
+ ["cs"]="serif",
+ ["de"]="serif",
+ ["en"]="serif",
+ ["fr"]="serif",
+ ["it"]="serif",
+ ["nl"]="serif",
+ ["pe"]="سریف",
+ ["ro"]="serif",
+ },
+ ["serried"]={
+ ["cs"]="semknuto",
+ ["de"]="kleinerabstand",
+ ["en"]="serried",
+ ["fr"]="serried",
+ ["it"]="vicino",
+ ["nl"]="aanelkaar",
+ ["pe"]="تنگهم",
+ ["ro"]="serried",
+ },
+ ["setups"]={
+ ["cs"]="einstellungen",
+ ["de"]="impostazioni",
+ ["en"]="setups",
+ ["fr"]="reglages",
+ ["it"]="nastaveni",
+ ["nl"]="instellingen",
+ ["pe"]="بارگذاریها",
+ ["ro"]="setari",
+ },
+ ["sheet"]={
+ ["cs"]="sheet",
+ ["de"]="sheet",
+ ["en"]="sheet",
+ ["fr"]="sheet",
+ ["it"]="sheet",
+ ["nl"]="sheet",
+ ["pe"]="ورقه",
+ ["ro"]="sheet",
+ },
+ ["singlesided"]={
+ ["cs"]="jednostranne",
+ ["de"]="einzelseitig",
+ ["en"]="singlesided",
+ ["fr"]="recto",
+ ["it"]="facciasingola",
+ ["nl"]="enkelzijdig",
+ ["pe"]="یکرو",
+ ["ro"]="ofata",
+ },
+ ["slanted"]={
+ ["cs"]="sklonene",
+ ["de"]="geneigt",
+ ["en"]="slanted",
+ ["fr"]="incline",
+ ["it"]="inclinato",
+ ["nl"]="schuin",
+ ["pe"]="خوابیده",
+ ["ro"]="inclinat",
+ },
+ ["slantedbold"]={
+ ["cs"]="sklonenetucne",
+ ["de"]="geneigtfett",
+ ["en"]="slantedbold",
+ ["fr"]="grasincline",
+ ["it"]="inclinatograssetto",
+ ["nl"]="schuinvet",
+ ["pe"]="مشکیخوابیده",
+ ["ro"]="inclinataldin",
+ },
+ ["small"]={
+ ["cs"]="male",
+ ["de"]="klein",
+ ["en"]="small",
+ ["fr"]="petit",
+ ["it"]="piccolo",
+ ["nl"]="klein",
+ ["pe"]="کوچک",
+ ["ro"]="mic",
+ },
+ ["smallbodyfont"]={
+ ["cs"]="smallbodyfont",
+ ["de"]="smallbodyfont",
+ ["en"]="smallbodyfont",
+ ["fr"]="petitepolicecorps",
+ ["it"]="piccolofontdelcorpo",
+ ["nl"]="kleinkorps",
+ ["pe"]="قلمبدنهکوچک",
+ ["ro"]="smallbodyfont",
+ },
+ ["smallbold"]={
+ ["cs"]="maletucne",
+ ["de"]="kleinfett",
+ ["en"]="smallbold",
+ ["fr"]="graspetit",
+ ["it"]="piccolograssetto",
+ ["nl"]="kleinvet",
+ ["pe"]="مشکیکوچک",
+ ["ro"]="micaldin",
+ },
+ ["smallbolditalic"]={
+ ["cs"]="maletucnekurzivni",
+ ["de"]="kleinfettitalic",
+ ["en"]="smallbolditalic",
+ ["fr"]="italiquegraspetit",
+ ["it"]="piccolograssettocorsivo",
+ ["nl"]="kleinvetitalic",
+ ["pe"]="ایتالیکمشکیکوچک",
+ ["ro"]="micaldininclinat",
+ },
+ ["smallboldslanted"]={
+ ["cs"]="maletucnesklonene",
+ ["de"]="kleinfettgeneigt",
+ ["en"]="smallboldslanted",
+ ["fr"]="inclinegraspetit",
+ ["it"]="piccolograssettoinclinato",
+ ["nl"]="kleinvetschuin",
+ ["pe"]="خوابیدهمشکیکوچک",
+ ["ro"]="micaldininclinat",
+ },
+ ["smallcaps"]={
+ ["cs"]="kapitalky",
+ ["de"]="smallcaps",
+ ["en"]="smallcaps",
+ ["fr"]="petitescapitales",
+ ["it"]="maiuscoletto",
+ ["nl"]="smallcaps",
+ ["pe"]="smallcaps",
+ ["ro"]="majusculemici",
+ },
+ ["smallitalic"]={
+ ["cs"]="malekurzivni",
+ ["de"]="kleinitalic",
+ ["en"]="smallitalic",
+ ["fr"]="italiquepetit",
+ ["it"]="piccolocorsivo",
+ ["nl"]="kleinitalic",
+ ["pe"]="ایتالیککوچک",
+ ["ro"]="micitalic",
+ },
+ ["smallitalicbold"]={
+ ["cs"]="malekurzivnitucne",
+ ["de"]="kleinitalicfett",
+ ["en"]="smallitalicbold",
+ ["fr"]="grasitaliquepetit",
+ ["it"]="piccolocorsivograssetto",
+ ["nl"]="kleinitalicvet",
+ ["pe"]="مشکیایتالیککوچک",
+ ["ro"]="micitalicaldin",
+ },
+ ["smallnormal"]={
+ ["cs"]="malenormalni",
+ ["de"]="kleinnormal",
+ ["en"]="smallnormal",
+ ["fr"]="normalpetit",
+ ["it"]="piccolonormale",
+ ["nl"]="kleinnormaal",
+ ["pe"]="نرمالکوچک",
+ ["ro"]="micnormal",
+ },
+ ["smallslanted"]={
+ ["cs"]="malesklonene",
+ ["de"]="kleingeneigt",
+ ["en"]="smallslanted",
+ ["fr"]="inclinepetit",
+ ["it"]="piccoloinclinato",
+ ["nl"]="kleinschuin",
+ ["pe"]="خوابیدهکوچک",
+ ["ro"]="micinclinat",
+ },
+ ["smallslantedbold"]={
+ ["cs"]="malesklonenetucne",
+ ["de"]="kleingeneigtfett",
+ ["en"]="smallslantedbold",
+ ["fr"]="grasinclinepetit",
+ ["it"]="piccoloinclinatograssetto",
+ ["nl"]="kleinschuinvet",
+ ["pe"]="مشکیخوابیدهکوچک",
+ ["ro"]="micinclinataldin",
+ },
+ ["smalltype"]={
+ ["cs"]="maletype",
+ ["de"]="kleintippen",
+ ["en"]="smalltype",
+ ["fr"]="petittype",
+ ["it"]="piccolotype",
+ ["nl"]="kleintype",
+ ["pe"]="تایپکوچک",
+ ["ro"]="mictype",
+ },
+ ["somewhere"]={
+ ["cs"]="nekde",
+ ["de"]="irgendwo",
+ ["en"]="somewhere",
+ ["fr"]="qqpart",
+ ["it"]="daqualcheparte",
+ ["nl"]="ergens",
+ ["pe"]="جایی",
+ ["ro"]="undeva",
+ },
+ ["sorted"]={
+ ["cs"]="tridene",
+ ["de"]="sortiert",
+ ["en"]="sorted",
+ ["fr"]="trie",
+ ["it"]="ordinato",
+ ["nl"]="gesorteerd",
+ ["pe"]="مرتب",
+ ["ro"]="sortat",
+ },
+ ["space"]={
+ ["cs"]="mezera",
+ ["de"]="spatium",
+ ["en"]="space",
+ ["fr"]="espace",
+ ["it"]="spazio",
+ ["nl"]="spatie",
+ ["pe"]="فضا",
+ ["ro"]="spatiu",
+ },
+ ["spacing"]={
+ ["cs"]="mezerovani",
+ ["de"]="spatiumausgleich",
+ ["en"]="spacing",
+ ["fr"]="espacement",
+ ["it"]="spaziatura",
+ ["nl"]="spatiering",
+ ["pe"]="فضاگذاری",
+ ["ro"]="spatiere",
+ },
+ ["speech"]={
+ ["cs"]="speech",
+ ["de"]="speech",
+ ["en"]="speech",
+ ["fr"]="discours",
+ ["it"]="speech",
+ ["nl"]="spraak",
+ ["pe"]="سخنرانی",
+ ["ro"]="speech",
+ },
+ ["split"]={
+ ["cs"]="split",
+ ["de"]="split",
+ ["en"]="split",
+ ["fr"]="split",
+ ["it"]="separa",
+ ["nl"]="splitsen",
+ ["pe"]="شکافتن",
+ ["ro"]="split",
+ },
+ ["spot"]={
+ ["cs"]="spot",
+ ["de"]="spot",
+ ["en"]="spot",
+ ["fr"]="spot",
+ ["it"]="spot",
+ ["nl"]="spot",
+ ["pe"]="لکه",
+ ["ro"]="spot",
+ },
+ ["standard"]={
+ ["cs"]="standardni",
+ ["de"]="standard",
+ ["en"]="standard",
+ ["fr"]="standard",
+ ["it"]="standard",
+ ["nl"]="standaard",
+ ["pe"]="استاندارد",
+ ["ro"]="standard",
+ },
+ ["start"]={
+ ["cs"]="start",
+ ["de"]="start",
+ ["en"]="start",
+ ["fr"]="demarre",
+ ["it"]="inizia",
+ ["nl"]="start",
+ ["pe"]="شروع",
+ ["ro"]="start",
+ },
+ ["sticker"]={
+ ["cs"]="sticker",
+ ["de"]="sticker",
+ ["en"]="sticker",
+ ["fr"]="sticker",
+ ["it"]="sticker",
+ ["nl"]="sticker",
+ ["pe"]="دشنه",
+ ["ro"]="sticker",
+ },
+ ["stop"]={
+ ["cs"]="stop",
+ ["de"]="stop",
+ ["en"]="stop",
+ ["fr"]="stoppe",
+ ["it"]="termina",
+ ["nl"]="stop",
+ ["pe"]="پایان",
+ ["ro"]="stop",
+ },
+ ["stopper"]={
+ ["cs"]="predel",
+ ["de"]="trenner",
+ ["en"]="stopper",
+ ["fr"]="stopper",
+ ["it"]="stopper",
+ ["nl"]="afsluiter",
+ ["pe"]="ایست",
+ ["ro"]="stopper",
+ },
+ ["starter"]={
+ ["en"]="starter",
+ ["nl"]="opener",
+ },
+ ["stretch"]={
+ ["cs"]="natahnout",
+ ["de"]="strecken",
+ ["en"]="stretch",
+ ["fr"]="etire",
+ ["it"]="dilata",
+ ["nl"]="rek",
+ ["pe"]="بکش",
+ ["ro"]="dilatat",
+ },
+ ["strict"]={
+ ["cs"]="striktni",
+ ["de"]="streng",
+ ["en"]="strict",
+ ["fr"]="strict",
+ ["it"]="rigido",
+ ["nl"]="streng",
+ ["pe"]="اکید",
+ ["ro"]="strict",
+ },
+ ["strong"]={
+ ["cs"]="strong",
+ ["de"]="strong",
+ ["en"]="strong",
+ ["fr"]="strong",
+ ["it"]="strong",
+ ["nl"]="sterk",
+ ["pe"]="محکم",
+ ["ro"]="strong",
+ },
+ ["strut"]={
+ ["cs"]="strut",
+ ["de"]="strut",
+ ["en"]="strut",
+ ["fr"]="strut",
+ ["it"]="strut",
+ ["nl"]="strut",
+ ["pe"]="بست",
+ ["ro"]="strut",
+ },
+ ["sub"]={
+ ["cs"]="pod",
+ ["de"]="unter",
+ ["en"]="sub",
+ ["fr"]="sous",
+ ["it"]="sotto",
+ ["nl"]="sub",
+ ["pe"]="زیر",
+ ["ro"]="sub",
+ },
+ ["subbackward"]={
+ ["cs"]="podzpet",
+ ["de"]="unterrueckwaerts",
+ ["en"]="subbackward",
+ ["fr"]="sousretourarriere",
+ ["it"]="sottoindietro",
+ ["nl"]="subachteruit",
+ ["pe"]="زیرعقبگرد",
+ ["ro"]="subinapoi",
+ },
+ ["subformula"]={
+ ["cs"]="subrovnice",
+ ["de"]="subformel",
+ ["en"]="subformula",
+ ["fr"]="subformule",
+ ["it"]="subformula",
+ ["nl"]="subformule",
+ ["pe"]="زیرفرمول",
+ ["ro"]="subformula",
+ },
+ ["subforward"]={
+ ["cs"]="podvpred",
+ ["de"]="untervorwaerts",
+ ["en"]="subforward",
+ ["fr"]="sousavance",
+ ["it"]="sottoavanti",
+ ["nl"]="subvooruit",
+ ["pe"]="زیرجلوگرد",
+ ["ro"]="subavans",
+ },
+ ["subject"]={
+ ["cs"]="tema",
+ ["de"]="thema",
+ ["en"]="subject",
+ ["fr"]="sujet",
+ ["it"]="argomento",
+ ["nl"]="onderwerp",
+ ["pe"]="موضوع",
+ ["ro"]="subiect",
+ },
+ ["subpage"]={
+ ["cs"]="podstranka",
+ ["de"]="unterseite",
+ ["en"]="subpage",
+ ["fr"]="souspage",
+ ["it"]="sottopagina",
+ ["nl"]="subpagina",
+ ["pe"]="زیرصفحه",
+ ["ro"]="subpagina",
+ },
+ ["subsection"]={
+ ["cs"]="podsekce",
+ ["de"]="unterabsatz",
+ ["en"]="subsection",
+ ["fr"]="soussection",
+ ["it"]="sottocapoverso",
+ ["nl"]="subparagraaf",
+ ["pe"]="زیربخش",
+ ["ro"]="subsectiune",
+ },
+ ["subsubject"]={
+ ["cs"]="podtema",
+ ["de"]="unterthema",
+ ["en"]="subsubject",
+ ["fr"]="soussujet",
+ ["it"]="sottoargomento",
+ ["nl"]="subonderwerp",
+ ["pe"]="زیرموضوع",
+ ["ro"]="subsubiect",
+ },
+ ["subsubsection"]={
+ ["cs"]="podpodsekce",
+ ["de"]="unterunterabsatz",
+ ["en"]="subsubsection",
+ ["fr"]="soussoussection",
+ ["it"]="sottosottocapoverso",
+ ["nl"]="subsubparagraaf",
+ ["pe"]="زیرزیربخش",
+ ["ro"]="subsubsectiune",
+ },
+ ["subsubsubject"]={
+ ["cs"]="podpodtema",
+ ["de"]="unterunterthema",
+ ["en"]="subsubsubject",
+ ["fr"]="soussoussujet",
+ ["it"]="sottosottoargomento",
+ ["nl"]="subsubonderwerp",
+ ["pe"]="زیرزیرموضوع",
+ ["ro"]="subsubsubiect",
+ },
+ ["subsubsubsection"]={
+ ["cs"]="podpodpodsekce",
+ ["de"]="unterunterunterabsatz",
+ ["en"]="subsubsubsection",
+ ["fr"]="soussoussoussection",
+ ["it"]="sottosottosottocapoverso",
+ ["nl"]="subsubsubparagraaf",
+ ["pe"]="زیرزیرزیربخش",
+ ["ro"]="subsubsubsectiune",
+ },
+ ["subsubsubsubject"]={
+ ["cs"]="podpodpodtema",
+ ["de"]="unterunterunterthema",
+ ["en"]="subsubsubsubject",
+ ["fr"]="soussoussoussujet",
+ ["it"]="sottosottosottoargomento",
+ ["nl"]="subsubsubonderwerp",
+ ["pe"]="زیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubiect",
+ },
+ ["subsubsubsubsection"]={
+ ["cs"]="podpodpodpodsekce",
+ ["de"]="unterunterunterunterabsatz",
+ ["en"]="subsubsubsubsection",
+ ["fr"]="soussoussoussoussection",
+ ["it"]="sottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsectiune",
+ },
+ ["subsubsubsubsubject"]={
+ ["cs"]="podpodpodpodtema",
+ ["de"]="unterunterunterunterthema",
+ ["en"]="subsubsubsubsubject",
+ ["fr"]="soussoussoussoussujet",
+ ["it"]="sottosottosottosottoargomento",
+ ["nl"]="subsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubsubsubiect",
+ },
+ ["subsubsubsubsubsubsubsubsubsection"]={
+ ["cs"]="podpodpodpodpodpodpodpodpodsekce",
+ ["de"]="unterunterunterunterunterunterunterunterunterabsatz",
+ ["en"]="subsubsubsubsubsubsubsubsubsection",
+ ["fr"]="soussoussoussoussoussoussoussoussoussection",
+ ["it"]="sottosottosottosottosottosottosottosottosottocapoverso",
+ ["nl"]="subsubsubsubsubsubsubsubsubparagraaf",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیربخش",
+ ["ro"]="subsubsubsubsubsubsubsubsubsectiune",
+ },
+ ["subsubsubsubsubsubsubsubsubsubject"]={
+ ["cs"]="podpodpodpodpodpodpodpodpodtema",
+ ["de"]="unterunterunterunterunterunterunterunterunterthema",
+ ["en"]="subsubsubsubsubsubsubsubsubsubject",
+ ["fr"]="soussoussoussoussoussoussoussoussoussujet",
+ ["it"]="sottosottosottosottosottosottosottosottosottoargomento",
+ ["nl"]="subsubsubsubsubsubsubsubsubonderwerp",
+ ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیرموضوع",
+ ["ro"]="subsubsubsubsubsubsubsubsubsubiect",
+ },
+ ["sunday"]={
+ ["cs"]="nedele",
+ ["de"]="sonntag",
+ ["en"]="sunday",
+ ["fr"]="dimanche",
+ ["it"]="domenica",
+ ["nl"]="zondag",
+ ["pe"]="یکشنبه",
+ ["ro"]="duminica",
+ },
+ ["support"]={
+ ["cs"]="podpora",
+ ["de"]="support",
+ ["en"]="support",
+ ["fr"]="support",
+ ["it"]="supporto",
+ ["nl"]="support",
+ ["pe"]="حمایت",
+ ["ro"]="suport",
+ },
+ ["sym"]={
+ ["cs"]="sym",
+ ["de"]="sym",
+ ["en"]="sym",
+ ["fr"]="sym",
+ ["it"]="sim",
+ ["nl"]="sym",
+ ["pe"]="نم",
+ ["ro"]="sym",
+ },
+ ["symbol"]={
+ ["cs"]="symbol",
+ ["de"]="symbol",
+ ["en"]="symbol",
+ ["fr"]="symbole",
+ ["it"]="simbolo",
+ ["nl"]="symbool",
+ ["pe"]="نماد",
+ ["ro"]="simbol",
+ },
+ ["synchronize"]={
+ ["cs"]="synchronize",
+ ["de"]="synchronize",
+ ["en"]="synchronize",
+ ["fr"]="synchronize",
+ ["it"]="synchronize",
+ ["nl"]="synchroniseer",
+ ["pe"]="تطابق",
+ ["ro"]="synchronize",
+ },
+ ["system"]={
+ ["cs"]="system",
+ ["de"]="systeme",
+ ["en"]="system",
+ ["fr"]="systeme",
+ ["it"]="sistema",
+ ["nl"]="systeem",
+ ["pe"]="سیستم",
+ ["ro"]="sistem",
+ },
+ ["table"]={
+ ["cs"]="tabulka",
+ ["de"]="tabelle",
+ ["en"]="table",
+ ["fr"]="tableau",
+ ["it"]="tabella",
+ ["nl"]="tabel",
+ ["pe"]="جدول",
+ ["ro"]="tabelul",
+ },
+ ["tablehead"]={
+ ["cs"]="zahlavitabulky",
+ ["de"]="tabellenueberschrift",
+ ["en"]="tablehead",
+ ["fr"]="tetetableau",
+ ["it"]="testatabella",
+ ["nl"]="tabelkop",
+ ["pe"]="سرجدول",
+ ["ro"]="antettabel",
+ },
+ ["tables"]={
+ ["cs"]="tabulky",
+ ["de"]="tabellen",
+ ["en"]="tables",
+ ["fr"]="tables",
+ ["it"]="tabelle",
+ ["nl"]="tabellen",
+ ["pe"]="جدولها",
+ ["ro"]="tabelele",
+ },
+ ["tabletail"]={
+ ["cs"]="konectabulky",
+ ["de"]="tabellenende",
+ ["en"]="tabletail",
+ ["fr"]="queuetableau",
+ ["it"]="codatabella",
+ ["nl"]="tabelstaart",
+ ["pe"]="دنبالهجدول",
+ ["ro"]="subsoltabel",
+ },
+ ["tabulate"]={
+ ["cs"]="tabelator",
+ ["de"]="tabulator",
+ ["en"]="tabulate",
+ ["fr"]="tabule",
+ ["it"]="tabulato",
+ ["nl"]="tabulatie",
+ ["pe"]="جدولبندی",
+ ["ro"]="tabulate",
+ },
+ ["tabulatehead"]={
+ ["cs"]="tabulatehead",
+ ["de"]="tabulatehead",
+ ["en"]="tabulatehead",
+ ["fr"]="tetetabule",
+ ["it"]="testatabulato",
+ ["nl"]="tabulatiekop",
+ ["pe"]="سرجدولبندی",
+ ["ro"]="tabulatehead",
+ },
+ ["tabulatetail"]={
+ ["cs"]="tabulatetail",
+ ["de"]="tabulatetail",
+ ["en"]="tabulatetail",
+ ["fr"]="queuetabule",
+ ["it"]="codatabulato",
+ ["nl"]="tabulatiestaart",
+ ["pe"]="دنبالهجدولبندی",
+ ["ro"]="tabulatetail",
+ },
+ ["tall"]={
+ ["cs"]="vysoko",
+ ["de"]="lang",
+ ["en"]="tall",
+ ["fr"]="long",
+ ["it"]="alto",
+ ["nl"]="lang",
+ ["pe"]="دراز",
+ ["ro"]="inalt",
+ },
+ ["teletype"]={
+ ["cs"]="strojopis",
+ ["de"]="fernschreiber",
+ ["en"]="teletype",
+ ["fr"]="teletype",
+ ["it"]="teletype",
+ ["nl"]="teletype",
+ ["pe"]="دورنگاره",
+ ["ro"]="teletype",
+ },
+ ["temporary"]={
+ ["cs"]="docasne",
+ ["de"]="temporaer",
+ ["en"]="temporary",
+ ["fr"]="temporaire",
+ ["it"]="temporaneo",
+ ["nl"]="voorlopig",
+ ["pe"]="موقتی",
+ ["ro"]="temporar",
+ },
+ ["test"]={
+ ["cs"]="test",
+ ["de"]="test",
+ ["en"]="test",
+ ["fr"]="test",
+ ["it"]="test",
+ ["nl"]="test",
+ ["pe"]="تست",
+ ["ro"]="test",
+ },
+ ["text"]={
+ ["cs"]="text",
+ ["de"]="text",
+ ["en"]="text",
+ ["fr"]="texte",
+ ["it"]="testo",
+ ["nl"]="tekst",
+ ["pe"]="متن",
+ ["ro"]="text",
+ },
+ ["three"]={
+ ["cs"]="tri",
+ ["de"]="drei",
+ ["en"]="three",
+ ["fr"]="trois",
+ ["it"]="tre",
+ ["nl"]="drie",
+ ["pe"]="سه",
+ ["ro"]="trei",
+ },
+ ["thursday"]={
+ ["cs"]="ctvrtek",
+ ["de"]="donnerstag",
+ ["en"]="thursday",
+ ["fr"]="jeudi",
+ ["it"]="giovedi",
+ ["nl"]="donderdag",
+ ["pe"]="پنجشنبه",
+ ["ro"]="joi",
+ },
+ ["title"]={
+ ["cs"]="titul",
+ ["de"]="titel",
+ ["en"]="title",
+ ["fr"]="titre",
+ ["it"]="titolo",
+ ["nl"]="titel",
+ ["pe"]="عنوان",
+ ["ro"]="titlu",
+ },
+ ["toggle"]={
+ ["cs"]="toggle",
+ ["de"]="toggle",
+ ["en"]="wissel",
+ ["fr"]="toggle",
+ ["it"]="toggle",
+ ["nl"]="toggle",
+ ["pe"]="تغییر",
+ ["ro"]="toggle",
+ },
+ ["tolerant"]={
+ ["cs"]="tolerantni",
+ ["de"]="tolerant",
+ ["en"]="tolerant",
+ ["fr"]="tolerant",
+ ["it"]="tollerante",
+ ["nl"]="soepel",
+ ["pe"]="بردبار",
+ ["ro"]="tolerant",
+ },
+ ["top"]={
+ ["cs"]="vrsek",
+ ["de"]="oben",
+ ["en"]="top",
+ ["fr"]="sup",
+ ["it"]="cima",
+ ["nl"]="boven",
+ ["pe"]="بالا",
+ ["ro"]="sus",
+ },
+ ["tuesday"]={
+ ["cs"]="utery",
+ ["de"]="dienstag",
+ ["en"]="tuesday",
+ ["fr"]="mardi",
+ ["it"]="martedi",
+ ["nl"]="dinsdag",
+ ["pe"]="سهشنبه",
+ ["ro"]="marti",
+ },
+ ["two"]={
+ ["cs"]="dve",
+ ["de"]="zwei",
+ ["en"]="two",
+ ["fr"]="deux",
+ ["it"]="due",
+ ["nl"]="twee",
+ ["pe"]="دو",
+ ["ro"]="doi",
+ },
+ ["txt"]={
+ ["cs"]="txt",
+ ["de"]="txt",
+ ["en"]="txt",
+ ["fr"]="txt",
+ ["it"]="txt",
+ ["nl"]="txt",
+ ["pe"]="txt",
+ ["ro"]="txt",
+ },
+ ["type"]={
+ ["cs"]="opis",
+ ["de"]="tippen",
+ ["en"]="type",
+ ["fr"]="type",
+ ["it"]="type",
+ ["nl"]="type",
+ ["pe"]="تایپ",
+ ["ro"]="type",
+ },
+ ["typing"]={
+ ["cs"]="typing",
+ ["de"]="tippen",
+ ["en"]="typing",
+ ["fr"]="typing",
+ ["it"]="typing",
+ ["nl"]="typen",
+ ["pe"]="تایپکردن",
+ ["ro"]="typing",
+ },
+ ["unavailable"]={
+ ["cs"]="nedostupne",
+ ["de"]="nichtverfuegbar",
+ ["en"]="unavailable",
+ ["fr"]="indisponible",
+ ["it"]="nondisponibile",
+ ["nl"]="nietbeschikbaar",
+ ["pe"]="غیرموجود",
+ ["ro"]="nedisponibil",
+ },
+ ["unit"]={
+ ["cs"]="jednotka",
+ ["de"]="einheit",
+ ["en"]="unit",
+ ["fr"]="unite",
+ ["it"]="unita",
+ ["nl"]="eenheid",
+ ["pe"]="واحد",
+ ["ro"]="unitate",
+ },
+ ["units"]={
+ ["cs"]="jednotky",
+ ["de"]="einheiten",
+ ["en"]="units",
+ ["fr"]="unites",
+ ["it"]="unita",
+ ["nl"]="eenheden",
+ ["pe"]="واحدها",
+ ["ro"]="unitati",
+ },
+ ["unknown"]={
+ ["cs"]="neznamy",
+ ["de"]="unbekannt",
+ ["en"]="unknown",
+ ["fr"]="inconnu",
+ ["it"]="ignoto",
+ ["nl"]="onbekend",
+ ["pe"]="ناشناس",
+ ["ro"]="necunoscut",
+ },
+ ["unpacked"]={
+ ["cs"]="rozbalene",
+ ["de"]="ungepackt",
+ ["en"]="unpacked",
+ ["fr"]="degroupe",
+ ["it"]="unpacked",
+ ["nl"]="vanelkaar",
+ ["pe"]="غیرفشرده",
+ ["ro"]="despachetat",
+ },
+ ["url"]={
+ ["cs"]="url",
+ ["de"]="url",
+ ["en"]="url",
+ ["fr"]="url",
+ ["it"]="url",
+ ["nl"]="url",
+ ["pe"]="url",
+ ["ro"]="url",
+ },
+ ["used"]={
+ ["cs"]="uzito",
+ ["de"]="verwende",
+ ["en"]="used",
+ ["fr"]="used",
+ ["it"]="usato",
+ ["nl"]="gebruikt",
+ ["pe"]="استفادهشده",
+ ["ro"]="folosit",
+ },
+ ["value"]={
+ ["cs"]="hodnota",
+ ["de"]="wert",
+ ["en"]="value",
+ ["fr"]="valeur",
+ ["it"]="valore",
+ ["nl"]="waarde",
+ ["pe"]="مقدار",
+ ["ro"]="valoare",
+ },
+ ["vertical"]={
+ ["cs"]="vertikalne",
+ ["de"]="vertikal",
+ ["en"]="vertical",
+ ["fr"]="verticale",
+ ["it"]="verticale",
+ ["nl"]="vertikaal",
+ ["pe"]="عمودی",
+ ["ro"]="vertical",
+ },
+ ["very"]={
+ ["cs"]="velmi",
+ ["de"]="sehr",
+ ["en"]="very",
+ ["fr"]="tres",
+ ["it"]="molto",
+ ["nl"]="zeer",
+ ["pe"]="خیلی",
+ ["ro"]="foarte",
+ },
+ ["verystrict"]={
+ ["cs"]="velmistriktni",
+ ["de"]="sehrstreng",
+ ["en"]="verystrict",
+ ["fr"]="tresstrict",
+ ["it"]="moltorigido",
+ ["nl"]="zeerstreng",
+ ["pe"]="خیلیسختگیر",
+ ["ro"]="foartestrict",
+ },
+ ["verytolerant"]={
+ ["cs"]="velmitolerantni",
+ ["de"]="sehrtolerant",
+ ["en"]="verytolerant",
+ ["fr"]="trestolerant",
+ ["it"]="moltotollerante",
+ ["nl"]="zeersoepel",
+ ["pe"]="خیلیبردبار",
+ ["ro"]="foartetolerant",
+ },
+ ["weak"]={
+ ["cs"]="weak",
+ ["de"]="weak",
+ ["en"]="weak",
+ ["fr"]="weak",
+ ["it"]="weak",
+ ["nl"]="zwak",
+ ["pe"]="هفته",
+ ["ro"]="weak",
+ },
+ ["wednesday"]={
+ ["cs"]="streda",
+ ["de"]="mittwoch",
+ ["en"]="wednesday",
+ ["fr"]="mercredi",
+ ["it"]="mercoledi",
+ ["nl"]="woensdag",
+ ["pe"]="چهارشنبه",
+ ["ro"]="miercuri",
+ },
+ ["week"]={
+ ["cs"]="tyden",
+ ["de"]="woche",
+ ["en"]="week",
+ ["fr"]="semaine",
+ ["it"]="settimana",
+ ["nl"]="week",
+ ["pe"]="هفته",
+ ["ro"]="saptamana",
+ },
+ ["weekday"]={
+ ["cs"]="vsedniden",
+ ["de"]="wochentag",
+ ["en"]="weekday",
+ ["fr"]="joursemaine",
+ ["it"]="giornosettimana",
+ ["nl"]="weekdag",
+ ["pe"]="روزهفته",
+ ["ro"]="zisaptamana",
+ },
+ ["white"]={
+ ["cs"]="bily",
+ ["de"]="weiss",
+ ["en"]="white",
+ ["fr"]="blanc",
+ ["it"]="bianco",
+ ["nl"]="wit",
+ ["pe"]="سفید",
+ ["ro"]="alb",
+ },
+ ["wide"]={
+ ["cs"]="siroce",
+ ["de"]="breit",
+ ["en"]="wide",
+ ["fr"]="ample",
+ ["it"]="ampio",
+ ["nl"]="breed",
+ ["pe"]="گسترده",
+ ["ro"]="larg",
+ },
+ ["width"]={
+ ["cs"]="sirka",
+ ["de"]="breite",
+ ["en"]="width",
+ ["fr"]="largeur",
+ ["it"]="ampiezza",
+ ["nl"]="breedte",
+ ["pe"]="عرض",
+ ["ro"]="latime",
+ },
+ ["xml"]={
+ ["cs"]="xml",
+ ["de"]="xml",
+ ["en"]="xml",
+ ["fr"]="xml",
+ ["it"]="xml",
+ ["nl"]="xml",
+ ["pe"]="xml",
+ ["ro"]="xml",
+ },
+ ["year"]={
+ ["cs"]="rok",
+ ["de"]="jahr",
+ ["en"]="year",
+ ["fr"]="annee",
+ ["it"]="anno",
+ ["nl"]="jaar",
+ ["pe"]="سال",
+ ["ro"]="an",
+ },
+ ["yes"]={
+ ["cs"]="ano",
+ ["de"]="ja",
+ ["en"]="yes",
+ ["fr"]="oui",
+ ["it"]="si",
+ ["nl"]="ja",
+ ["pe"]="بله",
+ ["ro"]="da",
+ },
+ },
+}
diff --git a/tex/context/base/mult-def.tex b/tex/context/base/mult-def.tex
new file mode 100644
index 000000000..cff9fb074
--- /dev/null
+++ b/tex/context/base/mult-def.tex
@@ -0,0 +1,35 @@
+%D \module
+%D [ file=mult-def,
+%D version=2008.10.22,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Definitions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
+
+\setvalue{@interface@czech@}{cs}
+\setvalue{@interface@german@}{de}
+\setvalue{@interface@english@}{en}
+\setvalue{@interface@french@}{fr}
+\setvalue{@interface@italian@}{it}
+\setvalue{@interface@dutch@}{nl}
+\setvalue{@interface@persian@}{pe}
+\setvalue{@interface@romanian@}{ro}
+
+% \def\userinterfacetag
+% {\ifcsname @interface@\defaultinterface @\endcsname\csname @interface@\defaultinterface @\endcsname\else en\fi}
+\def\userinterfacetag
+ {\ifcsname @interface@\currentinterface @\endcsname\csname @interface@\currentinterface @\endcsname\else en\fi}
+\def\userresponsestag
+ {\ifcsname @interface@\currentresponses @\endcsname\csname @interface@\currentresponses @\endcsname\else en\fi}
+
+\input mult-\userinterfacetag \relax
+\input mult-m\userresponsestag \relax
+
+\protect \endinput
diff --git a/tex/context/base/mult-en.tex b/tex/context/base/mult-en.tex
new file mode 100644
index 000000000..20917a034
--- /dev/null
+++ b/tex/context/base/mult-en.tex
@@ -0,0 +1,1693 @@
+% this file is auto-generated, don't edit this file
+%
+% definitions for interface variables for language en
+%
+\setinterfacevariable{Addition}{Addition}
+\setinterfacevariable{Balloon}{Balloon}
+\setinterfacevariable{Character}{Character}
+\setinterfacevariable{Characters}{Characters}
+\setinterfacevariable{CloseDocument}{CloseDocument}
+\setinterfacevariable{ExitViewer}{ExitViewer}
+\setinterfacevariable{FirstPage}{FirstPage}
+\setinterfacevariable{FitHeight}{FitHeight}
+\setinterfacevariable{FitWidth}{FitWidth}
+\setinterfacevariable{GotoPage}{GotoPage}
+\setinterfacevariable{Greek}{Greek}
+\setinterfacevariable{Help}{Help}
+\setinterfacevariable{HideField}{HideField}
+\setinterfacevariable{HideLayer}{HideLayer}
+\setinterfacevariable{Key}{Key}
+\setinterfacevariable{LastPage}{LastPage}
+\setinterfacevariable{LoadForm}{LoadForm}
+\setinterfacevariable{MONTH}{MONTH}
+\setinterfacevariable{New}{New}
+\setinterfacevariable{NextJump}{NextJump}
+\setinterfacevariable{NextPage}{NextPage}
+\setinterfacevariable{Numbers}{Numbers}
+\setinterfacevariable{OpenNamedDocument}{OpenNamedDocument}
+\setinterfacevariable{Paragraph}{Paragraph}
+\setinterfacevariable{PauseMovie}{PauseMovie}
+\setinterfacevariable{PauseRendering}{PauseRendering}
+\setinterfacevariable{PauseSound}{PauseSound}
+\setinterfacevariable{PreviousJump}{PreviousJump}
+\setinterfacevariable{PreviousPage}{PreviousPage}
+\setinterfacevariable{PrintDocument}{PrintDocument}
+\setinterfacevariable{Query}{Query}
+\setinterfacevariable{QueryAgain}{QueryAgain}
+\setinterfacevariable{ResetForm}{ResetForm}
+\setinterfacevariable{ResumeMovie}{ResumeMovie}
+\setinterfacevariable{ResumeRendering}{ResumeRendering}
+\setinterfacevariable{ResumeSound}{ResumeSound}
+\setinterfacevariable{Romannumerals}{Romannumerals}
+\setinterfacevariable{SaveDocument}{SaveDocument}
+\setinterfacevariable{SaveForm}{SaveForm}
+\setinterfacevariable{SaveNamedDocument}{SaveNamedDocument}
+\setinterfacevariable{SearchAgain}{SearchAgain}
+\setinterfacevariable{SearchDocument}{SearchDocument}
+\setinterfacevariable{ShowBookmarks}{ShowBookmarks}
+\setinterfacevariable{ShowField}{ShowField}
+\setinterfacevariable{ShowThumbs}{ShowThumbs}
+\setinterfacevariable{StartMovie}{StartMovie}
+\setinterfacevariable{StartRendering}{StartRendering}
+\setinterfacevariable{StartSound}{StartSound}
+\setinterfacevariable{StopMovie}{StopMovie}
+\setinterfacevariable{StopRendering}{StopRendering}
+\setinterfacevariable{StopSound}{StopSound}
+\setinterfacevariable{SubmitForm}{SubmitForm}
+\setinterfacevariable{ToggleLayer}{ToggleLayer}
+\setinterfacevariable{ToggleViewer}{ToggleViewer}
+\setinterfacevariable{URL}{URL}
+\setinterfacevariable{VideLayer}{VideLayer}
+\setinterfacevariable{ViewerHelp}{ViewerHelp}
+\setinterfacevariable{WEEKDAY}{WEEKDAY}
+\setinterfacevariable{WORD}{WORD}
+\setinterfacevariable{abbreviation}{abbreviation}
+\setinterfacevariable{abbreviations}{abbreviations}
+\setinterfacevariable{absolute}{absolute}
+\setinterfacevariable{action}{action}
+\setinterfacevariable{after}{after}
+\setinterfacevariable{all}{all}
+\setinterfacevariable{always}{always}
+\setinterfacevariable{answerarea}{answerarea}
+\setinterfacevariable{appendices}{appendices}
+\setinterfacevariable{appendix}{appendix}
+\setinterfacevariable{april}{April}
+\setinterfacevariable{atmargin}{atmargin}
+\setinterfacevariable{atpage}{atpage}
+\setinterfacevariable{august}{August}
+\setinterfacevariable{author}{author}
+\setinterfacevariable{auto}{auto}
+\setinterfacevariable{autointro}{autointro}
+\setinterfacevariable{back}{back}
+\setinterfacevariable{background}{background}
+\setinterfacevariable{backmatter}{backmatter}
+\setinterfacevariable{backpart}{backpart}
+\setinterfacevariable{backspace}{backspace}
+\setinterfacevariable{backward}{backward}
+\setinterfacevariable{bbl}{bbl}
+\setinterfacevariable{before}{before}
+\setinterfacevariable{begin}{begin}
+\setinterfacevariable{bib}{bib}
+\setinterfacevariable{big}{big}
+\setinterfacevariable{bigbodyfont}{bigbodyfont}
+\setinterfacevariable{bigpreference}{bigpreference}
+\setinterfacevariable{blank}{blank}
+\setinterfacevariable{blockquote}{blockquote}
+\setinterfacevariable{bodymatter}{bodymatter}
+\setinterfacevariable{bodypart}{bodypart}
+\setinterfacevariable{bold}{bold}
+\setinterfacevariable{bolditalic}{bolditalic}
+\setinterfacevariable{boldslanted}{boldslanted}
+\setinterfacevariable{bookmark}{bookmark}
+\setinterfacevariable{both}{both}
+\setinterfacevariable{bottom}{bottom}
+\setinterfacevariable{brief}{brief}
+\setinterfacevariable{broad}{broad}
+\setinterfacevariable{buffer}{buffer}
+\setinterfacevariable{by}{by}
+\setinterfacevariable{calligraphic}{calligraphic}
+\setinterfacevariable{cap}{cap}
+\setinterfacevariable{capital}{capital}
+\setinterfacevariable{center}{center}
+\setinterfacevariable{chapter}{chapter}
+\setinterfacevariable{character}{character}
+\setinterfacevariable{characters}{characters}
+\setinterfacevariable{cite}{cite}
+\setinterfacevariable{color}{color}
+\setinterfacevariable{column}{column}
+\setinterfacevariable{columns}{columns}
+\setinterfacevariable{command}{command}
+\setinterfacevariable{commands}{commands}
+\setinterfacevariable{comment}{comment}
+\setinterfacevariable{component}{component}
+\setinterfacevariable{concept}{concept}
+\setinterfacevariable{content}{content}
+\setinterfacevariable{contents}{contents}
+\setinterfacevariable{continue}{continue}
+\setinterfacevariable{controls}{controls}
+\setinterfacevariable{conversion}{conversion}
+\setinterfacevariable{current}{current}
+\setinterfacevariable{cutspace}{cutspace}
+\setinterfacevariable{date}{date}
+\setinterfacevariable{day}{day}
+\setinterfacevariable{december}{December}
+\setinterfacevariable{default}{default}
+\setinterfacevariable{depth}{depth}
+\setinterfacevariable{description}{description}
+\setinterfacevariable{disable}{disable}
+\setinterfacevariable{display}{display}
+\setinterfacevariable{dot}{dot}
+\setinterfacevariable{doublesided}{doublesided}
+\setinterfacevariable{down}{down}
+\setinterfacevariable{each}{each}
+\setinterfacevariable{edge}{edge}
+\setinterfacevariable{empty}{empty}
+\setinterfacevariable{end}{end}
+\setinterfacevariable{endnote}{endnote}
+\setinterfacevariable{enumeration}{enumeration}
+\setinterfacevariable{environment}{environment}
+\setinterfacevariable{even}{even}
+\setinterfacevariable{external}{external}
+\setinterfacevariable{fact}{fact}
+\setinterfacevariable{february}{February}
+\setinterfacevariable{figure}{figure}
+\setinterfacevariable{figures}{figures}
+\setinterfacevariable{file}{file}
+\setinterfacevariable{final}{final}
+\setinterfacevariable{first}{first}
+\setinterfacevariable{firstcolumn}{firstcolumn}
+\setinterfacevariable{firstpage}{firstpage}
+\setinterfacevariable{firstsubpage}{firstsubpage}
+\setinterfacevariable{fit}{fit}
+\setinterfacevariable{five}{five}
+\setinterfacevariable{fix}{fix}
+\setinterfacevariable{fixed}{fixed}
+\setinterfacevariable{flexible}{flexible}
+\setinterfacevariable{float}{float}
+\setinterfacevariable{flushinner}{flushinner}
+\setinterfacevariable{flushleft}{flushleft}
+\setinterfacevariable{flushouter}{flushouter}
+\setinterfacevariable{flushright}{flushright}
+\setinterfacevariable{footer}{footer}
+\setinterfacevariable{footnote}{footnote}
+\setinterfacevariable{force}{force}
+\setinterfacevariable{foreground}{foreground}
+\setinterfacevariable{formeel}{formeel}
+\setinterfacevariable{formula}{formula}
+\setinterfacevariable{formulae}{formulae}
+\setinterfacevariable{forward}{forward}
+\setinterfacevariable{four}{four}
+\setinterfacevariable{frame}{frame}
+\setinterfacevariable{framedtext}{framedtext}
+\setinterfacevariable{friday}{friday}
+\setinterfacevariable{frontmatter}{frontmatter}
+\setinterfacevariable{frontpart}{frontpart}
+\setinterfacevariable{global}{global}
+\setinterfacevariable{graphic}{graphic}
+\setinterfacevariable{graphics}{graphics}
+\setinterfacevariable{gray}{gray}
+\setinterfacevariable{greek}{greek}
+\setinterfacevariable{grid}{grid}
+\setinterfacevariable{halfline}{halfline}
+\setinterfacevariable{handwritten}{handwritten}
+\setinterfacevariable{hang}{hang}
+\setinterfacevariable{hanging}{hanging}
+\setinterfacevariable{head}{head}
+\setinterfacevariable{header}{header}
+\setinterfacevariable{height}{height}
+\setinterfacevariable{helptext}{helptext}
+\setinterfacevariable{hencefore}{hencefore}
+\setinterfacevariable{here}{here}
+\setinterfacevariable{hereafter}{hereafter}
+\setinterfacevariable{hidden}{hidden}
+\setinterfacevariable{hiding}{hiding}
+\setinterfacevariable{high}{high}
+\setinterfacevariable{horizontal}{horizontal}
+\setinterfacevariable{hyphenated}{hyphenated}
+\setinterfacevariable{hz}{hz}
+\setinterfacevariable{inbetween}{inbetween}
+\setinterfacevariable{index}{index}
+\setinterfacevariable{indices}{indices}
+\setinterfacevariable{informeel}{informeel}
+\setinterfacevariable{inherit}{inherit}
+\setinterfacevariable{inleft}{inleft}
+\setinterfacevariable{inmargin}{inmargin}
+\setinterfacevariable{inner}{inner}
+\setinterfacevariable{inneredge}{inneredge}
+\setinterfacevariable{innermargin}{innermargin}
+\setinterfacevariable{inright}{inright}
+\setinterfacevariable{interaction}{interaction}
+\setinterfacevariable{interactionmenu}{interactionmenu}
+\setinterfacevariable{intermezzi}{intermezzi}
+\setinterfacevariable{intermezzo}{intermezzo}
+\setinterfacevariable{intext}{intext}
+\setinterfacevariable{intro}{intro}
+\setinterfacevariable{italic}{italic}
+\setinterfacevariable{italicbold}{italicbold}
+\setinterfacevariable{item}{item}
+\setinterfacevariable{itemize}{itemize}
+\setinterfacevariable{its}{its}
+\setinterfacevariable{january}{January}
+\setinterfacevariable{joinedup}{joinedup}
+\setinterfacevariable{july}{July}
+\setinterfacevariable{june}{June}
+\setinterfacevariable{keep}{keep}
+\setinterfacevariable{knockout}{knockout}
+\setinterfacevariable{label}{label}
+\setinterfacevariable{landscape}{landscape}
+\setinterfacevariable{last}{last}
+\setinterfacevariable{lastcolumn}{lastcolumn}
+\setinterfacevariable{lastpage}{lastpage}
+\setinterfacevariable{lastpagenumber}{lastpagenumber}
+\setinterfacevariable{lastsubpage}{lastsubpage}
+\setinterfacevariable{layer}{layer}
+\setinterfacevariable{left}{left}
+\setinterfacevariable{leftedge}{leftedge}
+\setinterfacevariable{lefthanging}{lefthanging}
+\setinterfacevariable{leftmargin}{leftmargin}
+\setinterfacevariable{leftpage}{leftpage}
+\setinterfacevariable{lefttoright}{lefttoright}
+\setinterfacevariable{legend}{legend}
+\setinterfacevariable{lesshyphenation}{lesshyphenation}
+\setinterfacevariable{line}{line}
+\setinterfacevariable{linenote}{linenote}
+\setinterfacevariable{lines}{lines}
+\setinterfacevariable{list}{list}
+\setinterfacevariable{local}{local}
+\setinterfacevariable{localenvironment}{localenvironment}
+\setinterfacevariable{logo}{logo}
+\setinterfacevariable{logos}{logos}
+\setinterfacevariable{lohi}{lohi}
+\setinterfacevariable{loose}{loose}
+\setinterfacevariable{low}{low}
+\setinterfacevariable{ls}{ls}
+\setinterfacevariable{makeup}{makeup}
+\setinterfacevariable{mar}{mar}
+\setinterfacevariable{march}{March}
+\setinterfacevariable{margin}{margin}
+\setinterfacevariable{marginedge}{marginedge}
+\setinterfacevariable{margintitle}{margintitle}
+\setinterfacevariable{marking}{marking}
+\setinterfacevariable{mathalignment}{mathalignment}
+\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathmatrix}{mathmatrix}
+\setinterfacevariable{max}{max}
+\setinterfacevariable{maxdepth}{maxdepth}
+\setinterfacevariable{maxheight}{maxheight}
+\setinterfacevariable{maxwidth}{maxwidth}
+\setinterfacevariable{may}{May}
+\setinterfacevariable{mediaeval}{mediaeval}
+\setinterfacevariable{medium}{medium}
+\setinterfacevariable{middle}{middle}
+\setinterfacevariable{min}{min}
+\setinterfacevariable{mindepth}{mindepth}
+\setinterfacevariable{minheight}{minheight}
+\setinterfacevariable{minwidth}{minwidth}
+\setinterfacevariable{mirrored}{mirrored}
+\setinterfacevariable{monday}{monday}
+\setinterfacevariable{mono}{mono}
+\setinterfacevariable{month}{month}
+\setinterfacevariable{morehyphenation}{morehyphenation}
+\setinterfacevariable{name}{name}
+\setinterfacevariable{narrow}{narrow}
+\setinterfacevariable{negative}{negative}
+\setinterfacevariable{never}{never}
+\setinterfacevariable{new}{new}
+\setinterfacevariable{next}{next}
+\setinterfacevariable{nextevenpage}{nextevenpage}
+\setinterfacevariable{nextoddpage}{nextoddpage}
+\setinterfacevariable{nextpage}{nextpage}
+\setinterfacevariable{nextsubpage}{nextsubpage}
+\setinterfacevariable{no}{no}
+\setinterfacevariable{nocheck}{nocheck}
+\setinterfacevariable{nofit}{nofit}
+\setinterfacevariable{nogrid}{nogrid}
+\setinterfacevariable{nohz}{nohz}
+\setinterfacevariable{nomarking}{nomarking}
+\setinterfacevariable{none}{none}
+\setinterfacevariable{nonumber}{nonumber}
+\setinterfacevariable{normal}{normal}
+\setinterfacevariable{nospacing}{nospacing}
+\setinterfacevariable{not}{not}
+\setinterfacevariable{note}{note}
+\setinterfacevariable{nothanging}{nothanging}
+\setinterfacevariable{nothyphenated}{nothyphenated}
+\setinterfacevariable{november}{November}
+\setinterfacevariable{nowhere}{nowhere}
+\setinterfacevariable{nowhite}{nowhite}
+\setinterfacevariable{number}{number}
+\setinterfacevariable{numbers}{numbers}
+\setinterfacevariable{october}{October}
+\setinterfacevariable{odd}{odd}
+\setinterfacevariable{off}{off}
+\setinterfacevariable{offset}{offset}
+\setinterfacevariable{old}{old}
+\setinterfacevariable{on}{on}
+\setinterfacevariable{one}{one}
+\setinterfacevariable{opposite}{opposite}
+\setinterfacevariable{outer}{outer}
+\setinterfacevariable{outeredge}{outeredge}
+\setinterfacevariable{outermargin}{outermargin}
+\setinterfacevariable{overbar}{overbar}
+\setinterfacevariable{overbars}{overbars}
+\setinterfacevariable{overlay}{overlay}
+\setinterfacevariable{overprint}{overprint}
+\setinterfacevariable{overstrike}{overstrike}
+\setinterfacevariable{overstrikes}{overstrikes}
+\setinterfacevariable{packed}{packed}
+\setinterfacevariable{page}{page}
+\setinterfacevariable{pagecomment}{pagecomment}
+\setinterfacevariable{pagenumber}{pagenumber}
+\setinterfacevariable{paper}{paper}
+\setinterfacevariable{paragraph}{paragraph}
+\setinterfacevariable{part}{part}
+\setinterfacevariable{positive}{positive}
+\setinterfacevariable{postponing}{postponing}
+\setinterfacevariable{postscript}{postscript}
+\setinterfacevariable{preference}{preference}
+\setinterfacevariable{preview}{preview}
+\setinterfacevariable{previous}{previous}
+\setinterfacevariable{previousevenpage}{previousevenpage}
+\setinterfacevariable{previousoddpage}{previousoddpage}
+\setinterfacevariable{previouspage}{previouspage}
+\setinterfacevariable{previoussubpage}{previoussubpage}
+\setinterfacevariable{printable}{printable}
+\setinterfacevariable{process}{process}
+\setinterfacevariable{product}{product}
+\setinterfacevariable{program}{program}
+\setinterfacevariable{project}{project}
+\setinterfacevariable{protected}{protected}
+\setinterfacevariable{quadruple}{quadruple}
+\setinterfacevariable{quotation}{quotation}
+\setinterfacevariable{quote}{quote}
+\setinterfacevariable{ran}{ran}
+\setinterfacevariable{random}{random}
+\setinterfacevariable{readonly}{readonly}
+\setinterfacevariable{rectangular}{rectangular}
+\setinterfacevariable{referral}{referral}
+\setinterfacevariable{register}{register}
+\setinterfacevariable{regular}{regular}
+\setinterfacevariable{rekening}{rekening}
+\setinterfacevariable{relative}{relative}
+\setinterfacevariable{repeat}{repeat}
+\setinterfacevariable{required}{required}
+\setinterfacevariable{reset}{reset}
+\setinterfacevariable{reverse}{reverse}
+\setinterfacevariable{right}{right}
+\setinterfacevariable{rightedge}{rightedge}
+\setinterfacevariable{righthanging}{righthanging}
+\setinterfacevariable{rightmargin}{rightmargin}
+\setinterfacevariable{rightpage}{rightpage}
+\setinterfacevariable{righttoleft}{righttoleft}
+\setinterfacevariable{roman}{roman}
+\setinterfacevariable{romannumerals}{romannumerals}
+\setinterfacevariable{rotate}{rotate}
+\setinterfacevariable{rotated}{rotated}
+\setinterfacevariable{round}{round}
+\setinterfacevariable{row}{row}
+\setinterfacevariable{rule}{rule}
+\setinterfacevariable{samepage}{samepage}
+\setinterfacevariable{sans}{sans}
+\setinterfacevariable{sansbold}{sansbold}
+\setinterfacevariable{sansserif}{sansserif}
+\setinterfacevariable{saturday}{saturday}
+\setinterfacevariable{screen}{screen}
+\setinterfacevariable{section}{section}
+\setinterfacevariable{sectionblockenvironment}{sectionblockenvironment}
+\setinterfacevariable{sectionnumber}{sectionnumber}
+\setinterfacevariable{see}{see}
+\setinterfacevariable{september}{September}
+\setinterfacevariable{serif}{serif}
+\setinterfacevariable{serried}{serried}
+\setinterfacevariable{setups}{setups}
+\setinterfacevariable{sheet}{sheet}
+\setinterfacevariable{short}{short}
+\setinterfacevariable{singlesided}{singlesided}
+\setinterfacevariable{slanted}{slanted}
+\setinterfacevariable{slantedbold}{slantedbold}
+\setinterfacevariable{small}{small}
+\setinterfacevariable{smallbodyfont}{smallbodyfont}
+\setinterfacevariable{smallbold}{smallbold}
+\setinterfacevariable{smallbolditalic}{smallbolditalic}
+\setinterfacevariable{smallboldslanted}{smallboldslanted}
+\setinterfacevariable{smallcaps}{smallcaps}
+\setinterfacevariable{smallitalic}{smallitalic}
+\setinterfacevariable{smallitalicbold}{smallitalicbold}
+\setinterfacevariable{smallnormal}{smallnormal}
+\setinterfacevariable{smallslanted}{smallslanted}
+\setinterfacevariable{smallslantedbold}{smallslantedbold}
+\setinterfacevariable{smalltype}{smalltype}
+\setinterfacevariable{somewhere}{somewhere}
+\setinterfacevariable{sorted}{sorted}
+\setinterfacevariable{space}{space}
+\setinterfacevariable{spacing}{spacing}
+\setinterfacevariable{speech}{speech}
+\setinterfacevariable{split}{split}
+\setinterfacevariable{spot}{spot}
+\setinterfacevariable{standard}{standard}
+\setinterfacevariable{start}{start}
+\setinterfacevariable{starter}{starter}
+\setinterfacevariable{sticker}{sticker}
+\setinterfacevariable{stop}{stop}
+\setinterfacevariable{stopper}{stopper}
+\setinterfacevariable{stretch}{stretch}
+\setinterfacevariable{strict}{strict}
+\setinterfacevariable{strong}{strong}
+\setinterfacevariable{strut}{strut}
+\setinterfacevariable{sub}{sub}
+\setinterfacevariable{subbackward}{subbackward}
+\setinterfacevariable{subformula}{subformula}
+\setinterfacevariable{subforward}{subforward}
+\setinterfacevariable{subject}{subject}
+\setinterfacevariable{subpage}{subpage}
+\setinterfacevariable{subsection}{subsection}
+\setinterfacevariable{subsubject}{subsubject}
+\setinterfacevariable{subsubsection}{subsubsection}
+\setinterfacevariable{subsubsubject}{subsubsubject}
+\setinterfacevariable{subsubsubsection}{subsubsubsection}
+\setinterfacevariable{subsubsubsubject}{subsubsubsubject}
+\setinterfacevariable{subsubsubsubsection}{subsubsubsubsection}
+\setinterfacevariable{subsubsubsubsubject}{subsubsubsubsubject}
+\setinterfacevariable{subsubsubsubsubsection}{subsubsubsubsubsection}
+\setinterfacevariable{subsubsubsubsubsubject}{subsubsubsubsubsubject}
+\setinterfacevariable{subsubsubsubsubsubsection}{subsubsubsubsubsubsection}
+\setinterfacevariable{subsubsubsubsubsubsubject}{subsubsubsubsubsubsubject}
+\setinterfacevariable{subsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsection}
+\setinterfacevariable{subsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubject}
+\setinterfacevariable{subsubsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsubsection}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubsubject}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsubsubsection}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubsubsubject}
+\setinterfacevariable{sunday}{sunday}
+\setinterfacevariable{support}{support}
+\setinterfacevariable{sym}{sym}
+\setinterfacevariable{symbol}{symbol}
+\setinterfacevariable{synchronize}{synchronize}
+\setinterfacevariable{system}{system}
+\setinterfacevariable{table}{table}
+\setinterfacevariable{tablehead}{tablehead}
+\setinterfacevariable{tables}{tables}
+\setinterfacevariable{tabletail}{tabletail}
+\setinterfacevariable{tabulate}{tabulate}
+\setinterfacevariable{tabulatehead}{tabulatehead}
+\setinterfacevariable{tabulatetail}{tabulatetail}
+\setinterfacevariable{tall}{tall}
+\setinterfacevariable{teletype}{teletype}
+\setinterfacevariable{temporary}{temporary}
+\setinterfacevariable{test}{test}
+\setinterfacevariable{text}{text}
+\setinterfacevariable{three}{three}
+\setinterfacevariable{thursday}{thursday}
+\setinterfacevariable{title}{title}
+\setinterfacevariable{toggle}{wissel}
+\setinterfacevariable{tolerant}{tolerant}
+\setinterfacevariable{top}{top}
+\setinterfacevariable{tuesday}{tuesday}
+\setinterfacevariable{two}{two}
+\setinterfacevariable{txt}{txt}
+\setinterfacevariable{type}{type}
+\setinterfacevariable{typing}{typing}
+\setinterfacevariable{unavailable}{unavailable}
+\setinterfacevariable{underbar}{underbar}
+\setinterfacevariable{underbars}{underbars}
+\setinterfacevariable{unit}{unit}
+\setinterfacevariable{units}{units}
+\setinterfacevariable{unknown}{unknown}
+\setinterfacevariable{unpacked}{unpacked}
+\setinterfacevariable{up}{up}
+\setinterfacevariable{url}{url}
+\setinterfacevariable{used}{used}
+\setinterfacevariable{value}{value}
+\setinterfacevariable{vertical}{vertical}
+\setinterfacevariable{very}{very}
+\setinterfacevariable{verystrict}{verystrict}
+\setinterfacevariable{verytolerant}{verytolerant}
+\setinterfacevariable{weak}{weak}
+\setinterfacevariable{wednesday}{wednesday}
+\setinterfacevariable{week}{week}
+\setinterfacevariable{weekday}{weekday}
+\setinterfacevariable{white}{white}
+\setinterfacevariable{wide}{wide}
+\setinterfacevariable{width}{width}
+\setinterfacevariable{xml}{xml}
+\setinterfacevariable{year}{year}
+\setinterfacevariable{yes}{yes}
+% definitions for interface constants for language en
+%
+\setinterfaceconstant{action}{action}
+\setinterfaceconstant{address}{address}
+\setinterfaceconstant{after}{after}
+\setinterfaceconstant{afterhead}{afterhead}
+\setinterfaceconstant{afterkey}{afterkey}
+\setinterfaceconstant{align}{align}
+\setinterfaceconstant{aligncharacter}{aligncharacter}
+\setinterfaceconstant{alignmentcharacter}{alignmentcharacter}
+\setinterfaceconstant{alignsymbol}{alignsymbol}
+\setinterfaceconstant{aligntitle}{aligntitle}
+\setinterfaceconstant{alternative}{alternative}
+\setinterfaceconstant{andtext}{andtext}
+\setinterfaceconstant{apa}{apa}
+\setinterfaceconstant{arrow}{arrow}
+\setinterfaceconstant{artauthor}{artauthor}
+\setinterfaceconstant{artauthoretaldisplay}{artauthoretaldisplay}
+\setinterfaceconstant{artauthoretallimit}{artauthoretallimit}
+\setinterfaceconstant{artauthoretaltext}{artauthoretaltext}
+\setinterfaceconstant{at}{at}
+\setinterfaceconstant{author}{author}
+\setinterfaceconstant{authoretaldisplay}{authoretaldisplay}
+\setinterfaceconstant{authoretallimit}{authoretallimit}
+\setinterfaceconstant{authoretaltext}{authoretaltext}
+\setinterfaceconstant{auto}{auto}
+\setinterfaceconstant{autofile}{autofile}
+\setinterfaceconstant{autofocus}{autofocus}
+\setinterfaceconstant{autohang}{autohang}
+\setinterfaceconstant{autostrut}{autostrut}
+\setinterfaceconstant{autowidth}{autowidth}
+\setinterfaceconstant{axis}{axis}
+\setinterfaceconstant{background}{background}
+\setinterfaceconstant{backgroundcolor}{backgroundcolor}
+\setinterfaceconstant{backgroundcorner}{backgroundcorner}
+\setinterfaceconstant{backgrounddepth}{backgrounddepth}
+\setinterfaceconstant{backgroundoffset}{backgroundoffset}
+\setinterfaceconstant{backgroundradius}{backgroundradius}
+\setinterfaceconstant{backgroundscreen}{backgroundscreen}
+\setinterfaceconstant{backspace}{backspace}
+\setinterfaceconstant{balance}{balance}
+\setinterfaceconstant{before}{before}
+\setinterfaceconstant{beforehead}{beforehead}
+\setinterfaceconstant{bet}{bet}
+\setinterfaceconstant{big}{big}
+\setinterfaceconstant{blank}{blank}
+\setinterfaceconstant{blockway}{blockway}
+\setinterfaceconstant{bodyfont}{bodyfont}
+\setinterfaceconstant{bookmark}{bookmark}
+\setinterfaceconstant{bottom}{bottom}
+\setinterfaceconstant{bottomafter}{bottomafter}
+\setinterfaceconstant{bottombefore}{bottombefore}
+\setinterfaceconstant{bottomdistance}{bottomdistance}
+\setinterfaceconstant{bottomframe}{bottomframe}
+\setinterfaceconstant{bottomoffset}{bottomoffset}
+\setinterfaceconstant{bottomspace}{bottomspace}
+\setinterfaceconstant{bottomstate}{bottomstate}
+\setinterfaceconstant{cache}{cache}
+\setinterfaceconstant{calculate}{calculate}
+\setinterfaceconstant{ccommand}{ccommand}
+\setinterfaceconstant{click}{click}
+\setinterfaceconstant{clickin}{clickin}
+\setinterfaceconstant{clickout}{clickout}
+\setinterfaceconstant{clipoffset}{clipoffset}
+\setinterfaceconstant{closeaction}{closeaction}
+\setinterfaceconstant{closecommand}{closecommand}
+\setinterfaceconstant{closepageaction}{closepageaction}
+\setinterfaceconstant{closesymbol}{closesymbol}
+\setinterfaceconstant{color}{color}
+\setinterfaceconstant{column}{column}
+\setinterfaceconstant{columndistance}{columndistance}
+\setinterfaceconstant{columns}{columns}
+\setinterfaceconstant{command}{command}
+\setinterfaceconstant{commandafter}{commandafter}
+\setinterfaceconstant{commandbefore}{commandbefore}
+\setinterfaceconstant{commands}{commands}
+\setinterfaceconstant{component}{component}
+\setinterfaceconstant{compoundhyphen}{compoundhyphen}
+\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{connector}{connector}
+\setinterfaceconstant{continue}{continue}
+\setinterfaceconstant{contrastcolor}{contrastcolor}
+\setinterfaceconstant{controls}{controls}
+\setinterfaceconstant{conversion}{conversion}
+\setinterfaceconstant{convertfile}{convertfile}
+\setinterfaceconstant{corner}{corner}
+\setinterfaceconstant{coupling}{coupling}
+\setinterfaceconstant{couplingway}{couplingway}
+\setinterfaceconstant{criterium}{criterium}
+\setinterfaceconstant{current}{current}
+\setinterfaceconstant{cutspace}{cutspace}
+\setinterfaceconstant{dash}{dash}
+\setinterfaceconstant{dat}{dat}
+\setinterfaceconstant{database}{database}
+\setinterfaceconstant{date}{date}
+\setinterfaceconstant{deepnumbercommand}{deepnumbercommand}
+\setinterfaceconstant{deeptextcommand}{deeptextcommand}
+\setinterfaceconstant{default}{default}
+\setinterfaceconstant{delay}{delay}
+\setinterfaceconstant{depth}{depth}
+\setinterfaceconstant{depthcorrection}{depthcorrection}
+\setinterfaceconstant{direction}{direction}
+\setinterfaceconstant{directory}{directory}
+\setinterfaceconstant{display}{display}
+\setinterfaceconstant{distance}{distance}
+\setinterfaceconstant{dot}{dot}
+\setinterfaceconstant{doublesided}{doublesided}
+\setinterfaceconstant{dummy}{dummy}
+\setinterfaceconstant{dx}{dx}
+\setinterfaceconstant{dy}{dy}
+\setinterfaceconstant{edge}{edge}
+\setinterfaceconstant{edgedistance}{edgedistance}
+\setinterfaceconstant{editor}{editor}
+\setinterfaceconstant{editoretaldisplay}{editoretaldisplay}
+\setinterfaceconstant{editoretallimit}{editoretallimit}
+\setinterfaceconstant{editoretaltext}{editoretaltext}
+\setinterfaceconstant{empty}{empty}
+\setinterfaceconstant{equalheight}{equalheight}
+\setinterfaceconstant{equalwidth}{equalwidth}
+\setinterfaceconstant{escape}{escape}
+\setinterfaceconstant{evenmargin}{evenmargin}
+\setinterfaceconstant{expansion}{expansion}
+\setinterfaceconstant{export}{export}
+\setinterfaceconstant{extras}{extras}
+\setinterfaceconstant{factor}{factor}
+\setinterfaceconstant{fallback}{fallback}
+\setinterfaceconstant{family}{family}
+\setinterfaceconstant{fieldbackgroundcolor}{fieldbackgroundcolor}
+\setinterfaceconstant{fieldframecolor}{fieldframecolor}
+\setinterfaceconstant{fieldlayer}{fieldlayer}
+\setinterfaceconstant{fieldoffset}{fieldoffset}
+\setinterfaceconstant{file}{file}
+\setinterfaceconstant{filtercommand}{filtercommand}
+\setinterfaceconstant{finalnamesep}{finalnamesep}
+\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{focus}{focus}
+\setinterfaceconstant{focusin}{focusin}
+\setinterfaceconstant{focusout}{focusout}
+\setinterfaceconstant{footer}{footer}
+\setinterfaceconstant{footerdistance}{footerdistance}
+\setinterfaceconstant{footerstate}{footerstate}
+\setinterfaceconstant{foregroundcolor}{foregroundcolor}
+\setinterfaceconstant{foregroundstyle}{foregroundstyle}
+\setinterfaceconstant{format}{format}
+\setinterfaceconstant{frame}{frame}
+\setinterfaceconstant{framecolor}{framecolor}
+\setinterfaceconstant{framecorner}{framecorner}
+\setinterfaceconstant{framedepth}{framedepth}
+\setinterfaceconstant{frameoffset}{frameoffset}
+\setinterfaceconstant{frameradius}{frameradius}
+\setinterfaceconstant{frames}{frames}
+\setinterfaceconstant{from}{from}
+\setinterfaceconstant{get}{get}
+\setinterfaceconstant{global}{global}
+\setinterfaceconstant{grid}{grid}
+\setinterfaceconstant{hang}{hang}
+\setinterfaceconstant{headalign}{headalign}
+\setinterfaceconstant{headcolor}{headcolor}
+\setinterfaceconstant{headcommand}{headcommand}
+\setinterfaceconstant{headconversion}{headconversion}
+\setinterfaceconstant{header}{header}
+\setinterfaceconstant{headerdistance}{headerdistance}
+\setinterfaceconstant{headerstate}{headerstate}
+\setinterfaceconstant{headlabel}{headlabel}
+\setinterfaceconstant{headnumber}{headnumber}
+\setinterfaceconstant{headstyle}{headstyle}
+\setinterfaceconstant{height}{height}
+\setinterfaceconstant{hfactor}{hfactor}
+\setinterfaceconstant{hfil}{hfil}
+\setinterfaceconstant{hidenumber}{hidenumber}
+\setinterfaceconstant{hoffset}{hoffset}
+\setinterfaceconstant{horoffset}{horoffset}
+\setinterfaceconstant{hyphen}{hyphen}
+\setinterfaceconstant{icommand}{icommand}
+\setinterfaceconstant{in}{in}
+\setinterfaceconstant{inbetween}{inbetween}
+\setinterfaceconstant{increment}{increment}
+\setinterfaceconstant{incrementnumber}{incrementnumber}
+\setinterfaceconstant{indenting}{indenting}
+\setinterfaceconstant{indentnext}{indentnext}
+\setinterfaceconstant{indicator}{indicator}
+\setinterfaceconstant{inner}{inner}
+\setinterfaceconstant{innermargin}{innermargin}
+\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{intent}{intent}
+\setinterfaceconstant{interaction}{interaction}
+\setinterfaceconstant{interlinespace}{interlinespace}
+\setinterfaceconstant{itemalign}{itemalign}
+\setinterfaceconstant{items}{items}
+\setinterfaceconstant{juniorsep}{juniorsep}
+\setinterfaceconstant{ken}{ken}
+\setinterfaceconstant{keyexpansion}{keyexpansion}
+\setinterfaceconstant{keyword}{keyword}
+\setinterfaceconstant{label}{label}
+\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{left}{left}
+\setinterfaceconstant{leftcolor}{leftcolor}
+\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
+\setinterfaceconstant{leftedge}{leftedge}
+\setinterfaceconstant{leftedgedistance}{leftedgedistance}
+\setinterfaceconstant{leftframe}{leftframe}
+\setinterfaceconstant{lefthyphen}{lefthyphen}
+\setinterfaceconstant{leftmargin}{leftmargin}
+\setinterfaceconstant{leftmargindistance}{leftmargindistance}
+\setinterfaceconstant{leftoffset}{leftoffset}
+\setinterfaceconstant{leftquotation}{leftquotation}
+\setinterfaceconstant{leftquote}{leftquote}
+\setinterfaceconstant{leftsentence}{leftsentence}
+\setinterfaceconstant{leftspeech}{leftspeech}
+\setinterfaceconstant{leftstyle}{leftstyle}
+\setinterfaceconstant{leftsubsentence}{leftsubsentence}
+\setinterfaceconstant{lefttext}{lefttext}
+\setinterfaceconstant{leftwidth}{leftwidth}
+\setinterfaceconstant{level}{level}
+\setinterfaceconstant{levels}{levels}
+\setinterfaceconstant{limittext}{limittext}
+\setinterfaceconstant{line}{line}
+\setinterfaceconstant{linecorrection}{linecorrection}
+\setinterfaceconstant{lines}{lines}
+\setinterfaceconstant{list}{list}
+\setinterfaceconstant{listtext}{listtext}
+\setinterfaceconstant{local}{local}
+\setinterfaceconstant{location}{location}
+\setinterfaceconstant{logo}{logo}
+\setinterfaceconstant{logos}{logos}
+\setinterfaceconstant{marcolor}{marcolor}
+\setinterfaceconstant{margin}{margin}
+\setinterfaceconstant{margindistance}{margindistance}
+\setinterfaceconstant{marginedge}{marginedge}
+\setinterfaceconstant{marginedgetext}{marginedgetext}
+\setinterfaceconstant{margintext}{margintext}
+\setinterfaceconstant{marking}{marking}
+\setinterfaceconstant{marstyle}{marstyle}
+\setinterfaceconstant{max}{max}
+\setinterfaceconstant{maxdepth}{maxdepth}
+\setinterfaceconstant{maxheight}{maxheight}
+\setinterfaceconstant{maxwidth}{maxwidth}
+\setinterfaceconstant{maybeyear}{maybeyear}
+\setinterfaceconstant{menu}{menu}
+\setinterfaceconstant{method}{method}
+\setinterfaceconstant{middle}{middle}
+\setinterfaceconstant{middlespeech}{middlespeech}
+\setinterfaceconstant{middletext}{middletext}
+\setinterfaceconstant{midsentence}{midsentence}
+\setinterfaceconstant{min}{min}
+\setinterfaceconstant{mindepth}{mindepth}
+\setinterfaceconstant{minheight}{minheight}
+\setinterfaceconstant{minwidth}{minwidth}
+\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{n}{n}
+\setinterfaceconstant{name}{name}
+\setinterfaceconstant{namesep}{namesep}
+\setinterfaceconstant{nbottom}{nbottom}
+\setinterfaceconstant{nc}{nc}
+\setinterfaceconstant{next}{next}
+\setinterfaceconstant{nl}{nl}
+\setinterfaceconstant{nleft}{nleft}
+\setinterfaceconstant{nlines}{nlines}
+\setinterfaceconstant{norm}{norm}
+\setinterfaceconstant{nr}{nr}
+\setinterfaceconstant{nright}{nright}
+\setinterfaceconstant{ntop}{ntop}
+\setinterfaceconstant{number}{number}
+\setinterfaceconstant{numbercolor}{numbercolor}
+\setinterfaceconstant{numbercommand}{numbercommand}
+\setinterfaceconstant{numberconversion}{numberconversion}
+\setinterfaceconstant{numberconversionset}{numberconversionset}
+\setinterfaceconstant{numberdistance}{numberdistance}
+\setinterfaceconstant{numbering}{numbering}
+\setinterfaceconstant{numberorder}{numberorder}
+\setinterfaceconstant{numberprefix}{numberprefix}
+\setinterfaceconstant{numbersegments}{numbersegments}
+\setinterfaceconstant{numberseparator}{numberseparator}
+\setinterfaceconstant{numberseparatorset}{numberseparatorset}
+\setinterfaceconstant{numberset}{numberset}
+\setinterfaceconstant{numberstarter}{numberstarter}
+\setinterfaceconstant{numberstopper}{numberstopper}
+\setinterfaceconstant{numberstyle}{numberstyle}
+\setinterfaceconstant{numberwidth}{numberwidth}
+\setinterfaceconstant{nx}{nx}
+\setinterfaceconstant{ny}{ny}
+\setinterfaceconstant{object}{object}
+\setinterfaceconstant{obstruction}{obstruction}
+\setinterfaceconstant{oddmargin}{oddmargin}
+\setinterfaceconstant{offset}{offset}
+\setinterfaceconstant{openaction}{openaction}
+\setinterfaceconstant{openpageaction}{openpageaction}
+\setinterfaceconstant{option}{option}
+\setinterfaceconstant{order}{order}
+\setinterfaceconstant{orientation}{orientation}
+\setinterfaceconstant{otherstext}{otherstext}
+\setinterfaceconstant{outermargin}{outermargin}
+\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownnumber}{ownnumber}
+\setinterfaceconstant{page}{page}
+\setinterfaceconstant{pageboundaries}{pageboundaries}
+\setinterfaceconstant{pagecolor}{pagecolor}
+\setinterfaceconstant{pagecommand}{pagecommand}
+\setinterfaceconstant{pageconversion}{pageconversion}
+\setinterfaceconstant{pageconversionset}{pageconversionset}
+\setinterfaceconstant{pagenumber}{pagenumber}
+\setinterfaceconstant{pageprefix}{pageprefix}
+\setinterfaceconstant{pageprefixconnector}{pageprefixconnector}
+\setinterfaceconstant{pageprefixconversion}{pageprefixconversion}
+\setinterfaceconstant{pageprefixconversionset}{pageprefixconversionset}
+\setinterfaceconstant{pageprefixsegments}{pageprefixsegments}
+\setinterfaceconstant{pageprefixseparatorset}{pageprefixseparatorset}
+\setinterfaceconstant{pageprefixset}{pageprefixset}
+\setinterfaceconstant{pageprefixstarter}{pageprefixstarter}
+\setinterfaceconstant{pageprefixstopper}{pageprefixstopper}
+\setinterfaceconstant{pagesegments}{pagesegments}
+\setinterfaceconstant{pageseparatorset}{pageseparatorset}
+\setinterfaceconstant{pageset}{pageset}
+\setinterfaceconstant{pagestarter}{pagestarter}
+\setinterfaceconstant{pagestate}{pagestate}
+\setinterfaceconstant{pagestopper}{pagestopper}
+\setinterfaceconstant{pagestyle}{pagestyle}
+\setinterfaceconstant{palet}{palet}
+\setinterfaceconstant{paper}{paper}
+\setinterfaceconstant{paragraph}{paragraph}
+\setinterfaceconstant{place}{place}
+\setinterfaceconstant{placehead}{placehead}
+\setinterfaceconstant{placestopper}{placestopper}
+\setinterfaceconstant{position}{position}
+\setinterfaceconstant{prefix}{prefix}
+\setinterfaceconstant{prefixconnector}{prefixconnector}
+\setinterfaceconstant{prefixconversion}{prefixconversion}
+\setinterfaceconstant{prefixconversionset}{prefixconversionset}
+\setinterfaceconstant{prefixsegments}{prefixsegments}
+\setinterfaceconstant{prefixseparatorset}{prefixseparatorset}
+\setinterfaceconstant{prefixset}{prefixset}
+\setinterfaceconstant{prefixstarter}{prefixstarter}
+\setinterfaceconstant{prefixstopper}{prefixstopper}
+\setinterfaceconstant{preset}{preset}
+\setinterfaceconstant{preview}{preview}
+\setinterfaceconstant{previous}{previous}
+\setinterfaceconstant{previousnumber}{previousnumber}
+\setinterfaceconstant{process}{process}
+\setinterfaceconstant{pubsep}{pubsep}
+\setinterfaceconstant{radius}{radius}
+\setinterfaceconstant{random}{random}
+\setinterfaceconstant{range}{range}
+\setinterfaceconstant{reduction}{reduction}
+\setinterfaceconstant{ref}{ref}
+\setinterfaceconstant{refcommand}{refcommand}
+\setinterfaceconstant{reference}{reference}
+\setinterfaceconstant{referenceprefix}{referenceprefix}
+\setinterfaceconstant{referencing}{referencing}
+\setinterfaceconstant{regionin}{regionin}
+\setinterfaceconstant{regionout}{regionout}
+\setinterfaceconstant{repeat}{repeat}
+\setinterfaceconstant{reset}{reset}
+\setinterfaceconstant{resetnumber}{resetnumber}
+\setinterfaceconstant{resolution}{resolution}
+\setinterfaceconstant{right}{right}
+\setinterfaceconstant{rightcolor}{rightcolor}
+\setinterfaceconstant{rightcompoundhyphen}{rightcompoundhyphen}
+\setinterfaceconstant{rightedge}{rightedge}
+\setinterfaceconstant{rightedgedistance}{rightedgedistance}
+\setinterfaceconstant{rightframe}{rightframe}
+\setinterfaceconstant{righthyphen}{righthyphen}
+\setinterfaceconstant{rightmargin}{rightmargin}
+\setinterfaceconstant{rightmargindistance}{rightmargindistance}
+\setinterfaceconstant{rightoffset}{rightoffset}
+\setinterfaceconstant{rightquotation}{rightquotation}
+\setinterfaceconstant{rightquote}{rightquote}
+\setinterfaceconstant{rightsentence}{rightsentence}
+\setinterfaceconstant{rightspeech}{rightspeech}
+\setinterfaceconstant{rightstyle}{rightstyle}
+\setinterfaceconstant{rightsubsentence}{rightsubsentence}
+\setinterfaceconstant{righttext}{righttext}
+\setinterfaceconstant{rightwidth}{rightwidth}
+\setinterfaceconstant{rotation}{rotation}
+\setinterfaceconstant{rule}{rule}
+\setinterfaceconstant{rulecolor}{rulecolor}
+\setinterfaceconstant{rulethickness}{rulethickness}
+\setinterfaceconstant{samepage}{samepage}
+\setinterfaceconstant{sample}{sample}
+\setinterfaceconstant{samplesize}{samplesize}
+\setinterfaceconstant{saveinlist}{saveinlist}
+\setinterfaceconstant{scale}{scale}
+\setinterfaceconstant{scope}{scope}
+\setinterfaceconstant{screen}{screen}
+\setinterfaceconstant{section}{section}
+\setinterfaceconstant{sectionconversion}{sectionconversion}
+\setinterfaceconstant{sectionconversionset}{sectionconversionset}
+\setinterfaceconstant{sectionnumber}{sectionnumber}
+\setinterfaceconstant{sectionresetset}{sectionresetset}
+\setinterfaceconstant{sectionsegments}{sectionsegments}
+\setinterfaceconstant{sectionseparatorset}{sectionseparatorset}
+\setinterfaceconstant{sectionset}{sectionset}
+\setinterfaceconstant{sectionstarter}{sectionstarter}
+\setinterfaceconstant{sectionstopper}{sectionstopper}
+\setinterfaceconstant{separator}{separator}
+\setinterfaceconstant{set}{set}
+\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{side}{side}
+\setinterfaceconstant{sidealign}{sidealign}
+\setinterfaceconstant{sidemethod}{sidemethod}
+\setinterfaceconstant{sidespaceafter}{sidespaceafter}
+\setinterfaceconstant{sidespacebefore}{sidespacebefore}
+\setinterfaceconstant{sign}{sign}
+\setinterfaceconstant{size}{size}
+\setinterfaceconstant{small}{small}
+\setinterfaceconstant{sort}{sort}
+\setinterfaceconstant{sorttype}{sorttype}
+\setinterfaceconstant{source}{source}
+\setinterfaceconstant{space}{space}
+\setinterfaceconstant{spaceafter}{spaceafter}
+\setinterfaceconstant{spacebefore}{spacebefore}
+\setinterfaceconstant{spaceinbetween}{spaceinbetween}
+\setinterfaceconstant{spacing}{spacing}
+\setinterfaceconstant{split}{split}
+\setinterfaceconstant{splitcolor}{splitcolor}
+\setinterfaceconstant{splitmethod}{splitmethod}
+\setinterfaceconstant{splitoffset}{splitoffset}
+\setinterfaceconstant{spot}{spot}
+\setinterfaceconstant{stack}{stack}
+\setinterfaceconstant{start}{start}
+\setinterfaceconstant{starter}{starter}
+\setinterfaceconstant{state}{state}
+\setinterfaceconstant{step}{step}
+\setinterfaceconstant{stop}{stop}
+\setinterfaceconstant{stopper}{stopper}
+\setinterfaceconstant{stretch}{stretch}
+\setinterfaceconstant{strip}{strip}
+\setinterfaceconstant{strut}{strut}
+\setinterfaceconstant{style}{style}
+\setinterfaceconstant{sub}{sub}
+\setinterfaceconstant{subtitle}{subtitle}
+\setinterfaceconstant{suffix}{suffix}
+\setinterfaceconstant{surnamesep}{surnamesep}
+\setinterfaceconstant{sx}{sx}
+\setinterfaceconstant{sy}{sy}
+\setinterfaceconstant{symalign}{symalign}
+\setinterfaceconstant{symbol}{symbol}
+\setinterfaceconstant{symbolset}{symbolset}
+\setinterfaceconstant{symcolor}{symcolor}
+\setinterfaceconstant{symstyle}{symstyle}
+\setinterfaceconstant{synonym}{synonym}
+\setinterfaceconstant{synonymcolor}{synonymcolor}
+\setinterfaceconstant{synonymcommand}{synonymcommand}
+\setinterfaceconstant{synonymstyle}{synonymstyle}
+\setinterfaceconstant{tab}{tab}
+\setinterfaceconstant{text}{text}
+\setinterfaceconstant{textcolor}{textcolor}
+\setinterfaceconstant{textcommand}{textcommand}
+\setinterfaceconstant{textdistance}{textdistance}
+\setinterfaceconstant{textlayer}{textlayer}
+\setinterfaceconstant{textmargin}{textmargin}
+\setinterfaceconstant{textmethod}{textmethod}
+\setinterfaceconstant{textseparator}{textseparator}
+\setinterfaceconstant{textsize}{textsize}
+\setinterfaceconstant{textstate}{textstate}
+\setinterfaceconstant{textstyle}{textstyle}
+\setinterfaceconstant{textwidth}{textwidth}
+\setinterfaceconstant{title}{title}
+\setinterfaceconstant{titlecolor}{titlecolor}
+\setinterfaceconstant{titlecommand}{titlecommand}
+\setinterfaceconstant{titledistance}{titledistance}
+\setinterfaceconstant{titleleft}{titleleft}
+\setinterfaceconstant{titleright}{titleright}
+\setinterfaceconstant{titlestyle}{titlestyle}
+\setinterfaceconstant{to}{to}
+\setinterfaceconstant{tolerance}{tolerance}
+\setinterfaceconstant{top}{top}
+\setinterfaceconstant{topdistance}{topdistance}
+\setinterfaceconstant{topframe}{topframe}
+\setinterfaceconstant{topoffset}{topoffset}
+\setinterfaceconstant{topspace}{topspace}
+\setinterfaceconstant{topstate}{topstate}
+\setinterfaceconstant{totalnumber}{totalnumber}
+\setinterfaceconstant{type}{type}
+\setinterfaceconstant{unit}{unit}
+\setinterfaceconstant{unknownreference}{unknownreference}
+\setinterfaceconstant{urlalternative}{urlalternative}
+\setinterfaceconstant{urlspace}{urlspace}
+\setinterfaceconstant{validate}{validate}
+\setinterfaceconstant{vcommand}{vcommand}
+\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfil}{vfil}
+\setinterfaceconstant{voffset}{voffset}
+\setinterfaceconstant{vonsep}{vonsep}
+\setinterfaceconstant{way}{way}
+\setinterfaceconstant{wfactor}{wfactor}
+\setinterfaceconstant{white}{white}
+\setinterfaceconstant{width}{width}
+\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xmax}{xmax}
+\setinterfaceconstant{xoffset}{xoffset}
+\setinterfaceconstant{xscale}{xscale}
+\setinterfaceconstant{xstep}{xstep}
+\setinterfaceconstant{yfactor}{yfactor}
+\setinterfaceconstant{ymax}{ymax}
+\setinterfaceconstant{yoffset}{yoffset}
+\setinterfaceconstant{yscale}{yscale}
+\setinterfaceconstant{ystep}{ystep}
+% definitions for interface elements for language en
+%
+\setinterfaceelement{answerlines}{answerlines}
+\setinterfaceelement{answerspace}{answerspace}
+\setinterfaceelement{begin}{begin}
+\setinterfaceelement{complete}{complete}
+\setinterfaceelement{coupled}{coupled}
+\setinterfaceelement{currentlocal}{currentlocal}
+\setinterfaceelement{emptyone}{empty}
+\setinterfaceelement{emptytwo}{empty}
+\setinterfaceelement{end}{end}
+\setinterfaceelement{endsetup}{}
+\setinterfaceelement{get}{get}
+\setinterfaceelement{increment}{increment}
+\setinterfaceelement{list}{list}
+\setinterfaceelement{listof}{listof}
+\setinterfaceelement{load}{load}
+\setinterfaceelement{local}{local}
+\setinterfaceelement{makeup}{makeup}
+\setinterfaceelement{next}{next}
+\setinterfaceelement{place}{place}
+\setinterfaceelement{previous}{previous}
+\setinterfaceelement{previouslocal}{previouslocal}
+\setinterfaceelement{reserve}{reserve}
+\setinterfaceelement{see}{see}
+\setinterfaceelement{setup}{setup}
+\setinterfaceelement{start}{start}
+\setinterfaceelement{stop}{stop}
+\setinterfaceelement{text}{text}
+\setinterfaceelement{type}{type}
+% definitions for interface commands for language en
+%
+\setinterfacecommand{CAPPED}{CAP}
+\setinterfacecommand{Character}{Character}
+\setinterfacecommand{Characters}{Characters}
+\setinterfacecommand{LABELTEXT}{LABELTEXT}
+\setinterfacecommand{MONTH}{MONTH}
+\setinterfacecommand{Numbers}{Numbers}
+\setinterfacecommand{Romannumerals}{Romannumerals}
+\setinterfacecommand{SmallCapped}{Cap}
+\setinterfacecommand{SmallCaps}{Caps}
+\setinterfacecommand{WEEKDAY}{WEEKDAY}
+\setinterfacecommand{WORD}{WORD}
+\setinterfacecommand{WORDS}{WORDS}
+\setinterfacecommand{Word}{Word}
+\setinterfacecommand{Words}{Words}
+\setinterfacecommand{about}{about}
+\setinterfacecommand{adaptlayout}{adaptlayout}
+\setinterfacecommand{arg}{arg}
+\setinterfacecommand{at}{at}
+\setinterfacecommand{atleftmargin}{atleftmargin}
+\setinterfacecommand{atpage}{atpage}
+\setinterfacecommand{atrightmargin}{atrightmargin}
+\setinterfacecommand{background}{background}
+\setinterfacecommand{backspace}{backspace}
+\setinterfacecommand{blackrule}{blackrule}
+\setinterfacecommand{blackrules}{blackrules}
+\setinterfacecommand{blank}{blank}
+\setinterfacecommand{bookmark}{bookmark}
+\setinterfacecommand{bottomdistance}{bottomdistance}
+\setinterfacecommand{bottomheight}{bottomheight}
+\setinterfacecommand{bottomspace}{bottomspace}
+\setinterfacecommand{but}{but}
+\setinterfacecommand{button}{button}
+\setinterfacecommand{bypassblocks}{bypassblocks}
+\setinterfacecommand{character}{character}
+\setinterfacecommand{characters}{characters}
+\setinterfacecommand{chem}{chem}
+\setinterfacecommand{clip}{clip}
+\setinterfacecommand{clonefield}{clonefield}
+\setinterfacecommand{color}{color}
+\setinterfacecommand{colorbar}{colorbar}
+\setinterfacecommand{colorvalue}{colorvalue}
+\setinterfacecommand{column}{column}
+\setinterfacecommand{comment}{comment}
+\setinterfacecommand{comparecolorgroup}{comparecolorgroup}
+\setinterfacecommand{comparepalet}{comparepalet}
+\setinterfacecommand{completepagenumber}{completepagenumber}
+\setinterfacecommand{completeregister}{completeregister}
+\setinterfacecommand{component}{component}
+\setinterfacecommand{convertnumber}{convertnumber}
+\setinterfacecommand{copyfield}{copyfield}
+\setinterfacecommand{correctwhitespace}{correctwhitespace}
+\setinterfacecommand{coupledocument}{coupledocument}
+\setinterfacecommand{couplemarking}{couplemarking}
+\setinterfacecommand{couplepage}{couplepage}
+\setinterfacecommand{couplepaper}{couplepaper}
+\setinterfacecommand{coupleregister}{coupleregister}
+\setinterfacecommand{crlf}{crlf}
+\setinterfacecommand{currentdate}{currentdate}
+\setinterfacecommand{currentheadnumber}{currentheadnumber}
+\setinterfacecommand{cutspace}{cutspace}
+\setinterfacecommand{date}{date}
+\setinterfacecommand{decouplemarking}{decouplemarking}
+\setinterfacecommand{decrementnumber}{decrementnumber}
+\setinterfacecommand{define}{define}
+\setinterfacecommand{defineaccent}{defineaccent}
+\setinterfacecommand{defineblank}{defineblank}
+\setinterfacecommand{defineblock}{defineblock}
+\setinterfacecommand{definebodyfont}{definebodyfont}
+\setinterfacecommand{definebodyfontenvironment}{definebodyfontenvironment}
+\setinterfacecommand{definebuffer}{definebuffer}
+\setinterfacecommand{definecharacter}{definecharacter}
+\setinterfacecommand{definecolor}{definecolor}
+\setinterfacecommand{definecolorgroup}{definecolorgroup}
+\setinterfacecommand{definecolumnbreak}{definecolumnbreak}
+\setinterfacecommand{definecolumnset}{definecolumnset}
+\setinterfacecommand{definecombination}{definecombination}
+\setinterfacecommand{definecombinedlist}{definecombinedlist}
+\setinterfacecommand{definecommand}{definecommand}
+\setinterfacecommand{defineconversion}{defineconversion}
+\setinterfacecommand{definedescription}{definedescription}
+\setinterfacecommand{defineenumeration}{defineenumeration}
+\setinterfacecommand{definefield}{definefield}
+\setinterfacecommand{definefieldstack}{definefieldstack}
+\setinterfacecommand{definefiguresymbol}{definefiguresymbol}
+\setinterfacecommand{definefloat}{definefloat}
+\setinterfacecommand{definefont}{definefont}
+\setinterfacecommand{definefontstyle}{definefontstyle}
+\setinterfacecommand{definefontsynonym}{definefontsynonym}
+\setinterfacecommand{defineframed}{defineframed}
+\setinterfacecommand{defineframedtext}{defineframedtext}
+\setinterfacecommand{definehbox}{definehbox}
+\setinterfacecommand{definehead}{definehead}
+\setinterfacecommand{defineindenting}{defineindenting}
+\setinterfacecommand{defineinmargin}{defineinmargin}
+\setinterfacecommand{defineinteractionmenu}{defineinteractionmenu}
+\setinterfacecommand{defineitemgroup}{defineitemgroup}
+\setinterfacecommand{definelabel}{definelabel}
+\setinterfacecommand{definelayer}{definelayer}
+\setinterfacecommand{definelayout}{definelayout}
+\setinterfacecommand{definelist}{definelist}
+\setinterfacecommand{definelogo}{definelogo}
+\setinterfacecommand{definemainfield}{definemainfield}
+\setinterfacecommand{definemakeup}{definemakeup}
+\setinterfacecommand{definemarking}{definemarking}
+\setinterfacecommand{definemathalignment}{definemathalignment}
+\setinterfacecommand{defineoutput}{defineoutput}
+\setinterfacecommand{defineoverlay}{defineoverlay}
+\setinterfacecommand{definepagebreak}{definepagebreak}
+\setinterfacecommand{definepalet}{definepalet}
+\setinterfacecommand{definepapersize}{definepapersize}
+\setinterfacecommand{defineparagraphs}{defineparagraphs}
+\setinterfacecommand{defineplacement}{defineplacement}
+\setinterfacecommand{defineprofile}{defineprofile}
+\setinterfacecommand{defineprogram}{defineprogram}
+\setinterfacecommand{definerawfont}{definerawfont}
+\setinterfacecommand{definereference}{definereference}
+\setinterfacecommand{definereferenceformat}{definereferenceformat}
+\setinterfacecommand{definereferencelist}{definereferencelist}
+\setinterfacecommand{defineregister}{defineregister}
+\setinterfacecommand{definerule}{definerule}
+\setinterfacecommand{definesection}{definesection}
+\setinterfacecommand{definesectionblock}{definesectionblock}
+\setinterfacecommand{definesorting}{definesorting}
+\setinterfacecommand{definestartstop}{definestartstop}
+\setinterfacecommand{definestyle}{definestyle}
+\setinterfacecommand{definesubfield}{definesubfield}
+\setinterfacecommand{definesymbol}{definesymbol}
+\setinterfacecommand{definesynonyms}{definesynonyms}
+\setinterfacecommand{definetabletemplate}{definetabletemplate}
+\setinterfacecommand{definetabulate}{definetabulate}
+\setinterfacecommand{definetext}{definetext}
+\setinterfacecommand{definetextposition}{definetextposition}
+\setinterfacecommand{definetextvariable}{definetextvariable}
+\setinterfacecommand{definetype}{definetype}
+\setinterfacecommand{definetyping}{definetyping}
+\setinterfacecommand{defineversion}{defineversion}
+\setinterfacecommand{determineheadnumber}{determineheadnumber}
+\setinterfacecommand{determinelistcharacteristics}{determinelistcharacteristics}
+\setinterfacecommand{determineregistercharacteristics}{determineregistercharacteristics}
+\setinterfacecommand{dimension}{dimension}
+\setinterfacecommand{disableinteractionmenu}{disableinteractionmenu}
+\setinterfacecommand{domicile}{domicile}
+\setinterfacecommand{donttest}{donttest}
+\setinterfacecommand{edgedistance}{edgedistance}
+\setinterfacecommand{edgewidth}{edgewidth}
+\setinterfacecommand{emptylines}{emptylines}
+\setinterfacecommand{environment}{environment}
+\setinterfacecommand{externalfigure}{externalfigure}
+\setinterfacecommand{fact}{fact}
+\setinterfacecommand{field}{field}
+\setinterfacecommand{fieldstack}{fieldstack}
+\setinterfacecommand{fillinfield}{fillinfield}
+\setinterfacecommand{fillinline}{fillinline}
+\setinterfacecommand{fillinrules}{fillinrules}
+\setinterfacecommand{fillintext}{fillintext}
+\setinterfacecommand{fitfield}{fitfield}
+\setinterfacecommand{fixedspace}{fixedspace}
+\setinterfacecommand{fixedspaces}{fixedspaces}
+\setinterfacecommand{followprofile}{followprofile}
+\setinterfacecommand{followprofileversion}{followprofileversion}
+\setinterfacecommand{followversion}{followversion}
+\setinterfacecommand{footerdistance}{footerdistance}
+\setinterfacecommand{footerheight}{footerheight}
+\setinterfacecommand{footnote}{footnote}
+\setinterfacecommand{footnotetext}{footnotetext}
+\setinterfacecommand{forceblocks}{forceblocks}
+\setinterfacecommand{formulanumber}{formulanumber}
+\setinterfacecommand{fraction}{fraction}
+\setinterfacecommand{framed}{framed}
+\setinterfacecommand{from}{from}
+\setinterfacecommand{getbuffer}{getbuffer}
+\setinterfacecommand{getmarking}{getmarking}
+\setinterfacecommand{getnumber}{getnumber}
+\setinterfacecommand{godown}{godown}
+\setinterfacecommand{goto}{goto}
+\setinterfacecommand{gotobox}{gotobox}
+\setinterfacecommand{gotopage}{gotopage}
+\setinterfacecommand{graycolor}{graycolor}
+\setinterfacecommand{greyvalue}{greyvalue}
+\setinterfacecommand{grid}{grid}
+\setinterfacecommand{hairline}{hairline}
+\setinterfacecommand{head}{head}
+\setinterfacecommand{headerdistance}{headerdistance}
+\setinterfacecommand{headerheight}{headerheight}
+\setinterfacecommand{headlevel}{headlevel}
+\setinterfacecommand{headnumber}{headnumber}
+\setinterfacecommand{headsym}{headsym}
+\setinterfacecommand{headtext}{headtext}
+\setinterfacecommand{hideblocks}{hideblocks}
+\setinterfacecommand{high}{high}
+\setinterfacecommand{hl}{hl}
+\setinterfacecommand{immediatebetweenlist}{immediatebetweenlist}
+\setinterfacecommand{immediatetolist}{immediatetolist}
+\setinterfacecommand{in}{in}
+\setinterfacecommand{incrementnumber}{incrementnumber}
+\setinterfacecommand{indenting}{indenting}
+\setinterfacecommand{inframed}{inframed}
+\setinterfacecommand{infull}{infull}
+\setinterfacecommand{ininner}{ininner}
+\setinterfacecommand{inleft}{inleft}
+\setinterfacecommand{inleftedge}{inleftedge}
+\setinterfacecommand{inleftmargin}{inleftmargin}
+\setinterfacecommand{inline}{inline}
+\setinterfacecommand{inmargin}{inmargin}
+\setinterfacecommand{inmframed}{inmaframed}
+\setinterfacecommand{inneredgedistance}{inneredgedistance}
+\setinterfacecommand{inneredgewidth}{inneredgewidth}
+\setinterfacecommand{innermargindistance}{innermargindistance}
+\setinterfacecommand{innermarginwidth}{innermarginwidth}
+\setinterfacecommand{inothermargin}{inothermargin}
+\setinterfacecommand{inouter}{inouter}
+\setinterfacecommand{inright}{inright}
+\setinterfacecommand{inrightedge}{inrightedge}
+\setinterfacecommand{inrightmargin}{inrightmargin}
+\setinterfacecommand{installlanguage}{installlanguage}
+\setinterfacecommand{interactionbar}{interactionbar}
+\setinterfacecommand{interactionbuttons}{interactionbuttons}
+\setinterfacecommand{interactionmenu}{interactionmenu}
+\setinterfacecommand{item}{item}
+\setinterfacecommand{items}{items}
+\setinterfacecommand{its}{its}
+\setinterfacecommand{keepblocks}{keepblocks}
+\setinterfacecommand{label}{label}
+\setinterfacecommand{labels}{labels}
+\setinterfacecommand{labeltext}{labeltext}
+\setinterfacecommand{language}{language}
+\setinterfacecommand{leftaligned}{leftaligned}
+\setinterfacecommand{leftedgedistance}{leftedgedistance}
+\setinterfacecommand{leftedgewidth}{leftedgewidth}
+\setinterfacecommand{leftmargindistance}{leftmargindistance}
+\setinterfacecommand{leftmarginwidth}{leftmarginwidth}
+\setinterfacecommand{leg}{leg}
+\setinterfacecommand{linewidth}{linethickness}
+\setinterfacecommand{listheight}{listheight}
+\setinterfacecommand{listlength}{listlength}
+\setinterfacecommand{listsymbol}{listsymbol}
+\setinterfacecommand{listwidth}{listwidth}
+\setinterfacecommand{logfields}{logfields}
+\setinterfacecommand{lohi}{lohi}
+\setinterfacecommand{low}{low}
+\setinterfacecommand{macroname}{name}
+\setinterfacecommand{mainlanguage}{mainlanguage}
+\setinterfacecommand{makeupheight}{makeupheight}
+\setinterfacecommand{makeupwidth}{makeupwidth}
+\setinterfacecommand{mar}{mar}
+\setinterfacecommand{margindistance}{margindistance}
+\setinterfacecommand{marginrule}{marginrule}
+\setinterfacecommand{margintext}{margintext}
+\setinterfacecommand{margintitle}{margintitle}
+\setinterfacecommand{marginwidth}{marginwidth}
+\setinterfacecommand{marginword}{marginword}
+\setinterfacecommand{marking}{marking}
+\setinterfacecommand{markversion}{markversion}
+\setinterfacecommand{mathematics}{mathematics}
+\setinterfacecommand{menubutton}{menubutton}
+\setinterfacecommand{mframed}{maframed}
+\setinterfacecommand{midaligned}{midaligned}
+\setinterfacecommand{mirror}{mirror}
+\setinterfacecommand{month}{month}
+\setinterfacecommand{moveformula}{moveformula}
+\setinterfacecommand{moveongrid}{moveongrid}
+\setinterfacecommand{movesidefloat}{movesidefloat}
+\setinterfacecommand{navigating}{navigating}
+\setinterfacecommand{nodimension}{nodimension}
+\setinterfacecommand{noheaderandfooterlines}{noheaderandfooterlines}
+\setinterfacecommand{noindenting}{noindenting}
+\setinterfacecommand{nolist}{nolist}
+\setinterfacecommand{nomarking}{nomarking}
+\setinterfacecommand{nomoreblocks}{nomoreblocks}
+\setinterfacecommand{nomorefiles}{nomorefiles}
+\setinterfacecommand{nop}{nop}
+\setinterfacecommand{nospace}{nospace}
+\setinterfacecommand{note}{note}
+\setinterfacecommand{notopandbottomlines}{notopandbottomlines}
+\setinterfacecommand{notsmallcapped}{nocap}
+\setinterfacecommand{nowhitespace}{nowhitespace}
+\setinterfacecommand{numberofsubpages}{numberofsubpages}
+\setinterfacecommand{numbers}{numbers}
+\setinterfacecommand{outeredgedistance}{outeredgedistance}
+\setinterfacecommand{outeredgewidth}{outeredgewidth}
+\setinterfacecommand{outermargindistance}{outermargindistance}
+\setinterfacecommand{outermarginwidth}{outermarginwidth}
+\setinterfacecommand{packed}{packed}
+\setinterfacecommand{page}{page}
+\setinterfacecommand{pagedepth}{pagedepth}
+\setinterfacecommand{pagenumber}{pagenumber}
+\setinterfacecommand{pageoffset}{pageoffset}
+\setinterfacecommand{pagereference}{pagereference}
+\setinterfacecommand{pagetype}{pagetype}
+\setinterfacecommand{paperheight}{paperheight}
+\setinterfacecommand{paperwidth}{paperwidth}
+\setinterfacecommand{periods}{periods}
+\setinterfacecommand{plaatsruwelijst}{placerawlist}
+\setinterfacecommand{placebookmarks}{placebookmarks}
+\setinterfacecommand{placecombinedlist}{placecombinedlist}
+\setinterfacecommand{placefloat}{placefloat}
+\setinterfacecommand{placefootnotes}{placefootnotes}
+\setinterfacecommand{placeformula}{placeformula}
+\setinterfacecommand{placeheadnumber}{placeheadnumber}
+\setinterfacecommand{placeheadtext}{placeheadtext}
+\setinterfacecommand{placelegend}{placelegend}
+\setinterfacecommand{placelist}{placelist}
+\setinterfacecommand{placelocalfootnotes}{placelocalfootnotes}
+\setinterfacecommand{placelogos}{placelogos}
+\setinterfacecommand{placeongrid}{placeongrid}
+\setinterfacecommand{placeontopofeachother}{placeontopofeachother}
+\setinterfacecommand{placepagenumber}{placepagenumber}
+\setinterfacecommand{placereferencelist}{placereferencelist}
+\setinterfacecommand{placeregister}{placeregister}
+\setinterfacecommand{placerule}{placerule}
+\setinterfacecommand{placesidebyside}{placesidebyside}
+\setinterfacecommand{placesubformula}{placesubformula}
+\setinterfacecommand{placetextvariable}{placetextvariable}
+\setinterfacecommand{position}{position}
+\setinterfacecommand{positiontext}{positiontext}
+\setinterfacecommand{printpaperheight}{printpaperheight}
+\setinterfacecommand{printpaperwidth}{printpaperwidth}
+\setinterfacecommand{processblocks}{processblocks}
+\setinterfacecommand{processpage}{processpage}
+\setinterfacecommand{product}{product}
+\setinterfacecommand{program}{program}
+\setinterfacecommand{project}{project}
+\setinterfacecommand{publication}{publication}
+\setinterfacecommand{quotation}{quotation}
+\setinterfacecommand{quote}{quote}
+\setinterfacecommand{ran}{ran}
+\setinterfacecommand{redo}{redo}
+\setinterfacecommand{ref}{ref}
+\setinterfacecommand{reference}{reference}
+\setinterfacecommand{referral}{referral}
+\setinterfacecommand{referraldate}{referraldate}
+\setinterfacecommand{referring}{referring}
+\setinterfacecommand{remark}{remark}
+\setinterfacecommand{reset}{reset}
+\setinterfacecommand{resetmarking}{resetmarking}
+\setinterfacecommand{resetnumber}{resetnumber}
+\setinterfacecommand{resettext}{resettextcontent}
+\setinterfacecommand{rightaligned}{rightaligned}
+\setinterfacecommand{rightedgedistance}{rightedgedistance}
+\setinterfacecommand{rightedgewidth}{rightedgewidth}
+\setinterfacecommand{rightmargindistance}{rightmargindistance}
+\setinterfacecommand{rightmarginwidth}{rightmarginwidth}
+\setinterfacecommand{romannumerals}{romannumerals}
+\setinterfacecommand{rotate}{rotate}
+\setinterfacecommand{scale}{scale}
+\setinterfacecommand{screen}{screen}
+\setinterfacecommand{selectblocks}{selectblocks}
+\setinterfacecommand{selectpaper}{selectpaper}
+\setinterfacecommand{selectversion}{selectversion}
+\setinterfacecommand{setnumber}{setnumber}
+\setinterfacecommand{settextcontent}{settextcontent}
+\setinterfacecommand{settextvariable}{settextvariable}
+\setinterfacecommand{setupalign}{setupalign}
+\setinterfacecommand{setupanswerarea}{setupanswerarea}
+\setinterfacecommand{setuparranging}{setuparranging}
+\setinterfacecommand{setupbackground}{setupbackground}
+\setinterfacecommand{setupbackgrounds}{setupbackgrounds}
+\setinterfacecommand{setupblackrules}{setupblackrules}
+\setinterfacecommand{setupblank}{setupblank}
+\setinterfacecommand{setupblock}{setupblock}
+\setinterfacecommand{setupbodyfont}{setupbodyfont}
+\setinterfacecommand{setupbodyfontenvironment}{setupbodyfontenvironment}
+\setinterfacecommand{setupbottom}{setupbottom}
+\setinterfacecommand{setupbottomtexts}{setupbottomtexts}
+\setinterfacecommand{setupbuffer}{setupbuffer}
+\setinterfacecommand{setupbuttons}{setupbuttons}
+\setinterfacecommand{setupcapitals}{setupcapitals}
+\setinterfacecommand{setupcaption}{setupcaption}
+\setinterfacecommand{setupcaptions}{setupcaptions}
+\setinterfacecommand{setupclipping}{setupclipping}
+\setinterfacecommand{setupcolor}{setupcolor}
+\setinterfacecommand{setupcolors}{setupcolors}
+\setinterfacecommand{setupcolumns}{setupcolumns}
+\setinterfacecommand{setupcolumnset}{setupcolumnset}
+\setinterfacecommand{setupcolumnsetlines}{setupcolumnsetlines}
+\setinterfacecommand{setupcolumnsetstart}{setupcolumnsetstart}
+\setinterfacecommand{setupcombinations}{setupcombinations}
+\setinterfacecommand{setupcombinedlist}{setupcombinedlist}
+\setinterfacecommand{setupcomment}{setupcomment}
+\setinterfacecommand{setupdescriptions}{setupdescriptions}
+\setinterfacecommand{setupenumerations}{setupenumerations}
+\setinterfacecommand{setupexternalfigures}{setupexternalfigures}
+\setinterfacecommand{setupfield}{setupfield}
+\setinterfacecommand{setupfields}{setupfields}
+\setinterfacecommand{setupfillinlines}{setupfillinlines}
+\setinterfacecommand{setupfillinrules}{setupfillinrules}
+\setinterfacecommand{setupfloat}{setupfloat}
+\setinterfacecommand{setupfloats}{setupfloats}
+\setinterfacecommand{setupfloatsplitting}{setupfloatsplitting}
+\setinterfacecommand{setupfooter}{setupfooter}
+\setinterfacecommand{setupfootertexts}{setupfootertexts}
+\setinterfacecommand{setupfootnotedefinition}{setupfootnotedefinition}
+\setinterfacecommand{setupfootnotes}{setupfootnotes}
+\setinterfacecommand{setupforms}{setupforms}
+\setinterfacecommand{setupformulas}{setupformulae}
+\setinterfacecommand{setupframed}{setupframed}
+\setinterfacecommand{setupframedtexts}{setupframedtexts}
+\setinterfacecommand{setuphead}{setuphead}
+\setinterfacecommand{setupheader}{setupheader}
+\setinterfacecommand{setupheadertexts}{setupheadertexts}
+\setinterfacecommand{setupheadnumber}{setupheadnumber}
+\setinterfacecommand{setupheads}{setupheads}
+\setinterfacecommand{setupheadtext}{setupheadtext}
+\setinterfacecommand{setuphyphenmark}{setuphyphenmark}
+\setinterfacecommand{setupindentations}{setupindentations}
+\setinterfacecommand{setupindenting}{setupindenting}
+\setinterfacecommand{setupinmargin}{setupinmargin}
+\setinterfacecommand{setupinteraction}{setupinteraction}
+\setinterfacecommand{setupinteractionbar}{setupinteractionbar}
+\setinterfacecommand{setupinteractionmenu}{setupinteractionmenu}
+\setinterfacecommand{setupinteractionscreen}{setupinteractionscreen}
+\setinterfacecommand{setupinterlinespace}{setupinterlinespace}
+\setinterfacecommand{setupitemgroup}{setupitemgroup}
+\setinterfacecommand{setupitemgroups}{setupitemizations}
+\setinterfacecommand{setupitems}{setupitems}
+\setinterfacecommand{setuplabeltext}{setuplabeltext}
+\setinterfacecommand{setuplanguage}{setuplanguage}
+\setinterfacecommand{setuplayout}{setuplayout}
+\setinterfacecommand{setuplegend}{setuplegend}
+\setinterfacecommand{setuplinenumbering}{setuplinenumbering}
+\setinterfacecommand{setuplines}{setuplines}
+\setinterfacecommand{setuplinewidth}{setuplinewidth}
+\setinterfacecommand{setuplist}{setuplist}
+\setinterfacecommand{setupmakeup}{setupmakeup}
+\setinterfacecommand{setupmarginblocks}{setupmarginblocks}
+\setinterfacecommand{setupmarginrules}{setupmarginrules}
+\setinterfacecommand{setupmarking}{setupmarking}
+\setinterfacecommand{setupmathalignment}{setupmathalignment}
+\setinterfacecommand{setupnarrower}{setupnarrower}
+\setinterfacecommand{setupnumber}{setupnumber}
+\setinterfacecommand{setupnumbering}{setupnumbering}
+\setinterfacecommand{setupoppositeplacing}{setupoppositeplacing}
+\setinterfacecommand{setupoutput}{setupoutput}
+\setinterfacecommand{setuppagecomment}{setuppagecomment}
+\setinterfacecommand{setuppagenumber}{setuppagenumber}
+\setinterfacecommand{setuppagenumbering}{setuppagenumbering}
+\setinterfacecommand{setuppagetransitions}{setuppagetransitions}
+\setinterfacecommand{setuppalet}{setuppalet}
+\setinterfacecommand{setuppaper}{setuppaper}
+\setinterfacecommand{setuppapersize}{setuppapersize}
+\setinterfacecommand{setupparagraphnumbering}{setupparagraphnumbering}
+\setinterfacecommand{setupparagraphs}{setupparagraphs}
+\setinterfacecommand{setupplacement}{setupplacement}
+\setinterfacecommand{setuppositioning}{setuppositioning}
+\setinterfacecommand{setupprofiles}{setupprofiles}
+\setinterfacecommand{setupprograms}{setupprograms}
+\setinterfacecommand{setuppublications}{setuppublications}
+\setinterfacecommand{setupquote}{setupquote}
+\setinterfacecommand{setupreferencelist}{setupreferencelist}
+\setinterfacecommand{setupreferencing}{setupreferencing}
+\setinterfacecommand{setupregister}{setupregister}
+\setinterfacecommand{setuprotate}{setuprotate}
+\setinterfacecommand{setuprule}{setuprule}
+\setinterfacecommand{setups}{setups}
+\setinterfacecommand{setupscreens}{setupscreens}
+\setinterfacecommand{setupsection}{setupsection}
+\setinterfacecommand{setupsectionblock}{setupsectionblock}
+\setinterfacecommand{setupsorting}{setupsorting}
+\setinterfacecommand{setupspacing}{setupspacing}
+\setinterfacecommand{setupstartstop}{setupstartstop}
+\setinterfacecommand{setupstrut}{setupstrut}
+\setinterfacecommand{setupsubpagenumber}{setupsubpagenumber}
+\setinterfacecommand{setupsymbolset}{setupsymbolset}
+\setinterfacecommand{setupsynchronization}{setupsynchronization}
+\setinterfacecommand{setupsynchronizationbar}{setupsynchronizationbar}
+\setinterfacecommand{setupsynonyms}{setupsynonyms}
+\setinterfacecommand{setupsystem}{setupsystem}
+\setinterfacecommand{setuptab}{setuptab}
+\setinterfacecommand{setuptables}{setuptables}
+\setinterfacecommand{setuptabulate}{setuptabulate}
+\setinterfacecommand{setuptext}{setuptext}
+\setinterfacecommand{setuptextposition}{setuptextposition}
+\setinterfacecommand{setuptextrules}{setuptextrules}
+\setinterfacecommand{setuptexttexts}{setuptexttexts}
+\setinterfacecommand{setuptextvariable}{setuptextvariable}
+\setinterfacecommand{setupthinrules}{setupthinrules}
+\setinterfacecommand{setuptolerance}{setuptolerance}
+\setinterfacecommand{setuptop}{setuptop}
+\setinterfacecommand{setuptoptexts}{setuptoptexts}
+\setinterfacecommand{setuptype}{setuptype}
+\setinterfacecommand{setuptyping}{setuptyping}
+\setinterfacecommand{setupunderbar}{setupunderbar}
+\setinterfacecommand{setupurl}{setupurl}
+\setinterfacecommand{setupversions}{setupversions}
+\setinterfacecommand{setupwhitespace}{setupwhitespace}
+\setinterfacecommand{showbodyfont}{showbodyfont}
+\setinterfacecommand{showbodyfontenvironment}{showbodyfontenvironment}
+\setinterfacecommand{showcolor}{showcolor}
+\setinterfacecommand{showcolorgroup}{showcolorgroup}
+\setinterfacecommand{showexternalfigures}{showexternalfigures}
+\setinterfacecommand{showfields}{showfields}
+\setinterfacecommand{showframe}{showframe}
+\setinterfacecommand{showgrid}{showgrid}
+\setinterfacecommand{showlayout}{showlayout}
+\setinterfacecommand{showmakeup}{showmakeup}
+\setinterfacecommand{showpalet}{showpalet}
+\setinterfacecommand{showprint}{showprint}
+\setinterfacecommand{showsetups}{showsetups}
+\setinterfacecommand{showstruts}{showstruts}
+\setinterfacecommand{showsymbolset}{showsymbolset}
+\setinterfacecommand{smallcapped}{cap}
+\setinterfacecommand{someline}{someline}
+\setinterfacecommand{somewhere}{somewhere}
+\setinterfacecommand{space}{space}
+\setinterfacecommand{splitfloat}{splitfloat}
+\setinterfacecommand{startalignment}{startalignment}
+\setinterfacecommand{startbackground}{startbackground}
+\setinterfacecommand{startcoding}{startcoding}
+\setinterfacecommand{startcolor}{startcolor}
+\setinterfacecommand{startcolumnmakeup}{startcolumnmakeup}
+\setinterfacecommand{startcolumns}{startcolumns}
+\setinterfacecommand{startcolumnset}{startcolumnset}
+\setinterfacecommand{startcombination}{startcombination}
+\setinterfacecommand{startcomponent}{startcomponent}
+\setinterfacecommand{startdocument}{startdocument}
+\setinterfacecommand{startenvironment}{startenvironment}
+\setinterfacecommand{startfigure}{startfigure}
+\setinterfacecommand{startglobal}{startglobal}
+\setinterfacecommand{startline}{startline}
+\setinterfacecommand{startlinecorrection}{startlinecorrection}
+\setinterfacecommand{startlinenumbering}{startlinenumbering}
+\setinterfacecommand{startlines}{startlines}
+\setinterfacecommand{startlocal}{startlocal}
+\setinterfacecommand{startlocalfootnotes}{startlocalfootnotes}
+\setinterfacecommand{startmakeup}{startmakeup}
+\setinterfacecommand{startmarginblock}{startmarginblock}
+\setinterfacecommand{startmarginrule}{startmarginrule}
+\setinterfacecommand{startnarrower}{startnarrower}
+\setinterfacecommand{startopposite}{startopposite}
+\setinterfacecommand{startoverlay}{startoverlay}
+\setinterfacecommand{startoverzicht}{startoverview}
+\setinterfacecommand{startpacked}{startpacked}
+\setinterfacecommand{startpositioning}{startpositioning}
+\setinterfacecommand{startproduct}{startproduct}
+\setinterfacecommand{startprofile}{startprofile}
+\setinterfacecommand{startproject}{startproject}
+\setinterfacecommand{startquotation}{startquotation}
+\setinterfacecommand{startraster}{startraster}
+\setinterfacecommand{startsymbolset}{startsymbolset}
+\setinterfacecommand{startsynchronization}{startsynchronization}
+\setinterfacecommand{starttable}{starttable}
+\setinterfacecommand{starttables}{starttables}
+\setinterfacecommand{starttext}{starttext}
+\setinterfacecommand{starttextrule}{starttextrule}
+\setinterfacecommand{startunpacked}{startunpacked}
+\setinterfacecommand{startversion}{startversion}
+\setinterfacecommand{stopalignment}{stopalignment}
+\setinterfacecommand{stopbackground}{stopbackground}
+\setinterfacecommand{stopcoding}{stopcoding}
+\setinterfacecommand{stopcolor}{stopcolor}
+\setinterfacecommand{stopcolumnmakeup}{stopcolumnmakeup}
+\setinterfacecommand{stopcolumns}{stopcolumns}
+\setinterfacecommand{stopcolumnset}{stopcolumnset}
+\setinterfacecommand{stopcombination}{stopcombination}
+\setinterfacecommand{stopcomponent}{stopcomponent}
+\setinterfacecommand{stopdocument}{stopdocument}
+\setinterfacecommand{stopenvironment}{stopenvironment}
+\setinterfacecommand{stopglobal}{stopglobal}
+\setinterfacecommand{stopline}{stopline}
+\setinterfacecommand{stoplinecorrection}{stoplinecorrection}
+\setinterfacecommand{stoplinenumbering}{stoplinenumbering}
+\setinterfacecommand{stoplines}{stoplines}
+\setinterfacecommand{stoplocal}{stoplocal}
+\setinterfacecommand{stoplocalfootnotes}{stoplocalfootnotes}
+\setinterfacecommand{stopmakeup}{stopmakeup}
+\setinterfacecommand{stopmarginblock}{stopmarginblock}
+\setinterfacecommand{stopmarginrule}{stopmarginrule}
+\setinterfacecommand{stopnarrower}{stopnarrower}
+\setinterfacecommand{stopopposite}{stopopposite}
+\setinterfacecommand{stopoverlay}{stopoverlay}
+\setinterfacecommand{stopoverzicht}{stopoverview}
+\setinterfacecommand{stoppacked}{stoppacked}
+\setinterfacecommand{stoppositioning}{stoppositioning}
+\setinterfacecommand{stopproduct}{stopproduct}
+\setinterfacecommand{stopprofile}{stopprofile}
+\setinterfacecommand{stopproject}{stopproject}
+\setinterfacecommand{stopquotation}{stopquotation}
+\setinterfacecommand{stopraster}{stopraster}
+\setinterfacecommand{stopsynchronization}{stopsynchronization}
+\setinterfacecommand{stoptable}{stoptable}
+\setinterfacecommand{stoptables}{stoptables}
+\setinterfacecommand{stoptext}{stoptext}
+\setinterfacecommand{stoptextrule}{stoptextrule}
+\setinterfacecommand{stopunpacked}{stopunpacked}
+\setinterfacecommand{stopversion}{stopversion}
+\setinterfacecommand{stretched}{stretched}
+\setinterfacecommand{subformulanumber}{subformulanumber}
+\setinterfacecommand{subpagenumber}{subpagenumber}
+\setinterfacecommand{switchtobodyfont}{switchtobodyfont}
+\setinterfacecommand{switchtorawfont}{switchtorawfont}
+\setinterfacecommand{sym}{sym}
+\setinterfacecommand{symbol}{symbol}
+\setinterfacecommand{synchronizationbar}{synchronizationbar}
+\setinterfacecommand{synchronize}{synchronize}
+\setinterfacecommand{tab}{tab}
+\setinterfacecommand{testcolumn}{testcolumn}
+\setinterfacecommand{testpage}{testpage}
+\setinterfacecommand{tex}{tex}
+\setinterfacecommand{textheight}{textheight}
+\setinterfacecommand{textreference}{textreference}
+\setinterfacecommand{textrule}{textrule}
+\setinterfacecommand{textvariable}{textvariable}
+\setinterfacecommand{textwidth}{textwidth}
+\setinterfacecommand{thinrule}{thinrule}
+\setinterfacecommand{thinrules}{thinrules}
+\setinterfacecommand{tooltip}{tooltip}
+\setinterfacecommand{topdistance}{topdistance}
+\setinterfacecommand{topheight}{topheight}
+\setinterfacecommand{topspace}{topspace}
+\setinterfacecommand{totalnumberofpages}{totalnumberofpages}
+\setinterfacecommand{translate}{translate}
+\setinterfacecommand{txt}{txt}
+\setinterfacecommand{typ}{typ}
+\setinterfacecommand{type}{type}
+\setinterfacecommand{typebuffer}{typebuffer}
+\setinterfacecommand{typefile}{typefile}
+\setinterfacecommand{unitmeaning}{unitmeaning}
+\setinterfacecommand{unknown}{unknown}
+\setinterfacecommand{useJSscripts}{useJSscripts}
+\setinterfacecommand{useURL}{useURL}
+\setinterfacecommand{useXMLfilter}{useXMLfilter}
+\setinterfacecommand{useblocks}{useblocks}
+\setinterfacecommand{usecommands}{usecommands}
+\setinterfacecommand{useencoding}{useencoding}
+\setinterfacecommand{useexternaldocument}{useexternaldocument}
+\setinterfacecommand{useexternalfigure}{useexternalfigure}
+\setinterfacecommand{useexternalfile}{useexternalfile}
+\setinterfacecommand{useexternalfiles}{useexternalfiles}
+\setinterfacecommand{useexternalsoundtrack}{useexternalsoundtrack}
+\setinterfacecommand{usemodule}{usemodule}
+\setinterfacecommand{usemodules}{usemodules}
+\setinterfacecommand{usepath}{usedirectory}
+\setinterfacecommand{usereferences}{usereferences}
+\setinterfacecommand{usespecials}{usespecials}
+\setinterfacecommand{usesymbols}{usesymbols}
+\setinterfacecommand{usetypescript}{usetypescript}
+\setinterfacecommand{usetypescriptfile}{usetypescriptfile}
+\setinterfacecommand{useurl}{useurl}
+\setinterfacecommand{version}{version}
+\setinterfacecommand{vl}{vl}
+\setinterfacecommand{weekday}{weekday}
+\setinterfacecommand{whitespace}{whitespace}
+\setinterfacecommand{wordright}{wordright}
+\setinterfacecommand{writebetweenlist}{writebetweenlist}
+\setinterfacecommand{writetolist}{writetolist}
+\setinterfacecommand{writetoreferencelist}{writetoreferencelist}
+\setinterfacecommand{writetoregister}{writetoregister}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-fr.tex b/tex/context/base/mult-fr.tex
new file mode 100644
index 000000000..5244565e9
--- /dev/null
+++ b/tex/context/base/mult-fr.tex
@@ -0,0 +1,1693 @@
+% this file is auto-generated, don't edit this file
+%
+% definitions for interface variables for language fr
+%
+\setinterfacevariable{Addition}{Ajout}
+\setinterfacevariable{Balloon}{Ballon}
+\setinterfacevariable{Character}{Caratere}
+\setinterfacevariable{Characters}{Caracteres}
+\setinterfacevariable{CloseDocument}{FermeDocument}
+\setinterfacevariable{ExitViewer}{SortVisualisateur}
+\setinterfacevariable{FirstPage}{PremierePage}
+\setinterfacevariable{FitHeight}{AjusteHauteur}
+\setinterfacevariable{FitWidth}{AjusteLargeur}
+\setinterfacevariable{GotoPage}{VaalaPage}
+\setinterfacevariable{Greek}{Grec}
+\setinterfacevariable{Help}{Aide}
+\setinterfacevariable{HideField}{CacheChamp}
+\setinterfacevariable{HideLayer}{CacheCalque}
+\setinterfacevariable{Key}{Cle}
+\setinterfacevariable{LastPage}{DernierePage}
+\setinterfacevariable{LoadForm}{ChargeForm}
+\setinterfacevariable{MONTH}{MOIS}
+\setinterfacevariable{New}{Nouveau}
+\setinterfacevariable{NextJump}{SautSuivant}
+\setinterfacevariable{NextPage}{PageSuivante}
+\setinterfacevariable{Numbers}{Numeros}
+\setinterfacevariable{OpenNamedDocument}{OuvreDocumentNomme}
+\setinterfacevariable{Paragraph}{Paragraphe}
+\setinterfacevariable{PauseMovie}{PauseFilm}
+\setinterfacevariable{PauseRendering}{PauseRendering}
+\setinterfacevariable{PauseSound}{PauseSon}
+\setinterfacevariable{PreviousJump}{SautPrecedent}
+\setinterfacevariable{PreviousPage}{PagePrecedente}
+\setinterfacevariable{PrintDocument}{ImprimeDocument}
+\setinterfacevariable{Query}{Query}
+\setinterfacevariable{QueryAgain}{QueryAgain}
+\setinterfacevariable{ResetForm}{RazForm}
+\setinterfacevariable{ResumeMovie}{ReprendFilm}
+\setinterfacevariable{ResumeRendering}{ResumeRendering}
+\setinterfacevariable{ResumeSound}{ReprendSon}
+\setinterfacevariable{Romannumerals}{Chiffresromains}
+\setinterfacevariable{SaveDocument}{SauvegardeDocument}
+\setinterfacevariable{SaveForm}{SauvegardeForm}
+\setinterfacevariable{SaveNamedDocument}{SauvegardeDocumentNomme}
+\setinterfacevariable{SearchAgain}{RechercheSuivant}
+\setinterfacevariable{SearchDocument}{RechercheDocument}
+\setinterfacevariable{ShowBookmarks}{ShowBookmarks}
+\setinterfacevariable{ShowField}{MontreChamp}
+\setinterfacevariable{ShowThumbs}{ShowThumbs}
+\setinterfacevariable{StartMovie}{DemarreFilm}
+\setinterfacevariable{StartRendering}{StartRendering}
+\setinterfacevariable{StartSound}{DemarreSon}
+\setinterfacevariable{StopMovie}{StoppeFilm}
+\setinterfacevariable{StopRendering}{StopRendering}
+\setinterfacevariable{StopSound}{StoppeSon}
+\setinterfacevariable{SubmitForm}{SoumettreForm}
+\setinterfacevariable{ToggleLayer}{ToggleLayer}
+\setinterfacevariable{ToggleViewer}{ChangeVisualisateur}
+\setinterfacevariable{URL}{URL}
+\setinterfacevariable{VideLayer}{VideLayer}
+\setinterfacevariable{ViewerHelp}{AideVisualisateur}
+\setinterfacevariable{WEEKDAY}{JOURSEMAINE}
+\setinterfacevariable{WORD}{MOT}
+\setinterfacevariable{abbreviation}{abreviation}
+\setinterfacevariable{abbreviations}{abreviations}
+\setinterfacevariable{absolute}{absolute}
+\setinterfacevariable{action}{action}
+\setinterfacevariable{after}{apres}
+\setinterfacevariable{all}{tout}
+\setinterfacevariable{always}{toujours}
+\setinterfacevariable{answerarea}{answerarea}
+\setinterfacevariable{appendices}{annexes}
+\setinterfacevariable{appendix}{annexe}
+\setinterfacevariable{april}{avril}
+\setinterfacevariable{atmargin}{alamarge}
+\setinterfacevariable{atpage}{alapage}
+\setinterfacevariable{august}{aout}
+\setinterfacevariable{author}{auteur}
+\setinterfacevariable{auto}{auto}
+\setinterfacevariable{autointro}{autointro}
+\setinterfacevariable{back}{retour}
+\setinterfacevariable{background}{arriereplan}
+\setinterfacevariable{backmatter}{epilogue}
+\setinterfacevariable{backpart}{postface}
+\setinterfacevariable{backspace}{retourarriere}
+\setinterfacevariable{backward}{retourarriere}
+\setinterfacevariable{bbl}{bbl}
+\setinterfacevariable{before}{avant}
+\setinterfacevariable{begin}{begin}
+\setinterfacevariable{bib}{bib}
+\setinterfacevariable{big}{grand}
+\setinterfacevariable{bigbodyfont}{grandepolicecorp}
+\setinterfacevariable{bigpreference}{grandepreference}
+\setinterfacevariable{blank}{vide}
+\setinterfacevariable{blockquote}{blockquote}
+\setinterfacevariable{bodymatter}{texteprincipal}
+\setinterfacevariable{bodypart}{corpsdetexte}
+\setinterfacevariable{bold}{gras}
+\setinterfacevariable{bolditalic}{italiquegras}
+\setinterfacevariable{boldslanted}{inclinegras}
+\setinterfacevariable{bookmark}{marquepage}
+\setinterfacevariable{both}{lesdeux}
+\setinterfacevariable{bottom}{inf}
+\setinterfacevariable{brief}{brief}
+\setinterfacevariable{broad}{large}
+\setinterfacevariable{buffer}{buffer}
+\setinterfacevariable{by}{par}
+\setinterfacevariable{calligraphic}{calligraphique}
+\setinterfacevariable{cap}{cap}
+\setinterfacevariable{capital}{capitale}
+\setinterfacevariable{center}{center}
+\setinterfacevariable{chapter}{chapitre}
+\setinterfacevariable{character}{caractere}
+\setinterfacevariable{characters}{caracteres}
+\setinterfacevariable{cite}{cite}
+\setinterfacevariable{color}{couleur}
+\setinterfacevariable{column}{colonne}
+\setinterfacevariable{columns}{colonnes}
+\setinterfacevariable{command}{commande}
+\setinterfacevariable{commands}{commandes}
+\setinterfacevariable{comment}{commentaire}
+\setinterfacevariable{component}{composant}
+\setinterfacevariable{concept}{concept}
+\setinterfacevariable{content}{contenu}
+\setinterfacevariable{contents}{contenus}
+\setinterfacevariable{continue}{continue}
+\setinterfacevariable{controls}{controles}
+\setinterfacevariable{conversion}{conversion}
+\setinterfacevariable{current}{courant}
+\setinterfacevariable{cutspace}{cutspace}
+\setinterfacevariable{date}{date}
+\setinterfacevariable{day}{jour}
+\setinterfacevariable{december}{decembre}
+\setinterfacevariable{default}{defaut}
+\setinterfacevariable{depth}{profondeur}
+\setinterfacevariable{description}{description}
+\setinterfacevariable{disable}{desactiver}
+\setinterfacevariable{display}{affichage}
+\setinterfacevariable{dot}{point}
+\setinterfacevariable{doublesided}{rectoverso}
+\setinterfacevariable{down}{down}
+\setinterfacevariable{each}{chaque}
+\setinterfacevariable{edge}{bord}
+\setinterfacevariable{empty}{vide}
+\setinterfacevariable{end}{end}
+\setinterfacevariable{endnote}{notefin}
+\setinterfacevariable{enumeration}{enumeration}
+\setinterfacevariable{environment}{environement}
+\setinterfacevariable{even}{paire}
+\setinterfacevariable{external}{external}
+\setinterfacevariable{fact}{fait}
+\setinterfacevariable{february}{fevrier}
+\setinterfacevariable{figure}{figure}
+\setinterfacevariable{figures}{figures}
+\setinterfacevariable{file}{fichier}
+\setinterfacevariable{final}{final}
+\setinterfacevariable{first}{premier}
+\setinterfacevariable{firstcolumn}{premierecolonne}
+\setinterfacevariable{firstpage}{premierepage}
+\setinterfacevariable{firstsubpage}{premieresouspage}
+\setinterfacevariable{fit}{adapte}
+\setinterfacevariable{five}{cinq}
+\setinterfacevariable{fix}{fixe}
+\setinterfacevariable{fixed}{fixe}
+\setinterfacevariable{flexible}{flexible}
+\setinterfacevariable{float}{flottant}
+\setinterfacevariable{flushinner}{flushinner}
+\setinterfacevariable{flushleft}{flushleft}
+\setinterfacevariable{flushouter}{flushouter}
+\setinterfacevariable{flushright}{flushright}
+\setinterfacevariable{footer}{pdp}
+\setinterfacevariable{footnote}{notepdp}
+\setinterfacevariable{force}{force}
+\setinterfacevariable{foreground}{premierplan}
+\setinterfacevariable{formeel}{formeel}
+\setinterfacevariable{formula}{formule}
+\setinterfacevariable{formulae}{formules}
+\setinterfacevariable{forward}{avance}
+\setinterfacevariable{four}{quatre}
+\setinterfacevariable{frame}{cadre}
+\setinterfacevariable{framedtext}{texteencadre}
+\setinterfacevariable{friday}{vendredi}
+\setinterfacevariable{frontmatter}{preambule}
+\setinterfacevariable{frontpart}{preface}
+\setinterfacevariable{global}{global}
+\setinterfacevariable{graphic}{graphique}
+\setinterfacevariable{graphics}{graphiques}
+\setinterfacevariable{gray}{gris}
+\setinterfacevariable{greek}{grec}
+\setinterfacevariable{grid}{grille}
+\setinterfacevariable{halfline}{demiligne}
+\setinterfacevariable{handwritten}{manuscript}
+\setinterfacevariable{hang}{suspend}
+\setinterfacevariable{hanging}{suspend}
+\setinterfacevariable{head}{tete}
+\setinterfacevariable{header}{entete}
+\setinterfacevariable{height}{hauteur}
+\setinterfacevariable{helptext}{texteaide}
+\setinterfacevariable{hencefore}{precedent}
+\setinterfacevariable{here}{ici}
+\setinterfacevariable{hereafter}{suivant}
+\setinterfacevariable{hidden}{cache}
+\setinterfacevariable{hiding}{cache}
+\setinterfacevariable{high}{haut}
+\setinterfacevariable{horizontal}{horizontale}
+\setinterfacevariable{hyphenated}{hyphenated}
+\setinterfacevariable{hz}{hz}
+\setinterfacevariable{inbetween}{entre}
+\setinterfacevariable{index}{index}
+\setinterfacevariable{indices}{indices}
+\setinterfacevariable{informeel}{informeel}
+\setinterfacevariable{inherit}{herite}
+\setinterfacevariable{inleft}{dansgauche}
+\setinterfacevariable{inmargin}{dansmarge}
+\setinterfacevariable{inner}{interieur}
+\setinterfacevariable{inneredge}{bordinterieur}
+\setinterfacevariable{innermargin}{margeinterieure}
+\setinterfacevariable{inright}{dansdroit}
+\setinterfacevariable{interaction}{interaction}
+\setinterfacevariable{interactionmenu}{menuinteraction}
+\setinterfacevariable{intermezzi}{intermezzi}
+\setinterfacevariable{intermezzo}{intermezzo}
+\setinterfacevariable{intext}{danstexte}
+\setinterfacevariable{intro}{intro}
+\setinterfacevariable{italic}{italique}
+\setinterfacevariable{italicbold}{grasitalique}
+\setinterfacevariable{item}{element}
+\setinterfacevariable{itemize}{lister}
+\setinterfacevariable{its}{its}
+\setinterfacevariable{january}{janvier}
+\setinterfacevariable{joinedup}{joinedup}
+\setinterfacevariable{july}{juillet}
+\setinterfacevariable{june}{juin}
+\setinterfacevariable{keep}{maintient}
+\setinterfacevariable{knockout}{knockout}
+\setinterfacevariable{label}{etiquette}
+\setinterfacevariable{landscape}{paysage}
+\setinterfacevariable{last}{dernier}
+\setinterfacevariable{lastcolumn}{dernierecolonne}
+\setinterfacevariable{lastpage}{dernierepage}
+\setinterfacevariable{lastpagenumber}{derniernumeropage}
+\setinterfacevariable{lastsubpage}{dernieresouspage}
+\setinterfacevariable{layer}{layer}
+\setinterfacevariable{left}{gauche}
+\setinterfacevariable{leftedge}{bordgauche}
+\setinterfacevariable{lefthanging}{lefthanging}
+\setinterfacevariable{leftmargin}{margegauche}
+\setinterfacevariable{leftpage}{pagegauche}
+\setinterfacevariable{lefttoright}{lefttoright}
+\setinterfacevariable{legend}{legende}
+\setinterfacevariable{lesshyphenation}{lesshyphenation}
+\setinterfacevariable{line}{ligne}
+\setinterfacevariable{linenote}{noteligne}
+\setinterfacevariable{lines}{lignes}
+\setinterfacevariable{list}{liste}
+\setinterfacevariable{local}{local}
+\setinterfacevariable{localenvironment}{environementlocal}
+\setinterfacevariable{logo}{logo}
+\setinterfacevariable{logos}{logos}
+\setinterfacevariable{lohi}{baha}
+\setinterfacevariable{loose}{perte}
+\setinterfacevariable{low}{bas}
+\setinterfacevariable{ls}{ls}
+\setinterfacevariable{makeup}{makeup}
+\setinterfacevariable{mar}{mar}
+\setinterfacevariable{march}{mars}
+\setinterfacevariable{margin}{marge}
+\setinterfacevariable{marginedge}{bordmarge}
+\setinterfacevariable{margintitle}{titremarge}
+\setinterfacevariable{marking}{marquage}
+\setinterfacevariable{mathalignment}{mathalignment}
+\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathmatrix}{mathmatrix}
+\setinterfacevariable{max}{max}
+\setinterfacevariable{maxdepth}{maxdepth}
+\setinterfacevariable{maxheight}{maxheight}
+\setinterfacevariable{maxwidth}{maxwidth}
+\setinterfacevariable{may}{mai}
+\setinterfacevariable{mediaeval}{medieval}
+\setinterfacevariable{medium}{moyen}
+\setinterfacevariable{middle}{milieu}
+\setinterfacevariable{min}{min}
+\setinterfacevariable{mindepth}{mindepth}
+\setinterfacevariable{minheight}{hauteurmin}
+\setinterfacevariable{minwidth}{largeurmin}
+\setinterfacevariable{mirrored}{reflete}
+\setinterfacevariable{monday}{lundi}
+\setinterfacevariable{mono}{mono}
+\setinterfacevariable{month}{mois}
+\setinterfacevariable{morehyphenation}{morehyphenation}
+\setinterfacevariable{name}{nom}
+\setinterfacevariable{narrow}{etroit}
+\setinterfacevariable{negative}{negatif}
+\setinterfacevariable{never}{jamais}
+\setinterfacevariable{new}{nouveau}
+\setinterfacevariable{next}{prochain}
+\setinterfacevariable{nextevenpage}{pagepairesuivante}
+\setinterfacevariable{nextoddpage}{pageimpairesuivante}
+\setinterfacevariable{nextpage}{pagesuivante}
+\setinterfacevariable{nextsubpage}{souspagesuivante}
+\setinterfacevariable{no}{non}
+\setinterfacevariable{nocheck}{nonverifie}
+\setinterfacevariable{nofit}{nofit}
+\setinterfacevariable{nogrid}{nogrid}
+\setinterfacevariable{nohz}{nohz}
+\setinterfacevariable{nomarking}{sansmarquage}
+\setinterfacevariable{none}{rien}
+\setinterfacevariable{nonumber}{sansnumero}
+\setinterfacevariable{normal}{normal}
+\setinterfacevariable{nospacing}{sansespacement}
+\setinterfacevariable{not}{pas}
+\setinterfacevariable{note}{note}
+\setinterfacevariable{nothanging}{nonsuspendu}
+\setinterfacevariable{nothyphenated}{nothyphenated}
+\setinterfacevariable{november}{novembre}
+\setinterfacevariable{nowhere}{nulpart}
+\setinterfacevariable{nowhite}{sansblanc}
+\setinterfacevariable{number}{numero}
+\setinterfacevariable{numbers}{numeros}
+\setinterfacevariable{october}{octobre}
+\setinterfacevariable{odd}{impair}
+\setinterfacevariable{off}{desactive}
+\setinterfacevariable{offset}{offset}
+\setinterfacevariable{old}{old}
+\setinterfacevariable{on}{actif}
+\setinterfacevariable{one}{un}
+\setinterfacevariable{opposite}{opposition}
+\setinterfacevariable{outer}{exterieur}
+\setinterfacevariable{outeredge}{bordexterieur}
+\setinterfacevariable{outermargin}{margeexterieure}
+\setinterfacevariable{overbar}{overbar}
+\setinterfacevariable{overbars}{overbars}
+\setinterfacevariable{overlay}{revetement}
+\setinterfacevariable{overprint}{overprint}
+\setinterfacevariable{overstrike}{surlignetout}
+\setinterfacevariable{overstrikes}{surligne}
+\setinterfacevariable{packed}{groupe}
+\setinterfacevariable{page}{page}
+\setinterfacevariable{pagecomment}{commentairepage}
+\setinterfacevariable{pagenumber}{numeropage}
+\setinterfacevariable{paper}{papier}
+\setinterfacevariable{paragraph}{paragraphe}
+\setinterfacevariable{part}{partie}
+\setinterfacevariable{positive}{positif}
+\setinterfacevariable{postponing}{postponing}
+\setinterfacevariable{postscript}{postscript}
+\setinterfacevariable{preference}{preference}
+\setinterfacevariable{preview}{previsualisation}
+\setinterfacevariable{previous}{precedent}
+\setinterfacevariable{previousevenpage}{pagepaireprecedente}
+\setinterfacevariable{previousoddpage}{pageimpaireprecedente}
+\setinterfacevariable{previouspage}{pageprecedente}
+\setinterfacevariable{previoussubpage}{souspageprecedente}
+\setinterfacevariable{printable}{editable}
+\setinterfacevariable{process}{process}
+\setinterfacevariable{product}{produit}
+\setinterfacevariable{program}{programme}
+\setinterfacevariable{project}{projet}
+\setinterfacevariable{protected}{protege}
+\setinterfacevariable{quadruple}{quadruple}
+\setinterfacevariable{quotation}{citation}
+\setinterfacevariable{quote}{citer}
+\setinterfacevariable{ran}{cours}
+\setinterfacevariable{random}{aleatoire}
+\setinterfacevariable{readonly}{lectureseule}
+\setinterfacevariable{rectangular}{rectangulaire}
+\setinterfacevariable{referral}{referral}
+\setinterfacevariable{register}{registre}
+\setinterfacevariable{regular}{regulier}
+\setinterfacevariable{rekening}{rekening}
+\setinterfacevariable{relative}{relatif}
+\setinterfacevariable{repeat}{repete}
+\setinterfacevariable{required}{recquis}
+\setinterfacevariable{reset}{raz}
+\setinterfacevariable{reverse}{inverse}
+\setinterfacevariable{right}{droite}
+\setinterfacevariable{rightedge}{borddroit}
+\setinterfacevariable{righthanging}{righthanging}
+\setinterfacevariable{rightmargin}{margedroite}
+\setinterfacevariable{rightpage}{pagedroite}
+\setinterfacevariable{righttoleft}{righttoleft}
+\setinterfacevariable{roman}{roman}
+\setinterfacevariable{romannumerals}{chiffresromains}
+\setinterfacevariable{rotate}{oriente}
+\setinterfacevariable{rotated}{tourne}
+\setinterfacevariable{round}{rond}
+\setinterfacevariable{row}{rang}
+\setinterfacevariable{rule}{regle}
+\setinterfacevariable{samepage}{memepage}
+\setinterfacevariable{sans}{sans}
+\setinterfacevariable{sansbold}{sansgras}
+\setinterfacevariable{sansserif}{sansserif}
+\setinterfacevariable{saturday}{samedi}
+\setinterfacevariable{screen}{ecran}
+\setinterfacevariable{section}{section}
+\setinterfacevariable{sectionblockenvironment}{environementblocsection}
+\setinterfacevariable{sectionnumber}{numerosection}
+\setinterfacevariable{see}{voit}
+\setinterfacevariable{september}{septembre}
+\setinterfacevariable{serif}{serif}
+\setinterfacevariable{serried}{serried}
+\setinterfacevariable{setups}{reglages}
+\setinterfacevariable{sheet}{sheet}
+\setinterfacevariable{short}{short}
+\setinterfacevariable{singlesided}{recto}
+\setinterfacevariable{slanted}{incline}
+\setinterfacevariable{slantedbold}{grasincline}
+\setinterfacevariable{small}{petit}
+\setinterfacevariable{smallbodyfont}{petitepolicecorps}
+\setinterfacevariable{smallbold}{graspetit}
+\setinterfacevariable{smallbolditalic}{italiquegraspetit}
+\setinterfacevariable{smallboldslanted}{inclinegraspetit}
+\setinterfacevariable{smallcaps}{petitescapitales}
+\setinterfacevariable{smallitalic}{italiquepetit}
+\setinterfacevariable{smallitalicbold}{grasitaliquepetit}
+\setinterfacevariable{smallnormal}{normalpetit}
+\setinterfacevariable{smallslanted}{inclinepetit}
+\setinterfacevariable{smallslantedbold}{grasinclinepetit}
+\setinterfacevariable{smalltype}{petittype}
+\setinterfacevariable{somewhere}{qqpart}
+\setinterfacevariable{sorted}{trie}
+\setinterfacevariable{space}{espace}
+\setinterfacevariable{spacing}{espacement}
+\setinterfacevariable{speech}{discours}
+\setinterfacevariable{split}{split}
+\setinterfacevariable{spot}{spot}
+\setinterfacevariable{standard}{standard}
+\setinterfacevariable{start}{demarre}
+\setinterfacevariable{starter}{starter}
+\setinterfacevariable{sticker}{sticker}
+\setinterfacevariable{stop}{stoppe}
+\setinterfacevariable{stopper}{stopper}
+\setinterfacevariable{stretch}{etire}
+\setinterfacevariable{strict}{strict}
+\setinterfacevariable{strong}{strong}
+\setinterfacevariable{strut}{strut}
+\setinterfacevariable{sub}{sous}
+\setinterfacevariable{subbackward}{sousretourarriere}
+\setinterfacevariable{subformula}{subformule}
+\setinterfacevariable{subforward}{sousavance}
+\setinterfacevariable{subject}{sujet}
+\setinterfacevariable{subpage}{souspage}
+\setinterfacevariable{subsection}{soussection}
+\setinterfacevariable{subsubject}{soussujet}
+\setinterfacevariable{subsubsection}{soussoussection}
+\setinterfacevariable{subsubsubject}{soussoussujet}
+\setinterfacevariable{subsubsubsection}{soussoussoussection}
+\setinterfacevariable{subsubsubsubject}{soussoussoussujet}
+\setinterfacevariable{subsubsubsubsection}{soussoussoussoussection}
+\setinterfacevariable{subsubsubsubsubject}{soussoussoussoussujet}
+\setinterfacevariable{subsubsubsubsubsection}{soussoussoussoussoussection}
+\setinterfacevariable{subsubsubsubsubsubject}{soussoussoussoussoussujet}
+\setinterfacevariable{subsubsubsubsubsubsection}{soussoussoussoussoussoussection}
+\setinterfacevariable{subsubsubsubsubsubsubject}{soussoussoussoussoussoussujet}
+\setinterfacevariable{subsubsubsubsubsubsubsection}{soussoussoussoussoussoussoussection}
+\setinterfacevariable{subsubsubsubsubsubsubsubject}{soussoussoussoussoussoussoussujet}
+\setinterfacevariable{subsubsubsubsubsubsubsubsection}{soussoussoussoussoussoussoussoussection}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubject}{soussoussoussoussoussoussoussoussujet}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsection}{soussoussoussoussoussoussoussoussoussection}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsubject}{soussoussoussoussoussoussoussoussoussujet}
+\setinterfacevariable{sunday}{dimanche}
+\setinterfacevariable{support}{support}
+\setinterfacevariable{sym}{sym}
+\setinterfacevariable{symbol}{symbole}
+\setinterfacevariable{synchronize}{synchronize}
+\setinterfacevariable{system}{systeme}
+\setinterfacevariable{table}{tableau}
+\setinterfacevariable{tablehead}{tetetableau}
+\setinterfacevariable{tables}{tables}
+\setinterfacevariable{tabletail}{queuetableau}
+\setinterfacevariable{tabulate}{tabule}
+\setinterfacevariable{tabulatehead}{tetetabule}
+\setinterfacevariable{tabulatetail}{queuetabule}
+\setinterfacevariable{tall}{long}
+\setinterfacevariable{teletype}{teletype}
+\setinterfacevariable{temporary}{temporaire}
+\setinterfacevariable{test}{test}
+\setinterfacevariable{text}{texte}
+\setinterfacevariable{three}{trois}
+\setinterfacevariable{thursday}{jeudi}
+\setinterfacevariable{title}{titre}
+\setinterfacevariable{toggle}{toggle}
+\setinterfacevariable{tolerant}{tolerant}
+\setinterfacevariable{top}{sup}
+\setinterfacevariable{tuesday}{mardi}
+\setinterfacevariable{two}{deux}
+\setinterfacevariable{txt}{txt}
+\setinterfacevariable{type}{type}
+\setinterfacevariable{typing}{typing}
+\setinterfacevariable{unavailable}{indisponible}
+\setinterfacevariable{underbar}{souslignetout}
+\setinterfacevariable{underbars}{sousligne}
+\setinterfacevariable{unit}{unite}
+\setinterfacevariable{units}{unites}
+\setinterfacevariable{unknown}{inconnu}
+\setinterfacevariable{unpacked}{degroupe}
+\setinterfacevariable{up}{up}
+\setinterfacevariable{url}{url}
+\setinterfacevariable{used}{used}
+\setinterfacevariable{value}{valeur}
+\setinterfacevariable{vertical}{verticale}
+\setinterfacevariable{very}{tres}
+\setinterfacevariable{verystrict}{tresstrict}
+\setinterfacevariable{verytolerant}{trestolerant}
+\setinterfacevariable{weak}{weak}
+\setinterfacevariable{wednesday}{mercredi}
+\setinterfacevariable{week}{semaine}
+\setinterfacevariable{weekday}{joursemaine}
+\setinterfacevariable{white}{blanc}
+\setinterfacevariable{wide}{ample}
+\setinterfacevariable{width}{largeur}
+\setinterfacevariable{xml}{xml}
+\setinterfacevariable{year}{annee}
+\setinterfacevariable{yes}{oui}
+% definitions for interface constants for language fr
+%
+\setinterfaceconstant{action}{action}
+\setinterfaceconstant{address}{adresse}
+\setinterfaceconstant{after}{apres}
+\setinterfaceconstant{afterhead}{aprestete}
+\setinterfaceconstant{afterkey}{aprescle}
+\setinterfaceconstant{align}{alignement}
+\setinterfaceconstant{aligncharacter}{caracterealigne}
+\setinterfaceconstant{alignmentcharacter}{alignementcaractere}
+\setinterfaceconstant{alignsymbol}{alignsymbol}
+\setinterfaceconstant{aligntitle}{alignementtitre}
+\setinterfaceconstant{alternative}{alternative}
+\setinterfaceconstant{andtext}{andtext}
+\setinterfaceconstant{apa}{apa}
+\setinterfaceconstant{arrow}{fleche}
+\setinterfaceconstant{artauthor}{artauthor}
+\setinterfaceconstant{artauthoretaldisplay}{artauthoretaldisplay}
+\setinterfaceconstant{artauthoretallimit}{artauthoretallimit}
+\setinterfaceconstant{artauthoretaltext}{artauthoretaltext}
+\setinterfaceconstant{at}{a}
+\setinterfaceconstant{author}{auteur}
+\setinterfaceconstant{authoretaldisplay}{authoretaldisplay}
+\setinterfaceconstant{authoretallimit}{authoretallimit}
+\setinterfaceconstant{authoretaltext}{authoretaltext}
+\setinterfaceconstant{auto}{auto}
+\setinterfaceconstant{autofile}{autofile}
+\setinterfaceconstant{autofocus}{autofocus}
+\setinterfaceconstant{autohang}{autohang}
+\setinterfaceconstant{autostrut}{autostrut}
+\setinterfaceconstant{autowidth}{autolargeur}
+\setinterfaceconstant{axis}{axe}
+\setinterfaceconstant{background}{arriereplan}
+\setinterfaceconstant{backgroundcolor}{couleurarriereplan}
+\setinterfaceconstant{backgroundcorner}{coinarriereplan}
+\setinterfaceconstant{backgrounddepth}{profondeurarriereplan}
+\setinterfaceconstant{backgroundoffset}{decalagearriereplan}
+\setinterfaceconstant{backgroundradius}{rayonarriereplan}
+\setinterfaceconstant{backgroundscreen}{ecranarriereplan}
+\setinterfaceconstant{backspace}{retour}
+\setinterfaceconstant{balance}{equilibre}
+\setinterfaceconstant{before}{avant}
+\setinterfaceconstant{beforehead}{avanttete}
+\setinterfaceconstant{bet}{bet}
+\setinterfaceconstant{big}{grand}
+\setinterfaceconstant{blank}{vide}
+\setinterfaceconstant{blockway}{blockway}
+\setinterfaceconstant{bodyfont}{policecorps}
+\setinterfaceconstant{bookmark}{marquepage}
+\setinterfaceconstant{bottom}{inf}
+\setinterfaceconstant{bottomafter}{bottomafter}
+\setinterfaceconstant{bottombefore}{bottombefore}
+\setinterfaceconstant{bottomdistance}{distanceinf}
+\setinterfaceconstant{bottomframe}{cadreinf}
+\setinterfaceconstant{bottomoffset}{decalageinf}
+\setinterfaceconstant{bottomspace}{espaceinf}
+\setinterfaceconstant{bottomstate}{etatinf}
+\setinterfaceconstant{cache}{cache}
+\setinterfaceconstant{calculate}{calculer}
+\setinterfaceconstant{ccommand}{ccommande}
+\setinterfaceconstant{click}{clic}
+\setinterfaceconstant{clickin}{clicinterieur}
+\setinterfaceconstant{clickout}{clicexterieur}
+\setinterfaceconstant{clipoffset}{clipoffset}
+\setinterfaceconstant{closeaction}{actionfermeture}
+\setinterfaceconstant{closecommand}{closecommand}
+\setinterfaceconstant{closepageaction}{actionfermeturepage}
+\setinterfaceconstant{closesymbol}{closesymbol}
+\setinterfaceconstant{color}{couleur}
+\setinterfaceconstant{column}{colonne}
+\setinterfaceconstant{columndistance}{distancecolonne}
+\setinterfaceconstant{columns}{colonnes}
+\setinterfaceconstant{command}{commande}
+\setinterfaceconstant{commandafter}{commandeapres}
+\setinterfaceconstant{commandbefore}{commandeavant}
+\setinterfaceconstant{commands}{commandes}
+\setinterfaceconstant{component}{composant}
+\setinterfaceconstant{compoundhyphen}{compoundhyphen}
+\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{connector}{connector}
+\setinterfaceconstant{continue}{continue}
+\setinterfaceconstant{contrastcolor}{coleurcontraste}
+\setinterfaceconstant{controls}{controles}
+\setinterfaceconstant{conversion}{conversion}
+\setinterfaceconstant{convertfile}{conversionfichier}
+\setinterfaceconstant{corner}{coin}
+\setinterfaceconstant{coupling}{couplage}
+\setinterfaceconstant{couplingway}{modecouplage}
+\setinterfaceconstant{criterium}{critere}
+\setinterfaceconstant{current}{courant}
+\setinterfaceconstant{cutspace}{cutspace}
+\setinterfaceconstant{dash}{pointille}
+\setinterfaceconstant{dat}{dat}
+\setinterfaceconstant{database}{database}
+\setinterfaceconstant{date}{date}
+\setinterfaceconstant{deepnumbercommand}{deepnumbercommand}
+\setinterfaceconstant{deeptextcommand}{deeptextcommand}
+\setinterfaceconstant{default}{defaut}
+\setinterfaceconstant{delay}{delai}
+\setinterfaceconstant{depth}{profondeur}
+\setinterfaceconstant{depthcorrection}{correctionprofondeur}
+\setinterfaceconstant{direction}{direction}
+\setinterfaceconstant{directory}{repertoire}
+\setinterfaceconstant{display}{affichage}
+\setinterfaceconstant{distance}{distance}
+\setinterfaceconstant{dot}{point}
+\setinterfaceconstant{doublesided}{rectoverso}
+\setinterfaceconstant{dummy}{dummy}
+\setinterfaceconstant{dx}{dx}
+\setinterfaceconstant{dy}{dy}
+\setinterfaceconstant{edge}{bord}
+\setinterfaceconstant{edgedistance}{distancebord}
+\setinterfaceconstant{editor}{editor}
+\setinterfaceconstant{editoretaldisplay}{editoretaldisplay}
+\setinterfaceconstant{editoretallimit}{editoretallimit}
+\setinterfaceconstant{editoretaltext}{editoretaltext}
+\setinterfaceconstant{empty}{vide}
+\setinterfaceconstant{equalheight}{equalheight}
+\setinterfaceconstant{equalwidth}{equalwidth}
+\setinterfaceconstant{escape}{escape}
+\setinterfaceconstant{evenmargin}{margepaire}
+\setinterfaceconstant{expansion}{expansion}
+\setinterfaceconstant{export}{export}
+\setinterfaceconstant{extras}{extras}
+\setinterfaceconstant{factor}{facteur}
+\setinterfaceconstant{fallback}{fallback}
+\setinterfaceconstant{family}{famille}
+\setinterfaceconstant{fieldbackgroundcolor}{couleurarrierreplanchamp}
+\setinterfaceconstant{fieldframecolor}{couleurcadrechamp}
+\setinterfaceconstant{fieldlayer}{calquechamp}
+\setinterfaceconstant{fieldoffset}{offsetchamp}
+\setinterfaceconstant{file}{fichier}
+\setinterfaceconstant{filtercommand}{filtercommand}
+\setinterfaceconstant{finalnamesep}{finalnamesep}
+\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{focus}{focus}
+\setinterfaceconstant{focusin}{focusin}
+\setinterfaceconstant{focusout}{focusout}
+\setinterfaceconstant{footer}{pdp}
+\setinterfaceconstant{footerdistance}{dsitancepdp}
+\setinterfaceconstant{footerstate}{etatpdp}
+\setinterfaceconstant{foregroundcolor}{couleurpremierplan}
+\setinterfaceconstant{foregroundstyle}{stylepremierplan}
+\setinterfaceconstant{format}{formatter}
+\setinterfaceconstant{frame}{cadre}
+\setinterfaceconstant{framecolor}{couleurcadre}
+\setinterfaceconstant{framecorner}{coincadre}
+\setinterfaceconstant{framedepth}{profondeurcadre}
+\setinterfaceconstant{frameoffset}{decalagecadre}
+\setinterfaceconstant{frameradius}{rayoncadre}
+\setinterfaceconstant{frames}{cadres}
+\setinterfaceconstant{from}{de}
+\setinterfaceconstant{get}{obtient}
+\setinterfaceconstant{global}{global}
+\setinterfaceconstant{grid}{grille}
+\setinterfaceconstant{hang}{suspend}
+\setinterfaceconstant{headalign}{headalign}
+\setinterfaceconstant{headcolor}{couleurtete}
+\setinterfaceconstant{headcommand}{commandetete}
+\setinterfaceconstant{headconversion}{conversiontete}
+\setinterfaceconstant{header}{entete}
+\setinterfaceconstant{headerdistance}{distanceentete}
+\setinterfaceconstant{headerstate}{etatentete}
+\setinterfaceconstant{headlabel}{etiquettetete}
+\setinterfaceconstant{headnumber}{numerotete}
+\setinterfaceconstant{headstyle}{styletete}
+\setinterfaceconstant{height}{hauteur}
+\setinterfaceconstant{hfactor}{facteurhauteur}
+\setinterfaceconstant{hfil}{hfil}
+\setinterfaceconstant{hidenumber}{hidenumber}
+\setinterfaceconstant{hoffset}{decalagehauteur}
+\setinterfaceconstant{horoffset}{horoffset}
+\setinterfaceconstant{hyphen}{hyphen}
+\setinterfaceconstant{icommand}{icommande}
+\setinterfaceconstant{in}{in}
+\setinterfaceconstant{inbetween}{entre}
+\setinterfaceconstant{increment}{incremente}
+\setinterfaceconstant{incrementnumber}{incrementenumero}
+\setinterfaceconstant{indenting}{composeenalinea}
+\setinterfaceconstant{indentnext}{indentesuivant}
+\setinterfaceconstant{indicator}{indicateur}
+\setinterfaceconstant{inner}{interieur}
+\setinterfaceconstant{innermargin}{margeinterieure}
+\setinterfaceconstant{inputfile}{fichierentree}
+\setinterfaceconstant{intent}{intent}
+\setinterfaceconstant{interaction}{interaction}
+\setinterfaceconstant{interlinespace}{espaceinterligne}
+\setinterfaceconstant{itemalign}{itemalign}
+\setinterfaceconstant{items}{elements}
+\setinterfaceconstant{juniorsep}{juniorsep}
+\setinterfaceconstant{ken}{ken}
+\setinterfaceconstant{keyexpansion}{keyexpansion}
+\setinterfaceconstant{keyword}{motcle}
+\setinterfaceconstant{label}{etiquette}
+\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{left}{gauche}
+\setinterfaceconstant{leftcolor}{couleurgauche}
+\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
+\setinterfaceconstant{leftedge}{bordgauche}
+\setinterfaceconstant{leftedgedistance}{distancebordgauche}
+\setinterfaceconstant{leftframe}{cadregauche}
+\setinterfaceconstant{lefthyphen}{lefthyphen}
+\setinterfaceconstant{leftmargin}{margegauche}
+\setinterfaceconstant{leftmargindistance}{distancemargegauche}
+\setinterfaceconstant{leftoffset}{decalagegauche}
+\setinterfaceconstant{leftquotation}{citationgauche}
+\setinterfaceconstant{leftquote}{citergauche}
+\setinterfaceconstant{leftsentence}{phrasegauche}
+\setinterfaceconstant{leftspeech}{leftspeech}
+\setinterfaceconstant{leftstyle}{leftstyle}
+\setinterfaceconstant{leftsubsentence}{sousphrasegauche}
+\setinterfaceconstant{lefttext}{textegauche}
+\setinterfaceconstant{leftwidth}{largeurgauche}
+\setinterfaceconstant{level}{niveau}
+\setinterfaceconstant{levels}{niveaux}
+\setinterfaceconstant{limittext}{limittext}
+\setinterfaceconstant{line}{ligne}
+\setinterfaceconstant{linecorrection}{correctionligne}
+\setinterfaceconstant{lines}{lignes}
+\setinterfaceconstant{list}{liste}
+\setinterfaceconstant{listtext}{texteliste}
+\setinterfaceconstant{local}{local}
+\setinterfaceconstant{location}{emplacement}
+\setinterfaceconstant{logo}{logo}
+\setinterfaceconstant{logos}{logos}
+\setinterfaceconstant{marcolor}{couleurmarquage}
+\setinterfaceconstant{margin}{marge}
+\setinterfaceconstant{margindistance}{distancemarge}
+\setinterfaceconstant{marginedge}{bordmarge}
+\setinterfaceconstant{marginedgetext}{textebordmarge}
+\setinterfaceconstant{margintext}{textemarge}
+\setinterfaceconstant{marking}{marquage}
+\setinterfaceconstant{marstyle}{stylemarquage}
+\setinterfaceconstant{max}{max}
+\setinterfaceconstant{maxdepth}{maxdepth}
+\setinterfaceconstant{maxheight}{hauteurmax}
+\setinterfaceconstant{maxwidth}{largeurmax}
+\setinterfaceconstant{maybeyear}{maybeyear}
+\setinterfaceconstant{menu}{menu}
+\setinterfaceconstant{method}{methode}
+\setinterfaceconstant{middle}{milieu}
+\setinterfaceconstant{middlespeech}{middlespeech}
+\setinterfaceconstant{middletext}{textecentre}
+\setinterfaceconstant{midsentence}{midsentence}
+\setinterfaceconstant{min}{min}
+\setinterfaceconstant{mindepth}{profondeurmin}
+\setinterfaceconstant{minheight}{hauteurmin}
+\setinterfaceconstant{minwidth}{largeurmin}
+\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{n}{n}
+\setinterfaceconstant{name}{nom}
+\setinterfaceconstant{namesep}{namesep}
+\setinterfaceconstant{nbottom}{ninf}
+\setinterfaceconstant{nc}{nc}
+\setinterfaceconstant{next}{suivant}
+\setinterfaceconstant{nl}{nl}
+\setinterfaceconstant{nleft}{ngauche}
+\setinterfaceconstant{nlines}{nlignes}
+\setinterfaceconstant{norm}{norme}
+\setinterfaceconstant{nr}{nr}
+\setinterfaceconstant{nright}{ndroite}
+\setinterfaceconstant{ntop}{nsup}
+\setinterfaceconstant{number}{numero}
+\setinterfaceconstant{numbercolor}{couleurnumero}
+\setinterfaceconstant{numbercommand}{commandenumero}
+\setinterfaceconstant{numberconversion}{numberconversion}
+\setinterfaceconstant{numberconversionset}{numberconversionset}
+\setinterfaceconstant{numberdistance}{numberdistance}
+\setinterfaceconstant{numbering}{numerotation}
+\setinterfaceconstant{numberorder}{numberorder}
+\setinterfaceconstant{numberprefix}{numberprefix}
+\setinterfaceconstant{numbersegments}{numbersegments}
+\setinterfaceconstant{numberseparator}{separateurnumbero}
+\setinterfaceconstant{numberseparatorset}{numberseparatorset}
+\setinterfaceconstant{numberset}{numberset}
+\setinterfaceconstant{numberstarter}{numberstarter}
+\setinterfaceconstant{numberstopper}{numberstopper}
+\setinterfaceconstant{numberstyle}{stylenumero}
+\setinterfaceconstant{numberwidth}{numberwidth}
+\setinterfaceconstant{nx}{nx}
+\setinterfaceconstant{ny}{ny}
+\setinterfaceconstant{object}{objet}
+\setinterfaceconstant{obstruction}{obstruction}
+\setinterfaceconstant{oddmargin}{margepaire}
+\setinterfaceconstant{offset}{offset}
+\setinterfaceconstant{openaction}{actionouverture}
+\setinterfaceconstant{openpageaction}{actionouverturepage}
+\setinterfaceconstant{option}{option}
+\setinterfaceconstant{order}{order}
+\setinterfaceconstant{orientation}{orientation}
+\setinterfaceconstant{otherstext}{otherstext}
+\setinterfaceconstant{outermargin}{margeexterieure}
+\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownnumber}{numeroproprio}
+\setinterfaceconstant{page}{page}
+\setinterfaceconstant{pageboundaries}{limitespage}
+\setinterfaceconstant{pagecolor}{couleurpage}
+\setinterfaceconstant{pagecommand}{commandepage}
+\setinterfaceconstant{pageconversion}{pageconversion}
+\setinterfaceconstant{pageconversionset}{pageconversionset}
+\setinterfaceconstant{pagenumber}{numeropage}
+\setinterfaceconstant{pageprefix}{pageprefix}
+\setinterfaceconstant{pageprefixconnector}{pageprefixconnector}
+\setinterfaceconstant{pageprefixconversion}{pageprefixconversion}
+\setinterfaceconstant{pageprefixconversionset}{pageprefixconversionset}
+\setinterfaceconstant{pageprefixsegments}{pageprefixsegments}
+\setinterfaceconstant{pageprefixseparatorset}{pageprefixseparatorset}
+\setinterfaceconstant{pageprefixset}{pageprefixset}
+\setinterfaceconstant{pageprefixstarter}{pageprefixstarter}
+\setinterfaceconstant{pageprefixstopper}{pageprefixstopper}
+\setinterfaceconstant{pagesegments}{pagesegments}
+\setinterfaceconstant{pageseparatorset}{pageseparatorset}
+\setinterfaceconstant{pageset}{pageset}
+\setinterfaceconstant{pagestarter}{pagestarter}
+\setinterfaceconstant{pagestate}{etatpage}
+\setinterfaceconstant{pagestopper}{pagestopper}
+\setinterfaceconstant{pagestyle}{stylepage}
+\setinterfaceconstant{palet}{palette}
+\setinterfaceconstant{paper}{papier}
+\setinterfaceconstant{paragraph}{paragraphe}
+\setinterfaceconstant{place}{place}
+\setinterfaceconstant{placehead}{placetete}
+\setinterfaceconstant{placestopper}{emplacementstopper}
+\setinterfaceconstant{position}{position}
+\setinterfaceconstant{prefix}{prefixe}
+\setinterfaceconstant{prefixconnector}{prefixconnector}
+\setinterfaceconstant{prefixconversion}{prefixconversion}
+\setinterfaceconstant{prefixconversionset}{prefixconversionset}
+\setinterfaceconstant{prefixsegments}{prefixsegments}
+\setinterfaceconstant{prefixseparatorset}{prefixseparatorset}
+\setinterfaceconstant{prefixset}{prefixset}
+\setinterfaceconstant{prefixstarter}{prefixstarter}
+\setinterfaceconstant{prefixstopper}{prefixstopper}
+\setinterfaceconstant{preset}{prereglage}
+\setinterfaceconstant{preview}{previsualisation}
+\setinterfaceconstant{previous}{precedent}
+\setinterfaceconstant{previousnumber}{numeroprecedent}
+\setinterfaceconstant{process}{process}
+\setinterfaceconstant{pubsep}{pubsep}
+\setinterfaceconstant{radius}{rayon}
+\setinterfaceconstant{random}{aleatoire}
+\setinterfaceconstant{range}{range}
+\setinterfaceconstant{reduction}{reduction}
+\setinterfaceconstant{ref}{ref}
+\setinterfaceconstant{refcommand}{refcommand}
+\setinterfaceconstant{reference}{reference}
+\setinterfaceconstant{referenceprefix}{referenceprefix}
+\setinterfaceconstant{referencing}{referencing}
+\setinterfaceconstant{regionin}{entreregion}
+\setinterfaceconstant{regionout}{regionexterieure}
+\setinterfaceconstant{repeat}{repete}
+\setinterfaceconstant{reset}{reset}
+\setinterfaceconstant{resetnumber}{raznumero}
+\setinterfaceconstant{resolution}{resolution}
+\setinterfaceconstant{right}{droite}
+\setinterfaceconstant{rightcolor}{couleurdroite}
+\setinterfaceconstant{rightcompoundhyphen}{rightcompoundhyphen}
+\setinterfaceconstant{rightedge}{borddroit}
+\setinterfaceconstant{rightedgedistance}{distanceborddroit}
+\setinterfaceconstant{rightframe}{cadredroit}
+\setinterfaceconstant{righthyphen}{righthyphen}
+\setinterfaceconstant{rightmargin}{margedroite}
+\setinterfaceconstant{rightmargindistance}{distancemargedroite}
+\setinterfaceconstant{rightoffset}{rightoffset}
+\setinterfaceconstant{rightquotation}{citationdroite}
+\setinterfaceconstant{rightquote}{citerdroite}
+\setinterfaceconstant{rightsentence}{phrasedroite}
+\setinterfaceconstant{rightspeech}{rightspeech}
+\setinterfaceconstant{rightstyle}{styledroit}
+\setinterfaceconstant{rightsubsentence}{sousphrasedroite}
+\setinterfaceconstant{righttext}{textedroit}
+\setinterfaceconstant{rightwidth}{largeurdroite}
+\setinterfaceconstant{rotation}{rotation}
+\setinterfaceconstant{rule}{ligne}
+\setinterfaceconstant{rulecolor}{couleurligne}
+\setinterfaceconstant{rulethickness}{epaisseurligne}
+\setinterfaceconstant{samepage}{memepage}
+\setinterfaceconstant{sample}{echantillon}
+\setinterfaceconstant{samplesize}{samplesize}
+\setinterfaceconstant{saveinlist}{saveinlist}
+\setinterfaceconstant{scale}{echelle}
+\setinterfaceconstant{scope}{scope}
+\setinterfaceconstant{screen}{ecran}
+\setinterfaceconstant{section}{section}
+\setinterfaceconstant{sectionconversion}{sectionconversion}
+\setinterfaceconstant{sectionconversionset}{sectionconversionset}
+\setinterfaceconstant{sectionnumber}{numerosection}
+\setinterfaceconstant{sectionresetset}{sectionresetset}
+\setinterfaceconstant{sectionsegments}{sectionsegments}
+\setinterfaceconstant{sectionseparatorset}{sectionseparatorset}
+\setinterfaceconstant{sectionset}{sectionset}
+\setinterfaceconstant{sectionstarter}{sectionstarter}
+\setinterfaceconstant{sectionstopper}{sectionstopper}
+\setinterfaceconstant{separator}{separateur}
+\setinterfaceconstant{set}{set}
+\setinterfaceconstant{setups}{reglages}
+\setinterfaceconstant{side}{cote}
+\setinterfaceconstant{sidealign}{sidealign}
+\setinterfaceconstant{sidemethod}{sidemethod}
+\setinterfaceconstant{sidespaceafter}{espacelateralapres}
+\setinterfaceconstant{sidespacebefore}{espacelateralavant}
+\setinterfaceconstant{sign}{signe}
+\setinterfaceconstant{size}{dimension}
+\setinterfaceconstant{small}{petit}
+\setinterfaceconstant{sort}{sort}
+\setinterfaceconstant{sorttype}{sorttype}
+\setinterfaceconstant{source}{origine}
+\setinterfaceconstant{space}{espace}
+\setinterfaceconstant{spaceafter}{espaceapres}
+\setinterfaceconstant{spacebefore}{espaceavant}
+\setinterfaceconstant{spaceinbetween}{spaceinbetween}
+\setinterfaceconstant{spacing}{espacement}
+\setinterfaceconstant{split}{split}
+\setinterfaceconstant{splitcolor}{splitcolor}
+\setinterfaceconstant{splitmethod}{splitmethod}
+\setinterfaceconstant{splitoffset}{splitoffset}
+\setinterfaceconstant{spot}{spot}
+\setinterfaceconstant{stack}{stack}
+\setinterfaceconstant{start}{demarre}
+\setinterfaceconstant{starter}{starter}
+\setinterfaceconstant{state}{etat}
+\setinterfaceconstant{step}{pas}
+\setinterfaceconstant{stop}{stoppe}
+\setinterfaceconstant{stopper}{taquet}
+\setinterfaceconstant{stretch}{etire}
+\setinterfaceconstant{strip}{strip}
+\setinterfaceconstant{strut}{strut}
+\setinterfaceconstant{style}{style}
+\setinterfaceconstant{sub}{sous}
+\setinterfaceconstant{subtitle}{soustitre}
+\setinterfaceconstant{suffix}{suffix}
+\setinterfaceconstant{surnamesep}{surnamesep}
+\setinterfaceconstant{sx}{sx}
+\setinterfaceconstant{sy}{sy}
+\setinterfaceconstant{symalign}{symalignement}
+\setinterfaceconstant{symbol}{symbole}
+\setinterfaceconstant{symbolset}{jeusymbole}
+\setinterfaceconstant{symcolor}{couleursym}
+\setinterfaceconstant{symstyle}{stylesym}
+\setinterfaceconstant{synonym}{synonyme}
+\setinterfaceconstant{synonymcolor}{couleursynonyme}
+\setinterfaceconstant{synonymcommand}{synonymcommand}
+\setinterfaceconstant{synonymstyle}{stylesynonyme}
+\setinterfaceconstant{tab}{tab}
+\setinterfaceconstant{text}{texte}
+\setinterfaceconstant{textcolor}{couleurtexte}
+\setinterfaceconstant{textcommand}{commandetexte}
+\setinterfaceconstant{textdistance}{distancetexte}
+\setinterfaceconstant{textlayer}{calquetexte}
+\setinterfaceconstant{textmargin}{margetexte}
+\setinterfaceconstant{textmethod}{textmethod}
+\setinterfaceconstant{textseparator}{separateurtexte}
+\setinterfaceconstant{textsize}{tailletexte}
+\setinterfaceconstant{textstate}{etattexte}
+\setinterfaceconstant{textstyle}{styletexte}
+\setinterfaceconstant{textwidth}{largeurtexte}
+\setinterfaceconstant{title}{titre}
+\setinterfaceconstant{titlecolor}{couleurtitre}
+\setinterfaceconstant{titlecommand}{titlecommand}
+\setinterfaceconstant{titledistance}{distancetitre}
+\setinterfaceconstant{titleleft}{titleleft}
+\setinterfaceconstant{titleright}{titleright}
+\setinterfaceconstant{titlestyle}{styletitre}
+\setinterfaceconstant{to}{vers}
+\setinterfaceconstant{tolerance}{tolerance}
+\setinterfaceconstant{top}{sup}
+\setinterfaceconstant{topdistance}{distancesup}
+\setinterfaceconstant{topframe}{cadresup}
+\setinterfaceconstant{topoffset}{decalagesup}
+\setinterfaceconstant{topspace}{espacesup}
+\setinterfaceconstant{topstate}{etatsup}
+\setinterfaceconstant{totalnumber}{totalnumber}
+\setinterfaceconstant{type}{type}
+\setinterfaceconstant{unit}{unite}
+\setinterfaceconstant{unknownreference}{referenceinconnue}
+\setinterfaceconstant{urlalternative}{alternativeurl}
+\setinterfaceconstant{urlspace}{espaceurl}
+\setinterfaceconstant{validate}{valider}
+\setinterfaceconstant{vcommand}{vcommande}
+\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfil}{vfil}
+\setinterfaceconstant{voffset}{voffset}
+\setinterfaceconstant{vonsep}{vonsep}
+\setinterfaceconstant{way}{mode}
+\setinterfaceconstant{wfactor}{facteurlargeur}
+\setinterfaceconstant{white}{blanc}
+\setinterfaceconstant{width}{largeur}
+\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xmax}{xmax}
+\setinterfaceconstant{xoffset}{xoffset}
+\setinterfaceconstant{xscale}{xscale}
+\setinterfaceconstant{xstep}{xstep}
+\setinterfaceconstant{yfactor}{yfactor}
+\setinterfaceconstant{ymax}{ymax}
+\setinterfaceconstant{yoffset}{yoffset}
+\setinterfaceconstant{yscale}{yscale}
+\setinterfaceconstant{ystep}{ystep}
+% definitions for interface elements for language fr
+%
+\setinterfaceelement{answerlines}{answerlines}
+\setinterfaceelement{answerspace}{answerspace}
+\setinterfaceelement{begin}{debut}
+\setinterfaceelement{complete}{complete}
+\setinterfaceelement{coupled}{couple}
+\setinterfaceelement{currentlocal}{localcourant}
+\setinterfaceelement{emptyone}{vide}
+\setinterfaceelement{emptytwo}{vide}
+\setinterfaceelement{end}{fin}
+\setinterfaceelement{endsetup}{}
+\setinterfaceelement{get}{obtient}
+\setinterfaceelement{increment}{incremente}
+\setinterfaceelement{list}{liste}
+\setinterfaceelement{listof}{listede}
+\setinterfaceelement{load}{charge}
+\setinterfaceelement{local}{local}
+\setinterfaceelement{makeup}{makeup}
+\setinterfaceelement{next}{suivant}
+\setinterfaceelement{place}{place}
+\setinterfaceelement{previous}{precedent}
+\setinterfaceelement{previouslocal}{localprecedent}
+\setinterfaceelement{reserve}{reserver}
+\setinterfaceelement{see}{voit}
+\setinterfaceelement{setup}{regle}
+\setinterfaceelement{start}{demarre}
+\setinterfaceelement{stop}{stoppe}
+\setinterfaceelement{text}{texte}
+\setinterfaceelement{type}{type}
+% definitions for interface commands for language fr
+%
+\setinterfacecommand{CAPPED}{CAP}
+\setinterfacecommand{Character}{Caractere}
+\setinterfacecommand{Characters}{Caracteres}
+\setinterfacecommand{LABELTEXT}{LABELTEXTE}
+\setinterfacecommand{MONTH}{MOIS}
+\setinterfacecommand{Numbers}{Numeros}
+\setinterfacecommand{Romannumerals}{Chiffresromains}
+\setinterfacecommand{SmallCapped}{Cap}
+\setinterfacecommand{SmallCaps}{Caps}
+\setinterfacecommand{WEEKDAY}{JOURSEMAINE}
+\setinterfacecommand{WORD}{MOT}
+\setinterfacecommand{WORDS}{MOTS}
+\setinterfacecommand{Word}{Mot}
+\setinterfacecommand{Words}{Mots}
+\setinterfacecommand{about}{concernant}
+\setinterfacecommand{adaptlayout}{adaptedisposition}
+\setinterfacecommand{arg}{arg}
+\setinterfacecommand{at}{a}
+\setinterfacecommand{atleftmargin}{atleftmargin}
+\setinterfacecommand{atpage}{alapage}
+\setinterfacecommand{atrightmargin}{atrightmargin}
+\setinterfacecommand{background}{arriereplan}
+\setinterfacecommand{backspace}{retourarriere}
+\setinterfacecommand{blackrule}{lignenoire}
+\setinterfacecommand{blackrules}{lignesnoires}
+\setinterfacecommand{blank}{vide}
+\setinterfacecommand{bookmark}{marquepage}
+\setinterfacecommand{bottomdistance}{distanceinf}
+\setinterfacecommand{bottomheight}{hauteurinf}
+\setinterfacecommand{bottomspace}{espaceinf}
+\setinterfacecommand{but}{but}
+\setinterfacecommand{button}{bouton}
+\setinterfacecommand{bypassblocks}{sauteblocs}
+\setinterfacecommand{character}{caractere}
+\setinterfacecommand{characters}{caracteres}
+\setinterfacecommand{chem}{chem}
+\setinterfacecommand{clip}{clip}
+\setinterfacecommand{clonefield}{clonechamp}
+\setinterfacecommand{color}{couleur}
+\setinterfacecommand{colorbar}{barrecouleur}
+\setinterfacecommand{colorvalue}{valeurcouleur}
+\setinterfacecommand{column}{colonne}
+\setinterfacecommand{comment}{commentaire}
+\setinterfacecommand{comparecolorgroup}{comparegroupecouleur}
+\setinterfacecommand{comparepalet}{comparepalette}
+\setinterfacecommand{completepagenumber}{completenumeropage}
+\setinterfacecommand{completeregister}{completeregistre}
+\setinterfacecommand{component}{composant}
+\setinterfacecommand{convertnumber}{convertitnumero}
+\setinterfacecommand{copyfield}{copitchamp}
+\setinterfacecommand{correctwhitespace}{corrigeespaceblanc}
+\setinterfacecommand{coupledocument}{coupledocument}
+\setinterfacecommand{couplemarking}{couplemarquage}
+\setinterfacecommand{couplepage}{pagedouble}
+\setinterfacecommand{couplepaper}{couplepapier}
+\setinterfacecommand{coupleregister}{coupleregistre}
+\setinterfacecommand{crlf}{crlf}
+\setinterfacecommand{currentdate}{datecourante}
+\setinterfacecommand{currentheadnumber}{numerotetecourant}
+\setinterfacecommand{cutspace}{cutspace}
+\setinterfacecommand{date}{date}
+\setinterfacecommand{decouplemarking}{decouplemarquage}
+\setinterfacecommand{decrementnumber}{decrementenumero}
+\setinterfacecommand{define}{definit}
+\setinterfacecommand{defineaccent}{definitaccent}
+\setinterfacecommand{defineblank}{definitvide}
+\setinterfacecommand{defineblock}{definitbloc}
+\setinterfacecommand{definebodyfont}{definitpolicecorps}
+\setinterfacecommand{definebodyfontenvironment}{definitenvironnementpolicecorps}
+\setinterfacecommand{definebuffer}{definitbuffer}
+\setinterfacecommand{definecharacter}{definicaractere}
+\setinterfacecommand{definecolor}{definitcouleur}
+\setinterfacecommand{definecolorgroup}{definitgroupecouleur}
+\setinterfacecommand{definecolumnbreak}{definitsautdecolonne}
+\setinterfacecommand{definecolumnset}{definitjeucolonne}
+\setinterfacecommand{definecombination}{definecombination}
+\setinterfacecommand{definecombinedlist}{definitlisteimbriquee}
+\setinterfacecommand{definecommand}{definitcommande}
+\setinterfacecommand{defineconversion}{definitconversion}
+\setinterfacecommand{definedescription}{definitdescription}
+\setinterfacecommand{defineenumeration}{definitenumeration}
+\setinterfacecommand{definefield}{definitchamp}
+\setinterfacecommand{definefieldstack}{definitpilechamp}
+\setinterfacecommand{definefiguresymbol}{definitsymbolefigure}
+\setinterfacecommand{definefloat}{definitflottant}
+\setinterfacecommand{definefont}{definitpolice}
+\setinterfacecommand{definefontstyle}{definitstylepolice}
+\setinterfacecommand{definefontsynonym}{definitsynonymepolice}
+\setinterfacecommand{defineframed}{defineframed}
+\setinterfacecommand{defineframedtext}{defineframedtext}
+\setinterfacecommand{definehbox}{definithbox}
+\setinterfacecommand{definehead}{definittete}
+\setinterfacecommand{defineindenting}{definitcompoalinea}
+\setinterfacecommand{defineinmargin}{definitdansmarge}
+\setinterfacecommand{defineinteractionmenu}{definitmenuinteraction}
+\setinterfacecommand{defineitemgroup}{defineitemgroup}
+\setinterfacecommand{definelabel}{definitetiquette}
+\setinterfacecommand{definelayer}{definitcalque}
+\setinterfacecommand{definelayout}{definitdisposition}
+\setinterfacecommand{definelist}{definitliste}
+\setinterfacecommand{definelogo}{definitlogo}
+\setinterfacecommand{definemainfield}{definitchampprincipal}
+\setinterfacecommand{definemakeup}{definitmakeup}
+\setinterfacecommand{definemarking}{definitmarquage}
+\setinterfacecommand{definemathalignment}{definemathalignment}
+\setinterfacecommand{defineoutput}{definitsortie}
+\setinterfacecommand{defineoverlay}{definitrevetement}
+\setinterfacecommand{definepagebreak}{definitsautdepage}
+\setinterfacecommand{definepalet}{definitpalette}
+\setinterfacecommand{definepapersize}{definittaillepapier}
+\setinterfacecommand{defineparagraphs}{definitparagraphes}
+\setinterfacecommand{defineplacement}{defineplacement}
+\setinterfacecommand{defineprofile}{definitprofil}
+\setinterfacecommand{defineprogram}{definitprogramme}
+\setinterfacecommand{definerawfont}{definitpolicebrute}
+\setinterfacecommand{definereference}{definitreference}
+\setinterfacecommand{definereferenceformat}{definitformatreference}
+\setinterfacecommand{definereferencelist}{definitlistereference}
+\setinterfacecommand{defineregister}{definitregistre}
+\setinterfacecommand{definerule}{definitregle}
+\setinterfacecommand{definesection}{definitsection}
+\setinterfacecommand{definesectionblock}{definitblocsection}
+\setinterfacecommand{definesorting}{definittri}
+\setinterfacecommand{definestartstop}{definitdemarrestoppe}
+\setinterfacecommand{definestyle}{definitstyle}
+\setinterfacecommand{definesubfield}{definitsouschamp}
+\setinterfacecommand{definesymbol}{definitsymbole}
+\setinterfacecommand{definesynonyms}{definitsynonymes}
+\setinterfacecommand{definetabletemplate}{definittrametableau}
+\setinterfacecommand{definetabulate}{definittabulation}
+\setinterfacecommand{definetext}{definittexte}
+\setinterfacecommand{definetextposition}{definitpositiontexte}
+\setinterfacecommand{definetextvariable}{definitvariabletexte}
+\setinterfacecommand{definetype}{definittype}
+\setinterfacecommand{definetyping}{definitdactylo}
+\setinterfacecommand{defineversion}{definitversion}
+\setinterfacecommand{determineheadnumber}{determinenumerotete}
+\setinterfacecommand{determinelistcharacteristics}{determinecaracteristiqueliste}
+\setinterfacecommand{determineregistercharacteristics}{determinecaracteristiquesregistre}
+\setinterfacecommand{dimension}{dimension}
+\setinterfacecommand{disableinteractionmenu}{inhibemenuinteraction}
+\setinterfacecommand{domicile}{domicile}
+\setinterfacecommand{donttest}{sanstest}
+\setinterfacecommand{edgedistance}{distancebord}
+\setinterfacecommand{edgewidth}{largeurbord}
+\setinterfacecommand{emptylines}{emptylines}
+\setinterfacecommand{environment}{environement}
+\setinterfacecommand{externalfigure}{figureexterne}
+\setinterfacecommand{fact}{fait}
+\setinterfacecommand{field}{champ}
+\setinterfacecommand{fieldstack}{pilechamp}
+\setinterfacecommand{fillinfield}{remplitchamp}
+\setinterfacecommand{fillinline}{remplitligne}
+\setinterfacecommand{fillinrules}{remplitlignesreglees}
+\setinterfacecommand{fillintext}{remplittexte}
+\setinterfacecommand{fitfield}{ajustechamp}
+\setinterfacecommand{fixedspace}{espacefixe}
+\setinterfacecommand{fixedspaces}{espacesfixes}
+\setinterfacecommand{followprofile}{suivantprofil}
+\setinterfacecommand{followprofileversion}{suivantversionprofil}
+\setinterfacecommand{followversion}{suivantversion}
+\setinterfacecommand{footerdistance}{distancepdp}
+\setinterfacecommand{footerheight}{hauteurpdp}
+\setinterfacecommand{footnote}{notepdp}
+\setinterfacecommand{footnotetext}{textenotepdp}
+\setinterfacecommand{forceblocks}{forceblocs}
+\setinterfacecommand{formulanumber}{numeroformule}
+\setinterfacecommand{fraction}{fraction}
+\setinterfacecommand{framed}{framed}
+\setinterfacecommand{from}{de}
+\setinterfacecommand{getbuffer}{prendbuffer}
+\setinterfacecommand{getmarking}{obtientmarquage}
+\setinterfacecommand{getnumber}{getnumber}
+\setinterfacecommand{godown}{vaenbas}
+\setinterfacecommand{goto}{va}
+\setinterfacecommand{gotobox}{vaalaboite}
+\setinterfacecommand{gotopage}{vaalapage}
+\setinterfacecommand{graycolor}{couleurgrise}
+\setinterfacecommand{greyvalue}{valeurgris}
+\setinterfacecommand{grid}{grille}
+\setinterfacecommand{hairline}{ligneh}
+\setinterfacecommand{head}{tete}
+\setinterfacecommand{headerdistance}{distanceentete}
+\setinterfacecommand{headerheight}{hauteurentete}
+\setinterfacecommand{headlevel}{niveautete}
+\setinterfacecommand{headnumber}{numerotete}
+\setinterfacecommand{headsym}{headsym}
+\setinterfacecommand{headtext}{textetete}
+\setinterfacecommand{hideblocks}{cacheblocs}
+\setinterfacecommand{high}{haut}
+\setinterfacecommand{hl}{hl}
+\setinterfacecommand{immediatebetweenlist}{immediatebetweenlist}
+\setinterfacecommand{immediatetolist}{immediatetolist}
+\setinterfacecommand{in}{dans}
+\setinterfacecommand{incrementnumber}{incrementenumero}
+\setinterfacecommand{indenting}{composeenalinea}
+\setinterfacecommand{inframed}{inframed}
+\setinterfacecommand{infull}{infull}
+\setinterfacecommand{ininner}{ininner}
+\setinterfacecommand{inleft}{dansgauche}
+\setinterfacecommand{inleftedge}{dansbordgauche}
+\setinterfacecommand{inleftmargin}{dansmargegauche}
+\setinterfacecommand{inline}{alaligne}
+\setinterfacecommand{inmargin}{dansmarge}
+\setinterfacecommand{inmframed}{inmframed}
+\setinterfacecommand{inneredgedistance}{inneredgedistance}
+\setinterfacecommand{inneredgewidth}{inneredgewidth}
+\setinterfacecommand{innermargindistance}{innermargindistance}
+\setinterfacecommand{innermarginwidth}{innermarginwidth}
+\setinterfacecommand{inothermargin}{dansautremarge}
+\setinterfacecommand{inouter}{inouter}
+\setinterfacecommand{inright}{dansdroite}
+\setinterfacecommand{inrightedge}{dansborddroit}
+\setinterfacecommand{inrightmargin}{dansmargedroite}
+\setinterfacecommand{installlanguage}{installelangue}
+\setinterfacecommand{interactionbar}{barreinteraction}
+\setinterfacecommand{interactionbuttons}{boutonsinteraction}
+\setinterfacecommand{interactionmenu}{menuinteraction}
+\setinterfacecommand{item}{element}
+\setinterfacecommand{items}{elements}
+\setinterfacecommand{its}{el}
+\setinterfacecommand{keepblocks}{gardeblocs}
+\setinterfacecommand{label}{etiquette}
+\setinterfacecommand{labels}{etiquettes}
+\setinterfacecommand{labeltext}{labeltexte}
+\setinterfacecommand{language}{langue}
+\setinterfacecommand{leftaligned}{aligneagauche}
+\setinterfacecommand{leftedgedistance}{distancebordgauche}
+\setinterfacecommand{leftedgewidth}{largeurbordgauche}
+\setinterfacecommand{leftmargindistance}{distancemargegauche}
+\setinterfacecommand{leftmarginwidth}{largeurmargegauche}
+\setinterfacecommand{leg}{leg}
+\setinterfacecommand{linewidth}{largeurligne}
+\setinterfacecommand{listheight}{hauteurliste}
+\setinterfacecommand{listlength}{llongueurliste}
+\setinterfacecommand{listsymbol}{listesymbole}
+\setinterfacecommand{listwidth}{largeurliste}
+\setinterfacecommand{logfields}{logchamp}
+\setinterfacecommand{lohi}{baha}
+\setinterfacecommand{low}{bas}
+\setinterfacecommand{macroname}{nommacro}
+\setinterfacecommand{mainlanguage}{langueprincipale}
+\setinterfacecommand{makeupheight}{hauteurmakeup}
+\setinterfacecommand{makeupwidth}{largeurmakeup}
+\setinterfacecommand{mar}{mar}
+\setinterfacecommand{margindistance}{distancemarge}
+\setinterfacecommand{marginrule}{margereglee}
+\setinterfacecommand{margintext}{textemarge}
+\setinterfacecommand{margintitle}{titremarge}
+\setinterfacecommand{marginwidth}{largeurmarge}
+\setinterfacecommand{marginword}{motmarge}
+\setinterfacecommand{marking}{marquage}
+\setinterfacecommand{markversion}{marquageversion}
+\setinterfacecommand{mathematics}{mathematique}
+\setinterfacecommand{menubutton}{boutonmenu}
+\setinterfacecommand{mframed}{mframed}
+\setinterfacecommand{midaligned}{aligneaumilieu}
+\setinterfacecommand{mirror}{reflete}
+\setinterfacecommand{month}{mois}
+\setinterfacecommand{moveformula}{deplaceformule}
+\setinterfacecommand{moveongrid}{deplacesurgrille}
+\setinterfacecommand{movesidefloat}{movesidefloat}
+\setinterfacecommand{navigating}{navigating}
+\setinterfacecommand{nodimension}{sansdimension}
+\setinterfacecommand{noheaderandfooterlines}{sanslignesenteteetpdp}
+\setinterfacecommand{noindenting}{sansalinea}
+\setinterfacecommand{nolist}{sansliste}
+\setinterfacecommand{nomarking}{sansmarquage}
+\setinterfacecommand{nomoreblocks}{pasplusdeblocs}
+\setinterfacecommand{nomorefiles}{pasplusdefichiers}
+\setinterfacecommand{nop}{nop}
+\setinterfacecommand{nospace}{sansespace}
+\setinterfacecommand{note}{note}
+\setinterfacecommand{notopandbottomlines}{sanslignessupetinf}
+\setinterfacecommand{notsmallcapped}{nocap}
+\setinterfacecommand{nowhitespace}{sansespaceblanc}
+\setinterfacecommand{numberofsubpages}{nombredesouspages}
+\setinterfacecommand{numbers}{numeros}
+\setinterfacecommand{outeredgedistance}{outeredgedistance}
+\setinterfacecommand{outeredgewidth}{outeredgewidth}
+\setinterfacecommand{outermargindistance}{outermargindistance}
+\setinterfacecommand{outermarginwidth}{outermarginwidth}
+\setinterfacecommand{packed}{groupe}
+\setinterfacecommand{page}{page}
+\setinterfacecommand{pagedepth}{pagedepth}
+\setinterfacecommand{pagenumber}{numeropage}
+\setinterfacecommand{pageoffset}{pageoffset}
+\setinterfacecommand{pagereference}{referencepage}
+\setinterfacecommand{pagetype}{tapepage}
+\setinterfacecommand{paperheight}{hauteurpapier}
+\setinterfacecommand{paperwidth}{largeurpapier}
+\setinterfacecommand{periods}{periodes}
+\setinterfacecommand{plaatsruwelijst}{placerawlist}
+\setinterfacecommand{placebookmarks}{placemarquespages}
+\setinterfacecommand{placecombinedlist}{placelisteinmbriquee}
+\setinterfacecommand{placefloat}{placeflottant}
+\setinterfacecommand{placefootnotes}{placenotespdp}
+\setinterfacecommand{placeformula}{placeformule}
+\setinterfacecommand{placeheadnumber}{placenumerotete}
+\setinterfacecommand{placeheadtext}{placetextetete}
+\setinterfacecommand{placelegend}{placelegende}
+\setinterfacecommand{placelist}{placeliste}
+\setinterfacecommand{placelocalfootnotes}{placenotespdplocales}
+\setinterfacecommand{placelogos}{placelogos}
+\setinterfacecommand{placeongrid}{placesurgrille}
+\setinterfacecommand{placeontopofeachother}{placelesunsaudessusdesautres}
+\setinterfacecommand{placepagenumber}{placenumeropage}
+\setinterfacecommand{placereferencelist}{placelistereference}
+\setinterfacecommand{placeregister}{placeregistre}
+\setinterfacecommand{placerule}{placeregle}
+\setinterfacecommand{placesidebyside}{placecoteacote}
+\setinterfacecommand{placesubformula}{placesousformule}
+\setinterfacecommand{placetextvariable}{placevariabletexte}
+\setinterfacecommand{position}{position}
+\setinterfacecommand{positiontext}{positionnetexte}
+\setinterfacecommand{printpaperheight}{hauteureditionpapier}
+\setinterfacecommand{printpaperwidth}{largeureditionpapier}
+\setinterfacecommand{processblocks}{traiteblocs}
+\setinterfacecommand{processpage}{traitepage}
+\setinterfacecommand{product}{produit}
+\setinterfacecommand{program}{programme}
+\setinterfacecommand{project}{projet}
+\setinterfacecommand{publication}{publication}
+\setinterfacecommand{quotation}{citation}
+\setinterfacecommand{quote}{citer}
+\setinterfacecommand{ran}{ran}
+\setinterfacecommand{redo}{refait}
+\setinterfacecommand{ref}{ref}
+\setinterfacecommand{reference}{reference}
+\setinterfacecommand{referral}{recommandation}
+\setinterfacecommand{referraldate}{daterecommandation}
+\setinterfacecommand{referring}{faitreference}
+\setinterfacecommand{remark}{commentaire}
+\setinterfacecommand{reset}{raz}
+\setinterfacecommand{resetmarking}{razmarquage}
+\setinterfacecommand{resetnumber}{raznumero}
+\setinterfacecommand{resettext}{resettextcontent}
+\setinterfacecommand{rightaligned}{aligneadroite}
+\setinterfacecommand{rightedgedistance}{distanceborddroit}
+\setinterfacecommand{rightedgewidth}{largeurborddroit}
+\setinterfacecommand{rightmargindistance}{distancemargedroite}
+\setinterfacecommand{rightmarginwidth}{largeurmargedroite}
+\setinterfacecommand{romannumerals}{chiffresromains}
+\setinterfacecommand{rotate}{oriente}
+\setinterfacecommand{scale}{echelle}
+\setinterfacecommand{screen}{ecran}
+\setinterfacecommand{selectblocks}{selectionneblocs}
+\setinterfacecommand{selectpaper}{selectionnepapier}
+\setinterfacecommand{selectversion}{selectionneversion}
+\setinterfacecommand{setnumber}{affectenumero}
+\setinterfacecommand{settextcontent}{settext}
+\setinterfacecommand{settextvariable}{affectevariabletexte}
+\setinterfacecommand{setupalign}{reglealignement}
+\setinterfacecommand{setupanswerarea}{setupanswerarea}
+\setinterfacecommand{setuparranging}{reglearrangement}
+\setinterfacecommand{setupbackground}{reglearriereplan}
+\setinterfacecommand{setupbackgrounds}{reglearriereplans}
+\setinterfacecommand{setupblackrules}{reglelignesnoires}
+\setinterfacecommand{setupblank}{definitvide}
+\setinterfacecommand{setupblock}{reglebloc}
+\setinterfacecommand{setupbodyfont}{reglepolicecorps}
+\setinterfacecommand{setupbodyfontenvironment}{regleenvironnementpolicecorps}
+\setinterfacecommand{setupbottom}{regleinf}
+\setinterfacecommand{setupbottomtexts}{regletextesinf}
+\setinterfacecommand{setupbuffer}{reglebuffer}
+\setinterfacecommand{setupbuttons}{regleboutons}
+\setinterfacecommand{setupcapitals}{reglecapitales}
+\setinterfacecommand{setupcaption}{regleintitule}
+\setinterfacecommand{setupcaptions}{regleintitules}
+\setinterfacecommand{setupclipping}{regleclipping}
+\setinterfacecommand{setupcolor}{reglecouleur}
+\setinterfacecommand{setupcolors}{reglecouleurs}
+\setinterfacecommand{setupcolumns}{reglecolonnes}
+\setinterfacecommand{setupcolumnset}{reglejeucolonne}
+\setinterfacecommand{setupcolumnsetlines}{setupcolumnsetlines}
+\setinterfacecommand{setupcolumnsetstart}{setupcolumnsetstart}
+\setinterfacecommand{setupcombinations}{reglecombinaisons}
+\setinterfacecommand{setupcombinedlist}{reglelisteimbriquee}
+\setinterfacecommand{setupcomment}{reglecommentaire}
+\setinterfacecommand{setupdescriptions}{regledescriptions}
+\setinterfacecommand{setupenumerations}{regleenumerations}
+\setinterfacecommand{setupexternalfigures}{reglefiguresexternes}
+\setinterfacecommand{setupfield}{reglechamp}
+\setinterfacecommand{setupfields}{reglechamps}
+\setinterfacecommand{setupfillinlines}{regleremplitligne}
+\setinterfacecommand{setupfillinrules}{regleremplitlignesreglees}
+\setinterfacecommand{setupfloat}{regleflottant}
+\setinterfacecommand{setupfloats}{regleflottants}
+\setinterfacecommand{setupfloatsplitting}{regleseparationflottant}
+\setinterfacecommand{setupfooter}{reglepdp}
+\setinterfacecommand{setupfootertexts}{regletextespdp}
+\setinterfacecommand{setupfootnotedefinition}{definitnotepdp}
+\setinterfacecommand{setupfootnotes}{reglenotepdp}
+\setinterfacecommand{setupforms}{regleformulaires}
+\setinterfacecommand{setupformulas}{regleformules}
+\setinterfacecommand{setupframed}{regleencadre}
+\setinterfacecommand{setupframedtexts}{setupframedtexts}
+\setinterfacecommand{setuphead}{regletete}
+\setinterfacecommand{setupheader}{regleentete}
+\setinterfacecommand{setupheadertexts}{regletextesentete}
+\setinterfacecommand{setupheadnumber}{reglenumerotete}
+\setinterfacecommand{setupheads}{regletetes}
+\setinterfacecommand{setupheadtext}{regletextetete}
+\setinterfacecommand{setuphyphenmark}{reglemarquagehyphenation}
+\setinterfacecommand{setupindentations}{reglealineas}
+\setinterfacecommand{setupindenting}{reglecomposeenalinea}
+\setinterfacecommand{setupinmargin}{regledansmarge}
+\setinterfacecommand{setupinteraction}{regleinteraction}
+\setinterfacecommand{setupinteractionbar}{reglebarreinteraction}
+\setinterfacecommand{setupinteractionmenu}{reglemenuinteraction}
+\setinterfacecommand{setupinteractionscreen}{regleecraninteraction}
+\setinterfacecommand{setupinterlinespace}{regleespacementinterligne}
+\setinterfacecommand{setupitemgroup}{setupitemgroup}
+\setinterfacecommand{setupitemgroups}{reglegroupeselements}
+\setinterfacecommand{setupitems}{regleelements}
+\setinterfacecommand{setuplabeltext}{reglelabeltexte}
+\setinterfacecommand{setuplanguage}{reglelangue}
+\setinterfacecommand{setuplayout}{regledisposition}
+\setinterfacecommand{setuplegend}{reglelegende}
+\setinterfacecommand{setuplinenumbering}{reglenumerotationligne}
+\setinterfacecommand{setuplines}{reglelignes}
+\setinterfacecommand{setuplinewidth}{regleepaisseurligne}
+\setinterfacecommand{setuplist}{regleliste}
+\setinterfacecommand{setupmakeup}{reglemakeup}
+\setinterfacecommand{setupmarginblocks}{regleblocmarge}
+\setinterfacecommand{setupmarginrules}{reglemargereglee}
+\setinterfacecommand{setupmarking}{reglemarquage}
+\setinterfacecommand{setupmathalignment}{setupmathalignment}
+\setinterfacecommand{setupnarrower}{reglecompoetroite}
+\setinterfacecommand{setupnumber}{reglenumero}
+\setinterfacecommand{setupnumbering}{reglenumerotation}
+\setinterfacecommand{setupoppositeplacing}{regleplacementopposition}
+\setinterfacecommand{setupoutput}{reglesortie}
+\setinterfacecommand{setuppagecomment}{reglecommentairepage}
+\setinterfacecommand{setuppagenumber}{reglenumeropage}
+\setinterfacecommand{setuppagenumbering}{reglenumerotationpage}
+\setinterfacecommand{setuppagetransitions}{regletransitionspage}
+\setinterfacecommand{setuppalet}{reglepalette}
+\setinterfacecommand{setuppaper}{reglepapier}
+\setinterfacecommand{setuppapersize}{regletaillepapier}
+\setinterfacecommand{setupparagraphnumbering}{reglenumerotationparagraphe}
+\setinterfacecommand{setupparagraphs}{regleparagraphes}
+\setinterfacecommand{setupplacement}{setupplacement}
+\setinterfacecommand{setuppositioning}{reglepositionnement}
+\setinterfacecommand{setupprofiles}{regleprofils}
+\setinterfacecommand{setupprograms}{regleprogrammes}
+\setinterfacecommand{setuppublications}{reglepublications}
+\setinterfacecommand{setupquote}{demarreciter}
+\setinterfacecommand{setupreferencelist}{reglelistereference}
+\setinterfacecommand{setupreferencing}{reglereferencage}
+\setinterfacecommand{setupregister}{regleregistre}
+\setinterfacecommand{setuprotate}{regleoriente}
+\setinterfacecommand{setuprule}{regleregle}
+\setinterfacecommand{setups}{reglages}
+\setinterfacecommand{setupscreens}{regleecrans}
+\setinterfacecommand{setupsection}{reglesection}
+\setinterfacecommand{setupsectionblock}{regleblocsection}
+\setinterfacecommand{setupsorting}{regletri}
+\setinterfacecommand{setupspacing}{regleespacement}
+\setinterfacecommand{setupstartstop}{regledemarrestoppe}
+\setinterfacecommand{setupstrut}{reglestrut}
+\setinterfacecommand{setupsubpagenumber}{reglesousnumeropage}
+\setinterfacecommand{setupsymbolset}{reglejeusymboles}
+\setinterfacecommand{setupsynchronization}{reglesynchronisation}
+\setinterfacecommand{setupsynchronizationbar}{reglebarresynchronisation}
+\setinterfacecommand{setupsynonyms}{reglesynonymes}
+\setinterfacecommand{setupsystem}{reglesysteme}
+\setinterfacecommand{setuptab}{regletab}
+\setinterfacecommand{setuptables}{regletableaux}
+\setinterfacecommand{setuptabulate}{regletabulation}
+\setinterfacecommand{setuptext}{regletexte}
+\setinterfacecommand{setuptextposition}{reglepositiontexte}
+\setinterfacecommand{setuptextrules}{reglelignesreglestexte}
+\setinterfacecommand{setuptexttexts}{regletextestexte}
+\setinterfacecommand{setuptextvariable}{reglevariabletexte}
+\setinterfacecommand{setupthinrules}{regletraitsfins}
+\setinterfacecommand{setuptolerance}{regletolerance}
+\setinterfacecommand{setuptop}{reglesup}
+\setinterfacecommand{setuptoptexts}{regletextessup}
+\setinterfacecommand{setuptype}{regletype}
+\setinterfacecommand{setuptyping}{regledactylo}
+\setinterfacecommand{setupunderbar}{reglesouslignage}
+\setinterfacecommand{setupurl}{regleurl}
+\setinterfacecommand{setupversions}{regleversions}
+\setinterfacecommand{setupwhitespace}{regleespaceblanc}
+\setinterfacecommand{showbodyfont}{montrepolicecorps}
+\setinterfacecommand{showbodyfontenvironment}{montreenvironnementpolicecorps}
+\setinterfacecommand{showcolor}{montrecouleur}
+\setinterfacecommand{showcolorgroup}{montregroupecouleur}
+\setinterfacecommand{showexternalfigures}{montrefiguresexternes}
+\setinterfacecommand{showfields}{montrechamps}
+\setinterfacecommand{showframe}{montrecadre}
+\setinterfacecommand{showgrid}{montregrille}
+\setinterfacecommand{showlayout}{montredisposition}
+\setinterfacecommand{showmakeup}{montremakeup}
+\setinterfacecommand{showpalet}{montrepalette}
+\setinterfacecommand{showprint}{montreedition}
+\setinterfacecommand{showsetups}{montrereglages}
+\setinterfacecommand{showstruts}{montrestruts}
+\setinterfacecommand{showsymbolset}{montrejeusymboles}
+\setinterfacecommand{smallcapped}{cap}
+\setinterfacecommand{someline}{uneligne}
+\setinterfacecommand{somewhere}{qqpart}
+\setinterfacecommand{space}{espace}
+\setinterfacecommand{splitfloat}{separeflottant}
+\setinterfacecommand{startalignment}{demarrealignement}
+\setinterfacecommand{startbackground}{demarrearriereplan}
+\setinterfacecommand{startcoding}{demarrecodage}
+\setinterfacecommand{startcolor}{demarrecouleur}
+\setinterfacecommand{startcolumnmakeup}{startcolumnmakeup}
+\setinterfacecommand{startcolumns}{demarrecolonnes}
+\setinterfacecommand{startcolumnset}{demarrejeucolonne}
+\setinterfacecommand{startcombination}{demarrecombinaison}
+\setinterfacecommand{startcomponent}{demarrecomposant}
+\setinterfacecommand{startdocument}{demarredocument}
+\setinterfacecommand{startenvironment}{demarreenvironement}
+\setinterfacecommand{startfigure}{demarrefigure}
+\setinterfacecommand{startglobal}{demarreglobal}
+\setinterfacecommand{startline}{demarreligne}
+\setinterfacecommand{startlinecorrection}{demarrecorrectionligne}
+\setinterfacecommand{startlinenumbering}{demarrenumerotationligne}
+\setinterfacecommand{startlines}{demarrelignes}
+\setinterfacecommand{startlocal}{demarrelocal}
+\setinterfacecommand{startlocalfootnotes}{demarrenotespdplocales}
+\setinterfacecommand{startmakeup}{demarremakeup}
+\setinterfacecommand{startmarginblock}{demarreblocmarge}
+\setinterfacecommand{startmarginrule}{demarremargereglee}
+\setinterfacecommand{startnarrower}{demarrecompoetroite}
+\setinterfacecommand{startopposite}{demarreopposition}
+\setinterfacecommand{startoverlay}{demarrerevetement}
+\setinterfacecommand{startoverzicht}{demarrevuedensemble}
+\setinterfacecommand{startpacked}{demarregroupe}
+\setinterfacecommand{startpositioning}{demarrepositionnement}
+\setinterfacecommand{startproduct}{demarreproduit}
+\setinterfacecommand{startprofile}{demarreprofil}
+\setinterfacecommand{startproject}{demarreprojet}
+\setinterfacecommand{startquotation}{demarrecitation}
+\setinterfacecommand{startraster}{demarreraster}
+\setinterfacecommand{startsymbolset}{demarrejeusymboles}
+\setinterfacecommand{startsynchronization}{demarresynchronisation}
+\setinterfacecommand{starttable}{demarretableau}
+\setinterfacecommand{starttables}{demarretableaux}
+\setinterfacecommand{starttext}{demarretexte}
+\setinterfacecommand{starttextrule}{demarreligneregleetexte}
+\setinterfacecommand{startunpacked}{demarredegroupe}
+\setinterfacecommand{startversion}{demarreversion}
+\setinterfacecommand{stopalignment}{stoppealignement}
+\setinterfacecommand{stopbackground}{stoppearriereplan}
+\setinterfacecommand{stopcoding}{stoppecodage}
+\setinterfacecommand{stopcolor}{stoppecouleur}
+\setinterfacecommand{stopcolumnmakeup}{stopcolumnmakeup}
+\setinterfacecommand{stopcolumns}{stoppecolonnes}
+\setinterfacecommand{stopcolumnset}{stoppejeucolonne}
+\setinterfacecommand{stopcombination}{stoppecombinaison}
+\setinterfacecommand{stopcomponent}{stoppecomposant}
+\setinterfacecommand{stopdocument}{stoppedocument}
+\setinterfacecommand{stopenvironment}{stoppeenvironement}
+\setinterfacecommand{stopglobal}{stoppeglobal}
+\setinterfacecommand{stopline}{stoppeligne}
+\setinterfacecommand{stoplinecorrection}{stoppecorrectionligne}
+\setinterfacecommand{stoplinenumbering}{stoppenumerotationligne}
+\setinterfacecommand{stoplines}{stoppelignes}
+\setinterfacecommand{stoplocal}{stoppelocal}
+\setinterfacecommand{stoplocalfootnotes}{stoppenotespdplocales}
+\setinterfacecommand{stopmakeup}{stoppemakeup}
+\setinterfacecommand{stopmarginblock}{stoppeblocmarge}
+\setinterfacecommand{stopmarginrule}{stoppemargereglee}
+\setinterfacecommand{stopnarrower}{stopcompoetroite}
+\setinterfacecommand{stopopposite}{stoppeopposition}
+\setinterfacecommand{stopoverlay}{stopperevetement}
+\setinterfacecommand{stopoverzicht}{stoppevuedensemble}
+\setinterfacecommand{stoppacked}{stoppegroupe}
+\setinterfacecommand{stoppositioning}{stoppepositionnement}
+\setinterfacecommand{stopproduct}{stoppeproduit}
+\setinterfacecommand{stopprofile}{stoppeprofil}
+\setinterfacecommand{stopproject}{stoppeprojet}
+\setinterfacecommand{stopquotation}{stoppecitation}
+\setinterfacecommand{stopraster}{stopperaster}
+\setinterfacecommand{stopsynchronization}{stoppesynchronisation}
+\setinterfacecommand{stoptable}{stoppetableau}
+\setinterfacecommand{stoptables}{stoppetableaux}
+\setinterfacecommand{stoptext}{stoppetexte}
+\setinterfacecommand{stoptextrule}{stoppeligneregleetexte}
+\setinterfacecommand{stopunpacked}{stoppedegroupe}
+\setinterfacecommand{stopversion}{stoppeversion}
+\setinterfacecommand{stretched}{etire}
+\setinterfacecommand{subformulanumber}{numerosousformule}
+\setinterfacecommand{subpagenumber}{sousnumeropage}
+\setinterfacecommand{switchtobodyfont}{changepolicecorps}
+\setinterfacecommand{switchtorawfont}{changepolicebrute}
+\setinterfacecommand{sym}{sym}
+\setinterfacecommand{symbol}{symbole}
+\setinterfacecommand{synchronizationbar}{barresynchronisation}
+\setinterfacecommand{synchronize}{synchronise}
+\setinterfacecommand{tab}{tab}
+\setinterfacecommand{testcolumn}{testcolumn}
+\setinterfacecommand{testpage}{testpage}
+\setinterfacecommand{tex}{tex}
+\setinterfacecommand{textheight}{hauteurtexte}
+\setinterfacecommand{textreference}{referencetexte}
+\setinterfacecommand{textrule}{ligneregleetexte}
+\setinterfacecommand{textvariable}{variabletexte}
+\setinterfacecommand{textwidth}{largeurtexte}
+\setinterfacecommand{thinrule}{traitfin}
+\setinterfacecommand{thinrules}{traitsfins}
+\setinterfacecommand{tooltip}{suggestion}
+\setinterfacecommand{topdistance}{distancesup}
+\setinterfacecommand{topheight}{hauteursup}
+\setinterfacecommand{topspace}{espacesup}
+\setinterfacecommand{totalnumberofpages}{nombretotaldepages}
+\setinterfacecommand{translate}{traduire}
+\setinterfacecommand{txt}{txt}
+\setinterfacecommand{typ}{typ}
+\setinterfacecommand{type}{dactylographier}
+\setinterfacecommand{typebuffer}{tapebuffer}
+\setinterfacecommand{typefile}{fichierdactylo}
+\setinterfacecommand{unitmeaning}{sensunite}
+\setinterfacecommand{unknown}{inconnu}
+\setinterfacecommand{useJSscripts}{utiliseJSscripts}
+\setinterfacecommand{useURL}{utiliseURL}
+\setinterfacecommand{useXMLfilter}{useXMLfilter}
+\setinterfacecommand{useblocks}{utiliseblocs}
+\setinterfacecommand{usecommands}{utilisecommandes}
+\setinterfacecommand{useencoding}{utiliseencodage}
+\setinterfacecommand{useexternaldocument}{utilisedocumentexterne}
+\setinterfacecommand{useexternalfigure}{utilisefigureexterne}
+\setinterfacecommand{useexternalfile}{utilisefichierexterne}
+\setinterfacecommand{useexternalfiles}{utilisefichiersexternes}
+\setinterfacecommand{useexternalsoundtrack}{utilisepsiteaudioexterne}
+\setinterfacecommand{usemodule}{utilisemodule}
+\setinterfacecommand{usemodules}{utilisemodules}
+\setinterfacecommand{usepath}{utilisechemin}
+\setinterfacecommand{usereferences}{utilisereferences}
+\setinterfacecommand{usespecials}{utilisespecialites}
+\setinterfacecommand{usesymbols}{utilisesymboles}
+\setinterfacecommand{usetypescript}{usetypescript}
+\setinterfacecommand{usetypescriptfile}{usetypescriptfile}
+\setinterfacecommand{useurl}{utiliseurl}
+\setinterfacecommand{version}{version}
+\setinterfacecommand{vl}{vl}
+\setinterfacecommand{weekday}{joursemaine}
+\setinterfacecommand{whitespace}{espaceblanc}
+\setinterfacecommand{wordright}{motdroit}
+\setinterfacecommand{writebetweenlist}{ecritentreliste}
+\setinterfacecommand{writetolist}{ecritdansliste}
+\setinterfacecommand{writetoreferencelist}{ecritdanslistereference}
+\setinterfacecommand{writetoregister}{ecritregistre}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-fst.tex b/tex/context/base/mult-fst.tex
new file mode 100644
index 000000000..c237f5743
--- /dev/null
+++ b/tex/context/base/mult-fst.tex
@@ -0,0 +1,53 @@
+%D \module
+%D [ file=mult-fst,
+%D version=2006.08.16,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Speed Up,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% And so, after a few years of keeping this potentially dangerous
+% speedup in cont-exp, we now move it to the kernel: the next
+% patch is 30\% faster on main interface (seconds) (9->7 sec on
+% 1 million calls). Another speed up is still under testing.
+
+\unprotect
+
+\startinterface english
+
+ \def\dosetvalue #1#2{\@EA\def \csname#1#2\endcsname}
+ \def\dosetevalue #1#2{\@EA\edef\csname#1#2\endcsname}
+ \def\dosetgvalue #1#2{\@EA\gdef\csname#1#2\endcsname}
+ \def\dosetxvalue #1#2{\@EA\gdef\csname#1#2\endcsname}
+ \def\docopyvalue#1#2#3{\@EA\def \csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}}
+
+ \ifx\ctxlua\undefined
+
+ \def\setinterfaceconstant#1#2%
+ {\setvalue{\c!prefix!#1}{#1}}
+
+ \def\setinterfacevariable#1#2%
+ {\setvalue{\v!prefix!#1}{#2}}
+
+ \else
+
+ \def\setinterfaceconstant#1#2%
+ {\ctxlua{interfaces.setconstant("#1","#2")}%
+ \setvalue{\c!prefix!#1}{#1}}
+
+ \def\setinterfacevariable#1#2%
+ {\ctxlua{interfaces.setvariable("#1","#2")}%
+ \setvalue{\v!prefix!#1}{#2}}
+
+ \fi
+
+ \def\interfaced#1{#1}
+
+\stopinterface
+
+\protect \endinput
diff --git a/tex/context/base/mult-ini.lua b/tex/context/base/mult-ini.lua
new file mode 100644
index 000000000..92a7bc629
--- /dev/null
+++ b/tex/context/base/mult-ini.lua
@@ -0,0 +1,105 @@
+if not modules then modules = { } end modules ['mult-ini'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, gmatch, gsub = string.format, string.gmatch, string.gsub
+local lpegmatch = lpeg.match
+local serialize = table.serialize
+
+interfaces = interfaces or { }
+interfaces.messages = interfaces.messages or { }
+interfaces.constants = interfaces.constants or { }
+interfaces.variables = interfaces.variables or { }
+
+storage.register("interfaces/messages", interfaces.messages, "interfaces.messages" )
+storage.register("interfaces/constants", interfaces.constants, "interfaces.constants")
+storage.register("interfaces/variables", interfaces.variables, "interfaces.variables")
+
+local messages, constants, variables = interfaces.messages, interfaces.constants, interfaces.variables
+
+function interfaces.setmessages(category,str)
+ local m = messages[category] or { }
+ for k, v in gmatch(str,"(%S+) *: *(.-) *[\n\r]") do
+ m[k] = gsub(v,"%-%-","%%s")
+ end
+ messages[category] = m
+end
+
+function interfaces.setmessage(category,tag,message)
+ local m = messages[category]
+ if not m then
+ m = { }
+ messages[category] = m
+ end
+ m[tag] = gsub(message,"%-%-","%%s")
+end
+
+function interfaces.getmessage(category,tag,default)
+ local m = messages[category]
+ return (m and m[tag]) or default or "unknown message"
+end
+
+function interfaces.doifelsemessage(category,tag)
+ local m = messages[category]
+ return commands.testcase(m and m[tag])
+end
+
+local messagesplitter = lpeg.splitat(",")
+
+function interfaces.makemessage(category,tag,arguments)
+ local m = messages[category]
+ m = (m and (m[tag] or m[tostring(tag)])) or format("unknown message, category '%s', tag '%s'",category,tag)
+ if not m then
+ return m .. " " .. tag
+ elseif not arguments then
+ return m
+ else
+ return format(m,lpegmatch(messagesplitter,arguments))
+ end
+end
+
+function interfaces.showmessage(category,tag,arguments)
+ local m = messages[category]
+ commands.writestatus((m and m.title) or "unknown title",interfaces.makemessage(category,tag,arguments))
+end
+
+function interfaces.setvariable(variable,given)
+--~ variables[given] = variable
+ variables[variable] = given
+end
+
+function interfaces.setconstant(constant,given)
+ constants[given] = constant
+end
+
+-- it's nicer to have numbers as reference than a hash
+
+interfaces.cachedsetups = interfaces.cachedsetups or { }
+interfaces.hashedsetups = interfaces.hashedsetups or { }
+
+storage.register("interfaces.cachedsetups", interfaces.cachedsetups, "interfaces.cachedsetups")
+storage.register("interfaces.hashedsetups", interfaces.hashedsetups, "interfaces.hashedsetups")
+
+local cachedsetups = interfaces.cachedsetups
+local hashedsetups = interfaces.hashedsetups
+
+function interfaces.cachesetup(t)
+ local hash = serialize(t)
+ local done = hashedsetups[hash]
+ if done then
+ return cachedsetups[done]
+ else
+ done = #cachedsetups + 1
+ cachedsetups[done] = t
+ hashedsetups[hash] = done
+ return t
+ end
+end
+
+function interfaces.is_command(str)
+ return (str and str ~= "" and token.csname_name(token.create(str)) ~= "") or false
+end
diff --git a/tex/context/base/mult-ini.mkii b/tex/context/base/mult-ini.mkii
new file mode 100644
index 000000000..c2bb40861
--- /dev/null
+++ b/tex/context/base/mult-ini.mkii
@@ -0,0 +1,935 @@
+%D \module
+%D [ file=mult-ini,
+%D version=2008.10.22, % 1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is a stripped down version of \type {mult-ini.tex},
+%D which we keep around as \type {mult-kep.tex} for sentimental
+%D reasons. There you will find some more historic information.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Initialization}
+
+\unprotect
+
+%D \macros
+%D [constanten,variabelen,commands]
+%D {v!,c!,k!,s!,e!,m!,l!,r!,f!,p!,x!,y!}
+%D
+%D In the system modules we introduced some prefixed constants,
+%D variables (both macros) and registers. Apart from a
+%D tremendous saving in terms of memory and a gain in speed we
+%D use from now on prefixes when possible for just another
+%D reason: consistency and multi||linguality. Systematically
+%D using prefixed macros enables us to implement a
+%D multi||lingual user interface. Redefining these next set of
+%D prefixes therefore can have desastrous results.
+%D
+%D \startlinecorrection
+%D \starttable[|c|c|c|]
+%D \HL
+%D \NC \bf prefix \NC \bf meaning \NC \bf application \NC\SR
+%D \HL
+%D \NC \type{\c!prefix!} \NC c! \NC constant (direct) \NC\FR
+%D \NC \type{\e!prefix!} \NC e! \NC element \NC\MR
+%D \NC \type{\f!prefix!} \NC f! \NC file \NC\MR
+%D \NC \type{\k!prefix!} \NC k! \NC constant (indirect) \NC\MR
+%D \NC \type{\l!prefix!} \NC l! \NC language \NC\MR
+%D \NC \type{\m!prefix!} \NC m! \NC message \NC\MR
+%D \NC \type{\p!prefix!} \NC p! \NC procedure \NC\MR
+%D \NC \type{\r!prefix!} \NC r! \NC reference \NC\MR
+%D \NC \type{\s!prefix!} \NC s! \NC system \NC\MR
+%D \NC \type{\v!prefix!} \NC v! \NC variable \NC\MR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D In the single||lingual version we used \type{!}, \type{!!},
+%D \type{!!!} and \type{!!!!}.
+
+\def\c!prefix!{c!} \def\e!prefix!{e!} \def\f!prefix!{f!}
+\def\k!prefix!{k!} \def\l!prefix!{l!} \def\m!prefix!{m!}
+\def\p!prefix!{p!} \def\r!prefix!{r!} \def\s!prefix!{s!}
+\def\v!prefix!{v!} \def\t!prefix!{t!}
+
+%D \macros
+%D [constants,variables,commands]
+%D {@@,??}
+%D
+%D Variables generated by the system can be recognized on their
+%D prefix \type{@@}. They are composed of a command (class)
+%D specific tag, which can be recognized on \type{??}, and a
+%D system constant, which has the prefix \type{c!}. We'll se
+%D some more of this.
+
+\def\??prefix {??}
+\def\@@prefix {@@}
+
+%D Just to be complete we repeat some of the already defined
+%D system constants here. Maybe their prefix \type{\s!} now
+%D falls into place.
+
+\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}
+
+%D The word \type{height} takes 6~token memory cells. The
+%D control sequence \type{\height} on the other hand uses only
+%D one. Knowing this, we can improve the performance of \TEX,
+%D both is terms of speed and memory usage, by using control
+%D sequences instead of the words written in full.
+%D
+%D Where in the \ASCII\ file the second lines takes nine extra
+%D characters, \TEX\ saves us 13~tokens.
+%D
+%D \starttyping
+%D \hrule width 10pt height 2pt depth 1pt
+%D \hrule \!!width 10pt \!!height 2pt \!!depth 1pt
+%D \stoptyping
+%D
+%D One condition is that we have defined \type{\!!height},
+%D \type{\!!width} and \type{\!!depth} as respectively
+%D \type{height}, \type{width} and \type{depth}. Using this
+%D scheme therefore only makes sense when a token sequence is
+%D used more than once. Savings like this should of course be
+%D implemented in english, just because \TEX\ is english.
+
+\def\!!width {width}
+\def\!!height {height}
+\def\!!depth {depth}
+\def\!!plus {plus}
+\def\!!minus {minus}
+\def\!!fill {fill}
+\def\!!to {to}
+
+%D \macros
+%D {defineinterfaceconstant,
+%D defineinterfacevariable,
+%D defineinterfaceelement,
+%D definesystemvariable,
+%D definesystemconstant,
+%D definemessageconstant,
+%D definereferenceconstant,
+%D definefileconstant}
+%D
+%D The first part of this module is dedicated to dealing with
+%D multi||lingual constants and variables. When \CONTEXT\ grew
+%D bigger and bigger in terms of bytes and used string space,
+%D we switched to predefined constants. At the cost of more
+%D hash table entries, the macros not only becase more compact,
+%D they became much faster too. Maybe an even bigger advantage
+%D was that mispelling could no longer lead to problems. Even a
+%D multi||lingual interface became possible.
+%D
+%D Constants --- we'll introduce the concept of variables later
+%D on --- are preceded by a type specific prefix, followed by a
+%D \type{!}. To force consistency, we provide a few commands
+%D for defining such constants.
+%D
+%D \starttyping
+%D \defineinterfaceconstant {name} {meaning}
+%D \defineinterfacevariable {name} {meaning}
+%D \defineinterfaceelement {name} {meaning}
+%D \stoptyping
+%D
+%D Which is the same as:
+%D
+%D \starttyping
+%D \def\c!name{meaning}
+%D \def\v!name{meaning}
+%D \def\e!name{meaning}
+%D \stoptyping
+
+\def\defineinterfaceconstant #1#2{\setvalue{\c!prefix!#1}{#2}}
+\def\defineinterfacevariable #1#2{\setvalue{\v!prefix!#1}{#2}}
+\def\defineinterfaceelement #1#2{\setvalue{\e!prefix!#1}{#2}}
+
+%D Next come some interface independant constants:
+%D
+%D \starttyping
+%D \definereferenceconstant {name} {meaning}
+%D \definefileconstant {name} {meaning}
+%D \stoptyping
+
+\def\definereferenceconstant #1#2{\setvalue{\r!prefix!#1}{#2}}
+\def\definefileconstant #1#2{\setvalue{\f!prefix!#1}{#2}}
+
+%D A new one:
+
+\def\definetypescriptconstant#1#2{\setvalue{\t!prefix!#1}{#2}}
+
+%D And finaly we have the one argument, space saving constants
+%D
+%D \starttyping
+%D \definesystemconstant {name}
+%D \definemessageconstant {name}
+%D \stoptyping
+
+\def\definesystemconstant #1{\setvalue{\s!prefix!#1}{#1}}
+\def\definemessageconstant #1{\setvalue{\m!prefix!#1}{#1}}
+
+%D In a parameter driven system, some parameters are shared
+%D by more system components. In \CONTEXT\ we can distinguish
+%D parameters by a unique prefix. Such a prefix is defined
+%D with:
+%D
+%D \starttyping
+%D \definesystemvariable {name}
+%D \stoptyping
+
+\def\definesystemvariable#1{\setevalue{\??prefix#1}{\@@prefix#1}}
+
+\definesystemvariable{ms}
+
+%D \macros
+%D {selectinterface,
+%D defaultinterface, currentinterface, currentresponses}
+%D
+%D With \type{\selectinterface} we specify the language we are
+%D going to use. The system asks for the language wanted, and
+%D defaults to \type{\currentinterface} when we just give
+%D \type{enter}. By default the message system uses the
+%D current interface language, but \type{\currentresponses}
+%D can specify another language too.
+%D
+%D Because we want to generate formats directly too, we do
+%D not ask for interface specifications when these are already
+%D defined (like in cont-nl.tex and alike).
+
+\ifx\defaultinterface\undefined
+
+ \def\defaultinterface{english}
+
+ \def\selectinterface
+ {\def\docommand##1##2%
+ {\bgroup
+ \endlinechar\minusone
+ \global\read16 to ##1
+ \egroup
+ \doifnothing\currentinterface{\let##1=##2}%
+ \doifundefined{\s!prefix!##1}{\let##1=##2}}%
+ \docommand\currentinterface\defaultinterface
+ \writestatus{interface}{defining \currentinterface\space interface}%
+ \writeline
+ \docommand\currentresponses\currentinterface
+ \writestatus{interface}{using \currentresponses\space messages}%
+ \writeline
+ \let\selectinterface\relax}
+
+\else
+
+ \def\selectinterface
+ {\writestatus{interface}{defining \currentinterface\space interface}%
+ \writeline
+ \writestatus{interface}{using \currentresponses\space messages}%
+ \writeline
+ \let\selectinterface\relax}
+
+\fi
+
+\ifx\currentinterface\undefined \let\currentinterface=\defaultinterface \fi
+\ifx\currentresponses\undefined \let\currentresponses=\defaultinterface \fi
+
+%D \macros
+%D {startinterface}
+%D
+%D Sometimes we want to define things only for specific
+%D interface languages. This can be done by means of the
+%D selector:
+%D
+%D \starttyping
+%D \startinterface language
+%D
+%D language specific definitions & commands
+%D
+%D \stopinterface
+%D \stoptyping
+
+\def\startinterface #1
+ {\doifnot{#1}{all}{\doifnotinset\currentinterface{#1}{\gobbleuntil\stopinterface}}}
+
+\let\stopinterface\relax
+
+%D \macros
+%D {startmessages,
+%D getmessage,
+%D showmessage,
+%D makemessage}
+%D
+%D A package as large as \CONTEXT\ can hardly function without
+%D a decent message mechanism. Due to its multi||lingual
+%D interface, the message subsystem has to be multi||lingual
+%D too. A major drawback of this feature is that we have to
+%D code messages. As a result, the source becomes less self
+%D documented. On the other hand, consistency will improve.
+%D
+%D Because the overhead in terms of entries in the (already
+%D exhausted) hash table has to be minimal, messages are packed
+%D in libraries. We can extract a message from such a library
+%D in three ways:
+%D
+%D \starttyping
+%D \getmessage {library} {tag}
+%D \showmessage {library} {tag} {data}
+%D \makemessage {library} {tag} {data}
+%D \stoptyping
+%D
+%D The first command gets the message \type{tag} from the
+%D \type{library} specified. The other commands take an extra
+%D argument: a list of items to be inserted in the message
+%D text. While \type{\showmessage} shows the message at the
+%D terminal, the other commands generate the message as text.
+%D Before we explain the \type{data} argument, we give an
+%D example of a library.
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D title: something
+%D 1: first message
+%D 2: second (--) message --
+%D \stopmessages
+%D \stoptyping
+%D
+%D The first message is a simple one and can be shown with:
+%D
+%D \starttyping
+%D \showmessage {alfa} {1} {}
+%D \stoptyping
+%D
+%D The second message on the other hand needs some extra data:
+%D
+%D \starttyping
+%D \showmessage {alfa} {2} {and last,to you}
+%D \stoptyping
+%D
+%D This message is shown as:
+%D
+%D \starttyping
+%D something : second (and last) message to you
+%D \stoptyping
+%D
+%D As we can see, the title entry is shown with the message.
+%D The data fields are comma separated and are specified in the
+%D message text by \type{--}.
+%D
+%D It is not required to define all messages in a library at
+%D once. We can add messages to a library in the following way:
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D 10: tenth message
+%D \stopmessages
+%D \stoptyping
+%D
+%D Because such definitions can take place in different
+%D modules, the system gives a warning when a tag occurs more
+%D than once. The first occurrence takes preference over later
+%D ones, so we had better use a save offset, as shown in the
+%D example. As we can see, the title field is specified only
+%D the first time!
+%D
+%D Because we want to check for duplicate tags, the macros
+%D are a bit more complicated than neccessary. The \NEWLINE\
+%D token is used as message separator.
+%D
+%D For internal purposes one can use \type {\setmessagetext},
+%D which puts the message text asked for in \type
+%D {\currentmessagetext}.
+
+\def\findinterfacemessage#1#2%
+ {\let#2\empty
+ \def\dofindinterfacemessage##1 #1: ##2\relax##3\end{\def#2{##2}}%
+ \edef\!!stringa{\getvalue{\??ms\currentmessagelibrary} #1: \relax}%
+ \expandafter\dofindinterfacemessage\!!stringa\end}
+
+\def\composemessagetext#1--#2--#3--#4--#5--#6--#7--#8--#9\\%
+ {\def\docomposemessagetext##1,##2,##3,##4,##5,##6,##7,##8,##9\\%
+ {\edef\currentmessagetext{#1##1#2##2#3##3#4##4#5##5#6##6#7##7#8##8}}%
+ \docomposemessagetext}
+
+\def\setmessagetext#1#2%
+ {\def\currentmessagelibrary{#1}%
+ \findinterfacemessage{#2}\currentmessagetext}
+
+\unexpanded\def\getmessage#1#2%
+ {\def\currentmessagelibrary{#1}%
+ \findinterfacemessage{#2}\currentmessagetext
+ \currentmessagetext}
+
+\unexpanded\def\makemessage#1#2#3%
+ {\def\currentmessagelibrary{#1}%
+ \findinterfacemessage{#2}\currentmessagetext
+ \@EA\composemessagetext\currentmessagetext----------------\\#3,,,,,,,,\\%
+ \currentmessagetext}
+
+\def\showmessage#1#2#3%
+ {\def\currentmessagelibrary{#1}%
+ \findinterfacemessage{#2}\currentmessagetext
+ \findinterfacemessage{title}\currentmessagetitle
+ \ifx\currentmessagetext\empty
+ \def\currentmessagetext{}%
+ \else
+ \@EA\composemessagetext\currentmessagetext----------------\\#3,,,,,,,,\\%
+ \fi
+ \@EA\writestatus\@EA{\currentmessagetitle}{\currentmessagetext}}
+
+\def\doaddinterfacemessage#1#2%
+ {\findinterfacemessage{#1}\currentmessagetext
+ \doifelsenothing\currentmessagetext
+ {\setxvalue{\??ms\currentmessagelibrary}%
+ {\getvalue{\??ms\currentmessagelibrary} #1: #2\relax}}
+ {\debuggerinfotrue % we consider this an important error
+ \debuggerinfo
+ {message}
+ {duplicate tag #1
+ in library \currentmessagelibrary\space
+ of interface \currentresponses}}%
+ \futurelet\next\getinterfacemessage}
+
+\bgroup
+\obeylines
+\gdef\addinterfacemessage#1: #2
+ {\doaddinterfacemessage{#1}{#2}}%
+\egroup
+
+\def\getinterfacemessage
+ {\ifx\next\stopmessages
+ \egroup\expandafter\gobbleoneargument
+ \else
+ \expandafter\addinterfacemessage
+ \fi}
+
+\let\stopmessages\undefined % for dep checker
+
+\def\startmessages #1 library: #2
+ {\definemessageconstant{#2}% handy for modules
+ \bgroup
+ \obeylines
+ \doifinsetelse{#1}{\currentresponses,all}
+ {\def\next
+ {\def\currentmessagelibrary{#2}%
+ \doifundefined{\??ms\currentmessagelibrary}
+ {\letgvalueempty{\??ms\currentmessagelibrary}}%
+ \futurelet\next\getinterfacemessage}}
+ {\long\def\next##1\stopmessages{\egroup}}%
+ \next}
+
+%D Here, the messages are stored in a way that saves hash
+%D entries, i.e. they are packed in one macro per library.
+%D This was important in the days when we used \TEX's with
+%D hash tables of about 10.000. The next, less efficient way
+%D of storing the message, makes \CONTEXT\ run upto 5\%
+%D faster by storing each message in a macro. In July 2000,
+%D this costs some 185 additional hash entries, and since
+%D we run large \TEX's, let do it!
+
+\def\startmessages #1 library: #2
+ {\definemessageconstant{#2}% handy for modules
+ \bgroup
+ \obeylines
+ \ifcsname\m!prefix!#2\endcsname\else\setgvalue{\m!prefix!#2}{#2}\fi
+ \doifinsetelse{#1}{\currentresponses,all}
+ {\def\next
+ {\def\currentmessagelibrary{#2}%
+ \futurelet\next\getinterfacemessage}}
+ {\long\def\next##1\stopmessages{\egroup}}%
+ \next}
+
+\def\findinterfacemessage#1#2%
+ {\edef#2{\getvalue{\??ms\currentmessagelibrary#1}}}
+
+\def\doaddinterfacemessage#1#2%
+ {\doifdefined{\??ms\currentmessagelibrary#1}
+ {\debuggerinfotrue % we consider this an important error
+ \debuggerinfo
+ {message}
+ {duplicate tag #1
+ in library \currentmessagelibrary\space
+ of interface \currentresponses}}%
+ \setxvalue{\??ms\currentmessagelibrary#1}{#2}%
+ \futurelet\next\getinterfacemessage}
+
+\def\setinterfacemessage#1#2#3%
+ {\ifcsname\m!prefix!#1\endcsname\else\setgvalue{\m!prefix!#1}{#1}\fi
+ \expandafter\def\csname\??ms#1#2\endcsname{#3}}
+
+%D \macros
+%D {ifshowwarnings, ifshowmessages}
+%D
+%D Sometimes displaying message can slow down processing
+%D considerably. We therefore introduce warnings. Users can
+%D turn of warnings and messages by saying:
+%D
+%D \starttyping
+%D \showwarningstrue
+%D \showmessagestrue
+%D \stoptyping
+%D
+%D Turning off messages also turns off warnings, which is
+%D quote logical because they are less important.
+
+% not yet mkiv
+
+\newif\ifshowwarnings \showwarningstrue
+\newif\ifshowmessages \showmessagestrue
+
+\let\normalshowmessage\showmessage
+
+\def\showwarning
+ {\ifshowwarnings
+ \expandafter\showmessage
+ \else
+ \expandafter\gobblethreearguments
+ \fi}
+
+\def\showmessage
+ {\ifshowmessages
+ \expandafter\normalshowmessage
+ \else
+ \expandafter\gobblethreearguments
+ \fi}
+
+%D \macros
+%D {dosetvalue,dosetevalue,dosetgvalue,dosetxvalue,docopyvalue,doresetvalue} % dogetvalue
+%D
+%D We already defined these auxiliary macros in the system
+%D modules. Starting with this module however, we have to take
+%D multi||linguality a bit more serious.
+
+\def\doresetvalue#1#2%
+ {\dosetvalue{#1}{#2}{}}
+
+\def\doignorevalue#1#2#3%
+ {\dosetvalue{#1}{#2}{}}
+
+\def\dosetvalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\dosetevalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\edef\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\edef\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\dosetgvalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\gdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\gdef\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\dosetxvalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\xdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\xdef\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\docopyvalue#1#2#3% real tricky expansion, quite unreadable
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#3\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1\csname\k!prefix!#3\endcsname
+ \@EA\endcsname\@EA{\csname#2\csname\k!prefix!#3\endcsname\endcsname}%
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}%
+ \fi}
+
+%D We can now redefine some messages that will be
+%D introduced in the multi||lingual system module.
+
+\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}\waitonfatalerror}
+\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}\waitonfatalerror}
+\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}\waitonfatalerror}
+
+%D \CONTEXT\ is a parameter driven package. This means that
+%D users instruct the system by means of variables, values and
+%D keywords. These instructions take the form:
+%D
+%D \starttyping
+%D \setupsomething[some variable=some value, another one=a keyword]
+%D \stoptyping
+%D
+%D or by keyword only:
+%D
+%D \starttyping
+%D \dosomething[this way,that way,no way]
+%D \stoptyping
+%D
+%D Because the same variables can occur in more than one setup
+%D command, we have to be able to distinguish them. This is
+%D achieved by assigning them a unique prefix.
+%D
+%D Imagine a setup command for boxed text, that enables us to
+%D specify the height and width of the box. Behide the scenes
+%D the command
+%D
+%D \starttyping
+%D \setupbox [width=12cm, height=3cm]
+%D \stoptyping
+%D
+%D results in something like
+%D
+%D \starttyping
+%D \ {12cm}
+%D \ {3cm}
+%D \stoptyping
+%D
+%D while a similar command for specifying the page dimensions
+%D of an \cap{A4} page results in:
+%D
+%D \starttyping
+%D \ {21.0cm}
+%D \ {27.9cm}
+%D \stoptyping
+%D
+%D The prefixes \type{} and \type{} are hidden from
+%D users and can therefore be language independant. Variables
+%D on the other hand, differ for each language:
+%D
+%D \starttyping
+%D \ {}
+%D \ {}
+%D \ {}
+%D \stoptyping
+%D
+%D In this example we can see that the assigned values or
+%D keywords are language dependant too. This will be a
+%D complication when defining multi||lingual setup files.
+%D
+%D A third phenomena is that variables and values can have a
+%D similar meaning.
+%D
+%D \starttyping
+%D \ {}
+%D \ {12cm}
+%D \stoptyping
+%D
+%D A (minor) complication is that where in english we use
+%D \type{}, in dutch we find both \type{} and
+%D \type{}. This means that when we use some sort of
+%D translation table, we have to distinguish between the
+%D variables at the left side and the fixed values at the
+%D right.
+%D
+%D The same goes for commands that are composed of different
+%D user supplied and/or language specific elements. In english
+%D we can use:
+%D
+%D \starttyping
+%D \
+%D \
+%D \stoptyping
+%D
+%D But in dutch we have the following:
+%D
+%D \starttyping
+%D \
+%D \
+%D \stoptyping
+%D
+%D These subtle differences automatically lead to a solution
+%D where variables, values, elements and other components have
+%D a similar logical name (used in macro's) but a different
+%D meaning (supplied by the user).
+%D
+%D Our solution is one in which the whole system is programmed
+%D in terms of identifiers with language specific meanings. In
+%D such an implementation, each fixed variable is available as:
+%D
+%D \starttyping
+%D \
+%D \stoptyping
+%D
+%D This means that for instance:
+%D
+%D \starttyping
+%D \setupbox[width=12cm]
+%D \stoptyping
+%D
+%D expands to something like:
+%D
+%D \starttyping
+%D \def\boxwidth{12cm}
+%D \stoptyping
+%D
+%D because we don't want to recode the source, a setup command
+%D in another language has to expand to this variable, so:
+%D
+%D \starttyping
+%D \setupblock[width=12cm]
+%D \stoptyping
+%D
+%D has to result in the definition of \type{\boxwidth} too.
+%D This method enables us to build compact, fast and readable
+%D code.
+%D
+%D An alternative method, which we considered using, uses a
+%D more indirect way. In this case, both calls generate a
+%D different variable:
+%D
+%D \starttyping
+%D \def\boxwidth {12cm}
+%D \def\boxbreedte {12cm}
+%D \stoptyping
+%D
+%D And because we don't want to recode those megabytes of
+%D already developed code, this variable has to be called with
+%D something like:
+%D
+%D \starttyping
+%D \valueof\box\width
+%D \stoptyping
+%D
+%D where \type{\valueof} takes care of the translation of
+%D \type{width} or \type{breedte} to \type{width} and
+%D combining this with \type{box} to \type{\boxwidth}.
+%D
+%D One advantage of this other scheme is that, within certain
+%D limits, we can implement an interface that can be switched
+%D to another language at will, while the current approach
+%D fixes the interface at startup. There are, by the way,
+%D other reasons too for not choosing this scheme. Switching
+%D user generated commands is for instance impossible and a
+%D dual interface would therefore give a strange mix of
+%D languages.
+%D
+%D Now let's work out the first scheme. Although the left hand
+%D of the assignment is a variable from the users point of
+%D view, it is a constant in terms of the system. Both
+%D \type{width} and \type{breedte} expand to \type{width}
+%D because in the source we only encounter \type{width}. Such
+%D system constants are presented as
+%D
+%D \starttyping
+%D \c!width
+%D \stoptyping
+%D
+%D This constant is always equivalent to \type{width}. As we
+%D can see, we use \type{c!} to mark this one as constant. Its
+%D dutch counterpart is:
+%D
+%D \starttyping
+%D breedte
+%D \stoptyping
+%D
+%D When we interpret a setup command each variable is
+%D translated to it's \type{c!} counterpart. This means that
+%D \type{breedte} and \type{width} expand to \type{breedte}
+%D and \type{\c!width} which both expand to \type{width}. That
+%D way user variables become system constants.
+%D
+%D The interpretation is done by means of a general setup
+%D command \type{\getparameters} that we introduced in the
+%D system module. Let us define some simple setup command:
+%D
+%D \starttyping
+%D \def\setupbox[#1]%
+%D {\getparameters[\??bx][#1]}
+%D \stoptyping
+%D
+%D This command can be used as:
+%D
+%D \starttyping
+%D \setupbox [width=3cm, height=1cm]
+%D \stoptyping
+%D
+%D Afterwards we have two variables \type{\@@bxwidth} and
+%D \type{\@@bxheight} which have the values \type{3cm} and
+%D \type{1cm} assigned. These variables are a combinatiom of
+%D the setup prefix \type{\??bx}, which expands to \type{@@bx}
+%D and the translated user supplied variables \type{width} and
+%D \type{height} or \type{breedte} and \type{hoogte},
+%D depending on the actual language. In dutch we just say:
+%D
+%D \starttyping
+%D \setupblock [width=3cm, height=1cm]
+%D \stoptyping
+%D
+%D and get ourselves \type{\@@bxwidth} and \type{\@@bxheight}
+%D too. In the source of \CONTEXT, we can recognize constants
+%D and variables on their leading \type{c!}, \type{v!} etc.,
+%D prefixes on \type{??} and composed variables on \type{@@}.
+%D
+%D We already saw that user supplied keywords need some
+%D special treatment too. This time we don't translate the
+%D keyword, but instead use in the source a variable which
+%D meaning depends on the interface language.
+%D
+%D \starttyping
+%D \v!left
+%D \stoptyping
+%D
+%D Which can be used in macro's like:
+%D
+%D \starttyping
+%D \processaction
+%D [\@@bxlocation]
+%D [ \v!left=>\dosomethingontheleft,
+%D \v!middle=>\dosomthinginthemiddle,
+%D \v!right=>\dosomethingontheright]
+%D \stoptyping
+%D
+%D Because variables like \type{\@@bxlocation} can have a lot
+%D of meanings, including tricky expandable tokens, we cannot
+%D translate this meaning when we compare. This means that
+%D \type{\@@bxlocation} can be \type{left} of \type{links} of
+%D whatever meaning suits the language. But because
+%D \type{\v!left} also has a meaning that suits the language,
+%D we are able to compare.
+%D
+%D Although we know it sounds confusing we want to state two
+%D important characteristics of the interface as described:
+%D
+%D \startnarrower \em
+%D user variables become system constants
+%D \stopnarrower
+%D
+%D and
+%D
+%D \startnarrower \em
+%D user constants (keywords) become system variables
+%D \stopnarrower
+%D
+
+%D Anno 2003 I've forgotten why the \type {\c!internal} is
+%D still in there; it's probably a left over from an experiment.
+
+\let\c!internal!y \string
+\def\c!internal!n {-}
+\let\c!internal! \c!internal!y
+
+\def\setinterfaceconstant#1#2%
+ {\setvalue{\c!prefix!#1}{\c!internal!#1}%
+ \setvalue{\k!prefix!#2}{#1}}
+
+\def\setinterfacevariable#1#2%
+ {\setvalue{\v!prefix!#1}{#2}}
+
+%D \macros
+%D {defineinterfaceconstant}
+%D
+%D Next we redefine a previously defined macro to take care of
+%D interface translation too. It's a bit redundant, because
+%D in these situations we could use the c||version, but for
+%D documentation purposes the x||alternative comes in handy.
+
+\def\defineinterfaceconstant#1#2%
+ {\setvalue{\c!prefix!#1}{#2}}
+
+%D \macros
+%D {startelements}
+%D
+%D Due to the object oriented nature of \CONTEXT, we also need
+%D to define the elements that are used to build commands.
+%D
+%D Such elements sometimes are the same in diferent
+%D languages, but mostly they differ. Things can get even
+%D confusing when we look at for instance the setup commands.
+%D In english we say \type{\setup}, but in dutch we
+%D have: \type{\stelin}. Such split elements are no
+%D problem, because we just define two elements. When no second
+%D part is needed, we use a \type{-}:
+
+\def\setinterfaceelement#1#2%
+ {\ifcsname\e!prefix!#1\endcsname
+ \doifnotvalue{\e!prefix!#1}{#2}{\setvalue{\e!prefix!#1}{#2}}%
+ \else
+ \setvalue{\e!prefix!#1}{#2}%
+ \fi}
+
+\def\setinterfacecommand#1#2%
+ {\doifnot{#1}{#2}{\@EA\def\csname#2\@EA\endcsname\@EA{\csname#1\endcsname}}}% or just \let ?
+
+%D We just ignore these:
+
+\def\startvariables{\gobbleuntil\stopvariables}
+\def\startconstants{\gobbleuntil\stopconstants}
+\def\startelements {\gobbleuntil\stopelements}
+\def\startcommands {\gobbleuntil\stopcommands}
+
+%D \macros
+%D {interfaced}
+%D
+%D The setup commands translate the constants automatically.
+%D When we want to translate 'by hand' we can use the simple
+%D but effective command:
+%D
+%D \starttyping
+%D \interfaced {something}
+%D \stoptyping
+%D
+%D Giving \type{\interfaced{breedte}} results in \type{width}
+%D or, when not defined, in \type{breedte} itself. This
+%D macro is used in the font switching mechanism.
+
+\def\interfaced#1%
+ {\ifcsname\k!prefix!#1\endcsname
+ \csname\k!prefix!#1\endcsname
+ \else
+ #1%
+ \fi}
+
+%D So much for the basic multi||lingual interface commands. The
+%D macro's can be enhanced with more testing facilities, but
+%D for the moment they suffice.
+
+%D Out of convenience we define the banners here.
+
+\def\contextbanner
+ {ConTeXt \space
+ ver: \contextversion \space \contextmark \space \space
+ fmt: \formatversion \space \space
+ int: \currentinterface/\currentresponses}
+
+\def\showcontextbanner
+ {\writeline\writebanner{\contextbanner}\writeline}
+
+\edef\formatversion
+ {\the\normalyear.\the\normalmonth.\the\normalday}
+
+\ifx\contextversion\undefined
+ \def\contextversion {unknown}
+ \def\contextversionnumber{0}
+\else
+ \def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3 #4:#5}
+ \edef\contextversionnumber{\expandafter\contextversionnumber\contextversion\relax\space\contextmark}
+\fi
+
+\ifx\undefined\everydump
+ \newtoks\everydump
+ \def\dump{\the\everydump\normaldump}
+\fi
+
+\appendtoks \showcontextbanner \to \everydump
+
+\protect \endinput
diff --git a/tex/context/base/mult-ini.mkiv b/tex/context/base/mult-ini.mkiv
new file mode 100644
index 000000000..e20548f9b
--- /dev/null
+++ b/tex/context/base/mult-ini.mkiv
@@ -0,0 +1,865 @@
+%D \module
+%D [ file=mult-ini,
+%D version=2008.10.22, % 1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 is a stripped down version of \type {mult-ini.tex},
+%D which we keep around as \type {mult-kep.tex} for sentimental
+%D reasons. There you will find some more historic information.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / Initialization}
+
+\unprotect
+
+\registerctxluafile{mult-ini}{1.001}
+
+%D \macros
+%D [constanten,variabelen,commands]
+%D {v!,c!,k!,s!,e!,m!,l!,r!,f!,p!,x!,y!}
+%D
+%D In the system modules we introduced some prefixed constants,
+%D variables (both macros) and registers. Apart from a
+%D tremendous saving in terms of memory and a gain in speed we
+%D use from now on prefixes when possible for just another
+%D reason: consistency and multi||linguality. Systematically
+%D using prefixed macros enables us to implement a
+%D multi||lingual user interface. Redefining these next set of
+%D prefixes therefore can have desastrous results.
+%D
+%D \startlinecorrection
+%D \starttable[|c|c|c|]
+%D \HL
+%D \NC \bf prefix \NC \bf meaning \NC \bf application \NC\SR
+%D \HL
+%D \NC \type{\c!prefix!} \NC c! \NC constant (direct) \NC\FR
+%D \NC \type{\e!prefix!} \NC e! \NC element \NC\MR
+%D \NC \type{\f!prefix!} \NC f! \NC file \NC\MR
+%D \NC \type{\k!prefix!} \NC k! \NC constant (indirect) \NC\MR
+%D \NC \type{\l!prefix!} \NC l! \NC language \NC\MR
+%D \NC \type{\m!prefix!} \NC m! \NC message \NC\MR
+%D \NC \type{\p!prefix!} \NC p! \NC procedure \NC\MR
+%D \NC \type{\r!prefix!} \NC r! \NC reference \NC\MR
+%D \NC \type{\s!prefix!} \NC s! \NC system \NC\MR
+%D \NC \type{\v!prefix!} \NC v! \NC variable \NC\MR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D In the single||lingual version we used \type{!}, \type{!!},
+%D \type{!!!} and \type{!!!!}.
+
+\def\c!prefix!{c!} \def\e!prefix!{e!} \def\f!prefix!{f!}
+\def\k!prefix!{k!} \def\l!prefix!{l!} \def\m!prefix!{m!}
+\def\p!prefix!{p!} \def\r!prefix!{r!} \def\s!prefix!{s!}
+\def\v!prefix!{v!} \def\t!prefix!{t!}
+
+%D \macros
+%D [constants,variables,commands]
+%D {@@,??}
+%D
+%D Variables generated by the system can be recognized on their
+%D prefix \type{@@}. They are composed of a command (class)
+%D specific tag, which can be recognized on \type{??}, and a
+%D system constant, which has the prefix \type{c!}. We'll se
+%D some more of this.
+
+\def\??prefix {??}
+\def\@@prefix {@@}
+
+%D Just to be complete we repeat some of the already defined
+%D system constants here. Maybe their prefix \type{\s!} now
+%D falls into place.
+
+\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!true {true}
+\def\s!false {false}
+
+%D The word \type{height} takes 6~token memory cells. The
+%D control sequence \type{\height} on the other hand uses only
+%D one. Knowing this, we can improve the performance of \TEX,
+%D both is terms of speed and memory usage, by using control
+%D sequences instead of the words written in full.
+%D
+%D Where in the \ASCII\ file the second lines takes nine extra
+%D characters, \TEX\ saves us 13~tokens.
+%D
+%D \starttyping
+%D \hrule width 10pt height 2pt depth 1pt
+%D \hrule \!!width 10pt \!!height 2pt \!!depth 1pt
+%D \stoptyping
+%D
+%D One condition is that we have defined \type{\!!height},
+%D \type{\!!width} and \type{\!!depth} as respectively
+%D \type{height}, \type{width} and \type{depth}. Using this
+%D scheme therefore only makes sense when a token sequence is
+%D used more than once. Savings like this should of course be
+%D implemented in english, just because \TEX\ is english.
+
+\def\!!width {width}
+\def\!!height{height}
+\def\!!depth {depth}
+\def\!!plus {plus}
+\def\!!minus {minus}
+\def\!!fill {fill}
+\def\!!to {to}
+\def\!!spread{spread}
+
+%D Kind of special:
+
+\edef\!!TLT{\detokenize{TLT}}
+\edef\!!TRT{\detokenize{TRT}}
+
+%D \macros
+%D {defineinterfaceconstant,
+%D defineinterfacevariable,
+%D defineinterfaceelement,
+%D definesystemvariable,
+%D definesystemconstant,
+%D definemessageconstant,
+%D definereferenceconstant,
+%D definefileconstant}
+%D
+%D The first part of this module is dedicated to dealing with
+%D multi||lingual constants and variables. When \CONTEXT\ grew
+%D bigger and bigger in terms of bytes and used string space,
+%D we switched to predefined constants. At the cost of more
+%D hash table entries, the macros not only becase more compact,
+%D they became much faster too. Maybe an even bigger advantage
+%D was that mispelling could no longer lead to problems. Even a
+%D multi||lingual interface became possible.
+%D
+%D Constants --- we'll introduce the concept of variables later
+%D on --- are preceded by a type specific prefix, followed by a
+%D \type{!}. To force consistency, we provide a few commands
+%D for defining such constants.
+%D
+%D \starttyping
+%D \defineinterfaceconstant {name} {meaning}
+%D \defineinterfacevariable {name} {meaning}
+%D \defineinterfaceelement {name} {meaning}
+%D \stoptyping
+%D
+%D Which is the same as:
+%D
+%D \starttyping
+%D \def\c!name{meaning}
+%D \def\v!name{meaning}
+%D \def\e!name{meaning}
+%D \stoptyping
+
+\unexpanded\def\defineinterfaceconstant #1#2{\setvalue{\c!prefix!#1}{#2}}
+\unexpanded\def\defineinterfacevariable #1#2{\setvalue{\v!prefix!#1}{#2}}
+\unexpanded\def\defineinterfaceelement #1#2{\setvalue{\e!prefix!#1}{#2}}
+
+%D Next come some interface independant constants:
+%D
+%D \starttyping
+%D \definereferenceconstant {name} {meaning}
+%D \definefileconstant {name} {meaning}
+%D \stoptyping
+
+\unexpanded\def\definereferenceconstant #1#2{\setvalue{\r!prefix!#1}{#2}}
+\unexpanded\def\definefileconstant #1#2{\setvalue{\f!prefix!#1}{#2}}
+
+%D A new one:
+
+\unexpanded\def\definetypescriptconstant#1#2{\setvalue{\t!prefix!#1}{#2}}
+
+%D And finaly we have the one argument, space saving constants
+%D
+%D \starttyping
+%D \definesystemconstant {name}
+%D \definemessageconstant {name}
+%D \stoptyping
+
+\unexpanded\def\definesystemconstant #1{\setvalue{\s!prefix!#1}{#1}}
+\unexpanded\def\definemessageconstant #1{\setvalue{\m!prefix!#1}{#1}}
+
+%D In a parameter driven system, some parameters are shared
+%D by more system components. In \CONTEXT\ we can distinguish
+%D parameters by a unique prefix. Such a prefix is defined
+%D with:
+%D
+%D \starttyping
+%D \definesystemvariable {name}
+%D \stoptyping
+
+\unexpanded\def\definesystemvariable#1{\setevalue{\??prefix#1}{\@@prefix#1}}
+
+\definesystemvariable{ms}
+
+%D \macros
+%D {selectinterface,
+%D defaultinterface, currentinterface, currentresponses}
+%D
+%D With \type{\selectinterface} we specify the language we are
+%D going to use. The system asks for the language wanted, and
+%D defaults to \type{\currentinterface} when we just give
+%D \type{enter}. By default the message system uses the
+%D current interface language, but \type{\currentresponses}
+%D can specify another language too.
+%D
+%D Because we want to generate formats directly too, we do
+%D not ask for interface specifications when these are already
+%D defined (like in cont-nl.tex and alike).
+
+\ifx\defaultinterface\undefined
+
+ \def\defaultinterface{english}
+
+ \def\selectinterface
+ {\def\docommand##1##2%
+ {\bgroup
+ \endlinechar\minusone
+ \global\read16 to ##1
+ \egroup
+ \doifnothing\currentinterface{\let##1=##2}%
+ \doifundefined{\s!prefix!##1}{\let##1=##2}}%
+ \docommand\currentinterface\defaultinterface
+ \writestatus{interface}{defining \currentinterface\space interface}%
+ \writeline
+ \docommand\currentresponses\currentinterface
+ \writestatus{interface}{using \currentresponses\space messages}%
+ \writeline
+ \let\selectinterface\relax}
+
+\else
+
+ \def\selectinterface
+ {\writestatus{interface}{defining \currentinterface\space interface}%
+ \writeline
+ \writestatus{interface}{using \currentresponses\space messages}%
+ \writeline
+ \let\selectinterface\relax}
+
+\fi
+
+\ifx\currentinterface\undefined \let\currentinterface\defaultinterface \fi
+\ifx\currentresponses\undefined \let\currentresponses\defaultinterface \fi
+
+%D \macros
+%D {startinterface}
+%D
+%D Sometimes we want to define things only for specific
+%D interface languages. This can be done by means of the
+%D selector:
+%D
+%D \starttyping
+%D \startinterface language
+%D
+%D language specific definitions & commands
+%D
+%D \stopinterface
+%D \stoptyping
+
+\unexpanded\def\startinterface #1
+ {\doifnot{#1}{all}{\doifnotinset\currentinterface{#1}{\gobbleuntil\stopinterface}}}
+
+\let\stopinterface\relax
+
+%D \macros
+%D {startmessages,
+%D getmessage,
+%D showmessage,
+%D makemessage}
+%D
+%D A package as large as \CONTEXT\ can hardly function without
+%D a decent message mechanism. Due to its multi||lingual
+%D interface, the message subsystem has to be multi||lingual
+%D too. A major drawback of this feature is that we have to
+%D code messages. As a result, the source becomes less self
+%D documented. On the other hand, consistency will improve.
+%D
+%D Because the overhead in terms of entries in the (already
+%D exhausted) hash table has to be minimal, messages are packed
+%D in libraries. We can extract a message from such a library
+%D in three ways:
+%D
+%D \starttyping
+%D \getmessage {library} {tag}
+%D \showmessage {library} {tag} {data}
+%D \makemessage {library} {tag} {data}
+%D \stoptyping
+%D
+%D The first command gets the message \type{tag} from the
+%D \type{library} specified. The other commands take an extra
+%D argument: a list of items to be inserted in the message
+%D text. While \type{\showmessage} shows the message at the
+%D terminal, the other commands generate the message as text.
+%D Before we explain the \type{data} argument, we give an
+%D example of a library.
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D title: something
+%D 1: first message
+%D 2: second (--) message --
+%D \stopmessages
+%D \stoptyping
+%D
+%D The first message is a simple one and can be shown with:
+%D
+%D \starttyping
+%D \showmessage {alfa} {1} {}
+%D \stoptyping
+%D
+%D The second message on the other hand needs some extra data:
+%D
+%D \starttyping
+%D \showmessage {alfa} {2} {and last,to you}
+%D \stoptyping
+%D
+%D This message is shown as:
+%D
+%D \starttyping
+%D something : second (and last) message to you
+%D \stoptyping
+%D
+%D As we can see, the title entry is shown with the message.
+%D The data fields are comma separated and are specified in the
+%D message text by \type{--}.
+%D
+%D It is not required to define all messages in a library at
+%D once. We can add messages to a library in the following way:
+%D
+%D \starttyping
+%D \startmessages english library: alfa
+%D 10: tenth message
+%D \stopmessages
+%D \stoptyping
+%D
+%D Because such definitions can take place in different
+%D modules, the system gives a warning when a tag occurs more
+%D than once. The first occurrence takes preference over later
+%D ones, so we had better use a save offset, as shown in the
+%D example. As we can see, the title field is specified only
+%D the first time!
+%D
+%D Because we want to check for duplicate tags, the macros
+%D are a bit more complicated than neccessary. The \NEWLINE\
+%D token is used as message separator.
+%D
+%D For internal purposes one can use \type {\setmessagetext},
+%D which puts the message text asked for in \type
+%D {\currentmessagetext}.
+
+\unexpanded\def\startmessages #1 library: #2 %
+ {\bgroup
+ \ifcsname\m!prefix!#2\endcsname\else\setgvalue{\m!prefix!#2}{#2}\fi
+ \catcode13=\active
+ \doifinsetelse{#1}{\currentresponses,all}\dostartmessages\nostartmessages{#2}}
+
+\def\dostartmessages#1#2\stopmessages
+ {\ctxlua{interfaces.setmessages("#1",\!!bs#2\!!es)}%
+ \egroup}
+
+\def\nostartmessages#1#2\stopmessages
+ {\egroup}
+
+\def\setinterfacemessage#1#2#3%
+ {\ifcsname\m!prefix!#1\endcsname\else\setgvalue{\m!prefix!#1}{#1}\fi
+ \ctxlua{interfaces.setmessage("#1","#2",\!!bs#3\!!es)}}
+
+\unexpanded\def\setmessagetext #1#2{\edef\currentmessagetext{\ctxlua{tex.sprint(tex.ctxcatcodes,interfaces.getmessage("#1","#2"))}}}
+\unexpanded\def\doifelsemessage #1#2{\ctxlua{interfaces.doifelsemessage("#1","#2")}}
+\unexpanded\def\getmessage #1#2{\ctxlua{tex.sprint(tex.ctxcatcodes,interfaces.getmessage("#1","#2"))}}
+\unexpanded\def\getmessagedefault#1#2#3{\ctxlua{tex.sprint(tex.ctxcatcodes,interfaces.getmessage("#1","#2","#3"))}}
+\unexpanded\def\makemessage #1#2#3{\ctxlua{tex.sprint(tex.ctxcatcodes,interfaces.makemessage("#1","#2","#3"))}}
+\unexpanded\def\showmessage #1#2#3{\ctxlua{interfaces.showmessage("#1","#2","#3")}}
+
+%D \macros
+%D {ifshowwarnings, ifshowmessages}
+%D
+%D Sometimes displaying message can slow down processing
+%D considerably. We therefore introduce warnings. Users can
+%D turn of warnings and messages by saying:
+%D
+%D \starttyping
+%D \showwarningstrue
+%D \showmessagestrue
+%D \stoptyping
+%D
+%D Turning off messages also turns off warnings, which is
+%D quote logical because they are less important.
+
+% not yet mkiv
+
+\newif\ifshowwarnings \showwarningstrue
+\newif\ifshowmessages \showmessagestrue
+
+\let\normalshowmessage\showmessage
+
+\def\showwarning
+ {\ifshowwarnings
+ \expandafter\showmessage
+ \else
+ \expandafter\gobblethreearguments
+ \fi}
+
+\def\showmessage
+ {\ifshowmessages
+ \expandafter\normalshowmessage
+ \else
+ \expandafter\gobblethreearguments
+ \fi}
+
+%D \macros
+%D {dosetvalue,dosetevalue,dosetgvalue,dosetxvalue,docopyvalue,doresetvalue} % dogetvalue
+%D
+%D We already defined these auxiliary macros in the system
+%D modules. Starting with this module however, we have to take
+%D multi||linguality a bit more serious.
+%D
+%D The additional \type {\c!internal!n} prefixing is no longer
+%D needed as we now have separate interface files when dealing
+%D with setups (quick ref docs) and no longer reload the whole
+%D interface. (We no longer need the link back to the main
+%D internal interface.)
+
+\def\doresetvalue#1#2%
+ {\dosetvalue{#1}{#2}{}}
+
+\def\doignorevalue#1#2#3%
+ {\dosetvalue{#1}{#2}{}}
+
+\def\dosetvalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\dosetevalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\edef\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\edef\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\dosetgvalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\gdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\gdef\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\dosetxvalue#1#2%
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#2\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\xdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\xdef\csname#1#2%\endcsname
+ \fi\endcsname}
+
+\def\docopyvalue#1#2#3% real tricky expansion, quite unreadable
+ {\let\c!internal!\c!internal!n
+ \ifcsname\k!prefix!#3\endcsname
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1\csname\k!prefix!#3\endcsname
+ \@EA\endcsname\@EA{\csname#2\csname\k!prefix!#3\endcsname\endcsname}%
+ \else
+ \let\c!internal!\c!internal!y
+ \@EA\def\csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}%
+ \fi}
+
+%D We can now redefine some messages that will be
+%D introduced in the multi||lingual system module.
+
+\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}\waitonfatalerror}
+\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}\waitonfatalerror}
+\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}\waitonfatalerror}
+
+%D \CONTEXT\ is a parameter driven package. This means that
+%D users instruct the system by means of variables, values and
+%D keywords. These instructions take the form:
+%D
+%D \starttyping
+%D \setupsomething[some variable=some value, another one=a keyword]
+%D \stoptyping
+%D
+%D or by keyword only:
+%D
+%D \starttyping
+%D \dosomething[this way,that way,no way]
+%D \stoptyping
+%D
+%D Because the same variables can occur in more than one setup
+%D command, we have to be able to distinguish them. This is
+%D achieved by assigning them a unique prefix.
+%D
+%D Imagine a setup command for boxed text, that enables us to
+%D specify the height and width of the box. Behide the scenes
+%D the command
+%D
+%D \starttyping
+%D \setupbox [width=12cm, height=3cm]
+%D \stoptyping
+%D
+%D results in something like
+%D
+%D \starttyping
+%D \ {12cm}
+%D \ {3cm}
+%D \stoptyping
+%D
+%D while a similar command for specifying the page dimensions
+%D of an \cap{A4} page results in:
+%D
+%D \starttyping
+%D \ {21.0cm}
+%D \ {27.9cm}
+%D \stoptyping
+%D
+%D The prefixes \type{} and \type{} are hidden from
+%D users and can therefore be language independant. Variables
+%D on the other hand, differ for each language:
+%D
+%D \starttyping
+%D \ {}
+%D \ {}
+%D \ {}
+%D \stoptyping
+%D
+%D In this example we can see that the assigned values or
+%D keywords are language dependant too. This will be a
+%D complication when defining multi||lingual setup files.
+%D
+%D A third phenomena is that variables and values can have a
+%D similar meaning.
+%D
+%D \starttyping
+%D \ {}
+%D \ {12cm}
+%D \stoptyping
+%D
+%D A (minor) complication is that where in english we use
+%D \type{}, in dutch we find both \type{} and
+%D \type{}. This means that when we use some sort of
+%D translation table, we have to distinguish between the
+%D variables at the left side and the fixed values at the
+%D right.
+%D
+%D The same goes for commands that are composed of different
+%D user supplied and/or language specific elements. In english
+%D we can use:
+%D
+%D \starttyping
+%D \
+%D \
+%D \stoptyping
+%D
+%D But in dutch we have the following:
+%D
+%D \starttyping
+%D \
+%D \
+%D \stoptyping
+%D
+%D These subtle differences automatically lead to a solution
+%D where variables, values, elements and other components have
+%D a similar logical name (used in macro's) but a different
+%D meaning (supplied by the user).
+%D
+%D Our solution is one in which the whole system is programmed
+%D in terms of identifiers with language specific meanings. In
+%D such an implementation, each fixed variable is available as:
+%D
+%D \starttyping
+%D \
+%D \stoptyping
+%D
+%D This means that for instance:
+%D
+%D \starttyping
+%D \setupbox[width=12cm]
+%D \stoptyping
+%D
+%D expands to something like:
+%D
+%D \starttyping
+%D \def\boxwidth{12cm}
+%D \stoptyping
+%D
+%D because we don't want to recode the source, a setup command
+%D in another language has to expand to this variable, so:
+%D
+%D \starttyping
+%D \setupblock[width=12cm]
+%D \stoptyping
+%D
+%D has to result in the definition of \type{\boxwidth} too.
+%D This method enables us to build compact, fast and readable
+%D code.
+%D
+%D An alternative method, which we considered using, uses a
+%D more indirect way. In this case, both calls generate a
+%D different variable:
+%D
+%D \starttyping
+%D \def\boxwidth {12cm}
+%D \def\boxbreedte {12cm}
+%D \stoptyping
+%D
+%D And because we don't want to recode those megabytes of
+%D already developed code, this variable has to be called with
+%D something like:
+%D
+%D \starttyping
+%D \valueof\box\width
+%D \stoptyping
+%D
+%D where \type{\valueof} takes care of the translation of
+%D \type{width} or \type{breedte} to \type{width} and
+%D combining this with \type{box} to \type{\boxwidth}.
+%D
+%D One advantage of this other scheme is that, within certain
+%D limits, we can implement an interface that can be switched
+%D to another language at will, while the current approach
+%D fixes the interface at startup. There are, by the way,
+%D other reasons too for not choosing this scheme. Switching
+%D user generated commands is for instance impossible and a
+%D dual interface would therefore give a strange mix of
+%D languages.
+%D
+%D Now let's work out the first scheme. Although the left hand
+%D of the assignment is a variable from the users point of
+%D view, it is a constant in terms of the system. Both
+%D \type{width} and \type{breedte} expand to \type{width}
+%D because in the source we only encounter \type{width}. Such
+%D system constants are presented as
+%D
+%D \starttyping
+%D \c!width
+%D \stoptyping
+%D
+%D This constant is always equivalent to \type{width}. As we
+%D can see, we use \type{c!} to mark this one as constant. Its
+%D dutch counterpart is:
+%D
+%D \starttyping
+%D breedte
+%D \stoptyping
+%D
+%D When we interpret a setup command each variable is
+%D translated to it's \type{c!} counterpart. This means that
+%D \type{breedte} and \type{width} expand to \type{breedte}
+%D and \type{\c!width} which both expand to \type{width}. That
+%D way user variables become system constants.
+%D
+%D The interpretation is done by means of a general setup
+%D command \type{\getparameters} that we introduced in the
+%D system module. Let us define some simple setup command:
+%D
+%D \starttyping
+%D \unexpanded\def\setupbox[#1]%
+%D {\getparameters[\??bx][#1]}
+%D \stoptyping
+%D
+%D This command can be used as:
+%D
+%D \starttyping
+%D \setupbox [width=3cm, height=1cm]
+%D \stoptyping
+%D
+%D Afterwards we have two variables \type{\@@bxwidth} and
+%D \type{\@@bxheight} which have the values \type{3cm} and
+%D \type{1cm} assigned. These variables are a combinatiom of
+%D the setup prefix \type{\??bx}, which expands to \type{@@bx}
+%D and the translated user supplied variables \type{width} and
+%D \type{height} or \type{breedte} and \type{hoogte},
+%D depending on the actual language. In dutch we just say:
+%D
+%D \starttyping
+%D \stelblokin [breedte=3cm,hoogte=1cm]
+%D \stoptyping
+%D
+%D and get ourselves \type{\@@bxwidth} and \type{\@@bxheight}
+%D too. In the source of \CONTEXT, we can recognize constants
+%D and variables on their leading \type{c!}, \type{v!} etc.,
+%D prefixes on \type{??} and composed variables on \type{@@}.
+%D
+%D We already saw that user supplied keywords need some
+%D special treatment too. This time we don't translate the
+%D keyword, but instead use in the source a variable which
+%D meaning depends on the interface language.
+%D
+%D \starttyping
+%D \v!left
+%D \stoptyping
+%D
+%D Which can be used in macro's like:
+%D
+%D \starttyping
+%D \processaction
+%D [\@@bxlocation]
+%D [ \v!left=>\dosomethingontheleft,
+%D \v!middle=>\dosomthinginthemiddle,
+%D \v!right=>\dosomethingontheright]
+%D \stoptyping
+%D
+%D Because variables like \type{\@@bxlocation} can have a lot
+%D of meanings, including tricky expandable tokens, we cannot
+%D translate this meaning when we compare. This means that
+%D \type{\@@bxlocation} can be \type{left} of \type{links} of
+%D whatever meaning suits the language. But because
+%D \type{\v!left} also has a meaning that suits the language,
+%D we are able to compare.
+%D
+%D Although we know it sounds confusing we want to state two
+%D important characteristics of the interface as described:
+%D
+%D \startnarrower \em
+%D user variables become system constants
+%D \stopnarrower
+%D
+%D and
+%D
+%D \startnarrower \em
+%D user constants (keywords) become system variables
+%D \stopnarrower
+
+%D Anno 2003 I've forgotten why the \type {\c!internal} is
+%D still in there; it's probably a left over from the time that
+%D the user interface documents were not using a specification
+%D alongside a keyword specification but used a shared file in
+%D which case we need to go in both directions.
+
+\let\c!internal!y \string
+\def\c!internal!n {-}
+\let\c!internal! \c!internal!y
+
+% temporary mkiv hack (we can best just store the whole table in memory)
+
+\def\setinterfaceconstant#1#2%
+ {\ctxlua{interfaces.setconstant("#1","#2")}%
+ \setvalue{\c!prefix!#1}{\c!internal!#1}%
+ \setvalue{\k!prefix!#2}{#1}}
+
+\def\setinterfacevariable#1#2%
+ {\ctxlua{interfaces.setvariable("#1","#2")}%
+ \setvalue{\v!prefix!#1}{#2}}
+
+%D \macros
+%D {defineinterfaceconstant}
+%D
+%D Next we redefine a previously defined macro to take care of
+%D interface translation too. It's a bit redundant, because
+%D in these situations we could use the c||version, but for
+%D documentation purposes the x||alternative comes in handy.
+
+\unexpanded\def\defineinterfaceconstant#1#2%
+ {\setvalue{\c!prefix!#1}{#2}}
+
+%D \macros
+%D {startelements}
+%D
+%D Due to the object oriented nature of \CONTEXT, we also need
+%D to define the elements that are used to build commands.
+%D
+%D Such elements sometimes are the same in diferent
+%D languages, but mostly they differ. Things can get even
+%D confusing when we look at for instance the setup commands.
+%D In english we say \type{\setup}, but in dutch we
+%D have: \type{\stelin}. Such split elements are no
+%D problem, because we just define two elements. When no second
+%D part is needed, we use a \type{-}:
+
+\def\setinterfaceelement#1#2%
+ {\ifcsname\e!prefix!#1\endcsname
+ \doifnotvalue{\e!prefix!#1}{#2}{\setvalue{\e!prefix!#1}{#2}}%
+ \else
+ \setvalue{\e!prefix!#1}{#2}%
+ \fi}
+
+\def\setinterfacecommand#1#2%
+ {\doifnot{#1}{#2}{\@EA\def\csname#2\@EA\endcsname\@EA{\csname#1\endcsname}}}% or just \let ?
+
+%D We just ignore these:
+
+\unexpanded\def\startvariables{\gobbleuntil\stopvariables}
+\unexpanded\def\startconstants{\gobbleuntil\stopconstants}
+\unexpanded\def\startelements {\gobbleuntil\stopelements}
+\unexpanded\def\startcommands {\gobbleuntil\stopcommands}
+
+%D \macros
+%D {interfaced}
+%D
+%D The setup commands translate the constants automatically.
+%D When we want to translate 'by hand' we can use the simple
+%D but effective command:
+%D
+%D \starttyping
+%D \interfaced {something}
+%D \stoptyping
+%D
+%D Giving \type{\interfaced{breedte}} results in \type{width}
+%D or, when not defined, in \type{breedte} itself. This
+%D macro is used in the font switching mechanism.
+
+\def\interfaced#1%
+ {\ifcsname\k!prefix!#1\endcsname
+ \csname\k!prefix!#1\endcsname
+ \else
+ #1%
+ \fi}
+
+%D So much for the basic multi||lingual interface commands. The
+%D macro's can be enhanced with more testing facilities, but
+%D for the moment they suffice.
+
+%D Out of convenience we define the banners here.
+
+\def\contextbanner
+ {ConTeXt \space
+ ver: \contextversion \space \contextmark \space \space
+ fmt: \formatversion \space \space
+ int: \currentinterface/\currentresponses}
+
+\def\showcontextbanner
+ {\writeline\writebanner{\contextbanner}\writeline}
+
+\edef\formatversion
+ {\the\normalyear .\the\normalmonth.\the\normalday}
+
+\ifx\contextversion\undefined
+ \def\contextversion {unknown}
+ \def\contextversionnumber{0}
+\else
+ \def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3 #4:#5}
+ \edef\contextversionnumber{\expandafter\contextversionnumber\contextversion\relax\space\contextmark}
+\fi
+
+\ifx\undefined\everydump
+ \newtoks\everydump
+ \def\dump{\the\everydump\normaldump}
+\fi
+
+\appendtoks \showcontextbanner \to \everydump
+
+\protect \endinput
diff --git a/tex/context/base/mult-it.tex b/tex/context/base/mult-it.tex
new file mode 100644
index 000000000..ce14800de
--- /dev/null
+++ b/tex/context/base/mult-it.tex
@@ -0,0 +1,1693 @@
+% this file is auto-generated, don't edit this file
+%
+% definitions for interface variables for language it
+%
+\setinterfacevariable{Addition}{Aggiunta}
+\setinterfacevariable{Balloon}{Pallone}
+\setinterfacevariable{Character}{Lettera}
+\setinterfacevariable{Characters}{Lettere}
+\setinterfacevariable{CloseDocument}{ChiudiDocumento}
+\setinterfacevariable{ExitViewer}{EsciVisualizzatore}
+\setinterfacevariable{FirstPage}{PrimaPagina}
+\setinterfacevariable{FitHeight}{FitHeight}
+\setinterfacevariable{FitWidth}{FitWidth}
+\setinterfacevariable{GotoPage}{VaiAPagina}
+\setinterfacevariable{Greek}{Greco}
+\setinterfacevariable{Help}{Aiuto}
+\setinterfacevariable{HideField}{NascondiCampo}
+\setinterfacevariable{HideLayer}{HideLayer}
+\setinterfacevariable{Key}{Tasto}
+\setinterfacevariable{LastPage}{UltimaPagina}
+\setinterfacevariable{LoadForm}{CaricaForm}
+\setinterfacevariable{MONTH}{MESE}
+\setinterfacevariable{New}{Nuovo}
+\setinterfacevariable{NextJump}{SaltoSuccessivo}
+\setinterfacevariable{NextPage}{PaginaSuccessiva}
+\setinterfacevariable{Numbers}{Numeri}
+\setinterfacevariable{OpenNamedDocument}{OpenNamedDocument}
+\setinterfacevariable{Paragraph}{Capoverso}
+\setinterfacevariable{PauseMovie}{PausaFilm}
+\setinterfacevariable{PauseRendering}{PauseRendering}
+\setinterfacevariable{PauseSound}{PausaSuono}
+\setinterfacevariable{PreviousJump}{SaltoPrecedente}
+\setinterfacevariable{PreviousPage}{PaginaPrecedente}
+\setinterfacevariable{PrintDocument}{StampaDocumento}
+\setinterfacevariable{Query}{Richiesta}
+\setinterfacevariable{QueryAgain}{RinnovaRichiesta}
+\setinterfacevariable{ResetForm}{ReimpostaForm}
+\setinterfacevariable{ResumeMovie}{RiprendiFilm}
+\setinterfacevariable{ResumeRendering}{ResumeRendering}
+\setinterfacevariable{ResumeSound}{RiprendiSuono}
+\setinterfacevariable{Romannumerals}{Numeriromani}
+\setinterfacevariable{SaveDocument}{SalvaDocumento}
+\setinterfacevariable{SaveForm}{SalvaForm}
+\setinterfacevariable{SaveNamedDocument}{SaveNamedDocument}
+\setinterfacevariable{SearchAgain}{CercaAncora}
+\setinterfacevariable{SearchDocument}{CercaDocumento}
+\setinterfacevariable{ShowBookmarks}{MostraSegnalibro}
+\setinterfacevariable{ShowField}{MostraCampo}
+\setinterfacevariable{ShowThumbs}{MostraThumbs}
+\setinterfacevariable{StartMovie}{IniziaFilm}
+\setinterfacevariable{StartRendering}{StartRendering}
+\setinterfacevariable{StartSound}{IniziaSuono}
+\setinterfacevariable{StopMovie}{FermaFilm}
+\setinterfacevariable{StopRendering}{StopRendering}
+\setinterfacevariable{StopSound}{FermaSuono}
+\setinterfacevariable{SubmitForm}{MandaForm}
+\setinterfacevariable{ToggleLayer}{ToggleLayer}
+\setinterfacevariable{ToggleViewer}{ScambiaVisualizzatore}
+\setinterfacevariable{URL}{URL}
+\setinterfacevariable{VideLayer}{VideLayer}
+\setinterfacevariable{ViewerHelp}{AiutoVisualizzatore}
+\setinterfacevariable{WEEKDAY}{GIORNOSETTIMANA}
+\setinterfacevariable{WORD}{PAROLA}
+\setinterfacevariable{abbreviation}{abbreviazione}
+\setinterfacevariable{abbreviations}{abbreviazioni}
+\setinterfacevariable{absolute}{assoluto}
+\setinterfacevariable{action}{azione}
+\setinterfacevariable{after}{dopo}
+\setinterfacevariable{all}{tutti}
+\setinterfacevariable{always}{sempre}
+\setinterfacevariable{answerarea}{answerarea}
+\setinterfacevariable{appendices}{appendici}
+\setinterfacevariable{appendix}{appendice}
+\setinterfacevariable{april}{aprile}
+\setinterfacevariable{atmargin}{almargine}
+\setinterfacevariable{atpage}{apagina}
+\setinterfacevariable{august}{agosto}
+\setinterfacevariable{author}{autore}
+\setinterfacevariable{auto}{auto}
+\setinterfacevariable{autointro}{autointro}
+\setinterfacevariable{back}{dietro}
+\setinterfacevariable{background}{sfondo}
+\setinterfacevariable{backmatter}{postambolo}
+\setinterfacevariable{backpart}{postfazione}
+\setinterfacevariable{backspace}{backspace}
+\setinterfacevariable{backward}{indietro}
+\setinterfacevariable{bbl}{bbl}
+\setinterfacevariable{before}{prima}
+\setinterfacevariable{begin}{begin}
+\setinterfacevariable{bib}{bib}
+\setinterfacevariable{big}{grande}
+\setinterfacevariable{bigbodyfont}{grossofontdeltesto}
+\setinterfacevariable{bigpreference}{grandepreferenza}
+\setinterfacevariable{blank}{rigovuoto}
+\setinterfacevariable{blockquote}{blockquote}
+\setinterfacevariable{bodymatter}{testiprincipali}
+\setinterfacevariable{bodypart}{testoprincipale}
+\setinterfacevariable{bold}{grassetto}
+\setinterfacevariable{bolditalic}{grassettocorsivo}
+\setinterfacevariable{boldslanted}{grassettoinclinato}
+\setinterfacevariable{bookmark}{segnalibro}
+\setinterfacevariable{both}{entrambi}
+\setinterfacevariable{bottom}{fondo}
+\setinterfacevariable{brief}{brief}
+\setinterfacevariable{broad}{ampio}
+\setinterfacevariable{buffer}{buffer}
+\setinterfacevariable{by}{da}
+\setinterfacevariable{calligraphic}{calligrafico}
+\setinterfacevariable{cap}{cap}
+\setinterfacevariable{capital}{maiuscolo}
+\setinterfacevariable{center}{center}
+\setinterfacevariable{chapter}{capitolo}
+\setinterfacevariable{character}{lettera}
+\setinterfacevariable{characters}{lettere}
+\setinterfacevariable{cite}{cite}
+\setinterfacevariable{color}{colore}
+\setinterfacevariable{column}{colonna}
+\setinterfacevariable{columns}{colonne}
+\setinterfacevariable{command}{comando}
+\setinterfacevariable{commands}{comandi}
+\setinterfacevariable{comment}{commento}
+\setinterfacevariable{component}{componente}
+\setinterfacevariable{concept}{concetto}
+\setinterfacevariable{content}{indice}
+\setinterfacevariable{contents}{indici}
+\setinterfacevariable{continue}{continua}
+\setinterfacevariable{controls}{controlli}
+\setinterfacevariable{conversion}{coversione}
+\setinterfacevariable{current}{corrente}
+\setinterfacevariable{cutspace}{cutspace}
+\setinterfacevariable{date}{data}
+\setinterfacevariable{day}{giorno}
+\setinterfacevariable{december}{dicembre}
+\setinterfacevariable{default}{implicito}
+\setinterfacevariable{depth}{profondita}
+\setinterfacevariable{description}{descrizione}
+\setinterfacevariable{disable}{disattiva}
+\setinterfacevariable{display}{schermo}
+\setinterfacevariable{dot}{punto}
+\setinterfacevariable{doublesided}{doppiafaccia}
+\setinterfacevariable{down}{down}
+\setinterfacevariable{each}{ogni}
+\setinterfacevariable{edge}{bordo}
+\setinterfacevariable{empty}{vuoto}
+\setinterfacevariable{end}{end}
+\setinterfacevariable{endnote}{endnote}
+\setinterfacevariable{enumeration}{enumerazione}
+\setinterfacevariable{environment}{ambiente}
+\setinterfacevariable{even}{pari}
+\setinterfacevariable{external}{esterno}
+\setinterfacevariable{fact}{fatto}
+\setinterfacevariable{february}{febbraio}
+\setinterfacevariable{figure}{figura}
+\setinterfacevariable{figures}{figure}
+\setinterfacevariable{file}{file}
+\setinterfacevariable{final}{finale}
+\setinterfacevariable{first}{primo}
+\setinterfacevariable{firstcolumn}{firstcolumn}
+\setinterfacevariable{firstpage}{primapagina}
+\setinterfacevariable{firstsubpage}{primasottopagina}
+\setinterfacevariable{fit}{adatta}
+\setinterfacevariable{five}{cinque}
+\setinterfacevariable{fix}{fisso}
+\setinterfacevariable{fixed}{fisso}
+\setinterfacevariable{flexible}{flessibile}
+\setinterfacevariable{float}{oggettomobile}
+\setinterfacevariable{flushinner}{flushinner}
+\setinterfacevariable{flushleft}{flushleft}
+\setinterfacevariable{flushouter}{flushouter}
+\setinterfacevariable{flushright}{flushright}
+\setinterfacevariable{footer}{piedipagina}
+\setinterfacevariable{footnote}{notapdp}
+\setinterfacevariable{force}{forza}
+\setinterfacevariable{foreground}{foreground}
+\setinterfacevariable{formeel}{formeel}
+\setinterfacevariable{formula}{formula}
+\setinterfacevariable{formulae}{formule}
+\setinterfacevariable{forward}{avanti}
+\setinterfacevariable{four}{quattro}
+\setinterfacevariable{frame}{cornice}
+\setinterfacevariable{framedtext}{testoincorniciato}
+\setinterfacevariable{friday}{venerdi}
+\setinterfacevariable{frontmatter}{preambolo}
+\setinterfacevariable{frontpart}{prefazione}
+\setinterfacevariable{global}{globale}
+\setinterfacevariable{graphic}{grafico}
+\setinterfacevariable{graphics}{grafici}
+\setinterfacevariable{gray}{grigio}
+\setinterfacevariable{greek}{greco}
+\setinterfacevariable{grid}{griglia}
+\setinterfacevariable{halfline}{mezzariga}
+\setinterfacevariable{handwritten}{grafiamanuale}
+\setinterfacevariable{hang}{sospendi}
+\setinterfacevariable{hanging}{sospeso}
+\setinterfacevariable{head}{testa}
+\setinterfacevariable{header}{intestazione}
+\setinterfacevariable{height}{altezza}
+\setinterfacevariable{helptext}{testoaiuto}
+\setinterfacevariable{hencefore}{precedente}
+\setinterfacevariable{here}{qui}
+\setinterfacevariable{hereafter}{seguente}
+\setinterfacevariable{hidden}{nascosto}
+\setinterfacevariable{hiding}{nascondere}
+\setinterfacevariable{high}{alto}
+\setinterfacevariable{horizontal}{orizzontale}
+\setinterfacevariable{hyphenated}{sillabato}
+\setinterfacevariable{hz}{hz}
+\setinterfacevariable{inbetween}{tra}
+\setinterfacevariable{index}{indiceanalitico}
+\setinterfacevariable{indices}{indicianalitici}
+\setinterfacevariable{informeel}{informeel}
+\setinterfacevariable{inherit}{inherit}
+\setinterfacevariable{inleft}{insinistra}
+\setinterfacevariable{inmargin}{inmargine}
+\setinterfacevariable{inner}{interno}
+\setinterfacevariable{inneredge}{bordointerno}
+\setinterfacevariable{innermargin}{margineinterno}
+\setinterfacevariable{inright}{indestra}
+\setinterfacevariable{interaction}{interazione}
+\setinterfacevariable{interactionmenu}{menuinterattivo}
+\setinterfacevariable{intermezzi}{intermezzi}
+\setinterfacevariable{intermezzo}{intermezzo}
+\setinterfacevariable{intext}{intesto}
+\setinterfacevariable{intro}{intro}
+\setinterfacevariable{italic}{corsivo}
+\setinterfacevariable{italicbold}{corsivograssetto}
+\setinterfacevariable{item}{elemento}
+\setinterfacevariable{itemize}{elenco}
+\setinterfacevariable{its}{its}
+\setinterfacevariable{january}{gennaio}
+\setinterfacevariable{joinedup}{unito}
+\setinterfacevariable{july}{luglio}
+\setinterfacevariable{june}{giugno}
+\setinterfacevariable{keep}{mantieni}
+\setinterfacevariable{knockout}{knockout}
+\setinterfacevariable{label}{etichetta}
+\setinterfacevariable{landscape}{orizzontale}
+\setinterfacevariable{last}{ultimo}
+\setinterfacevariable{lastcolumn}{lastcolumn}
+\setinterfacevariable{lastpage}{ultimapagina}
+\setinterfacevariable{lastpagenumber}{lastpagenumber}
+\setinterfacevariable{lastsubpage}{ultimasottopagina}
+\setinterfacevariable{layer}{layer}
+\setinterfacevariable{left}{sinistra}
+\setinterfacevariable{leftedge}{bordosinistro}
+\setinterfacevariable{lefthanging}{lefthanging}
+\setinterfacevariable{leftmargin}{marginesinistro}
+\setinterfacevariable{leftpage}{paginasinistra}
+\setinterfacevariable{lefttoright}{lefttoright}
+\setinterfacevariable{legend}{legenda}
+\setinterfacevariable{lesshyphenation}{lesshyphenation}
+\setinterfacevariable{line}{riga}
+\setinterfacevariable{linenote}{linenote}
+\setinterfacevariable{lines}{righe}
+\setinterfacevariable{list}{elenco}
+\setinterfacevariable{local}{locale}
+\setinterfacevariable{localenvironment}{ambientelocale}
+\setinterfacevariable{logo}{logo}
+\setinterfacevariable{logos}{loghi}
+\setinterfacevariable{lohi}{pedap}
+\setinterfacevariable{loose}{lento}
+\setinterfacevariable{low}{basso}
+\setinterfacevariable{ls}{ls}
+\setinterfacevariable{makeup}{makeup}
+\setinterfacevariable{mar}{mar}
+\setinterfacevariable{march}{marzo}
+\setinterfacevariable{margin}{margine}
+\setinterfacevariable{marginedge}{bordomargine}
+\setinterfacevariable{margintitle}{titoloinmargine}
+\setinterfacevariable{marking}{marcatura}
+\setinterfacevariable{mathalignment}{mathalignment}
+\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathmatrix}{mathmatrix}
+\setinterfacevariable{max}{max}
+\setinterfacevariable{maxdepth}{maxdepth}
+\setinterfacevariable{maxheight}{maxheight}
+\setinterfacevariable{maxwidth}{maxwidth}
+\setinterfacevariable{may}{maggio}
+\setinterfacevariable{mediaeval}{medievale}
+\setinterfacevariable{medium}{medio}
+\setinterfacevariable{middle}{centro}
+\setinterfacevariable{min}{min}
+\setinterfacevariable{mindepth}{mindepth}
+\setinterfacevariable{minheight}{altezzamin}
+\setinterfacevariable{minwidth}{ampiezzamin}
+\setinterfacevariable{mirrored}{riflesso}
+\setinterfacevariable{monday}{lunedi}
+\setinterfacevariable{mono}{mono}
+\setinterfacevariable{month}{mese}
+\setinterfacevariable{morehyphenation}{morehyphenation}
+\setinterfacevariable{name}{nome}
+\setinterfacevariable{narrow}{stretto}
+\setinterfacevariable{negative}{negativo}
+\setinterfacevariable{never}{mai}
+\setinterfacevariable{new}{nuovo}
+\setinterfacevariable{next}{successivo}
+\setinterfacevariable{nextevenpage}{paginaparisuccessiva}
+\setinterfacevariable{nextoddpage}{paginadisparisuccessiva}
+\setinterfacevariable{nextpage}{paginasuccessiva}
+\setinterfacevariable{nextsubpage}{sottopaginasuccessiva}
+\setinterfacevariable{no}{no}
+\setinterfacevariable{nocheck}{nocheck}
+\setinterfacevariable{nofit}{nofit}
+\setinterfacevariable{nogrid}{nogrid}
+\setinterfacevariable{nohz}{nohz}
+\setinterfacevariable{nomarking}{nomarcature}
+\setinterfacevariable{none}{nessuno}
+\setinterfacevariable{nonumber}{nonumber}
+\setinterfacevariable{normal}{normale}
+\setinterfacevariable{nospacing}{nospacing}
+\setinterfacevariable{not}{non}
+\setinterfacevariable{note}{note}
+\setinterfacevariable{nothanging}{nonsospeso}
+\setinterfacevariable{nothyphenated}{nonsillabato}
+\setinterfacevariable{november}{novembre}
+\setinterfacevariable{nowhere}{danessunaparte}
+\setinterfacevariable{nowhite}{nobianco}
+\setinterfacevariable{number}{numero}
+\setinterfacevariable{numbers}{numeri}
+\setinterfacevariable{october}{ottobre}
+\setinterfacevariable{odd}{dispari}
+\setinterfacevariable{off}{disattivo}
+\setinterfacevariable{offset}{offset}
+\setinterfacevariable{old}{old}
+\setinterfacevariable{on}{attivo}
+\setinterfacevariable{one}{uno}
+\setinterfacevariable{opposite}{opposto}
+\setinterfacevariable{outer}{esterno}
+\setinterfacevariable{outeredge}{bordoesterno}
+\setinterfacevariable{outermargin}{margineesterno}
+\setinterfacevariable{overbar}{sopralinea}
+\setinterfacevariable{overbars}{sopralinee}
+\setinterfacevariable{overlay}{sovrapponi}
+\setinterfacevariable{overprint}{overprint}
+\setinterfacevariable{overstrike}{sbarrato}
+\setinterfacevariable{overstrikes}{sbarrati}
+\setinterfacevariable{packed}{impaccato}
+\setinterfacevariable{page}{pagina}
+\setinterfacevariable{pagecomment}{commentopagina}
+\setinterfacevariable{pagenumber}{numeropagina}
+\setinterfacevariable{paper}{carta}
+\setinterfacevariable{paragraph}{capoverso}
+\setinterfacevariable{part}{parte}
+\setinterfacevariable{positive}{positivo}
+\setinterfacevariable{postponing}{posporre}
+\setinterfacevariable{postscript}{postscript}
+\setinterfacevariable{preference}{preferenza}
+\setinterfacevariable{preview}{anteprima}
+\setinterfacevariable{previous}{precedente}
+\setinterfacevariable{previousevenpage}{paginapariprecedente}
+\setinterfacevariable{previousoddpage}{paginadispariprecedente}
+\setinterfacevariable{previouspage}{paginaprecedente}
+\setinterfacevariable{previoussubpage}{sottopaginaprecedente}
+\setinterfacevariable{printable}{stampabile}
+\setinterfacevariable{process}{process}
+\setinterfacevariable{product}{prodotto}
+\setinterfacevariable{program}{programma}
+\setinterfacevariable{project}{progetto}
+\setinterfacevariable{protected}{protetto}
+\setinterfacevariable{quadruple}{quadruplo}
+\setinterfacevariable{quotation}{citazione}
+\setinterfacevariable{quote}{menzione}
+\setinterfacevariable{ran}{corse}
+\setinterfacevariable{random}{casuale}
+\setinterfacevariable{readonly}{solalettura}
+\setinterfacevariable{rectangular}{rettangolare}
+\setinterfacevariable{referral}{referral}
+\setinterfacevariable{register}{registro}
+\setinterfacevariable{regular}{regolare}
+\setinterfacevariable{rekening}{rekening}
+\setinterfacevariable{relative}{relativo}
+\setinterfacevariable{repeat}{ripeti}
+\setinterfacevariable{required}{richiestp}
+\setinterfacevariable{reset}{reimposta}
+\setinterfacevariable{reverse}{invertito}
+\setinterfacevariable{right}{destra}
+\setinterfacevariable{rightedge}{bordodestro}
+\setinterfacevariable{righthanging}{righthanging}
+\setinterfacevariable{rightmargin}{marginedestro}
+\setinterfacevariable{rightpage}{paginadestra}
+\setinterfacevariable{righttoleft}{righttoleft}
+\setinterfacevariable{roman}{roman}
+\setinterfacevariable{romannumerals}{numeriromani}
+\setinterfacevariable{rotate}{ruota}
+\setinterfacevariable{rotated}{ruotato}
+\setinterfacevariable{round}{rotondo}
+\setinterfacevariable{row}{row}
+\setinterfacevariable{rule}{linea}
+\setinterfacevariable{samepage}{stessapagina}
+\setinterfacevariable{sans}{sans}
+\setinterfacevariable{sansbold}{sansgrassetto}
+\setinterfacevariable{sansserif}{sansserif}
+\setinterfacevariable{saturday}{sabato}
+\setinterfacevariable{screen}{schermo}
+\setinterfacevariable{section}{capoverso}
+\setinterfacevariable{sectionblockenvironment}{ambientebloccosezione}
+\setinterfacevariable{sectionnumber}{numerosezione}
+\setinterfacevariable{see}{vedi}
+\setinterfacevariable{september}{settembre}
+\setinterfacevariable{serif}{serif}
+\setinterfacevariable{serried}{vicino}
+\setinterfacevariable{setups}{nastaveni}
+\setinterfacevariable{sheet}{sheet}
+\setinterfacevariable{short}{short}
+\setinterfacevariable{singlesided}{facciasingola}
+\setinterfacevariable{slanted}{inclinato}
+\setinterfacevariable{slantedbold}{inclinatograssetto}
+\setinterfacevariable{small}{piccolo}
+\setinterfacevariable{smallbodyfont}{piccolofontdelcorpo}
+\setinterfacevariable{smallbold}{piccolograssetto}
+\setinterfacevariable{smallbolditalic}{piccolograssettocorsivo}
+\setinterfacevariable{smallboldslanted}{piccolograssettoinclinato}
+\setinterfacevariable{smallcaps}{maiuscoletto}
+\setinterfacevariable{smallitalic}{piccolocorsivo}
+\setinterfacevariable{smallitalicbold}{piccolocorsivograssetto}
+\setinterfacevariable{smallnormal}{piccolonormale}
+\setinterfacevariable{smallslanted}{piccoloinclinato}
+\setinterfacevariable{smallslantedbold}{piccoloinclinatograssetto}
+\setinterfacevariable{smalltype}{piccolotype}
+\setinterfacevariable{somewhere}{daqualcheparte}
+\setinterfacevariable{sorted}{ordinato}
+\setinterfacevariable{space}{spazio}
+\setinterfacevariable{spacing}{spaziatura}
+\setinterfacevariable{speech}{speech}
+\setinterfacevariable{split}{separa}
+\setinterfacevariable{spot}{spot}
+\setinterfacevariable{standard}{standard}
+\setinterfacevariable{start}{inizia}
+\setinterfacevariable{starter}{starter}
+\setinterfacevariable{sticker}{sticker}
+\setinterfacevariable{stop}{termina}
+\setinterfacevariable{stopper}{stopper}
+\setinterfacevariable{stretch}{dilata}
+\setinterfacevariable{strict}{rigido}
+\setinterfacevariable{strong}{strong}
+\setinterfacevariable{strut}{strut}
+\setinterfacevariable{sub}{sotto}
+\setinterfacevariable{subbackward}{sottoindietro}
+\setinterfacevariable{subformula}{subformula}
+\setinterfacevariable{subforward}{sottoavanti}
+\setinterfacevariable{subject}{argomento}
+\setinterfacevariable{subpage}{sottopagina}
+\setinterfacevariable{subsection}{sottocapoverso}
+\setinterfacevariable{subsubject}{sottoargomento}
+\setinterfacevariable{subsubsection}{sottosottocapoverso}
+\setinterfacevariable{subsubsubject}{sottosottoargomento}
+\setinterfacevariable{subsubsubsection}{sottosottosottocapoverso}
+\setinterfacevariable{subsubsubsubject}{sottosottosottoargomento}
+\setinterfacevariable{subsubsubsubsection}{sottosottosottosottocapoverso}
+\setinterfacevariable{subsubsubsubsubject}{sottosottosottosottoargomento}
+\setinterfacevariable{subsubsubsubsubsection}{sottosottosottosottosottocapoverso}
+\setinterfacevariable{subsubsubsubsubsubject}{sottosottosottosottosottoargomento}
+\setinterfacevariable{subsubsubsubsubsubsection}{sottosottosottosottosottosottocapoverso}
+\setinterfacevariable{subsubsubsubsubsubsubject}{sottosottosottosottosottosottoargomento}
+\setinterfacevariable{subsubsubsubsubsubsubsection}{sottosottosottosottosottosottosottocapoverso}
+\setinterfacevariable{subsubsubsubsubsubsubsubject}{sottosottosottosottosottosottosottoargomento}
+\setinterfacevariable{subsubsubsubsubsubsubsubsection}{sottosottosottosottosottosottosottosottocapoverso}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubject}{sottosottosottosottosottosottosottosottoargomento}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsection}{sottosottosottosottosottosottosottosottosottocapoverso}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsubject}{sottosottosottosottosottosottosottosottosottoargomento}
+\setinterfacevariable{sunday}{domenica}
+\setinterfacevariable{support}{supporto}
+\setinterfacevariable{sym}{sim}
+\setinterfacevariable{symbol}{simbolo}
+\setinterfacevariable{synchronize}{synchronize}
+\setinterfacevariable{system}{sistema}
+\setinterfacevariable{table}{tabella}
+\setinterfacevariable{tablehead}{testatabella}
+\setinterfacevariable{tables}{tabelle}
+\setinterfacevariable{tabletail}{codatabella}
+\setinterfacevariable{tabulate}{tabulato}
+\setinterfacevariable{tabulatehead}{testatabulato}
+\setinterfacevariable{tabulatetail}{codatabulato}
+\setinterfacevariable{tall}{alto}
+\setinterfacevariable{teletype}{teletype}
+\setinterfacevariable{temporary}{temporaneo}
+\setinterfacevariable{test}{test}
+\setinterfacevariable{text}{testo}
+\setinterfacevariable{three}{tre}
+\setinterfacevariable{thursday}{giovedi}
+\setinterfacevariable{title}{titolo}
+\setinterfacevariable{toggle}{toggle}
+\setinterfacevariable{tolerant}{tollerante}
+\setinterfacevariable{top}{cima}
+\setinterfacevariable{tuesday}{martedi}
+\setinterfacevariable{two}{due}
+\setinterfacevariable{txt}{txt}
+\setinterfacevariable{type}{type}
+\setinterfacevariable{typing}{typing}
+\setinterfacevariable{unavailable}{nondisponibile}
+\setinterfacevariable{underbar}{sottolinea}
+\setinterfacevariable{underbars}{sottolinee}
+\setinterfacevariable{unit}{unita}
+\setinterfacevariable{units}{unita}
+\setinterfacevariable{unknown}{ignoto}
+\setinterfacevariable{unpacked}{unpacked}
+\setinterfacevariable{up}{up}
+\setinterfacevariable{url}{url}
+\setinterfacevariable{used}{usato}
+\setinterfacevariable{value}{valore}
+\setinterfacevariable{vertical}{verticale}
+\setinterfacevariable{very}{molto}
+\setinterfacevariable{verystrict}{moltorigido}
+\setinterfacevariable{verytolerant}{moltotollerante}
+\setinterfacevariable{weak}{weak}
+\setinterfacevariable{wednesday}{mercoledi}
+\setinterfacevariable{week}{settimana}
+\setinterfacevariable{weekday}{giornosettimana}
+\setinterfacevariable{white}{bianco}
+\setinterfacevariable{wide}{ampio}
+\setinterfacevariable{width}{ampiezza}
+\setinterfacevariable{xml}{xml}
+\setinterfacevariable{year}{anno}
+\setinterfacevariable{yes}{si}
+% definitions for interface constants for language it
+%
+\setinterfaceconstant{action}{azione}
+\setinterfaceconstant{address}{indirizzo}
+\setinterfaceconstant{after}{dopo}
+\setinterfaceconstant{afterhead}{dopotesta}
+\setinterfaceconstant{afterkey}{dopotasto}
+\setinterfaceconstant{align}{allinea}
+\setinterfaceconstant{aligncharacter}{allineacarattere}
+\setinterfaceconstant{alignmentcharacter}{carattereallineamento}
+\setinterfaceconstant{alignsymbol}{alignsymbol}
+\setinterfaceconstant{aligntitle}{allineatitolo}
+\setinterfaceconstant{alternative}{alternativa}
+\setinterfaceconstant{andtext}{andtext}
+\setinterfaceconstant{apa}{apa}
+\setinterfaceconstant{arrow}{freccia}
+\setinterfaceconstant{artauthor}{artauthor}
+\setinterfaceconstant{artauthoretaldisplay}{artauthoretaldisplay}
+\setinterfaceconstant{artauthoretallimit}{artauthoretallimit}
+\setinterfaceconstant{artauthoretaltext}{artauthoretaltext}
+\setinterfaceconstant{at}{ad}
+\setinterfaceconstant{author}{autore}
+\setinterfaceconstant{authoretaldisplay}{authoretaldisplay}
+\setinterfaceconstant{authoretallimit}{authoretallimit}
+\setinterfaceconstant{authoretaltext}{authoretaltext}
+\setinterfaceconstant{auto}{auto}
+\setinterfaceconstant{autofile}{autofile}
+\setinterfaceconstant{autofocus}{autofocus}
+\setinterfaceconstant{autohang}{autohang}
+\setinterfaceconstant{autostrut}{autostrut}
+\setinterfaceconstant{autowidth}{autoampiezza}
+\setinterfaceconstant{axis}{asse}
+\setinterfaceconstant{background}{sfondo}
+\setinterfaceconstant{backgroundcolor}{coloresfondo}
+\setinterfaceconstant{backgroundcorner}{angolosfondo}
+\setinterfaceconstant{backgrounddepth}{profonditasfondo}
+\setinterfaceconstant{backgroundoffset}{offsetsfondo}
+\setinterfaceconstant{backgroundradius}{raggiosfondo}
+\setinterfaceconstant{backgroundscreen}{schermosfondo}
+\setinterfaceconstant{backspace}{backspace}
+\setinterfaceconstant{balance}{bilanciamento}
+\setinterfaceconstant{before}{prima}
+\setinterfaceconstant{beforehead}{primaditesta}
+\setinterfaceconstant{bet}{bet}
+\setinterfaceconstant{big}{grande}
+\setinterfaceconstant{blank}{rigovuoto}
+\setinterfaceconstant{blockway}{blockway}
+\setinterfaceconstant{bodyfont}{fonttesto}
+\setinterfaceconstant{bookmark}{segnalibro}
+\setinterfaceconstant{bottom}{fondo}
+\setinterfaceconstant{bottomafter}{bottomafter}
+\setinterfaceconstant{bottombefore}{bottombefore}
+\setinterfaceconstant{bottomdistance}{distanzafondo}
+\setinterfaceconstant{bottomframe}{cornicefondo}
+\setinterfaceconstant{bottomoffset}{offsetfondo}
+\setinterfaceconstant{bottomspace}{spaziofondo}
+\setinterfaceconstant{bottomstate}{statofondo}
+\setinterfaceconstant{cache}{cache}
+\setinterfaceconstant{calculate}{calcola}
+\setinterfaceconstant{ccommand}{ccomando}
+\setinterfaceconstant{click}{click}
+\setinterfaceconstant{clickin}{clickdentro}
+\setinterfaceconstant{clickout}{clickfuori}
+\setinterfaceconstant{clipoffset}{clipoffset}
+\setinterfaceconstant{closeaction}{azionechiudi}
+\setinterfaceconstant{closecommand}{closecommand}
+\setinterfaceconstant{closepageaction}{azionechiudipagina}
+\setinterfaceconstant{closesymbol}{closesymbol}
+\setinterfaceconstant{color}{colore}
+\setinterfaceconstant{column}{colonna}
+\setinterfaceconstant{columndistance}{distanzacolonne}
+\setinterfaceconstant{columns}{colonne}
+\setinterfaceconstant{command}{comando}
+\setinterfaceconstant{commandafter}{comdandodopo}
+\setinterfaceconstant{commandbefore}{comandoprima}
+\setinterfaceconstant{commands}{comandi}
+\setinterfaceconstant{component}{component}
+\setinterfaceconstant{compoundhyphen}{compoundhyphen}
+\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{connector}{connector}
+\setinterfaceconstant{continue}{continua}
+\setinterfaceconstant{contrastcolor}{colorecontrasto}
+\setinterfaceconstant{controls}{controlli}
+\setinterfaceconstant{conversion}{conversione}
+\setinterfaceconstant{convertfile}{convertifile}
+\setinterfaceconstant{corner}{angolo}
+\setinterfaceconstant{coupling}{accoppiamento}
+\setinterfaceconstant{couplingway}{modoaccoppiamento}
+\setinterfaceconstant{criterium}{criterio}
+\setinterfaceconstant{current}{corrente}
+\setinterfaceconstant{cutspace}{cutspace}
+\setinterfaceconstant{dash}{dash}
+\setinterfaceconstant{dat}{dat}
+\setinterfaceconstant{database}{database}
+\setinterfaceconstant{date}{data}
+\setinterfaceconstant{deepnumbercommand}{deepnumbercommand}
+\setinterfaceconstant{deeptextcommand}{deeptextcommand}
+\setinterfaceconstant{default}{implicito}
+\setinterfaceconstant{delay}{attesa}
+\setinterfaceconstant{depth}{profondita}
+\setinterfaceconstant{depthcorrection}{correzioneprofondita}
+\setinterfaceconstant{direction}{direzione}
+\setinterfaceconstant{directory}{directory}
+\setinterfaceconstant{display}{display}
+\setinterfaceconstant{distance}{distanza}
+\setinterfaceconstant{dot}{punto}
+\setinterfaceconstant{doublesided}{doppiafaccia}
+\setinterfaceconstant{dummy}{dummy}
+\setinterfaceconstant{dx}{dx}
+\setinterfaceconstant{dy}{dy}
+\setinterfaceconstant{edge}{bordo}
+\setinterfaceconstant{edgedistance}{distanzabordo}
+\setinterfaceconstant{editor}{editor}
+\setinterfaceconstant{editoretaldisplay}{editoretaldisplay}
+\setinterfaceconstant{editoretallimit}{editoretallimit}
+\setinterfaceconstant{editoretaltext}{editoretaltext}
+\setinterfaceconstant{empty}{vuoto}
+\setinterfaceconstant{equalheight}{equalheight}
+\setinterfaceconstant{equalwidth}{equalwidth}
+\setinterfaceconstant{escape}{escape}
+\setinterfaceconstant{evenmargin}{marginepari}
+\setinterfaceconstant{expansion}{espansione}
+\setinterfaceconstant{export}{export}
+\setinterfaceconstant{extras}{extras}
+\setinterfaceconstant{factor}{fattore}
+\setinterfaceconstant{fallback}{fallback}
+\setinterfaceconstant{family}{famiglia}
+\setinterfaceconstant{fieldbackgroundcolor}{coloresfondocampo}
+\setinterfaceconstant{fieldframecolor}{colorecornicecampo}
+\setinterfaceconstant{fieldlayer}{fieldlayer}
+\setinterfaceconstant{fieldoffset}{offsetcampo}
+\setinterfaceconstant{file}{file}
+\setinterfaceconstant{filtercommand}{filtercommand}
+\setinterfaceconstant{finalnamesep}{finalnamesep}
+\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{focus}{focus}
+\setinterfaceconstant{focusin}{focusin}
+\setinterfaceconstant{focusout}{focusout}
+\setinterfaceconstant{footer}{piedipagina}
+\setinterfaceconstant{footerdistance}{distanzapdp}
+\setinterfaceconstant{footerstate}{statopdp}
+\setinterfaceconstant{foregroundcolor}{coloreprimopiano}
+\setinterfaceconstant{foregroundstyle}{foregroundstyle}
+\setinterfaceconstant{format}{format}
+\setinterfaceconstant{frame}{cornice}
+\setinterfaceconstant{framecolor}{colorecornice}
+\setinterfaceconstant{framecorner}{angolocornice}
+\setinterfaceconstant{framedepth}{profonditacornice}
+\setinterfaceconstant{frameoffset}{offsetcornice}
+\setinterfaceconstant{frameradius}{raggiocornice}
+\setinterfaceconstant{frames}{cornici}
+\setinterfaceconstant{from}{da}
+\setinterfaceconstant{get}{prendi}
+\setinterfaceconstant{global}{globale}
+\setinterfaceconstant{grid}{griglia}
+\setinterfaceconstant{hang}{sospendi}
+\setinterfaceconstant{headalign}{headalign}
+\setinterfaceconstant{headcolor}{coloretesta}
+\setinterfaceconstant{headcommand}{headcommand}
+\setinterfaceconstant{headconversion}{conversionetesta}
+\setinterfaceconstant{header}{intestazione}
+\setinterfaceconstant{headerdistance}{distanzaintestazione}
+\setinterfaceconstant{headerstate}{statointestazione}
+\setinterfaceconstant{headlabel}{etichettatesta}
+\setinterfaceconstant{headnumber}{numerotesta}
+\setinterfaceconstant{headstyle}{stiletesta}
+\setinterfaceconstant{height}{altezza}
+\setinterfaceconstant{hfactor}{hfactor}
+\setinterfaceconstant{hfil}{hfil}
+\setinterfaceconstant{hidenumber}{hidenumber}
+\setinterfaceconstant{hoffset}{hoffset}
+\setinterfaceconstant{horoffset}{horoffset}
+\setinterfaceconstant{hyphen}{hyphen}
+\setinterfaceconstant{icommand}{icomando}
+\setinterfaceconstant{in}{in}
+\setinterfaceconstant{inbetween}{tra}
+\setinterfaceconstant{increment}{incremento}
+\setinterfaceconstant{incrementnumber}{incrementanumero}
+\setinterfaceconstant{indenting}{rientro}
+\setinterfaceconstant{indentnext}{rientrasuccessivo}
+\setinterfaceconstant{indicator}{indicatore}
+\setinterfaceconstant{inner}{interno}
+\setinterfaceconstant{innermargin}{margineinterno}
+\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{intent}{intent}
+\setinterfaceconstant{interaction}{interazione}
+\setinterfaceconstant{interlinespace}{interlinea}
+\setinterfaceconstant{itemalign}{itemalign}
+\setinterfaceconstant{items}{elementi}
+\setinterfaceconstant{juniorsep}{juniorsep}
+\setinterfaceconstant{ken}{ken}
+\setinterfaceconstant{keyexpansion}{keyexpansion}
+\setinterfaceconstant{keyword}{parolachiave}
+\setinterfaceconstant{label}{etichetta}
+\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{left}{sinistra}
+\setinterfaceconstant{leftcolor}{coloresinistra}
+\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
+\setinterfaceconstant{leftedge}{bordosinistro}
+\setinterfaceconstant{leftedgedistance}{distanzabordosinistro}
+\setinterfaceconstant{leftframe}{cornicesinistra}
+\setinterfaceconstant{lefthyphen}{lefthyphen}
+\setinterfaceconstant{leftmargin}{marginesinistro}
+\setinterfaceconstant{leftmargindistance}{distanzamarginesinistro}
+\setinterfaceconstant{leftoffset}{offsetsinistro}
+\setinterfaceconstant{leftquotation}{citazionesinistra}
+\setinterfaceconstant{leftquote}{menzionesinistra}
+\setinterfaceconstant{leftsentence}{frasesinistra}
+\setinterfaceconstant{leftspeech}{leftspeech}
+\setinterfaceconstant{leftstyle}{stilesinistra}
+\setinterfaceconstant{leftsubsentence}{sottofrasesinistra}
+\setinterfaceconstant{lefttext}{testosinistro}
+\setinterfaceconstant{leftwidth}{ampiezzasinistra}
+\setinterfaceconstant{level}{livello}
+\setinterfaceconstant{levels}{livelli}
+\setinterfaceconstant{limittext}{limittext}
+\setinterfaceconstant{line}{riga}
+\setinterfaceconstant{linecorrection}{correzioneriga}
+\setinterfaceconstant{lines}{righe}
+\setinterfaceconstant{list}{elenco}
+\setinterfaceconstant{listtext}{listtext}
+\setinterfaceconstant{local}{locale}
+\setinterfaceconstant{location}{luogo}
+\setinterfaceconstant{logo}{logo}
+\setinterfaceconstant{logos}{loghi}
+\setinterfaceconstant{marcolor}{coloremarcatura}
+\setinterfaceconstant{margin}{margine}
+\setinterfaceconstant{margindistance}{distanzamargine}
+\setinterfaceconstant{marginedge}{bordomargine}
+\setinterfaceconstant{marginedgetext}{testobordomargine}
+\setinterfaceconstant{margintext}{testomargine}
+\setinterfaceconstant{marking}{marcatura}
+\setinterfaceconstant{marstyle}{stilemarcatura}
+\setinterfaceconstant{max}{max}
+\setinterfaceconstant{maxdepth}{maxdepth}
+\setinterfaceconstant{maxheight}{altezzamax}
+\setinterfaceconstant{maxwidth}{ampiezzamax}
+\setinterfaceconstant{maybeyear}{maybeyear}
+\setinterfaceconstant{menu}{menu}
+\setinterfaceconstant{method}{metodo}
+\setinterfaceconstant{middle}{centro}
+\setinterfaceconstant{middlespeech}{middlespeech}
+\setinterfaceconstant{middletext}{testocentro}
+\setinterfaceconstant{midsentence}{midsentence}
+\setinterfaceconstant{min}{min}
+\setinterfaceconstant{mindepth}{mindeoth}
+\setinterfaceconstant{minheight}{altezzamin}
+\setinterfaceconstant{minwidth}{ampiezzamin}
+\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{n}{n}
+\setinterfaceconstant{name}{nome}
+\setinterfaceconstant{namesep}{namesep}
+\setinterfaceconstant{nbottom}{nfondo}
+\setinterfaceconstant{nc}{nc}
+\setinterfaceconstant{next}{successivo}
+\setinterfaceconstant{nl}{nl}
+\setinterfaceconstant{nleft}{nsinistra}
+\setinterfaceconstant{nlines}{nrighe}
+\setinterfaceconstant{norm}{norma}
+\setinterfaceconstant{nr}{nr}
+\setinterfaceconstant{nright}{ndestra}
+\setinterfaceconstant{ntop}{ncima}
+\setinterfaceconstant{number}{numero}
+\setinterfaceconstant{numbercolor}{colorenumero}
+\setinterfaceconstant{numbercommand}{comandonumero}
+\setinterfaceconstant{numberconversion}{numberconversion}
+\setinterfaceconstant{numberconversionset}{numberconversionset}
+\setinterfaceconstant{numberdistance}{numberdistance}
+\setinterfaceconstant{numbering}{numerazione}
+\setinterfaceconstant{numberorder}{numberorder}
+\setinterfaceconstant{numberprefix}{numberprefix}
+\setinterfaceconstant{numbersegments}{numbersegments}
+\setinterfaceconstant{numberseparator}{separatorenumero}
+\setinterfaceconstant{numberseparatorset}{numberseparatorset}
+\setinterfaceconstant{numberset}{numberset}
+\setinterfaceconstant{numberstarter}{numberstarter}
+\setinterfaceconstant{numberstopper}{numberstopper}
+\setinterfaceconstant{numberstyle}{stilenumero}
+\setinterfaceconstant{numberwidth}{numberwidth}
+\setinterfaceconstant{nx}{nx}
+\setinterfaceconstant{ny}{ny}
+\setinterfaceconstant{object}{oggetto}
+\setinterfaceconstant{obstruction}{ostruzione}
+\setinterfaceconstant{oddmargin}{marginedispari}
+\setinterfaceconstant{offset}{offset}
+\setinterfaceconstant{openaction}{azioneapri}
+\setinterfaceconstant{openpageaction}{azioneapripagina}
+\setinterfaceconstant{option}{opzione}
+\setinterfaceconstant{order}{order}
+\setinterfaceconstant{orientation}{orientation}
+\setinterfaceconstant{otherstext}{otherstext}
+\setinterfaceconstant{outermargin}{margineesterno}
+\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownnumber}{numeroproprio}
+\setinterfaceconstant{page}{pagina}
+\setinterfaceconstant{pageboundaries}{limitipagina}
+\setinterfaceconstant{pagecolor}{colorepagina}
+\setinterfaceconstant{pagecommand}{comandopagina}
+\setinterfaceconstant{pageconversion}{pageconversion}
+\setinterfaceconstant{pageconversionset}{pageconversionset}
+\setinterfaceconstant{pagenumber}{numeropagina}
+\setinterfaceconstant{pageprefix}{pageprefix}
+\setinterfaceconstant{pageprefixconnector}{pageprefixconnector}
+\setinterfaceconstant{pageprefixconversion}{pageprefixconversion}
+\setinterfaceconstant{pageprefixconversionset}{pageprefixconversionset}
+\setinterfaceconstant{pageprefixsegments}{pageprefixsegments}
+\setinterfaceconstant{pageprefixseparatorset}{pageprefixseparatorset}
+\setinterfaceconstant{pageprefixset}{pageprefixset}
+\setinterfaceconstant{pageprefixstarter}{pageprefixstarter}
+\setinterfaceconstant{pageprefixstopper}{pageprefixstopper}
+\setinterfaceconstant{pagesegments}{pagesegments}
+\setinterfaceconstant{pageseparatorset}{pageseparatorset}
+\setinterfaceconstant{pageset}{pageset}
+\setinterfaceconstant{pagestarter}{pagestarter}
+\setinterfaceconstant{pagestate}{statopagina}
+\setinterfaceconstant{pagestopper}{pagestopper}
+\setinterfaceconstant{pagestyle}{stilepagina}
+\setinterfaceconstant{palet}{tavolozza}
+\setinterfaceconstant{paper}{carta}
+\setinterfaceconstant{paragraph}{capoverso}
+\setinterfaceconstant{place}{metti}
+\setinterfaceconstant{placehead}{mettitesta}
+\setinterfaceconstant{placestopper}{mettistopper}
+\setinterfaceconstant{position}{posizione}
+\setinterfaceconstant{prefix}{prefisso}
+\setinterfaceconstant{prefixconnector}{prefixconnector}
+\setinterfaceconstant{prefixconversion}{prefixconversion}
+\setinterfaceconstant{prefixconversionset}{prefixconversionset}
+\setinterfaceconstant{prefixsegments}{prefixsegments}
+\setinterfaceconstant{prefixseparatorset}{prefixseparatorset}
+\setinterfaceconstant{prefixset}{prefixset}
+\setinterfaceconstant{prefixstarter}{prefixstarter}
+\setinterfaceconstant{prefixstopper}{prefixstopper}
+\setinterfaceconstant{preset}{preimpostato}
+\setinterfaceconstant{preview}{anteprima}
+\setinterfaceconstant{previous}{precedente}
+\setinterfaceconstant{previousnumber}{numeroprecedente}
+\setinterfaceconstant{process}{process}
+\setinterfaceconstant{pubsep}{pubsep}
+\setinterfaceconstant{radius}{raggio}
+\setinterfaceconstant{random}{casuale}
+\setinterfaceconstant{range}{range}
+\setinterfaceconstant{reduction}{riduzione}
+\setinterfaceconstant{ref}{ref}
+\setinterfaceconstant{refcommand}{refcommand}
+\setinterfaceconstant{reference}{riferimento}
+\setinterfaceconstant{referenceprefix}{referenceprefix}
+\setinterfaceconstant{referencing}{referencing}
+\setinterfaceconstant{regionin}{entraregione}
+\setinterfaceconstant{regionout}{esciregione}
+\setinterfaceconstant{repeat}{ripeti}
+\setinterfaceconstant{reset}{reset}
+\setinterfaceconstant{resetnumber}{resetnumber}
+\setinterfaceconstant{resolution}{risoluzione}
+\setinterfaceconstant{right}{destra}
+\setinterfaceconstant{rightcolor}{coloredestra}
+\setinterfaceconstant{rightcompoundhyphen}{rightcompoundhyphen}
+\setinterfaceconstant{rightedge}{bordodestro}
+\setinterfaceconstant{rightedgedistance}{distanzabordodestro}
+\setinterfaceconstant{rightframe}{cornicedestra}
+\setinterfaceconstant{righthyphen}{righthyphen}
+\setinterfaceconstant{rightmargin}{marginedestro}
+\setinterfaceconstant{rightmargindistance}{distanzamarginedestro}
+\setinterfaceconstant{rightoffset}{offsetdestro}
+\setinterfaceconstant{rightquotation}{citazionedestra}
+\setinterfaceconstant{rightquote}{menzionedestra}
+\setinterfaceconstant{rightsentence}{frasedestra}
+\setinterfaceconstant{rightspeech}{rightspeech}
+\setinterfaceconstant{rightstyle}{stiledestra}
+\setinterfaceconstant{rightsubsentence}{sottofrasedestra}
+\setinterfaceconstant{righttext}{testodestro}
+\setinterfaceconstant{rightwidth}{ampiezzadestra}
+\setinterfaceconstant{rotation}{rotazione}
+\setinterfaceconstant{rule}{linea}
+\setinterfaceconstant{rulecolor}{colorelinea}
+\setinterfaceconstant{rulethickness}{spessorelinea}
+\setinterfaceconstant{samepage}{stessapagina}
+\setinterfaceconstant{sample}{campione}
+\setinterfaceconstant{samplesize}{samplesize}
+\setinterfaceconstant{saveinlist}{saveinlist}
+\setinterfaceconstant{scale}{scala}
+\setinterfaceconstant{scope}{scope}
+\setinterfaceconstant{screen}{schermo}
+\setinterfaceconstant{section}{sezione}
+\setinterfaceconstant{sectionconversion}{sectionconversion}
+\setinterfaceconstant{sectionconversionset}{sectionconversionset}
+\setinterfaceconstant{sectionnumber}{numerosezione}
+\setinterfaceconstant{sectionresetset}{sectionresetset}
+\setinterfaceconstant{sectionsegments}{sectionsegments}
+\setinterfaceconstant{sectionseparatorset}{sectionseparatorset}
+\setinterfaceconstant{sectionset}{sectionset}
+\setinterfaceconstant{sectionstarter}{sectionstarter}
+\setinterfaceconstant{sectionstopper}{sectionstopper}
+\setinterfaceconstant{separator}{separatore}
+\setinterfaceconstant{set}{set}
+\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{side}{lato}
+\setinterfaceconstant{sidealign}{sidealign}
+\setinterfaceconstant{sidemethod}{sidemethod}
+\setinterfaceconstant{sidespaceafter}{spaziolateraledopo}
+\setinterfaceconstant{sidespacebefore}{spaziolateraleprima}
+\setinterfaceconstant{sign}{segno}
+\setinterfaceconstant{size}{dimensione}
+\setinterfaceconstant{small}{piccolo}
+\setinterfaceconstant{sort}{sort}
+\setinterfaceconstant{sorttype}{sorttype}
+\setinterfaceconstant{source}{origine}
+\setinterfaceconstant{space}{spazio}
+\setinterfaceconstant{spaceafter}{spaziodopo}
+\setinterfaceconstant{spacebefore}{spazioprima}
+\setinterfaceconstant{spaceinbetween}{spaceinbetween}
+\setinterfaceconstant{spacing}{spaziatura}
+\setinterfaceconstant{split}{separa}
+\setinterfaceconstant{splitcolor}{splitcolor}
+\setinterfaceconstant{splitmethod}{splitmethod}
+\setinterfaceconstant{splitoffset}{splitoffset}
+\setinterfaceconstant{spot}{spot}
+\setinterfaceconstant{stack}{stack}
+\setinterfaceconstant{start}{inizia}
+\setinterfaceconstant{starter}{starter}
+\setinterfaceconstant{state}{stato}
+\setinterfaceconstant{step}{passo}
+\setinterfaceconstant{stop}{termina}
+\setinterfaceconstant{stopper}{stopper}
+\setinterfaceconstant{stretch}{dilata}
+\setinterfaceconstant{strip}{strip}
+\setinterfaceconstant{strut}{strut}
+\setinterfaceconstant{style}{stile}
+\setinterfaceconstant{sub}{sotto}
+\setinterfaceconstant{subtitle}{sottotitolo}
+\setinterfaceconstant{suffix}{suffix}
+\setinterfaceconstant{surnamesep}{surnamesep}
+\setinterfaceconstant{sx}{sx}
+\setinterfaceconstant{sy}{sy}
+\setinterfaceconstant{symalign}{symallinea}
+\setinterfaceconstant{symbol}{simbolo}
+\setinterfaceconstant{symbolset}{setsimboli}
+\setinterfaceconstant{symcolor}{coloresimbolo}
+\setinterfaceconstant{symstyle}{stilesimbolo}
+\setinterfaceconstant{synonym}{sinonimo}
+\setinterfaceconstant{synonymcolor}{coloresinonimi}
+\setinterfaceconstant{synonymcommand}{synonymcommand}
+\setinterfaceconstant{synonymstyle}{stilesinonimi}
+\setinterfaceconstant{tab}{tab}
+\setinterfaceconstant{text}{testo}
+\setinterfaceconstant{textcolor}{coloretesto}
+\setinterfaceconstant{textcommand}{comandotesto}
+\setinterfaceconstant{textdistance}{distanzatesto}
+\setinterfaceconstant{textlayer}{textlayer}
+\setinterfaceconstant{textmargin}{textmargin}
+\setinterfaceconstant{textmethod}{textmethod}
+\setinterfaceconstant{textseparator}{separatoretesto}
+\setinterfaceconstant{textsize}{dimensionetesto}
+\setinterfaceconstant{textstate}{statotesto}
+\setinterfaceconstant{textstyle}{stiletesto}
+\setinterfaceconstant{textwidth}{ampiezzatesto}
+\setinterfaceconstant{title}{titolo}
+\setinterfaceconstant{titlecolor}{coloretitolo}
+\setinterfaceconstant{titlecommand}{titlecommand}
+\setinterfaceconstant{titledistance}{distanzatitolo}
+\setinterfaceconstant{titleleft}{titleleft}
+\setinterfaceconstant{titleright}{titleright}
+\setinterfaceconstant{titlestyle}{stiletitolo}
+\setinterfaceconstant{to}{verso}
+\setinterfaceconstant{tolerance}{tolleranza}
+\setinterfaceconstant{top}{cima}
+\setinterfaceconstant{topdistance}{distanzacima}
+\setinterfaceconstant{topframe}{cornicecima}
+\setinterfaceconstant{topoffset}{offsetcima}
+\setinterfaceconstant{topspace}{spaziocima}
+\setinterfaceconstant{topstate}{statocima}
+\setinterfaceconstant{totalnumber}{totalnumber}
+\setinterfaceconstant{type}{type}
+\setinterfaceconstant{unit}{unita}
+\setinterfaceconstant{unknownreference}{riferimentoingoto}
+\setinterfaceconstant{urlalternative}{alternativaurl}
+\setinterfaceconstant{urlspace}{spaziourl}
+\setinterfaceconstant{validate}{verifica}
+\setinterfaceconstant{vcommand}{vcomando}
+\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfil}{vfil}
+\setinterfaceconstant{voffset}{voffset}
+\setinterfaceconstant{vonsep}{vonsep}
+\setinterfaceconstant{way}{modo}
+\setinterfaceconstant{wfactor}{wfactor}
+\setinterfaceconstant{white}{bianco}
+\setinterfaceconstant{width}{ampiezza}
+\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xmax}{xmax}
+\setinterfaceconstant{xoffset}{xoffset}
+\setinterfaceconstant{xscale}{xscale}
+\setinterfaceconstant{xstep}{xstep}
+\setinterfaceconstant{yfactor}{yfactor}
+\setinterfaceconstant{ymax}{ymax}
+\setinterfaceconstant{yoffset}{yoffset}
+\setinterfaceconstant{yscale}{yscale}
+\setinterfaceconstant{ystep}{ystep}
+% definitions for interface elements for language it
+%
+\setinterfaceelement{answerlines}{answerlines}
+\setinterfaceelement{answerspace}{answerspace}
+\setinterfaceelement{begin}{inizio}
+\setinterfaceelement{complete}{completo}
+\setinterfaceelement{coupled}{accoppiato}
+\setinterfaceelement{currentlocal}{correntelocale}
+\setinterfaceelement{emptyone}{prazdne}
+\setinterfaceelement{emptytwo}{vuoti}
+\setinterfaceelement{end}{fine}
+\setinterfaceelement{endsetup}{}
+\setinterfaceelement{get}{prendi}
+\setinterfaceelement{increment}{incrementa}
+\setinterfaceelement{list}{elenco}
+\setinterfaceelement{listof}{elencodi}
+\setinterfaceelement{load}{carica}
+\setinterfaceelement{local}{locale}
+\setinterfaceelement{makeup}{makeup}
+\setinterfaceelement{next}{successivo}
+\setinterfaceelement{place}{metti}
+\setinterfaceelement{previous}{precedente}
+\setinterfaceelement{previouslocal}{precedentelocale}
+\setinterfaceelement{reserve}{riserva}
+\setinterfaceelement{see}{vedi}
+\setinterfaceelement{setup}{imposta}
+\setinterfaceelement{start}{inizia}
+\setinterfaceelement{stop}{termina}
+\setinterfaceelement{text}{testo}
+\setinterfaceelement{type}{type}
+% definitions for interface commands for language it
+%
+\setinterfacecommand{CAPPED}{CAP}
+\setinterfacecommand{Character}{Lettera}
+\setinterfacecommand{Characters}{Lettere}
+\setinterfacecommand{LABELTEXT}{TESTOETICHETTA}
+\setinterfacecommand{MONTH}{MESE}
+\setinterfacecommand{Numbers}{Numeri}
+\setinterfacecommand{Romannumerals}{Numeriromani}
+\setinterfacecommand{SmallCapped}{Cap}
+\setinterfacecommand{SmallCaps}{Caps}
+\setinterfacecommand{WEEKDAY}{GIORNOSETTIMANA}
+\setinterfacecommand{WORD}{PAROLA}
+\setinterfacecommand{WORDS}{PAROLE}
+\setinterfacecommand{Word}{Parola}
+\setinterfacecommand{Words}{Parole}
+\setinterfacecommand{about}{intorno}
+\setinterfacecommand{adaptlayout}{adattalayout}
+\setinterfacecommand{arg}{arg}
+\setinterfacecommand{at}{al}
+\setinterfacecommand{atleftmargin}{atleftmargin}
+\setinterfacecommand{atpage}{apagina}
+\setinterfacecommand{atrightmargin}{atrightmargin}
+\setinterfacecommand{background}{sfondo}
+\setinterfacecommand{backspace}{spaziodietro}
+\setinterfacecommand{blackrule}{lineanera}
+\setinterfacecommand{blackrules}{lineenere}
+\setinterfacecommand{blank}{rigovuoto}
+\setinterfacecommand{bookmark}{segnalibro}
+\setinterfacecommand{bottomdistance}{distanzafondo}
+\setinterfacecommand{bottomheight}{altezzafondo}
+\setinterfacecommand{bottomspace}{spaziofondo}
+\setinterfacecommand{but}{fondo}
+\setinterfacecommand{button}{pulsante}
+\setinterfacecommand{bypassblocks}{saltablocchi}
+\setinterfacecommand{character}{lettera}
+\setinterfacecommand{characters}{lettere}
+\setinterfacecommand{chem}{chim}
+\setinterfacecommand{clip}{clip}
+\setinterfacecommand{clonefield}{clonacampo}
+\setinterfacecommand{color}{colore}
+\setinterfacecommand{colorbar}{barracolori}
+\setinterfacecommand{colorvalue}{valorecolore}
+\setinterfacecommand{column}{colonna}
+\setinterfacecommand{comment}{commento}
+\setinterfacecommand{comparecolorgroup}{confrontagruppocolori}
+\setinterfacecommand{comparepalet}{confrontatavolozza}
+\setinterfacecommand{completepagenumber}{numeropaginacompleto}
+\setinterfacecommand{completeregister}{completeregister}
+\setinterfacecommand{component}{componenet}
+\setinterfacecommand{convertnumber}{convertinumero}
+\setinterfacecommand{copyfield}{copiacampo}
+\setinterfacecommand{correctwhitespace}{correggispaziobianco}
+\setinterfacecommand{coupledocument}{accoppiadocumento}
+\setinterfacecommand{couplemarking}{accoppiamarcatura}
+\setinterfacecommand{couplepage}{accoppiapagina}
+\setinterfacecommand{couplepaper}{accoppiacarta}
+\setinterfacecommand{coupleregister}{accoppiaregistro}
+\setinterfacecommand{crlf}{crlf}
+\setinterfacecommand{currentdate}{datadioggi}
+\setinterfacecommand{currentheadnumber}{numerotestacorrente}
+\setinterfacecommand{cutspace}{cutspace}
+\setinterfacecommand{date}{data}
+\setinterfacecommand{decouplemarking}{separamarcatura}
+\setinterfacecommand{decrementnumber}{decrementnumber}
+\setinterfacecommand{define}{definisci}
+\setinterfacecommand{defineaccent}{definisciaccento}
+\setinterfacecommand{defineblank}{definiscirigovuoto}
+\setinterfacecommand{defineblock}{definisciblocco}
+\setinterfacecommand{definebodyfont}{definiscifontdeltesto}
+\setinterfacecommand{definebodyfontenvironment}{definisciambientefontdeltesto}
+\setinterfacecommand{definebuffer}{definiscibuffer}
+\setinterfacecommand{definecharacter}{definiscicarattere}
+\setinterfacecommand{definecolor}{definiscicolore}
+\setinterfacecommand{definecolorgroup}{definiscigruppocolori}
+\setinterfacecommand{definecolumnbreak}{definecolumnbreak}
+\setinterfacecommand{definecolumnset}{definiscigruppocolonne}
+\setinterfacecommand{definecombination}{definecombination}
+\setinterfacecommand{definecombinedlist}{definiscielencocombinato}
+\setinterfacecommand{definecommand}{definiscicomando}
+\setinterfacecommand{defineconversion}{definisciconversione}
+\setinterfacecommand{definedescription}{definiscidescrizione}
+\setinterfacecommand{defineenumeration}{definiscienumerazione}
+\setinterfacecommand{definefield}{definiscicampo}
+\setinterfacecommand{definefieldstack}{definiscistackcampi}
+\setinterfacecommand{definefiguresymbol}{definiscifigurasimbolo}
+\setinterfacecommand{definefloat}{definiscioggettomobile}
+\setinterfacecommand{definefont}{definiscifont}
+\setinterfacecommand{definefontstyle}{definiscistilefont}
+\setinterfacecommand{definefontsynonym}{definiscisinonimofont}
+\setinterfacecommand{defineframed}{definisciincorniciato}
+\setinterfacecommand{defineframedtext}{definiscitestoincorniciato}
+\setinterfacecommand{definehbox}{definiscihbox}
+\setinterfacecommand{definehead}{definiscitesta}
+\setinterfacecommand{defineindenting}{definiscirientro}
+\setinterfacecommand{defineinmargin}{defineinmargin}
+\setinterfacecommand{defineinteractionmenu}{definiscimenuinterazione}
+\setinterfacecommand{defineitemgroup}{defineitemgroup}
+\setinterfacecommand{definelabel}{definiscietichetta}
+\setinterfacecommand{definelayer}{definelayer}
+\setinterfacecommand{definelayout}{definiscilayout}
+\setinterfacecommand{definelist}{definiscielenco}
+\setinterfacecommand{definelogo}{definiscilogo}
+\setinterfacecommand{definemainfield}{definiscicampoprincipale}
+\setinterfacecommand{definemakeup}{definiscimakeup}
+\setinterfacecommand{definemarking}{definiscimarcatura}
+\setinterfacecommand{definemathalignment}{definemathalignment}
+\setinterfacecommand{defineoutput}{definiscioutput}
+\setinterfacecommand{defineoverlay}{definiscisovrapposizione}
+\setinterfacecommand{definepagebreak}{definepagebreak}
+\setinterfacecommand{definepalet}{definiscitavolozza}
+\setinterfacecommand{definepapersize}{definiscidimensionicarta}
+\setinterfacecommand{defineparagraphs}{definiscicapoversi}
+\setinterfacecommand{defineplacement}{defineplacement}
+\setinterfacecommand{defineprofile}{definisciprofilo}
+\setinterfacecommand{defineprogram}{definisciprogramma}
+\setinterfacecommand{definerawfont}{definiscifontgrezzo}
+\setinterfacecommand{definereference}{definisciriferimento}
+\setinterfacecommand{definereferenceformat}{definisciformatoriferimento}
+\setinterfacecommand{definereferencelist}{definiscilistariferimenti}
+\setinterfacecommand{defineregister}{definisciregistro}
+\setinterfacecommand{definerule}{definiscilinea}
+\setinterfacecommand{definesection}{definiscisezione}
+\setinterfacecommand{definesectionblock}{definiscibloccosezione}
+\setinterfacecommand{definesorting}{definisciordinamento}
+\setinterfacecommand{definestartstop}{definisciiniziatermina}
+\setinterfacecommand{definestyle}{definiscistile}
+\setinterfacecommand{definesubfield}{definiscisottocampo}
+\setinterfacecommand{definesymbol}{definiscisimbolo}
+\setinterfacecommand{definesynonyms}{definiscisinonimi}
+\setinterfacecommand{definetabletemplate}{definiscimodellotabella}
+\setinterfacecommand{definetabulate}{definiscitabulato}
+\setinterfacecommand{definetext}{definiscitesto}
+\setinterfacecommand{definetextposition}{definisciposizionetesto}
+\setinterfacecommand{definetextvariable}{definiscivariabiletesto}
+\setinterfacecommand{definetype}{definiscitype}
+\setinterfacecommand{definetyping}{definiscityping}
+\setinterfacecommand{defineversion}{definisciversion}
+\setinterfacecommand{determineheadnumber}{determinanumerotesta}
+\setinterfacecommand{determinelistcharacteristics}{determinacarattersticheelenco}
+\setinterfacecommand{determineregistercharacteristics}{determinacaratteristicheregistro}
+\setinterfacecommand{dimension}{dimensione}
+\setinterfacecommand{disableinteractionmenu}{disabilitamenuinterazione}
+\setinterfacecommand{domicile}{domicilio}
+\setinterfacecommand{donttest}{notest}
+\setinterfacecommand{edgedistance}{distanzabordo}
+\setinterfacecommand{edgewidth}{ampiezzabordo}
+\setinterfacecommand{emptylines}{emptylines}
+\setinterfacecommand{environment}{ambiente}
+\setinterfacecommand{externalfigure}{figuraesterna}
+\setinterfacecommand{fact}{fatto}
+\setinterfacecommand{field}{campi}
+\setinterfacecommand{fieldstack}{stackcampi}
+\setinterfacecommand{fillinfield}{camporiempimento}
+\setinterfacecommand{fillinline}{rigariempimento}
+\setinterfacecommand{fillinrules}{lineeriempimento}
+\setinterfacecommand{fillintext}{testoriempimento}
+\setinterfacecommand{fitfield}{adattacampo}
+\setinterfacecommand{fixedspace}{spaziofisso}
+\setinterfacecommand{fixedspaces}{spazifissi}
+\setinterfacecommand{followprofile}{seguiprofilo}
+\setinterfacecommand{followprofileversion}{seguiversioneprofilo}
+\setinterfacecommand{followversion}{seguiversione}
+\setinterfacecommand{footerdistance}{distanzapdp}
+\setinterfacecommand{footerheight}{altezzapdp}
+\setinterfacecommand{footnote}{notapdp}
+\setinterfacecommand{footnotetext}{testonotapdp}
+\setinterfacecommand{forceblocks}{forzablocchi}
+\setinterfacecommand{formulanumber}{numeroformula}
+\setinterfacecommand{fraction}{frazione}
+\setinterfacecommand{framed}{incorniciato}
+\setinterfacecommand{from}{da}
+\setinterfacecommand{getbuffer}{prendibuffer}
+\setinterfacecommand{getmarking}{prendimarcatura}
+\setinterfacecommand{getnumber}{getnumber}
+\setinterfacecommand{godown}{vaigiu}
+\setinterfacecommand{goto}{vaia}
+\setinterfacecommand{gotobox}{vaiabox}
+\setinterfacecommand{gotopage}{vaiapagina}
+\setinterfacecommand{graycolor}{coloregrigio}
+\setinterfacecommand{greyvalue}{valoregrigio}
+\setinterfacecommand{grid}{griglia}
+\setinterfacecommand{hairline}{capello}
+\setinterfacecommand{head}{testa}
+\setinterfacecommand{headerdistance}{distanzaintestazione}
+\setinterfacecommand{headerheight}{altezzaintestazione}
+\setinterfacecommand{headlevel}{livellotesta}
+\setinterfacecommand{headnumber}{numerotesta}
+\setinterfacecommand{headsym}{headsym}
+\setinterfacecommand{headtext}{testoinstestazioni}
+\setinterfacecommand{hideblocks}{nascondiblocchi}
+\setinterfacecommand{high}{ap}
+\setinterfacecommand{hl}{hl}
+\setinterfacecommand{immediatebetweenlist}{immediatebetweenlist}
+\setinterfacecommand{immediatetolist}{immediatetolist}
+\setinterfacecommand{in}{in}
+\setinterfacecommand{incrementnumber}{incrementanumero}
+\setinterfacecommand{indenting}{rientro}
+\setinterfacecommand{inframed}{circondato}
+\setinterfacecommand{infull}{perlungo}
+\setinterfacecommand{ininner}{ininner}
+\setinterfacecommand{inleft}{insinistra}
+\setinterfacecommand{inleftedge}{inlatosinistro}
+\setinterfacecommand{inleftmargin}{inmarginesinistro}
+\setinterfacecommand{inline}{inriga}
+\setinterfacecommand{inmargin}{inmargine}
+\setinterfacecommand{inmframed}{inmaframed}
+\setinterfacecommand{inneredgedistance}{inneredgedistance}
+\setinterfacecommand{inneredgewidth}{inneredgewidth}
+\setinterfacecommand{innermargindistance}{innermargindistance}
+\setinterfacecommand{innermarginwidth}{innermarginwidth}
+\setinterfacecommand{inothermargin}{inaltromargine}
+\setinterfacecommand{inouter}{inouter}
+\setinterfacecommand{inright}{indestra}
+\setinterfacecommand{inrightedge}{inlatodestro}
+\setinterfacecommand{inrightmargin}{inmarginedestro}
+\setinterfacecommand{installlanguage}{installalingua}
+\setinterfacecommand{interactionbar}{barrainterazione}
+\setinterfacecommand{interactionbuttons}{pulsantinterazione}
+\setinterfacecommand{interactionmenu}{menuinterattivo}
+\setinterfacecommand{item}{elemento}
+\setinterfacecommand{items}{elementi}
+\setinterfacecommand{its}{el}
+\setinterfacecommand{keepblocks}{tieniblocchi}
+\setinterfacecommand{label}{etichetta}
+\setinterfacecommand{labels}{etichette}
+\setinterfacecommand{labeltext}{testoetichetta}
+\setinterfacecommand{language}{lingua}
+\setinterfacecommand{leftaligned}{allineasinistra}
+\setinterfacecommand{leftedgedistance}{distanzabordosinistro}
+\setinterfacecommand{leftedgewidth}{ampiezzabordosinistro}
+\setinterfacecommand{leftmargindistance}{distanzamarginesinistro}
+\setinterfacecommand{leftmarginwidth}{ampiezzamarginesinistro}
+\setinterfacecommand{leg}{leg}
+\setinterfacecommand{linewidth}{spessoreriga}
+\setinterfacecommand{listheight}{altezzaelenco}
+\setinterfacecommand{listlength}{lunghezzaelenco}
+\setinterfacecommand{listsymbol}{listsymbol}
+\setinterfacecommand{listwidth}{ampiezzaelenco}
+\setinterfacecommand{logfields}{logcampi}
+\setinterfacecommand{lohi}{pedap}
+\setinterfacecommand{low}{ped}
+\setinterfacecommand{macroname}{nome}
+\setinterfacecommand{mainlanguage}{linguaprincipale}
+\setinterfacecommand{makeupheight}{altezzamakeup}
+\setinterfacecommand{makeupwidth}{ampiezzamakeup}
+\setinterfacecommand{mar}{mar}
+\setinterfacecommand{margindistance}{distanzamargine}
+\setinterfacecommand{marginrule}{lineamargine}
+\setinterfacecommand{margintext}{testoinmargine}
+\setinterfacecommand{margintitle}{titoloinmargine}
+\setinterfacecommand{marginwidth}{ampiezzamargine}
+\setinterfacecommand{marginword}{parolainmargine}
+\setinterfacecommand{marking}{marcatura}
+\setinterfacecommand{markversion}{marcaversione}
+\setinterfacecommand{mathematics}{matematica}
+\setinterfacecommand{menubutton}{pulsantemenu}
+\setinterfacecommand{mframed}{maframed}
+\setinterfacecommand{midaligned}{allineacentro}
+\setinterfacecommand{mirror}{riflessione}
+\setinterfacecommand{month}{mese}
+\setinterfacecommand{moveformula}{spostaformula}
+\setinterfacecommand{moveongrid}{spostaagriglia}
+\setinterfacecommand{movesidefloat}{movesidefloat}
+\setinterfacecommand{navigating}{navigating}
+\setinterfacecommand{nodimension}{nientedimensioni}
+\setinterfacecommand{noheaderandfooterlines}{nientelineintestazionepdp}
+\setinterfacecommand{noindenting}{nienterientro}
+\setinterfacecommand{nolist}{nienteelenco}
+\setinterfacecommand{nomarking}{nientemarcatura}
+\setinterfacecommand{nomoreblocks}{bastablocchi}
+\setinterfacecommand{nomorefiles}{bastafile}
+\setinterfacecommand{nop}{nop}
+\setinterfacecommand{nospace}{nientespazio}
+\setinterfacecommand{note}{nota}
+\setinterfacecommand{notopandbottomlines}{nientelineecimafondo}
+\setinterfacecommand{notsmallcapped}{nocap}
+\setinterfacecommand{nowhitespace}{nientespaziobianco}
+\setinterfacecommand{numberofsubpages}{numberofsubpages}
+\setinterfacecommand{numbers}{numeri}
+\setinterfacecommand{outeredgedistance}{outeredgedistance}
+\setinterfacecommand{outeredgewidth}{outeredgewidth}
+\setinterfacecommand{outermargindistance}{outermargindistance}
+\setinterfacecommand{outermarginwidth}{outermarginwidth}
+\setinterfacecommand{packed}{impaccato}
+\setinterfacecommand{page}{pagina}
+\setinterfacecommand{pagedepth}{pagedepth}
+\setinterfacecommand{pagenumber}{numeropagina}
+\setinterfacecommand{pageoffset}{pageoffset}
+\setinterfacecommand{pagereference}{riferimentopagina}
+\setinterfacecommand{pagetype}{tipopagina}
+\setinterfacecommand{paperheight}{altezzacarta}
+\setinterfacecommand{paperwidth}{ampiezzacarta}
+\setinterfacecommand{periods}{punti}
+\setinterfacecommand{plaatsruwelijst}{placerawlist}
+\setinterfacecommand{placebookmarks}{mettisegnalibro}
+\setinterfacecommand{placecombinedlist}{mettielencocombinato}
+\setinterfacecommand{placefloat}{placefloat}
+\setinterfacecommand{placefootnotes}{mettinotepdp}
+\setinterfacecommand{placeformula}{mettiformula}
+\setinterfacecommand{placeheadnumber}{posizionanumerotesta}
+\setinterfacecommand{placeheadtext}{posizionatestotesta}
+\setinterfacecommand{placelegend}{mettilegenda}
+\setinterfacecommand{placelist}{mettielenco}
+\setinterfacecommand{placelocalfootnotes}{mettinotepdplocali}
+\setinterfacecommand{placelogos}{mettiloghi}
+\setinterfacecommand{placeongrid}{mettiingriglia}
+\setinterfacecommand{placeontopofeachother}{mettiunosullaltro}
+\setinterfacecommand{placepagenumber}{mettinumeropagina}
+\setinterfacecommand{placereferencelist}{placereferencelist}
+\setinterfacecommand{placeregister}{mettiregistro}
+\setinterfacecommand{placerule}{mettilinea}
+\setinterfacecommand{placesidebyside}{mettifiancoafianco}
+\setinterfacecommand{placesubformula}{mettisottoformula}
+\setinterfacecommand{placetextvariable}{mettivariabiletesto}
+\setinterfacecommand{position}{posizione}
+\setinterfacecommand{positiontext}{posizionatesto}
+\setinterfacecommand{printpaperheight}{altezzacartastampa}
+\setinterfacecommand{printpaperwidth}{ampiezzacartastampa}
+\setinterfacecommand{processblocks}{elaborablocchi}
+\setinterfacecommand{processpage}{elaborapagina}
+\setinterfacecommand{product}{prodotto}
+\setinterfacecommand{program}{programma}
+\setinterfacecommand{project}{progetto}
+\setinterfacecommand{publication}{pubblicazione}
+\setinterfacecommand{quotation}{citazione}
+\setinterfacecommand{quote}{menzione}
+\setinterfacecommand{ran}{ran}
+\setinterfacecommand{redo}{rifai}
+\setinterfacecommand{ref}{rif}
+\setinterfacecommand{reference}{riferimento}
+\setinterfacecommand{referral}{referral}
+\setinterfacecommand{referraldate}{datareferral}
+\setinterfacecommand{referring}{referring}
+\setinterfacecommand{remark}{commento}
+\setinterfacecommand{reset}{reimposta}
+\setinterfacecommand{resetmarking}{reimpostamarcatura}
+\setinterfacecommand{resetnumber}{resetnumber}
+\setinterfacecommand{resettext}{resettextcontent}
+\setinterfacecommand{rightaligned}{allineadestra}
+\setinterfacecommand{rightedgedistance}{distanzabordodestro}
+\setinterfacecommand{rightedgewidth}{ampiezzabordodestro}
+\setinterfacecommand{rightmargindistance}{distanzamarginedestro}
+\setinterfacecommand{rightmarginwidth}{ampiezzamarginedestro}
+\setinterfacecommand{romannumerals}{numeriromani}
+\setinterfacecommand{rotate}{ruota}
+\setinterfacecommand{scale}{scala}
+\setinterfacecommand{screen}{schermo}
+\setinterfacecommand{selectblocks}{selezionablocchi}
+\setinterfacecommand{selectpaper}{selezionacarta}
+\setinterfacecommand{selectversion}{selezionaversione}
+\setinterfacecommand{setnumber}{setnumber}
+\setinterfacecommand{settextcontent}{settext}
+\setinterfacecommand{settextvariable}{setvariabiletesto}
+\setinterfacecommand{setupalign}{impostaallineamento}
+\setinterfacecommand{setupanswerarea}{setupanswerarea}
+\setinterfacecommand{setuparranging}{impostaparranging}
+\setinterfacecommand{setupbackground}{impostasfondo}
+\setinterfacecommand{setupbackgrounds}{impostasfondi}
+\setinterfacecommand{setupblackrules}{impostalineenere}
+\setinterfacecommand{setupblank}{impostarigovuoto}
+\setinterfacecommand{setupblock}{impostablocco}
+\setinterfacecommand{setupbodyfont}{impostafontdeltesto}
+\setinterfacecommand{setupbodyfontenvironment}{impostaambientefontdeltesto}
+\setinterfacecommand{setupbottom}{impostafondo}
+\setinterfacecommand{setupbottomtexts}{impostatestifondo}
+\setinterfacecommand{setupbuffer}{impostabuffer}
+\setinterfacecommand{setupbuttons}{impostapulsanti}
+\setinterfacecommand{setupcapitals}{impostamaiuscole}
+\setinterfacecommand{setupcaption}{impostacaption}
+\setinterfacecommand{setupcaptions}{impostacaptions}
+\setinterfacecommand{setupclipping}{impostaclippling}
+\setinterfacecommand{setupcolor}{impostacolore}
+\setinterfacecommand{setupcolors}{impostacolori}
+\setinterfacecommand{setupcolumns}{impostacolonne}
+\setinterfacecommand{setupcolumnset}{impostagruppocolonne}
+\setinterfacecommand{setupcolumnsetlines}{setupcolumnsetlines}
+\setinterfacecommand{setupcolumnsetstart}{setupcolumnsetstart}
+\setinterfacecommand{setupcombinations}{impostacombinazioni}
+\setinterfacecommand{setupcombinedlist}{impostaelencocombinato}
+\setinterfacecommand{setupcomment}{impostacommento}
+\setinterfacecommand{setupdescriptions}{impostadescrizioni}
+\setinterfacecommand{setupenumerations}{impostaenumerazioni}
+\setinterfacecommand{setupexternalfigures}{impostafigureesterne}
+\setinterfacecommand{setupfield}{impostacampo}
+\setinterfacecommand{setupfields}{impostacampi}
+\setinterfacecommand{setupfillinlines}{impostarigheriempimento}
+\setinterfacecommand{setupfillinrules}{impostalineeriempimento}
+\setinterfacecommand{setupfloat}{impostaoggettomobile}
+\setinterfacecommand{setupfloats}{impostaoggettimobili}
+\setinterfacecommand{setupfloatsplitting}{impostaspezzamentooggettomobile}
+\setinterfacecommand{setupfooter}{impostapdp}
+\setinterfacecommand{setupfootertexts}{impostatestipdp}
+\setinterfacecommand{setupfootnotedefinition}{impostadefinizionenotepdp}
+\setinterfacecommand{setupfootnotes}{impostanotepdp}
+\setinterfacecommand{setupforms}{impostaforms}
+\setinterfacecommand{setupformulas}{impostaformule}
+\setinterfacecommand{setupframed}{impostaincorniciato}
+\setinterfacecommand{setupframedtexts}{impostatestiincorniciati}
+\setinterfacecommand{setuphead}{impostatesta}
+\setinterfacecommand{setupheader}{impostainstestazione}
+\setinterfacecommand{setupheadertexts}{impostatestiintestazioni}
+\setinterfacecommand{setupheadnumber}{impostanumerotesta}
+\setinterfacecommand{setupheads}{impostateste}
+\setinterfacecommand{setupheadtext}{impostatestointestazioni}
+\setinterfacecommand{setuphyphenmark}{impostasegnosillabazione}
+\setinterfacecommand{setupindentations}{impostarientri}
+\setinterfacecommand{setupindenting}{impostarientro}
+\setinterfacecommand{setupinmargin}{impostainmargine}
+\setinterfacecommand{setupinteraction}{impostainterazione}
+\setinterfacecommand{setupinteractionbar}{impostabarrainterazione}
+\setinterfacecommand{setupinteractionmenu}{impostamenuinterazione}
+\setinterfacecommand{setupinteractionscreen}{impostaschermointerazione}
+\setinterfacecommand{setupinterlinespace}{impostainterlinea}
+\setinterfacecommand{setupitemgroup}{setupitemgroup}
+\setinterfacecommand{setupitemgroups}{impostaelencazioni}
+\setinterfacecommand{setupitems}{impostaelementi}
+\setinterfacecommand{setuplabeltext}{impostatestoetichette}
+\setinterfacecommand{setuplanguage}{impostalingua}
+\setinterfacecommand{setuplayout}{impostalayout}
+\setinterfacecommand{setuplegend}{impostalegenda}
+\setinterfacecommand{setuplinenumbering}{impostanumerazionerighe}
+\setinterfacecommand{setuplines}{impostarighe}
+\setinterfacecommand{setuplinewidth}{impostaampiezzariga}
+\setinterfacecommand{setuplist}{impostaelenco}
+\setinterfacecommand{setupmakeup}{impostamakeup}
+\setinterfacecommand{setupmarginblocks}{impostablocchimargine}
+\setinterfacecommand{setupmarginrules}{impostalineemargine}
+\setinterfacecommand{setupmarking}{impostamarcatura}
+\setinterfacecommand{setupmathalignment}{setupmathalignment}
+\setinterfacecommand{setupnarrower}{impostapiustretto}
+\setinterfacecommand{setupnumber}{impostanumerazione}
+\setinterfacecommand{setupnumbering}{impostanumerazione}
+\setinterfacecommand{setupoppositeplacing}{impostaposizionamentoopposti}
+\setinterfacecommand{setupoutput}{impostaoutput}
+\setinterfacecommand{setuppagecomment}{impostacommentopagina}
+\setinterfacecommand{setuppagenumber}{impostanumeropagina}
+\setinterfacecommand{setuppagenumbering}{impostanumerazionepagina}
+\setinterfacecommand{setuppagetransitions}{impostatransizionepagina}
+\setinterfacecommand{setuppalet}{impostatavolozza}
+\setinterfacecommand{setuppaper}{setuppaper}
+\setinterfacecommand{setuppapersize}{impostadimensionicarta}
+\setinterfacecommand{setupparagraphnumbering}{impostanumerazionecapoversi}
+\setinterfacecommand{setupparagraphs}{impostacapoversi}
+\setinterfacecommand{setupplacement}{setupplacement}
+\setinterfacecommand{setuppositioning}{impostaposizionamento}
+\setinterfacecommand{setupprofiles}{impostaprofili}
+\setinterfacecommand{setupprograms}{impostaprogrammi}
+\setinterfacecommand{setuppublications}{impostapubblicazioni}
+\setinterfacecommand{setupquote}{impostamenzione}
+\setinterfacecommand{setupreferencelist}{impostalistariferimenti}
+\setinterfacecommand{setupreferencing}{impostariferimento}
+\setinterfacecommand{setupregister}{impostaregistro}
+\setinterfacecommand{setuprotate}{impostarotazione}
+\setinterfacecommand{setuprule}{impostalinea}
+\setinterfacecommand{setups}{impostazioni}
+\setinterfacecommand{setupscreens}{impostaschermi}
+\setinterfacecommand{setupsection}{impostasezione}
+\setinterfacecommand{setupsectionblock}{impostabloccosezione}
+\setinterfacecommand{setupsorting}{impostaordinamento}
+\setinterfacecommand{setupspacing}{impostaspaziatura}
+\setinterfacecommand{setupstartstop}{impostainiziatermina}
+\setinterfacecommand{setupstrut}{impostastrut}
+\setinterfacecommand{setupsubpagenumber}{impostanumerosottopagina}
+\setinterfacecommand{setupsymbolset}{impostasetsimboli}
+\setinterfacecommand{setupsynchronization}{impostasincronizzazione}
+\setinterfacecommand{setupsynchronizationbar}{impostabarrasincronizzazione}
+\setinterfacecommand{setupsynonyms}{impostasinonimi}
+\setinterfacecommand{setupsystem}{impostasistema}
+\setinterfacecommand{setuptab}{impostatab}
+\setinterfacecommand{setuptables}{impostatabelle}
+\setinterfacecommand{setuptabulate}{impostatabulato}
+\setinterfacecommand{setuptext}{impostatesto}
+\setinterfacecommand{setuptextposition}{impostaposizionetesto}
+\setinterfacecommand{setuptextrules}{impostalineetesto}
+\setinterfacecommand{setuptexttexts}{impostatestotesti}
+\setinterfacecommand{setuptextvariable}{impostavariabiletesto}
+\setinterfacecommand{setupthinrules}{impostalineesottili}
+\setinterfacecommand{setuptolerance}{impostatolleranza}
+\setinterfacecommand{setuptop}{impostacima}
+\setinterfacecommand{setuptoptexts}{impostatesticima}
+\setinterfacecommand{setuptype}{impostatype}
+\setinterfacecommand{setuptyping}{impostatyping}
+\setinterfacecommand{setupunderbar}{impostasottolinea}
+\setinterfacecommand{setupurl}{impostaurl}
+\setinterfacecommand{setupversions}{impostaversioni}
+\setinterfacecommand{setupwhitespace}{impostaspaziobianco}
+\setinterfacecommand{showbodyfont}{mostrafontdeltesto}
+\setinterfacecommand{showbodyfontenvironment}{mostraambientefontdeltesto}
+\setinterfacecommand{showcolor}{mostracolore}
+\setinterfacecommand{showcolorgroup}{mostragruppocolori}
+\setinterfacecommand{showexternalfigures}{mostrafiguresterne}
+\setinterfacecommand{showfields}{mostracampi}
+\setinterfacecommand{showframe}{mostracornice}
+\setinterfacecommand{showgrid}{mostragriglia}
+\setinterfacecommand{showlayout}{mostralyout}
+\setinterfacecommand{showmakeup}{mostramakeup}
+\setinterfacecommand{showpalet}{mostratavolozza}
+\setinterfacecommand{showprint}{mostrastampa}
+\setinterfacecommand{showsetups}{mostraimpostazioni}
+\setinterfacecommand{showstruts}{mostrastruts}
+\setinterfacecommand{showsymbolset}{mostrasetsimboli}
+\setinterfacecommand{smallcapped}{cap}
+\setinterfacecommand{someline}{qualcheriga}
+\setinterfacecommand{somewhere}{daqualcheparte}
+\setinterfacecommand{space}{spazio}
+\setinterfacecommand{splitfloat}{spezzaoggettomobile}
+\setinterfacecommand{startalignment}{iniziaallineamento}
+\setinterfacecommand{startbackground}{iniziasfondo}
+\setinterfacecommand{startcoding}{iniziacodifica}
+\setinterfacecommand{startcolor}{iniziacolore}
+\setinterfacecommand{startcolumnmakeup}{startcolumnmakeup}
+\setinterfacecommand{startcolumns}{iniziacolonne}
+\setinterfacecommand{startcolumnset}{iniziagruppocolonne}
+\setinterfacecommand{startcombination}{iniziacombinazione}
+\setinterfacecommand{startcomponent}{iniziacomponente}
+\setinterfacecommand{startdocument}{iniziadocumento}
+\setinterfacecommand{startenvironment}{iniziaambiente}
+\setinterfacecommand{startfigure}{iniziafigura}
+\setinterfacecommand{startglobal}{iniziaglobale}
+\setinterfacecommand{startline}{iniziariga}
+\setinterfacecommand{startlinecorrection}{iniziacorrezioneriga}
+\setinterfacecommand{startlinenumbering}{inizianumerazionerighe}
+\setinterfacecommand{startlines}{iniziarighe}
+\setinterfacecommand{startlocal}{inizialocale}
+\setinterfacecommand{startlocalfootnotes}{inizianotepdplocali}
+\setinterfacecommand{startmakeup}{iniziamakeup}
+\setinterfacecommand{startmarginblock}{iniziabloccomargine}
+\setinterfacecommand{startmarginrule}{inizialineamargine}
+\setinterfacecommand{startnarrower}{iniziapiustretto}
+\setinterfacecommand{startopposite}{iniziaopposto}
+\setinterfacecommand{startoverlay}{iniziasovrapposizione}
+\setinterfacecommand{startoverzicht}{iniziaoverview}
+\setinterfacecommand{startpacked}{iniziaimpaccato}
+\setinterfacecommand{startpositioning}{iniziaposizionamento}
+\setinterfacecommand{startproduct}{iniziaprodotto}
+\setinterfacecommand{startprofile}{iniziaprofilo}
+\setinterfacecommand{startproject}{iniziaprogetto}
+\setinterfacecommand{startquotation}{iniziacitazione}
+\setinterfacecommand{startraster}{iniziaraster}
+\setinterfacecommand{startsymbolset}{iniziasetsimboli}
+\setinterfacecommand{startsynchronization}{iniziasincronizzazione}
+\setinterfacecommand{starttable}{iniziatabella}
+\setinterfacecommand{starttables}{iniziatabelle}
+\setinterfacecommand{starttext}{iniziatesto}
+\setinterfacecommand{starttextrule}{inizialineatesto}
+\setinterfacecommand{startunpacked}{iniziaunpacked}
+\setinterfacecommand{startversion}{iniziaversione}
+\setinterfacecommand{stopalignment}{terminaallineamento}
+\setinterfacecommand{stopbackground}{terminasfondo}
+\setinterfacecommand{stopcoding}{terminacodifica}
+\setinterfacecommand{stopcolor}{terminacolore}
+\setinterfacecommand{stopcolumnmakeup}{stopcolumnmakeup}
+\setinterfacecommand{stopcolumns}{terminacolonne}
+\setinterfacecommand{stopcolumnset}{terminagruppocolonne}
+\setinterfacecommand{stopcombination}{terminacombinazione}
+\setinterfacecommand{stopcomponent}{terminacomponente}
+\setinterfacecommand{stopdocument}{terminadocumento}
+\setinterfacecommand{stopenvironment}{terminaambiente}
+\setinterfacecommand{stopglobal}{terminaglobale}
+\setinterfacecommand{stopline}{terminariga}
+\setinterfacecommand{stoplinecorrection}{terminacorrezioneriga}
+\setinterfacecommand{stoplinenumbering}{terminanumerazionerighe}
+\setinterfacecommand{stoplines}{terminarighe}
+\setinterfacecommand{stoplocal}{terminalocale}
+\setinterfacecommand{stoplocalfootnotes}{terminanotepdplocali}
+\setinterfacecommand{stopmakeup}{terminamakeup}
+\setinterfacecommand{stopmarginblock}{terminabloccomargine}
+\setinterfacecommand{stopmarginrule}{terminalineamargine}
+\setinterfacecommand{stopnarrower}{terminapiustretto}
+\setinterfacecommand{stopopposite}{terminaopposto}
+\setinterfacecommand{stopoverlay}{terminasovrapposizione}
+\setinterfacecommand{stopoverzicht}{terminaoverview}
+\setinterfacecommand{stoppacked}{terminaimpaccato}
+\setinterfacecommand{stoppositioning}{terminaposizionamento}
+\setinterfacecommand{stopproduct}{terminaprodotto}
+\setinterfacecommand{stopprofile}{terminaprofili}
+\setinterfacecommand{stopproject}{terminaprogetto}
+\setinterfacecommand{stopquotation}{terminacitazione}
+\setinterfacecommand{stopraster}{terminaraster}
+\setinterfacecommand{stopsynchronization}{terminasincronizzazione}
+\setinterfacecommand{stoptable}{terminatabella}
+\setinterfacecommand{stoptables}{terminatabelle}
+\setinterfacecommand{stoptext}{terminatesto}
+\setinterfacecommand{stoptextrule}{terminalineatesto}
+\setinterfacecommand{stopunpacked}{terminaunpacked}
+\setinterfacecommand{stopversion}{terminaversioni}
+\setinterfacecommand{stretched}{stirato}
+\setinterfacecommand{subformulanumber}{numerosottoformula}
+\setinterfacecommand{subpagenumber}{subpagenumber}
+\setinterfacecommand{switchtobodyfont}{cambiaafontdeltesto}
+\setinterfacecommand{switchtorawfont}{passaafontgrezzo}
+\setinterfacecommand{sym}{sim}
+\setinterfacecommand{symbol}{simbolo}
+\setinterfacecommand{synchronizationbar}{barrasincronizzazione}
+\setinterfacecommand{synchronize}{sincronizza}
+\setinterfacecommand{tab}{tab}
+\setinterfacecommand{testcolumn}{testcolumn}
+\setinterfacecommand{testpage}{testpage}
+\setinterfacecommand{tex}{tex}
+\setinterfacecommand{textheight}{altezzatesto}
+\setinterfacecommand{textreference}{riferimentotesto}
+\setinterfacecommand{textrule}{lineatesto}
+\setinterfacecommand{textvariable}{variabiletesto}
+\setinterfacecommand{textwidth}{ampiezzatesto}
+\setinterfacecommand{thinrule}{lineasottile}
+\setinterfacecommand{thinrules}{lineesottili}
+\setinterfacecommand{tooltip}{tooltip}
+\setinterfacecommand{topdistance}{distanzacima}
+\setinterfacecommand{topheight}{altezzacima}
+\setinterfacecommand{topspace}{spaziocima}
+\setinterfacecommand{totalnumberofpages}{numerototaledipagine}
+\setinterfacecommand{translate}{traduci}
+\setinterfacecommand{txt}{txt}
+\setinterfacecommand{typ}{typ}
+\setinterfacecommand{type}{type}
+\setinterfacecommand{typebuffer}{typebuffer}
+\setinterfacecommand{typefile}{typefile}
+\setinterfacecommand{unitmeaning}{nomeunita}
+\setinterfacecommand{unknown}{ignoto}
+\setinterfacecommand{useJSscripts}{usaJSscripts}
+\setinterfacecommand{useURL}{usaURL}
+\setinterfacecommand{useXMLfilter}{useXMLfilter}
+\setinterfacecommand{useblocks}{usablocco}
+\setinterfacecommand{usecommands}{usacomandi}
+\setinterfacecommand{useencoding}{usacodifica}
+\setinterfacecommand{useexternaldocument}{usadocumentoesterno}
+\setinterfacecommand{useexternalfigure}{usafiguraesterna}
+\setinterfacecommand{useexternalfile}{usafileesterno}
+\setinterfacecommand{useexternalfiles}{usafileesterni}
+\setinterfacecommand{useexternalsoundtrack}{usacolonnasonoraesterna}
+\setinterfacecommand{usemodule}{usamodulo}
+\setinterfacecommand{usemodules}{usamoduli}
+\setinterfacecommand{usepath}{usacartella}
+\setinterfacecommand{usereferences}{usariferimenti}
+\setinterfacecommand{usespecials}{usaspecialita}
+\setinterfacecommand{usesymbols}{usasimboli}
+\setinterfacecommand{usetypescript}{usetypescript}
+\setinterfacecommand{usetypescriptfile}{usetypescriptfile}
+\setinterfacecommand{useurl}{usaurl}
+\setinterfacecommand{version}{versione}
+\setinterfacecommand{vl}{vl}
+\setinterfacecommand{weekday}{giornosettimana}
+\setinterfacecommand{whitespace}{spaziobianco}
+\setinterfacecommand{wordright}{paroladestra}
+\setinterfacecommand{writebetweenlist}{scrividentroelenco}
+\setinterfacecommand{writetolist}{scriviinelenco}
+\setinterfacecommand{writetoreferencelist}{scriviinlistariferimenti}
+\setinterfacecommand{writetoregister}{scriviinregistro}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mcs.tex b/tex/context/base/mult-mcs.tex
new file mode 100644
index 000000000..98c392c9f
--- /dev/null
+++ b/tex/context/base/mult-mcs.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{neznama reference --}
+\setinterfacemessage{references}{3}{neznamy typ reference --}
+\setinterfacemessage{references}{2}{duplicitni reference -- na strane --}
+\setinterfacemessage{references}{4}{nedovolena reference --}
+\setinterfacemessage{references}{30}{neznamy objekt --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{reference}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{duplicitni object --}
+\setinterfacemessage{references}{21}{dokument -- nacten}
+\setinterfacemessage{references}{22}{dokument -- neni interaktivni}
+\setinterfacemessage{references}{23}{obskurni (nejasna) reference -- (prefix=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{number --}
+\setinterfacemessage{handlings}{1}{font handling --}
+\setinterfacemessage{handlings}{3}{unknown font handling --}
+\setinterfacemessage{handlings}{2}{font handling -- is loaded}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{system}
+\setinterfacemessage{systems}{41}{externi soubor -- ve skupine -- neexistuje}
+\setinterfacemessage{systems}{9}{-- nenalezeno/nezpracovano}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{nova verze pomocneho souboru, je treba druheho behu}
+\setinterfacemessage{systems}{21}{pomocny soubor necten}
+\setinterfacemessage{systems}{20}{vyznam (trideni) -- nacten}
+\setinterfacemessage{systems}{5}{makra z -- nactena}
+\setinterfacemessage{systems}{4}{prikaz -- je jiz definovan}
+\setinterfacemessage{systems}{27}{verze}
+\setinterfacemessage{systems}{26}{registry}
+\setinterfacemessage{systems}{25}{reference}
+\setinterfacemessage{systems}{24}{plovouci bloky}
+\setinterfacemessage{systems}{1}{nacteni pomocneho souboru odlozeno (typemode)}
+\setinterfacemessage{systems}{23}{-- upraveno na --}
+\setinterfacemessage{systems}{22}{pouzijte platny pomocny soubor}
+\setinterfacemessage{systems}{2}{-- nacteno}
+\setinterfacemessage{systems}{19}{vyznam (synonyma) -- nacten}
+\setinterfacemessage{systems}{18}{synonymum -- -- neexistuje}
+\setinterfacemessage{systems}{7}{makra z -- jsou jiz nactena}
+\setinterfacemessage{systems}{6}{zadna makra v -- nenalezena}
+\setinterfacemessage{systems}{14}{vynucena nova stranka v seznamu na --}
+\setinterfacemessage{systems}{15}{uklada se buffer --}
+\setinterfacemessage{systems}{16}{sazi se buffer --}
+\setinterfacemessage{systems}{17}{sazi se doslovny (verbatim) buffer --}
+\setinterfacemessage{systems}{13}{znacka -- definovana --}
+\setinterfacemessage{systems}{12}{pomosny soubor neni setriden, pouzijte texutil}
+\setinterfacemessage{systems}{11}{vytvarim jednoduchy pomocny soubor}
+\setinterfacemessage{systems}{10}{nepouzivejte em v --}
+\setinterfacemessage{floatblocks}{1}{-- precislovano / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- presunuto}
+\setinterfacemessage{floatblocks}{2}{-- ulozeno}
+\setinterfacemessage{floatblocks}{5}{poradi prizpusobeno}
+\setinterfacemessage{floatblocks}{4}{-- umisteno}
+\setinterfacemessage{floatblocks}{7}{pocet spodnich plovoucich objektu je omezen na --}
+\setinterfacemessage{floatblocks}{6}{pocet hornich plovoucich objektu je omezen na --}
+\setinterfacemessage{floatblocks}{9}{poradi naruseno}
+\setinterfacemessage{floatblocks}{8}{radku je mene nez --}
+\setinterfacemessage{floatblocks}{title}{plovouciobjekty}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{nedefinovano}
+\setinterfacemessage{floatblocks}{11}{nedan zadny blok}
+\setinterfacemessage{floatblocks}{10}{-- omezeno}
+\setinterfacemessage{interactions}{1}{pomer -- x -- (s x v)}
+\setinterfacemessage{interactions}{3}{neaktivni}
+\setinterfacemessage{interactions}{2}{aktivni}
+\setinterfacemessage{interactions}{5}{unknown attachment --}
+\setinterfacemessage{interactions}{4}{zadna strankova synchronizace (--) v hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- does not exist}
+\setinterfacemessage{interactions}{title}{interakce}
+\setinterfacemessage{interactions}{21}{-- kod vlozen}
+\setinterfacemessage{regimes}{1}{kodovani --}
+\setinterfacemessage{regimes}{3}{nezname kodovani --}
+\setinterfacemessage{regimes}{2}{je nacteno kodovani --}
+\setinterfacemessage{regimes}{title}{kodovani}
+\setinterfacemessage{structures}{1}{zacatek oddilu (sekce) --}
+\setinterfacemessage{structures}{title}{struktury}
+\setinterfacemessage{structures}{2}{konec oddilu (sekce) --}
+\setinterfacemessage{linguals}{1}{vzory -- pro -- nacteny (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{deleni slov -- pro -- nacteno (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{zadne vzory -- pro -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{vzory pro -- nenacteny}
+\setinterfacemessage{linguals}{4}{zadne deleni slov -- pro -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{specificke volby jazyka [--] zavadeji -- (zavlecenou) mezeru}
+\setinterfacemessage{linguals}{6}{jazyk -- neni definovan}
+\setinterfacemessage{linguals}{9}{language -- is active}
+\setinterfacemessage{linguals}{8}{specificke volby jazyka [--] bez mezer pripojeny}
+\setinterfacemessage{linguals}{title}{jazyky}
+\setinterfacemessage{linguals}{10}{vzory --nacteny}
+\setinterfacemessage{verbatims}{1}{soubor -- neexistuje}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{filter -- is loaded}
+\setinterfacemessage{filters}{title}{filter}
+\setinterfacemessage{filters}{2}{unknown filter --}
+\setinterfacemessage{textblocks}{1}{nova verze, je treba druhy beh}
+\setinterfacemessage{textblocks}{3}{ctu bloky z --}
+\setinterfacemessage{textblocks}{2}{zapisuji bloky do --}
+\setinterfacemessage{textblocks}{5}{-- neni skryto}
+\setinterfacemessage{textblocks}{4}{je treba druhy beh}
+\setinterfacemessage{textblocks}{7}{-- skryto}
+\setinterfacemessage{textblocks}{6}{-- skryto a zpracovano}
+\setinterfacemessage{textblocks}{9}{-- nevysazeno}
+\setinterfacemessage{textblocks}{8}{-- vysazeno}
+\setinterfacemessage{textblocks}{title}{textovyblok}
+\setinterfacemessage{textblocks}{12}{-- preskoceno}
+\setinterfacemessage{textblocks}{11}{-- nacteno a vysazeno}
+\setinterfacemessage{textblocks}{10}{-- nacteno a zpracovano}
+\setinterfacemessage{encodings}{1}{kodovani --}
+\setinterfacemessage{encodings}{3}{nezname kodovani --}
+\setinterfacemessage{encodings}{2}{je nacteno kodovani --}
+\setinterfacemessage{encodings}{title}{kodovani}
+\setinterfacemessage{columns}{1}{je mozno pouze -- sloupcu}
+\setinterfacemessage{columns}{3}{problem, vypina se vyvazovani}
+\setinterfacemessage{columns}{2}{pouzijte \string\filbreak\space jako alternativu}
+\setinterfacemessage{columns}{5}{spodni plovouci objekt jeste neni podporovan}
+\setinterfacemessage{columns}{4}{horni plovouci objekt jeste neni podporovan}
+\setinterfacemessage{columns}{7}{vyvazovani ukonceno po 100 krocich}
+\setinterfacemessage{columns}{6}{-- plovouci objekt(y) odlozeny}
+\setinterfacemessage{columns}{9}{kontrola nerovnost}
+\setinterfacemessage{columns}{8}{vyvazeno v -- krocich}
+\setinterfacemessage{columns}{title}{sloupce}
+\setinterfacemessage{columns}{13}{siroky plovouci objekt je presunut nad sloupce}
+\setinterfacemessage{columns}{12}{plovouci objekt je presunut do nasledujiciho sloupce / --}
+\setinterfacemessage{columns}{11}{plovouci objekt je pro sloupec prilis siroky}
+\setinterfacemessage{columns}{10}{zbyl (mene nez) 1 radek}
+\setinterfacemessage{symbols}{1}{nacita se soubor symbolu --}
+\setinterfacemessage{symbols}{title}{symboly}
+\setinterfacemessage{files}{1}{synonymum souboru -- je jiz pouzito pro --}
+\setinterfacemessage{files}{title}{soubory}
+\setinterfacemessage{versions}{1}{postradam @+}
+\setinterfacemessage{versions}{3}{oznacene strany: --}
+\setinterfacemessage{versions}{2}{oznacuji se strany}
+\setinterfacemessage{versions}{title}{verze}
+\setinterfacemessage{specials}{1}{-- nacteno}
+\setinterfacemessage{specials}{3}{-- je resetovano}
+\setinterfacemessage{specials}{2}{neni dovoleno hlubsi zanoreni --}
+\setinterfacemessage{specials}{5}{nacita se definicni soubor --}
+\setinterfacemessage{specials}{4}{prikaz -- neexistuje}
+\setinterfacemessage{specials}{7}{neznamy ovladac (driver) --}
+\setinterfacemessage{specials}{6}{zanoreni neni dovoleno}
+\setinterfacemessage{specials}{title}{speciality}
+\setinterfacemessage{layouts}{1}{vyska textu prizpusobena s -- na strane --}
+\setinterfacemessage{layouts}{3}{-- krat text odlozen}
+\setinterfacemessage{layouts}{2}{-- krat odlozeny text umisten}
+\setinterfacemessage{layouts}{5}{okrajove bloky neaktivni}
+\setinterfacemessage{layouts}{4}{okrajove bloky aktivni}
+\setinterfacemessage{layouts}{7}{pocita se misto pro logo}
+\setinterfacemessage{layouts}{6}{sada stran -- zpracovana (velikost --)}
+\setinterfacemessage{layouts}{9}{aktualne ne vice nez -- urovne/urovni vyctu}
+\setinterfacemessage{layouts}{8}{pocita se pozadi}
+\setinterfacemessage{layouts}{title}{layout}
+\setinterfacemessage{layouts}{11}{svisla mezera -- neni povolena v pevnem radkovem rejstriku}
+\setinterfacemessage{layouts}{10}{-- a -- nedava dohromady 1.0}
+\setinterfacemessage{fonts}{1}{kodovani --}
+\setinterfacemessage{fonts}{3}{neznama varianta --}
+\setinterfacemessage{fonts}{2}{varianta -- je nactena}
+\setinterfacemessage{fonts}{5}{styl -- neni definovan}
+\setinterfacemessage{fonts}{4}{zakladni font -- neni definovan}
+\setinterfacemessage{fonts}{7}{neznamy format --}
+\setinterfacemessage{fonts}{6}{-- je nacten}
+\setinterfacemessage{fonts}{14}{bodyfont -- is defined (can better be done global)}
+\setinterfacemessage{fonts}{8}{styl -- definovan}
+\setinterfacemessage{fonts}{title}{zakladnifont}
+\setinterfacemessage{fonts}{10}{neznamy font --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{global file --}
+\setinterfacemessage{databases}{2}{local file --}
+\setinterfacemessage{databases}{4}{unknown file --}
+\setinterfacemessage{databases}{title}{databases}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{nacita se soubor skriptu --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{neznama preambule --}
+\setinterfacemessage{check}{1}{postradam '=' po '--' na radku --}
+\setinterfacemessage{check}{3}{-- -- nahrazuje makro, uzijte VERZALKY!}
+\setinterfacemessage{check}{2}{ocekavam -- argument(y) na radku --}
+\setinterfacemessage{check}{title}{kontrola}
+\setinterfacemessage{metapost}{1}{loading metapost library --}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{obraz -- nelze nalezt}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{obraz -- nepritomen}
+\setinterfacemessage{figures}{5}{dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{dimenze obrazu -- nacteny primo z jeho souboru}
+\setinterfacemessage{figures}{6}{dimenze obrazu -- spocteny programem rlxtools}
+\setinterfacemessage{figures}{8}{obrazovy objekt -- je znovu pouzit}
+\setinterfacemessage{figures}{title}{obrazy}
+\setinterfacemessage{colors}{1}{system -- je globalne aktivovana}
+\setinterfacemessage{colors}{3}{-- neni definovana --}
+\setinterfacemessage{colors}{2}{system -- je lokalne activovana}
+\setinterfacemessage{colors}{5}{neznamy system --}
+\setinterfacemessage{colors}{4}{system -- je nacten}
+\setinterfacemessage{colors}{7}{palette -- neni k dispozici}
+\setinterfacemessage{colors}{6}{palette -- je k dispozici}
+\setinterfacemessage{colors}{9}{-- prostor barev neni podporovan}
+\setinterfacemessage{colors}{8}{specifikace -- v barve -- bude cerna}
+\setinterfacemessage{colors}{title}{barva}
+\setinterfacemessage{colors}{12}{-- is registered}
+\setinterfacemessage{colors}{11}{barva je prevedena na sed}
+\setinterfacemessage{colors}{10}{-- prostor barev je podporovan}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mde.tex b/tex/context/base/mult-mde.tex
new file mode 100644
index 000000000..4da89ba33
--- /dev/null
+++ b/tex/context/base/mult-mde.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{unbekannte Referenz --}
+\setinterfacemessage{references}{3}{unbekannte Referenz Typ --}
+\setinterfacemessage{references}{2}{doppelte Referenz -- auf Seite --}
+\setinterfacemessage{references}{4}{illegale Referenz --}
+\setinterfacemessage{references}{30}{unbekanntes Object --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{referenzen}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{doppeltes Object --}
+\setinterfacemessage{references}{21}{Dokument -- geladen}
+\setinterfacemessage{references}{22}{Dokument -- ist nicht aktiv}
+\setinterfacemessage{references}{23}{Obskure Referenz -- (Prefix=--)}
+\setinterfacemessage{documents}{1}{Blatt --}
+\setinterfacemessage{documents}{title}{Blaetter}
+\setinterfacemessage{documents}{2}{Nummer --}
+\setinterfacemessage{handlings}{1}{Font Verarbeitung --}
+\setinterfacemessage{handlings}{3}{unknown font handling --}
+\setinterfacemessage{handlings}{2}{Font Verarbeitung -- ist geladen}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{system}
+\setinterfacemessage{systems}{41}{Externe Datei -- in Gruppe -- existiert nicht}
+\setinterfacemessage{systems}{9}{-- nicht gefunden/verarbeitet}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{Neue Version der Hilfsdatei, zweiter Durchlauf benoetigt}
+\setinterfacemessage{systems}{21}{Die Hilfsdatei ist nicht geladen}
+\setinterfacemessage{systems}{20}{Bedeutung (sortieren) von -- geladen}
+\setinterfacemessage{systems}{5}{Modul -- geladen}
+\setinterfacemessage{systems}{4}{Befehl -- ist bereits definiert}
+\setinterfacemessage{systems}{27}{Version}
+\setinterfacemessage{systems}{26}{Register}
+\setinterfacemessage{systems}{25}{Referenzen}
+\setinterfacemessage{systems}{24}{Fliessbloecke}
+\setinterfacemessage{systems}{1}{Laden der Hilfsdatei aufgeschoben (Eingabe-Modus)}
+\setinterfacemessage{systems}{23}{-- angeordnet auf --}
+\setinterfacemessage{systems}{22}{Benoetige gueltige Hilfsdateie}
+\setinterfacemessage{systems}{2}{-- geladen}
+\setinterfacemessage{systems}{19}{Bedeutung (synonyme) von -- geladen}
+\setinterfacemessage{systems}{18}{Synonym -- -- existiert nicht}
+\setinterfacemessage{systems}{7}{Modul -- bereits geladen}
+\setinterfacemessage{systems}{6}{Modul -- gefunden}
+\setinterfacemessage{systems}{14}{Erzwungendes Seitenumbruch in Liste bei --}
+\setinterfacemessage{systems}{15}{Speichere Buffer --}
+\setinterfacemessage{systems}{16}{Setzte Buffer --}
+\setinterfacemessage{systems}{17}{Setzte tippen-Buffer --}
+\setinterfacemessage{systems}{13}{Beschriftung -- definiert --}
+\setinterfacemessage{systems}{12}{Die Hilfdatei ist nicht sortiert, verwende texutil}
+\setinterfacemessage{systems}{11}{Erstelle einfache Hilfdatei}
+\setinterfacemessage{systems}{10}{Benutzte kein em in --}
+\setinterfacemessage{floatblocks}{1}{-- neu nummeriert / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- verschoben}
+\setinterfacemessage{floatblocks}{2}{-- gespeichert}
+\setinterfacemessage{floatblocks}{5}{Reihenfolge angepasst}
+\setinterfacemessage{floatblocks}{4}{-- plaziert}
+\setinterfacemessage{floatblocks}{7}{Anz. der unteren Gleitobjekte beschraengt auf --}
+\setinterfacemessage{floatblocks}{6}{Anz. der oberen Gleitobjekte beschraengt auf --}
+\setinterfacemessage{floatblocks}{9}{Reigenfolge gestoert}
+\setinterfacemessage{floatblocks}{8}{weniger als -- zeilen}
+\setinterfacemessage{floatblocks}{title}{Gleitobjektbloecke}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{undefiniert}
+\setinterfacemessage{floatblocks}{11}{kein Block gegeben}
+\setinterfacemessage{floatblocks}{10}{-- begrenzt}
+\setinterfacemessage{interactions}{1}{Seitenverhaeltnis -- x -- (B x H)}
+\setinterfacemessage{interactions}{3}{inaktiv}
+\setinterfacemessage{interactions}{2}{aktiv}
+\setinterfacemessage{interactions}{5}{unknown attachment --}
+\setinterfacemessage{interactions}{4}{keine Seitensynchronisation (--) im hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- does not exist}
+\setinterfacemessage{interactions}{title}{Interaktion}
+\setinterfacemessage{interactions}{21}{-- Code eingefuegt}
+\setinterfacemessage{regimes}{1}{Kodierung --}
+\setinterfacemessage{regimes}{3}{Unbekannte Kodierung --}
+\setinterfacemessage{regimes}{2}{Kodierung -- ist geladen}
+\setinterfacemessage{regimes}{title}{Kodierung}
+\setinterfacemessage{structures}{1}{Begin des Abschnittsblocks --}
+\setinterfacemessage{structures}{title}{struktur}
+\setinterfacemessage{structures}{2}{Ende des Abschnittsblocks --}
+\setinterfacemessage{linguals}{1}{Trennmuster -- fuer -- geladen (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{Trenndefinitionen -- fuer -- geladen (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{Keine Trennmuster -- fuer -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{Trennmuster fuer -- nicht geladen}
+\setinterfacemessage{linguals}{4}{Keine Trenndefinitionen -- fuer -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{Sprachenspezifische Option [--] fuegt eine Luecke von -- ein}
+\setinterfacemessage{linguals}{6}{Sprache -- ist undefiniert}
+\setinterfacemessage{linguals}{9}{Sprache -- ist aktiv}
+\setinterfacemessage{linguals}{8}{Sprachenspezifische Option [--] nahtlos hinzugefuegt}
+\setinterfacemessage{linguals}{title}{Sprache}
+\setinterfacemessage{linguals}{10}{Trennmuster --geladen}
+\setinterfacemessage{verbatims}{1}{Datei -- existiert nicht}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{filter -- ist geladen}
+\setinterfacemessage{filters}{title}{filter}
+\setinterfacemessage{filters}{2}{unknown filter --}
+\setinterfacemessage{textblocks}{1}{neue Version, zweiter Durchlauf benoetigt}
+\setinterfacemessage{textblocks}{3}{lese Bloecke von --}
+\setinterfacemessage{textblocks}{2}{schreibe Bloecke zu --}
+\setinterfacemessage{textblocks}{5}{-- nicht verborgen}
+\setinterfacemessage{textblocks}{4}{zweiter Durchlauf benoetigt}
+\setinterfacemessage{textblocks}{7}{-- verborgen}
+\setinterfacemessage{textblocks}{6}{-- verborgen und verarbeitet}
+\setinterfacemessage{textblocks}{9}{-- nicht gesetzt}
+\setinterfacemessage{textblocks}{8}{-- gesetzt}
+\setinterfacemessage{textblocks}{title}{textblock}
+\setinterfacemessage{textblocks}{12}{-- ausgelassen}
+\setinterfacemessage{textblocks}{11}{-- geladen und gesetzt}
+\setinterfacemessage{textblocks}{10}{-- geladen und verarbeitet}
+\setinterfacemessage{encodings}{1}{Kodierung --}
+\setinterfacemessage{encodings}{3}{Unbekannte Kodierung --}
+\setinterfacemessage{encodings}{2}{Kodierung -- ist geladen}
+\setinterfacemessage{encodings}{title}{Kodierung}
+\setinterfacemessage{columns}{1}{nur -- Spalten moeglich}
+\setinterfacemessage{columns}{3}{Problem, verwende [ausgleich=nein]}
+\setinterfacemessage{columns}{2}{benutzte \string\filbreak\space als Alternative}
+\setinterfacemessage{columns}{5}{Gleitobjekt unten ncoh nicht unterstuetzt}
+\setinterfacemessage{columns}{4}{Gleitobjekt oben ncoh nicht unterstuetzt}
+\setinterfacemessage{columns}{7}{ausgleich nach 100 Schritten abgebrocheb}
+\setinterfacemessage{columns}{6}{-- Gleitobjekt(e) verschoben}
+\setinterfacemessage{columns}{9}{Ausrichtung ueberpruefen}
+\setinterfacemessage{columns}{8}{ausgeglichen nach -- Schritt(en)}
+\setinterfacemessage{columns}{title}{Spalten}
+\setinterfacemessage{columns}{13}{breites Gleitobjekt an den Anfang der Spalten verschoben}
+\setinterfacemessage{columns}{12}{Gleitobjekt in naechste Zeile verschoben / --}
+\setinterfacemessage{columns}{11}{Gleitobjekt zu breit fuer Spalte}
+\setinterfacemessage{columns}{10}{(weniger als) 1 Zeile uebrig}
+\setinterfacemessage{symbols}{1}{Lade Symboldatei --}
+\setinterfacemessage{symbols}{title}{Symbole}
+\setinterfacemessage{files}{1}{Dateisynonym -- wird bereits fuer -- benutzt}
+\setinterfacemessage{files}{title}{files}
+\setinterfacemessage{versions}{1}{fehlendes @+}
+\setinterfacemessage{versions}{3}{Ausgewaehlte Seiten: --}
+\setinterfacemessage{versions}{2}{Erstelle Seiten}
+\setinterfacemessage{versions}{title}{Version}
+\setinterfacemessage{specials}{1}{-- geladen}
+\setinterfacemessage{specials}{3}{-- ist zurueckgesetzt}
+\setinterfacemessage{specials}{2}{keine tiefere Verschachtelung erlaubt --}
+\setinterfacemessage{specials}{5}{lade Definitionsdatei --}
+\setinterfacemessage{specials}{4}{Befehl -- existiert nicht}
+\setinterfacemessage{specials}{7}{unbekante Driver --}
+\setinterfacemessage{specials}{6}{Verschachtelung nicht erlaubt}
+\setinterfacemessage{specials}{title}{spezielles}
+\setinterfacemessage{layouts}{1}{Texthoehe angepasst mit -- auf Seite --}
+\setinterfacemessage{layouts}{3}{-- mal Text verschoben}
+\setinterfacemessage{layouts}{2}{-- mal verschobener Text plaziert}
+\setinterfacemessage{layouts}{5}{marginalbloecke inaktiv}
+\setinterfacemessage{layouts}{4}{marginalbloecke aktiv}
+\setinterfacemessage{layouts}{7}{berechne Platzbedarf des Logos}
+\setinterfacemessage{layouts}{6}{Unterseitenfolge -- verarbeitet (Groesse --)}
+\setinterfacemessage{layouts}{9}{z.Z. nicht mehr als -- Ebenen in Aufzaehlungen}
+\setinterfacemessage{layouts}{8}{berechne Hintergrund}
+\setinterfacemessage{layouts}{title}{Layout}
+\setinterfacemessage{layouts}{11}{Zwischenraum -- nicht im Grittermoduserlau}
+\setinterfacemessage{layouts}{10}{-- und -- ergeben zusammen nicht 1.0}
+\setinterfacemessage{fonts}{1}{Kodierung --}
+\setinterfacemessage{fonts}{3}{Unbekannte Variante --}
+\setinterfacemessage{fonts}{2}{Variante -- ist geladen}
+\setinterfacemessage{fonts}{5}{Stil -- ist nicht definiert}
+\setinterfacemessage{fonts}{4}{Fliesstext -- ist nicht definiert}
+\setinterfacemessage{fonts}{7}{unbekanntes Format --}
+\setinterfacemessage{fonts}{6}{-- ist geladen}
+\setinterfacemessage{fonts}{14}{Fliesstext -- wurde definiert (besser waere globale Definition)}
+\setinterfacemessage{fonts}{8}{Stil -- definiert}
+\setinterfacemessage{fonts}{title}{Fliesstext}
+\setinterfacemessage{fonts}{10}{unbekanntes Font --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{globale Datei --}
+\setinterfacemessage{databases}{2}{lokale Datei --}
+\setinterfacemessage{databases}{4}{unbekannte Datei --}
+\setinterfacemessage{databases}{title}{Datenbank}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{Lade Scriptdatei --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{unbekannte Preamble --}
+\setinterfacemessage{check}{1}{Fehlendes '=' nach '--' in Zeile --}
+\setinterfacemessage{check}{3}{-- -- ersetzt ein Makro, verwende VERSALIEN!}
+\setinterfacemessage{check}{2}{-- Argument(e) in Zeile -- erwartet}
+\setinterfacemessage{check}{title}{check}
+\setinterfacemessage{metapost}{1}{Lade metapost Bibliothek --}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{Abbildung -- kann nicht gefunden werden}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{Abbildung -- wird nicht erstellt}
+\setinterfacemessage{figures}{5}{Dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{Dimensionen von -- geladen aus der Abbildungsdatei selbst}
+\setinterfacemessage{figures}{6}{Dimensionen von -- ausgerechnet durch rlxtools}
+\setinterfacemessage{figures}{8}{Abbildungobjekt -- wurde wiederverwandt}
+\setinterfacemessage{figures}{title}{Abbildungen}
+\setinterfacemessage{colors}{1}{system -- ist global aktiviert}
+\setinterfacemessage{colors}{3}{-- ist undefiniert --}
+\setinterfacemessage{colors}{2}{system -- ist lokal aktiviert}
+\setinterfacemessage{colors}{5}{unbekanntes System --}
+\setinterfacemessage{colors}{4}{system -- ist geladen}
+\setinterfacemessage{colors}{7}{palette -- ist nicht verfuegbar}
+\setinterfacemessage{colors}{6}{palette -- ist verfuegbar}
+\setinterfacemessage{colors}{9}{-- Farbraum wird nicht unterstuetzt}
+\setinterfacemessage{colors}{8}{Spezifikation -- bei Farbe -- wird schwarz}
+\setinterfacemessage{colors}{title}{farbe}
+\setinterfacemessage{colors}{12}{-- is registered}
+\setinterfacemessage{colors}{11}{Farbe wird in Grau umgewandelt}
+\setinterfacemessage{colors}{10}{-- Farbraum wird unterstuetzt}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-men.tex b/tex/context/base/mult-men.tex
new file mode 100644
index 000000000..4c1bc9942
--- /dev/null
+++ b/tex/context/base/mult-men.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{unknown reference --}
+\setinterfacemessage{references}{3}{unknown reference type --}
+\setinterfacemessage{references}{2}{duplicate reference -- on page --}
+\setinterfacemessage{references}{4}{illegal reference --}
+\setinterfacemessage{references}{30}{unknown object --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{references}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{duplicate object --}
+\setinterfacemessage{references}{21}{document -- loaded}
+\setinterfacemessage{references}{22}{document -- is not interactive}
+\setinterfacemessage{references}{23}{obscure reference -- (prefix=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{number --}
+\setinterfacemessage{handlings}{1}{font handling --}
+\setinterfacemessage{handlings}{3}{unknown font handling --}
+\setinterfacemessage{handlings}{2}{font handling -- is loaded}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{system}
+\setinterfacemessage{systems}{41}{external file -- in group -- does not exist}
+\setinterfacemessage{systems}{9}{-- not found/processed}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{new version of utility file, second pass needed}
+\setinterfacemessage{systems}{21}{no utility data is loaded}
+\setinterfacemessage{systems}{20}{meaning (sorts) of -- loaded}
+\setinterfacemessage{systems}{5}{module -- loaded}
+\setinterfacemessage{systems}{4}{command -- is already defined}
+\setinterfacemessage{systems}{27}{Version}
+\setinterfacemessage{systems}{26}{Registers}
+\setinterfacemessage{systems}{25}{References}
+\setinterfacemessage{systems}{24}{Floatblocks}
+\setinterfacemessage{systems}{1}{loading utility-file postponed (typemode)}
+\setinterfacemessage{systems}{23}{-- arranged at --}
+\setinterfacemessage{systems}{22}{use a valid utilityfile}
+\setinterfacemessage{systems}{2}{-- loaded}
+\setinterfacemessage{systems}{19}{meaning (synonyms) of -- loaded}
+\setinterfacemessage{systems}{18}{synonym -- -- does not exist}
+\setinterfacemessage{systems}{7}{module -- already loaded}
+\setinterfacemessage{systems}{6}{module -- not found}
+\setinterfacemessage{systems}{14}{forced newpage in list at --}
+\setinterfacemessage{systems}{15}{saving buffer --}
+\setinterfacemessage{systems}{16}{typesetting buffer --}
+\setinterfacemessage{systems}{17}{typesetting verbatim buffer --}
+\setinterfacemessage{systems}{13}{mark -- defined --}
+\setinterfacemessage{systems}{12}{the utility-file is not sorted, use texutil}
+\setinterfacemessage{systems}{11}{building simple util}
+\setinterfacemessage{systems}{10}{don't use em in --}
+\setinterfacemessage{floatblocks}{1}{-- renumbered / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- moved}
+\setinterfacemessage{floatblocks}{2}{-- saved}
+\setinterfacemessage{floatblocks}{5}{order adapted}
+\setinterfacemessage{floatblocks}{4}{-- placed}
+\setinterfacemessage{floatblocks}{7}{n of bottom floats limited to --}
+\setinterfacemessage{floatblocks}{6}{n of top floats limited to --}
+\setinterfacemessage{floatblocks}{9}{order disturbed}
+\setinterfacemessage{floatblocks}{8}{less than -- lines}
+\setinterfacemessage{floatblocks}{title}{floatblocks}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{undefined}
+\setinterfacemessage{floatblocks}{11}{no block given}
+\setinterfacemessage{floatblocks}{10}{-- limited}
+\setinterfacemessage{interactions}{1}{aspect ratio -- x -- (b x h)}
+\setinterfacemessage{interactions}{3}{inactive}
+\setinterfacemessage{interactions}{2}{active}
+\setinterfacemessage{interactions}{5}{unknown attachment --}
+\setinterfacemessage{interactions}{4}{no pagesynchronisation (--) in hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- does not exist}
+\setinterfacemessage{interactions}{title}{interaction}
+\setinterfacemessage{interactions}{21}{-- code inserted}
+\setinterfacemessage{regimes}{1}{regime --}
+\setinterfacemessage{regimes}{3}{unknown regime --}
+\setinterfacemessage{regimes}{2}{regime -- is loaded}
+\setinterfacemessage{regimes}{title}{regime}
+\setinterfacemessage{structures}{1}{begin of sectionblock --}
+\setinterfacemessage{structures}{title}{structure}
+\setinterfacemessage{structures}{2}{end of sectionblock --}
+\setinterfacemessage{linguals}{1}{patterns -- for -- loaded (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{hyphenations -- for -- loaded (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{no patterns -- for -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{patterns for -- not loaded}
+\setinterfacemessage{linguals}{4}{no hyphenations -- for -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{language specific options [--] introduce a -- skip}
+\setinterfacemessage{linguals}{6}{language -- is undefined}
+\setinterfacemessage{linguals}{9}{language -- is active}
+\setinterfacemessage{linguals}{8}{language specific options [--] seamless appended}
+\setinterfacemessage{linguals}{title}{language}
+\setinterfacemessage{linguals}{10}{patterns --loaded}
+\setinterfacemessage{verbatims}{1}{file -- does not exist}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{filter -- is loaded}
+\setinterfacemessage{filters}{title}{filter}
+\setinterfacemessage{filters}{2}{unknown filter --}
+\setinterfacemessage{textblocks}{1}{new version, second pass needed}
+\setinterfacemessage{textblocks}{3}{reading blocks from --}
+\setinterfacemessage{textblocks}{2}{writing blocks to --}
+\setinterfacemessage{textblocks}{5}{-- not hidden}
+\setinterfacemessage{textblocks}{4}{second pass needed}
+\setinterfacemessage{textblocks}{7}{-- hidden}
+\setinterfacemessage{textblocks}{6}{-- hidden and processed}
+\setinterfacemessage{textblocks}{9}{-- not typeset}
+\setinterfacemessage{textblocks}{8}{-- typeset}
+\setinterfacemessage{textblocks}{title}{textblocks}
+\setinterfacemessage{textblocks}{12}{-- skipped}
+\setinterfacemessage{textblocks}{11}{-- loaded and typeset}
+\setinterfacemessage{textblocks}{10}{-- loaded and processed}
+\setinterfacemessage{encodings}{1}{coding --}
+\setinterfacemessage{encodings}{3}{unknown coding --}
+\setinterfacemessage{encodings}{2}{coding -- is loaded}
+\setinterfacemessage{encodings}{title}{encoding}
+\setinterfacemessage{columns}{1}{only -- columns possible}
+\setinterfacemessage{columns}{3}{problems, disable balancing}
+\setinterfacemessage{columns}{2}{use \string\filbreak\space as alternative}
+\setinterfacemessage{columns}{5}{bottom float not yet supported}
+\setinterfacemessage{columns}{4}{top float not yet supported}
+\setinterfacemessage{columns}{7}{balancing aborted after 100 steps}
+\setinterfacemessage{columns}{6}{-- float(s) postponed}
+\setinterfacemessage{columns}{9}{check raggedness}
+\setinterfacemessage{columns}{8}{balanced in -- step(s)}
+\setinterfacemessage{columns}{title}{columns}
+\setinterfacemessage{columns}{13}{wide float moved to top of columns}
+\setinterfacemessage{columns}{12}{float moved to next column / --}
+\setinterfacemessage{columns}{11}{float too wide for column}
+\setinterfacemessage{columns}{10}{(less than) 1 line left}
+\setinterfacemessage{symbols}{1}{loading symbolset --}
+\setinterfacemessage{symbols}{title}{symbols}
+\setinterfacemessage{files}{1}{file synonym -- is already used for --}
+\setinterfacemessage{files}{title}{files}
+\setinterfacemessage{versions}{1}{missing @+}
+\setinterfacemessage{versions}{3}{selected pages: --}
+\setinterfacemessage{versions}{2}{marking pages}
+\setinterfacemessage{versions}{title}{version}
+\setinterfacemessage{specials}{1}{-- loaded}
+\setinterfacemessage{specials}{3}{-- is reset}
+\setinterfacemessage{specials}{2}{no deeper nesting is permitted --}
+\setinterfacemessage{specials}{5}{loading definition file --}
+\setinterfacemessage{specials}{4}{command -- does not exist}
+\setinterfacemessage{specials}{7}{unknown driver --}
+\setinterfacemessage{specials}{6}{nesting is not permitted}
+\setinterfacemessage{specials}{title}{specials}
+\setinterfacemessage{layouts}{1}{textheight adapted with -- at page --}
+\setinterfacemessage{layouts}{3}{-- times text postponed}
+\setinterfacemessage{layouts}{2}{-- times postponed text placed}
+\setinterfacemessage{layouts}{5}{marginblocks inactive}
+\setinterfacemessage{layouts}{4}{marginblocks active}
+\setinterfacemessage{layouts}{7}{calculating logospace}
+\setinterfacemessage{layouts}{6}{subpage set -- processed (size --)}
+\setinterfacemessage{layouts}{9}{currently no more than -- levels in itemizations}
+\setinterfacemessage{layouts}{8}{calculating backgrounds}
+\setinterfacemessage{layouts}{title}{layout}
+\setinterfacemessage{layouts}{11}{spacing -- not permitted in gridmode}
+\setinterfacemessage{layouts}{10}{-- and -- don't add up to 1.0}
+\setinterfacemessage{fonts}{1}{coding --}
+\setinterfacemessage{fonts}{3}{unknown variant --}
+\setinterfacemessage{fonts}{2}{variant -- is loaded}
+\setinterfacemessage{fonts}{5}{style -- is not defined}
+\setinterfacemessage{fonts}{4}{bodyfont -- is not defined}
+\setinterfacemessage{fonts}{7}{unknown format --}
+\setinterfacemessage{fonts}{6}{-- is loaded}
+\setinterfacemessage{fonts}{14}{bodyfont -- is defined (can better be done global)}
+\setinterfacemessage{fonts}{8}{style -- defined}
+\setinterfacemessage{fonts}{title}{bodyfont}
+\setinterfacemessage{fonts}{10}{unknown font file --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{global file --}
+\setinterfacemessage{databases}{2}{local file --}
+\setinterfacemessage{databases}{4}{unknown file --}
+\setinterfacemessage{databases}{title}{databases}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{loading script set --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{unknown preamble --}
+\setinterfacemessage{check}{1}{missing or ungrouped '=' after '--' in line --}
+\setinterfacemessage{check}{3}{-- -- replaces a macro, use CAPITALS!}
+\setinterfacemessage{check}{2}{-- argument(s) expected in line --}
+\setinterfacemessage{check}{title}{check}
+\setinterfacemessage{metapost}{1}{loading metapost library --}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{figure -- can not be found}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{figure -- is not preset}
+\setinterfacemessage{figures}{5}{dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{dimensions of -- loaded from figurefile itself}
+\setinterfacemessage{figures}{6}{dimensions of -- calculated by rlxtools}
+\setinterfacemessage{figures}{8}{figureobject -- is reused}
+\setinterfacemessage{figures}{title}{figures}
+\setinterfacemessage{colors}{1}{system -- is global activated}
+\setinterfacemessage{colors}{3}{-- is not defined --}
+\setinterfacemessage{colors}{2}{system -- is local activated}
+\setinterfacemessage{colors}{5}{unknown system --}
+\setinterfacemessage{colors}{4}{system -- is loaded}
+\setinterfacemessage{colors}{7}{palette -- is not available}
+\setinterfacemessage{colors}{6}{palette -- is available}
+\setinterfacemessage{colors}{9}{-- color space is not supported}
+\setinterfacemessage{colors}{8}{specification -- at color -- becomes black}
+\setinterfacemessage{colors}{title}{color}
+\setinterfacemessage{colors}{12}{-- is registered}
+\setinterfacemessage{colors}{11}{color is converted to gray}
+\setinterfacemessage{colors}{10}{-- color space is supported}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mes.lua b/tex/context/base/mult-mes.lua
new file mode 100644
index 000000000..5c8129711
--- /dev/null
+++ b/tex/context/base/mult-mes.lua
@@ -0,0 +1,2046 @@
+if not modules then modules = { } end modules ['mult-mes'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+return {
+ ["publications"]={
+ ["files"]={ "bibl-tra.mkiv" },
+ ["title"]={
+ ["en"]="publications",
+ },
+ ["1"]={
+ ["en"]="file -- not found, unknown style ignored",
+ },
+ ["2"]={
+ ["en"]="file -- not found, waiting for bibtex",
+ },
+ ["3"]={
+ ["en"]="wrote a new auxiliary file \\jobname.aux",
+ },
+ ["4"]={
+ ["en"]="loading database from --",
+ },
+ ["5"]={
+ ["en"]="warning: cite argument -- on line \\the\\inputlineno",
+ },
+ ["6"]={
+ ["en"]="loading formatting style from --",
+ },
+ },
+ ["check"]={
+ ["1"]={
+ ["cs"]="postradam '=' po '--' na radku --",
+ ["de"]="Fehlendes '=' nach '--' in Zeile --",
+ ["en"]="missing or ungrouped '=' after '--' in line --",
+ ["fr"]="manquant ou dégroupé '=' après '--' à la ligne --",
+ ["it"]="'=' mancante o non raggruppato dopo '--' alla riga --",
+ ["nl"]="'=' ontbreekt of zonder {} na '--' in regel --",
+ ["no"]="manglende '=' etter '--' i linje --",
+ ["ro"]="lipseste '=' dupa '--' in linia --",
+ },
+ ["2"]={
+ ["cs"]="ocekavam -- argument(y) na radku --",
+ ["de"]="-- Argument(e) in Zeile -- erwartet",
+ ["en"]="-- argument(s) expected in line --",
+ ["fr"]="-- argument(s) attendu(s) à la ligne --",
+ ["it"]="-- argomento/i attesi alla riga --",
+ ["nl"]="-- argument(en) verwacht in regel --",
+ ["no"]="-- argument forventet i linje --",
+ ["ro"]="argumentul(ele) -- sunt asteptate in linia --",
+ },
+ ["3"]={
+ ["cs"]="-- -- nahrazuje makro, uzijte VERZALKY!",
+ ["de"]="-- -- ersetzt ein Makro, verwende VERSALIEN!",
+ ["en"]="-- -- replaces a macro, use CAPITALS!",
+ ["fr"]="-- -- remplace une macro, utilisez des MAJUSCULES !",
+ ["it"]="-- -- sostituisce una macro, usare le MAIUSCOLE!",
+ ["nl"]="-- -- vervangt een macro, gebruik HOOFDLETTERS!",
+ ["no"]="-- -- overskygger en makro, bruk STORE BOKSTAVER!",
+ ["ro"]="-- -- inlocuieste un macro, folositi MAJUSCULE!",
+ },
+ ["files"]={ "mult-sys.tex" },
+ ["title"]={
+ ["cs"]="kontrola",
+ ["de"]="check",
+ ["en"]="check",
+ ["fr"]="vérification",
+ ["it"]="controllo",
+ ["nl"]="controle",
+ ["no"]="kontroll",
+ ["ro"]="verificari",
+ },
+ },
+ ["colors"]={
+ ["1"]={
+ ["cs"]="system -- je globalne aktivovana",
+ ["de"]="system -- ist global aktiviert",
+ ["en"]="system -- is global activated",
+ ["fr"]="le système -- est globalement activé",
+ ["it"]="sistema -- attivato globalmente",
+ ["nl"]="systeem -- is globaal actief",
+ ["no"]="system -- er aktivert globalt",
+ ["ro"]="sistem -- este activata global",
+ },
+ ["10"]={
+ ["cs"]="-- prostor barev je podporovan",
+ ["de"]="-- Farbraum wird unterstuetzt",
+ ["en"]="-- color space is supported",
+ ["fr"]="-- l'espace de couleur est supporté",
+ ["it"]="spazio dei colori -- supportato",
+ ["nl"]="-- kleurruimte wordt ondersteund",
+ ["no"]="-- fargerom er støttet",
+ ["ro"]="spatiul de culoare -- este suportat",
+ },
+ ["11"]={
+ ["cs"]="barva je prevedena na sed",
+ ["de"]="Farbe wird in Grau umgewandelt",
+ ["en"]="color is converted to gray",
+ ["fr"]="la couleur est convertie en niveau de gris",
+ ["it"]="il colore ø convertito in grigio",
+ ["nl"]="kleur wordt vertaald in grijs",
+ ["no"]="fargen vil bli vist som grø",
+ ["ro"]="culoarea este convertita la gri",
+ },
+ ["12"]={
+ ["cs"]="-- is registered",
+ ["de"]="-- is registered",
+ ["en"]="-- is registered",
+ ["fr"]="-- est enregistré",
+ ["it"]="-- is registered",
+ ["nl"]="-- is geregistreerd",
+ ["no"]="-- is registered",
+ ["ro"]="-- is registered",
+ },
+ ["2"]={
+ ["cs"]="system -- je lokalne activovana",
+ ["de"]="system -- ist lokal aktiviert",
+ ["en"]="system -- is local activated",
+ ["fr"]="le système -- est localement activé",
+ ["it"]="sistema -- attivato localmente",
+ ["nl"]="systeem -- is lokaal actief",
+ ["no"]="system -- er aktivert lokalt",
+ ["ro"]="sistem -- este activata local",
+ },
+ ["3"]={
+ ["cs"]="-- neni definovana --",
+ ["de"]="-- ist undefiniert --",
+ ["en"]="-- is not defined --",
+ ["fr"]="-- n'est pas défini --",
+ ["it"]="-- non definito --",
+ ["nl"]="-- is niet gedefinieerd --",
+ ["no"]="-- er udefinert --",
+ ["ro"]="-- nu este definita --",
+ },
+ ["4"]={
+ ["cs"]="system -- je nacten",
+ ["de"]="system -- ist geladen",
+ ["en"]="system -- is loaded",
+ ["fr"]="le système -- est chargé",
+ ["it"]="sistema -- caricato",
+ ["nl"]="systeem -- wordt geladen",
+ ["no"]="system -- er lest inn",
+ ["ro"]="sistem -- este incarcata",
+ },
+ ["5"]={
+ ["cs"]="neznamy system --",
+ ["de"]="unbekanntes System --",
+ ["en"]="unknown system --",
+ ["fr"]="système -- inconnu",
+ ["it"]="sistema -- sconosciuto",
+ ["nl"]="onbekend systeem --",
+ ["no"]="ukjent system --",
+ ["ro"]="sistem -- necunoscuta",
+ },
+ ["6"]={
+ ["cs"]="palette -- je k dispozici",
+ ["de"]="palette -- ist verfuegbar",
+ ["en"]="palette -- is available",
+ ["fr"]="la palette -- est disponible",
+ ["it"]="tavolozza -- resa disponibile",
+ ["nl"]="palet -- is beschikbaar",
+ ["no"]="palett -- er tilgjengelig",
+ ["ro"]="paleta -- este disponibila",
+ },
+ ["7"]={
+ ["cs"]="palette -- neni k dispozici",
+ ["de"]="palette -- ist nicht verfuegbar",
+ ["en"]="palette -- is not available",
+ ["fr"]="le palette -- n'est pas disponible",
+ ["it"]="tavolozza -- non disponibile",
+ ["nl"]="palet -- is niet beschikbaar",
+ ["no"]="palett -- er ikke tilgjengelig",
+ ["ro"]="palette -- nu este disponibila",
+ },
+ ["8"]={
+ ["cs"]="specifikace -- v barve -- bude cerna",
+ ["de"]="Spezifikation -- bei Farbe -- wird schwarz",
+ ["en"]="specification -- at color -- becomes black",
+ ["fr"]="la spécification -- de la couleur -- devient noire",
+ ["it"]="specifica -- del colore -- convertita in nero",
+ ["nl"]="specificatie -- bij -- wordt zwart",
+ ["no"]="spesifikasjon -- for farge -- gir kun svart",
+ ["ro"]="specificatia -- la culoarea -- devine neagra",
+ },
+ ["9"]={
+ ["cs"]="-- prostor barev neni podporovan",
+ ["de"]="-- Farbraum wird nicht unterstuetzt",
+ ["en"]="-- color space is not supported",
+ ["fr"]="l'espace de couleur -- n'est pas supporté",
+ ["it"]="spazio dei colori -- non supportato",
+ ["nl"]="-- kleurruimte wordt niet ondersteund",
+ ["no"]="-- fargerom er ikke støttet",
+ ["ro"]="spatiul de culoare -- nu este suportat",
+ },
+ ["files"]={ "colo-ini.tex" },
+ ["title"]={
+ ["cs"]="barva",
+ ["de"]="farbe",
+ ["en"]="color",
+ ["fr"]="couleurs",
+ ["it"]="colore",
+ ["nl"]="kleur",
+ ["no"]="farge",
+ ["ro"]="culori",
+ },
+ },
+ ["columns"]={
+ ["1"]={
+ ["cs"]="je mozno pouze -- sloupcu",
+ ["de"]="nur -- Spalten moeglich",
+ ["en"]="only -- columns possible",
+ ["fr"]="seules -- colonnes possibles",
+ ["it"]="solo -- colonne possibili",
+ ["nl"]="maximaal -- kolommen",
+ ["no"]="maksimalt -- kolonner",
+ ["ro"]="este posibil numai -- coloane",
+ },
+ ["10"]={
+ ["cs"]="zbyl (mene nez) 1 radek",
+ ["de"]="(weniger als) 1 Zeile uebrig",
+ ["en"]="(less than) 1 line left",
+ ["fr"]="(moins de) 1 ligne restante",
+ ["it"]="(meno di) una riga rimasta",
+ ["nl"]="(minder dan) 1 regel over",
+ ["no"]="(mindre enn) 1 linje igjen",
+ ["ro"]="a mai ramas (mai putin de) 1 linie",
+ },
+ ["11"]={
+ ["cs"]="plovouci objekt je pro sloupec prilis siroky",
+ ["de"]="Gleitobjekt zu breit fuer Spalte",
+ ["en"]="float too wide for column",
+ ["fr"]="flottant mis à la largeur de la colonne",
+ ["it"]="oggetto mobile troppo ampio per la colonna",
+ ["nl"]="plaatsblok te breed voor kolom",
+ ["no"]="flytblokk for bredt for kolonna",
+ ["ro"]="blocul este prea lat pentru coloana",
+ },
+ ["12"]={
+ ["cs"]="plovouci objekt je presunut do nasledujiciho sloupce / --",
+ ["de"]="Gleitobjekt in naechste Zeile verschoben / --",
+ ["en"]="float moved to next column / --",
+ ["fr"]="flottant déplacé à la colonne suivante / --",
+ ["it"]="oggetto mobile spostata alla colonna successiva / --",
+ ["nl"]="plaatsblok verplaatst naar volgende kolom / --",
+ ["no"]="flytblokk forskjøvet til neste kolonne / --",
+ ["ro"]="blocul este mutat pe urmatoarea coloana / --",
+ },
+ ["13"]={
+ ["cs"]="siroky plovouci objekt je presunut nad sloupce",
+ ["de"]="breites Gleitobjekt an den Anfang der Spalten verschoben",
+ ["en"]="wide float moved to top of columns",
+ ["fr"]="flottant large déplacé dans la partie supérieure de la colonne",
+ ["it"]="oggetto mobile ampio spostato sopra le colonne",
+ ["nl"]="breed figuur geplaatst boven kolommen",
+ ["no"]="bred flytblokk forksjøvet til toppen av kolonnene",
+ ["ro"]="blocul lat este mutat in partea de sus a coloanelor",
+ },
+ ["2"]={
+ ["cs"]="pouzijte \\string\\filbreak\\space jako alternativu",
+ ["de"]="benutzte \\string\\filbreak\\space als Alternative",
+ ["en"]="use \\string\\filbreak\\space as alternative",
+ ["fr"]="utilisez \\string\\filbreak\\space en tant qu'alternative",
+ ["it"]="in alternativa, usare \\string\\filbreak",
+ ["nl"]="gebruik eventueel \\string\\filbreak",
+ ["no"]="bruk \\string\\filbreak\\space som et alternativ",
+ ["ro"]="folositi \\string\\filbreak\\space ca alternativa",
+ },
+ ["3"]={
+ ["cs"]="problem, vypina se vyvazovani",
+ ["de"]="Problem, verwende [ausgleich=nein]",
+ ["en"]="problems, disable balancing",
+ ["fr"]="problèmes, désactive l'équilibrage",
+ ["it"]="problemi, disabilitare il bilanciamento",
+ ["nl"]="probleempje, probeer [balanceren=nee]",
+ ["no"]="problemer, slår av balansering",
+ ["ro"]="probleme, se dezactiveaza alinierea",
+ },
+ ["4"]={
+ ["cs"]="horni plovouci objekt jeste neni podporovan",
+ ["de"]="Gleitobjekt oben ncoh nicht unterstuetzt",
+ ["en"]="top float not yet supported",
+ ["fr"]="flottant en partie supérieure pas encore supporté",
+ ["it"]="float in cima non ancora supportato",
+ ["nl"]="plaatsblok boven nog niet mogelijk",
+ ["no"]="flytblokker øverst er ikke støttet enda",
+ ["ro"]="cadrele top (top float) nu sunt inca suportate",
+ },
+ ["5"]={
+ ["cs"]="spodni plovouci objekt jeste neni podporovan",
+ ["de"]="Gleitobjekt unten ncoh nicht unterstuetzt",
+ ["en"]="bottom float not yet supported",
+ ["fr"]="flottant en partie inférieure pas encore supporté",
+ ["it"]="float in fondo non ancora supportato",
+ ["nl"]="plaatsblok onder nog niet mogelijk",
+ ["no"]="flytblokker nedert er ikke støttet enda",
+ ["ro"]="cadrele bottom (bottom float) nu sunt inca suportate",
+ },
+ ["6"]={
+ ["cs"]="-- plovouci objekt(y) odlozeny",
+ ["de"]="-- Gleitobjekt(e) verschoben",
+ ["en"]="-- float(s) postponed",
+ ["fr"]="-- flottant(s) reporté(s)",
+ ["it"]="-- float(s) posticipate",
+ ["nl"]="-- plaatsblok(en) opgeschort",
+ ["no"]="-- flytblokk forskjøvet",
+ ["ro"]="-- blocurile sunt amanate",
+ },
+ ["7"]={
+ ["cs"]="vyvazovani ukonceno po 100 krocich",
+ ["de"]="ausgleich nach 100 Schritten abgebrocheb",
+ ["en"]="balancing aborted after 100 steps",
+ ["fr"]="équilibrage abandonné après 100 pas",
+ ["it"]="bilanciamento annullato dopo 100 passi",
+ ["nl"]="balanceren afgebroken na 100 stappen",
+ ["no"]="balansering avbrutt etter 100 iterasjoner",
+ ["ro"]="alinierea este oprita dupa 100 de incercari",
+ },
+ ["8"]={
+ ["cs"]="vyvazeno v -- krocich",
+ ["de"]="ausgeglichen nach -- Schritt(en)",
+ ["en"]="balanced in -- step(s)",
+ ["fr"]="équilibré en -- pas",
+ ["it"]="bilanciamento in -- passo/i",
+ ["nl"]="gebalanceerd in -- stap(pen)",
+ ["no"]="balansert etter -- iterasjoner",
+ ["ro"]="aliniat in -- pas(i)",
+ },
+ ["9"]={
+ ["cs"]="kontrola nerovnost",
+ ["de"]="Ausrichtung ueberpruefen",
+ ["en"]="check raggedness",
+ ["fr"]="vérification des irrégularités",
+ ["it"]="controllare seghettamento",
+ ["nl"]="uitlijnen controleren!",
+ ["no"]="kontroller tekstlayout!",
+ ["ro"]="verificat alinierea",
+ },
+ ["files"]={ "page-ini.tex" },
+ ["title"]={
+ ["cs"]="sloupce",
+ ["de"]="Spalten",
+ ["en"]="columns",
+ ["fr"]="colonnes",
+ ["it"]="colonne",
+ ["nl"]="kolommen",
+ ["no"]="kolonner",
+ ["ro"]="coloane",
+ },
+ },
+ ["databases"]={
+ ["1"]={
+ ["cs"]="--",
+ ["de"]="--",
+ ["en"]="--",
+ ["fr"]="--",
+ ["it"]="--",
+ ["nl"]="--",
+ ["no"]="--",
+ ["ro"]="--",
+ },
+ ["2"]={
+ ["cs"]="local file --",
+ ["de"]="lokale Datei --",
+ ["en"]="local file --",
+ ["fr"]="fichier local --",
+ ["it"]="file locale --",
+ ["nl"]="lokaal bestand --",
+ ["no"]="lokal fil --",
+ ["ro"]="fisier local --",
+ },
+ ["3"]={
+ ["cs"]="global file --",
+ ["de"]="globale Datei --",
+ ["en"]="global file --",
+ ["fr"]="fichier global --",
+ ["it"]="file globale --",
+ ["nl"]="globaal bestand --",
+ ["no"]="global fil --",
+ ["ro"]="fisier global --",
+ },
+ ["4"]={
+ ["cs"]="unknown file --",
+ ["de"]="unbekannte Datei --",
+ ["en"]="unknown file --",
+ ["fr"]="fichier inconnu --",
+ ["it"]="file sconosciuto --",
+ ["nl"]="onbekend bestand --",
+ ["no"]="ukjent fil --",
+ ["ro"]="fisier necunoscut --",
+ },
+ ["files"]={ "core-dat.tex" },
+ ["title"]={
+ ["cs"]="databases",
+ ["de"]="Datenbank",
+ ["en"]="databases",
+ ["fr"]="bases de données",
+ ["it"]="database",
+ ["nl"]="database",
+ ["no"]="databaser",
+ ["ro"]="baze de date",
+ },
+ },
+ ["documents"]={
+ ["1"]={
+ ["de"]="Blatt --",
+ ["en"]="sheet --",
+ ["nl"]="sheet --",
+ },
+ ["2"]={
+ ["de"]="Nummer --",
+ ["en"]="number --",
+ ["nl"]="nummer --",
+ },
+ ["files"]={ "docs-bri.tex", "docs-she.tex" },
+ ["title"]={
+ ["de"]="Blaetter",
+ ["en"]="sheets",
+ ["nl"]="sheets",
+ },
+ },
+ ["encodings"]={
+ ["1"]={
+ ["cs"]="kodovani --",
+ ["de"]="Kodierung --",
+ ["en"]="coding --",
+ ["fr"]="encodage --",
+ ["it"]="codifica --",
+ ["nl"]="codering --",
+ ["no"]="koding --",
+ ["ro"]="codificarea --",
+ },
+ ["2"]={
+ ["cs"]="je nacteno kodovani --",
+ ["de"]="Kodierung -- ist geladen",
+ ["en"]="coding -- is loaded",
+ ["fr"]="l'encodage -- est chargé",
+ ["it"]="codifica -- caricata",
+ ["nl"]="codering -- wordt geladen",
+ ["no"]="koding -- er lest inn",
+ ["ro"]="codificarea -- este Encarcata",
+ },
+ ["3"]={
+ ["cs"]="nezname kodovani --",
+ ["de"]="Unbekannte Kodierung --",
+ ["en"]="unknown coding --",
+ ["fr"]="encodage -- inconnu",
+ ["it"]="codifica sconosciuta --",
+ ["nl"]="onbekende codering --",
+ ["no"]="ukjent koding --",
+ ["ro"]="codificarea -- este necunoscuta",
+ },
+ ["files"]={ "enco-ini.mkii" },
+ ["title"]={
+ ["cs"]="kodovani",
+ ["de"]="Kodierung",
+ ["en"]="encoding",
+ ["fr"]="encodage",
+ ["it"]="codifica",
+ ["nl"]="encoding",
+ ["no"]="koding",
+ ["ro"]="codificari",
+ },
+ },
+ ["figures"]={
+ ["1"]={
+ ["cs"]="obraz -- nelze nalezt",
+ ["de"]="Abbildung -- kann nicht gefunden werden",
+ ["en"]="figure -- can not be found",
+ ["fr"]="la figure -- ne peut être trouvée",
+ ["it"]="figura -- non trovata",
+ ["nl"]="figuur -- is niet te vinden",
+ ["ro"]="figura -- nu poate fi gasita",
+ },
+ ["2"]={
+ ["cs"]="obraz -- nepritomen",
+ ["de"]="Abbildung -- wird nicht erstellt",
+ ["en"]="figure -- is not preset",
+ ["fr"]="la figure -- n'est pas pré-sélectionnée",
+ ["it"]="la figura -- non è preimpostata",
+ ["nl"]="figuur -- wordt niet preset",
+ ["ro"]="figura -- nu este presetata",
+ },
+ ["3"]={
+ ["cs"]="dimensions of -- are determined externally",
+ ["de"]="dimensions of -- are determined externally",
+ ["en"]="dimensions of -- are determined externally",
+ ["fr"]="dimensions of -- are determined externally",
+ ["it"]="dimensions of -- are determined externally",
+ ["nl"]="maten van -- worden extern vastgesteld",
+ ["ro"]="dimensions of -- are determined externally",
+ },
+ ["4"]={
+ ["cs"]="dimenze obrazu -- nacteny primo z jeho souboru",
+ ["de"]="Dimensionen von -- geladen aus der Abbildungsdatei selbst",
+ ["en"]="dimensions of -- loaded from figurefile itself",
+ ["fr"]="les dimensions de -- chargées implicitement à partir du fichier de figure",
+ ["it"]="dimensioni di -- caricate dal file di immagini stesso",
+ ["nl"]="maten van -- geladen uit figuurfile zelf",
+ ["ro"]="dimensiunea figurii -- se incarca din fisierul insusi",
+ },
+ ["5"]={
+ ["cs"]="dimensions of -- are unknown",
+ ["de"]="Dimensions of -- are unknown",
+ ["en"]="dimensions of -- are unknown",
+ ["fr"]="dimensions of -- are unknown",
+ ["it"]="dimensions of -- are unknown",
+ ["nl"]="maten van -- zijn onbekend",
+ ["ro"]="dimensions of -- are unknown",
+ },
+ ["6"]={
+ ["cs"]="dimenze obrazu -- spocteny programem rlxtools",
+ ["de"]="Dimensionen von -- ausgerechnet durch rlxtools",
+ ["en"]="dimensions of -- calculated by rlxtools",
+ ["fr"]="les dimensions de -- calculées par rlxtools",
+ ["it"]="dimensioni di -- calcolate da rlxtools",
+ ["nl"]="maten van -- berekend door rlxtools",
+ ["ro"]="dimensiunea figurii -- este calculata de rlxtools",
+ },
+ ["8"]={
+ ["cs"]="obrazovy objekt -- je znovu pouzit",
+ ["de"]="Abbildungobjekt -- wurde wiederverwandt",
+ ["en"]="figureobject -- is reused",
+ ["fr"]="figureobject -- est réutilisé",
+ ["it"]="oggetto-figura -- riutilizzato",
+ ["nl"]="figuurobject -- wordt opnieuw gebruikt",
+ ["ro"]="obiectul figura -- este refolosit",
+ },
+ ["files"]={ "core-inc.mkii" },
+ ["title"]={
+ ["cs"]="obrazy",
+ ["de"]="Abbildungen",
+ ["en"]="figures",
+ ["fr"]="figures",
+ ["it"]="figure",
+ ["nl"]="figuren",
+ ["ro"]="figuri",
+ },
+ },
+ ["files"]={
+ ["1"]={
+ ["cs"]="synonymum souboru -- je jiz pouzito pro --",
+ ["de"]="Dateisynonym -- wird bereits fuer -- benutzt",
+ ["en"]="file synonym -- is already used for --",
+ ["fr"]="le synonyme de fichier -- est déjà utilisé pour --",
+ ["it"]="sinonimo file -- già in uso per --",
+ ["nl"]="file synoniem -- is al in gebruik voor --",
+ ["no"]="filesynonym -- er allerede brukt for --",
+ ["ro"]="sinonimul fisierelor -- este folosit deja pentru --",
+ },
+ ["files"]={ "core-fil.tex" },
+ ["title"]={
+ ["cs"]="soubory",
+ ["de"]="files",
+ ["en"]="files",
+ ["fr"]="fichiers",
+ ["it"]="file",
+ ["nl"]="files",
+ ["no"]="filer",
+ ["ro"]="fisiere",
+ },
+ },
+ ["filters"]={
+ ["1"]={
+ ["cs"]="filter -- is loaded",
+ ["de"]="filter -- ist geladen",
+ ["en"]="filter -- is loaded",
+ ["fr"]="le filtre -- est chargé",
+ ["it"]="filtro -- caricato",
+ ["nl"]="filter -- wordt geladen",
+ },
+ ["2"]={
+ ["cs"]="unknown filter --",
+ ["de"]="unknown filter --",
+ ["en"]="unknown filter --",
+ ["fr"]="filtre -- inconnu",
+ ["it"]="filtro sconosciuto --",
+ ["nl"]="onbekend filter --",
+ },
+ ["files"]={ "filt-ini.tex" },
+ ["title"]={
+ ["cs"]="filter",
+ ["de"]="filter",
+ ["en"]="filter",
+ ["fr"]="filtre",
+ ["it"]="filtri",
+ ["nl"]="filter",
+ },
+ },
+ ["floatblocks"]={
+ ["1"]={
+ ["cs"]="-- precislovano / -- => --",
+ ["de"]="-- neu nummeriert / -- => --",
+ ["en"]="-- renumbered / -- => --",
+ ["fr"]="-- renuméroté / -- => --",
+ ["it"]="-- rinumerato / -- => --",
+ ["nl"]="-- hernummerd / -- => --",
+ ["no"]="-- renummerert / -- => --",
+ ["ro"]="-- renumerotat / -- => --",
+ },
+ ["10"]={
+ ["cs"]="-- omezeno",
+ ["de"]="-- begrenzt",
+ ["en"]="-- limited",
+ ["fr"]="-- limité",
+ ["it"]="-- limitato",
+ ["nl"]="-- begrensd",
+ ["no"]="-- begrenset",
+ ["ro"]="-- limitat",
+ },
+ ["11"]={
+ ["cs"]="nedan zadny blok",
+ ["de"]="kein Block gegeben",
+ ["en"]="no block given",
+ ["fr"]="pas de bloc donné",
+ ["it"]="nessun oggetto specificato",
+ ["nl"]="geen blok opgegeven",
+ ["no"]="ingen blokk oppgitt",
+ ["ro"]="nu este dat nici un bloc",
+ },
+ ["12"]={
+ ["cs"]="nedefinovano",
+ ["de"]="undefiniert",
+ ["en"]="undefined",
+ ["fr"]="indéfini",
+ ["it"]="non definito",
+ ["nl"]="niet gedefinieerd",
+ ["no"]="udefinert",
+ ["ro"]="nedefinit",
+ },
+ ["13"]={
+ ["cs"]="there is nothing to split",
+ ["de"]="there is nothing to split",
+ ["en"]="there is nothing to split",
+ ["fr"]="there is nothing to split",
+ ["it"]="there is nothing to split",
+ ["nl"]="er is niets te splitsen",
+ ["no"]="there is nothing to split",
+ ["ro"]="there is nothing to split",
+ },
+ ["2"]={
+ ["cs"]="-- ulozeno",
+ ["de"]="-- gespeichert",
+ ["en"]="-- saved",
+ ["fr"]="-- sauvegardé",
+ ["it"]="-- salvato",
+ ["nl"]="-- bewaard",
+ ["no"]="-- lagret",
+ ["ro"]="-- salvat",
+ },
+ ["3"]={
+ ["cs"]="-- presunuto",
+ ["de"]="-- verschoben",
+ ["en"]="-- moved",
+ ["fr"]="-- déplacé",
+ ["it"]="-- mosso",
+ ["nl"]="-- verplaatst",
+ ["no"]="-- flyttet",
+ ["ro"]="-- mutat",
+ },
+ ["4"]={
+ ["cs"]="-- umisteno",
+ ["de"]="-- plaziert",
+ ["en"]="-- placed",
+ ["fr"]="-- placé",
+ ["it"]="-- sistemato",
+ ["nl"]="-- geplaatst",
+ ["no"]="-- plassert",
+ ["ro"]="-- plasat",
+ },
+ ["5"]={
+ ["cs"]="poradi prizpusobeno",
+ ["de"]="Reihenfolge angepasst",
+ ["en"]="order adapted",
+ ["fr"]="ordre adapté",
+ ["it"]="ordine aggiustato",
+ ["nl"]="volgorde aangepast",
+ ["no"]="rekkefølge tilpasset",
+ ["ro"]="ordinea adaptata",
+ },
+ ["6"]={
+ ["cs"]="pocet hornich plovoucich objektu je omezen na --",
+ ["de"]="Anz. der oberen Gleitobjekte beschraengt auf --",
+ ["en"]="n of top floats limited to --",
+ ["fr"]="n flottants de haut de page limité à --",
+ ["it"]="n di top floats limitato a --",
+ ["nl"]="maximaal -- boven",
+ ["no"]="maksimalt -- flytblokker øverst",
+ ["ro"]="nr. cadrelor de sus limitat la --",
+ },
+ ["7"]={
+ ["cs"]="pocet spodnich plovoucich objektu je omezen na --",
+ ["de"]="Anz. der unteren Gleitobjekte beschraengt auf --",
+ ["en"]="n of bottom floats limited to --",
+ ["fr"]="n flottants de bas de page limité à --",
+ ["it"]="n di bottom floats limitato a --",
+ ["nl"]="maximaal -- onder",
+ ["no"]="maksimalt -- flytblokker nederst",
+ ["ro"]="nr. blocurilor de jos limitat la --",
+ },
+ ["8"]={
+ ["cs"]="radku je mene nez --",
+ ["de"]="weniger als -- zeilen",
+ ["en"]="less than -- lines",
+ ["fr"]="moins de -- lignes",
+ ["it"]="meno di -- righe",
+ ["nl"]="minder dan -- regels",
+ ["no"]="mindre enn -- linjer",
+ ["ro"]="mai putin de -- linii",
+ },
+ ["9"]={
+ ["cs"]="poradi naruseno",
+ ["de"]="Reigenfolge gestoert",
+ ["en"]="order disturbed",
+ ["fr"]="ordre perturbé",
+ ["it"]="ordine disturbato",
+ ["nl"]="volgorde verstoord",
+ ["no"]="rekkefølge endret",
+ ["ro"]="ordinea deranjata",
+ },
+ ["files"]={ "page-flt.tex", "strc-flt.tex" },
+ ["title"]={
+ ["cs"]="plovouciobjekty",
+ ["de"]="Gleitobjektbloecke",
+ ["en"]="floatblocks",
+ ["fr"]="blocs de flottants",
+ ["it"]="oggetti mobili",
+ ["nl"]="plaatsblokken",
+ ["no"]="flytblokker",
+ ["ro"]="Blocuri",
+ },
+ },
+ ["fonts"]={
+ ["1"]={
+ ["cs"]="kodovani --",
+ ["de"]="Kodierung --",
+ ["en"]="coding --",
+ ["fr"]="encodage --",
+ ["it"]="codifica --",
+ ["nl"]="codering --",
+ ["no"]="koding --",
+ ["ro"]="codificarea --",
+ },
+ ["10"]={
+ ["cs"]="neznamy font --",
+ ["de"]="unbekanntes Font --",
+ ["en"]="unknown font file --",
+ ["fr"]="fichier de police -- inconnu",
+ ["it"]="file di font sconosciuto --",
+ ["nl"]="onbekende font file --",
+ ["no"]="ukjent fontfil --",
+ ["ro"]="fisier font necunoscut --",
+ },
+ ["14"]={
+ ["cs"]="bodyfont -- is defined (can better be done global)",
+ ["de"]="Fliesstext -- wurde definiert (besser waere globale Definition)",
+ ["en"]="bodyfont -- is defined (can better be done global)",
+ ["fr"]="policecorps -- est défini (une définition globale pourrait être plus adéquat)",
+ ["it"]="corpo del testo -- definito (sarebbe meglio globale)",
+ ["nl"]="korps -- is gedefinieerd (kan beter globaal plaatsvinden)",
+ ["no"]="bodyfont -- is defined (can better be done global)",
+ ["ro"]="bodyfont -- is defined (can better be done global)",
+ },
+ ["2"]={
+ ["cs"]="varianta -- je nactena",
+ ["de"]="Variante -- ist geladen",
+ ["en"]="variant -- is loaded",
+ ["fr"]="la variante -- est chargée",
+ ["it"]="variante -- caricata",
+ ["nl"]="variant -- wordt geladen",
+ ["no"]="variant -- er lest inn",
+ ["ro"]="varianta -- este incarcata",
+ },
+ ["3"]={
+ ["cs"]="neznama varianta --",
+ ["de"]="Unbekannte Variante --",
+ ["en"]="unknown variant --",
+ ["fr"]="variante -- inconnue",
+ ["it"]="variante sconosciuta --",
+ ["nl"]="onbekende variant --",
+ ["no"]="ukjent variant --",
+ ["ro"]="varianta necunoscuta --",
+ },
+ ["4"]={
+ ["cs"]="zakladni font -- neni definovan",
+ ["de"]="Fliesstext -- ist nicht definiert",
+ ["en"]="bodyfont -- is not defined",
+ ["fr"]="policecorps -- n'est pas définie",
+ ["it"]="corpo del testo -- non definito",
+ ["nl"]="korps -- is niet gedefinieerd",
+ ["no"]="hovedfont -- er ikke definert",
+ ["ro"]="corpul de litere -- nu este definit",
+ },
+ ["5"]={
+ ["cs"]="styl -- neni definovan",
+ ["de"]="Stil -- ist nicht definiert",
+ ["en"]="style -- is not defined",
+ ["fr"]="le style -- n'est pas défini",
+ ["it"]="stile -- non definito",
+ ["nl"]="stijl -- is niet gedefinieerd",
+ ["no"]="stil -- er ikke definert",
+ ["ro"]="stilul -- nu este definit",
+ },
+ ["6"]={
+ ["cs"]="-- je nacten",
+ ["de"]="-- ist geladen",
+ ["en"]="-- is loaded",
+ ["fr"]="-- est chargé",
+ ["it"]="-- caricato",
+ ["nl"]="-- wordt geladen",
+ ["no"]="-- er lest inn",
+ ["ro"]="-- este incarcat",
+ },
+ ["7"]={
+ ["cs"]="neznamy format --",
+ ["de"]="unbekanntes Format --",
+ ["en"]="unknown format --",
+ ["fr"]="format -- inconnu",
+ ["it"]="formato sconosciuto --",
+ ["nl"]="onbekend formaat --",
+ ["no"]="ukjent format --",
+ ["ro"]="format necunoscut --",
+ },
+ ["8"]={
+ ["cs"]="styl -- definovan",
+ ["de"]="Stil -- definiert",
+ ["en"]="style -- defined",
+ ["fr"]="style -- défini",
+ ["it"]="stile -- definito",
+ ["nl"]="stijl -- gedefinieerd",
+ ["no"]="stil -- definert",
+ ["ro"]="stilul -- definit",
+ },
+ ["files"]={ "font-ini.mkii", "font-ini.mkiv" },
+ ["title"]={
+ ["cs"]="zakladnifont",
+ ["de"]="Fliesstext",
+ ["en"]="bodyfont",
+ ["fr"]="corps de texte",
+ ["it"]="font del corpo",
+ ["nl"]="korps",
+ ["no"]="hovedfont",
+ ["ro"]="corp de litere",
+ },
+ },
+ ["handlings"]={
+ ["1"]={
+ ["cs"]="font handling --",
+ ["de"]="Font Verarbeitung --",
+ ["en"]="font handling --",
+ ["fr"]="manipulation -- de police",
+ ["it"]="font handling --",
+ ["nl"]="font afhandeling --",
+ ["no"]="font handling --",
+ ["ro"]="font handling --",
+ },
+ ["2"]={
+ ["cs"]="font handling -- is loaded",
+ ["de"]="Font Verarbeitung -- ist geladen",
+ ["en"]="font handling -- is loaded",
+ ["fr"]="la manipulation -- de police est chargée",
+ ["it"]="font handling -- is loaded",
+ ["nl"]="font afhandeling -- wordt geladen",
+ ["no"]="font handling -- is loaded",
+ ["ro"]="font handling -- is loaded",
+ },
+ ["3"]={
+ ["cs"]="unknown font handling --",
+ ["de"]="unknown font handling --",
+ ["en"]="unknown font handling --",
+ ["fr"]="manipulation -- inconnue de police",
+ ["it"]="unknown font handling --",
+ ["nl"]="onbekende font afhandeling --",
+ ["no"]="unknown font handling --",
+ ["ro"]="unknown font handling --",
+ },
+ ["files"]={ "hand-ini.mkii" },
+ ["title"]={
+ ["cs"]="handling",
+ ["de"]="handling",
+ ["en"]="handling",
+ ["fr"]="manipulation",
+ ["it"]="handling",
+ ["nl"]="handling",
+ ["no"]="handling",
+ ["ro"]="handling",
+ },
+ },
+ ["interactions"]={
+ ["1"]={
+ ["cs"]="pomer -- x -- (s x v)",
+ ["de"]="Seitenverhaeltnis -- x -- (B x H)",
+ ["en"]="aspect ratio -- x -- (b x h)",
+ ["fr"]="ratio d'aspect -- x -- (b x h)",
+ ["it"]="rapporto -- x -- (b x a)",
+ ["nl"]="aspect ratio -- x -- (b x h)",
+ ["no"]="forholdstall -- x -- (b x h)",
+ ["ro"]="aspectul -- x -- (b x h)",
+ },
+ ["2"]={
+ ["cs"]="aktivni",
+ ["de"]="aktiv",
+ ["en"]="active",
+ ["fr"]="actif",
+ ["it"]="attiva",
+ ["nl"]="actief",
+ ["no"]="aktiv",
+ ["ro"]="activ",
+ },
+ ["21"]={
+ ["cs"]="-- kod vlozen",
+ ["de"]="-- Code eingefuegt",
+ ["en"]="-- code inserted",
+ ["fr"]="-- code inseré",
+ ["it"]="codice -- inserito",
+ ["nl"]="-- code tussengevoegd",
+ ["no"]="-- kode satt inn / tilføyd",
+ ["ro"]="-- cod inserat",
+ },
+ ["3"]={
+ ["cs"]="neaktivni",
+ ["de"]="inaktiv",
+ ["en"]="inactive",
+ ["fr"]="inactif",
+ ["it"]="inattiva",
+ ["nl"]="niet actief",
+ ["no"]="inaktiv",
+ ["ro"]="inactiv",
+ },
+ ["4"]={
+ ["cs"]="zadna strankova synchronizace (--) v hmode",
+ ["de"]="keine Seitensynchronisation (--) im hmode",
+ ["en"]="no pagesynchronisation (--) in hmode",
+ ["fr"]="pas de synchronisation de page (--) dans le hmode",
+ ["it"]="sincronizzazione di pagina (--) non disponibile in hmode",
+ ["nl"]="geen paginasynchronisatie (--) in hmode",
+ ["no"]="ingen sidesynkronisering (--) i hmode",
+ ["ro"]="nu exista sincronizare pt. pagini (--) in hmode",
+ },
+ ["5"]={
+ ["cs"]="unknown attachment --",
+ ["de"]="unknown attachment --",
+ ["en"]="unknown attachment --",
+ ["fr"]="le fichier joint -- est inconnu",
+ ["it"]="unknown attachment --",
+ ["nl"]="onbekend attachment --",
+ ["no"]="unknown attachment --",
+ ["ro"]="unknown attachment --",
+ },
+ ["6"]={
+ ["cs"]="attachment file -- does not exist",
+ ["de"]="attachment file -- does not exist",
+ ["en"]="attachment file -- does not exist",
+ ["fr"]="le fichier joint -- n'existe pas",
+ ["it"]="attachment file -- does not exist",
+ ["nl"]="attachment file -- bestaat niet",
+ ["no"]="attachment file -- does not exist",
+ ["ro"]="attachment file -- does not exist",
+ },
+ ["files"]={ "core-int.tex", "spec-ini.tex" },
+ ["title"]={
+ ["cs"]="interakce",
+ ["de"]="Interaktion",
+ ["en"]="interaction",
+ ["fr"]="interaction",
+ ["it"]="interazione",
+ ["nl"]="interactie",
+ ["no"]="interaksjon",
+ ["ro"]="interactiuni",
+ },
+ },
+ ["javascript"]={
+ ["1"]={
+ ["cs"]="nacita se soubor skriptu --",
+ ["de"]="Lade Scriptdatei --",
+ ["en"]="loading script set --",
+ ["fr"]="chargement du jeu de script --",
+ ["it"]="caricamento dello script set --",
+ ["nl"]="script set -- wordt geladen",
+ ["no"]="leser inn scriptsett --",
+ ["ro"]="se incarca scriptul --",
+ },
+ ["2"]={
+ ["cs"]="neznama preambule --",
+ ["de"]="unbekannte Preamble --",
+ ["en"]="unknown preamble --",
+ ["fr"]="préambule -- inconnu",
+ ["it"]="preambolo sconosciuto --",
+ ["nl"]="onbekende preamble --",
+ ["no"]="ukjent 'preamble' --",
+ ["ro"]="preambul necunoscut --",
+ },
+ ["files"]={ "java-ini.tex" },
+ ["title"]={
+ ["cs"]="javascript",
+ ["de"]="javascript",
+ ["en"]="javascript",
+ ["fr"]="javascript",
+ ["it"]="javascript",
+ ["nl"]="javascript",
+ ["no"]="javascript",
+ ["ro"]="javascript",
+ },
+ },
+ ["layouts"]={
+ ["1"]={
+ ["cs"]="vyska textu prizpusobena s -- na strane --",
+ ["de"]="Texthoehe angepasst mit -- auf Seite --",
+ ["en"]="textheight adapted with -- at page --",
+ ["fr"]="hauteurtexte adaptée avec -- à la page --",
+ ["it"]="altezza del testo adattata con -- a pagina --",
+ ["nl"]="teksthoogte aangepast met -- op pagina --",
+ ["no"]="teksthøyde tilpasset med -- på side --",
+ ["ro"]="textheight adaptat cu -- la pagina --",
+ },
+ ["10"]={
+ ["cs"]="-- a -- nedava dohromady 1.0",
+ ["de"]="-- und -- ergeben zusammen nicht 1.0",
+ ["en"]="-- and -- don't add up to 1.0",
+ ["fr"]="-- et -- ne sont pas ajoutés à 1.0",
+ ["it"]="-- e -- non sommano a 1.0",
+ ["nl"]="-- en -- tellen niet op tot 1.0",
+ ["no"]="-- og -- er ikke 1.0 til sammen",
+ ["ro"]="-- si -- nu se adauga pana la 1.0",
+ },
+ ["11"]={
+ ["cs"]="svisla mezera -- neni povolena v pevnem radkovem rejstriku",
+ ["de"]="Zwischenraum -- nicht im Grittermoduserlau",
+ ["en"]="spacing -- not permitted in gridmode",
+ ["fr"]="espacement -- non permis en modegrille",
+ ["it"]="spaziatura -- non permessa in modo griglia",
+ ["nl"]="interlinie -- niet toegestaan in gridmode",
+ ["no"]="mellomrom -- ikke tillatt i gridmodus",
+ ["ro"]="spatierea -- nu este permisa in gridmode",
+ },
+ ["2"]={
+ ["cs"]="-- krat odlozeny text umisten",
+ ["de"]="-- mal verschobener Text plaziert",
+ ["en"]="-- times postponed text placed",
+ ["fr"]="-- times postponed text placed",
+ ["it"]="posizionato testo posticipato -- volte",
+ ["nl"]="-- maal uitgestelde tekst tussengevoegd",
+ ["no"]="-- ganger forskjøvet tekst plassert",
+ ["ro"]="textul amanat de -- ori a fost plasat",
+ },
+ ["3"]={
+ ["cs"]="-- krat text odlozen",
+ ["de"]="-- mal Text verschoben",
+ ["en"]="-- times text postponed",
+ ["fr"]="-- times text postponed",
+ ["it"]="testo posticipato -- volte",
+ ["nl"]="-- maal tekst plaatsen uitstellen",
+ ["no"]="-- ganger tekst forskjøvet",
+ ["ro"]="textul amanat de -- ori",
+ },
+ ["4"]={
+ ["cs"]="okrajove bloky aktivni",
+ ["de"]="marginalbloecke aktiv",
+ ["en"]="marginblocks active",
+ ["fr"]="blocsmarge actifs",
+ ["it"]="blocchi in margine attivi",
+ ["nl"]="margeblokken actief",
+ ["no"]="margblokker aktive",
+ ["ro"]="blocuri marginale active",
+ },
+ ["5"]={
+ ["cs"]="okrajove bloky neaktivni",
+ ["de"]="marginalbloecke inaktiv",
+ ["en"]="marginblocks inactive",
+ ["fr"]="blocsmarge inactifs",
+ ["it"]="blocchi in margine inattivi",
+ ["nl"]="margeblokken inactief",
+ ["no"]="margblokker inaktive",
+ ["ro"]="blocuri marginale inactive",
+ },
+ ["6"]={
+ ["cs"]="sada stran -- zpracovana (velikost --)",
+ ["de"]="Unterseitenfolge -- verarbeitet (Groesse --)",
+ ["en"]="subpage set -- processed (size --)",
+ ["fr"]="jeu de souspage -- traité (taille --)",
+ ["it"]="gruppo di sottopagine -- elaborato (dimensione --)",
+ ["nl"]="subpagina reeks -- verwerkt (aantal --)",
+ ["no"]="delside sett -- behandlet (størrelse --)",
+ ["ro"]="setul -- de subpagini procesat (dimensiunea --)",
+ },
+ ["7"]={
+ ["cs"]="pocita se misto pro logo",
+ ["de"]="berechne Platzbedarf des Logos",
+ ["en"]="calculating logospace",
+ ["fr"]="calcul de l'espace pour le logo",
+ ["it"]="calcolo dello spazio per logo",
+ ["nl"]="beeldmerken berekenen",
+ ["no"]="beregner plass for logo",
+ ["ro"]="se calculeaza spatiul pentru logo",
+ },
+ ["8"]={
+ ["cs"]="pocita se pozadi",
+ ["de"]="berechne Hintergrund",
+ ["en"]="calculating backgrounds",
+ ["fr"]="calcul des arrières-plans",
+ ["it"]="calcolo dello sfondo",
+ ["nl"]="achtergronden berekenen",
+ ["no"]="beregner bakgrunn",
+ ["ro"]="se calculeaza fundalurile",
+ },
+ ["9"]={
+ ["cs"]="aktualne ne vice nez -- urovne/urovni vyctu",
+ ["de"]="z.Z. nicht mehr als -- Ebenen in Aufzaehlungen",
+ ["en"]="currently no more than -- levels in itemizations",
+ ["fr"]="pas plus de -- niveaux pour l'instant dans les élémentarisations",
+ ["it"]="attualmente non più di -- livelli di elencazione",
+ ["nl"]="momenteel maximaal -- niveaus in opsommingen",
+ ["no"]="for øyeblikket maksimalt -- nivåer i opplisting",
+ ["ro"]="acum nu se supota mai mult de -- nivele de adancime la iteratii",
+ },
+ ["files"]={ "core-itm.tex", "page-bck.mkii", "page-bck.mkiv", "page-ini.tex", "page-log.tex", "strc-itm.tex" },
+ ["title"]={
+ ["cs"]="layout",
+ ["de"]="Layout",
+ ["en"]="layout",
+ ["fr"]="calque",
+ ["it"]="layout",
+ ["nl"]="layout",
+ ["no"]="layout",
+ ["ro"]="aranjamente",
+ },
+ },
+ ["linguals"]={
+ ["1"]={
+ ["cs"]="vzory -- pro -- nacteny (n=--,e=--,m=--)",
+ ["de"]="Trennmuster -- fuer -- geladen (n=--,e=--,m=--)",
+ ["en"]="patterns -- for -- loaded (n=--,e=--,m=--)",
+ ["fr"]="les motifs -- pour -- sont chargés (n=--,e=--,m=--)",
+ ["it"]="schemi -- per -- caricati (n=--,e=--,m=--)",
+ ["nl"]="afbreekpatronen -- voor -- geladen (n=--,e=--,m=--)",
+ ["no"]="orddelingsmønster -- for -- er lest inn (n=--,e=--,m=--)",
+ ["ro"]="sablonul -- pentru -- s-a incarcat (n=--,e=--,m=--)",
+ },
+ ["10"]={
+ ["cs"]="vzory --nacteny",
+ ["de"]="Trennmuster --geladen",
+ ["en"]="patterns --loaded",
+ ["fr"]="motifs -- chargés",
+ ["it"]="schemi -- caricati",
+ ["nl"]="patronen --geladen",
+ ["no"]="orddelingsmønster -- er lest inn",
+ ["ro"]="sabloanele -- incarcate",
+ },
+ ["2"]={
+ ["cs"]="zadne vzory -- pro -- (n=--,e=--,m=--) (--,--)",
+ ["de"]="Keine Trennmuster -- fuer -- (n=--,e=--,m=--) (--,--)",
+ ["en"]="no patterns -- for -- (n=--,e=--,m=--) (--,--)",
+ ["fr"]="pas de motifs -- pour -- (n=--,e=--,m=--) (--,--)",
+ ["it"]="niente schemi -- per -- (n=--,e=--,m=--) (--,--)",
+ ["nl"]="geen afbreekpatronen -- voor -- (n=--,e=--,m=--) (--,--)",
+ ["no"]="ingen orddelingsmønster -- for -- (n=--,e=--,m=--) (--,--)",
+ ["ro"]="nu exista sabloane -- pentru -- (n=--,e=--,m=--) (--,--)",
+ },
+ ["3"]={
+ ["cs"]="deleni slov -- pro -- nacteno (n=--,e=--,m=--)",
+ ["de"]="Trenndefinitionen -- fuer -- geladen (n=--,e=--,m=--)",
+ ["en"]="hyphenations -- for -- loaded (n=--,e=--,m=--)",
+ ["fr"]="hyphenations -- pour -- chargés (n=--,e=--,m=--)",
+ ["it"]="sillabazione -- per -- caricata (n=--,e=--,m=--)",
+ ["nl"]="afbreekdefinities -- voor -- geladen (n=--,e=--,m=--)",
+ ["no"]="orddelingsdefinisjon -- for -- er lest inn (n=--,e=--,m=--)",
+ ["ro"]="despartirea in silabe -- pentru -- s-a incarcat (n=--,e=--,m=--)",
+ },
+ ["4"]={
+ ["cs"]="zadne deleni slov -- pro -- (n=--,e=--,m=--)",
+ ["de"]="Keine Trenndefinitionen -- fuer -- (n=--,e=--,m=--)",
+ ["en"]="no hyphenations -- for -- (n=--,e=--,m=--)",
+ ["fr"]="pas d'hyphenations -- pour -- (n=--,e=--,m=--)",
+ ["it"]="niente sillabazione -- per -- (n=--,e=--,m=--)",
+ ["nl"]="geen afbreekdefinities -- voor -- (n=--,e=--,m=--)",
+ ["no"]="ingen orddelingsdefinisjon -- for -- (n=--,e=--,m=--)",
+ ["ro"]="nu exista despartire in silabe -- pentru -- (n=--,e=--,m=--)",
+ },
+ ["5"]={
+ ["cs"]="vzory pro -- nenacteny",
+ ["de"]="Trennmuster fuer -- nicht geladen",
+ ["en"]="patterns for -- not loaded",
+ ["fr"]="les motifs pour -- ne sont pas chargés",
+ ["it"]="schemi per -- non caricati",
+ ["nl"]="afbreekpatronen voor -- niet geladen",
+ ["no"]="orddelingsmønster for -- er ikke lest inn",
+ ["ro"]="sabloanele pentru -- nu sunt incarcate",
+ },
+ ["6"]={
+ ["cs"]="jazyk -- neni definovan",
+ ["de"]="Sprache -- ist undefiniert",
+ ["en"]="language -- is undefined",
+ ["fr"]="langue -- non définie",
+ ["it"]="lingua -- non definita",
+ ["nl"]="taal -- is niet gedefinieerd",
+ ["no"]="spràk -- er udefinert",
+ ["ro"]="limba -- nu este definita",
+ },
+ ["7"]={
+ ["cs"]="specificke volby jazyka [--] zavadeji -- (zavlecenou) mezeru",
+ ["de"]="Sprachenspezifische Option [--] fuegt eine Luecke von -- ein",
+ ["en"]="language specific options [--] introduce a -- skip",
+ ["fr"]="les options spécifiques de langue [--] introduisent un -- saut",
+ ["it"]="opzioni specifiche per la lingua [--] introducono un salto --",
+ ["nl"]="taal specifieke opties [--] introduceren een skip van --",
+ ["no"]="spràk spesifikk opsjon [--] introduserer et -- hopp",
+ ["ro"]="optiunile specifice ale limbii [--] introduc un spatiu --",
+ },
+ ["8"]={
+ ["cs"]="specificke volby jazyka [--] bez mezer pripojeny",
+ ["de"]="Sprachenspezifische Option [--] nahtlos hinzugefuegt",
+ ["en"]="language specific options [--] seamless appended",
+ ["fr"]="les options spécifiques de langue [--] sont ajoutés en douceur",
+ ["it"]="opzioni specifiche per la lingua [--] aggiunte trasparentemente",
+ ["nl"]="taal specifieke opties [--] naadloos toegevoegd",
+ ["no"]="spràk spesifikk opsjon [--] problemfritt tilføyd",
+ ["ro"]="optiunile specifice ale limbii [--] adaugate",
+ },
+ ["9"]={
+ ["cs"]="language -- is active",
+ ["de"]="Sprache -- ist aktiv",
+ ["en"]="language -- is active",
+ ["fr"]="la langue -- est active",
+ ["it"]="lingua -- attiva",
+ ["nl"]="taal -- is actief",
+ ["no"]="spràk -- er aktivt",
+ ["ro"]="limba -- este activa",
+ },
+ ["files"]={ "lang-ini.mkii", "lang-ini.mkiv" },
+ ["title"]={
+ ["cs"]="jazyky",
+ ["de"]="Sprache",
+ ["en"]="language",
+ ["fr"]="langue",
+ ["it"]="lingua",
+ ["nl"]="taal",
+ ["no"]="sprøk",
+ ["ro"]="limbi",
+ },
+ },
+ ["metapost"]={
+ ["1"]={
+ ["cs"]="loading metapost library --",
+ ["de"]="Lade metapost Bibliothek --",
+ ["en"]="loading metapost library --",
+ ["fr"]="chargement de la bibliothèque metapost --",
+ ["it"]="caricamento della libreria metapost --",
+ ["nl"]="metapost bibliotheek -- wordt geladen",
+ ["no"]="metapost bibliotek -- blir lest inn",
+ ["ro"]="se incarca biblioteca metapost --",
+ },
+ ["files"]={ "meta-ini.mkii", "meta-ini.mkiv" },
+ ["title"]={
+ ["cs"]="metapost",
+ ["de"]="metapost",
+ ["en"]="metapost",
+ ["fr"]="metapost",
+ ["it"]="metapost",
+ ["nl"]="metapost",
+ ["no"]="metapost",
+ ["ro"]="metapost",
+ },
+ },
+ ["references"]={
+ ["1"]={
+ ["cs"]="neznama reference --",
+ ["de"]="unbekannte Referenz --",
+ ["en"]="unknown reference --",
+ ["fr"]="réference -- inconnue",
+ ["it"]="riferimento sconosciuto --",
+ ["nl"]="onbekende verwijzing --",
+ ["no"]="ukjent referanse --",
+ ["ro"]="referinta necunoscuta --",
+ },
+ ["2"]={
+ ["cs"]="duplicitni reference -- na strane --",
+ ["de"]="doppelte Referenz -- auf Seite --",
+ ["en"]="duplicate reference -- on page --",
+ ["fr"]="réference -- dupliquée à la page --",
+ ["it"]="riferimento duplicato -- a pagina --",
+ ["nl"]="dubbele verwijzing -- op pagina --",
+ ["no"]="duplikat referanse -- pø side --",
+ ["ro"]="referinta duplicat -- la pagina --",
+ },
+ ["21"]={
+ ["cs"]="dokument -- nacten",
+ ["de"]="Dokument -- geladen",
+ ["en"]="document -- loaded",
+ ["fr"]="document -- chargé",
+ ["it"]="documento -- caricato",
+ ["nl"]="document -- geladen",
+ ["no"]="dokument -- er lest inn",
+ ["ro"]="documentul -- este incarcat",
+ },
+ ["22"]={
+ ["cs"]="dokument -- neni interaktivni",
+ ["de"]="Dokument -- ist nicht aktiv",
+ ["en"]="document -- is not interactive",
+ ["fr"]="le document -- n'est pas interactif",
+ ["it"]="il documento -- non ø interattivo",
+ ["nl"]="document -- is niet interactief",
+ ["no"]="dokument -- er ikke interaktivt",
+ ["ro"]="documentul -- nu este interactiv",
+ },
+ ["23"]={
+ ["cs"]="obskurni (nejasna) reference -- (prefix=--)",
+ ["de"]="Obskure Referenz -- (Prefix=--)",
+ ["en"]="obscure reference -- (prefix=--)",
+ ["fr"]="reference -- indéterminé (préfixe=--)",
+ ["it"]="riferimento ambiguo -- (prefisso=--)",
+ ["nl"]="onduidelijke verwijzing -- (prefix=--)",
+ ["no"]="obskur referanse -- (Prefix=--)",
+ ["ro"]="referinta obscura -- (prefix=--)",
+ },
+ ["24"]={
+ ["en"]="references from document '--' are not exported",
+ },
+ ["25"]={
+ ["en"]="references from document '--' are not imported (export again)",
+ },
+ ["26"]={
+ ["en"]="references from document '--' are imported",
+ },
+ ["3"]={
+ ["cs"]="neznamy typ reference --",
+ ["de"]="unbekannte Referenz Typ --",
+ ["en"]="unknown reference type --",
+ ["fr"]="type -- de réference inconnu",
+ ["it"]="riferimento di tipo sconosciuto --",
+ ["nl"]="type verwijzing -- onbekend",
+ ["no"]="ukjent referansetype --",
+ ["ro"]="tip necunoscut de referinta --",
+ },
+ ["30"]={
+ ["cs"]="neznamy objekt --",
+ ["de"]="unbekanntes Object --",
+ ["en"]="unknown object --",
+ ["fr"]="objet -- inconnu",
+ ["it"]="oggetto sconosciuto --",
+ ["nl"]="onbekend object --",
+ ["no"]="ukjent objekt --",
+ ["ro"]="obiect necunoscut --",
+ },
+ ["31"]={
+ ["cs"]="duplicitni object --",
+ ["de"]="doppeltes Object --",
+ ["en"]="duplicate object --",
+ ["fr"]="objet -- dupliqué",
+ ["it"]="oggetto duplicato --",
+ ["nl"]="dubbel object --",
+ ["no"]="duplikat objekt --",
+ ["ro"]="obiect duplicat --",
+ },
+ ["4"]={
+ ["cs"]="nedovolena reference --",
+ ["de"]="illegale Referenz --",
+ ["en"]="illegal reference --",
+ ["fr"]="réference -- inconnue",
+ ["it"]="riferimento illecito --",
+ ["nl"]="verboden verwijzing --",
+ ["no"]="ulovlig referanse --",
+ ["ro"]="referinta eronata --",
+ },
+ ["files"]={ "core-obj.tex", "core-ref.tex", "strc-ref.tex" },
+ ["title"]={
+ ["cs"]="reference",
+ ["de"]="referenzen",
+ ["en"]="references",
+ ["fr"]="réferences",
+ ["it"]="riferimenti",
+ ["nl"]="verwijzingen",
+ ["no"]="referanser",
+ ["ro"]="referinte",
+ },
+ },
+ ["regimes"]={
+ ["1"]={
+ ["cs"]="kodovani --",
+ ["de"]="Kodierung --",
+ ["en"]="regime --",
+ ["fr"]="encodage --",
+ ["it"]="codifica --",
+ ["nl"]="regime --",
+ ["no"]="koding --",
+ ["ro"]="codificarea --",
+ },
+ ["2"]={
+ ["cs"]="je nacteno kodovani --",
+ ["de"]="Kodierung -- ist geladen",
+ ["en"]="regime -- is loaded",
+ ["fr"]="l'encodage -- est chargé",
+ ["it"]="codifica -- caricata",
+ ["nl"]="regime -- wordt geladen",
+ ["no"]="koding -- er lest inn",
+ ["ro"]="codificarea -- este Encarcata",
+ },
+ ["3"]={
+ ["cs"]="nezname kodovani --",
+ ["de"]="Unbekannte Kodierung --",
+ ["en"]="unknown regime --",
+ ["fr"]="encodage -- inconnu",
+ ["it"]="codifica sconosciuta --",
+ ["nl"]="onbekend regime --",
+ ["no"]="ukjent koding --",
+ ["ro"]="codificarea -- este necunoscuta",
+ },
+ ["files"]={ "regi-ini.mkii" },
+ ["title"]={
+ ["cs"]="kodovani",
+ ["de"]="Kodierung",
+ ["en"]="regime",
+ ["fr"]="encodage",
+ ["it"]="codifica",
+ ["nl"]="regime",
+ ["no"]="koding",
+ ["ro"]="codificari",
+ },
+ },
+ ["specials"]={
+ ["1"]={
+ ["cs"]="-- nacteno",
+ ["de"]="-- geladen",
+ ["en"]="-- loaded",
+ ["fr"]="-- chargé",
+ ["it"]="-- caricato",
+ ["nl"]="-- geladen",
+ ["no"]="-- er lest inn",
+ ["ro"]="-- incarcat",
+ },
+ ["2"]={
+ ["cs"]="neni dovoleno hlubsi zanoreni --",
+ ["de"]="keine tiefere Verschachtelung erlaubt --",
+ ["en"]="no deeper nesting is permitted --",
+ ["fr"]="pas d'imbracations plus profondes ne sont permises --",
+ ["it"]="non ø permesso un annidamento maggiore --",
+ ["nl"]="verdere nesting is niet toegestaan --",
+ ["no"]="dypere 'nesting' er ikke tillatt --",
+ ["ro"]="nu este permis un nivel de imbricare mai mare --",
+ },
+ ["3"]={
+ ["cs"]="-- je resetovano",
+ ["de"]="-- ist zurueckgesetzt",
+ ["en"]="-- is reset",
+ ["fr"]="-- est remis à zéro",
+ ["it"]="-- reimpostato",
+ ["nl"]="-- gereset",
+ ["no"]="-- er tilbakestilt",
+ ["ro"]="-- s-a resetat",
+ },
+ ["4"]={
+ ["cs"]="prikaz -- neexistuje",
+ ["de"]="Befehl -- existiert nicht",
+ ["en"]="command -- does not exist",
+ ["fr"]="la commande -- n'existe pas",
+ ["it"]="il comando -- non esiste",
+ ["nl"]="commando -- bestaat niet",
+ ["no"]="kommando -- eksisterer ikke",
+ ["ro"]="comanda -- nu exista",
+ },
+ ["5"]={
+ ["cs"]="nacita se definicni soubor --",
+ ["de"]="lade Definitionsdatei --",
+ ["en"]="loading definition file --",
+ ["fr"]="chargement du fichier de définition --",
+ ["it"]="caricamento del file di definizione --",
+ ["nl"]="definitiefile -- wordt geladen",
+ ["no"]="leser inn definisjonsfil for --",
+ ["ro"]="se incarca fisierul de definitii --",
+ },
+ ["6"]={
+ ["cs"]="zanoreni neni dovoleno",
+ ["de"]="Verschachtelung nicht erlaubt",
+ ["en"]="nesting is not permitted",
+ ["fr"]="l'imbrication n'est pas permise",
+ ["it"]="annidamento non permesso",
+ ["nl"]="nesting is niet toegestaan",
+ ["no"]="'nesting' er ikke tillatt",
+ ["ro"]="imbricarea nu este permisa",
+ },
+ ["7"]={
+ ["cs"]="neznamy ovladac (driver) --",
+ ["de"]="unbekante Driver --",
+ ["en"]="unknown driver --",
+ ["fr"]="pilote -- inconnu",
+ ["it"]="driver sconosciuto --",
+ ["nl"]="onbekende driver --",
+ ["no"]="ukjent driver --",
+ ["ro"]="driver necunoscut --",
+ },
+ ["files"]={ "spec-ini.tex" },
+ ["title"]={
+ ["cs"]="speciality",
+ ["de"]="spezielles",
+ ["en"]="specials",
+ ["fr"]="specials",
+ ["it"]="specialitø",
+ ["nl"]="specials",
+ ["no"]="specials",
+ ["ro"]="specials",
+ },
+ },
+ ["structures"]={
+ ["1"]={
+ ["cs"]="zacatek oddilu (sekce) --",
+ ["de"]="Begin des Abschnittsblocks --",
+ ["en"]="begin of sectionblock --",
+ ["fr"]="début de blocsection --",
+ ["it"]="inizio del blocco (sezione) --",
+ ["nl"]="begin van sectieblok --",
+ ["no"]="starten av blokk -- (seksjon)",
+ ["ro"]="inceput de bloc sectiune --",
+ },
+ ["2"]={
+ ["cs"]="konec oddilu (sekce) --",
+ ["de"]="Ende des Abschnittsblocks --",
+ ["en"]="end of sectionblock --",
+ ["fr"]="fin de blocsection --",
+ ["it"]="fine del blocco (sezione) --",
+ ["nl"]="eind van sectieblok --",
+ ["no"]="slutten av blokk -- (seksjon)",
+ ["ro"]="sfarsit de bloc sectiune --",
+ },
+ ["files"]={ "core-sec.mkii", "core-sec.mkiv", "strc-sbe.tex" },
+ ["title"]={
+ ["cs"]="struktury",
+ ["de"]="struktur",
+ ["en"]="structure",
+ ["fr"]="structure",
+ ["it"]="struttura",
+ ["nl"]="structuur",
+ ["no"]="struktur",
+ ["ro"]="structuri",
+ },
+ },
+ ["symbols"]={
+ ["1"]={
+ ["cs"]="nacita se soubor symbolu --",
+ ["de"]="Lade Symboldatei --",
+ ["en"]="loading symbolset --",
+ ["fr"]="chargement du jeu de symbole --",
+ ["it"]="caricamento gruppo di simboli --",
+ ["nl"]="symboolset -- wordt geladen",
+ ["no"]="leser inn symbolsett --",
+ ["ro"]="se incarca setul de simboluri --",
+ },
+ ["files"]={ "symb-ini.tex" },
+ ["title"]={
+ ["cs"]="symboly",
+ ["de"]="Symbole",
+ ["en"]="symbols",
+ ["fr"]="symboles",
+ ["it"]="simboli",
+ ["nl"]="symbolen",
+ ["no"]="symboler",
+ ["ro"]="simboluri",
+ },
+ },
+ ["systems"]={
+ ["1"]={
+ ["cs"]="nacteni pomocneho souboru odlozeno (typemode)",
+ ["de"]="Laden der Hilfsdatei aufgeschoben (Eingabe-Modus)",
+ ["en"]="loading utility-file postponed (typemode)",
+ ["fr"]="chargement de fichier utilitaire reporté (typemode)",
+ ["it"]="caricamento dei file supplementari posticipato (typemode)",
+ ["nl"]="laden hulpfile uitgesteld (typemode)",
+ ["no"]="innlesning av hjelpefila utsatt (typemode)",
+ ["ro"]="se incarca utilitarul-fisierul este amanat (typemode)",
+ },
+ ["10"]={
+ ["cs"]="nepouzivejte em v --",
+ ["de"]="Benutzte kein em in --",
+ ["en"]="don't use em in --",
+ ["fr"]="n'utilisez pas em dans --",
+ ["it"]="non usare em in --",
+ ["nl"]="gebruik geen em in --",
+ ["no"]="ikke bruk em i --",
+ ["ro"]="nu folositi em in --",
+ },
+ ["11"]={
+ ["cs"]="vytvarim jednoduchy pomocny soubor",
+ ["de"]="Erstelle einfache Hilfdatei",
+ ["en"]="building simple util",
+ ["fr"]="construction util simple",
+ ["it"]="costruzione di un semplice supplemento",
+ ["nl"]="aanmaken basale hulpfile",
+ ["no"]="lager enkel hjelpefil",
+ ["ro"]="se creeaza un utilitar simplu",
+ },
+ ["12"]={
+ ["cs"]="pomosny soubor neni setriden, pouzijte texutil",
+ ["de"]="Die Hilfdatei ist nicht sortiert, verwende texutil",
+ ["en"]="the utility-file is not sorted, use texutil",
+ ["fr"]="le fichier utilitaire n'est pas trié, utilise texutil",
+ ["it"]="file di supplemento non ordinato, usare texutil",
+ ["nl"]="de hulpfile is niet gesorteerd, gebruik texutil",
+ ["no"]="hjelpefila er ikke sortert, bruk texutil",
+ ["ro"]="fisierul utilitar nu este sortat, folositi texutil",
+ },
+ ["13"]={
+ ["cs"]="znacka -- definovana --",
+ ["de"]="Beschriftung -- definiert --",
+ ["en"]="mark -- defined --",
+ ["fr"]="marquage -- defini --",
+ ["it"]="marcatura -- definita --",
+ ["nl"]="markering -- gedefinieerd --",
+ ["no"]="markering -- definert --",
+ ["ro"]="marcajul -- definit --",
+ },
+ ["14"]={
+ ["cs"]="vynucena nova stranka v seznamu na --",
+ ["de"]="Erzwungendes Seitenumbruch in Liste bei --",
+ ["en"]="forced newpage in list at --",
+ ["fr"]="nouvellepage forcée dans la liste à --",
+ ["it"]="nuova pagina obbligata in lista a --",
+ ["nl"]="geforceerde paginaovergang in lijst voor --",
+ ["no"]="tvunget sideskift i liste ved --",
+ ["ro"]="s-a fortat trecere pa pagina noua in lista la --",
+ },
+ ["15"]={
+ ["cs"]="uklada se buffer --",
+ ["de"]="Speichere Buffer --",
+ ["en"]="saving buffer --",
+ ["fr"]="sauvegarde du tampon (buffer) --",
+ ["it"]="salvataggio del buffer --",
+ ["nl"]="wegschrijven buffer --",
+ ["no"]="lagrer Buffer --",
+ ["ro"]="buffer salvat --",
+ },
+ ["16"]={
+ ["cs"]="sazi se buffer --",
+ ["de"]="Setzte Buffer --",
+ ["en"]="typesetting buffer --",
+ ["fr"]="composition du tampon (buffer) --",
+ ["it"]="composizione del buffer --",
+ ["nl"]="inlezen buffer --",
+ ["no"]="tegnsetter buffer --",
+ ["ro"]="buffer-ul -- s-a cules",
+ },
+ ["17"]={
+ ["cs"]="sazi se doslovny (verbatim) buffer --",
+ ["de"]="Setzte tippen-Buffer --",
+ ["en"]="typesetting verbatim buffer --",
+ ["fr"]="composition textuelle du tampon (buffer) --",
+ ["it"]="composizione verbatim del buffer --",
+ ["nl"]="verbatim inlezen buffer --",
+ ["no"]="tegnsetter verbatim-buffer --",
+ ["ro"]="se culege buffer-ul verbatim --",
+ },
+ ["18"]={
+ ["cs"]="synonymum -- -- neexistuje",
+ ["de"]="Synonym -- -- existiert nicht",
+ ["en"]="synonym -- -- does not exist",
+ ["fr"]="le synonyme -- -- n'existe pas",
+ ["it"]="sinonimo -- -- non esistente",
+ ["nl"]="synoniem -- -- bestaat niet",
+ ["no"]="synonym -- -- eksisterer ikke",
+ ["ro"]="sinonimul -- -- nu exista",
+ },
+ ["19"]={
+ ["cs"]="vyznam (synonyma) -- nacten",
+ ["de"]="Bedeutung (synonyme) von -- geladen",
+ ["en"]="meaning (synonyms) of -- loaded",
+ ["fr"]="signification (synonymes) de -- chargée",
+ ["it"]="significato (sinonimi) di -- caricato",
+ ["nl"]="betekenissen (synoniemen) van -- geladen",
+ ["no"]="betydning (synonymer) av -- er lest inn",
+ ["ro"]="intelesul (sinonimele) pentru -- incarcat",
+ },
+ ["2"]={
+ ["cs"]="-- nacteno",
+ ["de"]="-- geladen",
+ ["en"]="-- loaded",
+ ["fr"]="-- chargé",
+ ["it"]="-- caricato",
+ ["nl"]="-- geladen",
+ ["no"]="-- er lest inn",
+ ["ro"]="-- s-a incarcat",
+ },
+ ["20"]={
+ ["cs"]="vyznam (trideni) -- nacten",
+ ["de"]="Bedeutung (sortieren) von -- geladen",
+ ["en"]="meaning (sorts) of -- loaded",
+ ["fr"]="signification (tris) de -- chargée",
+ ["it"]="significato (specie) di -- caricato",
+ ["nl"]="betekenissen (sorteren) van -- geladen",
+ ["no"]="betydning (sorterer) av -- er lest inn",
+ ["ro"]="intelesul (ordinea) pentru -- incarcat",
+ },
+ ["21"]={
+ ["cs"]="pomocny soubor necten",
+ ["de"]="Die Hilfsdatei ist nicht geladen",
+ ["en"]="no utility data is loaded",
+ ["fr"]="pas de données utilitaires chargées",
+ ["it"]="nessuna informazione supplementare caricata",
+ ["nl"]="de hulpfile is niet geladen",
+ ["no"]="hjelpefila er ikke lest inn",
+ ["ro"]="nici o data utilitara nu este incarcata",
+ },
+ ["22"]={
+ ["cs"]="pouzijte platny pomocny soubor",
+ ["de"]="Benoetige gueltige Hilfsdateie",
+ ["en"]="use a valid utilityfile",
+ ["fr"]="utilise un fichier utilitaire valide",
+ ["it"]="usare un file supplementare valido",
+ ["nl"]="gebruik een goede hulpfile",
+ ["no"]="bruk en gyldig hjelpefil",
+ ["ro"]="folositi un fisier utilitar valid",
+ },
+ ["23"]={
+ ["cs"]="-- upraveno na --",
+ ["de"]="-- angeordnet auf --",
+ ["en"]="-- arranged at --",
+ ["fr"]="-- arrangé à --",
+ ["it"]="-- sistemato a --",
+ ["nl"]="-- gearrangeerd op --",
+ ["no"]="-- arrangert på --",
+ ["ro"]="-- aranjat la --",
+ },
+ ["24"]={
+ ["cs"]="plovouci bloky",
+ ["de"]="Fliessbloecke",
+ ["en"]="Floatblocks",
+ ["fr"]="blocsflottants",
+ ["it"]="Oggetti mobili",
+ ["nl"]="Plaatsblokken",
+ ["no"]="Flytblokker",
+ ["ro"]="Blocuri",
+ },
+ ["25"]={
+ ["cs"]="reference",
+ ["de"]="Referenzen",
+ ["en"]="References",
+ ["fr"]="Réferences",
+ ["it"]="Riferimenti",
+ ["nl"]="Verwijzingen",
+ ["no"]="Referanser",
+ ["ro"]="Referinte",
+ },
+ ["26"]={
+ ["cs"]="registry",
+ ["de"]="Register",
+ ["en"]="Registers",
+ ["fr"]="Registres",
+ ["it"]="Registri",
+ ["nl"]="Registers",
+ ["no"]="Registere",
+ ["ro"]="Registri",
+ },
+ ["27"]={
+ ["cs"]="verze",
+ ["de"]="Version",
+ ["en"]="Version",
+ ["fr"]="Version",
+ ["it"]="Versione",
+ ["nl"]="Versie",
+ ["no"]="Versjon",
+ ["ro"]="Versiune",
+ },
+ ["4"]={
+ ["cs"]="prikaz -- je jiz definovan",
+ ["de"]="Befehl -- ist bereits definiert",
+ ["en"]="command -- is already defined",
+ ["fr"]="la commande -- est déjà définie",
+ ["it"]="comando -- già definito",
+ ["nl"]="commando -- is al gedefinieerd",
+ ["no"]="kommando -- er allerede definert",
+ ["ro"]="comanda -- este deja definita",
+ },
+ ["41"]={
+ ["cs"]="externi soubor -- ve skupine -- neexistuje",
+ ["de"]="Externe Datei -- in Gruppe -- existiert nicht",
+ ["en"]="external file -- in group -- does not exist",
+ ["fr"]="le fichier externe -- du groupe -- n'existe pas",
+ ["it"]="il file esterno -- del gruppo -- non esiste",
+ ["nl"]="externe file -- in groep -- bestaat niet",
+ ["no"]="ekstern fil -- i gruppe -- eksisterer ikke",
+ ["ro"]="fisierul extern -- din grupul -- nu exista",
+ },
+ ["5"]={
+ ["cs"]="makra z -- nactena",
+ ["de"]="Modul -- geladen",
+ ["en"]="module -- loaded",
+ ["fr"]="module -- chargé",
+ ["it"]="macro del modulo -- caricate",
+ ["nl"]="module -- geladen",
+ ["no"]="makroene i modul -- er lest inn",
+ ["ro"]="macro-urile din modulul -- s-au incarcat",
+ },
+ ["6"]={
+ ["cs"]="zadna makra v -- nenalezena",
+ ["de"]="Modul -- gefunden",
+ ["en"]="module -- not found",
+ ["fr"]="module -- non trouvé",
+ ["it"]="nessuna macro trovata nel modulo --",
+ ["nl"]="geen module -- gevonden",
+ ["no"]="ingen makroer funnet i modul ---",
+ ["ro"]="nu s-au gasit macro-uri in modulul --",
+ },
+ ["7"]={
+ ["cs"]="makra z -- jsou jiz nactena",
+ ["de"]="Modul -- bereits geladen",
+ ["en"]="module -- already loaded",
+ ["fr"]="module -- déjà chargé",
+ ["it"]="macro del modulo -- già caricate",
+ ["nl"]="module -- reeds geladen",
+ ["no"]="makroene i modul -- er allerede lest inn",
+ ["ro"]="macro-urile din modulul -- s-au incarcat deja",
+ },
+ ["8"]={
+ ["cs"]="nova verze pomocneho souboru, je treba druheho behu",
+ ["de"]="Neue Version der Hilfsdatei, zweiter Durchlauf benoetigt",
+ ["en"]="new version of utility file, second pass needed",
+ ["fr"]="nouvelle version de fichier utilitaire, seconde passe nécessaire",
+ ["it"]="nuova versione del file supplementare, seconda passata necessaria",
+ ["nl"]="nieuwe versie hulpfile, tweede run nodig",
+ ["no"]="ny versjon av hjelpefil, andre gjennomkjøring nødvendig",
+ ["ro"]="o noua versiune de fisier utilitar, este necesara o noua trecere",
+ },
+ ["9"]={
+ ["cs"]="-- nenalezeno/nezpracovano",
+ ["de"]="-- nicht gefunden/verarbeitet",
+ ["en"]="-- not found/processed",
+ ["fr"]="-- non trouvé/traité",
+ ["it"]="-- non trovato/elaborato",
+ ["nl"]="-- niet gevonden/geplaatst",
+ ["no"]="-- ikke funnet/behandlet",
+ ["ro"]="-- nu este gasit/procesat",
+ },
+ ["91"]={
+ ["en"]="papertray --",
+ ["nl"]="papierlade --",
+ },
+ ["files"]={ "core-mis.tex", "page-ini.tex", "prag-gen.tex", "strc-mar.tex" },
+ ["title"]={
+ ["cs"]="system",
+ ["de"]="system",
+ ["en"]="system",
+ ["fr"]="système",
+ ["it"]="sistema",
+ ["nl"]="systeem",
+ ["no"]="system",
+ ["ro"]="sistem",
+ },
+ },
+ ["textblocks"]={
+ ["1"]={
+ ["cs"]="nova verze, je treba druhy beh",
+ ["de"]="neue Version, zweiter Durchlauf benoetigt",
+ ["en"]="new version, second pass needed",
+ ["fr"]="nouvelle version, une seconde passe est nécessaire",
+ ["it"]="nuova versione, seconda passata necessaria",
+ ["nl"]="nieuwe versie, tweede run nodig",
+ ["no"]="ny versjon, andre gjennomkjøring nødvendig",
+ ["ro"]="o noua versiune, este nevoie de inca o trecere",
+ },
+ ["10"]={
+ ["cs"]="-- nacteno a zpracovano",
+ ["de"]="-- geladen und verarbeitet",
+ ["en"]="-- loaded and processed",
+ ["fr"]="-- chargé et traité",
+ ["it"]="-- caricato ed elaborato",
+ ["nl"]="-- geladen en verwerkt",
+ ["no"]="-- lest inn og behandlet",
+ ["ro"]="-- incarcat si procesat",
+ },
+ ["11"]={
+ ["cs"]="-- nacteno a vysazeno",
+ ["de"]="-- geladen und gesetzt",
+ ["en"]="-- loaded and typeset",
+ ["fr"]="-- chargé et composé",
+ ["it"]="-- caricato e composto",
+ ["nl"]="-- geladen en geplaatst",
+ ["no"]="-- lest inn og tegnsatt",
+ ["ro"]="-- incarcat si cules",
+ },
+ ["12"]={
+ ["cs"]="-- preskoceno",
+ ["de"]="-- ausgelassen",
+ ["en"]="-- skipped",
+ ["fr"]="-- sauté",
+ ["it"]="-- saltato",
+ ["nl"]="-- overgeslagen",
+ ["no"]="-- utelatt",
+ ["ro"]="-- sarit peste",
+ },
+ ["2"]={
+ ["cs"]="zapisuji bloky do --",
+ ["de"]="schreibe Bloecke zu --",
+ ["en"]="writing blocks to --",
+ ["fr"]="ecriture des blocs vers --",
+ ["it"]="scrittura dei blocchi su --",
+ ["nl"]="wegschrijven blokken naar --",
+ ["no"]="skriver blokker til --",
+ ["ro"]="se scriu blocurile in --",
+ },
+ ["3"]={
+ ["cs"]="ctu bloky z --",
+ ["de"]="lese Bloecke von --",
+ ["en"]="reading blocks from --",
+ ["fr"]="lecture des blocs en provenance de --",
+ ["it"]="lettura dei blocchi da --",
+ ["nl"]="inlezen blokken uit --",
+ ["no"]="leser blokker fra --",
+ ["ro"]="se citesc blocurile din --",
+ },
+ ["4"]={
+ ["cs"]="je treba druhy beh",
+ ["de"]="zweiter Durchlauf benoetigt",
+ ["en"]="second pass needed",
+ ["fr"]="seconde passe nécessaire",
+ ["it"]="seconda passata necessaria",
+ ["nl"]="er is een tweede run nodig",
+ ["no"]="andre gjennomkjøring nødvendig",
+ ["ro"]="este nevoie de inca o trecere",
+ },
+ ["5"]={
+ ["cs"]="-- neni skryto",
+ ["de"]="-- nicht verborgen",
+ ["en"]="-- not hidden",
+ ["fr"]="-- non caché",
+ ["it"]="-- non nascosto",
+ ["nl"]="-- niet verborgen",
+ ["no"]="-- ikke skjult",
+ ["ro"]="-- nu este ascuns",
+ },
+ ["6"]={
+ ["cs"]="-- skryto a zpracovano",
+ ["de"]="-- verborgen und verarbeitet",
+ ["en"]="-- hidden and processed",
+ ["fr"]="-- caché et traité",
+ ["it"]="-- nascosto ed elaborato",
+ ["nl"]="-- verborgen en verwerkt",
+ ["no"]="-- skjult og behandlet",
+ ["ro"]="-- ascuns si procesat",
+ },
+ ["7"]={
+ ["cs"]="-- skryto",
+ ["de"]="-- verborgen",
+ ["en"]="-- hidden",
+ ["fr"]="-- caché",
+ ["it"]="-- nascosto",
+ ["nl"]="-- verborgen",
+ ["no"]="-- skjult",
+ ["ro"]="-- ascuns",
+ },
+ ["8"]={
+ ["cs"]="-- vysazeno",
+ ["de"]="-- gesetzt",
+ ["en"]="-- typeset",
+ ["fr"]="-- composé",
+ ["it"]="-- composto",
+ ["nl"]="-- gehandhaafd",
+ ["no"]="-- tegnsatt",
+ ["ro"]="-- cules",
+ },
+ ["9"]={
+ ["cs"]="-- nevysazeno",
+ ["de"]="-- nicht gesetzt",
+ ["en"]="-- not typeset",
+ ["fr"]="-- non composé",
+ ["it"]="-- non composto",
+ ["nl"]="-- niet gehandhaafd",
+ ["no"]="-- ikke tegnsatt",
+ ["ro"]="-- nu este cules",
+ },
+ ["files"]={ "core-blk.tex" },
+ ["title"]={
+ ["cs"]="textovyblok",
+ ["de"]="textblock",
+ ["en"]="textblocks",
+ ["fr"]="blocs de texte",
+ ["it"]="blocchi di testo",
+ ["nl"]="tekstblokken",
+ ["no"]="tekstblokker",
+ ["ro"]="blocuri de text",
+ },
+ },
+ ["verbatims"]={
+ ["1"]={
+ ["cs"]="soubor -- neexistuje",
+ ["de"]="Datei -- existiert nicht",
+ ["en"]="file -- does not exist",
+ ["fr"]="le fichier -- n'existe pas",
+ ["it"]="il file -- non esiste",
+ ["nl"]="file -- bestaat niet",
+ ["no"]="fil -- eksisterer ikke",
+ ["ro"]="fisierul -- nu exista",
+ },
+ ["files"]={ "core-ver.tex" },
+ ["title"]={
+ ["cs"]="verbatim",
+ ["de"]="verbatim",
+ ["en"]="verbatim",
+ ["fr"]="verbatim",
+ ["it"]="verbatim",
+ ["nl"]="typen",
+ ["no"]="verbatim",
+ ["ro"]="verbatim",
+ },
+ },
+ ["versions"]={
+ ["1"]={
+ ["cs"]="postradam @+",
+ ["de"]="fehlendes @+",
+ ["en"]="missing @+",
+ ["fr"]="@+ manquant",
+ ["it"]="@+ mancante",
+ ["nl"]="er mankeert een @+",
+ ["no"]="manglende @+",
+ ["ro"]="lipseste @+",
+ },
+ ["2"]={
+ ["cs"]="oznacuji se strany",
+ ["de"]="Erstelle Seiten",
+ ["en"]="marking pages",
+ ["fr"]="marquage des pages",
+ ["it"]="marcatura pagine",
+ ["nl"]="markeren pagina's",
+ ["no"]="markerer sider",
+ ["ro"]="pagini marcate",
+ },
+ ["3"]={
+ ["cs"]="oznacene strany: --",
+ ["de"]="Ausgewaehlte Seiten: --",
+ ["en"]="selected pages: --",
+ ["fr"]="pages sélectionnées : --",
+ ["it"]="pagine selezionate: --",
+ ["nl"]="geselecteerde pagina's: --",
+ ["no"]="valgte sider: --",
+ ["ro"]="pagini selectate: --",
+ },
+ ["files"]={ "core-int.tex" },
+ ["title"]={
+ ["cs"]="verze",
+ ["de"]="Version",
+ ["en"]="version",
+ ["fr"]="version",
+ ["it"]="version",
+ ["nl"]="versie",
+ ["no"]="versjon",
+ ["ro"]="versiuni",
+ },
+ },
+}
diff --git a/tex/context/base/mult-mfr.tex b/tex/context/base/mult-mfr.tex
new file mode 100644
index 000000000..78e4f9f17
--- /dev/null
+++ b/tex/context/base/mult-mfr.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{réference -- inconnue}
+\setinterfacemessage{references}{3}{type -- de réference inconnu}
+\setinterfacemessage{references}{2}{réference -- dupliquée à la page --}
+\setinterfacemessage{references}{4}{réference -- inconnue}
+\setinterfacemessage{references}{30}{objet -- inconnu}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{réferences}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{objet -- dupliqué}
+\setinterfacemessage{references}{21}{document -- chargé}
+\setinterfacemessage{references}{22}{le document -- n'est pas interactif}
+\setinterfacemessage{references}{23}{reference -- indéterminé (préfixe=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{number --}
+\setinterfacemessage{handlings}{1}{manipulation -- de police}
+\setinterfacemessage{handlings}{3}{manipulation -- inconnue de police}
+\setinterfacemessage{handlings}{2}{la manipulation -- de police est chargée}
+\setinterfacemessage{handlings}{title}{manipulation}
+\setinterfacemessage{systems}{title}{système}
+\setinterfacemessage{systems}{41}{le fichier externe -- du groupe -- n'existe pas}
+\setinterfacemessage{systems}{9}{-- non trouvé/traité}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{nouvelle version de fichier utilitaire, seconde passe nécessaire}
+\setinterfacemessage{systems}{21}{pas de données utilitaires chargées}
+\setinterfacemessage{systems}{20}{signification (tris) de -- chargée}
+\setinterfacemessage{systems}{5}{module -- chargé}
+\setinterfacemessage{systems}{4}{la commande -- est déjà définie}
+\setinterfacemessage{systems}{27}{Version}
+\setinterfacemessage{systems}{26}{Registres}
+\setinterfacemessage{systems}{25}{Réferences}
+\setinterfacemessage{systems}{24}{blocsflottants}
+\setinterfacemessage{systems}{1}{chargement de fichier utilitaire reporté (typemode)}
+\setinterfacemessage{systems}{23}{-- arrangé à --}
+\setinterfacemessage{systems}{22}{utilise un fichier utilitaire valide}
+\setinterfacemessage{systems}{2}{-- chargé}
+\setinterfacemessage{systems}{19}{signification (synonymes) de -- chargée}
+\setinterfacemessage{systems}{18}{le synonyme -- -- n'existe pas}
+\setinterfacemessage{systems}{7}{module -- déjà chargé}
+\setinterfacemessage{systems}{6}{module -- non trouvé}
+\setinterfacemessage{systems}{14}{nouvellepage forcée dans la liste à --}
+\setinterfacemessage{systems}{15}{sauvegarde du tampon (buffer) --}
+\setinterfacemessage{systems}{16}{composition du tampon (buffer) --}
+\setinterfacemessage{systems}{17}{composition textuelle du tampon (buffer) --}
+\setinterfacemessage{systems}{13}{marquage -- defini --}
+\setinterfacemessage{systems}{12}{le fichier utilitaire n'est pas trié, utilise texutil}
+\setinterfacemessage{systems}{11}{construction util simple}
+\setinterfacemessage{systems}{10}{n'utilisez pas em dans --}
+\setinterfacemessage{floatblocks}{1}{-- renuméroté / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- déplacé}
+\setinterfacemessage{floatblocks}{2}{-- sauvegardé}
+\setinterfacemessage{floatblocks}{5}{ordre adapté}
+\setinterfacemessage{floatblocks}{4}{-- placé}
+\setinterfacemessage{floatblocks}{7}{n flottants de bas de page limité à --}
+\setinterfacemessage{floatblocks}{6}{n flottants de haut de page limité à --}
+\setinterfacemessage{floatblocks}{9}{ordre perturbé}
+\setinterfacemessage{floatblocks}{8}{moins de -- lignes}
+\setinterfacemessage{floatblocks}{title}{blocs de flottants}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{indéfini}
+\setinterfacemessage{floatblocks}{11}{pas de bloc donné}
+\setinterfacemessage{floatblocks}{10}{-- limité}
+\setinterfacemessage{interactions}{1}{ratio d'aspect -- x -- (b x h)}
+\setinterfacemessage{interactions}{3}{inactif}
+\setinterfacemessage{interactions}{2}{actif}
+\setinterfacemessage{interactions}{5}{le fichier joint -- est inconnu}
+\setinterfacemessage{interactions}{4}{pas de synchronisation de page (--) dans le hmode}
+\setinterfacemessage{interactions}{6}{le fichier joint -- n'existe pas}
+\setinterfacemessage{interactions}{title}{interaction}
+\setinterfacemessage{interactions}{21}{-- code inseré}
+\setinterfacemessage{regimes}{1}{encodage --}
+\setinterfacemessage{regimes}{3}{encodage -- inconnu}
+\setinterfacemessage{regimes}{2}{l'encodage -- est chargé}
+\setinterfacemessage{regimes}{title}{encodage}
+\setinterfacemessage{structures}{1}{début de blocsection --}
+\setinterfacemessage{structures}{title}{structure}
+\setinterfacemessage{structures}{2}{fin de blocsection --}
+\setinterfacemessage{linguals}{1}{les motifs -- pour -- sont chargés (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{hyphenations -- pour -- chargés (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{pas de motifs -- pour -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{les motifs pour -- ne sont pas chargés}
+\setinterfacemessage{linguals}{4}{pas d'hyphenations -- pour -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{les options spécifiques de langue [--] introduisent un -- saut}
+\setinterfacemessage{linguals}{6}{langue -- non définie}
+\setinterfacemessage{linguals}{9}{la langue -- est active}
+\setinterfacemessage{linguals}{8}{les options spécifiques de langue [--] sont ajoutés en douceur}
+\setinterfacemessage{linguals}{title}{langue}
+\setinterfacemessage{linguals}{10}{motifs -- chargés}
+\setinterfacemessage{verbatims}{1}{le fichier -- n'existe pas}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{le filtre -- est chargé}
+\setinterfacemessage{filters}{title}{filtre}
+\setinterfacemessage{filters}{2}{filtre -- inconnu}
+\setinterfacemessage{textblocks}{1}{nouvelle version, une seconde passe est nécessaire}
+\setinterfacemessage{textblocks}{3}{lecture des blocs en provenance de --}
+\setinterfacemessage{textblocks}{2}{ecriture des blocs vers --}
+\setinterfacemessage{textblocks}{5}{-- non caché}
+\setinterfacemessage{textblocks}{4}{seconde passe nécessaire}
+\setinterfacemessage{textblocks}{7}{-- caché}
+\setinterfacemessage{textblocks}{6}{-- caché et traité}
+\setinterfacemessage{textblocks}{9}{-- non composé}
+\setinterfacemessage{textblocks}{8}{-- composé}
+\setinterfacemessage{textblocks}{title}{blocs de texte}
+\setinterfacemessage{textblocks}{12}{-- sauté}
+\setinterfacemessage{textblocks}{11}{-- chargé et composé}
+\setinterfacemessage{textblocks}{10}{-- chargé et traité}
+\setinterfacemessage{encodings}{1}{encodage --}
+\setinterfacemessage{encodings}{3}{encodage -- inconnu}
+\setinterfacemessage{encodings}{2}{l'encodage -- est chargé}
+\setinterfacemessage{encodings}{title}{encodage}
+\setinterfacemessage{columns}{1}{seules -- colonnes possibles}
+\setinterfacemessage{columns}{3}{problèmes, désactive l'équilibrage}
+\setinterfacemessage{columns}{2}{utilisez \string\filbreak\space en tant qu'alternative}
+\setinterfacemessage{columns}{5}{flottant en partie inférieure pas encore supporté}
+\setinterfacemessage{columns}{4}{flottant en partie supérieure pas encore supporté}
+\setinterfacemessage{columns}{7}{équilibrage abandonné après 100 pas}
+\setinterfacemessage{columns}{6}{-- flottant(s) reporté(s)}
+\setinterfacemessage{columns}{9}{vérification des irrégularités}
+\setinterfacemessage{columns}{8}{équilibré en -- pas}
+\setinterfacemessage{columns}{title}{colonnes}
+\setinterfacemessage{columns}{13}{flottant large déplacé dans la partie supérieure de la colonne}
+\setinterfacemessage{columns}{12}{flottant déplacé à la colonne suivante / --}
+\setinterfacemessage{columns}{11}{flottant mis à la largeur de la colonne}
+\setinterfacemessage{columns}{10}{(moins de) 1 ligne restante}
+\setinterfacemessage{symbols}{1}{chargement du jeu de symbole --}
+\setinterfacemessage{symbols}{title}{symboles}
+\setinterfacemessage{files}{1}{le synonyme de fichier -- est déjà utilisé pour --}
+\setinterfacemessage{files}{title}{fichiers}
+\setinterfacemessage{versions}{1}{@+ manquant}
+\setinterfacemessage{versions}{3}{pages sélectionnées : --}
+\setinterfacemessage{versions}{2}{marquage des pages}
+\setinterfacemessage{versions}{title}{version}
+\setinterfacemessage{specials}{1}{-- chargé}
+\setinterfacemessage{specials}{3}{-- est remis à zéro}
+\setinterfacemessage{specials}{2}{pas d'imbracations plus profondes ne sont permises --}
+\setinterfacemessage{specials}{5}{chargement du fichier de définition --}
+\setinterfacemessage{specials}{4}{la commande -- n'existe pas}
+\setinterfacemessage{specials}{7}{pilote -- inconnu}
+\setinterfacemessage{specials}{6}{l'imbrication n'est pas permise}
+\setinterfacemessage{specials}{title}{specials}
+\setinterfacemessage{layouts}{1}{hauteurtexte adaptée avec -- à la page --}
+\setinterfacemessage{layouts}{3}{-- times text postponed}
+\setinterfacemessage{layouts}{2}{-- times postponed text placed}
+\setinterfacemessage{layouts}{5}{blocsmarge inactifs}
+\setinterfacemessage{layouts}{4}{blocsmarge actifs}
+\setinterfacemessage{layouts}{7}{calcul de l'espace pour le logo}
+\setinterfacemessage{layouts}{6}{jeu de souspage -- traité (taille --)}
+\setinterfacemessage{layouts}{9}{pas plus de -- niveaux pour l'instant dans les élémentarisations}
+\setinterfacemessage{layouts}{8}{calcul des arrières-plans}
+\setinterfacemessage{layouts}{title}{calque}
+\setinterfacemessage{layouts}{11}{espacement -- non permis en modegrille}
+\setinterfacemessage{layouts}{10}{-- et -- ne sont pas ajoutés à 1.0}
+\setinterfacemessage{fonts}{1}{encodage --}
+\setinterfacemessage{fonts}{3}{variante -- inconnue}
+\setinterfacemessage{fonts}{2}{la variante -- est chargée}
+\setinterfacemessage{fonts}{5}{le style -- n'est pas défini}
+\setinterfacemessage{fonts}{4}{policecorps -- n'est pas définie}
+\setinterfacemessage{fonts}{7}{format -- inconnu}
+\setinterfacemessage{fonts}{6}{-- est chargé}
+\setinterfacemessage{fonts}{14}{policecorps -- est défini (une définition globale pourrait être plus adéquat)}
+\setinterfacemessage{fonts}{8}{style -- défini}
+\setinterfacemessage{fonts}{title}{corps de texte}
+\setinterfacemessage{fonts}{10}{fichier de police -- inconnu}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{fichier global --}
+\setinterfacemessage{databases}{2}{fichier local --}
+\setinterfacemessage{databases}{4}{fichier inconnu --}
+\setinterfacemessage{databases}{title}{bases de données}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{chargement du jeu de script --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{préambule -- inconnu}
+\setinterfacemessage{check}{1}{manquant ou dégroupé '=' après '--' à la ligne --}
+\setinterfacemessage{check}{3}{-- -- remplace une macro, utilisez des MAJUSCULES !}
+\setinterfacemessage{check}{2}{-- argument(s) attendu(s) à la ligne --}
+\setinterfacemessage{check}{title}{vérification}
+\setinterfacemessage{metapost}{1}{chargement de la bibliothèque metapost --}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{la figure -- ne peut être trouvée}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{la figure -- n'est pas pré-sélectionnée}
+\setinterfacemessage{figures}{5}{dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{les dimensions de -- chargées implicitement à partir du fichier de figure}
+\setinterfacemessage{figures}{6}{les dimensions de -- calculées par rlxtools}
+\setinterfacemessage{figures}{8}{figureobject -- est réutilisé}
+\setinterfacemessage{figures}{title}{figures}
+\setinterfacemessage{colors}{1}{le système -- est globalement activé}
+\setinterfacemessage{colors}{3}{-- n'est pas défini --}
+\setinterfacemessage{colors}{2}{le système -- est localement activé}
+\setinterfacemessage{colors}{5}{système -- inconnu}
+\setinterfacemessage{colors}{4}{le système -- est chargé}
+\setinterfacemessage{colors}{7}{le palette -- n'est pas disponible}
+\setinterfacemessage{colors}{6}{la palette -- est disponible}
+\setinterfacemessage{colors}{9}{l'espace de couleur -- n'est pas supporté}
+\setinterfacemessage{colors}{8}{la spécification -- de la couleur -- devient noire}
+\setinterfacemessage{colors}{title}{couleurs}
+\setinterfacemessage{colors}{12}{-- est enregistré}
+\setinterfacemessage{colors}{11}{la couleur est convertie en niveau de gris}
+\setinterfacemessage{colors}{10}{-- l'espace de couleur est supporté}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mit.tex b/tex/context/base/mult-mit.tex
new file mode 100644
index 000000000..6d2a8f516
--- /dev/null
+++ b/tex/context/base/mult-mit.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{riferimento sconosciuto --}
+\setinterfacemessage{references}{3}{riferimento di tipo sconosciuto --}
+\setinterfacemessage{references}{2}{riferimento duplicato -- a pagina --}
+\setinterfacemessage{references}{4}{riferimento illecito --}
+\setinterfacemessage{references}{30}{oggetto sconosciuto --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{riferimenti}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{oggetto duplicato --}
+\setinterfacemessage{references}{21}{documento -- caricato}
+\setinterfacemessage{references}{22}{il documento -- non ø interattivo}
+\setinterfacemessage{references}{23}{riferimento ambiguo -- (prefisso=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{number --}
+\setinterfacemessage{handlings}{1}{font handling --}
+\setinterfacemessage{handlings}{3}{unknown font handling --}
+\setinterfacemessage{handlings}{2}{font handling -- is loaded}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{sistema}
+\setinterfacemessage{systems}{41}{il file esterno -- del gruppo -- non esiste}
+\setinterfacemessage{systems}{9}{-- non trovato/elaborato}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{nuova versione del file supplementare, seconda passata necessaria}
+\setinterfacemessage{systems}{21}{nessuna informazione supplementare caricata}
+\setinterfacemessage{systems}{20}{significato (specie) di -- caricato}
+\setinterfacemessage{systems}{5}{macro del modulo -- caricate}
+\setinterfacemessage{systems}{4}{comando -- già definito}
+\setinterfacemessage{systems}{27}{Versione}
+\setinterfacemessage{systems}{26}{Registri}
+\setinterfacemessage{systems}{25}{Riferimenti}
+\setinterfacemessage{systems}{24}{Oggetti mobili}
+\setinterfacemessage{systems}{1}{caricamento dei file supplementari posticipato (typemode)}
+\setinterfacemessage{systems}{23}{-- sistemato a --}
+\setinterfacemessage{systems}{22}{usare un file supplementare valido}
+\setinterfacemessage{systems}{2}{-- caricato}
+\setinterfacemessage{systems}{19}{significato (sinonimi) di -- caricato}
+\setinterfacemessage{systems}{18}{sinonimo -- -- non esistente}
+\setinterfacemessage{systems}{7}{macro del modulo -- già caricate}
+\setinterfacemessage{systems}{6}{nessuna macro trovata nel modulo --}
+\setinterfacemessage{systems}{14}{nuova pagina obbligata in lista a --}
+\setinterfacemessage{systems}{15}{salvataggio del buffer --}
+\setinterfacemessage{systems}{16}{composizione del buffer --}
+\setinterfacemessage{systems}{17}{composizione verbatim del buffer --}
+\setinterfacemessage{systems}{13}{marcatura -- definita --}
+\setinterfacemessage{systems}{12}{file di supplemento non ordinato, usare texutil}
+\setinterfacemessage{systems}{11}{costruzione di un semplice supplemento}
+\setinterfacemessage{systems}{10}{non usare em in --}
+\setinterfacemessage{floatblocks}{1}{-- rinumerato / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- mosso}
+\setinterfacemessage{floatblocks}{2}{-- salvato}
+\setinterfacemessage{floatblocks}{5}{ordine aggiustato}
+\setinterfacemessage{floatblocks}{4}{-- sistemato}
+\setinterfacemessage{floatblocks}{7}{n di bottom floats limitato a --}
+\setinterfacemessage{floatblocks}{6}{n di top floats limitato a --}
+\setinterfacemessage{floatblocks}{9}{ordine disturbato}
+\setinterfacemessage{floatblocks}{8}{meno di -- righe}
+\setinterfacemessage{floatblocks}{title}{oggetti mobili}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{non definito}
+\setinterfacemessage{floatblocks}{11}{nessun oggetto specificato}
+\setinterfacemessage{floatblocks}{10}{-- limitato}
+\setinterfacemessage{interactions}{1}{rapporto -- x -- (b x a)}
+\setinterfacemessage{interactions}{3}{inattiva}
+\setinterfacemessage{interactions}{2}{attiva}
+\setinterfacemessage{interactions}{5}{unknown attachment --}
+\setinterfacemessage{interactions}{4}{sincronizzazione di pagina (--) non disponibile in hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- does not exist}
+\setinterfacemessage{interactions}{title}{interazione}
+\setinterfacemessage{interactions}{21}{codice -- inserito}
+\setinterfacemessage{regimes}{1}{codifica --}
+\setinterfacemessage{regimes}{3}{codifica sconosciuta --}
+\setinterfacemessage{regimes}{2}{codifica -- caricata}
+\setinterfacemessage{regimes}{title}{codifica}
+\setinterfacemessage{structures}{1}{inizio del blocco (sezione) --}
+\setinterfacemessage{structures}{title}{struttura}
+\setinterfacemessage{structures}{2}{fine del blocco (sezione) --}
+\setinterfacemessage{linguals}{1}{schemi -- per -- caricati (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{sillabazione -- per -- caricata (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{niente schemi -- per -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{schemi per -- non caricati}
+\setinterfacemessage{linguals}{4}{niente sillabazione -- per -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{opzioni specifiche per la lingua [--] introducono un salto --}
+\setinterfacemessage{linguals}{6}{lingua -- non definita}
+\setinterfacemessage{linguals}{9}{lingua -- attiva}
+\setinterfacemessage{linguals}{8}{opzioni specifiche per la lingua [--] aggiunte trasparentemente}
+\setinterfacemessage{linguals}{title}{lingua}
+\setinterfacemessage{linguals}{10}{schemi -- caricati}
+\setinterfacemessage{verbatims}{1}{il file -- non esiste}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{filtro -- caricato}
+\setinterfacemessage{filters}{title}{filtri}
+\setinterfacemessage{filters}{2}{filtro sconosciuto --}
+\setinterfacemessage{textblocks}{1}{nuova versione, seconda passata necessaria}
+\setinterfacemessage{textblocks}{3}{lettura dei blocchi da --}
+\setinterfacemessage{textblocks}{2}{scrittura dei blocchi su --}
+\setinterfacemessage{textblocks}{5}{-- non nascosto}
+\setinterfacemessage{textblocks}{4}{seconda passata necessaria}
+\setinterfacemessage{textblocks}{7}{-- nascosto}
+\setinterfacemessage{textblocks}{6}{-- nascosto ed elaborato}
+\setinterfacemessage{textblocks}{9}{-- non composto}
+\setinterfacemessage{textblocks}{8}{-- composto}
+\setinterfacemessage{textblocks}{title}{blocchi di testo}
+\setinterfacemessage{textblocks}{12}{-- saltato}
+\setinterfacemessage{textblocks}{11}{-- caricato e composto}
+\setinterfacemessage{textblocks}{10}{-- caricato ed elaborato}
+\setinterfacemessage{encodings}{1}{codifica --}
+\setinterfacemessage{encodings}{3}{codifica sconosciuta --}
+\setinterfacemessage{encodings}{2}{codifica -- caricata}
+\setinterfacemessage{encodings}{title}{codifica}
+\setinterfacemessage{columns}{1}{solo -- colonne possibili}
+\setinterfacemessage{columns}{3}{problemi, disabilitare il bilanciamento}
+\setinterfacemessage{columns}{2}{in alternativa, usare \string\filbreak}
+\setinterfacemessage{columns}{5}{float in fondo non ancora supportato}
+\setinterfacemessage{columns}{4}{float in cima non ancora supportato}
+\setinterfacemessage{columns}{7}{bilanciamento annullato dopo 100 passi}
+\setinterfacemessage{columns}{6}{-- float(s) posticipate}
+\setinterfacemessage{columns}{9}{controllare seghettamento}
+\setinterfacemessage{columns}{8}{bilanciamento in -- passo/i}
+\setinterfacemessage{columns}{title}{colonne}
+\setinterfacemessage{columns}{13}{oggetto mobile ampio spostato sopra le colonne}
+\setinterfacemessage{columns}{12}{oggetto mobile spostata alla colonna successiva / --}
+\setinterfacemessage{columns}{11}{oggetto mobile troppo ampio per la colonna}
+\setinterfacemessage{columns}{10}{(meno di) una riga rimasta}
+\setinterfacemessage{symbols}{1}{caricamento gruppo di simboli --}
+\setinterfacemessage{symbols}{title}{simboli}
+\setinterfacemessage{files}{1}{sinonimo file -- già in uso per --}
+\setinterfacemessage{files}{title}{file}
+\setinterfacemessage{versions}{1}{@+ mancante}
+\setinterfacemessage{versions}{3}{pagine selezionate: --}
+\setinterfacemessage{versions}{2}{marcatura pagine}
+\setinterfacemessage{versions}{title}{version}
+\setinterfacemessage{specials}{1}{-- caricato}
+\setinterfacemessage{specials}{3}{-- reimpostato}
+\setinterfacemessage{specials}{2}{non ø permesso un annidamento maggiore --}
+\setinterfacemessage{specials}{5}{caricamento del file di definizione --}
+\setinterfacemessage{specials}{4}{il comando -- non esiste}
+\setinterfacemessage{specials}{7}{driver sconosciuto --}
+\setinterfacemessage{specials}{6}{annidamento non permesso}
+\setinterfacemessage{specials}{title}{specialitø}
+\setinterfacemessage{layouts}{1}{altezza del testo adattata con -- a pagina --}
+\setinterfacemessage{layouts}{3}{testo posticipato -- volte}
+\setinterfacemessage{layouts}{2}{posizionato testo posticipato -- volte}
+\setinterfacemessage{layouts}{5}{blocchi in margine inattivi}
+\setinterfacemessage{layouts}{4}{blocchi in margine attivi}
+\setinterfacemessage{layouts}{7}{calcolo dello spazio per logo}
+\setinterfacemessage{layouts}{6}{gruppo di sottopagine -- elaborato (dimensione --)}
+\setinterfacemessage{layouts}{9}{attualmente non più di -- livelli di elencazione}
+\setinterfacemessage{layouts}{8}{calcolo dello sfondo}
+\setinterfacemessage{layouts}{title}{layout}
+\setinterfacemessage{layouts}{11}{spaziatura -- non permessa in modo griglia}
+\setinterfacemessage{layouts}{10}{-- e -- non sommano a 1.0}
+\setinterfacemessage{fonts}{1}{codifica --}
+\setinterfacemessage{fonts}{3}{variante sconosciuta --}
+\setinterfacemessage{fonts}{2}{variante -- caricata}
+\setinterfacemessage{fonts}{5}{stile -- non definito}
+\setinterfacemessage{fonts}{4}{corpo del testo -- non definito}
+\setinterfacemessage{fonts}{7}{formato sconosciuto --}
+\setinterfacemessage{fonts}{6}{-- caricato}
+\setinterfacemessage{fonts}{14}{corpo del testo -- definito (sarebbe meglio globale)}
+\setinterfacemessage{fonts}{8}{stile -- definito}
+\setinterfacemessage{fonts}{title}{font del corpo}
+\setinterfacemessage{fonts}{10}{file di font sconosciuto --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{file globale --}
+\setinterfacemessage{databases}{2}{file locale --}
+\setinterfacemessage{databases}{4}{file sconosciuto --}
+\setinterfacemessage{databases}{title}{database}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{caricamento dello script set --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{preambolo sconosciuto --}
+\setinterfacemessage{check}{1}{'=' mancante o non raggruppato dopo '--' alla riga --}
+\setinterfacemessage{check}{3}{-- -- sostituisce una macro, usare le MAIUSCOLE!}
+\setinterfacemessage{check}{2}{-- argomento/i attesi alla riga --}
+\setinterfacemessage{check}{title}{controllo}
+\setinterfacemessage{metapost}{1}{caricamento della libreria metapost --}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{figura -- non trovata}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{la figura -- non è preimpostata}
+\setinterfacemessage{figures}{5}{dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{dimensioni di -- caricate dal file di immagini stesso}
+\setinterfacemessage{figures}{6}{dimensioni di -- calcolate da rlxtools}
+\setinterfacemessage{figures}{8}{oggetto-figura -- riutilizzato}
+\setinterfacemessage{figures}{title}{figure}
+\setinterfacemessage{colors}{1}{sistema -- attivato globalmente}
+\setinterfacemessage{colors}{3}{-- non definito --}
+\setinterfacemessage{colors}{2}{sistema -- attivato localmente}
+\setinterfacemessage{colors}{5}{sistema -- sconosciuto}
+\setinterfacemessage{colors}{4}{sistema -- caricato}
+\setinterfacemessage{colors}{7}{tavolozza -- non disponibile}
+\setinterfacemessage{colors}{6}{tavolozza -- resa disponibile}
+\setinterfacemessage{colors}{9}{spazio dei colori -- non supportato}
+\setinterfacemessage{colors}{8}{specifica -- del colore -- convertita in nero}
+\setinterfacemessage{colors}{title}{colore}
+\setinterfacemessage{colors}{12}{-- is registered}
+\setinterfacemessage{colors}{11}{il colore ø convertito in grigio}
+\setinterfacemessage{colors}{10}{spazio dei colori -- supportato}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mnl.tex b/tex/context/base/mult-mnl.tex
new file mode 100644
index 000000000..b8204a40b
--- /dev/null
+++ b/tex/context/base/mult-mnl.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{onbekende verwijzing --}
+\setinterfacemessage{references}{3}{type verwijzing -- onbekend}
+\setinterfacemessage{references}{2}{dubbele verwijzing -- op pagina --}
+\setinterfacemessage{references}{4}{verboden verwijzing --}
+\setinterfacemessage{references}{30}{onbekend object --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{verwijzingen}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{dubbel object --}
+\setinterfacemessage{references}{21}{document -- geladen}
+\setinterfacemessage{references}{22}{document -- is niet interactief}
+\setinterfacemessage{references}{23}{onduidelijke verwijzing -- (prefix=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{nummer --}
+\setinterfacemessage{handlings}{1}{font afhandeling --}
+\setinterfacemessage{handlings}{3}{onbekende font afhandeling --}
+\setinterfacemessage{handlings}{2}{font afhandeling -- wordt geladen}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{systeem}
+\setinterfacemessage{systems}{41}{externe file -- in groep -- bestaat niet}
+\setinterfacemessage{systems}{9}{-- niet gevonden/geplaatst}
+\setinterfacemessage{systems}{91}{papierlade --}
+\setinterfacemessage{systems}{8}{nieuwe versie hulpfile, tweede run nodig}
+\setinterfacemessage{systems}{21}{de hulpfile is niet geladen}
+\setinterfacemessage{systems}{20}{betekenissen (sorteren) van -- geladen}
+\setinterfacemessage{systems}{5}{module -- geladen}
+\setinterfacemessage{systems}{4}{commando -- is al gedefinieerd}
+\setinterfacemessage{systems}{27}{Versie}
+\setinterfacemessage{systems}{26}{Registers}
+\setinterfacemessage{systems}{25}{Verwijzingen}
+\setinterfacemessage{systems}{24}{Plaatsblokken}
+\setinterfacemessage{systems}{1}{laden hulpfile uitgesteld (typemode)}
+\setinterfacemessage{systems}{23}{-- gearrangeerd op --}
+\setinterfacemessage{systems}{22}{gebruik een goede hulpfile}
+\setinterfacemessage{systems}{2}{-- geladen}
+\setinterfacemessage{systems}{19}{betekenissen (synoniemen) van -- geladen}
+\setinterfacemessage{systems}{18}{synoniem -- -- bestaat niet}
+\setinterfacemessage{systems}{7}{module -- reeds geladen}
+\setinterfacemessage{systems}{6}{geen module -- gevonden}
+\setinterfacemessage{systems}{14}{geforceerde paginaovergang in lijst voor --}
+\setinterfacemessage{systems}{15}{wegschrijven buffer --}
+\setinterfacemessage{systems}{16}{inlezen buffer --}
+\setinterfacemessage{systems}{17}{verbatim inlezen buffer --}
+\setinterfacemessage{systems}{13}{markering -- gedefinieerd --}
+\setinterfacemessage{systems}{12}{de hulpfile is niet gesorteerd, gebruik texutil}
+\setinterfacemessage{systems}{11}{aanmaken basale hulpfile}
+\setinterfacemessage{systems}{10}{gebruik geen em in --}
+\setinterfacemessage{floatblocks}{1}{-- hernummerd / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- verplaatst}
+\setinterfacemessage{floatblocks}{2}{-- bewaard}
+\setinterfacemessage{floatblocks}{5}{volgorde aangepast}
+\setinterfacemessage{floatblocks}{4}{-- geplaatst}
+\setinterfacemessage{floatblocks}{7}{maximaal -- onder}
+\setinterfacemessage{floatblocks}{6}{maximaal -- boven}
+\setinterfacemessage{floatblocks}{9}{volgorde verstoord}
+\setinterfacemessage{floatblocks}{8}{minder dan -- regels}
+\setinterfacemessage{floatblocks}{title}{plaatsblokken}
+\setinterfacemessage{floatblocks}{13}{er is niets te splitsen}
+\setinterfacemessage{floatblocks}{12}{niet gedefinieerd}
+\setinterfacemessage{floatblocks}{11}{geen blok opgegeven}
+\setinterfacemessage{floatblocks}{10}{-- begrensd}
+\setinterfacemessage{interactions}{1}{aspect ratio -- x -- (b x h)}
+\setinterfacemessage{interactions}{3}{niet actief}
+\setinterfacemessage{interactions}{2}{actief}
+\setinterfacemessage{interactions}{5}{onbekend attachment --}
+\setinterfacemessage{interactions}{4}{geen paginasynchronisatie (--) in hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- bestaat niet}
+\setinterfacemessage{interactions}{title}{interactie}
+\setinterfacemessage{interactions}{21}{-- code tussengevoegd}
+\setinterfacemessage{regimes}{1}{regime --}
+\setinterfacemessage{regimes}{3}{onbekend regime --}
+\setinterfacemessage{regimes}{2}{regime -- wordt geladen}
+\setinterfacemessage{regimes}{title}{regime}
+\setinterfacemessage{structures}{1}{begin van sectieblok --}
+\setinterfacemessage{structures}{title}{structuur}
+\setinterfacemessage{structures}{2}{eind van sectieblok --}
+\setinterfacemessage{linguals}{1}{afbreekpatronen -- voor -- geladen (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{afbreekdefinities -- voor -- geladen (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{geen afbreekpatronen -- voor -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{afbreekpatronen voor -- niet geladen}
+\setinterfacemessage{linguals}{4}{geen afbreekdefinities -- voor -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{taal specifieke opties [--] introduceren een skip van --}
+\setinterfacemessage{linguals}{6}{taal -- is niet gedefinieerd}
+\setinterfacemessage{linguals}{9}{taal -- is actief}
+\setinterfacemessage{linguals}{8}{taal specifieke opties [--] naadloos toegevoegd}
+\setinterfacemessage{linguals}{title}{taal}
+\setinterfacemessage{linguals}{10}{patronen --geladen}
+\setinterfacemessage{verbatims}{1}{file -- bestaat niet}
+\setinterfacemessage{verbatims}{title}{typen}
+\setinterfacemessage{filters}{1}{filter -- wordt geladen}
+\setinterfacemessage{filters}{title}{filter}
+\setinterfacemessage{filters}{2}{onbekend filter --}
+\setinterfacemessage{textblocks}{1}{nieuwe versie, tweede run nodig}
+\setinterfacemessage{textblocks}{3}{inlezen blokken uit --}
+\setinterfacemessage{textblocks}{2}{wegschrijven blokken naar --}
+\setinterfacemessage{textblocks}{5}{-- niet verborgen}
+\setinterfacemessage{textblocks}{4}{er is een tweede run nodig}
+\setinterfacemessage{textblocks}{7}{-- verborgen}
+\setinterfacemessage{textblocks}{6}{-- verborgen en verwerkt}
+\setinterfacemessage{textblocks}{9}{-- niet gehandhaafd}
+\setinterfacemessage{textblocks}{8}{-- gehandhaafd}
+\setinterfacemessage{textblocks}{title}{tekstblokken}
+\setinterfacemessage{textblocks}{12}{-- overgeslagen}
+\setinterfacemessage{textblocks}{11}{-- geladen en geplaatst}
+\setinterfacemessage{textblocks}{10}{-- geladen en verwerkt}
+\setinterfacemessage{encodings}{1}{codering --}
+\setinterfacemessage{encodings}{3}{onbekende codering --}
+\setinterfacemessage{encodings}{2}{codering -- wordt geladen}
+\setinterfacemessage{encodings}{title}{encoding}
+\setinterfacemessage{columns}{1}{maximaal -- kolommen}
+\setinterfacemessage{columns}{3}{probleempje, probeer [balanceren=nee]}
+\setinterfacemessage{columns}{2}{gebruik eventueel \string\filbreak}
+\setinterfacemessage{columns}{5}{plaatsblok onder nog niet mogelijk}
+\setinterfacemessage{columns}{4}{plaatsblok boven nog niet mogelijk}
+\setinterfacemessage{columns}{7}{balanceren afgebroken na 100 stappen}
+\setinterfacemessage{columns}{6}{-- plaatsblok(en) opgeschort}
+\setinterfacemessage{columns}{9}{uitlijnen controleren!}
+\setinterfacemessage{columns}{8}{gebalanceerd in -- stap(pen)}
+\setinterfacemessage{columns}{title}{kolommen}
+\setinterfacemessage{columns}{13}{breed figuur geplaatst boven kolommen}
+\setinterfacemessage{columns}{12}{plaatsblok verplaatst naar volgende kolom / --}
+\setinterfacemessage{columns}{11}{plaatsblok te breed voor kolom}
+\setinterfacemessage{columns}{10}{(minder dan) 1 regel over}
+\setinterfacemessage{symbols}{1}{symboolset -- wordt geladen}
+\setinterfacemessage{symbols}{title}{symbolen}
+\setinterfacemessage{files}{1}{file synoniem -- is al in gebruik voor --}
+\setinterfacemessage{files}{title}{files}
+\setinterfacemessage{versions}{1}{er mankeert een @+}
+\setinterfacemessage{versions}{3}{geselecteerde pagina's: --}
+\setinterfacemessage{versions}{2}{markeren pagina's}
+\setinterfacemessage{versions}{title}{versie}
+\setinterfacemessage{specials}{1}{-- geladen}
+\setinterfacemessage{specials}{3}{-- gereset}
+\setinterfacemessage{specials}{2}{verdere nesting is niet toegestaan --}
+\setinterfacemessage{specials}{5}{definitiefile -- wordt geladen}
+\setinterfacemessage{specials}{4}{commando -- bestaat niet}
+\setinterfacemessage{specials}{7}{onbekende driver --}
+\setinterfacemessage{specials}{6}{nesting is niet toegestaan}
+\setinterfacemessage{specials}{title}{specials}
+\setinterfacemessage{layouts}{1}{teksthoogte aangepast met -- op pagina --}
+\setinterfacemessage{layouts}{3}{-- maal tekst plaatsen uitstellen}
+\setinterfacemessage{layouts}{2}{-- maal uitgestelde tekst tussengevoegd}
+\setinterfacemessage{layouts}{5}{margeblokken inactief}
+\setinterfacemessage{layouts}{4}{margeblokken actief}
+\setinterfacemessage{layouts}{7}{beeldmerken berekenen}
+\setinterfacemessage{layouts}{6}{subpagina reeks -- verwerkt (aantal --)}
+\setinterfacemessage{layouts}{9}{momenteel maximaal -- niveaus in opsommingen}
+\setinterfacemessage{layouts}{8}{achtergronden berekenen}
+\setinterfacemessage{layouts}{title}{layout}
+\setinterfacemessage{layouts}{11}{interlinie -- niet toegestaan in gridmode}
+\setinterfacemessage{layouts}{10}{-- en -- tellen niet op tot 1.0}
+\setinterfacemessage{fonts}{1}{codering --}
+\setinterfacemessage{fonts}{3}{onbekende variant --}
+\setinterfacemessage{fonts}{2}{variant -- wordt geladen}
+\setinterfacemessage{fonts}{5}{stijl -- is niet gedefinieerd}
+\setinterfacemessage{fonts}{4}{korps -- is niet gedefinieerd}
+\setinterfacemessage{fonts}{7}{onbekend formaat --}
+\setinterfacemessage{fonts}{6}{-- wordt geladen}
+\setinterfacemessage{fonts}{14}{korps -- is gedefinieerd (kan beter globaal plaatsvinden)}
+\setinterfacemessage{fonts}{8}{stijl -- gedefinieerd}
+\setinterfacemessage{fonts}{title}{korps}
+\setinterfacemessage{fonts}{10}{onbekende font file --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{globaal bestand --}
+\setinterfacemessage{databases}{2}{lokaal bestand --}
+\setinterfacemessage{databases}{4}{onbekend bestand --}
+\setinterfacemessage{databases}{title}{database}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{script set -- wordt geladen}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{onbekende preamble --}
+\setinterfacemessage{check}{1}{'=' ontbreekt of zonder {} na '--' in regel --}
+\setinterfacemessage{check}{3}{-- -- vervangt een macro, gebruik HOOFDLETTERS!}
+\setinterfacemessage{check}{2}{-- argument(en) verwacht in regel --}
+\setinterfacemessage{check}{title}{controle}
+\setinterfacemessage{metapost}{1}{metapost bibliotheek -- wordt geladen}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{figuur -- is niet te vinden}
+\setinterfacemessage{figures}{3}{maten van -- worden extern vastgesteld}
+\setinterfacemessage{figures}{2}{figuur -- wordt niet preset}
+\setinterfacemessage{figures}{5}{maten van -- zijn onbekend}
+\setinterfacemessage{figures}{4}{maten van -- geladen uit figuurfile zelf}
+\setinterfacemessage{figures}{6}{maten van -- berekend door rlxtools}
+\setinterfacemessage{figures}{8}{figuurobject -- wordt opnieuw gebruikt}
+\setinterfacemessage{figures}{title}{figuren}
+\setinterfacemessage{colors}{1}{systeem -- is globaal actief}
+\setinterfacemessage{colors}{3}{-- is niet gedefinieerd --}
+\setinterfacemessage{colors}{2}{systeem -- is lokaal actief}
+\setinterfacemessage{colors}{5}{onbekend systeem --}
+\setinterfacemessage{colors}{4}{systeem -- wordt geladen}
+\setinterfacemessage{colors}{7}{palet -- is niet beschikbaar}
+\setinterfacemessage{colors}{6}{palet -- is beschikbaar}
+\setinterfacemessage{colors}{9}{-- kleurruimte wordt niet ondersteund}
+\setinterfacemessage{colors}{8}{specificatie -- bij -- wordt zwart}
+\setinterfacemessage{colors}{title}{kleur}
+\setinterfacemessage{colors}{12}{-- is geregistreerd}
+\setinterfacemessage{colors}{11}{kleur wordt vertaald in grijs}
+\setinterfacemessage{colors}{10}{-- kleurruimte wordt ondersteund}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mno.tex b/tex/context/base/mult-mno.tex
new file mode 100644
index 000000000..ee6fd3273
--- /dev/null
+++ b/tex/context/base/mult-mno.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{ukjent referanse --}
+\setinterfacemessage{references}{3}{ukjent referansetype --}
+\setinterfacemessage{references}{2}{duplikat referanse -- pø side --}
+\setinterfacemessage{references}{4}{ulovlig referanse --}
+\setinterfacemessage{references}{30}{ukjent objekt --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{referanser}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{duplikat objekt --}
+\setinterfacemessage{references}{21}{dokument -- er lest inn}
+\setinterfacemessage{references}{22}{dokument -- er ikke interaktivt}
+\setinterfacemessage{references}{23}{obskur referanse -- (Prefix=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{number --}
+\setinterfacemessage{handlings}{1}{font handling --}
+\setinterfacemessage{handlings}{3}{unknown font handling --}
+\setinterfacemessage{handlings}{2}{font handling -- is loaded}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{system}
+\setinterfacemessage{systems}{41}{ekstern fil -- i gruppe -- eksisterer ikke}
+\setinterfacemessage{systems}{9}{-- ikke funnet/behandlet}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{ny versjon av hjelpefil, andre gjennomkjøring nødvendig}
+\setinterfacemessage{systems}{21}{hjelpefila er ikke lest inn}
+\setinterfacemessage{systems}{20}{betydning (sorterer) av -- er lest inn}
+\setinterfacemessage{systems}{5}{makroene i modul -- er lest inn}
+\setinterfacemessage{systems}{4}{kommando -- er allerede definert}
+\setinterfacemessage{systems}{27}{Versjon}
+\setinterfacemessage{systems}{26}{Registere}
+\setinterfacemessage{systems}{25}{Referanser}
+\setinterfacemessage{systems}{24}{Flytblokker}
+\setinterfacemessage{systems}{1}{innlesning av hjelpefila utsatt (typemode)}
+\setinterfacemessage{systems}{23}{-- arrangert på --}
+\setinterfacemessage{systems}{22}{bruk en gyldig hjelpefil}
+\setinterfacemessage{systems}{2}{-- er lest inn}
+\setinterfacemessage{systems}{19}{betydning (synonymer) av -- er lest inn}
+\setinterfacemessage{systems}{18}{synonym -- -- eksisterer ikke}
+\setinterfacemessage{systems}{7}{makroene i modul -- er allerede lest inn}
+\setinterfacemessage{systems}{6}{ingen makroer funnet i modul ---}
+\setinterfacemessage{systems}{14}{tvunget sideskift i liste ved --}
+\setinterfacemessage{systems}{15}{lagrer Buffer --}
+\setinterfacemessage{systems}{16}{tegnsetter buffer --}
+\setinterfacemessage{systems}{17}{tegnsetter verbatim-buffer --}
+\setinterfacemessage{systems}{13}{markering -- definert --}
+\setinterfacemessage{systems}{12}{hjelpefila er ikke sortert, bruk texutil}
+\setinterfacemessage{systems}{11}{lager enkel hjelpefil}
+\setinterfacemessage{systems}{10}{ikke bruk em i --}
+\setinterfacemessage{floatblocks}{1}{-- renummerert / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- flyttet}
+\setinterfacemessage{floatblocks}{2}{-- lagret}
+\setinterfacemessage{floatblocks}{5}{rekkefølge tilpasset}
+\setinterfacemessage{floatblocks}{4}{-- plassert}
+\setinterfacemessage{floatblocks}{7}{maksimalt -- flytblokker nederst}
+\setinterfacemessage{floatblocks}{6}{maksimalt -- flytblokker øverst}
+\setinterfacemessage{floatblocks}{9}{rekkefølge endret}
+\setinterfacemessage{floatblocks}{8}{mindre enn -- linjer}
+\setinterfacemessage{floatblocks}{title}{flytblokker}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{udefinert}
+\setinterfacemessage{floatblocks}{11}{ingen blokk oppgitt}
+\setinterfacemessage{floatblocks}{10}{-- begrenset}
+\setinterfacemessage{interactions}{1}{forholdstall -- x -- (b x h)}
+\setinterfacemessage{interactions}{3}{inaktiv}
+\setinterfacemessage{interactions}{2}{aktiv}
+\setinterfacemessage{interactions}{5}{unknown attachment --}
+\setinterfacemessage{interactions}{4}{ingen sidesynkronisering (--) i hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- does not exist}
+\setinterfacemessage{interactions}{title}{interaksjon}
+\setinterfacemessage{interactions}{21}{-- kode satt inn / tilføyd}
+\setinterfacemessage{regimes}{1}{koding --}
+\setinterfacemessage{regimes}{3}{ukjent koding --}
+\setinterfacemessage{regimes}{2}{koding -- er lest inn}
+\setinterfacemessage{regimes}{title}{koding}
+\setinterfacemessage{structures}{1}{starten av blokk -- (seksjon)}
+\setinterfacemessage{structures}{title}{struktur}
+\setinterfacemessage{structures}{2}{slutten av blokk -- (seksjon)}
+\setinterfacemessage{linguals}{1}{orddelingsmønster -- for -- er lest inn (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{orddelingsdefinisjon -- for -- er lest inn (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{ingen orddelingsmønster -- for -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{orddelingsmønster for -- er ikke lest inn}
+\setinterfacemessage{linguals}{4}{ingen orddelingsdefinisjon -- for -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{spràk spesifikk opsjon [--] introduserer et -- hopp}
+\setinterfacemessage{linguals}{6}{spràk -- er udefinert}
+\setinterfacemessage{linguals}{9}{spràk -- er aktivt}
+\setinterfacemessage{linguals}{8}{spràk spesifikk opsjon [--] problemfritt tilføyd}
+\setinterfacemessage{linguals}{title}{sprøk}
+\setinterfacemessage{linguals}{10}{orddelingsmønster -- er lest inn}
+\setinterfacemessage{verbatims}{1}{fil -- eksisterer ikke}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{filter -- is loaded}
+\setinterfacemessage{filters}{title}{filter}
+\setinterfacemessage{filters}{2}{unknown filter --}
+\setinterfacemessage{textblocks}{1}{ny versjon, andre gjennomkjøring nødvendig}
+\setinterfacemessage{textblocks}{3}{leser blokker fra --}
+\setinterfacemessage{textblocks}{2}{skriver blokker til --}
+\setinterfacemessage{textblocks}{5}{-- ikke skjult}
+\setinterfacemessage{textblocks}{4}{andre gjennomkjøring nødvendig}
+\setinterfacemessage{textblocks}{7}{-- skjult}
+\setinterfacemessage{textblocks}{6}{-- skjult og behandlet}
+\setinterfacemessage{textblocks}{9}{-- ikke tegnsatt}
+\setinterfacemessage{textblocks}{8}{-- tegnsatt}
+\setinterfacemessage{textblocks}{title}{tekstblokker}
+\setinterfacemessage{textblocks}{12}{-- utelatt}
+\setinterfacemessage{textblocks}{11}{-- lest inn og tegnsatt}
+\setinterfacemessage{textblocks}{10}{-- lest inn og behandlet}
+\setinterfacemessage{encodings}{1}{koding --}
+\setinterfacemessage{encodings}{3}{ukjent koding --}
+\setinterfacemessage{encodings}{2}{koding -- er lest inn}
+\setinterfacemessage{encodings}{title}{koding}
+\setinterfacemessage{columns}{1}{maksimalt -- kolonner}
+\setinterfacemessage{columns}{3}{problemer, slår av balansering}
+\setinterfacemessage{columns}{2}{bruk \string\filbreak\space som et alternativ}
+\setinterfacemessage{columns}{5}{flytblokker nedert er ikke støttet enda}
+\setinterfacemessage{columns}{4}{flytblokker øverst er ikke støttet enda}
+\setinterfacemessage{columns}{7}{balansering avbrutt etter 100 iterasjoner}
+\setinterfacemessage{columns}{6}{-- flytblokk forskjøvet}
+\setinterfacemessage{columns}{9}{kontroller tekstlayout!}
+\setinterfacemessage{columns}{8}{balansert etter -- iterasjoner}
+\setinterfacemessage{columns}{title}{kolonner}
+\setinterfacemessage{columns}{13}{bred flytblokk forksjøvet til toppen av kolonnene}
+\setinterfacemessage{columns}{12}{flytblokk forskjøvet til neste kolonne / --}
+\setinterfacemessage{columns}{11}{flytblokk for bredt for kolonna}
+\setinterfacemessage{columns}{10}{(mindre enn) 1 linje igjen}
+\setinterfacemessage{symbols}{1}{leser inn symbolsett --}
+\setinterfacemessage{symbols}{title}{symboler}
+\setinterfacemessage{files}{1}{filesynonym -- er allerede brukt for --}
+\setinterfacemessage{files}{title}{filer}
+\setinterfacemessage{versions}{1}{manglende @+}
+\setinterfacemessage{versions}{3}{valgte sider: --}
+\setinterfacemessage{versions}{2}{markerer sider}
+\setinterfacemessage{versions}{title}{versjon}
+\setinterfacemessage{specials}{1}{-- er lest inn}
+\setinterfacemessage{specials}{3}{-- er tilbakestilt}
+\setinterfacemessage{specials}{2}{dypere 'nesting' er ikke tillatt --}
+\setinterfacemessage{specials}{5}{leser inn definisjonsfil for --}
+\setinterfacemessage{specials}{4}{kommando -- eksisterer ikke}
+\setinterfacemessage{specials}{7}{ukjent driver --}
+\setinterfacemessage{specials}{6}{'nesting' er ikke tillatt}
+\setinterfacemessage{specials}{title}{specials}
+\setinterfacemessage{layouts}{1}{teksthøyde tilpasset med -- på side --}
+\setinterfacemessage{layouts}{3}{-- ganger tekst forskjøvet}
+\setinterfacemessage{layouts}{2}{-- ganger forskjøvet tekst plassert}
+\setinterfacemessage{layouts}{5}{margblokker inaktive}
+\setinterfacemessage{layouts}{4}{margblokker aktive}
+\setinterfacemessage{layouts}{7}{beregner plass for logo}
+\setinterfacemessage{layouts}{6}{delside sett -- behandlet (størrelse --)}
+\setinterfacemessage{layouts}{9}{for øyeblikket maksimalt -- nivåer i opplisting}
+\setinterfacemessage{layouts}{8}{beregner bakgrunn}
+\setinterfacemessage{layouts}{title}{layout}
+\setinterfacemessage{layouts}{11}{mellomrom -- ikke tillatt i gridmodus}
+\setinterfacemessage{layouts}{10}{-- og -- er ikke 1.0 til sammen}
+\setinterfacemessage{fonts}{1}{koding --}
+\setinterfacemessage{fonts}{3}{ukjent variant --}
+\setinterfacemessage{fonts}{2}{variant -- er lest inn}
+\setinterfacemessage{fonts}{5}{stil -- er ikke definert}
+\setinterfacemessage{fonts}{4}{hovedfont -- er ikke definert}
+\setinterfacemessage{fonts}{7}{ukjent format --}
+\setinterfacemessage{fonts}{6}{-- er lest inn}
+\setinterfacemessage{fonts}{14}{bodyfont -- is defined (can better be done global)}
+\setinterfacemessage{fonts}{8}{stil -- definert}
+\setinterfacemessage{fonts}{title}{hovedfont}
+\setinterfacemessage{fonts}{10}{ukjent fontfil --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{global fil --}
+\setinterfacemessage{databases}{2}{lokal fil --}
+\setinterfacemessage{databases}{4}{ukjent fil --}
+\setinterfacemessage{databases}{title}{databaser}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{leser inn scriptsett --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{ukjent 'preamble' --}
+\setinterfacemessage{check}{1}{manglende '=' etter '--' i linje --}
+\setinterfacemessage{check}{3}{-- -- overskygger en makro, bruk STORE BOKSTAVER!}
+\setinterfacemessage{check}{2}{-- argument forventet i linje --}
+\setinterfacemessage{check}{title}{kontroll}
+\setinterfacemessage{metapost}{1}{metapost bibliotek -- blir lest inn}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{figure -- can not be found}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{figure -- is not preset}
+\setinterfacemessage{figures}{5}{dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{dimensions of -- loaded from figurefile itself}
+\setinterfacemessage{figures}{6}{dimensions of -- calculated by rlxtools}
+\setinterfacemessage{figures}{8}{figureobject -- is reused}
+\setinterfacemessage{figures}{title}{figures}
+\setinterfacemessage{colors}{1}{system -- er aktivert globalt}
+\setinterfacemessage{colors}{3}{-- er udefinert --}
+\setinterfacemessage{colors}{2}{system -- er aktivert lokalt}
+\setinterfacemessage{colors}{5}{ukjent system --}
+\setinterfacemessage{colors}{4}{system -- er lest inn}
+\setinterfacemessage{colors}{7}{palett -- er ikke tilgjengelig}
+\setinterfacemessage{colors}{6}{palett -- er tilgjengelig}
+\setinterfacemessage{colors}{9}{-- fargerom er ikke støttet}
+\setinterfacemessage{colors}{8}{spesifikasjon -- for farge -- gir kun svart}
+\setinterfacemessage{colors}{title}{farge}
+\setinterfacemessage{colors}{12}{-- is registered}
+\setinterfacemessage{colors}{11}{fargen vil bli vist som grø}
+\setinterfacemessage{colors}{10}{-- fargerom er støttet}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mpe.tex b/tex/context/base/mult-mpe.tex
new file mode 100644
index 000000000..4c1bc9942
--- /dev/null
+++ b/tex/context/base/mult-mpe.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{unknown reference --}
+\setinterfacemessage{references}{3}{unknown reference type --}
+\setinterfacemessage{references}{2}{duplicate reference -- on page --}
+\setinterfacemessage{references}{4}{illegal reference --}
+\setinterfacemessage{references}{30}{unknown object --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{references}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{duplicate object --}
+\setinterfacemessage{references}{21}{document -- loaded}
+\setinterfacemessage{references}{22}{document -- is not interactive}
+\setinterfacemessage{references}{23}{obscure reference -- (prefix=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{number --}
+\setinterfacemessage{handlings}{1}{font handling --}
+\setinterfacemessage{handlings}{3}{unknown font handling --}
+\setinterfacemessage{handlings}{2}{font handling -- is loaded}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{system}
+\setinterfacemessage{systems}{41}{external file -- in group -- does not exist}
+\setinterfacemessage{systems}{9}{-- not found/processed}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{new version of utility file, second pass needed}
+\setinterfacemessage{systems}{21}{no utility data is loaded}
+\setinterfacemessage{systems}{20}{meaning (sorts) of -- loaded}
+\setinterfacemessage{systems}{5}{module -- loaded}
+\setinterfacemessage{systems}{4}{command -- is already defined}
+\setinterfacemessage{systems}{27}{Version}
+\setinterfacemessage{systems}{26}{Registers}
+\setinterfacemessage{systems}{25}{References}
+\setinterfacemessage{systems}{24}{Floatblocks}
+\setinterfacemessage{systems}{1}{loading utility-file postponed (typemode)}
+\setinterfacemessage{systems}{23}{-- arranged at --}
+\setinterfacemessage{systems}{22}{use a valid utilityfile}
+\setinterfacemessage{systems}{2}{-- loaded}
+\setinterfacemessage{systems}{19}{meaning (synonyms) of -- loaded}
+\setinterfacemessage{systems}{18}{synonym -- -- does not exist}
+\setinterfacemessage{systems}{7}{module -- already loaded}
+\setinterfacemessage{systems}{6}{module -- not found}
+\setinterfacemessage{systems}{14}{forced newpage in list at --}
+\setinterfacemessage{systems}{15}{saving buffer --}
+\setinterfacemessage{systems}{16}{typesetting buffer --}
+\setinterfacemessage{systems}{17}{typesetting verbatim buffer --}
+\setinterfacemessage{systems}{13}{mark -- defined --}
+\setinterfacemessage{systems}{12}{the utility-file is not sorted, use texutil}
+\setinterfacemessage{systems}{11}{building simple util}
+\setinterfacemessage{systems}{10}{don't use em in --}
+\setinterfacemessage{floatblocks}{1}{-- renumbered / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- moved}
+\setinterfacemessage{floatblocks}{2}{-- saved}
+\setinterfacemessage{floatblocks}{5}{order adapted}
+\setinterfacemessage{floatblocks}{4}{-- placed}
+\setinterfacemessage{floatblocks}{7}{n of bottom floats limited to --}
+\setinterfacemessage{floatblocks}{6}{n of top floats limited to --}
+\setinterfacemessage{floatblocks}{9}{order disturbed}
+\setinterfacemessage{floatblocks}{8}{less than -- lines}
+\setinterfacemessage{floatblocks}{title}{floatblocks}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{undefined}
+\setinterfacemessage{floatblocks}{11}{no block given}
+\setinterfacemessage{floatblocks}{10}{-- limited}
+\setinterfacemessage{interactions}{1}{aspect ratio -- x -- (b x h)}
+\setinterfacemessage{interactions}{3}{inactive}
+\setinterfacemessage{interactions}{2}{active}
+\setinterfacemessage{interactions}{5}{unknown attachment --}
+\setinterfacemessage{interactions}{4}{no pagesynchronisation (--) in hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- does not exist}
+\setinterfacemessage{interactions}{title}{interaction}
+\setinterfacemessage{interactions}{21}{-- code inserted}
+\setinterfacemessage{regimes}{1}{regime --}
+\setinterfacemessage{regimes}{3}{unknown regime --}
+\setinterfacemessage{regimes}{2}{regime -- is loaded}
+\setinterfacemessage{regimes}{title}{regime}
+\setinterfacemessage{structures}{1}{begin of sectionblock --}
+\setinterfacemessage{structures}{title}{structure}
+\setinterfacemessage{structures}{2}{end of sectionblock --}
+\setinterfacemessage{linguals}{1}{patterns -- for -- loaded (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{hyphenations -- for -- loaded (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{no patterns -- for -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{patterns for -- not loaded}
+\setinterfacemessage{linguals}{4}{no hyphenations -- for -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{language specific options [--] introduce a -- skip}
+\setinterfacemessage{linguals}{6}{language -- is undefined}
+\setinterfacemessage{linguals}{9}{language -- is active}
+\setinterfacemessage{linguals}{8}{language specific options [--] seamless appended}
+\setinterfacemessage{linguals}{title}{language}
+\setinterfacemessage{linguals}{10}{patterns --loaded}
+\setinterfacemessage{verbatims}{1}{file -- does not exist}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{filter -- is loaded}
+\setinterfacemessage{filters}{title}{filter}
+\setinterfacemessage{filters}{2}{unknown filter --}
+\setinterfacemessage{textblocks}{1}{new version, second pass needed}
+\setinterfacemessage{textblocks}{3}{reading blocks from --}
+\setinterfacemessage{textblocks}{2}{writing blocks to --}
+\setinterfacemessage{textblocks}{5}{-- not hidden}
+\setinterfacemessage{textblocks}{4}{second pass needed}
+\setinterfacemessage{textblocks}{7}{-- hidden}
+\setinterfacemessage{textblocks}{6}{-- hidden and processed}
+\setinterfacemessage{textblocks}{9}{-- not typeset}
+\setinterfacemessage{textblocks}{8}{-- typeset}
+\setinterfacemessage{textblocks}{title}{textblocks}
+\setinterfacemessage{textblocks}{12}{-- skipped}
+\setinterfacemessage{textblocks}{11}{-- loaded and typeset}
+\setinterfacemessage{textblocks}{10}{-- loaded and processed}
+\setinterfacemessage{encodings}{1}{coding --}
+\setinterfacemessage{encodings}{3}{unknown coding --}
+\setinterfacemessage{encodings}{2}{coding -- is loaded}
+\setinterfacemessage{encodings}{title}{encoding}
+\setinterfacemessage{columns}{1}{only -- columns possible}
+\setinterfacemessage{columns}{3}{problems, disable balancing}
+\setinterfacemessage{columns}{2}{use \string\filbreak\space as alternative}
+\setinterfacemessage{columns}{5}{bottom float not yet supported}
+\setinterfacemessage{columns}{4}{top float not yet supported}
+\setinterfacemessage{columns}{7}{balancing aborted after 100 steps}
+\setinterfacemessage{columns}{6}{-- float(s) postponed}
+\setinterfacemessage{columns}{9}{check raggedness}
+\setinterfacemessage{columns}{8}{balanced in -- step(s)}
+\setinterfacemessage{columns}{title}{columns}
+\setinterfacemessage{columns}{13}{wide float moved to top of columns}
+\setinterfacemessage{columns}{12}{float moved to next column / --}
+\setinterfacemessage{columns}{11}{float too wide for column}
+\setinterfacemessage{columns}{10}{(less than) 1 line left}
+\setinterfacemessage{symbols}{1}{loading symbolset --}
+\setinterfacemessage{symbols}{title}{symbols}
+\setinterfacemessage{files}{1}{file synonym -- is already used for --}
+\setinterfacemessage{files}{title}{files}
+\setinterfacemessage{versions}{1}{missing @+}
+\setinterfacemessage{versions}{3}{selected pages: --}
+\setinterfacemessage{versions}{2}{marking pages}
+\setinterfacemessage{versions}{title}{version}
+\setinterfacemessage{specials}{1}{-- loaded}
+\setinterfacemessage{specials}{3}{-- is reset}
+\setinterfacemessage{specials}{2}{no deeper nesting is permitted --}
+\setinterfacemessage{specials}{5}{loading definition file --}
+\setinterfacemessage{specials}{4}{command -- does not exist}
+\setinterfacemessage{specials}{7}{unknown driver --}
+\setinterfacemessage{specials}{6}{nesting is not permitted}
+\setinterfacemessage{specials}{title}{specials}
+\setinterfacemessage{layouts}{1}{textheight adapted with -- at page --}
+\setinterfacemessage{layouts}{3}{-- times text postponed}
+\setinterfacemessage{layouts}{2}{-- times postponed text placed}
+\setinterfacemessage{layouts}{5}{marginblocks inactive}
+\setinterfacemessage{layouts}{4}{marginblocks active}
+\setinterfacemessage{layouts}{7}{calculating logospace}
+\setinterfacemessage{layouts}{6}{subpage set -- processed (size --)}
+\setinterfacemessage{layouts}{9}{currently no more than -- levels in itemizations}
+\setinterfacemessage{layouts}{8}{calculating backgrounds}
+\setinterfacemessage{layouts}{title}{layout}
+\setinterfacemessage{layouts}{11}{spacing -- not permitted in gridmode}
+\setinterfacemessage{layouts}{10}{-- and -- don't add up to 1.0}
+\setinterfacemessage{fonts}{1}{coding --}
+\setinterfacemessage{fonts}{3}{unknown variant --}
+\setinterfacemessage{fonts}{2}{variant -- is loaded}
+\setinterfacemessage{fonts}{5}{style -- is not defined}
+\setinterfacemessage{fonts}{4}{bodyfont -- is not defined}
+\setinterfacemessage{fonts}{7}{unknown format --}
+\setinterfacemessage{fonts}{6}{-- is loaded}
+\setinterfacemessage{fonts}{14}{bodyfont -- is defined (can better be done global)}
+\setinterfacemessage{fonts}{8}{style -- defined}
+\setinterfacemessage{fonts}{title}{bodyfont}
+\setinterfacemessage{fonts}{10}{unknown font file --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{global file --}
+\setinterfacemessage{databases}{2}{local file --}
+\setinterfacemessage{databases}{4}{unknown file --}
+\setinterfacemessage{databases}{title}{databases}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{loading script set --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{unknown preamble --}
+\setinterfacemessage{check}{1}{missing or ungrouped '=' after '--' in line --}
+\setinterfacemessage{check}{3}{-- -- replaces a macro, use CAPITALS!}
+\setinterfacemessage{check}{2}{-- argument(s) expected in line --}
+\setinterfacemessage{check}{title}{check}
+\setinterfacemessage{metapost}{1}{loading metapost library --}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{figure -- can not be found}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{figure -- is not preset}
+\setinterfacemessage{figures}{5}{dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{dimensions of -- loaded from figurefile itself}
+\setinterfacemessage{figures}{6}{dimensions of -- calculated by rlxtools}
+\setinterfacemessage{figures}{8}{figureobject -- is reused}
+\setinterfacemessage{figures}{title}{figures}
+\setinterfacemessage{colors}{1}{system -- is global activated}
+\setinterfacemessage{colors}{3}{-- is not defined --}
+\setinterfacemessage{colors}{2}{system -- is local activated}
+\setinterfacemessage{colors}{5}{unknown system --}
+\setinterfacemessage{colors}{4}{system -- is loaded}
+\setinterfacemessage{colors}{7}{palette -- is not available}
+\setinterfacemessage{colors}{6}{palette -- is available}
+\setinterfacemessage{colors}{9}{-- color space is not supported}
+\setinterfacemessage{colors}{8}{specification -- at color -- becomes black}
+\setinterfacemessage{colors}{title}{color}
+\setinterfacemessage{colors}{12}{-- is registered}
+\setinterfacemessage{colors}{11}{color is converted to gray}
+\setinterfacemessage{colors}{10}{-- color space is supported}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-mro.tex b/tex/context/base/mult-mro.tex
new file mode 100644
index 000000000..da96a23a4
--- /dev/null
+++ b/tex/context/base/mult-mro.tex
@@ -0,0 +1,208 @@
+\setinterfacemessage{references}{1}{referinta necunoscuta --}
+\setinterfacemessage{references}{3}{tip necunoscut de referinta --}
+\setinterfacemessage{references}{2}{referinta duplicat -- la pagina --}
+\setinterfacemessage{references}{4}{referinta eronata --}
+\setinterfacemessage{references}{30}{obiect necunoscut --}
+\setinterfacemessage{references}{25}{references from document '--' are not imported (export again)}
+\setinterfacemessage{references}{24}{references from document '--' are not exported}
+\setinterfacemessage{references}{title}{referinte}
+\setinterfacemessage{references}{26}{references from document '--' are imported}
+\setinterfacemessage{references}{31}{obiect duplicat --}
+\setinterfacemessage{references}{21}{documentul -- este incarcat}
+\setinterfacemessage{references}{22}{documentul -- nu este interactiv}
+\setinterfacemessage{references}{23}{referinta obscura -- (prefix=--)}
+\setinterfacemessage{documents}{1}{sheet --}
+\setinterfacemessage{documents}{title}{sheets}
+\setinterfacemessage{documents}{2}{number --}
+\setinterfacemessage{handlings}{1}{font handling --}
+\setinterfacemessage{handlings}{3}{unknown font handling --}
+\setinterfacemessage{handlings}{2}{font handling -- is loaded}
+\setinterfacemessage{handlings}{title}{handling}
+\setinterfacemessage{systems}{title}{sistem}
+\setinterfacemessage{systems}{41}{fisierul extern -- din grupul -- nu exista}
+\setinterfacemessage{systems}{9}{-- nu este gasit/procesat}
+\setinterfacemessage{systems}{91}{papertray --}
+\setinterfacemessage{systems}{8}{o noua versiune de fisier utilitar, este necesara o noua trecere}
+\setinterfacemessage{systems}{21}{nici o data utilitara nu este incarcata}
+\setinterfacemessage{systems}{20}{intelesul (ordinea) pentru -- incarcat}
+\setinterfacemessage{systems}{5}{macro-urile din modulul -- s-au incarcat}
+\setinterfacemessage{systems}{4}{comanda -- este deja definita}
+\setinterfacemessage{systems}{27}{Versiune}
+\setinterfacemessage{systems}{26}{Registri}
+\setinterfacemessage{systems}{25}{Referinte}
+\setinterfacemessage{systems}{24}{Blocuri}
+\setinterfacemessage{systems}{1}{se incarca utilitarul-fisierul este amanat (typemode)}
+\setinterfacemessage{systems}{23}{-- aranjat la --}
+\setinterfacemessage{systems}{22}{folositi un fisier utilitar valid}
+\setinterfacemessage{systems}{2}{-- s-a incarcat}
+\setinterfacemessage{systems}{19}{intelesul (sinonimele) pentru -- incarcat}
+\setinterfacemessage{systems}{18}{sinonimul -- -- nu exista}
+\setinterfacemessage{systems}{7}{macro-urile din modulul -- s-au incarcat deja}
+\setinterfacemessage{systems}{6}{nu s-au gasit macro-uri in modulul --}
+\setinterfacemessage{systems}{14}{s-a fortat trecere pa pagina noua in lista la --}
+\setinterfacemessage{systems}{15}{buffer salvat --}
+\setinterfacemessage{systems}{16}{buffer-ul -- s-a cules}
+\setinterfacemessage{systems}{17}{se culege buffer-ul verbatim --}
+\setinterfacemessage{systems}{13}{marcajul -- definit --}
+\setinterfacemessage{systems}{12}{fisierul utilitar nu este sortat, folositi texutil}
+\setinterfacemessage{systems}{11}{se creeaza un utilitar simplu}
+\setinterfacemessage{systems}{10}{nu folositi em in --}
+\setinterfacemessage{floatblocks}{1}{-- renumerotat / -- => --}
+\setinterfacemessage{floatblocks}{3}{-- mutat}
+\setinterfacemessage{floatblocks}{2}{-- salvat}
+\setinterfacemessage{floatblocks}{5}{ordinea adaptata}
+\setinterfacemessage{floatblocks}{4}{-- plasat}
+\setinterfacemessage{floatblocks}{7}{nr. blocurilor de jos limitat la --}
+\setinterfacemessage{floatblocks}{6}{nr. cadrelor de sus limitat la --}
+\setinterfacemessage{floatblocks}{9}{ordinea deranjata}
+\setinterfacemessage{floatblocks}{8}{mai putin de -- linii}
+\setinterfacemessage{floatblocks}{title}{Blocuri}
+\setinterfacemessage{floatblocks}{13}{there is nothing to split}
+\setinterfacemessage{floatblocks}{12}{nedefinit}
+\setinterfacemessage{floatblocks}{11}{nu este dat nici un bloc}
+\setinterfacemessage{floatblocks}{10}{-- limitat}
+\setinterfacemessage{interactions}{1}{aspectul -- x -- (b x h)}
+\setinterfacemessage{interactions}{3}{inactiv}
+\setinterfacemessage{interactions}{2}{activ}
+\setinterfacemessage{interactions}{5}{unknown attachment --}
+\setinterfacemessage{interactions}{4}{nu exista sincronizare pt. pagini (--) in hmode}
+\setinterfacemessage{interactions}{6}{attachment file -- does not exist}
+\setinterfacemessage{interactions}{title}{interactiuni}
+\setinterfacemessage{interactions}{21}{-- cod inserat}
+\setinterfacemessage{regimes}{1}{codificarea --}
+\setinterfacemessage{regimes}{3}{codificarea -- este necunoscuta}
+\setinterfacemessage{regimes}{2}{codificarea -- este Encarcata}
+\setinterfacemessage{regimes}{title}{codificari}
+\setinterfacemessage{structures}{1}{inceput de bloc sectiune --}
+\setinterfacemessage{structures}{title}{structuri}
+\setinterfacemessage{structures}{2}{sfarsit de bloc sectiune --}
+\setinterfacemessage{linguals}{1}{sablonul -- pentru -- s-a incarcat (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{3}{despartirea in silabe -- pentru -- s-a incarcat (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{2}{nu exista sabloane -- pentru -- (n=--,e=--,m=--) (--,--)}
+\setinterfacemessage{linguals}{5}{sabloanele pentru -- nu sunt incarcate}
+\setinterfacemessage{linguals}{4}{nu exista despartire in silabe -- pentru -- (n=--,e=--,m=--)}
+\setinterfacemessage{linguals}{7}{optiunile specifice ale limbii [--] introduc un spatiu --}
+\setinterfacemessage{linguals}{6}{limba -- nu este definita}
+\setinterfacemessage{linguals}{9}{limba -- este activa}
+\setinterfacemessage{linguals}{8}{optiunile specifice ale limbii [--] adaugate}
+\setinterfacemessage{linguals}{title}{limbi}
+\setinterfacemessage{linguals}{10}{sabloanele -- incarcate}
+\setinterfacemessage{verbatims}{1}{fisierul -- nu exista}
+\setinterfacemessage{verbatims}{title}{verbatim}
+\setinterfacemessage{filters}{1}{filter -- is loaded}
+\setinterfacemessage{filters}{title}{filter}
+\setinterfacemessage{filters}{2}{unknown filter --}
+\setinterfacemessage{textblocks}{1}{o noua versiune, este nevoie de inca o trecere}
+\setinterfacemessage{textblocks}{3}{se citesc blocurile din --}
+\setinterfacemessage{textblocks}{2}{se scriu blocurile in --}
+\setinterfacemessage{textblocks}{5}{-- nu este ascuns}
+\setinterfacemessage{textblocks}{4}{este nevoie de inca o trecere}
+\setinterfacemessage{textblocks}{7}{-- ascuns}
+\setinterfacemessage{textblocks}{6}{-- ascuns si procesat}
+\setinterfacemessage{textblocks}{9}{-- nu este cules}
+\setinterfacemessage{textblocks}{8}{-- cules}
+\setinterfacemessage{textblocks}{title}{blocuri de text}
+\setinterfacemessage{textblocks}{12}{-- sarit peste}
+\setinterfacemessage{textblocks}{11}{-- incarcat si cules}
+\setinterfacemessage{textblocks}{10}{-- incarcat si procesat}
+\setinterfacemessage{encodings}{1}{codificarea --}
+\setinterfacemessage{encodings}{3}{codificarea -- este necunoscuta}
+\setinterfacemessage{encodings}{2}{codificarea -- este Encarcata}
+\setinterfacemessage{encodings}{title}{codificari}
+\setinterfacemessage{columns}{1}{este posibil numai -- coloane}
+\setinterfacemessage{columns}{3}{probleme, se dezactiveaza alinierea}
+\setinterfacemessage{columns}{2}{folositi \string\filbreak\space ca alternativa}
+\setinterfacemessage{columns}{5}{cadrele bottom (bottom float) nu sunt inca suportate}
+\setinterfacemessage{columns}{4}{cadrele top (top float) nu sunt inca suportate}
+\setinterfacemessage{columns}{7}{alinierea este oprita dupa 100 de incercari}
+\setinterfacemessage{columns}{6}{-- blocurile sunt amanate}
+\setinterfacemessage{columns}{9}{verificat alinierea}
+\setinterfacemessage{columns}{8}{aliniat in -- pas(i)}
+\setinterfacemessage{columns}{title}{coloane}
+\setinterfacemessage{columns}{13}{blocul lat este mutat in partea de sus a coloanelor}
+\setinterfacemessage{columns}{12}{blocul este mutat pe urmatoarea coloana / --}
+\setinterfacemessage{columns}{11}{blocul este prea lat pentru coloana}
+\setinterfacemessage{columns}{10}{a mai ramas (mai putin de) 1 linie}
+\setinterfacemessage{symbols}{1}{se incarca setul de simboluri --}
+\setinterfacemessage{symbols}{title}{simboluri}
+\setinterfacemessage{files}{1}{sinonimul fisierelor -- este folosit deja pentru --}
+\setinterfacemessage{files}{title}{fisiere}
+\setinterfacemessage{versions}{1}{lipseste @+}
+\setinterfacemessage{versions}{3}{pagini selectate: --}
+\setinterfacemessage{versions}{2}{pagini marcate}
+\setinterfacemessage{versions}{title}{versiuni}
+\setinterfacemessage{specials}{1}{-- incarcat}
+\setinterfacemessage{specials}{3}{-- s-a resetat}
+\setinterfacemessage{specials}{2}{nu este permis un nivel de imbricare mai mare --}
+\setinterfacemessage{specials}{5}{se incarca fisierul de definitii --}
+\setinterfacemessage{specials}{4}{comanda -- nu exista}
+\setinterfacemessage{specials}{7}{driver necunoscut --}
+\setinterfacemessage{specials}{6}{imbricarea nu este permisa}
+\setinterfacemessage{specials}{title}{specials}
+\setinterfacemessage{layouts}{1}{textheight adaptat cu -- la pagina --}
+\setinterfacemessage{layouts}{3}{textul amanat de -- ori}
+\setinterfacemessage{layouts}{2}{textul amanat de -- ori a fost plasat}
+\setinterfacemessage{layouts}{5}{blocuri marginale inactive}
+\setinterfacemessage{layouts}{4}{blocuri marginale active}
+\setinterfacemessage{layouts}{7}{se calculeaza spatiul pentru logo}
+\setinterfacemessage{layouts}{6}{setul -- de subpagini procesat (dimensiunea --)}
+\setinterfacemessage{layouts}{9}{acum nu se supota mai mult de -- nivele de adancime la iteratii}
+\setinterfacemessage{layouts}{8}{se calculeaza fundalurile}
+\setinterfacemessage{layouts}{title}{aranjamente}
+\setinterfacemessage{layouts}{11}{spatierea -- nu este permisa in gridmode}
+\setinterfacemessage{layouts}{10}{-- si -- nu se adauga pana la 1.0}
+\setinterfacemessage{fonts}{1}{codificarea --}
+\setinterfacemessage{fonts}{3}{varianta necunoscuta --}
+\setinterfacemessage{fonts}{2}{varianta -- este incarcata}
+\setinterfacemessage{fonts}{5}{stilul -- nu este definit}
+\setinterfacemessage{fonts}{4}{corpul de litere -- nu este definit}
+\setinterfacemessage{fonts}{7}{format necunoscut --}
+\setinterfacemessage{fonts}{6}{-- este incarcat}
+\setinterfacemessage{fonts}{14}{bodyfont -- is defined (can better be done global)}
+\setinterfacemessage{fonts}{8}{stilul -- definit}
+\setinterfacemessage{fonts}{title}{corp de litere}
+\setinterfacemessage{fonts}{10}{fisier font necunoscut --}
+\setinterfacemessage{databases}{1}{--}
+\setinterfacemessage{databases}{3}{fisier global --}
+\setinterfacemessage{databases}{2}{fisier local --}
+\setinterfacemessage{databases}{4}{fisier necunoscut --}
+\setinterfacemessage{databases}{title}{baze de date}
+\setinterfacemessage{publications}{1}{file -- not found, unknown style ignored}
+\setinterfacemessage{publications}{3}{wrote a new auxiliary file \jobname.aux}
+\setinterfacemessage{publications}{title}{publications}
+\setinterfacemessage{publications}{2}{file -- not found, waiting for bibtex}
+\setinterfacemessage{publications}{4}{loading database from --}
+\setinterfacemessage{publications}{5}{warning: cite argument -- on line \the\inputlineno}
+\setinterfacemessage{publications}{6}{loading formatting style from --}
+\setinterfacemessage{javascript}{1}{se incarca scriptul --}
+\setinterfacemessage{javascript}{title}{javascript}
+\setinterfacemessage{javascript}{2}{preambul necunoscut --}
+\setinterfacemessage{check}{1}{lipseste '=' dupa '--' in linia --}
+\setinterfacemessage{check}{3}{-- -- inlocuieste un macro, folositi MAJUSCULE!}
+\setinterfacemessage{check}{2}{argumentul(ele) -- sunt asteptate in linia --}
+\setinterfacemessage{check}{title}{verificari}
+\setinterfacemessage{metapost}{1}{se incarca biblioteca metapost --}
+\setinterfacemessage{metapost}{title}{metapost}
+\setinterfacemessage{figures}{1}{figura -- nu poate fi gasita}
+\setinterfacemessage{figures}{3}{dimensions of -- are determined externally}
+\setinterfacemessage{figures}{2}{figura -- nu este presetata}
+\setinterfacemessage{figures}{5}{dimensions of -- are unknown}
+\setinterfacemessage{figures}{4}{dimensiunea figurii -- se incarca din fisierul insusi}
+\setinterfacemessage{figures}{6}{dimensiunea figurii -- este calculata de rlxtools}
+\setinterfacemessage{figures}{8}{obiectul figura -- este refolosit}
+\setinterfacemessage{figures}{title}{figuri}
+\setinterfacemessage{colors}{1}{sistem -- este activata global}
+\setinterfacemessage{colors}{3}{-- nu este definita --}
+\setinterfacemessage{colors}{2}{sistem -- este activata local}
+\setinterfacemessage{colors}{5}{sistem -- necunoscuta}
+\setinterfacemessage{colors}{4}{sistem -- este incarcata}
+\setinterfacemessage{colors}{7}{palette -- nu este disponibila}
+\setinterfacemessage{colors}{6}{paleta -- este disponibila}
+\setinterfacemessage{colors}{9}{spatiul de culoare -- nu este suportat}
+\setinterfacemessage{colors}{8}{specificatia -- la culoarea -- devine neagra}
+\setinterfacemessage{colors}{title}{culori}
+\setinterfacemessage{colors}{12}{-- is registered}
+\setinterfacemessage{colors}{11}{culoarea este convertita la gri}
+\setinterfacemessage{colors}{10}{spatiul de culoare -- este suportat}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-nl.tex b/tex/context/base/mult-nl.tex
new file mode 100644
index 000000000..074d5f3d5
--- /dev/null
+++ b/tex/context/base/mult-nl.tex
@@ -0,0 +1,1693 @@
+% this file is auto-generated, don't edit this file
+%
+% definitions for interface variables for language nl
+%
+\setinterfacevariable{Addition}{Toevoeging}
+\setinterfacevariable{Balloon}{Ballon}
+\setinterfacevariable{Character}{Letter}
+\setinterfacevariable{Characters}{Letters}
+\setinterfacevariable{CloseDocument}{SluitDocument}
+\setinterfacevariable{ExitViewer}{VerlaatViewer}
+\setinterfacevariable{FirstPage}{EerstePagina}
+\setinterfacevariable{FitHeight}{HoogtePassend}
+\setinterfacevariable{FitWidth}{BreedtePassend}
+\setinterfacevariable{GotoPage}{GaNaarPagina}
+\setinterfacevariable{Greek}{Grieks}
+\setinterfacevariable{Help}{Help}
+\setinterfacevariable{HideField}{VerbergVeld}
+\setinterfacevariable{HideLayer}{VerbergLaag}
+\setinterfacevariable{Key}{Sleutel}
+\setinterfacevariable{LastPage}{LaatstePagina}
+\setinterfacevariable{LoadForm}{LaadFormulier}
+\setinterfacevariable{MONTH}{MAAND}
+\setinterfacevariable{New}{Nieuw}
+\setinterfacevariable{NextJump}{VolgendeSprong}
+\setinterfacevariable{NextPage}{VolgendePagina}
+\setinterfacevariable{Numbers}{Cijfers}
+\setinterfacevariable{OpenNamedDocument}{OpenDocumentOpNaam}
+\setinterfacevariable{Paragraph}{Paragraaf}
+\setinterfacevariable{PauseMovie}{PauzeerFilm}
+\setinterfacevariable{PauseRendering}{PauzeerRendering}
+\setinterfacevariable{PauseSound}{PauzeerGeluid}
+\setinterfacevariable{PreviousJump}{VorigeSprong}
+\setinterfacevariable{PreviousPage}{VorigePagina}
+\setinterfacevariable{PrintDocument}{PrintDocument}
+\setinterfacevariable{Query}{RaadpleegDocument}
+\setinterfacevariable{QueryAgain}{HerhaalRaadplegen}
+\setinterfacevariable{ResetForm}{ResetFormulier}
+\setinterfacevariable{ResumeMovie}{HervatFilm}
+\setinterfacevariable{ResumeRendering}{HervatRendering}
+\setinterfacevariable{ResumeSound}{HervatGeluid}
+\setinterfacevariable{Romannumerals}{Romeins}
+\setinterfacevariable{SaveDocument}{BewaarDocument}
+\setinterfacevariable{SaveForm}{BewaarFormulier}
+\setinterfacevariable{SaveNamedDocument}{BewaarDocumentOpNaam}
+\setinterfacevariable{SearchAgain}{HerhaalZoeken}
+\setinterfacevariable{SearchDocument}{DoorzoekDocument}
+\setinterfacevariable{ShowBookmarks}{ShowBookmarks}
+\setinterfacevariable{ShowField}{ToonVeld}
+\setinterfacevariable{ShowThumbs}{ShowThumbs}
+\setinterfacevariable{StartMovie}{StartFilm}
+\setinterfacevariable{StartRendering}{StartRendering}
+\setinterfacevariable{StartSound}{StartGeluid}
+\setinterfacevariable{StopMovie}{StopFilm}
+\setinterfacevariable{StopRendering}{StopRendering}
+\setinterfacevariable{StopSound}{StopGeluid}
+\setinterfacevariable{SubmitForm}{VerzendFormulier}
+\setinterfacevariable{ToggleLayer}{WisselLaag}
+\setinterfacevariable{ToggleViewer}{WisselViewer}
+\setinterfacevariable{URL}{URL}
+\setinterfacevariable{VideLayer}{ToonLaag}
+\setinterfacevariable{ViewerHelp}{ViewerHelp}
+\setinterfacevariable{WEEKDAY}{WEEKDAG}
+\setinterfacevariable{WORD}{WOORD}
+\setinterfacevariable{abbreviation}{afkorting}
+\setinterfacevariable{abbreviations}{afkortingen}
+\setinterfacevariable{absolute}{absoluut}
+\setinterfacevariable{action}{actie}
+\setinterfacevariable{after}{na}
+\setinterfacevariable{all}{alles}
+\setinterfacevariable{always}{altijd}
+\setinterfacevariable{answerarea}{antwoordgebied}
+\setinterfacevariable{appendices}{bijlagen}
+\setinterfacevariable{appendix}{bijlage}
+\setinterfacevariable{april}{april}
+\setinterfacevariable{atmargin}{opmarge}
+\setinterfacevariable{atpage}{oppagina}
+\setinterfacevariable{august}{augustus}
+\setinterfacevariable{author}{auteur}
+\setinterfacevariable{auto}{auto}
+\setinterfacevariable{autointro}{autointro}
+\setinterfacevariable{back}{terug}
+\setinterfacevariable{background}{achtergrond}
+\setinterfacevariable{backmatter}{uitleidingen}
+\setinterfacevariable{backpart}{uitleiding}
+\setinterfacevariable{backspace}{rugwit}
+\setinterfacevariable{backward}{achteruit}
+\setinterfacevariable{bbl}{bbl}
+\setinterfacevariable{before}{voor}
+\setinterfacevariable{begin}{begin}
+\setinterfacevariable{bib}{bib}
+\setinterfacevariable{big}{groot}
+\setinterfacevariable{bigbodyfont}{grootkorps}
+\setinterfacevariable{bigpreference}{grotevoorkeur}
+\setinterfacevariable{blank}{blanko}
+\setinterfacevariable{blockquote}{blokcitaat}
+\setinterfacevariable{bodymatter}{hoofdteksten}
+\setinterfacevariable{bodypart}{hoofdtekst}
+\setinterfacevariable{bold}{vet}
+\setinterfacevariable{bolditalic}{vetitalic}
+\setinterfacevariable{boldslanted}{vetschuin}
+\setinterfacevariable{bookmark}{bookmark}
+\setinterfacevariable{both}{beide}
+\setinterfacevariable{bottom}{onder}
+\setinterfacevariable{brief}{brief}
+\setinterfacevariable{broad}{ruim}
+\setinterfacevariable{buffer}{buffer}
+\setinterfacevariable{by}{per}
+\setinterfacevariable{calligraphic}{calligrafie}
+\setinterfacevariable{cap}{kap}
+\setinterfacevariable{capital}{kapitaal}
+\setinterfacevariable{center}{centreer}
+\setinterfacevariable{chapter}{hoofdstuk}
+\setinterfacevariable{character}{letter}
+\setinterfacevariable{characters}{letters}
+\setinterfacevariable{cite}{cite}
+\setinterfacevariable{color}{kleur}
+\setinterfacevariable{column}{kolom}
+\setinterfacevariable{columns}{kolommen}
+\setinterfacevariable{command}{commando}
+\setinterfacevariable{commands}{commandos}
+\setinterfacevariable{comment}{commentaar}
+\setinterfacevariable{component}{onderdeel}
+\setinterfacevariable{concept}{concept}
+\setinterfacevariable{content}{inhoud}
+\setinterfacevariable{contents}{inhouden}
+\setinterfacevariable{continue}{verder}
+\setinterfacevariable{controls}{sturing}
+\setinterfacevariable{conversion}{conversie}
+\setinterfacevariable{current}{huidige}
+\setinterfacevariable{cutspace}{snijwit}
+\setinterfacevariable{date}{datum}
+\setinterfacevariable{day}{dag}
+\setinterfacevariable{december}{december}
+\setinterfacevariable{default}{default}
+\setinterfacevariable{depth}{diepte}
+\setinterfacevariable{description}{doordefinitie}
+\setinterfacevariable{disable}{blokkeer}
+\setinterfacevariable{display}{scherm}
+\setinterfacevariable{dot}{punt}
+\setinterfacevariable{doublesided}{dubbelzijdig}
+\setinterfacevariable{down}{omlaag}
+\setinterfacevariable{each}{elk}
+\setinterfacevariable{edge}{rand}
+\setinterfacevariable{empty}{leeg}
+\setinterfacevariable{end}{eind}
+\setinterfacevariable{endnote}{eindnoot}
+\setinterfacevariable{enumeration}{doornummering}
+\setinterfacevariable{environment}{omgeving}
+\setinterfacevariable{even}{even}
+\setinterfacevariable{external}{extern}
+\setinterfacevariable{fact}{gegeven}
+\setinterfacevariable{february}{februari}
+\setinterfacevariable{figure}{figuur}
+\setinterfacevariable{figures}{figuren}
+\setinterfacevariable{file}{file}
+\setinterfacevariable{final}{definitief}
+\setinterfacevariable{first}{eerste}
+\setinterfacevariable{firstcolumn}{eerstekolom}
+\setinterfacevariable{firstpage}{eerstepagina}
+\setinterfacevariable{firstsubpage}{eerstesubpagina}
+\setinterfacevariable{fit}{passend}
+\setinterfacevariable{five}{vijf}
+\setinterfacevariable{fix}{herstel}
+\setinterfacevariable{fixed}{vast}
+\setinterfacevariable{flexible}{flexibel}
+\setinterfacevariable{float}{blok}
+\setinterfacevariable{flushinner}{lijnbinnen}
+\setinterfacevariable{flushleft}{lijnlinks}
+\setinterfacevariable{flushouter}{lijnbuiten}
+\setinterfacevariable{flushright}{lijnrechts}
+\setinterfacevariable{footer}{voet}
+\setinterfacevariable{footnote}{voetnoot}
+\setinterfacevariable{force}{forceer}
+\setinterfacevariable{foreground}{voorgrond}
+\setinterfacevariable{formeel}{formeel}
+\setinterfacevariable{formula}{formule}
+\setinterfacevariable{formulae}{formules}
+\setinterfacevariable{forward}{vooruit}
+\setinterfacevariable{four}{vier}
+\setinterfacevariable{frame}{kader}
+\setinterfacevariable{framedtext}{kadertekst}
+\setinterfacevariable{friday}{vrijdag}
+\setinterfacevariable{frontmatter}{inleidingen}
+\setinterfacevariable{frontpart}{inleiding}
+\setinterfacevariable{global}{globaal}
+\setinterfacevariable{graphic}{grafiek}
+\setinterfacevariable{graphics}{grafieken}
+\setinterfacevariable{gray}{grijs}
+\setinterfacevariable{greek}{grieks}
+\setinterfacevariable{grid}{grid}
+\setinterfacevariable{halfline}{halveregel}
+\setinterfacevariable{handwritten}{handschrift}
+\setinterfacevariable{hang}{hang}
+\setinterfacevariable{hanging}{hangend}
+\setinterfacevariable{head}{kop}
+\setinterfacevariable{header}{hoofd}
+\setinterfacevariable{height}{hoogte}
+\setinterfacevariable{helptext}{helptekst}
+\setinterfacevariable{hencefore}{hierboven}
+\setinterfacevariable{here}{hier}
+\setinterfacevariable{hereafter}{hieronder}
+\setinterfacevariable{hidden}{verborgen}
+\setinterfacevariable{hiding}{verbergen}
+\setinterfacevariable{high}{hoog}
+\setinterfacevariable{horizontal}{horizontaal}
+\setinterfacevariable{hyphenated}{afgebroken}
+\setinterfacevariable{hz}{hz}
+\setinterfacevariable{inbetween}{tussen}
+\setinterfacevariable{index}{index}
+\setinterfacevariable{indices}{indices}
+\setinterfacevariable{informeel}{informeel}
+\setinterfacevariable{inherit}{erf}
+\setinterfacevariable{inleft}{inlinker}
+\setinterfacevariable{inmargin}{inmarge}
+\setinterfacevariable{inner}{binnen}
+\setinterfacevariable{inneredge}{binnenrand}
+\setinterfacevariable{innermargin}{binnenmarge}
+\setinterfacevariable{inright}{inrechter}
+\setinterfacevariable{interaction}{interactie}
+\setinterfacevariable{interactionmenu}{interactiemenu}
+\setinterfacevariable{intermezzi}{intermezzos}
+\setinterfacevariable{intermezzo}{intermezzo}
+\setinterfacevariable{intext}{intekst}
+\setinterfacevariable{intro}{intro}
+\setinterfacevariable{italic}{italic}
+\setinterfacevariable{italicbold}{italicvet}
+\setinterfacevariable{item}{som}
+\setinterfacevariable{itemize}{opsomming}
+\setinterfacevariable{its}{its}
+\setinterfacevariable{january}{januari}
+\setinterfacevariable{joinedup}{aansluitend}
+\setinterfacevariable{july}{juli}
+\setinterfacevariable{june}{juni}
+\setinterfacevariable{keep}{handhaaf}
+\setinterfacevariable{knockout}{knockout}
+\setinterfacevariable{label}{label}
+\setinterfacevariable{landscape}{liggend}
+\setinterfacevariable{last}{laatste}
+\setinterfacevariable{lastcolumn}{laatstekolom}
+\setinterfacevariable{lastpage}{laatstepagina}
+\setinterfacevariable{lastpagenumber}{laatstepaginanummer}
+\setinterfacevariable{lastsubpage}{laatstesubpagina}
+\setinterfacevariable{layer}{layer}
+\setinterfacevariable{left}{links}
+\setinterfacevariable{leftedge}{linkerrand}
+\setinterfacevariable{lefthanging}{linkshangend}
+\setinterfacevariable{leftmargin}{linkermarge}
+\setinterfacevariable{leftpage}{linkerpagina}
+\setinterfacevariable{lefttoright}{lefttoright}
+\setinterfacevariable{legend}{legenda}
+\setinterfacevariable{lesshyphenation}{lesshyphenation}
+\setinterfacevariable{line}{regel}
+\setinterfacevariable{linenote}{regelnoot}
+\setinterfacevariable{lines}{regels}
+\setinterfacevariable{list}{lijst}
+\setinterfacevariable{local}{lokaal}
+\setinterfacevariable{localenvironment}{deelomgeving}
+\setinterfacevariable{logo}{logo}
+\setinterfacevariable{logos}{logos}
+\setinterfacevariable{lohi}{laho}
+\setinterfacevariable{loose}{los}
+\setinterfacevariable{low}{laag}
+\setinterfacevariable{ls}{ls}
+\setinterfacevariable{makeup}{opmaak}
+\setinterfacevariable{mar}{mar}
+\setinterfacevariable{march}{maart}
+\setinterfacevariable{margin}{marge}
+\setinterfacevariable{marginedge}{kantlijn}
+\setinterfacevariable{margintitle}{margetitel}
+\setinterfacevariable{marking}{markering}
+\setinterfacevariable{mathalignment}{wiskundeuitlijnen}
+\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathmatrix}{wiskundematrix}
+\setinterfacevariable{max}{max}
+\setinterfacevariable{maxdepth}{maxdepth}
+\setinterfacevariable{maxheight}{maxheight}
+\setinterfacevariable{maxwidth}{maxwidth}
+\setinterfacevariable{may}{mei}
+\setinterfacevariable{mediaeval}{mediaeval}
+\setinterfacevariable{medium}{middel}
+\setinterfacevariable{middle}{midden}
+\setinterfacevariable{min}{min}
+\setinterfacevariable{mindepth}{mindepth}
+\setinterfacevariable{minheight}{minhoogte}
+\setinterfacevariable{minwidth}{minbreedte}
+\setinterfacevariable{mirrored}{gespiegeld}
+\setinterfacevariable{monday}{maandag}
+\setinterfacevariable{mono}{mono}
+\setinterfacevariable{month}{maand}
+\setinterfacevariable{morehyphenation}{morehyphenation}
+\setinterfacevariable{name}{naam}
+\setinterfacevariable{narrow}{smal}
+\setinterfacevariable{negative}{negatief}
+\setinterfacevariable{never}{nooit}
+\setinterfacevariable{new}{nieuw}
+\setinterfacevariable{next}{volgende}
+\setinterfacevariable{nextevenpage}{volgendeevenpagina}
+\setinterfacevariable{nextoddpage}{volgendeonevenpagina}
+\setinterfacevariable{nextpage}{volgendepagina}
+\setinterfacevariable{nextsubpage}{volgendesubpagina}
+\setinterfacevariable{no}{nee}
+\setinterfacevariable{nocheck}{geencontrole}
+\setinterfacevariable{nofit}{nietpassend}
+\setinterfacevariable{nogrid}{geengrid}
+\setinterfacevariable{nohz}{geenhz}
+\setinterfacevariable{nomarking}{geenmarkering}
+\setinterfacevariable{none}{geen}
+\setinterfacevariable{nonumber}{geennummer}
+\setinterfacevariable{normal}{normaal}
+\setinterfacevariable{nospacing}{geenspatiering}
+\setinterfacevariable{not}{niet}
+\setinterfacevariable{note}{note}
+\setinterfacevariable{nothanging}{niethangend}
+\setinterfacevariable{nothyphenated}{nietafgebroken}
+\setinterfacevariable{november}{november}
+\setinterfacevariable{nowhere}{nergens}
+\setinterfacevariable{nowhite}{geenwit}
+\setinterfacevariable{number}{nummer}
+\setinterfacevariable{numbers}{cijfers}
+\setinterfacevariable{october}{oktober}
+\setinterfacevariable{odd}{oneven}
+\setinterfacevariable{off}{uit}
+\setinterfacevariable{offset}{offset}
+\setinterfacevariable{old}{oud}
+\setinterfacevariable{on}{aan}
+\setinterfacevariable{one}{een}
+\setinterfacevariable{opposite}{naast}
+\setinterfacevariable{outer}{buiten}
+\setinterfacevariable{outeredge}{buitenrand}
+\setinterfacevariable{outermargin}{buitenmarge}
+\setinterfacevariable{overbar}{overstreep}
+\setinterfacevariable{overbars}{overstrepen}
+\setinterfacevariable{overlay}{overlay}
+\setinterfacevariable{overprint}{overprint}
+\setinterfacevariable{overstrike}{doorstreep}
+\setinterfacevariable{overstrikes}{doorstrepen}
+\setinterfacevariable{packed}{opelkaar}
+\setinterfacevariable{page}{pagina}
+\setinterfacevariable{pagecomment}{paginacommentaar}
+\setinterfacevariable{pagenumber}{paginanummer}
+\setinterfacevariable{paper}{papier}
+\setinterfacevariable{paragraph}{alinea}
+\setinterfacevariable{part}{deel}
+\setinterfacevariable{positive}{positief}
+\setinterfacevariable{postponing}{uitstellen}
+\setinterfacevariable{postscript}{postscript}
+\setinterfacevariable{preference}{voorkeur}
+\setinterfacevariable{preview}{preview}
+\setinterfacevariable{previous}{vorige}
+\setinterfacevariable{previousevenpage}{vorigeevenpagina}
+\setinterfacevariable{previousoddpage}{vorigeonevenpagina}
+\setinterfacevariable{previouspage}{vorigepagina}
+\setinterfacevariable{previoussubpage}{vorigesubpagina}
+\setinterfacevariable{printable}{printbaar}
+\setinterfacevariable{process}{proces}
+\setinterfacevariable{product}{produkt}
+\setinterfacevariable{program}{programma}
+\setinterfacevariable{project}{project}
+\setinterfacevariable{protected}{beschermd}
+\setinterfacevariable{quadruple}{viertal}
+\setinterfacevariable{quotation}{citaat}
+\setinterfacevariable{quote}{citeer}
+\setinterfacevariable{ran}{ran}
+\setinterfacevariable{random}{willekeurig}
+\setinterfacevariable{readonly}{alleenleesbaar}
+\setinterfacevariable{rectangular}{recht}
+\setinterfacevariable{referral}{kenmerk}
+\setinterfacevariable{register}{register}
+\setinterfacevariable{regular}{regular}
+\setinterfacevariable{rekening}{rekening}
+\setinterfacevariable{relative}{relatief}
+\setinterfacevariable{repeat}{herhaal}
+\setinterfacevariable{required}{verplicht}
+\setinterfacevariable{reset}{reset}
+\setinterfacevariable{reverse}{omgekeerd}
+\setinterfacevariable{right}{rechts}
+\setinterfacevariable{rightedge}{rechterrand}
+\setinterfacevariable{righthanging}{rechtshangend}
+\setinterfacevariable{rightmargin}{rechtermarge}
+\setinterfacevariable{rightpage}{rechterpagina}
+\setinterfacevariable{righttoleft}{righttoleft}
+\setinterfacevariable{roman}{romaan}
+\setinterfacevariable{romannumerals}{romeins}
+\setinterfacevariable{rotate}{roteer}
+\setinterfacevariable{rotated}{geroteerd}
+\setinterfacevariable{round}{rond}
+\setinterfacevariable{row}{rij}
+\setinterfacevariable{rule}{lijn}
+\setinterfacevariable{samepage}{zelfdepagina}
+\setinterfacevariable{sans}{sans}
+\setinterfacevariable{sansbold}{sansvet}
+\setinterfacevariable{sansserif}{schreefloos}
+\setinterfacevariable{saturday}{zaterdag}
+\setinterfacevariable{screen}{raster}
+\setinterfacevariable{section}{paragraaf}
+\setinterfacevariable{sectionblockenvironment}{sectieblokomgeving}
+\setinterfacevariable{sectionnumber}{sectienummer}
+\setinterfacevariable{see}{zie}
+\setinterfacevariable{september}{september}
+\setinterfacevariable{serif}{serif}
+\setinterfacevariable{serried}{aanelkaar}
+\setinterfacevariable{setups}{instellingen}
+\setinterfacevariable{sheet}{sheet}
+\setinterfacevariable{short}{kort}
+\setinterfacevariable{singlesided}{enkelzijdig}
+\setinterfacevariable{slanted}{schuin}
+\setinterfacevariable{slantedbold}{schuinvet}
+\setinterfacevariable{small}{klein}
+\setinterfacevariable{smallbodyfont}{kleinkorps}
+\setinterfacevariable{smallbold}{kleinvet}
+\setinterfacevariable{smallbolditalic}{kleinvetitalic}
+\setinterfacevariable{smallboldslanted}{kleinvetschuin}
+\setinterfacevariable{smallcaps}{smallcaps}
+\setinterfacevariable{smallitalic}{kleinitalic}
+\setinterfacevariable{smallitalicbold}{kleinitalicvet}
+\setinterfacevariable{smallnormal}{kleinnormaal}
+\setinterfacevariable{smallslanted}{kleinschuin}
+\setinterfacevariable{smallslantedbold}{kleinschuinvet}
+\setinterfacevariable{smalltype}{kleintype}
+\setinterfacevariable{somewhere}{ergens}
+\setinterfacevariable{sorted}{gesorteerd}
+\setinterfacevariable{space}{spatie}
+\setinterfacevariable{spacing}{spatiering}
+\setinterfacevariable{speech}{spraak}
+\setinterfacevariable{split}{splitsen}
+\setinterfacevariable{spot}{spot}
+\setinterfacevariable{standard}{standaard}
+\setinterfacevariable{start}{start}
+\setinterfacevariable{starter}{opener}
+\setinterfacevariable{sticker}{sticker}
+\setinterfacevariable{stop}{stop}
+\setinterfacevariable{stopper}{afsluiter}
+\setinterfacevariable{stretch}{rek}
+\setinterfacevariable{strict}{streng}
+\setinterfacevariable{strong}{sterk}
+\setinterfacevariable{strut}{strut}
+\setinterfacevariable{sub}{sub}
+\setinterfacevariable{subbackward}{subachteruit}
+\setinterfacevariable{subformula}{subformule}
+\setinterfacevariable{subforward}{subvooruit}
+\setinterfacevariable{subject}{onderwerp}
+\setinterfacevariable{subpage}{subpagina}
+\setinterfacevariable{subsection}{subparagraaf}
+\setinterfacevariable{subsubject}{subonderwerp}
+\setinterfacevariable{subsubsection}{subsubparagraaf}
+\setinterfacevariable{subsubsubject}{subsubonderwerp}
+\setinterfacevariable{subsubsubsection}{subsubsubparagraaf}
+\setinterfacevariable{subsubsubsubject}{subsubsubonderwerp}
+\setinterfacevariable{subsubsubsubsection}{subsubsubsubparagraaf}
+\setinterfacevariable{subsubsubsubsubject}{subsubsubsubonderwerp}
+\setinterfacevariable{subsubsubsubsubsection}{subsubsubsubsubparagraaf}
+\setinterfacevariable{subsubsubsubsubsubject}{subsubsubsubsubonderwerp}
+\setinterfacevariable{subsubsubsubsubsubsection}{subsubsubsubsubsubparagraaf}
+\setinterfacevariable{subsubsubsubsubsubsubject}{subsubsubsubsubsubonderwerp}
+\setinterfacevariable{subsubsubsubsubsubsubsection}{subsubsubsubsubsubsubparagraaf}
+\setinterfacevariable{subsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubonderwerp}
+\setinterfacevariable{subsubsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsubparagraaf}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubonderwerp}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsubsubparagraaf}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubsubonderwerp}
+\setinterfacevariable{sunday}{zondag}
+\setinterfacevariable{support}{support}
+\setinterfacevariable{sym}{sym}
+\setinterfacevariable{symbol}{symbool}
+\setinterfacevariable{synchronize}{synchroniseer}
+\setinterfacevariable{system}{systeem}
+\setinterfacevariable{table}{tabel}
+\setinterfacevariable{tablehead}{tabelkop}
+\setinterfacevariable{tables}{tabellen}
+\setinterfacevariable{tabletail}{tabelstaart}
+\setinterfacevariable{tabulate}{tabulatie}
+\setinterfacevariable{tabulatehead}{tabulatiekop}
+\setinterfacevariable{tabulatetail}{tabulatiestaart}
+\setinterfacevariable{tall}{lang}
+\setinterfacevariable{teletype}{teletype}
+\setinterfacevariable{temporary}{voorlopig}
+\setinterfacevariable{test}{test}
+\setinterfacevariable{text}{tekst}
+\setinterfacevariable{three}{drie}
+\setinterfacevariable{thursday}{donderdag}
+\setinterfacevariable{title}{titel}
+\setinterfacevariable{toggle}{toggle}
+\setinterfacevariable{tolerant}{soepel}
+\setinterfacevariable{top}{boven}
+\setinterfacevariable{tuesday}{dinsdag}
+\setinterfacevariable{two}{twee}
+\setinterfacevariable{txt}{txt}
+\setinterfacevariable{type}{type}
+\setinterfacevariable{typing}{typen}
+\setinterfacevariable{unavailable}{nietbeschikbaar}
+\setinterfacevariable{underbar}{onderstreep}
+\setinterfacevariable{underbars}{onderstrepen}
+\setinterfacevariable{unit}{eenheid}
+\setinterfacevariable{units}{eenheden}
+\setinterfacevariable{unknown}{onbekend}
+\setinterfacevariable{unpacked}{vanelkaar}
+\setinterfacevariable{up}{omhoog}
+\setinterfacevariable{url}{url}
+\setinterfacevariable{used}{gebruikt}
+\setinterfacevariable{value}{waarde}
+\setinterfacevariable{vertical}{vertikaal}
+\setinterfacevariable{very}{zeer}
+\setinterfacevariable{verystrict}{zeerstreng}
+\setinterfacevariable{verytolerant}{zeersoepel}
+\setinterfacevariable{weak}{zwak}
+\setinterfacevariable{wednesday}{woensdag}
+\setinterfacevariable{week}{week}
+\setinterfacevariable{weekday}{weekdag}
+\setinterfacevariable{white}{wit}
+\setinterfacevariable{wide}{breed}
+\setinterfacevariable{width}{breedte}
+\setinterfacevariable{xml}{xml}
+\setinterfacevariable{year}{jaar}
+\setinterfacevariable{yes}{ja}
+% definitions for interface constants for language nl
+%
+\setinterfaceconstant{action}{actie}
+\setinterfaceconstant{address}{adres}
+\setinterfaceconstant{after}{na}
+\setinterfaceconstant{afterhead}{kopna}
+\setinterfaceconstant{afterkey}{natoets}
+\setinterfaceconstant{align}{uitlijnen}
+\setinterfaceconstant{aligncharacter}{karakteruitlijnen}
+\setinterfaceconstant{alignmentcharacter}{uitlijnkarakter}
+\setinterfaceconstant{alignsymbol}{alignsymbol}
+\setinterfaceconstant{aligntitle}{titeluitlijnen}
+\setinterfaceconstant{alternative}{variant}
+\setinterfaceconstant{andtext}{andtext}
+\setinterfaceconstant{apa}{apa}
+\setinterfaceconstant{arrow}{pijl}
+\setinterfaceconstant{artauthor}{artauthor}
+\setinterfaceconstant{artauthoretaldisplay}{artauthoretaldisplay}
+\setinterfaceconstant{artauthoretallimit}{artauthoretallimit}
+\setinterfaceconstant{artauthoretaltext}{artauthoretaltext}
+\setinterfaceconstant{at}{op}
+\setinterfaceconstant{author}{auteur}
+\setinterfaceconstant{authoretaldisplay}{authoretaldisplay}
+\setinterfaceconstant{authoretallimit}{authoretallimit}
+\setinterfaceconstant{authoretaltext}{authoretaltext}
+\setinterfaceconstant{auto}{auto}
+\setinterfaceconstant{autofile}{autofile}
+\setinterfaceconstant{autofocus}{autofocus}
+\setinterfaceconstant{autohang}{autohang}
+\setinterfaceconstant{autostrut}{autostrut}
+\setinterfaceconstant{autowidth}{autobreedte}
+\setinterfaceconstant{axis}{assenstelsel}
+\setinterfaceconstant{background}{achtergrond}
+\setinterfaceconstant{backgroundcolor}{achtergrondkleur}
+\setinterfaceconstant{backgroundcorner}{achtergrondhoek}
+\setinterfaceconstant{backgrounddepth}{achtergronddiepte}
+\setinterfaceconstant{backgroundoffset}{achtergrondoffset}
+\setinterfaceconstant{backgroundradius}{achtergrondstraal}
+\setinterfaceconstant{backgroundscreen}{achtergrondraster}
+\setinterfaceconstant{backspace}{rugwit}
+\setinterfaceconstant{balance}{balanceren}
+\setinterfaceconstant{before}{voor}
+\setinterfaceconstant{beforehead}{kopvoor}
+\setinterfaceconstant{bet}{bet}
+\setinterfaceconstant{big}{groot}
+\setinterfaceconstant{blank}{blanko}
+\setinterfaceconstant{blockway}{blokwijze}
+\setinterfaceconstant{bodyfont}{korps}
+\setinterfaceconstant{bookmark}{bookmark}
+\setinterfaceconstant{bottom}{onder}
+\setinterfaceconstant{bottomafter}{bottomafter}
+\setinterfaceconstant{bottombefore}{bottombefore}
+\setinterfaceconstant{bottomdistance}{onderafstand}
+\setinterfaceconstant{bottomframe}{onderkader}
+\setinterfaceconstant{bottomoffset}{onderoffset}
+\setinterfaceconstant{bottomspace}{bodemwit}
+\setinterfaceconstant{bottomstate}{onderstatus}
+\setinterfaceconstant{cache}{cache}
+\setinterfaceconstant{calculate}{bereken}
+\setinterfaceconstant{ccommand}{ccommando}
+\setinterfaceconstant{click}{klik}
+\setinterfaceconstant{clickin}{klikin}
+\setinterfaceconstant{clickout}{klikuit}
+\setinterfaceconstant{clipoffset}{clipoffset}
+\setinterfaceconstant{closeaction}{sluitactie}
+\setinterfaceconstant{closecommand}{sluitcommando}
+\setinterfaceconstant{closepageaction}{sluitpaginaactie}
+\setinterfaceconstant{closesymbol}{sluitsymbool}
+\setinterfaceconstant{color}{kleur}
+\setinterfaceconstant{column}{kolom}
+\setinterfaceconstant{columndistance}{kolomafstand}
+\setinterfaceconstant{columns}{kolommen}
+\setinterfaceconstant{command}{commando}
+\setinterfaceconstant{commandafter}{nacommando}
+\setinterfaceconstant{commandbefore}{voorcommando}
+\setinterfaceconstant{commands}{commandos}
+\setinterfaceconstant{component}{component}
+\setinterfaceconstant{compoundhyphen}{koppelteken}
+\setinterfaceconstant{compress}{comprimeren}
+\setinterfaceconstant{connector}{connector}
+\setinterfaceconstant{continue}{doorgaan}
+\setinterfaceconstant{contrastcolor}{contrastkleur}
+\setinterfaceconstant{controls}{sturing}
+\setinterfaceconstant{conversion}{conversie}
+\setinterfaceconstant{convertfile}{converteerfile}
+\setinterfaceconstant{corner}{hoek}
+\setinterfaceconstant{coupling}{koppeling}
+\setinterfaceconstant{couplingway}{koppelwijze}
+\setinterfaceconstant{criterium}{criterium}
+\setinterfaceconstant{current}{huidige}
+\setinterfaceconstant{cutspace}{snijwit}
+\setinterfaceconstant{dash}{streep}
+\setinterfaceconstant{dat}{dat}
+\setinterfaceconstant{database}{database}
+\setinterfaceconstant{date}{datum}
+\setinterfaceconstant{deepnumbercommand}{diepnummercommando}
+\setinterfaceconstant{deeptextcommand}{dieptekstcommando}
+\setinterfaceconstant{default}{default}
+\setinterfaceconstant{delay}{wachttijd}
+\setinterfaceconstant{depth}{diepte}
+\setinterfaceconstant{depthcorrection}{dieptecorrectie}
+\setinterfaceconstant{direction}{richting}
+\setinterfaceconstant{directory}{gebied}
+\setinterfaceconstant{display}{scherm}
+\setinterfaceconstant{distance}{afstand}
+\setinterfaceconstant{dot}{punt}
+\setinterfaceconstant{doublesided}{dubbelzijdig}
+\setinterfaceconstant{dummy}{dummy}
+\setinterfaceconstant{dx}{dx}
+\setinterfaceconstant{dy}{dy}
+\setinterfaceconstant{edge}{rand}
+\setinterfaceconstant{edgedistance}{randafstand}
+\setinterfaceconstant{editor}{editor}
+\setinterfaceconstant{editoretaldisplay}{editoretaldisplay}
+\setinterfaceconstant{editoretallimit}{editoretallimit}
+\setinterfaceconstant{editoretaltext}{editoretaltext}
+\setinterfaceconstant{empty}{leeg}
+\setinterfaceconstant{equalheight}{equalheight}
+\setinterfaceconstant{equalwidth}{equalwidth}
+\setinterfaceconstant{escape}{escape}
+\setinterfaceconstant{evenmargin}{evenmarge}
+\setinterfaceconstant{expansion}{expansie}
+\setinterfaceconstant{export}{exporteer}
+\setinterfaceconstant{extras}{extras}
+\setinterfaceconstant{factor}{factor}
+\setinterfaceconstant{fallback}{terugval}
+\setinterfaceconstant{family}{soort}
+\setinterfaceconstant{fieldbackgroundcolor}{veldachtergrondkleur}
+\setinterfaceconstant{fieldframecolor}{veldkaderkleur}
+\setinterfaceconstant{fieldlayer}{veldlaag}
+\setinterfaceconstant{fieldoffset}{veldoffset}
+\setinterfaceconstant{file}{file}
+\setinterfaceconstant{filtercommand}{filtercommand}
+\setinterfaceconstant{finalnamesep}{finalnamesep}
+\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{focus}{focus}
+\setinterfaceconstant{focusin}{focusin}
+\setinterfaceconstant{focusout}{focusuit}
+\setinterfaceconstant{footer}{voet}
+\setinterfaceconstant{footerdistance}{voetafstand}
+\setinterfaceconstant{footerstate}{voetstatus}
+\setinterfaceconstant{foregroundcolor}{voorgrondkleur}
+\setinterfaceconstant{foregroundstyle}{voorgrondletter}
+\setinterfaceconstant{format}{formatteer}
+\setinterfaceconstant{frame}{kader}
+\setinterfaceconstant{framecolor}{kaderkleur}
+\setinterfaceconstant{framecorner}{kaderhoek}
+\setinterfaceconstant{framedepth}{kaderdiepte}
+\setinterfaceconstant{frameoffset}{kaderoffset}
+\setinterfaceconstant{frameradius}{kaderstraal}
+\setinterfaceconstant{frames}{hokjes}
+\setinterfaceconstant{from}{van}
+\setinterfaceconstant{get}{haal}
+\setinterfaceconstant{global}{globaal}
+\setinterfaceconstant{grid}{grid}
+\setinterfaceconstant{hang}{hang}
+\setinterfaceconstant{headalign}{kopuitlijnen}
+\setinterfaceconstant{headcolor}{kopkleur}
+\setinterfaceconstant{headcommand}{kopcommando}
+\setinterfaceconstant{headconversion}{kopconversie}
+\setinterfaceconstant{header}{hoofd}
+\setinterfaceconstant{headerdistance}{hoofdafstand}
+\setinterfaceconstant{headerstate}{hoofdstatus}
+\setinterfaceconstant{headlabel}{koplabel}
+\setinterfaceconstant{headnumber}{kopnummer}
+\setinterfaceconstant{headstyle}{kopletter}
+\setinterfaceconstant{height}{hoogte}
+\setinterfaceconstant{hfactor}{hfactor}
+\setinterfaceconstant{hfil}{hfil}
+\setinterfaceconstant{hidenumber}{hidenumber}
+\setinterfaceconstant{hoffset}{hoffset}
+\setinterfaceconstant{horoffset}{rugoffset}
+\setinterfaceconstant{hyphen}{hyphen}
+\setinterfaceconstant{icommand}{icommando}
+\setinterfaceconstant{in}{in}
+\setinterfaceconstant{inbetween}{tussen}
+\setinterfaceconstant{increment}{verhoog}
+\setinterfaceconstant{incrementnumber}{verhoognummer}
+\setinterfaceconstant{indenting}{inspringen}
+\setinterfaceconstant{indentnext}{springvolgendein}
+\setinterfaceconstant{indicator}{aanduiding}
+\setinterfaceconstant{inner}{binnen}
+\setinterfaceconstant{innermargin}{binnenmarge}
+\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{intent}{intent}
+\setinterfaceconstant{interaction}{interactie}
+\setinterfaceconstant{interlinespace}{interlinie}
+\setinterfaceconstant{itemalign}{itemuitlijnen}
+\setinterfaceconstant{items}{items}
+\setinterfaceconstant{juniorsep}{juniorsep}
+\setinterfaceconstant{ken}{ken}
+\setinterfaceconstant{keyexpansion}{sleutelexpansie}
+\setinterfaceconstant{keyword}{trefwoord}
+\setinterfaceconstant{label}{label}
+\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{left}{links}
+\setinterfaceconstant{leftcolor}{linkerkleur}
+\setinterfaceconstant{leftcompoundhyphen}{linkerkoppelteken}
+\setinterfaceconstant{leftedge}{linkerrand}
+\setinterfaceconstant{leftedgedistance}{linkerrandafstand}
+\setinterfaceconstant{leftframe}{linkerkader}
+\setinterfaceconstant{lefthyphen}{lefthyphen}
+\setinterfaceconstant{leftmargin}{linkermarge}
+\setinterfaceconstant{leftmargindistance}{linkermargeafstand}
+\setinterfaceconstant{leftoffset}{linkeroffset}
+\setinterfaceconstant{leftquotation}{linkercitaat}
+\setinterfaceconstant{leftquote}{linkerciteer}
+\setinterfaceconstant{leftsentence}{linkerzin}
+\setinterfaceconstant{leftspeech}{linkeruitspraak}
+\setinterfaceconstant{leftstyle}{linkerletter}
+\setinterfaceconstant{leftsubsentence}{linkersubzin}
+\setinterfaceconstant{lefttext}{linkertekst}
+\setinterfaceconstant{leftwidth}{linkerbreedte}
+\setinterfaceconstant{level}{niveau}
+\setinterfaceconstant{levels}{niveaus}
+\setinterfaceconstant{limittext}{limiettekst}
+\setinterfaceconstant{line}{regel}
+\setinterfaceconstant{linecorrection}{regelcorrectie}
+\setinterfaceconstant{lines}{regels}
+\setinterfaceconstant{list}{lijst}
+\setinterfaceconstant{listtext}{lijsttekst}
+\setinterfaceconstant{local}{lokaal}
+\setinterfaceconstant{location}{plaats}
+\setinterfaceconstant{logo}{logo}
+\setinterfaceconstant{logos}{logos}
+\setinterfaceconstant{marcolor}{markleur}
+\setinterfaceconstant{margin}{marge}
+\setinterfaceconstant{margindistance}{margeafstand}
+\setinterfaceconstant{marginedge}{kantlijn}
+\setinterfaceconstant{marginedgetext}{kantlijntekst}
+\setinterfaceconstant{margintext}{margetekst}
+\setinterfaceconstant{marking}{markering}
+\setinterfaceconstant{marstyle}{marletter}
+\setinterfaceconstant{max}{max}
+\setinterfaceconstant{maxdepth}{maxdepth}
+\setinterfaceconstant{maxheight}{maxhoogte}
+\setinterfaceconstant{maxwidth}{maxbreedte}
+\setinterfaceconstant{maybeyear}{maybeyear}
+\setinterfaceconstant{menu}{menu}
+\setinterfaceconstant{method}{methode}
+\setinterfaceconstant{middle}{midden}
+\setinterfaceconstant{middlespeech}{middenuitspraak}
+\setinterfaceconstant{middletext}{middentekst}
+\setinterfaceconstant{midsentence}{middenzin}
+\setinterfaceconstant{min}{min}
+\setinterfaceconstant{mindepth}{mindiepte}
+\setinterfaceconstant{minheight}{minhoogte}
+\setinterfaceconstant{minwidth}{minbreedte}
+\setinterfaceconstant{monthconversion}{maandconversie}
+\setinterfaceconstant{n}{n}
+\setinterfaceconstant{name}{naam}
+\setinterfaceconstant{namesep}{namesep}
+\setinterfaceconstant{nbottom}{nonder}
+\setinterfaceconstant{nc}{nc}
+\setinterfaceconstant{next}{volgende}
+\setinterfaceconstant{nl}{nl}
+\setinterfaceconstant{nleft}{nlinks}
+\setinterfaceconstant{nlines}{nregels}
+\setinterfaceconstant{norm}{norm}
+\setinterfaceconstant{nr}{nr}
+\setinterfaceconstant{nright}{nrechts}
+\setinterfaceconstant{ntop}{nboven}
+\setinterfaceconstant{number}{nummer}
+\setinterfaceconstant{numbercolor}{nummerkleur}
+\setinterfaceconstant{numbercommand}{nummercommando}
+\setinterfaceconstant{numberconversion}{numberconversion}
+\setinterfaceconstant{numberconversionset}{numberconversionset}
+\setinterfaceconstant{numberdistance}{nummerafstand}
+\setinterfaceconstant{numbering}{nummeren}
+\setinterfaceconstant{numberorder}{numberorder}
+\setinterfaceconstant{numberprefix}{numberprefix}
+\setinterfaceconstant{numbersegments}{numbersegments}
+\setinterfaceconstant{numberseparator}{nummerscheider}
+\setinterfaceconstant{numberseparatorset}{numberseparatorset}
+\setinterfaceconstant{numberset}{numberset}
+\setinterfaceconstant{numberstarter}{numberstarter}
+\setinterfaceconstant{numberstopper}{numberstopper}
+\setinterfaceconstant{numberstyle}{nummerletter}
+\setinterfaceconstant{numberwidth}{nummerbreedte}
+\setinterfaceconstant{nx}{nx}
+\setinterfaceconstant{ny}{ny}
+\setinterfaceconstant{object}{object}
+\setinterfaceconstant{obstruction}{blokkade}
+\setinterfaceconstant{oddmargin}{onevenmarge}
+\setinterfaceconstant{offset}{offset}
+\setinterfaceconstant{openaction}{openactie}
+\setinterfaceconstant{openpageaction}{openpaginaactie}
+\setinterfaceconstant{option}{optie}
+\setinterfaceconstant{order}{order}
+\setinterfaceconstant{orientation}{orientatie}
+\setinterfaceconstant{otherstext}{otherstext}
+\setinterfaceconstant{outermargin}{buitenmarge}
+\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownnumber}{eigennummer}
+\setinterfaceconstant{page}{pagina}
+\setinterfaceconstant{pageboundaries}{paginaovergangen}
+\setinterfaceconstant{pagecolor}{paginakleur}
+\setinterfaceconstant{pagecommand}{paginacommando}
+\setinterfaceconstant{pageconversion}{pageconversion}
+\setinterfaceconstant{pageconversionset}{pageconversionset}
+\setinterfaceconstant{pagenumber}{paginanummer}
+\setinterfaceconstant{pageprefix}{pageprefix}
+\setinterfaceconstant{pageprefixconnector}{pageprefixconnector}
+\setinterfaceconstant{pageprefixconversion}{pageprefixconversion}
+\setinterfaceconstant{pageprefixconversionset}{pageprefixconversionset}
+\setinterfaceconstant{pageprefixsegments}{pageprefixsegments}
+\setinterfaceconstant{pageprefixseparatorset}{pageprefixseparatorset}
+\setinterfaceconstant{pageprefixset}{pageprefixset}
+\setinterfaceconstant{pageprefixstarter}{pageprefixstarter}
+\setinterfaceconstant{pageprefixstopper}{pageprefixstopper}
+\setinterfaceconstant{pagesegments}{pagesegments}
+\setinterfaceconstant{pageseparatorset}{pageseparatorset}
+\setinterfaceconstant{pageset}{pageset}
+\setinterfaceconstant{pagestarter}{pagestarter}
+\setinterfaceconstant{pagestate}{paginastatus}
+\setinterfaceconstant{pagestopper}{pagestopper}
+\setinterfaceconstant{pagestyle}{paginaletter}
+\setinterfaceconstant{palet}{palet}
+\setinterfaceconstant{paper}{papier}
+\setinterfaceconstant{paragraph}{alinea}
+\setinterfaceconstant{place}{plaatsen}
+\setinterfaceconstant{placehead}{plaatskop}
+\setinterfaceconstant{placestopper}{plaatsafsluiter}
+\setinterfaceconstant{position}{positie}
+\setinterfaceconstant{prefix}{prefix}
+\setinterfaceconstant{prefixconnector}{prefixconnector}
+\setinterfaceconstant{prefixconversion}{prefixconversion}
+\setinterfaceconstant{prefixconversionset}{prefixconversionset}
+\setinterfaceconstant{prefixsegments}{prefixsegments}
+\setinterfaceconstant{prefixseparatorset}{prefixseparatorset}
+\setinterfaceconstant{prefixset}{prefixset}
+\setinterfaceconstant{prefixstarter}{prefixstarter}
+\setinterfaceconstant{prefixstopper}{prefixstopper}
+\setinterfaceconstant{preset}{preset}
+\setinterfaceconstant{preview}{preview}
+\setinterfaceconstant{previous}{vorige}
+\setinterfaceconstant{previousnumber}{vorigenummer}
+\setinterfaceconstant{process}{proces}
+\setinterfaceconstant{pubsep}{pubsep}
+\setinterfaceconstant{radius}{straal}
+\setinterfaceconstant{random}{willekeur}
+\setinterfaceconstant{range}{bereik}
+\setinterfaceconstant{reduction}{reductie}
+\setinterfaceconstant{ref}{ref}
+\setinterfaceconstant{refcommand}{refcommand}
+\setinterfaceconstant{reference}{verwijzing}
+\setinterfaceconstant{referenceprefix}{referenceprefix}
+\setinterfaceconstant{referencing}{refereren}
+\setinterfaceconstant{regionin}{gebiedin}
+\setinterfaceconstant{regionout}{gebieduit}
+\setinterfaceconstant{repeat}{herhaal}
+\setinterfaceconstant{reset}{reset}
+\setinterfaceconstant{resetnumber}{resetnummer}
+\setinterfaceconstant{resolution}{resolutie}
+\setinterfaceconstant{right}{rechts}
+\setinterfaceconstant{rightcolor}{rechterkleur}
+\setinterfaceconstant{rightcompoundhyphen}{rechterkoppelteken}
+\setinterfaceconstant{rightedge}{rechterrand}
+\setinterfaceconstant{rightedgedistance}{rechterrandafstand}
+\setinterfaceconstant{rightframe}{rechterkader}
+\setinterfaceconstant{righthyphen}{righthyphen}
+\setinterfaceconstant{rightmargin}{rechtermarge}
+\setinterfaceconstant{rightmargindistance}{rechtermargeafstand}
+\setinterfaceconstant{rightoffset}{rechteroffset}
+\setinterfaceconstant{rightquotation}{rechtercitaat}
+\setinterfaceconstant{rightquote}{rechterciteer}
+\setinterfaceconstant{rightsentence}{rechterzin}
+\setinterfaceconstant{rightspeech}{rechteruitspraak}
+\setinterfaceconstant{rightstyle}{rechterletter}
+\setinterfaceconstant{rightsubsentence}{rechtersubzin}
+\setinterfaceconstant{righttext}{rechtertekst}
+\setinterfaceconstant{rightwidth}{rechterbreedte}
+\setinterfaceconstant{rotation}{rotatie}
+\setinterfaceconstant{rule}{lijn}
+\setinterfaceconstant{rulecolor}{lijnkleur}
+\setinterfaceconstant{rulethickness}{lijndikte}
+\setinterfaceconstant{samepage}{zelfdepagina}
+\setinterfaceconstant{sample}{monster}
+\setinterfaceconstant{samplesize}{samplesize}
+\setinterfaceconstant{saveinlist}{saveinlist}
+\setinterfaceconstant{scale}{schaal}
+\setinterfaceconstant{scope}{scope}
+\setinterfaceconstant{screen}{raster}
+\setinterfaceconstant{section}{sectie}
+\setinterfaceconstant{sectionconversion}{sectionconversion}
+\setinterfaceconstant{sectionconversionset}{sectionconversionset}
+\setinterfaceconstant{sectionnumber}{sectienummer}
+\setinterfaceconstant{sectionresetset}{sectionresetset}
+\setinterfaceconstant{sectionsegments}{sectionsegments}
+\setinterfaceconstant{sectionseparatorset}{sectionseparatorset}
+\setinterfaceconstant{sectionset}{sectionset}
+\setinterfaceconstant{sectionstarter}{sectionstarter}
+\setinterfaceconstant{sectionstopper}{sectionstopper}
+\setinterfaceconstant{separator}{scheider}
+\setinterfaceconstant{set}{set}
+\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{side}{zij}
+\setinterfaceconstant{sidealign}{zijuitlijnen}
+\setinterfaceconstant{sidemethod}{zijmethode}
+\setinterfaceconstant{sidespaceafter}{zijnawit}
+\setinterfaceconstant{sidespacebefore}{zijvoorwit}
+\setinterfaceconstant{sign}{teken}
+\setinterfaceconstant{size}{formaat}
+\setinterfaceconstant{small}{klein}
+\setinterfaceconstant{sort}{sort}
+\setinterfaceconstant{sorttype}{sortering}
+\setinterfaceconstant{source}{bron}
+\setinterfaceconstant{space}{spatie}
+\setinterfaceconstant{spaceafter}{nawit}
+\setinterfaceconstant{spacebefore}{voorwit}
+\setinterfaceconstant{spaceinbetween}{tussenwit}
+\setinterfaceconstant{spacing}{spatiering}
+\setinterfaceconstant{split}{splitsen}
+\setinterfaceconstant{splitcolor}{splitskleur}
+\setinterfaceconstant{splitmethod}{splitsmethode}
+\setinterfaceconstant{splitoffset}{splitsoffset}
+\setinterfaceconstant{spot}{spot}
+\setinterfaceconstant{stack}{stapel}
+\setinterfaceconstant{start}{start}
+\setinterfaceconstant{starter}{opener}
+\setinterfaceconstant{state}{status}
+\setinterfaceconstant{step}{stap}
+\setinterfaceconstant{stop}{stop}
+\setinterfaceconstant{stopper}{afsluiter}
+\setinterfaceconstant{stretch}{rek}
+\setinterfaceconstant{strip}{strip}
+\setinterfaceconstant{strut}{strut}
+\setinterfaceconstant{style}{letter}
+\setinterfaceconstant{sub}{sub}
+\setinterfaceconstant{subtitle}{subtitel}
+\setinterfaceconstant{suffix}{suffix}
+\setinterfaceconstant{surnamesep}{surnamesep}
+\setinterfaceconstant{sx}{sx}
+\setinterfaceconstant{sy}{sy}
+\setinterfaceconstant{symalign}{symuitlijnen}
+\setinterfaceconstant{symbol}{symbool}
+\setinterfaceconstant{symbolset}{symboolset}
+\setinterfaceconstant{symcolor}{symkleur}
+\setinterfaceconstant{symstyle}{symletter}
+\setinterfaceconstant{synonym}{synoniem}
+\setinterfaceconstant{synonymcolor}{synoniemkleur}
+\setinterfaceconstant{synonymcommand}{synoniemcommando}
+\setinterfaceconstant{synonymstyle}{synoniemletter}
+\setinterfaceconstant{tab}{tab}
+\setinterfaceconstant{text}{tekst}
+\setinterfaceconstant{textcolor}{tekstkleur}
+\setinterfaceconstant{textcommand}{tekstcommando}
+\setinterfaceconstant{textdistance}{tekstafstand}
+\setinterfaceconstant{textlayer}{tekstlaag}
+\setinterfaceconstant{textmargin}{tekstmarge}
+\setinterfaceconstant{textmethod}{tekstmethode}
+\setinterfaceconstant{textseparator}{tekstscheider}
+\setinterfaceconstant{textsize}{tekstformaat}
+\setinterfaceconstant{textstate}{tekststatus}
+\setinterfaceconstant{textstyle}{tekstletter}
+\setinterfaceconstant{textwidth}{tekstbreedte}
+\setinterfaceconstant{title}{titel}
+\setinterfaceconstant{titlecolor}{titelkleur}
+\setinterfaceconstant{titlecommand}{titelcommando}
+\setinterfaceconstant{titledistance}{titelafstand}
+\setinterfaceconstant{titleleft}{titellinks}
+\setinterfaceconstant{titleright}{titelrechts}
+\setinterfaceconstant{titlestyle}{titelletter}
+\setinterfaceconstant{to}{aan}
+\setinterfaceconstant{tolerance}{tolerantie}
+\setinterfaceconstant{top}{boven}
+\setinterfaceconstant{topdistance}{bovenafstand}
+\setinterfaceconstant{topframe}{bovenkader}
+\setinterfaceconstant{topoffset}{bovenoffset}
+\setinterfaceconstant{topspace}{kopwit}
+\setinterfaceconstant{topstate}{bovenstatus}
+\setinterfaceconstant{totalnumber}{totalnumber}
+\setinterfaceconstant{type}{type}
+\setinterfaceconstant{unit}{eenheid}
+\setinterfaceconstant{unknownreference}{onbekendeverwijzing}
+\setinterfaceconstant{urlalternative}{urlvariant}
+\setinterfaceconstant{urlspace}{urlspatie}
+\setinterfaceconstant{validate}{valideer}
+\setinterfaceconstant{vcommand}{vcommando}
+\setinterfaceconstant{veroffset}{kopoffset}
+\setinterfaceconstant{vfil}{vfil}
+\setinterfaceconstant{voffset}{voffset}
+\setinterfaceconstant{vonsep}{vonsep}
+\setinterfaceconstant{way}{wijze}
+\setinterfaceconstant{wfactor}{bfactor}
+\setinterfaceconstant{white}{wit}
+\setinterfaceconstant{width}{breedte}
+\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xmax}{xmax}
+\setinterfaceconstant{xoffset}{xoffset}
+\setinterfaceconstant{xscale}{xschaal}
+\setinterfaceconstant{xstep}{xstap}
+\setinterfaceconstant{yfactor}{yfactor}
+\setinterfaceconstant{ymax}{ymax}
+\setinterfaceconstant{yoffset}{yoffset}
+\setinterfaceconstant{yscale}{yschaal}
+\setinterfaceconstant{ystep}{ystap}
+% definitions for interface elements for language nl
+%
+\setinterfaceelement{answerlines}{antwoordregels}
+\setinterfaceelement{answerspace}{antwoordruimte}
+\setinterfaceelement{begin}{beginvan}
+\setinterfaceelement{complete}{volledige}
+\setinterfaceelement{coupled}{gekoppelde}
+\setinterfaceelement{currentlocal}{huidigelokale}
+\setinterfaceelement{emptyone}{leeg}
+\setinterfaceelement{emptytwo}{lege}
+\setinterfaceelement{end}{eindvan}
+\setinterfaceelement{endsetup}{in}
+\setinterfaceelement{get}{haal}
+\setinterfaceelement{increment}{verhoog}
+\setinterfaceelement{list}{lijst}
+\setinterfaceelement{listof}{lijstmet}
+\setinterfaceelement{load}{laad}
+\setinterfaceelement{local}{lokale}
+\setinterfaceelement{makeup}{opmaak}
+\setinterfaceelement{next}{volgende}
+\setinterfaceelement{place}{plaats}
+\setinterfaceelement{previous}{vorige}
+\setinterfaceelement{previouslocal}{vorigelokale}
+\setinterfaceelement{reserve}{reserveer}
+\setinterfaceelement{see}{zie}
+\setinterfaceelement{setup}{stel}
+\setinterfaceelement{start}{start}
+\setinterfaceelement{stop}{stop}
+\setinterfaceelement{text}{tekst}
+\setinterfaceelement{type}{type}
+% definitions for interface commands for language nl
+%
+\setinterfacecommand{CAPPED}{KAP}
+\setinterfacecommand{Character}{Letter}
+\setinterfacecommand{Characters}{Letters}
+\setinterfacecommand{LABELTEXT}{LABELTEKST}
+\setinterfacecommand{MONTH}{MAAND}
+\setinterfacecommand{Numbers}{Cijfers}
+\setinterfacecommand{Romannumerals}{Romeins}
+\setinterfacecommand{SmallCapped}{Kap}
+\setinterfacecommand{SmallCaps}{Kaps}
+\setinterfacecommand{WEEKDAY}{WEEKDAG}
+\setinterfacecommand{WORD}{WOORD}
+\setinterfacecommand{WORDS}{WOORDEN}
+\setinterfacecommand{Word}{Woord}
+\setinterfacecommand{Words}{Woorden}
+\setinterfacecommand{about}{about}
+\setinterfacecommand{adaptlayout}{paslayoutaan}
+\setinterfacecommand{arg}{arg}
+\setinterfacecommand{at}{op}
+\setinterfacecommand{atleftmargin}{oplinkermarge}
+\setinterfacecommand{atpage}{oppagina}
+\setinterfacecommand{atrightmargin}{oprechtermarge}
+\setinterfacecommand{background}{achtergrond}
+\setinterfacecommand{backspace}{rugwit}
+\setinterfacecommand{blackrule}{blokje}
+\setinterfacecommand{blackrules}{blokjes}
+\setinterfacecommand{blank}{blanko}
+\setinterfacecommand{bookmark}{bookmark}
+\setinterfacecommand{bottomdistance}{onderafstand}
+\setinterfacecommand{bottomheight}{onderhoogte}
+\setinterfacecommand{bottomspace}{bodemwit}
+\setinterfacecommand{but}{but}
+\setinterfacecommand{button}{button}
+\setinterfacecommand{bypassblocks}{passeerblokken}
+\setinterfacecommand{character}{letter}
+\setinterfacecommand{characters}{letters}
+\setinterfacecommand{chem}{chem}
+\setinterfacecommand{clip}{clip}
+\setinterfacecommand{clonefield}{kloonveld}
+\setinterfacecommand{color}{kleur}
+\setinterfacecommand{colorbar}{kleurenbalk}
+\setinterfacecommand{colorvalue}{kleurwaarde}
+\setinterfacecommand{column}{kolom}
+\setinterfacecommand{comment}{commentaar}
+\setinterfacecommand{comparecolorgroup}{vergelijkkleurgroep}
+\setinterfacecommand{comparepalet}{vergelijkpalet}
+\setinterfacecommand{completepagenumber}{volledigepaginanummer}
+\setinterfacecommand{completeregister}{volledigregister}
+\setinterfacecommand{component}{onderdeel}
+\setinterfacecommand{convertnumber}{converteernummer}
+\setinterfacecommand{copyfield}{copieerveld}
+\setinterfacecommand{correctwhitespace}{corrigeerwitruimte}
+\setinterfacecommand{coupledocument}{koppeldocument}
+\setinterfacecommand{couplemarking}{koppelmarkering}
+\setinterfacecommand{couplepage}{koppelpagina}
+\setinterfacecommand{couplepaper}{koppelpapier}
+\setinterfacecommand{coupleregister}{koppelregister}
+\setinterfacecommand{crlf}{crlf}
+\setinterfacecommand{currentdate}{huidigedatum}
+\setinterfacecommand{currentheadnumber}{huidigekopnummer}
+\setinterfacecommand{cutspace}{snijwit}
+\setinterfacecommand{date}{datum}
+\setinterfacecommand{decouplemarking}{ontkoppelmarkering}
+\setinterfacecommand{decrementnumber}{verlaagnummer}
+\setinterfacecommand{define}{definieer}
+\setinterfacecommand{defineaccent}{definieeraccent}
+\setinterfacecommand{defineblank}{definieerblanko}
+\setinterfacecommand{defineblock}{definieerblok}
+\setinterfacecommand{definebodyfont}{definieerkorps}
+\setinterfacecommand{definebodyfontenvironment}{definieerkorpsomgeving}
+\setinterfacecommand{definebuffer}{definieerbuffer}
+\setinterfacecommand{definecharacter}{definieerkarakter}
+\setinterfacecommand{definecolor}{definieerkleur}
+\setinterfacecommand{definecolorgroup}{definieerkleurgroep}
+\setinterfacecommand{definecolumnbreak}{definieerkolomovergang}
+\setinterfacecommand{definecolumnset}{definieerkolomgroep}
+\setinterfacecommand{definecombination}{definieercombinatie}
+\setinterfacecommand{definecombinedlist}{definieersamengesteldelijst}
+\setinterfacecommand{definecommand}{definieercommando}
+\setinterfacecommand{defineconversion}{definieerconversie}
+\setinterfacecommand{definedescription}{doordefinieren}
+\setinterfacecommand{defineenumeration}{doornummeren}
+\setinterfacecommand{definefield}{definieerveld}
+\setinterfacecommand{definefieldstack}{definieerveldstapel}
+\setinterfacecommand{definefiguresymbol}{definieerfiguursymbool}
+\setinterfacecommand{definefloat}{definieerplaatsblok}
+\setinterfacecommand{definefont}{definieerfont}
+\setinterfacecommand{definefontstyle}{definieerfontstijl}
+\setinterfacecommand{definefontsynonym}{definieerfontsynoniem}
+\setinterfacecommand{defineframed}{definieeromlijnd}
+\setinterfacecommand{defineframedtext}{definieerkadertekst}
+\setinterfacecommand{definehbox}{definieerhbox}
+\setinterfacecommand{definehead}{definieerkop}
+\setinterfacecommand{defineindenting}{doorspringen}
+\setinterfacecommand{defineinmargin}{definieerinmarge}
+\setinterfacecommand{defineinteractionmenu}{definieerinteractiemenu}
+\setinterfacecommand{defineitemgroup}{definieeritemgroep}
+\setinterfacecommand{definelabel}{doorlabelen}
+\setinterfacecommand{definelayer}{definieerlayer}
+\setinterfacecommand{definelayout}{definieerlayout}
+\setinterfacecommand{definelist}{definieerlijst}
+\setinterfacecommand{definelogo}{definieerbeeldmerk}
+\setinterfacecommand{definemainfield}{definieerhoofdveld}
+\setinterfacecommand{definemakeup}{definieeropmaak}
+\setinterfacecommand{definemarking}{definieermarkering}
+\setinterfacecommand{definemathalignment}{definieerwiskundeuitlijnen}
+\setinterfacecommand{defineoutput}{definieeruitvoer}
+\setinterfacecommand{defineoverlay}{definieeroverlay}
+\setinterfacecommand{definepagebreak}{definieerpaginaovergang}
+\setinterfacecommand{definepalet}{definieerpalet}
+\setinterfacecommand{definepapersize}{definieerpapierformaat}
+\setinterfacecommand{defineparagraphs}{definieeralineas}
+\setinterfacecommand{defineplacement}{definieerplaats}
+\setinterfacecommand{defineprofile}{definieerprofiel}
+\setinterfacecommand{defineprogram}{definieerprogramma}
+\setinterfacecommand{definerawfont}{definerawfont}
+\setinterfacecommand{definereference}{definieerreferentie}
+\setinterfacecommand{definereferenceformat}{definieerreferentieformaat}
+\setinterfacecommand{definereferencelist}{definieerreferentielijst}
+\setinterfacecommand{defineregister}{definieerregister}
+\setinterfacecommand{definerule}{definieerlijn}
+\setinterfacecommand{definesection}{definieersectie}
+\setinterfacecommand{definesectionblock}{definieersectieblok}
+\setinterfacecommand{definesorting}{definieersorteren}
+\setinterfacecommand{definestartstop}{definieerstartstop}
+\setinterfacecommand{definestyle}{definieerletter}
+\setinterfacecommand{definesubfield}{definieersubveld}
+\setinterfacecommand{definesymbol}{definieersymbool}
+\setinterfacecommand{definesynonyms}{definieersynoniemen}
+\setinterfacecommand{definetabletemplate}{definieertabelvorm}
+\setinterfacecommand{definetabulate}{definieertabulatie}
+\setinterfacecommand{definetext}{definieertekst}
+\setinterfacecommand{definetextposition}{definieertekstpositie}
+\setinterfacecommand{definetextvariable}{definieertekstvariabele}
+\setinterfacecommand{definetype}{definieertype}
+\setinterfacecommand{definetyping}{definieertypen}
+\setinterfacecommand{defineversion}{definieerversie}
+\setinterfacecommand{determineheadnumber}{bepaalkopnummer}
+\setinterfacecommand{determinelistcharacteristics}{bepaallijstkenmerken}
+\setinterfacecommand{determineregistercharacteristics}{bepaalregisterkenmerken}
+\setinterfacecommand{dimension}{dimensie}
+\setinterfacecommand{disableinteractionmenu}{blokkeerinteractiemenu}
+\setinterfacecommand{domicile}{woonplaats}
+\setinterfacecommand{donttest}{geentest}
+\setinterfacecommand{edgedistance}{randafstand}
+\setinterfacecommand{edgewidth}{randbreedte}
+\setinterfacecommand{emptylines}{legeregels}
+\setinterfacecommand{environment}{omgeving}
+\setinterfacecommand{externalfigure}{externfiguur}
+\setinterfacecommand{fact}{geg}
+\setinterfacecommand{field}{veld}
+\setinterfacecommand{fieldstack}{veldstapel}
+\setinterfacecommand{fillinfield}{invulveld}
+\setinterfacecommand{fillinline}{invulregel}
+\setinterfacecommand{fillinrules}{invullijnen}
+\setinterfacecommand{fillintext}{invultekst}
+\setinterfacecommand{fitfield}{passendveld}
+\setinterfacecommand{fixedspace}{vastespatie}
+\setinterfacecommand{fixedspaces}{vastespaties}
+\setinterfacecommand{followprofile}{volgprofiel}
+\setinterfacecommand{followprofileversion}{volgprofielversie}
+\setinterfacecommand{followversion}{volgversie}
+\setinterfacecommand{footerdistance}{voetafstand}
+\setinterfacecommand{footerheight}{voethoogte}
+\setinterfacecommand{footnote}{voetnoot}
+\setinterfacecommand{footnotetext}{voetnoottekst}
+\setinterfacecommand{forceblocks}{forceerblokken}
+\setinterfacecommand{formulanumber}{formulenummer}
+\setinterfacecommand{fraction}{breuk}
+\setinterfacecommand{framed}{omlijnd}
+\setinterfacecommand{from}{uit}
+\setinterfacecommand{getbuffer}{haalbuffer}
+\setinterfacecommand{getmarking}{haalmarkering}
+\setinterfacecommand{getnumber}{haalnummer}
+\setinterfacecommand{godown}{omlaag}
+\setinterfacecommand{goto}{naar}
+\setinterfacecommand{gotobox}{naarbox}
+\setinterfacecommand{gotopage}{naarpagina}
+\setinterfacecommand{graycolor}{grijskleur}
+\setinterfacecommand{greyvalue}{grijswaarde}
+\setinterfacecommand{grid}{rooster}
+\setinterfacecommand{hairline}{haarlijn}
+\setinterfacecommand{head}{kop}
+\setinterfacecommand{headerdistance}{hoofdafstand}
+\setinterfacecommand{headerheight}{hoofdhoogte}
+\setinterfacecommand{headlevel}{kopniveau}
+\setinterfacecommand{headnumber}{kopnummer}
+\setinterfacecommand{headsym}{kopsym}
+\setinterfacecommand{headtext}{koptekst}
+\setinterfacecommand{hideblocks}{verbergblokken}
+\setinterfacecommand{high}{hoog}
+\setinterfacecommand{hl}{hl}
+\setinterfacecommand{immediatebetweenlist}{directtussenlijst}
+\setinterfacecommand{immediatetolist}{directnaarlijst}
+\setinterfacecommand{in}{in}
+\setinterfacecommand{incrementnumber}{verhoognummer}
+\setinterfacecommand{indenting}{inspringen}
+\setinterfacecommand{inframed}{inlijnd}
+\setinterfacecommand{infull}{voluit}
+\setinterfacecommand{ininner}{inbinnen}
+\setinterfacecommand{inleft}{inlinker}
+\setinterfacecommand{inleftedge}{inlinkerrand}
+\setinterfacecommand{inleftmargin}{inlinkermarge}
+\setinterfacecommand{inline}{inregel}
+\setinterfacecommand{inmargin}{inmarge}
+\setinterfacecommand{inmframed}{inwilijnd}
+\setinterfacecommand{inneredgedistance}{binnenrandafstand}
+\setinterfacecommand{inneredgewidth}{binnenrandbreedte}
+\setinterfacecommand{innermargindistance}{binnenmargeafstand}
+\setinterfacecommand{innermarginwidth}{binnenmargebreedte}
+\setinterfacecommand{inothermargin}{inanderemarge}
+\setinterfacecommand{inouter}{inbuiten}
+\setinterfacecommand{inright}{inrechter}
+\setinterfacecommand{inrightedge}{inrechterrand}
+\setinterfacecommand{inrightmargin}{inrechtermarge}
+\setinterfacecommand{installlanguage}{installeertaal}
+\setinterfacecommand{interactionbar}{interactiebalk}
+\setinterfacecommand{interactionbuttons}{interactiebuttons}
+\setinterfacecommand{interactionmenu}{interactiemenu}
+\setinterfacecommand{item}{som}
+\setinterfacecommand{items}{items}
+\setinterfacecommand{its}{its}
+\setinterfacecommand{keepblocks}{handhaafblokken}
+\setinterfacecommand{label}{label}
+\setinterfacecommand{labels}{labels}
+\setinterfacecommand{labeltext}{labeltekst}
+\setinterfacecommand{language}{taal}
+\setinterfacecommand{leftaligned}{regellinks}
+\setinterfacecommand{leftedgedistance}{linkerrandafstand}
+\setinterfacecommand{leftedgewidth}{linkerrandbreedte}
+\setinterfacecommand{leftmargindistance}{linkermargeafstand}
+\setinterfacecommand{leftmarginwidth}{linkermargebreedte}
+\setinterfacecommand{leg}{leg}
+\setinterfacecommand{linewidth}{lijndikte}
+\setinterfacecommand{listheight}{lijsthoogte}
+\setinterfacecommand{listlength}{lijstlengte}
+\setinterfacecommand{listsymbol}{lijstsymbool}
+\setinterfacecommand{listwidth}{lijstbreedte}
+\setinterfacecommand{logfields}{registreervelden}
+\setinterfacecommand{lohi}{laho}
+\setinterfacecommand{low}{laag}
+\setinterfacecommand{macroname}{naam}
+\setinterfacecommand{mainlanguage}{hoofdtaal}
+\setinterfacecommand{makeupheight}{zethoogte}
+\setinterfacecommand{makeupwidth}{zetbreedte}
+\setinterfacecommand{mar}{mar}
+\setinterfacecommand{margindistance}{margeafstand}
+\setinterfacecommand{marginrule}{kantlijn}
+\setinterfacecommand{margintext}{margetekst}
+\setinterfacecommand{margintitle}{margetitel}
+\setinterfacecommand{marginwidth}{margebreedte}
+\setinterfacecommand{marginword}{margewoord}
+\setinterfacecommand{marking}{markeer}
+\setinterfacecommand{markversion}{markeerversie}
+\setinterfacecommand{mathematics}{wiskunde}
+\setinterfacecommand{menubutton}{menubutton}
+\setinterfacecommand{mframed}{wilijnd}
+\setinterfacecommand{midaligned}{regelmidden}
+\setinterfacecommand{mirror}{spiegel}
+\setinterfacecommand{month}{maand}
+\setinterfacecommand{moveformula}{verplaatsformule}
+\setinterfacecommand{moveongrid}{verplaatsopgrid}
+\setinterfacecommand{movesidefloat}{verplaatszijblok}
+\setinterfacecommand{navigating}{navigerend}
+\setinterfacecommand{nodimension}{geendimensie}
+\setinterfacecommand{noheaderandfooterlines}{geenhoofdenvoetregels}
+\setinterfacecommand{noindenting}{nietinspringen}
+\setinterfacecommand{nolist}{geenlijst}
+\setinterfacecommand{nomarking}{geenmarkering}
+\setinterfacecommand{nomoreblocks}{geenblokkenmeer}
+\setinterfacecommand{nomorefiles}{geenfilesmeer}
+\setinterfacecommand{nop}{nop}
+\setinterfacecommand{nospace}{geenspatie}
+\setinterfacecommand{note}{noot}
+\setinterfacecommand{notopandbottomlines}{geenbovenenonderregels}
+\setinterfacecommand{notsmallcapped}{nokap}
+\setinterfacecommand{nowhitespace}{geenwitruimte}
+\setinterfacecommand{numberofsubpages}{aantalsubpaginas}
+\setinterfacecommand{numbers}{cijfers}
+\setinterfacecommand{outeredgedistance}{buitenrandafstand}
+\setinterfacecommand{outeredgewidth}{buitenrandbreedte}
+\setinterfacecommand{outermargindistance}{buitenmargeafstand}
+\setinterfacecommand{outermarginwidth}{buitenmargebreedte}
+\setinterfacecommand{packed}{opelkaar}
+\setinterfacecommand{page}{pagina}
+\setinterfacecommand{pagedepth}{paginadiepte}
+\setinterfacecommand{pagenumber}{paginanummer}
+\setinterfacecommand{pageoffset}{paginaoffset}
+\setinterfacecommand{pagereference}{paginareferentie}
+\setinterfacecommand{pagetype}{soortpagina}
+\setinterfacecommand{paperheight}{papierhoogte}
+\setinterfacecommand{paperwidth}{papierbreedte}
+\setinterfacecommand{periods}{punten}
+\setinterfacecommand{plaatsruwelijst}{plaatsruwelijst}
+\setinterfacecommand{placebookmarks}{plaatsbookmarks}
+\setinterfacecommand{placecombinedlist}{plaatssamengesteldelijst}
+\setinterfacecommand{placefloat}{plaatsplaatsblok}
+\setinterfacecommand{placefootnotes}{plaatsvoetnoten}
+\setinterfacecommand{placeformula}{plaatsformule}
+\setinterfacecommand{placeheadnumber}{plaatskopnummer}
+\setinterfacecommand{placeheadtext}{plaatskoptekst}
+\setinterfacecommand{placelegend}{plaatslegenda}
+\setinterfacecommand{placelist}{plaatslijst}
+\setinterfacecommand{placelocalfootnotes}{plaatslokalevoetnoten}
+\setinterfacecommand{placelogos}{plaatsbeeldmerken}
+\setinterfacecommand{placeongrid}{plaatsopgrid}
+\setinterfacecommand{placeontopofeachother}{plaatsonderelkaar}
+\setinterfacecommand{placepagenumber}{plaatspaginanummer}
+\setinterfacecommand{placereferencelist}{plaatsreferentielijst}
+\setinterfacecommand{placeregister}{plaatsregister}
+\setinterfacecommand{placerule}{plaatslijn}
+\setinterfacecommand{placesidebyside}{plaatsnaastelkaar}
+\setinterfacecommand{placesubformula}{plaatssubformule}
+\setinterfacecommand{placetextvariable}{plaatstekstvariabele}
+\setinterfacecommand{position}{positioneer}
+\setinterfacecommand{positiontext}{positioneertekst}
+\setinterfacecommand{printpaperheight}{printpapierhoogte}
+\setinterfacecommand{printpaperwidth}{printpapierbreedte}
+\setinterfacecommand{processblocks}{verwerkblokken}
+\setinterfacecommand{processpage}{verwerkpagina}
+\setinterfacecommand{product}{produkt}
+\setinterfacecommand{program}{programma}
+\setinterfacecommand{project}{projekt}
+\setinterfacecommand{publication}{publicatie}
+\setinterfacecommand{quotation}{citaat}
+\setinterfacecommand{quote}{citeer}
+\setinterfacecommand{ran}{ran}
+\setinterfacecommand{redo}{herhaal}
+\setinterfacecommand{ref}{ref}
+\setinterfacecommand{reference}{referentie}
+\setinterfacecommand{referral}{kenmerk}
+\setinterfacecommand{referraldate}{kenmerkdatum}
+\setinterfacecommand{referring}{refereer}
+\setinterfacecommand{remark}{toelichting}
+\setinterfacecommand{reset}{reset}
+\setinterfacecommand{resetmarking}{resetmarkering}
+\setinterfacecommand{resetnumber}{resetnummer}
+\setinterfacecommand{resettext}{resettekstinhoud}
+\setinterfacecommand{rightaligned}{regelrechts}
+\setinterfacecommand{rightedgedistance}{rechterrandafstand}
+\setinterfacecommand{rightedgewidth}{rechterrandbreedte}
+\setinterfacecommand{rightmargindistance}{rechtermargeafstand}
+\setinterfacecommand{rightmarginwidth}{rechtermargebreedte}
+\setinterfacecommand{romannumerals}{romeins}
+\setinterfacecommand{rotate}{roteer}
+\setinterfacecommand{scale}{schaal}
+\setinterfacecommand{screen}{scherm}
+\setinterfacecommand{selectblocks}{selecteerblokken}
+\setinterfacecommand{selectpaper}{selecteerpapier}
+\setinterfacecommand{selectversion}{selecteerversie}
+\setinterfacecommand{setnumber}{setnummer}
+\setinterfacecommand{settextcontent}{steltekstinhoudin}
+\setinterfacecommand{settextvariable}{kentekstvariabeletoe}
+\setinterfacecommand{setupalign}{steluitlijnenin}
+\setinterfacecommand{setupanswerarea}{stelantwoordgebiedin}
+\setinterfacecommand{setuparranging}{stelarrangerenin}
+\setinterfacecommand{setupbackground}{stelachtergrondin}
+\setinterfacecommand{setupbackgrounds}{stelachtergrondenin}
+\setinterfacecommand{setupblackrules}{stelblokjesin}
+\setinterfacecommand{setupblank}{stelblankoin}
+\setinterfacecommand{setupblock}{stelblokin}
+\setinterfacecommand{setupbodyfont}{stelkorpsin}
+\setinterfacecommand{setupbodyfontenvironment}{stelkorpsomgevingin}
+\setinterfacecommand{setupbottom}{stelonderin}
+\setinterfacecommand{setupbottomtexts}{stelondertekstenin}
+\setinterfacecommand{setupbuffer}{stelbufferin}
+\setinterfacecommand{setupbuttons}{stelbuttonsin}
+\setinterfacecommand{setupcapitals}{stelkapitalenin}
+\setinterfacecommand{setupcaption}{stelblokkopjein}
+\setinterfacecommand{setupcaptions}{stelblokkopjesin}
+\setinterfacecommand{setupclipping}{stelclipin}
+\setinterfacecommand{setupcolor}{stelkleurin}
+\setinterfacecommand{setupcolors}{stelkleurenin}
+\setinterfacecommand{setupcolumns}{stelkolommenin}
+\setinterfacecommand{setupcolumnset}{stelkolomgroepin}
+\setinterfacecommand{setupcolumnsetlines}{stelkolomgroepregelsin}
+\setinterfacecommand{setupcolumnsetstart}{stelkolomgroepstartin}
+\setinterfacecommand{setupcombinations}{stelcombinatiesin}
+\setinterfacecommand{setupcombinedlist}{stelsamengesteldelijstin}
+\setinterfacecommand{setupcomment}{stelcommentaarin}
+\setinterfacecommand{setupdescriptions}{steldoordefinierenin}
+\setinterfacecommand{setupenumerations}{steldoornummerenin}
+\setinterfacecommand{setupexternalfigures}{stelexternefigurenin}
+\setinterfacecommand{setupfield}{stelveldin}
+\setinterfacecommand{setupfields}{stelveldenin}
+\setinterfacecommand{setupfillinlines}{stelinvulregelsin}
+\setinterfacecommand{setupfillinrules}{stelinvullijnenin}
+\setinterfacecommand{setupfloat}{stelplaatsblokin}
+\setinterfacecommand{setupfloats}{stelplaatsblokkenin}
+\setinterfacecommand{setupfloatsplitting}{stelplaatsbloksplitsenin}
+\setinterfacecommand{setupfooter}{stelvoetin}
+\setinterfacecommand{setupfootertexts}{stelvoettekstenin}
+\setinterfacecommand{setupfootnotedefinition}{stelvoetnootdefinitiein}
+\setinterfacecommand{setupfootnotes}{stelvoetnotenin}
+\setinterfacecommand{setupforms}{stelformulierenin}
+\setinterfacecommand{setupformulas}{stelformulesin}
+\setinterfacecommand{setupframed}{stelomlijndin}
+\setinterfacecommand{setupframedtexts}{stelkadertekstenin}
+\setinterfacecommand{setuphead}{stelkopin}
+\setinterfacecommand{setupheader}{stelhoofdin}
+\setinterfacecommand{setupheadertexts}{stelhoofdtekstenin}
+\setinterfacecommand{setupheadnumber}{stelkopnummerin}
+\setinterfacecommand{setupheads}{stelkoppenin}
+\setinterfacecommand{setupheadtext}{stelkoptekstin}
+\setinterfacecommand{setuphyphenmark}{stelkoppeltekenin}
+\setinterfacecommand{setupindentations}{steldoorspringenin}
+\setinterfacecommand{setupindenting}{stelinspringenin}
+\setinterfacecommand{setupinmargin}{stelinmargein}
+\setinterfacecommand{setupinteraction}{stelinteractiein}
+\setinterfacecommand{setupinteractionbar}{stelinteractiebalkin}
+\setinterfacecommand{setupinteractionmenu}{stelinteractiemenuin}
+\setinterfacecommand{setupinteractionscreen}{stelinteractieschermin}
+\setinterfacecommand{setupinterlinespace}{stelinterliniein}
+\setinterfacecommand{setupitemgroup}{stelitemgroepin}
+\setinterfacecommand{setupitemgroups}{stelopsommingenin}
+\setinterfacecommand{setupitems}{stelitemsin}
+\setinterfacecommand{setuplabeltext}{stellabeltekstin}
+\setinterfacecommand{setuplanguage}{steltaalin}
+\setinterfacecommand{setuplayout}{stellayoutin}
+\setinterfacecommand{setuplegend}{stellegendain}
+\setinterfacecommand{setuplinenumbering}{stelregelnummerenin}
+\setinterfacecommand{setuplines}{stelregelsin}
+\setinterfacecommand{setuplinewidth}{stellijndiktein}
+\setinterfacecommand{setuplist}{stellijstin}
+\setinterfacecommand{setupmakeup}{stelopmaakin}
+\setinterfacecommand{setupmarginblocks}{stelmargeblokkenin}
+\setinterfacecommand{setupmarginrules}{stelkantlijnin}
+\setinterfacecommand{setupmarking}{stelmarkeringin}
+\setinterfacecommand{setupmathalignment}{stelwiskundeuitlijnenin}
+\setinterfacecommand{setupnarrower}{stelsmallerin}
+\setinterfacecommand{setupnumber}{stelnummerin}
+\setinterfacecommand{setupnumbering}{stelnummerenin}
+\setinterfacecommand{setupoppositeplacing}{stelnaastplaatsenin}
+\setinterfacecommand{setupoutput}{steluitvoerin}
+\setinterfacecommand{setuppagecomment}{stelpaginacommentaarin}
+\setinterfacecommand{setuppagenumber}{stelpaginanummerin}
+\setinterfacecommand{setuppagenumbering}{stelpaginanummeringin}
+\setinterfacecommand{setuppagetransitions}{stelpaginaovergangenin}
+\setinterfacecommand{setuppalet}{stelpaletin}
+\setinterfacecommand{setuppaper}{stelpapierin}
+\setinterfacecommand{setuppapersize}{stelpapierformaatin}
+\setinterfacecommand{setupparagraphnumbering}{stelparagraafnummerenin}
+\setinterfacecommand{setupparagraphs}{stelalineasin}
+\setinterfacecommand{setupplacement}{stelplaatsin}
+\setinterfacecommand{setuppositioning}{stelpositionerenin}
+\setinterfacecommand{setupprofiles}{stelprofielenin}
+\setinterfacecommand{setupprograms}{stelprogrammasin}
+\setinterfacecommand{setuppublications}{stelpublicatiesin}
+\setinterfacecommand{setupquote}{stelciterenin}
+\setinterfacecommand{setupreferencelist}{stelreferentielijstin}
+\setinterfacecommand{setupreferencing}{stelrefererenin}
+\setinterfacecommand{setupregister}{stelregisterin}
+\setinterfacecommand{setuprotate}{stelroterenin}
+\setinterfacecommand{setuprule}{stellijnin}
+\setinterfacecommand{setups}{instellingen}
+\setinterfacecommand{setupscreens}{stelrastersin}
+\setinterfacecommand{setupsection}{stelsectiein}
+\setinterfacecommand{setupsectionblock}{stelsectieblokin}
+\setinterfacecommand{setupsorting}{stelsorterenin}
+\setinterfacecommand{setupspacing}{stelspatieringin}
+\setinterfacecommand{setupstartstop}{stelstartstopin}
+\setinterfacecommand{setupstrut}{stelstrutin}
+\setinterfacecommand{setupsubpagenumber}{stelsubpaginanummerin}
+\setinterfacecommand{setupsymbolset}{stelsymboolsetin}
+\setinterfacecommand{setupsynchronization}{stelsynchronisatiein}
+\setinterfacecommand{setupsynchronizationbar}{stelsynchronisatiebalkin}
+\setinterfacecommand{setupsynonyms}{stelsynoniemenin}
+\setinterfacecommand{setupsystem}{stelsysteemin}
+\setinterfacecommand{setuptab}{steltabin}
+\setinterfacecommand{setuptables}{steltabellenin}
+\setinterfacecommand{setuptabulate}{steltabulatiein}
+\setinterfacecommand{setuptext}{steltekstin}
+\setinterfacecommand{setuptextposition}{steltekstpositiein}
+\setinterfacecommand{setuptextrules}{steltekstlijnenin}
+\setinterfacecommand{setuptexttexts}{stelteksttekstenin}
+\setinterfacecommand{setuptextvariable}{steltekstvariabelein}
+\setinterfacecommand{setupthinrules}{steldunnelijnenin}
+\setinterfacecommand{setuptolerance}{steltolerantiein}
+\setinterfacecommand{setuptop}{stelbovenin}
+\setinterfacecommand{setuptoptexts}{stelboventekstenin}
+\setinterfacecommand{setuptype}{steltypein}
+\setinterfacecommand{setuptyping}{steltypenin}
+\setinterfacecommand{setupunderbar}{stelonderstrepenin}
+\setinterfacecommand{setupurl}{stelurlin}
+\setinterfacecommand{setupversions}{stelversiesin}
+\setinterfacecommand{setupwhitespace}{stelwitruimtein}
+\setinterfacecommand{showbodyfont}{toonkorps}
+\setinterfacecommand{showbodyfontenvironment}{toonkorpsomgeving}
+\setinterfacecommand{showcolor}{toonkleur}
+\setinterfacecommand{showcolorgroup}{toonkleurgroep}
+\setinterfacecommand{showexternalfigures}{toonexternefiguren}
+\setinterfacecommand{showfields}{toonvelden}
+\setinterfacecommand{showframe}{toonkader}
+\setinterfacecommand{showgrid}{toongrid}
+\setinterfacecommand{showlayout}{toonlayout}
+\setinterfacecommand{showmakeup}{toonopmaak}
+\setinterfacecommand{showpalet}{toonpalet}
+\setinterfacecommand{showprint}{toonprint}
+\setinterfacecommand{showsetups}{tooninstellingen}
+\setinterfacecommand{showstruts}{toonstruts}
+\setinterfacecommand{showsymbolset}{toonsymboolset}
+\setinterfacecommand{smallcapped}{kap}
+\setinterfacecommand{someline}{eenregel}
+\setinterfacecommand{somewhere}{ergens}
+\setinterfacecommand{space}{spatie}
+\setinterfacecommand{splitfloat}{splitsplaatsblok}
+\setinterfacecommand{startalignment}{startuitlijnen}
+\setinterfacecommand{startbackground}{startachtergrond}
+\setinterfacecommand{startcoding}{startcodering}
+\setinterfacecommand{startcolor}{startkleur}
+\setinterfacecommand{startcolumnmakeup}{startkolomopmaak}
+\setinterfacecommand{startcolumns}{startkolommen}
+\setinterfacecommand{startcolumnset}{startkolomgroep}
+\setinterfacecommand{startcombination}{startcombinatie}
+\setinterfacecommand{startcomponent}{startonderdeel}
+\setinterfacecommand{startdocument}{startdocument}
+\setinterfacecommand{startenvironment}{startomgeving}
+\setinterfacecommand{startfigure}{startfiguur}
+\setinterfacecommand{startglobal}{startglobaal}
+\setinterfacecommand{startline}{startregel}
+\setinterfacecommand{startlinecorrection}{startregelcorrectie}
+\setinterfacecommand{startlinenumbering}{startregelnummeren}
+\setinterfacecommand{startlines}{startregels}
+\setinterfacecommand{startlocal}{startlokaal}
+\setinterfacecommand{startlocalfootnotes}{startlokalevoetnoten}
+\setinterfacecommand{startmakeup}{startopmaak}
+\setinterfacecommand{startmarginblock}{startmargeblok}
+\setinterfacecommand{startmarginrule}{startkantlijn}
+\setinterfacecommand{startnarrower}{startsmaller}
+\setinterfacecommand{startopposite}{startnaast}
+\setinterfacecommand{startoverlay}{startoverlay}
+\setinterfacecommand{startoverzicht}{startoverzicht}
+\setinterfacecommand{startpacked}{startopelkaar}
+\setinterfacecommand{startpositioning}{startpositioneren}
+\setinterfacecommand{startproduct}{startprodukt}
+\setinterfacecommand{startprofile}{startprofiel}
+\setinterfacecommand{startproject}{startprojekt}
+\setinterfacecommand{startquotation}{startcitaat}
+\setinterfacecommand{startraster}{startraster}
+\setinterfacecommand{startsymbolset}{startsymboolset}
+\setinterfacecommand{startsynchronization}{startsynchronisatie}
+\setinterfacecommand{starttable}{starttabel}
+\setinterfacecommand{starttables}{starttabellen}
+\setinterfacecommand{starttext}{starttekst}
+\setinterfacecommand{starttextrule}{starttekstlijn}
+\setinterfacecommand{startunpacked}{startvanelkaar}
+\setinterfacecommand{startversion}{startversie}
+\setinterfacecommand{stopalignment}{stopuitlijnen}
+\setinterfacecommand{stopbackground}{stopachtergrond}
+\setinterfacecommand{stopcoding}{stopcodering}
+\setinterfacecommand{stopcolor}{stopkleur}
+\setinterfacecommand{stopcolumnmakeup}{stopkolomopmaak}
+\setinterfacecommand{stopcolumns}{stopkolommen}
+\setinterfacecommand{stopcolumnset}{stopkolomgroep}
+\setinterfacecommand{stopcombination}{stopcombinatie}
+\setinterfacecommand{stopcomponent}{stoponderdeel}
+\setinterfacecommand{stopdocument}{stopdocument}
+\setinterfacecommand{stopenvironment}{stopomgeving}
+\setinterfacecommand{stopglobal}{stopglobaal}
+\setinterfacecommand{stopline}{stopregel}
+\setinterfacecommand{stoplinecorrection}{stopregelcorrectie}
+\setinterfacecommand{stoplinenumbering}{stopregelnummeren}
+\setinterfacecommand{stoplines}{stopregels}
+\setinterfacecommand{stoplocal}{stoplokaal}
+\setinterfacecommand{stoplocalfootnotes}{stoplokalevoetnoten}
+\setinterfacecommand{stopmakeup}{stopopmaak}
+\setinterfacecommand{stopmarginblock}{stopmargeblok}
+\setinterfacecommand{stopmarginrule}{stopkantlijn}
+\setinterfacecommand{stopnarrower}{stopsmaller}
+\setinterfacecommand{stopopposite}{stopnaast}
+\setinterfacecommand{stopoverlay}{stopoverlay}
+\setinterfacecommand{stopoverzicht}{stopoverzicht}
+\setinterfacecommand{stoppacked}{stopopelkaar}
+\setinterfacecommand{stoppositioning}{stoppositioneren}
+\setinterfacecommand{stopproduct}{stopprodukt}
+\setinterfacecommand{stopprofile}{stopprofiel}
+\setinterfacecommand{stopproject}{stopprojekt}
+\setinterfacecommand{stopquotation}{stopcitaat}
+\setinterfacecommand{stopraster}{stopraster}
+\setinterfacecommand{stopsynchronization}{stopsynchronisatie}
+\setinterfacecommand{stoptable}{stoptabel}
+\setinterfacecommand{stoptables}{stoptabellen}
+\setinterfacecommand{stoptext}{stoptekst}
+\setinterfacecommand{stoptextrule}{stoptekstlijn}
+\setinterfacecommand{stopunpacked}{stopvanelkaar}
+\setinterfacecommand{stopversion}{stopversie}
+\setinterfacecommand{stretched}{uitgerekt}
+\setinterfacecommand{subformulanumber}{subformulenummer}
+\setinterfacecommand{subpagenumber}{subpaginanummer}
+\setinterfacecommand{switchtobodyfont}{switchnaarkorps}
+\setinterfacecommand{switchtorawfont}{switchtorawfont}
+\setinterfacecommand{sym}{sym}
+\setinterfacecommand{symbol}{symbool}
+\setinterfacecommand{synchronizationbar}{synchronisatiebalk}
+\setinterfacecommand{synchronize}{synchroniseer}
+\setinterfacecommand{tab}{tab}
+\setinterfacecommand{testcolumn}{testkolom}
+\setinterfacecommand{testpage}{testpagina}
+\setinterfacecommand{tex}{tex}
+\setinterfacecommand{textheight}{teksthoogte}
+\setinterfacecommand{textreference}{tekstreferentie}
+\setinterfacecommand{textrule}{tekstlijn}
+\setinterfacecommand{textvariable}{tekstvariabele}
+\setinterfacecommand{textwidth}{tekstbreedte}
+\setinterfacecommand{thinrule}{dunnelijn}
+\setinterfacecommand{thinrules}{dunnelijnen}
+\setinterfacecommand{tooltip}{suggestie}
+\setinterfacecommand{topdistance}{bovenafstand}
+\setinterfacecommand{topheight}{bovenhoogte}
+\setinterfacecommand{topspace}{kopwit}
+\setinterfacecommand{totalnumberofpages}{totaalaantalpaginas}
+\setinterfacecommand{translate}{vertaal}
+\setinterfacecommand{txt}{txt}
+\setinterfacecommand{typ}{typ}
+\setinterfacecommand{type}{type}
+\setinterfacecommand{typebuffer}{typebuffer}
+\setinterfacecommand{typefile}{typefile}
+\setinterfacecommand{unitmeaning}{betekenis}
+\setinterfacecommand{unknown}{onbekend}
+\setinterfacecommand{useJSscripts}{gebruikJSscripts}
+\setinterfacecommand{useURL}{gebruikURL}
+\setinterfacecommand{useXMLfilter}{gebruikXMLfilter}
+\setinterfacecommand{useblocks}{gebruikblokken}
+\setinterfacecommand{usecommands}{gebruikcommandos}
+\setinterfacecommand{useencoding}{usecodering}
+\setinterfacecommand{useexternaldocument}{gebruikexterndocument}
+\setinterfacecommand{useexternalfigure}{gebruikexternfiguur}
+\setinterfacecommand{useexternalfile}{gebruikexternefile}
+\setinterfacecommand{useexternalfiles}{gebruikexternefiles}
+\setinterfacecommand{useexternalsoundtrack}{gebruikexterngeluidsfragment}
+\setinterfacecommand{usemodule}{gebruikmodule}
+\setinterfacecommand{usemodules}{gebruikmodules}
+\setinterfacecommand{usepath}{gebruikgebied}
+\setinterfacecommand{usereferences}{gebruikreferenties}
+\setinterfacecommand{usespecials}{gebruikspecials}
+\setinterfacecommand{usesymbols}{gebruiksymbolen}
+\setinterfacecommand{usetypescript}{gebruiktypescript}
+\setinterfacecommand{usetypescriptfile}{gebruiktypescriptfile}
+\setinterfacecommand{useurl}{gebruikurl}
+\setinterfacecommand{version}{versie}
+\setinterfacecommand{vl}{vl}
+\setinterfacecommand{weekday}{weekdag}
+\setinterfacecommand{whitespace}{witruimte}
+\setinterfacecommand{wordright}{woordrechts}
+\setinterfacecommand{writebetweenlist}{schrijftussenlijst}
+\setinterfacecommand{writetolist}{schrijfnaarlijst}
+\setinterfacecommand{writetoreferencelist}{schrijfnaarreferentielijst}
+\setinterfacecommand{writetoregister}{schrijfnaarregister}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-ro.tex b/tex/context/base/mult-ro.tex
new file mode 100644
index 000000000..738e49f72
--- /dev/null
+++ b/tex/context/base/mult-ro.tex
@@ -0,0 +1,1693 @@
+% this file is auto-generated, don't edit this file
+%
+% definitions for interface variables for language ro
+%
+\setinterfacevariable{Addition}{Adaugare}
+\setinterfacevariable{Balloon}{Balon}
+\setinterfacevariable{Character}{Caracter}
+\setinterfacevariable{Characters}{Caractere}
+\setinterfacevariable{CloseDocument}{InchideDocument}
+\setinterfacevariable{ExitViewer}{IesireVizualizator}
+\setinterfacevariable{FirstPage}{PrimaPagina}
+\setinterfacevariable{FitHeight}{AjustatInaltime}
+\setinterfacevariable{FitWidth}{AjustatLatime}
+\setinterfacevariable{GotoPage}{LaPagina}
+\setinterfacevariable{Greek}{Grec}
+\setinterfacevariable{Help}{Ajutor}
+\setinterfacevariable{HideField}{AscundeCamp}
+\setinterfacevariable{HideLayer}{HideLayer}
+\setinterfacevariable{Key}{Cheie}
+\setinterfacevariable{LastPage}{UltimaPagina}
+\setinterfacevariable{LoadForm}{IncarcaFormular}
+\setinterfacevariable{MONTH}{LUNA}
+\setinterfacevariable{New}{Nou}
+\setinterfacevariable{NextJump}{SaltUrmator}
+\setinterfacevariable{NextPage}{PaginaUrmatoare}
+\setinterfacevariable{Numbers}{Numere}
+\setinterfacevariable{OpenNamedDocument}{OpenNamedDocument}
+\setinterfacevariable{Paragraph}{Paragraf}
+\setinterfacevariable{PauseMovie}{PauzaFilm}
+\setinterfacevariable{PauseRendering}{PauseRendering}
+\setinterfacevariable{PauseSound}{PauzaSunet}
+\setinterfacevariable{PreviousJump}{SaltPrecedent}
+\setinterfacevariable{PreviousPage}{PaginaPrecedenta}
+\setinterfacevariable{PrintDocument}{TiparesteDocument}
+\setinterfacevariable{Query}{Query}
+\setinterfacevariable{QueryAgain}{QueryAgain}
+\setinterfacevariable{ResetForm}{ResetareFormular}
+\setinterfacevariable{ResumeMovie}{RepornesteFilm}
+\setinterfacevariable{ResumeRendering}{ResumeRendering}
+\setinterfacevariable{ResumeSound}{RepornesteSunet}
+\setinterfacevariable{Romannumerals}{Numereromane}
+\setinterfacevariable{SaveDocument}{SalvareDocument}
+\setinterfacevariable{SaveForm}{SalveazaFormular}
+\setinterfacevariable{SaveNamedDocument}{SaveNamedDocument}
+\setinterfacevariable{SearchAgain}{CautaDinNou}
+\setinterfacevariable{SearchDocument}{CautaDocument}
+\setinterfacevariable{ShowBookmarks}{ShowBookmarks}
+\setinterfacevariable{ShowField}{AfiseazaCamp}
+\setinterfacevariable{ShowThumbs}{ShowThumbs}
+\setinterfacevariable{StartMovie}{StartFilm}
+\setinterfacevariable{StartRendering}{StartRendering}
+\setinterfacevariable{StartSound}{StartSunet}
+\setinterfacevariable{StopMovie}{StopFilm}
+\setinterfacevariable{StopRendering}{StopRendering}
+\setinterfacevariable{StopSound}{StopSunet}
+\setinterfacevariable{SubmitForm}{TrimiteFormular}
+\setinterfacevariable{ToggleLayer}{ToggleLayer}
+\setinterfacevariable{ToggleViewer}{SchimbaVizualizator}
+\setinterfacevariable{URL}{URL}
+\setinterfacevariable{VideLayer}{VideLayer}
+\setinterfacevariable{ViewerHelp}{AjutorVizualizator}
+\setinterfacevariable{WEEKDAY}{ZISAPTAMANA}
+\setinterfacevariable{WORD}{CUVANT}
+\setinterfacevariable{abbreviation}{abreviere}
+\setinterfacevariable{abbreviations}{abrevieri}
+\setinterfacevariable{absolute}{absolut}
+\setinterfacevariable{action}{actiune}
+\setinterfacevariable{after}{dupa}
+\setinterfacevariable{all}{tot}
+\setinterfacevariable{always}{totdeauna}
+\setinterfacevariable{answerarea}{answerarea}
+\setinterfacevariable{appendices}{apendixuri}
+\setinterfacevariable{appendix}{apendix}
+\setinterfacevariable{april}{aprilie}
+\setinterfacevariable{atmargin}{lamargine}
+\setinterfacevariable{atpage}{lapagina}
+\setinterfacevariable{august}{august}
+\setinterfacevariable{author}{autor}
+\setinterfacevariable{auto}{auto}
+\setinterfacevariable{autointro}{autointro}
+\setinterfacevariable{back}{inapot}
+\setinterfacevariable{background}{fundal}
+\setinterfacevariable{backmatter}{epilogul}
+\setinterfacevariable{backpart}{epilog}
+\setinterfacevariable{backspace}{spatiuspate}
+\setinterfacevariable{backward}{inapoi}
+\setinterfacevariable{bbl}{bbl}
+\setinterfacevariable{before}{inainte}
+\setinterfacevariable{begin}{begin}
+\setinterfacevariable{bib}{bib}
+\setinterfacevariable{big}{mare}
+\setinterfacevariable{bigbodyfont}{bigbodyfont}
+\setinterfacevariable{bigpreference}{preferintamare}
+\setinterfacevariable{blank}{blank}
+\setinterfacevariable{blockquote}{blockquote}
+\setinterfacevariable{bodymatter}{principalul}
+\setinterfacevariable{bodypart}{principal}
+\setinterfacevariable{bold}{aldin}
+\setinterfacevariable{bolditalic}{aldinitalic}
+\setinterfacevariable{boldslanted}{aldininclinat}
+\setinterfacevariable{bookmark}{semncarte}
+\setinterfacevariable{both}{ambele}
+\setinterfacevariable{bottom}{subsol}
+\setinterfacevariable{brief}{brief}
+\setinterfacevariable{broad}{broad}
+\setinterfacevariable{buffer}{buffer}
+\setinterfacevariable{by}{de}
+\setinterfacevariable{calligraphic}{caligrafic}
+\setinterfacevariable{cap}{cap}
+\setinterfacevariable{capital}{majuscula}
+\setinterfacevariable{center}{center}
+\setinterfacevariable{chapter}{capitol}
+\setinterfacevariable{character}{caracter}
+\setinterfacevariable{characters}{caractere}
+\setinterfacevariable{cite}{cite}
+\setinterfacevariable{color}{culoare}
+\setinterfacevariable{column}{coloana}
+\setinterfacevariable{columns}{coloane}
+\setinterfacevariable{command}{comanda}
+\setinterfacevariable{commands}{comenzi}
+\setinterfacevariable{comment}{comentariu}
+\setinterfacevariable{component}{componenta}
+\setinterfacevariable{concept}{concept}
+\setinterfacevariable{content}{cuprins}
+\setinterfacevariable{contents}{cuprinsuri}
+\setinterfacevariable{continue}{continuu}
+\setinterfacevariable{controls}{controale}
+\setinterfacevariable{conversion}{conversie}
+\setinterfacevariable{current}{curent}
+\setinterfacevariable{cutspace}{cutspace}
+\setinterfacevariable{date}{data}
+\setinterfacevariable{day}{zi}
+\setinterfacevariable{december}{decembrie}
+\setinterfacevariable{default}{implicit}
+\setinterfacevariable{depth}{adancime}
+\setinterfacevariable{description}{descriere}
+\setinterfacevariable{disable}{dezactivat}
+\setinterfacevariable{display}{display}
+\setinterfacevariable{dot}{punct}
+\setinterfacevariable{doublesided}{douafete}
+\setinterfacevariable{down}{down}
+\setinterfacevariable{each}{fiecare}
+\setinterfacevariable{edge}{bordura}
+\setinterfacevariable{empty}{gol}
+\setinterfacevariable{end}{end}
+\setinterfacevariable{endnote}{endnote}
+\setinterfacevariable{enumeration}{enumerare}
+\setinterfacevariable{environment}{mediu}
+\setinterfacevariable{even}{par}
+\setinterfacevariable{external}{extern}
+\setinterfacevariable{fact}{fapt}
+\setinterfacevariable{february}{februarie}
+\setinterfacevariable{figure}{figura}
+\setinterfacevariable{figures}{figure}
+\setinterfacevariable{file}{fisier}
+\setinterfacevariable{final}{final}
+\setinterfacevariable{first}{primul}
+\setinterfacevariable{firstcolumn}{firstcolumn}
+\setinterfacevariable{firstpage}{primapagina}
+\setinterfacevariable{firstsubpage}{primasubpagina}
+\setinterfacevariable{fit}{ajustat}
+\setinterfacevariable{five}{cinci}
+\setinterfacevariable{fix}{fix}
+\setinterfacevariable{fixed}{fixat}
+\setinterfacevariable{flexible}{flexibil}
+\setinterfacevariable{float}{obiectmobil}
+\setinterfacevariable{flushinner}{flushinner}
+\setinterfacevariable{flushleft}{flushleft}
+\setinterfacevariable{flushouter}{flushouter}
+\setinterfacevariable{flushright}{flushright}
+\setinterfacevariable{footer}{subsol}
+\setinterfacevariable{footnote}{notasubsol}
+\setinterfacevariable{force}{fortat}
+\setinterfacevariable{foreground}{primplan}
+\setinterfacevariable{formeel}{formeel}
+\setinterfacevariable{formula}{formula}
+\setinterfacevariable{formulae}{formule}
+\setinterfacevariable{forward}{avans}
+\setinterfacevariable{four}{patru}
+\setinterfacevariable{frame}{incadrat}
+\setinterfacevariable{framedtext}{textinconjurat}
+\setinterfacevariable{friday}{vineri}
+\setinterfacevariable{frontmatter}{prologul}
+\setinterfacevariable{frontpart}{prolog}
+\setinterfacevariable{global}{global}
+\setinterfacevariable{graphic}{graficul}
+\setinterfacevariable{graphics}{graficele}
+\setinterfacevariable{gray}{gri}
+\setinterfacevariable{greek}{grec}
+\setinterfacevariable{grid}{grila}
+\setinterfacevariable{halfline}{jumatatelinie}
+\setinterfacevariable{handwritten}{scrismanual}
+\setinterfacevariable{hang}{suspenda}
+\setinterfacevariable{hanging}{suspendat}
+\setinterfacevariable{head}{antet}
+\setinterfacevariable{header}{antet}
+\setinterfacevariable{height}{inaltime}
+\setinterfacevariable{helptext}{textajutator}
+\setinterfacevariable{hencefore}{precedent}
+\setinterfacevariable{here}{aici}
+\setinterfacevariable{hereafter}{urmator}
+\setinterfacevariable{hidden}{ascuns}
+\setinterfacevariable{hiding}{ascundere}
+\setinterfacevariable{high}{inalt}
+\setinterfacevariable{horizontal}{orizontal}
+\setinterfacevariable{hyphenated}{despsilabe}
+\setinterfacevariable{hz}{hz}
+\setinterfacevariable{inbetween}{intre}
+\setinterfacevariable{index}{index}
+\setinterfacevariable{indices}{indexuri}
+\setinterfacevariable{informeel}{informeel}
+\setinterfacevariable{inherit}{inherit}
+\setinterfacevariable{inleft}{instanga}
+\setinterfacevariable{inmargin}{inmargine}
+\setinterfacevariable{inner}{intern}
+\setinterfacevariable{inneredge}{inneredge}
+\setinterfacevariable{innermargin}{innermargin}
+\setinterfacevariable{inright}{indreapta}
+\setinterfacevariable{interaction}{interactiune}
+\setinterfacevariable{interactionmenu}{meniuinteractiune}
+\setinterfacevariable{intermezzi}{intermezzi}
+\setinterfacevariable{intermezzo}{intermezzo}
+\setinterfacevariable{intext}{intext}
+\setinterfacevariable{intro}{intro}
+\setinterfacevariable{italic}{italic}
+\setinterfacevariable{italicbold}{italicaldin}
+\setinterfacevariable{item}{element}
+\setinterfacevariable{itemize}{enumerare}
+\setinterfacevariable{its}{propriu}
+\setinterfacevariable{january}{ianuarie}
+\setinterfacevariable{joinedup}{unit}
+\setinterfacevariable{july}{iulie}
+\setinterfacevariable{june}{iunie}
+\setinterfacevariable{keep}{mentine}
+\setinterfacevariable{knockout}{knockout}
+\setinterfacevariable{label}{eticheta}
+\setinterfacevariable{landscape}{vedere}
+\setinterfacevariable{last}{ultim}
+\setinterfacevariable{lastcolumn}{lastcolumn}
+\setinterfacevariable{lastpage}{ultimapagina}
+\setinterfacevariable{lastpagenumber}{lastpagenumber}
+\setinterfacevariable{lastsubpage}{ultimasubpagina}
+\setinterfacevariable{layer}{layer}
+\setinterfacevariable{left}{stanga}
+\setinterfacevariable{leftedge}{bordurastanga}
+\setinterfacevariable{lefthanging}{lefthanging}
+\setinterfacevariable{leftmargin}{marginestanga}
+\setinterfacevariable{leftpage}{paginastanga}
+\setinterfacevariable{lefttoright}{lefttoright}
+\setinterfacevariable{legend}{legenda}
+\setinterfacevariable{lesshyphenation}{lesshyphenation}
+\setinterfacevariable{line}{linie}
+\setinterfacevariable{linenote}{linenote}
+\setinterfacevariable{lines}{linii}
+\setinterfacevariable{list}{lista}
+\setinterfacevariable{local}{local}
+\setinterfacevariable{localenvironment}{mediulocal}
+\setinterfacevariable{logo}{logo}
+\setinterfacevariable{logos}{logos}
+\setinterfacevariable{lohi}{lohi}
+\setinterfacevariable{loose}{larg}
+\setinterfacevariable{low}{jos}
+\setinterfacevariable{ls}{ls}
+\setinterfacevariable{makeup}{marcaj}
+\setinterfacevariable{mar}{mar}
+\setinterfacevariable{march}{martie}
+\setinterfacevariable{margin}{margine}
+\setinterfacevariable{marginedge}{marginebordura}
+\setinterfacevariable{margintitle}{titlumarginal}
+\setinterfacevariable{marking}{marcaje}
+\setinterfacevariable{mathalignment}{mathalignment}
+\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathmatrix}{mathmatrix}
+\setinterfacevariable{max}{max}
+\setinterfacevariable{maxdepth}{maxdepth}
+\setinterfacevariable{maxheight}{maxheight}
+\setinterfacevariable{maxwidth}{maxwidth}
+\setinterfacevariable{may}{mai}
+\setinterfacevariable{mediaeval}{medieval}
+\setinterfacevariable{medium}{mediu}
+\setinterfacevariable{middle}{centru}
+\setinterfacevariable{min}{min}
+\setinterfacevariable{mindepth}{mindepth}
+\setinterfacevariable{minheight}{inaltimeminima}
+\setinterfacevariable{minwidth}{latimeminima}
+\setinterfacevariable{mirrored}{oglindit}
+\setinterfacevariable{monday}{luni}
+\setinterfacevariable{mono}{mono}
+\setinterfacevariable{month}{luna}
+\setinterfacevariable{morehyphenation}{morehyphenation}
+\setinterfacevariable{name}{nume}
+\setinterfacevariable{narrow}{ingust}
+\setinterfacevariable{negative}{negativ}
+\setinterfacevariable{never}{niciodata}
+\setinterfacevariable{new}{nou}
+\setinterfacevariable{next}{urmatorul}
+\setinterfacevariable{nextevenpage}{paginaparaurmatoarea}
+\setinterfacevariable{nextoddpage}{paginaimparaurmatoarea}
+\setinterfacevariable{nextpage}{paginaurmatoare}
+\setinterfacevariable{nextsubpage}{urmatoareasubpagina}
+\setinterfacevariable{no}{nu}
+\setinterfacevariable{nocheck}{nocheck}
+\setinterfacevariable{nofit}{nofit}
+\setinterfacevariable{nogrid}{nogrid}
+\setinterfacevariable{nohz}{nohz}
+\setinterfacevariable{nomarking}{faramarcare}
+\setinterfacevariable{none}{niciunul}
+\setinterfacevariable{nonumber}{nonumber}
+\setinterfacevariable{normal}{normal}
+\setinterfacevariable{nospacing}{nospacing}
+\setinterfacevariable{not}{nu}
+\setinterfacevariable{note}{note}
+\setinterfacevariable{nothanging}{nothanging}
+\setinterfacevariable{nothyphenated}{nedespsilabe}
+\setinterfacevariable{november}{noiembrie}
+\setinterfacevariable{nowhere}{niciunde}
+\setinterfacevariable{nowhite}{faraalb}
+\setinterfacevariable{number}{numar}
+\setinterfacevariable{numbers}{numere}
+\setinterfacevariable{october}{octombrie}
+\setinterfacevariable{odd}{impar}
+\setinterfacevariable{off}{dezactivat}
+\setinterfacevariable{offset}{offset}
+\setinterfacevariable{old}{old}
+\setinterfacevariable{on}{on}
+\setinterfacevariable{one}{unu}
+\setinterfacevariable{opposite}{opus}
+\setinterfacevariable{outer}{extern}
+\setinterfacevariable{outeredge}{outeredge}
+\setinterfacevariable{outermargin}{outermargin}
+\setinterfacevariable{overbar}{barasus}
+\setinterfacevariable{overbars}{supralinie}
+\setinterfacevariable{overlay}{overlay}
+\setinterfacevariable{overprint}{overprint}
+\setinterfacevariable{overstrike}{liniepeste}
+\setinterfacevariable{overstrikes}{liniipeste}
+\setinterfacevariable{packed}{impachetat}
+\setinterfacevariable{page}{pagina}
+\setinterfacevariable{pagecomment}{comentariupagina}
+\setinterfacevariable{pagenumber}{numarpagina}
+\setinterfacevariable{paper}{foaie}
+\setinterfacevariable{paragraph}{paragraf}
+\setinterfacevariable{part}{parte}
+\setinterfacevariable{positive}{positiv}
+\setinterfacevariable{postponing}{postponing}
+\setinterfacevariable{postscript}{postscript}
+\setinterfacevariable{preference}{preferinta}
+\setinterfacevariable{preview}{previzualizare}
+\setinterfacevariable{previous}{precedent}
+\setinterfacevariable{previousevenpage}{paginaparaprecedenta}
+\setinterfacevariable{previousoddpage}{paginaimparaprecedenta}
+\setinterfacevariable{previouspage}{paginaanterioara}
+\setinterfacevariable{previoussubpage}{subpaginaanterioara}
+\setinterfacevariable{printable}{tiparibil}
+\setinterfacevariable{process}{process}
+\setinterfacevariable{product}{produs}
+\setinterfacevariable{program}{program}
+\setinterfacevariable{project}{proiect}
+\setinterfacevariable{protected}{protejat}
+\setinterfacevariable{quadruple}{cvadrupul}
+\setinterfacevariable{quotation}{citat}
+\setinterfacevariable{quote}{minicitat}
+\setinterfacevariable{ran}{rulat}
+\setinterfacevariable{random}{aleator}
+\setinterfacevariable{readonly}{readonly}
+\setinterfacevariable{rectangular}{rectangular}
+\setinterfacevariable{referral}{referinta}
+\setinterfacevariable{register}{registru}
+\setinterfacevariable{regular}{regular}
+\setinterfacevariable{rekening}{rekening}
+\setinterfacevariable{relative}{relativ}
+\setinterfacevariable{repeat}{repetat}
+\setinterfacevariable{required}{obligatoriu}
+\setinterfacevariable{reset}{reset}
+\setinterfacevariable{reverse}{reverse}
+\setinterfacevariable{right}{dreapta}
+\setinterfacevariable{rightedge}{borduradreapta}
+\setinterfacevariable{righthanging}{righthanging}
+\setinterfacevariable{rightmargin}{marginedreapta}
+\setinterfacevariable{rightpage}{paginadreapta}
+\setinterfacevariable{righttoleft}{righttoleft}
+\setinterfacevariable{roman}{roman}
+\setinterfacevariable{romannumerals}{numereromane}
+\setinterfacevariable{rotate}{rotit}
+\setinterfacevariable{rotated}{rotat}
+\setinterfacevariable{round}{rotund}
+\setinterfacevariable{row}{rand}
+\setinterfacevariable{rule}{rigla}
+\setinterfacevariable{samepage}{aceeasipagina}
+\setinterfacevariable{sans}{sans}
+\setinterfacevariable{sansbold}{sansaldin}
+\setinterfacevariable{sansserif}{sansserif}
+\setinterfacevariable{saturday}{sambata}
+\setinterfacevariable{screen}{ecran}
+\setinterfacevariable{section}{sectiune}
+\setinterfacevariable{sectionblockenvironment}{blocsectiuneambient}
+\setinterfacevariable{sectionnumber}{numarsetiune}
+\setinterfacevariable{see}{vezi}
+\setinterfacevariable{september}{septembrie}
+\setinterfacevariable{serif}{serif}
+\setinterfacevariable{serried}{serried}
+\setinterfacevariable{setups}{setari}
+\setinterfacevariable{sheet}{sheet}
+\setinterfacevariable{short}{short}
+\setinterfacevariable{singlesided}{ofata}
+\setinterfacevariable{slanted}{inclinat}
+\setinterfacevariable{slantedbold}{inclinataldin}
+\setinterfacevariable{small}{mic}
+\setinterfacevariable{smallbodyfont}{smallbodyfont}
+\setinterfacevariable{smallbold}{micaldin}
+\setinterfacevariable{smallbolditalic}{micaldininclinat}
+\setinterfacevariable{smallboldslanted}{micaldininclinat}
+\setinterfacevariable{smallcaps}{majusculemici}
+\setinterfacevariable{smallitalic}{micitalic}
+\setinterfacevariable{smallitalicbold}{micitalicaldin}
+\setinterfacevariable{smallnormal}{micnormal}
+\setinterfacevariable{smallslanted}{micinclinat}
+\setinterfacevariable{smallslantedbold}{micinclinataldin}
+\setinterfacevariable{smalltype}{mictype}
+\setinterfacevariable{somewhere}{undeva}
+\setinterfacevariable{sorted}{sortat}
+\setinterfacevariable{space}{spatiu}
+\setinterfacevariable{spacing}{spatiere}
+\setinterfacevariable{speech}{speech}
+\setinterfacevariable{split}{split}
+\setinterfacevariable{spot}{spot}
+\setinterfacevariable{standard}{standard}
+\setinterfacevariable{start}{start}
+\setinterfacevariable{starter}{starter}
+\setinterfacevariable{sticker}{sticker}
+\setinterfacevariable{stop}{stop}
+\setinterfacevariable{stopper}{stopper}
+\setinterfacevariable{stretch}{dilatat}
+\setinterfacevariable{strict}{strict}
+\setinterfacevariable{strong}{strong}
+\setinterfacevariable{strut}{strut}
+\setinterfacevariable{sub}{sub}
+\setinterfacevariable{subbackward}{subinapoi}
+\setinterfacevariable{subformula}{subformula}
+\setinterfacevariable{subforward}{subavans}
+\setinterfacevariable{subject}{subiect}
+\setinterfacevariable{subpage}{subpagina}
+\setinterfacevariable{subsection}{subsectiune}
+\setinterfacevariable{subsubject}{subsubiect}
+\setinterfacevariable{subsubsection}{subsubsectiune}
+\setinterfacevariable{subsubsubject}{subsubsubiect}
+\setinterfacevariable{subsubsubsection}{subsubsubsectiune}
+\setinterfacevariable{subsubsubsubject}{subsubsubsubiect}
+\setinterfacevariable{subsubsubsubsection}{subsubsubsubsectiune}
+\setinterfacevariable{subsubsubsubsubject}{subsubsubsubsubiect}
+\setinterfacevariable{subsubsubsubsubsection}{subsubsubsubsubsectiune}
+\setinterfacevariable{subsubsubsubsubsubject}{subsubsubsubsubsubiect}
+\setinterfacevariable{subsubsubsubsubsubsection}{subsubsubsubsubsubsectiune}
+\setinterfacevariable{subsubsubsubsubsubsubject}{subsubsubsubsubsubsubiect}
+\setinterfacevariable{subsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsectiune}
+\setinterfacevariable{subsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubiect}
+\setinterfacevariable{subsubsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsubsectiune}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubsubiect}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsection}{subsubsubsubsubsubsubsubsubsectiune}
+\setinterfacevariable{subsubsubsubsubsubsubsubsubsubject}{subsubsubsubsubsubsubsubsubsubiect}
+\setinterfacevariable{sunday}{duminica}
+\setinterfacevariable{support}{suport}
+\setinterfacevariable{sym}{sym}
+\setinterfacevariable{symbol}{simbol}
+\setinterfacevariable{synchronize}{synchronize}
+\setinterfacevariable{system}{sistem}
+\setinterfacevariable{table}{tabelul}
+\setinterfacevariable{tablehead}{antettabel}
+\setinterfacevariable{tables}{tabelele}
+\setinterfacevariable{tabletail}{subsoltabel}
+\setinterfacevariable{tabulate}{tabulate}
+\setinterfacevariable{tabulatehead}{tabulatehead}
+\setinterfacevariable{tabulatetail}{tabulatetail}
+\setinterfacevariable{tall}{inalt}
+\setinterfacevariable{teletype}{teletype}
+\setinterfacevariable{temporary}{temporar}
+\setinterfacevariable{test}{test}
+\setinterfacevariable{text}{text}
+\setinterfacevariable{three}{trei}
+\setinterfacevariable{thursday}{joi}
+\setinterfacevariable{title}{titlu}
+\setinterfacevariable{toggle}{toggle}
+\setinterfacevariable{tolerant}{tolerant}
+\setinterfacevariable{top}{sus}
+\setinterfacevariable{tuesday}{marti}
+\setinterfacevariable{two}{doi}
+\setinterfacevariable{txt}{txt}
+\setinterfacevariable{type}{type}
+\setinterfacevariable{typing}{typing}
+\setinterfacevariable{unavailable}{nedisponibil}
+\setinterfacevariable{underbar}{sublinie}
+\setinterfacevariable{underbars}{sublinii}
+\setinterfacevariable{unit}{unitate}
+\setinterfacevariable{units}{unitati}
+\setinterfacevariable{unknown}{necunoscut}
+\setinterfacevariable{unpacked}{despachetat}
+\setinterfacevariable{up}{up}
+\setinterfacevariable{url}{url}
+\setinterfacevariable{used}{folosit}
+\setinterfacevariable{value}{valoare}
+\setinterfacevariable{vertical}{vertical}
+\setinterfacevariable{very}{foarte}
+\setinterfacevariable{verystrict}{foartestrict}
+\setinterfacevariable{verytolerant}{foartetolerant}
+\setinterfacevariable{weak}{weak}
+\setinterfacevariable{wednesday}{miercuri}
+\setinterfacevariable{week}{saptamana}
+\setinterfacevariable{weekday}{zisaptamana}
+\setinterfacevariable{white}{alb}
+\setinterfacevariable{wide}{larg}
+\setinterfacevariable{width}{latime}
+\setinterfacevariable{xml}{xml}
+\setinterfacevariable{year}{an}
+\setinterfacevariable{yes}{da}
+% definitions for interface constants for language ro
+%
+\setinterfaceconstant{action}{actiune}
+\setinterfaceconstant{address}{adresa}
+\setinterfaceconstant{after}{dupa}
+\setinterfaceconstant{afterhead}{dupatitlu}
+\setinterfaceconstant{afterkey}{dupatasta}
+\setinterfaceconstant{align}{aliniere}
+\setinterfaceconstant{aligncharacter}{aliniazacaracter}
+\setinterfaceconstant{alignmentcharacter}{alierecaracter}
+\setinterfaceconstant{alignsymbol}{alignsymbol}
+\setinterfaceconstant{aligntitle}{alinieretitlu}
+\setinterfaceconstant{alternative}{alternativ}
+\setinterfaceconstant{andtext}{andtext}
+\setinterfaceconstant{apa}{apa}
+\setinterfaceconstant{arrow}{sageata}
+\setinterfaceconstant{artauthor}{artauthor}
+\setinterfaceconstant{artauthoretaldisplay}{artauthoretaldisplay}
+\setinterfaceconstant{artauthoretallimit}{artauthoretallimit}
+\setinterfaceconstant{artauthoretaltext}{artauthoretaltext}
+\setinterfaceconstant{at}{la}
+\setinterfaceconstant{author}{autor}
+\setinterfaceconstant{authoretaldisplay}{authoretaldisplay}
+\setinterfaceconstant{authoretallimit}{authoretallimit}
+\setinterfaceconstant{authoretaltext}{authoretaltext}
+\setinterfaceconstant{auto}{auto}
+\setinterfaceconstant{autofile}{autofile}
+\setinterfaceconstant{autofocus}{autofocus}
+\setinterfaceconstant{autohang}{autohang}
+\setinterfaceconstant{autostrut}{autostrut}
+\setinterfaceconstant{autowidth}{autolatime}
+\setinterfaceconstant{axis}{axa}
+\setinterfaceconstant{background}{fundal}
+\setinterfaceconstant{backgroundcolor}{culoarefundal}
+\setinterfaceconstant{backgroundcorner}{coltfundal}
+\setinterfaceconstant{backgrounddepth}{adancimefundal}
+\setinterfaceconstant{backgroundoffset}{offsetfundal}
+\setinterfaceconstant{backgroundradius}{razafundal}
+\setinterfaceconstant{backgroundscreen}{ecranfundal}
+\setinterfaceconstant{backspace}{spatiuspate}
+\setinterfaceconstant{balance}{balanta}
+\setinterfaceconstant{before}{inainte}
+\setinterfaceconstant{beforehead}{inaintetitlu}
+\setinterfaceconstant{bet}{bet}
+\setinterfaceconstant{big}{mare}
+\setinterfaceconstant{blank}{blanc}
+\setinterfaceconstant{blockway}{blockway}
+\setinterfaceconstant{bodyfont}{fonttext}
+\setinterfaceconstant{bookmark}{semncarte}
+\setinterfaceconstant{bottom}{jos}
+\setinterfaceconstant{bottomafter}{bottomafter}
+\setinterfaceconstant{bottombefore}{bottombefore}
+\setinterfaceconstant{bottomdistance}{distantajos}
+\setinterfaceconstant{bottomframe}{framejos}
+\setinterfaceconstant{bottomoffset}{offsetjos}
+\setinterfaceconstant{bottomspace}{spatiujos}
+\setinterfaceconstant{bottomstate}{starejos}
+\setinterfaceconstant{cache}{cache}
+\setinterfaceconstant{calculate}{calculeaza}
+\setinterfaceconstant{ccommand}{comandac}
+\setinterfaceconstant{click}{click}
+\setinterfaceconstant{clickin}{clickintru}
+\setinterfaceconstant{clickout}{clickies}
+\setinterfaceconstant{clipoffset}{clipoffset}
+\setinterfaceconstant{closeaction}{actiuneinchidere}
+\setinterfaceconstant{closecommand}{closecommand}
+\setinterfaceconstant{closepageaction}{actiuneinchiderepagina}
+\setinterfaceconstant{closesymbol}{closesymbol}
+\setinterfaceconstant{color}{culoare}
+\setinterfaceconstant{column}{coloana}
+\setinterfaceconstant{columndistance}{distantacoloane}
+\setinterfaceconstant{columns}{coloane}
+\setinterfaceconstant{command}{comanda}
+\setinterfaceconstant{commandafter}{comandadupa}
+\setinterfaceconstant{commandbefore}{comandainainte}
+\setinterfaceconstant{commands}{comenzi}
+\setinterfaceconstant{component}{component}
+\setinterfaceconstant{compoundhyphen}{compoundhyphen}
+\setinterfaceconstant{compress}{compress}
+\setinterfaceconstant{connector}{connector}
+\setinterfaceconstant{continue}{continua}
+\setinterfaceconstant{contrastcolor}{culoarecontrast}
+\setinterfaceconstant{controls}{controale}
+\setinterfaceconstant{conversion}{conversie}
+\setinterfaceconstant{convertfile}{convertestefisier}
+\setinterfaceconstant{corner}{colt}
+\setinterfaceconstant{coupling}{cuplare}
+\setinterfaceconstant{couplingway}{modcuplare}
+\setinterfaceconstant{criterium}{criteriu}
+\setinterfaceconstant{current}{curent}
+\setinterfaceconstant{cutspace}{cutspace}
+\setinterfaceconstant{dash}{dash}
+\setinterfaceconstant{dat}{dat}
+\setinterfaceconstant{database}{database}
+\setinterfaceconstant{date}{data}
+\setinterfaceconstant{deepnumbercommand}{deepnumbercommand}
+\setinterfaceconstant{deeptextcommand}{deeptextcommand}
+\setinterfaceconstant{default}{implicit}
+\setinterfaceconstant{delay}{intarziere}
+\setinterfaceconstant{depth}{inaltime}
+\setinterfaceconstant{depthcorrection}{corectieadancime}
+\setinterfaceconstant{direction}{directie}
+\setinterfaceconstant{directory}{director}
+\setinterfaceconstant{display}{display}
+\setinterfaceconstant{distance}{distanta}
+\setinterfaceconstant{dot}{punct}
+\setinterfaceconstant{doublesided}{douafete}
+\setinterfaceconstant{dummy}{dummy}
+\setinterfaceconstant{dx}{dx}
+\setinterfaceconstant{dy}{dy}
+\setinterfaceconstant{edge}{bordura}
+\setinterfaceconstant{edgedistance}{distantabordura}
+\setinterfaceconstant{editor}{editor}
+\setinterfaceconstant{editoretaldisplay}{editoretaldisplay}
+\setinterfaceconstant{editoretallimit}{editoretallimit}
+\setinterfaceconstant{editoretaltext}{editoretaltext}
+\setinterfaceconstant{empty}{gol}
+\setinterfaceconstant{equalheight}{equalheight}
+\setinterfaceconstant{equalwidth}{equalwidth}
+\setinterfaceconstant{escape}{escape}
+\setinterfaceconstant{evenmargin}{marginepara}
+\setinterfaceconstant{expansion}{expansiune}
+\setinterfaceconstant{export}{export}
+\setinterfaceconstant{extras}{extras}
+\setinterfaceconstant{factor}{factor}
+\setinterfaceconstant{fallback}{fallback}
+\setinterfaceconstant{family}{familie}
+\setinterfaceconstant{fieldbackgroundcolor}{culoarefundalcamp}
+\setinterfaceconstant{fieldframecolor}{culoareframecamp}
+\setinterfaceconstant{fieldlayer}{fieldlayer}
+\setinterfaceconstant{fieldoffset}{offsetcamp}
+\setinterfaceconstant{file}{fisier}
+\setinterfaceconstant{filtercommand}{filtercommand}
+\setinterfaceconstant{finalnamesep}{finalnamesep}
+\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{focus}{focus}
+\setinterfaceconstant{focusin}{focusin}
+\setinterfaceconstant{focusout}{focusout}
+\setinterfaceconstant{footer}{subsol}
+\setinterfaceconstant{footerdistance}{distantasubsol}
+\setinterfaceconstant{footerstate}{staresubsol}
+\setinterfaceconstant{foregroundcolor}{foregroundcolor}
+\setinterfaceconstant{foregroundstyle}{foregroundstyle}
+\setinterfaceconstant{format}{format}
+\setinterfaceconstant{frame}{frame}
+\setinterfaceconstant{framecolor}{culoareframe}
+\setinterfaceconstant{framecorner}{coltframe}
+\setinterfaceconstant{framedepth}{adancimeframe}
+\setinterfaceconstant{frameoffset}{offsetframe}
+\setinterfaceconstant{frameradius}{razaframe}
+\setinterfaceconstant{frames}{frames}
+\setinterfaceconstant{from}{dela}
+\setinterfaceconstant{get}{adu}
+\setinterfaceconstant{global}{global}
+\setinterfaceconstant{grid}{grid}
+\setinterfaceconstant{hang}{suspenda}
+\setinterfaceconstant{headalign}{headalign}
+\setinterfaceconstant{headcolor}{culoaretitlu}
+\setinterfaceconstant{headcommand}{headcommand}
+\setinterfaceconstant{headconversion}{conversietitlu}
+\setinterfaceconstant{header}{antet}
+\setinterfaceconstant{headerdistance}{distantaantet}
+\setinterfaceconstant{headerstate}{stareantet}
+\setinterfaceconstant{headlabel}{etichetatitlu}
+\setinterfaceconstant{headnumber}{numartitlu}
+\setinterfaceconstant{headstyle}{stiltitlu}
+\setinterfaceconstant{height}{inaltime}
+\setinterfaceconstant{hfactor}{hfactor}
+\setinterfaceconstant{hfil}{hfil}
+\setinterfaceconstant{hidenumber}{hidenumber}
+\setinterfaceconstant{hoffset}{hoffset}
+\setinterfaceconstant{horoffset}{offsetoriz}
+\setinterfaceconstant{hyphen}{hyphen}
+\setinterfaceconstant{icommand}{comandai}
+\setinterfaceconstant{in}{in}
+\setinterfaceconstant{inbetween}{intre}
+\setinterfaceconstant{increment}{increment}
+\setinterfaceconstant{incrementnumber}{numarincrement}
+\setinterfaceconstant{indenting}{aliniat}
+\setinterfaceconstant{indentnext}{aliniaturmator}
+\setinterfaceconstant{indicator}{indicator}
+\setinterfaceconstant{inner}{intern}
+\setinterfaceconstant{innermargin}{innermargin}
+\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{intent}{intent}
+\setinterfaceconstant{interaction}{interactiune}
+\setinterfaceconstant{interlinespace}{spatiereinterliniara}
+\setinterfaceconstant{itemalign}{itemalign}
+\setinterfaceconstant{items}{elemente}
+\setinterfaceconstant{juniorsep}{juniorsep}
+\setinterfaceconstant{ken}{ken}
+\setinterfaceconstant{keyexpansion}{keyexpansion}
+\setinterfaceconstant{keyword}{keyword}
+\setinterfaceconstant{label}{eticheta}
+\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{left}{stanga}
+\setinterfaceconstant{leftcolor}{culoarestanga}
+\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
+\setinterfaceconstant{leftedge}{bordurastanga}
+\setinterfaceconstant{leftedgedistance}{distantabordurastanga}
+\setinterfaceconstant{leftframe}{framestanga}
+\setinterfaceconstant{lefthyphen}{lefthyphen}
+\setinterfaceconstant{leftmargin}{marginestanga}
+\setinterfaceconstant{leftmargindistance}{distantamarginestanga}
+\setinterfaceconstant{leftoffset}{offsetstanga}
+\setinterfaceconstant{leftquotation}{citatstanga}
+\setinterfaceconstant{leftquote}{minicitatstanga}
+\setinterfaceconstant{leftsentence}{propozitiestanga}
+\setinterfaceconstant{leftspeech}{leftspeech}
+\setinterfaceconstant{leftstyle}{stilstanga}
+\setinterfaceconstant{leftsubsentence}{subpropozitiestanga}
+\setinterfaceconstant{lefttext}{textstanga}
+\setinterfaceconstant{leftwidth}{latimestanga}
+\setinterfaceconstant{level}{nivel}
+\setinterfaceconstant{levels}{nivele}
+\setinterfaceconstant{limittext}{limittext}
+\setinterfaceconstant{line}{linie}
+\setinterfaceconstant{linecorrection}{corectielinie}
+\setinterfaceconstant{lines}{linii}
+\setinterfaceconstant{list}{lista}
+\setinterfaceconstant{listtext}{listtext}
+\setinterfaceconstant{local}{local}
+\setinterfaceconstant{location}{locatie}
+\setinterfaceconstant{logo}{logo}
+\setinterfaceconstant{logos}{logos}
+\setinterfaceconstant{marcolor}{culoaremarcaj}
+\setinterfaceconstant{margin}{margine}
+\setinterfaceconstant{margindistance}{distantamargine}
+\setinterfaceconstant{marginedge}{coltbordura}
+\setinterfaceconstant{marginedgetext}{textcoltbordura}
+\setinterfaceconstant{margintext}{textmargine}
+\setinterfaceconstant{marking}{marcaje}
+\setinterfaceconstant{marstyle}{stilmarcaj}
+\setinterfaceconstant{max}{max}
+\setinterfaceconstant{maxdepth}{maxdepth}
+\setinterfaceconstant{maxheight}{inaltimemaxima}
+\setinterfaceconstant{maxwidth}{latimemaxima}
+\setinterfaceconstant{maybeyear}{maybeyear}
+\setinterfaceconstant{menu}{meniu}
+\setinterfaceconstant{method}{metoda}
+\setinterfaceconstant{middle}{mijloc}
+\setinterfaceconstant{middlespeech}{middlespeech}
+\setinterfaceconstant{middletext}{textmijloc}
+\setinterfaceconstant{midsentence}{midsentence}
+\setinterfaceconstant{min}{min}
+\setinterfaceconstant{mindepth}{mindepth}
+\setinterfaceconstant{minheight}{inaltimeminima}
+\setinterfaceconstant{minwidth}{latimeminima}
+\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{n}{n}
+\setinterfaceconstant{name}{nume}
+\setinterfaceconstant{namesep}{namesep}
+\setinterfaceconstant{nbottom}{njos}
+\setinterfaceconstant{nc}{nc}
+\setinterfaceconstant{next}{urmatorul}
+\setinterfaceconstant{nl}{nl}
+\setinterfaceconstant{nleft}{nstanga}
+\setinterfaceconstant{nlines}{nlinii}
+\setinterfaceconstant{norm}{norm}
+\setinterfaceconstant{nr}{nr}
+\setinterfaceconstant{nright}{ndreapta}
+\setinterfaceconstant{ntop}{nsus}
+\setinterfaceconstant{number}{numar}
+\setinterfaceconstant{numbercolor}{culoarenumar}
+\setinterfaceconstant{numbercommand}{comandanumar}
+\setinterfaceconstant{numberconversion}{numberconversion}
+\setinterfaceconstant{numberconversionset}{numberconversionset}
+\setinterfaceconstant{numberdistance}{numberdistance}
+\setinterfaceconstant{numbering}{numerotare}
+\setinterfaceconstant{numberorder}{numberorder}
+\setinterfaceconstant{numberprefix}{numberprefix}
+\setinterfaceconstant{numbersegments}{numbersegments}
+\setinterfaceconstant{numberseparator}{separatornumar}
+\setinterfaceconstant{numberseparatorset}{numberseparatorset}
+\setinterfaceconstant{numberset}{numberset}
+\setinterfaceconstant{numberstarter}{numberstarter}
+\setinterfaceconstant{numberstopper}{numberstopper}
+\setinterfaceconstant{numberstyle}{stilnumar}
+\setinterfaceconstant{numberwidth}{numberwidth}
+\setinterfaceconstant{nx}{nx}
+\setinterfaceconstant{ny}{ny}
+\setinterfaceconstant{object}{obiect}
+\setinterfaceconstant{obstruction}{obstructie}
+\setinterfaceconstant{oddmargin}{margineimpara}
+\setinterfaceconstant{offset}{offset}
+\setinterfaceconstant{openaction}{actiunedeschidere}
+\setinterfaceconstant{openpageaction}{actiunedeschiderepagina}
+\setinterfaceconstant{option}{optiune}
+\setinterfaceconstant{order}{order}
+\setinterfaceconstant{orientation}{orientation}
+\setinterfaceconstant{otherstext}{otherstext}
+\setinterfaceconstant{outermargin}{outermargin}
+\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownnumber}{numarpropriu}
+\setinterfaceconstant{page}{pagina}
+\setinterfaceconstant{pageboundaries}{marginipagina}
+\setinterfaceconstant{pagecolor}{culoarepagina}
+\setinterfaceconstant{pagecommand}{comandapagina}
+\setinterfaceconstant{pageconversion}{pageconversion}
+\setinterfaceconstant{pageconversionset}{pageconversionset}
+\setinterfaceconstant{pagenumber}{numarpagina}
+\setinterfaceconstant{pageprefix}{pageprefix}
+\setinterfaceconstant{pageprefixconnector}{pageprefixconnector}
+\setinterfaceconstant{pageprefixconversion}{pageprefixconversion}
+\setinterfaceconstant{pageprefixconversionset}{pageprefixconversionset}
+\setinterfaceconstant{pageprefixsegments}{pageprefixsegments}
+\setinterfaceconstant{pageprefixseparatorset}{pageprefixseparatorset}
+\setinterfaceconstant{pageprefixset}{pageprefixset}
+\setinterfaceconstant{pageprefixstarter}{pageprefixstarter}
+\setinterfaceconstant{pageprefixstopper}{pageprefixstopper}
+\setinterfaceconstant{pagesegments}{pagesegments}
+\setinterfaceconstant{pageseparatorset}{pageseparatorset}
+\setinterfaceconstant{pageset}{pageset}
+\setinterfaceconstant{pagestarter}{pagestarter}
+\setinterfaceconstant{pagestate}{pagestate}
+\setinterfaceconstant{pagestopper}{pagestopper}
+\setinterfaceconstant{pagestyle}{stilpagina}
+\setinterfaceconstant{palet}{paleta}
+\setinterfaceconstant{paper}{hartie}
+\setinterfaceconstant{paragraph}{paragraf}
+\setinterfaceconstant{place}{pune}
+\setinterfaceconstant{placehead}{punetitlu}
+\setinterfaceconstant{placestopper}{punestopper}
+\setinterfaceconstant{position}{pozitie}
+\setinterfaceconstant{prefix}{prefix}
+\setinterfaceconstant{prefixconnector}{prefixconnector}
+\setinterfaceconstant{prefixconversion}{prefixconversion}
+\setinterfaceconstant{prefixconversionset}{prefixconversionset}
+\setinterfaceconstant{prefixsegments}{prefixsegments}
+\setinterfaceconstant{prefixseparatorset}{prefixseparatorset}
+\setinterfaceconstant{prefixset}{prefixset}
+\setinterfaceconstant{prefixstarter}{prefixstarter}
+\setinterfaceconstant{prefixstopper}{prefixstopper}
+\setinterfaceconstant{preset}{preset}
+\setinterfaceconstant{preview}{previzualizare}
+\setinterfaceconstant{previous}{precendent}
+\setinterfaceconstant{previousnumber}{numarprecedent}
+\setinterfaceconstant{process}{process}
+\setinterfaceconstant{pubsep}{pubsep}
+\setinterfaceconstant{radius}{raza}
+\setinterfaceconstant{random}{aleator}
+\setinterfaceconstant{range}{range}
+\setinterfaceconstant{reduction}{reducere}
+\setinterfaceconstant{ref}{ref}
+\setinterfaceconstant{refcommand}{refcommand}
+\setinterfaceconstant{reference}{referinta}
+\setinterfaceconstant{referenceprefix}{referenceprefix}
+\setinterfaceconstant{referencing}{referinta}
+\setinterfaceconstant{regionin}{regiuneintrare}
+\setinterfaceconstant{regionout}{regiuneiesire}
+\setinterfaceconstant{repeat}{repeta}
+\setinterfaceconstant{reset}{reset}
+\setinterfaceconstant{resetnumber}{resetnumber}
+\setinterfaceconstant{resolution}{rezolutie}
+\setinterfaceconstant{right}{dreapta}
+\setinterfaceconstant{rightcolor}{culoaredreapta}
+\setinterfaceconstant{rightcompoundhyphen}{rightcompoundhyphen}
+\setinterfaceconstant{rightedge}{borduradreapta}
+\setinterfaceconstant{rightedgedistance}{distantacoltdreapta}
+\setinterfaceconstant{rightframe}{framedreapta}
+\setinterfaceconstant{righthyphen}{righthyphen}
+\setinterfaceconstant{rightmargin}{marginedreapta}
+\setinterfaceconstant{rightmargindistance}{distantamarginedreapta}
+\setinterfaceconstant{rightoffset}{offsetdreapta}
+\setinterfaceconstant{rightquotation}{citatdreapta}
+\setinterfaceconstant{rightquote}{minicitatdreapta}
+\setinterfaceconstant{rightsentence}{propozitiedreapta}
+\setinterfaceconstant{rightspeech}{rightspeech}
+\setinterfaceconstant{rightstyle}{stildreapta}
+\setinterfaceconstant{rightsubsentence}{subpropozitiedreapta}
+\setinterfaceconstant{righttext}{textdreapta}
+\setinterfaceconstant{rightwidth}{marginedreapta}
+\setinterfaceconstant{rotation}{rotatie}
+\setinterfaceconstant{rule}{rigla}
+\setinterfaceconstant{rulecolor}{culoarerigla}
+\setinterfaceconstant{rulethickness}{grosimerigla}
+\setinterfaceconstant{samepage}{aceeasipagina}
+\setinterfaceconstant{sample}{exemplu}
+\setinterfaceconstant{samplesize}{samplesize}
+\setinterfaceconstant{saveinlist}{saveinlist}
+\setinterfaceconstant{scale}{scala}
+\setinterfaceconstant{scope}{scop}
+\setinterfaceconstant{screen}{ecran}
+\setinterfaceconstant{section}{sectiune}
+\setinterfaceconstant{sectionconversion}{sectionconversion}
+\setinterfaceconstant{sectionconversionset}{sectionconversionset}
+\setinterfaceconstant{sectionnumber}{numarsectiune}
+\setinterfaceconstant{sectionresetset}{sectionresetset}
+\setinterfaceconstant{sectionsegments}{sectionsegments}
+\setinterfaceconstant{sectionseparatorset}{sectionseparatorset}
+\setinterfaceconstant{sectionset}{sectionset}
+\setinterfaceconstant{sectionstarter}{sectionstarter}
+\setinterfaceconstant{sectionstopper}{sectionstopper}
+\setinterfaceconstant{separator}{separator}
+\setinterfaceconstant{set}{set}
+\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{side}{parte}
+\setinterfaceconstant{sidealign}{sidealign}
+\setinterfaceconstant{sidemethod}{sidemethod}
+\setinterfaceconstant{sidespaceafter}{spatiulateraldupa}
+\setinterfaceconstant{sidespacebefore}{spatiulateralinainte}
+\setinterfaceconstant{sign}{semn}
+\setinterfaceconstant{size}{dimensiune}
+\setinterfaceconstant{small}{mic}
+\setinterfaceconstant{sort}{sort}
+\setinterfaceconstant{sorttype}{sorttype}
+\setinterfaceconstant{source}{sursa}
+\setinterfaceconstant{space}{spatiu}
+\setinterfaceconstant{spaceafter}{spatiudupa}
+\setinterfaceconstant{spacebefore}{spatiuinainte}
+\setinterfaceconstant{spaceinbetween}{spaceinbetween}
+\setinterfaceconstant{spacing}{spatiere}
+\setinterfaceconstant{split}{split}
+\setinterfaceconstant{splitcolor}{splitcolor}
+\setinterfaceconstant{splitmethod}{splitmethod}
+\setinterfaceconstant{splitoffset}{splitoffset}
+\setinterfaceconstant{spot}{spot}
+\setinterfaceconstant{stack}{stack}
+\setinterfaceconstant{start}{start}
+\setinterfaceconstant{starter}{starter}
+\setinterfaceconstant{state}{stare}
+\setinterfaceconstant{step}{pas}
+\setinterfaceconstant{stop}{stop}
+\setinterfaceconstant{stopper}{stopper}
+\setinterfaceconstant{stretch}{dilatat}
+\setinterfaceconstant{strip}{strip}
+\setinterfaceconstant{strut}{strut}
+\setinterfaceconstant{style}{stil}
+\setinterfaceconstant{sub}{sub}
+\setinterfaceconstant{subtitle}{subtitlu}
+\setinterfaceconstant{suffix}{suffix}
+\setinterfaceconstant{surnamesep}{surnamesep}
+\setinterfaceconstant{sx}{sx}
+\setinterfaceconstant{sy}{sy}
+\setinterfaceconstant{symalign}{symaliniere}
+\setinterfaceconstant{symbol}{simbol}
+\setinterfaceconstant{symbolset}{setsimbol}
+\setinterfaceconstant{symcolor}{culoaresimbol}
+\setinterfaceconstant{symstyle}{stilsimbol}
+\setinterfaceconstant{synonym}{sinonim}
+\setinterfaceconstant{synonymcolor}{culoaresinonim}
+\setinterfaceconstant{synonymcommand}{synonymcommand}
+\setinterfaceconstant{synonymstyle}{stilsinonim}
+\setinterfaceconstant{tab}{tab}
+\setinterfaceconstant{text}{text}
+\setinterfaceconstant{textcolor}{culoaretext}
+\setinterfaceconstant{textcommand}{comandatext}
+\setinterfaceconstant{textdistance}{textdistance}
+\setinterfaceconstant{textlayer}{textlayer}
+\setinterfaceconstant{textmargin}{textmargin}
+\setinterfaceconstant{textmethod}{textmethod}
+\setinterfaceconstant{textseparator}{separatortext}
+\setinterfaceconstant{textsize}{dimensiunetext}
+\setinterfaceconstant{textstate}{staretext}
+\setinterfaceconstant{textstyle}{stiltext}
+\setinterfaceconstant{textwidth}{latimetext}
+\setinterfaceconstant{title}{titlu}
+\setinterfaceconstant{titlecolor}{culoaretitlu}
+\setinterfaceconstant{titlecommand}{titlecommand}
+\setinterfaceconstant{titledistance}{distantatitlu}
+\setinterfaceconstant{titleleft}{titleleft}
+\setinterfaceconstant{titleright}{titleright}
+\setinterfaceconstant{titlestyle}{stiltitlu}
+\setinterfaceconstant{to}{catre}
+\setinterfaceconstant{tolerance}{toleranta}
+\setinterfaceconstant{top}{sus}
+\setinterfaceconstant{topdistance}{distantasus}
+\setinterfaceconstant{topframe}{framesus}
+\setinterfaceconstant{topoffset}{offsetsus}
+\setinterfaceconstant{topspace}{spatiusus}
+\setinterfaceconstant{topstate}{staresus}
+\setinterfaceconstant{totalnumber}{totalnumber}
+\setinterfaceconstant{type}{type}
+\setinterfaceconstant{unit}{unitate}
+\setinterfaceconstant{unknownreference}{referintanecunoscuta}
+\setinterfaceconstant{urlalternative}{urlalternativ}
+\setinterfaceconstant{urlspace}{spatiuurl}
+\setinterfaceconstant{validate}{verifica}
+\setinterfaceconstant{vcommand}{comandav}
+\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfil}{vfil}
+\setinterfaceconstant{voffset}{voffset}
+\setinterfaceconstant{vonsep}{vonsep}
+\setinterfaceconstant{way}{mod}
+\setinterfaceconstant{wfactor}{factorw}
+\setinterfaceconstant{white}{alb}
+\setinterfaceconstant{width}{latime}
+\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xmax}{xmax}
+\setinterfaceconstant{xoffset}{xoffset}
+\setinterfaceconstant{xscale}{xscala}
+\setinterfaceconstant{xstep}{xstep}
+\setinterfaceconstant{yfactor}{yfactor}
+\setinterfaceconstant{ymax}{ymax}
+\setinterfaceconstant{yoffset}{yoffset}
+\setinterfaceconstant{yscale}{yscala}
+\setinterfaceconstant{ystep}{ystep}
+% definitions for interface elements for language ro
+%
+\setinterfaceelement{answerlines}{answerlines}
+\setinterfaceelement{answerspace}{answerspace}
+\setinterfaceelement{begin}{inceput}
+\setinterfaceelement{complete}{complet}
+\setinterfaceelement{coupled}{cuplat}
+\setinterfaceelement{currentlocal}{localcurent}
+\setinterfaceelement{emptyone}{gol}
+\setinterfaceelement{emptytwo}{gol}
+\setinterfaceelement{end}{sfarsit}
+\setinterfaceelement{endsetup}{}
+\setinterfaceelement{get}{get}
+\setinterfaceelement{increment}{increment}
+\setinterfaceelement{list}{lista}
+\setinterfaceelement{listof}{listade}
+\setinterfaceelement{load}{incarca}
+\setinterfaceelement{local}{local}
+\setinterfaceelement{makeup}{makeup}
+\setinterfaceelement{next}{urmatorul}
+\setinterfaceelement{place}{pune}
+\setinterfaceelement{previous}{precedent}
+\setinterfaceelement{previouslocal}{precedentlocal}
+\setinterfaceelement{reserve}{rezervat}
+\setinterfaceelement{see}{vezi}
+\setinterfaceelement{setup}{setare}
+\setinterfaceelement{start}{start}
+\setinterfaceelement{stop}{stop}
+\setinterfaceelement{text}{text}
+\setinterfaceelement{type}{type}
+% definitions for interface commands for language ro
+%
+\setinterfacecommand{CAPPED}{KAP}
+\setinterfacecommand{Character}{Litera}
+\setinterfacecommand{Characters}{Litere}
+\setinterfacecommand{LABELTEXT}{TEXTETICHETA}
+\setinterfacecommand{MONTH}{LUNA}
+\setinterfacecommand{Numbers}{Numere}
+\setinterfacecommand{Romannumerals}{Numereromane}
+\setinterfacecommand{SmallCapped}{Kap}
+\setinterfacecommand{SmallCaps}{Kaps}
+\setinterfacecommand{WEEKDAY}{ZIDINSAPTAMANA}
+\setinterfacecommand{WORD}{CUVANT}
+\setinterfacecommand{WORDS}{CUVINTE}
+\setinterfacecommand{Word}{Cuvant}
+\setinterfacecommand{Words}{Cuvinte}
+\setinterfacecommand{about}{despre}
+\setinterfacecommand{adaptlayout}{adapteazaaspect}
+\setinterfacecommand{arg}{arg}
+\setinterfacecommand{at}{la}
+\setinterfacecommand{atleftmargin}{atleftmargin}
+\setinterfacecommand{atpage}{lapagina}
+\setinterfacecommand{atrightmargin}{atrightmargin}
+\setinterfacecommand{background}{fundal}
+\setinterfacecommand{backspace}{spatiuspate}
+\setinterfacecommand{blackrule}{linieneagra}
+\setinterfacecommand{blackrules}{liniinegre}
+\setinterfacecommand{blank}{blanc}
+\setinterfacecommand{bookmark}{semncarte}
+\setinterfacecommand{bottomdistance}{distantajos}
+\setinterfacecommand{bottomheight}{inaltimejos}
+\setinterfacecommand{bottomspace}{spatiujos}
+\setinterfacecommand{but}{but}
+\setinterfacecommand{button}{buton}
+\setinterfacecommand{bypassblocks}{saripesteblocuri}
+\setinterfacecommand{character}{litera}
+\setinterfacecommand{characters}{litere}
+\setinterfacecommand{chem}{chem}
+\setinterfacecommand{clip}{clip}
+\setinterfacecommand{clonefield}{cloneazacamp}
+\setinterfacecommand{color}{culoare}
+\setinterfacecommand{colorbar}{baraculoare}
+\setinterfacecommand{colorvalue}{valoareculoare}
+\setinterfacecommand{column}{coloana}
+\setinterfacecommand{comment}{comentariu}
+\setinterfacecommand{comparecolorgroup}{comparagrupculoare}
+\setinterfacecommand{comparepalet}{comparapaleta}
+\setinterfacecommand{completepagenumber}{completeazanumarpagina}
+\setinterfacecommand{completeregister}{completeregister}
+\setinterfacecommand{component}{componenta}
+\setinterfacecommand{convertnumber}{convertestenumar}
+\setinterfacecommand{copyfield}{copiazacamp}
+\setinterfacecommand{correctwhitespace}{corecteazaspatiualb}
+\setinterfacecommand{coupledocument}{cupleazadocument}
+\setinterfacecommand{couplemarking}{cupleazamarcaje}
+\setinterfacecommand{couplepage}{paginadubla}
+\setinterfacecommand{couplepaper}{hartiedubla}
+\setinterfacecommand{coupleregister}{cupleazaregistru}
+\setinterfacecommand{crlf}{crlf}
+\setinterfacecommand{currentdate}{datacurenta}
+\setinterfacecommand{currentheadnumber}{numartitlucurent}
+\setinterfacecommand{cutspace}{cutspace}
+\setinterfacecommand{date}{data}
+\setinterfacecommand{decouplemarking}{decupleazamarcaje}
+\setinterfacecommand{decrementnumber}{decrementnumber}
+\setinterfacecommand{define}{defineste}
+\setinterfacecommand{defineaccent}{definesteaccent}
+\setinterfacecommand{defineblank}{definesteblanc}
+\setinterfacecommand{defineblock}{definestebloc}
+\setinterfacecommand{definebodyfont}{definestefonttext}
+\setinterfacecommand{definebodyfontenvironment}{definestemediulfonttext}
+\setinterfacecommand{definebuffer}{definestebuffer}
+\setinterfacecommand{definecharacter}{definestecaracter}
+\setinterfacecommand{definecolor}{definesteculoare}
+\setinterfacecommand{definecolorgroup}{definestegrupculori}
+\setinterfacecommand{definecolumnbreak}{definecolumnbreak}
+\setinterfacecommand{definecolumnset}{definecolumnset}
+\setinterfacecommand{definecombination}{definecombination}
+\setinterfacecommand{definecombinedlist}{definestelistacombinata}
+\setinterfacecommand{definecommand}{definestecomanda}
+\setinterfacecommand{defineconversion}{definesteconversie}
+\setinterfacecommand{definedescription}{definestedescriere}
+\setinterfacecommand{defineenumeration}{definesteenumerare}
+\setinterfacecommand{definefield}{definestecamp}
+\setinterfacecommand{definefieldstack}{definestestivacampuri}
+\setinterfacecommand{definefiguresymbol}{definestesimbolfigura}
+\setinterfacecommand{definefloat}{definestefloat}
+\setinterfacecommand{definefont}{definestefont}
+\setinterfacecommand{definefontstyle}{definestestilfont}
+\setinterfacecommand{definefontsynonym}{definestesinonimfont}
+\setinterfacecommand{defineframed}{definesteinconjurare}
+\setinterfacecommand{defineframedtext}{definestetextinconjurat}
+\setinterfacecommand{definehbox}{definestehbox}
+\setinterfacecommand{definehead}{definesteantet}
+\setinterfacecommand{defineindenting}{definestealiat}
+\setinterfacecommand{defineinmargin}{defineinmargin}
+\setinterfacecommand{defineinteractionmenu}{definestemeniuinteractiune}
+\setinterfacecommand{defineitemgroup}{defineitemgroup}
+\setinterfacecommand{definelabel}{definesteeticheta}
+\setinterfacecommand{definelayer}{definelayer}
+\setinterfacecommand{definelayout}{definelayout}
+\setinterfacecommand{definelist}{definestelista}
+\setinterfacecommand{definelogo}{definestelogo}
+\setinterfacecommand{definemainfield}{definestecampprincipal}
+\setinterfacecommand{definemakeup}{definestemakeup}
+\setinterfacecommand{definemarking}{definestemarcaje}
+\setinterfacecommand{definemathalignment}{definemathalignment}
+\setinterfacecommand{defineoutput}{definesteoutput}
+\setinterfacecommand{defineoverlay}{definesteoverlay}
+\setinterfacecommand{definepagebreak}{definepagebreak}
+\setinterfacecommand{definepalet}{definestepaleta}
+\setinterfacecommand{definepapersize}{definestedimensiunehartie}
+\setinterfacecommand{defineparagraphs}{definesteparagraf}
+\setinterfacecommand{defineplacement}{defineplacement}
+\setinterfacecommand{defineprofile}{definesteprofil}
+\setinterfacecommand{defineprogram}{definesteprogram}
+\setinterfacecommand{definerawfont}{definestefontraw}
+\setinterfacecommand{definereference}{definestereferinte}
+\setinterfacecommand{definereferenceformat}{definesteformatreferinte}
+\setinterfacecommand{definereferencelist}{definestelistareferinte}
+\setinterfacecommand{defineregister}{definesteregistru}
+\setinterfacecommand{definerule}{definesterigla}
+\setinterfacecommand{definesection}{definestesectiune}
+\setinterfacecommand{definesectionblock}{definesteblocsectiune}
+\setinterfacecommand{definesorting}{definestesortare}
+\setinterfacecommand{definestartstop}{definestestartstop}
+\setinterfacecommand{definestyle}{definestestil}
+\setinterfacecommand{definesubfield}{definestesubcamp}
+\setinterfacecommand{definesymbol}{definestesimbol}
+\setinterfacecommand{definesynonyms}{definestesinonim}
+\setinterfacecommand{definetabletemplate}{definestesablontabel}
+\setinterfacecommand{definetabulate}{definestetabulatori}
+\setinterfacecommand{definetext}{definestetext}
+\setinterfacecommand{definetextposition}{definestepozitietext}
+\setinterfacecommand{definetextvariable}{definestevariabilatext}
+\setinterfacecommand{definetype}{definetype}
+\setinterfacecommand{definetyping}{definestetyping}
+\setinterfacecommand{defineversion}{definesteversiune}
+\setinterfacecommand{determineheadnumber}{determinanumartitlu}
+\setinterfacecommand{determinelistcharacteristics}{determinacaracteristicilelistei}
+\setinterfacecommand{determineregistercharacteristics}{determinacaracteristiciregistru}
+\setinterfacecommand{dimension}{dimensiune}
+\setinterfacecommand{disableinteractionmenu}{dezactiveazameniuinteractiune}
+\setinterfacecommand{domicile}{domiciliu}
+\setinterfacecommand{donttest}{nutesta}
+\setinterfacecommand{edgedistance}{distantacolt}
+\setinterfacecommand{edgewidth}{latimecolturi}
+\setinterfacecommand{emptylines}{emptylines}
+\setinterfacecommand{environment}{mediu}
+\setinterfacecommand{externalfigure}{figuraexterna}
+\setinterfacecommand{fact}{fact}
+\setinterfacecommand{field}{camp}
+\setinterfacecommand{fieldstack}{stivacampuri}
+\setinterfacecommand{fillinfield}{campumplere}
+\setinterfacecommand{fillinline}{linieumplere}
+\setinterfacecommand{fillinrules}{rigleumplere}
+\setinterfacecommand{fillintext}{textumplere}
+\setinterfacecommand{fitfield}{potrivestecamp}
+\setinterfacecommand{fixedspace}{spatiufixat}
+\setinterfacecommand{fixedspaces}{spatiifixate}
+\setinterfacecommand{followprofile}{urmeazaprofil}
+\setinterfacecommand{followprofileversion}{urmeazaversiuneprofil}
+\setinterfacecommand{followversion}{urmeazaversiune}
+\setinterfacecommand{footerdistance}{distantasubsol}
+\setinterfacecommand{footerheight}{inaltimesubsol}
+\setinterfacecommand{footnote}{notasubsol}
+\setinterfacecommand{footnotetext}{footnotetext}
+\setinterfacecommand{forceblocks}{forteazablocuri}
+\setinterfacecommand{formulanumber}{numarformula}
+\setinterfacecommand{fraction}{fractie}
+\setinterfacecommand{framed}{framed}
+\setinterfacecommand{from}{din}
+\setinterfacecommand{getbuffer}{adubuffer}
+\setinterfacecommand{getmarking}{adumarcaje}
+\setinterfacecommand{getnumber}{getnumber}
+\setinterfacecommand{godown}{injos}
+\setinterfacecommand{goto}{dute}
+\setinterfacecommand{gotobox}{dutebox}
+\setinterfacecommand{gotopage}{dutepagina}
+\setinterfacecommand{graycolor}{culoaregri}
+\setinterfacecommand{greyvalue}{valoaregri}
+\setinterfacecommand{grid}{grid}
+\setinterfacecommand{hairline}{firdepar}
+\setinterfacecommand{head}{titlu}
+\setinterfacecommand{headerdistance}{distantaantet}
+\setinterfacecommand{headerheight}{inaltimeantet}
+\setinterfacecommand{headlevel}{niveltitlu}
+\setinterfacecommand{headnumber}{numartitlu}
+\setinterfacecommand{headsym}{headsym}
+\setinterfacecommand{headtext}{texttitlu}
+\setinterfacecommand{hideblocks}{ascundeblocuri}
+\setinterfacecommand{high}{inalt}
+\setinterfacecommand{hl}{hl}
+\setinterfacecommand{immediatebetweenlist}{immediatebetweenlist}
+\setinterfacecommand{immediatetolist}{immediatetolist}
+\setinterfacecommand{in}{in}
+\setinterfacecommand{incrementnumber}{numarincrement}
+\setinterfacecommand{indenting}{aliniat}
+\setinterfacecommand{inframed}{inframed}
+\setinterfacecommand{infull}{pelung}
+\setinterfacecommand{ininner}{ininner}
+\setinterfacecommand{inleft}{instanga}
+\setinterfacecommand{inleftedge}{inparteastanga}
+\setinterfacecommand{inleftmargin}{inmargineastanga}
+\setinterfacecommand{inline}{inlinie}
+\setinterfacecommand{inmargin}{marginal}
+\setinterfacecommand{inmframed}{inmaframed}
+\setinterfacecommand{inneredgedistance}{inneredgedistance}
+\setinterfacecommand{inneredgewidth}{inneredgewidth}
+\setinterfacecommand{innermargindistance}{innermargindistance}
+\setinterfacecommand{innermarginwidth}{innermarginwidth}
+\setinterfacecommand{inothermargin}{inaltamargine}
+\setinterfacecommand{inouter}{inouter}
+\setinterfacecommand{inright}{indreapta}
+\setinterfacecommand{inrightedge}{inparteadreapta}
+\setinterfacecommand{inrightmargin}{inmargineadreapta}
+\setinterfacecommand{installlanguage}{instalarelimba}
+\setinterfacecommand{interactionbar}{barainteractiune}
+\setinterfacecommand{interactionbuttons}{butoaneinteractiune}
+\setinterfacecommand{interactionmenu}{meniuinteractiune}
+\setinterfacecommand{item}{element}
+\setinterfacecommand{items}{element}
+\setinterfacecommand{its}{el}
+\setinterfacecommand{keepblocks}{pastreazablocuri}
+\setinterfacecommand{label}{eticheta}
+\setinterfacecommand{labels}{etichete}
+\setinterfacecommand{labeltext}{texteticheta}
+\setinterfacecommand{language}{limba}
+\setinterfacecommand{leftaligned}{aliniatstanga}
+\setinterfacecommand{leftedgedistance}{distantacoltstanga}
+\setinterfacecommand{leftedgewidth}{latimecoltstanga}
+\setinterfacecommand{leftmargindistance}{distantamarginestanga}
+\setinterfacecommand{leftmarginwidth}{latimemarginestanga}
+\setinterfacecommand{leg}{leg}
+\setinterfacecommand{linewidth}{grosimelinie}
+\setinterfacecommand{listheight}{inaltimelista}
+\setinterfacecommand{listlength}{lungimelista}
+\setinterfacecommand{listsymbol}{listsymbol}
+\setinterfacecommand{listwidth}{latimelista}
+\setinterfacecommand{logfields}{logcampuri}
+\setinterfacecommand{lohi}{jossus}
+\setinterfacecommand{low}{jos}
+\setinterfacecommand{macroname}{nume}
+\setinterfacecommand{mainlanguage}{limbaprincipala}
+\setinterfacecommand{makeupheight}{inaltimemakeup}
+\setinterfacecommand{makeupwidth}{latimemakeup}
+\setinterfacecommand{mar}{mar}
+\setinterfacecommand{margindistance}{distantamargine}
+\setinterfacecommand{marginrule}{liniemargine}
+\setinterfacecommand{margintext}{textmarginal}
+\setinterfacecommand{margintitle}{titlumarginal}
+\setinterfacecommand{marginwidth}{latimemargine}
+\setinterfacecommand{marginword}{cuvantmarginal}
+\setinterfacecommand{marking}{marcaje}
+\setinterfacecommand{markversion}{marcheazaversiune}
+\setinterfacecommand{mathematics}{matematica}
+\setinterfacecommand{menubutton}{butonmeniu}
+\setinterfacecommand{mframed}{maframed}
+\setinterfacecommand{midaligned}{aliniatcentru}
+\setinterfacecommand{mirror}{reflexie}
+\setinterfacecommand{month}{luna}
+\setinterfacecommand{moveformula}{moveformula}
+\setinterfacecommand{moveongrid}{mutapegrid}
+\setinterfacecommand{movesidefloat}{movesidefloat}
+\setinterfacecommand{navigating}{navigating}
+\setinterfacecommand{nodimension}{faradimensiune}
+\setinterfacecommand{noheaderandfooterlines}{faraliniiantetsisubsol}
+\setinterfacecommand{noindenting}{faraaliniat}
+\setinterfacecommand{nolist}{faralista}
+\setinterfacecommand{nomarking}{faramarcaje}
+\setinterfacecommand{nomoreblocks}{gatablocuri}
+\setinterfacecommand{nomorefiles}{farafisiere}
+\setinterfacecommand{nop}{nop}
+\setinterfacecommand{nospace}{faraspatiu}
+\setinterfacecommand{note}{nota}
+\setinterfacecommand{notopandbottomlines}{faraliniisussijos}
+\setinterfacecommand{notsmallcapped}{nokap}
+\setinterfacecommand{nowhitespace}{faraspatiualb}
+\setinterfacecommand{numberofsubpages}{numberofsubpages}
+\setinterfacecommand{numbers}{numere}
+\setinterfacecommand{outeredgedistance}{outeredgedistance}
+\setinterfacecommand{outeredgewidth}{outeredgewidth}
+\setinterfacecommand{outermargindistance}{outermargindistance}
+\setinterfacecommand{outermarginwidth}{outermarginwidth}
+\setinterfacecommand{packed}{impachetat}
+\setinterfacecommand{page}{pagina}
+\setinterfacecommand{pagedepth}{pagedepth}
+\setinterfacecommand{pagenumber}{numarpagina}
+\setinterfacecommand{pageoffset}{pageoffset}
+\setinterfacecommand{pagereference}{referintapagina}
+\setinterfacecommand{pagetype}{tippagina}
+\setinterfacecommand{paperheight}{inaltimehartie}
+\setinterfacecommand{paperwidth}{latimehartie}
+\setinterfacecommand{periods}{puncte}
+\setinterfacecommand{plaatsruwelijst}{placerawlist}
+\setinterfacecommand{placebookmarks}{plaseazasemnecarte}
+\setinterfacecommand{placecombinedlist}{punelistacombinata}
+\setinterfacecommand{placefloat}{placefloat}
+\setinterfacecommand{placefootnotes}{punenotesubsol}
+\setinterfacecommand{placeformula}{puneformula}
+\setinterfacecommand{placeheadnumber}{placeheadnumber}
+\setinterfacecommand{placeheadtext}{placeheadtext}
+\setinterfacecommand{placelegend}{punelegenda}
+\setinterfacecommand{placelist}{punelista}
+\setinterfacecommand{placelocalfootnotes}{punenotesubsollocale}
+\setinterfacecommand{placelogos}{punelogouri}
+\setinterfacecommand{placeongrid}{plaseazapegrid}
+\setinterfacecommand{placeontopofeachother}{punedeasuprafiecareia}
+\setinterfacecommand{placepagenumber}{punenumarpagina}
+\setinterfacecommand{placereferencelist}{placereferencelist}
+\setinterfacecommand{placeregister}{puneregistru}
+\setinterfacecommand{placerule}{punerigla}
+\setinterfacecommand{placesidebyside}{punefatainfata}
+\setinterfacecommand{placesubformula}{punesubformula}
+\setinterfacecommand{placetextvariable}{punevariabilatext}
+\setinterfacecommand{position}{pozitie}
+\setinterfacecommand{positiontext}{pozitietext}
+\setinterfacecommand{printpaperheight}{inaltimehartieimprimanta}
+\setinterfacecommand{printpaperwidth}{latimehartieimprimanta}
+\setinterfacecommand{processblocks}{proceseazabloc}
+\setinterfacecommand{processpage}{proceseazapagina}
+\setinterfacecommand{product}{produs}
+\setinterfacecommand{program}{program}
+\setinterfacecommand{project}{proiect}
+\setinterfacecommand{publication}{publicatie}
+\setinterfacecommand{quotation}{citat}
+\setinterfacecommand{quote}{minicitat}
+\setinterfacecommand{ran}{ran}
+\setinterfacecommand{redo}{refa}
+\setinterfacecommand{ref}{ref}
+\setinterfacecommand{reference}{referinta}
+\setinterfacecommand{referral}{referit}
+\setinterfacecommand{referraldate}{datareferit}
+\setinterfacecommand{referring}{referring}
+\setinterfacecommand{remark}{remarca}
+\setinterfacecommand{reset}{reset}
+\setinterfacecommand{resetmarking}{reseteazamarcaje}
+\setinterfacecommand{resetnumber}{resetnumber}
+\setinterfacecommand{resettext}{resettextcontent}
+\setinterfacecommand{rightaligned}{aliniatdreapta}
+\setinterfacecommand{rightedgedistance}{distantacoltdreapta}
+\setinterfacecommand{rightedgewidth}{latimecoltdreapta}
+\setinterfacecommand{rightmargindistance}{distantamarginedreapta}
+\setinterfacecommand{rightmarginwidth}{latimemarginedreapta}
+\setinterfacecommand{romannumerals}{numereromane}
+\setinterfacecommand{rotate}{roteste}
+\setinterfacecommand{scale}{scala}
+\setinterfacecommand{screen}{ecran}
+\setinterfacecommand{selectblocks}{selecteazablocuri}
+\setinterfacecommand{selectpaper}{selecteazahartie}
+\setinterfacecommand{selectversion}{selecteazaversiune}
+\setinterfacecommand{setnumber}{setnumber}
+\setinterfacecommand{settextcontent}{settextcontent}
+\setinterfacecommand{settextvariable}{setvariabilatext}
+\setinterfacecommand{setupalign}{seteazaalinierea}
+\setinterfacecommand{setupanswerarea}{setupanswerarea}
+\setinterfacecommand{setuparranging}{seteazaaranjareapag}
+\setinterfacecommand{setupbackground}{seteazafundal}
+\setinterfacecommand{setupbackgrounds}{seteazafundaluri}
+\setinterfacecommand{setupblackrules}{seteazaliniinegre}
+\setinterfacecommand{setupblank}{seteazablanc}
+\setinterfacecommand{setupblock}{seteazabloc}
+\setinterfacecommand{setupbodyfont}{seteazafonttext}
+\setinterfacecommand{setupbodyfontenvironment}{seteazamediulfonttext}
+\setinterfacecommand{setupbottom}{seteazajos}
+\setinterfacecommand{setupbottomtexts}{seteazatextejos}
+\setinterfacecommand{setupbuffer}{seteazabuffer}
+\setinterfacecommand{setupbuttons}{seteazabutoane}
+\setinterfacecommand{setupcapitals}{seteazamajuscule}
+\setinterfacecommand{setupcaption}{seteazalegenda}
+\setinterfacecommand{setupcaptions}{seteazalegendele}
+\setinterfacecommand{setupclipping}{seteazaclipping}
+\setinterfacecommand{setupcolor}{seteazaculoare}
+\setinterfacecommand{setupcolors}{seteazaculori}
+\setinterfacecommand{setupcolumns}{seteazacoloane}
+\setinterfacecommand{setupcolumnset}{setupcolumnset}
+\setinterfacecommand{setupcolumnsetlines}{setupcolumnsetlines}
+\setinterfacecommand{setupcolumnsetstart}{setupcolumnsetstart}
+\setinterfacecommand{setupcombinations}{seteazacombinari}
+\setinterfacecommand{setupcombinedlist}{seteazalistacombinata}
+\setinterfacecommand{setupcomment}{seteazacomentariu}
+\setinterfacecommand{setupdescriptions}{seteazadescriere}
+\setinterfacecommand{setupenumerations}{seteazaenumerare}
+\setinterfacecommand{setupexternalfigures}{seteazafiguriexterne}
+\setinterfacecommand{setupfield}{seteazacamp}
+\setinterfacecommand{setupfields}{seteazacampuri}
+\setinterfacecommand{setupfillinlines}{seteazaliniiumplere}
+\setinterfacecommand{setupfillinrules}{seteazarigleumplere}
+\setinterfacecommand{setupfloat}{seteazafloat}
+\setinterfacecommand{setupfloats}{seteazafloats}
+\setinterfacecommand{setupfloatsplitting}{seteazaimpartireafloat}
+\setinterfacecommand{setupfooter}{seteazasubsol}
+\setinterfacecommand{setupfootertexts}{seteazatextesubsol}
+\setinterfacecommand{setupfootnotedefinition}{seteazadefinireanotasubsol}
+\setinterfacecommand{setupfootnotes}{seteazanotasubsol}
+\setinterfacecommand{setupforms}{seteazaformulare}
+\setinterfacecommand{setupformulas}{seteazaformule}
+\setinterfacecommand{setupframed}{seteazainconjurat}
+\setinterfacecommand{setupframedtexts}{definestetexteinconjurate}
+\setinterfacecommand{setuphead}{seteazatitlu}
+\setinterfacecommand{setupheader}{seteazaantet}
+\setinterfacecommand{setupheadertexts}{seteazatexteantet}
+\setinterfacecommand{setupheadnumber}{seteazanumartitlu}
+\setinterfacecommand{setupheads}{seteazatitluri}
+\setinterfacecommand{setupheadtext}{seteazatexttitlu}
+\setinterfacecommand{setuphyphenmark}{seteazaliniesilabe}
+\setinterfacecommand{setupindentations}{seteazaaliniate}
+\setinterfacecommand{setupindenting}{seteazaaliniat}
+\setinterfacecommand{setupinmargin}{seteazamarginal}
+\setinterfacecommand{setupinteraction}{seteazainteractiunea}
+\setinterfacecommand{setupinteractionbar}{seteazabarainteractiune}
+\setinterfacecommand{setupinteractionmenu}{seteazameniuinteractiune}
+\setinterfacecommand{setupinteractionscreen}{seteazaecraninteractiune}
+\setinterfacecommand{setupinterlinespace}{seteazaspatiuinterliniar}
+\setinterfacecommand{setupitemgroup}{setupitemgroup}
+\setinterfacecommand{setupitemgroups}{setareitemization}
+\setinterfacecommand{setupitems}{seteazaelemente}
+\setinterfacecommand{setuplabeltext}{seteazatexteticheta}
+\setinterfacecommand{setuplanguage}{setarelimba}
+\setinterfacecommand{setuplayout}{seteazaaspect}
+\setinterfacecommand{setuplegend}{seteazalegenda}
+\setinterfacecommand{setuplinenumbering}{seteazanumerotarelinii}
+\setinterfacecommand{setuplines}{seteazalinii}
+\setinterfacecommand{setuplinewidth}{seteazagrosimelinie}
+\setinterfacecommand{setuplist}{seteazalista}
+\setinterfacecommand{setupmakeup}{seteazamakeup}
+\setinterfacecommand{setupmarginblocks}{seteazablocurimarginale}
+\setinterfacecommand{setupmarginrules}{seteazaliniimargine}
+\setinterfacecommand{setupmarking}{seteazamarcaje}
+\setinterfacecommand{setupmathalignment}{setupmathalignment}
+\setinterfacecommand{setupnarrower}{seteazaingust}
+\setinterfacecommand{setupnumber}{setupnumber}
+\setinterfacecommand{setupnumbering}{seteazanumerotare}
+\setinterfacecommand{setupoppositeplacing}{seteazaplasareaopozita}
+\setinterfacecommand{setupoutput}{setareoutput}
+\setinterfacecommand{setuppagecomment}{seteazacomentariupagina}
+\setinterfacecommand{setuppagenumber}{seteazanumarpagina}
+\setinterfacecommand{setuppagenumbering}{seteazanumerotarepagina}
+\setinterfacecommand{setuppagetransitions}{seteazatranzitiepagina}
+\setinterfacecommand{setuppalet}{seteazapaleta}
+\setinterfacecommand{setuppaper}{setuppaper}
+\setinterfacecommand{setuppapersize}{seteazadimensiunihartie}
+\setinterfacecommand{setupparagraphnumbering}{seteazanumerotareparagrafe}
+\setinterfacecommand{setupparagraphs}{seteazaparagrafe}
+\setinterfacecommand{setupplacement}{setupplacement}
+\setinterfacecommand{setuppositioning}{setarepozitie}
+\setinterfacecommand{setupprofiles}{seteazaprofile}
+\setinterfacecommand{setupprograms}{seteazaprograme}
+\setinterfacecommand{setuppublications}{seteazapublicatii}
+\setinterfacecommand{setupquote}{seteazaminicitat}
+\setinterfacecommand{setupreferencelist}{seteazalistareferinte}
+\setinterfacecommand{setupreferencing}{seteazareferinte}
+\setinterfacecommand{setupregister}{seteazaregistru}
+\setinterfacecommand{setuprotate}{seteazarotare}
+\setinterfacecommand{setuprule}{seteazarigla}
+\setinterfacecommand{setups}{setari}
+\setinterfacecommand{setupscreens}{seteazaecrane}
+\setinterfacecommand{setupsection}{seteazasectiune}
+\setinterfacecommand{setupsectionblock}{seteazablocsectiune}
+\setinterfacecommand{setupsorting}{seteazasortare}
+\setinterfacecommand{setupspacing}{seteazaspatiu}
+\setinterfacecommand{setupstartstop}{setupstartstop}
+\setinterfacecommand{setupstrut}{seteazastrut}
+\setinterfacecommand{setupsubpagenumber}{seteazanumarsubpagina}
+\setinterfacecommand{setupsymbolset}{seteazasimbol}
+\setinterfacecommand{setupsynchronization}{setaresincronizare}
+\setinterfacecommand{setupsynchronizationbar}{setarebarasincronizare}
+\setinterfacecommand{setupsynonyms}{seteazasinonime}
+\setinterfacecommand{setupsystem}{seteazasistem}
+\setinterfacecommand{setuptab}{seteazatab}
+\setinterfacecommand{setuptables}{seteazatabele}
+\setinterfacecommand{setuptabulate}{seteazatabulatori}
+\setinterfacecommand{setuptext}{seteazatext}
+\setinterfacecommand{setuptextposition}{seteazapozitietext}
+\setinterfacecommand{setuptextrules}{seteazarigletext}
+\setinterfacecommand{setuptexttexts}{seteazatextetext}
+\setinterfacecommand{setuptextvariable}{seteazavariabilatext}
+\setinterfacecommand{setupthinrules}{seteazaliniesubtire}
+\setinterfacecommand{setuptolerance}{seteazatoleranta}
+\setinterfacecommand{setuptop}{seteazasus}
+\setinterfacecommand{setuptoptexts}{seteazatextesus}
+\setinterfacecommand{setuptype}{seteazatype}
+\setinterfacecommand{setuptyping}{seteazatyping}
+\setinterfacecommand{setupunderbar}{seteazasublinie}
+\setinterfacecommand{setupurl}{seteazaurl}
+\setinterfacecommand{setupversions}{seteazaversiuni}
+\setinterfacecommand{setupwhitespace}{seteazaspatiualb}
+\setinterfacecommand{showbodyfont}{afiseazafonttext}
+\setinterfacecommand{showbodyfontenvironment}{afiseazamediufonttext}
+\setinterfacecommand{showcolor}{afiseazaculoare}
+\setinterfacecommand{showcolorgroup}{afiseazagrupculoare}
+\setinterfacecommand{showexternalfigures}{afiseazafiguriexterne}
+\setinterfacecommand{showfields}{afiseazacampuri}
+\setinterfacecommand{showframe}{afiseazarama}
+\setinterfacecommand{showgrid}{afiseazagrid}
+\setinterfacecommand{showlayout}{afiseazaaspect}
+\setinterfacecommand{showmakeup}{afiseazamakeup}
+\setinterfacecommand{showpalet}{afiseazapaleta}
+\setinterfacecommand{showprint}{afiseazatiparire}
+\setinterfacecommand{showsetups}{afiseazasetari}
+\setinterfacecommand{showstruts}{afiseazastruts}
+\setinterfacecommand{showsymbolset}{afiseazasetsimboluri}
+\setinterfacecommand{smallcapped}{kap}
+\setinterfacecommand{someline}{olinie}
+\setinterfacecommand{somewhere}{undeva}
+\setinterfacecommand{space}{spatiu}
+\setinterfacecommand{splitfloat}{impartefloat}
+\setinterfacecommand{startalignment}{startaliniere}
+\setinterfacecommand{startbackground}{startfundal}
+\setinterfacecommand{startcoding}{startcodificare}
+\setinterfacecommand{startcolor}{startculoare}
+\setinterfacecommand{startcolumnmakeup}{startcolumnmakeup}
+\setinterfacecommand{startcolumns}{startcoloane}
+\setinterfacecommand{startcolumnset}{startcolumnset}
+\setinterfacecommand{startcombination}{startcombinare}
+\setinterfacecommand{startcomponent}{startcomponenta}
+\setinterfacecommand{startdocument}{startdocument}
+\setinterfacecommand{startenvironment}{startmediu}
+\setinterfacecommand{startfigure}{startfigura}
+\setinterfacecommand{startglobal}{startglobal}
+\setinterfacecommand{startline}{startlinie}
+\setinterfacecommand{startlinecorrection}{startcorectielinie}
+\setinterfacecommand{startlinenumbering}{startnumerotarelinii}
+\setinterfacecommand{startlines}{startlinii}
+\setinterfacecommand{startlocal}{startlocal}
+\setinterfacecommand{startlocalfootnotes}{startnotesubsollocale}
+\setinterfacecommand{startmakeup}{startmakeup}
+\setinterfacecommand{startmarginblock}{startblocmarginal}
+\setinterfacecommand{startmarginrule}{startliniemargine}
+\setinterfacecommand{startnarrower}{startingust}
+\setinterfacecommand{startopposite}{startopozit}
+\setinterfacecommand{startoverlay}{startoverlay}
+\setinterfacecommand{startoverzicht}{startoverview}
+\setinterfacecommand{startpacked}{startimpachetat}
+\setinterfacecommand{startpositioning}{startpozitionare}
+\setinterfacecommand{startproduct}{startprodus}
+\setinterfacecommand{startprofile}{startprofil}
+\setinterfacecommand{startproject}{startproiect}
+\setinterfacecommand{startquotation}{startcitat}
+\setinterfacecommand{startraster}{startraster}
+\setinterfacecommand{startsymbolset}{startsetsimboluri}
+\setinterfacecommand{startsynchronization}{startsincronizare}
+\setinterfacecommand{starttable}{starttabel}
+\setinterfacecommand{starttables}{starttabele}
+\setinterfacecommand{starttext}{starttext}
+\setinterfacecommand{starttextrule}{startriglatext}
+\setinterfacecommand{startunpacked}{startneimpachetat}
+\setinterfacecommand{startversion}{startversiune}
+\setinterfacecommand{stopalignment}{stopaliniere}
+\setinterfacecommand{stopbackground}{stopfundal}
+\setinterfacecommand{stopcoding}{stopcodificare}
+\setinterfacecommand{stopcolor}{stopculoare}
+\setinterfacecommand{stopcolumnmakeup}{stopcolumnmakeup}
+\setinterfacecommand{stopcolumns}{stopcoloane}
+\setinterfacecommand{stopcolumnset}{stopcolumnset}
+\setinterfacecommand{stopcombination}{stopcombinare}
+\setinterfacecommand{stopcomponent}{stopcomponenta}
+\setinterfacecommand{stopdocument}{stopdocument}
+\setinterfacecommand{stopenvironment}{stopmediu}
+\setinterfacecommand{stopglobal}{stopblobal}
+\setinterfacecommand{stopline}{stoplinie}
+\setinterfacecommand{stoplinecorrection}{stopcorectielinie}
+\setinterfacecommand{stoplinenumbering}{stopnumerotarelinii}
+\setinterfacecommand{stoplines}{stoplinii}
+\setinterfacecommand{stoplocal}{stoplocal}
+\setinterfacecommand{stoplocalfootnotes}{stopnotesubsollocale}
+\setinterfacecommand{stopmakeup}{stopmakeup}
+\setinterfacecommand{stopmarginblock}{stopblocmarginal}
+\setinterfacecommand{stopmarginrule}{stopliniemargine}
+\setinterfacecommand{stopnarrower}{stopingust}
+\setinterfacecommand{stopopposite}{stopopozit}
+\setinterfacecommand{stopoverlay}{stopoverlay}
+\setinterfacecommand{stopoverzicht}{stopoverview}
+\setinterfacecommand{stoppacked}{stopimpachetat}
+\setinterfacecommand{stoppositioning}{stoppozitionare}
+\setinterfacecommand{stopproduct}{stopprodus}
+\setinterfacecommand{stopprofile}{stopprofil}
+\setinterfacecommand{stopproject}{stopproiect}
+\setinterfacecommand{stopquotation}{stopcitat}
+\setinterfacecommand{stopraster}{stopraster}
+\setinterfacecommand{stopsynchronization}{stopsincronizare}
+\setinterfacecommand{stoptable}{stoptabel}
+\setinterfacecommand{stoptables}{stoptabele}
+\setinterfacecommand{stoptext}{stoptext}
+\setinterfacecommand{stoptextrule}{stopriglatext}
+\setinterfacecommand{stopunpacked}{stopneimpachetat}
+\setinterfacecommand{stopversion}{stopversiune}
+\setinterfacecommand{stretched}{intins}
+\setinterfacecommand{subformulanumber}{numarsubformula}
+\setinterfacecommand{subpagenumber}{subpagenumber}
+\setinterfacecommand{switchtobodyfont}{trecilafonttext}
+\setinterfacecommand{switchtorawfont}{trecilafontraw}
+\setinterfacecommand{sym}{sim}
+\setinterfacecommand{symbol}{simbol}
+\setinterfacecommand{synchronizationbar}{barasincronizare}
+\setinterfacecommand{synchronize}{sincronizeaza}
+\setinterfacecommand{tab}{tab}
+\setinterfacecommand{testcolumn}{testcolumn}
+\setinterfacecommand{testpage}{testpage}
+\setinterfacecommand{tex}{tex}
+\setinterfacecommand{textheight}{inaltimetext}
+\setinterfacecommand{textreference}{referintatext}
+\setinterfacecommand{textrule}{riglatext}
+\setinterfacecommand{textvariable}{variabilatext}
+\setinterfacecommand{textwidth}{latimetext}
+\setinterfacecommand{thinrule}{liniesubtire}
+\setinterfacecommand{thinrules}{liniisubtiri}
+\setinterfacecommand{tooltip}{tooltip}
+\setinterfacecommand{topdistance}{distantasus}
+\setinterfacecommand{topheight}{inaltimesus}
+\setinterfacecommand{topspace}{spatiusus}
+\setinterfacecommand{totalnumberofpages}{numartotalpagini}
+\setinterfacecommand{translate}{traduce}
+\setinterfacecommand{txt}{txt}
+\setinterfacecommand{typ}{typ}
+\setinterfacecommand{type}{type}
+\setinterfacecommand{typebuffer}{scriebuffer}
+\setinterfacecommand{typefile}{typefile}
+\setinterfacecommand{unitmeaning}{numeunitate}
+\setinterfacecommand{unknown}{necunoscut}
+\setinterfacecommand{useJSscripts}{folosestescriptJS}
+\setinterfacecommand{useURL}{folosesteURL}
+\setinterfacecommand{useXMLfilter}{useXMLfilter}
+\setinterfacecommand{useblocks}{folosestebloc}
+\setinterfacecommand{usecommands}{folosestecomenzi}
+\setinterfacecommand{useencoding}{folosestecodificarea}
+\setinterfacecommand{useexternaldocument}{folosestedocumentextern}
+\setinterfacecommand{useexternalfigure}{folosestefiguraexterna}
+\setinterfacecommand{useexternalfile}{folosestefisierextern}
+\setinterfacecommand{useexternalfiles}{folosestefisiereexterne}
+\setinterfacecommand{useexternalsoundtrack}{folosestemuzicaexterna}
+\setinterfacecommand{usemodule}{folosestemodul}
+\setinterfacecommand{usemodules}{folosestemodule}
+\setinterfacecommand{usepath}{folosestedirector}
+\setinterfacecommand{usereferences}{folosestereferinte}
+\setinterfacecommand{usespecials}{folosestespeciale}
+\setinterfacecommand{usesymbols}{folosestesimboluri}
+\setinterfacecommand{usetypescript}{usetypescript}
+\setinterfacecommand{usetypescriptfile}{usetypescriptfile}
+\setinterfacecommand{useurl}{folosesteurl}
+\setinterfacecommand{version}{versiune}
+\setinterfacecommand{vl}{vl}
+\setinterfacecommand{weekday}{zidinsaptamana}
+\setinterfacecommand{whitespace}{spatiualb}
+\setinterfacecommand{wordright}{cuvantdreapta}
+\setinterfacecommand{writebetweenlist}{scrieintreliste}
+\setinterfacecommand{writetolist}{scrieinlista}
+\setinterfacecommand{writetoreferencelist}{scrieinlistareferinte}
+\setinterfacecommand{writetoregister}{scrieinregistru}
+%
+\endinput
\ No newline at end of file
diff --git a/tex/context/base/mult-sys.tex b/tex/context/base/mult-sys.tex
new file mode 100644
index 000000000..d48ce0a94
--- /dev/null
+++ b/tex/context/base/mult-sys.tex
@@ -0,0 +1,882 @@
+%D \module
+%D [ file=mult-sys,
+%D version=1996.06.01,
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=System,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 In boring module we define a lot of obscure but useful
+%D system constants. By doing so we save lots of memory while
+%D at the same time we prevent ourself from typing errors.
+
+\writestatus{loading}{ConTeXt Multilingual Macros / System}
+
+\unprotect
+
+%D The constants are grouped in such a way that there is a
+%D minimal change of conflicts.
+%D
+%D \starttyping
+%D \definesystemconstants {word}
+%D \definemessageconstant {word}
+%D \stoptyping
+%D
+%D This commands generate \type{\s!word} and \type{\m!word}.
+
+\definesystemconstant {hans}
+\definesystemconstant {taco}
+
+%D First we define some system constants used for both the
+%D multi||lingual interface and multi||linguag typesetting.
+
+\definesystemconstant {afrikaans} \definesystemconstant {af}
+\definesystemconstant {arabic} \definesystemconstant {ar}
+\definesystemconstant {catalan} \definesystemconstant {ca}
+\definesystemconstant {chinese} \definesystemconstant {cn}
+\definesystemconstant {croatian} \definesystemconstant {hr}
+\definesystemconstant {czech} \definesystemconstant {cs} \definesystemconstant {cz}
+\definesystemconstant {danish} \definesystemconstant {da}
+\definesystemconstant {dutch} \definesystemconstant {nl}
+\definesystemconstant {english} \definesystemconstant {en}
+\definesystemconstant {finish} \definesystemconstant {fi}
+\definesystemconstant {french} \definesystemconstant {fr}
+\definesystemconstant {german} \definesystemconstant {de}
+\definesystemconstant {hungarian} \definesystemconstant {hu}
+\definesystemconstant {italian} \definesystemconstant {it}
+\definesystemconstant {latin} \definesystemconstant {la}
+\definesystemconstant {lithuanian} \definesystemconstant {lt}
+\definesystemconstant {bokmal} \definesystemconstant {nb} \definesystemconstant {norwegian} \definesystemconstant {no}
+\definesystemconstant {nynorsk} \definesystemconstant {nn}
+\definesystemconstant {polish} \definesystemconstant {pl}
+\definesystemconstant {persian} \definesystemconstant {pe}
+\definesystemconstant {portuguese} \definesystemconstant {pt}
+\definesystemconstant {romanian} \definesystemconstant {ro}
+\definesystemconstant {russian} \definesystemconstant {ru}
+\definesystemconstant {slovak} \definesystemconstant {sk}
+\definesystemconstant {slovenian} \definesystemconstant {sl}
+\definesystemconstant {slovene}
+\definesystemconstant {spanish} \definesystemconstant {es}
+\definesystemconstant {swedish} \definesystemconstant {sv}
+\definesystemconstant {turkish} \definesystemconstant {tr}
+\definesystemconstant {turkmen} \definesystemconstant {tk}
+\definesystemconstant {gbenglish} \definesystemconstant {gb} \definesystemconstant {ukenglish} \definesystemconstant {uk}
+\definesystemconstant {usenglish} \definesystemconstant {us}
+\definesystemconstant {ukrainian} \definesystemconstant {ua}
+\definesystemconstant {greek} \definesystemconstant {gr}
+\definesystemconstant {ancientgreek} \definesystemconstant {agr}
+\definesystemconstant {vietnamese} \definesystemconstant {vi} \definesystemconstant {vn}
+
+%D For proper \UNICODE\ support we need a few font related
+%D constants.
+
+\definesystemconstant {BoldItalic}
+\definesystemconstant {BoldSlanted}
+\definesystemconstant {Bold}
+\definesystemconstant {Italic}
+\definesystemconstant {Regular}
+\definesystemconstant {Slanted}
+\definesystemconstant {Unicode}
+
+\definesystemconstant {Serif} \definesystemconstant {Regular}
+\definesystemconstant {Sans} \definesystemconstant {Support}
+\definesystemconstant {Mono} \definesystemconstant {Type}
+\definesystemconstant {Math}
+\definesystemconstant {Handwriting}
+\definesystemconstant {Calligraphy}
+\definesystemconstant {Casual}
+
+\definesystemconstant {SerifBold} \definesystemconstant {SansBold} \definesystemconstant {MonoBold}
+\definesystemconstant {SerifItalic} \definesystemconstant {SansItalic} \definesystemconstant {MonoItalic}
+\definesystemconstant {SerifBoldItalic} \definesystemconstant {SansBoldItalic} \definesystemconstant {MonoBoldItalic}
+\definesystemconstant {SerifSlanted} \definesystemconstant {SansSlanted} \definesystemconstant {MonoSlanted}
+\definesystemconstant {SerifBoldSlanted} \definesystemconstant {SansBoldSlanted} \definesystemconstant {MonoBoldSlanted}
+\definesystemconstant {SerifCaps} \definesystemconstant {SansCaps} \definesystemconstant {MonoCaps}
+
+\definesystemconstant {Normal}
+\definesystemconstant {Caps}
+
+\definesystemconstant {mnem} % kind of generic short tag
+
+\definesystemconstant {file}
+\definesystemconstant {name}
+\definesystemconstant {spec}
+
+\definesystemconstant {serif}
+\definesystemconstant {sans}
+\definesystemconstant {mono}
+\definesystemconstant {math}
+\definesystemconstant {handwriting}
+\definesystemconstant {calligraphy}
+\definesystemconstant {casual}
+\definesystemconstant {fax}
+
+\definesystemconstant {fallback}
+
+\definesystemconstant {none}
+\definesystemconstant {default}
+\definesystemconstant {smallcaps}
+
+%D As the name of their define command states, the next set of
+%D constants is used in the message macro's.
+
+\definemessageconstant {check}
+\definemessageconstant {colors}
+\definemessageconstant {columns}
+\definemessageconstant {encodings}
+\definemessageconstant {regimes}
+\definemessageconstant {figures}
+\definemessageconstant {fields}
+\definemessageconstant {files}
+\definemessageconstant {floatblocks}
+\definemessageconstant {fonts}
+\definemessageconstant {handlings}
+\definemessageconstant {interactions}
+\definemessageconstant {javascript}
+\definemessageconstant {layouts}
+\definemessageconstant {linguals}
+\definemessageconstant {references}
+\definemessageconstant {specials}
+\definemessageconstant {structures}
+\definemessageconstant {symbols}
+\definemessageconstant {systems}
+\definemessageconstant {lua}
+\definemessageconstant {textblocks}
+\definemessageconstant {verbatims}
+\definemessageconstant {versions}
+\definemessageconstant {metapost}
+\definemessageconstant {chemicals}
+\definemessageconstant {publications}
+
+%D Net come some \CONTEXT\ constants, used in the definition
+%D of private commands:
+
+\definesystemconstant {tex}
+\definesystemconstant {xml}
+\definesystemconstant {lua}
+
+\definesystemconstant {next}
+\definesystemconstant {pickup}
+\definesystemconstant {ascii}
+\definesystemconstant {default}
+\definesystemconstant {unknown}
+\definesystemconstant {action}
+\definesystemconstant {compare}
+\definesystemconstant {do}
+\definesystemconstant {dodo}
+\definesystemconstant {complex}
+\definesystemconstant {simple}
+\definesystemconstant {start}
+\definesystemconstant {stop}
+\definesystemconstant {dummy}
+\definesystemconstant {local}
+\definesystemconstant {global}
+\definesystemconstant {done}
+\definesystemconstant {font}
+\definesystemconstant {link}
+\definesystemconstant {parent}
+\definesystemconstant {clone}
+\definesystemconstant {section} \let\v!sectionlevel\s!section % for old times sake
+\definesystemconstant {handler}
+\definesystemconstant {counter}
+\definesystemconstant {single}
+\definesystemconstant {multi}
+
+\definesystemconstant {hasnumber}
+\definesystemconstant {hastitle}
+\definesystemconstant {hascaption}
+\definesystemconstant {haslevel}
+
+\definesystemconstant {mkiv}
+\definesystemconstant {mkii}
+\definesystemconstant {entities}
+
+\definesystemconstant {normal}
+\definesystemconstant {bold}
+\definesystemconstant {italic}
+\definesystemconstant {slanted}
+
+\definesystemconstant {default}
+\definesystemconstant {smallcaps}
+
+%D A more experienced \TEX\ user will recognize the next four
+%D constants. We need these because font-definitions are
+%D partially english.
+
+\definesystemconstant {run}
+
+\definesystemconstant {fam}
+\definesystemconstant {text}
+\definesystemconstant {script}
+\definesystemconstant {scriptscript}
+
+\definesystemconstant {lefthyphenmin}
+\definesystemconstant {righthyphenmin}
+
+\definesystemconstant {skewchar}
+\definesystemconstant {hyphenchar}
+\definesystemconstant {catcodes}
+\definesystemconstant {encoding}
+\definesystemconstant {resource}
+\definesystemconstant {mapping}
+\definesystemconstant {language}
+\definesystemconstant {patterns}
+\definesystemconstant {rname}
+\definesystemconstant {rscale}
+\definesystemconstant {handling}
+\definesystemconstant {features}
+\definesystemconstant {fallbacks}
+\definesystemconstant {background}
+\definesystemconstant {ucmap}
+
+\definesystemconstant {property}
+\definesystemconstant {overprint}
+\definesystemconstant {layer}
+\definesystemconstant {effect}
+\definesystemconstant {negative}
+\definesystemconstant {color}
+\definesystemconstant {transparency}
+
+\definesystemconstant {black}
+\definesystemconstant {white}
+
+\definesystemconstant {format}
+\definesystemconstant {extensions}
+\definesystemconstant {initializations}
+
+%D Just to be complete we define the standard \TEX\ units.
+
+\definesystemconstant {cm}
+\definesystemconstant {em}
+\definesystemconstant {ex}
+\definesystemconstant {mm}
+\definesystemconstant {pt}
+\definesystemconstant {sp}
+\definesystemconstant {bp}
+\definesystemconstant {in}
+\definesystemconstant {pc}
+\definesystemconstant {cm}
+\definesystemconstant {dd}
+\definesystemconstant {cc}
+\definesystemconstant {nd}
+\definesystemconstant {nc}
+
+%D These constants are used for internal and utility
+%D commands.
+
+\definesystemconstant {check}
+\definesystemconstant {reset}
+\definesystemconstant {set}
+
+\definesystemconstant {entrya}
+\definesystemconstant {entryb}
+\definesystemconstant {entryc}
+\definesystemconstant {entryd}
+\definesystemconstant {entry}
+\definesystemconstant {see}
+\definesystemconstant {from}
+\definesystemconstant {to}
+\definesystemconstant {line}
+\definesystemconstant {page}
+\definesystemconstant {realpage}
+\definesystemconstant {userpage}
+\definesystemconstant {subpage}
+
+\definesystemconstant {synonym}
+
+\definesystemconstant {reference}
+\definesystemconstant {main}
+
+\definesystemconstant {list}
+
+\definesystemconstant {item}
+\definesystemconstant {itemcount}
+
+\definesystemconstant {number}
+\definesystemconstant {references}
+\definesystemconstant {between}
+\definesystemconstant {format}
+\definesystemconstant {old}
+
+\definesystemconstant {thisisblock}
+\definesystemconstant {thiswasblock}
+
+\definesystemconstant {figurepreset}
+
+\definesystemconstant {empty}
+
+%D Some \CONTEXT\ commands take a two||pass aproach to
+%D optimize the typesetting. Each two||pass object has its
+%D own tag.
+
+\definesystemconstant {pass}
+
+\definesystemconstant {data}
+\definesystemconstant {float}
+\definesystemconstant {list}
+\definesystemconstant {page}
+\definesystemconstant {subpage}
+\definesystemconstant {margin}
+\definesystemconstant {profile}
+\definesystemconstant {versionbegin}
+\definesystemconstant {versionend}
+\definesystemconstant {cross}
+\definesystemconstant {paragraph}
+
+%D A lot of macros use tags to distinguish between different
+%D objects, e.g. lists and registers.
+
+\definesystemconstant {prt} % part (deel)
+\definesystemconstant {chp} % chapter (hoofdstuk)
+\definesystemconstant {sec} % section (paragraaf)
+\definesystemconstant {tit} % title (titel)
+\definesystemconstant {sub} % subject (onderwerp)
+\definesystemconstant {mar} % margin (marge)
+\definesystemconstant {num} % number (doornummeren)
+\definesystemconstant {def} % definition (doordefinieren)
+\definesystemconstant {for} % formula (formule)
+\definesystemconstant {fnt} % footnote (voetnoot)
+\definesystemconstant {ind} % index (register)
+\definesystemconstant {lin} % linked index
+\definesystemconstant {lst} % list (opsomming)
+\definesystemconstant {flt} % float (plaatsblok)
+\definesystemconstant {pag} % page (pagina)
+\definesystemconstant {txt} % text (tekst)
+\definesystemconstant {ref} % reference (verwijzing)
+\definesystemconstant {lab} % label (label)
+\definesystemconstant {aut} % automatic (inhoud, index)
+\definesystemconstant {vwa} % automatic (illustrations)
+\definesystemconstant {vwb} % automatic (illustrations)
+
+\definesystemconstant {kop} % kop % still dutch
+
+%D Reference labels can be tagged by users, for instance by
+%D means of \type{tag:}. The reference mechanism itself uses
+%D some tags too. These are definitely not to be used by users.
+%D Here they are:
+
+\definereferenceconstant {cross} {:c:} % cross reference
+\definereferenceconstant {view} {:v:} % view reference
+\definereferenceconstant {viewa} {:a:} % view reference test a
+\definereferenceconstant {viewb} {:b:} % view reference test b
+\definereferenceconstant {page} {:p:} % page referece
+\definereferenceconstant {list} {:l:} % list reference
+\definereferenceconstant {exec} {:e:} % execution reference
+\definereferenceconstant {form} {:m:} % form reference
+\definereferenceconstant {syst} {:s:} % system reference
+
+\definereferenceconstant {from} {:f:} % from list reference
+\definereferenceconstant {to} {:t:} % to list reference
+
+\definereferenceconstant {object} {:o:} % object reference
+\definereferenceconstant {driver} {:d:} % driver object reference
+\definereferenceconstant {widget} {:w:} % field chain reference
+
+\definereferenceconstant {java} {:j:} % java scripts
+
+%D When we use numbers and dimensions the same applies as
+%D with the keywords like \type{width} and \type{plus}
+%D mentioned earlier.
+
+\def\!!ten {10}
+\def\!!twelve {12}
+\def\!!hundred {100}
+\def\!!thousand {1000}
+\def\!!tenthousand {10000}
+\def\!!maxcard {65536}
+\def\!!medcard {32768}
+
+\def\!!zeropoint {0pt}
+\def\!!onepoint {1pt}
+\def\!!twopoint {2pt}
+\def\!!threepoint {3pt}
+\def\!!fourpoint {4pt}
+\def\!!fivepoint {5pt}
+\def\!!sixpoint {6pt}
+\def\!!sevenpoint {7pt}
+\def\!!eightpoint {8pt}
+\def\!!ninepoint {9pt}
+\def\!!tenpoint {10pt}
+\def\!!elevenpoint {11pt}
+\def\!!twelvepoint {12pt}
+\def\!!fourteenpointfour {14.4pt}
+
+\let\onerealpoint\onepoint % needed for latex
+
+% D Another optimization is:
+%
+% \let\points\onepoint
+
+%D A rough test is:
+%D
+%D \starttyping
+%D \def\TestMe % 7.75 sec on a P4/2G
+%D {\dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points
+%D \dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points}
+%D
+%D \def\TestMe % 11.5 sec on a P4/2G
+%D {\dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt%
+%D \dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt}
+%D
+%D \def\TestMe % 12.5 sec on a P4/2G
+%D {\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt%
+%D \dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt}
+%D
+%D \testfeatureonce {500000}{\TestMe}
+%D \stoptyping
+
+%D Variables are composed of a command specific tag and a user
+%D supplied variable (system constant). The first tag \type{ag}
+%D for instance is available as \type{\??ag} and expands to
+%D \type{@@ag} in composed variables.
+
+% vervallen : hd hr hm vt vr vm tr tn te br bm bo on om or
+
+\definesystemvariable {ab} % AlignedBoxes
+\definesystemvariable {ac} % ACcent
+\definesystemvariable {ae} % AttributEs
+\definesystemvariable {ag} % AchterGrond
+\definesystemvariable {al} % ALinea's
+\definesystemvariable {am} % interActieMenu
+\definesystemvariable {an} % ANchor
+\definesystemvariable {as} % AlignmentSwitch
+\definesystemvariable {at} % ATtachments
+\definesystemvariable {ba} % synchronisatieBAlk
+\definesystemvariable {be} % startstop (BeginEnd)
+\definesystemvariable {bj} % BlokJe
+\definesystemvariable {bk} % Blokken (floats)
+\definesystemvariable {bl} % BLanko
+\definesystemvariable {bg} % BleedinG
+\definesystemvariable {bo} % BlankO (definitions)
+\definesystemvariable {bp} % BreakPoint
+\definesystemvariable {br} % sideBaR
+\definesystemvariable {bs} % SelecteerBlokken
+\definesystemvariable {bt} % BuTton
+\definesystemvariable {bu} % BUffer
+\definesystemvariable {bv} % Brieven
+\definesystemvariable {by} % Per
+\definesystemvariable {cb} % CollectBox
+\definesystemvariable {cc} % Comment
+\definesystemvariable {ce} % CasEs
+\definesystemvariable {ch} % CHaracterspacing
+\definesystemvariable {ci} % CItaat
+\definesystemvariable {ck} % Character Kerning
+\definesystemvariable {cl} % kleur (CoLor setup)
+\definesystemvariable {cn} % CollumN
+\definesystemvariable {cm} % CheMical
+\definesystemvariable {co} % COmbinaties
+\definesystemvariable {cp} % CliP
+\definesystemvariable {cr} % kleur (ColoR)
+\definesystemvariable {cs} % kleur (ColorSeparation
+\definesystemvariable {cv} % ConVersie
+\definesystemvariable {cy} % CrYteria
+\definesystemvariable {da} % DAte
+\definesystemvariable {db} % Labels
+\definesystemvariable {dc} % DroppedCaps
+\definesystemvariable {dd} % DoorDefinieren
+\definesystemvariable {de} % DEel
+\definesystemvariable {di} % DIrections
+\definesystemvariable {dl} % DunneLijnen
+\definesystemvariable {dn} % DoorNummeren
+\definesystemvariable {dm} % DefineMeasure
+\definesystemvariable {do} % DefinieerOpmaak
+\definesystemvariable {du} % DUmmy
+\definesystemvariable {ds} % DoorSpringen
+\definesystemvariable {ef} % ExternFiguur
+\definesystemvariable {ec} % EnCoding
+\definesystemvariable {en} % ENvironments
+\definesystemvariable {ep} % ExternfiguurPreset
+\definesystemvariable {eq} % EQalign
+\definesystemvariable {er} % external resources
+\definesystemvariable {ex} % ExterneFiguren
+\definesystemvariable {fa} % font feature
+\definesystemvariable {fc} % FramedContent
+\definesystemvariable {fd} % FielD
+\definesystemvariable {fe} % FoxetExtensions
+\definesystemvariable {ff} % FontFile
+\definesystemvariable {fg} % FiGuurmaten
+\definesystemvariable {fi} % FIle
+\definesystemvariable {fl} % Floats
+\definesystemvariable {fm} % ForMules
+\definesystemvariable {fn} % subformulas
+\definesystemvariable {fo} % xml FO
+\definesystemvariable {fp} % FilegroeP
+\definesystemvariable {fq} % Features
+\definesystemvariable {fr} % ForM
+\definesystemvariable {fs} % FileSynonym
+\definesystemvariable {ft} % FonTs
+\definesystemvariable {fu} % FontSolution
+\definesystemvariable {fv} % FontVariant
+\definesystemvariable {fw} % simpleFonts by Wolfgang
+\definesystemvariable {fx} % FoXet
+\definesystemvariable {gr} % GRid
+\definesystemvariable {ha} % HAng
+\definesystemvariable {hs} % HSpace
+\definesystemvariable {ht} % HiddenText
+\definesystemvariable {ia} % Interactie
+\definesystemvariable {ib} % InteractieBalk
+\definesystemvariable {ic} % ICc profiles
+\definesystemvariable {id} % Index
+\definesystemvariable {ig} % ItemGroup
+\definesystemvariable {ih} % InHoudsopgave
+\definesystemvariable {ii} % stelIndexIn
+\definesystemvariable {il} % stelInvulRegelsin
+\definesystemvariable {im} % InMarge
+\definesystemvariable {in} % INspringen
+\definesystemvariable {ip} % InsertPages
+\definesystemvariable {is} % Items
+\definesystemvariable {it} % stelInTerliniein
+\definesystemvariable {iv} % stelInvulLijnenin
+\definesystemvariable {ka} % KAntlijn
+\definesystemvariable {kd} % KaDerteksten
+\definesystemvariable {kj} % KopJes (floats)
+\definesystemvariable {kk} % Kapitalen
+\definesystemvariable {kl} % KoLommen
+\definesystemvariable {km} % KenMerk
+\definesystemvariable {ko} % KOp(pen)
+\definesystemvariable {kp} % KopPelteken
+\definesystemvariable {kr} % KoRps
+\definesystemvariable {ks} % KolomSpan
+\definesystemvariable {kt} % KonTakten
+\definesystemvariable {kw} % KontaktWaarde
+\definesystemvariable {la} % LAnguage
+\definesystemvariable {lb} % LaBels
+\definesystemvariable {ld} % LegenDa
+\definesystemvariable {le} % LinetablE
+\definesystemvariable {lf} % LocalFigures
+\definesystemvariable {lg} % taal (LanGuage)
+\definesystemvariable {li} % LIjst
+\definesystemvariable {lk} % LinK
+\definesystemvariable {ll} % Layers
+\definesystemvariable {lx} % LayerteXt
+\definesystemvariable {ln} % LijNen
+\definesystemvariable {lo} % LOgos
+\definesystemvariable {lt} % LiTeratuur
+\definesystemvariable {ls} % languageScript
+\definesystemvariable {ly} % LaYout
+\definesystemvariable {ma} % MargeAchtergrond
+\definesystemvariable {mb} % MargeBlokken
+\definesystemvariable {md} % MoDule
+\definesystemvariable {mg} % Metapost paGe
+\definesystemvariable {mh} % MultilingualHead
+\definesystemvariable {mk} % MarKering
+\definesystemvariable {ml} % MultilingualLabel
+\definesystemvariable {mm} % MultilingualMath
+\definesystemvariable {mt} % inline MaTh
+\definesystemvariable {mo} % Math Options
+\definesystemvariable {mp} % MetaPost
+\definesystemvariable {mx} % MatriX
+\definesystemvariable {ng} % parbuilders
+\definesystemvariable {nh} % new heads (structure)
+\definesystemvariable {nn} % structurenumbering
+\definesystemvariable {nm} % Nummering
+\definesystemvariable {np} % NaastPlaatsen
+\definesystemvariable {nr} % Nummeren
+\definesystemvariable {of} % OFfset
+\definesystemvariable {oi} % OmlijndInstellingen
+\definesystemvariable {ol} % OmLijnd
+\definesystemvariable {od} % Omlijnd Defaults (simple)
+\definesystemvariable {on} % ONderstreep
+\definesystemvariable {oo} % OpsOmmingen
+\definesystemvariable {op} % OPsomming
+\definesystemvariable {or} % OtpfilteR
+\definesystemvariable {os} % OffSet
+\definesystemvariable {ot} % OTpsequence
+\definesystemvariable {ov} % OVerlay
+\definesystemvariable {ox} % OffsetBox
+\definesystemvariable {pa} % PAlet
+\definesystemvariable {pb} % PuBlication
+\definesystemvariable {pc} % PageComment
+\definesystemvariable {pe} % PagEhandler
+\definesystemvariable {pf} % ProFiel
+\definesystemvariable {pg} % KoppelPagina
+\definesystemvariable {ph} % ParagrapH
+\definesystemvariable {pl} % PLaats
+\definesystemvariable {pn} % PaginaNummer
+\definesystemvariable {po} % PrOcessor
+\definesystemvariable {pp} % PaPier
+\definesystemvariable {pr} % PRogrammas
+\definesystemvariable {ps} % PoSitioneren
+\definesystemvariable {pt} % PageshifT
+\definesystemvariable {py} % PropertYs
+\definesystemvariable {pv} % PublicationVariable
+\definesystemvariable {ra} % RAise
+\definesystemvariable {rd} % RenDering
+\definesystemvariable {rf} % ReFereren
+\definesystemvariable {rg} % ReGel
+\definesystemvariable {rl} % ReferentieLijst
+\definesystemvariable {rn} % RegelNummer
+\definesystemvariable {ro} % ROteren
+\definesystemvariable {rr} % linenotes
+\definesystemvariable {rs} % RaSters
+\definesystemvariable {rt} % RoosTers
+\definesystemvariable {rv} % ReserVeerfiguur
+\definesystemvariable {rw} % RenderingWindow
+\definesystemvariable {sa} % ScAle
+\definesystemvariable {sb} % SectieBlok
+\definesystemvariable {sc} % SCherm
+\definesystemvariable {sd} % SounD
+\definesystemvariable {se} % SEctie
+\definesystemvariable {sf} % SpeciFics
+\definesystemvariable {sg} % SpacinG
+\definesystemvariable {sh} % ShapeText
+\definesystemvariable {si} % SplIt
+\definesystemvariable {sk} % SectieKop
+\definesystemvariable {sl} % SmalLer
+\definesystemvariable {sm} % SynonieMen
+\definesystemvariable {sn} % SubNummer
+\definesystemvariable {so} % SOrteren
+\definesystemvariable {sp} % SelecteerPapier
+\definesystemvariable {sr} % SpacehandleR
+\definesystemvariable {ss} % Symbool
+\definesystemvariable {st} % STickers
+\definesystemvariable {su} % SetUp
+\definesystemvariable {sv} % SysteemVariabelen
+\definesystemvariable {sw} % SectionWorld
+\definesystemvariable {sx} % Selector
+\definesystemvariable {sy} % SYnchronisatie
+\definesystemvariable {ta} % TAb
+\definesystemvariable {tb} % TekstBlokken
+\definesystemvariable {td} % TextbackgrounDs
+\definesystemvariable {te} % TEmplate
+\definesystemvariable {tf} % TypeFace
+\definesystemvariable {tg} % Tex paGe
+\definesystemvariable {ti} % TabelInstellingen
+\definesystemvariable {tk} % Teksten
+\definesystemvariable {tl} % TekstLijnen
+\definesystemvariable {tm} % TypesynonyM
+\definesystemvariable {tp} % TyPen
+\definesystemvariable {tx} % TeXtflow
+\definesystemvariable {to} % TOlerance
+\definesystemvariable {tr} % TRacer
+\definesystemvariable {ts} % TypeScript
+\definesystemvariable {tt} % TabulaTe
+\definesystemvariable {ty} % TYpe
+\definesystemvariable {uc} % Unicode
+\definesystemvariable {ui} % UItvoer
+\definesystemvariable {ur} % URl
+\definesystemvariable {up} % Utility Program
+\definesystemvariable {va} % VspAce
+\definesystemvariable {ve} % VErsie
+\definesystemvariable {vn} % VoetNoten
+\definesystemvariable {vs} % VSpacing
+\definesystemvariable {vt} % VerTical
+\definesystemvariable {wr} % WitRuimte
+\definesystemvariable {wl} % WordList
+\definesystemvariable {xf} % XML File
+\definesystemvariable {xl} % lxml (mkiv)
+\definesystemvariable {xm} % xml (mkiv)
+\definesystemvariable {xp} % XML Processing
+\definesystemvariable {xy} % schaal
+\definesystemvariable {za} % ZetspiegelAanpassing
+
+%D Next we define some language independant one letter
+%D variables and keywords.
+
+\defineinterfaceconstant {x} {x} % x offset
+\defineinterfaceconstant {y} {y} % y offset
+\defineinterfaceconstant {w} {w} % width
+\defineinterfaceconstant {h} {h} % height
+\defineinterfaceconstant {s} {s} % size
+\defineinterfaceconstant {t} {t} % title
+\defineinterfaceconstant {c} {c} % creator
+\defineinterfaceconstant {e} {e} % extension
+\defineinterfaceconstant {f} {f} % file
+
+\defineinterfaceconstant {a} {a} % kunnen weg
+\defineinterfaceconstant {b} {b} % kunnen weg
+\defineinterfaceconstant {c} {c} % kunnen weg
+\defineinterfaceconstant {d} {d} % kunnen weg
+\defineinterfaceconstant {e} {e} % kunnen weg
+
+\defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {r} {r}
+\defineinterfaceconstant {g} {g}
+\defineinterfaceconstant {b} {b}
+\defineinterfaceconstant {c} {c}
+\defineinterfaceconstant {m} {m}
+\defineinterfaceconstant {y} {y}
+\defineinterfaceconstant {k} {k}
+\defineinterfaceconstant {a} {a} % alternative
+\defineinterfaceconstant {t} {t} % transparency
+\defineinterfaceconstant {p} {p} % percentage
+
+\defineinterfaceconstant {t} {t}
+\defineinterfaceconstant {h} {h}
+\defineinterfaceconstant {b} {b}
+
+\defineinterfaceconstant {rgb} {rgb}
+\defineinterfacevariable {rgb} {rgb}
+
+\defineinterfaceconstant {cmyk} {cmyk}
+\defineinterfacevariable {cmyk} {cmyk}
+
+\defineinterfaceconstant {mp} {mp}
+\defineinterfacevariable {mp} {mp}
+
+\defineinterfacevariable {s} {s}
+
+\defineinterfacevariable {a} {a}
+\defineinterfacevariable {b} {b}
+\defineinterfacevariable {c} {c}
+\defineinterfacevariable {d} {d}
+
+%D Special purpose variables:
+
+\def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi}
+
+%D The names of files and their extensions are fixed.
+%D \CONTEXT\ uses as less files as possible. Utility files can
+%D be recognized by the first two characters of the extension:
+%D \type{tu}.
+
+\definefileconstant {utilityfilename} {texutil}
+
+\definefileconstant {blockextension} {tub}
+\definefileconstant {figureextension} {tuf}
+\definefileconstant {inputextension} {tui}
+\definefileconstant {outputextension} {tuo} % tup for previous run
+\definefileconstant {optionextension} {top}
+\definefileconstant {temporaryextension} {tmp}
+\definefileconstant {patternsextension} {pat}
+\definefileconstant {hyphensextension} {hyp}
+\definefileconstant {fontmapextension} {map}
+\definefileconstant {bibextension} {bbl}
+
+%D These files are loaded at start||up. They may contain system
+%D specific setups (or calls to other files), old macro's, to
+%D garantee compatibility and new macro's noy yet present in
+%D the format.
+
+\definefileconstant {errfilename} {cont-err}
+\definefileconstant {sysfilename} {cont-sys}
+\definefileconstant {oldfilename} {cont-old}
+\definefileconstant {newfilename} {cont-new}
+\definefileconstant {filfilename} {cont-fil}
+\definefileconstant {modfilename} {cont-mod}
+
+%D Handy for typescripts (we could use s! instead:
+
+\definetypescriptconstant {name} {name}
+\definetypescriptconstant {default} {default}
+\definetypescriptconstant {map} {map}
+\definetypescriptconstant {special} {special}
+\definetypescriptconstant {size} {size}
+
+%D The next two files specify user settings as well as
+%D \TEXEXEC\ settings when generating a format.
+
+\definefileconstant {usrfilename} {cont-usr} % .tex
+\definefileconstant {fmtfilename} {cont-fmt} % .tex
+
+%D The setup files for the language, font, color and special
+%D subsystems have a common prefix. This means that we have at
+%D most three characters for unique filenames.
+
+\definefileconstant {colorprefix} {colo-}
+\definefileconstant {encodingprefix} {enco-}
+\definefileconstant {filterprefix} {filt-}
+\definefileconstant {fontprefix} {font-}
+\definefileconstant {handlingprefix} {hand-}
+\definefileconstant {javascriptprefix} {java-}
+\definefileconstant {languageprefix} {lang-}
+\definefileconstant {mathprefix} {math-}
+\definefileconstant {metapostprefix} {meta-}
+\definefileconstant {regimeprefix} {regi-}
+\definefileconstant {specialprefix} {spec-}
+\definefileconstant {symbolprefix} {symb-}
+\definefileconstant {typeprefix} {type-}
+\definefileconstant {xtagprefix} {xtag-}
+\definefileconstant {propprefix} {prop-}
+\definefileconstant {unicprefix} {unic-}
+\definefileconstant {sortprefix} {sort-}
+\definefileconstant {prettyprefix} {pret-}
+
+\definefileconstant {moduleprefix} {m-}
+\definefileconstant {styleprefix} {s-}
+\definefileconstant {xstyleprefix} {x-}
+\definefileconstant {privateprefix} {p-}
+\definefileconstant {thirdprefix} {t-}
+
+%definefileconstant {beforeprefix} {b-}
+%definefileconstant {afterprefix} {a-}
+
+%D \CONTEXT\ follows different strategies for finding files.
+%D The macros that are responsible for this 'clever' searching
+%D make use of two (very important) path specifiers.
+
+\definefileconstant {pathseparator} {/}
+\definefileconstant {currentpath} {.}
+\definefileconstant {parentpath} {..}
+
+%D The way fonts are defined and called upon is language
+%D independant. We follow the scheme laid down by Knuth in
+%D Plain \TEX. We'll explain their meaning later.
+
+\defineinterfaceconstant {tf} {tf}
+\defineinterfaceconstant {bf} {bf}
+\defineinterfaceconstant {bs} {bs}
+\defineinterfaceconstant {bi} {bi}
+\defineinterfaceconstant {sl} {sl}
+\defineinterfaceconstant {it} {it}
+\defineinterfaceconstant {sc} {sc}
+\defineinterfaceconstant {rm} {rm}
+\defineinterfaceconstant {ss} {ss}
+\defineinterfaceconstant {tt} {tt}
+\defineinterfaceconstant {hw} {hw}
+\defineinterfaceconstant {cg} {cg}
+\defineinterfaceconstant {os} {os}
+\defineinterfaceconstant {mm} {mm}
+\defineinterfaceconstant {i} {i}
+\defineinterfaceconstant {nn} {nn}
+
+\defineinterfaceconstant {x} {x}
+\defineinterfaceconstant {xx} {xx}
+
+\defineinterfaceconstant {em} {em}
+
+\defineinterfaceconstant {mi} {mi}
+\defineinterfaceconstant {sy} {sy}
+\defineinterfaceconstant {ex} {ex}
+\defineinterfaceconstant {mr} {mr}
+
+\defineinterfaceconstant {ma} {ma}
+\defineinterfaceconstant {mb} {mb}
+\defineinterfaceconstant {mc} {mc}
+
+%D For figure inclusion we need:
+
+\defineinterfaceconstant {tif} {tif}
+\defineinterfaceconstant {eps} {eps}
+\defineinterfaceconstant {mps} {mps}
+\defineinterfaceconstant {jpg} {jpg}
+\defineinterfaceconstant {pdf} {pdf}
+\defineinterfaceconstant {png} {png}
+\defineinterfaceconstant {avi} {avi}
+\defineinterfaceconstant {mov} {mov}
+\defineinterfaceconstant {svg} {svg}
+\defineinterfaceconstant {tex} {tex}
+\defineinterfaceconstant {tmp} {tmp}
+
+%D A careful reader will have noticed that in the module
+%D \type{mult-ini} we defined \type{\selectinterface}. We were
+%D not yet able to actually select an interface, because we
+%D still had to define the constants and variables. Now we've
+%D done so, selection is permitted.
+
+\selectinterface
+
+%D Ok, here are some more, because we've got ouselves some
+%D extensions to \CONTEXT.
+
+\definemessageconstant {addresses}
+\definemessageconstant {documents}
+
+\protect
+
+\endinput
diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua
new file mode 100644
index 000000000..9ed71fd72
--- /dev/null
+++ b/tex/context/base/node-aux.lua
@@ -0,0 +1,145 @@
+if not modules then modules = { } end modules ['node-aux'] = {
+ version = 1.001,
+ comment = "companion to node-spl.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local gsub, format = string.gsub, string.format
+
+local free_node = node.free
+local hpack_nodes = node.hpack
+local node_fields = node.fields
+
+function nodes.repack_hlist(list,...)
+ local temp, b = hpack_nodes(list,...)
+ list = temp.list
+ temp.list = nil
+ free_node(temp)
+ return list, b
+end
+
+function nodes.merge(a,b)
+ if a and b then
+ local t = node.fields(a.id)
+ for i=3,#t do
+ local name = t[i]
+ a[name] = b[name]
+ end
+ end
+ return a, b
+end
+
+local fields, whatsitfields = { }, { }
+
+for k, v in next, node.types() do
+ if v == "whatsit" then
+ fields[k], fields[v] = { }, { }
+ for kk, vv in next, node.whatsits() do
+ local f = node_fields(k,kk)
+ whatsitfields[kk], whatsitfields[vv] = f, f
+ end
+ else
+ local f = node_fields(k)
+ fields[k], fields[v] = f, f
+ end
+end
+
+nodes.fields, nodes.whatsitfields = fields, whatsitfields
+
+function nodes.info(n)
+ local id = n.id
+ local tp = node.type(id)
+ local list = (tp == "whatsit" and whatsitfields[n.subtype]) or fields[id]
+ logs.report(format("%14s","type"),tp)
+ for k,v in next, list do
+ logs.report(format("%14s",v),gsub(gsub(tostring(n[v]),"%s+"," "),"node ",""))
+ end
+end
+
+-- history:
+--
+-- local function cp_skipable(a,id) -- skipable nodes at the margins during character protrusion
+-- return (
+-- id ~= glyph_node
+-- or id == ins_node
+-- or id == mark_node
+-- or id == adjust_node
+-- or id == penalty_node
+-- or (id == glue_node and a.spec.writable)
+-- or (id == disc_node and a.pre == nil and a.post == nil and a.replace == nil)
+-- or (id == math_node and a.surround == 0)
+-- or (id == kern_node and (a.kern == 0 or a.subtype == NORMAL))
+-- or (id == hlist_node and a.width == 0 and a.height == 0 and a.depth == 0 and a.list == nil)
+-- or (id == whatsit_node and a.subtype ~= pdf_refximage_node and a.subtype ~= pdf_refxform_node)
+-- )
+-- end
+--
+-- local function glyph_width(a)
+-- local ch = chardata[a.font][a.char]
+-- return (ch and ch.width) or 0
+-- end
+--
+-- local function glyph_total(a)
+-- local ch = chardata[a.font][a.char]
+-- return (ch and (ch.height+ch.depth)) or 0
+-- end
+--
+-- local function non_discardable(a) -- inline
+-- return a.id < math_node -- brrrr
+-- end
+--
+-- local function calculate_badness(t,s)
+-- if t == 0 then
+-- return 0
+-- elseif s <= 0 then
+-- return INF_BAD
+-- else
+-- local r
+-- if t <= 7230584 then
+-- r = t * 297 / s
+-- elseif s >= 1663497 then
+-- r = t / floor(s / 297)
+-- else
+-- r = t
+-- end
+-- r = floor(r)
+-- if r > 1290 then
+-- return INF_BAD
+-- else
+-- return floor((r * r * r + 0x20000) / 0x40000) -- 0400000 / 01000000
+-- end
+-- end
+-- end
+--
+-- left-overs
+--
+-- local function round_xn_over_d(x, n, d)
+-- local positive -- was x >= 0
+-- if x >= 0 then
+-- positive = true
+-- else
+-- x = -x
+-- positive = false
+-- end
+-- local t = floor(x % 0x8000) * n -- 0100000
+-- local f = floor(t / 0x8000) -- 0100000
+-- local u = floor(x / 0x8000) * n + f -- 0100000
+-- local v = floor(u % d) * 0x8000 + f -- 0100000
+-- if floor(u / d) >= 0x8000 then -- 0100000
+-- logs.error("parbuilder",'arith_error')
+-- else
+-- u = 0x8000 * floor(u / d) + floor(v / d) -- 0100000
+-- end
+-- v = floor(v % d)
+-- if 2*v >= d then
+-- u = u + 1
+-- end
+-- if positive then
+-- return u
+-- else
+-- return -u
+-- end
+-- end
+
diff --git a/tex/context/base/node-bck.lua b/tex/context/base/node-bck.lua
new file mode 100644
index 000000000..94fbac85f
--- /dev/null
+++ b/tex/context/base/node-bck.lua
@@ -0,0 +1,119 @@
+if not modules then modules = { } end modules ['node-bck'] = {
+ version = 1.001,
+ comment = "companion to node-bck.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- beware, this one takes quite some runtime, so we need a status flag
+-- maybe some page related state
+
+local hlist = node.id("hlist")
+local vlist = node.id("vlist")
+
+local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local traverse = node.traverse
+
+local new_rule = nodes.rule
+local new_glue = nodes.glue
+
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+local a_background = attributes.private('background')
+
+local function add_backgrounds(head) -- boxes, inline will be done too
+ local id = head.id
+ if id == vlist or id == hlist then
+ local current = head.list
+ while current do
+ local id = current.id
+ if id == hlist then -- and current.list
+ local background = has_attribute(current,a_background)
+ if background then
+ -- direct to hbox
+ -- colorspace is already set so we can omit that and stick to color
+ local mode = has_attribute(current,a_colorspace)
+ if mode then
+ local glue = new_glue(-current.width)
+ local rule = new_rule(current.width,current.height,current.depth)
+ local color = has_attribute(current,a_color)
+ local transparency = has_attribute(current,a_transparency)
+ set_attribute(rule,a_colorspace, mode)
+ if color then
+ set_attribute(rule,a_color, color)
+ end
+ if transparency then
+ set_attribute(rule,a_transparency,transparency)
+ end
+ rule.next = glue
+ glue.next = current.list
+ current.list = rule
+ end
+ else
+ -- temporary hack for aligments
+ local list, background, found = current.list, nil, nil
+ for l in traverse(list) do
+ background = has_attribute(l,a_background)
+ if background then
+ found = l
+ break
+ end
+ end
+ if background then
+ local mode = has_attribute(found,a_colorspace)
+ if mode then
+ local glue = new_glue(-current.width)
+ local rule = new_rule(current.width,current.height,current.depth)
+ local color = has_attribute(found,a_color)
+ local transparency = has_attribute(found,a_transparency)
+ set_attribute(rule,a_colorspace, mode)
+ if color then
+ set_attribute(rule,a_color, color)
+ end
+ if transparency then
+ set_attribute(rule,a_transparency,transparency)
+ end
+ rule.next = glue
+ glue.next = list
+ current.list = rule
+ end
+ else
+ add_backgrounds(current)
+ end
+ end
+ elseif id == vlist then -- and current.list
+ -- direct to vbox
+ local background = has_attribute(current,a_background)
+ if background then
+ local mode = has_attribute(current,a_colorspace)
+ if mode then
+ local glue = new_glue(-current.height-current.depth)
+ local rule = new_rule(current.width,current.height,current.depth)
+ local color = has_attribute(current,a_color)
+ local transparency = has_attribute(current,a_transparency)
+ set_attribute(rule,a_colorspace, mode)
+ if color then
+ set_attribute(rule,a_color, color)
+ end
+ if transparency then
+ set_attribute(rule,a_transparency,transparency)
+ end
+ rule.next = glue
+ glue.next = current.list
+ current.list = rule
+ end
+ end
+ add_backgrounds(current)
+ end
+ current = current.next
+ end
+ end
+ return head, true
+end
+
+nodes.add_backgrounds = add_backgrounds
+
+tasks.appendaction("shipouts","normalizers","nodes.add_backgrounds")
diff --git a/tex/context/base/node-bck.mkiv b/tex/context/base/node-bck.mkiv
new file mode 100644
index 000000000..41a6da2cb
--- /dev/null
+++ b/tex/context/base/node-bck.mkiv
@@ -0,0 +1,163 @@
+%D \module
+%D [ file=node-bck,
+%D version=2009.06.08,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Node Support / Backgrounds}
+
+%D This is first attempt to replacing backgrounds in a few
+%D tables mechanisms.
+
+\unprotect
+
+\registerctxluafile{node-bck}{1.001}
+
+%D Box helpers:
+
+\def\doaddbackgroundtobox#1[#2]%
+ {\begingroup\faststartcolor[#2]%
+ \normalexpanded{\noexpand\faststopcolor\endgroup#1
+ attr \backgroundattribute \plusone
+ attr \colormodelattribute \the\attribute\colormodelattribute
+ attr \colorattribute \the\attribute\colorattribute
+ attr \transparencyattribute \the\attribute\transparencyattribute}}
+
+\def\backgroundvbox{\doaddbackgroundtobox\vbox}
+\def\backgroundvtop{\doaddbackgroundtobox\vtop}
+\def\backgroundhbox{\doaddbackgroundtobox\hbox}
+
+\def\colorattr#1%
+ {\ifcsname(cs:\currentpalet#1)\endcsname
+ \thecolorattr{\currentpalet#1}%
+ \else\ifcsname(cs:#1)\endcsname
+ \thecolorattr{#1}%
+ \fi\fi}
+
+\def\thecolorattr#1%
+ {attr \colormodelattribute \attribute\colormodelattribute
+ attr \colorattribute \csname(cs:#1)\endcsname
+ attr \transparencyattribute \csname(ts:#1)\endcsname}
+
+\def\backgroundcolorattr#1%
+ {\ifcsname(cs:\currentpalet#1)\endcsname
+ \thebackgroundcolorattr{\currentpalet#1}%
+ \else\ifcsname(cs:#1)\endcsname
+ \thebackgroundcolorattr{#1}%
+ \fi\fi}
+
+\def\thebackgroundcolorattr#1%
+ {attr \backgroundattribute \plusone
+ attr \colormodelattribute \attribute\colormodelattribute
+ attr \colorattribute \csname(cs:#1)\endcsname
+ attr \transparencyattribute \csname(ts:#1)\endcsname}
+
+% \def\backgroundvbox[#1]{\vbox \backgroundcolorattr{#1}}
+% \def\backgroundvtop[#1]{\vtop \backgroundcolorattr{#1}}
+% \def\backgroundhbox[#1]{\hbox \backgroundcolorattr{#1}}
+
+%D tabulate:
+
+\def\tabulatenormalcolumn#1%
+ {\doiffastoptionalcheckelse{\tabulatenormalcolumnyes#1}{\tabulatenormalcolumnnop#1}}
+
+\def\tabulatenormalcolumnnop#1% overloads anch-pgr
+ {&\iftabulateequal\tabulateequalpos\else\tabulatenormalpos\fi&\global\chardef\tabulatetype#1&}
+
+\def\tabulatenormalcolumnyes#1[#2]%
+ {&\iftabulateequal\tabulateequalpos\else\tabulatenormalpos\fi&\global\chardef\tabulatetype#1&%
+ \iftrialtypesetting\else\settabulatecolor{#2}\fi\ignorespaces}
+
+\newcount\maxtabularcolorcolumn
+
+\def\settabulatecolor#1% we could store the attributes at the cost of a lua call
+ {\begingroup
+ \global\settrue\tabulatehascolors
+ \ifnum\tabulatecolumn>\maxtabularcolorcolumn
+ \global\maxtabularcolorcolumn\tabulatecolumn
+ \fi
+ \setxvalue{\??tt:c:\the\tabulatecolumn}{#1}%
+ \attribute\backgroundattribute\plusone
+ \faststartcolor[#1]\strut\char0\faststopcolor
+ \endgroup}
+
+\def\repeatsettabulatecolor
+ {\begingroup
+ \ifcsname\??tt:c:\the\tabulatecolumn\endcsname
+ \attribute\backgroundattribute\plusone
+ \faststartcolor[\csname\??tt:c:\the\tabulatecolumn\endcsname]\strut\char0\faststopcolor
+ \fi
+ \endgroup}
+
+\def\resettabulatecolors
+ {\ifcase\maxtabularcolorcolumn\else
+ \doresettabulatecolors
+ \fi}
+
+\def\doresettabulatecolors
+ {\dorecurse\maxtabularcolorcolumn{\letgvalue{\??tt:c:\recurselevel}\undefined}} % slow
+
+\appendtoks
+ \resettabulatecolors
+\to \everyaftertabulaterow
+
+\def\splitofftabulatebox % overloads in anch-pgr
+ {\dontcomplain
+ \global\setbox\tabulatebox % % % global ? % % %
+ \vsplit\tablebox\tabulatecolumn to \lineheight
+ \setbox\tabulatebox\normalvbox
+ {\unvbox\tabulatebox}%
+ \setbox\tabulatebox\hbox to \wd\tabulatebox
+ {\iftrialtypesetting\else\ifconditional\tabulatehascolors\repeatsettabulatecolor\fi\fi
+ \hss\dotabulatehook{\box\tabulatebox}\hss}%
+ \ht\tabulatebox\strutht
+ \dp\tabulatebox\strutdp
+ \box\tabulatebox
+ \iftrialtypesetting\else\ifconditional\tablehaspositions\doflushtabulateepos\fi\fi}
+
+\appendtoks
+ \global\setfalse\tabulatehascolors
+\to \everytabulate
+
+\protect \endinput
+
+% test
+
+\starttext
+
+\backgroundvbox[green] {\input tufte } \par
+\backgroundvbox[blue] {\input ward } \par
+\backgroundvbox[red] {\input knuth } \par
+\backgroundhbox[yellow]{\rotate[rotation=45]{hello world}} \par
+
+\starttabulate[||p||]
+\NC test \NC test \NC test \NC \NR
+\NC test \NC[green] \input tufte \NC[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
+\NC[blue] test \NC[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 \NC[gray] test \NC \NR
+\NC test \NC test \NC test \NC \NR
+\NC test \NC test \NC test \NC \NR
+\NC[blue] test \NC test \NC test \NC \NR
+\NC test \NC test \NC test \NC \NR
+\NC test \NC test \NC[magenta] test \NC \NR
+\NC test \NC test \NC test \NC \NR
+\NC test \NC[cyan] \dorecurse{10}{\input ward }\NC test \NC \NR
+\NC test \NC test \NC test \NC \NR
+\NC test \NC[yellow] test \NC test \NC \NR
+\stoptabulate
+
+\stoptext
diff --git a/tex/context/base/node-dir.lua b/tex/context/base/node-dir.lua
new file mode 100644
index 000000000..05e4835e5
--- /dev/null
+++ b/tex/context/base/node-dir.lua
@@ -0,0 +1,308 @@
+if not modules then modules = { } end modules ['node-mir'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Taco Hoekwater and Hans Hagen",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[
+
Serializing nodes can be handy for tracing. Also, saving and
+loading node lists can come in handy as soon we are going to
+use external applications to process node lists.
+--ldx]]--
+
+function nodes.show(stack)
+-- texio.write_nl(table.serialize(stack))
+end
+
+function nodes.save(stack,name) -- *.ltn : luatex node file
+-- if name then
+-- file.savedata(name,table.serialize(stack))
+-- else
+-- texio.write_nl('log',table.serialize(stack))
+-- end
+end
+
+function nodes.load(name)
+-- return file.loaddata(name)
+-- -- todo
+end
diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua
new file mode 100644
index 000000000..c6e3be448
--- /dev/null
+++ b/tex/context/base/node-fin.lua
@@ -0,0 +1,442 @@
+if not modules then modules = { } end modules ['node-fin'] = {
+ version = 1.001,
+ comment = "companion to node-fin.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this module is being reconstructed
+
+local next, type, format = next, type, string.format
+local texsprint = tex.sprint
+
+local ctxcatcodes = tex.ctxcatcodes
+
+local glyph = node.id('glyph')
+local glue = node.id('glue')
+local rule = node.id('rule')
+local whatsit = node.id('whatsit')
+local hlist = node.id('hlist')
+local vlist = node.id('vlist')
+
+local has_attribute = node.has_attribute
+local copy_node = node.copy
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+states = states or { }
+shipouts = shipouts or { }
+
+local numbers = attributes.numbers
+local trigger = attributes.private('trigger')
+local triggering = false
+
+-- these two will be like trackers
+
+function states.enabletriggering()
+ triggering = true
+end
+function states.disabletriggering()
+ triggering = false
+end
+
+-- the following code is no longer needed due to the new backend
+-- but we keep it around for a while as an example
+--
+-- states.collected = states.collected or { }
+--
+-- storage.register("states/collected", states.collected, "states.collected")
+--
+-- local collected = states.collected
+--
+-- function states.collect(str)
+-- collected[#collected+1] = str
+-- end
+--
+-- function states.flush()
+-- if #collected > 0 then
+-- for i=1,#collected do
+-- texsprint(ctxcatcodes,collected[i]) -- we're in context mode anyway
+-- end
+-- collected = { }
+-- states.collected = collected
+-- end
+-- end
+--
+-- function states.check()
+-- texio.write_nl(concat(collected,"\n"))
+-- end
+
+-- we used to do the main processor loop here and call processor for each node
+-- but eventually this was too much a slow down (1 sec on 23 for 120 pages mk)
+-- so that we moved looping to the processor itself; this may lead to a bit of
+-- duplicate code once that we have more state handlers
+
+local function process_attribute(head,plugin) -- head,attribute,enabled,initializer,resolver,processor,finalizer
+ local namespace = plugin.namespace
+ if namespace.enabled ~= false then -- this test will go away
+ starttiming(attributes)
+ local done, used, ok = false, nil, false
+ local attribute = namespace.attribute or numbers[plugin.name] -- todo: plugin.attribute
+ local processor = plugin.processor
+ if processor then
+ local initializer = plugin.initializer
+ local resolver = plugin.resolver
+ local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip !
+ if initializer then
+ initializer(namespace,attribute,head)
+ end
+ head, ok = processor(namespace,attribute,head,inheritance)
+ if ok then
+ local finalizer = plugin.finalizer
+ if finalizer then
+ head, ok, used = finalizer(namespace,attribute,head)
+ if used then
+ local flusher = plugin.flusher
+ if flusher then
+ head = flusher(namespace,attribute,head,used)
+ end
+ end
+ end
+ done = true
+ end
+ end
+ stoptiming(attributes)
+ return head, done
+ else
+ return head, false
+ end
+end
+
+nodes.process_attribute = process_attribute
+
+function nodes.install_attribute_handler(plugin) -- we need to avoid this nested function
+ return function(head)
+ return process_attribute(head,plugin)
+ end
+end
+
+--~ experiment (maybe local to function makes more sense)
+--~
+--~ plugindata = { }
+--~
+--~ local template = [[
+--~ local plugin = plugindata["%s"]
+--~ local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+--~ local namespace = plugin.namespace
+--~ local attribute = namespace.attribute
+--~ local processor = plugin.processor
+--~ local initializer = plugin.initializer
+--~ local resolver = plugin.resolver
+--~ local finalizer = plugin.finalizer
+--~ local flusher = plugin.flusher
+--~ return function (head)
+--~ if namespace.enabled then
+--~ starttiming(attributes)
+--~ local done, used, ok = false, nil, false
+--~ if procesxsor then
+--~ local inheritance = (resolver and resolver()) or nil -- -0x7FFFFFFF -- we can best use nil and skip !
+--~ if initializer then
+--~ initializer(namespace,attribute,head)
+--~ end
+--~ head, ok = processor(namespace,attribute,head,inheritance)
+--~ if ok then
+--~ if finalizer then
+--~ head, ok, used = finalizer(namespace,attribute,head)
+--~ if used and flusher then
+--~ head = flusher(namespace,attribute,head,used)
+--~ end
+--~ end
+--~ done = true
+--~ end
+--~ end
+--~ stoptiming(attributes)
+--~ return head, done
+--~ else
+--~ return head, false
+--~ end
+--~ end
+--~ ]]
+--~
+--~ function nodes.install_attribute_handler(plugin) -- we need to avoid this nested function
+--~ plugindata[plugin.name] = plugin
+--~ local str = format(template,plugin.name)
+--~ return loadstring(str)()
+--~ end
+
+-- the injectors
+
+local insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+
+local nsdata, nsdone, nsforced, nsselector, nstrigger
+local current, current_selector, done = 0, 0, false -- nb, stack has a local current !
+
+function states.initialize(namespace,attribute,head)
+ nsdata, nsnone = namespace.data, namespace.none
+ nsforced, nsselector, nslistwise = namespace.forced, namespace.selector, namespace.listwise
+ nstrigger = triggering and namespace.triggering and trigger
+ current, current_selector, done = 0, 0, false -- todo: done cleanup
+end
+
+function states.finalize(namespace,attribute,head) -- is this one ok?
+ if current > 0 and nsnone then
+ local id = head.id
+ if id == hlist or id == vlist then
+ local list = head.list
+ if list then
+ head.list = insert_node_before(list,list,copy_node(nsnone))
+ end
+ else
+ head = insert_node_before(head,head,copy_node(nsnone))
+ end
+ return head, true, true
+ end
+ return head, false, false
+end
+
+local function process(namespace,attribute,head,inheritance,default) -- one attribute
+ local stack, done = head, false
+ while stack do
+ local id = stack.id
+ -- we need to deal with literals too (reset as well as oval)
+ -- if id == glyph or (id == whatsit and stack.subtype == 8) or (id == rule and stack.width ~= 0) or (id == glue and stack.leader) then -- or disc
+ if id == glyph or (id == rule and stack.width ~= 0) or (id == glue and stack.leader) then -- or disc
+ local c = has_attribute(stack,attribute)
+ if c then
+ if default and c == inheritance then
+ if current ~= default then
+ head = insert_node_before(head,stack,copy_node(nsdata[default]))
+ current, done = default, true
+ end
+ elseif current ~= c then
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ current, done = c, true
+ end
+ -- here ? compare selective
+ if id == glue then --leader
+ -- same as *list
+ local content = stack.leader
+ if content then
+ local savedcurrent = current
+ local ci = content.id
+ if ci == hlist or ci == vlist then
+ -- else we reset inside a box unneeded, okay, the downside is
+ -- that we trigger color in each repeated box, so there is room
+ -- for improvement here
+ current = 0
+ end
+ local ok = false
+ if nstrigger and has_attribute(stack,nstrigger) then
+ local outer = has_attribute(stack,attribute)
+ if outer ~= inheritance then
+ stack.leader, ok = process(namespace,attribute,content,inheritance,outer)
+ else
+ stack.leader, ok = process(namespace,attribute,content,inheritance,default)
+ end
+ else
+ stack.leader, ok = process(namespace,attribute,content,inheritance,default)
+ end
+ current = savedcurrent
+ done = done or ok
+ end
+ end
+ elseif default and inheritance then
+ if current ~= default then
+ head = insert_node_before(head,stack,copy_node(nsdata[default]))
+ current, done = default, true
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current, done = 0, true
+ end
+ elseif id == hlist or id == vlist then
+ local content = stack.list
+ if content then
+ local ok = false
+ if nstrigger and has_attribute(stack,nstrigger) then
+ local outer = has_attribute(stack,attribute)
+ if outer ~= inheritance then
+ stack.list, ok = process(namespace,attribute,content,inheritance,outer)
+ else
+ stack.list, ok = process(namespace,attribute,content,inheritance,default)
+ end
+ else
+ stack.list, ok = process(namespace,attribute,content,inheritance,default)
+ end
+ done = done or ok
+ end
+ end
+ stack = stack.next
+ end
+ return head, done
+end
+
+states.process = process
+
+-- we can force a selector, e.g. document wide color spaces, saves a little
+-- watch out, we need to check both the selector state (like colorspace) and
+-- the main state (like color), otherwise we get into troubles when a selector
+-- state changes while the main state stays the same (like two glyphs following
+-- each other with the same color but different color spaces e.g. \showcolor)
+
+local function selective(namespace,attribute,head,inheritance,default) -- two attributes
+ local stack, done = head, false
+ while stack do
+ local id = stack.id
+ -- we need to deal with literals too (reset as well as oval)
+ -- if id == glyph or (id == whatsit and stack.subtype == 8) or (id == rule and stack.width ~= 0) or (id == glue and stack.leader) then -- or disc
+ if id == glyph or (id == rule and stack.width ~= 0) or (id == glue and stack.leader) then -- or disc
+ local c = has_attribute(stack,attribute)
+ if c then
+ if default and c == inheritance then
+ if current ~= default then
+ local data = nsdata[default]
+ head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+ current, done = default, true
+ end
+ else
+ local s = has_attribute(stack,nsselector)
+ if current ~= c or current_selector ~= s then
+ local data = nsdata[c]
+ head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+ current, current_selector, done = c, s, true
+ end
+ end
+ elseif default and inheritance then
+ if current ~= default then
+ local data = nsdata[default]
+ head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+ current, done = default, true
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current, current_selector, done = 0, 0, true
+ end
+ if id == glue then -- leader
+ -- same as *list
+ local content = stack.leader
+ if content then
+ local savedcurrent = current
+ local ci = content.id
+ if ci == hlist or ci == vlist then
+ -- else we reset inside a box unneeded, okay, the downside is
+ -- that we trigger color in each repeated box, so there is room
+ -- for improvement here
+ current = 0
+ end
+ local ok = false
+ if nstrigger and has_attribute(stack,nstrigger) then
+ local outer = has_attribute(stack,attribute)
+ if outer ~= inheritance then
+ stack.leader, ok = selective(namespace,attribute,content,inheritance,outer)
+ else
+ stack.leader, ok = selective(namespace,attribute,content,inheritance,default)
+ end
+ else
+ stack.leader, ok = selective(namespace,attribute,content,inheritance,default)
+ end
+ current = savedcurrent
+ done = done or ok
+ end
+ end
+ elseif id == hlist or id == vlist then
+ local content = stack.list
+ if content then
+ local ok = false
+ if nstrigger and has_attribute(stack,nstrigger) then
+ local outer = has_attribute(stack,attribute)
+ if outer ~= inheritance then
+ stack.list, ok = selective(namespace,attribute,content,inheritance,outer)
+ else
+ stack.list, ok = selective(namespace,attribute,content,inheritance,default)
+ end
+ else
+ stack.list, ok = selective(namespace,attribute,content,inheritance,default)
+ end
+ done = done or ok
+ end
+ end
+ stack = stack.next
+ end
+ return head, done
+end
+
+states.selective = selective
+
+-- Ideally the next one should be merged with the previous but keeping it separate is
+-- safer. We deal with two situations: efficient boxwise (layoutareas) and mixed layers
+-- (as used in the stepper). In the stepper we cannot use the box branch as it involves
+-- paragraph lines and then getsmixed up. A messy business (esp since we want to be
+-- efficient).
+
+local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
+ local stack, done = head, false
+ local current, depth = default or 0, 0
+ while stack do
+ local id = stack.id
+ if id == glyph or (id == rule and stack.width ~= 0) or (id == glue and stack.leader) then -- or disc
+ local c = has_attribute(stack,attribute)
+ if c then
+ if current ~= c then
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ depth = depth + 1
+ current, done = c, true
+ end
+ if id == glue then
+ local content = stack.leader
+ if content then -- unchecked
+ local ok = false
+ stack.leader, ok = stacked(namespace,attribute,content,current)
+ done = done or ok
+ end
+ end
+ elseif default then
+ --
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ depth = depth - 1
+ current, done = 0, true
+ end
+ elseif id == hlist or id == vlist then
+ local content = stack.list
+ if content then
+ -- the problem is that broken lines gets the attribute which can be a later one
+ if nslistwise then
+ local c = has_attribute(stack,attribute)
+ if c and current ~= c and nslistwise[c] then -- viewerlayer
+ local p = current
+ current, done = c, true
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ stack.list = stacked(namespace,attribute,content,current)
+ head, stack = insert_node_after(head,stack,copy_node(nsnone))
+ current = p
+ else
+ local ok = false
+ stack.list, ok = stacked(namespace,attribute,content,current)
+ done = done or ok
+ end
+ else
+ local ok = false
+ stack.list, ok = stacked(namespace,attribute,content,current)
+ done = done or ok
+ end
+ end
+ end
+ stack = stack.next
+ end
+ while depth > 0 do
+ head = insert_node_after(head,stack,copy_node(nsnone))
+ depth = depth -1
+ end
+ return head, done
+end
+
+states.stacked = stacked
+
+-- -- --
+
+statistics.register("attribute processing time", function()
+ return statistics.elapsedseconds(attributes,"front- and backend")
+end)
diff --git a/tex/context/base/node-fin.mkiv b/tex/context/base/node-fin.mkiv
new file mode 100644
index 000000000..ea9e83f16
--- /dev/null
+++ b/tex/context/base/node-fin.mkiv
@@ -0,0 +1,74 @@
+%D \module
+%D [ file=attr-ini,
+%D version=2007.06.06, % probably a bit older
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Finalizing,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 Node Support / Finalizing}
+
+% Objects are processed indepently \unknown\ actually we may
+% need a proper callback.
+
+\unprotect
+
+\registerctxluafile{node-fin}{1.001} % we might generalize this one
+
+\definesystemattribute[trigger] \chardef\triggerattribute \dogetattributeid{trigger} % feature inheritance
+
+\def\finalizeobjectbox #1{\ctxlua{nodes.process_page(tex.box[\number#1])}}
+\def\finalizeshipoutbox#1{\ctxlua{nodes.process_page(tex.box[\number#1])}}
+
+% tricky stuff:
+
+% THIS MIGHT BECOME OBSOLETE.
+
+\newcount\attributeboxcount
+
+\edef\startinheritattributes{\attribute\triggerattribute\plusone}
+\edef\stopinheritattributes {\attribute\triggerattribute\attributeunsetvalue}
+
+\def\doattributedcopy{\afterassignment\dodoattributedcopy\attributeboxcount}
+\def\doattributedbox {\afterassignment\dodoattributedbox \attributeboxcount}
+
+\def\dodoattributedcopy
+ {\startinheritattributes
+ \ifvbox\attributeboxcount
+ \vbox{\unvcopy\attributeboxcount}%
+ \else
+ \hbox{\unhcopy\attributeboxcount}%
+ \fi
+ \stopinheritattributes}
+
+\def\dodoattributedbox
+ {\startinheritattributes
+ \ifvbox\attributeboxcount
+ \vbox{\unvbox\attributeboxcount}%
+ \else
+ \hbox{\unhbox\attributeboxcount}%
+ \fi
+ \stopinheritattributes}
+
+\def\enableattributeinheritance
+ {\ctxlua{states.enabletriggering()}%
+ \let\attributedcopy\doattributedcopy
+ \let\attributedbox \doattributedbox}
+
+\def\disableattributeinheritance
+ {\ctxlua{states.disabletriggering()}%
+ \let\attributedcopy\copy
+ \let\attributedbox \box}
+
+\disableattributeinheritance
+
+% \appendtoks
+% \enableattributeinheritance % will become default
+% \to\everyjob
+
+\protect \endinput
diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua
new file mode 100644
index 000000000..b0d073425
--- /dev/null
+++ b/tex/context/base/node-fnt.lua
@@ -0,0 +1,207 @@
+if not modules then modules = { } end modules ['node-fnt'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+
+local trace_characters = false trackers.register("nodes.characters", function(v) trace_characters = v end)
+
+local glyph = node.id('glyph')
+
+local traverse_id = node.traverse_id
+local has_attribute = node.has_attribute
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+fonts = fonts or { }
+fonts.tfm = fonts.tfm or { }
+fonts.ids = fonts.ids or { }
+
+local fontdata = fonts.ids
+
+-- some tests with using an array of dynamics[id] and processes[id] demonstrated
+-- that there was nothing to gain (unless we also optimize other parts)
+--
+-- maybe getting rid of the intermediate shared can save some time
+
+-- potential speedup: check for subtype < 256 so that we can remove that test
+-- elsewhere, danger: injected nodes will not be dealt with but that does not
+-- happen often; we could consider processing sublists but that might need mor
+-- checking later on; the current approach also permits variants
+
+if tex.attribute[0] < 0 then
+
+ texio.write_nl("log","!")
+ texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
+ texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
+ texio.write_nl("log","! purposed so setting them at the TeX end might break the font handler.")
+ texio.write_nl("log","!")
+
+ tex.attribute[0] = 0 -- else no features
+
+end
+
+-- this will be redone and split in a generic one and a context one
+
+function nodes.process_characters(head)
+ -- either next or not, but definitely no already processed list
+ starttiming(nodes)
+ local usedfonts, attrfonts, done = { }, { }, false
+ local a, u, prevfont, prevattr = 0, 0, nil, 0
+ for n in traverse_id(glyph,head) do
+ local font, attr = n.font, has_attribute(n,0) -- zero attribute is reserved for fonts in context
+ if attr and attr > 0 then
+ if font ~= prevfont or attr ~= prevattr then
+ local used = attrfonts[font]
+ if not used then
+ used = { }
+ attrfonts[font] = used
+ end
+ if not used[attr] then
+ -- we do some testing outside the function
+ local tfmdata = fontdata[font]
+ local shared = tfmdata.shared
+ if shared then
+ local dynamics = shared.dynamics
+ if dynamics then
+ local d = shared.set_dynamics(font,dynamics,attr) -- still valid?
+ if d then
+ used[attr] = d
+ a = a + 1
+ end
+ end
+ end
+ end
+ prevfont, prevattr = font, attr
+ end
+ elseif font ~= prevfont then
+ prevfont, prevattr = font, 0
+ local used = usedfonts[font]
+ if not used then
+ local tfmdata = fontdata[font]
+ if tfmdata then
+ local shared = tfmdata.shared -- we need to check shared, only when same features
+ if shared then
+ local processors = shared.processes
+ if processors and #processors > 0 then
+ usedfonts[font] = processors
+ u = u + 1
+ end
+ end
+ else
+ -- probably nullfont
+ end
+ end
+ else
+ prevattr = attr
+ end
+ end
+ -- we could combine these and just make the attribute nil
+ if u == 1 then
+ local font, processors = next(usedfonts)
+ local n = #processors
+ if n > 0 then
+ local h, d = processors[1](head,font,false)
+ head, done = h or head, done or d
+ if n > 1 then
+ for i=2,n do
+ local h, d = processors[i](head,font,false)
+ head, done = h or head, done or d
+ end
+ end
+ end
+ elseif u > 0 then
+ for font, processors in next, usedfonts do
+ local n = #processors
+ local h, d = processors[1](head,font,false)
+ head, done = h or head, done or d
+ if n > 1 then
+ for i=2,n do
+ local h, d = processors[i](head,font,false)
+ head, done = h or head, done or d
+ end
+ end
+ end
+ end
+ if a == 1 then
+ local font, dynamics = next(attrfonts)
+ for attribute, processors in next, dynamics do -- attr can switch in between
+ local n = #processors
+ local h, d = processors[1](head,font,attribute)
+ head, done = h or head, done or d
+ if n > 1 then
+ for i=2,n do
+ local h, d = processors[i](head,font,attribute)
+ head, done = h or head, done or d
+ end
+ end
+ end
+ elseif a > 0 then
+ for font, dynamics in next, attrfonts do
+ for attribute, processors in next, dynamics do -- attr can switch in between
+ local n = #processors
+ local h, d = processors[1](head,font,attribute)
+ head, done = h or head, done or d
+ if n > 1 then
+ for i=2,n do
+ local h, d = processors[i](head,font,attribute)
+ head, done = h or head, done or d
+ end
+ end
+ end
+ end
+ end
+ stoptiming(nodes)
+ if trace_characters then
+ nodes.report(head,done)
+ end
+ return head, true
+end
+
+if node.protect_glyphs then
+
+ nodes.protect_glyphs = node.protect_glyphs
+ nodes.unprotect_glyphs = node.unprotect_glyphs
+
+else do
+
+ -- initial value subtype : X000 0001 = 1 = 0x01 = char
+ --
+ -- expected before linebreak : X000 0000 = 0 = 0x00 = glyph
+ -- X000 0010 = 2 = 0x02 = ligature
+ -- X000 0100 = 4 = 0x04 = ghost
+ -- X000 1010 = 10 = 0x0A = leftboundary lig
+ -- X001 0010 = 18 = 0x12 = rightboundary lig
+ -- X001 1010 = 26 = 0x1A = both boundaries lig
+ -- X000 1100 = 12 = 0x1C = leftghost
+ -- X001 0100 = 20 = 0x14 = rightghost
+
+ function nodes.protect_glyphs(head)
+ local done = false
+ for g in traverse_id(glyph,head) do
+ local s = g.subtype
+ if s == 1 then
+ done, g.subtype = true, 256
+ elseif s <= 256 then
+ done, g.subtype = true, 256 + s
+ end
+ end
+ return done
+ end
+
+ function nodes.unprotect_glyphs(head)
+ local done = false
+ for g in traverse_id(glyph,head) do
+ local s = g.subtype
+ if s > 256 then
+ done, g.subtype = true, s - 256
+ end
+ end
+ return done
+ end
+
+end end
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
new file mode 100644
index 000000000..36e240238
--- /dev/null
+++ b/tex/context/base/node-ini.lua
@@ -0,0 +1,244 @@
+if not modules then modules = { } end modules ['node-ini'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
Most of the code that had accumulated here is now separated in
+modules.
+--ldx]]--
+
+-- this module is being reconstructed
+
+local utf = unicode.utf8
+local next, type = next, type
+local format, concat, match, utfchar = string.format, table.concat, string.match, utf.char
+
+local chardata = characters and characters.data
+
+--[[ldx--
+
We start with a registration system for atributes so that we can use the
+symbolic names later on.
+--ldx]]--
+
+attributes = attributes or { }
+
+attributes.names = attributes.names or { }
+attributes.numbers = attributes.numbers or { }
+attributes.list = attributes.list or { }
+attributes.unsetvalue = -0x7FFFFFFF
+
+storage.register("attributes/names", attributes.names, "attributes.names")
+storage.register("attributes/numbers", attributes.numbers, "attributes.numbers")
+storage.register("attributes/list", attributes.list, "attributes.list")
+
+local names, numbers, list = attributes.names, attributes.numbers, attributes.list
+
+function attributes.define(name,number) -- at the tex end
+ if not numbers[name] then
+ numbers[name], names[number], list[number] = number, name, { }
+ end
+end
+
+--[[ldx--
+
We can use the attributes in the range 127-255 (outside user space). These
+are only used when no attribute is set at the \TEX\ end which normally
+happens in .
+--ldx]]--
+
+storage.shared.attributes_last_private = storage.shared.attributes_last_private or 127
+
+function attributes.private(name) -- at the lua end (hidden from user)
+ local number = numbers[name]
+ if not number then
+ local last = storage.shared.attributes_last_private or 127
+ if last < 255 then
+ last = last + 1
+ storage.shared.attributes_last_private = last
+ end
+ number = last
+ numbers[name], names[number], list[number] = number, name, { }
+ end
+ return number
+end
+
+--[[ldx--
+
Access to nodes is what gives its power. Here we
+implement a few helper functions. These functions are rather optimized.
+--ldx]]--
+
+--[[ldx--
+
When manipulating node lists in , we will remove
+nodes and insert new ones. While node access was implemented, we did
+quite some experiments in order to find out if manipulating nodes
+in was feasible from the perspective of performance.
+
+
First of all, we noticed that the bottleneck is more with excessive
+callbacks (some gets called very often) and the conversion from and to
+'s datastructures. However, at the end, we
+found that inserting and deleting nodes in a table could become a
+bottleneck.
+
+
This resulted in two special situations in passing nodes back to
+: a table entry with value false is ignored,
+and when instead of a table true is returned, the
+original table is used.
+
+
Insertion is handled (at least in as follows. When
+we need to insert a node at a certain position, we change the node at
+that position by a dummy node, tagged inline which itself
+has_attribute the original node and one or more new nodes. Before we pass
+back the list we collapse the list. Of course collapsing could be built
+into the engine, but this is a not so natural extension.
+
+
When we collapse (something that we only do when really needed), we
+also ignore the empty nodes. [This is obsolete!]
+--ldx]]--
+
+nodes = nodes or { }
+
+local hlist = node.id('hlist')
+local vlist = node.id('vlist')
+local glyph = node.id('glyph')
+local glue = node.id('glue')
+local penalty = node.id('penalty')
+local kern = node.id('kern')
+local whatsit = node.id('whatsit')
+
+local traverse_id = node.traverse_id
+local traverse = node.traverse
+local free_node = node.free
+local remove_node = node.remove
+local insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+
+function nodes.remove(head, current, free_too)
+ local t = current
+ head, current = remove_node(head,current)
+ if t then
+ if free_too then
+ free_node(t)
+ t = nil
+ else
+ t.next, t.prev = nil, nil
+ end
+ end
+ return head, current, t
+end
+
+function nodes.delete(head,current)
+ return nodes.remove(head,current,true)
+end
+
+nodes.before = insert_node_before
+nodes.after = insert_node_after
+
+-- we need to test this, as it might be fixed now
+
+function nodes.before(h,c,n)
+ if c then
+ if c == h then
+ n.next = h
+ n.prev = nil
+ h.prev = n
+ else
+ local cp = c.prev
+ n.next = c
+ n.prev = cp
+ if cp then
+ cp.next = n
+ end
+ c.prev = n
+ return h, n
+ end
+ end
+ return n, n
+end
+
+function nodes.after(h,c,n)
+ if c then
+ local cn = c.next
+ if cn then
+ n.next = cn
+ cn.prev = n
+ else
+ n.next = nil
+ end
+ c.next = n
+ n.prev = c
+ return h, n
+ end
+ return n, n
+end
+
+-- local h, c = nodes.replace(head,current,new)
+-- local c = nodes.replace(false,current,new)
+-- local c = nodes.replace(current,new)
+
+function nodes.replace(head,current,new) -- no head returned if false
+ if not new then
+ head, current, new = false, head, current
+ end
+ local prev, next = current.prev, current.next
+ if next then
+ new.next, next.prev = next, new
+ end
+ if prev then
+ new.prev, prev.next = prev, new
+ end
+ if head then
+ if head == current then
+ head = new
+ end
+ free_node(current)
+ return head, new
+ else
+ free_node(current)
+ return new
+ end
+end
+
+-- will move
+
+local function count(stack,flat)
+ local n = 0
+ while stack do
+ local id = stack.id
+ if not flat and id == hlist or id == vlist then
+ local list = stack.list
+ if list then
+ n = n + 1 + count(list) -- self counts too
+ else
+ n = n + 1
+ end
+ else
+ n = n + 1
+ end
+ stack = stack.next
+ end
+ return n
+end
+
+nodes.count = count
+
+-- new, will move
+
+function attributes.ofnode(n)
+ local a = n.attr
+ if a then
+ local names = attributes.names
+ a = a.next
+ while a do
+ local number, value = a.number, a.value
+ texio.write_nl(format("%s : attribute %3i, value %4i, name %s",tostring(n),number,value,names[number] or '?'))
+ a = a.next
+ end
+ end
+end
+
+local left, space = lpeg.P("<"), lpeg.P(" ")
+
+nodes.filterkey = left * (1-left)^0 * left * space^0 * lpeg.C((1-space)^0)
diff --git a/tex/context/base/node-ini.mkiv b/tex/context/base/node-ini.mkiv
new file mode 100644
index 000000000..787259316
--- /dev/null
+++ b/tex/context/base/node-ini.mkiv
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=node-ini,
+%D version=2006.08.20,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Node Support / Initialization}
+
+\unprotect
+
+\newcount\filterstate \filterstate\plusone
+
+\registerctxluafile{node-ini}{1.001}
+\registerctxluafile{node-dir}{1.001}
+\registerctxluafile{node-aux}{1.001}
+\registerctxluafile{node-tst}{1.001}
+\registerctxluafile{node-tra}{1.001} % we might split it off (module)
+\registerctxluafile{node-seq}{1.001} % we might generalize this one
+\registerctxluafile{node-tsk}{1.001}
+\registerctxluafile{node-tex}{1.001}
+\registerctxluafile{node-res}{1.001}
+\registerctxluafile{node-pro}{1.001}
+\registerctxluafile{node-shp}{1.001}
+\registerctxluafile{node-ser}{1.001}
+\registerctxluafile{node-ext}{1.001}
+\registerctxluafile{node-inj}{1.001} % we might split it off
+\registerctxluafile{node-typ}{1.001} % experimental
+
+\newtoks \attributesresetlist
+
+\ifdefined \v!global \else \def\v!global{global} \fi % for metatex
+
+\unexpanded\def\defineattribute
+ {\dodoubleempty\dodefineattribute}
+
+\def\dodefineattribute[#1][#2]% alternatively we can let lua do the housekeeping
+ {\expandafter\newattribute\csname @attr@#1\endcsname
+ \expandafter \xdef\csname :attr:#1\endcsname{\number\lastallocatedattribute}%
+ \ctxlua{attributes.define("#1",\number\lastallocatedattribute)}%
+ %\writestatus\m!systems{defining attribute #1 with number \number\lastallocatedattribute}%
+ \doifnotinset\v!global{#2}{\appendetoks\csname @attr@#1\endcsname\attributeunsetvalue\to\attributesresetlist}}
+
+\unexpanded\def\definesystemattribute
+ {\dodoubleempty\dodefinesystemattribute}
+
+\def\dodefinesystemattribute[#1][#2]% alternatively we can let lua do the housekeeping
+ {\scratchcounter\ctxlua{tex.print(attributes.private("#1"))}\relax
+ \global\expandafter\attributedef\csname @attr@#1\endcsname\scratchcounter
+ \expandafter \xdef\csname :attr:#1\endcsname{\number\scratchcounter}%
+ %\writestatus\m!systems{defining system attribute #1 with number \number\scratchcounter}%
+ \doifnotinset\v!global{#2}{\appendetoks\csname @attr@#1\endcsname\attributeunsetvalue\to\attributesresetlist}}
+
+% expandable so we can \edef them for speed
+
+\def\dosetattribute#1#2{\csname @attr@#1\endcsname#2\relax}
+\def\doresetattribute#1{\csname @attr@#1\endcsname\attributeunsetvalue}
+\def\dogetattribute #1{\number\csname @attr@#1\endcsname}
+\def\dogetattributeid#1{\csname :attr:#1\endcsname}
+
+\let\dompattribute\gobbletwoarguments
+
+\def\resetallattributes{\the\attributesresetlist}
+
+\newcount\shownodescounter
+
+\def\shownextnodes {\afterassignment\doshownodes\shownextnodescounter}
+\def\showflatnodes {\afterassignment\doshownodes\showflatnodescounter}
+\def\doshownextnodes {\ctxlua{texio.write_nl('log',nodes.serializebox(\number\shownodescounter,false,true))}}
+\def\doshowflatnodes {\ctxlua{texio.write_nl('log',nodes.serializebox(\number\shownodescounter,true, true))}}
+\def\visualizenextnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,false,true)}}}
+\def\visualizeflatnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,true,true)}}}
+
+\unexpanded\def\starttracingnodes[#1]{\ctxlua{nodes.tracers.characters.start("#1")}}
+\unexpanded\def\stoptracingnodes {\ctxlua{nodes.tracers.characters.stop()}}
+
+% \starttext
+% \starttracingnodes[characters]
+% \input tufte \par
+% \input tufte \par
+% \stoptracingnodes
+% \stoptext
+
+\protect \endinput
diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua
new file mode 100644
index 000000000..9c4612a22
--- /dev/null
+++ b/tex/context/base/node-inj.lua
@@ -0,0 +1,466 @@
+if not modules then modules = { } end modules ['node-inj'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- tricky ... fonts.ids is not yet defined .. to be solved (maybe general tex ini)
+
+-- This is very experimental (this will change when we have luatex > .50 and
+-- a few pending thingies are available. Also, Idris needs to make a few more
+-- test fonts. Btw, future versions of luatex will have extended glyph properties
+-- that can be of help.
+
+local next = next
+
+local trace_injections = false trackers.register("nodes.injections", function(v) trace_injections = v end)
+
+fonts = fonts or { }
+fonts.tfm = fonts.tfm or { }
+fonts.ids = fonts.ids or { }
+
+local fontdata = fonts.ids
+
+local glyph = node.id('glyph')
+local kern = node.id('kern')
+
+local traverse_id = node.traverse_id
+local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+
+local newkern = nodes.kern
+
+local markbase = attributes.private('markbase')
+local markmark = attributes.private('markmark')
+local markdone = attributes.private('markdone')
+local cursbase = attributes.private('cursbase')
+local curscurs = attributes.private('curscurs')
+local cursdone = attributes.private('cursdone')
+local kernpair = attributes.private('kernpair')
+
+local cursives = { }
+local marks = { }
+local kerns = { }
+
+-- currently we do gpos/kern in a bit inofficial way but when we
+-- have the extra fields in glyphnodes to manipulate ht/dp/wd
+-- explicitly i will provide an alternative; also, we can share
+-- tables
+
+-- for the moment we pass the r2l key ... volt/arabtype tests
+
+function nodes.set_cursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
+ local dx, dy = factor*(exit[1]-entry[1]), factor*(exit[2]-entry[2])
+ local ws, wn = tfmstart.width, tfmnext.width
+ local bound = #cursives + 1
+ set_attribute(start,cursbase,bound)
+ set_attribute(nxt,curscurs,bound)
+ cursives[bound] = { rlmode, dx, dy, ws, wn }
+ return dx, dy, bound
+end
+
+function nodes.set_pair(current,factor,rlmode,r2lflag,spec,tfmchr)
+ local x, y, w, h = factor*spec[1], factor*spec[2], factor*spec[3], factor*spec[4]
+ -- dy = y - h
+ if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then
+ local bound = has_attribute(current,kernpair)
+ if bound then
+ local kb = kerns[bound]
+ -- inefficient but singles have less, but weird anyway, needs checking
+ kb[2], kb[3], kb[4], kb[5] = (kb[2] or 0) + x, (kb[3] or 0) + y, (kb[4] or 0)+ w, (kb[5] or 0) + h
+ else
+ bound = #kerns + 1
+ set_attribute(current,kernpair,bound)
+ kerns[bound] = { rlmode, x, y, w, h, r2lflag, tfmchr.width }
+ end
+ return x, y, w, h, bound
+ end
+ return x, y, w, h -- no bound
+end
+
+function nodes.set_kern(current,factor,rlmode,x,tfmchr)
+ local dx = factor*x
+ if dx ~= 0 then
+ local bound = #kerns + 1
+ set_attribute(current,kernpair,bound)
+ kerns[bound] = { rlmode, dx }
+ end
+ return dx, bound
+end
+
+function nodes.set_mark(start,base,factor,rlmode,ba,ma,index) --ba=baseanchor, ma=markanchor
+ local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
+ local bound = has_attribute(base,markbase)
+ if bound then
+ local mb = marks[bound]
+ if mb then
+ if not index then index = #mb + 1 end
+ mb[index] = { dx, dy }
+ set_attribute(start,markmark,bound)
+ set_attribute(start,markdone,index)
+ return dx, dy, bound
+ else
+ logs.report("nodes mark", "possible problem, U+%04X is base without data (id: %s)",base.char,bound)
+ end
+ end
+ index = index or 1
+ bound = #marks + 1
+ set_attribute(base,markbase,bound)
+ set_attribute(start,markmark,bound)
+ set_attribute(start,markdone,index)
+ marks[bound] = { [index] = { dx, dy } }
+ return dx, dy, bound
+end
+
+function nodes.trace_injection(head)
+ local function dir(n)
+ return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or ("unset")
+ end
+ local function report(...)
+ logs.report("nodes finisher",...)
+ end
+ report("begin run")
+ for n in traverse_id(glyph,head) do
+ if n.subtype < 256 then
+ local kp = has_attribute(n,kernpair)
+ local mb = has_attribute(n,markbase)
+ local mm = has_attribute(n,markmark)
+ local md = has_attribute(n,markdone)
+ local cb = has_attribute(n,cursbase)
+ local cc = has_attribute(n,curscurs)
+ report("char U+%05X, font=%s",n.char,n.font)
+ if kp then
+ local k = kerns[kp]
+ if k[3] then
+ report(" pairkern: dir=%s, x=%s, y=%s, w=%s, h=%s",dir(k[1]),k[2] or "?",k[3] or "?",k[4] or "?",k[5] or "?")
+ else
+ report(" kern: dir=%s, dx=%s",dir(k[1]),k[2] or "?")
+ end
+ end
+ if mb then
+ report(" markbase: bound=%s",mb)
+ end
+ if mm then
+ local m = marks[mm]
+ if mb then
+ local m = m[mb]
+ if m then
+ report(" markmark: bound=%s, index=%s, dx=%s, dy=%s",mm,md or "?",m[1] or "?",m[2] or "?")
+ else
+ report(" markmark: bound=%s, missing index",mm)
+ end
+ else
+ m = m[1]
+ report(" markmark: bound=%s, dx=%s, dy=%s",mm,m[1] or "?",m[2] or "?")
+ end
+ end
+ if cb then
+ report(" cursbase: bound=%s",cb)
+ end
+ if cc then
+ local c = cursives[cc]
+ report(" curscurs: bound=%s, dir=%s, dx=%s, dy=%s",cc,dir(c[1]),c[2] or "?",c[3] or "?")
+ end
+ end
+ end
+ report("end run")
+end
+
+-- todo: reuse tables (i.e. no collection), but will be extra fields anyway
+
+function nodes.inject_kerns(head,where,keep)
+ local has_marks, has_cursives, has_kerns = next(marks), next(cursives), next(kerns)
+ if has_marks or has_cursives then
+--~ if has_marks or has_cursives or has_kerns then
+ if trace_injections then
+ nodes.trace_injection(head)
+ end
+ -- in the future variant we will not copy items but refs to tables
+ local done, ky, rl, valid, cx, wx, mk = false, { }, { }, { }, { }, { }, { }
+ if has_kerns then -- move outside loop
+ local nf, tm = nil, nil
+ for n in traverse_id(glyph,head) do
+ if n.subtype < 256 then
+ valid[#valid+1] = n
+ if n.font ~= nf then
+ nf = n.font
+ tm = fontdata[nf].marks
+ end
+ mk[n] = tm[n.char]
+ local k = has_attribute(n,kernpair)
+ if k then
+ local kk = kerns[k]
+ if kk then
+ local x, y, w, h = kk[2] or 0, kk[3] or 0, kk[4] or 0, kk[5] or 0
+ local dy = y - h
+ if dy ~= 0 then
+ ky[n] = dy
+ end
+ if w ~= 0 or x ~= 0 then
+ wx[n] = kk
+ end
+ rl[n] = kk[1] -- could move in test
+ end
+ end
+ end
+ end
+ else
+ local nf, tm = nil, nil
+ for n in traverse_id(glyph,head) do
+ if n.subtype < 256 then
+ valid[#valid+1] = n
+ if n.font ~= nf then
+ nf = n.font
+ tm = fontdata[nf].marks
+ end
+ mk[n] = tm[n.char]
+ end
+ end
+ end
+ if #valid > 0 then
+ -- we can assume done == true because we have cursives and marks
+ local cx = { }
+ if has_kerns and next(ky) then
+ for n, k in next, ky do
+ n.yoffset = k
+ end
+ end
+ -- todo: reuse t and use maxt
+ if has_cursives then
+ local p_cursbase, p = nil, nil
+ -- since we need valid[n+1] we can also use a "while true do"
+ local t, d, maxt = { }, { }, 0
+ for i=1,#valid do -- valid == glyphs
+ local n = valid[i]
+ if not mk[n] then
+ local n_cursbase = has_attribute(n,cursbase)
+ if p_cursbase then
+ local n_curscurs = has_attribute(n,curscurs)
+ if p_cursbase == n_curscurs then
+ local c = cursives[n_curscurs]
+ if c then
+ local rlmode, dx, dy, ws, wn = c[1], c[2], c[3], c[4], c[5]
+ if rlmode >= 0 then
+ dx = dx - ws
+ else
+ dx = dx + wn
+ end
+ if dx ~= 0 then
+ cx[n] = dx
+ rl[n] = rlmode
+ end
+ -- if rlmode and rlmode < 0 then
+ dy = -dy
+ -- end
+ maxt = maxt + 1
+ t[maxt] = p
+ d[maxt] = dy
+ else
+ maxt = 0
+ end
+ end
+ elseif maxt > 0 then
+ local ny = n.yoffset
+ for i=maxt,1,-1 do
+ ny = ny + d[i]
+ local ti = t[i]
+ ti.yoffset = ti.yoffset + ny
+ end
+ maxt = 0
+ end
+ if not n_cursbase and maxt > 0 then
+ local ny = n.yoffset
+ for i=maxt,1,-1 do
+ ny = ny + d[i]
+ local ti = t[i]
+ ti.yoffset = ny
+ end
+ maxt = 0
+ end
+ p_cursbase, p = n_cursbase, n
+ end
+ end
+ if maxt > 0 then
+ local ny = n.yoffset
+ for i=maxt,1,-1 do
+ ny = ny + d[i]
+ local ti = t[i]
+ ti.yoffset = ny
+ end
+ maxt = 0
+ end
+ if not keep then
+ cursives = { }
+ end
+ end
+ if has_marks then
+ for i=1,#valid do
+ local p = valid[i]
+ local p_markbase = has_attribute(p,markbase)
+ if p_markbase then
+ local mrks = marks[p_markbase]
+ for n in traverse_id(glyph,p.next) do
+ local n_markmark = has_attribute(n,markmark)
+ if p_markbase == n_markmark then
+ local index = has_attribute(n,markdone) or 1
+ local d = mrks[index]
+ if d then
+ -- local rlmode = d[3] -- not used
+ -- if rlmode and rlmode > 0 then
+ -- todo
+ -- else
+ local k = wx[p]
+ if k then
+ n.xoffset = p.xoffset - d[1] - k[2]
+ else
+ n.xoffset = p.xoffset - d[1]
+ end
+ -- end
+ if mk[p] then
+ n.yoffset = p.yoffset + d[2]
+ else
+ n.yoffset = n.yoffset + p.yoffset + d[2]
+ end
+ end
+ else
+ break
+ end
+ end
+ end
+ end
+ if not keep then
+ marks = { }
+ end
+ end
+ -- todo : combine
+ if next(wx) then
+ for n, k in next, wx do
+ -- only w can be nil, can be sped up when w == nil
+ local rl, x, w, r2l = k[1], k[2] or 0, k[4] or 0, k[6]
+ local wx = w - x
+--~ if rl < 0 then
+--~ if r2l then
+--~ if wx ~= 0 then
+--~ insert_node_before(head,n,newkern(wx))
+--~ end
+--~ if x ~= 0 then
+--~ insert_node_after (head,n,newkern(x))
+--~ end
+--~ else
+--~ if x ~= 0 then
+--~ insert_node_before(head,n,newkern(x))
+--~ end
+--~ if wx ~= 0 then
+--~ insert_node_after(head,n,newkern(wx))
+--~ end
+--~ end
+--~ else
+ if r2l then
+ if wx ~= 0 then
+ insert_node_before(head,n,newkern(wx))
+ end
+ if x ~= 0 then
+ insert_node_after (head,n,newkern(x))
+ end
+ else
+ if x ~= 0 then
+ insert_node_before(head,n,newkern(x))
+ end
+ if wx ~= 0 then
+ insert_node_after(head,n,newkern(wx))
+ end
+ end
+--~ end
+ end
+ end
+ if next(cx) then
+ for n, k in next, cx do
+ if k ~= 0 then
+ local rln = rl[n]
+ if rln and rln < 0 then
+ insert_node_before(head,n,newkern(-k))
+ else
+ insert_node_before(head,n,newkern(k))
+ end
+ end
+ end
+ end
+ if not keep then
+ kerns = { }
+ end
+ return head, true
+ elseif not keep then
+ kerns, cursives, marks = { }, { }, { }
+ end
+ elseif has_kerns then
+ if trace_injections then
+ nodes.trace_injection(head)
+ end
+ for n in traverse_id(glyph,head) do
+ local k = has_attribute(n,kernpair)
+ if k then
+ local kk = kerns[k]
+ if kk then
+ local rl, x, y, w = kk[1], kk[2] or 0, kk[3], kk[4]
+ if y and y ~= 0 then
+ n.yoffset = y -- todo: h ?
+ end
+ if w then
+ -- copied from above
+ local r2l = kk[6]
+ local wx = w - x
+--~ if rl < 0 then
+--~ if r2l then
+--~ if x ~= 0 then
+--~ insert_node_before(head,n,newkern(x))
+--~ end
+--~ if wx ~= 0 then
+--~ insert_node_after(head,n,newkern(wx))
+--~ end
+--~ else
+--~ if wx ~= 0 then
+--~ insert_node_before(head,n,newkern(wx))
+--~ end
+--~ if x ~= 0 then
+--~ insert_node_after (head,n,newkern(x))
+--~ end
+--~ end
+--~ else
+ if r2l then
+ if wx ~= 0 then
+ insert_node_before(head,n,newkern(wx))
+ end
+ if x ~= 0 then
+ insert_node_after (head,n,newkern(x))
+ end
+ else
+ if x ~= 0 then
+ insert_node_before(head,n,newkern(x))
+ end
+ if wx ~= 0 then
+ insert_node_after(head,n,newkern(wx))
+ end
+ end
+--~ end
+ else
+ -- simple (e.g. kernclass kerns)
+ if x ~= 0 then
+ insert_node_before(head,n,newkern(x))
+ end
+ end
+ end
+ end
+ end
+ if not keep then
+ kerns = { }
+ end
+ return head, true
+ else
+ -- no tracing needed
+ end
+ return head, false
+end
diff --git a/tex/context/base/node-mig.lua b/tex/context/base/node-mig.lua
new file mode 100644
index 000000000..f9f0ad231
--- /dev/null
+++ b/tex/context/base/node-mig.lua
@@ -0,0 +1,120 @@
+if not modules then modules = { } end modules ['node-mig'] = {
+ version = 1.001,
+ comment = "companion to node-mig.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+local hlist = node.id('hlist')
+local vlist = node.id('vlist')
+local insert = node.id('ins')
+local mark = node.id('mark')
+
+local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local remove_nodes = nodes.remove
+
+local migrated = attributes.private("migrated")
+
+local trace_migrations = false
+
+trackers.register("nodes.migrations", function(v) trace_migrations = v end)
+
+local migrate_inserts, migrate_marks
+
+local t_inserts, t_marks, t_sweeps = 0, 0, 0
+
+local function locate(head,first,last,ni,nm)
+ local current = head
+ while current do
+ local id = current.id
+ if id == vlist or id == hlist then
+ current.list, first, last, ni, nm = locate(current.list,first,last,ni,nm)
+ current= current.next
+ elseif migrate_inserts and id == insert then
+ local insert
+ head, current, insert = remove_nodes(head,current)
+ insert.next = nil
+ if first then
+ insert.prev, last.next = last, insert
+ else
+ insert.prev, first = nil, insert
+ end
+ last, ni = insert, ni + 1
+ elseif migrate_marks and id == mark then
+ local mark
+ head, current, mark = remove_nodes(head,current)
+ mark.next = nil
+ if first then
+ mark.prev, last.next = last, mark
+ else
+ mark.prev, first = nil, mark
+ end
+ last, nm = mark, nm + 1
+ else
+ current= current.next
+ end
+ end
+ return head, first, last, ni, nm
+end
+
+function nodes.migrate_outwards(head,where)
+ local done = false
+ if head then
+ local current = head
+ while current do
+ local id = current.id
+ if id == vlist or id == hlist and not has_attribute(current,migrated) then
+ set_attribute(current,migrated,1)
+ t_sweeps = t_sweeps + 1
+ local h = current.list
+ local first, last, ni, nm
+ while h do
+ local id = h.id
+ if id == vlist or id == hlist then
+ h, first, last, ni, nm = locate(h,first,last,0,0)
+ end
+ h = h.next
+ end
+ if first then
+ t_inserts, t_marks = t_inserts + ni, t_marks + nm
+ if trace_migrations and (ni > 0 or nm > 0) then
+ logs.report("nodes","sweep %s, %s inserts and %s marks migrated outwards",t_sweeps,ni,nm)
+ end
+ -- inserts after head
+ local n = current.next
+ if n then
+ last.next, n.prev = n, last
+ end
+ current.next, first.prev = first, current
+ done, current = true, last
+ end
+ end
+ current = current.next
+ end
+ return head, done
+ end
+end
+
+experiments.register("marks.migrate", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.migrate_outwards")
+ end
+ migrate_marks = v
+end)
+
+experiments.register("inserts.migrate", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.migrate_outwards")
+ end
+ migrate_inserts = v
+end)
+
+statistics.register("node migrations", function()
+ if trace_migrations and t_sweeps > 0 then
+ return format("%s sweeps, %s inserts moved, %s marks moved",t_sweeps,t_inserts,t_marks)
+ end
+end)
diff --git a/tex/context/base/node-mig.mkiv b/tex/context/base/node-mig.mkiv
new file mode 100644
index 000000000..cd731b96f
--- /dev/null
+++ b/tex/context/base/node-mig.mkiv
@@ -0,0 +1,60 @@
+%D \module
+%D [ file=node-mig,
+%D version=2010.01.19,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Inserts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Node Support / Migrations}
+
+%D This is very experimental and although it is used in a
+%D real project it mostly serves a testbed for Taco and me so
+%D as prelude to extending the inserts mechanism.
+%D
+%D \starttyping
+%D \automigrateinserts
+%D
+%D \hbox{\vbox{x\footnote{1}x\footnote{2}x\footnote{3}x}}
+%D \vbox{x\footnote{4}x}
+%D \hbox{\vbox{x\footnote{5}x}}
+%D
+%D \hbox{x}
+%D \hbox{x\footnote{6}x}
+%D \hbox{x}
+%D
+%D \starttabulate
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \NC test \NC test \footnote{test} \input tufte \NC \NR
+%D \stoptabulate
+%D \stoptyping
+
+\unprotect
+
+\registerctxluafile{node-mig}{1.001}
+
+\newtoks \everyautomigratefootnotes
+\newtoks \everyautomigratemarks
+
+\def\automigrateinserts{\the\everyautomigratefootnotes}
+\def\automigratemarks {\the\everyautomigratemarks}
+
+\appendtoks
+ \let\postponenotes\relax
+ \enableexperiments[inserts.migrate]%
+\to \everyautomigratefootnotes
+
+\appendtoks
+ \enableexperiments[marks.migrate]%
+\to \everyautomigratemarks
+
+\protect
diff --git a/tex/context/base/node-pag.lua b/tex/context/base/node-pag.lua
new file mode 100644
index 000000000..4bc53c6dd
--- /dev/null
+++ b/tex/context/base/node-pag.lua
@@ -0,0 +1,30 @@
+if not modules then modules = { } end modules ['node-pag'] = {
+ version = 1.001,
+ comment = "companion to node-pag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this callback might disappear and come back in the same way
+-- as par builders
+
+pagebuilders = pagebuilders or { }
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+local actions = tasks.actions("pagebuilders",5)
+
+local function processor(head,groupcode,size,packtype,maxdepth,direction)
+ starttiming(pagebuilders)
+ local _, done = actions(head,groupcode,size,packtype,maxdepth,direction)
+ stoptiming(pagebuilders)
+ return (done and head) or true
+-- return vpack(head)
+end
+
+--~ callbacks.register('pre_output_filter', processor, "preparing output box")
+
+--~ statistics.register("output preparation time", function()
+--~ return statistics.elapsedseconds(pagebuilders)
+--~ end)
diff --git a/tex/context/base/node-pag.mkiv b/tex/context/base/node-pag.mkiv
new file mode 100644
index 000000000..487901ad0
--- /dev/null
+++ b/tex/context/base/node-pag.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=node-pag,
+%D version=2008.09.30,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Page Building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Node Macros / Page Building}
+
+\unprotect
+
+\registerctxluafile{node-pag}{1.001}
+
+\protect \endinput
diff --git a/tex/context/base/node-par.lua b/tex/context/base/node-par.lua
new file mode 100644
index 000000000..7be7e7917
--- /dev/null
+++ b/tex/context/base/node-par.lua
@@ -0,0 +1,101 @@
+if not modules then modules = { } end modules ['node-par'] = {
+ version = 1.001,
+ comment = "companion to node-par.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+parbuilders = parbuilders or { }
+parbuilders.constructors = parbuilders.constructors or { }
+parbuilders.names = parbuilders.names or { }
+parbuilders.numbers = parbuilders.numbers or { }
+parbuilders.attribute = attributes.numbers['parbuilder'] or 999
+
+storage.register("parbuilders.names", parbuilders.names, "parbuilders.names")
+storage.register("parbuilders.numbers", parbuilders.numbers, "parbuilders.numbers")
+
+local constructors, names, numbers, p_attribute = parbuilders.constructors, parbuilders.names, parbuilders.numbers, parbuilders.attribute
+
+local has_attribute = node.has_attribute
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+local mainconstructor = nil -- not stored in format
+
+function parbuilders.register(name,number)
+ parbuilders.names[number] = name
+ parbuilders.numbers[name] = number
+end
+
+function parbuilders.setmain(name)
+ mainconstructor = numbers[name]
+end
+
+-- return values:
+--
+-- true : tex will break itself
+-- false : idem but dangerous
+-- head : list of valid vmode nodes with last being hlist
+
+function parbuilders.constructor(head,followed_by_display)
+ if type(head) == "boolean" then
+ return head
+ else
+ local attribute = has_attribute(head,p_attribute) or mainconstructor
+ if attribute then
+ local constructor = names[attribute]
+ if constructor then
+ local handler = constructor and constructors[constructor]
+ if handler then
+ return handler(head,followed_by_display)
+ else
+ logs.report("parbuilders","handler '%s' is not defined",tostring(constructor))
+ return true -- let tex break
+ end
+ end
+ end
+ return true -- let tex break
+ end
+end
+
+-- just for testing
+
+function parbuilders.constructors.default(head,followed_by_display)
+ return true -- let tex break
+end
+
+-- also for testing (no surrounding spacing done)
+
+function parbuilders.constructors.oneline(head,followed_by_display)
+ return node.hpack(head)
+end
+
+-- It makes no sense to have a sequence here as we already have
+-- pre and post hooks and only one parbuilder makes sense, so no:
+--
+-- local actions = tasks.actions("parbuilders",1)
+
+-- todo: enable one as main
+
+local actions = parbuilders.constructor
+local enabled = false
+
+function parbuilders.enable () enabled = true end
+function parbuilders.disable() enabled = false end
+
+local function processor(head,followed_by_display)
+ if enabled then
+ starttiming(parbuilders)
+ local head = actions(head,followed_by_display)
+ stoptiming(parbuilders)
+ return head
+ else
+ return true -- let tex do the work
+ end
+end
+
+callbacks.register('linebreak_filter', processor, "breaking paragraps into lines")
+
+statistics.register("linebreak processing time", function()
+ return statistics.elapsedseconds(parbuilders)
+end)
diff --git a/tex/context/base/node-par.mkiv b/tex/context/base/node-par.mkiv
new file mode 100644
index 000000000..cb53e643d
--- /dev/null
+++ b/tex/context/base/node-par.mkiv
@@ -0,0 +1,78 @@
+%D \module
+%D [ file=node-par,
+%D version=2008.09.30,
+%D title=\CONTEXT\ Node Macros,
+%D subtitle=Paragraph Building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Node Macros / Paragraph Building}
+
+%D This is very experimental, undocumented, subjected to changes, etc. just as
+%D the underlying interfaces.
+
+% \enableparbuilders
+%
+% \startparbuilder[default]
+% \input tufte \par
+% \startparbuilder[oneline]
+% \input tufte \par
+% \stopparbuilder
+% \input tufte \par
+% \stopparbuilder
+
+\unprotect
+
+\registerctxluafile{node-par}{1.001}
+
+\definesystemattribute[parbuilder] \chardef\parbuilderattribute \dogetattributeid{parbuilder}
+
+% todo auto-enable
+
+% management (enable/disable) is global and will move to lua
+
+\newcount\nofparbuilders
+
+\unexpanded\def\defineparbuilder[#1]%
+ {\global\advance\nofparbuilders\plusone
+ \ctxlua{parbuilders.register("#1",\number\nofparbuilders)}%
+ \setxvalue{\??ng:#1}{\attribute\parbuilderattribute\nofparbuilders}}
+
+\unexpanded\def\startparbuilder[#1]%
+ {\edef\@@currentparbuilder{\number\attribute\parbuilderattribute}%
+ \globalpushmacro\@@currentparbuilder
+ \getvalue{\??ng:#1}%
+ \checkparbuilders}
+
+\unexpanded\def\stopparbuilder
+ {\ifhmode\par\fi
+ \globalpopmacro\@@currentparbuilder
+ \attribute\parbuilderattribute\@@currentparbuilder\relax
+ \checkparbuilders}
+
+\def\setmainparbuilder[#1]%
+ {\ctxlua{parbuilders.setmain("#1")}}
+
+% no high level interface, after all implementing a linebreaker is not something that
+% the average user will do
+
+\defineparbuilder[default] % just for testing
+\defineparbuilder[oneline] % just for testing
+\defineparbuilder[basic] % just for testing
+
+\def\enableparbuilders {\ctxlua{parbuilders.enable ()}}
+\def\disableparbuilders{\ctxlua{parbuilders.disable()}}
+
+\def\checkparbuilders % can be more efficient as we don't want to do this to often
+ {\ifcase\attribute\parbuilderattribute
+ \disableparbuilders
+ \else
+ \enableparbuilders
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua
new file mode 100644
index 000000000..4f5b3dcbe
--- /dev/null
+++ b/tex/context/base/node-pro.lua
@@ -0,0 +1,149 @@
+if not modules then modules = { } end modules ['node-pro'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utf = unicode.utf8
+local format, concat = string.format, table.concat
+
+local trace_callbacks = false trackers.register("nodes.callbacks", function(v) trace_callbacks = v end)
+
+local glyph = node.id('glyph')
+
+local free_node = node.free
+local first_character = node.first_character
+
+nodes.processors = nodes.processors or { }
+
+-- vbox: grouptype: vbox vtop output split_off split_keep | box_type: exactly|aditional
+-- hbox: grouptype: hbox adjusted_hbox(=hbox_in_vmode) | box_type: exactly|aditional
+
+lists = lists or { }
+chars = chars or { }
+words = words or { } -- not used yet
+
+local actions = tasks.actions("processors",4)
+
+local n = 0
+
+local function reconstruct(head)
+ local t = { }
+ local h = head
+ while h do
+ local id = h.id
+ if id == glyph then
+ t[#t+1] = utf.char(h.char)
+ else
+ t[#t+1] = "[]"
+ end
+ h = h.next
+ end
+ return concat(t)
+end
+
+local function tracer(what,state,head,groupcode,before,after,show)
+ if not groupcode then
+ groupcode = "unknown"
+ elseif groupcode == "" then
+ groupcode = "mvl"
+ end
+ n = n + 1
+ if show then
+ logs.report("nodes","%s %s: %s, group: %s, nodes: %s -> %s, string: %s",what,n,state,groupcode,before,after,reconstruct(head))
+ else
+ logs.report("nodes","%s %s: %s, group: %s, nodes: %s -> %s",what,n,state,groupcode,before,after)
+ end
+end
+
+nodes.processors.enabled = true -- thsi will become a proper state (like trackers)
+
+function nodes.processors.pre_linebreak_filter(head,groupcode,size,packtype,direction)
+ local first, found = first_character(head)
+ if found then
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode,size,packtype,direction)
+ local after = nodes.count(head,true)
+ if done then
+ tracer("pre_linebreak","changed",head,groupcode,before,after,true)
+ else
+ tracer("pre_linebreak","unchanged",head,groupcode,before,after,true)
+ end
+ return (done and head) or true
+ else
+ local head, done = actions(head,groupcode,size,packtype,direction)
+ return (done and head) or true
+ end
+ elseif trace_callbacks then
+ local n = nodes.count(head,false)
+ tracer("pre_linebreak","no chars",head,groupcode,n,n)
+ end
+ return true
+end
+
+function nodes.processors.hpack_filter(head,groupcode,size,packtype,direction)
+ local first, found = first_character(head)
+ if found then
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode,size,packtype,direction)
+ local after = nodes.count(head,true)
+ if done then
+ tracer("hpack","changed",head,groupcode,before,after,true)
+ else
+ tracer("hpack","unchanged",head,groupcode,before,after,true)
+ end
+ return (done and head) or true
+ else
+ local head, done = actions(head,groupcode,size,packtype,direction)
+ return (done and head) or true
+ end
+ elseif trace_callbacks then
+ local n = nodes.count(head,false)
+ tracer("hpack","no chars",head,groupcode,n,n)
+ end
+ return true
+end
+
+callbacks.register('pre_linebreak_filter', nodes.processors.pre_linebreak_filter,"all kind of horizontal manipulations (before par break)")
+callbacks.register('hpack_filter' , nodes.processors.hpack_filter,"all kind of horizontal manipulations")
+
+local actions = tasks.actions("finalizers",1) -- head, where
+
+-- beware, these are packaged boxes so no first_character test
+-- maybe some day a hash with valid groupcodes
+--
+-- beware, much can pass twice, for instance vadjust passes two times
+
+function nodes.processors.post_linebreak_filter(head,groupcode)
+--~ local first, found = first_character(head)
+--~ if found then
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode)
+ local after = nodes.count(head,true)
+ if done then
+ tracer("finalizer","changed",head,groupcode,before,after,true)
+ else
+ tracer("finalizer","unchanged",head,groupcode,before,after,true)
+ end
+ return (done and head) or true
+ else
+ local head, done = actions(head,groupcode)
+ return (done and head) or true
+ end
+--~ elseif trace_callbacks then
+--~ local n = nodes.count(head,false)
+--~ tracer("finalizer","no chars",head,groupcode,n,n)
+--~ end
+--~ return true
+end
+
+callbacks.register('post_linebreak_filter', nodes.processors.post_linebreak_filter,"all kind of horizontal manipulations (after par break)")
+
+statistics.register("h-node processing time", function()
+ return statistics.elapsedseconds(nodes,"including kernel") -- hm, ok here?
+end)
diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua
new file mode 100644
index 000000000..7128b1a6d
--- /dev/null
+++ b/tex/context/base/node-ref.lua
@@ -0,0 +1,533 @@
+if not modules then modules = { } end modules ['node-bck'] = {
+ version = 1.001,
+ comment = "companion to node-bck.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We supported pdf right from the start and in mkii this has resulted in
+-- extensive control over the links. Nowadays pdftex provides a lot more
+-- control over margins but as mkii supports multiple backends we stuck to
+-- our own mechanisms. In mkiv again we implement our own handling. Eventually
+-- we will even disable the pdf primitives.
+
+-- helper, will end up in luatex
+
+local cleanupreferences, cleanupdestinations = false, true
+
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
+
+local hpack_list = node.hpack
+local list_dimensions = node.dimensions
+
+-- current.glue_set current.glue_sign
+
+local trace_backend = false trackers.register("nodes.backend", function(v) trace_backend = v end)
+local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end)
+local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end)
+
+local hlist = node.id("hlist")
+local vlist = node.id("vlist")
+local glue = node.id("glue")
+local whatsit = node.id("whatsit")
+
+local new_kern = nodes.kern
+
+local has_attribute = node.has_attribute
+local traverse = node.traverse
+local find_node_tail = node.tail or node.slide
+local tosequence = nodes.tosequence
+
+local function dimensions(parent,start,stop)
+ stop = stop and stop.next
+ if parent then
+ if stop then
+ return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop)
+ else
+ return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start)
+ end
+ else
+ if stop then
+ return list_dimensions(start,stop)
+ else
+ return list_dimensions(start)
+ end
+ end
+end
+
+--~ more compact
+
+local function dimensions(parent,start,stop)
+ if parent then
+ return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop and stop.next)
+ else
+ return list_dimensions(start,stop and stop.next)
+ end
+end
+
+-- is pardir important at all?
+
+local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir)
+ local width, height, depth = dimensions(parent,first,last)
+ if pardir == "TRT" or txtdir == "+TRT" then
+ width = - width
+ end
+ local result, resolved = make(width,height,depth,reference)
+ if result and resolved then
+ if head == first then
+ if trace_backend then
+ logs.report("backend","head: %04i %s %s %s => w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
+ end
+ result.next = first
+ first.prev = result
+ return result, last
+ else
+ if trace_backend then
+ logs.report("backend","middle: %04i %s %s => w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
+ end
+ local prev = first.prev
+ if prev then
+ result.next = first
+ result.prev = prev
+ prev.next = result
+ first.prev = result
+ else
+ result.next = first
+ first.prev = result
+ end
+ if first == head.next then
+ head.next = result -- hm, weird
+ end
+ return head, last
+ end
+ else
+ return head, last
+ end
+end
+
+local function inject_list(id,current,reference,make,stack,pardir,txtdir)
+ local width, height, depth, correction = current.width, current.height, current.depth, 0
+ local moveright = false
+ local first = current.list
+ if id == hlist then
+ -- can be either an explicit hbox or a line and there is no way
+ -- to recognize this; anyway only if ht/dp (then inline)
+ --
+ -- to be tested: 0=unknown, 1=linebreak, 2=hbox
+--~ if id.subtype == 1 then
+ local sr = stack[reference]
+ if first then
+ if sr and sr[2] then
+ local last = find_node_tail(first)
+ if last.id == glue and last.subtype == 9 then
+ local prev = last.prev
+ moveright = first.id == glue and first.subtype == 8
+ if prev and prev.id == glue and prev.subtype == 15 then
+ width = dimensions(current,first,prev.prev) -- maybe not current as we already take care of it
+ else
+ if moveright and first.writable then
+ width = width - first.spec.stretch*current.glue_set * current.glue_sign
+ end
+ if last.writable then
+ width = width - last.spec.stretch*current.glue_set * current.glue_sign
+ end
+ end
+ end
+ else
+ -- also weird
+ end
+--~ else
+--~ print("!!!!!!!!!!!!!!!!!")
+ -- simple
+--~ end
+ else
+ -- ok
+ end
+ correction = width
+ else
+ correction = height + depth
+ height, depth = depth, height -- ugly hack, needed because pdftex backend does something funny
+ end
+ if pardir == "TRT" then
+ width = - width
+ end
+ local result, resolved = make(width,height,depth,reference)
+ if result and resolved then
+ if trace_backend then
+ logs.report("backend","box: %04i %s %s: w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",width,height,depth,resolved)
+ end
+ if not first then
+ current.list = result
+ elseif moveright then -- brr no prevs done
+ -- result after first
+ local n = first.next
+ result.next = n
+ first.next = result
+ result.prev = first
+ if n then n.prev = result end
+ else
+ -- first after result
+ result.next = first
+ first.prev = result
+ current.list = result
+ end
+ end
+end
+
+-- skip is somewhat messy
+
+local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main
+ if head then
+ local current, first, last, firstdir, reference = head, nil, nil, nil, nil
+ pardir = pardir or "==="
+ txtdir = txtdir or "==="
+ while current do
+ local id = current.id
+ local r = has_attribute(current,attribute)
+ if id == whatsit then
+ local subtype = current.subtype
+ if subtype == 6 then
+ pardir = current.dir
+ elseif subtype == 7 then
+ txtdir = current.dir
+ end
+ elseif id == hlist or id == vlist then
+ if not reference and r and (not skip or r > skip) then
+ inject_list(id,current,r,make,stack,pardir,txtdir)
+ end
+ if r then
+ done[r] = (done[r] or 0) + 1
+ end
+ local list = current.list
+ if list then
+ local _
+ current.list, _, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
+ end
+ if r then
+ done[r] = done[r] - 1
+ end
+ elseif not r then
+ -- just go on, can be kerns
+ elseif not reference then
+ reference, first, last, firstdir = r, current, current, txtdir
+ elseif r == reference then
+ last = current
+ elseif (done[reference] or 0) == 0 then
+ if not skip or r > skip then
+ head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+ reference, first, last, firstdir = nil, nil, nil, nil
+ end
+ else
+ reference, first, last, firstdir = r, current, current, txtdir
+ end
+ current = current.next
+ end
+ if reference and (done[reference] or 0) == 0 then
+ head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+ end
+ end
+ return head, true, pardir, txtdir
+end
+
+local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular !
+ if head then
+ pardir = pardir or "==="
+ txtdir = txtdir or "==="
+ local current = head
+ while current do
+ local id = current.id
+ local r = has_attribute(current,attribute)
+ if id == whatsit then
+ local subtype = current.subtype
+ if subtype == 6 then
+ pardir = current.dir
+ elseif subtype == 7 then
+ txtdir = current.dir
+ end
+ elseif id == hlist or id == vlist then
+ if r and not done[r] then
+ done[r] = true
+ inject_list(id,current,r,make,stack,pardir,txtdir)
+ end
+ current.list = inject_area(current.list,attribute,make,stack,done,current,pardir,txtdir)
+ elseif r and not done[r] then
+ done[r] = true
+ head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir)
+ end
+ current = current.next
+ end
+ end
+ return head, true
+end
+
+-- tracing
+
+local new_rule = nodes.rule
+local new_kern = nodes.kern
+local set_attribute = node.set_attribute
+local register_color = colors.register
+
+local a_colormodel = attributes.private('colormodel')
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local u_transparency = nil
+local u_colors = { }
+local force_gray = true
+
+local function colorize(width,height,depth,n)
+ if force_gray then n = 0 end
+ u_transparency = u_transparency or transparencies.register(nil,2,.65)
+ local ucolor = u_colors[n]
+ if not ucolor then
+ if n == 1 then
+ u_color = register_color(nil,'rgb',.75,0,0)
+ elseif n == 2 then
+ u_color = register_color(nil,'rgb',0,.75,0)
+ elseif n == 3 then
+ u_color = register_color(nil,'rgb',0,0,.75)
+ else
+ n = 0
+ u_color = register_color(nil,'gray',.5)
+ end
+ u_colors[n] = u_color
+ end
+ local rule = new_rule(width,height,depth)
+ set_attribute(rule,a_colormodel,1) -- gray color model
+ set_attribute(rule,a_color,u_color)
+ set_attribute(rule,a_transparency,u_transparency)
+ if width < 0 then
+ local kern = new_kern(width)
+ rule.width = -width
+ kern.next = rule
+ rule.prev = kern
+ return kern
+ else
+ return rule
+ end
+end
+
+local new_kern = nodes.kern
+local texattribute = tex.attribute
+local texcount = tex.count
+
+-- references:
+
+nodes.references = {
+ attribute = attributes.private('reference'),
+ stack = { },
+ done = { },
+}
+
+local stack, done, attribute = nodes.references.stack, nodes.references.done, nodes.references.attribute
+
+local nofreferences, topofstack = 0, 0
+
+local function setreference(n,h,d,r) -- n is just a number, can be used for tracing
+ topofstack = topofstack + 1
+ stack[topofstack] = { n, h, d, codeinjections.prerollreference(r) } -- the preroll permits us to determine samepage (but delayed also has some advantages)
+--~ texattribute[attribute] = topofstack -- todo -> at tex end
+ texcount.lastreferenceattribute = topofstack
+end
+
+nodes.setreference = setreference
+
+local function makereference(width,height,depth,reference)
+ local sr = stack[reference]
+ if sr then
+ local resolved, ht, dp, set = sr[1], sr[2], sr[3], sr[4]
+ if ht then
+ if height < ht then height = ht end
+ if depth < dp then depth = dp end
+ end
+ local annot = nodeinjections.reference(width,height,depth,set)
+ if annot then
+ nofreferences = nofreferences + 1
+ local result, current
+ if trace_references then
+ local step = 65536
+ result = hpack_list(colorize(width,height-step,depth-step,2)) -- step subtracted so that we can see seperate links
+ result.width = 0
+ current = result
+ end
+ if current then
+ current.next = annot
+ else
+ result = annot
+ end
+ result = hpack_list(result,0)
+ result.width, result.height, result.depth = 0, 0, 0
+ if cleanupreferences then stack[reference] = nil end
+ return result, resolved
+ else
+ logs.report("backends","unable to resolve reference annotation %s",reference)
+ end
+ else
+ logs.report("backends","unable to resolve reference attribute %s",reference)
+ end
+end
+
+function nodes.add_references(head)
+ if topofstack > 0 then
+ return inject_areas(head,attribute,makereference,stack,done)
+ else
+ return head, false
+ end
+end
+
+-- destinations (we can clean up once set!)
+
+nodes.destinations = {
+ attribute = attributes.private('destination'),
+ stack = { },
+ done = { },
+}
+
+local stack, done, attribute = nodes.destinations.stack, nodes.destinations.done, nodes.destinations.attribute
+
+local nofdestinations, topofstack = 0, 0
+
+local function setdestination(n,h,d,name,view) -- n = grouplevel, name == table
+ topofstack = topofstack + 1
+ stack[topofstack] = { n, h, d, name, view }
+ return topofstack
+end
+
+nodes.setdestination = setdestination
+
+local function makedestination(width,height,depth,reference)
+ local sr = stack[reference]
+ if sr then
+ local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5]
+ if ht then
+ if height < ht then height = ht end
+ if depth < dp then depth = dp end
+ end
+ local result, current
+ if trace_destinations then
+ local step = 0
+ if width == 0 then
+ step = 4*65536
+ width, height, depth = 5*step, 5*step, 0
+ end
+ for n=1,#name do
+ local rule = hpack_list(colorize(width,height,depth,3))
+ rule.width = 0
+ if not result then
+ result, current = rule, rule
+ else
+ current.next = rule
+ rule.prev = current
+ current = rule
+ end
+ width, height = width - step, height - step
+ end
+ end
+ nofdestinations = nofdestinations + 1
+ for n=1,#name do
+ local annot = nodeinjections.destination(width,height,depth,name[n],view)
+ if not result then
+ result, current = annot, annot
+ else
+ current.next = annot
+ annot.prev = current
+ current = annot
+ end
+ end
+ result = hpack_list(result,0)
+ result.width, result.height, result.depth = 0, 0, 0
+ if cleanupdestinations then stack[reference] = nil end
+ return result, resolved
+ else
+ logs.report("backends","unable to resolve destination attribute %s",reference)
+ end
+end
+
+function nodes.add_destinations(head)
+ if topofstack > 0 then
+ return inject_area(head,attribute,makedestination,stack,done) -- singular
+ else
+ return head, false
+ end
+end
+
+-- will move
+
+function jobreferences.mark(reference,h,d,view)
+ return setdestination(tex.currentgrouplevel,h,d,reference,view)
+end
+
+function jobreferences.inject(prefix,reference,h,d,highlight,newwindow,layer) -- todo: use currentreference is possible
+ local set, bug = jobreferences.identify(prefix,reference)
+ if bug or #set == 0 then
+ -- unknown ref, just don't set it and issue an error
+ else
+ -- check
+ set.highlight, set.newwindow,set.layer = highlight, newwindow, layer
+ setreference(tex.currentgrouplevel,h,d,set) -- sets attribute / todo: for set[*].error
+ end
+end
+
+function jobreferences.injectcurrentset(h,d) -- used inside doifelse
+ local currentset = jobreferences.currentset
+ if currentset then
+ setreference(tex.currentgrouplevel,h,d,currentset) -- sets attribute / todo: for set[*].error
+ end
+end
+
+--
+
+local function checkboth(open,close)
+ if open and open ~= "" then
+ local set, bug = jobreferences.identify("",open)
+ open = not bug and #set > 0 and set
+ end
+ if close and close ~= "" then
+ local set, bug = jobreferences.identify("",close)
+ close = not bug and #set > 0 and set
+ end
+ return open, close
+end
+
+-- expansion is temp hack
+
+local opendocument, closedocument, openpage, closepage
+
+local function check(what)
+ if what and what ~= "" then
+ local set, bug = jobreferences.identify("",what)
+ return not bug and #set > 0 and set
+ end
+end
+
+function jobreferences.checkopendocumentactions (open) opendocument = check(open) end
+function jobreferences.checkclosedocumentactions(close) closedocument = check(close) end
+function jobreferences.checkopenpageactions (open) openpage = check(open) end
+function jobreferences.checkclosepageactions (close) closepage = check(close) end
+
+function jobreferences.flushdocumentactions()
+ if opendocument or closedocument then
+ backends.codeinjections.flushdocumentactions(opendocument,closedocument) -- backend
+ end
+end
+function jobreferences.flushpageactions()
+ if openpage or closepage then
+ backends.codeinjections.flushpageactions(openpage,closepage) -- backend
+ end
+end
+
+-- end temp hack
+
+statistics.register("interactive elements", function()
+ if nofreferences > 0 or nofdestinations > 0 then
+ return string.format("%s references, %s destinations",nofreferences,nofdestinations)
+ else
+ return nil
+ end
+end)
+
+function jobreferences.enable_interaction()
+ tasks.enableaction("shipouts","nodes.add_references")
+ tasks.enableaction("shipouts","nodes.add_destinations")
+end
diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua
new file mode 100644
index 000000000..a8ea8745a
--- /dev/null
+++ b/tex/context/base/node-res.lua
@@ -0,0 +1,302 @@
+if not modules then modules = { } end modules ['node-res'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local gmatch, format = string.gmatch, string.format
+local copy_node, free_node, free_list, new_node, node_type, node_id = node.copy, node.free, node.flush_list, node.new, node.type, node.id
+local tonumber, round = tonumber, math.round
+
+local glyph_node = node_id("glyph")
+
+--[[ldx--
+
The next function is not that much needed but in we use
+for debugging node management.
+--ldx]]--
+
+nodes = nodes or { }
+
+nodes.whatsits = { } -- table.swapped(node.whatsits())
+
+local reserved = { }
+local whatsits = nodes.whatsits
+
+for k, v in next, node.whatsits() do
+ whatsits[k], whatsits[v] = v, k -- two way
+end
+
+local function register_node(n)
+ reserved[#reserved+1] = n
+ return n
+end
+
+nodes.register = register_node
+
+function nodes.cleanup_reserved(nofboxes) -- todo
+ nodes.tracers.steppers.reset() -- todo: make a registration subsystem
+ local nr, nl = #reserved, 0
+ for i=1,nr do
+ local ri = reserved[i]
+ -- if not (ri.id == glue_spec and not ri.is_writable) then
+ free_node(reserved[i])
+ -- end
+ end
+ if nofboxes then
+ local tb = tex.box
+ for i=0,nofboxes do
+ local l = tb[i]
+ if l then
+ free_node(tb[i])
+ nl = nl + 1
+ end
+ end
+ end
+ reserved = { }
+ return nr, nl, nofboxes -- can be nil
+end
+
+function nodes.usage()
+ local t = { }
+ for n, tag in gmatch(status.node_mem_usage,"(%d+) ([a-z_]+)") do
+ t[tag] = n
+ end
+ return t
+end
+
+local disc = register_node(new_node("disc"))
+local kern = register_node(new_node("kern",1))
+local penalty = register_node(new_node("penalty"))
+local glue = register_node(new_node("glue")) -- glue.spec = nil
+local glue_spec = register_node(new_node("glue_spec"))
+local glyph = register_node(new_node("glyph",0))
+local textdir = register_node(new_node("whatsit",whatsits.dir)) -- 7 (6 is local par node)
+local rule = register_node(new_node("rule"))
+local latelua = register_node(new_node("whatsit",whatsits.late_lua)) -- 35
+local user_n = register_node(new_node("whatsit",whatsits.user_defined)) user_n.type = 100 -- 44
+local user_l = register_node(new_node("whatsit",whatsits.user_defined)) user_l.type = 110 -- 44
+local user_s = register_node(new_node("whatsit",whatsits.user_defined)) user_s.type = 115 -- 44
+local user_t = register_node(new_node("whatsit",whatsits.user_defined)) user_t.type = 116 -- 44
+local left_margin_kern = register_node(new_node("margin_kern",0))
+local right_margin_kern = register_node(new_node("margin_kern",1))
+local lineskip = register_node(new_node("glue",1))
+local baselineskip = register_node(new_node("glue",2))
+local leftskip = register_node(new_node("glue",8))
+local rightskip = register_node(new_node("glue",9))
+local temp = register_node(new_node("temp",0))
+
+function nodes.zeroglue(n)
+ local s = n.spec
+ return not writable or (
+ s.width == 0
+ and s.stretch == 0
+ and s.shrink == 0
+ and s.stretch_order == 0
+ and s.shrink_order == 0
+ )
+end
+
+function nodes.glyph(fnt,chr)
+ local n = copy_node(glyph)
+ if fnt then n.font = fnt end
+ if chr then n.char = chr end
+ return n
+end
+
+function nodes.penalty(p)
+ local n = copy_node(penalty)
+ n.penalty = p
+ return n
+end
+
+function nodes.kern(k)
+ local n = copy_node(kern)
+ n.kern = k
+ return n
+end
+
+function nodes.glue_spec(width,stretch,shrink)
+ local s = copy_node(glue_spec)
+ s.width, s.stretch, s.shrink = width, stretch, shrink
+ return s
+end
+
+local function someskip(skip,width,stretch,shrink)
+ local n = copy_node(skip)
+ if not width then
+ -- no spec
+ elseif tonumber(width) then
+ local s = copy_node(glue_spec)
+ s.width, s.stretch, s.shrink = width, stretch, shrink
+ n.spec = s
+ else
+ -- shared
+ n.spec = copy_node(width)
+ end
+ return n
+end
+
+function nodes.glue(width,stretch,shrink)
+ return someskip(glue,width,stretch,shrink)
+end
+function nodes.leftskip(width,stretch,shrink)
+ return someskip(leftskip,width,stretch,shrink)
+end
+function nodes.rightskip(width,stretch,shrink)
+ return someskip(rightskip,width,stretch,shrink)
+end
+function nodes.lineskip(width,stretch,shrink)
+ return someskip(lineskip,width,stretch,shrink)
+end
+function nodes.baselineskip(width,stretch,shrink)
+ return someskip(baselineskip,width,stretch,shrink)
+end
+
+function nodes.disc()
+ return copy_node(disc)
+end
+
+function nodes.textdir(dir)
+ local t = copy_node(textdir)
+ t.dir = dir
+ return t
+end
+
+function nodes.rule(width,height,depth,dir)
+ local n = copy_node(rule)
+ if width then n.width = width end
+ if height then n.height = height end
+ if depth then n.depth = depth end
+ if dir then n.dir = dir end
+ return n
+end
+
+function nodes.latelua(code)
+ local n = copy_node(latelua)
+ n.data = code
+ return n
+end
+
+function nodes.leftmarginkern(glyph,width)
+ local n = copy_node(left_margin_kern)
+ if not glyph then
+ logs.fatal("nodes","invalid pointer to left margin glyph node")
+ elseif glyph.id ~= glyph_node then
+ logs.fatal("nodes","invalid node type %s for left margin glyph node",node_type(glyph))
+ else
+ n.glyph = glyph
+ end
+ if width then
+ n.width = width
+ end
+ return n
+end
+
+function nodes.rightmarginkern(glyph,width)
+ local n = copy_node(right_margin_kern)
+ if not glyph then
+ logs.fatal("nodes","invalid pointer to right margin glyph node")
+ elseif glyph.id ~= glyph_node then
+ logs.fatal("nodes","invalid node type %s for right margin glyph node",node_type(p))
+ else
+ n.glyph = glyph
+ end
+ if width then
+ n.width = width
+ end
+ return n
+end
+
+function nodes.temp()
+ return copy_node(temp)
+end
+--[[
+
At some point we ran into a problem that the glue specification
+of the zeropoint dimension was overwritten when adapting a glue spec
+node. This is a side effect of glue specs being shared. After a
+couple of hours tracing and debugging Taco and I came to the
+conclusion that it made no sense to complicate the spec allocator
+and settled on a writable flag. This all is a side effect of the
+fact that some glues use reserved memory slots (with the zeropoint
+glue being a noticeable one). So, next we wrap this into a function
+and hide it for the user. And yes, LuaTeX now gives a warning as
+well.
+]]--
+
+if tex.luatexversion > 51 then
+
+ function nodes.writable_spec(n)
+ local spec = n.spec
+ if not spec then
+ spec = copy_node(glue_spec)
+ n.spec = spec
+ elseif not spec.writable then
+ spec = copy_node(spec)
+ n.spec = spec
+ end
+ return spec
+ end
+
+else
+
+ function nodes.writable_spec(n)
+ local spec = n.spec
+ if not spec then
+ spec = copy_node(glue_spec)
+ else
+ spec = copy_node(spec)
+ end
+ n.spec = spec
+ return spec
+ end
+
+end
+
+local cache = { }
+
+function nodes.usernumber(num)
+ local n = cache[num]
+ if n then
+ return copy_node(n)
+ else
+ local n = copy_node(user_n)
+ if num then n.value = num end
+ return n
+ end
+end
+
+function nodes.userlist(list)
+ local n = copy_node(user_l)
+ if list then n.value = list end
+ return n
+end
+
+local cache = { } -- we could use the same cache
+
+function nodes.userstring(str)
+ local n = cache[str]
+ if n then
+ return copy_node(n)
+ else
+ local n = copy_node(user_s)
+ n.type = 115
+ if str then n.value = str end
+ return n
+ end
+end
+
+function nodes.usertokens(tokens)
+ local n = copy_node(user_t)
+ if tokens then n.value = tokens end
+ return n
+end
+
+statistics.register("cleaned up reserved nodes", function()
+ return format("%s nodes, %s lists of %s", nodes.cleanup_reserved(tex.count["lastallocatedbox"]))
+end) -- \topofboxstack
+
+statistics.register("node memory usage", function() -- comes after cleanup !
+ return status.node_mem_usage
+end)
diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua
new file mode 100644
index 000000000..9dd89bcda
--- /dev/null
+++ b/tex/context/base/node-rul.lua
@@ -0,0 +1,288 @@
+if not modules then modules = { } end modules ['node-rul'] = {
+ version = 1.001,
+ comment = "companion to node-rul.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this will go to an auxiliary module
+-- beware: rules now have a dir field
+
+local glyph = node.id("glyph")
+local disc = node.id("disc")
+local rule = node.id("rule")
+
+function nodes.strip_range(first,last) -- todo: dir
+ if first and last then -- just to be sure
+ local current = first
+ while current and current ~= last do
+ local id = current.id
+ if id == glyph or id == disc then
+ --~ if id == glyph or id == rule or id == disc then
+ first = current
+ break
+ else
+ current = current.next
+ end
+ end
+ local current = last
+ while current and current ~= first do
+ local id = current.id
+ --~ if id == glyph or id == rule or id == disc then
+ if id == glyph or id == disc then
+ last = current
+ break
+ else
+ current = current.prev
+ end
+ end
+ end
+ return first, last
+end
+
+-- todo: order and maybe other dimensions
+
+local trace_ruled = false trackers.register("nodes.ruled", function(v) trace_ruled = v end)
+
+local floor = math.floor
+local n_tostring, n_tosequence = nodes.ids_tostring, nodes.tosequence
+
+local a_ruled = attributes.private('ruled')
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+
+local glyph = node.id("glyph")
+local disc = node.id("disc")
+local glue = node.id("glue")
+local penalty = node.id("penalty")
+local kern = node.id("kern")
+local hlist = node.id("hlist")
+local vlist = node.id("vlist")
+local rule = node.id("rule")
+local whatsit = node.id("whatsit")
+
+local new_rule = nodes.rule
+local new_kern = nodes.kern
+local new_glue = nodes.glue
+
+local insert_before, insert_after, strip_range = node.insert_before, node.insert_after, nodes.strip_range
+local list_dimensions, has_attribute, set_attribute = node.dimensions, node.has_attribute, node.set_attribute
+local hpack_nodes = node.hpack
+local dimenfactor = fonts.dimenfactor
+local texwrite = tex.write
+
+local fontdata = fonts.ids
+local variables = interfaces.variables
+
+-- we can use this one elsewhere too
+--
+-- todo: functions: word, sentence
+--
+-- glyph rule unset whatsit glue margin_kern kern math disc
+
+local checkdir = true
+
+-- we assume {glyphruns} and no funny extra kerning, ok, maybe we need
+-- a dummy character as start and end; anyway we only collect glyphs
+
+local function process_words(attribute,data,flush,head,parent) -- we have hlistdir and local dir
+ local n = head
+ if n then
+ local f, l, a, d, i, level
+ local continue, done, strip = false, false, false
+ while n do
+ local id = n.id
+ if id == glyph or id == rule then
+ local aa = has_attribute(n,attribute)
+ if aa then
+ if aa == a then
+ if not f then -- ?
+ f = n
+ end
+ l = n
+ else
+ -- possible extensions: when in same class then keep spanning
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ f, l, a = n, n, aa
+ level, i = floor(a/1000), a%1000
+ d = data[i]
+ continue = d.continue == variables.yes
+ end
+ else
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ f, l, a = nil, nil, nil
+ end
+ elseif f and (id == disc or (id == kern and n.subtype == 0)) then
+ l = n
+ elseif id == hlist or id == vlist then
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ f, l, a = nil, nil, nil
+ end
+ local list = n.list
+ if list then
+ n.list = process_words(attribute,data,flush,list,n)
+ end
+ elseif checkdir and id == whatsit and n.subtype == 7 then -- only changes in dir, we assume proper boundaries
+ if f and a then
+ l = n
+ end
+ elseif f then
+ if continue then
+ if id == penalty or id == kern then
+ l = n
+ elseif id == glue then
+ l = n
+ end
+ else
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ f, l, a = nil, nil, nil
+ end
+ end
+ n = n.next
+ end
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ return head, true -- todo: done
+ else
+ return head, false
+ end
+end
+
+nodes.process_words = process_words
+
+--
+
+nodes.rules = nodes.rules or { }
+nodes.rules.data = nodes.rules.data or { }
+
+storage.register("nodes/rules/data", nodes.rules.data, "nodes.rules.data")
+
+local data = nodes.rules.data
+
+function nodes.rules.define(settings)
+ data[#data+1] = settings
+ texwrite(#data)
+end
+
+local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose
+-- check for f and l
+ local r, m
+ if true then
+ f, l = strip_range(f,l)
+ end
+ local w = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,f,l.next)
+ local method, offset, continue, dy, rulethickness, unit, order, max, ma, ca, ta =
+ d.method, d.offset, d.continue, d.dy, d.rulethickness, d.unit, d.order, d.max, d.ma, d.ca, d.ta
+ local e = dimenfactor(unit,fontdata[f.font])
+ local colorspace = (ma > 0 and ma) or has_attribute(f,a_colorspace) or 1
+ local color = (ca > 0 and ca) or has_attribute(f,a_color)
+ local transparency = (ta > 0 and ta) or has_attribute(f,a_transparency)
+ local foreground = order == variables.foreground
+ rulethickness= rulethickness/2
+ if level > max then
+ level = max
+ end
+ if method == 0 then -- center
+ offset = 2*offset
+ m = (offset+(level-1)*dy+rulethickness)*e/2
+ else
+ m = 0
+ end
+ for i=1,level do
+ local ht = (offset+(i-1)*dy+rulethickness)*e - m
+ local dp = -(offset+(i-1)*dy-rulethickness)*e + m
+ local r = new_rule(w,ht,dp)
+ if color then
+ set_attribute(r,a_colorspace,colorspace)
+ set_attribute(r,a_color,color)
+ end
+ if transparency then
+ set_attribute(r,a_transparency,transparency)
+ end
+ local k = new_kern(-w)
+ if foreground then
+ insert_after(head,l,k)
+ insert_after(head,k,r)
+ l = r
+ else
+ head, _ = insert_before(head,f,r)
+ insert_after(head,r,k)
+ end
+ if trace_ruled then
+ logs.report("ruled", "level: %s, width: %i, height: %i, depth: %i, nodes: %s, text: %s",
+ level,w,ht,dp,n_tostring(f,l),n_tosequence(f,l,true))
+ -- level,r.width,r.height,r.depth,n_tostring(f,l),n_tosequence(f,l,true))
+ end
+ end
+ return head
+end
+
+local process = nodes.process_words
+
+nodes.rules.process = function(head) return process(a_ruled,data,flush_ruled,head) end
+
+function nodes.rules.enable()
+ tasks.enableaction("shipouts","nodes.rules.process")
+end
+
+-- elsewhere:
+--
+-- tasks.appendaction ("shipouts", "normalizers", "nodes.rules.process")
+-- tasks.disableaction("shipouts", "nodes.rules.process") -- only kick in when used
+
+local trace_shifted = false trackers.register("nodes.shifted", function(v) trace_shifted = v end)
+
+local a_shifted = attributes.private('shifted')
+
+nodes.shifts = nodes.shifts or { }
+nodes.shifts.data = nodes.shifts.data or { }
+
+storage.register("nodes/shifts/data", nodes.shifts.data, "nodes.shifts.data")
+
+local data = nodes.shifts.data
+
+function nodes.shifts.define(settings)
+ data[#data+1] = settings
+ texwrite(#data)
+end
+
+local function flush_shifted(head,first,last,data,level,parent,strip) -- not that fast but acceptable for this purpose
+ if true then
+ first, last = strip_range(first,last)
+ end
+ local prev, next = first.prev, last.next
+ first.prev, last.next = nil, nil
+ local width, height, depth = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,first,next)
+ local list = hpack_nodes(first,width,"exactly")
+ if first == head then
+ head = list
+ end
+ if prev then
+ prev.next, list.prev = list, prev
+ end
+ if next then
+ next.prev, list.next = list, next
+ end
+ local raise = data.dy * dimenfactor(data.unit,fontdata[first.font])
+ list.shift, list.height, list.depth = raise, height, depth
+ if trace_shifted then
+ logs.report("shifted", "width: %s, nodes: %s, text: %s",width,n_tostring(first,last),n_tosequence(first,last,true))
+ end
+ return head
+end
+
+local process = nodes.process_words
+
+nodes.shifts.process = function(head) return process(a_shifted,data,flush_shifted,head) end
+
+function nodes.shifts.enable()
+ tasks.enableaction("shipouts","nodes.shifts.process")
+end
diff --git a/tex/context/base/node-rul.mkiv b/tex/context/base/node-rul.mkiv
new file mode 100644
index 000000000..1270eb81d
--- /dev/null
+++ b/tex/context/base/node-rul.mkiv
@@ -0,0 +1,343 @@
+%D \module
+%D [ file=node-rul,
+%D version=2009.11.03, % 1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Bars,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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: ex and and em traveling with attribute
+
+\writestatus{loading}{ConTeXt Core Macros / Bars}
+
+%D The name of this file might change.
+
+%D \macros
+%D {underbar,underbars,
+%D overbar,overbars,
+%D overstrike,overstrikes,
+%D setupbar}
+%D
+%D In the rare case that we need undelined words, for instance
+%D because all font alternatives are already in use, one can
+%D use \type{\underbar} and \type{\overstrike} and their plural
+%D forms.
+%D
+%D \startbuffer
+%D \underbars{drawing \underbar{bars} under words is a typewriter leftover}
+%D \overstrikes{striking words makes them \overstrike{unreadable} but
+%D sometimes even \overbar{top lines} come into view.}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D The next macros are derived from the \PLAIN\ \TEX\ one, but
+%D also supports nesting. The \type{$} keeps us in horizontal
+%D mode and at the same time applies grouping.
+%D
+%D \showsetup{underbar}
+%D \showsetup{underbars}
+%D \showsetup{overbar}
+%D \showsetup{overbars}
+%D \showsetup{overstrike}
+%D \showsetup{overstrikes}
+%D
+%D \showsetup{setupunderbar}
+
+\unprotect
+
+%definesystemattribute[ruled]
+%definesystemattribute[shifted]
+
+\registerctxluafile{node-rul}{1.001}
+
+\newtoks\checkalldefinedbars
+
+\def\barparameter #1{\csname\dobarparameter\currentbar#1\endcsname}
+\def\dobarparameter #1#2{\ifcsname\??on#1#2\endcsname\??on#1#2\else\expandafter\dobarparentparameter\csname\??on#1\s!parent\endcsname#2\fi}
+\def\dobarparentparameter#1#2{\ifx#1\relax\s!empty\else\dobarparameter#1#2\fi}
+
+\unexpanded\def\definebar
+ {\dotripleempty\dodefinebar}
+
+\def\dodefinebar[#1][#2][#3]%
+ {\ifthirdargument
+ \getparameters[\??on#1][\s!parent=#2,#3]%
+ \else
+ \getparameters[\??on#1][\s!parent=,#2]%
+ \fi
+ %
+ %\setvalue{\??on:#1}{0}%
+ %
+ \ifcsname\??on:#1:c\endcsname
+ \csname\??on:#1:c\endcsname\zerocount
+ \else
+ \expandafter\newcount\csname\??on:#1:c\endcsname
+ \fi
+ \normalexpanded{\checkalldefinedbars{\noexpand\doredefinebar{#1}\the\checkalldefinedbars}}%
+ \dodefinebarindeed{#1}%
+ \setuvalue{#1}{\doruled{#1}}}
+
+\def\dodefinebarindeed#1%
+ {\bgroup
+ \def\currentbar{#1}%
+ \doifsomethingelse{\barparameter\c!color}
+ {\donetrue\colored[\barparameter\c!color]}
+ {\donefalse}%
+ \normalexpanded
+ {\egroup
+ \scratchcounter\ctxlua{nodes.rules.define {
+ method = \barparameter\c!method,
+ offset = \barparameter\c!offset,
+ continue = "\barparameter\c!continue",
+ dy = \barparameter\c!dy,
+ rulethickness = \barparameter\c!rulethickness,
+ unit = "\barparameter\c!unit",
+ order = "\barparameter\c!order",
+ max = \barparameter\c!max,
+ ma = \ifdone\the\attribute\colormodelattribute \else0\fi,
+ ca = \ifdone\the\attribute\colorattribute \else0\fi,
+ ta = \ifdone\the\attribute\transparencyattribute\else0\fi
+ }}}%
+ \setevalue{\??on#1:a}{\the\scratchcounter}}
+
+\let\doredefinebar\dodefinebarindeed
+
+\def\doruled#1%
+ {\groupedcommand{\dodoruled{#1}}\relax}
+
+\def\dodoruled
+ {\ctxlua{nodes.rules.enable()}%
+ \glet\dodoruled\dodoruledindeed
+ \dodoruled}
+
+\def\dodoruledindeed#1%
+ {\advance\csname\??on:#1:c\endcsname\plusone
+ \scratchcounter\csname\??on:#1:c\endcsname
+ \attribute\ruledattribute\numexpr1000*\scratchcounter
+ +\csname\??on#1\ifcsname\??on#1:\number\scratchcounter\s!parent\endcsname:\number\scratchcounter\fi:a\endcsname}
+
+% ungrouped
+
+\unexpanded\def\startbar[#1]%
+ {\begingroup
+ \dodoruled{#1}}
+
+\unexpanded\def\stopbar
+ {\endgroup}
+
+\newcount\currentbarnesting % todo: same as colors
+
+\unexpanded\def\pushbar[#1]%
+ {\global\advance\currentbarnesting\plusone
+ \expandafter\edef\csname\??on:s:\number\currentbarnesting\endcsname
+ {\attribute\ruledattribute\the\attribute\ruledattribute}% stack
+ \dodoruled{#1}}
+
+\unexpanded\def\popbar
+ {\csname\??on:s:\number\currentbarnesting\endcsname
+ \global\advance\currentbarnesting\minusone}
+
+\unexpanded\def\setupbars
+ {\dodoubleempty\dosetupbars}
+
+\def\dosetupbars[#1][#2]% not that efficient
+ {\ifsecondargument
+ \getparameters[\??on#1][#2]%
+ \dodefinebarindeed{#1}%
+ \else
+ \getparameters[\??on][#1]%
+ \the\checkalldefinedbars
+ \fi}
+
+\setupbars
+ [\c!method=0, % new: 0=center nested, 1=stack nested
+ \c!continue=\v!no,
+ \c!offset=0, % upwards, replaces: topoffset bottomoffset
+ \c!dy=0,
+ \c!max=3,
+ \c!rulethickness=.1,
+ \c!order=\v!foreground,
+ \c!unit=ex, % so now we are relative
+ \c!color=] % replaces: rulecolor
+
+% \definebar[touchbar] [\c!method=0,\c!dy=-0.4,\c!offset=-0.0]
+% \definebar[touchbars] [touchbar] [\c!continue=\v!yes]
+
+\definebar[\v!overstrike] [\c!method=0,\c!dy= 0.4,\c!offset= 0.5,\c!continue=\v!yes]
+\definebar[\v!underbar] [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes]
+\definebar[\v!overbar] [\c!method=1,\c!dy= 0.4,\c!offset= 1.8,\c!continue=\v!yes]
+
+\definebar[\v!overstrikes] [\v!overstrike] [\c!continue=\v!no]
+\definebar[\v!underbars] [\v!underbar] [\c!continue=\v!no]
+\definebar[\v!overbars] [\v!overbar] [\c!continue=\v!no]
+
+% we want these always so ...
+
+\expandafter\let\expandafter\overstrike \csname\v!overstrike \endcsname
+\expandafter\let\expandafter\underbar \csname\v!underbar \endcsname
+\expandafter\let\expandafter\overbar \csname\v!overbar \endcsname
+\expandafter\let\expandafter\overstrikes\csname\v!overstrikes\endcsname
+\expandafter\let\expandafter\underbars \csname\v!underbars \endcsname
+\expandafter\let\expandafter\overbars \csname\v!overbars \endcsname
+
+\unexpanded\def\setupunderbar[#1]% too incompatible for the moment
+ {}
+
+%D This will move: (a bit duplicated)
+
+\newtoks\checkalldefinedshifts
+
+\def\shiftparameter #1{\csname\doshiftparameter\currentshift#1\endcsname}
+\def\shiftparameterhash#1{\doshiftparameterhash{\??ra\currentshift}#1}
+
+\def\doshiftparameter #1#2{\ifcsname\??ra#1#2\endcsname\??ra#1#2\else\expandafter\doshiftparentparameter\csname\??ra#1\s!parent\endcsname#2\fi}
+\def\doshiftparameterhash#1#2{\ifcsname#1#2\endcsname#1\else\expandafter\doshiftparentparameterhash\csname#1\s!parent\endcsname#2\fi}
+
+\def\doshiftparentparameter #1#2{\ifx#1\relax\s!empty\else\doshiftparameter #1#2\fi}
+\def\doshiftparentparameterhash#1#2{\ifx#1\relax \else\doshiftparameterhash#1#2\fi}
+
+\def\dosetshiftattributes#1#2% style color
+ {\edef\fontattributehash {\shiftparameterhash#1}%
+ \edef\colorattributehash{\shiftparameterhash#2}%
+ \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
+ \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
+
+\unexpanded\def\defineshift
+ {\dotripleempty\dodefineshift}
+
+\def\dodefineshift[#1][#2][#3]%
+ {\ifthirdargument
+ \getparameters[\??ra#1][\s!parent=#2,#3]%
+ \else
+ \getparameters[\??ra#1][\s!parent=,#2]%
+ \fi
+ %
+ %\setvalue{\??ra:#1}{0}%
+ %
+ \ifcsname\??ra:#1:c\endcsname
+ \csname\??ra:#1:c\endcsname\zerocount
+ \else
+ \expandafter\newcount\csname\??ra:#1:c\endcsname
+ \fi
+ \normalexpanded{\checkalldefinedshifts{\noexpand\doredefineshift{#1}\the\checkalldefinedshifts}}%
+ \dodefineshiftindeed{#1}%
+ \setuvalue{#1}{\doshifted{#1}}}
+
+\def\dodefineshiftindeed#1%
+ {\bgroup
+ \def\currentshift{#1}%
+ \normalexpanded
+ {\egroup
+ \scratchcounter\ctxlua{nodes.shifts.define {
+ method = \shiftparameter\c!method,
+ continue = "\shiftparameter\c!continue",
+ dy = \shiftparameter\c!dy,
+ unit = "\shiftparameter\c!unit",
+ }}}%
+ \setevalue{\??ra#1:a}{\the\scratchcounter}}
+
+\let\doredefineshift\dodefineshiftindeed
+
+\def\doshifted#1%
+ {\groupedcommand{\dodoshifted{#1}}\relax}
+
+\def\dodoshifted
+ {\ctxlua{nodes.shifts.enable()}%
+ \glet\dodoshifted\dodoshiftedindeed
+ \dodoshifted}
+
+% \def\dodoshiftedindeed#1%
+% {\def\currentshift{#1}%
+% \advance\csname\??ra:#1:c\endcsname\plusone
+% \scratchcounter\csname\??ra:#1:c\endcsname
+% \attribute\shiftedattribute\numexpr1000*\scratchcounter
+% +\csname\??ra#1\ifcsname\??ra#1:\number\scratchcounter\s!parent\endcsname:\number\scratchcounter\fi:a\endcsname
+% \setupalign[\shiftparameter\c!align]%
+% \dosetshiftattributes\c!style\c!color}
+
+\def\dostartisolation{\char0 }
+\def\dostopisolation {\char0 }
+\def\doisolator {\char0 }
+
+\def\doisolatedgroupedalign#1#2%
+ {\groupedcommand
+ {\begingroup\dostartisolation\begingroup#1}
+ {#2\endgroup\dostopisolation\endgroup}}
+
+\def\dosetupisolatedalign#1%
+ {\doisolator
+ \setupalign[#1]\relax}
+
+\def\dodoshiftedindeed#1%
+ {\def\currentshift{#1}%
+ \advance\csname\??ra:#1:c\endcsname\plusone
+ \scratchcounter\csname\??ra:#1:c\endcsname
+ \attribute\shiftedattribute\numexpr1000*\scratchcounter
+ +\csname\??ra#1\ifcsname\??ra#1:\number\scratchcounter\s!parent\endcsname:\number\scratchcounter\fi:a\endcsname
+ \dosetshiftattributes\c!style\c!color
+ \dosetupisolatedalign{\shiftparameter\c!align}}
+
+\def\doshifted#1%
+ {\doisolatedgroupedalign{\dodoshifted{#1}}{}}
+
+\unexpanded\def\startshift[#1]%
+ {\begingroup
+ \dodoshifted{#1}}
+
+\unexpanded\def\stopshift
+ {\endgroup}
+
+\unexpanded\def\setupshifts
+ {\dodoubleempty\dosetupshifts}
+
+\def\dosetupshifts[#1][#2]% not that efficient
+ {\ifsecondargument
+ \getparameters[\??ra#1][#2]%
+ \dodefineshiftindeed{#1}%
+ \else
+ \getparameters[\??ra][#1]%
+ \the\checkalldefinedshifts
+ \fi}
+
+\setupshifts
+ [\c!method=0,
+ \c!continue=\v!no,
+ \c!dy=0,
+ \c!unit=ex,
+ \c!align=,
+ \c!style=,
+ \c!color=]
+
+\def\v!shiftup {shiftup}
+\def\v!shiftdown{shiftdown}
+
+\defineshift [\v!shiftup] [\c!method=0,\c!dy=-1,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]
+\defineshift [\v!shiftdown] [\c!method=1,\c!dy=.3,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]
+
+% we want these always so ...
+
+\expandafter\let\expandafter\shiftup \csname\v!shiftup \endcsname
+\expandafter\let\expandafter\shiftdown \csname\v!shiftdown \endcsname
+
+\protect \endinput
+
+% obsolete:
+
+\setupunderbar
+ [\c!alternative=a,
+ \c!rulethickness=\linewidth,
+ \c!bottomoffset=1.5pt,
+ \c!topoffset=2.5pt,
+ \c!rulecolor=]
diff --git a/tex/context/base/node-seq.lua b/tex/context/base/node-seq.lua
new file mode 100644
index 000000000..3a2cf5b6e
--- /dev/null
+++ b/tex/context/base/node-seq.lua
@@ -0,0 +1,186 @@
+if not modules then modules = { } end modules ['node-seq'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
Here we implement a mechanism for chaining the special functions
+that we use in to deal with mode list processing. We
+assume that namespaces for the functions are used, but for speed we
+use locals to refer to them when compiling the chain.
+--ldx]]--
+
+-- todo: delayed: i.e. we register them in the right order already but delay usage
+
+local format, gsub, concat, gmatch = string.format, string.gsub, table.concat, string.gmatch
+local type, loadstring = type, loadstring
+
+sequencer = sequencer or { }
+
+local function validaction(action)
+ local g = _G
+ for str in gmatch(action,"[^%.]+") do
+ g = g[str]
+ if not g then
+ return false
+ end
+ end
+ return true
+end
+
+function sequencer.reset()
+ return {
+ list = { },
+ order = { },
+ kind = { },
+ askip = { },
+ gskip = { },
+ }
+end
+
+function sequencer.prependgroup(t,group,where)
+ local list, order = t.list, t.order
+ table.remove_value(order,group)
+ table.insert_before_value(order,where,group)
+ list[group] = { }
+end
+
+function sequencer.appendgroup(t,group,where)
+ local list, order = t.list, t.order
+ table.remove_value(order,group)
+ table.insert_after_value(order,where,group)
+ list[group] = { }
+end
+
+function sequencer.prependaction(t,group,action,where,kind,force)
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ table.remove_value(g,action)
+ table.insert_before_value(g,where,action)
+ t.kind[action] = kind
+ end
+end
+
+function sequencer.appendaction(t,group,action,where,kind,force)
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ table.remove_value(g,action)
+ table.insert_after_value(g,where,action)
+ t.kind[action] = kind
+ end
+end
+
+function sequencer.enableaction (t,action) t.askip[action] = false end
+function sequencer.disableaction(t,action) t.askip[action] = true end
+function sequencer.enablegroup (t,group) t.gskip[group] = false end
+function sequencer.disablegroup (t,group) t.gskip[group] = true end
+
+function sequencer.setkind(t,action,kind)
+ t.kind[action] = kind
+end
+
+function sequencer.removeaction(t,group,action,force)
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ table.remove_value(g,action)
+ end
+end
+
+function sequencer.compile(t,compiler,n)
+ if type(t) == "string" then
+ -- already compiled
+ elseif compiler then
+ t = compiler(t,n)
+ else
+ t = sequencer.tostring(t)
+ end
+ return loadstring(t)()
+end
+
+local function localize(str)
+ return (gsub(str,"%.","_"))
+end
+
+local template = [[
+%s
+return function(...)
+%s
+end]]
+
+function sequencer.tostring(t)
+ local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
+ local vars, calls, args = { }, { }, nil
+ for i=1,#order do
+ local group = order[i]
+ if not gskip[group] then
+ local actions = list[group]
+ for i=1,#actions do
+ local action = actions[i]
+ if not askip[action] then
+ local localized = localize(action)
+ vars [#vars +1] = format("local %s = %s", localized, action)
+ calls[#calls+1] = format(" %s(...) -- %s %i", localized, group, i)
+ end
+ end
+ end
+ end
+ return format(template,concat(vars,"\n"),concat(calls,"\n"))
+end
+
+-- we used to deal with tail as well but now that the lists are always
+-- double linked and the kernel function no longer expect tail as
+-- argument we stick to head and done (done can probably also go
+-- as luatex deals with return values efficiently now .. in the
+-- past there was some copying involved, but no longer)
+
+local template = [[
+%s
+return function(head%s)
+ local ok, done = false, false
+%s
+ return head, done
+end]]
+
+function sequencer.nodeprocessor(t,n)
+ local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
+ local vars, calls, args = { }, { }, nil
+ if n == 0 then
+ args = ""
+ elseif n == 1 then
+ args = ",one"
+ elseif n == 2 then
+ args = ",one,two"
+ elseif n == 3 then
+ args = ",one,two,three"
+ elseif n == 4 then
+ args = ",one,two,three,four"
+ elseif n == 5 then
+ args = ",one,two,three,four,five"
+ else
+ args = ",..."
+ end
+ for i=1,#order do
+ local group = order[i]
+ if not gskip[group] then
+ local actions = list[group]
+ for i=1,#actions do
+ local action = actions[i]
+ if not askip[action] then
+ local localized = localize(action)
+ vars[#vars+1] = format("local %s = %s",localized,action)
+ if kind[action] == "nohead" then
+ calls[#calls+1] = format(" ok = %s(head%s) done = done or ok -- %s %i",localized,args,group,i)
+ else
+ calls[#calls+1] = format(" head, ok = %s(head%s) done = done or ok -- %s %i",localized,args,group,i)
+ end
+ end
+ end
+ end
+ end
+ local processor = format(template,concat(vars,"\n"),args,concat(calls,"\n"))
+--~ print(processor)
+ return processor
+end
diff --git a/tex/context/base/node-ser.lua b/tex/context/base/node-ser.lua
new file mode 100644
index 000000000..e632e92da
--- /dev/null
+++ b/tex/context/base/node-ser.lua
@@ -0,0 +1,276 @@
+if not modules then modules = { } end modules ['node-ser'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- beware, some field names will change in a next releases
+-- of luatex; this is pretty old code that needs an overhaul
+
+local type, format, concat = type, string.format, table.concat
+
+local ctxcatcodes = tex.ctxcatcodes
+
+local hlist = node.id('hlist')
+local vlist = node.id('vlist')
+
+local traverse = node.traverse
+local node_fields = node.fields
+local node_type = node.type
+
+local expand = table.tohash {
+ "list", -- list_ptr & ins_ptr & adjust_ptr
+ "pre", --
+ "post", --
+ "spec", -- glue_ptr
+ "top_skip", --
+ "attr", --
+ "replace", -- nobreak
+ "components", -- lig_ptr
+ "box_left", --
+ "box_right", --
+ "glyph", -- margin_char
+ "leader", -- leader_ptr
+ "action", -- action_ptr
+ "value", -- user_defined nodes with subtype 'a' en 'n'
+}
+
+-- page_insert: "height", "last_ins_ptr", "best_ins_ptr"
+-- split_insert: "height", "last_ins_ptr", "best_ins_ptr", "broken_ptr", "broken_ins"
+
+local ignore = table.tohash {
+ "page_insert",
+ "split_insert",
+ "ref_count",
+}
+
+local dimension = table.tohash {
+ "width", "height", "depth", "shift",
+ "stretch", "shrink",
+ "xoffset", "yoffset",
+ "surround",
+ "kern",
+ "box_left_width", "box_right_width"
+}
+
+-- flat: don't use next, but indexes
+-- verbose: also add type
+-- can be sped up
+
+nodes.dimensionfields = dimension
+nodes.listablefields = expand
+nodes.ignorablefields = ignore
+
+-- not ok yet:
+
+function nodes.astable(n,sparse) -- not yet ok
+ local f, t = node_fields(n.id,n.subtype), { }
+ for i=1,#f do
+ local v = f[i]
+ local d = n[v]
+ if d then
+ if ignore[v] or v == "id" then
+ -- skip
+ elseif expand[v] then -- or: type(n[v]) ~= "string" or type(n[v]) ~= "number" or type(n[v]) ~= "table"
+ t[v] = "pointer to list"
+ elseif sparse then
+ if (type(d) == "number" and d ~= 0) or (type(d) == "string" and d ~= "") then
+ t[v] = d
+ end
+ else
+ t[v] = d
+ end
+ end
+ end
+ t.type = node_type(n.id)
+ return t
+end
+
+-- under construction:
+
+local function totable(n,flat,verbose)
+ -- todo: no local function
+ local function to_table(n,flat,verbose)
+ local f = node_fields(n.id,n.subtype)
+ local tt = { }
+ for k=1,#f do
+ local v = f[k]
+ local nv = n[v]
+ if nv then
+ if ignore[v] then
+ -- skip
+ elseif expand[v] then
+ if type(nv) == "number" or type(nv) == "string" then
+ tt[v] = nv
+ else
+ tt[v] = totable(nv,flat,verbose)
+ end
+ elseif type(nv) == "table" then
+ tt[v] = nv -- totable(nv,flat,verbose) -- data
+ else
+ tt[v] = nv
+ end
+ end
+ end
+ if verbose then
+ tt.type = node_type(tt.id)
+ end
+ return tt
+ end
+ if n then
+ if flat then
+ local t = { }
+ while n do
+ t[#t+1] = to_table(n,flat,verbise)
+ n = n.next
+ end
+ return t
+ else
+ local t = to_table(n)
+ if n.next then
+ t.next = totable(n.next,flat,verbose)
+ end
+ return t
+ end
+ else
+ return { }
+ end
+end
+
+nodes.totable = totable
+
+local function key(k)
+ return ((type(k) == "number") and "["..k.."]") or k
+end
+
+-- not ok yet; this will become a module
+
+local function serialize(root,name,handle,depth,m)
+ handle = handle or print
+ if depth then
+ depth = depth .. " "
+ handle(format("%s%s={",depth,key(name)))
+ else
+ depth = ""
+ local tname = type(name)
+ if tname == "string" then
+ if name == "return" then
+ handle("return {")
+ else
+ handle(name .. "={")
+ end
+ elseif tname == "number" then
+ handle("[" .. name .. "]={")
+ else
+ handle("t={")
+ end
+ end
+ if root then
+ local fld
+ if root.id then
+ fld = node_fields(root.id,root.subtype) -- we can cache these (todo)
+ else
+ fld = table.sortedkeys(root)
+ end
+ if type(root) == 'table' and root['type'] then -- userdata or table
+ handle(format("%s %s=%q,",depth,'type',root['type']))
+ end
+ for f=1,#fld do
+ local k = fld[f]
+ if k == "ref_count" then
+ -- skip
+ elseif k then
+ local v = root[k]
+ local t = type(v)
+ if t == "number" then
+ if v == 0 then
+ -- skip
+ else
+ handle(format("%s %s=%s,",depth,key(k),v))
+ end
+ elseif t == "string" then
+ if v == "" then
+ -- skip
+ else
+ handle(format("%s %s=%q,",depth,key(k),v))
+ end
+ elseif t == "boolean" then
+ handle(format("%s %s=%q,",depth,key(k),tostring(v)))
+ elseif v then -- userdata or table
+ serialize(v,k,handle,depth,m+1)
+ end
+ end
+ end
+ if root['next'] then -- userdata or table
+ serialize(root['next'],'next',handle,depth,m+1)
+ end
+ end
+ if m and m > 0 then
+ handle(format("%s},",depth))
+ else
+ handle(format("%s}",depth))
+ end
+end
+
+function nodes.serialize(root,name)
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
+ end
+ serialize(root, name, flush, nil, 0)
+ return concat(t,"\n")
+end
+
+function nodes.serializebox(n,flat,verbose,name)
+ return nodes.serialize(nodes.totable(tex.box[n],flat,verbose),name)
+end
+
+function nodes.visualizebox(...)
+ tex.print(ctxcatcodes,"\\starttyping")
+ tex.print(nodes.serializebox(...))
+ tex.print("\\stoptyping")
+end
+
+function nodes.list(head,n) -- name might change to nodes.type
+ if not n then
+ tex.print(ctxcatcodes,"\\starttyping")
+ end
+ while head do
+ local id = head.id
+ tex.print(string.rep(" ",n or 0) .. tostring(head) .. "\n")
+ if id == hlist or id == vlist then
+ nodes.list(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+ if not n then
+ tex.print("\\stoptyping")
+ end
+end
+
+function nodes.print(head,n)
+ while head do
+ local id = head.id
+ texio.write_nl(string.rep(" ",n or 0) .. tostring(head))
+ if id == hlist or id == vlist then
+ nodes.print(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+end
+
+function nodes.check_for_leaks(sparse)
+ local l = { }
+ local q = node.usedlist()
+ for p in traverse(q) do
+ local s = table.serialize(nodes.astable(p,sparse),node_type(p.id))
+ l[s] = (l[s] or 0) + 1
+ end
+ node.flush_list(q)
+ for k, v in next, l do
+ texio.write_nl(format("%s * %s", v, k))
+ end
+end
+
diff --git a/tex/context/base/node-shp.lua b/tex/context/base/node-shp.lua
new file mode 100644
index 000000000..50b16efa5
--- /dev/null
+++ b/tex/context/base/node-shp.lua
@@ -0,0 +1,58 @@
+if not modules then modules = { } end modules ['node-shp'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local hlist = node.id('hlist')
+local vlist = node.id('vlist')
+local disc = node.id('disc')
+local mark = node.id('mark')
+local kern = node.id('kern')
+local glue = node.id('glue')
+
+local free_node = node.free
+local remove_node = node.remove
+
+local function cleanup_page(head) -- rough
+ local start = head
+ while start do
+ local id = start.id
+ if id == disc or (id == glue and not start.writable) or (id == kern and start.kern == 0) or id == mark then
+ head, start, tmp = remove_node(head,start)
+ free_node(tmp)
+ elseif id == hlist or id == vlist then
+ local sl = start.list
+ if sl then
+ start.list = cleanup_page(sl)
+ start = start.next
+ else
+ head, start, tmp = remove_node(head,start)
+ free_node(tmp)
+ end
+ else
+ start = start.next
+ end
+ end
+ return head
+end
+
+nodes.cleanup_page_first = false
+
+function nodes.cleanup_page(head)
+ -- about 10% of the nodes make no sense for the backend
+ if nodes.cleanup_page_first then
+ head = cleanup_page(head)
+ end
+ return head, false
+end
+
+local actions = tasks.actions("shipouts",0) -- no extra arguments
+
+function nodes.process_page(head) -- problem, attr loaded before node, todo ...
+ return actions(head)
+end
+
+--~ nodes.process_page = actions
diff --git a/tex/context/base/node-tex.lua b/tex/context/base/node-tex.lua
new file mode 100644
index 000000000..a6eef3269
--- /dev/null
+++ b/tex/context/base/node-tex.lua
@@ -0,0 +1,39 @@
+if not modules then modules = { } end modules ['node-tex'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+kernel = kernel or { }
+
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+local hyphenate, ligaturing, kerning = lang.hyphenate, node.ligaturing, node.kerning
+
+function kernel.hyphenation(head)
+ -- starttiming(kernel)
+ local done = hyphenate(head)
+ -- stoptiming(kernel)
+ return head, done
+end
+
+function kernel.ligaturing(head)
+ -- starttiming(kernel)
+ local head, tail, done = ligaturing(head) -- todo: check what is returned
+ -- stoptiming(kernel)
+ return head, done
+end
+
+function kernel.kerning(head)
+ -- starttiming(kernel)
+ local head, tail, done = kerning(head) -- todo: check what is returned
+ -- stoptiming(kernel)
+ return head, done
+end
+
+callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere")
+callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere")
+callbacks.register('kerning' , false, "normal kerning routine, called elsewhere")
diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua
new file mode 100644
index 000000000..5acd70baf
--- /dev/null
+++ b/tex/context/base/node-tra.lua
@@ -0,0 +1,474 @@
+if not modules then modules = { } end modules ['node-tra'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
This is rather experimental. We need more control and some of this
+might become a runtime module instead. This module will be cleaned up!
+--ldx]]--
+
+local utf = unicode.utf8
+local format, match, concat, rep, utfchar = string.format, string.match, table.concat, string.rep, utf.char
+
+local ctxcatcodes = tex.ctxcatcodes
+
+fonts = fonts or { }
+fonts.tfm = fonts.tfm or { }
+fonts.ids = fonts.ids or { }
+
+nodes = nodes or { }
+nodes.tracers = nodes.tracers or { }
+nodes.tracers.characters = nodes.tracers.characters or { }
+nodes.tracers.steppers = nodes.tracers.steppers or { }
+
+local glyph = node.id('glyph')
+local hlist = node.id('hlist')
+local vlist = node.id('vlist')
+local disc = node.id('disc')
+local glue = node.id('glue')
+local kern = node.id('kern')
+local rule = node.id('rule')
+local whatsit = node.id('whatsit')
+
+local copy_node_list = node.copy_list
+local hpack_node_list = node.hpack
+local free_node_list = node.flush_list
+local first_character = node.first_character
+local node_type = node.type
+local traverse_nodes = node.traverse
+
+local texsprint = tex.sprint
+local fontdata = fonts.ids
+
+function nodes.tracers.characters.collect(head,list,tag,n)
+ n = n or 0
+ local ok, fn = false, nil
+ while head do
+ local id = head.id
+ if id == glyph then
+ local f = head.font
+ if f ~= fn then
+ ok, fn = false, f
+ end
+ local c = head.char
+ local i = fontdata[f].indices[c] or 0
+ if not ok then
+ ok = true
+ n = n + 1
+ list[n] = list[n] or { }
+ list[n][tag] = { }
+ end
+ local l = list[n][tag]
+ l[#l+1] = { c, f, i }
+ elseif id == disc then
+ -- skip
+ else
+ ok = false
+ end
+ head = head.next
+ end
+end
+
+function nodes.tracers.characters.equal(ta, tb)
+ if #ta ~= #tb then
+ return false
+ else
+ for i=1,#ta do
+ local a, b = ta[i], tb[i]
+ if a[1] ~= b[1] or a[2] ~= b[2] or a[3] ~= b[3] then
+ return false
+ end
+ end
+ end
+ return true
+end
+
+function nodes.tracers.characters.string(t)
+ local tt = { }
+ for i=1,#t do
+ tt[i] = utfchar(t[i][1])
+ end
+ return concat(tt,"")
+end
+
+function nodes.tracers.characters.unicodes(t,decimal)
+ local tt = { }
+ for i=1,#t do
+ local n = t[i][1]
+ if n == 0 then
+ tt[i] = "-"
+ elseif decimal then
+ tt[i] = n
+ else
+ tt[i] = format("U+%04X",n)
+ end
+ end
+ return concat(tt," ")
+end
+
+function nodes.tracers.characters.indices(t,decimal)
+ local tt = { }
+ for i=1,#t do
+ local n = t[i][3]
+ if n == 0 then
+ tt[i] = "-"
+ elseif decimal then
+ tt[i] = n
+ else
+ tt[i] = format("U+%04X",n)
+ end
+ end
+ return concat(tt," ")
+end
+
+function nodes.tracers.characters.start()
+ local npc = nodes.process_characters
+ local list = { }
+ function nodes.process_characters(head)
+ local n = #list
+ nodes.tracers.characters.collect(head,list,'before',n)
+ local h, d = npc(head)
+ nodes.tracers.characters.collect(head,list,'after',n)
+ if #list > n then
+ list[#list+1] = { }
+ end
+ return h, d
+ end
+ function nodes.tracers.characters.stop()
+ tracers.list['characters'] = list
+ local variables = {
+ ['title'] = 'ConTeXt Character Processing Information',
+ ['color-background-one'] = lmx.get('color-background-yellow'),
+ ['color-background-two'] = lmx.get('color-background-purple'),
+ }
+ lmx.show('context-characters.lmx',variables)
+ nodes.process_characters = npc
+ tasks.restart("processors", "characters")
+ end
+ tasks.restart("processors", "characters")
+end
+
+local stack = { }
+
+function nodes.tracers.start(tag)
+ stack[#stack+1] = tag
+ local tracer = nodes.tracers[tag]
+ if tracer and tracer.start then
+ tracer.start()
+ end
+end
+function nodes.tracers.stop()
+ local tracer = stack[#stack]
+ if tracer and tracer.stop then
+ tracer.stop()
+ end
+ stack[#stack] = nil
+end
+
+-- experimental
+
+local collection, collecting, messages = { }, false, { }
+
+function nodes.tracers.steppers.start()
+ collecting = true
+end
+
+function nodes.tracers.steppers.stop()
+ collecting = false
+end
+
+function nodes.tracers.steppers.reset()
+ for i=1,#collection do
+ local c = collection[i]
+ if c then
+ free_node_list(c)
+ end
+ end
+ collection, messages = { }, { }
+end
+
+function nodes.tracers.steppers.nofsteps()
+ return tex.write(#collection)
+end
+
+function nodes.tracers.steppers.glyphs(n,i)
+ local c = collection[i]
+ if c then
+ tex.box[n] = hpack_node_list(copy_node_list(c))
+ end
+end
+
+function nodes.tracers.steppers.features()
+-- local f = first_character(collection[1])
+-- if f then -- something fishy with first_character
+ local f = collection[1]
+ while f do
+ if f.id == glyph then
+ local tfmdata, t = fontdata[f.font], { }
+ for feature, value in table.sortedhash(tfmdata.shared.features) do
+ if feature == "number" or feature == "features" then
+ -- private
+ elseif type(value) == "boolean" then
+ if value then
+ t[#t+1] = format("%s=yes",feature)
+ else
+ -- skip
+ end
+ else
+ t[#t+1] = format("%s=%s",feature,value)
+ end
+ end
+ if #t > 0 then
+ texsprint(ctxcatcodes,concat(t,", "))
+ else
+ texsprint(ctxcatcodes,"no features")
+ end
+ return
+ end
+ f = f.next
+ end
+end
+
+function nodes.tracers.fontchar(font,char)
+ local n = nodes.glyph()
+ n.font, n.char, n.subtype = font, char, 256
+ node.write(n)
+end
+
+function nodes.tracers.steppers.codes(i,command)
+ local c = collection[i]
+ while c do
+ local id = c.id
+ if id == glyph then
+ if command then
+ texsprint(ctxcatcodes,format("%s{%s}{%s}",command,c.font,c.char))
+ else
+ texsprint(ctxcatcodes,format("[%s:U+%04X]",c.font,c.char))
+ end
+ elseif id == whatsit and (c.subtype == 6 or c.subtype == 7) then
+ texsprint(ctxcatcodes,format("[%s]",c.dir))
+ else
+ texsprint(ctxcatcodes,format("[%s]",node_type(id)))
+ end
+ c = c.next
+ end
+end
+
+function nodes.tracers.steppers.messages(i,command,split)
+ local list = messages[i] -- or { "no messages" }
+ if list then
+ for i=1,#list do
+ local l = list[i]
+ if split then
+ local a, b = match(l,"^(.-)%s*:%s*(.*)$")
+ texsprint(ctxcatcodes,format("%s{%s}{%s}",command,a or l,b or ""))
+ else
+ texsprint(ctxcatcodes,format("%s{%s}",command,l))
+ end
+ end
+ end
+end
+
+-- hooks into the node list processor (see otf)
+
+function nodes.tracers.steppers.check(head)
+ if collecting then
+ nodes.tracers.steppers.reset()
+ local n = copy_node_list(head)
+ nodes.inject_kerns(n,nil,"trace",true)
+ nodes.protect_glyphs(n) -- can be option
+ collection[1] = n
+ end
+end
+
+function nodes.tracers.steppers.register(head)
+ if collecting then
+ local nc = #collection+1
+ if messages[nc] then
+ local n = copy_node_list(head)
+ nodes.inject_kerns(n,nil,"trace",true)
+ nodes.protect_glyphs(n) -- can be option
+ collection[nc] = n
+ end
+ end
+end
+
+function nodes.tracers.steppers.message(str,...)
+ str = format(str,...)
+ if collecting then
+ local n = #collection + 1
+ local m = messages[n]
+ if not m then m = { } messages[n] = m end
+ m[#m+1] = str
+ end
+ return str -- saves an intermediate var in the caller
+end
+
+-- this will be reorganized:
+
+function nodes.show_list(head, message)
+ if message then
+ texio.write_nl(message)
+ end
+ for n in traverse_nodes(head) do
+ texio.write_nl(tostring(n))
+ end
+end
+
+function nodes.check_glyphs(head,message)
+ local t = { }
+ for g in traverse_id(glyph,head) do
+ t[#t+1] = format("U+%04X:%s",g.char,g.subtype)
+ end
+ if #t > 0 then
+ logs.report(message or "nodes","%s glyphs: %s",#t,concat(t," "))
+ end
+ return false
+end
+
+function nodes.tosequence(start,stop,compact)
+ if start then
+ local t = { }
+ while start do
+ local id = start.id
+ if id == glyph then
+ local c = start.char
+ if compact then
+ if start.components then
+ t[#t+1] = nodes.tosequence(start.components,nil,compact)
+ else
+ t[#t+1] = format("%s",utfchar(c))
+ end
+ else
+ t[#t+1] = format("U+%04X:%s",c,utfchar(c))
+ end
+ elseif id == whatsit and start.subtype == 6 or start.subtype == 7 then
+ t[#t+1] = "[" .. start.dir .. "]"
+ elseif id == rule then
+ if compact then
+ t[#t+1] = "|"
+ else
+ t[#t+1] = node_type(id)
+ end
+ else
+ if compact then
+ t[#t+1] = "[]"
+ else
+ t[#t+1] = node_type(id)
+ end
+ end
+ if start == stop then
+ break
+ else
+ start = start.next
+ end
+ end
+ if compact then
+ return concat(t)
+ else
+ return concat(t," ")
+ end
+ else
+ return "[empty]"
+ end
+end
+
+function nodes.report(t,done)
+ if done then
+ if status.output_active then
+ logs.report("nodes","output, changed, %s nodes",nodes.count(t))
+ else
+ texio.write("nodes","normal, changed, %s nodes",nodes.count(t))
+ end
+ else
+ if status.output_active then
+ logs.report("nodes","output, unchanged, %s nodes",nodes.count(t))
+ else
+ texio.write("nodes","normal, unchanged, %s nodes",nodes.count(t))
+ end
+ end
+end
+
+function nodes.pack_list(head)
+ local t = { }
+ for n in traverse(head) do
+ t[#t+1] = tostring(n)
+ end
+ return t
+end
+
+function nodes.ids_to_string(head,tail)
+ local t, last_id, last_n = { }, nil, 0
+ for n in traverse_nodes(head,tail) do -- hm, does not stop at tail
+ local id = n.id
+ if not last_id then
+ last_id, last_n = id, 1
+ elseif last_id == id then
+ last_n = last_n + 1
+ else
+ if last_n > 1 then
+ t[#t+1] = format("[%s*%s]",last_n,node_type(last_id) or "?")
+ else
+ t[#t+1] = format("[%s]",node_type(last_id) or "?")
+ end
+ last_id, last_n = id, 1
+ end
+ if n == tail then
+ break
+ end
+ end
+ if not last_id then
+ t[#t+1] = "no nodes"
+ elseif last_n > 1 then
+ t[#t+1] = format("[%s*%s]",last_n,node_type(last_id) or "?")
+ else
+ t[#t+1] = format("[%s]",node_type(last_id) or "?")
+ end
+ return concat(t," ")
+end
+
+nodes.ids_tostring = nodes.ids_to_string
+
+local function show_simple_list(h,depth,n)
+ while h do
+ texio.write_nl(rep(" ",n) .. tostring(h))
+ if not depth or n < depth then
+ local id = h.id
+ if id == hlist or id == vlist then
+ show_simple_list(h.list,depth,n+1)
+ end
+ end
+ h = h.next
+ end
+end
+
+--~ \startluacode
+--~ callback.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end)
+--~ \stopluacode
+--~ \vbox{b\footnote{n}a}
+--~ \startluacode
+--~ callback.register('buildpage_filter',nil)
+--~ \stopluacode
+
+nodes.show_simple_list = function(h,depth) show_simple_list(h,depth,0) end
+
+function nodes.list_to_utf(h,joiner)
+ local joiner = (joiner ==true and utfchar(0x200C)) or joiner -- zwnj
+ local w = { }
+ while h do
+ if h.id == glyph then -- always true
+ w[#w+1] = utfchar(h.char)
+ if joiner then
+ w[#w+1] = joiner
+ end
+ else
+ w[#w+1] = "[-]"
+ end
+ h = h.next
+ end
+ return concat(w)
+end
diff --git a/tex/context/base/node-tsk.lua b/tex/context/base/node-tsk.lua
new file mode 100644
index 000000000..206b4a266
--- /dev/null
+++ b/tex/context/base/node-tsk.lua
@@ -0,0 +1,315 @@
+if not modules then modules = { } end modules ['node-tsk'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this might move to task-*
+
+local trace_tasks = false trackers.register("tasks.creation", function(v) trace_tasks = v end)
+
+tasks = tasks or { }
+tasks.data = tasks.data or { }
+
+function tasks.new(name,list)
+ local tasklist = sequencer.reset()
+ tasks.data[name] = { list = tasklist, runner = false }
+ for l=1,#list do
+ sequencer.appendgroup(tasklist,list[l])
+ end
+end
+
+function tasks.restart(name)
+ local data = tasks.data[name]
+ if data then
+ data.runner = false
+ end
+end
+
+function tasks.enableaction(name,action)
+ local data = tasks.data[name]
+ if data then
+ sequencer.enableaction(data.list,action)
+ data.runner = false
+ end
+end
+
+function tasks.disableaction(name,action)
+ local data = tasks.data[name]
+ if data then
+ sequencer.disableaction(data.list,action)
+ data.runner = false
+ end
+end
+
+function tasks.enablegroup(name,group)
+ local data = tasks.data[name]
+ if data then
+ sequencer.enablegroup(data.list,group)
+ data.runner = false
+ end
+end
+
+function tasks.disablegroup(name,group)
+ local data = tasks.data[name]
+ if data then
+ sequencer.disablegroup(data.list,group)
+ data.runner = false
+ end
+end
+
+function tasks.appendaction(name,group,action,where,kind)
+ local data = tasks.data[name]
+ if data then
+ sequencer.appendaction(data.list,group,action,where,kind)
+ data.runner = false
+ end
+end
+
+function tasks.prependaction(name,group,action,where,kind)
+ local data = tasks.data[name]
+ if data then
+ sequencer.prependaction(data.list,group,action,where,kind)
+ data.runner = false
+ end
+end
+
+function tasks.removeaction(name,group,action)
+ local data = tasks.data[name]
+ if data then
+ sequencer.removeaction(data.list,group,action)
+ data.runner = false
+ end
+end
+
+function tasks.showactions(name,group,action,where,kind)
+ local data = tasks.data[name]
+ if data then
+ logs.report("nodes","task %s, list:\n%s",name,sequencer.nodeprocessor(data.list))
+ end
+end
+
+-- Optimizing for the number of arguments makes sense, but getting rid of
+-- the nested call (no problem but then we also need to register the
+-- callback with this mechanism so that it gets updated) does not save
+-- much time (24K calls on mk.tex).
+
+local created, total = 0, 0
+
+statistics.register("node list callback tasks", function()
+ if total > 0 then
+ return string.format("%s unique task lists, %s instances (re)created, %s calls",table.count(tasks.data),created,total)
+ else
+ return nil
+ end
+end)
+
+local compile, nodeprocessor = sequencer.compile, sequencer.nodeprocessor
+
+function tasks.actions(name,n) -- we optimize for the number or arguments (no ...)
+ local data = tasks.data[name]
+ if data then
+ if n == 0 then
+ return function(head)
+ local runner = data.runner
+ total = total + 1 -- will go away
+ if not runner then
+ created = created + 1
+ if trace_tasks then
+ logs.report("nodes","creating task runner '%s'",name)
+ end
+ runner = compile(data.list,nodeprocessor,0)
+ data.runner = runner
+ end
+ return runner(head)
+ end
+ elseif n == 1 then
+ return function(head,one)
+ total = total + 1 -- will go away
+ local runner = data.runner
+ if not runner then
+ created = created + 1
+ if trace_tasks then
+ logs.report("nodes","creating task runner '%s' with 1 extra arguments",name)
+ end
+ runner = compile(data.list,nodeprocessor,1)
+ data.runner = runner
+ end
+ return runner(head,one)
+ end
+ elseif n == 2 then
+ return function(head,one,two)
+ total = total + 1 -- will go away
+ local runner = data.runner
+ if not runner then
+ created = created + 1
+ if trace_tasks then
+ logs.report("nodes","creating task runner '%s' with 2 extra arguments",name)
+ end
+ runner = compile(data.list,nodeprocessor,2)
+ data.runner = runner
+ end
+ return runner(head,one,two)
+ end
+ elseif n == 3 then
+ return function(head,one,two,three)
+ total = total + 1 -- will go away
+ local runner = data.runner
+ if not runner then
+ created = created + 1
+ if trace_tasks then
+ logs.report("nodes","creating task runner '%s' with 3 extra arguments",name)
+ end
+ runner = compile(data.list,nodeprocessor,3)
+ data.runner = runner
+ end
+ return runner(head,one,two,three)
+ end
+ elseif n == 4 then
+ return function(head,one,two,three,four)
+ total = total + 1 -- will go away
+ local runner = data.runner
+ if not runner then
+ created = created + 1
+ if trace_tasks then
+ logs.report("nodes","creating task runner '%s' with 4 extra arguments",name)
+ end
+ runner = compile(data.list,nodeprocessor,4)
+ data.runner = runner
+ end
+ return runner(head,one,two,three,four)
+ end
+ elseif n == 5 then
+ return function(head,one,two,three,four,five)
+ total = total + 1 -- will go away
+ local runner = data.runner
+ if not runner then
+ created = created + 1
+ if trace_tasks then
+ logs.report("nodes","creating task runner '%s' with 5 extra arguments",name)
+ end
+ runner = compile(data.list,nodeprocessor,5)
+ data.runner = runner
+ end
+ return runner(head,one,two,three,four,five)
+ end
+ else
+ return function(head,...)
+ total = total + 1 -- will go away
+ local runner = data.runner
+ if not runner then
+ created = created + 1
+ if trace_tasks then
+ logs.report("nodes","creating task runner '%s' with n extra arguments",name)
+ end
+ runner = compile(data.list,nodeprocessor,"n")
+ data.runner = runner
+ end
+ return runner(head,...)
+ end
+ end
+ else
+ return nil
+ end
+end
+
+function tasks.table(name) --maybe move this to task-deb.lua
+ local tsk = tasks.data[name]
+ local lst = tsk and tsk.list
+ local HL, NC, NR, bold, type = context.HL, context.NC, context.NR, context.bold, context.type
+ if lst then
+ local list, order = lst.list, lst.order
+ if list and order then
+ context.starttabulate { "|l|l|" }
+ NC() bold("category") NC() bold("function") NC() NR()
+ for i=1,#order do
+ HL()
+ local o = order[i]
+ local l = list[o]
+ if #l == 0 then
+ NC() type(o) NC() context("unset") NC() NR()
+ else
+ local done = false
+ for k, v in table.sortedhash(l) do
+ NC() if not done then type(o) done = true end NC() type(v) NC() NR()
+ end
+ end
+ end
+ context.stoptabulate()
+ end
+ end
+end
+
+tasks.new (
+ "processors",
+ {
+ "before", -- for users
+ "normalizers",
+ "characters",
+ "words",
+ "fonts",
+ "lists",
+ "after", -- for users
+ }
+)
+
+tasks.new (
+ "finalizers",
+ {
+ "before", -- for users
+ "normalizers",
+-- "characters",
+-- "finishers",
+ "fonts",
+ "lists",
+ "after", -- for users
+ }
+)
+
+tasks.new (
+ "shipouts",
+ {
+ "before", -- for users
+ "normalizers",
+ "finishers",
+ "after", -- for users
+ }
+)
+
+tasks.new (
+ "mvlbuilders",
+ {
+ "before", -- for users
+ "normalizers",
+ "after", -- for users
+ }
+)
+
+tasks.new (
+ "vboxbuilders",
+ {
+ "before", -- for users
+ "normalizers",
+ "after", -- for users
+ }
+)
+
+--~ tasks.new (
+--~ "parbuilders",
+--~ {
+--~ "before", -- for users
+--~ "lists",
+--~ "after", -- for users
+--~ }
+--~ )
+
+--~ tasks.new (
+--~ "pagebuilders",
+--~ {
+--~ "before", -- for users
+--~ "lists",
+--~ "after", -- for users
+--~ }
+--~ )
diff --git a/tex/context/base/node-tst.lua b/tex/context/base/node-tst.lua
new file mode 100644
index 000000000..d7ea96f26
--- /dev/null
+++ b/tex/context/base/node-tst.lua
@@ -0,0 +1,119 @@
+if not modules then modules = { } end modules ['node-tst'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local glue = node.id("glue")
+local penalty = node.id("penalty")
+local kern = node.id("kern")
+local glyph = node.id("glyph")
+local whatsit = node.id("whatsit")
+local hlist = node.id("hlist")
+
+local find_node_tail = node.tail or node.slide
+
+local chardata = characters.data
+
+function nodes.the_left_margin(n) -- todo: three values
+ while n do
+ local id = n.id
+ if id == glue then
+ if n.subtype == 8 then -- 7 in c/web source
+ return n.spec.width
+ else
+ return 0
+ end
+ elseif id == whatsit then
+ n = n.next
+ elseif id == hlist then
+ return n.width
+ else
+ break
+ end
+ end
+ return 0
+end
+
+function nodes.the_right_margin(n)
+ if n then
+ n = find_node_tail(n)
+ while n do
+ local id = n.id
+ if id == glue then
+ if n.subtype == 9 then -- 8 in the c/web source
+ return n.spec.width
+ else
+ return 0
+ end
+ elseif id == whatsit then
+ n = n.prev
+ else
+ break
+ end
+ end
+ end
+ return false
+end
+
+function nodes.somespace(n,all)
+ if n then
+ local id = n.id
+ if id == glue then
+ return (all or (n.spec.width ~= 0)) and glue
+ elseif id == kern then
+ return (all or (n.kern ~= 0)) and kern
+ elseif id == glyph then
+ local category = chardata[n.char].category
+ -- maybe more category checks are needed
+ return (category == "zs") and glyph
+ end
+ end
+ return false
+end
+
+function nodes.somepenalty(n,value)
+ if n then
+ local id = n.id
+ if id == penalty then
+ if value then
+ return n.penalty == value
+ else
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function nodes.is_display_math(head)
+ local n = head.prev
+ while n do
+ local id = n.id
+ if id == penalty then
+ elseif id == glue then
+ if n.subtype == 6 then -- above_display_short_skip
+ return true
+ end
+ else
+ break
+ end
+ n = n.prev
+ end
+ n = head.next
+ while n do
+ local id = n.id
+ if id == penalty then
+ elseif id == glue then
+ if n.subtype == 7 then -- below_display_short_skip
+ return true
+ end
+ else
+ break
+ end
+ n = n.next
+ end
+ return false
+end
diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua
new file mode 100644
index 000000000..5ab6b6975
--- /dev/null
+++ b/tex/context/base/node-typ.lua
@@ -0,0 +1,53 @@
+if not modules then modules = { } end modules ['node-typ'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this will be replaced by blob-ini cum suis so typesetting will go away
+
+local utfvalues = string.utfvalues
+
+local newglyph = nodes.glyph
+local newglue = nodes.glue
+
+local hpack, vpack = node.hpack, node.vpack
+
+typesetting = typesetting or { }
+
+local function tonodes(str,fontid,spacing) -- don't use this
+ local head, prev = nil, nil
+ for s in utfvalues(str) do
+ local next
+ if spacing and s == 32 then
+ next = newglue(spacing or 64*1024*10)
+ else
+ next = newglyph(fontid or 1,s)
+ end
+ if not head then
+ head = next
+ else
+ prev.next = next
+ next.prev = prev
+ end
+ prev = next
+ end
+ return head
+end
+
+typesetting.tonodes = tonodes
+
+function typesetting.hpack(str,fontid,spacing)
+ return hpack(tonodes(str,fontid,spacing))
+end
+
+function typesetting.vpack(str,fontid,spacing)
+ -- vpack is just a hack, and a proper implentation is on the agenda
+ -- as it needs more info etc than currently available
+ return vpack(tonodes(str,fontid,spacing))
+end
+
+--~ node.write(typesetting.hpack("Hello World!"))
+--~ node.write(typesetting.hpack("Hello World!",1,100*1024*10))
diff --git a/tex/context/base/norm-alo.tex b/tex/context/base/norm-alo.tex
new file mode 100644
index 000000000..d47f49037
--- /dev/null
+++ b/tex/context/base/norm-alo.tex
@@ -0,0 +1,36 @@
+%D \module
+%D [ file=norm-alo,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Norm Macros,
+%D subtitle=\ALEPH\ and \OMEGA,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This file will become obsolete!
+
+% omega primitives
+
+\let\textdir = \textdir
+\let\pagedir = \pagedir
+\let\mathdir = \mathdir
+\let\pardir = \pardir
+\let\bodydir = \bodydir
+\let\leftghost = \leftghost
+\let\rightghost = \rightghost
+\let\localleftbox = \localleftbox
+\let\localrightbox = \localrightbox
+\let\localinterlinepenalty = \localinterlinepenalty
+\let\localbrokenpenalty = \localbrokenpenalty
+
+% aleph primitives
+
+\let\boxdir = \boxdir
+\let\pagebottomoffset = \pagebottomoffset
+\let\pagerightoffset = \pagerightoffset
+
+\endinput
diff --git a/tex/context/base/norm-ctx.tex b/tex/context/base/norm-ctx.tex
new file mode 100644
index 000000000..707705d89
--- /dev/null
+++ b/tex/context/base/norm-ctx.tex
@@ -0,0 +1,16 @@
+%D \module
+%D [ file=norm-ctx,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Norm Macros,
+%D subtitle=\ALEPH\ and \OMEGA,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 few more might end up here (like the weird ones in syst-ini).
+
+\let\normalreqno = \normaleqno
diff --git a/tex/context/base/norm-etx.tex b/tex/context/base/norm-etx.tex
new file mode 100644
index 000000000..3edd8e7ef
--- /dev/null
+++ b/tex/context/base/norm-etx.tex
@@ -0,0 +1,79 @@
+%D \module
+%D [ file=norm-etx,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Norm Macros,
+%D subtitle=\ETEX,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% etex primitives
+
+\let \normalbotmarks = \botmarks
+\let \normalclubpenalties = \clubpenalties
+\let \normalcurrentgrouplevel = \currentgrouplevel
+\let \normalcurrentgrouptype = \currentgrouptype
+\let \normalcurrentifbranch = \currentifbranch
+\let \normalcurrentiflevel = \currentiflevel
+\let \normalcurrentiftype = \currentiftype
+\let \normaldetokenize = \detokenize
+\let \normaldimexpr = \dimexpr
+\let \normaldisplaywidowpenalties = \displaywidowpenalties
+\let \normaleTeXVersion = \eTeXVersion
+\let \normaleTeXminorversion = \eTeXminorversion
+\let \normaleTeXrevision = \eTeXrevision
+\let \normaleTeXversion = \eTeXversion
+\let \normaleveryeof = \everyeof
+\let \normalfirstmarks = \firstmarks
+\let \normalfontchardp = \fontchardp
+\let \normalfontcharht = \fontcharht
+\let \normalfontcharic = \fontcharic
+\let \normalfontcharwd = \fontcharwd
+\let \normalglueexpr = \glueexpr
+\let \normalglueshrink = \glueshrink
+\let \normalglueshrinkorder = \glueshrinkorder
+\let \normalgluestretch = \gluestretch
+\let \normalgluestretchorder = \gluestretchorder
+\let \normalgluetomu = \gluetomu
+\let \normalifcsname = \ifcsname
+\let \normalifdefined = \ifdefined
+\let \normaliffontchar = \iffontchar
+\let \normalinteractionmode = \interactionmode
+\let \normalinterlinepenalties = \interlinepenalties
+\let \normallastlinefit = \lastlinefit
+\let \normallastnodetype = \lastnodetype
+\let \normalmarks = \marks
+\let \normalmuexpr = \muexpr
+\let \normalmutoglue = \mutoglue
+\let \normalnumexpr = \numexpr
+\let \normalpagediscards = \pagediscards
+\let \normalparshapedimen = \parshapedimen
+\let \normalparshapeindent = \parshapeindent
+\let \normalparshapelength = \parshapelength
+\let \normalpredisplaydirection = \predisplaydirection
+\let \normalprotected = \protected
+\let \normalreadline = \readline
+\let \normalsavinghyphcodes = \savinghyphcodes
+\let \normalsavingvdiscards = \savingvdiscards
+\let \normalscantokens = \scantokens
+\let \normalshowgroups = \showgroups
+\let \normalshowifs = \showifs
+\let \normalshowtokens = \showtokens
+\let \normalsplitbotmarks = \splitbotmarks
+\let \normalsplitdiscards = \splitdiscards
+\let \normalsplitfirstmarks = \splitfirstmarks
+\let \normaltopmarks = \topmarks
+\let \normaltracingassigns = \tracingassigns
+\let \normaltracinggroups = \tracinggroups
+\let \normaltracingifs = \tracingifs
+\let \normaltracingnesting = \tracingnesting
+\let \normaltracingscantokens = \tracingscantokens
+\let \normalunexpanded = \unexpanded
+\let \normalunless = \unless
+\let \normalwidowpenalties = \widowpenalties
+
+\endinput
diff --git a/tex/context/base/norm-ltx.tex b/tex/context/base/norm-ltx.tex
new file mode 100644
index 000000000..a779735dd
--- /dev/null
+++ b/tex/context/base/norm-ltx.tex
@@ -0,0 +1,177 @@
+%D \module
+%D [ file=norm-ltx,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Norm Macros,
+%D subtitle=\LUATEX,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This file will become obsolete!
+
+% luatex primitives (incomplete)
+
+\let \normalUdelcode = \Udelcode
+\let \normalUdelcodenum = \Udelcodenum
+\let \normalUdelimiter = \Udelimiter
+\let \normalUmathaccent = \Umathaccent
+\let \normalUmathaccents = \Umathaccents
+\let \normalUmathaxis = \Umathaxis
+\let \normalUmathbinbinspacing = \Umathbinbinspacing
+\let \normalUmathbinclosespacing = \Umathbinclosespacing
+\let \normalUmathbininnerspacing = \Umathbininnerspacing
+\let \normalUmathbinopenspacing = \Umathbinopenspacing
+\let \normalUmathbinopspacing = \Umathbinopspacing
+\let \normalUmathbinordspacing = \Umathbinordspacing
+\let \normalUmathbinpunctspacing = \Umathbinpunctspacing
+\let \normalUmathbinrelspacing = \Umathbinrelspacing
+\let \normalUmathbotaccent = \Umathbotaccent
+\let \normalUmathchar = \Umathchar
+\let \normalUmathchardef = \Umathchardef
+\let \normalUmathcharnum = \Umathcharnum
+\let \normalUmathclosebinspacing = \Umathclosebinspacing
+\let \normalUmathcloseclosespacing = \Umathcloseclosespacing
+\let \normalUmathcloseinnerspacing = \Umathcloseinnerspacing
+\let \normalUmathcloseopenspacing = \Umathcloseopenspacing
+\let \normalUmathcloseopspacing = \Umathcloseopspacing
+\let \normalUmathcloseordspacing = \Umathcloseordspacing
+\let \normalUmathclosepunctspacing = \Umathclosepunctspacing
+\let \normalUmathcloserelspacing = \Umathcloserelspacing
+\let \normalUmathcode = \Umathcode
+\let \normalUmathcodenum = \Umathcodenum
+\let \normalUmathconnectoroverlapmin = \Umathconnectoroverlapmin
+\let \normalUmathfractiondelsize = \Umathfractiondelsize
+\let \normalUmathfractiondenomdown = \Umathfractiondenomdown
+\let \normalUmathfractiondenomvgap = \Umathfractiondenomvgap
+\let \normalUmathfractionnumup = \Umathfractionnumup
+\let \normalUmathfractionnumvgap = \Umathfractionnumvgap
+\let \normalUmathfractionrule = \Umathfractionrule
+\let \normalUmathinnerbinspacing = \Umathinnerbinspacing
+\let \normalUmathinnerclosespacing = \Umathinnerclosespacing
+\let \normalUmathinnerinnerspacing = \Umathinnerinnerspacing
+\let \normalUmathinneropenspacing = \Umathinneropenspacing
+\let \normalUmathinneropspacing = \Umathinneropspacing
+\let \normalUmathinnerordspacing = \Umathinnerordspacing
+\let \normalUmathinnerpunctspacing = \Umathinnerpunctspacing
+\let \normalUmathinnerrelspacing = \Umathinnerrelspacing
+\let \normalUmathlimitabovebgap = \Umathlimitabovebgap
+\let \normalUmathlimitabovekern = \Umathlimitabovekern
+\let \normalUmathlimitabovevgap = \Umathlimitabovevgap
+\let \normalUmathlimitdownbgap = \Umathlimitdownbgap
+\let \normalUmathlimitdownkern = \Umathlimitdownkern
+\let \normalUmathlimitdownvgap = \Umathlimitdownvgap
+\let \normalUmathopbinspacing = \Umathopbinspacing
+\let \normalUmathopclosespacing = \Umathopclosespacing
+\let \normalUmathopenbinspacing = \Umathopenbinspacing
+\let \normalUmathopenclosespacing = \Umathopenclosespacing
+\let \normalUmathopeninnerspacing = \Umathopeninnerspacing
+\let \normalUmathopenopenspacing = \Umathopenopenspacing
+\let \normalUmathopenopspacing = \Umathopenopspacing
+\let \normalUmathopenordspacing = \Umathopenordspacing
+\let \normalUmathopenpunctspacing = \Umathopenpunctspacing
+\let \normalUmathopenrelspacing = \Umathopenrelspacing
+\let \normalUmathoperatorsize = \Umathoperatorsize
+\let \normalUmathopinnerspacing = \Umathopinnerspacing
+\let \normalUmathopopenspacing = \Umathopopenspacing
+\let \normalUmathopopspacing = \Umathopopspacing
+\let \normalUmathopordspacing = \Umathopordspacing
+\let \normalUmathoppunctspacing = \Umathoppunctspacing
+\let \normalUmathoprelspacing = \Umathoprelspacing
+\let \normalUmathordbinspacing = \Umathordbinspacing
+\let \normalUmathordclosespacing = \Umathordclosespacing
+\let \normalUmathordinnerspacing = \Umathordinnerspacing
+\let \normalUmathordopenspacing = \Umathordopenspacing
+\let \normalUmathordopspacing = \Umathordopspacing
+\let \normalUmathordordspacing = \Umathordordspacing
+\let \normalUmathordpunctspacing = \Umathordpunctspacing
+\let \normalUmathordrelspacing = \Umathordrelspacing
+\let \normalUmathoverbarkern = \Umathoverbarkern
+\let \normalUmathoverbarrule = \Umathoverbarrule
+\let \normalUmathoverbarvgap = \Umathoverbarvgap
+\let \normalUmathoverdelimiterbgap = \Umathoverdelimiterbgap
+\let \normalUmathoverdelimitervgap = \Umathoverdelimitervgap
+\let \normalUmathpunctbinspacing = \Umathpunctbinspacing
+\let \normalUmathpunctclosespacing = \Umathpunctclosespacing
+\let \normalUmathpunctinnerspacing = \Umathpunctinnerspacing
+\let \normalUmathpunctopenspacing = \Umathpunctopenspacing
+\let \normalUmathpunctopspacing = \Umathpunctopspacing
+\let \normalUmathpunctordspacing = \Umathpunctordspacing
+\let \normalUmathpunctpunctspacing = \Umathpunctpunctspacing
+\let \normalUmathpunctrelspacing = \Umathpunctrelspacing
+\let \normalUmathquad = \Umathquad
+\let \normalUmathradicaldegreeafter = \Umathradicaldegreeafter
+\let \normalUmathradicaldegreebefore = \Umathradicaldegreebefore
+\let \normalUmathradicaldegreeraise = \Umathradicaldegreeraise
+\let \normalUmathradicalkern = \Umathradicalkern
+\let \normalUmathradicalrule = \Umathradicalrule
+\let \normalUmathradicalvgap = \Umathradicalvgap
+\let \normalUmathrelbinspacing = \Umathrelbinspacing
+\let \normalUmathrelclosespacing = \Umathrelclosespacing
+\let \normalUmathrelinnerspacing = \Umathrelinnerspacing
+\let \normalUmathrelopenspacing = \Umathrelopenspacing
+\let \normalUmathrelopspacing = \Umathrelopspacing
+\let \normalUmathrelordspacing = \Umathrelordspacing
+\let \normalUmathrelpunctspacing = \Umathrelpunctspacing
+\let \normalUmathrelrelspacing = \Umathrelrelspacing
+\let \normalUmathspaceafterscript = \Umathspaceafterscript
+\let \normalUmathstackdenomdown = \Umathstackdenomdown
+\let \normalUmathstacknumup = \Umathstacknumup
+\let \normalUmathstackvgap = \Umathstackvgap
+\let \normalUmathsubshiftdown = \Umathsubshiftdown
+\let \normalUmathsubshiftdrop = \Umathsubshiftdrop
+\let \normalUmathsubsupshiftdown = \Umathsubsupshiftdown
+\let \normalUmathsubsupvgap = \Umathsubsupvgap
+\let \normalUmathsubtopmax = \Umathsubtopmax
+\let \normalUmathsupbottommin = \Umathsupbottommin
+\let \normalUmathsupshiftdrop = \Umathsupshiftdrop
+\let \normalUmathsupshiftup = \Umathsupshiftup
+\let \normalUmathsupsubbottommax = \Umathsupsubbottommax
+\let \normalUmathunderbarkern = \Umathunderbarkern
+\let \normalUmathunderbarrule = \Umathunderbarrule
+\let \normalUmathunderbarvgap = \Umathunderbarvgap
+\let \normalUmathunderdelimiterbgap = \Umathunderdelimiterbgap
+\let \normalUmathunderdelimitervgap = \Umathunderdelimitervgap
+\let \normalUoverdelimiter = \Uoverdelimiter
+\let \normalUradical = \Uradical
+\let \normalUroot = \Uroot
+\let \normalUunderdelimiter = \Uunderdelimiter
+\let \normalattribute = \attribute
+\let \normalattributedef = \attributedef
+\let \normalcatcodetable = \catcodetable
+\let \normalclearmarks = \clearmarks
+\let \normalcrampeddisplaystyle = \crampeddisplaystyle
+\let \normalcrampedscriptscriptstyle = \crampedscriptscriptstyle
+\let \normalcrampedscriptstyle = \crampedscriptstyle
+\let \normalcrampedtextstyle = \crampedtextstyle
+\let \normalformatname = \formatname
+\let \normalifabsdim = \ifabsdim
+\let \normalifabsnum = \ifabsnum
+\let \normalifprimitive = \ifprimitive
+\let \normalinitcatcodetable = \initcatcodetable
+\let \normallatelua = \latelua
+\let \normalluaescapestring = \luaescapestring
+\let \normalluastartup = \luastartup
+\let \normalluatexdatestamp = \luatexdatestamp
+\let \normalluatexrevision = \luatexrevision
+\let \normalluatexversion = \luatexversion
+\let \normalnokerns = \nokerns
+\let \normalnoligs = \noligs
+\let \normalpageleftoffset = \pageleftoffset
+\let \normalpagetopoffset = \pagetopoffset
+\let \normalpostexhyphenchar = \postexhyphenchar
+\let \normalposthyphenchar = \posthyphenchar
+\let \normalpreexhyphenchar = \preexhyphenchar
+\let \normalprehyphenchar = \prehyphenchar
+\let \normalprimitive = \primitive
+\let \normalsavecatcodetable = \savecatcodetable
+\let \normalscantextokens = \scantextokens
+\let \normalsuppressfontnotfounderror = \suppressfontnotfounderror
+\let \normalsuppressifcsnameerror = \suppressifcsnameerror
+\let \normalsuppresslongerror = \suppresslongerror
+\let \normalsynctex = \synctex
+
+\endinput
diff --git a/tex/context/base/norm-ptx.tex b/tex/context/base/norm-ptx.tex
new file mode 100644
index 000000000..8f911d874
--- /dev/null
+++ b/tex/context/base/norm-ptx.tex
@@ -0,0 +1,130 @@
+%D \module
+%D [ file=norm-ptx,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Norm Macros,
+%D subtitle=\PDFTEX,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\let \normalefcode = \efcode
+\let \normalexpanded = \expanded
+\let \normalifincsname = \ifincsname
+\let \normalifpdfabsdim = \ifpdfabsdim
+\let \normalifpdfabsnum = \ifpdfabsnum
+\let \normalifpdfprimitive = \ifpdfprimitive
+\let \normalleftmarginkern = \leftmarginkern
+\let \normalletterspacefont = \letterspacefont
+\let \normallpcode = \lpcode
+\let \normalpdfadjustspacing = \pdfadjustspacing
+\let \normalpdfannot = \pdfannot
+\let \normalpdfcatalog = \pdfcatalog
+\let \normalpdfcolorstack = \pdfcolorstack
+\let \normalpdfcolorstackinit = \pdfcolorstackinit
+\let \normalpdfcompresslevel = \pdfcompresslevel
+\let \normalpdfcopyfont = \pdfcopyfont
+\let \normalpdfcreationdate = \pdfcreationdate
+\let \normalpdfdecimaldigits = \pdfdecimaldigits
+\let \normalpdfdest = \pdfdest
+\let \normalpdfdestmargin = \pdfdestmargin
+\let \normalpdfdraftmode = \pdfdraftmode
+\let \normalpdfeachlinedepth = \pdfeachlinedepth
+\let \normalpdfeachlineheight = \pdfeachlineheight
+\let \normalpdfendlink = \pdfendlink
+\let \normalpdfendthread = \pdfendthread
+\let \normalpdffirstlineheight = \pdffirstlineheight
+\let \normalpdffontattr = \pdffontattr
+\let \normalpdffontexpand = \pdffontexpand
+\let \normalpdffontname = \pdffontname
+\let \normalpdffontobjnum = \pdffontobjnum
+\let \normalpdffontsize = \pdffontsize
+\let \normalpdfforcepagebox = \pdfforcepagebox % obsolete
+\let \normalpdfgamma = \pdfgamma
+\let \normalpdfgentounicode = \pdfgentounicode
+\let \normalpdfglyphtounicode = \pdfglyphtounicode
+\let \normalpdfhorigin = \pdfhorigin
+\let \normalpdfignoreddimen = \pdfignoreddimen
+\let \normalpdfimageapplygamma = \pdfimageapplygamma
+\let \normalpdfimagegamma = \pdfimagegamma
+\let \normalpdfimagehicolor = \pdfimagehicolor
+\let \normalpdfimageresolution = \pdfimageresolution
+\let \normalpdfincludechars = \pdfincludechars
+\let \normalpdfinclusioncopyfonts = \pdfinclusioncopyfonts
+\let \normalpdfinclusionerrorlevel = \pdfinclusionerrorlevel
+\let \normalpdfinfo = \pdfinfo
+\let \normalpdfinsertht = \pdfinsertht
+\let \normalpdflastannot = \pdflastannot
+\let \normalpdflastlinedepth = \pdflastlinedepth
+\let \normalpdflastlink = \pdflastlink
+\let \normalpdflastobj = \pdflastobj
+\let \normalpdflastxform = \pdflastxform
+\let \normalpdflastximage = \pdflastximage
+\let \normalpdflastximagecolordepth = \pdflastximagecolordepth
+\let \normalpdflastximagepages = \pdflastximagepages
+\let \normalpdflastxpos = \pdflastxpos
+\let \normalpdflastypos = \pdflastypos
+\let \normalpdflinkmargin = \pdflinkmargin
+\let \normalpdfliteral = \pdfliteral
+\let \normalpdfmapfile = \pdfmapfile
+\let \normalpdfmapline = \pdfmapline
+\let \normalpdfminorversion = \pdfminorversion
+\let \normalpdfmovechars = \pdfmovechars % obsolete
+\let \normalpdfnames = \pdfnames
+\let \normalpdfnoligatures = \pdfnoligatures
+\let \normalpdfnormaldeviate = \pdfnormaldeviate
+\let \normalpdfobj = \pdfobj
+\let \normalpdfobjcompresslevel = \pdfobjcompresslevel
+\let \normalpdfoptionalwaysusepdfpagebox = \pdfoptionalwaysusepdfpagebox % obsolete
+\let \normalpdfoptionpdfinclusionerrorlevel = \pdfoptionpdfinclusionerrorlevel % obsolete
+\let \normalpdfoptionpdfminorversion = \pdfoptionpdfminorversion
+\let \normalpdfoutline = \pdfoutline
+\let \normalpdfoutput = \pdfoutput
+\let \normalpdfpageattr = \pdfpageattr
+\let \normalpdfpagebox = \pdfpagebox
+\let \normalpdfpageheight = \pdfpageheight
+\let \normalpdfpageref = \pdfpageref
+\let \normalpdfpageresources = \pdfpageresources
+\let \normalpdfpagesattr = \pdfpagesattr
+\let \normalpdfpagewidth = \pdfpagewidth
+\let \normalpdfpkmode = \pdfpkmode
+\let \normalpdfpkresolution = \pdfpkresolution
+\let \normalpdfprimitive = \pdfprimitive
+\let \normalpdfprotrudechars = \pdfprotrudechars
+\let \normalpdfpxdimen = \pdfpxdimen
+\let \normalpdfrandomseed = \pdfrandomseed
+\let \normalpdfrefobj = \pdfrefobj
+\let \normalpdfrefxform = \pdfrefxform
+\let \normalpdfrefximage = \pdfrefximage
+\let \normalpdfreplacefont = \pdfreplacefont
+\let \normalpdfrestore = \pdfrestore
+\let \normalpdfretval = \pdfretval
+\let \normalpdfsave = \pdfsave
+\let \normalpdfsavepos = \pdfsavepos
+\let \normalpdfsetmatrix = \pdfsetmatrix
+\let \normalpdfsetrandomseed = \pdfsetrandomseed
+\let \normalpdfstartlink = \pdfstartlink
+\let \normalpdfstartthread = \pdfstartthread
+\let \normalpdftexbanner = \pdftexbanner
+\let \normalpdftexrevision = \pdftexrevision
+\let \normalpdftexversion = \pdftexversion
+\let \normalpdfthread = \pdfthread
+\let \normalpdfthreadmargin = \pdfthreadmargin
+\let \normalpdftracingfonts = \pdftracingfonts
+\let \normalpdftrailer = \pdftrailer
+\let \normalpdfuniformdeviate = \pdfuniformdeviate
+\let \normalpdfuniqueresname = \pdfuniqueresname
+\let \normalpdfvorigin = \pdfvorigin
+\let \normalpdfxform = \pdfxform
+\let \normalpdfxformname = \pdfxformname
+\let \normalpdfximage = \pdfximage
+\let \normalpdfximagebbox = \pdfximagebbox
+\let \normalquitvmode = \quitvmode
+\let \normalrightmarginkern = \rightmarginkern
+\let \normalrpcode = \rpcode
+\let \normaltagcode = \tagcode
+
+\endinput
diff --git a/tex/context/base/norm-tex.tex b/tex/context/base/norm-tex.tex
new file mode 100644
index 000000000..61f9740ef
--- /dev/null
+++ b/tex/context/base/norm-tex.tex
@@ -0,0 +1,351 @@
+%D \module
+%D [ file=norm-etx,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Norm Macros,
+%D subtitle=\TEX,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%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 Since \LUATEX\ can generate these lists internally it started
+%D to make sense to cleanup this \type {\normalstuff} for \MKII\ as
+%D well. The tables are generated with a \LUA\ script.
+
+% tex primitives
+
+% Beware, we already redefined \dump, \outer and \everyjob !
+
+% \normal = \
+% \normal- = \-
+% \normal/ = \/
+\let \normalabove = \above
+\let \normalabovedisplayshortskip = \abovedisplayshortskip
+\let \normalabovedisplayskip = \abovedisplayskip
+\let \normalabovewithdelims = \abovewithdelims
+\let \normalaccent = \accent
+\let \normaladjdemerits = \adjdemerits
+\let \normaladvance = \advance
+\let \normalafterassignment = \afterassignment
+\let \normalaftergroup = \aftergroup
+\let \normalatop = \atop
+\let \normalatopwithdelims = \atopwithdelims
+\let \normalbadness = \badness
+\let \normalbaselineskip = \baselineskip
+\let \normalbatchmode = \batchmode
+\let \normalbegingroup = \begingroup
+\let \normalbelowdisplayshortskip = \belowdisplayshortskip
+\let \normalbelowdisplayskip = \belowdisplayskip
+\let \normalbinoppenalty = \binoppenalty
+\let \normalbotmark = \botmark
+\let \normalbox = \box
+\let \normalboxmaxdepth = \boxmaxdepth
+\let \normalbrokenpenalty = \brokenpenalty
+\let \normalcatcode = \catcode
+\let \normalchar = \char
+\let \normalchardef = \chardef
+\let \normalcleaders = \cleaders
+\let \normalclosein = \closein
+\let \normalcloseout = \closeout
+\let \normalclubpenalty = \clubpenalty
+\let \normalcopy = \copy
+\let \normalcount = \count
+\let \normalcountdef = \countdef
+\let \normalcr = \cr
+\let \normalcrcr = \crcr
+\let \normalcsname = \csname
+\let \normalday = \day
+\let \normaldeadcycles = \deadcycles
+\let \normaldef = \def
+\let \normaldefaulthyphenchar = \defaulthyphenchar
+\let \normaldefaultskewchar = \defaultskewchar
+\let \normaldelcode = \delcode
+\let \normaldelimiter = \delimiter
+\let \normaldelimiterfactor = \delimiterfactor
+\let \normaldelimitershortfall = \delimitershortfall
+\let \normaldimen = \dimen
+\let \normaldimendef = \dimendef
+\let \normaldirectlua = \directlua
+\let \normaldiscretionary = \discretionary
+\let \normaldisplayindent = \displayindent
+\let \normaldisplaylimits = \displaylimits
+\let \normaldisplaystyle = \displaystyle
+\let \normaldisplaywidowpenalty = \displaywidowpenalty
+\let \normaldisplaywidth = \displaywidth
+\let \normaldivide = \divide
+\let \normaldoublehyphendemerits = \doublehyphendemerits
+\let \normaldp = \dp
+% \normaldump = \dump
+\let \normaledef = \edef
+\let \normalelse = \else
+\let \normalemergencystretch = \emergencystretch
+\let \normalend = \end
+\let \normalendcsname = \endcsname
+\let \normalendgroup = \endgroup
+\let \normalendinput = \endinput
+\let \normalendlinechar = \endlinechar
+\let \normaleqno = \eqno
+\let \normalerrhelp = \errhelp
+\let \normalerrmessage = \errmessage
+\let \normalerrorcontextlines = \errorcontextlines
+\let \normalerrorstopmode = \errorstopmode
+\let \normalescapechar = \escapechar
+\let \normaleverycr = \everycr
+\let \normaleverydisplay = \everydisplay
+\let \normaleveryhbox = \everyhbox
+% \normaleveryjob = \everyjob
+\let \normaleverymath = \everymath
+\let \normaleverypar = \everypar
+\let \normaleveryvbox = \everyvbox
+\let \normalexhyphenchar = \exhyphenchar
+\let \normalexhyphenpenalty = \exhyphenpenalty
+\let \normalexpandafter = \expandafter
+\let \normalfam = \fam
+\let \normalfi = \fi
+\let \normalfinalhyphendemerits = \finalhyphendemerits
+\let \normalfirstmark = \firstmark
+\let \normalfloatingpenalty = \floatingpenalty
+\let \normalfont = \font
+\let \normalfontdimen = \fontdimen
+\let \normalfontname = \fontname
+\let \normalfuturelet = \futurelet
+\let \normalgdef = \gdef
+\let \normalglobal = \global
+\let \normalglobaldefs = \globaldefs
+\let \normalhalign = \halign
+\let \normalhangafter = \hangafter
+\let \normalhangindent = \hangindent
+\let \normalhbadness = \hbadness
+\let \normalhbox = \hbox
+\let \normalhfil = \hfil
+\let \normalhfill = \hfill
+\let \normalhfilneg = \hfilneg
+\let \normalhfuzz = \hfuzz
+\let \normalhoffset = \hoffset
+\let \normalholdinginserts = \holdinginserts
+\let \normalhrule = \hrule
+\let \normalhsize = \hsize
+\let \normalhskip = \hskip
+\let \normalhss = \hss
+\let \normalht = \ht
+\let \normalhyphenation = \hyphenation
+\let \normalhyphenchar = \hyphenchar
+\let \normalhyphenpenalty = \hyphenpenalty
+\let \normalif = \if
+\let \normalifcase = \ifcase
+\let \normalifcat = \ifcat
+\let \normalifdim = \ifdim
+\let \normalifeof = \ifeof
+\let \normaliffalse = \iffalse
+\let \normalifhbox = \ifhbox
+\let \normalifhmode = \ifhmode
+\let \normalifinner = \ifinner
+\let \normalifmmode = \ifmmode
+\let \normalifnum = \ifnum
+\let \normalifodd = \ifodd
+\let \normaliftrue = \iftrue
+\let \normalifvbox = \ifvbox
+\let \normalifvmode = \ifvmode
+\let \normalifvoid = \ifvoid
+\let \normalifx = \ifx
+\let \normalignorespaces = \ignorespaces
+\let \normalimmediate = \immediate
+\let \normalindent = \indent
+% \normalinput = \input
+\let \normalinputlineno = \inputlineno
+\let \normalinsert = \insert
+\let \normalinsertpenalties = \insertpenalties
+\let \normalinterlinepenalty = \interlinepenalty
+\let \normaljobname = \jobname
+\let \normalkern = \kern
+\let \normallanguage = \language
+\let \normallastbox = \lastbox
+\let \normallastkern = \lastkern
+\let \normallastpenalty = \lastpenalty
+\let \normallastskip = \lastskip
+\let \normallccode = \lccode
+\let \normalleaders = \leaders
+\let \normalleft = \left
+\let \normallefthyphenmin = \lefthyphenmin
+\let \normalleftskip = \leftskip
+\let \normalleqno = \leqno
+\let \normallet = \let
+\let \normallimits = \limits
+\let \normallinepenalty = \linepenalty
+\let \normallineskip = \lineskip
+\let \normallineskiplimit = \lineskiplimit
+\let \normallong = \long
+\let \normallooseness = \looseness
+\let \normallower = \lower
+\let \normallowercase = \lowercase
+\let \normalmag = \mag
+\let \normalmark = \mark
+\let \normalmathaccent = \mathaccent
+\let \normalmathbin = \mathbin
+\let \normalmathchar = \mathchar
+\let \normalmathchardef = \mathchardef
+\let \normalmathchoice = \mathchoice
+\let \normalmathclose = \mathclose
+\let \normalmathcode = \mathcode
+\let \normalmathinner = \mathinner
+\let \normalmathop = \mathop
+\let \normalmathopen = \mathopen
+\let \normalmathord = \mathord
+\let \normalmathpunct = \mathpunct
+\let \normalmathrel = \mathrel
+\let \normalmathsurround = \mathsurround
+\let \normalmaxdeadcycles = \maxdeadcycles
+\let \normalmaxdepth = \maxdepth
+\let \normalmeaning = \meaning
+\let \normalmedmuskip = \medmuskip
+\let \normalmessage = \message
+\let \normalmiddle = \middle
+\let \normalmkern = \mkern
+\let \normalmonth = \month
+\let \normalmoveleft = \moveleft
+\let \normalmoveright = \moveright
+\let \normalmskip = \mskip
+\let \normalmultiply = \multiply
+\let \normalmuskip = \muskip
+\let \normalmuskipdef = \muskipdef
+\let \normalnewlinechar = \newlinechar
+\let \normalnoalign = \noalign
+\let \normalnoboundary = \noboundary
+\let \normalnoexpand = \noexpand
+\let \normalnoindent = \noindent
+\let \normalnolimits = \nolimits
+\let \normalnonscript = \nonscript
+\let \normalnonstopmode = \nonstopmode
+\let \normalnulldelimiterspace = \nulldelimiterspace
+\let \normalnullfont = \nullfont
+\let \normalnumber = \number
+\let \normalomit = \omit
+\let \normalopenin = \openin
+\let \normalopenout = \openout
+\let \normalor = \or
+% \normalouter = \outer
+\let \normaloutput = \output
+\let \normaloutputpenalty = \outputpenalty
+\let \normalover = \over
+\let \normaloverfullrule = \overfullrule
+\let \normaloverline = \overline
+\let \normaloverwithdelims = \overwithdelims
+\let \normalpagedepth = \pagedepth
+\let \normalpagefilllstretch = \pagefilllstretch
+\let \normalpagefillstretch = \pagefillstretch
+\let \normalpagefilstretch = \pagefilstretch
+\let \normalpagegoal = \pagegoal
+\let \normalpageshrink = \pageshrink
+\let \normalpagestretch = \pagestretch
+\let \normalpagetotal = \pagetotal
+\let \normalpar = \par
+\let \normalparfillskip = \parfillskip
+\let \normalparindent = \parindent
+\let \normalparshape = \parshape
+\let \normalparskip = \parskip
+\let \normalpatterns = \patterns
+\let \normalpausing = \pausing
+\let \normalpenalty = \penalty
+\let \normalpostdisplaypenalty = \postdisplaypenalty
+\let \normalpredisplaypenalty = \predisplaypenalty
+\let \normalpredisplaysize = \predisplaysize
+\let \normalpretolerance = \pretolerance
+\let \normalprevdepth = \prevdepth
+\let \normalprevgraf = \prevgraf
+\let \normalradical = \radical
+\let \normalraise = \raise
+\let \normalread = \read
+\let \normalrelax = \relax
+\let \normalrelpenalty = \relpenalty
+\let \normalright = \right
+\let \normalrighthyphenmin = \righthyphenmin
+\let \normalrightskip = \rightskip
+\let \normalromannumeral = \romannumeral
+\let \normalscriptfont = \scriptfont
+\let \normalscriptscriptfont = \scriptscriptfont
+\let \normalscriptscriptstyle = \scriptscriptstyle
+\let \normalscriptspace = \scriptspace
+\let \normalscriptstyle = \scriptstyle
+\let \normalscrollmode = \scrollmode
+\let \normalsetbox = \setbox
+\let \normalsetlanguage = \setlanguage
+\let \normalsfcode = \sfcode
+\let \normalshipout = \shipout
+\let \normalshow = \show
+\let \normalshowbox = \showbox
+\let \normalshowboxbreadth = \showboxbreadth
+\let \normalshowboxdepth = \showboxdepth
+\let \normalshowlists = \showlists
+\let \normalshowthe = \showthe
+\let \normalskewchar = \skewchar
+\let \normalskip = \skip
+\let \normalskipdef = \skipdef
+\let \normalspacefactor = \spacefactor
+\let \normalspaceskip = \spaceskip
+\let \normalspan = \span
+\let \normalspecial = \special
+\let \normalsplitbotmark = \splitbotmark
+\let \normalsplitfirstmark = \splitfirstmark
+\let \normalsplitmaxdepth = \splitmaxdepth
+\let \normalsplittopskip = \splittopskip
+\let \normalstring = \string
+\let \normaltabskip = \tabskip
+\let \normaltextfont = \textfont
+\let \normaltextstyle = \textstyle
+\let \normalthe = \the
+\let \normalthickmuskip = \thickmuskip
+\let \normalthinmuskip = \thinmuskip
+\let \normaltime = \time
+\let \normaltoks = \toks
+\let \normaltoksdef = \toksdef
+\let \normaltolerance = \tolerance
+\let \normaltopmark = \topmark
+\let \normaltopskip = \topskip
+\let \normaltracingcommands = \tracingcommands
+\let \normaltracinglostchars = \tracinglostchars
+\let \normaltracingmacros = \tracingmacros
+\let \normaltracingonline = \tracingonline
+\let \normaltracingoutput = \tracingoutput
+\let \normaltracingpages = \tracingpages
+\let \normaltracingparagraphs = \tracingparagraphs
+\let \normaltracingrestores = \tracingrestores
+\let \normaltracingstats = \tracingstats
+\let \normaluccode = \uccode
+\let \normaluchyph = \uchyph
+\let \normalunderline = \underline
+\let \normalunhbox = \unhbox
+\let \normalunhcopy = \unhcopy
+\let \normalunkern = \unkern
+\let \normalunpenalty = \unpenalty
+\let \normalunskip = \unskip
+\let \normalunvbox = \unvbox
+\let \normalunvcopy = \unvcopy
+\let \normaluppercase = \uppercase
+\let \normalvadjust = \vadjust
+\let \normalvalign = \valign
+\let \normalvbadness = \vbadness
+\let \normalvbox = \vbox
+\let \normalvcenter = \vcenter
+\let \normalvfil = \vfil
+\let \normalvfill = \vfill
+\let \normalvfilneg = \vfilneg
+\let \normalvfuzz = \vfuzz
+\let \normalvoffset = \voffset
+\let \normalvrule = \vrule
+\let \normalvsize = \vsize
+\let \normalvskip = \vskip
+\let \normalvsplit = \vsplit
+\let \normalvss = \vss
+\let \normalvtop = \vtop
+\let \normalwd = \wd
+\let \normalwidowpenalty = \widowpenalty
+\let \normalwrite = \write
+\let \normalxdef = \xdef
+\let \normalxleaders = \xleaders
+\let \normalxspaceskip = \xspaceskip
+\let \normalyear = \year
+
+\endinput
diff --git a/tex/context/base/norm-xtx.tex b/tex/context/base/norm-xtx.tex
new file mode 100644
index 000000000..3da944656
--- /dev/null
+++ b/tex/context/base/norm-xtx.tex
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=norm-xtx,
+%D version=2009.03.19,
+%D title=\CONTEXT\ Norm Macros,
+%D subtitle=\XETEX,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% xetex primitives
+
+% nothing yet (also defined pdftex primitives)
+
+\endinput
diff --git a/tex/context/base/pack-bar.mkiv b/tex/context/base/pack-bar.mkiv
new file mode 100644
index 000000000..05afd32d0
--- /dev/null
+++ b/tex/context/base/pack-bar.mkiv
@@ -0,0 +1,67 @@
+%D \module
+%D [ file=pack-bar,
+%D version=2009.06.26,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Bars,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Bars}
+
+%D This code has been moved from scrn-int to here (was some old
+%D experimental code). It could be in scrn-bar but it's static.
+
+\unprotect
+
+%D \startbuffer
+%D \dorecurse{10}
+%D {\horizontalpositionbar
+%D \pos\recurselevel \min1 \max10
+%D \token\framed{\recurselevel}%
+%D \\}
+%D
+%D \hbox to 15em
+%D {\hss
+%D \dorecurse{10}
+%D {\verticalpositionbar\pos\recurselevel\min1\max10\token\blackrule\\
+%D \hss}}
+%D \stopbuffer
+
+\def\horizontalpositionbar\pos#1\min#2\max#3\token#4\\%
+ {\hbox to \hsize
+ {\hskip\zeropoint\!!plus #1\!!fill
+ \hskip\zeropoint\!!plus-#2\!!fill
+ #4\relax
+ \hskip\zeropoint\!!plus #3\!!fill
+ \hskip\zeropoint\!!plus-#1\!!fill}}
+
+\def\verticalpositionbar\pos#1\min#2\max#3\token#4\\%
+ {\vbox to \vsize
+ {\vskip\zeropoint\!!plus #1\!!fill
+ \vskip\zeropoint\!!plus-#2\!!fill
+ \hbox{#4}\relax
+ \vskip\zeropoint\!!plus #3\!!fill
+ \vskip\zeropoint\!!plus-#1\!!fill}}
+
+\def\horizontalgrowingbar\pos#1\min#2\max#3\height#4\depth#5\\%
+ {\hbox to \hsize
+ {\scratchcounter\numexpr#1-#2+\plusone\relax
+ \leaders\vrule\hskip\zeropoint\!!plus \scratchcounter\!!fill
+ \vrule\!!width\zeropoint\!!height#4\!!depth#5%
+ \hskip\zeropoint\!!plus #3\!!fill
+ \hskip\zeropoint\!!plus-#1\!!fill}}
+
+\def\verticalgrowingbar\pos#1\min#2\max#3\width#4\\%
+ {\vbox to \vsize
+ {\scratchcounter\numexpr#1-#2+\plusone\relax
+ \leaders\hrule\vskip\zeropoint\!!plus\scratchcounter\!!fill
+ \hrule\!!width#4\!!height\zeropoint\!!depth\zeropoint
+ \vskip\zeropoint\!!plus #3\!!fill
+ \vskip\zeropoint\!!plus-#1\!!fill}}
+
+\protect \endinput
diff --git a/tex/context/base/pack-box.mkii b/tex/context/base/pack-box.mkii
new file mode 100644
index 000000000..8adeedb91
--- /dev/null
+++ b/tex/context/base/pack-box.mkii
@@ -0,0 +1,954 @@
+%D \module
+%D [ file=pack-box,
+%D version=2002.04.12,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Boxes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Boxes}
+
+%D This module contains all kind of macros for moving content
+%D around. Many macros here come from other modules, but
+%D depencies made it more clear to isolate them.
+
+% \placeornament
+
+\unprotect
+
+% \definelayer[\v!tekst-2][\c!positie=\v!ja]
+% \definelayer[\v!tekst-1][\c!positie=\v!ja]
+% \definelayer[\v!tekst+1][\c!positie=\v!ja]
+% \definelayer[\v!tekst+2][\c!positie=\v!ja]
+
+% we need to set the size, else we get dimensions depending
+% on the content, which in itsel fis ok, but can lead to loops
+% due to rounding errors (happened in demo-obv)
+
+\definelayer[\v!text-2][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text-1][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text+1][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text+2][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+
+\def\internaltextoverlay#1% will become more generic and installable
+ {\startoverlay % i.e. probably an overlay by itself
+ {\positionoverlay{\v!text#1}} % see later
+ {\composedlayer {\v!text#1}}
+ \stopoverlay}
+
+%\def\internaltextoverlay#1%
+% {\hbox to \zeropoint{\positionoverlay{\v!tekst#1}\hss}%
+% \composedlayer{\v!tekst#1}}
+
+% todo: share info, so that tuo will be smaller
+
+\defineoverlay[\v!text-2][\internaltextoverlay{-2}]
+\defineoverlay[\v!text-1][\internaltextoverlay{-1}]
+\defineoverlay[\v!text+1][\internaltextoverlay{+1}]
+\defineoverlay[\v!text+2][\internaltextoverlay{+2}]
+
+% to be documented
+
+\definelayer[anchor]
+
+\def\anchor
+ {\dosingleargument\doanchor}
+
+\def\doanchor[#1]%
+ {\ifundefined{\??an#1}\@EA\dodoanchor\else\@EA\nonoanchor\fi[#1]}
+
+\def\nonoanchor[#1]%
+ {\getvalue{\??an#1}}
+
+\def\dodoanchor[#1]%
+ {\dotripleempty\dododoanchor[#1]}
+
+\def\dododoanchor
+ {\ifthirdargument
+ \expandafter\dodoanchorT
+ \else
+ \expandafter\dodoanchorS
+ \fi}
+
+\def\dodoanchorS[#1][#2][#3]%
+ {\dodoanchorT[#1][#2][#2]}
+
+\def\dodoanchorT[#1][#2][#3]%
+ {\dowithnextbox
+ {\bgroup
+ \checktextbackgrounds
+ \setbox\scratchbox\null
+ \wd\scratchbox\nextboxwd
+ \ht\scratchbox\nextboxht
+ \dp\scratchbox\nextboxdp
+ \setlayer
+ [anchor]
+ [\c!width=\wd\scratchbox,
+ \c!height=\ht\scratchbox,
+ \c!offset=\!!zeropoint,
+ #2,#3]
+ {\setlayer[#1]{\flushnextbox}}%
+ \framed
+ [#2,
+ \c!background=anchor,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ #3]
+ {\box\scratchbox}%
+ \egroup}%
+ \vbox}
+
+\def\defineanchor
+ {\doquadrupleempty\dodefineanchor}
+
+\def\dodefineanchor[#1][#2][#3][#4]%
+ {\setvalue{\??an#1}{\dodefinedanchor[#2][#3][#4]}}
+
+\def\dodefinedanchor[#1][#2][#3]%
+ {\def\docommand[##1][##2]%
+ {\ifsecondargument
+ \def\next{\dodoanchorT[#1][#2,##1][#3,##2]}%
+ \else\iffirstargument
+ \def\next{\dodoanchorT[#1][#2,##1][#2,##1]}%
+ \else
+ \def\next{\dodoanchorT[#1][#2][#3]}%
+ \fi\fi
+ \next}%
+ \dodoubleempty\docommand}
+
+\def\@@collectorbox{@@collectorbox}
+
+\def\definecollector
+ {\dodoubleargument\dodefinecollector}
+
+\def\dodefinecollector[#1][#2]%
+ {\ifundefined{\@@collectorbox#1}%
+ \expandafter\newbox\csname\@@collectorbox#1\endcsname
+ \fi
+ \resetcollector[#1]%
+ \setupcollector
+ [#1]
+ [\c!state=\v!start,
+ \c!x=\!!zeropoint,\c!y=\!!zeropoint,
+ \c!offset=\!!zeropoint,\c!rotation=, % geen 0 !
+ \c!hoffset=\!!zeropoint,\c!voffset=\!!zeropoint,
+ \c!location=rb,\c!corner=,#2]}
+
+\def\setupcollector
+ {\dodoubleargument\dosetupcollector}
+
+\def\dosetupcollector[#1][#2]%
+ {\def\docommand##1{\getparameters[\??cb##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+\def\setcollector
+ {\dodoubleargument\dosetcollector}
+
+\def\dosetcollector[#1][#2]%
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \dowithnextbox
+ {\ifundefined{\@@collectorbox#1}%
+ \writestatus{collector}{unknown layer #1}%
+ \else
+ \dodosetcollector[#1][#2]%
+ \fi
+ \egroup}
+ \hbox}
+
+\def\collectorparameter#1{\csname\??cb\currentcollector#1\endcsname}
+
+\def\dodosetcollector[#1][#2]% todo: keep reference point
+ {\def\currentcollector{#1}%
+ \mathchardef\collectorbox\csname\@@collectorbox#1\endcsname
+ \getparameters[\??cb#1][#2]%
+ \@@layerxsiz\wd\collectorbox
+ \@@layerysiz\ht\collectorbox
+ \doifvaluesomething{\??cb#1\c!rotation}
+ {\setbox\nextbox\hbox
+ {\rotate
+ [\c!location=\v!high,
+ \c!rotation=\collectorparameter\c!rotation]
+ {\flushnextbox}}}%
+ \advance\@@layerysiz\dp\collectorbox
+ \@@layerxpos\collectorparameter\c!x
+ \advance\@@layerxpos\collectorparameter\c!hoffset
+ \@@layerypos\collectorparameter\c!y
+ \advance\@@layerypos\collectorparameter\c!voffset
+ \doifelse\v!middle{\collectorparameter\c!corner}
+ {\ifdim\@@layerxsiz>\zeropoint
+ \advance\@@layerxpos.5\@@layerxsiz
+ \fi
+ \ifdim\@@layerysiz>\zeropoint
+ \advance\@@layerypos.5\@@layerysiz
+ \fi}%
+ {\ExpandBothAfter\doifinset\v!bottom{\collectorparameter\c!corner}
+ {\ifdim\@@layerysiz>\zeropoint
+ \advance\@@layerypos-\@@layerysiz
+ \@@layerypos-\@@layerypos
+ \fi}%
+ \ExpandBothAfter\doifinset\v!right{\collectorparameter\c!corner}
+ {\ifdim\@@layerxsiz>\zeropoint
+ \advance\@@layerxpos-\@@layerxsiz
+ \@@layerxpos-\@@layerxpos
+ \fi}}%
+ \setbox\nextbox\hbox
+ {\alignedbox[\collectorparameter\c!location]\vbox{\flushnextbox}}%
+ \boxmaxdepth\zeropoint % really needed, nice example
+ \global\advance\boxhdisplacement\@@layerxpos
+ \ifdim\boxhdisplacement<\zeropoint
+ \global\setbox\collectorbox\hbox
+ {\hskip-\boxhdisplacement
+ \box\collectorbox}%
+ \fi
+ \global\advance\boxvdisplacement\@@layerypos
+ \ifdim\boxvdisplacement<\zeropoint
+ \global\setbox\collectorbox\hbox
+ {\lower-\boxvdisplacement
+ \box\collectorbox}%
+ \fi
+ \@@layerxsiz\wd\collectorbox
+ \@@layerysiz\ht\collectorbox
+ \advance\@@layerysiz\dp\collectorbox
+ \global\setbox\collectorbox\hbox
+ {\box\collectorbox
+ \hskip-\@@layerxsiz
+ \hskip\@@layerxpos\relax
+ \ifdim\boxhdisplacement<\zeropoint
+ \hskip-\boxhdisplacement
+ \fi
+ \lower\@@layerypos\hbox
+ {\ifdim\boxvdisplacement<\zeropoint
+ \lower-\boxvdisplacement\flushnextbox
+ \else
+ \flushnextbox
+ \fi}}%
+ % combine height and depth into depth only (later flushed as height)
+ \global\setbox\collectorbox\hbox
+ {\lower\ht\collectorbox\box\collectorbox}%
+ % just to be sure
+ \ifdim\wd\collectorbox<\@@layerxsiz
+ \global\wd\collectorbox\@@layerxsiz
+ \fi}
+
+\def\flushcollector[#1]%
+ {\ifundefined{\@@collectorbox#1}%
+ \writestatus{collector}{unknown collector #1}%
+ \else
+ \doifnotvalue{\??cb#1\c!state}\v!stop
+ {\vbox
+ {\hbox
+ {\doifelsevalue{\??cb#1\c!state}\v!repeat
+ {\let\next\copy}{\let\next\box}%
+ \raise\dp\csname\@@collectorbox#1\endcsname
+ \next\csname\@@collectorbox#1\endcsname}}}%
+ \fi}
+
+\def\composedcollector#1{\flushcollector[#1]}
+
+\def\resetcollector[#1]%
+ {\ifundefined{\@@collectorbox#1}\else
+ \global\setbox\csname\@@collectorbox#1\endcsname\emptybox
+ \fi}
+
+\def\adaptcollector
+ {\dodoubleargument\doadaptcollector}
+
+\def\doadaptcollector[#1][#2]%
+ {\bgroup
+ \def\currentcollector{#1}%
+ \mathchardef\collectorbox\csname\@@collectorbox#1\endcsname
+ \getparameters
+ [\??cb#1][\c!voffset=\zeropoint,\c!hoffset=\zeropoint,#2]%
+ \scratchdimen\wd\collectorbox
+ \advance\scratchdimen\collectorparameter\c!hoffset
+ \global\wd\collectorbox\scratchdimen
+ \scratchdimen\ht\collectorbox
+ \advance\scratchdimen\collectorparameter\c!voffset
+ \global\ht\collectorbox\scratchdimen
+ \egroup}
+
+%\definecollector[test]
+%\setcollector[test]
+% [location=rb]
+% {\externalfigure[koe][frame=on,width=3cm]}
+%\setcollector[test]
+% [corner={right,bottom},location={left,top}]
+% {\framed{gans}}
+%\composedcollector{test}
+
+\definecollector
+ [caption]
+
+\def\collectedtext
+ {\dodoubleempty\docollectedtext}
+
+\def\docollectedtext[#1][#2]#3%
+ {\bgroup
+ \dowithnextbox
+ {\setcollector
+ [caption]
+ {\flushnextbox}%
+ \setcollector
+ [caption][#1]
+ {\getparameters[\??du][#2]%
+ \dosetfontattribute\??du\c!style\setupinterlinespace
+ \framed % watch the special setting of kader/overlay
+ [\c!frame=\v!overlay,#2]
+ {\doattributes\??du\c!style\c!color{#3}}}%
+ \composedcollector{caption}%
+ \egroup}%
+ \hbox}
+
+% \collectedtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\definelayer
+ [caption]
+
+\def\layeredtext
+ {\dodoubleempty\dolayeredtext}
+
+\def\dolayeredtext[#1][#2]#3%
+ {\bgroup
+ \dowithnextbox
+ {\!!widtha \nextboxwd
+ \!!heighta\nextboxht
+ \bgroup % preserve \nextbox
+ \setuplayer
+ [caption]
+ [\c!width=\!!widtha,\c!height=\!!heighta]%
+ \setlayer
+ [caption]
+ [#1]
+ {\getparameters[\??du][#2]%
+ \dosetfontattribute\??du\c!style\setupinterlinespace
+ \framed
+ [\c!frame=\v!overlay,,#2]
+ {\doattributes\??du\c!style\c!color{#3}}}%
+ \egroup
+ \framed
+ [\c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!background={\v!foreground,caption},
+ \c!width=\!!widtha,
+ \c!height=\!!heighta]
+ {\flushnextbox}%
+ \egroup}%
+ \hbox}
+
+% \layeredtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\def\ornamenttext
+ {\dodoubleempty\doornamenttext}
+
+\def\doornamenttext[#1][#2]%
+ {\bgroup
+ \doifassignmentelse{#1}
+ {\getparameters[\s!dummy][\c!alternative=\v!a,#1]%
+ \doifelse\dummyalternative\v!a
+ {\egroup\collectedtext}%
+ {\egroup\layeredtext }%
+ [#1][#2]}%
+ {\egroup\getvalue{#1}}}
+
+\def\defineornament
+ {\dotripleempty\dodefineornament}
+
+\def\dodefineornament[#1][#2][#3]%
+ {\setvalue{#1}{\doornamenttext[#2][#3]}}
+
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex,alternative=b]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=a]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{photo}{\externalfigure[molen][width=3cm]}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=b]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{drawing}{\externalfigure[hakker][width=3cm]}
+
+% pas op: aanpassen aan nieuwe layer hoek ankers en columnset
+
+\newcount\nofbleeds % per pag
+
+\def\setupbleeding
+ {\dodoubleempty\getparameters[\??bg]}
+
+\setupbleeding
+ [\c!location=l,
+ \c!stretch=\v!yes,
+ \c!width=3cm,
+ \c!height=3cm,
+ \c!offset=2mm,
+ \c!page=\v!no,
+ \c!voffset=\@@bgoffset,
+ \c!hoffset=\@@bgoffset]
+
+\def\bleed
+ {\dosingleempty\dobleed}
+
+
+\def\bleedwidth {\the\hsize}%
+\def\bleedheight{\the\vsize}%
+
+\def\dobleed[#1]#2%
+ {\hbox\bgroup
+ \xdef\bleedwidth {\the\hsize}%
+ \xdef\bleedheight{\the\vsize}%
+ \global\advance\nofbleeds\plusone
+ \getparameters[\??bg][#1]%
+ \!!doneafalse % left
+ \!!donebfalse % right
+ \!!donecfalse % top
+ \!!donedfalse % bottom
+ % replace this part ! todo: default location
+ \processaction
+ [\@@bglocation]
+ [ t=>\!!donectrue\let\@@bghoffset\!!zeropoint,
+ b=>\!!donedtrue\let\@@bghoffset\!!zeropoint,
+ l=>\!!doneatrue\let\@@bgvoffset\!!zeropoint,
+ r=>\!!donebtrue\let\@@bgvoffset\!!zeropoint,
+ bl=>\!!doneatrue\!!donedtrue,
+ lb=>\!!doneatrue\!!donedtrue,
+ br=>\!!donebtrue\!!donedtrue,
+ rb=>\!!donebtrue\!!donedtrue,
+ tl=>\!!doneatrue\!!donectrue,
+ lt=>\!!doneatrue\!!donectrue,
+ tr=>\!!donebtrue\!!donectrue,
+ rt=>\!!donebtrue\!!donectrue]%
+ \doifelse\@@bgstretch\v!yes\donetrue\donefalse
+ \scratchdimen\@@bgwidth
+ \ifdone
+ \if!!donea
+ \advance\scratchdimen\MPx{\??bg:\number\nofbleeds}%
+ \else\if!!doneb
+ \scratchdimen\paperwidth
+ \advance\scratchdimen-\MPx{\??bg:\number\nofbleeds}%
+ \fi\fi
+ \fi
+ \advance\scratchdimen\@@bghoffset
+ \xdef\bleedwidth{\the\scratchdimen}%
+ \scratchdimen\@@bgheight
+ \ifdone
+ \if!!donec
+ \scratchdimen\paperheight
+ \advance\scratchdimen-\MPy{\??bg:\number\nofbleeds}%
+ \else\if!!doned
+ \advance\scratchdimen\MPy{\??bg:\number\nofbleeds}%
+ \fi\fi
+ \fi
+ \advance\scratchdimen\@@bgvoffset
+ \xdef\bleedheight{\the\scratchdimen}%
+ \hsize\bleedwidth
+ \vsize\bleedheight
+ \setbox\scratchbox\hbox{#2}%
+ \doif\@@bgpage\v!yes
+ {\setbox\scratchbox\topskippedbox{\box\scratchbox}}%
+ \setbox\scratchbox\hbox to \@@bgwidth
+ {\if!!donea\hss\fi\box\scratchbox\if!!doneb\hss\fi}%
+ \if!!doned
+ \setbox\scratchbox\hbox
+ {\lower\bleedheight\hbox{\raise\@@bgheight\box\scratchbox}}%
+ \fi
+ \wd\scratchbox\@@bgwidth
+ \ht\scratchbox\@@bgheight
+ \dp\scratchbox\zeropoint
+ \ifdone
+ \hpos{\??bg:\number\nofbleeds}{\box\scratchbox}%
+ \else
+ \box\scratchbox
+ \fi
+ \egroup}
+
+\setupbleeding[\c!stretch=\v!yes]
+
+\defineexternalfigure[bleed][\c!width=\bleedwidth,\c!height=\bleedheight]
+
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[right]{none}
+% {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placesomefloat[right]{none}
+% {\bleed[width=5cm,height=3cm,location=rb]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure
+% [top,none]
+% {} % no caption
+% {\bleed
+% [hoffset=-\backspace,
+% voffset=3mm,
+% width=0cm,
+% height=6\lineheight,
+% page=yes, % correct for topskip
+% location=lt]
+% {\externalfigure[koe][bleed][frame=on]}}
+
+% \setlayerframed[layer id][layer settings][framed setting]{data}
+% \setlayerframed[layer id][combined settings]{data}
+
+\def\setlayerframed
+ {\dotripleempty\dosetlayerframed}
+
+\def\dosetlayerframed
+ {\ifthirdargument
+ \expandafter\dosetlayerframedT
+ \else
+ \expandafter\dosetlayerframedS
+ \fi}
+
+\def\dosetlayerframedT[#1][#2][#3]%
+ {\dowithnextbox{\setlayer[#1][#2]{\flushnextbox}}%
+ \hbox\framed[#3]}
+
+\def\dosetlayerframedS[#1][#2][#3]%
+ {\dowithnextbox
+ {\setlayer
+ [#1]
+ [\c!width=\nextboxwd,\c!height=\nextboxht,
+ \c!offset=\!!zeropoint,#2]
+ {\flushnextbox}}%
+ \hbox\framed[\c!location=\v!normal,#2]}
+
+\def\setlayertext
+ {\dotripleempty\dosetlayertext}
+
+\def\dosetlayertext[#1][#2][#3]%
+ {\bgroup
+ \getparameters
+ [\??lx]
+ [\c!align=,
+ \c!width=\hsize,
+ \c!color=,
+ \c!style=,
+ #3]%
+ \dowithnextboxcontent
+ {\forgetall
+ \hsize\@@lxwidth
+ \expanded{\setupalign[\@@lxalign]}%
+ \dosetfontattribute\??lx\c!style}
+ {\setlayer[#1][#2]{\strut\color[\@@lxcolor]{\flushnextbox}}%
+ \egroup}%
+ \vtop}
+
+% \setupbackgrounds
+% [page]
+% [background=pagefigures]
+%
+% \definelayer
+% [pagefigures]
+% [x=-2mm,
+% y=-2mm,
+% width=\paperwidth,
+% height=\paperheight]
+%
+% \definelayerpreset [lefttop] [corner={left,top},location={right,bottom}]
+% \definelayerpreset [righttop] [corner={right,top},location={left,bottom}]
+% \definelayerpreset [leftbottom] [corner={left,bottom},location={right,top}]
+% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}]
+% \definelayerpreset [middle] [corner=middle,location=middle]
+%
+% \setlayer[pagefigures][preset=lefttop]
+% \setlayer[pagefigures][preset=righttop]
+% \setlayer[pagefigures][preset=leftbottom]
+% \setlayer[pagefigures][preset=rightbottom]
+
+\definelayerpreset
+ [\v!left\v!top]
+ [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}]
+
+\definelayerpreset
+ [\v!right\v!top]
+ [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}]
+
+\definelayerpreset
+ [\v!left\v!bottom]
+ [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}]
+
+\definelayerpreset
+ [\v!right\v!bottom]
+ [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}]
+
+\definelayerpreset
+ [\v!middle]
+ [\c!corner=\v!middle,\c!location=\v!middle]
+
+% \definelayerpreset
+% [\v!middle\v!top]
+% [\c!location=\v!bottom,\c!hoffset=.5\layerwidth]
+
+% \definelayerpreset
+% [\v!middle\v!bottom]
+% [\c!location=\v!top,\c!hoffset=.5\layerwidth,\c!voffset=\layerheight]
+
+% \definelayerpreset
+% [\v!middle\v!left]
+% [\c!location=\v!right,\c!voffset=.5\layerheight]
+
+% \definelayerpreset
+% [\v!middle\v!right]
+% [\c!location=\v!left,\c!hoffset=\layerwidth,\c!voffset=.5\layerheight]
+
+\definelayerpreset
+ [\v!middle\v!top]
+ [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!bottom]
+ [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!left]
+ [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight]
+
+\definelayerpreset
+ [\v!middle\v!right]
+ [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight]
+
+\def\alignedbox
+ {\dodoubleempty\doalignedbox[]}
+
+% \def\doalignedbox[#1][#2]%
+% {\bgroup
+% %\let\iftraceboxplacement\iftracelayers % ugly
+% \dowithnextbox
+% {\let\next\middlebox
+% \processaction
+% [#2]
+% [ t=>\let\next\topbox , b=>\let\next\bottombox ,
+% l=>\let\next\leftbox , r=>\let\next\rightbox ,
+% bl=>\let\next\bottomleftbox,br=>\let\next\bottomrightbox,
+% tl=>\let\next\topleftbox ,tr=>\let\next\toprightbox ,
+% lt=>\let\next\lefttopbox ,lb=>\let\next\leftbottombox ,
+% rt=>\let\next\righttopbox ,rb=>\let\next\rightbottombox]%
+% \next{\flushnextbox}%
+% \egroup}#1}
+
+\def\doalignedbox[#1][#2]%
+ {\bgroup
+ %\let\iftraceboxplacement\iftracelayers % ugly
+ \dowithnextbox
+ {\serializecommalist[#2]%
+ \executeifdefined{\??ab\??ab\serializedcommalist}\middlebox{\flushnextbox}%
+ \egroup}#1}
+
+\setvalue{\??ab\??ab }{\middlebox}
+\setvalue{\??ab\??ab\v!middle }{\middlebox}
+\setvalue{\??ab\??ab\v!left }{\leftbox }
+\setvalue{\??ab\??ab\v!right }{\rightbox }
+\setvalue{\??ab\??ab\v!bottom }{\bottombox}
+\setvalue{\??ab\??ab\v!top }{\topbox }
+
+\setvalue{\??ab\??ab\v!middle\v!middle}{\middlebox}
+\setvalue{\??ab\??ab\v!left \v!top }{\lefttopbox}
+\setvalue{\??ab\??ab\v!left \v!bottom}{\leftbottombox}
+\setvalue{\??ab\??ab\v!right \v!top }{\righttopbox}
+\setvalue{\??ab\??ab\v!right \v!bottom}{\rightbottombox}
+\setvalue{\??ab\??ab\v!top \v!left }{\topleftbox}
+\setvalue{\??ab\??ab\v!bottom\v!left }{\bottomleftbox}
+\setvalue{\??ab\??ab\v!top \v!right }{\toprightbox}
+\setvalue{\??ab\??ab\v!bottom\v!right }{\bottomrightbox}
+
+\setvalue{\??ab\??ab c}{\middlebox}
+\setvalue{\??ab\??ab l}{\leftbox}
+\setvalue{\??ab\??ab r}{\rightbox}
+\setvalue{\??ab\??ab b}{\bottombox}
+\setvalue{\??ab\??ab t}{\topbox}
+
+\setvalue{\??ab\??ab lt}{\lefttopbox}
+\setvalue{\??ab\??ab lb}{\leftbottombox}
+\setvalue{\??ab\??ab rt}{\righttopbox}
+\setvalue{\??ab\??ab rb}{\rightbottombox}
+\setvalue{\??ab\??ab tl}{\topleftbox}
+\setvalue{\??ab\??ab bl}{\bottomleftbox}
+\setvalue{\??ab\??ab tr}{\toprightbox}
+\setvalue{\??ab\??ab br}{\bottomrightbox}
+
+\setvalue{\??ab\??ab m}{\middlebox}
+
+% The next ones were desparately needed by Vit Zyka (see
+% \type {supp-box} for definitions).
+
+\setvalue{\??ab\??ab g}{\baselinemiddlebox}
+\setvalue{\??ab\??ab gl}{\baselineleftbox}
+\setvalue{\??ab\??ab gc}{\baselinemiddlebox}
+\setvalue{\??ab\??ab gr}{\baselinerightbox}
+
+\setvalue{\??ab\??ab \v!line }{\baselinemiddlebox} % \v!grid is taken
+\setvalue{\??ab\??ab \v!line\v!left }{\baselineleftbox}
+\setvalue{\??ab\??ab \v!line\v!middle}{\baselinemiddlebox}
+\setvalue{\??ab\??ab \v!line\v!right }{\baselinerightbox}
+
+\unexpanded\def\offsetbox
+ {\dodoubleempty\dooffsetbox[]}
+
+% left/right/top/bottomoffset -> dimensions change
+% x/y | method=fixed -> dimensions don't change
+
+\def\dooffsetbox[#1][#2]%
+ {\bgroup
+ \dowithnextbox
+ {\getparameters[\??ox]
+ [\c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!width=\nextboxwd,
+ \c!height=\nextboxht,
+ \c!depth=\nextboxdp,
+ \c!location=,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!method=,
+ #2]%
+ \donefalse
+ \ifdim\@@oxleftoffset =\zeropoint\else\donetrue\fi
+ \ifdim\@@oxrightoffset=\zeropoint\else\donetrue\fi
+ \ifdim\@@oxtopoffset =\zeropoint\else\donetrue\fi
+ \ifdim\@@oxbottomoffset =\zeropoint\else\donetrue\fi
+ \ifdone
+ \doif\@@oxmethod\v!fixed % new
+ {\ifdim\@@oxleftoffset=\zeropoint
+ \ifdim\@@oxrightoffset=\zeropoint \else
+ \scratchdimen-\@@oxrightoffset
+ \edef\@@oxx{\the\scratchdimen}%
+ \let\@@oxrightoffset\zeropoint
+ \fi
+ \else
+ \let\@@oxx\@@oxleftoffset
+ \let\@@oxleftoffset\zeropoint
+ \fi
+ \ifdim\@@oxtopoffset=\zeropoint
+ \ifdim\@@oxbottomoffset=\zeropoint \else
+ \scratchdimen-\@@oxbottomoffset
+ \edef\@@oxy{\the\scratchdimen}%
+ \let\@@oxbottomoffset\zeropoint
+ \fi
+ \else
+ \let\@@oxy\@@oxtopoffset
+ \let\@@oxtopoffset\zeropoint
+ \fi
+ \donefalse}%
+ \fi
+ \ifdone
+ \setbox\nextbox\vbox
+ {\forgetall\offinterlineskip
+ \vskip\@@oxtopoffset
+ \hbox
+ {\hskip\@@oxleftoffset
+ \flushnextbox
+ \hskip\@@oxrightoffset}%
+ \vskip\@@oxbottomoffset}%
+ \scratchdimen\nextboxht
+ \advance\scratchdimen\nextboxdp
+ \nextboxht\scratchdimen
+ \nextboxdp\zeropoint
+ \fi
+ \freezedimenmacro\@@oxwidth
+ \freezedimenmacro\@@oxheight
+ \freezedimenmacro\@@oxdepth
+ \setbox\nextbox\hbox
+ {\hskip\@@oxx\lower\@@oxy\hbox
+ {\doifelsenothing\@@oxlocation
+ {\flushnextbox}
+ {\alignedbox[\@@oxlocation]\hbox{\flushnextbox}}}}%
+ \nextboxwd\@@oxwidth
+ \nextboxht\@@oxheight
+ \nextboxdp\@@oxdepth
+ \flushnextbox
+ \egroup}#1}
+
+% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
+%
+% \placefigure[left,none]{}{\offset[leftoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+% \placefigure[left,none]{}{\offset[rightoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+% \placefigure[left,none]{}{\offset[topoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+
+\unexpanded\def\offset {\dodoubleempty\dooffsetbox [\hbox]} % yes or no
+\unexpanded\def\aligned{\dosingleempty\doalignedbox[\hbox]} % yes or no
+
+%\ruledhbox{\offsetbox[x=-1cm,y=-1cm,location=c]
+% {\framed[width=4cm,height=4cm]{x}}}
+
+\def\dotabbed#1#2#3#4%
+ {\dontleavehmode
+ \bgroup
+ \setbox\scratchbox\hbox{#3}%
+ \hbox to \wd\scratchbox{#1#4#2}%
+ \egroup}
+
+\unexpanded\def\ltabbed{\dotabbed\relax\hss}
+\unexpanded\def\rtabbed{\dotabbed\hss \relax}
+\unexpanded\def\ctabbed{\dotabbed\hss \hss} \let\mtabbed\ctabbed
+
+% \ltabbed{\romeins{3}}{\romeins{1}} test \endgraf
+% \ltabbed{\romeins{3}}{\romeins{2}} test \endgraf
+% \ltabbed{\romeins{3}}{\romeins{3}} test \endgraf
+%
+% \rtabbed{\romeins{3}}{\romeins{1}} test \endgraf
+% \rtabbed{\romeins{3}}{\romeins{2}} test \endgraf
+% \rtabbed{\romeins{3}}{\romeins{3}} test \endgraf
+%
+% \ctabbed{\romeins{3}}{\romeins{1}} test \endgraf
+% \ctabbed{\romeins{3}}{\romeins{2}} test \endgraf
+% \ctabbed{\romeins{3}}{\romeins{3}} test \endgraf
+
+% alternative, if done, then other name
+%
+% \def\dotabbed#1#2#3#4%
+% {\dontleavehmode
+% \bgroup
+% \scratchdimen\zeropoint
+% \def\docommand##1%
+% {\setbox\scratchbox\hbox{##1}%
+% \ifdim\wd\scratchbox>\scratchdimen
+% \scratchdimen\wd\scratchbox
+% \fi}%
+% \processcommalist[#3]\docommand
+% \hbox to \scratchdimen{#1#4#2}%
+% \egroup}
+%
+% \def\ltabbed{\dotabbed\relax\hss}
+% \def\rtabbed{\dotabbed\hss \relax}
+% \def\ctabbed{\dotabbed\hss \hss} \let\mtabbed\ctabbed
+%
+% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
+% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
+% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
+%
+% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
+% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
+% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
+%
+% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
+% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
+% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
+
+% to be documented
+
+\unexpanded\def\phantombox[#1]%
+ {\hbox\bgroup
+ \getparameters
+ [\??ol]
+ [\c!width=\zeropoint,%
+ \c!height=\zeropoint,%
+ \c!depth=\zeropoint,#1]%
+ \setbox\scratchbox\null
+ \wd\scratchbox\@@olwidth
+ \ht\scratchbox\@@olheight
+ \dp\scratchbox\@@oldepth
+ \box\scratchbox
+ \egroup}
+
+% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
+
+\unexpanded\def\backgroundimage#1#2#3% repeat hsize vsize
+ {\bgroup
+ \forgetall
+ \dowithnextbox
+ {\offinterlineskip
+ \ifcase#1\relax
+ % just one
+ \else
+ \scratchdimen#2\divide\scratchdimen\nextboxwd\count0\scratchdimen\advance\count0\plusone
+ \scratchdimen#3\divide\scratchdimen\nextboxht\count2\scratchdimen\advance\count2\plusone
+ % to be considered, probably methods
+ \ifcase#1\or % x and y
+ \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
+ \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
+ \or % x
+ \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
+ \or % y
+ \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
+ \fi
+ \fi
+ \ifdim\nextboxwd>#2\relax
+ \setbox\nextbox\hbox to #2{\hss\flushnextbox\hss}%
+ \setbox\nextbox\hbox{\expanded{\clip[\c!width=#2,\c!height=\the\nextboxht]{\flushnextbox}}}%
+ \fi
+ \ifdim\nextboxht>#3\relax
+ \setbox\nextbox\vbox to #3{\vss\flushnextbox\vss}%
+ \setbox\nextbox\hbox{\expanded{\clip[\c!width=\the\nextboxwd,\c!height=#3]{\flushnextbox}}}%
+ \fi
+ \flushnextbox
+ \egroup}%
+ \hbox}
+
+\protect \endinput
diff --git a/tex/context/base/pack-box.mkiv b/tex/context/base/pack-box.mkiv
new file mode 100644
index 000000000..6cb492aa6
--- /dev/null
+++ b/tex/context/base/pack-box.mkiv
@@ -0,0 +1,944 @@
+%D \module
+%D [ file=pack-box,
+%D version=2002.04.12,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Boxes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Boxes}
+
+%D This module contains all kind of macros for moving content
+%D around. Many macros here come from other modules, but
+%D depencies made it more clear to isolate them.
+
+% \placeornament
+
+\unprotect
+
+% \definelayer[\v!tekst-2][\c!positie=\v!ja]
+% \definelayer[\v!tekst-1][\c!positie=\v!ja]
+% \definelayer[\v!tekst+1][\c!positie=\v!ja]
+% \definelayer[\v!tekst+2][\c!positie=\v!ja]
+
+% we need to set the size, else we get dimensions depending
+% on the content, which in itsel fis ok, but can lead to loops
+% due to rounding errors (happened in demo-obv)
+
+\definelayer[\v!text-2][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text-1][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text+1][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text+2][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+
+\def\internaltextoverlay#1% will become more generic and installable
+ {\startoverlay % i.e. probably an overlay by itself
+ {\positionoverlay{\v!text#1}} % see later
+ {\composedlayer {\v!text#1}}
+ \stopoverlay}
+
+%\def\internaltextoverlay#1%
+% {\hbox to \zeropoint{\positionoverlay{\v!tekst#1}\hss}%
+% \composedlayer{\v!tekst#1}}
+
+% todo: share info, so that tuo will be smaller
+
+\defineoverlay[\v!text-2][\internaltextoverlay{-2}]
+\defineoverlay[\v!text-1][\internaltextoverlay{-1}]
+\defineoverlay[\v!text+1][\internaltextoverlay{+1}]
+\defineoverlay[\v!text+2][\internaltextoverlay{+2}]
+
+% to be documented
+
+\definelayer[anchor]
+
+\def\anchor
+ {\dosingleargument\doanchor}
+
+\def\doanchor[#1]%
+ {\ifcsname\??an#1\endcsname\@EA\nonoanchor\else\@EA\dodoanchor\fi[#1]}
+
+\def\nonoanchor[#1]%
+ {}
+
+\def\dodoanchor[#1]%
+ {\dotripleempty\dododoanchor[#1]}
+
+\def\dododoanchor
+ {\ifthirdargument
+ \expandafter\dodoanchorT
+ \else
+ \expandafter\dodoanchorS
+ \fi}
+
+\def\dodoanchorS[#1][#2][#3]%
+ {\dodoanchorT[#1][#2][#2]}
+
+\def\dodoanchorT[#1][#2][#3]%
+ {\dowithnextbox
+ {\bgroup
+ \checktextbackgrounds
+ \setbox\scratchbox\null
+ \wd\scratchbox\nextboxwd
+ \ht\scratchbox\nextboxht
+ \dp\scratchbox\nextboxdp
+ \setlayer
+ [anchor]
+ [\c!width=\wd\scratchbox,
+ \c!height=\ht\scratchbox,
+ \c!offset=\!!zeropoint,
+ #2,#3]
+ {\setlayer[#1]{\flushnextbox}}%
+ \framed
+ [#2,
+ \c!background=anchor,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ #3]
+ {\box\scratchbox}%
+ \egroup}%
+ \vbox}
+
+\unexpanded\def\defineanchor
+ {\doquadrupleempty\dodefineanchor}
+
+\def\dodefineanchor[#1][#2][#3][#4]%
+ {\setvalue{\??an#1}{\dodefinedanchor[#2][#3][#4]}}
+
+\def\dodefinedanchor[#1][#2][#3]%
+ {\def\docommand[##1][##2]%
+ {\ifsecondargument
+ \def\next{\dodoanchorT[#1][#2,##1][#3,##2]}%
+ \else\iffirstargument
+ \def\next{\dodoanchorT[#1][#2,##1][#2,##1]}%
+ \else
+ \def\next{\dodoanchorT[#1][#2][#3]}%
+ \fi\fi
+ \next}%
+ \dodoubleempty\docommand}
+
+\def\@@collectorbox{@@collectorbox}
+
+\unexpanded\def\definecollector
+ {\dodoubleargument\dodefinecollector}
+
+\def\dodefinecollector[#1][#2]%
+ {\ifcsname\@@collectorbox#1\endcsname \else
+ \expandafter\newbox\csname\@@collectorbox#1\endcsname
+ \fi
+ \resetcollector[#1]%
+ \setupcollector
+ [#1]
+ [\c!state=\v!start,
+ \c!x=\!!zeropoint,\c!y=\!!zeropoint,
+ \c!offset=\!!zeropoint,\c!rotation=, % geen 0 !
+ \c!hoffset=\!!zeropoint,\c!voffset=\!!zeropoint,
+ \c!location=rb,\c!corner=,#2]}
+
+\unexpanded\def\setupcollector
+ {\dodoubleargument\dosetupcollector}
+
+\def\dosetupcollector[#1][#2]%
+ {\def\docommand##1{\getparameters[\??cb##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+\def\setcollector
+ {\dodoubleargument\dosetcollector}
+
+\def\dosetcollector[#1][#2]%
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \dowithnextbox
+ {\ifcsname\@@collectorbox#1\endcsname
+ \dodosetcollector[#1][#2]%
+ \else
+ \writestatus{collector}{unknown layer #1}%
+ \fi
+ \egroup}
+ \hbox}
+
+\def\collectorparameter#1{\csname\??cb\currentcollector#1\endcsname}
+
+\def\dodosetcollector[#1][#2]% todo: keep reference point
+ {\def\currentcollector{#1}%
+ \chardef\collectorbox\csname\@@collectorbox#1\endcsname
+ \getparameters[\??cb#1][#2]%
+ \@@layerxsiz\wd\collectorbox
+ \@@layerysiz\ht\collectorbox
+ \doifvaluesomething{\??cb#1\c!rotation}
+ {\setbox\nextbox\hbox
+ {\rotate
+ [\c!location=\v!high,
+ \c!rotation=\collectorparameter\c!rotation]
+ {\flushnextbox}}}%
+ \advance\@@layerysiz\dp\collectorbox
+ \@@layerxpos\collectorparameter\c!x
+ \advance\@@layerxpos\collectorparameter\c!hoffset
+ \@@layerypos\collectorparameter\c!y
+ \advance\@@layerypos\collectorparameter\c!voffset
+ \doifelse\v!middle{\collectorparameter\c!corner}
+ {\ifdim\@@layerxsiz>\zeropoint
+ \advance\@@layerxpos.5\@@layerxsiz
+ \fi
+ \ifdim\@@layerysiz>\zeropoint
+ \advance\@@layerypos.5\@@layerysiz
+ \fi}%
+ {\normalexpanded{\noexpand\doifinset{\v!bottom}{\collectorparameter\c!corner}}
+ {\ifdim\@@layerysiz>\zeropoint
+ \advance\@@layerypos-\@@layerysiz
+ \@@layerypos-\@@layerypos
+ \fi}%
+ \normalexpanded{\noexpand\doifinset{\v!right}{\collectorparameter\c!corner}}
+ {\ifdim\@@layerxsiz>\zeropoint
+ \advance\@@layerxpos-\@@layerxsiz
+ \@@layerxpos-\@@layerxpos
+ \fi}}%
+ \setbox\nextbox\hbox
+ {\alignedbox[\collectorparameter\c!location]\vbox{\flushnextbox}}%
+ \boxmaxdepth\zeropoint % really needed, nice example
+ \global\advance\boxhdisplacement\@@layerxpos
+ \ifdim\boxhdisplacement<\zeropoint
+ \global\setbox\collectorbox\hbox
+ {\hskip-\boxhdisplacement
+ \box\collectorbox}%
+ \fi
+ \global\advance\boxvdisplacement\@@layerypos
+ \ifdim\boxvdisplacement<\zeropoint
+ \global\setbox\collectorbox\hbox
+ {\lower-\boxvdisplacement
+ \box\collectorbox}%
+ \fi
+ \@@layerxsiz\wd\collectorbox
+ \@@layerysiz\ht\collectorbox
+ \advance\@@layerysiz\dp\collectorbox
+ \global\setbox\collectorbox\hbox
+ {\box\collectorbox
+ \hskip-\@@layerxsiz
+ \hskip\@@layerxpos\relax
+ \ifdim\boxhdisplacement<\zeropoint
+ \hskip-\boxhdisplacement
+ \fi
+ \lower\@@layerypos\hbox
+ {\ifdim\boxvdisplacement<\zeropoint
+ \lower-\boxvdisplacement\flushnextbox
+ \else
+ \flushnextbox
+ \fi}}%
+ % combine height and depth into depth only (later flushed as height)
+ \global\setbox\collectorbox\hbox
+ {\lower\ht\collectorbox\box\collectorbox}%
+ % just to be sure
+ \ifdim\wd\collectorbox<\@@layerxsiz
+ \global\wd\collectorbox\@@layerxsiz
+ \fi}
+
+\def\flushcollector[#1]%
+ {\ifcsname\@@collectorbox#1\endcsname
+ \doifnotvalue{\??cb#1\c!state}\v!stop
+ {\vbox
+ {\hbox
+ {\doifelsevalue{\??cb#1\c!state}\v!repeat
+ {\let\next\copy}{\let\next\box}%
+ \raise\dp\csname\@@collectorbox#1\endcsname
+ \next\csname\@@collectorbox#1\endcsname}}}%
+ \else
+ \writestatus{collector}{unknown collector #1}%
+ \fi}
+
+\def\composedcollector#1{\flushcollector[#1]}
+
+\def\resetcollector[#1]%
+ {\ifcsname\@@collectorbox#1\endcsname
+ \global\setbox\csname\@@collectorbox#1\endcsname\emptybox
+ \fi}
+
+\def\adaptcollector
+ {\dodoubleargument\doadaptcollector}
+
+\def\doadaptcollector[#1][#2]%
+ {\bgroup
+ \def\currentcollector{#1}%
+ \chardef\collectorbox\csname\@@collectorbox#1\endcsname
+ \getparameters[\??cb#1][\c!voffset=\zeropoint,\c!hoffset=\zeropoint,#2]%
+ \scratchdimen\wd\collectorbox
+ \advance\scratchdimen\collectorparameter\c!hoffset
+ \global\wd\collectorbox\scratchdimen
+ \scratchdimen\ht\collectorbox
+ \advance\scratchdimen\collectorparameter\c!voffset
+ \global\ht\collectorbox\scratchdimen
+ \egroup}
+
+%\definecollector[test]
+%\setcollector[test]
+% [location=rb]
+% {\externalfigure[koe][frame=on,width=3cm]}
+%\setcollector[test]
+% [corner={right,bottom},location={left,top}]
+% {\framed{gans}}
+%\composedcollector{test}
+
+\definecollector
+ [caption]
+
+\def\collectedtext
+ {\dodoubleempty\docollectedtext}
+
+\def\docollectedtext[#1][#2]#3%
+ {\bgroup
+ \dowithnextbox
+ {\setcollector
+ [caption]
+ {\flushnextbox}%
+ \setcollector
+ [caption][#1]
+ {\getparameters[\??du][#2]%
+ \dosetfontattribute\??du\c!style\setupinterlinespace
+ \framed % watch the special setting of kader/overlay
+ [\c!frame=\v!overlay,#2]
+ {\doattributes\??du\c!style\c!color{#3}}}%
+ \composedcollector{caption}%
+ \egroup}%
+ \hbox}
+
+% \collectedtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \collectedtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\definelayer
+ [caption]
+
+\def\layeredtext
+ {\dodoubleempty\dolayeredtext}
+
+\def\dolayeredtext[#1][#2]#3%
+ {\bgroup
+ \dowithnextbox
+ {\!!widtha \nextboxwd
+ \!!heighta\nextboxht
+ \bgroup % preserve \nextbox
+ \setuplayer
+ [caption]
+ [\c!width=\!!widtha,\c!height=\!!heighta]%
+ \setlayer
+ [caption]
+ [#1]
+ {\getparameters[\??du][#2]%
+ \dosetfontattribute\??du\c!style\setupinterlinespace
+ \framed
+ [\c!frame=\v!overlay,,#2]
+ {\doattributes\??du\c!style\c!color{#3}}}%
+ \egroup
+ \framed
+ [\c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!background={\v!foreground,caption},
+ \c!width=\!!widtha,
+ \c!height=\!!heighta]
+ {\flushnextbox}%
+ \egroup}%
+ \hbox}
+
+% \layeredtext
+% [corner={right,bottom},location={left,top}]
+% [background=color,backgroundcolor=white,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={right,bottom},location={right,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+%
+% \layeredtext
+% [rotation=90,corner={left,bottom},location={left,top}]
+% [frame=on,offset=0pt]
+% {gans}
+% {\externalfigure[koe][width=3cm]}
+
+\def\ornamenttext
+ {\dodoubleempty\doornamenttext}
+
+\def\doornamenttext[#1][#2]%
+ {\bgroup
+ \doifassignmentelse{#1}
+ {\getparameters[\s!dummy][\c!alternative=\v!a,#1]%
+ \doifelse\dummyalternative\v!a
+ {\egroup\collectedtext}%
+ {\egroup\layeredtext }%
+ [#1][#2]}%
+ {\egroup\getvalue{#1}}}
+
+\unexpanded\def\defineornament
+ {\dotripleempty\dodefineornament}
+
+\def\dodefineornament[#1][#2][#3]%
+ {\setvalue{#1}{\doornamenttext[#2][#3]}}
+
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={right,top},
+% hoffset=-.25ex,alternative=b]
+% [frame=on,background=color,backgroundcolor=red,offset=0pt]
+%
+% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=a]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{photo}{\externalfigure[molen][width=3cm]}
+%
+% \defineornament
+% [affiliation]
+% [rotation=90,corner={right,bottom},location={left,top},
+% hoffset=.25ex,voffset=.25ex,alternative=b]
+% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
+%
+% \affiliation{drawing}{\externalfigure[hakker][width=3cm]}
+
+% pas op: aanpassen aan nieuwe layer hoek ankers en columnset
+
+\newcount\nofbleeds % per pag
+
+\unexpanded\def\setupbleeding
+ {\dodoubleempty\getparameters[\??bg]}
+
+\setupbleeding
+ [\c!location=l,
+ \c!stretch=\v!yes,
+ \c!width=3cm,
+ \c!height=3cm,
+ \c!offset=2mm,
+ \c!page=\v!no,
+ \c!voffset=\@@bgoffset,
+ \c!hoffset=\@@bgoffset]
+
+\def\bleed
+ {\dosingleempty\dobleed}
+
+
+\def\bleedwidth {\the\hsize}%
+\def\bleedheight{\the\vsize}%
+
+\def\dobleed[#1]#2%
+ {\hbox\bgroup
+ \xdef\bleedwidth {\the\hsize}%
+ \xdef\bleedheight{\the\vsize}%
+ \global\advance\nofbleeds\plusone
+ \getparameters[\??bg][#1]%
+ \!!doneafalse % left
+ \!!donebfalse % right
+ \!!donecfalse % top
+ \!!donedfalse % bottom
+ % replace this part ! todo: default location
+ \processaction
+ [\@@bglocation]
+ [ t=>\!!donectrue\let\@@bghoffset\!!zeropoint,
+ b=>\!!donedtrue\let\@@bghoffset\!!zeropoint,
+ l=>\!!doneatrue\let\@@bgvoffset\!!zeropoint,
+ r=>\!!donebtrue\let\@@bgvoffset\!!zeropoint,
+ bl=>\!!doneatrue\!!donedtrue,
+ lb=>\!!doneatrue\!!donedtrue,
+ br=>\!!donebtrue\!!donedtrue,
+ rb=>\!!donebtrue\!!donedtrue,
+ tl=>\!!doneatrue\!!donectrue,
+ lt=>\!!doneatrue\!!donectrue,
+ tr=>\!!donebtrue\!!donectrue,
+ rt=>\!!donebtrue\!!donectrue]%
+ \doifelse\@@bgstretch\v!yes\donetrue\donefalse
+ \scratchdimen\@@bgwidth
+ \ifdone
+ \if!!donea
+ \advance\scratchdimen\MPx{\??bg:\number\nofbleeds}%
+ \else\if!!doneb
+ \scratchdimen\paperwidth
+ \advance\scratchdimen-\MPx{\??bg:\number\nofbleeds}%
+ \fi\fi
+ \fi
+ \advance\scratchdimen\@@bghoffset
+ \xdef\bleedwidth{\the\scratchdimen}%
+ \scratchdimen\@@bgheight
+ \ifdone
+ \if!!donec
+ \scratchdimen\paperheight
+ \advance\scratchdimen-\MPy{\??bg:\number\nofbleeds}%
+ \else\if!!doned
+ \advance\scratchdimen\MPy{\??bg:\number\nofbleeds}%
+ \fi\fi
+ \fi
+ \advance\scratchdimen\@@bgvoffset
+ \xdef\bleedheight{\the\scratchdimen}%
+ \hsize\bleedwidth
+ \vsize\bleedheight
+ \setbox\scratchbox\hbox{#2}%
+ \doif\@@bgpage\v!yes
+ {\setbox\scratchbox\topskippedbox{\box\scratchbox}}%
+ \setbox\scratchbox\hbox to \@@bgwidth
+ {\if!!donea\hss\fi\box\scratchbox\if!!doneb\hss\fi}%
+ \if!!doned
+ \setbox\scratchbox\hbox
+ {\lower\bleedheight\hbox{\raise\@@bgheight\box\scratchbox}}%
+ \fi
+ \wd\scratchbox\@@bgwidth
+ \ht\scratchbox\@@bgheight
+ \dp\scratchbox\zeropoint
+ \ifdone
+ \hpos{\??bg:\number\nofbleeds}{\box\scratchbox}%
+ \else
+ \box\scratchbox
+ \fi
+ \egroup}
+
+\setupbleeding[\c!stretch=\v!yes]
+
+\defineexternalfigure[bleed][\c!width=\bleedwidth,\c!height=\bleedheight]
+
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[left]{none}
+% {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure[right]{none}
+% {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}}
+%
+% \input tufte
+%
+% \placefigure
+% [top,none]
+% {} % no caption
+% {\bleed
+% [hoffset=-\backspace,
+% voffset=3mm,
+% width=0cm,
+% height=6\lineheight,
+% page=yes, % correct for topskip
+% location=lt]
+% {\externalfigure[koe][bleed][frame=on]}}
+
+% \setlayerframed[layer id][layer settings][framed setting]{data}
+% \setlayerframed[layer id][combined settings]{data}
+
+\def\setlayerframed
+ {\dotripleempty\dosetlayerframed}
+
+\def\dosetlayerframed
+ {\ifthirdargument
+ \expandafter\dosetlayerframedT
+ \else
+ \expandafter\dosetlayerframedS
+ \fi}
+
+\def\dosetlayerframedT[#1][#2][#3]%
+ {\dowithnextbox{\setlayer[#1][#2]{\flushnextbox}}%
+ \hbox\framed[#3]}
+
+\def\dosetlayerframedS[#1][#2][#3]%
+ {\dowithnextbox % we could use a local setlayer command (no doif..empty) which also saves a nextbox
+ {\setlayer[#1][\c!width=\nextboxwd,\c!height=\nextboxht,\c!offset=\!!zeropoint,#2]{\flushnextbox}}%
+ \hbox\framed[\c!location=\v!normal,#2]}
+
+\def\setlayertext
+ {\dotripleempty\dosetlayertext}
+
+\def\dosetlayertext[#1][#2][#3]%
+ {\bgroup
+ \getparameters
+ [\??lx]
+ [\c!align=,
+ \c!width=\hsize,
+ \c!color=,
+ \c!style=,
+ #3]%
+ \dowithnextboxcontent
+ {\forgetall
+ \hsize\@@lxwidth
+ \expanded{\setupalign[\@@lxalign]}%
+ \dosetfontattribute\??lx\c!style}
+ {\setlayer[#1][#2]{\strut\color[\@@lxcolor]{\flushnextbox}}%
+ \egroup}%
+ \vtop}
+
+% \setupbackgrounds
+% [page]
+% [background=pagefigures]
+%
+% \definelayer
+% [pagefigures]
+% [x=-2mm,
+% y=-2mm,
+% width=\paperwidth,
+% height=\paperheight]
+%
+% \definelayerpreset [lefttop] [corner={left,top},location={right,bottom}]
+% \definelayerpreset [righttop] [corner={right,top},location={left,bottom}]
+% \definelayerpreset [leftbottom] [corner={left,bottom},location={right,top}]
+% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}]
+% \definelayerpreset [middle] [corner=middle,location=middle]
+%
+% \setlayer[pagefigures][preset=lefttop]
+% \setlayer[pagefigures][preset=righttop]
+% \setlayer[pagefigures][preset=leftbottom]
+% \setlayer[pagefigures][preset=rightbottom]
+
+\definelayerpreset
+ [\v!left\v!top]
+ [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}]
+
+\definelayerpreset
+ [\v!right\v!top]
+ [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}]
+
+\definelayerpreset
+ [\v!left\v!bottom]
+ [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}]
+
+\definelayerpreset
+ [\v!right\v!bottom]
+ [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}]
+
+\definelayerpreset
+ [\v!middle]
+ [\c!corner=\v!middle,\c!location=\v!middle]
+
+% \definelayerpreset
+% [\v!middle\v!top]
+% [\c!location=\v!bottom,\c!hoffset=.5\layerwidth]
+
+% \definelayerpreset
+% [\v!middle\v!bottom]
+% [\c!location=\v!top,\c!hoffset=.5\layerwidth,\c!voffset=\layerheight]
+
+% \definelayerpreset
+% [\v!middle\v!left]
+% [\c!location=\v!right,\c!voffset=.5\layerheight]
+
+% \definelayerpreset
+% [\v!middle\v!right]
+% [\c!location=\v!left,\c!hoffset=\layerwidth,\c!voffset=.5\layerheight]
+
+\definelayerpreset
+ [\v!middle\v!top]
+ [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!bottom]
+ [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth]
+
+\definelayerpreset
+ [\v!middle\v!left]
+ [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight]
+
+\definelayerpreset
+ [\v!middle\v!right]
+ [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight]
+
+\def\alignedbox
+ {\dodoubleempty\doalignedbox[]}
+
+% \def\doalignedbox[#1][#2]%
+% {\bgroup
+% %\let\iftraceboxplacement\iftracelayers % ugly
+% \dowithnextbox
+% {\let\next\middlebox
+% \processaction
+% [#2]
+% [ t=>\let\next\topbox , b=>\let\next\bottombox ,
+% l=>\let\next\leftbox , r=>\let\next\rightbox ,
+% bl=>\let\next\bottomleftbox,br=>\let\next\bottomrightbox,
+% tl=>\let\next\topleftbox ,tr=>\let\next\toprightbox ,
+% lt=>\let\next\lefttopbox ,lb=>\let\next\leftbottombox ,
+% rt=>\let\next\righttopbox ,rb=>\let\next\rightbottombox]%
+% \next{\flushnextbox}%
+% \egroup}#1}
+
+\def\doalignedbox[#1][#2]%
+ {\bgroup
+ %\let\iftraceboxplacement\iftracelayers % ugly
+ \dowithnextbox
+ {\serializecommalist[#2]%
+ \executeifdefined{\??ab\??ab\serializedcommalist}\middlebox{\flushnextbox}%
+ \egroup}#1}
+
+\setvalue{\??ab\??ab }{\middlebox}
+\setvalue{\??ab\??ab\v!middle }{\middlebox}
+\setvalue{\??ab\??ab\v!left }{\leftbox }
+\setvalue{\??ab\??ab\v!right }{\rightbox }
+\setvalue{\??ab\??ab\v!bottom }{\bottombox}
+\setvalue{\??ab\??ab\v!top }{\topbox }
+
+\setvalue{\??ab\??ab\v!middle\v!middle}{\middlebox}
+\setvalue{\??ab\??ab\v!left \v!top }{\lefttopbox}
+\setvalue{\??ab\??ab\v!left \v!bottom}{\leftbottombox}
+\setvalue{\??ab\??ab\v!right \v!top }{\righttopbox}
+\setvalue{\??ab\??ab\v!right \v!bottom}{\rightbottombox}
+\setvalue{\??ab\??ab\v!top \v!left }{\topleftbox}
+\setvalue{\??ab\??ab\v!bottom\v!left }{\bottomleftbox}
+\setvalue{\??ab\??ab\v!top \v!right }{\toprightbox}
+\setvalue{\??ab\??ab\v!bottom\v!right }{\bottomrightbox}
+
+\setvalue{\??ab\??ab c}{\middlebox}
+\setvalue{\??ab\??ab l}{\leftbox}
+\setvalue{\??ab\??ab r}{\rightbox}
+\setvalue{\??ab\??ab b}{\bottombox}
+\setvalue{\??ab\??ab t}{\topbox}
+
+\setvalue{\??ab\??ab lt}{\lefttopbox}
+\setvalue{\??ab\??ab lb}{\leftbottombox}
+\setvalue{\??ab\??ab rt}{\righttopbox}
+\setvalue{\??ab\??ab rb}{\rightbottombox}
+\setvalue{\??ab\??ab tl}{\topleftbox}
+\setvalue{\??ab\??ab bl}{\bottomleftbox}
+\setvalue{\??ab\??ab tr}{\toprightbox}
+\setvalue{\??ab\??ab br}{\bottomrightbox}
+
+\setvalue{\??ab\??ab m}{\middlebox}
+
+% The next ones were desparately needed by Vit Zyka (see
+% \type {supp-box} for definitions).
+
+\setvalue{\??ab\??ab g}{\baselinemiddlebox}
+\setvalue{\??ab\??ab gl}{\baselineleftbox}
+\setvalue{\??ab\??ab gc}{\baselinemiddlebox}
+\setvalue{\??ab\??ab gr}{\baselinerightbox}
+
+\setvalue{\??ab\??ab \v!line }{\baselinemiddlebox} % \v!grid is taken
+\setvalue{\??ab\??ab \v!line\v!left }{\baselineleftbox}
+\setvalue{\??ab\??ab \v!line\v!middle}{\baselinemiddlebox}
+\setvalue{\??ab\??ab \v!line\v!right }{\baselinerightbox}
+
+\unexpanded\def\offsetbox
+ {\dodoubleempty\dooffsetbox[]}
+
+% left/right/top/bottomoffset -> dimensions change
+% x/y | method=fixed -> dimensions don't change
+
+\def\dooffsetbox[#1][#2]%
+ {\bgroup
+ \dowithnextbox
+ {\getparameters[\??ox]
+ [\c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!width=\nextboxwd,
+ \c!height=\nextboxht,
+ \c!depth=\nextboxdp,
+ \c!location=,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!method=,
+ #2]%
+ \donefalse
+ \ifdim\@@oxleftoffset =\zeropoint\else\donetrue\fi
+ \ifdim\@@oxrightoffset=\zeropoint\else\donetrue\fi
+ \ifdim\@@oxtopoffset =\zeropoint\else\donetrue\fi
+ \ifdim\@@oxbottomoffset =\zeropoint\else\donetrue\fi
+ \ifdone
+ \doif\@@oxmethod\v!fixed % new
+ {\ifdim\@@oxleftoffset=\zeropoint
+ \ifdim\@@oxrightoffset=\zeropoint \else
+ \scratchdimen-\@@oxrightoffset
+ \edef\@@oxx{\the\scratchdimen}%
+ \let\@@oxrightoffset\zeropoint
+ \fi
+ \else
+ \let\@@oxx\@@oxleftoffset
+ \let\@@oxleftoffset\zeropoint
+ \fi
+ \ifdim\@@oxtopoffset=\zeropoint
+ \ifdim\@@oxbottomoffset=\zeropoint \else
+ \scratchdimen-\@@oxbottomoffset
+ \edef\@@oxy{\the\scratchdimen}%
+ \let\@@oxbottomoffset\zeropoint
+ \fi
+ \else
+ \let\@@oxy\@@oxtopoffset
+ \let\@@oxtopoffset\zeropoint
+ \fi
+ \donefalse}%
+ \fi
+ \ifdone
+ \setbox\nextbox\vbox
+ {\forgetall\offinterlineskip
+ \vskip\@@oxtopoffset
+ \hbox
+ {\hskip\@@oxleftoffset
+ \flushnextbox
+ \hskip\@@oxrightoffset}%
+ \vskip\@@oxbottomoffset}%
+ \scratchdimen\nextboxht
+ \advance\scratchdimen\nextboxdp
+ \nextboxht\scratchdimen
+ \nextboxdp\zeropoint
+ \fi
+ \freezedimenmacro\@@oxwidth
+ \freezedimenmacro\@@oxheight
+ \freezedimenmacro\@@oxdepth
+ \setbox\nextbox\hbox
+ {\hskip\@@oxx\lower\@@oxy\hbox
+ {\doifelsenothing\@@oxlocation
+ {\flushnextbox}
+ {\alignedbox[\@@oxlocation]\hbox{\flushnextbox}}}}%
+ \nextboxwd\@@oxwidth
+ \nextboxht\@@oxheight
+ \nextboxdp\@@oxdepth
+ \flushnextbox
+ \egroup}#1}
+
+% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
+%
+% \placefigure[left,none]{}{\offset[leftoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+% \placefigure[left,none]{}{\offset[rightoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+% \placefigure[left,none]{}{\offset[topoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
+% \input tufte
+
+\unexpanded\def\offset {\dodoubleempty\dooffsetbox [\hbox]} % yes or no
+\unexpanded\def\aligned{\dosingleempty\doalignedbox[\hbox]} % yes or no
+
+%\ruledhbox{\offsetbox[x=-1cm,y=-1cm,location=c]
+% {\framed[width=4cm,height=4cm]{x}}}
+
+\def\dotabbed#1#2#3#4%
+ {\dontleavehmode
+ \bgroup
+ \setbox\scratchbox\hbox{#3}%
+ \hbox to \wd\scratchbox{#1#4#2}%
+ \egroup}
+
+\unexpanded\def\ltabbed{\dotabbed\relax\hss}
+\unexpanded\def\rtabbed{\dotabbed\hss \relax}
+\unexpanded\def\ctabbed{\dotabbed\hss \hss} \let\mtabbed\ctabbed
+
+% \ltabbed{\romeins{3}}{\romeins{1}} test \endgraf
+% \ltabbed{\romeins{3}}{\romeins{2}} test \endgraf
+% \ltabbed{\romeins{3}}{\romeins{3}} test \endgraf
+%
+% \rtabbed{\romeins{3}}{\romeins{1}} test \endgraf
+% \rtabbed{\romeins{3}}{\romeins{2}} test \endgraf
+% \rtabbed{\romeins{3}}{\romeins{3}} test \endgraf
+%
+% \ctabbed{\romeins{3}}{\romeins{1}} test \endgraf
+% \ctabbed{\romeins{3}}{\romeins{2}} test \endgraf
+% \ctabbed{\romeins{3}}{\romeins{3}} test \endgraf
+
+% alternative, if done, then other name
+%
+% \def\dotabbed#1#2#3#4%
+% {\dontleavehmode
+% \bgroup
+% \scratchdimen\zeropoint
+% \def\docommand##1%
+% {\setbox\scratchbox\hbox{##1}%
+% \ifdim\wd\scratchbox>\scratchdimen
+% \scratchdimen\wd\scratchbox
+% \fi}%
+% \processcommalist[#3]\docommand
+% \hbox to \scratchdimen{#1#4#2}%
+% \egroup}
+%
+% \def\ltabbed{\dotabbed\relax\hss}
+% \def\rtabbed{\dotabbed\hss \relax}
+% \def\ctabbed{\dotabbed\hss \hss} \let\mtabbed\ctabbed
+%
+% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
+% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
+% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
+%
+% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
+% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
+% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
+%
+% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
+% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
+% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
+
+% to be documented
+
+\unexpanded\def\phantombox[#1]%
+ {\hbox\bgroup
+ \getparameters
+ [\??ol]
+ [\c!width=\zeropoint,%
+ \c!height=\zeropoint,%
+ \c!depth=\zeropoint,#1]%
+ \setbox\scratchbox\null
+ \wd\scratchbox\@@olwidth
+ \ht\scratchbox\@@olheight
+ \dp\scratchbox\@@oldepth
+ \box\scratchbox
+ \egroup}
+
+% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
+
+\unexpanded\def\backgroundimage#1#2#3% repeat hsize vsize
+ {\bgroup
+ \forgetall
+ \dowithnextbox
+ {\offinterlineskip
+ \ifcase#1\relax
+ % just one
+ \else
+ \scratchdimen#2\divide\scratchdimen\nextboxwd\count0\scratchdimen\advance\count0\plusone
+ \scratchdimen#3\divide\scratchdimen\nextboxht\count2\scratchdimen\advance\count2\plusone
+ % to be considered, probably methods
+ \ifcase#1\or % x and y
+ \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
+ \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
+ \or % x
+ \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
+ \or % y
+ \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
+ \fi
+ \fi
+ \ifdim\nextboxwd>#2\relax
+ \setbox\nextbox\hbox to #2{\hss\flushnextbox\hss}%
+ \setbox\nextbox\hbox{\expanded{\clip[\c!width=#2,\c!height=\the\nextboxht]{\flushnextbox}}}%
+ \fi
+ \ifdim\nextboxht>#3\relax
+ \setbox\nextbox\vbox to #3{\vss\flushnextbox\vss}%
+ \setbox\nextbox\hbox{\expanded{\clip[\c!width=\the\nextboxwd,\c!height=#3]{\flushnextbox}}}%
+ \fi
+ \flushnextbox
+ \egroup}%
+ \hbox}
+
+\protect \endinput
diff --git a/tex/context/base/pack-lyr.mkii b/tex/context/base/pack-lyr.mkii
new file mode 100644
index 000000000..85549bccb
--- /dev/null
+++ b/tex/context/base/pack-lyr.mkii
@@ -0,0 +1,755 @@
+%D \module
+%D [ file=pack-lyr,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Layers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Layers}
+
+%D This module is now etex dependent.
+
+% todo : first / last / next / +... => page key
+% test on left/right box when no doublesided option given
+% use \ifcsname instead of doifvalue
+
+\unprotect
+
+% When being backgrounds layers get the background offset
+% displacement. Should be an option, on by default
+% (compatibility).
+
+% positie=forceer == ja maar dan ook in status=herhaal
+
+%D The layering mechanism implemented here is independent of
+%D the output routine, but future extensions may depend on a
+%D more close cooperation.
+
+%D First we overload a macro from \type {core-rul}. From now on
+%D we accept a (optional) argument: the specific layer it
+%D will go in. This means that we can move an overlay from one
+%D background to the other using the dimensions of the parent.
+
+%D ! ! ! ! to be documented ! ! ! !
+
+\ifx\undefined\defineoverlay \message{loaded to early} \wait \fi
+
+\def\defineoverlay
+ {\dotripleempty\dodefineoverlay}
+
+\def\dodefineoverlay[#1][#2][#3]% overlay [layer] content
+ {\ifthirdargument
+ \writestatus{BEWARE}{This (overlay definition) has changed!}% temp
+ \def\docommand##1{\setvalue{\??ov##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}
+ \else
+ \def\docommand##1{\setvalue{\??ov##1}{\executedefinedoverlay{##1}{#2}}}%
+ \fi
+ \processcommalist[#1]\docommand}
+
+%D When tracing is turned on, a couple of boxes will
+%D show up as well as the reference point.
+
+\newif\iftracelayers % \tracelayerstrue
+
+%D This handy constant saved some string memory.
+
+\def\@@layerbox{@@layerbox}
+
+%D \macros
+%D {definelayer}
+%D
+%D Each layer gets its own (global) box. This also means that
+%D the data that goes into a layer, is typeset immediately.
+%D Each layer automatically gets an associated overlay,
+%D which can be used in any background assignment.
+
+% todo : links/rechts
+
+\def\definelayer
+ {\dodoubleargument\dodefinelayer}
+
+\def\dodefinelayer[#1][#2]% \zeropoint ipv \!!zeropoint
+ {\setuplayer
+ [#1]
+ [\c!doublesided=,\c!preset=,
+ \c!state=\v!start,\c!direction=\v!normal,\c!option=,
+ \c!x=\zeropoint,\c!y=\zeropoint,\c!position=\v!no,
+ \c!line=0,\c!column=0,
+ \c!width=\nextboxwd,\c!height=\nextboxht,
+ \c!offset=\zeropoint,\c!rotation=, % geen 0 !
+ \c!hoffset=\zeropoint,\c!voffset=\zeropoint,
+ \c!dx=\zeropoint,\c!dy=\zeropoint,
+ \c!location=rb,\c!position=\v!no,\c!page=,
+ \c!method=\v!overlay,
+ \c!sx=1,\c!sy=1,\c!corner=,#2]%
+ \doifvalue{\??ll#1\c!doublesided}\v!yes
+ {\dopresetlayerbox{\v!left #1}%
+ \dopresetlayerbox{\v!right#1}}%
+ \dopresetlayerbox{#1}%
+ \defineoverlay[#1][\composedlayer{#1}]}
+
+\def\dopresetlayerbox#1%
+ {\ifundefined{\@@layerbox#1}%
+ \expandafter\newbox\csname\@@layerbox#1\endcsname
+ \else
+ \resetlayer[#1]%
+ \fi}
+
+%D \macros
+%D {setuplayer}
+%D
+%D After a layer is defined, you can change its
+%D characteristics.
+
+\def\setuplayer
+ {\dodoubleargument\dosetuplayer}
+
+\def\dosetuplayer[#1][#2]%
+ {\def\docommand##1{\getparameters[\??ll##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+%D \macros
+%D {setlayer}
+%D
+%D Data is moved into a layer with the following macro. When
+%D \type {position} is set, relative positioning is used, with
+%D the current point as reference point. Otherwise the topleft
+%D corner is used as reference point.
+%D
+%D \starttyping
+%D \setlayer [identifier] [optional parameters] {data}
+%D \stoptyping
+
+\newcount\currentlayerdata
+
+\let\currentlayerwidth \!!zeropoint
+\let\currentlayerheight\!!zeropoint
+
+\def\setcurrentlayerdimensions
+ {\dodoubleempty\dosetcurrentlayerdimensions}
+
+\def\dosetcurrentlayerdimensions[#1][#2]% name left|right
+ {\edef\currentlayerwidth {\thelayerwidth {#2#1}}%
+ \edef\currentlayerheight{\thelayerheight{#2#1}}}
+
+\def\thelayerwidth #1{\the\wd\executeifdefined{\@@layerbox#1}\emptybox}
+\def\thelayerheight#1{\the\ht\executeifdefined{\@@layerbox#1}\emptybox}
+
+\def\setlayer
+ {\dotripleempty\dosetlayer}
+
+\def\dosetlayer[#1][#2][#3]% #4 == box do \fi is ok
+ {\doifelsevalue{\??ll#1\c!state}\v!stop
+ {\dowithnextbox\donothing\hbox}
+ {\ifthirdargument
+ \dodosetlayer[#1][#2][#3]%
+ \else
+ \doifassignmentelse{#2}
+ {\dodosetlayer[#1][][#2]}%
+ {\dodosetlayer[#1][#2][]}%
+ \fi}}
+
+\def\dodosetlayer[#1][#2][#3]% #2 = links/rechts
+ {\bgroup
+ \recalculatebackgrounds
+ \recalculatelogos
+ \global\advance\currentlayerdata\plusone
+ \forgetall
+ \dontcomplain
+ \doifvalue{\??ll#1\c!option}\v!test\tracelayerstrue
+ \iftracelayers\traceboxplacementtrue\fi
+ \dowithnextbox % sneller als aparte macro
+ {\ifcsname\@@layerbox#1\endcsname % nb: odd/even discard, left/right not
+ \edef\@@layerloc{#2}%
+ \ifx\@@layerloc\v!even
+ \ifodd\realpageno
+ % discard nextbox
+ \else
+ \dododosetlayer[#1][\v!left][#3]%
+ \fi
+ \else\ifx\@@layerloc\v!odd
+ \ifodd\realpageno
+ \dododosetlayer[#1][\v!right][#3]%
+ %\else
+ % discard nextbox
+ \fi
+ \else
+ \dododosetlayer[#1][#2][#3]%
+ \fi\fi
+ \else
+ \writestatus{layer}{unknown layer #1}%
+ \fi
+ \egroup}%
+ \hbox}
+
+\newbox\layerbox
+
+\newdimen\@@layerxsiz
+\newdimen\@@layerysiz
+\newdimen\@@layerxoff
+\newdimen\@@layeryoff
+\newdimen\@@layerxpos
+\newdimen\@@layerypos
+
+\let\lastlayerxpos\!!zeropoint
+\let\lastlayerypos\!!zeropoint
+\let\lastlayerwd \!!zeropoint
+\let\lastlayerht \!!zeropoint
+\let\lastlayerdp \!!zeropoint
+
+% todo left/right
+
+\def\setlastlayerpos#1%
+ {\edef\layerpage{\MPp{lyr:\the\currentlayerdata}}%
+ \xdef\lastlayerxpos{\the\dimexpr-\MPx{lyr:#1:\layerpage}+\MPx{lyr:\the\currentlayerdata}\relax}%
+ \xdef\lastlayerypos{\the\dimexpr \MPy{lyr:#1:\layerpage}-\MPy{lyr:\the\currentlayerdata}\relax}}
+
+\def\definelayerpreset
+ {\dodoubleargument\dodefinelayerpreset}
+
+% \def\dodefinelayerpreset[#1][#2]%
+% {\setvalue{\??ll\??ll#1}{\dopresetlayer{#2}}}
+%
+% more fun: \definelayerpreset[whatever][lefttop]
+
+\def\dodefinelayerpreset[#1][#2]%
+ {\doifassignmentelse{#2}
+ {\setvalue{\??ll\??ll#1}{\dopresetlayer{#2}}}
+ {\setvalue{\??ll\??ll#1}{\getvalue{\??ll\??ll#2}}}}
+
+\def\dopresetlayer#1#2#3% #1=list #2=tag #3=list
+ {\getparameters[\??ll#2][#1,#3]}
+
+\letempty\currentlayer
+
+\def\layerparameter#1{\csname\??ll\currentlayer#1\endcsname}
+
+\newdimen\layerwidth
+\newdimen\layerheight
+
+\chardef\@@lacome=1 % LAyerCOnstructionMEthod / temp, will be default
+
+\def\dododosetlayer[#1][#2][#3]% will be sped up
+ {% we use the global width, never change this
+ \def\currentlayer{#1}%
+ \@@layerxsiz\layerparameter\c!width
+ \@@layerysiz\layerparameter\c!height
+ \layerwidth \@@layerxsiz
+ \layerheight\@@layerysiz
+ % preroll
+ \getparameters[\??ll\currentlayer][#3]%
+ % presets and real roll
+% maybe todo:
+% \doif{\layerparameter\c!method}\v!fit
+% {\@@layerxsiz\thelayerwidth \currentlayer
+% \@@layerysiz\thelayerheight\currentlayer
+% \layerwidth \@@layerxsiz
+% \layerheight\@@layerysiz
+% }%
+ % etc
+ \executeifdefined{\??ll\??ll\layerparameter\c!preset}\gobbletwoarguments\currentlayer{#3}%
+ % that was real slow
+ \doif{\layerparameter\c!position}\v!overlay % slow, use \dosetvalue instead
+ {\getparameters[\??ll\currentlayer][\c!width=\zeropoint,\c!height=\zeropoint,\c!position=\v!yes]}%
+ \doifsomething{\layerparameter\c!rotation}
+ {\setbox\nextbox\hbox
+ {\rotate % to be checked with new rotation
+ [\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]
+ {\flushnextbox}}}%
+ % no, not local
+ % \@@layerxsiz\layerparameter\c!width
+ % \@@layerysiz\layerparameter\c!height
+ % never change that
+ \@@layerxpos\layerparameter\c!x
+ \@@layerypos\layerparameter\c!y
+ \doifelse{\layerparameter\c!hoffset}\v!max
+ {\@@layerxoff\@@layerxsiz}{\@@layerxoff\layerparameter\c!hoffset}%
+ \doifelse{\layerparameter\c!voffset}\v!max
+ {\@@layeryoff\@@layerysiz}{\@@layeryoff\layerparameter\c!voffset}%
+ % dx/dy are internal context ones and can be used in preset
+ \advance\@@layerxoff\dimexpr\layerparameter\c!offset+\layerparameter\c!dx\relax
+ \advance\@@layeryoff\dimexpr\layerparameter\c!offset+\layerparameter\c!dy\relax
+ \@@layerxpos\layerparameter\c!sx\@@layerxpos
+ \@@layerypos\layerparameter\c!sy\@@layerypos
+ \@@layerxoff\layerparameter\c!sx\@@layerxoff
+ \@@layeryoff\layerparameter\c!sy\@@layeryoff
+ \doifelse{\layerparameter\c!position}\v!yes % combine ^
+ {\setlastlayerpos{#2\currentlayer}% todo l/r %%%%%%%%%%%%
+ \@@layerxpos\lastlayerxpos
+ \@@layerypos\lastlayerypos
+ \letgvalue{\??ll\currentlayer\layerpage\c!position}\v!yes
+ \letgvalue{\??ll\currentlayer\c!state}\v!start % needed ?
+ \setbox\layerbox\vbox to \@@layerysiz
+ {\hbox to \@@layerxsiz{\xypos{lyr:\the\currentlayerdata}\hss}\vss}}
+ {\setbox\layerbox\emptybox
+ \globallet\lastlayerxpos\!!zeropoint
+ \globallet\lastlayerypos\!!zeropoint
+ \ExpandBothAfter\doifinset\v!bottom{\layerparameter\c!corner}
+ {\ifnum\layerparameter\c!line=\zerocount\else % can be < 0
+ \setevalue{\??ll\currentlayer\c!line}%
+ {\the\numexpr-\layerparameter\c!line+\layoutlines+\plusone\relax}%
+ \fi
+ \ifdim\@@layerysiz>\zeropoint
+ \advance\@@layerypos-\@@layerysiz
+ \@@layerypos-\@@layerypos
+ \@@layeryoff-\@@layeryoff
+ \fi}%
+ \ExpandBothAfter\doifinset\v!right{\layerparameter\c!corner}
+ {\ifnum\layerparameter\c!column=\zerocount\else % can be < 0
+ \setevalue{\??ll\currentlayer\c!column}%
+ {\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}%
+ \fi
+ \ifdim\@@layerxsiz>\zeropoint
+ \advance\@@layerxpos-\@@layerxsiz
+ \@@layerxpos-\@@layerxpos
+ \@@layerxoff-\@@layerxoff
+ \fi}%
+ \ExpandBothAfter\doif\v!middle{\layerparameter\c!corner}
+ {\ifdim\@@layerxsiz>\zeropoint \advance\@@layerxpos.5\@@layerxsiz \fi
+ \ifdim\@@layerysiz>\zeropoint \advance\@@layerypos.5\@@layerysiz \fi}%
+ \edef\layerpage{\layerparameter\c!page}}%
+ \doifsomething\layerpage
+ {\edef\layerpage{:\layerpage}%
+ \doifundefined{\@@layerbox#2\currentlayer\layerpage}
+ {\global\expandafter\newbox\csname\@@layerbox#2\currentlayer\layerpage\endcsname}}%
+ \dontcomplain % more comfortable
+ \mathchardef\layerpagebox\csname\@@layerbox#2\currentlayer\layerpage\endcsname
+ \ifvoid\layerpagebox
+ \gsetboxllx\layerpagebox\zeropoint
+ \gsetboxlly\layerpagebox\zeropoint
+ \fi
+ \global\setbox\layerpagebox\vbox %to \layerparameter\c!height % new, otherwise no negative y possible
+ {\offinterlineskip
+ %postpone, to after nextboxwd correction % \hsize\layerparameter\c!width % new, keep box small
+ %\ifvoid\csname\@@layerbox\currentlayer\layerpage\endcsname\else % why not #2#1
+ \ifvoid\layerpagebox
+ \let\lastlayerwidth \zeropoint
+ \let\lastlayerheight\zeropoint
+ \else
+ \edef\lastlayerwidth {\the\wd\layerpagebox}%
+ \edef\lastlayerheight{\the\ht\layerpagebox}%
+ \ht\layerpagebox\zeropoint
+ \dp\layerpagebox\zeropoint
+ \wd\layerpagebox\zeropoint
+ \doifnot{\layerparameter\c!direction}\v!reverse{\box\layerpagebox}%
+ \fi
+ % don't move
+ \xdef\lastlayerwd{\the\nextboxwd}%
+ \xdef\lastlayerht{\the\nextboxht}% % not entirely ok when grid !
+ \xdef\lastlayerdp{\the\nextboxdp}% % not entirely ok when grid !
+ % this code
+ \doifelse{\layerparameter\c!location}\v!grid\donetrue\donefalse
+ \ifdone
+ \nextboxht\strutheight
+ \nextboxdp\strutdepth
+ \else
+ \setbox\nextbox\hbox{\alignedbox[\layerparameter\c!location]\vbox{\flushnextbox}}%
+ \fi
+ \ifnum\layerparameter\c!line=\zerocount\else % no \ifcase, can be negative
+ \advance\@@layerypos\dimexpr\layerparameter\c!line\lineheight+\topskip-\lineheight-\nextboxht\relax
+ \fi
+ \ifnum\layerparameter\c!column=\zerocount\else % no \ifcase, can be negative
+ \advance\@@layerxpos\layoutcolumnoffset{\layerparameter\c!column}%
+ \fi
+ \ifdone
+ \setbox\nextbox\hbox{\alignedbox[rb]\vbox{\flushnextbox}}%
+ \fi
+ % ll registration
+ \scratchdimen\@@layerxpos
+ \advance\scratchdimen\@@layerxoff
+ \ifdim\scratchdimen<\getboxllx\layerpagebox
+ \gsetboxllx\layerpagebox\scratchdimen
+ \fi
+ \ifcase\@@lacome\or % this test will become obsolete
+ \advance\scratchdimen\nextboxwd
+ \nextboxwd\ifdim\scratchdimen>\lastlayerwidth \scratchdimen \else \lastlayerwidth \fi
+ \fi
+ \scratchdimen\@@layerypos
+ \advance\scratchdimen\@@layeryoff
+ \ifdim\scratchdimen<\getboxlly\layerpagebox
+ \gsetboxlly\layerpagebox\scratchdimen
+ \fi
+ % ll compensation
+ \ifcase\@@lacome\or % this test will become obsolete
+ \advance\scratchdimen\dimexpr\nextboxht+\nextboxdp\relax
+ \nextboxht\ifdim\scratchdimen>\lastlayerheight \scratchdimen \else \lastlayerheight \fi
+ \nextboxdp\zeropoint
+ \fi
+ % placement
+ \hsize\layerparameter\c!width % new, keep box small
+ \vbox to \layerparameter\c!height \bgroup
+ \smashbox\nextbox
+ \vskip\dimexpr\@@layerypos+\@@layeryoff\relax
+ \hskip\dimexpr\@@layerxpos+\@@layerxoff\relax
+ \flushnextbox
+ \ifvoid\layerpagebox
+ % already flushed
+ \else
+ % the reverse case % check !
+ \vskip-\dimexpr\@@layerypos+\@@layeryoff\relax
+ \box\layerpagebox
+ \fi
+ \egroup}%
+ % when position is true, the layerbox holds the compensation and needs
+ % to be placed; never change this !
+ \ifvoid\layerbox\else\box\layerbox\fi}
+
+%D Given the task to be accomplished, the previous macro is
+%D not even that complicated. It mainly comes down to skipping
+%D to the right place and placing a box on top of or below the
+%D existing content. In the case of position tracking, another
+%D reference point is chosen.
+
+%D \macros
+%D {doifelselayerdata}
+%D
+
+\def\doifelselayerdata#1%
+ {\ifundefined{\@@layerbox#1}%
+ \@EA\secondoftwoarguments
+ \else\ifvoid\csname\@@layerbox#1\endcsname
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi\fi}
+
+%D \macros
+%D {flushlayer}
+%D
+%D When we flush a layer, we flush both the main one and the
+%D page dependent one (when defined). This feature is more
+%D efficient in \ETEX\ since there testing for an undefined
+%D macro does not takes hash space.
+
+% todo: setups before flush, handy hook
+
+\unexpanded\def\flushlayer[#1]%
+ {\doifelsevalue{\??ll#1\c!state}\v!next
+ {\global\letvalue{\??ll#1\c!state}\v!start} % dangerous, stack-built-up
+ {\doifelsevalue{\??ll#1\c!state}\v!continue
+ {\global\letvalue{\??ll#1\c!state}\v!repeat} % dangerous, stack-built-up
+ {\doifelsevalue{\??ll#1\c!doublesided}\v!yes
+ {\doifundefinedelse{\@@layerbox#1}%
+ {\dodoflushlayerA[#1]}
+ {\doifbothsidesoverruled
+ {\dodoflushlayerB\v!left [#1]}% left
+ {\dodoflushlayerB\v!right[#1]}% right
+ {\dodoflushlayerB\v!left [#1]}}}% left
+ {\dodoflushlayerA[#1]}}}}
+
+\def\dodoflushlayerA[#1]%
+ {\doifnotvalue{\??ll#1\c!state}\v!stop
+ {\startoverlay
+ {\dodoflushlayer1{#1}{#1}}
+ {\dodoflushlayer0{#1}{#1:\realfolio}}
+ \stopoverlay}}
+
+\def\dodoflushlayerB#1[#2]%
+ {\doifnotvalue{\??ll#2\c!state}\v!stop
+ {\startoverlay
+ {\dodoflushlayer1{#2}{#2}}
+ {\dodoflushlayer0{#2}{#2:\realfolio}}
+ {\dodoflushlayer1{#2}{#1#2}}
+ {\dodoflushlayer0{#2}{#1#2:\realfolio}}
+ \stopoverlay}}
+
+\def\dodoflushlayer#1#2#3%
+ {\ifundefined{\@@layerbox#3}%
+ \ifcase#1\else\writestatus{layer}{unknown layer #3}\fi
+ \else
+ \bgroup
+ \forgetall
+ \offinterlineskip
+ % needed because we need to handle method
+ \executeifdefined{\??ll\??ll\getvalue{\??ll#2\c!preset}}\gobbletwoarguments{#2}{}%
+ %
+ \doifvalue{\??ll#2\c!option}\v!test\tracelayerstrue
+ \iftracelayers\traceboxplacementtrue\fi
+ \!!doneafalse
+ \!!donebfalse
+ \doifvalue{\??ll#2\c!method}\v!overlay\!!doneatrue
+ \doifvalue{\??ll#2\c!method}\v!fit\!!donebtrue
+ \!!donectrue
+ \ifcase#1\else
+ \doifnotvalue{\??ll#2\c!position}\v!yes
+ {\doifvalue{\??ll#2\c!repeat}\v!yes\!!donecfalse
+ \doifvalue{\??ll#2\c!state}\v!repeat\!!donecfalse}%
+ \fi
+ \mathchardef\layerbox\csname\@@layerbox#3\endcsname
+ % we need to copy in order to retain the negative offsets for a next
+ % stage of additions, i.e. llx/lly accumulate in repeat mode and the
+ % compensation may differ each flush depending on added content
+ \setbox\nextbox \if!!doneb
+% \vbox
+% {\scratchdimen\getboxlly\layerbox
+% \vskip-\scratchdimen
+% \scratchdimen\getboxllx\layerbox
+% \hskip-\scratchdimen
+% \advance\scratchdimen-\wd\layerbox
+% \hsize-\scratchdimen
+% \if!!donec\box\else\copy\fi\layerbox}%
+ \vbox
+ {\vskip-\getboxlly\layerbox
+ \hskip-\getboxllx\layerbox
+ \hsize-\dimexpr\getboxllx\layerbox-\wd\layerbox\relax
+ \if!!donec\box\else\copy\fi\layerbox}%
+ \else
+ \if!!donec\box\else\copy\fi\layerbox % sorry for the delay due to copying
+ \fi
+ % todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
+ \iftracelayers \ruledvbox \else \vbox \fi \if!!donea to \overlayheight \fi
+ {\hbox \if!!donea to \overlaywidth \fi
+ {% klopt dit? #3 en niet #2 ?
+ \doifvalue{\??ll#3\realfolio\c!position}\v!yes{\xypos{lyr:#3:\realfolio}}%
+ \doifoverlayelse{#3}
+ {\box\nextbox}
+ {\startlayoutcomponent{l:#3}{layer #3}\box\nextbox\stoplayoutcomponent}%
+ \hss}%
+ \vss}%
+ \if!!donec
+ \gsetboxllx\layerbox\zeropoint
+ \gsetboxlly\layerbox\zeropoint
+ \fi
+ \egroup
+ \fi}
+
+% \definelayer[test][method=fit] \setupcolors[state=start] \tracelayerstrue
+%
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=10pt]{g}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=-10pt]{bb}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test][x=-20pt]{cccccc}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{dd}\setlayer[test][x=-20pt,y=-3pt]{eeeeee}\flushlayer[test]}
+
+%D \macros
+%D {composedlayer,placelayer,tightlayer}
+%D
+%D This is a handy shortcut, which saves a couple of braces
+%D when we use it as parameter. This name also suits better
+%D to other layering commands.
+
+\def\composedlayer#1{\flushlayer[#1]}
+
+\let\placelayer\flushlayer
+
+\def\tightlayer[#1]%
+ {\hbox
+ {\def\currentlayer{#1}% todo: left/right
+ \setbox\nextbox\emptybox % hoogte/breedte are \wd\nextbox/\ht\nextbox
+ \hsize\layerparameter\c!width % \overlaywidth = \hsize
+ \vsize\layerparameter\c!height % \overlaywheight = \vsize
+ \composedlayer{#1}}}
+
+%D \macros
+%D {resetlayer}
+%D
+%D This macro hardly needs an explanation (and is seldom
+%D needed as well).
+
+\def\doresetlayer#1%
+ {\ifundefined{\@@layerbox#1}\else
+ \global\setbox\csname\@@layerbox#1\endcsname\emptybox
+ \fi}
+
+\def\resetlayer[#1]%
+ {\doresetlayer{#1}%
+ \doifvalue{\??ll#1\c!doublesided}\v!yes % kind of redundant test
+ {\doresetlayer{\v!left #1}%
+ \doresetlayer{\v!right#1}}%
+ \doresetlayer{#1:\realfolio}}
+
+%D \macros
+%D {setMPlayer}
+%D
+%D The following layer macro uses the positions that are
+%D registered by \METAPOST.
+%D
+%D \starttyping
+%D \definelayer[test]
+%D
+%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
+%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
+%D \setMPlayer [test] [somepos-3] {\externalfigure[cow.mps][width=2cm]}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 10cm withcolor red ;
+%D register ("somepos-1",2cm,3cm,center currentpicture) ;
+%D register ("somepos-2",8cm,5cm,(-1cm,-2cm)) ;
+%D register ("somepos-3",0cm,0cm,(-2cm,2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \getMPlayer[test]{\useMPgraphic{oeps}}
+%D \stoptyping
+%D
+%D The last line is equivalent to
+%D
+%D \starttyping
+%D \framed
+%D [background={foreground,test},offset=overlay]
+%D {\useMPgraphic{oeps}}
+%D \stoptyping
+
+\def\setMPlayer
+ {\dotripleempty\dosetMPlayer}
+
+\def\MPlayerwidth {\hsize}
+\def\MPlayerheight{\vsize}
+
+\def\dosetMPlayer[#1][#2][#3]%
+ {\checkpositions % new, else only support after \starttext
+ \edef\MPlayerwidth {\MPw{#2}}%
+ \edef\MPlayerheight{\MPh{#2}}%
+ \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]}
+
+\def\getMPlayer
+ {\dodoubleempty\dogetMPlayer}
+
+\def\dogetMPlayer[#1][#2]%
+ {\framed
+ [\c!background={\v!foreground,#1},
+ \c!frame=\v!off,
+ \c!offset=\v!overlay,#2]}
+
+% Some day this (old) mechanism will be combined/integrated
+% in overlays
+
+\newskip\xposition \newskip\yposition
+\newskip\xdimension \newskip\ydimension
+\newskip\xoffset \newskip\yoffset
+
+% already defined \newbox\positionbox
+
+\def\startpositioning
+ {\bgroup
+ \xposition \zeropoint \yposition \zeropoint
+ \xdimension\zeropoint \ydimension\zeropoint
+ \xoffset \zeropoint \yoffset \zeropoint
+ \hfuzz \paperwidth \vfuzz \paperheight
+ \setbox\positionbox\hbox\bgroup}
+
+\def\stoppositioning
+ {\doifnot\@@psoffset\v!yes
+ {\global\xoffset\zeropoint
+ \global\yoffset\zeropoint}%
+ \global\advance\xdimension \xoffset
+ \global\advance\ydimension \yoffset
+ \egroup
+ \vbox to \ydimension
+ {\vskip\yoffset
+ \hbox to \xdimension
+ {\hskip\xoffset
+ \box\positionbox
+ \hfill}
+ \vfill}%
+ \egroup}
+
+\def\resetpositioning
+ {\getparameters[\??ps]
+ [\c!state=\v!start,%
+ \c!unit=\s!cm,%
+ \c!factor=1,%
+ \c!scale=1,%
+ \c!xfactor=\@@psfactor,%
+ \c!yfactor=\@@psfactor,%
+ \c!xscale=\@@psscale,%
+ \c!yscale=\@@psscale,%
+ \c!xstep=\v!absolute,%
+ \c!ystep=\v!absolute,%
+ \c!xoffset=\!!zeropoint,%
+ \c!yoffset=\!!zeropoint]}
+
+\def\setuppositioning
+ {\resetpositioning
+ \dodoubleargument\getparameters[\??ps]}
+
+\def\calculateposition#1#2#3#4#5#6#7#8#9%
+ {\setdimensionwithunit\scratchskip{#1}\@@psunit
+ \scratchskip#8\scratchskip
+ \scratchskip#9\scratchskip
+ \advance\scratchskip #4\relax
+ \doif{#2}\v!relative
+ {\advance\scratchskip #3%
+ \let#4\!!zeropoint}%
+ #3\scratchskip\relax
+ \doifnot\@@psstate\v!overlay
+ {\scratchskip#5\relax
+ \advance\scratchskip #3\relax
+ \ifdim#3<-#7\relax \global#7-#3\relax \fi
+ \ifdim\scratchskip>#6\relax \global#6\scratchskip\relax \fi}}
+
+\def\position
+ {\dosingleempty\doposition}
+
+\def\doposition[#1]#2(#3,#4)%
+ {\dowithnextbox
+ {\bgroup
+ \getparameters[\??ps][#1]%
+ \dontcomplain
+ \calculateposition{#3}\@@psxstep\xposition
+ \@@psxoffset{\nextboxwd}\xdimension\xoffset
+ \@@psxscale\@@psxfactor
+ \scratchdimen\nextboxht \advance\scratchdimen \nextboxdp
+ \calculateposition{#4}\@@psystep\yposition
+ \@@psyoffset\scratchdimen\ydimension\yoffset
+ \@@psyscale\@@psyfactor
+ \vbox to \zeropoint % kan beter.
+ {\vskip\yposition
+ \hbox to \zeropoint
+ {\hskip\xposition
+ \flushnextbox
+ \hss}
+ \vss}%
+ \xdef\dopoppositioning
+ {\xposition\the\xposition
+ \yposition\the\yposition
+ \noexpand\def\noexpand\@@psxoffset{\@@psxoffset}%
+ \noexpand\def\noexpand\@@psyoffset{\@@psyoffset}}%
+ \egroup
+ \dopoppositioning
+ \ignorespaces}
+ \hbox}
+
+\resetpositioning
+
+\setuppositioning
+ [\c!unit=\s!cm,
+ \c!factor=1,
+ \c!scale=1,
+ \c!xstep=\v!absolute,
+ \c!ystep=\v!absolute,
+ \c!offset=\v!yes,
+ \c!xoffset=\!!zeropoint,
+ \c!yoffset=\!!zeropoint]
+
+%D Watch out, a redefinition:
+
+\ifx\settextpagecontent\undefined \writestatus\m!systems{error in page-lyr.tex} \wait \fi
+
+\let\normalsettextpagecontent\settextpagecontent
+
+\definelayer
+ [OTRTEXT]
+
+\setuplayer
+ [OTRTEXT]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight]
+
+% will be overloaded in page-spr
+
+\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+ {\doifelselayerdata{OTRTEXT}
+ {\setbox#1\hbox to \makeupwidth
+ {\startoverlay
+ {\tightlayer[OTRTEXT]} % first, otherwise problems with toc
+ {\normalsettextpagecontent{#1}{#2}{#3}\box#1}
+ \stopoverlay}%
+ \dp#1\zeropoint}%
+ {\normalsettextpagecontent{#1}{#2}{#3}}}
+
+\protect \endinput
diff --git a/tex/context/base/pack-lyr.mkiv b/tex/context/base/pack-lyr.mkiv
new file mode 100644
index 000000000..0cb3ee244
--- /dev/null
+++ b/tex/context/base/pack-lyr.mkiv
@@ -0,0 +1,786 @@
+%D \module
+%D [ file=pack-lyr,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Layers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Layers}
+
+% todo : first / last / next / +... => page key
+% test on left/right box when no doublesided option given
+% use \ifcsname instead of doifvalue
+
+\unprotect
+
+% When being backgrounds layers get the background offset
+% displacement. Should be an option, on by default
+% (compatibility).
+
+% positie=forceer == ja maar dan ook in status=herhaal
+
+%D The layering mechanism implemented here is independent of
+%D the output routine, but future extensions may depend on a
+%D more close cooperation.
+
+%D First we overload a macro from \type {core-rul}. From now on
+%D we accept a (optional) argument: the specific layer it
+%D will go in. This means that we can move an overlay from one
+%D background to the other using the dimensions of the parent.
+
+\ifx\undefined\defineoverlay \message{loaded to early} \wait \fi
+
+\unexpanded\def\defineoverlay
+ {\dotripleempty\dodefineoverlay}
+
+\def\dodefineoverlay[#1][#2][#3]% overlay [layer] content
+ {\ifthirdargument
+ %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp
+ \def\docommand##1{\setvalue{\??ov##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}
+ \else
+ \def\docommand##1{\setvalue{\??ov##1}{\executedefinedoverlay{##1}{#2}}}%
+ \fi
+ \processcommalist[#1]\docommand}
+
+%D When tracing is turned on, a couple of boxes will
+%D show up as well as the reference point.
+
+\newif\iftracelayers % \tracelayerstrue
+
+%D This handy constant saved some string memory.
+
+\def\@@layerbox{@@layerbox}
+
+%D \macros
+%D {definelayer}
+%D
+%D Each layer gets its own (global) box. This also means that
+%D the data that goes into a layer, is typeset immediately.
+%D Each layer automatically gets an associated overlay,
+%D which can be used in any background assignment.
+
+% todo : links/rechts
+
+\unexpanded\def\definelayer
+ {\dodoubleargument\dodefinelayer}
+
+\def\dodefinelayer[#1][#2]% \zeropoint ipv \!!zeropoint
+ {\setuplayer
+ [#1]
+ [\c!doublesided=,\c!preset=,
+ \c!state=\v!start,\c!direction=\v!normal,\c!option=,
+ \c!x=\zeropoint,\c!y=\zeropoint,\c!position=\v!no,
+ \c!line=0,\c!column=0,
+ \c!width=\nextboxwd,\c!height=\nextboxht,
+ \c!offset=\zeropoint,\c!rotation=, % geen 0 !
+ \c!hoffset=\zeropoint,\c!voffset=\zeropoint,
+ \c!dx=\zeropoint,\c!dy=\zeropoint,
+ \c!location=rb,\c!position=\v!no,\c!page=,
+ \c!method=\v!overlay,
+ \c!sx=1,\c!sy=1,\c!corner=,#2]%
+ \doifvalue{\??ll#1\c!doublesided}\v!yes
+ {\dopresetlayerbox{\v!left #1}%
+ \dopresetlayerbox{\v!right#1}}%
+ \dopresetlayerbox{#1}%
+ \defineoverlay[#1][\composedlayer{#1}]}
+
+\def\dopresetlayerbox#1%
+ {\ifcsname\@@layerbox#1\endcsname
+ \resetlayer[#1]%
+ \else
+ \expandafter\newbox\csname\@@layerbox#1\endcsname
+ \fi}
+
+%D \macros
+%D {setuplayer}
+%D
+%D After a layer is defined, you can change its
+%D characteristics.
+
+\unexpanded\def\setuplayer
+ {\dodoubleargument\dosetuplayer}
+
+\def\dosetuplayer[#1][#2]%
+ {\def\docommand##1{\getparameters[\??ll##1][#2]}%
+ \processcommalist[#1]\docommand}
+
+%D \macros
+%D {setlayer}
+%D
+%D Data is moved into a layer with the following macro. When
+%D \type {position} is set, relative positioning is used, with
+%D the current point as reference point. Otherwise the topleft
+%D corner is used as reference point.
+%D
+%D \starttyping
+%D \setlayer [identifier] [optional parameters] {data}
+%D \stoptyping
+
+\newcount\currentlayerdata
+
+\let\currentlayerwidth \!!zeropoint
+\let\currentlayerheight\!!zeropoint
+
+\def\setcurrentlayerdimensions
+ {\dodoubleempty\dosetcurrentlayerdimensions}
+
+\def\dosetcurrentlayerdimensions[#1][#2]% name left|right
+ {\edef\currentlayerwidth {\thelayerwidth {#2#1}}%
+ \edef\currentlayerheight{\thelayerheight{#2#1}}}
+
+\def\thelayerwidth #1{\the\wd\executeifdefined{\@@layerbox#1}\emptybox}
+\def\thelayerheight#1{\the\ht\executeifdefined{\@@layerbox#1}\emptybox}
+
+\def\setlayer
+ {\dotripleempty\dosetlayer}
+
+% \def\dosetlayer[#1][#2][#3]% #4 == box do \fi is ok
+% {\doifelsevalue{\??ll#1\c!state}\v!stop
+% {\dowithnextbox\donothing\hbox}
+% {\ifthirdargument
+% \dodosetlayer[#1][#2][#3]%
+% \else
+% \dodosetlayer[#1][][#2]%
+% \fi}}
+
+\def\dosetlayer[#1][#2][#3]% #4 == box do \fi is ok
+ {\doifelsevalue{\??ll#1\c!state}\v!stop
+ {\dowithnextbox\donothing\hbox}
+ {\ifthirdargument
+ \dodosetlayer[#1][#2][#3]%
+ \else
+ \doifassignmentelse{#2}
+ {\dodosetlayer[#1][][#2]}%
+ {\dodosetlayer[#1][#2][]}%
+ \fi}}
+
+\def\dodosetlayer[#1][#2][#3]% #2 = links/rechts
+ {\bgroup
+ \recalculatebackgrounds % brrr
+ \global\advance\currentlayerdata\plusone
+ \forgetall
+ \dontcomplain
+ \doifvalue{\??ll#1\c!option}\v!test\tracelayerstrue
+ \iftracelayers\traceboxplacementtrue\fi
+ \dowithnextbox{\dodosetlayerindeed{#1}{#2}{#3}\egroup}\hbox}
+
+\def\dodosetlayerindeed#1#2#3% #2 = links/rechts
+ {\ifcsname\@@layerbox#1\endcsname % nb: odd/even discard, left/right not
+ \edef\@@layerloc{#2}%
+ \ifx\@@layerloc\v!even
+ \ifodd\realpageno
+ % discard nextbox
+ \else
+ \dododosetlayer[#1][\v!left][#3]%
+ \fi
+ \else\ifx\@@layerloc\v!odd
+ \ifodd\realpageno
+ \dododosetlayer[#1][\v!right][#3]%
+ %\else
+ % discard nextbox
+ \fi
+ \else
+ \dododosetlayer[#1][#2][#3]%
+ \fi\fi
+ \else
+ \writestatus{layer}{unknown layer #1}%
+ \fi}
+
+\newbox\layerbox
+
+\newdimen\@@layerxsiz
+\newdimen\@@layerysiz
+\newdimen\@@layerxoff
+\newdimen\@@layeryoff
+\newdimen\@@layerxpos
+\newdimen\@@layerypos
+
+\let\lastlayerxpos\!!zeropoint
+\let\lastlayerypos\!!zeropoint
+\let\lastlayerwd \!!zeropoint
+\let\lastlayerht \!!zeropoint
+\let\lastlayerdp \!!zeropoint
+
+% todo left/right
+
+\def\setlastlayerpos#1%
+ {\edef\layerpage{\MPp{lyr:\the\currentlayerdata}}%
+ \xdef\lastlayerxpos{\the\dimexpr-\MPx{lyr:#1:\layerpage}+\MPx{lyr:\the\currentlayerdata}\relax}%
+ \xdef\lastlayerypos{\the\dimexpr \MPy{lyr:#1:\layerpage}-\MPy{lyr:\the\currentlayerdata}\relax}}
+
+\unexpanded\def\definelayerpreset
+ {\dodoubleargument\dodefinelayerpreset}
+
+% \def\dodefinelayerpreset[#1][#2]%
+% {\setvalue{\??ll\??ll#1}{\dopresetlayer{#2}}}
+%
+% more fun: \definelayerpreset[whatever][lefttop]
+
+\def\dodefinelayerpreset[#1][#2]%
+ {\doifassignmentelse{#2}
+ {\setvalue{\??ll\??ll#1}{\dopresetlayer{#2}}}
+ {\setvalue{\??ll\??ll#1}{\csname\??ll\??ll#2\endcsname}}}
+
+\def\dopresetlayer#1#2#3% #1=list #2=tag #3=list
+ {\getparameters[\??ll#2][#1,#3]}
+
+\letempty\currentlayer
+
+\def\layerparameter#1{\csname\??ll\currentlayer#1\endcsname}
+
+\newdimen\layerwidth
+\newdimen\layerheight
+
+\chardef\@@lacome=1 % LAyerCOnstructionMEthod / temp, will be default
+
+\def\dododosetlayer[#1][#2][#3]% will be sped up
+ {% we use the global width, never change this
+ \def\currentlayer{#1}%
+ \@@layerxsiz\layerparameter\c!width
+ \@@layerysiz\layerparameter\c!height
+ \layerwidth \@@layerxsiz
+ \layerheight\@@layerysiz
+ % preroll
+ \getparameters[\??ll\currentlayer][#3]%
+ %
+ % \executeifdefined{\??ll\??ll\layerparameter\c!preset}\gobbletwoarguments\currentlayer{#3}%
+ %
+ \edef\@@currentlayerpreset{\layerparameter\c!preset}%
+ \ifcsname\??ll\??ll\@@currentlayerpreset\endcsname\csname\??ll\??ll\@@currentlayerpreset\endcsname\currentlayer{#3}\fi
+ %
+ \doif{\layerparameter\c!position}\v!overlay % slow, use \dosetvalue instead
+ {\getparameters[\??ll\currentlayer][\c!width=\zeropoint,\c!height=\zeropoint,\c!position=\v!yes]}%
+ \doifsomething{\layerparameter\c!rotation}% todo: use direct lowlevel call
+ {\setbox\nextbox\hbox{\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\flushnextbox}}}%
+ % no, not local
+ % \@@layerxsiz\layerparameter\c!width
+ % \@@layerysiz\layerparameter\c!height
+ % never change that
+ \@@layerxpos\layerparameter\c!x
+ \@@layerypos\layerparameter\c!y
+ \doifelse{\layerparameter\c!hoffset}\v!max{\@@layerxoff\@@layerxsiz}{\@@layerxoff\layerparameter\c!hoffset}%
+ \doifelse{\layerparameter\c!voffset}\v!max{\@@layeryoff\@@layerysiz}{\@@layeryoff\layerparameter\c!voffset}%
+ % dx/dy are internal context ones and can be used in preset
+ \advance\@@layerxoff\dimexpr\layerparameter\c!offset+\layerparameter\c!dx\relax
+ \advance\@@layeryoff\dimexpr\layerparameter\c!offset+\layerparameter\c!dy\relax
+ \@@layerxpos\layerparameter\c!sx\@@layerxpos
+ \@@layerypos\layerparameter\c!sy\@@layerypos
+ \@@layerxoff\layerparameter\c!sx\@@layerxoff
+ \@@layeryoff\layerparameter\c!sy\@@layeryoff
+ \edef\@@currentlayerposition{\layerparameter\c!position}%
+ \ifx\@@currentlayerposition\v!yes % combine ^
+ \setlastlayerpos{#2\currentlayer}% sets \layerpage; todo l/r %%%%%%%%%%%%
+ \@@layerxpos\lastlayerxpos
+ \@@layerypos\lastlayerypos
+ \letgvalue{\??ll\currentlayer\layerpage\c!position}\v!yes
+ \letgvalue{\??ll\currentlayer\c!state}\v!start % needed ?
+ \setbox\layerbox\vbox to \@@layerysiz{\hbox to \@@layerxsiz{\xypos{lyr:\the\currentlayerdata}\hss}\vss}%
+ \else
+ \setbox\layerbox\emptybox
+ \globallet\lastlayerxpos\!!zeropoint
+ \globallet\lastlayerypos\!!zeropoint
+ \normalexpanded{\noexpand\doifinset{\v!bottom}{\layerparameter\c!corner}}\dosetlayerbottompositions
+ \normalexpanded{\noexpand\doifinset{\v!right }{\layerparameter\c!corner}}\dosetlayerrightpositions
+ \normalexpanded{\noexpand\doifinset{\v!middle}{\layerparameter\c!corner}}\dosetlayermiddlepositions
+ \edef\layerpage{\layerparameter\c!page}%
+ \fi
+ \ifx\layerpage\empty \else % is expanded
+ \edef\layerpage{:\layerpage}%
+ \ifcsname\@@layerbox#2\currentlayer\layerpage\endcsname \else
+ \expandafter\newbox\csname\@@layerbox#2\currentlayer\layerpage\endcsname
+ \fi
+ \fi
+ \chardef\layerpagebox\csname\@@layerbox#2\currentlayer\layerpage\endcsname
+ \ifvoid\layerpagebox
+ \gsetboxllx\layerpagebox\zeropoint
+ \gsetboxlly\layerpagebox\zeropoint
+ \fi
+ \global\setbox\layerpagebox\vbox %to \layerparameter\c!height % new, otherwise no negative y possible
+ {\offinterlineskip
+ %postpone, to after nextboxwd correction % \hsize\layerparameter\c!width % new, keep box small
+ %\ifvoid\csname\@@layerbox\currentlayer\layerpage\endcsname\else % why not #2#1
+ \ifvoid\layerpagebox
+ \let\lastlayerwidth \zeropoint
+ \let\lastlayerheight\zeropoint
+ \else
+ \edef\lastlayerwidth {\the\wd\layerpagebox}%
+ \edef\lastlayerheight{\the\ht\layerpagebox}%
+ \ht\layerpagebox\zeropoint
+ \dp\layerpagebox\zeropoint
+ \wd\layerpagebox\zeropoint
+ \doifnot{\layerparameter\c!direction}\v!reverse{\box\layerpagebox}%
+ \fi
+ % don't move
+ \xdef\lastlayerwd{\the\nextboxwd}%
+ \xdef\lastlayerht{\the\nextboxht}% % not entirely ok when grid !
+ \xdef\lastlayerdp{\the\nextboxdp}% % not entirely ok when grid !
+ % this code
+ \doifelse{\layerparameter\c!location}\v!grid\donetrue\donefalse
+ \ifdone
+ \nextboxht\strutheight
+ \nextboxdp\strutdepth
+ \else
+ \setbox\nextbox\hbox{\alignedbox[\layerparameter\c!location]\vbox{\flushnextbox}}%
+ \fi
+ \ifnum\layerparameter\c!line=\zerocount\else % no \ifcase, can be negative
+ \advance\@@layerypos\dimexpr\layerparameter\c!line\lineheight+\topskip-\lineheight-\nextboxht\relax
+ \fi
+ \ifnum\layerparameter\c!column=\zerocount\else % no \ifcase, can be negative
+ \advance\@@layerxpos\layoutcolumnoffset{\layerparameter\c!column}%
+ \fi
+ \ifdone
+ \setbox\nextbox\hbox{\alignedbox[rb]\vbox{\flushnextbox}}%
+ \fi
+ % ll registration
+ \scratchdimen\@@layerxpos
+ \advance\scratchdimen\@@layerxoff
+ \ifdim\scratchdimen<\getboxllx\layerpagebox
+ \gsetboxllx\layerpagebox\scratchdimen
+ \fi
+ \ifcase\@@lacome\or % this test will become obsolete
+ \advance\scratchdimen\nextboxwd
+ \nextboxwd\ifdim\scratchdimen>\lastlayerwidth \scratchdimen \else \lastlayerwidth \fi
+ \fi
+ \scratchdimen\dimexpr\@@layerypos+\@@layeryoff\relax
+ \ifdim\scratchdimen<\getboxlly\layerpagebox
+ \gsetboxlly\layerpagebox\scratchdimen
+ \fi
+ % ll compensation
+ \ifcase\@@lacome\or % this test will become obsolete
+ \advance\scratchdimen\dimexpr\nextboxht+\nextboxdp\relax
+ \nextboxht\ifdim\scratchdimen>\lastlayerheight \scratchdimen \else \lastlayerheight \fi
+ \nextboxdp\zeropoint
+ \fi
+ % placement
+ \hsize\layerparameter\c!width % new, keep box small
+ \vbox to \layerparameter\c!height \bgroup
+ \smashbox\nextbox
+ \vskip\dimexpr\@@layerypos+\@@layeryoff\relax
+ \hskip\dimexpr\@@layerxpos+\@@layerxoff\relax
+ \flushnextbox
+ \ifvoid\layerpagebox
+ % already flushed
+ \else
+ % the reverse case % check !
+ \vskip-\dimexpr\@@layerypos+\@@layeryoff\relax
+ \box\layerpagebox
+ \fi
+ \egroup}%
+ % when position is true, the layerbox holds the compensation and needs
+ % to be placed; never change this !
+ \ifvoid\layerbox\else\box\layerbox\fi}
+
+\def\dosetlayerbottompositions
+ {\ifnum\layerparameter\c!line=\zerocount\else % can be < 0
+ \setevalue{\??ll\currentlayer\c!line}{\the\numexpr-\layerparameter\c!line+\layoutlines+\plusone\relax}%
+ \fi
+ \ifdim\@@layerysiz>\zeropoint
+ \advance\@@layerypos-\@@layerysiz
+ \@@layerypos-\@@layerypos
+ \@@layeryoff-\@@layeryoff
+ \fi}
+
+\def\dosetlayerrightpositions
+ {\ifnum\layerparameter\c!column=\zerocount\else % can be < 0
+ \setevalue{\??ll\currentlayer\c!column}{\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}%
+ \fi
+ \ifdim\@@layerxsiz>\zeropoint
+ \advance\@@layerxpos-\@@layerxsiz
+ \@@layerxpos-\@@layerxpos
+ \@@layerxoff-\@@layerxoff
+ \fi}
+
+\def\dosetlayermiddlepositions
+ {\ifdim\@@layerxsiz>\zeropoint \advance\@@layerxpos.5\@@layerxsiz \fi
+ \ifdim\@@layerysiz>\zeropoint \advance\@@layerypos.5\@@layerysiz \fi}
+
+%D Given the task to be accomplished, the previous macro is
+%D not even that complicated. It mainly comes down to skipping
+%D to the right place and placing a box on top of or below the
+%D existing content. In the case of position tracking, another
+%D reference point is chosen.
+
+%D \macros
+%D {doifelselayerdata}
+
+\def\doifelselayerdata#1%
+ {\ifcsname\@@layerbox#1\endcsname
+ \ifvoid\csname\@@layerbox#1\endcsname
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+%D \macros
+%D {flushlayer}
+%D
+%D When we flush a layer, we flush both the main one and the
+%D page dependent one (when defined). This feature is more
+%D efficient in \ETEX\ since there testing for an undefined
+%D macro does not takes hash space.
+
+% todo: setups before flush, handy hook
+
+% \unexpanded\def\flushlayer[#1]%
+% {\doifelsevalue{\??ll#1\c!state}\v!next
+% {\global\letvalue{\??ll#1\c!state}\v!start} % dangerous, stack-built-up
+% {\doifelsevalue{\??ll#1\c!state}\v!continue
+% {\global\letvalue{\??ll#1\c!state}\v!repeat} % dangerous, stack-built-up
+% {\doifelsevalue{\??ll#1\c!doublesided}\v!yes
+% {\doifundefinedelse{\@@layerbox#1}%
+% {\dodoflushlayerA[#1]}
+% {\doifbothsidesoverruled
+% {\dodoflushlayerB\v!left [#1]}% left
+% {\dodoflushlayerB\v!right[#1]}% right
+% {\dodoflushlayerB\v!left [#1]}}}% left
+% {\dodoflushlayerA[#1]}}}}
+
+\unexpanded\def\flushlayer[#1]% quite core, so optimized
+ {\begingroup
+ \forgetall
+ \edef\currentlayer{#1}%
+ \edef\@@currentlayerstate{\csname\??ll\currentlayer\c!state\endcsname}%
+ \ifx\@@currentlayerstate\v!stop
+ % nothing
+ \else\ifx\@@currentlayerstate\v!next
+ \global\expandafter\let\csname\??ll\currentlayer\c!state\endcsname\v!start % dangerous, stack-built-up
+ \else\ifx\@@currentlayerstate\v!continue
+ \global\expandafter\let\csname\??ll\currentlayer\c!state\endcsname\v!repeat % dangerous, stack-built-up
+ \else
+ \edef\@@currentlayerdoublesided{\csname\??ll\currentlayer\c!doublesided\endcsname}%
+ \ifx\@@currentlayerdoublesided\v!yes
+ \ifcsname\@@layerbox#1\endcsname
+ % we can make a dedicated one for this
+ \doifbothsidesoverruled{\dodoflushlayerB\v!left}{\dodoflushlayerB\v!right}{\dodoflushlayerB\v!left}%
+ \else
+ \dodoflushlayerA
+ \fi
+ \else
+ \dodoflushlayerA
+ \fi
+ \fi\fi\fi
+ \endgroup}
+
+% \ifcase#1\else\writestatus{layer}{unknown layer #3}\fi
+
+\def\dodoflushlayerA
+ {\startoverlay
+ {\ifcsname\@@layerbox\currentlayer \endcsname\dodoflushlayer\plusone \currentlayer \fi}%
+ {\ifcsname\@@layerbox\currentlayer:\realfolio\endcsname\dodoflushlayer\zerocount{\currentlayer:\realfolio}\fi}%
+ \stopoverlay}
+
+\def\dodoflushlayerB#1%
+ {\startoverlay
+ {\ifcsname\@@layerbox \currentlayer \endcsname\dodoflushlayer\plusone \currentlayer \fi}%
+ {\ifcsname\@@layerbox \currentlayer:\realfolio\endcsname\dodoflushlayer\zerocount {\currentlayer:\realfolio}\fi}%
+ {\ifcsname\@@layerbox#1\currentlayer \endcsname\dodoflushlayer\plusone {#1\currentlayer }\fi}%
+ {\ifcsname\@@layerbox#1\currentlayer:\realfolio\endcsname\dodoflushlayer\zerocount{#1\currentlayer:\realfolio}\fi}%
+ \stopoverlay}
+
+\def\dodoflushlayer#1#2% quite core, so optimized
+ {\begingroup % already grouped
+ \offinterlineskip
+ \edef\@@currentlayermethod{\csname\??ll\currentlayer\c!method\endcsname}%
+ \edef\@@currentlayeroption{\csname\??ll\currentlayer\c!option\endcsname}%
+ % needed because we need to handle method but we should find a way to
+ % speed this up
+ \edef\@@currentlayerpreset{\csname\??ll\currentlayer\c!preset\endcsname}%
+ \ifcsname\??ll\??ll\@@currentlayerpreset\endcsname\csname\??ll\??ll\@@currentlayerpreset\endcsname\currentlayer{}\fi
+ %
+ \ifx\@@currentlayeroption\v!test
+ \tracelayerstrue
+ \fi
+ \iftracelayers
+ \traceboxplacementtrue
+ \fi
+ \!!doneafalse
+ \!!donebfalse
+ \ifx\@@currentlayermethod\v!overlay\!!doneatrue\fi
+ \ifx\@@currentlayermethod\v!fit \!!donebtrue\fi
+ \!!donectrue
+ \ifcase#1\else
+ \edef\@@currentlayerposition{\csname\??ll\currentlayer\c!position\endcsname}%
+ \ifx\@@currentlayerposition\v!yes \else
+ \edef\@@currentlayerrepeat{\csname\??ll\currentlayer\c!repeat\endcsname}%
+ % \edef\@@currentlayerstate {\csname\??ll\currentlayer\c!state\endcsname}% actually this is already set
+ \ifx\@@currentlayerrepeat\v!yes
+ \!!donecfalse
+ \else\ifx\@@currentlayerstate\v!repeat
+ \!!donecfalse
+ \fi\fi
+ \fi
+ \fi
+ \chardef\layerbox\csname\@@layerbox#2\endcsname % \@@layerbox\currentlayer
+ % we need to copy in order to retain the negative offsets for a next
+ % stage of additions, i.e. llx/lly accumulate in repeat mode and the
+ % compensation may differ each flush depending on added content
+ \setbox\nextbox
+ \if!!doneb
+ \therepositionededlayerbox
+ \else
+ \if!!donec\box\else\copy\fi\layerbox % sorry for the delay due to copying
+ \fi
+ % todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
+ \doifoverlayelse{#2}{\setlayoutcomponentattribute\v!layer{#2}}\resetlayoutcomponentattribute
+ \iftracelayers \ruledvbox \else \vbox \fi \if!!donea to \overlayheight \fi \layoutcomponentboxattribute
+ {\hbox \if!!donea to \overlaywidth \fi
+ {\edef\@@currentlayerpageposition{\csname\??ll#2\realfolio\c!position\endcsname}%
+ \ifx\@@currentlayerpageposition\v!yes\xypos{lyr:#2:\realfolio}\fi
+ \box\nextbox
+ \hss}%
+ \vss}%
+ \if!!donec
+ \gsetboxllx\layerbox\zeropoint
+ \gsetboxlly\layerbox\zeropoint
+ \fi
+ \endgroup}
+
+\def\therepositionededlayerbox % assumes that \if!!donec is set (todo: use dedicated flags)
+ {\vbox
+ {\vskip-\getboxlly\layerbox
+ \hskip-\getboxllx\layerbox
+ \hsize-\dimexpr\getboxllx\layerbox-\wd\layerbox\relax
+ \if!!donec\box\else\copy\fi\layerbox}}
+
+% \definelayer[test][method=fit] \setupcolors[state=start] \tracelayerstrue
+%
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=10pt]{g}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=-10pt]{bb}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test][x=-20pt]{cccccc}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{dd}\setlayer[test][x=-20pt,y=-3pt]{eeeeee}\flushlayer[test]}
+
+%D \macros
+%D {composedlayer,placelayer,tightlayer}
+%D
+%D This is a handy shortcut, which saves a couple of braces
+%D when we use it as parameter. This name also suits better
+%D to other layering commands.
+
+\def\composedlayer#1{\flushlayer[#1]}
+
+\let\placelayer\flushlayer
+
+\def\tightlayer[#1]%
+ {\hbox
+ {\def\currentlayer{#1}% todo: left/right
+ \setbox\nextbox\emptybox % hoogte/breedte are \wd\nextbox/\ht\nextbox
+ \hsize\layerparameter\c!width % \overlaywidth = \hsize
+ \vsize\layerparameter\c!height % \overlaywheight = \vsize
+ \composedlayer{#1}}}
+
+%D \macros
+%D {resetlayer}
+%D
+%D This macro hardly needs an explanation (and is seldom
+%D needed as well).
+
+\def\doresetlayer#1%
+ {\ifcsname\@@layerbox#1\endcsname
+ \global\setbox\csname\@@layerbox#1\endcsname\emptybox
+ \fi}
+
+\def\resetlayer[#1]%
+ {\doresetlayer{#1}%
+ \doifvalue{\??ll#1\c!doublesided}\v!yes % kind of redundant test
+ {\doresetlayer{\v!left #1}%
+ \doresetlayer{\v!right#1}}%
+ \doresetlayer{#1:\realfolio}}
+
+%D \macros
+%D {setMPlayer}
+%D
+%D The following layer macro uses the positions that are
+%D registered by \METAPOST.
+%D
+%D \starttyping
+%D \definelayer[test]
+%D
+%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
+%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
+%D \setMPlayer [test] [somepos-3] {\externalfigure[cow.mps][width=2cm]}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 10cm withcolor red ;
+%D register ("somepos-1",2cm,3cm,center currentpicture) ;
+%D register ("somepos-2",8cm,5cm,(-1cm,-2cm)) ;
+%D register ("somepos-3",0cm,0cm,(-2cm,2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \getMPlayer[test]{\useMPgraphic{oeps}}
+%D \stoptyping
+%D
+%D The last line is equivalent to
+%D
+%D \starttyping
+%D \framed
+%D [background={foreground,test},offset=overlay]
+%D {\useMPgraphic{oeps}}
+%D \stoptyping
+
+\def\setMPlayer
+ {\dotripleempty\dosetMPlayer}
+
+\def\MPlayerwidth {\hsize}
+\def\MPlayerheight{\vsize}
+
+\def\dosetMPlayer[#1][#2][#3]%
+ {\edef\MPlayerwidth {\MPw{#2}}%
+ \edef\MPlayerheight{\MPh{#2}}%
+ \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]}
+
+\def\getMPlayer
+ {\dodoubleempty\dogetMPlayer}
+
+\def\dogetMPlayer[#1][#2]%
+ {\framed
+ [\c!background={\v!foreground,#1},
+ \c!frame=\v!off,
+ \c!offset=\v!overlay,#2]}
+
+% The next mechanism is obsolete and will be removed in \MKIV\ (or move to
+% the compatibility module.
+
+\newskip\xposition \newskip\yposition
+\newskip\xdimension \newskip\ydimension
+\newskip\xoffset \newskip\yoffset
+
+% already defined \newbox\positionbox
+
+\unexpanded\def\startpositioning
+ {\bgroup
+ \xposition \zeropoint \yposition \zeropoint
+ \xdimension\zeropoint \ydimension\zeropoint
+ \xoffset \zeropoint \yoffset \zeropoint
+ \hfuzz \paperwidth \vfuzz \paperheight
+ \setbox\positionbox\hbox\bgroup}
+
+\unexpanded\def\stoppositioning
+ {\doifnot\@@psoffset\v!yes
+ {\global\xoffset\zeropoint
+ \global\yoffset\zeropoint}%
+ \global\advance\xdimension \xoffset
+ \global\advance\ydimension \yoffset
+ \egroup
+ \vbox to \ydimension
+ {\vskip\yoffset
+ \hbox to \xdimension
+ {\hskip\xoffset
+ \box\positionbox
+ \hfill}
+ \vfill}%
+ \egroup}
+
+\def\resetpositioning
+ {\getparameters[\??ps]
+ [\c!state=\v!start,%
+ \c!unit=\s!cm,%
+ \c!factor=1,%
+ \c!scale=1,%
+ \c!xfactor=\@@psfactor,%
+ \c!yfactor=\@@psfactor,%
+ \c!xscale=\@@psscale,%
+ \c!yscale=\@@psscale,%
+ \c!xstep=\v!absolute,%
+ \c!ystep=\v!absolute,%
+ \c!xoffset=\!!zeropoint,%
+ \c!yoffset=\!!zeropoint]}
+
+\unexpanded\def\setuppositioning
+ {\resetpositioning
+ \dodoubleargument\getparameters[\??ps]}
+
+\def\calculateposition#1#2#3#4#5#6#7#8#9%
+ {\setdimensionwithunit\scratchskip{#1}\@@psunit
+ \scratchskip#8\scratchskip
+ \scratchskip#9\scratchskip
+ \advance\scratchskip #4\relax
+ \doif{#2}\v!relative
+ {\advance\scratchskip #3%
+ \let#4\!!zeropoint}%
+ #3\scratchskip\relax
+ \doifnot\@@psstate\v!overlay
+ {\scratchskip#5\relax
+ \advance\scratchskip #3\relax
+ \ifdim#3<-#7\relax \global#7-#3\relax \fi
+ \ifdim\scratchskip>#6\relax \global#6\scratchskip\relax \fi}}
+
+\def\position
+ {\dosingleempty\doposition}
+
+\def\doposition[#1]#2(#3,#4)%
+ {\dowithnextbox
+ {\bgroup
+ \getparameters[\??ps][#1]%
+ \dontcomplain
+ \calculateposition{#3}\@@psxstep\xposition
+ \@@psxoffset{\nextboxwd}\xdimension\xoffset
+ \@@psxscale\@@psxfactor
+ \scratchdimen\nextboxht \advance\scratchdimen \nextboxdp
+ \calculateposition{#4}\@@psystep\yposition
+ \@@psyoffset\scratchdimen\ydimension\yoffset
+ \@@psyscale\@@psyfactor
+ \vbox to \zeropoint % kan beter.
+ {\vskip\yposition
+ \hbox to \zeropoint
+ {\hskip\xposition
+ \flushnextbox
+ \hss}
+ \vss}%
+ \xdef\dopoppositioning
+ {\xposition\the\xposition
+ \yposition\the\yposition
+ \noexpand\def\noexpand\@@psxoffset{\@@psxoffset}%
+ \noexpand\def\noexpand\@@psyoffset{\@@psyoffset}}%
+ \egroup
+ \dopoppositioning
+ \ignorespaces}
+ \hbox}
+
+\resetpositioning
+
+\setuppositioning
+ [\c!unit=\s!cm,
+ \c!factor=1,
+ \c!scale=1,
+ \c!xstep=\v!absolute,
+ \c!ystep=\v!absolute,
+ \c!offset=\v!yes,
+ \c!xoffset=\!!zeropoint,
+ \c!yoffset=\!!zeropoint]
+
+%D Watch out, a redefinition:
+
+\ifx\settextpagecontent\undefined \writestatus\m!systems{error in page-lyr.tex} \wait \fi
+
+\let\normalsettextpagecontent\settextpagecontent
+
+\definelayer
+ [OTRTEXT]
+
+\setuplayer
+ [OTRTEXT]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight]
+
+% will be overloaded in page-spr
+
+\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+ {\doifelselayerdata{OTRTEXT}
+ {\setbox#1\hbox to \makeupwidth
+ {\startoverlay
+ {\tightlayer[OTRTEXT]} % first, otherwise problems with toc
+ {\normalsettextpagecontent{#1}{#2}{#3}\box#1}
+ \stopoverlay}%
+ \dp#1\zeropoint}%
+ {\normalsettextpagecontent{#1}{#2}{#3}}}
+
+\protect \endinput
diff --git a/tex/context/base/pack-obj.lua b/tex/context/base/pack-obj.lua
new file mode 100644
index 000000000..0ee46fc99
--- /dev/null
+++ b/tex/context/base/pack-obj.lua
@@ -0,0 +1,54 @@
+if not modules then modules = { } end modules ['pack-obj'] = {
+ version = 1.001,
+ comment = "companion to pack-obj.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
We save object references in the main utility table. jobobjects are
+reusable components.
+--ldx]]--
+
+local texsprint, texcount = tex.sprint, tex.count
+
+jobobjects = jobobjects or { }
+jobobjects.collected = jobobjects.collected or { }
+jobobjects.tobesaved = jobobjects.tobesaved or { }
+
+local collected, tobesaved = jobobjects.collected, jobobjects.tobesaved
+
+local function initializer()
+ collected, tobesaved = jobobjects.collected, jobobjects.tobesaved
+end
+
+job.register('jobobjects.collected', jobobjects.tobesaved, initializer, nil)
+
+function jobobjects.save(tag,number,page)
+ local t = { number, page }
+ tobesaved[tag], collected[tag] = t, t
+end
+
+function jobobjects.set(tag,number,page)
+ collected[tag] = { number, page }
+end
+
+function jobobjects.get(tag)
+ return collected[tag] or tobesaved[tag]
+end
+
+function jobobjects.number(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ texsprint((o and o[1]) or default)
+end
+
+function jobobjects.page(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ texsprint((o and o[2]) or default)
+end
+
+function jobobjects.doifelse(tag)
+ commands.testcase(collected[tag] or tobesaved[tag])
+end
+
diff --git a/tex/context/base/pack-obj.mkii b/tex/context/base/pack-obj.mkii
new file mode 100644
index 000000000..6971ad04f
--- /dev/null
+++ b/tex/context/base/pack-obj.mkii
@@ -0,0 +1,371 @@
+%D \module
+%D [ file=pack-obj,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Objects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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, move more to mkiv, get rid of blabelgroup
+
+\writestatus{loading}{ConTeXt Packaging Macros / Objects}
+
+\unprotect
+
+%D \macros
+%D {setobject,getobject,ifinobject}
+%D
+%D Boxes can be considered reuable objects. Unfortunaltely once
+%D passed to the \DVI\ file, such objects cannot be reused. In
+%D \PDF\ however, reusing is possible and sometimes even a
+%D necessity. Therefore, \CONTEXT\ supports reusable objects.
+%D
+%D During the \TEX\ processing run, boxes can serve the purpose
+%D of objects, and the \DVI\ driver module implements objects
+%D using packed boxes.
+%D
+%D The \PDF\ and \PDFTEX\ driver modules implement objects
+%D using \PDF\ forms. There is no (real) restriction on the
+%D number of objects there.
+%D
+%D The first application of objects in \CONTEXT\ concerned
+%D \METAPOST\ graphics and fill||in form fields. The first
+%D application can save lots of bytes, while the latter use is
+%D more a necessity than byte saving.
+%D
+%D \starttyping
+%D \setobject{class}{name}\somebox{}
+%D \getobject{class}{name}
+%D \stoptyping
+%D
+%D Here \type{\somebox} can be whatever box specification suits
+%D \TEX. We save the dimensions of an object, although some
+%D drivers will do so themselves. This means that when for
+%D instance using \PDFTEX\ we could save a hash entry plus some
+%D 20+ memory locations per object by delegating this
+%D housekeeping to the driver. The current approach permits
+%D us to keep the box characteristic too.
+
+\newif\ifinobject
+
+\def\checkobjectreferences
+ {\startnointerference
+ \protectlabels
+ \ifx\usedoutputdriver\currentoutput
+ \doutilities{objectreferences}\jobname\empty\relax\relax
+ \else
+ % different format (will fails on \purenumber)
+ \fi
+ \global\let\checkobjectreferences\relax
+ \stopnointerference}
+
+\def\objectplaceholder{NOT YET FLUSHED}%
+
+\def\presetobject#1#2% \global added
+ {\blabelgroup
+ \ifcsname\r!object#1::#2\endcsname\else
+ \global\@EA\let\csname\r!object#1::#2\endcsname\objectplaceholder
+ \fi
+ \elabelgroup}
+
+\def\dosetobject#1#2#3% \initializepaper this will move to \everyshipout
+ {\initializepaper
+ \blabelgroup
+ \ifcsname\r!object#2::#3\endcsname
+ \elabelgroup \expandafter\gobblefivearguments
+ \else % tzt, overload internal referenced objects to save entries
+ \elabelgroup \expandafter\dodosetobject
+ \fi
+ {#1}{#2}{#3}}
+
+\def\resetobject#1#2%
+ {\checkobjectreferences
+ \letbeundefined{\r!object#1::#2}}
+
+%D \macros
+%D {finalizeobjectbox}
+%D
+%D This one provides a hook for last minute object box processing
+%D we need this in \MKIV.
+
+\ifx\finalizeobjectbox\undefined
+ \let\finalizeobjectbox\gobbleoneargument
+\fi
+
+%D Somehow there is a rounding error problem in either \PDFTEX\
+%D or in viewers, or maybe it is conforming the specs. The next
+%D variable compensate for it by removing the rather tight
+%D clip.
+
+\def\objectoffset{1cm}
+
+% \def\dodosetobject#1#2#3%
+% {\bgroup
+% \inobjecttrue
+% \dowithnextbox{\dododosetobject{#1}{#2}{#3}\egroup}}
+
+\def\dodosetobject#1#2#3%
+ {\bgroup
+ \globalpushmacro\crossreferenceobject \objectreferenced
+ \inobjecttrue
+ \dowithnextbox
+ {\globalpopmacro\crossreferenceobject
+ \dododosetobject{#1}{#2}{#3}\egroup}}
+
+\def\dododosetobject#1#2#3%
+ {\blabelgroup
+ \dontshowcomposition % rather fuzzy in \setxvalue ... \hbox
+ \scratchdimen\objectoffset
+ \@EA\xdef\csname\r!object#2::#3\endcsname
+ {\noexpand\dohandleobject{#2}{#3}%
+ {\ifhbox\nextbox\hbox\else\vbox\fi}%
+ %{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
+ {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}%
+ {\number\scratchdimen}}%
+ \expanded % freeze the dimensions since \dostartobject may use \nextbox
+ {\dostartobject
+ {#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
+ \ifcase#1\relax\else \ifdim\objectoffset>\zeropoint
+ \setbox\nextbox\vbox spread 2\scratchdimen
+ {\forgetall \offinterlineskip
+ \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}%
+ \fi \fi
+ \flushnextbox
+ \dostopobject
+ \elabelgroup}
+
+\def\getobject#1#2%
+ {\blabelgroup
+ \let\dohandleobject\dogetobject
+ \csname\r!object#1::#2\endcsname}
+
+% \def\dogetobject#1#2#3#4#5#6%
+% {\initializepaper
+% \forgetall
+% \dontshowcomposition
+% \setbox\scratchbox\vbox
+% {\doinsertobject{#1}{#2}}%
+% \setbox\scratchbox#3%
+% {\vbox to #5\scaledpoint
+% {\ifdim\ht\scratchbox>#5\scaledpoint
+% % or \ifdim\wd\scratchbox>#4\scaledpoint
+% \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+% \else
+% \vss\box\scratchbox
+% \fi}}%
+% \wd\scratchbox#4\scaledpoint
+% \ht\scratchbox#5\scaledpoint
+% \dp\scratchbox#6\scaledpoint
+% \box\scratchbox
+% \elabelgroup}
+
+% \def\dogetobject#1#2#3#4#5#6#7%
+% {\initializepaper
+% \forgetall
+% \dontshowcomposition
+% \setbox\scratchbox\vbox
+% {\doinsertobject{#1}{#2}}%
+% \setbox\scratchbox#3%
+% {\vbox to #5\scaledpoint
+% {\ifdim\ht\scratchbox>#5\scaledpoint
+% % or \ifdim\wd\scratchbox>#4\scaledpoint
+% \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+% \else
+% \vss\box\scratchbox
+% \fi}}%
+% \scratchdimen#7\scaledpoint
+% \setbox\nextbox\hbox
+% {\hskip-\scratchdimen\lower\scratchdimen\flushnextbox}%
+% \wd\scratchbox#4\scaledpoint
+% \ht\scratchbox#5\scaledpoint
+% \dp\scratchbox#6\scaledpoint
+% \box\scratchbox
+% \elabelgroup}
+
+\def\dogetobject#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf
+ {\initializepaper
+ \forgetall
+ \dontshowcomposition
+ \setbox\scratchbox\vbox
+ {\doinsertobject{#1}{#2}}%
+ \setbox\scratchbox#3%
+ {\vbox to #5\scaledpoint
+ {\ifdim\ht\scratchbox>#5\scaledpoint
+ \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+ \else\ifdim\wd\scratchbox>#4\scaledpoint
+ \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+ \else
+ %\vss\box\scratchbox
+ \vss\hbox to #4\scaledpoint{\box\scratchbox\hss}% fix Chof
+ \fi\fi}}%
+ \box\scratchbox
+ \elabelgroup}
+
+%D If needed one can ask for the dimensions of an object with:
+%D
+%D \starttyping
+%D \getobjectdimensions{class}{name}
+%D \stoptyping
+%D
+%D The results are reported in \type {\objectwidth}, \type
+%D {\objectheight} and \type {\objectdepth}.
+
+% \def\dogetobjectdimensions#1#2#3#4#5#6%
+% {\def\objectwidth {#4\s!sp}%
+% \def\objectheight{#5\s!sp}%
+% \def\objectdepth {#6\s!sp}}
+
+\def\dogetobjectdimensions#1#2#3#4#5#6#7%
+ {\def\objectwidth {#4\s!sp}%
+ \def\objectheight{#5\s!sp}%
+ \def\objectdepth {#6\s!sp}%
+ \def\objectmargin{#7\s!sp}}
+
+\def\getobjectdimensions#1#2%
+ {\let\dohandleobject\dogetobjectdimensions
+ \let\objectwidth \!!zeropoint
+ \let\objectheight\!!zeropoint
+ \let\objectdepth \!!zeropoint
+ \labelcsname\r!object#1::#2\endcsname}
+
+%D Apart from this kind of objects, that have typeset content,
+%D we can have low level driver specific objects. Both types
+%D can have references to internal representations, hidden for
+%D the user. We keep track of such references by means of a
+%D dedicated cross reference mechanism. Normally, objects are
+%D defined before they are used, but forward referencing
+%D sometimes occurs.
+%D
+%D \starttyping
+%D \dosetobjectreference {class} {identifier} {reference value} {page}
+%D \dogetobjectreference {class} {identifier} \csname
+%D \stoptyping
+%D
+%D These commands are to be called by the \type{\startobject},
+%D \type{\stopobject} and \type{\insertobject} specials.
+
+\def\objectreferenced{\global\chardef\crossreferenceobject\plusone}
+\def\driverreferenced{\global\chardef\crossreferenceobject\zerocount}
+
+\objectreferenced
+
+% no undefined test ! ! ! ! (pdftex fails on undefined objects)
+
+\def\setobjectreferences
+ {\def\objectreference##1##2##3##4%
+ {\ifundefined{\r!driver##1::##2}%
+ \setxvalue{\r!driver##1::##2}{{##3}{##4}}%
+ \else
+ \showmessage\m!references{31}{[##1 ##2=>##3/##4]}%
+ \fi}}
+
+\def\resetobjectreferences
+ {\let\objectreference\gobblefourarguments}
+
+\resetobjectreferences
+
+\def\doregisterobjectreference#1#2#3%
+ {\checkobjectreferences
+ \blabelgroup
+ \expanded{\writeutilitycommand{\noexpand\objectreference{#1}{#2}{#3}{\noexpand\realfolio}}}%
+ \setxvalue{\r!driver#1::#2}{{#3}{\noexpand\realfolio}}%
+ \elabelgroup}
+
+\def\dooverloadobjectreference#1#2#3%
+ {\checkobjectreferences
+ \blabelgroup
+ \setxvalue{\r!driver#1::#2}{{#3}{\noexpand\realfolio}}%
+ \elabelgroup}
+
+\def\dosetobjectreference
+ {\ifcase\crossreferenceobject
+ \objectreferenced
+ \expandafter\dooverloadobjectreference
+ \else
+ \expandafter\doregisterobjectreference
+ \fi}
+
+\def\dosetdriverreference
+ {\driverreferenced\dosetobjectreference}
+
+\def\defaultobjectreference#1#2{0} % driver dependent
+\def\defaultobjectpage #1#2{\realfolio}
+
+\def\dogetobjectreference {\dodogetobjectreference\firstoftwoarguments\defaultobjectreference}
+\def\dogetobjectreferencepage{\dodogetobjectreference\secondoftwoarguments\defaultobjectpage}
+
+\def\dodogetobjectreference#1#2#3#4#5%
+ {\checkobjectreferences
+ \blabelgroup
+ \ifundefined{\r!driver#3::#4}%
+ \showmessage\m!references{30}{[#3 #4=>#3/#4]}%
+ \xdef#5{#2{#3}{#4}}%
+ \else
+ \xdef#5{\@EAEAEA#1\csname\r!driver#3::#4\endcsname}%
+ \fi
+ \elabelgroup}
+
+\def\setobject {\driverreferenced\dosetobject1}
+\def\settightobject{\driverreferenced\dosetobject0}
+
+%D \macros
+%D {doifobjectfoundelse,doifobjectreferencefoundelse}
+%D
+%D To prevent redundant definition of objects, one can use
+%D the next tests:
+%D
+%D \starttyping
+%D \doifobjectfoundelse{class}{object}{do then}{do else}
+%D \doifobjectreferencefoundelse{class}{object}{do then}{do else}
+%D \stoptyping
+
+\def\doifobjectfoundelse#1#2%
+ {\blabelgroup \ifcsname\r!object#1::#2\endcsname
+ \elabelgroup \expandafter\firstoftwoarguments
+ \else
+ \elabelgroup \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifobjectreferencefoundelse#1#2%
+ {\checkobjectreferences
+ \blabelgroup \ifcsname\r!driver#1::#2\endcsname
+ \elabelgroup \expandafter\firstoftwoarguments
+ \else
+ \elabelgroup \expandafter\secondoftwoarguments
+ \fi}
+
+%D \macros
+%D {doifobjectssupportedelse}
+%D
+%D Starting with reuse of graphics, we will implement object
+%D reuse when possible. To enable mechanisms to determine
+%D what method to use, we provide:
+%D
+%D \starttyping
+%D \doifobjectssupportedelse{true action}{false action}
+%D \stoptyping
+%D
+%D As we can see, currently objects depend on the special
+%D driver.
+
+\newif\ifobjectssupported \objectssupportedtrue
+
+\def\doifobjectssupportedelse
+ {\ifobjectssupported
+ \@EA\doifspecialavailableelse\@EA\doinsertobject
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
+
+%D There is a conceptual problem here. Objects are not possible
+%D in \DVI, unless faked like in \type {spec-dvi}. This means
+%D that we must be careful in loading special drivers that do
+%D support objects while we still want to be able to use the
+%D \DVI\ output.
+
+\protect \endinput
diff --git a/tex/context/base/pack-obj.mkiv b/tex/context/base/pack-obj.mkiv
new file mode 100644
index 000000000..81220e324
--- /dev/null
+++ b/tex/context/base/pack-obj.mkiv
@@ -0,0 +1,399 @@
+%D \module
+%D [ file=pack-obj,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Objects,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Objects}
+
+\unprotect
+
+\let\objectreference\gobblefourarguments % catch mkii tuo stuff
+
+\registerctxluafile{pack-obj}{1.001}
+
+% \startluacode
+% local texbox, texdimen, texcount, texwrite = tex.box, tex.dimen, tex.count, tex.write
+% local pdfxform, pdfrefxform = pdf.xform, pdf.refxform
+%
+% function pdf.xform (l) texbox["objectbox"] = nil return l end
+% function pdf.refxform(l) return node.copy_list(l) end
+%
+% backends.codeinjections.register = pdf.xform
+% backends.codeinjections.restore = pdf.refxform
+%
+% local codeinjections = backends.codeinjections
+%
+% objects = objects or { }
+%
+% local data = { }
+%
+% objects.data = data
+% objects.n = 0
+%
+% function objects.register(name)
+% objects.n = objects.n + 1
+% local list = texbox.objectbox
+% nodes.process_page(list)
+% data[name] = {
+% codeinjections.restore(list),
+% texdimen.objectwd,
+% texdimen.objectht,
+% texdimen.objectdp,
+% texdimen.objectoff,
+% }
+% end
+%
+% function objects.restore(name)
+% local d = data[name]
+% if d then
+% texbox .objectbox = codeinjections.restore(d[1])
+% texdimen.objectwd = d[2]
+% texdimen.objectht = d[3]
+% texdimen.objectdp = d[4]
+% texdimen.objectoff = d[5]
+% else
+% texbox .objectbox = nil
+% texdimen.objectwd = 0
+% texdimen.objectht = 0
+% texdimen.objectdp = 0
+% texdimen.objectoff = 0
+% end
+% end
+%
+% function objects.reference(name)
+% local d = data[name]
+% texwrite((d and d[1]) or 0)
+% end
+%
+% function objects.enhance(name)
+% local d = data[name]
+% if d then
+% d[6] = texcount.realpageno
+% end
+% end
+%
+% function objects.page(name)
+% local d = data[name]
+% texwrite((d and d[6]) or texcount.realpageno)
+% end
+%
+% function objects.doifelse(name)
+% commands.testcase(data[name])
+% end
+% \stopluacode
+%
+% \newbox \objectbox
+% \newtoks \everyobject
+% \newif \ifinobject
+%
+% \newdimen\objectoff \def\objectmargin{\the\objectoff}
+% \newdimen\objectwd \def\objectwidth {\the\objectwd }
+% \newdimen\objectht \def\objectheight{\the\objectht }
+% \newdimen\objectdp \def\objectdepth {\the\objectdp }
+%
+% \def\objectoffset{1cm}
+%
+% \everyobject{\the\everyPDFxform}
+%
+% \let\doresetobjects\relax
+%
+% \def\setobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}}
+% \def\settightobject#1#2{\begingroup\objectoff\zeropoint \inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}}
+%
+% \let\objectsetvbox\vbox %\def\objectsetvbox{\ruledvbox}
+% \let\objectgetvbox\vbox %\def\objectgetvbox{\ruledvbox}
+% \let\objectsethbox\hbox %\def\objectsethbox{\ruledhbox}
+% \let\objectgethbox\hbox %\def\objectgethbox{\ruledhbox}
+%
+% \def\dosetobject#1#2%
+% {\objectwd\wd\nextbox
+% \objectht\ht\nextbox
+% \objectdp\dp\nextbox
+% \ifdim\objectoff=\zeropoint\relax
+% \setbox\objectbox\box\nextbox
+% \else
+% \setbox\objectbox\objectsetvbox spread 2\objectoff{\vss\objectsethbox spread 2\objectoff{\hss\flushnextbox\hss}\vss}%
+% \fi
+% \ctxlua{objects.register("#1::#2")}%
+% \endgroup}
+%
+% \def\getobject#1#2%
+% {\begingroup
+% \ctxlua{objects.restore("#1::#2")}%
+% \ifdim\objectoff=\zeropoint\relax \else
+% \setbox\objectbox\objectgetvbox to \dimexpr\objectht+\objectdp\relax
+% {\vss\objectgethbox to \objectwd{\hss\box\objectbox\hss}\vss}%
+% \wd\objectbox\objectwd
+% \ht\objectbox\objectht
+% \dp\objectbox\objectdp
+% \fi
+% \box\objectbox
+% \endgroup}
+%
+% \def\getpageobject#1#2%
+% {\begingroup
+% \ctxlua{objects.restore("#1::#2")}%
+% \ifdim\objectoff=\zeropoint\relax
+% \setbox\objectbox\objectgethbox{\ctxlatelua{objects.enhance("#1::#2")}\box\objectbox}
+% \else
+% \setbox\objectbox\objectgetvbox to \dimexpr\objectht+\objectdp\relax
+% {\vss\objectgethbox to \objectwd{\ctxlatelua{objects.enhance("#1::#2")}\hss\box\objectbox\hss}\vss}%
+% \wd\objectbox\objectwd
+% \ht\objectbox\objectht
+% \dp\objectbox\objectdp
+% \fi
+% \box\objectbox
+% \endgroup}
+%
+% \def\setobjectdirectly #1#2{\ctxlua{objects.register("#1::#2")}}
+% \def\getobjectdirectly #1#2{\ctxlua{objects.restore ("#1::#2")}}
+% \def\getobjectdimensions #1#2{\ctxlua{objects.restore ("#1::#2")}}
+% \def\doifobjectfoundelse #1#2{\ctxlua{objects.doifelse("#1::#2")}}
+% \def\doifobjectreferencefoundelse#1#2{\ctxlua{objects.doifelse("#1::#2")}}
+%
+% \let\objectreferenced\relax
+% \let\driverreferenced\relax
+%
+% \def\doregisterobjectreference{\writestatus{objects}{obsolete: register object reference}\gobblethreearguments}
+% \def\dooverloadobjectreference{\writestatus{objects}{obsolete: overload object reference}\gobblethreearguments}
+% \def\dosetobjectreference {\writestatus{objects}{obsolete: set object reference}\gobblethreearguments}
+% \def\dosetdriverreference {\writestatus{objects}{obsolete: set driver reference}\gobblethreearguments}
+%
+% \def\defaultobjectreference{0}
+% \def\defaultobjectpage {\realfolio}
+%
+% \def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{objects.reference("#1::#2)}}}
+% \def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{objects.page("#1::#2))}}}
+%
+% \protect
+%
+% \starttext
+% test \setobject{a}{b}\ruledhbox{xxx}\getobject{a}{b} test
+% \vskip3cm
+% test \settightobject{a}{b}\ruledhbox{xxx}\getobject{a}{b} test
+% test \settightobject{a}{c}\ruledhbox{xxx}\getobject{a}{c} test
+% \dorecurse{5000}{test \setobject{a}{b}\ruledhbox{xxx}\getobject{a}{b} test }
+% \stoptext
+
+%D \macros
+%D {setobject,getobject,ifinobject}
+%D
+%D Boxes can be considered reuable objects. Unfortunaltely once
+%D passed to the \DVI\ file, such objects cannot be reused. In
+%D \PDF\ however, reusing is possible and sometimes even a
+%D necessity. Therefore, \CONTEXT\ supports reusable objects.
+%D
+%D During the \TEX\ processing run, boxes can serve the purpose
+%D of objects, and the \DVI\ driver module implements objects
+%D using packed boxes.
+%D
+%D The \PDF\ and \PDFTEX\ driver modules implement objects
+%D using \PDF\ forms. There is no (real) restriction on the
+%D number of objects there.
+%D
+%D The first application of objects in \CONTEXT\ concerned
+%D \METAPOST\ graphics and fill||in form fields. The first
+%D application can save lots of bytes, while the latter use is
+%D more a necessity than byte saving.
+%D
+%D \starttyping
+%D \setobject{class}{name}\somebox{}
+%D \getobject{class}{name}
+%D \stoptyping
+%D
+%D Here \type{\somebox} can be whatever box specification suits
+%D \TEX. We save the dimensions of an object, although some
+%D drivers will do so themselves. This means that when for
+%D instance using \PDFTEX\ we could save a hash entry plus some
+%D 20+ memory locations per object by delegating this
+%D housekeeping to the driver. The current approach permits
+%D us to keep the box characteristic too.
+
+\newif\ifinobject
+
+\def\objectplaceholder{NOT YET FLUSHED}%
+
+\def\presetobject#1#2% \global added
+ {\ifcsname\r!object#1::#2\endcsname\else
+ \global\@EA\let\csname\r!object#1::#2\endcsname\objectplaceholder
+ \fi}
+
+\def\dosetobject#1#2#3% \initializepaper this will move to \everyshipout
+ {% \initializepaper
+ \ifcsname\r!object#2::#3\endcsname
+ \expandafter\gobblefivearguments
+ \else % tzt, overload internal referenced objects to save entries
+ \expandafter\dodosetobject
+ \fi
+ {#1}{#2}{#3}}
+
+\def\resetobject#1#2%
+ {\letbeundefined{\r!object#1::#2}}
+
+%D \macros
+%D {finalizeobjectbox}
+%D
+%D This one provides a hook for last minute object box processing
+%D we need this in \MKIV.
+
+\ifx\finalizeobjectbox\undefined
+ \let\finalizeobjectbox\gobbleoneargument
+\fi
+
+%D Somehow there is a rounding error problem in either \PDFTEX\
+%D or in viewers, or maybe it is conforming the specs. The next
+%D variable compensate for it by removing the rather tight
+%D clip.
+
+\def\objectoffset{1cm}
+
+\def\dodosetobject#1#2#3%
+ {\bgroup
+ \globalpushmacro\crossreferenceobject \objectreferenced
+ \inobjecttrue
+ \dowithnextbox
+ {\globalpopmacro\crossreferenceobject
+ \dododosetobject{#1}{#2}{#3}\egroup}}
+
+\def\dododosetobject#1#2#3%
+ {\begingroup
+ \dontshowcomposition % rather fuzzy in \setxvalue ... \hbox
+ \scratchdimen\objectoffset
+ \@EA\xdef\csname\r!object#2::#3\endcsname
+ {\noexpand\dohandleobject{#2}{#3}%
+ {\ifhbox\nextbox\hbox\else\vbox\fi}%
+ {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}%
+ {\number\scratchdimen}}%
+ \expanded % freeze the dimensions since \dostartobject may use \nextbox
+ {\dostartobject{#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
+ \ifcase#1\relax\else \ifdim\objectoffset>\zeropoint
+ \setbox\nextbox\vbox spread 2\scratchdimen
+ {\forgetall \offinterlineskip
+ \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}%
+ \fi \fi
+ \flushnextbox
+ \dostopobject
+ \endgroup}
+
+\def\getobject#1#2%
+ {\begingroup
+ \let\dohandleobject\dogetobject
+ \csname\r!object#1::#2\endcsname}
+
+\def\dogetobject#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf
+ {% \initializepaper
+ \forgetall
+ \dontshowcomposition
+ \setbox\scratchbox\vbox attr \viewerlayerattribute \attribute\viewerlayerattribute
+ {\doinsertobject{#1}{#2}}%
+ \setbox\scratchbox#3%
+ {\vbox to #5\scaledpoint
+ {\ifdim\ht\scratchbox>#5\scaledpoint
+ \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+ \else\ifdim\wd\scratchbox>#4\scaledpoint
+ \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss
+ \else
+ %\vss\box\scratchbox
+ \vss\hbox to #4\scaledpoint{\box\scratchbox\hss}% fix Chof
+ \fi\fi}}%
+% \forcecolorhack % needed in order to use layers etc
+ \box\scratchbox
+ \endgroup}
+
+%D If needed one can ask for the dimensions of an object with:
+%D
+%D \starttyping
+%D \getobjectdimensions{class}{name}
+%D \stoptyping
+%D
+%D The results are reported in \type {\objectwidth}, \type
+%D {\objectheight} and \type {\objectdepth}.
+
+\def\dogetobjectdimensions#1#2#3#4#5#6#7%
+ {\def\objectwidth {#4\s!sp}%
+ \def\objectheight{#5\s!sp}%
+ \def\objectdepth {#6\s!sp}%
+ \def\objectmargin{#7\s!sp}}
+
+\def\getobjectdimensions#1#2%
+ {\let\dohandleobject\dogetobjectdimensions
+ \let\objectwidth \!!zeropoint
+ \let\objectheight\!!zeropoint
+ \let\objectdepth \!!zeropoint
+ \csname\r!object#1::#2\endcsname}
+
+%D Apart from this kind of objects, that have typeset content,
+%D we can have low level driver specific objects. Both types
+%D can have references to internal representations, hidden for
+%D the user. We keep track of such references by means of a
+%D dedicated cross reference mechanism. Normally, objects are
+%D defined before they are used, but forward referencing
+%D sometimes occurs.
+%D
+%D \starttyping
+%D \dosetobjectreference {class} {identifier} {reference value} {page}
+%D \dogetobjectreference {class} {identifier} \csname
+%D \stoptyping
+%D
+%D These commands are to be called by the \type{\startobject},
+%D \type{\stopobject} and \type{\insertobject} specials.
+
+\def\objectreferenced{\global\chardef\crossreferenceobject\plusone}
+\def\driverreferenced{\global\chardef\crossreferenceobject\zerocount}
+
+\objectreferenced
+
+% no undefined test ! ! ! ! (pdftex fails on undefined objects)
+
+\def\doregisterobjectreference#1#2#3{\normalexpanded{\noexpand\ctxlatelua{jobobjects.save("#1::#2",#3,\noexpand\the\realpageno)}}}
+\def\dooverloadobjectreference#1#2#3{\ctxlua{jobobjects.set("#1::#2",#3,\the\realpageno)}}
+
+\def\dosetobjectreference
+ {\ifcase\crossreferenceobject
+ \objectreferenced
+ \expandafter\dooverloadobjectreference
+ \else
+ \expandafter\doregisterobjectreference
+ \fi}
+
+\def\dosetdriverreference
+ {\driverreferenced\dosetobjectreference}
+
+\def\defaultobjectreference#1#2{0} % driver dependent
+\def\defaultobjectpage #1#2{\realfolio}
+
+\def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{jobobjects.number("#1::#2","\defaultobjectreference{#1}{#2}")}}}
+\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{jobobjects.page("#1::#2","\defaultobjectpage{#1}{#2}")}}}
+
+\def\setobject {\driverreferenced\dosetobject1}
+\def\settightobject{\driverreferenced\dosetobject0}
+
+%D \macros
+%D {doifobjectfoundelse,doifobjectreferencefoundelse}
+%D
+%D To prevent redundant definition of objects, one can use
+%D the next tests:
+%D
+%D \starttyping
+%D \doifobjectfoundelse{class}{object}{do then}{do else}
+%D \doifobjectreferencefoundelse{class}{object}{do then}{do else}
+%D \stoptyping
+
+\def\doifobjectfoundelse#1#2%
+ {\ifcsname\r!object#1::#2\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifobjectreferencefoundelse#1#2{\ctxlua{jobobjects.doifelse("#1::#2")}}
+
+\protect \endinput
diff --git a/tex/context/base/pack-rul.lua b/tex/context/base/pack-rul.lua
new file mode 100644
index 000000000..378167c97
--- /dev/null
+++ b/tex/context/base/pack-rul.lua
@@ -0,0 +1,53 @@
+if not modules then modules = { } end modules ['pack-rul'] = {
+ version = 1.001,
+ comment = "companion to pack-rul.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+
An explanation is given in the history document mk.
+--ldx]]--
+
+local texdimen, texcount, texbox = tex.dimen, tex.count, tex.box
+local hpack, free, copy, traverse_id = node.hpack, node.free, node.copy_list, node.traverse_id
+
+function commands.doreshapeframedbox(n)
+ local noflines, lastlinelength, box = 0, 0, texbox[n]
+ if box.width ~= 0 then
+ local list = box.list
+ if list then
+ local width, done = 0, false
+ for h in traverse_id('hlist',list) do -- no dir etc needed
+ local l = h.list
+ if l then
+ done = true
+ local p = hpack(copy(l))
+ lastlinelength = p.width
+ if lastlinelength > width then
+ width = lastlinelength
+ end
+ free(p)
+ end
+ end
+ if done then
+ if width ~= 0 then
+ for h in traverse_id('hlist',list) do
+ local l = h.list
+ if l then
+ -- if h.width ~= width then -- else no display math handling (uses shift)
+ h.list = hpack(l,width,'exactly',h.dir)
+ h.shift = 0 -- needed for display math
+ h.width = width
+ -- end
+ end
+ end
+ end
+ box.width = width
+ end
+ end
+ end
+ texdimen["framedlastlength"] = lastlinelength
+ texcount["framednoflines"] = noflines
+end
diff --git a/tex/context/base/pack-rul.mkii b/tex/context/base/pack-rul.mkii
new file mode 100644
index 000000000..055094547
--- /dev/null
+++ b/tex/context/base/pack-rul.mkii
@@ -0,0 +1,3650 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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}
+
+\unprotect
+
+%D We have removed the rather old and out dated raster methods. They
+%D have not been used for ages.
+
+%D \macros
+%D {linewidth, setuplinewidth}
+%D
+%D This module deals with rules (lines) in several ways. First
+%D we introduce two macros that can be used to set some common
+%D characteristics.
+%D
+%D \showsetup{setuplinewidth}
+%D
+%D The linewidth is available in \type{\linewidth}. The
+%D preset value of .4pt equals the default hard coded \TEX\
+%D rule width.
+
+\newdimen\linewidth
+
+\def\dosetuplinewidth[#1]%
+ {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
+
+\def\setuplinewidth
+ {\dosingleargument\dosetuplinewidth}
+
+%D \macros
+%D {ruledlinewidth, inheritruledlinewidth}
+%D
+%D Inside framed boxed we will use a private dimensions. As
+%D an option one can let the linewidth inherit its value from
+%D this one.
+
+\newdimen\ruledlinewidth \newif\ifinheritruledlinewidth
+
+% %D \TEX\ lacks support for color and even gray scales. The next
+% %D macros can provide a sort of poor mans gray scales as well
+% %D as give access to more suitable methods of rendering. Such a
+% %D method looks like:
+% %D
+% %D \starttyping
+% %D \def\methodegraybox#1#2#3#4#5#6%
+% %D { ... }
+% %D \stoptyping
+% %D
+% %D The string \type{graybox} is a common element in the name,
+% %D so we can have for instance \type {\postscriptgraybox} or
+% %D \type {\texgraybox}. The first three arguments take a
+% %D dimension, the fourth one takes a number between~0 and~1,
+% %D and the last argument specifies a radius of the box when
+% %D rounded corners are used, so:
+% %D
+% %D \startbuffer
+% %D \dotgraybox{.5\hsize}{1cm}{0cm}{.85}{\v!no}{0pt}
+% %D \stopbuffer
+% %D
+% %D \typebuffer
+% %D
+% %D becomes:
+% %D
+% %D %\startlinecorrection
+% %D % \vbox to 1cm{\getbuffer}
+% %D %\stoplinecorrection
+% %D
+% %D \startlinecorrection
+% %D \unprotect
+% %D \vbox to 1cm{\dotgraybox{.5\hsize}{1cm}{0cm}{.85}{\v!no}{0pt}}
+% %D \protect
+% %D \stoplinecorrection
+% %D
+% %D There are two predefined methodes, one uses periods and the
+% %D other uses small rules. The second method is less
+% %D efficient, but sometimes give better results. The dimensions
+% %D of the resullting box are set to zero.
+%
+% \setvalue{\v!dot graybox}{\processraster\symbol\rasterdot}
+% \setvalue{\v!rule graybox}{\processraster\symbol\rasterbox}
+%
+% \def\rasterdot{\rasterfont.}
+% \def\rasterbox{\hss\vrule\!!width.4pt\!!height.4pt\!!depth\zeropoint}
+%
+% %D Now of course we need:
+%
+% \ifx\rasterfont\undefined \def\rasterfont{\fivepoint} \fi
+%
+% %D We implement two pure \TEX\ based generators, that use
+% %D \type{\leaders} to quickly gerenate the gray pattern. One
+% %D should beware of \DIMENSION\ conflicts, so we use some
+% %D registers above~8. These macros are memory hungry and byte
+% %D spoiling.
+%
+% \def\processraster#1#2#3#4#5#6#7%
+% {\bgroup
+% \forgetall
+% \dontcomplain
+% \dimen10=\onepoint
+% \dimen10=\@@rsfactor\dimen10
+% \dimen10=#5\dimen10
+% \setbox2\hbox to #2
+% {\cleaders\hbox to 2\dimen10{#1\hss}\hss}%
+% \dimen12=#3%
+% \advance\dimen12 #4%
+% % \setbox0\vbox to \dimen12
+% {\cleaders\vbox to 2\dimen10{\box2\vss}\vss}%
+% \setbox0\hbox
+% {\hskip-.5\dimen10\lower0.5\dimen10\copy0
+% \hskip-\wd0\hskip\dimen10\lower1.5\dimen10\box0}%
+% \box0
+% \egroup}
+
+%D \macros
+%D {setupscreens}
+%D
+%D The previous macro uses a predefined constant
+%D \type{\@@rsfactor}. This factor can be set by:
+%D
+%D \showsetup{setupscreens}
+
+\def\setupscreens
+ {\dodoubleargument\getparameters[\??rs]}
+
+% %D The most appropriate way to call for this feature is
+% %D using \type{\graybox}, which is defined as:
+%
+% \def\graybox{\getvalue{\@@rsmethod graybox}}
+%
+% %D We just introduced two pure \TEX\ methods for generating
+% %D rasters. However, it's far more efficient and comfortable in
+% %D terms of speed, memory usage and file size, to use a driver
+% %D supported method.
+%
+% \setvalue{\v!external graybox}{\setgraybox}
+%
+% %D For compatibility reasons we also define the original one:
+%
+% \setvalue{\v!postscript graybox}{\getvalue{\v!external graybox}}
+%
+% %D A quite valid way of letting drivers do the job, is giving
+% %D a solid rule a gray texture.
+
+%D We will communicate through module specific variables, current
+%D framed parameters and some reserved dimension registers.
+
+\newdimen \frameddimenwd
+\newdimen \frameddimenht
+\newdimen \frameddimendp
+
+%D We don't have to stick to a \TEX\ drawn rule, but
+%D also can use rounded or even fancier shapes, as we will
+%D see later on.
+
+\def\dofilledbox
+ {\bgroup
+ \doifelse{\framedparameter\c!backgroundcorner}\v!rectangular
+ {\dofilledlinedbox}
+ {\ifzeropt\dimexpr\framedparameter\c!backgroundradius\relax % just in case of .x\bodyfontsize
+ \dofilledlinedbox
+ \else
+ \dofilledroundbox
+ \fi}%
+ \egroup}
+
+\def\dophantombox
+ {\hphantom{\dofilledbox}}
+
+\def\dofilledlinedbox
+ {\vrule\!!width\frameddimenwd\!!height\frameddimenht\!!depth\frameddimendp\relax}%
+
+\def\dostrokedroundbox
+ {\doif{\framedparameter\c!frame}\v!on\dodostrokedroundbox}
+
+\def\dodostrokedroundbox
+ {\bgroup
+ \edef\ovalmod{\framedparameter\c!framecorner}%
+ \doifelse\ovalmod\v!round{\let\ovalmod\!!zerocount}{\edef\ovalmod{\number\ovalmod}}%
+ \edef\ovalwid{\the\frameddimenwd}%
+ \edef\ovalhei{\the\frameddimenht}%
+ \edef\ovaldep{\the\frameddimendp}%
+ \edef\ovallin{\the\dimexpr\ruledlinewidth}%
+ \edef\ovalrad{\the\dimexpr\framedparameter\c!frameradius}%
+ \let\ovalstr\!!plusone
+ \let\ovalfil\!!zerocount
+ \forcecolorhack
+ \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod
+ \egroup}
+
+\def\dofilledroundbox
+ {\bgroup
+ \edef\ovalmod{\framedparameter\c!backgroundcorner}%
+ \doifelse\ovalmod\v!round{\let\ovalmod\!!zerocount}{\edef\ovalmod{\number\ovalmod}}%
+ \edef\ovalwid{\the\frameddimenwd}%
+ \edef\ovalhei{\the\frameddimenht}%
+ \edef\ovaldep{\the\frameddimendp}%
+ \edef\ovallin{\the\dimexpr\ruledlinewidth\relax}%
+ \edef\ovalrad{\the\dimexpr\framedparameter\c!backgroundradius\relax}%
+ \let\ovalstr\!!zerocount
+ \let\ovalfil\!!plusone
+ \forcecolorhack
+ \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod
+ \egroup}
+
+% 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 The oval box is drawn using a special macro, depending on
+%D the driver in use.
+
+\def\dograybox % avoid black rules when no gray
+ {\doifelsenothing{\framedparameter\c!backgroundscreen}
+ {\dophantombox}
+ {\raster[\framedparameter\c!backgroundscreen]{\dofilledbox}}}
+
+%D It won't be a surprise that we not only provide gray boxes,
+%D but also colored ones. Here it is:
+
+\def\docolorbox
+ {\hbox{\ifincolor
+ \doifcolorelse{\framedparameter\c!backgroundcolor}
+ {\localcolortrue\color[\framedparameter\c!backgroundcolor]{\dofilledbox}}
+ {\dophantombox}%
+ \else
+ \dophantombox
+ \fi}}
+
+%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
+%D backgrounds, we introduce overlays. An overlay is something
+%D that contrary to its name lays {\em under} the text. An
+%D 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
+%D non||used arguments and the two step call that enable the
+%D setting of the width, height and depth variables.
+%D 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
+%D the dimensions have a 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
+\let\overlaydepth \!!zeropoint % values. The attributes
+\let\overlayoffset \!!zeropoint % of the frame can be (are)
+\let\overlaycolor \empty % set somewhere else.
+\let\overlaylinewidth \!!zeropoint %
+\let\overlaylinecolor \empty %
+
+%D The next register is used to initialize overlays.
+
+\newtoks\everyoverlay
+
+%D An example of an initialization is the following (overlays
+%D can contain text and be executed under an regime where
+%D interlineskip is off).
+
+\appendtoks \oninterlineskip \to \everyoverlay
+
+\def\defineoverlay
+ {\dodoubleargument\dodefineoverlay}
+
+\def\dodefineoverlay[#1][#2]%
+ {\def\docommand##1{\setvalue{\??ov##1}{\executedefinedoverlay{##1}{#2}}}%
+ \processcommalist[#1]\docommand}
+
+\prependtoks
+ \hsize\overlaywidth
+ \vsize\overlayheight
+\to\everyoverlay
+
+\long\def\executedefinedoverlay#1#2%
+ {\bgroup
+ \edef\overlaywidth {\the\frameddimenwd\space}%
+ \edef\overlayheight{\the\dimexpr\frameddimenht+\frameddimendp\relax\space}%
+ \edef\overlaydepth {\the\frameddimendp\space}%
+ \edef\overlaycolor {\framedparameter\c!backgroundcolor}%
+ %\edef\overlaycorner{\framedparameter\c!backgroundcorner}%
+ %\edef\overlayradius{\framedparameter\c!backgroundradius}%
+ \let\overlayoffset\backgroundoffset % we steal this one
+ \setbox\scratchbox\hbox{\lower\overlaydepth\hbox{\the\everyoverlay#2}}%
+ \setbox\scratchbox\hbox
+ {\hskip-.5\dimexpr\wd\scratchbox-\overlaywidth \relax
+ \raise-.5\dimexpr\ht\scratchbox-\frameddimenht\relax % not overlayheight !
+ \box\scratchbox}%
+ \wd\scratchbox\overlaywidth
+ \ht\scratchbox\overlayheight
+ \dp\scratchbox\overlaydepth
+ \startlayoutcomponent{o:#1}{overlay #1}%
+ \box\scratchbox
+ \stoplayoutcomponent
+ \egroup}
+
+%D The empty case is:
+
+\let\executeoverlay\gobblesevenarguments
+
+%D For testing we provide:
+
+\def\doifoverlayelse#1%
+ {\doifdefinedelse{\??ov#1}}
+
+%D We predefine two already familiar backgrounds:
+
+\setvalue{\??ov\v!screen}{\dograybox }
+\setvalue{\??ov\v!color }{\docolorbox}
+
+% %D After all these preparations, the background macro does no
+% %D bring to many surprises. One has to keep in mind that this
+% %D macro starts up a call chain, depending on the background
+% %D one needs:
+% %D
+% %D \startitemize[packed]
+% %D \item a raster, color or user defined shape
+% %D \item square or round corners
+% %D \item a \TEX\ or driver based method
+% %D \stopitemize
+% %D
+% %D The macro can be extended by adding commands to the token
+% %D list register \type {\everybackgroundbox}. For this
+% %D purpose, the name of the current background is available in
+% %D \type {\currentbackgound}.
+
+%D The content of the box will be (temporary) saved in a box. We
+%D also have an extra box for backgrounds.
+
+\newbox\framebox
+\newbox\extraframebox
+
+\newtoks\everybackgroundbox
+
+\let\currentbackground\empty
+
+% \def\dodobackgroundbox#1% also less passing, we can get rid of the old method
+% {\bgroup
+% \def\currentbackground{#1}%
+% \the\everybackgroundbox
+% \setbox\extraframebox\hbox
+% {\vbox{\moveleft\backgroundoffset\hbox{\executeifdefined{\??ov\currentbackground}\donothing}}}%
+% \wd\extraframebox\zeropoint % \backgroundwidth
+% \ht\extraframebox\backgroundheight
+% \dp\extraframebox\backgrounddepth
+% \box\extraframebox % \hskip-\backgroundwidth
+% \egroup}
+
+% \def\dodobackgroundbox#1% also less passing, we can get rid of the old method
+% {\bgroup
+% \def\currentbackground{#1}%
+% \ifcsname\??ov\currentbackground\endcsname
+% \the\everybackgroundbox
+% \setbox\extraframebox\hbox{\vbox{\moveleft\backgroundoffset\hbox{\csname\??ov\currentbackground\endcsname}}}%
+% \wd\extraframebox\zeropoint % \backgroundwidth
+% \ht\extraframebox\backgroundheight
+% \dp\extraframebox\backgrounddepth
+% \box\extraframebox % \hskip-\backgroundwidth
+% \fi
+% \egroup}
+
+\def\dodobackgroundbox
+ {\bgroup
+ \ifcsname\??ov\currentbackground\endcsname
+ \the\everybackgroundbox
+ \setbox\extraframebox\hbox{\vbox{\moveleft\backgroundoffset\hbox{\csname\??ov\currentbackground\endcsname}}}%
+ \wd\extraframebox\zeropoint % \backgroundwidth
+ \ht\extraframebox\backgroundheight
+ \dp\extraframebox\backgrounddepth
+ \box\extraframebox % \hskip-\backgroundwidth
+ \fi
+ \egroup}
+
+\def\dododobackgroundbox#1,#2% #2 gobbles spaces
+ {\edef\currentbackground{#1}%
+ \ifx\currentbackground\s!unknown\else
+ \dodobackgroundbox\expandafter\dododobackgroundbox
+ \fi#2}
+
+\let\backgroundoffset\!!zeropoint
+\let\backgrounddepth \!!zeropoint
+\def\backgroundwidth {\the\hsize}
+\def\backgroundheight{\the\vsize}
+
+% todo: also \def\theforegroundbox{#1}
+
+% \def\dobackgroundbox#1%
+% {\setbox\framebox\vbox
+% {\forgetall
+% \boxmaxdepth\maxdimen
+% \scratchdimen \framedparameter{#1}\relax
+% \frameddimenwd\dimexpr\wd\framebox+2\scratchdimen\relax
+% \frameddimenht\dimexpr\ht\framebox+ \scratchdimen\relax
+% \frameddimendp\dimexpr\dp\framebox+ \scratchdimen+\framedparameter\c!backgrounddepth\relax
+% \edef\backgroundoffset{\the\scratchdimen}%
+% \edef\backgroundwidth {\the\wd\framebox}%
+% \edef\backgroundheight{\the\ht\framebox}%
+% \edef\backgrounddepth {\the\dp\framebox}%
+% %\edef\foregroundbox{\box#1}%
+% \def\foregroundbox% fuzzy but needed hack, this \vss, otherwise
+% {\vbox to \backgroundheight{\vss\box\framebox\vss}}% vertical shift
+% \edef\component{\framedparameter\c!component}%
+% \hbox to \backgroundwidth % in case 'foreground' is used as overlay
+% {\ifx\component\empty
+% \rawprocesscommalist[\framedbackground]\dodobackgroundbox
+% \else
+% \startlayoutcomponent{b:\component}{\s!background\space\component}%
+% \rawprocesscommalist[\framedbackground]\dodobackgroundbox
+% \stoplayoutcomponent
+% \fi
+% \box\framebox\hss}}}
+
+\def\normalforegroundbox% fuzzy but needed hack, this \vss, otherwise
+ {\vbox to \backgroundheight{\vss\box\framebox\vss}}% vertical shift
+
+\def\dobackgroundbox#1%
+ {\setbox\framebox\vbox
+ {\forgetall
+ \boxmaxdepth\maxdimen
+ \scratchdimen \framedparameter{#1}\relax
+ \frameddimenwd\dimexpr\wd\framebox+2\scratchdimen\relax
+ \frameddimenht\dimexpr\ht\framebox+ \scratchdimen\relax
+ \frameddimendp\dimexpr\dp\framebox+ \scratchdimen+\framedparameter\c!backgrounddepth\relax
+ \edef\backgroundoffset{\the\scratchdimen}%
+ \edef\backgroundwidth {\the\wd\framebox}%
+ \edef\backgroundheight{\the\ht\framebox}%
+ \edef\backgrounddepth {\the\dp\framebox}%
+ %\edef\foregroundbox{\box#1}%
+ \edef\component{\framedparameter\c!component}%
+ \let\foregroundbox\normalforegroundbox
+ \hbox to \backgroundwidth % in case 'foreground' is used as overlay
+ {\ifx\component\empty
+ \expanded{\dododobackgroundbox\framedparameter\c!background},\s!unknown,\relax
+ \else
+ \startlayoutcomponent{b:\component}{background \component}%
+ \expanded{\dododobackgroundbox\framedparameter\c!background},\s!unknown,\relax
+ \stoplayoutcomponent
+ \fi
+ \box\framebox\hss}}}
+
+%D One can explictly insert the foreground box. For that
+%D purpose we introduce the overlay \type {foreground}.
+
+\defineoverlay[\v!foreground][\foregroundbox]
+
+%D We can specify overlays as a comma separated list of
+%D overlays, a sometimes handy feature.
+
+%D Besides backgrounds (overlays) we also need some macros to
+%D draw outlines (ruled borders). Again we have to deal with
+%D square and round corners. The first category can be handled
+%D by \TEX\ itself, the latter one depends on the driver. This
+%D macro also support a negative offset.
+
+\ifx\scratchoffset\undefined \newdimen\scratchoffset \fi
+
+\def\dooutlinebox % we needed to move the color command in order to apply attributes properly
+ {\setbox\framebox\vbox % rules on top of box
+ {\scratchoffset \framedparameter\c!frameoffset\relax
+ \frameddimenwd\dimexpr\wd\framebox+2\scratchoffset\relax
+ \frameddimenht\dimexpr\ht\framebox+ \scratchoffset\relax
+ \frameddimendp\dimexpr\dp\framebox+ \scratchoffset+\framedparameter\c!framedepth\relax
+ \ifdim\frameddimendp<\zeropoint
+ \advance\frameddimenht \frameddimendp
+ \scratchdimen-\frameddimendp
+ \frameddimendp\zeropoint
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \setbox\extraframebox\hbox
+ {\doifsomething{\framedparameter\c!framecolor}{\color[\framedparameter\c!framecolor]}{\dostrokedbox}}%
+ \setbox\extraframebox\hbox
+ {\raise\scratchdimen\vbox
+ {\moveleft\scratchoffset
+ \box\extraframebox}}%
+ \wd\extraframebox\wd\framebox
+ \ht\extraframebox\ht\framebox
+ \dp\extraframebox\dp\framebox
+ \hbox{\box\framebox\hskip-\wd\extraframebox\box\extraframebox}}}
+
+\def\dostrokedbox
+ {\doifelse{\framedparameter\c!framecorner}\v!rectangular
+ {\dostrokedlinedbox}
+ {\ifzeropt\dimexpr\framedparameter\c!frameradius\relax % just in case of .x\bodyfontsize
+ \dostrokedlinedbox
+ \else
+ \dostrokedroundbox
+ \fi}}
+
+\def\dostrokedlinedbox
+ {\setbox\scratchbox\null
+ \wd\scratchbox\frameddimenwd
+ \ht\scratchbox\frameddimenht
+ \dp\scratchbox\frameddimendp
+ \setbox\scratchbox\vbox \bgroup
+ \csname t\@@frame@@\framedparameter\c!frame\framedparameter\c!topframe \endcsname
+ \hbox \bgroup
+ \csname l\@@frame@@\framedparameter\c!frame\framedparameter\c!leftframe \endcsname
+ \box\scratchbox
+ \csname r\@@frame@@\framedparameter\c!frame\framedparameter\c!rightframe \endcsname
+ \egroup
+ \csname b\@@frame@@\framedparameter\c!frame\framedparameter\c!bottomframe\endcsname
+ \egroup
+ \wd\scratchbox\frameddimenwd
+ \ht\scratchbox\frameddimenht
+ \dp\scratchbox\frameddimendp
+ \box\scratchbox}
+
+\def\@@frame@@{@@frame@@}
+
+% \setvalue{t\@@frame@@\v!on \v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{t\@@frame@@\v!off\v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{t\@@frame@@\v!on }{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!on }{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!on \v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!off\v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!on }{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!on }{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+
+\def\@@frame@@trule{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+\def\@@frame@@brule{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+\def\@@frame@@rrule{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+\def\@@frame@@lrule{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+
+\letvalue{t\@@frame@@\v!on \v!on}\@@frame@@trule
+\letvalue{t\@@frame@@\v!off\v!on}\@@frame@@trule
+\letvalue{t\@@frame@@\v!on }\@@frame@@trule
+
+\letvalue{b\@@frame@@\v!on \v!on}\@@frame@@brule
+\letvalue{b\@@frame@@\v!off\v!on}\@@frame@@brule
+\letvalue{b\@@frame@@\v!on }\@@frame@@brule
+
+\letvalue{l\@@frame@@\v!on \v!on}\@@frame@@lrule
+\letvalue{l\@@frame@@\v!off\v!on}\@@frame@@lrule
+\letvalue{l\@@frame@@\v!on }\@@frame@@lrule
+
+\letvalue{r\@@frame@@\v!on \v!on}\@@frame@@rrule
+\letvalue{r\@@frame@@\v!off\v!on}\@@frame@@rrule
+\letvalue{r\@@frame@@\v!on }\@@frame@@rrule
+
+% no overlapping rules
+
+\def\@@frame@@trules{\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}\nointerlineskip\kern-\ruledlinewidth}
+\def\@@frame@@brules{\kern-\ruledlinewidth\nointerlineskip\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}}
+\def\@@frame@@rrules{\kern-\ruledlinewidth\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth}
+\def\@@frame@@lrules{\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth\kern-\ruledlinewidth}
+
+% small is relatively new
+
+\letvalue{t\@@frame@@\v!small\v!small}\@@frame@@trules
+\letvalue{t\@@frame@@\v!off \v!small}\@@frame@@trules
+\letvalue{t\@@frame@@\v!small }\@@frame@@trules
+
+\letvalue{b\@@frame@@\v!small\v!small}\@@frame@@brules
+\letvalue{b\@@frame@@\v!off \v!small}\@@frame@@brules
+\letvalue{b\@@frame@@\v!small }\@@frame@@brules
+
+\letvalue{l\@@frame@@\v!small\v!small}\@@frame@@lrules
+\letvalue{l\@@frame@@\v!off \v!small}\@@frame@@lrules
+\letvalue{l\@@frame@@\v!small }\@@frame@@lrules
+
+\letvalue{r\@@frame@@\v!small\v!small}\@@frame@@rrules
+\letvalue{r\@@frame@@\v!off \v!small}\@@frame@@rrules
+\letvalue{r\@@frame@@\v!small }\@@frame@@rrules
+
+%D I condidered using the low level support command
+%D \type{\ruledhbox}, but this would slow down processing by a
+%D factor~3.
+
+% \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
+%D \CONTEXT. They deal with putting rules around boxes, provide
+%D backgrounds, offer alignment features, and some more. We
+%D start with defining some booleans. These give an impression
+%D of what we are going to take into account.
+
+% todo: chardefs
+
+\newif\ifboxhasoffset
+\newif\ifboxhaswidth
+\newif\ifboxhasheight
+\newif\ifboxhasformat
+\newif\ifboxhasstrut
+\newif\ifboxisoverlaid
+\newif\ifboxhasframe
+\newif\ifdelayedstrut
+
+%D We also need a few \DIMENSIONS:
+
+\newdimen\@@localoffset
+\newdimen\@@globalwidth
+
+%D \macros
+%D {framed, setupframed}
+%D
+%D Ruled boxes are typeset using \type{\framed}. This command
+%D is quite versatile and, although some users will probably
+%D seldom use it, one cannot overlook its features.
+%D
+%D \showsetup{setupframed}
+%D \showsetup{framed}
+%D
+%D This general macro is a special version of an even more
+%D general case, that can easily be linked into other macros
+%D that need some kind of framing. The local version is called
+%D with an extra parameter: the variable identifier. The reason
+%D for passing this identifier between brackets lays in the
+%D mere fact that this way we can use the optional argument
+%D grabbers.
+
+\def\defaultframeoffset{.25ex}
+
+\unexpanded\def\framed
+ {\bgroup
+ \copylocalframed[\??ol][\??oi]% == \presetlocalframed[\??ol]%
+ \dodoubleempty\startlocalframed[\??ol]}
+
+\def\presetlocalframed[#1]%
+ {\copylocalframed[#1][\??oi]}
+
+% \def\copylocalframed[#1]#2[#3]%
+% {\copyparameters[#1][#3]%
+% [\c!width,\c!height,\c!radius,\c!corner,\c!depth,\c!offset,%
+% \c!autowidth,\c!empty,\c!component,\c!orientation,\c!lines,%
+% \c!align,\c!bottom,\c!top,\c!strut,\c!autostrut,\c!location,\c!setups,\c!extras,%
+% \c!foregroundstyle,\c!foregroundcolor,%
+% \c!background,\c!backgroundoffset,\c!backgroundcorner,\c!backgroundradius,\c!backgrounddepth,\c!backgroundcolor,\c!backgroundscreen,%
+% \c!frame,\c!frameoffset,\c!framecorner,\c!frameradius,\c!framedepth,\c!framecolor,\c!rulethickness,%
+% \c!topframe,\c!bottomframe,\c!leftframe,\c!rightframe]}
+
+% since framed is used all over the place, we have a (small) speedup)
+
+\def\copylocalframed[#1]#2[#3]%
+ {\edef\copiedfrom{#1}\edef\copiedto{#3}%
+ \docopyvalue\copiedfrom\copiedto\c!width
+ \docopyvalue\copiedfrom\copiedto\c!height
+ \docopyvalue\copiedfrom\copiedto\c!autowidth
+ \docopyvalue\copiedfrom\copiedto\c!offset
+ \docopyvalue\copiedfrom\copiedto\c!empty
+ \docopyvalue\copiedfrom\copiedto\c!rulethickness
+ \docopyvalue\copiedfrom\copiedto\c!radius
+ \docopyvalue\copiedfrom\copiedto\c!corner
+ \docopyvalue\copiedfrom\copiedto\c!depth
+ \docopyvalue\copiedfrom\copiedto\c!frame
+ \docopyvalue\copiedfrom\copiedto\c!framecolor
+ \docopyvalue\copiedfrom\copiedto\c!foregroundstyle
+ \docopyvalue\copiedfrom\copiedto\c!foregroundcolor
+ \docopyvalue\copiedfrom\copiedto\c!lines
+ \docopyvalue\copiedfrom\copiedto\c!orientation
+ \docopyvalue\copiedfrom\copiedto\c!topframe
+ \docopyvalue\copiedfrom\copiedto\c!bottomframe
+ \docopyvalue\copiedfrom\copiedto\c!leftframe
+ \docopyvalue\copiedfrom\copiedto\c!rightframe
+ \docopyvalue\copiedfrom\copiedto\c!rulethickness
+ \docopyvalue\copiedfrom\copiedto\c!frameoffset
+ \docopyvalue\copiedfrom\copiedto\c!background
+ \docopyvalue\copiedfrom\copiedto\c!component
+ \docopyvalue\copiedfrom\copiedto\c!backgroundoffset
+ \docopyvalue\copiedfrom\copiedto\c!backgroundscreen
+ \docopyvalue\copiedfrom\copiedto\c!backgroundcolor
+ \docopyvalue\copiedfrom\copiedto\c!align
+ \docopyvalue\copiedfrom\copiedto\c!bottom
+ \docopyvalue\copiedfrom\copiedto\c!top
+ \docopyvalue\copiedfrom\copiedto\c!strut
+ \docopyvalue\copiedfrom\copiedto\c!autostrut
+ \docopyvalue\copiedfrom\copiedto\c!location
+ \docopyvalue\copiedfrom\copiedto\c!component
+ \docopyvalue\copiedfrom\copiedto\c!extras
+ \docopyvalue\copiedfrom\copiedto\c!setups
+ \docopyvalue\copiedfrom\copiedto\c!backgroundradius
+ \docopyvalue\copiedfrom\copiedto\c!backgroundcorner
+ \docopyvalue\copiedfrom\copiedto\c!backgrounddepth
+ \docopyvalue\copiedfrom\copiedto\c!frameradius
+ \docopyvalue\copiedfrom\copiedto\c!framecorner
+ \docopyvalue\copiedfrom\copiedto\c!framedepth}
+
+\def\setupframed
+ {\dodoubleempty\dosetupframed}
+
+\def\dosetupframed
+ {\ifsecondargument
+ \@EA\dodoublesetupframed
+ \else
+ \@EA\dosinglesetupframed
+ \fi}
+
+\def\dosinglesetupframed[#1][#2]%
+ {\getparameters[\??oi][#1]}
+
+\def\dodoublesetupframed[#1][#2]%
+ {\bgroup
+ \let\dodoubleempty\empty
+ \def\doframed[##1]{\gdef\globalredefinedframed{\dodoubleempty\doframed[##1,#2]}}%
+ \getvalue{#1}%
+ \egroup
+ \letvalue{#1}\globalredefinedframed}
+
+%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 \setuplocalframed[myframed][width=4cm,height=2cm]
+%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
+%D looking for the user supplied ones. The first step is
+%D omitted in the local case, because these are preset at
+%D declaration time and keep their values unless explictly
+%D changed. By presetting the variables everytime the normal
+%D command is called, we can use this command nested, without
+%D the unwanted side effect of inheritance. The boolean is
+%D used to speed up the color stack.
+
+\newif\ifinframed
+
+\def\localframed
+ {\bgroup
+ \dodoubleempty\startlocalframed}
+
+%D The next one is faster on multiple backgrounds per page. No
+%D dimensions can be set, only frames and backgrounds.
+
+\def\fastlocalframed[#1]#2[#3]#4% 3-4
+ {\bgroup
+ \inframedtrue
+ \edef\@@framed{#1}%
+ % more bytes
+ % \scratchdimen\framedparameter\c!frameoffset
+ % \setevalue{\@@framed\c!frameoffset}{\the\scratchdimen}%
+ % \doifnotvalue{\@@framed\c!backgroundoffset}\v!frame
+ % {\scratchdimen\framedparameter\c!backgroundoffset
+ % \setevalue{\@@framed\c!backgroundoffset}{\the\scratchdimen}}%
+ % less bytes
+ \@EA\freezedimenmacro\csname\@@framed\c!frameoffset\endcsname
+ \doifnotvalue{\@@framed\c!backgroundoffset}\v!frame
+ {\@EA\freezedimenmacro\csname\@@framed\c!backgroundoffset\endcsname}%
+ % so far
+ \setbox\framebox\hbox{#4}%
+ \getparameters[\@@framed][#3]% no \expanded !
+ % no, better in calling macro
+ %
+ % \edef\doframedsetups{\framedparameter\c!setups}%
+ % \ifx\doframedsetups\empty\else
+ % \edef\doframedsetups{\noexpand\setups[\doframedsetups]}%
+ % \fi
+ \removeframedboxdepth
+ \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}%
+ \ifx\framedforegroundcolor\empty\else\docolorframebox\fi
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}%
+ \edef\overlaylinewidth{\the\ruledlinewidth}%
+ \edef\@@localframing {\framedparameter\c!frame}%
+ \ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else
+ \edef\framedrulethickness{\framedparameter\c!rulethickness}%
+ \ifx\framedrulethickness\empty\else
+ \ruledlinewidth\framedrulethickness\relax
+ \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \fi
+ \dooutlinebox % real or invisible frame
+ \fi \fi
+ \edef\framedbackground{\framedparameter\c!background}%
+ \ifx\framedbackground\empty\else\dobackedbox\fi
+ \restoreframedboxdepth
+ \box\framebox
+ \egroup}
+
+%D Before we go into details, we present (and implement) the
+%D main framing routine. I saw no real reason for splitting the
+%D next two macros into smaller pieces. The content will be
+%D collected in a horizontal or vertical box with fixed or free
+%D dimensions and specific settings concerning aligment and
+%D offsets.
+%D
+%D In the first few lines, we pre||expand the frame and
+%D background offsets. We do so, because the can be defined in
+%D terms of the main offset. However, see for instance page
+%D backgrounds, when \type {#2} sets the offset to \type
+%D {overlay}, both offsets become invalid.
+%D
+%D Because it is used so often the he next macro is (and
+%D looks) rather optimized.
+
+\let\postprocessframebox\relax
+
+\let\@@framed\s!unknown
+
+\def\framedparameter#1%
+ {\csname\@@framed#1\endcsname}
+
+\newdimen\!!framedwidth
+\newdimen\!!framedheight
+
+\def\startlocalframed[#1][#2]%
+ {\bgroup
+ \inframedtrue
+ \edef\@@framed{#1}%
+ % this piece of pre expansion is needed (sometimes used in frameoffset)
+ % \doifvaluesomething{\@@framed\c!rulethickness} % obsolete
+ % {\ruledlinewidth\getvalue{\@@framed\c!rulethickness}}% obsolete
+ % this piece of pre expansion is needed (sometimes used circular)
+ \setevalue{\@@framed\c!frameoffset}{\the\dimexpr\framedparameter\c!frameoffset\relax}%
+ \doifnotvalue{\@@framed\c!backgroundoffset}\v!frame
+ {\setevalue{\@@framed\c!backgroundoffset}{\the\dimexpr\framedparameter\c!backgroundoffset\relax}}%
+ % to prevent deadlock in case of self refering
+ \ifsecondargument % faster
+ \getparameters[\@@framed][#2]% here !
+ \fi
+ % new, experimental dirty hook
+ \framedparameter\c!extras
+ % to get the right spacing
+ \doifvaluesomething{\@@framed\c!foregroundstyle}
+ {\@EA\doconvertfont\csname\@@framed\c!foregroundstyle\endcsname\empty}%
+ % beware, both the frame and background offset can be overruled
+ %
+ \edef\doframedsetups{\framedparameter\c!setups}%
+ \ifx\doframedsetups\empty\else
+ \edef\doframedsetups{\noexpand\setups[\doframedsetups]}%
+ \fi
+ % 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\@@localautostrut {\framedparameter\c!autostrut}%
+ \edef\@@localframing {\framedparameter\c!frame}%
+ \edef\@@locallocation {\framedparameter\c!location}%
+ \edef\@@localorientation{\framedparameter\c!orientation}%
+ %
+ \edef\@@localautowidth {\framedparameter\c!autowidth}%
+ %
+ \ifx\@@localframing\v!overlay % no frame, no offset, no framewidth
+ \boxhasframefalse
+ \let\localoffset\v!overlay
+ \else\ifx\@@localframing\v!none % no frame, no framewidth
+ \boxhasframefalse
+ \else
+ \boxhasframetrue
+ \fi\fi
+ \ifboxhasframe
+ \edef\framedrulethickness{\framedparameter\c!rulethickness}%
+ \ifx\framedrulethickness\empty\else
+ \ruledlinewidth\framedrulethickness\relax
+ \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \fi
+ \else
+ \ruledlinewidth\zeropoint
+ \fi
+ \ifx\localformat\empty
+ \boxhasformatfalse
+ \else
+ \boxhasformattrue
+ \dosetraggedcommand\localformat
+ \edef\dobeforeframedbox{\raggedtopcommand\framedparameter\c!top}%
+ \edef\doafterframedbox {\framedparameter\c!bottom\raggedbottomcommand}%
+ \fi
+ \ifx\localoffset\v!none
+ \boxhasoffsetfalse
+ \boxhasstrutfalse
+ \boxisoverlaidfalse
+ \@@localoffset\ruledlinewidth
+ \else\ifx\localoffset\v!overlay
+ % \ifx\@@localframing\v!no \boxhasframefalse \fi % test first
+ \boxhasoffsetfalse
+ \boxhasstrutfalse
+ \boxisoverlaidtrue
+ \@@localoffset\zeropoint
+ \else
+ \boxhasoffsettrue
+ \boxhasstruttrue
+ \boxisoverlaidfalse
+ \ifx\localoffset\v!default % new per 2-6-2000
+ \let\localoffset\defaultframeoffset
+ \letvalue{\@@framed\c!offset}\defaultframeoffset
+ \else
+ \let\defaultframeoffset\localoffset
+ \fi
+ \@@localoffset\dimexpr\localoffset+\ruledlinewidth\relax
+ \fi\fi
+ \!!framedheight\zeropoint
+ \!!framedwidth \zeropoint
+ \ifx\localwidth\v!fit
+ \ifboxhasformat
+ \boxhaswidthtrue
+ \!!framedwidth\hsize
+ \else
+ \boxhaswidthfalse
+ \fi
+ \else\ifx\localwidth\v!fixed % equals \v!fit but no shapebox
+ \ifboxhasformat
+ \boxhaswidthtrue
+ \!!framedwidth\hsize
+ \else
+ \boxhaswidthfalse
+ \fi
+ \else\ifx\localwidth\v!broad
+ \boxhaswidthtrue
+ \!!framedwidth\hsize
+ \else\ifx\localwidth\v!local
+ \boxhaswidthtrue
+ \setlocalhsize
+ \!!framedwidth\localhsize
+ \else
+ \boxhaswidthtrue
+ \!!framedwidth\localwidth
+ \fi\fi\fi\fi
+ \ifx\localheight\v!fit
+ \boxhasheightfalse % no longer: \boxhasstrutfalse
+ \else\ifx\localheight\v!broad
+ \boxhasheightfalse
+ \else
+ \boxhasheighttrue
+ \!!framedheight\localheight
+ \fi\fi
+ \ifboxhasheight
+ % obey user set height, also downward compatible
+ \else
+ \doifvaluesomething{\@@framed\c!lines}
+ {\ifcase\framedparameter\c!lines\else
+ \!!framedheight\framedparameter\c!lines\lineheight
+ \edef\localheight{\the\!!framedheight}%
+ \boxhasheighttrue
+ \fi}%
+ \fi
+ % this is now an option: width=local
+ %
+ % \ifdim\!!framedwidth=\hsize
+ % \parindent\zeropoint
+ % \setlocalhsize
+ % \!!framedwidth\localhsize
+ % \fi
+ % i.e. disable (colsetbackgroundproblemintechniek)
+ \advance\!!framedwidth -2\@@localoffset
+ \advance\!!framedheight -2\@@localoffset
+ \ifx\localstrut\v!no
+ \boxhasstrutfalse
+ \else\ifx\localstrut\v!global
+ \setstrut
+ \else\ifx\localstrut\v!local
+ \setfontstrut
+ \else
+ \setstrut
+ \fi\fi\fi
+ \ifboxhasstrut
+ \let\localbegstrut\begstrut
+ \let\localendstrut\endstrut
+ \let\localstrut \strut
+ \else
+ \let\localbegstrut\pseudobegstrut % was: \relax
+ \let\localendstrut\pseudoendstrut % was: \relax
+ \let\localstrut \pseudostrut % was: \relax
+ %\ifboxhasheight\ifdim\!!framedheight<\strutht % saveguard
+ % \let\localbegstrut\relax % but not that
+ % \let\localstrut \relax % save after all
+ %\fi\fi
+ \fi
+ \ifx\@@localautostrut\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
+ \ifboxhasheight
+ \let\\\vboxednewline
+ \ifboxhaswidth
+ \let\hairline\vboxedhairline
+ \ifboxhasformat
+ \let\next\doformatboxSomeFormat
+ \else
+ \let\next\doformatboxNoFormat
+ \fi
+ \else
+ \let\hairline\hboxedhairline
+ \ifboxhasformat
+ \let\next\doformatboxHeight
+ \else
+ \let\next\doformatboxVSize
+ \fi
+ \fi
+ \else
+ \ifboxhaswidth
+ \ifboxhasformat
+ \let\hairline\vboxedhairline
+ \let\\\vboxednewline
+ \let\next\doformatboxWidth
+ \else
+ \let\hairline\hboxedhairline
+ \let\\\hboxednewline
+ \let\next\doformatboxHSize
+ \fi
+ \else
+ \let\hairline\hboxedhairline
+ \let\\\hboxednewline
+ \let\next\doformatboxNoSize
+ \fi
+ \fi
+ \edef\framedwidth % a new feature, visible for user
+ {\ifdim\!!framedwidth >\zeropoint\the\!!framedwidth \else\zeropoint\fi}%
+ \edef\framedheight% a new feature, visible for user
+ {\ifdim\!!framedheight>\zeropoint\the\!!framedheight\else\zeropoint\fi}%
+ % we need to register the (outer) color
+ \startregistercolor[\framedparameter\c!foregroundcolor]%
+ % first alternative
+ %\def\dowithframedbox%
+ % {\let\postprocessframebox\relax %new
+ % \aftergroup\stoplocalframed}%
+ % \afterassignment\dowithframedbox
+ % \setbox\framebox=\next}
+ % second alternative
+ %\dowithnextbox
+ % {\setbox\framebox\flushnextbox
+ % \let\postprocessframebox\relax %new
+ % \stoplocalframed}
+ % \next}
+ \@@startframedorientation
+ \afterassignment\dodowithframebox
+ \setbox\framebox\next}
+
+\def\dowithframebox
+ {% moved : \let\postprocessframebox\relax
+ \stoplocalframed}
+
+\def\dodowithframebox
+ {\aftergroup\dowithframebox}
+
+\let\doafterframedbox \relax
+\let\dobeforeframedbox\relax
+
+%D Carefull analysis of this macro will learn us that not all
+%D branches in the last conditionals can be encountered, that
+%D is, some assignments to \type{\next} will never occur.
+%D Nevertheless we implement the whole scheme, if not for
+%D future extensions.
+
+%D \macros
+%D {ifreshapeframebox}
+%D
+%D The last few lines tell what to do after the content of the
+%D box is collected and passed to the next macro. In the case
+%D of a fixed width and centered alignment, the content is
+%D evaluated and used to determine the most natural width. The
+%D rest 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
+
+\def\stoplocalframed
+ {\dontshowcomposition
+ \@@stopframedorientation % hm, wrong place ! should rotate the result (after reshape)
+ \stopregistercolor
+ \handleframedlocator\c!before\@@locallocation
+ \ifboxhasformat
+ \ifx\@@localautowidth\v!force
+ \ifreshapeframebox\doreshapeframedbox\fi
+ \boxhaswidthfalse
+ \else
+ \ifx\localwidth\v!fit
+ \ifx\@@localautowidth\v!yes
+ \ifreshapeframebox\doreshapeframedbox\fi
+ \fi
+ \boxhaswidthfalse
+ \else\ifx\localwidth\v!fixed
+ \boxhaswidthfalse
+ \else
+ \resetshapeframebox
+ \fi\fi
+ \fi
+ \else
+ \resetshapeframebox
+ \fi
+ \ifboxhaswidth
+ \wd\framebox\!!framedwidth
+ \fi
+ \ifboxhasheight
+ \ht\framebox\!!framedheight
+ \fi
+ \doifvalue{\@@framed\c!empty}\v!yes
+ {\setbox\scratchbox\null
+ \wd\scratchbox\wd\framebox
+ \ht\scratchbox\ht\framebox
+ \dp\scratchbox\dp\framebox
+ \setbox\framebox\box\scratchbox}%
+ \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}%
+ \ifx\framedforegroundcolor\empty\else\docolorframebox\fi
+ \ifboxhasoffset
+ \dooffsetframebox
+ \fi
+ \ifboxisoverlaid \else
+ \dolocateframebox
+ \fi
+ \ifx\postprocessframebox\relax \else
+ \let\next\postprocessframebox
+ \let\postprocessframebox\relax % prevent nesting
+ \next\framebox
+ \fi
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}%
+ \edef\overlaylinewidth{\the\ruledlinewidth}% \@@...
+ \ifboxhasframe % real or invisible frame
+ \dooutlinebox
+ \fi
+ \edef\framedbackground{\framedparameter\c!background}%
+ \ifx\framedbackground\empty\else\dobackedbox\fi
+ \handleframedlocator\c!after\@@locallocation
+ \box\framebox
+ \egroup
+ \egroup}
+
+\def\installframedlocator#1#2#3%
+ {\setvalue{\??ol:\c!location:\c!before:#1}{#2}%
+ \setvalue{\??ol:\c!location:\c!after :#1}{#3}}
+
+\def\handleframedlocator#1#2%
+ {\getvalue{\??ol:\c!location:#1:#2}}
+
+\def\doprelocframedbox#1%
+ {\scratchdimen\dimexpr#1+\ruledlinewidth\relax
+ \ifboxhasoffset
+ \advance\scratchdimen \framedparameter\c!offset
+ \fi
+ \scratchskip\dimexpr\ht\framebox-\scratchdimen\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\framebox\ht\framebox
+ \ht\framebox\zeropoint}
+
+\installframedlocator \v!depth
+ {}
+ {\ht\framebox\dimexpr\ht\framebox-\strutdp\relax
+ \dp\framebox\strutdp
+ \box\framebox}
+
+\installframedlocator \v!height
+ {}
+ {\dp\framebox\dimexpr\ht\framebox-\strutht\relax
+ \ht\framebox\strutht
+ \box\framebox}
+
+\installframedlocator \v!high
+ {}
+ {\doprelocframedbox\strutht
+ \setbox\framebox\hbox{\lower\scratchskip\box\framebox}%
+ \ht\framebox\strutht
+ \dp\framebox\strutdp
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!line
+ {}
+ {\setbox\framebox\hbox{\lower.5\ht\framebox\box\framebox}%
+ \ht\framebox.5\lineheight
+ \dp\framebox.5\lineheight
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!low
+ {}
+ {\doprelocframedbox\strutdp
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\strutht
+ \dp\framebox\strutdp
+ \box\framebox}
+
+\installframedlocator \v!top
+ {}
+ {\doprelocframedbox\strutht
+ \setbox\framebox\hbox{\lower\scratchskip\box\framebox}%
+ \ht\framebox\scratchdimen
+ \dp\framebox\scratchskip
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!middle
+ {}
+ {\scratchdimen.5\ht\framebox
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\scratchdimen
+ \dp\framebox\scratchdimen
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!lohi
+ {\handleframedlocator\c!before\v!middle}
+ {\handleframedlocator\c!after \v!middle}
+
+\installframedlocator \v!bottom
+ {}
+ {\doprelocframedbox\strutdp
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\scratchskip
+ \dp\framebox\scratchdimen
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!keep % retains height/depth
+ {\removeframedboxdepth}
+ {\restoreframedboxdepth}
+
+% also used in fastlocalframed
+
+\newdimen\originalframedwd
+\newdimen\originalframedht
+\newdimen\originalframeddp
+
+\def\removeframedboxdepth
+ {\originalframedwd\wd\framebox
+ \originalframedht\ht\framebox
+ \originalframeddp\dp\framebox
+ \ifzeropt\originalframeddp\else\setbox\framebox\hbox{\raise\originalframeddp\box\framebox}\fi
+ \wd\framebox\originalframedwd
+ \ht\framebox\dimexpr\originalframedht+\originalframeddp\relax
+ \dp\framebox\zeropoint}
+
+\def\restoreframedboxdepth
+ {\ifzeropt\originalframeddp\else\setbox\framebox\hbox{\lower\originalframeddp\box\framebox}\fi
+ \wd\framebox\originalframedwd
+ \ht\framebox\originalframedht
+ \dp\framebox\originalframeddp}
+
+% \let\@@startframedorientation\relax
+% \let\@@stopframedorientation \relax
+
+% \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\@@startframedorientation
+ {\let\@@stopframedorientation \relax
+ \ifx\@@localorientation\empty\else
+ \ifcase\@@localorientation\else
+ \scratchcounter\@@localorientation
+ \divide\scratchcounter\plustwo
+ \ifodd\scratchcounter
+ \swapmacros\framedwidth \framedheight
+ \swapmacros\localwidth \localheight
+ \swapdimens\!!framedheight\!!framedwidth
+ \def\@@stopframedorientation{\@@dostopframedorientation\plusone}%
+ \else
+ \def\@@stopframedorientation{\@@dostopframedorientation\zerocount}%
+ \fi
+ \fi
+ \fi}
+
+\def\@@dostopframedorientation#1%
+ {\ifcase#1\else
+ \swapmacros\framedwidth \framedheight
+ \swapmacros\localwidth \localheight
+ \swapdimens\!!framedheight\!!framedwidth
+ \fi
+ \setbox\framebox\hbox{\dorotatebox\@@localorientation\hbox{\box\framebox}}}
+
+%D The last conditional takes care of the special situation of
+%D in||line \inframed[height=3cm]{framed} boxes. Such boxes have
+%D to be \inframed{aligned} with the running text.
+
+\def\doinframed[#1]% we could omit #1] but readibility ...
+ {\framed[\c!location=\v!low,#1]}
+
+\unexpanded\def\inframed
+ {\dosingleempty\doinframed}
+
+%D When we set \type{empty} to \type{yes}, we get
+%D ourselves a frame and/or background, but no content, so
+%D actually we have a sort of phantom framed box.
+
+%D Because color marks and specials can interfere with
+%D spacing, we provide a way to specify a foregroundcolor.
+
+\def\docolorframebox
+ {\doifvaluesomething{\@@framed\c!foregroundcolor}
+ {\doifcolorelse{\framedparameter\c!foregroundcolor}
+ {\setbox\framebox\hbox
+ {\localcolortrue
+ \color[\framedparameter\c!foregroundcolor]{\box\framebox}}}
+ {}}}
+
+%D \macros
+%D {mframed, minframed}
+%D
+%D When Tobias asked how to frame mathematical elements in
+%D formulas, Taco's posted the 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
+%D one would expect, we move the test to the outer level. We
+%D 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
+%D takes care of setting the super- and subscripts styles
+
+\ifx\restoremathstyle\undefined \let\restoremathstyle\relax \fi
+
+\def\domframed[#1][#2]#3%
+ {\begingroup
+ \ifmmode
+ \ifinner
+ \let\mframedstyle\restoremathstyle
+ \else
+ \let\mframedstyle\displaystyle
+ \fi
+ \else
+ \let\mframedstyle\restoremathstyle
+ \fi
+ #1\ifdone
+ \def\normalstrut{$\mframedstyle\vphantom($}%
+ \framed
+ [\c!frameoffset=\@@oioffset,\c!offset=\v!overlay,#2]
+ {$\mframedstyle#3$}%
+ \else
+ \inframed
+ [#2]
+ {$\mframedstyle#3$}%
+ \fi
+ \endgroup}
+
+\def\mframed
+ {\dodoubleempty\domframed[\donetrue]}
+
+\def\inmframed
+ {\dodoubleempty\domframed[\donefalse]}
+
+%D So instead of the rather versatile \type {\framed}, we ue
+%D the \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
+%D
+%D \getbuffer
+%D
+%D However, we got into troubles when we want to nest sub- and
+%D superscripts, like in
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y^{\mframed{z}_{\mframed{z}}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D Therefore, we can best use \type {\super} and \type {\suber}
+%D instead of \type {^} and \type {_}. Both commands take care
+%D of proper font switching.
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y\super{\mframed{z}\suber{\mframed{z}}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D As usual, one can specify in what way the text should be
+%D framed. One should be aware of the fact that, inorder to
+%D preserve the proper spacing, the \type {offset} is set to
+%D \type {overlay} and \type {frameoffset} is used used
+%D instead.
+%D
+%D \startbuffer
+%D \startformula
+%D x \times y\super{\mframed[framecolor=red]{z}\suber{z}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D For inline use, we also provide the \type {\inmframed}
+%D alternative: we want $x \times \inmframed{y}$ in inline
+%D math, right?
+
+%D This previous framing macros needs a lot of alternatives for
+%D putting rules around boxes, inserting offsets and aligning
+%D text. Each step is handled by separate macros.
+
+\def\dowidenframebox#1%
+ {\setbox\framebox\vbox
+ {\kern#1\hbox{\kern#1\box\framebox\kern#1}\kern#1}}
+
+\def\dooffsetframebox{\dowidenframebox\localoffset}
+\def\dolocateframebox{\dowidenframebox\ruledlinewidth}
+
+%D Let's hope that the next few examples show us enough of
+%D what needs to be 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=nee,offset=.5cm] {rule based learning}
+%D \framed[strut=nee,offset=0cm] {rule based learning}
+%D \framed[strut=nee,offset=none] {rule based learning}
+%D \framed[strut=nee,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
+%D between borders with straight lines and those with round
+%D corners. When using the first alternative it is possible to
+%D turn off one or more lines. More fancy shapes are also
+%D possible by specifying dedicated backgrounds. Turning lines
+%D on and off is implemented as efficient as possible and as a
+%D result is interface language dependant. This next
+%D implementation evolved from simpler ones. It puts for
+%D instance the rules on top of the content and provides
+%D additional offset capabilities. The lot of calls to other
+%D macros makes this mechanism not that easy to comprehend.
+
+%D Getting the backgrounds right takes less code. Again we
+%D have to take care of additional offsets.
+
+\def\dobackedbox
+ {\doifelsevalue{\@@framed\c!backgroundoffset}\v!frame % new
+ {\dobackgroundbox\c!frameoffset}
+ {\dobackgroundbox\c!backgroundoffset}}
+
+%D We handle left, right or middle alignment as well as fixed
+%D or free widths and heights. Each combination gets its own
+%D macro.
+
+%D The following code handles one-liners: \type{align={line,flushright}}.
+%D Beware, since we entered a group and either or not grab the next
+%D bgroup token, we need to finish the group in the oneliner mode.
+
+\ifx\raggedoneliner\undefined \chardef\raggedoneliner\zerocount \fi
+
+\def\doformatonelinerbox % beware: assumes explicit preceding bgroup
+ {\ifcase\raggedoneliner
+ \expandafter\nodoformatonelinerbox
+ \else
+ \expandafter\dodoformatonelinerbox
+ \fi}
+
+\def\dodoformatonelinerbox
+ {\dowithnextboxcontent
+ {\ignorespaces}
+ {\hbox to \hsize
+ {\ifcase\raggedstatus\or\hss\or\hss\fi
+ \unhbox\nextbox \removeunwantedspaces
+ \ifcase\raggedstatus\or \or\hss\or\hss\fi}%
+ \egroup}
+ \hbox}
+
+\def\nodoformatonelinerbox % grabs {
+ {\let\next=}
+
+%D The handlers:
+
+\def\doformatboxSomeFormat
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \forgetall
+ \oninterlineskip
+ \hsize\!!framedwidth
+ \vsize\!!framedheight
+ \doframedsetups
+ \raggedcommand
+ \dobeforeframedbox
+ \bgroup
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\doafterframedbox
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxNoFormat
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \forgetall
+ \oninterlineskip
+ \hsize\!!framedwidth
+ \vsize\!!framedheight
+ \doframedsetups
+ \raggedcenter
+ \vss
+ \bgroup
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxHeight
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \forgetall
+ \oninterlineskip
+ \doframedsetups
+ \raggedcommand
+ \vss
+ \bgroup
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \localbegstrut
+ \doformatonelinerbox}
+
+\def\doformatboxWidth
+ {\vbox
+ \bgroup
+ \let\postprocessframebox\relax
+ \forgetall
+ \oninterlineskip
+ \hsize\!!framedwidth
+ \doframedsetups
+ \raggedcommand
+ \dobeforeframedbox
+ \bgroup
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\doafterframedbox
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxVSize
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \forgetall
+ \vsize\!!framedheight
+ \doframedsetups
+ \vss
+ \bgroup
+ \aftergroup\vss
+ \aftergroup\egroup
+ \hbox
+ \bgroup
+ \aftergroup\egroup
+ \localstrut
+ \doformatonelinerbox}
+
+\def\doformatboxHSize
+ {\hbox to \!!framedwidth
+ \bgroup
+ \let\postprocessframebox\relax
+ \forgetall
+ \doframedsetups
+ \hss
+ \localstrut
+ \bgroup
+ \aftergroup\hss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxNoSize
+ {\hbox
+ \bgroup
+ \let\postprocessframebox\relax
+ \doframedsetups
+ \localstrut
+ \doformatonelinerbox}
+
+\let\doframedsetups\relax
+
+%D On the next page we show some examples of how these macros
+%D come into action. The examples show us how
+%D \type {fit}, \type {broad} dimensions influence the
+%D formatting. Watch the visualized struts. \footnote {Here we
+%D used \type {\showstruts}.}
+%D
+%D \startpostponing
+%D \bgroup
+%D \showstruts
+%D \dontcomplain
+%D \startlinecorrection
+%D \halign{#\enskip\enskip\enskip\enskip\enskip\cr
+%D \framed[width=.2\hsize, height=.2\hsize, align=] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=yes] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=yes] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=yes] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=yes] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=yes] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=right] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=right] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=right] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=right] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=right] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=right] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=left] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=left] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=left] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=left] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=left] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=left] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=middle] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=middle] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=middle] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=middle] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=middle] {a\par b\par c}\cr}
+%D \stoplinecorrection
+%D \blank[2*big]
+%D \egroup
+%D \stoppostponing
+
+%D \macros
+%D {framednoflines, framedlastlength}
+%D
+%D It is possible to let the frame macro calculate the width
+%D of a centered box automatically (\type {fit}). When
+%D doing so, we need to reshape the box:
+
+% The next implementation is frozen! It preserves the depth,
+% otherwise we get problems with framed display math and auto
+% width.
+
+\newcount\framednoflines
+\newdimen\framedlastlength
+
+\def\resetshapeframebox
+ {\framednoflines \zerocount
+ \framedlastlength\zeropoint}
+
+\chardef\reshapeframeboxmethod\plusone % 0=no flush, 1=old method 2=no depth messing
+
+\def\shapeboxstrut % put this in front if needed !
+ {\vrule\!!width\zeropoint\!!height\ht\shapebox\!!depth\dp\shapebox}
+
+\let\framedboxwidth \!!zeropoint
+\let\framedboxheight\!!zeropoint
+\let\framedboxdepth \!!zeropoint
+
+\def\doreshapeframedbox % frozen, that is ... \shapeboxstrut added
+ {\ifvbox\framebox
+ \beginofshapebox
+ \unvcopy\framebox
+ \endofshapebox
+ \global\@@globalwidth\zeropoint
+ \edef\framedboxwidth {\the\wd\framebox}%
+ \edef\framedboxheight{\the\ht\framebox}%
+ \edef\framedboxdepth {\the\dp\framebox}%
+ \resetshapeframebox
+ \reshapebox
+ {\setbox0\hbox
+ {\strut\ifhbox\shapebox\shapeboxstrut\unhbox\else\box\fi\shapebox}%
+ \global\advance\framednoflines \plusone
+ \ifdim\framedlastlength>\zeropoint\else
+ \global\framedlastlength\wd0
+ \fi
+ \ifdim\wd0>\@@globalwidth
+ \global\@@globalwidth\wd0
+ \fi}%
+ \ifreshapingfailed
+ % no need for anothr pass or finalizer
+ \else
+ \dosetraggedcommand\localformat
+ \raggedcommand
+ \ifboxhasheight
+ \setbox\framebox\vbox to \localheight
+ {\hsize\@@globalwidth
+ \reshapebox{\hbox to \hsize{\ifhbox\shapebox\shapeboxstrut\unhbox\else\box\fi\shapebox}}%
+ \dobeforeframedbox
+ \innerflushshapebox
+ \doafterframedbox}%
+ \else
+ \setbox\framebox\vbox to \framedboxheight % \ht\framebox
+ {\hsize\@@globalwidth
+ \reshapebox{\hbox to \hsize{\ifhbox\shapebox\shapeboxstrut\unhbox\else\box\fi\shapebox}}%
+ \ifcase\reshapeframeboxmethod
+ \or \innerflushshapebox \or \innerflushshapebox
+ \fi}%
+ \ifcase\reshapeframeboxmethod \or
+ \dp\framebox\framedboxdepth % \strutdp otherwise problem with math
+ \fi
+ \fi
+ \ifdim\framedlastlength=\zeropoint\global\framedlastlength\wd\framebox\fi
+ \ifcase\framednoflines\global\framednoflines\plusone\fi
+ \fi
+ \fi}
+
+%D The two variables \type {\framednoflines} and \type
+%D {\framedlastlength} can be used in a second pass to
+%D optimized framed material.
+
+% 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
+%D frame as well as the background an additional offset and
+%D even a bit more depth. The blue outline is the frame, the
+%D red box is the background and the small black outline is the
+%D visualization of the resulting box, that is, we applied
+%D \type{\ruledhbox} to the result.
+
+%D \startpostponing
+%D \bgroup
+%D \unprotect
+%D \dontcomplain
+%D
+%D \startbuffer
+%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=\framedparameter\c!backgroundoffset\\
+%D frameoffset=\framedparameter\c!frameoffset\\
+%D depth=\framedparameter\c!depth}
+%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 \stopbuffer
+%D
+%D \getbuffer \page
+%D
+%D {\setupframed[depth=4pt]\getbuffer} \page
+%D
+%D \protect
+%D \egroup
+%D \stoppostponing
+
+%D When typesetting the framed box inline, we have to keep the
+%D baseline intact outside as well as inside the framed box.
+
+\def\doinlineframedbox
+ {\scratchdimen\dimexpr\strutdp+\ruledlinewidth\relax
+ \ifboxhasoffset
+ \advance\scratchdimen \framedparameter\c!offset
+ \fi
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\strutht
+ \dp\framebox\strutdp
+ \box\framebox}
+
+%D We can also lower the box over the natural depth of the
+%D line.
+
+\def\doloweredframedbox
+ {\ht\framebox\dimexpr\ht\framebox+\dp\framebox-\strutdp\relax
+ \dp\framebox\strutdp
+ \box\framebox}
+
+%D Hanging the content is mainly meant for cases like the
+%D following:
+%D
+%D \starttyping
+%D \framed[strut=no]
+%D {\framed[height=2cm,location=hanging]{test}%
+%D \framed[height=1cm,location=hanging]{test}}
+%D \stoptyping
+
+\def\dohangingframedbox % best with strut=no
+ {\scratchdimen\dimexpr\ht\framebox+\dp\framebox\relax
+ \ht\framebox\zeropoint
+ \dp\framebox\scratchdimen}
+
+%D We can draw lines from left to right and top to bottom by
+%D using the normal \type{\hairline} command. Both directions
+%D 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
+%D possible to the circumstances and act as natural as
+%D possible.
+
+\def\vboxedhairline
+ {\bgroup
+ \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi
+ \dimen4=\dimexpr\dimen2+\ruledlinewidth\relax
+ \setbox0\vbox
+ {\advance\hsize 2\dimen4
+ \vskip\dimen2
+ \hrule
+ \!!height\ruledlinewidth
+ \!!depth\zeropoint
+ \!!width\hsize
+ \vskip\dimen2}%
+ %\endgraf\nointerlineskip\endgraf
+ %\moveleft\dimen4\box0
+ %\endgraf\nointerlineskip\localbegstrut
+ \endgraf\obeydepth\nointerlineskip
+ \moveleft\dimen4\box0
+ \endgraf\nointerlineskip\localbegstrut % beware, we might kill it in a style using \vskip\lineheight
+ \egroup} % so this must not be changed
+
+\def\hboxedhairline % use framed dimen
+ {\bgroup
+ \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi
+ \ifboxhasheight
+ \dimen4\dimexpr\localheight/2+\strutdp-2\ruledlinewidth\relax
+ \dimen6\dimexpr\localheight/2-\strutdp+2\ruledlinewidth\relax
+ \else
+ \dimen4\dimexpr\strutht+\dimen2\relax
+ \dimen6\dimexpr\strutdp+\dimen2\relax
+ \fi
+ \unskip
+ \setbox\scratchbox\hbox
+ {\hskip\dimen2
+ \vrule\!!height\dimen4\!!depth\dimen6\!!width\ruledlinewidth
+ \hskip\dimen2}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \ignorespaces
+ \egroup}
+
+%D The argument of the frame command accepts \type{\\} as a
+%D sort of newline signal. In horizontal boxes it expands to a
+%D space.
+
+\def\vboxednewline
+ {\endgraf\ignorespaces}
+
+\def\hboxednewline
+ {\unskip\normalspace\ignorespaces}
+
+%D We can set each rule on or off. The default setting is
+%D inherited from \type{frame}. An earlier implementation
+%D use a bit different approach, but the new one seems more
+%D 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 {setupblackrules}
+%D
+%D The graphic capabilities of \TEX\ do not go beyond simple
+%D filled rules, except of course when using specials. Let's
+%D start with a warning: using this commands is far more slower
+%D than using the \TEX\ primitives \type{\hrule} and
+%D \type{\vrule}, but they save us some tokens. The
+%D characteristics of these rule drawing command can be set by:
+%D
+%D \showsetup{setupblackrules}
+
+\def\setupblackrules
+ {\dodoubleargument\getparameters[\??bj]}
+
+%D \macros
+%D {blackrule}
+%D
+%D The simple command draws only one rule. Its optional
+%D argument can be used to specify the dimensions. By setting
+%D the width, height or depth to \type {max}, one gets the
+%D natural dimensions.
+%D
+%D \showsetup{blackrule}
+
+\def\doblackrule[#1]%
+ {\hbox\bgroup
+ \getparameters[\??bj][#1]%
+ \setstrut
+ \doif\@@bjwidth \v!max{\def\@@bjwidth {1em}}%
+ \doif\@@bjheight\v!max{\def\@@bjheight{\strutht}}%
+ \doif\@@bjdepth \v!max{\def\@@bjdepth {\strutdp}}%
+ \localstartcolor[\@@bjcolor]%
+ \vrule
+ \!!width \@@bjwidth
+ \!!height\@@bjheight
+ \!!depth \@@bjdepth
+ \localstopcolor
+ \egroup}
+
+\unexpanded\def\blackrule
+ {\dosingleempty\doblackrule}
+
+%D \macros
+%D {blackrules}
+%D
+%D One can call for a sequence of black rules, if needed
+%D equally spaced over the given width.
+%D
+%D \showsetup{blackrules}
+%D
+%D The two alternative calls are therefore:
+%D
+%D \startbuffer
+%D Tell me, is this according to the \blackrules[n=6]?
+%D These \blackrules[alternativevariant=b,n=10,distance=.2em,width=4cm] are quite clear.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or:
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D We could of course have implemented this macro using
+%D \type{\leaders}, but this would probably have taken more
+%D tokens.
+
+\def\doblackrules[#1]%
+ {\hbox\bgroup
+ \getparameters[\??bj][#1]%
+ \!!widtha\@@bjwidth
+ \!!widthb\@@bjdistance
+ \doif\@@bjalternative\c!b
+ {\scratchcounter\@@bjn
+ \ifnum\scratchcounter=\plusone
+ \!!widthb\zeropoint
+ \else
+ \advance\scratchcounter \minusone
+ \advance\!!widtha -\scratchcounter\!!widthb
+ \divide \!!widtha \@@bjn
+ \fi}%
+ \localstartcolor[\@@bjcolor]%
+ \dorecurse\@@bjn
+ {\vrule
+ \!!width \!!widtha
+ \!!height\@@bjheight
+ \!!depth \@@bjdepth
+ \hskip\!!widthb}%
+ \unskip
+ \localstopcolor
+ \egroup}
+
+\unexpanded\def\blackrules
+ {\dosingleempty\doblackrules}
+
+%D The next commands can be used to draw margin rules. We
+%D support two methods: \marginrule{one for in||line use} and
+%D one that acts on a paragraph. Drawing a margin rule is
+%D rather straightforward because we can use the commands that
+%D put text in the margin.
+
+\def\dodrawmarginrule
+ {\setbox\scratchbox\hbox
+ {\vrule\!!depth\strutdepth\!!height\strutheight\!!width\@@karulethickness}%
+ \smashbox\scratchbox % no \vsmash !!!
+ \box\scratchbox}
+
+\def\drawmarginrule
+ {\strut\inleft{\dodrawmarginrule}}
+
+%D \macros
+%D {marginrule}
+%D
+%D The first method gobbles words and simply puts a bar in the
+%D margin. This method is not entirely robust.
+%D
+%D \showsetup{marginrule}
+
+\definecomplexorsimple\marginrule
+
+\def\simplemarginrule
+ {\let\processword\drawmarginrule
+ \processwords}
+
+\def\complexmarginrule[#1]%
+ {\ifnum#1<\@@kalevel\relax \else
+ \def\@@kadefaultwidth{#1}%
+ \expandafter\simplemarginrule
+ \fi}
+
+%D We need an auxiliary variable
+
+\def\@@kadefaultwidth{1}
+
+%D \macros
+%D {setupmarginrules}
+%D
+%D This macro definitions show us that we can pass an optional
+%D level, which is matched against the previous set one. The
+%D level can be set up with
+%D
+%D \showsetup{setupmarginrules}
+
+\def\setupmarginrules
+ {\dodoubleargument\getparameters[\??ka]}
+
+%D \macros
+%D {startmarginrule}
+%D
+%D The second method collects text and reformats it afterwards,
+%D using the shapebox macros. We prevent local margin rules.
+%D
+%D \showsetup{startmarginrule}
+
+\definecomplexorsimple\startmarginrule
+
+\def\simplestartmarginrule
+ {\bgroup
+ \let\drawmarginrule\relax
+ \let\stopmarginrule\dostopmarginrule
+ \beginofshapebox}
+
+\def\complexstartmarginrule[#1]%
+ {\bgroup
+ \let\drawmarginrule\relax
+ \ifnum#1<\@@kalevel\relax
+ \let\stopmarginrule\egroup
+ \else
+ \def\@@kadefaultwidth{#1}%
+ \let\stopmarginrule\dostopmarginrule
+ \expandafter\beginofshapebox
+ \fi}
+
+\def\dostopmarginrule
+ {\endofshapebox
+ \reshapebox
+ {\hbox{\inleftmargin{\dodrawmarginrule}\box\shapebox}}%
+ \flushshapebox
+ \egroup}
+
+%D \startbuffer
+%D \setupmarginrules[level=5]
+%D
+%D \startmarginrule[1]
+%D First we set the level at~5. Next we typeset this first
+%D paragraph as a level~1 one. As expected no rule show up.
+%D \stopmarginrule
+%D
+%D \startmarginrule[5]
+%D The second paragraph is a level~5 one. As we can see here,
+%D the marginal rule gets a width according to its level.
+%D \stopmarginrule
+%D
+%D \startmarginrule[8]
+%D It will of course be no surprise that this third paragraph
+%D has a even thicker margin rule. This behavior can be
+%D overruled by specifying the width explictly.
+%D \stopmarginrule
+%D \stopbuffer
+%D
+%D In next example we show most features. Watch the rule
+%D thickness adapting itself to the level.
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D We just said:
+%D
+%D \typebuffer
+
+%D \macros
+%D {vl, hl}
+%D
+%D The command \type{\vl} draws a vertical rule \vl\ with strut
+%D dimensions, multiplied with the factor specified in the
+%D optional argument. The height and depth are clipped \vl[3]
+%D to the baselinedistance. Its horizontal counterpart
+%D \type{\hl} draws a horizontal rule \hl\ with a width of 1em,
+%D multiplied with the optional factor. The horizontal rule is
+%D drawn on top of the baseline.
+%D
+%D \showsetup{vl}
+%D \showsetup{hl}
+
+\def\complexvl[#1]%
+ {\bgroup
+ \!!dimena#1\strutht
+ \!!dimenb#1\strutdp
+ \setbox\scratchbox\hbox
+ {\vrule
+ \!!width \linewidth
+ \!!height\!!dimena
+ \!!depth \!!dimenb}%
+ \dp\scratchbox\strutdp
+ \ht\scratchbox\strutht
+ \box\scratchbox
+ \egroup}
+
+\def\complexhl[#1]%
+ {\hbox
+ {\vrule
+ \!!width #1\s!em
+ \!!height\linewidth
+ \!!depth \zeropoint}}
+
+\definecomplexorsimple\vl \def\simplevl{\complexvl[1]}
+\definecomplexorsimple\hl \def\simplehl{\complexhl[1]}
+
+%D \macros
+%D {hairline, thinrule, thinrules, setupthinrules}
+%D
+%D Drawing thin lines can of course easily be accomplished by
+%D the \TEX\ primitives \type{\hrule} and \type{\vrule}. The
+%D next few macros however free us from some specifications.
+%D
+%D \startbuffer
+%D some text
+%D
+%D \hairline
+%D
+%D some more text
+%D
+%D \thinrule
+%D
+%D more and more text
+%D
+%D hi \thinrule\ there
+%D
+%D and then the final text
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D becomes
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D So we've got
+%D
+%D \showsetup{hairline}
+%D \showsetup{thinrule}
+%D
+%D Both can be set up with:
+%D
+%D \showsetup{setupthinrules}
+%D
+%D We also have
+%D
+%D \showsetup{thinrules}
+%D
+%D which looks like: \thinrules[n=2]
+
+\def\thinrule
+ {\strut
+ \bgroup
+ \chardef\ruletype\plusone
+ \processaction
+ [\@@dlalternative]
+ [ \v!a=>\chardef\ruletype0,% no line
+ %\v!b=>\chardef\ruletype1,% height/depth
+ \v!c=>\chardef\ruletype2,% topheight/botdepth
+ % 11=>\chardef\ruletype1,% fallback for backgrounds
+ 0=>\chardef\ruletype0,% compatible with backgrounds
+ % 1=>\chardef\ruletype1,% compatible with backgrounds
+ 2=>\chardef\ruletype2]% compatible with backgrounds
+ \doifsomething\@@dlrulethickness
+ {\linewidth\@@dlrulethickness}%
+ \ifdim\linewidth=\zeropoint
+ \chardef\ruletype\zerocount
+ \else
+ \doifnot\@@dlframe\v!on{\chardef\ruletype\zerocount}%
+ \fi
+ \ifnum\ruletype=\plusone
+ \doif\@@dlheight\v!max{\let\@@dlheight\!!plusone}%
+ \doif\@@dldepth \v!max{\let\@@dldepth \!!plusone}%
+ \else
+ \let\@@dlheight\!!plusone
+ \let\@@dldepth\!!plusone
+ \fi
+ \freezedimensionwithunit\@@dlheight\strutht
+ \freezedimensionwithunit\@@dldepth\strutdp
+ \divide\linewidth \plustwo
+ \doifelse\@@dlbackground\v!color
+ {\startcolor[\@@dlbackgroundcolor]%
+ \ifnum\ruletype=\plustwo % prevent overshoot due to rounding
+ \leaders
+ \hrule
+ \!!height\dimexpr\@@dlheight-.5\linewidth\relax
+ \!!depth \dimexpr\@@dldepth -.5\linewidth\relax
+ \hfill
+ \else
+ \leaders
+ \hrule
+ \!!height\@@dlheight
+ \!!depth \@@dldepth
+ \hfill
+ \fi
+ \stopcolor
+ \ifcase\ruletype
+ % no rule
+ \or
+ \startcolor[\@@dlcolor]%
+ \hfillneg
+ \leaders\hrule\!!height\linewidth\!!depth\linewidth\hfill
+ \stopcolor
+ \or
+ \startcolor[\@@dlcolor]%
+ \hfillneg\leaders\hrule\!!height\dimexpr-\@@dldepth+\linewidth\relax\!!depth\@@dldepth\hfill
+ \hfillneg\leaders\hrule\!!height\@@dlheight\!!depth\dimexpr-\@@dlheight+\linewidth\relax\hfill
+ \stopcolor
+ \fi}
+ {\ifcase\ruletype \else
+ \startcolor[\@@dlcolor]%
+ \leaders\hrule\!!height\@@dlheight\!!depth\@@dldepth\hfill
+ \stopcolor
+ \fi}%
+ \strut
+ \carryoverpar\egroup}
+
+\def\hairline
+ {\endgraf
+ \thinrule
+ \endgraf}
+
+\def\dosetupthinrules[#1]%
+ {\getparameters[\??dl][#1]}
+
+\def\setupthinrules
+ {\dosingleargument\dosetupthinrules}
+
+\def\dothinrules[#1]%
+ {\bgroup
+ \dosetupthinrules[#1]%
+ \@@dlbefore
+ \assignvalue\@@dlinterlinespace\@@dlinterlinespace{1.0}{1.5}{2.0}%
+ \spacing\@@dlinterlinespace
+ \dorecurse\@@dln
+ {\ifnum\recurselevel=\@@dln \dothinrulesnobreak \else
+ \ifnum\recurselevel=2 \dothinrulesnobreak \fi\fi
+ \thinrule
+ \ifnum\recurselevel<\@@dln\relax
+ % test needed, else messed up whitespace
+ \ifx\@@dlinbetween\empty
+ \softbreak
+ \else
+ \endgraf
+ \nowhitespace
+ \@@dlinbetween
+ \fi
+ \fi}%
+ \doifelsenothing\@@dlafter
+ {\carryoverpar\egroup}
+ {\@@dlafter\egroup}}
+
+\def\thinrules
+ {\dosingleempty\dothinrules}
+
+%D A couple of examples are given below.
+%D
+%D \startbuffer
+%D \setupthinrules[n=3,inbetween=,color=gray]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [color=green] test test \par
+%D test test \thinrules [height=max, depth=max] test test \par
+%D
+%D \setupthinrules[height=.9,depth=.9]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [alternativevariant=b] test test \par
+%D test test \thinrules [alternativevariant=c] test test \par
+%D test test \thinrules [alternativevariant=c,inbetween=\vskip2ex] test test \par
+%D \stopbuffer
+%D
+%D \typebuffer {\getbuffer}
+%D
+%D There are a couple of alternative ways to visualize rules
+%D using backgrounds. At first sight these may look strange,
+%D but they make sense in educational settings. The
+%D alternatives are more or less compatible with the more
+%D advanced \METAPOST\ based implementation.
+%D
+%D \startbuffer[a]
+%D \setupthinrules
+%D [n=2,
+%D backgroundcolor=gray ,
+%D rulethickness=1pt,
+%D colorkleur=donkerblauw,
+%D after=\blank,
+%D before=\blank]
+%D \stopbuffer
+%D
+%D \typebuffer[a]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a]
+%D \thinrules[alternativevariant=b]
+%D \thinrules[alternativevariant=c]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,background=color]
+%D \thinrules[alternativevariant=b,background=color]
+%D \thinrules[alternativevariant=c,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=b,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=c,height=.8,depth=.8,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+
+%D \macros
+%D {optimizethinrules}
+%D
+%D By saying \type {\thinrulestrue} or \type {-false}, we
+%D can influence the way dangling lines are handled.
+
+\newif\ifoptimizethinrules \optimizethinrulestrue
+
+\def\dothinrulesnobreak
+ {\ifoptimizethinrules\penalty500\fi}
+
+%D \macros
+%D {startframedtext, setupframedtexts, defineframedtext}
+%D
+%D The general framing command we discussed previously, is not
+%D entirely suited for what we call framed texts, as for
+%D instance used in intermezzo's. The next examples show what
+%D 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
+%D as well as the 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<>}
+%D \showsetup{<>}
+%D
+%D The next definition shows the defaults.
+
+\def\dodefineframedtext[#1][#2]%
+ {\presetlocalframed[\??kd#1]%
+ \getparameters[\??kd#1]
+ [\c!width=0.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!foregroundcolor=,
+ \c!foregroundstyle=,
+ \c!background=,
+ \c!backgroundcolor=,
+ \c!backgroundscreen=\@@rsscreen,
+ \c!linecorrection=\v!on,
+ \c!depthcorrection=\v!on,
+ \c!margin=\v!standard,
+ \c!orientation=,
+ \c!indenting=,
+ #2]%
+ \setvalue{\e!start#1}{\dostartframedtext[#1]}%
+ \setvalue{\e!stop #1}{\dostopframedtext }%
+ \setvalue {#1}{\doframedtext [#1]}}
+
+\def\defineframedtext
+ {\dodoubleempty\dodefineframedtext}
+
+%D We define the general (and original) case by just saying:
+
+\defineframedtext[\v!framedtext]
+
+%D We need several steps before the actual job is done,
+%D because we have to handle an optional identifier (and
+%D because these commands evolved out of a single case).
+
+\def\framedtextparameter#1#2%
+ {\csname\??kd#1#2\endcsname}
+
+\def\dosetupframedtexts[#1][#2]%
+ {\ifsecondargument
+ \def\docommand##1{\getparameters[\??kd##1][#2]}%
+ \processcommacommand[#1]\docommand % new, #1 may be macro
+ \else
+ \getparameters[\??kd\v!framedtext][#1]%
+ \fi}
+
+\def\setupframedtexts
+ {\dodoubleempty\dosetupframedtexts}
+
+\def\dostartframedtext
+ {\bgroup\dotripleempty\dodostartframedtext}
+
+\def\dodostartframedtext[#1][#2][#3]%
+ {\doifassignmentelse{#2}
+ {\dododostartframedtext[#1][][#2]}
+ {\dododostartframedtext[#1][#2][#3]}}
+
+\setfalse\framedtextlocationnone
+
+\def\checkframedtext % messy dependency
+ {\ifinsidefloat
+ \localhsize\hsize
+ \else\ifdim\sidefloatvsize>\zeropoint % will be proper handle
+ % \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
+ \else
+ \localhsize\hsize
+ \fi\fi}
+
+\def\dododostartframedtext[#1][#2][#3]% #3 only passed to framed, not to framedtext
+ {\doifsomething{#2}{\setvalue{\??kd#1\c!location}{#2}}% does not listen to #3
+ \setfalse\framedtextlocationnone
+ \processaction % \v!low en \v!depth are already taken !
+ [\framedtextparameter{#1}\c!location]
+ [ \v!left=>\letvalue{\??kd#1\c!left }\relax
+ \letvalue{\??kd#1\c!right}\hfill,
+ \v!right=>\letvalue{\??kd#1\c!left }\hfill
+ \letvalue{\??kd#1\c!right}\relax,
+ \v!middle=>\letvalue{\??kd#1\c!left }\hfill
+ \letvalue{\??kd#1\c!right}\hfill,
+ \v!none=>\letvalue{\??kd#1\c!left }\relax % new
+ \letvalue{\??kd#1\c!right}\relax % new
+ \settrue\framedtextlocationnone]%
+ \letvalue{\??kd#1\c!location}\empty
+ % removed 06/2001
+ % \forgetparindent
+ % added 06/2001 [see demo-bbv]
+ \localhsize\hsize \checkframedtext
+ % so far
+ \setbox\framebox\vbox
+ \startboxedcontent
+ \hsize\localhsize
+ % \insidefloattrue % ? better
+ \expanded{\switchtobodyfont[\framedtextparameter{#1}\c!bodyfont]}%
+ \startcolor[\framedtextparameter{#1}\c!color]%
+ \localframed[\??kd#1][\c!strut=\v!no,#3]% todo: use delayedstrut
+ \bgroup
+ \let\\=\endgraf
+ \framedtextparameter{#1}\c!inner % oud spul
+ \doifvalue{\??kd#1\c!depthcorrection}\v!on % new, inside box
+ {\bgroup
+ \verticalstrut
+ % we need \nowhitespace in case of setups setting whitespace
+ % nb, not safe, text vs \vbox as next
+ \vskip-\struttotal
+ \nowhitespace % na vskip ! new 20/05/2004, fails with next content being box (\scale{..})
+ }%
+ \doinhibitblank % \blank[\v!disable]% plaatst signal
+\setupindenting[\framedtextparameter{#1}\c!indenting]%
+ \doconvertfont{\framedtextparameter{#1}\c!style}\empty
+ \def\dostopframedtext{\dodostopframedtext{#1}{#2}}}
+
+%D The \type {none} option is handy for nested usage, as
+%D in the presentation styles, where we don't want
+%D interference.
+
+\def\dodostopframedtext#1#2% % no \baselinecorrection, see faq docs
+ {\endgraf
+ \removelastskip
+ \doifvalue{\??kd#1\c!depthcorrection}\v!on % local and global
+ {\forgetall
+ \vskip-\struttotal
+ \verticalstrut
+ \egroup
+ \forgetall
+ \vskip-\lineheight
+ % will be an option, not default
+ % \setbaselinecorrections
+ % \donegbotbaselinecorrection
+ \verticalstrut}
+ \stopboxedcontent
+ \stopcolor
+ \ifconditional\framedtextlocationnone
+ \egroup
+ \box\framebox
+ \else\ifinsidefloat
+ \egroup
+ \box\framebox
+ \else
+ \egroup
+ \doplacement[\??kd#1][\c!depthcorrection=\v!off]{\box\framebox}%
+ \fi\fi
+ \egroup}
+
+%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
+%D slightly different and is not aligned.
+
+\def\doframedtext
+ {\bgroup\dodoubleempty\dodoframedtext}
+
+\def\dodoframedtext[#1][#2]% beware!
+ {\expanded{\switchtobodyfont[\getvalue{\??kd#1\c!bodyfont}]}%
+ \localframed[\??kd#1][\c!strut=\v!no,#2]%
+ \bgroup
+ \blank[\v!disable]%
+ \let\\=\endgraf
+ \getvalue{\??kd#1\c!inner}% % kleur naar outer level
+ \dostartattributes{\??kd#1}\c!style\c!color\empty
+ \bgroup
+ \aftergroup\docloseframedtext
+ \let\next=}
+
+\def\docloseframedtext
+ {\removelastskip
+ \dostopattributes
+ \egroup
+ \egroup}
+
+%D \macros
+%D {defineframed}
+%D
+%D One can also define simple framed texts, using:
+%D
+%D \showsetup{defineframed}
+
+\def\defineframed
+ {\dodoubleempty\dodefineframed}
+
+\def\dodefineframed[#1][#2]%
+ {\iffirstargument
+ \setvalue{#1}{\dodoubleempty\doframed[#2]}%
+ \fi}
+
+\def\doframed[#1][#2]%
+ {\framed[#1,#2]}
+
+%D \macros
+%D {textrule, starttextrule, setuptextrules}
+%D
+%D Putting rules before and after a paragraph is very space
+%D sensitive, but the next command handles that quite well. It
+%D comes in two disguises:
+%D
+%D \startbuffer
+%D \textrule[top]{fragments}
+%D \input reich
+%D \textrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [width=90pt,distance=12pt,rulecolor=blue,
+%D bodyfont=small,style=\sc,color=red]
+%D
+%D \starttextrule{Ship Building Tools}
+%D \nl \setuptolerance[tolerant] \input materie
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [location=inmargin,
+%D bodyfont=small,style=slantedbold]
+%D
+%D \starttextrule{wonderful}
+%D \input tufte
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D The formal definition of these commands is:
+%D
+%D \showsetup{textrule}
+%D \showsetup{starttextrule}
+%D \showsetup{setuptextrules}
+%D
+%D The implementation looks a bit complicated due to the
+%D optional arguments.
+
+\def\setuptextrules
+ {\dodoubleargument\getparameters[\??tl]}
+
+\def\complextextrule[#1]% if needed we can make it installable
+ {\let\next\dobottomtextrule
+ \processaction
+ [#1]
+ [ \v!top=>\let\next\dotoptextrule,
+ \v!middle=>\let\next\domiddletextrule,
+ \v!bottom=>\let\next\dobottomtextrule]%
+ \dosinglegroupempty\next}
+
+\definecomplexorsimple\textrule
+
+\def\simpletextrule
+ {\dosinglegroupempty\dounknowntextrule}
+
+\def\docomplextextrule#1%
+ {\bgroup
+ \advance\hsize\dimexpr-\rightskip-\leftskip\relax
+ \setbox\scratchbox\hbox to \hsize
+ {\dimen4\dimexpr .5ex+.5\linewidth\relax
+ \dimen6\dimexpr-.5ex+.5\linewidth\relax
+ \doifnothing{#1}\firstargumentfalse
+ \iffirstargument
+ \doifelse\@@tllocation\v!inmargin
+ {\llap{\doattributes\??tl\c!style\c!color{#1}\hskip\leftmargindistance}}
+ {\color[\@@tlrulecolor]
+ {\vrule\!!height\dimen4\!!depth\dimen6\!!width\@@tlwidth}%
+ \hbox spread 2\dimexpr\@@tldistance\relax
+ {\hss\doattributes\??tl\c!style\c!color{\strut#1}\hss}}%
+ \fi
+ \color[\@@tlrulecolor]
+ {\leaders\hrule\!!height\dimen4\!!depth\dimen6\hfill}}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \noindent\box\scratchbox
+%\nobreak\verticalstrut\kern-\struttotal
+% evt \witruimte
+ \egroup}
+
+\def\dotoptextrule#1%
+ {\page[\v!preference] % interferes
+ %\whitespace % no
+ \@@tlbefore
+ \docomplextextrule{#1}%
+% todo, option: \doifnothing{#1}{\ruledvskip-.5ex}
+ \nowhitespace
+ \@@tlinbetween
+ \endgraf}
+
+\def\dodobottomtextrule#1#2%
+ {\ifhmode
+ \endgraf
+ \fi
+ \dimen0\strutdp
+ \ifdim\prevdepth>\strutdp\else % was <\strutdp
+ \ifdim\prevdepth>\zeropoint
+ \advance\dimen0 -\prevdepth
+ \fi
+ \fi
+ \advance\dimen0 .5ex
+ \vskip\dimen0
+% ==
+% \vskip\dimexpr \strutdp + .5ex
+% \ifdim\prevdepth>\strutdp\else\ifdim\prevdepth>\zeropoint-\prevdepth\fi\fi\relax
+%
+ \@@tlinbetween
+ \doifelsenothing{#2}
+ {\bgroup
+ \advance\hsize\dimexpr-\rightskip-\leftskip\relax
+ \nointerlineskip
+ \moveleft-\leftskip\vbox
+ {\color[\@@tlrulecolor]
+ {\hrule\!!depth\linewidth\!!height\zeropoint\!!width\hsize}}%
+ \egroup}
+ {\docomplextextrule{#2}}%
+ \ifvmode\prevdepth\zeropoint\fi
+ #1%
+ \page[\v!preference]}
+
+\def\dobottomtextrule
+ {\dodobottomtextrule\@@tlafter}
+
+\def\domiddletextrule
+ {\dodobottomtextrule\@@tlinbetween}
+
+\def\dounknowntextrule
+ {\iffirstargument
+ \@EA\dotoptextrule
+ \else
+ \@EA\dobottomtextrule\@EA\empty
+ \fi}
+
+%D The grouped commands also supports bodyfont switching:
+
+\def\starttextrule#1%
+ {\bgroup
+ \def\dounknowntextrule{\domiddletextrule}
+ \dotoptextrule{#1}
+ \bgroup
+ \doifsomething\@@tlbodyfont{\switchtobodyfont[\@@tlbodyfont]}}
+
+\def\stoptextrule
+ {\par
+ \egroup
+ \dobottomtextrule\empty
+ \egroup}
+
+%D \macros
+%D {fillinrules, setupfillinrules}
+%D
+%D The next few commands do not really deserve a place in a
+%D core module, because they deal with specific typography.
+%D Nevertheless I decided to make them part of the core,
+%D because they permit us to make questionaires. Let's start
+%D with some examples.
+%D
+%D \fillinrules[n=2,width=fit]{first}
+%D \fillinrules[n=2,width=broad]{first}
+%D \fillinrules[n=2,width=3cm]{first}
+%D \fillinrules[n=2,width=3cm,distance=.5em,separator=:]{first}
+%D \fillinrules[n=2]{first}{last}
+%D \fillintext{first}{last} \input reich \par
+%D
+%D The main command is \type{\fillinrules}. This command takes
+%D one and an optional second argument and sets a paragraph with
+%D empty visualized lines.
+%D
+%D \showsetup{fillinrules}
+%D \showsetup{setupfillinrules}
+
+\def\setupfillinrules
+ {\dodoubleargument\getparameters[\??il]}
+
+\definecomplexorsimpleempty\fillinrules
+
+\def\complexfillinrules[#1]%
+ {\def\docomplexfillinrules##1##2%
+ {\dodocomplexfillinrules[#1]{##1}{##2}{\thinrules
+ [\c!n=\@@iln,\c!interlinespace=\@@ilinterlinespace,\c!before=,\c!after=]}}%
+ \dodoublegroupempty\docomplexfillinrules}
+
+\def\dodocomplexfillinrules[#1]#2#3#4%
+ {\endgraf
+ \@@ilbefore
+ \begingroup
+ \setupfillinrules[#1]%
+ \noindent
+ \doifsomething{#2}
+ {\doifelse\@@ilwidth\v!fit
+ {\let\@@ildistance\!!zeropoint
+ \hbox}
+ {\doifelse\@@ilwidth\v!broad
+ {\hbox}
+ {\hbox to \@@ilwidth}}%
+ \bgroup
+ \doattributes\??il\c!style\c!color{\strut#2\hfill\@@ilseparator}%
+ \hskip\@@ildistance
+ \egroup}%
+ %\hangindent=\wd0\relax % tzt hang=yes,n
+ %\parindent=\hangindent
+ %\box0\relax
+ \setupwhitespace[\v!big]%
+ \ignorespaces
+ #4%
+ \doifsomething{#3}
+ {\kern\@@ildistance
+ \doattributes\??il\c!style\c!color{#3\strut}}%
+ \endgroup
+ \endgraf
+ \@@ilafter}
+
+%D \macros
+%D {fillintext}
+%D
+%D To provide compatible layouts when texts and lines are
+%D mixed, one can typeset a paragraph by using the command
+%D \type{\fillintext}.
+%D
+%D \showsetup{fillintext}
+
+\definecomplexorsimpleempty\fillintext
+
+\def\complexfillintext[#1]% rather rough, using an \unhbox is suboptimal
+ {\def\docomplexfillintext##1##2%
+ {\dowithnextbox
+ {\dodocomplexfillinrules[#1]{##1}{\hfill##2}{\unhbox\nextbox\unskip}}%
+ \hbox\bgroup\let\par\egroup\ignorespaces}%
+ \dodoublegroupempty\docomplexfillintext}
+
+%D \macros
+%D {fillinline, setupfillinlines}
+%D
+%D Another member of the family takes care of putting a (often
+%D small) rule after a piece of text, like
+%D
+%D \startbuffer
+%D \fillinline \input reich \par
+%D \fillinline[margin=0cm] \input reich \par
+%D \stopbuffer
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D which was typeset by saying:
+%D
+%D \typebuffer
+%D
+%D The two commands that take care of this are:
+%D
+%D \showsetup{fillinline}
+%D \showsetup{setupfillinlines}
+
+\def\setupfillinlines
+ {\dodoubleargument\getparameters[\??iv]}
+
+\definecomplexorsimpleempty\fillinline
+
+\def\complexfillinline[#1]%
+ {%\endgraf % interferes with \definedescription cum suis
+ \@@ivbefore
+ \begingroup
+ \setupfillinlines[#1]%
+ \advance\rightskip \@@ivmargin
+ \parfillskip\zeropoint
+ \def\par % very dangerous
+ {\let\par\endgraf % -)
+ \ifhmode\unskip\hfill\fi
+ \scratchdimen\dimexpr\@@ivwidth-\@@ivdistance\relax
+ \ifdim\scratchdimen>\@@ivmargin\else\expandafter\rlap\fi
+ {\kern\@@ivdistance
+ \vrule
+ \!!width \scratchdimen
+ \!!height.5\linewidth
+ \!!depth .5\linewidth}%
+ \endgraf % !
+ \endgroup
+ \endgraf % !
+ \@@ilafter}}
+
+%D \stopdocumentation
+%D \bgroup
+%D
+%D \setupframedtexts
+%D [setuptext]
+%D [background=color,backgroundcolor=white]
+%D
+%D \startbuffer
+%D \setupbackground
+%D [backgroundoffset=4pt,
+%D background=screen,
+%D frame=on,
+%D framecolor=red,
+%D leftoffset=2pt]
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D \startbackground
+%D
+%D \macros
+%D {setupbackground,startbackground,background}
+%D
+%D The section deals with backgrounds in the running text. This
+%D means that texts is to be collected and split over pages. To
+%D show what can be done, we provide this part of the
+%D documentation with some gray background and a red frame.
+%D Both the background and frame can have all characteristics
+%D of \type{\framed}. This time we used the setting:
+%D
+%D \typebuffer
+%D
+%D The implementation is not that sophisticated, but suffices.
+%D The main problem with this kind of functionality is to get
+%D the spacing all right.
+
+%D Specifying the background is more or less the same as
+%D specifying a framed box.
+%D
+%D \showsetup{setupbackground}
+
+\presetlocalframed[\??ag]
+
+\def\dosetupbackground[#1]%
+ {\getparameters[\??ag][#1]%
+ \doifelse\@@agstate\v!start
+ {\let\startbackground\dostartbackground
+ \let\stopbackground \dostopbackground
+ \let\background \dobackground}
+ {\let\startbackground\relax
+ \let\stopbackground \relax
+ \let\background \relax}}
+
+\def\setupbackground
+ {\dosingleargument\dosetupbackground}
+
+%D Actually typesetting the background is implemented rather
+%D straightforward. We need to handle some spacing as well as
+%D the (often) a bit smaller horizontal size.
+%D
+%D \showsetup{startbackground}
+%D
+%D Although we could have used a scratch one, we first
+%D declare a boolean.
+
+% 0=no-split, 1=no-split+indent, 2=split, 3=split+indent
+
+\chardef\backgroundsplitmode\plusthree
+
+%D The \type{\vbox to \lineheight{}\vskip\zeropoint}
+%D construction gives the first real line a decent height by
+%D adding a dummy line.
+
+\def\dostartbackground
+ {\endgraf
+ \bgroup
+ \setbox0\vbox\bgroup
+ \vbox to \lineheight{}\vskip\zeropoint
+ \blank[\v!disable]
+ % \advance\hsize -\@@agleftoffset
+ % \advance\hsize -\@@agrightoffset
+ \leftskip \@@agleftoffset % new **
+ \rightskip\@@agrightoffset} % new **
+
+%D This dummy line is removed by \type{\setbox2=\vsplit0 to
+%D \lineheight}. That way \type{\topskip} takes care of the
+%D lineheight. I'll probably forget to apply this trick
+%D elsewhere.
+
+\def\dostopbackground % improved version (i hope)
+ {\endgraf
+ \removelastskip
+ \egroup
+ \dimen2\leftskip % new **
+ \forgetall
+ \ifinsidefloat
+ \chardef\backgroundsplitmode\zerocount
+ \fi
+ \ifcase\backgroundsplitmode
+ \localframed[\??ag][\c!offset=\v!overlay]{\box0}%
+ \or
+ \hskip\dimen2
+ \localframed[\??ag][\c!offset=\v!overlay]{\box0}%
+ \else
+ \splitmaxdepth\boxmaxdepth
+ \splittopskip\topskip
+ \setbox2\vsplit0 to \lineheight % get rid of fake line
+ \loop
+ \ifdim\pagetotal=\zeropoint % empty page
+ \scratchdimen\textheight
+ \chardef\backgroundsplit\plusone % split to max height
+ \else
+ \setbox\scratchbox\vbox{\@@agbefore}%
+ \scratchdimen\dimexpr\pagegoal-\ht\scratchbox-\pagetotal\relax
+ \chardef\backgroundsplit\plustwo % split to partial height
+ \fi
+ \advance\scratchdimen\dimexpr-\@@agtopoffset-\@@agbottomoffset\relax
+ \ifdim\scratchdimen>2\lineheight\relax % reasonable, will be configurable
+ \ifdim\ht0>\scratchdimen % larger than page
+ \setbox2\vsplit0 to \scratchdimen
+ \else
+ \setbox2\box0
+ \chardef\backgroundsplit\zerocount % no split
+ \fi
+ \setbox2\vbox \ifcase\backgroundsplit\or to \textheight \fi % max split
+ {\vskip\@@agtopoffset
+ \popsplitproperties
+ \unvcopy2
+ \prevdepth\dp2
+ \obeydepth
+ \vskip\@@agbottomoffset
+ \vfill}
+ \@@agbefore
+ \ifcase\backgroundsplit\or\or % partial split
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal=1.2\pagegoal % be a bit more tolerant
+ \fi
+ \fi
+ \startlinecorrection
+ %\localframed[\??ag][\c!offset=\v!overlay]{\hskip\@@agleftoffset\box2\hskip\@@agrightoffset}%
+ \ifnum\backgroundsplitmode=\plusthree \hskip\dimen2 \fi %
+ \localframed[\??ag][\c!offset=\v!overlay]{\box2}% new **
+ \stoplinecorrection
+ \ifcase\backgroundsplit % no split
+ \@@agafter
+ \else % some split
+ \vfill\eject % geen \page !
+ \fi
+ \else
+ \page
+ \fi
+ \ifdim\ht0>\zeropoint \repeat
+ \fi
+ \egroup
+ \endgraf}
+
+%D As a bonus we also have a short command, that is of not
+%D much use, but kept there for historic reasons.
+%D
+%D \showsetup{background}
+
+\def\dobackground
+ {\bgroup
+ \dowithnextbox
+ {\localframed[\??ag][\c!offset=\v!overlay]{\flushnextbox}\egroup}
+ \vbox}
+
+%D \stopdocumentation
+%D \stopbackground
+%D \egroup
+
+%D New, for the moment private; let's see when GB finds out
+%D about this one and its 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
+
+\def\defineframedcontent
+ {\dodoubleempty\dodefineframedcontent}
+
+\def\dodefineframedcontent[#1][#2]%
+ {\presetlocalframed[\??fc#1]%
+ \getparameters[\??fc#1]
+ [\c!leftoffset=\zeropoint,
+ \c!rightoffset=\getvalue{\??fc#1\c!leftoffset},
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\getvalue{\??fc#1\c!topoffset},
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!linecorrection=\v!no,
+ \c!left=,
+ \c!right=,
+ #2]}
+
+\let\setuplocalframed\getparameters
+
+\def\setupframedcontent
+ {\dodoubleempty\dosetupframedcontent}
+
+\def\dosetupframedcontent[#1][#2]%
+ {\def\docommand##1{\getparameters[\??fc##1][#2]}%
+ \processcommacommand[#1]\docommand}
+
+\def\startframedcontent[#1]%
+ {\bgroup
+ \let\stopframedcontent\egroup
+ \doifnot{#1}\v!off
+ {\doifdefined{\??fc#1\c!frame}
+ {\def\stopframedcontent{\dostopframedcontent{#1}}%
+ \dostartframedcontent{#1}}}}
+
+\def\dostartframedcontent#1%
+ {\setbox\framebox\hbox\bgroup
+ \setlocalhsize
+ \hsize\localhsize
+ \advance\hsize\dimexpr-\getvalue{\??fc#1\c!leftoffset}-\getvalue{\??fc#1\c!rightoffset} \relax
+ \advance\vsize\dimexpr-\getvalue{\??fc#1\c!topoffset} -\getvalue{\??fc#1\c!bottomoffset}\relax
+ \hskip\getvalue{\??fc#1\c!leftoffset}%
+ \vbox\bgroup
+ \vskip\getvalue{\??fc#1\c!topoffset}%
+ \vbox\bgroup
+ \forgetall
+ \blank[\v!disable]}
+
+\def\dostopframedcontent#1%
+ {\removelastskip
+ \egroup
+ \vskip\getvalue{\??fc#1\c!bottomoffset}%
+ \egroup
+ \hskip\getvalue{\??fc#1\c!rightoffset}%
+ \egroup
+ \doifvalue{\??fc#1\c!width}\v!fit
+ {\letvalue{\??fc#1\c!width}\v!fixed}% no shapebox
+ \ifinsidefloat
+ \donefalse
+ \else
+ \doifelsevalue{\??fc#1\c!linecorrection}\v!yes\donetrue\donefalse
+ \fi
+ % plaats ?
+ \ifdone\startlinecorrection\fi
+ \getvalue{\??fc#1\c!left}% new
+ \localframed[\??fc#1]{\box\framebox}%
+ \getvalue{\??fc#1\c!right}% new
+ \ifdone\stoplinecorrection\fi
+ \egroup}
+
+%D \macros
+%D {backgroundline}
+%D
+%D For the moment an undocumented feature, but a cancidate
+%D for going public.
+
+\def\backgroundline[#1]%
+ %{\doifsomething{#1}{\dobackgroundline{#1}}\hbox}
+ {\doifcolorelse{#1}{\dobackgroundline{#1}\hbox}\hbox}
+
+% \def\backgroundline[#1]%
+% {\doifcolor{#1}{\dobackgroundline{#1}}\hbox}
+
+\def\dobackgroundline#1%
+ {\dowithnextbox
+ {\hbox
+ {\localcolortrue
+ \startcolor[#1]%
+ \vrule
+ \!!width \nextboxwd
+ \!!height\nextboxht
+ \!!depth \nextboxdp
+ \stopcolor
+ \hskip-\nextboxwd
+ \flushnextbox}}}
+
+%D \macros
+%D {encircled}
+%D
+%D Some not so robust left||overs (borrowed from Knuth,
+%D \TEX Book\ page 356):
+
+\def\encircled#1%
+ {{\ooalign{\hfil\raise0.07ex\hbox{{\tx#1}}\hfil\crcr\mathhexbox20D}}}
+
+\let\omcirkeld\encircled
+
+\setuplinewidth
+ [\v!medium]
+
+\setupframed
+ [\c!width=\v!fit,
+ \c!height=\v!broad,
+ \c!lines=,
+ \c!offset=0.25ex, % \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!backgroundscreen=\@@rsscreen,
+ \c!backgroundcolor=,
+ \c!backgroundoffset=\!!zeropoint,
+ \c!framecolor=,
+ \c!frameoffset=\!!zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner,
+ \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!align=,
+ \c!bottom=\vss,
+ \c!top=,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!yes,
+ \c!location=\v!normal,
+ \c!orientation=,
+ \c!autowidth=\v!yes,
+ \c!setups=]
+
+\setupscreens
+ [%\c!factor=1.0, % obsolete
+ %\c!method=\v!external, % obsolete
+ \c!screen=0.95]
+
+\setupblackrules
+ [\c!n=3,
+ \c!width=1em,
+ \c!height=1ex,
+ \c!depth=\!!zeropoint,
+ \c!alternative=\c!a,
+ \c!distance=.25ex,
+ \c!color=]
+
+\setupmarginrules
+ [\c!level=0,
+ \c!rulethickness=\@@kadefaultwidth\linewidth]
+
+\setupthinrules
+ [\c!interlinespace=\v!small,
+ \c!n=3,
+ \c!before=,
+ \c!inbetween={\blank[\v!white]},
+ \c!after=,
+ \c!color=,
+ \c!height=.5\linewidth,
+ \c!depth=.5\linewidth,
+ \c!frame=\v!on, % compatible with textbackgrounds
+ \c!alternative=\v!b,
+ \c!backgroundcolor=,
+ \c!background=,
+ \c!rulethickness=]
+
+\setuptextrules
+ [\c!location=\v!left,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=,
+ \c!width=2em,
+ \c!style=\v!bold,
+ \c!color=,
+ \c!rulecolor=,
+ \c!bodyfont=,
+ \c!distance=.5em]
+
+\setupfillinrules
+ [\c!width=\v!broad,
+ \c!distance=1em,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!n=1,
+ \c!interlinespace=\v!small,
+ \c!separator=,
+ \c!style=\v!normal,
+ \c!color=]
+
+\setupfillinlines
+ [\c!width=3cm,
+ \c!margin=\@@ivwidth,
+ \c!distance=1em,
+ \c!before=\blank,
+ \c!after=\blank]
+
+\setupbackground
+ [\c!leftoffset=.5\bodyfontsize,
+ \c!rightoffset=\@@agleftoffset,
+ \c!topoffset=\!!zeropoint,
+ \c!bottomoffset=\@@agtopoffset,
+ \c!state=\v!start,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ \c!frame=\v!off,
+ \c!color=,
+ \c!depth=\!!zeropoint,
+ \c!background=\v!screen,
+ \c!backgroundcolor=\@@agcolor,
+ \c!screen=\@@rsscreen,
+ \c!before=,
+ \c!after=]
+
+\protect \endinput
diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv
new file mode 100644
index 000000000..afacc2901
--- /dev/null
+++ b/tex/context/base/pack-rul.mkiv
@@ -0,0 +1,3686 @@
+%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 / Hans Hagen \& Ton Otten}]
+%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 redo framedtexts like framedcontent (parameter stuff)
+
+%D After a few months testing this solution is now added
+%D to the core. This introduces a possible incompatibility
+%D between \MKII\ and \MKIV\ but for the better.
+
+\registerctxluafile{pack-rul}{1.001}
+
+% old off new
+% 4 lines oeps : 3.6 2.8 3.0
+% tufte 7.5 4.1 4.3
+
+\unprotect
+
+%D We have removed the rather old and out dated raster methods. They
+%D have not been used for ages. You can still find the old code in
+%D the \MKII\ counterpart of this module.
+
+%D This module is rather optimized so sometimes readability has been
+%D sacrisfied for speed. This is because the framing mechanism is used
+%D all over the place.
+
+%D \macros
+%D {linewidth, setuplinewidth}
+%D
+%D This module deals with rules (lines) in several ways. First
+%D we introduce two macros that can be used to set some common
+%D characteristics.
+%D
+%D \showsetup{setuplinewidth}
+%D
+%D The linewidth is available in \type{\linewidth}. The
+%D preset value of .4pt equals the default hard coded \TEX\
+%D rule width.
+
+\newdimen\linewidth
+
+\def\dosetuplinewidth[#1]%
+ {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
+
+\unexpanded\def\setuplinewidth
+ {\dosingleargument\dosetuplinewidth}
+
+%D \macros
+%D {ruledlinewidth, inheritruledlinewidth}
+%D
+%D Inside framed boxed we will use a private dimensions. As
+%D an option one can let the linewidth inherit its value from
+%D this one.
+
+\newdimen\ruledlinewidth \newif\ifinheritruledlinewidth
+
+%D \macros
+%D {setupscreens}
+%D
+%D The previous macro uses a predefined constant
+%D \type{\@@rsfactor}. This factor can be set by:
+%D
+%D \showsetup{setupscreens}
+
+\unexpanded\def\setupscreens
+ {\dodoubleargument\getparameters[\??rs]}
+
+%D We will communicate through module specific variables, current
+%D framed parameters and some reserved dimension registers.
+
+\newdimen \frameddimenwd
+\newdimen \frameddimenht
+\newdimen \frameddimendp
+
+%D We don't have to stick to a \TEX\ drawn rule, but
+%D also can use rounded or even fancier shapes, as we will
+%D see later on.
+
+\def\dofilledbox
+ {\bgroup
+ \edef\@@framedfilledmod{\framedparameter\c!backgroundcorner}%
+ \ifx\@@framedfilledmod\v!rectangular
+ \dofilledlinedbox
+ \else\ifzeropt\dimexpr\framedparameter\c!backgroundradius\relax % just in case of .x\bodyfontsize
+ \dofilledlinedbox
+ \else
+ \dofilledroundbox
+ \fi\fi
+ \egroup}
+
+\def\dophantombox
+ {\hphantom{\dofilledbox}}
+
+\def\dofilledlinedbox
+ {\vrule\!!width\frameddimenwd\!!height\frameddimenht\!!depth\frameddimendp\relax}%
+
+\def\dostrokedroundbox
+ {\doif{\framedparameter\c!frame}\v!on\dodostrokedroundbox}
+
+\def\dodostrokedroundbox
+ {\bgroup
+ \edef\ovalmod{\framedparameter\c!framecorner}%
+ \ifx\ovalmod\v!round
+ \let\ovalmod\!!zerocount
+ \else
+ \edef\ovalmod{\number\ovalmod}%
+ \fi
+ \edef\ovalwid{\the\frameddimenwd}%
+ \edef\ovalhei{\the\frameddimenht}%
+ \edef\ovaldep{\the\frameddimendp}%
+ \edef\ovallin{\the\dimexpr\ruledlinewidth}%
+ \edef\ovalrad{\the\dimexpr\framedparameter\c!frameradius}%
+ \let\ovalstr\!!plusone
+ \let\ovalfil\!!zerocount
+% \forcecolorhack
+ \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod
+ \egroup}
+
+\def\dofilledroundbox
+ {\bgroup
+ \edef\ovalmod{\framedparameter\c!backgroundcorner}%
+ \ifx\ovalmod\v!round
+ \let\ovalmod\!!zerocount
+ \else
+ \edef\ovalmod{\number\ovalmod}%
+ \fi
+ \edef\ovalwid{\the\frameddimenwd}%
+ \edef\ovalhei{\the\frameddimenht}%
+ \edef\ovaldep{\the\frameddimendp}%
+ \edef\ovallin{\the\dimexpr\ruledlinewidth\relax}%
+ \edef\ovalrad{\the\dimexpr\framedparameter\c!backgroundradius\relax}%
+ \let\ovalstr\!!zerocount
+ \let\ovalfil\!!plusone
+% \forcecolorhack
+ \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod
+ \egroup}
+
+% 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 The oval box is drawn using a special macro, depending on
+%D the driver in use.
+
+\def\dograybox % avoid black rules when no gray
+ {\doifelsenothing{\framedparameter\c!backgroundscreen}
+ {\dophantombox}
+ {\raster[\framedparameter\c!backgroundscreen]{\dofilledbox}}}
+
+%D It won't be a surprise that we not only provide gray boxes,
+%D but also colored ones. Here it is:
+
+\def\dobackgroundcolorbox
+ {\hbox{\faststartcolor[\framedbackgroundcolor]\dofilledbox\faststopcolor}}
+ %{\hbox{\doactivatecolor\framedbackgroundcolor\dofilledbox}}
+
+\def\docolorbox % can be more of \color[] -> \faststartcolor in mkiv
+ {\ifincolor
+ \edef\framedbackgroundcolor{\framedparameter\c!backgroundcolor}%
+ \ifx\framedbackgroundcolor\empty
+ \dophantombox
+ \else
+ \doifcolorelse\framedbackgroundcolor\dobackgroundcolorbox\dophantombox
+ \fi
+ \else
+ \dophantombox
+ \fi}
+
+%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
+%D backgrounds, we introduce overlays. An overlay is something
+%D that contrary to its name lays {\em under} the text. An
+%D 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
+%D non||used arguments and the two step call that enable the
+%D setting of the width, height and depth variables.
+%D 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
+%D the dimensions have a 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
+\let\overlaydepth \!!zeropoint % values. The attributes
+\let\overlayoffset \!!zeropoint % of the frame can be (are)
+\let\overlaycolor \empty % set somewhere else.
+\let\overlaylinewidth \!!zeropoint %
+\let\overlaylinecolor \empty %
+
+%D The next register is used to initialize overlays.
+
+\newtoks\everyoverlay
+
+%D An example of an initialization is the following (overlays
+%D can contain text and be executed under an regime where
+%D interlineskip is off).
+
+\appendtoks \oninterlineskip \to \everyoverlay
+
+\unexpanded\def\defineoverlay
+ {\dodoubleargument\dodefineoverlay}
+
+\def\dodefineoverlay[#1][#2]%
+ {\def\docommand##1{\setvalue{\??ov##1}{\executedefinedoverlay{##1}{#2}}}%
+ \processcommalist[#1]\docommand}
+
+\prependtoks
+ \hsize\overlaywidth
+ \vsize\overlayheight
+\to\everyoverlay
+
+\long\def\executedefinedoverlay#1#2%
+ {\bgroup
+ \setlayoutcomponentattribute\v!overlay{#1}%
+ \edef\overlaywidth {\the\frameddimenwd\space}%
+ \edef\overlayheight{\the\dimexpr\frameddimenht+\frameddimendp\relax\space}%
+ \edef\overlaydepth {\the\frameddimendp\space}%
+ \edef\overlaycolor {\framedparameter\c!backgroundcolor}%
+ %\edef\overlaycorner{\framedparameter\c!backgroundcorner}%
+ %\edef\overlayradius{\framedparameter\c!backgroundradius}%
+ \let\overlayoffset\backgroundoffset % we steal this one
+ \setbox\scratchbox\hbox{\lower\overlaydepth\hbox{\the\everyoverlay#2}}%
+ \setbox\scratchbox\hbox \layoutcomponentboxattribute
+ {\hskip-.5\dimexpr\wd\scratchbox-\overlaywidth \relax
+ \raise-.5\dimexpr\ht\scratchbox-\frameddimenht\relax % not overlayheight !
+ \box\scratchbox}%
+ \wd\scratchbox\frameddimenwd
+ \ht\scratchbox\frameddimenht
+ \dp\scratchbox\frameddimendp
+ \box\scratchbox
+ \egroup}
+
+%D The empty case is:
+
+\let\executeoverlay\gobblesevenarguments
+
+%D For testing we provide:
+
+\def\doifoverlayelse#1%
+ {\ifcsname\??ov#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+%D We predefine two already familiar backgrounds:
+
+\setvalue{\??ov\v!screen}{\dograybox }
+\setvalue{\??ov\v!color }{\docolorbox}
+
+% %D After all these preparations, the background macro does no
+% %D bring to many surprises. One has to keep in mind that this
+% %D macro starts up a call chain, depending on the background
+% %D one needs:
+% %D
+% %D \startitemize[packed]
+% %D \item a raster, color or user defined shape
+% %D \item square or round corners
+% %D \item a \TEX\ or driver based method
+% %D \stopitemize
+% %D
+% %D The macro can be extended by adding commands to the token
+% %D list register \type {\everybackgroundbox}. For this
+% %D purpose, the name of the current background is available in
+% %D \type {\currentbackgound}.
+
+%D The content of the box will be (temporary) saved in a box. We
+%D also have an extra box for backgrounds.
+
+\newbox\framebox
+\newbox\extraframebox
+
+\newtoks\everybackgroundbox
+
+\let\currentbackground\empty
+
+\def\dodobackgroundbox
+ {\bgroup
+ \ifcsname\??ov\currentbackground\endcsname
+ \the\everybackgroundbox
+ \setbox\extraframebox\hbox{\vbox{\moveleft\backgroundoffset\hbox{\csname\??ov\currentbackground\endcsname}}}%
+ \wd\extraframebox\zeropoint % \backgroundwidth
+ \ht\extraframebox\backgroundheight
+ \dp\extraframebox\backgrounddepth
+ \box\extraframebox % \hskip-\backgroundwidth
+ \fi
+ \egroup}
+
+\def\dododobackgroundbox#1,#2% #2 gobbles spaces
+ {\edef\currentbackground{#1}%
+ \ifx\currentbackground\s!unknown\else % use $ instead of s!unknown
+ \dodobackgroundbox\expandafter\dododobackgroundbox
+ \fi#2}
+
+\let\backgroundoffset\!!zeropoint
+\let\backgrounddepth \!!zeropoint
+\def\backgroundwidth {\the\hsize}
+\def\backgroundheight{\the\vsize}
+
+\def\normalforegroundbox% fuzzy but needed hack, this \vss, otherwise
+ {\vbox to \backgroundheight{\vss\box\framebox\vss}}% vertical shift
+
+\def\dobackedbox
+ {\setbox\framebox\vbox
+ {\framedforgetall
+ \boxmaxdepth\maxdimen
+ \frameddimenwd\dimexpr\wd\framebox+2\!!framedbackgroundoffset\relax
+ \frameddimenht\dimexpr\ht\framebox+ \!!framedbackgroundoffset\relax
+ \frameddimendp\dimexpr\dp\framebox+ \!!framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax
+ \edef\backgroundoffset{\the\!!framedbackgroundoffset}%
+ \edef\backgroundwidth {\the\wd\framebox}%
+ \edef\backgroundheight{\the\ht\framebox}%
+ \edef\backgrounddepth {\the\dp\framebox}%
+ %\edef\foregroundbox{\box#1}%
+ \edef\component{\framedparameter\c!component}%
+ \ifx\component\empty
+ \resetlayoutcomponentattribute
+ \else
+ \setlayoutcomponentattribute\v!background\component
+ \fi
+ \let\foregroundbox\normalforegroundbox
+ \hbox \layoutcomponentboxattribute to \backgroundwidth % width in case 'foreground' is used as overlay
+ {\expandafter\dododobackgroundbox\framedbackground,\s!unknown,\relax % hm, messy .. look into it
+ \box\framebox\hss}}}
+
+%D One can explictly insert the foreground box. For that
+%D purpose we introduce the overlay \type {foreground}.
+
+\defineoverlay[\v!foreground][\foregroundbox]
+
+%D We can specify overlays as a comma separated list of
+%D overlays, a sometimes handy feature.
+
+%D Besides backgrounds (overlays) we also need some macros to
+%D draw outlines (ruled borders). Again we have to deal with
+%D square and round corners. The first category can be handled
+%D by \TEX\ itself, the latter one depends on the driver. This
+%D macro also support a negative offset.
+
+\def\dooutlinebox % we needed to move the color command in order to apply attributes properly
+ {\setbox\framebox\vbox % rules on top of box
+ {\frameddimenwd\dimexpr\wd\framebox+2\!!framedframeoffset\relax
+ \frameddimenht\dimexpr\ht\framebox+ \!!framedframeoffset\relax
+ \frameddimendp\dimexpr\dp\framebox+ \!!framedframeoffset+\framedparameter\c!framedepth\relax
+ \ifdim\frameddimendp<\zeropoint
+ \advance\frameddimenht \frameddimendp
+ \scratchdimen-\frameddimendp
+ \frameddimendp\zeropoint
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \setbox\extraframebox\hbox
+ {\doifsomething{\framedparameter\c!framecolor}{\color[\framedparameter\c!framecolor]}{\dostrokedbox}}%
+ \setbox\extraframebox\hbox
+ {\raise\scratchdimen\vbox
+ {\moveleft\!!framedframeoffset
+ \box\extraframebox}}%
+ \wd\extraframebox\wd\framebox
+ \ht\extraframebox\ht\framebox
+ \dp\extraframebox\dp\framebox
+ \hbox{\box\framebox\hskip-\wd\extraframebox\box\extraframebox}}}
+
+\def\dostrokedbox
+ {\edef\@@framedcornermod{\framedparameter\c!framecorner}%
+ \ifx\@@framedcornermod\v!rectangular
+ \dostrokedlinedbox
+ \else\ifzeropt\dimexpr\framedparameter\c!frameradius\relax % just in case of .x\bodyfontsize
+ \dostrokedlinedbox
+ \else
+ \dostrokedroundbox
+ \fi\fi}
+
+\def\dostrokedlinedbox
+ {\setbox\scratchbox\null
+ \wd\scratchbox\frameddimenwd
+ \ht\scratchbox\frameddimenht
+ \dp\scratchbox\frameddimendp
+ \setbox\scratchbox\vbox \bgroup
+ \csname t\@@frame@@\framedparameter\c!frame\framedparameter\c!topframe \endcsname
+ \hbox \bgroup
+ \csname l\@@frame@@\framedparameter\c!frame\framedparameter\c!leftframe \endcsname
+ \box\scratchbox
+ \csname r\@@frame@@\framedparameter\c!frame\framedparameter\c!rightframe \endcsname
+ \egroup
+ \csname b\@@frame@@\framedparameter\c!frame\framedparameter\c!bottomframe\endcsname
+ \egroup
+ \wd\scratchbox\frameddimenwd
+ \ht\scratchbox\frameddimenht
+ \dp\scratchbox\frameddimendp
+ \box\scratchbox}
+
+\def\@@frame@@{@@frame@@}
+
+% \setvalue{t\@@frame@@\v!on \v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{t\@@frame@@\v!off\v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{t\@@frame@@\v!on }{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{b\@@frame@@\v!on }{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!on \v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!off\v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{l\@@frame@@\v!on }{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+% \setvalue{r\@@frame@@\v!on }{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+
+\def\@@frame@@trule{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
+\def\@@frame@@brule{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
+\def\@@frame@@rrule{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
+\def\@@frame@@lrule{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
+
+\letvalue{t\@@frame@@\v!on \v!on}\@@frame@@trule
+\letvalue{t\@@frame@@\v!off\v!on}\@@frame@@trule
+\letvalue{t\@@frame@@\v!on }\@@frame@@trule
+
+\letvalue{b\@@frame@@\v!on \v!on}\@@frame@@brule
+\letvalue{b\@@frame@@\v!off\v!on}\@@frame@@brule
+\letvalue{b\@@frame@@\v!on }\@@frame@@brule
+
+\letvalue{l\@@frame@@\v!on \v!on}\@@frame@@lrule
+\letvalue{l\@@frame@@\v!off\v!on}\@@frame@@lrule
+\letvalue{l\@@frame@@\v!on }\@@frame@@lrule
+
+\letvalue{r\@@frame@@\v!on \v!on}\@@frame@@rrule
+\letvalue{r\@@frame@@\v!off\v!on}\@@frame@@rrule
+\letvalue{r\@@frame@@\v!on }\@@frame@@rrule
+
+% no overlapping rules
+
+\def\@@frame@@trules{\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}\nointerlineskip\kern-\ruledlinewidth}
+\def\@@frame@@brules{\kern-\ruledlinewidth\nointerlineskip\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}}
+\def\@@frame@@rrules{\kern-\ruledlinewidth\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth}
+\def\@@frame@@lrules{\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth\kern-\ruledlinewidth}
+
+% small is relatively new
+
+\letvalue{t\@@frame@@\v!small\v!small}\@@frame@@trules
+\letvalue{t\@@frame@@\v!off \v!small}\@@frame@@trules
+\letvalue{t\@@frame@@\v!small }\@@frame@@trules
+
+\letvalue{b\@@frame@@\v!small\v!small}\@@frame@@brules
+\letvalue{b\@@frame@@\v!off \v!small}\@@frame@@brules
+\letvalue{b\@@frame@@\v!small }\@@frame@@brules
+
+\letvalue{l\@@frame@@\v!small\v!small}\@@frame@@lrules
+\letvalue{l\@@frame@@\v!off \v!small}\@@frame@@lrules
+\letvalue{l\@@frame@@\v!small }\@@frame@@lrules
+
+\letvalue{r\@@frame@@\v!small\v!small}\@@frame@@rrules
+\letvalue{r\@@frame@@\v!off \v!small}\@@frame@@rrules
+\letvalue{r\@@frame@@\v!small }\@@frame@@rrules
+
+%D I condidered using the low level support command
+%D \type{\ruledhbox}, but this would slow down processing by a
+%D factor~3.
+
+% \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
+%D \CONTEXT. They deal with putting rules around boxes, provide
+%D backgrounds, offer alignment features, and some more. We
+%D start with defining some booleans. These give an impression
+%D of what we are going to take into account.
+
+% todo: chardefs
+
+\newif\ifboxhasoffset
+\newif\ifboxhaswidth
+\newif\ifboxhasheight
+\newif\ifboxhasformat
+\newif\ifboxhasstrut
+\newif\ifboxisoverlaid
+\newif\ifboxhasframe
+\newif\ifdelayedstrut
+\newif\ifboxhasextraoffset
+
+%D We also need a few \DIMENSIONS:
+
+\newdimen\@@localoffset
+\newdimen\@@globalwidth
+
+%D \macros
+%D {framed, setupframed}
+%D
+%D Ruled boxes are typeset using \type{\framed}. This command
+%D is quite versatile and, although some users will probably
+%D seldom use it, one cannot overlook its features.
+%D
+%D \showsetup{setupframed}
+%D \showsetup{framed}
+%D
+%D This general macro is a special version of an even more
+%D general case, that can easily be linked into other macros
+%D that need some kind of framing. The local version is called
+%D with an extra parameter: the variable identifier. The reason
+%D for passing this identifier between brackets lays in the
+%D mere fact that this way we can use the optional argument
+%D grabbers.
+
+\def\defaultframeoffset{.25ex}
+
+\def\presetlocalframed [#1]{\letvalue{#1\s!parent}\??oi}
+\def\inheritlocalframed[#1]#2[#3]{\letvalue{#1\s!parent}#3}
+\def\copylocalframed [#1]#2[#3]{\setvalue{#1\s!parent}{#3}}
+
+\let\setuplocalframed\getparameters % obsolete
+
+\presetlocalframed[\??ol]
+
+\newcount\framednesting
+
+\unexpanded\def\framed
+ {\bgroup
+ \advance\framednesting\plusone
+ \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol
+ \dodoubleempty\startlocalframed[\??ol:\the\framednesting]}
+
+\unexpanded\def\setupframed
+ {\dodoubleempty\dosetupframed}
+
+\def\dosetupframed
+ {\ifsecondargument
+ \@EA\dodoublesetupframed
+ \else
+ \@EA\dosinglesetupframed
+ \fi}
+
+\def\dosinglesetupframed[#1][#2]%
+ {\getparameters[\??ol][#1]}
+
+\def\dodoublesetupframed[#1][#2]%
+ {\bgroup
+ \let\dodoubleempty\empty
+ \def\doframed[##1]{\gdef\globalredefinedframed{\dodoubleempty\doframed[##1,#2]}}%
+ \getvalue{#1}%
+ \egroup
+ \letvalue{#1}\globalredefinedframed}
+
+%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 \setuplocalframed[myframed][width=4cm,height=2cm]
+%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
+%D looking for the user supplied ones. The first step is
+%D omitted in the local case, because these are preset at
+%D declaration time and keep their values unless explictly
+%D changed. By presetting the variables everytime the normal
+%D command is called, we can use this command nested, without
+%D the unwanted side effect of inheritance. The boolean is
+%D used to speed up the color stack.
+
+\newif\ifinframed
+
+\def\localframed
+ {\bgroup
+ \dodoubleempty\startlocalframed}
+
+%D The next one is faster on multiple backgrounds per page. No
+%D dimensions can be set, only frames and backgrounds.
+
+\def\fastlocalframed[#1]#2[#3]#4% 3-4
+ {\bgroup
+ \inframedtrue
+ \edef\@@framed{#1}%
+ \setbox\framebox\hbox{#4}%
+ \getparameters[\@@framed][#3]% no \expanded !
+ \!!framedframeoffset\framedparameter\c!frameoffset
+ \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}%
+ \ifx\@@framedbackgroundoffset\v!frame
+ \!!framedbackgroundoffset\!!framedframeoffset
+ \else
+ \!!framedbackgroundoffset\@@framedbackgroundoffset
+ \fi
+ % not here, in calling macro: setups
+ \removeframedboxdepth
+% \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}%
+% \ifx\framedforegroundcolor\empty\else\docolorframebox\fi
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}%
+ \edef\overlaylinewidth{\the\ruledlinewidth}%
+ \edef\@@localframing {\framedparameter\c!frame}%
+ \ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else
+ \edef\framedrulethickness{\framedparameter\c!rulethickness}%
+ \ifx\framedrulethickness\empty\else
+ \ruledlinewidth\framedrulethickness\relax
+ \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \fi
+ \dooutlinebox % real or invisible frame
+ \fi \fi
+ \edef\framedbackground{\framedparameter\c!background}%
+ \ifx\framedbackground\empty\else\dobackedbox\fi
+ \restoreframedboxdepth
+ \box\framebox
+ \egroup}
+
+%D Here is another fast one:
+
+\def\localbackgroundframed#1#2#3#4% tag box wd ht
+ {\setbox#2\vbox\bgroup
+ \inframedtrue
+ \edef\@@framed{\??ma#1}%
+ \expandafter\def\csname\??ma#1\c!component\endcsname{#1}%
+ \expandafter\def\csname\??ma#1\c!width \endcsname{#3}%
+ \expandafter\def\csname\??ma#1\c!height \endcsname{#4}%
+ \!!framedframeoffset\framedparameter\c!frameoffset
+ \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}%
+ \ifx\@@framedbackgroundoffset\v!frame
+ \!!framedbackgroundoffset\!!framedframeoffset
+ \else
+ \!!framedbackgroundoffset\@@framedbackgroundoffset
+ \fi
+ \setbox\framebox\box#2%
+ \dp\framebox\zeropoint
+% \removeframedboxdepth
+% \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}%
+% \ifx\framedforegroundcolor\empty\else\docolorframebox\fi
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}%
+ \edef\overlaylinewidth{\the\ruledlinewidth}%
+ \edef\@@localframing {\framedparameter\c!frame}%
+ \ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else
+ \edef\framedrulethickness{\framedparameter\c!rulethickness}%
+ \ifx\framedrulethickness\empty\else
+ \ruledlinewidth\framedrulethickness\relax
+ \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \fi
+ \dooutlinebox % real or invisible frame
+ \fi \fi
+ \edef\framedbackground{\framedparameter\c!background}%
+ \ifx\framedbackground\empty\else\dobackedbox\fi
+% \restoreframedboxdepth
+ \box\framebox
+ \egroup}
+
+%D Before we go into details, we present (and implement) the
+%D main framing routine. I saw no real reason for splitting the
+%D next two macros into smaller pieces. The content will be
+%D collected in a horizontal or vertical box with fixed or free
+%D dimensions and specific settings concerning aligment and
+%D offsets.
+%D
+%D In the first few lines, we pre||expand the frame and
+%D background offsets. We do so, because the can be defined in
+%D terms of the main offset. However, see for instance page
+%D backgrounds, when \type {#2} sets the offset to \type
+%D {overlay}, both offsets become invalid.
+%D
+%D Because it is used so often the he next macro is (and
+%D looks) rather optimized.
+
+% \def\s!root{root} % maybe configurable
+
+\let\postprocessframebox\relax
+
+\let\@@framed\s!unknown
+
+% \def\framedparameter #1{\csname\doframedparameter\@@framed#1\endcsname}
+% \def\framedparameterhash#1{\doframedparameterhash \@@framed#1}
+%
+% \def\doframedparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedparentparameter \csname#1\s!parent\endcsname#2\fi}
+% \def\doframedparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doframedparentparameterhash\csname#1\s!parent\endcsname#2\fi}
+%
+% \def\doframedparentparameter #1#2{\ifx#1\relax\s!empty\else\doframedparameter #1#2\fi}
+% \def\doframedparentparameterhash#1#2{\ifx#1\relax \else\doframedparameterhash#1#2\fi}
+%
+% \def\doframedparentparameter#1#2{\ifx#1\relax\doframedrootparameter#2\else\doframedparameter#1#2\fi}
+% \def\doframedrootparameter #1{\ifcsname\??oi#1\endcsname\??oi#1\else\s!empty\fi}
+
+\def\framedparameter #1{\csname\doframedparameter\@@framed{#1}\endcsname}
+\def\framedparameterhash#1{\doframedparameterhash \@@framed#1}
+
+\def\doframedparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedparentparameter \csname#1\s!parent\endcsname{#2}\fi}
+\def\doframedparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doframedparentparameterhash\csname#1\s!parent\endcsname#2\fi}
+
+\def\doframedparentparameter #1#2{\ifx#1\relax\s!empty\else\doframedparameter #1{#2}\fi}
+\def\doframedparentparameterhash#1#2{\ifx#1\relax \else\doframedparameterhash#1#2\fi}
+
+\def\doframedparentparameter#1#2{\ifx#1\relax\doframedrootparameter#2\else\doframedparameter#1{#2}\fi}
+\def\doframedrootparameter #1{\ifcsname\??oi#1\endcsname\??oi#1\else\s!empty\fi}
+
+\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax}
+
+\def\dosetframedattributes#1#2% style color
+ {\edef\fontattributehash {\framedparameterhash#1}%
+ \edef\colorattributehash{\framedparameterhash#2}%
+ \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
+ \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
+
+% defaults, kind of isolated now
+
+\getparameters
+ [\??oi]
+ [\c!width=\v!fit,
+ \c!height=\v!broad,
+ %\c!lines=,
+ \c!offset=0.25ex, % \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!backgroundscreen=,
+ %\c!backgroundcolor=,
+ \c!backgroundoffset=\zeropoint,
+ %\c!framecolor=,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner,
+ \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!align=,
+ \c!bottom=\vss,
+ %\c!top=,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!yes,
+ \c!location=\v!normal,
+ %\c!orientation=,
+ \c!autowidth=\v!yes,
+ %\c!setups=
+]
+
+\getparameters
+ [\??od] % for fast version
+ [\c!frame=\v!off,
+ \c!depth=\zeropoint,
+ \c!offset=\v!overlay,
+ %\c!component=,
+ \c!radius=.5\bodyfontsize,
+ \c!rulethickness=\linewidth,
+ \c!corner=\v!rectangular,
+ \c!backgroundoffset=\zeropoint,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner,
+ \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]
+
+% so far
+
+\newdimen\!!framedwidth
+\newdimen\!!framedheight
+\newdimen\!!framedscratch % so that users can use \scratchdimen
+\newdimen\!!framedframeoffset
+\newdimen\!!framedbackgroundoffset
+
+\let\setextraframedoffsets \relax
+\let\applyextraframedoffsets\relax
+
+% todo: protect local \framednames
+
+\unexpanded\def\startlocalframed[#1][#2]%
+ {\bgroup
+ \inframedtrue
+ \edef\@@framed{#1}%
+ \ifsecondargument % faster
+ \getparameters[\@@framed][#2]% here !
+ \fi
+ \!!framedframeoffset\framedparameter\c!frameoffset
+ \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}%
+ \ifx\@@framedbackgroundoffset\v!frame
+ \!!framedbackgroundoffset\!!framedframeoffset
+ \else
+ \!!framedbackgroundoffset\@@framedbackgroundoffset
+ \fi
+ % new, experimental dirty hook
+ \framedparameter\c!extras
+ % to get the right spacing
+ \edef\fontattributehash{\framedparameterhash\c!foregroundstyle}%
+ \ifx\fontattributehash\empty\else\dosetfontattribute\fontattributehash\c!foregroundstyle\fi
+ % beware, both the frame and background offset can be overruled
+ %
+ \edef\doframedsetups{\framedparameter\c!setups}%
+ \ifx\doframedsetups\empty\else
+ \edef\doframedsetups{\noexpand\setups[\doframedsetups]}%
+ \fi
+ % 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\@@localautostrut {\framedparameter\c!autostrut}%
+ \edef\@@localframing {\framedparameter\c!frame}%
+ \edef\@@locallocation {\framedparameter\c!location}%
+ \edef\@@localorientation{\framedparameter\c!orientation}%
+ %
+ \edef\@@localautowidth {\framedparameter\c!autowidth}%
+ %
+ \ifx\@@localframing\v!overlay % no frame, no offset, no framewidth
+ \boxhasframefalse
+ \let\localoffset\v!overlay
+ \else\ifx\@@localframing\v!none % no frame, no framewidth
+ \boxhasframefalse
+ \else
+ \boxhasframetrue
+ \fi\fi
+ \ifboxhasframe
+ \edef\framedrulethickness{\framedparameter\c!rulethickness}%
+ \ifx\framedrulethickness\empty\else
+ \ruledlinewidth\framedrulethickness\relax
+ \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \fi
+ \else
+ \ruledlinewidth\zeropoint
+ \fi
+ \ifx\localformat\empty
+ \boxhasformatfalse
+ \else
+ \boxhasformattrue
+ \dosetraggedcommand\localformat
+ \edef\dobeforeframedbox{\raggedtopcommand\framedparameter\c!top}%
+ \edef\doafterframedbox {\framedparameter\c!bottom\raggedbottomcommand}%
+ \fi
+ \ifx\localoffset\v!none
+ \boxhasoffsetfalse
+ \boxhasstrutfalse
+ \boxisoverlaidfalse
+ \@@localoffset\ruledlinewidth
+ \else\ifx\localoffset\v!overlay
+ % \ifx\@@localframing\v!no \boxhasframefalse \fi % test first
+ \boxhasoffsetfalse
+ \boxhasstrutfalse
+ \boxisoverlaidtrue
+ \@@localoffset\zeropoint
+ \else
+ \boxhasoffsettrue
+ \boxhasstruttrue
+ \boxisoverlaidfalse
+ \ifx\localoffset\v!default % new per 2-6-2000
+ \let\localoffset\defaultframeoffset
+ \expandafter\let\csname\@@framed\c!offset\endcsname\defaultframeoffset
+ \else
+ \let\defaultframeoffset\localoffset
+ \fi
+ \@@localoffset\dimexpr\localoffset+\ruledlinewidth\relax
+ \fi\fi
+ \!!framedheight\zeropoint
+ \!!framedwidth \zeropoint
+ \ifx\localwidth\v!fit
+ \ifboxhasformat
+ \boxhaswidthtrue
+ \!!framedwidth\hsize
+ \else
+ \boxhaswidthfalse
+ \fi
+ \else\ifx\localwidth\v!fixed % equals \v!fit but no shapebox
+ \ifboxhasformat
+ \boxhaswidthtrue
+ \!!framedwidth\hsize
+ \else
+ \boxhaswidthfalse
+ \fi
+ \else\ifx\localwidth\v!broad
+ \boxhaswidthtrue
+ \!!framedwidth\hsize
+ \else\ifx\localwidth\v!local
+ \boxhaswidthtrue
+ \setlocalhsize
+ \!!framedwidth\localhsize
+ \else
+ \boxhaswidthtrue
+ \!!framedwidth\localwidth
+ \fi\fi\fi\fi
+ \ifx\localheight\v!fit
+ \boxhasheightfalse % no longer: \boxhasstrutfalse
+ \else\ifx\localheight\v!broad
+ \boxhasheightfalse
+ \else
+ \boxhasheighttrue
+ \!!framedheight\localheight
+ \fi\fi
+ \ifboxhasheight
+ % obey user set height, also downward compatible
+ \else
+ \edef\@@framedlines{\framedparameter\c!lines}%
+ \ifx\@@framedlines\empty\else
+ \ifcase\@@framedlines\else
+ \!!framedheight\@@framedlines\lineheight
+ \edef\localheight{\the\!!framedheight}%
+ \boxhasheighttrue
+ \fi
+ \fi
+ \fi
+ % this is now an option: width=local
+ %
+ % \ifdim\!!framedwidth=\hsize
+ % \parindent\zeropoint
+ % \setlocalhsize
+ % \!!framedwidth\localhsize
+ % \fi
+ % i.e. disable (colsetbackgroundproblemintechniek)
+ \advance\!!framedwidth -2\@@localoffset
+ \advance\!!framedheight -2\@@localoffset
+ \ifx\localstrut\v!no
+ \boxhasstrutfalse
+ \else\ifx\localstrut\v!global
+ \setstrut
+ \else\ifx\localstrut\v!local
+ \setfontstrut
+ \else
+ \setstrut
+ \fi\fi\fi
+ \ifboxhasstrut
+ \let\localbegstrut\begstrut
+ \let\localendstrut\endstrut
+ \let\localstrut \strut
+ \else
+ \let\localbegstrut\pseudobegstrut % was: \relax
+ \let\localendstrut\pseudoendstrut % was: \relax
+ \let\localstrut \pseudostrut % was: \relax
+ %\ifboxhasheight\ifdim\!!framedheight<\strutht % saveguard
+ % \let\localbegstrut\relax % but not that
+ % \let\localstrut \relax % save after all
+ %\fi\fi
+ \fi
+ \ifx\@@localautostrut\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
+ \ifboxhasheight
+ \let\\\vboxednewline
+ \ifboxhaswidth
+ \let\hairline\vboxedhairline
+ \ifboxhasformat
+ \let\next\doformatboxSomeFormat
+ \else
+ \let\next\doformatboxNoFormat
+ \fi
+ \else
+ \let\hairline\hboxedhairline
+ \ifboxhasformat
+ \let\next\doformatboxHeight
+ \else
+ \let\next\doformatboxVSize
+ \fi
+ \fi
+ \else
+ \ifboxhaswidth
+ \ifboxhasformat
+ \let\hairline\vboxedhairline
+ \let\\\vboxednewline
+ \let\next\doformatboxWidth
+ \else
+ \let\hairline\hboxedhairline
+ \let\\\hboxednewline
+ \let\next\doformatboxHSize
+ \fi
+ \else
+ \let\hairline\hboxedhairline
+ \let\\\hboxednewline
+ \let\next\doformatboxNoSize
+ \fi
+ \fi
+ \setextraframedoffsets
+ \edef\framedbackground{\framedparameter\c!background}%
+ \ifx\framedbackground\empty
+ \let\framedforgetall\forgetall
+ \else
+ \let\framedforgetall\relax
+ \forgetall
+ \fi
+ \edef\framedwidth {\ifdim\!!framedwidth >\zeropoint\the\!!framedwidth \else\!!zeropoint\fi}% a new feature, visible for user
+ \edef\framedheight{\ifdim\!!framedheight>\zeropoint\the\!!framedheight\else\!!zeropoint\fi}% a new feature, visible for user
+ \edef\framedoffset{\the\dimexpr\ifboxhasoffset\localoffset\else\zeropoint\fi}%
+ \@@startframedorientation
+ \afterassignment\dodowithframebox
+ \setbox\framebox\next}
+
+\def\dowithframebox
+ {% moved : \let\postprocessframebox\relax
+ \stoplocalframed}
+
+\def\dodowithframebox
+ {\aftergroup\dowithframebox}
+
+\let\doafterframedbox \relax
+\let\dobeforeframedbox\relax
+
+%D Carefull analysis of this macro will learn us that not all
+%D branches in the last conditionals can be encountered, that
+%D is, some assignments to \type{\next} will never occur.
+%D Nevertheless we implement the whole scheme, if not for
+%D future extensions.
+
+%D \macros
+%D {ifreshapeframebox}
+%D
+%D The last few lines tell what to do after the content of the
+%D box is collected and passed to the next macro. In the case
+%D of a fixed width and centered alignment, the content is
+%D evaluated and used to determine the most natural width. The
+%D rest 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
+
+\unexpanded\def\stoplocalframed
+ {\dontshowcomposition
+ \@@stopframedorientation % hm, wrong place ! should rotate the result (after reshape)
+ \handleframedlocator\c!before\@@locallocation
+ \ifboxhasformat
+ \ifx\@@localautowidth\v!force
+ \ifreshapeframebox\doreshapeframedbox\fi
+ \boxhaswidthfalse
+ \else
+ \ifx\localwidth\v!fit
+ \ifx\@@localautowidth\v!yes
+ \ifreshapeframebox\doreshapeframedbox\fi
+ \fi
+ \boxhaswidthfalse
+ \else\ifx\localwidth\v!fixed
+ \boxhaswidthfalse
+ \else
+ \resetshapeframebox
+ \fi\fi
+ \fi
+ \ifconditional\boxcontentneedsprocessing
+ \mkdoprocessboxcontents\framebox
+ \fi
+ \else
+ \resetshapeframebox
+ \fi
+ \ifboxhaswidth
+ \wd\framebox\!!framedwidth
+ \fi
+ \ifboxhasheight
+ \ht\framebox\!!framedheight
+ \fi
+ \doif{\framedparameter\c!empty}\v!yes\dosetfakedframebox
+ \ifboxhasextraoffset
+ \applyextraframedoffsets
+ \fi
+ \ifboxhasoffset
+ \dooffsetframebox
+ \fi
+ \ifboxisoverlaid \else
+ \dolocateframebox
+ \fi
+ \ifx\postprocessframebox\relax \else
+ \let\next\postprocessframebox
+ \let\postprocessframebox\relax % prevent nesting
+ \next\framebox
+ \fi
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}%
+ \edef\overlaylinewidth{\the\ruledlinewidth}% \@@...
+ \ifboxhasframe % real or invisible frame
+ \dooutlinebox
+ \fi
+ \ifx\framedbackground\empty\else\dobackedbox\fi
+ \handleframedlocator\c!after\@@locallocation
+ \box\framebox
+ \egroup
+ \egroup}
+
+\def\dosetfakedframebox
+ {\setbox\scratchbox\null
+ \wd\scratchbox\wd\framebox
+ \ht\scratchbox\ht\framebox
+ \dp\scratchbox\dp\framebox
+ \setbox\framebox\box\scratchbox}
+
+% test: (saves one forgetall)
+%
+% \edef\framedbackground{\framedparameter\c!background}%
+% \ifx\framedbackground\empty
+% \let\framedforgetall\forgetall
+% \else
+% \let\framedforgetall\relax
+% \forgetall
+% \fi
+
+\def\installframedlocator#1#2#3%
+ {\setvalue{\??oi:\c!location:\c!before:#1}{#2}%
+ \setvalue{\??oi:\c!location:\c!after :#1}{#3}}
+
+\def\handleframedlocator#1#2%
+ {\csname\??oi:\c!location:#1:#2\endcsname}
+
+\def\doprelocframedbox#1%
+ {\scratchdimen\dimexpr#1+\ruledlinewidth\relax
+ \ifboxhasoffset
+ \advance\scratchdimen \framedparameter\c!offset
+ \fi
+ \scratchskip\dimexpr\ht\framebox-\scratchdimen\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\framebox\ht\framebox
+ \ht\framebox\zeropoint}
+
+\installframedlocator \v!depth
+ {}
+ {\ht\framebox\dimexpr\ht\framebox-\strutdp\relax
+ \dp\framebox\strutdp
+ \box\framebox}
+
+\installframedlocator \v!height
+ {}
+ {\dp\framebox\dimexpr\ht\framebox-\strutht\relax
+ \ht\framebox\strutht
+ \box\framebox}
+
+\installframedlocator \v!high
+ {}
+ {\doprelocframedbox\strutht
+ \setbox\framebox\hbox{\lower\scratchskip\box\framebox}%
+ \ht\framebox\strutht
+ \dp\framebox\strutdp
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!line
+ {}
+ {\setbox\framebox\hbox{\lower.5\ht\framebox\box\framebox}%
+ \ht\framebox.5\lineheight
+ \dp\framebox.5\lineheight
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!low
+ {}
+ {\doprelocframedbox\strutdp
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\strutht
+ \dp\framebox\strutdp
+ \box\framebox}
+
+\installframedlocator \v!top
+ {}
+ {\doprelocframedbox\strutht
+ \setbox\framebox\hbox{\lower\scratchskip\box\framebox}%
+ \ht\framebox\scratchdimen
+ \dp\framebox\scratchskip
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!middle
+ {}
+ {\scratchdimen.5\ht\framebox
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\scratchdimen
+ \dp\framebox\scratchdimen
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!lohi
+ {\handleframedlocator\c!before\v!middle}
+ {\handleframedlocator\c!after \v!middle}
+
+\installframedlocator \v!bottom
+ {}
+ {\doprelocframedbox\strutdp
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\scratchskip
+ \dp\framebox\scratchdimen
+ \hbox{\box\framebox}}
+
+\installframedlocator \v!keep % retains height/depth
+ {\removeframedboxdepth}
+ {\restoreframedboxdepth}
+
+% also used in fastlocalframed
+
+\newdimen\originalframedwd
+\newdimen\originalframedht
+\newdimen\originalframeddp
+
+\def\removeframedboxdepth
+ {\originalframedwd\wd\framebox
+ \originalframedht\ht\framebox
+ \originalframeddp\dp\framebox
+ \ifzeropt\originalframeddp\else\setbox\framebox\hbox{\raise\originalframeddp\box\framebox}\fi
+ \wd\framebox\originalframedwd
+ \ht\framebox\dimexpr\originalframedht+\originalframeddp\relax
+ \dp\framebox\zeropoint}
+
+\def\restoreframedboxdepth
+ {\ifzeropt\originalframeddp\else\setbox\framebox\hbox{\lower\originalframeddp\box\framebox}\fi
+ \wd\framebox\originalframedwd
+ \ht\framebox\originalframedht
+ \dp\framebox\originalframeddp}
+
+% \let\@@startframedorientation\relax
+% \let\@@stopframedorientation \relax
+
+% \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\@@startframedorientation
+ {\let\@@stopframedorientation \relax
+ \ifx\@@localorientation\empty\else
+ \ifcase\@@localorientation\else
+ \scratchcounter\@@localorientation
+ \divide\scratchcounter\plustwo
+ \ifodd\scratchcounter
+ \swapmacros\framedwidth \framedheight
+ \swapmacros\localwidth \localheight
+ \swapdimens\!!framedheight\!!framedwidth
+ \def\@@stopframedorientation{\@@dostopframedorientation\plusone}%
+ \else
+ \def\@@stopframedorientation{\@@dostopframedorientation\zerocount}%
+ \fi
+ \fi
+ \fi}
+
+\def\@@dostopframedorientation#1%
+ {\ifcase#1\else
+ \swapmacros\framedwidth \framedheight
+ \swapmacros\localwidth \localheight
+ \swapdimens\!!framedheight\!!framedwidth
+ \fi
+ \setbox\framebox\hbox{\dorotatebox\@@localorientation\hbox{\box\framebox}}}
+
+%D The last conditional takes care of the special situation of
+%D in||line \inframed[height=3cm]{framed} boxes. Such boxes have
+%D to be \inframed{aligned} with the running text.
+
+\def\doinframed[#1]% we could omit #1] but readibility ...
+ {\framed[\c!location=\v!low,#1]}
+
+\unexpanded\def\inframed
+ {\dosingleempty\doinframed}
+
+%D When we set \type{empty} to \type{yes}, we get
+%D ourselves a frame and/or background, but no content, so
+%D actually we have a sort of phantom framed box.
+
+%D Because color marks and specials can interfere with
+%D spacing, we provide a way to specify a foregroundcolor.
+
+\def\docolorframebox
+ {\doifcolor\framedforegroundcolor
+ {\setbox\framebox\hbox{\faststartcolor[\framedforegroundcolor]\box\framebox\faststopcolor}}}
+ %{\setbox\framebox\hbox{\doactivatecolor\framedforegroundcolor\box\framebox}}}
+
+%D \macros
+%D {mframed, minframed}
+%D
+%D When Tobias asked how to frame mathematical elements in
+%D formulas, Taco's posted the 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
+%D one would expect, we move the test to the outer level. We
+%D 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
+%D takes care of setting the super- and subscripts styles
+
+\newcount\mframedstyle
+
+\def\doinlinemframed[#1]#2%
+ {\begingroup
+ \mframedstyle\mathstyle\relax
+ \inframed[#1]{\Ustartmath\triggermathstyle\mframedstyle#2\Ustopmath}%
+ \endgroup}
+
+\def\funnymathstrut{\Ustartmath\triggermathstyle\mframedstyle\vphantom{(}\Ustopmath}
+
+\def\dodisplaymframed[#1]#2%
+ {\begingroup
+ \mframedstyle\mathstyle\relax
+ \let\normalstrut\funnymathstrut
+ \framed[#1]{\Ustartmath\triggermathstyle\mframedstyle#2\Ustopmath}%
+ \endgroup}
+
+\def\mframed {\dosingleempty\dodisplaymframed}
+\def\inmframed{\dosingleempty\doinlinemframed }
+
+%D So instead of the rather versatile \type {\framed}, we ue
+%D the \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
+%D
+%D \getbuffer
+%D
+%D However, we got into troubles when we want to nest sub- and
+%D superscripts, like in
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y^{\mframed{z}_{\mframed{z}}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D Therefore, we can best use \type {\super} and \type {\suber}
+%D instead of \type {^} and \type {_}. Both commands take care
+%D of proper font switching.
+%D
+%D \startbuffer
+%D \startformula
+%D x \times \mframed{y} \times y\super{\mframed{z}\suber{\mframed{z}}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D As usual, one can specify in what way the text should be
+%D framed. One should be aware of the fact that, inorder to
+%D preserve the proper spacing, the \type {offset} is set to
+%D \type {overlay} and \type {frameoffset} is used used
+%D instead.
+%D
+%D \startbuffer
+%D \startformula
+%D x \times y\super{\mframed[framecolor=red]{z}\suber{z}}
+%D \stopformula
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+%D
+%D For inline use, we also provide the \type {\inmframed}
+%D alternative: we want $x \times \inmframed{y}$ in inline
+%D math, right?
+
+%D This previous framing macros needs a lot of alternatives for
+%D putting rules around boxes, inserting offsets and aligning
+%D text. Each step is handled by separate macros.
+
+\def\dowidenframebox#1%
+ {\setbox\framebox\vbox
+ {\kern#1\hbox{\kern#1\box\framebox\kern#1}\kern#1}}
+
+\def\dooffsetframebox{\dowidenframebox\localoffset}
+\def\dolocateframebox{\dowidenframebox\ruledlinewidth}
+
+%D Let's hope that the next few examples show us enough of
+%D what needs to be 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=nee,offset=.5cm] {rule based learning}
+%D \framed[strut=nee,offset=0cm] {rule based learning}
+%D \framed[strut=nee,offset=none] {rule based learning}
+%D \framed[strut=nee,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
+%D between borders with straight lines and those with round
+%D corners. When using the first alternative it is possible to
+%D turn off one or more lines. More fancy shapes are also
+%D possible by specifying dedicated backgrounds. Turning lines
+%D on and off is implemented as efficient as possible and as a
+%D result is interface language dependant. This next
+%D implementation evolved from simpler ones. It puts for
+%D instance the rules on top of the content and provides
+%D additional offset capabilities. The lot of calls to other
+%D macros makes this mechanism not that easy to comprehend.
+
+%D We handle left, right or middle alignment as well as fixed
+%D or free widths and heights. Each combination gets its own
+%D macro.
+
+%D The following code handles one-liners: \type{align={line,flushright}}.
+%D Beware, since we entered a group and either or not grab the next
+%D bgroup token, we need to finish the group in the oneliner mode.
+
+\ifx\raggedoneliner\undefined \chardef\raggedoneliner\zerocount \fi
+
+\def\doformatonelinerbox % beware: assumes explicit preceding bgroup
+ {\ifcase\raggedoneliner
+ \expandafter\nodoformatonelinerbox
+ \else
+ \expandafter\dodoformatonelinerbox
+ \fi}
+
+\def\dodoformatonelinerbox
+ {\dowithnextboxcontent
+ {\ignorespaces}
+ {\hbox to \hsize
+ {\ifcase\raggedstatus\or\hss\or\hss\fi
+ \unhbox\nextbox \removeunwantedspaces
+ \ifcase\raggedstatus\or \or\hss\or\hss\fi}%
+ \egroup}
+ \hbox}
+
+\def\nodoformatonelinerbox % grabs {
+ {\let\next=}
+
+%D The handlers:
+
+\def\framedforgetall{\forgetall}
+
+\def\setframedforegroundcolor
+ {\edef\colorattributehash{\framedparameterhash\c!foregroundcolor}%
+ \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash\c!foregroundcolor\fi}
+
+\def\doformatboxSomeFormat
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \framedforgetall
+ \setframedforegroundcolor
+ \oninterlineskip
+ \hsize\!!framedwidth
+ \vsize\!!framedheight
+ \doframedsetups
+ \raggedcommand
+ \dobeforeframedbox
+ \bgroup
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\doafterframedbox
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxNoFormat
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \framedforgetall
+ \setframedforegroundcolor
+ \oninterlineskip
+ \hsize\!!framedwidth
+ \vsize\!!framedheight
+ \doframedsetups
+ \raggedcenter
+ \vss
+ \bgroup
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxHeight
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \framedforgetall
+ \setframedforegroundcolor
+ \oninterlineskip
+ \doframedsetups
+ \raggedcommand
+ \vss
+ \bgroup
+ \aftergroup\localendstrut
+ \aftergroup\vss
+ \aftergroup\egroup
+ \localbegstrut
+ \doformatonelinerbox}
+
+\def\doformatboxWidth
+ {\vbox
+ \bgroup
+ \let\postprocessframebox\relax
+ \framedforgetall
+ \setframedforegroundcolor
+ \oninterlineskip
+ \hsize\!!framedwidth
+ \doframedsetups
+ \raggedcommand
+ \dobeforeframedbox
+ \bgroup
+ \localbegstrut
+ \aftergroup\localendstrut
+ \aftergroup\doafterframedbox
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxVSize
+ {\vbox to \!!framedheight
+ \bgroup
+ \let\postprocessframebox\relax
+ \framedforgetall
+ \setframedforegroundcolor
+ \vsize\!!framedheight
+ \doframedsetups
+ \vss
+ \bgroup
+ \aftergroup\vss
+ \aftergroup\egroup
+ \hbox
+ \bgroup
+ \aftergroup\egroup
+ \localstrut
+ \doformatonelinerbox}
+
+\def\doformatboxHSize
+ {\hbox to \!!framedwidth
+ \bgroup
+ \let\postprocessframebox\relax
+ \framedforgetall
+ \setframedforegroundcolor
+ \doframedsetups
+ \hss
+ \localstrut
+ \bgroup
+ \aftergroup\hss
+ \aftergroup\egroup
+ \doformatonelinerbox}
+
+\def\doformatboxNoSize
+ {\hbox
+ \bgroup
+ \setframedforegroundcolor
+ \let\postprocessframebox\relax
+ \doframedsetups
+ \localstrut
+ \doformatonelinerbox}
+
+\let\doframedsetups\relax
+
+%D On the next page we show some examples of how these macros
+%D come into action. The examples show us how
+%D \type {fit}, \type {broad} dimensions influence the
+%D formatting. Watch the visualized struts. \footnote {Here we
+%D used \type {\showstruts}.}
+%D
+%D \startpostponing
+%D \bgroup
+%D \showstruts
+%D \dontcomplain
+%D \startlinecorrection
+%D \halign{#\enskip\enskip\enskip\enskip\enskip\cr
+%D \framed[width=.2\hsize, height=.2\hsize, align=] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=yes] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=yes] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=yes] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=yes] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=yes] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=right] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=right] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=right] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=right] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=right] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=right] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=left] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=left] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=left] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=left] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=left] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=left] {a\par b\par c}\cr
+%D \noalign{\vskip1em}
+%D \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=broad, align=middle] {a\par b\par c}&
+%D \framed[width=.2\hsize, height=fit, align=middle] {a\par b\par c}&
+%D \framed[width=fit, height=.2\hsize, align=middle] {a\par b\par c}&
+%D \framed[width=fit, height=broad, align=middle] {a\par b\par c}&
+%D \framed[width=fit, height=fit, align=middle] {a\par b\par c}\cr}
+%D \stoplinecorrection
+%D \blank[2*big]
+%D \egroup
+%D \stoppostponing
+
+%D \macros
+%D {framednoflines, framedlastlength}
+%D
+%D It is possible to let the frame macro calculate the width
+%D of a centered box automatically (\type {fit}). When
+%D doing so, we need to reshape the box:
+
+\newcount\framednoflines
+\newdimen\framedlastlength
+
+\def\resetshapeframebox
+ {\framednoflines \zerocount
+ \framedlastlength\zeropoint}
+
+\let\framedboxwidth \!!zeropoint
+\let\framedboxheight\!!zeropoint
+\let\framedboxdepth \!!zeropoint
+
+\def\doreshapeframedbox{\ifvbox\framebox\ctxlua{commands.doreshapeframedbox(\number\framebox)}\fi}
+
+%D The two variables \type {\framednoflines} and \type
+%D {\framedlastlength} can be used in a second pass to
+%D optimized framed material.
+
+% 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
+%D frame as well as the background an additional offset and
+%D even a bit more depth. The blue outline is the frame, the
+%D red box is the background and the small black outline is the
+%D visualization of the resulting box, that is, we applied
+%D \type{\ruledhbox} to the result.
+
+%D \startpostponing
+%D \bgroup
+%D \unprotect
+%D \dontcomplain
+%D
+%D \startbuffer
+%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 \stopbuffer
+%D
+%D \getbuffer \page
+%D
+%D {\setupframed[depth=4pt]\getbuffer} \page
+%D
+%D \protect
+%D \egroup
+%D \stoppostponing
+
+%D When typesetting the framed box inline, we have to keep the
+%D baseline intact outside as well as inside the framed box.
+
+\def\doinlineframedbox
+ {\scratchdimen\dimexpr\strutdp+\ruledlinewidth\relax
+ \ifboxhasoffset
+ \advance\scratchdimen \framedparameter\c!offset
+ \fi
+ \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
+ \ht\framebox\strutht
+ \dp\framebox\strutdp
+ \box\framebox}
+
+%D We can also lower the box over the natural depth of the
+%D line.
+
+\def\doloweredframedbox
+ {\ht\framebox\dimexpr\ht\framebox+\dp\framebox-\strutdp\relax
+ \dp\framebox\strutdp
+ \box\framebox}
+
+%D Hanging the content is mainly meant for cases like the
+%D following:
+%D
+%D \starttyping
+%D \framed[strut=no]
+%D {\framed[height=2cm,location=hanging]{test}%
+%D \framed[height=1cm,location=hanging]{test}}
+%D \stoptyping
+
+\def\dohangingframedbox % best with strut=no
+ {\scratchdimen\dimexpr\ht\framebox+\dp\framebox\relax
+ \ht\framebox\zeropoint
+ \dp\framebox\scratchdimen}
+
+%D We can draw lines from left to right and top to bottom by
+%D using the normal \type{\hairline} command. Both directions
+%D 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
+%D possible to the circumstances and act as natural as
+%D possible.
+
+\def\vboxedhairline
+ {\bgroup
+ \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi
+ \dimen4=\dimexpr\dimen2+\ruledlinewidth\relax
+ \setbox0\vbox
+ {\advance\hsize 2\dimen4
+ \vskip\dimen2
+ \hrule
+ \!!height\ruledlinewidth
+ \!!depth\zeropoint
+ \!!width\hsize
+ \vskip\dimen2}%
+ %\endgraf\nointerlineskip\endgraf
+ %\moveleft\dimen4\box0
+ %\endgraf\nointerlineskip\localbegstrut
+ \endgraf\obeydepth\nointerlineskip
+ \moveleft\dimen4\box0
+ \endgraf\nointerlineskip\localbegstrut % beware, we might kill it in a style using \vskip\lineheight
+ \egroup} % so this must not be changed
+
+\def\hboxedhairline % use framed dimen
+ {\bgroup
+ \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi
+ \ifboxhasheight
+ \dimen4\dimexpr\localheight/2+\strutdp-2\ruledlinewidth\relax
+ \dimen6\dimexpr\localheight/2-\strutdp+2\ruledlinewidth\relax
+ \else
+ \dimen4\dimexpr\strutht+\dimen2\relax
+ \dimen6\dimexpr\strutdp+\dimen2\relax
+ \fi
+ \unskip
+ \setbox\scratchbox\hbox
+ {\hskip\dimen2
+ \vrule\!!height\dimen4\!!depth\dimen6\!!width\ruledlinewidth
+ \hskip\dimen2}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \ignorespaces
+ \egroup}
+
+%D The argument of the frame command accepts \type{\\} as a
+%D sort of newline signal. In horizontal boxes it expands to a
+%D space.
+
+\def\vboxednewline
+ {\endgraf\ignorespaces}
+
+\def\hboxednewline
+ {\unskip\normalspace\ignorespaces}
+
+%D We can set each rule on or off. The default setting is
+%D inherited from \type{frame}. An earlier implementation
+%D use a bit different approach, but the new one seems more
+%D 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 {setupblackrules}
+%D
+%D The graphic capabilities of \TEX\ do not go beyond simple
+%D filled rules, except of course when using specials. Let's
+%D start with a warning: using this commands is far more slower
+%D than using the \TEX\ primitives \type{\hrule} and
+%D \type{\vrule}, but they save us some tokens. The
+%D characteristics of these rule drawing command can be set by:
+%D
+%D \showsetup{setupblackrules}
+
+\unexpanded\def\setupblackrules
+ {\dodoubleargument\getparameters[\??bj]}
+
+%D \macros
+%D {blackrule}
+%D
+%D The simple command draws only one rule. Its optional
+%D argument can be used to specify the dimensions. By setting
+%D the width, height or depth to \type {max}, one gets the
+%D natural dimensions.
+%D
+%D \showsetup{blackrule}
+
+\def\complexblackrule[#1]%
+ {\hbox\bgroup\getparameters[\??bj][#1]\domakeblackrule\egroup}
+
+\def\simpleblackrule
+ {\hbox\bgroup\domakeblackrule\egroup}
+
+\def\domakeblackrule
+ {\doif\@@bjwidth \v!max{\def\@@bjwidth {1em}}%
+ \doif\@@bjheight\v!max{\setstrut\let\setstrut\relax\def\@@bjheight{\strutht}}%
+ \doif\@@bjdepth \v!max{\setstrut\def\@@bjdepth {\strutdp}}%
+ \startcolor[\@@bjcolor]% can be made faster, just direct attr
+ \vrule
+ \!!width \@@bjwidth
+ \!!height\@@bjheight
+ \!!depth \@@bjdepth
+ \stopcolor}
+
+\definecomplexorsimple\blackrule
+
+%D \macros
+%D {blackrules}
+%D
+%D One can call for a sequence of black rules, if needed
+%D equally spaced over the given width.
+%D
+%D \showsetup{blackrules}
+%D
+%D The two alternative calls are therefore:
+%D
+%D \startbuffer
+%D Tell me, is this according to the \blackrules[n=6]?
+%D These \blackrules[alternativevariant=b,n=10,distance=.2em,width=4cm] are quite clear.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or:
+%D
+%D \startvoorbeeld
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D \stopvoorbeeld
+%D
+%D We could of course have implemented this macro using
+%D \type{\leaders}, but this would probably have taken more
+%D tokens.
+
+\def\doblackrules[#1]%
+ {\hbox\bgroup
+ \getparameters[\??bj][#1]%
+ \!!widtha\@@bjwidth
+ \!!widthb\@@bjdistance
+ \doif\@@bjalternative\c!b
+ {\scratchcounter\@@bjn
+ \ifnum\scratchcounter=\plusone
+ \!!widthb\zeropoint
+ \else
+ \advance\scratchcounter \minusone
+ \advance\!!widtha -\scratchcounter\!!widthb
+ \divide \!!widtha \@@bjn
+ \fi}%
+ \startcolor[\@@bjcolor]%
+ \dorecurse\@@bjn
+ {\vrule
+ \!!width \!!widtha
+ \!!height\@@bjheight
+ \!!depth \@@bjdepth
+ \hskip\!!widthb}%
+ \unskip
+ \stopcolor
+ \egroup}
+
+\unexpanded\def\blackrules
+ {\dosingleempty\doblackrules}
+
+%D The next commands can be used to draw margin rules. We
+%D support two methods: \marginrule{one for in||line use} and
+%D one that acts on a paragraph. Drawing a margin rule is
+%D rather straightforward because we can use the commands that
+%D put text in the margin.
+
+\def\dodrawmarginrule
+ {\setbox\scratchbox\hbox
+ {\vrule\!!depth\strutdepth\!!height\strutheight\!!width\@@karulethickness}%
+ \smashbox\scratchbox % no \vsmash !!!
+ \box\scratchbox}
+
+\def\drawmarginrule
+ {\strut\inleft{\dodrawmarginrule}}
+
+%D \macros
+%D {marginrule}
+%D
+%D The first method gobbles words and simply puts a bar in the
+%D margin. This method is not entirely robust.
+%D
+%D \showsetup{marginrule}
+
+\definecomplexorsimple\marginrule
+
+\def\simplemarginrule
+ {\let\processword\drawmarginrule
+ \processwords}
+
+\def\complexmarginrule[#1]%
+ {\ifnum#1<\@@kalevel\relax \else
+ \def\@@kadefaultwidth{#1}%
+ \expandafter\simplemarginrule
+ \fi}
+
+%D We need an auxiliary variable
+
+\def\@@kadefaultwidth{1}
+
+%D \macros
+%D {setupmarginrules}
+%D
+%D This macro definitions show us that we can pass an optional
+%D level, which is matched against the previous set one. The
+%D level can be set up with
+%D
+%D \showsetup{setupmarginrules}
+
+\unexpanded\def\setupmarginrules
+ {\dodoubleargument\getparameters[\??ka]}
+
+%D \macros
+%D {startmarginrule}
+%D
+%D The second method collects text and reformats it afterwards,
+%D using the shapebox macros. We prevent local margin rules.
+%D
+%D \showsetup{startmarginrule}
+
+\definecomplexorsimple\startmarginrule
+
+\def\simplestartmarginrule
+ {\bgroup
+ \let\drawmarginrule\relax
+ \let\stopmarginrule\dostopmarginrule
+ \beginofshapebox}
+
+\def\complexstartmarginrule[#1]%
+ {\bgroup
+ \let\drawmarginrule\relax
+ \ifnum#1<\@@kalevel\relax
+ \let\stopmarginrule\egroup
+ \else
+ \def\@@kadefaultwidth{#1}%
+ \let\stopmarginrule\dostopmarginrule
+ \expandafter\beginofshapebox
+ \fi}
+
+\def\dostopmarginrule
+ {\endofshapebox
+ \reshapebox
+ {\hbox{\inleftmargin{\dodrawmarginrule}\box\shapebox}}%
+ \flushshapebox
+ \egroup}
+
+%D \startbuffer
+%D \setupmarginrules[level=5]
+%D
+%D \startmarginrule[1]
+%D First we set the level at~5. Next we typeset this first
+%D paragraph as a level~1 one. As expected no rule show up.
+%D \stopmarginrule
+%D
+%D \startmarginrule[5]
+%D The second paragraph is a level~5 one. As we can see here,
+%D the marginal rule gets a width according to its level.
+%D \stopmarginrule
+%D
+%D \startmarginrule[8]
+%D It will of course be no surprise that this third paragraph
+%D has a even thicker margin rule. This behavior can be
+%D overruled by specifying the width explictly.
+%D \stopmarginrule
+%D \stopbuffer
+%D
+%D In next example we show most features. Watch the rule
+%D thickness adapting itself to the level.
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D We just said:
+%D
+%D \typebuffer
+
+%D \macros
+%D {vl, hl}
+%D
+%D The command \type{\vl} draws a vertical rule \vl\ with strut
+%D dimensions, multiplied with the factor specified in the
+%D optional argument. The height and depth are clipped \vl[3]
+%D to the baselinedistance. Its horizontal counterpart
+%D \type{\hl} draws a horizontal rule \hl\ with a width of 1em,
+%D multiplied with the optional factor. The horizontal rule is
+%D drawn on top of the baseline.
+%D
+%D \showsetup{vl}
+%D \showsetup{hl}
+
+\def\dovlwdhtdp#1#2#3%
+ {\bgroup
+ \!!dimena#2\strutht
+ \!!dimenb#3\strutdp
+ \setbox\scratchbox\hbox
+ {\vrule
+ \!!width #1\linewidth
+ \!!height\!!dimena
+ \!!depth \!!dimenb}%
+ \dp\scratchbox\strutdp
+ \ht\scratchbox\strutht
+ \box\scratchbox
+ \egroup}
+
+\def\complexvl[#1]%
+ {\dovlwdhtdp{1}{#1}{#1}}
+
+\def\complexhl[#1]%
+ {\hbox
+ {\vrule
+ \!!width #1\s!em
+ \!!height\linewidth
+ \!!depth \zeropoint}}
+
+\definecomplexorsimple\vl \def\simplevl{\complexvl[1]}
+\definecomplexorsimple\hl \def\simplehl{\complexhl[1]}
+
+%D \macros
+%D {hairline, thinrule, thinrules, setupthinrules}
+%D
+%D Drawing thin lines can of course easily be accomplished by
+%D the \TEX\ primitives \type{\hrule} and \type{\vrule}. The
+%D next few macros however free us from some specifications.
+%D
+%D \startbuffer
+%D some text
+%D
+%D \hairline
+%D
+%D some more text
+%D
+%D \thinrule
+%D
+%D more and more text
+%D
+%D hi \thinrule\ there
+%D
+%D and then the final text
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D becomes
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D So we've got
+%D
+%D \showsetup{hairline}
+%D \showsetup{thinrule}
+%D
+%D Both can be set up with:
+%D
+%D \showsetup{setupthinrules}
+%D
+%D We also have
+%D
+%D \showsetup{thinrules}
+%D
+%D which looks like: \thinrules[n=2]
+
+\def\thinrule
+ {\strut
+ \bgroup
+ \chardef\ruletype\plusone
+ \processaction
+ [\@@dlalternative]
+ [ \v!a=>\chardef\ruletype0,% no line
+ %\v!b=>\chardef\ruletype1,% height/depth
+ \v!c=>\chardef\ruletype2,% topheight/botdepth
+ % 11=>\chardef\ruletype1,% fallback for backgrounds
+ 0=>\chardef\ruletype0,% compatible with backgrounds
+ % 1=>\chardef\ruletype1,% compatible with backgrounds
+ 2=>\chardef\ruletype2]% compatible with backgrounds
+ \doifsomething\@@dlrulethickness
+ {\linewidth\@@dlrulethickness}%
+ \ifdim\linewidth=\zeropoint
+ \chardef\ruletype\zerocount
+ \else
+ \doifnot\@@dlframe\v!on{\chardef\ruletype\zerocount}%
+ \fi
+ \ifnum\ruletype=\plusone
+ \doif\@@dlheight\v!max{\let\@@dlheight\!!plusone}%
+ \doif\@@dldepth \v!max{\let\@@dldepth \!!plusone}%
+ \else
+ \let\@@dlheight\!!plusone
+ \let\@@dldepth\!!plusone
+ \fi
+ \freezedimensionwithunit\@@dlheight\strutht
+ \freezedimensionwithunit\@@dldepth\strutdp
+ \divide\linewidth \plustwo
+ \doifelse\@@dlbackground\v!color
+ {\startcolor[\@@dlbackgroundcolor]%
+ \ifnum\ruletype=\plustwo % prevent overshoot due to rounding
+ \leaders
+ \hrule
+ \!!height\dimexpr\@@dlheight-.5\linewidth\relax
+ \!!depth \dimexpr\@@dldepth -.5\linewidth\relax
+ \hfill
+ \else
+ \leaders
+ \hrule
+ \!!height\@@dlheight
+ \!!depth \@@dldepth
+ \hfill
+ \fi
+ \stopcolor
+ \ifcase\ruletype
+ % no rule
+ \or
+ \startcolor[\@@dlcolor]%
+ \hfillneg
+ \leaders\hrule\!!height\linewidth\!!depth\linewidth\hfill
+ \stopcolor
+ \or
+ \startcolor[\@@dlcolor]%
+ \hfillneg\leaders\hrule\!!height\dimexpr-\@@dldepth+\linewidth\relax\!!depth\@@dldepth\hfill
+ \hfillneg\leaders\hrule\!!height\@@dlheight\!!depth\dimexpr-\@@dlheight+\linewidth\relax\hfill
+ \stopcolor
+ \fi}
+ {\ifcase\ruletype \else
+ \startcolor[\@@dlcolor]%
+ \leaders\hrule\!!height\@@dlheight\!!depth\@@dldepth\hfill
+ \stopcolor
+ \fi}%
+ \strut
+ \carryoverpar\egroup}
+
+\def\hairline
+ {\endgraf
+ \thinrule
+ \endgraf}
+
+\def\dosetupthinrules[#1]%
+ {\getparameters[\??dl][#1]}
+
+\unexpanded\def\setupthinrules
+ {\dosingleargument\dosetupthinrules}
+
+\def\dothinrules[#1]%
+ {\bgroup
+ \dosetupthinrules[#1]%
+ \@@dlbefore
+ \assignvalue\@@dlinterlinespace\@@dlinterlinespace{1.0}{1.5}{2.0}%
+ \spacing\@@dlinterlinespace
+ \dorecurse\@@dln
+ {\ifnum\recurselevel=\@@dln \dothinrulesnobreak \else
+ \ifnum\recurselevel=2 \dothinrulesnobreak \fi\fi
+ \thinrule
+ \ifnum\recurselevel<\@@dln\relax
+ % test needed, else messed up whitespace
+ \ifx\@@dlinbetween\empty
+ \softbreak
+ \else
+ \endgraf
+ \nowhitespace
+ \@@dlinbetween
+ \fi
+ \fi}%
+ \doifelsenothing\@@dlafter
+ {\carryoverpar\egroup}
+ {\@@dlafter\egroup}}
+
+\def\thinrules
+ {\dosingleempty\dothinrules}
+
+%D A couple of examples are given below.
+%D
+%D \startbuffer
+%D \setupthinrules[n=3,inbetween=,color=gray]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [color=green] test test \par
+%D test test \thinrules [height=max, depth=max] test test \par
+%D
+%D \setupthinrules[height=.9,depth=.9]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [alternativevariant=b] test test \par
+%D test test \thinrules [alternativevariant=c] test test \par
+%D test test \thinrules [alternativevariant=c,inbetween=\vskip2ex] test test \par
+%D \stopbuffer
+%D
+%D \typebuffer {\getbuffer}
+%D
+%D There are a couple of alternative ways to visualize rules
+%D using backgrounds. At first sight these may look strange,
+%D but they make sense in educational settings. The
+%D alternatives are more or less compatible with the more
+%D advanced \METAPOST\ based implementation.
+%D
+%D \startbuffer[a]
+%D \setupthinrules
+%D [n=2,
+%D backgroundcolor=gray ,
+%D rulethickness=1pt,
+%D colorkleur=donkerblauw,
+%D after=\blank,
+%D before=\blank]
+%D \stopbuffer
+%D
+%D \typebuffer[a]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a]
+%D \thinrules[alternativevariant=b]
+%D \thinrules[alternativevariant=c]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,background=color]
+%D \thinrules[alternativevariant=b,background=color]
+%D \thinrules[alternativevariant=c,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=b,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=c,height=.8,depth=.8,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+
+%D \macros
+%D {optimizethinrules}
+%D
+%D By saying \type {\thinrulestrue} or \type {-false}, we
+%D can influence the way dangling lines are handled.
+
+\newif\ifoptimizethinrules \optimizethinrulestrue
+
+\def\dothinrulesnobreak
+ {\ifoptimizethinrules\penalty500\fi}
+
+%D \macros
+%D {startframedtext, setupframedtexts, defineframedtext}
+%D
+%D The general framing command we discussed previously, is not
+%D entirely suited for what we call framed texts, as for
+%D instance used in intermezzo's. The next examples show what
+%D 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
+%D as well as the 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<>}
+%D \showsetup{<>}
+%D
+%D The next definition shows the defaults.
+
+\def\dodefineframedtext[#1][#2]%
+ {\presetlocalframed[\??kd#1]%
+ \getparameters[\??kd#1]
+ [\c!width=0.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!foregroundcolor=,
+ \c!foregroundstyle=,
+ \c!background=,
+ \c!backgroundcolor=,
+ \c!backgroundscreen=\@@rsscreen,
+ \c!linecorrection=\v!on,
+ \c!depthcorrection=\v!on,
+ \c!margin=\v!standard,
+ \c!orientation=,
+ \c!indenting=,
+ #2]%
+ \setuvalue{\e!start#1}{\dostartframedtext[#1]}%
+ \setuvalue{\e!stop #1}{\dostopframedtext }%
+ \setuvalue {#1}{\doframedtext [#1]}}
+
+\unexpanded\def\defineframedtext
+ {\dodoubleempty\dodefineframedtext}
+
+%D We define the general (and original) case by just saying:
+
+\defineframedtext[\v!framedtext]
+
+%D We need several steps before the actual job is done,
+%D because we have to handle an optional identifier (and
+%D because these commands evolved out of a single case).
+
+\def\framedtextparameter#1#2% todo: currentframedtext
+ {\csname\??kd#1#2\endcsname}
+
+\def\dosetupframedtexts[#1][#2]%
+ {\ifsecondargument
+ \def\docommand##1{\getparameters[\??kd##1][#2]}%
+ \processcommacommand[#1]\docommand % new, #1 may be macro
+ \else
+ \getparameters[\??kd\v!framedtext][#1]%
+ \fi}
+
+\unexpanded\def\setupframedtexts
+ {\dodoubleempty\dosetupframedtexts}
+
+\def\dostartframedtext
+ {\bgroup\dotripleempty\dodostartframedtext}
+
+\def\dodostartframedtext[#1][#2][#3]%
+ {\doifassignmentelse{#2}
+ {\dododostartframedtext[#1][][#2]}
+ {\dododostartframedtext[#1][#2][#3]}}
+
+\setfalse\framedtextlocationnone
+
+\def\checkframedtext % messy dependency
+ {\ifinsidefloat
+ \localhsize\hsize
+ \else\ifdim\sidefloatvsize>\zeropoint % will be proper handle
+ % \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
+ \else
+ \localhsize\hsize
+ \fi\fi}
+
+\def\dododostartframedtext[#1][#2][#3]% #3 only passed to framed, not to framedtext
+ {\doifsomething{#2}{\setvalue{\??kd#1\c!location}{#2}}% does not listen to #3
+ \setfalse\framedtextlocationnone
+ \processaction % \v!low en \v!depth are already taken !
+ [\framedtextparameter{#1}\c!location]
+ [ \v!left=>\letvalue{\??kd#1\c!left }\relax
+ \letvalue{\??kd#1\c!right}\hfill,
+ \v!right=>\letvalue{\??kd#1\c!left }\hfill
+ \letvalue{\??kd#1\c!right}\relax,
+ \v!middle=>\letvalue{\??kd#1\c!left }\hfill
+ \letvalue{\??kd#1\c!right}\hfill,
+ \v!none=>\letvalue{\??kd#1\c!left }\relax % new
+ \letvalue{\??kd#1\c!right}\relax % new
+ \settrue\framedtextlocationnone]%
+ \letvalue{\??kd#1\c!location}\empty
+ % removed 06/2001
+ % \forgetparindent
+ % added 06/2001 [see demo-bbv]
+ \localhsize\hsize \checkframedtext
+ % so far
+ \setbox\framebox\vbox
+ \startboxedcontent
+ \hsize\localhsize
+ % \insidefloattrue % ? better
+ \normalexpanded{\noexpand\switchtobodyfont[\framedtextparameter{#1}\c!bodyfont]}%
+ \startcolor[\framedtextparameter{#1}\c!color]%
+ \localframed[\??kd#1][\c!strut=\v!no,#3]% todo: use delayedstrut
+ \bgroup
+ \let\\=\endgraf
+ \framedtextparameter{#1}\c!inner % oud spul
+ \doifvalue{\??kd#1\c!depthcorrection}\v!on % new, inside box
+ {\bgroup
+ \verticalstrut
+ % we need \nowhitespace in case of setups setting whitespace
+ % nb, not safe, text vs \vbox as next
+ \vskip-\struttotal
+ \nowhitespace % na vskip ! new 20/05/2004, fails with next content being box (\scale{..})
+ }%
+ \doinhibitblank % \blank[\v!disable]% plaatst signal
+\setupindenting[\framedtextparameter{#1}\c!indenting]%
+ \doconvertfont{\framedtextparameter{#1}\c!style}\empty
+ \def\dostopframedtext{\dodostopframedtext{#1}{#2}}}
+
+%D The \type {none} option is handy for nested usage, as
+%D in the presentation styles, where we don't want
+%D interference.
+
+\def\dodostopframedtext#1#2% % no \baselinecorrection, see faq docs
+ {\endgraf
+ \removelastskip
+ \doifvalue{\??kd#1\c!depthcorrection}\v!on % local and global
+ {\forgetall
+ \vskip-\struttotal
+ \verticalstrut
+ \egroup
+ \forgetall % brrr too often
+ \vskip-\lineheight
+ % will be an option, not default
+ % \setbaselinecorrections
+ % \donegbotbaselinecorrection
+ \verticalstrut}
+ \stopboxedcontent
+ \stopcolor
+ \ifconditional\framedtextlocationnone
+ \egroup
+ \box\framebox
+ \else\ifinsidefloat
+ \egroup
+ \box\framebox
+ \else
+ \egroup
+ \doplacement[\??kd#1][\c!depthcorrection=\v!off]{\box\framebox}%
+ \fi\fi
+ \egroup}
+
+%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
+%D slightly different and is not aligned.
+
+\def\doframedtext
+ {\bgroup\dodoubleempty\dodoframedtext}
+
+\def\dodoframedtext[#1][#2]% beware!
+ {\normalexpanded{\noexpand\switchtobodyfont[\getvalue{\??kd#1\c!bodyfont}]}%
+ \localframed[\??kd#1][\c!strut=\v!no,#2]%
+ \bgroup
+ \blank[\v!disable]%
+ \let\\=\endgraf
+ \getvalue{\??kd#1\c!inner}% % kleur naar outer level
+ \dostartattributes{\??kd#1}\c!style\c!color\empty
+ \bgroup
+ \aftergroup\docloseframedtext
+ \let\next=}
+
+\def\docloseframedtext
+ {\removelastskip
+ \dostopattributes
+ \egroup
+ \egroup}
+
+%D \macros
+%D {defineframed}
+%D
+%D One can also define simple framed texts, using:
+%D
+%D \showsetup{defineframed}
+
+\unexpanded\def\defineframed
+ {\dodoubleempty\dodefineframed}
+
+\def\dodefineframed[#1][#2]%
+ {\iffirstargument
+ \setuvalue{#1}{\dodoubleempty\doframed[#2]}%
+ \fi}
+
+\def\doframed[#1][#2]%
+ {\framed[#1,#2]}
+
+%D \macros
+%D {textrule, starttextrule, setuptextrules}
+%D
+%D Putting rules before and after a paragraph is very space
+%D sensitive, but the next command handles that quite well. It
+%D comes in two disguises:
+%D
+%D \startbuffer
+%D \textrule[top]{fragments}
+%D \input reich
+%D \textrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [width=90pt,distance=12pt,rulecolor=blue,
+%D bodyfont=small,style=\sc,color=red]
+%D
+%D \starttextrule{Ship Building Tools}
+%D \nl \setuptolerance[tolerant] \input materie
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [location=inmargin,
+%D bodyfont=small,style=slantedbold]
+%D
+%D \starttextrule{wonderful}
+%D \input tufte
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D The formal definition of these commands is:
+%D
+%D \showsetup{textrule}
+%D \showsetup{starttextrule}
+%D \showsetup{setuptextrules}
+%D
+%D The implementation looks a bit complicated due to the
+%D optional arguments.
+
+\unexpanded\def\setuptextrules
+ {\dodoubleargument\getparameters[\??tl]}
+
+\def\complextextrule[#1]% if needed we can make it installable
+ {\let\next\dobottomtextrule
+ \processaction
+ [#1]
+ [ \v!top=>\let\next\dotoptextrule,
+ \v!middle=>\let\next\domiddletextrule,
+ \v!bottom=>\let\next\dobottomtextrule]%
+ \dosinglegroupempty\next}
+
+\definecomplexorsimple\textrule
+
+\def\simpletextrule
+ {\dosinglegroupempty\dounknowntextrule}
+
+\def\docomplextextrule#1%
+ {\bgroup
+ \advance\hsize\dimexpr-\rightskip-\leftskip\relax
+ \setbox\scratchbox\hbox to \hsize
+ {\dimen4\dimexpr .5ex+.5\linewidth\relax
+ \dimen6\dimexpr-.5ex+.5\linewidth\relax
+ \doifsomething{#1}
+ {\doifelse\@@tllocation\v!inmargin
+ {\llap{\doattributes\??tl\c!style\c!color{#1}\hskip\leftmargindistance}}
+ {\color[\@@tlrulecolor]
+ {\vrule\!!height\dimen4\!!depth\dimen6\!!width\@@tlwidth}%
+ \hbox spread 2\dimexpr\@@tldistance\relax
+ {\hss\doattributes\??tl\c!style\c!color{\strut#1}\hss}}}%
+ \color[\@@tlrulecolor]
+ {\leaders\hrule\!!height\dimen4\!!depth\dimen6\hfill}}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \noindent\box\scratchbox
+%\nobreak\verticalstrut\kern-\struttotal
+% evt \witruimte
+ \egroup}
+
+\def\dotoptextrule#1%
+ {\page[\v!preference] % interferes
+ %\whitespace % no
+ \@@tlbefore
+ \docomplextextrule{#1}%
+% todo, option: \doifnothing{#1}{\ruledvskip-.5ex}
+ \nowhitespace
+ \@@tlinbetween
+ \endgraf}
+
+\def\dodobottomtextrule#1#2%
+ {\ifhmode
+ \endgraf
+ \fi
+ \dimen0\strutdp
+ \ifdim\prevdepth>\strutdp\else % was <\strutdp
+ \ifdim\prevdepth>\zeropoint
+ \advance\dimen0 -\prevdepth
+ \fi
+ \fi
+ \advance\dimen0 .5ex
+ \vskip\dimen0
+% ==
+% \vskip\dimexpr \strutdp + .5ex
+% \ifdim\prevdepth>\strutdp\else\ifdim\prevdepth>\zeropoint-\prevdepth\fi\fi\relax
+%
+ \@@tlinbetween
+ \doifelsenothing{#2}
+ {\bgroup
+ \advance\hsize\dimexpr-\rightskip-\leftskip\relax
+ \nointerlineskip
+ \moveleft-\leftskip\vbox
+ {\color[\@@tlrulecolor]
+ {\hrule\!!depth\linewidth\!!height\zeropoint\!!width\hsize}}%
+ \egroup}
+ {\docomplextextrule{#2}}%
+ \ifvmode\prevdepth\zeropoint\fi
+ #1%
+ \page[\v!preference]}
+
+\def\dobottomtextrule
+ {\dodobottomtextrule\@@tlafter}
+
+\def\domiddletextrule
+ {\dodobottomtextrule\@@tlinbetween}
+
+\def\dounknowntextrule
+ {\iffirstargument
+ \@EA\dotoptextrule
+ \else
+ \@EA\dobottomtextrule\@EA\empty
+ \fi}
+
+%D The grouped commands also supports bodyfont switching:
+
+\unexpanded\def\starttextrule#1%
+ {\bgroup
+ \def\dounknowntextrule{\domiddletextrule}
+ \dotoptextrule{#1}
+ \bgroup
+ \doifsomething\@@tlbodyfont{\switchtobodyfont[\@@tlbodyfont]}}
+
+\unexpanded\def\stoptextrule
+ {\par
+ \egroup
+ \dobottomtextrule\empty
+ \egroup}
+
+%D \macros
+%D {fillinrules, setupfillinrules}
+%D
+%D The next few commands do not really deserve a place in a
+%D core module, because they deal with specific typography.
+%D Nevertheless I decided to make them part of the core,
+%D because they permit us to make questionaires. Let's start
+%D with some examples.
+%D
+%D \fillinrules[n=2,width=fit]{first}
+%D \fillinrules[n=2,width=broad]{first}
+%D \fillinrules[n=2,width=3cm]{first}
+%D \fillinrules[n=2,width=3cm,distance=.5em,separator=:]{first}
+%D \fillinrules[n=2]{first}{last}
+%D \fillintext{first}{last} \input reich \par
+%D
+%D The main command is \type{\fillinrules}. This command takes
+%D one and an optional second argument and sets a paragraph with
+%D empty visualized lines.
+%D
+%D \showsetup{fillinrules}
+%D \showsetup{setupfillinrules}
+
+\unexpanded\def\setupfillinrules
+ {\dodoubleargument\getparameters[\??il]}
+
+\definecomplexorsimpleempty\fillinrules
+
+\def\complexfillinrules[#1]%
+ {\def\docomplexfillinrules##1##2%
+ {\dodocomplexfillinrules[#1]{##1}{##2}{\thinrules
+ [\c!n=\@@iln,\c!interlinespace=\@@ilinterlinespace,\c!before=,\c!after=]}}%
+ \dodoublegroupempty\docomplexfillinrules}
+
+\def\dodocomplexfillinrules[#1]#2#3#4%
+ {\endgraf
+ \@@ilbefore
+ \begingroup
+ \setupfillinrules[#1]%
+ \noindent
+ \doifsomething{#2}
+ {\doifelse\@@ilwidth\v!fit
+ {\let\@@ildistance\!!zeropoint
+ \hbox}
+ {\doifelse\@@ilwidth\v!broad
+ {\hbox}
+ {\hbox to \@@ilwidth}}%
+ \bgroup
+ \doattributes\??il\c!style\c!color{\strut#2\hfill\@@ilseparator}%
+ \hskip\@@ildistance
+ \egroup}%
+ %\hangindent=\wd0\relax % tzt hang=yes,n
+ %\parindent=\hangindent
+ %\box0\relax
+ \setupwhitespace[\v!big]%
+ \ignorespaces
+ #4%
+ \doifsomething{#3}
+ {\kern\@@ildistance
+ \doattributes\??il\c!style\c!color{#3\strut}}%
+ \endgroup
+ \endgraf
+ \@@ilafter}
+
+%D \macros
+%D {fillintext}
+%D
+%D To provide compatible layouts when texts and lines are
+%D mixed, one can typeset a paragraph by using the command
+%D \type{\fillintext}.
+%D
+%D \showsetup{fillintext}
+
+\definecomplexorsimpleempty\fillintext
+
+\def\complexfillintext[#1]% rather rough, using an \unhbox is suboptimal
+ {\def\docomplexfillintext##1##2%
+ {\dowithnextbox
+ {\dodocomplexfillinrules[#1]{##1}{\hfill##2}{\unhbox\nextbox\unskip}}%
+ \hbox\bgroup\let\par\egroup\ignorespaces}%
+ \dodoublegroupempty\docomplexfillintext}
+
+%D \macros
+%D {fillinline, setupfillinlines}
+%D
+%D Another member of the family takes care of putting a (often
+%D small) rule after a piece of text, like
+%D
+%D \startbuffer
+%D \fillinline \input reich \par
+%D \fillinline[margin=0cm] \input reich \par
+%D \stopbuffer
+%D
+%D \startvoorbeeld
+%D \getbuffer
+%D \stopvoorbeeld
+%D
+%D which was typeset by saying:
+%D
+%D \typebuffer
+%D
+%D The two commands that take care of this are:
+%D
+%D \showsetup{fillinline}
+%D \showsetup{setupfillinlines}
+
+\unexpanded\def\setupfillinlines
+ {\dodoubleargument\getparameters[\??iv]}
+
+\definecomplexorsimpleempty\fillinline
+
+\def\complexfillinline[#1]%
+ {%\endgraf % interferes with \definedescription cum suis
+ \@@ivbefore
+ \begingroup
+ \setupfillinlines[#1]%
+ \advance\rightskip \@@ivmargin
+ \parfillskip\zeropoint
+ \def\par % very dangerous
+ {\let\par\endgraf % -)
+ \ifhmode\unskip\hfill\fi
+ \scratchdimen\dimexpr\@@ivwidth-\@@ivdistance\relax
+ \ifdim\scratchdimen>\@@ivmargin\else\expandafter\rlap\fi
+ {\kern\@@ivdistance
+ \vrule
+ \!!width \scratchdimen
+ \!!height.5\linewidth
+ \!!depth .5\linewidth}%
+ \endgraf % !
+ \endgroup
+ \endgraf % !
+ \@@ilafter}}
+
+%D \stopdocumentation
+%D \bgroup
+%D
+%D \setupframedtexts
+%D [setuptext]
+%D [background=color,backgroundcolor=white]
+%D
+%D \startbuffer
+%D \setupbackground
+%D [backgroundoffset=4pt,
+%D background=screen,
+%D frame=on,
+%D framecolor=red,
+%D leftoffset=2pt]
+%D \stopbuffer
+%D
+%D \getbuffer
+%D
+%D \startbackground
+%D
+%D \macros
+%D {setupbackground,startbackground,background}
+%D
+%D The section deals with backgrounds in the running text. This
+%D means that texts is to be collected and split over pages. To
+%D show what can be done, we provide this part of the
+%D documentation with some gray background and a red frame.
+%D Both the background and frame can have all characteristics
+%D of \type{\framed}. This time we used the setting:
+%D
+%D \typebuffer
+%D
+%D The implementation is not that sophisticated, but suffices.
+%D The main problem with this kind of functionality is to get
+%D the spacing all right.
+
+%D Specifying the background is more or less the same as
+%D specifying a framed box.
+%D
+%D \showsetup{setupbackground}
+
+\presetlocalframed[\??ag]
+
+\def\dosetupbackground[#1]%
+ {\getparameters[\??ag][#1]%
+ \doifelse\@@agstate\v!start
+ {\let\startbackground\dostartbackground
+ \let\stopbackground \dostopbackground
+ \let\background \dobackground}
+ {\let\startbackground\relax
+ \let\stopbackground \relax
+ \let\background \relax}}
+
+\unexpanded\def\setupbackground
+ {\dosingleargument\dosetupbackground}
+
+%D Actually typesetting the background is implemented rather
+%D straightforward. We need to handle some spacing as well as
+%D the (often) a bit smaller horizontal size.
+%D
+%D \showsetup{startbackground}
+%D
+%D Although we could have used a scratch one, we first
+%D declare a boolean.
+
+% 0=no-split, 1=no-split+indent, 2=split, 3=split+indent
+
+\chardef\backgroundsplitmode\plusthree
+
+%D The \type{\vbox to \lineheight{}\vskip\zeropoint}
+%D construction gives the first real line a decent height by
+%D adding a dummy line.
+
+\def\dostartbackground
+ {\endgraf
+ \bgroup
+ \setbox0\vbox\bgroup
+ \vbox to \lineheight{}\vskip\zeropoint
+ \blank[\v!disable]
+ % \advance\hsize -\@@agleftoffset
+ % \advance\hsize -\@@agrightoffset
+ \leftskip \@@agleftoffset % new **
+ \rightskip\@@agrightoffset} % new **
+
+%D This dummy line is removed by \type{\setbox2=\vsplit0 to
+%D \lineheight}. That way \type{\topskip} takes care of the
+%D lineheight. I'll probably forget to apply this trick
+%D elsewhere.
+
+\def\dostopbackground % improved version (i hope)
+ {\endgraf
+ \removelastskip
+ \egroup
+ \dimen2\leftskip % new **
+ \forgetall
+ \ifinsidefloat
+ \chardef\backgroundsplitmode\zerocount
+ \fi
+ \ifcase\backgroundsplitmode
+ \localframed[\??ag][\c!offset=\v!overlay]{\box0}%
+ \or
+ \hskip\dimen2
+ \localframed[\??ag][\c!offset=\v!overlay]{\box0}%
+ \else
+ \splitmaxdepth\boxmaxdepth
+ \splittopskip\topskip
+ \setbox2\vsplit0 to \lineheight % get rid of fake line
+ \loop
+ \ifdim\pagetotal=\zeropoint % empty page
+ \scratchdimen\textheight
+ \chardef\backgroundsplit\plusone % split to max height
+ \else
+ \setbox\scratchbox\vbox{\@@agbefore}%
+ \scratchdimen\dimexpr\pagegoal-\ht\scratchbox-\pagetotal\relax
+ \chardef\backgroundsplit\plustwo % split to partial height
+ \fi
+ \advance\scratchdimen\dimexpr-\@@agtopoffset-\@@agbottomoffset\relax
+ \ifdim\scratchdimen>2\lineheight\relax % reasonable, will be configurable
+ \ifdim\ht0>\scratchdimen % larger than page
+ \setbox2\vsplit0 to \scratchdimen
+ \else
+ \setbox2\box0
+ \chardef\backgroundsplit\zerocount % no split
+ \fi
+ \setbox2\vbox \ifcase\backgroundsplit\or to \textheight \fi % max split
+ {\vskip\@@agtopoffset
+ \unvcopy2
+ \prevdepth\dp2
+ \obeydepth
+ \vskip\@@agbottomoffset
+ \vfill}
+ \@@agbefore
+ \ifcase\backgroundsplit\or\or % partial split
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal=1.2\pagegoal % be a bit more tolerant
+ \fi
+ \fi
+ \startlinecorrection
+ %\localframed[\??ag][\c!offset=\v!overlay]{\hskip\@@agleftoffset\box2\hskip\@@agrightoffset}%
+ \ifnum\backgroundsplitmode=\plusthree \hskip\dimen2 \fi %
+ \localframed[\??ag][\c!offset=\v!overlay]{\box2}% new **
+ \stoplinecorrection
+ \ifcase\backgroundsplit % no split
+ \@@agafter
+ \else % some split
+ \vfill\eject % geen \page !
+ \fi
+ \else
+ \page
+ \fi
+ \ifdim\ht0>\zeropoint \repeat
+ \fi
+ \egroup
+ \endgraf}
+
+%D As a bonus we also have a short command, that is of not
+%D much use, but kept there for historic reasons.
+%D
+%D \showsetup{background}
+
+\def\dobackground
+ {\bgroup
+ \dowithnextbox
+ {\localframed[\??ag][\c!offset=\v!overlay]{\flushnextbox}\egroup}
+ \vbox}
+
+%D \stopdocumentation
+%D \stopbackground
+%D \egroup
+
+%D New, for the moment private; let's see when GB finds out
+%D about this one and its 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
+
+% \unexpanded\def\defineframedcontent
+% {\dodoubleempty\dodefineframedcontent}
+%
+% \def\dodefineframedcontent[#1][#2]%
+% {\presetlocalframed[\??fc#1]%
+% \getparameters[\??fc#1]
+% [\c!leftoffset=\zeropoint,
+% \c!rightoffset=\getvalue{\??fc#1\c!leftoffset},
+% \c!topoffset=\zeropoint,
+% \c!bottomoffset=\getvalue{\??fc#1\c!topoffset},
+% \c!strut=\v!no,
+% \c!offset=\v!overlay,
+% \c!linecorrection=\v!no,
+% \c!left=,
+% \c!right=,
+% #2]}
+%
+% \unexpanded\def\setupframedcontent
+% {\dodoubleempty\dosetupframedcontent}
+%
+% \def\dosetupframedcontent[#1][#2]%
+% {\def\docommand##1{\getparameters[\??fc##1][#2]}%
+% \processcommacommand[#1]\docommand}
+%
+% \unexpanded\def\startframedcontent[#1]%
+% {\bgroup
+% \doifelse{#1}\v!off
+% {\let\stopframedcontent\egroup}
+% {\ifcsname\??fc#1\c!frame\endcsname
+% \dostartframedcontent{#1}%
+% \fi}}
+%
+% \def\dostartframedcontent#1%
+% {\unexpanded\def\stopframedcontent{\dostopframedcontent{#1}}%
+% \setbox\framebox\hbox\bgroup
+% \setlocalhsize
+% \hsize\localhsize
+% \advance\hsize\dimexpr-\getvalue{\??fc#1\c!leftoffset}-\getvalue{\??fc#1\c!rightoffset} \relax
+% \advance\vsize\dimexpr-\getvalue{\??fc#1\c!topoffset} -\getvalue{\??fc#1\c!bottomoffset}\relax
+% \hskip\getvalue{\??fc#1\c!leftoffset}%
+% \vbox\bgroup
+% \vskip\getvalue{\??fc#1\c!topoffset}%
+% \vbox\bgroup
+% \forgetall
+% \blank[\v!disable]}
+%
+% \def\dostopframedcontent#1%
+% {\removelastskip
+% \egroup
+% \vskip\getvalue{\??fc#1\c!bottomoffset}%
+% \egroup
+% \hskip\getvalue{\??fc#1\c!rightoffset}%
+% \egroup
+% \doifvalue{\??fc#1\c!width}\v!fit
+% {\letvalue{\??fc#1\c!width}\v!fixed}% no shapebox
+% \ifinsidefloat
+% \donefalse
+% \else
+% \doifelsevalue{\??fc#1\c!linecorrection}\v!yes\donetrue\donefalse
+% \fi
+% % plaats ?
+% \ifdone\startlinecorrection\fi
+% \getvalue{\??fc#1\c!left}% new
+% \localframed[\??fc#1]{\box\framebox}%
+% \getvalue{\??fc#1\c!right}% new
+% \ifdone\stoplinecorrection\fi
+% \egroup}
+
+\def\framedcontentparameter #1{\csname\doframedcontentparameter{\??fc\@@framedcontent}#1\endcsname}
+\def\doframedcontentparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedcontentparentparameter\csname#1\s!parent\endcsname#2\fi}
+\def\doframedcontentparentparameter#1#2{\ifx#1\relax\s!empty\else\doframedcontentparameter#1#2\fi}
+
+\presetlocalframed[\??fc]
+
+\getparameters
+ [\??fc]
+ [\c!leftoffset=\zeropoint,
+ \c!rightoffset=\framedcontentparameter\c!leftoffset,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\framedcontentparameter\c!topoffset,
+ \c!strut=\v!no,
+ %\c!linecorrection=\v!no,
+ %\c!left=,
+ %\c!right=,
+ %\c!width=\v!fit,
+ \c!offset=\v!overlay]
+
+\def\letframedcontentparameter#1%
+ {\letvalue{\??fc\@@framedcontent#1}}
+
+\unexpanded\def\defineframedcontent
+ {\dodoubleempty\dodefineframedcontent}
+
+\def\dodefineframedcontent[#1][#2]%
+ {\getparameters[\??fc#1][\s!parent=\??fc,#2]}
+
+\unexpanded\def\setupframedcontent
+ {\dodoubleempty\dosetupframedcontent}
+
+\def\dosetupframedcontent[#1][#2]%
+ {\def\docommand##1{\getparameters[\??fc##1][#2]}%
+ \processcommacommand[#1]\docommand}
+
+\unexpanded\def\startframedcontent
+ {\dosingleempty\dostartframedcontent}
+
+\def\dostartframedcontent[#1]%
+ {\bgroup
+ \edef\@@framedcontent{#1}%
+ \let\stopframedcontent\egroup
+ \doifnot{#1}\v!off{\dodostartframedcontent{#1}}}
+
+\def\dodostartframedcontent#1%
+ {\unexpanded\def\stopframedcontent{\dostopframedcontent{#1}}%
+ \setbox\framebox\hbox\bgroup
+ \setlocalhsize
+ \hsize\localhsize
+ \advance\hsize\dimexpr-\framedcontentparameter\c!leftoffset-\framedcontentparameter\c!rightoffset \relax
+ \advance\vsize\dimexpr-\framedcontentparameter\c!topoffset -\framedcontentparameter\c!bottomoffset\relax
+ \hskip\framedcontentparameter\c!leftoffset
+ \vbox\bgroup
+ \vskip\framedcontentparameter\c!topoffset
+ \vbox\bgroup
+ \forgetall
+ \blank[\v!disable]}
+
+\def\dostopframedcontent#1%
+ {\removelastskip
+ \egroup
+ \vskip\framedcontentparameter\c!bottomoffset
+ \egroup
+ \hskip\framedcontentparameter\c!rightoffset
+ \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
+ \localframed[\??fc#1]{\box\framebox}%
+ \framedcontentparameter\c!right % new
+ \ifdone\stoplinecorrection\fi
+ \egroup}
+
+%D \macros
+%D {backgroundline}
+%D
+%D For the moment an undocumented feature, but a cancidate
+%D for going public.
+
+\def\backgroundline[#1]%
+ %{\doifsomething{#1}{\dobackgroundline{#1}}\hbox}
+ {\doifcolorelse{#1}{\dobackgroundline{#1}\hbox}\hbox}
+
+% \def\backgroundline[#1]%
+% {\doifcolor{#1}{\dobackgroundline{#1}}\hbox}
+
+\def\dobackgroundline#1%
+ {\dowithnextbox
+ {\hbox
+ {\startcolor[#1]%
+ \vrule
+ \!!width \nextboxwd
+ \!!height\nextboxht
+ \!!depth \nextboxdp
+ \stopcolor
+ \hskip-\nextboxwd
+ \flushnextbox}}}
+
+%D \macros
+%D {encircled}
+%D
+%D Some not so robust left||overs (borrowed from Knuth,
+%D \TEX Book\ page 356):
+
+\def\encircled#1%
+ {{\ooalign{\hfil\raise0.07ex\hbox{{\tx#1}}\hfil\crcr\mathhexbox20D}}}
+
+\let\omcirkeld\encircled
+
+\setuplinewidth
+ [\v!medium]
+
+\setupframed
+ [\c!width=\v!fit,
+ \c!height=\v!broad,
+ \c!lines=,
+ \c!offset=0.25ex, % \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!backgroundscreen=\@@rsscreen,
+ \c!backgroundcolor=,
+ \c!backgroundoffset=\zeropoint,
+ \c!framecolor=,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner,
+ \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!align=,
+ \c!bottom=\vss,
+ \c!top=,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!yes,
+ \c!location=\v!normal,
+ \c!orientation=,
+ \c!autowidth=\v!yes,
+ \c!setups=]
+
+\setupscreens
+ [%\c!factor=1.0, % obsolete
+ %\c!method=\v!external, % obsolete
+ \c!screen=0.95]
+
+\setupblackrules
+ [\c!n=3,
+ \c!width=1em,
+ \c!height=1ex,
+ \c!depth=\!!zeropoint,
+ \c!alternative=\c!a,
+ \c!distance=.25ex,
+ \c!color=]
+
+\setupmarginrules
+ [\c!level=0,
+ \c!rulethickness=\@@kadefaultwidth\linewidth]
+
+\setupthinrules
+ [\c!interlinespace=\v!small,
+ \c!n=3,
+ \c!before=,
+ \c!inbetween={\blank[\v!white]},
+ \c!after=,
+ \c!color=,
+ \c!height=.5\linewidth,
+ \c!depth=.5\linewidth,
+ \c!frame=\v!on, % compatible with textbackgrounds
+ \c!alternative=\v!b,
+ \c!backgroundcolor=,
+ \c!background=,
+ \c!rulethickness=]
+
+\setuptextrules
+ [\c!location=\v!left,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=,
+ \c!width=2em,
+ \c!style=\v!bold,
+ \c!color=,
+ \c!rulecolor=,
+ \c!bodyfont=,
+ \c!distance=.5em]
+
+\setupfillinrules
+ [\c!width=\v!broad,
+ \c!distance=1em,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!n=1,
+ \c!interlinespace=\v!small,
+ \c!separator=,
+ \c!style=\v!normal,
+ \c!color=]
+
+\setupfillinlines
+ [\c!width=3cm,
+ \c!margin=\@@ivwidth,
+ \c!distance=1em,
+ \c!before=\blank,
+ \c!after=\blank]
+
+\setupbackground
+ [\c!leftoffset=.5\bodyfontsize,
+ \c!rightoffset=\@@agleftoffset,
+ \c!topoffset=\!!zeropoint,
+ \c!bottomoffset=\@@agtopoffset,
+ \c!state=\v!start,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ \c!frame=\v!off,
+ \c!color=,
+ \c!depth=\!!zeropoint,
+ \c!background=\v!screen,
+ \c!backgroundcolor=\@@agcolor,
+ \c!screen=\@@rsscreen,
+ \c!before=,
+ \c!after=]
+
+% Experimental extension:
+
+\def\c!loffset{loffset}
+\def\c!roffset{roffset}
+\def\c!toffset{toffset}
+\def\c!boffset{boffset}
+
+\getparameters
+ [\??oi]
+ [\c!loffset=\zeropoint,
+ \c!roffset=\zeropoint,
+ \c!toffset=\zeropoint,
+ \c!boffset=\zeropoint]
+
+\newdimen\!!framedloffset
+\newdimen\!!framedroffset
+\newdimen\!!framedtoffset
+\newdimen\!!framedboffset
+
+\def\setextraframedoffsets
+ {\boxhasextraoffsetfalse
+ \!!framedloffset\framedparameter\c!loffset
+ \!!framedroffset\framedparameter\c!roffset
+ \!!framedtoffset\framedparameter\c!toffset
+ \!!framedboffset\framedparameter\c!boffset
+ \relax
+ \ifzeropt\!!framedloffset\else \advance\!!framedwidth -\!!framedloffset \boxhasextraoffsettrue \fi
+ \ifzeropt\!!framedroffset\else \advance\!!framedwidth -\!!framedroffset \boxhasextraoffsettrue \fi
+ \ifzeropt\!!framedtoffset\else \advance\!!framedheight-\!!framedtoffset \boxhasextraoffsettrue \fi
+ \ifzeropt\!!framedboffset\else \advance\!!framedheight-\!!framedboffset \boxhasextraoffsettrue \fi}
+
+\def\applyextraframedoffsets
+ {\setbox\framebox\vbox\bgroup
+ \vskip\!!framedtoffset
+ \hbox\bgroup
+ \hskip\!!framedloffset
+ \box\framebox
+ \hskip\!!framedroffset
+ \egroup
+ \vskip\!!framedboffset
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/page-app.mkii b/tex/context/base/page-app.mkii
new file mode 100644
index 000000000..e5c149aa0
--- /dev/null
+++ b/tex/context/base/page-app.mkii
@@ -0,0 +1,225 @@
+%D \module
+%D [ file=page-app, % from meta-fig
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Independent page building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Applications}
+
+%D The fitting page code is moved from \type {meta-fig} to
+%D here.
+
+\unprotect
+
+\definepapersize
+ [\??fp\s!dummy]
+ [\c!width=\fittingwd,
+ \c!height=\fittinght]
+
+\definelayout
+ [\??fp\s!dummy]
+ [\c!width=\fittingwd,\c!height=\fittinght,\c!location=\v!middle,
+ \c!topspace=\!!zeropoint,\c!backspace=\!!zeropoint,
+ \c!cutspace=\!!zeropoint,\c!bottomspace=\!!zeropoint,
+ \c!textdistance=\!!zeropoint,\c!lines=0,\c!grid=\v!no,
+ \c!top=\!!zeropoint,\c!bottom=\!!zeropoint,
+ \c!margin=\!!zeropoint,\c!edge=\!!zeropoint,
+ \c!leftmargin=\!!zeropoint,\c!leftedge=\!!zeropoint,
+ \c!rightmargin=\!!zeropoint,\c!rightedge=\!!zeropoint,
+ \c!header=\!!zeropoint,\c!footer=\!!zeropoint]
+
+
+\def\dostartfittingpage[#1][#2]%
+ {\page % this is kind of tricky! there can be preceding page refs
+ \autostarttext
+ \bgroup % resulting in a zero height page; test fig-make !
+ \def\currentfittingpage{#1}%
+ \dontcomplain
+ % runs under current page regime, i.e. page variables passed to mp
+ \getparameters[\currentfittingpage][\c!paper=,#2]% auto or size or nothing
+ \setbox\scratchbox\hbox
+ \bgroup
+ % needed later \getparameters[\currentfittingpage][\c!paper=,#2]% auto or size or nothing
+ \doifvalue{\currentfittingpage\c!margin}\v!page % undocumented
+ {\offsetbox
+ [\c!leftoffset=\backspace,
+ \c!rightoffset=\cutspace,
+ \c!topoffset=\topspace,
+ \c!bottomoffset=\bottomspace]\hbox}%
+ \bgroup
+ \scale[\c!scale=\getvalue{\currentfittingpage\c!scale}]%
+ \bgroup\localframed[\currentfittingpage]%
+ \bgroup}
+
+\def\dostopfittingpage
+ {\egroup % localframed
+ \egroup % scale
+ \egroup % offsetbox
+ \egroup % scratchbox
+ \edef\fittingwd{\the\wd\scratchbox}%
+ \edef\fittinght{\the\ht\scratchbox}%
+ \startlocallayout
+ \ifdim\fittinght<\lineheight
+ % write status : too small
+ \setbox\scratchbox\vbox to \lineheight{\vss\box\scratchbox\vss}%
+ \edef\fittinght{\the\lineheight}%
+ \fi
+ \let\checkcurrentlayout\relax % else interference with odd/even layout
+ \processaction
+ [\getvalue{\currentfittingpage\c!paper}]
+ [ \v!auto=>\let\fittingpapersize\printpapersize,
+ \s!unknown=>\let\fittingpapersize\commalistelement,
+ \s!default=>\def\fittingpapersize{\??fp\s!dummy}]%
+ \expanded{\setuppapersize[\??fp\s!dummy][\fittingpapersize]}%
+ \definelayout
+ [\v!page]%
+ [\c!location=\v!middle,
+ \c!width=\fittingwd,
+ \c!height=\fittinght]%
+ \setuplayout
+ [\v!page]%
+ \startmakeup[\v!standard][\c!textstate=\v!empty,\c!doublesided=\v!no,\c!page=]%
+ \centerbox{\box\scratchbox}%
+ \stopmakeup
+ \stoplocallayout
+ \egroup
+ \autostoptext}
+
+%D \TEX\ pages (for \METAPOST\ pages, see \type {meta-fig}):
+
+\presetlocalframed[\??tg]
+
+\def\setupTEXpage
+ {\dodoubleargument\getparameters[\??tg]}
+
+\def\startTEXpage
+ {\dosingleempty\dostartTEXpage}
+
+\def\dostartTEXpage[#1]%
+ {\dostartfittingpage[\??tg][#1]\gobblespacetokens}
+
+\def\stopTEXpage
+ {\removelastspace
+ \dostopfittingpage}
+
+\setupTEXpage
+ [\c!scale=1000,
+ \c!strut=\v!no,
+ \c!align=\v!normal, % needed, else problems !
+ \c!offset=\v!overlay,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!frame=\v!off]
+
+%D For Mojca:
+%D
+%D \starttyping
+%D \startTEXstream \chapter{Bla} Hello world!\crlf Hello world! \stopTEXstream
+%D \startTEXpage \chapter{Bla} Hello world!\crlf Hello world! \stopTEXpage
+%D \stoptyping
+%D
+%D maybe I should support stream=yes in framed.
+
+\def\startTEXstream
+ {\dosingleempty\dostartTEXstream}
+
+\def\dostartTEXstream[#1]%
+ {\page
+ \defineoutputstream[tex]%
+ \enableoutputstream[tex]%
+ \def\stopTEXstream
+ {\disableoutputstream
+ \startTEXpage
+ \outputstreamunvbox[tex]%
+ \stopTEXpage}}
+
+%D Application pages (for an example, see \type {m-pstric}):
+
+\def\@@texapp{texapp}
+\def\@@texdim{texdim}
+
+\def\saveTEXapplication#1#2%
+ {\immediate\openout\scratchwrite=\bufferprefix\@@texdim.tmp
+ \immediate\write\scratchwrite{\dimen#1=\the\ht\scratchbox}%
+ \immediate\write\scratchwrite{\dimen#2=\the\wd\scratchbox}%
+ \immediate\closeout\scratchwrite}
+
+\def\restoreTEXapplication
+ {\readlocfile{\bufferprefix\@@texdim.tmp}\donothing\donothing}
+
+\def\startTEXapplication
+ {\dosingleempty\dostartTEXapplication}
+
+\long\def\dostartTEXapplication[#1]#2#3\stopTEXapplication
+ {\bgroup
+ \bgroup
+ \let\f!temporaryextension\c!tex
+ \setbuffer[\@@texapp]%
+ \starttext
+ #2% preamble
+ \startTEXpage[#1]%
+ \topskip\zeropoint
+ \setbox\scratchbox\hbox{#3}%
+ \saveTEXapplication02% dimensions
+ \box\scratchbox
+ \stopTEXpage
+ \stoptext
+ \endbuffer
+ \egroup
+ \doifelse\jobsuffix{dvi}\donetrue\donefalse
+ \executesystemcommand{texexec \bufferprefix\@@texapp.tex --once --batch}%
+ \ifdone % eps
+ \executesystemcommand{dvips -E* -o \@@texapp.eps \@@texapp}%
+ \else % pdf
+ \executesystemcommand{dvips \bufferprefix\@@texapp}%
+ \executesystemcommand{ps2pdf \bufferprefix\@@texapp.ps \bufferprefix\@@texapp.pdf}%
+% \executesystemcommand{texmfstart pstopdf \bufferprefix\@@texapp.ps \bufferprefix\@@texapp.pdf}%
+ \fi
+ \restoreTEXapplication % dimensions
+ \doifelse\jobsuffix{dvi}\donetrue\donefalse
+ \setbox\scratchbox\hbox
+ {\expanded{\externalfigure
+ [\bufferprefix\@@texapp.\ifdone eps\else pdf\fi]
+ [\c!object=\v!no]}}%
+ \setbox\scratchbox\hbox
+ {\lower\ht\scratchbox\hbox{\raise\dimen2\box\scratchbox}}%
+ \wd\scratchbox\dimen0
+ \ht\scratchbox\dimen2
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {startpagefigure}
+%D
+%D \starttyping
+%D \starttext \pagefigure[two.1] \stoptext
+%D \stoptyping
+
+\def\startpagefigure
+ {\dodoubleempty\dostartpagefigure}
+
+\def\dostartpagefigure[#1][#2]%
+ {\bgroup
+ \getparameters[\??ex][\c!offset=\v!overlay,#2]%
+ \startTEXpage[\c!offset=\@@exoffset]%
+ \externalfigure[#1][#2]\ignorespaces} % so we can put some text below the graphic
+
+\def\stoppagefigure
+ {\stopTEXpage
+ \egroup}
+
+\def\pagefigure
+ {\dodoubleempty\dopagefigure}
+
+\def\dopagefigure[#1][#2]%
+ {\dostartpagefigure[#1][#2]\stoppagefigure}
+
+\protect \endinput
diff --git a/tex/context/base/page-app.mkiv b/tex/context/base/page-app.mkiv
new file mode 100644
index 000000000..7dd71cf2a
--- /dev/null
+++ b/tex/context/base/page-app.mkiv
@@ -0,0 +1,225 @@
+%D \module
+%D [ file=page-app, % from meta-fig
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Independent page building,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Applications}
+
+%D The fitting page code is moved from \type {meta-fig} to
+%D here.
+
+\unprotect
+
+\definepapersize
+ [\??fp\s!dummy]
+ [\c!width=\fittingwd,
+ \c!height=\fittinght]
+
+\definelayout
+ [\??fp\s!dummy]
+ [\c!width=\fittingwd,\c!height=\fittinght,\c!location=\v!middle,
+ \c!topspace=\!!zeropoint,\c!backspace=\!!zeropoint,
+ \c!cutspace=\!!zeropoint,\c!bottomspace=\!!zeropoint,
+ \c!textdistance=\!!zeropoint,\c!lines=0,\c!grid=\v!no,
+ \c!top=\!!zeropoint,\c!bottom=\!!zeropoint,
+ \c!margin=\!!zeropoint,\c!edge=\!!zeropoint,
+ \c!leftmargin=\!!zeropoint,\c!leftedge=\!!zeropoint,
+ \c!rightmargin=\!!zeropoint,\c!rightedge=\!!zeropoint,
+ \c!header=\!!zeropoint,\c!footer=\!!zeropoint]
+
+
+\def\dostartfittingpage[#1][#2]%
+ {\page % this is kind of tricky! there can be preceding page refs
+ \autostarttext
+ \bgroup % resulting in a zero height page; test fig-make !
+ \def\currentfittingpage{#1}%
+ \dontcomplain
+ % runs under current page regime, i.e. page variables passed to mp
+ \getparameters[\currentfittingpage][\c!paper=,#2]% auto or size or nothing
+ \setbox\scratchbox\hbox
+ \bgroup
+ % needed later \getparameters[\currentfittingpage][\c!paper=,#2]% auto or size or nothing
+ \doifvalue{\currentfittingpage\c!margin}\v!page % undocumented
+ {\offsetbox
+ [\c!leftoffset=\backspace,
+ \c!rightoffset=\cutspace,
+ \c!topoffset=\topspace,
+ \c!bottomoffset=\bottomspace]\hbox}%
+ \bgroup
+ \scale[\c!scale=\getvalue{\currentfittingpage\c!scale}]%
+ \bgroup\localframed[\currentfittingpage]%
+ \bgroup}
+
+\def\dostopfittingpage
+ {\egroup % localframed
+ \egroup % scale
+ \egroup % offsetbox
+ \egroup % scratchbox
+ \edef\fittingwd{\the\wd\scratchbox}%
+ \edef\fittinght{\the\ht\scratchbox}%
+ \startlocallayout
+ \ifdim\fittinght<\lineheight
+ % write status : too small
+ \setbox\scratchbox\vbox to \lineheight{\vss\box\scratchbox\vss}%
+ \edef\fittinght{\the\lineheight}%
+ \fi
+ \let\checkcurrentlayout\relax % else interference with odd/even layout
+ \processaction
+ [\getvalue{\currentfittingpage\c!paper}]
+ [ \v!auto=>\let\fittingpapersize\printpapersize,
+ \s!unknown=>\let\fittingpapersize\commalistelement,
+ \s!default=>\def\fittingpapersize{\??fp\s!dummy}]%
+ \expanded{\setuppapersize[\??fp\s!dummy][\fittingpapersize]}%
+ \definelayout
+ [\v!page]%
+ [\c!location=\v!middle,
+ \c!width=\fittingwd,
+ \c!height=\fittinght]%
+ \setuplayout
+ [\v!page]%
+ \startmakeup[\v!standard][\c!textstate=\v!empty,\c!doublesided=\v!no,\c!page=]%
+ \centerbox{\box\scratchbox}%
+ \stopmakeup
+ \stoplocallayout
+ \egroup
+ \autostoptext}
+
+%D \TEX\ pages (for \METAPOST\ pages, see \type {meta-fig}):
+
+\presetlocalframed[\??tg]
+
+\unexpanded\def\setupTEXpage
+ {\dodoubleargument\getparameters[\??tg]}
+
+\unexpanded\def\startTEXpage
+ {\dosingleempty\dostartTEXpage}
+
+\def\dostartTEXpage[#1]%
+ {\dostartfittingpage[\??tg][#1]\gobblespacetokens}
+
+\unexpanded\def\stopTEXpage
+ {\removelastspace
+ \dostopfittingpage}
+
+\setupTEXpage
+ [\c!scale=1000,
+ \c!strut=\v!no,
+ \c!align=\v!normal, % needed, else problems !
+ \c!offset=\v!overlay,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!frame=\v!off]
+
+%D For Mojca:
+%D
+%D \starttyping
+%D \startTEXstream \chapter{Bla} Hello world!\crlf Hello world! \stopTEXstream
+%D \startTEXpage \chapter{Bla} Hello world!\crlf Hello world! \stopTEXpage
+%D \stoptyping
+%D
+%D maybe I should support stream=yes in framed.
+
+\unexpanded\def\startTEXstream
+ {\dosingleempty\dostartTEXstream}
+
+\def\dostartTEXstream[#1]%
+ {\page
+ \defineoutputstream[tex]%
+ \enableoutputstream[tex]%
+ \unexpanded\def\stopTEXstream
+ {\disableoutputstream
+ \startTEXpage
+ \outputstreamunvbox[tex]%
+ \stopTEXpage}}
+
+%D Application pages (for an example, see \type {m-pstric}):
+
+\def\@@texapp{texapp}
+\def\@@texdim{texdim}
+
+\def\saveTEXapplication#1#2%
+ {\immediate\openout\scratchwrite=\bufferprefix\@@texdim.tmp
+ \immediate\write\scratchwrite{\dimen#1=\the\ht\scratchbox}%
+ \immediate\write\scratchwrite{\dimen#2=\the\wd\scratchbox}%
+ \immediate\closeout\scratchwrite}
+
+\def\restoreTEXapplication
+ {\readlocfile{\bufferprefix\@@texdim.tmp}\donothing\donothing}
+
+\def\startTEXapplication
+ {\dosingleempty\dostartTEXapplication}
+
+\long\def\dostartTEXapplication[#1]#2#3\stopTEXapplication
+ {\bgroup
+ \bgroup
+ \let\f!temporaryextension\c!tex
+ \setbuffer[\@@texapp]%
+ \starttext
+ #2% preamble
+ \startTEXpage[#1]%
+ \topskip\zeropoint
+ \setbox\scratchbox\hbox{#3}%
+ \saveTEXapplication02% dimensions
+ \box\scratchbox
+ \stopTEXpage
+ \stoptext
+ \endbuffer
+ \egroup
+ \doifelse\jobsuffix{dvi}\donetrue\donefalse
+ \executesystemcommand{texexec \bufferprefix\@@texapp.tex --once --batch}%
+ \ifdone % eps
+ \executesystemcommand{dvips -E* -o \@@texapp.eps \@@texapp}%
+ \else % pdf
+ \executesystemcommand{dvips \bufferprefix\@@texapp}%
+ \executesystemcommand{ps2pdf \bufferprefix\@@texapp.ps \bufferprefix\@@texapp.pdf}%
+% \executesystemcommand{texmfstart pstopdf \bufferprefix\@@texapp.ps \bufferprefix\@@texapp.pdf}%
+ \fi
+ \restoreTEXapplication % dimensions
+ \doifelse\jobsuffix{dvi}\donetrue\donefalse
+ \setbox\scratchbox\hbox
+ {\expanded{\externalfigure
+ [\bufferprefix\@@texapp.\ifdone eps\else pdf\fi]
+ [\c!object=\v!no]}}%
+ \setbox\scratchbox\hbox
+ {\lower\ht\scratchbox\hbox{\raise\dimen2\box\scratchbox}}%
+ \wd\scratchbox\dimen0
+ \ht\scratchbox\dimen2
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \egroup}
+
+%D \macros
+%D {startpagefigure}
+%D
+%D \starttyping
+%D \starttext \pagefigure[two.1] \stoptext
+%D \stoptyping
+
+\unexpanded\def\startpagefigure
+ {\dodoubleempty\dostartpagefigure}
+
+\def\dostartpagefigure[#1][#2]%
+ {\bgroup
+ \getparameters[\??ex][\c!offset=\v!overlay,#2]%
+ \startTEXpage[\c!offset=\@@exoffset]%
+ \externalfigure[#1][#2]\ignorespaces} % so we can put some text below the graphic
+
+\unexpanded\def\stoppagefigure
+ {\stopTEXpage
+ \egroup}
+
+\def\pagefigure
+ {\dodoubleempty\dopagefigure}
+
+\def\dopagefigure[#1][#2]%
+ {\dostartpagefigure[#1][#2]\stoppagefigure}
+
+\protect \endinput
diff --git a/tex/context/base/page-bck.mkii b/tex/context/base/page-bck.mkii
new file mode 100644
index 000000000..0b4ad779a
--- /dev/null
+++ b/tex/context/base/page-bck.mkii
@@ -0,0 +1,593 @@
+%D \module
+%D [ file=page-bck, % copied from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Backgrounds}
+
+% \chardef\kindofpagetextareas=1 will isolate graphics from backgrounds
+
+\unprotect
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+%D \macros
+%D {recalculatebackgrounds}
+%D
+%D We use a couple of switches so that we can minimize the
+%D amount of background calculations. The main switch is set
+%D by the recalculate directive.
+%D
+%D \starttyping
+%D \recalculatebackgrounds
+%D \stoptyping
+%D
+%D Other modules may not directly set the switches
+%D themselves.
+
+\newif\ifnewbackground
+\newif\ifsomebackground
+
+%D For special purposes, users can question the \type
+%D {*background} mode. This mode is only available when
+%D typesetting the pagebody.
+%D
+%D \starttyping
+%D \startmode[*background] ...
+%D \stoptyping
+
+\appendtoks
+ \ifsomebackground \ifnewbackground \setsystemmode\v!background \fi \fi
+\to \everybeforepagebody
+
+%D \macros
+%D {addmainbackground, addtextbackground,
+%D addpagebackground, addprintbackground}
+%D
+%D Apart from the previously mentioned directive, the
+%D interface between this module and the other modules
+%D is made up by four macros that add background to parts of
+%D the layout.
+%D
+%D \starttyping
+%D \addmainbackground
+%D \addtextbackground
+%D \addpagebackground
+%D \addprintbackground
+%D \stoptyping
+
+%D To minimize calculations, we keep track of the state of the
+%D background of each area. A previous implementation did
+%D check each call to the background calculation macro, but
+%D using an intermediate usage flag instead of testing each
+%D time saves about 3\% on a run with a couple of backgrounds.
+%D (On the 824 pages maps bibliography runtime went down from
+%D 309 to 299 seconds.)
+
+\def\checkbackground#1%
+ {\edef\!!stringe{\??ma#1}%
+ \doifelsevaluenothing{\!!stringe\c!background }
+ {\doifelsevaluenothing{\!!stringe\c!foregroundcolor}
+ {\doifelsevalue{\!!stringe\c!frame }\v!on\!!doneatrue
+ {\doifelsevalue{\!!stringe\c!leftframe }\v!on\!!doneatrue
+ {\doifelsevalue{\!!stringe\c!rightframe}\v!on\!!doneatrue
+ {\doifelsevalue{\!!stringe\c!topframe }\v!on\!!doneatrue
+ {\doifelsevalue{\!!stringe\c!bottomframe }\v!on\!!doneatrue
+ \!!doneafalse}}}}}
+ \!!doneatrue}
+ \!!doneatrue
+ \if!!donea
+ \setusage \!!stringe
+ \else
+ \resetusage\!!stringe
+ \fi}
+
+\def\ifsomebackgroundfound#1%
+ {\ifusage{\??ma#1}}
+
+% \def\doifsomebackgroundelse#1#2#3%
+% {\ifusage{\??ma#1}#2\else#3\fi}
+
+\def\doifsomebackgroundelse#1%
+ {\ifusage{\??ma#1}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+%D The background mechanism falls back on the \type {\framed}
+%D macro. This means that all normal frame and overlay
+%D features can be used.
+
+\def\addsomebackground#1#2#3#4% area box width height / zero test added
+ {\ifsomebackgroundfound#1\ifdim#3>\zeropoint\ifdim#4>\zeropoint
+ \doifvaluesomething{\??ma#1\c!setups}{\setups[\getvalue{\??ma#1\c!setups}]}% should not produce funny spaces !
+ \setbox#2\vbox\fastlocalframed
+ [\??ma#1]
+ [\c!component=#1,\c!strut=\v!no,\c!offset=\v!overlay,\c!setups=,%
+ \c!width=#3,\c!height=#4]
+ {\dp#2\zeropoint\box#2}%
+ \fi\fi\fi}
+
+%D There are quite some backgrounds. At the bottom layer,
+%D there is the {\em paper} background. This one is only
+%D used for special purposes, like annotations to documents.
+
+\def\addprintbackground#1%
+ {\addsomebackground
+ \v!paper#1\printpaperwidth\printpaperheight}
+
+%D The page backgrounds can be put behind the {\em left
+%D page}, the {\em right page} or {\em each page}. As with
+%D the paper background, these are calculated on each page.
+
+\def\addpagebackground#1%
+ {\doifbothsidesoverruled
+ {\addsomebackground\v!rightpage#1\paperwidth\paperheight}
+ {\addsomebackground\v!rightpage#1\paperwidth\paperheight}
+ {\addsomebackground\v!leftpage #1\paperwidth\paperheight}%
+ \addsomebackground\v!page #1\paperwidth\paperheight}
+
+%D Then there are the 25 areas that make up the layout: {\em
+%D top, header, text, footer, bottom} times {\em left edge,
+%D left margin, text, right margin, right edge}. These are
+%D only recalculated when they change or when the \type
+%D {status} is set to \type {repeat}.
+
+\newbox\leftbackground
+\newbox\rightbackground
+
+\def\addmainbackground#1% todo: dimension spec
+ {\ifsomebackground
+ \ifnewbackground \setbackgroundboxes \fi
+ \setbox#1\vbox
+ {\offinterlineskip
+ \doifmarginswapelse
+ {\copy\leftbackground}{\copy\rightbackground}%
+ \box#1}%
+ \fi}
+
+%D Finaly there is an aditional {\em text} background, again
+%D useful for special purposes only. This one is calculated
+%D each time. The hidden backgrounds are not meant for users!
+
+\newconditional\hiddenbackgroundenabled
+
+\def\addtextbackground#1%
+ {\ifconditional\hiddenbackgroundenabled
+ \addsomebackground\v!hidden#1\makeupwidth\textheight % mine !
+ \fi
+ \addsomebackground\v!text#1\makeupwidth\textheight}
+
+%D The next couple of macros implement the area backgrounds.
+%D As said, these are cached in dedicated boxes. The offsets
+%D and depth of the page are used for alignment purposes.
+
+\newdimen\pageoffset % bleed
+\newdimen\pagedepth
+
+\let\pagebackgroundhoffset\!!zeropoint
+\let\pagebackgroundvoffset\!!zeropoint
+\let\pagebackgrounddepth \!!zeropoint
+
+% \def\setbackgroundboxes
+% {\showmessage\m!layouts8\empty
+% \setbackgroundbox\leftbackground\relax
+% \ifdoublesided
+% \setbackgroundbox\rightbackground\doswapmargins
+% \fi
+% \doifnot\@@mastatus\v!herhaal{\global\newbackgroundfalse}}
+
+%D We need a bit more clever mechanism in order to handle
+%D layers well. This means that we cannot calculate both
+%D background at the same time since something may have
+%D changed halfway a page.
+
+\chardef\newrightbackground\zerocount
+\chardef\newleftbackground \zerocount
+
+\def\recalculatebackgrounds
+ {\global\newbackgroundtrue}
+
+\def\setbackgroundboxes
+ {\ifnewbackground
+ \global\chardef\newrightbackground\plusone
+ \global\chardef\newleftbackground\plusone
+ \global\setbox\leftbackground\emptybox
+ \global\setbox\rightbackground\emptybox
+ \fi
+ \doifbothsides
+ {\ifcase\newleftbackground \else
+ % \showmessage\m!layouts8\empty
+ \setbackgroundbox\leftbackground\relax
+ \global\chardef\newleftbackground\zerocount
+ \global\chardef\newrightbackground\zerocount
+ \fi}
+ {\ifcase\newleftbackground \else
+ % \showmessage\m!layouts8\empty
+ \setbackgroundbox\leftbackground\relax
+ \global\chardef\newleftbackground\zerocount
+ \fi}
+ {\ifcase\newrightbackground \else
+ % \showmessage\m!layouts8\empty
+ \setbackgroundbox\rightbackground\doswapmargins
+ \global\chardef\newrightbackground\zerocount
+ \fi}%
+ \ifx\@@mastate\v!repeat\else\global\newbackgroundfalse\fi}
+
+\def\addmainbackground#1% todo: dimension spec
+ {\ifsomebackground
+ \setbackgroundboxes
+ \setbox#1\vbox
+ {\offinterlineskip
+ \doifmarginswapelse
+ {\copy\leftbackground}
+ {\copy\rightbackground}
+ \box#1}%
+ \fi}
+
+\def\setbackgroundoffsets
+ {\ifsomebackground \ifnewbackground
+ \global\let\pagebackgroundhoffset\!!zeropoint
+ \global\let\pagebackgroundvoffset\!!zeropoint
+ \global\let\pagebackgrounddepth \!!zeropoint
+ \doifsomebackgroundelse{\v!text\v!text}\donetrue\donefalse
+ \ifdone\else\doifsomebackgroundelse\v!text\donetrue\donothing\fi
+ \ifdone
+ \bgroup
+ \scratchdimen\getvalue{\??ma\v!page\c!offset}%
+ \doifsomebackgroundelse{\v!top\v!text}\donothing
+ {\doifsomebackgroundelse{\v!bottom\v!text}\donothing
+ {\xdef\pagebackgroundhoffset{\the\scratchdimen}}}%
+ \doifsomebackgroundelse{\v!text\v!rightedge}\donothing
+ {\doifsomebackgroundelse{\v!text\v!leftedge}\donothing
+ {\xdef\pagebackgroundvoffset{\the\scratchdimen}%
+ \scratchdimen\getvalue{\??ma\v!page\c!depth}%
+ \xdef\pagebackgrounddepth{\the\scratchdimen}}}%
+ \egroup
+ \fi
+ \fi \fi}
+
+\appendtoks \setbackgroundoffsets \to \everybeforepagebody
+
+\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins
+
+\def\setbackgroundbox#1#2%
+ {\global\setbox#1\vbox
+ {\dontcomplain
+ \swapmargins
+ \ifconditional\swapbackgroundmargins
+ \doifmarginswapelse \donothing
+ {\swapmacros\v!rightmargin\v!leftmargin
+ \swapmacros\v!rightedge \v!leftedge}%
+ \fi
+ \calculatereducedvsizes
+ \offinterlineskip
+ #2\relax
+ \vskip\dimexpr-\topheight-\topdistance\relax
+ \dodopagebodybackground\v!top\topheight
+ \vskip\topdistance
+ \dodopagebodybackground\v!header\headerheight
+ \vskip\headerdistance
+ \dodopagebodybackground\v!text\textheight
+ \vskip\footerdistance
+ \dodopagebodybackground\v!footer\footerheight
+ \vskip\bottomdistance
+ \dodopagebodybackground\v!bottom\bottomheight
+ \vfilll}%
+ \smashbox#1}
+
+\def\dodopagebodybackground#1#2%
+ {\ifdim#2>\zeropoint % added, faster
+ \setbox\scratchbox\vbox to #2
+ \bgroup\hbox\bgroup
+ % \swapmargins
+ \goleftonpage
+ \dododopagebodybackground\leftedgewidth #2#1\v!leftedge
+ \hskip\leftedgedistance
+ \dododopagebodybackground\leftmarginwidth #2#1\v!leftmargin
+ \hskip\leftmargindistance
+ \dododopagebodybackground\makeupwidth #2#1\v!text
+ \hskip\rightmargindistance
+ \dododopagebodybackground\rightmarginwidth#2#1\v!rightmargin
+ \hskip\rightedgedistance
+ \dododopagebodybackground\rightedgewidth #2#1\v!rightedge
+ \egroup\egroup
+ \wd\scratchbox\zeropoint
+ \box\scratchbox\relax
+ \fi}
+
+\def\dododopagebodybackground#1#2#3#4% width height pos pos
+ {\ifsomebackgroundfound{#3#4}%
+ \ifdim#2>\zeropoint\relax
+ \ifdim#1>\zeropoint\relax
+ \doifvaluesomething{\??ma#3#4\c!setups}{\setups[\getvalue{\??ma#3#4\c!setups}]}% should not produce funny spaces !
+ \fastlocalframed
+ [\??ma#3#4]
+ [\c!component=#3-#4,\c!offset=\v!overlay,\c!setups=]
+ {\vbox to #2{\vss\hbox to#1{\hss\getvalue{\??ma#3#4\c!command}\hss}\vss}}%
+ \else
+ \hskip#1%
+ \fi
+ \else
+ \hskip#1%
+ \fi
+ \else
+ \hskip#1%
+ \fi}
+
+%D The background mechanism is quite demanding in terms or
+%D resources. We used to delay these definitions till runtime
+%D usage, but since today's \TEX's are large, we now do the
+%D work on forehand.
+%D
+%D \starttyping
+%D \setupbackgrounds [settings]
+%D \setupbackgrounds [paper,page,text,..] [settings]
+%D \setupbackgrounds [top,...] [leftedge,...] [settings]
+%D \stoptyping
+%D
+%D \showsetup{setupbackgrounds}
+%D
+%D Because the number of arguments runs from one to three,
+%D we need to check for it.
+
+\def\setupbackgrounds
+ {\dotripleempty\dosetupbackgrounds}
+
+\def\dosetupbackgrounds[#1][#2][#3]%
+ {\ifthirdargument
+ \global\somebackgroundtrue
+ \def\docommand##1%
+ {\doifinsetelse{##1}{\v!paper,\v!page,\v!leftpage,\v!rightpage}
+ {\getparameters[\??ma##1][#3]\checkbackground{##1}}
+ {\def\dodocommand####1{\getparameters[\??ma##1####1][#3]\checkbackground{##1####1}}%
+ \processcommalist[#2]\dodocommand}}%
+ \processcommalist[#1]\docommand
+ \else\ifsecondargument
+ \global\somebackgroundtrue
+ \doifcommonelse{#1}{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage}
+ {\def\docommand##1{\getparameters[\??ma##1][#2]\checkbackground{##1}}%
+ \processcommalist[#1]\docommand}%
+ {\setupbackgrounds
+ [#1]%
+ [\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge]%
+ [#2]}%
+ \else\iffirstargument
+ \getparameters[\??ma][#1]%
+ \fi\fi\fi
+ \doifelsevalue{\??ma\v!page\c!offset}\v!overlay
+ {\global\pageoffset\zeropoint}
+ {\global\pageoffset\getvalue{\??ma\v!page\c!offset}}%
+ \global\pagedepth\getvalue{\??ma\v!page\c!depth}%
+ \xdef\pagebackgroundoffset{\the\pageoffset}%
+ \xdef\pagebackgrounddepth {\the\pagedepth }%
+ \doifelse\@@mastate\v!stop
+ {\global\newbackgroundfalse}
+ {\global\newbackgroundtrue }}
+
+\let\pagebackgroundoffset\!!zeropoint
+\let\pagebackgrounddepth \!!zeropoint
+
+%D Each areas (currently there are $1+3+25+1=30$ of them)
+%D has its own low level framed object associated.
+
+\presetlocalframed [\??ma\v!paper]
+\presetlocalframed [\??ma\v!page]
+\presetlocalframed [\??ma\v!leftpage]
+\presetlocalframed [\??ma\v!rightpage]
+
+\copyparameters
+ [\??ma\v!paper\c!frame][\??ma\v!page]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+\copyparameters
+ [\??ma\v!paper\c!background][\??ma\v!page]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+\copyparameters
+ [\??ma\v!page\c!frame][\??ma\v!page]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+\copyparameters
+ [\??ma\v!page\c!background][\??ma\v!page]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+\copyparameters
+ [\??ma\v!leftpage\c!frame][\??ma\v!leftpage]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+\copyparameters
+ [\??ma\v!leftpage\c!background][\??ma\v!leftpage]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+\copyparameters
+ [\??ma\v!rightpage\c!frame][\??ma\v!rightpage]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+\copyparameters
+ [\??ma\v!rightpage\c!background][\??ma\v!rightpage]
+ [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen]
+
+%D We save some keying by defining the areas using
+%D intermediate commands. The inheritance macro makes sure
+%D that copies are efficient.
+
+\def\dodocommand#1#2%
+ {\copylocalframed
+ [\??ma#1#2][\??ma\v!page]%
+ \getparameters
+ [\??ma#1#2]
+ [\c!background=,\c!frame=,\c!color=,\c!screen=\@@rsscreen,
+ \c!bottomframe=,\c!topframe=,\c!leftframe=,\c!rightframe=]%
+ \inheritparameter[\??ma][#1#2\c!color][\v!page\c!color]%
+ \inheritparameter[\??ma][#1#2\c!screen][\v!page\c!screen]%
+ \inheritparameter[\??ma][#1#2\c!framecolor][\v!page\c!framecolor]%
+ \inheritparameter[\??ma][#1#2\c!backgroundcolor][\v!page\c!backgroundcolor]%
+ \inheritparameter[\??ma][#1#2\c!backgroundscreen][\v!page\c!backgroundscreen]}
+
+%D The stand alone text area inherits from the page too.
+
+\dodocommand\v!text \empty
+\dodocommand\v!hidden\empty
+
+%D We now define all 25 main areas in a row.
+
+\def\docommand#1%
+ {\dodocommand#1\v!leftedge
+ \dodocommand#1\v!leftmargin
+ \dodocommand#1\v!text
+ \dodocommand#1\v!rightmargin
+ \dodocommand#1\v!rightedge}
+
+\docommand\v!top
+\docommand\v!header
+\docommand\v!text
+\docommand\v!footer
+\docommand\v!bottom
+
+%D We need some cleanup now.
+
+\let\dodocommand\relax \let\docommand\relax
+
+%D We now set up the individual areas to use reasonable
+%D defaults.
+
+\setupbackgrounds
+ [\c!state=\c!start]
+
+\setupbackgrounds
+ [\v!paper,\v!page,\v!leftpage,\v!rightpage]
+ [\c!frame=\v!off,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ \c!background=,
+ \c!screen=\@@rsscreen,
+ \c!color=,
+ %\c!frameoffset=\getvalue{\??ma\v!page\c!offset},
+ %\c!backgroundoffset=\getvalue{\??ma\v!page\c!offset},
+ \c!offset=\!!zeropoint, % later set to \v!overlay, watch out !
+ \c!depth=\!!zeropoint]
+
+\def\docommand#1%
+ {\inheritparameter[\??ma][#1\c!frameoffset][\v!page\c!offset]%
+ \inheritparameter[\??ma][#1\c!backgroundoffset][\v!page\c!offset]}
+
+\docommand\v!paper
+\docommand\v!page
+\docommand\v!leftpage
+\docommand\v!rightpage
+
+%D Again we clean up temporary macros.
+
+\let\docommand\relax
+
+%D The hidden layer can be populated by extending the
+%D following comma separated list. This only happens in core
+%D modules.
+
+% todo page-2 .. page+2 achter pagina -> bleed
+% spread-2 .. spread+2 achter spread -> spread (repeat 2 times)
+
+\def\enablehiddenbackground
+ {\global\settrue\hiddenbackgroundenabled
+ \global\somebackgroundtrue
+ \recalculatebackgrounds}
+
+\def\disablehiddenbackground
+ {\global\setfalse\hiddenbackgroundenabled}
+
+\def\hiddenbackground
+ {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2}
+
+\setupbackgrounds
+ [\v!hidden]
+ [\c!background=\hiddenbackground]
+
+% The next series is used in local (for instance floating)
+% backgrounds.
+
+\presetlocalframed
+ [\??ma\v!local]
+
+\def\localbackground
+ {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2}
+
+\defineoverlay[\v!local-2][\positionoverlay{\v!local-2}]
+\defineoverlay[\v!local-1][\positionoverlay{\v!local-1}]
+\defineoverlay[\v!local+1][\positionoverlay{\v!local+1}]
+\defineoverlay[\v!local+2][\positionoverlay{\v!local+2}]
+
+\def\addlocalbackgroundtobox
+ {\ifconditional\hiddenbackgroundenabled
+ \expandafter\doaddlocalbackground
+ \else
+ \resetglobal \expandafter\gobbleoneargument
+ \fi}
+
+\def\doaddlocalbackground#1%
+ {\dodoglobal\setbox#1\hbox
+ {\fastlocalframed % \localframed
+ [\??ma\v!local]
+ [\c!component=local,\c!frame=\v!off,\c!offset=\v!overlay,\c!setups=,%
+ \c!location=\v!keep,% when we use \localframed instead of \fastlocalframed
+ \c!background=\localbackground]%
+ {\registerMPlocaltextarea{\box#1}}}%
+ \resetglobal % redundant
+ \doglobal\increment\localpositionnumber\relax} % afterwards !
+
+% Test how previous macro behaves with depth:
+%
+% \startcolumnset
+% \input tufte
+% \placefigure{none}{\framed[lines=5]{xxx}}
+% \input tufte
+% \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate}
+% \input tufte
+% \stopcolumnset
+
+%D Because we haven't really set up backgrounds yet, we set
+%D the main efficiency switch to false.
+
+\somebackgroundfalse
+
+\protect \endinput
+
+%D Removed \quote {features}:
+%D
+%D \starttyping
+%D \startinteraction
+%D \doifmarginswapelse
+%D {\copy\leftbackground}
+%D {\copy\rightbackground}%
+%D \stopinteraction
+%D \stoptyping
+%D
+%D \starttyping
+%D \edef\setpagebackgrounddepth%
+%D {\dp#2=\the\dp#2}%
+%D \setbox#2=\vbox\localframed[\??ma#1]{...}
+%D \setpagebackgrounddepth
+%D \stoptyping
diff --git a/tex/context/base/page-bck.mkiv b/tex/context/base/page-bck.mkiv
new file mode 100644
index 000000000..93400943d
--- /dev/null
+++ b/tex/context/base/page-bck.mkiv
@@ -0,0 +1,563 @@
+%D \module
+%D [ file=page-bck, % copied from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Backgrounds,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Backgrounds}
+
+% \chardef\kindofpagetextareas=1 will isolate graphics from backgrounds
+
+% todo \fastlocalframed -> \localbackgroundframed
+
+\unprotect
+
+%D \macros
+%D {recalculatebackgrounds}
+%D
+%D We use a couple of switches so that we can minimize the
+%D amount of background calculations. The main switch is set
+%D by the recalculate directive.
+%D
+%D \starttyping
+%D \recalculatebackgrounds
+%D \stoptyping
+%D
+%D Other modules may not directly set the switches
+%D themselves.
+
+\newif\ifnewbackground
+\newif\ifsomebackground
+
+%D For special purposes, users can question the \type
+%D {*background} mode. This mode is only available when
+%D typesetting the pagebody.
+%D
+%D \starttyping
+%D \startmode[*background] ...
+%D \stoptyping
+
+\appendtoks
+ \ifsomebackground \ifnewbackground \setsystemmode\v!background \fi \fi
+\to \everybeforepagebody
+
+%D \macros
+%D {addmainbackground, addtextbackground,
+%D addpagebackground, addprintbackground}
+%D
+%D Apart from the previously mentioned directive, the
+%D interface between this module and the other modules
+%D is made up by four macros that add background to parts of
+%D the layout.
+%D
+%D \starttyping
+%D \addmainbackground
+%D \addtextbackground
+%D \addpagebackground
+%D \addprintbackground
+%D \stoptyping
+
+%D To minimize calculations, we keep track of the state of the
+%D background of each area. A previous implementation did
+%D check each call to the background calculation macro, but
+%D using an intermediate usage flag instead of testing each
+%D time saves about 3\% on a run with a couple of backgrounds.
+%D (On the 824 pages maps bibliography runtime went down from
+%D 309 to 299 seconds.)
+
+% \let\currentotrbackground\empty
+%
+% \def\@@docheckbackground#1#2%
+% {\ifcsname\currentotrbackground#1\endcsname
+% \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\!!doneatrue\fi
+% \fi}
+%
+% \def\@@nocheckbackground#1#2%
+% {\ifcsname\currentotrbackground#1\endcsname
+% \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\else\!!doneatrue\fi
+% \fi}
+%
+% \def\checkbackground#1%
+% {\edef\currentotrbackground{\??ma#1}%
+% \begingroup
+% \!!doneafalse
+% \if!!donea\else\@@nocheckbackground\c!background \empty
+% \if!!donea\else\@@docheckbackground\c!frame \v!on
+% \if!!donea\else\@@nocheckbackground\c!foregroundcolor\empty
+% \if!!donea\else\@@docheckbackground\c!leftframe \v!on
+% \if!!donea\else\@@docheckbackground\c!rightframe \v!on
+% \if!!donea\else\@@docheckbackground\c!topframe \v!on
+% \if!!donea\else\@@docheckbackground\c!bottomframe \v!on \fi\fi\fi\fi\fi\fi\fi
+% \if!!donea
+% \endgroup\setusage \currentotrbackground
+% \else
+% \endgroup\resetusage\currentotrbackground
+% \fi}
+%
+% \def\ifsomebackgroundfound#1%
+% {\ifusage{\??ma#1}}
+%
+% \def\doifsomebackgroundelse#1%
+% {\ifusage{\??ma#1}%
+% \expandafter\firstoftwoarguments
+% \else
+% \expandafter\secondoftwoarguments
+% \fi}
+
+\let\currentotrbackground\empty
+
+\def\@@docheckbackground#1#2%
+ {\ifcsname\currentotrbackground#1\endcsname
+ \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\!!doneatrue\fi
+ \fi}
+
+\def\@@nocheckbackground#1#2%
+ {\ifcsname\currentotrbackground#1\endcsname
+ \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\else\!!doneatrue\fi
+ \fi}
+
+\def\checkbackground#1% here we need an \ifempty primitive
+ {\edef\currentotrbackground{\??ma#1}%
+ \begingroup
+ \!!doneafalse
+ \if!!donea\else\@@nocheckbackground\c!background \empty
+ \if!!donea\else\@@docheckbackground\c!frame \v!on
+ \if!!donea\else\@@nocheckbackground\c!foregroundcolor\empty
+ \if!!donea\else\@@docheckbackground\c!leftframe \v!on
+ \if!!donea\else\@@docheckbackground\c!rightframe \v!on
+ \if!!donea\else\@@docheckbackground\c!topframe \v!on
+ \if!!donea\else\@@docheckbackground\c!bottomframe \v!on \fi\fi\fi\fi\fi\fi\fi
+ \if!!donea
+ \endgroup\expandafter\let\csname\currentotrbackground\endcsname\relax
+ \else
+ \endgroup\expandafter\let\csname\currentotrbackground\endcsname\undefined
+ \fi}
+
+\def\ifsomebackgroundfound#1%
+ {\ifcsname\??ma#1\endcsname}
+
+\def\doifsomebackgroundelse#1%
+ {\ifcsname\??ma#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\doifsomebackground#1%
+ {\ifcsname\??ma#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D The background mechanism falls back on the \type {\framed}
+%D macro. This means that all normal frame and overlay
+%D features can be used.
+
+% \def\addsomebackground#1#2#3#4% area box width height / zero test added
+% {\ifsomebackgroundfound#1\ifdim#3>\zeropoint\ifdim#4>\zeropoint
+% \ifcsname\??ma#1\c!setups\endcsname % to be done
+% \doprocesslocalsetups{\csname\??ma#1\c!setups\endcsname}% should not produce funny spaces !
+% \fi
+% \setbox#2\vbox\fastlocalframed % maybe \superfastlocalframed{tag}{w}{h}
+% [\??ma#1]%
+% [\c!component=#1,\c!width=#3,\c!height=#4]% are width and height used?
+% {\dp#2\zeropoint\box#2}%
+% \fi\fi\fi}
+
+\def\addsomebackground#1#2#3#4% area box width height / zero test added
+ {\ifsomebackgroundfound#1\ifdim#3>\zeropoint\ifdim#4>\zeropoint
+ \ifcsname\??ma#1\c!setups\endcsname % to be done
+ \doprocesslocalsetups{\csname\??ma#1\c!setups\endcsname}% should not produce funny spaces !
+ \fi
+ \localbackgroundframed{#1}{#2}{#3}{#4}%
+ \fi\fi\fi}
+
+%D There are quite some backgrounds. At the bottom layer,
+%D there is the {\em paper} background. This one is only
+%D used for special purposes, like annotations to documents.
+
+\def\addprintbackground#1%
+ {\addsomebackground\v!paper#1\printpaperwidth\printpaperheight}
+
+%D The page backgrounds can be put behind the {\em left
+%D page}, the {\em right page} or {\em each page}. As with
+%D the paper background, these are calculated on each page.
+
+\def\addpagebackground#1%
+ {\doifbothsidesoverruled
+ {\addsomebackground\v!rightpage#1\paperwidth\paperheight}
+ {\addsomebackground\v!rightpage#1\paperwidth\paperheight}
+ {\addsomebackground\v!leftpage #1\paperwidth\paperheight}%
+ \addsomebackground\v!page #1\paperwidth\paperheight}
+
+%D Then there are the 25 areas that make up the layout: {\em
+%D top, header, text, footer, bottom} times {\em left edge,
+%D left margin, text, right margin, right edge}. These are
+%D only recalculated when they change or when the \type
+%D {status} is set to \type {repeat}.
+
+\newbox\leftbackground
+\newbox\rightbackground
+
+\def\addmainbackground#1% todo: dimension spec
+ {\ifsomebackground
+ \ifnewbackground \setbackgroundboxes \fi
+ \setbox#1\vbox
+ {\offinterlineskip
+ \doifmarginswapelse{\copy\leftbackground}{\copy\rightbackground}%
+ \box#1}%
+ \fi}
+
+%D Finaly there is an aditional {\em text} background, again
+%D useful for special purposes only. This one is calculated
+%D each time. The hidden backgrounds are not meant for users!
+
+\newconditional\hiddenbackgroundenabled
+
+\def\addtextbackground#1%
+ {\ifconditional\hiddenbackgroundenabled
+ \addsomebackground\v!hidden#1\makeupwidth\textheight % mine !
+ \fi
+ \addsomebackground\v!text#1\makeupwidth\textheight}
+
+%D The next couple of macros implement the area backgrounds.
+%D As said, these are cached in dedicated boxes. The offsets
+%D and depth of the page are used for alignment purposes.
+
+\newdimen\pageoffset % bleed
+\newdimen\pagedepth
+
+% \def\setbackgroundboxes
+% {\showmessage\m!layouts8\empty
+% \setbackgroundbox\leftbackground\relax
+% \ifdoublesided
+% \setbackgroundbox\rightbackground\doswapmargins
+% \fi
+% \doifnot\@@mastatus\v!herhaal{\global\newbackgroundfalse}}
+
+%D We need a bit more clever mechanism in order to handle
+%D layers well. This means that we cannot calculate both
+%D background at the same time since something may have
+%D changed halfway a page.
+
+\chardef\newrightbackground\zerocount
+\chardef\newleftbackground \zerocount
+
+\def\recalculatebackgrounds
+ {\global\newbackgroundtrue}
+
+\def\setbackgroundboxes
+ {\ifnewbackground
+ \dosetbackgroundboxesr
+ \fi
+ \doifbothsides\dosetbackgroundboxesa\dosetbackgroundboxesb\dosetbackgroundboxesc
+ \ifx\@@mastate\v!repeat\else\global\newbackgroundfalse\fi}
+
+\def\dosetbackgroundboxesr
+ {\global\chardef\newrightbackground\plusone
+ \global\chardef\newleftbackground\plusone
+ \global\setbox\leftbackground\emptybox
+ \global\setbox\rightbackground\emptybox}
+\def\dosetbackgroundboxesa
+ {\ifcase\newleftbackground \else
+ % \showmessage\m!layouts8\empty
+ \setbackgroundbox\leftbackground\relax
+ \global\chardef\newleftbackground\zerocount
+ \global\chardef\newrightbackground\zerocount
+ \fi}
+\def\dosetbackgroundboxesb
+ {\ifcase\newleftbackground \else
+ % \showmessage\m!layouts8\empty
+ \setbackgroundbox\leftbackground\relax
+ \global\chardef\newleftbackground\zerocount
+ \fi}
+\def\dosetbackgroundboxesc
+ {\ifcase\newrightbackground \else
+ % \showmessage\m!layouts8\empty
+ \setbackgroundbox\rightbackground\doswapmargins
+ \global\chardef\newrightbackground\zerocount
+ \fi}
+
+\def\addmainbackground#1% todo: dimension spec
+ {\ifsomebackground
+ \setbackgroundboxes
+ \setbox#1\vbox
+ {\offinterlineskip
+ \doifmarginswapelse{\copy\leftbackground}{\copy\rightbackground}%
+ \box#1}%
+ \fi}
+
+\newdimen\pagebackgroundhoffset
+\newdimen\pagebackgroundvoffset
+\newdimen\pagebackgrounddepth
+\newdimen\pagebackgroundoffset
+
+\def\setbackgroundoffsets % used in menus (we can use ifcsname's here)
+ {\ifsomebackground \ifnewbackground
+ \global\pagebackgroundhoffset\zeropoint
+ \global\pagebackgroundvoffset\zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \doifsomebackgroundelse{\v!text\v!text}\donetrue\donefalse
+ \ifdone\else\doifsomebackgroundelse\v!text\donetrue\donothing\fi
+ \ifdone
+ \begingroup
+ \scratchdimen\csname\??ma\v!page\c!offset\endcsname
+ \doifsomebackgroundelse{\v!top\v!text}\donothing
+ {\doifsomebackgroundelse{\v!bottom\v!text}\donothing
+ {\global\pagebackgroundhoffset\scratchdimen}}%
+ \doifsomebackgroundelse{\v!text\v!rightedge}\donothing
+ {\doifsomebackgroundelse{\v!text\v!leftedge}\donothing
+ {\global\pagebackgroundvoffset\scratchdimen
+ \global\pagebackgrounddepth\csname\??ma\v!page\c!depth\endcsname}}%
+ \endgroup
+ \fi
+ \fi \fi}
+
+\appendtoks \setbackgroundoffsets \to \everybeforepagebody
+
+\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins
+
+\def\setbackgroundbox#1#2%
+ {\global\setbox#1\vbox
+ {\dontcomplain
+ \swapmargins
+ \ifconditional\swapbackgroundmargins
+ \doifmarginswapelse \donothing
+ {\swapmacros\v!rightmargin\v!leftmargin
+ \swapmacros\v!rightedge \v!leftedge}%
+ \fi
+ \calculatereducedvsizes
+ \offinterlineskip
+ #2\relax
+ \vskip\dimexpr-\topheight-\topdistance\relax
+ \dodopagebodybackground\v!top\topheight
+ \vskip\topdistance
+ \dodopagebodybackground\v!header\headerheight
+ \vskip\headerdistance
+ \dodopagebodybackground\v!text\textheight
+ \vskip\footerdistance
+ \dodopagebodybackground\v!footer\footerheight
+ \vskip\bottomdistance
+ \dodopagebodybackground\v!bottom\bottomheight
+ \vfilll}%
+ \smashbox#1}
+
+\def\dodopagebodybackground#1#2% maybe helper
+ {\ifdim#2>\zeropoint % added, faster
+ \setbox\scratchbox\vbox to #2
+ \bgroup\hbox\bgroup
+ % \swapmargins
+ \goleftonpage
+ \dododopagebodybackground\leftedgewidth #2#1\v!leftedge
+ \hskip\leftedgedistance
+ \dododopagebodybackground\leftmarginwidth #2#1\v!leftmargin
+ \hskip\leftmargindistance
+ \dododopagebodybackground\makeupwidth #2#1\v!text
+ \hskip\rightmargindistance
+ \dododopagebodybackground\rightmarginwidth#2#1\v!rightmargin
+ \hskip\rightedgedistance
+ \dododopagebodybackground\rightedgewidth #2#1\v!rightedge
+ \egroup\egroup
+ \wd\scratchbox\zeropoint
+ \box\scratchbox\relax
+ \fi}
+
+\def\dododopagebodybackground#1#2#3#4% width height pos pos % maybe helper
+ {\ifsomebackgroundfound{#3#4}%
+ \ifdim#2>\zeropoint\relax
+ \ifdim#1>\zeropoint\relax
+ \ifcsname\??ma#3#4\c!setups\endcsname % to be done
+ \doprocesslocalsetups{\csname\??ma#3#4\c!setups\endcsname}% should not produce funny spaces !
+ \fi
+ \fastlocalframed
+ [\??ma#3#4]%
+ [\c!component=#3-#4]%
+ {\vbox to #2{\vss\hbox to#1{\hss\csname\??ma#3#4\c!command\endcsname\hss}\vss}}%
+ \else
+ \hskip#1%
+ \fi
+ \else
+ \hskip#1%
+ \fi
+ \else
+ \hskip#1%
+ \fi}
+
+%D The background mechanism is quite demanding in terms or
+%D resources. We used to delay these definitions till runtime
+%D usage, but since today's \TEX's are large, we now do the
+%D work on forehand.
+%D
+%D \starttyping
+%D \setupbackgrounds [settings]
+%D \setupbackgrounds [paper,page,text,..] [settings]
+%D \setupbackgrounds [top,...] [leftedge,...] [settings]
+%D \stoptyping
+%D
+%D \showsetup{setupbackgrounds}
+%D
+%D Because the number of arguments runs from one to three,
+%D we need to check for it.
+
+\unexpanded\def\setupbackgrounds
+ {\dotripleempty\dosetupbackgrounds}
+
+\def\dosetupbackgrounds[#1][#2][#3]%
+ {\ifthirdargument
+ \global\somebackgroundtrue
+ \def\docommand##1%
+ {\doifinsetelse{##1}{\v!paper,\v!page,\v!leftpage,\v!rightpage}
+ {\getparameters[\??ma##1][#3]\checkbackground{##1}}
+ {\def\dodocommand####1{\getparameters[\??ma##1####1][#3]\checkbackground{##1####1}}%
+ \processcommalist[#2]\dodocommand}}%
+ \processcommalist[#1]\docommand
+ \else\ifsecondargument
+ \global\somebackgroundtrue
+ \doifcommonelse{#1}{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage}
+ {\def\docommand##1{\getparameters[\??ma##1][#2]\checkbackground{##1}}%
+ \processcommalist[#1]\docommand}%
+ {\setupbackgrounds
+ [#1]%
+ [\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge]%
+ [#2]}%
+ \else\iffirstargument
+ \getparameters[\??ma][#1]%
+ \fi\fi\fi
+ \doifelsevalue{\??ma\v!page\c!offset}\v!overlay
+ {\global\pageoffset\zeropoint}
+ {\global\pageoffset\csname\??ma\v!page\c!offset\endcsname}%
+ \global\pagedepth\csname\??ma\v!page\c!depth\endcsname
+ \global\pagebackgroundoffset\pageoffset
+ \global\pagebackgrounddepth\pagedepth
+ \doifelse\@@mastate\v!stop
+ {\global\newbackgroundfalse}
+ {\global\newbackgroundtrue }}
+
+%D Each areas (currently there are $1+3+25+1=30$ of them)
+%D has its own low level framed object associated.
+
+\def\installsomebackground#1#2{\inheritlocalframed[\??ma#1#2][\??od]}
+
+\installsomebackground \v!paper \empty
+\installsomebackground \v!page \empty
+\installsomebackground \v!leftpage \empty
+\installsomebackground \v!rightpage \empty
+
+%D The stand alone text area inherits from the page too.
+
+\installsomebackground \v!text \empty
+\installsomebackground \v!hidden \empty
+
+%D We save some keying by defining the areas using a helper:
+
+\def\docommand#1%
+ {\installsomebackground#1\v!leftedge
+ \installsomebackground#1\v!leftmargin
+ \installsomebackground#1\v!text
+ \installsomebackground#1\v!rightmargin
+ \installsomebackground#1\v!rightedge}
+
+\docommand \v!top
+\docommand \v!header
+\docommand \v!text
+\docommand \v!footer
+\docommand \v!bottom
+
+%D We need some cleanup now.
+
+\let\docommand\relax
+
+%D We now set up the individual areas to use reasonable
+%D defaults.
+
+\installsomebackground \v!paper \empty
+\installsomebackground \v!page \empty
+\installsomebackground \v!leftpage \empty
+\installsomebackground \v!rightpage \empty
+
+\getparameters
+ [\??ma\v!page]
+ [\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere
+ \c!depth=\zeropoint]
+
+%D General setup:
+
+\setupbackgrounds
+ [\c!state=\c!start]
+
+%D The hidden layer can be populated by extending the
+%D following comma separated list. This only happens in core
+%D modules.
+
+% todo page-2 .. page+2 achter pagina -> bleed
+% spread-2 .. spread+2 achter spread -> spread (repeat 2 times)
+
+\def\enablehiddenbackground
+ {\global\settrue\hiddenbackgroundenabled
+ \global\somebackgroundtrue
+ \recalculatebackgrounds}
+
+\def\disablehiddenbackground
+ {\global\setfalse\hiddenbackgroundenabled}
+
+\def\hiddenbackground
+ {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2}
+
+\setupbackgrounds
+ [\v!hidden]
+ [\c!background=\hiddenbackground]
+
+% The next series is used in local (for instance floating)
+% backgrounds.
+
+\installsomebackground \v!local \empty % not really a background, invisible for users
+
+\getparameters
+ [\??ma\v!local]
+ [\c!component=local,
+ \c!background=\localbackground]
+
+\def\localbackground
+ {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2}
+
+\defineoverlay[\v!local-2][\positionoverlay{\v!local-2}]
+\defineoverlay[\v!local-1][\positionoverlay{\v!local-1}]
+\defineoverlay[\v!local+1][\positionoverlay{\v!local+1}]
+\defineoverlay[\v!local+2][\positionoverlay{\v!local+2}]
+
+\def\addlocalbackgroundtobox
+ {\ifconditional\hiddenbackgroundenabled
+ \expandafter\doaddlocalbackground
+ \else
+ \resetglobal \expandafter\gobbleoneargument
+ \fi}
+
+\def\doaddlocalbackground#1%
+ {\dodoglobal\setbox#1\hbox{\fastlocalframed[\??ma\v!local][]{\registerMPlocaltextarea{\box#1}}}%
+ \resetglobal % redundant
+ \doglobal\increment\localpositionnumber\relax} % afterwards !
+
+% Test how previous macro behaves with depth:
+%
+% \startcolumnset
+% \input tufte
+% \placefigure{none}{\framed[lines=5]{xxx}}
+% \input tufte
+% \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate}
+% \input tufte
+% \stopcolumnset
+
+%D Because we haven't really set up backgrounds yet, we set
+%D the main efficiency switch to false.
+
+\somebackgroundfalse
+
+\protect \endinput
diff --git a/tex/context/base/page-flt.lua b/tex/context/base/page-flt.lua
new file mode 100644
index 000000000..74d1e4e8c
--- /dev/null
+++ b/tex/context/base/page-flt.lua
@@ -0,0 +1,227 @@
+if not modules then modules = { } end modules ['page-flt'] = {
+ version = 1.001,
+ comment = "companion to page-flt.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setdimen, setbox, setcount, texbox = tex.setdimen, tex.setbox, tex.setcount, tex.box
+local insert, remove = table.insert, table.remove
+local texwrite, texsprint, ctxcatcodes = tex.write, tex.sprint, tex.ctxcatcodes
+
+local copy_node_list = node.copy_list
+
+local trace_floats = false trackers.register("graphics.floats", function(v) trace_floats = v end) -- name might change
+
+-- we use floatbox, floatwidth, floatheight
+-- text page leftpage rightpage (todo: top, bottom, margin, order)
+
+floats = floats or { }
+
+local noffloats, last, default, pushed = 0, nil, "text", { }
+
+local function initialize()
+ return {
+ text = { },
+ page = { },
+ leftpage = { },
+ rightpage = { },
+ }
+end
+
+local stacks = initialize()
+
+-- list location
+
+function floats.stacked(which) -- floats.thenofstacked
+ return #stacks[which or default]
+end
+
+function floats.thestacked(which)
+ return texwrite(#stacks[which or default])
+end
+
+function floats.push()
+ insert(pushed,stacks)
+ stacks = initialize()
+ setcount("global","savednoffloats",0)
+end
+
+function floats.pop()
+ local popped = remove(pushed)
+ if popped then
+ for which, stack in next, stacks do
+ for i=1,#stack do
+ insert(popped[which],stack[i])
+ end
+ end
+ stacks = popped
+ setcount("global","savednoffloats",#stacks[default])
+ end
+end
+
+local function setdimensions(b)
+ local w, h, d = 0, 0, 0
+ if b then
+ w, h, d = b.width, b.height, b.depth
+ end
+ setdimen("global","floatwidth", w)
+ setdimen("global","floatheight", h+d)
+ return w, h, d
+end
+
+local function get(stack,n)
+ n = n or #stack
+ if n > 0 then
+ local t = stack[n]
+ if t then
+ return t, t.box, n
+ end
+ end
+end
+
+function floats.save(which,data)
+ which = which or default
+ local stack = stacks[which]
+ noffloats = noffloats + 1
+ local b = texbox.floatbox
+ local w, h, d = b.width, b.height, b.depth
+ local t = {
+ n = noffloats,
+ data = data or { },
+ box = copy_node_list(b),
+ }
+ texbox.floatbox = nil
+ insert(stack,t)
+ setcount("global","savednoffloats",#stacks[default])
+ if trace_floats then
+ logs.report("floats","saving %s float %s in slot %s (%i,%i,%i)",which,noffloats,#stack,w,h,d)
+ else
+ interfaces.showmessage("floatblocks",2,noffloats)
+ end
+end
+
+function floats.resave(which)
+ if last then
+ which = which or default
+ local stack = stacks[which]
+ local b = texbox.floatbox
+ local w, h, d = b.width, b.height, b.depth
+ last.box = copy_node_list(b)
+ texbox.floatbox = nil
+ insert(stack,1,last)
+ setcount("global","savednoffloats",#stacks[default])
+ if trace_floats then
+ logs.report("floats","resaving %s float %s in slot %s (%i,%i,%i)",which,noffloats,#stack,w,h,d)
+ else
+ interfaces.showmessage("floatblocks",2,noffloats)
+ end
+ else
+ logs.report("floats","unable to resave float")
+ end
+end
+
+function floats.flush(which,n)
+ which = which or default
+ local stack = stacks[which]
+ local t, b, n = get(stack,n or 1)
+ if t then
+ local w, h, d = setdimensions(b)
+ if trace_floats then
+ logs.report("floats","flushing %s float %s from slot %s (%i,%i,%i)",which,t.n,n,w,h,d)
+ else
+ interfaces.showmessage("floatblocks",3,t.n)
+ end
+ texbox.floatbox = b
+ last = remove(stack,n)
+ last.box = nil
+ setcount("global","savednoffloats",#stacks[default])
+ else
+ setdimensions()
+ end
+end
+
+function floats.thevar(name,default)
+ local value = last and last.data[name] or default
+ if value and value ~= "" then
+ texsprint(ctxcatcodes,value)
+ end
+end
+
+function floats.consult(which,n)
+ which = which or default
+ local stack = stacks[which]
+ local t, b, n = get(stack,n)
+ if t then
+ local w, h, d = setdimensions(b)
+ if trace_floats then
+ logs.report("floats","consulting %s float %s in slot %s (%i,%i,%i)",which,t.n,n,w,h,d)
+ end
+ return t, b, n
+ else
+ if trace_floats then
+ logs.report("floats","nothing to consult")
+ end
+ setdimensions()
+ end
+end
+
+function floats.collect(which,maxwidth,distance)
+ which = which or default
+ local stack = stacks[which]
+ local n, m = #stack, 0
+ for i=1,n do
+ local t, b, n = get(stack,i)
+ if t then
+ local w, h, d = setdimensions(b)
+ if w + distance < maxwidth then
+ m = m + 1
+ maxwidth = maxwidth - w - distance
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if m == 0 then
+ m = 1
+ end
+ setcount("global","nofcollectedfloats",m)
+end
+
+function commands.doifsavedfloatelse(which)
+ local stack = stacks[which or default]
+ commands.doifelse(#stack>0)
+end
+
+function floats.thecheckedpagefloat(packed)
+ local result = ""
+ if structure.pages.is_odd() then
+ if #stacks.rightpage > 0 then
+ result = "rightpage"
+ elseif #stacks.page > 0 then
+ result = "page"
+ elseif #stacks.leftpage > 0 then
+ if packed then
+ result = "leftpage"
+ else
+ result = "empty"
+ end
+ end
+ else
+ if #stacks.leftpage > 0 then
+ result = "leftpage"
+ elseif #stacks.page > 0 then
+ result = "page"
+ elseif #stacks.rightpage > 0 then
+ if packed then
+ result = "rightpage"
+ else
+ result = "empty"
+ end
+ end
+ end
+ texsprint(ctxcatcodes,result)
+end
diff --git a/tex/context/base/page-flt.mkiv b/tex/context/base/page-flt.mkiv
new file mode 100644
index 000000000..944626b8e
--- /dev/null
+++ b/tex/context/base/page-flt.mkiv
@@ -0,0 +1,233 @@
+%D \module
+%D [ file=page-flt,
+%D version=2010.04,08,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Float Management,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Float Management}
+
+%D This module has code that previously was in other modules. There is
+%D also float related code in \type {strc-flt.mkiv}.
+
+\registerctxluafile{page-flt}{1.001}
+
+\unprotect
+
+%D To be checked and removed
+
+%def\dosavefloatinfo {\showmessage\m!floatblocks2{\the\totalnoffloats}}
+\def\doinsertfloatinfo {\showmessage\m!floatblocks4{\the\totalnoffloats}}
+\def\dofloatflushedinfo{\showmessage\m!floatblocks3{\the\numexpr\totalnoffloats-\savednoffloats\relax}}
+
+%D Extra float registers.
+
+\newif\ifsomefloatwaiting \somefloatwaitingfalse
+\newif\ifroomforfloat \roomforfloattrue
+\newif\ifnofloatpermitted \nofloatpermittedfalse
+\newif\ifcenterfloatbox \centerfloatboxtrue
+\newif\iflocalcenterfloatbox \localcenterfloatboxfalse
+\newif\ifglobalcenterfloatbox \globalcenterfloatboxfalse
+\newif\ifflushingfloats \flushingfloatsfalse
+\newif\ifpackflushedfloats \packflushedfloatstrue % for the moment
+\newif\ifpackcolumnfloats \packcolumnfloatstrue
+
+\newcount\totalnoffloats
+\newcount\savednoffloats
+\newcount\noffloatinserts
+\newcount\nofcollectedfloats % communication channel
+
+\newbox \floatlist
+\newbox \savedfloatlist
+\newbox \floattext
+
+\newdimen\floatwidth
+\newdimen\floatheight
+\newdimen\floatdepth
+\newdimen\floattextwidth
+\newdimen\floattextheight
+
+\newbox \floatbox
+\newbox \savedfloatbox
+
+%D From now on we manage the float stack at the \LUA\ end instead of packing
+%D them in a box and splitting off stacked floats. It's not so much less code
+%D but it's cleaner this way. It also opens op some posibilities as we can now
+%D more conveniently cary additional information around.
+
+\newtoks \everyfloatscheck
+
+\appendtoks
+ \ifcase\savednoffloats
+ \global\somefloatwaitingfalse
+ \else
+ \global\somefloatwaitingtrue
+ \fi
+\to \everyfloatscheck
+
+\def\dofloatsflush#1#2%
+ {\ctxlua{floats.flush("#1",\number#2)}%
+ \the\everyfloatscheck}
+
+\def\dofloatssave#1%
+ {\ctxlua{floats.save("#1")}%
+ \the\everyfloatscheck}
+
+\def\dofloatsresave#1%
+ {\ctxlua{floats.resave("#1")}%
+ \the\everyfloatscheck}
+
+\def\dopushsavedfloats
+ {\ctxlua{floats.push()}%
+ \the\everyfloatscheck}
+
+\def\dopopsavedfloats
+ {\ctxlua{floats.pop()}%
+ \the\everyfloatscheck}
+
+\def\dofloatsgetinfo#1%
+ {\ctxlua{floats.consult("#1")}}
+
+\def\doifsavedfloatelse#1%
+ {\ctxlua{commands.doifsavedfloatelse("#1")}}
+
+\def\dofloatscollect#1#2#3%
+ {\ctxlua{floats.collect("#1",\number\dimexpr#2,\number\dimexpr#3)}}
+
+\def\dofloatsnofstacked#1%
+ {\ctxlua{floats.thestacked("#1")}}
+
+\def\dofloatsgetvariable#1%
+ {\ctxlua{floats.thevar("specification")}}
+
+\let\dopushcolumnfloats\dopushsavedfloats
+\let\dopopcolumnfloats \dopopsavedfloats
+
+\def\dofloatssavepagefloat#1#2%
+ {\ctxlua{floats.save("#1", { specification = "#2" })}}
+
+%D The following code is in transition as we don't want to break the
+%D current single column, multi column, and columnset mechanism.
+%D
+%D First we reimplement some helpers.
+
+\def\dogetfloat
+ {\ifsomefloatwaiting
+ \dofloatsflush{text}{1}%
+ \ifcenterfloatbox
+ \ifdim\wd\globalscratchbox<\hsize
+ \global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}%
+ \else
+ % retain special alignments
+ \ifinsidecolumns
+ \ifdim\wd\floatbox>\makeupwidth
+ \global\wd\floatbox\makeupwidth
+ \fi
+ \fi
+ \fi
+ \fi
+ \else
+ \global\savednoffloats\zerocount
+ \global\setbox\floatbox\emptybox
+ \fi}
+
+\def\dosavefloat
+ {\dofloatssave{text}%
+ \nonoindentation} % brrr nonoindentation here
+
+\def\doresavefloat
+ {\dofloatsresave{text}}
+
+\def\doreversesavefloat
+ {\dofloatsresave{text}}
+
+\def\doflushsavedfloats % simplified \OTRONEdodoflushfloats
+ {\doloop
+ {\ifsomefloatwaiting
+ \docheckiffloatfits
+ \ifroomforfloat
+ \dogetfloat
+ \doplacefloatbox
+ \else
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}}
+
+%D Page floats use different stacks.
+
+\newtoks \everybeforeflushedpagefloat
+
+\def\doflushsomepagefloat#1% future releases can do more clever things
+ {\dofloatsflush{#1}{1}%
+ \edef\floatspecification{\dofloatsgetvariable{specification}}%
+ \the\everybeforeflushedpagefloat
+ \vbox to \textheight
+ {\doifnotinset\v!high\floatspecification\vfill
+ \box\floatbox
+ \doifnotinset\v!low\floatspecification\vfill}%
+ \vfill\eject}
+
+% \def\doflushpagefloats
+% {\doifoddpageelse
+% {\ifnum\dofloatsnofstacked{rightpage}>\zerocount
+% \doflushsomepagefloat{rightpage}%
+% \else\ifnum\dofloatsnofstacked{page}>\zerocount
+% \doflushsomepagefloat{page}
+% \else\ifnum\dofloatsnofstacked{leftpage}>\zerocount
+% \null\vfill\eject
+% %\doflushsomepagefloat{leftpage}%
+% \fi\fi\fi}
+% {\ifnum\dofloatsnofstacked{leftpage}>\zerocount
+% \doflushsomepagefloat{leftpage}%
+% \else\ifnum\dofloatsnofstacked{page}>\zerocount
+% \doflushsomepagefloat{page}
+% \else\ifnum\dofloatsnofstacked{rightpage}>\zerocount
+% \null\vfill\eject
+% %\doflushsomepagefloat{rightpage}%
+% \fi\fi\fi}}
+
+\def\doflushpagefloats
+ {\edef\checkedpagefloat{\ctxlua{floats.thecheckedpagefloat()}}% (true) for packed
+ \ifx\checkedpagefloat\empty
+ % nothing
+ \else\ifx\checkedpagefloat\v!empty
+ \null\vfill\eject
+ \else
+ \doflushsomepagefloat\checkedpagefloat
+ \fi\fi}
+
+\def\uncenteredfloatbox
+ {\ifcenterfloatbox
+ \ifhbox\floatbox\relax % remove centering
+ \ifdim\wd\floatbox=\hsize
+ \ifhbox\floatbox
+ \setbox\scratchbox\hbox
+ {\unhbox\floatbox
+ \unskip\unskip
+ \global\setbox\globalscratchbox\lastbox}%
+ \box\globalscratchbox
+ \else
+ \box\floatbox
+ \fi
+ \else
+ \box\floatbox
+ \fi
+ \else
+ \box\floatbox
+ \fi
+ \else
+ \box\floatbox
+ \fi}
+
+\ifdefined\doflushfloats\else \let\doflushfloats\relax \fi
+\ifdefined\flushfloatbox\else \let\flushfloatbox\relax \fi
+
+\protect \endinput
diff --git a/tex/context/base/page-flw.mkii b/tex/context/base/page-flw.mkii
new file mode 100644
index 000000000..3eb867a78
--- /dev/null
+++ b/tex/context/base/page-flw.mkii
@@ -0,0 +1,107 @@
+%D \module
+%D [ file=page-flw,
+%D version=2003.04.19, % from test-002 (1997) profile experiment
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Text Flows,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA ADE]
+%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 Page Macros / Text Flows}
+
+%D This is high experimental and especially flushing may change (proper
+%D spacing is the driving force here).
+
+\unprotect
+
+\def\definetextflow
+ {\dodoubleempty\dodefinetextflow}
+
+\def\dodefinetextflow[#1][#2]% flow settings
+ {\iffirstargument
+ \doiftextflowcollectorelse{#1}
+ {\setbox\textflowcollector{#1}\emptybox}
+ {\@EA\newbox\csname\??tx:c:#1\endcsname}%
+ \getparameters[\??tx:p:#1]
+ [\c!width=\hsize,\c!style=,#2]%
+ \fi}
+
+\def\textflowparameter#1#2{\csname\??tx:p:#1#2\endcsname}
+\def\textflowcollector #1{\csname\??tx:c:#1\endcsname}
+
+\def\doiftextflowcollectorelse#1{\doifdefinedelse{\??tx:c:#1}}
+
+\def\doiftextflowelse#1%
+ {\doiftextflowcollectorelse{#1}
+ {\ifvoid\textflowcollector{#1}%
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+ {\secondoftwoarguments}}
+
+\def\doiftextflow#1%
+ {\doiftextflowelse{#1}\firstofoneargument\gobbleoneargument}
+
+\def\starttextflow[#1]%
+ {\doiftextflowcollectorelse{#1}
+ {\global\setbox\textflowcollector{#1}\vbox
+ \bgroup
+ \unvbox\textflowcollector{#1}%
+ \hsize\textflowparameter{#1}\c!width
+ \doifsomething{\textflowparameter{#1}\c!style}%
+ {\doconvertfont{\textflowparameter{#1}\c!style}}%
+ \def\stoptextflow{\endgraf\egroup}}
+ {\let\stoptextflow\relax}}
+
+\def\flushtextflow#1%
+ {\doiftextflow{#1}
+ {\ifdim\ht\textflowcollector{#1}>\vsize
+ \setbox\scratchbox\vsplit\textflowcollector{#1} to \vsize
+ \unvbox\scratchbox
+ \else
+ \unvbox\textflowcollector{#1}%
+ \fi}}
+
+\protect \endinput
+
+% Example (dutch)
+%
+% \stelpapierformaatin [S6]
+% \steltolerantiein [soepel,rek]
+% \stelkleurenin [status=start]
+% \stelvoetin [strut=nee]
+% \stelwitruimtein [groot]
+%
+% \stellayoutin
+% [rechterrand=5cm,breedte=passend,marge=0pt,randafstand=1cm,
+% voet=4cm,voetafstand=1cm,hoofd=0cm]
+%
+% \stelteksttekstenin[rand][][\vbox{\flushtextflow{alpha}}]
+% \stelvoettekstenin [rand][][\vbox{\flushtextflow{beta}}]
+% \stelvoettekstenin [\vbox{\flushtextflow{gamma}}][]
+%
+% \definetextflow [alfa] [breedte=\rechterrandbreedte]
+% \definetextflow [beta] [breedte=\rechterrandbreedte]
+% \definetextflow [gamma] [breedte=\voethoogte]
+%
+% \starttekst
+%
+% \dorecurse{50}
+% {\getrandomnumber{\funny}{0}{8}
+% \ifcase\funny \starttextflow[alfa] \input tufte.tex \stoptextflow
+% \or \starttextflow[beta] \input knuth.tex \stoptextflow
+% \or \starttextflow[gamma] \input materie.tex \stoptextflow
+% \or {\bf TUFTE}\quad \input tufte \par
+% \or {\bf TUFTE}\quad \input tufte \par
+% \or {\bf KNUTH}\quad \input knuth \par
+% \or {\bf KNUTH}\quad \input knuth \par
+% \or {\bf MATERIE}\quad \input materie \par
+% \else {\bf MATERIE}\quad \input materie \par
+% \fi}
+%
+% \stoptekst
diff --git a/tex/context/base/page-flw.mkiv b/tex/context/base/page-flw.mkiv
new file mode 100644
index 000000000..81b4fedcb
--- /dev/null
+++ b/tex/context/base/page-flw.mkiv
@@ -0,0 +1,107 @@
+%D \module
+%D [ file=page-flw,
+%D version=2003.04.19, % from test-002 (1997) profile experiment
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Text Flows,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA ADE]
+%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 Page Macros / Text Flows}
+
+%D This is high experimental and especially flushing may change (proper
+%D spacing is the driving force here).
+
+\unprotect
+
+\unexpanded\def\definetextflow
+ {\dodoubleempty\dodefinetextflow}
+
+\def\dodefinetextflow[#1][#2]% flow settings
+ {\iffirstargument
+ \doiftextflowcollectorelse{#1}
+ {\setbox\textflowcollector{#1}\emptybox}
+ {\@EA\newbox\csname\??tx:c:#1\endcsname}%
+ \getparameters[\??tx:p:#1]
+ [\c!width=\hsize,\c!style=,#2]%
+ \fi}
+
+\def\textflowparameter#1#2{\csname\??tx:p:#1#2\endcsname}
+\def\textflowcollector #1{\csname\??tx:c:#1\endcsname}
+
+\def\doiftextflowcollectorelse#1{\doifdefinedelse{\??tx:c:#1}}
+
+\def\doiftextflowelse#1%
+ {\doiftextflowcollectorelse{#1}
+ {\ifvoid\textflowcollector{#1}%
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+ {\secondoftwoarguments}}
+
+\def\doiftextflow#1%
+ {\doiftextflowelse{#1}\firstofoneargument\gobbleoneargument}
+
+\unexpanded\def\starttextflow[#1]%
+ {\doiftextflowcollectorelse{#1}
+ {\global\setbox\textflowcollector{#1}\vbox
+ \bgroup
+ \unvbox\textflowcollector{#1}%
+ \hsize\textflowparameter{#1}\c!width
+ \doifsomething{\textflowparameter{#1}\c!style}%
+ {\doconvertfont{\textflowparameter{#1}\c!style}}%
+ \unexpanded\def\stoptextflow{\endgraf\egroup}}
+ {\let\stoptextflow\relax}}
+
+\def\flushtextflow#1%
+ {\doiftextflow{#1}
+ {\ifdim\ht\textflowcollector{#1}>\vsize
+ \setbox\scratchbox\vsplit\textflowcollector{#1} to \vsize
+ \unvbox\scratchbox
+ \else
+ \unvbox\textflowcollector{#1}%
+ \fi}}
+
+\protect \endinput
+
+% Example (dutch)
+%
+% \stelpapierformaatin [S6]
+% \steltolerantiein [soepel,rek]
+% \stelkleurenin [status=start]
+% \stelvoetin [strut=nee]
+% \stelwitruimtein [groot]
+%
+% \stellayoutin
+% [rechterrand=5cm,breedte=passend,marge=0pt,randafstand=1cm,
+% voet=4cm,voetafstand=1cm,hoofd=0cm]
+%
+% \stelteksttekstenin[rand][][\vbox{\flushtextflow{alpha}}]
+% \stelvoettekstenin [rand][][\vbox{\flushtextflow{beta}}]
+% \stelvoettekstenin [\vbox{\flushtextflow{gamma}}][]
+%
+% \definetextflow [alfa] [breedte=\rechterrandbreedte]
+% \definetextflow [beta] [breedte=\rechterrandbreedte]
+% \definetextflow [gamma] [breedte=\voethoogte]
+%
+% \starttekst
+%
+% \dorecurse{50}
+% {\getrandomnumber{\funny}{0}{8}
+% \ifcase\funny \starttextflow[alfa] \input tufte.tex \stoptextflow
+% \or \starttextflow[beta] \input knuth.tex \stoptextflow
+% \or \starttextflow[gamma] \input materie.tex \stoptextflow
+% \or {\bf TUFTE}\quad \input tufte \par
+% \or {\bf TUFTE}\quad \input tufte \par
+% \or {\bf KNUTH}\quad \input knuth \par
+% \or {\bf KNUTH}\quad \input knuth \par
+% \or {\bf MATERIE}\quad \input materie \par
+% \else {\bf MATERIE}\quad \input materie \par
+% \fi}
+%
+% \stoptekst
diff --git a/tex/context/base/page-imp.mkii b/tex/context/base/page-imp.mkii
new file mode 100644
index 000000000..e4ece04a6
--- /dev/null
+++ b/tex/context/base/page-imp.mkii
@@ -0,0 +1,1314 @@
+%D \module
+%D [ file=page-imp, % was: core-pag,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Pagebody Building (Imposition),
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% much of this can more to run time loading !
+
+\writestatus{loading}{ConTeXt Page Macros / Pagebody Building}
+
+\unprotect
+
+% sizing bug:
+%
+% \setuppapersize[A4][A4,landscape] \setuparranging[2UP] \showframe
+%
+% \starttext \dorecurse{10}{\input tufte \par} \stoptext
+
+% to be moved code:
+
+\newif\ifclipprintbox \clipprintboxtrue
+%newif\ifclippagebox \clippageboxtrue
+
+\def\clippedprintbox#1#2% can be made more efficient, see other clipper
+ {\ifclipprintbox
+ \!!widthc \pagebackgroundoffset
+ \!!widtha \dimexpr\paperwidth + \!!widthc\relax
+ \!!heighta\dimexpr\paperheight+2\!!widthc\relax
+ \setbox#2\vbox to \paperheight{\vfill\box#2}%
+ \ht#2\paperheight
+ \wd#2\paperwidth
+ \setbox#2\vbox
+ {\framed
+ [\c!offset=\!!widthc,\c!strut=\v!no,\c!frame=\v!off]
+ {\box#2}}%
+ \setbox#2\hbox to \paperwidth
+ {\ifcase#1\relax
+ \!!widthb\zeropoint
+ \hskip-\!!widthc
+ \else
+ \!!widthb\!!widthc
+ \fi
+ \lower\!!widthc\hbox
+ {\clip
+ [\c!width=\!!widtha,\c!height=\!!heighta,
+ \c!hoffset=\!!widthb,\c!voffset=\zeropoint]
+ {\box#2}}}%
+ \wd#2\paperwidth
+ \ht#2\paperheight
+ \fi
+ \box#2\relax}
+
+\let\clippagebox \gobbleoneargument
+\let\clipprintbox\gobbleoneargument
+
+% \setuppagenumbering[alternative=doublesided]
+% \setupcolors[state=start]
+% \setuppapersize[A4][A4,oversized]
+% \setuplayout[location=middle,clipoffset=5mm]
+% \setupbackgrounds
+% [page]
+% [frame=on,rulethickness=1mm,
+% backgroundoffset=10mm,background=color,backgroundcolor=red]
+% \starttext \dorecurse{10}{\input tufte \par} \stoptext
+
+\def\clippagebox#1%
+ {\ifdim\@@lyclipoffset>\zeropoint
+ \!!widtha \wd#1%
+ \!!heighta\ht#1%
+ \!!deptha \dp#1%
+ \setbox#1\hbox
+ {\!!widthb \@@lyclipoffset
+ \advance\!!heighta\dimexpr\!!deptha+2\!!widthb\relax
+ \advance\!!widtha \!!widthb
+ \doifbothsides
+ {\advance\!!widtha\!!widthb \!!widthc-\!!widthb \hskip\!!widthc}%
+ {\!!widthc\zeropoint}
+ {\!!widthc-\!!widthb \hskip\!!widthc}%
+ \lower\!!widthb\hbox
+ {\clip
+ [\c!hoffset=\!!widthc,
+ \c!voffset=-\!!widthb,
+ \c!width=\!!widtha,
+ \c!height=\!!heighta]%
+ {\box#1}}}%
+ \wd#1\!!widtha
+ \ht#1\!!heighta
+ \dp#1\!!deptha
+ \fi}
+
+%D \macros
+%D {starttextdata}
+%D
+%D This is a user macro (appending to every last shipout is not
+%D really user friendly.
+
+\newtoks \collectedtextdata
+
+\long\def\starttextdata#1\stoptextdata
+ {\doglobal\appendtoks#1\to\collectedtextdata}
+
+\def\flushtextdata
+ {\vsmashed{\the\collectedtextdata}% all dimensions zero
+ \global\collectedtextdata\emptytoks
+ \globallet\flushtextdata\donothing}
+
+\prependtoks \flushtextdata \to \everylastshipout
+
+% moved code:
+
+% \def\myshipout#1%
+% {\beforeshipout % voor de pagebody dus !
+% \dontshowcomposition
+% \ifarrangingpages\@EA\actualarrange\else\@EA\actualshipout\fi
+% {\thisisrealpage\realfolio#1}%
+% \gotonextrealpage
+% \aftershipout}
+
+\def\installpagehandler#1#2% % a handler takes one argument: something to be boxed
+ {\setvalue{\??pp:\c!method:#1}{#2}} % and shipped out (don't depend on the exact package)
+
+\installpagehandler\v!normal
+ {\ifarrangingpages\expandafter\actualarrange\else\expandafter\actualshipout\fi}
+
+\def\myshipout#1%
+ {\beforeshipout % voor de pagebody dus !
+ \dontshowcomposition
+ \executeifdefined{\??pp:\c!method:\@@ppmethod}\gobbleoneargument{\thisisrealpage\realfolio#1}%
+ \gotonextrealpage
+ \aftershipout}
+
+\newbox\postponedcontent
+
+% \def\flushatshipout
+% {\dowithnextbox
+% {\global\setbox\postponedcontent\hbox to \zeropoint
+% {%\hskip-\maxdimen % niet hier, gaat mis in acrobat (clipt)
+% \box\postponedcontent\flushnextbox}%
+% \global\ht\postponedcontent\zeropoint
+% \global\dp\postponedcontent\zeropoint
+% \global\wd\postponedcontent\zeropoint}%
+% \hbox}
+
+\def\flushatshipout
+ {\dowithnextbox
+ {\global\setbox\postponedcontent\hbox to \zeropoint
+ {%\hskip-\maxdimen % niet hier, gaat mis in acrobat (clipt)
+ \unhbox\postponedcontent\unhbox\nextbox}%
+ \global\ht\postponedcontent\zeropoint
+ \global\dp\postponedcontent\zeropoint
+ \global\wd\postponedcontent\zeropoint}%
+ \hbox}
+
+% \starttypen
+% \def\pagestoshipout{1,3,5}
+% \stoptypen
+
+\newcount\shippedoutpages
+
+\let\pagestoshipout\empty % {1,3,6}
+\chardef\whichpagetoshipout=0 % 0=all 1=odd 2=even
+
+\ifx\finalizeshipoutbox\undefined \let\finalizeshipoutbox\firstofoneargument \fi
+
+\def\actualshipout#1%
+ {\global\advance\shippedoutpages\plusone
+ % this is not resource safe!
+ \ifx\pagestoshipout\empty
+ \ifcase\whichpagetoshipout\relax
+ \donetrue
+ \or % 1
+ \ifodd\shippedoutpages\relax\donetrue\else\donefalse\fi
+ \or % 2
+ \ifodd\shippedoutpages\relax\donefalse\else\donetrue\fi
+ \else
+ \donetrue
+ \fi
+ \else % testen, aangepast / expanded nodig ?
+ \expanded{\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}%
+ \donetrue\donefalse
+ \fi
+ \ifdone
+ \shipout\vbox
+ {\forgetall
+ \offinterlineskip
+ \dontcomplain
+ \scratchdimen-1in
+ \vskip\scratchdimen
+ \hskip\scratchdimen
+ \hbox % \setbox0=\box.. is nicer
+ {\setbox0\hbox{\finalizeshipoutbox{#1}}% just in case there are objects there, hook for testing
+ \setbox\scratchbox\hbox
+ {% before the main one !
+ \ifcase\realfolio \or
+ \the\everyfirstshipout
+ \global\everyfirstshipout\emptytoks
+ \fi
+ % the main one
+ \the\everyshipout\relax
+ % always last (and after the main one)
+ \ifnum\realpageno=\lastpage\relax
+ \the\everylastshipout
+ \global\everylastshipout\emptytoks
+ \fi}%
+ \smashbox\scratchbox
+ \box\scratchbox
+ \box\postponedcontent % evt ver naar links !
+ \box0}}%
+ \else
+ \message
+ {[\ifarrangingpages arranged \fi page
+ \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace
+ not flushed]}%
+ \setbox0\hbox{#1}%
+ \deadcycles\zerocount
+ \fi}
+
+\def\actualarrange#1%
+ {\setbox0\hbox{\thisisrealpage{\realfolio}#1}%
+ \pusharrangedpage0%
+ \deadcycles\zerocount}
+
+%D We need a couple of boxes for duplex printing \unknown
+
+\newbox\arrangedpageA \newbox\arrangedpageB
+
+%D \unknown\ and some for simulating big sheets.
+
+\newbox\arrangedpageC \newbox\arrangedpageD
+\newbox\arrangedpageE \newbox\arrangedpageF
+\newbox\arrangedpageG \newbox\arrangedpageH
+
+\newif\ifswaparranged
+\newif\ifnegatearranged
+\newif\ifmirrorarranged
+\newif\ifdoublearranged
+
+\newif\ifarrangingdisabled
+
+\def\arrangedrotationO{0}
+\def\arrangedrotationE{0}
+
+\newcounter\arrangedpageN
+\newcounter\arrangedpageM
+
+\chardef\arrangedpageT=1
+\chardef\arrangedpageX=1
+\chardef\arrangedpageY=1
+
+\def\calculatepaperoffsets#1%
+ {\scratchdimen\getvalue{\??pp#1\c!offset}%
+ \divide\scratchdimen \arrangedpageX
+ \global\advance\paperwidth -2\scratchdimen
+ \scratchdimen\getvalue{\??pp#1\c!offset}%
+ \divide\scratchdimen \arrangedpageY
+ \global\advance\paperheight-2\scratchdimen}
+
+\newconditional\arrangedbackgroundokay % more ifs -> conditionals
+
+\def\setuparranging[#1]%
+ {\ifarrangingdisabled \else
+ \doifelse{#1}\v!disable
+ {\global\arrangingdisabledtrue}
+ {\global\arrangingdisabledfalse}%
+ \global\arrangingpagestrue
+ \global\negatearrangedfalse
+ \global\mirrorarrangedfalse
+ \global\doublearrangedfalse
+ \gdef\arrangedrotationO{0}%
+ \gdef\arrangedrotationE{180}%
+ \processallactionsinset
+ [#1]
+ [ \v!mirrored=>\global\mirrorarrangedtrue,
+ \v!doublesided=>\global\doublearrangedtrue,
+ \v!negative=>\global\negatearrangedtrue,
+ \v!rotated=>\gdef\arrangedrotationO {90}\gdef\arrangedrotationE{270},
+ 90=>\gdef\arrangedrotationO {90}\gdef\arrangedrotationE{270},
+ 180=>\gdef\arrangedrotationO{180}\gdef\arrangedrotationE{0},
+ 270=>\gdef\arrangedrotationO{270}\gdef\arrangedrotationE{90},
+ \s!reset=>\global\arrangingpagesfalse,
+ \v!background=>\global\settrue\arrangedbackgroundokay,
+ \s!unknown=>\checkinstalledpagearrangement\commalistelement]%
+ % no \s!default=> we can have aaa,,bbb
+ \ifx\handlearrangedpage\undefined
+ \global\arrangingpagesfalse
+ \fi
+ \doifcommonelse{#1}{90,270,\v!rotated}
+ {\swapmacros\horizontalcutmarks\verticalcutmarks}{}% ugly solution
+ \setuppapersize
+ \ifarrangingpages
+ \abortutilitygeneration
+ \fi
+ \fi}
+
+\def\installpagearrangement #1 %
+ {\setgvalue{\??pp\??pp#1}}
+
+\def\checkinstalledpagearrangement#1% can be empty: aaa,,bbb
+ {\executeifdefined{\??pp\??pp#1}\donothing}
+
+\def\dosetuparrangement#1#2#3#4#5#6#7#8%
+ {\global\chardef\arrangedpageX #1%
+ \global\chardef\arrangedpageY #2%
+ \global\chardef\arrangedpageT #3%
+ \global\chardef\horizontalcutmarks#4%
+ \global\chardef\verticalcutmarks #5%
+ \global\let \pusharrangedpage #6%
+ \global\let \poparrangedpages #7%
+ \global\let \handlearrangedpage#8}
+
+\installpagearrangement {\v!normal}
+ {\global\arrangingpagesfalse}
+
+\installpagearrangement 2*16
+ {\dosetuparrangement{4}{4}{16}{5}{5}%
+ \pusharrangedpageTHIRTYTWO\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*8
+ {\dosetuparrangement{4}{2}{8}{5}{3}%
+ \pusharrangedpageSIXTEEN\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*4
+ {\dosetuparrangement{2}{2}{4}{3}{3}%
+ \pusharrangedpageEIGHT\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*2
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageFOURA\poparrangedpagesAB\relax}
+
+\installpagearrangement 2**2
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageFOURB\poparrangedpagesAB\relax}
+
+\installpagearrangement 2SIDE
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageSIDETOP\poparrangedpagesTWO\handlearrangedpageSIDE}
+
+\installpagearrangement 2TOP
+ {\dosetuparrangement{1}{2}{2}{2}{3}%
+ \pusharrangedpageSIDETOP\poparrangedpagesTWO\handlearrangedpageTOP}
+
+\installpagearrangement 2UP
+ {\dosetuparrangement{2}{1}{4}{3}{2}%
+ \pusharrangedpageTWO\poparrangedpagesTWO\handlearrangedpageTWOUP}
+
+\installpagearrangement 2DOWN
+ {\dosetuparrangement{1}{2}{4}{2}{3}%
+ \pusharrangedpageTWO\poparrangedpagesTWO\handlearrangedpageTWODOWN}
+
+\installpagearrangement 2*4*2 % one defined by Willy Egger:
+ {\dosetuparrangement{2}{2}{4}{3}{2}%
+ \pusharrangedpageSIXTEENTWO\poparrangedpagesAtoD\relax}
+
+\installpagearrangement 2*2*4 % onother one of Willy Egger
+ {\dosetuparrangement{2}{1}{8}{3}{2}%
+ \pusharrangedpageSIXTEENFOUR\poparrangedpagesAtoH\relax}
+
+\installpagearrangement 2TOPSIDE
+ {\dosetuparrangement{1}{2}{4}{2}{3}%
+ \pusharrangedpageTWOTOPSIDE\poparrangedpagesTWOTOPSIDE\handlearrangedpageTOP}
+
+% \def\filluparrangedpages % beware: \realpageno is 1 ahead
+% {\ifarrangingpages
+% \scratchcounter-\realpageno
+% \divide\scratchcounter \arrangedpageT
+% \multiply\scratchcounter \arrangedpageT
+% \advance\scratchcounter \realpageno
+% \advance\scratchcounter \minusone
+% \dorecurse\scratchcounter{\noheaderandfooterlines\ejectdummypage}%
+% \fi}
+
+\def\filluparrangedpages % beware: \realpageno is 1 ahead
+ {\ifarrangingpages
+ \scratchcounter\numexpr\realpageno-\plusone\relax
+ \dosetmodulo\scratchcounter\arrangedpageT\scratchcounter
+ \ifcase\scratchcounter\else
+ \advance\scratchcounter \plusone
+ \dostepwiserecurse\scratchcounter\arrangedpageT\plusone
+ {\noheaderandfooterlines\ejectdummypage}%
+ \fi
+ \fi}
+
+\def\handlearrangedpageXandY#1#2#3#4#5%
+ {\global\setbox#5\hbox to \arrangedpageX\paperwidth
+ {\setbox\scratchbox\vbox to \arrangedpageY\paperheight
+ {\forgetall
+ \offinterlineskip
+ \dontcomplain
+ \vskip#4\paperheight
+ \hskip#3\paperwidth
+ \dorotatebox{\ifcase#2 0\else180\fi}\hbox{\box#1}%
+ \vfill}%
+ \wd\scratchbox\zeropoint
+ \box\scratchbox\box#5\hss}}
+
+\def\gotonextarrangepage
+ {\global\advance\arrangeno \plusone
+ \def\pagecutmarksymbol{\the\arrangeno}}
+
+\def\outputarrangedbox#1%
+ {\bgroup
+ \gotonextarrangepage
+ \ifnum\arrangedrotationO\arrangedrotationE>\zerocount
+ \setbox#1\vbox
+ {\ifdoublearranged
+ \ifodd\arrangeno
+ \dorotatebox\arrangedrotationO\hbox{\box#1}%
+ \else
+ \dorotatebox\arrangedrotationE\hbox{\box#1}%
+ \fi
+ \else
+ \dorotatebox\arrangedrotationO\hbox{\box#1}%
+ \fi}%
+ \fi
+ \ifmirrorarranged
+ \setbox#1\vbox{\domirrorbox\vbox{\box#1}}%
+ \fi
+ \ifnegatearranged
+ \negatecolorbox{#1}%
+ \fi
+ \finishpagebox#1%
+ \ifconditional\arrangedbackgroundokay\addprintbackground#1\fi
+ \actualshipout{\box#1}%
+ \egroup}
+
+%D The format file can be 16K smaller when we postpone the
+%D real arrangments. Some day ...
+
+% TOP
+
+% 32/16/8/4/SIDE
+
+\def\poparrangedpagesAB
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+\def\pusharrangedpageTHIRTYTWO#1% taco's challenge
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}033\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}003\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}130\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}130\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}033\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}003\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}102\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}132\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}031\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 12
+ \or \handlearrangedpageXandY{#1}031\arrangedpageA % 13
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 14
+ \or \handlearrangedpageXandY{#1}102\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}132\arrangedpageA % 16
+ \or \handlearrangedpageXandY{#1}122\arrangedpageA % 17
+ \or \handlearrangedpageXandY{#1}112\arrangedpageB % 18
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 19
+ \or \handlearrangedpageXandY{#1}021\arrangedpageA % 20
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 21
+ \or \handlearrangedpageXandY{#1}021\arrangedpageB % 22
+ \or \handlearrangedpageXandY{#1}122\arrangedpageB % 23
+ \or \handlearrangedpageXandY{#1}112\arrangedpageA % 24
+ \or \handlearrangedpageXandY{#1}013\arrangedpageA % 25
+ \or \handlearrangedpageXandY{#1}023\arrangedpageB % 26
+ \or \handlearrangedpageXandY{#1}120\arrangedpageB % 27
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 28
+ \or \handlearrangedpageXandY{#1}120\arrangedpageA % 29
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 30
+ \or \handlearrangedpageXandY{#1}013\arrangedpageB % 31
+ \or \handlearrangedpageXandY{#1}023\arrangedpageA % 32
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageSIXTEEN#1% changed to match the official way of doing
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}031\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}031\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}130\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}130\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}120\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}120\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 12
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 13
+ \or \handlearrangedpageXandY{#1}021\arrangedpageB % 14
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}021\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageEIGHT#1% changed to match the official way of doing
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 8
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageFOURA{\pusharrangedpageFOURdo01}
+\def\pusharrangedpageFOURB{\pusharrangedpageFOURdo10}
+
+\def\pusharrangedpageFOURdo#1#2#3%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#3}010\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#3}0{#1}0\arrangedpageB % 2/3 not {1}
+ \or \handlearrangedpageXandY{#3}0{#2}0\arrangedpageB % 3/2 not {1}
+ \or \handlearrangedpageXandY{#3}000\arrangedpageA % 4
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageSIDETOP#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \poparrangedpages
+ \fi}
+
+\def\handlearrangedpageSIDE
+ {\global\wd\arrangedpageA\paperwidth
+ \global\wd\arrangedpageB\paperwidth
+ \global\setbox\arrangedpageA\hbox
+ {\box\arrangedpageA\box\arrangedpageB}%
+ \global\ht\arrangedpageA\paperheight}
+
+\def\handlearrangedpageTOP
+ {\global\ht\arrangedpageA\paperheight
+ \global\ht\arrangedpageB\paperheight
+ \global\setbox\arrangedpageA\vbox
+ {\forgetall\offinterlineskip\vskip\paperheight
+ \box\arrangedpageA\box\arrangedpageB}%
+ \global\setbox\arrangedpageB\box\scratchbox} % ?
+
+% 2UP/2DOWN / 1pt prevents overflow
+
+\def\splitoffarrangedpagesTWO
+ {\splittopskip\zeropoint
+ \global\setbox\arrangedpageA\vsplit\arrangedpageB to \onepoint
+ \scratchdimen\dimexpr\ht\arrangedpageB-\onepoint\relax
+ \ifdim\scratchdimen>\onepoint
+ \setbox\scratchbox\vsplit\arrangedpageB to \scratchdimen
+ \fi}
+
+\def\handlearrangedpageTWOUP
+ {\splitoffarrangedpagesTWO
+ \ifswaparranged
+ \global\setbox\arrangedpageA\hbox
+ {\clippedprintbox0\arrangedpageA
+ \clippedprintbox1\arrangedpageB}%
+ \swaparrangedfalse
+ \else
+ \global\setbox\arrangedpageA\hbox
+ {\clippedprintbox0\arrangedpageB
+ \clippedprintbox1\arrangedpageA}%
+ \swaparrangedtrue
+ \fi
+ \global\ht\arrangedpageA\paperheight
+ \global\setbox\arrangedpageB\box\scratchbox}
+
+\def\handlearrangedpageTWODOWN
+ {\splitoffarrangedpagesTWO
+ \global\ht\arrangedpageA\paperheight
+ \global\ht\arrangedpageB\paperheight
+ \ifswaparranged
+ \global\setbox\arrangedpageA\vbox
+ {\forgetall\offinterlineskip\vskip\paperheight
+ \box\arrangedpageA\box\arrangedpageB}%
+ \swaparrangedfalse
+ \else
+ \global\setbox\arrangedpageA\vbox
+ {\forgetall\offinterlineskip\vskip\paperheight
+ \box\arrangedpageB\box\arrangedpageA}%
+ \swaparrangedtrue
+ \fi
+ \global\setbox\arrangedpageB\box\scratchbox}
+
+\def\poparrangedpagesTWO
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \swaparrangedfalse
+ \doloop
+ {\handlearrangedpage
+ \bgroup
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \ht\arrangedpageA\paperheight
+ \wd\arrangedpageA\paperwidth
+ \outputarrangedbox\arrangedpageA
+ \egroup
+ \ifdim\ht\arrangedpageB=\zeropoint
+ \exitloop
+ \fi}%
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+\def\pusharrangedpageTWO#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \global\setbox\arrangedpageB\vbox
+ {\forgetall
+ \offinterlineskip
+ \unvbox\arrangedpageB
+ \allowbreak
+ \ht#1\onepoint
+ \dp#1\zeropoint
+ \vbox{\box#1}}}
+
+\def\poparrangedpagesTWOTOPSIDE
+ {\ifnum\arrangedpageN>\zerocount
+ \bgroup
+ \gdef\arrangedpageN{2}\poparrangedpagesTWO
+ \let\arrangedpageA\arrangedpageC
+ \let\arrangedpageB\arrangedpageD
+ \gdef\arrangedpageN{2}\poparrangedpagesTWO
+ \doglobal\newcounter\arrangedpageN
+ \egroup
+ \fi}
+
+\def\pusharrangedpageTWOTOPSIDE#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 2
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 2
+ \poparrangedpages
+ \fi}
+
+%D Willy Egger's sheet simulations:
+
+\def\poparrangedpagesAtoH
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \outputarrangedbox\arrangedpageC
+ \outputarrangedbox\arrangedpageD
+ \outputarrangedbox\arrangedpageE
+ \outputarrangedbox\arrangedpageF
+ \outputarrangedbox\arrangedpageG
+ \outputarrangedbox\arrangedpageH
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+% to arrange 16 pages on 2 sheets to form one booklet
+
+\def\poparrangedpagesAtoD
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \outputarrangedbox\arrangedpageC
+ \outputarrangedbox\arrangedpageD
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+% to arrange 16 pages on 4 sheets to form one booklet
+
+\def\pusharrangedpageSIXTEENFOUR#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}010\arrangedpageE % 5
+ \or \handlearrangedpageXandY{#1}000\arrangedpageF % 6
+ \or \handlearrangedpageXandY{#1}010\arrangedpageG % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageH % 8
+ \or \handlearrangedpageXandY{#1}010\arrangedpageH % 9
+ \or \handlearrangedpageXandY{#1}000\arrangedpageG % 10
+ \or \handlearrangedpageXandY{#1}010\arrangedpageF % 11
+ \or \handlearrangedpageXandY{#1}000\arrangedpageE % 12
+ \or \handlearrangedpageXandY{#1}010\arrangedpageD % 13
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 14
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+% to arrange 16 pages on 2 sheets to form one booklet
+
+\def\pusharrangedpageSIXTEENTWO#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}011\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}001\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageD % 5
+ \or \handlearrangedpageXandY{#1}110\arrangedpageC % 6
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}100\arrangedpageC % 11
+ \or \handlearrangedpageXandY{#1}110\arrangedpageD % 12
+ \or \handlearrangedpageXandY{#1}011\arrangedpageD % 13
+ \or \handlearrangedpageXandY{#1}001\arrangedpageC % 14
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+% % handy for stickers etc, this way we can treat them as page
+%
+% \setuppapersize [XY][A4]
+% \setuppaper [topspace=5mm,backspace=5mm,dx=1mm,dy=1mm,nx=2,ny=6]
+% \setuplayout [page] [topspace=5mm,backspace=5mm]
+% \setuplayout [page]
+% \setuplayout [location=middle]
+% \setuparranging [XY]
+% \showframe
+%
+% \starttext \dorecurse{30}{test \recurselevel \page} \stoptext
+
+\def\pusharrangedpageXY#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \doglobal\increment\arrangedpageM
+ \global\setbox\arrangedpageB\hbox
+ \ifdim\@@ppwidth>\zeropoint to \@@ppwidth \fi
+ {\ifvoid\arrangedpageB\else
+ \unhbox\arrangedpageB
+ \ifdim\@@ppdx>\zeropoint \else \hss\fi
+ \hskip\@@ppdx
+ \ifdim\@@ppdx>\zeropoint \else \hss\fi
+ \fi
+ \box#1}%
+ \ifnum\arrangedpageM<\arrangedpageX\else
+ \global\setbox\arrangedpageA\vbox
+ \ifdim\@@ppheight>\zeropoint to \@@ppheight \fi
+ {\offinterlineskip
+ \ifvoid\arrangedpageA\else
+ \unvbox\arrangedpageA
+ \ifdim\@@ppdy>\zeropoint \else \vss\fi
+ \vskip\@@ppdy
+ \ifdim\@@ppdy>\zeropoint \else \vss\fi
+ \fi
+ \box\arrangedpageB}%
+ \doglobal\newcounter\arrangedpageM
+ \fi
+ \ifnum\arrangedpageN<\arrangedpageT\else
+ \poparrangedpages
+ \fi}
+
+\def\poparrangedpagesXY
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight \arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \doglobal\newcounter\arrangedpageN
+ \doglobal\newcounter\arrangedpageM
+ \fi}
+
+\installpagearrangement XY
+ {\dosetuparrangement\@@ppnx\@@ppny\@@ppxy\!!zerocount\!!zerocount
+ \pusharrangedpageXY\poparrangedpagesXY\relax}
+
+%D A crazy definition, don't guess who pushed me for the landscape option.
+
+\definepapersize
+ [XY]
+ [\c!height=\dimexpr\dimexpr\@@ppheight-\numexpr\@@ppny-1\relax\dimexpr\@@ppdy\relax\relax/\@@ppny\relax,
+ \c!width =\dimexpr\dimexpr\@@ppwidth -\numexpr\@@ppnx-1\relax\dimexpr\@@ppdx\relax\relax/\@@ppnx\relax]
+
+\setuppaper
+ [\c!width =\dimexpr\printpaperwidth -2\dimexpr\@@ppbackspace\relax\relax,
+ \c!height=\dimexpr\printpaperheight-2\dimexpr\@@pptopspace \relax\relax]
+
+% \definepageshift[test][horizontal][10pt,20pt,30pt,40pt,50pt]
+% \definepageshift[test][vertical] [10pt,20pt,30pt,40pt,50pt]
+%
+% \setuppageshift[test]
+% \setuppageshift[test][test]
+% \setuppageshift[test][none]
+% \setuppageshift[none][test]
+% \setuppageshift[paper][test][test] % arrange only
+% \setuppageshift[paper][test] % arrange only
+% \setuppageshift[print][test][test]
+%
+% \showframe \dorecurse{100}{\input tufte \par}
+
+% #1=name #2=horizontal|vertical #3=shiftlist
+
+\def\definepageshift
+ {\dotripleargument\dodefinepageshift}
+
+\def\dodefinepageshift[#1][#2][#3]%
+ {\setvalue{\??pt#2:#1}{#3}}
+
+\letempty \hpageshifts \newcounter\nofhpageshifts
+\letempty \vpageshifts \newcounter\nofvpageshifts
+
+% \let\shiftprintpagebox\gobbleoneargument
+% \let\shiftpaperpagebox\gobbleoneargument
+
+\def\dogetpageshift#1#2#3% #1=\dimenx #2=\xpageshifts #3=\nofxpageshifts
+ {\ifx#2\empty
+ #1\zeropoint
+ \else
+ \doglobal\increment#3%
+ \getfromcommacommand[#2][#3]%
+ \ifx\commalistelement\empty
+ \globallet#3\!!plusone
+ \getfromcommacommand[#2][#3]%
+ \fi
+ \ifx\commalistelement\empty
+ #1\zeropoint
+ \else
+ #1=\commalistelement
+ \donetrue
+ \fi
+ \fi}
+
+\def\shiftpagebox#1%
+ {\donefalse
+ \dogetpageshift{\dimen0}\hpageshifts\nofhpageshifts
+ \dogetpageshift{\dimen2}\vpageshifts\nofvpageshifts
+ \ifdone % see also layout offsets, maybe \movebox
+ \edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
+ \setbox#1\vbox % \forgetall already done
+ {\offinterlineskip\vskip\dimen2\hskip\dimen0\box#1}%
+ \next
+ \fi}
+
+\def\setuppageshift
+ {\dotripleempty\dosetuppageshift}
+
+\def\dosetuppageshift[#1][#2][#3]% page|paper horizontal vertical
+ {\ifthirdargument % paper=arrange
+ \let\hpageshifts\empty
+ \let\vpageshifts\empty
+ \let\shiftprintpagebox\gobbleoneargument
+ \let\shiftpaperpagebox\gobbleoneargument
+ \doifdefined{\??pt\v!horizontal:#2}
+ {\edef\hpageshifts{\getvalue{\??pt\v!horizontal:#2}}}%
+ \doifdefined{\??pt\v!vertical :#3}
+ {\edef\vpageshifts{\getvalue{\??pt\v!vertical :#3}}}%
+ \doif{#1}\v!page{\let\shiftprintpagebox\shiftpagebox}%
+ \doif{#1}\v!paper{\let\shiftpaperpagebox\shiftpagebox}%
+ \else\ifsecondargument
+ \doifinsetelse{#1}{\v!page,\v!paper}
+ {\setuppageshift[#1][#2][#2]}
+ {\setuppageshift[\v!page][#1][#2]}%
+ \else\iffirstargument
+ \setuppageshift[\v!page][#1][#1]%
+ \fi\fi\fi}
+
+%D One can (mis)use this mechanism, in close cooperation
+%D with \PDFTEX\ to arrange pages of already produced files.
+%D
+%D \starttyping
+%D \insertpages[file.pdf][1,3][n=30,width=18cm]
+%D \stoptyping
+%D
+%D The pages are inserted in the text area, and even pages
+%D are repositioned according to the width. In this example
+%D empty pages are added after page 1 and 3.
+%D
+%D Selecting pages can be accomplished by:
+%D
+%D \starttyping
+%D \filterpages[file.pdf][1,3,5][n=30,width=18cm]
+%D \stoptyping
+%D
+%D One may pass \type {odd} or \type {even} instead of a
+%D comma separated list. A third alternative is:
+%D
+%D \starttyping
+%D \copypages[file.pdf][n=30,scale=950]
+%D \stoptyping
+%D
+%D This macros inserts the page, according to the settings
+%D provided.
+
+\def\insertpages
+ {\dotripleempty\doinsertpages}
+
+\def\doinsertpages[#1][#2][#3]%
+ {\doifassignmentelse{#2}
+ {\dodoinsertpages[#1][][#2]}
+ {\dodoinsertpages[#1][#2][#3]}}
+
+\def\dodoinsertpages[#1][#2][#3]%
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#1]%
+ \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]%
+ \doifinset0{#2}{\null\page}%
+ \dorecurse\@@ipn
+ {\dofilterpage{#1}\recurselevel
+ \doifinset\recurselevel{#2}{\null\page}}%
+ \egroup}
+
+\def\filterpages
+ {\dotripleempty\dofilterpages}
+
+\def\dofilterpages[#1][#2][#3]% % \noffigurepages not yet supported
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#1]%
+ \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]%
+ \doifelse{#2}\v!even
+ {\dorecurse\@@ipn
+ {\ifodd\recurselevel\relax\else\dofilterpage{#1}\recurselevel\fi}}
+ {\doifelse{#2}\v!odd
+ {\dorecurse\@@ipn
+ {\ifodd\recurselevel\relax\dofilterpage{#1}\recurselevel\fi}}
+ {\def\dodocommand##1%
+ {\ifnum##1>\@@ipn\else\dofilterpage{#1}{##1}\fi}%
+ \def\docommand##1%
+ {\dowithrange{##1}\dodocommand}%
+ \processcommalist[#2]\docommand}}%
+ \egroup}
+
+\def\dofilterpage#1#2%
+ {\hbox to \textwidth
+ {\ifdoublesided\ifdim\@@ipwidth>\zeropoint\relax\ifodd\realpageno\else
+ \hfill
+ \def\dowithfigure{\hskip-\@@ipwidth}%
+ \fi\fi\fi
+ \setbox0\hbox
+ {\externalfigure[#1][\c!page=#2,\c!height=\textheight]}%
+ \wd0\zeropoint
+ \box0}
+ \page}
+
+\def\copypages
+ {\dodoubleempty\docopypages}
+
+\def\docopypages[#1][#2]%
+ {\bgroup
+ \getfiguredimensions[#1]%
+ \getparameters[\??ip]
+ [\c!n=\noffigurepages,
+ \c!marking=\v!off,
+ \c!scale=\!!thousand,
+ \c!offset=\!!zeropoint,
+ #2]%
+ \dorecurse\@@ipn
+ {\vbox to \textheight
+ {\hsize\textwidth
+ \scratchdimen\@@ipoffset
+ \centeredbox
+ {\doifelse\@@ipmarking\v!on\cuthbox\hbox
+ {\ifdim\scratchdimen>\zeropoint\relax
+ \advance\vsize -2\scratchdimen
+ \advance\hsize -2\scratchdimen
+ \externalfigure[#1][\c!page=\recurselevel,#2,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]%
+ \else
+ \externalfigure[#1][\c!page=\recurselevel,#2,\c!offset=\v!overlay]%
+ \fi}}}
+ \page}
+ \egroup}
+
+%D \macros
+%D {combinepages}
+%D
+%D Yet another way of postprocessing is handles by \type
+%D {\combinepages}. This macro builds a matrix of pages from a
+%D file, for example:
+%D
+%D \starttyping
+%D \setuppapersize
+%D [A4][A4] % or [A4,landscape][A4,landscape]
+%D
+%D \setuplayout
+%D [header=0pt,footer=1cm,
+%D backspace=1cm,topspace=1cm,
+%D width=middle,height=middle]
+%D
+%D \setupfootertexts
+%D [presentation---\currentdate\space---\space\pagenumber]
+%D
+%D \starttext
+%D \combinepages[slides][nx=2,ny=3,frame=on]
+%D \stoptext
+%D \stoptyping
+%D
+%D One can influence the way the pages are combined. (This
+%D will be explained some time.)
+
+\def\combinepages
+ {\dodoubleempty\docombinepages}
+
+\def\docombinepages[#1][#2]% a=perpag b=free
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#1]%
+ \getparameters
+ [\??ip]
+ [\c!alternative=\v!a,
+ \c!n=\noffigurepages,\c!nx=2,\c!ny=2,\c!start=1,\c!stop=\!!maxcard,
+ \c!distance=\bodyfontsize,
+ \c!bottom=\vfill,\c!top=\vss,
+ \c!left=\hss,\c!right=\hss,
+ \c!before=\page,\c!after=\page,\c!inbetween=\blank,
+ \c!frame=,\c!background=,\c!backgroundcolor=,
+ #2]%
+ \def\@@ipname{#1}%
+ \@@ipbefore
+ \executeifdefined{\strippedcsname\docombinepages\@@ipalternative}\docombinepagesb
+ \@@ipafter
+ \egroup}
+
+\def\docombinepagesa
+ {\globallet\combinedpagescounter\@@ipstart
+ \doloop
+ {\vbox to \textheight
+ {\hsize\textwidth % ? ?
+ \scratchdimen\@@ipdistance
+ \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
+ \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax
+ \dorecurse\@@ipny
+ {\hbox to \hsize
+ {\dorecurse\@@ipnx
+ {\vbox to \!!heighta
+ {\hsize\!!widtha
+ \vsize\!!heighta
+ \@@iptop
+ \hbox to \hsize
+ {\@@ipleft
+ \ifnum\combinedpagescounter>\@@ipstop\relax
+ \globallet\@@ipn\!!zerocount
+ \else\ifnum\combinedpagescounter>\@@ipn \else
+ \externalfigure[\@@ipname]
+ [\c!object=\v!no,
+ \c!page=\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\@@ipbackground,
+ \c!backgroundcolor=\@@ipbackgroundcolor,
+ \c!frame=\@@ipframe]%
+ \fi\fi
+ \@@ipright}
+ \@@ipbottom}%
+ \doglobal\increment\combinedpagescounter
+ \hfil}%
+ \hfilneg}
+ \vfil}%
+ \vfilneg}%
+ \page
+ \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}}
+
+\def\docombinepagesc
+ {\globallet\combinedpagescounter\@@ipstart
+ \doloop
+ {\vbox to \textheight
+ {\hsize\textwidth % ? ?
+ \scratchdimen\@@ipdistance
+ \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
+ \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax
+ \hbox to \hsize
+ {\dorecurse\@@ipnx
+ {\@@ipleft
+ \vbox to \textheight
+ {\hsize\!!widtha
+ {\dorecurse\@@ipny
+ {\@@iptop
+ \hbox to \hsize
+ {\vbox to \!!heighta
+ {\hsize\!!widtha
+ \vsize\!!heighta
+ \ifnum\combinedpagescounter>\@@ipstop\relax
+ \globallet\@@ipn\!!zerocount
+ \else\ifnum\combinedpagescounter>\@@ipn \else
+ \externalfigure[\@@ipname]
+ [\c!object=\v!no,
+ \c!page=\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\@@ipbackground,
+ \c!backgroundcolor=\@@ipbackgroundcolor,
+ \c!frame=\@@ipframe]%
+ \fi\fi}}
+ \doglobal\increment\combinedpagescounter
+ \@@ipbottom}%
+ \vfil}%
+ \vfilneg}
+ \hfil}%
+ \hfilneg}}
+ \page
+ \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}}
+
+\let\docombinepageshorizontal\docombinepagesa
+\let\docombinepagesvertical \docombinepagesc
+
+\def\docombinepagesb
+ {\globallet\combinedpagescounter\@@ipstart
+ \doloop
+ {\startbaselinecorrection
+ \scratchdimen\@@ipdistance
+ \!!widtha\dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
+ \hbox to \hsize
+ {\dorecurse\@@ipnx
+ {\doglobal\increment\combinedpagescounter
+ \ifnum\combinedpagescounter>\@@ipn \else
+ \expanded{\externalfigure[\@@ipname]
+ [\c!page=\combinedpagescounter,
+ \c!width=\the\!!widtha,% todo \freezedimenmacro
+ \c!background=\@@ipbackground,
+ \c!backgroundcolor=\@@ipbackgroundcolor,
+ \c!frame=\@@ipframe]}%
+ \hfill
+ \fi}\hfillneg}%
+ \stopbaselinecorrection
+ \ifnum\combinedpagescounter<\@@ipn\relax
+ \@@ipinbetween
+ \else
+ \exitloop
+ \fi}}
+
+%D \macros
+%D {setuppagecomment,startpagecomment}
+%D
+%D This command is not yet documented. Usage:
+%D
+%D \starttyping
+%D \setuppagecomment[state=start,location=right]
+%D
+%D \startpagecomment
+%D \input knuth
+%D \stoppagecomment
+%D \stoptyping
+
+\def\setuppagecomment
+ {\dosingleempty\dosetuppagecomment}
+
+\def\dosetuppagecomment[#1]%
+ {\getparameters[\??pc][#1]%
+ \doifelse\@@pcstate\v!start
+ {\doifinsetelse\@@pclocation{\v!bottom,\v!top}
+ {\setuppapersize[\c!left=\hskip\@@pcoffset]%
+ \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcheight\relax}%
+ \edef\@@pcpaperwidth {\the\dimexpr\paperwidth+\@@pcoffset+\@@pcoffset\relax}%
+ \defineoverlay[\v!pagecomment][\placepagecommentTB]}
+ {\setuppapersize[\c!top=\vskip\@@pcoffset]%
+ \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset\relax}%
+ \edef\@@pcpaperwidth {\the\dimexpr\paperwidth+\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcwidth\relax}%
+ \defineoverlay[\v!pagecomment][\placepagecommentLR]}%
+ \processaction
+ [\@@pclocation]
+ [ \v!bottom=>{\setuppapersize[\c!bottom =\vss,\c!top =\vskip\@@pcoffset]},
+ \v!top=>{\setuppapersize[\c!top =\vss,\c!bottom =\vskip\@@pcoffset]},
+ \v!left=>{\setuppapersize[\c!left =\hss,\c!right=\hskip\@@pcoffset]},
+ \v!right=>{\setuppapersize[\c!right=\hss,\c!left =\hskip\@@pcoffset]}]%
+ \definepapersize
+ [\v!pagecomment]
+ [\c!height=\@@pcpaperheight,
+ \c!width=\@@pcpaperwidth]%
+ \let\@@pcprintpapersize\printpapersize
+ \setuppapersize[\papersize][\v!pagecomment]%
+ \setupbackgrounds[\v!paper][\c!background=\v!pagecomment]}
+ {\doif\@@pcstate\v!stop % else initialization invokes backgrounds
+ {% this should be tested first
+ % \expanded{\setuppapersize[\papersize][\@@pcprintpapersize]}%
+ \setupbackgrounds[\v!paper][\c!background=]}}}
+
+\def\@@pcprintpapersize{\printpapersize}
+
+\def\placepagecommentTB
+ {\vbox to \printpaperheight
+ {\forgetall
+ \hsize\printpaperwidth
+ \vskip\@@pcoffset
+ \doifelse\@@pclocation\v!bottom{\vskip\dimexpr\paperheight+\@@pcdistance\relax}\vss
+ \hskip\@@pcoffset
+ \vbox to \@@pcheight
+ {\forgetall
+ \hsize\paperwidth
+ \ifpagecomment
+ \getbuffer[\v!pagecomment]%
+ \global\pagecommentfalse
+ \fi}%
+ \hfill
+ \doifelse\@@pclocation\v!bottom\vss{\vskip\dimexpr\paperheight+\@@pcdistance\relax}%
+ \vskip\@@pcoffset}}
+
+\def\placepagecommentLR
+ {\hbox to \printpaperwidth
+ {\hskip\@@pcoffset
+ \doifelse\@@pclocation\v!right{\hskip\paperwidth\hskip\@@pcdistance}\hss
+ \vbox to \printpaperheight
+ {\forgetall
+ \vskip\@@pcoffset
+ \hsize\@@pcwidth
+ \ifpagecomment
+ \getbuffer[\v!pagecomment]%
+ \global\pagecommentfalse
+ \fi
+ \vss}%
+ \doifelse\@@pclocation\v!right\hss{\hskip\paperwidth\hskip\@@pcdistance}%
+ \hskip\@@pcoffset}}
+
+\newif\ifpagecomment
+
+\setvalue{\e!start\v!pagecomment}%
+ {\global\pagecommenttrue
+ \dostartbuffer[\v!pagecomment][\e!start\v!pagecomment][\e!stop\v!pagecomment]}
+
+\setuppagecomment
+ [\c!state=, % \v!stop would invoke background calculation
+ \c!location=\v!bottom,
+ \c!offset=.5cm,
+ \c!distance=.5cm,
+ \c!height=5cm,
+ \c!width=10cm]
+
+% This macro cuts a page into n parts that can be pasted
+% together.
+
+\def\slicepages
+ {\dotripleempty\doslicepages}
+
+\def\doslicepages[#1][#2][#3]%
+ {\ifthirdargument
+ \dodoslicepages[#1][#2][#3]%
+ \else
+ \dodoslicepages[#1][#2][#2]%
+ \fi}
+
+\newcounter\slicedpagenumber
+
+\def\dodoslicepages[#1][#2][#3]%
+ {\bgroup
+ \dontcomplain
+ \globallet\slicedpagenumber\!!zerocount
+ \getfiguredimensions[#1]
+ \getparameters
+ [\??ip]
+ [\c!n=1,
+ \c!offset=\!!zeropoint,
+ \c!hoffset=\!!zeropoint,\c!voffset=\!!zeropoint,
+ \c!width=\figurewidth,\c!height=\figureheight,#2]
+ \ifnum\@@ipn>\zerocount
+ \definepapersize
+ [\s!dummy][\c!height=\@@ipheight,\c!width=\@@ipwidth]
+ \setuppapersize
+ [\s!dummy][\s!dummy]
+ \setuplayout
+ [\c!backspace=\!!zeropoint,\c!topspace=\!!zeropoint,
+ \c!height=\v!middle,\c!width=\v!middle,
+ \c!textdistance=\!!zeropoint,
+ \c!header=\!!zeropoint,\c!footer=\!!zeropoint]
+ \fi
+ \dorecurse\noffigurepages
+ {\global\let\slicedpagenumber\recurselevel
+ \ifnum\@@ipn>\plusone
+ \dorecurse\@@ipn
+ {\let\xslice\recurselevel
+ \dorecurse\@@ipn
+ {\let\yslice\recurselevel
+ \clip
+ [\c!nx=\@@ipn,\c!ny=\@@ipn,\c!x=\xslice,\c!y=\yslice]
+ {\scale
+ [\c!scale=\@@ipn000]
+ {\externalfigure[#1][\c!page=\slicedpagenumber]}}
+ \page}}
+ \else
+ \ifodd\slicedpagenumber\relax
+ \getparameters[\??ip][#2]
+ \else
+ \getparameters[\??ip][#3]
+ \fi
+ \hskip\@@ipoffset
+ \clip
+ [\c!hoffset=\@@iphoffset,\c!voffset=\@@ipvoffset,
+ \c!height=\@@ipheight,\c!width=\@@ipwidth]
+ {\externalfigure[#1][\c!page=\slicedpagenumber]}
+ \page
+ \fi}
+ \egroup}
+
+% \starttext \slicepages[slice1.pdf][n=3] \stoptext
+
+\protect \endinput
diff --git a/tex/context/base/page-imp.mkiv b/tex/context/base/page-imp.mkiv
new file mode 100644
index 000000000..a0f32ef86
--- /dev/null
+++ b/tex/context/base/page-imp.mkiv
@@ -0,0 +1,1299 @@
+%D \module
+%D [ file=page-imp, % was: core-pag,
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Pagebody Building (Imposition),
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% much of this can more to run time loading !
+
+\writestatus{loading}{ConTeXt Page Macros / Pagebody Building}
+
+\unprotect
+
+% sizing bug:
+%
+% \setuppapersize[A4][A4,landscape] \setuparranging[2UP] \showframe
+%
+% \starttext \dorecurse{10}{\input tufte \par} \stoptext
+
+% to be moved code:
+
+\newif\ifclipprintbox \clipprintboxtrue
+%newif\ifclippagebox \clippageboxtrue
+
+\def\clippedprintbox#1#2% can be made more efficient, see other clipper
+ {\ifclipprintbox
+ \!!widthc \pagebackgroundoffset
+ \!!widtha \dimexpr\paperwidth + \!!widthc\relax
+ \!!heighta\dimexpr\paperheight+2\!!widthc\relax
+ \setbox#2\vbox to \paperheight{\vfill\box#2}%
+ \ht#2\paperheight
+ \wd#2\paperwidth
+ \setbox#2\vbox
+ {\framed
+ [\c!offset=\!!widthc,\c!strut=\v!no,\c!frame=\v!off]
+ {\box#2}}%
+ \setbox#2\hbox to \paperwidth
+ {\ifcase#1\relax
+ \!!widthb\zeropoint
+ \hskip-\!!widthc
+ \else
+ \!!widthb\!!widthc
+ \fi
+ \lower\!!widthc\hbox
+ {\clip
+ [\c!width=\!!widtha,\c!height=\!!heighta,
+ \c!hoffset=\!!widthb,\c!voffset=\zeropoint]
+ {\box#2}}}%
+ \wd#2\paperwidth
+ \ht#2\paperheight
+ \fi
+ \box#2\relax}
+
+\let\clippagebox \gobbleoneargument
+\let\clipprintbox\gobbleoneargument
+
+% \setuppagenumbering[alternative=doublesided]
+% \setupcolors[state=start]
+% \setuppapersize[A4][A4,oversized]
+% \setuplayout[location=middle,clipoffset=5mm]
+% \setupbackgrounds
+% [page]
+% [frame=on,rulethickness=1mm,
+% backgroundoffset=10mm,background=color,backgroundcolor=red]
+% \starttext \dorecurse{10}{\input tufte \par} \stoptext
+
+\def\clippagebox % skip fast over false
+ {\ifdim\@@lyclipoffset>\zeropoint
+ \expandafter\doclippagebox
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doclippagebox#1%
+ {\!!widtha \wd#1%
+ \!!heighta\ht#1%
+ \!!deptha \dp#1%
+ \setbox#1\hbox
+ {\!!widthb \@@lyclipoffset
+ \advance\!!heighta\dimexpr\!!deptha+2\!!widthb\relax
+ \advance\!!widtha \!!widthb
+ \doifbothsides
+ {\advance\!!widtha\!!widthb \!!widthc-\!!widthb \hskip\!!widthc}%
+ {\!!widthc\zeropoint}
+ {\!!widthc-\!!widthb \hskip\!!widthc}%
+ \lower\!!widthb\hbox
+ {\clip
+ [\c!hoffset=\!!widthc,
+ \c!voffset=-\!!widthb,
+ \c!width=\!!widtha,
+ \c!height=\!!heighta]%
+ {\box#1}}}%
+ \wd#1\!!widtha
+ \ht#1\!!heighta
+ \dp#1\!!deptha}
+
+%D \macros
+%D {starttextdata}
+%D
+%D This is a user macro (appending to every last shipout is not
+%D really user friendly.
+
+\newtoks \collectedtextdata
+
+\long\unexpanded\def\starttextdata#1\stoptextdata
+ {\doglobal\appendtoks#1\to\collectedtextdata}
+
+\def\flushtextdata
+ {\vsmashed{\the\collectedtextdata}% all dimensions zero
+ \global\collectedtextdata\emptytoks
+ \globallet\flushtextdata\donothing}
+
+\prependtoks \flushtextdata \to \everylastshipout
+
+\def\installpagehandler#1#2% % a handler takes one argument: something to be boxed
+ {\setgvalue{\??pp:\c!method:#1}##1{#2{##1}}} % and shipped out (don't depend on the exact package)
+
+\installpagehandler\v!normal
+ {\ifarrangingpages\expandafter\actualarrange\else\expandafter\actualshipout\fi}
+
+\def\myshipout#1%
+ {\beforeshipout % voor de pagebody dus !
+ \dontshowcomposition
+ \executeifdefined{\??pp:\c!method:\@@ppmethod}\gobbleoneargument{#1}%
+ \setnextrealpageno
+ \aftershipout}
+
+\newbox\postponedcontent
+
+\def\flushatshipout
+ {\dowithnextbox
+ {\global\setbox\postponedcontent\hbox to \zeropoint
+ {%\hskip-\maxdimen % niet hier, gaat mis in acrobat (clipt)
+ \unhbox\postponedcontent\unhbox\nextbox}% was \box
+ \global\ht\postponedcontent\zeropoint
+ \global\dp\postponedcontent\zeropoint
+ \global\wd\postponedcontent\zeropoint}%
+ \hbox}
+
+% \starttypen
+% \def\pagestoshipout{1,3,5}
+% \stoptypen
+
+\newcount\shippedoutpages
+
+\let\pagestoshipout\empty % {1,3,6}
+\chardef\whichpagetoshipout=0 % 0=all 1=odd 2=even
+
+\def\actualshipout#1%
+ {\global\advance\shippedoutpages\plusone
+ % this is not resource safe!
+ \ifx\pagestoshipout\empty
+ \ifcase\whichpagetoshipout\relax
+ \donetrue
+ \or % 1
+ \ifodd\shippedoutpages\relax\donetrue\else\donefalse\fi
+ \or % 2
+ \ifodd\shippedoutpages\relax\donefalse\else\donetrue\fi
+ \else
+ \donetrue
+ \fi
+ \else % testen, aangepast / expanded nodig ?
+ \normalexpanded{\noexpand\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}%
+ \donetrue\donefalse
+ \fi
+ \ifdone
+ \shipout\vbox
+ {%\forgetall
+ \offinterlineskip
+ \dontcomplain
+ \scratchdimen-1in
+ \vskip\scratchdimen
+ \hskip\scratchdimen
+ \setbox0\hbox{#1}% just in case there are objects there, hook for testing
+ \finalizeshipoutbox0%
+ \setbox\scratchbox\hbox
+ {% before the main one !
+ \ifcase\realfolio \or
+ \the\everyfirstshipout
+ \global\everyfirstshipout\emptytoks
+ \fi
+ % the main one
+ \the\everyshipout\relax
+ % always last (and after the main one)
+ \ifnum\realpageno=\lastpage\relax
+ \the\everylastshipout
+ \global\everylastshipout\emptytoks
+ \fi}%
+ \smashbox\scratchbox
+ \hbox % \setbox0=\box.. is nicer
+ {\box\scratchbox
+ \ifvoid\postponedcontent\else\box\postponedcontent\fi % evt ver naar links !
+ \box0}}%
+ \else
+ \message
+ {[\ifarrangingpages arranged \fi page
+ \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace
+ not flushed]}%
+ \setbox0\hbox{#1}%
+ \deadcycles\zerocount
+ \fi}
+
+\def\actualarrange#1%
+ {\setbox0\hbox{#1}%
+ \pusharrangedpage0%
+ \deadcycles\zerocount}
+
+%D We need a couple of boxes for duplex printing \unknown
+
+\newbox\arrangedpageA \newbox\arrangedpageB
+
+%D \unknown\ and some for simulating big sheets.
+
+\newbox\arrangedpageC \newbox\arrangedpageD
+\newbox\arrangedpageE \newbox\arrangedpageF
+\newbox\arrangedpageG \newbox\arrangedpageH
+
+\newif\ifswaparranged
+\newif\ifnegatearranged
+\newif\ifmirrorarranged
+\newif\ifdoublearranged
+
+\newif\ifarrangingdisabled
+
+\def\arrangedrotationO{0}
+\def\arrangedrotationE{0}
+
+\newcounter\arrangedpageN
+\newcounter\arrangedpageM
+
+\chardef\arrangedpageT=1
+\chardef\arrangedpageX=1
+\chardef\arrangedpageY=1
+
+\def\calculatepaperoffsets#1%
+ {\scratchdimen\getvalue{\??pp#1\c!offset}%
+ \divide\scratchdimen \arrangedpageX
+ \global\advance\paperwidth -2\scratchdimen
+ \scratchdimen\getvalue{\??pp#1\c!offset}%
+ \divide\scratchdimen \arrangedpageY
+ \global\advance\paperheight-2\scratchdimen}
+
+\newconditional\arrangedbackgroundokay % more ifs -> conditionals
+
+\unexpanded\def\setuparranging[#1]%
+ {\ifarrangingdisabled \else
+ \doifelse{#1}\v!disable
+ {\global\arrangingdisabledtrue}
+ {\global\arrangingdisabledfalse}%
+ \global\arrangingpagestrue
+ \global\negatearrangedfalse
+ \global\mirrorarrangedfalse
+ \global\doublearrangedfalse
+ \gdef\arrangedrotationO{0}%
+ \gdef\arrangedrotationE{180}%
+ \processallactionsinset
+ [#1]
+ [ \v!mirrored=>\global\mirrorarrangedtrue,
+ \v!doublesided=>\global\doublearrangedtrue,
+ \v!negative=>\global\negatearrangedtrue,
+ \v!rotated=>\gdef\arrangedrotationO {90}\gdef\arrangedrotationE{270},
+ 90=>\gdef\arrangedrotationO {90}\gdef\arrangedrotationE{270},
+ 180=>\gdef\arrangedrotationO{180}\gdef\arrangedrotationE{0},
+ 270=>\gdef\arrangedrotationO{270}\gdef\arrangedrotationE{90},
+ \s!reset=>\global\arrangingpagesfalse,
+ \v!background=>\global\settrue\arrangedbackgroundokay,
+ \s!unknown=>\checkinstalledpagearrangement\commalistelement]%
+ % no \s!default=> we can have aaa,,bbb
+ \ifx\handlearrangedpage\undefined
+ \global\arrangingpagesfalse
+ \fi
+ \doifcommonelse{#1}{90,270,\v!rotated}
+ {\swapmacros\horizontalcutmarks\verticalcutmarks}{}% ugly solution
+ \setuppapersize
+ \fi}
+
+\def\installpagearrangement #1 %
+ {\setgvalue{\??pp\??pp#1}}
+
+\def\checkinstalledpagearrangement#1% can be empty: aaa,,bbb
+ {\executeifdefined{\??pp\??pp#1}\donothing}
+
+\def\dosetuparrangement#1#2#3#4#5#6#7#8%
+ {\global\chardef\arrangedpageX #1%
+ \global\chardef\arrangedpageY #2%
+ \global\chardef\arrangedpageT #3%
+ \global\chardef\horizontalcutmarks#4%
+ \global\chardef\verticalcutmarks #5%
+ \global\let \pusharrangedpage #6%
+ \global\let \poparrangedpages #7%
+ \global\let \handlearrangedpage#8}
+
+\installpagearrangement {\v!normal}
+ {\global\arrangingpagesfalse}
+
+\installpagearrangement 2*16
+ {\dosetuparrangement{4}{4}{16}{5}{5}%
+ \pusharrangedpageTHIRTYTWO\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*8
+ {\dosetuparrangement{4}{2}{8}{5}{3}%
+ \pusharrangedpageSIXTEEN\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*4
+ {\dosetuparrangement{2}{2}{4}{3}{3}%
+ \pusharrangedpageEIGHT\poparrangedpagesAB\relax}
+
+\installpagearrangement 2*2
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageFOURA\poparrangedpagesAB\relax}
+
+\installpagearrangement 2**2
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageFOURB\poparrangedpagesAB\relax}
+
+\installpagearrangement 2SIDE
+ {\dosetuparrangement{2}{1}{2}{3}{2}%
+ \pusharrangedpageSIDETOP\poparrangedpagesTWO\handlearrangedpageSIDE}
+
+\installpagearrangement 2TOP
+ {\dosetuparrangement{1}{2}{2}{2}{3}%
+ \pusharrangedpageSIDETOP\poparrangedpagesTWO\handlearrangedpageTOP}
+
+\installpagearrangement 2UP
+ {\dosetuparrangement{2}{1}{4}{3}{2}%
+ \pusharrangedpageTWO\poparrangedpagesTWO\handlearrangedpageTWOUP}
+
+\installpagearrangement 2DOWN
+ {\dosetuparrangement{1}{2}{4}{2}{3}%
+ \pusharrangedpageTWO\poparrangedpagesTWO\handlearrangedpageTWODOWN}
+
+\installpagearrangement 2*4*2 % one defined by Willy Egger:
+ {\dosetuparrangement{2}{2}{4}{3}{2}%
+ \pusharrangedpageSIXTEENTWO\poparrangedpagesAtoD\relax}
+
+\installpagearrangement 2*2*4 % onother one of Willy Egger
+ {\dosetuparrangement{2}{1}{8}{3}{2}%
+ \pusharrangedpageSIXTEENFOUR\poparrangedpagesAtoH\relax}
+
+\installpagearrangement 2TOPSIDE
+ {\dosetuparrangement{1}{2}{4}{2}{3}%
+ \pusharrangedpageTWOTOPSIDE\poparrangedpagesTWOTOPSIDE\handlearrangedpageTOP}
+
+% \def\filluparrangedpages % beware: \realpageno is 1 ahead
+% {\ifarrangingpages
+% \scratchcounter-\realpageno
+% \divide\scratchcounter \arrangedpageT
+% \multiply\scratchcounter \arrangedpageT
+% \advance\scratchcounter \realpageno
+% \advance\scratchcounter \minusone
+% \dorecurse\scratchcounter{\noheaderandfooterlines\ejectdummypage}%
+% \fi}
+
+\def\filluparrangedpages % beware: \realpageno is 1 ahead
+ {\ifarrangingpages
+ \scratchcounter\numexpr\realpageno-\plusone\relax
+ \dosetmodulo\scratchcounter\arrangedpageT\scratchcounter
+ \ifcase\scratchcounter\else
+ \advance\scratchcounter \plusone
+ \dostepwiserecurse\scratchcounter\arrangedpageT\plusone
+ {\noheaderandfooterlines\ejectdummypage}%
+ \fi
+ \fi}
+
+\def\handlearrangedpageXandY#1#2#3#4#5%
+ {\global\setbox#5\hbox to \arrangedpageX\paperwidth
+ {\setbox\scratchbox\vbox to \arrangedpageY\paperheight
+ {%\forgetall
+ \offinterlineskip
+ \dontcomplain
+ \vskip#4\paperheight
+ \hskip#3\paperwidth
+ \dorotatebox{\ifcase#2 0\else180\fi}\hbox{\box#1}%
+ \vfill}%
+ \wd\scratchbox\zeropoint
+ \box\scratchbox\box#5\hss}}
+
+\def\gotonextarrangepage
+ {\global\advance\arrangeno \plusone
+ \def\pagecutmarksymbol{\the\arrangeno}}
+
+\def\outputarrangedbox#1%
+ {\bgroup
+ \forgetall % somehow we're back and need to redo this
+ \gotonextarrangepage
+ \ifnum\arrangedrotationO\arrangedrotationE>\zerocount
+ \setbox#1\vbox
+ {\ifdoublearranged
+ \ifodd\arrangeno
+ \dorotatebox\arrangedrotationO\hbox{\box#1}%
+ \else
+ \dorotatebox\arrangedrotationE\hbox{\box#1}%
+ \fi
+ \else
+ \dorotatebox\arrangedrotationO\hbox{\box#1}%
+ \fi}%
+ \fi
+ \ifmirrorarranged
+ \setbox#1\vbox{\domirrorbox\vbox{\box#1}}%
+ \fi
+ \ifnegatearranged
+ \negatecolorbox{#1}%
+ \fi
+ \finishpagebox#1%
+ \ifconditional\arrangedbackgroundokay\addprintbackground#1\fi
+ \actualshipout{\box#1}%
+ \egroup}
+
+%D The format file can be 16K smaller when we postpone the
+%D real arrangments. Some day ...
+
+% TOP
+
+% 32/16/8/4/SIDE
+
+\def\poparrangedpagesAB
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+\def\pusharrangedpageTHIRTYTWO#1% taco's challenge
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}033\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}003\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}130\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}130\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}033\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}003\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}102\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}132\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}031\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 12
+ \or \handlearrangedpageXandY{#1}031\arrangedpageA % 13
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 14
+ \or \handlearrangedpageXandY{#1}102\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}132\arrangedpageA % 16
+ \or \handlearrangedpageXandY{#1}122\arrangedpageA % 17
+ \or \handlearrangedpageXandY{#1}112\arrangedpageB % 18
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 19
+ \or \handlearrangedpageXandY{#1}021\arrangedpageA % 20
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 21
+ \or \handlearrangedpageXandY{#1}021\arrangedpageB % 22
+ \or \handlearrangedpageXandY{#1}122\arrangedpageB % 23
+ \or \handlearrangedpageXandY{#1}112\arrangedpageA % 24
+ \or \handlearrangedpageXandY{#1}013\arrangedpageA % 25
+ \or \handlearrangedpageXandY{#1}023\arrangedpageB % 26
+ \or \handlearrangedpageXandY{#1}120\arrangedpageB % 27
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 28
+ \or \handlearrangedpageXandY{#1}120\arrangedpageA % 29
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 30
+ \or \handlearrangedpageXandY{#1}013\arrangedpageB % 31
+ \or \handlearrangedpageXandY{#1}023\arrangedpageA % 32
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageSIXTEEN#1% changed to match the official way of doing
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}031\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}031\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}130\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}130\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}120\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}120\arrangedpageB % 11
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 12
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 13
+ \or \handlearrangedpageXandY{#1}021\arrangedpageB % 14
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}021\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageEIGHT#1% changed to match the official way of doing
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 3
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 5
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 6
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 8
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageFOURA{\pusharrangedpageFOURdo01}
+\def\pusharrangedpageFOURB{\pusharrangedpageFOURdo10}
+
+\def\pusharrangedpageFOURdo#1#2#3%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#3}010\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#3}0{#1}0\arrangedpageB % 2/3 not {1}
+ \or \handlearrangedpageXandY{#3}0{#2}0\arrangedpageB % 3/2 not {1}
+ \or \handlearrangedpageXandY{#3}000\arrangedpageA % 4
+ \poparrangedpages
+ \fi}
+
+\def\pusharrangedpageSIDETOP#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \poparrangedpages
+ \fi}
+
+\def\handlearrangedpageSIDE
+ {\global\wd\arrangedpageA\paperwidth
+ \global\wd\arrangedpageB\paperwidth
+ \global\setbox\arrangedpageA\hbox
+ {\box\arrangedpageA\box\arrangedpageB}%
+ \global\ht\arrangedpageA\paperheight}
+
+\def\handlearrangedpageTOP
+ {\global\ht\arrangedpageA\paperheight
+ \global\ht\arrangedpageB\paperheight
+ \global\setbox\arrangedpageA\vbox
+ {%\forgetall
+ \offinterlineskip\vskip\paperheight
+ \box\arrangedpageA\box\arrangedpageB}%
+ \global\setbox\arrangedpageB\box\scratchbox} % ?
+
+% 2UP/2DOWN / 1pt prevents overflow
+
+\def\splitoffarrangedpagesTWO
+ {\splittopskip\zeropoint
+ \global\setbox\arrangedpageA\vsplit\arrangedpageB to \onepoint
+ \scratchdimen\dimexpr\ht\arrangedpageB-\onepoint\relax
+ \ifdim\scratchdimen>\onepoint
+ \setbox\scratchbox\vsplit\arrangedpageB to \scratchdimen
+ \fi}
+
+\def\handlearrangedpageTWOUP
+ {\splitoffarrangedpagesTWO
+ \ifswaparranged
+ \global\setbox\arrangedpageA\hbox
+ {\clippedprintbox0\arrangedpageA
+ \clippedprintbox1\arrangedpageB}%
+ \swaparrangedfalse
+ \else
+ \global\setbox\arrangedpageA\hbox
+ {\clippedprintbox0\arrangedpageB
+ \clippedprintbox1\arrangedpageA}%
+ \swaparrangedtrue
+ \fi
+ \global\ht\arrangedpageA\paperheight
+ \global\setbox\arrangedpageB\box\scratchbox}
+
+\def\handlearrangedpageTWODOWN
+ {\splitoffarrangedpagesTWO
+ \global\ht\arrangedpageA\paperheight
+ \global\ht\arrangedpageB\paperheight
+ \ifswaparranged
+ \global\setbox\arrangedpageA\vbox
+ {%\forgetall
+ \offinterlineskip\vskip\paperheight
+ \box\arrangedpageA\box\arrangedpageB}%
+ \swaparrangedfalse
+ \else
+ \global\setbox\arrangedpageA\vbox
+ {%\forgetall
+ \offinterlineskip\vskip\paperheight
+ \box\arrangedpageB\box\arrangedpageA}%
+ \swaparrangedtrue
+ \fi
+ \global\setbox\arrangedpageB\box\scratchbox}
+
+\def\poparrangedpagesTWO
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \swaparrangedfalse
+ \doloop
+ {\handlearrangedpage
+ \bgroup
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \ht\arrangedpageA\paperheight
+ \wd\arrangedpageA\paperwidth
+ \outputarrangedbox\arrangedpageA
+ \egroup
+ \ifdim\ht\arrangedpageB=\zeropoint
+ \exitloop
+ \fi}%
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+\def\pusharrangedpageTWO#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \global\setbox\arrangedpageB\vbox
+ {%\forgetall
+ \offinterlineskip
+ \unvbox\arrangedpageB
+ \allowbreak
+ \ht#1\onepoint
+ \dp#1\zeropoint
+ \vbox{\box#1}}}
+
+\def\poparrangedpagesTWOTOPSIDE
+ {\ifnum\arrangedpageN>\zerocount
+ \bgroup
+ \gdef\arrangedpageN{2}\poparrangedpagesTWO
+ \let\arrangedpageA\arrangedpageC
+ \let\arrangedpageB\arrangedpageD
+ \gdef\arrangedpageN{2}\poparrangedpagesTWO
+ \doglobal\newcounter\arrangedpageN
+ \egroup
+ \fi}
+
+\def\pusharrangedpageTWOTOPSIDE#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 2
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 2
+ \poparrangedpages
+ \fi}
+
+%D Willy Egger's sheet simulations:
+
+\def\poparrangedpagesAtoH
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \outputarrangedbox\arrangedpageC
+ \outputarrangedbox\arrangedpageD
+ \outputarrangedbox\arrangedpageE
+ \outputarrangedbox\arrangedpageF
+ \outputarrangedbox\arrangedpageG
+ \outputarrangedbox\arrangedpageH
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+% to arrange 16 pages on 2 sheets to form one booklet
+
+\def\poparrangedpagesAtoD
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight\arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \outputarrangedbox\arrangedpageB
+ \outputarrangedbox\arrangedpageC
+ \outputarrangedbox\arrangedpageD
+ \doglobal\newcounter\arrangedpageN
+ \fi}
+
+% to arrange 16 pages on 4 sheets to form one booklet
+
+\def\pusharrangedpageSIXTEENFOUR#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}010\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}000\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}010\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}000\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}010\arrangedpageE % 5
+ \or \handlearrangedpageXandY{#1}000\arrangedpageF % 6
+ \or \handlearrangedpageXandY{#1}010\arrangedpageG % 7
+ \or \handlearrangedpageXandY{#1}000\arrangedpageH % 8
+ \or \handlearrangedpageXandY{#1}010\arrangedpageH % 9
+ \or \handlearrangedpageXandY{#1}000\arrangedpageG % 10
+ \or \handlearrangedpageXandY{#1}010\arrangedpageF % 11
+ \or \handlearrangedpageXandY{#1}000\arrangedpageE % 12
+ \or \handlearrangedpageXandY{#1}010\arrangedpageD % 13
+ \or \handlearrangedpageXandY{#1}000\arrangedpageC % 14
+ \or \handlearrangedpageXandY{#1}010\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}000\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+% to arrange 16 pages on 2 sheets to form one booklet
+
+\def\pusharrangedpageSIXTEENTWO#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \ifcase\arrangedpageN
+ \or \handlearrangedpageXandY{#1}011\arrangedpageA % 1
+ \or \handlearrangedpageXandY{#1}001\arrangedpageB % 2
+ \or \handlearrangedpageXandY{#1}011\arrangedpageC % 3
+ \or \handlearrangedpageXandY{#1}001\arrangedpageD % 4
+ \or \handlearrangedpageXandY{#1}100\arrangedpageD % 5
+ \or \handlearrangedpageXandY{#1}110\arrangedpageC % 6
+ \or \handlearrangedpageXandY{#1}100\arrangedpageB % 7
+ \or \handlearrangedpageXandY{#1}110\arrangedpageA % 8
+ \or \handlearrangedpageXandY{#1}100\arrangedpageA % 9
+ \or \handlearrangedpageXandY{#1}110\arrangedpageB % 10
+ \or \handlearrangedpageXandY{#1}100\arrangedpageC % 11
+ \or \handlearrangedpageXandY{#1}110\arrangedpageD % 12
+ \or \handlearrangedpageXandY{#1}011\arrangedpageD % 13
+ \or \handlearrangedpageXandY{#1}001\arrangedpageC % 14
+ \or \handlearrangedpageXandY{#1}011\arrangedpageB % 15
+ \or \handlearrangedpageXandY{#1}001\arrangedpageA % 16
+ \poparrangedpages
+ \fi}
+
+% % handy for stickers etc, this way we can treat them as page
+%
+% \setuppapersize [XY][A4]
+% \setuppaper [topspace=5mm,backspace=5mm,dx=1mm,dy=1mm,nx=2,ny=6]
+% \setuplayout [page] [topspace=5mm,backspace=5mm]
+% \setuplayout [page]
+% \setuplayout [location=middle]
+% \setuparranging [XY]
+% \showframe
+%
+% \starttext \dorecurse{30}{test \recurselevel \page} \stoptext
+
+\def\pusharrangedpageXY#1%
+ {\doglobal\increment\arrangedpageN
+ \reportarrangedpage\arrangedpageN
+ \doglobal\increment\arrangedpageM
+ \global\setbox\arrangedpageB\hbox
+ \ifdim\@@ppwidth>\zeropoint to \@@ppwidth \fi
+ {\ifvoid\arrangedpageB\else
+ \unhbox\arrangedpageB
+ \ifdim\@@ppdx>\zeropoint \else \hss\fi
+ \hskip\@@ppdx
+ \ifdim\@@ppdx>\zeropoint \else \hss\fi
+ \fi
+ \box#1}%
+ \ifnum\arrangedpageM<\arrangedpageX\else
+ \global\setbox\arrangedpageA\vbox
+ \ifdim\@@ppheight>\zeropoint to \@@ppheight \fi
+ {\offinterlineskip
+ \ifvoid\arrangedpageA\else
+ \unvbox\arrangedpageA
+ \ifdim\@@ppdy>\zeropoint \else \vss\fi
+ \vskip\@@ppdy
+ \ifdim\@@ppdy>\zeropoint \else \vss\fi
+ \fi
+ \box\arrangedpageB}%
+ \doglobal\newcounter\arrangedpageM
+ \fi
+ \ifnum\arrangedpageN<\arrangedpageT\else
+ \poparrangedpages
+ \fi}
+
+\def\poparrangedpagesXY
+ {\ifnum\arrangedpageN>\zerocount
+ \dontcomplain
+ \paperwidth\arrangedpageX\paperwidth
+ \paperheight \arrangedpageY\paperheight
+ \outputarrangedbox\arrangedpageA
+ \doglobal\newcounter\arrangedpageN
+ \doglobal\newcounter\arrangedpageM
+ \fi}
+
+\installpagearrangement XY
+ {\dosetuparrangement\@@ppnx\@@ppny\@@ppxy\!!zerocount\!!zerocount
+ \pusharrangedpageXY\poparrangedpagesXY\relax}
+
+%D A crazy definition, don't guess who pushed me for the landscape option.
+
+\definepapersize
+ [XY]
+ [\c!height=\dimexpr\dimexpr\@@ppheight-\numexpr\@@ppny-1\relax\dimexpr\@@ppdy\relax\relax/\@@ppny\relax,
+ \c!width =\dimexpr\dimexpr\@@ppwidth -\numexpr\@@ppnx-1\relax\dimexpr\@@ppdx\relax\relax/\@@ppnx\relax]
+
+\setuppaper
+ [\c!width =\dimexpr\printpaperwidth -2\dimexpr\@@ppbackspace\relax\relax,
+ \c!height=\dimexpr\printpaperheight-2\dimexpr\@@pptopspace \relax\relax]
+
+% \definepageshift[test][horizontal][10pt,20pt,30pt,40pt,50pt]
+% \definepageshift[test][vertical] [10pt,20pt,30pt,40pt,50pt]
+%
+% \setuppageshift[test]
+% \setuppageshift[test][test]
+% \setuppageshift[test][none]
+% \setuppageshift[none][test]
+% \setuppageshift[paper][test][test] % arrange only
+% \setuppageshift[paper][test] % arrange only
+% \setuppageshift[print][test][test]
+%
+% \showframe \dorecurse{100}{\input tufte \par}
+
+% #1=name #2=horizontal|vertical #3=shiftlist
+
+\unexpanded\def\definepageshift
+ {\dotripleargument\dodefinepageshift}
+
+\def\dodefinepageshift[#1][#2][#3]%
+ {\setvalue{\??pt#2:#1}{#3}}
+
+\letempty \hpageshifts \newcounter\nofhpageshifts
+\letempty \vpageshifts \newcounter\nofvpageshifts
+
+% \let\shiftprintpagebox\gobbleoneargument
+% \let\shiftpaperpagebox\gobbleoneargument
+
+\def\dogetpageshift#1#2#3% #1=\dimenx #2=\xpageshifts #3=\nofxpageshifts
+ {\ifx#2\empty
+ #1\zeropoint
+ \else
+ \doglobal\increment#3%
+ \getfromcommacommand[#2][#3]%
+ \ifx\commalistelement\empty
+ \globallet#3\!!plusone
+ \getfromcommacommand[#2][#3]%
+ \fi
+ \ifx\commalistelement\empty
+ #1\zeropoint
+ \else
+ #1=\commalistelement
+ \donetrue
+ \fi
+ \fi}
+
+\def\shiftpagebox#1%
+ {\donefalse
+ \dogetpageshift{\dimen0}\hpageshifts\nofhpageshifts
+ \dogetpageshift{\dimen2}\vpageshifts\nofvpageshifts
+ \ifdone % see also layout offsets, maybe \movebox
+ \edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
+ \setbox#1\vbox
+ {\offinterlineskip\vskip\dimen2\hskip\dimen0\box#1}%
+ \next
+ \fi}
+
+\unexpanded\def\setuppageshift
+ {\dotripleempty\dosetuppageshift}
+
+\def\dosetuppageshift[#1][#2][#3]% page|paper horizontal vertical
+ {\ifthirdargument % paper=arrange
+ \let\hpageshifts\empty
+ \let\vpageshifts\empty
+ \let\shiftprintpagebox\gobbleoneargument
+ \let\shiftpaperpagebox\gobbleoneargument
+ \doifdefined{\??pt\v!horizontal:#2}
+ {\edef\hpageshifts{\getvalue{\??pt\v!horizontal:#2}}}%
+ \doifdefined{\??pt\v!vertical :#3}
+ {\edef\vpageshifts{\getvalue{\??pt\v!vertical :#3}}}%
+ \doif{#1}\v!page{\let\shiftprintpagebox\shiftpagebox}%
+ \doif{#1}\v!paper{\let\shiftpaperpagebox\shiftpagebox}%
+ \else\ifsecondargument
+ \doifinsetelse{#1}{\v!page,\v!paper}
+ {\setuppageshift[#1][#2][#2]}
+ {\setuppageshift[\v!page][#1][#2]}%
+ \else\iffirstargument
+ \setuppageshift[\v!page][#1][#1]%
+ \fi\fi\fi}
+
+%D One can (mis)use this mechanism, in close cooperation
+%D with \PDFTEX\ to arrange pages of already produced files.
+%D
+%D \starttyping
+%D \insertpages[file.pdf][1,3][n=30,width=18cm]
+%D \stoptyping
+%D
+%D The pages are inserted in the text area, and even pages
+%D are repositioned according to the width. In this example
+%D empty pages are added after page 1 and 3.
+%D
+%D Selecting pages can be accomplished by:
+%D
+%D \starttyping
+%D \filterpages[file.pdf][1,3,5][n=30,width=18cm]
+%D \stoptyping
+%D
+%D One may pass \type {odd} or \type {even} instead of a
+%D comma separated list. A third alternative is:
+%D
+%D \starttyping
+%D \copypages[file.pdf][n=30,scale=950]
+%D \stoptyping
+%D
+%D This macros inserts the page, according to the settings
+%D provided.
+
+\def\insertpages
+ {\dotripleempty\doinsertpages}
+
+\def\doinsertpages[#1][#2][#3]%
+ {\doifassignmentelse{#2}
+ {\dodoinsertpages[#1][][#2]}
+ {\dodoinsertpages[#1][#2][#3]}}
+
+\def\dodoinsertpages[#1][#2][#3]%
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#1]%
+ \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]%
+ \doifinset0{#2}{\null\page}%
+ \dorecurse\@@ipn
+ {\dofilterpage{#1}\recurselevel
+ \doifinset\recurselevel{#2}{\null\page}}%
+ \egroup}
+
+\def\filterpages
+ {\dotripleempty\dofilterpages}
+
+\def\dofilterpages[#1][#2][#3]% % \noffigurepages not yet supported
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#1]%
+ \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]%
+ \doifelse{#2}\v!even
+ {\dorecurse\@@ipn
+ {\ifodd\recurselevel\relax\else\dofilterpage{#1}\recurselevel\fi}}
+ {\doifelse{#2}\v!odd
+ {\dorecurse\@@ipn
+ {\ifodd\recurselevel\relax\dofilterpage{#1}\recurselevel\fi}}
+ {\def\dodocommand##1%
+ {\ifnum##1>\@@ipn\else\dofilterpage{#1}{##1}\fi}%
+ \def\docommand##1%
+ {\dowithrange{##1}\dodocommand}%
+ \processcommalist[#2]\docommand}}%
+ \egroup}
+
+\def\dofilterpage#1#2%
+ {\hbox to \textwidth
+ {\ifdoublesided\ifdim\@@ipwidth>\zeropoint\relax\ifodd\realpageno\else
+ \hfill
+ \def\dowithfigure{\hskip-\@@ipwidth}%
+ \fi\fi\fi
+ \setbox0\hbox
+ {\externalfigure[#1][\c!page=#2,\c!height=\textheight]}%
+ \wd0\zeropoint
+ \box0}
+ \page}
+
+\def\copypages
+ {\dodoubleempty\docopypages}
+
+\def\docopypages[#1][#2]%
+ {\bgroup
+ \getfiguredimensions[#1]%
+ \getparameters[\??ip]
+ [\c!n=\noffigurepages,
+ \c!marking=\v!off,
+ \c!scale=\!!thousand,
+ \c!offset=\!!zeropoint,
+ #2]%
+ \dorecurse\@@ipn
+ {\vbox to \textheight
+ {\hsize\textwidth
+ \scratchdimen\@@ipoffset
+ \centeredbox
+ {\doifelse\@@ipmarking\v!on\cuthbox\hbox
+ {\ifdim\scratchdimen>\zeropoint\relax
+ \advance\vsize -2\scratchdimen
+ \advance\hsize -2\scratchdimen
+ \externalfigure[#1][\c!page=\recurselevel,#2,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]%
+ \else
+ \externalfigure[#1][\c!page=\recurselevel,#2,\c!offset=\v!overlay]%
+ \fi}}}
+ \page}
+ \egroup}
+
+%D \macros
+%D {combinepages}
+%D
+%D Yet another way of postprocessing is handles by \type
+%D {\combinepages}. This macro builds a matrix of pages from a
+%D file, for example:
+%D
+%D \starttyping
+%D \setuppapersize
+%D [A4][A4] % or [A4,landscape][A4,landscape]
+%D
+%D \setuplayout
+%D [header=0pt,footer=1cm,
+%D backspace=1cm,topspace=1cm,
+%D width=middle,height=middle]
+%D
+%D \setupfootertexts
+%D [presentation---\currentdate\space---\space\pagenumber]
+%D
+%D \starttext
+%D \combinepages[slides][nx=2,ny=3,frame=on]
+%D \stoptext
+%D \stoptyping
+%D
+%D One can influence the way the pages are combined. (This
+%D will be explained some time.)
+
+\def\combinepages
+ {\dodoubleempty\docombinepages}
+
+\def\docombinepages[#1][#2]% a=perpag b=free
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#1]%
+ \getparameters
+ [\??ip]
+ [\c!alternative=\v!a,
+ \c!n=\noffigurepages,\c!nx=2,\c!ny=2,\c!start=1,\c!stop=\!!maxcard,
+ \c!distance=\bodyfontsize,
+ \c!bottom=\vfill,\c!top=\vss,
+ \c!left=\hss,\c!right=\hss,
+ \c!before=\page,\c!after=\page,\c!inbetween=\blank,
+ \c!frame=,\c!background=,\c!backgroundcolor=,
+ #2]%
+ \def\@@ipname{#1}%
+ \@@ipbefore
+ \expandcheckedcsname{\??ip::\c!alternative:}\@@ipalternative\v!b
+ \@@ipafter
+ \egroup}
+
+\setvalue{\??ip::\c!alternative:\v!a}%
+ {\globallet\combinedpagescounter\@@ipstart
+ \doloop
+ {\vbox to \textheight
+ {\hsize\textwidth % ? ?
+ \scratchdimen\@@ipdistance
+ \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
+ \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax
+ \dorecurse\@@ipny
+ {\hbox to \hsize
+ {\dorecurse\@@ipnx
+ {\vbox to \!!heighta
+ {\hsize\!!widtha
+ \vsize\!!heighta
+ \@@iptop
+ \hbox to \hsize
+ {\@@ipleft
+ \ifnum\combinedpagescounter>\@@ipstop\relax
+ \globallet\@@ipn\!!zerocount
+ \else\ifnum\combinedpagescounter>\@@ipn \else
+ \externalfigure[\@@ipname]
+ [\c!object=\v!no,
+ \c!page=\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\@@ipbackground,
+ \c!backgroundcolor=\@@ipbackgroundcolor,
+ \c!frame=\@@ipframe]%
+ \fi\fi
+ \@@ipright}
+ \@@ipbottom}%
+ \doglobal\increment\combinedpagescounter
+ \hfil}%
+ \hfilneg}
+ \vfil}%
+ \vfilneg}%
+ \page
+ \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}}
+
+\setvalue{\??ip::\c!alternative:\v!c}%
+ {\globallet\combinedpagescounter\@@ipstart
+ \doloop
+ {\vbox to \textheight
+ {\hsize\textwidth % ? ?
+ \scratchdimen\@@ipdistance
+ \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
+ \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax
+ \hbox to \hsize
+ {\dorecurse\@@ipnx
+ {\@@ipleft
+ \vbox to \textheight
+ {\hsize\!!widtha
+ {\dorecurse\@@ipny
+ {\@@iptop
+ \hbox to \hsize
+ {\vbox to \!!heighta
+ {\hsize\!!widtha
+ \vsize\!!heighta
+ \ifnum\combinedpagescounter>\@@ipstop\relax
+ \globallet\@@ipn\!!zerocount
+ \else\ifnum\combinedpagescounter>\@@ipn \else
+ \externalfigure[\@@ipname]
+ [\c!object=\v!no,
+ \c!page=\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\@@ipbackground,
+ \c!backgroundcolor=\@@ipbackgroundcolor,
+ \c!frame=\@@ipframe]%
+ \fi\fi}}
+ \doglobal\increment\combinedpagescounter
+ \@@ipbottom}%
+ \vfil}%
+ \vfilneg}
+ \hfil}%
+ \hfilneg}}
+ \page
+ \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}}
+
+\setvalue{\??ip::\c!alternative:\v!horizontal}{\getvalue{\??ip::\c!alternative:\v!a}}
+\setvalue{\??ip::\c!alternative:\v!vertical }{\getvalue{\??ip::\c!alternative:\v!c}}
+
+\setvalue{\??ip::\c!alternative:\v!b}%
+ {\globallet\combinedpagescounter\@@ipstart
+ \doloop
+ {\startbaselinecorrection
+ \scratchdimen\@@ipdistance
+ \!!widtha\dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
+ \hbox to \hsize
+ {\dorecurse\@@ipnx
+ {\doglobal\increment\combinedpagescounter
+ \ifnum\combinedpagescounter>\@@ipn \else
+ \normalexpanded{\noexpand\externalfigure[\@@ipname]
+ [\c!page=\combinedpagescounter,
+ \c!width=\the\!!widtha,% todo \freezedimenmacro
+ \c!background=\@@ipbackground,
+ \c!backgroundcolor=\@@ipbackgroundcolor,
+ \c!frame=\@@ipframe]}%
+ \hfill
+ \fi}\hfillneg}%
+ \stopbaselinecorrection
+ \ifnum\combinedpagescounter<\@@ipn\relax
+ \@@ipinbetween
+ \else
+ \exitloop
+ \fi}}
+
+%D \macros
+%D {setuppagecomment,startpagecomment}
+%D
+%D This command is not yet documented. Usage:
+%D
+%D \starttyping
+%D \setuppagecomment[state=start,location=right]
+%D
+%D \startpagecomment
+%D \input knuth
+%D \stoppagecomment
+%D \stoptyping
+
+\unexpanded\def\setuppagecomment
+ {\dosingleempty\dosetuppagecomment}
+
+\def\dosetuppagecomment[#1]%
+ {\getparameters[\??pc][#1]%
+ \doifelse\@@pcstate\v!start
+ {\doifinsetelse\@@pclocation{\v!bottom,\v!top}
+ {\setuppapersize[\c!left=\hskip\@@pcoffset]%
+ \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcheight\relax}%
+ \edef\@@pcpaperwidth {\the\dimexpr\paperwidth+\@@pcoffset+\@@pcoffset\relax}%
+ \defineoverlay[\v!pagecomment][\placepagecommentTB]}
+ {\setuppapersize[\c!top=\vskip\@@pcoffset]%
+ \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset\relax}%
+ \edef\@@pcpaperwidth {\the\dimexpr\paperwidth+\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcwidth\relax}%
+ \defineoverlay[\v!pagecomment][\placepagecommentLR]}%
+ \processaction
+ [\@@pclocation]
+ [ \v!bottom=>{\setuppapersize[\c!bottom =\vss,\c!top =\vskip\@@pcoffset]},
+ \v!top=>{\setuppapersize[\c!top =\vss,\c!bottom =\vskip\@@pcoffset]},
+ \v!left=>{\setuppapersize[\c!left =\hss,\c!right=\hskip\@@pcoffset]},
+ \v!right=>{\setuppapersize[\c!right=\hss,\c!left =\hskip\@@pcoffset]}]%
+ \definepapersize
+ [\v!pagecomment]
+ [\c!height=\@@pcpaperheight,
+ \c!width=\@@pcpaperwidth]%
+ \let\@@pcprintpapersize\printpapersize
+ \setuppapersize[\papersize][\v!pagecomment]%
+ \setupbackgrounds[\v!paper][\c!background=\v!pagecomment]}
+ {\doif\@@pcstate\v!stop % else initialization invokes backgrounds
+ {% this should be tested first
+ % \normalexpanded{\noexpand\setuppapersize[\papersize][\@@pcprintpapersize]}%
+ \setupbackgrounds[\v!paper][\c!background=]}}}
+
+\def\@@pcprintpapersize{\printpapersize}
+
+\unexpanded\def\placepagecommentTB
+ {\vbox to \printpaperheight
+ {%\forgetall
+ \hsize\printpaperwidth
+ \vskip\@@pcoffset
+ \doifelse\@@pclocation\v!bottom{\vskip\dimexpr\paperheight+\@@pcdistance\relax}\vss
+ \hskip\@@pcoffset
+ \vbox to \@@pcheight
+ {%\forgetall
+ \hsize\paperwidth
+ \ifpagecomment
+ \getbuffer[\v!pagecomment]%
+ \global\pagecommentfalse
+ \fi}%
+ \hfill
+ \doifelse\@@pclocation\v!bottom\vss{\vskip\dimexpr\paperheight+\@@pcdistance\relax}%
+ \vskip\@@pcoffset}}
+
+\unexpanded\def\placepagecommentLR
+ {\hbox to \printpaperwidth
+ {\hskip\@@pcoffset
+ \doifelse\@@pclocation\v!right{\hskip\paperwidth\hskip\@@pcdistance}\hss
+ \vbox to \printpaperheight
+ {%\forgetall
+ \vskip\@@pcoffset
+ \hsize\@@pcwidth
+ \ifpagecomment
+ \getbuffer[\v!pagecomment]%
+ \global\pagecommentfalse
+ \fi
+ \vss}%
+ \doifelse\@@pclocation\v!right\hss{\hskip\paperwidth\hskip\@@pcdistance}%
+ \hskip\@@pcoffset}}
+
+\newif\ifpagecomment
+
+\setvalue{\e!start\v!pagecomment}%
+ {\global\pagecommenttrue
+ \dostartbuffer[\v!pagecomment][\e!start\v!pagecomment][\e!stop\v!pagecomment]}
+
+\setuppagecomment
+ [\c!state=, % \v!stop would invoke background calculation
+ \c!location=\v!bottom,
+ \c!offset=.5cm,
+ \c!distance=.5cm,
+ \c!height=5cm,
+ \c!width=10cm]
+
+% This macro cuts a page into n parts that can be pasted
+% together.
+
+\def\slicepages
+ {\dotripleempty\doslicepages}
+
+\def\doslicepages[#1][#2][#3]%
+ {\ifthirdargument
+ \dodoslicepages[#1][#2][#3]%
+ \else
+ \dodoslicepages[#1][#2][#2]%
+ \fi}
+
+\newcounter\slicedpagenumber
+
+\def\dodoslicepages[#1][#2][#3]%
+ {\bgroup
+ \dontcomplain
+ \globallet\slicedpagenumber\!!zerocount
+ \getfiguredimensions[#1]
+ \getparameters
+ [\??ip]
+ [\c!n=1,
+ \c!offset=\!!zeropoint,
+ \c!hoffset=\!!zeropoint,\c!voffset=\!!zeropoint,
+ \c!width=\figurewidth,\c!height=\figureheight,#2]
+ \ifnum\@@ipn>\zerocount
+ \definepapersize
+ [\s!dummy][\c!height=\@@ipheight,\c!width=\@@ipwidth]
+ \setuppapersize
+ [\s!dummy][\s!dummy]
+ \setuplayout
+ [\c!backspace=\!!zeropoint,\c!topspace=\!!zeropoint,
+ \c!height=\v!middle,\c!width=\v!middle,
+ \c!textdistance=\!!zeropoint,
+ \c!header=\!!zeropoint,\c!footer=\!!zeropoint]
+ \fi
+ \dorecurse\noffigurepages
+ {\global\let\slicedpagenumber\recurselevel
+ \ifnum\@@ipn>\plusone
+ \dorecurse\@@ipn
+ {\let\xslice\recurselevel
+ \dorecurse\@@ipn
+ {\let\yslice\recurselevel
+ \clip
+ [\c!nx=\@@ipn,\c!ny=\@@ipn,\c!x=\xslice,\c!y=\yslice]
+ {\scale
+ [\c!scale=\@@ipn000]
+ {\externalfigure[#1][\c!page=\slicedpagenumber]}}
+ \page}}
+ \else
+ \ifodd\slicedpagenumber\relax
+ \getparameters[\??ip][#2]
+ \else
+ \getparameters[\??ip][#3]
+ \fi
+ \hskip\@@ipoffset
+ \clip
+ [\c!hoffset=\@@iphoffset,\c!voffset=\@@ipvoffset,
+ \c!height=\@@ipheight,\c!width=\@@ipwidth]
+ {\externalfigure[#1][\c!page=\slicedpagenumber]}
+ \page
+ \fi}
+ \egroup}
+
+% \starttext \slicepages[slice1.pdf][n=3] \stoptext
+
+\protect \endinput
diff --git a/tex/context/base/page-ini.mkii b/tex/context/base/page-ini.mkii
new file mode 100644
index 000000000..816b7d944
--- /dev/null
+++ b/tex/context/base/page-ini.mkii
@@ -0,0 +1,1558 @@
+ %D \module
+%D [ file=page-ini,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Initializations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Initializations}
+
+% still a dutch/english mess
+
+%D This class of modules implements the output routines and
+%D floating body support. Although the modules are relatively
+%D new, the code herein is rather old. This reordering was
+%D needed when column sets were implemented and sharing code
+%D started to make sense.
+
+%D The history shows from the code, since both column
+%D mechanism use a different way of looping over columns.
+
+\unprotect
+
+\def\m!otr{otr}
+
+\chardef\normalpagebox=255
+
+\newbox\pagebox
+
+\ifx\recalculatelayout\undefined
+
+ \let \recalculatelayout \relax
+
+\fi
+
+\ifx\recalculatelogos\undefined
+
+ \let \recalculatelogos \relax
+ \let \addlogobackground \gobbleoneargument %
+
+\fi
+
+\ifx\recalculatebackgrounds\undefined
+
+ \let \recalculatebackgrounds \relax
+ \let \addmainbackground \gobbleoneargument %
+ \let \addtextbackground \gobbleoneargument %
+ \let \addpagebackground \gobbleoneargument %
+ \let \addprintbackground \gobbleoneargument %
+ \let \addstatusinfo \gobbleoneargument %
+
+\fi
+
+\ifx\realpageno\undefined
+
+ \countdef\realpageno = 0 \realpageno = 1
+ \countdef\userpageno = 1 \userpageno = 1
+ \countdef\subpageno = 2 \subpageno = 0 % !!
+ \countdef\arrangeno = 3 \arrangeno = 0 % !!
+
+ \let\pageno\userpageno
+
+\fi
+
+\ifx\realfolio\undefined
+
+ \def\realfolio{\the\realpageno}
+
+\fi
+
+\newcount\nofshipouts
+
+\appendtoks
+ \global\advance\nofshipouts\plusone
+\to \everyaftershipout
+
+% principle:
+%
+% multiple otr's
+%
+% (1) single column, simple routine (old one)
+% (2) multi column, collect and split routine (old one)
+% (3) multi column, page by page (new one, needed for taco)
+% (4) single column, spread handling (for fun)
+% (5) multi column, page by page, spread handling (as challenge)
+%
+% common components
+%
+% (1) float placement
+% (2) float flushing
+% (3) page body building
+% (4) ...
+%
+% ort
+%
+% + balancing
+% - mixed / one / multi / balancetofit
+% + backgrounds
+% + pre / post
+% + distances / heights
+% + ragged / baseline / normal
+% - pos sync
+% - last page
+%
+% - itemize / subtexts -> old mechanism
+%
+% floats
+%
+% - top / bottom / side / page / column / spead
+% - flush / packed flush / current page / next page / area
+%
+% footnotes
+%
+% + carry over pre column / local to column
+% + last column / pre last column / each column
+% - multiple classes
+% - area / page / end
+%
+% areas
+%
+% - top / bottom / mid in spread
+%
+% IMPORTANT
+%
+% switchtobodyfont in between ivm top
+
+% floats:
+%
+% tricky in balancing mode, a la huidige multi columns
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+% messages moved
+
+\ifx\dosetuplayout\undefined % overloaded in page-lay !
+
+ \def\setuplayout{\dodoubleempty\getparameters[\??ly]}
+
+\fi
+
+\ifx\mkprocesscolumncontents\undefined\let\mkprocesscolumncontents\gobbleoneargument\fi
+\ifx\mkprocesspagecontents \undefined\let\mkprocesspagecontents \gobbleoneargument\fi
+\ifx\mkprocessboxcontents \undefined\let\mkprocessboxcontents \gobbleoneargument\fi
+
+\def\normalejectpenalty{-\plustenthousand } \let\ejectpenalty\normalejectpenalty
+\def\normalsuperpenalty{-\plustwentythousand} \let\superpenalty\normalsuperpenalty
+
+%D In case we're not running \ETEX, we need to bypass a
+%D couple of primitives.
+
+% ONE = single column
+% MUL = multi column
+% SET = columns sets
+
+\def\@@OTR{OTR}
+
+\let\OTRdefault\empty
+
+\def\OTRcommand#1%
+ {\csname\@@OTR
+ \ifcsname\@@OTR\OTRidentifier\strippedcsname#1\endcsname
+ \OTRidentifier
+ \else\ifcsname\@@OTR\OTRdefault\strippedcsname#1\endcsname % fallback
+ \OTRdefault
+ \fi\fi
+ \strippedcsname#1\endcsname}
+
+% obsolete
+
+\def\installotr#1% andere naam, beter \connectotr of zo
+ {\def\OTRidentifier{#1}}
+
+\def\activateotr#1#2%
+ {\def\OTRidentifier{#1}%
+ \def\OTRdefault {#2}}
+
+%D The initialization of the \type {\hsize} and \type {\vsize}
+%D depends on the OTR used.
+
+\def\setvsize {\OTRcommand\setvsize}
+\def\sethsize {\OTRcommand\sethsize}
+\def\finalsidefloatoutput {\OTRcommand\finalsidefloatoutput}
+\def\dopagecontents {\OTRcommand\dopagecontents}
+
+\def\dosettopinserts {\OTRcommand\dosettopinserts}
+\def\dosetbotinserts {\OTRcommand\dosetbotinserts}
+\def\dotopinsertions {\OTRcommand\dotopinsertions}
+\def\dobotinsertions {\OTRcommand\dobotinsertions}
+\def\dosetbothinserts {\OTRcommand\dosetbothinserts}
+
+\def\doflushfloats {\OTRcommand\doflushfloats}
+\def\flushfloatbox {\OTRcommand\flushfloatbox}
+\def\docheckiffloatfits {\OTRcommand\docheckiffloatfits}
+
+\def\someherefloat {\OTRcommand\someherefloat}
+\def\somefixdfloat {\OTRcommand\somefixdfloat}
+\def\somepagefloat {\OTRcommand\somepagefloat}
+\def\sometopsfloat {\OTRcommand\sometopsfloat}
+\def\somebotsfloat {\OTRcommand\somebotsfloat}
+\def\somesidefloat {\OTRcommand\somesidefloat}
+
+\def\flushsavedfloats {\OTRcommand\flushsavedfloats}
+
+\def\synchronizehsize {\OTRcommand\synchronizehsize}
+
+\def\gotonextpage {\OTRcommand\gotonextpage }
+\def\gotonextpageX{\OTRcommand\gotonextpageX} % will become obsolete
+
+% beter een \installotr#1 met #1 = macro en auto test
+
+\newif \iftraceotr
+\newif \ifinotr
+\newtoks \mainoutput
+\newcount\otrlevel
+
+% When issuing two \par\penalty-\plustenthousand's, only the first
+% triggers the otr; obscure feature or optimization?
+
+\def\outputcounter{-100010} % -10010
+
+\def\doinvokeoutput
+ {\iftraceotr
+ \expandafter\dodotracedoutput
+ \else
+ \expandafter\dodoinvokeoutput
+ \fi}
+
+\def\outputmessage#1#2#3%
+ {\iftraceotr\writestatus\m!otr{#1 #2 \number#3}\fi}
+
+\def\dodoinvokeoutput#1%
+ {\outputmessage+{special}{#1}%
+ \bgroup\par\penalty#1\relax\egroup
+ \outputmessage-{special}{#1}}
+
+\def\dodotracedoutput#1%
+ {\outputmessage+{traced}{#1/\the\outputpenalty}%
+ \writestatus\m!otr{c:\number\mofcolumns,v:\the\vsize,g:\the\pagegoal,t:\the\pagetotal}%
+ \dodoinvokeoutput{#1}%
+ \writestatus\m!otr{c:\number\mofcolumns,v:\the\vsize,g:\the\pagegoal,t:\the\pagetotal}%
+ \outputmessage-{traced}{#1/\the\outputpenalty}}
+
+\def\installoutput#1#2% \invoke \action
+ {\decrement\outputcounter
+ \edef#1{\noexpand\doinvokeoutput{\outputcounter}}%
+ \setvalue{\@@OTR\outputcounter}{#2}}
+
+\def\invokeoutputroutine
+ {\outputmessage+{trying}\outputpenalty
+ \executeifdefined{\@@OTR\the\outputpenalty}\dodonormaloutput
+ \outputmessage-{trying}\outputpenalty}
+
+\def\dodonormaloutput
+ {\outputmessage+{normal}\outputpenalty
+ \the\OTRcommand\output
+ \outputmessage-{normal}\outputpenalty}
+
+\mainoutput{\invokeoutputroutine} \output{\inotrtrue\the\mainoutput}
+
+%D Some hooks:
+
+\output{\inotrtrue\the\everybeforeoutput\the\mainoutput\the\everyafteroutput}
+
+\ifx\pagediscards\undefined \let\pagediscards\relax \fi
+
+\installoutput\synchronizeoutput % maybe add pagediscards
+ {\ifvoid\normalpagebox\else
+ \unvbox\normalpagebox
+ \pagediscards % maybe not needed ?
+ \fi}
+
+\installoutput\discardpage
+ {\setbox\scratchbox\box\normalpagebox}
+
+%D In order to force consistent use of variables, we
+%D predefine a lot of them here.
+
+%D The next two registers can be used to store pre column
+%D material as well as footnotes or so.
+
+\newbox\precolumnbox \newdimen\precolumnboxheight
+\newbox\postcolumnbox \newdimen\postcolumnboxheight
+
+%D We reserve a counter for the number of columns as well as
+%D the current column. Both are not to be changed by users!
+
+\newcount\nofcolumns \nofcolumns = 1
+\newcount\mofcolumns \mofcolumns = 1
+
+\chardef\maxnofcolumns = 50
+\chardef\allocatednofcolumns = 0
+
+%D The next dimensions reports the final column height
+
+\newdimen\finalcolumnheights
+\newcount\finalcolumnlines
+
+%D During initialization the temporary boxes are allocated.
+%D This enables us to use as much columns as we want, without
+%D exhausting the pool of boxes too fast. We could have packed
+%D them in one box, but we've got enough boxes.
+%D
+%D Two sets of boxes are declared, the txtboxes are used for
+%D the text, the topboxes are for moved column floats.
+
+\def\@col@{@col@}
+
+\def\initializecolumns#1%
+ {\ifnum#1>\maxnofcolumns
+ \showmessage\m!columns1\maxnofcolumns
+ \nofcolumns\maxnofcolumns
+ \else
+ \nofcolumns#1\relax
+ \fi
+ \ifnum\nofcolumns>\allocatednofcolumns
+ \dorecurse\nofcolumns
+ {\ifnum\recurselevel>\allocatednofcolumns\relax
+ % \newbox\next \letgvalue{\@col@-\recurselevel-t}=\next
+ \@EA\newbox\csname\@col@-\recurselevel-t\endcsname % text
+ \@EA\newbox\csname\@col@-\recurselevel-f\endcsname % foot
+ \@EA\newbox\csname\@col@-\recurselevel-h\endcsname % top insert
+ \@EA\newbox\csname\@col@-\recurselevel-l\endcsname % top insert
+ \fi}%
+ \global\chardef\allocatednofcolumns=\nofcolumns
+ \fi}
+
+\def\firstcolumnbox {\columntextbox\plusone}
+\def\currentcolumnbox {\columntextbox\mofcolumns}
+\def\lastcolumnbox {\columntextbox\nofcolumns}
+
+\def\firsttopcolumnbox {\columntopbox \plusone}
+\def\currenttopcolumnbox{\columntopbox \mofcolumns}
+\def\lasttopcolumnbox {\columntopbox \nofcolumns}
+
+\def\columntextbox#1{\csname\@col@-\number#1-t\endcsname}
+\def\columnfootbox#1{\csname\@col@-\number#1-f\endcsname}
+\def\columntopbox #1{\csname\@col@-\number#1-h\endcsname}
+\def\columnbotbox #1{\csname\@col@-\number#1-l\endcsname}
+
+\def\columnsettextbox{\global\setbox\columntextbox}
+\def\columnsetfootbox{\global\setbox\columnfootbox}
+\def\columnsettopbox {\global\setbox\columntopbox}
+\def\columnsetbotbox {\global\setbox\columnbotbox}
+
+\def\columngettextbox{\copy\columntextbox}
+\def\columngetfootbox{\copy\columnfootbox}
+\def\columngettopbox {\copy\columntopbox}
+\def\columngetbotbox {\copy\columnbotbox}
+
+\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}}
+\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}}
+\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}}
+\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}}
+
+%D Without going in details we present two macro's which handle
+%D the columns. The action which is transfered by the the first
+%D and only parameter can do something with \type
+%D {\currentcolumnbox}. In case of the mid columns, \type
+%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled
+%D outside these macro's.
+
+\def\dohandlecolumn#1%
+ {\mofcolumns\recurselevel
+ \let\currentcolumn\recurselevel
+ #1\relax}
+
+\def\dohandleallcolumns#1%
+ {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
+
+\def\dohandlerevcolumns#1%
+ {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
+
+\def\dohandlemidcolumns#1%
+ {\dohandleallcolumns
+ {\ifnum\recurselevel>\plusone
+ \ifnum\recurselevel<\nofcolumns
+ \dohandlecolumn{#1}%
+ \fi
+ \fi}}
+
+%D This register can be used as a temporary storage for page
+%D content.
+
+\newbox\restofpage
+
+%D Features.
+
+\newif\ifintermediatefootnotes
+\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
+\newif\iflastcolumnfootnotes %\lastcolumnfootnotestrue
+\newif\ifbalancecolumns %\balancecolumnstrue
+\newif\ifbalancetoheight %\balancetoheighttrue
+\newif\ifforcecolumngrid \forcecolumngridtrue
+\newif\ifstretchcolumns \stretchcolumnsfalse
+\newif\ifinheritcolumns \inheritcolumnsfalse
+\newif\ifheightencolumns \heightencolumnsfalse
+
+\newif\ifbalancingcolumns
+\newif\ifcollectingcontent
+\newif\ifcolumnoverflow
+\newif\iffinalflushingfloats
+\newif\ifpackflushedfloats \packflushedfloatstrue % for the moment
+
+\newdimen\intercolumnwidth
+\newdimen\localcolumnwidth
+\newdimen\savedpagetotal
+
+\chardef\columndirection=0 % 0:lr 1:rl
+
+\def\minbalancetoplines {1}
+\def\minfreecolumnlines {2}
+
+\newif\ifrecentercolumnbox \recentercolumnboxtrue
+\newif\ifrerecentercolumnbox \rerecentercolumnboxtrue
+\newif\ifpackcolumnfloats \packcolumnfloatstrue
+
+\newbox\collectedpagefloats
+\newbox\collectedleftpagefloats
+\newbox\collectedrightpagefloats
+
+%D The \type {\ifdim} test is needed, because otherwise the
+%D last line of a text end up on top of the baseline instead of
+%D on the baseline, as is the case with preceding pages.
+%D Also, a \type {\vfil} better than a \type {\vfill}.
+
+% to be replaced by \page[now] \page[final] / merged
+
+% \def\eject {\par\penalty-\plustenthousand } % == {\par\break} % plain
+% \def\supereject {\par\penalty-\plustwentythousand} % also plain
+
+\def\eject {\par\ifvmode\penalty\ejectpenalty\fi\resetpagebreak} % == {\par\break} % plain
+\def\supereject {\par\ifvmode\penalty\superpenalty\fi\resetpagebreak} % also plain
+
+\def\doejectpage {\par\ifvmode\ifdim\pagetotal>\pagegoal\else\normalvfil\fi\fi} % pg set to \textheight
+\def\ejectpage {\doejectpage\eject}
+\def\superejectpage{\doejectpage\supereject}
+
+\ifx\bye\undefined \def\bye{\par\vfill\supereject\end} \fi % plain tex command
+
+% floats
+%
+% \def\ejectinsert
+% {\flushnotes
+% \bgroup
+% \noftopfloats\plusthousand
+% \nofbotfloats\zerocount
+% \doflushfloats
+% \egroup}
+
+\def\ejectinsert
+ {\flushnotes
+ \bgroup
+ \noftopfloats\plusthousand
+ \nofbotfloats\zerocount
+ % this is needed in case a float that has been stored
+ % ends up at the current page; this border case occurs when
+ % the calculated room is 'eps' smaller that the room available
+ % when just flushing; so now we have (maybe optional):
+ \pagebaselinecorrection
+ % alas, this is tricky but needed (first surfaced in prikkels)
+ \doflushfloats
+ \egroup}
+
+\def\ejectdummypage
+ {\endgraf \ifvmode
+ \ejectinsert
+ \hardespatie % will be different
+ \vfill
+ \gotonextpage
+ \fi}
+
+\def\beforefinaloutput
+ {}
+
+\def\afterfinaloutput
+ {\forgetall
+ \vskip\zeropoint\relax
+ \ifvoid\normalpagebox \else
+ \unvbox\normalpagebox
+ \penalty\outputpenalty
+ \fi
+ % not really needed, replaced by \flushsavedfloats
+ \ifnum\outputpenalty>\superpenalty \else % better use a proper otr signal
+ \dosupereject
+ \fi
+ % but does not hurt either (we're still in the otr!)
+ \inpagebodytrue % needed for enabling \blank !
+ \flushsavedfloats % was \dosetbothinserts; only otr one !
+ \setvsize % this is needed for interacting components, like floats and multicolumns
+ \adaptfuzzypagegoal} % watch this hack!
+
+\def\dofinaloutput#1#2% \vbox: prevents spurious spaces in every..pagebody
+ {\beforefinaloutput
+ \the\everybeforeshipout % brrr not in shipout
+ \ifspecialbasedsettings
+ \myshipout{\hbox{\hbox to \zeropoint{\the\pageboundsettings}%
+ \hbox{\vbox{\dopagebody#1#2\setpagecounters}}}}%
+ \else
+ \the\pageboundsettings
+ \myshipout{\hbox{\vbox{\dopagebody#1#2\setpagecounters}}}%
+ \fi
+ \the\everyaftershipout
+ \afterfinaloutput
+ \popproperties} % ... and here ...
+
+\def\donofinaloutput#1#2%
+ {\beforefinaloutput
+ \the\everybeforeshipout
+ \setpagecounters
+ \message{[-\the\realpageno]}%
+ \setbox\scratchbox\hbox
+ {%\the\everyshipout % still needed here ?
+ \dopagebody#1#2}%
+ \deadcycles\zerocount
+ \gotonextrealpage
+ \the\everyaftershipout
+ \afterfinaloutput
+ \popproperties} % ... and here
+
+% beware: \ifprocessingpages is in use
+
+\ifx\checkpageversion\undefined \let\checkpageversion\relax \fi % todo: hook into \everybeforeshipout
+\ifx\doflushspread \undefined \let\doflushspread \relax \fi % todo
+
+\def\finaloutput#1#2%
+ {\checkpageversion
+ \ifprocessingpages
+ \ifpageselected
+ \@EAEAEA\dofinaloutput
+ \else
+ \@EAEAEA\donofinaloutput
+ \fi
+ \else
+ \ifpageselected
+ \@EAEAEA\donofinaloutput
+ \else
+ \@EAEAEA\dofinaloutput
+ \fi
+ \fi#1#2%
+ \resetselectiepagina
+ \incrementpagenumber
+ \checkpagedimensions
+ \ifnum\outputpenalty>\superpenalty \else
+ \dosupereject
+ \fi
+ \doflushspread
+ \dopostponeblock}
+
+\def\dooutput
+ {\finaloutput\unvbox\normalpagebox}
+
+\maxdeadcycles=1000
+
+% will be installable tracer; better use chardef
+
+% this needs a real cleanup
+
+\def\doplaceversiontext#1#2%
+ {\doifsomething{#2}
+ {\defconvertedcommand\ascii{#2}%
+ \space#1:\space\ascii\space
+ \!!doneatrue}}
+
+\def\placeversioninfo % nog engels maken
+ {\ifcase\conceptmode
+ % 0 : nothing
+ \or
+ % 1 : simple
+ \vskip\!!sixpoint
+ \hbox to \makeupwidth
+ {\infofont
+ \v!concept:\space\currentdate
+ \hss\reportpagedimensions}%
+ \else
+ % 2/3 : extensive
+ \vskip\!!sixpoint
+ \hbox to \makeupwidth
+ {\infofont
+ \getmessage\m!systems{27}:\space\currentdate\space
+ \doplaceversiontext\v!project \currentproject
+ \doplaceversiontext\v!product \currentproduct
+ \doplaceversiontext\v!component\currentcomponent
+ \if!!donea\else\space\v!file:\space\jobname\fi
+ \hss\reportpagedimensions}%
+ \fi}
+
+% tot hier
+
+\def\doversion[#1]%
+ {\chardef\conceptmode\zerocount
+ \overfullrule\zeropoint
+ \processaction % \v!final=>
+ [#1]
+ [ \v!concept=>\chardef\conceptmode\plusone, % simple banner
+ \v!file=>\chardef\conceptmode\plustwo, % full banner
+ \v!temporary=>\chardef\conceptmode\plusthree % full banner plus
+ \overfullrule5\points]} % info in the margin
+
+\def\version
+ {\dosingleargument\doversion}
+
+\def\addstatusinfo
+ {\ifcase\conceptmode
+ \@EA\gobbleoneargument
+ \else
+ \@EA\doaddstatusinfo
+ \fi}
+
+\def\doaddstatusinfo#1%
+ {\setbox#1\vbox to \paperheight
+ {\vsmashbox#1\box#1%
+ \offinterlineskip
+ \vskip\topspace
+ \hsize\paperwidth
+ \hfill\hbox{\placetestinfo\hskip.5cm}\vss
+ \settexthoffset\hskip\texthoffset % brrrr
+ %\tlap{\placeversioninfo}\vskip.5cm
+ \vbox to 1cm{\vss\placeversioninfo\vss}}}
+
+\def\dotestinfo#1#2#3%
+ {\ifinpagebody\else\ifnum\conceptmode=\plusthree
+ \begingroup
+ \defconvertedcommand\ascii{#3}%
+ \xdef\extratestinfo
+ {#2\space\ascii}%
+ \gdef\totaltestinfo
+ {\global\setbox#1\vbox
+ {\unvbox#1\relax
+ \infofont \setupinterlinespace
+ \hbox
+ {\strut
+ \expanded{\doboundtext{\extratestinfo}{12em}{..}}%
+ \quad}}}%
+ \endgroup
+ \ifinner
+ \aftergroup\totaltestinfo
+ \else
+ \totaltestinfo
+ \fi
+ \fi\fi}
+
+% this will be inserts some day
+
+% \installinsertion\referenceinfobox
+% \installinsertion\registerinfobox
+% \installinsertion\floatinfobox
+
+\newbox\referenceinfobox
+\newbox\registerinfobox
+\newbox\floatinfobox
+
+\def\referenceinfo{\dotestinfo\referenceinfobox}
+\def\registerinfo {\dotestinfo\registerinfobox}
+\def\floatinfo {\dotestinfo\floatinfobox}
+
+\def\placetestinfo
+ {\vbox to \makeupheight
+ {\forgetall
+ \infofont
+ \hsize10em
+ \ifvoid\floatinfobox\else
+ \strut \getmessage\m!systems{24}%
+ \vskip\!!sixpoint
+ \unvbox\floatinfobox
+ \vskip\!!twelvepoint
+ \fi
+ \ifvoid\referenceinfobox\else
+ \strut \getmessage\m!systems{25}%
+ \vskip\!!sixpoint
+ \unvbox\referenceinfobox
+ \vskip\!!twelvepoint
+ \fi
+ \ifvoid\registerinfobox\else
+ \strut \getmessage\m!systems{26}%
+ \vskip\!!sixpoint
+ \unvbox\registerinfobox
+ \fi
+ \vss}}
+
+\version[\v!final]
+
+% bewaren tvb documentatie
+%
+% \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}}
+
+\newtoks\afterpage \newtoks\aftereverypage
+\newtoks\beforepage \newtoks\beforeeverypage
+
+\chardef\showgridstate=0
+
+\def\showgrid
+ {\dosingleempty\doshowgrid}
+
+\def\doshowgrid[#1]%
+ {\chardef\showgridstate \plusone % downward compatible default
+ \chardef\gridboxlinemode \plusone
+ \chardef\gridboxlinenomode\plusone
+ \processallactionsinset
+ [#1]%
+ [ \v!reset=>\chardef\showgridstate \zerocount,
+ \v!bottom=>\chardef\showgridstate \plusone,
+ \v!top=>\chardef\showgridstate \plustwo,
+ \v!none=>\chardef\gridboxlinemode \zerocount,
+ \v!all=>\chardef\gridboxlinemode \plusone,
+ \v!lines=>\chardef\gridboxlinemode \plustwo,
+ \v!frame=>\chardef\gridboxlinemode \plusthree,
+ \v!nonumber=>\chardef\gridboxlinenomode\zerocount,
+ \v!right=>\chardef\gridboxlinenomode\plusone,
+ \v!left=>\chardef\gridboxlinenomode\plustwo]}
+
+\def\buildpagebox#1%
+ {\setbox#1\vbox to \paperheight
+ {\hsize\paperwidth
+ \vskip\topspace
+ \doifbothsides
+ {\hskip\backspace}
+ {\hskip\backspace}
+ {\hskip\paperwidth \hskip-\backspace \hskip-\makeupwidth}%
+ \box#1}%
+ \dp#1\zeropoint}
+
+% \newif\ifpagebodyornaments \pagebodyornamentstrue
+%
+% \appendtoks
+% \global\pagebodyornamentstrue
+% \to \everyaftershipout
+
+\newif\ifarrangingpages \arrangingpagesfalse
+
+\chardef\pageornamentstate\zerocount % 0=on 1=one-off 2=always-off
+
+\def\pagebodyornamentstrue {\chardef\pageornamentstate\zerocount} % for a while
+\def\pagebodyornamentsfalse{\chardef\pageornamentstate\plusone} % for a while
+
+\appendtoks
+ \ifcase\pageornamentstate\or
+ \chardef\pageornamentstate\zerocount
+ \fi
+\to \everyaftershipout
+
+\let\poparrangedpages\relax
+\let\pusharrangedpage\relax
+
+\ifx\shiftprintpagebox\undefined
+ \let\shiftprintpagebox\gobbleoneargument
+ \let\shiftpaperpagebox\gobbleoneargument
+\fi
+
+\ifx\registerpageposition\undefined
+ \let\registerpageposition\gobbleoneargument
+\fi
+
+\def\reportarrangedpage#1%
+ {\showmessage\m!systems
+ {23}{\the\realpageno.\the\pageno\ifnum\subpageno>0 .\the\subpageno\fi,#1}}
+
+\newif\ifsavepagebody \newbox\savedpagebody
+
+% beware, \??ly is used before defined, i.e. bad module design
+
+\setuplayout[\c!method=\v!normal]
+
+\def\buildpagebody#1#2%
+ {\ifsavepagebody\global\setbox\savedpagebody\fi
+ \vbox
+ {\beginrestorecatcodes
+ \forgetall % igv problemen, check: \boxmaxdepth\maxdimen
+ \boxmaxdepth\maxdimen % new
+ \dontcomplain
+ % the following plugin uses and sets pagebox; beware: this
+ % will change and is for my (hh) personal experiments
+ \executeifdefined{\??ly\c!method\@@lymethod}%
+ {\getvalue{\??ly\c!method\v!normal}}#1#2%
+ % the finishing touch
+ \ifcase\pageornamentstate
+ \addpagebackground \pagebox
+ \fi
+ \registerpageposition\pagebox
+ \ifarrangingpages
+ \shiftpaperpagebox \pagebox % \v!paper
+ \else
+ \clippagebox \pagebox
+ \doifelse\@@lymarking\v!page
+ {\replicatepagebox \pagebox
+ \addpagecutmarks \pagebox}
+ {\addpagecutmarks \pagebox
+ \replicatepagebox \pagebox}%
+ \scalepagebox \pagebox
+ \mirrorpaperbox \pagebox
+ \orientpaperbox \pagebox
+ \addpagecolormarks \pagebox
+ \centerpagebox \pagebox
+ \addprintbackground\pagebox
+ \mirrorprintbox \pagebox
+ \orientprintbox \pagebox
+ \shiftprintpagebox \pagebox % \v!page
+ \offsetprintbox \pagebox
+ \negateprintbox \pagebox
+ \fi
+ \box\pagebox
+ \endrestorecatcodes}%
+ \ifsavepagebody\copy\savedpagebody\fi}
+
+\setvalue{\??ly\c!method\v!normal}#1#2%
+ {\setbox\pagebox\vbox
+ {\offinterlineskip
+ \ifcase\pageornamentstate
+ \bgroup % else footnotes get inconsistent font/baseline
+ \dostartattributes\??ly\c!style\c!color\empty
+ \offinterlineskip
+ \gettextboxes
+ \dostopattributes
+ \egroup
+ \fi
+ \getmainbox#1#2}% including footnotes
+ \ifcase\pageornamentstate
+ \addmainbackground \pagebox
+ \addlogobackground \pagebox
+ \fi
+ \buildpagebox \pagebox
+ \addstatusinfo \pagebox}
+
+\def\finishpagebox#1%
+ {\ifarrangingpages
+ \addpagecutmarks #1%
+ \addpagecolormarks#1%
+ \centerpagebox #1%
+ \mirrorprintbox #1%
+ \orientprintbox #1%
+ \offsetprintbox #1%
+ \negateprintbox #1%
+ \fi}
+
+\appendtoks \restoreglobalbodyfont \to \everybeforepagebody
+\appendtoks \restorecolumnsettings \to \everybeforepagebody
+
+\ifx\nestednewbox\undefined \newbox\nestednextbox \fi
+
+\prependtoks \let\nextbox\nestednextbox \to \everybeforepagebody
+
+\def\dopagebody#1#2%
+ {%\getallmarks % now in following token register
+ \the\everybeforepagebody
+ \starttextproperties
+ \gotonextsubpage % nog eens: als in pagina (tbv standaard opmaak)
+ \dontshowboxes % dan hier blokkeren en verderop resetten
+% \shipoutfacingpage
+ \checkreferences
+ \checkmargeblokken
+ \the\beforeeverypage
+ \flushtoks\beforepage
+ \inpagebodytrue\buildpagebody#1#2%
+ \flushtoks\afterpage
+ \the\aftereverypage
+ \resetpagebreak
+ %updatelistreferences % now in aftereverypage
+ \resetlayouttextlines % will go to \aftereverypage
+ \stoptextproperties
+ \the\everyafterpagebody}
+
+\newtoks\pageboundsettings
+
+\prependtoks \initializepaper \to \pageboundsettings
+
+% not here
+
+\newif\ifpagebreakdisabled \pagebreakdisabledfalse
+
+% \chardef\testpagemethod=0 % todo: \testnewpage[method=,lines=,voffset=]
+%
+% \def\testpage {\dotripleempty\dotestpage[\plusone]}
+% \def\testpageonly{\dotripleempty\dotestpage[\plustwo]}
+%
+% \def\dotestpage[#1][#2][#3]%
+% {%\relax % needed before \if
+% \endgraf
+% \ifpagebreakdisabled
+% % do nothing
+% \else
+% %ifnum#1=\plusone\synchronizeoutput\fi
+% \ifdim\pagegoal<\maxdimen \relax
+% \ifdim\pagetotal<\pagegoal \relax
+% \scratchdimen\lineheight
+% \multiply\scratchdimen#2\relax
+% \advance\scratchdimen \pagetotal
+% \ifdim\lastskip<\parskip
+% \advance\scratchdimen \parskip
+% \fi
+% \ifthirdargument
+% \advance\scratchdimen#3\relax
+% \fi
+% \ifcase\testpagemethod
+% \ifdim\scratchdimen>.99\pagegoal
+% \vfill\eject % \penalty-\!!tenthousand\relax
+% \fi
+% \or
+% \advance\scratchdimen-\pagegoal
+% \ifdim\scratchdimen>-\lineheight
+% \vfill\eject % \penalty-\!!tenthousand\relax
+% \fi
+% \or
+% \getnoflines\pagegoal
+% \advance\scratchdimen-\noflines\lineheight \relax
+% \ifdim\scratchdimen>-\lineheight
+% \vfill\eject % \penalty-\!!tenthousand\relax
+% \fi
+% \or % same as 0 but more accurate
+% \advance\scratchdimen-10\s!sp\relax
+% \ifdim\scratchdimen>\pagegoal
+% \vfill\eject % \penalty-\!!tenthousand\relax
+% \fi
+% \fi
+% \else
+% % force page break / new
+% % \vfill\eject % \penalty-\!!tenthousand\relax
+% \fi
+% \else
+% \ifnum#1=\plusone\goodbreak\fi
+% \fi
+% \fi}
+
+\chardef\testpagemethod \zerocount % todo: \testnewpage[method=,lines=,voffset=]
+\chardef\testpagetrigger\zerocount
+
+\def\testpage {\dotripleempty\dotestpage[\plusone ]} %
+\def\testpageonly{\dotripleempty\dotestpage[\plustwo ]} % no penalties added to the mvl
+\def\testpagesync{\dotripleempty\dotestpage[\plusthree]} % force sync
+
+\def\dotestpage[#1][#2][#3]% don't change, only add more methods
+ {\relax % needed before \if
+ \ifpagebreakdisabled
+ \endgraf
+ \else
+ % new from here
+ \ifcase\testpagetrigger
+ \endgraf
+ \or
+ \ifvmode
+ \dosomebreak\allowbreak
+ \else % indeed?
+ \vadjust{\allowbreak}%
+ \endgraf
+ \fi
+ \fi
+ % till here
+ \ifdim\pagegoal<\maxdimen \relax
+ \ifdim\pagetotal<\pagegoal \relax
+ \scratchdimen\lineheight
+ \multiply\scratchdimen#2\relax
+ \advance\scratchdimen \pagetotal
+ \ifdim\lastskip<\parskip
+ \advance\scratchdimen \parskip
+ \fi
+ \ifthirdargument
+ \advance\scratchdimen#3\relax
+ \fi
+ \ifcase\testpagemethod
+ \ifdim\scratchdimen>.99\pagegoal
+ \penalty-\!!tenthousand\relax
+ \fi
+ \or
+ \advance\scratchdimen-\pagegoal
+ \ifdim\scratchdimen>-\lineheight
+ \penalty-\!!tenthousand\relax
+ \fi
+ \or
+ \getnoflines\pagegoal
+ \advance\scratchdimen-\noflines\lineheight \relax
+ \ifdim\scratchdimen>-\lineheight
+ \penalty-\!!tenthousand\relax
+ \fi
+ \or % same as 0 but more accurate
+ \advance\scratchdimen-10\s!sp\relax
+ \ifdim\scratchdimen>\pagegoal
+ \penalty-\!!tenthousand\relax
+ \fi
+ \fi
+ \else
+ \ifnum#1=\plusthree
+ \flushpagesofar
+ \fi
+ \fi
+ \else
+ \ifnum#1=\plusone\goodbreak\fi
+ \fi
+ \fi}
+
+\def\flushpagesofar
+ {\endgraf
+ \ifdim\pagetotal>\pagegoal
+ \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal
+ \goodbreak % \penalty0
+ \else
+ \page
+ \fi
+ \else
+ \fi}
+
+\def\testcolumn
+ {\dodoubleempty\dotestcolumn}
+
+\def\dotestcolumn[#1][#2]%
+ {%\relax % needed before \if !
+ \endgraf
+ \ifdim\pagegoal<\maxdimen \ifdim\pagetotal<\pagegoal % \relax
+ \scratchdimen\pagegoal
+ \advance\scratchdimen-\pagetotal
+ \ifdim\lastskip<\parskip
+ \advance\scratchdimen \parskip
+ \fi
+ \ifsecondargument
+ \advance\scratchdimen#2%
+ \fi
+ \getrawnoflines\scratchdimen % raw !
+ % \message{[\number#1>\number\noflines ?}\wait
+ \ifnum#1>\noflines
+ \column
+ \fi
+ \else
+ \penalty-\!!tenthousand % untested ! ! \column
+ \fi \fi}
+
+\let\resetcurrentsectionmarks\relax
+
+% was: \resetsectionmarks\firstsection, zie \handlepagebreak
+
+\def\page{\pagebreak} % the short form of \pagebreak (mult-com one)
+
+\def\resetpagebreak
+ {\global\pagebreakdisabledfalse}
+
+\def\simplifypagebreak
+ {\def\dopagebreak[##1]{\goodbreak}}
+
+\def\disablepagebreaks
+ {\def\dopagebreak[##1]{}}
+
+\def\executepagebreakhandler#1%
+ {\edef\@@pagespecification{#1}%
+ \doifdefinedelse{\??pe:\@@pagespecification}
+ {\getvalue{\??pe:\@@pagespecification}}
+ {\doifdefinedelse{\??pe::\@@pagespecification}
+ {\executepagebreakhandlers{\getvalue{\??pe::\@@pagespecification}}}
+ {\getvalue{\??pe:\s!unknown}}}}
+
+\long\def\installpagebreakhandler#1#2%
+ {\long\setvalue{\??pe:#1}{#2}}
+
+% \definecomplexorsimple\pagebreak
+
+% \def\simplepagebreak
+% {\executepagebreakhandler\v!ja}
+
+% \def\complexpagebreak[#1]% if empty, do nothing and avoid processing,
+% {\flushnotes % see head's; watch how we group
+% \doifsomething{#1}{\bgroup\executepagebreakhandlers{#1}\egroup}}
+
+\unexpanded\def\pagebreak
+ {\dosingleempty\dopagebreak}
+
+\def\dopagebreak[#1]% so, page ornaments are reset after a pagebreak command, unless set
+ {\bgroup
+ \edef\prevrealpageno{\the\realpageno}%
+ \ifcase\pageornamentstate \or
+ % disable reset after shipout
+ \global\chardef\pageornamentstate\plustwo
+ \fi
+ \iffirstargument % or if empty i.e. []
+ \flushnotes\executepagebreakhandlers{#1}%
+ \else % so, no pagebreak when \pagebreak[] ! ! !
+ \flushnotes\executepagebreakhandler\v!yes
+ \fi
+ \ifnum\prevrealpageno<\realpageno
+ \global\chardef\pageornamentstate\zerocount
+ \fi
+ \egroup}
+
+\def\executepagebreakhandlers#1%
+ {\processcommacommand[#1]\executepagebreakhandler}
+
+\installpagebreakhandler \s!dummy
+ {\ejectinsert
+ \gotonextpage
+ \ejectdummypage}
+
+\installpagebreakhandler \v!frame
+ {\page\bgroup\showframe\page[\v!empty]\egroup}
+
+\installpagebreakhandler \s!unknown
+ {\doifinstringelse{+}\@@pagespecification
+ {\ejectinsert
+ \gotonextpage
+ \dorecurse\@@pagespecification\ejectdummypage}
+ {\doifnumberelse\@@pagespecification
+ {\ejectinsert
+ \gotonextpage
+ \doloop
+ {\ifnum\userpageno<\@@pagespecification\relax
+ \ejectdummypage
+ \else
+ \exitloop
+ \fi}}
+ {}}}
+
+\installpagebreakhandler \s!default
+ {} % do nothing if empty
+
+\installpagebreakhandler \v!reset
+ {% better not: \global\chardef\pageornamentstate\zerocount
+ \resetpagebreak}
+
+\installpagebreakhandler \v!disable
+ {\global\pagebreakdisabledtrue}
+
+\installpagebreakhandler \v!yes
+ {\ifpagebreakdisabled\else
+ \ejectinsert
+ \gotonextpage
+ \ifinsidecolumns % this will move to MUL
+ \ejectpage % anders soms geen overgang
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!makeup % ??
+ {\ifpagebreakdisabled\else
+ \eject
+ \fi}
+
+\installpagebreakhandler \v!blank
+ {\ifcase\pageornamentstate
+ \global\chardef\pageornamentstate\plusone
+ \fi}
+
+\installpagebreakhandler \v!no
+ {\ifpagebreakdisabled\else
+ \dosomebreak\nobreak
+ \fi}
+
+\installpagebreakhandler \v!preference
+ {\ifpagebreakdisabled\else
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[3][\zeropoint]%
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!bigpreference
+ {\ifpagebreakdisabled\else
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[5][\zeropoint]%
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!empty
+ {\ejectinsert
+ \gotonextpage
+ \doifnotvalue{\??tk\v!header\c!state}\v!stop{\setupheader[\c!state=\v!empty]}%
+ \doifnotvalue{\??tk\v!footer\c!state}\v!stop{\setupfooter[\c!state=\v!empty]}%
+ \ejectdummypage}
+
+\installpagebreakhandler \v!left
+ {\ejectinsert
+ \gotonextpageX % will become \gotonextpage
+ \doifbothsidesoverruled{}{\resetcurrentsectionmarks\ejectdummypage}{}}
+
+\installpagebreakhandler \v!right
+ {\ejectinsert
+ \gotonextpageX % will become \gotonextpage
+ \doifbothsidesoverruled{}{}{\resetcurrentsectionmarks\ejectdummypage}}
+
+\installpagebreakhandler \v!even
+ {\page
+ \doifoddpageelse{\resetcurrentsectionmarks\ejectdummypage}\donothing}
+
+\installpagebreakhandler \v!odd
+ {\page
+ \doifoddpageelse\donothing{\resetcurrentsectionmarks\ejectdummypage}}
+
+\installpagebreakhandler \v!quadruple % not yet ok inside columnsets
+ {\ifdoublesided
+ \!!counta\realpageno
+ \!!countb\realpageno
+ \divide\!!counta 4
+ \divide\!!countb 2
+ \ifnum\!!counta=\!!countb
+ \else
+ \executepagebreakhandler\v!yes
+ \executepagebreakhandler\v!empty
+ \executepagebreakhandler\v!empty
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!last
+ {\ejectinsert
+ \gotonextpageX % will become \gotonextpage
+ \relax
+ \doifbothsidesoverruled
+ {\shipoutfacingpage}
+ {}
+ {\noheaderandfooterlines \ejectdummypage}%
+ \filluparrangedpages}
+
+\installpagebreakhandler \v!lastpage % handy for backpage preceded by empty pages
+ {\executepagebreakhandler\v!yes
+ \ifdoublesided
+ \executepagebreakhandler\v!left
+ \executepagebreakhandler\v!empty
+ \executepagebreakhandler\v!empty
+ \fi}
+
+\installpagebreakhandler \v!start
+ {\globallet\shipout\normalshipout}
+
+\installpagebreakhandler \v!stop
+ {\globallet\shipout\noshipout}
+
+% nb: \executepagebreakhandler\v!hoofd in other ones
+
+\installpagebreakhandler \v!header
+ {\doifnotvalue{\??tk\v!header\c!state}\v!stop{\setupheader[\c!state=\v!empty]}}
+
+\installpagebreakhandler \v!footer
+ {\doifnotvalue{\??tk\v!footer\c!state}\v!stop{\setupfooter[\c!state=\v!empty]}}
+
+% \definepagebreak
+% [chapter]
+% [yes,header,right]
+%
+% \setuphead
+% [chapter]
+% [page=chapter,
+% header=empty,
+% footer=chapter]
+%
+% \definepagebreak % untested
+% [lastpage]
+% [left,{empty,right},{empty,left}]
+
+% public page handler, beware: definepage already in use (core-ref)
+%
+% \definepagebreak[instance][forsure]
+% \definepagebreak[forsure][yes,+4]
+
+\def\definepagebreak
+ {\dodoubleargument\dodefinepagebreak}
+
+\def\dodefinepagebreak[#1][#2]% non recursive, meant for simple mappings
+ {\setvalue{\??pe::#1}{#2}}
+
+% hier nog uti blokkeren
+
+% don't change this / test case:
+%
+% \setupbackgrounds[state=repeat]
+% \setupbackgrounds[text][text][background=whatever]
+% \couplepage[chapter][before={\defineoverlay[whatever][ON]}]
+% \setuphead[chapter][before={\pagetype[chapter]}]
+% \chapter{First} \page test \chapter{second} \page test
+
+\long\def\installcolumnbreakhandler#1#2#3% #1=otr-id #2=tag
+ {\long\setvalue{\??cn:#1:#2}{#3}}
+
+\def\definecolumnbreak
+ {\dodoubleargument\dodefinecolumnbreak}
+
+\def\dodefinecolumnbreak[#1][#2]% non recursive, meant for simple mappings
+ {\setvalue{\??cn::#1}{#2}}
+
+%\def\columnbreak
+% {\dosingleempty\docolumnbreak}
+%
+%\def\docolumnbreak[#1]%
+% {\expanded{\nextcolumn[\executeifdefined{\??cn::#1}{#1}]}}
+
+\definecomplexorsimple\columnbreak
+
+\def\simplecolumnbreak
+ {\executecolumnbreakhandler\v!yes}
+
+\def\complexcolumnbreak[#1]% if empty, do nothing and avoid processing
+ {\doifsomething{#1}{\executecolumnbreakhandlers{#1}}}
+
+\def\executecolumnbreakhandlers#1%
+ {\processcommacommand[#1]\executecolumnbreakhandler}
+
+\def\executecolumnbreakhandler#1% here no commalist
+ {\edef\@@columnspecification{#1}%
+ \doifdefinedelse{\??cn:\OTRidentifier:\@@columnspecification}
+ {\getvalue{\??cn:\OTRidentifier:\@@columnspecification}}
+ {\doifdefinedelse{\??cn::\@@columnspecification}
+ {\executecolumnbreakhandlers{\getvalue{\??cn::\@@columnspecification}}}
+ {\getvalue{\??cn:\OTRidentifier:\s!unknown}}}}
+
+%let\nextcolumn\columnbreak
+\let\column \columnbreak
+
+% We don't want spurious last pages (due to left over marks):
+
+\def\noshipout
+ {\writestatus\m!systems{ignoring further shipouts}%
+ \global\advance\realpageno\minusone % else no flush of resources
+ \dowithnextbox{\deadcycles\zerocount}}
+
+% \def\doignorerestoftext
+% {\ifarrangingpages \else \ifnum\textlevel>\zerocount \else
+% \globallet\shipout\noshipout
+% \fi \fi}
+%
+% better:
+
+\def\doignorerestoftext
+ {\ifarrangingpages \else \ifnum\textlevel=\plusone
+ \globallet\shipout\noshipout
+ \fi \fi}
+
+\let\ignorerestoftext\donothing
+
+\prependtoks % only ignore in a symmetrical doc
+ \globallet\ignorerestoftext\doignorerestoftext
+\to \everystarttext
+
+% \appendtoks
+% \ignorerestoftext
+% \to \everylastshipout
+
+\newif\ifpageselected \pageselectedtrue
+\newif\ifselectingpages \selectingpagesfalse
+\newif\ifprocessingpages\processingpagestrue
+
+\let\pageselection \empty
+\let\currentpageselection\empty
+\let\aftershipout \relax
+\let\beforeshipout \relax
+
+\def\dodobeforeshipout#1%
+ {\global\let\beforeshipout\relax
+ \getvalue{\??pg#1\c!before}}
+
+\def\dobeforeshipout
+ {\doifsomething\currentpageselection
+ {\processcommacommand[\currentpageselection]\dodobeforeshipout}}
+
+\def\dododoaftershipout#1%
+ {\global\let\aftershipout\relax
+ \global\let\currentpageselection\empty
+ \getvalue{\??pg#1\c!after}}
+
+\def\dodoaftershipout#1%
+ {\doifelsevalue{\??pg#1\c!option}\v!doublesided
+ {\doifbothsidesoverruled
+ {\dododoaftershipout{#1}}
+ {\dododoaftershipout{#1}}
+ {}}
+ {\dododoaftershipout{#1}}}
+
+\def\doaftershipout
+ {\doifsomething\currentpageselection
+ {\processcommacommand[\currentpageselection]\dodoaftershipout}}
+
+% Dit wordt eigenlijk nooit en moet worden vervangen door
+% het meer algemene mechanisme.
+
+\def\dopagetype[#1]%
+ {\edef\desoortpagina{#1}%
+ \ifx\desoortpagina\empty \else
+ \@EA\doglobal\@EA\addtocommalist\@EA{\desoortpagina}\currentpageselection
+ \ifselectingpages
+ \fullexpandtwoargsafter\doifcommon\desoortpagina\pageselection
+ {\global\pageselectedtrue}%
+ \fi
+ \gdef\beforeshipout{\dobeforeshipout}%
+ \gdef\aftershipout {\doaftershipout}%
+ \fi}
+
+\def\pagetype
+ {\dosingleargument\dopagetype}
+
+\def\docouplepage[#1][#2]%
+ {\getparameters
+ [\??pg]
+ [\c!before=,
+ \c!after=,
+ \c!option=,
+ #2]%
+ \def\docommand##1%
+ {\getparameters
+ [\??pg##1]
+ [\c!before=\@@pgbefore,
+ \c!after=\@@pgafter,
+ \c!option=\@@pgoption]}%
+ \processcommalist[#1]\docommand}%
+
+\def\couplepage
+ {\dodoubleargument\docouplepage}
+
+\def\doprocesspage[#1][#2]%
+ {\processaction
+ [#2]
+ [\v!yes=>\global\processingpagestrue,
+ \v!no=>\global\processingpagesfalse]%
+ \gdef\pageselection{#1}%
+ \global\selectingpagestrue
+ \global\pageselectedfalse}
+
+\def\processpage
+ {\dodoubleargument\doprocesspage}
+
+\def\resetselectiepagina
+ {\ifselectingpages
+ \doifbothsidesoverruled{\global\pageselectedfalse}{}{\global\pageselectedfalse}%
+ \fi}
+
+\newif\ifregistertextareas
+\newif\iftracetextareas
+
+\newbox\registertextbox
+
+% \def\registeredtextarea#1#2#3% #1=lower-dp #2=correct-ht #3=box
+% {\hbox{\box#3}}
+
+\def\enabletextarearegistration{\global\registertextareastrue}
+
+\def\registeredtextarea#1#2#3% #1=lower-dp #2=correct-ht #3=box
+ {\hbox\bgroup
+ \ifregistertextareas \ifx\registerMPtextarea\undefined \else
+ \setbox\registertextbox\null
+ \wd\registertextbox\wd#3%
+ \ht\registertextbox\ht#3%
+ \dp\registertextbox\dp#3%
+ \ifcase#1\or % 1
+ \setbox\registertextbox\hbox{\lower\strutdp\box\registertextbox}%
+ \fi
+ \ifcase#2\or % 1
+ \setbox\registertextbox\hbox{\raise\topskip\hbox{\lower\strutht\box\registertextbox}}%
+ \dp\registertextbox\strutdp
+ \fi
+ \dp\registertextbox\strutdp % needed
+ %\setbox\registertextbox\hbox
+ % {\iftracetextareas\gray\boxrulewidth2pt\ruledhbox\fi
+ % {\registerMPtextarea{\box\registertextbox}}}%
+ \setbox\registertextbox\hbox
+ {\registerMPtextarea{\box\registertextbox}}%
+ \smashbox\registertextbox
+ \box\registertextbox
+ \fi \fi
+ \box#3%
+ \egroup}
+
+%D \macros
+%D {setupoppositeplacing,startopposite}
+%D
+%D \starttyping
+%D \starttext
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D \stoptext
+%D \stoptyping
+
+% Moved from page-mar.tex, made english, cleaned up, but still to be
+% redesigned
+
+\newbox\facingpage
+
+\def\setupoppositeplacing
+ {\dodoubleargument\getparameters[\??np]}
+
+\def\startopposite
+ {\dowithnextboxcontent
+ {\hsize\makeupwidth}%
+ {\global\setbox\facingpage\vbox
+ {\ifvoid\facingpage
+ \@@npbefore
+ \else
+ \@@npinbetween
+ \unvbox\facingpage
+ \fi
+ \box\nextbox}}%
+ \vbox\bgroup}
+
+\def\stopopposite
+ {\egroup}
+
+\def\finishfacingpage
+ {\ifvoid\facingpage\else
+ \global\setbox\facingpage\vbox to \makeupheight
+ {\unvbox\facingpage
+ \@@npafter
+ \vss}%
+ \fi}
+
+\def\shipoutfacingpage
+ {\doif\@@npstate\v!start
+ {\ifvoid\facingpage\else
+ \ifnum\realpageno>\plusone
+ \bgroup
+ \chardef\pageornamentstate\plusone
+ \finishfacingpage
+ \myshipout{\buildpagebody\box\facingpage}%
+ \egroup
+ \else
+ \global\setbox\facingpage\emptybox
+ \fi
+ \fi}}
+
+\setupoppositeplacing
+ [\c!state=\v!start,
+ \c!before=,
+ \c!inbetween=\blank,
+ \c!after=]
+
+\protect \endinput
diff --git a/tex/context/base/page-ini.mkiv b/tex/context/base/page-ini.mkiv
new file mode 100644
index 000000000..07d342282
--- /dev/null
+++ b/tex/context/base/page-ini.mkiv
@@ -0,0 +1,1512 @@
+%D \module
+%D [ file=page-ini,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Initializations,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Initializations}
+
+% still a dutch/english mess
+
+%D This class of modules implements the output routines and
+%D floating body support. Although the modules are relatively
+%D new, the code herein is rather old. This reordering was
+%D needed when column sets were implemented and sharing code
+%D started to make sense.
+
+%D The history shows from the code, since both column
+%D mechanism use a different way of looping over columns.
+
+\unprotect
+
+\def\m!otr{otr}
+
+\chardef\normalpagebox=255
+
+\newbox\pagebox
+
+\ifx\recalculatelayout\undefined
+
+ \let \recalculatelayout \relax
+
+\fi
+
+\ifx\recalculatebackgrounds\undefined
+
+ \let \recalculatebackgrounds \relax
+ \let \addmainbackground \gobbleoneargument %
+ \let \addtextbackground \gobbleoneargument %
+ \let \addpagebackground \gobbleoneargument %
+ \let \addprintbackground \gobbleoneargument %
+ \let \addstatusinfo \gobbleoneargument %
+
+\fi
+
+\ifx\realpageno\undefined
+
+ \countdef\realpageno = 0 \realpageno = 1
+ \countdef\userpageno = 1 \userpageno = 1
+ \countdef\subpageno = 2 \subpageno = 0 % !!
+ \countdef\arrangeno = 3 \arrangeno = 0 % !!
+
+ \let\pageno\userpageno
+
+\fi
+
+\ifx\realfolio\undefined
+
+ \def\realfolio{\the\realpageno}
+
+\fi
+
+\newcount\nofshipouts
+
+\appendtoks
+ \global\advance\nofshipouts\plusone
+\to \everyaftershipout
+
+% principle:
+%
+% multiple otr's
+%
+% (1) single column, simple routine (old one)
+% (2) multi column, collect and split routine (old one)
+% (3) multi column, page by page (new one, needed for taco)
+% (4) single column, spread handling (for fun)
+% (5) multi column, page by page, spread handling (as challenge)
+%
+% common components
+%
+% (1) float placement
+% (2) float flushing
+% (3) page body building
+% (4) ...
+%
+% ort
+%
+% + balancing
+% - mixed / one / multi / balancetofit
+% + backgrounds
+% + pre / post
+% + distances / heights
+% + ragged / baseline / normal
+% - pos sync
+% - last page
+%
+% - itemize / subtexts -> old mechanism
+%
+% floats
+%
+% - top / bottom / side / page / column / spead
+% - flush / packed flush / current page / next page / area
+%
+% footnotes
+%
+% + carry over pre column / local to column
+% + last column / pre last column / each column
+% - multiple classes
+% - area / page / end
+%
+% areas
+%
+% - top / bottom / mid in spread
+%
+% IMPORTANT
+%
+% switchtobodyfont in between ivm top
+
+% floats:
+%
+% tricky in balancing mode, a la huidige multi columns
+
+\ifx\dosetuplayout\undefined % overloaded in page-lay !
+
+ \unexpanded\def\setuplayout{\dodoubleempty\getparameters[\??ly]}
+
+\fi
+
+\ifx\mkprocesscolumncontents\undefined\let\mkprocesscolumncontents\gobbleoneargument\fi
+\ifx\mkprocesspagecontents \undefined\let\mkprocesspagecontents \gobbleoneargument\fi
+\ifx\mkprocessboxcontents \undefined\let\mkprocessboxcontents \gobbleoneargument\fi
+
+\def\normalejectpenalty{-\plustenthousand } \let\ejectpenalty\normalejectpenalty
+\def\normalsuperpenalty{-\plustwentythousand} \let\superpenalty\normalsuperpenalty
+
+%D In case we're not running \ETEX, we need to bypass a
+%D couple of primitives.
+
+% ONE = single column
+% MUL = multi column
+% SET = columns sets
+
+\def\@@OTR{OTR}
+
+\let\OTRdefault\empty
+
+% obsolete
+
+\def\installotr#1% andere naam, beter \connectotr of zo
+ {\def\OTRidentifier{#1}}
+
+% \def\OTRcommand#1%
+% {\csname\@@OTR
+% \ifcsname\@@OTR\OTRidentifier\strippedcsname#1\endcsname
+% \OTRidentifier
+% \else\ifcsname\@@OTR\OTRdefault\strippedcsname#1\endcsname % fallback
+% \OTRdefault
+% \fi\fi
+% \strippedcsname#1\endcsname}
+%
+% maybe faster but at least less tracing:
+
+\def\OTRcommand#1%
+ {\csname\@@OTR
+ \ifcsname\@@OTR\OTRidentifier\expandafter\gobbleoneargument\string#1\endcsname
+ \OTRidentifier
+ \else\ifcsname\@@OTR\OTRdefault\expandafter\gobbleoneargument\string#1\endcsname % fallback
+ \OTRdefault
+ \fi\fi
+ \expandafter\gobbleoneargument\string#1\endcsname}
+
+\def\activateotr#1#2%
+ {\def\OTRidentifier{#1}%
+ \def\OTRdefault {#2}}
+
+% variant that does a preset:
+
+\newtoks\registeredotrcommands
+
+\def\registerotrcommand#1%
+ {\appendtoks\dowithotrcommand#1\to\registeredotrcommands}
+
+\def\dopresetotrcommand#1%
+ {\expandafter\let\expandafter#1\csname\@@OTR
+ \ifcsname\@@OTR\OTRidentifier\expandafter\gobbleoneargument\string#1\endcsname
+ \OTRidentifier
+ \else\ifcsname\@@OTR\OTRdefault\expandafter\gobbleoneargument\string#1\endcsname % fallback
+ \OTRdefault
+ \fi\fi
+ \expandafter\gobbleoneargument\string#1\endcsname}
+
+\def\activateotr#1#2%
+ {\def\OTRidentifier{#1}%
+ \def\OTRdefault {#2}%
+ \let\dowithotrcommand\dopresetotrcommand
+ \the\registeredotrcommands}
+
+\appendtoks
+ \activateotr{ONE}{}%
+\to\everydump
+
+%D The initialization of the \type {\hsize} and \type {\vsize}
+%D depends on the OTR used.
+
+% todo: \registerotrcommand\output, is a toks
+
+\registerotrcommand\setvsize % \def\setvsize {\OTRcommand\setvsize}
+\registerotrcommand\sethsize % \def\sethsize {\OTRcommand\sethsize}
+\registerotrcommand\finalsidefloatoutput % \def\finalsidefloatoutput {\OTRcommand\finalsidefloatoutput}
+\registerotrcommand\dopagecontents % \def\dopagecontents {\OTRcommand\dopagecontents}
+\registerotrcommand\dosettopinserts % \def\dosettopinserts {\OTRcommand\dosettopinserts}
+\registerotrcommand\dosetbotinserts % \def\dosetbotinserts {\OTRcommand\dosetbotinserts}
+\registerotrcommand\dotopinsertions % \def\dotopinsertions {\OTRcommand\dotopinsertions}
+\registerotrcommand\dobotinsertions % \def\dobotinsertions {\OTRcommand\dobotinsertions}
+\registerotrcommand\dosetbothinserts % \def\dosetbothinserts {\OTRcommand\dosetbothinserts}
+\registerotrcommand\doflushfloats % \def\doflushfloats {\OTRcommand\doflushfloats}
+\registerotrcommand\flushfloatbox % \def\flushfloatbox {\OTRcommand\flushfloatbox}
+\registerotrcommand\docheckiffloatfits % \def\docheckiffloatfits {\OTRcommand\docheckiffloatfits}
+\registerotrcommand\flushsavedfloats % \def\flushsavedfloats {\OTRcommand\flushsavedfloats}
+\registerotrcommand\synchronizehsize % \def\synchronizehsize {\OTRcommand\synchronizehsize}
+\registerotrcommand\gotonextpage % \def\gotonextpage {\OTRcommand\gotonextpage }
+\registerotrcommand\gotonextpageX % \def\gotonextpageX {\OTRcommand\gotonextpageX} % will become obsolete
+
+% wrong, will be redone
+%
+% \registerotrcommand\someherefloat % \def\someherefloat {\OTRcommand\someherefloat}
+% \registerotrcommand\somefixdfloat % \def\somefixdfloat {\OTRcommand\somefixdfloat}
+% \registerotrcommand\somepagefloat % \def\somepagefloat {\OTRcommand\somepagefloat}
+% \registerotrcommand\sometopsfloat % \def\sometopsfloat {\OTRcommand\sometopsfloat}
+% \registerotrcommand\somebotsfloat % \def\somebotsfloat {\OTRcommand\somebotsfloat}
+% \registerotrcommand\somesidefloat % \def\somesidefloat {\OTRcommand\somesidefloat}
+
+% beter een \installotr#1 met #1 = macro en auto test
+
+\newif \iftraceotr
+\newif \ifinotr
+\newtoks \mainoutput
+\newcount\otrlevel
+
+% When issuing two \par\penalty-\plustenthousand's, only the first
+% triggers the otr; obscure feature or optimization?
+
+\newcount\outputcounter \outputcounter=-100010 % -10010
+
+\def\doinvokeoutput
+ {\iftraceotr
+ \expandafter\dodotracedoutput
+ \else
+ \expandafter\dodoinvokeoutput
+ \fi}
+
+\def\doshowoutputmessage#1#2#3%
+ {\writestatus\m!otr{#1 #2 \number#3}}
+
+\def\dodoinvokeoutput#1%
+ {\bgroup\par\penalty#1\egroup}
+
+\def\dodotracedoutput#1%
+ {\doshowoutputmessage+{traced}{#1/\the\outputpenalty}%
+ \writestatus\m!otr{c:\number\mofcolumns,v:\the\vsize,g:\the\pagegoal,t:\the\pagetotal}%
+ \dodoinvokeoutput{#1}%
+ \writestatus\m!otr{c:\number\mofcolumns,v:\the\vsize,g:\the\pagegoal,t:\the\pagetotal}%
+ \doshowoutputmessage-{traced}{#1/\the\outputpenalty}}
+
+\def\installoutput#1#2% \invoke \action
+ {\global\advance\outputcounter\minusone
+ \edef#1{\noexpand\doinvokeoutput{\number\outputcounter}}%
+ \setvalue{\@@OTR\number\outputcounter}{#2}}
+
+\def\invoketracedoutputroutine
+ {\doshowoutputmessage+{trying}\outputpenalty
+ \ifcsname\@@OTR\the\outputpenalty\endcsname
+ \doshowoutputmessage+{special}\outputpenalty
+ \csname\@@OTR\the\outputpenalty\endcsname
+ \doshowoutputmessage-{special}\outputpenalty
+ \else
+ \doshowoutputmessage+{normal}\outputpenalty
+ \the\OTRcommand\output
+ \doshowoutputmessage-{normal}\outputpenalty
+ \fi
+ \doshowoutputmessage-{trying}\outputpenalty}
+
+\def\invokenormaloutputroutine
+ {\ifcsname\@@OTR\the\outputpenalty\endcsname
+ \csname\@@OTR\the\outputpenalty\endcsname
+ \else
+ \the\OTRcommand\output
+ \fi}
+
+\def\invokeoutputroutine
+ {\iftraceotr
+ \expandafter\invoketracedoutputroutine
+ \else
+ \expandafter\invokenormaloutputroutine
+ \fi}
+
+\mainoutput{\invokeoutputroutine} \output{\inotrtrue\the\mainoutput}
+
+%D Some hooks:
+
+\output{\inotrtrue\the\everybeforeoutput\the\mainoutput\the\everyafteroutput}
+
+\ifx\pagediscards\undefined \let\pagediscards\relax \fi
+
+\installoutput\synchronizeoutput % maybe add pagediscards
+ {\ifvoid\normalpagebox\else
+ \unvbox\normalpagebox
+ \pagediscards % maybe not needed ?
+ \fi}
+
+\installoutput\discardpage
+ {\setbox\scratchbox\box\normalpagebox}
+
+%D In order to force consistent use of variables, we
+%D predefine a lot of them here.
+
+%D The next two registers can be used to store pre column
+%D material as well as footnotes or so.
+
+\newbox\precolumnbox \newdimen\precolumnboxheight
+\newbox\postcolumnbox \newdimen\postcolumnboxheight
+
+%D We reserve a counter for the number of columns as well as
+%D the current column. Both are not to be changed by users!
+
+\newcount\nofcolumns \nofcolumns = 1
+\newcount\mofcolumns \mofcolumns = 1
+
+\chardef\maxnofcolumns = 50
+\chardef\allocatednofcolumns = 0
+
+%D The next dimensions reports the final column height
+
+\newdimen\finalcolumnheights
+\newcount\finalcolumnlines
+
+%D During initialization the temporary boxes are allocated.
+%D This enables us to use as much columns as we want, without
+%D exhausting the pool of boxes too fast. We could have packed
+%D them in one box, but we've got enough boxes.
+%D
+%D Two sets of boxes are declared, the txtboxes are used for
+%D the text, the topboxes are for moved column floats.
+
+\def\@col@{@col@}
+
+\def\initializecolumns#1%
+ {\ifnum#1>\maxnofcolumns
+ \showmessage\m!columns1\maxnofcolumns
+ \nofcolumns\maxnofcolumns
+ \else
+ \nofcolumns#1\relax
+ \fi
+ \ifnum\nofcolumns>\allocatednofcolumns
+ \dorecurse\nofcolumns
+ {\ifnum\recurselevel>\allocatednofcolumns\relax
+ % \newbox\next \letgvalue{\@col@-\recurselevel-t}=\next
+ \@EA\newbox\csname\@col@-\recurselevel-t\endcsname % text
+ \@EA\newbox\csname\@col@-\recurselevel-f\endcsname % foot
+ \@EA\newbox\csname\@col@-\recurselevel-h\endcsname % top insert
+ \@EA\newbox\csname\@col@-\recurselevel-l\endcsname % top insert
+ \fi}%
+ \global\chardef\allocatednofcolumns=\nofcolumns
+ \fi}
+
+\def\firstcolumnbox {\columntextbox\plusone}
+\def\currentcolumnbox {\columntextbox\mofcolumns}
+\def\lastcolumnbox {\columntextbox\nofcolumns}
+
+\def\firsttopcolumnbox {\columntopbox \plusone}
+\def\currenttopcolumnbox{\columntopbox \mofcolumns}
+\def\lasttopcolumnbox {\columntopbox \nofcolumns}
+
+\def\columntextbox#1{\csname\@col@-\number#1-t\endcsname}
+\def\columnfootbox#1{\csname\@col@-\number#1-f\endcsname}
+\def\columntopbox #1{\csname\@col@-\number#1-h\endcsname}
+\def\columnbotbox #1{\csname\@col@-\number#1-l\endcsname}
+
+\def\columnsettextbox{\global\setbox\columntextbox}
+\def\columnsetfootbox{\global\setbox\columnfootbox}
+\def\columnsettopbox {\global\setbox\columntopbox}
+\def\columnsetbotbox {\global\setbox\columnbotbox}
+
+\def\columngettextbox{\copy\columntextbox}
+\def\columngetfootbox{\copy\columnfootbox}
+\def\columngettopbox {\copy\columntopbox}
+\def\columngetbotbox {\copy\columnbotbox}
+
+\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}}
+\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}}
+\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}}
+\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}}
+
+%D Without going in details we present two macro's which handle
+%D the columns. The action which is transfered by the the first
+%D and only parameter can do something with \type
+%D {\currentcolumnbox}. In case of the mid columns, \type
+%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled
+%D outside these macro's.
+
+\def\dohandlecolumn#1%
+ {\mofcolumns\recurselevel
+ \let\currentcolumn\recurselevel
+ #1\relax}
+
+\def\dohandleallcolumns#1%
+ {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
+
+\def\dohandlerevcolumns#1%
+ {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
+
+\def\dohandlemidcolumns#1%
+ {\dohandleallcolumns
+ {\ifnum\recurselevel>\plusone
+ \ifnum\recurselevel<\nofcolumns
+ \dohandlecolumn{#1}%
+ \fi
+ \fi}}
+
+%D This register can be used as a temporary storage for page
+%D content.
+
+\newbox\restofpage
+
+%D Features.
+
+\newif\ifintermediatefootnotes
+\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
+\newif\iflastcolumnfootnotes %\lastcolumnfootnotestrue
+\newif\ifbalancecolumns %\balancecolumnstrue
+\newif\ifbalancetoheight %\balancetoheighttrue
+\newif\ifforcecolumngrid \forcecolumngridtrue
+\newif\ifstretchcolumns \stretchcolumnsfalse
+\newif\ifinheritcolumns \inheritcolumnsfalse
+\newif\ifheightencolumns \heightencolumnsfalse
+
+\newif\ifbalancingcolumns
+\newif\ifcollectingcontent
+\newif\ifcolumnoverflow
+
+\newdimen\intercolumnwidth
+\newdimen\localcolumnwidth
+\newdimen\savedpagetotal
+
+\chardef\columndirection=0 % 0:lr 1:rl
+
+\def\minbalancetoplines {1}
+\def\minfreecolumnlines {2}
+
+\newif\ifrecentercolumnbox \recentercolumnboxtrue
+\newif\ifrerecentercolumnbox \rerecentercolumnboxtrue
+\newif\ifpackcolumnfloats \packcolumnfloatstrue
+
+\newbox\collectedpagefloats
+\newbox\collectedleftpagefloats
+\newbox\collectedrightpagefloats
+
+%D The \type {\ifdim} test is needed, because otherwise the
+%D last line of a text end up on top of the baseline instead of
+%D on the baseline, as is the case with preceding pages.
+%D Also, a \type {\vfil} better than a \type {\vfill}.
+
+% to be replaced by \page[now] \page[final] / merged
+
+% \def\eject {\par\penalty-\plustenthousand } % == {\par\break} % plain
+% \def\supereject {\par\penalty-\plustwentythousand} % also plain
+
+\def\eject {\par\ifvmode\penalty\ejectpenalty\fi\resetpagebreak} % == {\par\break} % plain
+\def\supereject {\par\ifvmode\penalty\superpenalty\fi\resetpagebreak} % also plain
+
+\def\doejectpage {\par\ifvmode\ifdim\pagetotal>\pagegoal\else\normalvfil\fi\fi} % pg set to \textheight
+\def\ejectpage {\doejectpage\eject}
+\def\superejectpage{\doejectpage\supereject}
+
+\ifx\bye\undefined \def\bye{\par\vfill\supereject\end} \fi % plain tex command
+
+% floats
+
+\def\ejectinsert
+ {%\flushnotes already done
+ \bgroup
+ \noftopfloats\plusthousand
+ \nofbotfloats\zerocount
+ % this is needed in case a float that has been stored
+ % ends up at the current page; this border case occurs when
+ % the calculated room is 'eps' smaller that the room available
+ % when just flushing; so now we have (maybe optional):
+ \pagebaselinecorrection
+ % alas, this is tricky but needed (first surfaced in prikkels)
+ \doflushfloats
+ \egroup}
+
+\def\ejectdummypage
+ {\endgraf \ifvmode
+ \ejectinsert
+ \fixedspace
+ \vfill
+ \gotonextpage
+ \fi}
+
+\def\beforefinaloutput
+ {}
+
+\def\afterfinaloutput
+ {%\forgetall
+ \vskip\zeropoint\relax
+ \ifvoid\normalpagebox \else
+ \unvbox\normalpagebox
+ \penalty\outputpenalty
+ \fi
+ % not really needed, replaced by \flushsavedfloats
+ \ifnum\outputpenalty>\superpenalty \else % better use a proper otr signal
+ \dosupereject
+ \fi
+ % but does not hurt either (we're still in the otr!)
+ \inpagebodytrue % needed for enabling \blank !
+ \flushsavedfloats % was \dosetbothinserts; only otr one !
+ \setvsize} % this is needed for interacting components, like floats and multicolumns
+
+\def\dofinaloutput#1#2% \vbox: prevents spurious spaces in every..pagebody
+ {\forgetall
+ \beforefinaloutput
+ \the\everybeforeshipout % brrr not in shipout
+ \the\pageboundsettings
+ \myshipout{\hbox{\vbox{\dopagebody#1#2}}}% is this hbox needed
+ \the\everyaftershipout
+ \afterfinaloutput}
+
+\def\donofinaloutput#1#2%
+ {\forgetall
+ \beforefinaloutput
+ \the\everybeforeshipout
+ \message{[-\the\realpageno]}%
+ \setbox\scratchbox\hbox{\dopagebody#1#2}%
+ \deadcycles\zerocount
+ \setnextrealpageno
+ \the\everyaftershipout
+ \afterfinaloutput}
+
+% beware: \ifprocessingpages is in use
+
+\ifdefined\doflushspread\else \let\doflushspread\relax \fi % todo
+
+\def\finaloutput#1#2%
+ {\ifprocessingpages
+ \ifpageselected
+ \@EAEAEA\dofinaloutput
+ \else
+ \@EAEAEA\donofinaloutput
+ \fi
+ \else
+ \ifpageselected
+ \@EAEAEA\donofinaloutput
+ \else
+ \@EAEAEA\dofinaloutput
+ \fi
+ \fi#1#2%
+ \resetselectiepagina
+ \incrementpagenumber
+ \incrementsubpagenumber
+ \checkpagedimensions
+ \ifnum\outputpenalty>\superpenalty \else
+ \dosupereject
+ \fi
+ \doflushspread
+ \doflushpostponedcontent}
+
+\def\dooutput
+ {\finaloutput\unvbox\normalpagebox}
+
+\maxdeadcycles=1000
+
+% will be installable tracer; better use chardef
+
+% this needs a real cleanup
+
+\def\doplaceversiontext#1#2%
+ {\doifsomething{#2}
+ {\defconvertedcommand\ascii{#2}%
+ \space#1:\space\ascii\space
+ \!!doneatrue}}
+
+\unexpanded\def\placeversioninfo % nog engels maken
+ {\ifcase\conceptmode
+ % 0 : nothing
+ \or
+ % 1 : simple
+ \vskip\!!sixpoint
+ \hbox to \makeupwidth
+ {\infofont
+ \v!concept:\space\currentdate
+ \hss\reportpagedimensions}%
+ \else
+ % 2/3 : extensive
+ \vskip\!!sixpoint
+ \hbox to \makeupwidth
+ {\infofont
+ \getmessage\m!systems{27}:\space\currentdate\space
+ \doplaceversiontext\v!project \currentproject
+ \doplaceversiontext\v!product \currentproduct
+ \doplaceversiontext\v!component\currentcomponent
+ \if!!donea\else\space\v!file:\space\jobname\fi
+ \hss\reportpagedimensions}%
+ \fi}
+
+% tot hier
+
+\def\doversion[#1]%
+ {\chardef\conceptmode\zerocount
+ \overfullrule\zeropoint
+ \processaction % \v!final=>
+ [#1]
+ [ \v!concept=>\chardef\conceptmode\plusone, % simple banner
+ \v!file=>\chardef\conceptmode\plustwo, % full banner
+ \v!temporary=>\chardef\conceptmode\plusthree % full banner plus
+ \overfullrule5\points]} % info in the margin
+
+\def\version
+ {\dosingleargument\doversion}
+
+\def\addstatusinfo
+ {\ifcase\conceptmode
+ \@EA\gobbleoneargument
+ \else
+ \@EA\doaddstatusinfo
+ \fi}
+
+\def\doaddstatusinfo#1%
+ {\setbox#1\vbox to \paperheight
+ {\vsmashbox#1\box#1%
+ \offinterlineskip
+ \vskip\topspace
+ \hsize\paperwidth
+ %\hfill\hbox{\placetestinfo\hskip.5cm}\vss % obsolete
+ \settexthoffset\hskip\texthoffset % brrrr
+ \vbox to 1cm{\vss\placeversioninfo\vss}}}
+
+\def\dotestinfo#1#2#3%
+ {\ifinpagebody\else\ifnum\conceptmode=\plusthree
+ \begingroup
+ \defconvertedcommand\ascii{#3}%
+ \xdef\extratestinfo
+ {#2\space\ascii}%
+ \gdef\totaltestinfo
+ {\global\setbox#1\vbox
+ {\unvbox#1\relax
+ \infofont \setupinterlinespace
+ \hbox
+ {\strut
+ \expanded{\doboundtext{\extratestinfo}{12em}{..}}%
+ \quad}}}%
+ \endgroup
+ \ifinner
+ \aftergroup\totaltestinfo
+ \else
+ \totaltestinfo
+ \fi
+ \fi\fi}
+
+\version[\v!final]
+
+% bewaren tvb documentatie
+%
+% \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}}
+
+\newtoks\afterpage \newtoks\aftereverypage
+\newtoks\beforepage \newtoks\beforeeverypage
+
+\chardef\showgridstate=0
+
+\def\showgrid
+ {\dosingleempty\doshowgrid}
+
+\def\doshowgrid[#1]%
+ {\chardef\showgridstate \plusone % downward compatible default
+ \chardef\gridboxlinemode \plusone
+ \chardef\gridboxlinenomode\plusone
+ \processallactionsinset
+ [#1]%
+ [ \v!reset=>\chardef\showgridstate \zerocount,
+ \v!bottom=>\chardef\showgridstate \plusone,
+ \v!top=>\chardef\showgridstate \plustwo,
+ \v!none=>\chardef\gridboxlinemode \zerocount,
+ \v!all=>\chardef\gridboxlinemode \plusone,
+ \v!lines=>\chardef\gridboxlinemode \plustwo,
+ \v!frame=>\chardef\gridboxlinemode \plusthree,
+ \v!nonumber=>\chardef\gridboxlinenomode\zerocount,
+ \v!right=>\chardef\gridboxlinenomode\plusone,
+ \v!left=>\chardef\gridboxlinenomode\plustwo,
+ \v!outer=>\chardef\gridboxlinenomode\plusthree]%
+ \ifcase\showgridstate
+ \let\addtextgridlayer\gobbleoneargument
+ \else % 1=bottom 2=top
+ \let\addtextgridlayer\doaddtextgridlayer
+ \fi}
+
+\definepalet
+ [layout]
+ [grid=red,
+ page=green]
+
+% if really needed for speed we can cache the grid
+
+\let\addtextgridlayer\gobbleoneargument
+
+\def\doaddtextgridlayer#1% to be checked for color and layer
+ {\startcolor[layout:grid]%
+ \setgridbox\scratchbox\makeupwidth\textheight % todo: check color
+ \global\setbox#1\hbox
+ {\ifcase\showgridstate\or\or\box#1\hskip-\makeupwidth\fi
+ \bgroup % color
+ \ifcase\layoutcolumns\else
+ \gray
+ \setlayoutcomponentattribute\v!grid\v!columns
+ \hbox \layoutcomponentboxattribute to \makeupwidth
+ {\dorecurse\layoutcolumns
+ {\hskip\layoutcolumnwidth
+ \ifnum\recurselevel<\layoutcolumns
+ \vrule
+ \!!height\ht\scratchbox
+ \!!depth\dp\scratchbox
+ \!!width\layoutcolumndistance
+ \fi}}%
+ \hskip-\makeupwidth
+ \fi
+ \setlayoutcomponentattribute\v!grid\v!lines
+ \hbox \layoutcomponentboxattribute{\box\scratchbox}%
+ \egroup
+ \ifcase\showgridstate\or\hskip-\makeupwidth\box#1\fi}%
+ \stopcolor}
+
+\def\buildpagebox#1%
+ {\setbox#1\vbox to \paperheight
+ {\hsize\paperwidth
+ \vskip\topspace
+ \doifbothsides
+ {\hskip\backspace}
+ {\hskip\backspace}
+ {\hskip\paperwidth \hskip-\backspace \hskip-\makeupwidth}%
+ \box#1}%
+ \dp#1\zeropoint}
+
+% \newif\ifpagebodyornaments \pagebodyornamentstrue
+%
+% \appendtoks
+% \global\pagebodyornamentstrue
+% \to \everyaftershipout
+
+\newif\ifarrangingpages \arrangingpagesfalse
+
+\chardef\pageornamentstate\zerocount % 0=on 1=one-off 2=always-off
+
+\def\pagebodyornamentstrue {\chardef\pageornamentstate\zerocount} % for a while
+\def\pagebodyornamentsfalse{\chardef\pageornamentstate\plusone} % for a while
+
+\appendtoks
+ \ifcase\pageornamentstate\or
+ \chardef\pageornamentstate\zerocount
+ \fi
+\to \everyaftershipout
+
+\let\poparrangedpages\relax
+\let\pusharrangedpage\relax
+
+\ifx\shiftprintpagebox\undefined
+ \let\shiftprintpagebox\gobbleoneargument
+ \let\shiftpaperpagebox\gobbleoneargument
+\fi
+
+\ifx\registerpageposition\undefined
+ \let\registerpageposition\gobbleoneargument
+\fi
+
+\def\reportarrangedpage#1%
+ {\showmessage\m!systems
+ {23}{\the\realpageno.\the\pageno\ifnum\subpageno>0 .\the\subpageno\fi,#1}}
+
+\newif\ifsavepagebody \newbox\savedpagebody
+
+% beware, \??ly is used before defined, i.e. bad module design
+
+\setuplayout[\c!method=\v!normal]
+
+\def\buildpagebody#1#2%
+ {\ifsavepagebody\global\setbox\savedpagebody\fi
+ \vbox
+ {\beginrestorecatcodes
+% \forgetall % igv problemen, check: \boxmaxdepth\maxdimen
+ \boxmaxdepth\maxdimen % new
+ \dontcomplain
+ % the following plugin uses and sets pagebox; beware: this
+ % will change and is for my (hh) personal experiments
+ \executeifdefined{\??ly\c!method\@@lymethod}%
+ {\getvalue{\??ly\c!method\v!normal}}#1#2%
+ % the finishing touch
+ \ifcase\pageornamentstate
+ \addpagebackground \pagebox
+ \fi
+ \registerpageposition\pagebox
+ \ifarrangingpages
+ \shiftpaperpagebox \pagebox % \v!paper
+ \else
+ \clippagebox \pagebox
+ \doifelse\@@lymarking\v!page
+ {\replicatepagebox \pagebox
+ \addpagecutmarks \pagebox}
+ {\addpagecutmarks \pagebox
+ \replicatepagebox \pagebox}%
+ \scalepagebox \pagebox
+ \mirrorpaperbox \pagebox
+ \orientpaperbox \pagebox
+ \addpagecolormarks \pagebox
+ \centerpagebox \pagebox
+ \addprintbackground\pagebox
+ \mirrorprintbox \pagebox
+ \orientprintbox \pagebox
+ \shiftprintpagebox \pagebox % \v!page
+ \offsetprintbox \pagebox
+ \negateprintbox \pagebox
+ \fi
+ \box\pagebox
+ \endrestorecatcodes}%
+ \ifsavepagebody\copy\savedpagebody\fi}
+
+\setvalue{\??ly\c!method\v!normal}#1#2%
+ {\setbox\pagebox\vbox
+ {\offinterlineskip
+ \ifcase\pageornamentstate
+ \bgroup % else footnotes get inconsistent font/baseline
+ \dostartattributes\??ly\c!style\c!color\empty
+ \offinterlineskip
+ \gettextboxes
+ \dostopattributes
+ \egroup
+ \fi
+ \getmainbox#1#2}% including footnotes
+ \ifcase\pageornamentstate
+ \addmainbackground \pagebox
+ \fi
+ \buildpagebox \pagebox
+ \addstatusinfo \pagebox}
+
+\def\finishpagebox#1%
+ {\ifarrangingpages
+ \addpagecutmarks #1%
+ \addpagecolormarks#1%
+ \centerpagebox #1%
+ \mirrorprintbox #1%
+ \orientprintbox #1%
+ \offsetprintbox #1%
+ \negateprintbox #1%
+ \fi}
+
+\appendtoks \restoreouterspacing \to \everybeforepagebody
+\appendtoks \restoreglobalbodyfont \to \everybeforepagebody
+%appendtoks \restoreouterspacing \to \everybeforepagebody
+
+\ifx\nestednewbox\undefined \newbox\nestednextbox \fi
+
+\prependtoks \let\nextbox\nestednextbox \to \everybeforepagebody
+
+\def\dopagebody#1#2%
+ {%\getallmarks % now in following token register
+ \the\everybeforepagebody
+ \starttextproperties
+% \setnextsubpageno % nog eens: als in pagina (tbv standaard opmaak)
+ \dontshowboxes % dan hier blokkeren en verderop resetten
+% \shipoutfacingpage
+ \checkmarginblocks
+ \the\beforeeverypage
+ \normalexpanded{\global\beforepage\emptytoks\the\beforepage}% \scratchtoks\beforepage\global\beforepage\emptytoks\the\scratchtoks % was \flushtoks\beforepage
+ \inpagebodytrue\buildpagebody#1#2%
+ \normalexpanded{\global\afterpage \emptytoks\the\afterpage }% \scratchtoks\afterpage \global\afterpage \emptytoks\the\scratchtoks % was \flushtoks\afterpage
+ \the\aftereverypage
+ \resetpagebreak
+ %updatelistreferences % now in aftereverypage
+ \resetlayouttextlines % will go to \aftereverypage
+ \stoptextproperties
+ \the\everyafterpagebody}
+
+\newtoks\pageboundsettings
+
+% \prependtoks \initializepaper \to \pageboundsettings
+
+% not here
+
+\newif\ifpagebreakdisabled \pagebreakdisabledfalse
+
+\chardef\testpagemethod \zerocount % todo: \testnewpage[method=,lines=,voffset=]
+\chardef\testpagetrigger\zerocount
+
+\def\testpage {\dotripleempty\dotestpage[\plusone ]} %
+\def\testpageonly{\dotripleempty\dotestpage[\plustwo ]} % no penalties added to the mvl
+\def\testpagesync{\dotripleempty\dotestpage[\plusthree]} % force sync
+
+\def\dotestpage[#1][#2][#3]% don't change, only add more methods
+ {\relax % needed before \if
+ \ifpagebreakdisabled
+ \endgraf
+ \else
+ % new from here
+ \ifcase\testpagetrigger
+ \endgraf
+ \or
+ \ifvmode
+ \dosomebreak\allowbreak
+ \else % indeed?
+ \vadjust{\allowbreak}%
+ \endgraf
+ \fi
+ \fi
+ % till here
+ \ifdim\pagegoal<\maxdimen \relax
+ \ifdim\pagetotal<\pagegoal \relax
+ \scratchdimen\lineheight
+ \multiply\scratchdimen#2\relax
+ \advance\scratchdimen \pagetotal
+ \ifdim\lastskip<\parskip
+ \advance\scratchdimen \parskip
+ \fi
+ \ifthirdargument
+ \advance\scratchdimen#3\relax
+ \fi
+ \ifcase\testpagemethod
+ \ifdim\scratchdimen>.99\pagegoal
+ \penalty-\!!tenthousand\relax
+ \fi
+ \or
+ \advance\scratchdimen-\pagegoal
+ \ifdim\scratchdimen>-\lineheight
+ \penalty-\!!tenthousand\relax
+ \fi
+ \or
+ \getnoflines\pagegoal
+ \advance\scratchdimen-\noflines\lineheight \relax
+ \ifdim\scratchdimen>-\lineheight
+ \penalty-\!!tenthousand\relax
+ \fi
+ \or % same as 0 but more accurate
+ \advance\scratchdimen-10\s!sp\relax
+ \ifdim\scratchdimen>\pagegoal
+ \penalty-\!!tenthousand\relax
+ \fi
+ \fi
+ \else
+ \ifnum#1=\plusthree
+ \flushpagesofar
+ \fi
+ \fi
+ \else
+ \ifnum#1=\plusone\goodbreak\fi
+ \fi
+ \fi}
+
+\def\flushpagesofar
+ {\endgraf
+ \ifdim\pagetotal>\pagegoal
+ \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal
+ \goodbreak % \penalty0
+ \else
+ \page
+ \fi
+ \else
+ \fi}
+
+\def\testcolumn
+ {\dodoubleempty\dotestcolumn}
+
+\def\dotestcolumn[#1][#2]%
+ {%\relax % needed before \if !
+ \endgraf
+ \ifdim\pagegoal<\maxdimen \ifdim\pagetotal<\pagegoal % \relax
+ \scratchdimen\pagegoal
+ \advance\scratchdimen-\pagetotal
+ \ifdim\lastskip<\parskip
+ \advance\scratchdimen \parskip
+ \fi
+ \ifsecondargument
+ \advance\scratchdimen#2%
+ \fi
+ \getrawnoflines\scratchdimen % raw !
+ % \message{[\number#1>\number\noflines ?}\wait
+ \ifnum#1>\noflines
+ \column
+ \fi
+ \else
+ \penalty-\!!tenthousand % untested ! ! \column
+ \fi \fi}
+
+\let\resetcurrentsectionmarks\relax
+
+% was: \resetsectionmarks\firstsection, zie \handlepagebreak
+
+\def\page{\pagebreak} % the short form of \pagebreak (mult-com one)
+
+\def\resetpagebreak
+ {\global\pagebreakdisabledfalse}
+
+\def\simplifypagebreak
+ {\def\dopagebreak[##1]{\goodbreak}}
+
+\def\disablepagebreaks
+ {\def\dopagebreak[##1]{}}
+
+\def\executepagebreakhandler#1%
+ {\edef\@@pagespecification{#1}%
+ \ifcsname\??pe:\@@pagespecification\endcsname
+ \csname\??pe:\@@pagespecification\endcsname
+ \else\ifcsname\??pe::\@@pagespecification\endcsname
+ \executepagebreakhandlers{\csname\??pe::\@@pagespecification\endcsname}%
+ \else
+ \csname\??pe:\s!unknown\endcsname
+ \fi\fi}
+
+\long\def\installpagebreakhandler#1#2%
+ {\long\setvalue{\??pe:#1}{#2}}
+
+\unexpanded\def\pagebreak
+ {\dosingleempty\dopagebreak}
+
+\def\dopagebreak[#1]% so, page ornaments are reset after a pagebreak command, unless set
+ {\bgroup
+ \flushnotes
+ \edef\prevrealpageno{\the\realpageno}%
+ \ifcase\pageornamentstate \or
+ % disable reset after shipout
+ \global\chardef\pageornamentstate\plustwo
+ \fi
+ \iffirstargument % or if empty i.e. []
+ \executepagebreakhandlers{#1}%
+ \else % so, no pagebreak when \pagebreak[] ! ! !
+ \executepagebreakhandler\v!yes
+ \fi
+ \ifnum\prevrealpageno<\realpageno
+ % there must have been a reason why i added the ifcase
+ % but it fails on tests/mkiv/pages/ornaments-001.tex
+ % as WS found out so we have to wait till the next side
+ % effect shows up
+ % \ifcase\pageornamentstate\or
+ \global\chardef\pageornamentstate\zerocount
+ % \fi
+ \fi
+ \egroup}
+
+\def\executepagebreakhandlers#1%
+ {\processcommacommand[#1]\executepagebreakhandler}
+
+\installpagebreakhandler \s!dummy
+ {\ejectinsert
+ \gotonextpage
+ \ejectdummypage}
+
+\installpagebreakhandler \v!frame
+ {\page\bgroup\showframe\page[\v!empty]\egroup}
+
+\installpagebreakhandler \s!unknown
+ {\doifinstringelse{+}\@@pagespecification
+ {\ejectinsert
+ \gotonextpage
+ \dorecurse\@@pagespecification\ejectdummypage}
+ {\doifnumberelse\@@pagespecification
+ {\ejectinsert
+ \gotonextpage
+ \doloop
+ {\ifnum\userpageno<\@@pagespecification\relax
+ \ejectdummypage
+ \else
+ \exitloop
+ \fi}}
+ {}}}
+
+\installpagebreakhandler \s!default
+ {} % do nothing if empty
+
+\installpagebreakhandler \v!reset
+ {% better not: \global\chardef\pageornamentstate\zerocount
+ \resetpagebreak}
+
+\installpagebreakhandler \v!disable
+ {\global\pagebreakdisabledtrue}
+
+\installpagebreakhandler \v!yes
+ {\ifpagebreakdisabled\else
+ \ejectinsert
+ \gotonextpage
+ \ifinsidecolumns % this will move to MUL
+ \ejectpage % anders soms geen overgang
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!makeup % ??
+ {\ifpagebreakdisabled\else
+ \eject
+ \fi}
+
+\installpagebreakhandler \v!blank
+ {\ifcase\pageornamentstate
+ \global\chardef\pageornamentstate\plusone
+ \fi}
+
+\installpagebreakhandler \v!no
+ {\ifpagebreakdisabled\else
+ \dosomebreak\nobreak
+ \fi}
+
+\installpagebreakhandler \v!preference
+ {\ifpagebreakdisabled\else
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[3][\zeropoint]%
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!bigpreference
+ {\ifpagebreakdisabled\else
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[5][\zeropoint]%
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!empty
+ {\ejectinsert
+ \gotonextpage
+ \doifnotvalue{\??tk\v!header\c!state}\v!stop{\setupheader[\c!state=\v!empty]}%
+ \doifnotvalue{\??tk\v!footer\c!state}\v!stop{\setupfooter[\c!state=\v!empty]}%
+ \ejectdummypage}
+
+\installpagebreakhandler \v!left
+ {\ejectinsert
+ \gotonextpageX % will become \gotonextpage
+ \doifbothsidesoverruled{}{\resetcurrentsectionmarks\ejectdummypage}{}}
+
+\installpagebreakhandler \v!right
+ {\ejectinsert
+ \gotonextpageX % will become \gotonextpage
+ \doifbothsidesoverruled{}{}{\resetcurrentsectionmarks\ejectdummypage}}
+
+\installpagebreakhandler \v!even
+ {\page
+ \doifoddpageelse{\resetcurrentsectionmarks\ejectdummypage}\donothing}
+
+\installpagebreakhandler \v!odd
+ {\page
+ \doifoddpageelse\donothing{\resetcurrentsectionmarks\ejectdummypage}}
+
+\installpagebreakhandler \v!quadruple % not yet ok inside columnsets
+ {\ifdoublesided
+ \!!counta\realpageno
+ \!!countb\realpageno
+ \divide\!!counta 4
+ \divide\!!countb 2
+ \ifnum\!!counta=\!!countb
+ \else
+ \executepagebreakhandler\v!yes
+ \executepagebreakhandler\v!empty
+ \executepagebreakhandler\v!empty
+ \fi
+ \fi}
+
+\installpagebreakhandler \v!last
+ {\ejectinsert
+ \gotonextpageX % will become \gotonextpage
+ \relax
+ \doifbothsidesoverruled
+ {\shipoutfacingpage}
+ {}
+ {\noheaderandfooterlines \ejectdummypage}%
+ \filluparrangedpages}
+
+\installpagebreakhandler \v!lastpage % handy for backpage preceded by empty pages
+ {\executepagebreakhandler\v!yes
+ \ifdoublesided
+ \executepagebreakhandler\v!left
+ \executepagebreakhandler\v!empty
+ \executepagebreakhandler\v!empty
+ \fi}
+
+\installpagebreakhandler \v!start
+ {\globallet\shipout\normalshipout}
+
+\installpagebreakhandler \v!stop
+ {\globallet\shipout\noshipout}
+
+% nb: \executepagebreakhandler\v!hoofd in other ones
+
+\installpagebreakhandler \v!header
+ {\doifnotvalue{\??tk\v!header\c!state}\v!stop{\setupheader[\c!state=\v!empty]}}
+
+\installpagebreakhandler \v!footer
+ {\doifnotvalue{\??tk\v!footer\c!state}\v!stop{\setupfooter[\c!state=\v!empty]}}
+
+% \definepagebreak
+% [chapter]
+% [yes,header,right]
+%
+% \setuphead
+% [chapter]
+% [page=chapter,
+% header=empty,
+% footer=chapter]
+%
+% \definepagebreak % untested
+% [lastpage]
+% [left,{empty,right},{empty,left}]
+
+% public page handler, beware: definepage already in use (core-ref)
+%
+% \definepagebreak[instance][forsure]
+% \definepagebreak[forsure][yes,+4]
+
+\unexpanded\def\definepagebreak
+ {\dodoubleargument\dodefinepagebreak}
+
+\def\dodefinepagebreak[#1][#2]% non recursive, meant for simple mappings
+ {\setvalue{\??pe::#1}{#2}}
+
+% don't change this / test case:
+%
+% \setupbackgrounds[state=repeat]
+% \setupbackgrounds[text][text][background=whatever]
+% \couplepage[chapter][before={\defineoverlay[whatever][ON]}]
+% \setuphead[chapter][before={\pagetype[chapter]}]
+% \chapter{First} \page test \chapter{second} \page test
+
+\long\def\installcolumnbreakhandler#1#2#3% #1=otr-id #2=tag
+ {\long\setvalue{\??cn:#1:#2}{#3}}
+
+\unexpanded\def\definecolumnbreak
+ {\dodoubleargument\dodefinecolumnbreak}
+
+\def\dodefinecolumnbreak[#1][#2]% non recursive, meant for simple mappings
+ {\setvalue{\??cn::#1}{#2}}
+
+%\def\columnbreak
+% {\dosingleempty\docolumnbreak}
+%
+%\def\docolumnbreak[#1]%
+% {\expanded{\nextcolumn[\executeifdefined{\??cn::#1}{#1}]}}
+
+\definecomplexorsimple\columnbreak
+
+\def\simplecolumnbreak
+ {\executecolumnbreakhandler\v!yes}
+
+\def\complexcolumnbreak[#1]% if empty, do nothing and avoid processing
+ {\doifsomething{#1}{\executecolumnbreakhandlers{#1}}}
+
+\def\executecolumnbreakhandlers#1%
+ {\processcommacommand[#1]\executecolumnbreakhandler}
+
+\def\executecolumnbreakhandler#1% here no commalist
+ {\edef\@@columnspecification{#1}%
+ \doifdefinedelse{\??cn:\OTRidentifier:\@@columnspecification}
+ {\getvalue{\??cn:\OTRidentifier:\@@columnspecification}}
+ {\doifdefinedelse{\??cn::\@@columnspecification}
+ {\executecolumnbreakhandlers{\getvalue{\??cn::\@@columnspecification}}}
+ {\getvalue{\??cn:\OTRidentifier:\s!unknown}}}}
+
+%let\nextcolumn\columnbreak
+\let\column \columnbreak
+
+% We don't want spurious last pages (due to left over marks):
+
+\def\noshipout
+ {\writestatus\m!systems{ignoring further shipouts}%
+ \global\advance\realpageno\minusone % else no flush of resources
+ \dowithnextbox{\deadcycles\zerocount}}
+
+% \def\doignorerestoftext
+% {\ifarrangingpages \else \ifnum\textlevel>\zerocount \else
+% \globallet\shipout\noshipout
+% \fi \fi}
+%
+% better:
+
+\def\doignorerestoftext
+ {\ifarrangingpages \else \ifnum\textlevel=\plusone
+ \globallet\shipout\noshipout
+ \fi \fi}
+
+\let\ignorerestoftext\donothing
+
+\prependtoks % only ignore in a symmetrical doc
+ \globallet\ignorerestoftext\doignorerestoftext
+\to \everystarttext
+
+% \appendtoks
+% \ignorerestoftext
+% \to \everylastshipout
+
+\newif\ifpageselected \pageselectedtrue
+\newif\ifselectingpages \selectingpagesfalse
+\newif\ifprocessingpages\processingpagestrue
+
+\let\pageselection \empty
+\let\currentpageselection\empty
+\let\aftershipout \relax
+\let\beforeshipout \relax
+
+\def\dodobeforeshipout#1%
+ {\global\let\beforeshipout\relax
+ \csname\??pg#1\c!before\endcsname}
+
+\def\dobeforeshipout
+ {\doifsomething\currentpageselection
+ {\processcommacommand[\currentpageselection]\dodobeforeshipout}}
+
+\def\dododoaftershipout#1%
+ {\global\let\aftershipout\relax
+ \global\let\currentpageselection\empty
+ \csname\??pg#1\c!after\endcsname}
+
+\def\dodoaftershipout#1%
+ {\doifelsevalue{\??pg#1\c!option}\v!doublesided
+ {\doifbothsidesoverruled
+ {\dododoaftershipout{#1}}
+ {\dododoaftershipout{#1}}
+ {}}
+ {\dododoaftershipout{#1}}}
+
+\def\doaftershipout
+ {\doifsomething\currentpageselection
+ {\processcommacommand[\currentpageselection]\dodoaftershipout}}
+
+% Dit wordt eigenlijk nooit en moet worden vervangen door
+% het meer algemene mechanisme.
+
+\def\dopagetype[#1]%
+ {\edef\desoortpagina{#1}%
+ \ifx\desoortpagina\empty \else
+ \@EA\doglobal\@EA\addtocommalist\@EA{\desoortpagina}\currentpageselection
+ \ifselectingpages
+ \fullexpandtwoargsafter\doifcommon\desoortpagina\pageselection
+ {\global\pageselectedtrue}%
+ \fi
+ \gdef\beforeshipout{\dobeforeshipout}%
+ \gdef\aftershipout {\doaftershipout}%
+ \fi}
+
+\def\pagetype
+ {\dosingleargument\dopagetype}
+
+\def\docouplepage[#1][#2]%
+ {\getparameters
+ [\??pg]
+ [\c!before=,
+ \c!after=,
+ \c!option=,
+ #2]%
+ \def\docommand##1%
+ {\getparameters
+ [\??pg##1]
+ [\c!before=\@@pgbefore,
+ \c!after=\@@pgafter,
+ \c!option=\@@pgoption]}%
+ \processcommalist[#1]\docommand}%
+
+\def\couplepage
+ {\dodoubleargument\docouplepage}
+
+\def\doprocesspage[#1][#2]%
+ {\processaction
+ [#2]
+ [\v!yes=>\global\processingpagestrue,
+ \v!no=>\global\processingpagesfalse]%
+ \gdef\pageselection{#1}%
+ \global\selectingpagestrue
+ \global\pageselectedfalse}
+
+\def\processpage
+ {\dodoubleargument\doprocesspage}
+
+\def\resetselectiepagina
+ {\ifselectingpages
+ \doifbothsidesoverruled{\global\pageselectedfalse}{}{\global\pageselectedfalse}%
+ \fi}
+
+\newif\ifregistertextareas
+\newif\iftracetextareas
+
+\newbox\registertextbox
+
+% \def\registeredtextarea#1#2#3% #1=lower-dp #2=correct-ht #3=box
+% {\hbox{\box#3}}
+
+\def\enabletextarearegistration{\global\registertextareastrue}
+
+\def\registeredtextarea#1#2#3% #1=lower-dp #2=correct-ht #3=box
+ {\hbox\bgroup
+ \ifregistertextareas \ifx\registerMPtextarea\undefined \else
+ \setbox\registertextbox\null
+ \wd\registertextbox\wd#3%
+ \ht\registertextbox\ht#3%
+ \dp\registertextbox\dp#3%
+ \ifcase#1\or % 1
+ \setbox\registertextbox\hbox{\lower\strutdp\box\registertextbox}%
+ \fi
+ \ifcase#2\or % 1
+ \setbox\registertextbox\hbox{\raise\topskip\hbox{\lower\strutht\box\registertextbox}}%
+ \dp\registertextbox\strutdp
+ \fi
+ \dp\registertextbox\strutdp % needed
+ %\setbox\registertextbox\hbox
+ % {\iftracetextareas\gray\boxrulewidth2pt\ruledhbox\fi
+ % {\registerMPtextarea{\box\registertextbox}}}%
+ \setbox\registertextbox\hbox
+ {\registerMPtextarea{\box\registertextbox}}%
+ \smashbox\registertextbox
+ \box\registertextbox
+ \fi \fi
+ \box#3%
+ \egroup}
+
+%D \macros
+%D {setupoppositeplacing,startopposite}
+%D
+%D \starttyping
+%D \starttext
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D \stoptext
+%D \stoptyping
+
+% Moved from page-mar.tex, made english, cleaned up, but still to be
+% redesigned
+
+\newbox\facingpage
+
+\unexpanded\def\setupoppositeplacing
+ {\dodoubleargument\getparameters[\??np]}
+
+\unexpanded\def\startopposite
+ {\dowithnextboxcontent
+ {\hsize\makeupwidth}%
+ {\global\setbox\facingpage\vbox
+ {\ifvoid\facingpage
+ \@@npbefore
+ \else
+ \@@npinbetween
+ \unvbox\facingpage
+ \fi
+ \box\nextbox}}%
+ \vbox\bgroup}
+
+\unexpanded\def\stopopposite
+ {\egroup}
+
+\def\finishfacingpage
+ {\ifvoid\facingpage\else
+ \global\setbox\facingpage\vbox to \makeupheight
+ {\unvbox\facingpage
+ \@@npafter
+ \vss}%
+ \fi}
+
+\def\shipoutfacingpage
+ {\doif\@@npstate\v!start
+ {\ifvoid\facingpage\else
+ \ifnum\realpageno>\plusone
+ \bgroup
+ \chardef\pageornamentstate\plusone
+ \finishfacingpage
+ \myshipout{\buildpagebody\box\facingpage}%
+ \egroup
+ \else
+ \global\setbox\facingpage\emptybox
+ \fi
+ \fi}}
+
+\setupoppositeplacing
+ [\c!state=\v!start,
+ \c!before=,
+ \c!inbetween=\blank,
+ \c!after=]
+
+\protect \endinput
diff --git a/tex/context/base/page-ins.mkii b/tex/context/base/page-ins.mkii
new file mode 100644
index 000000000..069153434
--- /dev/null
+++ b/tex/context/base/page-ins.mkii
@@ -0,0 +1,103 @@
+%D \module
+%D [ file=core-ins,
+%D version=2002.04.16,
+%D title=\CONTEXT\ Insertion Macros,
+%D subtitle=Insertions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Insertions}
+
+%D Insertions are special data collections that are associated
+%D to \TEX's internal page builder. When multiple footnote
+%D classes were introduced, I decided to isolate some of the
+%D functionality in a module.
+
+\unprotect
+
+\newtoks\@@insertionlist
+
+\def\processinsertions{\the\@@insertionlist}
+
+\let\doprocessinsert\gobbleoneargument
+
+%\def\installinsertion#1%
+% {\ifx#1\undefined
+% \newinsert#1%
+% \count#1\plusthousand
+% \skip #1\zeropoint
+% \dimen#1\maxdimen
+% \appendtoks\doprocessinsert#1\to\@@insertionlist
+% \fi}
+
+\def\installinsertion#1%
+ {\ifx#1\undefined
+ \let#1\relax
+ \fi
+ \ifx#1\relax % permits \csname...\endcsname
+ \newinsert#1%
+ \count#1\plusthousand
+ \skip #1\zeropoint
+ \dimen#1\maxdimen
+ \appendtoks\doprocessinsert#1\to\@@insertionlist
+ \fi}
+
+
+\def\synchronizeinsertions
+ {\def\doprocessinsert##1{\ifvoid##1\else\insert##1{\unvbox##1}\fi}%
+ \processinsertions}
+
+%D For instance, when we postpone footnotes, we need to save
+%D some data related to the inserts. The next methods are
+%D far from ideal, but better than nothing. We save and
+%D restore box content and associated data independently.
+%D The box content is only restores when non||void.
+
+\def\backupinsertion#1%
+ {\csname\string#1\endcsname}
+
+\def\installbackupinsertion#1%
+ {\expandafter\newinsert\csname\string#1\endcsname
+ \count\backupinsertion#1\zerocount
+ \skip \backupinsertion#1\zeropoint
+ \dimen\backupinsertion#1\maxdimen}
+
+\def\saveinsertionbox#1%
+ {\ifdim\ht#1>\zeropoint % hm, actually unknown
+ \global\setbox\backupinsertion#1\box#1%
+ \else
+ \global\setbox\backupinsertion#1\emptybox
+ \fi}
+
+\def\restoreinsertionbox#1%
+ {\ifvoid\backupinsertion#1\else % if void, we keep the content
+ \global\setbox#1\box\backupinsertion#1%
+ \fi}
+
+\def\eraseinsertionbackup#1%
+ {\global\setbox\backupinsertion#1\emptybox}
+
+\def\saveinsertiondata#1%
+ {\global\skip \backupinsertion#1\skip #1%
+ \global\count\backupinsertion#1\count#1%
+ \global\dimen\backupinsertion#1\dimen#1}
+
+\def\restoreinsertiondata#1%
+ {\global\skip #1\skip \backupinsertion#1%
+ \global\count#1\count\backupinsertion#1%
+ \global\dimen#1\dimen\backupinsertion#1}
+
+%D Auxiliary macros:
+
+\def\addinsertionheight#1\to#2%
+ {\ifvoid#1\else
+ \advance#2 1\skip#1\relax
+ \advance#2 \ht #1\relax
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/page-ins.mkiv b/tex/context/base/page-ins.mkiv
new file mode 100644
index 000000000..3e12bfcf0
--- /dev/null
+++ b/tex/context/base/page-ins.mkiv
@@ -0,0 +1,94 @@
+%D \module
+%D [ file=core-ins,
+%D version=2002.04.16,
+%D title=\CONTEXT\ Insertion Macros,
+%D subtitle=Insertions,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Insertions}
+
+%D Insertions are special data collections that are associated
+%D to \TEX's internal page builder. When multiple footnote
+%D classes were introduced, I decided to isolate some of the
+%D functionality in a module.
+
+\unprotect
+
+\newtoks\@@insertionlist
+
+\def\processinsertions{\the\@@insertionlist}
+
+\let\doprocessinsert\gobbleoneargument
+
+\def\installinsertion#1%
+ {\ifdefined#1\else
+ \let#1\relax
+ \fi
+ \ifx#1\relax % permits \csname...\endcsname
+ \newinsert#1%
+ \count#1\plusthousand
+ \skip #1\zeropoint
+ \dimen#1\maxdimen
+ \appendtoks\doprocessinsert#1\to\@@insertionlist
+ \fi}
+
+
+\def\synchronizeinsertions
+ {\def\doprocessinsert##1{\ifvoid##1\else\insert##1{\unvbox##1}\fi}%
+ \processinsertions}
+
+%D For instance, when we postpone footnotes, we need to save
+%D some data related to the inserts. The next methods are
+%D far from ideal, but better than nothing. We save and
+%D restore box content and associated data independently.
+%D The box content is only restores when non||void.
+
+\def\backupinsertion#1%
+ {\csname\string#1\endcsname}
+
+\def\installbackupinsertion#1%
+ {\expandafter\newinsert\csname\string#1\endcsname
+ \count\backupinsertion#1\zerocount
+ \skip \backupinsertion#1\zeropoint
+ \dimen\backupinsertion#1\maxdimen}
+
+\def\saveinsertionbox#1%
+ {\ifdim\ht#1>\zeropoint % hm, actually unknown
+ \global\setbox\backupinsertion#1\box#1%
+ \else
+ \global\setbox\backupinsertion#1\emptybox
+ \fi}
+
+\def\restoreinsertionbox#1%
+ {\ifvoid\backupinsertion#1\else % if void, we keep the content
+ \global\setbox#1\box\backupinsertion#1%
+ \fi}
+
+\def\eraseinsertionbackup#1%
+ {\global\setbox\backupinsertion#1\emptybox}
+
+\def\saveinsertiondata#1%
+ {\global\skip \backupinsertion#1\skip #1%
+ \global\count\backupinsertion#1\count#1%
+ \global\dimen\backupinsertion#1\dimen#1}
+
+\def\restoreinsertiondata#1%
+ {\global\skip #1\skip \backupinsertion#1%
+ \global\count#1\count\backupinsertion#1%
+ \global\dimen#1\dimen\backupinsertion#1}
+
+%D Auxiliary macros:
+
+\def\addinsertionheight#1\to#2%
+ {\ifvoid#1\else
+ \advance#2 1\skip#1\relax
+ \advance#2 \ht #1\relax
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/page-lay.mkii b/tex/context/base/page-lay.mkii
new file mode 100644
index 000000000..de1194c2a
--- /dev/null
+++ b/tex/context/base/page-lay.mkii
@@ -0,0 +1,1429 @@
+%D \module
+%D [ file=page-lay,
+%D version=2000.10.20, % copied from main-001
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Layout Specification,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Layout Specification}
+
+%D This module is now etex dependent.
+
+% to be translated into english
+
+% hoofdhoogte wordt bij status=hoog niet aangepast op outer
+% level, wel binnen bepaalde berekeningen
+
+%D Before you start wondering why some of the page related
+%D modules skip upward or left in order to place elements, you
+%D must realize that the reference point is the top left
+%D corner of the main typesetting area. One reason for this
+%D choice is that it suited some viewers that displayed page
+%D areas. Another reason is that margins, edges and top and
+%D bottom areas are kind of virtual, while the header, text
+%D and footer areas normally determine the text flow.
+
+\unprotect
+
+%D First we get rid of the funny \TEX\ offset defaults of one
+%D inch by setting them to zero.
+
+\voffset = 0pt % setting this to -1in let's go metapost crazy
+\hoffset = 0pt % setting this to -1in let's go metapost crazy
+
+%D The dimensions related to layout areas are represented by
+%D real dimensions.
+
+\newdimen\paperheight \paperheight = 297mm
+\newdimen\paperwidth \paperwidth = 210mm
+
+\newdimen\printpaperheight \printpaperheight = \paperheight
+\newdimen\printpaperwidth \printpaperwidth = \paperwidth
+
+\newdimen\makeupheight % calculated
+\newdimen\makeupwidth % calculated
+
+\newdimen\textheight % calculated
+\newdimen\textwidth % calculated
+
+\newdimen\topspace \topspace = 2cm
+\newdimen\backspace \backspace = \topspace
+\newdimen\cutspace \cutspace = 0pt
+\newdimen\bottomspace \bottomspace = 0pt
+
+\newdimen\headerheight \headerheight = 2cm
+\newdimen\footerheight \footerheight = \headerheight
+
+\newdimen\topoffset \topoffset = 0pt
+\newdimen\backoffset \backoffset = \topoffset
+
+\newdimen\leftmarginwidth \leftmarginwidth = 3cm
+\newdimen\rightmarginwidth \rightmarginwidth = \leftmarginwidth
+
+\newdimen\leftedgewidth \leftedgewidth = 3cm
+\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth
+
+\newdimen\topheight \topheight = 0cm
+\newdimen\bottomheight \bottomheight = \topheight
+
+\newcount\layoutlines \layoutlines = 0
+\newcount\layoutcolumns \layoutcolumns = 0
+\newdimen\layoutcolumndistance \layoutcolumndistance = 0pt
+\newdimen\layoutcolumnwidth \layoutcolumnwidth = 0pt
+
+%D We can save some tokens and fuzzy parameters by using a
+%D symbolic name for the current set of layout parameters.
+
+\let\currentlayout\empty
+
+\def\layoutparameter#1%
+ {\csname\??ly\ifcsname
+ \??ly\currentlayout#1\endcsname\currentlayout
+ \fi#1\endcsname}
+
+\def\namedlayoutparameter#1#2%
+ {\csname\??ly\ifcsname\??ly #1#2\endcsname#1\else
+ \ifcsname\??ly\currentlayout#2\endcsname\currentlayout
+ \fi\fi#2\endcsname}
+
+%D Beause normal \TEX\ has at most 256 dimensions (of which a
+%D substantial part is already in use), we provide a way to
+%D generate a format with macro based alternatives. For a long
+%D time, this used to be the default case. Beware: only fixed
+%D dimensions can be used in calculations! By the way, the
+%D gain in speed can hardly be called impressive and is roughly
+%D 1 second on a 35 second run of 850 empty pages with a
+%D couple of backgrounds only (which is far less than one
+%D percent on a normal document).
+
+%D The next series of dimensions are complemented by left
+%D and rights ones.
+
+\newdimen \margindistance
+\newdimen \edgedistance
+\newdimen \marginwidth
+\newdimen \edgewidth
+
+%D Because a distance does not really makes sense when there
+%D is no area, we use a zero distance in case there is no
+%D area.
+
+\def\layoutdistance#1#2%
+ {\ifdim\zeropoint<#1\layoutparameter#2\else\zeropoint\fi}
+
+%D The horizontal distances are:
+
+\newdimen \leftedgedistance
+\newdimen \rightedgedistance
+\newdimen \leftmargindistance
+\newdimen \rightmargindistance
+
+%D The vertical distances are:
+
+\newdimen \topdistance
+\newdimen \headerdistance
+\newdimen \footerdistance
+\newdimen \bottomdistance
+
+%D We need to calculate the extra distances:
+
+\def\setlayoutdimensions
+ {\global\marginwidth \layoutparameter\c!margin
+ \global\edgewidth \layoutparameter\c!edge
+ \global\margindistance \layoutparameter\c!margindistance
+ \global\edgedistance \layoutparameter\c!edgedistance
+ \global\leftedgedistance \layoutdistance \leftedgewidth \c!leftedgedistance
+ \global\rightedgedistance \layoutdistance \rightedgewidth \c!rightedgedistance
+ \global\leftmargindistance \layoutdistance \leftmarginwidth \c!leftmargindistance
+ \global\rightmargindistance\layoutdistance \rightmarginwidth \c!rightmargindistance
+ \global\topdistance \layoutdistance \topheight \c!topdistance
+ \global\headerdistance \layoutdistance \headerheight \c!headerdistance
+ \global\footerdistance \layoutdistance \footerheight \c!footerdistance
+ \global\bottomdistance \layoutdistance \bottomheight \c!bottomdistance}
+
+\def\setlayoutdistances % local in \setreducedvsize
+ {\headerdistance\layoutdistance\headerheight\c!headerdistance
+ \footerdistance\layoutdistance\footerheight\c!footerdistance}
+
+% these are wrong in the running text, assumes some swapping, needs a cleanup
+
+\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth }
+\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth}
+\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
+\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}
+
+\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth }
+\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth}
+\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance }
+\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance}
+
+\def\outerspacewidth {\rightorleftpageaction\cutspace\backspace}
+\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace}
+
+\newtoks\extralayoutcalculations \def\calculatelayoutextras{\the\extralayoutcalculations}
+
+% \appendtoks
+% non etex calculations used to go here
+% \to \extralayoutcalculations
+
+\newtoks\everyswapmargins % watch the order !
+
+\appendtoks
+ \swapdimens\leftmargindistance\rightmargindistance
+ \swapdimens\leftedgedistance \rightedgedistance
+ \swapdimens\leftmarginwidth \rightmarginwidth
+ \swapdimens\leftedgewidth \rightedgewidth
+\to \everyswapmargins
+
+\appendtoks
+ \swapmacros\leftmargintotal \rightmargintotal
+ \swapmacros\leftedgetotal \rightedgetotal
+ \swapmacros\leftsidetotal \rightsidetotal
+ \swapmacros\leftcombitotal \rightcombitotal
+ \swapmacros\innermargintotal\outermargintotal
+ \swapmacros\inneredgetotal \outeredgetotal
+ \swapmacros\innercombitotal \outercombitotal
+ \swapmacros\innersidetotal \outersidetotal
+\to \everyswapmargins
+
+%D \macros
+%D {definepapersize}
+%D
+%D Before we start calculating layout dimensions, we will
+%D first take care of paper sizes. The first argument can be
+%D either an assignment (for defaults) or an identifier, in
+%D which case the second argument is an assignment.
+%D
+%D \showsetup{definepapersize}
+
+\def\definepapersize
+ {\dodoubleempty\dodefinepapersize}
+
+\def\definepapersize
+ {\dotripleempty\dodefinepapersize}
+
+\def\dodefinepapersize[#1][#2][#3]%
+ {\ifsecondargument
+ \doifsomething{#1} % to be sure
+ {\doifassignmentelse{#2}
+ {\getparameters
+ [\??pp#1] % geen \c!scale, scheelt hash ruimte
+ [\c!width=\@@ppwidth,\c!height=\@@ppheight,\c!offset=\@@ppoffset,#2]}
+ {\setvalue{\??pp:1:#1}{#2}%
+ \setvalue{\??pp:2:#1}{#3}}}%
+ \else
+ \getparameters[\??pp][#1]%
+ \setuppapersize % hm. this will freeze !
+ \fi}
+
+%D For the moment we need to fake this macro.
+
+\ifx\setuppapersize\undefined
+ \let\setuppapersize\relax
+\fi
+
+%D We set the defaults to the dimensions of an A4 sheet of
+%D paper.
+
+\definepapersize
+ [\c!width=210mm,\c!height=297mm,\c!offset=\!!zeropoint]
+
+%D Yet undocumented, let's see if it gets noticed.
+%D
+%D \starttyping
+%D \definepapersize[main] [A4] [A4]
+%D \definepapersize[extra][A4,landscape][A4,landscape]
+%D
+%D \starttext
+%D \setuppapersize[main]
+%D Page 1. \page
+%D Page 2. \page
+%D \setuppapersize[extra]
+%D Page 2 \page
+%D \setuppapersize[main]
+%D Page 3. \page
+%D Page 4. \page
+%D \adaptpapersize[extra]
+%D Page 5. \page
+%D Page 6. \page
+%D \stoptext
+%D \stoptyping
+
+%D \macros
+%D {setuppaper,setuppapersize}
+%D
+%D When setting up the papersize on which to typeset and
+%D print, we can also determine some more characteristics.
+%D
+%D \showsetup{setuppapersize}
+%D
+%D We keep track of these features with the following
+%D variables.
+
+\chardef\papermirror =0 \chardef\printmirror =0
+\chardef\paperorientation=0 \chardef\printorientation=0 % beware: later no chardef
+\chardef\paperreverse =0 \chardef\printreverse =0
+\chardef\paperlandscape =0 \chardef\printlandscape =0
+
+\let\papersize\empty \let\printpapersize\empty
+
+\def\paperscale{1} \newif\ifnegateprintbox
+
+\def\setuppaper[#1]%
+ {\getparameters[\??pp][\c!paper=,\c!page=,#1]%
+ \edef\@@ppxy{\the\numexpr\@@ppnx*\@@ppny\relax}%
+ \doifelsenothing\@@pppage
+ {\doifelsenothing\@@pppaper
+ {} % {\setuppapersize} % added, removed, no need for, too tricky, mag-01 (fixed by freezing pp's)
+ {\dodosetuppapersize[\papersize][\@@pppaper]}}
+ {\doifelsenothing\@@pppaper
+ {\dodosetuppapersize[\@@pppage][\printpapersize]}
+ {\dodosetuppapersize[\@@pppage][\@@pppaper]}}}
+
+\def\setuppapersize
+ {\dodoubleempty\dosetuppapersize}
+
+\def\dosetuppapersize[#1][#2]%
+ {\doifassignmentelse{#1}
+ {\setuppaper[#1]}
+ {\doifelsenothing{#2}
+ {\expanded{\dodosetuppapersize
+ [\executeifdefined{\??pp:1:#1}{#1}]%
+ [\executeifdefined{\??pp:2:#1}{}]}}
+ {\doifassignmentelse{#2}
+ {\getparameters[\??pp\executeifdefined{\??pp:1:#1}{#1}][#2]}
+ {\expanded{\dodosetuppapersize
+ [\executeifdefined{\??pp:1:#1}{#1}]%
+ [\executeifdefined{\??pp:1:#2}{#2}]}}}}}
+
+\let\reinstatepapersize\relax
+
+\def\adaptpapersize
+ {\global\let\reinstatepapersize\restorepapersize
+ \setuppapersize}
+
+\appendtoks
+ \reinstatepapersize
+ \global\let\reinstatepapersize\relax
+\to \everyaftershipout
+
+\def\dodosetuppapersize[#1][#2]%
+ {\ifsecondargument
+ \expanded{\dododosetuppapersize[#1][#2]}%
+ \calculatehsizes
+ \calculatevsizes
+ \recalculatelogos
+ \recalculatebackgrounds
+ \recalculatelayout
+ \else\iffirstargument
+ \setuppapersize[#1][#2]%
+ \else\ifx\papersize\undefined\else
+ \restorepapersize
+ \fi\fi\fi}
+
+% dimen freeze is a bit tricky, but catches local redundant calls
+% with values where e.g width is defined in terms of \paperwidth
+
+\def\dododosetuppapersize[#1][#2]%
+ {\xdef\restorepapersize{\noexpand\setuppapersize[#1][#2]}%
+ \dosetuppaperorientation{#1}\paperlandscape\paperorientation\paperreverse\papermirror
+ \dosetuppaperorientation{#2}\printlandscape\printorientation\printreverse\printmirror
+ \def\docommand##1%
+ {\doifsomething{##1}{\doifdefined{\??pp##1\c!width}
+ {\global\paperwidth \getvalue{\??pp##1\c!width}%
+ \global\paperheight\getvalue{\??pp##1\c!height}%
+\ifinpagebody
+ \setevalue{\??pp##1\c!height}{\the\paperheight}%
+ \setevalue{\??pp##1\c!width }{\the\paperwidth }%
+\fi
+ \calculatepaperoffsets{##1}%
+ \xdef\papersize{##1}}}}%
+ \processcommacommand[#1]\docommand
+ \doifdefinedelse{\??pp#1\c!scale}
+ {\edef\paperscale{\getvalue{\??pp#1\c!scale}}}
+ {\edef\paperscale{1}}%
+ \def\docommand##1%
+ {\doifsomething{##1}{\doifdefined{\??pp##1\c!width}
+ {\global\printpaperwidth \getvalue{\??pp##1\c!width}%
+ \global\printpaperheight\getvalue{\??pp##1\c!height}%
+\ifinpagebody
+ \setevalue{\??pp##1\c!height}{\the\printpaperheight}%
+ \setevalue{\??pp##1\c!width }{\the\printpaperwidth}%
+\fi
+ \xdef\printpapersize{##1}}}}%
+ \processcommacommand[#2]\docommand
+ \global\setdimentoatleast\paperwidth \onepoint
+ \global\setdimentoatleast\paperheight \onepoint
+ \global\setdimentoatleast\printpaperwidth \onepoint
+ \global\setdimentoatleast\printpaperheight\onepoint
+ \ifcase\paperlandscape\else
+ \doglobal\swapdimens\paperwidth\paperheight
+ \fi
+ \ifcase\printlandscape\else
+ \doglobal\swapdimens\printpaperwidth\printpaperheight
+ \fi
+ % this check can be confusing, so we've added the possibility
+ % to bypass this test: \setuppapersize[option=fit]
+ \doif\@@ppoption\v!max % \v!fit is
+ {\bgroup
+ % we need to pre-swap else we get the wrong paper size
+ \ifcase\paperorientation\else
+ \doifinset\paperorientation{90,270}{\swapdimens\paperwidth\paperheight}%
+ \fi
+ \ifcase\printorientation\else
+ \doifinset\printorientation{90,270}{\swapdimens\printpaperwidth\printpaperheight}%
+ \fi
+ \ifdim\paperheight>\printpaperheight
+ \global\printpaperheight\paperheight
+ \writestatus\m!systems{print height forced to paper height}%
+ \fi
+ \ifdim\paperwidth>\printpaperwidth
+ \global\printpaperwidth\paperwidth
+ \writestatus\m!systems{print width forced to paper width}%
+ \fi
+ \egroup}}
+
+\def\dosetuppaperorientation#1#2#3#4#5%
+ {\global\chardef#2\zerocount
+ \global\chardef#5\zerocount
+ \globallet#3\!!zerocount
+ \globallet#4\!!zerocount
+ \global\negateprintboxfalse
+ \processallactionsinset
+ [#1]
+ [ \v!landscape=>\global\chardef#2\plusone,
+ \v!mirrored=>\global\chardef#5\plusone,
+ \v!rotated=>\gdef#3{90}\gdef#4{270},
+ \v!negative=>\global\negateprintboxtrue,
+ 90=>\gdef#3{90}\gdef#4{270},
+ 180=>\gdef#3{180}\gdef#4{0},
+ 270=>\gdef#3{270}\gdef#4{90}]}
+
+\ifx\calculatepaperoffsets\undefined
+
+ \def\calculatepaperoffsets#1%
+ {\scratchdimen\getvalue{\??pp#1\c!offset}%
+ \global\advance\paperwidth -2\scratchdimen
+ \global\advance\paperheight-2\scratchdimen}
+
+\fi
+
+\let\restorepapersize\relax
+
+\def\checkforems[#1]%
+ {\def\docommand##1%
+ {\beforesplitstring##1\at em\to\asciia
+ \doifnot\asciia{##1}
+ {\aftersplitstring\asciia\at=\to\asciia
+ \doifsomething\asciia
+ {\showmessage\m!systems{10}{##1}}}}%
+ \processcommalist[#1]\docommand}
+
+\ifx\setups\undefined \def\setups[#1]{\setdefaultpenalties} \fi
+
+% \newtoks \everybeforelayout \relax
+% \newtoks \everyafterlayout \relax
+
+\def\recalculatelayout
+ {\doifsomething{\layoutparameter\c!page\layoutparameter\c!paper}
+ {\expanded{\dododosetuppapersize[\layoutparameter\c!page][\layoutparameter\c!paper]}}%
+ \dorecalculatelayout}
+
+\def\dorecalculatelayout
+ {%\the\everybeforelayout
+ \setups[\layoutparameter\c!preset]%
+ \global\leftmarginwidth \layoutparameter\c!leftmargin
+ \global\rightmarginwidth\layoutparameter\c!rightmargin
+ \global\leftedgewidth \layoutparameter\c!leftedge
+ \global\rightedgewidth \layoutparameter\c!rightedge
+ \global\headerheight \layoutparameter\c!header
+ \global\footerheight \layoutparameter\c!footer
+ \global\bottomheight \layoutparameter\c!bottom
+ \global\topheight \layoutparameter\c!top
+ \global\backspace \layoutparameter\c!backspace
+ \global\topspace \layoutparameter\c!topspace
+ \setlayoutdimensions % the rest of the `dimensions'
+ \doifelse\@@lygrid\v!yes\gridsnappingtrue\gridsnappingfalse
+ \ifgridsnapping
+ \setsystemmode\v!grid
+ \else
+ \resetsystemmode\v!grid
+ \fi
+ \setups[\layoutparameter\c!setups]% depends on gridsnapping !
+ \simplesetupwhitespace
+ \simplesetupblank
+ \global\cutspace\layoutparameter\c!cutspace
+ \relax
+ \doifelse{\layoutparameter\c!width}\v!middle
+ {\ifdim\cutspace=\zeropoint
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax}
+ {\doifelse{\layoutparameter\c!width}\v!fit
+ {\ifdim\cutspace=\zeropoint
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax
+ \scratchdimen\dimexpr\backspace
+ -\leftedgewidth -\leftedgedistance
+ -\leftmarginwidth-\leftmargindistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupwidth\dimexpr
+ -\rightmargindistance-\rightmarginwidth
+ -\rightedgedistance -\rightedgewidth
+ -\scratchdimen\relax}
+ {\global\makeupwidth\layoutparameter\c!width\relax
+ \ifdim\cutspace=\zeropoint
+ \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax
+ % \else
+ % A kind of inconsistent specification, but used
+ % in for instance s-pre-19.tex; the cutspace is
+ % used only for determining some kind of right
+ % margin; don't use this in doublesided mode
+ \fi}}%
+ \scratchdimen\layoutparameter\c!bottomspace\relax
+ %\ifdim\scratchdimen=\zeropoint
+ % \scratchdimen\topspace
+ %\fi
+ \global\bottomspace\layoutparameter\c!bottomspace\relax
+ \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty
+ \ifcase\layoutlines
+ \doifelse{\layoutparameter\c!height}\v!middle
+ {\ifdim\bottomspace=\zeropoint
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax}
+ {\doifelse{\layoutparameter\c!height}\v!fit
+ {\ifdim\bottomspace=\zeropoint
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\bottomspace\relax
+ \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax}
+ {\global\makeupheight\layoutparameter\c!height\relax
+ \ifdim\bottomspace=\zeropoint
+ \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax
+ \else
+ % inconsistent specification
+ \fi}}%
+ \else
+ % beware, when the bodyfont changes (switched) this will change as well; implementing
+ % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set
+ % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we
+ % stick to the current method (after a night of experimenting ...2003/10/13)
+ \global\makeupheight\dimexpr
+ \layoutparameter\c!lines\lineheight-\strutheight+\topskip+
+ \headerdistance+\headerheight+\footerdistance+\footerheight\relax
+ \fi
+ \backoffset\layoutparameter\c!horoffset
+ \topoffset \layoutparameter\c!veroffset
+ \global\setdimentoatleast\makeupwidth\onepoint
+ \global\setdimentoatleast\makeupheight \onepoint
+ % \checkcurrentlayout % here ?
+ % \the\everyafterlayout
+ \calculatelayoutextras
+ \calculatehsizes
+ \calculatevsizes
+ \calculatepseudocolumns
+ \checkgridsnapping
+ \recalculatelogos
+ \recalculatebackgrounds}
+
+\def\calculatepseudocolumns
+ {\global\layoutcolumns\layoutparameter\c!columns
+ \global\layoutcolumndistance\layoutparameter\c!columndistance
+ \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax
+ \global\divide\layoutcolumnwidth\layoutcolumns
+ \dorecurse\layoutcolumns
+ {\setxvalue{\??ly:c:\recurselevel}%
+ {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}}}
+
+%\dorecurse\layoutcolumns
+% {\setxvalue{\??ly:c:\recurselevel}{\the\dimexpr
+% (\numexpr(\recurselevel-1)\dimexpr(\layoutcolumnwidth+\layoutcolumndistance))}}
+
+\def\layoutcolumnoffset#1%
+ {\executeifdefined{\??ly:c:#1}\!!zeropoint}
+
+\def\checklayout
+ {\ifdim\makeupheight=\layoutlines\lineheight \else \recalculatelayout \fi}
+
+\appendtoks \checklayout \to \everystarttext
+
+% document:
+%
+% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page]
+%
+% \startstandardmakeup[page=blank] ... \stopstandardmakeup
+
+\def\changetolayout#1%
+ {%\writestatus\m!layouts{changing to layout #1}%
+ \xdef\currentlayout{#1}\recalculatelayout}
+
+\def\checkcurrentoddlayout
+ {\ifcsname\??ly\v!odd\c!state\endcsname
+ \doifvalue{\??ly\v!odd\c!state}\v!start{\changetolayout\v!odd}%
+ \fi}
+
+\def\checkcurrentevenlayout
+ {\ifcsname\??ly\v!even\c!state\endcsname
+ \doifvalue{\??ly\v!even\c!state}\v!start{\changetolayout\v!even}%
+ \fi}
+
+\ifx\lastpage\undefined \def\lastpage{1} \fi
+
+\def\reverserealfolio
+ {\ifnum\lastpage>\plusone
+ \ifnum\lastpage=\realfolio
+ \v!last
+ \else\ifnum\plusone=\realfolio
+ \v!first
+ \else
+ \the\numexpr\realfolio-\lastpage\relax
+ \fi\fi
+ \else
+ \!!zerocount
+ \fi}
+
+\def\checkcurrentlayout % public and used in naw, so keep this name
+ {\ifcsname\??ly\realfolio\c!state\endcsname
+ \doifvalue{\??ly\realfolio\c!state}\v!start{\changetolayout\realfolio}%
+ \else\ifcsname\??ly\reverserealfolio\c!state\endcsname
+ \doifvalue{\??ly\reverserealfolio\c!state}\v!start{\changetolayout\reverserealfolio}%
+ \else\ifcsname\??ly\v!current\c!state\endcsname
+ \changetolayout\v!current % no start test ?
+ \else
+ \doifoddpageelse\checkcurrentoddlayout\checkcurrentevenlayout
+ \fi\fi\fi}
+
+% testcase
+%
+% \setuppagenumbering[alternative=doublesided]
+%
+% \setuplayout [width=11cm]
+% \definelayout [odd] [backspace=1cm]
+% \definelayout [even] [backspace=4cm]
+% \definelayout [5] [backspace=5cm]
+% \definelayout [6] [backspace=5cm]
+% \definelayout [-2] [backspace=0cm,cutspace=0cm]
+% \definelayout [last] [backspace=0cm,cutspace=0cm]
+%
+% \checkcurrentlayout \showframe
+%
+% \starttext
+% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf}
+% \stoptext
+
+%appendtoks \checkcurrentlayout \to \everyaftershipout % no
+\appendtoks \checkcurrentlayout \to \everystarttext
+
+\appendtoks
+ \dochecknextlayout
+\to \everyaftershipout
+
+% \def\dochecknextlayout
+% {\ifx\currentlayout\v!current
+% % prevent redundant calculations
+% \else
+% \globallet\currentlayout\empty
+% \global\letbeundefined{\??ly\v!current\c!state}%
+% \checkcurrentlayout
+% \fi}
+%
+% this breaks after a standardmakeup
+
+\def\dochecknextlayout{\checkcurrentlayout}
+
+\newif\ifdoublesidedprint
+
+\def\presetcenterpagebox % in \setuplayout !!!!!!!!!!!!!!!!
+ {\doublesidedprintfalse
+ \ExpandFirstAfter\processallactionsinset
+ [\@@lylocation]
+ [ \v!middle=>{\setuppapersize[\c!left=\hss,\c!right=\hss,\c!top=\vss,\c!bottom=\vss]},
+ \v!left=>{\setuppapersize[\c!left=,\c!right=\hss]},
+ \v!right=>{\setuppapersize[\c!left=\hss,\c!right=]},
+ \v!bottom=>{\setuppapersize[\c!top=\vss,\c!bottom=]},
+ \v!top=>{\setuppapersize[\c!top=,\c!bottom=\vss]},%
+ \v!doublesided=>\doublesidedprinttrue,
+ \v!singlesided=>\doublesidedprintfalse]}
+
+\def\definelayout
+ {\dodoubleargument\dodefinelayout}
+
+\def\dodefinelayout[#1][#2]%
+ {\getparameters[\??ly#1][\c!state=\v!start,#2]}
+
+\def\dodosetuplayout[#1][#2]%
+ {\ConvertToConstant\doifnot{#2}\v!reset % #2 ?
+ {\getparameters[\??ly#1][#2]%
+ \checkforems[#2]}}
+
+% global needed for non-doublesided standardmakeup
+
+\def\dosetuplayout[#1][#2]%
+ {\globallet\currentlayout\empty % new, global
+ \ifsecondargument
+ \dodosetuplayout[#1][#2]%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\dodosetuplayout[][#1]}
+ {\doifnot{#1}\v!reset{\xdef\currentlayout{#1}}}% new, global
+ \fi\fi
+ \recalculatelayout
+ \checkcurrentlayout % here ?
+ \presetcenterpagebox}
+
+\def\setuplayout
+ {\dodoubleempty\dosetuplayout}
+
+\let\@@zaheight=\!!zeropoint
+
+\def\dopushpagedimensions
+ {\xdef\oldtextheight {\the\textheight }%
+ \xdef\oldfooterheight{\the\footerheight}%
+ \global\let\@@zaheight\@@zaheight}
+
+\def\dopoppagedimensions
+ {\global\textheight \oldtextheight
+ \global\footerheight\oldfooterheight
+ \recalculatelayout
+ \global\let\pushpagedimensions\dopushpagedimensions
+ \global\let\poppagedimensions\relax}
+
+\let\poppagedimensions = \relax
+\let\pushpagedimensions = \dopushpagedimensions
+
+% Elke \csname ... \endcsname wordt ook aangemaakt, dus ook
+% in een test met \doifdefined. Bij veel bladzijden kan dit
+% te veel macro's kosten. Vandaar de set \adaptedpages. Het
+% kost tijd, maar scheelt macro's.
+
+\let\adaptedpages\empty
+
+\def\adaptpagedimensions
+ {\ifx\adaptedpages\empty\else
+ \rawdoifinsetelse\realfolio\adaptedpages
+ {\getvalue{\??za\realfolio}%
+ \letbeundefined{\??za\realfolio}}
+ \donothing
+ \fi}
+
+\def\checkpagedimensions
+ {\poppagedimensions
+ \adaptpagedimensions}
+
+\def\reportpagedimensions
+ {\ifx\poppagedimensions\relax \else
+ \space\the\dimexpr\@@zaheight\relax\space-\space
+ \fi
+ \realfolio}
+
+\def\dodoadaptlayout[#1]%
+ {\getparameters[\??za][\c!height=,\c!lines=0,#1]%
+ \pushpagedimensions
+ \ifcase\@@zalines\relax
+ \showmessage\m!layouts1{\@@zaheight,\realfolio}%
+ \else
+ \showmessage\m!layouts1{\@@zalines\space\v!lines,\realfolio}%
+ \def\@@zaheight{\@@zalines\openlineheight}%
+ \fi
+ \doifelse\@@zaheight\v!max
+ {\balancedimensions\textheight\footerheight\footerheight}
+ {\balancedimensions\textheight\footerheight\@@zaheight}%
+ \ifdim\footerheight<\zeropoint
+ \global\advance\textheight \footerheight
+ \global\footerheight\zeropoint
+ \global\xdef\@@zaheight{\layoutparameter\c!footer\space(\v!max)}%
+ \fi
+ \setvsize
+ \global\pagegoal\vsize % nog corrigeren voor insertions ?
+ \recalculatelogos
+ \recalculatebackgrounds
+ \global\let\pushpagedimensions\relax
+ \global\let\poppagedimensions\dopoppagedimensions}
+
+\def\doadaptlayout[#1][#2]%
+ {\doifelsenothing{#2}
+ {\dodoadaptlayout[#1]}
+ {\def\docommand##1%
+ {\addtocommalist{##1}\adaptedpages
+ \setgvalue{\??za##1}{\dodoadaptlayout[#2]}}%
+ \processcommalist[#1]\docommand
+ \adaptpagedimensions}}
+
+\def\adaptlayout
+ {\dodoubleempty\doadaptlayout}
+
+% describe interface
+
+%D Centering the paper area on the print area is determined
+%D by the \type {top}, \type {bottom}, \type {left} and \type
+%D {right} parameters.
+
+\def\centerpagebox#1%
+ {\printpaperwidth \paperscale\printpaperwidth
+ \printpaperheight\paperscale\printpaperheight
+ \setbox#1\vbox to \printpaperheight
+ {\@@pptop
+ \hbox to \printpaperwidth
+ {\ifdoublesidedprint
+ \doifbothsides
+ {\@@ppleft \box#1\@@ppright}
+ {\@@ppleft \box#1\@@ppright}
+ {\@@ppright\box#1\@@ppleft }%
+ \else
+ \@@ppleft \box#1\@@ppright
+ \fi}%
+ \par
+ \@@ppbottom}}
+
+\def\offsetprintbox#1%
+ {\ifdim\topoffset=\zeropoint % \relax
+ \ifdim\backoffset=\zeropoint
+ \donefalse
+ \else
+ \donetrue
+ \fi
+ \else
+ \donetrue
+ \fi
+ \ifdone
+ \edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
+ \setbox#1\vbox
+ {%\forgetall
+ \offinterlineskip
+ \vskip\topoffset
+ \doifbothsides{\hskip\backoffset}{\hskip\backoffset}{\hskip-\backoffset}%
+ \box#1}%
+ \next
+ \fi}
+
+\def\replicatepagebox#1%
+ {\ifnum\@@lynx>\plusone
+ \donetrue
+ \else\ifnum\@@lyny>\plusone
+ \donetrue
+ \else
+ \donefalse
+ \fi\fi
+ \ifdone
+ \setbox#1\vbox
+ {%\forgetall
+ \offinterlineskip
+ \dorecurse\@@lyny
+ {\hbox{\dorecurse\@@lynx{\copy#1\hskip\@@lydx}\unskip}%
+ \vskip\@@lydy}
+ \unskip}%
+ \fi}
+
+\def\orientpagebodybox#1#2#3%
+ {\ifnum#2#3>\zerocount
+ \setbox#1\vbox
+ {\edef\somerotation{\ifdoublesided\ifodd\realpageno#2\else#3\fi\else#2\fi}%
+ \dorotatebox\somerotation\hbox{\box#1}}%
+ \fi}
+
+\def\orientpaperbox#1%
+ {\orientpagebodybox{#1}\paperorientation\paperreverse}
+
+\def\orientprintbox#1%
+ {\orientpagebodybox{#1}\printorientation\printreverse}
+
+\def\mirrorpagebodybox#1#2%
+ {\ifcase#2\or
+ \setbox#1\vbox
+ {\domirrorbox\vbox{\box#1}}%
+ \fi}
+
+\def\mirrorpaperbox#1%
+ {\mirrorpagebodybox{#1}\papermirror}
+
+\def\mirrorprintbox#1%
+ {\mirrorpagebodybox{#1}\printmirror}
+
+\def\scalepagebox#1%
+ {\ifdim\@@lyscale\points=\onepoint \else
+ \setbox#1\vbox
+ {\scale[\c!sx=\@@lyscale,\c!sy=\@@lyscale]{\box#1}}%
+ \paperwidth\@@lyscale\paperwidth
+ \paperheight \@@lyscale\paperheight
+ \fi}
+
+\def\negateprintbox#1%
+ {\ifnegateprintbox
+ \negatecolorbox{#1}%
+ \fi}
+
+\def\pagecutmarksymbol {\the\realpageno}
+\def\pagecutmarklength {.5cm}
+\let\pagecutmarktoptext \empty
+\let\pagecutmarkbottomtext \empty
+
+\def\extrapagecutmarkbottomtext
+ {\rlap{\jobname}\hfill\currentdate\space-\space\currenttime\hfill\llap{\realfolio}}
+
+\def\makepagecutbox % #1
+ {\let\cutmarksymbol \pagecutmarksymbol
+ \let\cutmarklength \pagecutmarklength
+ \let\cutmarktoptext \pagecutmarktoptext
+ \let\cutmarkbottomtext\pagecutmarkbottomtext
+ \makecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!on}%
+ {\makepagecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!page}% only at outer when nx/ny > 0
+ {\makepagecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!empty}%
+ {\let\pagecutmarksymbol\empty
+ \let\pagecutmarktoptext\empty
+ \let\pagecutmarkbottomtext\empty
+ \makepagecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!text}%
+ {\let\pagecutmarksymbol\empty
+ \let\pagecutmarkbottomtext\extrapagecutmarkbottomtext
+ \makepagecutbox}
+
+\setvalue{\??ly:c:\c!marking:\v!color}%
+ {\doaddpagecolormarks\colormarkbox}
+
+\setvalue{\??ly:c:\c!marking:\v!screen}%
+ {\doaddpagecolormarks\rastermarkbox}
+
+\def\addpagecutmarks % #1
+ {\executeifdefined{\??ly:n:\c!marking:\@@lymarking}\gobbleoneargument}
+
+\def\addpagecolormarks % #1
+ {\executeifdefined{\??ly:c:\c!marking:\@@lymarking}\gobbleoneargument}
+
+\def\doaddpagecolormarks#1#2%
+ {\makepagecutbox{#2}%
+ \ifnum\horizontalcutmarks>2 \chardef\colormarkoffset4 \fi
+ \ifnum\verticalcutmarks >2 \chardef\colormarkoffset4 \fi
+ #1{#2}}
+
+% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET
+
+\ifx\doifelselayoutsomeline\undefined % defined in page-txt
+ \let\doifelselayoutsomeline\secondofthreearguments
+\fi
+
+\def\calculatevsizes % global needed in \recalculatelayoutregel
+ {\redoglobal\textheight\makeupheight
+ \doifelselayoutsomeline \v!header
+ {\redoglobal\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}%
+ \donothing
+ \doifelselayoutsomeline \v!footer
+ {\redoglobal\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}%
+ \donothing
+ \ifzeropt\headerheight
+ \resetsystemmode\v!header
+ \else
+ \setsystemmode\v!header
+ \fi
+ \ifzeropt\footerheight
+ \resetsystemmode\v!footer
+ \else
+ \setsystemmode\v!footer
+ \fi
+ \resetglobal
+ \setvsize}
+
+\def\calculatereducedvsizes
+ {\textheight\makeupheight
+ \doifelselayoutsomeline \v!header
+ {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}%
+ {\headerheight\zeropoint
+ \setlayoutdistances}%
+ \doifelselayoutsomeline \v!footer
+ {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}%
+ {\footerheight\zeropoint
+ \setlayoutdistances}}
+
+\newdimen\innermakeupwidth % special purpose
+\newdimen\innermakeupmargin % special purpose
+
+\chardef\innermakeupcompensation\plusone
+
+\def\compensatedinnermakeupmargin
+ {\dimexpr\ifnum\innermakeupcompensation=\plusone+\innermakeupmargin\else\zeropoint\fi\relax}
+
+\def\freezetextwidth % \makeupwidth may be set to \textwidth
+ {\textwidth\makeupwidth % which is a tricky but valid value
+ \doifsomething{\layoutparameter\c!textwidth}
+ {\textwidth\layoutparameter\c!textwidth}% % local
+ \global\innermakeupwidth\textwidth
+ \doifelsenothing{\layoutparameter\c!textmargin}
+ {\global\innermakeupmargin\zeropoint}
+ {\global\innermakeupmargin\layoutparameter\c!textmargin}%
+ \global\advance\innermakeupwidth-\dimexpr\innermakeupmargin+\innermakeupmargin\relax
+ \advance\textwidth-\dimexpr\innermakeupmargin+\innermakeupmargin\relax} % local
+
+\def\calculatehsizes
+ {\freezetextwidth
+ \sethsize}
+
+% De onderstaande macro voert commando's uit, afhankelijk van
+% het karakter van het paginanummer.
+%
+% \doifoddpageelse{then-commando}{else-commando}
+
+%D When we start at an even page, we need to swap the layout
+%D differently. We cannot adapt the real page number, since
+%D it is used in cross referencing. The next switch is set
+%D when we start at an even page.
+
+\newif\ifshiftedrealpageno
+
+% \def\doifoddpageelse#1#2%
+% {\ifshiftedrealpageno
+% \ifodd\realpageno#2\else#1\fi
+% \else
+% \ifodd\realpageno#1\else#2\fi
+% \fi}
+
+\def\doifoddpageelse
+ {\ifshiftedrealpageno
+ \ifodd\realpageno
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi
+ \else
+ \ifodd\realpageno
+ \@EAEAEA\firstoftwoarguments
+ \else
+ \@EAEAEA\secondoftwoarguments
+ \fi
+ \fi}
+
+\let\doifonevenpaginaelse\doifoddpageelse
+
+% what are those \relax'es doing there?
+
+% \def\doifbothsidesoverruled#1#2#3%
+% {\ifdoublesided
+% \doifoddpageelse{#2}{#3}\relax
+% \else
+% #1\relax
+% \fi}
+
+% \def\doifbothsides#1#2#3%
+% {\ifdoublesided
+% \ifsinglesided
+% #1\relax
+% \else
+% \doifoddpageelse{#2}{#3}\relax
+% \fi
+% \else
+% #1\relax
+% \fi}
+
+\def\redoifoddpageelse#1{\doifoddpageelse}
+
+\def\doifbothsidesoverruled
+ {\ifdoublesided
+ \@EA\redoifoddpageelse
+ \else
+ \@EA\firstofthreearguments
+ \fi}
+
+\def\doifbothsides
+ {\ifdoublesided
+ \ifsinglesided
+ \@EAEAEA\firstofthreearguments
+ \else
+ \@EAEAEA\redoifoddpageelse
+ \fi
+ \else
+ \@EA\firstofthreearguments
+ \fi}
+
+\newdimen\texthoffset
+
+\def\settexthoffset
+ {\doifbothsides
+ {\texthoffset\backspace}
+ {\texthoffset\backspace}
+ {\texthoffset\dimexpr\paperwidth-\backspace-\makeupwidth\relax}}
+
+\def\goleftonpage
+ {\hskip-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}
+
+\def\doifmarginswapelse#1#2%
+ {\doifbothsides{#1}{#1}{#2}}
+
+\def\swapmargins
+ {\doifmarginswapelse\relax\doswapmargins}
+
+\def\doswapmargins
+ {\let\swapmargins \relax % to prevent local swapping
+ \let\doswapmargins\relax % to prevent local swapping
+ \the\everyswapmargins}
+
+\def\rightorleftpageaction
+ {\ifdoublesided
+ \ifsinglesided
+ \@EAEAEA\firstoftwoarguments
+ \else
+ \@EAEAEA\doifoddpageelse
+ \fi
+ \else
+ \@EA\firstoftwoarguments
+ \fi}
+
+\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth }
+\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth}
+\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
+\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}
+
+\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth }
+\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth}
+\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance }
+\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance}
+
+\def\outerspacewidth {\rightorleftpageaction\cutspace \backspace }
+\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace}
+
+\def\leftmargintotal {\dimexpr\leftmarginwidth +\leftmargindistance \relax}
+\def\rightmargintotal {\dimexpr\rightmarginwidth+\rightmargindistance\relax}
+\def\leftedgetotal {\dimexpr\leftedgewidth +\leftedgedistance \relax}
+\def\rightedgetotal {\dimexpr\rightedgewidth +\rightedgedistance \relax}
+
+\def\leftsidetotal {\dimexpr\leftmarginwidth +\leftedgetotal \relax}
+\def\rightsidetotal {\dimexpr\rightmarginwidth+\rightedgetotal\relax}
+\def\leftcombitotal {\dimexpr\leftmargintotal +\leftedgetotal \relax}
+\def\rightcombitotal {\dimexpr\rightmargintotal+\rightedgetotal\relax}
+
+\def\innermargintotal {\dimexpr\innermarginwidth+\innermargindistance\relax}
+\def\outermargintotal {\dimexpr\outermarginwidth+\outermargindistance\relax}
+\def\inneredgetotal {\dimexpr\inneredgewidth +\inneredgedistance \relax}
+\def\outeredgetotal {\dimexpr\outeredgewidth +\outeredgedistance \relax}
+
+\def\innercombitotal {\dimexpr\innermargintotal+\inneredgetotal\relax}
+\def\outercombitotal {\dimexpr\outermargintotal+\outeredgetotal\relax}
+\def\innersidetotal {\dimexpr\innermarginwidth+\inneredgetotal\relax}
+\def\outersidetotal {\dimexpr\outermarginwidth+\outeredgetotal\relax}
+
+%D \macros
+%D {startlocallayout}
+%D
+%D These macros should be used with care. They permit local
+%D layouts (as used in fitting pages, see \type {page-app.tex}).
+
+%D This is kind of obsolete now that we have \type
+%D {\definelayout}, so this hack will disappear in future
+%D versions.
+
+\def\startlocallayout
+ {\globalpushmacro\restorepapersize
+ \globalpushmacro\currentlayout}
+
+\def\stoplocallayout
+ {\globalpopmacro\currentlayout
+ \globalpopmacro\restorepapersize
+ \restorepapersize
+ \setuplayout}
+
+%D \macros
+%D {showprint, showframe, showlayout, showsetups}
+%D
+%D We predefine a couple of tracing macros.
+%D
+%D \showsetup{showprint}
+%D \showsetup{showframe}
+%D \showsetup{showlayout}
+%D \showsetup{showsetups}
+%D %showsetup{showmargins}
+
+\fetchruntimecommand \showprint {page-run.mkii}
+\fetchruntimecommand \showframe {page-run.mkii}
+\fetchruntimecommand \showlayout {page-run.mkii}
+\fetchruntimecommand \showsetups {page-run.mkii}
+\fetchruntimecommand \showmargins {page-run.mkii}
+
+%D The default dimensions are quite old and will not change.
+%D The funny fractions were introduced when we went from fixed
+%D dimensions to relative ones. Since \CONTEXT\ is a dutch
+%D package, the dimensions are based on the metric system. The
+%D asymmetrical layout is kind of handy for short
+%D quick||and||dirty stapled documents.
+%D
+%D Although valid, it is not a real good idea to use
+%D dimensions based on the \type {em} unit. First of all,
+%D since there are no fonts loaded yet, this dimension makes
+%D no sense, and second, you would loose track of values,
+%D since they could change while going to a new page,
+%D depending on the current font setting.
+
+\setuplayout
+ [ \c!topspace=.08417508418\paperheight, % 2.5cm
+ \c!top=\!!zeropoint,
+ \c!topdistance=\!!zeropoint,
+ \c!header=.06734006734\paperheight, % 2.0cm
+ \c!headerdistance=\!!zeropoint,
+ \c!height=.84175084175\paperheight, % 25.0cm
+ \c!footerdistance=\layoutparameter\c!headerdistance,
+ \c!footer=.06734006734\paperheight, % 2.0cm
+ \c!bottomdistance=\layoutparameter\c!topdistance,
+ \c!bottom=\!!zeropoint,
+ \c!backspace=.11904761905\paperwidth, % 2.5cm
+ \c!edge=\!!zeropoint,
+ \c!edgedistance=\layoutparameter\c!margindistance,
+ \c!margin=.12649983170\paperwidth, % snijwit-2*afstand
+ \c!margindistance=.02008341748\paperwidth, % 12.0pt
+ \c!leftedge=\layoutparameter\c!edge,
+ \c!leftedgedistance=\layoutparameter\c!edgedistance,
+ \c!leftmargin=\layoutparameter\c!margin,
+ \c!leftmargindistance=\layoutparameter\c!margindistance,
+ \c!width=.71428571429\paperwidth, % 15.0cm
+ \c!rightmargindistance=\layoutparameter\c!margindistance,
+ \c!rightmargin=\layoutparameter\c!margin,
+ \c!rightedgedistance=\layoutparameter\c!edgedistance,
+ \c!rightedge=\layoutparameter\c!edge,
+ \c!veroffset=\!!zeropoint,
+ \c!bottomspace=\!!zeropoint,
+ \c!horoffset=\!!zeropoint,
+ \c!cutspace=\!!zeropoint,
+ \c!textwidth=, % dangerous option -> centered / local
+ \c!textmargin=, % dangerous option -> both sides
+ \c!textdistance=\!!zeropoint, % shift down on grid
+ \c!style=,
+ \c!color=,
+ \c!marking=\v!off,
+ \c!location=, % \v!singlesided, but empty is signal
+ \c!scale=1,
+ \c!nx=1,
+ \c!ny=1,
+ \c!dx=\!!zeropoint,
+ \c!dy=\!!zeropoint,
+ \c!grid=\v!no,
+ \c!preset=,
+ \c!setups=\systemsetupsprefix\s!default,
+ \c!clipoffset=\!!zeropoint,
+ \c!lines=0,
+ \c!paper=, % for foxet
+ \c!page=, % for foxet
+ \c!columns=1,
+ \c!columndistance=\!!zeropoint]
+
+%D First we define a whole range of (DIN) papersizes,
+%D of which the A-series makes most sense. We enable checking.
+
+%D We also set some of the parameters that will be used when
+%D positioning the typeset paper onto the print paper.
+
+\setuppaper % (size) % only used in XY imposition
+ [\c!width=\zeropoint,
+ \c!height=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!backspace=\zeropoint,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!nx=1,
+ \c!ny=1,
+ \c!method=\v!normal]
+
+\setuppapersize
+ [\c!option=\v!max,
+ \c!top=,
+ \c!bottom=\vss,
+ \c!left=,
+ \c!right=\hss]
+
+\definepapersize [A0] [\c!width=841mm,\c!height=1189mm]
+\definepapersize [A1] [\c!width=594mm,\c!height=841mm]
+\definepapersize [A2] [\c!width=420mm,\c!height=594mm]
+\definepapersize [A3] [\c!width=297mm,\c!height=420mm]
+\definepapersize [A4] [\c!width=210mm,\c!height=297mm]
+\definepapersize [A5] [\c!width=148mm,\c!height=210mm]
+\definepapersize [A6] [\c!width=105mm,\c!height=148mm]
+\definepapersize [A7] [\c!width=74mm,\c!height=105mm]
+\definepapersize [A8] [\c!width=52mm,\c!height=74mm]
+\definepapersize [A9] [\c!width=37mm,\c!height=52mm]
+\definepapersize [A10] [\c!width=26mm,\c!height=37mm]
+
+\definepapersize [B0] [\c!width=1000mm,\c!height=1414mm]
+\definepapersize [B1] [\c!width=707mm,\c!height=1000mm]
+\definepapersize [B2] [\c!width=500mm,\c!height=707mm]
+\definepapersize [B3] [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm]
+\definepapersize [B4] [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm]
+\definepapersize [B5] [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm]
+\definepapersize [B6] [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm]
+\definepapersize [B7] [\c!width=88mm,\c!height=125mm]
+\definepapersize [B8] [\c!width=62mm,\c!height=88mm] % [\c!width=63mm,\c!height=88mm]
+\definepapersize [B9] [\c!width=44mm,\c!height=62mm] % [\c!width=44mm,\c!height=63mm]
+\definepapersize [B10] [\c!width=31mm,\c!height=44mm]
+
+\definepapersize [C0] [\c!width=917mm,\c!height=1297mm]
+\definepapersize [C1] [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm]
+\definepapersize [C2] [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm]
+\definepapersize [C3] [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm]
+\definepapersize [C4] [\c!width=229mm,\c!height=324mm]
+\definepapersize [C5] [\c!width=162mm,\c!height=229mm]
+\definepapersize [C6] [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm]
+\definepapersize [C7] [\c!width=81mm,\c!height=114mm] % [\c!width=81mm,\c!height=115mm]
+\definepapersize [C8] [\c!width=57mm,\c!height=81mm]
+\definepapersize [C9] [\c!width=40mm,\c!height=57mm]
+\definepapersize [C10] [\c!width=28mm,\c!height=40mm]
+
+%D Per August 2004 the rounding of some (seldom used) sizes
+%D were corrected top the latest DIN specifications. Peter
+%D Rolf came up with these and a few more missing sizes.
+%D Watch out: spaces and slashes!
+
+\definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm]
+\definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm]
+\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm]
+
+%D Because there are no standardized screen sizes, we define
+%D a bunch of sizes with $4:3$ ratios. The \type {S6} size is
+%D nearly as wide as a sheet of \type {A4} paper.
+
+\definepapersize [S3] [\c!width=300pt,\c!height=225pt]
+\definepapersize [S4] [\c!width=400pt,\c!height=300pt]
+\definepapersize [S5] [\c!width=500pt,\c!height=375pt]
+\definepapersize [S6] [\c!width=600pt,\c!height=450pt]
+\definepapersize [S8] [\c!width=800pt,\c!height=600pt]
+\definepapersize [SW] [\c!width=800pt,\c!height=450pt]
+\definepapersize [SM] [\c!width=720pt,\c!height=450pt]
+
+%D These are handy too:
+
+\definepapersize [S33] [\c!width=300pt,\c!height=300pt]
+\definepapersize [S44] [\c!width=400pt,\c!height=400pt]
+\definepapersize [S55] [\c!width=500pt,\c!height=500pt]
+\definepapersize [S66] [\c!width=600pt,\c!height=600pt]
+
+%D One may wonder if \TEX\ should be used for typesetting
+%D \CDROM\ covers, but it does not hurt to have the paper size
+%D ready.
+
+\definepapersize [CD] [\c!width=120mm,\c!height=120mm]
+
+%D The next series is for our English speaking friends who
+%D decided to stick to non metric values. Thanks to Nelson
+%D Beebe for completing the inch based list.
+
+\definepapersize [letter] [\c!width=8.5in,\c!height=11in]
+\definepapersize [ledger] [\c!width=11in,\c!height=17in]
+\definepapersize [tabloid] [\c!width=17in,\c!height=11in]
+
+\definepapersize [legal] [\c!width=8.5in,\c!height=14in]
+\definepapersize [folio] [\c!width=8.5in,\c!height=13in]
+\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in]
+
+\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet
+\definepapersize [B] [\c!width=11in,\c!height=17in] % 2 sheets
+\definepapersize [C] [\c!width=17in,\c!height=22in] % 4 sheets
+
+%D The next set is for Tobias Burnus, who gave me the sizes.
+
+\definepapersize [envelope 9] [\c!width=8.88in,\c!height=3.88in]
+\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in]
+\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in]
+\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in]
+\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in]
+\definepapersize [monarch] [\c!width=7.5in,\c!height=3.88in]
+\definepapersize [check] [\c!width=8.58in,\c!height=3.88in]
+\definepapersize [DL] [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm]
+\definepapersize [E4] [\c!width=280mm,\c!height=400mm]
+
+%D The next three sets are supplied by Taco:
+
+\definepapersize [RA0] [\c!width=860mm,\c!height=1220mm]
+\definepapersize [RA1] [\c!width=610mm,\c!height=860mm]
+\definepapersize [RA2] [\c!width=430mm,\c!height=610mm]
+\definepapersize [RA3] [\c!width=305mm,\c!height=430mm]
+\definepapersize [RA4] [\c!width=215mm,\c!height=305mm]
+
+%D ISO SRA (supplementary raw A) sizes:
+
+\definepapersize [SRA0] [\c!width=900mm,\c!height=1280mm]
+\definepapersize [SRA1] [\c!width=640mm,\c!height=900mm]
+\definepapersize [SRA2] [\c!width=450mm,\c!height=640mm]
+\definepapersize [SRA3] [\c!width=320mm,\c!height=450mm]
+\definepapersize [SRA4] [\c!width=225mm,\c!height=320mm]
+
+%D Swedish thesis formats:
+
+\definepapersize [G5] [\c!width=169mm,\c!height=239mm]
+\definepapersize [E5] [\c!width=155mm,\c!height=220mm]
+
+%D Industry invention:
+
+\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm]
+
+%D We can now default to a reasonable size. We match the print
+%D paper size with the typeset paper size. This setting should
+%D come after the first layout specification (already done).
+
+\setuppapersize
+ [A4][A4]
+
+%D A few goodies:
+
+\definepapersize
+ [oversized]
+ [ \c!width=\dimexpr\paperwidth +1.5cm\relax,
+ \c!height=\dimexpr\paperheight+1.5cm\relax]
+
+\definepapersize
+ [doublesized]
+ [ \c!width=\dimexpr \paperwidth \relax,
+ \c!height=\dimexpr2\paperheight\relax]
+
+\definepapersize
+ [doubleoversized]
+ [ \c!width=\dimexpr \paperheight+1.5cm\relax,
+ \c!height=\dimexpr2\paperwidth +1.5cm\relax]
+
+%D For orthogonality:
+
+\definepapersize
+ [undersized]
+ [ \c!width=\dimexpr\paperwidth -1.5cm\relax,
+ \c!height=\dimexpr\paperheight-1.5cm\relax]
+
+\definelayout
+ [\v!page]
+ [\c!backspace=\zeropoint,
+ \c!cutspace=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!bottomspace=\zeropoint,
+ \c!margin=\zeropoint,
+ \c!edge=\zeropoint,
+ \c!header=\zeropoint,
+ \c!footer=\zeropoint,
+ \c!top=\zeropoint,
+ \c!bottom=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!leftedge=\zeropoint,
+ \c!rightedge=\zeropoint,
+ \c!textdistance=\zeropoint,
+ \c!width=\v!middle,
+ \c!height=\v!middle,
+ \c!lines=0,
+ \c!grid=\v!no]
+
+\definelayout
+ [\v!middle]
+ [\c!width=\v!middle,
+ \c!height=\v!middle]
+
+\protect \endinput
diff --git a/tex/context/base/page-lay.mkiv b/tex/context/base/page-lay.mkiv
new file mode 100644
index 000000000..28f9be594
--- /dev/null
+++ b/tex/context/base/page-lay.mkiv
@@ -0,0 +1,1425 @@
+%D \module
+%D [ file=page-lay,
+%D version=2000.10.20, % copied from main-001
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Layout Specification,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Layout Specification}
+
+%D This module is now etex dependent.
+
+% to be translated into english
+
+% hoofdhoogte wordt bij status=hoog niet aangepast op outer
+% level, wel binnen bepaalde berekeningen
+
+%D Before you start wondering why some of the page related
+%D modules skip upward or left in order to place elements, you
+%D must realize that the reference point is the top left
+%D corner of the main typesetting area. One reason for this
+%D choice is that it suited some viewers that displayed page
+%D areas. Another reason is that margins, edges and top and
+%D bottom areas are kind of virtual, while the header, text
+%D and footer areas normally determine the text flow.
+
+\unprotect
+
+%D First we get rid of the funny \TEX\ offset defaults of one
+%D inch by setting them to zero.
+
+\voffset = 0pt % setting this to -1in let's go metapost crazy
+\hoffset = 0pt % setting this to -1in let's go metapost crazy
+
+%D The dimensions related to layout areas are represented by
+%D real dimensions.
+
+\newdimen\paperheight \paperheight = 297mm
+\newdimen\paperwidth \paperwidth = 210mm
+
+\newdimen\printpaperheight \printpaperheight = \paperheight
+\newdimen\printpaperwidth \printpaperwidth = \paperwidth
+
+\newdimen\makeupheight % calculated
+\newdimen\makeupwidth % calculated
+
+\newdimen\textheight % calculated
+\newdimen\textwidth % calculated
+
+\newdimen\topspace \topspace = 2cm
+\newdimen\backspace \backspace = \topspace
+\newdimen\cutspace \cutspace = 0pt
+\newdimen\bottomspace \bottomspace = 0pt
+
+\newdimen\headerheight \headerheight = 2cm
+\newdimen\footerheight \footerheight = \headerheight
+
+\newdimen\topoffset \topoffset = 0pt
+\newdimen\backoffset \backoffset = \topoffset
+
+\newdimen\leftmarginwidth \leftmarginwidth = 3cm
+\newdimen\rightmarginwidth \rightmarginwidth = \leftmarginwidth
+
+\newdimen\leftedgewidth \leftedgewidth = 3cm
+\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth
+
+\newdimen\topheight \topheight = 0cm
+\newdimen\bottomheight \bottomheight = \topheight
+
+\newcount\layoutlines \layoutlines = 0
+\newcount\layoutcolumns \layoutcolumns = 0
+\newdimen\layoutcolumndistance \layoutcolumndistance = 0pt
+\newdimen\layoutcolumnwidth \layoutcolumnwidth = 0pt
+
+%D We can save some tokens and fuzzy parameters by using a
+%D symbolic name for the current set of layout parameters.
+
+\let\currentlayout\empty
+
+\def\layoutparameter#1%
+ {\csname\??ly\ifcsname
+ \??ly\currentlayout#1\endcsname\currentlayout
+ \fi#1\endcsname}
+
+\def\namedlayoutparameter#1#2%
+ {\csname\??ly\ifcsname\??ly #1#2\endcsname#1\else
+ \ifcsname\??ly\currentlayout#2\endcsname\currentlayout
+ \fi\fi#2\endcsname}
+
+%D Beause normal \TEX\ has at most 256 dimensions (of which a
+%D substantial part is already in use), we provide a way to
+%D generate a format with macro based alternatives. For a long
+%D time, this used to be the default case. Beware: only fixed
+%D dimensions can be used in calculations! By the way, the
+%D gain in speed can hardly be called impressive and is roughly
+%D 1 second on a 35 second run of 850 empty pages with a
+%D couple of backgrounds only (which is far less than one
+%D percent on a normal document).
+
+%D The next series of dimensions are complemented by left
+%D and rights ones.
+
+\newdimen \margindistance
+\newdimen \edgedistance
+\newdimen \marginwidth
+\newdimen \edgewidth
+
+%D Because a distance does not really makes sense when there
+%D is no area, we use a zero distance in case there is no
+%D area.
+
+\def\layoutdistance#1#2%
+ {\ifdim\zeropoint<#1\layoutparameter#2\else\zeropoint\fi}
+
+%D The horizontal distances are:
+
+\newdimen \leftedgedistance
+\newdimen \rightedgedistance
+\newdimen \leftmargindistance
+\newdimen \rightmargindistance
+
+%D The vertical distances are:
+
+\newdimen \topdistance
+\newdimen \headerdistance
+\newdimen \footerdistance
+\newdimen \bottomdistance
+
+%D We need to calculate the extra distances:
+
+\def\setlayoutdimensions
+ {\global\marginwidth \layoutparameter\c!margin
+ \global\edgewidth \layoutparameter\c!edge
+ \global\margindistance \layoutparameter\c!margindistance
+ \global\edgedistance \layoutparameter\c!edgedistance
+ \global\leftedgedistance \layoutdistance \leftedgewidth \c!leftedgedistance
+ \global\rightedgedistance \layoutdistance \rightedgewidth \c!rightedgedistance
+ \global\leftmargindistance \layoutdistance \leftmarginwidth \c!leftmargindistance
+ \global\rightmargindistance\layoutdistance \rightmarginwidth \c!rightmargindistance
+ \global\topdistance \layoutdistance \topheight \c!topdistance
+ \global\headerdistance \layoutdistance \headerheight \c!headerdistance
+ \global\footerdistance \layoutdistance \footerheight \c!footerdistance
+ \global\bottomdistance \layoutdistance \bottomheight \c!bottomdistance}
+
+\def\setlayoutdistances % local in \setreducedvsize
+ {\headerdistance\layoutdistance\headerheight\c!headerdistance
+ \footerdistance\layoutdistance\footerheight\c!footerdistance}
+
+% these are wrong in the running text, assumes some swapping, needs a cleanup
+
+\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth }
+\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth}
+\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
+\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}
+
+\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth }
+\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth}
+\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance }
+\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance}
+
+\def\outerspacewidth {\rightorleftpageaction\cutspace\backspace}
+\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace}
+
+\newtoks\extralayoutcalculations \def\calculatelayoutextras{\the\extralayoutcalculations}
+
+% \appendtoks
+% non etex calculations used to go here
+% \to \extralayoutcalculations
+
+\newtoks\everyswapmargins % watch the order !
+
+\appendtoks
+ \swapdimens\leftmargindistance\rightmargindistance
+ \swapdimens\leftedgedistance \rightedgedistance
+ \swapdimens\leftmarginwidth \rightmarginwidth
+ \swapdimens\leftedgewidth \rightedgewidth
+\to \everyswapmargins
+
+\appendtoks
+ \swapmacros\leftmargintotal \rightmargintotal
+ \swapmacros\leftedgetotal \rightedgetotal
+ \swapmacros\leftsidetotal \rightsidetotal
+ \swapmacros\leftcombitotal \rightcombitotal
+ \swapmacros\innermargintotal\outermargintotal
+ \swapmacros\inneredgetotal \outeredgetotal
+ \swapmacros\innercombitotal \outercombitotal
+ \swapmacros\innersidetotal \outersidetotal
+\to \everyswapmargins
+
+%D \macros
+%D {definepapersize}
+%D
+%D Before we start calculating layout dimensions, we will
+%D first take care of paper sizes. The first argument can be
+%D either an assignment (for defaults) or an identifier, in
+%D which case the second argument is an assignment.
+%D
+%D \showsetup{definepapersize}
+
+\unexpanded\def\definepapersize
+ {\dodoubleempty\dodefinepapersize}
+
+\unexpanded\def\definepapersize
+ {\dotripleempty\dodefinepapersize}
+
+\def\dodefinepapersize[#1][#2][#3]%
+ {\ifsecondargument
+ \doifsomething{#1} % to be sure
+ {\doifassignmentelse{#2}
+ {\getparameters
+ [\??pp#1] % geen \c!scale, scheelt hash ruimte
+ [\c!width=\@@ppwidth,\c!height=\@@ppheight,\c!offset=\@@ppoffset,#2]}
+ {\setvalue{\??pp:1:#1}{#2}%
+ \setvalue{\??pp:2:#1}{#3}}}%
+ \else
+ \getparameters[\??pp][#1]%
+ \setuppapersize % hm. this will freeze !
+ \fi}
+
+%D For the moment we need to fake this macro.
+
+\ifx\setuppapersize\undefined
+ \let\setuppapersize\relax
+\fi
+
+%D We set the defaults to the dimensions of an A4 sheet of
+%D paper.
+
+\definepapersize
+ [\c!width=210mm,\c!height=297mm,\c!offset=\zeropoint]
+
+%D Yet undocumented, let's see if it gets noticed.
+%D
+%D \starttyping
+%D \definepapersize[main] [A4] [A4]
+%D \definepapersize[extra][A4,landscape][A4,landscape]
+%D
+%D \starttext
+%D \setuppapersize[main]
+%D Page 1. \page
+%D Page 2. \page
+%D \setuppapersize[extra]
+%D Page 2 \page
+%D \setuppapersize[main]
+%D Page 3. \page
+%D Page 4. \page
+%D \adaptpapersize[extra]
+%D Page 5. \page
+%D Page 6. \page
+%D \stoptext
+%D \stoptyping
+
+%D \macros
+%D {setuppaper,setuppapersize}
+%D
+%D When setting up the papersize on which to typeset and
+%D print, we can also determine some more characteristics.
+%D
+%D \showsetup{setuppapersize}
+%D
+%D We keep track of these features with the following
+%D variables.
+
+\chardef\papermirror =0 \chardef\printmirror =0
+\chardef\paperorientation=0 \chardef\printorientation=0 % beware: later no chardef
+\chardef\paperreverse =0 \chardef\printreverse =0
+\chardef\paperlandscape =0 \chardef\printlandscape =0
+
+\let\papersize\empty \let\printpapersize\empty
+
+\def\paperscale{1} \newif\ifnegateprintbox
+
+\unexpanded\def\setuppaper[#1]%
+ {\getparameters[\??pp][\c!paper=,\c!page=,#1]%
+ \edef\@@ppxy{\the\numexpr\@@ppnx*\@@ppny\relax}%
+ \doifelsenothing\@@pppage
+ {\doifelsenothing\@@pppaper
+ {} % {\setuppapersize} % added, removed, no need for, too tricky, mag-01 (fixed by freezing pp's)
+ {\dodosetuppapersize[\papersize][\@@pppaper]}}
+ {\doifelsenothing\@@pppaper
+ {\dodosetuppapersize[\@@pppage][\printpapersize]}
+ {\dodosetuppapersize[\@@pppage][\@@pppaper]}}}
+
+\unexpanded\def\setuppapersize
+ {\dodoubleempty\dosetuppapersize}
+
+\def\dosetuppapersize[#1][#2]%
+ {\doifassignmentelse{#1}
+ {\setuppaper[#1]}
+ {\doifelsenothing{#2}
+ {\expanded{\dodosetuppapersize
+ [\executeifdefined{\??pp:1:#1}{#1}]%
+ [\executeifdefined{\??pp:2:#1}{}]}}
+ {\doifassignmentelse{#2}
+ {\getparameters[\??pp\executeifdefined{\??pp:1:#1}{#1}][#2]}
+ {\expanded{\dodosetuppapersize
+ [\executeifdefined{\??pp:1:#1}{#1}]%
+ [\executeifdefined{\??pp:1:#2}{#2}]}}}}}
+
+\let\reinstatepapersize\relax
+
+\def\adaptpapersize
+ {\global\let\reinstatepapersize\restorepapersize
+ \setuppapersize}
+
+\appendtoks
+ \reinstatepapersize
+ \global\let\reinstatepapersize\relax
+\to \everyaftershipout
+
+\def\dodosetuppapersize[#1][#2]%
+ {\ifsecondargument
+ \expanded{\dododosetuppapersize[#1][#2]}%
+ \calculatehsizes
+ \calculatevsizes
+ \recalculatebackgrounds
+ \recalculatelayout
+ \else\iffirstargument
+ \setuppapersize[#1][#2]%
+ \else\ifx\papersize\undefined\else
+ \restorepapersize
+ \fi\fi\fi}
+
+% dimen freeze is a bit tricky, but catches local redundant calls
+% with values where e.g width is defined in terms of \paperwidth
+
+\def\dododosetuppapersize[#1][#2]%
+ {\xdef\restorepapersize{\noexpand\setuppapersize[#1][#2]}%
+ \dosetuppaperorientation{#1}\paperlandscape\paperorientation\paperreverse\papermirror
+ \dosetuppaperorientation{#2}\printlandscape\printorientation\printreverse\printmirror
+ \def\docommand##1%
+ {\doifsomething{##1}{\doifdefined{\??pp##1\c!width}
+ {\global\paperwidth \getvalue{\??pp##1\c!width}%
+ \global\paperheight\getvalue{\??pp##1\c!height}%
+ \ifinpagebody
+ \setevalue{\??pp##1\c!height}{\the\paperheight}%
+ \setevalue{\??pp##1\c!width }{\the\paperwidth }%
+ \fi
+ \calculatepaperoffsets{##1}%
+ \xdef\papersize{##1}}}}%
+ \processcommacommand[#1]\docommand
+ \doifdefinedelse{\??pp#1\c!scale}
+ {\edef\paperscale{\getvalue{\??pp#1\c!scale}}}
+ {\edef\paperscale{1}}%
+ \def\docommand##1%
+ {\doifsomething{##1}{\doifdefined{\??pp##1\c!width}
+ {\global\printpaperwidth \getvalue{\??pp##1\c!width}%
+ \global\printpaperheight\getvalue{\??pp##1\c!height}%
+ \ifinpagebody
+ \setevalue{\??pp##1\c!height}{\the\printpaperheight}%
+ \setevalue{\??pp##1\c!width }{\the\printpaperwidth}%
+ \fi
+ \xdef\printpapersize{##1}}}}%
+ \processcommacommand[#2]\docommand
+ \global\setdimentoatleast\paperwidth \onepoint
+ \global\setdimentoatleast\paperheight \onepoint
+ \global\setdimentoatleast\printpaperwidth \onepoint
+ \global\setdimentoatleast\printpaperheight\onepoint
+ \ifcase\paperlandscape\else
+ \doglobal\swapdimens\paperwidth\paperheight
+ \fi
+ \ifcase\printlandscape\else
+ \doglobal\swapdimens\printpaperwidth\printpaperheight
+ \fi
+ % this check can be confusing, so we've added the possibility
+ % to bypass this test: \setuppapersize[option=fit]
+ \doif\@@ppoption\v!max % \v!fit is
+ {\bgroup
+ % we need to pre-swap else we get the wrong paper size
+ \ifcase\paperorientation\else
+ \doifinset\paperorientation{90,270}{\swapdimens\paperwidth\paperheight}%
+ \fi
+ \ifcase\printorientation\else
+ \doifinset\printorientation{90,270}{\swapdimens\printpaperwidth\printpaperheight}%
+ \fi
+ \ifdim\paperheight>\printpaperheight
+ \global\printpaperheight\paperheight
+ \writestatus\m!systems{print height forced to paper height}%
+ \fi
+ \ifdim\paperwidth>\printpaperwidth
+ \global\printpaperwidth\paperwidth
+ \writestatus\m!systems{print width forced to paper width}%
+ \fi
+ \egroup}}
+
+\def\dosetuppaperorientation#1#2#3#4#5%
+ {\global\chardef#2\zerocount
+ \global\chardef#5\zerocount
+ \globallet#3\!!zerocount
+ \globallet#4\!!zerocount
+ \global\negateprintboxfalse
+ \processallactionsinset
+ [#1]
+ [ \v!landscape=>\global\chardef#2\plusone,
+ \v!mirrored=>\global\chardef#5\plusone,
+ \v!rotated=>\gdef#3{90}\gdef#4{270},
+ \v!negative=>\global\negateprintboxtrue,
+ 90=>\gdef#3{90}\gdef#4{270},
+ 180=>\gdef#3{180}\gdef#4{0},
+ 270=>\gdef#3{270}\gdef#4{90}]}
+
+\ifx\calculatepaperoffsets\undefined
+
+ \def\calculatepaperoffsets#1%
+ {\scratchdimen\getvalue{\??pp#1\c!offset}%
+ \global\advance\paperwidth -2\scratchdimen
+ \global\advance\paperheight-2\scratchdimen}
+
+\fi
+
+\let\restorepapersize\relax
+
+% \def\docheckforems#1%
+% {\beforesplitstring#1\at em\to\asciia
+% \doifnot\asciia{#1}
+% {\aftersplitstring\asciia\at=\to\asciia
+% \doifsomething\asciia{\showmessage\m!systems{10}{#1}}}}
+%
+% \def\checkforems[#1]%
+% {\processcommalist[#1]\docheckforems}
+
+\ifx\setups\undefined \unexpanded\def\setups[#1]{\setdefaultpenalties} \fi
+
+% \newtoks \everybeforelayout \relax
+% \newtoks \everyafterlayout \relax
+
+\def\recalculatelayout
+ {\doifsomething{\layoutparameter\c!page\layoutparameter\c!paper}
+ {\expanded{\dododosetuppapersize[\layoutparameter\c!page][\layoutparameter\c!paper]}}%
+ \dorecalculatelayout}
+
+\ifdefined\docheckgridsnapping \else \let\docheckgridsnapping\relax \fi
+
+\def\dorecalculatelayout
+ {%\the\everybeforelayout
+ \setups[\layoutparameter\c!preset]%
+ \global\leftmarginwidth \layoutparameter\c!leftmargin
+ \global\rightmarginwidth\layoutparameter\c!rightmargin
+ \global\leftedgewidth \layoutparameter\c!leftedge
+ \global\rightedgewidth \layoutparameter\c!rightedge
+ \global\headerheight \layoutparameter\c!header
+ \global\footerheight \layoutparameter\c!footer
+ \global\bottomheight \layoutparameter\c!bottom
+ \global\topheight \layoutparameter\c!top
+ \global\backspace \layoutparameter\c!backspace
+ \global\topspace \layoutparameter\c!topspace
+ \setlayoutdimensions % the rest of the `dimensions'
+ \docheckgridsnapping
+ \doprocesslocalsetups{\layoutparameter\c!setups}% depends on gridsnapping !
+ \simplesetupwhitespace
+ \simplesetupblank
+ \setupinterlinespace[\v!reset]% \synchronizegloballinespecs
+ \global\cutspace\layoutparameter\c!cutspace
+ \relax
+ \doifelse{\layoutparameter\c!width}\v!middle
+ {\ifdim\cutspace=\zeropoint
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax}
+ {\doifelse{\layoutparameter\c!width}\v!fit
+ {\ifdim\cutspace=\zeropoint
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax
+ \scratchdimen\dimexpr\backspace
+ -\leftedgewidth -\leftedgedistance
+ -\leftmarginwidth-\leftmargindistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupwidth\dimexpr
+ -\rightmargindistance-\rightmarginwidth
+ -\rightedgedistance -\rightedgewidth
+ -\scratchdimen\relax}
+ {\global\makeupwidth\layoutparameter\c!width\relax
+ \ifdim\cutspace=\zeropoint
+ \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax
+ % \else
+ % A kind of inconsistent specification, but used
+ % in for instance s-pre-19.tex; the cutspace is
+ % used only for determining some kind of right
+ % margin; don't use this in doublesided mode
+ \fi}}%
+ \scratchdimen\layoutparameter\c!bottomspace\relax
+ %\ifdim\scratchdimen=\zeropoint
+ % \scratchdimen\topspace
+ %\fi
+ \global\bottomspace\layoutparameter\c!bottomspace\relax
+ \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty
+ \ifcase\layoutlines
+ \doifelse{\layoutparameter\c!height}\v!middle
+ {\ifdim\bottomspace=\zeropoint
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax}
+ {\doifelse{\layoutparameter\c!height}\v!fit
+ {\ifdim\bottomspace=\zeropoint
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\bottomspace\relax
+ \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax
+ \ifdim\scratchdimen<\zeropoint
+ \scratchdimen\zeropoint
+ \fi
+ \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax}
+ {\global\makeupheight\layoutparameter\c!height\relax
+ \ifdim\bottomspace=\zeropoint
+ \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax
+ \else
+ % inconsistent specification
+ \fi}}%
+ \else
+ % beware, when the bodyfont changes (switched) this will change as well; implementing
+ % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set
+ % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we
+ % stick to the current method (after a night of experimenting ...2003/10/13)
+ \global\makeupheight\dimexpr
+ \layoutparameter\c!lines\lineheight-\strutheight+\topskip+
+ \headerdistance+\headerheight+\footerdistance+\footerheight\relax
+ \fi
+ \backoffset\layoutparameter\c!horoffset
+ \topoffset \layoutparameter\c!veroffset
+ \global\setdimentoatleast\makeupwidth\onepoint
+ \global\setdimentoatleast\makeupheight \onepoint
+ % \checkcurrentlayout % here ?
+ % \the\everyafterlayout
+ \calculatelayoutextras
+ \calculatehsizes
+ \calculatevsizes
+ \calculatepseudocolumns
+ \recalculatebackgrounds}
+
+\def\calculatepseudocolumns
+ {\global\layoutcolumns\layoutparameter\c!columns
+ \global\layoutcolumndistance\layoutparameter\c!columndistance
+ \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax
+ \global\divide\layoutcolumnwidth\layoutcolumns
+ \dorecurse\layoutcolumns
+ {\setxvalue{\??ly:c:\recurselevel}%
+ {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}}}
+
+%\dorecurse\layoutcolumns
+% {\setxvalue{\??ly:c:\recurselevel}{\the\dimexpr
+% (\numexpr(\recurselevel-1)\dimexpr(\layoutcolumnwidth+\layoutcolumndistance))}}
+
+\def\layoutcolumnoffset#1%
+ {\executeifdefined{\??ly:c:#1}\zeropoint}
+
+\def\checklayout
+ {\ifdim\makeupheight=\layoutlines\lineheight \else \recalculatelayout \fi}
+
+\appendtoks \checklayout \to \everystarttext
+
+% document:
+%
+% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page]
+%
+% \startstandardmakeup[page=blank] ... \stopstandardmakeup
+
+\def\changetolayout#1%
+ {%\writestatus\m!layouts{changing to layout #1}%
+ \xdef\currentlayout{#1}\recalculatelayout}
+
+\def\checkcurrentoddlayout
+ {\ifcsname\??ly\v!odd\c!state\endcsname
+ \doifvalue{\??ly\v!odd\c!state}\v!start{\changetolayout\v!odd}%
+ \fi}
+
+\def\checkcurrentevenlayout
+ {\ifcsname\??ly\v!even\c!state\endcsname
+ \doifvalue{\??ly\v!even\c!state}\v!start{\changetolayout\v!even}%
+ \fi}
+
+\ifx\lastpage\undefined \def\lastpage{1} \fi
+
+\def\reverserealfolio
+ {\ifnum\lastpage>\plusone
+ \ifnum\lastpage=\realfolio
+ \v!last
+ \else\ifnum\plusone=\realfolio
+ \v!first
+ \else
+ \the\numexpr\realfolio-\lastpage\relax
+ \fi\fi
+ \else
+ \!!zerocount
+ \fi}
+
+\def\checkcurrentlayout % public and used in naw, so keep this name
+ {\ifcsname\??ly\realfolio\c!state\endcsname
+ \doifvalue{\??ly\realfolio\c!state}\v!start{\changetolayout\realfolio}%
+ \else\ifcsname\??ly\reverserealfolio\c!state\endcsname
+ \doifvalue{\??ly\reverserealfolio\c!state}\v!start{\changetolayout\reverserealfolio}%
+ \else\ifcsname\??ly\v!current\c!state\endcsname
+ \changetolayout\v!current % no start test ?
+ \else
+ \doifoddpageelse\checkcurrentoddlayout\checkcurrentevenlayout
+ \fi\fi\fi}
+
+% testcase
+%
+% \setuppagenumbering[alternative=doublesided]
+%
+% \setuplayout [width=11cm]
+% \definelayout [odd] [backspace=1cm]
+% \definelayout [even] [backspace=4cm]
+% \definelayout [5] [backspace=5cm]
+% \definelayout [6] [backspace=5cm]
+% \definelayout [-2] [backspace=0cm,cutspace=0cm]
+% \definelayout [last] [backspace=0cm,cutspace=0cm]
+%
+% \checkcurrentlayout \showframe
+%
+% \starttext
+% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf}
+% \stoptext
+
+%appendtoks \checkcurrentlayout \to \everyaftershipout % no
+\appendtoks \checkcurrentlayout \to \everystarttext
+
+\appendtoks
+ \dochecknextlayout
+\to \everyaftershipout
+
+% \def\dochecknextlayout
+% {\ifx\currentlayout\v!current
+% % prevent redundant calculations
+% \else
+% \globallet\currentlayout\empty
+% \global\letbeundefined{\??ly\v!current\c!state}%
+% \checkcurrentlayout
+% \fi}
+%
+% this breaks after a standardmakeup
+
+\def\dochecknextlayout{\checkcurrentlayout}
+
+\newif\ifdoublesidedprint
+
+\def\presetcenterpagebox % in \setuplayout !!!!!!!!!!!!!!!!
+ {\doublesidedprintfalse
+ \normalexpanded{\noexpand\processallactionsinset[\@@lylocation]}
+ [ \v!middle=>{\setuppapersize[\c!left=\hss,\c!right=\hss,\c!top=\vss,\c!bottom=\vss]},
+ \v!left=>{\setuppapersize[\c!left=,\c!right=\hss]},
+ \v!right=>{\setuppapersize[\c!left=\hss,\c!right=]},
+ \v!bottom=>{\setuppapersize[\c!top=\vss,\c!bottom=]},
+ \v!top=>{\setuppapersize[\c!top=,\c!bottom=\vss]},%
+ \v!doublesided=>\doublesidedprinttrue,
+ \v!singlesided=>\doublesidedprintfalse]}
+
+\unexpanded\def\definelayout
+ {\dodoubleargument\dodefinelayout}
+
+\def\dodefinelayout[#1][#2]%
+ {\getparameters[\??ly#1][\c!state=\v!start,#2]}
+
+% \def\dodosetuplayout[#1][#2]%
+% {\ConvertToConstant\doifnot{#2}\v!reset % #2 ?
+% {\getparameters[\??ly#1][#2]%
+% \checkforems[#2]}}
+
+\def\dodosetuplayout[#1][#2]%
+ {\doifnot{#2}\v!reset{\getparameters[\??ly#1][#2]}}
+
+% global needed for non-doublesided standardmakeup
+
+\def\dosetuplayout[#1][#2]%
+ {\globallet\currentlayout\empty % new, global
+ \ifsecondargument
+ \dodosetuplayout[#1][#2]%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\dodosetuplayout[][#1]}
+ {\doifnot{#1}\v!reset{\xdef\currentlayout{#1}}}% new, global
+ \fi\fi
+ \recalculatelayout
+ \checkcurrentlayout % here ?
+ \presetcenterpagebox}
+
+\unexpanded\def\setuplayout
+ {\dodoubleempty\dosetuplayout}
+
+\let\@@zaheight\!!zeropoint
+
+\def\dopushpagedimensions
+ {\xdef\oldtextheight {\the\textheight }%
+ \xdef\oldfooterheight{\the\footerheight}%
+ \global\let\@@zaheight\@@zaheight}
+
+\def\dopoppagedimensions
+ {\global\textheight \oldtextheight
+ \global\footerheight\oldfooterheight
+ \recalculatelayout
+ \global\let\pushpagedimensions\dopushpagedimensions
+ \global\let\poppagedimensions\relax}
+
+\let\poppagedimensions \relax
+\let\pushpagedimensions\dopushpagedimensions
+
+% Elke \csname ... \endcsname wordt ook aangemaakt, dus ook
+% in een test met \doifdefined. Bij veel bladzijden kan dit
+% te veel macro's kosten. Vandaar de set \adaptedpages. Het
+% kost tijd, maar scheelt macro's.
+
+\let\adaptedpages\empty
+
+\def\adaptpagedimensions
+ {\ifx\adaptedpages\empty\else
+ \adaptpagedimensionsindeed
+ \fi}
+
+\def\adaptpagedimensionsindeed
+ {\rawdoifinset\realfolio\adaptedpages
+ {\removefromcommalist\realfolio\adaptedpages
+ \getvalue{\??za\realfolio}%
+ \letbeundefined{\??za\realfolio}}}
+
+\def\checkpagedimensions
+ {\poppagedimensions
+ \adaptpagedimensions}
+
+\def\reportpagedimensions
+ {\ifx\poppagedimensions\relax \else
+ \space\the\dimexpr\@@zaheight\relax\space-\space
+ \fi
+ \realfolio}
+
+\def\dodoadaptlayout[#1]%
+ {\getparameters[\??za][\c!height=,\c!lines=0,#1]%
+ \pushpagedimensions
+ \ifcase\@@zalines\relax
+ \showmessage\m!layouts1{\@@zaheight,\realfolio}%
+ \else
+ \showmessage\m!layouts1{\@@zalines\space\v!lines,\realfolio}%
+ \def\@@zaheight{\@@zalines\openlineheight}%
+ \fi
+ \doifelse\@@zaheight\v!max
+ {\balancedimensions\textheight\footerheight\footerheight}
+ {\balancedimensions\textheight\footerheight\@@zaheight}%
+ \ifdim\footerheight<\zeropoint
+ \global\advance\textheight \footerheight
+ \global\footerheight\zeropoint
+ \global\xdef\@@zaheight{\layoutparameter\c!footer\space(\v!max)}%
+ \fi
+ \setvsize
+ \global\pagegoal\vsize % nog corrigeren voor insertions ?
+ \recalculatebackgrounds
+ \global\let\pushpagedimensions\relax
+ \global\let\poppagedimensions\dopoppagedimensions}
+
+\def\doadaptlayout[#1][#2]%
+ {\doifelsenothing{#2}
+ {\dodoadaptlayout[#1]}
+ {\def\docommand##1%
+ {\addtocommalist{##1}\adaptedpages
+ \setgvalue{\??za##1}{\dodoadaptlayout[#2]}}%
+ \processcommalist[#1]\docommand
+ \adaptpagedimensions}}
+
+\def\adaptlayout
+ {\dodoubleempty\doadaptlayout}
+
+% describe interface
+
+%D Centering the paper area on the print area is determined
+%D by the \type {top}, \type {bottom}, \type {left} and \type
+%D {right} parameters.
+
+\def\centerpagebox#1%
+ {\printpaperwidth \paperscale\printpaperwidth
+ \printpaperheight\paperscale\printpaperheight
+ \setbox#1\vbox to \printpaperheight
+ {\@@pptop
+ \hbox to \printpaperwidth
+ {\ifdoublesidedprint
+ \doifbothsides
+ {\@@ppleft \box#1\@@ppright}
+ {\@@ppleft \box#1\@@ppright}
+ {\@@ppright\box#1\@@ppleft }%
+ \else
+ \@@ppleft \box#1\@@ppright
+ \fi}%
+ \par
+ \@@ppbottom}}
+
+\def\offsetprintbox#1%
+ {\ifdim\topoffset=\zeropoint % \relax
+ \ifdim\backoffset=\zeropoint
+ \donefalse
+ \else
+ \donetrue
+ \fi
+ \else
+ \donetrue
+ \fi
+ \ifdone
+ \edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
+ \setbox#1\vbox
+ {\offinterlineskip
+ \vskip\topoffset
+ \hskip\doifbothsides\backoffset\backoffset{-\backoffset}%
+ \box#1}%
+ \next
+ \fi}
+
+\def\replicatepagebox#1%
+ {\ifnum\@@lynx>\plusone
+ \donetrue
+ \else\ifnum\@@lyny>\plusone
+ \donetrue
+ \else
+ \donefalse
+ \fi\fi
+ \ifdone
+ \setbox#1\vbox
+ {\offinterlineskip
+ \dorecurse\@@lyny
+ {\hbox{\dorecurse\@@lynx{\copy#1\hskip\@@lydx}\unskip}%
+ \vskip\@@lydy}
+ \unskip}%
+ \fi}
+
+\def\orientpagebodybox#1#2#3%
+ {\ifnum#2#3>\zerocount
+ \setbox#1\vbox
+ {\edef\somerotation{\ifdoublesided\ifodd\realpageno#2\else#3\fi\else#2\fi}%
+ \dorotatebox\somerotation\hbox{\box#1}}%
+ \fi}
+
+\def\orientpaperbox#1%
+ {\orientpagebodybox{#1}\paperorientation\paperreverse}
+
+\def\orientprintbox#1%
+ {\orientpagebodybox{#1}\printorientation\printreverse}
+
+\def\mirrorpagebodybox#1#2%
+ {\ifcase#2\or
+ \setbox#1\vbox{\domirrorbox\vbox{\box#1}}%
+ \fi}
+
+\def\mirrorpaperbox#1%
+ {\mirrorpagebodybox{#1}\papermirror}
+
+\def\mirrorprintbox#1%
+ {\mirrorpagebodybox{#1}\printmirror}
+
+\def\scalepagebox#1%
+ {\ifdim\@@lyscale\points=\onepoint \else
+ \setbox#1\vbox{\scale[\c!sx=\@@lyscale,\c!sy=\@@lyscale]{\box#1}}%
+ \paperwidth \@@lyscale\paperwidth
+ \paperheight\@@lyscale\paperheight
+ \fi}
+
+\def\negateprintbox#1%
+ {\ifnegateprintbox
+ \negatecolorbox{#1}%
+ \fi}
+
+\def\pagecutmarksymbol {\the\realpageno}
+\def\pagecutmarklength {.5cm}
+\let\pagecutmarktoptext \empty
+\let\pagecutmarkbottomtext \empty
+
+\def\extrapagecutmarkbottomtext
+ {\rlap{\jobname}\hfill\currentdate\space-\space\currenttime\hfill\llap{\realfolio}}
+
+\def\makepagecutbox % #1
+ {\let\cutmarksymbol \pagecutmarksymbol
+ \let\cutmarklength \pagecutmarklength
+ \let\cutmarktoptext \pagecutmarktoptext
+ \let\cutmarkbottomtext\pagecutmarkbottomtext
+ \makecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!on}%
+ {\makepagecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!page}% only at outer when nx/ny > 0
+ {\makepagecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!empty}%
+ {\let\pagecutmarksymbol\empty
+ \let\pagecutmarktoptext\empty
+ \let\pagecutmarkbottomtext\empty
+ \makepagecutbox}
+
+\setvalue{\??ly:n:\c!marking:\v!text}%
+ {\let\pagecutmarksymbol\empty
+ \let\pagecutmarkbottomtext\extrapagecutmarkbottomtext
+ \makepagecutbox}
+
+\setvalue{\??ly:c:\c!marking:\v!color}%
+ {\doaddpagecolormarks\colormarkbox}
+
+\setvalue{\??ly:c:\c!marking:\v!screen}%
+ {\doaddpagecolormarks\rastermarkbox}
+
+\letvalue{\??ly:c:\c!marking:\v!unknown}\gobbleoneargument
+\letvalue{\??ly:n:\c!marking:\v!unknown}\gobbleoneargument
+
+% \def\addpagecutmarks {\executeifdefined{\??ly:n:\c!marking:\@@lymarking}\gobbleoneargument}
+% \def\addpagecolormarks{\executeifdefined{\??ly:c:\c!marking:\@@lymarking}\gobbleoneargument}
+
+\def\addpagecutmarks {\expandcheckedcsname{\??ly:n:\c!marking:}\@@lymarking\s!unknown}
+\def\addpagecolormarks{\expandcheckedcsname{\??ly:c:\c!marking:}\@@lymarking\s!unknown}
+
+\def\doaddpagecolormarks#1#2%
+ {\makepagecutbox{#2}%
+ \ifnum\horizontalcutmarks>\plustwo \chardef\colormarkoffset\plusfour \fi
+ \ifnum\verticalcutmarks >\plustwo \chardef\colormarkoffset\plusfour \fi
+ #1{#2}}
+
+% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET
+
+\ifx\doifelselayoutsomeline\undefined % defined in page-txt
+ \let\doifelselayoutsomeline\secondofthreearguments
+\fi
+
+\def\compensatevsizeheader {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
+\def\compensatevsizefooter {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
+\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
+\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
+
+\def\compensatevsizeheaderzero{\headerheight\zeropoint\setlayoutdistances}
+\def\compensatevsizefooterzero{\footerheight\zeropoint\setlayoutdistances}
+
+\def\calculatevsizes
+ {\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing
+ \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing
+ \setvsizemodes
+ \resetglobal
+ \setvsize}
+
+\def\calculateglobalvsizes
+ {\global\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing
+ \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing
+ \setvsizemodes
+ \setvsize}
+
+\def\setvsizemodes
+ {\ifzeropt\headerheight
+ \resetsystemmode\v!header
+ \else
+ \setsystemmode\v!header
+ \fi
+ \ifzeropt\footerheight
+ \resetsystemmode\v!footer
+ \else
+ \setsystemmode\v!footer
+ \fi}
+
+\def\calculatereducedvsizes
+ {\textheight\makeupheight
+ \doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero
+ \doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero}
+
+\newdimen\innermakeupwidth % special purpose
+\newdimen\innermakeupmargin % special purpose
+
+\chardef\innermakeupcompensation\plusone
+
+\def\compensatedinnermakeupmargin
+ {\dimexpr\ifnum\innermakeupcompensation=\plusone+\innermakeupmargin\else\zeropoint\fi\relax}
+
+\def\freezetextwidth % \makeupwidth may be set to \textwidth
+ {\textwidth\makeupwidth % which is a tricky but valid value
+ \doifsomething{\layoutparameter\c!textwidth}
+ {\textwidth\layoutparameter\c!textwidth}% % local
+ \global\innermakeupwidth\textwidth
+ \doifelsenothing{\layoutparameter\c!textmargin}
+ {\global\innermakeupmargin\zeropoint}
+ {\global\innermakeupmargin\layoutparameter\c!textmargin}%
+ \global\advance\innermakeupwidth-\dimexpr\innermakeupmargin+\innermakeupmargin\relax
+ \advance\textwidth-\dimexpr\innermakeupmargin+\innermakeupmargin\relax} % local
+
+\def\calculatehsizes
+ {\freezetextwidth
+ \sethsize}
+
+% De onderstaande macro voert commando's uit, afhankelijk van
+% het karakter van het paginanummer.
+%
+% \doifoddpageelse{then-commando}{else-commando}
+
+%D When we start at an even page, we need to swap the layout
+%D differently. We cannot adapt the real page number, since
+%D it is used in cross referencing. The next switch is set
+%D when we start at an even page.
+
+% We could use nested if here plus some \@EAEAEA's but but the
+% next variant has less expansion which is nicer in tracing.
+
+\def\doifoddpageelse {\ifodd\pagenoshift\expandafter\doifoddpageelseyes \else\expandafter\doifoddpageelsenop \fi}
+\def\doifoddpageelseyes{\ifodd\realpageno \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments \fi}
+\def\doifoddpageelsenop{\ifodd\realpageno \expandafter\firstoftwoarguments \else\expandafter\secondoftwoarguments\fi}
+
+\let\doifonevenpaginaelse\doifoddpageelse
+
+\def\redoifoddpageelse#1{\doifoddpageelse}
+
+\def\doifbothsidesoverruled
+ {\ifdoublesided
+ \expandafter\redoifoddpageelse
+ \else
+ \expandafter\firstofthreearguments
+ \fi}
+
+\def\doifbothsides% #1 #2 #3
+ {\ifdoublesided
+ \expandafter\doifbothsidesindeed
+ \else
+ \expandafter\firstofthreearguments
+ \fi}
+
+\def\doifbothsidesindeed
+ {\ifsinglesided
+ \expandafter\firstofthreearguments
+ \else
+ \expandafter\redoifoddpageelse
+ \fi}
+
+\newdimen\texthoffset
+
+\def\settexthoffset
+ {\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}}
+
+% The next hack is too tricky as we may shipout more pages:
+%
+% \def\freezepagestatechecks
+% {\the\everyfreezepagestatechecks}
+%
+% \newtoks \everyfreezepagestatechecks
+%
+% \appendtoks
+% \doifbothsides
+% {\let\doifbothsides\firstofthreearguments}%
+% {\let\doifbothsides\secondofthreearguments}%
+% {\let\doifbothsides\thirdofthreearguments}%
+% \rightorleftpageaction
+% {\let\rightorleftpageaction\firstoftwoarguments}%
+% {\let\rightorleftpageaction\secondoftwoarguments}%
+% \doifmarginswapelse
+% {\let\doifmarginswapelse\firstoftwoarguments}%
+% {\let\doifmarginswapelse\secondoftwoarguments}%
+% \to \everyfreezepagestatechecks
+%
+% \prependtoks
+% \freezepagestatechecks
+% \to \everybeforeshipout
+
+\def\goleftonpage
+ {\hskip-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}
+
+\def\doifmarginswapelse#1#2%
+ {\doifbothsides{#1}{#1}{#2}}
+
+\def\swapmargins
+ {\doifmarginswapelse\relax\doswapmargins}
+
+\def\doswapmargins
+ {\let\swapmargins \relax % to prevent local swapping
+ \let\doswapmargins\relax % to prevent local swapping
+ \the\everyswapmargins}
+
+\def\rightorleftpageaction
+ {\ifdoublesided
+ \expandafter\rightorleftpageactionindeed
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\rightorleftpageactionindeed
+ {\ifsinglesided
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\doifoddpageelse
+ \fi}
+
+\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth }
+\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth}
+\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
+\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}
+
+\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth }
+\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth}
+\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance }
+\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance}
+
+\def\outerspacewidth {\rightorleftpageaction\cutspace \backspace}
+\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace }
+
+\def\leftmargintotal {\dimexpr\leftmarginwidth +\leftmargindistance \relax}
+\def\rightmargintotal {\dimexpr\rightmarginwidth+\rightmargindistance\relax}
+\def\leftedgetotal {\dimexpr\leftedgewidth +\leftedgedistance \relax}
+\def\rightedgetotal {\dimexpr\rightedgewidth +\rightedgedistance \relax}
+
+\def\leftsidetotal {\dimexpr\leftmarginwidth +\leftedgetotal \relax}
+\def\rightsidetotal {\dimexpr\rightmarginwidth+\rightedgetotal\relax}
+\def\leftcombitotal {\dimexpr\leftmargintotal +\leftedgetotal \relax}
+\def\rightcombitotal {\dimexpr\rightmargintotal+\rightedgetotal\relax}
+
+\def\innermargintotal {\dimexpr\innermarginwidth+\innermargindistance\relax}
+\def\outermargintotal {\dimexpr\outermarginwidth+\outermargindistance\relax}
+\def\inneredgetotal {\dimexpr\inneredgewidth +\inneredgedistance \relax}
+\def\outeredgetotal {\dimexpr\outeredgewidth +\outeredgedistance \relax}
+
+\def\innercombitotal {\dimexpr\innermargintotal+\inneredgetotal\relax}
+\def\outercombitotal {\dimexpr\outermargintotal+\outeredgetotal\relax}
+\def\innersidetotal {\dimexpr\innermarginwidth+\inneredgetotal\relax}
+\def\outersidetotal {\dimexpr\outermarginwidth+\outeredgetotal\relax}
+
+%D \macros
+%D {startlocallayout}
+%D
+%D These macros should be used with care. They permit local
+%D layouts (as used in fitting pages, see \type {page-app.tex}).
+
+%D This is kind of obsolete now that we have \type
+%D {\definelayout}, so this hack will disappear in future
+%D versions.
+
+\unexpanded\def\startlocallayout
+ {\globalpushmacro\restorepapersize
+ \globalpushmacro\currentlayout}
+
+\unexpanded\def\stoplocallayout
+ {\globalpopmacro\currentlayout
+ \globalpopmacro\restorepapersize
+ \restorepapersize
+ \setuplayout}
+
+%D \macros
+%D {showprint, showframe, showlayout, showsetups}
+%D
+%D We predefine a couple of tracing macros.
+%D
+%D \showsetup{showprint}
+%D \showsetup{showframe}
+%D \showsetup{showlayout}
+%D \showsetup{showsetups}
+%D %showsetup{showmargins}
+
+\fetchruntimecommand \showprint {page-run.mkii}
+\fetchruntimecommand \showframe {page-run.mkii}
+\fetchruntimecommand \showlayout {page-run.mkii}
+\fetchruntimecommand \showsetups {page-run.mkii}
+\fetchruntimecommand \showmargins {page-run.mkii}
+
+%D The default dimensions are quite old and will not change.
+%D The funny fractions were introduced when we went from fixed
+%D dimensions to relative ones. Since \CONTEXT\ is a dutch
+%D package, the dimensions are based on the metric system. The
+%D asymmetrical layout is kind of handy for short
+%D quick||and||dirty stapled documents.
+%D
+%D Although valid, it is not a real good idea to use
+%D dimensions based on the \type {em} unit. First of all,
+%D since there are no fonts loaded yet, this dimension makes
+%D no sense, and second, you would loose track of values,
+%D since they could change while going to a new page,
+%D depending on the current font setting.
+
+\setuplayout
+ [ \c!topspace=.08417508418\paperheight, % 2.5cm
+ \c!top=\zeropoint,
+ \c!topdistance=\zeropoint,
+ \c!header=.06734006734\paperheight, % 2.0cm
+ \c!headerdistance=\zeropoint,
+ \c!height=.84175084175\paperheight, % 25.0cm
+ \c!footerdistance=\layoutparameter\c!headerdistance,
+ \c!footer=.06734006734\paperheight, % 2.0cm
+ \c!bottomdistance=\layoutparameter\c!topdistance,
+ \c!bottom=\zeropoint,
+ \c!backspace=.11904761905\paperwidth, % 2.5cm
+ \c!edge=\zeropoint,
+ \c!edgedistance=\layoutparameter\c!margindistance,
+ \c!margin=.12649983170\paperwidth, % snijwit-2*afstand
+ \c!margindistance=.02008341748\paperwidth, % 12.0pt
+ \c!leftedge=\layoutparameter\c!edge,
+ \c!leftedgedistance=\layoutparameter\c!edgedistance,
+ \c!leftmargin=\layoutparameter\c!margin,
+ \c!leftmargindistance=\layoutparameter\c!margindistance,
+ \c!width=.71428571429\paperwidth, % 15.0cm \dimexpr\
+ \c!rightmargindistance=\layoutparameter\c!margindistance,
+ \c!rightmargin=\layoutparameter\c!margin,
+ \c!rightedgedistance=\layoutparameter\c!edgedistance,
+ \c!rightedge=\layoutparameter\c!edge,
+ \c!veroffset=\zeropoint,
+ \c!bottomspace=\zeropoint,
+ \c!horoffset=\zeropoint,
+ \c!cutspace=\zeropoint,
+ \c!textwidth=, % dangerous option -> centered / local
+ \c!textmargin=, % dangerous option -> both sides
+ \c!textdistance=\zeropoint, % shift down on grid
+ \c!style=,
+ \c!color=,
+ \c!marking=\v!off,
+ \c!location=, % \v!singlesided, but empty is signal
+ \c!scale=1,
+ \c!nx=1,
+ \c!ny=1,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!grid=\v!no,
+ \c!preset=,
+ \c!setups=\systemsetupsprefix\s!default,
+ \c!clipoffset=\zeropoint,
+ \c!lines=0,
+ \c!paper=, % for foxet
+ \c!page=, % for foxet
+ \c!columns=1,
+ \c!columndistance=\zeropoint]
+
+%D First we define a whole range of (DIN) papersizes,
+%D of which the A-series makes most sense. We enable checking.
+
+%D We also set some of the parameters that will be used when
+%D positioning the typeset paper onto the print paper.
+
+\setuppaper % (size) % only used in XY imposition
+ [\c!width=\zeropoint,
+ \c!height=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!backspace=\zeropoint,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!nx=1,
+ \c!ny=1,
+ \c!method=\v!normal]
+
+\setuppapersize
+ [\c!option=\v!max,
+ \c!top=,
+ \c!bottom=\vss,
+ \c!left=,
+ \c!right=\hss]
+
+\definepapersize [A0] [\c!width=841mm,\c!height=1189mm]
+\definepapersize [A1] [\c!width=594mm,\c!height=841mm]
+\definepapersize [A2] [\c!width=420mm,\c!height=594mm]
+\definepapersize [A3] [\c!width=297mm,\c!height=420mm]
+\definepapersize [A4] [\c!width=210mm,\c!height=297mm]
+\definepapersize [A5] [\c!width=148mm,\c!height=210mm]
+\definepapersize [A6] [\c!width=105mm,\c!height=148mm]
+\definepapersize [A7] [\c!width=74mm,\c!height=105mm]
+\definepapersize [A8] [\c!width=52mm,\c!height=74mm]
+\definepapersize [A9] [\c!width=37mm,\c!height=52mm]
+\definepapersize [A10] [\c!width=26mm,\c!height=37mm]
+
+\definepapersize [B0] [\c!width=1000mm,\c!height=1414mm]
+\definepapersize [B1] [\c!width=707mm,\c!height=1000mm]
+\definepapersize [B2] [\c!width=500mm,\c!height=707mm]
+\definepapersize [B3] [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm]
+\definepapersize [B4] [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm]
+\definepapersize [B5] [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm]
+\definepapersize [B6] [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm]
+\definepapersize [B7] [\c!width=88mm,\c!height=125mm]
+\definepapersize [B8] [\c!width=62mm,\c!height=88mm] % [\c!width=63mm,\c!height=88mm]
+\definepapersize [B9] [\c!width=44mm,\c!height=62mm] % [\c!width=44mm,\c!height=63mm]
+\definepapersize [B10] [\c!width=31mm,\c!height=44mm]
+
+\definepapersize [C0] [\c!width=917mm,\c!height=1297mm]
+\definepapersize [C1] [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm]
+\definepapersize [C2] [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm]
+\definepapersize [C3] [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm]
+\definepapersize [C4] [\c!width=229mm,\c!height=324mm]
+\definepapersize [C5] [\c!width=162mm,\c!height=229mm]
+\definepapersize [C6] [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm]
+\definepapersize [C7] [\c!width=81mm,\c!height=114mm] % [\c!width=81mm,\c!height=115mm]
+\definepapersize [C8] [\c!width=57mm,\c!height=81mm]
+\definepapersize [C9] [\c!width=40mm,\c!height=57mm]
+\definepapersize [C10] [\c!width=28mm,\c!height=40mm]
+
+%D Per August 2004 the rounding of some (seldom used) sizes
+%D were corrected top the latest DIN specifications. Peter
+%D Rolf came up with these and a few more missing sizes.
+%D Watch out: spaces and slashes!
+
+\definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm]
+\definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm]
+\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm]
+
+%D Because there are no standardized screen sizes, we define
+%D a bunch of sizes with $4:3$ ratios. The \type {S6} size is
+%D nearly as wide as a sheet of \type {A4} paper.
+
+\definepapersize [S3] [\c!width=300pt,\c!height=225pt]
+\definepapersize [S4] [\c!width=400pt,\c!height=300pt]
+\definepapersize [S5] [\c!width=500pt,\c!height=375pt]
+\definepapersize [S6] [\c!width=600pt,\c!height=450pt]
+\definepapersize [S8] [\c!width=800pt,\c!height=600pt]
+\definepapersize [SW] [\c!width=800pt,\c!height=450pt]
+\definepapersize [SM] [\c!width=720pt,\c!height=450pt]
+
+%D These are handy too:
+
+\definepapersize [S33] [\c!width=300pt,\c!height=300pt]
+\definepapersize [S44] [\c!width=400pt,\c!height=400pt]
+\definepapersize [S55] [\c!width=500pt,\c!height=500pt]
+\definepapersize [S66] [\c!width=600pt,\c!height=600pt]
+
+%D One may wonder if \TEX\ should be used for typesetting
+%D \CDROM\ covers, but it does not hurt to have the paper size
+%D ready.
+
+\definepapersize [CD] [\c!width=120mm,\c!height=120mm]
+
+%D The next series is for our English speaking friends who
+%D decided to stick to non metric values. Thanks to Nelson
+%D Beebe for completing the inch based list.
+
+\definepapersize [letter] [\c!width=8.5in,\c!height=11in]
+\definepapersize [ledger] [\c!width=11in,\c!height=17in]
+\definepapersize [tabloid] [\c!width=17in,\c!height=11in]
+
+\definepapersize [legal] [\c!width=8.5in,\c!height=14in]
+\definepapersize [folio] [\c!width=8.5in,\c!height=13in]
+\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in]
+
+\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet
+\definepapersize [B] [\c!width=11in,\c!height=17in] % 2 sheets
+\definepapersize [C] [\c!width=17in,\c!height=22in] % 4 sheets
+
+%D The next set is for Tobias Burnus, who gave me the sizes.
+
+\definepapersize [envelope 9] [\c!width=8.88in,\c!height=3.88in]
+\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in]
+\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in]
+\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in]
+\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in]
+\definepapersize [monarch] [\c!width=7.5in,\c!height=3.88in]
+\definepapersize [check] [\c!width=8.58in,\c!height=3.88in]
+\definepapersize [DL] [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm]
+\definepapersize [E4] [\c!width=280mm,\c!height=400mm]
+
+%D The next three sets are supplied by Taco:
+
+\definepapersize [RA0] [\c!width=860mm,\c!height=1220mm]
+\definepapersize [RA1] [\c!width=610mm,\c!height=860mm]
+\definepapersize [RA2] [\c!width=430mm,\c!height=610mm]
+\definepapersize [RA3] [\c!width=305mm,\c!height=430mm]
+\definepapersize [RA4] [\c!width=215mm,\c!height=305mm]
+
+%D ISO SRA (supplementary raw A) sizes:
+
+\definepapersize [SRA0] [\c!width=900mm,\c!height=1280mm]
+\definepapersize [SRA1] [\c!width=640mm,\c!height=900mm]
+\definepapersize [SRA2] [\c!width=450mm,\c!height=640mm]
+\definepapersize [SRA3] [\c!width=320mm,\c!height=450mm]
+\definepapersize [SRA4] [\c!width=225mm,\c!height=320mm]
+
+%D Swedish thesis formats:
+
+\definepapersize [G5] [\c!width=169mm,\c!height=239mm]
+\definepapersize [E5] [\c!width=155mm,\c!height=220mm]
+
+%D Industry invention:
+
+\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm]
+
+%D We can now default to a reasonable size. We match the print
+%D paper size with the typeset paper size. This setting should
+%D come after the first layout specification (already done).
+
+\setuppapersize
+ [A4][A4]
+
+%D A few goodies:
+
+\definepapersize
+ [oversized]
+ [ \c!width=\dimexpr\paperwidth +1.5cm\relax,
+ \c!height=\dimexpr\paperheight+1.5cm\relax]
+
+\definepapersize
+ [doublesized]
+ [ \c!width=\dimexpr \paperwidth \relax,
+ \c!height=\dimexpr2\paperheight\relax]
+
+\definepapersize
+ [doubleoversized]
+ [ \c!width=\dimexpr \paperheight+1.5cm\relax,
+ \c!height=\dimexpr2\paperwidth +1.5cm\relax]
+
+%D For orthogonality:
+
+\definepapersize
+ [undersized]
+ [ \c!width=\dimexpr\paperwidth -1.5cm\relax,
+ \c!height=\dimexpr\paperheight-1.5cm\relax]
+
+\definelayout
+ [\v!page]
+ [\c!backspace=\zeropoint,
+ \c!cutspace=\zeropoint,
+ \c!topspace=\zeropoint,
+ \c!bottomspace=\zeropoint,
+ \c!margin=\zeropoint,
+ \c!edge=\zeropoint,
+ \c!header=\zeropoint,
+ \c!footer=\zeropoint,
+ \c!top=\zeropoint,
+ \c!bottom=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!leftedge=\zeropoint,
+ \c!rightedge=\zeropoint,
+ \c!textdistance=\zeropoint,
+ \c!width=\v!middle,
+ \c!height=\v!middle,
+ \c!lines=0,
+ \c!grid=\v!no]
+
+\definelayout
+ [\v!middle]
+ [\c!width=\v!middle,
+ \c!height=\v!middle]
+
+\protect \endinput
diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua
new file mode 100644
index 000000000..1f2c96251
--- /dev/null
+++ b/tex/context/base/page-lin.lua
@@ -0,0 +1,215 @@
+if not modules then modules = { } end modules ['page-lin'] = {
+ version = 1.001,
+ comment = "companion to page-lin.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- experimental
+
+local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end)
+
+local format = string.format
+local texsprint, texwrite, texbox = tex.sprint, tex.write, tex.box
+
+local ctxcatcodes = tex.ctxcatcodes
+local variables = interfaces.variables
+
+nodes = nodes or { }
+nodes.lines = nodes.lines or { }
+nodes.lines.data = nodes.lines.data or { } -- start step tag
+
+storage.register("lines/data", nodes.lines.data, "nodes.lines.data")
+
+-- if there is demand for it, we can support multiple numbering streams
+-- and use more than one attibute
+
+local hlist, vlist, whatsit = node.id('hlist'), node.id('vlist'), node.id('whatsit')
+
+local display_math = attributes.private('display-math')
+local line_number = attributes.private('line-number')
+local line_reference = attributes.private('line-reference')
+
+local current_list = { }
+local cross_references = { }
+local chunksize = 250 -- not used in boxed
+
+local has_attribute = node.has_attribute
+local traverse_id = node.traverse_id
+local traverse = node.traverse
+local copy_node = node.copy
+local hpack_node = node.hpack
+local insert_node_after = node.insert_after
+local insert_node_before = node.insert_before
+
+local whatsit = node.id("whatsit")
+
+local data = nodes.lines.data
+local last = #data
+
+nodes.lines.scratchbox = nodes.lines.scratchbox or 0
+
+-- cross referencing
+
+function nodes.lines.number(n)
+ n = tonumber(n)
+ local cr = cross_references[n] or 0
+ cross_references[n] = nil
+ return cr
+end
+
+local function resolve(n,m) -- we can now check the 'line' flag (todo)
+ while n do
+ local id = n.id
+ if id == whatsit then -- why whatsit
+ local a = has_attribute(n,line_reference)
+ if a then
+ cross_references[a] = m
+ end
+ elseif id == hlist or id == vlist then
+ resolve(n.list,m)
+ end
+ n = n.next
+ end
+end
+
+function nodes.lines.finalize(t)
+ local getnumber = nodes.lines.number
+ for _,p in next, t do
+ for _,r in next, p do
+ if r.metadata.kind == "line" then
+ local e = r.entries
+ local u = r.userdata
+ e.linenumber = getnumber(e.text or 0) -- we can nil e.text
+ e.conversion = u and u.conversion
+ r.userdata = nil -- hack
+ end
+ end
+ end
+end
+
+local filters = jobreferences.filters
+local helpers = structure.helpers
+
+jobreferences.registerfinalizer(nodes.lines.finalize)
+
+filters.line = filters.line or { }
+
+function filters.line.default(data)
+-- helpers.title(data.entries.linenumber or "?",data.metadata)
+ texsprint(ctxcatcodes,format("\\convertnumber{%s}{%s}",data.entries.conversion or "numbers",data.entries.linenumber or "0"))
+end
+
+function filters.line.page(data,prefixspec,pagespec) -- redundant
+ helpers.prefixpage(data,prefixspec,pagespec)
+end
+
+function filters.line.linenumber(data) -- raw
+ texwrite(data.entries.linenumber or "0")
+end
+
+-- boxed variant, todo: use number mechanism
+
+nodes.lines.boxed = { }
+
+-- todo: cache setups, and free id no longer used
+-- use interfaces.cachesetup(t)
+
+function nodes.lines.boxed.register(configuration)
+ last = last + 1
+ data[last] = configuration
+ if trace_numbers then
+ logs.report("lines","registering setup %s",last)
+ end
+ return last
+end
+
+function nodes.lines.boxed.setup(n,configuration)
+ local d = data[n]
+ if d then
+ if trace_numbers then
+ logs.report("lines","updating setup %s",n)
+ end
+ for k,v in next, configuration do
+ d[k] = v
+ end
+ else
+ if trace_numbers then
+ logs.report("lines","registering setup %s (br)",n)
+ end
+ data[n] = configuration
+ end
+ return n
+end
+
+local the_left_margin = nodes.the_left_margin
+
+local function check_number(n,a,skip) -- move inline
+ local d = data[a]
+ if d then
+ local s = d.start or 1
+ current_list[#current_list+1] = { n, s }
+ if not skip and s % d.step == 0 then
+ local tag = d.tag or ""
+ texsprint(ctxcatcodes, format("\\makenumber{%s}{%s}{%s}{%s}{%s}{%s}\\endgraf",tag,s,n.shift,n.width,the_left_margin(n.list),n.dir))
+ if trace_numbers then
+ logs.report("numbers","making number %s for setup %s: %s (%s)",#current_list,a,s,d.continue or "no")
+ end
+ else
+ texsprint(ctxcatcodes, "\\skipnumber\\endgraf")
+ end
+ d.start = s + 1 -- (d.step or 1)
+ end
+end
+
+function nodes.lines.boxed.stage_one(n)
+ current_list = { }
+ local head = texbox[n]
+ if head then
+ local list = head.list
+ local last_a, skip = nil, false
+ for n in traverse_id(hlist,list) do -- attr test here and quit as soon as zero found
+ if n.height == 0 and n.depth == 0 then
+ -- skip funny hlists
+ else
+ local a = has_attribute(n.list,line_number)
+ if a and a > 0 then
+ if last_a ~= a then
+ if data[a].method == variables.next then
+ skip = true
+ end
+ last_a = a
+ end
+ if has_attribute(n,display_math) then
+ if nodes.is_display_math(n) then
+ check_number(n,a,skip)
+ end
+ else
+ -- the following test fails somehow (change in luatex?)
+ -- if node.first_character(n.list) then
+ check_number(n,a,skip)
+ -- end
+ end
+ skip = false
+ end
+ end
+ end
+ end
+end
+
+function nodes.lines.boxed.stage_two(n,m)
+ if #current_list > 0 then
+ m = m or nodes.lines.scratchbox
+ local t, i = { }, 0
+ for l in traverse_id(hlist,texbox[m].list) do
+ t[#t+1] = copy_node(l)
+ end
+ for i=1,#current_list do
+ local li = current_list[i]
+ local n, m, ti = li[1], li[2], t[i]
+ ti.next, n.list = n.list, ti
+ resolve(n,m)
+ end
+ end
+end
diff --git a/tex/context/base/page-lin.mkii b/tex/context/base/page-lin.mkii
new file mode 100644
index 000000000..a04804ce6
--- /dev/null
+++ b/tex/context/base/page-lin.mkii
@@ -0,0 +1,312 @@
+%D \module
+%D [ file=page-lin, % copied from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Line Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Core Macros / Line Numbering}
+
+\unprotect
+
+\newif\ifnumberinglines
+\newif\iftypesettinglines
+
+\newcount\linenumber
+\newcount\linestepper
+
+\chardef\linenumberlocation=0
+
+\newtoks\beforeeverylinenumbering
+\newtoks\aftereverylinenumbering
+
+% het gebruik van \setlocalreference scheelt een hash entry
+
+\def\dodoshowlinenumber % for use elsewhere, to be extended
+ {\doplacelinenumber
+ \global\advance\linenumber \plusone}
+
+\def\completelinenumber
+ {\@@rnleft\convertnumber\@@rnconversion\linenumber\@@rnright}
+
+\def\dosetuplinenumbering[#1]%
+ {\getparameters[\??rn][\c!start=1,\c!step=1,#1]%
+ \global\linenumber\plusone}
+
+\def\setuplinenumbering
+ {\dosingleargument\dosetuplinenumbering}
+
+\def\dostartnummerenLINE
+ {\EveryPar{\placelinenumber}} % why not append to everypar ? better
+
+\def\dostopnummerenLINE
+ {\the\aftereverylinenumbering
+ \egroup}
+
+\def\dostartnummerenVERB
+ {\EveryLine{\placelinenumber}}
+
+\def\dostopnummerenVERB
+ {\the\aftereverylinenumbering
+ \egroup}
+
+\newevery \everylinenumber \relax
+
+\def\dodoplacelinenumber
+ {% beware of em's, the font is already switched !
+ \setbox\scratchbox\hbox
+ {\setbox0\hbox{\@@rncommand{\completelinenumber}}\vsmashbox0%
+ \ifcase\linenumberlocation
+ \iftypesettinglines % hack
+ \expandafter\llap
+ \else
+ \expandafter\rlap
+ \fi{\hbox to \@@rnwidth{\box0\hss}}% was \llap, nog testen !!
+ \or
+ \inleftmargin
+ {\forgetall
+ \doifelse\@@rnwidth\v!margin
+ {\hsize\leftmarginwidth}{\hsize\@@rnwidth}%
+ \alignedline\@@rnalign\v!right{\box0\hskip\@@rndistance}}%
+ \else
+ \inrightmargin
+ {\forgetall
+ \doifelse\@@rnwidth\v!margin
+ {\hsize\rightmarginwidth}{\hsize\@@rnwidth}%
+ \alignedline\@@rnalign\v!left{\hskip\@@rndistance\box0}}%
+ \fi}%
+ \vsmashbox\scratchbox
+ \box\scratchbox
+ \the\everylinenumber}
+
+\def\complexstartlinenumbering[#1]%
+ {\doifnot{#1}\v!continue
+ {\doifnumberelse{#1}
+ {\global\linenumber#1\relax}
+ {\doifelsenothing\@@rnstart
+ {\global\linenumber\plusone}
+ {\global\linenumber\@@rnstart}}}%
+ \chardef\linenumberlocation\zerocount
+ \processaction
+ [\@@rnlocation]
+ [ \v!inmargin=>\chardef\linenumberlocation\plusone,
+ \v!inleft=>\chardef\linenumberlocation\plusone,
+ \v!inright=>\chardef\linenumberlocation\plustwo,
+ \v!margin=>\chardef\linenumberlocation\plusone]%
+ % \v!text=>\chardef\linenumberlocation\zerocount,
+ %\s!unknown=>\chardef\linenumberlocation\zerocount,
+ %\s!default=>\chardef\linenumberlocation\zerocount]%
+ \doifnot\@@rnwidth\v!margin
+ {\freezedimenmacro\@@rnwidth
+ \ifcase\linenumberlocation % text
+ \advance\leftskip\@@rnwidth\relax
+ \fi}%
+ \freezedimenmacro\@@rndistance
+ \chardef\@@rn@@rnmethod
+ \ifprocessingverbatim\zerocount\else\iftypesettinglines\plusone\else\plustwo\fi\fi
+ \processaction
+ [\@@rnmethod]
+ [ \v!type=>\chardef\@@rn@@rnmethod\zerocount,
+ \v!line=>\chardef\@@rn@@rnmethod\plusone,
+ \v!text=>\chardef\@@rn@@rnmethod\plustwo,
+ \v!file=>\chardef\@@rn@@rnmethod\plusthree]%
+ \ifcase\@@rn@@rnmethod % verbatim, line by line
+ \typesettinglinestrue
+ \let\dostartnummeren\dostartnummerenVERB
+ \let\stoplinenumbering\dostopnummerenVERB
+ \def\placelinenumber
+ {\doplacelinenumber
+ \global\advance\linenumber \plusone}%
+ \or % text, line by line
+ \let\dostartnummeren\dostartnummerenLINE
+ \let\stoplinenumbering\dostopnummerenLINE
+ \def\placelinenumber
+ {\doplacelinenumber
+ \global\advance\linenumber \plusone}%
+ \or % text, whole lot
+ \let\dostartnummeren\dostartnummerenPAR
+ \let\stoplinenumbering\dostopnummerenPAR
+ \def\placelinenumber
+ {\global\advance\linenumber \minusone
+ \doplacelinenumber}%
+ \or % verbatim, selective line by line
+ \typesettinglinestrue
+ \let\dostartnummeren\dostartnummerenVERB
+ \let\stoplinenumbering\dostopnummerenVERB
+ \def\placelinenumber
+ {\global\linenumber\verbatimlinenumber
+ \global\advance\linenumber \minusone
+ \doplacelinenumber}%
+ \fi
+ \dostartnummeren}
+
+\def\startlinenumbering
+ {\bgroup
+ \the\beforeeverylinenumbering
+ \numberinglinestrue
+ \complexorsimpleempty\startlinenumbering}
+
+\def\donoplacelinenumber
+ {\the\everylinenumber}
+
+\def\doplacelinenumber
+ {\ifnum\linenumber<\@@rnstart\relax
+ \donoplacelinenumber
+ \else
+ \ifnum\numexpr(\linenumber/\@@rnstep)*\@@rnstep\relax=\linenumber
+ \doattributes\??rn\c!style\c!color\dodoplacelinenumber
+ \else
+ \donoplacelinenumber
+ \fi
+ \fi}
+
+\def\someline[#1]%
+ {\dolinereference0[#1]\ignorespaces}
+
+\def\startline[#1]%
+ {\dolinereference1[#1]\ignorespaces}
+
+\def\stopline[#1]%
+ {\removelastspace\dolinereference2[#1]}
+
+\def\inline#1[#2]%
+ {\doifelsenothing{#1}
+ {\doifinstringelse{--}\currenttextreference
+ {\in{\leftlabeltext\v!lines}{\rightlabeltext\v!lines}[\@@rnprefix#2]}
+ {\in{\leftlabeltext\v!line }{\rightlabeltext\v!line }[\@@rnprefix#2]}}
+ {\in{#1}[\@@rnprefix#2]}}
+
+\def\dostartnummerenPAR
+ {\beginofshapebox
+ \doglobal\newcounter\linereference}
+
+% localcrossref heroverwegen
+
+\def\setlinereference#1#2#3#4%
+ {\setxvalue{lrf:#1}{\noexpand\dogetlinereference{#2}{#3}{#4}}}
+
+\def\getlinereference#1%
+ {\getvalue{lrf:#1}}
+
+\def\dogetlinereference#1#2#3%
+ {\edef\linereferencename{#1}%
+ \edef\linereferenceline{#2}%
+ \edef\linereferenceplus{#3}}
+
+% 1 xxx xxx xxx xxx xxx xxx xxx
+% 2 xxx yyy yyy yyy yyy yyy yyy <= start y
+% 3 yyy yyy yyy yyy yyy yyy yyy
+% 4 yyy yyy yyy yyy yyy xxx xxx <= stop y
+% 5 xxx xxx xxx xxx xxx xxx xxx
+
+\def\dolinereference#1[#2]%
+ {\bgroup
+ \dimen0=\strutdp
+ \doif\@@rnreferencing\v!on
+ {\doglobal\increment\linereference
+ % start 1=>(n=y,l=0,p=1)
+ % stop 2=>(n=y,l=0,p=2)
+ \setlinereference{\linereference}{\@@rnprefix#2}{0}{#1}%
+ \advance\dimen0 \linereference sp}%
+ \prewordbreak
+ \vrule \!!width \zeropoint \!!depth \dimen0 \!!height \zeropoint
+ \prewordbreak
+ \egroup}
+
+\def\dostopnummerenPAR % dp's -> openstrutdepth
+ {\endofshapebox
+ \checkreferences
+ \linestepper\zerocount
+ \reshapebox{\global\advance\linestepper \plusone}%
+ \global\advance\linenumber \linestepper
+ \doifelse\@@rnreferencing\v!on
+ {\reshapebox % We are going back!
+ {\global\advance\linenumber \minusone
+ \dimen0=\dp\shapebox
+ \advance\dimen0 -\strutdp\relax
+ \ifdim\dimen0>\zeropoint
+ % 1=>4 | 2=>4 1=>2
+ % start 1=>(n=y,l=2,p=1)
+ % stop 2=>(n=y,l=4,p=2)
+ \dostepwiserecurse\plusone{\number\dimen0}\plusone
+ {\getlinereference\recurselevel
+ \setlinereference\recurselevel
+ {\linereferencename}{\the\linenumber}{\linereferenceplus}}%
+ \fi}%
+ \global\advance\linenumber \linestepper
+ \ifnum\linereference>\zerocount % anders vreemde loop in paragraphs+recurse
+ \dorecurse\linereference
+ {\getlinereference\recurselevel
+ \ifnum\linereferenceplus=2 % stop
+ % ref y: text = 4 / Kan dit buiten referentie mechanisme om?
+ \expanded{\setlocalcrossreference
+ {\referenceprefix\linereferencename}{}{}{\linereferenceline}}%
+ \fi}%
+ \dorecurse\linereference
+ {\getlinereference\recurselevel
+ \ifnum\linereferenceplus<2 % start / lone
+ \ifnum\linereferenceplus=1 % start
+ \getreferenceelements\linereferencename % text = 4
+ \ifnum\linereferenceline<0\currenttextreference\relax % 0 prevents error
+ \edef\linereferenceline{\linereferenceline--\currenttextreference}%
+ \fi
+ \fi
+ \expanded{\setlocalcrossreference
+ {\referenceprefix\linereferencename}{}{}{\linereferenceline}}%
+ \fi}%
+ \global\let\scratchline\linenumber % We are going back!
+ \reshapebox
+ {\doglobal\decrement\scratchline
+ \hbox
+ {\dorecurse\linereference
+ {\getlinereference\recurselevel
+ \getreferenceelements\linereferencename
+ \beforesplitstring\currenttextreference--\at--\to\firstline
+ \ifnum\firstline=\scratchline\relax
+ % beter een rawtextreference, i.e. expanded
+ % \textreference[\linereferencename]{\currenttextreference}%
+ \rawtextreference\s!lin\linereferencename\currenttextreference
+ \expanded{\setlocalcrossreference
+ {\referenceprefix\linereferencename}{}{}{0}}% ==done
+ \fi}%
+ \dimen0\dp\shapebox
+ \advance\dimen0 -\strutdp\relax
+ \ifdim\dimen0>\zeropoint
+ \dp\shapebox\strutdp
+ \fi
+ \placelinenumber\box\shapebox}}% no \strut !
+ \else
+ \reshapebox{\hbox{\placelinenumber\box\shapebox}}% no \strut !
+ \fi}
+ {\reshapebox{\global\advance\linenumber \minusone}%
+ \global\advance\linenumber \linestepper
+ \reshapebox{\hbox{\placelinenumber\box\shapebox}}}% no \strut !
+ \global\advance\linenumber \linestepper
+ \flushshapebox
+ \the\aftereverylinenumbering
+ \egroup}
+
+\setuplinenumbering
+ [\c!method=,
+ \c!conversion=\v!numbers,
+ \c!start=1,
+ \c!step=1,
+ \c!location=\v!margin,
+ \c!style=,
+ \c!color=,
+ \c!prefix=,
+ \c!referencing=\v!on,
+ \c!width=\ifcase\linenumberlocation2em\else\v!margin\fi,
+ \c!left=,
+ \c!right=,
+ \c!command=,
+ \c!distance=\zeropoint,
+ \c!align=\ifcase\linenumberlocation\v!right\or\v!right\or\v!left\fi]
+
+\protect \endinput
diff --git a/tex/context/base/page-lin.mkiv b/tex/context/base/page-lin.mkiv
new file mode 100644
index 000000000..51f027639
--- /dev/null
+++ b/tex/context/base/page-lin.mkiv
@@ -0,0 +1,498 @@
+%D \module
+%D [ file=page-lin,
+%D version=2007.11.29,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Line Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% generic or not ... maybe not bother too much and simplify to mkiv only
+
+\writestatus{loading}{ConTeXt Core Macros / Line Numbering}
+
+\unprotect
+
+% todo: save settings
+
+% low level interface
+
+\registerctxluafile{page-lin}{1.001}
+
+\definesystemattribute[line-number] \chardef\linenumberattribute \dogetattributeid{line-number}
+\definesystemattribute[line-reference] \chardef\linereferenceattribute \dogetattributeid{line-reference}
+
+\appendtoksonce \attribute\linenumberattribute \attributeunsetvalue \to \everyforgetall
+\appendtoksonce \attribute\displaymathattribute\plusone \to \everybeforedisplayformula
+
+\newcount\linenumber
+\newbox \linenumberscratchbox
+\newcount\linenumberchunk
+\newcount\linerefcounter
+
+\newconditional\tracelinenumbering
+
+\def\mkprocesstextlinenumbers#1%
+ {\setbox\linenumberscratchbox\vbox{\forgetall\offinterlineskip\ctxlua{nodes.lines.boxed.stage_one(\number#1)}}%
+ \ctxlua{nodes.lines.boxed.stage_two(\number#1,\number\linenumberscratchbox)}}% can move to lua code
+
+% id nr shift width leftskip dir
+
+% \def\mkskiplinenumber #1#2#3#4#6#5{}
+% \def\mkleftlinenumber #1#2#3#4#5#6{\hbox{\llap{#2\quad\hskip#3\scaledpoint}}}
+% \def\mkrightlinenumber#1#2#3#4#5#6{\hbox{\rlap{\hskip#4\scaledpoint\hskip#3\scaledpoint\quad#2}}}
+
+\let\makenumber\gobblesixarguments
+
+\newconditional\boxcontentneedsprocessing
+
+\def\mkdoprocesspagecontents #1{\mkaddtextlinenumbers{#1}\plusone \plusone}
+\def\mkdoprocessboxcontents #1{\mkaddtextlinenumbers{#1}\plusone \plusone}
+\def\mkdoprocesscolumncontents#1{\mkaddtextlinenumbers{#1}\currentcolumn\nofcolumns}
+
+\def\mklinenumberparameters
+ {continue = "\linenumberparameter\c!continue",
+ start = \linenumberparameter\c!start,
+ step = \linenumberparameter\c!step,
+ method = "\linenumberparameter\c!method",
+ tag = "\currentlinenumbering"}
+
+\def\mklinenumberupdateparameters
+ {continue = "\linenumberparameter\c!continue"}
+
+\def\mkdefinetextlinenumbering
+ {\setxvalue{ln:c:\currentlinenumbering}{\number\ctxlua{tex.sprint(nodes.lines.boxed.register({\mklinenumberparameters}))}}}
+
+\def\mkupdatetextlinenumbering
+ {\ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{\mklinenumberupdateparameters})}}
+
+\def\mkstarttextlinenumbering#1#2% always when assignment
+ {\globallet\mkprocesspagecontents \mkdoprocesspagecontents
+ \globallet\mkprocesscolumncontents\mkdoprocesscolumncontents
+ \global\settrue\boxcontentneedsprocessing % see core-rul.mkiv
+ \edef\currentlinenumbering{#1}%
+ \ifcase#2\relax
+ \mkupdatetextlinenumbering % continue
+ \or
+ \mkdefinetextlinenumbering % only when assignment
+ \fi
+ \attribute\linenumberattribute\getvalue{ln:c:\currentlinenumbering}\relax}
+
+\def\mksetuptextlinenumbering
+ {\ifcsname ln:c:\currentlinenumbering\endcsname
+ \ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{\mklinenumberparameters})}%
+ \fi}
+
+\def\mkstoptextlinenumbering
+ {\attribute\linenumberattribute\attributeunsetvalue}
+
+% we could make this a bit more efficient by putting the end reference
+% in the same table as the start one but why make things complex ...
+
+\let\dofinishlinereference\dofinishfullreference
+
+\def\mksomelinereference#1#2#3%
+ {\dontleavehmode\begingroup
+ \global\advance\linerefcounter\plusone
+ \attribute\linereferenceattribute\linerefcounter
+ #3%
+ % for the moment we use a simple system i.e. no prefixes etc .. todo: store as number
+ \expanded{\dodosetreference{line}{#2}{conversion=\linenumberparameter\c!conversion}{\the\linerefcounter}}% kind labels userdata text
+ \endgroup}
+
+\def\mkstartlinereference#1{\mksomelinereference{#1}{lr:b:#1}{}\ignorespaces}
+\def\mkstoplinereference #1{\removeunwantedspaces\mksomelinereference{#1}{lr:e:#1}{}}
+
+\def\mklinestartreference#1[#2]{\in{#1}[lr:b:#2]} % not interfaced
+\def\mklinestopreference #1[#2]{\in{#1}[lr:e:#2]} % not interfaced
+
+% high level interface
+
+\newif\ifnumberinglines
+\newif\iftypesettinglines
+
+\let\currentlinenumbering\empty
+
+\chardef\linenumbermode = 1 % 0=continue, 1=restart
+\chardef\linenumberlocation = 1 % 0=middle, 1=left, 2=right, 3=inner, 4=outer, 5=text, 6=begin, 7=end
+\chardef\linenumberalignment = 5 % 0=middle, 1=left, 2=right, 5=auto
+
+\newevery \beforeeverylinenumbering \relax
+\newevery \aftereverylinenumbering \relax
+\newevery \everylinenumber \relax
+
+\newdimen\linenumberwidth
+\newdimen\linenumberdistance
+
+\unexpanded\def\definelinenumbering
+ {\dosingleempty\dodefinelinenumbering}
+
+\def\dodefinelinenumbering[#1]%
+ {\edef\currentlinenumbering{#1}%
+ \mkdefinetextlinenumbering}
+
+\unexpanded\def\setuplinenumbering
+ {\dodoubleempty\dosetuplinenumbering}
+
+\def\dosetuplinenumbering[#1][#2]%
+ {\ifsecondargument
+ \def\currentlinenumbering{#1}%
+ \getparameters[\??rn#1][#2]%
+ \else
+ \let\currentlinenumbering\empty
+ \getparameters[\??rn][#1]%
+ \fi
+ \mksetuptextlinenumbering}
+
+\def\linenumberparameter#1%
+ {\csname\??rn\ifcsname\??rn\currentlinenumbering#1\endcsname\currentlinenumbering\fi#1\endcsname}
+
+\def\linenumberattributes
+ {\doattributes{\??rn\ifcsname\??rn\currentlinenumbering\c!style\endcsname\currentlinenumbering\fi}}
+
+\setuplinenumbering
+ [\c!conversion=\v!numbers,
+ \c!start=1,
+ \c!step=1,
+ \c!method=\v!first,
+ \c!continue=\v!no,
+ \c!location=\v!left,
+ \c!style=,
+ \c!color=,
+ \c!width=2em,
+ \c!left=,
+ \c!right=,
+ \c!command=,
+ \c!distance=\zeropoint,
+ \c!align=\v!auto]
+
+\definelinenumbering
+
+\unexpanded\def\startlinenumbering
+ {\dodoubleempty\dostartlinenumbering}
+
+% no intermediate changes in values, define a class, otherwise each range
+% would need a number
+
+% todo: text
+
+\expandafter\chardef\csname\??rn:l:\v!middle \endcsname \zerocount
+\expandafter\chardef\csname\??rn:l:\v!left \endcsname \plusone
+\expandafter\chardef\csname\??rn:l:\v!margin \endcsname \plusone
+\expandafter\chardef\csname\??rn:l:\v!inmargin\endcsname \plusone
+\expandafter\chardef\csname\??rn:l:\v!inleft \endcsname \plusone
+\expandafter\chardef\csname\??rn:l:\v!right \endcsname \plustwo
+\expandafter\chardef\csname\??rn:l:\v!inright \endcsname \plustwo
+\expandafter\chardef\csname\??rn:l:\v!inner \endcsname \plusthree
+\expandafter\chardef\csname\??rn:l:\v!outer \endcsname \plusfour
+\expandafter\chardef\csname\??rn:l:\v!text \endcsname \plusfive
+\expandafter\chardef\csname\??rn:l:\v!begin \endcsname \plussix
+\expandafter\chardef\csname\??rn:l:\v!end \endcsname \plusseven
+
+\expandafter\chardef\csname\??rn:a:\v!middle \endcsname \zerocount
+\expandafter\chardef\csname\??rn:a:\v!right \endcsname \plusone
+\expandafter\chardef\csname\??rn:a:\v!flushleft \endcsname \plusone
+\expandafter\chardef\csname\??rn:a:\v!left \endcsname \plustwo
+\expandafter\chardef\csname\??rn:a:\v!flushright\endcsname \plustwo
+\expandafter\chardef\csname\??rn:a:\v!auto \endcsname \plusfive
+
+\def\dostartlinenumbering[#1][#2]% todo: c!continue
+ {\begingroup
+ \chardef\linenumbermode\plusone
+ \ifsecondargument
+ \def\currentlinenumbering{#1}%
+ \doifassignmentelse{#2}
+ {\getparameters[\??rn\currentlinenumbering][#2]}
+ {\doifnumberelse{#2}% downward compatible
+ {\setvalue{\??rn#1\c!start}{#2}}%
+ {\doif{#2}\v!continue
+ {\getparameters[\??rn\currentlinenumbering][\c!continue=\v!yes]%
+ \chardef\linenumbermode\zerocount}}}%
+ \else\iffirstargument
+ \doifnumberelse{#1}% downward compatible
+ {\let\currentlinenumbering\empty
+ \setvalue{\??rn\c!start}{#1}}%
+ {\doifelse{#1}\v!continue
+ {\let\currentlinenumbering\empty
+ \getparameters[\??rn\currentlinenumbering][\c!continue=\v!yes]%
+ \chardef\linenumbermode\zerocount}
+ {\def\currentlinenumbering{#1}}}%
+ \fi\fi
+ \doif{\linenumberparameter\c!continue}\v!yes
+ {\chardef\linenumbermode\zerocount}%
+ \numberinglinestrue
+ \the\beforeeverylinenumbering
+ \mkstarttextlinenumbering\currentlinenumbering\linenumbermode}
+
+\unexpanded\def\stoplinenumbering
+ {\mkstoptextlinenumbering
+ \the\aftereverylinenumbering
+ \endgroup}
+
+% number placement
+
+\let\mkskiplinenumber \gobblesixarguments
+
+\def\mkdoinnerlinenumber{\doifoddpageelse\mkdoleftlinenumber\mkdorightlinenumber}
+\def\mkdoouterlinenumber{\doifoddpageelse\mkdorightlinenumber\mkdoleftlinenumber}
+
+\def\mkleftlinenumber
+ {\ifcase\linenumberlocation
+ \expandafter\mkdoleftlinenumber
+ \or
+ \expandafter\mkdoleftlinenumber
+ \or
+ \expandafter\mkdoleftlinenumber
+ \or
+ \expandafter\mkdoinnerlinenumber
+ \or
+ \expandafter\mkdoouterlinenumber
+ \or
+ \expandafter\mkdotextlinenumber
+ \or
+ \expandafter\mkdobeginlinenumber
+ \or
+ \expandafter\mkdoendlinenumber
+ \fi}
+
+\def\mkrightlinenumber
+ {\ifcase\linenumberlocation
+ \expandafter\mkdorightlinenumber
+ \or
+ \expandafter\mkdorightlinenumber
+ \or
+ \expandafter\mkdorightlinenumber
+ \or
+ \expandafter\mkdoouterlinenumber
+ \or
+ \expandafter\mkdoinnerlinenumber
+ \or
+ \expandafter\mkdotextlinenumber
+ \or
+ \expandafter\mkdoendlinenumber
+ \or
+ \expandafter\mkdobeginlinenumber
+ \fi}
+
+\def\mkaddtextlinenumbers#1#2#3% box col max
+ {\bgroup
+ \chardef\linenumberbox #1\relax
+ \chardef\linenumbercolumn #2\relax
+ \chardef\linenumberlastcolumn#3\relax
+ \fullrestoreglobalbodyfont
+ \def\skipnumber{\hbox{}}%
+ \let\makenumber\maketextlinenumber
+ \mkprocesstextlinenumbers\linenumberbox
+ \egroup}
+
+\def\maketextlinenumber#1%
+ {\edef\currentlinenumbering{#1}%
+ \chardef\linenumberlocation \executeifdefined{\??rn:l:\linenumberparameter\c!location}\plusone % left
+ \chardef\linenumberalignment\executeifdefined{\??rn:a:\linenumberparameter\c!align }\plusfive % auto
+ \ifcase\linenumberlastcolumn\relax
+ \let\domakenumber\mkskiplinenumber
+ \or
+ % one column
+ \ifcase\linenumberlocation
+ \let\domakenumber\mkskiplinenumber
+ % hm
+ \or
+ \let\domakenumber\mkleftlinenumber
+ \or
+ \let\domakenumber\mkrightlinenumber
+ \or % inner
+ \let\domakenumber\mkdoinnerlinenumber
+ \or % outer
+ \let\domakenumber\mkdoouterlinenumber
+ \or % text
+ \let\domakenumber\mkdotextlinenumber
+ \or
+ \let\domakenumber\mkdobeginlinenumber
+ \or
+ \let\domakenumber\mkdoendlinenumber
+ \fi
+ \else\ifcase\linenumbercolumn\relax
+ \let\domakenumber\mkskiplinenumber
+ \or
+ \let\domakenumber\mkleftlinenumber
+ \ifcase\linenumberlocation\or
+ \chardef\linenumberlocation\plusone
+ \or
+ \chardef\linenumberlocation\plustwo
+ \else
+ \chardef\linenumberlocation\plusone
+ \or
+ \chardef\linenumberlocation\plusone
+ \or
+ \chardef\linenumberlocation\plusone
+ \or
+ \chardef\linenumberlocation\plusone % todo
+ \or
+ \chardef\linenumberlocation\plusone % todo
+ \fi
+ \else
+ \let\domakenumber\mkrightlinenumber
+ \ifcase\linenumberlocation\or
+ \chardef\linenumberlocation\plustwo
+ \or
+ \chardef\linenumberlocation\plusone
+ \or
+ \chardef\linenumberlocation\plustwo
+ \or
+ \chardef\linenumberlocation\plustwo
+ \or
+ \chardef\linenumberlocation\plustwo % todo
+ \or
+ \chardef\linenumberlocation\plustwo % todo
+ \fi
+ \fi\fi
+ \domakenumber{#1}}
+
+\def\mkdotextlinenumber #1#2#3#4#5#6% beware, one needs so compensate for this in the width !
+ {\hbox{\dosomelinenumber{#1}{2}{#2}{#5}\hskip#3\scaledpoint}}
+
+\def\mkdotextlinenumber #1#2#3#4#5#6% beware, one needs so compensate for this in the width !
+ {\hbox{\dosomelinenumber{#1}{2}{#2}{#5}\hskip#3\scaledpoint}}
+
+\def\mkdoleftlinenumber #1#2#3#4#5#6%
+ {\naturalhbox to \zeropoint
+ {\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi
+ \llap{\dosomelinenumber{#1}{2}{#2}{#5}\kern#3\scaledpoint}}}
+
+\def\mkdorightlinenumber#1#2#3#4#5#6%
+ {\naturalhbox to \zeropoint
+ {\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi
+ \rlap{\hskip#4\scaledpoint\hskip#3\scaledpoint\dosomelinenumber{#1}{1}{#2}{#5}}}}
+
+\def\mkdobeginlinenumber #1#2#3#4#5#6%
+ {\ifcase\istltdir#6\relax
+ \chardef\linenumberlocation\plusone
+ \expandafter\mkdoleftlinenumber
+ \else
+ \chardef\linenumberlocation\plustwo
+ \expandafter\mkdorightlinenumber
+ \fi{#1}{#2}{#3}{#4}{#5}{#6}}
+
+\def\mkdoendlinenumber#1#2#3#4#5#6%
+ {\ifcase\istltdir#6\relax
+ \chardef\linenumberlocation\plustwo
+ \expandafter\mkdorightlinenumber
+ \else
+ \chardef\linenumberlocation\plusone
+ \expandafter\mkdoleftlinenumber
+ \fi{#1}{#2}{#3}{#4}{#5}{#6}}
+
+\def\dosomelinenumber#1#2#3#4% tag 1=left|2=right linenumber leftskip
+ {\begingroup
+ \def\currentlinenumbering{#1}%
+ \def\linenumber{#3}% unsafe
+ \doifelse{\linenumberparameter\c!width}\v!margin
+ {\linenumberwidth\leftmarginwidth}
+ {\linenumberwidth\linenumberparameter\c!width}%
+ \linenumberdistance\linenumberparameter\c!distance\relax
+ \ifcase#2\relax\or\hskip\linenumberdistance\fi\relax
+ \ifnum\linenumberlocation=\plusfive
+ \scratchdimen\dimexpr#4\scaledpoint-\linenumberdistance\relax
+ \chardef\linenumberlocation\plusone
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \ifcase\linenumberalignment
+ \chardef\linenumberlocation\zerocount % middle
+ \or
+ \chardef\linenumberlocation\plusone % left
+ \or
+ \chardef\linenumberlocation\plustwo % right
+ \fi
+ \ifconditional\tracelinenumbering\ruledhbox\else\hbox\fi to \linenumberwidth
+ {\ifcase\linenumberlocation
+ \hss % middle
+ \or
+ % left
+ \or
+ \hss % right
+ \or
+ \doifoddpageelse\relax\hss % inner
+ \or
+ \doifoddpageelse\hss\relax % outer
+ \fi
+ \linenumberattributes\c!style\c!color
+ {\linenumberparameter\c!command
+ {\linenumberparameter\c!left
+ \convertnumber{\linenumberparameter\c!conversion}{#3}%
+ \linenumberparameter\c!right}}%
+ \ifcase\linenumberlocation
+ \hss % middle
+ \or
+ \hss % left
+ \or
+ % right
+ \or
+ \doifoddpageelse\hss\relax % inner
+ \or
+ \doifoddpageelse\relax\hss % outer
+ \fi}%
+ \ifcase#2\relax\or\or\hskip\linenumberdistance\fi\relax
+ \hskip-\scratchdimen
+ \the\everylinenumber
+ \endgroup}
+
+% left right inner outer
+
+% align: \alignedline\@@rnalign\v!right{\box0\hskip\@@rndistance}
+
+% referencing
+
+\def\someline [#1]{\mkstartlinereference{#1}\mkstoplinereference{#1}}
+\unexpanded\def\startline[#1]{\mkstartlinereference{#1}}
+\unexpanded\def\stopline [#1]{\mkstoplinereference {#1}}
+
+\def\mkshowstartlinereference#1%
+ {\ifconditional\tracelinenumbering
+ \setbox\scratchbox\hbox{\llap
+ {\vrule\!!width\onepoint\!!depth\strutdp\!!height.8\strutht\raise.85\strutht\hbox{\llap{\tt\txx#1}}}}%
+ \smashbox\scratchbox\box\scratchbox
+ \fi}
+\def\mkshowstoplinereference#1%
+ {\ifconditional\tracelinenumbering
+ \setbox\scratchbox\hbox{\rlap
+ {\raise.85\strutht\hbox{\rlap{\tt\txx#1}}\vrule\!!width\onepoint\!!depth\strutdp\!!height.8\strutht}}%
+ \smashbox\scratchbox\box\scratchbox
+ \fi}
+
+\def\mkstartlinereference#1{\mksomelinereference{#1}{lr:b:#1}{\mkshowstartlinereference{#1}}\ignorespaces}
+\def\mkstoplinereference #1{\removeunwantedspaces\mksomelinereference{#1}{lr:e:#1}{\mkshowstoplinereference{#1}}}
+
+% eventually we will do this in lua
+
+\def\currentreferencelinenumber{\ctxlua{jobreferences.filter("linenumber")}}
+
+\def\doifelsesamelinereference#1#2#3%
+ {\doifreferencefoundelse{lr:b:#1}
+ {\edef\fline{\currentreferencelinenumber}%
+ \doifreferencefoundelse{lr:e:#1}
+ {\edef\tline{\currentreferencelinenumber}%
+ %[\fline,\tline]
+ \ifx\fline\tline#2\else#3\fi}
+ {\unknownreference{#1}#2}}
+ {\unknownreference{#1}#2}}
+
+\def\inline#1[#2]%
+ {\doifelsenothing{#1}
+ {\doifelsesamelinereference{#2}
+ {\in{\leftlabeltext\v!line}{\rightlabeltext\v!line}[lr:b:#2]}
+ {\in{\leftlabeltext\v!lines}{}[lr:b:#2]--\in{}{\rightlabeltext\v!lines}[lr:e:#2]}}
+ {\doifelsesamelinereference{#2}
+ {\in{#1}[lr:b:#2]}
+ {\in{#1}[lr:b:#2]--\in[lr:e:#2]}}}
+
+\def\inlinerange[#1]%
+ {\doifelsesamelinereference{#1}
+ {\in[lr:b:#1]}
+ {\in[lr:b:#1]--\in[lr:e:#1]}}
+
+\protect \endinput
diff --git a/tex/context/base/page-log.mkii b/tex/context/base/page-log.mkii
new file mode 100644
index 000000000..18c7991b1
--- /dev/null
+++ b/tex/context/base/page-log.mkii
@@ -0,0 +1,202 @@
+%D \module
+%D [ file=page-log, % moved here from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Logos,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Logos}
+
+\unprotect
+
+%D Although logos can conveniently be implemented on top of
+%D background and text areas, we provide a dedicated mechanism
+%D here. One reason is that such a separate mechanism cannot
+%D interfere with the other ones, but an even more important
+%D reason is that logos are kind of special in the sense that
+%D they have a short life span and may change after the first
+%D page.
+
+%D \macros
+%D {recalculatelogos,addlogobackground}
+%D
+%D The interface to the other low level page building routines
+%D is provided by a macro that signals changes in layout
+%D specifications:
+%D
+%D \starttyping
+%D \recalculatelogos
+%D \stoptyping
+%D
+%D as well as a simple placement macro:
+%D
+%D \starttyping
+%D \addlogobackground
+%D \stoptyping
+%D
+%D In no way the following boolean switch should be used
+%D directly.
+
+\newif\ifnewlogos
+
+\def\recalculatelogos
+ {\global\newlogostrue}
+
+%D The current state of logos is registered in a status
+%D variable \type {\logostatus}.
+%D
+%D \starttabulate[|l|l|l|]
+%D \NC 0 \NC don't place \NC remains 0 \NC \NR
+%D \NC 1 \NC place now \NC remains 1 \NC \NR
+%D \NC 2 \NC calulate and place \NC becomes 1 \NC \NR
+%D \NC 3 \NC calculate and place once \NC becomes 2 \NC \NR
+%D \stoptabulate
+
+\chardef\logostatus=0
+
+\def\addlogobackground#1% todo: dimension spec
+ {\ifcase\logostatus \else
+ \ifcase\logostatus
+ % no logos to take care of
+ \or % 1
+ \ifnewlogos
+ \chardef\logostatus2
+ \setlogoboxes
+ \chardef\logostatus1
+ \global\newlogosfalse
+ \fi
+ \or % 2
+ \setlogoboxes
+ \chardef\logostatus1
+ \or % 3
+ \setlogoboxes
+ \global\chardef\logostatus2
+ \fi
+ \setbox#1\vbox
+ {\offinterlineskip
+ \doifmarginswapelse
+ {\copy\leftlogos}
+ {\copy\rightlogos}
+ \box#1}%
+ \fi}
+
+%D For efficiency reasons (and since logos seldom change inside
+%D a document) we can save the left and right hand (or first
+%D and following page) logos in boxes. The areas are slightly
+%D different from the ones used in backgrounds and text
+%D placement, but still related to the page layout. The {\em
+%D left} and {\em right edge}, as well as {\em top} and {\em
+%D bottom} touch the bounding box of the paper and are
+%D therefore not the sams as their background adn text
+%D counterparts. In addition there are {\em left}, {\em right}
+%D and {\em middle} areas as well as a {\em page} one.
+
+\newbox\leftlogos
+\newbox\rightlogos
+
+\def\setlogoboxes
+ {\showmessage\m!layouts7\empty
+ \dosetlogobox\leftlogos\relax
+ \ifdoublesided
+ \dosetlogobox\rightlogos\doswapmargins
+ \fi}
+
+\def\dosetlogobox#1#2%
+ {\global\setbox#1\vbox to \paperheight
+ {\dontcomplain % needed here ?
+ \calculatereducedvsizes % needed here ?
+ \offinterlineskip
+ #2\relax
+ \vskip-\topspace
+ \dodosetlogobox\v!top\blap
+ \vskip\topspace
+ \dodosetlogobox\v!header\blap
+ \vskip\dimexpr\headerheight+\headerdistance\relax
+ \dodosetlogobox\v!text\blap
+ \vskip\dimexpr\textheight+\footerdistance+\footerheight\relax
+ \dodosetlogobox\v!footer \tlap
+ \vfilll
+ \dodosetlogobox\v!bottom\tlap
+ \vskip\topspace}
+ \smashbox#1}
+
+\def\dodosetlogobox#1#2%
+ {\hbox % width equals \makeupwidth
+ {\def\docommand##1%
+ {\donefalse
+ \ifnum\logostatus=3 \ExpandBothAfter
+ \doifinset{\getvalue{\??lo#1##1}}\requestedlogos\donetrue
+ \else
+ \doifvalue{\??lo#1##1\c!state}\v!start\donetrue
+ \fi
+ \ifdone
+ #2{\hbox{\getvalue{\??lo#1##1\c!command}}}%
+ \fi}%
+ \def\dodocommand##1##2##3##4##5##6%
+ {\hsmash
+ {\hskip-\texthoffset
+ \hbox to \paperwidth
+ {\rlap{\docommand##1}\hss\llap{\docommand##6}}%
+ \hskip-\paperwidth
+ \hbox to \paperwidth
+ {\hskip\texthoffset
+ \hskip-\leftmarginwidth
+ \hskip-\leftmargindistance
+ \hbox to \leftmarginwidth{\docommand##2\hss}%
+ \hskip\leftmargindistance
+ \hbox to \makeupwidth{\docommand##3\hss\docommand##4}%
+ \hskip\rightmargindistance
+ \hbox to \rightmarginwidth{\hss\docommand##5}%
+ \hfill}}}%
+ \normalbaselines
+ \settexthoffset
+ \hsmash
+ {\hbox to \makeupwidth{\hss\docommand\c!middle\hss}}%
+ \hsmash
+ {\hskip-\texthoffset
+ \hbox to \paperwidth{\docommand\v!page\hss}}%
+ \swapmargins
+ \doifbothsidesoverruled
+ {\dodocommand
+ \v!leftedge \v!leftmargin \v!left
+ \v!right \v!rightmargin \v!rightedge}
+ {\dodocommand
+ \v!leftedge \v!leftmargin \v!left
+ \v!right \v!rightmargin \v!rightedge}
+ {\dodocommand
+ \v!rightedge \v!rightmargin \v!right
+ \v!left \v!leftmargin \v!leftedge}}}
+
+%D The user interface is relatively simple and provides
+%D macros for assigning logos to logo areas as well as
+%D forcing placement.
+%D
+%D \showsetup{definelogo}
+%D \showsetup{placelogos}
+
+\let\definedlogos \empty
+\let\requestedlogos\empty
+
+\long\def\dodefinelogo[#1][#2][#3][#4]%
+ {\addtocommalist{#1}\definedlogos
+ \long\setvalue{\??lo#2#3}{#1}%
+ \getparameters[\??lo#2#3][#4]%
+ \global\chardef\logostatus2 }
+
+\def\definelogo
+ {\doquadrupleargument\dodefinelogo}
+
+\def\placelogos
+ {\dosingleempty\doplacelogos}
+
+\def\doplacelogos[#1]%
+ {\xdef\requestedlogos{\iffirstargument#1\else\definedlogos\fi}%
+ \global\chardef\logostatus3 }
+
+\protect \endinput
diff --git a/tex/context/base/page-mak.mkii b/tex/context/base/page-mak.mkii
new file mode 100644
index 000000000..040feb1d2
--- /dev/null
+++ b/tex/context/base/page-mak.mkii
@@ -0,0 +1,234 @@
+%D \module
+%D [ file=page-mak, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Simple MakeUp,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / MakeUp}
+
+\unprotect
+
+%D \macros
+%D {definemakeup, setupmakeup, startmakeup}
+%D
+%D A makeup is a separate page, like a title page or colofon.
+%D There is one standard makeup page, but you can define more
+%D if needed.
+%D
+%D \starttyping
+%D \startstandardmakeup
+%D My Fancy Title
+%D \stopstandardmakeup
+%D \stoptyping
+%D
+%D The associated commands are:
+%D
+%D \showsetup{definemakeup}
+%D \showsetup{setupmakeup}
+%D \showsetup{startmakeup}
+
+\def\definemakeup
+ {\dodoubleargument\dodefinemakeup}
+
+\def\dodefinemakeup[#1][#2]%
+ {\getparameters
+ [\??do#1]%
+ [\c!width=\innermakeupwidth, % example in manual / was \makeupwidth
+ \c!height=\textheight, % example in manual
+ \c!voffset=\!!zeropoint, % example in manual
+ \c!hoffset=\!!zeropoint, % example in manual
+ \c!commands=,
+ \c!setups=,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty,
+ \c!before=,
+ \c!top=\vss,
+ \c!bottom=\vss,
+ \c!after=,
+ \c!bottomstate=\v!normal,
+ \c!topstate=\v!normal,
+ \c!textstate=\v!normal,
+ \c!headerstate=\v!stop,
+ \c!footerstate=\v!stop,
+ \c!pagestate=\v!stop, % in manual ! ! !
+ \c!color=,
+ \c!align=,
+ #2]%
+ \setvalue{\e!start#1\e!makeup}{\startmakeup[#1]}%
+ \setvalue{\e!stop #1\e!makeup}{\stopmakeup}}
+
+\def\setupmakeup
+ {\dodoubleargument\dosetupmakeup}
+
+\def\dosetupmakeup[#1]%
+ {\getparameters[\??do#1]}
+
+%D This will save us some 375 bytes in the format file.
+
+\def\makeupparameter#1{\getvalue{\??do\currentmakeup#1}}
+
+%D The \type{\start}||\type{\stop} macros are used for both
+%D the direct and indirect way. The parameterless call will
+%D build a simple box.
+
+\newtoks\everymakeup
+
+\appendtoks \postponemarks \to \everymakeup
+
+\let\currentmakeup\empty
+
+\def\startmakeup
+ {\dodoubleempty\dostartmakeup}
+
+\def\dostartmakeup[#1][#2]%
+ {\bgroup
+ \edef\currentmakeup{#1}%
+ \the\everymakeup
+ \iffirstargument
+ \setupmakeup[\currentmakeup][#2]%
+ \let\stopmakeup\dodostopmakeup
+ \expandafter \dodostartmakeup
+ \else
+ \let\stopmakeup\donostopmakeup
+ \expandafter \donostartmakeup
+ \fi}
+
+%D The simple case:
+
+\def\donostartmakeup % textwidth ?
+ {\page
+ \setupheader[\c!state=\v!empty]%
+ \setupfooter[\c!state=\v!empty]%
+ \setsystemmode\v!makeup
+ \vbox to \textheight\bgroup\hsize\textwidth}
+
+\def\donostopmakeup
+ {\egroup
+ \flushmarks % new, here, else empty pages
+ \page
+ \egroup}
+
+%D The normal one:
+
+\newbox\makeupbox
+
+\def\dodostartmakeup
+ {\doifvaluesomething{\??do\currentmakeup\c!page}
+ {\ExpandFirstAfter\page[\makeupparameter\c!page]}%
+ \pagetype[\currentmakeup]%
+ \setsystemmode\v!makeup
+ \setupmakeuplayout
+ \makeupparameter\c!commands % hm, what is this one doing here ?
+ \startregistercolor[\makeupparameter\c!color]%
+ \forgetall % else indented flush
+ \global\setbox\makeupbox\vbox to \makeupparameter\c!height
+ \bgroup
+% \forgetall
+ \setups[\makeupparameter\c!setups]%
+ \hsize\makeupparameter\c!width
+ \doifsomething{\makeupparameter\c!align}
+ {\setupalign[\makeupparameter\c!align]}%
+ \makeupparameter\c!top}
+
+\def\dodostopmakeup
+ {\endgraf
+ \makeupparameter\c!bottom
+ \egroup
+ \flushmarks % new, here, else empty pages
+ \stopregistercolor
+ \doflushmakeup
+ \egroup
+ \calculatehsizes
+ \calculatevsizes}
+
+%D Selective page processing is handled here. (Why?)
+
+\def\doflushmakeup
+ {\ifprocessingpages
+ \ifpageselected
+ \doshipoutmakeup
+ \fi
+ \else
+ \ifpageselected \else
+ \doshipoutmakeup
+ \fi
+ \fi
+ \ifselectingpages
+ \global\pageselectedfalse
+ \fi}
+
+% \def\pushpagestate{\globalpushmacro\@@pnstate}
+% \def\poppagestate {\globalpopmacro \@@pnstate}
+
+\def\doshipoutmakeup
+ {\pushpagestate % new
+ \makeupparameter\c!before
+ \setbox\makeupbox\vbox{\hbox{\color[\makeupparameter\c!color]{\box\makeupbox}}}%
+ % \ifgridsnapping
+ % new per 22/6/2006
+ \ifdim\ht\makeupbox>\vsize
+ \ht\makeupbox\vsize
+ \fi
+ % \fi
+ \box\makeupbox
+ \setuppagenumber[\c!state=\makeupparameter\c!pagestate]%
+ \setupmakeuplayout
+ \page
+ \makeupparameter\c!after
+ \relax % voor fi
+ \ifdoublesided \ifodd\realpageno\else
+ \processaction
+ [\makeupparameter\c!doublesided]
+ [ \v!yes=>\null
+ \page,
+ \v!empty=>{\setupmakeuplayout
+ \page[\v!blank]%
+ \null
+ \page}]%
+ \fi \fi
+ \poppagestate} % new
+
+%D The text surrounding the main body text can be influenced
+%D by setting their associated status variables. The
+%D connection between them is made by the following macro
+
+\def\setupmakeuplayout
+ {\setupfooter[\c!state=\makeupparameter\c!footerstate]%
+ \setupheader[\c!state=\makeupparameter\c!headerstate]%
+ \setuptext [\c!state=\makeupparameter\c!textstate]%
+ \setupbottom[\c!state=\makeupparameter\c!bottomstate]%
+ \setuptop [\c!state=\makeupparameter\c!topstate]%
+ % this is needed, but no \setuplayout here; fails in texexec --fig=c
+ \recalculatelayout}
+
+%D The standard page template is defined as follows:
+
+\definemakeup
+ [\v!standard]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight,
+ \c!voffset=\!!zeropoint,
+ \c!hoffset=\!!zeropoint,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty]
+
+\definemakeup
+ [\v!text]
+ [\c!topstate=\v!start,
+ \c!headerstate=\v!start,
+ \c!textstate=\v!start,
+ \c!footerstate=\v!start,
+ \c!bottomstate=\v!start,
+ \c!doublesided=\v!no,
+ \c!page=\v!yes,
+ \c!top=\pseudostrut\ignorespaces,
+ \c!bottom=\obeydepth\vss]
+
+\protect \endinput
diff --git a/tex/context/base/page-mak.mkiv b/tex/context/base/page-mak.mkiv
new file mode 100644
index 000000000..fd89a45ff
--- /dev/null
+++ b/tex/context/base/page-mak.mkiv
@@ -0,0 +1,233 @@
+%D \module
+%D [ file=page-mak, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Simple MakeUp,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / MakeUp}
+
+\unprotect
+
+%D \macros
+%D {definemakeup, setupmakeup, startmakeup}
+%D
+%D A makeup is a separate page, like a title page or colofon.
+%D There is one standard makeup page, but you can define more
+%D if needed.
+%D
+%D \starttyping
+%D \startstandardmakeup
+%D My Fancy Title
+%D \stopstandardmakeup
+%D \stoptyping
+%D
+%D The associated commands are:
+%D
+%D \showsetup{definemakeup}
+%D \showsetup{setupmakeup}
+%D \showsetup{startmakeup}
+
+\unexpanded\def\definemakeup
+ {\dodoubleargument\dodefinemakeup}
+
+\def\dodefinemakeup[#1][#2]%
+ {\getparameters
+ [\??do#1]%
+ [\c!width=\innermakeupwidth, % example in manual / was \makeupwidth
+ \c!height=\textheight, % example in manual
+ \c!voffset=\!!zeropoint, % example in manual
+ \c!hoffset=\!!zeropoint, % example in manual
+ \c!commands=,
+ \c!setups=,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty,
+ \c!before=,
+ \c!top=\vss,
+ \c!bottom=\vss,
+ \c!after=,
+ \c!bottomstate=\v!normal,
+ \c!topstate=\v!normal,
+ \c!textstate=\v!normal,
+ \c!headerstate=\v!stop,
+ \c!footerstate=\v!stop,
+ \c!pagestate=\v!stop, % in manual ! ! !
+ \c!color=,
+ \c!align=,
+ #2]%
+ \setvalue{\e!start#1\e!makeup}{\startmakeup[#1]}%
+ \setvalue{\e!stop #1\e!makeup}{\stopmakeup}}
+
+\unexpanded\def\setupmakeup
+ {\dodoubleargument\dosetupmakeup}
+
+\def\dosetupmakeup[#1]%
+ {\getparameters[\??do#1]}
+
+%D This will save us some 375 bytes in the format file.
+
+\def\makeupparameter#1{\getvalue{\??do\currentmakeup#1}}
+
+%D The \type{\start}||\type{\stop} macros are used for both
+%D the direct and indirect way. The parameterless call will
+%D build a simple box.
+
+\newtoks\everymakeup
+
+\appendtoks \postponemarks \to \everymakeup
+
+\let\currentmakeup\empty
+
+\unexpanded\def\startmakeup
+ {\dodoubleempty\dostartmakeup}
+
+\def\dostartmakeup[#1][#2]%
+ {\bgroup
+ \edef\currentmakeup{#1}%
+ \the\everymakeup
+ \iffirstargument
+ \setupmakeup[\currentmakeup][#2]%
+ \let\stopmakeup\dodostopmakeup
+ \expandafter \dodostartmakeup
+ \else
+ \let\stopmakeup\donostopmakeup
+ \expandafter \donostartmakeup
+ \fi}
+
+%D The simple case:
+
+\def\donostartmakeup % textwidth ?
+ {\page
+ \setupheader[\c!state=\v!empty]%
+ \setupfooter[\c!state=\v!empty]%
+ \setsystemmode\v!makeup
+ \vbox to \textheight\bgroup\hsize\textwidth}
+
+\def\donostopmakeup
+ {\egroup
+ \flushmarks % new, here, else empty pages
+ \page
+ \egroup}
+
+%D The normal one:
+
+\newbox\makeupbox
+
+\def\dodostartmakeup
+ {\doifvaluesomething{\??do\currentmakeup\c!page}
+ {\ExpandFirstAfter\page[\makeupparameter\c!page]}%
+ \pagetype[\currentmakeup]%
+ \setsystemmode\v!makeup
+ \setupmakeuplayout
+ \makeupparameter\c!commands % hm, what is this one doing here ?
+ \forgetall % else indented flush
+ \global\setbox\makeupbox\vbox to \makeupparameter\c!height
+ \bgroup
+ \doifsomething{\makeupparameter\c!color}{\startcolor[\makeupparameter\c!color]}% can be made faster
+ \doprocesslocalsetups{\makeupparameter\c!setups}%
+ \hsize\makeupparameter\c!width
+ \doifsomething{\makeupparameter\c!align}
+ {\setupalign[\makeupparameter\c!align]}%
+ \makeupparameter\c!top}
+
+\def\dodostopmakeup
+ {\endgraf
+ \makeupparameter\c!bottom
+ \doifsomething{\makeupparameter\c!color}{\stopcolor}%
+ \egroup
+ \flushmarks % new, here, else empty pages
+ \doflushmakeup
+ \egroup
+ \calculatehsizes
+ \calculatevsizes}
+
+%D Selective page processing is handled here. (Why?)
+
+\def\doflushmakeup
+ {\ifprocessingpages
+ \ifpageselected
+ \doshipoutmakeup
+ \fi
+ \else
+ \ifpageselected \else
+ \doshipoutmakeup
+ \fi
+ \fi
+ \ifselectingpages
+ \global\pageselectedfalse
+ \fi}
+
+% \def\pushpagestate{\globalpushmacro\@@pnstate}
+% \def\poppagestate {\globalpopmacro \@@pnstate}
+
+\def\doshipoutmakeup
+ {\pushpagestate % new
+ \makeupparameter\c!before
+ \setbox\makeupbox\vbox{\hbox{\color[\makeupparameter\c!color]{\box\makeupbox}}}%
+ % \ifgridsnapping
+ % new per 22/6/2006
+ \ifdim\ht\makeupbox>\vsize
+ \ht\makeupbox\vsize
+ \fi
+ % \fi
+ \box\makeupbox
+ \setuppagenumber[\c!state=\makeupparameter\c!pagestate]%
+ \setupmakeuplayout
+ \page
+ \makeupparameter\c!after
+ \relax % voor fi
+ \ifdoublesided \ifodd\realpageno\else
+ \processaction
+ [\makeupparameter\c!doublesided]
+ [ \v!yes=>\null
+ \page,
+ \v!empty=>{\setupmakeuplayout
+ \page[\v!blank]%
+ \null
+ \page}]%
+ \fi \fi
+ \poppagestate} % new
+
+%D The text surrounding the main body text can be influenced
+%D by setting their associated status variables. The
+%D connection between them is made by the following macro
+
+\unexpanded\def\setupmakeuplayout
+ {\setupfooter[\c!state=\makeupparameter\c!footerstate]%
+ \setupheader[\c!state=\makeupparameter\c!headerstate]%
+ \setuptext [\c!state=\makeupparameter\c!textstate]%
+ \setupbottom[\c!state=\makeupparameter\c!bottomstate]%
+ \setuptop [\c!state=\makeupparameter\c!topstate]%
+ % this is needed, but no \setuplayout here; fails in texexec --fig=c
+ \recalculatelayout}
+
+%D The standard page template is defined as follows:
+
+\definemakeup
+ [\v!standard]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight,
+ \c!voffset=\!!zeropoint,
+ \c!hoffset=\!!zeropoint,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty]
+
+\definemakeup
+ [\v!text]
+ [\c!topstate=\v!start,
+ \c!headerstate=\v!start,
+ \c!textstate=\v!start,
+ \c!footerstate=\v!start,
+ \c!bottomstate=\v!start,
+ \c!doublesided=\v!no,
+ \c!page=\v!yes,
+ \c!top=\pseudostrut\ignorespaces,
+ \c!bottom=\obeydepth\vss]
+
+\protect \endinput
diff --git a/tex/context/base/page-mar.mkii b/tex/context/base/page-mar.mkii
new file mode 100644
index 000000000..96223bafe
--- /dev/null
+++ b/tex/context/base/page-mar.mkii
@@ -0,0 +1,867 @@
+%D \module
+%D [ file=page-mar, % moved here from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Marginal Things,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Support for margin words is one of the reasons for writing
+%D \CONTEXT. Over time support for marginal content has been
+%D extended en enhanced. Therefore it's always good to watch
+%D out for unexpected side effects.
+
+\writestatus{loading}{ConTeXt Page Macros / Maginal Things}
+
+\unprotect
+
+%D There are three categories and their historically grown meaning is
+%D as follows:
+%D
+%D marginlines: these are flushed relative to the start of a line and
+%D need to be invoked there.
+%D
+%D marginwords: these can be issued in the text flow and will migrate
+%D sidewards; in spite of the name, it can be a paragraph of text as
+%D well, but normally it's words.
+%D
+%D margintexts: these can be set beforehand and are flushed at the
+%D next paragraph of text (of header)
+%D
+%D While these mechanisms were rather separated, they now are slightly
+%D more integrated. Instead of low level instances we now have a mechanism
+%D for defining additional ones.
+
+%D \macros
+%D {inleftedge,inleftmargin,inrightmargin,inrightedge}
+%D
+%D The fast and clean way of putting things in the margin is
+%D using \type{\rlap} or \type{\llap}. Unfortunately these
+%D macro's don't handle indentation, left and right skips. We
+%D therefore embed them in some macro's that (force and)
+%D remove the indentation and restore it afterwards.
+
+\def\definemarginline
+ {\dodoubleargument\dodefinemarginline}
+
+\def\dodefinemarginline[#1][#2]%
+ {\getparameters
+ [\??im\??im#1]
+ [\c!location=\v!left,
+ \c!distance=\zeropoint,
+ \c!width=\leftmarginwidth,
+ \c!hoffset=\leftmargindistance,
+ \c!command=,
+ #2]%
+ \unexpanded\setvalue{#1}{\dohandlemarginline{#1}}}
+
+\def\marginlineparameter #1{\csname\??im\??im\currentmarginline#1\endcsname}
+\def\marginlineexecuter #1#2{\executeifdefined{\??im\??im\currentmarginline#1}{#2}}
+
+\def\dohandlemarginline#1% #2
+ {\def\currentmarginline{#1}%
+ \csname\s!do\??im\??im\executeifdefined{\??im\??im#1\c!location}\v!left\endcsname{#1}} % {#2}
+
+\def\doleftmarginline#1#2% #1 is redundant (we can remove it when we group dohandlemarginline; maybe ...
+ {\pushindentation
+ \llap
+ {\def\currentmarginline{#1}%
+ \postsignalrightpage
+ \hsize\marginlineparameter\c!width\relax
+ \marginlineexecuter\c!command\firstofoneargument{#2}\relax
+ \hskip\dimexpr
+ +\leftskip
+ +\compensatedinnermakeupmargin
+ +\marginlineparameter\c!hoffset
+ +\marginlineparameter\c!distance
+ \relax}%
+ \popindentation
+ \ignorespaces}
+
+\def\dorightmarginline#1#2% #1 is redundant
+ {\pushindentation
+ \rlap
+ {\def\currentmarginline{#1}%
+ \postsignalrightpage
+ \hskip\dimexpr
+ +\hsize
+ -\rightskip
+ +\compensatedinnermakeupmargin
+ +\marginlineparameter\c!hoffset
+ +\marginlineparameter\c!distance
+ \relax
+ \hsize\marginlineparameter\c!width
+ \marginlineexecuter\c!command\firstofoneargument{#2}}%
+ \popindentation
+ \ignorespaces}
+
+\long\def\installmarginlinehandler#1#2{\setvalue{\s!do\??im\??im#1}{#2}}
+
+\installmarginlinehandler \v!left {\doleftmarginline}
+\installmarginlinehandler \v!right {\dorightmarginline}
+\installmarginlinehandler \v!inner {\presignalrightpage\doifrightpageelse\doleftmarginline \dorightmarginline}
+\installmarginlinehandler \v!outer {\presignalrightpage\doifrightpageelse\dorightmarginline\doleftmarginline }
+
+\definemarginline[inleftmargin] [\c!location=\v!left, \c!width=\leftmarginwidth, \c!distance=\leftmargindistance, \c!hoffset=\zeropoint]
+\definemarginline[inrightmargin][\c!location=\v!right,\c!width=\rightmarginwidth,\c!distance=\rightmargindistance,\c!hoffset=\zeropoint]
+\definemarginline[inleftedge] [\c!location=\v!left, \c!width=\leftedgewidth, \c!distance=\leftedgedistance, \c!hoffset=\leftmargintotal]
+\definemarginline[inrightedge] [\c!location=\v!right,\c!width=\rightedgewidth, \c!distance=\rightedgedistance, \c!hoffset=\rightmargintotal]
+
+\definemarginline[inoutermargin][\c!location=\v!outer,\c!width=\outermarginwidth,\c!distance=\outermargindistance,\c!hoffset=\zeropoint]
+\definemarginline[ininnermargin][\c!location=\v!inner,\c!width=\innermarginwidth,\c!distance=\innermargindistance,\c!hoffset=\zeropoint]
+\definemarginline[inouteredge] [\c!location=\v!outer,\c!width=\outeredgewidth, \c!distance=\outeredgedistance, \c!hoffset=\outermargintotal]
+\definemarginline[ininneredge] [\c!location=\v!inner,\c!width=\inneredgewidth, \c!distance=\inneredgedistance, \c!hoffset=\innermargintotal]
+
+\definemarginline[atleftmargin] [\c!location=\v!left, \c!command=\lrlap,\c!width=\zeropoint,\c!distance=\zeropoint,\c!hoffset=\zeropoint]
+\definemarginline[atrightmargin][\c!location=\v!right,\c!command=\rllap,\c!width=\zeropoint,\c!distance=\zeropoint,\c!hoffset=\zeropoint]
+
+\ifx\lrlap\undefined \def\lrlap#1{\llap{\rlap{#1}}} \fi
+\ifx\rllap\undefined \def\rllap#1{\rlap{\llap{#1}}} \fi
+
+\def\lrlap#1{\llap{\rlap{#1}}}
+\def\rllap#1{\rlap{\hskip\hsize\llap{#1}}}
+
+%D We want to keep things efficient and therefore only handle
+%D situations like:
+%D
+%D \startbuffer
+%D \inleftedge {fine} some text \par
+%D \strut \inleftmargin {fine} some text \par
+%D \noindent \inrightmargin {fine} some text \par
+%D \noindent \strut \inrightedge {fine} some text \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D which looks like:
+%D
+%D \bgroup
+%D \getbuffer
+%D \parindent 30pt
+%D \getbuffer
+%D \egroup
+%D
+%D A torture test:
+%D
+%D \starttyping
+%D \def\TestLine#1#2{\backgroundline[#1]{\strut\white\tttf#2~\recurselevel}}
+%D
+%D \startbuffer
+%D \inleftmargin {\TestLine{red} {lm}} test test test \par
+%D \inrightmargin{\TestLine{green} {rm}} test test test \par
+%D \inleftedge {\TestLine{red} {le}} test test test \par
+%D \inrightedge {\TestLine{green} {re}} test test test \par
+%D \inoutermargin{\TestLine{blue} {om}} test test test \par
+%D \ininnermargin{\TestLine{yellow}{im}} test test test \par
+%D \inouteredge {\TestLine{blue} {oe}} test test test \par
+%D \ininneredge {\TestLine{yellow}{ie}} test test test \par
+%D \atleftmargin {\TestLine{red} {alm}} \hfill test \par
+%D \atrightmargin{\TestLine{green} {arm}} test \hfill \par
+%D \stopbuffer
+%D
+%D \dorecurse{40}\getbuffer \page
+%D \stoptyping
+
+%D New, yet undocumented:
+%D
+%D used for pascal:
+%D
+%D \starttyping
+%D \index {test} test \index {west} west \index {rest} rest
+%D
+%D \startnarrower
+%D \placeregister[index][alternative=b,command=\atleftmargin]
+%D \stopnarrower
+%D \stoptyping
+
+% todo: compensate distance when setuplayout[textwidth=..]
+% todo: generalize margin/edge model, now too much duplication
+
+%D The next bunch of macros looks messy which is due to its
+%D multi-purpose character.
+
+\chardef\margincontentdisplacement \zerocount
+\let \margincontentdistance \!!zeropoint
+\let \margincontenthoffset \!!zeropoint
+\def \margincontentlines {1}
+\def \margincontenttag {0}
+\let \margincontentseparator \empty
+\def \margincontentstrutheight {\strutht}
+
+\newcount\margincontentlevel
+\newdimen\margincontentheight
+
+\def\setupinmargin
+ {\dodoubleempty\dosetupinmargin}
+
+\def\dosetupinmargin[#1][#2]%
+ {\ifsecondargument
+ \processcommalist[#1]{\dodosetupinmargin[#2]}% becomes [#2]{##1}
+ \else
+ \getparameters[\??im][#1]%
+ \fi}
+
+% \def\dodosetupinmargin[#1]#2% [settings]{class}
+% {\checkinmargin[#2]%
+% \getparameters[\??im#2][#1]}
+
+\def\dodosetupinmargin[#1]#2% [settings]{class}
+ {\checkinmargin[#2]%
+ \getparameters[\??im#2][#1]%
+ % will become an \everyinmarginsetup thing
+ \ifcase\executeifdefined{\??im#2\c!sidemethod}{0}\else
+ \enableparpositions
+ \fi}
+
+\def\checkinmargin[#1]%
+ {\ifundefined{\??im#1\c!offset}% this offset is related to framed !
+ \addtocommalist{#1}\inmargintaglist
+ \presetmargintext[#1]%
+ \fi}
+
+\def\presetmargintext[#1]%
+ {\presetlocalframed
+ [\??im#1]%
+ \getparameters
+ [\??im#1]
+ [\c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!line=1,
+ \c!separator=,
+ \c!width=\v!broad,
+ \c!distance=, % empty = signal
+ \c!hoffset=\zeropoint,
+ \c!style=\@@imstyle,
+ \c!color=\@@imcolor,
+ \c!strut=\@@imstrut,
+ \c!location=\@@imlocation,
+ \c!align=\@@imalign,
+ \c!before=\@@imbefore,
+ \c!after=\@@imafter]}
+
+\newdimen\naturalmargincontentheight
+
+\def\makemargintextblock#1#2#3% width l r content
+ {\bgroup
+ \forgetall % added, else problems with 'center' and nested itemize
+ \dontcomplain
+ \hsize\getvalue{\??im#1\c!width}\relax
+ \doifnumberelse\margincontenttag
+ {\ifcase\margincontenttag\relax
+ \edef\margincontenttag{#1}% first one is setups id as well
+ \fi}
+ \donothing
+ \doifnumberelse\margincontenttag
+ {\ifnum\margincontenttag>25 % to be translated
+ \writestatus\m!systems{potential margin stack overflow (\margincontenttag)}%
+ \fi}
+ \donothing
+ % we need to preserve {a,b,c} kind of settings
+ \let\margincontentalign#1%
+ \processallactionsinset
+ [\getvalue{\??im\margincontenttag\c!align}]
+ [ \v!yes=>\let\margincontentalign#1,
+ \v!no=>\let\margincontentalign\v!normal,
+ \v!inner=>\let\margincontentalign#1,
+ \v!outer=>\let\margincontentalign#2,
+ \v!left=>\let\margincontentalign\v!left,
+ \v!middle=>\let\margincontentalign\v!middle,
+ \v!right=>\let\margincontentalign\v!right]%
+ \doifvaluesomething{\??im\margincontenttag\c!align} % watch {} around set
+ {\edef\margincontentalign{{\getvalue{\??im\margincontenttag\c!align},\margincontentalign}}}%
+ %
+ \expanded{\getparameters[\??im\margincontenttag][\c!align=\margincontentalign]}%
+ %
+ \edef\margincontentstrut{\getvalue{\??im\margincontenttag\c!strut}}%
+ \savestrut %
+ \setbox\scratchbox\vbox\localframed
+ [\??im\margincontenttag]
+ [\c!strut=\v!no,\c!offset=\v!overlay] % strut handled internally
+ {\decrement\margincontentlines
+ \dorecurse\margincontentlines{\savedstrut\endgraf\nointerlineskip}% ! savedstrut
+ \@@imbefore
+ \dostartattributes{\??im\margincontenttag}\c!style\c!color\empty
+ \dosetupstrut[\margincontentstrut]% was: \setstrut % yes or no
+ \begstrut#3\endstrut\endgraf
+ \xdef\margincontentstrutheight{\the\strutht}% so that it's known outside the framed
+ \dostopattributes
+ \@@imafter}%
+ \global \naturalmargincontentheight\ht\scratchbox
+ \global\advance\naturalmargincontentheight\dp\scratchbox
+ \doif\@@imstack\v!yes
+ {\def\overlappingmargin{-20\scaledpoint}% test value, maybe .25\strutboxdp, maybe configurable
+ \setbox\scratchbox\vbox{\stackeddown\vbox{\box\scratchbox}}}% new
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp % nieuw
+ \box\scratchbox
+ \egroup}
+
+%D The stacker permits constructs like:
+%D
+%D \starttyping
+%D \setupinmargin[stack=yes]
+%D
+%D \inleft{test 1}test\break
+%D \inleft{test 2}test\break
+%D \inleft{test 1}
+%D \input tufte
+%D \inleft{test 1}
+%D \inleft{test 2}
+%D \inleft{test 3}
+%D \input tufte
+%D \inleft{test 1}
+%D \inleft{test 2\endgraf test 3}
+%D \inleft{test 4}
+%D \input tufte
+%D \inleft{test 1}
+%D \inleft{test 2\endgraf test 3}
+%D \inleft{test 4\endgraf test 5\endgraf test 6}
+%D \inleft{test 7\endgraf test 8\endgraf test 9}
+%D \input tufte
+%D \stoptyping
+
+%D This approach permits us to implement a better mechanism
+%D later. We need the \type {\graphicvadjust} in order to
+%D handle:
+%D
+%D \starttyping
+%D \inleft{test} {\red \dorecurse{40}{test }\par}
+%D {\red \inleft{test} \dorecurse{40}{test }\par}
+%D \stoptyping
+%D
+%D The outer margin color is either black or color set as
+%D main text color.
+
+\newif\ifrightmargin % documenteren
+
+\ifx\dopositionmarginbox\undefined
+ \def\dopositionmarginbox#1{\graphicvadjust{\box#1}}
+\fi
+
+% watch out, margin dimensions are swapped locally (\swapmargins)
+
+% with \margincontentmethod one can control pagebreaks
+%
+% 0 no break
+% 1 each entry is one line
+% 2 only natural height
+% 3 also stack height
+
+\chardef\margincontentmethod \plusthree % beware: 1 = old method
+\chardef\marginpagecheckmethod\plusone
+
+\def\margincontentextralines{1} % old method, play safe
+\def\nofmargincontentlines {0}
+
+\def\doplacemargintext#1#2#3#4%
+ {\dontcomplain
+ \strut
+ \doifsomething{#1}
+ {\def\margincontenttag{#1}}%
+ \doifinsetelse{\margincontenttag}{\v!left,\v!right} % ugly hack
+ {\let \margincontentdistance \empty % signal
+ \let \margincontenthoffset \zeropoint}
+ {\edef\margincontentdistance{\executeifdefined{\??im\margincontenttag\c!distance }\empty }% signal
+ \edef\margincontenthoffset {\executeifdefined{\??im\margincontenttag\c!hoffset }\zeropoint}}%
+ \edef\margincontentlines {\executeifdefined{\??im\margincontenttag\c!line }\plusone }%
+ \edef\margincontentseparator {\executeifdefined{\??im\margincontenttag\c!separator}\donothing}%
+ \setbox\scratchbox\hbox{#4}% % todo: make sure that color stack works
+ \ifcase\margincontentmethod
+ \scratchdimen\zeropoint
+ \or % old method
+ \scratchdimen\ht\scratchbox
+ \advance\scratchdimen\dp\scratchbox
+ \or
+ \scratchdimen\naturalmargincontentheight
+ \or
+ \scratchdimen\naturalmargincontentheight
+ \ifx\laststackvmove\undefined\else\global\advance\scratchdimen\laststackvmove\fi
+ \fi
+ \ifdim\scratchdimen>\margincontentheight
+ \global\margincontentheight\scratchdimen
+ \fi
+ \setbox\scratchbox\hbox
+ {#2{\hskip#3\strut
+ \ifcase\margincontentdisplacement
+ % normal, move strutheight up
+ \scratchdimen\strutdp
+ \advance\scratchdimen \margincontentstrutheight
+ \advance\scratchdimen -\strutht
+ \raise\scratchdimen
+ \or
+ % low, obey vadjust
+ \fi
+ \box\scratchbox}}%
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \gdef\margincontentstrutheight{\the\strutht}%
+ %\graphicvadjust{\box\scratchbox}} % fails in high math lines, let it be
+ %\hbox{\lower\strutdp\box\scratchbox}} % alas, wrong lapping, therefore useless
+ \dopositionmarginbox\scratchbox}
+
+% \def\domarginblockskip#1%
+% {\hskip\margincontenthoffset
+% \hskip\compensatedinnermakeupmargin\relax
+% \doifelsenothing\margincontentdistance
+% {\hskip\getvalue{\??im#1\c!distance}}
+% {\hskip\margincontentdistance}%
+% \relax}
+
+\def\domarginblockskip#1%
+ {\doifelsenothing\margincontentdistance
+ {\hskip\dimexpr
+ +\margincontenthoffset
+ +\compensatedinnermakeupmargin
+ +\csname\??im#1\c!distance\endcsname
+ \relax}
+ {\dimexpr
+ +\margincontenthoffset
+ +\compensatedinnermakeupmargin
+ +\margincontentdistance
+ \relax}%
+ \relax}
+
+\def\doleftmarginblock#1#2%
+ {\doplacemargintext{#1}\llap\zeropoint
+ {\llap{\placemargincontentseparator}%
+ \makemargintextblock\v!left\v!right{#2}%
+ \domarginblockskip\v!left}}
+
+\def\dorightmarginblock#1#2%
+ {\doplacemargintext{#1}\rlap\hsize
+ {\hskip\textwidth\hskip-\hsize % new: hsize correction
+ \domarginblockskip\v!right
+ \makemargintextblock\v!right\v!left{#2}%
+ \rlap{\placemargincontentseparator}}}
+
+\def\placemargincontentseparator
+ {\ifnum\margincontentlevel>\zerocount
+ \ifx\margincontentseparator\empty\else
+ \bgroup
+ \scratchdimen\margincontentlines\lineheight
+ \advance\scratchdimen -\lineheight
+ \lower\scratchdimen\hbox{\margincontentseparator}%
+ \egroup
+ \fi
+ \fi}
+
+\newbox\marginconstructbox
+
+\def\doinmarginswapped#1#2#3#4%
+ {\iffirstsidefloatparagraph\nowhitespace\fi % zo laat mogelijk
+ \setbox\marginconstructbox\hbox\bgroup % prevents page break in the middle of construction
+ \startsignalrightpage
+ \doifswappedrightpageelse
+ {\rightmargintrue #2}
+ {\rightmarginfalse#1}
+ {#3}% setups
+ {#4}% content
+ \stopsignalrightpage
+ \egroup
+ \unhbox\marginconstructbox}
+
+% history made this a bit complicated, the +/- was needed before
+% we had enough mem/hash to do the page correction
+
+\edef\inmargintaglist{+,-,\v!low,\v!left,\v!right,\v!inner,\v!outer}
+
+% the old one:
+%
+% \def\doinmargin[#1][#2][#3][#4][#5]% #6 #7
+% {\doifcommonelse{+,-,\v!laag}{#4}
+% {\dodoinmargin[#1][#2][#3][#4][#5]}
+% {\dodoinmargin[#1][#2][#3][][#4]}}
+%
+% an alternative:
+%
+% \letvalue{\??im\v!laag\c!offset}\empty
+% \letvalue{\??im +\c!offset}\empty
+% \letvalue{\??im -\c!offset}\empty
+%
+% \def\doinmargin[#1][#2][#3][#4][#5]% #6 #7
+% {\doifnumberelse{#4}
+% {\dodoinmargin[#1][#2][#3][#4][#5]}
+% {\doifdefinedelse{\??im#4\c!offset}
+% {\dodoinmargin[#1][#2][#3][#4][#5]}
+% {\dodoinmargin[#1][#2][#3][][#4]}}}
+%
+% the problem is that we need to keep downward compatibility
+% with respect to the first argument thing a reference or a
+% directive; the alternative is to force users to pass a
+% directive along with a reference; anyhow, as long as one
+% does not use references that have the same name as a
+% directive we can use the (slow) alternative
+
+\def\doinmargin[#1][#2][#3][#4][#5]% #6 #7
+ {\expanded{\doifinsetelse{#4}{\inmargintaglist}}
+ {\dodoinmargin[#1][#2][#3][#4][#5]}
+ {\dodoinmargin[#1][#2][#3][][#4]}}
+
+\def\defineinmargin
+ {\doquadrupleempty\dodefineinmargin}
+
+\def\dodefineinmargin[#1][#2][#3][#4]%
+ {\doifassignmentelse{#4}
+ {\setupinmargin[#1][#4]%
+ \setvalue{#1}{\indentation\doquintupleempty\doinmargin[#2][#3][#1]}}
+ {\setvalue{#1}{\indentation\doquintupleempty\doinmargin[#2][#3][#4]}}}
+
+\defineinmargin [inleft] [\v!left] [\v!normal] % takes left settings
+\defineinmargin [inright] [\v!right] [\v!normal] % takes right settings
+\defineinmargin [ininner] [\v!inner] [\v!normal] % takes left/right settings
+\defineinmargin [inouter] [\v!outer] [\v!normal] % takes left/right settings
+\defineinmargin [inmargin] [\@@imlocation] [\v!normal] % takes left/right settings
+\defineinmargin [inother] [\@@imlocation] [\v!reverse] % takes left/right settings
+
+\def\inothermargin{\inother}
+
+%D This permits definitions like:
+%D
+%D \starttyping
+%D \defineinmargin [SomePlace] [inner] [normal] [distance=1cm]
+%D \defineinmargin [SomePlace] [inner] [normal] [SomePlace] \setupinmargin[SomePlace][distance=1cm]
+%D \defineinmargin [MyPlace] [inner] [normal] [SomePlace]
+%D \defineinmargin [YourPlace] [inner] [normal] [SomePlace]
+%D \stoptyping
+%D
+%D A torture test:
+%D
+%D \starttyping
+%D \startbuffer
+%D \inleft {\TestLine{red} {l}} test test test \par
+%D \inright {\TestLine{green} {r}} test test test \par
+%D \inmargin {\TestLine{blue} {m}} test test test \par
+%D \inothermargin{\TestLine{yellow} {x}} test test test \par
+%D \ininner {\TestLine{cyan} {i}} test test test \par
+%D \inouter {\TestLine{magenta}{o}} test test test \par
+%D \stopbuffer
+%D
+%D \dorecurse{80}\getbuffer \page
+%D \stoptyping
+%D
+%D and
+%D
+%D \starttyping
+%D \defineinmargin [InOuterA] [outer] [normal] [distance=0cm]
+%D \defineinmargin [InOuterB] [outer] [normal] [distance=1cm]
+%D \defineinmargin [InOuterC] [outer] [normal] [distance=2cm,line=2]
+%D
+%D \startbuffer
+%D \InOuterA{\TestLine{red} {A}} test test test \par
+%D \InOuterB{\TestLine{green}{B}} test test test \par
+%D \InOuterC{\TestLine{blue} {C}} test test test \par
+%D \stopbuffer
+%D
+%D \dorecurse{80}\getbuffer \page
+%D
+%D \dorecurse{10}{\inleft {one} test \inleft {two} test } \page
+%D
+%D \start
+%D \margintext {one} \margintext {two} \input thuan \par
+%D \setupinmargin[1][line=3,distance=1cm]
+%D \margintext [1]{one}
+%D \margintext [2]{two}
+%D \input thuan \page
+%D \stop
+%D
+%D \setupinmargin[3][location=inner,distance=1cm]
+%D \setupinmargin[4][location=outer,distance=2cm]
+%D
+%D % \setupinmargin[left] [line=2]
+%D % \setupinmargin[right][line=2]
+%D
+%D \dorecurse
+%D {10}
+%D {\margintext {\kern3cm\TestLine{blue}{none}}
+%D \margintext[3] {\TestLine{darkgray}{3}}
+%D \margintext[4] {\TestLine{darkgray}{4}}
+%D \margintext[left] {\TestLine{red} {left}}
+%D \margintext[right]{\TestLine{green} {right}}
+%D \margintext[inner]{\TestLine{cyan} {inner}}
+%D \margintext[outer]{\TestLine{magenta} {outer}}
+%D \input thuan \endgraf}
+%D
+%D \dorecurse{10}{\margintext{test\\test\\test} \input thuan \endgraf}
+%D \stoptyping
+
+% Test case:
+%
+% \setuppagenumbering[alternative=doublesided] \setupwhitespace[medium]
+%
+% \placefigure[right]{}{\externalfigure[dummy][width=2cm]}
+% \input tufte \inothermargin{test} \input tufte
+
+% \def\dodoinmargin[#1][#2][#3][#4][#5]#6%
+% {\bgroup
+% \forgetall % otherwise sidefloat problems, added 2005/07/20, maybe dangerous
+% \postponenotes % group is (somehow) needed
+% \doifinsetelse\v!low{#4}
+% {\chardef\margincontentdisplacement\plusone}
+% {\chardef\margincontentdisplacement\zerocount}%
+% \doif\v!reverse{#2}
+% {\swapmacros\dorightmarginblock\doleftmarginblock}%
+% \processaction
+% [#1]
+% [ \v!left=>\let\next\doleftmarginblock, % no swapping
+% \v!right=>\let\next\dorightmarginblock, % no swapping
+% \v!inner=>\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock },
+% \v!outer=>\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock},
+% \s!unknown=>\ifdoublesided
+% \doifcommonelse{+,-}{#4}
+% {\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock }}
+% {\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock}}%
+% \else
+% \let\next\doleftmarginblock
+% \fi]%
+% \next{#3}{#6}%
+% \rawpagereference\s!mar{#5}% naar binnen ! ! ! !
+% \flushnotes
+% \egroup % don't forget the group
+% \ignorespaces}
+
+% test first
+%
+% setupsystem[random=1235]
+%
+% \setupinmargin[left][sidemethod=3]
+% \dorecurse{10}{test \fakewords{20}{40} test \inleft{test\\test} test \fakewords{20}{40} \par}
+% \page
+% \setupinmargin[left][sidemethod=4]
+% \dorecurse{40}{test \fakewords{50}{80} test \inleft{test\\test} \par}
+% \page
+
+\def\dodoinmargin[#1][#2][#3][#4][#5]#6%
+ {\bgroup
+% \tracingall
+ % old stuff, a bit tricky, but now interfaced
+ \edef\currentmargincontent{#1}%
+ \chardef\marginrepositionmethod\executeifdefined{\??im\currentmargincontent\c!sidemethod }\plusone
+ \chardef\margincontentmethod \executeifdefined{\??im\currentmargincontent\c!textmethod }\plusthree
+ \chardef\marginpagecheckmethod \executeifdefined{\??im\currentmargincontent\c!splitmethod}\plusone
+ % so far
+ \forgetall % otherwise sidefloat problems, added 2005/07/20, maybe dangerous
+ \postponenotes % group is (somehow) needed
+ \doifinsetelse\v!low{#4}
+ {\chardef\margincontentdisplacement\plusone}
+ {\chardef\margincontentdisplacement\zerocount}%
+ \doif\v!reverse{#2}
+ {\swapmacros\dorightmarginblock\doleftmarginblock}%
+ \processaction
+ [#1]
+ [ \v!left=>\let\next\doleftmarginblock, % no swapping
+ \v!right=>\let\next\dorightmarginblock, % no swapping
+ \v!inner=>\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock },
+ \v!outer=>\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock},
+ \s!unknown=>\ifdoublesided
+ \doifcommonelse{+,-}{#4}
+ {\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock }}
+ {\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock}}%
+ \else
+ \let\next\doleftmarginblock
+ \fi]%
+ \next{#3}{#6}%
+ \rawpagereference\s!mar{#5}% naar binnen ! ! ! !
+ \flushnotes
+ \egroup % don't forget the group
+ \ignorespaces}
+
+% dit zijn voorlopig lokale commando's / vervallen
+%
+% \def\woordinmarge {\indentation\doquintupleempty\doinmargin[\@@implaats][\inleftmargin][\inrightmarge]}
+%
+% \def\woordinlinker {\inleftmargin } % vervallen
+% \def\woordinrechter{\inrechtermarge} % vervallen
+
+% Some day: \definemarking[\v!margetitel]
+
+%D Now come the margin text collectors. The collected content is
+%D flushed at every paragraph by the following macro. Note for
+%D myself: here the location (plaats) is no longer a tag (number).
+
+% gone: \def\doflushmargincontent{\doinmargin[\@@implaats][\v!normaal][]} % + [#1][#2]{#3}}
+
+%D These are now all the same (long ago they had different
+%D implementations, somewhere in Sork time if I remember
+%D right).
+
+\def\margintext {\dodoubleempty\domargincontent}
+\def\marginword {\margintext}
+\def\margintitle{\margintext} % txt mark as well
+
+\newtoks\collectedmargintexts % so .. delayed!
+\chardef\margintextcollected \zerocount
+
+\def\domargincontent[#1][#2]#3% we used to check for #2/#1 being number, no longer now
+ {\global\chardef\margintextcollected\plusone
+ \edef\margincontenttag{#1}%
+ \ifx\margincontenttag\empty
+ \global\advance\margincontentlevel\plusone
+ \edef\margincontenttag{\number\margincontentlevel}%
+ \fi
+ \checkinmargin[\margincontenttag]%
+ \doglobal \appendetoks
+ \noexpand \checkinmargin[\margincontenttag]%
+ \noexpand \doinmargin[\executeifdefined{\??im\margincontenttag\c!location}\@@imlocation][\v!normal][\margincontenttag][\margincontenttag][#2]%
+ \to \collectedmargintexts
+ \doglobal \appendtoks
+ {#3}%
+ \to \collectedmargintexts}
+
+\let\restoreinterlinepenalty\relax
+
+\def\flushmargincontents % plural
+ {\restoreinterlinepenalty % here?
+ \ifcase\margintextcollected\else % called quite often, so we
+ \expandafter\doflushmargincontents % speed up the \fi scan by
+ \fi} % using a \do..
+
+\def\doflushmargincontents % links + rechts
+ {\bgroup
+ \forgetall
+ \global\margincontentheight\zeropoint
+ \startsignalrightpage
+ \the\collectedmargintexts
+ \signalrightpage
+ \stopsignalrightpage
+ \resetmargincontent
+ % dirty tricks
+ \ifcase\margincontentmethod
+ \donefalse
+ \else\ifinsidecolumns % brrrr
+ \donetrue % how fuzzy
+ \else\ifdim\margincontentheight>\lineheight\relax
+ \donetrue % how dirty
+ \else
+ \donefalse % how needed
+ \fi\fi\fi
+ \savemargincontentlines
+ \ifdone
+ \advance\margincontentheight \margincontentextralines\lineheight
+ \ifdim\pagegoal>\pagetotal
+ \bgroup % preserve \margincontentheight
+ \advance\margincontentheight \pagetotal
+ \ifdim\margincontentheight>\pagegoal
+ \egroup
+ \ifcase\marginpagecheckmethod
+ % disabled
+ \or
+ \setmargincontentpenalties
+ \or
+ % potentially dangerous, maybe better a \goodbreak; the problem is that
+ % there can be a penalty there, which we then overload and we also introduce
+ % nasty side effects, so, we drop this option
+ % \vadjust pre {\page}%
+ \fi
+ \else
+ \egroup
+ \fi
+ \fi
+ \else % We need the above because interlinepenalties overrule vadjusted \nobreaks.
+ % a bit dangerous
+ \vadjust{\nobreak}%
+ \fi
+ \egroup}
+
+\def\setmargincontentpenalties
+ {\getnoflines\margincontentheight
+ \keeplinestogether\noflines}
+
+\def\savemargincontentlines
+ {\bgroup
+ \advance\margincontentheight \margincontentextralines\lineheight % 1 by default
+ \getnoflines\margincontentheight
+ \xdef\nofmargincontentlines{\the\noflines}%
+ \egroup}
+
+\def\fillupmargincontentlines % etex ! ! !
+ {\endgraf
+ \begingroup
+ \scratchcounter\numexpr\nofmargincontentlines-\prevgraf\relax\relax
+ \ifnum\scratchcounter>\zerocount
+ \forgetall\dorecurse\scratchcounter{\nobreak\crlf}%
+ \fi
+ \endgroup}
+
+% Yet undocumented, for a manual flush in for instance headers.
+
+\def\resetmargincontent
+ {\global\margincontentlevel\zerocount
+ \global\chardef\margintextcollected\zerocount
+ \global\collectedmargintexts\emptytoks}
+
+% \def\placemargincontent
+% {\ifcase\margintextcollected\else
+% \bgroup
+% \chardef\graphicvadjustmode\zerocount
+% \doflushmargincontents
+% \egroup
+% \fi}
+%
+% font fix:
+
+\def\placemargincontent
+ {\ifcase\margintextcollected\else % was level check
+ \bgroup
+ \redoconvertfont % !!
+ \chardef\graphicvadjustmode\zerocount
+ \doflushmargincontents
+ \egroup
+ \fi}
+
+% For old times sake (i use it in project styles) we provide
+
+\def\placemargintexts {\placemargincontent}
+\def\resetmargetitels {\resetmargincontent}
+\def\margewoordpositie{\margewoord} % obsolete, now no longer range
+
+% but never use them yourself since they may disappear.
+
+\def\oplinker#1%
+ {\strut
+ \graphicvadjust
+ {\dontcomplain
+ \setbox\scratchbox\vtop{\forgetall\strut#1}%
+ \getboxheight\scratchdimen\of\box\scratchbox
+ \vskip-\scratchdimen % waarom stond hier een \ ?
+ \box\scratchbox}}
+
+\setupinmargin
+ [\c!style=\v!bold,
+ \c!color=,
+ \c!strut=\v!auto,
+ \c!location=\v!both,
+ \c!align=\v!inner,
+ \c!stack=\v!no,
+ \c!before=,
+ \c!after=]
+
+\setupinmargin
+ [\v!left]
+ [\c!distance=\leftmargindistance,
+ \c!width=\leftmarginwidth,
+ %\c!align=\v!left, % no
+ \c!location=\v!left]
+
+\setupinmargin
+ [\v!right]
+ [\c!distance=\rightmargindistance,
+ \c!width=\rightmarginwidth,
+ %\c!align=\v!right, % no
+ \c!location=\v!right]
+
+% bonus needed when [inner/outer] is used as tag
+
+\setupinmargin[\v!inner][\c!location=\v!inner,\c!align=\v!inner]
+\setupinmargin[\v!outer][\c!location=\v!outer,\c!align=\v!inner]
+
+% more efficient (5K less fotmat file)
+%
+% \letvalue{\??im\v!inner\c!location}\v!inner \letvalue{\??im\v!inner\c!align}\v!inner
+% \letvalue{\??im\v!outer\c!location}\v!outer \letvalue{\??im\v!outer\c!align}\v!inner
+
+\protect \endinput
diff --git a/tex/context/base/page-mar.mkiv b/tex/context/base/page-mar.mkiv
new file mode 100644
index 000000000..464b4f9bb
--- /dev/null
+++ b/tex/context/base/page-mar.mkiv
@@ -0,0 +1,824 @@
+%D \module
+%D [ file=page-mar, % moved here from main-001
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Marginal Things,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Support for margin words is one of the reasons for writing
+%D \CONTEXT. Over time support for marginal content has been
+%D extended en enhanced. Therefore it's always good to watch
+%D out for unexpected side effects.
+
+\writestatus{loading}{ConTeXt Page Macros / Maginal Things}
+
+\unprotect
+
+%D There are three categories and their historically grown meaning is
+%D as follows:
+%D
+%D marginlines: these are flushed relative to the start of a line and
+%D need to be invoked there.
+%D
+%D marginwords: these can be issued in the text flow and will migrate
+%D sidewards; in spite of the name, it can be a paragraph of text as
+%D well, but normally it's words.
+%D
+%D margintexts: these can be set beforehand and are flushed at the
+%D next paragraph of text (of header)
+%D
+%D While these mechanisms were rather separated, they now are slightly
+%D more integrated. Instead of low level instances we now have a mechanism
+%D for defining additional ones.
+
+%D \macros
+%D {inleftedge,inleftmargin,inrightmargin,inrightedge}
+%D
+%D The fast and clean way of putting things in the margin is
+%D using \type{\rlap} or \type{\llap}. Unfortunately these
+%D macro's don't handle indentation, left and right skips. We
+%D therefore embed them in some macro's that (force and)
+%D remove the indentation and restore it afterwards.
+
+\unexpanded\def\definemarginline
+ {\dodoubleargument\dodefinemarginline}
+
+\def\dodefinemarginline[#1][#2]%
+ {\getparameters
+ [\??im\??im#1]
+ [\c!location=\v!left,
+ \c!distance=\zeropoint,
+ \c!width=\leftmarginwidth,
+ \c!hoffset=\leftmargindistance,
+ \c!command=,
+ #2]%
+ \setuvalue{#1}{\dohandlemarginline{#1}}}
+
+\def\marginlineparameter #1{\csname\??im\??im\currentmarginline#1\endcsname}
+\def\marginlineexecuter #1#2{\executeifdefined{\??im\??im\currentmarginline#1}{#2}}
+
+\def\dohandlemarginline#1% #2
+ {\def\currentmarginline{#1}%
+ \csname\s!do\??im\??im\executeifdefined{\??im\??im#1\c!location}\v!left\endcsname{#1}} % {#2}
+
+\def\doleftmarginline#1#2% #1 is redundant (we can remove it when we group dohandlemarginline; maybe ...
+ {\pushindentation
+ \llap
+ {\def\currentmarginline{#1}%
+ \postsignalrightpage
+ \hsize\marginlineparameter\c!width\relax
+ \marginlineexecuter\c!command\firstofoneargument{#2}\relax
+ \hskip\dimexpr
+ +\leftskip
+ +\compensatedinnermakeupmargin
+ +\marginlineparameter\c!hoffset
+ +\marginlineparameter\c!distance
+ \relax}%
+ \popindentation
+ \ignorespaces}
+
+\def\dorightmarginline#1#2% #1 is redundant
+ {\pushindentation
+ \rlap
+ {\def\currentmarginline{#1}%
+ \postsignalrightpage
+ \hskip\dimexpr
+ +\hsize
+ -\rightskip
+ +\compensatedinnermakeupmargin
+ +\marginlineparameter\c!hoffset
+ +\marginlineparameter\c!distance
+ \relax
+ \hsize\marginlineparameter\c!width
+ \marginlineexecuter\c!command\firstofoneargument{#2}}%
+ \popindentation
+ \ignorespaces}
+
+\long\def\installmarginlinehandler#1#2{\setvalue{\s!do\??im\??im#1}{#2}}
+
+\installmarginlinehandler \v!left {\doleftmarginline}
+\installmarginlinehandler \v!right {\dorightmarginline}
+\installmarginlinehandler \v!inner {\presignalrightpage\doifrightpageelse\doleftmarginline \dorightmarginline}
+\installmarginlinehandler \v!outer {\presignalrightpage\doifrightpageelse\dorightmarginline\doleftmarginline }
+
+\definemarginline[inleftmargin] [\c!location=\v!left, \c!width=\leftmarginwidth, \c!distance=\leftmargindistance, \c!hoffset=\zeropoint]
+\definemarginline[inrightmargin][\c!location=\v!right,\c!width=\rightmarginwidth,\c!distance=\rightmargindistance,\c!hoffset=\zeropoint]
+\definemarginline[inleftedge] [\c!location=\v!left, \c!width=\leftedgewidth, \c!distance=\leftedgedistance, \c!hoffset=\leftmargintotal]
+\definemarginline[inrightedge] [\c!location=\v!right,\c!width=\rightedgewidth, \c!distance=\rightedgedistance, \c!hoffset=\rightmargintotal]
+
+\definemarginline[inoutermargin][\c!location=\v!outer,\c!width=\outermarginwidth,\c!distance=\outermargindistance,\c!hoffset=\zeropoint]
+\definemarginline[ininnermargin][\c!location=\v!inner,\c!width=\innermarginwidth,\c!distance=\innermargindistance,\c!hoffset=\zeropoint]
+\definemarginline[inouteredge] [\c!location=\v!outer,\c!width=\outeredgewidth, \c!distance=\outeredgedistance, \c!hoffset=\outermargintotal]
+\definemarginline[ininneredge] [\c!location=\v!inner,\c!width=\inneredgewidth, \c!distance=\inneredgedistance, \c!hoffset=\innermargintotal]
+
+\definemarginline[atleftmargin] [\c!location=\v!left, \c!command=\lrlap,\c!width=\zeropoint,\c!distance=\zeropoint,\c!hoffset=\zeropoint]
+\definemarginline[atrightmargin][\c!location=\v!right,\c!command=\rllap,\c!width=\zeropoint,\c!distance=\zeropoint,\c!hoffset=\zeropoint]
+
+\def\lrlap#1{\llap{\rlap{#1}}}
+\def\rllap#1{\rlap{\hskip\hsize\llap{#1}}}
+
+%D We want to keep things efficient and therefore only handle
+%D situations like:
+%D
+%D \startbuffer
+%D \inleftedge {fine} some text \par
+%D \strut \inleftmargin {fine} some text \par
+%D \noindent \inrightmargin {fine} some text \par
+%D \noindent \strut \inrightedge {fine} some text \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D which looks like:
+%D
+%D \bgroup
+%D \getbuffer
+%D \parindent 30pt
+%D \getbuffer
+%D \egroup
+%D
+%D A torture test:
+%D
+%D \starttyping
+%D \def\TestLine#1#2{\backgroundline[#1]{\strut\white\tttf#2~\recurselevel}}
+%D
+%D \startbuffer
+%D \inleftmargin {\TestLine{red} {lm}} test test test \par
+%D \inrightmargin{\TestLine{green} {rm}} test test test \par
+%D \inleftedge {\TestLine{red} {le}} test test test \par
+%D \inrightedge {\TestLine{green} {re}} test test test \par
+%D \inoutermargin{\TestLine{blue} {om}} test test test \par
+%D \ininnermargin{\TestLine{yellow}{im}} test test test \par
+%D \inouteredge {\TestLine{blue} {oe}} test test test \par
+%D \ininneredge {\TestLine{yellow}{ie}} test test test \par
+%D \atleftmargin {\TestLine{red} {alm}} \hfill test \par
+%D \atrightmargin{\TestLine{green} {arm}} test \hfill \par
+%D \stopbuffer
+%D
+%D \dorecurse{40}\getbuffer \page
+%D \stoptyping
+
+%D New, yet undocumented:
+%D
+%D used for pascal:
+%D
+%D \starttyping
+%D \index {test} test \index {west} west \index {rest} rest
+%D
+%D \startnarrower
+%D \placeregister[index][alternative=b,command=\atleftmargin]
+%D \stopnarrower
+%D \stoptyping
+
+% todo: compensate distance when setuplayout[textwidth=..]
+% todo: generalize margin/edge model, now too much duplication
+
+%D The next bunch of macros looks messy which is due to its
+%D multi-purpose character.
+
+\chardef\margincontentdisplacement \zerocount
+\let \margincontentdistance \!!zeropoint
+\let \margincontenthoffset \!!zeropoint
+\def \margincontentlines {1}
+\def \margincontenttag {0}
+\let \margincontentseparator \empty
+\def \margincontentstrutheight {\strutht}
+
+\newcount\margincontentlevel
+\newdimen\margincontentheight
+
+\unexpanded\def\setupinmargin
+ {\dodoubleempty\dosetupinmargin}
+
+\def\dosetupinmargin[#1][#2]%
+ {\ifsecondargument
+ \processcommalist[#1]{\dodosetupinmargin[#2]}% becomes [#2]{##1}
+ \else
+ \getparameters[\??im][#1]%
+ \fi}
+
+% \def\dodosetupinmargin[#1]#2% [settings]{class}
+% {\checkinmargin[#2]%
+% \getparameters[\??im#2][#1]}
+
+\def\dodosetupinmargin[#1]#2% [settings]{class}
+ {\checkinmargin[#2]%
+ \getparameters[\??im#2][#1]%
+ % will become an \everyinmarginsetup thing
+ \ifcase\executeifdefined{\??im#2\c!sidemethod}{0}\else
+ \enableparpositions
+ \fi}
+
+\def\checkinmargin[#1]%
+ {\ifcsname\??im#1\c!offset\endcsname\else % this offset is related to framed !
+ \addtocommalist{#1}\inmargintaglist
+ \presetmargintext[#1]%
+ \fi}
+
+\def\presetmargintext[#1]%
+ {\presetlocalframed
+ [\??im#1]%
+ \getparameters
+ [\??im#1]
+ [\c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!line=1,
+ \c!separator=,
+ \c!width=\v!broad,
+ \c!distance=, % empty = signal
+ \c!hoffset=\zeropoint,
+ \c!style=\@@imstyle,
+ \c!color=\@@imcolor,
+ \c!strut=\@@imstrut,
+ \c!location=\@@imlocation,
+ \c!align=\@@imalign,
+ \c!before=\@@imbefore,
+ \c!after=\@@imafter]}
+
+\newdimen\naturalmargincontentheight
+
+\def\makemargintextblock#1#2#3% width l r content
+ {\bgroup
+ \forgetall % added, else problems with 'center' and nested itemize
+ \dontcomplain
+ \hsize\getvalue{\??im#1\c!width}\relax
+ \doifnumberelse\margincontenttag
+ {\ifcase\margincontenttag\relax
+ \edef\margincontenttag{#1}% first one is setups id as well
+ \fi}
+ \donothing
+ \doifnumberelse\margincontenttag
+ {\ifnum\margincontenttag>25 % to be translated
+ \writestatus\m!systems{potential margin stack overflow (\margincontenttag)}%
+ \fi}
+ \donothing
+ % we need to preserve {a,b,c} kind of settings
+ \let\margincontentalign#1%
+ \processallactionsinset
+ [\getvalue{\??im\margincontenttag\c!align}]
+ [ \v!yes=>\let\margincontentalign#1,
+ \v!no=>\let\margincontentalign\v!normal,
+ \v!inner=>\let\margincontentalign#1,
+ \v!outer=>\let\margincontentalign#2,
+ \v!left=>\let\margincontentalign\v!left,
+ \v!middle=>\let\margincontentalign\v!middle,
+ \v!right=>\let\margincontentalign\v!right]%
+ \doifvaluesomething{\??im\margincontenttag\c!align} % watch {} around set
+ {\edef\margincontentalign{{\getvalue{\??im\margincontenttag\c!align},\margincontentalign}}}%
+ %
+ \expanded{\getparameters[\??im\margincontenttag][\c!align=\margincontentalign]}%
+ %
+ \edef\margincontentstrut{\getvalue{\??im\margincontenttag\c!strut}}%
+ \savestrut %
+ \setbox\scratchbox\vbox\localframed
+ [\??im\margincontenttag]
+ [\c!strut=\v!no,\c!offset=\v!overlay] % strut handled internally
+ {\decrement\margincontentlines
+ \dorecurse\margincontentlines{\savedstrut\endgraf\nointerlineskip}% ! savedstrut
+ \@@imbefore
+ \dostartattributes{\??im\margincontenttag}\c!style\c!color\empty
+ \dosetupstrut[\margincontentstrut]% was: \setstrut % yes or no
+ \begstrut#3\endstrut\endgraf
+ \xdef\margincontentstrutheight{\the\strutht}% so that it's known outside the framed
+ \dostopattributes
+ \@@imafter}%
+ \global \naturalmargincontentheight\ht\scratchbox
+ \global\advance\naturalmargincontentheight\dp\scratchbox
+ \doif\@@imstack\v!yes
+ {\def\overlappingmargin{-20\scaledpoint}% test value, maybe .25\strutboxdp, maybe configurable
+ \setbox\scratchbox\vbox{\stackeddown\vbox{\box\scratchbox}}}% new
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp % nieuw
+ \box\scratchbox
+ \egroup}
+
+%D The stacker permits constructs like:
+%D
+%D \starttyping
+%D \setupinmargin[stack=yes]
+%D
+%D \inleft{test 1}test\break
+%D \inleft{test 2}test\break
+%D \inleft{test 1}
+%D \input tufte
+%D \inleft{test 1}
+%D \inleft{test 2}
+%D \inleft{test 3}
+%D \input tufte
+%D \inleft{test 1}
+%D \inleft{test 2\endgraf test 3}
+%D \inleft{test 4}
+%D \input tufte
+%D \inleft{test 1}
+%D \inleft{test 2\endgraf test 3}
+%D \inleft{test 4\endgraf test 5\endgraf test 6}
+%D \inleft{test 7\endgraf test 8\endgraf test 9}
+%D \input tufte
+%D \stoptyping
+
+%D This approach permits us to implement a better mechanism
+%D later. We need the \type {\graphicvadjust} in order to
+%D handle:
+%D
+%D \starttyping
+%D \inleft{test} {\red \dorecurse{40}{test }\par}
+%D {\red \inleft{test} \dorecurse{40}{test }\par}
+%D \stoptyping
+%D
+%D The outer margin color is either black or color set as
+%D main text color.
+
+\newif\ifrightmargin % documenteren
+
+\ifx\dopositionmarginbox\undefined
+ \def\dopositionmarginbox#1{\graphicvadjust{\box#1}}
+\fi
+
+% watch out, margin dimensions are swapped locally (\swapmargins)
+
+% with \margincontentmethod one can control pagebreaks
+%
+% 0 no break
+% 1 each entry is one line
+% 2 only natural height
+% 3 also stack height
+
+\chardef\margincontentmethod \plusthree % beware: 1 = old method
+\chardef\marginpagecheckmethod\plusone
+
+\def\margincontentextralines{1} % old method, play safe
+\def\nofmargincontentlines {0}
+
+\def\doplacemargintext#1#2#3#4%
+ {\dontcomplain
+ \strut
+ \doifsomething{#1}
+ {\def\margincontenttag{#1}}%
+ \doifinsetelse{\margincontenttag}{\v!left,\v!right} % ugly hack
+ {\let \margincontentdistance \empty % signal
+ \let \margincontenthoffset \zeropoint}
+ {\edef\margincontentdistance{\executeifdefined{\??im\margincontenttag\c!distance }\empty }% signal
+ \edef\margincontenthoffset {\executeifdefined{\??im\margincontenttag\c!hoffset }\zeropoint}}%
+ \edef\margincontentlines {\executeifdefined{\??im\margincontenttag\c!line }\plusone }%
+ \edef\margincontentseparator {\executeifdefined{\??im\margincontenttag\c!separator}\donothing}%
+ \setbox\scratchbox\hbox{#4}% % todo: make sure that color stack works
+ \ifcase\margincontentmethod
+ \scratchdimen\zeropoint
+ \or % old method
+ \scratchdimen\ht\scratchbox
+ \advance\scratchdimen\dp\scratchbox
+ \or
+ \scratchdimen\naturalmargincontentheight
+ \or
+ \scratchdimen\naturalmargincontentheight
+ \ifx\laststackvmove\undefined\else\global\advance\scratchdimen\laststackvmove\fi
+ \fi
+ \ifdim\scratchdimen>\margincontentheight
+ \global\margincontentheight\scratchdimen
+ \fi
+ \setbox\scratchbox\hbox
+ {#2{\hskip#3\strut
+ \ifcase\margincontentdisplacement
+ % normal, move strutheight up
+ \scratchdimen\strutdp
+ \advance\scratchdimen \margincontentstrutheight
+ \advance\scratchdimen -\strutht
+ \raise\scratchdimen
+ \or
+ % low, obey vadjust
+ \fi
+ \box\scratchbox}}%
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \gdef\margincontentstrutheight{\the\strutht}%
+ %\graphicvadjust{\box\scratchbox}} % fails in high math lines, let it be
+ %\hbox{\lower\strutdp\box\scratchbox}} % alas, wrong lapping, therefore useless
+ \dopositionmarginbox\scratchbox}
+
+% \def\domarginblockskip#1%
+% {\hskip\margincontenthoffset
+% \hskip\compensatedinnermakeupmargin\relax
+% \doifelsenothing\margincontentdistance
+% {\hskip\getvalue{\??im#1\c!distance}}
+% {\hskip\margincontentdistance}%
+% \relax}
+
+\def\domarginblockskip#1%
+ {\doifelsenothing\margincontentdistance
+ {\hskip\dimexpr
+ +\margincontenthoffset
+ +\compensatedinnermakeupmargin
+ +\csname\??im#1\c!distance\endcsname
+ \relax}
+ {\dimexpr
+ +\margincontenthoffset
+ +\compensatedinnermakeupmargin
+ +\margincontentdistance
+ \relax}%
+ \relax}
+
+\def\doleftmarginblock#1#2%
+ {\doplacemargintext{#1}\llap\zeropoint
+ {\llap{\placemargincontentseparator}%
+ \makemargintextblock\v!left\v!right{#2}%
+ \domarginblockskip\v!left}}
+
+\def\dorightmarginblock#1#2%
+ {\doplacemargintext{#1}\rlap\hsize
+ {\hskip\textwidth\hskip-\hsize % new: hsize correction
+ \domarginblockskip\v!right
+ \makemargintextblock\v!right\v!left{#2}%
+ \rlap{\placemargincontentseparator}}}
+
+\unexpanded\def\placemargincontentseparator
+ {\ifnum\margincontentlevel>\zerocount
+ \ifx\margincontentseparator\empty\else
+ \bgroup
+ \scratchdimen\margincontentlines\lineheight
+ \advance\scratchdimen -\lineheight
+ \lower\scratchdimen\hbox{\margincontentseparator}%
+ \egroup
+ \fi
+ \fi}
+
+\newbox\marginconstructbox
+
+\def\doinmarginswapped#1#2#3#4%
+ {\iffirstsidefloatparagraph\nowhitespace\fi % zo laat mogelijk
+ \setbox\marginconstructbox\hbox\bgroup % prevents page break in the middle of construction
+ \startsignalrightpage
+ \doifswappedrightpageelse
+ {\rightmargintrue #2}
+ {\rightmarginfalse#1}
+ {#3}% setups
+ {#4}% content
+ \stopsignalrightpage
+ \egroup
+ \unhbox\marginconstructbox}
+
+% history made this a bit complicated, the +/- was needed before
+% we had enough mem/hash to do the page correction
+
+\edef\inmargintaglist{+,-,\v!low,\v!left,\v!right,\v!inner,\v!outer}
+
+% the old one:
+%
+% \def\doinmargin[#1][#2][#3][#4][#5]% #6 #7
+% {\doifcommonelse{+,-,\v!laag}{#4}
+% {\dodoinmargin[#1][#2][#3][#4][#5]}
+% {\dodoinmargin[#1][#2][#3][][#4]}}
+%
+% an alternative:
+%
+% \letvalue{\??im\v!laag\c!offset}\empty
+% \letvalue{\??im +\c!offset}\empty
+% \letvalue{\??im -\c!offset}\empty
+%
+% \def\doinmargin[#1][#2][#3][#4][#5]% #6 #7
+% {\doifnumberelse{#4}
+% {\dodoinmargin[#1][#2][#3][#4][#5]}
+% {\doifdefinedelse{\??im#4\c!offset}
+% {\dodoinmargin[#1][#2][#3][#4][#5]}
+% {\dodoinmargin[#1][#2][#3][][#4]}}}
+%
+% the problem is that we need to keep downward compatibility
+% with respect to the first argument thing a reference or a
+% directive; the alternative is to force users to pass a
+% directive along with a reference; anyhow, as long as one
+% does not use references that have the same name as a
+% directive we can use the (slow) alternative
+
+\def\doinmargin[#1][#2][#3][#4][#5]% #6 #7
+ {\expanded{\doifinsetelse{#4}{\inmargintaglist}}
+ {\dodoinmargin[#1][#2][#3][#4][#5]}
+ {\dodoinmargin[#1][#2][#3][][#4]}}
+
+\unexpanded\def\defineinmargin
+ {\doquadrupleempty\dodefineinmargin}
+
+\def\dodefineinmargin[#1][#2][#3][#4]%
+ {\doifassignmentelse{#4}
+ {\setupinmargin[#1][#4]%
+ \setvalue{#1}{\indentation\doquintupleempty\doinmargin[#2][#3][#1]}}
+ {\setvalue{#1}{\indentation\doquintupleempty\doinmargin[#2][#3][#4]}}}
+
+\defineinmargin [inleft] [\v!left] [\v!normal] % takes left settings
+\defineinmargin [inright] [\v!right] [\v!normal] % takes right settings
+\defineinmargin [ininner] [\v!inner] [\v!normal] % takes left/right settings
+\defineinmargin [inouter] [\v!outer] [\v!normal] % takes left/right settings
+\defineinmargin [inmargin] [\@@imlocation] [\v!normal] % takes left/right settings
+\defineinmargin [inother] [\@@imlocation] [\v!reverse] % takes left/right settings
+
+\def\inothermargin{\inother}
+
+%D This permits definitions like:
+%D
+%D \starttyping
+%D \defineinmargin [SomePlace] [inner] [normal] [distance=1cm]
+%D \defineinmargin [SomePlace] [inner] [normal] [SomePlace] \setupinmargin[SomePlace][distance=1cm]
+%D \defineinmargin [MyPlace] [inner] [normal] [SomePlace]
+%D \defineinmargin [YourPlace] [inner] [normal] [SomePlace]
+%D \stoptyping
+%D
+%D A torture test:
+%D
+%D \starttyping
+%D \startbuffer
+%D \inleft {\TestLine{red} {l}} test test test \par
+%D \inright {\TestLine{green} {r}} test test test \par
+%D \inmargin {\TestLine{blue} {m}} test test test \par
+%D \inothermargin{\TestLine{yellow} {x}} test test test \par
+%D \ininner {\TestLine{cyan} {i}} test test test \par
+%D \inouter {\TestLine{magenta}{o}} test test test \par
+%D \stopbuffer
+%D
+%D \dorecurse{80}\getbuffer \page
+%D \stoptyping
+%D
+%D and
+%D
+%D \starttyping
+%D \defineinmargin [InOuterA] [outer] [normal] [distance=0cm]
+%D \defineinmargin [InOuterB] [outer] [normal] [distance=1cm]
+%D \defineinmargin [InOuterC] [outer] [normal] [distance=2cm,line=2]
+%D
+%D \startbuffer
+%D \InOuterA{\TestLine{red} {A}} test test test \par
+%D \InOuterB{\TestLine{green}{B}} test test test \par
+%D \InOuterC{\TestLine{blue} {C}} test test test \par
+%D \stopbuffer
+%D
+%D \dorecurse{80}\getbuffer \page
+%D
+%D \dorecurse{10}{\inleft {one} test \inleft {two} test } \page
+%D
+%D \start
+%D \margintext {one} \margintext {two} \input thuan \par
+%D \setupinmargin[1][line=3,distance=1cm]
+%D \margintext [1]{one}
+%D \margintext [2]{two}
+%D \input thuan \page
+%D \stop
+%D
+%D \setupinmargin[3][location=inner,distance=1cm]
+%D \setupinmargin[4][location=outer,distance=2cm]
+%D
+%D % \setupinmargin[left] [line=2]
+%D % \setupinmargin[right][line=2]
+%D
+%D \dorecurse
+%D {10}
+%D {\margintext {\kern3cm\TestLine{blue}{none}}
+%D \margintext[3] {\TestLine{darkgray}{3}}
+%D \margintext[4] {\TestLine{darkgray}{4}}
+%D \margintext[left] {\TestLine{red} {left}}
+%D \margintext[right]{\TestLine{green} {right}}
+%D \margintext[inner]{\TestLine{cyan} {inner}}
+%D \margintext[outer]{\TestLine{magenta} {outer}}
+%D \input thuan \endgraf}
+%D
+%D \dorecurse{10}{\margintext{test\\test\\test} \input thuan \endgraf}
+%D \stoptyping
+
+% Test case:
+%
+% \setuppagenumbering[alternative=doublesided] \setupwhitespace[medium]
+%
+% \placefigure[right]{}{\externalfigure[dummy][width=2cm]}
+% \input tufte \inothermargin{test} \input tufte
+
+% test first
+%
+% setupsystem[random=1235]
+%
+% \setupinmargin[left][sidemethod=3]
+% \dorecurse{10}{test \fakewords{20}{40} test \inleft{test\\test} test \fakewords{20}{40} \par}
+% \page
+% \setupinmargin[left][sidemethod=4]
+% \dorecurse{40}{test \fakewords{50}{80} test \inleft{test\\test} \par}
+% \page
+
+\def\dodoinmargin[#1][#2][#3][#4][#5]#6%
+ {\bgroup
+ % old stuff, a bit tricky, but now interfaced
+ \edef\currentmargincontent{#1}%
+ \chardef\marginrepositionmethod\executeifdefined{\??im\currentmargincontent\c!sidemethod }\plusone
+ \chardef\margincontentmethod \executeifdefined{\??im\currentmargincontent\c!textmethod }\plusthree
+ \chardef\marginpagecheckmethod \executeifdefined{\??im\currentmargincontent\c!splitmethod}\plusone
+ % so far
+ \forgetall % otherwise sidefloat problems, added 2005/07/20, maybe dangerous
+ \postponenotes % group is (somehow) needed
+ \doifinsetelse\v!low{#4}
+ {\chardef\margincontentdisplacement\plusone}
+ {\chardef\margincontentdisplacement\zerocount}%
+ \doif\v!reverse{#2}
+ {\swapmacros\dorightmarginblock\doleftmarginblock}%
+ \processaction
+ [#1]
+ [ \v!left=>\let\next\doleftmarginblock, % no swapping
+ \v!right=>\let\next\dorightmarginblock, % no swapping
+ \v!inner=>\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock },
+ \v!outer=>\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock},
+ \s!unknown=>\ifdoublesided
+ \doifcommonelse{+,-}{#4}
+ {\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock }}
+ {\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock}}%
+ \else
+ \let\next\doleftmarginblock
+ \fi]%
+ \next{#3}{#6}%
+ \pagereference[#5]% naar binnen ! ! ! !
+ \flushnotes
+ \egroup % don't forget the group
+ \ignorespaces}
+
+% dit zijn voorlopig lokale commando's / vervallen
+%
+% \def\woordinmarge {\indentation\doquintupleempty\doinmargin[\@@implaats][\inleftmargin][\inrightmarge]}
+%
+% \def\woordinlinker {\inleftmargin } % vervallen
+% \def\woordinrechter{\inrechtermarge} % vervallen
+
+% Some day: \definemarking[\v!margetitel]
+
+%D Now come the margin text collectors. The collected content is
+%D flushed at every paragraph by the following macro. Note for
+%D myself: here the location (plaats) is no longer a tag (number).
+
+%D These are now all the same (long ago they had different
+%D implementations, somewhere in Sork time if I remember
+%D right).
+
+\def\margintext {\dodoubleempty\domargincontent}
+\def\marginword {\margintext}
+\def\margintitle{\margintext} % txt mark as well
+
+\newtoks\collectedmargintexts % so .. delayed!
+\chardef\margintextcollected \zerocount
+
+\def\domargincontent[#1][#2]#3% we used to check for #2/#1 being number, no longer now
+ {\global\chardef\margintextcollected\plusone
+ \global\let\flushmargincontents\doflushmargincontents
+ \edef\margincontenttag{#1}%
+ \ifx\margincontenttag\empty
+ \global\advance\margincontentlevel\plusone
+ \edef\margincontenttag{\number\margincontentlevel}%
+ \fi
+ \checkinmargin[\margincontenttag]%
+ \doglobal \appendetoks
+ \noexpand \checkinmargin[\margincontenttag]%
+ \noexpand \doinmargin[\executeifdefined{\??im\margincontenttag\c!location}\@@imlocation][\v!normal][\margincontenttag][\margincontenttag][#2]%
+ \to \collectedmargintexts
+ \doglobal \appendtoks
+ {#3}%
+ \to \collectedmargintexts}
+
+\def\doflushmargincontents % plural
+ {\ifcase\margintextcollected\else
+ \expandafter\flushmargincontentsindeed
+ \fi}
+
+\let\flushmargincontents\relax
+
+\def\flushmargincontentsindeed % links + rechts
+ {\bgroup
+ \forgetall
+ \global\margincontentheight\zeropoint
+ \startsignalrightpage
+ \the\collectedmargintexts
+ \signalrightpage
+ \stopsignalrightpage
+ \resetmargincontent
+ % dirty tricks
+ \ifcase\margincontentmethod
+ \donefalse
+ \else\ifinsidecolumns % brrrr
+ \donetrue % how fuzzy
+ \else\ifdim\margincontentheight>\lineheight\relax
+ \donetrue % how dirty
+ \else
+ \donefalse % how needed
+ \fi\fi\fi
+ \savemargincontentlines
+ \ifdone
+ \advance\margincontentheight \margincontentextralines\lineheight
+ \ifdim\pagegoal>\pagetotal
+ \bgroup % preserve \margincontentheight
+ \advance\margincontentheight \pagetotal
+ \ifdim\margincontentheight>\pagegoal
+ \egroup
+ \ifcase\marginpagecheckmethod
+ % disabled
+ \or
+ \setmargincontentpenalties
+ \or
+ % potentially dangerous, maybe better a \goodbreak; the problem is that
+ % there can be a penalty there, which we then overload and we also introduce
+ % nasty side effects, so, we drop this option
+ % \vadjust pre {\page}%
+ \fi
+ \else
+ \egroup
+ \fi
+ \fi
+ \else % We need the above because interlinepenalties overrule vadjusted \nobreaks.
+ % a bit dangerous
+ \vadjust{\nobreak}%
+ \fi
+ \global\let\flushmargincontents\relax
+ \egroup}
+
+\def\setmargincontentpenalties
+ {\getnoflines\margincontentheight
+ \keeplinestogether\noflines}
+
+\def\savemargincontentlines
+ {\bgroup
+ \advance\margincontentheight \margincontentextralines\lineheight % 1 by default
+ \getnoflines\margincontentheight
+ \xdef\nofmargincontentlines{\the\noflines}%
+ \egroup}
+
+\def\fillupmargincontentlines % etex ! ! !
+ {\endgraf
+ \begingroup
+ \scratchcounter\numexpr\nofmargincontentlines-\prevgraf\relax\relax
+ \ifnum\scratchcounter>\zerocount
+ \forgetall\dorecurse\scratchcounter{\nobreak\crlf}%
+ \fi
+ \endgroup}
+
+% Yet undocumented, for a manual flush in for instance headers.
+
+\def\resetmargincontent
+ {\global\margincontentlevel\zerocount
+ \global\chardef\margintextcollected\zerocount
+ \global\collectedmargintexts\emptytoks}
+
+\unexpanded\def\placemargincontent
+ {\ifcase\margintextcollected\else % was level check
+ \bgroup
+ \redoconvertfont % !!
+ \chardef\graphicvadjustmode\zerocount
+ \flushmargincontentsindeed
+ \egroup
+ \fi}
+
+% For old times sake (i use it in project styles) we provide
+
+\unexpanded\def\placemargintexts {\placemargincontent}
+\def\resetmargetitels {\resetmargincontent}
+\def\margewoordpositie{\margewoord} % obsolete, now no longer range
+
+% but never use them yourself since they may disappear.
+
+\def\oplinker#1%
+ {\strut
+ \graphicvadjust
+ {\dontcomplain
+ \setbox\scratchbox\vtop{\forgetall\strut#1}%
+ \getboxheight\scratchdimen\of\box\scratchbox
+ \vskip-\scratchdimen % waarom stond hier een \ ?
+ \box\scratchbox}}
+
+\setupinmargin
+ [\c!style=\v!bold,
+ \c!color=,
+ \c!strut=\v!auto,
+ \c!location=\v!both,
+ \c!align=\v!inner,
+ \c!stack=\v!no,
+ \c!before=,
+ \c!after=]
+
+\setupinmargin
+ [\v!left]
+ [\c!distance=\leftmargindistance,
+ \c!width=\leftmarginwidth,
+ %\c!align=\v!left, % no
+ \c!location=\v!left]
+
+\setupinmargin
+ [\v!right]
+ [\c!distance=\rightmargindistance,
+ \c!width=\rightmarginwidth,
+ %\c!align=\v!right, % no
+ \c!location=\v!right]
+
+% bonus needed when [inner/outer] is used as tag
+
+\setupinmargin[\v!inner][\c!location=\v!inner,\c!align=\v!inner]
+\setupinmargin[\v!outer][\c!location=\v!outer,\c!align=\v!inner]
+
+% more efficient (5K less fotmat file)
+%
+% \letvalue{\??im\v!inner\c!location}\v!inner \letvalue{\??im\v!inner\c!align}\v!inner
+% \letvalue{\??im\v!outer\c!location}\v!outer \letvalue{\??im\v!outer\c!align}\v!inner
+
+\protect \endinput
diff --git a/tex/context/base/page-mis.mkii b/tex/context/base/page-mis.mkii
new file mode 100644
index 000000000..bd029f896
--- /dev/null
+++ b/tex/context/base/page-mis.mkii
@@ -0,0 +1,268 @@
+%D \module
+%D [ file=page-mis,
+%D version=2008.11.17, % was part of page-flt.tex / 2000.10.20
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Misc Float Things,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Misc Float Things}
+
+\unprotect
+
+\newif\ifmargeblokken
+
+\def\dosetupmarginblocks[#1]%
+ {\getparameters[\??mb][#1]%
+ \doifelse\@@mbstate\v!start
+ {\showmessage\m!layouts4\empty
+ \margeblokkentrue
+ \let\somenextfloat\dosomenextfloat
+ \let\startmarginblock\dostartmarginblock
+ \let\stopmarginblock\dostopmarginblock}%
+ {\showmessage\m!layouts5\empty
+ \margeblokkenfalse
+ \def\somenextfloat[##1]%
+ {\someelsefloat[##1,\v!here]}%
+ \let\startmarginblock\dontstartmargeblok
+ \let\stopmarginblock\dontstopmargeblok}}
+
+\def\setupmarginblocks
+ {\dosingleargument\dosetupmarginblocks}
+
+\newbox\marginbox
+
+\def\dosomenextfloat[#1]%
+ {\global\setbox\marginbox\vbox
+ {\hsize\@@mbwidth
+ \unvcopy\marginbox
+ \ifvoid\marginbox\else\expandafter\@@mbinbetween\fi
+ \box\floatbox\filbreak}%
+ \ifdim\ht\marginbox>\textheight
+ \dosavefloatinfo
+ \else
+ \doinsertfloatinfo
+ \fi}
+
+\newbox\preparedmarginbox
+
+\def\reshapemargin
+ {\ifdim\ht\preparedmarginbox>\zeropoint
+ \beginofshapebox
+ \unvbox\preparedmarginbox
+ \endofshapebox
+ \reshapebox
+ {\box\shapebox}%
+ \setbox\preparedmarginbox\vbox to \textheight
+ {\@@mbtop
+ \flushshapebox
+ \@@mbbottom}%
+ \fi}
+
+\def\plaatsrechtermargeblok
+ {\hskip\rightmarginwidth}
+
+\def\plaatslinkermargeblok
+ {\hskip\leftmarginwidth}
+
+\def\checkmargeblokken
+ {\ifvoid\marginbox\else\docheckmargeblokken\fi}
+
+\def\docheckmargeblokken % erg inefficient
+ {\setbox\preparedmarginbox\vbox
+ {\forgetall
+ \splittopskip\topskip
+ \ifvoid\marginbox\else
+ \ifdim\ht\marginbox>\textheight
+ \vsplit\marginbox to \textheight
+ \else
+ \unvbox\marginbox
+ \fi
+ \fi}%
+ \reshapemargin
+ \setbox\preparedmarginbox\vbox
+ {\@@mbbefore\box\preparedmarginbox\@@mbafter}%
+ \def\rightmarginbox
+ {\def\plaatsrechtermargeblok
+ {\setbox\preparedmarginbox\hbox to \rightmarginwidth
+ {\@@mbleft\box\preparedmarginbox\@@mbright}%
+ \vsmashbox\preparedmarginbox
+ \box\preparedmarginbox}}%
+ \def\leftmarginbox
+ {\def\plaatslinkermargeblok
+ {\setbox\preparedmarginbox\hbox to \leftmarginwidth
+ {\@@mbright\box\preparedmarginbox\@@mbleft}%
+ \vsmashbox\preparedmarginbox
+ \box\preparedmarginbox}}%
+ \processaction % traag
+ [\@@mblocation]
+ [ \v!inmargin=>\doifbothsidesoverruled\rightmarginbox\rightmarginbox\leftmarginbox,
+ \v!middle=>\doifbothsidesoverruled\rightmarginbox\leftmarginbox\rightmarginbox,
+ \v!left=>\leftmarginbox,
+ \v!right=>\rightmarginbox,
+ \s!unknown=>\setbox\preparedmarginbox\hbox{}]}
+
+\def\dostartmarginblock % 2 maal \vbox ivm \unvbox elders
+ {\global\setbox\marginbox\vtop\bgroup\vbox\bgroup
+ \hsize\@@mbwidth
+ \ifvoid\marginbox\else
+ \unvbox\marginbox
+ \@@mbinbetween
+ \fi
+ \setupalign[\@@mbalign]%
+ \dostartattributes\??mb\c!style\c!color{}%
+ \begstrut\ignorespaces}
+
+\def\dostopmarginblock
+ {\unskip\endstrut
+ \dostopattributes
+ \egroup
+ \egroup}
+
+\def\dontstartmargeblok
+ {\@@mbbefore
+ \bgroup
+ \dostartattributes\??mb\c!style\c!color\empty}
+
+\def\dontstopmargeblok
+ {\dostopattributes
+ \egroup
+ \@@mbafter}
+
+\newcounter\nofpostponedblocks
+
+\newif\ifinpostponing
+
+\newevery\everytopofpage\relax
+
+\appendtoks \the\everytopofpage \to\everystarttext
+\appendtoks\global\everytopofpage\emptytoks\to\everystoptext
+
+% \startpostponing [pagenumber] [+pageoffset]
+%
+% \startpostponing[2]
+% PAGE 2 \blank
+% \stoppostponing
+%
+% \startpostponing[+1]
+% PAGE +1 \blank
+% \stoppostponing
+%
+% \startpostponing[+2]
+% PAGE +2 \blank
+% \stoppostponing
+%
+% \starttext \dorecurse{4}{\input tufte \page} \stoptext
+
+\newtoks \postponedpageblocks
+\newcounter\nofpostponedpageblocks
+
+% \ifinpostponing: handhaven, want gebruikt in stijlen ! ! ! ! !
+
+\def\flushpagefloats
+ {\doifoddpageelse
+ {\ifvoid\collectedleftpagefloats
+ \ifvoid\collectedrightpagefloats\else
+ \unvbox\collectedrightpagefloats
+ \page
+ %\the\everytopofpage
+ \fi
+ \fi}
+ {\ifvoid\collectedleftpagefloats\else
+ \unvbox\collectedleftpagefloats
+ \page
+ %\the\everytopofpage
+ \fi
+ \ifvoid\collectedrightpagefloats\else
+ \unvbox\collectedrightpagefloats
+ \page
+ %\the\everytopofpage
+ \fi}%
+ \ifvoid\collectedpagefloats\else
+ % message
+ \unvbox\collectedpagefloats
+ \fi}
+
+% \def\flushrestfloats
+% {\doif{\floatsharedparameter\c!cache}\v!no\doflushfloats}
+
+% \let\flushrestfloats\relax
+
+\def\dopostponeblock
+ {\bgroup % new may 2004
+ \setsystemmode\v!postponing % new may 2004
+ \the\everytopofpage
+ %\flushrestfloats
+ \flushpagefloats
+ \donefalse
+ \ifinpostponing \else
+ \ifcase\nofpostponedblocks \else \donetrue \fi
+ \ifcase\nofpostponedpageblocks \else \donetrue \fi
+ \fi
+ \ifdone
+ \bgroup % we need the color/font switch, else problems inside split verbatim
+ \setnormalcatcodes % postponing in verbatim
+ \pushpostponedpagecolor
+ \restoreglobalbodyfont % The \nof-test is
+ \global\pagetotal\zeropoint % recently added and
+ \global\inpostponingtrue % definitely needed else
+ \the\postponedpageblocks % we can loose or disorder
+ \dorecurse\nofpostponedblocks % floats; anyhow, this
+ {\getbuffer[pbuf-\recurselevel]}% % mechanism is still
+ \doflushfloats % new but potential dangerous % suboptimal and needs a
+ \doglobal\newcounter\nofpostponedblocks % proper analysis
+ \global\inpostponingfalse
+ \poppostponedpagecolor
+ \egroup
+ \fi
+ \egroup} % new may 2004
+
+\def\getpostponedblock#1#2%
+ {\doif{#1}\realfolio{\getbuffer[rbuf-#2]}} % no \ifnum, avoid \fi
+
+% beware, \dosingleempty conflicts with buffers (feeds back the \par)
+
+\setvalue{\e!start\v!postponing}%
+ {\bgroup
+ \obeylines
+ \doifnextoptionalelse{\egroup\nodostartpostponing}{\egroup\dodostartpostponing}}
+
+\def\nodostartpostponing[#1]%
+ {\doglobal\increment\nofpostponedpageblocks
+ \bgroup % a little bit of misusing grouping
+ \doifinstring{+}{#1}\advance \realpageno#1\relax % ugly but efficient
+ \doglobal\appendetoks\noexpand\getpostponedblock
+ {\realfolio}{\nofpostponedpageblocks}\to\postponedpageblocks
+ \egroup
+ \showmessage\m!layouts3\nofpostponedpageblocks
+ \dostartbuffer[rbuf-\nofpostponedpageblocks]%
+ [\e!start\v!postponing][\e!stop\v!postponing]}
+
+\def\dodostartpostponing
+ {\doglobal\increment\nofpostponedblocks
+ \showmessage\m!layouts3\nofpostponedblocks
+ \expanded{\dostartbuffer[pbuf-\nofpostponedblocks][\e!start\v!postponing][\e!stop\v!postponing]}}
+
+% Setups:
+
+\setupmarginblocks
+ [\c!state=\v!start,
+ \c!location=\v!inmargin,
+ \c!width=\rightmarginwidth,
+ \c!style=,
+ \c!color=,
+ \c!align=,
+ \c!left=,
+ \c!right=,
+ \c!top=,
+ \c!inbetween=\blank,
+ \c!bottom=\vfill,
+ \c!before=,
+ \c!after=]
+
+\protect \endinput
diff --git a/tex/context/base/page-mis.mkiv b/tex/context/base/page-mis.mkiv
new file mode 100644
index 000000000..f7c3d529d
--- /dev/null
+++ b/tex/context/base/page-mis.mkiv
@@ -0,0 +1,239 @@
+%D \module
+%D [ file=page-mis,
+%D version=2008.11.17, % was part of page-flt.tex / 2000.10.20
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Misc Float Things,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Misc Float Things}
+
+\unprotect
+
+\newif\ifmarginblocks
+
+\def\dosetupmarginblocks[#1]%
+ {\getparameters[\??mb][#1]%
+ \doifelse\@@mbstate\v!start
+ {\showmessage\m!layouts4\empty
+ \marginblockstrue
+ \let\somenextfloat\dosomenextfloat
+ \let\startmarginblock\dostartmarginblock
+ \let\stopmarginblock\dostopmarginblock}%
+ {\showmessage\m!layouts5\empty
+ \marginblocksfalse
+ \def\somenextfloat[##1]%
+ {\someelsefloat[##1,\v!here]}%
+ \let\startmarginblock\dontstartmargeblok
+ \let\stopmarginblock\dontstopmargeblok}}
+
+\unexpanded\def\setupmarginblocks
+ {\dosingleargument\dosetupmarginblocks}
+
+\newbox\marginbox
+
+\def\dosomenextfloat[#1]%
+ {\global\setbox\marginbox\vbox
+ {\hsize\@@mbwidth
+ \unvcopy\marginbox
+ \ifvoid\marginbox\else\expandafter\@@mbinbetween\fi
+ \box\floatbox\filbreak}%
+ \ifdim\ht\marginbox>\textheight
+ % \dosavefloatinfo
+ \else
+ \doinsertfloatinfo
+ \fi}
+
+\newbox\preparedmarginbox
+
+\def\reshapemargin
+ {\ifdim\ht\preparedmarginbox>\zeropoint
+ \beginofshapebox
+ \unvbox\preparedmarginbox
+ \endofshapebox
+ \reshapebox
+ {\box\shapebox}%
+ \setbox\preparedmarginbox\vbox to \textheight
+ {\@@mbtop
+ \flushshapebox
+ \@@mbbottom}%
+ \fi}
+
+\unexpanded\def\placerightmarginblock
+ {\hskip\rightmarginwidth}
+
+\unexpanded\def\placeleftmarginblock
+ {\hskip\leftmarginwidth}
+
+\def\checkmarginblocks
+ {\ifvoid\marginbox\else\docheckmarginblocks\fi}
+
+\def\docheckmarginblocks % erg inefficient
+ {\setbox\preparedmarginbox\vbox
+ {\forgetall
+ \splittopskip\topskip
+ \ifvoid\marginbox\else
+ \ifdim\ht\marginbox>\textheight
+ \vsplit\marginbox to \textheight
+ \else
+ \unvbox\marginbox
+ \fi
+ \fi}%
+ \reshapemargin
+ \setbox\preparedmarginbox\vbox
+ {\@@mbbefore\box\preparedmarginbox\@@mbafter}%
+ \def\rightmarginbox
+ {\unexpanded\def\placerightmarginblock
+ {\setbox\preparedmarginbox\hbox to \rightmarginwidth
+ {\@@mbleft\box\preparedmarginbox\@@mbright}%
+ \vsmashbox\preparedmarginbox
+ \box\preparedmarginbox}}%
+ \def\leftmarginbox
+ {\unexpanded\def\placeleftmarginblock
+ {\setbox\preparedmarginbox\hbox to \leftmarginwidth
+ {\@@mbright\box\preparedmarginbox\@@mbleft}%
+ \vsmashbox\preparedmarginbox
+ \box\preparedmarginbox}}%
+ \processaction % traag
+ [\@@mblocation]
+ [ \v!inmargin=>\doifbothsidesoverruled\rightmarginbox\rightmarginbox\leftmarginbox,
+ \v!middle=>\doifbothsidesoverruled\rightmarginbox\leftmarginbox\rightmarginbox,
+ \v!left=>\leftmarginbox,
+ \v!right=>\rightmarginbox,
+ \s!unknown=>\setbox\preparedmarginbox\hbox{}]}
+
+\def\dostartmarginblock % 2 maal \vbox ivm \unvbox elders
+ {\global\setbox\marginbox\vtop\bgroup\vbox\bgroup
+ \hsize\@@mbwidth
+ \ifvoid\marginbox\else
+ \unvbox\marginbox
+ \@@mbinbetween
+ \fi
+ \setupalign[\@@mbalign]%
+ \dostartattributes\??mb\c!style\c!color{}%
+ \begstrut\ignorespaces}
+
+\def\dostopmarginblock
+ {\unskip\endstrut
+ \dostopattributes
+ \egroup
+ \egroup}
+
+\def\dontstartmargeblok
+ {\@@mbbefore
+ \bgroup
+ \dostartattributes\??mb\c!style\c!color\empty}
+
+\def\dontstopmargeblok
+ {\dostopattributes
+ \egroup
+ \@@mbafter}
+
+\newcount\nofpostponedblocks
+
+\newif\ifinpostponing
+
+\newevery\everytopofpage\relax
+
+\appendtoks \the\everytopofpage \to\everystarttext
+\appendtoks\global\everytopofpage\emptytoks\to\everystoptext
+
+% \startpostponing [pagenumber] [+pageoffset]
+%
+% \startpostponing[2]
+% PAGE 2 \blank
+% \stoppostponing
+%
+% \startpostponing[+1]
+% PAGE +1 \blank
+% \stoppostponing
+%
+% \startpostponing[+2]
+% PAGE +2 \blank
+% \stoppostponing
+%
+% \starttext \dorecurse{4}{\input tufte \page} \stoptext
+
+\newtoks \postponedpageblocks
+\newcount \nofpostponedpageblocks
+
+% \ifinpostponing: handhaven, want gebruikt in stijlen ! ! ! ! !
+
+\def\dodoflushpostponedblocks
+ {\bgroup % we need the font switch, else problems inside split verbatim
+ \setnormalcatcodes % postponing in verbatim
+ \restoreglobalbodyfont
+ \global\pagetotal\zeropoint
+ \global\inpostponingtrue
+ \the\postponedpageblocks
+ \dorecurse\nofpostponedblocks
+ {\getbuffer[pbuf-\recurselevel]}%
+ \doflushfloats % new but potential dangerous
+ \global\nofpostponedblocks\zerocount
+ \global\inpostponingfalse
+ \egroup}
+
+\def\doflushpostponedblocks
+ {\ifinpostponing \else
+ \ifcase\nofpostponedblocks \else \dodoflushpostponedblocks \fi
+ \ifcase\nofpostponedpageblocks \else \dodoflushpostponedblocks \fi
+ \fi}
+
+\def\doflushpostponedcontent
+ {\bgroup
+ \setsystemmode\v!postponing
+ \the\everytopofpage
+ %\flushrestfloats
+ \doflushpagefloats
+ \doflushpostponedblocks
+ \egroup}
+
+\def\getpostponedblock#1#2%
+ {\doif{#1}\realfolio{\getbuffer[rbuf-#2]}} % no \ifnum, avoid \fi
+
+% beware, \dosingleempty conflicts with buffers (feeds back the \par)
+
+\setvalue{\e!start\v!postponing}%
+ {\bgroup
+ \obeylines
+ \doifnextoptionalelse{\egroup\nodostartpostponing}{\egroup\dodostartpostponing}}
+
+\def\nodostartpostponing[#1]%
+ {\global\advance\nofpostponedpageblocks\plusone % hm, never reset?
+ \bgroup % a little bit of misusing grouping
+ \doifinstring{+}{#1}\advance \realpageno#1\relax % ugly but efficient
+ \doglobal\appendetoks\noexpand\getpostponedblock
+ {\realfolio}{\number\nofpostponedpageblocks}\to\postponedpageblocks
+ \egroup
+ \showmessage\m!layouts3{\number\nofpostponedpageblocks}%
+ \dostartbuffer[rbuf-\number\nofpostponedpageblocks]%
+ [\e!start\v!postponing][\e!stop\v!postponing]}
+
+\def\dodostartpostponing
+ {\global\advance\nofpostponedblocks\plusone
+ \showmessage\m!layouts3{\number\nofpostponedblocks}%
+ \expanded{\dostartbuffer[pbuf-\number\nofpostponedblocks][\e!start\v!postponing][\e!stop\v!postponing]}}
+
+% Setups:
+
+\setupmarginblocks
+ [\c!state=\v!start,
+ \c!location=\v!inmargin,
+ \c!width=\rightmarginwidth,
+ \c!style=,
+ \c!color=,
+ \c!align=,
+ \c!left=,
+ \c!right=,
+ \c!top=,
+ \c!inbetween=\blank,
+ \c!bottom=\vfill,
+ \c!before=,
+ \c!after=]
+
+\protect \endinput
diff --git a/tex/context/base/page-mul.mkii b/tex/context/base/page-mul.mkii
new file mode 100644
index 000000000..c78af074a
--- /dev/null
+++ b/tex/context/base/page-mul.mkii
@@ -0,0 +1,1773 @@
+%D \module
+%D [ file=page-mul, % was: core-mul
+%D version=1998.03.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Multi Column Output,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Simple Multi Column}
+
+%D This module is mostly a copy from the original multi column
+%D routine as implemented in \type {core-mul}. When the main
+%D OTR macro's were isolated in modules and column sets were
+%D introduced, this module became part of the OTR modules. As
+%D a result this module is no longer generic. It also needs
+%D an overhaul.
+
+\unprotect
+
+% TO DO !
+
+\let\OTRMULsetvsize \OTRONEsetvsize
+\let\OTRMULsethsize \OTRONEsethsize
+\let\OTRMULdopagecontents \OTRONEdopagecontents
+\let\OTRMULfinalsidefloatoutput\OTRONEfinalsidefloatoutput % ???
+\let\OTRMULflushfloatbox \OTRONEflushfloatbox
+
+\let\OTRMULdosettopinserts \relax
+\let\OTRMULdosetbotinserts \relax
+\let\OTRMULdotopinsertions \relax
+\let\OTRMULdobotinsertions \relax
+\let\OTRMULdosetbothinserts \relax
+\let\OTRMULflushsavedfloats \relax
+
+\let\OTRMULflushsidefloats \forgetsidefloats % \relax
+\let\OTRMULsynchronizesidefloats\forgetsidefloats % \relax
+
+\newtoks \OTRMULoutput
+
+\def\OTRMULgotonextpage
+ {\ejectpage}
+
+\def\OTRMULgotonextpageX % will become obsolete
+ {\superejectpage}
+
+% check \count multiplications
+
+% some day try this in balancing routine
+%
+% \ifdim\pagetotal>\pagegoal
+% \eject
+% \else
+% \goodbreak
+% \fi
+
+%D The following macro's implement a multi||column output
+%D routine. The original implementation was based on Donald
+%D Knuth's implementation, which was adapted by Craig Platt to
+%D support balancing of the last page. I gradually adapted
+%D Platt's version to our needs but under certain
+%D circumstances things still went wrong. I considered all
+%D calls to Platt's \type{\balancingerror} as undesirable.
+
+%D This completely new implementation can handle enough
+%D situations for everyday documents, but is still far from
+%D perfect. While at the moment the routine doesn't support
+%D all kind of floats, it does support:
+%D
+%D \startitemize[packed]
+%D \item an unlimitted number of columns
+%D \item ragged or not ragged bottoms
+%D \item optional balancing without \type{\balancingerrors}
+%D \item different \type{\baselineskips}, \type{\spacing},
+%D \type{\topskip} and \type{\maxdepth}
+%D \item left- and right indentation, e.g. within lists
+%D \item moving columns floats to the next column or page
+%D \item handling of floats that are to wide for a columns
+%D \stopitemize
+%D
+%D One could wonder why single and multi||columns modes are
+%D still separated. One reason for this is that \TeX\ is not
+%D suited well for handling multi||columns. As a result, the
+%D single columns routines are more robust. Handling one
+%D column as a special case of multi||columns is posible but at
+%D the cost of worse float handling, worse page breaking,
+%D worse etc. Complicated multi||column page handling should
+%D be done in \cap{DTP}||systems anyway.
+%D
+%D There are three commands provided for entering and leaving
+%D multi||column mode and for going to the next column:
+%D
+%D \interface \type{\beginmulticolumns} \\ \\
+%D \interface \type{\endmulticolumns} \\ \\
+%D \interface \type{\ejectcolumn} \\ \\
+%D
+%D This routines are sort of stand||alone. They communicate
+%D with the rest of \CONTEXT\ by means of some interface
+%D macro's, which we only mention.
+%D
+%D \interface \type{\nofcolumns} \\
+%D the number of columns \\
+%D \interface \type{\minbalancetoplines} \\
+%D the minimum number op balanced top lines \\
+%D \interface \type{\betweencolumns} \\
+%D the stuff between columns \\
+%D \interface \type{\finaloutput{action}{box}} \\
+%D some kind of \type{\pagebody} and \type{\shipout} \\
+%D
+%D \interface \type{\ifbalancecolumns} \\
+%D balancing the colums or not \\
+%D \interface \type{\ifstretchcolumns} \\
+%D ragging the bottom or not \\
+%D
+%D \interface \type{\ifheightencolumns} \\
+%D fix the heigh tor not \\
+%D \interface \type{\fixedcolumnheight} \\
+%D the optional fixed height \\
+%D
+%D \interface \type{\ifinheritcolumns} \\
+%D handle ragging or not \\
+%D \interface \type{\ifr@ggedbottom} \\
+%D use ragged bottoms \\
+%D \interface \type{\ifb@selinebottom} \\
+%D put the bottom line on the baseline \\
+%D \interface \type{\ifnormalbottom} \\
+%D put the bottom line at the baseline \\
+%D
+%D \interface \type{\ifreversecolumns} \\
+%D reverse the order in wich columns are flushed \\
+%D
+%D \interface \type{\usercolumnwidth} \\
+%D the calculated width of a column \\
+%D \interface \type{\columntextwidth} \\
+%D the maximum width of a column \\
+%D \interface \type{\columntextheight} \\
+%D the minimum width of a column \\
+%D
+%D \interface \type{\spacingfactor} \\
+%D the spacing factor \\
+%D \interface \type{\bodyfontsize} \\
+%D the (local) bodyfontsize \\
+%D \interface \type{\openlineheight} \\
+%D the lineheight (including \type{\spacing}) \\
+%D
+%D \interface \type{\EveryBodyFont} \\
+%D communication channel to font switching routines \\
+%D
+%D \interface \type{\global\settopskip} \\
+%D set \type{\topskip} \\
+%D \interface \type{\setvsize} \\
+%D set \type{\vsize} and \type{\pagegoal} \\
+%D \interface \type{\sethsize} \\
+%D set \type{\hsize} \\
+%D
+%D \interface \type{\flushcolumnfloats} \\
+%D push saved column floats (next page) \\
+%D \interface \type{\flushcolumnfloat} \\
+%D push saved column floats (next column) \\
+%D \interface \type{\setcolumnfloats} \\
+%D initialize column floats \\
+%D
+%D \interface \type{\finishcolumnbox} \\
+%D do something special (a hook) \\
+%D \interface \type{\postprocesscolumnpagebox} \\
+%D do something with each columnbox (also a hook) \\
+%D \interface \type{\postprocesscolumnbox} \\
+%D do something with each columnbox (also a hook) \\
+%D \interface \type{\postprocesscolumnline} \\
+%D do something with each columnline (also a hook) \\
+%D \interface \type{\currentcolumn} \\
+%D the current column \\
+%D
+%D These interface macro's are called upon or initialized
+%D by the multi||column macro's.
+
+%D A lot of footnote stuff added!
+
+\def\finalcolumntextwidth {\makeupwidth}
+\def\finalcolumntextheight {\textheight}
+\def\columntextwidth {\makeupwidth}
+\def\columntextheight {\textheight}
+\def\usercolumnwidth {\textwidth}
+\def\columntextoffset {\!!zeropoint}
+
+\def\fixedcolumnheight {\textheight}
+\def\betweencolumns {\hskip\bodyfontsize}
+
+\let\setcolumnfloats \relax % in CONTEXT used for floats
+\let\flushcolumnfloats \relax % in CONTEXT used for floats
+\let\flushcolumnfloat \relax % in CONTEXT used for floats
+\let\finishcolumnbox \relax % in CONTEXT used for backgrounds
+
+% %D In fact, the column height and width are set by means of
+% %D two macro's. One can change their meaning if needed:
+%
+% \def\setcolumntextheight
+% {\def\columntextheight{\teksthoogte}}
+%
+% \def\setcolumntextwidth
+% {\def\columntextwidth{\zetbreedte}}
+
+%D Both macros are redefined in \CONTEXT\ when backgrounds
+%D are applied to columns. The final values are used when
+%D flushing the columns.
+
+\newtoks\singlecolumnout % remove that one
+
+%D It's more convenient to use \type {\columnwidth} instead
+%D of messing around with boxes each time.
+
+\newdimen\columnwidth
+\newdimen\gutterwidth
+
+\def\determinecolumnwidth
+ {\bgroup
+ \setbox\scratchbox\hbox
+ {\setcolumnhsize
+ \global\columnwidth\usercolumnwidth
+ \global\gutterwidth\intercolumnwidth}%
+ \egroup}
+
+%D Going to a new columns is done by means of a
+%D \type{\ejectcolumn}. The following definition does not
+%D always work.
+
+\def\ejectcolumn
+ {\goodbreak\showmessage\m!columns2\empty}
+
+%D The next macro should never be called so let's deal with it.
+%D There were several solutions to these kind of errors. First
+%D we check for a good breakpoint before firing up the
+%D multi||column routine (\type{\break} or \type{\allowbreak}).
+%D We do the same at the end of the routine
+%D (\type{\allowbreak}). These allowances are definitely
+%D needed!
+%D
+%D Some on first sight redundant calls to for instance
+%D \type{\setvsize} in the flushing, splitting and balancing
+%D macro's can definitely not be omitted! Some are just there
+%D to handle situations that only few times arise. One of
+%D those can be that the output routine is invoked before
+%D everything is taken care of. This happens when we
+%D flush (part of) the current page with an \type{\unvbox}
+%D with a \type{\pagetotal}~$\approx$ \type{\pagegoal}. One
+%D simply cannot balance columns that are just balanced.
+%D
+%D I hope one never sees the following message. Because it
+%D took me a lot of time to develop the multi||columns
+%D routines, every (although seldom) warning gives me the
+%D creeps!
+
+\def\balancingerror
+ {\showmessage\m!columns3\empty
+ \finaloutput\unvbox\normalpagebox}
+
+\def\OTRMULsometopsfloat{\showmessage\m!columns4\empty \someherefloat}
+\def\OTRMULsomebotsfloat{\showmessage\m!columns5\empty \someherefloat}
+
+\def\OTRMULsomeherefloat{\OTRONEsomeherefloat}
+
+%D The local column width is available in the dimension
+%D register \type{\localcolumnwidth}, which is calculated as:
+
+\def\setcolumnhsize % beware, this one is available for use in macros
+ {\setbox\scratchbox\hbox{\parindent\zeropoint\betweencolumns}%
+ \intercolumnwidth\wd\scratchbox
+ \localcolumnwidth\columntextwidth
+ \advance\localcolumnwidth -\leftskip
+ \advance\localcolumnwidth -\rightskip
+ % new
+ \advance\localcolumnwidth -\colleftskip
+ \advance\localcolumnwidth -\colrightskip
+ %
+ \advance\localcolumnwidth -\nofcolumns\intercolumnwidth
+ \advance\localcolumnwidth \intercolumnwidth
+ \divide \localcolumnwidth \nofcolumns
+ \scratchdimen\columntextoffset
+ \multiply\scratchdimen \plustwo
+ \advance\localcolumnwidth -\scratchdimen
+ \usercolumnwidth\localcolumnwidth
+ \hsize\localcolumnwidth} % we don't do it \global
+
+%D Torture test:
+%D
+%D \startbuffer
+%D \startbuffer[b]
+%D \startcolumns
+%D \input tufte
+%D \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower
+%D \input tufte
+%D \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower[left]
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D \stopbuffer
+%D
+%D \start
+%D \def\postprocesscolumnline#1{\ruledhbox{\strut\box#1}\hss}
+%D \getbuffer
+%D \stop
+
+%D One should be aware that when font related dimensions are
+%D used in typesetting the in||between material, these
+%D dimensions are influenced by bodyfont switches inside
+%D multi||column mode.
+
+\newdimen\mcscratchdimen
+\newcount\nofcolumnlines
+
+\chardef\multicolumnlinemethod\zerocount % 0: overshoot (old default), 1: tight
+% \chardef\multicolumnlinemethod\plusone
+
+\def\getmulticolumnlines
+ {\mcscratchdimen-\columntextoffset
+ \multiply\mcscratchdimen \plustwo
+ \advance\mcscratchdimen \columntextheight
+ \ifdim\precolumnboxheight>\zeropoint
+ \advance\mcscratchdimen -\precolumnboxheight
+ \fi
+ \settotalinsertionheight
+ \advance\mcscratchdimen -\totalinsertionheight
+ \ifcase\multicolumnlinemethod \getnoflines\mcscratchdimen
+ \or \getrawnoflines\mcscratchdimen
+ \else \getrawnoflines\mcscratchdimen
+ \fi
+ % added 30/7/2004
+ \ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines
+ \noflines\layoutlines
+ \fi \fi
+ \nofcolumnlines\noflines}
+
+\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
+
+\def\setcolumnvsize
+ {\getmulticolumnlines
+ \mcscratchdimen\nofcolumnlines\openlineheight
+ \advance\mcscratchdimen \multicolumnovershootratio\openlineheight % collect enough data
+ \global\vsize\nofcolumns\mcscratchdimen
+ \global\pagegoal\vsize} % let's do it only here
+
+%D It really starts here. After some checks and initializations
+%D we change the output routine to continous multi||column
+%D mode. This mode handles columns that fill the current and
+%D next full pages. The method used is (more or less)
+%D multiplying \type{\vsize} and dividing \type{\hsize} by
+%D \type{\nofcolumns}. More on this can be found in the
+%D \TeX book. We save the top of the current page in box
+%D \type{\precolumnbox}.
+%D
+%D We manipulate \type{\topskip} a bit, just to be shure that
+%D is has no flexibility. This has te be done every time a
+%D font switch takles place, because \type{\topskip} can depend
+%D on this.
+%D
+%D Watch the trick with the \type{\vbox}. This way we get the
+%D right interlining and white space.
+
+\def\beginmulticolumns
+ {\par
+ \flushnotes
+ \xdef\precolumndepth{\the\prevdepth}%
+ \begingroup
+ % new
+ \leftskip1\leftskip
+ \rightskip1\rightskip
+ \edef\colleftskip {\the\leftskip}%
+ \edef\colrightskip{\the\rightskip}%
+ \leftskip\zeropoint
+ \rightskip\zeropoint
+ %
+ \dontshowcomposition
+ %\setcolumntextwidth\relax
+ %\setcolumntextheight\relax
+ \widowpenalty\zerocount % is gewoon beter
+ \clubpenalty \zerocount % zeker bij grids
+ \ifsomefloatwaiting
+ \showmessage\m!columns6{\the\savednoffloats}%
+ \global\setbox\savedfloatlist\box\floatlist
+ \xdef\restoresavedfloats
+ {\global\savednoffloats\the\savednoffloats
+ \global\setbox\floatlist\box\savedfloatlist
+ \global\noexpand\somefloatwaitingtrue}%
+ \global\savednoffloats\zerocount
+ \global\somefloatwaitingfalse
+ \else
+ \global\let\restoresavedfloats\relax
+ \fi
+ \dimen0\pagetotal
+ \advance\dimen0 \parskip
+ \advance\dimen0 \openlineheight
+ \ifdim\dimen0<\pagegoal
+ \allowbreak
+ \else
+ \break % Sometimes fails
+ \fi
+ \appendtoks\topskip1\topskip\to\everybodyfont
+ \the\everybodyfont % ugly here
+ \saveinterlinespace % ugly here
+ \initializecolumns\nofcolumns
+ \hangafter\zerocount
+ \hangindent\zeropoint
+ \everypar\emptytoks
+ \ifdim\pagetotal=\zeropoint \else
+ \verticalstrut
+ \vskip-\struttotal
+ \fi
+ \global\savedpagetotal\pagetotal
+ \global\singlecolumnout\output
+ %\global\output{\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}}%
+ \global\output{\global\setbox\precolumnbox\vbox{\dotopinsertions\unvbox\normalpagebox}}%
+ \eject % no \holdinginserts=1, can make footnote disappear !
+ \global\precolumnboxheight\ht\precolumnbox
+ \global\output{\continuousmulticolumnsout}%
+ \setcolumnfloats
+ \dohandleallcolumns
+ {\global\setbox\currenttopcolumnbox\emptybox}%
+ \checkbegincolumnfootnotes
+ \activateotr{MUL}{ONE}% todo ! ! ! !
+ \let\sethsize\setcolumnhsize
+ \let\setvsize\setcolumnvsize
+ \sethsize
+ \setvsize
+ \showcomposition}
+
+%D When we leave the multi||column mode, we have to process the
+%D not yet shipped out part of the columns. When we don't
+%D balance, we simply force a continuous output, but a balanced
+%D output is more tricky.
+
+%D First we try to fill up the page and when all or something
+%D is left we try to balance things. This is another useful
+%D adaption of the ancesters of these macro's. It takes some
+%D reasoning to find out what happens and maybe I'm making
+%D some mistake, but it works.
+%D
+%D Voiding box \type{\precolumnbox} is sometimes necessary,
+%D e.g. when there is no text given between \type{\begin..}
+%D and \type{\end..}. The \type{\par} is needed!
+
+\chardef\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
+
+\def\endmulticolumns
+ {%\par
+ \ifnum\multicolumnendsyncmethod=\plustwo
+ \synchronizeoutput
+ \else
+ % don't combine these
+ \vskip\lineheight
+ \vskip-\lineheight % take footnotes into account
+ \fi
+ \dontshowcomposition
+ \doflushcolumnfloat % added recently
+ %\doflushcolumnfloats % no, since it results in wrong top floats
+ \flushnotes % before start of columns
+ \par
+ \ifbalancecolumns
+ \ifnum\multicolumnendsyncmethod=\plusone
+ \global\output{\continuousmulticolumnsout}%
+ \goodbreak
+ \fi
+ \global\output{\balancedmulticolumnsout}%
+ \else
+ \goodbreak
+ \fi
+ \eject % the prevdepth is important, try e.g. toclist in
+ \prevdepth\zeropoint % columns before some noncolumned text text
+ \global\output\singlecolumnout
+ \global\output{\the\mainoutput}% % % % % todo
+ \ifvoid\precolumnbox\else
+ \unvbox\precolumnbox
+ \fi
+ \global\precolumnboxheight\zeropoint
+ \endgroup % here
+ \nofcolumns\plusone
+ \setvsize % the outer one!
+ \synchronizeoutput % new may 2004 / we need to: \pagegoal\vsize
+ \checkendcolumnfootnotes
+ \dosomebreak\allowbreak
+ \restoresavedfloats}
+
+%D Because some initializations happen three times, we
+%D defined a macro for them. Erasing \type{\everypar} is
+%D needed because we don't want anything to interfere.
+
+\def\setmulticolumnsout
+ {\everypar\emptytoks
+ \dontcomplain
+ \settopskip
+ \setmaxdepth
+ \topskip1\topskip
+ \splittopskip\topskip
+ \splitmaxdepth\maxdepth
+ \boxmaxdepth\maxdepth % dangerous
+ \emergencystretch\zeropoint\relax} % sometimes needed !
+
+%D Flushing the page comes to pasting the columns together and
+%D appending the result to box \type{\precolumnbox}, if not
+%D void. I've seen a lot of implementations in which some skip
+%D was put between normal text and multi||column text. When we
+%D don't want this, the baselines can be messed up. I hope the
+%D seemingly complicated calculation of a correction
+%D \type{\kern} is adequate to overcome this. Although not
+%D watertight, spacing is taken into account and even multiple
+%D mode changes on one page go well. But cross your fingers and
+%D don't blame me.
+%D
+%D One of the complications of flushing out the boxes is that
+%D \type{\precolumnbox} needs to be \type{\unvbox}'ed, otherwise
+%D there is too less flexibility in the page when using
+%D \type{\r@ggedbottom}. It took a lot of time before these
+%D kind of problems were overcome. Using \type{\unvbox} at the
+%D wrong moment can generate \type{\balancingerror}'s.
+%D
+%D One can use the macros \type {\maxcolumnheight} and \type
+%D {\maxcolumndepth} when generating material between columns
+%D as well as postprocessing column lines.
+
+\let\maxcolumnheight=\zeropoint
+\let\maxcolumndepth =\zeropoint
+
+\newbox\columnpagebox
+
+\def\setmaxcolumndimensions
+ {\let\maxcolumnheight\!!zeropoint
+ \let\maxcolumndepth \!!zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\maxcolumnheight
+ \edef\maxcolumnheight{\the\ht\currentcolumnbox}%
+ \fi
+ \ifdim\dp\currentcolumnbox>\maxcolumndepth
+ \edef\maxcolumndepth{\the\dp\currentcolumnbox}%
+ \fi}}
+
+\chardef\multicolumntopflushmethod\plusone % 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++
+\chardef\multicolumntopalignmethod\plustwo % 0: nothing, 1: force grid, 2: follow grid
+
+\def\flushprecolumnboxnogrid
+ {\unvbox\precolumnbox}
+
+\def\flushprecolumnboxongrid
+ {\scratchdimen\savedpagetotal
+ \advance\scratchdimen -\ht\precolumnbox
+ \advance\scratchdimen -\dp\precolumnbox
+ \advance\scratchdimen -\topskip
+ \box\precolumnbox
+ \kern\scratchdimen}
+
+\newconditional\someprecolumncontent
+
+\def\flushcolumnedpage#1%
+ {\bgroup
+ \ifvoid\precolumnbox
+ \setfalse\someprecolumncontent % will be set elsewhere
+ \else
+ \settrue\someprecolumncontent
+\mkprocessboxcontents\precolumnbox
+ \fi
+ \forgetall
+ \setmulticolumnsout
+ \showcomposition
+ \setmaxcolumndimensions
+ \dohandleallcolumns
+ {\mkprocesscolumncontents\currentcolumnbox}%
+ \postprocesscolumns
+ \dohandleallcolumns % \hbox i.v.m. \showcomposition
+ {\global\setbox\currentcolumnbox\hbox to \localcolumnwidth
+ {\box\currentcolumnbox
+ \global\wd\currentcolumnbox\localcolumnwidth
+ \ifheightencolumns
+ \global\ht\currentcolumnbox\fixedcolumnheight
+ \fi}}%
+ \setmaxcolumndimensions
+ \overlaycolumnfootnotes
+ \setbox\columnpagebox\vbox
+ {\hbox to \finalcolumntextwidth
+ {\hskip\colleftskip\relax % new, \relax needed
+ \ifreversecolumns
+ \popsplitproperties % else wrong color stack
+ \@EA\dohandlerevcolumns
+ \else
+ \@EA\dohandleallcolumns
+ \fi
+ {\finishcolumnbox{\hbox
+ {\ifx\finishcolumnbox\relax\else\strut\fi
+ \box\currentcolumnbox}}%
+ \hfil}%
+ \unskip
+ \hskip\colrightskip}}% new
+ \scratchdimen\zeropoint
+ \dohandleallcolumns
+ {\ifdim-\ht\currenttopcolumnbox<\scratchdimen
+ \scratchdimen-\ht\currenttopcolumnbox
+ \fi
+ \global\setbox\currenttopcolumnbox\emptybox}%
+ \advance\scratchdimen \ht\columnpagebox
+ \setbox\scratchbox\hbox to \columntextwidth
+ {\vrule
+ \!!width\zeropoint
+ \!!height\scratchdimen
+ \!!depth\dp\columnpagebox
+ \dostepwiserecurse2\nofcolumns1{\hfil\betweencolumns}\hfil}%
+ \setbox\columnpagebox\hbox
+ {\box\columnpagebox
+ \hskip-\columntextwidth
+ \restoretextcolor{\box\scratchbox}}%
+ \postprocesscolumnpagebox % new, acts upon \box\columnpagebox
+ \ifconditional\someprecolumncontent
+ \settrue\someprecolumncontent
+ % next some incredible crappy code
+ \ifcase\multicolumntopalignmethod
+ \flushprecolumnboxnogrid % not on grid
+ \or
+ \flushprecolumnboxongrid % force on grid
+ \else\ifgridsnapping % somehow this junk fails in pascal
+ \flushprecolumnboxongrid % obey grid settings, force on grid
+ \else
+ \flushprecolumnboxnogrid % ignore grid settings, not on grid
+ \fi \fi
+ \fi
+ \global\precolumnboxheight\zeropoint
+ \setvsize
+ \dosomebreak\nobreak % hm, only needed when topstuff
+ \ifgridsnapping
+ \else
+ \ifcase\multicolumntopflushmethod
+ % sometimes method 1 goes wrong, so we need a way out; best sort this out
+ % when we run into it again
+ \or
+ % \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
+ \ifconditional\someprecolumncontent
+% \scratchdimen\topskip
+% \advance\scratchdimen -\openstrutheight
+% \nointerlineskip
+% \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \fi
+ \or
+% \scratchdimen\topskip
+% \advance\scratchdimen -\openstrutheight
+% \nointerlineskip
+% \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \or
+ % untested but maybe handy
+% \scratchdimen\topskip
+% \advance\scratchdimen -\openstrutheight
+% \nointerlineskip
+% \vskip-\scratchdimen
+% \vskip-\lineheight
+% \vbox{\strut}%
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip-\lineheight\relax
+ \vbox{\strut}%
+ \fi
+ \fi
+ \prevdepth\openstrutdepth
+ \nointerlineskip
+ \dp\columnpagebox\zeropoint
+ \global\finalcolumnheights\ht\columnpagebox
+ \getnoflines\finalcolumnheights
+ \global\finalcolumnlines\noflines
+ \ifcase#1\else
+ % messy correction, we need to rewrite this module (newcolumns)
+ \setbox\columnpagebox\vbox
+ {\offinterlineskip
+ \scratchdimen\ht\columnpagebox
+ \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
+ \box\columnpagebox
+ \vskip-\scratchdimen}%
+ \scratchdimen\noflines\openlineheight
+ \advance\scratchdimen-\openstrutdepth
+ \advance\scratchdimen-\openlineheight
+ \advance\scratchdimen\topskip
+ \ht\columnpagebox\scratchdimen
+ \dp\columnpagebox\openstrutdepth
+ % end of mess
+ \fi
+ \box\columnpagebox
+ \egroup}
+
+%D In case one didn't notice, finaly \type{\finishcolumnbox} is
+%D applied to all boxes. One can use these hooks for special
+%D purposes.
+%D
+%D Once upon a time I wanted to manipulate the individual lines
+%D in a column. This feature is demonstrated in the two examples
+%D below.
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1% or \postprocesscolumnbox
+%D {\ruledhbox{\box#1}\hss}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line: \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we show the natural width of the lines:
+%D
+%D {\getbuffer}
+%D
+%D The next example does a bit more advanced manipulation:
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1%
+%D {\ifodd\currentcolumn
+%D \hfill\unhbox#1\relax
+%D \else
+%D \relax\unhbox#1\hfill
+%D \fi}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we also see an application of \type{\currentcolumn}:
+%D
+%D {\getbuffer}
+%D
+%D This feature is implemented using the reshape macros
+%D presented in \type{supp-box}.
+
+\def\postprocesscolumns
+ {\ifx\postprocesscolumnline\undefined \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vtop
+ {\beginofshapebox
+ \unvbox\currentcolumnbox
+ \unskip\unskip
+ \endofshapebox
+ \reshapebox
+ {\dimen0\ht\shapebox
+ \dimen2\dp\shapebox
+ \setbox\shapebox\hbox to \hsize
+ {\postprocesscolumnline\shapebox}%
+ \ht\shapebox\dimen0
+ \dp\shapebox\dimen2
+ \box\shapebox}%
+ \flushshapebox
+ \everypar\emptytoks
+ \parskip\zeropoint % = \forgetall
+ \verticalstrut
+ \vskip-\struttotal
+ \vfil}}%
+ \fi
+ \ifx\postprocesscolumnbox\undefined \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\hbox
+ {\postprocesscolumnbox\currentcolumnbox}}
+ \fi}
+
+%D We default to doing nothing!
+
+\let\postprocesscolumnline =\undefined
+\let\postprocesscolumnbox =\undefined
+\let\postprocesscolumnpagebox=\relax
+
+%D \macros
+%D {reversecolumnstrue}
+%D
+%D We can force the macro that takes care of combining
+%D the columns, to flush them in the revere order. Of
+%D course, by default we don't reverse.
+
+\newif\ifreversecolumns
+
+%D Here comes the simple splitting routine. It's a bit
+%D longer than expected because of ragging bottoms or not.
+%D This part can be a bit shorter but I suppose that I will
+%D forget what happens. The splitting takes some already
+%D present material (think of floats) into account!
+%D
+%D First we present some auxiliary routines. Any material,
+%D like for instance floats, that is already present in the
+%D boxes is preserved.
+
+\def\splitcolumn#1from \box#2to \dimen#3 top \box#4%
+ {\bgroup
+ \ifdim\ht#4>\zeropoint
+ \dimen0\dimen#3\relax
+ \dimen2\dimen0
+ \advance\dimen0 -\ht#4%
+ \columnfootnotecorrection{#1}{\dimen0}%
+ \setbox0\vsplit#2 to \dimen0
+ \global\setbox#1\vbox to \dimen2
+ {\ifgridsnapping
+ \dimen0-\openstrutheight
+ \advance\dimen0 \topskip
+ \vskip\dimen0\copy#4\vskip-\dimen0
+ \else
+ \unvcopy#4%
+ \fi
+ \fuzzysnappedbox\unvbox0
+ \fakecolumnfootnotes{#1}}%
+ \else
+ \ifcase\clevernotes
+ \global\setbox#1\vsplit#2 to \dimen#3%
+ \global\setbox#1\vbox
+ {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
+ \else
+ \columnfootnotecorrection{#1}{\dimen#3}%
+ \setbox0\vsplit#2 to \dimen#3%
+ \global\setbox#1\vbox to \dimen#3%
+ {\fuzzysnappedbox\unvbox0
+ \fakecolumnfootnotes{#1}}%
+ \fi
+ \fi
+ \egroup}
+
+\def\splitcurrentcolumn from \box#1to \dimen#2%
+ {\splitcolumn\currentcolumnbox from \box#1 to \dimen#2 top \box\currenttopcolumnbox}
+
+\def\splitfirstcolumn from \box#1to \dimen#2%
+ {\splitcolumn\firstcolumnbox from \box#1 to \dimen#2 top \box\firsttopcolumnbox}
+
+\def\splitlastcolumn from \box#1to \dimen#2%
+ {\global\setbox\lastcolumnbox\vbox
+ {\unvcopy\lasttopcolumnbox
+ \fuzzysnappedbox\unvbox{#1}%
+ \fakecolumnfootnotes\lastcolumnbox}}
+
+%D NEW: still to be documented.
+
+\def\fakecolumnfootnotes#1%
+ {\relax
+ \ifcase\clevernotes\else
+ \ifnum#1=\lastcolumnbox
+ \fakenotes
+ \fi
+ \fi}
+
+\def\columnfootnotecorrection#1#2%
+ {\relax
+ \ifcase\clevernotes
+ % page notes
+ \or
+ \ifnum#1=\firstcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \else
+ \ifnum#1=\lastcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \fi}
+
+\def\overlaycolumnfootnotes
+ {\relax
+ \ifcase\clevernotes
+ % page notes
+ \else
+ \checknotepresence
+ \ifnotespresent
+ % the note box has the depth of the notefont
+ % because a column (i.e. first column has no depth,
+ % we need to anchor top down)
+ \bgroup
+ \ifcase\clevernotes\or
+ \getmulticolumnlines
+ \advance\nofcolumnlines \minustwo
+ \scratchdimen\nofcolumnlines\lineheight
+ \advance\scratchdimen \topskip
+ \setbox0\hbox
+ {\lower\scratchdimen\vbox{\placenoteinserts}}%
+ \ht0=\openstrutheight % \strutht
+ \dp0=\openstrutdepth % \strutdp
+ \scratchdimen\ht\firstcolumnbox
+ \global\setbox\firstcolumnbox\vbox to \scratchdimen
+ {\box\firstcolumnbox
+ \vskip-\scratchdimen
+ \restoretextcolor{\box0}}%
+ \else
+ % maybe here also \getmulticolumnlines
+ \scratchdimen\ht\firstcolumnbox
+ \advance\scratchdimen -\openstrutdepth % \strutdp
+ \getnoflines\scratchdimen
+ \advance\noflines \minustwo
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen \topskip
+ \setbox0\hbox
+ {\lower\scratchdimen\vbox{\placenoteinserts}}%
+ \ht0=\openstrutheight % \strutht
+ \dp0=\openstrutdepth % \strutdp
+ \scratchdimen\ht\lastcolumnbox
+ \global\setbox\lastcolumnbox\vbox to \scratchdimen
+ {\box\lastcolumnbox
+ \vskip-\scratchdimen
+ \restoretextcolor{\box0}}%
+ \fi
+ \egroup
+ \fi
+ \fi}
+
+%D Here comes the routine that splits the long box in columns.
+%D The macro \type{\flushcolumnfloats} can be used to flush
+%D either floats that were present before the multi||column
+%D mode was entered, or floats that migrate to next columns.
+%D Flushing floats is a delicate process.
+
+\def\continuousmulticolumnsout
+ {\bgroup
+ \forgetall
+ \setmulticolumnsout
+ \dontshowcomposition
+% \dimen0=\columntextheight
+% \advance\dimen0 -\precolumnboxheight
+% \settotalinsertionheight
+% \advance\dimen0 -\totalinsertionheight
+% \ifgridsnapping % evt altijd, nog testen
+% \getnoflines{\dimen0}
+% \dimen0=\noflines\openlineheight
+% \fi
+ \getmulticolumnlines
+ \dimen0=\nofcolumnlines\openlineheight
+ \dohandleallcolumns
+ {\splitcurrentcolumn from \box\normalpagebox to \dimen0}%
+ \setbox\restofpage\vbox{\unvbox\normalpagebox}%
+ \ifinheritcolumns
+ \ifr@ggedbottom % vreemd
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\dimen0\dp\currentcolumnbox
+ \unvbox\currentcolumnbox
+ \vskip-\dimen0
+ \vskip\openstrutdepth % \strutdp
+ \prevdepth\openstrutdepth % \strutdp
+ \vfill}}%
+ \ifbottomnotes \else
+ \dimen0\ht\firstcolumnbox
+ \fi
+ \fi
+ \ifn@rmalbottom
+ \advance\dimen0 \maxdepth
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\unvbox\currentcolumnbox}}%
+ \fi
+ \ifb@selinebottom
+ % the columns are on top of the baseline
+ \fi
+ \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \unvbox\currentcolumnbox % wel of niet \unvbox ?
+ \vfill
+ \fi}}%
+ \dohandleallcolumns
+ {\global\ht\currentcolumnbox\dimen0}%
+ \fi
+ \setbox\precolumnbox\vbox{\flushcolumnedpage\zerocount}%
+ \finaloutput\box\precolumnbox
+ \sethsize
+ \setvsize
+ \flushcolumnfloats
+ \unvbox\restofpage
+ % \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
+ \egroup}
+
+%D And this is the balancing stuff. Again, part of the routine
+%D is dedicated to handling ragged bottoms, but here we also
+%D see some handling concerning the stretching of columns.
+%D We set \type{\widowpenalty} at~0, which enables us to
+%D balance columns with few lines. The use of \type{\box2} and
+%D \type{\box4} garantees a more robust check when skips are
+%D used.
+
+\def\multicolumnsbalancemax{250} % 100 is too small when floats are involved
+
+\def\balancedmulticolumnsout
+ {\bgroup
+ \setmulticolumnsout
+ \dontshowcomposition
+ \widowpenalty\zerocount
+ \setbox0\vbox{\unvbox\normalpagebox}%
+\ifdim\ht0>\openlineheight % at least one line
+ \ifnum\minbalancetoplines<2 % balance anyway
+ \donetrue
+ \else % check criterium to available lines
+ \getnoflines{\ht0}%
+ \divide\noflines \nofcolumns \relax
+ \ifnum\noflines<\minbalancetoplines \relax
+ \dimen0\ht0
+ \advance\dimen0 \ht\firsttopcolumnbox
+ \advance\dimen0 \openlineheight \relax % let's play safe
+ \ifdim\dimen0>\columntextheight % column exceeding text height
+ \donetrue
+ \else % it seems to fit
+ \donefalse
+ \fi
+ \else % balance indeed
+ \donetrue
+ \fi
+ \fi
+\else % balancing does not make sense
+ \donefalse
+\fi
+\ifdone % start balancing
+ %\ifdim\ht0>\openlineheight
+ \dimen0\ht0
+ \advance\dimen0 \topskip
+ \advance\dimen0 -\baselineskip
+ \dohandleallcolumns
+ {\advance\dimen0 \ht\currenttopcolumnbox}%
+ \divide\dimen0 \nofcolumns
+ \vbadness\!!tenthousand\relax
+ \count255=\zerocount
+ \bgroup
+ \ifgridsnapping
+ \dimen2\lineheight
+ \else
+ \dimen2=\onepoint % RUBISH
+ \dimen2=\spacingfactor\dimen2
+ \fi
+ \doloop
+ {\advance\count255 \plusone
+ \global\setbox\restofpage\copy0\relax
+ \splitfirstcolumn from \box\restofpage to \dimen0
+ \dohandlemidcolumns
+ {\splitcurrentcolumn from \box\restofpage to \dimen0}%
+ \splitlastcolumn from \box\restofpage to \dimen0
+ \setbox2\vbox{\unvcopy\firstcolumnbox}%
+ \dimen4\zeropoint
+ \dohandleallcolumns
+ {\setbox4\vbox
+ {\unvcopy\currentcolumnbox
+ %rather new, test this on pdftex-z.tex
+ \unpenalty\unskip\unpenalty\unskip}% maybe better in main splitter
+ %\writestatus{balance}{\the\currentcolumnbox: \the\ht4}%
+% \dimen6\ht4 \ifdim\dimen6>\dimen4 \dimen4=\dimen6 \fi}%
+ \ifdim\ht4>\dimen4 \dimen4=\ht4 \fi}%
+ \advance\dimen4 -.0005pt % get rid of accurracy problem, pretty new
+ \ifnum\count255>\multicolumnsbalancemax\relax
+ \exitloop
+ \else\ifdim\dimen4>\ht2
+ \advance\dimen0 \dimen2\relax
+ \else
+ \exitloop
+ \fi\fi}%
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}% NIEUW
+ \ifnum\count255>\multicolumnsbalancemax\relax
+ \showmessage\m!columns7\empty
+ \else
+ \showmessage\m!columns8{\the\count255\space}%
+ \fi
+ \egroup
+ \ifinheritcolumns
+ % We cannot assume that the first column is the tallest, if
+ % only because we may have an aborted balance (one line in the
+ % first column and a graphic in the second one).
+ %
+ % \dimen0\ht\firstcolumnbox
+ % \dimen2\ht\firstcolumnbox
+ %
+ \dimen0=\zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\dimen0
+ \dimen0=\ht\currentcolumnbox
+ \fi}%
+ \dimen2\dimen0
+ % so far
+ \advance\dimen2 -\openlineheight
+ \dohandleallcolumns
+ {\dimen4\ht\currentcolumnbox
+ \dimen6=10\openlineheight % funny value
+ \global\setbox\currentcolumnbox\vbox to \dimen0
+ {\unvbox\currentcolumnbox
+ \ifdim\dimen4>\dimen6
+ \ifdim\dimen4<\dimen0
+ \ifdim\dimen4>\dimen2
+ \vskip\zeropoint % !!
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi
+ \else
+ \vskip\zeropoint
+ \fi
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi}}%
+ \else
+ \bgroup
+ \ifstretchcolumns
+ \dimen0\ht\firstcolumnbox
+ \dimen2=\bottomtolerance\ht\firstcolumnbox
+ \setbox0\vbox{\unvcopy\lastcolumnbox}%
+ \advance\dimen0 -\ht0\relax
+ \advance\dimen0 -\dp0\relax
+ \ifdim\dimen0>\openlineheight\relax
+ \ifdim\dimen0>\dimen2\relax
+ % \stretchcolumnsfalse % beter goed slecht dan slecht goed
+ \showmessage\m!columns9\empty
+ \fi
+ \fi
+ \fi
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \box\currentcolumnbox
+ \vfill
+ \fi}}%
+ \egroup
+ \fi
+ \else
+ % a one liner is not properly handled here, so best rewrite the text then
+ \showmessage\m!columns{10}\empty
+ \global\setbox\firstcolumnbox\vbox{\unvbox0}%
+ \fi
+ \global\output{\balancingerror}%
+ \b@selinebottomtrue % forces depth in separation rule
+ \flushcolumnedpage\plusone
+ \multicolumnseject
+ \egroup}
+
+\def\multicolumnseject
+ {\ifdim\pagetotal>\textheight
+ \eject % new
+ \else
+ \allowbreak
+ \fi}
+
+%D The multicolumn mechanism is incorporated in a \CONTEXT\
+%D interface, which acts like:
+%D
+%D \starttyping
+%D \startcolumns[n=4,balance=no]
+%D some text
+%D \stopcolumns
+%D \stoptyping
+%D
+%D The setup is optional. The default behaviour of columns
+%D can be set up with:
+%D
+%D \starttyping
+%D \setupcolumns
+%D [n=2,
+%D balance=yes]
+%D \stoptyping
+%D
+%D In this case, stretching is according to the way it's
+%D done outside columns (\type{\inheritcolumnstrue}). Also
+%D we can setup the \type{tolerance} within a column, the
+%D \type{distance} between columns and the fixed
+%D \type{height} of a column.
+
+%D Multi||column output: the float routines
+%D
+%D Here come the routines that handle the placement of column
+%D floats. Floats that are to big migrate to the next
+%D column. Floats that are too wide, migrate to the top of the
+%D next page, where they span as much columns as needed.
+%D Floats that are left over from outside the multi||column
+%D mode are flushed first. In macro \type{\finaloutput} the
+%D topfloats that are left from previous text should be set.
+%D
+%D When there are some floats in the queue, we inhibit the
+%D flushing of floats on top of columns. The number of
+%D waiting floats is preswent in \type{\savednoftopfloats} and
+%D is saved. As long as there are floats waiting, the topfloats
+%D are places as if we are outside multi||column mode. This is
+%D neccessary for e.g. multicolumn lists.
+%D
+%D When all those floats are flushed, we switch to the local
+%D flushing routine.
+
+\def\setcolumnfloats
+ {\xdef\globalsavednoffloats{\the\savednoffloats}%
+ \ifnum\globalsavednoffloats>\zerocount
+ \setglobalcolumnfloats
+ \else
+ \setlocalcolumnfloats
+ \fi}
+
+\def\setglobalcolumnfloats
+ {\everypar\emptytoks
+ \let\flushcolumnfloat\relax
+ %\let\doroomfloat\relax
+ \let\docheckiffloatfits\relax
+ \let\flushcolumnfloats\noflushcolumnfloats}
+
+\def\setlocalcolumnfloats
+ {\everypar{\flushnotes\flushcolumnfloat\flushmargincontents\checkindentation}%
+ \let\flushcolumnfloat\doflushcolumnfloat
+ %\let\doroomfloat\docolumnroomfloat
+ \let\docheckiffloatfits\docolumnroomfloat
+ \let\flushcolumnfloats\doflushcolumnfloats
+ \let\doflushfloats\doflushcolumnfloats % new
+ \let\dosetbothinserts\relax
+ \let\dotopinsertions\relax}
+
+\def\noflushcolumnfloats
+ {\bgroup
+ \xdef\localsavednoffloats{\the\savednoffloats}%
+ \global\savednoffloats\globalsavednoffloats
+ \dotopinsertions
+ \xdef\globalsavenoffloats{\the\savednoffloats}%
+ \ifnum\globalsavednoffloats=\zerocount
+ \setlocalcolumnfloats
+ \fi
+ \global\savednoffloats\localsavednoffloats
+ \egroup}
+
+%D We need to calculate the amount of free space in a columns.
+%D When there is not enough room, we migrate the float to the
+%D next column. These macro's are alternatives (and
+%D look||alikes) of \type{\doroomfloat}. When a float is to
+%D wide, for one column, it is moved to the top of the next
+%D page. Of course such moved floats have to be taken into
+%D account when we calculate the available space. It's a pitty
+%D that such things are no integral part of \TEX.
+
+\def\getcolumnstatus\column#1\total#2\goal#3\\%
+ {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
+ \dimen2=\zeropoint
+ \count255=\zerocount
+ \dimen8=\columntextheight
+ \advance\dimen8 -\precolumnboxheight
+ \def\dogetcolumnstatus
+ {\advance\count255 \plusone
+ \advance\dimen2 \ht\currenttopcolumnbox
+ \advance\dimen2 \dp\currenttopcolumnbox
+ \dimen4\dimen2
+ \advance\dimen4 \dimen0
+ \dimen6=\count255\dimen8
+ \ifdim\dimen4>\dimen6
+ \else
+ \let\dogetcolumnstatus\relax
+ \fi}%
+ \dohandleallcolumns{\dogetcolumnstatus}%
+ \ifnum\count255=0 \count255=1 \fi
+ #1=\count255
+ #2=\dimen4
+ #3=\dimen6 }
+
+\def\getinsertionheight
+ {\ifdim\pagegoal<\maxdimen
+ \bgroup
+ \dimen0=\columntextheight
+ \advance\dimen0 -\pagegoal
+ \xdef\insertionheight{\the\dimen0}%
+ \egroup
+ \else
+ \global\let\insertionheight\zeropoint
+ \fi}
+
+\def\docolumnroomfloat
+ {\ifpostponecolumnfloats
+ \global\roomforfloatfalse
+ \else\ifnofloatpermitted
+ \global\roomforfloatfalse
+ \else
+ \bgroup
+ \getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\%
+ \advance\dimen0 2\openlineheight % nog nodig ?
+ %\ifnum\count255=\nofcolumns
+ % \getinsertionheight
+ % %\message{\insertionheight}\wait
+ % \advance\dimen0 \insertionheight
+ %\fi
+ \setbox\scratchbox\vbox % tricky met objecten ?
+ {\blank[\@@bkspacebefore]
+ \snaptogrid\vbox{\copy\floatbox}}%
+ \advance\dimen0 \ht\scratchbox
+ \advance\dimen0 .5\lineheight % needed because goal a bit higher
+ %\message{column: \the\count255; total: \the\dimen0; goal: \the\dimen2}\wait
+ \ifdim\dimen0>\dimen2
+ \global\roomforfloatfalse
+ \else
+ \global\roomforfloattrue
+ \fi
+ \ifdim\wd\floatbox>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\roomforfloatfalse
+ \fi
+ \egroup
+ \fi\fi}
+
+%D Flushing one float is done as soon as possible, i.e.
+%D \type{\everypar}. This means that (at the moment)
+%D sidefloats are not supported (overulled)!
+
+\newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
+
+\def\doflushcolumnfloat
+ {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifprocessingverbatim\else\ifsomefloatwaiting
+ \bgroup
+ \forgetall
+ \let\doflushcolumnfloat\relax
+ \getcolumnstatus\column\mofcolumns\total\dimen0\goal\dimen2\\%
+ \ifdim\dimen0>\zeropoint
+ \dogetfloat
+ \ifdim\wd\floatbox>\hsize
+ \doresavefloat
+ \else
+ %\setbox2=\vbox
+ % {\blank[\@@bkspacebefore]
+ % \snaptogrid\vbox{\copy\floatbox}%
+ % \blank[\@@bkspaceafter]
+ \setbox2=\vbox
+ {\blank[\@@bkspacebefore]
+ \snaptogrid\vbox{\copy\floatbox}}%
+ \advance\dimen0 \ht2
+ \ifdim\dimen0>\dimen2
+ \ifnum\mofcolumns<\nofcolumns
+ \advance\mofcolumns \plusone
+%% bug %% \edef\currenttopcolumnbox{\getvalue{\@@topcol\the\count255}}%
+ \ifdim\ht\currenttopcolumnbox=\zeropoint
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox{\copy\floatbox}
+ \whitespace % nodig ?
+ \blank[\@@bkspaceafter]}%
+ \dimen4=\ht\currenttopcolumnbox
+ \advance\dimen4 \dp\currenttopcolumnbox
+ \global\advance\vsize -\dimen4
+ \advance\dimen4 -\pagegoal
+ \global\pagegoal-\dimen4
+ \showmessage\m!columns{12}a%
+ \else
+ \showmessage\m!columns{12}b%
+ \doresavefloat
+ \fi
+ \else
+ \showmessage\m!columns{12}c%
+ \doresavefloat
+ \fi
+ \else
+ \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
+ \par
+ \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
+ \nobreak
+ \blank[\@@bkspacebefore]
+ \nobreak
+ \fi
+ \flushfloatbox
+ \blank[\@@bkspaceafter]
+ \fi
+ \fi
+ \fi
+ \egroup
+ \fi\fi\fi\fi}
+
+%D This one looks complicated. Upto \type{\nofcolumns} floats
+%D are placed, taking the width of a float into account. This
+%D routine can be improved on different ways:
+%D
+%D \startitemize[intro,packed]
+%D \item taking into account some imaginary baseline, just to
+%D get the captions in line
+%D \item multipass flushing until as many floats are displaced
+%D as possible
+%D \stopitemize
+%D
+%D When handling lots of (small) floats spacing can get worse
+%D because of lining out the columns.
+
+\def\doflushcolumnfloats
+ {\ifpostponecolumnfloats\else
+ \bgroup
+ \forgetall
+ \ifsomefloatwaiting
+ \dimen8\zeropoint
+ \dimen4\zeropoint
+ \count0\zerocount % count0 can be used local
+ \count2\nofcolumns % count2 can be used local
+ \dohandleallcolumns
+ {\ifnum\count0>\zerocount % the wide one's reserved space
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\copy\currenttopcolumnbox
+ \hbox{\vphantom{\copy\floatbox}}}
+ \whitespace % nodig ?
+ \blank[\@@bkspaceafter]}%
+ \else
+ \dogetfloat
+ \ifdim\wd\floatbox>\finalcolumntextwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ \ifdim\wd\floatbox>\hsize
+ \dimen0\wd\floatbox
+ \advance\dimen0 \intercolumnwidth
+ \dimen2\hsize
+ \advance\dimen2 \intercolumnwidth
+ \advance\dimen0 .5pt % hm, why 1
+ \advance\dimen2 .5pt % hm, why 2
+ \divide\dimen0 \dimen2
+ \count0\dimen0
+ \advance\count0 \plusone
+ \ifnum\count0>\count2
+ \doresavefloat
+ \count0\zerocount
+ \else
+ \dimen0=\count0\hsize
+ \advance\dimen0 \count0\intercolumnwidth
+ \advance\dimen0 -\intercolumnwidth
+ \global\setbox\floatbox\hbox to \dimen0
+ %{\hss\hbox{\copy\floatbox}\hss}%
+ {\processaction[\@@bklocation] % how easy to forget
+ [ \v!left=>\copy\floatbox\hss,
+ \v!right=>\hss\copy\floatbox,
+ \s!default=>\hss\copy\floatbox\hss,
+ \s!unknown=>\hss\copy\floatbox\hss]}%
+ \fi
+ \showmessage\m!columns{13}\empty
+ \else
+ % \showmessage\m!columns{13}\empty
+ \fi
+ \ifdim\ht\floatbox>\zeropoint\relax
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\copy\currenttopcolumnbox
+ \copy\floatbox}
+ \whitespace % nodig ?
+ \blank[\@@bkspaceafter]}%
+ \fi
+ \dimen6\ht\currenttopcolumnbox
+ \advance\dimen6 \dp\currenttopcolumnbox
+ \fi
+ \ifdim\dimen4<\ht\currenttopcolumnbox
+ \dimen4\ht\currenttopcolumnbox
+ \fi
+ \advance\dimen8 \dimen6
+ \advance\count2 \minusone
+ \advance\count0 \minusone }%
+ \setvsize
+ \global\advance\vsize -\dimen8
+ \global\pagegoal\vsize
+ \else
+ %\doflushfloats % does not snap!
+ \fi
+ \egroup
+ \fi}
+
+%D The next macro can be used to flush floats in the current
+%D stream. No width checking is (yet) done.
+
+\def\insertcolumnfloats
+ {\doloop
+ {\ifsomefloatwaiting
+ \bgroup
+ \forgetall
+ % no check for width
+ \dogetfloat
+ \blank[\@@bkspacebefore]
+ \snaptogrid\vbox{\copy\floatbox}
+ \blank[\@@bkspaceafter]
+ \egroup
+ \else
+ \exitloop
+ \fi}}
+
+%D This were the multi||column routines. They can and need to
+%D be improved but at the moment their behaviour is acceptable.
+%D
+%D One inprovement can be to normalize the height of floats
+%D to $n\times$\type{\lineheight} with a macro like:
+%D
+%D \starttyping
+%D \normalizevbox{...}
+%D \stoptyping
+
+% border case, should fit on one page
+%
+% \startcolumns
+%
+% 1 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{1}}
+% 2 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{2}}
+% 3 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{3}}
+%
+% \stopcolumns
+
+\def\setupcolumns
+ {\dosingleempty\dosetupcolumns}
+
+\def\dosetupcolumns[#1]%
+ {\getparameters[\??kl][#1]%
+ \nofcolumns\@@kln\relax
+ \processaction
+ [\@@klrule]
+ [ \v!on=>\let\betweencolumns\linebetweencolumns,
+ \v!off=>\let\betweencolumns\spacebetweencolumns,
+ \s!default=>\let\betweencolumns\spacebetweencolumns,
+ \s!unknown=>\let\betweencolumns\@@klrule]}
+
+\def\linebetweencolumns
+ {\bgroup
+ \starttextproperties
+ \ifdim\@@kldistance>\zeropoint
+ \dimen0=\@@kldistance
+ \else
+ \dimen0=\linewidth
+ \fi
+ \advance\dimen0 -\linewidth
+ \hskip.5\dimen0
+ \vrule
+ \!!width\linewidth
+ \ifb@selinebottom\!!depth\strutdepth\fi
+ \hskip.5\dimen0\relax
+ \stoptextproperties
+ \egroup}
+
+\def\spacebetweencolumns
+ {\hskip\@@kldistance}
+
+\presetlocalframed[\??kl]
+
+\def\backgroundfinishcolumnbox
+ {\doifinsetelse\@@kloffset{\v!none,\v!overlay}
+ {\let\@@kloffset\!!zeropoint}
+ {\scratchdimen\@@kloffset
+ \advance\scratchdimen -\@@klrulethickness
+ \edef\@@kloffset{\the\scratchdimen}}%
+ \localframed
+ [\??kl]
+ [\c!strut=\v!no,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!align=]}
+
+\let\restorecolumnsettings\relax
+
+\definecomplexorsimpleempty\startcolumns
+
+\def\complexstartcolumns[#1]% %% \startcolumns
+ {\bgroup
+ \let\stopcolumns\egroup
+ \ifinsidecolumns
+ \else
+ \setupcolumns[#1]%
+ \ifnum\@@kln>1\relax
+ \whitespace
+ \begingroup
+ \doif\@@kloption\v!background
+ {\let\finishcolumnbox\backgroundfinishcolumnbox
+ \let\columntextoffset\@@kloffset}%
+ \ifx\@@klcommand\empty\else
+ \let\postprocesscolumnline\@@klcommand
+ \fi
+ \doifelsenothing\@@klheight
+ \heightencolumnsfalse
+ \heightencolumnstrue
+ \doifelse\@@kldirection\v!right
+ \reversecolumnsfalse
+ \reversecolumnstrue
+ \doifelse\@@klbalance\v!yes
+ \balancecolumnstrue
+ \balancecolumnsfalse
+\installalign\v!yes {\stretchcolumnstrue \inheritcolumnsfalse}% todo: new key
+\installalign\v!no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key
+\installalign\v!text{\stretchcolumnsfalse\inheritcolumnstrue }%
+\stretchcolumnsfalse
+\inheritcolumnstrue
+\doifsomething\@@klalign{\expanded{\setupalign[\@@klalign]}}%
+% \processaction
+% [\@@klalign]
+% [ \v!yes=>\stretchcolumnstrue
+% \inheritcolumnsfalse,
+% \v!no=>\stretchcolumnsfalse
+% \inheritcolumnsfalse,
+% \v!text=>\stretchcolumnsfalse
+% \inheritcolumnstrue]%
+ \nofcolumns=\@@kln
+ %
+ % probably more is needed, and how about nesting save's
+ %
+ \savecurrentblank
+ \savecurrentwhitespace
+ \def\restorecolumnsettings
+ {\boxmaxdepth\maxdimen % done elsewhere
+ \restorecurrentblank
+ \restorecurrentwhitespace}%
+ %
+ \edef\fixedcolumnheight{\@@klheight}%
+ \edef\minbalancetoplines{\@@klntop}%
+ \setuptolerance[\@@kltolerance]% %% \startcolumns
+ \setupblank[\@@klblank]%
+ \ifdim\ctxparskip>\zeropoint\relax
+ \setupwhitespace[\@@klblank]%
+ \fi
+ \def\stopcolumns
+ {\endmulticolumns
+ \global\insidecolumnsfalse
+ \endgroup
+ \egroup}%
+ \global\insidecolumnstrue
+ \beginmulticolumns
+ \fi
+ \fi}
+
+\installcolumnbreakhandler {MUL} \v!preference
+ {\goodbreak}
+
+\installcolumnbreakhandler {MUL} \v!yes
+ {\par % todo: since
+ {\testrulewidth\zeropoint\ruledvskip\textheight} % we misuse a
+ \penalty-200 % side effect
+ \vskip-\textheight
+ }% bugged : \prevdepth-\thousandpoint} % signals top of column to \blank
+
+%D New: only at start of columns; may change ! Rather
+%D interwoven and therefore to be integrated when the multi
+%D column modules are merged. (moved from cont-new.tex)
+
+\def\setupcolumnspan[#1]%
+ {\getparameters[\??ks][#1]}
+
+\presetlocalframed
+ [\??ks]
+
+\setupcolumnspan
+ [\c!n=2,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+\newbox\columnspanbox \let\postprocesscolumnspanbox\gobbleoneargument
+
+\def\dostartcolumnspan[#1]%
+ {\bgroup
+ \setupcolumnspan[#1]%
+ \forgetall
+ \ifinsidecolumns
+ \advance\hsize \intercolumnwidth
+ \hsize\@@ksn\hsize
+ \advance\hsize -\intercolumnwidth
+ \fi
+ \dowithnextbox
+ {\setbox\columnspanbox\flushnextbox
+ \ifinsidecolumns\wd\columnspanbox\hsize\fi
+ \postprocesscolumnspanbox\columnspanbox
+ \scratchdimen\ht\columnspanbox
+ \setbox\columnspanbox\hbox % depth to be checked, probably option!
+ {\localframed[\??ks][\c!offset=\v!overlay]{\box\columnspanbox}}%
+ \ht\columnspanbox\scratchdimen
+ \dp\columnspanbox\strutdp
+ \wd\columnspanbox\hsize
+ \ifinsidecolumns
+ \ifnum\@@ksn>1
+ \setvsize
+ \dohandleallcolumns
+ {\ifnum\currentcolumn>\@@ksn\else
+ \global\setbox\currenttopcolumnbox=\vbox
+ {\ifnum\currentcolumn=1
+ \snaptogrid\vbox{\copy\columnspanbox}
+ \else
+ \snaptogrid\vbox{\vphantom{\copy\columnspanbox}}
+ \fi}%
+ \wd\currenttopcolumnbox\hsize
+ \global\advance\vsize -\ht\currenttopcolumnbox
+ \fi}
+ \global\pagegoal\vsize
+ \else
+ \snaptogrid\vbox{\box\columnspanbox}
+ \fi
+ \else
+ \snaptogrid\vbox{\box\columnspanbox}
+ \fi
+ \endgraf
+ \ifvmode\prevdepth\strutdp\fi
+ \egroup}
+ \vbox\bgroup
+ %\topskipcorrection % becomes an option !
+ \EveryPar{\begstrut\EveryPar{}}} % also !
+
+\def\startcolumnspan
+ {\dosingleempty\dostartcolumnspan}
+
+\def\stopcolumnspan
+ {\egroup}
+
+\setupcolumns
+ [\c!n=2,
+ \c!ntop=1,
+ \c!command=,
+ \c!direction=\v!right,
+ \c!rule=\v!off,
+ \c!tolerance=\v!tolerant,
+ \c!distance=1.5\bodyfontsize, % influenced by switching
+ \c!height=,
+ \c!balance=\v!yes,
+ \c!align=\v!text,
+ \c!blank={\v!line,\v!fixed},
+ \c!option=,
+ \c!rulethickness=\linewidth,
+ \c!offset=.5\bodyfontsize]
+
+%D Undocumented and still under development.
+
+\def\startsimplecolumns
+ {\dosingleempty\dostartsimplecolumns}
+
+\def\dostartsimplecolumns[#1]%
+ {\bgroup
+ \nopenalties
+ \getparameters[\??kl]
+ [\c!width=\hsize,\c!distance=1.5\bodyfontsize,%
+ \c!n=2,\c!lines=0,#1]%
+ \let\rigidcolumnlines\@@kllines
+ \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln
+ \setbox\scratchbox\vbox\bgroup
+ \forgetall} % \blank[\v!disable]
+
+\def\stopsimplecolumns
+ {\removebottomthings
+ \egroup
+ \rigidcolumnbalance\scratchbox
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/page-mul.mkiv b/tex/context/base/page-mul.mkiv
new file mode 100644
index 000000000..88ec7a5e7
--- /dev/null
+++ b/tex/context/base/page-mul.mkiv
@@ -0,0 +1,1751 @@
+%D \module
+%D [ file=page-mul, % was: core-mul
+%D version=1998.03.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Multi Column Output,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Simple Multi Column}
+
+%D This module is mostly a copy from the original multi column
+%D routine as implemented in \type {core-mul}. When the main
+%D OTR macro's were isolated in modules and column sets were
+%D introduced, this module became part of the OTR modules. As
+%D a result this module is no longer generic. It also needs
+%D an overhaul.
+
+\unprotect
+
+% TO DO !
+
+\let\OTRMULsetvsize \OTRONEsetvsize
+\let\OTRMULsethsize \OTRONEsethsize
+\let\OTRMULdopagecontents \OTRONEdopagecontents
+\let\OTRMULfinalsidefloatoutput\OTRONEfinalsidefloatoutput % ???
+\let\OTRMULflushfloatbox \OTRONEflushfloatbox
+
+\let\OTRMULdosettopinserts \relax
+\let\OTRMULdosetbotinserts \relax
+\let\OTRMULdotopinsertions \relax
+\let\OTRMULdobotinsertions \relax
+\let\OTRMULdosetbothinserts \relax
+\let\OTRMULflushsavedfloats \relax
+
+\let\OTRMULflushsidefloats \forgetsidefloats % \relax
+\let\OTRMULsynchronizesidefloats\forgetsidefloats % \relax
+
+\newtoks \OTRMULoutput
+
+\def\OTRMULgotonextpage
+ {\ejectpage}
+
+\def\OTRMULgotonextpageX % will become obsolete
+ {\superejectpage}
+
+% check \count multiplications
+
+% some day try this in balancing routine
+%
+% \ifdim\pagetotal>\pagegoal
+% \eject
+% \else
+% \goodbreak
+% \fi
+
+%D The following macro's implement a multi||column output
+%D routine. The original implementation was based on Donald
+%D Knuth's implementation, which was adapted by Craig Platt to
+%D support balancing of the last page. I gradually adapted
+%D Platt's version to our needs but under certain
+%D circumstances things still went wrong. I considered all
+%D calls to Platt's \type{\balancingerror} as undesirable.
+
+%D This completely new implementation can handle enough
+%D situations for everyday documents, but is still far from
+%D perfect. While at the moment the routine doesn't support
+%D all kind of floats, it does support:
+%D
+%D \startitemize[packed]
+%D \item an unlimitted number of columns
+%D \item ragged or not ragged bottoms
+%D \item optional balancing without \type{\balancingerrors}
+%D \item different \type{\baselineskips}, \type{\spacing},
+%D \type{\topskip} and \type{\maxdepth}
+%D \item left- and right indentation, e.g. within lists
+%D \item moving columns floats to the next column or page
+%D \item handling of floats that are to wide for a columns
+%D \stopitemize
+%D
+%D One could wonder why single and multi||columns modes are
+%D still separated. One reason for this is that \TeX\ is not
+%D suited well for handling multi||columns. As a result, the
+%D single columns routines are more robust. Handling one
+%D column as a special case of multi||columns is posible but at
+%D the cost of worse float handling, worse page breaking,
+%D worse etc. Complicated multi||column page handling should
+%D be done in \cap{DTP}||systems anyway.
+%D
+%D There are three commands provided for entering and leaving
+%D multi||column mode and for going to the next column:
+%D
+%D \interface \type{\beginmulticolumns} \\ \\
+%D \interface \type{\endmulticolumns} \\ \\
+%D \interface \type{\ejectcolumn} \\ \\
+%D
+%D This routines are sort of stand||alone. They communicate
+%D with the rest of \CONTEXT\ by means of some interface
+%D macro's, which we only mention.
+%D
+%D \interface \type{\nofcolumns} \\
+%D the number of columns \\
+%D \interface \type{\minbalancetoplines} \\
+%D the minimum number op balanced top lines \\
+%D \interface \type{\betweencolumns} \\
+%D the stuff between columns \\
+%D \interface \type{\finaloutput{action}{box}} \\
+%D some kind of \type{\pagebody} and \type{\shipout} \\
+%D
+%D \interface \type{\ifbalancecolumns} \\
+%D balancing the colums or not \\
+%D \interface \type{\ifstretchcolumns} \\
+%D ragging the bottom or not \\
+%D
+%D \interface \type{\ifheightencolumns} \\
+%D fix the heigh tor not \\
+%D \interface \type{\fixedcolumnheight} \\
+%D the optional fixed height \\
+%D
+%D \interface \type{\ifinheritcolumns} \\
+%D handle ragging or not \\
+%D \interface \type{\ifr@ggedbottom} \\
+%D use ragged bottoms \\
+%D \interface \type{\ifb@selinebottom} \\
+%D put the bottom line on the baseline \\
+%D \interface \type{\ifnormalbottom} \\
+%D put the bottom line at the baseline \\
+%D
+%D \interface \type{\ifreversecolumns} \\
+%D reverse the order in wich columns are flushed \\
+%D
+%D \interface \type{\usercolumnwidth} \\
+%D the calculated width of a column \\
+%D \interface \type{\columntextwidth} \\
+%D the maximum width of a column \\
+%D \interface \type{\columntextheight} \\
+%D the minimum width of a column \\
+%D
+%D \interface \type{\spacingfactor} \\
+%D the spacing factor \\
+%D \interface \type{\bodyfontsize} \\
+%D the (local) bodyfontsize \\
+%D \interface \type{\openlineheight} \\
+%D the lineheight (including \type{\spacing}) \\
+%D
+%D \interface \type{\EveryBodyFont} \\
+%D communication channel to font switching routines \\
+%D
+%D \interface \type{\global\settopskip} \\
+%D set \type{\topskip} \\
+%D \interface \type{\setvsize} \\
+%D set \type{\vsize} and \type{\pagegoal} \\
+%D \interface \type{\sethsize} \\
+%D set \type{\hsize} \\
+%D
+%D \interface \type{\flushcolumnfloats} \\
+%D push saved column floats (next page) \\
+%D \interface \type{\flushcolumnfloat} \\
+%D push saved column floats (next column) \\
+%D \interface \type{\setcolumnfloats} \\
+%D initialize column floats \\
+%D
+%D \interface \type{\finishcolumnbox} \\
+%D do something special (a hook) \\
+%D \interface \type{\postprocesscolumnpagebox} \\
+%D do something with each columnbox (also a hook) \\
+%D \interface \type{\postprocesscolumnbox} \\
+%D do something with each columnbox (also a hook) \\
+%D \interface \type{\postprocesscolumnline} \\
+%D do something with each columnline (also a hook) \\
+%D \interface \type{\currentcolumn} \\
+%D the current column \\
+%D
+%D These interface macro's are called upon or initialized
+%D by the multi||column macro's.
+
+%D A lot of footnote stuff added!
+
+\def\finalcolumntextwidth {\makeupwidth}
+\def\finalcolumntextheight {\textheight}
+\def\columntextwidth {\makeupwidth}
+\def\columntextheight {\textheight}
+\def\usercolumnwidth {\textwidth}
+\def\columntextoffset {\!!zeropoint}
+
+\def\fixedcolumnheight {\textheight}
+\def\betweencolumns {\hskip\bodyfontsize}
+
+\let\setcolumnfloats \relax % in CONTEXT used for floats
+\let\flushcolumnfloats \relax % in CONTEXT used for floats
+\let\flushcolumnfloat \relax % in CONTEXT used for floats
+\let\finishcolumnbox \relax % in CONTEXT used for backgrounds
+
+% %D In fact, the column height and width are set by means of
+% %D two macro's. One can change their meaning if needed:
+%
+% \def\setcolumntextheight
+% {\def\columntextheight{\teksthoogte}}
+%
+% \def\setcolumntextwidth
+% {\def\columntextwidth{\zetbreedte}}
+
+%D Both macros are redefined in \CONTEXT\ when backgrounds
+%D are applied to columns. The final values are used when
+%D flushing the columns.
+
+\newtoks\singlecolumnout % remove that one
+
+%D It's more convenient to use \type {\columnwidth} instead
+%D of messing around with boxes each time.
+
+\newdimen\columnwidth
+\newdimen\gutterwidth
+
+\def\determinecolumnwidth
+ {\bgroup
+ \setbox\scratchbox\hbox
+ {\setcolumnhsize
+ \global\columnwidth\usercolumnwidth
+ \global\gutterwidth\intercolumnwidth}%
+ \egroup}
+
+%D Going to a new columns is done by means of a
+%D \type{\ejectcolumn}. The following definition does not
+%D always work.
+
+\def\ejectcolumn
+ {\goodbreak\showmessage\m!columns2\empty}
+
+%D The next macro should never be called so let's deal with it.
+%D There were several solutions to these kind of errors. First
+%D we check for a good breakpoint before firing up the
+%D multi||column routine (\type{\break} or \type{\allowbreak}).
+%D We do the same at the end of the routine
+%D (\type{\allowbreak}). These allowances are definitely
+%D needed!
+%D
+%D Some on first sight redundant calls to for instance
+%D \type{\setvsize} in the flushing, splitting and balancing
+%D macro's can definitely not be omitted! Some are just there
+%D to handle situations that only few times arise. One of
+%D those can be that the output routine is invoked before
+%D everything is taken care of. This happens when we
+%D flush (part of) the current page with an \type{\unvbox}
+%D with a \type{\pagetotal}~$\approx$ \type{\pagegoal}. One
+%D simply cannot balance columns that are just balanced.
+%D
+%D I hope one never sees the following message. Because it
+%D took me a lot of time to develop the multi||columns
+%D routines, every (although seldom) warning gives me the
+%D creeps!
+
+\def\balancingerror
+ {\showmessage\m!columns3\empty
+ \finaloutput\unvbox\normalpagebox}
+
+\def\OTRMULsometopsfloat{\showmessage\m!columns4\empty \someherefloat}
+\def\OTRMULsomebotsfloat{\showmessage\m!columns5\empty \someherefloat}
+
+\def\OTRMULsomeherefloat{\OTRONEsomeherefloat}
+
+%D The local column width is available in the dimension
+%D register \type{\localcolumnwidth}, which is calculated as:
+
+\def\setcolumnhsize % beware, this one is available for use in macros
+ {\setbox\scratchbox\hbox{\parindent\zeropoint\betweencolumns}%
+ \intercolumnwidth\wd\scratchbox
+ \localcolumnwidth\columntextwidth
+ \advance\localcolumnwidth -\leftskip
+ \advance\localcolumnwidth -\rightskip
+ % new
+ \advance\localcolumnwidth -\colleftskip
+ \advance\localcolumnwidth -\colrightskip
+ %
+ \advance\localcolumnwidth -\nofcolumns\intercolumnwidth
+ \advance\localcolumnwidth \intercolumnwidth
+ \divide \localcolumnwidth \nofcolumns
+ \scratchdimen\columntextoffset
+ \multiply\scratchdimen \plustwo
+ \advance\localcolumnwidth -\scratchdimen
+ \usercolumnwidth\localcolumnwidth
+ \hsize\localcolumnwidth} % we don't do it \global
+
+%D Torture test:
+%D
+%D \startbuffer
+%D \startbuffer[b]
+%D \startcolumns
+%D \input tufte
+%D \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower
+%D \input tufte
+%D \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startcolumns \startnarrower[left]
+%D \input tufte
+%D \stopnarrower \stopcolumns
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns
+%D \input tufte
+%D \stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D
+%D \startbuffer[b]
+%D \startnarrower[left] \startcolumns \startnarrower
+%D \input tufte
+%D \stopnarrower\stopcolumns \stopnarrower
+%D \stopbuffer
+%D \typebuffer[b] \getbuffer[b]
+%D \stopbuffer
+%D
+%D \start
+%D \def\postprocesscolumnline#1{\ruledhbox{\strut\box#1}\hss}
+%D \getbuffer
+%D \stop
+
+%D One should be aware that when font related dimensions are
+%D used in typesetting the in||between material, these
+%D dimensions are influenced by bodyfont switches inside
+%D multi||column mode.
+
+\newdimen\mcscratchdimen
+\newcount\nofcolumnlines
+
+\chardef\multicolumnlinemethod\zerocount % 0: overshoot (old default), 1: tight
+% \chardef\multicolumnlinemethod\plusone
+
+\def\getmulticolumnlines
+ {\mcscratchdimen-\columntextoffset
+ \multiply\mcscratchdimen \plustwo
+ \advance\mcscratchdimen \columntextheight
+ \ifdim\precolumnboxheight>\zeropoint
+ \advance\mcscratchdimen -\precolumnboxheight
+ \fi
+ \settotalinsertionheight
+ \advance\mcscratchdimen -\totalinsertionheight
+ \ifcase\multicolumnlinemethod \getnoflines\mcscratchdimen
+ \or \getrawnoflines\mcscratchdimen
+ \else \getrawnoflines\mcscratchdimen
+ \fi
+ % added 30/7/2004
+ \ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines
+ \noflines\layoutlines
+ \fi \fi
+ \nofcolumnlines\noflines}
+
+\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
+
+\def\setcolumnvsize
+ {\getmulticolumnlines
+ \mcscratchdimen\nofcolumnlines\openlineheight
+ \advance\mcscratchdimen \multicolumnovershootratio\openlineheight % collect enough data
+ \global\vsize\nofcolumns\mcscratchdimen
+ \global\pagegoal\vsize} % let's do it only here
+
+%D It really starts here. After some checks and initializations
+%D we change the output routine to continous multi||column
+%D mode. This mode handles columns that fill the current and
+%D next full pages. The method used is (more or less)
+%D multiplying \type{\vsize} and dividing \type{\hsize} by
+%D \type{\nofcolumns}. More on this can be found in the
+%D \TeX book. We save the top of the current page in box
+%D \type{\precolumnbox}.
+%D
+%D We manipulate \type{\topskip} a bit, just to be shure that
+%D is has no flexibility. This has te be done every time a
+%D font switch takles place, because \type{\topskip} can depend
+%D on this.
+%D
+%D Watch the trick with the \type{\vbox}. This way we get the
+%D right interlining and white space.
+
+\def\beginmulticolumns
+ {\par
+ \flushnotes
+ \xdef\precolumndepth{\the\prevdepth}%
+ \begingroup
+ % new
+ \leftskip1\leftskip
+ \rightskip1\rightskip
+ \edef\colleftskip {\the\leftskip}%
+ \edef\colrightskip{\the\rightskip}%
+ \leftskip\zeropoint
+ \rightskip\zeropoint
+ %
+ \dontshowcomposition
+ %\setcolumntextwidth\relax
+ %\setcolumntextheight\relax
+ \widowpenalty\zerocount % is gewoon beter
+ \clubpenalty \zerocount % zeker bij grids
+ \dopushcolumnfloats
+ \dimen0\dimexpr\pagetotal+\parskip+\openlineheight\relax
+ \ifdim\dimen0<\pagegoal
+ \allowbreak
+ \else
+ \break % Sometimes fails
+ \fi
+ \appendtoks\topskip1\topskip\to\everybodyfont
+ \the\everybodyfont % ugly here
+ \saveinterlinespace % ugly here
+ \initializecolumns\nofcolumns
+ \hangafter\zerocount
+ \hangindent\zeropoint
+ \everypar\emptytoks
+ \ifdim\pagetotal=\zeropoint \else
+ \verticalstrut
+ \vskip-\struttotal
+ \fi
+ \global\savedpagetotal\pagetotal
+ \global\singlecolumnout\output
+ %\global\output{\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}}%
+ \global\output{\global\setbox\precolumnbox\vbox{\dotopinsertions\unvbox\normalpagebox}}%
+ \eject % no \holdinginserts=1, can make footnote disappear !
+ \global\precolumnboxheight\ht\precolumnbox
+ \global\output{\continuousmulticolumnsout}%
+ \setcolumnfloats
+ \dohandleallcolumns
+ {\global\setbox\currenttopcolumnbox\emptybox}%
+ \checkbegincolumnfootnotes
+ \activateotr{MUL}{ONE}% todo ! ! ! !
+ \let\sethsize\setcolumnhsize
+ \let\setvsize\setcolumnvsize
+ \sethsize
+ \setvsize
+ \showcomposition}
+
+%D When we leave the multi||column mode, we have to process the
+%D not yet shipped out part of the columns. When we don't
+%D balance, we simply force a continuous output, but a balanced
+%D output is more tricky.
+
+%D First we try to fill up the page and when all or something
+%D is left we try to balance things. This is another useful
+%D adaption of the ancesters of these macro's. It takes some
+%D reasoning to find out what happens and maybe I'm making
+%D some mistake, but it works.
+%D
+%D Voiding box \type{\precolumnbox} is sometimes necessary,
+%D e.g. when there is no text given between \type{\begin..}
+%D and \type{\end..}. The \type{\par} is needed!
+
+\chardef\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
+
+\def\endmulticolumns
+ {%\par
+ \ifnum\multicolumnendsyncmethod=\plustwo
+ \synchronizeoutput
+ \else
+ % don't combine these
+ \vskip\lineheight
+ \vskip-\lineheight % take footnotes into account
+ \fi
+ \dontshowcomposition
+ \doflushcolumnfloat % added recently
+ %\doflushcolumnfloats % no, since it results in wrong top floats
+ \flushnotes % before start of columns
+ \par
+ \ifbalancecolumns
+ \ifnum\multicolumnendsyncmethod=\plusone
+ \global\output{\continuousmulticolumnsout}%
+ \goodbreak
+ \fi
+ \global\output{\balancedmulticolumnsout}%
+ \else
+ \goodbreak
+ \fi
+ \eject % the prevdepth is important, try e.g. toclist in
+ \prevdepth\zeropoint % columns before some noncolumned text text
+ \global\output\singlecolumnout
+ \global\output{\the\mainoutput}% % % % % todo
+ \ifvoid\precolumnbox\else
+ \unvbox\precolumnbox
+ \fi
+ \global\precolumnboxheight\zeropoint
+ \endgroup % here
+ \nofcolumns\plusone
+ \setvsize % the outer one!
+ \synchronizeoutput % new may 2004 / we need to: \pagegoal\vsize
+ \checkendcolumnfootnotes
+ \dosomebreak\allowbreak
+ \dopopcolumnfloats}
+
+%D Because some initializations happen three times, we
+%D defined a macro for them. Erasing \type{\everypar} is
+%D needed because we don't want anything to interfere.
+
+\def\setmulticolumnsout
+ {\everypar\emptytoks
+ \dontcomplain
+ \settopskip
+ \setmaxdepth
+ \topskip1\topskip
+ \splittopskip\topskip
+ \splitmaxdepth\maxdepth
+ \boxmaxdepth\maxdepth % dangerous
+ \emergencystretch\zeropoint\relax} % sometimes needed !
+
+%D Flushing the page comes to pasting the columns together and
+%D appending the result to box \type{\precolumnbox}, if not
+%D void. I've seen a lot of implementations in which some skip
+%D was put between normal text and multi||column text. When we
+%D don't want this, the baselines can be messed up. I hope the
+%D seemingly complicated calculation of a correction
+%D \type{\kern} is adequate to overcome this. Although not
+%D watertight, spacing is taken into account and even multiple
+%D mode changes on one page go well. But cross your fingers and
+%D don't blame me.
+%D
+%D One of the complications of flushing out the boxes is that
+%D \type{\precolumnbox} needs to be \type{\unvbox}'ed, otherwise
+%D there is too less flexibility in the page when using
+%D \type{\r@ggedbottom}. It took a lot of time before these
+%D kind of problems were overcome. Using \type{\unvbox} at the
+%D wrong moment can generate \type{\balancingerror}'s.
+%D
+%D One can use the macros \type {\maxcolumnheight} and \type
+%D {\maxcolumndepth} when generating material between columns
+%D as well as postprocessing column lines.
+
+\let\maxcolumnheight=\zeropoint
+\let\maxcolumndepth =\zeropoint
+
+\newbox\columnpagebox
+
+\def\setmaxcolumndimensions
+ {\let\maxcolumnheight\!!zeropoint
+ \let\maxcolumndepth \!!zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\maxcolumnheight
+ \edef\maxcolumnheight{\the\ht\currentcolumnbox}%
+ \fi
+ \ifdim\dp\currentcolumnbox>\maxcolumndepth
+ \edef\maxcolumndepth{\the\dp\currentcolumnbox}%
+ \fi}}
+
+\chardef\multicolumntopflushmethod\plusone % 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++
+\chardef\multicolumntopalignmethod\plustwo % 0: nothing, 1: force grid, 2: follow grid
+
+\def\flushprecolumnboxnogrid
+ {\unvbox\precolumnbox}
+
+\def\flushprecolumnboxongrid
+ {\scratchdimen\savedpagetotal
+ \advance\scratchdimen -\ht\precolumnbox
+ \advance\scratchdimen -\dp\precolumnbox
+ \advance\scratchdimen -\topskip
+ \box\precolumnbox
+ \kern\scratchdimen}
+
+\newconditional\someprecolumncontent
+
+\def\flushcolumnedpage#1%
+ {\bgroup
+ \ifvoid\precolumnbox
+ \setfalse\someprecolumncontent % will be set elsewhere
+ \else
+ \settrue\someprecolumncontent
+ \mkprocessboxcontents\precolumnbox
+ \fi
+ \forgetall
+ \setmulticolumnsout
+ \showcomposition
+ \setmaxcolumndimensions
+ \dohandleallcolumns
+ {\mkprocesscolumncontents\currentcolumnbox}%
+ \postprocesscolumns
+ \dohandleallcolumns % \hbox i.v.m. \showcomposition
+ {\global\setbox\currentcolumnbox\hbox to \localcolumnwidth
+ {\box\currentcolumnbox
+ \global\wd\currentcolumnbox\localcolumnwidth
+ \ifheightencolumns
+ \global\ht\currentcolumnbox\fixedcolumnheight
+ \fi}}%
+ \setmaxcolumndimensions
+ \overlaycolumnfootnotes
+ \setbox\columnpagebox\vbox
+ {\hbox to \finalcolumntextwidth
+ {\hskip\colleftskip\relax % new, \relax needed
+ \ifreversecolumns
+ \@EA\dohandlerevcolumns
+ \else
+ \@EA\dohandleallcolumns
+ \fi
+ {\finishcolumnbox{\hbox
+ {\ifx\finishcolumnbox\relax\else\strut\fi
+ \box\currentcolumnbox}}%
+ \hfil}%
+ \unskip
+ \hskip\colrightskip}}% new
+ \scratchdimen\zeropoint
+ \dohandleallcolumns
+ {\ifdim-\ht\currenttopcolumnbox<\scratchdimen
+ \scratchdimen-\ht\currenttopcolumnbox
+ \fi
+ \global\setbox\currenttopcolumnbox\emptybox}%
+ \advance\scratchdimen \ht\columnpagebox
+ \setbox\scratchbox\hbox to \columntextwidth
+ {\vrule
+ \!!width\zeropoint
+ \!!height\scratchdimen
+ \!!depth\dp\columnpagebox
+ \dostepwiserecurse2\nofcolumns1{\hfil\betweencolumns}\hfil}%
+ \setbox\columnpagebox\hbox
+ {\box\columnpagebox
+ \hskip-\columntextwidth
+ \box\scratchbox}%
+ \postprocesscolumnpagebox % new, acts upon \box\columnpagebox
+ \ifconditional\someprecolumncontent
+ \settrue\someprecolumncontent
+ % next some incredible crappy code
+ \ifcase\multicolumntopalignmethod
+ \flushprecolumnboxnogrid % not on grid
+ \or
+ \flushprecolumnboxongrid % force on grid
+ \else\ifgridsnapping % somehow this junk fails in pascal
+ \flushprecolumnboxongrid % obey grid settings, force on grid
+ \else
+ \flushprecolumnboxnogrid % ignore grid settings, not on grid
+ \fi \fi
+ \fi
+ \global\precolumnboxheight\zeropoint
+ \setvsize
+ \dosomebreak\nobreak % hm, only needed when topstuff
+ \ifgridsnapping
+ \else
+ \ifcase\multicolumntopflushmethod
+ % sometimes method 1 goes wrong, so we need a way out; best sort this out
+ % when we run into it again
+ \or
+ % \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
+ \ifconditional\someprecolumncontent
+% \scratchdimen\topskip
+% \advance\scratchdimen -\openstrutheight
+% \nointerlineskip
+% \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \fi
+ \or
+% \scratchdimen\topskip
+% \advance\scratchdimen -\openstrutheight
+% \nointerlineskip
+% \vskip-\scratchdimen
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip\relax
+ \or
+ % untested but maybe handy
+% \scratchdimen\topskip
+% \advance\scratchdimen -\openstrutheight
+% \nointerlineskip
+% \vskip-\scratchdimen
+% \vskip-\lineheight
+% \vbox{\strut}%
+ \nointerlineskip
+ \vskip\dimexpr\openstrutheight-\topskip-\lineheight\relax
+ \vbox{\strut}%
+ \fi
+ \fi
+ \prevdepth\openstrutdepth
+ \nointerlineskip
+ \dp\columnpagebox\zeropoint
+ \global\finalcolumnheights\ht\columnpagebox
+ \getnoflines\finalcolumnheights
+ \global\finalcolumnlines\noflines
+ \ifcase#1\else
+ % messy correction, we need to rewrite this module (newcolumns)
+ \setbox\columnpagebox\vbox
+ {\offinterlineskip
+ \scratchdimen\ht\columnpagebox
+ \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
+ \box\columnpagebox
+ \vskip-\scratchdimen}%
+ \scratchdimen\noflines\openlineheight
+ \advance\scratchdimen-\openstrutdepth
+ \advance\scratchdimen-\openlineheight
+ \advance\scratchdimen\topskip
+ \ht\columnpagebox\scratchdimen
+ \dp\columnpagebox\openstrutdepth
+ % end of mess
+ \fi
+ \box\columnpagebox
+ \egroup}
+
+%D In case one didn't notice, finaly \type{\finishcolumnbox} is
+%D applied to all boxes. One can use these hooks for special
+%D purposes.
+%D
+%D Once upon a time I wanted to manipulate the individual lines
+%D in a column. This feature is demonstrated in the two examples
+%D below.
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1% or \postprocesscolumnbox
+%D {\ruledhbox{\box#1}\hss}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line: \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we show the natural width of the lines:
+%D
+%D {\getbuffer}
+%D
+%D The next example does a bit more advanced manipulation:
+%D
+%D \startbuffer
+%D \def\postprocesscolumnline#1%
+%D {\ifodd\currentcolumn
+%D \hfill\unhbox#1\relax
+%D \else
+%D \relax\unhbox#1\hfill
+%D \fi}
+%D
+%D \startcolumns[n=4]
+%D \dorecurse{25}{line \recurselevel\par}
+%D \stopcolumns
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Here we also see an application of \type{\currentcolumn}:
+%D
+%D {\getbuffer}
+%D
+%D This feature is implemented using the reshape macros
+%D presented in \type{supp-box}.
+
+\def\postprocesscolumns
+ {\ifx\postprocesscolumnline\undefined \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vtop
+ {\beginofshapebox
+ \unvbox\currentcolumnbox
+ \unskip\unskip
+ \endofshapebox
+ \reshapebox
+ {\dimen0\ht\shapebox
+ \dimen2\dp\shapebox
+ \setbox\shapebox\hbox to \hsize
+ {\postprocesscolumnline\shapebox}%
+ \ht\shapebox\dimen0
+ \dp\shapebox\dimen2
+ \box\shapebox}%
+ \flushshapebox
+ \everypar\emptytoks
+ \parskip\zeropoint % = \forgetall
+ \verticalstrut
+ \vskip-\struttotal
+ \vfil}}%
+ \fi
+ \ifx\postprocesscolumnbox\undefined \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\hbox
+ {\postprocesscolumnbox\currentcolumnbox}}
+ \fi}
+
+%D We default to doing nothing!
+
+\let\postprocesscolumnline =\undefined
+\let\postprocesscolumnbox =\undefined
+\let\postprocesscolumnpagebox=\relax
+
+%D \macros
+%D {reversecolumnstrue}
+%D
+%D We can force the macro that takes care of combining
+%D the columns, to flush them in the revere order. Of
+%D course, by default we don't reverse.
+
+\newif\ifreversecolumns
+
+%D Here comes the simple splitting routine. It's a bit
+%D longer than expected because of ragging bottoms or not.
+%D This part can be a bit shorter but I suppose that I will
+%D forget what happens. The splitting takes some already
+%D present material (think of floats) into account!
+%D
+%D First we present some auxiliary routines. Any material,
+%D like for instance floats, that is already present in the
+%D boxes is preserved.
+
+\def\splitcolumn#1from \box#2to \dimen#3 top \box#4%
+ {\bgroup
+ \ifdim\ht#4>\zeropoint
+ \dimen0\dimen#3\relax
+ \dimen2\dimen0
+ \advance\dimen0 -\ht#4%
+ \columnfootnotecorrection{#1}{\dimen0}%
+ \setbox0\vsplit#2 to \dimen0
+ \global\setbox#1\vbox to \dimen2
+ {\ifgridsnapping
+ \dimen0-\openstrutheight
+ \advance\dimen0 \topskip
+ \vskip\dimen0\copy#4\vskip-\dimen0
+ \else
+ \unvcopy#4%
+ \fi
+ \fuzzysnappedbox\unvbox0
+ \fakecolumnfootnotes{#1}}%
+ \else
+ \ifcase\clevernotes
+ \global\setbox#1\vsplit#2 to \dimen#3%
+ \global\setbox#1\vbox
+ {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
+ \else
+ \columnfootnotecorrection{#1}{\dimen#3}%
+ \setbox0\vsplit#2 to \dimen#3%
+ \global\setbox#1\vbox to \dimen#3%
+ {\fuzzysnappedbox\unvbox0
+ \fakecolumnfootnotes{#1}}%
+ \fi
+ \fi
+ \egroup}
+
+\def\splitcurrentcolumn from \box#1to \dimen#2%
+ {\splitcolumn\currentcolumnbox from \box#1 to \dimen#2 top \box\currenttopcolumnbox}
+
+\def\splitfirstcolumn from \box#1to \dimen#2%
+ {\splitcolumn\firstcolumnbox from \box#1 to \dimen#2 top \box\firsttopcolumnbox}
+
+\def\splitlastcolumn from \box#1to \dimen#2%
+ {\global\setbox\lastcolumnbox\vbox
+ {\unvcopy\lasttopcolumnbox
+ \fuzzysnappedbox\unvbox{#1}%
+ \fakecolumnfootnotes\lastcolumnbox}}
+
+%D NEW: still to be documented.
+
+\def\fakecolumnfootnotes#1%
+ {\relax
+ \ifcase\clevernotes\else
+ \ifnum#1=\lastcolumnbox
+ \fakenotes
+ \fi
+ \fi}
+
+\def\columnfootnotecorrection#1#2%
+ {\relax
+ \ifcase\clevernotes
+ % page notes
+ \or
+ \ifnum#1=\firstcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \else
+ \ifnum#1=\lastcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \fi}
+
+\def\overlaycolumnfootnotes
+ {\relax
+ \ifcase\clevernotes
+ % page notes
+ \else
+ \checknotepresence
+ \ifnotespresent
+ % the note box has the depth of the notefont
+ % because a column (i.e. first column has no depth,
+ % we need to anchor top down)
+ \bgroup
+ \ifcase\clevernotes\or
+ \getmulticolumnlines
+ \advance\nofcolumnlines \minustwo
+ \scratchdimen\nofcolumnlines\lineheight
+ \advance\scratchdimen \topskip
+ \setbox0\hbox
+ {\lower\scratchdimen\vbox{\placenoteinserts}}%
+ \ht0=\openstrutheight % \strutht
+ \dp0=\openstrutdepth % \strutdp
+ \wd0=\zeropoint
+ \scratchdimen\ht\firstcolumnbox
+ \global\setbox\firstcolumnbox\vbox to \scratchdimen
+ {\box\firstcolumnbox
+ \vskip-\scratchdimen
+ \box0}%
+ \else
+ % maybe here also \getmulticolumnlines
+ \scratchdimen\ht\firstcolumnbox
+ \advance\scratchdimen -\openstrutdepth % \strutdp
+ \getnoflines\scratchdimen
+ \advance\noflines \minustwo
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen \topskip
+ \setbox0\hbox
+ {\lower\scratchdimen\vbox{\placenoteinserts}}%
+ \ht0=\openstrutheight % \strutht
+ \dp0=\openstrutdepth % \strutdp
+ \wd0=\zeropoint
+ \scratchdimen\ht\lastcolumnbox
+ \global\setbox\lastcolumnbox\vbox to \scratchdimen
+ {\box\lastcolumnbox
+ \vskip-\scratchdimen
+ \box0}%
+ \fi
+ \egroup
+ \fi
+ \fi}
+
+%D Here comes the routine that splits the long box in columns.
+%D The macro \type{\flushcolumnfloats} can be used to flush
+%D either floats that were present before the multi||column
+%D mode was entered, or floats that migrate to next columns.
+%D Flushing floats is a delicate process.
+
+\def\continuousmulticolumnsout
+ {\bgroup
+ \forgetall
+ \setmulticolumnsout
+ \dontshowcomposition
+% \dimen0=\columntextheight
+% \advance\dimen0 -\precolumnboxheight
+% \settotalinsertionheight
+% \advance\dimen0 -\totalinsertionheight
+% \ifgridsnapping % evt altijd, nog testen
+% \getnoflines{\dimen0}
+% \dimen0=\noflines\openlineheight
+% \fi
+ \getmulticolumnlines
+ \dimen0=\nofcolumnlines\openlineheight
+ \dohandleallcolumns
+ {\splitcurrentcolumn from \box\normalpagebox to \dimen0}%
+ \setbox\restofpage\vbox{\unvbox\normalpagebox}%
+ \ifinheritcolumns
+ \ifr@ggedbottom % vreemd
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\dimen0\dp\currentcolumnbox
+ \unvbox\currentcolumnbox
+ \vskip-\dimen0
+ \vskip\openstrutdepth % \strutdp
+ \prevdepth\openstrutdepth % \strutdp
+ \vfill}}%
+ \ifbottomnotes \else
+ \dimen0\ht\firstcolumnbox
+ \fi
+ \fi
+ \ifn@rmalbottom
+ \advance\dimen0 \maxdepth
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\unvbox\currentcolumnbox}}%
+ \fi
+ \ifb@selinebottom
+ % the columns are on top of the baseline
+ \fi
+ \else
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \unvbox\currentcolumnbox % wel of niet \unvbox ?
+ \vfill
+ \fi}}%
+ \dohandleallcolumns
+ {\global\ht\currentcolumnbox\dimen0}%
+ \fi
+ \setbox\precolumnbox\vbox{\flushcolumnedpage\zerocount}%
+ \finaloutput\box\precolumnbox
+ \sethsize
+ \setvsize
+ \flushcolumnfloats
+ \unvbox\restofpage
+ % \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
+ \egroup}
+
+%D And this is the balancing stuff. Again, part of the routine
+%D is dedicated to handling ragged bottoms, but here we also
+%D see some handling concerning the stretching of columns.
+%D We set \type{\widowpenalty} at~0, which enables us to
+%D balance columns with few lines. The use of \type{\box2} and
+%D \type{\box4} garantees a more robust check when skips are
+%D used.
+
+\def\multicolumnsbalancemax{250} % 100 is too small when floats are involved
+
+\def\balancedmulticolumnsout
+ {\bgroup
+ \setmulticolumnsout
+ \dontshowcomposition
+ \widowpenalty\zerocount
+ \setbox0\vbox{\unvbox\normalpagebox}%
+\ifdim\ht0>\openlineheight % at least one line
+ \ifnum\minbalancetoplines<2 % balance anyway
+ \donetrue
+ \else % check criterium to available lines
+ \getnoflines{\ht0}%
+ \divide\noflines \nofcolumns \relax
+ \ifnum\noflines<\minbalancetoplines \relax
+ \dimen0\ht0
+ \advance\dimen0 \ht\firsttopcolumnbox
+ \advance\dimen0 \openlineheight \relax % let's play safe
+ \ifdim\dimen0>\columntextheight % column exceeding text height
+ \donetrue
+ \else % it seems to fit
+ \donefalse
+ \fi
+ \else % balance indeed
+ \donetrue
+ \fi
+ \fi
+\else % balancing does not make sense
+ \donefalse
+\fi
+\ifdone % start balancing
+ %\ifdim\ht0>\openlineheight
+ \dimen0\ht0
+ \advance\dimen0 \topskip
+ \advance\dimen0 -\baselineskip
+ \dohandleallcolumns
+ {\advance\dimen0 \ht\currenttopcolumnbox}%
+ \divide\dimen0 \nofcolumns
+ \vbadness\!!tenthousand\relax
+ \count255=\zerocount
+ \bgroup
+ \ifgridsnapping
+ \dimen2\lineheight
+ \else
+ \dimen2=\onepoint % RUBISH
+ \dimen2=\spacingfactor\dimen2
+ \fi
+ \doloop
+ {\advance\count255 \plusone
+ \global\setbox\restofpage\copy0\relax
+ \splitfirstcolumn from \box\restofpage to \dimen0
+ \dohandlemidcolumns
+ {\splitcurrentcolumn from \box\restofpage to \dimen0}%
+ \splitlastcolumn from \box\restofpage to \dimen0
+ \setbox2\vbox{\unvcopy\firstcolumnbox}%
+ \dimen4\zeropoint
+ \dohandleallcolumns
+ {\setbox4\vbox
+ {\unvcopy\currentcolumnbox
+ %rather new, test this on pdftex-z.tex
+ \unpenalty\unskip\unpenalty\unskip}% maybe better in main splitter
+ %\writestatus{balance}{\the\currentcolumnbox: \the\ht4}%
+% \dimen6\ht4 \ifdim\dimen6>\dimen4 \dimen4=\dimen6 \fi}%
+ \ifdim\ht4>\dimen4 \dimen4=\ht4 \fi}%
+ \advance\dimen4 -.0005pt % get rid of accurracy problem, pretty new
+ \ifnum\count255>\multicolumnsbalancemax\relax
+ \exitloop
+ \else\ifdim\dimen4>\ht2
+ \advance\dimen0 \dimen2\relax
+ \else
+ \exitloop
+ \fi\fi}%
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}% NIEUW
+ \ifnum\count255>\multicolumnsbalancemax\relax
+ \showmessage\m!columns7\empty
+ \else
+ \showmessage\m!columns8{\the\count255\space}%
+ \fi
+ \egroup
+ \ifinheritcolumns
+ % We cannot assume that the first column is the tallest, if
+ % only because we may have an aborted balance (one line in the
+ % first column and a graphic in the second one).
+ %
+ % \dimen0\ht\firstcolumnbox
+ % \dimen2\ht\firstcolumnbox
+ %
+ \dimen0=\zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\dimen0
+ \dimen0=\ht\currentcolumnbox
+ \fi}%
+ \dimen2\dimen0
+ % so far
+ \advance\dimen2 -\openlineheight
+ \dohandleallcolumns
+ {\dimen4\ht\currentcolumnbox
+ \dimen6=10\openlineheight % funny value
+ \global\setbox\currentcolumnbox\vbox to \dimen0
+ {\unvbox\currentcolumnbox
+ \ifdim\dimen4>\dimen6
+ \ifdim\dimen4<\dimen0
+ \ifdim\dimen4>\dimen2
+ \vskip\zeropoint % !!
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi
+ \else
+ \vskip\zeropoint
+ \fi
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi}}%
+ \else
+ \bgroup
+ \ifstretchcolumns
+ \dimen0\ht\firstcolumnbox
+ \dimen2=\bottomtolerance\ht\firstcolumnbox
+ \setbox0\vbox{\unvcopy\lastcolumnbox}%
+ \advance\dimen0 -\ht0\relax
+ \advance\dimen0 -\dp0\relax
+ \ifdim\dimen0>\openlineheight\relax
+ \ifdim\dimen0>\dimen2\relax
+ % \stretchcolumnsfalse % beter goed slecht dan slecht goed
+ \showmessage\m!columns9\empty
+ \fi
+ \fi
+ \fi
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \box\currentcolumnbox
+ \vfill
+ \fi}}%
+ \egroup
+ \fi
+ \else
+ % a one liner is not properly handled here, so best rewrite the text then
+ \showmessage\m!columns{10}\empty
+ \global\setbox\firstcolumnbox\vbox{\unvbox0}%
+ \fi
+ \global\output{\balancingerror}%
+ \b@selinebottomtrue % forces depth in separation rule
+ \flushcolumnedpage\plusone
+ \multicolumnseject
+ \egroup}
+
+\def\multicolumnseject
+ {\ifdim\pagetotal>\textheight
+ \eject % new
+ \else
+ \allowbreak
+ \fi}
+
+%D The multicolumn mechanism is incorporated in a \CONTEXT\
+%D interface, which acts like:
+%D
+%D \starttyping
+%D \startcolumns[n=4,balance=no]
+%D some text
+%D \stopcolumns
+%D \stoptyping
+%D
+%D The setup is optional. The default behaviour of columns
+%D can be set up with:
+%D
+%D \starttyping
+%D \setupcolumns
+%D [n=2,
+%D balance=yes]
+%D \stoptyping
+%D
+%D In this case, stretching is according to the way it's
+%D done outside columns (\type{\inheritcolumnstrue}). Also
+%D we can setup the \type{tolerance} within a column, the
+%D \type{distance} between columns and the fixed
+%D \type{height} of a column.
+
+%D Multi||column output: the float routines
+%D
+%D Here come the routines that handle the placement of column
+%D floats. Floats that are to big migrate to the next
+%D column. Floats that are too wide, migrate to the top of the
+%D next page, where they span as much columns as needed.
+%D Floats that are left over from outside the multi||column
+%D mode are flushed first. In macro \type{\finaloutput} the
+%D topfloats that are left from previous text should be set.
+%D
+%D When there are some floats in the queue, we inhibit the
+%D flushing of floats on top of columns. The number of
+%D waiting floats is preswent in \type{\savednoftopfloats} and
+%D is saved. As long as there are floats waiting, the topfloats
+%D are places as if we are outside multi||column mode. This is
+%D neccessary for e.g. multicolumn lists.
+%D
+%D When all those floats are flushed, we switch to the local
+%D flushing routine.
+
+\def\dopushcolumnfloats
+ {\ifsomefloatwaiting
+ \showmessage\m!columns6{\the\savednoffloats}%
+ \global\setbox\savedfloatlist\box\floatlist
+ \xdef\dopopcolumnfloats
+ {\global\savednoffloats\the\savednoffloats
+ \global\setbox\floatlist\box\savedfloatlist
+ \global\noexpand\somefloatwaitingtrue}%
+ \global\savednoffloats\zerocount
+ \global\somefloatwaitingfalse
+ \else
+ \global\let\dopopcolumnfloats\relax
+ \fi}
+
+\let\dopopcolumnfloats\relax
+
+% \def\setcolumnfloats % messy as it adapts everypar
+% {\xdef\globalsavednoffloats{\the\savednoffloats}%
+% \ifnum\globalsavednoffloats>\zerocount
+% \setglobalcolumnfloats % hm, we always push so this never happens
+% \else
+% \setlocalcolumnfloats
+% \fi}
+
+\def\setcolumnfloats % messy as it adapts everypar, we need to adapt this
+ {\setlocalcolumnfloats}
+
+\newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
+
+\def\OTRMULdocheckiffloatfits{\ifconditional\onlylocalcolumnfloats\docolumnroomfloat \else\relax \fi}
+\def\OTRMULdosetbothinserts {\ifconditional\onlylocalcolumnfloats\relax \else\OTRONEdosetbothinserts\fi}
+\def\OTRMULdotopinsertions {\ifconditional\onlylocalcolumnfloats\relax \else\OTRONEdotopinsertions \fi}
+\def\OTRMULdoflushfloats {\ifconditional\onlylocalcolumnfloats\doflushcolumnfloats\else\OTRONEdoflushfloats \fi}
+
+\def\setlocalcolumnfloats
+ {\settrue\onlylocalcolumnfloats
+ \everypar{\flushnotes\flushcolumnfloat\flushmargincontents\checkindentation}%
+ \let\flushcolumnfloat\doflushcolumnfloat
+ \let\flushcolumnfloats\doflushcolumnfloats}
+
+\def\setglobalcolumnfloats
+ {\setfalse\onlylocalcolumnfloats
+ \everypar\emptytoks
+ \let\flushcolumnfloat\relax
+ \let\flushcolumnfloats\noflushcolumnfloats}
+
+\def\noflushcolumnfloats
+ {\bgroup
+ \xdef\localsavednoffloats{\the\savednoffloats}%
+ \global\savednoffloats\globalsavednoffloats
+ \dotopinsertions
+ \xdef\globalsavenoffloats{\the\savednoffloats}%
+ \ifnum\globalsavednoffloats=\zerocount
+ \setlocalcolumnfloats
+ \fi
+ \global\savednoffloats\localsavednoffloats
+ \egroup}
+
+%D We need to calculate the amount of free space in a columns.
+%D When there is not enough room, we migrate the float to the
+%D next column. These macro's are alternatives (and
+%D look||alikes) of \type{\doroomfloat}. When a float is to
+%D wide, for one column, it is moved to the top of the next
+%D page. Of course such moved floats have to be taken into
+%D account when we calculate the available space. It's a pitty
+%D that such things are no integral part of \TEX.
+
+\def\getcolumnstatus\column#1\total#2\goal#3\\%
+ {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
+ \dimen2=\zeropoint
+ \count255=\zerocount
+ \dimen8=\columntextheight
+ \advance\dimen8 -\precolumnboxheight
+ \def\dogetcolumnstatus
+ {\advance\count255 \plusone
+ \advance\dimen2 \ht\currenttopcolumnbox
+ \advance\dimen2 \dp\currenttopcolumnbox
+ \dimen4\dimen2
+ \advance\dimen4 \dimen0
+ \dimen6=\count255\dimen8
+ \ifdim\dimen4>\dimen6
+ \else
+ \let\dogetcolumnstatus\relax
+ \fi}%
+ \dohandleallcolumns{\dogetcolumnstatus}%
+ \ifnum\count255=0 \count255=1 \fi
+ #1=\count255
+ #2=\dimen4
+ #3=\dimen6 }
+
+\def\getinsertionheight
+ {\ifdim\pagegoal<\maxdimen
+ \bgroup
+ \dimen0=\columntextheight
+ \advance\dimen0 -\pagegoal
+ \xdef\insertionheight{\the\dimen0}%
+ \egroup
+ \else
+ \global\let\insertionheight\zeropoint
+ \fi}
+
+\def\docolumnroomfloat
+ {\ifpostponecolumnfloats
+ \global\roomforfloatfalse
+ \else\ifnofloatpermitted
+ \global\roomforfloatfalse
+ \else
+ \bgroup
+ \getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\%
+ \dofloatsgetinfo{text}%
+ \setbox\scratchbox\vbox % tricky met objecten ?
+ {\blank[\@@bkspacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}% copy?
+ \advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
+ \ifdim\dimen0>\dimen2
+ \global\roomforfloatfalse
+ \else
+ \global\roomforfloattrue
+ \fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\roomforfloatfalse
+ \fi
+ \egroup
+ \fi\fi}
+
+%D Flushing one float is done as soon as possible, i.e.
+%D \type{\everypar}. This means that (at the moment)
+%D sidefloats are not supported (overulled)!
+
+\newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
+
+\def\doflushcolumnfloat
+ {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifprocessingverbatim\else\ifsomefloatwaiting
+ \bgroup
+ \forgetall
+ \let\doflushcolumnfloat\relax
+ \getcolumnstatus\column\mofcolumns\total\dimen0\goal\dimen2\\%
+ \ifdim\dimen0>\zeropoint
+ \dofloatsgetinfo{text}%
+ \ifdim\floatwidth>\hsize
+ % dropped ?
+ \else
+ \setbox2\vbox
+ {\blank[\@@bkspacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}%
+ \advance\dimen0 \ht2
+ \ifdim\dimen0>\dimen2
+ \ifnum\mofcolumns<\nofcolumns
+ \advance\mofcolumns \plusone
+ \ifdim\ht\currenttopcolumnbox=\zeropoint
+ \dofloatsflush{text}{1}%
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox{\box\floatbox}
+ \whitespace % nodig ?
+ \blank[\@@bkspaceafter]}%
+ \dimen4=\htdp\currenttopcolumnbox
+ \global\advance\vsize -\dimen4
+ \advance\dimen4 -\pagegoal
+ \global\pagegoal-\dimen4
+ \showmessage\m!columns{12}a%
+ \else
+ \showmessage\m!columns{12}b%
+ \fi
+ \else
+ \showmessage\m!columns{12}c%
+ \fi
+ \else
+ \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
+ \par
+ \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
+ \nobreak
+ \blank[\@@bkspacebefore]
+ \nobreak
+ \fi
+ \dofloatsflush{text}{1}%
+ \flushfloatbox
+ \blank[\@@bkspaceafter]
+ \fi
+ \fi
+ \fi
+ \egroup
+ \fi\fi\fi\fi}
+
+%D This one looks complicated. Upto \type{\nofcolumns} floats
+%D are placed, taking the width of a float into account. This
+%D routine can be improved on different ways:
+%D
+%D \startitemize[intro,packed]
+%D \item taking into account some imaginary baseline, just to
+%D get the captions in line
+%D \item multipass flushing until as many floats are displaced
+%D as possible
+%D \stopitemize
+%D
+%D When handling lots of (small) floats spacing can get worse
+%D because of lining out the columns.
+
+
+\def\doflushcolumnfloats
+ {\ifpostponecolumnfloats\else
+ \bgroup
+ \forgetall
+ \ifsomefloatwaiting
+ \dimen8\zeropoint
+ \dimen4\zeropoint
+ \count0\zerocount % count0 can be used local
+ \count2\nofcolumns % count2 can be used local
+ \dohandleallcolumns
+ {\ifnum\count0>\zerocount % the wide one's reserved space
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\copy\currenttopcolumnbox
+ \hbox{\vphantom{\vskip\floatheight}}}% known from previous
+ \whitespace % nodig ?
+ \blank[\@@bkspaceafter]}%
+ \else
+ \dofloatsgetinfo{text}%
+ \ifdim\floatwidth>\hsize
+ \dimen0\dimexpr\floatwidth+\intercolumnwidth+.5pt\relax
+ \dimen2\dimexpr\hsize +\intercolumnwidth+.5pt\relax
+ \divide\dimen0 \dimen2
+ \count0\dimen0
+ \advance\count0 \plusone
+ \ifnum\count0>\count2
+ \count0\zerocount
+ \else
+ \dimen0\dimexpr\count0\hsize+\count0\intercolumnwidth-\intercolumnwidth\relax
+ \dofloatsflush{text}{1}%
+ \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ \global\setbox\floatbox\hbox to \dimen0
+ {\processaction[\@@bklocation] % how easy to forget
+ [ \v!left=>\box\floatbox\hss,
+ \v!right=>\hss\box\floatbox,
+ \s!default=>\hss\box\floatbox\hss,
+ \s!unknown=>\hss\box\floatbox\hss]}%
+ \fi
+ \showmessage\m!columns{13}\empty
+ \else
+ \dofloatsflush{text}{1}%
+ \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ % \showmessage\m!columns{13}\empty
+ \fi
+ \ifdim\ht\floatbox>\zeropoint\relax
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\box\currenttopcolumnbox % was copy
+ \box\floatbox}
+ \whitespace % nodig ?
+ \blank[\@@bkspaceafter]}%
+ \fi
+ \dimen6\htdp\currenttopcolumnbox
+ \fi
+ \ifdim\dimen4<\ht\currenttopcolumnbox
+ \dimen4\ht\currenttopcolumnbox
+ \fi
+ \advance\dimen8 \dimen6
+ \advance\count2 \minusone
+ \advance\count0 \minusone }%
+ \setvsize
+ \global\advance\vsize -\dimen8
+ \global\pagegoal\vsize
+ \else
+ %\doflushfloats % does not snap!
+ \fi
+ \egroup
+ \fi}
+
+%D The next macro can be used to flush floats in the current
+%D stream. No width checking is (yet) done.
+
+\def\insertcolumnfloats
+ {\doloop
+ {\ifsomefloatwaiting
+ \bgroup
+ \forgetall
+ % no check for width
+ \dogetfloat
+ \blank[\@@bkspacebefore]
+ \snaptogrid\vbox{\copy\floatbox}
+ \blank[\@@bkspaceafter]
+ \egroup
+ \else
+ \exitloop
+ \fi}}
+
+%D This were the multi||column routines. They can and need to
+%D be improved but at the moment their behaviour is acceptable.
+%D
+%D One inprovement can be to normalize the height of floats
+%D to $n\times$\type{\lineheight} with a macro like:
+%D
+%D \starttyping
+%D \normalizevbox{...}
+%D \stoptyping
+
+% border case, should fit on one page
+%
+% \startcolumns
+%
+% 1 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{1}}
+% 2 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{2}}
+% 3 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{3}}
+%
+% \stopcolumns
+
+\unexpanded\def\setupcolumns
+ {\dosingleempty\dosetupcolumns}
+
+\def\dosetupcolumns[#1]%
+ {\getparameters[\??kl][#1]%
+ \nofcolumns\@@kln\relax
+ \processaction
+ [\@@klrule]
+ [ \v!on=>\let\betweencolumns\linebetweencolumns,
+ \v!off=>\let\betweencolumns\spacebetweencolumns,
+ \s!default=>\let\betweencolumns\spacebetweencolumns,
+ \s!unknown=>\let\betweencolumns\@@klrule]}
+
+\def\linebetweencolumns
+ {\bgroup
+ \starttextproperties
+ \ifdim\@@kldistance>\zeropoint
+ \dimen0=\@@kldistance
+ \else
+ \dimen0=\linewidth
+ \fi
+ \advance\dimen0 -\linewidth
+ \hskip.5\dimen0
+ \vrule
+ \!!width\linewidth
+ \ifb@selinebottom\!!depth\strutdepth\fi
+ \hskip.5\dimen0\relax
+ \stoptextproperties
+ \egroup}
+
+\def\spacebetweencolumns
+ {\hskip\@@kldistance}
+
+\presetlocalframed[\??kl]
+
+\def\backgroundfinishcolumnbox
+ {\doifinsetelse\@@kloffset{\v!none,\v!overlay}
+ {\let\@@kloffset\!!zeropoint}
+ {\scratchdimen\@@kloffset
+ \advance\scratchdimen -\@@klrulethickness
+ \edef\@@kloffset{\the\scratchdimen}}%
+ \localframed
+ [\??kl]
+ [\c!strut=\v!no,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!align=]}
+
+\definecomplexorsimpleempty\startcolumns
+
+\def\complexstartcolumns[#1]% %% \startcolumns
+ {\bgroup
+ \let\stopcolumns\egroup
+ \ifinsidecolumns
+ \else
+ \setupcolumns[#1]%
+ \ifnum\@@kln>1\relax
+ \whitespace
+ \begingroup
+ \doif\@@kloption\v!background
+ {\let\finishcolumnbox\backgroundfinishcolumnbox
+ \let\columntextoffset\@@kloffset}%
+ \ifx\@@klcommand\empty\else
+ \let\postprocesscolumnline\@@klcommand
+ \fi
+ \doifelsenothing\@@klheight
+ \heightencolumnsfalse
+ \heightencolumnstrue
+ \doifelse\@@kldirection\v!right
+ \reversecolumnsfalse
+ \reversecolumnstrue
+ \doifelse\@@klbalance\v!yes
+ \balancecolumnstrue
+ \balancecolumnsfalse
+ \installalign\v!yes {\stretchcolumnstrue \inheritcolumnsfalse}% todo: new key
+ \installalign\v!no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key
+ \installalign\v!text{\stretchcolumnsfalse\inheritcolumnstrue }%
+ \stretchcolumnsfalse
+ \inheritcolumnstrue
+ \doifsomething\@@klalign{\expanded{\setupalign[\@@klalign]}}%
+ \nofcolumns=\@@kln
+ %
+ % probably more is needed, and how about nesting save's
+ %
+ \saveouterspacing
+ %
+ \edef\fixedcolumnheight{\@@klheight}%
+ \edef\minbalancetoplines{\@@klntop}%
+ \setuptolerance[\@@kltolerance]% %% \startcolumns
+ \setupblank[\@@klblank]%
+ \ifdim\ctxparskip>\zeropoint\relax
+ \setupwhitespace[\@@klblank]%
+ \fi
+ \unexpanded\def\stopcolumns
+ {\endmulticolumns
+ \global\insidecolumnsfalse
+ \endgroup
+ \egroup}%
+ \global\insidecolumnstrue
+ \beginmulticolumns
+ \fi
+ \fi}
+
+\installcolumnbreakhandler {MUL} \v!preference
+ {\goodbreak}
+
+\installcolumnbreakhandler {MUL} \v!yes
+ {\par % todo: since
+ {\testrulewidth\zeropoint\ruledvskip\textheight} % we misuse a
+ \penalty-200 % side effect
+ \vskip-\textheight
+ }% bugged : \prevdepth-\thousandpoint} % signals top of column to \blank
+
+%D New: only at start of columns; may change ! Rather
+%D interwoven and therefore to be integrated when the multi
+%D column modules are merged. (moved from cont-new.tex)
+
+\unexpanded\def\setupcolumnspan[#1]%
+ {\getparameters[\??ks][#1]}
+
+\presetlocalframed
+ [\??ks]
+
+\setupcolumnspan
+ [\c!n=2,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+\newbox\columnspanbox \let\postprocesscolumnspanbox\gobbleoneargument
+
+\def\dostartcolumnspan[#1]%
+ {\bgroup
+ \setupcolumnspan[#1]%
+ \forgetall
+ \ifinsidecolumns
+ \advance\hsize \intercolumnwidth
+ \hsize\@@ksn\hsize
+ \advance\hsize -\intercolumnwidth
+ \fi
+ \dowithnextbox
+ {\setbox\columnspanbox\flushnextbox
+ \ifinsidecolumns\wd\columnspanbox\hsize\fi
+ \postprocesscolumnspanbox\columnspanbox
+ \scratchdimen\ht\columnspanbox
+ \setbox\columnspanbox\hbox % depth to be checked, probably option!
+ {\localframed[\??ks][\c!offset=\v!overlay]{\box\columnspanbox}}%
+ \ht\columnspanbox\scratchdimen
+ \dp\columnspanbox\strutdp
+ \wd\columnspanbox\hsize
+ \ifinsidecolumns
+ \ifnum\@@ksn>1
+ \setvsize
+ \dohandleallcolumns
+ {\ifnum\currentcolumn>\@@ksn\else
+ \global\setbox\currenttopcolumnbox=\vbox
+ {\ifnum\currentcolumn=1
+ \snaptogrid\vbox{\copy\columnspanbox}
+ \else
+ \snaptogrid\vbox{\vphantom{\copy\columnspanbox}}
+ \fi}%
+ \wd\currenttopcolumnbox\hsize
+ \global\advance\vsize -\ht\currenttopcolumnbox
+ \fi}
+ \global\pagegoal\vsize
+ \else
+ \snaptogrid\vbox{\box\columnspanbox}
+ \fi
+ \else
+ \snaptogrid\vbox{\box\columnspanbox}
+ \fi
+ \endgraf
+ \ifvmode\prevdepth\strutdp\fi
+ \egroup}
+ \vbox\bgroup
+ %\topskipcorrection % becomes an option !
+ \EveryPar{\begstrut\EveryPar{}}} % also !
+
+\unexpanded\def\startcolumnspan
+ {\dosingleempty\dostartcolumnspan}
+
+\unexpanded\def\stopcolumnspan
+ {\egroup}
+
+\setupcolumns
+ [\c!n=2,
+ \c!ntop=1,
+ \c!command=,
+ \c!direction=\v!right,
+ \c!rule=\v!off,
+ \c!tolerance=\v!tolerant,
+ \c!distance=1.5\bodyfontsize, % influenced by switching
+ \c!height=,
+ \c!balance=\v!yes,
+ \c!align=\v!text,
+ \c!blank={\v!line,\v!fixed},
+ \c!option=,
+ \c!rulethickness=\linewidth,
+ \c!offset=.5\bodyfontsize]
+
+%D Undocumented and still under development.
+
+\unexpanded\def\startsimplecolumns
+ {\dosingleempty\dostartsimplecolumns}
+
+\def\dostartsimplecolumns[#1]%
+ {\bgroup
+ \nopenalties
+ \getparameters[\??kl]
+ [\c!width=\hsize,\c!distance=1.5\bodyfontsize,%
+ \c!n=2,\c!lines=0,#1]%
+ \let\rigidcolumnlines\@@kllines
+ \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln
+ \setbox\scratchbox\vbox\bgroup
+ \forgetall} % \blank[\v!disable]
+
+\unexpanded\def\stopsimplecolumns
+ {\removebottomthings
+ \egroup
+ \rigidcolumnbalance\scratchbox
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/page-not.mkii b/tex/context/base/page-not.mkii
new file mode 100644
index 000000000..9c67f18f1
--- /dev/null
+++ b/tex/context/base/page-not.mkii
@@ -0,0 +1,72 @@
+%D \module
+%D [ file=page-nnt,
+%D version=2002.04.16,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Footnotes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Footnotes}
+
+%D Terrible hacks: we need to share save/restore
+
+%D We've moved some footnote handling to a separate page
+%D module. The macros below are used in the single and multi
+%D column page handlers and permit mixed usage of column and
+%D page notes.
+
+\unprotect
+
+\def\checkbegincolumnfootnotes % should happen inside otr
+ {\ifcase\clevernotes
+ \erasenotebackup
+ \else
+ \doflushnotes
+ \savenotecontent
+ \fi
+ \savenotedata
+ \checknotes}
+
+\def\checkendcolumnfootnotes
+ {\restorenotedata % maybe better just \checknotes
+ \ifcase\clevernotes\else
+ \restorenotecontent
+ \fi}
+
+\def\checksinglecolumnfootnotes
+ {\checknotes} % njet : \restorenotedata
+
+\newdimen\totalinsertionheight
+
+\def\settotalinsertionheight
+ {\calculatetotalnoteheight
+ \totalinsertionheight\totalnoteheight
+ \addinsertionheight\topins\to\totalinsertionheight
+ \addinsertionheight\botins\to\totalinsertionheight}
+
+% hm
+
+\def\checkbegincolumnfootnotes % should happen inside otr
+ {\ifcase\clevernotes
+ \erasenotebackup
+ \else
+ \doflushnotes
+ \savenotecontent
+ \fi
+ \savenotedata
+ \checknotes}
+
+\def\checkendcolumnfootnotes
+ {\restorenotedata
+ \ifinsidecolumns
+ \ifcase\clevernotes\else
+ \restorenotecontent
+ \fi
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/page-not.mkiv b/tex/context/base/page-not.mkiv
new file mode 100644
index 000000000..95229f9d0
--- /dev/null
+++ b/tex/context/base/page-not.mkiv
@@ -0,0 +1,69 @@
+%D \module
+%D [ file=page-nnt,
+%D version=2002.04.16,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Footnotes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Footnotes}
+
+%D Terrible hacks: we need to share save/restore
+
+%D We've moved some footnote handling to a separate page
+%D module. The macros below are used in the single and multi
+%D column page handlers and permit mixed usage of column and
+%D page notes.
+
+\unprotect
+
+\def\checkbegincolumnfootnotes % should happen inside otr
+ {\ifcase\clevernotes
+ \erasenotebackup
+ \else
+ \flushnotes
+ \savenotecontent
+ \fi
+ \savenotedata}
+
+\def\checkendcolumnfootnotes
+ {\restorenotedata
+ \ifcase\clevernotes\else
+ \restorenotecontent
+ \fi}
+
+\let\checksinglecolumnfootnotes\relax
+
+\newdimen\totalinsertionheight
+
+\def\settotalinsertionheight
+ {\calculatetotalnoteheight
+ \totalinsertionheight\totalnoteheight
+ \addinsertionheight\topins\to\totalinsertionheight
+ \addinsertionheight\botins\to\totalinsertionheight}
+
+% hm
+
+\def\checkbegincolumnfootnotes % should happen inside otr
+ {\ifcase\clevernotes
+ \erasenotebackup
+ \else
+ \flushnotes
+ \savenotecontent
+ \fi
+ \savenotedata}
+
+\def\checkendcolumnfootnotes
+ {\restorenotedata
+ \ifinsidecolumns
+ \ifcase\clevernotes\else
+ \restorenotecontent
+ \fi
+ \fi}
+
+\protect \endinput
diff --git a/tex/context/base/page-one.mkii b/tex/context/base/page-one.mkii
new file mode 100644
index 000000000..1affc24d0
--- /dev/null
+++ b/tex/context/base/page-one.mkii
@@ -0,0 +1,659 @@
+%D \module
+%D [ file=page-one,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Default Routine,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Default Routine}
+
+%D This is just the good old \CONTEXT\ output routine, which
+%D has been there right from the start.
+
+\unprotect
+
+% OTRONE: basic single column
+
+\activateotr{ONE}{} % the default one
+
+\newtoks\OTRONEoutput
+
+\def\OTRONEgotonextpage
+ {\ejectpage}
+
+\def\OTRONEgotonextpageX % will become obsolete
+ {\superejectpage}
+
+\def\OTRONEsethsize
+ {\global\hsize\textwidth}
+
+% keep (original one)
+%
+% \def\OTRONEsetvsize
+% {\ifdim\vsize=\teksthoogte \else
+% \bgroup
+% \scratchdimen-\vsize
+% \advance\scratchdimen \teksthoogte
+% \global\advance\vsize \scratchdimen
+% \relax \ifdim\pagegoal<\maxdimen
+% \advance\scratchdimen \pagegoal
+% \global\pagegoal\scratchdimen
+% \fi
+% \egroup
+% \fi}
+%
+% no (keep)
+%
+% \def\OTRONEsetvsize
+% {\ifdim\vsize=\teksthoogte \else
+% \bgroup
+% \scratchdimen-\vsize
+% \advance\scratchdimen \teksthoogte
+% \ifgridsnapping
+% \getrawnoflines\scratchdimen
+% \scratchdimen\noflines\openlineheight
+% \ifdim\scratchdimen>\noflinesheight % available afterwards
+% \advance\scratchdimen-\openlineheight
+% \fi
+% \ifdim\scratchdimen<\zeropoint
+% \scratchdimen\zeropoint
+% \fi
+% \fi
+% \global\advance\vsize \scratchdimen
+% \relax \ifdim\pagegoal<\maxdimen
+% \advance\scratchdimen \pagegoal
+% \global\pagegoal\scratchdimen
+% \fi
+% \egroup
+% \fi}
+
+% \def\OTRONEsetvsize
+% {\ifgridsnapping
+% \ifcase\layoutlines
+% \getrawnoflines\teksthoogte
+% \else
+% \noflines\layoutlines
+% \fi
+% \global\vsize\noflines\openlineheight
+% \else
+% \global\vsize\teksthoogte
+% \fi
+% \ifdim\pagegoal<\maxdimen
+% \global\pagegoal\vsize
+% \fi}
+
+\newdimen\oldvsize
+
+\def\OTRONEsetvsize
+ {\ifgridsnapping
+ \ifcase\layoutlines
+ \getrawnoflines\textheight
+ \else
+ \noflines\layoutlines
+ \fi
+ \global\vsize\noflines\openlineheight
+ \else
+ \global\vsize\textheight
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\oldvsize=\vsize
+ % let's assume that the layout didn't change
+ \else
+ \bgroup
+ \global\oldvsize\vsize
+ \advance\vsize-\topinserted
+ \advance\vsize-\botinserted
+ \global\pagegoal\vsize
+ \egroup
+ \fi
+ \fi}
+
+\chardef\kindofpagetextareas=2 % whole page (public variable! never change)
+
+\def\OTRONEregisteredtextarea#1%
+ {\ifregistertextareas
+ \setbox0\vbox{#1}%
+ \wd0\makeupwidth % somehow a space creeps in
+ \vbox{\registeredtextarea000}%
+ \else
+ #1%
+ \fi}
+
+% \chardef\kindofpagetextareas\plusone
+
+\def\doOTRONEregisteredtextareaA#1%
+ {\ifregistertextareas
+ \xypos{pbd:\realfolio:b}% we could save bytes by only saving the y
+ \endgraf
+ \begingroup
+ \scratchdimen\MPy{pbd:\realfolio:b}%
+ \advance\scratchdimen-\MPy{pbd:\realfolio:e}%
+ \setbox\scratchbox\null
+ \wd\scratchbox\makeupwidth
+ \ht\scratchbox\scratchdimen
+ \vsmash{\registeredtextarea00\scratchbox}%
+ \endgroup
+ #1%
+ \endgraf
+ \xypos{pbd:\realfolio:e}%
+ \else
+ #1%
+ \fi}
+
+\def\doOTRONEregisteredtextareaB#1%
+ {\ifregistertextareas
+ \setbox0\vbox{#1}%
+ \wd0\makeupwidth % somehow a space creeps in
+ \vbox{\registeredtextarea000}%
+ \else
+ #1%
+ \fi}
+
+\let\OTRONEregisteredtextareaA\firstofoneargument
+\let\OTRONEregisteredtextareaB\firstofoneargument
+
+\def\OTRONEdopagecontents#1#2% \box \unvbox
+ {\bgroup % niet breedte zetten, kan fractie zijn!
+ \ifcase\kindofpagetextareas
+ \or % partial page (experimental)
+ \let\OTRONEregisteredtextareaA\doOTRONEregisteredtextareaA
+ \or % whole page (default)
+ \let\OTRONEregisteredtextareaB\doOTRONEregisteredtextareaB
+ \or % partial page (only works well with no stretch!)
+ \let\OTRONEregisteredtextareaA\doOTRONEregisteredtextareaB
+ \fi
+ \setbox0\vbox \ifbottomnotes to \textheight \fi
+ {\edef\currentpagedepth{\the\dp#2}% still to be derived from #1
+ \dotopinsertions
+ \ifgridsnapping
+ \OTRONEregisteredtextareaA{#1#2}%
+ \vskip-\currentpagedepth\vskip\openstrutdepth
+ \pushproperties % moved from just after #1#2
+ \prevdepth\openstrutdepth
+ \dobotinsertions
+ \vfil
+ \else\ifr@ggedbottom
+ \OTRONEregisteredtextareaA{#1#2}%
+ \vskip-\currentpagedepth\vskip\openstrutdepth
+ \pushproperties % moved from just after #1#2
+ \prevdepth\openstrutdepth
+ \dobotinsertions
+ \vfil
+ \else\ifb@selinebottom
+ \OTRONEregisteredtextareaA{#1#2}%
+ \kern-\currentpagedepth\kern\maxdepth
+ \pushproperties % moved from just after #1#2
+ \dobotinsertions
+ \else
+ \OTRONEregisteredtextareaA{#1#2}%
+ \pushproperties % moved from just after #1#2
+ \dobotinsertions % added
+ \fi\fi\fi
+ \fakepagenotes}% was \fakenotes, but wrong! (check with \setupalign[height])
+ \ifbottomnotes
+ \ifgridsnapping
+\ifcase\layoutlines % todo: make macro of this
+ \getrawnoflines\textheight
+\else
+ \noflines\layoutlines
+\fi
+% \getnoflines\textheight
+ \advance\noflines \minusone
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen \topskip
+ \else
+ \scratchdimen\ht0
+ \fi
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \setbox2\hbox
+ {\checksinglecolumnfootnotes
+ \lower\scratchdimen\vbox{\placebottomnotes}}%
+ \smashbox2% % needed here
+ \ifbottomnotes
+ \ht0\zeropoint
+ \fi
+ \OTRONEregisteredtextareaB
+ {\vbox to \textheight
+ {\box0\box2\ifbottomnotes\else\vfill\fi}}%
+ \egroup}
+
+\def\OTRONEfinalsidefloatoutput
+ {\finaloutput\unvbox\normalpagebox}
+
+\OTRONEoutput
+ {\sidefloatoutput}
+
+%D Insertions
+
+\newif\iftopofinsert
+
+% \def\OTRONEdosettopinserts
+% {\bgroup
+% \ifsomefloatwaiting
+% \noffloatinserts\zerocount
+% \let\totaltopinserted\!!zeropoint
+% \OTRONEdodosettopinserts
+% \ifnum\@@bknbottom=\zerocount
+% \ifnum\@@bknlines>\zerocount
+% \ifdim\totaltopinserted>\zeropoint\relax
+% \dimen0=\lineheight
+% \dimen0=\@@bknlines\dimen0
+% \advance\dimen0 \totaltopinserted\relax
+% \ifdim\dimen0>\textheight
+% \showmessage\m!floatblocks8\@@bknlines
+% \vfilll\eject
+% \fi
+% \fi
+% \fi
+% \fi
+% \fi
+% \egroup}
+
+\def\OTRONEdosettopinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \let\totaltopinserted\!!zeropoint
+ \OTRONEdodosettopinserts
+ \ifnum\@@bknbottom=\zerocount
+ \ifnum\@@bknlines>\zerocount
+ \ifdim\totaltopinserted>\zeropoint\relax
+ \ifdim\dimexpr\@@bknlines\lineheight+\totaltopinserted\relax>\textheight
+ \showmessage\m!floatblocks8\@@bknlines
+ \vfilll\eject
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRONEdodosettopinserts
+ {\ifnum\noffloatinserts<\noftopfloats
+ \dogetfloat
+ \ifdim\topinserted=\zeropoint
+ \topofinserttrue
+ \else
+ \topofinsertfalse
+ \fi
+ \global\advance\topinserted\dimexpr\ht\floatbox+\dp\floatbox+\floatbottomskip\relax
+ \ifdim\topinserted<\textheight\relax
+ \xdef\totaltopinserted{\the\topinserted}%
+ \insert\topins
+ {\forgetall
+ \iftopofinsert
+ \topskipcorrection % [xx] new: see icare topbleed
+ \kern-\lineskip\par
+ \prevdepth\maxdimen
+ \else
+ %\blank[-\@@bkspaceafter,\@@bkspacebefore]% inserts can't look back
+ \betweenfloatblanko
+ \fi
+ \flushfloatbox
+ \blank[\@@bkspaceafter]}%
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\noftopfloats\relax
+ \fi
+ \dofloatflushedinfo
+ \else
+ \doresavefloat
+ \noffloatinserts\noftopfloats\relax
+ \fi
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks6{\the\noftopfloats}%
+ \fi
+ \let\OTRONEdodosettopinserts\relax
+ \fi
+ \OTRONEdodosettopinserts}
+
+\def\OTRONEdosetbotinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \OTRONEdodosetbotinserts
+ \fi
+ \egroup}
+
+\def\OTRONEdodosetbotinserts
+ {\ifnum\noffloatinserts<\nofbotfloats\relax
+ \dogetfloat
+ \global\advance\botinserted \ht\floatbox\relax
+ \global\advance\botinserted \dp\floatbox\relax
+ \global\advance\botinserted \floattopskip\relax
+ \ifdim\botinserted<\pagegoal\relax
+ \insert\botins
+ {\forgetall
+ \blank[\@@bkspacebefore]%
+ \flushfloatbox}%
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\nofbotfloats
+ \fi
+ \dofloatflushedinfo
+ \else
+ \doresavefloat
+ \noffloatinserts\nofbotfloats\relax
+ \fi
+ \global\nofloatpermittedtrue % vgl topfloats s!
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks7{\the\nofbotfloats}%
+ \fi
+ \let\OTRONEdodosetbotinserts\relax
+ \fi
+ \OTRONEdodosetbotinserts}
+
+\def\OTRONEdosetbothinserts
+ {\global\topinserted\zeropoint
+ \global\botinserted\zeropoint
+ \ifflushingfloats \else
+ \OTRONEdosettopinserts
+ \OTRONEdosetbotinserts
+ \ifsomefloatwaiting
+ \doif\@@bkcache\v!no\doflushfloats
+ \fi
+ \fi}
+
+% \def\OTRONEdotopinsertions
+% {\ifvoid\topins\else
+% \ifgridsnapping
+% \box\topins
+% \vskip-\topskip \vskip\strutheight % [xx] new: see icare topbleed
+% \else
+% \unvbox\topins
+% \fi
+% \fi
+% \global\topinserted\zeropoint}
+
+\chardef\topinserttopskipmode=0 % 1 no topskip
+
+\def\OTRONEdotopinsertions
+ {\ifvoid\topins\else
+ \ifgridsnapping
+ \box\topins
+ \vskip-\topskip
+ \vskip\strutheight % [xx] new: see icare topbleed
+ \else
+ \ifcase\topinserttopskipmode
+ % 0: default, do nothing
+ \or
+ % 1: no topskip (crossed fingers)
+ \vskip-\topskip
+ \vskip\strutheight
+ \fi
+ \unvbox\topins
+ \fi
+ \fi
+ \global\topinserted\zeropoint}
+
+\def\OTRONEdobotinsertions
+ {\ifvoid\botins\else
+ \ifgridsnapping
+ \snaptogrid\hbox{\box\botins}%
+ \else
+ \unvbox\botins
+ \fi
+ \fi
+ \global\botinserted\zeropoint
+ \global\nofloatpermittedfalse}
+
+\def\OTRONEdoflushfloats
+ {\global\flushingfloatstrue
+ \ifsomefloatwaiting
+ \par
+ % if kept, then option and definitely off in gridmode ! ! ! !
+ % \ifvmode \prevdepth\maxdimen \fi % prevents whitespace; problematic in icare tests
+ \OTRONEdodoflushfloats
+ \fi
+ \global\savednoffloats\zerocount
+ \global\somefloatwaitingfalse
+ \global\flushingfloatsfalse}
+
+\def\OTRONEflushfloatbox % nog verder doorvoeren en meer info in marge
+ {\ifcenterfloatbox \ifdim\wd\floatbox<\hsize
+ \setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}%
+ \fi \fi
+ \snaptogrid\hbox{\iftestfloatbox\ruledhbox\fi{\copy\floatbox}}}
+
+\def\OTRONEdodoflushfloats % much in common with OTRSET
+ {\ifsomefloatwaiting
+ \ifpackflushedfloats
+ \centerfloatboxfalse
+ \dogetfloat
+ \ifdim\wd\floatbox>\makeupwidth
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi
+ \OTRONEsetvsize
+ \!!widtha\wd\floatbox
+ \dofloatflushedinfo
+ \doloop
+ {\ifsomefloatwaiting
+ \dosavefloatstatus
+ \dogetfloat
+ \advance\!!widtha 1em % variable
+ \advance\!!widtha \wd\floatbox\relax
+ \ifdim\!!widtha>\hsize
+ \dorestorefloatstatus
+ \global\somefloatwaitingtrue
+ \exitloop
+ \else
+ \global\setbox\floatbox\hbox
+ {\ifcase\columndirection % nog document wide
+ \ifvoid\savedfloatbox\else
+ \ifhbox\savedfloatbox\unhbox\else\box\fi\savedfloatbox\hfil
+ \fi
+ \ifhbox\floatbox\unhbox\else\box\fi\floatbox
+ \else
+ \ifhbox\floatbox\unhbox\else\box\fi\floatbox
+ \ifvoid\savedfloatbox\else
+ \hfil\ifhbox\savedfloatbox\unhbox\else\box\fi\savedfloatbox
+ \fi
+ \fi}%
+ \dofloatflushedinfo
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \global\setbox\floatbox\hbox to \hsize
+ {\hfil\ifhbox\floatbox\unhbox\else\box\fi\floatbox\hfil}%
+ \else
+ %\bgroup % \box\floatbox can be in use!? messy
+ \dogetfloat
+ %\doplacefloatbox
+ %\egroup
+ \dofloatflushedinfo
+ \fi
+ % there is a chance that due to rounding errors, the float
+ % fits on a page where it was first rejected, in which case
+ % the prevdepth is -maxdimen and we cannot obey the grid
+ \doplacefloatbox
+ \expandafter\OTRONEdodoflushfloats
+ \fi}
+
+\def\OTRONEdocheckiffloatfits % vervangen ivm downward comp
+ {\ifnofloatpermitted
+ \global\roomforfloatfalse
+ \else
+ % new per 31/5/2004, should be an option, only one column mode
+ \begingroup
+ \scratchdimen\dimexpr\pagetotal+\lineheight\relax
+ \ifdim\scratchdimen>\pagegoal
+ \goodbreak % hack ? needed in icare-az
+ \fi
+ % should be an option
+ \endgroup
+ \dimen0\dimexpr\pagetotal+\ht\floatbox+\dp\floatbox+\floattopskip-\pageshrink\relax
+ %\message{c:\the\mofcolumns,t:\the\pagetotal,g:\the\pagegoal}%\wait
+ \dimen2\pagegoal
+ \relax % needed
+ \ifcase\textfloatmethod
+ % method 0 : raw
+ \or
+ % method 1 : safe
+ \dimen2 .99\pagegoal
+ \or
+ % method 2 : tight
+ \advance\dimen0 -\onepoint
+ \fi
+ \relax % really needed ! ! ! !
+ \ifdim\dimen0>\dimen2
+ \global\roomforfloatfalse
+ \else
+ \global\roomforfloattrue
+ \fi
+ \fi}
+
+\def\OTRONEflushsavedfloats
+ {\dosetbothinserts}
+
+% TODO: TEST FIRST, NO CORRECTION NEEDED IN GRID MODE, EVT OPTION
+
+\def\OTRONEsomeherefloat[#1]% spacing between two successive must be better
+ {\baselinecorrection % not really needed in grid mode:
+ %\ifgridsnapping \else \baselinecorrection \fi % ! ! ! test test test ! ! ! !
+ \doplacefloatbox
+ \doinsertfloatinfo
+ \dochecknextindentation\??bk
+ \dorechecknextindentation}
+
+% \def\OTRONEsomefixdfloat % [#1]
+% {\docheckiffloatfits
+% \ifroomforfloat\else
+% \goodbreak
+% \fi
+% \showmessage\m!floatblocks9\empty
+% \someherefloat} % [#1]
+%
+% better:
+%
+% \dorecurse{50}
+% {[before normal] \input thuan
+% \placefigure{normal}{\framed[height=1cm,width=8cm]{}}
+% \placefigure{normal}{\framed[height=2cm,width=8cm]{}}
+% [before force] \input thuan
+% \placefigure[force]{force}{\framed[height=8cm,width=8cm]{}}}
+
+\chardef\fixedfloatmethod=3
+
+% \def\OTRONEsomefixdfloat % [#1]
+% {\docheckiffloatfits
+% \ifroomforfloat\else
+% \ifzeropt\pagetotal
+% % let's assume that there is room
+% \else
+% \ifcase\fixedfloatmethod
+% % disabled
+% \or % 1 (old method)
+% \goodbreak
+% \or % 2 (safe method)
+% \page
+% \or % 3 (keeps in stream)
+% \vskip\textheight
+% \vskip-\textheight
+% \or % 4 (also keeps in place)
+% \dosomebreak\nobreak
+% \fi
+% \fi
+% \fi
+% \showmessage\m!floatblocks9\empty
+% \someherefloat} % [#1]
+
+\def\OTRONEsomefixdfloat % [#1]
+ {% there is (in mkii) no good way to prevent a break
+ % so better fail than mess, we can get loose from
+ % heads, so be it
+ \showmessage\m!floatblocks9\empty
+ \OTRONEsomeherefloat} % [#1]
+
+\def\OTRONEsomesidefloat[#1]% links, rechts NOG TESTEN EN AANPASSEN
+ {\ifinsidecolumns
+ \someelsefloat[\v!here]%
+ \else
+ %\checkwaitingfloats{#1}%
+ \def\logsidefloat
+ {\doinsertfloatinfo}%
+ \setbox\floatbox\vbox{\box\floatbox}%
+ \wd\floatbox\floatwidth
+ \processfirstactioninset
+ [#1]
+ [ \v!left=>\leftfloat {\box\floatbox},
+ \v!right=>\rightfloat {\box\floatbox},
+ \v!inleft=>\leftmarginfloat {\box\floatbox},
+ \v!inright=>\rightmarginfloat{\box\floatbox},
+ \v!leftmargin=>\leftmarginfloat {\box\floatbox},
+ \v!rightmargin=>\rightmarginfloat{\box\floatbox},
+ \v!leftedge=>\leftedgefloat {\box\floatbox},
+ \v!rightedge=>\rightedgefloat {\box\floatbox},
+ \v!backspace=>\backspacefloat {\box\floatbox},
+ \v!cutspace=>\cutspacefloat {\box\floatbox},
+ \v!inmargin=>\cutspacefloat {\box\floatbox}]%
+ \doifinset\v!tall{#1}\flushsidefloatsafterpar
+ \fi}
+
+\def\OTRONEdosomepagefloat#1[#2]%
+ {%\checkwaitingfloats{#1}%
+ \global\setbox#1\vbox
+ {\unvbox#1%
+ \vbox to \textheight
+ {\doifnotinset\v!high{#2}\vfill
+ \box\floatbox
+ \doifnotinset\v!low{#2}\vfill}%
+ \goodbreak}%
+ \doinsertfloatinfo}
+
+\def\OTRONEsomepagefloat {\OTRONEdosomepagefloat\collectedpagefloats}
+\def\OTRONEsomeleftpagefloat {\OTRONEdosomepagefloat\collectedleftpagefloats}
+\def\OTRONEsomerightpagefloat{\OTRONEdosomepagefloat\collectedrightpagefloats}
+
+\def\OTRONEsometopsfloat[#1]%
+ {\ifdim\topinserted=\zeropoint
+ \topofinserttrue
+ \else
+ \topofinsertfalse
+ \fi
+ \global\advance\topinserted \ht\floatbox
+ \global\advance\topinserted \dp\floatbox
+ \global\advance\topinserted \floatbottomskip
+ \insert\topins
+ {\forgetall
+ \iftopofinsert
+ \topskipcorrection % [xx] new: see icare topbleed
+ \kern-\lineskip\par\prevdepth\maxdimen
+ \else
+ %\blank[-\@@bkspaceafter,\@@bkspacebefore]% inserts can't look back
+ \betweenfloatblanko
+ \fi
+ \flushfloatbox
+ \blank[\@@bkspaceafter]}%
+ \doinsertfloatinfo}
+
+\def\OTRONEsomebotsfloat[#1]%
+ {\global\advance\botinserted \ht\floatbox
+ \global\advance\botinserted \dp\floatbox
+ \global\advance\botinserted \floattopskip
+ \insert\botins
+ {\forgetall
+ \blank[\@@bkspacebefore]%
+ \flushfloatbox}%
+ %\global\nofloatpermittedtrue
+ \doinsertfloatinfo}
+
+\def\OTRONEsomefacefloat[#1]% untested
+ {\startopposite\flushfloatbox\stopopposite}
+
+\def\OTRONEnextcolumn[#1]%
+ {}
+
+\protect \endinput
diff --git a/tex/context/base/page-one.mkiv b/tex/context/base/page-one.mkiv
new file mode 100644
index 000000000..bbd35181e
--- /dev/null
+++ b/tex/context/base/page-one.mkiv
@@ -0,0 +1,532 @@
+%D \module
+%D [ file=page-one,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Default Routine,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Default Routine}
+
+%D This is just the good old \CONTEXT\ output routine, which
+%D has been there right from the start.
+
+\unprotect
+
+% OTRONE: basic single column
+
+\activateotr{ONE}{} % the default one
+
+\newtoks\OTRONEoutput
+
+\def\OTRONEgotonextpage
+ {\ejectpage}
+
+\def\OTRONEgotonextpageX % will become obsolete
+ {\superejectpage}
+
+\def\OTRONEsethsize
+ {\global\hsize\textwidth}
+
+\newdimen\oldvsize
+
+\def\OTRONEsetvsize
+ {\ifgridsnapping
+ \ifcase\layoutlines
+ \getrawnoflines\textheight
+ \else
+ \noflines\layoutlines
+ \fi
+ \global\vsize\noflines\openlineheight
+ \else
+ \global\vsize\textheight
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\oldvsize=\vsize
+ % let's assume that the layout didn't change
+ \else
+ \bgroup
+ \global\oldvsize\vsize
+ \advance\vsize-\topinserted
+ \advance\vsize-\botinserted
+ \global\pagegoal\vsize
+ \egroup
+ \fi
+ \fi}
+
+\chardef\kindofpagetextareas=2 % whole page (public variable! never change)
+
+% can we avoind the extra vboxing here?
+
+\def\OTRONEregisteredtextarea#1%
+ {\ifregistertextareas
+ \setbox0\vbox{#1}%
+ \wd0\makeupwidth % somehow a space creeps in
+ \vbox{\registeredtextarea000}%
+ \else
+ #1%
+ \fi}
+
+% \chardef\kindofpagetextareas\plusone
+
+\def\doOTRONEregisteredtextareaA#1%
+ {\ifregistertextareas
+ \xypos{pbd:\realfolio:b}% we could save bytes by only saving the y
+ \endgraf
+ \begingroup
+ \scratchdimen\dimexpr\MPy{pbd:\realfolio:b}-\MPy{pbd:\realfolio:e}\relax
+ \setbox\scratchbox\null
+ \wd\scratchbox\makeupwidth
+ \ht\scratchbox\scratchdimen
+ \vsmash{\registeredtextarea00\scratchbox}%
+ \endgroup
+ #1%
+ \endgraf
+ \xypos{pbd:\realfolio:e}%
+ \else
+ #1%
+ \fi}
+
+\def\doOTRONEregisteredtextareaB#1%
+ {\ifregistertextareas
+ \setbox0\vbox{#1}%
+ \wd0\makeupwidth % somehow a space creeps in
+ \vbox{\registeredtextarea000}%
+ \else
+ #1%
+ \fi}
+
+\let\OTRONEregisteredtextareaA\firstofoneargument
+\let\OTRONEregisteredtextareaB\firstofoneargument
+
+\def\OTRONEdopagecontents#1#2% \box \unvbox
+ {\bgroup % niet breedte zetten, kan fractie zijn!
+ \ifcase\kindofpagetextareas
+ \or % partial page (experimental)
+ \let\OTRONEregisteredtextareaA\doOTRONEregisteredtextareaA
+ \or % whole page (default)
+ \let\OTRONEregisteredtextareaB\doOTRONEregisteredtextareaB
+ \or % partial page (only works well with no stretch!)
+ \let\OTRONEregisteredtextareaA\doOTRONEregisteredtextareaB
+ \fi
+ \setbox0\vbox \ifbottomnotes to \textheight \fi
+ {\edef\currentpagedepth{\the\dp#2}% still to be derived from #1
+ \dotopinsertions
+ \ifgridsnapping
+ \OTRONEregisteredtextareaA{#1#2}%
+ \vskip-\currentpagedepth\vskip\openstrutdepth
+ \prevdepth\openstrutdepth
+ \dobotinsertions
+ \vfil
+ \else\ifr@ggedbottom
+ \OTRONEregisteredtextareaA{#1#2}%
+ \vskip-\currentpagedepth\vskip\openstrutdepth
+ \prevdepth\openstrutdepth
+ \dobotinsertions
+ \vfil
+ \else\ifb@selinebottom
+ \OTRONEregisteredtextareaA{#1#2}%
+ \kern-\currentpagedepth\kern\maxdepth
+ \dobotinsertions
+ \else
+ \OTRONEregisteredtextareaA{#1#2}%
+ \dobotinsertions % added
+ \fi\fi\fi
+ \fakepagenotes}% was \fakenotes, but wrong! (check with \setupalign[height])
+ \ifbottomnotes
+ \ifgridsnapping
+ \ifcase\layoutlines % todo: make macro of this
+ \getrawnoflines\textheight
+ \else
+ \noflines\layoutlines
+ \fi
+ \advance\noflines \minusone
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen \topskip
+ \else
+ \scratchdimen\ht0
+ \fi
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \setbox2\hbox
+ {\checksinglecolumnfootnotes
+ \lower\scratchdimen\vbox{\placebottomnotes}}%
+ \smashbox2% % needed here
+ \ifbottomnotes
+ \ht0\zeropoint
+ \fi
+ \OTRONEregisteredtextareaB
+ {\vbox to \textheight
+ {\box0\box2\ifbottomnotes\else\vfill\fi}}%
+ \egroup}
+
+\def\OTRONEfinalsidefloatoutput
+ {\finaloutput\unvbox\normalpagebox}
+
+\OTRONEoutput
+ {\sidefloatoutput}
+
+%D Insertions
+
+\newif\iftopofinsert
+
+\def\OTRONEdosettopinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \let\totaltopinserted\!!zeropoint
+ \OTRONEdodosettopinserts
+ \ifnum\@@bknbottom=\zerocount
+ \ifnum\@@bknlines>\zerocount
+ \ifdim\totaltopinserted>\zeropoint\relax
+ \ifdim\dimexpr\@@bknlines\lineheight+\totaltopinserted\relax>\textheight
+ \showmessage\m!floatblocks8\@@bknlines
+ \vfilll\eject
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRONEdodosettopinserts
+ {\ifnum\noffloatinserts<\noftopfloats
+ \dogetfloat
+ \ifdim\topinserted=\zeropoint
+ \topofinserttrue
+ \else
+ \topofinsertfalse
+ \fi
+ \global\advance\topinserted\dimexpr\ht\floatbox+\dp\floatbox+\floatbottomskip\relax
+ \ifdim\topinserted<\textheight\relax
+ \xdef\totaltopinserted{\the\topinserted}%
+ \insert\topins
+ {\forgetall
+ \iftopofinsert
+ \topskipcorrection % [xx] new: see icare topbleed
+ \kern-\lineskip\par
+ \prevdepth\maxdimen
+ \else
+ %\blank[-\@@bkspaceafter,\@@bkspacebefore]% inserts can't look back
+ \betweenfloatblanko
+ \fi
+ \flushfloatbox
+ \blank[\@@bkspaceafter]}%
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\noftopfloats\relax
+ \fi
+ \dofloatflushedinfo
+ \else
+ \doresavefloat
+ \noffloatinserts\noftopfloats\relax
+ \fi
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks6{\the\noftopfloats}%
+ \fi
+ \let\OTRONEdodosettopinserts\relax
+ \fi
+ \OTRONEdodosettopinserts}
+
+\def\OTRONEdosetbotinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \OTRONEdodosetbotinserts
+ \fi
+ \egroup}
+
+\def\OTRONEdodosetbotinserts
+ {\ifnum\noffloatinserts<\nofbotfloats\relax
+ \dogetfloat
+ \global\advance\botinserted \ht\floatbox\relax
+ \global\advance\botinserted \dp\floatbox\relax
+ \global\advance\botinserted \floattopskip\relax
+ \ifdim\botinserted<\pagegoal\relax
+ \insert\botins
+ {\forgetall
+ \blank[\@@bkspacebefore]%
+ \flushfloatbox}%
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\nofbotfloats
+ \fi
+ \dofloatflushedinfo
+ \else
+ \doresavefloat
+ \noffloatinserts\nofbotfloats\relax
+ \fi
+ \global\nofloatpermittedtrue % vgl topfloats s!
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks7{\the\nofbotfloats}%
+ \fi
+ \let\OTRONEdodosetbotinserts\relax
+ \fi
+ \OTRONEdodosetbotinserts}
+
+\def\OTRONEdosetbothinserts
+ {\global\topinserted\zeropoint
+ \global\botinserted\zeropoint
+ \ifflushingfloats \else
+ \OTRONEdosettopinserts
+ \OTRONEdosetbotinserts
+ \ifsomefloatwaiting
+ \doif\@@bkcache\v!no\doflushfloats
+ \fi
+ \fi}
+
+\chardef\topinserttopskipmode=0 % 1 no topskip
+
+\def\OTRONEdotopinsertions
+ {\ifvoid\topins\else
+ \ifgridsnapping
+ \box\topins
+ \vskip-\topskip
+ \vskip\strutheight % [xx] new: see icare topbleed
+ \else
+ \ifcase\topinserttopskipmode
+ % 0: default, do nothing
+ \or
+ % 1: no topskip (crossed fingers)
+ \vskip-\topskip
+ \vskip\strutheight
+ \fi
+ \unvbox\topins
+ \fi
+ \fi
+ \global\topinserted\zeropoint}
+
+\def\OTRONEdobotinsertions
+ {\ifvoid\botins\else
+ \ifgridsnapping
+ % \floatparameter\c!bottombefore
+ \snaptogrid\hbox{\box\botins}%
+ % \floatparameter\c!bottomafter
+ \else
+ \floatparameter\c!bottombefore
+ \unvbox\botins
+ \floatparameter\c!bottomafter
+ \fi
+ \fi
+ \global\botinserted\zeropoint
+ \global\nofloatpermittedfalse}
+
+\def\OTRONEdoflushfloats
+ {\global\flushingfloatstrue
+ \ifsomefloatwaiting
+ \par
+ % if kept, then option and definitely off in gridmode ! ! ! !
+ % \ifvmode \prevdepth\maxdimen \fi % prevents whitespace; problematic in icare tests
+ \OTRONEdodoflushfloats
+ \fi
+ \global\savednoffloats\zerocount
+ \global\somefloatwaitingfalse
+ \global\flushingfloatsfalse}
+
+\def\OTRONEflushfloatbox % nog verder doorvoeren en meer info in marge
+ {\ifcenterfloatbox \ifdim\wd\floatbox<\hsize
+ \global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}%
+ \fi \fi
+ \snaptogrid\hbox{\iftestfloatbox\ruledhbox\fi{\box\floatbox}}} % was copy
+
+\def\OTRONEdodoflushfloats % much in common with OTRSET
+ {\ifsomefloatwaiting
+ \ifpackflushedfloats
+ \centerfloatboxfalse % not needed as we do call directly
+ \dofloatscollect{text}{\hsize}{1em}%
+ \OTRONEsetvsize
+ \global\setbox\floatbox\hbox to \hsize
+ {\hfil
+ \dorecurse\nofcollectedfloats
+ {\ifcase\columndirection % nog document wide
+ \dofloatsflush{text}{1}%
+ \else
+ \dofloatsflushn{text}{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}%
+ \fi
+ \ifdim\wd\floatbox>\makeupwidth % \hsize
+ \hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \else
+ \box\floatbox
+ \fi
+ \ifnum\recurselevel<\nofcollectedfloats
+ \hfil
+ \fi}%
+ \hfil}%
+ \else
+ \dogetfloat
+ \fi
+ % there is a chance that due to rounding errors, the float
+ % fits on a page where it was first rejected, in which case
+ % the prevdepth is -maxdimen and we cannot obey the grid
+ \doplacefloatbox
+ \expandafter\OTRONEdodoflushfloats
+ \fi}
+
+\def\OTRONEdocheckiffloatfits % vervangen ivm downward comp
+ {\ifnofloatpermitted
+ \global\roomforfloatfalse
+ \else
+ % new per 31/5/2004, should be an option, only one column mode
+ \begingroup
+ \scratchdimen\dimexpr\pagetotal+\lineheight\relax
+ \ifdim\scratchdimen>\pagegoal
+ \goodbreak % hack ? needed in icare-az
+ \fi
+ % should be an option
+ \endgroup
+ \dimen0\dimexpr\pagetotal+\floatheight+\floattopskip-\pageshrink\relax
+ \dimen2\pagegoal
+ \relax % needed
+ \ifcase\textfloatmethod
+ % method 0 : raw
+ \or
+ % method 1 : safe
+ \dimen2 .99\pagegoal
+ \or
+ % method 2 : tight
+ \advance\dimen0 -\onepoint
+ \fi
+ \relax % really needed ! ! ! !
+ \ifdim\dimen0>\dimen2
+ \global\roomforfloatfalse
+ \else
+ \global\roomforfloattrue
+ \fi
+ \fi}
+
+\def\OTRONEflushsavedfloats
+ {\dosetbothinserts}
+
+% TODO: TEST FIRST, NO CORRECTION NEEDED IN GRID MODE, EVT OPTION
+
+\def\OTRONEsomeherefloat[#1]% spacing between two successive must be better
+ {\baselinecorrection % not really needed in grid mode:
+ %\ifgridsnapping \else \baselinecorrection \fi % ! ! ! test test test ! ! ! !
+ \doplacefloatbox
+ \doinsertfloatinfo
+ \dohandlenextfloatindent}
+
+% \def\OTRONEsomefixdfloat % [#1]
+% {\docheckiffloatfits
+% \ifroomforfloat\else
+% \goodbreak
+% \fi
+% \showmessage\m!floatblocks9\empty
+% \someherefloat} % [#1]
+%
+% better:
+%
+% \dorecurse{50}
+% {[before normal] \input thuan
+% \placefigure{normal}{\framed[height=1cm,width=8cm]{}}
+% \placefigure{normal}{\framed[height=2cm,width=8cm]{}}
+% [before force] \input thuan
+% \placefigure[force]{force}{\framed[height=8cm,width=8cm]{}}}
+
+\chardef\fixedfloatmethod=3
+
+% \def\OTRONEsomefixdfloat % [#1]
+% {\docheckiffloatfits
+% \ifroomforfloat\else
+% \ifzeropt\pagetotal
+% % let's assume that there is room
+% \else
+% \ifcase\fixedfloatmethod
+% % disabled
+% \or % 1 (old method)
+% \goodbreak
+% \or % 2 (safe method)
+% \page
+% \or % 3 (keeps in stream)
+% \vskip\textheight
+% \vskip-\textheight
+% \or % 4 (also keeps in place)
+% \dosomebreak\nobreak
+% \fi
+% \fi
+% \fi
+% \showmessage\m!floatblocks9\empty
+% \someherefloat} % [#1]
+
+\def\OTRONEsomefixdfloat % [#1]
+ {% there is (in mkii) no good way to prevent a break
+ % so better fail than mess, we can get loose from
+ % heads, so be it
+ \showmessage\m!floatblocks9\empty
+ \OTRONEsomeherefloat} % [#1]
+
+\def\OTRONEsomesidefloat[#1]% links, rechts NOG TESTEN EN AANPASSEN
+ {\ifinsidecolumns
+ \someelsefloat[\v!here]%
+ \else
+ %\checkwaitingfloats{#1}%
+ \def\logsidefloat
+ {\doinsertfloatinfo}%
+ \setbox\floatbox\vbox{\box\floatbox}%
+ \wd\floatbox\floatwidth
+ \processfirstactioninset
+ [#1]
+ [ \v!left=>\leftfloat {\box\floatbox},
+ \v!right=>\rightfloat {\box\floatbox},
+ \v!inleft=>\leftmarginfloat {\box\floatbox},
+ \v!inright=>\rightmarginfloat{\box\floatbox},
+ \v!leftmargin=>\leftmarginfloat {\box\floatbox},
+ \v!rightmargin=>\rightmarginfloat{\box\floatbox},
+ \v!leftedge=>\leftedgefloat {\box\floatbox},
+ \v!rightedge=>\rightedgefloat {\box\floatbox},
+ \v!backspace=>\backspacefloat {\box\floatbox},
+ \v!cutspace=>\cutspacefloat {\box\floatbox},
+ \v!inmargin=>\cutspacefloat {\box\floatbox}]%
+ \doifinset\v!tall{#1}\flushsidefloatsafterpar
+ \fi}
+
+\def\OTRONEsomepagefloat [#1]{\dofloatssavepagefloat{page} {#1}}
+\def\OTRONEsomeleftpagefloat [#1]{\dofloatssavepagefloat{leftpage} {#1}}
+\def\OTRONEsomerightpagefloat[#1]{\dofloatssavepagefloat{rightpage}{#1}}
+
+\def\OTRONEsometopsfloat[#1]%
+ {\ifdim\topinserted=\zeropoint
+ \topofinserttrue
+ \else
+ \topofinsertfalse
+ \fi
+ \global\advance\topinserted\dimexpr\ht\floatbox+\dp\floatbox+\floatbottomskip\relax
+ \insert\topins
+ {\forgetall
+ \iftopofinsert
+ \topskipcorrection % [xx] new: see icare topbleed
+ \kern-\lineskip\par\prevdepth\maxdimen
+ \else
+ %\blank[-\@@bkspaceafter,\@@bkspacebefore]% inserts can't look back
+ \betweenfloatblanko
+ \fi
+ \flushfloatbox
+ \blank[\@@bkspaceafter]}%
+ \doinsertfloatinfo}
+
+\def\OTRONEsomebotsfloat[#1]%
+ {\global\advance\botinserted\dimexpr\ht\floatbox+\dp\floatbox+\floattopskip\relax
+ \insert\botins
+ {\forgetall
+ \blank[\@@bkspacebefore]%
+ \flushfloatbox}%
+ %\global\nofloatpermittedtrue
+ \doinsertfloatinfo}
+
+\def\OTRONEsomefacefloat[#1]% untested
+ {\startopposite\flushfloatbox\stopopposite}
+
+\def\OTRONEnextcolumn[#1]%
+ {}
+
+\protect \endinput
diff --git a/tex/context/base/page-par.mkii b/tex/context/base/page-par.mkii
new file mode 100644
index 000000000..a5dea2e63
--- /dev/null
+++ b/tex/context/base/page-par.mkii
@@ -0,0 +1,58 @@
+%D \module
+%D [ file=page-par, % copied from page-lin
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Line Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Paragraph Numbering}
+
+\unprotect
+
+\newcount\internalparagraphnumber
+
+\def\setupparagraphnumbering
+ {\dosingleempty\dosetupparagraphnumbering}
+
+\def\dosetupparagraphnumbering[#1]%
+ {\getparameters
+ [\??ph][#1]%
+ \processaction
+ [\@@phstate]
+ [\v!start=>\let\showparagraphnumber\doshowparagraphnumberA,
+ \v!stop=>\let\showparagraphnumber\relax,
+ \v!line=>\let\showparagraphnumber\doshowparagraphnumberB,
+ \v!reset=>\global\internalparagraphnumber\zerocount
+ \let\showparagraphnumber\doshowparagraphnumberA]}
+
+\def\dodoshowparagraphnumber
+ {\global\advance\internalparagraphnumber \plusone
+ \inleftmargin % \tf normalizes em
+ {\tf{\doattributes\??ph\c!style\c!color{\the\internalparagraphnumber}}%
+ \kern\@@phdistance}}
+
+\def\doshowparagraphnumberA
+ {\ifprocessingverbatim
+ \iflinepar\dodoshowparagraphnumber\fi
+ \else
+ \dodoshowparagraphnumber
+ \fi}
+
+\def\doshowparagraphnumberB
+ {\ifnumberinglines
+ \doshowparagraphnumberA
+ \fi}
+
+\setupparagraphnumbering
+ [\c!state=\v!stop,
+ \c!style=,
+ \c!color=,
+ \c!distance=\ifcase\linenumberlocation2em\else\!!zeropoint\fi] % will change
+
+\protect \endinput
diff --git a/tex/context/base/page-par.mkiv b/tex/context/base/page-par.mkiv
new file mode 100644
index 000000000..fb8631eec
--- /dev/null
+++ b/tex/context/base/page-par.mkiv
@@ -0,0 +1,58 @@
+%D \module
+%D [ file=page-par, % copied from page-lin
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Line Numbering,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Paragraph Numbering}
+
+\unprotect
+
+\newcount\internalparagraphnumber
+
+\unexpanded\def\setupparagraphnumbering
+ {\dosingleempty\dosetupparagraphnumbering}
+
+\def\dosetupparagraphnumbering[#1]%
+ {\getparameters
+ [\??ph][#1]%
+ \processaction
+ [\@@phstate]
+ [\v!start=>\let\showparagraphnumber\doshowparagraphnumberA,
+ \v!stop=>\let\showparagraphnumber\relax,
+ \v!line=>\let\showparagraphnumber\doshowparagraphnumberB,
+ \v!reset=>\global\internalparagraphnumber\zerocount
+ \let\showparagraphnumber\doshowparagraphnumberA]}
+
+\def\dodoshowparagraphnumber
+ {\global\advance\internalparagraphnumber \plusone
+ \inleftmargin % \tf normalizes em
+ {\tf{\doattributes\??ph\c!style\c!color{\the\internalparagraphnumber}}%
+ \kern\@@phdistance}}
+
+\def\doshowparagraphnumberA
+ {\ifprocessingverbatim
+ \iflinepar\dodoshowparagraphnumber\fi
+ \else
+ \dodoshowparagraphnumber
+ \fi}
+
+\def\doshowparagraphnumberB
+ {\ifnumberinglines
+ \doshowparagraphnumberA
+ \fi}
+
+\setupparagraphnumbering
+ [\c!state=\v!stop,
+ \c!style=,
+ \c!color=,
+ \c!distance=\ifcase\linenumberlocation2em\else\!!zeropoint\fi] % will change
+
+\protect \endinput
diff --git a/tex/context/base/page-plg.mkii b/tex/context/base/page-plg.mkii
new file mode 100644
index 000000000..3203b923c
--- /dev/null
+++ b/tex/context/base/page-plg.mkii
@@ -0,0 +1,202 @@
+%D \module
+%D [ file=page-pls,
+%D version=2003.03.16,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Setup,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifx\pageareabox\undefined \else \endinput \fi
+
+\writestatus{loading}{ConTeXt Page Macros / Extra Page Building}
+
+%D This feature has been present for a while but has never been
+%D exploited: pluggable pagebuilders. The next example code
+%D demonstrates the application of one such a plug-in. This variant
+%D support \type {page}, \type {leftpage} and \type {rightpage}
+%D definitions where specific areas are placed with the \type
+%D {\pagearea} command.
+%D
+%D \starttyping
+%D \setupheadertexts[the header text]
+%D \setupfootertexts[a pretty long left footer text][something right]
+%D \setupbottomtexts[a not so long bottom text][another right thing]
+%D \setuptexttexts [margin][something marginal][indeed]
+%D
+%D \startpagelayout[leftpage]
+%D \setupTABLE[offset=overlay]
+%D \setupTABLE[c][1][width=\leftmarginwidth]
+%D \bTABLE
+%D \bTR
+%D \bTD[nx=3,background=color,backgroundcolor=green]
+%D \pagearea[header][text][middle]
+%D \eTD
+%D \eTR
+%D \bTR
+%D \bTD \pagearea[text][margin][left] \eTD
+%D \bTD[nx=2] \pagearea[text] \eTD
+%D \eTR
+%D \bTR
+%D \bTD[nx=3,offset=overlay]
+%D {\bTABLE[width=.5\hsize]
+%D \bTR
+%D \bTD \pagearea[footer][text][left] \eTD
+%D \bTD \pagearea[bottom][text][left] \eTD
+%D \eTR
+%D \eTABLE}
+%D \eTD
+%D \eTR
+%D \eTABLE
+%D \stoppagelayout
+%D
+%D \startpagelayout[rightpage]
+%D \setupTABLE[offset=overlay]
+%D \setupTABLE[c][1][width=\rightmarginwidth]
+%D \bTABLE
+%D \bTR
+%D \bTD[nx=3] \pagearea[header][text][middle] \eTD
+%D \eTR
+%D \bTR
+%D \bTD \pagearea[text][margin][left] \eTD
+%D \bTD[nx=2] \pagearea[text] \eTD
+%D \eTR
+%D \bTR
+%D \bTD[nx=3,offset=overlay]
+%D {\bTABLE[width=.5\hsize]
+%D \bTR
+%D \bTD \pagearea[bottom][text][right] \eTD
+%D \bTD \pagearea[footer][text][right] \eTD
+%D \eTR
+%D \eTABLE}
+%D \eTD
+%D \eTR
+%D \eTABLE
+%D \stoppagelayout
+%D
+%D \setupcolors[state=start]
+%D
+%D \setupbackgrounds[text][background=color,backgroundcolor=blue]
+%D \setupbackgrounds[header][text][background=color,backgroundcolor=red]
+%D
+%D \setuppagenumbering[alternative=doublesided,location=]
+%D
+%D \setuplayout[method=makeup]
+%D
+%D \definetextbackground
+%D [test]
+%D [state=start,
+%D background=color,
+%D backgroundcolor=yellow]
+%D
+%D \starttext
+%D
+%D \dorecurse{10}{\input tufte \par}
+%D
+%D \input tufte \starttest \input tufte \stoptest \input tufte
+%D
+%D \starttabulate
+%D \NC test \NC \starttest \input tufte \stoptest \NC \NR
+%D \stoptabulate
+%D
+%D \dorecurse{10}{\input tufte \par}
+%D
+%D \stoptext
+%D \stoptyping
+
+\unprotect
+
+\setvalue{\??ly\c!method\v!makeup}#1#2%
+ {\setbox\pagebox\hbox
+ {\vbox to \textheight
+ {\offinterlineskip
+ % optie
+ \vskip\dimexpr-1\topskip+\strutheight\relax
+ %
+ \textwidth\makeupwidth
+ \hsize\textwidth
+ \boxmaxdepth\maxdepth
+ \noindent
+ \dopagecontents#1#2}}%
+ \wd\pagebox\makeupwidth
+ \ht\pagebox\textheight
+ \dp\pagebox\zeropoint
+ \hsize\paperwidth
+ \vsize\paperheight
+ \setbox\pagebox\vbox
+ {\doifbothsidesoverruled
+ {\let\!!stringa\v!page}
+ {\let\!!stringa\v!rightpage}
+ {\let\!!stringa\v!leftpage}%
+ \getvalue{\??ly\c!method:\!!stringa}}%
+ \wd\pagebox\paperwidth
+ \ht\pagebox\paperheight
+ \dp\pagebox\zeropoint}
+
+\newbox\pageareabox
+
+\def\pagearea
+ {\dotripleempty\dopagearea}
+
+\def\dopagearea[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#3}\v!left
+ {\dodopagearea{#1}{#2}\c!lefttext}
+ {\doifelse{#3}\v!right
+ {\dodopagearea{#1}{#2}\c!righttext}
+ {\dodopagearea{#1}{#2}\c!middletext}}%
+ \else\ifsecondargument
+ \doifbothsidesoverruled
+ {\dodopagearea{#1}{#2}\c!righttext}
+ {\dodopagearea{#1}{#2}\c!righttext}
+ {\dodopagearea{#1}{#2}\c!lefttext }%
+ \else
+ \doif{#1}\v!text % copy due to trial runs in TABLE
+ {\iftrialtypesetting
+ \copy\pagebox
+ \else
+ \setbox\pagebox\vbox
+ {\localstarttextcolor
+ \box\pagebox
+ \localstoptextcolor}%
+ \localpositioningfalse
+ \addtextbackground\pagebox
+ \addtextgridlayer\pagebox
+ \box\pagebox
+ \fi}%
+ \fi\fi}
+
+\def\dodopagearea#1#2#3%
+ {\setbox\pageareabox\vbox{\getvalue{\??tk#1#2#3}}%
+ \ifsomebackgroundfound{#1#2}%
+ \iftrialtypesetting
+ \box\pageareabox
+ \else
+ \localframed
+ [\??ma#1#2]
+ [\c!width=\wd\pageareabox,
+ \c!height=\ht\pageareabox,
+ \c!offset=\v!overlay]
+ {\box\pageareabox}%
+ \fi
+ \else
+ \box\pageareabox
+ \fi}
+
+\setvalue{\??ly\c!method:\v!leftpage }{\getvalue{\??ly\c!method:\v!page}}
+\setvalue{\??ly\c!method:\v!rightpage}{\getvalue{\??ly\c!method:\v!page}}
+
+% \long\def\startpagelayout[#1]#2\stoppagelayout
+% {\long\setvalue{\??ly\c!method:#1}{#2}}
+
+\long\def\startpagelayout
+ {\bgroup\catcode`\^^M=\@@ignore\dostartpagelayout}
+
+\long\def\dostartpagelayout[#1]#2\stoppagelayout
+ {\egroup\long\setvalue{\??ly\c!method:#1}{#2}}
+
+\protect \endinput
diff --git a/tex/context/base/page-plg.mkiv b/tex/context/base/page-plg.mkiv
new file mode 100644
index 000000000..7d7612153
--- /dev/null
+++ b/tex/context/base/page-plg.mkiv
@@ -0,0 +1,198 @@
+%D \module
+%D [ file=page-pls,
+%D version=2003.03.16,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Setup,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifx\pageareabox\undefined \else \endinput \fi
+
+\writestatus{loading}{ConTeXt Page Macros / Extra Page Building}
+
+%D This feature has been present for a while but has never been
+%D exploited: pluggable pagebuilders. The next example code
+%D demonstrates the application of one such a plug-in. This variant
+%D support \type {page}, \type {leftpage} and \type {rightpage}
+%D definitions where specific areas are placed with the \type
+%D {\pagearea} command.
+%D
+%D \starttyping
+%D \setupheadertexts[the header text]
+%D \setupfootertexts[a pretty long left footer text][something right]
+%D \setupbottomtexts[a not so long bottom text][another right thing]
+%D \setuptexttexts [margin][something marginal][indeed]
+%D
+%D \startpagelayout[leftpage]
+%D \setupTABLE[offset=overlay]
+%D \setupTABLE[c][1][width=\leftmarginwidth]
+%D \bTABLE
+%D \bTR
+%D \bTD[nx=3,background=color,backgroundcolor=green]
+%D \pagearea[header][text][middle]
+%D \eTD
+%D \eTR
+%D \bTR
+%D \bTD \pagearea[text][margin][left] \eTD
+%D \bTD[nx=2] \pagearea[text] \eTD
+%D \eTR
+%D \bTR
+%D \bTD[nx=3,offset=overlay]
+%D {\bTABLE[width=.5\hsize]
+%D \bTR
+%D \bTD \pagearea[footer][text][left] \eTD
+%D \bTD \pagearea[bottom][text][left] \eTD
+%D \eTR
+%D \eTABLE}
+%D \eTD
+%D \eTR
+%D \eTABLE
+%D \stoppagelayout
+%D
+%D \startpagelayout[rightpage]
+%D \setupTABLE[offset=overlay]
+%D \setupTABLE[c][1][width=\rightmarginwidth]
+%D \bTABLE
+%D \bTR
+%D \bTD[nx=3] \pagearea[header][text][middle] \eTD
+%D \eTR
+%D \bTR
+%D \bTD \pagearea[text][margin][left] \eTD
+%D \bTD[nx=2] \pagearea[text] \eTD
+%D \eTR
+%D \bTR
+%D \bTD[nx=3,offset=overlay]
+%D {\bTABLE[width=.5\hsize]
+%D \bTR
+%D \bTD \pagearea[bottom][text][right] \eTD
+%D \bTD \pagearea[footer][text][right] \eTD
+%D \eTR
+%D \eTABLE}
+%D \eTD
+%D \eTR
+%D \eTABLE
+%D \stoppagelayout
+%D
+%D \setupcolors[state=start]
+%D
+%D \setupbackgrounds[text][background=color,backgroundcolor=blue]
+%D \setupbackgrounds[header][text][background=color,backgroundcolor=red]
+%D
+%D \setuppagenumbering[alternative=doublesided,location=]
+%D
+%D \setuplayout[method=makeup]
+%D
+%D \definetextbackground
+%D [test]
+%D [state=start,
+%D background=color,
+%D backgroundcolor=yellow]
+%D
+%D \starttext
+%D
+%D \dorecurse{10}{\input tufte \par}
+%D
+%D \input tufte \starttest \input tufte \stoptest \input tufte
+%D
+%D \starttabulate
+%D \NC test \NC \starttest \input tufte \stoptest \NC \NR
+%D \stoptabulate
+%D
+%D \dorecurse{10}{\input tufte \par}
+%D
+%D \stoptext
+%D \stoptyping
+
+\unprotect
+
+\setvalue{\??ly\c!method\v!makeup}#1#2%
+ {\setbox\pagebox\hbox
+ {\vbox to \textheight
+ {\offinterlineskip
+ % optie
+ \vskip\dimexpr-1\topskip+\strutheight\relax
+ %
+ \textwidth\makeupwidth
+ \hsize\textwidth
+ \boxmaxdepth\maxdepth
+ \noindent
+ \dopagecontents#1#2}}%
+ \wd\pagebox\makeupwidth
+ \ht\pagebox\textheight
+ \dp\pagebox\zeropoint
+ \hsize\paperwidth
+ \vsize\paperheight
+ \setbox\pagebox\vbox
+ {\doifbothsidesoverruled
+ {\let\!!stringa\v!page}
+ {\let\!!stringa\v!rightpage}
+ {\let\!!stringa\v!leftpage}%
+ \getvalue{\??ly\c!method:\!!stringa}}%
+ \wd\pagebox\paperwidth
+ \ht\pagebox\paperheight
+ \dp\pagebox\zeropoint}
+
+\newbox\pageareabox
+
+\def\pagearea
+ {\dotripleempty\dopagearea}
+
+\def\dopagearea[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#3}\v!left
+ {\dodopagearea{#1}{#2}\c!lefttext}
+ {\doifelse{#3}\v!right
+ {\dodopagearea{#1}{#2}\c!righttext}
+ {\dodopagearea{#1}{#2}\c!middletext}}%
+ \else\ifsecondargument
+ \doifbothsidesoverruled
+ {\dodopagearea{#1}{#2}\c!righttext}
+ {\dodopagearea{#1}{#2}\c!righttext}
+ {\dodopagearea{#1}{#2}\c!lefttext }%
+ \else
+ \doif{#1}\v!text % copy due to trial runs in TABLE
+ {\iftrialtypesetting
+ \copy\pagebox
+ \else
+ \localpositioningfalse
+ \addtextbackground\pagebox
+ \addtextgridlayer\pagebox
+ \box\pagebox
+ \fi}%
+ \fi\fi}
+
+\def\dodopagearea#1#2#3%
+ {\setbox\pageareabox\vbox{\getvalue{\??tk#1#2#3}}%
+ \ifsomebackgroundfound{#1#2}%
+ \iftrialtypesetting
+ \box\pageareabox
+ \else
+ \localframed
+ [\??ma#1#2]
+ [\c!width=\wd\pageareabox,
+ \c!height=\ht\pageareabox,
+ \c!offset=\v!overlay]
+ {\box\pageareabox}%
+ \fi
+ \else
+ \box\pageareabox
+ \fi}
+
+\setvalue{\??ly\c!method:\v!leftpage }{\getvalue{\??ly\c!method:\v!page}}
+\setvalue{\??ly\c!method:\v!rightpage}{\getvalue{\??ly\c!method:\v!page}}
+
+% \long\unexpanded\def\startpagelayout[#1]#2\stoppagelayout
+% {\long\setvalue{\??ly\c!method:#1}{#2}}
+
+\long\unexpanded\def\startpagelayout
+ {\bgroup\catcode`\^^M=\@@ignore\dostartpagelayout}
+
+\long\def\dostartpagelayout[#1]#2\stoppagelayout
+ {\egroup\long\setvalue{\??ly\c!method:#1}{#2}}
+
+\protect \endinput
diff --git a/tex/context/base/page-run.mkii b/tex/context/base/page-run.mkii
new file mode 100644
index 000000000..ae5af81e9
--- /dev/null
+++ b/tex/context/base/page-run.mkii
@@ -0,0 +1,382 @@
+%D \module
+%D [ file=page-run,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Runtime Macros}
+
+\unprotect
+
+\gdef\doshowprint[#1][#2][#3]%
+ {\framed
+ [\c!offset=\v!overlay,
+ \c!strut=\v!no]
+ {\forgetall
+ \dontcomplain
+ \globaldefs\minusone
+ \dimen0\pagegoal
+ \definepapersize[X][\c!width=4em, \c!height=6em]%
+ \definepapersize[Y][\c!width=12em,\c!height=14em]%
+ \setuppapersize[#1,X][#2,Y]%
+ \setuplayout[#3]%
+ \setbox0\vbox
+ {\framed
+ [\c!offset=\v!overlay,\c!strut=\v!no,
+ \c!width=\paperwidth,\c!height=\paperheight]
+ {\ss ABC\par DEF}}%
+ \doublesidedfalse
+ \def\cutmarklength{.5em}%
+ \addpagecutmarks0%
+ \replicatepagebox0%
+ \scalepagebox0%
+ \mirrorpaperbox0%
+ \orientpaperbox0%
+ \centerpagebox0%
+ \mirrorprintbox0%
+ \orientprintbox0%
+ \offsetprintbox0%
+ \pagegoal\dimen0
+ \box0}}
+
+\gdef\showprint
+ {\dotripleempty\doshowprint}
+
+% \switchnaarkorps[8pt]
+%
+% \startcombinatie[4*4]
+% {\toonprint} {\strut}
+% {\toonprint[][][plaats=midden]} {\type{plaats=midden}}
+% {\toonprint[][][plaats=midden,markering=aan]} {\type{markering=aan}\break
+% \type{plaats=midden}}
+% {\toonprint[][][plaats=midden,markering=aan,nx=2]} {\type{markering=aan}\break
+% \type{plaats=midden}\break
+% \type{nx=2}}
+% {\toonprint[][][plaats=links]} {\type{plaats=links}}
+% {\toonprint[][][plaats=rechts]} {\type{plaats=rechts}}
+% {\toonprint[][][plaats={links,onder}]} {\type{plaats={links,onder}}}
+% {\toonprint[][][plaats={rechts,onder}]} {\type{plaats={rechts,onder}}}
+% {\toonprint[][][nx=2,ny=1]} {\type{nx=2,ny=1}}
+% {\toonprint[][][nx=1,ny=2]} {\type{nx=1,ny=2}}
+% {\toonprint[][][nx=2,ny=2]} {\type{nx=2,ny=2}}
+% {\toonprint[][][nx=2,ny=2,plaats=midden]} {\type{nx=2,ny=2}\break
+% \type{plaats=midden}}
+% {\toonprint[][][rugoffset=3pt]} {\type{rugoffset=.5cm}}
+% {\toonprint[][][kopoffset=3pt]} {\type{kopoffset=.5cm}}
+% {\toonprint[][][schaal=1.5]} {\type{schaal=1.5}}
+% {\toonprint[][][schaal=0.8]} {\type{schaal=0.8}}
+% \stopcombinatie
+%
+% \startcombinatie[3*4]
+% {\toonprint[liggend][][plaats=midden]} {\type{liggend}}
+% {\toonprint[][liggend][plaats=midden]} {\strut\break\type{liggend}}
+% {\toonprint[liggend][liggend][plaats=midden]} {\type{liggend}\break\type{liggend}}
+% {\toonprint[90][][plaats=midden]} {\type{90}}
+% {\toonprint[][90][plaats=midden]} {\strut\break\type{90}}
+% {\toonprint[90][90][plaats=midden]} {\type{90}\break\type{90}}
+% {\toonprint[180][][plaats=midden]} {\type{180}}
+% {\toonprint[][180][plaats=midden]} {\strut\break\type{180}}
+% {\toonprint[180][180][plaats=midden]} {\type{180}\break\type{180}}
+% {\toonprint[gespiegeld][][plaats=midden]} {\type{gespiegeld}}
+% {\toonprint[][gespiegeld][plaats=midden]} {\strut\break\type{gespiegeld}}
+% {\toonprint[gespiegeld][gespiegeld][plaats=midden]} {\type{gespiegeld}\break\type{gespiegeld}}
+% \stopcombinatie
+
+\gdef\doshowframe[#1][#2]%
+ {\ifsecondargument
+ \setupbackgrounds
+ [\v!page]
+ [\c!frame=\v!on,
+ \c!corner=\v!rectangular,
+ \c!frameoffset=\!!zeropoint,
+ \c!framedepth=\!!zeropoint,
+ \c!framecolor=layout:page]
+ \setupbackgrounds
+ [#1][#2]
+ [\c!background=,
+ \c!frame=\v!on,
+ \c!corner=\v!rectangular,
+ \c!frameoffset=\!!zeropoint,
+ \c!framedepth=\!!zeropoint,
+ \c!framecolor=]
+ \else\iffirstargument
+ \showframe
+ [\v!header,\v!text,\v!footer]
+ [#1]
+ \else
+ \showframe
+ [\v!header,\v!text,\v!footer]
+ [\v!leftedge,\v!leftmargin,
+ \v!text,
+ \v!rightmargin,\v!rightedge]
+ \fi\fi
+ \setupbackgrounds
+ [\c!state=\v!repeat]}
+
+\gdef\showframe{\dodoubleempty\doshowframe}
+
+\gdef\showsetupA#1#2%
+ {#1&\PtToCm{\the#2}&\the#2&\tttf\string#2\cr}
+
+\gdef\showsetupB#1#2#3%
+ {#1&\tttf\string#3\cr}
+
+% \startinterface english % english is fallback
+
+\gdef\showsetups
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{paperheight} \paperheight
+ \showsetupA{paperwidth} \paperwidth
+ \showsetupA{printpaperheight} \printpaperheight
+ \showsetupA{printpaperwidth} \printpaperwidth
+ \showsetupA{topspace} \topspace
+ \showsetupA{backspace} \backspace
+ \showsetupA{height} \makeupheight
+ \showsetupA{width} \makeupwidth
+ \showsetupA{top} \topheight
+ \showsetupA{topdistance} \topdistance
+ \showsetupA{header} \headerheight
+ \showsetupA{headerdistance} \headerdistance
+ \showsetupA{textheight} \textheight
+ \showsetupA{footerdistance} \footerdistance
+ \showsetupA{footer} \footerheight
+ \showsetupA{bottomdistance} \bottomdistance
+ \showsetupA{bottom} \bottomheight
+ \showsetupA{leftedge} \leftedgewidth
+ \showsetupA{leftedgedistance} \leftedgedistance
+ \showsetupA{leftmargin} \leftmarginwidth
+ \showsetupA{leftmargindistance} \leftmargindistance
+ \showsetupA{textwidth} \textwidth
+ \showsetupA{rightmargindistance}\rightmargindistance
+ \showsetupA{rightmargin} \rightmarginwidth
+ \showsetupA{rightedgedistance} \rightedgedistance
+ \showsetupA{rightedge} \rightedgewidth
+ \showsetupB{bodyfontsize} \the \globalbodyfontsize
+ \showsetupB{line} \relax \normallineheight
+ \showsetupB{height} \relax \strutheightfactor
+ \showsetupB{depth} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+% \stopinterface
+
+\startinterface dutch
+
+\gdef\showsetups
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{papierhoogte} \papierhoogte
+ \showsetupA{papierbreedte} \papierbreedte
+ \showsetupA{printpapierhoogte} \printpapierhoogte
+ \showsetupA{printpapierbreedte} \printpapierbreedte
+ \showsetupA{kopwit} \kopwit
+ \showsetupA{rugwit} \rugwit
+ \showsetupA{snijwit} \snijwit
+ \showsetupA{hoogte} \zethoogte
+ \showsetupA{breedte} \zetbreedte
+ \showsetupA{boven} \bovenhoogte
+ \showsetupA{bovenafstand} \bovenafstand
+ \showsetupA{hoofd} \hoofdhoogte
+ \showsetupA{hoofdafstand} \hoofdafstand
+ \showsetupA{teksthoogte} \teksthoogte
+ \showsetupA{voetafstand} \voetafstand
+ \showsetupA{voet} \voethoogte
+ \showsetupA{onderafstand} \onderafstand
+ \showsetupA{onder} \onderhoogte
+ \showsetupA{linkerrand} \linkerrandbreedte
+ \showsetupA{linkerrandafstand} \linkerrandafstand
+ \showsetupA{linkermarge} \linkermargebreedte
+ \showsetupA{linkermargeafstand} \linkermargeafstand
+ \showsetupA{tekstbreedte} \tekstbreedte
+ \showsetupA{rechtermargeafstand}\rechtermargeafstand
+ \showsetupA{rechtermarge} \rechtermargebreedte
+ \showsetupA{rechterrandafstand} \rechterrandafstand
+ \showsetupA{rechterrand} \rechterrandbreedte
+ \showsetupB{korps} \the \globalbodyfontsize
+ \showsetupB{regel} \relax \normallineheight
+ \showsetupB{hoogte} \relax \strutheightfactor
+ \showsetupB{diepte} \relax \strutdepthfactor
+ \showsetupB{boven} \relax \topskipfactor
+ \showsetupB{onder} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+% todo: \showsetupA{rugwit} \rugwit
+
+\startinterface german
+
+\gdef\showsetups%
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{papierhoehe} \papierhoehe
+ \showsetupA{papierbreite} \papierbreite
+ \showsetupA{printpapierhoehe} \printpapierhoehe
+ \showsetupA{printpapierbreite} \printpapierbreite
+ \showsetupA{kopfweite} \kopfweite
+ \showsetupA{rumpfweite} \rumpfweite
+ \showsetupA{hoehe} \satzhoehe
+ \showsetupA{breite} \satzbreite
+ \showsetupA{oben} \hoeheoben
+ \showsetupA{abstandoben} \abstandoben
+ \showsetupA{kopfzeile} \kopfzeilenhoehe
+ \showsetupA{kopfzeilenabstand} \kopfzeilenabstand
+ \showsetupA{texthoehe} \texthoehe
+ \showsetupA{fusszeileabstand} \fusszeileabstand
+ \showsetupA{fusszeilen} \fusszeilenhoehe
+ \showsetupA{abstandunten} \abstandunten
+ \showsetupA{hoeheunten} \hoeheunten
+ \showsetupA{linkerrand} \breitelinkerrand
+ \showsetupA{abstandlinkerrand} \abstandlinkerrand
+ \showsetupA{linkemarginal} \linkemarginalbreite
+ \showsetupA{linkemarginalafstand} \linkemarginalafstand
+ \showsetupA{textbreite} \textbreite
+ \showsetupA{rechtemarginalafstand}\rechtemarginalafstand
+ \showsetupA{rechtemarginal} \rechtemarginalbreite
+ \showsetupA{abstandrechterrand} \abstandrechterrand
+ \showsetupA{rechterrand} \breiterechterrand
+ \showsetupB{fliesstext} \the \globalbodyfontsize
+ \showsetupB{linie} \relax \normallineheight
+ \showsetupB{hoehe} \relax \strutheightfactor
+ \showsetupB{tiefe} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+\startinterface czech
+
+\gdef\showsetups%
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{vyskapapiru} \vyskapapiru
+ \showsetupA{sirkapapiru} \sirkapapiru
+ \showsetupA{vyskatiskpapiru} \vyskatiskpapiru
+ \showsetupA{sirkatiskpapiru} \sirkatiskpapiru
+ \showsetupA{hornimezera} \hornimezera
+ \showsetupA{spodnimezera} \spodnimezera
+ \showsetupA{vyska} \vyskasazby
+ \showsetupA{breite} \sirkasazby
+ \showsetupA{vyskatextu} \vyskatextu
+ \showsetupA{sirkatextu} \sirkatextu
+ \showsetupA{horejsek} \vyskahorejsku
+ \showsetupA{vzdalenosthorejsku} \vzdalenosthorejsku
+ \showsetupA{zahlavi} \vyskazahlavi
+ \showsetupA{vzdalenostzahlavi} \vzdalenostzahlavi
+ \showsetupA{fusszeileabstand} \vzdalenostupati
+ \showsetupA{upati} \vyskaupati
+ \showsetupA{vzdalenostspodku} \vzdalenostspodku
+ \showsetupA{spodek} \vyakaspodku
+ \showsetupA{levyokraj} \sirkalevehookraje
+ \showsetupA{vzdalenostlevehookraje} \vzdalenostlevehookraje
+ \showsetupA{levamarginalie} \sirkalevemarginalie
+ \showsetupA{vzdalenostlevemarginalie} \vzdalenostlevemarginalie
+ \showsetupA{vzdalenostpravemarginalie}\vzdalenostpravemarginalie
+ \showsetupA{pravamarginalie} \sirkapravemarginalie
+ \showsetupA{vzdalenostpravehookraje} \vzdalenostpravehookraje
+ \showsetupA{pravyokraj} \sirkapravehookraje
+ \showsetupB{zakladnivelikost} \the \globalbodyfontsize
+ \showsetupB{linka} \relax \normallineheight
+ \showsetupB{vyska} \relax \strutheightfactor
+ \showsetupB{hloubka} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+\startinterface romanian
+
+\gdef\showsetups%
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{paperheight} \paperheight
+ \showsetupA{paperwidth} \paperwidth
+ \showsetupA{printpaperheight} \printpaperheight
+ \showsetupA{printpaperwidth} \printpaperwidth
+ \showsetupA{topspace} \topspace
+ \showsetupA{backspace} \backspace
+ \showsetupA{height} \makeupheight
+ \showsetupA{width} \makeupwidth
+ \showsetupA{top} \topheight
+ \showsetupA{topdistance} \topdistance
+ \showsetupA{header} \headerheight
+ \showsetupA{headerdistance} \headerdistance
+ \showsetupA{textheight} \textheight
+ \showsetupA{footerdistance} \footerdistance
+ \showsetupA{footer} \footerheight
+ \showsetupA{bottomdistance} \bottomdistance
+ \showsetupA{bottom} \bottomheight
+ \showsetupA{leftedge} \leftedgewidth
+ \showsetupA{leftedgedistance} \leftedgedistance
+ \showsetupA{leftmargin} \leftmarginwidth
+ \showsetupA{leftmargindistance} \leftmargindistance
+ \showsetupA{textwidth} \textwidth
+ \showsetupA{rightmargindistance}\rightmargindistance
+ \showsetupA{rightmargin} \rightmarginwidth
+ \showsetupA{rightedgedistance} \rightedgedistance
+ \showsetupA{rightedge} \rightedgewidth
+ \showsetupB{bodyfontsize} \the \globalbodyfontsize
+ \showsetupB{line} \relax \normallineheight
+ \showsetupB{height} \relax \strutheightfactor
+ \showsetupB{depth} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+\gdef\showlayout % interfereert lelijk met een \typefile er na
+ {\bgroup
+ \page
+ \showframe
+ \setuplayout[\c!marking=\v!on]
+ \dorecurse{4}{\showsetups\page}
+ \egroup}
+
+\gdef\showmargins
+ {\starttabulate
+ \NC asynchrone \NC \doifoddpageelse {odd} {even} \NC \NR
+ \NC synchrone \NC \doifrightpageelse {right} {left} \NC \NR
+ \NC right margin \NC \the\rightmarginwidth \NC \NR
+ \NC left margin \NC \the\leftmarginwidth \NC \NR
+ \NC outer margin \NC \the\outermarginwidth \NC \NR
+ \NC inner margin \NC \the\innermarginwidth \NC \NR
+ \stoptabulate}
+
+\protect \endinput
diff --git a/tex/context/base/page-run.mkiv b/tex/context/base/page-run.mkiv
new file mode 100644
index 000000000..ae5af81e9
--- /dev/null
+++ b/tex/context/base/page-run.mkiv
@@ -0,0 +1,382 @@
+%D \module
+%D [ file=page-run,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Runtime Macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Runtime Macros}
+
+\unprotect
+
+\gdef\doshowprint[#1][#2][#3]%
+ {\framed
+ [\c!offset=\v!overlay,
+ \c!strut=\v!no]
+ {\forgetall
+ \dontcomplain
+ \globaldefs\minusone
+ \dimen0\pagegoal
+ \definepapersize[X][\c!width=4em, \c!height=6em]%
+ \definepapersize[Y][\c!width=12em,\c!height=14em]%
+ \setuppapersize[#1,X][#2,Y]%
+ \setuplayout[#3]%
+ \setbox0\vbox
+ {\framed
+ [\c!offset=\v!overlay,\c!strut=\v!no,
+ \c!width=\paperwidth,\c!height=\paperheight]
+ {\ss ABC\par DEF}}%
+ \doublesidedfalse
+ \def\cutmarklength{.5em}%
+ \addpagecutmarks0%
+ \replicatepagebox0%
+ \scalepagebox0%
+ \mirrorpaperbox0%
+ \orientpaperbox0%
+ \centerpagebox0%
+ \mirrorprintbox0%
+ \orientprintbox0%
+ \offsetprintbox0%
+ \pagegoal\dimen0
+ \box0}}
+
+\gdef\showprint
+ {\dotripleempty\doshowprint}
+
+% \switchnaarkorps[8pt]
+%
+% \startcombinatie[4*4]
+% {\toonprint} {\strut}
+% {\toonprint[][][plaats=midden]} {\type{plaats=midden}}
+% {\toonprint[][][plaats=midden,markering=aan]} {\type{markering=aan}\break
+% \type{plaats=midden}}
+% {\toonprint[][][plaats=midden,markering=aan,nx=2]} {\type{markering=aan}\break
+% \type{plaats=midden}\break
+% \type{nx=2}}
+% {\toonprint[][][plaats=links]} {\type{plaats=links}}
+% {\toonprint[][][plaats=rechts]} {\type{plaats=rechts}}
+% {\toonprint[][][plaats={links,onder}]} {\type{plaats={links,onder}}}
+% {\toonprint[][][plaats={rechts,onder}]} {\type{plaats={rechts,onder}}}
+% {\toonprint[][][nx=2,ny=1]} {\type{nx=2,ny=1}}
+% {\toonprint[][][nx=1,ny=2]} {\type{nx=1,ny=2}}
+% {\toonprint[][][nx=2,ny=2]} {\type{nx=2,ny=2}}
+% {\toonprint[][][nx=2,ny=2,plaats=midden]} {\type{nx=2,ny=2}\break
+% \type{plaats=midden}}
+% {\toonprint[][][rugoffset=3pt]} {\type{rugoffset=.5cm}}
+% {\toonprint[][][kopoffset=3pt]} {\type{kopoffset=.5cm}}
+% {\toonprint[][][schaal=1.5]} {\type{schaal=1.5}}
+% {\toonprint[][][schaal=0.8]} {\type{schaal=0.8}}
+% \stopcombinatie
+%
+% \startcombinatie[3*4]
+% {\toonprint[liggend][][plaats=midden]} {\type{liggend}}
+% {\toonprint[][liggend][plaats=midden]} {\strut\break\type{liggend}}
+% {\toonprint[liggend][liggend][plaats=midden]} {\type{liggend}\break\type{liggend}}
+% {\toonprint[90][][plaats=midden]} {\type{90}}
+% {\toonprint[][90][plaats=midden]} {\strut\break\type{90}}
+% {\toonprint[90][90][plaats=midden]} {\type{90}\break\type{90}}
+% {\toonprint[180][][plaats=midden]} {\type{180}}
+% {\toonprint[][180][plaats=midden]} {\strut\break\type{180}}
+% {\toonprint[180][180][plaats=midden]} {\type{180}\break\type{180}}
+% {\toonprint[gespiegeld][][plaats=midden]} {\type{gespiegeld}}
+% {\toonprint[][gespiegeld][plaats=midden]} {\strut\break\type{gespiegeld}}
+% {\toonprint[gespiegeld][gespiegeld][plaats=midden]} {\type{gespiegeld}\break\type{gespiegeld}}
+% \stopcombinatie
+
+\gdef\doshowframe[#1][#2]%
+ {\ifsecondargument
+ \setupbackgrounds
+ [\v!page]
+ [\c!frame=\v!on,
+ \c!corner=\v!rectangular,
+ \c!frameoffset=\!!zeropoint,
+ \c!framedepth=\!!zeropoint,
+ \c!framecolor=layout:page]
+ \setupbackgrounds
+ [#1][#2]
+ [\c!background=,
+ \c!frame=\v!on,
+ \c!corner=\v!rectangular,
+ \c!frameoffset=\!!zeropoint,
+ \c!framedepth=\!!zeropoint,
+ \c!framecolor=]
+ \else\iffirstargument
+ \showframe
+ [\v!header,\v!text,\v!footer]
+ [#1]
+ \else
+ \showframe
+ [\v!header,\v!text,\v!footer]
+ [\v!leftedge,\v!leftmargin,
+ \v!text,
+ \v!rightmargin,\v!rightedge]
+ \fi\fi
+ \setupbackgrounds
+ [\c!state=\v!repeat]}
+
+\gdef\showframe{\dodoubleempty\doshowframe}
+
+\gdef\showsetupA#1#2%
+ {#1&\PtToCm{\the#2}&\the#2&\tttf\string#2\cr}
+
+\gdef\showsetupB#1#2#3%
+ {#1&\tttf\string#3\cr}
+
+% \startinterface english % english is fallback
+
+\gdef\showsetups
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{paperheight} \paperheight
+ \showsetupA{paperwidth} \paperwidth
+ \showsetupA{printpaperheight} \printpaperheight
+ \showsetupA{printpaperwidth} \printpaperwidth
+ \showsetupA{topspace} \topspace
+ \showsetupA{backspace} \backspace
+ \showsetupA{height} \makeupheight
+ \showsetupA{width} \makeupwidth
+ \showsetupA{top} \topheight
+ \showsetupA{topdistance} \topdistance
+ \showsetupA{header} \headerheight
+ \showsetupA{headerdistance} \headerdistance
+ \showsetupA{textheight} \textheight
+ \showsetupA{footerdistance} \footerdistance
+ \showsetupA{footer} \footerheight
+ \showsetupA{bottomdistance} \bottomdistance
+ \showsetupA{bottom} \bottomheight
+ \showsetupA{leftedge} \leftedgewidth
+ \showsetupA{leftedgedistance} \leftedgedistance
+ \showsetupA{leftmargin} \leftmarginwidth
+ \showsetupA{leftmargindistance} \leftmargindistance
+ \showsetupA{textwidth} \textwidth
+ \showsetupA{rightmargindistance}\rightmargindistance
+ \showsetupA{rightmargin} \rightmarginwidth
+ \showsetupA{rightedgedistance} \rightedgedistance
+ \showsetupA{rightedge} \rightedgewidth
+ \showsetupB{bodyfontsize} \the \globalbodyfontsize
+ \showsetupB{line} \relax \normallineheight
+ \showsetupB{height} \relax \strutheightfactor
+ \showsetupB{depth} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+% \stopinterface
+
+\startinterface dutch
+
+\gdef\showsetups
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{papierhoogte} \papierhoogte
+ \showsetupA{papierbreedte} \papierbreedte
+ \showsetupA{printpapierhoogte} \printpapierhoogte
+ \showsetupA{printpapierbreedte} \printpapierbreedte
+ \showsetupA{kopwit} \kopwit
+ \showsetupA{rugwit} \rugwit
+ \showsetupA{snijwit} \snijwit
+ \showsetupA{hoogte} \zethoogte
+ \showsetupA{breedte} \zetbreedte
+ \showsetupA{boven} \bovenhoogte
+ \showsetupA{bovenafstand} \bovenafstand
+ \showsetupA{hoofd} \hoofdhoogte
+ \showsetupA{hoofdafstand} \hoofdafstand
+ \showsetupA{teksthoogte} \teksthoogte
+ \showsetupA{voetafstand} \voetafstand
+ \showsetupA{voet} \voethoogte
+ \showsetupA{onderafstand} \onderafstand
+ \showsetupA{onder} \onderhoogte
+ \showsetupA{linkerrand} \linkerrandbreedte
+ \showsetupA{linkerrandafstand} \linkerrandafstand
+ \showsetupA{linkermarge} \linkermargebreedte
+ \showsetupA{linkermargeafstand} \linkermargeafstand
+ \showsetupA{tekstbreedte} \tekstbreedte
+ \showsetupA{rechtermargeafstand}\rechtermargeafstand
+ \showsetupA{rechtermarge} \rechtermargebreedte
+ \showsetupA{rechterrandafstand} \rechterrandafstand
+ \showsetupA{rechterrand} \rechterrandbreedte
+ \showsetupB{korps} \the \globalbodyfontsize
+ \showsetupB{regel} \relax \normallineheight
+ \showsetupB{hoogte} \relax \strutheightfactor
+ \showsetupB{diepte} \relax \strutdepthfactor
+ \showsetupB{boven} \relax \topskipfactor
+ \showsetupB{onder} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+% todo: \showsetupA{rugwit} \rugwit
+
+\startinterface german
+
+\gdef\showsetups%
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{papierhoehe} \papierhoehe
+ \showsetupA{papierbreite} \papierbreite
+ \showsetupA{printpapierhoehe} \printpapierhoehe
+ \showsetupA{printpapierbreite} \printpapierbreite
+ \showsetupA{kopfweite} \kopfweite
+ \showsetupA{rumpfweite} \rumpfweite
+ \showsetupA{hoehe} \satzhoehe
+ \showsetupA{breite} \satzbreite
+ \showsetupA{oben} \hoeheoben
+ \showsetupA{abstandoben} \abstandoben
+ \showsetupA{kopfzeile} \kopfzeilenhoehe
+ \showsetupA{kopfzeilenabstand} \kopfzeilenabstand
+ \showsetupA{texthoehe} \texthoehe
+ \showsetupA{fusszeileabstand} \fusszeileabstand
+ \showsetupA{fusszeilen} \fusszeilenhoehe
+ \showsetupA{abstandunten} \abstandunten
+ \showsetupA{hoeheunten} \hoeheunten
+ \showsetupA{linkerrand} \breitelinkerrand
+ \showsetupA{abstandlinkerrand} \abstandlinkerrand
+ \showsetupA{linkemarginal} \linkemarginalbreite
+ \showsetupA{linkemarginalafstand} \linkemarginalafstand
+ \showsetupA{textbreite} \textbreite
+ \showsetupA{rechtemarginalafstand}\rechtemarginalafstand
+ \showsetupA{rechtemarginal} \rechtemarginalbreite
+ \showsetupA{abstandrechterrand} \abstandrechterrand
+ \showsetupA{rechterrand} \breiterechterrand
+ \showsetupB{fliesstext} \the \globalbodyfontsize
+ \showsetupB{linie} \relax \normallineheight
+ \showsetupB{hoehe} \relax \strutheightfactor
+ \showsetupB{tiefe} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+\startinterface czech
+
+\gdef\showsetups%
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{vyskapapiru} \vyskapapiru
+ \showsetupA{sirkapapiru} \sirkapapiru
+ \showsetupA{vyskatiskpapiru} \vyskatiskpapiru
+ \showsetupA{sirkatiskpapiru} \sirkatiskpapiru
+ \showsetupA{hornimezera} \hornimezera
+ \showsetupA{spodnimezera} \spodnimezera
+ \showsetupA{vyska} \vyskasazby
+ \showsetupA{breite} \sirkasazby
+ \showsetupA{vyskatextu} \vyskatextu
+ \showsetupA{sirkatextu} \sirkatextu
+ \showsetupA{horejsek} \vyskahorejsku
+ \showsetupA{vzdalenosthorejsku} \vzdalenosthorejsku
+ \showsetupA{zahlavi} \vyskazahlavi
+ \showsetupA{vzdalenostzahlavi} \vzdalenostzahlavi
+ \showsetupA{fusszeileabstand} \vzdalenostupati
+ \showsetupA{upati} \vyskaupati
+ \showsetupA{vzdalenostspodku} \vzdalenostspodku
+ \showsetupA{spodek} \vyakaspodku
+ \showsetupA{levyokraj} \sirkalevehookraje
+ \showsetupA{vzdalenostlevehookraje} \vzdalenostlevehookraje
+ \showsetupA{levamarginalie} \sirkalevemarginalie
+ \showsetupA{vzdalenostlevemarginalie} \vzdalenostlevemarginalie
+ \showsetupA{vzdalenostpravemarginalie}\vzdalenostpravemarginalie
+ \showsetupA{pravamarginalie} \sirkapravemarginalie
+ \showsetupA{vzdalenostpravehookraje} \vzdalenostpravehookraje
+ \showsetupA{pravyokraj} \sirkapravehookraje
+ \showsetupB{zakladnivelikost} \the \globalbodyfontsize
+ \showsetupB{linka} \relax \normallineheight
+ \showsetupB{vyska} \relax \strutheightfactor
+ \showsetupB{hloubka} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+\startinterface romanian
+
+\gdef\showsetups%
+ {\noindent
+ \vbox
+ {\forgetall
+ \dontcomplain
+ \switchtobodyfont[\v!small]
+ \tabskip\zeropoint
+ \halign
+ {\strut##\quad\hss#\quad\hss#\quad\hss#\hss\cr
+ \showsetupA{paperheight} \paperheight
+ \showsetupA{paperwidth} \paperwidth
+ \showsetupA{printpaperheight} \printpaperheight
+ \showsetupA{printpaperwidth} \printpaperwidth
+ \showsetupA{topspace} \topspace
+ \showsetupA{backspace} \backspace
+ \showsetupA{height} \makeupheight
+ \showsetupA{width} \makeupwidth
+ \showsetupA{top} \topheight
+ \showsetupA{topdistance} \topdistance
+ \showsetupA{header} \headerheight
+ \showsetupA{headerdistance} \headerdistance
+ \showsetupA{textheight} \textheight
+ \showsetupA{footerdistance} \footerdistance
+ \showsetupA{footer} \footerheight
+ \showsetupA{bottomdistance} \bottomdistance
+ \showsetupA{bottom} \bottomheight
+ \showsetupA{leftedge} \leftedgewidth
+ \showsetupA{leftedgedistance} \leftedgedistance
+ \showsetupA{leftmargin} \leftmarginwidth
+ \showsetupA{leftmargindistance} \leftmargindistance
+ \showsetupA{textwidth} \textwidth
+ \showsetupA{rightmargindistance}\rightmargindistance
+ \showsetupA{rightmargin} \rightmarginwidth
+ \showsetupA{rightedgedistance} \rightedgedistance
+ \showsetupA{rightedge} \rightedgewidth
+ \showsetupB{bodyfontsize} \the \globalbodyfontsize
+ \showsetupB{line} \relax \normallineheight
+ \showsetupB{height} \relax \strutheightfactor
+ \showsetupB{depth} \relax \strutdepthfactor
+ \showsetupB{topskip} \relax \topskipfactor
+ \showsetupB{maxdepth} \relax \maxdepthfactor}}}
+
+\stopinterface
+
+\gdef\showlayout % interfereert lelijk met een \typefile er na
+ {\bgroup
+ \page
+ \showframe
+ \setuplayout[\c!marking=\v!on]
+ \dorecurse{4}{\showsetups\page}
+ \egroup}
+
+\gdef\showmargins
+ {\starttabulate
+ \NC asynchrone \NC \doifoddpageelse {odd} {even} \NC \NR
+ \NC synchrone \NC \doifrightpageelse {right} {left} \NC \NR
+ \NC right margin \NC \the\rightmarginwidth \NC \NR
+ \NC left margin \NC \the\leftmarginwidth \NC \NR
+ \NC outer margin \NC \the\outermarginwidth \NC \NR
+ \NC inner margin \NC \the\innermarginwidth \NC \NR
+ \stoptabulate}
+
+\protect \endinput
diff --git a/tex/context/base/page-set.mkii b/tex/context/base/page-set.mkii
new file mode 100644
index 000000000..eb01799ae
--- /dev/null
+++ b/tex/context/base/page-set.mkii
@@ -0,0 +1,2766 @@
+%D \module
+%D [ file=page-set,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Column Sets,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% getnoflines vs getrawnoflines
+
+% some day: cleanup and go etex
+
+\writestatus{loading}{ConTeXt Page Macros / Column Sets}
+
+% todo : last longer than previous
+% todo : block span over last column if footnotes
+% todo : diagnosis balancing run
+% todo : separate footnote placement
+% todo : go on on same page with colset
+% todo : test page areas per page
+% todo : leftmargin/rightmargin (better than afstand(1))
+
+% use the OTRSET layer for more purposes, like the footnotes !
+
+\unprotect
+
+\newcount\tofcolumns % total
+\newcount\lofcolumns % left
+\newcount\rofcolumns % right
+
+\newcount\columnfirstcell \columnfirstcell=1
+\newcount\columnlastcell
+\newcount\columnfreecells
+\newcount\currenthcell
+\newcount\currentvcell
+\newcount\columnhcells
+\newcount\columnvcells
+
+\newif\ifenoughcolumncells
+\newif\ifsomefreecolumncells
+\newif\ifcolumnspread
+\newif\iftracecolumnset % \tracecolumnsettrue
+
+\def\columnmaxcells {75} % runtime
+\def\columnmaxfreecells {0} % runtime
+\def\columngaplimit {0} % {5}
+
+\def\@otr@{otr}
+
+\def\OTRSETmakeupwidth{\innermakeupwidth}
+
+\let\OTRSETflushsidefloats \forgetsidefloats % \relax
+\let\OTRSETsynchronizesidefloats\forgetsidefloats % \relax
+
+\def\OTRSETgridcell #1#2{\csname \@otr@:\number#1:\number#2\endcsname}
+\def\OTRSETgetgridcell#1#2{\box\csname \@otr@:\number#1:\number#2\endcsname}
+\def\OTRSETsetgridcell#1#2{\global\setbox\csname\@otr@:\number#1:\number#2\endcsname}
+
+\long\def\OTRSETdoifcellelse#1#2%
+ {\relax\ifvoid\csname\@otr@:\number#1:\number#2\endcsname
+ \@EA\secondoftwoarguments\else\@EA\firstoftwoarguments
+ \fi}
+
+% The following two macros are used to compensate for a switch in body fonts
+% as in:
+%
+% \definecolumnset [two] [n=2,balancing=yes]
+% \definecolumnset [three] [n=3,balancing=yes]
+%
+% \setupcolumnsetlines[two][1][1][7]
+% \setupcolumnsetlines[two][1][2][10]
+%
+% \setupcolumnsetlines[three][1][1][40]
+% \setupcolumnsetlines[three][1][2][40]
+% \setupcolumnsetlines[three][1][3][40]
+%
+% \setupcolumnsetstart[three][1][1][15]
+% \setupcolumnsetstart[three][1][2][20]
+% \setupcolumnsetstart[three][1][3][20]
+%
+% \starttext
+% \startcolumnset [two] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \switchtobodyfont[small]
+% \startcolumnset [three] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \stoptext
+
+%D Marks in columnsets:
+%D
+%D \starttyping
+%D \definemarking[M]
+%D \setupheadertexts[\setups{show-M-marks}]
+%D \definecolumnset[test][n=3]
+%D
+%D \startsetups show-M-marks
+%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][1][last]\quad
+%D \getmarking[M][2][previous]/\getmarking[M][2][first]/\getmarking[M][2][last]\quad
+%D \getmarking[M][3][previous]/\getmarking[M][3][first]/\getmarking[M][3][last]\quad
+%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][last]\quad
+%D \getsavedmarking[M][previous]/\getsavedmarking[M][first]/\getsavedmarking[M][last]
+%D \stopsetups
+%D
+%D \startbuffer
+%D \section{Knuth} [K1]\marking[M]{k1} [K2]\marking[M]{k2} \input knuth
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \stopbuffer
+%D
+%D \startbuffer
+%D \section{Ward} [W]\marking[M]{w} \input ward
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D \section{Davis} [D]\marking[M]{d} \input davis
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \stopbuffer
+%D
+%D \startbuffer
+%D \section{Ward} [W]\marking[M]{w} \input ward
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D \section{Davis} [D]\marking[M]{d} \input davis
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \section{Douglas} [O]\marking[M]{o} \input douglas
+%D \stopbuffer
+%D
+%D \starttext
+%D \startcolumnset[test]
+%D \dorecurse{5}{\getbuffer}
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D % \column % sometimes needed
+%D \stopcolumnset
+%D \stoptext
+%D \stoptyping
+
+% not ok yet, for column sets we need a special case: within a column we
+% need to bubble-up the marks; the indirectness permits overloading here
+
+\let\saveOTRSETmark \refreshsavedmark
+\let\bubbleOTRSETmark\bubblesavedmark
+\let\resetOTRSETmark \resetsavedmark
+\let\presetOTRSETmark\presetsavedmark
+
+\def\doregisterOTRSETmarks#1{\saveOTRSETmark [#1][\number\mofcolumns]}
+\def\dobubbleOTRSETmarks #1{\bubbleOTRSETmark[#1][\number\mofcolumns]}
+\def\doresetOTRSETmarks #1{\resetOTRSETmark [#1][\recurselevel]}
+\def\dopresetOTRSETmarks #1{\presetOTRSETmark[#1][\recurselevel]}
+
+\def\registerOTRSETmarks
+ {\processcommacommand[\alldefinedmarks]\doregisterOTRSETmarks}
+\def\bubbleOTRSETmarks
+ {\processcommacommand[\alldefinedmarks]\dobubbleOTRSETmarks}
+\def\resetOTRSETmarks
+ {\dorecurse\nofcolumns{\processcommacommand[\alldefinedmarks]\doresetOTRSETmarks}}
+\def\presetOTRSETmarks
+ {\dorecurse\nofcolumns{\processcommacommand[\alldefinedmarks]\dopresetOTRSETmarks}}
+
+%D test case of Vit Zika (context list):
+%D
+%D \starttyping
+%D \setuplayout[height=middle,width=middle,grid=yes]
+%D
+%D \starttext
+%D \startcolumnset
+%D \dorecurse{10}
+%D {\input thuan \endgraf
+%D \bgroup
+%D \ss\restoreinterlinespace
+%D \dorecurse{3}{\input hawking \endgraf}
+%D \egroup
+%D \input bryson \endgraf}
+%D \stopcolumnset
+%D \stoptext
+%D \stoptyping
+
+\def\OTRSETsetcorrectnofcells#1%
+ {\bgroup
+ \!!counta#1\relax
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \restoreinterlinespace
+ \else
+ \!!dimena-\!!counta\lineheight
+ \restoreglobalbodyfont % slow, we need a fast one
+ \advance\!!dimena\!!counta\lineheight
+ \getnoflines\!!dimena
+ \advance\!!counta\noflines
+ \ifnum\!!counta<#1\else
+ \!!counta#1\relax
+ \fi
+ \fi
+ \relax % needed ! ! ! ! else lookahead over \fi and \@EA
+ \@EA\egroup\@EA\scratchcounter\the\!!counta\relax}
+
+\def\OTRSETsetcorrectcellht
+ {\bgroup
+ \!!dimena-\strutht\relax
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \restoreinterlinespace
+ \else
+ \restoreglobalbodyfont
+ \fi
+ \advance\!!dimena\strutht
+ \relax % needed ! ! ! ! else lookahead over \fi and \@EA
+ \@EA\egroup\@EA\scratchdimen\the\!!dimena\relax}
+
+\def\columnerasegridboxes % maybe dedicated loops
+ {\bgroup
+ \increment\columnmaxcells\relax
+ \ifodd\realpageno
+ \else % we are on the other page
+ \columnspreadfalse
+ \fi
+ \ifcolumnspread
+ \dorecurse\nofcolumns
+ {\let\!!stringa\recurselevel
+ \scratchcounter\recurselevel \advance\scratchcounter\lofcolumns
+ \edef\!!stringb{\the\scratchcounter}%
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
+ \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
+ \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
+ \box\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \else
+ \emptybox
+ %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox
+ \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \fi
+ \else
+ \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
+ \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
+ \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \else
+ \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \fi
+ \fi}}%
+ \else
+ \dorecurse \tofcolumns
+ {\let\!!stringa\recurselevel
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
+ \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox
+ \else
+ \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
+ \fi}}%
+ \fi
+ \dorecurse\tofcolumns
+ {\global\setbox\csname\@otr@:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}%
+ \global\columnfirstcell\zerocount
+ \global\columnlastcell\columnfirstcell
+ \global\columnfreecells\columnfirstcell
+ \egroup}
+
+\def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data}
+ {\!!countd#2\advance\!!countd#4\advance\!!countd\minusone
+ \!!counte#3\advance\!!counte#5\advance\!!counte\minusone
+ \dostepwiserecurse{#2}\!!countd\plusone
+ {\!!countf\recurselevel
+ \dostepwiserecurse{#3}\!!counte\plusone
+ {\OTRSETsetgridcell\!!countf\recurselevel#1}}%
+ \dostepwiserecurse{#3}\!!counte\plusone
+ {\global\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
+ \OTRSETsetgridcell{#2}\!!counte#6}
+
+\def\OTRSETsetgridcells
+ {\doOTRSETsetgridcells{\copy\placeholderboxb}}
+
+\def\OTRSETerasegridcells#1#2#3#4%
+ {\doOTRSETsetgridcells{\emptybox}{#1}{#2}{#3}{#4}{\emptybox}}
+
+\def\setupcolumnsetlines{\doquintupleempty\dosetupcolumnsettrick[l]}
+\def\setupcolumnsetstart{\doquintupleempty\dosetupcolumnsettrick[s]}
+
+\def\dosetupcolumnsettrick[#1][#2][#3][#4][#5]% tag id page col value
+ {% not needed, is already relative
+ % \doifinstringelse{+}{#3}{\scratchcounter\realpageno}{\scratchcounter\zerocount}%
+ % \advance\scratchcounter#3\relax % \relax needed
+ % \setevalue{\??mc:#1:#2:\the\scratchcounter:\number#4}{\number#5}}
+ \iffifthargument
+ \setevalue{\??mc:#1:#2:\number#3:\number#4}{\number#5}%
+ \else
+ \setevalue{\??mc:#1:#2:\number#3:0}{\number#4}%
+ \fi}
+
+\def\currentcolumnmaxcellstag #1{\??mc:l:\OTRSETidentifier:\columnsetpage:\number#1}
+\def\currentcolumnstartcelltag#1{\??mc:s:\OTRSETidentifier:\columnsetpage:\number#1}
+
+\def\doresetcolumnsetlines#1%
+ {\ifcsname\currentcolumnmaxcellstag{#1}\endcsname
+ \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
+ \fi
+ \ifcsname\currentcolumnmaxcellstag{#1}\endcsname
+ \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
+ \fi}
+
+\def\currentcolumnsomecells#1#2%
+ {\ifcsname#1\mofcolumns\endcsname
+ \ifnum\csname#1\mofcolumns\endcsname=\zerocount
+ #2%
+ \else
+ \number\numexpr\ifnum\csname#1\mofcolumns\endcsname<\zerocount
+ \columnmaxcells+\fi\csname#1\mofcolumns\endcsname\relax
+ \fi
+ \else\ifcsname#10\endcsname
+ \ifnum\csname#10\endcsname=\zerocount
+ #2%
+ \else
+ \number\numexpr\ifnum\csname#10\endcsname<\zerocount
+ \columnmaxcells+\fi\csname#10\endcsname\relax
+ \fi
+ \else
+ #2%
+ \fi\fi}
+
+\def\currentcolumnmaxcells {\currentcolumnsomecells\currentcolumnmaxcellstag \columnmaxcells}
+\def\currentcolumnstartcell{\currentcolumnsomecells\currentcolumnstartcelltag\plusone}
+
+\def\OTRSETsetfreecells#1#2% col start
+ {\bgroup
+ \global\columnfirstcell\ifnum#2=0 1\else#2\fi\relax
+ \OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
+ \edef\columnmaxcells{\the\scratchcounter}%
+ \ifnum\columnfirstcell>\columnmaxcells
+ \global\columnfreecells\zerocount
+ \global\columnfirstcell\plusone
+ \global\columnlastcell \zerocount
+ \global\somefreecolumncellsfalse
+ %\message{no cells a}%
+ \else
+ \doloop
+ {\ifnum\columnfirstcell>\columnmaxcells\relax
+ \exitloop
+ \else
+ \OTRSETdoifcellelse{#1}\columnfirstcell
+ {\global\advance\columnfirstcell\plusone}\exitloop
+ \fi}%
+ \global\columnlastcell\columnfirstcell
+ \doloop
+ {\ifnum\columnlastcell>\columnmaxcells\relax
+ \exitloop
+ \else
+ \OTRSETdoifcellelse{#1}\columnlastcell
+ {\global\advance\columnlastcell \minusone \exitloop}
+ {\global\advance\columnlastcell \plusone }%
+ \fi}%
+ \ifnum\columnfirstcell>\columnmaxcells
+ \global\columnfreecells\zerocount
+ \global\columnfirstcell\plusone
+ \global\columnlastcell \zerocount
+ \global\somefreecolumncellsfalse
+ %\message{no cells b}%
+ \else
+ \ifnum\columnlastcell>\columnmaxcells
+ \global\columnlastcell\columnmaxcells
+ \fi
+ \global\columnfreecells\columnlastcell
+ \global\advance\columnfreecells -\columnfirstcell
+ \global\advance\columnfreecells \plusone
+ \global\somefreecolumncellstrue
+ %\message{\number\columnfirstcell-\number\columnlastcell=\number\columnfreecells}%
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRSETgetmaxfreecells#1#2% col start
+ {\let\columnmaxfreecells\!!zerocount
+ \let\columnfrmfreecells\!!zerocount
+ \pushmacro \columnmaxcells
+\OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
+\edef\columnmaxcells{\the\scratchcounter}%
+ \scratchcounter\zerocount
+ \dostepwiserecurse{#2}\columnmaxcells\plusone
+ {\OTRSETdoifcellelse{#1}\recurselevel
+ {\ifnum\columnmaxfreecells<\scratchcounter
+ \edef\columnmaxfreecells{\the\scratchcounter}%
+ \let\columnfrmfreecells\recurselevel
+ \fi
+ \scratchcounter\zerocount}
+ {\advance\scratchcounter\plusone}}%
+ \popmacro\columnmaxcells}
+
+\long\def\OTRSETrecurseRL#1%
+ {\dostepwiserecurse\nofcolumns\plusone\minusone
+ {#1\hskip\OTRSETgetparameter\c!distance\recurselevel}}
+
+\def\OTRSETmakegridbox
+ {\ifcase\columndirection
+ \OTRSETdomakegridbox\plusone\nofcolumns\plusone
+ \else
+ \OTRSETdomakegridbox\nofcolumns\plusone\minusone
+ \fi}
+
+\def\OTRSETmakeupwidth{\makeupwidth} % temporary indirectness
+
+\def\OTRSETdomakegridbox#1#2#3%
+ {\hbox\bgroup
+ \dontcomplain
+ \forgetall % can go once in \flush
+ \!!heighta \textheight
+ % test first !
+ \hbox to \OTRSETmakeupwidth
+ {\dostepwiserecurse{#1}{#2}{#3}
+ {\mofcolumns\recurselevel
+ \localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \setbox\scratchbox\hbox\localframed
+ [\??mc\OTRSETidentifier\number\mofcolumns]%
+ [\c!width=\localcolumnwidth,\c!height=\!!heighta,\c!lines=]%
+ {}%
+ \wd\scratchbox\localcolumnwidth
+ \ht\scratchbox\!!heighta
+ \ifcase\columndirection
+ \hskip\OTRSETgetparameter\c!distance\recurselevel
+ \box\scratchbox
+ \else
+ \box\scratchbox
+ \hskip\OTRSETgetparameter\c!distance\recurselevel
+ \fi}}%
+ \hskip-\OTRSETmakeupwidth
+ % main text
+ \hbox to \OTRSETmakeupwidth
+ {\dostepwiserecurse{#1}{#2}{#3}
+ {\mofcolumns\recurselevel
+ \localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \offinterlineskip
+ \setbox\scratchbox\vbox to \!!heighta
+ {\topskipcorrection % not needed
+ \ifcase\OTRSETbalancemethod
+ % no
+ \or
+ % yes
+ \doifelselayerdata{OTRTEXT}\vfill\relax % temp hack
+ \or
+ % top
+ \or
+ % bottom
+ \vfill
+ \fi
+ \dorecurse\columnmaxcells
+ {\setbox\scratchbox\hbox{\OTRSETgetgridcell\mofcolumns\recurselevel}%
+% {\setbox\scratchbox\hbox
+% {\localstarttextcolor
+% \OTRSETgetgridcell\mofcolumns\recurselevel
+% \localstoptextcolor}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \ifcase\columndirection
+ \box\scratchbox
+ \else
+ \hbox to \localcolumnwidth
+ {\hskip\localcolumnwidth\llap{\box\scratchbox}}%
+ \fi
+ \par}%
+ \ifcase\OTRSETbalancemethod
+ % no
+ \else
+ % yes, top, bottom
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \removedepth
+ \restoreglobalbodyfont
+ \vskip\strutdepth
+ \fi
+ \kern\zeropoint
+ \vss
+ \fi}%
+ \wd\scratchbox\localcolumnwidth % \textwidth
+ \ifcase\columndirection
+ \hskip\OTRSETgetparameter\c!distance\recurselevel\box\scratchbox
+ \else
+ \box\scratchbox\hskip\OTRSETgetparameter\c!distance\recurselevel
+ \fi}}%
+ \egroup}
+
+\let\OTRSETbalht\zeropoint
+
+\def\OTRSETreducegridbox % for the moment no difference between methods
+ {\globallet\OTRSETbalht\zeropoint
+ \ifcase\OTRSETbalancemethod
+ % no balancing
+ \else
+ \bgroup
+ \!!counta\columnmaxcells
+ \donetrue
+ \doloop
+ {\dorecurse\nofcolumns{\OTRSETdoifcellelse\recurselevel\!!counta\donefalse\donothing}%
+ \ifdone
+ \ifnum\!!counta>\plusone\advance\!!counta\minusone\else\exitloop\fi
+ \else
+ \exitloop
+ \fi}%
+ \ifnum\!!counta>\plusone
+ \!!heighta\lineheight
+ \multiply\!!heighta \!!counta
+ \advance\!!heighta \topskip
+ \advance\!!heighta -\lineheight
+ \else
+ \!!heighta\zeropoint
+ \fi
+ \xdef\OTRSETbalht{\the\!!heighta}%
+ \egroup
+ \fi}
+
+\def\OTRSETflushfinalfootnotes
+ {\ifcase\lastcolumnlastcell \else
+ \setbox\scratchbox\hbox
+ {\placebottomnotes}%
+ \ifdim\ht\scratchbox>\zeropoint
+ \setbox\scratchbox\hbox
+ {\hbox to \zeropoint{\OTRSETgetgridcell\nofcolumns\lastcolumnlastcell}%
+ \box\scratchbox}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \OTRSETsetgridcell\nofcolumns\lastcolumnlastcell\box\scratchbox
+ \fi
+ \global\lastcolumnlastcell\zerocount
+ \fi}
+
+\def\OTRSETdoflush
+ {\ifcollectingcontent
+ \registerOTRSETmarks
+ \global\mofcolumns\plusone
+ \else
+ \OTRSETdofinalflush
+ \OTRSETdofinaloutput
+ \ifnum\columnsetpage>0
+ \dorecurse\nofcolumns{\doresetcolumnsetlines\recurselevel}%
+ \fi
+ \doglobal\increment\columnsetpage
+ \OTRSETinitializecolumns
+ %\OTRSETdoflushfloats
+ \OTRSETstartnextpage
+\presetOTRSETmarks
+ \initializecolumntextareas
+ \fi}
+
+\newbox\OTRfinalpagebox
+
+\def\OTRSETdofinalflush % see \OTRSETdoflush
+ {\OTRSETflushfinalfootnotes
+ \placecolumntextareas
+ \OTRSETcentergridcells
+ \bgroup % we want to keep the reduction local
+ \OTRSETreducegridbox
+ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
+ \egroup % otherwise we get the wrong number of free cells
+ %\gdef\localcolumnmaxcells{0}% here ?
+ \global\mofcolumns\nofcolumns} % otherwise problems in finaloutput
+
+\def\OTRSETdofinaloutput
+ {\ifdim\ht\OTRfinalpagebox=\textheight
+ \bgroup % \let\OTRSETsetvsize\relax % prevents useless search for gap
+ \ifcase\OTRSETbalancemethod
+ \finaloutput\box\OTRfinalpagebox
+ \else\ifdim\OTRSETbalht>\zeropoint
+ % catch a bordercase
+ \scratchdimen\OTRSETbalht
+ \advance\scratchdimen\lineheight\relax
+ \ifdim\scratchdimen>\textheight
+ % full page
+ \finaloutput\box\OTRfinalpagebox
+ \else
+ % same page
+ \global\setbox\OTRfinalpagebox \iftracecolumnset\ruledvbox\else\vbox\fi to \OTRSETbalht
+ {\box\OTRfinalpagebox\vss}%
+ \setlayer[OTRTEXT]{\box\OTRfinalpagebox}%
+ \snaptogrid\vbox{\vskip\OTRSETbalht}% hack
+ \fi
+ \else
+ \finaloutput\box\OTRfinalpagebox
+ \fi \fi
+ \globallet\OTRSETbalht\zeropoint
+ \egroup
+ \fi}
+
+\definesystemvariable {mc}
+\definesystemvariable {mt}
+\definesystemconstant {colset}
+
+\definetwopasslist\s!colset
+
+\newdimen \OTRSETtextswidth
+\newdimen \OTRSETtextsheight
+\let \OTRSETidentifier=\empty
+
+\newtoks \OTRSEToutput
+
+\def\OTRSETgetparameter#1#2{\csname\??mc\OTRSETidentifier\number#2#1\endcsname}
+\def\OTRSETsetparameter#1#2{\setvalue{\??mc\OTRSETidentifier\number#2#1}}
+
+\def\OTRSETskipstart
+ {\scratchcounter\executeifdefined{\??mc\OTRSETidentifier\c!start}\zerocount
+ \relax % needed !
+ \ifcase\scratchcounter\else
+ \advance\scratchcounter\plusone
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\plusone\nofcolumns\scratchcounter
+ \null
+ \fi}
+
+\def\OTRSETsetvsize % snap per sectie (gap here?)
+ {\ifcollectingcontent \else % can be assigndimen
+\OTRSETskipstart % not that well tested
+ \OTRSETcheckinsert % added
+ \OTRSETsetfreecells\mofcolumns\columnfirstcell
+ \ifsomefreecolumncells
+ \global\vsize\columnfreecells\lineheight
+ \ifinotr % else problems with floats, see extreme
+ \global\pagegoal\vsize % niet nodig, tenzij binnen otr
+ \fi
+ \synchronizeoutput % fails on example
+ % \allowbreak % hm
+ \fi
+ \synchronizenotes
+ \fi}
+
+\def\OTRSETsethsize % of course this does not migrate outside the otr
+ {\localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \textwidth\localcolumnwidth
+ \hsize\localcolumnwidth}
+
+\def\OTRSETsynchronizehsize
+ {\ifcase0\getvalue{\??mc\??mc\c!width}\else % some width set
+ \bgroup
+ \scratchdimen\OTRSETlocalwidth\mofcolumns
+ \ifdim\scratchdimen=\textwidth
+ \egroup
+ \else
+ % only if change in width and \column/\break
+ \egroup \OTRSETsethsize
+ \fi
+ \fi}
+
+\def\OTRSETcheckfreelines
+ {\OTRSETsetvsize}
+
+\def\doOTRSETcolumnseparator
+ {\hbox to \zeropoint{\hss\red\vl\hss}}
+
+\let\OTRSETcolumnseparator\relax
+
+\def\showbreaks
+ {\let\OTRSETcolumnseparator\doOTRSETcolumnseparator}
+
+% \installcolumnbreakhandler {SET} \v!ja
+% {% hmmm:
+% \ifhmode
+% \bgroup
+% \removeunwantedspaces
+% \parfillskip\zeropoint
+% \OTRSETcolumnseparator
+% \par
+% \egroup
+% \fi
+% % brrr:
+% \ejectinsert
+% \ejectpage
+% \OTRSETsynchronizehsize} % no \OTRSETsethsize, can be mid smaller (like tabulate)
+%
+% \installcolumnbreakhandler {SET} \v!forceer
+% {\OTRSETgotocolumn[\v!forceer]}
+% \installcolumnbreakhandler {SET} \v!eerste
+% {\OTRSETgotocolumn[\v!eerste]}
+% \installcolumnbreakhandler {SET} \v!laatste
+% {\OTRSETgotocolumn[\v!laatste]}
+%
+% \installcolumnbreakhandler {SET} \v!pagina
+% {\simplepagebreak % \flushnotes \executepagebreakhandler\v!ja
+% \ifnum\mofcolumns>\plusone
+% \OTRSETgotocolumn[\v!laatste,\v!forceer]%
+% \fi}
+
+\def\OTRSETcolumnhbreak
+ {\ifhmode
+ \bgroup
+ \removeunwantedspaces
+ \parfillskip\zeropoint
+ \OTRSETcolumnseparator
+ \par
+ \egroup
+ \fi}
+
+\installcolumnbreakhandler {SET} \v!local
+ {\OTRSETcolumnhbreak
+ \ejectinsert
+ \ejectpage % brrr
+ % no \OTRSETsethsize, can be mid smaller (like tabulate)
+ % also, this one should be executed at the outer level
+ % (setting hsize inside otr does not work)
+ \OTRSETsynchronizehsize}
+
+% We need to make sure that we really leave the column; mid
+% column we may end up in an empty gap, and we don't want to
+% stay there (basically such a gap is a small empty page
+% then).
+
+\installcolumnbreakhandler {SET} \v!yes
+ {\OTRSETcolumnhbreak
+ \edef\savedmofcolumns{\the\mofcolumns}%
+ \edef\savedrealpageno{\the\realpageno}%
+ \ejectinsert
+ \ejectpage % brrr
+ \doloop
+ {\ifnum\savedmofcolumns=\mofcolumns
+ \ifnum\savedrealpageno=\realpageno
+ \OTRSETdummycolumn
+ \else
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \OTRSETsynchronizehsize}
+
+\installcolumnbreakhandler {SET} \s!unknown
+ {\expanded{\OTRSETgotocolumn[\@@columnspecification]}}
+
+\installcolumnbreakhandler {SET} \v!page
+ {\vfill\eject % \doejectpage\eject
+ \OTRSETgotonextpage}
+
+\newtoks\OTRSETeverystartofcolumn
+
+\newbox\OTRSETsavedfootnotes
+
+% \installoutput\OTRSETflushtextsofar % spacing goes wrong
+
+%\def\OTRSETflushtextsofar
+% {\ifvoid\normalpagebox \else
+% \setbox\scratchbox\vbox{\unvbox\normalpagebox}%
+% \OTRSETsavenotes
+% \OTRSEThandleflushedtext0
+% \fi}
+
+% The complication is in the fact that when the HERE float
+% is placed, the otr is not invoked when there is not yet
+% enough content; this can lead to a change in order (turning
+% on the tracer with option 0 is very instructive, watch the
+% small numbers in the margin)
+%
+% 0 = no flushing, so no interference but user should handle
+% border cases of placement
+% 1 = the normal otr, rather untested
+% 2 = a solution that works ok, is experimental and above
+% all messy
+
+\chardef\OTRSETflushtextmode=0
+
+\def\OTRSETflushtextsofar
+ {\ifcase\OTRSETflushtextmode
+ % don't mess around
+ \or
+ % the normal one
+ \ifvoid\normalpagebox\else
+ \OTRSETnaturalflush
+ \OTRSETcheckfreelines
+ \fi
+ \or
+ % way to complicated, but kind of ok
+ \doOTRSETflushtextsofar
+ \fi}
+
+\newskip\lastskipinotr
+
+\installoutput\doOTRSETflushtextsofar % experimental
+ {\ifvoid\normalpagebox\else
+ \scratchdimen\dp\normalpagebox
+ \setbox\scratchbox\vbox
+ {\forgetall
+ \unvbox\normalpagebox
+ \global\lastskipinotr\lastskip\relax
+ \ifdim\lastskipinotr>\zeropoint\relax
+ \removelastskip
+ \else
+ \kern-\scratchdimen % handle depth
+ \fi}%
+ \ifdim\lastskipinotr>\zeropoint
+ \scratchskip\ht\scratchbox
+ \setbox\scratchbox\hbox
+ {\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\scratchdimen
+ \ht\scratchbox\scratchskip
+ \fi
+ \OTRSETsavenotes
+ \OTRSEThandleflushedtext\zerocount
+ \ifdim\lastskipinotr>\zeropoint
+ %\vskip \lastskipinotr % hm, gets lost anyway
+ \else
+ % we should not discard skips after here; tricky
+ \fi
+ \OTRSETsetvsize
+ \fi}
+
+\def\OTRSETplacebottomnotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \ifintermediatefootnotes \placebottomnotes \fi
+ \fi
+ \else
+ \placebottomnotes
+ \fi}
+
+\def\OTRSETflushsavednotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \flushsavednotes
+ \fi
+ \else
+ \flushsavednotes
+ \fi}
+
+\def\OTRSETsavenotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns \else
+ \savenotes
+ \fi
+ \fi}
+
+\appendtoks \OTRSETflushsavednotes \to \OTRSETeverystartofcolumn
+
+\def\OTRSETnaturalflush
+ {\bgroup
+ \forgetall % new, needed !
+ \setbox0\vbox to \columnfreecells\lineheight
+ {\vskip-\topskip
+ \vskip\lineheight
+ \prevdepth\strutdp
+ \unvbox\normalpagebox
+ \vfill}%
+ \setbox2\hbox
+ {\OTRSETplacebottomnotes}%
+ \setbox\scratchbox\hbox
+ {\wd0\zeropoint\box0\box2}%
+ \dp\scratchbox\strutdp
+ \OTRSEThandleflushedtext\plusone
+ \egroup}
+
+\newcount\lastcolumnlastcell
+
+\def\OTRSEThandleflushedtext#1%
+ {\getnoflines{\ht\scratchbox}%
+ %\wd\scratchbox\textwidth % geen \hsize kan < zijn in bv split tabulate
+ \wd\scratchbox\OTRSETlocalwidth\mofcolumns
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxf}
+ \mofcolumns\columnfirstcell\plusone\noflines
+ {\registeredtextarea1\columnfirstcell\scratchbox}% == \hbox / tricky htcorr == \columnfirstcell
+ \global\columnlastcell\columnfirstcell
+ \global\advance\columnlastcell \noflines
+ \global\lastcolumnlastcell\columnlastcell
+ \global\advance\lastcolumnlastcell \minusone
+ % find next (acceptable) gap, todo: deadcycle
+ \ifcase#1\else
+ \OTRSETfillgapsbetweencells\mofcolumns\columnlastcell
+ \fi
+ \OTRSETfindnextgap
+ % \message{\the\mofcolumns,\the\columnfirstcell,\the\columnfreecells}%
+ % \wait
+ % we cannot adapt the hsize since it may have changed (like
+ % inside a tabulate) so we only change it when there is a
+ % reason to do so
+ \OTRSETsynchronizehsize
+ \OTRSETsetvsize}
+
+\def\OTRSETfindnextgap
+ {\OTRSETsetfreecells\mofcolumns\columnlastcell
+ \ifsomefreecolumncells
+ % okay
+ \bubbleOTRSETmarks % not robust because we reenter
+ \else
+ \registerOTRSETmarks % not robust because we reenter
+ \global\advance\mofcolumns \plusone
+ \ifnum\mofcolumns>\nofcolumns
+ \OTRSETdoflush
+ \global\columnlastcell\plusone
+ \global\columnfirstcell\zerocount
+ \OTRSETdoflushfloats
+ \else
+ \the\OTRSETeverystartofcolumn
+ \global\columnlastcell\plusone
+ \global\columnfirstcell\zerocount
+ \fi
+ \fi}
+
+\let\OTRSETcheckfreelines\donothing
+
+\def\OTRSETfillgapsbetweencells#1#2% col
+ {\ifnum\columngaplimit>\zerocount
+ \donefalse
+ \dostepwiserecurse{#2}\columnmaxcells\plusone
+ {\OTRSETdoifcellelse{#1}\recurselevel
+ {\ifdone
+ \!!countb\recurselevel \advance\!!countb -\!!counta\relax
+ \ifnum\!!countb>\plusone
+ \advance\!!countb \minusone
+ \ifnum\!!countb<\columngaplimit\relax
+ \!!countb\recurselevel \advance\!!countb \minusone
+ \dostepwiserecurse\!!counta\!!countb\plusone
+ {\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}%
+ %\message{[gap]}%
+ \fi
+ \fi
+ \fi
+ \donefalse}
+ {\ifdone \else
+ \donetrue
+ \!!counta\recurselevel
+ \fi}}%
+ \fi}
+
+\appendtoks
+ \OTRSETfillgapsbetweencells\mofcolumns\plusone
+\to \OTRSETeverystartofcolumn
+
+%\def\OTRSETfreezeminimumgap#1%
+% {\OTRSETgetmaxfreecells{#1}{1}%
+% \ifnum\columnmaxfreecells>0
+% \!!countb=\columnfrmfreecells
+% \!!counta=\!!counta \advance\!!counta -\columnmaxfreecells
+% \dorecurse{\columnmaxcells}
+% {\ifnum\recurselevel<\!!counta\relax
+% \donetrue
+% \else\ifnum\recurselevel>\!!countb
+% \donetrue
+% \else
+% \donefalse
+% \fi\fi
+% \ifdone
+% \OTRSETdoifcellelse{#1}{\recurselevel}
+% {}{\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}%
+% \fi}%
+% \fi}
+%
+%\def\OTRSETfillgaps#1#2#3% col from to
+% {\dostepwiserecurse{#2}{#3}{1}
+% {\OTRSETdoifcellelse{#1}{\recurselevel}
+% {}{\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}}}
+%
+%\def\OTRSETfillbotgaps#1#2% col first
+% {\OTRSETfillgaps{#1}{#2}{\columnmaxcells}}
+%
+%\def\OTRSETfilltopgaps#1#2% col last
+% {\OTRSETfillgaps{#1}{1}{#2}}
+
+\newif\ifspancolumnslots \spancolumnslotstrue
+\newif\ifcheckcolumnspan \checkcolumnspantrue
+
+\def\OTRSETcheckwidthgap#1#2% box size
+ {\ifcheckcolumnspan
+ \bgroup
+ \scratchdimen#2%
+ \advance\scratchdimen-\wd#1\relax
+ \ifdim-10\scaledpoint>\scratchdimen
+ \egroup
+ \else\ifdim10\scaledpoint<\scratchdimen
+ \egroup
+ \else
+ \egroup
+ \wd#1=#2%
+ \fi\fi
+ \fi}
+
+\def\OTRSETcheckcolumnslot#1%
+ {\enoughcolumncellstrue
+ \ifspancolumnslots\else
+ \OTRSETcheckwidthgap#1\hsize
+ \ifdim\wd#1>\hsize
+ \enoughcolumncellsfalse
+ \fi
+ \fi
+ \ifenoughcolumncells
+ \getnoflines\pagetotal
+ \scratchcounter\noflines
+ \getnoflines{\ht#1}%
+ \columnvcells\noflines
+ \columnhcells\plusone
+ \advance\scratchcounter \columnvcells \relax
+ \ifnum\scratchcounter>\columnfreecells
+ \enoughcolumncellsfalse
+ \fi
+ \fi}
+
+\def\OTRSETstoreincolumnslotPAGE#1%
+ {\ifenoughcolumncells
+ % to do
+ \OTRSETsavebox{#1}%
+ \else
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\def\OTRSETstoreincolumnslotTOPS#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETcheckcolumnslot{#1}%
+ \ifenoughcolumncells
+ \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
+ \fi
+ \ifenoughcolumncells
+ \OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells
+ {\hbox{\copy#1}}%
+ \OTRSETsetvsize
+ \else
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\def\OTRSETstoreincolumnslotBOTS#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \edef\savedcolumnlastcell{\the\columnlastcell}%
+ \OTRSETcheckcolumnslot{#1}%
+ \ifenoughcolumncells
+ \advance\columnlastcell -\columnvcells \advance\columnlastcell \plusone
+% \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
+ \OTRSETcheckcolumnspace\mofcolumns\columnlastcell{#1}%
+ \fi
+ \ifenoughcolumncells
+ \OTRSETsetgridcells\mofcolumns\columnlastcell\columnhcells\columnvcells{\copy#1}%
+ \OTRSETfillgapsbetweencells\mofcolumns\savedcolumnlastcell % -)
+ \OTRSETsetvsize
+ \else
+ \columnlastcell\savedcolumnlastcell
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\newdimen\totalcolumnspace
+
+\def\columnspacetopoffset{0}
+\def\columnspacebotoffset{0}
+
+\def\OTRSETcheckcolumnspace#1#2#3% col row box
+ {\columnhcells\plusone
+ \totalcolumnspace\zeropoint
+ \scratchcounter#1%
+ \enoughcolumncellstrue
+ \doloop
+ {\advance\totalcolumnspace \OTRSETlocalwidth\scratchcounter\relax % needed
+\OTRSETcheckwidthgap#3\totalcolumnspace
+ \ifnum\wd#3>\totalcolumnspace\relax
+ \ifnum\scratchcounter=\nofcolumns
+ \enoughcolumncellsfalse
+ \exitloop
+ \else
+ \advance\columnhcells \plusone
+ \advance\scratchcounter \plusone
+ \advance\totalcolumnspace \OTRSETgetparameter\c!distance\scratchcounter
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \ifenoughcolumncells
+ \getnoflines{\ht#3}%
+ \columnvcells\noflines
+ \OTRSETcheckcolumncells{#1}{#2}\columnhcells\columnvcells
+ \fi}
+
+\def\OTRSETcheckcolumncells#1#2#3#4% col row wid hei
+ {\!!countd#1\advance\!!countd#3\advance\!!countd\minusone
+ \!!counte#2\advance\!!counte#4\advance\!!counte\minusone
+ \ifnum\!!counte>\columnmaxcells\relax
+ \enoughcolumncellsfalse
+ \else
+ \enoughcolumncellstrue
+%\let\columnspacetopoffset\zerocount
+%\scratchcounter#2\advance\scratchcounter\minusone
+%\ifnum\scratchcounter>0
+% \dostepwiserecurse{#1}\!!countd\plusone
+% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacetopoffset\plusone
+% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacetopoffset\plusone
+% \fi\fi}%
+% \advance\!!counte \columnspacetopoffset \relax
+% \advance\columnvcells \columnspacetopoffset \relax
+%\fi
+%\let\columnspacebotoffset\zerocount
+%\scratchcounter\!!counte
+%\advance\scratchcounter \columnvcells \relax
+%\ifnum\scratchcounter>\columnmaxcells\else
+% \dostepwiserecurse{#1}\!!countd\plusone
+% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacebotoffset\plusone
+% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacebotoffset\plusone
+% \fi\fi}%
+% \advance\!!counte \columnspacebotoffset \relax
+% \advance\columnvcells \columnspacebotoffset \relax
+%\fi
+ \dostepwiserecurse{#1}\!!countd\plusone % cols
+ {\ifenoughcolumncells
+ \!!countf\recurselevel\relax
+ \dostepwiserecurse{#2}\!!counte\plusone % rows
+ {\ifenoughcolumncells
+ \OTRSETdoifcellelse\!!countf\recurselevel
+ {\enoughcolumncellsfalse}{}%
+ \fi}%
+ \fi}%
+ \fi}
+
+\def\OTRSETsetpreferedcolumnslot#1#2%
+ {\doifsomething{#1}{\edef\preferedcolumn{#1}}%
+ \doifsomething{#2}{\edef\preferedrow {#2}}}
+
+\OTRSETsetpreferedcolumnslot{\nofcolumns}{1} % default ?
+
+\let\pofcolumns\mofcolumns
+\let\qofcolumns\mofcolumns
+
+\newif\ifquitincurrentcolumn
+
+\def\OTRSETstoreincolumnslotLRTB#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\nofcolumns+\currenthcell
+ \plusone\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotLRBT#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\nofcolumns+\currenthcell
+ \columnmaxcells\plusone-\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotRLTB#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \nofcolumns\qofcolumns-\currenthcell
+ \plusone\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotRLBT#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \nofcolumns\qofcolumns-\currenthcell
+ \columnmaxcells\plusone-\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotTBLR#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \plusone\columnmaxcells+\currentvcell
+ \mofcolumns\nofcolumns+\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotTBRL#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \plusone\columnmaxcells+\currentvcell
+ \nofcolumns\qofcolumns-\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotBTLR#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \columnmaxcells\plusone-\currentvcell
+ \mofcolumns\nofcolumns+\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotBTRL#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \columnmaxcells\plusone-\currentvcell
+ \nofcolumns\qofcolumns-\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotFXTB#1% fixed column
+ {\OTRSETcheckprefered
+ \OTRSETdoifcellelse\pofcolumns\plusone
+ {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot1}{#1}% % 1/2 dependent of place, todo
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \pofcolumns \pofcolumns +\currenthcell
+ \preferedrow\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotFXBT#1% fixed column
+ {\OTRSETcheckprefered
+ \OTRSETdoifcellelse\pofcolumns\columnmaxcells
+ {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot3}{#1}% % 3/2 dependent of place, todo
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \pofcolumns \pofcolumns +\currenthcell
+ \columnmaxcells\preferedrow-\currentvcell{#1}}
+
+% \def\OTRSETstoreincolumnslotHERE#1% fixed column
+% {\OTRSETprepareforcolumnslot2{#1}%
+% \OTRSETflushtextsofar
+% \getnoflines\pagetotal \advance\noflines\columnfirstcell
+% \OTRSETstoreincolumnslotindeed
+% \mofcolumns\mofcolumns+\currenthcell
+% \noflines\columnmaxcells+\currentvcell{#1}%
+% \OTRSETsetvsize}
+
+\chardef\OTRSETforcefixedfloats=0
+
+\def\OTRSETstoreincolumnslotHERE#1% fixed column
+ {\ifcase\OTRSETforcefixedfloats
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \else
+ \OTRSETstoreincolumnslotFIXD{#1}%
+ \fi}
+
+% this one looses too wide graphics
+%
+% \def\OTRSETstoreincolumnslotFIXD#1% fixed column
+% {\OTRSETprepareforcolumnslot2{#1}%
+% % no flush text sofar here, beware: no width test
+% \snaptogrid\vbox{\box#1}}
+%
+% still imperfect
+
+\def\OTRSETstoreincolumnslotFIXD#1% fixed column
+ {\OTRSETflushtextsofar
+ \ifdim\wd#1>\textwidth
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \else
+ % crappy test / needed for o-pbu-f / will be replaced
+ \getnoflines{\ht#1}%
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen\lineheight
+ \advance\scratchdimen\pagetotal\relax
+ \ifdim\scratchdimen<\pagegoal
+ %OTRSETprepareforcolumnslot3{#1}%
+ %ruledvskip\columnslotspacing\lineheight
+ \blank[\columnslotspacing*\v!line]%
+ \snaptogrid\hbox to \hsize{\hss\box#1\hss}% strange, why the centering
+ \blank[\columnslotspacing*\v!line]%
+ \else
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \fi
+ \fi}
+
+\def\OTRSETstoreincolumnslotSOMEWHERE#1#2%
+ {\OTRSETprepareforcolumnslot{#1}{#2}%
+ \OTRSETflushtextsofar
+ \getnoflines\pagetotal \advance\noflines\columnfirstcell
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\mofcolumns+\currenthcell
+ \noflines\columnmaxcells+\currentvcell{#2}%
+ \OTRSETsetvsize}
+
+\def\OTRSETcheckprefered
+ {\ifnum\preferedcolumn<\mofcolumns
+ \let\pofcolumns\mofcolumns
+ \else
+ \let\pofcolumns\preferedcolumn
+ \fi
+ \ifquitincurrentcolumn
+ \ifnum\mofcolumns=\nofcolumns
+ \def\qofcolumns{\mofcolumns}%
+ \else
+ \scratchcounter\mofcolumns
+ \advance\scratchcounter \plusone
+ \edef\qofcolumns{\the\scratchcounter}%
+ \fi
+ \else
+ \let\qofcolumns\mofcolumns
+ \fi}
+
+\def\OTRSETstoreincolumnslotindeed#1#2#3#4#5#6#7#8#9%
+ {\OTRSETcheckprefered
+ \enoughcolumncellsfalse
+ \donefalse
+ \dostepwiserecurse{#1}{#2}{#31}
+ {\ifdone
+ \exitloop
+ \else
+ #4=\recurselevel
+ \dostepwiserecurse{#5}{#6}{#71}
+ {\ifdone
+ \exitloop
+ \else
+ #8=\recurselevel
+ \OTRSETcheckcolumnspace\currenthcell\currentvcell{#9}%
+ \ifenoughcolumncells \donetrue \fi
+ \fi}%
+ \fi}%
+ \ifdone
+ \enoughcolumncellstrue
+ \else
+ \enoughcolumncellsfalse
+ \fi
+ \ifenoughcolumncells
+% \ifnum\columnspacetopoffset>0\message{[+++]}\fi
+% \ifnum\columnspacebotoffset>0\message{[---]}\fi
+% \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
+% {\vbox
+% {\ifcase\columnspacetopoffset\else\ruledvskip\columnspacetopoffset\lineheight\fi
+% \copy#9
+% \ifcase\columnspacebotoffset\else\ruledvskip\columnspacebotoffset\lineheight\fi}}%
+ \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
+ {\copy#9}%
+ \ifnum\currenthcell=\mofcolumns\relax
+ \ifdim\ht\OTRSETsavedfootnotes>\zeropoint
+ \OTRSETsetfreecells\mofcolumns\columnfirstcell
+ \ifsomefreecolumncells
+ \getnoflines{\ht\OTRSETsavedfootnotes}\relax
+ \ifnum\columnfreecells<\noflines
+ \global\somefreecolumncellsfalse
+ \else
+ %\message{[flt]}% float
+ \fi
+ \fi
+ \ifsomefreecolumncells
+ % ok, enough room for notes
+ %\message{[flt]}% float
+ \else % ?
+ \OTRSETsavebox{#9}%
+ \OTRSETerasegridcells\currenthcell\currentvcell\columnhcells\columnvcells
+ %\message{[clr]}% save box
+ \fi
+ \else
+ %\message{[flt]}% float
+ \fi
+ \else
+ %\message{[flt]}% float
+ \fi
+ \OTRSETsetvsize
+ %\message{[fnt]}% float
+ \else
+ %\message{[rej]}% save box
+ \OTRSETsavebox{#9}%
+ \fi}
+
+\chardef\columnslotspacing \plusone
+
+\def\OTRSETstoreincolumnslot#1% #2 % {method} {box} % alleen last
+ {% no messing around here
+ % \dp#2=\zeropoint
+ % \ifcase\columnslotspacing\else
+ % \setbox#2=\vbox spread \columnslotspacing\lineheight
+ % {\vss\box#2\vss}%
+ % \fi
+ % and don't change this any more
+% \doifdefinedelse{\strippedcsname\OTRSETstoreincolumnslot#1}
+% {\getvalue{\strippedcsname\OTRSETstoreincolumnslot#1}{#2}}
+% {\OTRSETstoreincolumnslotUNKNOWN{#2}}}
+ \executeifdefined{\strippedcsname\OTRSETstoreincolumnslot#1}
+ \OTRSETstoreincolumnslotUNKNOWN} % {#2}}
+
+\def\OTRSETstoreincolumnslotUNKNOWN#1%
+ {\OTRSETprepareforcolumnslot2{#1}\copy#1} % {} ?
+
+% \def\OTRSETprepareforcolumnslot#1#2% 1=hoog 2=midden 3=laag
+% {\dp#2\zeropoint
+% \ifcase\columnslotspacing\else
+% \scratchdimen\columnslotspacing\lineheight
+% \ifnum#1=2 \scratchdimen2\scratchdimen \fi
+% \setbox#2\vbox spread \scratchdimen
+% {\ifnum#1>1\vss\fi\box#2\relax\ifnum#1<3\vss\fi}%
+% \fi}
+
+\def\OTRSETprepareforcolumnslot#1#2% 1=hoog 2=midden 3=laag
+ {\dp#2\zeropoint
+ \ifcase\columnslotspacing\else
+ \scratchdimen\columnslotspacing\lineheight
+ \ifnum#1=2 \scratchdimen2\scratchdimen \fi
+ \begingroup
+ \advance\scratchdimen\ht#2\relax
+ \ifdim\scratchdimen<\columnmaxcells\lineheight
+ \endgroup \setbox#2\vbox spread \scratchdimen \bgroup
+ \else
+ \endgroup \setbox#2\vbox to \columnmaxcells\lineheight \bgroup
+ \vskip\strutdepth
+ \fi
+ \ifnum#1>1\vss\fi
+ \box#2\relax
+ \ifnum#1<3\vss\fi
+ \egroup
+ \fi}
+
+\def\OTRSETdocheckiffloatfits % eigenlijk moet else float anders
+ {\global\ifnofloatpermitted\roomforfloatfalse\else\roomforfloattrue\fi}
+
+\def\OTRSETunpreparebox#1%
+ {\ifhbox#1% spans and so
+ \global\setbox\floatbox\vbox{\box#1}%
+ \else
+ \setbox\scratchbox\vbox
+ {\unvbox#1\unskip\unskip\unskip
+ \global\setbox\floatbox\lastbox}%
+ \fi}
+
+\def\OTRSETsavebox#1% clean up the skips
+ {\OTRSETunpreparebox{#1}%
+ \dosavefloat}
+
+\def\OTRSETresavebox#1% clean up the skips
+ {\OTRSETunpreparebox{#1}%
+ \doresavefloat}
+
+\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
+ {\iftestfloatbox\ruledhbox\fi{\box\floatbox}}
+
+\def\OTRSETdoflushfloats
+ {\bgroup
+ \def\OTRSETsavebox##1{\!!doneafalse}%
+ \doloop
+ {\ifsomefloatwaiting
+\OTRSETskipstart
+ \dogetfloat
+ \ifdim\wd\floatbox>\zeropoint
+ \!!doneatrue
+ \dp\floatbox\zeropoint
+ \OTRSETstoreincolumnslot{TBLR}\floatbox
+ \if!!donea
+ %\message{[flu]}%
+ \else
+ \OTRSETresavebox\floatbox
+ \exitloop
+ \fi
+ \else
+ %\message{[err]}% happens but why?
+ \fi
+ \else
+ \exitloop
+ \fi}
+ \egroup}
+
+\newif\ifcentergridcells \centergridcellstrue
+
+\newif\ifcentergridcellonly \centergridcellonlyfalse
+\newif\ifautocentergridcellonly \autocentergridcellonlytrue
+
+\def\OTRSETcentergridcells
+ {\ifcentergridcells
+ \dorecurse\nofcolumns
+ {\currenthcell\recurselevel
+ \ifautocentergridcellonly
+ % we prevent centering when the next column is empty
+ % to be checked ! ! ! !
+ \advance\currenthcell \plusone
+ \centergridcellonlytrue
+ \ifnum\currenthcell>\nofcolumns
+ % ok already
+ \else
+ % only span if there is a next column with content
+ \dorecurse\columnmaxcells
+ {\ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ \centergridcellonlyfalse
+ \else\ifdim\dp\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ \centergridcellonlyfalse
+ \fi\fi}%
+ \fi
+ \fi
+ \currenthcell\recurselevel
+ \dorecurse\columnmaxcells
+ {\currentvcell\recurselevel\relax
+ \ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ \ifdim\dp\OTRSETgridcell\currenthcell\currentvcell=\zeropoint
+ \bgroup
+ \setbox\scratchbox\OTRSETgetgridcell\currenthcell\currentvcell
+ \getnoflines{\ht\scratchbox}%
+ \!!counta\currentvcell
+ \advance\!!counta -\noflines
+ \advance\!!counta \plusone
+ % first col always ok
+ \!!countb\currenthcell
+ \!!countc\currenthcell
+ \advance\!!countc \plusone
+ \!!donebtrue
+ \ifcentergridcellonly
+ \!!countc\maxdimen
+ \fi
+ \dostepwiserecurse\!!countc\nofcolumns\plusone
+ {\if!!doneb
+ \let\xrecurselevel\recurselevel
+ \dostepwiserecurse\!!counta\currentvcell\plusone
+ {\ifdim\ht\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
+ \!!donebfalse
+ \else\ifdim\wd\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
+ \!!donebfalse
+ \fi\fi}%
+ \if!!doneb
+ \!!countb\xrecurselevel
+ \fi
+ \fi}%
+ \totalcolumnspace\OTRSETlocalwidth\currenthcell
+ \dostepwiserecurse\!!countc\!!countb\plusone
+ {\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel
+ \advance\totalcolumnspace \OTRSETgetparameter\c!distance\recurselevel}%
+ \ifdim\totalcolumnspace>\wd\scratchbox
+ \setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}%
+ \fi
+ \OTRSETsetgridcell\currenthcell\currentvcell\box\scratchbox
+ \egroup
+ \fi
+ \fi}}%
+ \fi}
+
+\def\OTRSETinitializecolumns% once per page
+ {\columnspreadtrue % todo
+ \ifcolumnspread
+ \global\rofcolumns\getvalue{\??mc\OTRSETidentifier\c!nright}%
+ \global\lofcolumns\getvalue{\??mc\OTRSETidentifier\c!nleft}%
+ \global\tofcolumns\rofcolumns \relax
+ \ifodd\realpageno\relax
+ \global\nofcolumns\rofcolumns
+ \else
+ \global\advance\tofcolumns\lofcolumns
+ \global\nofcolumns\lofcolumns
+ \fi
+ \else
+ \global\nofcolumns\getvalue{\??mc\OTRSETidentifier\c!n}%
+ \global\rofcolumns\nofcolumns
+ \global\lofcolumns\nofcolumns
+ \global\tofcolumns\nofcolumns
+ \fi
+ \OTRSETassignwidths
+ \global\mofcolumns\plusone
+ \columnerasegridboxes}
+
+% vanaf hier:
+
+\def\definecolumnset
+ {\dodoubleargument\dodefinecolumnset}
+
+\def\dodefinecolumnset[#1][#2]%
+ {\getparameters[\??mc#1]
+ [\c!direction=\v!right,
+ \c!balance=\v!no,
+ \c!distance=1.5\bodyfontsize, % controleren
+ \c!n=2,
+ \c!nleft=\getvalue{\??mc#1\c!n},
+ \c!nright=\getvalue{\??mc#1\c!n},
+ \c!width=\v!fit,
+ \c!lines=0,
+ \c!start=0,
+ #2]%
+ \dorecurse{\getvalue{\??mc#1\c!nleft}} % todo
+ {\dododefinecolumnset[#1][\recurselevel]}%
+ \dorecurse{\getvalue{\??mc#1\c!nright}} % todo
+ {\dododefinecolumnset[#1][\recurselevel]}%
+ % redo framed settings
+ \setupcolumnset[#1][1][\c!distance=\!!zeropoint]}
+
+\def\dododefinecolumnset[#1][#2]%
+ {\presetlocalframed
+ [\??mc#1#2]%
+ \setupcolumnset
+ [#1][#2]
+ [\c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!align=,
+ \c!lines=0,% really needed since c!regels is now part of framed
+ \c!width=\getvalue{\??mc#1\c!width},
+ \c!distance=\getvalue{\??mc#1\c!distance}]}
+
+\def\setupcolumnset
+ {\dotripleargument\dosetupcolumnset}
+
+\def\dosetupcolumnset[#1][#2][#3]%
+ {\ifthirdargument
+ \def\docommand##1%
+ {\doifelse{##1}\v!each
+ {\dorecurse{\getvalue{\??mc#1\c!n}}{\docommand\recurselevel}}
+ {\getparameters[\??mc#1##1][#3]}}%
+ \processcommalist[#2]\docommand
+ \else
+ \getparameters[\??mc#1][#2]%
+ \fi}
+
+\definecolumnset[\s!default][\c!n=2] % fallback
+
+\def\OTRSETgotonextpage
+ {\vfill\eject
+ \relax\ifnum\mofcolumns>\plusone
+ \OTRSETgotocolumn[\v!last]%
+ \ifnum\mofcolumns>\plusone
+ \OTRSETgotocolumn[\v!force]%
+ \fi
+ \fi}
+
+\let\OTRSETgotonextpageX\OTRSETgotonextpage % will become obsolete
+
+\def\OTRSETgotocolumn
+ {\dosingleempty\doOTRSETgotocolumn}
+
+\def\doOTRSETgotoCOLROW#1% |*
+ {\bgroup % really needed
+ \splitstring#1\at*\to\column\and\row
+ \bgroup
+ \ifx\column\empty\else\expanded{\doOTRSETgotoCOLUMN{\column}}\fi
+ \egroup
+ \bgroup
+ \ifx\row \empty\else\expanded{\doOTRSETgotoROW {\row }}\fi
+ \egroup
+ \egroup}
+
+\def\doOTRSETgotoCOLUMN#1%
+ {\ifnum\mofcolumns=#1\else
+ \vfill\eject % \doejectpage\eject
+ \doloop
+ {\ifnum\mofcolumns=#1\relax
+ \exitloop \else \OTRSETdummycolumn
+ \fi}%
+ \fi}
+
+\def\doOTRSETgotoROW#1%
+ {\ifnum#1>1
+ \scratchcounter\zerocount
+ \currenthcell\mofcolumns
+ \currentvcell#1\advance\currentvcell \minusone
+ \dorecurse\currentvcell
+ {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
+ {\advance\scratchcounter\plusone}}
+ \getnoflines\pagetotal
+ \advance\scratchcounter-\noflines
+ \ifnum\scratchcounter>\zerocount
+ \dorecurse\scratchcounter{\line{\strut}}%
+ \fi
+ \fi
+ \OTRSETsetvsize}
+
+\def\doOTRSETgotocolumn[#1]% yes|force|first|last||*
+ {\processallactionsinset
+ [#1]
+ [ \v!yes=>\OTRSETdummycolumn,
+ \v!no=>,% not supported
+ \v!force=>\OTRSETdummycolumn,
+ \v!first=>\expanded{\doOTRSETgotoCOLUMN{1}},
+ \v!last=>\expanded{\doOTRSETgotoCOLUMN{\the\nofcolumns}},
+ \s!default=>\OTRSETdummycolumn,
+ \s!unknown=>\expanded{\doOTRSETgotoCOLROW{\commalistelement}}]}
+
+% to be documented and tested, not yet that robust
+
+% \def\OTRSETgotocell#1#2%
+% {\endgraf
+% \gdef\gotocellcounter{0}%
+% \doloop
+% {\ifnum\mofcolumns<#1\relax
+% \doglobal\increment\gotocellcounter\relax
+% \ifnum\gotocellcounter>#1\relax
+% \line{\strut}\crlf
+% \line{\strut}\crlf
+% \column
+% \writestatus{columnset}{quitting goto cell}%
+% \exitloop
+% \else
+% \column
+% \fi
+% \else
+% \exitloop
+% \fi}%
+% \ifnum\mofcolumns=#1\relax
+% \ifnum#2>1
+% \scratchcounter\zerocount
+% \currenthcell\mofcolumns
+% \currentvcell#2\advance\currentvcell \minusone
+% \dorecurse\currentvcell
+% {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
+% {\advance\scratchcounter\plusone}}
+% \getnoflines\pagetotal
+% \advance\scratchcounter-\noflines
+% \ifnum\scratchcounter>\zerocount
+% \dorecurse\scratchcounter{\line{\strut}}%
+% \fi
+% \fi
+% \fi
+% \OTRSETsetvsize}
+
+\def\OTRSETgotocell#1#2% obsolete: now \column[#1*#2]
+ {\endgraf
+ \doOTRSETgotoCOLUMN{#1}%
+ \doOTRSETgotoROW {#2}}
+
+\def\OTRSETdummycolumn
+ {\verticalstrut
+ \vskip-\struttotal
+ \vfill
+ \eject}
+
+\newcounter\columnsetlevel
+\let\currentcolumnset\empty
+\chardef\OTRSETfinish\zerocount
+
+\def\startcolumnset
+ {\dodoubleempty\dostartcolumnset}
+
+\def\dostartcolumnset[#1][#2]%
+ {\increment\columnsetlevel\relax
+ \globallet\localcolumnmaxcells\!!zerocount
+ \global\chardef\OTRSETfinish\zerocount
+ \resetOTRSETmarks
+ \ifnum\columnsetlevel=\plusone
+ \bgroup
+ \saveinterlinespace
+ \globallet\columnsetpage\!!plusone
+ \def\currentcolumnset{#2}%
+ \insidecolumnstrue % will be different flag in addition
+ \activateotr{SET}{ONE}% andere naam, activate or so
+ \doifelsenothing{#1}
+ {\globallet\OTRSETlist\s!default}
+ {\xdef\OTRSETlist{#1}}%
+ \OTRSETstartnextpage
+ \OTRSETassignwidths
+ \OTRSETsethsize
+ \else
+ \bgroup
+ \fi}
+
+% \setuplayout[grid=yes] \definecolumnset[example] \showgrid
+
+% \starttext
+% \startcolumnset[example]
+% \input knuth \endgraf \input knuth
+% \placetable{table}{\framed[width=\makeupwidth,height=4cm]{Hello}}
+% \input knuth \endgraf \input knuth
+% \stopcolumnset
+% \input knuth \endgraf \input knuth
+% \stoptext
+
+
+\def\OTRSETflushleftovers % new per 13/4/2006
+ {\OTRSETdoifcellelse{1}{1}
+ {\bgroup
+ \OTRSETcentergridcells
+ \chardef\OTRSETbalancemethod\plusone
+ \OTRSETreducegridbox
+ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
+ \global\ht\OTRfinalpagebox\textheight % signals output that there is content
+ \OTRSETdofinaloutput
+ \globallet\OTRSETbalht\zeropoint
+ \egroup}
+ {}}
+
+\def\stopcolumnset
+ {\relax
+ \ifnum\columnsetlevel=\plusone
+ \endgraf % needed, else wrong vsize in one par case
+ \global\chardef\OTRSETfinish\plusone
+ % no, extra page \pagebreak % (test on pascal toc)
+ \dostopcolumnset
+ \egroup
+ \global\notelimittrue % brrr, untested and fuzzy
+ \setvsize
+ \sethsize
+ \ifvoid\OTRfinalpagebox\else
+ % probably balanced
+ \ifdim\ht\OTRfinalpagebox<\textheight
+ \snaptogrid[\v!page]\hbox{\box\OTRfinalpagebox}%
+ \else
+ \box\OTRfinalpagebox
+ \fi
+ \fi
+ \global\chardef\OTRSETfinish\zerocount
+ \ifsomefloatwaiting \setvsize \pagebreak \setvsize \fi
+ \OTRSETflushleftovers
+ \else
+ \egroup
+ \fi
+ \decrement\columnsetlevel\relax}
+
+\chardef\OTRSETbalancemethod\zerocount
+
+\def\dostopcolumnset
+ {%\OTRSETdofinalflushfloats % yes/no
+ \ifcase\OTRSETbalancemethod
+ \OTRSETnobalance
+ \else
+ \OTRSETdobalance
+ \fi}
+
+\def\OTRSETdobalance
+ {\OTRSETnobalance}
+
+\def\localcolumnmaxcells{0}
+
+% don't loose empty 1page/1column with area (example **)
+%
+% \definecolumntextarea[title][x=1,y=4,nx=2,ny=7,state=start]
+% \setupcolumntextareatext[title][\vtop to 5cm{a\\b\\b\\d}]
+%
+% \starttext
+% \startcolumnset \dorecurse{1}{\input tufte \par} \stopcolumnset
+% \stoptext
+
+% better:
+
+\def\definecolumnsetarea {\definecolumntextarea}
+\def\setupcolumnsetarea {\setupcolumntextarea}
+\def\setupcolumnsetareatext{\setupcolumntextareatext}
+
+\def\OTRSETnobalance
+ {\iflastcolumnfootnotes % testen ! optie
+ % inhibit flush of floats !
+ % todo: nothing if no footnotes, else empty page
+ \dostepwiserecurse\mofcolumns\nofcolumns\plusone
+ {\vskip-\struttotal\verticalstrut\vfill\eject}%
+ \else
+ \ifnum\mofcolumns>\plusone
+ \donetrue
+ \else\ifdim\pagetotal>\zeropoint % too dangerous, we loose data
+ \donetrue
+ \else
+ \donefalse
+ \fi\fi
+ \ifdone
+ \ifnum\mofcolumns=\nofcolumns
+ \OTRSETflushfinalfootnotes
+ \else
+ % probably todo
+ \fi
+ \vfill
+ \eject
+\registerOTRSETmarks
+ % brr, may result in empty page after nicely fit text
+ % or if left, then lost of first column only text
+ \ifnum\mofcolumns>\plusone
+ \OTRSETdofinalflush
+ \OTRSETdofinaloutput
+ \fi
+ \fi
+ \fi}
+
+\def\OTRSETstartnextpage
+ {\doifsomething\OTRSETlist
+ {\getfromcommacommand[\OTRSETlist][1]%
+ \global\let\OTRSETidentifier\commalistelement
+ \doifundefined{\??mc\OTRSETidentifier\c!n}
+ {\globallet\OTRSETidentifier\s!default}%
+ \let\newcommalistelement\empty
+ \doglobal\replaceincommalist\OTRSETlist1%
+ \OTRSETrestart}}
+
+\def\OTRSETrestart % weed
+ {\OTRSETinitializefeatures
+ \OTRSETflushpreposttext
+ \OTRSETinitializecolumns
+ \OTRSETcheckinsert
+ \OTRSETcheckgrid
+ \OTRSETsetvsize
+ \OTRSETsethsize % or local ?
+ \OTRSETsetplaceholders
+ \OTRSEThandlepreposttext
+ \initializecolumntextareas % name !
+ \OTRSETcheckstartcells
+ \OTRSETsetvsize}
+
+% \def\OTRSETcheckstartcells
+% {\dorecurse\nofcolumns
+% {\bgroup
+% \mofcolumns\recurselevel
+% \scratchcounter\currentcolumnstartcell % uses \mofcolumns, returns 1 or more
+% \advance\scratchcounter \minusone
+% \dorecurse\scratchcounter
+% {\OTRSETdoifcellelse\mofcolumns\recurselevel
+% \donothing{\OTRSETsetgridcell\mofcolumns\recurselevel\copy\placeholderboxe}}%
+% \egroup}}
+
+\def\OTRSETcheckstartcells
+ {\dorecurse\nofcolumns
+ {\bgroup
+ \mofcolumns\recurselevel
+\OTRSETsetcorrectnofcells\currentcolumnstartcell
+\advance\scratchcounter \minusone
+ \dorecurse\scratchcounter
+ {\OTRSETdoifcellelse\mofcolumns\recurselevel
+ \donothing{\OTRSETsetgridcell\mofcolumns\recurselevel\copy\placeholderboxe}}%
+ \egroup}}
+
+% \OTRSEToutput
+% {\dontcomplain % new, get rid of overfull message (to be sorted out)
+% \OTRSETnaturalflush
+% %\OTRSETstartnextpage
+% \OTRSETdoflushfloats % actually belongs in \flushsavedfloats (but goes wrong)
+% \OTRSETcheckfreelines
+% \OTRSETchecksidefloat}
+
+\OTRSEToutput
+ {\dontcomplain % new, get rid of overfull message (to be sorted out)
+ \doloop
+ {\OTRSETnaturalflush
+ %\OTRSETstartnextpage % no
+ \OTRSETdoflushfloats % actually belongs in \flushsavedfloats (but goes wrong)
+ \OTRSETcheckfreelines
+ \ifsomefreecolumncells
+ \exitloop
+ \else
+ % flush page and get rid of more floats if present
+ \fi}%
+ \OTRSETchecksidefloat}
+
+\def\OTRSETinitializefeatures
+ {% number of lines
+ % new: raw
+ \getrawnoflines\textheight\xdef\columnmaxcells{\the\noflines}%
+ % direction
+ \doifelsevalue{\??mc\OTRSETidentifier\c!direction}\v!right
+ {\chardef\columndirection\zerocount}
+ {\chardef\columndirection\plusone}%
+ % balancing
+ \chardef\OTRSETbalancemethod\zerocount
+ \processaction
+ [\getvalue{\??mc\OTRSETidentifier\c!balance}]
+ [ \v!yes=>\chardef\OTRSETbalancemethod\plusone,
+ \v!top=>\chardef\OTRSETbalancemethod\plustwo,
+ \v!bottom=>\chardef\OTRSETbalancemethod\plusthree]}
+
+% keep 'm for a while
+%
+% \installoutput\OTRSETflushpreposttext
+% {\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}%
+% \ifcarryoverfootnotes \else
+% \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
+% \fi}
+%
+% to be tested on 'boekinhoud' in 'pascal/demo-bbi'
+%
+% junk ! ! ! ! !
+%
+%\installoutput\OTRSETflushpreposttext
+% {\global\setbox\precolumnbox\vbox
+% {\unvbox\normalpagebox
+% \strut\vskip-2\lineheight\strut}% we want a proper depth
+% \ifcarryoverfootnotes \else
+% \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
+% \fi}
+%
+% \starttext
+% \definecolumnset[two][n=2]
+% \startcolumnset[two] \dorecurse{4}{\input tufte } \stopcolumnset
+% \input tufte
+% \startcolumnset[two] \input tufte \stopcolumnset
+% \stoptext
+%
+% \installoutput\OTRSETflushpreposttext
+% {\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}%
+% \global\dp\precolumnbox\strutdepth
+% \ifcarryoverfootnotes \else
+% \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
+% \fi}
+
+% test:
+%
+% \setupcolumnset [test-1] [balance=yes]
+% \setupcolumnset [test-2] [balance=yes]
+% \setupcolumnsetlines[test-1][1][1] [8]
+% \setupcolumnsetlines[test-1][1][2][10]
+% \startcolumnset [test-1] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \startcolumnset [test-2] \dorecurse {2}{\input ward \par} \stopcolumnset
+
+\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi
+
+\installoutput\OTRSETflushpreposttext
+ {\global\setbox\precolumnbox\vbox
+ {\unvbox\normalpagebox
+ \global\lastskipinotr\lastskip}%
+ \ifdim\lastskipinotr>\zeropoint
+ \global\setbox\precolumnbox\hbox
+ {\lower\strutdepth\box\precolumnbox}%
+ \fi
+ \global\dp\precolumnbox\strutdepth
+ \ifcarryoverfootnotes \else
+ \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
+ \fi}
+
+\let\precolumnlines \!!zerocount
+\let\postcolumnlines\!!zerocount
+
+\def\OTRSEThandlepreposttext
+ {\ifdim\ht\precolumnbox>\zeropoint % new
+ \getnoflines{\ht\precolumnbox}%
+ \edef\precolumnlines{\the\noflines}%
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\plusone\nofcolumns\noflines
+ % normal version (single column set)
+ % {\box\precolumnbox}%
+ % compensated for bodyfont change
+ {\hbox
+ {\OTRSETsetcorrectcellht
+ \raise\scratchdimen\box\precolumnbox}}%
+ \else
+ \let\precolumnlines\!!zerocount
+ \fi
+ \ifdim\ht\postcolumnbox>\zeropoint % new, otherwise empty bottom line
+ \getnoflines{\ht\postcolumnbox}%
+ \edef\postcolumnlines{\the\noflines}%
+ \advance\columnfreecells -\noflines
+ \advance\columnfreecells \plusone
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\columnfreecells\nofcolumns\noflines
+ {\box\postcolumnbox}%
+ \else
+ \let\postcolumnlines\!!zerocount
+ \fi}
+
+\def\OTRSETchecksidefloat
+ {} % {\sidefloatoutput}
+
+\def\OTRSETfinalsidefloatoutput
+ {}
+
+\def\OTRSETcheckgrid
+ {\topskip1\topskip
+ \ifforcecolumngrid
+ \widowpenalty\zerocount
+ \clubpenalty\zerocount
+ \brokenpenalty\zerocount
+ \fi}
+
+\def\OTRSETcheckinsert
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \OTRSETforceinserts
+ \else
+ \OTRSETinhibitinserts
+ \fi
+ \else
+ \OTRSETforceinserts
+ \fi}
+
+\def\OTRSETforceinserts
+ {\enablenotes}
+
+\def\OTRSETinhibitinserts
+ {\disablenotes}
+
+% interface to footnotes
+
+\def\OTRSETassignwidths
+ {%\scratchdimen\makeupwidth
+ \freezetextwidth \scratchdimen\textwidth
+ %
+ \scratchcounter\zerocount
+ \dorecurse\nofcolumns
+ {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit
+ {\advance\scratchcounter \plusone }
+ {\advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}%
+ \advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!distance}}%
+ \ifcase\scratchcounter\else
+ \divide\scratchdimen \scratchcounter
+ \fi
+ \setgvalue{\??mc\??mc\c!width}{0}%
+ \dorecurse\nofcolumns
+ {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit
+ {\dimen0=\scratchdimen}
+ {\setgvalue{\??mc\??mc\c!width}{1}%
+ \dimen0=\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}%
+ \setxvalue{\??mc\recurselevel\??mc\c!width}{\the\dimen0}}}
+
+\def\OTRSETlocalwidth#1%
+ {\getvalue{\??mc\number#1\??mc\c!width}}
+
+\newbox\placeholderboxa
+\newbox\placeholderboxb
+\newbox\placeholderboxc
+\newbox\placeholderboxd
+\newbox\placeholderboxe
+\newbox\placeholderboxf
+
+\def\columnplaceholder#1#2%
+ {\hbox
+ {\localcolortrue
+ \setbox\scratchbox\hbox to \hsize
+ {\iftracecolumnset \incolortrue \localcolortrue
+ \hskip-.5ex%
+ \startcolor[columnset:#2]\vrule\!!width1ex\!!height.5ex\!!depth.5ex\stopcolor
+ \fi
+ \hss}%
+ \ifcase#1\relax
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\zeropoint
+ \else
+ \wd\scratchbox\hsize
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \fi
+ \box\scratchbox}}
+
+\definepalet
+ [columnset]
+ [a=cyan,b=green,c=blue,d=red,e=magenta,f=darkgray]
+
+\def\OTRSETsetplaceholders
+ {\global\setbox\placeholderboxa\columnplaceholder0a%
+ \global\setbox\placeholderboxb\columnplaceholder0b%
+ \global\setbox\placeholderboxc\columnplaceholder0c%
+ \global\setbox\placeholderboxd\columnplaceholder0d%
+ \global\setbox\placeholderboxe\columnplaceholder0e%
+ \global\setbox\placeholderboxf\columnplaceholder1f}
+
+\def\doOTRSETshowstatus
+ {\llap{\incolortrue \localcolortrue \tt\tfxx
+ \startcolor[blue](\the\vsize->\number\columnfirstcell\#\number\columnfreecells)\stopcolor
+ \hskip\leftskip}}
+
+\def\OTRSETshowstatus
+ {\iftracecolumnset \doOTRSETshowstatus \fi}
+
+% \appendtoks \OTRSETshowstatus \to \everypar
+
+% page contents
+
+\def\OTRSETdopagecontents#1#2% takes two args: \box \unvbox
+ {\vbox to \textheight{\forgetall#1#2\pushproperties}}
+
+\def\OTRSETsomepagefloat {\def\floatmethod{PAGE}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomeherefloat {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomeelsefloat {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomefixdfloat {\def\floatmethod{FIXD}\OTRSETsomeslotfloat} % check
+\def\OTRSETsometopfloat {\def\floatmethod{TOPS}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomebottomfloat{\def\floatmethod{BOTS}\OTRSETsomeslotfloat} % check
+
+\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
+ {\iftestfloatbox\ruledhbox\fi{\box\floatbox}}
+
+\def\OTRSETsomeslotfloat[#1]%
+ {\setbox\floatbox\vbox{\flushfloatbox}%
+ \dp\floatbox\strutdp
+ \@EA\uppercasestring\floatmethod\to\floatmethod
+ \OTRSETstoreincolumnslot\floatmethod\floatbox
+ \doinsertfloatinfo}
+
+% kind of new, looks much like OTRONE, but not entirely
+
+\def\OTRSETdosettopinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \let\totaltopinserted\!!zeropoint
+ \OTRSETdodosettopinserts
+ \ifnum\@@bknbottom=\zerocount
+ \ifnum\@@bknlines>\zerocount
+ \ifdim\totaltopinserted>\zeropoint\relax
+ \dimen0\lineheight
+ \dimen0=\@@bknlines\dimen0
+ \advance\dimen0 \totaltopinserted\relax
+ \ifdim\dimen0>\textheight % \vsize %%%%%%%%% \textheight
+ \showmessage\m!floatblocks8{\@@bknlines}%
+ \vfilll\eject
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRSETdodosettopinserts
+ {\ifnum\noffloatinserts<\noftopfloats
+ \dogetfloat
+ \ifdim\topinserted=\zeropoint\relax
+ \topofinserttrue
+ \else
+ \topofinsertfalse
+ \fi
+ \setbox\scratchbox\vbox % kan beter !
+ {\forgetall
+ \iftopofinsert
+ \ifdim\OTRSETtopoffset=\zeropoint
+ \moveongrid[\v!top]
+ \fi
+ \else
+ \betweenfloatblanko % inserts can't look back
+ \fi
+ \flushfloatbox
+ \blank[\@@bkspaceafter]}%
+ \global\advance\topinserted \ht\scratchbox\relax
+ \ifdim\topinserted>\vsize % was \textheight\relax
+ \OTRSETresavebox\floatbox
+ \noffloatinserts\noftopfloats\relax
+ \global\advance\topinserted -\ht\scratchbox
+ \let\OTRSETdodosettopinserts\relax % to be tested
+ \else
+ \xdef\totaltopinserted{\the\topinserted}%
+ \insert\topins{\forgetall\box\scratchbox}% interlineskip ?
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\noftopfloats\relax
+ \fi
+ \dofloatflushedinfo
+ \fi
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks6{\the\noftopfloats}%
+ \fi
+ \let\OTRSETdodosettopinserts\relax
+ \fi
+ \OTRSETdodosettopinserts}
+
+\def\OTRSETdosetbotinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \OTRSETdodosetbotinserts
+ \fi
+ \egroup}
+
+\def\OTRSETdodosetbotinserts
+ {\ifnum\noffloatinserts<\nofbotfloats\relax
+ \dogetfloat
+ \global\advance\botinserted \ht\floatbox\relax
+ \global\advance\botinserted \dp\floatbox\relax
+ \global\advance\botinserted \floattopskip\relax
+ \ifdim\botinserted<\pagegoal\relax
+ \insert\botins
+ {\forgetall
+ \blank[\@@bkspacebefore]%
+ \flushfloatbox}%
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\nofbotfloats
+ \fi
+ \dofloatflushedinfo
+ \else
+ \OTRSETresavebox\floatbox
+ \noffloatinserts\nofbotfloats\relax
+ \fi
+ \global\nofloatpermittedtrue % vgl topfloats s!
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks7{\the\nofbotfloats}%
+ \fi
+ \let\OTRSETdodosetbotinserts\relax
+ \fi
+ \OTRSETdodosetbotinserts}
+
+\let\OTRSETdosetbothinserts\relax
+
+\def\OTRSETdotopinsertions
+ {\ifvoid\topins\else
+ \ifvoid\columntopbox\mofcolumns
+ \columnsettopbox\mofcolumns\box\topins
+ \else
+ \columnsettopbox\mofcolumns\vbox % temp, must be better
+ {\forgetall
+ \offinterlineskip
+ \box\columntopbox\mofcolumns
+ \box\topins}
+ \fi
+ \fi
+ \global\topinserted\zeropoint\relax} % goes away
+
+\def\OTRSETdobotinsertions
+ {\ifvoid\botins \else
+ \columnsetbotbox\mofcolumns\box\botins
+% \else
+% \columnsetbotbox\mofcolumns\vbox % temp, must be better
+% {\forgetall
+% \offinterlineskip
+% \box\botins
+% \box\columnbotbox\mofcolumns}
+ \fi
+ \global\botinserted\zeropoint\relax} % goes away
+
+% set ipv text
+
+% left right 1 2 3 +1 +2 +3
+
+\let\columnleftareas \empty
+\let\columnrightareas\empty
+
+% links rechts => odd, even, n, named
+
+\def\definecolumntextarea
+ {\dotripleempty\dodefinecolumntextarea}
+
+\def\dodefinecolumntextarea[#1][#2][#3]% y=0 is mogelijke en handig !
+ {\ifthirdargument
+ \doifinsetelse{#2}{\v!both,\v!fixed}
+ {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]%
+ \definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
+ {\doifelse{#2}\v!next
+ {\doifoddpageelse
+ {\definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
+ {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]}}
+ {\presetlocalframed
+ [\??mt#1#2]%
+ \processaction[#2] % \doglobal voorkomt stack build up
+ [ \v!left=>\doglobal\addtocommalist{#1}\columnleftareas,
+ \v!right=>\doglobal\addtocommalist{#1}\columnrightareas]%
+ \getparameters[\??mt#1#2]
+ [\c!x=1,\c!y=1,\c!nx=1,\c!ny=1,\c!clipoffset=2\lineheight,
+ \c!leftoffset=\zeropoint,\c!rightoffset=\zeropoint,
+ \c!offset=\v!overlay,\c!strut=\v!no,\c!frame=\v!off,
+ \c!type=#2,\c!page=1,\c!state=\v!stop,#3]}}%
+ \else
+ \definecolumntextarea[#1][\v!next][#2]%
+ \fi}
+
+\def\setupcolumntextarea
+ {\dotripleempty\dosetupcolumntextarea}
+
+\def\dosetupcolumntextarea[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#2}\v!both
+ {\setupcolumntextarea[#1][\v!left ][#3]%
+ \setupcolumntextarea[#1][\v!right][#3]}
+ {\doifelse{#2}\v!next
+ {\doifoddpageelse
+ {\setupcolumntextarea[#1][\v!right][#3]}
+ {\setupcolumntextarea[#1][\v!left][#3]}}
+ {\getparameters[\??mt#1#2][#3]}}%
+ \else
+ \setupcolumntextarea[#1][\v!next][#2]%
+ \fi}
+
+\def\docheckcolumnsetareapage#1#2%
+ {\ifnum\getvalue{\??mt#1\c!page}>\plusone
+ \doifelsevalue{\??mt#1\c!type}\v!fixed
+ {\ifnum\columnsetpage=\getvalue{\??mt#1\c!page}\relax
+ \donetrue\else\donefalse
+ \fi}
+ {\ifnum\columnsetpage<\getvalue{\??mt#1\c!page}\relax
+ \donefalse\else\donetrue
+ \fi}%
+ \else
+ \donetrue
+ \fi}
+
+\def\initializecolumntextareas
+ {\ifodd\realpageno
+ \doinitializecolumntextareas\columnrightareas\v!right
+ \else
+ \doinitializecolumntextareas\columnleftareas\v!left
+ \fi}
+
+\def\doinitializecolumntextareas#1#2%
+ {\def\docommand##1%
+ {\docheckcolumnsetareapage{##1#2}\plusone
+ \ifdone
+ \donefalse
+ \processaction
+ [\getvalue{\??mt##1#2\c!state}]
+ [ \v!start=>\donetrue,
+ \v!repeat=>\donetrue,
+ \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
+ \ifdone\dodoinitializecolumntextareas{##1}{#2}\fi
+ \fi}%
+ \processcommacommand[#1]\docommand}
+
+\def\dodoinitializecolumntextareas#1#2%
+ {\doOTRSETsetgridcells
+ {\copy\placeholderboxd}
+ {\getvalue{\??mt#1#2\c!x }}{\getvalue{\??mt#1#2\c!y }}
+ {\getvalue{\??mt#1#2\c!nx}}{\getvalue{\??mt#1#2\c!ny}}
+ {\copy\placeholderboxd}}
+
+\def\placecolumntextareas
+ {\ifodd\realpageno
+ \doplacecolumntextareas\columnrightareas\v!right
+ \else
+ \doplacecolumntextareas\columnleftareas\v!left
+ \fi}
+
+\def\doplacecolumntextareas#1#2% global ?
+ {\bgroup
+ \forgetall
+ \def\docommand##1%
+ {\docheckcolumnsetareapage{##1#2}\zerocount
+ \ifdone
+ \donefalse
+ \processaction
+ [\getvalue{\??mt##1#2\c!state}]
+ [ \v!start=>\donetrue\doglobal\removefromcommalist{##1}#1,
+ \v!repeat=>\donetrue,
+ \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
+ \ifdone
+ \dodoplacecolumntextareas{##1}{#2}%
+ \else
+ \doglobal\removefromcommalist{##1}#1%
+ \fi
+ \fi}%
+ \processcommacommand[#1]\docommand
+ \egroup}
+
+% \page[left]
+% \definecolumntextarea[intro][left][x=1,y=1,nx=4,ny=20,state=start,background=introlayer]
+% \setupcolumntextareatext[intro][left][\setups{intro}]
+% \flushcolumntextareas
+
+\def\flushcolumntextareas
+ {\initializecolumntextareas
+ \setvsize}
+
+\def\columntextlastbackspace{\backspace}
+
+% beware, we have clipping offsets of 2\lineheight by default
+
+\def\columntextareaparameter#1%
+ {\csname\??mt\currentcolumntestarea#1\endcsname}
+
+\def\dodoplacecolumntextareas#1#2%
+ {\def\currentcolumntestarea{#1#2}%
+ \!!counta\columntextareaparameter\c!x
+ \!!countb\columntextareaparameter\c!nx
+ \docalculatecolumnsetspan
+ \!!heighta\columntextareaparameter\c!ny\lineheight
+ % wrong
+ % \ifnum\columntextareaparameter\c!y=\zerocount
+ % \advance\!!heighta -\lineheight
+ % \advance\!!heighta \topskip
+ % \fi
+ % \advance\!!heighta -\lineheight % option
+ \ifnum\columntextareaparameter\c!y=\plusone
+ \advance\!!heighta -\lineheight
+ \advance\!!heighta \topskip
+ \fi
+ %
+ \setbox\scratchbox\vbox
+ {\donetrue\localframed
+ [\??mt\currentcolumntestarea]
+ [\c!location=,% new (*)
+ \c!width=\!!widtha,\c!height=\!!heighta,\c!lines=]
+ {\columntextareaparameter\empty}}%
+ \!!counta\columntextareaparameter\c!x
+ \!!countb\columntextareaparameter\c!y
+ \advance\!!countb \columntextareaparameter\c!ny
+ \advance\!!countb \minusone
+ % new (*)
+ \doif{\columntextareaparameter\c!location}\v!depth
+ {\setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\zeropoint
+ \ht\scratchbox\!!heighta}%
+ %
+ \setbox0\hbox
+ {\ifcase\!!countc
+ \copy\scratchbox % \box
+ \else
+ \clip
+ [ %\c!topoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!leftoffset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!rightoffset=\columntextareaparameter\c!rightoffset,%
+ \c!width=\!!widthb,%
+ \c!height=\!!heighta]%
+ {\copy\scratchbox}%
+ \fi}%
+ \OTRSETsetgridcell\!!counta\!!countb\box0
+ \ifcase\!!countc\else
+ \advance\!!counta \columntextareaparameter\c!nx
+ \advance\!!counta -\!!countc
+ \advance\!!widtha -\!!widthb
+ \setbox0\hbox
+ {\hskip-\namedlayoutparameter\v!odd\c!backspace
+ \clip
+ [ %\c!topoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!rightoffset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!leftoffset=\columntextareaparameter\c!leftoffset,%
+ \c!width=\!!widtha,%
+ \c!height=\!!heighta,%
+ \c!hoffset=\!!widthb]%
+ {\copy\scratchbox}}%
+ \OTRSETsetgridcell\!!counta\!!countb\box0%
+ \fi}
+
+\def\setupcolumntextareatext
+ {\dotripleempty\dosetupcolumntextareatext}
+
+\long\def\dosetupcolumntextareatext[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#2}\v!both
+ {\setvalue{\??mt#1\v!left }{#3}%
+ \setvalue{\??mt#1\v!right}{#3}}
+ {\doifelse{#2}\v!next
+ {\doifoddpageelse
+ {\setvalue{\??mt#1\v!right}{#3}}%
+ {\setvalue{\??mt#1\v!left }{#3}}}%
+ {\setvalue{\??mt#1#2}{#3}}}%
+ \else
+ \setupcolumntextareatext[#1][\v!next][{#2}]%
+ \fi}
+
+\def\docalculatecolumnsetspan
+ {% \!!counta <= x
+ % \!!countb <= nx
+ % \!!widtha => total width
+ % \!!widthb => left width
+ % \!!countc => left cols
+ \!!widtha\!!countb\textwidth % we assume equal widths
+ \advance\!!countb \!!counta
+ \advance\!!countb \minusone
+ \ifnum\!!countb>\nofcolumns
+ \!!countc\!!countb
+ \advance\!!countc -\nofcolumns
+ \!!countb\nofcolumns
+ \else
+ \!!countc\zerocount
+ \fi
+ \advance\!!counta \plusone
+ \dostepwiserecurse\!!counta\!!countb\plusone
+ {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}%
+ \!!widthb\!!widtha
+ \advance\!!widthb -\!!countc\textwidth
+ \ifodd\realpageno \else % tricky, assumes that we keep there
+ \ifcase\!!countc\else
+ % nog niet ok voor enkel/doublesided
+ \advance\!!widtha \namedlayoutparameter\v!even\c!backspace
+ \advance\!!widtha \namedlayoutparameter\v!odd \c!backspace
+ \advance\!!widthb \namedlayoutparameter\v!even\c!backspace
+ \dorecurse\!!countc
+ {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}%
+ \fi
+ \fi}
+
+\def\columnsetspanhsize{\textwidth}
+
+\def\setcolumnsetspanhsize#1#2% x nx / uses counta/b
+ {\!!counta#1\!!countb#2\docalculatecolumnsetspan
+ \edef\columnsetspanhsize{\the\!!widtha}}
+
+\def\definecolumnsetspan
+ {\dodoubleempty\dodefinecolumnsetspan}
+
+\def\dodefinecolumnsetspan[#1][#2]%
+ {%\ifsecondargument
+ \defineframedtext
+ [cs:#1]
+ [\c!frame=\v!off,
+ \c!before=,
+ \c!after=,
+ \c!offset=\v!overlay,
+ \c!location=\v!left,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ \c!n=2,
+ \c!nlines=0,
+ \c!indenting=,
+ \c!indentnext=\v!yes,
+ \c!default=HERE,
+ \c!alternative=\v!a,
+ #2]%
+ %\else
+ % \definecolumnspan[][#1]%
+ }%\fi}
+
+\definecolumnsetspan[\s!default]
+
+\def\setupcolumnsetspan
+ {\dodoubleempty\dosetupcolumnsetspan}
+
+\def\dosetupcolumnsetspan[#1][#2]%
+ {\ifsecondargument
+ \setupframedtexts[cs:#1][#2]%
+ \else
+ \setupcolumnsetspan[\s!default][#1]%
+ \fi}
+
+\def\startcolumnsetspan
+ {\dotripleempty\dostartcolumnsetspan}
+
+%%%%%%%%%%%%%%%% TODO
+
+\def\dostartcolumnsetspan[#1][#2][#3]% [#3] gobbles space
+ {\endgraf % else rubish output if forgotten
+ \vskip \zeropoint % make sure otr is done, otherwise last line problems
+ \bgroup
+ \forgetall
+ \ifnum\columnsetlevel>\zerocount\else
+ % of course we needed a one-column fall back for tm
+ \columnsetspanhsize\hsize
+ \nofcolumns\plusone
+ \mofcolumns\plusone
+ \fi
+ \setupframedtexts[cs:#1]
+ [\c!width=\columnsetspanhsize,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ #2]%
+ % determine widths
+ \!!countc\framedtextparameter{cs:#1}\c!n
+ % \!!countd\numexpr(\nofcolumns-\mofcolumns+\plusone)%
+ \!!countd\nofcolumns
+ % n <= n of columns
+ \ifnum\!!countc>\!!countd \!!countc\!!countd \fi
+ \advance\!!countd -\mofcolumns
+ \advance\!!countd \plusone
+ % n <= n of available columns (alternative a)
+ \doif{\framedtextparameter{cs:#1}\c!alternative}\v!a
+ {\ifnum\!!countc>\!!countd \!!countc\!!countd \fi}%
+ % here it all starts
+ \setcolumnsetspanhsize\mofcolumns\!!countc % a/b used
+ \hsize\columnsetspanhsize
+ \setbox\scratchbox\vbox\bgroup
+ \dostartframedtext[cs:#1][\v!none]% geen nils placement
+ % spoils spacing : \vskip-\struttotal\par\verticalstrut\par
+ \ifnum\columnsetlevel>\zerocount
+ \framedtextparameter{cs:#1}\c!before
+ \fi
+ \def\stopcolumnsetspan{\dostopcolumnsetspan{#1}}}
+
+\def\dostopcolumnsetspan#1%
+ {\par
+ \verticalstrut
+ \kern-2\struttotal
+ \verticalstrut
+ \ifnum\columnsetlevel>\zerocount
+ \doifsomething{\framedtextparameter{cs:#1}\c!after}
+ {\framedtextparameter{cs:#1}\c!after
+ \kern\zeropoint}% otherwise blanks disappear, better be a switch
+ \else
+ \endgraf
+ \fi
+ \dostopframedtext
+ \egroup
+ \setbox\scratchbox\frozenhbox to \hsize
+ {\dontcomplain
+ \alignedline{\framedtextparameter{cs:#1}\c!location}\v!middle
+ {\lower\strutdepth\box\scratchbox}}%
+ \dp\scratchbox\zeropoint % else wrong snap insidefloat
+%
+% to be tested first (strange in grid mode)
+%
+% \setbox\scratchbox\frozenhbox to \hsize
+% {\dontcomplain
+% \chardef\alignstrutmode\zerocount
+% \alignedline{\framedtextparameter{cs:#1}\c!plaats}\v!midden
+% {\box\scratchbox}}%
+%
+ \ifinsidefloat
+ \box\scratchbox
+ \else\ifnum\columnsetlevel>\zerocount
+ % we only set \columnsetspacing when asked for, else bottom problems
+ % don't change this any more (test naw)
+ \chardef\columnslotspacing\framedtextparameter{cs:#1}\c!nlines\relax
+ % todo: nboven/onder & \chardef\columnslotlocation2
+ %\OTRSETstoreincolumnslotHERE\scratchbox
+ \edef\floatmethod{\framedtextparameter{cs:#1}\c!default}%
+ \@EA\uppercasestring\floatmethod\to\floatmethod
+ % todo : \v!here -> here enzovoorts
+ \OTRSETstoreincolumnslot\floatmethod\scratchbox
+ % watch out: no \dochecknextindentation{tag}
+ \checknextindentation[\framedtextparameter{cs:#1}\c!indentnext]%
+ \else
+ % of course we needed a one-column fall back for tm; brrr, the box has now too
+ % much height (try \ruledvbox); don't change this without testing techniek
+ \scratchdimen\ht\scratchbox
+ \advance\scratchdimen-\strutdp
+ \ht\scratchbox\scratchdimen
+ \framedtextparameter{cs:#1}\c!before
+ \snaptogrid\vbox{\box\scratchbox}%
+ \framedtextparameter{cs:#1}\c!after
+ \fi\fi
+ \egroup
+ \endgraf}
+
+% \startcolumnset[two]
+% \input tufte
+% \startcolumnsetspan[two][width=20cm,location=middle] \input tufte \stopcolumnsetspan
+% \startcolumnsetspan[two][default=btlr] \input tufte \stopcolumnsetspan
+% \input tufte \par
+% \input tufte \par
+% \startcolumnsetspan[two] \emptylines[5] \stopcolumnsetspan
+% \startcolumnsetspan[two] \input tufte \stopcolumnsetspan
+% \stopcolumnset
+
+\protect \endinput
+
+% extreme examples (1)
+%
+% \setupfloats[numbering=nocheck]
+%
+% \definecolumnset [first] [n=2,start=0]
+% \definecolumnset [next] [n=2,start=3]
+%
+% \setuptexttexts[\vbox to \textheight{\topskipcorrection \hsize\makeupwidth left \hfill right\vfill}]
+%
+% \setuphead[chapter][text=empty]
+%
+% \starttext
+%
+% \startcolumnset[first,next]
+% \placefigure[btrl]{}{}
+% \placefigure[tblr]{}{}
+% \chapter{thuan} \dorecurse{25}{\recurselevel: \input thuan \endgraf}
+% \stopcolumnset
+%
+% \startcolumnset[first,next]
+% \chapter{thuan} \dorecurse{25}{\input thuan \endgraf\placefigure{}{}}
+% \stopcolumnset
+
+\unprotect
+
+% only in columnsets
+
+% \def\cornerfigure
+% {\dotripleempty\docornerfigure}
+%
+% \def\docornerfigure[#1][#2][#3]% [layer] [location] [settings]
+% {\bgroup
+% \dowithnextbox
+% {\!!doneafalse
+% \!!donebfalse
+% \processallactionsinset
+% [\v!left,\v!bottom,#2]
+% [ \v!left=>\!!doneatrue ,
+% \v!right=>\!!doneafalse,
+% \v!top=>\!!donebtrue ,
+% \v!bottom=>\!!donebfalse]%
+% \!!widtha\nextboxwd
+% \if!!donea
+% % unchecked
+% \advance\!!widtha-\backspace
+% \else
+% % unchecked
+% \advance\!!widtha-\backspace
+% \fi
+% \!!widtha\textwidth % could be an option
+% \!!heighta\nextboxht
+% % zou een macro moeten zijn \getnoflayoutlines
+% \ifnum\layoutparameter\c!lines=\zerocount
+% \getnoflines\textheight
+% \else
+% \noflines\layoutparameter\c!lines
+% \fi
+% %
+% \advance\noflines \plusone % wordt default, instelbaar
+% \!!heightb\noflines\lineheight\relax
+% \if!!doneb % boven
+% % unchecked
+% \advance\!!heighta-\topspace
+% \advance\!!heighta-\headerheight
+% \advance\!!heighta-\headerdistance
+% \else % onder
+% % checked
+% \advance\!!heighta-\paperheight
+% \advance\!!heighta+\!!heightb
+% \advance\!!heighta+\topspace
+% \advance\!!heighta+\headerheight
+% \advance\!!heighta+\headerdistance
+% \advance\!!heighta-\footerdistance
+% \advance\!!heighta-\footerheight
+% \fi
+% \getnoflines\!!heighta
+% \!!heighta\noflines\lineheight\relax
+% \def\docornerfigure[####1]%
+% {\expanded{\plaatsfiguur[####1,\v!none]{}
+% {\noexpand\phantombox[\c!width=\the\!!widtha,\c!height=\the\!!heighta]}}}%
+% \if!!donea
+% \if!!doneb % links boven / rb
+% \setlayer[#1]
+% [\c!corner={\v!left,\v!top},\c!location=rb,#3]
+% {\flushnextbox}%
+% \docornerfigure[tblr]%
+% \else % links onder / rt
+% \setlayer[#1]
+% [\c!corner={\v!left,\v!bottom},\c!location=rt,#3]
+% {\flushnextbox}%
+% \docornerfigure[btlr]%
+% \fi
+% \else
+% \if!!doneb % rechts boven / lt
+% \setlayer[#1]
+% [\c!corner={\v!right,\v!top},\c!location=lb,#3]
+% {\flushnextbox}%
+% \docornerfigure[tbrl]%
+% \else % rechts onder / lb
+% \setlayer[#1]
+% [\c!corner={\v!right,\v!bottom},\c!location=lt,#3]
+% {\flushnextbox}%
+% \docornerfigure[btrl]%
+% \fi
+% \fi
+% \egroup}
+% \vbox}
diff --git a/tex/context/base/page-set.mkiv b/tex/context/base/page-set.mkiv
new file mode 100644
index 000000000..cc6fbb5e6
--- /dev/null
+++ b/tex/context/base/page-set.mkiv
@@ -0,0 +1,2674 @@
+%D \module
+%D [ file=page-set,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Column Sets,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% getnoflines vs getrawnoflines
+
+% some day: cleanup and go etex
+
+\writestatus{loading}{ConTeXt Page Macros / Column Sets}
+
+% todo : last longer than previous
+% todo : block span over last column if footnotes
+% todo : diagnosis balancing run
+% todo : separate footnote placement
+% todo : go on on same page with colset
+% todo : test page areas per page
+% todo : leftmargin/rightmargin (better than afstand(1))
+
+% use the OTRSET layer for more purposes, like the footnotes !
+
+\unprotect
+
+\newcount\tofcolumns % total
+\newcount\lofcolumns % left
+\newcount\rofcolumns % right
+
+\newcount\columnfirstcell \columnfirstcell=1
+\newcount\columnlastcell
+\newcount\columnfreecells
+\newcount\currenthcell
+\newcount\currentvcell
+\newcount\columnhcells
+\newcount\columnvcells
+
+\newif\ifenoughcolumncells
+\newif\ifsomefreecolumncells
+\newif\ifcolumnspread
+\newif\iftracecolumnset % \tracecolumnsettrue
+
+\def\columnmaxcells {75} % runtime
+\def\columnmaxfreecells {0} % runtime
+\def\columngaplimit {0} % {5}
+
+\def\@otr@{otr}
+
+\def\OTRSETmakeupwidth{\innermakeupwidth}
+
+\let\OTRSETflushsidefloats \forgetsidefloats % \relax
+\let\OTRSETsynchronizesidefloats\forgetsidefloats % \relax
+
+\def\OTRSETgridcell #1#2{\csname \@otr@:\number#1:\number#2\endcsname}
+\def\OTRSETgetgridcell#1#2{\box\csname \@otr@:\number#1:\number#2\endcsname}
+\def\OTRSETsetgridcell#1#2{\global\setbox\csname\@otr@:\number#1:\number#2\endcsname}
+
+\long\def\OTRSETdoifcellelse#1#2%
+ {\relax\ifvoid\csname\@otr@:\number#1:\number#2\endcsname
+ \@EA\secondoftwoarguments\else\@EA\firstoftwoarguments
+ \fi}
+
+% The following two macros are used to compensate for a switch in body fonts
+% as in:
+%
+% \definecolumnset [two] [n=2,balancing=yes]
+% \definecolumnset [three] [n=3,balancing=yes]
+%
+% \setupcolumnsetlines[two][1][1][7]
+% \setupcolumnsetlines[two][1][2][10]
+%
+% \setupcolumnsetlines[three][1][1][40]
+% \setupcolumnsetlines[three][1][2][40]
+% \setupcolumnsetlines[three][1][3][40]
+%
+% \setupcolumnsetstart[three][1][1][15]
+% \setupcolumnsetstart[three][1][2][20]
+% \setupcolumnsetstart[three][1][3][20]
+%
+% \starttext
+% \startcolumnset [two] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \switchtobodyfont[small]
+% \startcolumnset [three] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \stoptext
+
+%D Marks in columnsets:
+%D
+%D \starttyping
+%D \definemarking[M]
+%D \setupheadertexts[\setups{show-M-marks}]
+%D \definecolumnset[test][n=3]
+%D
+%D \startsetups show-M-marks
+%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][1][last]\quad
+%D \getmarking[M][2][previous]/\getmarking[M][2][first]/\getmarking[M][2][last]\quad
+%D \getmarking[M][3][previous]/\getmarking[M][3][first]/\getmarking[M][3][last]\quad
+%D \getmarking[M][1][previous]/\getmarking[M][1][first]/\getmarking[M][last]\quad
+%D \getsavedmarking[M][previous]/\getsavedmarking[M][first]/\getsavedmarking[M][last]
+%D \stopsetups
+%D
+%D \startbuffer
+%D \section{Knuth} [K1]\marking[M]{k1} [K2]\marking[M]{k2} \input knuth
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \stopbuffer
+%D
+%D \startbuffer
+%D \section{Ward} [W]\marking[M]{w} \input ward
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D \section{Davis} [D]\marking[M]{d} \input davis
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \stopbuffer
+%D
+%D \startbuffer
+%D \section{Ward} [W]\marking[M]{w} \input ward
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D \section{Davis} [D]\marking[M]{d} \input davis
+%D \section{Zapf} [Z]\marking[M]{z} \input zapf
+%D \section{Douglas} [O]\marking[M]{o} \input douglas
+%D \stopbuffer
+%D
+%D \starttext
+%D \startcolumnset[test]
+%D \dorecurse{5}{\getbuffer}
+%D \placefigure[here]{none}{\externalfigure[a][height=2cm]}
+%D % \column % sometimes needed
+%D \stopcolumnset
+%D \stoptext
+%D \stoptyping
+
+% not ok yet, for column sets we need a special case: within a column we
+% need to bubble-up the marks; the indirectness permits overloading here
+
+\let\saveOTRSETmark \refreshsavedmark
+\let\bubbleOTRSETmark\bubblesavedmark
+\let\resetOTRSETmark \resetsavedmark
+\let\presetOTRSETmark\presetsavedmark
+
+\def\doregisterOTRSETmarks#1{\saveOTRSETmark [#1][\number\mofcolumns]}
+\def\dobubbleOTRSETmarks #1{\bubbleOTRSETmark[#1][\number\mofcolumns]}
+\def\doresetOTRSETmarks #1{\resetOTRSETmark [#1][\recurselevel]}
+\def\dopresetOTRSETmarks #1{\presetOTRSETmark[#1][\recurselevel]}
+
+\def\registerOTRSETmarks
+ {\processcommacommand[\alldefinedmarks]\doregisterOTRSETmarks}
+\def\bubbleOTRSETmarks
+ {\processcommacommand[\alldefinedmarks]\dobubbleOTRSETmarks}
+\def\resetOTRSETmarks
+ {\dorecurse\nofcolumns{\processcommacommand[\alldefinedmarks]\doresetOTRSETmarks}}
+\def\presetOTRSETmarks
+ {\dorecurse\nofcolumns{\processcommacommand[\alldefinedmarks]\dopresetOTRSETmarks}}
+
+%D test case of Vit Zika (context list):
+%D
+%D \starttyping
+%D \setuplayout[height=middle,width=middle,grid=yes]
+%D
+%D \starttext
+%D \startcolumnset
+%D \dorecurse{10}
+%D {\input thuan \endgraf
+%D \bgroup
+%D \ss\restoreinterlinespace
+%D \dorecurse{3}{\input hawking \endgraf}
+%D \egroup
+%D \input bryson \endgraf}
+%D \stopcolumnset
+%D \stoptext
+%D \stoptyping
+
+\def\OTRSETsetcorrectnofcells#1%
+ {\bgroup
+ \!!counta#1\relax
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \restoreinterlinespace
+ \else
+ \!!dimena-\!!counta\lineheight
+ \restoreglobalbodyfont % slow, we need a fast one
+ \advance\!!dimena\!!counta\lineheight
+ \getnoflines\!!dimena
+ \advance\!!counta\noflines
+ \ifnum\!!counta<#1\else
+ \!!counta#1\relax
+ \fi
+ \fi
+ \relax % needed ! ! ! ! else lookahead over \fi and \@EA
+ \@EA\egroup\@EA\scratchcounter\the\!!counta\relax}
+
+\def\OTRSETsetcorrectcellht
+ {\bgroup
+ \!!dimena-\strutht\relax
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \restoreinterlinespace
+ \else
+ \restoreglobalbodyfont
+ \fi
+ \advance\!!dimena\strutht
+ \relax % needed ! ! ! ! else lookahead over \fi and \@EA
+ \@EA\egroup\@EA\scratchdimen\the\!!dimena\relax}
+
+\def\columnerasegridboxes % maybe dedicated loops
+ {\bgroup
+ \increment\columnmaxcells\relax
+ \ifodd\realpageno
+ \else % we are on the other page
+ \columnspreadfalse
+ \fi
+ \ifcolumnspread
+ \dorecurse\nofcolumns
+ {\let\!!stringa\recurselevel
+ \scratchcounter\recurselevel \advance\scratchcounter\lofcolumns
+ \edef\!!stringb{\the\scratchcounter}%
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
+ \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
+ \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
+ \box\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \else
+ \emptybox
+ %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox
+ \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \fi
+ \else
+ \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
+ \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
+ \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \else
+ \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
+ \fi
+ \fi}}%
+ \else
+ \dorecurse \tofcolumns
+ {\let\!!stringa\recurselevel
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
+ \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox
+ \else
+ \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
+ \fi}}%
+ \fi
+ \dorecurse\tofcolumns
+ {\global\setbox\csname\@otr@:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}%
+ \global\columnfirstcell\zerocount
+ \global\columnlastcell\columnfirstcell
+ \global\columnfreecells\columnfirstcell
+ \egroup}
+
+\def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data}
+ {\!!countd#2\advance\!!countd#4\advance\!!countd\minusone
+ \!!counte#3\advance\!!counte#5\advance\!!counte\minusone
+ \dostepwiserecurse{#2}\!!countd\plusone
+ {\!!countf\recurselevel
+ \dostepwiserecurse{#3}\!!counte\plusone
+ {\OTRSETsetgridcell\!!countf\recurselevel#1}}%
+ \dostepwiserecurse{#3}\!!counte\plusone
+ {\global\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
+ \OTRSETsetgridcell{#2}\!!counte#6}
+
+\def\OTRSETsetgridcells
+ {\doOTRSETsetgridcells{\copy\placeholderboxb}}
+
+\def\OTRSETerasegridcells#1#2#3#4%
+ {\doOTRSETsetgridcells{\emptybox}{#1}{#2}{#3}{#4}{\emptybox}}
+
+\unexpanded\def\setupcolumnsetlines{\doquintupleempty\dosetupcolumnsettrick[l]}
+\unexpanded\def\setupcolumnsetstart{\doquintupleempty\dosetupcolumnsettrick[s]}
+
+\def\dosetupcolumnsettrick[#1][#2][#3][#4][#5]% tag id page col value
+ {% not needed, is already relative
+ % \doifinstringelse{+}{#3}{\scratchcounter\realpageno}{\scratchcounter\zerocount}%
+ % \advance\scratchcounter#3\relax % \relax needed
+ % \setevalue{\??mc:#1:#2:\the\scratchcounter:\number#4}{\number#5}}
+ \iffifthargument
+ \setevalue{\??mc:#1:#2:\number#3:\number#4}{\number#5}%
+ \else
+ \setevalue{\??mc:#1:#2:\number#3:0}{\number#4}%
+ \fi}
+
+\def\currentcolumnmaxcellstag #1{\??mc:l:\OTRSETidentifier:\columnsetpage:\number#1}
+\def\currentcolumnstartcelltag#1{\??mc:s:\OTRSETidentifier:\columnsetpage:\number#1}
+
+\def\doresetcolumnsetlines#1%
+ {\ifcsname\currentcolumnmaxcellstag{#1}\endcsname
+ \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
+ \fi
+ \ifcsname\currentcolumnmaxcellstag{#1}\endcsname
+ \letgvalue{\currentcolumnmaxcellstag{#1}}\zerocount
+ \fi}
+
+\def\currentcolumnsomecells#1#2%
+ {\ifcsname#1\mofcolumns\endcsname
+ \ifnum\csname#1\mofcolumns\endcsname=\zerocount
+ #2%
+ \else
+ \number\numexpr\ifnum\csname#1\mofcolumns\endcsname<\zerocount
+ \columnmaxcells+\fi\csname#1\mofcolumns\endcsname\relax
+ \fi
+ \else\ifcsname#10\endcsname
+ \ifnum\csname#10\endcsname=\zerocount
+ #2%
+ \else
+ \number\numexpr\ifnum\csname#10\endcsname<\zerocount
+ \columnmaxcells+\fi\csname#10\endcsname\relax
+ \fi
+ \else
+ #2%
+ \fi\fi}
+
+\def\currentcolumnmaxcells {\currentcolumnsomecells\currentcolumnmaxcellstag \columnmaxcells}
+\def\currentcolumnstartcell{\currentcolumnsomecells\currentcolumnstartcelltag\plusone}
+
+\def\OTRSETsetfreecells#1#2% col start
+ {\bgroup
+ \global\columnfirstcell\ifnum#2=0 1\else#2\fi\relax
+ \OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
+ \edef\columnmaxcells{\the\scratchcounter}%
+ \ifnum\columnfirstcell>\columnmaxcells
+ \global\columnfreecells\zerocount
+ \global\columnfirstcell\plusone
+ \global\columnlastcell \zerocount
+ \global\somefreecolumncellsfalse
+ %\message{no cells a}%
+ \else
+ \doloop
+ {\ifnum\columnfirstcell>\columnmaxcells\relax
+ \exitloop
+ \else
+ \OTRSETdoifcellelse{#1}\columnfirstcell
+ {\global\advance\columnfirstcell\plusone}\exitloop
+ \fi}%
+ \global\columnlastcell\columnfirstcell
+ \doloop
+ {\ifnum\columnlastcell>\columnmaxcells\relax
+ \exitloop
+ \else
+ \OTRSETdoifcellelse{#1}\columnlastcell
+ {\global\advance\columnlastcell \minusone \exitloop}
+ {\global\advance\columnlastcell \plusone }%
+ \fi}%
+ \ifnum\columnfirstcell>\columnmaxcells
+ \global\columnfreecells\zerocount
+ \global\columnfirstcell\plusone
+ \global\columnlastcell \zerocount
+ \global\somefreecolumncellsfalse
+ %\message{no cells b}%
+ \else
+ \ifnum\columnlastcell>\columnmaxcells
+ \global\columnlastcell\columnmaxcells
+ \fi
+ \global\columnfreecells\columnlastcell
+ \global\advance\columnfreecells -\columnfirstcell
+ \global\advance\columnfreecells \plusone
+ \global\somefreecolumncellstrue
+ %\message{\number\columnfirstcell-\number\columnlastcell=\number\columnfreecells}%
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRSETgetmaxfreecells#1#2% col start
+ {\let\columnmaxfreecells\!!zerocount
+ \let\columnfrmfreecells\!!zerocount
+ \pushmacro \columnmaxcells
+\OTRSETsetcorrectnofcells\currentcolumnmaxcells % sets \scratchcounter
+\edef\columnmaxcells{\the\scratchcounter}%
+ \scratchcounter\zerocount
+ \dostepwiserecurse{#2}\columnmaxcells\plusone
+ {\OTRSETdoifcellelse{#1}\recurselevel
+ {\ifnum\columnmaxfreecells<\scratchcounter
+ \edef\columnmaxfreecells{\the\scratchcounter}%
+ \let\columnfrmfreecells\recurselevel
+ \fi
+ \scratchcounter\zerocount}
+ {\advance\scratchcounter\plusone}}%
+ \popmacro\columnmaxcells}
+
+\long\def\OTRSETrecurseRL#1%
+ {\dostepwiserecurse\nofcolumns\plusone\minusone
+ {#1\hskip\OTRSETgetparameter\c!distance\recurselevel}}
+
+\def\OTRSETmakegridbox
+ {\ifcase\columndirection
+ \OTRSETdomakegridbox\plusone\nofcolumns\plusone
+ \else
+ \OTRSETdomakegridbox\nofcolumns\plusone\minusone
+ \fi}
+
+\def\OTRSETmakeupwidth{\makeupwidth} % temporary indirectness
+
+\def\OTRSETdomakegridbox#1#2#3%
+ {\hbox\bgroup
+ \dontcomplain
+ \forgetall % can go once in \flush
+ \!!heighta \textheight
+ % test first !
+ \hbox to \OTRSETmakeupwidth
+ {\dostepwiserecurse{#1}{#2}{#3}
+ {\mofcolumns\recurselevel
+ \localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \setbox\scratchbox\hbox\localframed
+ [\??mc\OTRSETidentifier\number\mofcolumns]%
+ [\c!width=\localcolumnwidth,\c!height=\!!heighta,\c!lines=]%
+ {}%
+ \wd\scratchbox\localcolumnwidth
+ \ht\scratchbox\!!heighta
+ \ifcase\columndirection
+ \hskip\OTRSETgetparameter\c!distance\recurselevel
+ \box\scratchbox
+ \else
+ \box\scratchbox
+ \hskip\OTRSETgetparameter\c!distance\recurselevel
+ \fi}}%
+ \hskip-\OTRSETmakeupwidth
+ % main text
+ \hbox to \OTRSETmakeupwidth
+ {\dostepwiserecurse{#1}{#2}{#3}
+ {\mofcolumns\recurselevel
+ \localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \offinterlineskip
+ \setbox\scratchbox\vbox to \!!heighta
+ {%\topskipcorrection % not needed
+ \ifcase\OTRSETbalancemethod
+ % no
+ \or
+ % yes
+ \doifelselayerdata{OTRTEXT}\vfill\relax % temp hack
+ \or
+ % top
+ \or
+ % bottom
+ \vfill
+ \fi
+ \dorecurse\columnmaxcells
+ {\setbox\scratchbox\hbox{\OTRSETgetgridcell\mofcolumns\recurselevel}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \ifcase\columndirection
+ \box\scratchbox
+ \else
+ \hbox to \localcolumnwidth
+ {\hskip\localcolumnwidth\llap{\box\scratchbox}}%
+ \fi
+ \par}%
+ \ifcase\OTRSETbalancemethod
+ % no
+ \else
+ % yes, top, bottom
+ \ifdim\globalbodyfontsize=\localbodyfontsize
+ \removedepth
+ \restoreglobalbodyfont
+ \vskip\strutdepth
+ \fi
+ \kern\zeropoint
+ \vss
+ \fi}%
+ \wd\scratchbox\localcolumnwidth % \textwidth
+ \ifcase\columndirection
+ \hskip\OTRSETgetparameter\c!distance\recurselevel\box\scratchbox
+ \else
+ \box\scratchbox\hskip\OTRSETgetparameter\c!distance\recurselevel
+ \fi}}%
+ \egroup}
+
+\let\OTRSETbalht\zeropoint
+
+\def\OTRSETreducegridbox % for the moment no difference between methods
+ {\globallet\OTRSETbalht\zeropoint
+ \ifcase\OTRSETbalancemethod
+ % no balancing
+ \else
+ \bgroup
+ \!!counta\columnmaxcells
+ \donetrue
+ \doloop
+ {\dorecurse\nofcolumns{\OTRSETdoifcellelse\recurselevel\!!counta\donefalse\donothing}%
+ \ifdone
+ \ifnum\!!counta>\plusone\advance\!!counta\minusone\else\exitloop\fi
+ \else
+ \exitloop
+ \fi}%
+ \ifnum\!!counta>\plusone
+ \!!heighta\lineheight
+ \multiply\!!heighta \!!counta
+ \advance\!!heighta \topskip
+ \advance\!!heighta -\lineheight
+ \else
+ \!!heighta\zeropoint
+ \fi
+ \xdef\OTRSETbalht{\the\!!heighta}%
+ \egroup
+ \fi}
+
+\def\OTRSETflushfinalfootnotes
+ {\ifcase\lastcolumnlastcell \else
+ \setbox\scratchbox\hbox
+ {\placebottomnotes}%
+ \ifdim\ht\scratchbox>\zeropoint
+ \setbox\scratchbox\hbox
+ {\hbox to \zeropoint{\OTRSETgetgridcell\nofcolumns\lastcolumnlastcell}%
+ \box\scratchbox}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \OTRSETsetgridcell\nofcolumns\lastcolumnlastcell\box\scratchbox
+ \fi
+ \global\lastcolumnlastcell\zerocount
+ \fi}
+
+\def\OTRSETdoflush
+ {\ifcollectingcontent
+ \registerOTRSETmarks
+ \global\mofcolumns\plusone
+ \else
+ \OTRSETdofinalflush
+ \OTRSETdofinaloutput
+ \ifnum\columnsetpage>0
+ \dorecurse\nofcolumns{\doresetcolumnsetlines\recurselevel}%
+ \fi
+ \doglobal\increment\columnsetpage
+ \OTRSETinitializecolumns
+ %\OTRSETdoflushfloats
+ \OTRSETstartnextpage
+\presetOTRSETmarks
+ \initializecolumntextareas
+ \fi}
+
+\newbox\OTRfinalpagebox
+
+\def\OTRSETdofinalflush % see \OTRSETdoflush
+ {\OTRSETflushfinalfootnotes
+ \placecolumntextareas
+ \OTRSETcentergridcells
+ \bgroup % we want to keep the reduction local
+ \OTRSETreducegridbox
+ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
+ \egroup % otherwise we get the wrong number of free cells
+ %\gdef\localcolumnmaxcells{0}% here ?
+ \global\mofcolumns\nofcolumns} % otherwise problems in finaloutput
+
+\def\OTRSETdofinaloutput
+ {\ifdim\ht\OTRfinalpagebox=\textheight
+ \bgroup % \let\OTRSETsetvsize\relax % prevents useless search for gap
+ \ifcase\OTRSETbalancemethod
+ \finaloutput\box\OTRfinalpagebox
+ \else\ifdim\OTRSETbalht>\zeropoint
+ % catch a bordercase
+ \scratchdimen\OTRSETbalht
+ \advance\scratchdimen\lineheight\relax
+ \ifdim\scratchdimen>\textheight
+ % full page
+ \finaloutput\box\OTRfinalpagebox
+ \else
+ % same page
+ \global\setbox\OTRfinalpagebox \iftracecolumnset\ruledvbox\else\vbox\fi to \OTRSETbalht
+ {\box\OTRfinalpagebox\vss}%
+ \setlayer[OTRTEXT]{\box\OTRfinalpagebox}%
+ \snaptogrid\vbox{\vskip\OTRSETbalht}% hack
+ \fi
+ \else
+ \finaloutput\box\OTRfinalpagebox
+ \fi \fi
+ \globallet\OTRSETbalht\zeropoint
+ \egroup
+ \fi}
+
+\definesystemvariable {mc}
+\definesystemvariable {mt}
+\definesystemconstant {colset}
+
+\definetwopasslist\s!colset
+
+\newdimen \OTRSETtextswidth
+\newdimen \OTRSETtextsheight
+\let \OTRSETidentifier=\empty
+
+\newtoks \OTRSEToutput
+
+\def\OTRSETgetparameter#1#2{\csname\??mc\OTRSETidentifier\number#2#1\endcsname}
+\def\OTRSETsetparameter#1#2{\setvalue{\??mc\OTRSETidentifier\number#2#1}}
+
+\def\OTRSETskipstart
+ {\scratchcounter\executeifdefined{\??mc\OTRSETidentifier\c!start}\zerocount
+ \relax % needed !
+ \ifcase\scratchcounter\else
+ \advance\scratchcounter\plusone
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\plusone\nofcolumns\scratchcounter
+ \null
+ \fi}
+
+\def\OTRSETsetvsize % snap per sectie (gap here?)
+ {\ifcollectingcontent \else % can be assigndimen
+\OTRSETskipstart % not that well tested
+ \OTRSETcheckinsert % added
+ \OTRSETsetfreecells\mofcolumns\columnfirstcell
+ \ifsomefreecolumncells
+ \global\vsize\columnfreecells\lineheight
+ \ifinotr % else problems with floats, see extreme
+ \global\pagegoal\vsize % niet nodig, tenzij binnen otr
+ \fi
+ \synchronizeoutput % fails on example
+ % \allowbreak % hm
+ \fi
+ \synchronizenotes
+ \fi}
+
+\def\OTRSETsethsize % of course this does not migrate outside the otr
+ {\localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \textwidth\localcolumnwidth
+ \hsize\localcolumnwidth}
+
+\def\OTRSETsynchronizehsize
+ {\ifcase0\getvalue{\??mc\??mc\c!width}\else % some width set
+ \bgroup
+ \scratchdimen\OTRSETlocalwidth\mofcolumns
+ \ifdim\scratchdimen=\textwidth
+ \egroup
+ \else
+ % only if change in width and \column/\break
+ \egroup \OTRSETsethsize
+ \fi
+ \fi}
+
+\def\OTRSETcheckfreelines
+ {\OTRSETsetvsize}
+
+\def\doOTRSETcolumnseparator
+ {\hbox to \zeropoint{\hss\red\vl\hss}}
+
+\let\OTRSETcolumnseparator\relax
+
+\def\showbreaks
+ {\let\OTRSETcolumnseparator\doOTRSETcolumnseparator}
+
+% \installcolumnbreakhandler {SET} \v!ja
+% {% hmmm:
+% \ifhmode
+% \bgroup
+% \removeunwantedspaces
+% \parfillskip\zeropoint
+% \OTRSETcolumnseparator
+% \par
+% \egroup
+% \fi
+% % brrr:
+% \ejectinsert
+% \ejectpage
+% \OTRSETsynchronizehsize} % no \OTRSETsethsize, can be mid smaller (like tabulate)
+%
+% \installcolumnbreakhandler {SET} \v!forceer
+% {\OTRSETgotocolumn[\v!forceer]}
+% \installcolumnbreakhandler {SET} \v!eerste
+% {\OTRSETgotocolumn[\v!eerste]}
+% \installcolumnbreakhandler {SET} \v!laatste
+% {\OTRSETgotocolumn[\v!laatste]}
+%
+% \installcolumnbreakhandler {SET} \v!pagina
+% {\simplepagebreak % \flushnotes \executepagebreakhandler\v!ja
+% \ifnum\mofcolumns>\plusone
+% \OTRSETgotocolumn[\v!laatste,\v!forceer]%
+% \fi}
+
+\def\OTRSETcolumnhbreak
+ {\ifhmode
+ \bgroup
+ \removeunwantedspaces
+ \parfillskip\zeropoint
+ \OTRSETcolumnseparator
+ \par
+ \egroup
+ \fi}
+
+\installcolumnbreakhandler {SET} \v!local
+ {\OTRSETcolumnhbreak
+ \ejectinsert
+ \ejectpage % brrr
+ % no \OTRSETsethsize, can be mid smaller (like tabulate)
+ % also, this one should be executed at the outer level
+ % (setting hsize inside otr does not work)
+ \OTRSETsynchronizehsize}
+
+% We need to make sure that we really leave the column; mid
+% column we may end up in an empty gap, and we don't want to
+% stay there (basically such a gap is a small empty page
+% then).
+
+\installcolumnbreakhandler {SET} \v!yes
+ {\OTRSETcolumnhbreak
+ \edef\savedmofcolumns{\the\mofcolumns}%
+ \edef\savedrealpageno{\the\realpageno}%
+ \ejectinsert
+ \ejectpage % brrr
+ \doloop
+ {\ifnum\savedmofcolumns=\mofcolumns
+ \ifnum\savedrealpageno=\realpageno
+ \OTRSETdummycolumn
+ \else
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \OTRSETsynchronizehsize}
+
+\installcolumnbreakhandler {SET} \s!unknown
+ {\expanded{\OTRSETgotocolumn[\@@columnspecification]}}
+
+\installcolumnbreakhandler {SET} \v!page
+ {\vfill\eject % \doejectpage\eject
+ \OTRSETgotonextpage}
+
+\newtoks\OTRSETeverystartofcolumn
+
+\newbox\OTRSETsavedfootnotes
+
+% \installoutput\OTRSETflushtextsofar % spacing goes wrong
+
+%\def\OTRSETflushtextsofar
+% {\ifvoid\normalpagebox \else
+% \setbox\scratchbox\vbox{\unvbox\normalpagebox}%
+% \OTRSETsavenotes
+% \OTRSEThandleflushedtext0
+% \fi}
+
+% The complication is in the fact that when the HERE float
+% is placed, the otr is not invoked when there is not yet
+% enough content; this can lead to a change in order (turning
+% on the tracer with option 0 is very instructive, watch the
+% small numbers in the margin)
+%
+% 0 = no flushing, so no interference but user should handle
+% border cases of placement
+% 1 = the normal otr, rather untested
+% 2 = a solution that works ok, is experimental and above
+% all messy
+
+\chardef\OTRSETflushtextmode=0
+
+\def\OTRSETflushtextsofar
+ {\ifcase\OTRSETflushtextmode
+ % don't mess around
+ \or
+ % the normal one
+ \ifvoid\normalpagebox\else
+ \OTRSETnaturalflush
+ \OTRSETcheckfreelines
+ \fi
+ \or
+ % way to complicated, but kind of ok
+ \doOTRSETflushtextsofar
+ \fi}
+
+\newskip\lastskipinotr
+
+\installoutput\doOTRSETflushtextsofar % experimental
+ {\ifvoid\normalpagebox\else
+ \scratchdimen\dp\normalpagebox
+ \setbox\scratchbox\vbox
+ {\forgetall
+ \unvbox\normalpagebox
+ \global\lastskipinotr\lastskip\relax
+ \ifdim\lastskipinotr>\zeropoint\relax
+ \removelastskip
+ \else
+ \kern-\scratchdimen % handle depth
+ \fi}%
+ \ifdim\lastskipinotr>\zeropoint
+ \scratchskip\ht\scratchbox
+ \setbox\scratchbox\hbox
+ {\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\scratchdimen
+ \ht\scratchbox\scratchskip
+ \fi
+ \OTRSETsavenotes
+ \OTRSEThandleflushedtext\zerocount
+ \ifdim\lastskipinotr>\zeropoint
+ %\vskip \lastskipinotr % hm, gets lost anyway
+ \else
+ % we should not discard skips after here; tricky
+ \fi
+ \OTRSETsetvsize
+ \fi}
+
+\def\OTRSETplacebottomnotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \ifintermediatefootnotes \placebottomnotes \fi
+ \fi
+ \else
+ \placebottomnotes
+ \fi}
+
+\def\OTRSETflushsavednotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \flushsavednotes
+ \fi
+ \else
+ \flushsavednotes
+ \fi}
+
+\def\OTRSETsavenotes
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns \else
+ \savenotes
+ \fi
+ \fi}
+
+\appendtoks \OTRSETflushsavednotes \to \OTRSETeverystartofcolumn
+
+\def\OTRSETnaturalflush
+ {\bgroup
+ \forgetall % new, needed !
+ \setbox0\vbox to \columnfreecells\lineheight
+ {\vskip-\topskip
+ \vskip\lineheight
+ \prevdepth\strutdp
+ \unvbox\normalpagebox
+ \vfill}%
+ \setbox2\hbox
+ {\OTRSETplacebottomnotes}%
+ \setbox\scratchbox\hbox
+ {\wd0\zeropoint\box0\box2}%
+ \dp\scratchbox\strutdp
+ \OTRSEThandleflushedtext\plusone
+ \egroup}
+
+\newcount\lastcolumnlastcell
+
+\def\OTRSEThandleflushedtext#1%
+ {\getnoflines{\ht\scratchbox}%
+ %\wd\scratchbox\textwidth % geen \hsize kan < zijn in bv split tabulate
+ \wd\scratchbox\OTRSETlocalwidth\mofcolumns
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxf}
+ \mofcolumns\columnfirstcell\plusone\noflines
+ {\registeredtextarea1\columnfirstcell\scratchbox}% == \hbox / tricky htcorr == \columnfirstcell
+ \global\columnlastcell\columnfirstcell
+ \global\advance\columnlastcell \noflines
+ \global\lastcolumnlastcell\columnlastcell
+ \global\advance\lastcolumnlastcell \minusone
+ % find next (acceptable) gap, todo: deadcycle
+ \ifcase#1\else
+ \OTRSETfillgapsbetweencells\mofcolumns\columnlastcell
+ \fi
+ \OTRSETfindnextgap
+ % \message{\the\mofcolumns,\the\columnfirstcell,\the\columnfreecells}%
+ % \wait
+ % we cannot adapt the hsize since it may have changed (like
+ % inside a tabulate) so we only change it when there is a
+ % reason to do so
+ \OTRSETsynchronizehsize
+ \OTRSETsetvsize}
+
+\def\OTRSETfindnextgap
+ {\OTRSETsetfreecells\mofcolumns\columnlastcell
+ \ifsomefreecolumncells
+ % okay
+ \bubbleOTRSETmarks % not robust because we reenter
+ \else
+ \registerOTRSETmarks % not robust because we reenter
+ \global\advance\mofcolumns \plusone
+ \ifnum\mofcolumns>\nofcolumns
+ \OTRSETdoflush
+ \global\columnlastcell\plusone
+ \global\columnfirstcell\zerocount
+ \OTRSETdoflushfloats
+ \else
+ \the\OTRSETeverystartofcolumn
+ \global\columnlastcell\plusone
+ \global\columnfirstcell\zerocount
+ \fi
+ \fi}
+
+\let\OTRSETcheckfreelines\donothing
+
+\def\OTRSETfillgapsbetweencells#1#2% col
+ {\ifnum\columngaplimit>\zerocount
+ \donefalse
+ \dostepwiserecurse{#2}\columnmaxcells\plusone
+ {\OTRSETdoifcellelse{#1}\recurselevel
+ {\ifdone
+ \!!countb\recurselevel \advance\!!countb -\!!counta\relax
+ \ifnum\!!countb>\plusone
+ \advance\!!countb \minusone
+ \ifnum\!!countb<\columngaplimit\relax
+ \!!countb\recurselevel \advance\!!countb \minusone
+ \dostepwiserecurse\!!counta\!!countb\plusone
+ {\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}%
+ %\message{[gap]}%
+ \fi
+ \fi
+ \fi
+ \donefalse}
+ {\ifdone \else
+ \donetrue
+ \!!counta\recurselevel
+ \fi}}%
+ \fi}
+
+\appendtoks
+ \OTRSETfillgapsbetweencells\mofcolumns\plusone
+\to \OTRSETeverystartofcolumn
+
+\newif\ifspancolumnslots \spancolumnslotstrue
+\newif\ifcheckcolumnspan \checkcolumnspantrue
+
+\def\OTRSETcheckwidthgap#1#2% box size
+ {\ifcheckcolumnspan
+ \bgroup
+ \scratchdimen#2%
+ \advance\scratchdimen-\wd#1\relax
+ \ifdim-10\scaledpoint>\scratchdimen
+ \egroup
+ \else\ifdim10\scaledpoint<\scratchdimen
+ \egroup
+ \else
+ \egroup
+ \wd#1=#2%
+ \fi\fi
+ \fi}
+
+\def\OTRSETcheckcolumnslot#1%
+ {\enoughcolumncellstrue
+ \ifspancolumnslots\else
+ \OTRSETcheckwidthgap#1\hsize
+ \ifdim\wd#1>\hsize
+ \enoughcolumncellsfalse
+ \fi
+ \fi
+ \ifenoughcolumncells
+ \getnoflines\pagetotal
+ \scratchcounter\noflines
+ \getnoflines{\ht#1}%
+ \columnvcells\noflines
+ \columnhcells\plusone
+ \advance\scratchcounter \columnvcells \relax
+ \ifnum\scratchcounter>\columnfreecells
+ \enoughcolumncellsfalse
+ \fi
+ \fi}
+
+\def\OTRSETstoreincolumnslotPAGE#1%
+ {\ifenoughcolumncells
+ % to do
+ \OTRSETsavebox{#1}%
+ \else
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\def\OTRSETstoreincolumnslotTOPS#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETcheckcolumnslot{#1}%
+ \ifenoughcolumncells
+ \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
+ \fi
+ \ifenoughcolumncells
+ \OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells
+ {\hbox{\copy#1}}%
+ \OTRSETsetvsize
+ \else
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\def\OTRSETstoreincolumnslotBOTS#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \edef\savedcolumnlastcell{\the\columnlastcell}%
+ \OTRSETcheckcolumnslot{#1}%
+ \ifenoughcolumncells
+ \advance\columnlastcell -\columnvcells \advance\columnlastcell \plusone
+% \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
+ \OTRSETcheckcolumnspace\mofcolumns\columnlastcell{#1}%
+ \fi
+ \ifenoughcolumncells
+ \OTRSETsetgridcells\mofcolumns\columnlastcell\columnhcells\columnvcells{\copy#1}%
+ \OTRSETfillgapsbetweencells\mofcolumns\savedcolumnlastcell % -)
+ \OTRSETsetvsize
+ \else
+ \columnlastcell\savedcolumnlastcell
+ \OTRSETsavebox{#1}%
+ \fi}
+
+\newdimen\totalcolumnspace
+
+\def\columnspacetopoffset{0}
+\def\columnspacebotoffset{0}
+
+\def\OTRSETcheckcolumnspace#1#2#3% col row box
+ {\columnhcells\plusone
+ \totalcolumnspace\zeropoint
+ \scratchcounter#1%
+ \enoughcolumncellstrue
+ \doloop
+ {\advance\totalcolumnspace \OTRSETlocalwidth\scratchcounter\relax % needed
+\OTRSETcheckwidthgap#3\totalcolumnspace
+ \ifnum\wd#3>\totalcolumnspace\relax
+ \ifnum\scratchcounter=\nofcolumns
+ \enoughcolumncellsfalse
+ \exitloop
+ \else
+ \advance\columnhcells \plusone
+ \advance\scratchcounter \plusone
+ \advance\totalcolumnspace \OTRSETgetparameter\c!distance\scratchcounter
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \ifenoughcolumncells
+ \getnoflines{\ht#3}%
+ \columnvcells\noflines
+ \OTRSETcheckcolumncells{#1}{#2}\columnhcells\columnvcells
+ \fi}
+
+\def\OTRSETcheckcolumncells#1#2#3#4% col row wid hei
+ {\!!countd#1\advance\!!countd#3\advance\!!countd\minusone
+ \!!counte#2\advance\!!counte#4\advance\!!counte\minusone
+ \ifnum\!!counte>\columnmaxcells\relax
+ \enoughcolumncellsfalse
+ \else
+ \enoughcolumncellstrue
+%\let\columnspacetopoffset\zerocount
+%\scratchcounter#2\advance\scratchcounter\minusone
+%\ifnum\scratchcounter>0
+% \dostepwiserecurse{#1}\!!countd\plusone
+% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacetopoffset\plusone
+% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacetopoffset\plusone
+% \fi\fi}%
+% \advance\!!counte \columnspacetopoffset \relax
+% \advance\columnvcells \columnspacetopoffset \relax
+%\fi
+%\let\columnspacebotoffset\zerocount
+%\scratchcounter\!!counte
+%\advance\scratchcounter \columnvcells \relax
+%\ifnum\scratchcounter>\columnmaxcells\else
+% \dostepwiserecurse{#1}\!!countd\plusone
+% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacebotoffset\plusone
+% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \let\columnspacebotoffset\plusone
+% \fi\fi}%
+% \advance\!!counte \columnspacebotoffset \relax
+% \advance\columnvcells \columnspacebotoffset \relax
+%\fi
+ \dostepwiserecurse{#1}\!!countd\plusone % cols
+ {\ifenoughcolumncells
+ \!!countf\recurselevel\relax
+ \dostepwiserecurse{#2}\!!counte\plusone % rows
+ {\ifenoughcolumncells
+ \OTRSETdoifcellelse\!!countf\recurselevel
+ {\enoughcolumncellsfalse}{}%
+ \fi}%
+ \fi}%
+ \fi}
+
+\def\OTRSETsetpreferedcolumnslot#1#2%
+ {\doifsomething{#1}{\edef\preferedcolumn{#1}}%
+ \doifsomething{#2}{\edef\preferedrow {#2}}}
+
+\OTRSETsetpreferedcolumnslot{\nofcolumns}{1} % default ?
+
+\let\pofcolumns\mofcolumns
+\let\qofcolumns\mofcolumns
+
+\newif\ifquitincurrentcolumn
+
+\def\OTRSETstoreincolumnslotLRTB#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\nofcolumns+\currenthcell
+ \plusone\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotLRBT#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\nofcolumns+\currenthcell
+ \columnmaxcells\plusone-\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotRLTB#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \nofcolumns\qofcolumns-\currenthcell
+ \plusone\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotRLBT#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \nofcolumns\qofcolumns-\currenthcell
+ \columnmaxcells\plusone-\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotTBLR#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \plusone\columnmaxcells+\currentvcell
+ \mofcolumns\nofcolumns+\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotTBRL#1%
+ {\OTRSETprepareforcolumnslot1{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \plusone\columnmaxcells+\currentvcell
+ \nofcolumns\qofcolumns-\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotBTLR#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \columnmaxcells\plusone-\currentvcell
+ \mofcolumns\nofcolumns+\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotBTRL#1%
+ {\OTRSETprepareforcolumnslot3{#1}%
+ \OTRSETflushtextsofar
+ \OTRSETcheckprefered
+ \OTRSETstoreincolumnslotindeed
+ \columnmaxcells\plusone-\currentvcell
+ \nofcolumns\qofcolumns-\currenthcell{#1}}
+
+\def\OTRSETstoreincolumnslotFXTB#1% fixed column
+ {\OTRSETcheckprefered
+ \OTRSETdoifcellelse\pofcolumns\plusone
+ {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot1}{#1}% % 1/2 dependent of place, todo
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \pofcolumns \pofcolumns +\currenthcell
+ \preferedrow\columnmaxcells+\currentvcell{#1}}
+
+\def\OTRSETstoreincolumnslotFXBT#1% fixed column
+ {\OTRSETcheckprefered
+ \OTRSETdoifcellelse\pofcolumns\columnmaxcells
+ {\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot3}{#1}% % 3/2 dependent of place, todo
+ \OTRSETflushtextsofar
+ \OTRSETstoreincolumnslotindeed
+ \pofcolumns \pofcolumns +\currenthcell
+ \columnmaxcells\preferedrow-\currentvcell{#1}}
+
+\chardef\OTRSETforcefixedfloats=0
+
+\def\OTRSETstoreincolumnslotHERE#1% fixed column
+ {\ifcase\OTRSETforcefixedfloats
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \else
+ \OTRSETstoreincolumnslotFIXD{#1}%
+ \fi}
+
+% this one looses too wide graphics
+%
+% \def\OTRSETstoreincolumnslotFIXD#1% fixed column
+% {\OTRSETprepareforcolumnslot2{#1}%
+% % no flush text sofar here, beware: no width test
+% \snaptogrid\vbox{\box#1}}
+%
+% still imperfect
+
+\def\OTRSETstoreincolumnslotFIXD#1% fixed column
+ {\OTRSETflushtextsofar
+ \ifdim\wd#1>\textwidth
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \else
+ % crappy test / needed for o-pbu-f / will be replaced
+ \getnoflines{\ht#1}%
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen\lineheight
+ \advance\scratchdimen\pagetotal\relax
+ \ifdim\scratchdimen<\pagegoal
+ %OTRSETprepareforcolumnslot3{#1}%
+ %ruledvskip\columnslotspacing\lineheight
+ \blank[\columnslotspacing*\v!line]%
+ \snaptogrid\hbox to \hsize{\hss\box#1\hss}% strange, why the centering
+ \blank[\columnslotspacing*\v!line]%
+ \else
+ \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
+ \fi
+ \fi}
+
+\def\OTRSETstoreincolumnslotSOMEWHERE#1#2%
+ {\OTRSETprepareforcolumnslot{#1}{#2}%
+ \OTRSETflushtextsofar
+ \getnoflines\pagetotal \advance\noflines\columnfirstcell
+ \OTRSETstoreincolumnslotindeed
+ \mofcolumns\mofcolumns+\currenthcell
+ \noflines\columnmaxcells+\currentvcell{#2}%
+ \OTRSETsetvsize}
+
+\def\OTRSETcheckprefered
+ {\ifnum\preferedcolumn<\mofcolumns
+ \let\pofcolumns\mofcolumns
+ \else
+ \let\pofcolumns\preferedcolumn
+ \fi
+ \ifquitincurrentcolumn
+ \ifnum\mofcolumns=\nofcolumns
+ \def\qofcolumns{\mofcolumns}%
+ \else
+ \scratchcounter\mofcolumns
+ \advance\scratchcounter \plusone
+ \edef\qofcolumns{\the\scratchcounter}%
+ \fi
+ \else
+ \let\qofcolumns\mofcolumns
+ \fi}
+
+\def\OTRSETstoreincolumnslotindeed#1#2#3#4#5#6#7#8#9%
+ {\OTRSETcheckprefered
+ \enoughcolumncellsfalse
+ \donefalse
+ \dostepwiserecurse{#1}{#2}{#31}
+ {\ifdone
+ \exitloop
+ \else
+ #4=\recurselevel
+ \dostepwiserecurse{#5}{#6}{#71}
+ {\ifdone
+ \exitloop
+ \else
+ #8=\recurselevel
+ \OTRSETcheckcolumnspace\currenthcell\currentvcell{#9}%
+ \ifenoughcolumncells \donetrue \fi
+ \fi}%
+ \fi}%
+ \ifdone
+ \enoughcolumncellstrue
+ \else
+ \enoughcolumncellsfalse
+ \fi
+ \ifenoughcolumncells
+% \ifnum\columnspacetopoffset>0\message{[+++]}\fi
+% \ifnum\columnspacebotoffset>0\message{[---]}\fi
+% \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
+% {\vbox
+% {\ifcase\columnspacetopoffset\else\ruledvskip\columnspacetopoffset\lineheight\fi
+% \copy#9
+% \ifcase\columnspacebotoffset\else\ruledvskip\columnspacebotoffset\lineheight\fi}}%
+ \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
+ {\copy#9}%
+ \ifnum\currenthcell=\mofcolumns\relax
+ \ifdim\ht\OTRSETsavedfootnotes>\zeropoint
+ \OTRSETsetfreecells\mofcolumns\columnfirstcell
+ \ifsomefreecolumncells
+ \getnoflines{\ht\OTRSETsavedfootnotes}\relax
+ \ifnum\columnfreecells<\noflines
+ \global\somefreecolumncellsfalse
+ \else
+ %\message{[flt]}% float
+ \fi
+ \fi
+ \ifsomefreecolumncells
+ % ok, enough room for notes
+ %\message{[flt]}% float
+ \else % ?
+ \OTRSETsavebox{#9}%
+ \OTRSETerasegridcells\currenthcell\currentvcell\columnhcells\columnvcells
+ %\message{[clr]}% save box
+ \fi
+ \else
+ %\message{[flt]}% float
+ \fi
+ \else
+ %\message{[flt]}% float
+ \fi
+ \OTRSETsetvsize
+ %\message{[fnt]}% float
+ \else
+ %\message{[rej]}% save box
+ \OTRSETsavebox{#9}%
+ \fi}
+
+\chardef\columnslotspacing \plusone
+
+\def\OTRSETstoreincolumnslot#1% #2 % {method} {box} % alleen last
+ {% no messing around here
+ % \dp#2=\zeropoint
+ % \ifcase\columnslotspacing\else
+ % \setbox#2=\vbox spread \columnslotspacing\lineheight
+ % {\vss\box#2\vss}%
+ % \fi
+ % and don't change this any more
+% \doifdefinedelse{\strippedcsname\OTRSETstoreincolumnslot#1}
+% {\getvalue{\strippedcsname\OTRSETstoreincolumnslot#1}{#2}}
+% {\OTRSETstoreincolumnslotUNKNOWN{#2}}}
+ \executeifdefined{\strippedcsname\OTRSETstoreincolumnslot#1}
+ \OTRSETstoreincolumnslotUNKNOWN} % {#2}}
+
+\def\OTRSETstoreincolumnslotUNKNOWN#1%
+ {\OTRSETprepareforcolumnslot2{#1}\copy#1} % {} ?
+
+\def\OTRSETprepareforcolumnslot#1#2% 1=hoog 2=midden 3=laag
+ {\dp#2\zeropoint
+ \ifcase\columnslotspacing\else
+ \scratchdimen\columnslotspacing\lineheight
+ \ifnum#1=2 \scratchdimen2\scratchdimen \fi
+ \begingroup
+ \advance\scratchdimen\ht#2\relax
+ \ifdim\scratchdimen<\columnmaxcells\lineheight
+ \endgroup \setbox#2\vbox spread \scratchdimen \bgroup
+ \else
+ \endgroup \setbox#2\vbox to \columnmaxcells\lineheight \bgroup
+ \vskip\strutdepth
+ \fi
+ \ifnum#1>1\vss\fi
+ \box#2\relax
+ \ifnum#1<3\vss\fi
+ \egroup
+ \fi}
+
+\def\OTRSETdocheckiffloatfits % eigenlijk moet else float anders
+ {\global\ifnofloatpermitted\roomforfloatfalse\else\roomforfloattrue\fi}
+
+\def\OTRSETunpreparebox#1%
+ {\ifhbox#1% spans and so
+ \global\setbox\floatbox\vbox{\box#1}%
+ \else
+ \setbox\scratchbox\vbox
+ {\unvbox#1\unskip\unskip\unskip
+ \global\setbox\floatbox\lastbox}%
+ \fi}
+
+% for the moment resave is still needed here
+
+\def\OTRSETsavebox#1% clean up the skips
+ {\OTRSETunpreparebox{#1}%
+ \dofloatssave{text}}
+
+\def\OTRSETresavebox#1% clean up the skips
+ {\OTRSETunpreparebox{#1}%
+ \dofloatsresave{text}}
+
+\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
+ {\iftestfloatbox\ruledhbox\fi{\box\floatbox}}
+
+\def\OTRSETdoflushfloats
+ {\bgroup
+ \def\OTRSETsavebox##1{\!!doneafalse}%
+ \doloop
+ {\ifsomefloatwaiting
+ \OTRSETskipstart
+ \dofloatsgetinfo{text}%
+ \ifdim\floatwidth>\zeropoint
+ \!!doneatrue
+ \dofloatsflush{text}{1}%
+ \dp\floatbox\zeropoint
+ \OTRSETstoreincolumnslot{TBLR}\floatbox
+ \if!!donea
+ %\message{[flu]}%
+ \else
+ \OTRSETresavebox\floatbox
+ \exitloop
+ \fi
+ \else
+ %\message{[err]}% happens but why?
+ \fi
+ \else
+ \exitloop
+ \fi}
+ \egroup}
+
+\newif\ifcentergridcells \centergridcellstrue
+
+\newif\ifcentergridcellonly \centergridcellonlyfalse
+\newif\ifautocentergridcellonly \autocentergridcellonlytrue
+
+\def\OTRSETcentergridcells
+ {\ifcentergridcells
+ \dorecurse\nofcolumns
+ {\currenthcell\recurselevel
+ \ifautocentergridcellonly
+ % we prevent centering when the next column is empty
+ % to be checked ! ! ! !
+ \advance\currenthcell \plusone
+ \centergridcellonlytrue
+ \ifnum\currenthcell>\nofcolumns
+ % ok already
+ \else
+ % only span if there is a next column with content
+ \dorecurse\columnmaxcells
+ {\ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ \centergridcellonlyfalse
+ \else\ifdim\dp\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ \centergridcellonlyfalse
+ \fi\fi}%
+ \fi
+ \fi
+ \currenthcell\recurselevel
+ \dorecurse\columnmaxcells
+ {\currentvcell\recurselevel\relax
+ \ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ \ifdim\dp\OTRSETgridcell\currenthcell\currentvcell=\zeropoint
+ \bgroup
+ \setbox\scratchbox\OTRSETgetgridcell\currenthcell\currentvcell
+ \getnoflines{\ht\scratchbox}%
+ \!!counta\currentvcell
+ \advance\!!counta -\noflines
+ \advance\!!counta \plusone
+ % first col always ok
+ \!!countb\currenthcell
+ \!!countc\currenthcell
+ \advance\!!countc \plusone
+ \!!donebtrue
+ \ifcentergridcellonly
+ \!!countc\maxdimen
+ \fi
+ \dostepwiserecurse\!!countc\nofcolumns\plusone
+ {\if!!doneb
+ \let\xrecurselevel\recurselevel
+ \dostepwiserecurse\!!counta\currentvcell\plusone
+ {\ifdim\ht\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
+ \!!donebfalse
+ \else\ifdim\wd\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
+ \!!donebfalse
+ \fi\fi}%
+ \if!!doneb
+ \!!countb\xrecurselevel
+ \fi
+ \fi}%
+ \totalcolumnspace\OTRSETlocalwidth\currenthcell
+ \dostepwiserecurse\!!countc\!!countb\plusone
+ {\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel
+ \advance\totalcolumnspace \OTRSETgetparameter\c!distance\recurselevel}%
+ \ifdim\totalcolumnspace>\wd\scratchbox
+ \setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}%
+ \fi
+ \OTRSETsetgridcell\currenthcell\currentvcell\box\scratchbox
+ \egroup
+ \fi
+ \fi}}%
+ \fi}
+
+\def\OTRSETinitializecolumns% once per page
+ {\columnspreadtrue % todo
+ \ifcolumnspread
+ \global\rofcolumns\getvalue{\??mc\OTRSETidentifier\c!nright}%
+ \global\lofcolumns\getvalue{\??mc\OTRSETidentifier\c!nleft}%
+ \global\tofcolumns\rofcolumns \relax
+ \ifodd\realpageno\relax
+ \global\nofcolumns\rofcolumns
+ \else
+ \global\advance\tofcolumns\lofcolumns
+ \global\nofcolumns\lofcolumns
+ \fi
+ \else
+ \global\nofcolumns\getvalue{\??mc\OTRSETidentifier\c!n}%
+ \global\rofcolumns\nofcolumns
+ \global\lofcolumns\nofcolumns
+ \global\tofcolumns\nofcolumns
+ \fi
+ \OTRSETassignwidths
+ \global\mofcolumns\plusone
+ \columnerasegridboxes}
+
+% vanaf hier:
+
+\unexpanded\def\definecolumnset
+ {\dodoubleargument\dodefinecolumnset}
+
+\def\dodefinecolumnset[#1][#2]%
+ {\getparameters[\??mc#1]
+ [\c!direction=\v!right,
+ \c!balance=\v!no,
+ \c!distance=1.5\bodyfontsize, % controleren
+ \c!n=2,
+ \c!nleft=\getvalue{\??mc#1\c!n},
+ \c!nright=\getvalue{\??mc#1\c!n},
+ \c!width=\v!fit,
+ \c!lines=0,
+ \c!start=0,
+ #2]%
+ \dorecurse{\getvalue{\??mc#1\c!nleft}} % todo
+ {\dododefinecolumnset[#1][\recurselevel]}%
+ \dorecurse{\getvalue{\??mc#1\c!nright}} % todo
+ {\dododefinecolumnset[#1][\recurselevel]}%
+ % redo framed settings
+ \setupcolumnset[#1][1][\c!distance=\!!zeropoint]}
+
+\def\dododefinecolumnset[#1][#2]%
+ {\presetlocalframed
+ [\??mc#1#2]%
+ \setupcolumnset
+ [#1][#2]
+ [\c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!align=,
+ \c!lines=0,% really needed since c!regels is now part of framed
+ \c!width=\getvalue{\??mc#1\c!width},
+ \c!distance=\getvalue{\??mc#1\c!distance}]}
+
+\unexpanded\def\setupcolumnset
+ {\dotripleargument\dosetupcolumnset}
+
+\def\dosetupcolumnset[#1][#2][#3]%
+ {\ifthirdargument
+ \def\docommand##1%
+ {\doifelse{##1}\v!each
+ {\dorecurse{\getvalue{\??mc#1\c!n}}{\docommand\recurselevel}}
+ {\getparameters[\??mc#1##1][#3]}}%
+ \processcommalist[#2]\docommand
+ \else
+ \getparameters[\??mc#1][#2]%
+ \fi}
+
+\definecolumnset[\s!default][\c!n=2] % fallback
+
+\def\OTRSETgotonextpage
+ {\vfill\eject
+ \relax\ifnum\mofcolumns>\plusone
+ \OTRSETgotocolumn[\v!last]%
+ \ifnum\mofcolumns>\plusone
+ \OTRSETgotocolumn[\v!force]%
+ \fi
+ \fi}
+
+\let\OTRSETgotonextpageX\OTRSETgotonextpage % will become obsolete
+
+\def\OTRSETgotocolumn
+ {\dosingleempty\doOTRSETgotocolumn}
+
+\def\doOTRSETgotoCOLROW#1% |*
+ {\bgroup % really needed
+ \splitstring#1\at*\to\column\and\row
+ \bgroup
+ \ifx\column\empty\else\expanded{\doOTRSETgotoCOLUMN{\column}}\fi
+ \egroup
+ \bgroup
+ \ifx\row \empty\else\expanded{\doOTRSETgotoROW {\row }}\fi
+ \egroup
+ \egroup}
+
+\def\doOTRSETgotoCOLUMN#1%
+ {\ifnum\mofcolumns=#1\else
+ \vfill\eject % \doejectpage\eject
+ \doloop
+ {\ifnum\mofcolumns=#1\relax
+ \exitloop \else \OTRSETdummycolumn
+ \fi}%
+ \fi}
+
+\def\doOTRSETgotoROW#1%
+ {\ifnum#1>1
+ \scratchcounter\zerocount
+ \currenthcell\mofcolumns
+ \currentvcell#1\advance\currentvcell \minusone
+ \dorecurse\currentvcell
+ {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
+ {\advance\scratchcounter\plusone}}
+ \getnoflines\pagetotal
+ \advance\scratchcounter-\noflines
+ \ifnum\scratchcounter>\zerocount
+ \dorecurse\scratchcounter{\line{\strut}}%
+ \fi
+ \fi
+ \OTRSETsetvsize}
+
+\def\doOTRSETgotocolumn[#1]% yes|force|first|last||*
+ {\processallactionsinset
+ [#1]
+ [ \v!yes=>\OTRSETdummycolumn,
+ \v!no=>,% not supported
+ \v!force=>\OTRSETdummycolumn,
+ \v!first=>\expanded{\doOTRSETgotoCOLUMN{1}},
+ \v!last=>\expanded{\doOTRSETgotoCOLUMN{\the\nofcolumns}},
+ \s!default=>\OTRSETdummycolumn,
+ \s!unknown=>\expanded{\doOTRSETgotoCOLROW{\commalistelement}}]}
+
+% to be documented and tested, not yet that robust
+
+% \def\OTRSETgotocell#1#2%
+% {\endgraf
+% \gdef\gotocellcounter{0}%
+% \doloop
+% {\ifnum\mofcolumns<#1\relax
+% \doglobal\increment\gotocellcounter\relax
+% \ifnum\gotocellcounter>#1\relax
+% \line{\strut}\crlf
+% \line{\strut}\crlf
+% \column
+% \writestatus{columnset}{quitting goto cell}%
+% \exitloop
+% \else
+% \column
+% \fi
+% \else
+% \exitloop
+% \fi}%
+% \ifnum\mofcolumns=#1\relax
+% \ifnum#2>1
+% \scratchcounter\zerocount
+% \currenthcell\mofcolumns
+% \currentvcell#2\advance\currentvcell \minusone
+% \dorecurse\currentvcell
+% {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
+% {\advance\scratchcounter\plusone}}
+% \getnoflines\pagetotal
+% \advance\scratchcounter-\noflines
+% \ifnum\scratchcounter>\zerocount
+% \dorecurse\scratchcounter{\line{\strut}}%
+% \fi
+% \fi
+% \fi
+% \OTRSETsetvsize}
+
+\def\OTRSETgotocell#1#2% obsolete: now \column[#1*#2]
+ {\endgraf
+ \doOTRSETgotoCOLUMN{#1}%
+ \doOTRSETgotoROW {#2}}
+
+\def\OTRSETdummycolumn
+ {\verticalstrut
+ \vskip-\struttotal
+ \vfill
+ \eject}
+
+\newcounter\columnsetlevel
+\let\currentcolumnset\empty
+\chardef\OTRSETfinish\zerocount
+
+\unexpanded\def\startcolumnset
+ {\dodoubleempty\dostartcolumnset}
+
+\def\dostartcolumnset[#1][#2]%
+ {\increment\columnsetlevel\relax
+ \globallet\localcolumnmaxcells\!!zerocount
+ \global\chardef\OTRSETfinish\zerocount
+ \resetOTRSETmarks
+ \ifnum\columnsetlevel=\plusone
+ \bgroup
+ \saveinterlinespace
+ \globallet\columnsetpage\!!plusone
+ \def\currentcolumnset{#2}%
+ \insidecolumnstrue % will be different flag in addition
+ \activateotr{SET}{ONE}% andere naam, activate or so
+ \doifelsenothing{#1}
+ {\globallet\OTRSETlist\s!default}
+ {\xdef\OTRSETlist{#1}}%
+ \OTRSETstartnextpage
+ \OTRSETassignwidths
+ \OTRSETsethsize
+ \else
+ \bgroup
+ \fi}
+
+% \setuplayout[grid=yes] \definecolumnset[example] \showgrid
+
+% \starttext
+% \startcolumnset[example]
+% \input knuth \endgraf \input knuth
+% \placetable{table}{\framed[width=\makeupwidth,height=4cm]{Hello}}
+% \input knuth \endgraf \input knuth
+% \stopcolumnset
+% \input knuth \endgraf \input knuth
+% \stoptext
+
+\def\OTRSETflushleftovers % new per 13/4/2006
+ {\OTRSETdoifcellelse{1}{1}
+ {\bgroup
+ \OTRSETcentergridcells
+ \chardef\OTRSETbalancemethod\plusone
+ \OTRSETreducegridbox
+ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
+ \global\ht\OTRfinalpagebox\textheight % signals output that there is content
+ \OTRSETdofinaloutput
+ \globallet\OTRSETbalht\zeropoint
+ \egroup}
+ {}}
+
+\unexpanded\def\stopcolumnset
+ {\relax
+ \ifnum\columnsetlevel=\plusone
+ \endgraf % needed, else wrong vsize in one par case
+ \global\chardef\OTRSETfinish\plusone
+ % no, extra page \pagebreak % (test on pascal toc)
+ \dostopcolumnset
+ \egroup
+ \global\notelimittrue % brrr, untested and fuzzy
+ \setvsize
+ \sethsize
+ \ifvoid\OTRfinalpagebox\else
+ % probably balanced
+ \ifdim\ht\OTRfinalpagebox<\textheight
+ \snaptogrid[\v!page]\hbox{\box\OTRfinalpagebox}%
+ \else
+ \box\OTRfinalpagebox
+ \fi
+ \fi
+ \global\chardef\OTRSETfinish\zerocount
+ \ifsomefloatwaiting \setvsize \pagebreak \setvsize \fi
+ \OTRSETflushleftovers
+ \else
+ \egroup
+ \fi
+ \decrement\columnsetlevel\relax}
+
+\chardef\OTRSETbalancemethod\zerocount
+
+\def\dostopcolumnset
+ {%\OTRSETdofinalflushfloats % yes/no
+ \ifcase\OTRSETbalancemethod
+ \OTRSETnobalance
+ \else
+ \OTRSETdobalance
+ \fi}
+
+\def\OTRSETdobalance
+ {\OTRSETnobalance}
+
+\def\localcolumnmaxcells{0}
+
+% currently line represents real line, i.e. on the grid, and
+% not something noflines (also, watch out for switching from
+% 2-3 columns on one page with both sets balanced: the
+% second set does not see the first set
+
+% don't loose empty 1page/1column with area (example **)
+%
+% \definecolumntextarea[title][x=1,y=4,nx=2,ny=7,state=start]
+% \setupcolumntextareatext[title][\vtop to 5cm{a\\b\\b\\d}]
+%
+% \starttext
+% \startcolumnset \dorecurse{1}{\input tufte \par} \stopcolumnset
+% \stoptext
+
+% better:
+
+\unexpanded\def\definecolumnsetarea {\definecolumntextarea}
+\unexpanded\def\setupcolumnsetarea {\setupcolumntextarea}
+\unexpanded\def\setupcolumnsetareatext{\setupcolumntextareatext}
+
+% so this will be changed
+
+\def\OTRSETnobalance
+ {\iflastcolumnfootnotes % testen ! optie
+ % inhibit flush of floats !
+ % todo: nothing if no footnotes, else empty page
+ \dostepwiserecurse\mofcolumns\nofcolumns\plusone
+ {\vskip-\struttotal\verticalstrut\vfill\eject}%
+ \else
+ \ifnum\mofcolumns>\plusone
+ \donetrue
+ \else\ifdim\pagetotal>\zeropoint % too dangerous, we loose data
+ \donetrue
+ \else
+ \donefalse
+ \fi\fi
+ \ifdone
+ \ifnum\mofcolumns=\nofcolumns
+ \OTRSETflushfinalfootnotes
+ \else
+ % probably todo
+ \fi
+ \vfill
+ \eject
+\registerOTRSETmarks
+ % brr, may result in empty page after nicely fit text
+ % or if left, then lost of first column only text
+ \ifnum\mofcolumns>\plusone
+ \OTRSETdofinalflush
+ \OTRSETdofinaloutput
+ \fi
+ \fi
+ \fi}
+
+\def\OTRSETstartnextpage
+ {\doifsomething\OTRSETlist
+ {\getfromcommacommand[\OTRSETlist][1]%
+ \global\let\OTRSETidentifier\commalistelement
+ \doifundefined{\??mc\OTRSETidentifier\c!n}
+ {\globallet\OTRSETidentifier\s!default}%
+ \let\newcommalistelement\empty
+ \doglobal\replaceincommalist\OTRSETlist1%
+ \OTRSETrestart}}
+
+\def\OTRSETrestart % weed
+ {\OTRSETinitializefeatures
+ \OTRSETflushpreposttext
+ \OTRSETinitializecolumns
+ \OTRSETcheckinsert
+ \OTRSETcheckgrid
+ \OTRSETsetvsize
+ \OTRSETsethsize % or local ?
+ \OTRSETsetplaceholders
+ \OTRSEThandlepreposttext
+ \initializecolumntextareas % name !
+ \OTRSETcheckstartcells
+ \OTRSETsetvsize}
+
+\def\OTRSETcheckstartcells
+ {\dorecurse\nofcolumns
+ {\bgroup
+ \mofcolumns\recurselevel
+\OTRSETsetcorrectnofcells\currentcolumnstartcell
+\advance\scratchcounter \minusone
+ \dorecurse\scratchcounter
+ {\OTRSETdoifcellelse\mofcolumns\recurselevel
+ \donothing{\OTRSETsetgridcell\mofcolumns\recurselevel\copy\placeholderboxe}}%
+ \egroup}}
+
+\OTRSEToutput
+ {\dontcomplain % new, get rid of overfull message (to be sorted out)
+ \doloop
+ {\OTRSETnaturalflush
+ %\OTRSETstartnextpage % no
+ \OTRSETdoflushfloats % actually belongs in \flushsavedfloats (but goes wrong)
+ \OTRSETcheckfreelines
+ \ifsomefreecolumncells
+ \exitloop
+ \else
+ % flush page and get rid of more floats if present
+ \fi}%
+ \OTRSETchecksidefloat}
+
+\def\OTRSETinitializefeatures
+ {% number of lines
+ % new: raw
+ \getrawnoflines\textheight\xdef\columnmaxcells{\the\noflines}%
+ % direction
+ \doifelsevalue{\??mc\OTRSETidentifier\c!direction}\v!right
+ {\chardef\columndirection\zerocount}
+ {\chardef\columndirection\plusone}%
+ % balancing
+ \chardef\OTRSETbalancemethod\zerocount
+ \processaction
+ [\getvalue{\??mc\OTRSETidentifier\c!balance}]
+ [ \v!yes=>\chardef\OTRSETbalancemethod\plusone,
+ \v!top=>\chardef\OTRSETbalancemethod\plustwo,
+ \v!bottom=>\chardef\OTRSETbalancemethod\plusthree]}
+
+% test:
+%
+% \definecolumnset[test-1] %[balance=yes]
+% \definecolumnset[test-2] %[balance=yes]
+%
+% \setupcolumnsetlines[test-1][1][1] [4]
+% \setupcolumnsetlines[test-1][1][2][10]
+%
+% \startcolumnset [test-1] \dorecurse {1}{\input tufte \par} \stopcolumnset
+% \startcolumnset [test-2] \dorecurse {2}{\input ward \par} \stopcolumnset
+
+\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi
+
+\installoutput\OTRSETflushpreposttext
+ {\global\setbox\precolumnbox\vbox
+ {\unvbox\normalpagebox
+ \global\lastskipinotr\lastskip}%
+ \ifdim\lastskipinotr>\zeropoint
+ \global\setbox\precolumnbox\hbox
+ {\lower\strutdepth\box\precolumnbox}%
+ \fi
+ \global\dp\precolumnbox\strutdepth
+ \ifcarryoverfootnotes \else
+ \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
+ \fi}
+
+\let\precolumnlines \!!zerocount
+\let\postcolumnlines\!!zerocount
+
+\def\OTRSEThandlepreposttext
+ {\ifdim\ht\precolumnbox>\zeropoint % new
+ \getnoflines{\ht\precolumnbox}%
+ \edef\precolumnlines{\the\noflines}%
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\plusone\nofcolumns\noflines
+ % normal version (single column set)
+ % {\box\precolumnbox}%
+ % compensated for bodyfont change
+ {\hbox
+ {\OTRSETsetcorrectcellht
+ \raise\scratchdimen\box\precolumnbox}}%
+ \else
+ \let\precolumnlines\!!zerocount
+ \fi
+ \ifdim\ht\postcolumnbox>\zeropoint % new, otherwise empty bottom line
+ \getnoflines{\ht\postcolumnbox}%
+ \edef\postcolumnlines{\the\noflines}%
+ \advance\columnfreecells -\noflines
+ \advance\columnfreecells \plusone
+ \doOTRSETsetgridcells
+ {\copy\placeholderboxe}
+ \plusone\columnfreecells\nofcolumns\noflines
+ {\box\postcolumnbox}%
+ \else
+ \let\postcolumnlines\!!zerocount
+ \fi}
+
+\def\OTRSETchecksidefloat
+ {} % {\sidefloatoutput}
+
+\def\OTRSETfinalsidefloatoutput
+ {}
+
+\def\OTRSETcheckgrid
+ {\topskip1\topskip
+ \ifforcecolumngrid
+ \widowpenalty\zerocount
+ \clubpenalty\zerocount
+ \brokenpenalty\zerocount
+ \fi}
+
+\def\OTRSETcheckinsert
+ {\iflastcolumnfootnotes
+ \ifnum\nofcolumns=\mofcolumns
+ \OTRSETforceinserts
+ \else
+ \OTRSETinhibitinserts
+ \fi
+ \else
+ \OTRSETforceinserts
+ \fi}
+
+\def\OTRSETforceinserts
+ {\enablenotes}
+
+\def\OTRSETinhibitinserts
+ {\disablenotes}
+
+% interface to footnotes
+
+\def\OTRSETassignwidths
+ {%\scratchdimen\makeupwidth
+ \freezetextwidth \scratchdimen\textwidth
+ %
+ \scratchcounter\zerocount
+ \dorecurse\nofcolumns
+ {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit
+ {\advance\scratchcounter \plusone }
+ {\advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}%
+ \advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!distance}}%
+ \ifcase\scratchcounter\else
+ \divide\scratchdimen \scratchcounter
+ \fi
+ \setgvalue{\??mc\??mc\c!width}{0}%
+ \dorecurse\nofcolumns
+ {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit
+ {\dimen0=\scratchdimen}
+ {\setgvalue{\??mc\??mc\c!width}{1}%
+ \dimen0=\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}%
+ \setxvalue{\??mc\recurselevel\??mc\c!width}{\the\dimen0}}}
+
+\def\OTRSETlocalwidth#1%
+ {\getvalue{\??mc\number#1\??mc\c!width}}
+
+\newbox\placeholderboxa
+\newbox\placeholderboxb
+\newbox\placeholderboxc
+\newbox\placeholderboxd
+\newbox\placeholderboxe
+\newbox\placeholderboxf
+
+\def\columnplaceholder#1#2%
+ {\hbox
+ {\setbox\scratchbox\hbox to \hsize
+ {\iftracecolumnset
+ \hskip-.5ex%
+ \startcolor[columnset:#2]\vrule\!!width1ex\!!height.5ex\!!depth.5ex\stopcolor
+ \fi
+ \hss}%
+ \ifcase#1\relax
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\zeropoint
+ \else
+ \wd\scratchbox\hsize
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \fi
+ \box\scratchbox}}
+
+\definepalet
+ [columnset]
+ [a=cyan,b=green,c=blue,d=red,e=magenta,f=darkgray]
+
+\def\OTRSETsetplaceholders
+ {\global\setbox\placeholderboxa\columnplaceholder0a%
+ \global\setbox\placeholderboxb\columnplaceholder0b%
+ \global\setbox\placeholderboxc\columnplaceholder0c%
+ \global\setbox\placeholderboxd\columnplaceholder0d%
+ \global\setbox\placeholderboxe\columnplaceholder0e%
+ \global\setbox\placeholderboxf\columnplaceholder1f}
+
+\def\doOTRSETshowstatus
+ {\llap{\tt\tfxx
+ \startcolor[blue](\the\vsize->\number\columnfirstcell\#\number\columnfreecells)\stopcolor
+ \hskip\leftskip}}
+
+\installtextracer{OTRSET} % low level
+
+\def\enabletextracerOTRSET {\tracecolumnsettrue \let\OTRSETshowstatus\doOTRSETshowstatus}
+\def\disabletextracerOTRSET{\tracecolumnsetfalse\let\OTRSETshowstatus\relax}
+
+\disabletextracerOTRSET
+
+% \appendtoks \OTRSETshowstatus \to \everypar
+
+% page contents
+
+\def\OTRSETdopagecontents#1#2% takes two args: \box \unvbox
+ {\vbox to \textheight{\forgetall#1#2}}
+
+\def\OTRSETsomepagefloat {\def\floatmethod{PAGE}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomeherefloat {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomeelsefloat {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomefixdfloat {\def\floatmethod{FIXD}\OTRSETsomeslotfloat} % check
+\def\OTRSETsometopfloat {\def\floatmethod{TOPS}\OTRSETsomeslotfloat} % check
+\def\OTRSETsomebottomfloat{\def\floatmethod{BOTS}\OTRSETsomeslotfloat} % check
+
+\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
+ {\iftestfloatbox\ruledhbox\fi{\box\floatbox}}
+
+\def\OTRSETsomeslotfloat[#1]%
+ {\setbox\floatbox\vbox{\flushfloatbox}%
+ \dp\floatbox\strutdp
+ \@EA\uppercasestring\floatmethod\to\floatmethod
+ \OTRSETstoreincolumnslot\floatmethod\floatbox
+ \doinsertfloatinfo}
+
+% kind of new, looks much like OTRONE, but not entirely
+
+\def\OTRSETdosettopinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \let\totaltopinserted\!!zeropoint
+ \OTRSETdodosettopinserts
+ \ifnum\@@bknbottom=\zerocount
+ \ifnum\@@bknlines>\zerocount
+ \ifdim\totaltopinserted>\zeropoint\relax
+ \dimen0\lineheight
+ \dimen0=\@@bknlines\dimen0
+ \advance\dimen0 \totaltopinserted\relax
+ \ifdim\dimen0>\textheight % \vsize %%%%%%%%% \textheight
+ \showmessage\m!floatblocks8{\@@bknlines}%
+ \vfilll\eject
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \egroup}
+
+\def\OTRSETdodosettopinserts
+ {\ifnum\noffloatinserts<\noftopfloats
+ \dogetfloat
+ \ifdim\topinserted=\zeropoint\relax
+ \topofinserttrue
+ \else
+ \topofinsertfalse
+ \fi
+ \setbox\scratchbox\vbox % kan beter !
+ {\forgetall
+ \iftopofinsert
+ \ifdim\OTRSETtopoffset=\zeropoint
+ \moveongrid[\v!top]
+ \fi
+ \else
+ \betweenfloatblanko % inserts can't look back
+ \fi
+ \flushfloatbox
+ \blank[\@@bkspaceafter]}%
+ \global\advance\topinserted \ht\scratchbox\relax
+ \ifdim\topinserted>\vsize % was \textheight\relax
+ \OTRSETresavebox\floatbox
+ \noffloatinserts\noftopfloats\relax
+ \global\advance\topinserted -\ht\scratchbox
+ \let\OTRSETdodosettopinserts\relax % to be tested
+ \else
+ \xdef\totaltopinserted{\the\topinserted}%
+ \insert\topins{\forgetall\box\scratchbox}% interlineskip ?
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\noftopfloats\relax
+ \fi
+ \dofloatflushedinfo
+ \fi
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks6{\the\noftopfloats}%
+ \fi
+ \let\OTRSETdodosettopinserts\relax
+ \fi
+ \OTRSETdodosettopinserts}
+
+\def\OTRSETdosetbotinserts
+ {\bgroup
+ \ifsomefloatwaiting
+ \noffloatinserts\zerocount
+ \OTRSETdodosetbotinserts
+ \fi
+ \egroup}
+
+\def\OTRSETdodosetbotinserts
+ {\ifnum\noffloatinserts<\nofbotfloats\relax
+ \dogetfloat
+ \global\advance\botinserted \ht\floatbox\relax
+ \global\advance\botinserted \dp\floatbox\relax
+ \global\advance\botinserted \floattopskip\relax
+ \ifdim\botinserted<\pagegoal\relax
+ \insert\botins
+ {\forgetall
+ \blank[\@@bkspacebefore]%
+ \flushfloatbox}%
+ \ifsomefloatwaiting
+ \advance\noffloatinserts \plusone
+ \else
+ \noffloatinserts\nofbotfloats
+ \fi
+ \dofloatflushedinfo
+ \else
+ \OTRSETresavebox\floatbox
+ \noffloatinserts\nofbotfloats\relax
+ \fi
+ \global\nofloatpermittedtrue % vgl topfloats s!
+ \else
+ \ifsomefloatwaiting
+ \showmessage\m!floatblocks7{\the\nofbotfloats}%
+ \fi
+ \let\OTRSETdodosetbotinserts\relax
+ \fi
+ \OTRSETdodosetbotinserts}
+
+\let\OTRSETdosetbothinserts\relax
+
+\def\OTRSETdotopinsertions
+ {\ifvoid\topins\else
+ \ifvoid\columntopbox\mofcolumns
+ \columnsettopbox\mofcolumns\box\topins
+ \else
+ \columnsettopbox\mofcolumns\vbox % temp, must be better
+ {\forgetall
+ \offinterlineskip
+ \box\columntopbox\mofcolumns
+ \box\topins}
+ \fi
+ \fi
+ \global\topinserted\zeropoint\relax} % goes away
+
+\def\OTRSETdobotinsertions
+ {\ifvoid\botins \else
+ \columnsetbotbox\mofcolumns\box\botins
+% \else
+% \columnsetbotbox\mofcolumns\vbox % temp, must be better
+% {\forgetall
+% \offinterlineskip
+% \box\botins
+% \box\columnbotbox\mofcolumns}
+ \fi
+ \global\botinserted\zeropoint\relax} % goes away
+
+% set ipv text
+
+% left right 1 2 3 +1 +2 +3
+
+\let\columnleftareas \empty
+\let\columnrightareas\empty
+
+% links rechts => odd, even, n, named
+
+\unexpanded\def\definecolumntextarea
+ {\dotripleempty\dodefinecolumntextarea}
+
+\def\dodefinecolumntextarea[#1][#2][#3]% y=0 is mogelijke en handig !
+ {\ifthirdargument
+ \doifinsetelse{#2}{\v!both,\v!fixed}
+ {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]%
+ \definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
+ {\doifelse{#2}\v!next
+ {\doifoddpageelse
+ {\definecolumntextarea[#1][\v!right][\c!type=#2,#3]}
+ {\definecolumntextarea[#1][\v!left ][\c!type=#2,#3]}}
+ {\presetlocalframed
+ [\??mt#1#2]%
+ \processaction[#2] % \doglobal voorkomt stack build up
+ [ \v!left=>\doglobal\addtocommalist{#1}\columnleftareas,
+ \v!right=>\doglobal\addtocommalist{#1}\columnrightareas]%
+ \getparameters[\??mt#1#2]
+ [\c!x=1,\c!y=1,\c!nx=1,\c!ny=1,\c!clipoffset=2\lineheight,
+ \c!leftoffset=\zeropoint,\c!rightoffset=\zeropoint,
+ \c!offset=\v!overlay,\c!strut=\v!no,\c!frame=\v!off,
+ \c!type=#2,\c!page=1,\c!state=\v!stop,#3]}}%
+ \else
+ \definecolumntextarea[#1][\v!next][#2]%
+ \fi}
+
+\unexpanded\def\setupcolumntextarea
+ {\dotripleempty\dosetupcolumntextarea}
+
+\def\dosetupcolumntextarea[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#2}\v!both
+ {\setupcolumntextarea[#1][\v!left ][#3]%
+ \setupcolumntextarea[#1][\v!right][#3]}
+ {\doifelse{#2}\v!next
+ {\doifoddpageelse
+ {\setupcolumntextarea[#1][\v!right][#3]}
+ {\setupcolumntextarea[#1][\v!left][#3]}}
+ {\getparameters[\??mt#1#2][#3]}}%
+ \else
+ \setupcolumntextarea[#1][\v!next][#2]%
+ \fi}
+
+\def\docheckcolumnsetareapage#1#2%
+ {\ifnum\getvalue{\??mt#1\c!page}>\plusone
+ \doifelsevalue{\??mt#1\c!type}\v!fixed
+ {\ifnum\columnsetpage=\getvalue{\??mt#1\c!page}\relax
+ \donetrue\else\donefalse
+ \fi}
+ {\ifnum\columnsetpage<\getvalue{\??mt#1\c!page}\relax
+ \donefalse\else\donetrue
+ \fi}%
+ \else
+ \donetrue
+ \fi}
+
+\def\initializecolumntextareas
+ {\ifodd\realpageno
+ \doinitializecolumntextareas\columnrightareas\v!right
+ \else
+ \doinitializecolumntextareas\columnleftareas\v!left
+ \fi}
+
+\def\doinitializecolumntextareas#1#2%
+ {\def\docommand##1%
+ {\docheckcolumnsetareapage{##1#2}\plusone
+ \ifdone
+ \donefalse
+ \processaction
+ [\getvalue{\??mt##1#2\c!state}]
+ [ \v!start=>\donetrue,
+ \v!repeat=>\donetrue,
+ \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
+ \ifdone\dodoinitializecolumntextareas{##1}{#2}\fi
+ \fi}%
+ \processcommacommand[#1]\docommand}
+
+\def\dodoinitializecolumntextareas#1#2%
+ {\doOTRSETsetgridcells
+ {\copy\placeholderboxd}
+ {\getvalue{\??mt#1#2\c!x }}{\getvalue{\??mt#1#2\c!y }}
+ {\getvalue{\??mt#1#2\c!nx}}{\getvalue{\??mt#1#2\c!ny}}
+ {\copy\placeholderboxd}}
+
+\unexpanded\def\placecolumntextareas
+ {\ifodd\realpageno
+ \doplacecolumntextareas\columnrightareas\v!right
+ \else
+ \doplacecolumntextareas\columnleftareas\v!left
+ \fi}
+
+\def\doplacecolumntextareas#1#2% global ?
+ {\bgroup
+ \forgetall
+ \def\docommand##1%
+ {\docheckcolumnsetareapage{##1#2}\zerocount
+ \ifdone
+ \donefalse
+ \processaction
+ [\getvalue{\??mt##1#2\c!state}]
+ [ \v!start=>\donetrue\doglobal\removefromcommalist{##1}#1,
+ \v!repeat=>\donetrue,
+ \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
+ \ifdone
+ \dodoplacecolumntextareas{##1}{#2}%
+ \else
+ \doglobal\removefromcommalist{##1}#1%
+ \fi
+ \fi}%
+ \processcommacommand[#1]\docommand
+ \egroup}
+
+% \page[left]
+% \definecolumntextarea[intro][left][x=1,y=1,nx=4,ny=20,state=start,background=introlayer]
+% \setupcolumntextareatext[intro][left][\setups{intro}]
+% \flushcolumntextareas
+
+\def\flushcolumntextareas
+ {\initializecolumntextareas
+ \setvsize}
+
+\def\columntextlastbackspace{\backspace}
+
+% beware, we have clipping offsets of 2\lineheight by default
+
+\def\columntextareaparameter#1%
+ {\csname\??mt\currentcolumntestarea#1\endcsname}
+
+\def\dodoplacecolumntextareas#1#2%
+ {\def\currentcolumntestarea{#1#2}%
+ \!!counta\columntextareaparameter\c!x
+ \!!countb\columntextareaparameter\c!nx
+ \docalculatecolumnsetspan
+ \!!heighta\columntextareaparameter\c!ny\lineheight
+ % wrong
+ % \ifnum\columntextareaparameter\c!y=\zerocount
+ % \advance\!!heighta -\lineheight
+ % \advance\!!heighta \topskip
+ % \fi
+ % \advance\!!heighta -\lineheight % option
+ \ifnum\columntextareaparameter\c!y=\plusone
+ \advance\!!heighta -\lineheight
+ \advance\!!heighta \topskip
+ \fi
+ %
+ \setbox\scratchbox\vbox
+ {\donetrue\localframed
+ [\??mt\currentcolumntestarea]
+ [\c!location=,% new (*)
+ \c!width=\!!widtha,\c!height=\!!heighta,\c!lines=]
+ {\columntextareaparameter\empty}}%
+ \!!counta\columntextareaparameter\c!x
+ \!!countb\columntextareaparameter\c!y
+ \advance\!!countb \columntextareaparameter\c!ny
+ \advance\!!countb \minusone
+ % new (*)
+ \doif{\columntextareaparameter\c!location}\v!depth
+ {\setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\zeropoint
+ \ht\scratchbox\!!heighta}%
+ %
+ \setbox0\hbox
+ {\ifcase\!!countc
+ \copy\scratchbox % \box
+ \else
+ \clip
+ [ %\c!topoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!leftoffset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!rightoffset=\columntextareaparameter\c!rightoffset,%
+ \c!width=\!!widthb,%
+ \c!height=\!!heighta]%
+ {\copy\scratchbox}%
+ \fi}%
+ \OTRSETsetgridcell\!!counta\!!countb\box0
+ \ifcase\!!countc\else
+ \advance\!!counta \columntextareaparameter\c!nx
+ \advance\!!counta -\!!countc
+ \advance\!!widtha -\!!widthb
+ \setbox0\hbox
+ {\hskip-\namedlayoutparameter\v!odd\c!backspace
+ \clip
+ [ %\c!topoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!bottomoffset=\columntextareaparameter\c!clipoffset,%
+ %\c!rightoffset=\columntextareaparameter\c!clipoffset,%
+ \c!offset=\columntextareaparameter\c!clipoffset,%
+ \c!leftoffset=\columntextareaparameter\c!leftoffset,%
+ \c!width=\!!widtha,%
+ \c!height=\!!heighta,%
+ \c!hoffset=\!!widthb]%
+ {\copy\scratchbox}}%
+ \OTRSETsetgridcell\!!counta\!!countb\box0%
+ \fi}
+
+\unexpanded\def\setupcolumntextareatext
+ {\dotripleempty\dosetupcolumntextareatext}
+
+\long\def\dosetupcolumntextareatext[#1][#2][#3]%
+ {\ifthirdargument
+ \doifelse{#2}\v!both
+ {\setvalue{\??mt#1\v!left }{#3}%
+ \setvalue{\??mt#1\v!right}{#3}}
+ {\doifelse{#2}\v!next
+ {\doifoddpageelse
+ {\setvalue{\??mt#1\v!right}{#3}}%
+ {\setvalue{\??mt#1\v!left }{#3}}}%
+ {\setvalue{\??mt#1#2}{#3}}}%
+ \else
+ \setupcolumntextareatext[#1][\v!next][{#2}]%
+ \fi}
+
+\def\docalculatecolumnsetspan
+ {% \!!counta <= x
+ % \!!countb <= nx
+ % \!!widtha => total width
+ % \!!widthb => left width
+ % \!!countc => left cols
+ \!!widtha\!!countb\textwidth % we assume equal widths
+ \advance\!!countb \!!counta
+ \advance\!!countb \minusone
+ \ifnum\!!countb>\nofcolumns
+ \!!countc\!!countb
+ \advance\!!countc -\nofcolumns
+ \!!countb\nofcolumns
+ \else
+ \!!countc\zerocount
+ \fi
+ \advance\!!counta \plusone
+ \dostepwiserecurse\!!counta\!!countb\plusone
+ {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}%
+ \!!widthb\!!widtha
+ \advance\!!widthb -\!!countc\textwidth
+ \ifodd\realpageno \else % tricky, assumes that we keep there
+ \ifcase\!!countc\else
+ % nog niet ok voor enkel/doublesided
+ \advance\!!widtha \namedlayoutparameter\v!even\c!backspace
+ \advance\!!widtha \namedlayoutparameter\v!odd \c!backspace
+ \advance\!!widthb \namedlayoutparameter\v!even\c!backspace
+ \dorecurse\!!countc
+ {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}%
+ \fi
+ \fi}
+
+\def\columnsetspanhsize{\textwidth}
+
+\def\setcolumnsetspanhsize#1#2% x nx / uses counta/b
+ {\!!counta#1\!!countb#2\docalculatecolumnsetspan
+ \edef\columnsetspanhsize{\the\!!widtha}}
+
+\unexpanded\def\definecolumnsetspan
+ {\dodoubleempty\dodefinecolumnsetspan}
+
+\def\dodefinecolumnsetspan[#1][#2]%
+ {%\ifsecondargument
+ \defineframedtext
+ [cs:#1]
+ [\c!frame=\v!off,
+ \c!before=,
+ \c!after=,
+ \c!offset=\v!overlay,
+ \c!location=\v!left,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ \c!n=2,
+ \c!nlines=0,
+ \c!indenting=,
+ \c!indentnext=\v!yes,
+ \c!default=HERE,
+ \c!alternative=\v!a,
+ #2]%
+ %\else
+ % \definecolumnspan[][#1]%
+ }%\fi}
+
+\definecolumnsetspan[\s!default]
+
+\unexpanded\def\setupcolumnsetspan
+ {\dodoubleempty\dosetupcolumnsetspan}
+
+\def\dosetupcolumnsetspan[#1][#2]%
+ {\ifsecondargument
+ \setupframedtexts[cs:#1][#2]%
+ \else
+ \setupcolumnsetspan[\s!default][#1]%
+ \fi}
+
+\unexpanded\def\startcolumnsetspan
+ {\dotripleempty\dostartcolumnsetspan}
+
+%%%%%%%%%%%%%%%% TODO
+
+\def\dostartcolumnsetspan[#1][#2][#3]% [#3] gobbles space
+ {\endgraf % else rubish output if forgotten
+ \vskip \zeropoint % make sure otr is done, otherwise last line problems
+ \bgroup
+ \forgetall
+ \ifnum\columnsetlevel>\zerocount\else
+ % of course we needed a one-column fall back for tm
+ \columnsetspanhsize\hsize
+ \nofcolumns\plusone
+ \mofcolumns\plusone
+ \fi
+ \setupframedtexts[cs:#1]
+ [\c!width=\columnsetspanhsize,
+ \c!linecorrection=\v!off,
+ \c!depthcorrection=\v!off,
+ #2]%
+ % determine widths
+ \!!countc\framedtextparameter{cs:#1}\c!n
+ % \!!countd\numexpr(\nofcolumns-\mofcolumns+\plusone)%
+ \!!countd\nofcolumns
+ % n <= n of columns
+ \ifnum\!!countc>\!!countd \!!countc\!!countd \fi
+ \advance\!!countd -\mofcolumns
+ \advance\!!countd \plusone
+ % n <= n of available columns (alternative a)
+ \doif{\framedtextparameter{cs:#1}\c!alternative}\v!a
+ {\ifnum\!!countc>\!!countd \!!countc\!!countd \fi}%
+ % here it all starts
+ \setcolumnsetspanhsize\mofcolumns\!!countc % a/b used
+ \hsize\columnsetspanhsize
+ \setbox\scratchbox\vbox\bgroup
+ \dostartframedtext[cs:#1][\v!none]% geen nils placement
+ % spoils spacing : \vskip-\struttotal\par\verticalstrut\par
+ \ifnum\columnsetlevel>\zerocount
+ \framedtextparameter{cs:#1}\c!before
+ \fi
+ \unexpanded\def\stopcolumnsetspan{\dostopcolumnsetspan{#1}}}
+
+\def\dostopcolumnsetspan#1%
+ {\par
+ \verticalstrut
+ \kern-2\struttotal
+ \verticalstrut
+ \ifnum\columnsetlevel>\zerocount
+ \doifsomething{\framedtextparameter{cs:#1}\c!after}
+ {\framedtextparameter{cs:#1}\c!after
+ \kern\zeropoint}% otherwise blanks disappear, better be a switch
+ \else
+ \endgraf
+ \fi
+ \dostopframedtext
+ \egroup
+ \setbox\scratchbox\frozenhbox to \hsize
+ {\dontcomplain
+ \alignedline{\framedtextparameter{cs:#1}\c!location}\v!middle
+ {\lower\strutdepth\box\scratchbox}}%
+ \dp\scratchbox\zeropoint % else wrong snap insidefloat
+%
+% to be tested first (strange in grid mode)
+%
+% \setbox\scratchbox\frozenhbox to \hsize
+% {\dontcomplain
+% \chardef\alignstrutmode\zerocount
+% \alignedline{\framedtextparameter{cs:#1}\c!plaats}\v!midden
+% {\box\scratchbox}}%
+%
+ \ifinsidefloat
+ \box\scratchbox
+ \else\ifnum\columnsetlevel>\zerocount
+ % we only set \columnsetspacing when asked for, else bottom problems
+ % don't change this any more (test naw)
+ \chardef\columnslotspacing\framedtextparameter{cs:#1}\c!nlines\relax
+ % todo: nboven/onder & \chardef\columnslotlocation2
+ %\OTRSETstoreincolumnslotHERE\scratchbox
+ \edef\floatmethod{\framedtextparameter{cs:#1}\c!default}%
+ \@EA\uppercasestring\floatmethod\to\floatmethod
+ % todo : \v!here -> here enzovoorts
+ \OTRSETstoreincolumnslot\floatmethod\scratchbox
+ % watch out: no \dochecknextindentation{tag}
+ \checknextindentation[\framedtextparameter{cs:#1}\c!indentnext]%
+ \else
+ % of course we needed a one-column fall back for tm; brrr, the box has now too
+ % much height (try \ruledvbox); don't change this without testing techniek
+ \scratchdimen\ht\scratchbox
+ \advance\scratchdimen-\strutdp
+ \ht\scratchbox\scratchdimen
+ \framedtextparameter{cs:#1}\c!before
+ \snaptogrid\vbox{\box\scratchbox}%
+ \framedtextparameter{cs:#1}\c!after
+ \fi\fi
+ \egroup
+ \endgraf}
+
+% \startcolumnset[two]
+% \input tufte
+% \startcolumnsetspan[two][width=20cm,location=middle] \input tufte \stopcolumnsetspan
+% \startcolumnsetspan[two][default=btlr] \input tufte \stopcolumnsetspan
+% \input tufte \par
+% \input tufte \par
+% \startcolumnsetspan[two] \emptylines[5] \stopcolumnsetspan
+% \startcolumnsetspan[two] \input tufte \stopcolumnsetspan
+% \stopcolumnset
+
+\protect \endinput
+
+% extreme examples (1)
+%
+% \setupfloats[numbering=nocheck]
+%
+% \definecolumnset [first] [n=2,start=0]
+% \definecolumnset [next] [n=2,start=3]
+%
+% \setuptexttexts[\vbox to \textheight{\topskipcorrection \hsize\makeupwidth left \hfill right\vfill}]
+%
+% \setuphead[chapter][text=empty]
+%
+% \starttext
+%
+% \startcolumnset[first,next]
+% \placefigure[btrl]{}{}
+% \placefigure[tblr]{}{}
+% \chapter{thuan} \dorecurse{25}{\recurselevel: \input thuan \endgraf}
+% \stopcolumnset
+%
+% \startcolumnset[first,next]
+% \chapter{thuan} \dorecurse{25}{\input thuan \endgraf\placefigure{}{}}
+% \stopcolumnset
+
+\unprotect
+
+% only in columnsets
+
+% \def\cornerfigure
+% {\dotripleempty\docornerfigure}
+%
+% \def\docornerfigure[#1][#2][#3]% [layer] [location] [settings]
+% {\bgroup
+% \dowithnextbox
+% {\!!doneafalse
+% \!!donebfalse
+% \processallactionsinset
+% [\v!left,\v!bottom,#2]
+% [ \v!left=>\!!doneatrue ,
+% \v!right=>\!!doneafalse,
+% \v!top=>\!!donebtrue ,
+% \v!bottom=>\!!donebfalse]%
+% \!!widtha\nextboxwd
+% \if!!donea
+% % unchecked
+% \advance\!!widtha-\backspace
+% \else
+% % unchecked
+% \advance\!!widtha-\backspace
+% \fi
+% \!!widtha\textwidth % could be an option
+% \!!heighta\nextboxht
+% % zou een macro moeten zijn \getnoflayoutlines
+% \ifnum\layoutparameter\c!lines=\zerocount
+% \getnoflines\textheight
+% \else
+% \noflines\layoutparameter\c!lines
+% \fi
+% %
+% \advance\noflines \plusone % wordt default, instelbaar
+% \!!heightb\noflines\lineheight\relax
+% \if!!doneb % boven
+% % unchecked
+% \advance\!!heighta-\topspace
+% \advance\!!heighta-\headerheight
+% \advance\!!heighta-\headerdistance
+% \else % onder
+% % checked
+% \advance\!!heighta-\paperheight
+% \advance\!!heighta+\!!heightb
+% \advance\!!heighta+\topspace
+% \advance\!!heighta+\headerheight
+% \advance\!!heighta+\headerdistance
+% \advance\!!heighta-\footerdistance
+% \advance\!!heighta-\footerheight
+% \fi
+% \getnoflines\!!heighta
+% \!!heighta\noflines\lineheight\relax
+% \def\docornerfigure[####1]%
+% {\expanded{\plaatsfiguur[####1,\v!none]{}
+% {\noexpand\phantombox[\c!width=\the\!!widtha,\c!height=\the\!!heighta]}}}%
+% \if!!donea
+% \if!!doneb % links boven / rb
+% \setlayer[#1]
+% [\c!corner={\v!left,\v!top},\c!location=rb,#3]
+% {\flushnextbox}%
+% \docornerfigure[tblr]%
+% \else % links onder / rt
+% \setlayer[#1]
+% [\c!corner={\v!left,\v!bottom},\c!location=rt,#3]
+% {\flushnextbox}%
+% \docornerfigure[btlr]%
+% \fi
+% \else
+% \if!!doneb % rechts boven / lt
+% \setlayer[#1]
+% [\c!corner={\v!right,\v!top},\c!location=lb,#3]
+% {\flushnextbox}%
+% \docornerfigure[tbrl]%
+% \else % rechts onder / lb
+% \setlayer[#1]
+% [\c!corner={\v!right,\v!bottom},\c!location=lt,#3]
+% {\flushnextbox}%
+% \docornerfigure[btrl]%
+% \fi
+% \fi
+% \egroup}
+% \vbox}
diff --git a/tex/context/base/page-sid.mkii b/tex/context/base/page-sid.mkii
new file mode 100644
index 000000000..0848c9d8c
--- /dev/null
+++ b/tex/context/base/page-sid.mkii
@@ -0,0 +1,931 @@
+%D \module
+%D [ file=page-sid,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Side Floats,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Side Floats}
+
+\unprotect
+
+% problem: when too small, side effects; we need to determine the
+% shift earlier so that we can act when shift < size
+%
+% \definefloat[edgefigure]
+% \setupfloat
+% [edgefigure]
+% [rightmargindistance=-\rightmargintotal,
+% leftmargindistance=-\rightmargintotal,
+% default=outer]
+% \starttext
+% \placeedgefigure{}{\framed[width=12cm]{}} \input tufte
+% \placeedgefigure{}{\framed[width=5cm]{}} \input tufte
+% \placeedgefigure{}{\framed[width=4cm]{}} \input tufte
+% \placeedgefigure{}{\framed[width=2cm]{}} \input tufte
+% \stoptext
+
+% todo: dimexpr an dnumexpr
+
+% These macro deal with side floats. We started with Daniel
+% Comenetz macros as published in TUGBoat Volume 14 (1993),
+% No.\ 1: Anchored Figures at Either Margin. I extended and
+% patched the macros to suite our needs which results in a
+% messy module. Therefore, this module badly needs an update
+% because it's now a mixture of old and new macros.
+
+% afhankelijke variabelen
+%
+% \overgap vervangen door \floatsidetopskip
+% \sidegap vervangen door \floatsideskip
+% \undergap vervangen door \floatsidebottomskip
+%
+% \prskp vervangen door \ctxparskip
+
+% toegevoegde macro's/aanroepen
+%
+% \logsidefloat : loginformatie
+% \flushsidefloats : nodig voor koppen
+
+% recente wijzigingen:
+%
+% namen aangepast: \float... enz. i.p.v. \pic
+
+% Pas op: \EveryPar{\EveryPar{}\margetitel{whatever}}
+% \plaatsfiguur[links]{}{} moet goed gaan. In dat geval
+% begint de tekst terecht wat lager.
+
+\newdimen\sidefloatheight % includes the topskip
+\newdimen\sidefloatwidth
+\newdimen\sidefloathsize
+\newdimen\sidefloatshift
+\newdimen\sidefloatextrashift
+\newdimen\sidefloatvsize \def\nofloatvsize{-1pt }
+\newdimen\sidefloatprogress
+\newdimen\sidefloatpagetotal
+
+\newbox\floatbottom
+
+\newcount\sidefloatsidelines
+\newcount\sidefloatlinesdone
+
+% 1 = backspace
+% 2 = leftedge
+% 3 = leftmargin
+% 4 = leftside
+% 5 = rightside
+% 6 = rightmargin
+% 7 = rightedge
+% 8 = cutspace
+
+\chardef\sidefloattype\zerocount
+
+\def\backspacefloat {\global\chardef\sidefloattype1 \putsidefloat}
+\def\leftedgefloat {\global\chardef\sidefloattype2 \putsidefloat}
+\def\leftmarginfloat {\global\chardef\sidefloattype3 \putsidefloat}
+\def\leftfloat {\global\chardef\sidefloattype4 \putsidefloat}
+\def\rightfloat {\global\chardef\sidefloattype5 \putsidefloat}
+\def\rightmarginfloat {\global\chardef\sidefloattype6 \putsidefloat}
+\def\rightedgefloat {\global\chardef\sidefloattype7 \putsidefloat}
+\def\cutspacefloat {\global\chardef\sidefloattype8 \putsidefloat}
+
+\let\marginfloat \cutspacefloat
+
+\newif\ifroomforfloat
+\newif\iffloatshort
+\newif\iffloatflag
+\newif\iffloatrighteqo
+\newif\iffloatlefteqo
+
+\newdimen\sidefloatleftskip
+\newdimen\sidefloatrightskip
+\newdimen\sidefloatmaximum
+
+% \def\checksidefloatshift
+% {\ifdim\sidefloatmaximum>\zeropoint
+% \ifcase\sidefloattype
+% % invalid
+% \or
+% % backspace
+% \or
+% \global\sidefloatshift-\sidefloatmaximum
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftedgedistance \rightedgedistance
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftmargindistance \rightmargindistance
+% \or
+% \global\sidefloatshift-\sidefloatmaximum
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftmargindistance \rightmargindistance
+% \or
+% % left
+% \or
+% % right
+% \or
+% \global\sidefloatshift-\sidefloatmaximum
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftmargindistance \rightmargindistance
+% \or
+% \global\sidefloatshift-\sidefloatmaximum
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftedgedistance \rightedgedistance
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+% \global\advance\sidefloatshift-\rightorleftpageaction \leftmargindistance \rightmargindistance
+% \or
+% % cutspace
+% \fi
+% \fi}
+
+\def\checksidefloatshift
+ {\ifdim\sidefloatmaximum>\zeropoint
+ \ifcase\sidefloattype
+ % invalid
+ \or
+ % backspace
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftedgedistance \rightedgedistance
+ -\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ % left
+ \or
+ % right
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftedgedistance \rightedgedistance
+ -\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ % cutspace
+ \fi
+ \fi}
+
+% \def\setsidefloatskips
+% {\global\sidefloatrightskip\zeropoint
+% \global\sidefloatleftskip \zeropoint
+% \ifcase\sidefloattype
+% \or % backspace
+% \global \sidefloatleftskip \rightorleftpageaction \backspace \cutspace
+% \or % leftedge
+% \global \sidefloatleftskip \rightorleftpageaction \leftmargindistance\rightmargindistance
+% \global\advance\sidefloatleftskip \rightorleftpageaction \leftmarginwidth\rightmarginwidth
+% \global\advance\sidefloatleftskip \rightorleftpageaction \leftedgedistance\rightedgedistance
+% \or % leftmargin
+% \global \sidefloatleftskip \rightorleftpageaction \leftmargindistance\rightmargindistance
+% \or % leftside
+% \or % rightside
+% \or % rightmargin
+% \global \sidefloatrightskip\rightorleftpageaction \rightmargindistance\leftmargindistance
+% \or % rightedge
+% \global \sidefloatrightskip\rightorleftpageaction \rightmargindistance\leftmargindistance
+% \global\advance\sidefloatrightskip\rightorleftpageaction \rightmarginwidth\leftmarginwidth
+% \global\advance\sidefloatrightskip\rightorleftpageaction \rightedgedistance\leftedgedistance
+% \or % cutspace
+% \global \sidefloatrightskip\rightorleftpageaction \cutspace\backspace
+% \fi
+% \ifdim\sidefloatrightskip>\zeropoint
+% \doglobal\advance\sidefloatrightskip\rightskip
+% \fi
+% \ifdim\sidefloatleftskip>\zeropoint
+% \doglobal\advance\sidefloatleftskip\leftskip
+% \fi}
+
+
+% use \outermarginwidth etc here
+
+\def\setsidefloatskips
+ {\global\sidefloatrightskip\zeropoint
+ \global\sidefloatleftskip \zeropoint
+ \ifcase\sidefloattype
+ \or % backspace
+ \global\sidefloatleftskip\dimexpr
+ +\rightorleftpageaction \backspace \cutspace
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftedge
+ \global\sidefloatleftskip\dimexpr
+ +\rightorleftpageaction \leftmargindistance \rightmargindistance
+ +\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ +\rightorleftpageaction \leftedgedistance \rightedgedistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftmargin
+ \global\sidefloatleftskip\dimexpr
+ +\rightorleftpageaction \leftmargindistance \rightmargindistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftside
+ \or % rightside
+ \or % rightmargin
+ \global\sidefloatrightskip\dimexpr
+ +\rightorleftpageaction \rightmargindistance \leftmargindistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % rightedge
+ \global\sidefloatrightskip\dimexpr
+ +\rightorleftpageaction \rightmargindistance \leftmargindistance
+ +\rightorleftpageaction \rightmarginwidth \leftmarginwidth
+ +\rightorleftpageaction \rightedgedistance \leftedgedistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % cutspace
+ \global\sidefloatrightskip\dimexpr
+ +\rightorleftpageaction \cutspace \backspace
+ +\compensatedinnermakeupmargin
+ \relax
+ \fi
+ \ifdim\sidefloatrightskip>\zeropoint \doglobal\advance\sidefloatrightskip\rightskip \fi
+ \ifdim\sidefloatleftskip >\zeropoint \doglobal\advance\sidefloatleftskip \leftskip \fi}
+
+% eq is still crap
+
+\ifx\normalleqno\undefined
+
+ \let\floatrighteqo=\eqno
+ \let\floatleftleqo=\leqno
+
+\else
+
+ \let\floatrighteqo=\normaleqno
+ \let\floatleftleqo=\normalleqno
+
+\fi
+
+% Watch it even more! In inner, gaat't mis omdat daar
+% pagetotal enz niet zijn aangepast. Inner kan overigens niet
+% betrouwbaar worden getest!
+
+% \def\flushsidefloats%
+% {\par
+% \sidefloatprogress=\sidefloatvsize
+% \advance\sidefloatprogress by -\pagetotal
+% \ifdim\sidefloatprogress>\zeropoint
+% \witruimte % nog checken op interferentie
+% \kern\sidefloatprogress
+% \fi
+% \global\sidefloatvsize=\nofloatvsize
+% \global\floatflagfalse}
+%
+% no, too buggy, leads to top of page crap
+%
+%\def\flushsidefloats
+% {\par
+% \dochecksidefloat
+% \scratchcounter=-\hangafter
+% \dorecurse{\scratchcounter}{\strut\hfill\strut\par}}
+%
+%\def\flushsidefloats
+% {\par
+% \!!heighta\sidefloatvsize
+% \advance\!!heighta -\pagetotal
+% \ifdim\!!heighta>\zeropoint
+% % to be checked for interference
+% \witruimte
+% % will be option
+% \getnoflines\!!heighta
+% \!!heighta\noflines\lineheight
+% % so far for option
+% \kern\!!heighta
+% \fi
+% % == \forgetsidefloats
+% \global\sidefloatvsize\nofloatvsize
+% \global\floatshortfalse
+% \global\floatflagfalse}
+
+% \def\flushsidefloats
+% {\par
+% \!!heighta\sidefloatvsize
+% \advance\!!heighta -\pagetotal
+% \ifdim\!!heighta>\zeropoint
+% % to be checked for interference
+% \witruimte
+% % will be option
+% \getnoflines\!!heighta
+% \!!heighta\noflines\lineheight
+% % so far for option
+% \ifdim\sidefloatbottomskip>\zeropoint\relax
+% \ifdim\!!heighta>\sidefloatbottomskip
+% \advance\!!heighta-\sidefloatbottomskip
+% \kern\!!heighta
+% \vskip\sidefloatbottomskip
+% \else
+% \kern\!!heighta
+% \fi
+% \else
+% \kern\!!heighta
+% \fi
+% \fi
+% % == \forgetsidefloats
+% \global\sidefloatvsize\nofloatvsize
+% \global\floatshortfalse
+% \global\floatflagfalse}
+
+\newif\iftracesidefloats
+
+\def\flushsidefloats
+ {\par
+ \!!heighta\sidefloatvsize
+ \advance\!!heighta -\pagetotal
+ \ifnum\!!heighta>\zeropoint
+ \global\advance\sidefloatvsize -\sidefloatbottomskip
+ \ifdim\!!heighta>\zeropoint
+ \bgroup
+ \let\flushsidefloats\relax
+ \forgetall
+ \doloop
+ {\strut
+ \iftracesidefloats
+ \color[darkgray]%
+ {\baselinerulefalse
+ \boxrulewidth.5\points
+ \ruledhbox{\strut\kern\sidefloatwidth}}%
+ \fi
+ \par
+ \!!heighta\sidefloatvsize
+ \advance\!!heighta -\pagetotal
+ \ifdim\!!heighta>\zeropoint
+ \ifnum\recurselevel>\plushundred
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \egroup
+ \ifdim\parskip>\zeropoint
+ \ifdim\sidefloatbottomskip>\parskip
+ \nowhitespace
+ \vskip\sidefloatbottomskip
+ \fi
+ \fi
+ \else\ifdim\sidefloatbottomskip>\parskip
+ \vskip\sidefloatbottomskip
+ \fi\fi
+ \fi
+ % not entirely the same as \forgetsidefloats
+ \global\sidefloatvsize\nofloatvsize
+ % \global\sidefloatsidelines\zerocount % no, we flush before a side float
+ \global\floatshortfalse % so this will get lost
+ % also here if used at all \global\holdinginserts\zerocount
+ \global\floatflagfalse}
+
+\def\flushsidefloatsafterpar
+ {\xdef\oldpagetotal{\the\pagetotal}%
+ \gdef\checksidefloat
+ {\dochecksidefloat
+ \ifdim\oldpagetotal=\pagetotal \else
+ \global\let\checksidefloat\dochecksidefloat
+ \flushsidefloats
+ \global\sidefloatsidelines\zerocount % here !
+ \fi}}
+
+\def\forgetsidefloats
+ {\global\sidefloatvsize\nofloatvsize
+ \global\sidefloatsidelines\zerocount
+ % also here if used at all \global\holdinginserts\zerocount
+ \global\floatshortfalse
+ \global\floatflagfalse}
+
+\let\logsidefloat=\relax
+
+\def\pushpenalties % needed ? and right
+ {\widowpenalty\plusone
+ \clubpenalty\plustwo
+ \brokenpenalty\plusone
+ \let\pushpenalties\relax
+ \edef\poppenalties
+ {\widowpenalty \the\widowpenalty
+ \clubpenalty \the\clubpenalty
+ \brokenpenalty\the\brokenpenalty
+ \let\poppenalties\relax}}
+
+% shouldn;t that be:
+%
+% \def\pushpenalties % needed?
+% {\let\pushpenalties\relax
+% \edef\poppenalties
+% {\widowpenalty \the\widowpenalty
+% \clubpenalty \the\clubpenalty
+% \brokenpenalty\the\brokenpenalty
+% \let\poppenalties\relax}%
+% \widowpenalty\plusone
+% \clubpenalty\plustwo
+% \brokenpenalty\plusone}
+
+\let\poppenalties=\relax
+
+\def\restorepenalties
+ {\ifnum\outputpenalty=\!!tenthousand\else
+ \penalty\outputpenalty
+ \fi}
+
+\def\sidefloatoutput
+ {\iffloatshort
+ \unvbox\normalpagebox
+ \setbox\floatbottom\lastbox
+ \ifdim\wd\floatbottom>\sidefloathsize
+ \penalty-201
+ \box\floatbottom
+ \else
+ \ifvoid\floatbottom
+ \else
+ \restoreleftindent
+ \ifdim\wd\floatbottom<\sidefloathsize
+ \parskip\zeropoint
+ %\noindent
+ \ifinner\else\vadjust{\penalty\minusone}\fi
+ \iffloatlefteqo
+ \global\floatlefteqofalse
+ \else
+ \global\advance\sidefloathsize -\wd\floatbottom
+ \iffloatrighteqo
+ \global\floatrighteqofalse
+ \else
+ \global\divide\sidefloathsize \plustwo
+ \fi
+ \hskip\sidefloathsize
+ \fi
+ \fi
+ \box\floatbottom
+ \restorepenalties
+ \fi
+ \fi
+ % why was this \global\holdinginserts\zerocount
+ \global\floatshortfalse
+ \else
+ \finalsidefloatoutput % new
+ \global\sidefloatvsize\nofloatvsize
+ \global\sidefloatsidelines\zerocount
+ % we can end up in fig lock, so \global\holdinginserts\zerocount here too ?
+ \poppenalties
+ \fi}
+
+\def\finalsidefloatoutput% new
+ {\finaloutput\unvbox\normalpagebox}
+
+\def\restoreleftindent
+ {\relax \ifnum\sidefloattype>4 \else
+ \parskip\zeropoint % here ?
+ \ifdim\sidefloatwidth>\zeropoint % new, see prikkels
+ \noindent
+ \ifinner\else\vadjust{\penalty\minusone}\fi
+ \hskip\sidefloatwidth
+ %\else
+ % we have a margin or edge float
+ \fi
+ \fi}
+
+\ifx\normaleqno\undefined
+
+ \def\normaleqno
+ {\iffloatshort
+ \global\floatrighteqotrue
+ \fi
+ \floatrighteqo}
+
+\else
+
+ \def\eqno
+ {\iffloatshort
+ \global\floatrighteqotrue
+ \fi
+ \floatrighteqo}
+
+\fi
+
+% externfiguur -> grid =ja|hoogte|diepte|halveregel|passend -> helemaal in details
+% stelplaatsblokin -> zijuitlijnen=hoogte|diepte|regel|halveregel|grid -> halveregel in 'details'
+
+% replacement for below
+%
+% \global\setbox\floatbox\hbox % no \hskip, but \kern here
+% {\ifcase\sidefloattype
+% \vbox{#1}%
+% \or % 1
+% \hskip\sidefloatleftshift
+% \hskip\sidefloatshift
+% \vbox{#1}%
+% \kern-\sidefloatextrashift
+% \or % 2
+% \hskip\sidefloatshift
+% \vbox{#1}%
+% \kern-\sidefloatextrashift
+% \or % 3
+% \hskip\sidefloatshift
+% \vbox{#1}%
+% \kern-\sidefloatextrashift
+% \or % 4
+% \hskip\sidefloatleftshift
+% \hskip\sidefloatshift
+% \vbox{#1\removedepth}%
+% \kern-\sidefloatextrashift
+% \or % 5
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \kern\sidefloatrightshift
+% \or % 6
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \or % 7
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \or % 8
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \kern\sidefloatrightshift
+% \fi}%
+%
+% keep this ^
+
+\def\putsidefloat#1% grid (4) is rather experimental
+ {\par
+ \whitespace
+ % moved here dec 2001
+ {\everypar\emptytoks\forgetall\verticalstrut\vskip-\struttotal}% moved
+ \checksidefloatshift
+ \ifdim\sidefloatshift=\zeropoint \relax
+ \ifnum\sidefloattype=4
+ \global\advance\sidefloatshift\sidefloatextrashift
+ \global\sidefloatextrashift\zeropoint
+ \else\ifnum\sidefloattype=5
+ \global\advance\sidefloatshift\sidefloatextrashift
+ \global\sidefloatextrashift\zeropoint
+ \fi\fi
+ \else
+ \ifnum\sidefloattype<4
+ \global\chardef\sidefloattype4
+ \else\ifnum\sidefloattype>5
+ \global\chardef\sidefloattype5
+ \fi\fi
+ \fi
+ \previoussidefloat
+ \stallsidefloat
+ %\global\setbox\floatbox\hbox
+ % {\ifmarginfloat\else\ifrightfloat\else\kern\sidefloatleftshift\fi\fi
+ % \hskip\ifrightfloat-\sidefloatextrashift\else\sidefloatshift\fi
+ % \vbox{#1\ifnum\sidefloatalign=4 \removedepth\fi}%
+ % \kern\ifrightfloat\sidefloatshift\else-\sidefloatextrashift\fi
+ % \ifmarginfloat\else\ifrightfloat\kern\sidefloatrightshift\fi\fi}%
+ \global\setbox\floatbox\hbox % no \hskip, but \kern here
+ {\ifnum\sidefloattype=4
+ \hskip\sidefloatleftshift
+ \else\ifnum\sidefloattype=1
+ \hskip\sidefloatleftshift
+ \fi\fi
+ \ifnum\sidefloattype>4
+ \hskip-\sidefloatextrashift
+ \else
+ \hskip\sidefloatshift
+ \fi
+ \vbox{#1\ifnum\sidefloatalign=4 \removedepth\fi}%
+ \ifnum\sidefloattype>4
+ \kern\sidefloatshift
+ \else
+ \kern-\sidefloatextrashift
+ \fi
+ \ifnum\sidefloattype=8
+ \kern\sidefloatrightshift
+ \else\ifnum\sidefloattype=5
+ \kern\sidefloatrightshift
+ \fi\fi}%
+ \ifnum\sidefloatalign=4
+ \getnoflines{\ht\floatbox}%
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen-\strutdepth
+ \getrawnoflines\sidefloattopskip
+ \advance\scratchdimen\noflines\lineheight
+ % todo: maybe rounding problem here
+ % \global\setbox\floatbox\hbox{\lower\lineheight\box\floatbox}%
+ \global\setbox\floatbox\hbox{\lower\strutdepth\box\floatbox}%
+ \global\ht\floatbox\scratchdimen
+ \global\dp\floatbox\zeropoint
+ \fi
+ \ifcase\sidefloatalign \else
+ \global\sidefloattopskip\zeropoint
+ \fi
+ \scratchdimen
+ \ifnum\sidefloattype<4
+ \sidefloattopskip
+ \else\ifnum\sidefloattype>5
+ \sidefloattopskip
+ \else
+ \zeropoint
+ \fi\fi
+ % the top of the box is at the previous baseline
+ \ifcase\sidefloatalign
+ % 0 normal
+ \advance\scratchdimen\strutdepth % == \sidefloattopoffset
+ \or % 1 height
+ \advance\scratchdimen\strutdepth % == \sidefloattopoffset
+ \or % 2 line
+ \or % 3 depth
+ \advance\scratchdimen\lineheight
+ \advance\scratchdimen\strutdepth
+ \or % 4 grid
+ \scratchdimen\zeropoint
+ \or
+ \advance\scratchdimen\strutheight
+ \fi
+ % new
+ \global\sidefloatlinesdone\zerocount
+ \ifnum\sidefloatsidelines>\zerocount
+ \advance\scratchdimen\sidefloatsidelines\lineheight
+ \fi
+ % new
+ \global\setbox\floatbox\hbox
+ {\vbox
+ {\vskip\scratchdimen
+ \nointerlineskip
+ \box\floatbox
+ \ifnum\sidefloatalign=5 \vskip-\lineheight \fi}}%
+ \ifnum\sidefloattype<4
+ \global\sidefloattopskip\zeropoint
+ \else\ifnum\sidefloattype>5
+ \global\sidefloattopskip\zeropoint
+ \fi\fi
+ \global\sidefloatdownshift\zeropoint
+ \measuresidefloat
+ \ifroomforfloat \else
+ \tosssidefloat
+ \measuresidefloat
+ \stallsidefloat
+ \fi
+ \setsidefloat}
+
+\def\progresssidefloat
+ {\sidefloatprogress\sidefloatvsize
+ \iffloatflag
+ \advance\sidefloatprogress -\sidefloatpagetotal
+ \global\floatflagfalse
+ \else
+ \advance\sidefloatprogress -\pagetotal
+ \fi}
+
+\def\tosssidefloat
+ {\vfill\eject}
+
+\def\measuresidefloat
+ {\global\floatflagtrue
+ \global\sidefloatpagetotal \pagetotal % global
+ \ifnum\sidefloattype<4
+ \global \sidefloatwidth \zeropoint
+ \else\ifnum\sidefloattype>5
+ \global \sidefloatwidth \zeropoint
+ \else
+ \global \sidefloatwidth \wd\floatbox
+ \global\advance\sidefloatwidth \floatsideskip
+ \fi\fi
+ \ifdim\sidefloatwidth<\zeropoint
+ \global\sidefloatwidth\zeropoint
+ \fi
+ \global \sidefloathsize \hsize
+ \global\advance\sidefloathsize -\sidefloatwidth
+ \global \sidefloatheight \ht\floatbox
+ \global\advance\sidefloatheight \dp\floatbox
+ \global\advance\sidefloatheight \sidefloattopskip
+ \global \sidefloatvsize \sidefloatheight
+ \global\advance\sidefloatvsize \sidefloatpagetotal
+ \dimen0\sidefloatvsize
+ \dimen2\pagegoal
+ \relax
+ \ifcase\sidefloatmethod
+ % method 0 : raw
+ \or
+ % method 1 : safe
+ \dimen2 .99\pagegoal
+ \or
+ % method 2 : tight
+ \advance\dimen0 -\onepoint
+ \fi
+ \relax % really needed ! ! ! !
+ \ifdim\dimen0>\dimen2
+ \global\roomforfloatfalse
+ \else
+ \dimen0=\pagegoal
+ \advance\dimen0 -\sidefloatvsize
+ \ifdim\dimen0<\sidefloatbottomskip
+ \global\advance\sidefloatvsize \dimen0
+ \global\floatshorttrue
+ \pushpenalties
+ % why was this \global\holdinginserts\plusone
+ \else
+ \global\advance\sidefloatvsize \sidefloatbottomskip
+ \global\floatshortfalse
+ \fi
+ \global\roomforfloattrue
+ \fi}
+
+\def\setsidefloat% nilling everypar saves time and redudant pos's
+ {% removed here dec 2001
+ % {\everypar\emptytoks\forgetall\verticalstrut\vskip-\struttotal}%
+ \ifnum\sidefloattype=4 \kern\sidefloattopskip \fi
+ \ifnum\sidefloattype=5 \kern\sidefloattopskip \fi
+ \edef\presidefloatdepth{\the\prevdepth}%
+ \nointerlineskip
+ \bgroup
+ \everypar\emptytoks
+ \parskip\zeropoint
+ %\checksidefloatshift
+ \setsidefloatskips
+ \logsidefloat
+ \relax
+ \ifcase\sidefloattype
+ % invalid
+ \or % backspace
+ \noindent\llap{\rlap{\box\floatbox}\hskip\sidefloatleftskip}\hfill
+ \or % leftedge
+ \noindent\llap{\box\floatbox\hskip\sidefloatleftskip}\hfill
+ \or % leftmargin
+ \noindent\llap{\box\floatbox\hskip\sidefloatleftskip}\hfill
+ \or % leftside
+ \noindent\box\floatbox\hfill
+ \or % rightside
+ \hfill\box\floatbox
+ \or % rightmargin
+ \hfill\rlap{\hskip\sidefloatrightskip\box\floatbox}%
+ \or % rightedge
+ \hfill\rlap{\hskip\sidefloatrightskip\box\floatbox}%
+ \or % cutspace
+ \hfill\rlap{\hskip\sidefloatrightskip\llap{\box\floatbox}}%
+ \fi
+ \egroup
+ \par
+ \kern-\sidefloatheight
+ \penalty10001 % oeps, this will change
+ \normalbaselines
+ \prevdepth\presidefloatdepth
+ % \noindent
+ \resetsidefloatparagraph
+ \ignorespaces} % not really needed
+
+\newcount\sidefloatparagraph
+
+\def\iffirstsidefloatparagraph
+ {\ifcase\sidefloatparagraph\or}
+
+% without sidefloat lines
+%
+% \def\setsidefloatparagraph
+% {%\advance\sidefloatprogress \sidefloatbottomskip
+% %\!!counta\sidefloatprogress
+% \scratchdimen\sidefloatprogress
+% \advance\scratchdimen \strutht
+% \advance\scratchdimen -\roundingeps % new, needed in prikkels, prevent rounding errors
+% \!!counta\scratchdimen
+% \divide\!!counta \baselineskip
+% \ifnum\!!counta>0
+% \hangindent \ifnum\sidefloattype>4 -\fi\sidefloatwidth
+% \hangafter-\!!counta
+% \fi
+% \global\advance\sidefloatparagraph \plusone
+% \iftracesidefloats
+% \hskip-\sidefloatwidth
+% \color[darkgray]%
+% {\vrule\!!height.5\points\!!depth.5\points\!!width\sidefloatwidth
+% %\hskip-.25\bodyfontsize\showstruts\strut\hskip.25\bodyfontsize}%
+% \llap{\showstruts\strut\hskip.25\bodyfontsize}}%
+% \fi}
+
+\def\setsidefloatparagraph
+ {%\advance\sidefloatprogress \sidefloatbottomskip
+ %\!!counta\sidefloatprogress
+ \scratchdimen\sidefloatprogress
+ \advance\scratchdimen \strutht
+ \advance\scratchdimen -\roundingeps % new, needed in prikkels, prevent rounding errors
+ \!!counta\scratchdimen
+ \divide\!!counta \baselineskip\relax
+ \ifnum\!!counta>0
+ % new from here
+ \ifcase\sidefloatsidelines\else
+ \ifcase\sidefloatlinesdone
+ \global\sidefloatlinesdone\!!counta
+ \else
+ \scratchcounter\sidefloatlinesdone
+ \advance\scratchcounter-\!!counta
+ \global\advance\sidefloatsidelines-\scratchcounter
+ \fi
+ \fi
+ \ifnum\sidefloatsidelines>\zerocount
+ \scratchtoks\emptytoks
+ \scratchcounter\sidefloatsidelines
+ \scratchdimen\hsize
+ \advance\scratchdimen-\sidefloatwidth
+ \dorecurse\sidefloatsidelines
+ {\appendtoks \zeropoint \hsize \to \scratchtoks}%
+ \ifnum\!!counta>\sidefloatsidelines
+ \advance\!!counta -\sidefloatsidelines\relax
+ \advance\scratchcounter\!!counta
+ \dorecurse\!!counta
+ {\ifnum\sidefloattype>4
+ \appendtoks \zeropoint \scratchdimen \to \scratchtoks
+ \else
+ \appendtoks \sidefloatwidth \scratchdimen \to \scratchtoks
+ \fi}%
+ \fi
+ \advance\scratchcounter \plusone
+ \parshape \scratchcounter \the\scratchtoks \zeropoint \hsize\relax
+ \else
+ % new till here
+ \hangindent \ifnum\sidefloattype>4 -\fi\sidefloatwidth
+ \hangafter-\!!counta
+ \fi
+ \fi
+ \global\advance\sidefloatparagraph \plusone
+ \iftracesidefloats
+ \hskip-\sidefloatwidth
+ \color[darkgray]%
+ {\vrule\!!height.5\points\!!depth.5\points\!!width\sidefloatwidth
+ %\hskip-.25\bodyfontsize\showstruts\strut\hskip.25\bodyfontsize}%
+ \llap{\showstruts\strut\hskip.25\bodyfontsize}}%
+ \fi}
+
+\def\resetsidefloatparagraph
+ {\global\sidefloatparagraph\zerocount }
+
+\def\dochecksidefloat
+ {\progresssidefloat
+ \ifdim\sidefloatprogress>\zeropoint
+ \setsidefloatparagraph
+ \else
+ \resetsidefloatparagraph
+ \fi
+ \parskip\ctxparskip}
+
+\def\checksidefloat
+ {\dochecksidefloat}
+
+\def\synchronizesidefloats
+ {\ifinner \else \checksidefloat \fi}
+
+\def\doadjustsidefloatdisplaylines
+ {\par
+ \vskip-\parskip
+ \noindent
+ \ignorespaces}
+
+\def\adjustsidefloatdisplaylines
+ {\aftergroup\doadjustsidefloatdisplaylines}
+
+\def\previoussidefloat
+ {\progresssidefloat
+ \ifdim\sidefloatprogress>\zeropoint \relax
+ \iffloatshort
+ \global\floatshortfalse
+ \tosssidefloat
+ \else
+ \kern\sidefloatprogress
+ \fi
+ \fi}
+
+\def\stallsidefloat
+ {\!!counta\pageshrink
+ \divide\!!counta \baselineskip
+ \advance\!!counta \plusone
+ \parskip\zeropoint
+ \dorecurse\!!counta{\line{}}
+ \kern-\!!counta\baselineskip
+ \penalty\zerocount }
+
+% We need to hook it into the other otr's. This code will move.
+
+\let\OTRONEflushsidefloats \flushsidefloats
+\let\OTRONEsynchronizesidefloats\synchronizesidefloats
+
+% page-set
+%
+% \let\OTRSETflushsidefloats \forgetsidefloats
+% \let\OTRSETsynchronizesidefloats\forgetsidefloats
+
+% page-mul
+%
+% \let\OTRMULflushsidefloats \forgetsidefloats
+% \let\OTRMULsynchronizesidefloats\forgetsidefloats
+
+\def\synchronizesidefloats{\OTRcommand\synchronizesidefloats}
+\def\flushsidefloats {\OTRcommand\flushsidefloats}
+
+\protect \endinput
diff --git a/tex/context/base/page-sid.mkiv b/tex/context/base/page-sid.mkiv
new file mode 100644
index 000000000..c30204a4e
--- /dev/null
+++ b/tex/context/base/page-sid.mkiv
@@ -0,0 +1,795 @@
+%D \module
+%D [ file=page-sid,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Side Floats,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Side Floats}
+
+\unprotect
+
+% problem: when too small, side effects; we need to determine the
+% shift earlier so that we can act when shift < size
+%
+% \definefloat[edgefigure]
+% \setupfloat
+% [edgefigure]
+% [rightmargindistance=-\rightmargintotal,
+% leftmargindistance=-\rightmargintotal,
+% default=outer]
+% \starttext
+% \placeedgefigure{}{\framed[width=12cm]{}} \input tufte
+% \placeedgefigure{}{\framed[width=5cm]{}} \input tufte
+% \placeedgefigure{}{\framed[width=4cm]{}} \input tufte
+% \placeedgefigure{}{\framed[width=2cm]{}} \input tufte
+% \stoptext
+
+% todo: dimexpr an dnumexpr
+
+% These macro deal with side floats. We started with Daniel
+% Comenetz macros as published in TUGBoat Volume 14 (1993),
+% No.\ 1: Anchored Figures at Either Margin. I extended and
+% patched the macros to suite our needs which results in a
+% messy module. Therefore, this module badly needs an update
+% because it's now a mixture of old and new macros.
+
+% afhankelijke variabelen
+%
+% \overgap vervangen door \floatsidetopskip
+% \sidegap vervangen door \floatsideskip
+% \undergap vervangen door \floatsidebottomskip
+%
+% \prskp vervangen door \ctxparskip
+
+% toegevoegde macro's/aanroepen
+%
+% \logsidefloat : loginformatie
+% \flushsidefloats : nodig voor koppen
+
+% recente wijzigingen:
+%
+% namen aangepast: \float... enz. i.p.v. \pic
+
+% Pas op: \EveryPar{\EveryPar{}\margetitel{whatever}}
+% \plaatsfiguur[links]{}{} moet goed gaan. In dat geval
+% begint de tekst terecht wat lager.
+
+\newdimen\sidefloatheight % includes the topskip
+\newdimen\sidefloatwidth
+\newdimen\sidefloathsize
+\newdimen\sidefloatshift
+\newdimen\sidefloatextrashift
+\newdimen\sidefloatvsize \def\nofloatvsize{-1pt }
+\newdimen\sidefloatprogress
+\newdimen\sidefloatpagetotal
+
+\newbox\floatbottom
+
+\newcount\sidefloatsidelines
+\newcount\sidefloatlinesdone
+
+% 1 = backspace
+% 2 = leftedge
+% 3 = leftmargin
+% 4 = leftside
+% 5 = rightside
+% 6 = rightmargin
+% 7 = rightedge
+% 8 = cutspace
+
+\chardef\sidefloattype\zerocount
+
+\def\backspacefloat {\global\chardef\sidefloattype1 \putsidefloat}
+\def\leftedgefloat {\global\chardef\sidefloattype2 \putsidefloat}
+\def\leftmarginfloat {\global\chardef\sidefloattype3 \putsidefloat}
+\def\leftfloat {\global\chardef\sidefloattype4 \putsidefloat}
+\def\rightfloat {\global\chardef\sidefloattype5 \putsidefloat}
+\def\rightmarginfloat {\global\chardef\sidefloattype6 \putsidefloat}
+\def\rightedgefloat {\global\chardef\sidefloattype7 \putsidefloat}
+\def\cutspacefloat {\global\chardef\sidefloattype8 \putsidefloat}
+
+\let\marginfloat \cutspacefloat
+
+\newif\ifroomforfloat
+\newif\iffloatshort
+\newif\iffloatflag
+\newif\iffloatrighteqo
+\newif\iffloatlefteqo
+
+\newdimen\sidefloatleftskip
+\newdimen\sidefloatrightskip
+\newdimen\sidefloatmaximum
+
+\def\checksidefloatshift
+ {\ifdim\sidefloatmaximum>\zeropoint
+ \ifcase\sidefloattype
+ % invalid
+ \or
+ % backspace
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftedgedistance \rightedgedistance
+ -\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ % left
+ \or
+ % right
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ \global\sidefloatshift\dimexpr
+ -\sidefloatmaximum
+ -\rightorleftpageaction \leftedgedistance \rightedgedistance
+ -\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ -\rightorleftpageaction \leftmargindistance \rightmargindistance
+ -\compensatedinnermakeupmargin
+ \relax
+ \or
+ % cutspace
+ \fi
+ \fi}
+
+\def\setsidefloatskips
+ {\global\sidefloatrightskip\zeropoint
+ \global\sidefloatleftskip \zeropoint
+ \ifcase\sidefloattype
+ \or % backspace
+ \global\sidefloatleftskip\dimexpr
+ +\rightorleftpageaction \backspace \cutspace
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftedge
+ \global\sidefloatleftskip\dimexpr
+ +\rightorleftpageaction \leftmargindistance \rightmargindistance
+ +\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+ +\rightorleftpageaction \leftedgedistance \rightedgedistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftmargin
+ \global\sidefloatleftskip\dimexpr
+ +\rightorleftpageaction \leftmargindistance \rightmargindistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % leftside
+ \or % rightside
+ \or % rightmargin
+ \global\sidefloatrightskip\dimexpr
+ +\rightorleftpageaction \rightmargindistance \leftmargindistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % rightedge
+ \global\sidefloatrightskip\dimexpr
+ +\rightorleftpageaction \rightmargindistance \leftmargindistance
+ +\rightorleftpageaction \rightmarginwidth \leftmarginwidth
+ +\rightorleftpageaction \rightedgedistance \leftedgedistance
+ +\compensatedinnermakeupmargin
+ \relax
+ \or % cutspace
+ \global\sidefloatrightskip\dimexpr
+ +\rightorleftpageaction \cutspace \backspace
+ +\compensatedinnermakeupmargin
+ \relax
+ \fi
+ \ifdim\sidefloatrightskip>\zeropoint \doglobal\advance\sidefloatrightskip\rightskip \fi
+ \ifdim\sidefloatleftskip >\zeropoint \doglobal\advance\sidefloatleftskip \leftskip \fi}
+
+% eq is still crap
+
+\ifx\normalleqno\undefined
+
+ \let\floatrighteqo=\eqno
+ \let\floatleftleqo=\leqno
+
+\else
+
+ \let\floatrighteqo=\normaleqno
+ \let\floatleftleqo=\normalleqno
+
+\fi
+
+% Watch it even more! In inner, gaat't mis omdat daar
+% pagetotal enz niet zijn aangepast. Inner kan overigens niet
+% betrouwbaar worden getest!
+
+\newif\iftracesidefloats
+
+\def\flushsidefloats
+ {\par
+ \!!heighta\sidefloatvsize
+ \advance\!!heighta -\pagetotal
+ \ifnum\!!heighta>\zeropoint
+ \global\advance\sidefloatvsize -\sidefloatbottomskip
+ \ifdim\!!heighta>\zeropoint
+ \bgroup
+ \let\flushsidefloats\relax
+ \forgetall
+ \doloop
+ {\strut
+ \iftracesidefloats
+ \color[darkgray]%
+ {\baselinerulefalse
+ \boxrulewidth.5\points
+ \ruledhbox{\strut\kern\sidefloatwidth}}%
+ \fi
+ \par
+ \!!heighta\sidefloatvsize
+ \advance\!!heighta -\pagetotal
+ \ifdim\!!heighta>\zeropoint
+ \ifnum\recurselevel>\plushundred
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \egroup
+ \ifdim\parskip>\zeropoint
+ \ifdim\sidefloatbottomskip>\parskip
+ \nowhitespace
+ \vskip\sidefloatbottomskip
+ \fi
+ \fi
+ \else\ifdim\sidefloatbottomskip>\parskip
+ \vskip\sidefloatbottomskip
+ \fi\fi
+ \fi
+ % not entirely the same as \forgetsidefloats
+ \global\sidefloatvsize\nofloatvsize
+ % \global\sidefloatsidelines\zerocount % no, we flush before a side float
+ \global\floatshortfalse % so this will get lost
+ % also here if used at all \global\holdinginserts\zerocount
+ \global\floatflagfalse}
+
+\def\dochecksidefloatafterpar
+ {\dochecksidefloat
+ \ifdim\oldpagetotal=\pagetotal \else
+ \global\let\checksidefloat\dochecksidefloat
+ \flushsidefloats
+ \global\sidefloatsidelines\zerocount % here !
+ \fi}
+
+\def\flushsidefloatsafterpar
+ {\xdef\oldpagetotal{\the\pagetotal}%
+ \global\let\checksidefloat\dochecksidefloatafterpar}
+
+\def\forgetsidefloats
+ {\global\sidefloatvsize\nofloatvsize
+ \global\sidefloatsidelines\zerocount
+ % also here if used at all \global\holdinginserts\zerocount
+ \global\floatshortfalse
+ \global\floatflagfalse}
+
+\let\logsidefloat=\relax
+
+\def\pushpenalties % needed ? and right
+ {\widowpenalty\plusone
+ \clubpenalty\plustwo
+ \brokenpenalty\plusone
+ \let\pushpenalties\relax
+ \edef\poppenalties
+ {\widowpenalty \the\widowpenalty
+ \clubpenalty \the\clubpenalty
+ \brokenpenalty\the\brokenpenalty
+ \let\poppenalties\relax}}
+
+% shouldn;t that be:
+%
+% \def\pushpenalties % needed?
+% {\let\pushpenalties\relax
+% \edef\poppenalties
+% {\widowpenalty \the\widowpenalty
+% \clubpenalty \the\clubpenalty
+% \brokenpenalty\the\brokenpenalty
+% \let\poppenalties\relax}%
+% \widowpenalty\plusone
+% \clubpenalty\plustwo
+% \brokenpenalty\plusone}
+
+\let\poppenalties=\relax
+
+\def\restorepenalties
+ {\ifnum\outputpenalty=\!!tenthousand\else
+ \penalty\outputpenalty
+ \fi}
+
+\def\sidefloatoutput
+ {\iffloatshort
+ \unvbox\normalpagebox
+ \setbox\floatbottom\lastbox
+ \ifdim\wd\floatbottom>\sidefloathsize
+ \penalty-201
+ \box\floatbottom
+ \else
+ \ifvoid\floatbottom
+ \else
+ \restoreleftindent
+ \ifdim\wd\floatbottom<\sidefloathsize
+ \parskip\zeropoint
+ %\noindent
+ \ifinner\else\vadjust{\penalty\minusone}\fi
+ \iffloatlefteqo
+ \global\floatlefteqofalse
+ \else
+ \global\advance\sidefloathsize -\wd\floatbottom
+ \iffloatrighteqo
+ \global\floatrighteqofalse
+ \else
+ \global\divide\sidefloathsize \plustwo
+ \fi
+ \hskip\sidefloathsize
+ \fi
+ \fi
+ \box\floatbottom
+ \restorepenalties
+ \fi
+ \fi
+ % why was this \global\holdinginserts\zerocount
+ \global\floatshortfalse
+ \else
+ \finalsidefloatoutput % new
+ \global\sidefloatvsize\nofloatvsize
+ \global\sidefloatsidelines\zerocount
+ % we can end up in fig lock, so \global\holdinginserts\zerocount here too ?
+ \poppenalties
+ \fi}
+
+\def\finalsidefloatoutput% new
+ {\finaloutput\unvbox\normalpagebox}
+
+\def\restoreleftindent
+ {\relax \ifnum\sidefloattype>4 \else
+ \parskip\zeropoint % here ?
+ \ifdim\sidefloatwidth>\zeropoint % new, see prikkels
+ \noindent
+ \ifinner\else\vadjust{\penalty\minusone}\fi
+ \hskip\sidefloatwidth\relax
+ %\else
+ % we have a margin or edge float
+ \fi
+ \fi}
+
+\ifx\normaleqno\undefined
+
+ \def\normaleqno
+ {\iffloatshort
+ \global\floatrighteqotrue
+ \fi
+ \floatrighteqo}
+
+\else
+
+ \def\eqno
+ {\iffloatshort
+ \global\floatrighteqotrue
+ \fi
+ \floatrighteqo}
+
+\fi
+
+% externfiguur -> grid =ja|hoogte|diepte|halveregel|passend -> helemaal in details
+% stelplaatsblokin -> zijuitlijnen=hoogte|diepte|regel|halveregel|grid -> halveregel in 'details'
+
+% replacement for below
+%
+% \global\setbox\floatbox\hbox % no \hskip, but \kern here
+% {\ifcase\sidefloattype
+% \vbox{#1}%
+% \or % 1
+% \hskip\sidefloatleftshift
+% \hskip\sidefloatshift
+% \vbox{#1}%
+% \kern-\sidefloatextrashift
+% \or % 2
+% \hskip\sidefloatshift
+% \vbox{#1}%
+% \kern-\sidefloatextrashift
+% \or % 3
+% \hskip\sidefloatshift
+% \vbox{#1}%
+% \kern-\sidefloatextrashift
+% \or % 4
+% \hskip\sidefloatleftshift
+% \hskip\sidefloatshift
+% \vbox{#1\removedepth}%
+% \kern-\sidefloatextrashift
+% \or % 5
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \kern\sidefloatrightshift
+% \or % 6
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \or % 7
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \or % 8
+% \hskip-\sidefloatextrashift
+% \vbox{#1}%
+% \kern\sidefloatshift
+% \kern\sidefloatrightshift
+% \fi}%
+%
+% keep this ^
+
+\def\repositionsidefloat#1%
+ {\global\setbox\floatbox\hbox % no \hskip, but \kern here
+ {\ifnum\sidefloattype=\plusfour
+ \hskip\sidefloatleftshift
+ \else\ifnum\sidefloattype=\plusone
+ \hskip\sidefloatleftshift
+ \fi\fi
+ \ifnum\sidefloattype>\plusfour
+ \hskip-\sidefloatextrashift
+ \else
+ \hskip\sidefloatshift
+ \fi
+ \vbox{#1\ifnum\sidefloatalign=\plusfour \removedepth\fi}%
+ \ifnum\sidefloattype>\plusfour
+ \kern\sidefloatshift
+ \else
+ \kern-\sidefloatextrashift
+ \fi
+ \ifnum\sidefloattype=8
+ \kern\sidefloatrightshift
+ \else\ifnum\sidefloattype=\plusfive
+ \kern\sidefloatrightshift
+ \fi\fi}}
+
+\def\putsidefloat#1% grid (4) is rather experimental
+ {\par
+ \whitespace
+ % moved here dec 2001
+ {\everypar\emptytoks\forgetall\verticalstrut\vskip-\struttotal}% moved
+ \checksidefloatshift
+ \ifdim\sidefloatshift=\zeropoint \relax
+ \ifnum\sidefloattype=\plusfour
+ \global\advance\sidefloatshift\sidefloatextrashift
+ \global\sidefloatextrashift\zeropoint
+ \else\ifnum\sidefloattype=\plusfive
+ \global\advance\sidefloatshift\sidefloatextrashift
+ \global\sidefloatextrashift\zeropoint
+ \fi\fi
+ \else
+ \ifnum\sidefloattype<\plusfour
+ \global\chardef\sidefloattype\plusfour
+ \else\ifnum\sidefloattype>\plusfive
+ \global\chardef\sidefloattype\plusfive
+ \fi\fi
+ \fi
+ \previoussidefloat
+ \stallsidefloat
+ \repositionsidefloat{#1}%
+ \ifnum\sidefloatalign=\plusfour
+ \getnoflines{\ht\floatbox}%
+ \scratchdimen\noflines\lineheight
+ \advance\scratchdimen-\strutdepth
+ \getrawnoflines\sidefloattopskip
+ \advance\scratchdimen\noflines\lineheight
+ % todo: maybe rounding problem here
+ % \global\setbox\floatbox\hbox{\lower\lineheight\box\floatbox}%
+ \global\setbox\floatbox\hbox{\lower\strutdepth\box\floatbox}%
+ \global\ht\floatbox\scratchdimen
+ \global\dp\floatbox\zeropoint
+ \fi
+ \ifcase\sidefloatalign \else
+ \global\sidefloattopskip\zeropoint
+ \fi
+ \scratchdimen
+ \ifnum\sidefloattype<\plusfour
+ \sidefloattopskip
+ \else\ifnum\sidefloattype>\plusfive
+ \sidefloattopskip
+ \else
+ \zeropoint
+ \fi\fi
+ % the top of the box is at the previous baseline
+ \ifcase\sidefloatalign
+ % 0 normal
+ \advance\scratchdimen\strutdepth % == \sidefloattopoffset
+ \or % 1 height
+ \advance\scratchdimen\strutdepth % == \sidefloattopoffset
+ \or % 2 line
+ \or % 3 depth
+ \advance\scratchdimen\lineheight
+ \advance\scratchdimen\strutdepth
+ \or % 4 grid
+ \scratchdimen\zeropoint
+ \or
+ \advance\scratchdimen\strutheight
+ \fi
+ % new
+ \global\sidefloatlinesdone\zerocount
+ \ifnum\sidefloatsidelines>\zerocount
+ \advance\scratchdimen\sidefloatsidelines\lineheight
+ \fi
+ % new
+ \global\setbox\floatbox\hbox
+ {\vbox
+ {\vskip\scratchdimen
+ \nointerlineskip
+ \box\floatbox
+ \ifnum\sidefloatalign=\plusfive \vskip-\lineheight \fi}}%
+ \ifnum\sidefloattype<\plusfour
+ \global\sidefloattopskip\zeropoint
+ \else\ifnum\sidefloattype>\plusfive
+ \global\sidefloattopskip\zeropoint
+ \fi\fi
+ \global\sidefloatdownshift\zeropoint
+ \measuresidefloat
+ \ifroomforfloat \else
+ \vfill\eject % inline \tosssidefloat
+ \measuresidefloat
+ \stallsidefloat
+ \fi
+ \setsidefloat}
+
+\def\progresssidefloat
+ {\sidefloatprogress\sidefloatvsize
+ \advance\sidefloatprogress-\iffloatflag\sidefloatpagetotal\global\floatflagfalse\else\pagetotal\fi}
+
+\def\measuresidefloat
+ {\global\floatflagtrue
+ \global\sidefloatpagetotal \pagetotal % global
+ \ifnum\sidefloattype<\plusfour
+ \global \sidefloatwidth \zeropoint
+ \else\ifnum\sidefloattype>\plusfive
+ \global \sidefloatwidth \zeropoint
+ \else
+ \global \sidefloatwidth \wd\floatbox
+ \global\advance\sidefloatwidth \floatsideskip
+ \fi\fi
+ \ifdim\sidefloatwidth<\zeropoint
+ \global\sidefloatwidth\zeropoint
+ \fi
+ \global \sidefloathsize \hsize
+ \global\advance\sidefloathsize -\sidefloatwidth
+ \global \sidefloatheight \ht\floatbox
+ \global\advance\sidefloatheight \dp\floatbox
+ \global\advance\sidefloatheight \sidefloattopskip
+ \global \sidefloatvsize \sidefloatheight
+ \global\advance\sidefloatvsize \sidefloatpagetotal
+ \dimen0\sidefloatvsize
+ \dimen2\pagegoal
+ \relax
+ \ifcase\sidefloatmethod
+ % method 0 : raw
+ \or
+ % method 1 : safe
+ \dimen2 .99\pagegoal
+ \or
+ % method 2 : tight
+ \advance\dimen0 -\onepoint
+ \fi
+ \relax % really needed ! ! ! !
+ \ifdim\dimen0>\dimen2
+ \global\roomforfloatfalse
+ \else
+ \dimen0=\pagegoal
+ \advance\dimen0 -\sidefloatvsize
+ \ifdim\dimen0<\sidefloatbottomskip
+ \global\advance\sidefloatvsize \dimen0
+ \global\floatshorttrue
+ \pushpenalties
+ % why was this \global\holdinginserts\plusone
+ \else
+ \global\advance\sidefloatvsize \sidefloatbottomskip
+ \global\floatshortfalse
+ \fi
+ \global\roomforfloattrue
+ \fi}
+
+\def\setsidefloat% nilling everypar saves time and redudant pos's
+ {% removed here dec 2001
+ % {\everypar\emptytoks\forgetall\verticalstrut\vskip-\struttotal}%
+ \ifnum\sidefloattype=\plusfour \kern\sidefloattopskip \fi
+ \ifnum\sidefloattype=\plusfive \kern\sidefloattopskip \fi
+ \edef\presidefloatdepth{\the\prevdepth}%
+ \nointerlineskip
+ \bgroup
+ \everypar\emptytoks
+ \parskip\zeropoint
+ \setsidefloatskips
+ \logsidefloat
+ \relax
+ \ifcase\sidefloattype
+ % invalid
+ \or % backspace
+ \noindent\llap{\rlap{\box\floatbox}\hskip\sidefloatleftskip}\hfill
+ \or % leftedge
+ \noindent\llap{\box\floatbox\hskip\sidefloatleftskip}\hfill
+ \or % leftmargin
+ \noindent\llap{\box\floatbox\hskip\sidefloatleftskip}\hfill
+ \or % leftside
+ \noindent\box\floatbox\hfill
+ \or % rightside
+ \hfill\box\floatbox
+ \or % rightmargin
+ \hfill\rlap{\hskip\sidefloatrightskip\box\floatbox}%
+ \or % rightedge
+ \hfill\rlap{\hskip\sidefloatrightskip\box\floatbox}%
+ \or % cutspace
+ \hfill\rlap{\hskip\sidefloatrightskip\llap{\box\floatbox}}%
+ \fi
+ \egroup
+ \par
+\ifgridsnapping
+ \getrawnoflines\sidefloatheight
+ \sidefloatheight=\noflines\lineheight
+\fi
+ \kern-\sidefloatheight
+ \penalty10001 % oeps, this will change
+ \normalbaselines
+ \prevdepth\presidefloatdepth
+ % \noindent
+ \resetsidefloatparagraph
+ \ignorespaces} % not really needed
+
+\newcount\sidefloatparagraph
+
+\def\iffirstsidefloatparagraph
+ {\ifcase\sidefloatparagraph\or}
+
+% without sidefloat lines
+%
+% \def\setsidefloatparagraph
+% {%\advance\sidefloatprogress \sidefloatbottomskip
+% %\!!counta\sidefloatprogress
+% \scratchdimen\sidefloatprogress
+% \advance\scratchdimen \strutht
+% \advance\scratchdimen -\roundingeps % new, needed in prikkels, prevent rounding errors
+% \!!counta\scratchdimen
+% \divide\!!counta \baselineskip
+% \ifnum\!!counta>0
+% \hangindent \ifnum\sidefloattype>4 -\fi\sidefloatwidth
+% \hangafter-\!!counta
+% \fi
+% \global\advance\sidefloatparagraph \plusone
+% \iftracesidefloats
+% \hskip-\sidefloatwidth
+% \color[darkgray]%
+% {\vrule\!!height.5\points\!!depth.5\points\!!width\sidefloatwidth
+% %\hskip-.25\bodyfontsize\showstruts\strut\hskip.25\bodyfontsize}%
+% \llap{\showstruts\strut\hskip.25\bodyfontsize}}%
+% \fi}
+
+\def\setsidefloatparagraph
+ {%\advance\sidefloatprogress \sidefloatbottomskip
+ %\!!counta\sidefloatprogress
+ \scratchdimen\sidefloatprogress
+ \advance\scratchdimen \strutht
+ \advance\scratchdimen -\roundingeps % new, needed in prikkels, prevent rounding errors
+ \!!counta\scratchdimen
+ \divide\!!counta \baselineskip\relax
+ \ifnum\!!counta>0
+ % new from here
+ \ifcase\sidefloatsidelines\else
+ \ifcase\sidefloatlinesdone
+ \global\sidefloatlinesdone\!!counta
+ \else
+ \scratchcounter\sidefloatlinesdone
+ \advance\scratchcounter-\!!counta
+ \global\advance\sidefloatsidelines-\scratchcounter
+ \fi
+ \fi
+ \ifnum\sidefloatsidelines>\zerocount
+ \scratchtoks\emptytoks
+ \scratchcounter\sidefloatsidelines
+ \scratchdimen\hsize
+ \advance\scratchdimen-\sidefloatwidth
+ \dorecurse\sidefloatsidelines
+ {\appendtoks \zeropoint \hsize \to \scratchtoks}%
+ \ifnum\!!counta>\sidefloatsidelines
+ \advance\!!counta -\sidefloatsidelines\relax
+ \advance\scratchcounter\!!counta
+ \dorecurse\!!counta
+ {\ifnum\sidefloattype>\plusfour
+ \appendtoks \zeropoint \scratchdimen \to \scratchtoks
+ \else
+ \appendtoks \sidefloatwidth \scratchdimen \to \scratchtoks
+ \fi}%
+ \fi
+ \advance\scratchcounter \plusone
+ \parshape \scratchcounter \the\scratchtoks \zeropoint \hsize\relax
+ \else
+ % new till here
+ \hangindent \ifnum\sidefloattype>\plusfour -\fi\sidefloatwidth
+ \hangafter-\!!counta
+ \fi
+ \fi
+ \global\advance\sidefloatparagraph \plusone
+ \iftracesidefloats
+ \hskip-\sidefloatwidth
+ \color[darkgray]%
+ {\vrule\!!height.5\points\!!depth.5\points\!!width\sidefloatwidth
+ %\hskip-.25\bodyfontsize\showstruts\strut\hskip.25\bodyfontsize}%
+ \llap{\showstruts\strut\hskip.25\bodyfontsize}}%
+ \fi}
+
+\def\resetsidefloatparagraph
+ {\global\sidefloatparagraph\zerocount}
+
+\def\dochecksidefloat
+ {\progresssidefloat
+ \ifdim\sidefloatprogress>\zeropoint
+ \setsidefloatparagraph
+ \else
+ \resetsidefloatparagraph
+ \fi
+ \parskip\ctxparskip}
+
+\let\checksidefloat\dochecksidefloat
+
+\def\synchronizesidefloats
+ {\ifinner \else \checksidefloat \fi}
+
+\def\doadjustsidefloatdisplaylines
+ {\par
+ % not in mkiv: \vskip-\parskip
+ \noindent
+ \ignorespaces}
+
+\def\adjustsidefloatdisplaylines
+ {\aftergroup\doadjustsidefloatdisplaylines}
+
+\def\previoussidefloat
+ {\progresssidefloat
+ \ifdim\sidefloatprogress>\zeropoint \relax
+ \iffloatshort
+ \global\floatshortfalse
+ \vfill\eject % inline \tosssidefloat
+ \else
+ \kern\sidefloatprogress
+ \fi
+ \fi}
+
+\def\stallsidefloat
+ {\!!counta\pageshrink
+ \divide\!!counta \baselineskip
+ \advance\!!counta \plusone
+ \parskip\zeropoint
+ \dorecurse\!!counta{\line{}}
+ \kern-\!!counta\baselineskip
+ \penalty\zerocount }
+
+% We need to hook it into the other otr's. This code will move.
+
+\let\OTRONEflushsidefloats \flushsidefloats
+\let\OTRONEsynchronizesidefloats\synchronizesidefloats
+
+% page-set
+%
+% \let\OTRSETflushsidefloats \forgetsidefloats
+% \let\OTRSETsynchronizesidefloats\forgetsidefloats
+
+% page-mul
+%
+% \let\OTRMULflushsidefloats \forgetsidefloats
+% \let\OTRMULsynchronizesidefloats\forgetsidefloats
+
+\registerotrcommand\synchronizesidefloats % \def\synchronizesidefloats{\OTRcommand\synchronizesidefloats}
+\registerotrcommand\flushsidefloats % \def\flushsidefloats {\OTRcommand\flushsidefloats}
+
+\protect \endinput
diff --git a/tex/context/base/page-spr.mkii b/tex/context/base/page-spr.mkii
new file mode 100644
index 000000000..06947a36a
--- /dev/null
+++ b/tex/context/base/page-spr.mkii
@@ -0,0 +1,104 @@
+%D \module
+%D [ file=page-spr,
+%D version=2002.11.11,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Spreading,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Spreading}
+
+% This module is experimental and not yet official!
+
+\unprotect
+
+\newbox\spreadbox
+\newif \ifinspread
+
+\chardef\showspreadmode=1
+
+% beware, ugly overload, to be redone
+
+\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear
+ {\setbox#1\hbox
+ {\vbox to \textheight
+ {\offinterlineskip
+ \freezetextwidth
+ \hsize\textwidth % local variant of \sethsize
+ \boxmaxdepth\maxdepth
+ \noindent % content can be < \hsize
+ \dopagecontents#2#3}}%
+ \dp#1\zeropoint
+ \setbox#1\hbox to \makeupwidth
+ {\ifinspread
+ \ifvoid\spreadbox
+ \global\setbox\spreadbox\box#1%
+ \copy\spreadbox\hss % left page
+ \else
+ % prevent duplicate writes in normal run
+ \ifarrangingpages \else \ifcase\showspreadmode
+ \global\setbox\spreadbox\null
+ \wd\spreadbox\makeupwidth
+ \ht\spreadbox\textheight
+ \fi \fi
+ \hss\box\spreadbox % right page
+ \fi
+ \else
+ \hss\box#1\hss % never change the \hss's
+ \fi}}
+
+\def\doflushspread
+ {\ifinspread \ifvoid\spreadbox\else
+ % this page will be discarded later
+ \null \page
+ \fi \fi }
+
+\def\startspread
+ {\bgroup
+ \ifdoublesided
+ \page[\v!left]%
+ %\setsystemmode{spread}%
+ \inspreadtrue
+ \scratchdimen2\textwidth
+ \advance\scratchdimen2\backspace
+ \expanded{\setuplayout[\c!textwidth=\the\scratchdimen]}%
+ \def\startspread{\bgroup\let\stopspread\egroup}%
+ \let\stopspread\dostopspread
+ \else
+ \let\stopspread\egroup
+ \fi}
+
+\let\stopspread\relax
+
+\def\dostopspread
+ {\kern\zeropoint\page
+ \inspreadfalse
+ \setuplayout[\c!textwidth=\textwidth]
+ \page[\v!left]
+ \egroup}
+
+\protect \endinput
+
+% texexec --arr --pdf test
+%
+% \setuplayout[width=middle]
+% \setuppapersize[A4][A3,landscape]
+% \setuppagenumbering[alternative=doublesided]
+% \setuparranging[2UP]
+%
+% \starttext
+%
+% \dorecurse{3}{\input tufte }
+%
+% \startspread
+% \dorecurse{10}{\input tufte }
+% \stopspread
+%
+% \dorecurse{3}{\input tufte }
+%
+% \stoptext
diff --git a/tex/context/base/page-spr.mkiv b/tex/context/base/page-spr.mkiv
new file mode 100644
index 000000000..75b91dff7
--- /dev/null
+++ b/tex/context/base/page-spr.mkiv
@@ -0,0 +1,103 @@
+%D \module
+%D [ file=page-spr,
+%D version=2002.11.11,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Spreading,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Page Macros / Spreading}
+
+% This module is experimental and not yet official!
+
+\unprotect
+
+\newbox\spreadbox
+\newif \ifinspread
+
+\chardef\showspreadmode\plusone
+
+% beware, ugly overload, to be redone
+
+\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear
+ {\setbox#1\hbox
+ {\setlayoutcomponentattribute\v!page\v!text
+ \vbox \layoutcomponentboxattribute to \textheight
+ {\offinterlineskip
+ \freezetextwidth
+ \hsize\textwidth % local variant of \sethsize
+ \boxmaxdepth\maxdepth
+ \noindent % content can be < \hsize
+ \dopagecontents#2#3}}%
+ \dp#1\zeropoint
+ \setbox#1\hbox to \makeupwidth
+ {\ifinspread
+ \ifvoid\spreadbox
+ \global\setbox\spreadbox\box#1%
+ \copy\spreadbox\hss % left page
+ \else
+ % prevent duplicate writes in normal run
+ \ifarrangingpages \else \ifcase\showspreadmode
+ \global\setbox\spreadbox\null
+ \wd\spreadbox\makeupwidth
+ \ht\spreadbox\textheight
+ \fi \fi
+ \hss\box\spreadbox % right page
+ \fi
+ \else
+ \hss\box#1\hss % never change the \hss's
+ \fi}}
+
+\def\doflushspread
+ {\ifinspread \ifvoid\spreadbox\else
+ % this page will be discarded later
+ \null \page
+ \fi \fi }
+
+\unexpanded\def\startspread
+ {\bgroup
+ \ifdoublesided
+ \page[\v!left]%
+ %\setsystemmode{spread}%
+ \inspreadtrue
+ \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}%
+ \unexpanded\def\startspread{\bgroup\let\stopspread\egroup}%
+ \let\stopspread\dostopspread
+ \else
+ \let\stopspread\egroup
+ \fi}
+
+\let\stopspread\relax
+
+\def\dostopspread
+ {\kern\zeropoint\page
+ \inspreadfalse
+ \setuplayout[\c!textwidth=\textwidth]
+ \page[\v!left]
+ \egroup}
+
+\protect \endinput
+
+% texexec --arr --pdf test
+%
+% \setuplayout[width=middle]
+% \setuppapersize[A4][A3,landscape]
+% \setuppagenumbering[alternative=doublesided]
+% \setuparranging[2UP]
+%
+% \starttext
+%
+% \dorecurse{3}{\input tufte }
+%
+% \startspread
+% \dorecurse{10}{\input tufte }
+% \stopspread
+%
+% \dorecurse{3}{\input tufte }
+%
+% \stoptext
diff --git a/tex/context/base/page-str.lua b/tex/context/base/page-str.lua
new file mode 100644
index 000000000..c4d1957c3
--- /dev/null
+++ b/tex/context/base/page-str.lua
@@ -0,0 +1,221 @@
+if not modules then modules = { } end modules ['page-str'] = {
+ version = 1.001,
+ comment = "companion to page-str.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- work in progresss .. unfinished
+
+local concat = table.concat
+
+local find_tail, write_node, free_node, copy_nodelist = node.slide, node.write, node.free, node.copy_list
+local vpack_nodelist, hpack_nodelist = node.vpack, node.hpack
+local texdimen, texbox = tex.dimen, tex.box
+
+local new_kern = nodes.kern
+local new_glyph = nodes.glyph
+
+local trace_collecting = false trackers.register("streams.collecting", function(v) trace_collecting = v end)
+local trace_flushing = false trackers.register("streams.flushing", function(v) trace_flushing = v end)
+
+streams = streams or { }
+
+local data, name, stack = { }, nil, { }
+
+function streams.enable(newname)
+ if newname == "default" then
+ name = nil
+ else
+ name = newname
+ end
+end
+
+function streams.disable()
+ name = stack[#stack]
+end
+
+function streams.start(newname)
+ table.insert(stack,name)
+ name = newname
+end
+
+function streams.stop(newname)
+ name = table.remove(stack)
+end
+
+function streams.collect(head,where)
+ if name and head and name ~= "default" then
+ local tail = node.slide(head)
+ local dana = data[name]
+ if not dana then
+ dana = { }
+ data[name] = dana
+ end
+ local last = dana[#dana]
+ if last then
+ local tail = find_tail(last)
+ tail.next, head.prev = head, tail
+ elseif last == false then
+ dana[#dana] = head
+ else
+ dana[1] = head
+ end
+ if trace_collecting then
+ logs.report("streams","appending snippet '%s' to slot %s",name,#dana)
+ end
+ return nil, true
+ else
+ return head, false
+ end
+end
+
+function streams.push(thename)
+ if not thename or thename == "" then
+ thename = name
+ end
+ if thename and thename ~= "" then
+ local dana = data[thename]
+ if dana then
+ dana[#dana+1] = false
+ if trace_collecting then
+ logs.report("streams","pushing snippet '%s'",thename)
+ end
+ end
+ end
+end
+
+function streams.flush(name,copy) -- problem: we need to migrate afterwards
+ local dana = data[name]
+ if dana then
+ local dn = #dana
+ if dn == 0 then
+ -- nothing to flush
+ elseif copy then
+ if trace_flushing then
+ logs.report("streams","flushing copies of %s slots of '%s'",dn,name)
+ end
+ for i=1,dn do
+ local di = dana[i]
+ if di then
+ write_node(copy_nodelist(di.list)) -- list, will be option
+ end
+ end
+ if copy then
+ data[name] = nil
+ end
+ else
+ if trace_flushing then
+ logs.report("streams","flushing %s slots of '%s'",dn,name)
+ end
+ for i=1,dn do
+ local di = dana[i]
+ if di then
+ write_node(di.list) -- list, will be option
+ di.list = nil
+ free_node(di)
+ end
+ end
+ end
+ end
+end
+
+function streams.synchronize(list) -- this is an experiment !
+ -- we don't optimize this as we want to trace in detail
+ list = aux.settings_to_array(list)
+ local max = 0
+ if trace_flushing then
+ logs.report("streams","synchronizing list: %s",concat(list," "))
+ end
+ for i=1,#list do
+ local dana = data[list[i]]
+ if dana then
+ local n = #dana
+ if n > max then
+ max = n
+ end
+ end
+ end
+ if trace_flushing then
+ logs.report("streams","maximum number of slots: %s",max)
+ end
+ for m=1,max do
+ local height, depth = 0, 0
+ for i=1,#list do
+ local name = list[i]
+ local dana = data[name]
+ local slot = dana[m]
+ if slot then
+ local vbox = vpack_nodelist(slot)
+ local ht, dp = vbox.height, vbox.depth
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ dana[m] = vbox
+ if trace_flushing then
+ logs.report("streams","slot %s of '%s' is packed to height %s and depth %s",m,name,ht,dp)
+ end
+ end
+ end
+ if trace_flushing then
+ logs.report("streams","slot %s has max height %s and max depth %s",m,height,depth)
+ end
+ local strutht, strutdp = texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth
+ local struthtdp = strutht + strutdp
+ for i=1,#list do
+ local name = list[i]
+ local dana = data[name]
+ local vbox = dana[m]
+ if vbox then
+ local delta_height = height - vbox.height
+ local delta_depth = depth - vbox.depth
+ if delta_height > 0 or delta_depth > 0 then
+ if false then
+ -- actually we need to add glue and repack
+ vbox.height, vbox.depth = height, depth
+ if trace_flushing then
+ logs.report("streams","slot %s of '%s' with delta (%s,%s) is compensated",m,i,delta_height,delta_depth)
+ end
+ else
+ -- this is not yet ok as we also need to keep an eye on vertical spacing
+ -- so we might need to do some splitting or whatever
+ local tail = vbox.list and find_tail(vbox.list)
+ local n, delta = 0, delta_height -- for tracing
+ while delta > 0 do
+ -- we need to add some interline penalties
+ local line = copy_nodelist(tex.box.strutbox)
+ line.height, line.depth = strutht, strutdp
+ if tail then
+ tail.next, line.prev = line, tail
+ end
+ tail = line
+ n, delta = n +1, delta - struthtdp
+ end
+ dana[m] = vpack_nodelist(vbox.list)
+ vbox.list = nil
+ free_node(vbox)
+ if trace_flushing then
+ logs.report("streams","slot %s:%s with delta (%s,%s) is compensated by %s lines",m,i,delta_height,delta_depth,n)
+ end
+ end
+ end
+ else
+ -- make dummy
+ end
+ end
+ end
+end
+
+tasks.appendaction("mvlbuilders", "normalizers", "streams.collect")
+
+tasks.disableaction("mvlbuilders", "streams.collect")
+
+function streams.initialize()
+ tasks.enableaction ("mvlbuilders", "streams.collect")
+end
+
+-- todo: remove empty last { }'s
diff --git a/tex/context/base/page-str.mkii b/tex/context/base/page-str.mkii
new file mode 100644
index 000000000..cfaebe398
--- /dev/null
+++ b/tex/context/base/page-str.mkii
@@ -0,0 +1,376 @@
+%D \module
+%D [ file=page-str,
+%D version=2006.03.21,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Streams,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 Page Macros / Page Streams}
+
+%D The first version of this component of \CONTEXT\ was written
+%D for Thomas Schmitz who asked for parallel page streams. While
+%D playing with the code, I decided to make it into a component
+%D that can be used to construct all kind of stream related
+%D mechanisms. Because I could apply this feature in a project,
+%D there is some additional code here (related to graphics).
+%D
+%D These macros were written while listening to and watching the DVD
+%D \quotation {Rush In Rio}.
+
+% not yet ok in mkiv ... marknotes
+
+\unprotect
+
+% taco, what is the best way to append a otr chunk (insert pagediscards?)
+
+\let\currentoutputstream\s!default
+
+\newtoks\defaultstreamoutput \defaultstreamoutput=\OTRONEoutput
+
+\newtoks\normalstreamoutput \normalstreamoutput={\saveoutputstream[\currentoutputstream]}
+
+\newcount\streampenalty \streampenalty=-101010101
+
+\ifx\multicolumnseject\undefined \else
+ \let\normalmulticolumnseject\multicolumnseject
+ \def\multicolumnseject{\ifinoutputstream\else\normalmulticolumnseject\fi}
+\fi
+
+\newif\ifinoutputstream
+
+\newtoks \everyenableoutputstream
+
+\appendtoks
+ \flushsidefloats
+\to \everyenableoutputstream
+
+\def\enableoutputstream[#1]%
+ {\the\everyenableoutputstream
+ \finishoutputstream
+ \writestatus{otr}{switching to output stream #1}%
+ \inoutputstreamtrue
+ \xdef\currentoutputstream{#1}}
+
+\def\disableoutputstream
+ {\finishoutputstream
+ \writestatus{otr}{switching to default output stream}%
+ \inoutputstreamfalse
+ \global\let\currentoutputstream\s!default}
+
+\def\useoutputstream[#1]%
+ {\writestatus{otr}{using output stream #1}%
+ \xdef\currentoutputstream{#1}}
+
+\def\handlestreamoutput
+ {\doifelse\currentoutputstream\s!default
+ {\ifnum\outputpenalty=\streampenalty
+ \ifvoid\normalpagebox \else
+ \unvbox\normalpagebox
+ \fi
+ \else
+ \the\defaultstreamoutput
+ \fi}
+ {\the\normalstreamoutput}}
+
+\OTRONEoutput{\handlestreamoutput}
+
+\def\defineoutputstream[#1]%
+ {\doifundefined{otrs:#1}{\expandafter\newbox\csname otrs:#1\endcsname}}
+
+\def\outputstreamtag#1%
+ {\csname otrs:#1\endcsname}
+
+\def\finishoutputstream % todo: installoutput
+ {\endgraf
+ \penalty\streampenalty
+ \endgraf}
+
+\def\saveoutputstream[#1]%
+ {\writestatus{otr}{saving otr stream #1}%
+ \ifvoid\normalpagebox
+ \global\setbox\outputstreamtag{#1}\emptybox
+ \else
+ \global\setbox\outputstreamtag{#1}\vbox
+ {\presetoutputstream
+ \ifvoid\outputstreamtag{#1}\else\unvbox\outputstreamtag{#1}\fi
+ \scratchdimen\dp\normalpagebox
+ \unvbox\normalpagebox
+ \vskip-\scratchdimen
+ \kern\strutdepth}%
+ \fi}
+
+% \def\presetoutputstream
+% {\pdffirstlineheight\strutheight
+% \pdflastlinedepth \strutdepth
+% \pdfeachlineheight \strutheight
+% \pdfeachlinedepth \strutdepth}
+
+\let\presetoutputstream\relax
+
+\def\outputstreamht [#1]{\ht\outputstreamtag{#1}}
+\def\outputstreamdp [#1]{\dp\outputstreamtag{#1}}
+\def\outputstreamwd [#1]{\wd\outputstreamtag{#1}}
+
+%def\outputstreambox [#1]{\ifvoid\outputstreamtag{#1}\else\box \outputstreamtag{#1}\fi}
+%def\outputstreamcopy[#1]{\ifvoid\outputstreamtag{#1}\else\copy\outputstreamtag{#1}\fi}
+
+\def\dowithoutputstreambox#1[#2]{\ifvoid\outputstreamtag{#2}\else#1\outputstreamtag{#2}\fi}
+
+\def\outputstreamcopy {\dowithoutputstreambox\copy }
+\def\outputstreambox {\dowithoutputstreambox\box }
+\def\outputstreamunvcopy{\dowithoutputstreambox\unvcopy}
+\def\outputstreamunvbox {\dowithoutputstreambox\unvbox }
+
+%D Footnotes don't go along with streams, simply because there is no
+%D way to re-split inserts. A dirty way out is to use marks and store
+%D notes that way.
+
+\def\definemarknote
+ {\dodoubleempty\dodefinemarknote}
+
+\def\dodefinemarknote[#1][#2]%
+ {\definemarking[mn:#1]%
+ \setvalue{mn:#1:n}{0}%
+ \getparameters
+ [mn:#1]
+ [\c!before=,
+ \c!after=,
+ \c!inbetween=\endgraf,
+ \c!command=\firstofoneargument,
+ #2]}
+
+\def\setmarknote[#1]#2%
+ {\doglobal\incrementvalue{mn:#1:n}%
+ \setgvalue{mn:#1:t:\getvalue{mn:#1:n}}{#2}%
+ \expanded{\marking[mn:#1]{\getvalue{mn:#1:n}}}}
+
+\def\flushmarknotes[#1]% assumes split
+ {\begingroup
+% \edef\firstmarknote{0\fetchmark[mn:#1][column:first]}%
+% \edef\lastmarknote {0\fetchmark[mn:#1][column:last]}%
+% \ifnum\firstmarknote<\lastmarknote\relax
+% \getvalue{mn:#1\c!before}%
+% \dostepwiserecurse\firstmarknote\lastmarknote\plusone
+% {\ifnum\recurselevel>\firstmarknote\relax
+% \ifnum\recurselevel<\lastmarknote\relax
+% \getvalue{mn:#1\c!inbetween}%
+% \fi
+% \fi
+% \getvalue{mn:#1\c!command}{\getvalue{mn:#1:t:\recurselevel}}}%
+% \getvalue{mn:#1\c!after}%
+% \fi
+ \endgroup}
+
+\def\erasemarknotes[#1]%
+ {\begingroup
+ \edef\firstmarknote{0\fetchmark[mn:#1][column:first]}%
+ \edef\lastmarknote {0\fetchmark[mn:#1][column:last]}%
+ \dostepwiserecurse\firstmarknote\lastmarknote\plusone
+ {\global\letvalue{mn:#1:t:\recurselevel}\empty}%
+ \endgroup}
+
+%D The next section implements synchronization of (currently
+%D two) output streams. In due time we will implement both a
+%D vertical and horizontal system, as well as alternative
+%D splitters (firstpagevsize, succesivevsize etc).
+
+\def\synchronizeoutputstreams[#1]% [one,two] [left,right]
+ {\bgroup
+ \getfromcommalist[#1][\plusone]\let\firstoutputstream \commalistelement
+ \getfromcommalist[#1][\plustwo]\let\secondoutputstream\commalistelement
+ \forgeteverypar
+ \def\roundingeps{50sp}%
+ \getboxheight\dimen0\of\box\outputstreamtag\firstoutputstream
+ \getboxheight\dimen2\of\box\outputstreamtag\secondoutputstream
+ \scratchdimen\dimexpr\dimen0-\dimen2\relax
+ \ifdim\scratchdimen<-\roundingeps\relax
+ \scratchdimen-\scratchdimen
+ \writestatus{sync}{compensating first stream: \the\scratchdimen/\number\scratchdimen}%
+ \getroundednoflines\scratchdimen
+ \global\setbox\outputstreamtag\firstoutputstream\vbox
+ {\presetoutputstream
+ \unvbox\outputstreamtag\firstoutputstream\dorecurse\noflines\crlf}%
+ \else\ifdim\scratchdimen>\roundingeps\relax
+ \writestatus{sync}{compensating second stream: \the\scratchdimen/\number\scratchdimen}%
+ \getroundednoflines\scratchdimen
+ \global\setbox\outputstreamtag\secondoutputstream\vbox
+ {\presetoutputstream
+ \unvbox\outputstreamtag\secondoutputstream\dorecurse\noflines\crlf}%
+ \else
+ \writestatus{sync}{no need to compensate streams: \the\scratchdimen/\number\scratchdimen}%
+ \fi\fi
+ \egroup}
+
+\def\nofoutputstreamsplitlines {\v!auto} % {40}
+\def\outputstreamsplittolerance {-5}
+
+\def\flushoutputstreampages[#1]%
+ {\bgroup
+ \getfromcommalist[#1][\plusone]\let\firstoutputstream \commalistelement
+ \getfromcommalist[#1][\plustwo]\let\secondoutputstream\commalistelement
+ \doloop
+ {\flushoutputstreams[#1]%
+ \ifvoid\outputstreamtag\firstoutputstream
+ \ifvoid\outputstreamtag\secondoutputstream
+ \exitloop
+ \else
+ \global\setbox\outputstreamtag\firstoutputstream\vbox{\strut}%
+ \fi
+ \else
+ \ifvoid\outputstreamtag\secondoutputstream
+ \global\setbox\outputstreamtag\secondoutputstream\vbox{\strut}%
+ \else
+ % okay
+ \fi
+ \fi}%
+ \egroup}
+
+\def\flushoutputstreams[#1]%
+ {\bgroup
+ \getfromcommalist[#1][\plusone]\let\firstoutputstream \commalistelement
+ \getfromcommalist[#1][\plustwo]\let\secondoutputstream\commalistelement
+ \doif\nofoutputstreamsplitlines\v!auto
+ {\getrawnoflines\textheight
+ \edef\nofoutputstreamsplitlines{\the\noflines}}%
+ \splittopskip\strutheight
+ \scratchdimen\nofoutputstreamsplitlines\lineheight\relax
+ \unless\iffalse
+ \dimen0\scratchdimen
+ \doloop
+ {\setbox4\copy\outputstreamtag\firstoutputstream
+ \setbox0\vsplit4 to \dimen0
+ \setbox0\vbox
+ {\directsetup{stream:\firstoutputstream:top}%
+ \unvbox0
+ \directsetup{stream:\firstoutputstream:bottom}}%
+ \ifdim\ht0>\scratchdimen
+ \advance\dimen0-\lineheight
+ \else
+ \exitloop
+ \fi}%
+ \scratchdimen\dimen0
+ \dimen2\scratchdimen
+ \doloop
+ {\setbox6\copy\outputstreamtag\secondoutputstream
+ \setbox2\vsplit6 to \dimen2
+ \setbox2\vbox
+ {\directsetup{stream:\secondoutputstream:top}%
+ \unvbox0
+ \directsetup{stream:\secondoutputstream:bottom}}%
+ \ifdim\ht2>\scratchdimen
+ \advance\dimen2-\lineheight
+ \else
+ \exitloop
+ \fi}%
+ \scratchdimen\dimen2
+ \fi
+ \setbox4\copy\outputstreamtag\firstoutputstream
+ \setbox6\copy\outputstreamtag\secondoutputstream
+ \scratchcounter\zerocount
+ \doloop
+ {\setbox0\vsplit4 to \scratchdimen
+ \setbox0\vbox{\unvbox0}%
+ \setbox2\vsplit6 to \scratchdimen
+ \setbox2\vbox{\unvbox2}%
+ \ifvoid4
+ \exitloop
+ \else\ifvoid6
+ \exitloop
+ \else
+ \dimen8=\dimexpr\ht4-\ht6\relax
+ \ifdim\dimen8<\zeropoint\dimen8=-\dimen8\relax\fi
+ \advance\scratchcounter\plusone
+ \ifdim\dimen8<.5\lineheight
+ \exitloop
+ \else\ifnum\outputstreamsplittolerance>\zeropoint
+ \ifnum\scratchcounter>\outputstreamsplittolerance\relax
+ \exitloop
+ \else
+ \advance\scratchdimen\lineheight
+ \fi
+ \else\ifnum\outputstreamsplittolerance<\zeropoint
+ \ifnum-\scratchcounter<\outputstreamsplittolerance\relax
+ \exitloop
+ \else
+ \advance\scratchdimen-\lineheight
+ \fi
+ \else\ifnum\outputstreamsplittolerance=\zeropoint
+ \exitloop
+ \fi\fi\fi\fi
+ \fi\fi}%
+ \setbox0\vsplit\outputstreamtag\firstoutputstream to \scratchdimen
+ \setbox0\vbox to \textheight
+ {\presetoutputstream
+ \directsetup{stream:\firstoutputstream:top}%
+ \unvbox0
+ \vfill
+ \directsetup{stream:\firstoutputstream:bottom}}%
+ \setbox2\vsplit\outputstreamtag\secondoutputstream to \scratchdimen
+ \setbox2\vbox to \textheight
+ {\presetoutputstream
+ \directsetup{stream:\secondoutputstream:top}%
+ \unvbox2
+ \vfill
+ \directsetup{stream:\secondoutputstream:bottom}}%
+ \directsetup{stream:\firstoutputstream:reset}%
+ \directsetup{stream:\secondoutputstream:reset}%
+ \page[even]
+ \box0\vfill\page
+ \box2\vfill\page
+ \egroup}
+
+ %D Although one can put floats in a stream, it sometimes makes sense
+ %D to keep them apart and this is what local floats do.
+
+ \def\setuplocalfloats
+ {\getparameters[\??lf]}
+
+ \setuplocalfloats
+ [%before=\blank,
+ %after=\blank,
+ inbetween=\blank]
+
+ \installfloathandler \v!local \somelocalfloat
+
+ \initializeboxstack{localfloats}
+
+ \newcounter\noflocalfloats
+
+ \def\resetlocalfloats
+ {\doglobal\newcounter\noflocalfloats
+ \initializeboxstack{localfloats}}
+
+ \def\somelocalfloat[#1]%
+ {\doglobal\increment\noflocalfloats
+ \savebox{localfloats}{\noflocalfloats}{\box\floatbox}}
+
+ \def\getlocalfloats
+ {\dorecurse\noflocalfloats
+ {\ifnum\recurselevel=\plusone % 1\relax
+ \getvalue{\??lf\c!before}%
+ \else
+ \getvalue{\??lf\c!inbetween}%
+ \fi
+ \dontleavehmode\hbox{\foundbox{localfloats}\recurselevel}%
+ \ifnum\recurselevel=\noflocalfloats\relax
+ \getvalue{\??lf\c!after}%
+ \fi}}
+
+ \def\flushlocalfloats
+ {\getlocalfloats
+ \resetlocalfloats}
+
+ \def\getlocalfloat#1{\expanded{\foundbox{localfloats}{\number#1}}}
+
+ \def\forcelocalfloats{\let\forcedfloatmethod\v!local}
+
+%D Because many arrangements are possible, we will implement
+%D some examples in a runtime loadable module \type {m-streams}.
+
+\protect \endinput
diff --git a/tex/context/base/page-str.mkiv b/tex/context/base/page-str.mkiv
new file mode 100644
index 000000000..d73643cbe
--- /dev/null
+++ b/tex/context/base/page-str.mkiv
@@ -0,0 +1,144 @@
+%D \module
+%D [ file=page-str,
+%D version=2010.03.13, % 2006.03.21,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Streams,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright=PRAGMA-ADE]
+%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 Page Macros / Page Streams}
+
+%D The first version of this component of \CONTEXT\ was written
+%D for Thomas Schmitz who asked for parallel page streams. While
+%D playing with the code, I decided to make it into a component
+%D that can be used to construct all kind of stream related
+%D mechanisms. Because I could apply this feature in a project,
+%D there is some additional code here (related to graphics).
+%D
+%D These macros were written while listening to and watching the DVD
+%D \quotation {Rush In Rio}.
+%D
+%D The reimplementation (or rather experimenting with the complete
+%D rewrite) was done while looping over \quotation {Wende Snijders
+%D No.9}.
+%D
+%D Remark: marknotes are gone, at least for a while.
+
+\writestatus{loading}{ConTeXt Page Macros / Page Streams}
+
+\registerctxluafile{page-str}{1.001}
+
+\unprotect
+
+\let \currentoutputstream \empty
+\newif \ifinoutputstream
+\newtoks \everyenableoutputstream
+
+\appendtoks
+ \flushsidefloats
+\to \everyenableoutputstream
+
+\def\initializeoutputstreams
+ {\ctxlua{streams.initialize()}%
+ \glet\initializeoutputstreams\relax}
+
+\def\enableoutputstream[#1]%
+ {\initializeoutputstreams
+ \the\everyenableoutputstream
+ \inoutputstreamtrue
+ \xdef\currentoutputstream{#1}%
+ \ctxlua{streams.enable("#1")}}
+
+\def\disableoutputstream
+ {\inoutputstreamfalse
+ \global\let\currentoutputstream\s!default
+ \ctxlua{streams.disable()}}
+
+\unexpanded\def\startoutputstream[#1]%
+ {\begingroup
+ \initializeoutputstreams
+ \the\everyenableoutputstream
+ \inoutputstreamtrue
+ \xdef\currentoutputstream{#1}%
+ \ctxlua{streams.start("#1")}}
+
+\unexpanded\def\stopoutputstream
+ {\ctxlua{streams.stop()}%
+ \endgroup}
+
+\def\flushoutputstream [#1]{\ctxlua{streams.flush("#1")}}
+\def\outputstreamcopy [#1]{\vbox{\ctxlua{streams.flush("#1",true)}}}
+\def\outputstreambox [#1]{\vbox{\ctxlua{streams.flush("#1")}}}
+\def\outputstreamunvcopy[#1]{\ctxlua{streams.flush("#1",true)}}
+\def\outputstreamunvbox [#1]{\ctxlua{streams.flush("#1")}}
+\def\synchronizestreams [#1]{\ctxlua{streams.synchronize("#1")}}
+\def\dopushoutputstream [#1]{\ctxlua{streams.push("#1")}}
+
+\def\pushoutputstream {\dosingleempty\dopushoutputstream}
+
+% \unexpanded\def\defineoutputstream[#1]%
+% {\doifundefined{otrs:#1}{\expandafter\newbox\csname otrs:#1\endcsname}}
+%
+% \def\useoutputstream[#1]%
+% {\writestatus{otr}{using output stream #1}%
+% \xdef\currentoutputstream{#1}}
+%
+% \directsetup{stream:\firstoutputstream:set}
+% \directsetup{stream:\firstoutputstream:top}
+% \directsetup{stream:\firstoutputstream:bottom}
+% \directsetup{stream:\firstoutputstream:reset}
+
+%D Obsolete in \MKIV:
+
+\unexpanded\def\definemarknote {\dodoubleempty\dodefinemarknote}
+\def\dodefinemarknote[#1][#2]{}
+\def\setmarknote [#1]{\gobbleoneargument}
+\def\flushmarknotes [#1]{}
+\def\erasemarknotes [#1]{}
+
+\protect \endinput
+
+% \enabletrackers[streams.flushing]
+%
+% \setuplayout[grid=yes] \showgrid
+%
+% \starttext
+%
+% \input tufte
+%
+% \startoutputstream[nl]
+%
+% Wat doen we hier?
+%
+% \enableoutputstream[en]
+%
+% Are you sleeping, brother John?\footnote{xxx}
+%
+% \dorecurse{4}{x \footnote{note \recurselevel}\input tufte \par \pushoutputstream}
+%
+% \enableoutputstream[de]
+%
+% Bruder Jakob, schläfst du noch?\footnote{yyy}
+%
+% \dorecurse{4}{x \footnote{note \recurselevel}\input ward \par \pushoutputstream}
+%
+% \disableoutputstream
+%
+% \stopoutputstream
+%
+% Vader Jacob, slaap je nog?\footnote{zzz}
+%
+% \input tufte
+%
+% \synchronizestreams[en,de,nl]
+%
+% \page \flushoutputstream[en] \input knuth
+% \page \flushoutputstream[de] \input knuth
+% \page \flushoutputstream[nl] \input knuth
+%
+% \stoptext
diff --git a/tex/context/base/page-txt.mkii b/tex/context/base/page-txt.mkii
new file mode 100644
index 000000000..9fe73bec1
--- /dev/null
+++ b/tex/context/base/page-txt.mkii
@@ -0,0 +1,784 @@
+%D \module
+%D [ file=page-txt, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Texts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% \setuplayouttext in manual
+
+\writestatus{loading}{ConTeXt Page Macros / Texts}
+
+\unprotect
+
+\let\dodummypageskip\gobbleoneargument % obsolete
+
+%D Interfacing between this and other modules is handled by
+%D the following macros. The current state of a text line
+%D (header, footer, etc.) is checked by:
+%D
+%D \starttyping
+%D \resetlayouttextlines
+%D \stoptyping
+%D
+%D The main text box is finished by the following macro:
+%D
+%D \starttyping
+%D \getmainbox <\vbox|\unvbox>
+%D \stoptyping
+%D
+%D The text lines are collected with:
+%D
+%D \starttyping
+%D \gettextboxes
+%D \stoptyping
+%D
+%D It is possible to extens the default content of the text
+%D areas by appending content to the following token list
+%D registers:
+
+\newtoks\toptextcontent \newtoks\leftedgetextcontent
+\newtoks\headertextcontent \newtoks\leftmargintextcontent
+\newtoks\footertextcontent \newtoks\rightmargintextcontent
+\newtoks\bottomtextcontent \newtoks\rightedgetextcontent
+
+\newtoks\texttextcontent
+
+%D \macros
+%D {setuptop, setupheader, setuptext,
+%D setupfooter, setupbottom}
+%D
+%D The macros in this module sometimes look a bit more complicated
+%D than needed, which is a direct result of the fact that their
+%D ancestors are quite old and upward compatibility is a must.
+%D
+%D \showsetup{setuptop}
+%D \showsetup{setupheader}
+%D \showsetup{setuptext}
+%D \showsetup{setupfooter}
+%D \showsetup{setupbottom}
+
+\def\setuplayouttext
+ {\dotripleempty\dosetuplayouttext}
+
+\def\dosetuplayouttext[#1][#2][#3]% beware, non global
+ {\ifthirdargument
+ \getparameters[\??tk#1#2][#3]%
+ \else
+ %\getparameters[\??tk#1\v!text][#2]%
+ \edef\previoustextstate{\getvalue{\??tk#1\c!state}}%
+ \getparameters[\??tk#1][#2]%
+ \doifnotvalue{\??tk#1\c!state}\previoustextstate
+ {%\checkcurrentlayout % no
+ \edef\currenttextstate{\getvalue{\??tk#1\c!state}}%
+ % speed optimization (calculating backgrounds takes time)
+ \doifcommon{\previoustextstate,\currenttextstate}{\v!high,\v!none}
+ {\calculatevsizes
+ \recalculatebackgrounds
+ \recalculatelogos}}%
+ \fi}
+
+\def\setuptop {\dotripleempty\dosetuplayouttext[\v!top]}
+\def\setupheader {\dotripleempty\dosetuplayouttext[\v!header]}
+\def\setuptext {\dotripleempty\dosetuplayouttext[\v!text]}
+\def\setupfooter {\dotripleempty\dosetuplayouttext[\v!footer]}
+\def\setupbottom {\dotripleempty\dosetuplayouttext[\v!bottom]}
+
+%D \macros
+%D {noheaderandfooterlines,notopandbottomlines}
+%D
+%D Although not really needed, the following shortcuts
+%D sometimes come in handy.
+%D
+%D \showsetup{noheaderandfooterlines}
+%D \showsetup{notopandbottomlines}
+
+\def\noheaderandfooterlines
+ {\setupheader[\c!state=\v!empty]%
+ \setupfooter[\c!state=\v!empty]}
+
+\def\notopandbottomlines
+ {\setuptop [\c!state=\v!empty]%
+ \setupbottom[\c!state=\v!empty]}
+
+%D \macros
+%D {setuptoptexts, setupheadertexts, setuptexttexts,
+%D setupfootertexts, setupbottomtexts}
+%D
+%D The next macros take one or more arguments. The exact setup
+%D depends on the number of arguments. Although not that
+%D intuitive, the current scheme evolved out of the original.
+%D When margin and edge texts as well as middle texts showed
+%D up, the current odd|/|even scheme surfaced.
+%D
+%D \showsetup{setuptoptexts}
+%D \showsetup{setupheadertexts}
+%D \showsetup{setuptexttexts}
+%D \showsetup{setupfootertexts}
+%D \showsetup{setupbottomtexts}
+
+\def\setuptoptexts {\dosixtupleempty\dosetuptexts[\v!top]}
+\def\setupheadertexts {\dosixtupleempty\dosetuptexts[\v!header]}
+\def\setuptexttexts {\dosixtupleempty\dosetuptexts[\v!text]}
+\def\setupfootertexts {\dosixtupleempty\dosetuptexts[\v!footer ]}
+\def\setupbottomtexts {\dosixtupleempty\dosetuptexts[\v!bottom]}
+
+%D The left, right and center variables can also be set
+%D directly using the previously discussed macros.
+
+\def\dosetuptexts[#1][#2][#3][#4][#5][#6]%
+ {\ifsixthargument
+ \setvalue{\??tk#1#2\c!lefttext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#3}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#6}}%
+ \setvalue{\??tk#1#2\c!righttext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#5}}%
+ \else\iffifthargument
+ \setvalue{\??tk#1\v!text\c!lefttext}%
+ {\dodoubletexts{\??tk#1}\v!text
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#2}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#5}}%
+ \setvalue{\??tk#1\v!text\c!righttext}%
+ {\dodoubletexts{\??tk#1}\v!text
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}}%
+ \else\iffourthargument
+ \setvalue{\??tk#1#2\c!lefttext}%
+ {\dodoubletexts{\??tk#1}{#2}
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#3}%
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#3}}%
+ \setvalue{\??tk#1#2\c!righttext}%
+ {\dodoubletexts{\??tk#1}{#2}
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}}%
+ \else\ifthirdargument
+ \setvalue{\??tk#1\v!text\c!lefttext}%
+ {\dodoubletexts{\??tk#1}\v!text
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#2}%
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#2}}%
+ \setvalue{\??tk#1\v!text\c!righttext}%
+ {\dodoubletexts{\??tk#1}\v!text
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}}%
+ \else\ifsecondargument % new
+ \letvalue{\??tk#1\v!text\c!lefttext }\empty
+ \letvalue{\??tk#1\v!text\c!righttext}\empty
+ \setvalue{\??tk#1\v!text\c!middletext }%
+ {\dosingletexts{\??tk#1}\v!text\c!style\c!color\c!width{#2}}%
+ \else
+ \dosixtupleempty\dosetuptexts[#1][\v!text][][][][]%
+ \dosixtupleempty\dosetuptexts[#1][\v!margin][][][][]%
+ \dosixtupleempty\dosetuptexts[#1][\v!edge ][][][][]%
+ \fi\fi\fi\fi\fi}
+
+%D Left and right texts are swapped on odd and even pages, but
+%D only when double sided typesetting is enabled.
+
+\def\dodoubletexts#1#2#3#4#5#6%
+ {\doifoddpageelse
+ {\dosingletexts{#1}{#2}#3{#4}} % #3 => provides three arguments
+ {\dosingletexts{#1}{#2}#5{#6}}} % #5 => provides three arguments
+
+%D The next macro will be cleaned up amd made less messy and
+%D dependent.
+
+\def\placetextlinestrut#1%
+ {\doifvalue{#1\c!strut}\v!yes{\setstrut\strut}}
+
+\def\dosingletexts#1#2#3#4#5#6%
+ {\bgroup
+ \defconvertedargument\ascii{#6}%
+ \doifsomething\ascii
+ {\doattributes{#1#2}#3#4%
+ {\placetextlinestrut{#1}% here !
+ %\doifdefinedelse{\??mk\ascii\c!coupling} % brrr
+ \doifelsemarking\ascii
+ {\dolimitatetexts{#1#2#5}{\getmarking[\ascii][\v!first]}}
+ {\ConvertConstantAfter\doifelse\v!pagenumber{#6}
+ \@@plaatspaginanummer
+ {\ConvertConstantAfter\doifelse\v!date{#6}
+ {\currentdate}
+ {% #6{}{}{} -> {} needed for macros that look
+ % ahead, like \uniqueMPgraphic
+ \opeenregel\dolimitatetexts{#1#2#5}{#6{}{}{}}}}}}}%
+ \egroup}
+
+%D When specified, the texts are automatically limited in
+%D length.
+
+\def\dolimitatetexts#1#2%
+ {\doifelsevaluenothing{#1}{#2}{\limitatetext{#2}{\getvalue{#1}}{\unknown}}}
+
+%D The placement of text is hooked into the token lists
+%D associated to the area at hand.
+
+\appendtoks \placelayouttextline\v!top \topheight \to \toptextcontent
+\appendtoks \placelayouttextline\v!header\headerheight \to \headertextcontent
+\appendtoks \placelayouttextline\v!text \textheight \to \texttextcontent
+\appendtoks \placelayouttextline\v!footer\footerheight \to \footertextcontent
+\appendtoks \placelayouttextline\v!bottom\bottomheight \to \bottomtextcontent
+
+%D Texts can be disabled, moved up and ignored, depending in
+%D the \type {status} variable. This is handled by the next
+%D couple of macros.
+
+\def\settextlinestatus #1{\edef\textlinestatus{\csname\??tk#1\c!state\endcsname}}
+%def\resettextlinestatus#1{\letgvalue{\??tk#1\c!state}\v!normal}
+
+\def\resettextlinestatus#1% postpone
+ {\setgvalue{\??tk#1\s!reset}{\letgvalue{\??tk#1\c!state}\v!normal}}
+
+\def\placelayouttextline#1% #2
+ {\settextlinestatus{#1}%
+ \csname\string\placelayouttextline
+ \ifundefined{\string\placelayouttextline\textlinestatus}%
+ \s!unknown
+ \else
+ \textlinestatus
+ \fi
+ \endcsname{#1}} % {#2}
+
+\def\doifelselayouttextline#1% shown or not
+ {\doifinsetelse{\getvalue{\??tk#1\c!state}}{\v!normal,\v!start}}
+
+\def\doifelselayoutsomeline#1% present or not
+ {\edef\!!stringa{\csname\??tk#1\c!state\endcsname}%
+ \ifx\!!stringa\v!none
+ \@EA\secondoftwoarguments
+ \else\ifx\!!stringa\v!high
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi\fi}
+
+% \doplacelayouttextline does the actual placement (when a non-zero height)
+
+\newconditional\resyncaftertextline
+
+\setvalue{\string\placelayouttextline\v!normal }{\doplacelayouttextline}
+\setvalue{\string\placelayouttextline }{\doplacelayouttextline}
+
+\setvalue{\string\placelayouttextline\v!none}#1#2%
+ {}
+
+\setvalue{\string\placelayouttextline\v!high}#1#2%
+ {\global\settrue\resyncaftertextline
+ \resettextlinestatus{#1}}
+
+\setvalue{\string\placelayouttextline\v!empty}#1#2%
+ {\resettextlinestatus{#1}}
+
+\setvalue{\string\placelayouttextline\v!start}#1#2%
+ {\resettextlinestatus{#1}%
+ \doplacelayouttextline{#1}{#2}}
+
+\setvalue{\string\placelayouttextline\v!stop}#1#2%
+ {}
+
+\setvalue{\string\placelayouttextline\v!nomarking}#1#2%
+ {\bgroup
+ \resettextlinestatus{#1}%
+ \let\dogetmarking\nogetmarking
+ \doplacelayouttextline{#1}{#2}%
+ \egroup}
+
+\setvalue{\string\placelayouttextline\s!unknown}#1#2%
+ {\global\settrue\resyncaftertextline
+ \bgroup % new
+ \resettextlinestatus{#1}%
+ \getvalue{\??tk#1\textlinestatus}%
+ \getvalue{\??tk#1\v!text \textlinestatus}%
+ \getvalue{\??tk#1\v!margin\textlinestatus}%
+ \getvalue{\??tk#1\v!edge \textlinestatus}%
+ \doplacelayouttextline{#1}{#2}%
+ \egroup}
+
+%D The following macro has to be called after a page
+%D is flushed.
+
+\def\resetlayouttextline#1%
+ {\getvalue {\??tk#1\s!reset}%
+ \letgvalue{\??tk#1\s!reset}\relax}
+
+\def\resetlayouttextlines
+ {\resetlayouttextline\v!top
+ \resetlayouttextline\v!header
+ \resetlayouttextline\v!text
+ \resetlayouttextline\v!footer
+ \resetlayouttextline\v!bottom
+ \ifconditional\resyncaftertextline
+ \doglobal\calculatevsizes
+ \recalculatebackgrounds
+ \recalculatelogos
+ \global\setfalse\resyncaftertextline
+ \fi}
+
+% \settext[header][text][middle][xxx][yyy]
+
+\def\settextcontent
+ {\doquintupleempty\dosettextcontent}
+
+\def\dosettextcontent[#1][#2][#3][#4][#5]% header text middle text/text
+ {\iffifthargument
+ \setvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#5}}%
+ \else\iffourthargument
+ \setvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}}%
+ \else\ifthirdargument
+ \setvalue{\??tk#1#2\c!middletext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#3}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}}%
+ \fi\fi\fi}
+
+\def\resettextcontent
+ {\dotripleempty\doresettextcontent}
+
+\def\doresettextcontent[#1][#2][#3]% header text middle
+ {\ifthirdargument
+ \letvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}\empty
+ \else\ifsecondargument
+ \letvalue{\??tk#1#2\c!lefttext }\empty
+ \letvalue{\??tk#1#2\c!middletext}\empty
+ \letvalue{\??tk#1#2\c!righttext }\empty
+ \fi\fi}
+
+\let\settext \settextcontent % downward compatibility
+\let\resettext\resettextcontent % downward compatibility
+
+\setvalue{:\c!middle:\c!text:}{\c!middletext}
+\setvalue{:\c!left :\c!text:}{\c!lefttext }
+\setvalue{:\c!right :\c!text:}{\c!righttext }
+
+%D The next series of macros is not that easy to read,
+%D because they hook into the main page building macros. By
+%D using token list registers for the text content, we can
+%D easily hook in other code, like menu generators.
+%D
+%D Beware: the token lists are always expanded, also when the
+%D height of an area is zero. This is because reset actions can
+%D be part of them.
+
+\newbox\scratchpagebox
+
+\def\gettextboxes
+ {\setbox\scratchpagebox\vbox
+ {\dontcomplain
+ \calculatereducedvsizes
+ \swapmargins
+ \offinterlineskip
+ \vskip\dimexpr-\topheight-\topdistance\relax
+ \the\toptextcontent
+ \vskip\dimexpr\topheight+\topdistance\relax
+ \the\headertextcontent
+ \vskip\dimexpr\headerheight+\headerdistance\relax
+ \placepositionanchors
+ \vskip-\textheight
+ \the\texttextcontent
+ \vskip\textheight
+ \the\everyendoftextbody
+ \vskip\footerdistance
+ \the\footertextcontent
+ \vskip\dimexpr\footerheight+\bottomdistance\relax
+ \the\bottomtextcontent
+ \vskip\bottomheight
+ \vfilll}%
+ \smashbox\scratchpagebox
+ \box\scratchpagebox}
+
+\def\getmainbox#1#2%
+ {\setbox\scratchpagebox\vbox
+ {\offinterlineskip % na \paginaletter !
+ \calculatereducedvsizes
+ \calculatehsizes
+ \swapmargins
+ \vskip\dimexpr\headerheight+\headerdistance+\layoutparameter\c!textdistance\relax
+ \hbox to \makeupwidth
+ {\bgroup
+ \swapmargins
+ \goleftonpage
+ \ifdim\leftedgewidth>\zeropoint
+ \the\leftedgetextcontent
+ \hskip\leftedgewidth
+ \fi
+ \hskip\leftedgedistance
+ \ifdim\leftmarginwidth>\zeropoint
+ \the\leftmargintextcontent
+ \hskip\leftmarginwidth
+ \fi
+ \hskip\leftmargindistance
+ \egroup
+ \mkprocesspagecontents{#2}%
+ \settextpagecontent\scratchpagebox{#1}{#2}%
+ \setbox\scratchpagebox\vbox % can we avoid this extra box
+ {\startlayoutcomponent{textbody}{text body}%
+ \box\scratchpagebox
+ \stoplayoutcomponent}%
+ \addtextbackground\scratchpagebox
+ \addtextgridlayer\scratchpagebox
+ \localstarttextcolor % does not work in mkiv
+ \box\scratchpagebox
+ \localstoptextcolor % so we have to change this
+ \bgroup
+ \hskip\rightmargindistance
+ \ifdim\rightmarginwidth>\zeropoint
+ \the\rightmargintextcontent
+ \hskip\rightmarginwidth
+ \fi
+ \hskip\rightedgedistance
+ \ifdim\rightedgewidth>\zeropoint
+ \the\rightedgetextcontent
+ \hskip\rightedgewidth
+ \fi
+ \egroup
+ \hss}}%
+ \smashbox\scratchpagebox
+ \box\scratchpagebox}
+
+%D The main text area has to be combined with some additional
+%D (tracing) information.
+
+% will be overloaded in page-lyr
+
+\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+ {\setbox#1\hbox to \makeupwidth
+ {\hss % so don't change this
+ \vbox to \textheight
+ {\offinterlineskip
+ \freezetextwidth
+ \hsize\textwidth % local variant of \sethsize
+ \boxmaxdepth\maxdepth
+ \noindent % content can be < \hsize
+ \dopagecontents#2#3}%
+ \hss}%
+ \dp#1\zeropoint}
+
+\definepalet
+ [layout]
+ [grid=red,
+ page=green]
+
+\def\addtextgridlayer#1% tzt run time
+ {\ifcase\showgridstate\else % 1=bottom 2=top
+ \setgridbox\scratchbox\makeupwidth\textheight
+ \setbox#1\hbox
+ {\ifcase\showgridstate\or\or\box#1\hskip-\makeupwidth\fi
+ \bgroup % color
+ \startlayoutcomponent{gridcolumns}{grid columns}%
+ \incolortrue
+ \ifcase\layoutcolumns\else
+ \gray
+ \hbox to \makeupwidth
+ {\dorecurse\layoutcolumns
+ {\hskip\layoutcolumnwidth
+ \ifnum\recurselevel<\layoutcolumns
+ \vrule
+ \!!height\ht\scratchbox
+ \!!depth\dp\scratchbox
+ \!!width\layoutcolumndistance
+ \fi}}%
+ \hskip-\makeupwidth
+ \fi
+ \stoplayoutcomponent
+ \startlayoutcomponent{gridlines}{grid lines}%
+ \startcolor[layout:grid]\box\scratchbox\stopcolor
+ \stoplayoutcomponent
+ \egroup
+ \ifcase\showgridstate\or\hskip-\makeupwidth\box#1\fi}%
+ \fi}
+
+%D The placement of a whole line is handled by the next two
+%D macros. These are hooked into the general purpose token
+%D list registers mentioned before.
+
+\def\ignoredlinebreak{\unskip\space\ignorespaces}
+
+\def\doplacelayouttextline#1#2%
+ {\ifdim#2>\zeropoint\relax % prevents pagenumbers when zero height
+ \goleftonpage
+ \hbox
+ {\setbox\scratchpagebox\vbox to #2
+ {%\forgetall
+ \vsize#2\relax
+ \normalbaselines
+ \let\\\ignoredlinebreak
+ \let\crlf\ignoredlinebreak
+ %\getvalue{\??tk#1\v!text\c!before}%
+ \getvalue{\??tk#1\c!before}%
+ \doifbothsidesoverruled
+ {\dodoplacelayouttextline#1\c!lefttext \c!middletext\c!righttext\gobbleoneargument\getvalue}
+ {\dodoplacelayouttextline#1\c!lefttext \c!middletext\c!righttext\gobbleoneargument\getvalue}
+ {\dodoplacelayouttextline#1\c!righttext\c!middletext\c!lefttext \getvalue\gobbleoneargument}%
+ %\getvalue{\??tk#1\v!text\c!after}%
+ \getvalue{\??tk#1\c!after}%
+ \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
+ \dp\scratchpagebox\zeropoint
+ \box\scratchpagebox}%
+ \vskip-#2\relax
+ \fi}
+
+\def\dodoplacelayouttextline#1#2#3#4#5#6% \hsize toegevoegd, \hss's niet meer wijzigen
+ {\hbox
+ {\ifdim\leftedgewidth>\zeropoint
+ \dododoplacelayouttextline\leftedgewidth{#1}\v!edge
+ {\hss\getvalue{\??tk#1\v!edge#2}}%
+ \hskip\leftedgedistance
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ \dododoplacelayouttextline\leftmarginwidth{#1}\v!margin
+ {\hbox to \leftmarginwidth
+ {\hss\getvalue{\??tk#1\v!margin#2}}%
+ \hskip-\leftmarginwidth
+ \hbox to \leftmarginwidth
+ {\hss#5{\??tk#1\v!margin\c!margintext}}}%
+ \hskip\leftmargindistance
+ \fi
+ \ifdim\makeupwidth>\zeropoint
+ \dododoplacelayouttextline\makeupwidth{#1}\v!text
+ {\hbox to \makeupwidth
+ {\@@nmpre{#5{\??tk#1\v!text\c!marginedgetext}}%
+ \getvalue{\??tk#1\v!text#2}\hss}%
+ \hskip-\makeupwidth
+ \hbox to \makeupwidth
+ {\hss\getvalue{\??tk#1\v!text#3}\hss}%
+ \hskip-\makeupwidth
+ \hbox to \makeupwidth
+ {\hss\getvalue{\??tk#1\v!text#4}%
+ \@@nmpos{#6{\??tk#1\v!text\c!marginedgetext}}}}%
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ \hskip\rightmargindistance
+ \dododoplacelayouttextline\rightmarginwidth{#1}\v!margin
+ {\hbox to \rightmarginwidth
+ {\getvalue{\??tk#1\v!margin#4}\hss}%
+ \hskip-\rightmarginwidth
+ \hbox to \rightmarginwidth
+ {#6{\??tk#1\v!margin\c!margintext}\hss}}%
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ \hskip\rightedgedistance
+ \dododoplacelayouttextline\rightedgewidth{#1}\v!edge
+ {\getvalue{\??tk#1\v!edge#4}\hss}%
+ \fi}}
+
+% \def\dododoplacelayouttextline#1#2#3#4%
+% {\vbox % to \vsize
+% {\hsize#1\relax
+% \getvalue{\??tk#2#3\c!voor}
+% \hbox to #1{#4}%
+% \getvalue{\??tk#2#3\c!na}}}
+
+\def\dododoplacelayouttextline#1#2#3#4%
+ {\vbox % to \vsize
+ {\hsize#1\relax
+ \getvalue{\??tk#2#3\c!before}%
+ \startlayoutcomponent{t:#2:#3}{area #2 #3}%
+ \hbox to #1{#4}%
+ \stoplayoutcomponent
+ \getvalue{\??tk#2#3\c!after}}}
+
+%D Although it is far better to use backgrounds for this
+%D purpose, one can add a rule in the following way. This
+%D method makes the rules disappear in case of an empty text
+%D line. Consider this a feature.
+%D
+%D \starttyping
+%D \setupheadertexts[left][right]
+%D
+%D \setupheader[text][after=\hrule,style=bold]
+%D
+%D \starttext
+%D \input tufte \page
+%D \setupheader[state=empty]
+%D \input tufte \page
+%D \stoptext
+%D \stoptyping
+
+%D The next twosome will be done differently (using an
+%D existing auxiliary macro).
+
+% \def\@@nmpre#1{\setbox0\hbox{#1}\ifdim\wd0=\zeropoint\else\unhbox0\tfskip\fi}
+% \def\@@nmpos#1{\setbox0\hbox{#1}\ifdim\wd0=\zeropoint\else\tfskip\unhbox0\fi}
+
+% cleaner
+
+\def\@@nmpre#1{\doiftext{#1}{{#1}\tfskip}}
+\def\@@nmpos#1{\doiftext{#1}{\tfskip{#1}}}
+
+% newer
+
+\def\@@nmprepos#1#2#3#4#5%
+ {\doifelsenothing\@@nmwidth
+ {\doiftext{#5}{#1{#5}#2}}
+ {\doiftext{#5}{\hbox to \@@nmwidth{#3{#5}#4}}}}
+
+\def\@@nmpre{\@@nmprepos\empty\tfskip\relax\hss}
+\def\@@nmpos{\@@nmprepos\tfskip\empty\hss\relax}
+
+%D This code will move to \type {page-flt.tex}.
+
+\appendtoks
+ \plaatsrechtermargeblok \hskip-\rightmarginwidth
+\to \rightmargintextcontent
+
+\appendtoks
+ \plaatslinkermargeblok \hskip-\leftmarginwidth
+\to \leftmargintextcontent
+
+%D The next hook will later be used for keeping track of
+%D positions, i.e.\ it will provide a proper (page
+%D dependent) reference point.
+
+\ifx\undefined\placepositionanchors
+ \def\placepositionanchors{\vskip\textheight}
+\fi
+
+%D \macros
+%D {definetext}
+%D
+%D Some macros ago, we implemented the \type {status} option
+%D \type {unknown}. This one is used to take care of
+%D symbolic texts handlers.
+%D
+%D \showsetup{definetext}
+%D
+%D The next example demonstrates how we can use this
+%D mechanism to provide page (event) dependent text lines.
+%D
+%D \starttyping
+%D \definetext[chapter][footer][pagenumber]
+%D \setuphead[chapter][header=high,footer=chapter]
+%D \setupheadertexts[pagenumber]
+%D \setupfootertexts[left][right]
+%D \chapter{eerste} \dorecurse{20}{\input tufte \relax}
+%D \chapter{tweede} \dorecurse{20}{\input tufte \relax}
+%D \stoptyping
+
+\def\definetext
+ {\doseventupleempty\dodefinetext}
+
+\def\dodefinetext[#1][#2][#3][#4][#5][#6][#7]%
+ {\ifseventhargument
+ \setvalue{\??tk#2#3#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5][#6][#7]}%
+ \else\ifsixthargument
+ \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5][#6]}%
+ \else\iffifthargument
+ \setvalue{\??tk#2#3#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5]}%
+ \else\iffourthargument
+ \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4]}%
+ \else
+ \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3]}%
+ \fi\fi\fi\fi}
+
+%D The rest of this file is dedicated to setting up the
+%D texts. This code is not that impressive.
+
+\setupheadertexts [\v!text] [] []
+\setupheadertexts [\v!margin] [] []
+\setupheadertexts [\v!edge] [] []
+
+\setupfootertexts [\v!text] [] []
+\setupfootertexts [\v!margin] [] []
+\setupfootertexts [\v!edge] [] []
+
+\setuptexttexts [\v!text] [] []
+\setuptexttexts [\v!margin] [] []
+\setuptexttexts [\v!edge] [] []
+
+\setupbottomtexts [\v!text] [] []
+\setupbottomtexts [\v!margin] [] []
+\setupbottomtexts [\v!edge] [] []
+
+\setuptoptexts [\v!text] [] []
+\setuptoptexts [\v!margin] [] []
+\setuptoptexts [\v!edge] [] []
+
+% alternative
+%
+% \def\resetlayouttekst%
+% {\dodoubleempty\doresetlayouttekst}
+%
+% \def\doresetlayouttekst[#1][#2]%
+% {\ifsecondargument
+% \dodoresetlayouttekst[#1][#2]%
+% \else
+% \dodoresetlayouttekst[#1][\v!tekst]%
+% \fi}
+%
+% \def\dodoresetlayouttekst[#1][#2]%
+% {...}
+%
+% \def\docommand#1%
+% {\resetlayouttekst[#1][\v!tekst]%
+% \resetlayouttekst[#1][\v!marge]%
+% \resetlayouttekst[#1][\v!rand]}
+
+%D We combine a lot of similar settings in a macro that
+%D we will later dispose.
+
+\def\dodocommand[#1][#2]%
+ {\getparameters
+ [\??tk#1#2]
+ [%\c!state=\v!normal, % moved
+ \c!before=, % both global and local are used
+ \c!after=, % both global and local are used
+ \c!strut=, % the local one, not (yet) used
+ \c!style=\getvalue{\??tk#1\c!style},% hm, got lost
+ \c!color=\getvalue{\??tk#1\c!color}, % hm, got lost
+ \c!lefttext=,
+ \c!middletext=,
+ \c!righttext=,
+ \c!marginedgetext=,
+ \c!margintext=,
+ \c!width=]%
+ \inheritparameter[\??tk#1#2][\c!leftstyle ][\c!style ]%
+ \inheritparameter[\??tk#1#2][\c!rightstyle ][\c!style ]%
+ \inheritparameter[\??tk#1#2][\c!leftcolor ][\c!color ]%
+ \inheritparameter[\??tk#1#2][\c!rightcolor ][\c!color ]%
+ \inheritparameter[\??tk#1#2][\c!leftwidth ][\c!width]%
+ \inheritparameter[\??tk#1#2][\c!rightwidth][\c!width]}
+
+\def\docommand#1%
+ {\dodocommand[#1][\v!text]%
+ \dodocommand[#1][\v!margin]%
+ \dodocommand[#1][\v!edge]}
+
+\docommand\v!top
+\docommand\v!header
+\docommand\v!footer
+\docommand\v!text
+\docommand\v!bottom
+
+\let\docommand \relax
+\let\dodocommand\relax
+
+%D While the header and footer lines are moved away from the
+%D main text, the top and bottom lines are centered.
+
+\setuptop [\c!state=\v!normal,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setupheader[\c!state=\v!normal,\c!before=, \c!after=\vss,\c!strut=\v!yes]
+\setuptext [\c!state=\v!normal,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setupfooter[\c!state=\v!normal,\c!before=\vss,\c!after=, \c!strut=\v!yes]
+\setupbottom[\c!state=\v!normal,\c!before=\vss,\c!after=\vss,\c!strut=]
+
+\setuptop [\c!style=,\c!color=]
+\setupheader[\c!style=,\c!color=]
+\setuptext [\c!style=,\c!color=]
+\setupfooter[\c!style=,\c!color=]
+\setupbottom[\c!style=,\c!color=]
+
+\protect \endinput
diff --git a/tex/context/base/page-txt.mkiv b/tex/context/base/page-txt.mkiv
new file mode 100644
index 000000000..bdc7c1bb6
--- /dev/null
+++ b/tex/context/base/page-txt.mkiv
@@ -0,0 +1,850 @@
+%D \module
+%D [ file=page-txt, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Texts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% where we can do some mkiv cleanup
+
+% \setuplayouttext in manual
+
+\writestatus{loading}{ConTeXt Page Macros / Texts}
+
+\unprotect
+
+%D Interfacing between this and other modules is handled by
+%D the following macros. The current state of a text line
+%D (header, footer, etc.) is checked by:
+%D
+%D \starttyping
+%D \resetlayouttextlines
+%D \stoptyping
+%D
+%D The main text box is finished by the following macro:
+%D
+%D \starttyping
+%D \getmainbox <\vbox|\unvbox>
+%D \stoptyping
+%D
+%D The text lines are collected with:
+%D
+%D \starttyping
+%D \gettextboxes
+%D \stoptyping
+%D
+%D It is possible to extens the default content of the text
+%D areas by appending content to the following token list
+%D registers:
+
+\newtoks\toptextcontent \newtoks\leftedgetextcontent
+\newtoks\headertextcontent \newtoks\leftmargintextcontent
+\newtoks\footertextcontent \newtoks\rightmargintextcontent
+\newtoks\bottomtextcontent \newtoks\rightedgetextcontent
+
+\newtoks\texttextcontent
+
+%D \macros
+%D {setuptop, setupheader, setuptext,
+%D setupfooter, setupbottom}
+%D
+%D The macros in this module sometimes look a bit more complicated
+%D than needed, which is a direct result of the fact that their
+%D ancestors are quite old and upward compatibility is a must.
+%D
+%D \showsetup{setuptop}
+%D \showsetup{setupheader}
+%D \showsetup{setuptext}
+%D \showsetup{setupfooter}
+%D \showsetup{setupbottom}
+
+\unexpanded\def\setuplayouttext
+ {\dotripleempty\dosetuplayouttext}
+
+\def\dosetuplayouttext[#1][#2][#3]% beware, non global
+ {\ifthirdargument
+ \getparameters[\??tk#1#2][#3]%
+ \else
+ %\getparameters[\??tk#1\v!text][#2]%
+ \edef\previoustextstate{\csname\??tk#1\c!state\endcsname}%
+ \getparameters[\??tk#1][#2]%
+ \edef\currenttextstate{\csname\??tk#1\c!state\endcsname}%
+ \ifx\currenttextstate\previoustextstate
+ % no change in state
+ \else
+ %\checkcurrentlayout % no
+ % speed optimization (calculating backgrounds takes time)
+ \doifcommon{\previoustextstate,\currenttextstate}{\v!high,\v!none}
+ {\calculatevsizes
+ \recalculatebackgrounds}%
+ \fi
+ \fi}
+
+\unexpanded\def\setuptop {\dotripleempty\dosetuplayouttext[\v!top]}
+\unexpanded\def\setupheader {\dotripleempty\dosetuplayouttext[\v!header]}
+\unexpanded\def\setuptext {\dotripleempty\dosetuplayouttext[\v!text]}
+\unexpanded\def\setupfooter {\dotripleempty\dosetuplayouttext[\v!footer]}
+\unexpanded\def\setupbottom {\dotripleempty\dosetuplayouttext[\v!bottom]}
+
+%D \macros
+%D {noheaderandfooterlines,notopandbottomlines}
+%D
+%D Although not really needed, the following shortcuts
+%D sometimes come in handy.
+%D
+%D \showsetup{noheaderandfooterlines}
+%D \showsetup{notopandbottomlines}
+
+\def\noheaderandfooterlines
+ {\setupheader[\c!state=\v!empty]%
+ \setupfooter[\c!state=\v!empty]}
+
+\def\notopandbottomlines
+ {\setuptop [\c!state=\v!empty]%
+ \setupbottom[\c!state=\v!empty]}
+
+%D \macros
+%D {setuptoptexts, setupheadertexts, setuptexttexts,
+%D setupfootertexts, setupbottomtexts}
+%D
+%D The next macros take one or more arguments. The exact setup
+%D depends on the number of arguments. Although not that
+%D intuitive, the current scheme evolved out of the original.
+%D When margin and edge texts as well as middle texts showed
+%D up, the current odd|/|even scheme surfaced.
+%D
+%D \showsetup{setuptoptexts}
+%D \showsetup{setupheadertexts}
+%D \showsetup{setuptexttexts}
+%D \showsetup{setupfootertexts}
+%D \showsetup{setupbottomtexts}
+
+\unexpanded\def\setuptoptexts {\dosixtupleempty\dosetuptexts[\v!top ]}
+\unexpanded\def\setupheadertexts {\dosixtupleempty\dosetuptexts[\v!header ]}
+\unexpanded\def\setuptexttexts {\dosixtupleempty\dosetuptexts[\v!text ]}
+\unexpanded\def\setupfootertexts {\dosixtupleempty\dosetuptexts[\v!footer ]}
+\unexpanded\def\setupbottomtexts {\dosixtupleempty\dosetuptexts[\v!bottom ]}
+
+%D The left, right and center variables can also be set
+%D directly using the previously discussed macros.
+
+\def\dosetuptexts[#1][#2][#3][#4][#5][#6]%
+ {\ifsixthargument
+ \setvalue{\??tk#1#2\c!lefttext}%
+ {\dodoubletexts{#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#3}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#6}}%
+ \setvalue{\??tk#1#2\c!righttext}%
+ {\dodoubletexts{#1}{#2}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#5}}%
+ \else\iffifthargument
+ \setvalue{\??tk#1\v!text\c!lefttext}%
+ {\dodoubletexts{#1}\v!text
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#2}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#5}}%
+ \setvalue{\??tk#1\v!text\c!righttext}%
+ {\dodoubletexts{#1}\v!text
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}}%
+ \else\iffourthargument
+ \setvalue{\??tk#1#2\c!lefttext}%
+ {\dodoubletexts{#1}{#2}
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#3}%
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#3}}%
+ \setvalue{\??tk#1#2\c!righttext}%
+ {\dodoubletexts{#1}{#2}
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}}%
+ \else\ifthirdargument
+ \setvalue{\??tk#1\v!text\c!lefttext}%
+ {\dodoubletexts{#1}\v!text
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#2}%
+ {\c!leftstyle\c!leftcolor\c!leftwidth}{#2}}%
+ \setvalue{\??tk#1\v!text\c!righttext}%
+ {\dodoubletexts{#1}\v!text
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}}%
+ \else\ifsecondargument % new
+ \letvalue{\??tk#1\v!text\c!lefttext }\empty
+ \letvalue{\??tk#1\v!text\c!righttext }\empty
+ \setvalue{\??tk#1\v!text\c!middletext}{\dosingletexts{#1}\v!text\c!style\c!color\c!width{#2}}%
+ \else
+ \dosixtupleempty\dosetuptexts[#1][\v!text ][][][][]%
+ \dosixtupleempty\dosetuptexts[#1][\v!margin][][][][]%
+ \dosixtupleempty\dosetuptexts[#1][\v!edge ][][][][]%
+ \fi\fi\fi\fi\fi}
+
+%D Left and right texts are swapped on odd and even pages, but
+%D only when double sided typesetting is enabled.
+
+\def\dodoubletexts{\doifoddpageelse\dodoubletextsodd\dodoubletextseven}
+
+\def\dodoubletextsodd #1#2#3#4#5#6{\dosingletexts{#1}{#2}#3{#4}} % #3 => provides three arguments
+\def\dodoubletextseven#1#2#3#4#5#6{\dosingletexts{#1}{#2}#5{#6}} % #5 => provides three arguments
+
+%D The next macro will be cleaned up and made less messy and
+%D dependent.
+
+\unexpanded\def\placetextlinestrut#1%
+ {\doifvalue{#1\c!strut}\v!yes{\setstrut\strut}}
+
+\def\dosingletexts#1#2#3#4#5#6%
+ {\bgroup
+ \defconvertedargument\ascii{#6}% no longer \defconvertedargument, this also does not permit \v!pagenumber (i.e. v!)
+ \ifx\ascii\empty\else
+ \dostartattributes{\??tk#1#2}#3#4\empty
+ \placetextlinestrut{\??tk#1}% here !
+ \doifelsemarking\ascii
+ {\dolimitatetexts{\??tk#1#2#5}{\getmarking[\ascii][\v!first]}}%
+ {\ifcsname\??tk->\ascii\endcsname
+ \csname\??tk->\ascii\endcsname
+ \else
+ % #6{}{}{} -> {} needed for macros that look
+ % ahead, like \uniqueMPgraphic
+ \ignorecrlf\dolimitatetexts{\??tk#1#2#5}{#6{}{}{}}%
+ \fi}%
+ \dostopattributes
+ \fi
+ \egroup}
+
+\setvalue{\??tk->\v!pagenumber}{\placelocationpagenumber}
+\setvalue{\??tk->\v!date }{\currentdate}
+
+%D When specified, the texts are automatically limited in
+%D length.
+
+\def\dolimitatetexts#1#2%
+ {\doifelsevaluenothing{#1}{#2}{\limitatetext{#2}{\csname#1\endcsname}{\unknown}}}
+
+%D The placement of text is hooked into the token lists
+%D associated to the area at hand.
+
+\appendtoks \placelayouttextline\v!top \topheight \to \toptextcontent
+\appendtoks \placelayouttextline\v!header\headerheight \to \headertextcontent
+\appendtoks \placelayouttextline\v!text \textheight \to \texttextcontent
+\appendtoks \placelayouttextline\v!footer\footerheight \to \footertextcontent
+\appendtoks \placelayouttextline\v!bottom\bottomheight \to \bottomtextcontent
+
+%D Texts can be disabled, moved up and ignored, depending in
+%D the \type {status} variable. This is handled by the next
+%D couple of macros.
+
+% \def\settextlinestatus#1%
+% {\edef\textlinestatus{\csname\??tk#1\c!state\endcsname}}
+
+\def\settextlinestatus#1%
+ {\ifcase0\csname\??tk#1\c!n\endcsname\relax
+ \edef\textlinestatus{\csname\??tk#1\c!state\endcsname}%
+ \else
+ \setxvalue{\??tk#1\c!n}{\the\numexpr\csname\??tk#1\c!n\endcsname-1}%
+ \let\textlinestatus\v!stop
+ \fi}
+
+\appendtoks
+ \doifinset\v!header\floatspecification{\setxvalue{\??tk\v!header\c!n}{1}}%
+ \doifinset\v!footer\floatspecification{\setxvalue{\??tk\v!footer\c!n}{1}}%
+\to \everybeforeflushedpagefloat
+
+\def\resettextlinestatus#1% postpone
+ {\expandafter\gdef\csname\??tk#1\s!reset\endcsname{\global\expandafter\let\csname\??tk#1\c!state\endcsname\v!normal}}
+
+\unexpanded\def\placelayouttextline#1% #2
+ {\settextlinestatus#1%
+ \csname\??tk::\ifcsname\??tk::\textlinestatus\endcsname\textlinestatus\else\s!unknown\fi\endcsname#1} % {#2}
+
+\def\doifelselayouttextline#1% shown or not
+ {\edef\!!stringa{\csname\??tk#1\c!state\endcsname}%
+ \ifx\!!stringa\v!normal
+ \@EA\firstoftwoarguments
+ \else\ifx\!!stringa\v!start
+ \@EAEAEA\firstoftwoarguments
+ \else
+ \@EAEAEA\secondoftwoarguments
+ \fi\fi}
+
+\def\doifelselayoutsomeline#1% present or not
+ {\edef\!!stringa{\csname\??tk#1\c!state\endcsname}%
+ \ifx\!!stringa\v!none
+ \@EA\secondoftwoarguments
+ \else\ifx\!!stringa\v!high
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi\fi}
+
+% \doplacelayouttextline does the actual placement (when a non-zero height)
+
+\newconditional\resyncaftertextline
+
+% there is no need for {#1} etc since we use symbolic names
+
+\setvalue{\??tk::\v!normal}{\doplacelayouttextline}
+\setvalue{\??tk::\empty }{\doplacelayouttextline}
+
+\setvalue{\??tk::\v!none }#1#2{}
+\setvalue{\??tk::\v!stop }#1#2{}
+
+\setvalue{\??tk::\v!high}#1#2%
+ {\global\settrue\resyncaftertextline
+ \resettextlinestatus#1}
+
+\setvalue{\??tk::\v!empty}#1#2%
+ {\resettextlinestatus#1}
+
+\setvalue{\??tk::\v!start}#1#2%
+ {\resettextlinestatus#1%
+ \doplacelayouttextline#1#2}
+
+\setvalue{\??tk::\v!nomarking}#1#2%
+ {\bgroup
+ \resettextlinestatus#1%
+ \let\dogetmarking\nogetmarking
+ \doplacelayouttextline#1#2%
+ \egroup}
+
+\setvalue{\??tk::\s!unknown}#1#2%
+ {\global\settrue\resyncaftertextline
+ \bgroup % new
+ \resettextlinestatus#1%
+ \csname\??tk#1\textlinestatus\endcsname
+ \csname\??tk#1\v!text \textlinestatus\endcsname
+ \csname\??tk#1\v!margin\textlinestatus\endcsname
+ \csname\??tk#1\v!edge \textlinestatus\endcsname
+ \doplacelayouttextline#1#2%
+ \egroup}
+
+%D The following macro has to be called after a page
+%D is flushed.
+
+\def\resetlayouttextline#1%
+ {\csname\??tk#1\s!reset\endcsname
+ \global\expandafter\let\csname\??tk#1\s!reset\endcsname\relax}
+
+\def\resetlayouttextlines
+ {\resetlayouttextline\v!top
+ \resetlayouttextline\v!header
+ \resetlayouttextline\v!text
+ \resetlayouttextline\v!footer
+ \resetlayouttextline\v!bottom
+ \ifconditional\resyncaftertextline
+ \calculateglobalvsizes
+ \recalculatebackgrounds
+ \global\setfalse\resyncaftertextline
+ \fi}
+
+% \settext[header][text][middle][xxx][yyy]
+
+\def\settextcontent
+ {\doquintupleempty\dosettextcontent}
+
+\def\dosettextcontent[#1][#2][#3][#4][#5]% header text middle text/text
+ {\iffifthargument
+ \setvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#5}}%
+ \else\iffourthargument
+ \setvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}}%
+ \else\ifthirdargument
+ \setvalue{\??tk#1#2\c!middletext}%
+ {\dodoubletexts{\??tk#1}{#2}%
+ {\c!leftstyle \c!leftcolor \c!leftwidth }{#3}%
+ {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}}%
+ \fi\fi\fi}
+
+\def\resettextcontent
+ {\dotripleempty\doresettextcontent}
+
+\def\doresettextcontent[#1][#2][#3]% header text middle
+ {\ifthirdargument
+ \letvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}\empty
+ \else\ifsecondargument
+ \letvalue{\??tk#1#2\c!lefttext }\empty
+ \letvalue{\??tk#1#2\c!middletext}\empty
+ \letvalue{\??tk#1#2\c!righttext }\empty
+ \fi\fi}
+
+\let\settext \settextcontent % downward compatibility
+\let\resettext\resettextcontent % downward compatibility
+
+\setvalue{:\c!middle:\c!text:}{\c!middletext}
+\setvalue{:\c!left :\c!text:}{\c!lefttext }
+\setvalue{:\c!right :\c!text:}{\c!righttext }
+
+%D The next series of macros is not that easy to read,
+%D because they hook into the main page building macros. By
+%D using token list registers for the text content, we can
+%D easily hook in other code, like menu generators.
+%D
+%D Beware: the token lists are always expanded, also when the
+%D height of an area is zero. This is because reset actions can
+%D be part of them.
+
+\newbox\scratchpagebox
+
+\def\gettextboxes
+ {\setbox\scratchpagebox\vbox
+ {\dontcomplain
+ \calculatereducedvsizes
+ \swapmargins
+ \offinterlineskip
+ \vskip\dimexpr-\topheight-\topdistance\relax
+ \the\toptextcontent
+ \vskip\dimexpr\topheight+\topdistance\relax
+ \the\headertextcontent
+ \vskip\dimexpr\headerheight+\headerdistance\relax
+ \placepositionanchors
+ \vskip-\textheight
+ \the\texttextcontent
+ \vskip\textheight
+ \the\everyendoftextbody
+ \vskip\footerdistance
+ \the\footertextcontent
+ \vskip\dimexpr\footerheight+\bottomdistance\relax
+ \the\bottomtextcontent
+ \vskip\bottomheight
+ \vfilll}%
+ \smashbox\scratchpagebox
+ \box\scratchpagebox}
+
+\def\getmainbox#1#2%
+ {\setbox\scratchpagebox\vbox
+ {\offinterlineskip % na \paginaletter !
+ \calculatereducedvsizes
+ \calculatehsizes
+ \swapmargins
+ \vskip\dimexpr\headerheight+\headerdistance+\layoutparameter\c!textdistance\relax
+ \hbox to \makeupwidth
+ {\bgroup
+ \swapmargins
+ \goleftonpage
+ \ifdim\leftedgewidth>\zeropoint
+ \the\leftedgetextcontent
+ \hskip\leftedgewidth
+ \fi
+ \hskip\leftedgedistance
+ \ifdim\leftmarginwidth>\zeropoint
+ \the\leftmargintextcontent
+ \hskip\leftmarginwidth
+ \fi
+ \hskip\leftmargindistance
+ \egroup
+ \mkprocesspagecontents{#2}%
+ \settextpagecontent\scratchpagebox{#1}{#2}%
+ \addtextbackground\scratchpagebox
+ \addtextgridlayer\scratchpagebox
+ \box\scratchpagebox
+ \bgroup
+ \hskip\rightmargindistance
+ \ifdim\rightmarginwidth>\zeropoint
+ \the\rightmargintextcontent
+ \hskip\rightmarginwidth
+ \fi
+ \hskip\rightedgedistance
+ \ifdim\rightedgewidth>\zeropoint
+ \the\rightedgetextcontent
+ \hskip\rightedgewidth
+ \fi
+ \egroup
+ \hss}}%
+ \smashbox\scratchpagebox
+ \box\scratchpagebox}
+
+%D The main text area has to be combined with some additional
+%D (tracing) information.
+
+% will be stored as normal and overloaded in page-lyr and later in
+% page-spr we overload the the stored version .. evenatually i will
+% clear up the experimental mess
+
+\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+ {\setbox#1\hbox to \makeupwidth
+ {\hss % so don't change this
+ \setlayoutcomponentattribute\v!page\v!text
+ \vbox \layoutcomponentboxattribute to \textheight
+ {\offinterlineskip
+ \freezetextwidth
+ \hsize\textwidth % local variant of \sethsize
+ \boxmaxdepth\maxdepth
+ \noindent % content can be < \hsize
+ \dopagecontents#2#3}%
+ \hss}%
+ \dp#1\zeropoint}
+
+%D The placement of a whole line is handled by the next two
+%D macros. These are hooked into the general purpose token
+%D list registers mentioned before.
+
+\def\ignoredlinebreak{\unskip\space\ignorespaces}
+
+% \def\doplacelayouttextline#1#2%
+% {\ifdim#2>\zeropoint\relax % prevents pagenumbers when zero height
+% \goleftonpage
+% \hbox
+% {\setbox\scratchpagebox\vbox to #2
+% {\vsize#2\relax
+% \normalbaselines
+% \let\\\ignoredlinebreak
+% \let\crlf\ignoredlinebreak
+% \csname\??tk#1\c!before\endcsname
+% \doifbothsidesoverruled
+% {\dodoplacelayouttextline#1\c!lefttext \c!middletext\c!righttext\zerocount\plusone}
+% {\dodoplacelayouttextline#1\c!lefttext \c!middletext\c!righttext\zerocount\plusone}
+% {\dodoplacelayouttextline#1\c!righttext\c!middletext\c!lefttext \plusone\zerocount}%
+% \csname\??tk#1\c!after\endcsname
+% \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
+% \dp\scratchpagebox\zeropoint
+% \box\scratchpagebox}%
+% \vskip-#2\relax
+% \fi}
+%
+% \def\dodoplacelayouttextline#1#2#3#4#5#6% \hsize toegevoegd, \hss's niet meer wijzigen
+% {\hbox
+% {\ifdim\leftedgewidth>\zeropoint
+% \dododoplacelayouttextline\leftedgewidth#1\v!edge
+% {\hss\csname\??tk#1\v!edge#2\endcsname}%
+% \hskip\leftedgedistance
+% \fi
+% \ifdim\leftmarginwidth>\zeropoint
+% \dododoplacelayouttextline\leftmarginwidth#1\v!margin
+% {\hbox to \leftmarginwidth
+% {\hss\csname\??tk#1\v!margin#2\endcsname}%
+% \hskip-\leftmarginwidth
+% \hbox to \leftmarginwidth
+% {\hss\ifcase#5\or\csname\??tk#1\v!margin\c!margintext\endcsname\fi}}%
+% \hskip\leftmargindistance
+% \fi
+% \ifdim\makeupwidth>\zeropoint
+% \dododoplacelayouttextline\makeupwidth{#1}\v!text
+% {\hbox to \makeupwidth
+% {\ifcase#5\or\@@nmpre{\csname\??tk#1\v!text\c!marginedgetext\endcsname}\fi
+% \csname\??tk#1\v!text#2\endcsname\hss}%
+% \hskip-\makeupwidth
+% \hbox to \makeupwidth
+% {\hss\csname\??tk#1\v!text#3\endcsname\hss}%
+% \hskip-\makeupwidth
+% \hbox to \makeupwidth
+% {\hss\csname\??tk#1\v!text#4\endcsname
+% \ifcase#6\or\@@nmpos{\csname\??tk#1\v!text\c!marginedgetext\endcsname}\fi}}%
+% \fi
+% \ifdim\rightmarginwidth>\zeropoint
+% \hskip\rightmargindistance
+% \dododoplacelayouttextline\rightmarginwidth{#1}\v!margin
+% {\hbox to \rightmarginwidth
+% {\csname\??tk#1\v!margin#4\endcsname\hss}%
+% \hskip-\rightmarginwidth
+% \hbox to \rightmarginwidth
+% {\ifcase#6\or\csname\??tk#1\v!margin\c!margintext\endcsname\fi\hss}}%
+% \fi
+% \ifdim\rightedgewidth>\zeropoint
+% \hskip\rightedgedistance
+% \dododoplacelayouttextline\rightedgewidth{#1}\v!edge
+% {\csname\??tk#1\v!edge#4\endcsname\hss}%
+% \fi}}
+%
+% \def\dododoplacelayouttextline#1#2#3#4%
+% {\vbox % to \vsize
+% {\hsize#1\relax
+% \csname\??tk#2#3\c!before\endcsname
+% \setlayoutcomponentattribute#2#3%
+% \hbox \layoutcomponentboxattribute to #1{#4}%
+% \csname\??tk#2#3\c!after\endcsname}}
+
+\def\doplacelayouttextline#1#2%
+ {\let\currentlayouttextline#1%
+ \ifdim#2>\zeropoint\relax % prevents pagenumbers when zero height
+ \doplacelayouttextlineindeed{#2}%
+ \fi}
+
+\def\doplacelayouttextlineindeed#1%
+ {\goleftonpage
+ \hbox
+ {\setbox\scratchpagebox\vbox to #1
+ {\vsize#1\relax
+ \normalbaselines
+ \let\\\ignoredlinebreak
+ \let\crlf\ignoredlinebreak
+ \csname\??tk\currentlayouttextline\c!before\endcsname
+ \doifbothsidesoverruled\dodoplacelayouttextlineright\dodoplacelayouttextlineright\dodoplacelayouttextlineleft
+ \csname\??tk\currentlayouttextline\c!after\endcsname
+ \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
+ \dp\scratchpagebox\zeropoint
+ \box\scratchpagebox}%
+ \vskip-#1\relax}
+
+\def\dodoplacelayouttextlineright{\dodoplacelayouttextline\c!lefttext \c!middletext\c!righttext\zerocount\plusone}
+\def\dodoplacelayouttextlineleft {\dodoplacelayouttextline\c!righttext\c!middletext\c!lefttext \plusone\zerocount}
+
+\def\dodoplacelayouttextline#1#2#3#4#5% \hsize toegevoegd, \hss's niet meer wijzigen
+ {\hbox
+ {\ifdim\leftedgewidth>\zeropoint
+ \dododoplacelayouttextline\leftedgewidth\currentlayouttextline\v!edge{\thelayoutleftedgeline#1}%
+ \hskip\leftedgedistance
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ \dododoplacelayouttextline\leftmarginwidth\currentlayouttextline\v!margin{\thelayoutleftmarginline#1#4}%
+ \hskip\leftmargindistance
+ \fi
+ \ifdim\makeupwidth>\zeropoint
+ \dododoplacelayouttextline\makeupwidth\currentlayouttextline\v!text{\thelayouttextline#1#2#3#4#5}%
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ \hskip\rightmargindistance
+ \dododoplacelayouttextline\rightmarginwidth\currentlayouttextline\v!margin{\thelayoutrightmarginline#3#5}%
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ \hskip\rightedgedistance
+ \dododoplacelayouttextline\rightedgewidth\currentlayouttextline\v!edge{\thelayoutrightedgeline#3}%
+ \fi}}
+
+\def\thelayoutleftedgeline#1%
+ {\hss\csname\??tk\currentlayouttextline\v!edge#1\endcsname}%
+
+\def\thelayoutrightedgeline#1%
+ {\csname\??tk\currentlayouttextline\v!edge#1\endcsname\hss}
+
+\def\thelayoutleftmarginline#1#2%
+ {\hbox to \leftmarginwidth{\hss\csname\??tk\currentlayouttextline\v!margin#1\endcsname}%
+ \hskip-\leftmarginwidth
+ \hbox to \leftmarginwidth{\hss\ifcase#2\or\csname\??tk\currentlayouttextline\v!margin\c!margintext\endcsname\fi}}
+
+\def\thelayoutrightmarginline#1#2%
+ {\hbox to \rightmarginwidth{\csname\??tk\currentlayouttextline\v!margin#1\endcsname\hss}%
+ \hskip-\rightmarginwidth
+ \hbox to \rightmarginwidth{\ifcase#2\or\csname\??tk\currentlayouttextline\v!margin\c!margintext\endcsname\fi\hss}}
+
+\def\thelayoutedgetextline{\csname\??tk\currentlayouttextline\v!text\c!marginedgetext\endcsname}
+
+\def\thelayouttextline#1#2#3#4#5%
+ {\hbox to \makeupwidth{\ifcase#4\or\@@nmpre\thelayoutedgetextline\fi\csname\??tk\currentlayouttextline\v!text#1\endcsname\hss}%
+ \hskip-\makeupwidth
+ \hbox to \makeupwidth{\hss\csname\??tk\currentlayouttextline\v!text#2\endcsname\hss}%
+ \hskip-\makeupwidth
+ \hbox to \makeupwidth{\hss\csname\??tk\currentlayouttextline\v!text#3\endcsname\ifcase#5\or\@@nmpos\thelayoutedgetextline\fi}}
+
+\def\dododoplacelayouttextline#1#2#3#4%
+ {\vbox % to \vsize
+ {\hsize#1\relax
+ \csname\??tk#2#3\c!before\endcsname
+ \setlayoutcomponentattribute#2#3%
+ \hbox \layoutcomponentboxattribute to #1{#4}%
+ \csname\??tk#2#3\c!after\endcsname}}
+
+%D Although it is far better to use backgrounds for this
+%D purpose, one can add a rule in the following way. This
+%D method makes the rules disappear in case of an empty text
+%D line. Consider this a feature.
+%D
+%D \starttyping
+%D \setupheadertexts[left][right]
+%D
+%D \setupheader[text][after=\hrule,style=bold]
+%D
+%D \starttext
+%D \input tufte \page
+%D \setupheader[state=empty]
+%D \input tufte \page
+%D \stoptext
+%D \stoptyping
+
+%D The next twosome will be done differently (using an
+%D existing auxiliary macro).
+
+% \def\@@nmpre#1{\setbox0\hbox{#1}\ifdim\wd0=\zeropoint\else\unhbox0\tfskip\fi}
+% \def\@@nmpos#1{\setbox0\hbox{#1}\ifdim\wd0=\zeropoint\else\tfskip\unhbox0\fi}
+
+% cleaner
+%
+% \def\@@nmpre#1{\doiftext{#1}{{#1}\tfskip}}
+% \def\@@nmpos#1{\doiftext{#1}{\tfskip{#1}}}
+%
+% newer
+%
+% \def\@@nmprepos#1#2#3#4#5%
+% {\doifelsenothing\@@nmwidth
+% {\doiftext{#5}{#1{#5}#2}}
+% {\doiftext{#5}{\hbox to \@@nmwidth{#3{#5}#4}}}}
+%
+% \def\@@nmpre{\@@nmprepos\empty\tfskip\relax\hss}
+% \def\@@nmpos{\@@nmprepos\tfskip\empty\hss\relax}
+%
+% faster
+
+\def\@@nmpre#1%
+ {\begingroup
+ \setbox\scratchbox\normalhbox{\trialtypesettingtrue\ignorespaces#1\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox\else
+ \doifelsenothing\@@nmwidth
+ {\box\scratchbox\tfskip}
+ {\hbox to \@@nmwidth{\box\scratchbox\hss}}%
+ \fi
+ \endgroup}
+
+\def\@@nmpos#1%
+ {\begingroup
+ \setbox\scratchbox\normalhbox{\trialtypesettingtrue\ignorespaces#1\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox\else
+ \doifelsenothing\@@nmwidth
+ {\tfskip\box\scratchbox}
+ {\hbox to \@@nmwidth{\hss\box\scratchbox}}%
+ \fi
+ \endgroup}
+
+%D This code will move to \type {page-flt.tex}.
+
+\appendtoks \placerightmarginblock \hskip-\rightmarginwidth \to \rightmargintextcontent
+\appendtoks \placeleftmarginblock \hskip-\leftmarginwidth \to \leftmargintextcontent
+
+%D The next hook will later be used for keeping track of
+%D positions, i.e.\ it will provide a proper (page
+%D dependent) reference point.
+
+\ifx\undefined\placepositionanchors
+ \unexpanded\def\placepositionanchors{\vskip\textheight}
+\fi
+
+%D \macros
+%D {definetext}
+%D
+%D Some macros ago, we implemented the \type {status} option
+%D \type {unknown}. This one is used to take care of
+%D symbolic texts handlers.
+%D
+%D \showsetup{definetext}
+%D
+%D The next example demonstrates how we can use this
+%D mechanism to provide page (event) dependent text lines.
+%D
+%D \starttyping
+%D \definetext[chapter][footer][pagenumber]
+%D \setuphead[chapter][header=high,footer=chapter]
+%D \setupheadertexts[pagenumber]
+%D \setupfootertexts[left][right]
+%D \chapter{eerste} \dorecurse{20}{\input tufte \relax}
+%D \chapter{tweede} \dorecurse{20}{\input tufte \relax}
+%D \stoptyping
+
+\unexpanded\def\definetext
+ {\doseventupleempty\dodefinetext}
+
+\def\dodefinetext[#1][#2][#3][#4][#5][#6][#7]%
+ {\ifseventhargument
+ \setvalue{\??tk#2#3#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5][#6][#7]}%
+ \else\ifsixthargument
+ \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5][#6]}%
+ \else\iffifthargument
+ \setvalue{\??tk#2#3#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5]}%
+ \else\iffourthargument
+ \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4]}%
+ \else
+ \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3]}%
+ \fi\fi\fi\fi}
+
+%D The rest of this file is dedicated to setting up the
+%D texts. This code is not that impressive.
+
+\setupheadertexts [\v!text] [] []
+\setupheadertexts [\v!margin] [] []
+\setupheadertexts [\v!edge] [] []
+
+\setupfootertexts [\v!text] [] []
+\setupfootertexts [\v!margin] [] []
+\setupfootertexts [\v!edge] [] []
+
+\setuptexttexts [\v!text] [] []
+\setuptexttexts [\v!margin] [] []
+\setuptexttexts [\v!edge] [] []
+
+\setupbottomtexts [\v!text] [] []
+\setupbottomtexts [\v!margin] [] []
+\setupbottomtexts [\v!edge] [] []
+
+\setuptoptexts [\v!text] [] []
+\setuptoptexts [\v!margin] [] []
+\setuptoptexts [\v!edge] [] []
+
+% alternative
+%
+% \def\resetlayouttekst%
+% {\dodoubleempty\doresetlayouttekst}
+%
+% \def\doresetlayouttekst[#1][#2]%
+% {\ifsecondargument
+% \dodoresetlayouttekst[#1][#2]%
+% \else
+% \dodoresetlayouttekst[#1][\v!tekst]%
+% \fi}
+%
+% \def\dodoresetlayouttekst[#1][#2]%
+% {...}
+%
+% \def\docommand#1%
+% {\resetlayouttekst[#1][\v!tekst]%
+% \resetlayouttekst[#1][\v!marge]%
+% \resetlayouttekst[#1][\v!rand]}
+
+%D We combine a lot of similar settings in a macro that
+%D we will later dispose.
+
+\def\dodocommand[#1][#2]%
+ {\getparameters
+ [\??tk#1#2]
+ [%\c!state=\v!normal, % moved
+ \c!before=,% both global and local are used
+ \c!after=,% both global and local are used
+ \c!strut=,% the local one, not (yet) used
+ \c!style=\csname\??tk#1\c!style\endcsname,% hm, got lost
+ \c!color=\csname\??tk#1\c!color\endcsname,% hm, got lost
+ \c!lefttext=,
+ \c!middletext=,
+ \c!righttext=,
+ \c!marginedgetext=,
+ \c!margintext=,
+ \c!width=]%
+ \inheritparameter[\??tk#1#2][\c!leftstyle ][\c!style ]%
+ \inheritparameter[\??tk#1#2][\c!rightstyle][\c!style ]%
+ \inheritparameter[\??tk#1#2][\c!leftcolor ][\c!color ]%
+ \inheritparameter[\??tk#1#2][\c!rightcolor][\c!color ]%
+ \inheritparameter[\??tk#1#2][\c!leftwidth ][\c!width]%
+ \inheritparameter[\??tk#1#2][\c!rightwidth][\c!width]}
+
+\def\docommand#1%
+ {\dodocommand[#1][\v!text]%
+ \dodocommand[#1][\v!margin]%
+ \dodocommand[#1][\v!edge]}
+
+\docommand\v!top
+\docommand\v!header
+\docommand\v!footer
+\docommand\v!text
+\docommand\v!bottom
+
+\let\docommand \relax
+\let\dodocommand\relax
+
+%D While the header and footer lines are moved away from the
+%D main text, the top and bottom lines are centered.
+
+\setuptop [\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setupheader[\c!state=\v!normal,\c!n=0,\c!before=, \c!after=\vss,\c!strut=\v!yes]
+\setuptext [\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setupfooter[\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=, \c!strut=\v!yes]
+\setupbottom[\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+
+\setuptop [\c!style=,\c!color=]
+\setupheader[\c!style=,\c!color=]
+\setuptext [\c!style=,\c!color=]
+\setupfooter[\c!style=,\c!color=]
+\setupbottom[\c!style=,\c!color=]
+
+\protect \endinput
diff --git a/tex/context/base/pdfr-def.mkii b/tex/context/base/pdfr-def.mkii
new file mode 100644
index 000000000..7554bda9e
--- /dev/null
+++ b/tex/context/base/pdfr-def.mkii
@@ -0,0 +1,843 @@
+% filename : pdfr-def.tex
+% comment : generated by mtxrun --script chars --pdf
+% author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+% copyright: PRAGMA ADE / ConTeXt Development Team
+% license : see context related readme files
+%
+\pdfglyphtounicode{space}{0020}%
+\pdfglyphtounicode{exclam}{0021}%
+\pdfglyphtounicode{quotedbl}{0022}%
+\pdfglyphtounicode{numbersign}{0023}%
+\pdfglyphtounicode{dollar}{0024}%
+\pdfglyphtounicode{percent}{0025}%
+\pdfglyphtounicode{ampersand}{0026}%
+\pdfglyphtounicode{quotesingle}{0027}%
+\pdfglyphtounicode{parenleft}{0028}%
+\pdfglyphtounicode{parenright}{0029}%
+\pdfglyphtounicode{asterisk}{002A}%
+\pdfglyphtounicode{plus}{002B}%
+\pdfglyphtounicode{comma}{002C}%
+\pdfglyphtounicode{hyphen}{002D}%
+\pdfglyphtounicode{period}{002E}%
+\pdfglyphtounicode{slash}{002F}%
+\pdfglyphtounicode{zero}{0030}%
+\pdfglyphtounicode{one}{0031}%
+\pdfglyphtounicode{two}{0032}%
+\pdfglyphtounicode{three}{0033}%
+\pdfglyphtounicode{four}{0034}%
+\pdfglyphtounicode{five}{0035}%
+\pdfglyphtounicode{six}{0036}%
+\pdfglyphtounicode{seven}{0037}%
+\pdfglyphtounicode{eight}{0038}%
+\pdfglyphtounicode{nine}{0039}%
+\pdfglyphtounicode{colon}{003A}%
+\pdfglyphtounicode{semicolon}{003B}%
+\pdfglyphtounicode{less}{003C}%
+\pdfglyphtounicode{equal}{003D}%
+\pdfglyphtounicode{greater}{003E}%
+\pdfglyphtounicode{question}{003F}%
+\pdfglyphtounicode{at}{0040}%
+\pdfglyphtounicode{A}{0041}%
+\pdfglyphtounicode{B}{0042}%
+\pdfglyphtounicode{C}{0043}%
+\pdfglyphtounicode{D}{0044}%
+\pdfglyphtounicode{E}{0045}%
+\pdfglyphtounicode{F}{0046}%
+\pdfglyphtounicode{G}{0047}%
+\pdfglyphtounicode{H}{0048}%
+\pdfglyphtounicode{I}{0049}%
+\pdfglyphtounicode{J}{004A}%
+\pdfglyphtounicode{K}{004B}%
+\pdfglyphtounicode{L}{004C}%
+\pdfglyphtounicode{M}{004D}%
+\pdfglyphtounicode{N}{004E}%
+\pdfglyphtounicode{O}{004F}%
+\pdfglyphtounicode{P}{0050}%
+\pdfglyphtounicode{Q}{0051}%
+\pdfglyphtounicode{R}{0052}%
+\pdfglyphtounicode{S}{0053}%
+\pdfglyphtounicode{T}{0054}%
+\pdfglyphtounicode{U}{0055}%
+\pdfglyphtounicode{V}{0056}%
+\pdfglyphtounicode{W}{0057}%
+\pdfglyphtounicode{X}{0058}%
+\pdfglyphtounicode{Y}{0059}%
+\pdfglyphtounicode{Z}{005A}%
+\pdfglyphtounicode{bracketleft}{005B}%
+\pdfglyphtounicode{backslash}{005C}%
+\pdfglyphtounicode{bracketright}{005D}%
+\pdfglyphtounicode{asciicircum}{005E}%
+\pdfglyphtounicode{underscore}{005F}%
+\pdfglyphtounicode{grave}{0060}%
+\pdfglyphtounicode{a}{0061}%
+\pdfglyphtounicode{b}{0062}%
+\pdfglyphtounicode{c}{0063}%
+\pdfglyphtounicode{d}{0064}%
+\pdfglyphtounicode{e}{0065}%
+\pdfglyphtounicode{f}{0066}%
+\pdfglyphtounicode{g}{0067}%
+\pdfglyphtounicode{h}{0068}%
+\pdfglyphtounicode{i}{0069}%
+\pdfglyphtounicode{j}{006A}%
+\pdfglyphtounicode{k}{006B}%
+\pdfglyphtounicode{l}{006C}%
+\pdfglyphtounicode{m}{006D}%
+\pdfglyphtounicode{n}{006E}%
+\pdfglyphtounicode{o}{006F}%
+\pdfglyphtounicode{p}{0070}%
+\pdfglyphtounicode{q}{0071}%
+\pdfglyphtounicode{r}{0072}%
+\pdfglyphtounicode{s}{0073}%
+\pdfglyphtounicode{t}{0074}%
+\pdfglyphtounicode{u}{0075}%
+\pdfglyphtounicode{v}{0076}%
+\pdfglyphtounicode{w}{0077}%
+\pdfglyphtounicode{x}{0078}%
+\pdfglyphtounicode{y}{0079}%
+\pdfglyphtounicode{z}{007A}%
+\pdfglyphtounicode{braceleft}{007B}%
+\pdfglyphtounicode{bar}{007C}%
+\pdfglyphtounicode{braceright}{007D}%
+\pdfglyphtounicode{asciitilde}{007E}%
+\pdfglyphtounicode{exclamdown}{00A1}%
+\pdfglyphtounicode{cent}{00A2}%
+\pdfglyphtounicode{sterling}{00A3}%
+\pdfglyphtounicode{currency}{00A4}%
+\pdfglyphtounicode{yen}{00A5}%
+\pdfglyphtounicode{brokenbar}{00A6}%
+\pdfglyphtounicode{section}{00A7}%
+\pdfglyphtounicode{dieresis}{00A8}%
+\pdfglyphtounicode{copyright}{00A9}%
+\pdfglyphtounicode{ordfeminine}{00AA}%
+\pdfglyphtounicode{guillemotleft}{00AB}%
+\pdfglyphtounicode{logicalnot}{00AC}%
+\pdfglyphtounicode{registered}{00AE}%
+\pdfglyphtounicode{macron}{00AF}%
+\pdfglyphtounicode{degree}{00B0}%
+\pdfglyphtounicode{plusminus}{00B1}%
+\pdfglyphtounicode{acute}{00B4}%
+\pdfglyphtounicode{mu}{00B5}%
+\pdfglyphtounicode{paragraph}{00B6}%
+\pdfglyphtounicode{periodcentered}{00B7}%
+\pdfglyphtounicode{cedilla}{00B8}%
+\pdfglyphtounicode{ordmasculine}{00BA}%
+\pdfglyphtounicode{guillemotright}{00BB}%
+\pdfglyphtounicode{onequarter}{00BC}%
+\pdfglyphtounicode{onehalf}{00BD}%
+\pdfglyphtounicode{threequarters}{00BE}%
+\pdfglyphtounicode{questiondown}{00BF}%
+\pdfglyphtounicode{Agrave}{00C0}%
+\pdfglyphtounicode{Aacute}{00C1}%
+\pdfglyphtounicode{Acircumflex}{00C2}%
+\pdfglyphtounicode{Atilde}{00C3}%
+\pdfglyphtounicode{Adieresis}{00C4}%
+\pdfglyphtounicode{Aring}{00C5}%
+\pdfglyphtounicode{AE}{00C6}%
+\pdfglyphtounicode{Ccedilla}{00C7}%
+\pdfglyphtounicode{Egrave}{00C8}%
+\pdfglyphtounicode{Eacute}{00C9}%
+\pdfglyphtounicode{Ecircumflex}{00CA}%
+\pdfglyphtounicode{Edieresis}{00CB}%
+\pdfglyphtounicode{Igrave}{00CC}%
+\pdfglyphtounicode{Iacute}{00CD}%
+\pdfglyphtounicode{Icircumflex}{00CE}%
+\pdfglyphtounicode{Idieresis}{00CF}%
+\pdfglyphtounicode{Eth}{00D0}%
+\pdfglyphtounicode{Ntilde}{00D1}%
+\pdfglyphtounicode{Ograve}{00D2}%
+\pdfglyphtounicode{Oacute}{00D3}%
+\pdfglyphtounicode{Ocircumflex}{00D4}%
+\pdfglyphtounicode{Otilde}{00D5}%
+\pdfglyphtounicode{Odieresis}{00D6}%
+\pdfglyphtounicode{multiply}{00D7}%
+\pdfglyphtounicode{Oslash}{00D8}%
+\pdfglyphtounicode{Ugrave}{00D9}%
+\pdfglyphtounicode{Uacute}{00DA}%
+\pdfglyphtounicode{Ucircumflex}{00DB}%
+\pdfglyphtounicode{Udieresis}{00DC}%
+\pdfglyphtounicode{Yacute}{00DD}%
+\pdfglyphtounicode{Thorn}{00DE}%
+\pdfglyphtounicode{germandbls}{00DF}%
+\pdfglyphtounicode{agrave}{00E0}%
+\pdfglyphtounicode{aacute}{00E1}%
+\pdfglyphtounicode{acircumflex}{00E2}%
+\pdfglyphtounicode{atilde}{00E3}%
+\pdfglyphtounicode{adieresis}{00E4}%
+\pdfglyphtounicode{aring}{00E5}%
+\pdfglyphtounicode{ae}{00E6}%
+\pdfglyphtounicode{ccedilla}{00E7}%
+\pdfglyphtounicode{egrave}{00E8}%
+\pdfglyphtounicode{eacute}{00E9}%
+\pdfglyphtounicode{ecircumflex}{00EA}%
+\pdfglyphtounicode{edieresis}{00EB}%
+\pdfglyphtounicode{igrave}{00EC}%
+\pdfglyphtounicode{iacute}{00ED}%
+\pdfglyphtounicode{icircumflex}{00EE}%
+\pdfglyphtounicode{idieresis}{00EF}%
+\pdfglyphtounicode{eth}{00F0}%
+\pdfglyphtounicode{ntilde}{00F1}%
+\pdfglyphtounicode{ograve}{00F2}%
+\pdfglyphtounicode{oacute}{00F3}%
+\pdfglyphtounicode{ocircumflex}{00F4}%
+\pdfglyphtounicode{otilde}{00F5}%
+\pdfglyphtounicode{odieresis}{00F6}%
+\pdfglyphtounicode{divide}{00F7}%
+\pdfglyphtounicode{oslash}{00F8}%
+\pdfglyphtounicode{ugrave}{00F9}%
+\pdfglyphtounicode{uacute}{00FA}%
+\pdfglyphtounicode{ucircumflex}{00FB}%
+\pdfglyphtounicode{udieresis}{00FC}%
+\pdfglyphtounicode{yacute}{00FD}%
+\pdfglyphtounicode{thorn}{00FE}%
+\pdfglyphtounicode{ydieresis}{00FF}%
+\pdfglyphtounicode{Amacron}{0100}%
+\pdfglyphtounicode{amacron}{0101}%
+\pdfglyphtounicode{Abreve}{0102}%
+\pdfglyphtounicode{abreve}{0103}%
+\pdfglyphtounicode{Aogonek}{0104}%
+\pdfglyphtounicode{aogonek}{0105}%
+\pdfglyphtounicode{Cacute}{0106}%
+\pdfglyphtounicode{cacute}{0107}%
+\pdfglyphtounicode{Ccircumflex}{0108}%
+\pdfglyphtounicode{ccircumflex}{0109}%
+\pdfglyphtounicode{Cdotaccent}{010A}%
+\pdfglyphtounicode{cdotaccent}{010B}%
+\pdfglyphtounicode{Ccaron}{010C}%
+\pdfglyphtounicode{ccaron}{010D}%
+\pdfglyphtounicode{Dcaron}{010E}%
+\pdfglyphtounicode{dcaron}{010F}%
+\pdfglyphtounicode{Dcroat}{0110}%
+\pdfglyphtounicode{dcroat}{0111}%
+\pdfglyphtounicode{Emacron}{0112}%
+\pdfglyphtounicode{emacron}{0113}%
+\pdfglyphtounicode{Ebreve}{0114}%
+\pdfglyphtounicode{ebreve}{0115}%
+\pdfglyphtounicode{Edotaccent}{0116}%
+\pdfglyphtounicode{edotaccent}{0117}%
+\pdfglyphtounicode{Eogonek}{0118}%
+\pdfglyphtounicode{eogonek}{0119}%
+\pdfglyphtounicode{Ecaron}{011A}%
+\pdfglyphtounicode{ecaron}{011B}%
+\pdfglyphtounicode{Gcircumflex}{011C}%
+\pdfglyphtounicode{gcircumflex}{011D}%
+\pdfglyphtounicode{Gbreve}{011E}%
+\pdfglyphtounicode{gbreve}{011F}%
+\pdfglyphtounicode{Gdotaccent}{0120}%
+\pdfglyphtounicode{gdotaccent}{0121}%
+\pdfglyphtounicode{Gcommaaccent}{0122}%
+\pdfglyphtounicode{gcommaaccent}{0123}%
+\pdfglyphtounicode{Hcircumflex}{0124}%
+\pdfglyphtounicode{hcircumflex}{0125}%
+\pdfglyphtounicode{Hbar}{0126}%
+\pdfglyphtounicode{hbar}{0127}%
+\pdfglyphtounicode{Itilde}{0128}%
+\pdfglyphtounicode{itilde}{0129}%
+\pdfglyphtounicode{Imacron}{012A}%
+\pdfglyphtounicode{imacron}{012B}%
+\pdfglyphtounicode{Ibreve}{012C}%
+\pdfglyphtounicode{ibreve}{012D}%
+\pdfglyphtounicode{Iogonek}{012E}%
+\pdfglyphtounicode{iogonek}{012F}%
+\pdfglyphtounicode{Idotaccent}{0130}%
+\pdfglyphtounicode{dotlessi}{0131}%
+\pdfglyphtounicode{IJ}{0132}%
+\pdfglyphtounicode{ij}{0133}%
+\pdfglyphtounicode{Jcircumflex}{0134}%
+\pdfglyphtounicode{jcircumflex}{0135}%
+\pdfglyphtounicode{Kcommaaccent}{0136}%
+\pdfglyphtounicode{kcommaaccent}{0137}%
+\pdfglyphtounicode{kgreenlandic}{0138}%
+\pdfglyphtounicode{Lacute}{0139}%
+\pdfglyphtounicode{lacute}{013A}%
+\pdfglyphtounicode{Lcommaaccent}{013B}%
+\pdfglyphtounicode{lcommaaccent}{013C}%
+\pdfglyphtounicode{Lcaron}{013D}%
+\pdfglyphtounicode{lcaron}{013E}%
+\pdfglyphtounicode{Ldot}{013F}%
+\pdfglyphtounicode{ldot}{0140}%
+\pdfglyphtounicode{Lslash}{0141}%
+\pdfglyphtounicode{lslash}{0142}%
+\pdfglyphtounicode{Nacute}{0143}%
+\pdfglyphtounicode{nacute}{0144}%
+\pdfglyphtounicode{Ncommaaccent}{0145}%
+\pdfglyphtounicode{ncommaaccent}{0146}%
+\pdfglyphtounicode{Ncaron}{0147}%
+\pdfglyphtounicode{ncaron}{0148}%
+\pdfglyphtounicode{napostrophe}{0149}%
+\pdfglyphtounicode{Eng}{014A}%
+\pdfglyphtounicode{eng}{014B}%
+\pdfglyphtounicode{Omacron}{014C}%
+\pdfglyphtounicode{omacron}{014D}%
+\pdfglyphtounicode{Obreve}{014E}%
+\pdfglyphtounicode{obreve}{014F}%
+\pdfglyphtounicode{Ohungarumlaut}{0150}%
+\pdfglyphtounicode{ohungarumlaut}{0151}%
+\pdfglyphtounicode{OE}{0152}%
+\pdfglyphtounicode{oe}{0153}%
+\pdfglyphtounicode{Racute}{0154}%
+\pdfglyphtounicode{racute}{0155}%
+\pdfglyphtounicode{Rcommaaccent}{0156}%
+\pdfglyphtounicode{rcommaaccent}{0157}%
+\pdfglyphtounicode{Rcaron}{0158}%
+\pdfglyphtounicode{rcaron}{0159}%
+\pdfglyphtounicode{Sacute}{015A}%
+\pdfglyphtounicode{sacute}{015B}%
+\pdfglyphtounicode{Scircumflex}{015C}%
+\pdfglyphtounicode{scircumflex}{015D}%
+\pdfglyphtounicode{Scedilla}{015E}%
+\pdfglyphtounicode{scedilla}{015F}%
+\pdfglyphtounicode{Scaron}{0160}%
+\pdfglyphtounicode{scaron}{0161}%
+\pdfglyphtounicode{Tcommaaccent}{0162}%
+\pdfglyphtounicode{tcommaaccent}{0163}%
+\pdfglyphtounicode{Tcaron}{0164}%
+\pdfglyphtounicode{tcaron}{0165}%
+\pdfglyphtounicode{Tbar}{0166}%
+\pdfglyphtounicode{tbar}{0167}%
+\pdfglyphtounicode{Utilde}{0168}%
+\pdfglyphtounicode{utilde}{0169}%
+\pdfglyphtounicode{Umacron}{016A}%
+\pdfglyphtounicode{umacron}{016B}%
+\pdfglyphtounicode{Ubreve}{016C}%
+\pdfglyphtounicode{ubreve}{016D}%
+\pdfglyphtounicode{Uring}{016E}%
+\pdfglyphtounicode{uring}{016F}%
+\pdfglyphtounicode{Uhungarumlaut}{0170}%
+\pdfglyphtounicode{uhungarumlaut}{0171}%
+\pdfglyphtounicode{Uogonek}{0172}%
+\pdfglyphtounicode{uogonek}{0173}%
+\pdfglyphtounicode{Wcircumflex}{0174}%
+\pdfglyphtounicode{wcircumflex}{0175}%
+\pdfglyphtounicode{Ycircumflex}{0176}%
+\pdfglyphtounicode{ycircumflex}{0177}%
+\pdfglyphtounicode{Ydieresis}{0178}%
+\pdfglyphtounicode{Zacute}{0179}%
+\pdfglyphtounicode{zacute}{017A}%
+\pdfglyphtounicode{Zdotaccent}{017B}%
+\pdfglyphtounicode{zdotaccent}{017C}%
+\pdfglyphtounicode{Zcaron}{017D}%
+\pdfglyphtounicode{zcaron}{017E}%
+\pdfglyphtounicode{longs}{017F}%
+\pdfglyphtounicode{florin}{0192}%
+\pdfglyphtounicode{Ohorn}{01A0}%
+\pdfglyphtounicode{ohorn}{01A1}%
+\pdfglyphtounicode{Uhorn}{01AF}%
+\pdfglyphtounicode{uhorn}{01B0}%
+\pdfglyphtounicode{Gcaron}{01E6}%
+\pdfglyphtounicode{gcaron}{01E7}%
+\pdfglyphtounicode{Aringacute}{01FA}%
+\pdfglyphtounicode{aringacute}{01FB}%
+\pdfglyphtounicode{AEacute}{01FC}%
+\pdfglyphtounicode{aeacute}{01FD}%
+\pdfglyphtounicode{Oslashacute}{01FE}%
+\pdfglyphtounicode{oslashacute}{01FF}%
+\pdfglyphtounicode{Scommaaccent}{0218}%
+\pdfglyphtounicode{scommaaccent}{0219}%
+\pdfglyphtounicode{afii57929}{02BC}%
+\pdfglyphtounicode{afii64937}{02BD}%
+\pdfglyphtounicode{circumflex}{02C6}%
+\pdfglyphtounicode{caron}{02C7}%
+\pdfglyphtounicode{breve}{02D8}%
+\pdfglyphtounicode{dotaccent}{02D9}%
+\pdfglyphtounicode{ring}{02DA}%
+\pdfglyphtounicode{ogonek}{02DB}%
+\pdfglyphtounicode{tilde}{02DC}%
+\pdfglyphtounicode{hungarumlaut}{02DD}%
+\pdfglyphtounicode{gravecomb}{0300}%
+\pdfglyphtounicode{acutecomb}{0301}%
+\pdfglyphtounicode{tildecomb}{0303}%
+\pdfglyphtounicode{hookabovecomb}{0309}%
+\pdfglyphtounicode{dotbelowcomb}{0323}%
+\pdfglyphtounicode{tonos}{0384}%
+\pdfglyphtounicode{dieresistonos}{0385}%
+\pdfglyphtounicode{Alphatonos}{0386}%
+\pdfglyphtounicode{anoteleia}{0387}%
+\pdfglyphtounicode{Epsilontonos}{0388}%
+\pdfglyphtounicode{Etatonos}{0389}%
+\pdfglyphtounicode{Iotatonos}{038A}%
+\pdfglyphtounicode{Omicrontonos}{038C}%
+\pdfglyphtounicode{Upsilontonos}{038E}%
+\pdfglyphtounicode{Omegatonos}{038F}%
+\pdfglyphtounicode{iotadieresistonos}{0390}%
+\pdfglyphtounicode{Alpha}{0391}%
+\pdfglyphtounicode{Beta}{0392}%
+\pdfglyphtounicode{Gamma}{0393}%
+\pdfglyphtounicode{Epsilon}{0395}%
+\pdfglyphtounicode{Zeta}{0396}%
+\pdfglyphtounicode{Eta}{0397}%
+\pdfglyphtounicode{Theta}{0398}%
+\pdfglyphtounicode{Iota}{0399}%
+\pdfglyphtounicode{Kappa}{039A}%
+\pdfglyphtounicode{Lambda}{039B}%
+\pdfglyphtounicode{Mu}{039C}%
+\pdfglyphtounicode{Nu}{039D}%
+\pdfglyphtounicode{Xi}{039E}%
+\pdfglyphtounicode{Omicron}{039F}%
+\pdfglyphtounicode{Pi}{03A0}%
+\pdfglyphtounicode{Rho}{03A1}%
+\pdfglyphtounicode{Sigma}{03A3}%
+\pdfglyphtounicode{Tau}{03A4}%
+\pdfglyphtounicode{Upsilon}{03A5}%
+\pdfglyphtounicode{Phi}{03A6}%
+\pdfglyphtounicode{Chi}{03A7}%
+\pdfglyphtounicode{Psi}{03A8}%
+\pdfglyphtounicode{Iotadieresis}{03AA}%
+\pdfglyphtounicode{Upsilondieresis}{03AB}%
+\pdfglyphtounicode{alphatonos}{03AC}%
+\pdfglyphtounicode{epsilontonos}{03AD}%
+\pdfglyphtounicode{etatonos}{03AE}%
+\pdfglyphtounicode{iotatonos}{03AF}%
+\pdfglyphtounicode{upsilondieresistonos}{03B0}%
+\pdfglyphtounicode{alpha}{03B1}%
+\pdfglyphtounicode{beta}{03B2}%
+\pdfglyphtounicode{gamma}{03B3}%
+\pdfglyphtounicode{delta}{03B4}%
+\pdfglyphtounicode{epsilon}{03B5}%
+\pdfglyphtounicode{zeta}{03B6}%
+\pdfglyphtounicode{eta}{03B7}%
+\pdfglyphtounicode{theta}{03B8}%
+\pdfglyphtounicode{iota}{03B9}%
+\pdfglyphtounicode{kappa}{03BA}%
+\pdfglyphtounicode{lambda}{03BB}%
+\pdfglyphtounicode{nu}{03BD}%
+\pdfglyphtounicode{xi}{03BE}%
+\pdfglyphtounicode{omicron}{03BF}%
+\pdfglyphtounicode{pi}{03C0}%
+\pdfglyphtounicode{rho}{03C1}%
+\pdfglyphtounicode{sigma1}{03C2}%
+\pdfglyphtounicode{sigma}{03C3}%
+\pdfglyphtounicode{tau}{03C4}%
+\pdfglyphtounicode{upsilon}{03C5}%
+\pdfglyphtounicode{phi}{03C6}%
+\pdfglyphtounicode{chi}{03C7}%
+\pdfglyphtounicode{psi}{03C8}%
+\pdfglyphtounicode{omega}{03C9}%
+\pdfglyphtounicode{iotadieresis}{03CA}%
+\pdfglyphtounicode{upsilondieresis}{03CB}%
+\pdfglyphtounicode{omicrontonos}{03CC}%
+\pdfglyphtounicode{upsilontonos}{03CD}%
+\pdfglyphtounicode{omegatonos}{03CE}%
+\pdfglyphtounicode{theta1}{03D1}%
+\pdfglyphtounicode{Upsilon1}{03D2}%
+\pdfglyphtounicode{phi1}{03D5}%
+\pdfglyphtounicode{omega1}{03D6}%
+\pdfglyphtounicode{afii10023}{0401}%
+\pdfglyphtounicode{afii10051}{0402}%
+\pdfglyphtounicode{afii10052}{0403}%
+\pdfglyphtounicode{afii10053}{0404}%
+\pdfglyphtounicode{afii10054}{0405}%
+\pdfglyphtounicode{afii10055}{0406}%
+\pdfglyphtounicode{afii10056}{0407}%
+\pdfglyphtounicode{afii10057}{0408}%
+\pdfglyphtounicode{afii10058}{0409}%
+\pdfglyphtounicode{afii10059}{040A}%
+\pdfglyphtounicode{afii10060}{040B}%
+\pdfglyphtounicode{afii10061}{040C}%
+\pdfglyphtounicode{afii10062}{040E}%
+\pdfglyphtounicode{afii10145}{040F}%
+\pdfglyphtounicode{afii10017}{0410}%
+\pdfglyphtounicode{afii10018}{0411}%
+\pdfglyphtounicode{afii10019}{0412}%
+\pdfglyphtounicode{afii10020}{0413}%
+\pdfglyphtounicode{afii10021}{0414}%
+\pdfglyphtounicode{afii10022}{0415}%
+\pdfglyphtounicode{afii10024}{0416}%
+\pdfglyphtounicode{afii10025}{0417}%
+\pdfglyphtounicode{afii10026}{0418}%
+\pdfglyphtounicode{afii10027}{0419}%
+\pdfglyphtounicode{afii10028}{041A}%
+\pdfglyphtounicode{afii10029}{041B}%
+\pdfglyphtounicode{afii10030}{041C}%
+\pdfglyphtounicode{afii10031}{041D}%
+\pdfglyphtounicode{afii10032}{041E}%
+\pdfglyphtounicode{afii10033}{041F}%
+\pdfglyphtounicode{afii10034}{0420}%
+\pdfglyphtounicode{afii10035}{0421}%
+\pdfglyphtounicode{afii10036}{0422}%
+\pdfglyphtounicode{afii10037}{0423}%
+\pdfglyphtounicode{afii10038}{0424}%
+\pdfglyphtounicode{afii10039}{0425}%
+\pdfglyphtounicode{afii10040}{0426}%
+\pdfglyphtounicode{afii10041}{0427}%
+\pdfglyphtounicode{afii10042}{0428}%
+\pdfglyphtounicode{afii10043}{0429}%
+\pdfglyphtounicode{afii10044}{042A}%
+\pdfglyphtounicode{afii10045}{042B}%
+\pdfglyphtounicode{afii10046}{042C}%
+\pdfglyphtounicode{afii10047}{042D}%
+\pdfglyphtounicode{afii10048}{042E}%
+\pdfglyphtounicode{afii10049}{042F}%
+\pdfglyphtounicode{afii10065}{0430}%
+\pdfglyphtounicode{afii10066}{0431}%
+\pdfglyphtounicode{afii10067}{0432}%
+\pdfglyphtounicode{afii10068}{0433}%
+\pdfglyphtounicode{afii10069}{0434}%
+\pdfglyphtounicode{afii10070}{0435}%
+\pdfglyphtounicode{afii10072}{0436}%
+\pdfglyphtounicode{afii10073}{0437}%
+\pdfglyphtounicode{afii10074}{0438}%
+\pdfglyphtounicode{afii10075}{0439}%
+\pdfglyphtounicode{afii10076}{043A}%
+\pdfglyphtounicode{afii10077}{043B}%
+\pdfglyphtounicode{afii10078}{043C}%
+\pdfglyphtounicode{afii10079}{043D}%
+\pdfglyphtounicode{afii10080}{043E}%
+\pdfglyphtounicode{afii10081}{043F}%
+\pdfglyphtounicode{afii10082}{0440}%
+\pdfglyphtounicode{afii10083}{0441}%
+\pdfglyphtounicode{afii10084}{0442}%
+\pdfglyphtounicode{afii10085}{0443}%
+\pdfglyphtounicode{afii10086}{0444}%
+\pdfglyphtounicode{afii10087}{0445}%
+\pdfglyphtounicode{afii10088}{0446}%
+\pdfglyphtounicode{afii10089}{0447}%
+\pdfglyphtounicode{afii10090}{0448}%
+\pdfglyphtounicode{afii10091}{0449}%
+\pdfglyphtounicode{afii10092}{044A}%
+\pdfglyphtounicode{afii10093}{044B}%
+\pdfglyphtounicode{afii10094}{044C}%
+\pdfglyphtounicode{afii10095}{044D}%
+\pdfglyphtounicode{afii10096}{044E}%
+\pdfglyphtounicode{afii10097}{044F}%
+\pdfglyphtounicode{afii10071}{0451}%
+\pdfglyphtounicode{afii10099}{0452}%
+\pdfglyphtounicode{afii10100}{0453}%
+\pdfglyphtounicode{afii10101}{0454}%
+\pdfglyphtounicode{afii10102}{0455}%
+\pdfglyphtounicode{afii10103}{0456}%
+\pdfglyphtounicode{afii10104}{0457}%
+\pdfglyphtounicode{afii10105}{0458}%
+\pdfglyphtounicode{afii10106}{0459}%
+\pdfglyphtounicode{afii10107}{045A}%
+\pdfglyphtounicode{afii10108}{045B}%
+\pdfglyphtounicode{afii10109}{045C}%
+\pdfglyphtounicode{afii10110}{045E}%
+\pdfglyphtounicode{afii10193}{045F}%
+\pdfglyphtounicode{afii10146}{0462}%
+\pdfglyphtounicode{afii10194}{0463}%
+\pdfglyphtounicode{afii10147}{0472}%
+\pdfglyphtounicode{afii10195}{0473}%
+\pdfglyphtounicode{afii10148}{0474}%
+\pdfglyphtounicode{afii10196}{0475}%
+\pdfglyphtounicode{afii10050}{0490}%
+\pdfglyphtounicode{afii10098}{0491}%
+\pdfglyphtounicode{afii10846}{04D9}%
+\pdfglyphtounicode{afii57799}{05B0}%
+\pdfglyphtounicode{afii57801}{05B1}%
+\pdfglyphtounicode{afii57800}{05B2}%
+\pdfglyphtounicode{afii57802}{05B3}%
+\pdfglyphtounicode{afii57793}{05B4}%
+\pdfglyphtounicode{afii57794}{05B5}%
+\pdfglyphtounicode{afii57795}{05B6}%
+\pdfglyphtounicode{afii57798}{05B7}%
+\pdfglyphtounicode{afii57797}{05B8}%
+\pdfglyphtounicode{afii57806}{05B9}%
+\pdfglyphtounicode{afii57796}{05BB}%
+\pdfglyphtounicode{afii57807}{05BC}%
+\pdfglyphtounicode{afii57839}{05BD}%
+\pdfglyphtounicode{afii57645}{05BE}%
+\pdfglyphtounicode{afii57841}{05BF}%
+\pdfglyphtounicode{afii57842}{05C0}%
+\pdfglyphtounicode{afii57804}{05C1}%
+\pdfglyphtounicode{afii57803}{05C2}%
+\pdfglyphtounicode{afii57658}{05C3}%
+\pdfglyphtounicode{afii57664}{05D0}%
+\pdfglyphtounicode{afii57665}{05D1}%
+\pdfglyphtounicode{afii57666}{05D2}%
+\pdfglyphtounicode{afii57667}{05D3}%
+\pdfglyphtounicode{afii57668}{05D4}%
+\pdfglyphtounicode{afii57669}{05D5}%
+\pdfglyphtounicode{afii57670}{05D6}%
+\pdfglyphtounicode{afii57671}{05D7}%
+\pdfglyphtounicode{afii57672}{05D8}%
+\pdfglyphtounicode{afii57673}{05D9}%
+\pdfglyphtounicode{afii57674}{05DA}%
+\pdfglyphtounicode{afii57675}{05DB}%
+\pdfglyphtounicode{afii57676}{05DC}%
+\pdfglyphtounicode{afii57677}{05DD}%
+\pdfglyphtounicode{afii57678}{05DE}%
+\pdfglyphtounicode{afii57679}{05DF}%
+\pdfglyphtounicode{afii57680}{05E0}%
+\pdfglyphtounicode{afii57681}{05E1}%
+\pdfglyphtounicode{afii57682}{05E2}%
+\pdfglyphtounicode{afii57683}{05E3}%
+\pdfglyphtounicode{afii57684}{05E4}%
+\pdfglyphtounicode{afii57685}{05E5}%
+\pdfglyphtounicode{afii57686}{05E6}%
+\pdfglyphtounicode{afii57687}{05E7}%
+\pdfglyphtounicode{afii57688}{05E8}%
+\pdfglyphtounicode{afii57689}{05E9}%
+\pdfglyphtounicode{afii57690}{05EA}%
+\pdfglyphtounicode{afii57716}{05F0}%
+\pdfglyphtounicode{afii57717}{05F1}%
+\pdfglyphtounicode{afii57718}{05F2}%
+\pdfglyphtounicode{afii57388}{060C}%
+\pdfglyphtounicode{afii57403}{061B}%
+\pdfglyphtounicode{afii57407}{061F}%
+\pdfglyphtounicode{afii57409}{0621}%
+\pdfglyphtounicode{afii57410}{0622}%
+\pdfglyphtounicode{afii57411}{0623}%
+\pdfglyphtounicode{afii57412}{0624}%
+\pdfglyphtounicode{afii57413}{0625}%
+\pdfglyphtounicode{afii57414}{0626}%
+\pdfglyphtounicode{afii57415}{0627}%
+\pdfglyphtounicode{afii57416}{0628}%
+\pdfglyphtounicode{afii57417}{0629}%
+\pdfglyphtounicode{afii57418}{062A}%
+\pdfglyphtounicode{afii57419}{062B}%
+\pdfglyphtounicode{afii57420}{062C}%
+\pdfglyphtounicode{afii57421}{062D}%
+\pdfglyphtounicode{afii57422}{062E}%
+\pdfglyphtounicode{afii57423}{062F}%
+\pdfglyphtounicode{afii57424}{0630}%
+\pdfglyphtounicode{afii57425}{0631}%
+\pdfglyphtounicode{afii57426}{0632}%
+\pdfglyphtounicode{afii57427}{0633}%
+\pdfglyphtounicode{afii57428}{0634}%
+\pdfglyphtounicode{afii57429}{0635}%
+\pdfglyphtounicode{afii57430}{0636}%
+\pdfglyphtounicode{afii57431}{0637}%
+\pdfglyphtounicode{afii57432}{0638}%
+\pdfglyphtounicode{afii57433}{0639}%
+\pdfglyphtounicode{afii57434}{063A}%
+\pdfglyphtounicode{afii57440}{0640}%
+\pdfglyphtounicode{afii57441}{0641}%
+\pdfglyphtounicode{afii57442}{0642}%
+\pdfglyphtounicode{afii57443}{0643}%
+\pdfglyphtounicode{afii57444}{0644}%
+\pdfglyphtounicode{afii57445}{0645}%
+\pdfglyphtounicode{afii57446}{0646}%
+\pdfglyphtounicode{afii57470}{0647}%
+\pdfglyphtounicode{afii57448}{0648}%
+\pdfglyphtounicode{afii57449}{0649}%
+\pdfglyphtounicode{afii57450}{064A}%
+\pdfglyphtounicode{afii57451}{064B}%
+\pdfglyphtounicode{afii57452}{064C}%
+\pdfglyphtounicode{afii57453}{064D}%
+\pdfglyphtounicode{afii57454}{064E}%
+\pdfglyphtounicode{afii57455}{064F}%
+\pdfglyphtounicode{afii57456}{0650}%
+\pdfglyphtounicode{afii57457}{0651}%
+\pdfglyphtounicode{afii57458}{0652}%
+\pdfglyphtounicode{afii57392}{0660}%
+\pdfglyphtounicode{afii57393}{0661}%
+\pdfglyphtounicode{afii57394}{0662}%
+\pdfglyphtounicode{afii57395}{0663}%
+\pdfglyphtounicode{afii57396}{0664}%
+\pdfglyphtounicode{afii57397}{0665}%
+\pdfglyphtounicode{afii57398}{0666}%
+\pdfglyphtounicode{afii57399}{0667}%
+\pdfglyphtounicode{afii57400}{0668}%
+\pdfglyphtounicode{afii57401}{0669}%
+\pdfglyphtounicode{afii57381}{066A}%
+\pdfglyphtounicode{afii63167}{066D}%
+\pdfglyphtounicode{afii57511}{0679}%
+\pdfglyphtounicode{afii57506}{067E}%
+\pdfglyphtounicode{afii57507}{0686}%
+\pdfglyphtounicode{afii57512}{0688}%
+\pdfglyphtounicode{afii57513}{0691}%
+\pdfglyphtounicode{afii57508}{0698}%
+\pdfglyphtounicode{afii57505}{06A4}%
+\pdfglyphtounicode{afii57509}{06AF}%
+\pdfglyphtounicode{afii57514}{06BA}%
+\pdfglyphtounicode{afii57519}{06D2}%
+\pdfglyphtounicode{afii57534}{06D5}%
+\pdfglyphtounicode{Wgrave}{1E80}%
+\pdfglyphtounicode{wgrave}{1E81}%
+\pdfglyphtounicode{Wacute}{1E82}%
+\pdfglyphtounicode{wacute}{1E83}%
+\pdfglyphtounicode{Wdieresis}{1E84}%
+\pdfglyphtounicode{wdieresis}{1E85}%
+\pdfglyphtounicode{Ygrave}{1EF2}%
+\pdfglyphtounicode{ygrave}{1EF3}%
+\pdfglyphtounicode{afii61664}{200C}%
+\pdfglyphtounicode{afii301}{200D}%
+\pdfglyphtounicode{afii299}{200E}%
+\pdfglyphtounicode{afii300}{200F}%
+\pdfglyphtounicode{figuredash}{2012}%
+\pdfglyphtounicode{endash}{2013}%
+\pdfglyphtounicode{emdash}{2014}%
+\pdfglyphtounicode{afii208}{2015}%
+\pdfglyphtounicode{underscoredbl}{2017}%
+\pdfglyphtounicode{quoteleft}{2018}%
+\pdfglyphtounicode{quoteright}{2019}%
+\pdfglyphtounicode{quotesinglbase}{201A}%
+\pdfglyphtounicode{quotereversed}{201B}%
+\pdfglyphtounicode{quotedblleft}{201C}%
+\pdfglyphtounicode{quotedblright}{201D}%
+\pdfglyphtounicode{quotedblbase}{201E}%
+\pdfglyphtounicode{dagger}{2020}%
+\pdfglyphtounicode{daggerdbl}{2021}%
+\pdfglyphtounicode{bullet}{2022}%
+\pdfglyphtounicode{onedotenleader}{2024}%
+\pdfglyphtounicode{twodotenleader}{2025}%
+\pdfglyphtounicode{ellipsis}{2026}%
+\pdfglyphtounicode{afii61573}{202C}%
+\pdfglyphtounicode{afii61574}{202D}%
+\pdfglyphtounicode{afii61575}{202E}%
+\pdfglyphtounicode{perthousand}{2030}%
+\pdfglyphtounicode{minute}{2032}%
+\pdfglyphtounicode{second}{2033}%
+\pdfglyphtounicode{guilsinglleft}{2039}%
+\pdfglyphtounicode{guilsinglright}{203A}%
+\pdfglyphtounicode{exclamdbl}{203C}%
+\pdfglyphtounicode{fraction}{2044}%
+\pdfglyphtounicode{colonmonetary}{20A1}%
+\pdfglyphtounicode{franc}{20A3}%
+\pdfglyphtounicode{lira}{20A4}%
+\pdfglyphtounicode{peseta}{20A7}%
+\pdfglyphtounicode{afii57636}{20AA}%
+\pdfglyphtounicode{dong}{20AB}%
+\pdfglyphtounicode{Euro}{20AC}%
+\pdfglyphtounicode{afii61248}{2105}%
+\pdfglyphtounicode{Ifraktur}{2111}%
+\pdfglyphtounicode{afii61289}{2113}%
+\pdfglyphtounicode{afii61352}{2116}%
+\pdfglyphtounicode{weierstrass}{2118}%
+\pdfglyphtounicode{Rfraktur}{211C}%
+\pdfglyphtounicode{prescription}{211E}%
+\pdfglyphtounicode{trademark}{2122}%
+\pdfglyphtounicode{Omega}{2126}%
+\pdfglyphtounicode{estimated}{212E}%
+\pdfglyphtounicode{aleph}{2135}%
+\pdfglyphtounicode{onethird}{2153}%
+\pdfglyphtounicode{twothirds}{2154}%
+\pdfglyphtounicode{oneeighth}{215B}%
+\pdfglyphtounicode{threeeighths}{215C}%
+\pdfglyphtounicode{fiveeighths}{215D}%
+\pdfglyphtounicode{seveneighths}{215E}%
+\pdfglyphtounicode{arrowleft}{2190}%
+\pdfglyphtounicode{arrowup}{2191}%
+\pdfglyphtounicode{arrowright}{2192}%
+\pdfglyphtounicode{arrowdown}{2193}%
+\pdfglyphtounicode{arrowboth}{2194}%
+\pdfglyphtounicode{arrowupdn}{2195}%
+\pdfglyphtounicode{arrowupdnbse}{21A8}%
+\pdfglyphtounicode{carriagereturn}{21B5}%
+\pdfglyphtounicode{arrowdblleft}{21D0}%
+\pdfglyphtounicode{arrowdblup}{21D1}%
+\pdfglyphtounicode{arrowdblright}{21D2}%
+\pdfglyphtounicode{arrowdbldown}{21D3}%
+\pdfglyphtounicode{arrowdblboth}{21D4}%
+\pdfglyphtounicode{universal}{2200}%
+\pdfglyphtounicode{partialdiff}{2202}%
+\pdfglyphtounicode{existential}{2203}%
+\pdfglyphtounicode{emptyset}{2205}%
+\pdfglyphtounicode{Delta}{2206}%
+\pdfglyphtounicode{gradient}{2207}%
+\pdfglyphtounicode{element}{2208}%
+\pdfglyphtounicode{notelement}{2209}%
+\pdfglyphtounicode{suchthat}{220B}%
+\pdfglyphtounicode{product}{220F}%
+\pdfglyphtounicode{summation}{2211}%
+\pdfglyphtounicode{minus}{2212}%
+\pdfglyphtounicode{asteriskmath}{2217}%
+\pdfglyphtounicode{radical}{221A}%
+\pdfglyphtounicode{proportional}{221D}%
+\pdfglyphtounicode{infinity}{221E}%
+\pdfglyphtounicode{orthogonal}{221F}%
+\pdfglyphtounicode{angle}{2220}%
+\pdfglyphtounicode{logicaland}{2227}%
+\pdfglyphtounicode{logicalor}{2228}%
+\pdfglyphtounicode{intersection}{2229}%
+\pdfglyphtounicode{union}{222A}%
+\pdfglyphtounicode{integral}{222B}%
+\pdfglyphtounicode{therefore}{2234}%
+\pdfglyphtounicode{similar}{223C}%
+\pdfglyphtounicode{congruent}{2245}%
+\pdfglyphtounicode{approxequal}{2248}%
+\pdfglyphtounicode{notequal}{2260}%
+\pdfglyphtounicode{equivalence}{2261}%
+\pdfglyphtounicode{lessequal}{2264}%
+\pdfglyphtounicode{greaterequal}{2265}%
+\pdfglyphtounicode{propersubset}{2282}%
+\pdfglyphtounicode{propersuperset}{2283}%
+\pdfglyphtounicode{notsubset}{2284}%
+\pdfglyphtounicode{reflexsubset}{2286}%
+\pdfglyphtounicode{reflexsuperset}{2287}%
+\pdfglyphtounicode{circleplus}{2295}%
+\pdfglyphtounicode{circlemultiply}{2297}%
+\pdfglyphtounicode{perpendicular}{22A5}%
+\pdfglyphtounicode{dotmath}{22C5}%
+\pdfglyphtounicode{house}{2302}%
+\pdfglyphtounicode{revlogicalnot}{2310}%
+\pdfglyphtounicode{integraltp}{2320}%
+\pdfglyphtounicode{integralbt}{2321}%
+\pdfglyphtounicode{angleleft}{2329}%
+\pdfglyphtounicode{angleright}{232A}%
+\pdfglyphtounicode{SF100000}{2500}%
+\pdfglyphtounicode{SF110000}{2502}%
+\pdfglyphtounicode{SF10000}{250C}%
+\pdfglyphtounicode{SF30000}{2510}%
+\pdfglyphtounicode{SF20000}{2514}%
+\pdfglyphtounicode{SF40000}{2518}%
+\pdfglyphtounicode{SF80000}{251C}%
+\pdfglyphtounicode{SF90000}{2524}%
+\pdfglyphtounicode{SF60000}{252C}%
+\pdfglyphtounicode{SF70000}{2534}%
+\pdfglyphtounicode{SF50000}{253C}%
+\pdfglyphtounicode{SF430000}{2550}%
+\pdfglyphtounicode{SF240000}{2551}%
+\pdfglyphtounicode{SF510000}{2552}%
+\pdfglyphtounicode{SF520000}{2553}%
+\pdfglyphtounicode{SF390000}{2554}%
+\pdfglyphtounicode{SF220000}{2555}%
+\pdfglyphtounicode{SF210000}{2556}%
+\pdfglyphtounicode{SF250000}{2557}%
+\pdfglyphtounicode{SF500000}{2558}%
+\pdfglyphtounicode{SF490000}{2559}%
+\pdfglyphtounicode{SF380000}{255A}%
+\pdfglyphtounicode{SF280000}{255B}%
+\pdfglyphtounicode{SF270000}{255C}%
+\pdfglyphtounicode{SF260000}{255D}%
+\pdfglyphtounicode{SF360000}{255E}%
+\pdfglyphtounicode{SF370000}{255F}%
+\pdfglyphtounicode{SF420000}{2560}%
+\pdfglyphtounicode{SF190000}{2561}%
+\pdfglyphtounicode{SF200000}{2562}%
+\pdfglyphtounicode{SF230000}{2563}%
+\pdfglyphtounicode{SF470000}{2564}%
+\pdfglyphtounicode{SF480000}{2565}%
+\pdfglyphtounicode{SF410000}{2566}%
+\pdfglyphtounicode{SF450000}{2567}%
+\pdfglyphtounicode{SF460000}{2568}%
+\pdfglyphtounicode{SF400000}{2569}%
+\pdfglyphtounicode{SF540000}{256A}%
+\pdfglyphtounicode{SF530000}{256B}%
+\pdfglyphtounicode{SF440000}{256C}%
+\pdfglyphtounicode{upblock}{2580}%
+\pdfglyphtounicode{dnblock}{2584}%
+\pdfglyphtounicode{block}{2588}%
+\pdfglyphtounicode{lfblock}{258C}%
+\pdfglyphtounicode{rtblock}{2590}%
+\pdfglyphtounicode{ltshade}{2591}%
+\pdfglyphtounicode{shade}{2592}%
+\pdfglyphtounicode{dkshade}{2593}%
+\pdfglyphtounicode{filledbox}{25A0}%
+\pdfglyphtounicode{H22073}{25A1}%
+\pdfglyphtounicode{H18543}{25AA}%
+\pdfglyphtounicode{H18551}{25AB}%
+\pdfglyphtounicode{filledrect}{25AC}%
+\pdfglyphtounicode{triagup}{25B2}%
+\pdfglyphtounicode{triagrt}{25BA}%
+\pdfglyphtounicode{triagdn}{25BC}%
+\pdfglyphtounicode{triaglf}{25C4}%
+\pdfglyphtounicode{lozenge}{25CA}%
+\pdfglyphtounicode{circle}{25CB}%
+\pdfglyphtounicode{H18533}{25CF}%
+\pdfglyphtounicode{invbullet}{25D8}%
+\pdfglyphtounicode{invcircle}{25D9}%
+\pdfglyphtounicode{openbullet}{25E6}%
+\pdfglyphtounicode{smileface}{263A}%
+\pdfglyphtounicode{invsmileface}{263B}%
+\pdfglyphtounicode{sun}{263C}%
+\pdfglyphtounicode{female}{2640}%
+\pdfglyphtounicode{male}{2642}%
+\pdfglyphtounicode{spade}{2660}%
+\pdfglyphtounicode{club}{2663}%
+\pdfglyphtounicode{heart}{2665}%
+\pdfglyphtounicode{diamond}{2666}%
+\pdfglyphtounicode{musicalnote}{266A}%
+\pdfglyphtounicode{musicalnotedbl}{266B}%
+%
+\endinput
diff --git a/tex/context/base/pdfr-ec.mkii b/tex/context/base/pdfr-ec.mkii
new file mode 100644
index 000000000..b6604984c
--- /dev/null
+++ b/tex/context/base/pdfr-ec.mkii
@@ -0,0 +1,145 @@
+%D \module
+%D [ file=pdfr-ec,
+%D version=2005.07.27,
+%D title=\CONTEXT\ PDF Font Resources,
+%D subtitle=EC encoding,
+%D author={Vladimir Volovich / Taco Hoekwater},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 vector is derived (but reformatted a bit) from
+%D the one in \LaTeX's CMap package
+
+\startpdffontresource[ec]
+/CIDInit /ProcSet findresource begin
+12 dict begin
+ begincmap
+ /CIDSystemInfo
+ << /Registry (TeX)
+ /Ordering (T1)
+ /Supplement 0
+ >> def
+ /CMapName /TeX-T1-0 def
+ /CMapType 2 def
+ 1 begincodespacerange
+ <00>
+ endcodespacerange
+ 10 beginbfrange
+ <0E> <0F> <2039>
+ <10> <12> <201C>
+ <15> <16> <2013>
+ <21> <26> <0021>
+ <28> <5F> <0028>
+ <61> <7E> <0061>
+ <00C0>
+ <00D8>
+ <00E0>
+ <00F8>
+ endbfrange
+ 95 beginbfchar
+ <00> <0060>
+ <01> <00B4>
+ <02> <02C6>
+ <03> <02DC>
+ <04> <00A8>
+ <05> <02DD>
+ <06> <02DA>
+ <07> <02C7>
+ <08> <02D8>
+ <09> <00AF>
+ <0A> <02D9>
+ <0B> <00B8>
+ <0C> <02DB>
+ <0D> <201A>
+ <13> <00AB>
+ <14> <00BB>
+ <17> <200C>
+ <19> <0131>
+ <1B> <00660066>
+ <1C> <00660069>
+ <1D> <0066006C>
+ <1E> <006600660069>
+ <1F> <00660066006C>
+ <20> <2423>
+ <27> <2019>
+ <60> <2018>
+ <7F> <002D>
+ <80> <0102>
+ <81> <0104>
+ <82> <0106>
+ <83> <010C>
+ <84> <010E>
+ <85> <011A>
+ <86> <0118>
+ <87> <011E>
+ <88> <0139>
+ <89> <013D>
+ <8A> <0141>
+ <8B> <0143>
+ <8C> <0147>
+ <8D> <014A>
+ <8E> <0150>
+ <8F> <0154>
+ <90> <0158>
+ <91> <015A>
+ <92> <0160>
+ <93> <015E>
+ <94> <0164>
+ <95> <021A>
+ <96> <0170>
+ <97> <016E>
+ <98> <0178>
+ <99> <0179>
+ <9A> <017D>
+ <9B> <017B>
+ <9C> <0132>
+ <9D> <0130>
+ <9E> <0111>
+ <9F> <00A7>
+ <0103>
+ <0105>
+ <0107>
+ <010D>
+ <010F>
+ <011B>
+ <0119>
+ <011F>
+ <013A>
+ <013E>
+ <0142>
+ <0144>
+ <0148>
+ <014B>
+ <0151>
+ <0155>
+ <0159>
+ <015B>
+ <0161>
+ <015F>
+ <0165>
+ <021B>
+ <0171>
+ <016F>
+ <00FF>
+ <017A>
+ <017E>
+ <017C>
+ <0133>
+ <00A1>
+ <00BF>
+ <00A3>
+ <0152>
+ <00530053>
+ <0153>
+ <00DF>
+ endbfchar
+ endcmap
+CMapName currentdict /CMap defineresource pop end
+end
+\stoppdffontresource
+
+\endinput
diff --git a/tex/context/base/pdfr-il2.mkii b/tex/context/base/pdfr-il2.mkii
new file mode 100644
index 000000000..70bcb25da
--- /dev/null
+++ b/tex/context/base/pdfr-il2.mkii
@@ -0,0 +1,233 @@
+%D \module
+%D [ file=pdfr-il2,
+%D version=2000.12.10,
+%D title=\CONTEXT\ PDF Font Resources,
+%D subtitle=ISO Latin 2,
+%D author={Ondrej Koala Vacha, Hans Hagen},
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 vector is derived (but reformatted a bit) from a
+%D sample send to me by Petr Ferdus. There was some Czech
+%D comment in which I could recognize the name of Ondrej
+%D Koala Vacha. More information on setting up such a vector
+%D can be found in the \PDF\ reference manual.
+
+\startpdffontresource[il2]
+/CIDInit /ProcSet findresource begin
+12 dict begin
+ begincmap
+ /CIDSystemInfo
+ << /Registry (Adobe)
+ /Ordering (T1UV)
+ /Supplement 0
+ >> def
+ /CMapName /Adobe-Identity-UCS def
+ /CMapType 1 def
+ 1 begincodespacerange
+ <00>
+ endcodespacerange
+ %%FontSpecificEncoding
+ 191 beginbfrange
+ <20> <20> <0020> % space dec: 32 oct:040 hex:20
+ <21> <21> <0021> % exclam dec: 33 oct:041 hex:21
+ <22> <22> <0022> % quotedbl dec: 34 oct:042 hex:22
+ <23> <23> <0023> % numbersign dec: 35 oct:043 hex:23
+ <24> <24> <0024> % dollar dec: 36 oct:044 hex:24
+ <25> <25> <0025> % percent dec: 37 oct:045 hex:25
+ <26> <26> <0026> % ampersand dec: 38 oct:046 hex:26
+ <27> <27> <0027> % quotesingle dec: 39 oct:047 hex:27
+ <28> <28> <0028> % parenleft dec: 40 oct:050 hex:28
+ <29> <29> <0029> % parenright dec: 41 oct:051 hex:29
+ <2a> <2a> <002a> % asterisk dec: 42 oct:052 hex:2a
+ <2b> <2b> <002b> % plus dec: 43 oct:053 hex:2b
+ <2c> <2c> <002c> % comma dec: 44 oct:054 hex:2c
+ <2d> <2d> <002d> % hyphen dec: 45 oct:055 hex:2d
+ <2e> <2e> <002e> % period dec: 46 oct:056 hex:2e
+ <2f> <2f> <002f> % slash dec: 47 oct:057 hex:2f
+ <30> <30> <0030> % zero dec: 48 oct:060 hex:30
+ <31> <31> <0031> % one dec: 49 oct:061 hex:31
+ <32> <32> <0032> % two dec: 50 oct:062 hex:32
+ <33> <33> <0033> % three dec: 51 oct:063 hex:33
+ <34> <34> <0034> % four dec: 52 oct:064 hex:34
+ <35> <35> <0035> % five dec: 53 oct:065 hex:35
+ <36> <36> <0036> % six dec: 54 oct:066 hex:36
+ <37> <37> <0037> % seven dec: 55 oct:067 hex:37
+ <38> <38> <0038> % eight dec: 56 oct:070 hex:38
+ <39> <39> <0039> % nine dec: 57 oct:071 hex:39
+ <3a> <3a> <003a> % colon dec: 58 oct:072 hex:3a
+ <3b> <3b> <003b> % semicolon dec: 59 oct:073 hex:3b
+ <3c> <3c> <003c> % less dec: 60 oct:074 hex:3c
+ <3d> <3d> <003d> % equal dec: 61 oct:075 hex:3d
+ <3e> <3e> <003e> % greater dec: 62 oct:076 hex:3e
+ <3f> <3f> <003f> % question dec: 63 oct:077 hex:3f
+ <40> <40> <0040> % at dec: 64 oct:100 hex:40
+ <41> <41> <0041> % A dec: 65 oct:101 hex:41
+ <42> <42> <0042> % B dec: 66 oct:102 hex:42
+ <43> <43> <0043> % C dec: 67 oct:103 hex:43
+ <44> <44> <0044> % D dec: 68 oct:104 hex:44
+ <45> <45> <0045> % E dec: 69 oct:105 hex:45
+ <46> <46> <0046> % F dec: 70 oct:106 hex:46
+ <47> <47> <0047> % G dec: 71 oct:107 hex:47
+ <48> <48> <0048> % H dec: 72 oct:110 hex:48
+ <49> <49> <0049> % I dec: 73 oct:111 hex:49
+ <4a> <4a> <004a> % J dec: 74 oct:112 hex:4a
+ <4b> <4b> <004b> % K dec: 75 oct:113 hex:4b
+ <4c> <4c> <004c> % L dec: 76 oct:114 hex:4c
+ <4d> <4d> <004d> % M dec: 77 oct:115 hex:4d
+ <4e> <4e> <004e> % N dec: 78 oct:116 hex:4e
+ <4f> <4f> <004f> % O dec: 79 oct:117 hex:4f
+ <50> <50> <0050> % P dec: 80 oct:120 hex:50
+ <51> <51> <0051> % Q dec: 81 oct:121 hex:51
+ <52> <52> <0052> % R dec: 82 oct:122 hex:52
+ <53> <53> <0053> % S dec: 83 oct:123 hex:53
+ <54> <54> <0054> % T dec: 84 oct:124 hex:54
+ <55> <55> <0055> % U dec: 85 oct:125 hex:55
+ <56> <56> <0056> % V dec: 86 oct:126 hex:56
+ <57> <57> <0057> % W dec: 87 oct:127 hex:57
+ <58> <58> <0058> % X dec: 88 oct:130 hex:58
+ <59> <59> <0059> % Y dec: 89 oct:131 hex:59
+ <5a> <5a> <005a> % Z dec: 90 oct:132 hex:5a
+ <5b> <5b> <005b> % bracketleft dec: 91 oct:133 hex:5b
+ <5c> <5c> <005c> % backslash dec: 92 oct:134 hex:5c
+ <5d> <5d> <005d> % bracketright dec: 93 oct:135 hex:5d
+ <5e> <5e> <005e> % asciicircum dec: 94 oct:136 hex:5e
+ <5f> <5f> <005f> % underscore dec: 95 oct:137 hex:5f
+ <60> <60> <0060> % grave dec: 96 oct:140 hex:60
+ <61> <61> <0061> % a dec: 97 oct:141 hex:61
+ <62> <62> <0062> % b dec: 98 oct:142 hex:62
+ <63> <63> <0063> % c dec: 99 oct:143 hex:63
+ <64> <64> <0064> % d dec:100 oct:144 hex:64
+ <65> <65> <0065> % e dec:101 oct:145 hex:65
+ <66> <66> <0066> % f dec:102 oct:146 hex:66
+ <67> <67> <0067> % g dec:103 oct:147 hex:67
+ <68> <68> <0068> % h dec:104 oct:150 hex:68
+ <69> <69> <0069> % i dec:105 oct:151 hex:69
+ <6a> <6a> <006a> % j dec:106 oct:152 hex:6a
+ <6b> <6b> <006b> % k dec:107 oct:153 hex:6b
+ <6c> <6c> <006c> % l dec:108 oct:154 hex:6c
+ <6d> <6d> <006d> % m dec:109 oct:155 hex:6d
+ <6e> <6e> <006e> % n dec:110 oct:156 hex:6e
+ <6f> <6f> <006f> % o dec:111 oct:157 hex:6f
+ <70> <70> <0070> % p dec:112 oct:160 hex:70
+ <71> <71> <0071> % q dec:113 oct:161 hex:71
+ <72> <72> <0072> % r dec:114 oct:162 hex:72
+ <73> <73> <0073> % s dec:115 oct:163 hex:73
+ <74> <74> <0074> % t dec:116 oct:164 hex:74
+ <75> <75> <0075> % u dec:117 oct:165 hex:75
+ <76> <76> <0076> % v dec:118 oct:166 hex:76
+ <77> <77> <0077> % w dec:119 oct:167 hex:77
+ <78> <78> <0078> % x dec:120 oct:170 hex:78
+ <79> <79> <0079> % y dec:121 oct:171 hex:79
+ <7a> <7a> <007a> % z dec:122 oct:172 hex:7a
+ <7b> <7b> <007b> % braceleft dec:123 oct:173 hex:7b
+ <7c> <7c> <007c> % bar dec:124 oct:174 hex:7c
+ <7d> <7d> <007d> % braceright dec:125 oct:175 hex:7d
+ <7e> <7e> <007e> % asciitilde dec:126 oct:176 hex:7e
+ <00a0> % nbspace dec:160 oct:240 hex:a0
+ <0104> % Aogonek dec:161 oct:241 hex:a1
+ <00a2> % breve dec:162 oct:242 hex:a2
+ <00a3> % Lslash dec:163 oct:243 hex:a3
+ <00a4> % currency dec:164 oct:244 hex:a4
+ <013d> % Lcaron dec:165 oct:245 hex:a5
+ <015a> % Sacute dec:166 oct:246 hex:a6
+ <00a7> % section dec:167 oct:247 hex:a7
+ <00a8> % dieresis dec:168 oct:250 hex:a8
+ <0160> % Scaron dec:169 oct:251 hex:a9
+ <015e> % Scedilla dec:170 oct:252 hex:aa
+ <0164> % Tcaron dec:171 oct:253 hex:ab
+ <0179> % Zacute dec:172 oct:254 hex:ac
+ <00ad> % sfthyphen dec:173 oct:255 hex:ad
+ <017d> % Zcaron dec:174 oct:256 hex:ae
+ <00af> % Zdotaccent dec:175 oct:257 hex:af
+ <00b0> % ring dec:176 oct:260 hex:b0
+ <0105> % aogonek dec:177 oct:261 hex:b1
+ <00b2> % ogonek dec:178 oct:262 hex:b2
+ <00b3> % lslash dec:179 oct:263 hex:b3
+