From d1faffcd5d92925a6c5e66ebb72b4c8dcfae236f Mon Sep 17 00:00:00 2001
From: Context Git Mirror Bot 
Date: Thu, 17 Dec 2015 16:15:07 +0100
Subject: 2015-12-17 15:59:00
---
 tex/context/base/anch-pgr.mkiv                     |   15 +-
 tex/context/base/anch-snc.mkiv                     |    2 +-
 tex/context/base/anch-tab.mkiv                     |    6 +-
 tex/context/base/attr-ini.mkiv                     |    4 +-
 tex/context/base/back-exp.lua                      |    3 +-
 tex/context/base/back-pdf.mkiv                     |    8 +-
 tex/context/base/buff-ini.mkiv                     |    2 +-
 tex/context/base/buff-ver.mkiv                     |   19 +-
 tex/context/base/catc-act.mkiv                     |    2 +
 tex/context/base/char-def.lua                      |    1 -
 tex/context/base/char-ini.lua                      |    2 +-
 tex/context/base/chem-str.mkiv                     |   42 +-
 tex/context/base/cldf-ini.lua                      |   60 +-
 tex/context/base/colo-ext.mkiv                     |    2 +-
 tex/context/base/colo-ini.mkiv                     |   37 +-
 tex/context/base/cont-new.mkiv                     |    2 +-
 tex/context/base/context-version.pdf               |  Bin 4190 -> 4171 bytes
 tex/context/base/context.mkiv                      |    2 +-
 tex/context/base/core-con.mkiv                     |    3 +-
 tex/context/base/core-env.mkiv                     |  211 +-
 tex/context/base/core-ini.mkiv                     |    4 +-
 tex/context/base/core-sys.mkiv                     |    3 +-
 tex/context/base/core-uti.mkiv                     |    2 +-
 tex/context/base/enco-ini.mkiv                     |    2 +-
 tex/context/base/file-mod.mkvi                     |    9 +-
 tex/context/base/font-agl.lua                      |   99 +-
 tex/context/base/font-con.lua                      |    2 +
 tex/context/base/font-ctx.lua                      |    6 +-
 tex/context/base/font-dsp.lua                      |   16 +-
 tex/context/base/font-emp.mkvi                     |    2 +-
 tex/context/base/font-fea.mkvi                     |    7 +-
 tex/context/base/font-fil.mkvi                     |  195 +-
 tex/context/base/font-ini.mkvi                     |  121 +-
 tex/context/base/font-inj.lua                      |   60 +-
 tex/context/base/font-map.lua                      |   66 +-
 tex/context/base/font-mat.mkvi                     |   63 +-
 tex/context/base/font-nod.lua                      |    6 +-
 tex/context/base/font-ota.lua                      |    5 +-
 tex/context/base/font-otd.lua                      |   48 +-
 tex/context/base/font-oti.lua                      |   69 +-
 tex/context/base/font-otj.lua                      |  675 ++--
 tex/context/base/font-otl.lua                      |    2 +-
 tex/context/base/font-otn.lua                      |   91 +-
 tex/context/base/font-otr.lua                      |    3 +-
 tex/context/base/font-ots.lua                      |  790 ++--
 tex/context/base/font-ott.lua                      |  233 +-
 tex/context/base/font-pre.mkiv                     |    6 +-
 tex/context/base/font-sel.mkvi                     |    3 +-
 tex/context/base/font-sty.mkvi                     |   18 +-
 tex/context/base/font-sym.mkvi                     |   12 +-
 tex/context/base/font-tra.mkiv                     |    4 +-
 tex/context/base/grph-epd.mkiv                     |    2 +-
 tex/context/base/grph-fig.mkiv                     |   24 +-
 tex/context/base/grph-inc.mkiv                     |   18 +-
 tex/context/base/grph-trf.mkiv                     |   32 +-
 tex/context/base/lang-hyp.lua                      |    8 +-
 tex/context/base/lang-ini.lua                      |   74 +-
 tex/context/base/lang-ini.mkiv                     |  117 +-
 tex/context/base/lang-lab.mkiv                     |   71 +-
 tex/context/base/lang-mis.mkiv                     |  108 +-
 tex/context/base/luat-ini.mkiv                     |   10 +-
 tex/context/base/lxml-ini.mkiv                     |   11 +-
 tex/context/base/lxml-tex.lua                      |    2 +-
 tex/context/base/m-oldotf.mkiv                     |    2 +-
 tex/context/base/math-ali.mkiv                     |    4 +-
 tex/context/base/math-arr.mkiv                     |    2 +-
 tex/context/base/math-def.mkiv                     |    2 +-
 tex/context/base/math-fen.mkiv                     |  103 +-
 tex/context/base/math-ini.mkiv                     |  194 +-
 tex/context/base/math-noa.lua                      |    5 +-
 tex/context/base/math-rad.mkvi                     |    8 +-
 tex/context/base/math-tag.lua                      |    3 +-
 tex/context/base/meta-ini.mkiv                     |   40 +-
 tex/context/base/meta-pdf.mkiv                     |    4 +-
 tex/context/base/meta-pdh.mkiv                     |   20 +-
 tex/context/base/meta-tex.mkiv                     |    2 +-
 tex/context/base/mlib-pdf.mkiv                     |    8 +-
 tex/context/base/mlib-pps.mkiv                     |   22 +-
 tex/context/base/mult-aux.mkiv                     |   44 +-
 tex/context/base/mult-def.mkiv                     |    7 +-
 tex/context/base/mult-dim.mkvi                     |   53 +-
 tex/context/base/mult-low.lua                      |    5 +
 tex/context/base/mult-prm.lua                      |   28 +
 tex/context/base/node-acc.lua                      |   14 +-
 tex/context/base/node-bck.mkiv                     |   19 +-
 tex/context/base/node-fin.lua                      |   32 +
 tex/context/base/node-fin.mkiv                     |    8 +-
 tex/context/base/node-fnt.lua                      |  140 +-
 tex/context/base/node-ini.lua                      |  310 +-
 tex/context/base/node-inj.lua                      |  603 ---
 tex/context/base/node-met.lua                      |   46 +-
 tex/context/base/node-nut.lua                      |  110 +-
 tex/context/base/node-pro.lua                      |   69 +-
 tex/context/base/node-ref.lua                      |   14 +-
 tex/context/base/node-res.lua                      |  110 +-
 tex/context/base/node-rul.mkiv                     |   19 +-
 tex/context/base/node-tra.lua                      |   90 +-
 tex/context/base/node-tst.lua                      |    7 +-
 tex/context/base/node-typ.lua                      |   53 +-
 tex/context/base/pack-bck.mkvi                     |    6 +-
 tex/context/base/pack-box.mkiv                     |   91 +-
 tex/context/base/pack-com.mkiv                     |   16 +-
 tex/context/base/pack-cut.mkiv                     |    4 +-
 tex/context/base/pack-fen.mkiv                     |   16 +-
 tex/context/base/pack-lyr.mkiv                     |  123 +-
 tex/context/base/pack-obj.lua                      |    2 +-
 tex/context/base/pack-obj.mkiv                     |    6 +-
 tex/context/base/pack-rul.mkiv                     |  172 +-
 tex/context/base/page-app.mkiv                     |    4 +-
 tex/context/base/page-bck.mkiv                     |   30 +-
 tex/context/base/page-box.mkvi                     |   32 +-
 tex/context/base/page-brk.mkiv                     |   34 +-
 tex/context/base/page-com.mkiv                     |    4 +-
 tex/context/base/page-flt.mkiv                     |    4 +-
 tex/context/base/page-grd.mkiv                     |    4 +-
 tex/context/base/page-imp.mkiv                     |   73 +-
 tex/context/base/page-inf.mkiv                     |    4 +-
 tex/context/base/page-ini.mkiv                     |    4 +-
 tex/context/base/page-lay.mkiv                     |   61 +-
 tex/context/base/page-lin.mkvi                     |   16 +-
 tex/context/base/page-mak.mkvi                     |    2 +-
 tex/context/base/page-mix.lua                      |    9 +-
 tex/context/base/page-mix.mkiv                     |   16 +-
 tex/context/base/page-mrk.mkiv                     |   15 +-
 tex/context/base/page-one.mkiv                     |   14 +-
 tex/context/base/page-otr.lua                      |   12 +
 tex/context/base/page-otr.mkvi                     |   11 +-
 tex/context/base/page-sel.mkvi                     |    4 +-
 tex/context/base/page-set.mkiv                     |    6 +-
 tex/context/base/page-sid.mkiv                     |   12 +-
 tex/context/base/page-txt.mkvi                     |   26 +-
 tex/context/base/phys-dim.mkiv                     |   23 +-
 tex/context/base/publ-dat.lua                      |    5 +-
 tex/context/base/publ-imp-apa.lua                  |   26 +-
 tex/context/base/publ-imp-apa.mkvi                 |   27 +-
 tex/context/base/publ-ini.mkiv                     |    2 +-
 tex/context/base/scrn-fld.mkvi                     |   10 +-
 tex/context/base/scrp-cjk.lua                      |    2 +-
 tex/context/base/spac-adj.mkiv                     |    2 +-
 tex/context/base/spac-ali.lua                      |    2 +-
 tex/context/base/spac-ali.mkiv                     |   79 +-
 tex/context/base/spac-hor.mkiv                     |   70 +-
 tex/context/base/spac-pag.mkiv                     |    2 +-
 tex/context/base/spac-prf.lua                      |   26 +-
 tex/context/base/spac-ver.lua                      |  146 +-
 tex/context/base/spac-ver.mkiv                     |  163 +-
 tex/context/base/status-files.pdf                  |  Bin 24446 -> 24365 bytes
 tex/context/base/status-lua.pdf                    |  Bin 257653 -> 257681 bytes
 tex/context/base/status-mkiv.lua                   |   12 +-
 tex/context/base/strc-flt.mkvi                     |  198 +-
 tex/context/base/strc-ind.mkiv                     |    6 +
 tex/context/base/strc-ini.lua                      |    1 -
 tex/context/base/strc-itm.mkvi                     |   40 +-
 tex/context/base/strc-lnt.mkvi                     |   10 +-
 tex/context/base/strc-lst.mkvi                     |   97 +-
 tex/context/base/strc-mar.lua                      |    4 +-
 tex/context/base/strc-mat.mkiv                     |   10 +-
 tex/context/base/strc-not.mkvi                     |   14 +-
 tex/context/base/strc-num.mkiv                     |   14 +-
 tex/context/base/strc-ref.mkvi                     |   36 +-
 tex/context/base/strc-ren.mkiv                     |    6 +-
 tex/context/base/strc-sec.mkiv                     |    3 +-
 tex/context/base/strc-syn.mkiv                     |    2 +
 tex/context/base/supp-box.mkiv                     |  158 +-
 tex/context/base/symb-ini.mkiv                     |   11 +-
 tex/context/base/syst-aux.lua                      |  247 ++
 tex/context/base/syst-aux.mkiv                     |  723 ++--
 tex/context/base/syst-ini.mkii                     |    1 -
 tex/context/base/syst-ini.mkiv                     |   11 +-
 tex/context/base/syst-lua.lua                      |   51 -
 tex/context/base/tabl-mis.mkiv                     |    2 +-
 tex/context/base/tabl-ntb.mkiv                     |  217 +-
 tex/context/base/tabl-tab.mkiv                     |    2 +-
 tex/context/base/tabl-tbl.mkiv                     |  317 +-
 tex/context/base/tabl-tsp.mkiv                     |    2 +-
 tex/context/base/toks-ini.lua                      |   15 +-
 tex/context/base/trac-inf.lua                      |    6 +-
 tex/context/base/trac-log.lua                      |    4 +
 tex/context/base/trac-vis.lua                      |  299 +-
 tex/context/base/trac-vis.mkiv                     |   34 +
 tex/context/base/type-ini.mkvi                     |   22 +-
 tex/context/base/typo-cln.lua                      |    2 +-
 tex/context/base/typo-dha.lua                      |    7 +-
 tex/context/base/typo-fln.mkiv                     |    2 +-
 tex/context/base/typo-krn.lua                      |   12 +-
 tex/context/base/typo-lin.lua                      |    8 +-
 tex/context/base/typo-mar.lua                      |    2 +-
 tex/context/base/typo-pag.lua                      |    2 +-
 tex/context/base/typo-sus.lua                      |    4 +-
 tex/context/base/typo-tal.lua                      |    2 -
 tex/context/base/typo-wrp.lua                      |    4 +-
 tex/context/base/util-prs.lua                      |   11 +-
 tex/context/base/xetx-chr.mkii                     |   20 +-
 tex/context/base/xetx-cls.mkii                     |  269 +-
 tex/context/base/xetx-utf.mkii                     |  432 ++-
 tex/generic/context/luatex/luatex-basics-nod.lua   |   31 +-
 tex/generic/context/luatex/luatex-fonts-def.lua    |    2 +-
 tex/generic/context/luatex/luatex-fonts-inj.lua    | 1152 ------
 tex/generic/context/luatex/luatex-fonts-merged.lua |  277 +-
 tex/generic/context/luatex/luatex-fonts-ota.lua    |   30 +-
 tex/generic/context/luatex/luatex-fonts-otn.lua    | 3848 --------------------
 tex/generic/context/luatex/luatex-fonts.lua        |    6 +-
 tex/generic/context/luatex/luatex-languages.lua    |   15 +-
 tex/generic/context/luatex/luatex-languages.tex    |    2 +
 tex/generic/context/luatex/luatex-pdf.tex          |    2 -
 205 files changed, 6399 insertions(+), 9458 deletions(-)
 delete mode 100644 tex/context/base/node-inj.lua
 create mode 100644 tex/context/base/page-otr.lua
 delete mode 100644 tex/generic/context/luatex/luatex-fonts-inj.lua
 delete mode 100644 tex/generic/context/luatex/luatex-fonts-otn.lua
(limited to 'tex')
diff --git a/tex/context/base/anch-pgr.mkiv b/tex/context/base/anch-pgr.mkiv
index 56ff656d9..a7ad26dff 100644
--- a/tex/context/base/anch-pgr.mkiv
+++ b/tex/context/base/anch-pgr.mkiv
@@ -256,14 +256,15 @@
 \def\MPoverlayanchor#1{\MPpos\MPanchorid}
 
 \def\anch_positions_overlay_compose
-  {\vbox to \d_overlay_height
+  {\vpack to \d_overlay_height
      {%\writestatus{!!!}{\currentpositionoverlay/\MPanchoridentifier/\MPanchornumber}%
       \edef\MPanchorid{\currentpositionoverlay::\MPanchoridentifier:\MPanchornumber}% realpageno
     % \edef\MPanchor##1{\MPpos\MPanchorid}%
       \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
       \the\everyinsertpositionaction
       \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
-      \setbox\scratchbox\hbox to \d_overlay_width{\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
+      \setbox\scratchbox\hbox to \d_overlay_width
+        {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
       \ht\scratchbox\d_overlay_height
       \dp\scratchbox\zeropoint
       \anch_mark_tagged_box\scratchbox\MPanchorid % needs an hbox
@@ -289,12 +290,13 @@
    \endgroup}
 
 \def\anch_positions_region_overlay_compose
-  {\vbox to \d_overlay_height
+  {\vpack to \d_overlay_height
      {\let\MPanchorid\currentpositionregion
       \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
       \the\everyinsertpositionaction
       \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
-      \setbox\scratchbox\hbox to \d_overlay_width{\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
+      \setbox\scratchbox\hbox to \d_overlay_width
+        {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
       \ht\scratchbox\d_overlay_height
       \dp\scratchbox\zeropoint
       \box\scratchbox
@@ -411,7 +413,8 @@
    \anch_positions_meta_graphic_prepare
    \obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change
    \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments
-   \setbox\b_anch_positions_graphic\hbox{\ignorespaces\csname#1#2\endcsname\removelastspace}%
+   \setbox\b_anch_positions_graphic\hbox
+     {\ignorespaces\csname#1#2\endcsname\removelastspace}%
    \smashbox\b_anch_positions_graphic
    \box\b_anch_positions_graphic
    \endgroup}
@@ -421,7 +424,7 @@
    \setupMPvariables[#2][#1,#3]%
    \edef\currentmpvariableclass{#2}%
    \anch_positions_meta_graphic_prepare
-   \getvalue{\??positiongraphic#2}%
+   \csname\??positiongraphic#2\endcsname
    \endgroup}%
 
 \def\startMPpositionmethod#1#2\stopMPpositionmethod
diff --git a/tex/context/base/anch-snc.mkiv b/tex/context/base/anch-snc.mkiv
index 27769fbf9..d0d3a58d1 100644
--- a/tex/context/base/anch-snc.mkiv
+++ b/tex/context/base/anch-snc.mkiv
@@ -60,7 +60,7 @@
      \global\advance\csname\s!num:\s!syncpos:#1\endcsname\plusone
      \setsyncpositions{#1}%
      % option: geen w/h, alleen p 0 0 0 data
-     \setpositionplus{\s!syncpos:#1:\the\csname\s!num:\s!syncpos:#1\endcsname}{#2}\hbox{\strut}%
+     \setpositionplus{\s!syncpos:#1:\the\csname\s!num:\s!syncpos:#1\endcsname}{#2}\hpack{\strut}%
    \else
      \strut
    \fi}
diff --git a/tex/context/base/anch-tab.mkiv b/tex/context/base/anch-tab.mkiv
index da735b49d..7e0116cbf 100644
--- a/tex/context/base/anch-tab.mkiv
+++ b/tex/context/base/anch-tab.mkiv
@@ -184,7 +184,7 @@
 
 \def\tabulateEQpos
   {\setbox\scratchbox\hbox{\tabulateEQ}%
-   \hbox to \wd\scratchbox{\hss\kern\zeropoint\tabulatepos\hss}%
+   \hbox to \wd\scratchbox{\hss\kern\zeropoint\tabulatepos\hss}% hpack
    \kern-\wd\scratchbox
    \box\scratchbox}
 
@@ -371,11 +371,11 @@
    \dodoubleempty\anch_framed_indeed}
 
 \def\anch_framed_indeed[#1][#2]%
-  {\setbox\scratchbox\hbox
+  {\setbox\scratchbox\hpack
      {\scratchwidth \dimexpr\MPx{e:#1}-\MPx{b:#1}\relax
       \scratchdepth \dimexpr\MPy{b:#1}-\MPy{e:#1}+\MPd{e:#1}\relax
       \scratchheight\dimexpr\scratchdepth+\MPh{b:#1}\relax
-      \lower\scratchdepth\hbox
+      \lower\scratchdepth\hpack
         {\framed[\c!width=\scratchwidth,\c!height=\scratchheight,\c!offset=\v!overlay,#2]{}}}%
    \smashedbox\scratchbox
    \egroup}
diff --git a/tex/context/base/attr-ini.mkiv b/tex/context/base/attr-ini.mkiv
index ffed65bd7..3f0b7fb27 100644
--- a/tex/context/base/attr-ini.mkiv
+++ b/tex/context/base/attr-ini.mkiv
@@ -65,8 +65,8 @@
    \fi}
 
 \unexpanded\def\newattribute#1%
-  {\attr_basics_define_indeed\s!public[\strippedcsname#1][]%
-   \expandafter\let\expandafter#1\csname\??attributeid\strippedcsname#1\endcsname}
+  {\attr_basics_define_indeed\s!public[\csstring#1][]%
+   \expandafter\let\expandafter#1\csname\??attributeid\csstring#1\endcsname}
 
 % expandable so we can \edef them for speed
 
diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua
index 840a6d3e3..5390911bb 100644
--- a/tex/context/base/back-exp.lua
+++ b/tex/context/base/back-exp.lua
@@ -2696,8 +2696,7 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
             else
                 local subtype = getsubtype(n)
                 if subtype == userskip_code then
-                    local spec = getfield(n,"spec")
-                    if getfield(spec,"width") > threshold then
+                    if getfield(n,"width") > threshold then
                         if last and not somespace[currentcontent[nofcurrentcontent]] then
                             local a = getattr(n,a_tagged) or pat
                             if a == last then
diff --git a/tex/context/base/back-pdf.mkiv b/tex/context/base/back-pdf.mkiv
index cc21355e9..d74c4c569 100644
--- a/tex/context/base/back-pdf.mkiv
+++ b/tex/context/base/back-pdf.mkiv
@@ -46,7 +46,7 @@
 
 %D These are already set:
 
-\pdfhorigin 1 true in
+\pdfhorigin 1in
 \pdfvorigin \pdfhorigin
 
 %D These too and most of them will be protected as well:
@@ -164,10 +164,10 @@
   {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}}
 
 \unexpanded\def\dodotransformnextbox#1#2#3#4#5#6%
-  {\hbox
+  {\hpack
      {\kern #5\onebasepoint
       \raise#6\onebasepoint
-      \hbox
+      \hpack
         {\clf_pdfstartmatrix rx #1 sx #2 sy #3 ry #4\relax
          \box\nextbox
          \clf_pdfstopmatrix}}}
@@ -289,7 +289,7 @@
    \edef\dofill{\number#7}%
    \edef\mode{\number#8}%
    % no \ifcase, else \relax in pdfcode
-   \setbox\scratchbox\hbox
+   \setbox\scratchbox\hpack
      {\ifnum\dostroke\dofill>\zerocount
         \pdfliteral
           {q
diff --git a/tex/context/base/buff-ini.mkiv b/tex/context/base/buff-ini.mkiv
index 0d3d8b792..7cc6cdbd4 100644
--- a/tex/context/base/buff-ini.mkiv
+++ b/tex/context/base/buff-ini.mkiv
@@ -122,7 +122,7 @@
 
 \unexpanded\def\buff_stop#1%
   {\endgroup % (3 & 4 & 5 & 6)
-   \getvalue{#1}}
+   \csname#1\endcsname}
 
 % \installctxfunction\dopickupbuffer{commands.dopickupbuffer}
 
diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv
index 450d5164c..dbb675320 100644
--- a/tex/context/base/buff-ver.mkiv
+++ b/tex/context/base/buff-ver.mkiv
@@ -90,13 +90,9 @@
    \let\obeyedspace\specialobeyedspace
    \let\controlspace\specialcontrolspace
    \edef\p_buff_lines{\typeparameter\c!lines}%
-   \ifcsname\??typinglines\p_buff_lines\endcsname
-     \csname\??typinglines\p_buff_lines\endcsname
-   \fi
+   \begincsname\??typinglines\p_buff_lines\endcsname
    \edef\p_buff_space{\typeparameter\c!space}%
-   \ifcsname\??typingspace\p_buff_space\endcsname
-     \csname\??typingspace\p_buff_space\endcsname
-   \fi
+   \begincsname\??typingspace\p_buff_space\endcsname
    \relax\the\everyinitializeverbatim\relax}
 
 \unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
@@ -136,13 +132,9 @@
    \let\obeyedspace\specialobeyedspace
    \let\controlspace\specialcontrolspace
    \edef\p_buff_lines{\typingparameter\c!lines}%
-   \ifcsname\??typinglines\p_buff_lines\endcsname
-     \csname\??typinglines\p_buff_lines\endcsname
-   \fi
+   \begincsname\??typinglines\p_buff_lines\endcsname
    \edef\p_buff_space{\typingparameter\c!space}%
-   \ifcsname\??typingspace\p_buff_space\endcsname
-     \csname\??typingspace\p_buff_space\endcsname
-   \fi
+   \begincsname\??typingspace\p_buff_space\endcsname
    \relax\the\everyinitializeverbatim\relax}
 
 %D \macros
@@ -1001,7 +993,8 @@
 %    \let\next}
 
 \appendtoks
-    \def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize
+    %def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize
+    \def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize
     \def\tex #1{\letterbackslash#1}%
 \to \everysimplifycommands
 
diff --git a/tex/context/base/catc-act.mkiv b/tex/context/base/catc-act.mkiv
index 8c7935d4d..bd1ffd38d 100644
--- a/tex/context/base/catc-act.mkiv
+++ b/tex/context/base/catc-act.mkiv
@@ -16,6 +16,8 @@
 
 \unprotect
 
+% todo: \letcharcode=\something
+
 %D \macros
 %D   {installactivecharacter}
 
diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua
index 1d8946cbd..a525005f0 100644
--- a/tex/context/base/char-def.lua
+++ b/tex/context/base/char-def.lua
@@ -59305,7 +59305,6 @@ characters.data={
  [0x2061]={
   category="cf",
   comment="maybe: nulloperator",
-  contextname="relax",
   description="FUNCTION APPLICATION",
   direction="bn",
   linebreak="al",
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index 0a79051e8..b59c9db6d 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -1301,7 +1301,7 @@ if not characters.superscripts then
     if storage then
         storage.register("characters/superscripts", superscripts, "characters.superscripts")
         storage.register("characters/subscripts",   subscripts,   "characters.subscripts")
-        storage.register("characters/fractions",    fractions,   "characters.fractions")
+        storage.register("characters/fractions",    fractions,    "characters.fractions")
     end
 
 end
diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv
index cdbba6e2a..5b8c6a069 100644
--- a/tex/context/base/chem-str.mkiv
+++ b/tex/context/base/chem-str.mkiv
@@ -144,7 +144,7 @@
   {\dodoubleempty\chem_start}
 
 \def\chem_start[#1][#2]%
-  {\ifmmode\vcenter\else\vbox\fi
+  {\ifmmode\vcenter\else\vbox\fi % vpack ?
    \bgroup
    \synchronizestrut{\chemicalparameter\c!strut}%
    \dontcomplain
@@ -161,7 +161,7 @@
        {\edef\currentchemical{#1}}%
    \fi\fi
    \the\everystructurechemical
-   \setbox\b_chem_result\hbox\bgroup
+   \setbox\b_chem_result\hpack\bgroup
    \clf_startchemical
      width         {\chemicalparameter\c!width}%
      height        {\chemicalparameter\c!height}%
@@ -198,12 +198,12 @@
      [\c!frame=\chemicalparameter\c!frame,
       \c!rulethickness=\chemicalparameter\c!rulethickness,
       \c!framecolor=\chemicalparameter\c!framecolor]%
-     {\vbox{\box\b_chem_result\vss}}} % remove depth
+     {\vpack{\box\b_chem_result\vss}}} % remove depth
 
 \unexpanded\def\chem_framed_nop
   {\directlocalframed
      [\??chemicalframed]%
-     {\vbox{\box\b_chem_result\vss}}} % remove depth
+     {\vpack{\box\b_chem_result\vss}}} % remove depth
 
 \let\startstructurechemical\startchemical
 \let\stopstructurechemical \stopchemical
@@ -242,7 +242,7 @@
    \ignorespaces}
 
 \appendtoks
-    \setbox\b_chem_result\hbox{\raise\MPlly\box\b_chem_result}%
+    \setbox\b_chem_result\hpack{\raise\MPlly\box\b_chem_result}%
     \d_chem_width \wd\b_chem_result
     \d_chem_height\ht\b_chem_result
     \d_chem_depth \dp\b_chem_result
@@ -271,17 +271,17 @@
 \to \everystructurechemical
 
 \def\chem_add_texts
-  {\setbox2\hbox to \d_chem_width{\strut\hss\hbox{\strut\m_chem_mid_text}\hss}%
-   \setbox4\hbox to \d_chem_width{\strut\hss\hbox{\strut\m_chem_top_text}\hss}%
-   \setbox6\hbox to \d_chem_width{\strut\hss\hbox{\strut\m_chem_bot_text}\hss}%
-   \setbox\b_chem_result\hbox \bgroup
+  {\setbox2\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_mid_text}\hss}%
+   \setbox4\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_top_text}\hss}%
+   \setbox6\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_bot_text}\hss}%
+   \setbox\b_chem_result\hpack \bgroup
      \box\b_chem_result
      \hskip-\d_chem_width
-     \raise\d_chem_height\hbox{\lower\ht4\box4}%
+     \raise\d_chem_height\hpack{\lower\ht4\box4}%
      \hskip-\d_chem_width
      \lower.5\dimexpr\ht2-\dp2\relax\box2%
      \hskip-\d_chem_width
-     \lower\d_chem_depth \hbox{\raise\dp6\box6}%
+     \lower\d_chem_depth \hpack{\raise\dp6\box6}%
      \hss
    \egroup} % text on top of chemicals
 
@@ -333,7 +333,7 @@
   {\let\chem_box_visual_yes\hbox      \let\chem_box_visual_nop\relax    }
 
 \def\chem_top_construct#1#2#3#4%
-  {\hbox\bgroup
+  {\hpack\bgroup
    \setstrut
    \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
    \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
@@ -344,7 +344,7 @@
    \egroup}
 
 \def\chem_bottom_construct#1#2#3#4%
-  {\hbox\bgroup
+  {\hpack\bgroup
    \setstrut
    \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
    \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
@@ -355,14 +355,14 @@
    \egroup}
 
 \unexpanded\def\chemicalleft#1#2% redundant boxes thanks to visual
-  {\hbox\bgroup
+  {\hbox\bgroup % hpack ?
    \setstrut
    \llap{\chem_box_visual_nop{\strut#1}}%
    \chem_box_visual_nop{\strut#2}%
    \egroup}
 
 \unexpanded\def\chemicalright#1#2% redundant boxes thanks to visual
-  {\hbox\bgroup
+  {\hbox\bgroup % hpack ?
    \setstrut
    \chem_box_visual_yes{\strut#2}%
    \rlap{\chem_box_visual_nop{\strut#1}}%
@@ -442,7 +442,7 @@
 \unexpanded\def\chemicaloxidationseven{\chemicaloxidation\relax7}
 
 \unexpanded\def\chemicalbar
-  {\hbox \s!spread .5\emwidth \bgroup
+  {\hpack \s!spread .5\emwidth \bgroup
      \hss
      \vrule \s!height .9\strutht \s!depth .65\strutdp \s!width .1\exheight
      \hss
@@ -540,7 +540,7 @@
    \hbox{\usechemicalstyleandcolor\c!style\c!color\clf_inlinechemical{#1}}}
 
 \unexpanded\def\chemicalbondrule
-  {\hbox{\vrule\s!height.75\exheight\s!depth-\dimexpr.75\exheight-\linewidth\relax\s!width\emwidth\relax}}
+  {\hpack{\vrule\s!height.75\exheight\s!depth-\dimexpr.75\exheight-\linewidth\relax\s!width\emwidth\relax}}
 
 \definechemicalsymbol[i:space]       [\enspace\quad\enspace]
 \definechemicalsymbol[i:plus]        [\enspace\mathematics{+}\enspace]
@@ -549,8 +549,8 @@
 \definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightoverleftarrow{}{}}\enspace]
 \definechemicalsymbol[i:mesomeric]   [\enspace\mathematics{\xleftrightarrow{}{}}\enspace]
 \definechemicalsymbol[i:single]      [\chemicalbondrule]
-\definechemicalsymbol[i:double]      [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
-\definechemicalsymbol[i:triple]      [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:double]      [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:triple]      [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
 
 \unexpanded\def\chemicalsinglebond {\chemicalsymbol[i:single]}
 \unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:double]}
@@ -614,8 +614,8 @@
 \definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill]  % \chem_arrow_construct\xrightoverleftarrow
 \definechemicalsymbol[d:mesomeric]   [\leftarrowfill]           % \chem_arrow_construct\xleftrightarrow
 \definechemicalsymbol[d:single]      [\chemicalbondrule]
-\definechemicalsymbol[d:double]      [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
-\definechemicalsymbol[d:triple]      [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[d:double]      [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[d:triple]      [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
 \definechemicalsymbol[d:opencomplex] [\mathematics{\Bigg[}]     % not yet ok
 \definechemicalsymbol[d:closecomplex][\mathematics{\Bigg]}]     % not yet ok
 
diff --git a/tex/context/base/cldf-ini.lua b/tex/context/base/cldf-ini.lua
index f6a1ba849..62dbe67b3 100644
--- a/tex/context/base/cldf-ini.lua
+++ b/tex/context/base/cldf-ini.lua
@@ -903,23 +903,57 @@ else
 end
 
 local generics = { }  context.generics = generics
+local indexer  = nil
 
-local function indexer(parent,k)
-    if type(k) == "string" then
-        local c = "\\" .. tostring(generics[k] or k)
-        local f = function(first,...)
-            if first == nil then
-                flush(currentcatcodes,c)
-            else
-                return writer(parent,c,first,...)
+-- if environment.initex then
+
+    indexer = function(parent,k)
+        if type(k) == "string" then
+            local c = "\\" .. tostring(generics[k] or k)
+            local f = function(first,...)
+                if first == nil then
+                    flush(currentcatcodes,c)
+                else
+                    return writer(parent,c,first,...)
+                end
             end
+            parent[k] = f
+            return f
+        else
+            return context -- catch
         end
-        parent[k] = f
-        return f
-    else
-        return context -- catch
     end
-end
+
+-- else
+--
+--     local create   = token.create
+--     local twrite   = token.write
+--     local setmacro = token.set_macro
+--
+--     indexer = function(parent,k)
+--         if type(k) == "string" then
+--             local s = tostring(generics[k] or k)
+--             local t = create(s)
+--             if t.cmdname == "undefined_cs" then
+--                 report_cld("macro \\%s is not yet defined",s)
+--                 token.set_macro(s,"")
+--                 t = create(s)
+--             end
+--             local i = t.id
+--             local f = function(first,...)
+--                 twrite(t.tok) --= we need to keep t uncollected
+--                 if first ~= nil then
+--                     return writer(parent,first,...)
+--                 end
+--             end
+--             parent[k] = f
+--             return f
+--         else
+--             return context -- catch
+--         end
+--     end
+--
+-- end
 
 -- Potential optimization: after the first call we know if there will be an
 -- argument. Of course there is the side effect that for instance abuse like
diff --git a/tex/context/base/colo-ext.mkiv b/tex/context/base/colo-ext.mkiv
index c076fda9e..74ce2d3e5 100644
--- a/tex/context/base/colo-ext.mkiv
+++ b/tex/context/base/colo-ext.mkiv
@@ -30,7 +30,7 @@
 %D will negate the colors in box zero.
 
 \unexpanded\def\negatecolorbox#1% or just set attr of #1
-  {\setbox#1\hbox to \wd#1%
+  {\setbox#1\hpack to \wd#1%
      {\scratchdimen\wd#1\relax
       \startnegative % might change
       \blackrule[\c!color=\s!white,\c!height=\ht#1,\c!depth=\dp#1,\c!width=\scratchdimen]%
diff --git a/tex/context/base/colo-ini.mkiv b/tex/context/base/colo-ini.mkiv
index 1eb3d8d7e..937f85278 100644
--- a/tex/context/base/colo-ini.mkiv
+++ b/tex/context/base/colo-ini.mkiv
@@ -248,7 +248,7 @@
    \fi
    %
    \setfalse\c_colo_convert_gray
-   \getvalue{\??colorconversions\directcolorsparameter\c!conversion}% could be a nice \ifcsname
+   \begincsname\??colorconversions\directcolorsparameter\c!conversion\endcsname
    % too often:
    \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors{10}\v!rgb \fi
    \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors{10}\v!cmyk\fi
@@ -646,17 +646,20 @@
 \def\colo_helpers_activate_yes#1%
   {\edef\currentcolorname{#1}%
    \ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
-     \csname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
+    %\csname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
+     \lastnamedcs
      \csname\??transparencysetter\currentcolorprefix\currentcolorname\endcsname
    \else\ifcsname\??colorsetter\currentcolorname\endcsname
-     \csname\??colorsetter\currentcolorname\endcsname
+    %\csname\??colorsetter\currentcolorname\endcsname
+     \lastnamedcs
      \csname\??transparencysetter\currentcolorname\endcsname
    \fi\fi}
 
 \def\colo_helpers_activate_nop#1%
   {\edef\currentcolorname{#1}%
    \ifcsname\??colorsetter\currentcolorname\endcsname
-     \csname\??colorsetter\currentcolorname\endcsname
+    %\csname\??colorsetter\currentcolorname\endcsname
+     \lastnamedcs
      \csname\??transparencysetter\currentcolorname\endcsname
    \fi}
 
@@ -674,10 +677,12 @@
 \unexpanded\def\dousecurrentcolorparameter
   {\let\currentcolorname\currentcolorparameter % maybe only when success
    \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
-     \csname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
+    %\csname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
+     \lastnamedcs
      \csname\??transparencysetter\currentcolorprefix\currentcolorparameter\endcsname
    \else\ifcsname\??colorsetter\currentcolorparameter\endcsname
-     \csname\??colorsetter\currentcolorparameter\endcsname
+    %\csname\??colorsetter\currentcolorparameter\endcsname
+     \lastnamedcs
      \csname\??transparencysetter\currentcolorparameter\endcsname
    \fi\fi}
 
@@ -1018,10 +1023,15 @@
 \setvalue{\??colorattribute        currentcolor}{\the\attribute\colorattribute}        % for mpcolor
 \setvalue{\??transparencyattribute currentcolor}{\the\attribute\transparencyattribute} % for mpcolor
 
-\def\colo_helpers_inherited_current_ca#1{\csname\??colorattribute       \ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute       #1\endcsname#1\fi\fi\endcsname}
-\def\colo_helpers_inherited_current_cs#1{\csname\??colorsetter          \ifcsname\??colorsetter          \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorsetter          #1\endcsname#1\fi\fi\endcsname}
-\def\colo_helpers_inherited_current_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
-\def\colo_helpers_inherited_current_ts#1{\csname\??transparencysetter   \ifcsname\??transparencysetter   \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencysetter   #1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_ca#1{\csname\??colorattribute       \ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute       #1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_cs#1{\csname\??colorsetter          \ifcsname\??colorsetter          \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorsetter          #1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+%def\colo_helpers_inherited_current_ts#1{\csname\??transparencysetter   \ifcsname\??transparencysetter   \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencysetter   #1\endcsname#1\fi\fi\endcsname}
+
+\def\colo_helpers_inherited_current_ca#1{\ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorattribute       #1\endcsname\lastnamedcs\else\!!zerocount\fi\fi}
+\def\colo_helpers_inherited_current_cs#1{\ifcsname\??colorsetter          \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorsetter          #1\endcsname\lastnamedcs\else\fi\fi}
+\def\colo_helpers_inherited_current_ta#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi\fi}
+\def\colo_helpers_inherited_current_ts#1{\ifcsname\??transparencysetter   \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencysetter   #1\endcsname\lastnamedcs\else\fi\fi}
 
 %D Low level defs:
 
@@ -1078,10 +1088,13 @@
      \colo_helpers_inherited_current_ta{#1} }
 
 
-\def\thecolorattribute       #1{\number\csname\??colorattribute       \ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute       #1\endcsname#1\fi\fi\endcsname}
-\def\thetransparencyattribute#1{\number\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
 \def\thecolormodelattribute    {\the\attribute\colormodelattribute}
 
+%def\thecolorattribute       #1{\number\csname\??colorattribute       \ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute       #1\endcsname#1\fi\fi\endcsname}
+%def\thetransparencyattribute#1{\number\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+
+\def\thecolorattribute       #1{\number\ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??colorattribute       #1\endcsname\lastnamedcs\else\zerocount\fi\fi}
+\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\else\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi\fi}
 \def\internalspotcolorname   #1{\clf_spotcolorname  \thecolorattribute{#1} }
 \def\internalspotcolorparent #1{\clf_spotcolorparent\thecolorattribute{#1} }
 \def\internalspotcolorsize   #1{\clf_spotcolorvalue \thecolorattribute{#1} }
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index 57610f6bc..b48e9a499 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2015.11.19 19:13}
+\newcontextversion{2015.12.17 15:57}
 
 %D This file is loaded at runtime, thereby providing an excellent place for
 %D hacks, patches, extensions and new features.
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 0674945c2..6d20a25b5 100644
Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index 6beb784ac..4efa365de 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -39,7 +39,7 @@
 %D up and the dependencies are more consistent.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2015.11.19 19:13}
+\edef\contextversion{2015.12.17 15:57}
 \edef\contextkind   {beta}
 
 %D For those who want to use this:
diff --git a/tex/context/base/core-con.mkiv b/tex/context/base/core-con.mkiv
index cf4817cf9..1ca38ae14 100644
--- a/tex/context/base/core-con.mkiv
+++ b/tex/context/base/core-con.mkiv
@@ -598,7 +598,8 @@
 \setvalue{\??conversionwords\v!four }{4}
 \setvalue{\??conversionwords\v!five }{5}
 
-\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi}
+%def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi}
+\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\lastnamedcs\else#2\fi}
 
 % \defineconversion[ctx][c,o,n,t,e,x,t]
 %
diff --git a/tex/context/base/core-env.mkiv b/tex/context/base/core-env.mkiv
index 6217bb3c3..752eca784 100644
--- a/tex/context/base/core-env.mkiv
+++ b/tex/context/base/core-env.mkiv
@@ -62,22 +62,22 @@
 
 \unexpanded\def\setmode#1%
   {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
-   \csname\??mode#1\endcsname\enabledmode}
+   \lastnamedcs\enabledmode}
 
 \unexpanded\def\resetmode#1%
   {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
-   \csname\??mode#1\endcsname\disabledmode}
+   \lastnamedcs\disabledmode}
 
 \unexpanded\def\newsystemmode#1%
   {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi}
 
 \unexpanded\def\setsystemmode#1%
   {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
-   \csname\??mode\systemmodeprefix#1\endcsname\enabledmode}
+   \lastnamedcs\enabledmode}
 
 \unexpanded\def\resetsystemmode#1%
   {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
-   \csname\??mode\systemmodeprefix#1\endcsname\disabledmode}
+   \lastnamedcs\disabledmode}
 
 % \def\dosetsystemmode#1%
 %   {\csname\??mode\systemmodeprefix#1\endcsname\enabledmode}
@@ -117,18 +117,18 @@
 
 \def\syst_modes_prevent_indeed#1%
   {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
-   \syst_mode_prefix\csname\??mode#1\endcsname\preventedmode}
+   \syst_mode_prefix\lastnamedcs\preventedmode}
 
 \def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside
   {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
    \ifnum\csname\??mode#1\endcsname=\preventedmode \else
-     \syst_mode_prefix\csname\??mode#1\endcsname\enabledmode
+     \syst_mode_prefix\lastnamedcs\enabledmode
    \fi}
 
 \def\syst_modes_disable_indeed#1%
   {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
    \ifnum\csname\??mode#1\endcsname=\preventedmode \else
-     \syst_mode_prefix\csname\??mode#1\endcsname\disabledmode
+     \syst_mode_prefix\lastnamedcs\disabledmode
    \fi}
 
 %D If you do a lot of mode testing, it makes sense to define modes (or disable them
@@ -162,7 +162,8 @@
 
 \def\booleanmodevalue#1%
   {\ifcsname\??mode#1\endcsname
-     \ifcase\csname\??mode#1\endcsname
+    %\ifcase\csname\??mode#1\endcsname
+     \ifcase\lastnamedcs
        \s!false
      \or
        \s!true
@@ -175,36 +176,13 @@
 
 % check macros
 
-% For some reason the older version had an unprotect for grabbing the
-% mode list (only) which does not really make sense any more so that
-% has been removed. One should (un)protect at the outer level instead.
-
 \newconditional\c_checked_mode
 
 % one
 
-% \def\syst_modes_check_indeed#1%
-%   {\ifcsname\??mode#1\endcsname
-%      \ifcase\csname\??mode#1\endcsname\else
-%        \let\syst_modes_check_step\gobbleoneargument
-%      \fi
-%    \fi}
-%
-% \def\syst_modes_check#1#2#3%
-%   {\let\syst_modes_check_step\syst_modes_check_indeed
-%    \rawprocesscommacommand[#3]\syst_modes_check_step
-%    \ifx\syst_modes_check_step\gobbleoneargument
-%      \expandafter#1%
-%    \else
-%      \expandafter#2%
-%    \fi}
-
-% modes .. twice as fast on defined modes .. we could use definers and make it even faster
-% if needed
-
 \def\syst_modes_check_indeed#1%
   {\ifcsname\??mode#1\endcsname
-     \ifcase\csname\??mode#1\endcsname\else
+     \ifcase\lastnamedcs\else
        \let\syst_modes_check_step\gobbleoneargument
      \fi
    \fi}
@@ -219,7 +197,7 @@
    \fi}
 
 \def\syst_modes_check_yes#1#2#3%
-  {\ifcase\csname\??mode#3\endcsname
+  {\ifcase\lastnamedcs
      \expandafter#2%
    \or
      \expandafter#1%
@@ -227,7 +205,14 @@
      \expandafter#2%
    \fi}
 
-\def\syst_modes_check#1#2#3%
+\def\syst_modes_check_lr#1#2#3%
+  {\ifcsname\??mode#3\endcsname
+     \expandafter\syst_modes_check_yes
+   \else
+     \expandafter\syst_modes_check_nop
+   \fi#1#2{#3}}
+
+\def\syst_modes_check_ss#1#2[#3]%
   {\ifcsname\??mode#3\endcsname
      \expandafter\syst_modes_check_yes
    \else
@@ -238,7 +223,7 @@
 
 \def\syst_modes_check_all_indeed#1%
   {\ifcsname\??mode#1\endcsname
-     \ifcase\csname\??mode#1\endcsname
+     \ifcase\lastnamedcs
        \let\syst_modes_check_all_step\gobbleoneargument
      \or
        % enabled
@@ -249,7 +234,7 @@
      \let\syst_modes_check_all_step\gobbleoneargument
    \fi}
 
-\def\syst_modes_check_all#1#2#3%
+\def\syst_modes_check_all_lr#1#2#3%
   {\let\syst_modes_check_all_step\syst_modes_check_all_indeed
    \rawprocesscommacommand[#3]\syst_modes_check_all_step
    \ifx\syst_modes_check_all_step\gobbleoneargument
@@ -258,16 +243,25 @@
      \expandafter#1%
    \fi}
 
-\unexpanded\def\doifelsemode        {\syst_modes_check\firstoftwoarguments\secondoftwoarguments}
-\unexpanded\def\doifmode            {\syst_modes_check\firstofoneargument\gobbleoneargument}
-\unexpanded\def\doifnotmode         {\syst_modes_check\gobbleoneargument\firstofoneargument}
-\unexpanded\def\startmode       [#1]{\syst_modes_check\donothing\syst_modes_stop_yes{#1}}
-\unexpanded\def\startnotmode    [#1]{\syst_modes_check\syst_modes_stop_nop\donothing{#1}}
-\unexpanded\def\doifelseallmodes    {\syst_modes_check_all\firstoftwoarguments\secondoftwoarguments}
-\unexpanded\def\doifallmodes        {\syst_modes_check_all\firstofoneargument\gobbleoneargument}
-\unexpanded\def\doifnotallmodes     {\syst_modes_check_all\gobbleoneargument\firstofoneargument}
-\unexpanded\def\startallmodes   [#1]{\syst_modes_check_all\donothing\syst_modes_stop_all_yes{#1}}
-\unexpanded\def\startnotallmodes[#1]{\syst_modes_check_all\syst_modes_stop_all_nop\donothing{#1}}
+\def\syst_modes_check_all_ss#1#2[#3]%
+  {\let\syst_modes_check_all_step\syst_modes_check_all_indeed
+   \rawprocesscommacommand[#3]\syst_modes_check_all_step
+   \ifx\syst_modes_check_all_step\gobbleoneargument
+     \expandafter#2%
+   \else
+     \expandafter#1%
+   \fi}
+
+\unexpanded\def\doifelsemode    {\syst_modes_check_lr\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifmode        {\syst_modes_check_lr\firstofoneargument\gobbleoneargument}
+\unexpanded\def\doifnotmode     {\syst_modes_check_lr\gobbleoneargument\firstofoneargument}
+\unexpanded\def\startmode       {\syst_modes_check_ss\donothing\syst_modes_stop_yes}
+\unexpanded\def\startnotmode    {\syst_modes_check_ss\syst_modes_stop_nop\donothing}
+\unexpanded\def\doifelseallmodes{\syst_modes_check_all_lr\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifallmodes    {\syst_modes_check_all_lr\firstofoneargument\gobbleoneargument}
+\unexpanded\def\doifnotallmodes {\syst_modes_check_all_lr\gobbleoneargument\firstofoneargument}
+\unexpanded\def\startallmodes   {\syst_modes_check_all_ss\donothing\syst_modes_stop_all_yes}
+\unexpanded\def\startnotallmodes{\syst_modes_check_all_ss\syst_modes_stop_all_nop\donothing}
 
 \let\doifmodeelse     \doifelsemode
 \let\doifallmodeselse \doifelseallmodes
@@ -284,25 +278,47 @@
 
 %D Pushing/popping:
 
+% \unexpanded\def\pushmode[#1]%
+%   {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+%    \expandafter\edef\csname\??modestack#1\endcsname{\number\csname\??mode#1\endcsname}%
+%    \expandafter\pushmacro\csname\??modestack#1\endcsname}
+%
+% \unexpanded\def\popmode[#1]%
+%   {\ifcsname\??modestack#1\endcsname
+%      \expandafter\popmacro\csname\??modestack#1\endcsname
+%      \csname\??mode#1\endcsname\csname\??modestack#1\endcsname\relax
+%    \fi}
+%
+% \def\pushsystemmode#1%
+%   {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+%    \expandafter\edef\csname\??modestack\systemmodeprefix#1\endcsname{\number\csname\??mode\systemmodeprefix#1\endcsname}%
+%    \expandafter\pushmacro\csname\??modestack\systemmodeprefix#1\endcsname}
+%
+% \def\popsystemmode#1%
+%   {\ifcsname\??modestack\systemmodeprefix#1\endcsname
+%      \expandafter\popmacro\csname\??modestack\systemmodeprefix#1\endcsname
+%      \csname\??mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax
+%    \fi}
+
 \unexpanded\def\pushmode[#1]%
   {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
-   \expandafter\edef\csname\??modestack#1\endcsname{\number\csname\??mode#1\endcsname}%
-   \expandafter\pushmacro\csname\??modestack#1\endcsname}
+   \expandafter\edef\csname\??modestack#1\expandafter\endcsname\expandafter{\number\lastnamedcs}%
+   \expandafter\pushmacro\lastnamedcs}
 
 \unexpanded\def\popmode[#1]%
   {\ifcsname\??modestack#1\endcsname
-     \expandafter\popmacro\csname\??modestack#1\endcsname
+     \expandafter\popmacro\lastnamedcs
      \csname\??mode#1\endcsname\csname\??modestack#1\endcsname\relax
    \fi}
 
 \def\pushsystemmode#1%
   {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
-   \expandafter\edef\csname\??modestack\systemmodeprefix#1\endcsname{\number\csname\??mode\systemmodeprefix#1\endcsname}%
-   \expandafter\pushmacro\csname\??modestack\systemmodeprefix#1\endcsname}
+   \expandafter\edef\csname\??modestack\systemmodeprefix#1\expandafter\endcsname\expandafter{\number\lastnamedcs}%
+   \expandafter\pushmacro\lastnamedcs}
 
 \def\popsystemmode#1%
   {\ifcsname\??modestack\systemmodeprefix#1\endcsname
-     \expandafter\popmacro\csname\??modestack\systemmodeprefix#1\endcsname
+     \expandafter\popmacro\lastnamedcs
      \csname\??mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax
    \fi}
 
@@ -367,7 +383,7 @@
    \fi}
 
 \def\syst_modes_set_check
-  {\syst_modes_check\syst_modes_set_yes\syst_modes_set_nop\m_mode_case}
+  {\syst_modes_check_lr\syst_modes_set_yes\syst_modes_set_nop\m_mode_case}
 
 \def\syst_modes_set_yes#1%
   {\settrue\c_syst_modes_set_done
@@ -408,68 +424,17 @@
 \def\syst_setups_b[#1]{\processcommacommand[#1]\syst_setups} % [..]
 \def\syst_setups_c[#1]{\syst_setups{#1}} % [..]
 
-\letvalue{\??setup:\letterpercent}\gobbleoneargument
-
-% \def\syst_setups#1% the grid option will be extended to other main modes
-%   {\csname\??setup
-%      \ifgridsnapping
-%        \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else\ifcsname\??setup:#1\endcsname:#1\else:\letterpercent\fi\fi
-%      \else
-%                                                            \ifcsname\??setup:#1\endcsname:#1\else:\letterpercent\fi
-%      \fi
-%    \endcsname\empty} % takes one argument
+\letvalue{\??setup:\??empty}\gobbleoneargument
 
 \def\syst_setups#1% the grid option will be extended to other main modes
   {\csname\??setup
      \ifgridsnapping
-       \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else:\ifcsname\??setup:#1\endcsname#1\else\letterpercent\fi\fi
+       \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else:\ifcsname\??setup:#1\endcsname#1\else\??empty\fi\fi
      \else
-                                                           :\ifcsname\??setup:#1\endcsname#1\else\letterpercent\fi
+                                                           :\ifcsname\??setup:#1\endcsname#1\else\??empty\fi
      \fi
    \endcsname\empty} % takes one argument
 
-% not faster but less tracing sometimes:
-%
-% \def\syst_setups% the grid option will be extended to other main modes
-%   {\csname\??setup\ifgridsnapping\expandafter\syst_setups_grid\else\expandafter\syst_setups_normal\fi}
-%
-% \def\syst_setups_grid#1%
-%   {\ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else\ifcsname\??setup:#1\endcsname:#1\else:\letterpercent\fi\fi\endcsname\empty} % takes one argument
-%
-% \def\syst_setups_normal#1%
-%   {:\ifcsname\??setup:#1\endcsname#1\else\letterpercent\fi\endcsname\empty} % takes one argument
-%
-% only makes sense with many setups
-%
-% \def\syst_setups% the grid option will be extended to other main modes
-%   {\ifgridsnapping
-%      \expandafter\syst_setups_grid
-%    \else
-%      \expandafter\syst_setups_normal
-%    \fi}
-%
-% \def\syst_setups_normal#1% the grid option will be extended to other main modes
-%   {\csname\??setup
-%      :\ifcsname\??setup:#1\endcsname#1\else\letterpercent\fi
-%    \endcsname\empty} % takes one argument
-%
-% \def\syst_setups_grid#1% the grid option will be extended to other main modes
-%   {\csname\??setup
-%        \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else:\ifcsname\??setup:#1\endcsname#1\else\letterpercent\fi\fi
-%    \endcsname\empty} % takes one argument
-%
-% \let\directsetup\syst_setups
-% \let\texsetup   \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup
-
-% We can consider:
-%
-% \setvalue{\??setup->\v!auto}#1{\ctxcommand{autosetup("#1")}}
-%
-% ":\letterpercent" => "->\v!auto" with "\endcsname{#1}"
-%
-% but it won't work out well with multiple setups (intercepted at the
-% lua end) that then get only one argument.
-
 % no checking and we assume it being defined:
 
 \def\fastsetup                     #1{\csname\??setup:#1\endcsname\empty}
@@ -509,10 +474,10 @@
   {\clf_autosetups{#1}}
 
 \edef\setupwithargument#1% saves a few expansions
-  {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\letterpercent\noexpand\fi\endcsname}
+  {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\??empty\noexpand\fi\endcsname}
 
 \edef\setupwithargumentswapped#1#2% saves a few expansions (can be \let)
-  {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#2\endcsname#2\noexpand\else\letterpercent\noexpand\fi\endcsname{#1}}
+  {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#2\endcsname#2\noexpand\else\??empty\noexpand\fi\endcsname{#1}}
 
 \let\directsetup\syst_setups
 \let\texsetup   \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup
@@ -697,10 +662,13 @@
 \unexpanded\def\setgvariable#1#2#3{\expandafter\gdef\csname\??variables#1:#2\endcsname{#3}}
 \unexpanded\def\setxvariable#1#2#3{\expandafter\xdef\csname\??variables#1:#2\endcsname{#3}}
 
+% \def\getvariable#1#2%
+%   {\csname
+%      \ifcsname\??variables#1:#2\endcsname\??variables#1:#2\else\s!empty\fi
+%    \endcsname}
+
 \def\getvariable#1#2%
-  {\csname
-     \ifcsname\??variables#1:#2\endcsname\??variables#1:#2\else\s!empty\fi
-   \endcsname}
+  {\begincsname\??variables#1:#2\endcsname}
 
 \def\showvariable#1#2%
   {\showvalue{\ifcsname\??variables#1:#2\endcsname\??variables#1:#2\else\s!empty\fi}}
@@ -764,7 +732,8 @@
 \letvalue{\??variables:}\empty
 
 \unexpanded\def\doifelseemptyvariable#1#2%
-  {\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}%
+ %{\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}%
+  {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}%
    \ifx\m_syst_string_one\empty
      \expandafter\firstoffourarguments
    \else
@@ -774,7 +743,8 @@
 \let\doifemptyvariableelse\doifelseemptyvariable
 
 \unexpanded\def\doifemptyvariable#1#2%
-  {\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}%
+ %{\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}%
+  {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}%
    \ifx\m_syst_string_one\empty
      \expandafter\firstofoneargument
    \else
@@ -782,16 +752,21 @@
    \fi}
 
 \unexpanded\def\doifnotemptyvariable#1#2%
-  {\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}%
+ %{\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}%
+  {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}%
    \ifx\m_syst_string_one\empty
      \expandafter\gobbleoneargument
    \else
      \expandafter\firstofoneargument
    \fi}
 
-
-\def\getvariabledefault#1#2% #3% can be command, so no ifcsname here
-  {\executeifdefined{\??variables#1:#2}}% {#3}
+\def\getvariabledefault#1#2% #3% can be command
+ %{\executeifdefined{\??variables#1:#2}}% {#3}
+  {\ifcsname\??variables#1:#2\endcsname
+     \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+   \else
+     \expandafter\firstofoneargument
+   \fi}
 
 \unexpanded\def\setupenv
   {\dotripleargument\syst_variables_set[\getrawparameters][\s!environment]}
diff --git a/tex/context/base/core-ini.mkiv b/tex/context/base/core-ini.mkiv
index c338f6f81..0407409a3 100644
--- a/tex/context/base/core-ini.mkiv
+++ b/tex/context/base/core-ini.mkiv
@@ -115,8 +115,8 @@
 \newtoks \everyglobalbodyfont
 \newtoks \everydefinedfont
 
-\newevery \everybodyfont   \EveryBodyFont
-\newevery \everyfontswitch \EveryFontSwitch
+\newtoks \everybodyfont
+\newtoks \everyfontswitch
 
 \newtoks \everysetupbodyfont
 \newtoks \everyswitchtobodyfont
diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv
index 1358f4cce..cc9dafdd2 100644
--- a/tex/context/base/core-sys.mkiv
+++ b/tex/context/base/core-sys.mkiv
@@ -417,7 +417,8 @@
 %D This is a checked variant of \type {\getvalue}.
 
 \unexpanded\def\macroname#1% brrr
-  {\csname\ifcsname#1\endcsname#1\else\s!empty\fi\endcsname}
+% {\csname\ifcsname#1\endcsname#1\else\s!empty\fi\endcsname}
+  {\begincsname#1\endcsname}
 
 % %D A weird one that I probably needed once, so it might as well become
 % %D obsolete.
diff --git a/tex/context/base/core-uti.mkiv b/tex/context/base/core-uti.mkiv
index cdd8958ff..de9a893ee 100644
--- a/tex/context/base/core-uti.mkiv
+++ b/tex/context/base/core-uti.mkiv
@@ -18,7 +18,7 @@
 \registerctxluafile{core-uti}{1.001}
 
 \def\savecurrentvalue#1#2% immediate, so not \unexpanded
-  {\clf_savevariable{\strippedcsname#1}{#2}}
+  {\clf_savevariable{\csstring#1}{#2}}
 
 \appendtoks
     \clf_setjobcomment
diff --git a/tex/context/base/enco-ini.mkiv b/tex/context/base/enco-ini.mkiv
index 2f94c8fc8..f15fd1616 100644
--- a/tex/context/base/enco-ini.mkiv
+++ b/tex/context/base/enco-ini.mkiv
@@ -158,7 +158,7 @@
          \hidewidth
          \hskip#2\wd0
          \hskip-#3\slantperpoint % in plain 1ex * dimenless value
-         \vbox to .2\exheight{\box0\vss}\hidewidth
+         \vpack to .2\exheight{\box0\vss}\hidewidth
          \crcr}}}
 
 \unexpanded\def\buildtextmacron     {\bottomaccent{.25ex}{0}{15}{\textmacron}}
diff --git a/tex/context/base/file-mod.mkvi b/tex/context/base/file-mod.mkvi
index f043a68e8..8c46ddac0 100644
--- a/tex/context/base/file-mod.mkvi
+++ b/tex/context/base/file-mod.mkvi
@@ -115,10 +115,13 @@
 %    \fi
 %    \let\currentmoduleparameters\empty}
 
+% \def\moduleparameter#name#parameter% should have been \namedmoduleparameter
+%   {\csname\??module
+%      \ifcsname\??module#name:#parameter\endcsname#name:#parameter\fi
+%    \endcsname}
+
 \def\moduleparameter#name#parameter% should have been \namedmoduleparameter
-  {\csname\??module
-     \ifcsname\??module#name:#parameter\endcsname#name:#parameter\fi
-   \endcsname}
+  {\begincsname\??module#name:#parameter\endcsname}
 
 \letvalue\??module\empty % so we default to empty as with all parameters
 
diff --git a/tex/context/base/font-agl.lua b/tex/context/base/font-agl.lua
index e60a2be0c..dd3490523 100644
--- a/tex/context/base/font-agl.lua
+++ b/tex/context/base/font-agl.lua
@@ -6,18 +6,15 @@ if not modules then modules = { } end modules ['font-agl'] = {
     original  = "Adobe Glyph List, version 2.0, September 20, 2002",
 }
 
-local allocate = utilities.storage.allocate
+local allocate      = utilities.storage.allocate
 
-local names    = allocate {
-    -- filled from char-def.lua
-}
-local unicodes = allocate {
-    -- filled from char-def.lua
-}
+fonts               = fonts or { }
+local encodings     = fonts.encodings or { }
+fonts.encodings     = encodings
+local agl           = fonts.encodings.agl or { }
+fonts.encodings.agl = agl
 
-local ctxcodes = allocate {
-    -- filled from char-def.lua
-}
+table.setmetatableindex(agl,nil) -- prevent recursive lookups otherwise when autoloaded
 
 local synonyms = {
     Acyrillic                      = 0x0410,
@@ -636,48 +633,60 @@ local extras   = allocate { -- private extensions
     twodotenleader  = 0x2025,
 }
 
-for u, c in next, characters.data do
-    local a = c.adobename
-    if a then
-        unicodes[a] = u
-        names   [u] = a
-    end
-    local n = c.contextname
-    if n then
-        ctxcodes[n] = u
-     -- names   [u] = a
+-- We load this table only when needed. We could use a loading mechanism
+-- return the table but there are no more vectors like this so why bother.
+--
+-- Well, we currently have this table preloaded anyway.
+
+local names    = agl.names
+local unicodes = agl.unicodes
+local ctxcodes = agl.ctxcodes
+
+if not names then
+
+    names    = allocate { } -- filled from char-def.lua
+    unicodes = allocate { }
+    ctxcodes = allocate { }
+
+    for u, c in next, characters.data do
+        local a = c.adobename
+        if a then
+            unicodes[a] = u
+            names   [u] = a
+        end
+        local n = c.contextname
+        if n then
+            ctxcodes[n] = u
+         -- names   [u] = a
+        end
     end
-end
 
-for a, u in next, extras do
-    unicodes[a] = u
-    if not names[u] then
-        names[u] = a
+    for a, u in next, extras do
+        unicodes[a] = u
+        if not names[u] then
+            names[u] = a
+        end
     end
-end
 
-for s, u in next, synonyms do
-    unicodes[s] = u
-    if not names[u] then
-        names[u] = s
+    for s, u in next, synonyms do
+        unicodes[s] = u
+        if not names[u] then
+            names[u] = s
+        end
     end
-end
 
--- We load this table only when needed. We could use a loading mechanism
--- return the table but there are no more vectors like this so why bother.
---
--- Well, we currently have this table preloaded anyway.
+    if storage then
+        storage.register("encodings/names",    names,    "fonts.encodings.names")
+        storage.register("encodings/unicodes", unicodes, "fonts.encodings.unicodes")
+        storage.register("encodings/ctxcodes", ctxcodes, "fonts.encodings.ctxcodes")
+    end
 
-local agl = {
-    names    = names,     -- unicode -> name
-    unicodes = unicodes,  -- name -> unicode
-    ctxcodes = ctxcodes,  -- name -> unicode
-    synonyms = synonyms,  -- merged into the other two
-    extras   = extras,    -- merged into the other two
-}
+end
 
-fonts               = fonts or { }
-fonts.encodings     = fonts.encodings or { }
-fonts.encodings.agl = agl
+agl.names    = names     -- unicode -> name
+agl.unicodes = unicodes  -- name -> unicode
+agl.ctxcodes = ctxcodes  -- name -> unicode
+agl.synonyms = synonyms  -- merged into the other two
+agl.extras   = extras    -- merged into the other two
 
 return agl
diff --git a/tex/context/base/font-con.lua b/tex/context/base/font-con.lua
index 55d7793cf..e5bf9e9c1 100644
--- a/tex/context/base/font-con.lua
+++ b/tex/context/base/font-con.lua
@@ -682,6 +682,8 @@ function constructors.scale(tfmdata,specification)
         if isunicode then
             chr.unicode   = isunicode
             chr.tounicode = tounicode(isunicode)
+            -- in luatex > 0.85 we can do this:
+         -- chr.tounicode = isunicode
         end
         if hasquality then
             -- we could move these calculations elsewhere (saves calculations)
diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua
index 05a4fca3b..c00312098 100644
--- a/tex/context/base/font-ctx.lua
+++ b/tex/context/base/font-ctx.lua
@@ -2278,7 +2278,7 @@ local methods            = analyzers.methods
 
 local unsetvalue         = attributes.unsetvalue
 
-local traverse_by_id     = nuts.traverse_id
+local traverse_id        = nuts.traverse_id
 
 local a_color            = attributes.private('color')
 local a_colormodel       = attributes.private('colormodel')
@@ -2307,7 +2307,7 @@ local function markstates(head)
     if head then
         head = tonut(head)
         local model = getattr(head,a_colormodel) or 1
-        for glyph in traverse_by_id(glyph_code,head) do
+        for glyph in traverse_id(glyph_code,head) do
             local a = getprop(glyph,a_state)
             if a then
                 local name = colornames[a]
@@ -2357,7 +2357,7 @@ registerotffeature { -- adapts
 }
 
 function methods.nocolor(head,font,attr)
-    for n in traverse_by_id(glyph_code,head) do
+    for n in traverse_id(glyph_code,head) do
         if not font or getfont(n) == font then
             setattr(n,a_color,unsetvalue)
         end
diff --git a/tex/context/base/font-dsp.lua b/tex/context/base/font-dsp.lua
index 22f822979..05420f8d6 100644
--- a/tex/context/base/font-dsp.lua
+++ b/tex/context/base/font-dsp.lua
@@ -373,7 +373,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
         local coverage     = readushort(f)
         local subclasssets = readarray(f)
         local rules        = { }
-        if subclassets then
+        if subclasssets then
             coverage = readcoverage(f,tableoffset+coverage,true)
             for i=1,#subclasssets do
                 local offset = subclasssets[i]
@@ -1479,7 +1479,7 @@ do
         local glyphs         = fontdata.glyphs
         local nofglyphs      = fontdata.nofglyphs or #glyphs
         local noflookups     = #lookups
-        local lookupprefix   = sub(what,1,1)
+        local lookupprefix   = sub(what,2,2) -- g[s|p][ub|os]
         --
         for lookupid=1,noflookups do
             local lookup     = lookups[lookupid]
@@ -1491,8 +1491,13 @@ do
                 local nofsubtables = #subtables
                 local order        = lookup.order
                 local flags        = lookup.flags
-             -- local chain        = lookup.chain
+                -- this is expected in th efont handler (faster checking)
+                if flags[1] then flags[1] = "mark" end
+                if flags[2] then flags[2] = "ligature" end
+                if flags[3] then flags[2] = "base" end
+                --
                 local markclass    = lookup.markclass
+             -- local chain        = lookup.chain
                 if nofsubtables > 0 then
                     local steps     = { }
                     local nofsteps  = 0
@@ -1652,8 +1657,9 @@ do
         end
 
         for i, n in sortedhash(sublookupcheck) do
-            if n == 0 then
-                report("%s lookup %i is not used",what,i) -- lookups[i].done.lookupid
+            local t = lookups[i].type
+            if n == 0 and t ~= "extension" then
+                report("%s lookup %i of type %a is not used",what,i,t)
             end
         end
 
diff --git a/tex/context/base/font-emp.mkvi b/tex/context/base/font-emp.mkvi
index 34a1ea9cc..8f87ff7a1 100644
--- a/tex/context/base/font-emp.mkvi
+++ b/tex/context/base/font-emp.mkvi
@@ -43,7 +43,7 @@
 \let\m_font_emphasized_typeface\empty
 
 \def\font_emphasis_checked_typeface#slanted#italic%
-  {\edef\m_font_emphasized_typeface{\bodyfontvariable\s!em}%
+  {\edef\m_font_emphasized_typeface{\font_bodyfontvariable\s!em}%
    \ifx\m_font_emphasized_typeface\v!slanted
      #slanted%
    \else\ifx\m_font_emphasized_typeface\v!italic
diff --git a/tex/context/base/font-fea.mkvi b/tex/context/base/font-fea.mkvi
index 6280ae2bc..dade70494 100644
--- a/tex/context/base/font-fea.mkvi
+++ b/tex/context/base/font-fea.mkvi
@@ -248,8 +248,11 @@
 \installcorenamespace{featureyes}
 \installcorenamespace{featurenop}
 
-\unexpanded\def\font_feature_yes[#method]{\csname\??featureyes\ifcsname\??featureyes#method\endcsname#method\else\s!unknown\fi\endcsname}
-\unexpanded\def\font_feature_nop  #method{\csname\??featurenop\ifcsname\??featurenop#method\endcsname#method\else\s!unknown\fi\endcsname}
+%\unexpanded\def\font_feature_yes[#method]{\csname\??featureyes\ifcsname\??featureyes#method\endcsname#method\else\s!unknown\fi\endcsname}
+%\unexpanded\def\font_feature_nop  #method{\csname\??featurenop\ifcsname\??featurenop#method\endcsname#method\else\s!unknown\fi\endcsname}
+
+\unexpanded\def\font_feature_yes[#method]{\begincsname\??featureyes#method\endcsname}
+\unexpanded\def\font_feature_nop  #method{\begincsname\??featurenop#method\endcsname}
 
 \letvalue{\??featureyes +}\addfeature
 \letvalue{\??featurenop +}\addfeature
diff --git a/tex/context/base/font-fil.mkvi b/tex/context/base/font-fil.mkvi
index 1a20d1cd8..0bfc07b6c 100644
--- a/tex/context/base/font-fil.mkvi
+++ b/tex/context/base/font-fil.mkvi
@@ -191,21 +191,27 @@
 \def\font_helpers_true_fontname#name*#first#rest*#crap\relax
   {\ifcsname\??fontfile\fontclass#name\endcsname
      \ifx#first\empty
-       \expandafter\truefontname\csname\??fontfile\fontclass#name\endcsname
+      %\expandafter\truefontname\csname\??fontfile\fontclass#name\endcsname
+       \expandafter\truefontname\lastnamedcs
      \else
-       \expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname*#first#rest%
+      %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname*#first#rest%
+       \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
      \fi
    \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
      \ifx#first\empty
-       \expandafter\truefontname\csname\??fontfile\defaultfontclass#name\endcsname
+      %\expandafter\truefontname\csname\??fontfile\defaultfontclass#name\endcsname
+       \expandafter\truefontname\lastnamedcs
      \else
-       \expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname*#first#rest%
+      %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname*#first#rest%
+       \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
      \fi
    \else\ifcsname\??fontfile#name\endcsname
      \ifx#first\empty
-       \expandafter\truefontname\csname\??fontfile#name\endcsname
+      %\expandafter\truefontname\csname\??fontfile#name\endcsname
+       \expandafter\truefontname\lastnamedcs
      \else
-       \expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname*#first#rest%
+      %\expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname*#first#rest%
+       \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest%
      \fi
    \else
      #name\ifx#first\empty\else*#first#rest\fi
@@ -216,20 +222,25 @@
 
 \def\font_helpers_true_fontname_check_indeed#name*#crap\relax
   {\ifcsname\??fontfile\fontclass#name\endcsname
-     \expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname
+    %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname
+     \expandafter\font_helpers_true_fontname_check\lastnamedcs
    \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
-     \expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname
+    %\expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname
+     \expandafter\font_helpers_true_fontname_check\lastnamedcs
    \else\ifcsname\??fontfile#name\endcsname
-     \expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname
+    %\expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname
+     \expandafter\font_helpers_true_fontname_check\lastnamedcs
    \else
      #name%
    \fi\fi\fi}
 
 \def\expandfontsynonym#command#name% one level expansion
   {\ifcsname\??fontfile\fontclass#name\endcsname
-     \expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\fontclass#name\endcsname}%
+    %\expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\fontclass#name\endcsname}%
+     \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
    \else\ifcsname\??fontfile\defaultfontclass#2\endcsname
-     \expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\defaultfontclass#name\endcsname}%
+    %\expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\defaultfontclass#name\endcsname}%
+     \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}%
    \fi\fi}
 
 \def\doifelsefontsynonym#name%
@@ -250,9 +261,11 @@
 
 \def\tracedfontname#name%
   {#name\ifcsname\??fontfile\fontclass#name\endcsname
-     \expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname
+    %\expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname
+     \expandafter\tracedfontname\lastnamedcs
    \else\ifcsname\??fontfile#name\endcsname
-     \expandafter\tracedfontname\csname\??fontfile#name\endcsname
+    %\expandafter\tracedfontname\csname\??fontfile#name\endcsname
+     \expandafter\tracedfontname\lastnamedcs
    \fi\fi}
 
 %D \macros
@@ -266,7 +279,7 @@
 \let\fontclass       \empty
 \let\defaultfontclass\empty
 
-\def\fontclassname#class#name%
+\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting
   {\ifcsname\??fontfile#class#name\endcsname
      \fontclassname{#class}{\csname\??fontfile#class#name\endcsname}%
    \else\ifcsname\??fontfile#name\endcsname
@@ -283,84 +296,132 @@
 % without pre-expansion.
 
 \def\font_helpers_update_font_class_parameters
-  {\edef\m_font_class_direction {\ifcsname\??fontclass\fontclass\fontstyle\s!direction \endcsname\csname\??fontclass\fontclass\fontstyle\s!direction \endcsname\fi}%
-   \edef\m_font_class_features  {\ifcsname\??fontclass\fontclass\fontstyle\s!features  \endcsname\csname\??fontclass\fontclass\fontstyle\s!features  \endcsname\fi}%
-   \edef\m_font_class_fallbacks {\ifcsname\??fontclass\fontclass\fontstyle\s!fallbacks \endcsname\csname\??fontclass\fontclass\fontstyle\s!fallbacks \endcsname\fi}%
-   \edef\m_font_class_goodies   {\ifcsname\??fontclass\fontclass\fontstyle\s!goodies   \endcsname\csname\??fontclass\fontclass\fontstyle\s!goodies   \endcsname\fi}%
-   \edef\m_font_class_designsize{\ifcsname\??fontclass\fontclass\fontstyle\s!designsize\endcsname\csname\??fontclass\fontclass\fontstyle\s!designsize\endcsname\fi}}
+  {\edef\m_font_class_direction {\begincsname\??fontclass\fontclass\fontstyle\s!direction \endcsname}%
+   \edef\m_font_class_features  {\begincsname\??fontclass\fontclass\fontstyle\s!features  \endcsname}%
+   \edef\m_font_class_fallbacks {\begincsname\??fontclass\fontclass\fontstyle\s!fallbacks \endcsname}%
+   \edef\m_font_class_goodies   {\begincsname\??fontclass\fontclass\fontstyle\s!goodies   \endcsname}%
+   \edef\m_font_class_designsize{\begincsname\??fontclass\fontclass\fontstyle\s!designsize\endcsname}}
 
 % resolve
 
+% \def\font_helpers_set_features_yes#name%
+%   {\ifcsname\??fontfile\fontclass#name\s!features \endcsname \edef\m_font_features  % class + symbolic_name
+%     {\csname\??fontfile\fontclass#name\s!features \endcsname}\else
+%    \ifcsname\??fontfile          #name\s!features \endcsname \edef\m_font_features  % symbolic_name
+%     {\csname\??fontfile          #name\s!features \endcsname}\else
+%    \ifcsname\??fontfile\fontclass            #name\endcsname\expandafter\font_helpers_set_features_yes    % class + parent_name
+%      \csname\??fontfile\fontclass            #name\endcsname \else
+%    \ifcsname\??fontfile                      #name\endcsname \expandafter\font_helpers_set_features_yes    % parent_name
+%      \csname\??fontfile                      #name\endcsname \else
+%    \let\m_font_features\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_fallbacks_yes#name%
+%   {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks
+%     {\csname\??fontfile\fontclass#name\s!fallbacks\endcsname}\else
+%    \ifcsname\??fontfile          #name\s!fallbacks\endcsname \edef\m_font_fallbacks
+%     {\csname\??fontfile          #name\s!fallbacks\endcsname}\else
+%    \ifcsname\??fontfile\fontclass            #name\endcsname \expandafter\font_helpers_set_fallbacks_yes
+%      \csname\??fontfile\fontclass            #name\endcsname \else
+%    \ifcsname\??fontfile                      #name\endcsname \expandafter\font_helpers_set_fallbacks_yes
+%      \csname\??fontfile                      #name\endcsname \else
+%    \let\m_font_fallbacks\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_goodies_yes#name%
+%   {\ifcsname\??fontfile\fontclass#name\s!goodies  \endcsname \edef\m_font_goodies
+%     {\csname\??fontfile\fontclass#name\s!goodies  \endcsname}\else
+%    \ifcsname\??fontfile          #name\s!goodies  \endcsname \edef\m_font_goodies
+%     {\csname\??fontfile          #name\s!goodies  \endcsname}\else
+%    \ifcsname\??fontfile\fontclass            #name\endcsname \expandafter\font_helpers_set_goodies_yes
+%      \csname\??fontfile\fontclass            #name\endcsname \else
+%    \ifcsname\??fontfile                      #name\endcsname \expandafter\font_helpers_set_goodies_yes
+%      \csname\??fontfile                      #name\endcsname \else
+%    \let\m_font_goodies\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_designsize_yes#name%
+%   {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize
+%     {\csname\??fontfile\fontclass#name\s!designsize\endcsname}\else
+%    \ifcsname\??fontfile          #name\s!designsize\endcsname \edef\m_font_designsize
+%     {\csname\??fontfile          #name\s!designsize\endcsname}\else
+%    \ifcsname\??fontfile\fontclass             #name\endcsname \expandafter\font_helpers_set_designsize_yes
+%      \csname\??fontfile\fontclass             #name\endcsname \else
+%    \ifcsname\??fontfile                       #name\endcsname \expandafter\font_helpers_set_designsize_yes
+%      \csname\??fontfile                       #name\endcsname \else
+%    \let\m_font_designsize\empty\fi\fi\fi\fi}
+%
+% \def\font_helpers_set_features_nop#name%
+%   {\ifcsname\??fontfile#name\s!features \endcsname \edef\m_font_features
+%     {\csname\??fontfile#name\s!features \endcsname}\else
+%    \ifcsname\??fontfile            #name\endcsname \expandafter\font_helpers_set_features_nop
+%      \csname\??fontfile            #name\endcsname \else
+%    \let\m_font_features\empty\fi\fi}
+%
+% \def\font_helpers_set_fallbacks_nop#name%
+%   {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks
+%     {\csname\??fontfile#name\s!fallbacks\endcsname}\else
+%    \ifcsname\??fontfile            #name\endcsname \expandafter\font_helpers_set_fallbacks_nop
+%      \csname\??fontfile            #name\endcsname \else
+%    \let\m_font_fallbacks\empty\fi\fi}
+%
+% \def\font_helpers_set_goodies_nop#name%
+%   {\ifcsname\??fontfile#name\s!goodies  \endcsname \edef\m_font_goodies
+%     {\csname\??fontfile#name\s!goodies  \endcsname}\else
+%    \ifcsname\??fontfile            #name\endcsname \expandafter\font_helpers_set_goodies_nop
+%      \csname\??fontfile            #name\endcsname \else
+%    \let\m_font_goodies\empty\fi\fi}
+%
+% \def\font_helpers_set_designsize_nop#name%
+%   {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize
+%     {\csname\??fontfile#name\s!designsize\endcsname}\else
+%    \ifcsname\??fontfile             #name\endcsname \expandafter\font_helpers_set_designsize_nop
+%      \csname\??fontfile             #name\endcsname \else
+%    \let\m_font_designsize\empty\fi\fi}
+
 \def\font_helpers_set_features_yes#name%
-  {\ifcsname\??fontfile\fontclass#name\s!features \endcsname \edef\m_font_features  % class + symbolic_name
-    {\csname\??fontfile\fontclass#name\s!features \endcsname}\else
-   \ifcsname\??fontfile          #name\s!features \endcsname \edef\m_font_features  % symbolic_name
-    {\csname\??fontfile          #name\s!features \endcsname}\else
-   \ifcsname\??fontfile\fontclass            #name\endcsname\expandafter\font_helpers_set_features_yes    % class + parent_name
-     \csname\??fontfile\fontclass            #name\endcsname \else
-   \ifcsname\??fontfile                      #name\endcsname \expandafter\font_helpers_set_features_yes    % parent_name
-     \csname\??fontfile                      #name\endcsname \else
+  {\ifcsname\??fontfile\fontclass#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\else % class + symbolic_name
+   \ifcsname\??fontfile          #name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\else % symbolic_name
+   \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \else % class + parent_name
+   \ifcsname\??fontfile          #name\endcsname \expandafter\font_helpers_set_features_yes\lastnamedcs \else % parent_name
    \let\m_font_features\empty\fi\fi\fi\fi}
 
 \def\font_helpers_set_fallbacks_yes#name%
-  {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks
-    {\csname\??fontfile\fontclass#name\s!fallbacks\endcsname}\else
-   \ifcsname\??fontfile          #name\s!fallbacks\endcsname \edef\m_font_fallbacks
-    {\csname\??fontfile          #name\s!fallbacks\endcsname}\else
-   \ifcsname\??fontfile\fontclass            #name\endcsname \expandafter\font_helpers_set_fallbacks_yes
-     \csname\??fontfile\fontclass            #name\endcsname \else
-   \ifcsname\??fontfile                      #name\endcsname \expandafter\font_helpers_set_fallbacks_yes
-     \csname\??fontfile                      #name\endcsname \else
+  {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\else
+   \ifcsname\??fontfile          #name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\else
+   \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \else
+   \ifcsname\??fontfile          #name\endcsname \expandafter\font_helpers_set_fallbacks_yes\lastnamedcs \else
    \let\m_font_fallbacks\empty\fi\fi\fi\fi}
 
 \def\font_helpers_set_goodies_yes#name%
-  {\ifcsname\??fontfile\fontclass#name\s!goodies  \endcsname \edef\m_font_goodies
-    {\csname\??fontfile\fontclass#name\s!goodies  \endcsname}\else
-   \ifcsname\??fontfile          #name\s!goodies  \endcsname \edef\m_font_goodies
-    {\csname\??fontfile          #name\s!goodies  \endcsname}\else
-   \ifcsname\??fontfile\fontclass            #name\endcsname \expandafter\font_helpers_set_goodies_yes
-     \csname\??fontfile\fontclass            #name\endcsname \else
-   \ifcsname\??fontfile                      #name\endcsname \expandafter\font_helpers_set_goodies_yes
-     \csname\??fontfile                      #name\endcsname \else
+  {\ifcsname\??fontfile\fontclass#name\s!goodies  \endcsname \edef\m_font_goodies{\lastnamedcs}\else
+   \ifcsname\??fontfile          #name\s!goodies  \endcsname \edef\m_font_goodies{\lastnamedcs}\else
+   \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \else
+   \ifcsname\??fontfile          #name\endcsname \expandafter\font_helpers_set_goodies_yes\lastnamedcs \else
    \let\m_font_goodies\empty\fi\fi\fi\fi}
 
 \def\font_helpers_set_designsize_yes#name%
-  {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize
-    {\csname\??fontfile\fontclass#name\s!designsize\endcsname}\else
-   \ifcsname\??fontfile          #name\s!designsize\endcsname \edef\m_font_designsize
-    {\csname\??fontfile          #name\s!designsize\endcsname}\else
-   \ifcsname\??fontfile\fontclass             #name\endcsname \expandafter\font_helpers_set_designsize_yes
-     \csname\??fontfile\fontclass             #name\endcsname \else
-   \ifcsname\??fontfile                       #name\endcsname \expandafter\font_helpers_set_designsize_yes
-     \csname\??fontfile                       #name\endcsname \else
+  {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\else
+   \ifcsname\??fontfile          #name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\else
+   \ifcsname\??fontfile\fontclass#name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \else
+   \ifcsname\??fontfile          #name\endcsname \expandafter\font_helpers_set_designsize_yes\lastnamedcs \else
    \let\m_font_designsize\empty\fi\fi\fi\fi}
 
 \def\font_helpers_set_features_nop#name%
-  {\ifcsname\??fontfile#name\s!features \endcsname \edef\m_font_features
-    {\csname\??fontfile#name\s!features \endcsname}\else
-   \ifcsname\??fontfile            #name\endcsname \expandafter\font_helpers_set_features_nop
-     \csname\??fontfile            #name\endcsname \else
+  {\ifcsname\??fontfile#name\s!features\endcsname \edef\m_font_features{\lastnamedcs}\else
+   \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_features_nop\lastnamedcs \else
    \let\m_font_features\empty\fi\fi}
 
 \def\font_helpers_set_fallbacks_nop#name%
-  {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks
-    {\csname\??fontfile#name\s!fallbacks\endcsname}\else
-   \ifcsname\??fontfile            #name\endcsname \expandafter\font_helpers_set_fallbacks_nop
-     \csname\??fontfile            #name\endcsname \else
+  {\ifcsname\??fontfile#name\s!fallbacks\endcsname \edef\m_font_fallbacks{\lastnamedcs}\else
+   \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_fallbacks_nop\lastnamedcs \else
    \let\m_font_fallbacks\empty\fi\fi}
 
 \def\font_helpers_set_goodies_nop#name%
-  {\ifcsname\??fontfile#name\s!goodies  \endcsname \edef\m_font_goodies
-    {\csname\??fontfile#name\s!goodies  \endcsname}\else
-   \ifcsname\??fontfile            #name\endcsname \expandafter\font_helpers_set_goodies_nop
-     \csname\??fontfile            #name\endcsname \else
+  {\ifcsname\??fontfile#name\s!goodies\endcsname \edef\m_font_goodies{\lastnamedcs}\else
+   \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_goodies_nop\lastnamedcs \else
    \let\m_font_goodies\empty\fi\fi}
 
 \def\font_helpers_set_designsize_nop#name%
-  {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize
-    {\csname\??fontfile#name\s!designsize\endcsname}\else
-   \ifcsname\??fontfile             #name\endcsname \expandafter\font_helpers_set_designsize_nop
-     \csname\??fontfile             #name\endcsname \else
+  {\ifcsname\??fontfile#name\s!designsize\endcsname \edef\m_font_designsize{\lastnamedcs}\else
+   \ifcsname\??fontfile#name\endcsname \expandafter\font_helpers_set_designsize_nop\lastnamedcs \else
    \let\m_font_designsize\empty\fi\fi}
 
 \def\font_helpers_update_font_parameters_yes
diff --git a/tex/context/base/font-ini.mkvi b/tex/context/base/font-ini.mkvi
index f023d71ab..73b26eeb3 100644
--- a/tex/context/base/font-ini.mkvi
+++ b/tex/context/base/font-ini.mkvi
@@ -382,27 +382,18 @@
 \unexpanded\def\stopfont {\endgroup}
 
 %D \macros
-%D   {everybodyfont,Everybodyfont,everyglobalbodyfont}
+%D   {everybodyfont,everyglobalbodyfont}
 %D
 %D Every change in bodyfont size has conseqences for the baseline
 %D distance and skips between paragraphs. These are initialized
 %D in other modules. Here we only provide the hooks that
 %D garantees their handling.
-
+%D
 %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,bodyfontsize}
@@ -1023,11 +1014,22 @@
 %      \ifcsname\??fontenvironments\s!default\s!text  \endcsname  \s!text    \fi\fi
 %    \endcsname}
 
+% \def\currentfontbodysize % gets number (the normal sa 1 etc)
+%   {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+%      \csname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+%    \else\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
+%      \csname\??fontenvironments\s!default\somefontsize\endcsname
+%    \else
+%      \somefontsize
+%    \fi\fi}
+
 \def\currentfontbodysize % gets number (the normal sa 1 etc)
   {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
-     \csname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+    %\csname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+     \lastnamedcs
    \else\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
-     \csname\??fontenvironments\s!default\somefontsize\endcsname
+    %\csname\??fontenvironments\s!default\somefontsize\endcsname
+     \lastnamedcs
    \else
      \somefontsize
    \fi\fi}
@@ -1041,6 +1043,13 @@
                                                                                   \s!default         \fi\fi\fi\fi
    \endcsname}
 
+\def\font_currentfontbodyscale % gets character (x xx a etc)
+  {\ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments          \s!default\fontsize\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments\fontclass\s!default\s!text  \endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments          \s!default\s!text  \endcsname\lastnamedcs\else
+     \csname\??fontenvironments          \s!default         \endcsname            \fi\fi\fi\fi}
+
 \def\currentfontscale % used in default definition
   {\csname\??fontenvironments
      \ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\fontclass\s!default\fontsize\else
@@ -1050,6 +1059,13 @@
                                                                                    \s!default         \fi\fi\fi\fi
    \endcsname}
 
+\def\font_currentfontscale % used in default definition
+  {\ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments          \s!default\xfontsize\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments\fontclass\s!default\s!text   \endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments          \s!default\s!text   \endcsname\lastnamedcs\else
+     \csname\??fontenvironments          \s!default          \endcsname            \fi\fi\fi\fi}
+
 \setvalue{\??fontenvironments\s!default}{1}
 
 %D In the following macros we use \type{\currentxfontsize} to
@@ -1159,6 +1175,12 @@
      \ifcsname\??fontenvironments\s!default                       #parameter\endcsname\s!default                       #parameter\fi\fi\fi\fi
    \endcsname}
 
+\def\font_bodyfontvariable#parameter%
+  {\ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments\fontclass                       #parameter\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments          \normalizedbodyfontsize#parameter\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments\s!default                       #parameter\endcsname\lastnamedcs\fi\fi\fi\fi}
+
 \def\bodyfontsizevariable#size#parameter%
   {\csname\??fontenvironments
      \ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\fontclass#size#parameter\else
@@ -1167,17 +1189,31 @@
      \ifcsname\??fontenvironments\s!default     #parameter\endcsname\s!default     #parameter\fi\fi\fi\fi
    \endcsname}
 
+\def\font_bodyfontsizevariable#size#parameter%
+  {\ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments\fontclass     #parameter\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments          #size#parameter\endcsname\lastnamedcs\else
+   \ifcsname\??fontenvironments\s!default     #parameter\endcsname\lastnamedcs\fi\fi\fi\fi}
+
 \def\bodyfontinterlinespace{\bodyfontvariable\c!interlinespace} % used elsewhere
 
+% \def\bodyfontdimension#class#size#parameter#body%
+%   {\the\dimexpr
+%      \ifcsname\??fontenvironments     #class#size#parameter\endcsname
+%        \csname\??fontenvironments     #class#size#parameter\endcsname                   \else
+%      \ifcsname\??fontenvironments#class\s!default#parameter\endcsname
+%        \csname\??fontenvironments#class\s!default#parameter\endcsname\dimexpr#body\relax\else     % factor
+%      \ifcsname\??fontenvironments           #size#parameter\endcsname
+%        \csname\??fontenvironments           #size#parameter\endcsname                   \else
+%        \csname\??fontenvironments      \s!default#parameter\endcsname\dimexpr#body\relax\fi\fi\fi % factor
+%    \relax}
+
 \def\bodyfontdimension#class#size#parameter#body%
   {\the\dimexpr
-     \ifcsname\??fontenvironments     #class#size#parameter\endcsname
-       \csname\??fontenvironments     #class#size#parameter\endcsname                   \else
-     \ifcsname\??fontenvironments#class\s!default#parameter\endcsname
-       \csname\??fontenvironments#class\s!default#parameter\endcsname\dimexpr#body\relax\else     % factor
-     \ifcsname\??fontenvironments           #size#parameter\endcsname
-       \csname\??fontenvironments           #size#parameter\endcsname                   \else
-       \csname\??fontenvironments      \s!default#parameter\endcsname\dimexpr#body\relax\fi\fi\fi % factor
+     \ifcsname\??fontenvironments     #class#size#parameter\endcsname \lastnamedcs                   \else
+     \ifcsname\??fontenvironments#class\s!default#parameter\endcsname \lastnamedcs\dimexpr#body\relax\else     % factor
+     \ifcsname\??fontenvironments           #size#parameter\endcsname \lastnamedcs                   \else
+                                                                      \lastnamedcs\dimexpr#body\relax\fi\fi\fi % factor
    \relax}
 
 \unexpanded\def\definebodyfontenvironment
@@ -1638,7 +1674,8 @@
 
 \unexpanded\def\font_basics_switch_style#style%
   {\ifcsname\??fontstyle#style\endcsname
-     \csname\??fontstyle#style\endcsname
+    %\csname\??fontstyle#style\endcsname
+     \lastnamedcs
      \edef\fontstyle{#style}%
      \ifmmode\mr\fi % in order to be compatible with \rm in math mode
      % \the\everybodyfont % cleaner, in setting size as well as style
@@ -1689,7 +1726,7 @@
 \unexpanded\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message%
   {\edef\m_font_keyword{#keyword}%
    \ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname
-     \edef\m_font_step{\bodyfontvariable\m_font_keyword}%
+     \edef\m_font_step{\font_bodyfontvariable\m_font_keyword}%
      \normalexpanded{\font_helpers_set_font_set_font_option_body{#method}{\m_font_step}{#message}}%
    \else\ifx\m_font_keyword\v!reset
      \let\fontstyle\empty % new 31/7/2006
@@ -1830,7 +1867,8 @@
 \def\font_helpers_check_strategy_class_a % --- --- --- --- % pt tt bf a
   {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
      \setfalse\c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_class_b
    \fi}
@@ -1838,7 +1876,8 @@
 \def\font_helpers_check_strategy_class_b % --- --- --- def % pt tt bf
   {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_class_c
    \fi}
@@ -1846,7 +1885,8 @@
 \def\font_helpers_check_strategy_class_c % --- --- def --- % pt tt tf a
   {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_class_d
    \fi}
@@ -1854,7 +1894,8 @@
 \def\font_helpers_check_strategy_class_d % --- --- def def % pt tt tf
   {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_class_e
    \fi}
@@ -1862,7 +1903,8 @@
 \def\font_helpers_check_strategy_class_e % --- def def def % pt rm tf
   {\ifcsname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
      \setfalse\c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_class_f
    % \expandafter\font_helpers_check_strategy_a
@@ -1871,7 +1913,8 @@
 \def\font_helpers_check_strategy_class_f % def def def def % rm tf
   {\ifcsname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_a
    \fi}
@@ -1881,7 +1924,8 @@
 \def\font_helpers_check_strategy_a % --- --- --- --- % pt tt bf a
   {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
      \setfalse\c_font_auto_size
-     \csname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_b
    \fi}
@@ -1889,7 +1933,8 @@
 \def\font_helpers_check_strategy_b % --- --- --- --- % pt tt bf a
   {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_c
    \fi}
@@ -1897,7 +1942,8 @@
 \def\font_helpers_check_strategy_c % --- --- --- --- % pt tt bf a
   {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_d
    \fi}
@@ -1905,7 +1951,8 @@
 \def\font_helpers_check_strategy_d % --- --- --- --- % pt tt bf a
   {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_e
    \fi}
@@ -1913,7 +1960,8 @@
 \def\font_helpers_check_strategy_e % --- --- --- --- % pt tt bf a
   {\ifcsname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
      \setfalse\c_font_auto_size
-     \csname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \else
      \expandafter\font_helpers_check_strategy_f
    \fi}
@@ -1921,7 +1969,8 @@
 \def\font_helpers_check_strategy_f % --- --- --- --- % pt tt bf a
   {\ifcsname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
      \settrue\c_font_auto_size
-     \csname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+    %\csname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+     \lastnamedcs
    \fi}
 
 \let\applyfontstrategies     \font_helpers_check_strategy_a
@@ -2156,7 +2205,7 @@
       \the\everysetupbodyfont}}
 
 \unexpanded\def\font_basics_switchtobodyfont#specification%
-  {\edef\m_font_step{\bodyfontvariable{#specification}}%
+  {\edef\m_font_step{\font_bodyfontvariable{#specification}}%
    \ifx\m_font_step\empty
      \font_helpers_set_font\zerocount{#specification}%
    \else
@@ -2307,7 +2356,7 @@
 \newmacro\m_font_step
 
 \def\font_helpers_set_bodyfont_step#step%
-  {\edef\m_font_step{\bodyfontvariable{#step}}% not always \cs
+  {\edef\m_font_step{\font_bodyfontvariable{#step}}% not always \cs
    \font_basics_switch_points\m_font_step
    \font_basics_switch_style \fontstyle}
 
diff --git a/tex/context/base/font-inj.lua b/tex/context/base/font-inj.lua
index 36781f72f..89370210d 100644
--- a/tex/context/base/font-inj.lua
+++ b/tex/context/base/font-inj.lua
@@ -74,7 +74,6 @@ local nofregisteredkerns    = 0
 local nofregisteredpairs    = 0
 local nofregisteredmarks    = 0
 local nofregisteredcursives = 0
------ markanchors           = { } -- one base can have more marks
 local keepregisteredcounts  = false
 
 function injections.keepcounts()
@@ -91,10 +90,41 @@ end
 
 -- We need to make sure that a possible metatable will not kick in unexpectedly.
 
+-- function injections.reset(n)
+--     local p = rawget(properties,n)
+--     if p and rawget(p,"injections") then
+--         p.injections = nil
+--     end
+-- end
+
+-- function injections.copy(target,source)
+--     local sp = rawget(properties,source)
+--     if sp then
+--         local tp = rawget(properties,target)
+--         local si = rawget(sp,"injections")
+--         if si then
+--             si = fastcopy(si)
+--             if tp then
+--                 tp.injections = si
+--             else
+--                 propertydata[target] = {
+--                     injections = si,
+--                 }
+--             end
+--         else
+--             if tp then
+--                 tp.injections = nil
+--             end
+--         end
+--     end
+-- end
+
 function injections.reset(n)
     local p = rawget(properties,n)
-    if p and rawget(p,"injections") then
-        p.injections = nil
+    if p then
+        p.injections = false -- { }
+    else
+        properties[n] = false -- { injections = { } }
     end
 end
 
@@ -112,10 +142,17 @@ function injections.copy(target,source)
                     injections = si,
                 }
             end
+        elseif tp then
+            tp.injections = false -- { }
         else
-            if tp then
-                tp.injections = nil
-            end
+            properties[target] = { injections = { } }
+        end
+    else
+        local tp = rawget(properties,target)
+        if tp then
+            tp.injections = false -- { }
+        else
+            properties[target] = false -- { injections = { } }
         end
     end
 end
@@ -367,10 +404,11 @@ local function show(n,what,nested,symbol)
                 local markx     = i.markx     or 0
                 local marky     = i.marky     or 0
                 local markdir   = i.markdir   or 0
-                local markbase  = i.markbase  or 0 -- will be markbasenode
+                local markbase  = i.markbase  or 0
                 local cursivex  = i.cursivex  or 0
                 local cursivey  = i.cursivey  or 0
                 local ligaindex = i.ligaindex or 0
+                local cursbase  = i.cursiveanchor
                 local margin    = nested and 4 or 2
                 --
                 if rightkern ~= 0 or yoffset ~= 0 then
@@ -382,7 +420,13 @@ local function show(n,what,nested,symbol)
                     report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no")
                 end
                 if cursivex ~= 0 or cursivey ~= 0 then
-                    report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+                    if cursbase then
+                        report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+                    else
+                        report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+                    end
+                elseif cursbase then
+                    report_injections("%w%s curs: base",margin,symbol)
                 end
                 if ligaindex ~= 0 then
                     report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua
index b645d9aef..dc3f499ab 100644
--- a/tex/context/base/font-map.lua
+++ b/tex/context/base/font-map.lua
@@ -74,6 +74,71 @@ end
 local f_single = formatters["%04X"]
 local f_double = formatters["%04X%04X"]
 
+-- 0.684 0.661 0,672 0.650 : cache at lua end (more mem)
+-- 0.682 0,672 0.698 0.657 : no cache (moderate mem i.e. lua strings)
+-- 0.644 0.647 0.655 0.645 : convert in c (less mem in theory)
+
+-- local tounicodes = table.setmetatableindex(function(t,unicode)
+--     local s
+--     if unicode < 0x10000 then
+--         s = f_single(unicode)
+--     elseif unicode < 0x1FFFFFFFFF then
+--         s = f_double(floor(unicode/1024),unicode%1024+0xDC00)
+--     else
+--         s = false
+--     end
+--     t[unicode] = s
+--     return s
+-- end)
+--
+-- local function tounicode16(unicode,name)
+--     local s = tounicodes[unicode]
+--     if s then
+--         return s
+--     else
+--         report_fonts("can't convert %a in %a into tounicode",unicode,name)
+--     end
+-- end
+--
+-- local function tounicode16sequence(unicodes,name)
+--     local t = { }
+--     for l=1,#unicodes do
+--         local u = unicodes[l]
+--         local s = tounicodes[u]
+--         if s then
+--             t[l] = s
+--         else
+--             report_fonts ("can't convert %a in %a into tounicode",u,name)
+--             return
+--         end
+--     end
+--     return concat(t)
+-- end
+--
+-- local function tounicode(unicode,name)
+--     if type(unicode) == "table" then
+--         local t = { }
+--         for l=1,#unicode do
+--             local u = unicode[l]
+--             local s = tounicodes[u]
+--             if s then
+--                 t[l] = s
+--             else
+--                 report_fonts ("can't convert %a in %a into tounicode",u,name)
+--                 return
+--             end
+--         end
+--         return concat(t)
+--     else
+--         local s = tounicodes[unicode]
+--         if s then
+--             return s
+--         else
+--             report_fonts("can't convert %a in %a into tounicode",unicode,name)
+--         end
+--     end
+-- end
+
 local function tounicode16(unicode,name)
     if unicode < 0x10000 then
         return f_single(unicode)
@@ -126,7 +191,6 @@ local function tounicode(unicode,name)
     end
 end
 
-
 local function fromunicode16(str)
     if #str == 4 then
         return tonumber(str,16)
diff --git a/tex/context/base/font-mat.mkvi b/tex/context/base/font-mat.mkvi
index c8ee2630b..2e7c2080d 100644
--- a/tex/context/base/font-mat.mkvi
+++ b/tex/context/base/font-mat.mkvi
@@ -79,27 +79,51 @@
 % can be some interference here, which is why we use a different method
 % for bold.
 
+% \def\font_helpers_set_math_family_a
+%   {\ifcsname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+%      \csname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+%    \ifcsname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
+%      \csname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily          \endcsname \else
+%      \font_helpers_set_math_family_b
+%    \fi\fi}
+
+% \def\font_helpers_set_math_family_b
+%   {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+%      \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+%    \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
+%      \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily          \endcsname \else
+%      \font_helpers_set_math_family_c
+%    \fi\fi}
+
+% \def\font_helpers_set_math_family_c
+%   {\ifcsname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+%      \csname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+%    \ifcsname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
+%      \csname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily          \endcsname \else
+%                                                                                                   \settrue \c_font_auto_size
+%    \fi\fi}
+
 \def\font_helpers_set_math_family_a
   {\ifcsname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-     \csname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+     \lastnamedcs \else
    \ifcsname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
-     \csname\??fontinstanceready\fontclass       -\fontbody-\s!mm-\fontfamily          \endcsname \else
+     \lastnamedcs \else
      \font_helpers_set_math_family_b
    \fi\fi}
 
 \def\font_helpers_set_math_family_b
   {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-     \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+     \lastnamedcs \else
    \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
-     \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily          \endcsname \else
+     \lastnamedcs \else
      \font_helpers_set_math_family_c
    \fi\fi}
 
 \def\font_helpers_set_math_family_c
   {\ifcsname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-     \csname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+     \lastnamedcs \else
    \ifcsname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
-     \csname\??fontinstanceready                  \fontbody-\s!mm-\fontfamily          \endcsname \else
+     \lastnamedcs \else
                                                                                                   \settrue \c_font_auto_size
    \fi\fi}
 
@@ -114,11 +138,19 @@
    \let\fontbody\savedfontbody
    \setfalse\c_font_auto_size}
 
+% \def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
+%   {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+%      \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname #font#mbfam\font \else
+%    \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
+%      \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily          \endcsname #font#mbfam\font \else
+%      #font#mbfam#font#mrfam%
+%    \fi\fi}
+
 \def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
   {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname #font#mbfam\font \else
+     \lastnamedcs #font#mbfam\font \else
    \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily          \endcsname \settrue \c_font_auto_size
-     \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily          \endcsname #font#mbfam\font \else
+     \lastnamedcs #font#mbfam\font \else
      #font#mbfam#font#mrfam%
    \fi\fi}
 
@@ -221,7 +253,8 @@
 
 \appendtoks % can be analyzed once
     % why here ..
-    \edef\m_font_class_direction{\ifcsname\??fontclass\fontclass\s!mm\s!direction\endcsname\csname\??fontclass\fontclass\s!mm\s!direction\endcsname\fi}%
+   %\edef\m_font_class_direction{\ifcsname\??fontclass\fontclass\s!mm\s!direction\endcsname\csname\??fontclass\fontclass\s!mm\s!direction\endcsname\fi}%
+    \edef\m_font_class_direction{\begincsname\??fontclass\fontclass\s!mm\s!direction\endcsname}%
     % ...
     \ifx\m_font_class_direction\v!both
       \settrue\c_font_bidirectional_mathstrategy
@@ -362,8 +395,15 @@
 \letvalue{\??fontmathsynchronizer\s!bi }\font_helpers_synchronize_math_family_mb
 \letvalue{\??fontmathsynchronizer\empty}\font_helpers_synchronize_math_family_mr
 
+% \def\font_helpers_synchronize_math_family
+%   {\csname\??fontmathsynchronizer\ifcsname\??fontmathsynchronizer\fontalternative\endcsname\fontalternative\fi\endcsname}
+
 \def\font_helpers_synchronize_math_family
-  {\csname\??fontmathsynchronizer\ifcsname\??fontmathsynchronizer\fontalternative\endcsname\fontalternative\fi\endcsname}
+  {\ifcsname\??fontmathsynchronizer\fontalternative\endcsname
+     \lastnamedcs
+   \else
+     \font_helpers_synchronize_math_family_mr
+   \fi}
 
 \ifdefined \fontid % we need to keep this test for a while
     \appendtoks
@@ -385,7 +425,8 @@
     \to \t_font_math_strategies
 \fi
 
-\def\font_helpers_synchronize_math_bold_strategy{\csname\??fontmathstoredstrategy\fontclass\endcsname}
+%def\font_helpers_synchronize_math_bold_strategy{\csname\??fontmathstoredstrategy\fontclass\endcsname}
+\def\font_helpers_synchronize_math_bold_strategy{\begincsname\??fontmathstoredstrategy\fontclass\endcsname}
 
 \newconditional\c_font_pseudo_bold_math_state
 
diff --git a/tex/context/base/font-nod.lua b/tex/context/base/font-nod.lua
index cb89901cd..62178da30 100644
--- a/tex/context/base/font-nod.lua
+++ b/tex/context/base/font-nod.lua
@@ -324,9 +324,7 @@ function step_tracers.features()
 end
 
 function tracers.fontchar(font,char)
-    local n = new_glyph()
-    setfield(n,"font",font)
-    setchar(n,"char",char)
+    local n = new_glyph(font,char)
     setfield(n,"subtype",256)
     context(tonode(n))
 end
@@ -367,7 +365,7 @@ function step_tracers.codes(i,command,space)
             local d = d and d[c]
             context[command](f,c,d and d.class or "")
         else
-            context("[%s:U+%04X]",getfont(c),getchar(c))
+            context("[%s:U+%05X]",getfont(c),getchar(c))
         end
     end
 
diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua
index 1f1534870..08f69f92a 100644
--- a/tex/context/base/font-ota.lua
+++ b/tex/context/base/font-ota.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['font-otx'] = {
+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",
@@ -26,7 +26,6 @@ local methods             = allocate()
 
 analyzers.initializers    = initializers
 analyzers.methods         = methods
----------.useunicodemarks = false
 
 local a_state             = attributes.private('state')
 
@@ -108,7 +107,7 @@ analyzers.useunicodemarks = false
 -- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
 -- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
 
-function analyzers.setstate(head,font) -- we can skip math
+function analyzers.setstate(head,font)
     local useunicodemarks  = analyzers.useunicodemarks
     local tfmdata = fontdata[font]
     local descriptions = tfmdata.descriptions
diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua
index f8119dcfc..db041c722 100644
--- a/tex/context/base/font-otd.lua
+++ b/tex/context/base/font-otd.lua
@@ -63,11 +63,13 @@ function otf.setdynamics(font,attribute)
             script = definers.checkedscript(fontidentifiers[font],fontresources[font],features)
         end
         local ds = dynamics[script] -- can be metatable magic (less testing)
+-- or dynamics.dflt
         if not ds then
             ds = { }
             dynamics[script] = ds
         end
         local dsl = ds[language]
+-- or ds.dflt
         if not dsl then
             dsl = { }
             ds[language] = dsl
@@ -121,19 +123,22 @@ end
 
 -- we reimplement the dataset resolver
 
-local autofeatures = fonts.analyzers.features -- was: constants
+local autofeatures    = fonts.analyzers.features
+local featuretypes    = otf.tables.featuretypes
+local defaultscript   = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
 
-local resolved  = { } -- we only resolve a font,script,language,attribute pair once
-local wildcard  = "*"
-local default   = "dflt"
+local resolved = { } -- we only resolve a font,script,language,attribute pair once
+local wildcard = "*"
 
 -- what about analyze in local and not in font
 
-local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra)
+local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
     local features = sequence.features
     if features then
         local order = sequence.order
         if order then
+            local featuretype = featuretypes[sequence.type or "unknown"]
             for i=1,#order do --
                 local kind = order[i] --
                 local e_e
@@ -146,33 +151,22 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr
                 if e_e then
                     local scripts = features[kind] --
                     local languages = scripts[script] or scripts[wildcard]
+                    if not languages and autoscript then
+                        langages = defaultscript(featuretype,autoscript,scripts)
+                    end
                     if languages then
-                     -- local valid, what = false
-                        local valid = false
-                        -- not languages[language] or languages[default] or languages[wildcard] because we want tracing
+                        -- we need detailed control over default becase we want to trace
                         -- only first attribute match check, so we assume simple fina's
-                        -- default can become a font feature itself
+                        local valid = false
                         if languages[language] then
-                            valid = e_e -- was true
-                         -- what  = language
-                     -- elseif languages[default] then
-                     --     valid = true
-                     --     what  = default
+                            valid = e_e
                         elseif languages[wildcard] then
-                            valid = e_e -- was true
-                         -- what  = wildcard
+                            valid = e_e
+                        elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
+                            valid = e_e
                         end
                         if valid then
                             local attribute = autofeatures[kind] or false
-                         -- if a_e and dynamic < 0 then
-                         --     valid = false
-                         -- end
-                         -- if trace_applied then
-                         --     local typ, action = match(sequence.type,"(.*)_(.*)") -- brrr
-                         --     report_process(
-                         --         "%s font: %03i, dynamic: %03i, kind: %s, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s",
-                         --         (valid and "+") or "-",font,attr or 0,kind,script,language,what,typ,action,sequence.name)
-                         -- end
                             if trace_applied then
                                 report_process(
                                     "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
@@ -245,8 +239,10 @@ function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in specia
         rl[attr] = ra
         local sequences = tfmdata.resources.sequences
         if sequences then
+            local autoscript   = (s_enabled and s_enabled.autoscript  ) or (a_enabled and a_enabled.autoscript  )
+            local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
             for s=1,#sequences do
-                initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra)
+                initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
             end
         end
     end
diff --git a/tex/context/base/font-oti.lua b/tex/context/base/font-oti.lua
index 06c2a42fa..bacd001a5 100644
--- a/tex/context/base/font-oti.lua
+++ b/tex/context/base/font-oti.lua
@@ -13,9 +13,11 @@ local constructors       = fonts.constructors
 
 local otf                = constructors.newhandler("otf")
 local otffeatures        = constructors.newfeatures("otf")
-local otftables          = otf.tables
 local registerotffeature = otffeatures.register
 
+local otftables          = otf.tables or { }
+otf.tables               = otftables
+
 local allocate           = utilities.storage.allocate
 
 registerotffeature {
@@ -89,3 +91,68 @@ registerotffeature {
     }
 }
 
+-- here (as also in generic
+
+otftables.featuretypes = allocate {
+    gpos_single              = "position",
+    gpos_pair                = "position",
+    gpos_cursive             = "position",
+    gpos_mark2base           = "position",
+    gpos_mark2ligature       = "position",
+    gpos_mark2mark           = "position",
+    gpos_context             = "position",
+    gpos_contextchain        = "position",
+    gsub_single              = "substitution",
+    gsub_multiple            = "substitution",
+    gsub_alternate           = "substitution",
+    gsub_ligature            = "substitution",
+    gsub_context             = "substitution",
+    gsub_contextchain        = "substitution",
+    gsub_reversecontextchain = "substitution",
+    gsub_reversesub          = "substitution",
+}
+
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+    if featuretype == "position" then
+        local default = scripts.dflt
+        if default then
+            if autoscript == "position" or autoscript == true then
+                return default
+            else
+                report_otf("script feature %s not applied, enable default positioning")
+            end
+        else
+            -- no positioning at all
+        end
+    elseif featuretype == "substitution" then
+        local default = scripts.dflt
+        if default then
+            if autoscript == "substitution" or autoscript == true then
+                return default
+            end
+        end
+    end
+end
+
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+    if featuretype == "position" then
+        local default = languages.dflt
+        if default then
+            if autolanguage == "position" or autolanguage == true then
+                return default
+            else
+                report_otf("language feature %s not applied, enable default positioning")
+            end
+        else
+            -- no positioning at all
+        end
+    elseif featuretype == "substitution" then
+        local default = languages.dflt
+        if default then
+            if autolanguage == "substitution" or autolanguage == true then
+                return default
+            end
+        end
+    end
+end
+
diff --git a/tex/context/base/font-otj.lua b/tex/context/base/font-otj.lua
index a942296c9..db30ff9cd 100644
--- a/tex/context/base/font-otj.lua
+++ b/tex/context/base/font-otj.lua
@@ -19,13 +19,17 @@ if not modules then modules = { } end modules ['font-otj'] = {
 -- The subtype test is not needed as there will be no (new) properties set, given that we
 -- reset the properties.
 
+-- As we have a rawget on properties we don't need one on injections.
+
 if not nodes.properties then return end
 
 local next, rawget = next, rawget
 local utfchar = utf.char
 local fastcopy = table.fastcopy
 
-local trace_injections = false  trackers.register("fonts.injections", function(v) trace_injections = v end)
+local trace_injections = false  trackers.register("fonts.injections",         function(v) trace_injections = v end)
+local trace_marks      = false  trackers.register("fonts.injections.marks",   function(v) trace_marks      = v end)
+local trace_cursive    = false  trackers.register("fonts.injections.cursive", function(v) trace_cursive    = v end)
 
 local report_injections = logs.reporter("fonts","injections")
 
@@ -37,6 +41,10 @@ local fontdata           = fonts.hashes.identifiers
 nodes.injections         = nodes.injections or { }
 local injections         = nodes.injections
 
+local tracers            = nodes.tracers
+local setcolor           = tracers and tracers.colors.set
+local resetcolor         = tracers and tracers.colors.reset
+
 local nodecodes          = nodes.nodecodes
 local glyph_code         = nodecodes.glyph
 local disc_code          = nodecodes.disc
@@ -63,6 +71,7 @@ local getdisc            = nuts.getdisc
 local setdisc            = nuts.setdisc
 
 local traverse_id        = nuts.traverse_id
+local traverse_char      = nuts.traverse_char
 local insert_node_before = nuts.insert_before
 local insert_node_after  = nuts.insert_after
 local find_tail          = nuts.tail
@@ -93,10 +102,41 @@ end
 
 -- We need to make sure that a possible metatable will not kick in unexpectedly.
 
+-- function injections.reset(n)
+--     local p = rawget(properties,n)
+--     if p and rawget(p,"injections") then
+--         p.injections = nil
+--     end
+-- end
+
+-- function injections.copy(target,source)
+--     local sp = rawget(properties,source)
+--     if sp then
+--         local tp = rawget(properties,target)
+--         local si = rawget(sp,"injections")
+--         if si then
+--             si = fastcopy(si)
+--             if tp then
+--                 tp.injections = si
+--             else
+--                 propertydata[target] = {
+--                     injections = si,
+--                 }
+--             end
+--         else
+--             if tp then
+--                 tp.injections = nil
+--             end
+--         end
+--     end
+-- end
+
 function injections.reset(n)
     local p = rawget(properties,n)
-    if p and rawget(p,"injections") then
-        p.injections = nil
+    if p then
+        p.injections = false -- { }
+    else
+        properties[n] = false -- { injections = { } }
     end
 end
 
@@ -104,7 +144,8 @@ function injections.copy(target,source)
     local sp = rawget(properties,source)
     if sp then
         local tp = rawget(properties,target)
-        local si = rawget(sp,"injections")
+     -- local si = rawget(sp,"injections")
+        local si = sp.injections
         if si then
             si = fastcopy(si)
             if tp then
@@ -114,10 +155,17 @@ function injections.copy(target,source)
                     injections = si,
                 }
             end
+        elseif tp then
+            tp.injections = false -- { }
         else
-            if tp then
-                tp.injections = nil
-            end
+            properties[target] = { injections = { } }
+        end
+    else
+        local tp = rawget(properties,target)
+        if tp then
+            tp.injections = false -- { }
+        else
+            properties[target] = false -- { injections = { } }
         end
     end
 end
@@ -125,7 +173,8 @@ end
 function injections.setligaindex(n,index)
     local p = rawget(properties,n)
     if p then
-        local i = rawget(p,"injections")
+     -- local i = rawget(p,"injections")
+        local i = p.injections
         if i then
             i.ligaindex = index
         else
@@ -145,7 +194,8 @@ end
 function injections.getligaindex(n,default)
     local p = rawget(properties,n)
     if p then
-        local i = rawget(p,"injections")
+     -- local i = rawget(p,"injections")
+        local i = p.injections
         if i then
             return i.ligaindex or default
         end
@@ -164,10 +214,15 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
     else
         dx = dx - ws
     end
+    if dx == 0 then
+     -- get rid of funny -0
+        dx = 0
+    end
     --
     local p = rawget(properties,start)
     if p then
-        local i = rawget(p,"injections")
+     -- local i = rawget(p,"injections")
+        local i = p.injections
         if i then
             i.cursiveanchor = true
         else
@@ -184,7 +239,8 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
     end
     local p = rawget(properties,nxt)
     if p then
-        local i = rawget(p,"injections")
+     -- local i = rawget(p,"injections")
+        local i = p.injections
         if i then
             i.cursivex = dx
             i.cursivey = dy
@@ -224,6 +280,7 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
             end
             local p = rawget(properties,current)
             if p then
+             -- local i = p[injection]
                 local i = rawget(p,injection)
                 if i then
                     if leftkern ~= 0 then
@@ -280,6 +337,7 @@ function injections.setkern(current,factor,rlmode,x,injection)
             injection = "injections"
         end
         if p then
+         -- local i = rawget(p,injection)
             local i = rawget(p,injection)
             if i then
                 i.leftkern = dx + (i.leftkern or 0)
@@ -304,14 +362,14 @@ end
 function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
     local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
     nofregisteredmarks = nofregisteredmarks + 1
- -- markanchors[nofregisteredmarks] = base
     if rlmode >= 0 then
         dx = tfmbase.width - dx -- see later commented ox
     end
     local p = rawget(properties,start)
     -- hm, dejavu serif does a sloppy mark2mark before mark2base
     if p then
-        local i = rawget(p,"injections")
+     -- local i = rawget(p,"injections")
+        local i = p.injections
         if i then
             if i.markmark then
                 -- out of order mkmk: yes or no or option
@@ -369,10 +427,11 @@ local function show(n,what,nested,symbol)
                 local markx     = i.markx     or 0
                 local marky     = i.marky     or 0
                 local markdir   = i.markdir   or 0
-                local markbase  = i.markbase  or 0 -- will be markbasenode
+                local markbase  = i.markbase  or 0
                 local cursivex  = i.cursivex  or 0
                 local cursivey  = i.cursivey  or 0
                 local ligaindex = i.ligaindex or 0
+                local cursbase  = i.cursiveanchor
                 local margin    = nested and 4 or 2
                 --
                 if rightkern ~= 0 or yoffset ~= 0 then
@@ -384,7 +443,13 @@ local function show(n,what,nested,symbol)
                     report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no")
                 end
                 if cursivex ~= 0 or cursivey ~= 0 then
-                    report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+                    if cursbase then
+                        report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+                    else
+                        report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+                    end
+                elseif cursbase then
+                    report_injections("%w%s curs: base",margin,symbol)
                 end
                 if ligaindex ~= 0 then
                     report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
@@ -482,7 +547,8 @@ local function inject_kerns_only(head,where)
             if getsubtype(current) < 256 then
                 local p = rawget(properties,current)
                 if p then
-                    local i = rawget(p,"injections")
+                 -- local i = rawget(p,"injections")
+                    local i = p.injections
                     if i then
                         -- left|glyph|right
                         local leftkern = i.leftkern
@@ -493,7 +559,8 @@ local function inject_kerns_only(head,where)
                     if prevdisc then
                         local done = false
                         if post then
-                            local i = rawget(p,"postinjections")
+                         -- local i = rawget(p,"postinjections")
+                            local i = p.postinjections
                             if i then
                                 local leftkern = i.leftkern
                                 if leftkern and leftkern ~= 0 then
@@ -504,7 +571,8 @@ local function inject_kerns_only(head,where)
                             end
                         end
                         if replace then
-                            local i = rawget(p,"replaceinjections")
+                         -- local i = rawget(p,"replaceinjections")
+                            local i = p.replaceinjections
                             if i then
                                 local leftkern = i.leftkern
                                 if leftkern and leftkern ~= 0 then
@@ -513,16 +581,6 @@ local function inject_kerns_only(head,where)
                                     done = true
                                 end
                             end
-                        else
--- local i = rawget(p,"emptyinjections")
--- if i then
--- inspect(i)
---     local leftkern = i.leftkern
---     if leftkern and leftkern ~= 0 then
---         replace = newkern(leftkern)
---         done = true
---     end
--- end
                         end
                         if done then
                             setdisc(prevdisc,pre,post,replace)
@@ -537,17 +595,16 @@ local function inject_kerns_only(head,where)
             local done = false
             if pre then
                 -- left|pre glyphs|right
-                for n in traverse_id(glyph_code,pre) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"preinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    pre  = insert_node_before(pre,n,newkern(leftkern))
-                                    done = true
-                                end
+                for n in traverse_char(pre) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"preinjections")
+                        local i = p.injections or p.preinjections
+                        if i then
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                pre  = insert_node_before(pre,n,newkern(leftkern))
+                                done = true
                             end
                         end
                     end
@@ -555,17 +612,16 @@ local function inject_kerns_only(head,where)
             end
             if post then
                 -- left|post glyphs|right
-                for n in traverse_id(glyph_code,post) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"postinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    post = insert_node_before(post,n,newkern(leftkern))
-                                    done = true
-                                end
+                for n in traverse_char(post) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"postinjections")
+                        local i = p.injections or p.postinjections
+                        if i then
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                post = insert_node_before(post,n,newkern(leftkern))
+                                done = true
                             end
                         end
                     end
@@ -573,17 +629,16 @@ local function inject_kerns_only(head,where)
             end
             if replace then
                 -- left|replace glyphs|right
-                for n in traverse_id(glyph_code,replace) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"replaceinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    replace = insert_node_before(replace,n,newkern(leftkern))
-                                    done    = true
-                                end
+                for n in traverse_char(replace) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"replaceinjections")
+                        local i = p.injections or p.replaceinjections
+                        if i then
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                replace = insert_node_before(replace,n,newkern(leftkern))
+                                done    = true
                             end
                         end
                     end
@@ -630,7 +685,8 @@ local function inject_pairs_only(head,where)
             if getsubtype(current) < 256 then
                 local p = rawget(properties,current)
                 if p then
-                    local i = rawget(p,"injections")
+                 -- local i = rawget(p,"injections")
+                    local i = p.injections
                     if i then
                         -- left|glyph|right
                         local yoffset = i.yoffset
@@ -646,7 +702,8 @@ local function inject_pairs_only(head,where)
                             insert_node_after(head,current,newkern(rightkern))
                         end
                     else
-                        local i = rawget(p,"emptyinjections")
+                     -- local i = rawget(p,"emptyinjections")
+                        local i = p.emptyinjections
                         if i then
                             -- glyph|disc|glyph (special case)
                             local rightkern = i.rightkern
@@ -665,7 +722,8 @@ local function inject_pairs_only(head,where)
                     if prevdisc and p then
                         local done = false
                         if post then
-                            local i = rawget(p,"postinjections")
+                         -- local i = rawget(p,"postinjections")
+                            local i = p.postinjections
                             if i then
                                 local leftkern = i.leftkern
                                 if leftkern and leftkern ~= 0 then
@@ -676,7 +734,8 @@ local function inject_pairs_only(head,where)
                             end
                         end
                         if replace then
-                            local i = rawget(p,"replaceinjections")
+                         -- local i = rawget(p,"replaceinjections")
+                            local i = p.replaceinjections
                             if i then
                                 local leftkern = i.leftkern
                                 if leftkern and leftkern ~= 0 then
@@ -699,26 +758,25 @@ local function inject_pairs_only(head,where)
             local done = false
             if pre then
                 -- left|pre glyphs|right
-                for n in traverse_id(glyph_code,pre) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"preinjections")
-                            if i then
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    pre  = insert_node_before(pre,n,newkern(leftkern))
-                                    done = true
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(pre,n,newkern(rightkern))
-                                    done = true
-                                end
+                for n in traverse_char(pre) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"preinjections")
+                        local i = p.injections or p.preinjections
+                        if i then
+                            local yoffset = i.yoffset
+                            if yoffset and yoffset ~= 0 then
+                                setfield(n,"yoffset",yoffset)
+                            end
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                pre  = insert_node_before(pre,n,newkern(leftkern))
+                                done = true
+                            end
+                            local rightkern = i.rightkern
+                            if rightkern and rightkern ~= 0 then
+                                insert_node_after(pre,n,newkern(rightkern))
+                                done = true
                             end
                         end
                     end
@@ -726,26 +784,25 @@ local function inject_pairs_only(head,where)
             end
             if post then
                 -- left|post glyphs|right
-                for n in traverse_id(glyph_code,post) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"postinjections")
-                            if i then
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    post = insert_node_before(post,n,newkern(leftkern))
-                                    done = true
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(post,n,newkern(rightkern))
-                                    done = true
-                                end
+                for n in traverse_char(post) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"postinjections")
+                        local i = p.injections or p.postinjections
+                        if i then
+                            local yoffset = i.yoffset
+                            if yoffset and yoffset ~= 0 then
+                                setfield(n,"yoffset",yoffset)
+                            end
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                post = insert_node_before(post,n,newkern(leftkern))
+                                done = true
+                            end
+                            local rightkern = i.rightkern
+                            if rightkern and rightkern ~= 0 then
+                                insert_node_after(post,n,newkern(rightkern))
+                                done = true
                             end
                         end
                     end
@@ -753,26 +810,25 @@ local function inject_pairs_only(head,where)
             end
             if replace then
                 -- left|replace glyphs|right
-                for n in traverse_id(glyph_code,replace) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"replaceinjections")
-                            if i then
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    replace = insert_node_before(replace,n,newkern(leftkern))
-                                    done    = true
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(replace,n,newkern(rightkern))
-                                    done = true
-                                end
+                for n in traverse_char(replace) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"replaceinjections")
+                        local i = p.injections or p.replaceinjections
+                        if i then
+                            local yoffset = i.yoffset
+                            if yoffset and yoffset ~= 0 then
+                                setfield(n,"yoffset",yoffset)
+                            end
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                replace = insert_node_before(replace,n,newkern(leftkern))
+                                done    = true
+                            end
+                            local rightkern = i.rightkern
+                            if rightkern and rightkern ~= 0 then
+                                insert_node_after(replace,n,newkern(rightkern))
+                                done = true
                             end
                         end
                     end
@@ -782,7 +838,8 @@ local function inject_pairs_only(head,where)
                 if pre then
                     local p = rawget(properties,prevglyph)
                     if p then
-                        local i = rawget(p,"preinjections")
+                     -- local i = rawget(p,"preinjections")
+                        local i = p.preinjections
                         if i then
                             -- glyph|pre glyphs
                             local rightkern = i.rightkern
@@ -796,7 +853,8 @@ local function inject_pairs_only(head,where)
                 if replace then
                     local p = rawget(properties,prevglyph)
                     if p then
-                        local i = rawget(p,"replaceinjections")
+                     -- local i = rawget(p,"replaceinjections")
+                        local i = p.replaceinjections
                         if i then
                             -- glyph|replace glyphs
                             local rightkern = i.rightkern
@@ -829,6 +887,36 @@ local function inject_pairs_only(head,where)
     return tonode(head), true
 end
 
+-- local function showoffset(n,flag)
+--     local ox = getfield(n,"xoffset")
+--     local oy = getfield(n,"yoffset")
+--     if flag then
+--         if ox == 0 then
+--             setcolor(n,oy == 0 and "darkgray" or "darkgreen")
+--         else
+--             setcolor(n,oy == 0 and "darkblue" or "darkred")
+--         end
+--     else
+--         if ox == 0 then
+--             setcolor(n,oy == 0 and "gray" or "green")
+--         else
+--             setcolor(n,oy == 0 and "blue" or "red")
+--         end
+--     end
+-- end
+
+local function showoffset(n,flag)
+    local o = getfield(n,"xoffset")
+    if o == 0 then
+        o = getfield(n,"yoffset")
+    end
+    if o ~= 0 then
+        setcolor(n,flag and "darkred" or "darkgreen")
+    else
+        resetcolor(n)
+    end
+end
+
 local function inject_everything(head,where)
     head = tonut(head)
     if trace_injections then
@@ -838,6 +926,9 @@ local function inject_everything(head,where)
     local hasmarks    = nofregisteredmarks    > 0
     --
     local current   = head
+    local last      = nil
+    local font      = font
+    local markdata  = nil
     local prev      = nil
     local next      = nil
     local prevdisc  = nil
@@ -847,11 +938,13 @@ local function inject_everything(head,where)
     local replace   = nil -- saves a lookup
     --
     local cursiveanchor = nil
-    local lastanchor    = nil
     local minc          = 0
     local maxc          = 0
-    local last          = 0
     local glyphs        = { }
+    local marks         = { }
+    local nofmarks      = 0
+    --
+    -- move out
     --
     local function processmark(p,n,pn) -- p = basenode
         local px = getfield(p,"xoffset")
@@ -859,7 +952,8 @@ local function inject_everything(head,where)
         local rightkern = nil
         local pp = rawget(properties,p)
         if pp then
-            pp = rawget(pp,"injections")
+         -- pp = rawget(pp,"injections")
+            pp = pp.injections
             if pp then
                 rightkern = pp.rightkern
             end
@@ -890,7 +984,6 @@ local function inject_everything(head,where)
                 end
             end
         else
-            -- we need to deal with fonts that have marks with width
          -- if pn.markdir < 0 then
          --     ox = px - pn.markx
          --  -- report_injections("r2l case 3: %p",ox)
@@ -902,27 +995,18 @@ local function inject_everything(head,where)
             local wn = getfield(n,"width") -- in arial marks have widths
             if wn ~= 0 then
                 -- bad: we should center
-             -- insert_node_before(head,n,newkern(-wn/2))
-             -- insert_node_after(head,n,newkern(-wn/2))
                 pn.leftkern  = -wn/2
                 pn.rightkern = -wn/2
-             -- wx[n] = { 0, -wn/2, 0, -wn }
             end
-            -- so far
         end
+        local oy = getfield(n,"yoffset") + getfield(p,"yoffset") + pn.marky
         setfield(n,"xoffset",ox)
-        --
-        local py = getfield(p,"yoffset")
-     -- local oy = 0
-     -- if marks[p] then
-     --     oy = py + pn.marky
-     -- else
-     --     oy = getfield(n,"yoffset") + py + pn.marky
-     -- end
-        local oy = getfield(n,"yoffset") + py + pn.marky
         setfield(n,"yoffset",oy)
+        if trace_marks then
+            showoffset(n,true)
+        end
     end
-    --
+    -- todo: marks in disc
     while current do
         local id   = getid(current)
         local next = getnext(current)
@@ -930,79 +1014,82 @@ local function inject_everything(head,where)
             if getsubtype(current) < 256 then
                 local p = rawget(properties,current)
                 if p then
-                    local i = rawget(p,"injections")
+                 -- local i = rawget(p,"injections")
+                    local i = p.injections
                     if i then
-                        -- cursives
-                        if hascursives then
-                            local cursivex = p.cursivex
-                            if cursivex then
-                                if cursiveanchor then
-                                    if cursivex ~= 0 then
-                                        p.leftkern = (p.leftkern or 0) + cursivex
-                                    end
-                                    if lastanchor then
+                        local pm = i.markbasenode
+                        if pm then
+                            nofmarks = nofmarks + 1
+                            marks[nofmarks] = current
+                        else
+                            if hascursives then
+                                local cursivex = i.cursivex
+                                if cursivex then
+                                    if cursiveanchor then
+                                        if cursivex ~= 0 then
+                                            i.leftkern = (i.leftkern or 0) + cursivex
+                                        end
                                         if maxc == 0 then
                                             minc = 1
                                             maxc = 1
-                                            glyphs[1] = lastanchor
+                                            glyphs[1] = cursiveanchor
                                         else
                                             maxc = maxc + 1
-                                            glyphs[maxc] = lastanchor
+                                            glyphs[maxc] = cursiveanchor
                                         end
-                                        properties[cursiveanchor].cursivedy = p.cursivey
+                                        properties[cursiveanchor].cursivedy = i.cursivey -- cursiveprops
+                                        last = current
+                                    else
+                                        maxc = 0
                                     end
-                                    last = n
-                                else
-                                    maxc = 0
-                                end
-                            elseif maxc > 0 then
-                                local ny = getfield(n,"yoffset")
-                                for i=maxc,minc,-1 do
-                                    local ti = glyphs[i]
-                                    ny = ny + properties[ti].cursivedy
-                                    setfield(ti,"yoffset",ny) -- why not add ?
-                                end
-                                maxc = 0
-                            end
-                            if p.cursiveanchor then
-                                cursiveanchor = current -- no need for both now
-                                lastanchor    = current
-                            else
-                                cursiveanchor = nil
-                                lastanchor    = nil
-                                if maxc > 0 then
-                                    local ny = getfield(n,"yoffset")
+                                elseif maxc > 0 then
+                                    local ny = getfield(current,"yoffset")
                                     for i=maxc,minc,-1 do
                                         local ti = glyphs[i]
                                         ny = ny + properties[ti].cursivedy
                                         setfield(ti,"yoffset",ny) -- why not add ?
+                                        if trace_cursive then
+                                            showoffset(ti)
+                                        end
                                     end
                                     maxc = 0
+                                    cursiveanchor = nil
+                                end
+                                if i.cursiveanchor then
+                                    cursiveanchor = current -- no need for both now
+                                else
+                                    if maxc > 0 then
+                                        local ny = getfield(current,"yoffset")
+                                        for i=maxc,minc,-1 do
+                                            local ti = glyphs[i]
+                                            ny = ny + properties[ti].cursivedy
+                                            setfield(ti,"yoffset",ny) -- why not add ?
+                                            if trace_cursive then
+                                                showoffset(ti)
+                                            end
+                                        end
+                                        maxc = 0
+                                    end
+                                    cursiveanchor = nil
                                 end
                             end
-                        end
-                        -- marks
-                        if hasmarks then
-                            local pm = i.markbasenode
-                            if pm then
-                                processmark(pm,current,i)
+                            -- left|glyph|right
+                            local yoffset = i.yoffset
+                            if yoffset and yoffset ~= 0 then
+                                setfield(current,"yoffset",yoffset)
+                            end
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                insert_node_before(head,current,newkern(leftkern))
+                            end
+                            local rightkern = i.rightkern
+                            if rightkern and rightkern ~= 0 then
+                                insert_node_after(head,current,newkern(rightkern))
                             end
-                        end
-                        -- left|glyph|right
-                        local yoffset = i.yoffset
-                        if yoffset and yoffset ~= 0 then
-                            setfield(current,"yoffset",yoffset)
-                        end
-                        local leftkern = i.leftkern
-                        if leftkern and leftkern ~= 0 then
-                            insert_node_before(head,current,newkern(leftkern))
-                        end
-                        local rightkern = i.rightkern
-                        if rightkern and rightkern ~= 0 then
-                            insert_node_after(head,current,newkern(rightkern))
                         end
                     else
-                        local i = rawget(p,"emptyinjections")
+                     -- local i = rawget(p,"emptyinjections")
+                        local i = p.emptyinjections
                         if i then
                             -- glyph|disc|glyph (special case)
                             local rightkern = i.rightkern
@@ -1022,7 +1109,8 @@ local function inject_everything(head,where)
                         if p then
                             local done = false
                             if post then
-                                local i = rawget(p,"postinjections")
+                             -- local i = rawget(p,"postinjections")
+                                local i = p.postinjections
                                 if i then
                                     local leftkern = i.leftkern
                                     if leftkern and leftkern ~= 0 then
@@ -1033,7 +1121,8 @@ local function inject_everything(head,where)
                                 end
                             end
                             if replace then
-                                local i = rawget(p,"replaceinjections")
+                             -- local i = rawget(p,"replaceinjections")
+                                local i = p.replaceinjections
                                 if i then
                                     local leftkern = i.leftkern
                                     if leftkern and leftkern ~= 0 then
@@ -1055,11 +1144,10 @@ local function inject_everything(head,where)
                         for i=maxc,minc,-1 do
                             local ti = glyphs[i]
                             ny = ny + properties[ti].cursivedy
-                            setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- ?
+                            setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- can be mark
                         end
                         maxc = 0
                         cursiveanchor = nil
-                        lastanchor = nil
                     end
                 end
             end
@@ -1070,32 +1158,31 @@ local function inject_everything(head,where)
             local done = false
             if pre then
                 -- left|pre glyphs|right
-                for n in traverse_id(glyph_code,pre) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"preinjections")
-                            if i then
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    pre  = insert_node_before(pre,n,newkern(leftkern))
-                                    done = true
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(pre,n,newkern(rightkern))
-                                    done = true
-                                end
+                for n in traverse_char(pre) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"preinjections")
+                        local i = p.injections or p.preinjections
+                        if i then
+                            local yoffset = i.yoffset
+                            if yoffset and yoffset ~= 0 then
+                                setfield(n,"yoffset",yoffset)
                             end
-                            if hasmarks then
-                                local pm = i.markbasenode
-                                if pm then
-                                    processmark(pm,current,i)
-                                end
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                pre  = insert_node_before(pre,n,newkern(leftkern))
+                                done = true
+                            end
+                            local rightkern = i.rightkern
+                            if rightkern and rightkern ~= 0 then
+                                insert_node_after(pre,n,newkern(rightkern))
+                                done = true
+                            end
+                        end
+                        if hasmarks then
+                            local pm = i.markbasenode
+                            if pm then
+                                processmark(pm,current,i)
                             end
                         end
                     end
@@ -1103,32 +1190,31 @@ local function inject_everything(head,where)
             end
             if post then
                 -- left|post glyphs|right
-                for n in traverse_id(glyph_code,post) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"postinjections")
-                            if i then
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    post = insert_node_before(post,n,newkern(leftkern))
-                                    done = true
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(post,n,newkern(rightkern))
-                                    done = true
-                                end
+                for n in traverse_char(post) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"postinjections")
+                        local i = p.injections or p.postinjections
+                        if i then
+                            local yoffset = i.yoffset
+                            if yoffset and yoffset ~= 0 then
+                                setfield(n,"yoffset",yoffset)
                             end
-                            if hasmarks then
-                                local pm = i.markbasenode
-                                if pm then
-                                    processmark(pm,current,i)
-                                end
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                post = insert_node_before(post,n,newkern(leftkern))
+                                done = true
+                            end
+                            local rightkern = i.rightkern
+                            if rightkern and rightkern ~= 0 then
+                                insert_node_after(post,n,newkern(rightkern))
+                                done = true
+                            end
+                        end
+                        if hasmarks then
+                            local pm = i.markbasenode
+                            if pm then
+                                processmark(pm,current,i)
                             end
                         end
                     end
@@ -1136,32 +1222,31 @@ local function inject_everything(head,where)
             end
             if replace then
                 -- left|replace glyphs|right
-                for n in traverse_id(glyph_code,replace) do
-                    if getsubtype(n) < 256 then
-                        local p = rawget(properties,n)
-                        if p then
-                            local i = rawget(p,"injections") or rawget(p,"replaceinjections")
-                            if i then
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    replace = insert_node_before(replace,n,newkern(leftkern))
-                                    done    = true
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(replace,n,newkern(rightkern))
-                                    done = true
-                                end
+                for n in traverse_char(replace) do
+                    local p = rawget(properties,n)
+                    if p then
+                     -- local i = rawget(p,"injections") or rawget(p,"replaceinjections")
+                        local i = p.injections or p.replaceinjections
+                        if i then
+                            local yoffset = i.yoffset
+                            if yoffset and yoffset ~= 0 then
+                                setfield(n,"yoffset",yoffset)
                             end
-                            if hasmarks then
-                                local pm = i.markbasenode
-                                if pm then
-                                    processmark(pm,current,i)
-                                end
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
+                                replace = insert_node_before(replace,n,newkern(leftkern))
+                                done    = true
+                            end
+                            local rightkern = i.rightkern
+                            if rightkern and rightkern ~= 0 then
+                                insert_node_after(replace,n,newkern(rightkern))
+                                done = true
+                            end
+                        end
+                        if hasmarks then
+                            local pm = i.markbasenode
+                            if pm then
+                                processmark(pm,current,i)
                             end
                         end
                     end
@@ -1171,7 +1256,8 @@ local function inject_everything(head,where)
                 if pre then
                     local p = rawget(properties,prevglyph)
                     if p then
-                        local i = rawget(p,"preinjections")
+                     -- local i = rawget(p,"preinjections")
+                        local i = p.preinjections
                         if i then
                             -- glyph|pre glyphs
                             local rightkern = i.rightkern
@@ -1185,7 +1271,8 @@ local function inject_everything(head,where)
                 if replace then
                     local p = rawget(properties,prevglyph)
                     if p then
-                        local i = rawget(p,"replaceinjections")
+                     -- local i = rawget(p,"replaceinjections")
+                        local i = p.replaceinjections
                         if i then
                             -- glyph|replace glyphs
                             local rightkern = i.rightkern
@@ -1210,17 +1297,31 @@ local function inject_everything(head,where)
         current = next
     end
     -- cursive
-    if hascursives then
-        if last and maxc > 0 then
-            local ny = getfield(last,"yoffset")
-            for i=maxc,minc,-1 do
-                local ti = glyphs[i]
-                ny = ny + properties[ti].cursivedy
-                setfield(ti,"yoffset",ny) -- why not add ?
+    if hascursives and maxc > 0 then
+        local ny = getfield(last,"yoffset")
+        for i=maxc,minc,-1 do
+            local ti = glyphs[i]
+            ny = ny + properties[ti].cursivedy
+            setfield(ti,"yoffset",ny) -- why not add ?
+            if trace_cursive then
+                showoffset(ti)
             end
         end
     end
     --
+    if nofmarks > 0 then
+        for i=1,nofmarks do
+            local m = marks[i]
+            local p = rawget(properties,m)
+         -- local i = rawget(p,"injections")
+            local i = p.injections
+            local b = i.markbasenode
+            processmark(b,m,i)
+        end
+    elseif hasmarks then
+        -- sometyhing bad happened
+    end
+    --
     if keepregisteredcounts then
         keepregisteredcounts  = false
     else
diff --git a/tex/context/base/font-otl.lua b/tex/context/base/font-otl.lua
index 559cbb6a4..8844bd5c6 100644
--- a/tex/context/base/font-otl.lua
+++ b/tex/context/base/font-otl.lua
@@ -53,7 +53,7 @@ local report_otf         = logs.reporter("fonts","otf loading")
 local fonts              = fonts
 local otf                = fonts.handlers.otf
 
-otf.version              = 3.006 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version              = 3.008 -- beware: also sync font-mis.lua and in mtx-fonts
 otf.cache                = containers.define("fonts", "otl", otf.version, true)
 
 local otfreaders         = otf.readers
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index 6f5bf345b..f87cd1ab5 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -132,7 +132,7 @@ results in different tables.
 -- gpos_context              ok          --
 -- gpos_contextchain         ok          --
 --
--- todo: contextpos and contextsub and class stuff
+-- todo: contextpos
 --
 -- actions:
 --
@@ -243,7 +243,6 @@ local wildcard           = "*"
 local default            = "dflt"
 
 local nodecodes          = nodes.nodecodes
-local whatcodes          = nodes.whatcodes
 local glyphcodes         = nodes.glyphcodes
 local disccodes          = nodes.disccodes
 
@@ -315,8 +314,6 @@ local notmatchpre         = { }
 local notmatchpost        = { }
 local notmatchreplace     = { }
 
--- head is always a whatsit so we can safely assume that head is not changed
-
 -- we use this for special testing and documentation
 
 local checkstep       = (nodes and nodes.tracers and nodes.tracers.steppers.check)    or function() end
@@ -2702,26 +2699,49 @@ otf.chainhandlers = {
     verbose = verbose_handle_contextchain,
 }
 
+local handle_contextchain = nil
+
+-- normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
+
+function chained_contextchain(head,start,stop,...)
+    local steps    = currentlookup.steps
+    local nofsteps = currentlookup.nofsteps
+    if nofsteps > 1 then
+        reportmoresteps(dataset,sequence)
+    end
+    return handle_contextchain(head,start,...)
+end
+
 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
+        if handle_contextchain then -- no need for a message while making the format
             logwarning("installing normal contextchain handler")
         end
-        handlers.contextchain = normal_handle_contextchain
+        handle_contextchain = normal_handle_contextchain
     else
         logwarning("installing contextchain handler %a",method)
         local handler = otf.chainhandlers[method]
-        handlers.contextchain = function(...)
+        handle_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
+
+    handlers.gsub_context             = handle_contextchain
+    handlers.gsub_contextchain        = handle_contextchain
+    handlers.gsub_reversecontextchain = handle_contextchain
+    handlers.gpos_contextchain        = handle_contextchain
+    handlers.gpos_context             = handle_contextchain
+
+    handlers.contextchain = handle_contextchain
+
 end
 
+chainprocs.gsub_context             = chained_contextchain
+chainprocs.gsub_contextchain        = chained_contextchain
+chainprocs.gsub_reversecontextchain = chained_contextchain
+chainprocs.gpos_contextchain        = chained_contextchain
+chainprocs.gpos_context             = chained_contextchain
+
 otf.setcontextchain()
 
 local missing = { } -- we only report once
@@ -2761,20 +2781,33 @@ end)
 
 -- fonts.hashes.lookups = lookuphashes
 
-local autofeatures = fonts.analyzers.features -- was: constants
+local autofeatures    = fonts.analyzers.features
+local featuretypes    = otf.tables.featuretypes
+local defaultscript   = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
 
-local function initialize(sequence,script,language,enabled)
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
     local features = sequence.features
     if features then
         local order = sequence.order
         if order then
-            for i=1,#order do --
-                local kind  = order[i] --
+            local featuretype = featuretypes[sequence.type or "unknown"]
+            for i=1,#order do
+                local kind  = order[i]
                 local valid = enabled[kind]
                 if valid then
-                    local scripts = features[kind] --
-                    local languages = scripts[script] or scripts[wildcard]
-                    if languages and (languages[language] or languages[wildcard]) then
+                    local scripts   = features[kind]
+                    local languages = scripts and (
+                        scripts[script] or
+                        scripts[wildcard] or
+                        (autoscript and defaultscript(featuretype,autoscript,scripts))
+                    )
+                    local enabled = languages and (
+                        languages[language] or
+                        languages[wildcard] or
+                        (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+                    )
+                    if enabled then
                         return { valid, autofeatures[kind] or false, sequence, kind }
                     end
                 end
@@ -2787,11 +2820,13 @@ local function initialize(sequence,script,language,enabled)
 end
 
 function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
-    local shared     = tfmdata.shared
-    local properties = tfmdata.properties
-    local language   = properties.language or "dflt"
-    local script     = properties.script   or "dflt"
-    local enabled    = shared.features
+    local shared       = tfmdata.shared
+    local properties   = tfmdata.properties
+    local language     = properties.language or "dflt"
+    local script       = properties.script   or "dflt"
+    local enabled      = shared.features
+    local autoscript   = enabled and enabled.autoscript
+    local autolanguage = enabled and enabled.autolanguage
     local res = resolved[font]
     if not res then
         res = { }
@@ -2810,7 +2845,7 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
         rs[language] = rl
         local sequences = tfmdata.resources.sequences
         for s=1,#sequences do
-            local v = enabled and initialize(sequences[s],script,language,enabled)
+            local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
             if v then
                 rl[#rl+1] = v
             end
@@ -3794,10 +3829,10 @@ local function split(replacement,original)
     return result
 end
 
-local valid = {
-    coverage        = { chainsub = true, chainpos = true, contextsub = true },
+local valid = { -- does contextpos work?
+    coverage        = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
     reversecoverage = { reversesub = true },
-    glyphs          = { chainsub = true, chainpos = true },
+    glyphs          = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
 }
 
 local function prepare_contextchains(tfmdata)
diff --git a/tex/context/base/font-otr.lua b/tex/context/base/font-otr.lua
index f9dce389e..a5cb58c63 100644
--- a/tex/context/base/font-otr.lua
+++ b/tex/context/base/font-otr.lua
@@ -1954,7 +1954,8 @@ function readers.loadfont(filename,n)
                 hasitalics = fontdata.hasitalics or false,
             },
             resources     = {
-                filename      = fontdata.filename,
+             -- filename      = fontdata.filename,
+                filename      = filename,
                 private       = privateoffset,
                 duplicates    = fontdata.duplicates  or { },
                 features      = fontdata.features    or { }, -- we need to add these in the loader
diff --git a/tex/context/base/font-ots.lua b/tex/context/base/font-ots.lua
index 3bb2d326a..dd50a2e62 100644
--- a/tex/context/base/font-ots.lua
+++ b/tex/context/base/font-ots.lua
@@ -196,7 +196,6 @@ local wildcard           = "*"
 local default            = "dflt"
 
 local nodecodes          = nodes.nodecodes
-local whatcodes          = nodes.whatcodes
 local glyphcodes         = nodes.glyphcodes
 local disccodes          = nodes.disccodes
 
@@ -204,8 +203,8 @@ local glyph_code         = nodecodes.glyph
 local glue_code          = nodecodes.glue
 local disc_code          = nodecodes.disc
 local math_code          = nodecodes.math
-local dir_code           = nodecodes.dir or whatcodes.dir
-local localpar_code      = nodecodes.localpar or whatcodes.localpar
+local dir_code           = nodecodes.dir
+local localpar_code      = nodecodes.localpar
 
 local discretionary_code = disccodes.discretionary
 local ligature_code      = glyphcodes.ligature
@@ -314,7 +313,9 @@ local function gref(n) -- currently the same as in font-otb
 end
 
 local function cref(dataset,sequence,index)
-    if index then
+    if not dataset then
+        return "no valid dataset"
+    elseif index then
         return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index)
     else
         return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name)
@@ -671,7 +672,7 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
         setchar(start,multiple[1])
         if nofmultiples > 1 then
             local sn = getnext(start)
-            for k=2,nofmultiples do -- todo: use insert_node
+            for k=2,nofmultiples do
 -- untested:
 --
 -- while ignoremarks and marks[getchar(sn)] then
@@ -680,11 +681,7 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
                 local n = copy_node(start) -- ignore components
                 resetinjection(n)
                 setchar(n,multiple[k])
-                setboth(n,start,sn)
-                if sn then
-                    setprev(sn,n)
-                end
-                setnext(start,n)
+                insert_node_after(head,start,n)
                 start = n
             end
         end
@@ -777,9 +774,9 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
     local startchar = getchar(start)
     if marks[startchar] then
         while current do
-            local id = getid(current)
-            if ischar(current,currentfont) then
-                local lg = ligature[getchar(current)]
+            local ch = ischar(current,currentfont)
+            if ch then
+                local lg = ligature[ch]
                 if lg then
                     stop     = current
                     ligature = lg
@@ -814,8 +811,8 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
             local id = getid(current)
             -- weird test here
             if id == glyph_code then -- not needed
-                if ischar(current,currentfont) then
-                    local char = getchar(current)
+                local char = ischar(current,currentfont)
+                if char then
                     if skipmark and marks[char] then
                         current = getnext(current)
                     else -- ligature is a tree
@@ -894,50 +891,54 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
     else
         local prev = start
         local done = false
-        while snext and ischar(snext,currentfont) do
-            local nextchar = getchar(snext)
-            local krn = kerns[nextchar]
-            if not krn and marks[nextchar] then
-                prev = snext
-                snext = getnext(snext)
-            elseif not krn then
-                break
-            elseif step.format == "pair" then
-                local a, b = krn[1], krn[2]
-                if optimizekerns then
-                    -- this permits a mixed table, but we could also decide to optimize this
-                    -- in the loader and use format 'kern'
-                    if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
-                        local k = setkern(snext,factor,rlmode,a[3],injection)
+        while snext do
+            local nextchar = ischar(snext,currentfont)
+            if nextchar then
+                local krn = kerns[nextchar]
+                if not krn and marks[nextchar] then
+                    prev = snext
+                    snext = getnext(snext)
+                elseif not krn then
+                    break
+                elseif step.format == "pair" then
+                    local a, b = krn[1], krn[2]
+                    if optimizekerns then
+                        -- this permits a mixed table, but we could also decide to optimize this
+                        -- in the loader and use format 'kern'
+                        if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
+                            local k = setkern(snext,factor,rlmode,a[3],injection)
+                            if trace_kerns then
+                                logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
+                            end
+                            done = true
+                            break
+                        end
+                    end
+                    if a and #a > 0 then
+                        local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection)
                         if trace_kerns then
-                            logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
+                            local startchar = getchar(start)
+                            logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
                         end
-                        done = true
-                        break
                     end
-                end
-                if a and #a > 0 then
-                    local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection)
-                    if trace_kerns then
-                        local startchar = getchar(start)
-                        logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+                    if b and #b > 0 then
+                        local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+                        if trace_kerns then
+                            local startchar = getchar(snext)
+                            logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+                        end
                     end
-                end
-                if b and #b > 0 then
-                    local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
+                    done = true
+                    break
+                elseif krn ~= 0 then
+                    local k = setkern(snext,factor,rlmode,krn,injection)
                     if trace_kerns then
-                        local startchar = getchar(snext)
-                        logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
+                        logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
                     end
+                    done = true
+                    break
                 end
-                done = true
-                break
-            elseif krn ~= 0 then
-                local k = setkern(snext,factor,rlmode,krn,injection)
-                if trace_kerns then
-                    logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
-                end
-                done = true
+            else
                 break
             end
         end
@@ -956,36 +957,47 @@ function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
     local markchar = getchar(start)
     if marks[markchar] then
         local base = getprev(start) -- [glyph] [start=mark]
-        if base and ischar(base,currentfont) then
-            local basechar = getchar(base)
-            if marks[basechar] then
-                while true do
-                    base = getprev(base)
-                    if base and ischar(base,currentfont) then
-                        basechar = getchar(base)
-                        if not marks[basechar] then
-                            break
-                        end
-                    else
-                        if trace_bugs then
-                            logwarning("%s: no base for mark %s",pref(dataset,sequence),gref(markchar))
+        if base then
+            local basechar = ischar(base,currentfont)
+            if basechar then
+                if marks[basechar] then
+                    while true do
+                        base = getprev(base)
+                        if base then
+                            basechar = ischar(base,currentfont)
+                            if basechar then
+                                if not marks[basechar] then
+                                    break
+                                end
+                            else
+                                if trace_bugs then
+                                    logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+                                end
+                                return head, start, false
+                            end
+                        else
+                            if trace_bugs then
+                                logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+                            end
+                            return head, start, false
                         end
-                        return head, start, false
                     end
                 end
-            end
-            local ba = markanchors[1][basechar]
-            if ba then
-                local ma = markanchors[2]
-                local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
-                if trace_marks then
-                    logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
-                        pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+                local ba = markanchors[1][basechar]
+                if ba then
+                    local ma = markanchors[2]
+                    local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+                    if trace_marks then
+                        logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+                            pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+                    end
+                    return head, start, true
                 end
-                return head, start, true
+            elseif trace_bugs then
+                logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),1)
             end
         elseif trace_bugs then
-            logwarning("%s: prev node is no char",pref(dataset,sequence))
+            logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),2)
         end
     elseif trace_bugs then
         logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
@@ -999,49 +1011,60 @@ function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlm
     local markchar = getchar(start)
     if marks[markchar] then
         local base = getprev(start) -- [glyph] [optional marks] [start=mark]
-        if base and ischar(base,currentfont) then
-            local basechar = getchar(base)
-            if marks[basechar] then
-                while true do
-                    base = getprev(base)
-                    if base and ischar(base,currentfont) then
-                        basechar = getchar(base)
-                        if not marks[basechar] then
-                            break
-                        end
-                    else
-                        if trace_bugs then
-                            logwarning("%s: no base for mark %s",pref(dataset,sequence),gref(markchar))
+        if base then
+            local basechar = ischar(base,currentfont)
+            if basechar then
+                if marks[basechar] then
+                    while true do
+                        base = getprev(base)
+                        if base then
+                            basechar = ischar(base,currentfont)
+                            if basechar then
+                                if not marks[basechar] then
+                                    break
+                                end
+                            else
+                                if trace_bugs then
+                                    logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+                                end
+                                return head, start, false
+                            end
+                        else
+                            if trace_bugs then
+                                logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+                            end
+                            return head, start, false
                         end
-                        return head, start, false
                     end
                 end
-            end
-            local ba = markanchors[1][basechar]
-            if ba then
-                local ma = markanchors[2]
-                if ma then
-                    local index = getligaindex(start)
-                    ba = ba[index]
-                    if ba then
-                        local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar]) -- index
-                        if trace_marks then
-                            logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
-                                pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
-                        end
-                        return head, start, true
-                    else
-                        if trace_bugs then
-                            logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index)
+                local ba = markanchors[1][basechar]
+                if ba then
+                    local ma = markanchors[2]
+                    if ma then
+                        local index = getligaindex(start)
+                        ba = ba[index]
+                        if ba then
+                            local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar]) -- index
+                            if trace_marks then
+                                logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+                                    pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
+                            end
+                            return head, start, true
+                        else
+                            if trace_bugs then
+                                logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index)
+                            end
                         end
                     end
+                elseif trace_bugs then
+                --  logwarning("%s: char %s is missing in font",pref(dataset,sequence),gref(basechar))
+                    onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
                 end
             elseif trace_bugs then
-            --  logwarning("%s: char %s is missing in font",pref(dataset,sequence),gref(basechar))
-                onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
+                logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1)
             end
         elseif trace_bugs then
-            logwarning("%s: prev node is no char",pref(dataset,sequence))
+            logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),2)
         end
     elseif trace_bugs then
         logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
@@ -1064,17 +1087,19 @@ function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
                 end
             end
         end
-        if base and ischar(base,currentfont) then -- subtype test can go
-            local basechar = getchar(base)
-            local ba = markanchors[1][basechar] -- slot 1 has been made copy of the class hash
-            if ba then
-                local ma = markanchors[2]
-                local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
-                if trace_marks then
-                    logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
-                        pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+        if base then
+            local basechar = ischar(base,currentfont)
+            if basechar then -- subtype test can go
+                local ba = markanchors[1][basechar] -- slot 1 has been made copy of the class hash
+                if ba then
+                    local ma = markanchors[2]
+                    local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+                    if trace_marks then
+                        logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+                            pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+                    end
+                    return head, start, true
                 end
-                return head, start, true
             end
         end
     elseif trace_bugs then
@@ -1094,9 +1119,11 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
             end
         else
             local nxt = getnext(start)
-            while not done and nxt and ischar(nxt,currentfont) do
-                local nextchar = getchar(nxt)
-                if marks[nextchar] then
+            while not done and nxt do
+                local nextchar = ischar(nxt,currentfont)
+                if not nextchar then
+                    break
+                elseif marks[nextchar] then
                     -- should not happen (maybe warning)
                     nxt = getnext(nxt)
                 else
@@ -1159,7 +1186,7 @@ local logwarning = report_chain
 -- 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(head,start,stop,dataset,sequence,replacements,rlmode)
+local function reversesub(head,start,stop,dataset,sequence,replacements,rlmode)
     local char        = getchar(start)
     local replacement = replacements[char]
     if replacement then
@@ -1174,6 +1201,9 @@ function chainprocs.reversesub(head,start,stop,dataset,sequence,replacements,rlm
     end
 end
 
+
+chainprocs.reversesub = reversesub
+
 --[[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
@@ -1282,7 +1312,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
         end
     else
         if trace_multiples then
-            logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacements))
+            logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
         end
         return multiple_glyphs(head,start,replacement,currentlookup.flags[1]) -- not sequence.flags?
     end
@@ -1463,8 +1493,11 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
         if kerns then
             local prev = start
             local done = false
-            while snext and ischar(snext,currentfont) do
-                local nextchar = getchar(snext)
+            while snext do
+                local nextchar = ischar(snext,currentfont)
+                if not nextchar then
+                    break
+                end
                 local krn = kerns[nextchar]
                 if not krn and marks[nextchar] then
                     prev = snext
@@ -1527,38 +1560,49 @@ function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlooku
         local markanchors = steps[1].coverage[markchar] -- always 1 step
         if markanchors then
             local base = getprev(start) -- [glyph] [start=mark]
-            if base and ischar(base,currentfont) then
-                local basechar = getchar(base)
-                if marks[basechar] then
-                    while true do
-                        base = getprev(base)
-                        if base and ischar(base,currentfont) then
-                            basechar = getchar(base)
-                            if not marks[basechar] then
-                                break
-                            end
-                        else
-                            if trace_bugs then
-                                logwarning("%s: no base for mark %s",pref(dataset,sequence),gref(markchar))
+            if base then
+                local basechar = ischar(base,currentfont)
+                if basechar then
+                    if marks[basechar] then
+                        while true do
+                            base = getprev(base)
+                            if base then
+                                local basechar = ischar(base,currentfont)
+                                if basechar then
+                                    if not marks[basechar] then
+                                        break
+                                    end
+                                else
+                                    if trace_bugs then
+                                        logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
+                                    end
+                                    return head, start, false
+                                end
+                            else
+                                if trace_bugs then
+                                    logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
+                                end
+                                return head, start, false
                             end
-                            return head, start, false
                         end
                     end
-                end
-                local ba = markanchors[1][basechar]
-                if ba then
-                    local ma = markanchors[2]
-                    if ma then
-                        local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
-                        if trace_marks then
-                            logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
-                                cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+                    local ba = markanchors[1][basechar]
+                    if ba then
+                        local ma = markanchors[2]
+                        if ma then
+                            local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+                            if trace_marks then
+                                logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
+                                    cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+                            end
+                            return head, start, true
                         end
-                        return head, start, true
                     end
+                elseif trace_bugs then
+                    logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),1)
                 end
             elseif trace_bugs then
-                logwarning("%s: prev node is no char",cref(dataset,sequence))
+                logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),2)
             end
         elseif trace_bugs then
             logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
@@ -1580,42 +1624,53 @@ function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentl
         local markanchors = steps[1].coverage[markchar] -- always 1 step
         if markanchors then
             local base = getprev(start) -- [glyph] [optional marks] [start=mark]
-            if base and ischar(base,currentfont) then
-                local basechar = getchar(base)
-                if marks[basechar] then
-                    while true do
-                        base = getprev(base)
-                        if base and ischar(base,currentfont) then
-                            basechar = getchar(base)
-                            if not marks[basechar] then
-                                break
-                            end
-                        else
-                            if trace_bugs then
-                                logwarning("%s: no base for mark %s",cref(dataset,sequence),markchar)
+            if base then
+                local basechar = ischar(base,currentfont)
+                if basechar then
+                    if marks[basechar] then
+                        while true do
+                            base = getprev(base)
+                            if base then
+                                local basechar = ischar(base,currentfont)
+                                if basechar then
+                                    if not marks[basechar] then
+                                        break
+                                    end
+                                else
+                                    if trace_bugs then
+                                        logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,1)
+                                    end
+                                    return head, start, false
+                                end
+                            else
+                                if trace_bugs then
+                                    logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,2)
+                                end
+                                return head, start, false
                             end
-                            return head, start, false
                         end
                     end
-                end
-                local ba = markanchors[1][basechar]
-                if ba then
-                    local ma = markanchors[2]
-                    if ma then
-                        local index = getligaindex(start)
-                        ba = ba[index]
-                        if ba then
-                            local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
-                            if trace_marks then
-                                logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
-                                    cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
+                    local ba = markanchors[1][basechar]
+                    if ba then
+                        local ma = markanchors[2]
+                        if ma then
+                            local index = getligaindex(start)
+                            ba = ba[index]
+                            if ba then
+                                local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+                                if trace_marks then
+                                    logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
+                                        cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
+                                end
+                                return head, start, true
                             end
-                            return head, start, true
                         end
                     end
+                elseif trace_bugs then
+                    logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),1)
                 end
             elseif trace_bugs then
-                logwarning("%s, prev node is no char",cref(dataset,sequence))
+                logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),2)
             end
         elseif trace_bugs then
             logwarning("%s, mark %s has no anchors",cref(dataset,sequence),gref(markchar))
@@ -1648,22 +1703,26 @@ function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlooku
                     end
                 end
             end
-            if base and ischar(base,currentfont) then -- subtype test can go
-                local basechar = getchar(base)
-                local ba = markanchors[1][basechar]
-                if ba then
-                    local ma = markanchors[2]
-                    if ma then
-                        local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
-                        if trace_marks then
-                            logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
-                                cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+            if base then -- subtype test can go
+                local basechar = ischar(base,currentfont)
+                if basechar then
+                    local ba = markanchors[1][basechar]
+                    if ba then
+                        local ma = markanchors[2]
+                        if ma then
+                            local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+                            if trace_marks then
+                                logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
+                                    cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
+                            end
+                            return head, start, true
                         end
-                        return head, start, true
                     end
+                elseif trace_bugs then
+                    logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),1)
                 end
             elseif trace_bugs then
-                logwarning("%s: prev node is no mark",cref(dataset,sequence))
+                logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),2)
             end
         elseif trace_bugs then
             logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
@@ -1692,9 +1751,11 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
                 end
             else
                 local nxt = getnext(start)
-                while not done and nxt and ischar(nxt,currentfont) do
-                    local nextchar = getchar(nxt)
-                    if marks[nextchar] then
+                while not done and nxt do
+                    local nextchar = ischar(nxt,currentfont)
+                    if not nextchar then
+                        break
+                    elseif marks[nextchar] then
                         -- should not happen (maybe warning)
                         nxt = getnext(nxt)
                     else
@@ -1934,11 +1995,16 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
         local cprev         = getprev(start)
         local insertedmarks = 0
 
-        while cprev and ischar(cf,currentfont) and marks[getchar(cf)] do
-            insertedmarks = insertedmarks + 1
-            cf            = cprev
-            startishead   = cf == head
-            cprev         = getprev(cprev)
+        while cprev do
+            local char = ischar(cf,currentfont)
+            if char and marks[char] then
+                insertedmarks = insertedmarks + 1
+                cf            = cprev
+                startishead   = cf == head
+                cprev         = getprev(cprev)
+            else
+                break
+            end
         end
 
         setprev(lookaheaddisc,cprev)
@@ -1985,10 +2051,15 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
         local cnext         = getnext(start)
         local insertedmarks = 0
 
-        while cnext and ischar(cnext,currentfont) and marks[getchar(cnext)] do
-            insertedmarks = insertedmarks + 1
-            cl            = cnext
-            cnext         = getnext(cnext)
+        while cnext do
+            local char = ischar(cnext,currentfont)
+            if char and marks[char] then
+                insertedmarks = insertedmarks + 1
+                cl            = cnext
+                cnext         = getnext(cnext)
+            else
+                break
+            end
         end
         if cnext then
             setprev(cnext,backtrackdisc)
@@ -2119,7 +2190,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
         -- f..l = mid string
         if s == 1 then
             -- never happens
-            match = ischar(current,currentfont) and seq[1][getchar(current)]
+            local char = ischar(current,currentfont)
+            match = char and seq[1][char]
         else
             -- maybe we need a better space check (maybe check for glue or category or combination)
             -- we cannot optimize for n=2 because there can be disc nodes
@@ -2145,8 +2217,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
                         if last then
                             local id = getid(last)
                             if id == glyph_code then
-                                if ischar(last,currentfont) then
-                                    local char = getchar(last)
+                                local char = ischar(last,currentfont)
+                                if char then
                                     local ccd = descriptions[char]
                                     if ccd then
                                         local class = ccd.class or "base"
@@ -2259,15 +2331,15 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
                             if prev then
                                 local id = getid(prev)
                                 if id == glyph_code then
-                                    if ischar(prev,currentfont) then
-                                        local char = getchar(prev)
+                                    local char = ischar(prev,currentfont)
+                                    if char then
                                         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)
+                                                    show_skip(dataset,sequence,char,ck,class)
                                                 end
                                             elseif seq[n][char] then
                                                 n = n -1
@@ -2397,15 +2469,15 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
                         if current then
                             local id = getid(current)
                             if id == glyph_code then
-                                if ischar(current,currentfont) then
-                                    local char = getchar(current)
+                                local char = ischar(current,currentfont)
+                                if char then
                                     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)
+                                                show_skip(dataset,sequence,char,ck,class)
                                             end
                                         elseif seq[n][char] then
                                             n = n + 1
@@ -2534,7 +2606,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
                             done = true
                         end
                     else
-                        logprocess("%s: %s is not yet supported",cref(dataset,sequence),chainkind)
+                        logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
                     end
                  else
                     local i = 1
@@ -2591,7 +2663,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
                                 end
                             else
                                 -- actually an error
-                                logprocess("%s: %s is not yet supported",cref(dataset,sequence),chainkind)
+                                logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
                             end
                             i = i + 1
                         end
@@ -2605,7 +2677,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
             else
                 local replacements = ck[7]
                 if replacements then
-                    head, start, done = chainprocs.reversesub(head,start,last,dataset,sequence,replacements,rlmode)
+                    head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode)
                 else
                     done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts
                     if trace_contexts then
@@ -2632,6 +2704,23 @@ handlers.gsub_reversecontextchain = handle_contextchain
 handlers.gpos_contextchain        = handle_contextchain
 handlers.gpos_context             = handle_contextchain
 
+-- this needs testing
+
+function chained_contextchain(head,start,stop,dataset,sequence,currentlookup,rlmode)
+    local steps    = currentlookup.steps
+    local nofsteps = currentlookup.nofsteps
+    if nofsteps > 1 then
+        reportmoresteps(dataset,sequence)
+    end
+    return handle_contextchain(head,start,dataset,sequence,currentlookup,rlmode)
+end
+
+chainprocs.gsub_context             = chained_contextchain
+chainprocs.gsub_contextchain        = chained_contextchain
+chainprocs.gsub_reversecontextchain = chained_contextchain
+chainprocs.gpos_contextchain        = chained_contextchain
+chainprocs.gpos_context             = chained_contextchain
+
 local missing = setmetatableindex("table")
 
 local function logprocess(...)
@@ -2667,20 +2756,33 @@ end)
 
 -- fonts.hashes.sequences = sequencelists
 
-local autofeatures = fonts.analyzers.features -- was: constants
+local autofeatures    = fonts.analyzers.features
+local featuretypes    = otf.tables.featuretypes
+local defaultscript   = otf.features.checkeddefaultscript
+local defaultlanguage = otf.features.checkeddefaultlanguage
 
-local function initialize(sequence,script,language,enabled)
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
     local features = sequence.features
     if features then
         local order = sequence.order
         if order then
-            for i=1,#order do --
-                local kind  = order[i] --
+            local featuretype = featuretypes[sequence.type or "unknown"]
+            for i=1,#order do
+                local kind  = order[i]
                 local valid = enabled[kind]
                 if valid then
-                    local scripts = features[kind] --
-                    local languages = scripts[script] or scripts[wildcard]
-                    if languages and (languages[language] or languages[wildcard]) then
+                    local scripts   = features[kind]
+                    local languages = scripts and (
+                        scripts[script] or
+                        scripts[wildcard] or
+                        (autoscript and defaultscript(featuretype,autoscript,scripts))
+                    )
+                    local enabled = languages and (
+                        languages[language] or
+                        languages[wildcard] or
+                        (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+                    )
+                    if enabled then
                         return { valid, autofeatures[kind] or false, sequence, kind }
                     end
                 end
@@ -2693,11 +2795,13 @@ local function initialize(sequence,script,language,enabled)
 end
 
 function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
-    local shared     = tfmdata.shared
-    local properties = tfmdata.properties
-    local language   = properties.language or "dflt"
-    local script     = properties.script   or "dflt"
-    local enabled    = shared.features
+    local shared       = tfmdata.shared
+    local properties   = tfmdata.properties
+    local language     = properties.language or "dflt"
+    local script       = properties.script   or "dflt"
+    local enabled      = shared.features
+    local autoscript   = enabled and enabled.autoscript
+    local autolanguage = enabled and enabled.autolanguage
     local res = resolved[font]
     if not res then
         res = { }
@@ -2716,7 +2820,7 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
         rs[language] = rl
         local sequences = tfmdata.resources.sequences
         for s=1,#sequences do
-            local v = enabled and initialize(sequences[s],script,language,enabled)
+            local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
             if v then
                 rl[#rl+1] = v
             end
@@ -2746,8 +2850,13 @@ local function kernrun(disc,run)
     -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
     -- has happened but then it should be in the disc so basically this test indicates an error)
     --
-    while prevmarks and ischar(prevmarks,currentfont) and marks[getchar(prevmarks)] do
-        prevmarks = getprev(prevmarks)
+    while prevmarks do
+        local char = ischar(prevmarks,currentfont)
+        if char and marks[char] then
+            prevmarks = getprev(prevmarks)
+        else
+            break
+        end
     end
     --
     if prev and (pre or replace) and not ischar(prev,currentfont) then
@@ -3014,8 +3123,9 @@ local function featuresprocessor(head,font,attr)
             -- we need to get rid of this slide! probably no longer needed in latest luatex
             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 = getid(start)
-                if ischar(start,font) then
+                local id   = getid(start)
+                local char = ischar(start,font)
+                if char then
                     local a = getattr(start,0)
                     if a then
                         a = a == attr
@@ -3023,7 +3133,6 @@ local function featuresprocessor(head,font,attr)
                         a = true
                     end
                     if a then
-                        local char = getchar(start)
                         for i=1,nofsteps do
                             local step = steps[i]
                             local lookupcache = step.coverage
@@ -3069,32 +3178,35 @@ local function featuresprocessor(head,font,attr)
                         while start do
                             local id = getid(start)
                             if id ~= glyph_code then
-                                -- very unlikely
+                                -- very unlikely (if so we could use ischar)
                                 start = getnext(start)
-                            elseif ischar(start,font) then
-                                local a = getattr(start,0)
---                                 if a then
---                                     a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
---                                 else
---                                     a = not attribute or getprop(start,a_state) == attribute
---                                 end
---                                 if a then
-if not a or (a == attr) then
-                                    local lookupmatch = lookupcache[getchar(start)]
-                                    if lookupmatch then
-                                        -- sequence kan weg
-                                        local ok
-                                        head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
-                                        if ok then
-                                            done = true
+                            else
+                                local char = ischar(start,font)
+                                if char then
+                                    local a = getattr(start,0)
+                                 -- if a then
+                                 --     a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+                                 -- else
+                                 --     a = not attribute or getprop(start,a_state) == attribute
+                                 -- end
+                                 -- if a then
+                                    if not a or (a == attr) then
+                                        local lookupmatch = lookupcache[char]
+                                        if lookupmatch then
+                                            -- sequence kan weg
+                                            local ok
+                                            head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
+                                            if ok then
+                                                done = true
+                                            end
                                         end
+                                        if start then start = getnext(start) end
+                                    else
+                                        start = getnext(start)
                                     end
-                                    if start then start = getnext(start) end
                                 else
-                                    start = getnext(start)
+                                    return head, false
                                 end
-                            else
-                                return head, false
                             end
                         end
                         if done then
@@ -3106,16 +3218,17 @@ if not a or (a == attr) then
                     local function t_run(start,stop)
                         while start ~= stop do
                             local id = getid(start)
-                            if ischar(start,font) then
+                            local char = ischar(start,font)
+                            if char then
                                 local a = getattr(start,0)
---                                 if a then
---                                     a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
---                                 else
---                                     a = not attribute or getprop(start,a_state) == attribute
---                                 end
---                                 if a then
-if not a or (a == attr) then
-                                    local lookupmatch = lookupcache[getchar(start)]
+                             -- if a then
+                             --     a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+                             -- else
+                             --     a = not attribute or getprop(start,a_state) == attribute
+                             -- end
+                             -- if a then
+                                if not a or (a == attr) then
+                                    local lookupmatch = lookupcache[char]
                                     if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
                                         -- if we need more than ligatures we can outline the code and use functions
                                         local s = getnext(start)
@@ -3143,13 +3256,13 @@ if not a or (a == attr) then
 
                     local function d_run(prev) -- we can assume that prev and next are glyphs
                         local a = getattr(prev,0)
---                         if a then
---                             a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
---                         else
---                             a = not attribute or getprop(prev,a_state) == attribute
---                         end
---                         if a then
-if not a or (a == attr) then
+                     -- if a then
+                     --     a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+                     -- else
+                     --     a = not attribute or getprop(prev,a_state) == attribute
+                     -- end
+                     -- if a then
+                        if not a or (a == attr) then
                             local lookupmatch = lookupcache[getchar(prev)]
                             if lookupmatch then
                                 -- sequence kan weg
@@ -3164,13 +3277,13 @@ if not a or (a == attr) then
 
                     local function k_run(sub,injection,last)
                         local a = getattr(sub,0)
---                         if a then
---                             a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
---                         else
---                             a = not attribute or getprop(sub,a_state) == attribute
---                         end
---                         if a then
-if not a or (a == attr) then
+                     -- if a then
+                     --     a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+                     -- else
+                     --     a = not attribute or getprop(sub,a_state) == attribute
+                     -- end
+                     -- if a then
+                        if not a or (a == attr) then
                             -- sequence kan weg
                             for n in traverse_nodes(sub) do -- only gpos
                                 if n == last then
@@ -3196,7 +3309,8 @@ if not a or (a == attr) then
                     while start do
                         local id = getid(start)
                         if id == glyph_code then
-                            if ischar(start,font) then
+                            local char = ischar(start,font)
+                            if char then
                                 local a = getattr(start,0)
                                 if a then
                                     a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -3204,7 +3318,6 @@ if not a or (a == attr) then
                                     a = not attribute or getprop(start,a_state) == attribute
                                 end
                                 if a then
-                                    local char        = getchar(start)
                                     local lookupmatch = lookupcache[char]
                                     if lookupmatch then
                                         -- sequence kan weg
@@ -3293,43 +3406,45 @@ if not a or (a == attr) then
                         if id ~= glyph_code then
                             -- very unlikely
                             start = getnext(start)
-                        elseif ischar(start,font) then
-                            local a = getattr(start,0)
---                             if a then
---                                 a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
---                             else
---                                 a = not attribute or getprop(start,a_state) == attribute
---                             end
---                             if a then
-if not a or (a == attr) then
-                                local char = getchar(start)
-                                for i=1,nofsteps do
-                                    local step        = steps[i]
-                                    local lookupcache = step.coverage
-                                    if lookupcache then
-                                        local lookupmatch = lookupcache[char]
-                                        if lookupmatch then
-                                            -- we could move all code inline but that makes things even more unreadable
-                                            local ok
-                                            head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
-                                            if ok then
-                                                done = true
-                                                break
-                                            elseif not start then
-                                                -- don't ask why ... shouldn't happen
-                                                break
+                        else
+                            local char = ischar(start,font)
+                            if char then
+                                local a = getattr(start,0)
+                             -- if a then
+                             --     a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+                             -- else
+                             --     a = not attribute or getprop(start,a_state) == attribute
+                             -- end
+                             -- if a then
+                                if not a or (a == attr) then
+                                    for i=1,nofsteps do
+                                        local step        = steps[i]
+                                        local lookupcache = step.coverage
+                                        if lookupcache then
+                                            local lookupmatch = lookupcache[char]
+                                            if lookupmatch then
+                                                -- we could move all code inline but that makes things even more unreadable
+                                                local ok
+                                                head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+                                                if ok then
+                                                    done = true
+                                                    break
+                                                elseif not start then
+                                                    -- don't ask why ... shouldn't happen
+                                                    break
+                                                end
                                             end
+                                        else
+                                            report_missing_cache(dataset,sequence)
                                         end
-                                    else
-                                        report_missing_cache(dataset,sequence)
                                     end
+                                    if start then start = getnext(start) end
+                                else
+                                    start = getnext(start)
                                 end
-                                if start then start = getnext(start) end
                             else
-                                start = getnext(start)
+                                return head, false
                             end
-                        else
-                            return head, false
                         end
                     end
                     if done then
@@ -3340,13 +3455,13 @@ if not a or (a == attr) then
 
                 local function d_run(prev)
                     local a = getattr(prev,0)
---                     if a then
---                         a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
---                     else
---                         a = not attribute or getprop(prev,a_state) == attribute
---                     end
---                     if a then
-if not a or (a == attr) then
+                 -- if a then
+                 --     a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
+                 -- else
+                 --     a = not attribute or getprop(prev,a_state) == attribute
+                 -- end
+                 -- if a then
+                if not a or (a == attr) then
                         -- brr prev can be disc
                         local char = getchar(prev)
                         for i=1,nofsteps do
@@ -3371,13 +3486,13 @@ if not a or (a == attr) then
 
                 local function k_run(sub,injection,last)
                     local a = getattr(sub,0)
---                     if a then
---                         a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
---                     else
---                         a = not attribute or getprop(sub,a_state) == attribute
---                     end
---                     if a then
-if not a or (a == attr) then
+                 -- if a then
+                 --     a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
+                 -- else
+                 --     a = not attribute or getprop(sub,a_state) == attribute
+                 -- end
+                 -- if a then
+                    if not a or (a == attr) then
                         for n in traverse_nodes(sub) do -- only gpos
                             if n == last then
                                 break
@@ -3410,17 +3525,17 @@ if not a or (a == attr) then
 
                 local function t_run(start,stop)
                     while start ~= stop do
-                        local id = getid(start)
-                        if ischar(start,font) then
+                        local id   = getid(start)
+                        local char = ischar(start,font)
+                        if char then
                             local a = getattr(start,0)
---                             if a then
---                                 a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
---                             else
---                                 a = not attribute or getprop(start,a_state) == attribute
---                             end
---                             if a then
-if not a or (a == attr) then
-                                local char = getchar(start)
+                         -- if a then
+                         --     a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+                         -- else
+                         --     a = not attribute or getprop(start,a_state) == attribute
+                         -- end
+                         -- if a then
+                            if not a or (a == attr) then
                                 for i=1,nofsteps do
                                     local step = steps[i]
                                     local lookupcache = step.coverage
@@ -3458,7 +3573,8 @@ if not a or (a == attr) then
                 while start do
                     local id = getid(start)
                     if id == glyph_code then
-                        if ischar(start,font) then
+                        local char = ischar(start,font)
+                        if char then
                             local a = getattr(start,0)
                             if a then
                                 a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
@@ -3470,7 +3586,7 @@ if not a or (a == attr) then
                                     local step        = steps[i]
                                     local lookupcache = step.coverage
                                     if lookupcache then
-                                        local char = getchar(start)
+                                     -- local char = getchar(start)
                                         local lookupmatch = lookupcache[char]
                                         if lookupmatch then
                                             -- we could move all code inline but that makes things even more unreadable
diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua
index ed6519f38..80aea5d9a 100644
--- a/tex/context/base/font-ott.lua
+++ b/tex/context/base/font-ott.lua
@@ -1083,7 +1083,7 @@ table.setmetatableindex(usedfeatures, function(t,k) if k then local v = { } t[k]
 
 storage.register("fonts/otf/usedfeatures", usedfeatures, "fonts.handlers.otf.statistics.usedfeatures" )
 
-function otf.features.normalize(features)
+function otffeatures.normalize(features)
     if features then
         local h = { }
         for key, value in next, features do
@@ -1128,234 +1128,3 @@ function otf.features.normalize(features)
         return h
     end
 end
-
---~ table.print(otf.features.normalize({ language = "dutch", liga = "yes", ss99 = true, aalt = 3, abcd = "yes"  } ))
-
--- When I feel the need ...
-
---~ 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-pre.mkiv b/tex/context/base/font-pre.mkiv
index 492814915..17adc5290 100644
--- a/tex/context/base/font-pre.mkiv
+++ b/tex/context/base/font-pre.mkiv
@@ -25,6 +25,8 @@
   [always]
   [mode=node,    % we had 'auto', but let's try 'node' for a while and see what the impact is
    script=auto,  % on speed; 'base' just doesn't play well with dynamics; some day we can even
+   autoscript=position,
+   autolanguage=position,
    kern=yes,     % consider skipping the base passes when no base mode is used
    mark=yes,
    mkmk=yes,
@@ -106,6 +108,7 @@
 \definefontfeature
   [semitic-complete]
   [mode=node,analyze=yes,language=dflt,ccmp=yes,
+   autoscript=position,autolanguage=position,
    init=yes,medi=yes,fina=yes,isol=yes,
    mark=yes,mkmk=yes,kern=yes,curs=yes,
    liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes]
@@ -113,6 +116,7 @@
 \definefontfeature
   [semitic-simple]
   [mode=node,analyze=yes,language=dflt,ccmp=yes,
+   autoscript=position,autolanguage=position,
    init=yes,medi=yes,fina=yes,isol=yes,
    mark=yes,mkmk=yes,kern=yes,curs=yes,
    rlig=yes,calt=yes]
@@ -388,7 +392,7 @@
               \s!b=1.440,
               \s!c=1.728,
               \s!d=2.074,
-                 *=\currentfontscale, % wildcard
+                 *=\font_currentfontscale, % wildcard
               \s!x=0.8,
              \s!xx=0.6,
             \v!big=1.2,
diff --git a/tex/context/base/font-sel.mkvi b/tex/context/base/font-sel.mkvi
index 820d211eb..cd18812d2 100644
--- a/tex/context/base/font-sel.mkvi
+++ b/tex/context/base/font-sel.mkvi
@@ -108,7 +108,8 @@
 
 \def\selectfont_preset_process#name%
   {\ifcsname\??selectfontpreset#name\endcsname
-     \csname\??selectfontpreset#name\endcsname
+    %\csname\??selectfontpreset#name\endcsname
+     \lastnamedcs
    \else
      % unknown preset
    \fi}
diff --git a/tex/context/base/font-sty.mkvi b/tex/context/base/font-sty.mkvi
index 5924a3033..8c42d2516 100644
--- a/tex/context/base/font-sty.mkvi
+++ b/tex/context/base/font-sty.mkvi
@@ -77,7 +77,8 @@
    \fi}
 
 \def\applyalternativestyle#name% public
-  {\ifcsname\??alternativestyles#name\endcsname\csname\??alternativestyles#name\expandafter\endcsname\fi}
+ %{\ifcsname\??alternativestyles#name\endcsname\csname\??alternativestyles#name\expandafter\endcsname\fi}
+  {\begincsname\??alternativestyles#name\endcsname}
 
 %D Maybe too geneneric, but probably ok is the following. (Maybe one
 %D day we will use a dedicated grouped command for styles.)
@@ -150,9 +151,11 @@
 \def\font_helpers_do_convert_font
   {\edef\m_current_convert_font_dt{\detokenize\expandafter{\m_current_convert_font}}%
    \ifcsname\??alternativestyles\m_current_convert_font_dt\endcsname
-     \csname\??alternativestyles\m_current_convert_font_dt\expandafter\endcsname
+    %\csname\??alternativestyles\m_current_convert_font_dt\expandafter\endcsname
+     \expandafter\lastnamedcs
    \else\ifcsname\m_current_convert_font_dt\endcsname
      \csname\m_current_convert_font_dt\expandafter\endcsname
+     \expandafter\lastnamedcs
    \else
      \doubleexpandafter\m_current_convert_font
    \fi\fi}
@@ -182,16 +185,19 @@
 
 \unexpanded\def\dousestylehashparameter#hash#parameter%
   {\ifcsname#hash#parameter\endcsname
-     \expandafter\dousestyleparameter\csname#hash#parameter\endcsname
+    %\expandafter\dousestyleparameter\csname#hash#parameter\endcsname
+     \expandafter\dousestyleparameter\lastnamedcs
    \fi}
 
 \unexpanded\def\dousecurrentstyleparameter % empty check outside here
   {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
    \settrue\fontattributeisset % reset is done elsewhere
    \ifcsname\??alternativestyles\detokenizedstyleparameter\endcsname
-     \csname\??alternativestyles\detokenizedstyleparameter\endcsname
+    %\csname\??alternativestyles\detokenizedstyleparameter\endcsname
+     \lastnamedcs
    \else\ifcsname\detokenizedstyleparameter\endcsname
-     \csname\detokenizedstyleparameter\endcsname
+    %\csname\detokenizedstyleparameter\endcsname
+     \lastnamedcs
    \else
      \currentstyleparameter
    \fi\fi}
@@ -369,7 +375,7 @@
 %   {\executeifdefined{\??stylecollection#instance::\fontalternative}
 %   {\getvalue        {\??stylecollection#instance::\s!default}}}}}
 
-\unexpanded\def\styleinstance[#instance]%
+\unexpanded\def\styleinstance[#instance]% maybe \lastnamedcs here too
   {\csname\??stylecollection#instance:%
      \ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname
        \fontstyle:\fontalternative
diff --git a/tex/context/base/font-sym.mkvi b/tex/context/base/font-sym.mkvi
index a21bea0ba..4d31b96f8 100644
--- a/tex/context/base/font-sym.mkvi
+++ b/tex/context/base/font-sym.mkvi
@@ -135,7 +135,8 @@
 \def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
   {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
    \ifcsname\??symbolfont\askedsymbolfont\endcsname
-     \csname\??symbolfont\askedsymbolfont\endcsname
+    %\csname\??symbolfont\askedsymbolfont\endcsname
+     \lastnamedcs
    \else
      \font_basics_define_symbolic_font
    \fi}
@@ -143,7 +144,8 @@
 \def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
   {\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
    \ifcsname\??symbolfont\askedsymbolfont\endcsname
-     \csname\??symbolfont\askedsymbolfont\endcsname
+    %\csname\??symbolfont\askedsymbolfont\endcsname
+     \lastnamedcs
    \else
      \font_basics_define_symbolic_font
    \fi}
@@ -151,7 +153,8 @@
 \def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile
   {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
    \ifcsname\??symbolfont\askedsymbolfont\endcsname
-     \csname\??symbolfont\askedsymbolfont\endcsname
+    %\csname\??symbolfont\askedsymbolfont\endcsname
+     \lastnamedcs
    \else
      \font_basics_define_symbolic_font
    \fi}
@@ -159,7 +162,8 @@
 \def\setdirectsymbolicfont#fontname%
   {\edef\askedsymbolfont{\truefontname{#fontname} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
    \ifcsname\??symbolfont\askedsymbolfont\endcsname
-     \csname\??symbolfont\askedsymbolfont\endcsname
+    %\csname\??symbolfont\askedsymbolfont\endcsname
+     \lastnamedcs
    \else
      \font_basics_define_symbolic_font
    \fi}
diff --git a/tex/context/base/font-tra.mkiv b/tex/context/base/font-tra.mkiv
index 3d6811a64..f5290d614 100644
--- a/tex/context/base/font-tra.mkiv
+++ b/tex/context/base/font-tra.mkiv
@@ -15,6 +15,8 @@
 
 \writestatus{loading}{ConTeXt Font Macros / Tracing}
 
+%D just use fontid
+
 %D \macros
 %D   {showbodyfont}
 %D
@@ -122,7 +124,7 @@
 
 \unexpanded\def\otfstepcharcommand#1#2#3% font char class
   {\otfstepspace
-  \doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:\ruledhbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}%
+   \doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:\ruledhbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}%
    \otfstepspace}
 
 \unexpanded\def\otfstepfontcommand#1#2#3% id font size
diff --git a/tex/context/base/grph-epd.mkiv b/tex/context/base/grph-epd.mkiv
index 2df195589..8152772aa 100644
--- a/tex/context/base/grph-epd.mkiv
+++ b/tex/context/base/grph-epd.mkiv
@@ -33,7 +33,7 @@
    \c!background={\v!foreground,system:graphics:epdf}]
 
 \unexpanded\def\grph_epdf_add_overlay
-  {\global\setbox\foundexternalfigure\vbox\bgroup
+  {\global\setbox\foundexternalfigure\vbox\bgroup % vpack ?
      \system_graphics_epdf{\box\foundexternalfigure}%
    \egroup}
 
diff --git a/tex/context/base/grph-fig.mkiv b/tex/context/base/grph-fig.mkiv
index f5152874d..796309b88 100644
--- a/tex/context/base/grph-fig.mkiv
+++ b/tex/context/base/grph-fig.mkiv
@@ -112,8 +112,8 @@
 \let\placestopfigure\relax
 
 \unexpanded\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]%
-  {\hbox
-     {\setbox\scratchbox\hbox
+  {\hpack
+     {\setbox\scratchbox\hpack
         {\useexternalfigure[\s!dummy][#2][#3,#5]%
          \externalfigure[\s!dummy]}%
       \grph_steps_calculate
@@ -161,10 +161,10 @@
 
 \unexpanded\def\grph_steps_two_colorbar#1[#2]
   {\begingroup
-   \global\setbox\b_grph_steps_colorbar\vbox
+   \global\setbox\b_grph_steps_colorbar\vpack % \vbox ?
      {\forgetall
       \processcommalist[#2]\grph_colorbar_make_step}%
-   \global\setbox\b_grph_steps_colorbar\vbox
+   \global\setbox\b_grph_steps_colorbar\vpack
      {\hskip2\emwidth\box\b_grph_steps_colorbar}%
    \global\wd\b_grph_steps_colorbar\zeropoint
    \endgroup}
@@ -193,7 +193,7 @@
 
 \unexpanded\def\teststartfigure[#1][#2][#3]#4\teststopfigure
   {\begingroup
-     \setbox\scratchbox\hbox
+     \setbox\scratchbox\hpack
        {\useexternalfigure[\s!dummy][#2][\c!wfactor=\v!max]%
         \externalfigure[\s!dummy]}%
      \let\referring\grph_steps_three_referring
@@ -201,7 +201,7 @@
      \let\remark   \grph_steps_three_remark
      \let\colorbar \grph_steps_three_colorbar
      \c_grph_steps_reference\zerocount
-     \setbox0\vbox
+     \setbox0\vpack
        {\hsize240\points
         \startpositioning
           \grph_steps_calculate
@@ -232,7 +232,7 @@
      \let\marking  \grph_steps_four_marking
      \let\remark   \grph_steps_four_remark
      \let\colorbar \grph_steps_four_colorbar
-     \setbox2\vbox
+     \setbox2\vbox % \vpack ?
        {{\tfa\doifelsenothing{#1}{#2}{#1}}
         \blank
         \tfxx#4
@@ -242,10 +242,10 @@
      \else
        \ht0\ht2
      \fi
-     \hbox
+     \hpack
        {\hskip3\emwidth
-        \vtop{\vskip12\points\box0\vskip6\points}%
-        \vtop{\vskip12\points\box2\vskip6\points}}%
+        \tpack{\vskip12\points\box0\vskip6\points}%
+        \tpack{\vskip12\points\box2\vskip6\points}}%
    \endgroup}
 
 \unexpanded\def\grph_steps_three_referring(#1,#2)#3(#4,#5)#6[#7]%
@@ -307,11 +307,11 @@
 %   {\position(0,0){\getvalue{#1}}}
 
 \def\grph_steps_goto(#1,#2)#3[#4]%    (h,b)kader[ref]
-  {\gotobox{\vbox{\grph_steps_area(#1,#2)#3{}}}[#4]}
+  {\gotobox{\vpack{\grph_steps_area(#1,#2)#3{}}}[#4]}
 
 \def\grph_steps_text#1(#2,#3)#4(#5,#6)#7[#8]%
   {\advance\c_grph_steps_reference\plusone
-   \hbox
+   \hbox % \hpack ?
      {\quad
       \thisissomeinternal\s!vwb
         {#8}%
diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv
index 6b7f2bd63..47274a64e 100644
--- a/tex/context/base/grph-inc.mkiv
+++ b/tex/context/base/grph-inc.mkiv
@@ -370,7 +370,7 @@
 \let\dowithfigure\relax % name might change (into a proper hook)
 
 \unexpanded\def\doscalefigure % used at lua end
-  {\global\setbox\foundexternalfigure\vbox{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}}
+  {\global\setbox\foundexternalfigure\vpack{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}}
 
 \definescale % some day we will inherit
   [\v!figure]
@@ -543,7 +543,7 @@
 %D Internal graphics are handled at the \TEX\ end:
 
 \def\grph_include_process_tex#1%
-  {\global\setbox\foundexternalfigure\vbox\framed
+  {\global\setbox\foundexternalfigure\vbox\framed % no \vpack
      [\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!
@@ -552,15 +552,15 @@
 
 \unexpanded\def\docheckfigurebuffer  #1{\grph_include_process_tex{\getbuffer[#1]}}
 \unexpanded\def\docheckfiguretex     #1{\grph_include_process_tex{\input{#1}}}
-\unexpanded\def\docheckfigurecld     #1{\global\setbox\foundexternalfigure\vbox{\cldprocessfile{#1}}}
-\unexpanded\def\docheckfiguremps     #1{\global\setbox\foundexternalfigure\vbox{\convertMPtoPDF{#1}11}}
-\unexpanded\def\docheckfiguremprun #1#2{\global\setbox\foundexternalfigure\vbox{\useMPrun{#1}{#2}}}
+\unexpanded\def\docheckfigurecld     #1{\global\setbox\foundexternalfigure\vbox {\cldprocessfile{#1}}}
+\unexpanded\def\docheckfiguremps     #1{\global\setbox\foundexternalfigure\vpack{\convertMPtoPDF{#1}11}}
+\unexpanded\def\docheckfiguremprun #1#2{\global\setbox\foundexternalfigure\vpack{\useMPrun{#1}{#2}}}
 
 \unexpanded\def\relocateexternalfigure % easier here than in lua
-  {\global\setbox\foundexternalfigure\vbox to \ht\foundexternalfigure\bgroup
+  {\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup
      \vss
      \ht\foundexternalfigure\zeropoint
-     \hbox to \wd\foundexternalfigure\bgroup
+     \hpack to \wd\foundexternalfigure\bgroup
         \box\foundexternalfigure
         \hss
      \egroup
@@ -667,10 +667,10 @@
 % Helpers (will be replaced when xforms are accessible at the lua end)
 
 \unexpanded\def\dosetfigureobject#1%
-  {\setobject{FIG}{#1}\vbox{\box\foundexternalfigure}}
+  {\setobject{FIG}{#1}\vpack{\box\foundexternalfigure}}
 
 \unexpanded\def\doboxfigureobject#1%
-  {\global\setbox\foundexternalfigure\vbox{\getobject{FIG}{#1}}} % probably one vbox too many
+  {\global\setbox\foundexternalfigure\vpack{\getobject{FIG}{#1}}} % probably one vbox too many
 
 % Figure bases
 
diff --git a/tex/context/base/grph-trf.mkiv b/tex/context/base/grph-trf.mkiv
index fca5c7cf6..099efa114 100644
--- a/tex/context/base/grph-trf.mkiv
+++ b/tex/context/base/grph-trf.mkiv
@@ -140,7 +140,7 @@
    %
    \d_grph_scale_dp\dp\nextbox
    \ifx\p_depth\v!no \ifzeropt\d_grph_scale_dp \else
-     \setbox\nextbox\hbox{\raise\d_grph_scale_dp\box\nextbox}% new
+     \setbox\nextbox\hpack{\raise\d_grph_scale_dp\box\nextbox}% new
      \d_grph_scale_dp\dp\nextbox
    \fi \fi
    \d_grph_scale_wd\wd\nextbox
@@ -169,7 +169,7 @@
   {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd
    \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht
    \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp
-   \setbox\nextbox\hbox
+   \setbox\nextbox\hpack
      {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
       \smashedbox\nextbox
       \dostopscaling}%
@@ -300,7 +300,7 @@
   {\ifx\p_maxwidth \empty\else \edef\p_maxwidth {\the\dimexpr\p_maxwidth        }\fi
    \ifx\p_maxheight\empty\else \edef\p_maxheight{\the\dimexpr\p_maxheight       }\fi
    \ifx\p_lines    \empty\else \edef\p_height   {\the\dimexpr\p_lines\lineheight}\fi
-   \getvalue{\??scalegrid\scaleparameter\c!grid}}
+   \csname\??scalegrid\scaleparameter\c!grid\endcsname}
 
 \def\grph_scale_by_nature % where ! ! ! ! !
   {\ifx\p_width \empty\else \global\d_grph_scale_used_x_size\p_width \fi
@@ -676,13 +676,13 @@
   {\ifx\p_equalwidth\empty \else
     \scratchdimen\p_equalwidth\relax
     \ifdim\d_grph_scale_wd<\scratchdimen
-      \setbox\nextbox\hbox to \scratchdimen{\hss\box\nextbox\hss}%
+      \setbox\nextbox\hpack to \scratchdimen{\hss\box\nextbox\hss}%
     \fi
    \fi
    \ifx\p_equalheight\empty \else
      \scratchdimen\p_equalheight\relax
      \ifdim\d_grph_scale_ht<\scratchdimen
-       \setbox\nextbox\vbox to \scratchdimen{\vss\box\nextbox\vss}%
+       \setbox\nextbox\vpack to \scratchdimen{\vss\box\nextbox\vss}%
      \fi
    \fi}
 
@@ -839,7 +839,7 @@
      \scratchheight\clippingparameter\c!sy\scratchheight
      \advance\scratchyoffset \ht\nextbox
    \fi
-   \setbox\nextbox\hbox
+   \setbox\nextbox\hpack
      {\advance\scratchxoffset -\clippingparameter\c!leftoffset  \relax
       \advance\scratchyoffset -\clippingparameter\c!bottomoffset\relax
       \hskip-\scratchxoffset
@@ -848,13 +848,13 @@
    \wd\nextbox\zeropoint
    \ht\nextbox\zeropoint
    \dp\nextbox\zeropoint
-   \setbox\nextbox\hbox
+   \setbox\nextbox\hpack
      {\advance\scratchwidth \dimexpr\clippingparameter\c!leftoffset  +\clippingparameter\c!rightoffset\relax
       \advance\scratchheight\dimexpr\clippingparameter\c!bottomoffset+\clippingparameter\c!topoffset  \relax
       \dostartclipping{\clippingparameter\c!mp}\scratchwidth\scratchheight
         \box\nextbox
       \dostopclipping}%
-   \setbox\nextbox\hbox
+   \setbox\nextbox\hpack
      {\hskip-\clippingparameter\c!leftoffset
       \lower \clippingparameter\c!bottomoffset
       \box\nextbox}%
@@ -912,7 +912,7 @@
   {\scratchdimen\wd\nextbox
    % better use an hbox (if no \forgetall, leftskip etc may creep in)
    %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
-   \setbox\nextbox\hbox{\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
+   \setbox\nextbox\hpack{\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
    \wd\nextbox\scratchdimen
    \box\nextbox
    \egroup}
@@ -1100,19 +1100,19 @@
   {\csname\??rotatepreset
      \ifcsname\??rotatepreset\p_rotation_rotation\endcsname\p_rotation_rotation\else\v!default\fi
    \endcsname
-   \setbox\nextbox\vbox{\box\nextbox}% not really needed
+   \setbox\nextbox\vpack{\box\nextbox}% not really needed
    \dontcomplain
    \ifconditional\c_grph_rotate_center
      \d_grph_rotate_saved_width \wd\nextbox
      \d_grph_rotate_saved_height\ht\nextbox
      \d_grph_rotate_saved_depth \dp\nextbox
-     \setbox\nextbox\vbox{\vskip.5\ht\nextbox\hskip-.5\wd\nextbox\box\nextbox}%
+     \setbox\nextbox\vpack{\vskip.5\ht\nextbox\hskip-.5\wd\nextbox\box\nextbox}%
      \smashbox\nextbox
    \fi
    \d_grph_rotate_width \wd\nextbox
    \d_grph_rotate_height\ht\nextbox
    \d_grph_rotate_depth \dp\nextbox
-   \setbox\nextbox\vbox{\hbox{\raise\dp\nextbox\box\nextbox}}%
+   \setbox\nextbox\vpack{\hpack{\raise\dp\nextbox\box\nextbox}}%
    \d_grph_rotate_used_height \ht\nextbox
    % much of the next happens in lua (all the sin and cos) so we can do that in
    % one go if needed
@@ -1143,7 +1143,7 @@
      \fi\fi
    \fi
    \ifconditional\c_grph_rotate_center
-     \setbox\nextbox\vbox{\vskip-.5\d_grph_rotate_saved_height\hskip.5\d_grph_rotate_saved_height\box\nextbox}%
+     \setbox\nextbox\vpack{\vskip-.5\d_grph_rotate_saved_height\hskip.5\d_grph_rotate_saved_height\box\nextbox}%
      \wd\nextbox\d_grph_rotate_saved_width
      \ht\nextbox\d_grph_rotate_saved_height
      \dp\nextbox\d_grph_rotate_saved_depth
@@ -1209,9 +1209,9 @@
    \fi}
 
 \def\grph_rotate_apply
-  {\setbox\nextbox\vbox to \d_grph_rotate_y_size
+  {\setbox\nextbox\vpack to \d_grph_rotate_y_size
      {\vfill
-      \hbox to \d_grph_rotate_x_size
+      \hpack to \d_grph_rotate_x_size
         {\dostartrotation\p_rotation_rotation
            \wd\nextbox\zeropoint
            \ht\nextbox\zeropoint
@@ -1219,7 +1219,7 @@
          \dostoprotation
          \hfill}%
       \kern\d_grph_rotate_y_position}%
-   \setbox\nextbox\hbox
+   \setbox\nextbox\hpack
      {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax
       \lower\d_grph_rotate_y_offset\box\nextbox}}
 
diff --git a/tex/context/base/lang-hyp.lua b/tex/context/base/lang-hyp.lua
index 49976515d..d1260b8b4 100644
--- a/tex/context/base/lang-hyp.lua
+++ b/tex/context/base/lang-hyp.lua
@@ -328,9 +328,11 @@ local function hyphenate(dictionary,word,n) -- odd is okay
     end
     local l = 1
     local w = { "." }
+ -- local d = dictionary.codehash or lcchars[c]
     for i=1,n do
         local c = word[i]
         l = l + 1
+     -- w[l] = d[c] or c -- needs testing
         w[l] = lcchars[c] or c
     end
     l = l + 1
@@ -359,8 +361,8 @@ local function hyphenate(dictionary,word,n) -- odd is okay
         show_1(w)
     end
     --
-    local specials   = dictionary.specials
-    local patterns   = dictionary.patterns
+    local specials = dictionary.specials
+    local patterns = dictionary.patterns
     --
 -- inspect(specials)
     local spec
@@ -648,8 +650,6 @@ if context then
     local preexhyphenchar    = lang.preexhyphenchar
     local postexhyphenchar   = lang.postexhyphenchar
 
-    local lccodes            = characters.lccodes
-
     local a_hyphenation      = attributes.private("hyphenation")
 
     function traditional.loadpatterns(language)
diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua
index d75a665e2..46ccdec35 100644
--- a/tex/context/base/lang-ini.lua
+++ b/tex/context/base/lang-ini.lua
@@ -16,10 +16,13 @@ if not modules then modules = { } end modules ['lang-ini'] = {
 
 --~ lang:hyphenation(string) string = lang:hyphenation() lang:clear_hyphenation()
 
+-- todo: no foo:bar but foo(bar,...)
+
 local type, tonumber = type, tonumber
 local utfbyte = utf.byte
 local format, gsub = string.format, string.gsub
 local concat, sortedkeys, sortedpairs = table.concat, table.sortedkeys, table.sortedpairs
+local utfbytes = string.utfvalues
 
 local context   = context
 local commands  = commands
@@ -31,33 +34,37 @@ local trace_patterns = false  trackers.register("languages.patterns", function(v
 
 local report_initialization = logs.reporter("languages","initialization")
 
+local lang             = lang
+
 local prehyphenchar    = lang.prehyphenchar    -- global per language
 local posthyphenchar   = lang.posthyphenchar   -- global per language
 local preexhyphenchar  = lang.preexhyphenchar  -- global per language
 local postexhyphenchar = lang.postexhyphenchar -- global per language
 local lefthyphenmin    = lang.lefthyphenmin
 local righthyphenmin   = lang.righthyphenmin
+local sethjcode        = lang.sethjcode
+
+local uccodes          = characters.uccodes
 
-local lang           = lang
-lang.exceptions      = lang.hyphenation
-local new_langage    = lang.new
+lang.exceptions        = lang.hyphenation
+local new_langage      = lang.new
 
-languages            = languages or {}
-local languages      = languages
+languages              = languages or {}
+local languages        = languages
 
-languages.version    = 1.010
+languages.version      = 1.010
 
-languages.registered = languages.registered or { }
-local registered     = languages.registered
+languages.registered   = languages.registered or { }
+local registered       = languages.registered
 
-languages.associated = languages.associated or { }
-local associated     = languages.associated
+languages.associated   = languages.associated or { }
+local associated       = languages.associated
 
-languages.numbers    = languages.numbers    or { }
-local numbers        = languages.numbers
+languages.numbers      = languages.numbers    or { }
+local numbers          = languages.numbers
 
-languages.data       = languages.data       or { }
-local data           = languages.data
+languages.data         = languages.data       or { }
+local data             = languages.data
 
 storage.register("languages/registered",registered,"languages.registered")
 storage.register("languages/associated",associated,"languages.associated")
@@ -107,7 +114,8 @@ end
 -- patterns=en
 -- patterns=en,de
 
-local function validdata(dataset,what,tag)
+local function validdata(loaded,what,tag)
+    local dataset = loaded[what]
     if dataset then
         local data = dataset.data
         if not data or data == "" then
@@ -124,6 +132,31 @@ local function validdata(dataset,what,tag)
     end
 end
 
+local function sethjcodes(instance,loaded,what)
+    local l = loaded[what]
+    local c = l and l.characters
+    if c then
+        local h = l.codehash
+        if not h then
+            h = { }
+            l.codehash = h
+        end
+        local s = tex.savinghyphcodes
+        tex.savinghyphcodes = 0
+        for l in utfbytes(c) do
+            local u = uccodes[l]
+            sethjcode(instance,l,l)
+            h[l] = l
+            if type(u) == "number" then
+                -- we don't want ß -> SS
+                sethjcode(instance,u,l)
+                h[u] = l
+            end
+        end
+        tex.savinghyphcodes = s
+    end
+end
+
 local function loaddefinitions(tag,specification)
     statistics.starttiming(languages)
     local data, instance = resolve(tag)
@@ -160,12 +193,13 @@ local function loaddefinitions(tag,specification)
                     local loaded = table.load(fullname,gzipped and gzip.load)
                     if loaded then -- todo: version test
                         ok, nofloaded = true, nofloaded + 1
-                     -- instance:patterns   (loaded.patterns   and resources.patterns  .data or "")
-                     -- instance:hyphenation(loaded.exceptions and resources.exceptions.data or "")
-                        instance:patterns   (validdata(loaded.patterns,  "patterns",  tag) or "")
-                        instance:hyphenation(validdata(loaded.exceptions,"exceptions",tag) or "")
+if sethjcodes then -- for now
+                        sethjcodes(instance,loaded,"patterns")
+                        sethjcodes(instance,loaded,"exceptions")
+end
+                        instance:patterns   (validdata(loaded,"patterns",  tag) or "")
+                        instance:hyphenation(validdata(loaded,"exceptions",tag) or "")
                         resources[#resources+1] = loaded -- so we can use them otherwise
-
                     else
                         report_initialization("invalid definition %a for language %a in %a",definition,tag,filename)
                     end
diff --git a/tex/context/base/lang-ini.mkiv b/tex/context/base/lang-ini.mkiv
index 492128706..cfe3f84b8 100644
--- a/tex/context/base/lang-ini.mkiv
+++ b/tex/context/base/lang-ini.mkiv
@@ -86,51 +86,100 @@
 \installcorenamespace{language}
 \installcorenamespace{languagelinked}
 
+\def\currentusedlanguage{\currentlanguage}
+
 \def\defaultlanguage#1%
   {\ifcsname\??language#1\s!default\endcsname
-     \expandafter\defaultlanguage\csname\??language#1\s!default\endcsname
+    %\expandafter\defaultlanguage\csname\??language#1\s!default\endcsname
+     \expandafter\defaultlanguage\lastnamedcs
    \else
      #1%
    \fi}
 
+% \def\languageparameter#1%
+%   {\ifcsname\??language\currentlanguage#1\endcsname
+%      \csname\??language\currentlanguage#1\endcsname
+%    \else\ifcsname\??language\currentlanguage\s!default\endcsname
+%      \expandafter\specificlanguageparameter\csname\??language\currentlanguage\s!default\endcsname{#1}%
+%    \else\ifcsname\??language\s!default#1\endcsname
+%      \csname\??language\s!default#1\endcsname
+%    \fi\fi\fi}
+%
+% \def\specificlanguageparameter#1#2%
+%   {\ifcsname\??language#1#2\endcsname
+%      \csname\??language#1#2\endcsname
+%    \else\ifcsname\??language#1\s!default\endcsname
+%      \expandafter\specificlanguageparameter\csname\??language#1\s!default\endcsname{#2}%
+%    \else\ifcsname\??language\s!default#2\endcsname
+%      \csname\??language\s!default#2\endcsname
+%    \fi\fi\fi}
+%
+% \def\mainlanguageparameter#1%
+%   {\ifcsname\??language\currentmainlanguage#1\endcsname
+%      \csname\??language\currentmainlanguage#1\endcsname
+%    \else\ifcsname\??language\currentmainlanguage\s!default\endcsname
+%      \expandafter\specificlanguageparameter\csname\??language\currentmainlanguage\s!default\endcsname{#1}%
+%    \else\ifcsname\??language\s!default#1\endcsname
+%      \csname\??language\s!default#1\endcsname
+%    \fi\fi\fi}
+
 \def\languageparameter#1%
   {\ifcsname\??language\currentlanguage#1\endcsname
-     \csname\??language\currentlanguage#1\endcsname
+    %\csname\??language\currentlanguage#1\endcsname
+     \expandafter\empty\lastnamedcs
    \else\ifcsname\??language\currentlanguage\s!default\endcsname
-     \expandafter\specificlanguageparameter\csname\??language\currentlanguage\s!default\endcsname{#1}%
+    %\expandafter\specificlanguageparameter\csname\??language\currentlanguage\s!default\endcsname{#1}%
+     \expandafter\specificlanguageparameter\lastnamedcs{#1}%
    \else\ifcsname\??language\s!default#1\endcsname
-     \csname\??language\s!default#1\endcsname
+    %\csname\??language\s!default#1\endcsname
+     \expandafter\empty\lastnamedcs
    \fi\fi\fi}
 
 \def\specificlanguageparameter#1#2%
   {\ifcsname\??language#1#2\endcsname
-     \csname\??language#1#2\endcsname
+    %\csname\??language#1#2\endcsname
+     \expandafter\empty\lastnamedcs
    \else\ifcsname\??language#1\s!default\endcsname
-     \expandafter\specificlanguageparameter\csname\??language#1\s!default\endcsname{#2}%
+    %\expandafter\specificlanguageparameter\csname\??language#1\s!default\endcsname{#2}%
+     \expandafter\specificlanguageparameter\lastnamedcs{#2}%
    \else\ifcsname\??language\s!default#2\endcsname
-     \csname\??language\s!default#2\endcsname
+    %\csname\??language\s!default#2\endcsname
+     \expandafter\empty\lastnamedcs
    \fi\fi\fi}
 
 \def\mainlanguageparameter#1%
   {\ifcsname\??language\currentmainlanguage#1\endcsname
-     \csname\??language\currentmainlanguage#1\endcsname
+    %\csname\??language\currentmainlanguage#1\endcsname
+     \expandafter\empty\lastnamedcs
    \else\ifcsname\??language\currentmainlanguage\s!default\endcsname
-     \expandafter\specificlanguageparameter\csname\??language\currentmainlanguage\s!default\endcsname{#1}%
+    %\expandafter\specificlanguageparameter\csname\??language\currentmainlanguage\s!default\endcsname{#1}%
+     \expandafter\specificlanguageparameter\lastnamedcs{#1}%
    \else\ifcsname\??language\s!default#1\endcsname
-     \csname\??language\s!default#1\endcsname
+    %\csname\??language\s!default#1\endcsname
+     \expandafter\empty\lastnamedcs
    \fi\fi\fi}
 
-\def\currentusedlanguage{\currentlanguage}
-
 \let\usedlanguageparameter\languageparameter
 
+% \def\askedlanguageparameter#1% assumes \currentusedlanguage being set
+%   {\ifcsname\??language\currentusedlanguage#1\endcsname
+%      \csname\??language\currentusedlanguage#1\endcsname
+%    \else\ifcsname\??language\currentusedlanguage\s!default\endcsname
+%      \expandafter\specificlanguageparameter\csname\??language\currentusedlanguage\s!default\endcsname{#1}%
+%    \else\ifcsname\??language\s!default#1\endcsname
+%      \csname\??language\s!default#1\endcsname
+%    \fi\fi\fi}
+
 \def\askedlanguageparameter#1% assumes \currentusedlanguage being set
   {\ifcsname\??language\currentusedlanguage#1\endcsname
-     \csname\??language\currentusedlanguage#1\endcsname
+    %\csname\??language\currentusedlanguage#1\endcsname
+     \expandafter\empty\lastnamedcs
    \else\ifcsname\??language\currentusedlanguage\s!default\endcsname
-     \expandafter\specificlanguageparameter\csname\??language\currentusedlanguage\s!default\endcsname{#1}%
+    %\expandafter\specificlanguageparameter\csname\??language\currentusedlanguage\s!default\endcsname{#1}%
+     \expandafter\specificlanguageparameter\lastnamedcs{#1}%
    \else\ifcsname\??language\s!default#1\endcsname
-     \csname\??language\s!default#1\endcsname
+    %\csname\??language\s!default#1\endcsname
+     \expandafter\empty\lastnamedcs
    \fi\fi\fi}
 
 \unexpanded\def\setlanguageparameter#1%
@@ -223,7 +272,8 @@
 \let\doiflanguageelse\doifelselanguage
 
 \def\reallanguagetag#1%
-  {\ifcsname\??languagelinked#1\endcsname\csname\??languagelinked#1\endcsname\else#1\fi}
+ %{\ifcsname\??languagelinked#1\endcsname\csname\??languagelinked#1\endcsname\else#1\fi}
+  {\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi}
 
 % \language[#1] gave unwanted side effect of loading language specifics
 
@@ -546,10 +596,22 @@
 
 %D Fast switcher
 
+% \def\lang_basics_switch_asked
+%   {\ifx\askedlanguage\empty \else
+%      \ifcsname\??languagelinked\askedlanguage\endcsname
+%        \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+%        \ifx\currentlanguage\askedlanguage \else
+%          \setcurrentlanguage\currentmainlanguage\askedlanguage
+%          \lang_basics_synchronize
+%        \fi
+%      \fi
+%    \fi}
+
 \def\lang_basics_switch_asked
   {\ifx\askedlanguage\empty \else
      \ifcsname\??languagelinked\askedlanguage\endcsname
-       \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+      %\edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+       \edef\askedlanguage{\lastnamedcs}%
        \ifx\currentlanguage\askedlanguage \else
          \setcurrentlanguage\currentmainlanguage\askedlanguage
          \lang_basics_synchronize
@@ -574,11 +636,30 @@
 
 \newcount\mainlanguagenumber
 
+% \unexpanded\def\mainlanguage[#1]%
+%   {\edef\askedlanguage{#1}%
+%    \ifx\askedlanguage\empty \else
+%      \ifcsname\??languagelinked\askedlanguage\endcsname
+%        \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+%        \ifx\currentlanguage\askedlanguage
+%          \ifx\currentmainlanguage\askedlanguage \else
+%            \setcurrentlanguage\askedlanguage\askedlanguage
+%            \lang_basics_synchronize
+%          \fi
+%        \else
+%          \setcurrentlanguage\askedlanguage\askedlanguage
+%          \lang_basics_synchronize
+%        \fi
+%      \fi
+%    \fi
+%    \mainlanguagenumber\normallanguage}
+
 \unexpanded\def\mainlanguage[#1]%
   {\edef\askedlanguage{#1}%
    \ifx\askedlanguage\empty \else
      \ifcsname\??languagelinked\askedlanguage\endcsname
-       \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+      %\edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
+       \edef\askedlanguage{\lastnamedcs}%
        \ifx\currentlanguage\askedlanguage
          \ifx\currentmainlanguage\askedlanguage \else
            \setcurrentlanguage\askedlanguage\askedlanguage
diff --git a/tex/context/base/lang-lab.mkiv b/tex/context/base/lang-lab.mkiv
index f615ad6a6..ffa221ee8 100644
--- a/tex/context/base/lang-lab.mkiv
+++ b/tex/context/base/lang-lab.mkiv
@@ -92,21 +92,28 @@
      \def#3{#5#4}%
      \def#5##1##2% ##1=language
        {\ifcsname\??label\currentlabelcategory#1:##1:##2\endcsname
-          \csname\??label\currentlabelcategory#1:##1:##2\endcsname
+         %\csname\??label\currentlabelcategory#1:##1:##2\endcsname
+          \lastnamedcs
         \else\ifcsname\??label#1:##1:##2\endcsname
-          \csname\??label#1:##1:##2\endcsname
+         %\csname\??label#1:##1:##2\endcsname
+          \lastnamedcs
       % \else\ifcsname\??language#4\s!default\endcsname
       %   \expandafter#5\csname\??language#4\s!default\endcsname{##2}%
         \else\ifcsname\??language##1\s!default\endcsname
-          \expandafter#5\csname\??language##1\s!default\endcsname{##2}%
+         %\expandafter#5\csname\??language##1\s!default\endcsname{##2}%
+          \expandafter#5\lastnamedcs{##2}%
         \else\ifcsname\??label\currentlabelcategory#1:##2\endcsname
-          \csname\??label\currentlabelcategory#1:##2\endcsname
+         %\csname\??label\currentlabelcategory#1:##2\endcsname
+          \lastnamedcs
         \else\ifcsname\??label#1:##2\endcsname
-          \csname\??label#1:##2\endcsname
+         %\csname\??label#1:##2\endcsname
+          \lastnamedcs
         \else\ifcsname\??label\currentlabelcategory#1:\s!en:##2\endcsname
-          \csname\??label\currentlabelcategory#1:\s!en:##2\endcsname
+         %\csname\??label\currentlabelcategory#1:\s!en:##2\endcsname
+          \lastnamedcs
         \else\ifcsname\??label#1:\s!en:##2\endcsname
-          \csname\??label#1:\s!en:##2\endcsname
+         %\csname\??label#1:\s!en:##2\endcsname
+          \lastnamedcs
         \else
           ##2%
         \fi\fi\fi\fi\fi\fi\fi}%
@@ -118,13 +125,17 @@
      \unexpanded\def#3{#5#4}%
      \unexpanded\def#5##1##2%
        {\ifcsname\??label#1:##1:##2\endcsname
-          \expandafter\let\expandafter\thetextprefix\csname\??label#1:##1:##2\endcsname
+         %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##1:##2\endcsname
+          \expandafter\let\expandafter\thetextprefix\lastnamedcs
         \else\ifcsname\??language#4\s!default\endcsname
-          \expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+         %\expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+          \expandafter#5\lastnamedcs{##2}%
         \else\ifcsname\??label#1:##2\endcsname
-          \expandafter\let\expandafter\thetextprefix\csname\??label#1:##2\endcsname
+         %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##2\endcsname
+          \expandafter\let\expandafter\thetextprefix\lastnamedcs
         \else\ifcsname\??label#1:\s!en:##2\endcsname
-          \expandafter\let\expandafter\thetextprefix\csname\??label#1:\s!en:##2\endcsname
+         %\expandafter\let\expandafter\thetextprefix\csname\??label#1:\s!en:##2\endcsname
+          \expandafter\let\expandafter\thetextprefix\lastnamedcs
         \else
           \let\thetextprefix\dummytextprefix
         \fi\fi\fi\fi}%
@@ -218,18 +229,34 @@
 \let\m_lang_labels_left \empty
 \let\m_lang_labels_right\empty
 
+% \def\lang_labels_text_prefix_assign_yes#1[#2,#3,#4]%
+%   {\def\m_lang_labels_left {#2}% no longer an edef ... else \Word undefined expansion issues
+%    \def\m_lang_labels_right{#3}% no longer an edef ... else \Word undefined expansion issues
+%    \ifx\m_lang_labels_right\empty
+%      \ifx\m_lang_labels_left\empty
+%        \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{\empty\empty}%
+%      \else
+%        \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}\empty}%
+%      \fi
+%    \else
+%      \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}{#3}}%
+%    \fi}
+%
+% how we love obscure efficicency ...
+
 \def\lang_labels_text_prefix_assign_yes#1[#2,#3,#4]%
   {\def\m_lang_labels_left {#2}% no longer an edef ... else \Word undefined expansion issues
    \def\m_lang_labels_right{#3}% no longer an edef ... else \Word undefined expansion issues
-   \ifx\m_lang_labels_right\empty
-     \ifx\m_lang_labels_left\empty
-       \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{\empty\empty}%
+   \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1%
+     \ifx\m_lang_labels_right\empty
+       \ifx\m_lang_labels_left\empty
+         \endcsname{\empty\empty}%
+       \else
+         \endcsname{{#2}\empty}%
+       \fi
      \else
-       \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}\empty}%
-     \fi
-   \else
-     \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}{#3}}%
-   \fi}
+       \endcsname{{#2}{#3}}%
+     \fi}
 
 \def\lang_labels_text_prefix_assign_nop#1[#2]%
   {}
@@ -297,9 +324,11 @@
 \def\lang_translate[#1]%
   {\getparameters[\??translation][#1]%
    \ifcsname\??translation\currentlanguage\endcsname
-     \csname\??translation\currentlanguage\endcsname
+    %\csname\??translation\currentlanguage\endcsname
+     \lastnamedcs
    \else\ifcsname\??translation\s!en\endcsname
-     \csname\??translation\s!en\endcsname
+    %\csname\??translation\s!en\endcsname
+     \lastnamedcs
    \else
      [translation #1]%
    \fi\fi}
diff --git a/tex/context/base/lang-mis.mkiv b/tex/context/base/lang-mis.mkiv
index 2b886b3ce..87b58b303 100644
--- a/tex/context/base/lang-mis.mkiv
+++ b/tex/context/base/lang-mis.mkiv
@@ -186,6 +186,7 @@
 \installcorenamespace{discretionarytext}
 \installcorenamespace{discretionarymath}
 \installcorenamespace{discretionaryboth}
+\installcorenamespace{discretionarymode}
 
 \unexpanded\def\installdiscretionary#1#2%
   {\setevalue{\??discretionarymath\detokenize{#1}}{\detokenize{#1}}% ?
@@ -194,8 +195,11 @@
    \scratchcounter\expandafter`\detokenize{#1}%
    \expandafter\uedcatcodecommand\expandafter\ctxcatcodes\expandafter\scratchcounter\csname\??discretionaryboth\detokenize{#1}\endcsname}
 
-\unexpanded\def\handlemathmodediscretionary#1{\executeifdefined{\??discretionarymath\detokenize{#1}}\donothing}
-\unexpanded\def\handletextmodediscretionary#1{\executeifdefined{\??discretionarytext\detokenize{#1}}\donothing}
+%unexpanded\def\handlemathmodediscretionary#1{\executeifdefined{\??discretionarymath\detokenize{#1}}\donothing}
+%unexpanded\def\handletextmodediscretionary#1{\executeifdefined{\??discretionarytext\detokenize{#1}}\donothing}
+
+\unexpanded\def\handlemathmodediscretionary#1{\\ifcsname\??discretionarymath\detokenize{#1}\endcsname\lastnamedcs}
+\unexpanded\def\handletextmodediscretionary#1{\\ifcsname\??discretionarytext\detokenize{#1}\endcsname\lastnamedcs}
 
 \unexpanded\def\installdiscretionaries#1#2{\writestatus\m!system{use \string \installdiscretionary}} % obsolete
 
@@ -206,17 +210,18 @@
 
 \def\lang_discretionaries_command
   {% if direct if, we need \relax for lookahead in math mode
-   \csname
+   \csname\??discretionarymode
      \ifcase\discretionarymode
-       \strippedcsname\lang_discretionaries_process_none
+       n% \csstring\lang_discretionaries_process_none
      \else\ifmmode
-       \strippedcsname\lang_discretionaries_process_math
+       m% \csstring\lang_discretionaries_process_math
      \else
-       \strippedcsname\lang_discretionaries_process_text
+       t% \csstring\lang_discretionaries_process_text
      \fi\fi
    \endcsname}
 
-\def\lang_discretionaries_process_none#1%
+% \def\lang_discretionaries_process_none#1%
+\setvalue{\??discretionarymode n}#1%
   {\detokenize{#1}}
 
 %D The macro \type{\lang_discretionaries_check_before} takes care of loners like
@@ -252,9 +257,11 @@
    \ifx          :\nextnext \settrue \punctafterdiscretionary \else
    \ifx          ;\nextnext \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi}
 
-\let\lang_discretionaries_process_math\handlemathmodediscretionary
+%let\lang_discretionaries_process_math\handlemathmodediscretionary
+\letvalue{\??discretionarymode m}\handlemathmodediscretionary
 
-\def\lang_discretionaries_process_text#1% grouped !
+% \def\lang_discretionaries_process_text#1% grouped !
+\setvalue{\??discretionarymode t}#1%
   {\bgroup
    \let\nextnextnext\egroup
    \def\next##1#1%
@@ -269,7 +276,8 @@
    \ifx\discretionarytoken\empty
      \ifx#1\nextnext % takes care of ||| and +++ and ......
        \ifcsname\??discretionaryaction\string#1\endcsname
-         \csname\??discretionaryaction\string#1\endcsname
+        %\csname\??discretionaryaction\string#1\endcsname
+         \lastnamedcs
        \else\ifconditional\spaceafterdiscretionary
          \prewordbreak\hbox{\string#1}\relax
        \else\ifconditional\punctafterdiscretionary
@@ -284,7 +292,8 @@
        % \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak
        % but an hbox blocks a possible \discretionary
        \ifcsname\??discretionaryaction\endcsname
-         \csname\??discretionaryaction\endcsname
+        %\csname\??discretionaryaction\endcsname
+         \lastnamedcs
        \else\ifconditional\spaceafterdiscretionary
          \prewordbreak\textmodediscretionary\relax
        \else\ifconditional\punctafterdiscretionary
@@ -295,7 +304,8 @@
      %  \prewordbreak\textmodediscretionary\nextnext\allowbreak\postwordbreak
      \fi
    \else\ifcsname\??discretionaryaction\discretionarytoken\endcsname
-     \csname\??discretionaryaction\discretionarytoken\endcsname
+    %\csname\??discretionaryaction\discretionarytoken\endcsname
+     \lastnamedcs
    \else
      \lang_discretionaries_check_before
      \ifconditional\spaceafterdiscretionary
@@ -315,29 +325,36 @@
 %D use the more direct approach:
 
 \unexpanded\def\directdiscretionary
-  {\csname
+  {\csname\??discretionarymode
      \ifcase\discretionarymode
-       \strippedcsname\lang_discretionaries_process_none
+       n% \csstring\lang_discretionaries_process_none
      \else
-       \strippedcsname\lang_discretionaries_process_direct
+       d% \csstring\lang_discretionaries_process_direct
      \fi
    \endcsname}
 
 \unexpanded\def\indirectdiscretionary
-  {\csname
+  {\csname\??discretionarymode
      \ifcase\discretionarymode
-       \strippedcsname\lang_discretionaries_process_none
+       n% \csstring\lang_discretionaries_process_none
      \else
-       \strippedcsname\lang_discretionaries_process_indirect
+       i% \csstring\lang_discretionaries_process_indirect
      \fi
    \endcsname}
 
-\unexpanded\def\lang_discretionaries_process_direct#1%
+% \unexpanded\def\lang_discretionaries_process_direct#1%
+\setuvalue{\??discretionarymode d}#1%
   {\edef\discretionarytoken{\detokenize{#1}}%
    \let\textmodediscretionary\compoundhyphen
-   \executeifdefined{\??discretionaryaction\discretionarytoken}{\indirectdiscretionary{#1}}}
+  %\executeifdefined{\??discretionaryaction\discretionarytoken}{\indirectdiscretionary{#1}}}
+   \ifcsname\??discretionaryaction\discretionarytoken\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\indirectdiscretionary
+   \fi{#1}}
 
-\unexpanded\unexpanded\def\lang_discretionaries_process_indirect#1%
+% \unexpanded\unexpanded\def\lang_discretionaries_process_indirect#1%
+\setuvalue{\??discretionarymode i}#1%
   {\prewordbreak\discretionary{\hbox{#1}}{}{\hbox{#1}}\allowbreak\postwordbreak}
 
 \unexpanded\def\definetextmodediscretionary #1
@@ -592,34 +609,65 @@
 %D
 %D In later modules we will see how these commands are used.
 
+% \def\lang_compounds_handle_character_one#1#2%
+%   {\if\string#1\string#2% was: \ifx#1#2%
+%      \def\next{\csname\??compoundnormal\string#1\endcsname}%
+%    \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
+%      \def\next{\csname\??compoundsingle\string#1\string#2\endcsname}%
+%    \else
+%      \def\next{\csname\??compoundnormal\string#1\endcsname#2}%
+%    \fi\fi
+%    \next}
+%
+% \def\lang_compounds_handle_character_two#1#2#3%
+%   {\if\string#1\string#2%
+%      \def\next{\csname\??compoundnormal\string#1\endcsname#3}%
+%    \else\ifcsname\??compoundmultiple\string#1\string#2\string#3\endcsname
+%      \def\next{\csname\??compoundmultiple\string#1\string#2\string#3\endcsname}%
+%    \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
+%      \def\next{\csname\??compoundsingle\string#1\string#2\endcsname#3}%
+%    \else
+%      \def\next{\csname\??compoundnormal\string#1\endcsname#2#3}%
+%    \fi\fi\fi
+%    \next}
+
 \def\lang_compounds_handle_character_one#1#2%
   {\if\string#1\string#2% was: \ifx#1#2%
-     \def\next{\csname\??compoundnormal\string#1\endcsname}%
+    %\expandafter\let\expandafter\next\csname\??compoundnormal\string#1\endcsname
+     \csname\??compoundnormal\string#1\expandafter\endcsname
    \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
-     \def\next{\csname\??compoundsingle\string#1\string#2\endcsname}%
+    %\expandafter\let\expandafter\next\lastnamedcs
+     \expandafter\lastnamedcs
    \else
-     \def\next{\csname\??compoundnormal\string#1\endcsname#2}%
-   \fi\fi
-   \next}
+    %\expandafter\let\expandafter\next\lastnamedcs
+     \expandafter\lastnamedcs
+   \fi\fi}
 
 \def\lang_compounds_handle_character_two#1#2#3%
   {\if\string#1\string#2%
      \def\next{\csname\??compoundnormal\string#1\endcsname#3}%
    \else\ifcsname\??compoundmultiple\string#1\string#2\string#3\endcsname
-     \def\next{\csname\??compoundmultiple\string#1\string#2\string#3\endcsname}%
+     \expandafter\let\expandafter\next\lastnamedcs
    \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
-     \def\next{\csname\??compoundsingle\string#1\string#2\endcsname#3}%
+     \expandafter\let\expandafter\next\lastnamedcs
    \else
-     \def\next{\csname\??compoundnormal\string#1\endcsname#2#3}%
+     \expandafter\let\expandafter\next\lastnamedcs
    \fi\fi\fi
    \next}
 
 %D For very obscure applications (see for an application \type {lang-sla.tex}) we
 %D provide:
 
+% \def\simplifiedcompoundcharacter#1#2%
+%   {\ifcsname\??compoundsingle\string#1\string#2\endcsname
+%      \doubleexpandafter\firstofoneargument\csname\??compoundsingle\string#1\string#2\endcsname
+%    \else
+%      #2%
+%    \fi}
+
 \def\simplifiedcompoundcharacter#1#2%
   {\ifcsname\??compoundsingle\string#1\string#2\endcsname
-     \doubleexpandafter\firstofoneargument\csname\??compoundsingle\string#1\string#2\endcsname
+     \doubleexpandafter\firstofoneargument\lastnamedcs
    \else
      #2%
    \fi}
diff --git a/tex/context/base/luat-ini.mkiv b/tex/context/base/luat-ini.mkiv
index b455a4158..ec0572f32 100644
--- a/tex/context/base/luat-ini.mkiv
+++ b/tex/context/base/luat-ini.mkiv
@@ -259,24 +259,24 @@
 
 % This is a forward definition:
 
-\def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
-  {\expandafter\syst_helpers_checked_stripped_csname\string#1}
+% \def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
+%   {\expandafter\syst_helpers_checked_stripped_csname\string#1}
 
 \def\syst_helpers_checked_stripped_csname#1%
   {\if\noexpand#1\letterbackslash\else#1\fi}
 
 \normalprotected\def\installctxfunction#1#2%
-  {\edef\m_syst_name{\checkedstrippedcsname#1}%
+  {\edef\m_syst_name{\csstring#1}%
    \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
    \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
 
 \normalprotected\def\installctxscanner#1#2%
-  {\edef\m_syst_name{\checkedstrippedcsname#1}%
+  {\edef\m_syst_name{\csstring#1}%
    \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
    \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
 
 \normalprotected\def\resetctxscanner#1%
-  {\edef\m_syst_name{\checkedstrippedcsname#1}%
+  {\edef\m_syst_name{\csstring#1}%
    \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\zerocount
    \global\expandafter\let\csname\m_syst_name\endcsname\relax}
 
diff --git a/tex/context/base/lxml-ini.mkiv b/tex/context/base/lxml-ini.mkiv
index edccff831..9f84f8ca3 100644
--- a/tex/context/base/lxml-ini.mkiv
+++ b/tex/context/base/lxml-ini.mkiv
@@ -376,7 +376,7 @@
 % processing instructions
 
 \unexpanded\def\xmlinstalldirective#1#2%
-  {\clf_xmlinstalldirective{#1}{\checkedstrippedcsname#2}}
+  {\clf_xmlinstalldirective{#1}{\csstring#2}}
 
 % \def\xmlcontextdirective#1% kind class key value
 %   {\executeifdefined{xml#1directive}\gobblethreearguments}
@@ -423,10 +423,17 @@
    \c!entities=\v!yes]   % replace entities
 
 \def\xmlmapvalue    #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces
-\def\xmlvalue       #1#2#3{\executeifdefined{\??xmlmapvalue#1:#2}{#3}}
+%def\xmlvalue       #1#2#3{\executeifdefined{\??xmlmapvalue#1:#2}{#3}}
 %def\xmlvalue         #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\csname\??xmlmapvalue#1:#2\expandafter\expandafter\gobbleoneargument\expandafter\endcsname\else\expandafter\firstofoneargument\fi}
 \def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
 
+\def\xmlvalue#1#2% #3
+  {\ifcsname\??xmlmapvalue#1:#2\endcsname
+     \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
+   \else
+     \expandafter\firstofoneargument
+   \fi}
+
 \let\xmldoifvalueelse\xmldoifelsevalue
 
 \let\xmlmapval\xmlmapvalue
diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua
index f0a3cb385..7f375927e 100644
--- a/tex/context/base/lxml-tex.lua
+++ b/tex/context/base/lxml-tex.lua
@@ -249,7 +249,7 @@ function lxml.setescapedentities(v)
     end
 end
 
-lxml.setescapedentities()
+lxml.setescapedentities() -- off by default (for now)
 
 directives.register("lxml.escapedentities",lxml.setescapedentities)
 
diff --git a/tex/context/base/m-oldotf.mkiv b/tex/context/base/m-oldotf.mkiv
index 04a83a47b..418d0bc2a 100644
--- a/tex/context/base/m-oldotf.mkiv
+++ b/tex/context/base/m-oldotf.mkiv
@@ -24,7 +24,7 @@
         "font-otf",
         "font-otb",
         "font-inj",
-        "font-ota",
+--      "font-ota",
         "font-otn",
         "font-otd",
         "font-otp",
diff --git a/tex/context/base/math-ali.mkiv b/tex/context/base/math-ali.mkiv
index bdb4c36f7..c0f105121 100644
--- a/tex/context/base/math-ali.mkiv
+++ b/tex/context/base/math-ali.mkiv
@@ -1114,14 +1114,14 @@
            \box\scratchbox
          \else
            \ifdone
-             \vbox{\box\scratchbox\hbox to \displaywidth{\hss\math_box_llapped_math_no}}% \checkeddisplaymath
+             \vpack{\box\scratchbox\hpack to \displaywidth{\hss\math_box_llapped_math_no}}% \checkeddisplaymath
            \else
              \hss\box\scratchbox\math_box_llapped_math_no % hss makes room for number
            \fi
          \fi
        \else
          \ifdone
-           \vbox{\hbox to \displaywidth{\math_box_rlapped_math_no\hss}\box\scratchbox}% \checkeddisplaymath
+           \vpack{\hpack to \displaywidth{\math_box_rlapped_math_no\hss}\box\scratchbox}% \checkeddisplaymath
          \else
            \math_box_rlapped_math_no\box\scratchbox\hss % hss makes room for number
          \fi
diff --git a/tex/context/base/math-arr.mkiv b/tex/context/base/math-arr.mkiv
index 0e3a53f32..9056bf5a4 100644
--- a/tex/context/base/math-arr.mkiv
+++ b/tex/context/base/math-arr.mkiv
@@ -211,7 +211,7 @@
   {\ifcsname#1\endcsname
      \pushmacro\math_arrows_do
      \def\math_arrows_do[##1][##2]{\setuvalue{#1}{\math_arrows_do[#2][##2]}}%
-     \getvalue{#1}%
+     \csname#1\endcsname
      \popmacro\math_arrows_do
    \fi}
 
diff --git a/tex/context/base/math-def.mkiv b/tex/context/base/math-def.mkiv
index 7337bae4b..a8af5af5c 100644
--- a/tex/context/base/math-def.mkiv
+++ b/tex/context/base/math-def.mkiv
@@ -75,7 +75,7 @@
 
 \unexpanded\def\setoperatorlimits#1#2% operator limits
   {\savenormalmeaning{#1}%
-   \expandafter\def\expandafter#1\expandafter{\csname normal\strippedcsname#1\endcsname#2}}
+   \expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}}
 
 \setoperatorlimits \int              \intlimits
 \setoperatorlimits \iint             \intlimits
diff --git a/tex/context/base/math-fen.mkiv b/tex/context/base/math-fen.mkiv
index b0c90290d..11464dfbc 100644
--- a/tex/context/base/math-fen.mkiv
+++ b/tex/context/base/math-fen.mkiv
@@ -222,48 +222,107 @@
 \newconditional\c_math_fenced_done
 \newconditional\c_math_fenced_unknown  \settrue\c_math_fenced_unknown
 
-% maybe use \detokenize ...
+% maybe use \detokenize ... todo \lastnamedcs
+
+% \setvalue{\??mathleft  \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalleft  \nexttoken\fi}
+% \setvalue{\??mathright \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalright \nexttoken\fi}
+% \setvalue{\??mathmiddle\s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalmiddle\nexttoken\fi}
+%
+% \def\math_left
+%   {\settrue\c_math_fenced_done
+%    \edef\m_math_left{\meaning\nexttoken}%
+%    \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
+%
+% \def\math_right
+%   {\settrue\c_math_fenced_done
+%    \edef\m_math_right{\meaning\nexttoken}%
+%    \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
+%
+% \def\math_middle
+%   {\settrue\c_math_fenced_done
+%    \edef\m_math_middle{\meaning\nexttoken}%
+%    \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}
+%
+% \unexpanded\def\lfence#1%
+%   {\settrue\c_math_fenced_done
+%    \let\nexttoken#1%
+%    \edef\m_math_left{\meaning#1}%
+%    \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
+%
+% \unexpanded\def\rfence#1%
+%   {\settrue\c_math_fenced_done
+%    \let\nexttoken#1%
+%    \edef\m_math_right{\meaning#1}%
+%    \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
+%
+% \unexpanded\def\mfence#1%
+%   {\settrue\c_math_fenced_done
+%    \let\nexttoken#1%
+%    \edef\m_math_middle{\meaning#1}%
+%    \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}
+
+\unexpanded\def\installmathfencepair#1#2#3#4%
+  {\expandafter\let\csname\??mathleft \meaning#1\endcsname#2%
+   \expandafter\let\csname\??mathright\meaning#3\endcsname#4}
+
+\def\math_unknown_left  {\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalleft  \nexttoken\fi}
+\def\math_unknown_right {\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalright \nexttoken\fi}
+\def\math_unknown_middle{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalmiddle\nexttoken\fi}
+
+\letvalue{\??mathleft  \s!unknown}\math_unknown_left
+\letvalue{\??mathright \s!unknown}\math_unknown_right
+\letvalue{\??mathmiddle\s!unknown}\math_unknown_middle
 
 \def\math_left
   {\settrue\c_math_fenced_done
-   \edef\m_math_left{\meaning\nexttoken}%
-   \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
+   \ifcsname\??mathleft\meaning\nexttoken\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\math_unknown_left
+   \fi}
 
 \def\math_right
   {\settrue\c_math_fenced_done
-   \edef\m_math_right{\meaning\nexttoken}%
-   \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
+   \ifcsname\??mathright\meaning\nexttoken\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\math_unknown_right
+   \fi}
 
 \def\math_middle
   {\settrue\c_math_fenced_done
-   \edef\m_math_middle{\meaning\nexttoken}%
-   \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}
+   \ifcsname\??mathmiddle\meaning\nexttoken\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\math_unknown_middle
+   \fi}
 
 \unexpanded\def\lfence#1%
   {\settrue\c_math_fenced_done
    \let\nexttoken#1%
-   \edef\m_math_left{\meaning#1}%
-   \csname\??mathleft\ifcsname\??mathleft\m_math_left\endcsname\m_math_left\else\s!unknown\fi\endcsname}
+   \ifcsname\??mathleft\meaning\nexttoken\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\math_unknown_left
+   \fi}
 
 \unexpanded\def\rfence#1%
   {\settrue\c_math_fenced_done
    \let\nexttoken#1%
-   \edef\m_math_right{\meaning#1}%
-   \csname\??mathright\ifcsname\??mathright\m_math_right\endcsname\m_math_right\else\s!unknown\fi\endcsname}
+   \ifcsname\??mathright\meaning\nexttoken\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\math_unknown_right
+   \fi}
 
 \unexpanded\def\mfence#1%
   {\settrue\c_math_fenced_done
    \let\nexttoken#1%
-   \edef\m_math_middle{\meaning#1}%
-   \csname\??mathmiddle\ifcsname\??mathmiddle\m_math_middle\endcsname\m_math_middle\else\s!unknown\fi\endcsname}
-
-\setvalue{\??mathleft  \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalleft  \nexttoken\fi}
-\setvalue{\??mathright \s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalright \nexttoken\fi}
-\setvalue{\??mathmiddle\s!unknown}{\setfalse\c_math_fenced_done\ifconditional\c_math_fenced_unknown\normalmiddle\nexttoken\fi}
-
-\unexpanded\def\installmathfencepair#1#2#3#4%
-  {\expandafter\let\csname\??mathleft \meaning#1\endcsname#2%
-   \expandafter\let\csname\??mathright\meaning#3\endcsname#4}
+   \ifcsname\??mathmiddle\meaning\nexttoken\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\math_unknown_middle
+   \fi}
 
 \normalexpanded{\installmathfencepair {|\detokenize {|}} \Ldoublebar {|\detokenize {|}} \Rdoublebar}
 \normalexpanded{\installmathfencepair {|\detokenize{||}} \Ltriplebar {|\detokenize{||}} \Rtriplebar}
@@ -391,7 +450,7 @@
           \attribute\mathsizeattribute\numexpr\bigmathdelimitervariant*\plushundred+#1\relax
           \math_fenced_step#2\relax
         \else
-          \math_fenced_step#2{\vbox to\getvalue{\??mathbig\number#1}\bodyfontsize{}}%
+          \math_fenced_step#2{\vpack to\csname\??mathbig\number#1\endcsname\bodyfontsize{}}%
         \fi
         \nulldelimiterspace\zeropoint\relax
         \mathsurround\zeropoint
diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv
index 1e1d41534..96f55100f 100644
--- a/tex/context/base/math-ini.mkiv
+++ b/tex/context/base/math-ini.mkiv
@@ -13,6 +13,8 @@
 
 \writestatus{loading}{ConTeXt Math Macros / Initializations}
 
+% todo: hpack as we skip math anyway
+
 % Todo in luatex maincontrol.w: also accept a number here:
 %
 %    case set_math_param_cmd:
@@ -334,9 +336,11 @@
 
 \unexpanded\def\math_set_font_style_alternate#1%
   {\ifcsname\??mathstylealternate\fontclass:#1\endcsname
-     \expandafter\math_set_font_alternate\csname\??mathstylealternate\fontclass:#1\endcsname
+    %\expandafter\math_set_font_alternate\csname\??mathstylealternate\fontclass:#1\endcsname
+     \expandafter\math_set_font_alternate\lastnamedcs
    \else\ifcsname\??mathstylealternate#1\endcsname
-     \expandafter\math_set_font_alternate\csname\??mathstylealternate#1\endcsname
+    %\expandafter\math_set_font_alternate\csname\??mathstylealternate#1\endcsname
+     \expandafter\math_set_font_alternate\lastnamedcs
    \fi\fi}
 
 \unexpanded\def\setupmathrendering % the name might change
@@ -1148,12 +1152,20 @@
 
 \newcount\c_math_bidi
 
-\setvalue{\??mathbidi\v!no }{\clf_setmathdirection\zerocount\relax\c_math_bidi\attributeunsetvalue}
-\setvalue{\??mathbidi\v!yes}{\clf_setmathdirection\plusone  \relax\c_math_bidi\plusone}
+\def\math_bidi_enable {\clf_setmathdirection\plusone  \relax\c_math_bidi\plusone}
+\def\math_bidi_disable{\clf_setmathdirection\zerocount\relax\c_math_bidi\attributeunsetvalue}
+
+\letvalue{\??mathbidi\v!yes}\math_bidi_enable
+\letvalue{\??mathbidi\v!no }\math_bidi_disable
+
+% \appendtoks
+%     \edef\p_bidi{\mathematicsparameter\c!bidi}%
+%     \csname\??mathbidi\ifcsname\??mathbidi\p_bidi\endcsname\p_bidi\else\v!no\fi\endcsname
+% \to \everysetupmathematics
 
 \appendtoks
-    \edef\p_bidi{\mathematicsparameter\c!bidi}%
-    \csname\??mathbidi\ifcsname\??mathbidi\p_bidi\endcsname\p_bidi\else\v!no\fi\endcsname
+    \edef\p_bidi{\mathematicsparameter\c!bidi}% still needed ?
+    \ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi
 \to \everysetupmathematics
 
 \appendtoks
@@ -1182,14 +1194,28 @@
 \setvalue{\??mathgreek\v!normal}{2}
 \setvalue{\??mathgreek\v!italic}{3}
 
+% \appendtoks
+%     \edef\p_sygreek{\mathematicsparameter\s!sygreek}%
+%     \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}%
+%     \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}%
+%     \c_math_greek_attribute"% hex digits
+%       \csname\??mathgreek\ifcsname\??mathgreek\p_sygreek\endcsname\p_sygreek\else\v!none\fi\endcsname
+%       \csname\??mathgreek\ifcsname\??mathgreek\p_lcgreek\endcsname\p_lcgreek\else\v!none\fi\endcsname
+%       \csname\??mathgreek\ifcsname\??mathgreek\p_ucgreek\endcsname\p_ucgreek\else\v!none\fi\endcsname
+%     \relax
+%     \ifcase\c_math_greek_attribute
+%       \c_math_greek_attribute\attributeunsetvalue
+%     \fi
+% \to \everyswitchmathematics
+
 \appendtoks
-    \edef\p_sygreek{\mathematicsparameter\s!sygreek}%
-    \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}%
-    \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}%
+    \edef\p_sygreek{\mathematicsparameter\s!sygreek}% still needed ?
+    \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}% still needed ?
+    \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}% still needed ?
     \c_math_greek_attribute"% hex digits
-      \csname\??mathgreek\ifcsname\??mathgreek\p_sygreek\endcsname\p_sygreek\else\v!none\fi\endcsname
-      \csname\??mathgreek\ifcsname\??mathgreek\p_lcgreek\endcsname\p_lcgreek\else\v!none\fi\endcsname
-      \csname\??mathgreek\ifcsname\??mathgreek\p_ucgreek\endcsname\p_ucgreek\else\v!none\fi\endcsname
+      \ifcsname\??mathgreek\p_sygreek\endcsname\lastnamedcs\else1\fi
+      \ifcsname\??mathgreek\p_lcgreek\endcsname\lastnamedcs\else1\fi
+      \ifcsname\??mathgreek\p_ucgreek\endcsname\lastnamedcs\else1\fi
     \relax
     \ifcase\c_math_greek_attribute
       \c_math_greek_attribute\attributeunsetvalue
@@ -1236,11 +1262,19 @@
      \global\let\math_italics_initialize\relax
    \fi}
 
+% \appendtoks
+%     \edef\p_italics{\mathematicsparameter\s!italics}%
+%     \c_math_italics_attribute\csname\??mathitalics
+%         \ifcsname\??mathitalics\p_italics\endcsname\p_italics\else\v!none\fi
+%     \endcsname\relax
+%   % \math_italics_initialize
+% \to \everyswitchmathematics % only in mathematics
+
 \appendtoks
     \edef\p_italics{\mathematicsparameter\s!italics}%
-    \c_math_italics_attribute\csname\??mathitalics
-        \ifcsname\??mathitalics\p_italics\endcsname\p_italics\else\v!none\fi
-    \endcsname\relax
+    \c_math_italics_attribute
+        \ifcsname\??mathitalics\p_italics\endcsname\lastnamedcs\else\attributeunsetvalue\fi
+    \relax
   % \math_italics_initialize
 \to \everyswitchmathematics % only in mathematics
 
@@ -1936,48 +1970,47 @@
    \expandafter\let\csname\??mathstyle#1\normalexpanded{\endcsname\math_style_add_to_cache_choice}}
 
 % \def\math_style_set_indeed
-%   {\ifcsname\??mathstyle\m_math_style_asked\endcsname
-%      \csname\??mathstyle\m_math_style_asked\endcsname
-%    \else
-%      \math_style_set_indeed_cached
-%    \fi}
+%   {\csname\??mathstyle
+%      \ifcsname\??mathstyle\m_math_style_asked\endcsname
+%        \m_math_style_asked
+%      \else
+%        \??mathstyle
+%      \fi
+%    \endcsname}
 %
-% \def\math_style_set_indeed_cached
-%   {\ifcsname\??mathstylecache\m_math_style_asked\endcsname
-%      % already in cache
-%    \else
-%      \math_style_add_to_cache
-%    \fi
-%    \csname\??mathstylecache\m_math_style_asked\endcsname}
+% \setvalue{\??mathstyle\??mathstyle}%
+%   {\csname\??mathstylecache
+%      \ifcsname\??mathstylecache\m_math_style_asked\endcsname
+%        \m_math_style_asked
+%      \else
+%        \??mathstylecache
+%      \fi
+%    \endcsname}
 %
-% \def\math_style_add_to_cache
+% \setvalue{\??mathstylecache\??mathstylecache}%
 %   {\c_math_styles_state_style  \zerocount
 %    \c_math_styles_state_cramped\zerocount
 %    \c_math_styles_state_size   \zerocount
 %    \rawprocesscommacommand[\m_math_style_asked]\math_style_collect
-%    \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}}
-%
-% ugly but more efficient (as called often)
+%    \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
+%    \csname\??mathstylecache\m_math_style_asked\endcsname}
 
 \def\math_style_set_indeed
-  {\csname\??mathstyle
-     \ifcsname\??mathstyle\m_math_style_asked\endcsname
-       \m_math_style_asked
-     \else
-       \??mathstyle
-     \fi
-   \endcsname}
+  {\ifcsname\??mathstyle\m_math_style_asked\endcsname
+     \lastnamedcs
+   \else
+     \math_style_set_mathstyle_mathstyle
+   \fi}
 
-\setvalue{\??mathstyle\??mathstyle}%
-  {\csname\??mathstylecache
-     \ifcsname\??mathstylecache\m_math_style_asked\endcsname
-       \m_math_style_asked
-     \else
-       \??mathstylecache
-     \fi
-   \endcsname}
+\def\math_style_set_mathstyle_mathstyle
+  {\ifcsname\??mathstylecache\m_math_style_asked\endcsname
+     \lastnamedcs
+   \else
+     \math_style_set_mathstyle_mathstylecache
+     \??mathstylecache
+   \fi}
 
-\setvalue{\??mathstylecache\??mathstylecache}%
+\def\math_style_set_mathstyle_mathstylecache
   {\c_math_styles_state_style  \zerocount
    \c_math_styles_state_cramped\zerocount
    \c_math_styles_state_size   \zerocount
@@ -1985,6 +2018,9 @@
    \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
    \csname\??mathstylecache\m_math_style_asked\endcsname}
 
+\letvalue{\??mathstyle     \??mathstyle     }\math_style_set_mathstyle_mathstyle      % still needed?
+\letvalue{\??mathstylecache\??mathstylecache}\math_style_set_mathstyle_mathstylecache % still needed?
+
 %D \startbuffer
 %D $x\begingroup\setupmathstyle[script]x\endgroup x$
 %D $x{\setupmathstyle[script]x}x$
@@ -2021,40 +2057,44 @@
 %D version is a variation on the one in the math module (see \type{m-math} and|/|or
 %D \type {m-newmat}).
 
-\unexpanded\def\mathtext
-  {\mathortext\math_text_choice\hbox}
+\let\m_math_text_choice_face\relax
 
-% \def\math_text_choice#1%
-%   {\mathchoice
-%      {\math_text_choice_indeed\displaystyle\textface        {#1}}%
-%      {\math_text_choice_indeed\textstyle   \textface        {#1}}%
-%      {\math_text_choice_indeed\textstyle   \scriptface      {#1}}%
-%      {\math_text_choice_indeed\textstyle   \scriptscriptface{#1}}}
-%
-% \def\math_text_choice_indeed#1#2#3% no \everymath !
-%   {\hbox{\everymath{#1}\switchtobodyfont[#2]#3}} % 15 sec
-
-% \let\m_math_text_choice_style\relax
-%
-% \def\math_text_choice#1%
-%   {\edef\m_math_text_choice_style{\normalmathstyle}%
-%    \hbox\bgroup
-%    % \everymath{\triggermathstyle\m_math_text_choice_style}%
-%      \normalizebodyfontsize\m_math_text_choice_style{\mathstylefont\m_math_text_choice_style}%
-%      \font_basics_switchtobodyfont\m_math_text_choice_style
-%      #1%
-%    \egroup}
-
-\let\m_math_text_choice_face \relax
+% if needed we can get rid of the normalize (predo in font code)
 
-% \def\math_text_choice#1% if needed we can get rid of the normalize (predo in font code)
-%   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
-%    \hbox{\font_basics_switchtobodyfont\m_math_text_choice_face#1}}
+\def\math_text_choice_font#1%
+  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
+   \hbox\bgroup
+   \font_basics_switchtobodyfont\m_math_text_choice_face
+   #1%
+   \let\next}
 
-\def\math_text_choice% if needed we can get rid of the normalize (predo in font code)
+\def\math_text_choice_word#1%
   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
-  %\showmathstyle
-   \hbox\bgroup\font_basics_switchtobodyfont\m_math_text_choice_face\let\next}
+   \hbox\bgroup
+   \font_basics_switchtobodyfont\m_math_text_choice_face
+   #1%
+   \nospacing % \normalnospaces\plusone
+   \let\next}
+
+% \ruledhbox{$\mathtext{abc ffi}$}
+% \ruledhbox{$\mathword{abc ffi}$}
+
+\unexpanded\def\mathtext  {\mathortext{\math_text_choice_font\relax}\hbox}
+\unexpanded\def\mathword  {\mathortext{\math_text_choice_word\relax}\hbox}
+
+\unexpanded\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox}
+\unexpanded\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox}
+\unexpanded\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox}
+\unexpanded\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox}
+\unexpanded\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox}
+\unexpanded\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox}
+
+\unexpanded\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox}
+\unexpanded\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox}
+\unexpanded\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox}
+\unexpanded\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox}
+\unexpanded\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox}
+\unexpanded\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox}
 
 %D Safeguard against redefinitions:
 
diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua
index 85759ddf1..2c988077b 100644
--- a/tex/context/base/math-noa.lua
+++ b/tex/context/base/math-noa.lua
@@ -228,12 +228,13 @@ local function process(start,what,n,parent)
                  -- report_processing("stop processing")
                 end
             end
-        elseif id == math_char or id == math_textchar or id == math_delim then
-            break
         elseif id == math_noad then
+            -- single characters are like this
             local noad = getfield(start,"nucleus")      if noad then process(noad,what,n,start) end -- list
                   noad = getfield(start,"sup")          if noad then process(noad,what,n,start) end -- list
                   noad = getfield(start,"sub")          if noad then process(noad,what,n,start) end -- list
+        elseif id == math_char or id == math_textchar or id == math_delim then
+            break
         elseif id == math_box or id == math_sub then
             local noad = getfield(start,"list")         if noad then process(noad,what,n,start) end -- list (not getlist !)
         elseif id == math_fraction then
diff --git a/tex/context/base/math-rad.mkvi b/tex/context/base/math-rad.mkvi
index 23e056c1f..113d4af50 100644
--- a/tex/context/base/math-rad.mkvi
+++ b/tex/context/base/math-rad.mkvi
@@ -182,7 +182,7 @@
    %
    \edef\p_mp{\mathradicalparameter\c!mp}%
    %
-   \setbox\scratchbox\hbox\bgroup % todo: tag this box as sqrt
+   \setbox\scratchbox\hpack\bgroup % todo: tag this box as sqrt
      \uniqueMPgraphic
        {\p_mp}%
       %{...}%
@@ -190,7 +190,7 @@
    \scratchdimen       \wd\scratchbox
    \scratchtopoffset   \dimexpr\scratchoffset+\dp\nextbox\relax
    \scratchbottomoffset\dimexpr\scratchoffset+\ht\nextbox/2\relax
-   \hbox to \scratchdimen{\hss\box\nextbox\hskip\scratchoffset}%
+   \hpack to \scratchdimen{\hss\box\nextbox\hskip\scratchoffset}%
    \hskip-\scratchdimen
    \lower\dimexpr\scratchtopoffset\box\scratchbox%
    \ifx\currentmathradicaldegree\empty \else
@@ -241,11 +241,11 @@
    \edef\overlaylinecolor{\mathornamentparameter\c!color}%
    \edef\p_mp{\mathornamentparameter\c!mp}%
    % thw width of the graphic determines the width of the final result
-   \setbox\scratchbox\hbox{\uniqueMPgraphic{\p_mp}}% todo: add code key + tag
+   \setbox\scratchbox\hpack{\uniqueMPgraphic{\p_mp}}% todo: add code key + tag
    \scratchdimen       \wd\scratchbox
  % \scratchtopoffset   \dimexpr\scratchoffset+\dp\nextbox\relax
  % \scratchbottomoffset\dimexpr\scratchoffset+\ht\nextbox/2\relax
-   \hbox to \scratchdimen{\hss\box\nextbox\hss}%
+   \hpack to \scratchdimen{\hss\box\nextbox\hss}%
    \hskip-\scratchdimen
    \box\scratchbox
    \endgroup}
diff --git a/tex/context/base/math-tag.lua b/tex/context/base/math-tag.lua
index 82bc2171c..e83b401fb 100644
--- a/tex/context/base/math-tag.lua
+++ b/tex/context/base/math-tag.lua
@@ -528,8 +528,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
                     processsubsup(start)
                 end
             elseif id == glue_code then
-             -- local spec = getfield(start,"spec")
-             -- setattr(start,a_tagged,start_tagged("mspace",{ width = getfield(spec,"width") }))
+             -- setattr(start,a_tagged,start_tagged("mspace",{ width = getfield(start,"width") }))
                 setattr(start,a_tagged,start_tagged("mspace"))
                 stop_tagged()
             else
diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv
index dd8c9cdfa..6e1a8c231 100644
--- a/tex/context/base/meta-ini.mkiv
+++ b/tex/context/base/meta-ini.mkiv
@@ -284,7 +284,7 @@
    \endgroup}
 
 \def\meta_process_graphic_start
-  {\setbox\b_meta_graphic\hbox\bgroup}
+  {\setbox\b_meta_graphic\hpack\bgroup}
 
 \def\meta_process_graphic_stop
   {\egroup
@@ -369,7 +369,8 @@
 
 \def\includeMPgraphic#1% gets expanded !
   {\ifcsname\??mpgraphic#1\endcsname
-     \doubleexpandafter\fourthoffourarguments\csname\??mpgraphic#1\endcsname ; % ; is safeguard
+    %\doubleexpandafter\fourthoffourarguments\csname\??mpgraphic#1\endcsname ; % ; is safeguard
+     \doubleexpandafter\fourthoffourarguments\lastnamedcs ; % ; is safeguard
    \fi}
 
 \let\meta_enable_include\relax
@@ -540,10 +541,12 @@
    \fi}
 
 \def\MPrawvar#1#2% no checking
-  {\csname\??graphicvariable#1:#2\endcsname}
+ %{\csname\??graphicvariable#1:#2\endcsname}
+  {\begincsname\??graphicvariable#1:#2\endcsname}
 
 \def\MPvariable#1% todo: could be a framed chain
-  {\csname\??graphicvariable\currentmpvariableclass:#1\endcsname}
+ %{\csname\??graphicvariable\currentmpvariableclass:#1\endcsname}
+  {\begincsname\??graphicvariable\currentmpvariableclass:#1\endcsname}
 
 \unexpanded\def\useMPvariables
   {\dodoubleargument\meta_use_variables}
@@ -607,7 +610,7 @@
    \doifelsecolor \ascii                              % with 2\bodyfontsize
      {\meta_prepare_variable_color}
      {\begingroup
-      \setbox\b_meta_variable_box\hbox{\scratchdimen\m_meta_current_variable sp}%
+      \setbox\b_meta_variable_box\hpack{\scratchdimen\m_meta_current_variable sp}%
       \ifzeropt\wd\b_meta_variable_box
         \endgroup\meta_prepare_variable_number
       \else
@@ -665,7 +668,7 @@
 % hm, isn't this already done elsewhere?
 
 \unexpanded\def\meta_obey_box_depth
-  {\setbox\b_meta_graphic\hbox\bgroup
+  {\setbox\b_meta_graphic\hpack\bgroup
      \raise\MPlly\box\b_meta_graphic
    \egroup}
 
@@ -677,7 +680,7 @@
       \dp\b_meta_graphic\the\dp\b_meta_graphic}}
 
 \unexpanded\def\meta_obey_box_origin
-  {\setbox\b_meta_graphic\hbox\bgroup
+  {\setbox\b_meta_graphic\hpack\bgroup
      \kern\MPllx\raise\MPlly\box\b_meta_graphic
    \egroup}
 
@@ -694,10 +697,13 @@
 
 \unexpanded\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens
   {\MPllx#2\MPlly#3\MPurx#4\MPury#5%
-   \hbox{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent
+   \hpack{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent
+
+% \unexpanded\def\meta_use_box
+%   {\setobject{MP}}
 
 \unexpanded\def\meta_use_box
-  {\setobject{MP}}
+  {\setunreferencedobject{MP}}
 
 \def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although,
   {\begingroup                  % when there are that many they're probably not that unique anyway
@@ -706,10 +712,10 @@
    \ifcsname\??mpgraphic\overlaystamp:#1\endcsname\else
      \meta_enable_include % redundant
      \global\advance\c_meta_object_counter\plusone
-     \meta_use_box{\number\c_meta_object_counter}\hbox{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
+     \meta_use_box{\number\c_meta_object_counter}\hpack{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
      \setxvalue{\??mpgraphic\overlaystamp:#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}%
    \fi
-   \getvalue{\??mpgraphic\overlaystamp:#1}%
+   \csname\??mpgraphic\overlaystamp:#1\endcsname\empty
    \endgroup}
 
 \unexpanded\def\startuniqueMPgraphic
@@ -733,7 +739,7 @@
   {\meta_begin_graphic_group{#1}%
 %    \setupMPvariables[\currentMPgraphicname][#2]%
    \setupMPvariables[#1][#2]%
-   \getvalue{\??mpgraphic#1}\empty
+   \csname\??mpgraphic#1\endcsname\empty
    \meta_end_graphic_group}
 
 \def\meta_handle_use_graphic#1#2#3%
@@ -793,9 +799,9 @@
    \fi
    \meta_enable_include % redundant
    \global\advance\c_meta_object_counter\plusone
-   \meta_use_box{\number\c_meta_object_counter}\hbox{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
+   \meta_use_box{\number\c_meta_object_counter}\hpack{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
    \setxvalue{\??mpgraphic#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}%
-   \getvalue{\??mpgraphic#1}%
+   \csname\??mpgraphic#1\endcsname\empty
    \endgroup}
 
 \unexpanded\def\startreusableMPgraphic
@@ -819,7 +825,7 @@
   {\meta_begin_graphic_group{#1}%
 %    \doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}%
    \doifsomething{#2}{\setupMPvariables[#1][#2]}%
-   \getvalue{\??mpgraphic#1}\empty
+   \csname\??mpgraphic#1\endcsname\empty
    \meta_end_graphic_group}
 
 \let\reuseMPgraphic   \useMPgraphic   % we can save a setup here if needed
@@ -869,7 +875,7 @@
    \let\overlaystamp\overlaypagestamp
 %    \setupMPvariables[\m_meta_page_prefix:\currentMPgraphicname][#2]% prefix is new here
    \setupMPvariables[\m_meta_page_prefix:#1][#2]% prefix is new here
-   \getvalue{\??mpgraphic\m_meta_page_prefix:#1}{}%
+   \csname\??mpgraphic\m_meta_page_prefix:#1\endcsname\empty
    \meta_end_graphic_group}
 
 %D One way of defining a stamp is:
@@ -1489,7 +1495,7 @@
 
 \unexpanded\def\startMPcalculation
   {\begingroup
-   \setbox\nextbox\hbox\bgroup
+   \setbox\nextbox\hpack\bgroup
    \dosinglegroupempty\meta_start_calculation}
 
 \def\meta_start_calculation
diff --git a/tex/context/base/meta-pdf.mkiv b/tex/context/base/meta-pdf.mkiv
index 50eb1dd72..14c97042e 100644
--- a/tex/context/base/meta-pdf.mkiv
+++ b/tex/context/base/meta-pdf.mkiv
@@ -39,13 +39,13 @@
 
 \unexpanded\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 are ignored)
   {\dostarttagged\t!mpgraphic\empty
-   \naturalvbox attr \imageattribute 1 \bgroup
+   \naturalvpack attr \imageattribute 1 \bgroup
      \message{[MP to PDF]}%
      \xdef\MPfilename{#1}%
      \resetMPboundingbox
      \forgetall
      \offinterlineskip
-     \setbox\MPbox\vbox\bgroup
+     \setbox\MPbox\vpack\bgroup
        \clf_convertmpstopdf{\MPfilename}%
        \removeunwantedspaces % not that needed
      \egroup
diff --git a/tex/context/base/meta-pdh.mkiv b/tex/context/base/meta-pdh.mkiv
index c49613d36..3787a5638 100644
--- a/tex/context/base/meta-pdh.mkiv
+++ b/tex/context/base/meta-pdh.mkiv
@@ -106,10 +106,10 @@
 
 \def\convertMPtoPDF#1#2#3% watch the transparency reset
   {\resetMPvariables{#1}{#2}{#3}%
-   \vbox\bgroup
+   \vpack\bgroup
      \forgetall
      \offinterlineskip
-     \setbox\scratchbox\vbox\bgroup
+     \setbox\scratchbox\vpack\bgroup
         \setnormalcatcodes % we can be in verbatim or so
         \message{[MP to PDF]}%
         \startMPresources
@@ -120,12 +120,12 @@
         \pdfliteral{\letterpercent\space mps end}%
         \stopMPresources
      \egroup
-     \setbox\scratchbox\hbox\bgroup
+     \setbox\scratchbox\hpack\bgroup
         \hskip-\MPllx\onebasepoint
         \raise-\MPlly\onebasepoint
         \box\scratchbox
      \egroup
-     \setbox\scratchbox\vbox to \MPheight\bgroup
+     \setbox\scratchbox\vpack to \MPheight\bgroup
        \vfill
        \hsize\MPwidth
        \smashbox\scratchbox
@@ -154,13 +154,13 @@
    \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}%
+       \setbox#1\vpack spread 2\scratchdimen
+         {\forgetall\vss\hpack 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}%
+       \vpack to \MPheight
+         {\forgetall\vss\hpack to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
      \else
        \getMPPDFobject
      \fi
@@ -669,12 +669,12 @@
    \defconvertedcommand\MPtextdata\MPtextdata % no edef
    \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
    \executeifdefined{handleMPtext\MPtexttag}
-     {\setbox\scratchbox\hbox
+     {\setbox\scratchbox\hbox % text
         {\font\temp=#1\space at #2\onebasepoint
          \let\c\char
          \temp
          \MPfshowcommand{#3}}%
-      \setbox\scratchbox\hbox
+      \setbox\scratchbox\hpack
         {\hskip#4\onebasepoint
          \raise#5\onebasepoint
          \box\scratchbox}%
diff --git a/tex/context/base/meta-tex.mkiv b/tex/context/base/meta-tex.mkiv
index 9548afea1..35b5c133b 100644
--- a/tex/context/base/meta-tex.mkiv
+++ b/tex/context/base/meta-tex.mkiv
@@ -44,7 +44,7 @@
 \def\getTeXtext#1%
   {\getvalue{\??graphictextext#1}}
 
-\setvalue{\??graphictexdepth d}{\setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}}  % unchecked
+\setvalue{\??graphictexdepth d}{\setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}}  % unchecked
 \letvalue{\??graphictexdepth n}\donothing                                             % unchecked
 
 \setvalue{\??graphictexdepth\s!depth  }{\getvalue{\??graphictexdepth d}}
diff --git a/tex/context/base/mlib-pdf.mkiv b/tex/context/base/mlib-pdf.mkiv
index 92bf86ea9..78dab716d 100644
--- a/tex/context/base/mlib-pdf.mkiv
+++ b/tex/context/base/mlib-pdf.mkiv
@@ -48,7 +48,7 @@
    \global\MPury   \zeropoint}
 
 \def\repositionMPboxindeed
-  {\setbox\MPbox\hbox\bgroup
+  {\setbox\MPbox\hpack\bgroup
      \kern-\MPllx
      \raise-\MPlly
      \box\MPbox
@@ -67,7 +67,7 @@
 
 \def\finalizeMPbox
   {\repositionMPbox
-   \setbox\MPbox\vbox to \MPheight\bgroup
+   \setbox\MPbox\vpack to \MPheight\bgroup
      \vfill
      \hsize\MPwidth
      \smashbox\MPbox
@@ -78,7 +78,7 @@
 
 \def\MPtextext#1#2#3#4#5% beware: we use a different method now (see mlib-pps)
   {\begingroup
-   \setbox\MPbox\hbox{\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}%
+   \setbox\MPbox\hbox{\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}% text
    \MPllx-#4\onebasepoint
    \MPlly-#5\onebasepoint
    \repositionMPbox
@@ -96,7 +96,7 @@
    \naturalhbox attr \imageattribute 1 \bgroup
    \dousecolorparameter\s!black\forcecolorhack
    \setMPboundingbox{#1}{#2}{#3}{#4}%
-   \setbox\MPbox\vbox\bgroup
+   \setbox\MPbox\vpack\bgroup
  % \forgetall % already done elsewhere
    \noindent} % forces the proper cm in the backend
 
diff --git a/tex/context/base/mlib-pps.mkiv b/tex/context/base/mlib-pps.mkiv
index 269e000d5..cdccfc379 100644
--- a/tex/context/base/mlib-pps.mkiv
+++ b/tex/context/base/mlib-pps.mkiv
@@ -42,14 +42,14 @@
 
 \unexpanded\def\MPLIBsetNtext#1% #2% box text
   {\MPLIBflushenvironment
-   \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup
+   \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup % text
      \meta_set_current_color
      \let\MPLIBflushenvironment\doMPLIBflushenvironment
      \let\next} % gobble open brace
 
 \unexpanded\def\MPLIBsetCtext#1#2% #3% box colorspec text
   {\MPLIBflushenvironment
-   \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup
+   \dowithnextbox{\clf_mpsettext\nextbox #1}\hbox\bgroup % text
      \directcolored[#2]%
      \meta_set_current_color % so, textcolor wins !
      \let\MPLIBflushenvironment\doMPLIBflushenvironment
@@ -59,22 +59,22 @@
 
 \unexpanded\def\MPLIBgettextscaled#1#2#3%  why a copy .. can be used more often
   {\clf_mpgettext\MPtextbox #1%
-   \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}}
+   \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}}
 
 \unexpanded\def\MPLIBfigure#1#2%
-  {\setbox\scratchbox\hbox{\externalfigure[#1][\c!mask=#2]}%
+  {\setbox\scratchbox\hpack{\externalfigure[#1][\c!mask=#2]}%
    \clf_mpsetsxsy\wd\scratchbox\ht\scratchbox\zeropoint
-   \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}}
+   \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}}
 
 % horrible (we could inline scale and matrix code):
 
 \unexpanded\def\MPLIBgettextscaledcm#1#2#3#4#5#6#7#8#9% 2-7: sx,rx,ry,sy,tx,ty
   {\clf_mpgettext\MPtextbox #1%
-   \setbox\MPbox\hbox\bgroup
+   \setbox\MPbox\hpack\bgroup
      \dotransformnextbox{#2}{#3}{#4}{#5}{#6}{#7}% does push pop ... will be changed to proper lua call (avoid small numbers)
-       \vbox to \zeropoint\bgroup
+       \vpack to \zeropoint\bgroup
           \vss
-          \hbox to \zeropoint \bgroup
+          \hpack to \zeropoint \bgroup
            % \scale[\c!sx=#8,\c!sy=#9]{\raise\dp\MPtextbox\box\MPtextbox}%
            % \scale[\c!sx=#8,\c!sy=#9,\c!depth=\v!no]{\box\MPtextbox}%
              \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}%
@@ -130,7 +130,7 @@
 
 \def\doMPLIBstopgroup#1#2#3#4#5#6% some day this might happen elsewhere
   {\egroup
-   \setbox\scratchbox\hbox{\kern\onebasepoint\box\scratchbox}% weird correction
+   \setbox\scratchbox\hpack{\kern\onebasepoint\box\scratchbox}% weird correction
    \wd\scratchbox \dimexpr#5\onebasepoint-#3\onebasepoint+2\onebasepoint\relax
    \ht\scratchbox #6\onebasepoint
    \dp\scratchbox-#4\onebasepoint
@@ -139,7 +139,7 @@
      resources {\pdfbackendcurrentresources}
      \scratchbox
  % \setbox\scratchbox\hbox\bgroup\kern-\onebasepoint\useboxresource\lastsavedboxresourceindex\egroup % why twice?
-   \setbox\scratchbox\hbox\bgroup\kern-\onebasepoint\useboxresource\lastsavedboxresourceindex\egroup
+   \setbox\scratchbox\hpack\bgroup\kern-\onebasepoint\useboxresource\lastsavedboxresourceindex\egroup
    \wd\scratchbox\zeropoint
    \ht\scratchbox\zeropoint
    \dp\scratchbox\zeropoint
@@ -148,7 +148,7 @@
 
 \unexpanded\def\MPLIBstartgroup#1#2#3#4#5#6% isolated 0/1, knockout 0/1 llx lly urx ury
   {\begingroup
-   \setbox\scratchbox\hbox\bgroup
+   \setbox\scratchbox\hpack\bgroup
    \unexpanded\def\MPLIBstopgroup{\doMPLIBstopgroup{#1}{#2}{#3}{#4}{#5}{#6}}}
 
 \protect \endinput
diff --git a/tex/context/base/mult-aux.mkiv b/tex/context/base/mult-aux.mkiv
index b69d7f370..693edc90e 100644
--- a/tex/context/base/mult-aux.mkiv
+++ b/tex/context/base/mult-aux.mkiv
@@ -29,6 +29,8 @@
 
 \unprotect
 
+\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % cancel: dec:24 hex:18
+
 %D \starttyping
 %D \unprotect
 %D     \def\????aa{@@@@aa}
@@ -215,13 +217,15 @@
   %\def#3##1{\csname#4{#1#2}{##1}\endcsname}%
    \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
    \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
-   \def#5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+  %\def#5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+   \def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
    \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
    \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
  % \def#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version
  % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
-   \def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
-   \def#9##1{\csname#1#2:##1\endcsname}}
+%% \def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
+   \def#8##1{\begincsname#1#2:##1\endcsname}%
+   \def#9##1{\csname#1#2:##1\endcsname}} % can go when we use \begincsname
 
 % pre-expansion can be a bit faster but handly any effect on a normal run so let's go for
 % saving some memory
@@ -254,7 +258,9 @@
 
 \unexpanded\def\mult_interfaces_install_root_parameter_handler#1#2#3%
   {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
-   \def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\s!empty\fi\endcsname}}
+  %\def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\s!empty\fi\endcsname}}
+  %\def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\??empty\fi\endcsname}}
+   \def#3##1{\begincsname#1:##1\endcsname}}
 
 \unexpanded\def\installrootparameterhandler#1#2%
   {\normalexpanded
@@ -355,10 +361,13 @@
      \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
    \fi \fi}
 
-\def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi}
-\def\getparentchain       #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
-\def\getcurrentparentchain#1#2{\csname#1#2:\s!chain\endcsname} % for the moment test:
-\def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+%def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi}
+%def\getparentchain       #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+%def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+
+\def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi}
+\def\getparentchain       #1#2{\begincsname#1#2:\s!chain\endcsname}
+\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname}
 
 \unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones
   {\ifx#4\relax\let#4\empty\fi                                          % see \defineregister
@@ -610,7 +619,8 @@
 %D We don't need colons for such simple cases.
 
 \unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
-  {\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
+%%{\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
+  {\def#3##1{\begincsname#1##1\endcsname}%
    \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
  % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
    \def#5##1{\csname#1##1\endcsname}}
@@ -802,7 +812,8 @@
 
 \letvalue\??dummy\empty
 
-           \def\dummyparameter      #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname}
+%%         \def\dummyparameter      #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname}
+           \def\dummyparameter      #1{\begincsname\??dummy#1\endcsname}
            \def\directdummyparameter#1{\csname\??dummy#1\endcsname}
 \unexpanded\def\setdummyparameter   #1{\expandafter\def\csname\??dummy#1\endcsname}
 \unexpanded\def\letdummyparameter   #1{\expandafter\let\csname\??dummy#1\endcsname}
@@ -883,10 +894,17 @@
 \unexpanded\def\showparentchain#1#2%
   {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}
 
+% \def\mult_interfaces_show_parent_chain#1%
+%   {#1 => %
+%    \ifcsname#1:\s!parent\endcsname
+%       \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
+%    \fi}
+
 \def\mult_interfaces_show_parent_chain#1%
   {#1 => %
    \ifcsname#1:\s!parent\endcsname
-      \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
+     %\expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
+      \expandafter\mult_interfaces_show_parent_chain\lastnamedcs
    \fi}
 
 %D Another helper (needs to be applied):
@@ -991,7 +1009,7 @@
    \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
    \newtoks#4%
    \newtoks#7%
-   \edef\m_mult_interface_setup{\strippedcsname#2_}%
+   \edef\m_mult_interface_setup{\csstring#2_}%
    \unexpanded\edef#2{\syst_helpers_double_empty
      \csname\m_mult_interface_setup\s!simple\endcsname
      \csname\m_mult_interface_setup\s!single\endcsname
@@ -1081,7 +1099,7 @@
   {\ifx#3\relax\let#3\empty\fi
    \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}%
    \newtoks#4%
-   \edef\m_mult_interface_setup{\strippedcsname#2_}%
+   \edef\m_mult_interface_setup{\csstring#2_}%
    \unexpanded\edef#2{\syst_helpers_triple_empty
      \csname\m_mult_interface_setup\s!simple\endcsname
      \csname\m_mult_interface_setup\s!single\endcsname
diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv
index 8e51eb03e..30252f34a 100644
--- a/tex/context/base/mult-def.mkiv
+++ b/tex/context/base/mult-def.mkiv
@@ -24,8 +24,11 @@
 \setvalue{\??multilingual  persian}{pe}
 \setvalue{\??multilingual romanian}{ro}
 
-\def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\csname\??multilingual\currentinterface\endcsname\else en\fi}
-\def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\csname\??multilingual\currentresponses\endcsname\else en\fi}
+% \def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\csname\??multilingual\currentinterface\endcsname\else en\fi}
+% \def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\csname\??multilingual\currentresponses\endcsname\else en\fi}
+
+\def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\lastnamedcs\else en\fi}
+\def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\lastnamedcs\else en\fi}
 
 % \input mult-\userinterfacetag  \relax
 % \input mult-m\userresponsestag \relax
diff --git a/tex/context/base/mult-dim.mkvi b/tex/context/base/mult-dim.mkvi
index cf4b1f4c8..6e2b22038 100644
--- a/tex/context/base/mult-dim.mkvi
+++ b/tex/context/base/mult-dim.mkvi
@@ -36,6 +36,8 @@
 
 \installcorenamespace{dimensionnormal}
 
+\def\assign_dimension_direct#value#dimension#small#medium#big{#dimension=#value\relax}
+
 \setvalue{\??dimensionnormal \v!none  }#value#dimension#small#medium#big{#dimension\zeropoint}
 \setvalue{\??dimensionnormal \empty   }#value#dimension#small#medium#big{#dimension\zeropoint}
 \setvalue{\??dimensionnormal \v!small }#value#dimension#small#medium#big{#dimension=#small\relax}
@@ -44,10 +46,17 @@
 \setvalue{\??dimensionnormal-\v!small }#value#dimension#small#medium#big{#dimension=-#small\relax}
 \setvalue{\??dimensionnormal-\v!medium}#value#dimension#small#medium#big{#dimension=-#medium\relax}
 \setvalue{\??dimensionnormal-\v!big   }#value#dimension#small#medium#big{#dimension=-#big\relax}
-\setvalue{\??dimensionnormal\s!unknown}#value#dimension#small#medium#big{#dimension=#value\relax}
+\letvalue{\??dimensionnormal\s!unknown}\assign_dimension_direct
+
+% \unexpanded\def\assigndimension#value%
+%   {\csname\??dimensionnormal\ifcsname\??dimensionnormal#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
 
 \unexpanded\def\assigndimension#value%
-  {\csname\??dimensionnormal\ifcsname\??dimensionnormal#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+  {\ifcsname\??dimensionnormal#value\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\assign_dimension_direct
+   \fi{#value}}
 
 %D The next variant assigns to a macro instead of a dimension.
 %D
@@ -64,14 +73,24 @@
 
 \installcorenamespace{dimensionalfa}
 
+\def\assign_alpha_dimension_direct#value#macro#small#medium#big{\edef#macro{#value}}
+
 \setvalue{\??dimensionalfa\v!none   }#value#macro#small#medium#big{\let #macro\!!zerocount}
 \setvalue{\??dimensionalfa\v!small  }#value#macro#small#medium#big{\edef#macro{#small}}
 \setvalue{\??dimensionalfa\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}}
 \setvalue{\??dimensionalfa\v!big    }#value#macro#small#medium#big{\edef#macro{#big}}
-\setvalue{\??dimensionalfa\s!unknown}#value#macro#small#medium#big{\edef#macro{#value}}
+\letvalue{\??dimensionalfa\s!unknown}\assign_alpha_dimension_direct
+
+% \unexpanded\def\assignalfadimension#value%
+%   {\csname\??dimensionalfa\ifcsname\??dimensionalfa#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
 
 \unexpanded\def\assignalfadimension#value%
-  {\csname\??dimensionalfa\ifcsname\??dimensionalfa#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+  {\ifcsname\??dimensionalfa#value\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\assign_alpha_dimension_direct
+   \fi
+   {#value}}
 
 %D \macros
 %D   {assignvalue}
@@ -89,13 +108,22 @@
 
 \installcorenamespace{dimensionvalue}
 
+\def\assign_value_direct#value#macro#small#medium#big{\edef#macro{#value}}
+
 \setvalue{\??dimensionvalue\v!small  }#value#macro#small#medium#big{\edef#macro{#small}}
 \setvalue{\??dimensionvalue\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}}
 \setvalue{\??dimensionvalue\v!big    }#value#macro#small#medium#big{\edef#macro{#big}}
-\setvalue{\??dimensionvalue\s!unknown}#value#macro#small#medium#big{\edef#macro{#value}}
+\letvalue{\??dimensionvalue\s!unknown}\assign_value_direct
+
+% \unexpanded\def\assignvalue#value%
+%   {\csname\??dimensionvalue\ifcsname\??dimensionvalue#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
 
 \unexpanded\def\assignvalue#value%
-  {\csname\??dimensionvalue\ifcsname\??dimensionvalue#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+  {\ifcsname\??dimensionvalue#value\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\assign_value_direct
+  \fi{#value}}
 
 %D \macros
 %D   {assignwidth}
@@ -115,15 +143,24 @@
 
 \newbox\b_assign_width
 
+\def\assign_width_direct#value#dimension#content#extra{#dimension=#value\relax}
+
 \setvalue{\??dimensionwidth          }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width
                                                                      \setbox\b_assign_width\emptybox}
 \setvalue{\??dimensionwidth\v!fit    }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width
                                                                      \setbox\b_assign_width\emptybox}
 \setvalue{\??dimensionwidth\v!broad  }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\dimexpr\wd\b_assign_width+#extra\relax
                                                                      \setbox\b_assign_width\emptybox}
-\setvalue{\??dimensionwidth\s!unknown}#value#dimension#content#extra{#dimension=#value\relax}
+\letvalue{\??dimensionwidth\s!unknown}\assign_width_direct
+
+% \unexpanded\def\assignwidth#value%
+%   {\csname\??dimensionwidth\ifcsname\??dimensionwidth#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
 
 \unexpanded\def\assignwidth#value%
-  {\csname\??dimensionwidth\ifcsname\??dimensionwidth#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+  {\ifcsname\??dimensionwidth#value\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\assign_width_direct
+   \fi{#value}}
 
 \protect \endinput
diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua
index 1e77b7aa0..9b363d2d6 100644
--- a/tex/context/base/mult-low.lua
+++ b/tex/context/base/mult-low.lua
@@ -194,6 +194,7 @@ return {
         "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg",
         "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg",
         "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledmbox",
+        "ruledhpack", "ruledvpack", "ruledtpack",
         "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern",
         "ruledhglue", "ruledvglue", "normalhglue", "normalvglue",
         "ruledpenalty",
@@ -409,5 +410,9 @@ return {
         "Ucheckedstartdisplaymath", "Ucheckedstopdisplaymath",
         --
         "nobreak", "allowbreak", "goodbreak",
+        --
+        "nospace", "nospacing", "dospacing",
+        --
+        "naturalhbox", "naturalvbox", "naturalhpack", "naturalvpack",
     }
 }
diff --git a/tex/context/base/mult-prm.lua b/tex/context/base/mult-prm.lua
index feb22e3b2..a39f4b09e 100644
--- a/tex/context/base/mult-prm.lua
+++ b/tex/context/base/mult-prm.lua
@@ -245,6 +245,7 @@ return {
   "dvifeedback",
   "dvivariable",
   "efcode",
+  "hjcode",
   "fontid",
   "formatname",
   "gleaders",
@@ -263,6 +264,7 @@ return {
   "latelua",
   "leftghost",
   "leftmarginkern",
+  "letcharcode",
   "letterspacefont",
   "localbrokenpenalty",
   "localinterlinepenalty",
@@ -285,6 +287,7 @@ return {
   "nokerns",
   "nohrule",
   "noligs",
+  "nospaces",
   "novrule",
   "normaldeviate",
   "outputbox",
@@ -330,6 +333,17 @@ return {
   "uniformdeviate",
   "useboxresource",
   "useimageresource",
+  --
+  "vpack",
+  "hpack",
+  "tpack",
+  "csstring",
+  "begincsname",
+  "lastnamedcs",
+  "toksapp",
+  "tokspre",
+  "etoksapp",
+  "etokspre",
  },
  ["omega"]={
   "OmegaVersion",
@@ -722,6 +736,7 @@ return {
   "eTeXversion",
   "edef",
   "efcode",
+  "hjcode",
   "else",
   "emergencystretch",
   "end",
@@ -856,6 +871,7 @@ return {
   "leftskip",
   "leqno",
   "let",
+  "letcharcode",
   "letterspacefont",
   "limits",
   "linepenalty",
@@ -923,6 +939,7 @@ return {
   "nokerns",
   "nohrule",
   "noligs",
+  "nospaces",
   "novrule",
   "nolimits",
   "nolocaldirs",
@@ -1230,6 +1247,17 @@ return {
   "xleaders",
   "xspaceskip",
   "year",
+  --
+  "vpack",
+  "hpack",
+  "tpack",
+  "csstring",
+  "begincsname",
+  "lastnamedcs",
+  "toksapp",
+  "tokspre",
+  "etoksapp",
+  "etokspre",
  },
  ["xetex"]={
   "XeTeXversion",
diff --git a/tex/context/base/node-acc.lua b/tex/context/base/node-acc.lua
index 716b3ef4d..097cb83d9 100644
--- a/tex/context/base/node-acc.lua
+++ b/tex/context/base/node-acc.lua
@@ -57,8 +57,8 @@ local function injectspaces(head)
     while n do
         local id = getid(n)
         if id == glue_code then -- todo: check for subtype related to spacing (13/14 but most seems to be 0)
-       -- if getfield(getfield(n,"spec"),"width") > 0 then -- threshold
---          if p and p_id == glyph_code then
+       -- if getfield(n,."width") > 0 then -- threshold
+         -- if p and p_id == glyph_code then
             if p and getid(p) == glyph_code then
                 local g = copy_node(p)
                 local c = getfield(g,"components")
@@ -68,21 +68,13 @@ local function injectspaces(head)
                     setfield(g,"subtype",256)
                 end
                 local a = getattr(n,a_characters)
-                -- local s = copy_node(getfield(n,"spec"))
-                -- this will be fixed in luatex but for now a temp hack (zero test)
-                local s = getfield(n,"spec")
-                s = s == 0 and new_gluespec(0) or copy_node(s)
-                --
                 setchar(g,32)
-                setfield(n,"spec",s)
-             -- insert_after(p,p,g)
                 setlink(p,g)
                 setlink(g,n)
-                setfield(s,"width",getfield(s,"width") - getfield(g,"width"))
+                setfield(n,"width",getfield(n,"width") - getfield(g,"width"))
                 if a then
                     setattr(g,a_characters,a)
                 end
-                setattr(s,a_characters,0)
                 setattr(n,a_characters,0)
                 nofreplaced = nofreplaced + 1
             end
diff --git a/tex/context/base/node-bck.mkiv b/tex/context/base/node-bck.mkiv
index ff0de6a5d..ed927cf0d 100644
--- a/tex/context/base/node-bck.mkiv
+++ b/tex/context/base/node-bck.mkiv
@@ -28,11 +28,16 @@
 
 \def\colorattr#1%
   {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
-     \thecolorattr{\currentcolorprefix#1}%
+     \node_backgrounds_thecolorattr{\currentcolorprefix#1}%
    \else\ifcsname\??colorattribute#1\endcsname
-     \thecolorattr{#1}%
+     \node_backgrounds_thecolorattr{#1}%
    \fi\fi}
 
+\def\node_backgrounds_thecolorattr#1%
+  {attr \colormodelattribute   \attribute\colormodelattribute
+   attr \colorattribute        \lastnamedcs
+   attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
+
 \def\thecolorattr#1%
   {attr \colormodelattribute   \attribute\colormodelattribute
    attr \colorattribute        \csname\??colorattribute#1\endcsname
@@ -40,9 +45,9 @@
 
 \def\backgroundcolorattr#1%
   {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
-     \thebackgroundcolorattr{\currentcolorprefix#1}%
+     \node_backgrounds_thebackgroundcolorattr{\currentcolorprefix#1}%
    \else\ifcsname\??colorattribute#1\endcsname
-     \thebackgroundcolorattr{#1}%
+     \node_backgrounds_thebackgroundcolorattr{#1}%
    \fi\fi}
 
 \def\thebackgroundcolorattr#1%
@@ -51,6 +56,12 @@
    attr \colorattribute           \csname\??colorattribute#1\endcsname
    attr \transparencyattribute    \thetransparencyattribute{#1} } % can be optimized
 
+\def\node_backgrounds_thebackgroundcolorattr#1%
+  {attr \backgroundattribute      \plusone
+   attr \colormodelattribute      \attribute\colormodelattribute
+   attr \colorattribute           \lastnamedcs
+   attr \transparencyattribute    \thetransparencyattribute{#1} } % can be optimized
+
 \def\thealignbackgroundcolorattr#1%
   {attr \alignbackgroundattribute \plusone
    attr \colormodelattribute      \attribute\colormodelattribute
diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua
index d83dceb9f..c062ddd00 100644
--- a/tex/context/base/node-fin.lua
+++ b/tex/context/base/node-fin.lua
@@ -203,16 +203,22 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
                     local outer = getattr(stack,attribute)
                     if outer ~= inheritance then
                         local list, ok = process(namespace,attribute,content,inheritance,outer)
+if content ~= list then
                         setfield(stack,"list",list)
+end
                         done = done or ok
                     else
                         local list, ok = process(namespace,attribute,content,inheritance,default)
+if content ~= list then
                         setfield(stack,"list",list)
+end
                         done = done or ok
                     end
                 else
                     local list, ok = process(namespace,attribute,content,inheritance,default)
+if content ~= list then
                     setfield(stack,"list",list)
+end
                     done = done or ok
                 end
                 -- end nested --
@@ -251,16 +257,22 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
                         local outer = getattr(stack,attribute)
                         if outer ~= inheritance then
                             local list, ok = process(namespace,attribute,leader,inheritance,outer)
+if leader ~= list then
                             setfield(stack,"leader",list)
+end
                             done = done or ok
                         else
                             local list, ok = process(namespace,attribute,leader,inheritance,default)
+if leader ~= list then
                             setfield(stack,"leader",list)
+end
                             done = done or ok
                         end
                     else
                         local list, ok = process(namespace,attribute,leader,inheritance,default)
+if leader ~= list then
                         setfield(stack,"leader",list)
+end
                         done = done or ok
                     end
                     -- end nested --
@@ -320,16 +332,22 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
                     local outer = getattr(stack,attribute)
                     if outer ~= inheritance then
                         local list, ok = selective(namespace,attribute,content,inheritance,outer)
+if content ~= list then
                         setfield(stack,"list",list)
+end
                         done = done or ok
                     else
                         local list, ok = selective(namespace,attribute,content,inheritance,default)
+if content ~= list then
                         setfield(stack,"list",list)
+end
                         done = done or ok
                     end
                 else
                     local list, ok = selective(namespace,attribute,content,inheritance,default)
+if content ~= list then
                     setfield(stack,"list",list)
+end
                     done = done or ok
                 end
                 -- end nested
@@ -366,16 +384,22 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
                         local outer = getatribute(stack,attribute)
                         if outer ~= inheritance then
                             local list, ok = selective(namespace,attribute,leader,inheritance,outer)
+if leader ~= list then
                             setfield(stack,"leader",list)
+end
                             done = done or ok
                         else
                             local list, ok = selective(namespace,attribute,leader,inheritance,default)
+if leader ~= list then
                             setfield(stack,"leader",list)
+end
                             done = done or ok
                         end
                     else
                         local list, ok = selective(namespace,attribute,leader,inheritance,default)
+if leader ~= list then
                         setfield(stack,"leader",list)
+end
                         done = done or ok
                     end
                     -- end nested
@@ -440,18 +464,24 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
                         current = a
                         head = insert_node_before(head,stack,copied(nsdata[a]))
                         local list = stacked(namespace,attribute,content,current) -- two return values
+if content ~= list then
                         setfield(stack,"list",list)
+end
                         done = true
                         head, stack = insert_node_after(head,stack,copied(nsnone))
                         current = p
                     else
                         local list, ok = stacked(namespace,attribute,content,current)
+if content ~= list then
                         setfield(stack,"list",list) -- only if ok
+end
                         done = done or ok
                     end
                 else
                     local list, ok = stacked(namespace,attribute,content,current)
+if content ~= list then
                     setfield(stack,"list",list) -- only if ok
+end
                     done = done or ok
                 end
             end
@@ -471,7 +501,9 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
                 end
                 if leader then
                     local list, ok = stacked(namespace,attribute,content,current)
+if leader ~= list then
                     setfield(stack,"leader",list) -- only if ok
+end
                     done = done or ok
                     leader = false
                 end
diff --git a/tex/context/base/node-fin.mkiv b/tex/context/base/node-fin.mkiv
index 7c95699dd..413a00722 100644
--- a/tex/context/base/node-fin.mkiv
+++ b/tex/context/base/node-fin.mkiv
@@ -45,18 +45,18 @@
 \def\dodoattributedcopy
   {\startinheritattributes
    \ifvbox\attributeboxcount
-     \vbox{\unvcopy\attributeboxcount}%
+     \vpack{\unvcopy\attributeboxcount}%
    \else
-     \hbox{\unhcopy\attributeboxcount}%
+     \hpack{\unhcopy\attributeboxcount}%
    \fi
    \stopinheritattributes}
 
 \def\dodoattributedbox
   {\startinheritattributes
    \ifvbox\attributeboxcount
-     \vbox{\unvbox\attributeboxcount}%
+     \vpack{\unvbox\attributeboxcount}%
    \else
-     \hbox{\unhbox\attributeboxcount}%
+     \hpack{\unhbox\attributeboxcount}%
    \fi
    \stopinheritattributes}
 
diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua
index 667cf4d62..5e6d8f3d3 100644
--- a/tex/context/base/node-fnt.lua
+++ b/tex/context/base/node-fnt.lua
@@ -25,6 +25,7 @@ local report_fonts      = logs.reporter("fonts","processing")
 local fonthashes        = fonts.hashes
 local fontdata          = fonthashes.identifiers
 local fontvariants      = fonthashes.variants
+local fontmodes         = fonthashes.modes
 
 local otf               = fonts.handlers.otf
 
@@ -49,9 +50,12 @@ local getfield          = nuts.getfield
 ----- getdisc           = nuts.getdisc
 local setchar           = nuts.setchar
 local setlink           = nuts.setlink
+local setfield          = nuts.setfield
 
 local traverse_id       = nuts.traverse_id
+local traverse_char     = nuts.traverse_char
 local delete_node       = nuts.delete
+local protect_glyph     = nuts.protect_glyph
 
 local glyph_code        = nodecodes.glyph
 local disc_code         = nodecodes.disc
@@ -126,8 +130,8 @@ fonts.hashes.processes   = fontprocesses
 -- we need to deal with the basemode fonts here and can only run over ranges as we
 -- otherwise get luatex craches due to all kind of asserts in the disc/lig builder
 
-local ligaturing = node.ligaturing
-local kerning    = node.kerning
+local ligaturing = nuts.ligaturing
+local kerning    = nuts.kerning
 
 local expanders
 
@@ -158,6 +162,7 @@ function handlers.characters(head)
     local basefont  = nil
     local prevfont  = nil
     local prevattr  = 0
+    local mode      = nil
     local done      = false
     local variants  = nil
     local redundant = nil
@@ -185,13 +190,20 @@ function handlers.characters(head)
 
     local nuthead = tonut(head)
 
-    for n in traverse_id(glyph_code,nuthead) do
-        if getsubtype(n) < 256 then -- all are 1
-            local font = getfont(n)
-            local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
-            if font ~= prevfont or attr ~= prevattr then
+    for n in traverse_char(nuthead) do
+        local font = getfont(n)
+        local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+        if font ~= prevfont or attr ~= prevattr then
+            prevfont = font
+            prevattr = attr
+            mode     = fontmodes[font] -- we can also avoid the attr check
+            variants = fontvariants[font]
+            if mode == "none" then
+                -- skip
+                protect_glyph(n)
+            else
                 if basefont then
-                    basefont[2] = tonode(getprev(n)) -- todo, save p
+                    basefont[2] = getprev(n)
                 end
                 if attr > 0 then
                     local used = attrfonts[font]
@@ -206,7 +218,7 @@ function handlers.characters(head)
                             a = a + 1
                         elseif force_basepass then
                             b = b + 1
-                            basefont = { tonode(n), nil }
+                            basefont = { n, nil }
                             basefonts[b] = basefont
                         end
                     end
@@ -219,34 +231,31 @@ function handlers.characters(head)
                             u = u + 1
                         elseif force_basepass then
                             b = b + 1
-                            basefont = { tonode(n), nil }
+                            basefont = { n, nil }
                             basefonts[b] = basefont
                         end
                     end
                 end
-                prevfont = font
-                prevattr = attr
-                variants = fontvariants[font]
             end
-            if variants then
-                local char = getchar(n)
-                if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then
-                    local hash = variants[char]
-                    if hash then
-                        local p = getprev(n)
-                        if p and getid(p) == glyph_code then
-                            local char    = getchar(p)
-                            local variant = hash[char]
-                            if variant then
-                                if trace_variants then
-                                    report_fonts("replacing %C by %C",char,variant)
-                                end
-                                setchar(p,variant)
-                                if not redundant then
-                                    redundant = { n }
-                                else
-                                    redundant[#redundant+1] = n
-                                end
+        end
+        if variants then
+            local char = getchar(n)
+            if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then
+                local hash = variants[char]
+                if hash then
+                    local p = getprev(n)
+                    if p and getid(p) == glyph_code then
+                        local char    = getchar(p)
+                        local variant = hash[char]
+                        if variant then
+                            if trace_variants then
+                                report_fonts("replacing %C by %C",char,variant)
+                            end
+                            setchar(p,variant)
+                            if not redundant then
+                                redundant = { n }
+                            else
+                                redundant[#redundant+1] = n
                             end
                         end
                     end
@@ -279,40 +288,38 @@ function handlers.characters(head)
             -- we could use first_glyph
             local r = getfield(d,"replace") -- good enough
             if r then
-                for n in traverse_id(glyph_code,r) do
-                    if getsubtype(n) < 256 then -- all are 1
-                        local font = getfont(n)
-                        local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
-                        if font ~= prevfont or attr ~= prevattr then
-                            if attr > 0 then
-                                local used = attrfonts[font]
-                                if not used then
-                                    used = { }
-                                    attrfonts[font] = used
-                                end
-                                if not used[attr] then
-                                    local fd = setfontdynamics[font]
-                                    if fd then
-                                        used[attr] = fd[attr]
-                                        a = a + 1
-                                    end
+                for n in traverse_char(r) do
+                    local font = getfont(n)
+                    local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+                    if font ~= prevfont or attr ~= prevattr then
+                        if attr > 0 then
+                            local used = attrfonts[font]
+                            if not used then
+                                used = { }
+                                attrfonts[font] = used
+                            end
+                            if not used[attr] then
+                                local fd = setfontdynamics[font]
+                                if fd then
+                                    used[attr] = fd[attr]
+                                    a = a + 1
                                 end
-                            else
-                                local used = usedfonts[font]
-                                if not used then
-                                    local fp = fontprocesses[font]
-                                    if fp then
-                                        usedfonts[font] = fp
-                                        u = u + 1
-                                    end
+                            end
+                        else
+                            local used = usedfonts[font]
+                            if not used then
+                                local fp = fontprocesses[font]
+                                if fp then
+                                    usedfonts[font] = fp
+                                    u = u + 1
                                 end
                             end
-                            prevfont = font
-                            prevattr = attr
                         end
+                        prevfont = font
+                        prevattr = attr
                     end
-                    break
                 end
+                break
             elseif expanders then
                 local subtype = getsubtype(d)
                 if subtype == discretionary_code then
@@ -393,7 +400,7 @@ function handlers.characters(head)
         local start = range[1]
         local stop  = range[2]
         if (start or stop) and (start ~= stop) then
-            local front = head == start
+            local front = nuthead == start
             if stop then
                 start, stop = ligaturing(start,stop)
                 start, stop = kerning(start,stop)
@@ -402,12 +409,12 @@ function handlers.characters(head)
                 start = kerning(start)
             end
             if front then
-                head = start
+                head = tonode(start)
             end
         end
     else
         -- multiple fonts
-        local front = head == start
+        local front = nuthead == start
         for i=1,b do
             local range = basefonts[i]
             local start = range[1]
@@ -430,15 +437,18 @@ function handlers.characters(head)
                     setlink(stop,next)
                 end
                 if front then
-                    head  = start
+                    nuthead  = start
                     front = nil -- we assume a proper sequence
                 end
             end
             if front then
                 -- shouldn't happen
-                head = start
+                nuthead = start
             end
         end
+        if front then
+            head = tonode(nuthead)
+        end
     end
     stoptiming(nodes)
     if trace_characters then
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
index 73f2a8add..aac3b3284 100644
--- a/tex/context/base/node-ini.lua
+++ b/tex/context/base/node-ini.lua
@@ -57,150 +57,182 @@ nodes               = nodes or { }
 local nodes         = nodes
 nodes.handlers      = nodes.handlers or { }
 
+local mark          = utilities.storage.mark
 local allocate      = utilities.storage.allocate
 local formatcolumns = utilities.formatters.formatcolumns
 
--- there will be more of this:
-
-local skipcodes = allocate {
-    [  0] = "userskip",
-    [  1] = "lineskip",
-    [  2] = "baselineskip",
-    [  3] = "parskip",
-    [  4] = "abovedisplayskip",
-    [  5] = "belowdisplayskip",
-    [  6] = "abovedisplayshortskip",
-    [  7] = "belowdisplayshortskip",
-    [  8] = "leftskip",
-    [  9] = "rightskip",
-    [ 10] = "topskip",
-    [ 11] = "splittopskip",
-    [ 12] = "tabskip",
-    [ 13] = "spaceskip",
-    [ 14] = "xspaceskip",
-    [ 15] = "parfillskip",
-    [ 16] = "thinmuskip",
-    [ 17] = "medmuskip",
-    [ 18] = "thickmuskip",
-    [ 19] = "mathskip", -- experiment
-    [100] = "leaders",
-    [101] = "cleaders",
-    [102] = "xleaders",
-    [103] = "gleaders",
-}
-
-local leadercodes = allocate {
-    [100] = "leaders",
-    [101] = "cleaders",
-    [102] = "xleaders",
-    [103] = "gleaders",
-}
-
-local penaltycodes = allocate { -- unfortunately not used
-    [ 0] = "userpenalty",
-}
+local getsubtypes   = node.subtypes
+
+-- local listcodes = allocate {
+--     [0] = "unknown",
+--     [1] = "line",
+--     [2] = "box",
+--     [3] = "indent",
+--     [4] = "alignment", -- row or column
+--     [5] = "cell",
+--     [6] = "equation",
+--     [7] = "equationnumber",
+-- }
+
+local listcodes = mark(getsubtypes("list"))
+
+-- local rulecodes = allocate {
+--     [0] = "normal",
+--     [1] = "box",
+--     [2] = "image",
+--     [3] = "empty",
+--     [4] = "user",
+-- }
+
+local rulecodes = mark(getsubtypes("rule"))
+
+-- local glyphcodes = allocate {
+--     [0] = "character",
+--     [1] = "glyph",
+--     [2] = "ligature",
+--     [3] = "ghost",
+--     [4] = "left",
+--     [5] = "right",
+-- }
+
+local glyphcodes = mark(getsubtypes("glyph"))
+
+-- local disccodes = allocate {
+--     [0] = "discretionary", -- \discretionary
+--     [1] = "explicit",      -- \-
+--     [2] = "automatic",     -- following a -
+--     [3] = "regular",       -- by hyphenator: simple
+--     [4] = "first",         -- by hyphenator: hard first item
+--     [5] = "second",        -- by hyphenator: hard second item
+-- }
+
+local disccodes = mark(getsubtypes("disc"))
+
+-- local skipcodes = allocate {
+--     [  0] = "userskip",
+--     [  1] = "lineskip",
+--     [  2] = "baselineskip",
+--     [  3] = "parskip",
+--     [  4] = "abovedisplayskip",
+--     [  5] = "belowdisplayskip",
+--     [  6] = "abovedisplayshortskip",
+--     [  7] = "belowdisplayshortskip",
+--     [  8] = "leftskip",
+--     [  9] = "rightskip",
+--     [ 10] = "topskip",
+--     [ 11] = "splittopskip",
+--     [ 12] = "tabskip",
+--     [ 13] = "spaceskip",
+--     [ 14] = "xspaceskip",
+--     [ 15] = "parfillskip",
+--     [ 16] = "thinmuskip",
+--     [ 17] = "medmuskip",
+--     [ 18] = "thickmuskip",
+--     [ 19] = "mathskip", -- experiment
+--     [100] = "leaders",
+--     [101] = "cleaders",
+--     [102] = "xleaders",
+--     [103] = "gleaders",
+-- }
+
+local skipcodes = mark(getsubtypes("glue"))
+
+-- local leadercodes = allocate {
+--     [100] = "leaders",
+--     [101] = "cleaders",
+--     [102] = "xleaders",
+--     [103] = "gleaders",
+-- }
+
+local leadercodes = mark(getsubtypes("leader"))
+
+-- local fillcodes = allocate {
+--     [0] = "stretch",
+--     [1] = "fi",
+--     [2] = "fil",
+--     [3] = "fill",
+--     [4] = "filll",
+-- }
+
+local fillcodes = mark(getsubtypes("fill"))
+
+-- local penaltycodes = allocate { -- unfortunately not used (yet)
+--     [ 0] = "userpenalty",
+-- }
+
+local penaltycodes = mark(getsubtypes("penalty"))
 
 table.setmetatableindex(penaltycodes,function(t,k) return "userpenalty" end) -- not used anyway
 
-local noadcodes = allocate { -- simple nodes
-    [ 0] = "ord",
-    [ 1] = "opdisplaylimits",
-    [ 2] = "oplimits",
-    [ 3] = "opnolimits",
-    [ 4] = "bin",
-    [ 5] = "rel",
-    [ 6] = "open",
-    [ 7] = "close",
-    [ 8] = "punct",
-    [ 9] = "inner",
-    [10] = "under",
-    [11] = "over",
-    [12] = "vcenter",
-}
-
-local radicalcodes = allocate {
-    [0] = "radical",
-    [1] = "uradical",
-    [2] = "uroot",
-    [3] = "uunderdelimiter",
-    [4] = "uoverdelimiter",
-    [5] = "udelimiterunder",
-    [6] = "udelimiterover",
-}
-
-local listcodes = allocate {
-    [0] = "unknown",
-    [1] = "line",
-    [2] = "box",
-    [3] = "indent",
-    [4] = "alignment", -- row or column
-    [5] = "cell",
-    [6] = "equation",
-    [7] = "equationnumber",
-}
-
-local glyphcodes = allocate {
-    [0] = "character",
-    [1] = "glyph",
-    [2] = "ligature",
-    [3] = "ghost",
-    [4] = "left",
-    [5] = "right",
-}
-
-local kerncodes = allocate {
-    [0] = "fontkern",
-    [1] = "userkern",
-    [2] = "accentkern",
-}
-
-local mathcodes = allocate {
-    [0] = "beginmath",
-    [1] = "endmath",
-}
-
-local fillcodes = allocate {
-    [0] = "stretch",
-    [1] = "fi",
-    [2] = "fil",
-    [3] = "fill",
-    [4] = "filll",
-}
-
-local margincodes = allocate {
-    [0] = "left",
-    [1] = "right",
-}
-
-local disccodes = allocate {
-    [0] = "discretionary", -- \discretionary
-    [1] = "explicit",      -- \-
-    [2] = "automatic",     -- following a -
-    [3] = "regular",       -- by hyphenator: simple
-    [4] = "first",         -- by hyphenator: hard first item
-    [5] = "second",        -- by hyphenator: hard second item
-}
-
-local accentcodes = allocate {
-    [0] = "bothflexible",
-    [1] = "fixedtop",
-    [2] = "fixedbottom",
-    [3] = "fixedboth",
-}
-
-local fencecodes = allocate {
-    [0] = "unset",
-    [1] = "left",
-    [2] = "middle",
-    [3] = "right",
-}
-
-local rulecodes = allocate {
-    [0] = "normal",
-    [1] = "box",
-    [2] = "image",
-    [3] = "empty",
-}
+-- local kerncodes = allocate {
+--     [0] = "fontkern",
+--     [1] = "userkern",
+--     [2] = "accentkern",
+-- }
+
+local kerncodes = mark(getsubtypes("kern"))
+
+-- local margincodes = allocate {
+--     [0] = "left",
+--     [1] = "right",
+-- }
+
+local margincodes = mark(getsubtypes("marginkern"))
+
+-- local mathcodes = allocate {
+--     [0] = "beginmath",
+--     [1] = "endmath",
+-- }
+
+local mathcodes = mark(getsubtypes("math"))
+
+-- local noadcodes = allocate { -- simple nodes
+--     [ 0] = "ord",
+--     [ 1] = "opdisplaylimits",
+--     [ 2] = "oplimits",
+--     [ 3] = "opnolimits",
+--     [ 4] = "bin",
+--     [ 5] = "rel",
+--     [ 6] = "open",
+--     [ 7] = "close",
+--     [ 8] = "punct",
+--     [ 9] = "inner",
+--     [10] = "under",
+--     [11] = "over",
+--     [12] = "vcenter",
+-- }
+
+local noadcodes = mark(getsubtypes("noad"))
+
+-- local radicalcodes = allocate {
+--     [0] = "radical",
+--     [1] = "uradical",
+--     [2] = "uroot",
+--     [3] = "uunderdelimiter",
+--     [4] = "uoverdelimiter",
+--     [5] = "udelimiterunder",
+--     [6] = "udelimiterover",
+-- }
+
+local radicalcodes = mark(getsubtypes("radical"))
+
+-- local accentcodes = allocate {
+--     [0] = "bothflexible",
+--     [1] = "fixedtop",
+--     [2] = "fixedbottom",
+--     [3] = "fixedboth",
+-- }
+
+local accentcodes = mark(getsubtypes("accent"))
+
+-- local fencecodes = allocate {
+--     [0] = "unset",
+--     [1] = "left",
+--     [2] = "middle",
+--     [3] = "right",
+-- }
+
+local fencecodes = mark(getsubtypes("fence"))
 
 -- maybe we also need fractioncodes
 
@@ -257,8 +289,6 @@ listcodes.column           = listcodes.alignment
 kerncodes.italiccorrection = kerncodes.userkern
 kerncodes.kerning          = kerncodes.fontkern
 
-whatcodes.textdir          = whatcodes.dir
-
 nodes.codes = allocate { -- mostly for listing
     glue    = skipcodes,
     noad    = noadcodes,
diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua
deleted file mode 100644
index 402403529..000000000
--- a/tex/context/base/node-inj.lua
+++ /dev/null
@@ -1,603 +0,0 @@
-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",
-}
-
--- 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. Some optimizations can go away when we have faster machines.
-
--- todo: ignore kerns between disc and glyph
-
-local next = next
-local utfchar = utf.char
-
-local trace_injections = false  trackers.register("nodes.injections", function(v) trace_injections = v end)
-
-local report_injections = logs.reporter("nodes","injections")
-
-local attributes, nodes, node = attributes, nodes, node
-
-fonts                    = fonts
-local fontdata           = fonts.hashes.identifiers
-
-nodes.injections         = nodes.injections or { }
-local injections         = nodes.injections
-
-local nodecodes          = nodes.nodecodes
-local glyph_code         = nodecodes.glyph
-local kern_code          = nodecodes.kern
-
-local nuts               = nodes.nuts
-local nodepool           = nuts.pool
-
-local newkern            = nodepool.kern
-
-local tonode             = nuts.tonode
-local tonut              = nuts.tonut
-
-local getfield           = nuts.getfield
-local getnext            = nuts.getnext
-local getprev            = nuts.getprev
-local getid              = nuts.getid
-local getattr            = nuts.getattr
-local getfont            = nuts.getfont
-local getsubtype         = nuts.getsubtype
-local getchar            = nuts.getchar
-
-local setfield           = nuts.setfield
-local setattr            = nuts.setattr
-
-local traverse_id        = nuts.traverse_id
-local insert_node_before = nuts.insert_before
-local insert_node_after  = nuts.insert_after
-
-local a_kernpair = attributes.private('kernpair')
-local a_ligacomp = attributes.private('ligacomp')
-local a_markbase = attributes.private('markbase')
-local a_markmark = attributes.private('markmark')
-local a_markdone = attributes.private('markdone')
-local a_cursbase = attributes.private('cursbase')
-local a_curscurs = attributes.private('curscurs')
-local a_cursdone = attributes.private('cursdone')
-
-local unsetvalue = attributes.unsetvalue
-
--- This injector has been tested by Idris Samawi Hamid (several arabic fonts as well as
--- the rather demanding Husayni font), Khaled Hosny (latin and arabic) and Kaj Eigner
--- (arabic, hebrew and thai) and myself (whatever font I come across). I'm pretty sure
--- that this code is not 100% okay but examples are needed to figure things out.
-
-function injections.installnewkern(nk)
-    newkern = nk or newkern
-end
-
-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 .. idris: this needs
--- checking with husayni (volt and fontforge).
-
-function injections.reset(n)
---     if getattr(n,a_kernpair) then
---         setattr(n,a_kernpair,unsetvalue)
---     end
---     if getattr(n,a_markdone) then
---         setattr(n,a_markbase,unsetvalue)
---         setattr(n,a_markmark,unsetvalue)
---         setattr(n,a_markdone,unsetvalue)
---     end
---     if getattr(n,a_cursdone) then
---         setattr(n,a_cursbase,unsetvalue)
---         setattr(n,a_curscurs,unsetvalue)
---         setattr(n,a_cursdone,unsetvalue)
---     end
---     if getattr(n,a_ligacomp) then
---         setattr(n,a_ligacomp,unsetvalue)
---     end
-end
-
-function injections.setligaindex(n,index)
-    setattr(n,a_ligacomp,index)
-end
-
-function injections.getligaindex(n,default)
-    return getattr(n,a_ligacomp) or default
-end
-
-function injections.setcursive(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
-    setattr(start,a_cursbase,bound)
-    setattr(nxt,a_curscurs,bound)
-    cursives[bound] = { rlmode, dx, dy, ws, wn }
-    return dx, dy, bound
-end
-
-function injections.setpair(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 = getattr(current,a_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
-            setattr(current,a_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 injections.setkern(current,factor,rlmode,x,tfmchr)
-    local dx = factor*x
-    if dx ~= 0 then
-        local bound = #kerns + 1
-        setattr(current,a_kernpair,bound)
-        kerns[bound] = { rlmode, dx }
-        return dx, bound
-    else
-        return 0, 0
-    end
-end
-
-function injections.setmark(start,base,factor,rlmode,ba,ma) -- ba=baseanchor, ma=markanchor
-    local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
-    local bound = getattr(base,a_markbase)
-    local index = 1
-    if bound then
-        local mb = marks[bound]
-        if mb then
-         -- if not index then index = #mb + 1 end
-            index = #mb + 1
-            mb[index] = { dx, dy, rlmode }
-            setattr(start,a_markmark,bound)
-            setattr(start,a_markdone,index)
-            return dx, dy, bound
-        else
-            report_injections("possible problem, %U is base mark without data (id %a)",getchar(base),bound)
-        end
-    end
-    index = index or 1
-    bound = #marks + 1
-    setattr(base,a_markbase,bound)
-    setattr(start,a_markmark,bound)
-    setattr(start,a_markdone,index)
-    marks[bound] = { [index] = { dx, dy, rlmode } }
-    return dx, dy, bound
-end
-
-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 trace(head)
-    report_injections("begin run")
-    for n in traverse_id(glyph_code,head) do
-        if getsubtype(n) < 256 then
-            local kp = getattr(n,a_kernpair)
-            local mb = getattr(n,a_markbase)
-            local mm = getattr(n,a_markmark)
-            local md = getattr(n,a_markdone)
-            local cb = getattr(n,a_cursbase)
-            local cc = getattr(n,a_curscurs)
-            local char = getchar(n)
-            report_injections("font %s, char %U, glyph %c",getfont(n),char,char)
-            if kp then
-                local k = kerns[kp]
-                if k[3] then
-                    report_injections("  pairkern: dir %a, x %p, y %p, w %p, h %p",dir(k[1]),k[2],k[3],k[4],k[5])
-                else
-                    report_injections("  kern: dir %a, dx %p",dir(k[1]),k[2])
-                end
-            end
-            if mb then
-                report_injections("  markbase: bound %a",mb)
-            end
-            if mm then
-                local m = marks[mm]
-                if mb then
-                    local m = m[mb]
-                    if m then
-                        report_injections("  markmark: bound %a, index %a, dx %p, dy %p",mm,md,m[1],m[2])
-                    else
-                        report_injections("  markmark: bound %a, missing index",mm)
-                    end
-                else
-                    m = m[1]
-                    report_injections("  markmark: bound %a, dx %p, dy %p",mm,m and m[1],m and m[2])
-                end
-            end
-            if cb then
-                report_injections("  cursbase: bound %a",cb)
-            end
-            if cc then
-                local c = cursives[cc]
-                report_injections("  curscurs: bound %a, dir %a, dx %p, dy %p",cc,dir(c[1]),c[2],c[3])
-            end
-        end
-    end
-    report_injections("end run")
-end
-
--- todo: reuse tables (i.e. no collection), but will be extra fields anyway
--- todo: check for attribute
-
--- We can have a fast test on a font being processed, so we can check faster for marks etc
--- but I'll make a context variant anyway.
-
-local function show_result(head)
-    local current = head
-    local skipping = false
-    while current do
-        local id = getid(current)
-        if id == glyph_code then
-            report_injections("char: %C, width %p, xoffset %p, yoffset %p",
-                getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
-            skipping = false
-        elseif id == kern_code then
-            report_injections("kern: %p",getfield(current,"kern"))
-            skipping = false
-        elseif not skipping then
-            report_injections()
-            skipping = true
-        end
-        current = getnext(current)
-    end
-end
-
-function injections.handler(head,where,keep)
-    head = tonut(head)
-    local has_marks, has_cursives, has_kerns = next(marks), next(cursives), next(kerns)
-    if has_marks or has_cursives then
-        if trace_injections then
-            trace(head)
-        end
-        -- in the future variant we will not copy items but refs to tables
-        local done, ky, rl, valid, cx, wx, mk, nofvalid = false, { }, { }, { }, { }, { }, { }, 0
-        if has_kerns then -- move outside loop
-            local nf, tm = nil, nil
-            for n in traverse_id(glyph_code,head) do -- only needed for relevant fonts
-                if getsubtype(n) < 256 then
-                    nofvalid = nofvalid + 1
-                    valid[nofvalid] = n
-                    local f = getfont(n)
-                    if f ~= nf then
-                        nf = f
-                        tm = fontdata[nf].resources.marks -- other hash in ctx
-                    end
-                    if tm then
-                        mk[n] = tm[getchar(n)]
-                    end
-                    local k = getattr(n,a_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_code,head) do
-                if getsubtype(n) < 256 then
-                    nofvalid = nofvalid + 1
-                    valid[nofvalid] = n
-                    local f = getfont(n)
-                    if f ~= nf then
-                        nf = f
-                        tm = fontdata[nf].resources.marks -- other hash in ctx
-                    end
-                    if tm then
-                        mk[n] = tm[getchar(n)]
-                    end
-                end
-            end
-        end
-        if nofvalid > 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
-                    setfield(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,nofvalid do -- valid == glyphs
-                    local n = valid[i]
-                    if not mk[n] then
-                        local n_cursbase = getattr(n,a_cursbase)
-                        if p_cursbase then
-                            local n_curscurs = getattr(n,a_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 = getfield(n,"yoffset")
-                            for i=maxt,1,-1 do
-                                ny = ny + d[i]
-                                local ti = t[i]
-                                setfield(ti,"yoffset",getfield(ti,"yoffset") + ny)
-                            end
-                            maxt = 0
-                        end
-                        if not n_cursbase and maxt > 0 then
-                            local ny = getfield(n,"yoffset")
-                            for i=maxt,1,-1 do
-                                ny = ny + d[i]
-                                local ti = t[i]
-                                setfield(ti,"yoffset",ny) -- maybe add to current yoffset
-                            end
-                            maxt = 0
-                        end
-                        p_cursbase, p = n_cursbase, n
-                    end
-                end
-                if maxt > 0 then
-                    local ny = getfield(n,"yoffset") -- hm, n unset ?
-                    for i=maxt,1,-1 do
-                        ny = ny + d[i]
-                        local ti = t[i]
-                        setfield(ti,"yoffset",ny)
-                    end
-                    maxt = 0
-                end
-                if not keep then
-                    cursives = { }
-                end
-            end
-            if has_marks then
-                for i=1,nofvalid do
-                    local p = valid[i]
-                    local p_markbase = getattr(p,a_markbase)
-                    if p_markbase then
-                        local mrks      = marks[p_markbase]
-                        local nofmarks  = #mrks
-                        for n in traverse_id(glyph_code,getnext(p)) do
-                            local n_markmark = getattr(n,a_markmark)
-                            if p_markbase == n_markmark then
-                                local index = getattr(n,a_markdone) or 1
-                                local d = mrks[index]
-                                if d then
-                                    local rlmode = d[3]
-                                    --
-                                    local k = wx[p]
-                                    local px = getfield(p,"xoffset")
-                                    local ox = 0
-                                    if k then
-                                        local x = k[2]
-                                        local w = k[4]
-                                        if w then
-                                            if rlmode and rlmode >= 0 then
-                                                -- kern(x) glyph(p) kern(w-x) mark(n)
-                                                ox = px - getfield(p,"width") + d[1] - (w-x)
-                                             -- report_injections("l2r case 1: %p",ox)
-                                            else
-                                                -- kern(w-x) glyph(p) kern(x) mark(n)
-                                                ox = px - d[1] - x
-                                             -- report_injections("r2l case 1: %p",ox)
-                                            end
-                                        else
-                                            if rlmode and rlmode >= 0 then
-                                                -- okay for husayni
-                                                ox = px - getfield(p,"width") + d[1]
-                                             -- report_injections("r2l case 2: %p",ox)
-                                            else
-                                                -- needs checking: is x ok here?
-                                                ox = px - d[1] - x
-                                             -- report_injections("r2l case 2: %p",ox)
-                                            end
-                                        end
-                                    else
-                                     -- if rlmode and rlmode >= 0 then
-                                     --     ox = px - getfield(p,"width") + d[1]
-                                     --  -- report_injections("l2r case 3: %p",ox)
-                                     -- else
-                                     --     ox = px - d[1]
-                                     --  -- report_injections("r2l case 3: %p",ox)
-                                     -- end
-                                        --
-                                        -- we need to deal with fonts that have marks with width
-                                        --
-                                        local wp = getfield(p,"width")
-                                        local wn = getfield(n,"width") -- in arial marks have widths
-                                        if rlmode and rlmode >= 0 then
-                                            ox = px - wp + d[1]
-                                         -- report_injections("l2r case 3: %p",ox)
-                                        else
-                                            ox = px - d[1]
-                                         -- report_injections("r2l case 3: %p",ox)
-                                        end
-                                        if wn ~= 0 then
-                                            -- bad: we should center
-                                            insert_node_before(head,n,newkern(-wn/2))
-                                            insert_node_after(head,n,newkern(-wn/2))
-                                         -- wx[n] = { 0, -wn/2, 0, -wn }
-                                        end
-                                        -- so far
-                                    end
-                                    setfield(n,"xoffset",ox)
-                                    --
-                                    local py = getfield(p,"yoffset")
-                                    local oy = 0
-                                    if mk[p] then
-                                        oy = py + d[2]
-                                    else
-                                        oy = getfield(n,"yoffset") + py + d[2]
-                                    end
-                                    setfield(n,"yoffset",oy)
-                                    --
-                                    if nofmarks == 1 then
-                                        break
-                                    else
-                                        nofmarks = nofmarks - 1
-                                    end
-                                end
-                            elseif not n_markmark then
-                                break -- HH: added 2013-09-12: no need to deal with non marks
-                            else
-                                -- KE: there can be    sequences in ligatures
-                            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 (kernclasses), can be sped up when w == nil
-                    local x = k[2]
-                    local w = k[4]
-                    if w then
-                        local rl = k[1] -- r2l = k[6]
-                        local wx = w - x
-                        if rl < 0 then	-- KE: don't use r2l here
-                            if wx ~= 0 then
-                                insert_node_before(head,n,newkern(wx)) -- type 0/2
-                            end
-                            if x ~= 0 then
-                                insert_node_after (head,n,newkern(x))  -- type 0/2
-                            end
-                        else
-                            if x ~= 0 then
-                                insert_node_before(head,n,newkern(x))  -- type 0/2
-                            end
-                            if wx ~= 0 then
-                                insert_node_after (head,n,newkern(wx)) -- type 0/2
-                            end
-                        end
-                    elseif x ~= 0 then
-                        -- this needs checking for rl < 0 but it is unlikely that a r2l script
-                        -- uses kernclasses between glyphs so we're probably safe (KE has a
-                        -- problematic font where marks interfere with rl < 0 in the previous
-                        -- case)
-                        insert_node_before(head,n,newkern(x)) -- a real font kern, type 0
-                    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)) -- type 0/2
-                        else
-                            insert_node_before(head,n,newkern(k))  -- type 0/2
-                        end
-                    end
-                end
-            end
-            if not keep then
-                kerns = { }
-            end
-         -- if trace_injections then
-         --     show_result(head)
-         -- end
-            return tonode(head), true
-        elseif not keep then
-            kerns, cursives, marks = { }, { }, { }
-        end
-    elseif has_kerns then
-        if trace_injections then
-            trace(head)
-        end
-        for n in traverse_id(glyph_code,head) do
-            if getsubtype(n) < 256 then
-                local k = getattr(n,a_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
-                            setfield(n,"yoffset",y) -- todo: h ?
-                        end
-                        if w then
-                            -- copied from above
-                         -- local r2l = kk[6]
-                            local wx = w - x
-                            if rl < 0 then  -- KE: don't use r2l here
-                                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
-                            -- simple (e.g. kernclass kerns)
-                            if x ~= 0 then
-                                insert_node_before(head,n,newkern(x))
-                            end
-                        end
-                    end
-                end
-            end
-        end
-        if not keep then
-            kerns = { }
-        end
-     -- if trace_injections then
-     --     show_result(head)
-     -- end
-        return tonode(head), true
-    else
-        -- no tracing needed
-    end
-    return tonode(head), false
-end
diff --git a/tex/context/base/node-met.lua b/tex/context/base/node-met.lua
index 584f3bc93..5c6e18bd3 100644
--- a/tex/context/base/node-met.lua
+++ b/tex/context/base/node-met.lua
@@ -86,13 +86,13 @@ nodes.new                  = node.new
 nodes.tail                 = node.tail
 nodes.traverse             = node.traverse
 nodes.traverse_id          = node.traverse_id
+nodes.traverse_char        = node.traverse_char
 nodes.slide                = node.slide
 nodes.vpack                = node.vpack
 nodes.fields               = node.fields
 nodes.is_node              = node.is_node
 
 nodes.first_glyph          = node.first_glyph
-nodes.first_character      = node.first_character
 nodes.has_glyph            = node.has_glyph or node.first_glyph
 
 nodes.current_attr         = node.current_attr
@@ -108,6 +108,7 @@ nodes.set_attribute        = node.set_attribute
 nodes.unset_attribute      = node.unset_attribute
 
 nodes.protect_glyphs       = node.protect_glyphs
+nodes.protect_glyph        = node.protect_glyph
 nodes.unprotect_glyphs     = node.unprotect_glyphs
 nodes.kerning              = node.kerning
 nodes.ligaturing           = node.ligaturing
@@ -126,7 +127,7 @@ nodes.tonut  = function(n) return n end
 local getfield          = node.getfield
 local setfield          = node.setfield
 
-local getattr           = getfield
+local getattr           = node.get_attribute or node.has_attribute or getfield
 local setattr           = setfield
 
 local getnext           = node.getnext    or function(n) return getfield(n,"next")    end
@@ -174,14 +175,6 @@ local n_slide           = nodes.slide
 
 local n_remove_node     = node.remove -- not yet nodes.remove
 
--- if t.id == glue_code then
---     local s = t.spec
---     if s and s.writable then
---         free_node(s)
---     end
---     t.spec = nil
--- end
-
 local function remove(head,current,free_too)
     local t = current
     head, current = n_remove_node(head,current)
@@ -318,6 +311,8 @@ and hide it for the user. And yes, LuaTeX now gives a warning as
 well.
 ]]--
 
+-- writable will go away
+
 function nodes.writable_spec(n) -- not pool
     local spec = n_getfield(n,"spec")
     if not spec then
@@ -688,34 +683,3 @@ end
 
 nodes.keys   = keys       -- [id][subtype]
 nodes.fields = nodefields -- (n)
-
--- one issue solved in flush_node:
---
--- case glue_spec_node:
---     if (glue_ref_count(p)!=null) {
---         decr(glue_ref_count(p));
---         return ;
---     /*
---     } else if (! valid_node(p)) {
---          return ;
---     */
---     /*
---     } else {
---         free_node(p, get_node_size(type(p), subtype(p)));
---         return ;
---     */
---     }
---     break ;
---
--- or:
---
--- case glue_spec_node:
---     if (glue_ref_count(p)!=null) {
---         decr(glue_ref_count(p));
---         return ;
---     } else if (valid_node(p)) {
---         free_node(p, get_node_size(type(p), subtype(p)));
---         return ;
---     } else {
---         break ;
---     }
diff --git a/tex/context/base/node-nut.lua b/tex/context/base/node-nut.lua
index f5de89196..4b5e36f6c 100644
--- a/tex/context/base/node-nut.lua
+++ b/tex/context/base/node-nut.lua
@@ -123,7 +123,7 @@ nuts.getfield             = direct.getfield
 nuts.getnext              = direct.getnext
 nuts.getprev              = direct.getprev
 nuts.getid                = direct.getid
-nuts.getattr              = direct.has_attribute or direct.getfield
+nuts.getattr              = direct.get_attribute or direct.has_attribute or direct.getfield
 nuts.getchar              = direct.getchar
 nuts.getfont              = direct.getfont
 nuts.getsubtype           = direct.getsubtype
@@ -173,6 +173,7 @@ nuts.new                  = direct.new
 nuts.tail                 = direct.tail
 nuts.traverse             = direct.traverse
 nuts.traverse_id          = direct.traverse_id
+nuts.traverse_char        = direct.traverse_char
 nuts.slide                = direct.slide
 nuts.writable_spec        = direct.writable_spec
 nuts.vpack                = direct.vpack
@@ -180,7 +181,6 @@ nuts.is_node              = direct.is_node
 nuts.is_direct            = direct.is_direct
 nuts.is_nut               = direct.is_direct
 nuts.first_glyph          = direct.first_glyph
-nuts.first_character      = direct.first_character
 nuts.has_glyph            = direct.has_glyph or direct.first_glyph
 
 nuts.current_attr         = direct.current_attr
@@ -196,8 +196,10 @@ nuts.set_attribute        = direct.set_attribute
 nuts.unset_attribute      = direct.unset_attribute
 
 nuts.protect_glyphs       = direct.protect_glyphs
+nuts.protect_glyph        = direct.protect_glyph
 nuts.unprotect_glyphs     = direct.unprotect_glyphs
-
+nuts.ligaturing           = direct.ligaturing
+nuts.kerning              = direct.kerning
 nuts.effective_glue       = direct.effective_glue
 
 if not nuts.effective_glue then
@@ -226,7 +228,7 @@ end
 
 -- placeholders
 
-if not direct.kerning then
+if not nuts.kerning then
 
     local n_kerning = node.kerning
 
@@ -236,7 +238,7 @@ if not direct.kerning then
 
 end
 
-if not direct.ligaturing then
+if not nuts.ligaturing then
 
     local n_ligaturing = node.ligaturing
 
@@ -256,102 +258,6 @@ if not direct.mlist_to_hlist then
 
 end
 
--- new, a few experimental extra helpers that can speed up font handling 15%
--- especially a mix of complex (latin) features and discretionaries or complex
--- scripts with lots of contextual chains (for other use there is not that
--- much gain)
-
-if not direct.getdisc then
-
-    local getid      = nuts.getid
-    local getsubtype = nuts.getsubtype
-    local getfont    = nuts.getfont
-    local getfield   = nuts.getfield
-    local setfield   = nuts.setfield
-    local findtail   = nuts.tail
-
-    local glyph_code = nodecodes.glyph
-
-    -- this one saves finding tails (i.e. extra calls and passes)
-
-    function direct.getdisc(n,tailtoo)
-        local pre     = getfield(n,"pre")
-        local post    = getfield(n,"post")
-        local replace = getfield(n,"replace")
-        if tailtoo then
-            return pre, post, replace,
-                pre     and findtail(pre),
-                post    and findtail(post),
-                replace and findtail(replace)
-
-        else
-            return pre, post, replace
-        end
-    end
-
-    -- this one is more efficient than three assignments and we need to
-    -- do it in order to updat ethe internal tail data (will change)
-
-    function direct.setdisc(n,pre,post,replace,subtype,penalty)
-        setfield(n,"pre",pre)
-        setfield(n,"post",post)
-        setfield(n,"replace",replace)
-        if subtype then
-            setfield(n,"subtype",subtype)
-        end
-        if penalty then
-         -- setfield(n,"penalty",penalty)
-        end
-    end
-
-    -- very small speedup but more convenient
-
-    function direct.setchar(n,chr)
-        setfield(n,"char",chr)
-    end
-
-    function direct.setnext(n,next)
-        setfield(n,"next",next)
-    end
-
-    function direct.setprev(g,prev)
-        setfield(n,"prev",prev)
-    end
-
-    function direct.setboth(n,prev,next)
-        if n then
-            setfield(n,"next",next)
-            setfield(n,"prev",prev)
-        end
-    end
-
-    function direct.getboth(n)
-        if n then
-            return getfield(n,"prev"), getfield(n,"prev")
-        end
-    end
-
-    function direct.setlink(a,b)
-        if a then
-            if b then
-                setfield(a,"next",b)
-                setfield(b,"prev",a)
-            else
-                setfield(a,"next",nil)
-            end
-        elseif b then
-            setfield(b,"prev",nil)
-        end
-    end
-
-    -- this one saves a lot (one call instead of 3)
-
-    function direct.is_char(g,font)
-        return getid(g) == glyph_code and getsubtype(g) < 256 and (not font or getfont(g) == font)
-    end
-
-end
-
 nuts.getdisc = direct.getdisc
 nuts.setdisc = direct.setdisc
 nuts.setchar = direct.setchar
@@ -362,8 +268,6 @@ nuts.getboth = direct.getboth
 nuts.setlink = direct.setlink
 nuts.is_char = direct.is_char
 
---
-
 local d_remove_node     = direct.remove
 local d_free_node       = direct.free
 local d_getfield        = direct.getfield
diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua
index 7650c0e50..c7f68cf16 100644
--- a/tex/context/base/node-pro.lua
+++ b/tex/context/base/node-pro.lua
@@ -101,46 +101,46 @@ function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direc
     return true
 end
 
-local enabled = true
-
-function processors.hpack_filter(head,groupcode,size,packtype,direction)
-    if enabled then
-     -- local first, found = first_glyph(head) -- they really need to be glyphs
-        local found = force_processors or has_glyph(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
+local function hpack_filter(head,groupcode,size,packtype,direction)
+ -- local first, found = first_glyph(head) -- they really need to be glyphs
+    local found = force_processors or has_glyph(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
-                local head, done = actions(head,groupcode,size,packtype,direction)
-                return done and head or true
+                tracer("hpack","unchanged",head,groupcode,before,after,true)
             end
-        elseif trace_callbacks then
-            local n = nodes.count(head,false)
-            tracer("hpack","no chars",head,groupcode,n,n)
+            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
 
+processors.hpack_filter = hpack_filter
+
 do
 
     local setfield = nodes.setfield
     local hpack    = nodes.hpack
 
-    function nodes.fasthpack(...) -- todo: pass explicit arguments
-        enabled = false
-        local hp, b = hpack(...)
+    function nodes.fullhpack(head,...)
+        local ok = hpack_filter(head)
+        if not done or done == true then
+            ok = head
+        end
+        local hp, b = hpack(ok,...)
         setfield(hp,"prev",nil)
         setfield(hp,"next",nil)
-        enabled = true
         return hp, b
     end
 
@@ -148,15 +148,18 @@ end
 
 do
 
-    local setfield = nuts.setfield
-    local hpack    = nuts.hpack
+    local setboth = nuts.setboth
+    local hpack   = nuts.hpack
 
-    function nuts.fasthpack(...) -- todo: pass explicit arguments
-        enabled = false
+    function nuts.fullhpack(head,...)
+        local ok = hpack_filter(tonode(head))
+        if not done or done == true then
+            ok = head
+        else
+            ok = tonut(ok)
+        end
         local hp, b = hpack(...)
-        setfield(hp,"prev",nil)
-        setfield(hp,"next",nil)
-        enabled = true
+        setboth(hp)
         return hp, b
     end
 
diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua
index 633cfd4a6..58e62067f 100644
--- a/tex/context/base/node-ref.lua
+++ b/tex/context/base/node-ref.lua
@@ -264,12 +264,10 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
                     if prev and getid(prev) == glue_code and getsubtype(prev) == parfillskip_code then
                         width = dimensions(current,first,getprev(prev)) -- maybe not current as we already take care of it
                     else
-                        if moveright and getfield(first,"writable") then
-                            width = width - getfield(getfield(first,"spec"),"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
-                        end
-                        if getfield(last,"writable") then
-                            width = width - getfield(getfield(last,"spec"),"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
+                        if moveright then
+                            width = width - getfield(first,"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
                         end
+                        width = width - getfield(last,"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
                     end
                 end
             else
@@ -448,12 +446,10 @@ local function addstring(what,str,shift) --todo make a pluggable helper (in font
                 str   = str .. " "
                 shift = (shift or 2) * exheight
             end
-            local text = typesetters.fast_hpack(str,infofont)
+            local text = typesetters.tohpack(str,infofont)
             local rule = new_rule(emwidth/5,4*exheight,3*exheight)
             setfield(text,"shift",shift)
-            return nuts.fasthpack(nuts.linked(text,rule))
-         -- local text = typesetters.fast_hpack(str,fonts.infofont())
-         -- return text
+            return hpack_list(nuts.linked(text,rule))
         end
     end
 end
diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua
index 10144399c..401a429bb 100644
--- a/tex/context/base/node-res.lua
+++ b/tex/context/base/node-res.lua
@@ -167,13 +167,16 @@ local hlist             = register_nut(new_nut("hlist")) setfield(hlist,"dir","T
 local vlist             = register_nut(new_nut("vlist")) setfield(vlist,"dir","TLT")
 
 function nutpool.zeroglue(n)
-    local s = getfield(n,"spec")
-    return
-        getfield(s,"width")         == 0 and
-        getfield(s,"stretch")       == 0 and
-        getfield(s,"shrink")        == 0 and
-        getfield(s,"stretch_order") == 0 and
-        getfield(s,"shrink_order")  == 0
+    if n then
+        return
+            getfield(n,"width")         == 0 and
+            getfield(n,"stretch")       == 0 and
+            getfield(n,"shrink")        == 0 and
+            getfield(n,"stretch_order") == 0 and
+            getfield(n,"shrink_order")  == 0
+    else
+        return false
+    end
 end
 
 function nutpool.glyph(fnt,chr)
@@ -203,11 +206,21 @@ end
 
 function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
     local s = copy_nut(glue_spec)
-    if width         then setfield(s,"width",width)                 end
-    if stretch       then setfield(s,"stretch",stretch)             end
-    if shrink        then setfield(s,"shrink",shrink)               end
-    if stretch_order then setfield(s,"stretch_order",stretch_order) end
-    if shrink_order  then setfield(s,"shrink_order",shrink_order)   end
+    if width and width ~= 0 then
+        setfield(s,"width",width)
+    end
+    if stretch and stretch ~= 0 then
+        setfield(s,"stretch",stretch)
+    end
+    if shrink and shrink ~= 0 then
+        setfield(s,"shrink",shrink)
+    end
+    if stretch_order and stretch_order ~= 0 then
+        setfield(s,"stretch_order",stretch_order)
+    end
+    if shrink_order and shrink_order ~= 0 then
+        setfield(s,"shrink_order",shrink_order)
+    end
     return s
 end
 
@@ -217,11 +230,21 @@ local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
         -- no spec
     elseif width == false or tonumber(width) then
         local s = copy_nut(glue_spec)
-        if width         then setfield(s,"width",width)                 end
-        if stretch       then setfield(s,"stretch",stretch)             end
-        if shrink        then setfield(s,"shrink",shrink)               end
-        if stretch_order then setfield(s,"stretch_order",stretch_order) end
-        if shrink_order  then setfield(s,"shrink_order",shrink_order)   end
+        if width and width ~= 0 then
+            setfield(s,"width",width)
+        end
+        if stretch and stretch ~= 0 then
+            setfield(s,"stretch",stretch)
+        end
+        if shrink and shrink ~= 0 then
+            setfield(s,"shrink",shrink)
+        end
+        if stretch_order and stretch_order ~= 0 then
+            setfield(s,"stretch_order",stretch_order)
+        end
+        if shrink_order and shrink_order ~= 0 then
+            setfield(s,"shrink_order",shrink_order)
+        end
         setfield(n,"spec",s)
     else
         -- shared
@@ -268,9 +291,15 @@ function nutpool.negatedglue(glue)
     local width   = getfield(s,"width")
     local stretch = getfield(s,"stretch")
     local shrink  = getfield(s,"shrink")
-    if width   then setfield(s,"width",  -width)   end
-    if stretch then setfield(s,"stretch",-stretch) end
-    if shrink  then setfield(s,"shrink", -shrink)  end
+    if width and width ~= 0 then
+        setfield(s,"width",  -width)
+    end
+    if stretch and stretch ~= 0 then
+        setfield(s,"stretch",-stretch)
+    end
+    if shrink and shrink ~= 0 then
+        setfield(s,"shrink", -shrink)
+    end
     setfield(n,"spec",s)
     return n
 end
@@ -303,10 +332,18 @@ end
 
 function nutpool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt
     local n = copy_nut(rule)
-    if width  then setfield(n,"width",width)   end
-    if height then setfield(n,"height",height) end
-    if depth  then setfield(n,"depth",depth)   end
-    if dir    then setfield(n,"dir",dir)       end
+    if width then -- also 0 else adapt
+        setfield(n,"width",width)
+    end
+    if height then -- also 0 else adapt
+        setfield(n,"height",height)
+    end
+    if depth then -- also 0 else adapt
+        setfield(n,"depth",depth)
+    end
+    if dir then
+        setfield(n,"dir",dir)
+    end
     return n
 end
 
@@ -399,7 +436,7 @@ function nutpool.leftmarginkern(glyph,width)
     else
         setfield(n,"glyph",glyph)
     end
-    if width then
+    if width and width ~= 0 then
         setfield(n,"width",width)
     end
     return n
@@ -414,7 +451,7 @@ function nutpool.rightmarginkern(glyph,width)
     else
         setfield(n,"glyph",glyph)
     end
-    if width then
+    if width and width ~= 0 then
         setfield(n,"width",width)
     end
     return n
@@ -433,16 +470,16 @@ function nutpool.hlist(list,width,height,depth,shift)
     if list then
         setfield(n,"list",list)
     end
-    if width then
+    if width and width ~= 0 then
         setfield(n,"width",width)
     end
-    if height then
+    if height and height ~= 0 then
         setfield(n,"height",height)
     end
-    if depth then
+    if depth and depth ~= 0 then
         setfield(n,"depth",depth)
     end
-    if shift then
+    if shift and shift ~= 0 then
         setfield(n,"shift",shift)
     end
     return n
@@ -453,16 +490,16 @@ function nutpool.vlist(list,width,height,depth,shift)
     if list then
         setfield(n,"list",list)
     end
-    if width then
+    if width and width ~= 0 then
         setfield(n,"width",width)
     end
-    if height then
+    if height and height ~= 0 then
         setfield(n,"height",height)
     end
-    if depth then
+    if depth and depth ~= 0 then
         setfield(n,"depth",depth)
     end
-    if shift then
+    if shift and shift ~= 0 then
         setfield(n,"shift",shift)
     end
     return n
@@ -582,7 +619,10 @@ statistics.register("cleaned up reserved nodes", function()
 end) -- \topofboxstack
 
 statistics.register("node memory usage", function() -- comes after cleanup !
-    return status.node_mem_usage
+    local usage = status.node_mem_usage
+    if usage ~= "" then
+        return usage
+    end
 end)
 
 lua.registerfinalizer(cleanup, "cleanup reserved nodes")
diff --git a/tex/context/base/node-rul.mkiv b/tex/context/base/node-rul.mkiv
index 7fa0473a5..9899a5775 100644
--- a/tex/context/base/node-rul.mkiv
+++ b/tex/context/base/node-rul.mkiv
@@ -101,7 +101,8 @@
 
 \appendtoks
     \ifcsname\??barindex\currentbar\endcsname
-        \csname\??barindex\currentbar\endcsname\zerocount
+       %\csname\??barindex\currentbar\endcsname\zerocount
+        \lastnamedcs
     \else
         \expandafter\newcount\csname\??barindex\currentbar\endcsname
     \fi
@@ -141,13 +142,15 @@
 %\unexpanded\def\node_rules_set_indeed#1% maybe reverse the 1000 (also maybe use more attributes instead of settings)
 
 \unexpanded\def\node_rules_set#1% maybe reverse the 1000 (also maybe use more attributes instead of settings)
-  {\clf_enablerules % will be relaxed
-   \edef\currentbar{#1}%
+  {\edef\currentbar{#1}%
+   \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor
+   % todo: move this to lua .. we callout anyway
    \expandafter\let\expandafter\c_node_rules_index\csname\??barindex#1\endcsname
    \advance\c_node_rules_index\plusone
-   \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor
+   \clf_enablerules % will be relaxed
    \attribute\ruledattribute\numexpr
       \plusthousand*\c_node_rules_index
+      % optimizing this one needs testing
      +\csname\??barattribute#1\ifcsname\??bar#1:\number\c_node_rules_index\s!parent\endcsname:\number\c_node_rules_index\fi\endcsname
    \relax}
 
@@ -275,7 +278,8 @@
 
 \appendtoks
     \ifcsname\??shiftindex\currentshift\endcsname
-        \csname\??shiftindex\currentshift\endcsname\zerocount
+       %\csname\??shiftindex\currentshift\endcsname\zerocount
+        \lastnamedcs\zerocount
     \else
         \expandafter\newcount\csname\??shiftindex\currentshift\endcsname
     \fi
@@ -303,9 +307,8 @@
 %
 % \def\node_shifts_set_indeed#1% todo: check parent !
 
-\unexpanded\def\node_shifts_set#1% todo: check parent !
-  {\clf_enableshifts
-   \def\currentshift{#1}%
+\unexpanded\def\node_shifts_set#1% todo: check parent ! todo: move attr etc to lua
+  {\def\currentshift{#1}%
    \expandafter\let\expandafter\c_node_shifts_index\csname\??shiftindex#1\endcsname
    \advance\c_node_shifts_index\plusone
    \attribute\shiftedattribute\numexpr
diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua
index 0692c1fe6..e68228fe8 100644
--- a/tex/context/base/node-tra.lua
+++ b/tex/context/base/node-tra.lua
@@ -313,8 +313,7 @@ local function listtoutf(h,joiner,textonly,last,nodisc)
             end
         elseif textonly then
             if id == glue_code then
-                local spec = getfield(h,"spec")
-                if spec and getfield(spec,"width") > 0 then
+                if getfield(h,"width") > 0 then
                     w[#w+1] = " "
                 end
             elseif id == hlist_code or id == vlist_code then
@@ -362,93 +361,6 @@ local ptfactor = dimenfactors.pt
 local bpfactor = dimenfactors.bp
 local stripper = lpeg.patterns.stripzeros
 
--- start redefinition
---
--- -- if fmt then
--- --     return formatters[fmt](n*dimenfactors[unit],unit)
--- -- else
--- --     return match(formatters["%.20f"](n*dimenfactors[unit]),"(.-0?)0*$") .. unit
--- -- end
---
--- redefined:
-
--- local function nodetodimen(d,unit,fmt,strip)
---     d = tonut(d) -- tricky: direct nuts are an issue
---     if unit == true then
---         unit = "pt"
---         fmt  = "%0.5f%s"
---     else
---         unit = unit or 'pt'
---         if not fmt then
---             fmt = "%s%s"
---         elseif fmt == true then
---             fmt = "%0.5f%s"
---         end
---     end
---     local id = getid(d)
---     if id == kern_code then
---         local str = formatters[fmt](getfield(d,"width")*dimenfactors[unit],unit)
---         return strip and lpegmatch(stripper,str) or str
---     end
---     if id == glue_code then
---         d = getfield(d,"spec")
---     end
---     if not d or not getid(d) == gluespec_code then
---         local str = formatters[fmt](0,unit)
---         return strip and lpegmatch(stripper,str) or str
---     end
---     local width   = getfield(d,"width")
---     local plus    = getfield(d,"stretch_order")
---     local minus   = getfield(d,"shrink_order")
---     local stretch = getfield(d,"stretch")
---     local shrink  = getfield(d,"shrink")
---     if plus ~= 0 then
---         plus = " plus " .. stretch/65536 .. fillcodes[plus]
---     elseif stretch ~= 0 then
---         plus = formatters[fmt](stretch*dimenfactors[unit],unit)
---         plus = " plus " .. (strip and lpegmatch(stripper,plus) or plus)
---     else
---         plus = ""
---     end
---     if minus ~= 0 then
---         minus = " minus " .. shrink/65536 .. fillcodes[minus]
---     elseif shrink ~= 0 then
---         minus = formatters[fmt](shrink*dimenfactors[unit],unit)
---         minus = " minus " .. (strip and lpegmatch(stripper,minus) or minus)
---     else
---         minus = ""
---     end
---     local str = formatters[fmt](getfield(d,"width")*dimenfactors[unit],unit)
---     return (strip and lpegmatch(stripper,str) or str) .. plus .. minus
--- end
---
--- local function numbertodimen(d,unit,fmt,strip)
---     if not d then
---         local str = formatters[fmt](0,unit)
---         return strip and lpegmatch(stripper,str) or str
---     end
---     local t = type(d)
---     if t == 'string' then
---         return d
---     elseif t == "number" then
---         if unit == true then
---             unit = "pt"
---             fmt  = "%0.5f%s"
---         else
---             unit = unit or 'pt'
---             if not fmt then
---                 fmt = "%s%s"
---             elseif fmt == true then
---                 fmt = "%0.5f%s"
---             end
---         end
---         local str = formatters[fmt](d*dimenfactors[unit],unit)
---         return strip and lpegmatch(stripper,str) or str
---     else
---         return nodetodimen(d,unit,fmt,strip) -- real node
---     end
--- end
-
 local f_f_f = formatters["%0.5Fpt plus %0.5F%s minus %0.5F%s"]
 local f_f_m = formatters["%0.5Fpt plus %0.5F%s minus %0.5Fpt"]
 local f_p_f = formatters["%0.5Fpt plus %0.5Fpt minus %0.5F%s"]
diff --git a/tex/context/base/node-tst.lua b/tex/context/base/node-tst.lua
index 7f5102d5f..4832c048c 100644
--- a/tex/context/base/node-tst.lua
+++ b/tex/context/base/node-tst.lua
@@ -39,7 +39,7 @@ function nuts.leftmarginwidth(n) -- todo: three values
     while n do
         local id = getid(n)
         if id == glue_code then
-            return getsubtype(n) == leftskip_code and getfield(getfield(n,"spec"),"width") or 0
+            return getsubtype(n) == leftskip_code and getfield(n,"width") or 0
         elseif id == whatsit_code then
             n = getnext(n)
         elseif id == hlist_code then
@@ -57,7 +57,7 @@ function nuts.rightmarginwidth(n)
         while n do
             local id = getid(n)
             if id == glue_code then
-                return getsubtype(n) == rightskip_code and getfield(getfield(n,"spec"),"width") or 0
+                return getsubtype(n) == rightskip_code and getfield(n,"width") or 0
             elseif id == whatsit_code then
                 n = getprev(n)
             else
@@ -72,7 +72,8 @@ function nuts.somespace(n,all)
     if n then
         local id = getid(n)
         if id == glue_code then
-            return (all or (getfield(getfield(n,"spec"),"width") ~= 0)) and glue_code
+            return (all or ((getfield(n,"width") or 0) ~= 0)) and glue_code -- temp: or 0
+         -- return (all or (getfield(n,"width") ~= 0)) and glue_code
         elseif id == kern_code then
             return (all or (getfield(n,"kern") ~= 0)) and kern
         elseif id == glyph_code then
diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua
index 6c5577f08..2d84e07a3 100644
--- a/tex/context/base/node-typ.lua
+++ b/tex/context/base/node-typ.lua
@@ -19,11 +19,12 @@ local setfield        = nuts.setfield
 local setlink         = nuts.setlink
 local setchar         = nuts.setchar
 
+local getfield        = nuts.getfield
 local getfont         = nuts.getfont
 
 local hpack_node_list = nuts.hpack
 local vpack_node_list = nuts.vpack
-local fast_hpack_list = nuts.fasthpack
+local full_hpack_list = nuts.fullhpack
 local copy_node       = nuts.copy
 
 local nodepool        = nuts.pool
@@ -33,15 +34,19 @@ local new_glue        = nodepool.glue
 local utfvalues       = utf.values
 
 local currentfont     = font.current
+local currentattr     = node.current_attr
 local fontparameters  = fonts.hashes.parameters
 
 local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty
     local head, prev = nil, nil
+--     local attrid = nil
     if not fontid then
         if templateglyph then
             fontid = getfont(templateglyph)
+--             attrid = getfield(templateglyph,"attr")
         else
             fontid = currentfont()
+--             attrid = currentattr()
         end
     end
     local fp = fontparameters[fontid]
@@ -70,8 +75,10 @@ local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty
         if not next then
             -- nothing
         elseif not head then
+-- setfield(next,"attr",attrid)
             head = next
         else
+-- setfield(next,"attr",attrid)
             setlink(prev,next)
         end
         prev = next
@@ -83,42 +90,40 @@ local function tohpack(str,fontid,spacing)
     return hpack_node_list(tonodes(str,fontid,spacing),"exactly")
 end
 
-local function tohpackfast(str,fontid,spacing)
-    return fast_hpack_list(tonodes(str,fontid,spacing),"exactly")
+local function tohbox(str,fontid,spacing)
+    return full_hpack_list(tonodes(str,fontid,spacing),"exactly")
 end
 
 local function tovpack(str,fontid,spacing)
-    -- vpack is just a hack, and a proper implentation is on the agenda
+    -- vpack is just a hack, and a proper implemtation is on the agenda
     -- as it needs more info etc than currently available
     return vpack_node_list(tonodes(str,fontid,spacing))
 end
 
-local tovpackfast = tovpack
+local tovbox = tovpack -- for now no vpack filter
 
 local tnuts       = { }
 nuts.typesetters  = tnuts
 
 tnuts.tonodes     = tonodes
 tnuts.tohpack     = tohpack
-tnuts.tohpackfast = tohpackfast
+tnuts.tohbox      = tohbox
 tnuts.tovpack     = tovpack
-tnuts.tovpackfast = tovpackfast
-
-tnuts.hpack       = tohpack     -- obsolete
-tnuts.fast_hpack  = tohpackfast -- obsolete
-tnuts.vpack       = tovpack     -- obsolete
-
-typesetters.tonodes     = function(...) local h, b = tonodes    (...) return tonode(h), b end
-typesetters.tohpack     = function(...) local h, b = tohpack    (...) return tonode(h), b end
-typesetters.tohpackfast = function(...) local h, b = tohpackfast(...) return tonode(h), b end
-typesetters.tovpack     = function(...) local h, b = tovpack    (...) return tonode(h), b end
-typesetters.tovpackfast = function(...) local h, b = tovpackfast(...) return tonode(h), b end
-
-typesetters.hpack       = typesetters.tohpack     -- obsolete
-typesetters.fast_hpack  = typesetters.tofasthpack -- obsolete
-typesetters.vpack       = typesetters.tovpack     -- obsolete
-
--- node.write(nodes.typesetters.hpack("Hello World!"))
--- node.write(nodes.typesetters.hpack("Hello World!",1,100*1024*10))
+tnuts.tovbox      = tovbox
+
+typesetters.tonodes  = function(...) local h, b = tonodes(...) return tonode(h), b end
+typesetters.tohpack  = function(...) local h, b = tohpack(...) return tonode(h), b end
+typesetters.tohbox   = function(...) local h, b = tohbox (...) return tonode(h), b end
+typesetters.tovpack  = function(...) local h, b = tovpack(...) return tonode(h), b end
+typesetters.tovbox   = function(...) local h, b = tovbox (...) return tonode(h), b end
+
+typesetters.hpack    = typesetters.tohpack  -- obsolete
+typesetters.hbox     = typesetters.tohbox   -- obsolete
+typesetters.vpack    = typesetters.tovpack  -- obsolete
+
+-- node.write(nodes.typesetters.tohpack("Hello World!"))
+-- node.write(nodes.typesetters.tohbox ("Hello World!"))
+-- node.write(nodes.typesetters.tohpack("Hello World!",1,100*1024*10))
+-- node.write(nodes.typesetters.tohbox ("Hello World!",1,100*1024*10))
 
 string.tonodes = function(...) return tonode(tonodes(...)) end  -- quite convenient
diff --git a/tex/context/base/pack-bck.mkvi b/tex/context/base/pack-bck.mkvi
index 53cdf6de4..430339f6d 100644
--- a/tex/context/base/pack-bck.mkvi
+++ b/tex/context/base/pack-bck.mkvi
@@ -201,9 +201,9 @@
 \definebackground[\v!background]
 
 \ifdefined\startbackground \else
-    \expandafter\let\startbackground\csname\e!start\v!background\endcsname
-    \expandafter\let\stopbackground \csname\e!stop \v!background\endcsname
-    \expandafter\let\background     \csname        \v!background\endcsname
+    \expandafter\let\expandafter\startbackground\csname\e!start\v!background\endcsname
+    \expandafter\let\expandafter\stopbackground \csname\e!stop \v!background\endcsname
+    \expandafter\let\expandafter\background     \csname        \v!background\endcsname
 \fi
 
 \setupbackground
diff --git a/tex/context/base/pack-box.mkiv b/tex/context/base/pack-box.mkiv
index c5f3940f5..c48f4cbd1 100644
--- a/tex/context/base/pack-box.mkiv
+++ b/tex/context/base/pack-box.mkiv
@@ -147,7 +147,8 @@
 
 \unexpanded\def\resetcollector[#1]%
   {\ifcsname\??collectorbox#1\endcsname
-     \global\setbox\csname\??collectorbox#1\endcsname\emptybox
+    %\global\setbox\csname\??collectorbox#1\endcsname\emptybox
+     \global\setbox\lastnamedcs\emptybox
    \fi}
 
 \newconditional\c_pack_boxes_collector_valid_box
@@ -158,7 +159,8 @@
   {\edef\currentcollector{#1}%
    \ifcsname\??collectorbox\currentcollector\endcsname
      \settrue\c_pack_boxes_collector_valid_box
-     \expandafter\let\expandafter\b_pack_boxes_collector\csname\??collectorbox\currentcollector\endcsname
+    %\expandafter\let\expandafter\b_pack_boxes_collector\csname\??collectorbox\currentcollector\endcsname
+     \expandafter\let\expandafter\b_pack_boxes_collector\lastnamedcs
    \else
      \setfalse\c_pack_boxes_collector_valid_box
      \writestatus{collector}{unknown collector \currentcollector}%
@@ -209,14 +211,15 @@
 
 \def\pack_boxes_collector_check_corner#1%
   {\ifcsname\??collectorcorners#1\endcsname
-     \csname\??collectorcorners#1\endcsname
+    %\csname\??collectorcorners#1\endcsname
+     \lastnamedcs
    \fi}
 
 \def\pack_boxes_collector_finish
   {\edef\p_collector_rotation{\collectorparameter\c!rotation}%
    \edef\p_collector_corner  {\collectorparameter\c!corner}%
    \ifx\p_collector_rotation\empty \else
-     \setbox\nextbox\hbox
+     \setbox\nextbox\hpack
        {\rotate
           [\c!location=\v!high,
            \c!rotation=\p_collector_rotation]
@@ -227,24 +230,24 @@
    \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax
    \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax
    \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner
-   \setbox\nextbox\hbox
-     {\alignedbox[\collectorparameter\c!location]\vbox{\box\nextbox}}%
+   \setbox\nextbox\hpack
+     {\alignedbox[\collectorparameter\c!location]\vpack{\box\nextbox}}%
    \boxmaxdepth\zeropoint % really needed, nice example
    \global\advance\boxhdisplacement\d_pack_layers_x_position
    \ifdim\boxhdisplacement<\zeropoint
-     \global\setbox\b_pack_boxes_collector\hbox
+     \global\setbox\b_pack_boxes_collector\hpack
        {\kern-\boxhdisplacement
         \box\b_pack_boxes_collector}%
    \fi
    \global\advance\boxvdisplacement\d_pack_layers_y_position
    \ifdim\boxvdisplacement<\zeropoint
-     \global\setbox\b_pack_boxes_collector\hbox
+     \global\setbox\b_pack_boxes_collector\hpack
        {\lower-\boxvdisplacement
         \box\b_pack_boxes_collector}%
    \fi
    \d_pack_layers_x_size\wd\b_pack_boxes_collector
    \d_pack_layers_y_size\htdp\b_pack_boxes_collector
-   \global\setbox\b_pack_boxes_collector\hbox
+   \global\setbox\b_pack_boxes_collector\hpack
      {\box\b_pack_boxes_collector
       \kern\dimexpr
         -\d_pack_layers_x_size
@@ -253,13 +256,13 @@
            -\boxhdisplacement
          \fi
       \relax
-      \lower\d_pack_layers_y_position\hbox
+      \lower\d_pack_layers_y_position\hpack
         {\ifdim\boxvdisplacement<\zeropoint
            \lower-\boxvdisplacement
          \fi
          \box\nextbox}}%
    % combine height and depth into depth only (later flushed as height)
-   \global\setbox\b_pack_boxes_collector\hbox
+   \global\setbox\b_pack_boxes_collector\hpack
      {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}%
    % just to be sure
    \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size
@@ -273,7 +276,7 @@
    \ifconditional\c_pack_boxes_collector_valid_box
      \edef\p_collector_state{\collectorparameter\c!state}%
      \ifx\p_collector_state\v!stop \else
-       \vbox{\hbox{\raise
+       \vpack{\hpack{\raise
          \dp\b_pack_boxes_collector
          \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}%
      \fi
@@ -588,13 +591,13 @@
 \def\pack_boxes_bleed_finish
   {\doif{\bleedingparameter\c!page}\v!yes
      {\setbox\nextbox\topskippedbox{\box\nextbox}}%
-   \setbox\nextbox\hbox to \scratchwidth
+   \setbox\nextbox\hpack to \scratchwidth
      {\ifconditional\c_pack_boxes_l\hss\fi
       \box\nextbox
       \ifconditional\c_pack_boxes_r\hss\fi}%
    \ifconditional\c_pack_boxes_b
-     \setbox\nextbox\hbox
-       {\lower\bleedheight\hbox{\raise\scratchheight\box\nextbox}}%
+     \setbox\nextbox\hpack
+       {\lower\bleedheight\hpack{\raise\scratchheight\box\nextbox}}%
    \fi
    \wd\nextbox\scratchwidth
    \ht\nextbox\scratchheight
@@ -763,10 +766,18 @@
 \def\pack_boxes_aligned_box[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish}
 \def\pack_boxes_aligned    [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox}
 
+% \def\pack_boxes_aligned_finish
+%   {\csname\??alignedboxes
+%      \ifcsname\??alignedboxes\serializedcommalist\endcsname\serializedcommalist\else\v!middle\fi
+%    \endcsname{\flushnextbox}%
+%    \egroup}
+
 \def\pack_boxes_aligned_finish
-  {\csname\??alignedboxes
-     \ifcsname\??alignedboxes\serializedcommalist\endcsname\serializedcommalist\else\v!middle\fi
-   \endcsname{\flushnextbox}%
+  {\ifcsname\??alignedboxes\serializedcommalist\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\middlebox
+   \fi{\flushnextbox}%
    \egroup}
 
 \letvalue{\??alignedboxes                  }\middlebox
@@ -888,11 +899,11 @@
      \fi
    \fi
    \ifdone
-     \setbox\nextbox\vbox
+     \setbox\nextbox\vpack
        {\forgetall % already done
         \offinterlineskip
         \kern\scratchtopoffset
-        \hbox
+        \hpack
           {\kern\scratchleftoffset
            \box\nextbox
            \kern\scratchrightoffset}%
@@ -904,13 +915,13 @@
    \scratchheight\offsetboxparameter\c!height
    \scratchdepth \offsetboxparameter\c!depth
    \edef\p_location{\offsetboxparameter\c!location}%
-   \setbox\nextbox\hbox
+   \setbox\nextbox\hpack
      {\kern\scratchxposition
-      \lower\scratchyposition\hbox
+      \lower\scratchyposition\hpack
         {\ifx\p_location\empty
            \box\nextbox
          \else
-           \alignedbox[\p_location]\hbox{\box\nextbox}%
+           \alignedbox[\p_location]\hpack{\box\nextbox}%
          \fi}}%
    \wd\nextbox\scratchwidth
    \ht\nextbox\scratchheight
@@ -955,8 +966,8 @@
 \def\pack_boxes_tabbed#1#2#3#4%
   {\dontleavehmode
    \begingroup
-   \setbox\scratchbox\hbox{#3}%
-   \hbox to \wd\scratchbox{#1#4#2}%
+   \setbox\scratchbox\hpack{#3}%
+   \hpack to \wd\scratchbox{#1#4#2}%
    \endgroup}
 
 \unexpanded\def\ltabbed{\pack_boxes_tabbed\relax\hss}
@@ -968,7 +979,7 @@
 % to be documented
 
 \unexpanded\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{}
-  {\hbox\bgroup
+  {\hpack\bgroup
    \letdummyparameter\c!width \zeropoint
    \letdummyparameter\c!height\zeropoint
    \letdummyparameter\c!depth \zeropoint
@@ -1018,21 +1029,21 @@
      % to be considered: methods
      \ifcase\scratchcounter
      \or % x and y
-       \setbox\nextbox\hbox{\dorecurse\scratchnx{\copy\nextbox}}%
-       \setbox\nextbox\vbox{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
+       \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}%
+       \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
      \or % x
-       \setbox\nextbox\hbox{\dorecurse\scratchnx{\copy\nextbox}}%
+       \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}%
      \or % y
-       \setbox\nextbox\vbox{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
+       \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
      \fi
    \fi
    \ifdim\wd\nextbox>\scratchwidth
-     \setbox\nextbox\hbox to \scratchwidth{\hss\box\nextbox\hss}%
-     \setbox\nextbox\hbox{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
+     \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}%
+     \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
    \fi
    \ifdim\ht\nextbox>\scratchheight
-     \setbox\nextbox\vbox to \scratchheight{\vss\box\nextbox\vss}%
-     \setbox\nextbox\hbox{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
+     \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}%
+     \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
    \fi
    \box\nextbox
    \egroup}
@@ -1047,7 +1058,7 @@
 
 \def\pack_boxes_background_image_fill
   {\offinterlineskip
-   \setbox\nextbox\hbox\bgroup
+   \setbox\nextbox\hpack\bgroup
      \ifdim\scratchwidth>\scratchheight
        \scale[\c!width=\the\scratchwidth]{\box\nextbox}%
      \else
@@ -1055,7 +1066,7 @@
      \fi
    \egroup
    \ifdim\wd\nextbox>\scratchwidth
-     \setbox\nextbox\hbox to \scratchwidth
+     \setbox\nextbox\hpack to \scratchwidth
        {\ifcase\scratchcounter
           \hss\box\nextbox\hss
         \or
@@ -1065,10 +1076,11 @@
         \else
           \hss\box\nextbox\hss
         \fi}%
-     \setbox\nextbox\hbox{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
+     \setbox\nextbox\hpack
+       {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
    \fi
    \ifdim\ht\nextbox>\scratchheight
-     \setbox\nextbox\vbox to \scratchheight
+     \setbox\nextbox\vpack to \scratchheight
        {\ifcase\scratchcounter
           \vss\box\nextbox\vss
         \or
@@ -1078,7 +1090,8 @@
         \else
           \vss\box\nextbox\vss
         \fi}%
-     \setbox\nextbox\hbox{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
+     \setbox\nextbox\hpack
+       {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
    \fi
    \box\nextbox
    \egroup}
diff --git a/tex/context/base/pack-com.mkiv b/tex/context/base/pack-com.mkiv
index a3e43982d..623d669e7 100644
--- a/tex/context/base/pack-com.mkiv
+++ b/tex/context/base/pack-com.mkiv
@@ -422,8 +422,8 @@
    \egroup}
 
 \def\pack_combinations_save_caption
-  {\global\setbox\b_pack_combinations_captions\hbox
-     {\hbox{\box\b_pack_combinations_caption}%
+  {\global\setbox\b_pack_combinations_captions\hpack
+     {\hpack{\box\b_pack_combinations_caption}%
       \unhbox\b_pack_combinations_captions}}
 
 \def\pack_combinations_flush_captions
@@ -441,7 +441,7 @@
    \crcr}
 
 \def\pack_combinations_flush_captions_yes
-  {\global\setbox\b_pack_combinations_captions\hbox
+  {\global\setbox\b_pack_combinations_captions\hpack
      {\unhbox\b_pack_combinations_captions
       \global\setbox\b_pack_combinations_temp\lastbox}%
    \box\b_pack_combinations_temp
@@ -803,8 +803,8 @@
 \setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }}
 \setvalue{\??pairedboxalign   \v!top}{\getvalue{\??pairedboxalign\v!high}}
 
-\def\pack_pairedbox_valign#1{\setbox#1\vbox to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}}
-\def\pack_pairedbox_halign#1{\setbox#1\hbox to \s_pack_pairedboxes_size{\pack_pairedboxes_align_l\box#1\pack_pairedboxes_align_r}}
+\def\pack_pairedbox_valign#1{\setbox#1\vpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}}
+\def\pack_pairedbox_halign#1{\setbox#1\hpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_l\box#1\pack_pairedboxes_align_r}}
 
 \def\pack_pairedboxes_before
   {\ifx\p_location\empty
@@ -862,7 +862,7 @@
    \fi}
 
 \def\pack_pairedboxes_after
-  {\setbox\b_pack_pairedboxes_second\vbox
+  {\setbox\b_pack_pairedboxes_second\vpack
      {\ifnum\p_n>\plusone
         \rigidcolumnbalance\nextbox
       \else
@@ -896,7 +896,7 @@
    \egroup}
 
 \def\pack_pairedboxes_pack_vertical
-  {\dontleavehmode\vbox\bgroup
+  {\dontleavehmode\vpack\bgroup
      \forgetall
      \s_pack_pairedboxes_size\wd
        \ifdim\wd\b_pack_pairedboxes_first>\wd\b_pack_pairedboxes_second
@@ -915,7 +915,7 @@
        \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight\relax % \relax needed
      \fi
      \ifdim\s_pack_pairedboxes_size>\ht\b_pack_pairedboxes_second
-       \setbox\b_pack_pairedboxes_second\vbox to \s_pack_pairedboxes_size
+       \setbox\b_pack_pairedboxes_second\vpack to \s_pack_pairedboxes_size
          {\pack_pairedboxes_fill_top
           \box\b_pack_pairedboxes_second
           \pack_pairedboxes_fill_bottom}% \kern\zeropoint
diff --git a/tex/context/base/pack-cut.mkiv b/tex/context/base/pack-cut.mkiv
index 63f4524a8..ffd0251d5 100644
--- a/tex/context/base/pack-cut.mkiv
+++ b/tex/context/base/pack-cut.mkiv
@@ -93,7 +93,7 @@
         {\scratchdimen\dimexpr\cutmarklength/2\relax
          \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
          \normalvss
-         \hbox to \d_pack_cutmarks_width
+         \hpack to \d_pack_cutmarks_width
            {\llap{\copy\scratchbox\normalhskip\scratchskip}%
             \normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen
             \rlap{\normalhskip\scratchskip\copy\scratchbox}}%
@@ -116,7 +116,7 @@
         {\setbox\scratchbox\normalhbox{\horizontalcuts}%
          \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
          \tlap{\copy\scratchbox\normalvskip\scratchskip}%
-         \hbox to \d_pack_cutmarks_width
+         \hpack to \d_pack_cutmarks_width
            {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
             \setbox\scratchbox\normalhbox{\verticalcuts}%
             \llap{\copy\scratchbox\normalhskip\scratchskip}%
diff --git a/tex/context/base/pack-fen.mkiv b/tex/context/base/pack-fen.mkiv
index 04a36fa46..7bc821144 100644
--- a/tex/context/base/pack-fen.mkiv
+++ b/tex/context/base/pack-fen.mkiv
@@ -63,24 +63,24 @@
 
 \def\whateverleftframe#1%
   {\setinstalledframedimensions
-   \setbox\b_framed_rendered\vbox to \d_overlay_height{\vss#1\vss}%
-   \setbox\b_framed_rendered\hbox to \zeropoint{\box\b_framed_rendered\hss}%
+   \setbox\b_framed_rendered\vpack to \d_overlay_height{\vss#1\vss}%
+   \setbox\b_framed_rendered\hpack to \zeropoint{\box\b_framed_rendered\hss}%
    \ht\b_framed_rendered\zeropoint
    \dp\b_framed_rendered\zeropoint
    \box\b_framed_rendered}
 
 \def\whateverrightframe#1%
   {\setinstalledframedimensions
-   \setbox\b_framed_rendered\vbox to \d_overlay_height{\vss#1\vss}%
-   \setbox\b_framed_rendered\hbox to \zeropoint{\hss\box\b_framed_rendered}%
+   \setbox\b_framed_rendered\vpack to \d_overlay_height{\vss#1\vss}%
+   \setbox\b_framed_rendered\hpack to \zeropoint{\hss\box\b_framed_rendered}%
    \ht\b_framed_rendered\zeropoint
    \dp\b_framed_rendered\zeropoint
    \box\b_framed_rendered}
 
 \def\whatevertopframe#1%
   {\setinstalledframedimensions
-   \setbox\b_framed_rendered\hbox to \d_overlay_width{\hss#1\hss}%
-   \setbox\b_framed_rendered\vbox to \zeropoint{\box\b_framed_rendered\vss}%
+   \setbox\b_framed_rendered\hpack to \d_overlay_width{\hss#1\hss}%
+   \setbox\b_framed_rendered\vpack to \zeropoint{\box\b_framed_rendered\vss}%
    \ht\b_framed_rendered\zeropoint
    \dp\b_framed_rendered\zeropoint
    \box\b_framed_rendered
@@ -88,8 +88,8 @@
 
 \def\whateverbottomframe#1%
   {\setinstalledframedimensions
-   \setbox\b_framed_rendered\hbox to \d_overlay_width{\hss#1\hss}%
-   \setbox\b_framed_rendered\vbox to \zeropoint{\vss\box\b_framed_rendered}%
+   \setbox\b_framed_rendered\hpack to \d_overlay_width{\hss#1\hss}%
+   \setbox\b_framed_rendered\vpack to \zeropoint{\vss\box\b_framed_rendered}%
    \ht\b_framed_rendered\zeropoint
    \dp\b_framed_rendered\zeropoint
    \box\b_framed_rendered}
diff --git a/tex/context/base/pack-lyr.mkiv b/tex/context/base/pack-lyr.mkiv
index a847dec67..3d3638c3f 100644
--- a/tex/context/base/pack-lyr.mkiv
+++ b/tex/context/base/pack-lyr.mkiv
@@ -180,7 +180,8 @@
 
 \def\pack_layers_reset_box#1%
   {\ifcsname\??layerbox#1\endcsname
-     \global\setbox\csname\??layerbox#1\endcsname\emptybox
+    %\global\setbox\csname\??layerbox#1\endcsname\emptybox
+     \global\setbox\lastnamedcs\emptybox
    \fi}
 
 \def\resetlayer[#1]%
@@ -211,8 +212,11 @@
 % \def\thelayerwidth #1{\the\wd\executeifdefined{\??layerbox#1}\emptybox}
 % \def\thelayerheight#1{\the\ht\executeifdefined{\??layerbox#1}\emptybox}
 
-\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\csname\??layerbox#1\endcsname\else\zeropoint\fi}
-\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\csname\??layerbox#1\endcsname\else\zeropoint\fi}
+%def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\csname\??layerbox#1\endcsname\else\zeropoint\fi}
+%def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\csname\??layerbox#1\endcsname\else\zeropoint\fi}
+
+\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi}
+\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi}
 
 \unexpanded\def\setlayer
   {\dotripleempty\pack_layers_set}
@@ -222,7 +226,7 @@
    \edef\currentlayer{#1}%
    \edef\p_pack_layers_state{\layerparameter\c!state}%
    \ifx\p_pack_layers_state\v!stop
-     \dowithnextboxcs\egroup\hbox
+     \dowithnextboxcs\egroup\hbox % no pack ?
    \else\ifthirdargument
      \pack_layers_set_indeed[#1][#2][#3]%
    \else
@@ -272,19 +276,6 @@
 
 % todo: get position data in one go
 
-% \def\pack_layers_set_last_position_yes
-%   {\edef\m_pack_layers_page{\MPp{\??layerposition\the\c_pack_layers_current_data}}%
-%    \xdef\lastlayerxpos{\the\dimexpr-\MPx{\??layerposition\m_pack_layers_target\currentlayer:\m_pack_layers_page}+\MPx{\??layerposition\the\c_pack_layers_current_data}\relax}%
-%    \xdef\lastlayerypos{\the\dimexpr \MPy{\??layerposition\m_pack_layers_target\currentlayer:\m_pack_layers_page}-\MPy{\??layerposition\the\c_pack_layers_current_data}\relax}%}
-%    \d_pack_layers_x_position\lastlayerxpos
-%    \d_pack_layers_y_position\lastlayerypos
-%    \begingroup
-%      \edef\currentlayer{\currentlayer\m_pack_layers_page}%
-%      \global\letlayerparameter\c!position\v!yes
-%    \endgroup
-%    \global\letlayerparameter\c!state\v!start % needed ?
-%    \setbox\b_layers\vbox to \d_pack_layers_y_size{\hbox to \d_pack_layers_x_size{\xypos{\??layerposition\the\c_pack_layers_current_data}\hss}\vss}}
-
 \def\pack_layers_set_last_position_yes % target: left|right
   {% this will become one call
    \edef\m_pack_layers_anchor{\??layerposition\the\c_pack_layers_current_data}%
@@ -302,8 +293,8 @@
    %   \global\letlayerparameter\c!position\v!yes
    % \endgroup
    \global\letlayerparameter\c!state\v!start % needed ?
-   \setbox\b_layers\vbox to \d_pack_layers_y_size
-     {\hbox to \d_pack_layers_x_size
+   \setbox\b_layers\vpack to \d_pack_layers_y_size
+     {\hpack to \d_pack_layers_x_size
         {\xypos\m_pack_layers_anchor\hss}%
       \vss}}
 
@@ -335,7 +326,8 @@
    \edef\p_pack_layers_preset   {\layerparameter\c!preset  }%
    %
    \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
-     \csname\??layerpreset\p_pack_layers_preset\endcsname
+    %\csname\??layerpreset\p_pack_layers_preset\endcsname
+     \lastnamedcs
      \setupcurrentlayer[#1]% postroll
    \fi
    %
@@ -365,7 +357,8 @@
    \fi
    \ifx\p_pack_layers_rotation\empty \else
      % use direct call
-     \setbox\nextbox\hbox{\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\box\nextbox}}%
+     \setbox\nextbox\hpack
+       {\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\box\nextbox}}%
    \fi
    \d_pack_layers_x_offset\p_pack_layers_sx\dimexpr
      \ifx\p_pack_layers_hoffset\v!max\d_pack_layers_x_size\else\p_pack_layers_hoffset\fi+\p_pack_layers_offset+\p_pack_layers_dx
@@ -392,7 +385,7 @@
      \gsetboxllx\layerpagebox\zeropoint
      \gsetboxlly\layerpagebox\zeropoint
    \fi
-   \global\setbox\layerpagebox\vbox %to \layerparameter\c!height % new, otherwise no negative y possible
+   \global\setbox\layerpagebox\vpack %to \layerparameter\c!height % new, otherwise no negative y possible
      {\offinterlineskip
       \ifvoid\layerpagebox
         \let\lastlayerwidth \zeropoint
@@ -416,7 +409,8 @@
         \ht\nextbox\strutheight
         \dp\nextbox\strutdepth
       \else
-        \setbox\nextbox\hbox{\alignedbox[\p_pack_layers_location]\vbox{\box\nextbox}}%
+        \setbox\nextbox\hpack
+          {\alignedbox[\p_pack_layers_location]\vpack{\box\nextbox}}%
       \fi
       \ifnum\p_pack_layers_line=\zerocount\else % no \ifcase, can be negative
         \advance\d_pack_layers_y_position\dimexpr\p_pack_layers_line\lineheight+\topskip-\lineheight-\ht\nextbox\relax
@@ -425,7 +419,8 @@
         \advance\d_pack_layers_x_position\layoutcolumnoffset\p_pack_layers_column\relax
       \fi
       \ifx\p_pack_layers_location\v!grid
-        \setbox\nextbox\hbox{\alignedbox[rb]\vbox{\box\nextbox}}%
+        \setbox\nextbox\hpack
+          {\alignedbox[rb]\vpack{\box\nextbox}}%
       \fi
       % ll registration
       \scratchdimen\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
@@ -444,7 +439,7 @@
       \dp\nextbox\zeropoint
       % placement
       \hsize\p_pack_layers_width
-      \vbox to \p_pack_layers_height \bgroup
+      \vpack to \p_pack_layers_height \bgroup
         \smashbox\nextbox
         \vskip\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
         \hskip\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
@@ -498,7 +493,8 @@
 
 \def\doifelselayerdata#1%
   {\ifcsname\??layerbox#1\endcsname
-     \ifvoid\csname\??layerbox#1\endcsname
+    %\ifvoid\csname\??layerbox#1\endcsname
+     \ifvoid\lastnamedcs
        \doubleexpandafter\secondoftwoarguments
      \else
        \doubleexpandafter\firstoftwoarguments
@@ -550,6 +546,8 @@
 
 %  \ifcase#1\else\writestatus{layer}{unknown layer #3}\fi
 
+% todo: pass the layer with \lastnamedcs
+
 \def\pack_layers_flush_single
   {\startoverlay
      {\ifcsname\??layerbox  \currentlayer                \endcsname\pack_layers_flush_indeed\plusone   \currentlayer                 \fi}%
@@ -564,66 +562,6 @@
      {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}%
    \stopoverlay}
 
-% \def\pack_layers_flush_indeed#1#2% quite core, so optimized
-%   {\begingroup % already grouped
-%    \offinterlineskip
-%    \edef\p_pack_layers_preset{\layerparameter\c!preset}%
-%    \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
-%      \csname\??layerpreset\p_pack_layers_preset\endcsname
-%    \fi
-%    \edef\p_pack_layers_method{\layerparameter\c!method}%
-%    \edef\p_pack_layers_option{\layerparameter\c!option}%
-%    \ifx\p_pack_layers_option\v!test
-%      \settrue\c_pack_layers_trace
-%      \traceboxplacementtrue
-%    \fi
-%    \ifcase#1\relax
-%      \setfalse\c_pack_layers_repeated
-%    \else
-%      \edef\p_pack_layers_position{\layerparameter\c!position}%
-%      \ifx\p_pack_layers_position\v!yes
-%        \setfalse\c_pack_layers_repeated
-%      \else
-%        \edef\p_pack_layers_repeat{\layerparameter\c!repeat}%
-%        \ifx\p_pack_layers_repeat\v!yes
-%          \settrue\c_pack_layers_repeated
-%        \else\ifx\p_pack_layers_state\v!repeat
-%          \settrue\c_pack_layers_repeated
-%        \else
-%          \setfalse\c_pack_layers_repeated
-%        \fi\fi
-%      \fi
-%    \fi
-%    \chardef\b_layers\csname\??layerbox#2\endcsname % trick
-%    % 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
-%      \ifx\p_pack_layers_method\v!fit
-%        \pack_layers_positioned_box_yes
-%      \else
-%        \pack_layers_positioned_box_nop
-%      \fi
-%    % todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
-%    \doifoverlayelse{#2}%
-%      {\setlayoutcomponentattribute{\v!layer:#2}}%
-%      \resetlayoutcomponentattribute
-%    \ifx\p_pack_layers_option\v!test \ruledvbox \else \vbox \fi \ifx\p_pack_layers_method\v!overlay to \overlayheight \fi \layoutcomponentboxattribute
-%      {\hbox \ifx\p_pack_layers_method\v!overlay to \d_overlay_width \fi
-%         {\edef\currentlayer{#2\the\realpageno}% local
-%          \edef\p_pack_layers_position{\layerparameter\c!position}% local
-%          \ifx\p_pack_layers_position\v!yes
-%            \xypos{\??layerposition#2:\the\realpageno}%
-%          \fi
-%          \box\nextbox
-%          \hss}%
-%       \vss}%
-%    \ifconditional\c_pack_layers_repeated\else
-%      \gsetboxllx\b_layers\zeropoint
-%      \gsetboxlly\b_layers\zeropoint
-%    \fi
-%    \endgroup}
-
 \let\pack_layers_top_fill   \relax
 \let\pack_layers_bottom_fill\vss
 
@@ -632,7 +570,8 @@
    \offinterlineskip
    \edef\p_pack_layers_preset{\layerparameter\c!preset}%
    \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
-     \csname\??layerpreset\p_pack_layers_preset\endcsname
+    %\csname\??layerpreset\p_pack_layers_preset\endcsname
+     \lastnamedcs
    \fi
    \edef\p_pack_layers_method{\layerparameter\c!method}%
    \edef\p_pack_layers_option{\layerparameter\c!option}%
@@ -674,9 +613,9 @@
    % we have conflicting demands: some mechanisms want ll anchoring .. I need to figure this out
    % an dmaybe we will have 'origin=bottom' or so
    \setbox\nextbox
-   \ifx\p_pack_layers_option\v!test \ruledvbox \else \vbox \fi \ifx\p_pack_layers_method\v!overlay to \d_overlay_height \fi \layoutcomponentboxattribute
+   \ifx\p_pack_layers_option\v!test \ruledvbox \else \vpack \fi \ifx\p_pack_layers_method\v!overlay to \d_overlay_height \fi \layoutcomponentboxattribute
      {\pack_layers_top_fill
-      \hbox \ifx\p_pack_layers_method\v!overlay to \d_overlay_width \fi
+      \hpack \ifx\p_pack_layers_method\v!overlay to \d_overlay_width \fi
         {\box\nextbox
          \hss}%
       \pack_layers_bottom_fill}%
@@ -698,7 +637,7 @@
    \endgroup}
 
 \def\pack_layers_positioned_box_yes
-  {\vbox
+  {\vpack
      {\vskip-\getboxlly\b_layers
       \hskip-\getboxllx\b_layers
       \hsize-\dimexpr\getboxllx\b_layers-\wd\b_layers\relax
@@ -732,7 +671,7 @@
 %       \composedlayer{#1}}}
 
 \unexpanded\def\tightlayer[#1]%
-  {\hbox
+  {\hpack
      {\def\currentlayer{#1}% todo: left/right
       \setbox\nextbox\emptybox
       \d_overlay_width \layerparameter\c!width
@@ -807,7 +746,7 @@
 
 \unexpanded\def\settextpagecontent#1#2#3% #2 and #3 will disappear
   {\doifelselayerdata{OTRTEXT}
-     {\setbox#1\hbox to \makeupwidth
+     {\setbox#1\hpack to \makeupwidth
         {\startoverlay
            {\tightlayer[OTRTEXT]} % first, otherwise problems with toc
            {\normalsettextpagecontent{#1}{#2}{#3}\box#1}
diff --git a/tex/context/base/pack-obj.lua b/tex/context/base/pack-obj.lua
index a689a13b8..342ca32bd 100644
--- a/tex/context/base/pack-obj.lua
+++ b/tex/context/base/pack-obj.lua
@@ -127,7 +127,7 @@ objects = {
 
 function objects.register(ns,id,b,referenced)
     objects.n = objects.n + 1
-    nodes.handlers.finalize(b)
+    nodes.handlers.finalize(gettexbox(b))
     data[ns][id] = {
         codeinjections.registerboxresource(b), -- a box number
         gettexdimen("objectoff"),
diff --git a/tex/context/base/pack-obj.mkiv b/tex/context/base/pack-obj.mkiv
index 4a253324e..cc78b3ab7 100644
--- a/tex/context/base/pack-obj.mkiv
+++ b/tex/context/base/pack-obj.mkiv
@@ -83,9 +83,8 @@
   {\objectwd\dimexpr\wd\nextbox+2\objectoff\relax
    \objectht\dimexpr\ht\nextbox+ \objectoff\relax
    \objectdp\dimexpr\dp\nextbox+ \objectoff\relax
-   \setbox\objectbox\hbox
+   \setbox\objectbox\hpack
      {\hskip\objectoff
-      \raise\objectoff
       \box\nextbox}%
    \wd\objectbox\objectwd
    \ht\objectbox\objectht
@@ -95,9 +94,8 @@
   {\objectwd\dimexpr\wd\objectbox-2\objectoff\relax
    \objectht\dimexpr\ht\objectbox- \objectoff\relax
    \objectdp\dimexpr\dp\objectbox- \objectoff\relax
-   \setbox\objectbox\hbox
+   \setbox\objectbox\hpack
      {\hskip-\objectoff
-      \lower\objectoff
       \box\objectbox}%
    \wd\objectbox\objectwd
    \ht\objectbox\objectht
diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv
index e9da069c2..b858a8e6e 100644
--- a/tex/context/base/pack-rul.mkiv
+++ b/tex/context/base/pack-rul.mkiv
@@ -104,7 +104,8 @@
 
 \unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9%
   {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}%
-   \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root
+  %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root
+   \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root
    \unexpanded\def#8%
      {\bgroup
       \bgroup
@@ -368,7 +369,7 @@
    \fi}
 
 \def\pack_framed_background_box_color_indeed
-  {\hbox{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}}
+  {\hpack{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}}
 
 %D \macros
 %D   {defineoverlay, doifoverlayelse, overlayoffset,
@@ -493,7 +494,7 @@
      \fi
    \egroup
    \setlayoutcomponentattribute{\v!overlay:#1}%
-   \setbox\scratchbox\hbox \layoutcomponentboxattribute
+   \setbox\scratchbox\hpack \layoutcomponentboxattribute
      {\kern -.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \d_overlay_width
       \raise-.5\dimexpr\ht\scratchbox-\d_framed_target_ht\relax % not \d_overlay_height !
       \box\scratchbox}%
@@ -507,7 +508,7 @@
 %D   {overlayfakebox}
 
 \unexpanded\def\overlayfakebox
-  {\hbox
+  {\hpack
      {\setbox\scratchbox\emptyhbox
       \wd\scratchbox\d_overlay_width
       \ht\scratchbox\d_overlay_height
@@ -536,19 +537,21 @@
 
 \def\pack_framed_process_background
   {\ifcsname\??overlaybuiltin\m_framed_background\endcsname
-     \pack_framed_process_background_indeed_internal
+     \expandafter\pack_framed_process_background_indeed_internal\lastnamedcs
    \else\ifcsname\??overlay\m_framed_background\endcsname
-     \pack_framed_process_background_indeed_external
+     \expandafter\pack_framed_process_background_indeed_external\lastnamedcs
    \fi\fi}
 
-\def\pack_framed_process_background_indeed_internal % : in name
+\def\pack_framed_process_background_indeed_internal#1% % : in name
   {\bgroup
    \setbox\b_framed_extra\hbox{%\bgroup
      \ifzeropt\framedbackgroundoffset
-       \csname\??overlaybuiltin\m_framed_background\endcsname
+      %\csname\??overlaybuiltin\m_framed_background\endcsname
+       #1
      \else
        \kern-\framedbackgroundoffset
-       \hbox{\csname\??overlaybuiltin\m_framed_background\endcsname}%
+      %\hbox{\csname\??overlaybuiltin\m_framed_background\endcsname}%
+       \hbox{#1}%
      \fi
    }%\egroup
    \wd\b_framed_extra\zeropoint
@@ -557,15 +560,17 @@
    \box\b_framed_extra
    \egroup}
 
-\def\pack_framed_process_background_indeed_external
+\def\pack_framed_process_background_indeed_external#1%
   {\pack_framed_overlay_initialize
    \bgroup
    \setbox\b_framed_extra\hbox{%\bgroup
      \ifzeropt\framedbackgroundoffset
-       \csname\??overlay\m_framed_background\endcsname
+      %\csname\??overlay\m_framed_background\endcsname
+       #1%
      \else
        \kern-\framedbackgroundoffset
-       \hbox{\csname\??overlay\m_framed_background\endcsname}%
+      %\hbox{\csname\??overlay\m_framed_background\endcsname}%
+       \hbox{#1}%
      \fi
    }%\egroup
    \wd\b_framed_extra\zeropoint
@@ -590,7 +595,7 @@
 \newdimen\framedbackgroundoffset
 
 \def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise
-  {\vbox to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight
+  {\vpack to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight
 
 \def\pack_framed_add_region % experiment
   {\anch_mark_region_box\b_framed_normal}
@@ -662,7 +667,7 @@
 %D also support a negative offset.
 
 \def\pack_framed_add_outline
-  {\setbox\b_framed_normal\hbox % rules on top of box
+  {\setbox\b_framed_normal\hpack % rules on top of box
      {\d_framed_target_wd\dimexpr\wd\b_framed_normal+2\d_framed_frameoffset\relax
       \d_framed_target_ht\dimexpr\ht\b_framed_normal+ \d_framed_frameoffset\relax
       \d_framed_target_dp\dimexpr\dp\b_framed_normal+ \d_framed_frameoffset+\framedparameter\c!framedepth\relax
@@ -690,7 +695,7 @@
    \wd\scratchbox\d_framed_target_wd
    \ht\scratchbox\d_framed_target_ht
    \dp\scratchbox\d_framed_target_dp
-   \setbox\scratchbox\vbox \bgroup
+   \setbox\scratchbox\vpack \bgroup
      \csname   \??framedtop\p_framed_frame\framedparameter\c!topframe   \endcsname
      \nointerlineskip % new (needed for fences)
      \hbox \bgroup
@@ -729,8 +734,8 @@
 
 % no overlapping rules
 
-\def\pack_framed_t_rules{\hbox{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth}
-\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hbox{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}}
+\def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth}
+\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}}
 \def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth}
 \def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
 
@@ -1144,27 +1149,21 @@
      \dosetraggedcommand\localformat % not that fast
    \fi
    %
-   \csname\??framedoffsetalternative
-     \ifcsname\??framedoffsetalternative\localoffset\endcsname
-       \localoffset
-     \else
-       \s!unknown
-     \fi
-   \endcsname
-   \csname\??framedwidthalternative
-     \ifcsname\??framedwidthalternative\localwidth\endcsname
-       \localwidth
-     \else
-       \s!unknown
-     \fi
-   \endcsname
-   \csname\??framedheightalternative
-     \ifcsname\??framedheightalternative\localheight\endcsname
-       \localheight
-     \else
-       \s!unknown
-     \fi
-   \endcsname
+   \ifcsname\??framedoffsetalternative\localoffset\endcsname
+     \lastnamedcs
+   \else
+     \framed_offset_alternative_unknown
+   \fi
+   \ifcsname\??framedwidthalternative\localwidth\endcsname
+     \lastnamedcs
+   \else
+     \framed_width_alternative_unknown
+   \fi
+   \ifcsname\??framedheightalternative\localheight\endcsname
+     \lastnamedcs
+   \else
+     \framed_height_alternative_unknown
+   \fi
    % the next check could move to heightalternative
    \ifconditional\c_framed_has_height
      % obey user set height, also downward compatible
@@ -1188,13 +1187,11 @@
    % i.e. disable (colsetbackgroundproblemintechniek)
    \advance\d_framed_width  -2\d_framed_local_offset
    \advance\d_framed_height -2\d_framed_local_offset
-   \csname\??framedstrutalternative
-     \ifcsname\??framedstrutalternative\localstrut\endcsname
-       \localstrut
-     \else
-       \s!unknown
-     \fi
-   \endcsname
+   \ifcsname\??framedstrutalternative\localstrut\endcsname
+     \lastnamedcs
+   \else
+     \framed_offset_alternative_unknown
+   \fi
    % the next check could move to strutalternative
    \ifconditional\c_framed_has_strut
      \let\localbegstrut\begstrut
@@ -1327,6 +1324,10 @@
   {\settrue\c_framed_has_width
    \d_framed_width\localwidth}
 
+\def\framed_width_alternative_unknown
+  {\settrue\c_framed_has_width
+   \d_framed_width\localwidth}
+
 % heights
 
 \setvalue{\??framedheightalternative\empty}%
@@ -1349,7 +1350,11 @@
   {\settrue\c_framed_has_height
    \d_framed_height\localheight}
 
-% struts
+\def\framed_height_alternative_unknown
+  {\settrue\c_framed_has_height
+   \d_framed_height\localheight}
+
+% struts (use let instead?)
 
 \setvalue{\??framedstrutalternative\v!no}%
   {\setfalse\c_framed_has_strut}
@@ -1366,6 +1371,9 @@
 \setvalue{\??framedstrutalternative\s!unknown}%
   {\setstrut}
 
+\def\framed_strut_alternative_unknown
+  {\setstrut}
+
 % offsets
 
 \setvalue{\??framedoffsetalternative\v!none}%
@@ -1402,6 +1410,13 @@
    \let\defaultframeoffset\localoffset
    \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
 
+\def\framed_offset_alternative_unknown
+  {\settrue \c_framed_has_offset
+   \settrue \c_framed_has_strut
+   \setfalse\c_framed_is_overlaid
+   \let\defaultframeoffset\localoffset
+   \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
 % so far for alternatives
 
 \let\pack_framed_stop_orientation\relax
@@ -1500,7 +1515,7 @@
 
 \def\pack_framed_profile_box
   {\profilegivenbox\p_profile\b_framed_normal
-   \setbox\b_framed_normal\vbox{\unvbox\b_framed_normal}}
+   \setbox\b_framed_normal\vpack{\unvbox\b_framed_normal}}
 
 \unexpanded\def\pack_framed_finish
   {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down
@@ -1673,14 +1688,14 @@
 \installframedlocator \v!hanging % best with strut=no *1* / see mail to list by SB
   {}
   {\scratchdimen\ht\b_framed_normal
-   \setbox\b_framed_normal\hbox{\lower\scratchdimen\box\b_framed_normal}%
+   \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
    \dp\b_framed_normal\scratchdimen
    \ht\b_framed_normal\zeropoint
    \box\b_framed_normal}
 
 \installframedlocator \v!depth % *1*
   {}
-  {\setbox\b_framed_normal\hbox{\lower\strutdp\box\b_framed_normal}%
+  {\setbox\b_framed_normal\hpack{\lower\strutdp\box\b_framed_normal}%
    \ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
    \dp\b_framed_normal\strutdp
    \box\b_framed_normal}
@@ -1688,7 +1703,7 @@
 \installframedlocator \v!height % *1*
   {}
   {\scratchdimen\dimexpr \ht\b_framed_normal - \strutht \relax
-   \setbox\b_framed_normal\hbox{\lower\scratchdimen\box\b_framed_normal}%
+   \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
    \dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
    \ht\b_framed_normal\strutht
    \box\b_framed_normal}
@@ -1696,22 +1711,22 @@
 \installframedlocator \v!high
   {}
   {\pack_framed_locater_set\strutht
-   \setbox\b_framed_normal\hbox{\lower\d_framed_locator_dp\box\b_framed_normal}%
+   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
    \ht\b_framed_normal\strutht
    \dp\b_framed_normal\strutdp
-   \hbox{\box\b_framed_normal}}
+   \hpack{\box\b_framed_normal}}
 
 \installframedlocator \v!line
   {}
-  {\setbox\b_framed_normal\hbox{\lower.5\ht\b_framed_normal\box\b_framed_normal}%
+  {\setbox\b_framed_normal\hpack{\lower.5\ht\b_framed_normal\box\b_framed_normal}%
    \ht\b_framed_normal.5\lineheight
    \dp\b_framed_normal.5\lineheight
-   \hbox{\box\b_framed_normal}}
+   \hpack{\box\b_framed_normal}}
 
 \installframedlocator \v!low
   {}
   {\pack_framed_locater_set\strutdp
-   \setbox\b_framed_normal\hbox{\lower\d_framed_locator_ht\box\b_framed_normal}%
+   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
    \ht\b_framed_normal\strutht
    \dp\b_framed_normal\strutdp
    \box\b_framed_normal}
@@ -1719,18 +1734,18 @@
 \installframedlocator \v!top
   {}
   {\pack_framed_locater_set\strutht
-   \setbox\b_framed_normal\hbox{\lower\d_framed_locator_dp\box\b_framed_normal}%
+   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_dp\box\b_framed_normal}%
    \ht\b_framed_normal\d_framed_locator_ht
    \dp\b_framed_normal\d_framed_locator_dp
-   \hbox{\box\b_framed_normal}}
+   \hpack{\box\b_framed_normal}}
 
 \installframedlocator \v!middle
   {}
   {\scratchdimen.5\ht\b_framed_normal
-   \setbox\b_framed_normal\hbox{\lower\scratchdimen\box\b_framed_normal}%
+   \setbox\b_framed_normal\hpack{\lower\scratchdimen\box\b_framed_normal}%
    \ht\b_framed_normal\scratchdimen
    \dp\b_framed_normal\scratchdimen
-   \hbox{\box\b_framed_normal}}
+   \hpack{\box\b_framed_normal}}
 
 \installframedlocator \v!lohi
   {\pack_framed_locator_before\v!middle}
@@ -1739,10 +1754,10 @@
 \installframedlocator \v!bottom
   {}
   {\pack_framed_locater_set\strutdp
-   \setbox\b_framed_normal\hbox{\lower\d_framed_locator_ht\box\b_framed_normal}%
+   \setbox\b_framed_normal\hpack{\lower\d_framed_locator_ht\box\b_framed_normal}%
    \ht\b_framed_normal\d_framed_locator_dp
    \dp\b_framed_normal\d_framed_locator_ht
-   \hbox{\box\b_framed_normal}}
+   \hpack{\box\b_framed_normal}}
 
 \installframedlocator \v!keep % retains height/depth
   {\pack_framed_remove_depth}
@@ -1759,7 +1774,7 @@
    \d_framed_original_ht\ht\b_framed_normal
    \d_framed_original_dp\dp\b_framed_normal
    \ifzeropt\d_framed_original_dp\else
-     \setbox\b_framed_normal\hbox{\raise\d_framed_original_dp\box\b_framed_normal}%
+     \setbox\b_framed_normal\hpack{\raise\d_framed_original_dp\box\b_framed_normal}%
    \fi
    \wd\b_framed_normal\d_framed_original_wd
    \ht\b_framed_normal\dimexpr\d_framed_original_ht+\d_framed_original_dp\relax
@@ -1767,7 +1782,7 @@
 
 \def\pack_framed_restore_depth
   {\ifzeropt\d_framed_original_dp \else
-     \setbox\b_framed_normal\hbox{\lower\d_framed_original_dp\box\b_framed_normal}%
+     \setbox\b_framed_normal\hpack{\lower\d_framed_original_dp\box\b_framed_normal}%
    \fi
    \wd\b_framed_normal\d_framed_original_wd
    \ht\b_framed_normal\d_framed_original_ht
@@ -1813,7 +1828,7 @@
    \fi}
 
 \def\pack_framed_stop_orientation_indeed
-  {\setbox\b_framed_normal\hbox{\dorotatebox\p_framed_orientation\hbox{\box\b_framed_normal}}%
+  {\setbox\b_framed_normal\hpack{\dorotatebox\p_framed_orientation\hpack{\box\b_framed_normal}}%
    \d_framed_height\ht\b_framed_normal
    \d_framed_width \wd\b_framed_normal}
 
@@ -1929,7 +1944,7 @@
 \installframedlocator \v!mathematics
   {}
   {\lower\dimexpr\MPy\pack_framed_mc_two-\MPy\pack_framed_mc_one\relax
-   \hbox{\xypos\pack_framed_mc_one\box\b_framed_normal}}
+   \hpack{\xypos\pack_framed_mc_one\box\b_framed_normal}}
 
 \definemathframed[mframed]
 \definemathframed[inmframed][\c!location=\v!low]
@@ -1992,13 +2007,13 @@
    \ifzeropt\d_framed_boffset\else \advance\d_framed_height-\d_framed_boffset \settrue\c_framed_has_extra_offset \fi}
 
 \def\pack_framed_apply_extra_offsets
-  {\setbox\b_framed_normal\vbox\bgroup
+  {\setbox\b_framed_normal\vpack\bgroup
      \advance\d_framed_toffset\d_framed_applied_offset
      \advance\d_framed_boffset\d_framed_applied_offset
      \advance\d_framed_loffset\d_framed_applied_offset
      \advance\d_framed_roffset\d_framed_applied_offset
      \kern\d_framed_toffset
-     \hbox\bgroup
+     \hpack\bgroup
         \kern\d_framed_loffset
         \box\b_framed_normal
         \kern\d_framed_roffset
@@ -2007,9 +2022,9 @@
    \egroup}
 
 \def\pack_framed_widen_box
-  {\setbox\b_framed_normal\vbox
+  {\setbox\b_framed_normal\vpack
      {\kern\d_framed_applied_offset
-      \hbox{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}%
+      \hpack{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}%
       \kern\d_framed_applied_offset}}
 
 %D Let's hope that the next few examples show us enough of what needs to be
@@ -2094,14 +2109,14 @@
 
 \def\dodoformatonelinerbox
   {\afterassignment\redoformatonelinerbox
-   \setbox\nextbox\hbox}
+   \setbox\nextbox\hbox} % maybe \hpack
 
 \def\redoformatonelinerbox
   {\aftergroup\dododoformatonelinerbox
    \ignorespaces}
 
 \def\dododoformatonelinerbox
-  {\hbox to \hsize
+  {\hbox to \hsize % maybe \hpack
      {\ifcase\raggedstatus\or\hss\or\hss       \fi
       \unhbox\nextbox \removeunwantedspaces
       \ifcase\raggedstatus\or    \or\hss\or\hss\fi}%
@@ -2447,9 +2462,9 @@
    \par
    \kern-\d_framed_linewidth
    \dontleavehmode
-     \hbox to \zeropoint{\normalhss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}%
+     \hpack to \zeropoint{\normalhss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}%
      \hfill
-     \hbox to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\normalhss}%
+     \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\normalhss}%
    \par
    \nointerlineskip
    \kern\scratchoffset
@@ -2470,7 +2485,7 @@
      \dimen\scratchdepth \dimexpr\strutdp+\scratchoffset\relax
    \fi
    \unskip
-   \setbox\scratchbox\hbox
+   \setbox\scratchbox\hpack
      {\kern\scratchoffset
       \vrule\s!height\dimen\scratchheight\s!depth\dimen\scratchdepth\s!width\d_framed_linewidth
       \kern\scratchoffset}%
@@ -2842,9 +2857,9 @@
 
 \appendtoks
     \ifcsname\??regularframedlevel\currentframed\endcsname
-        % already defined, keeps settings
+      % already defined, keeps settings
     \else
-        \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname
+      \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname
     \fi
 \to \everypresetframed
 
@@ -2857,7 +2872,8 @@
 \unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent)
   {\bgroup
    \ifcsname\??regularframedlevel#1\endcsname
-     \expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname
+    %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname
+     \expandafter\let\expandafter\c_pack_framed_temp\lastnamedcs
    \else
      \let\c_pack_framed_temp\c_temp_framed_crap
    \fi
@@ -2951,7 +2967,7 @@
    \fi}
 
 \def\pack_framed_start_content_indeed
-  {\setbox\b_framed_normal\hbox\bgroup
+  {\setbox\b_framed_normal\hbox\bgroup % maybe \hpack
      \setlocalhsize
      \hsize\localhsize
      \scratchleftoffset  \framedcontentparameter\c!leftoffset  \relax
diff --git a/tex/context/base/page-app.mkiv b/tex/context/base/page-app.mkiv
index 2e81f7537..cdb964ab0 100644
--- a/tex/context/base/page-app.mkiv
+++ b/tex/context/base/page-app.mkiv
@@ -86,7 +86,7 @@
    \egroup
    % finalize
    \doif{\fittingpageparameter\c!margin}\v!page
-     {\setbox\b_page_fitting\hbox\bgroup
+     {\setbox\b_page_fitting\hpack\bgroup
         \offsetbox
           [\c!leftoffset=\backspace,
            \c!rightoffset=\cutspace,
@@ -95,7 +95,7 @@
           {\box\b_page_fitting}%
        \egroup}%
    \doifsomething{\fittingpageparameter\c!scale}
-     {\setbox\b_page_fitting\hbox\bgroup
+     {\setbox\b_page_fitting\hpack\bgroup
         \scale[\c!scale=\fittingpageparameter\c!scale]{\box\b_page_fitting}%
       \egroup}%
    \ifdim\ht\b_page_fitting=\zeropoint
diff --git a/tex/context/base/page-bck.mkiv b/tex/context/base/page-bck.mkiv
index 01de48e8c..b44910bbe 100644
--- a/tex/context/base/page-bck.mkiv
+++ b/tex/context/base/page-bck.mkiv
@@ -57,7 +57,8 @@
 
 \unexpanded\def\page_backgrounds_check_background
   {\ifcsname\??framed\currentotrbackground:\c!background\endcsname
-     \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}%
+    %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}%
+     \edef\page_background_temp{\lastnamedcs}%
      \ifx\page_background_temp\empty
        \expandafter\expandafter\expandafter\page_backgrounds_check_frame
      \else
@@ -69,7 +70,8 @@
 
 \def\page_backgrounds_check_frame
   {\ifcsname\??framed\currentotrbackground:\c!frame\endcsname
-     \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!frame\endcsname}%
+    %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!frame\endcsname}%
+     \edef\page_background_temp{\lastnamedcs}%
      \ifx\page_background_temp\v!on
        \page_backgrounds_set_yes
      \else
@@ -81,7 +83,8 @@
 
 \def\page_backgrounds_check_leftframe
   {\ifcsname\??framed\currentotrbackground:\c!leftframe\endcsname
-     \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!leftframe\endcsname}%
+    %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!leftframe\endcsname}%
+     \edef\page_background_temp{\lastnamedcs}%
      \ifx\page_background_temp\v!on
        \page_backgrounds_set_yes
      \else
@@ -93,7 +96,8 @@
 
 \def\page_backgrounds_check_rightframe
   {\ifcsname\??framed\currentotrbackground:\c!rightframe\endcsname
-     \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!rightframe\endcsname}%
+    %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!rightframe\endcsname}%
+     \edef\page_background_temp{\lastnamedcs}%
      \ifx\page_background_temp\v!on
        \page_backgrounds_set_yes
      \else
@@ -105,7 +109,8 @@
 
 \def\page_backgrounds_check_topframe
   {\ifcsname\??framed\currentotrbackground:\c!topframe\endcsname
-     \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!topframe\endcsname}%
+    %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!topframe\endcsname}%
+     \edef\page_background_temp{\lastnamedcs}%
      \ifx\page_background_temp\v!on
        \page_backgrounds_set_yes
      \else
@@ -117,7 +122,8 @@
 
 \def\page_backgrounds_check_bottomframe
   {\ifcsname\??framed\currentotrbackground:\c!bottomframe\endcsname
-     \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!bottomframe\endcsname}%
+    %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!bottomframe\endcsname}%
+     \edef\page_background_temp{\lastnamedcs}%
      \ifx\page_background_temp\v!on
        \page_backgrounds_set_yes
      \else
@@ -176,7 +182,7 @@
      \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces !
    \fi
    % #2 has the right dimensions already
-   \setbox#2\hbox{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground)
+   \setbox#2\hpack{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground)
 
 
 %D There are quite some backgrounds. At the bottom layer, there is the {\em
@@ -277,7 +283,7 @@
 \def\page_backgrounds_add_to_main#1% todo: dimension spec
   {\ifconditional\c_page_backgrounds_some
      \page_backgrounds_set_boxes
-     \setbox#1\vbox
+     \setbox#1\vpack
        {\offinterlineskip
         \doifelsemarginswap{\copy\leftbackground}{\copy\rightbackground}%
         \box#1}%
@@ -341,7 +347,7 @@
 \newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins
 
 \def\page_backgrounds_set_box#1% #2%
-  {\global\setbox#1\vbox
+  {\global\setbox#1\vpack
      {\dontcomplain
       \swapmargins
       \ifconditional\swapbackgroundmargins
@@ -378,8 +384,8 @@
    \smashbox#1}
 
 \def\page_backgrounds_set_box_row#1#2% maybe helper
-  {\setbox\scratchbox\vbox to #2
-     \bgroup\hbox\bgroup
+  {\setbox\scratchbox\vpack to #2
+     \bgroup\hpack\bgroup
        \goleftonpage
        \ifdim\leftedgewidth>\zeropoint
          \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname
@@ -446,7 +452,7 @@
    \ht\scratchbox#2}
 
 \def\page_backgrounds_set_box_cell_yes#1#2%
-  {\setbox\scratchbox\vbox to #2{\vss\hbox to#1{\hss\p_page_backgrounds_command\hss}\vss}%
+  {\setbox\scratchbox\vpack to #2{\vss\hpack to#1{\hss\p_page_backgrounds_command\hss}\vss}%
    \dp\scratchbox\zeropoint}
 
 %D The background mechanism is quite demanding in terms or resources. We used to
diff --git a/tex/context/base/page-box.mkvi b/tex/context/base/page-box.mkvi
index 8f5647a14..fa85aef68 100644
--- a/tex/context/base/page-box.mkvi
+++ b/tex/context/base/page-box.mkvi
@@ -46,10 +46,10 @@
    \v_page_target_left}
 
 \def\page_boxes_apply_center_indeed#box% we could test for a difference (saves packing)
-  {\setbox#box\vbox to \printpaperheight
+  {\setbox#box\vpack to \printpaperheight
      {\v_page_target_top
       \v_page_target_top_fill
-      \hbox to \printpaperwidth
+      \hpack to \printpaperwidth
         {\ifconditional\c_page_target_print_doublesided
            \doifbothsides
              {\page_boxes_apply_center_indeed_l_r#box}%
@@ -77,7 +77,7 @@
   {\scratchwidth \wd#box%
    \scratchheight\ht#box%
    \scratchdepth \dp#box%
-   \setbox#box\vbox
+   \setbox#box\vpack
      {\offinterlineskip
       \vskip\topoffset
       \hskip\doifbothsides\backoffset\backoffset{-\backoffset}%
@@ -96,10 +96,10 @@
    \fi\fi}
 
 \def\page_boxes_apply_replicate_indeed#box%
-  {\setbox#box\vbox
+  {\setbox#box\vpack
      {\offinterlineskip
       \dorecurse{\layoutparameter\c!ny}
-        {\hbox{\dorecurse{\layoutparameter\c!nx}{\copy#box\kern\layoutparameter\c!dx}\unskip}%
+        {\hpack{\dorecurse{\layoutparameter\c!nx}{\copy#box\kern\layoutparameter\c!dx}\unskip}%
          \vskip\layoutparameter\c!dy}
       \unskip}}
 
@@ -114,12 +114,12 @@
    \fi}
 
 \def\page_boxes_apply_orientate_indeed#odd#even#box%
-  {\setbox#box\vbox
+  {\setbox#box\vpack
      {\edef\somerotation{\number\ifdoublesided\ifodd\realpageno#odd\else#even\fi\else#odd\fi}%
-      \dorotatebox\somerotation\hbox{\box#box}}}
+      \dorotatebox\somerotation\hpack{\box#box}}}
 
 \def\page_boxes_apply_mirror#box%
-  {\setbox#box\vbox{\mirror{\box#box}}}
+  {\setbox#box\vpack{\mirror{\box#box}}}
 
 \def\page_boxes_apply_mirror_paper#box{\ifconditional\c_page_target_paper_mirror\page_boxes_apply_mirror{#box}\fi}
 \def\page_boxes_apply_mirror_print#box{\ifconditional\c_page_target_print_mirror\page_boxes_apply_mirror{#box}\fi}
@@ -152,7 +152,7 @@
    \fi}
 
 \def\page_boxes_apply_scale_indeed#sx#sy#box%
-  {\setbox#box\vbox{\scale[\c!sx=#sx,\c!sy=#sy]{\box#box}}% can be a fast one
+  {\setbox#box\vpack{\scale[\c!sx=#sx,\c!sy=#sy]{\box#box}}% can be a fast one
    \paperwidth #sx\paperwidth
    \paperheight#sy\paperheight}
 
@@ -189,7 +189,7 @@
    \scratchwidth \wd#box%
    \scratchheight\ht#box%
    \scratchdepth \dp#box%
-   \setbox#box\hbox
+   \setbox#box\hpack
      {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
       \advance\scratchwidth \scratchoffset
       \ifconditional#right\relax
@@ -198,7 +198,7 @@
       \else
          \scratchdimen\zeropoint
       \fi
-      \lower\scratchoffset\hbox
+      \lower\scratchoffset\hpack
         {\clip
            [\c!hoffset=\scratchdimen,
             \c!voffset=-\scratchoffset,
@@ -221,7 +221,7 @@
   {\scratchwidth \wd#box%
    \scratchheight\ht#box%
    \scratchdepth \dp#box%
-   \setbox#box\hbox
+   \setbox#box\hpack
      {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
       \advance\scratchwidth \scratchoffset
       \doifbothsides
@@ -231,7 +231,7 @@
         {\scratchdimen\zeropoint}
         {\scratchdimen-\scratchoffset
          \kern\scratchdimen}%
-      \lower\scratchoffset\hbox
+      \lower\scratchoffset\hpack
         {\clip
            [\c!hoffset=\scratchdimen,
             \c!voffset=-\scratchoffset,
@@ -245,7 +245,7 @@
 % nearly always some displacement so no speedup test needed
 
 \def\page_boxes_apply_offsets#1%
-  {\setbox#1\vbox to \paperheight
+  {\setbox#1\vpack to \paperheight
      {\hsize\paperwidth
       \vskip\topspace
       \doifbothsides
@@ -282,9 +282,9 @@
 
 \def\page_areas_register_boxed#1%
   {\begingroup
-   \setbox\scratchbox\vbox{#1}%
+   \setbox\scratchbox\vpack{#1}%
    \wd\scratchbox\makeupwidth % somehow a space creeps in
-   \vbox{\page_areas_registered_box00\scratchbox}% 0 0 will go
+   \vpack{\page_areas_registered_box00\scratchbox}% 0 0 will go
    \endgroup}
 
 % \def\page_areas_register_direct#1%
diff --git a/tex/context/base/page-brk.mkiv b/tex/context/base/page-brk.mkiv
index b9805decd..bea011555 100644
--- a/tex/context/base/page-brk.mkiv
+++ b/tex/context/base/page-brk.mkiv
@@ -58,15 +58,19 @@
 \def\page_breaks_handle_step#1%
   {\edef\page_breaks_current_option{#1}% can be used in handler
    \ifcsname\??pagebreakmethod\page_breaks_current_option\endcsname
-     \csname\??pagebreakmethod\page_breaks_current_option\endcsname
+    %\csname\??pagebreakmethod\page_breaks_current_option\endcsname
+     \lastnamedcs
    \else\ifcsname\??pagebreaks\page_breaks_current_option\endcsname
-     \expandafter\page_breaks_handle\csname\??pagebreaks\page_breaks_current_option\endcsname
+    %\expandafter\page_breaks_handle\csname\??pagebreaks\page_breaks_current_option\endcsname
+     \lastnamedcs
    \else
-     \csname\??pagebreakmethod\s!unknown\endcsname
+    %\csname\??pagebreakmethod\s!unknown\endcsname
+     \page_breaks_unknown
    \fi\fi}
 
 \def\page_breaks_handle_direct#1%
-  {\csname\??pagebreakmethod#1\endcsname}
+ %{\csname\??pagebreakmethod#1\endcsname}
+  {\begincsname\??pagebreakmethod#1\endcsname}
 
 \unexpanded\def\installpagebreakmethod#1#2% low level definer
   {\setvalue{\??pagebreakmethod#1}{#2}}
@@ -133,7 +137,7 @@
    \page[\v!empty]
    \endgroup}
 
-\installpagebreakmethod \s!unknown
+\unexpanded\def\page_breaks_unknown % how often called ?
   {\doifelseinstring{+}\page_breaks_current_option
      {\page_otr_flush_all_floats
       \page_otr_command_next_page
@@ -149,6 +153,9 @@
             \fi}}
         {}}}
 
+\installpagebreakmethod \s!unknown
+ {\page_breaks_unknown}
+
 \installpagebreakmethod \s!default
   {} % do nothing if empty
 
@@ -277,15 +284,18 @@
 \def\page_breaks_columns_handle_step#1%
   {\edef\page_breaks_columns_current_option{#1}%
    \ifcsname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
-     \csname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
+    %\csname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
+     \lastnamedcs
    \else\ifcsname\??columnbreaks\page_breaks_columns_current_option\endcsname
-     \expandafter\csname\page_breaks_columns_handle\??columnbreaks\page_breaks_columns_current_option\endcsname
-   \else
-     \csname\??columnbreakmethod\currentoutputroutine:\s!unknown\endcsname
-   \fi\fi}
+    %\expandafter\csname\page_breaks_columns_handle\??columnbreaks\page_breaks_columns_current_option\endcsname
+     \lastnamedcs
+   \else\ifcsname\??columnbreakmethod\currentoutputroutine:\s!unknown\endcsname
+     \lastnamedcs
+   \fi\fi\fi}
 
 \def\page_breaks_columns_handle_direct#1%
-  {\csname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
+ %{\csname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
+  {\begincsname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
 
 \unexpanded\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action
   {\setvalue{\??columnbreakmethod#1:#2}{#3}}
@@ -387,8 +397,6 @@
 %      \fi
 %    \fi}
 
-\let\triggerpagebuilder\relax
-
 \installcorenamespace {pagechecker}
 \installcorenamespace {pagecheckermethod}
 
diff --git a/tex/context/base/page-com.mkiv b/tex/context/base/page-com.mkiv
index 0ff8e3b54..b051b3db9 100644
--- a/tex/context/base/page-com.mkiv
+++ b/tex/context/base/page-com.mkiv
@@ -114,7 +114,7 @@
   {}% \setuppapersize[\c!bottom=,\c!top=,\c!left=,\c!right=]}
 
 \unexpanded\def\page_comments_top_bottom
-  {\vbox to \printpaperheight
+  {\vpack to \printpaperheight
      {%\forgetall
       \hsize\printpaperwidth\relax
       \ifx\p_page_commands_location\v!bottom
@@ -140,7 +140,7 @@
       \fi}}
 
 \unexpanded\def\page_comments_left_right
-  {\hbox to \printpaperwidth
+  {\hpack to \printpaperwidth
      {\ifx\p_page_commands_location\v!right
         \hskip\dimexpr\paperwidth+\d_page_comments_distance+\d_page_comments_offset\relax
       \else
diff --git a/tex/context/base/page-flt.mkiv b/tex/context/base/page-flt.mkiv
index 16c427139..c514496df 100644
--- a/tex/context/base/page-flt.mkiv
+++ b/tex/context/base/page-flt.mkiv
@@ -194,7 +194,7 @@
      \page_floats_flush\s!text\plusone
      \ifconditional\c_page_floats_center_box
        \ifdim\wd\globalscratchbox<\hsize
-         \global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}%
+         \global\setbox\floatbox\hpack to \hsize{\hss\box\floatbox\hss}%
        \else
          % retain special alignments
          \ifinsidecolumns
@@ -258,7 +258,7 @@
   {\page_floats_flush{#1}\plusone
    \edef\floatspecification{\clf_getfloatvariable{specification}}% Is this okay?
    \the\everybeforeflushedpagefloat
-   \vbox to \textheight
+   \vpack to \textheight
      {\doifnotinset\v!high\floatspecification\vfill
       \box\floatbox
       \doifnotinset\v!low\floatspecification\vfill}%
diff --git a/tex/context/base/page-grd.mkiv b/tex/context/base/page-grd.mkiv
index e70414b66..546bd4d89 100644
--- a/tex/context/base/page-grd.mkiv
+++ b/tex/context/base/page-grd.mkiv
@@ -92,13 +92,13 @@
 \def\page_grids_add_to_one_indeed#1%
   {\begingroup
    \resetvisualizers
-   \global\setbox#1\vbox{\backgroundline[layout:one]{\box#1}}%
+   \global\setbox#1\vpack{\backgroundline[layout:one]{\box#1}}%
    \endgroup}
 
 \def\page_grids_add_to_mix_indeed#1%
   {\begingroup
    \resetvisualizers
-   \global\setbox#1\vbox{\backgroundline[layout:mix]{\box#1}}%
+   \global\setbox#1\vpack{\backgroundline[layout:mix]{\box#1}}%
    \endgroup}
 
 \protect \endinput
diff --git a/tex/context/base/page-imp.mkiv b/tex/context/base/page-imp.mkiv
index 3d913a70a..403145d6a 100644
--- a/tex/context/base/page-imp.mkiv
+++ b/tex/context/base/page-imp.mkiv
@@ -73,12 +73,19 @@
 \unexpanded\def\invokepagehandler#1%
   {\expandnamespacevalue\??shipoutmethod{#1}\v!normal}
 
+% \def\page_shipouts_handle
+%   {\csname\??shipoutmethod\ifcsname\??shipoutmethod\v_page_target_method\endcsname
+%      \v_page_target_method
+%    \else
+%      \v!none
+%    \fi\endcsname}
+
 \def\page_shipouts_handle
-  {\csname\??shipoutmethod\ifcsname\??shipoutmethod\v_page_target_method\endcsname
-     \v_page_target_method
+  {\ifcsname\??shipoutmethod\v_page_target_method\endcsname
+     \expandafter\lastnamedcs
    \else
-     \v!none
-   \fi\endcsname}
+     \expandafter\page_shipouts_ignore
+   \fi}
 
 \installshipoutmethod \v!normal
   {\ifarrangingpages
@@ -108,7 +115,7 @@
    \ifcase\shipoutfinalizemethod
      \page_shipouts_handle{#1}%
    \else
-     \setbox\shipoutscratchbox\hbox{#1}% just in case there are objects there, hook for testing (will go away)
+     \setbox\shipoutscratchbox\hpack{#1}% just in case there are objects there, hook for testing (will go away)
      \finalizeshipoutbox\shipoutscratchbox
      \page_shipouts_handle{\box\shipoutscratchbox}%
    \fi
@@ -124,13 +131,13 @@
      {[\ifarrangingpages arranged \fi page
        \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace
        not flushed]}%
-   \setbox\scratchbox\hbox{#1}%
+   \setbox\scratchbox\hpack{#1}%
    \deadcycles\zerocount
    \endgroup}
 
 \def\page_otr_flush_every_stuff
   {\begingroup
-   \setbox\scratchbox\hbox
+   \setbox\scratchbox\hpack
      {% before the main one !
       \ifcase\realfolio \or
         \the\everyfirstshipout
@@ -166,15 +173,15 @@
      \normalexpanded{\doifelseinset{\the\shippedoutpages}{\pagestoshipout}}\donetrue\donefalse
    \fi
    \ifdone
-     \setbox\shipoutscratchbox\hbox{#1}%
+     \setbox\shipoutscratchbox\hpack{#1}%
      \ifcase\shipoutfinalizemethod
        \finalizeshipoutbox\shipoutscratchbox
      \fi
-     \normalshipout\vbox
+     \normalshipout\vpack
        {\offinterlineskip
         \vskip\d_page_shipouts_offset
         \hskip\d_page_shipouts_offset
-        \hbox
+        \hpack
           {\page_otr_flush_every_stuff
            \page_otr_flush_special_content
            \box\shipoutscratchbox}}%
@@ -185,7 +192,7 @@
 \def\page_shipouts_arrange#1%
   {% \global\advance\shippedoutpages\plusone
    \begingroup
-   \setbox\scratchbox\hbox
+   \setbox\scratchbox\hpack
      {\page_otr_flush_every_stuff
       \page_otr_flush_special_content
       \box\shipoutscratchbox}%
@@ -375,12 +382,12 @@
    \fi}
 
 \def\handlearrangedpageXandY#1#2#3#4#5%
-  {\global\setbox#5\hbox to \arrangedpageX\paperwidth
-     {\setbox\scratchbox\vbox to \arrangedpageY\paperheight
+  {\global\setbox#5\hpack to \arrangedpageX\paperwidth
+     {\setbox\scratchbox\vpack to \arrangedpageY\paperheight
         {\offinterlineskip
          \vskip#4\paperheight
          \hskip#3\paperwidth
-         \dorotatebox{\ifcase#2 0\else180\fi}\hbox{\box#1}%
+         \dorotatebox{\ifcase#2 0\else180\fi}\hpack{\box#1}%
          \vfill}%
       \wd\scratchbox\zeropoint
       \box\scratchbox\box#5\hss}}
@@ -394,15 +401,15 @@
    \forgetall % somehow we're back and need to redo this
    \gotonextarrangepage
    \ifnum\arrangedrotationO\arrangedrotationE>\zerocount
-     \setbox#1\vbox
+     \setbox#1\vpack
        {\ifconditional\arrangeddoublestate
           \ifodd\arrangeno
-            \dorotatebox\arrangedrotationO\hbox{\box#1}%
+            \dorotatebox\arrangedrotationO\hpack{\box#1}%
           \else
-            \dorotatebox\arrangedrotationE\hbox{\box#1}%
+            \dorotatebox\arrangedrotationE\hpack{\box#1}%
           \fi
         \else
-          \dorotatebox\arrangedrotationO\hbox{\box#1}%
+          \dorotatebox\arrangedrotationO\hpack{\box#1}%
         \fi}%
    \fi
    \ifconditional\arrangedmirrorstate
@@ -550,14 +557,14 @@
 \def\handlearrangedpageSIDE
   {\wd\arrangedpageA\paperwidth
    \wd\arrangedpageB\paperwidth
-   \global\setbox\arrangedpageA\hbox
+   \global\setbox\arrangedpageA\hpack
      {\box\arrangedpageA\box\arrangedpageB}%
    \ht\arrangedpageA\paperheight}
 
 \def\handlearrangedpageTOP
   {\ht\arrangedpageA\paperheight
    \ht\arrangedpageB\paperheight
-   \global\setbox\arrangedpageA\vbox
+   \global\setbox\arrangedpageA\vpack
      {\offinterlineskip\vskip\paperheight
       \box\arrangedpageA\box\arrangedpageB}%
    \global\setbox\arrangedpageB\box\scratchbox} % ?
@@ -577,14 +584,14 @@
    \ht\arrangedpageA\paperheight
    \ht\arrangedpageB\paperheight
    \ifconditional\arrangedswapstate
-     \global\setbox\arrangedpageA\hbox
+     \global\setbox\arrangedpageA\hpack
        {\page_boxes_apply_clip_print_left \arrangedpageA
         \box\arrangedpageA
         \page_boxes_apply_clip_print_right\arrangedpageB
         \box\arrangedpageB}%
      \setfalse\arrangedswapstate
    \else
-     \global\setbox\arrangedpageA\hbox
+     \global\setbox\arrangedpageA\hpack
        {\page_boxes_apply_clip_print_left \arrangedpageB
         \box\arrangedpageB
         \page_boxes_apply_clip_print_right\arrangedpageA
@@ -598,14 +605,14 @@
    \ht\arrangedpageA\paperheight
    \ht\arrangedpageB\paperheight
    \ifconditional\arrangedswapstate
-     \global\setbox\arrangedpageA\vbox
+     \global\setbox\arrangedpageA\vpack
        {\offinterlineskip
         \vskip\paperheight
         \box\arrangedpageA
         \box\arrangedpageB}%
      \setfalse\arrangedswapstate
    \else
-     \global\setbox\arrangedpageA\vbox
+     \global\setbox\arrangedpageA\vpack
        {\offinterlineskip
         \vskip\paperheight
         \box\arrangedpageB
@@ -635,14 +642,14 @@
 \def\pusharrangedpageTWO#1%
   {\advancearrangedpageN
    \reportarrangedpage\arrangedpageN
-   \global\setbox\arrangedpageB\vbox
+   \global\setbox\arrangedpageB\vpack
      {\offinterlineskip
       \unvbox\arrangedpageB
       \allowbreak
-      \setbox#1\vbox{\box#1}% really needed in order to keep real dimensions
+      \setbox#1\vpack{\box#1}% really needed in order to keep real dimensions
       \ht#1\onepoint
       \dp#1\zeropoint
-      \vbox{\box#1}}}
+      \vpack{\box#1}}}
 
 \def\poparrangedpagesTWOTOPSIDE
   {\ifnum\arrangedpageN>\zerocount
@@ -1189,7 +1196,7 @@
   {\advancearrangedpageN
    \global\advance\arrangedpageM\plusone
    \reportarrangedpage\arrangedpageN
-   \global\setbox\arrangedpageB\hbox \ifdim\v_page_target_width>\zeropoint to \v_page_target_width \fi
+   \global\setbox\arrangedpageB\hpack \ifdim\v_page_target_width>\zeropoint to \v_page_target_width \fi
       {\ifvoid\arrangedpageB\else
          \unhbox\arrangedpageB
          \ifdim\v_page_target_dx>\zeropoint
@@ -1202,7 +1209,7 @@
        \fi
        \box#1}%
     \ifnum\arrangedpageM<\arrangedpageX\else
-      \global\setbox\arrangedpageA\vbox \ifdim\v_page_target_height>\zeropoint to \v_page_target_height \fi
+      \global\setbox\arrangedpageA\vpack \ifdim\v_page_target_height>\zeropoint to \v_page_target_height \fi
         {\offinterlineskip
          \ifvoid\arrangedpageA\else
            \unvbox\arrangedpageA
@@ -1334,7 +1341,7 @@
 
 \def\page_boxes_apply_shift_indeed#1%
   {\edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
-   \setbox#1\vbox
+   \setbox#1\vpack
      {\offinterlineskip
       \vskip\d_page_boxes_v_shifts
       \hskip\d_page_boxes_h_shifts
@@ -1346,8 +1353,10 @@
 
 \def\page_boxes_setup_shift[#1][#2][#3]% page|paper horizontal vertical
   {\ifthirdargument                    % paper=arrange
-     \edef\page_boxes_h_shifts{\ifcsname\??pageshift\v!horizontal:#2\endcsname\csname\??pageshift\v!horizontal:#2\endcsname\fi}%
-     \edef\page_boxes_v_shifts{\ifcsname\??pageshift\v!vertical  :#3\endcsname\csname\??pageshift\v!vertical  :#3\endcsname\fi}%
+     %edef\page_boxes_h_shifts{\ifcsname\??pageshift\v!horizontal:#2\endcsname\csname\??pageshift\v!horizontal:#2\endcsname\fi}%
+     %edef\page_boxes_v_shifts{\ifcsname\??pageshift\v!vertical  :#3\endcsname\csname\??pageshift\v!vertical  :#3\endcsname\fi}%
+     \edef\page_boxes_h_shifts{\begincsname\??pageshift\v!horizontal:#2\endcsname}%
+     \edef\page_boxes_v_shifts{\begincsname\??pageshift\v!vertical  :#3\endcsname}%
      \doifelse{#1}\v!page {\let\page_boxes_apply_shift_print\page_boxes_apply_shift}{\let\page_boxes_apply_shift_print\gobbleoneargument}%
      \doifelse{#1}\v!paper{\let\page_boxes_apply_shift_paper\page_boxes_apply_shift}{\let\page_boxes_apply_shift_paper\gobbleoneargument}%
    \else\ifsecondargument
diff --git a/tex/context/base/page-inf.mkiv b/tex/context/base/page-inf.mkiv
index acfbf26f6..f60977e0c 100644
--- a/tex/context/base/page-inf.mkiv
+++ b/tex/context/base/page-inf.mkiv
@@ -89,7 +89,7 @@
 
 \def\page_info_add_to_box_indeed#1%
   {\scratchdimen\wd#1%
-   \setbox\b_page_versions\vbox to \ht#1%
+   \setbox\b_page_versions\vpack to \ht#1%
      {\vfill
       \settexthoffset
       \hsize\dimexpr\scratchdimen-2\texthoffset\relax
@@ -98,7 +98,7 @@
       \vskip\bodyfontsize}%
    \dp\b_page_versions\zeropoint
    \wd\b_page_versions\scratchdimen
-   \setbox#1\hbox{\box#1\hskip-\scratchdimen\box\b_page_versions}}
+   \setbox#1\hpack{\box#1\hskip-\scratchdimen\box\b_page_versions}}
 
 \setupversion % resets
   [\v!final]
diff --git a/tex/context/base/page-ini.mkiv b/tex/context/base/page-ini.mkiv
index 609757488..6f6cb7180 100644
--- a/tex/context/base/page-ini.mkiv
+++ b/tex/context/base/page-ini.mkiv
@@ -178,7 +178,7 @@
 \newbox        \b_page_boxes_saved_page_body
 
 \def\page_boxes_constructed_page_body#1#2%
-  {\ifconditional\c_page_boxes_save_page_body \global\setbox\b_page_boxes_saved_page_body \fi \vbox \bgroup
+  {\ifconditional\c_page_boxes_save_page_body \global\setbox\b_page_boxes_saved_page_body \fi \vpack \bgroup
       \boxmaxdepth\maxdimen % new
       \dontcomplain
       \page_marks_synchronize_page                    {#2}%  we could consider doing this for \pagebox (needs testing)
@@ -220,7 +220,7 @@
 \to \everybeforepagebody
 
 \def\page_boxes_constructed_page#1#2%
-  {\vbox\bgroup % intercept spurious spaces
+  {\vpack\bgroup % intercept spurious spaces
      \the\everybeforepagebody
      \starttextproperties
      \checkmarginblocks
diff --git a/tex/context/base/page-lay.mkiv b/tex/context/base/page-lay.mkiv
index 9fb60401d..f1aec4e3d 100644
--- a/tex/context/base/page-lay.mkiv
+++ b/tex/context/base/page-lay.mkiv
@@ -379,8 +379,11 @@
     \letvalue{\??layoutcurrent\currentlayouttarget}\relax
 \to \everydefinelayouttarget
 
-\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi}
-\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi}
+%def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi}
+%def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi}
+
+\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\lastnamedcs\else#1\fi}
+\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\lastnamedcs\else#1\fi}
 
 % \setuppaper    [page=A4,paper=A3] % the k/v variant, changes the current page mapping
 % \setuppapersize[A4][a=b,c=d]      % the k/v variant, changes nothing, just settings
@@ -497,8 +500,11 @@
 \setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle
                                                     \global\c_page_target_print_reverse    \rightrotationangle}
 
-\def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi}
-\def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi}
+%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi}
+%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi}
+
+\def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname}
+\def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname}
 
 \unexpanded\def\page_paper_identify_target#1%
   {\ifcsname\??layoutcurrent#1\endcsname
@@ -730,7 +736,7 @@
 
 \letvalue{\??layoutcolumn0}\zeropoint
 
-\def\layoutcolumnoffset#1%
+\def\layoutcolumnoffset#1% can travel around so we can't use \lastnamedcs
   {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname}
 
 \def\page_layouts_synchronize_at_start
@@ -821,12 +827,19 @@
 \installlayoutmethod\v!default{\page_layouts_check_default}
 \installlayoutmethod\v!normal {\page_layouts_check_default}
 
+% \def\page_layouts_check_next
+%   {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
+%      \layoutparameter\c!method
+%    \else
+%      \v!normal
+%    \fi\endcsname}
+
 \def\page_layouts_check_next
-  {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
-     \layoutparameter\c!method
+  {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
+     \lastnamedcs
    \else
-     \v!normal
-   \fi\endcsname}
+     \page_layouts_check_default
+   \fi}
 
 \let\checkcurrentlayout\page_layouts_check_next % public and used in naw, so this synonym will stay
 
@@ -908,7 +921,8 @@
 \setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided}
 
 \def\page_target_check_centering_indeed#1%
-  {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi}
+ % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi}
+  {\begincsname\??layoutlocation#1\endcsname}
 
 \unexpanded\def\page_target_check_centering
   {\setfalse\c_page_target_print_doublesided
@@ -933,12 +947,19 @@
 \installlayoutalternative\v!default{\page_boxes_construct_content_default}
 \installlayoutalternative\v!normal {\page_boxes_construct_content_default}
 
+% \def\page_boxes_construct_content % targetbox flusher box
+%   {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
+%      \layoutparameter\c!alternative
+%    \else
+%      \v!normal
+%    \fi\endcsname}
+
 \def\page_boxes_construct_content % targetbox flusher box
-  {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
-     \layoutparameter\c!alternative
+  {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
+     \expandafter\lastnamedcs
    \else
-     \v!normal
-   \fi\endcsname}
+     \expandafter\page_boxes_construct_content_default
+   \fi}
 
 %D \macros
 %D   {adaptlayout}
@@ -998,12 +1019,20 @@
    \global\let\page_adepts_push\relax
    \global\let\page_adepts_pop\page_adepts_pop_indeed}
 
+% \def\page_adapts_check
+%   {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname}
+%
+% \def\page_adapts_reset
+%   {\ifcsname\??pageadaptations\the\realpageno\endcsname
+%      \global\undefinevalue{\??pageadaptations\the\realpageno}%
+%    \fi}
+
 \def\page_adapts_check
-  {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname}
+  {\begincsname\??pageadaptations\the\realpageno\endcsname}
 
 \def\page_adapts_reset
   {\ifcsname\??pageadaptations\the\realpageno\endcsname
-     \global\undefinevalue{\??pageadaptations\the\realpageno}%
+     \expandafter\glet\csname\??pageadaptations\the\realpageno\endcsname\relax
    \fi}
 
 \def\page_adepts_push_indeed
diff --git a/tex/context/base/page-lin.mkvi b/tex/context/base/page-lin.mkvi
index 11e1f0b1b..0f12384a7 100644
--- a/tex/context/base/page-lin.mkvi
+++ b/tex/context/base/page-lin.mkvi
@@ -500,10 +500,10 @@
 \setuvalue{\??linenumberinghandler\v!end  }{\page_line_handle_end  \p_align}
 \setuvalue{\??linenumberinghandler\v!text }{\page_line_handle_begin\p_align}
 
-\setuevalue{\??linenumberinghandler\v!inleft  }{\getvalue{\??linenumberinghandler\v!left }}
-\setuevalue{\??linenumberinghandler\v!inmargin}{\getvalue{\??linenumberinghandler\v!left }}
-\setuevalue{\??linenumberinghandler\v!margin  }{\getvalue{\??linenumberinghandler\v!left }}
-\setuevalue{\??linenumberinghandler\v!inright }{\getvalue{\??linenumberinghandler\v!right}}
+\expandafter\let\csname\??linenumberinghandler\v!inleft  \expandafter\endcsname\csname\??linenumberinghandler\v!left \endcsname
+\expandafter\let\csname\??linenumberinghandler\v!inmargin\expandafter\endcsname\csname\??linenumberinghandler\v!left \endcsname
+\expandafter\let\csname\??linenumberinghandler\v!margin  \expandafter\endcsname\csname\??linenumberinghandler\v!left \endcsname
+\expandafter\let\csname\??linenumberinghandler\v!inright \expandafter\endcsname\csname\??linenumberinghandler\v!right\endcsname
 
 % referencing: \permithyphenation, also removes leading spaces (new per 29-11-2013)
 
@@ -527,14 +527,14 @@
    \fi}
 
 \def\page_lines_reference_show_start_indeed#1%
-  {\setbox\scratchbox\hbox{\llap
-     {\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht\raise.85\strutht\hbox{\llap{\tt\txx#1}}}}%
+  {\setbox\scratchbox\hpack{\llap
+     {\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht\raise.85\strutht\hpack{\llap{\tt\txx#1}}}}%
    \smashbox\scratchbox
    \box\scratchbox}
 
 \def\page_lines_reference_show_stop_indeed#1%
-  {\setbox\scratchbox\hbox{\rlap
-     {\raise.85\strutht\hbox{\rlap{\tt\txx#1}}\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht}}%
+  {\setbox\scratchbox\hpack{\rlap
+     {\raise.85\strutht\hpack{\rlap{\tt\txx#1}}\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht}}%
    \smashbox\scratchbox
    \box\scratchbox}
 
diff --git a/tex/context/base/page-mak.mkvi b/tex/context/base/page-mak.mkvi
index 3c90c2423..04df90d08 100644
--- a/tex/context/base/page-mak.mkvi
+++ b/tex/context/base/page-mak.mkvi
@@ -179,7 +179,7 @@
    \endgroup
    \makeupparameter\c!after\relax
    \ifdoublesided \ifodd\realpageno \else
-     \getvalue{\??makeupdoublesided\makeupparameter\c!doublesided}%
+     \csname\??makeupdoublesided\makeupparameter\c!doublesided\endcsname
    \fi \fi
    \strc_pagenumbers_page_state_pop % new
    \egroup
diff --git a/tex/context/base/page-mix.lua b/tex/context/base/page-mix.lua
index e52ba09db..2fb883c54 100644
--- a/tex/context/base/page-mix.lua
+++ b/tex/context/base/page-mix.lua
@@ -49,7 +49,6 @@ local vpack               = nuts.vpack
 local freenode            = nuts.free
 local concatnodes         = nuts.concat
 local slidenodes          = nuts.slide -- ok here as we mess with prev links intermediately
-local traversenodes       = nuts.traverse
 
 local getfield            = nuts.getfield
 local setfield            = nuts.setfield
@@ -169,7 +168,7 @@ local function discardtopglue(current,discarded)
     while current do
         local id = getid(current)
         if id == glue_code then
-            size = size + getfield(getfield(current,"spec"),"width")
+            size = size + getfield(current,"width")
             discarded[#discarded+1] = current
             current = getnext(current)
         elseif id == penalty_code then
@@ -177,7 +176,7 @@ local function discardtopglue(current,discarded)
                 discarded[#discarded+1] = current
                 current = getnext(current)
                 while current and getid(current) == glue_code do
-                    size = size + getfield(getfield(current,"spec"),"width")
+                    size = size + getfield(current,"width")
                     discarded[#discarded+1] = current
                     current = getnext(current)
                 end
@@ -216,7 +215,7 @@ local function stripbottomglue(results,discarded)
                 end
             elseif id == glue_code then
                 discarded[#discarded+1] = t
-                local width = getfield(getfield(t,"spec"),"width")
+                local width = getfield(t,"width")
                 if trace_state then
                     report_state("columns %s, discarded bottom glue %p",i,width)
                 end
@@ -478,7 +477,7 @@ local function preparesplit(specification) -- a rather large function
     head = current
 
     local function process_skip(current,nxt)
-        local advance = getfield(getfield(current,"spec"),"width")
+        local advance = getfield(current,"width")
         if advance ~= 0 then
             local state, skipped = checked(advance,"glue")
             if trace_state then
diff --git a/tex/context/base/page-mix.mkiv b/tex/context/base/page-mix.mkiv
index 5ff4ccc17..db98df4a8 100644
--- a/tex/context/base/page-mix.mkiv
+++ b/tex/context/base/page-mix.mkiv
@@ -213,7 +213,7 @@
      % preceding is overwritten ... needs to be figured out some day
      \page_one_command_routine
    \fi
-   \global\setbox\b_page_mix_preceding\vbox
+   \global\setbox\b_page_mix_preceding\vbox % pack ?
      {\page_otr_command_flush_top_insertions
       \ifdim\htdp\b_page_mix_preceding=\zeropoint \else
         \writestatus\m!columns{preceding error}%
@@ -522,7 +522,7 @@
        % moved here, before the packaging
        \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding
        % we need to avoid unvboxing with successive balanced on one page
-       \global\setbox\b_page_mix_preceding\vbox{\box\b_page_mix_preceding}%
+       \global\setbox\b_page_mix_preceding\vpack{\box\b_page_mix_preceding}%
        \wd\b_page_mix_preceding\scratchwidth % \makeupwidth
        \page_grids_add_to_one\b_page_mix_preceding
      \fi
@@ -619,7 +619,7 @@
    \setbox\b_page_mix_collected\vbox \bgroup
      \ifvoid\b_page_mix_preceding \else
      % \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding % already done
-       \vbox\bgroup
+       \vpack\bgroup
          \box\b_page_mix_preceding
        \egroup
        \global\d_page_mix_preceding_height\zeropoint
@@ -650,7 +650,7 @@
   {\bgroup
    \forgetall
    \dontcomplain
-   \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+   \setbox\b_page_mix_collected\vpack{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
    \page_mix_routine_construct\v!no
    \page_mix_routine_package
    \page_otr_construct_and_shipout\box\b_page_mix_collected
@@ -662,13 +662,13 @@
   {\bgroup
    \forgetall
    \dontcomplain
-   \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+   \setbox\b_page_mix_collected\vpack{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
    \doloop
      {%writestatus\m!columns{construct continue (\the\htdp\b_page_mix_collected)}%
       \page_mix_routine_construct\v!no
       \ifcase\clf_mixstate\relax
         % 0 = okay, we can balance
-        \setbox\b_page_mix_collected\vbox{\clf_mixflushlist}% we could avoid this
+        \setbox\b_page_mix_collected\vpack{\clf_mixflushlist}% we could avoid this
         %writestatus\m!columns{construct balance}%
         \page_mix_routine_construct\v!yes
         \page_mix_routine_package
@@ -692,7 +692,7 @@
         %writestatus\m!columns{flush continue}%
         \page_mix_routine_package
         \page_otr_construct_and_shipout\box\b_page_mix_collected
-        \setbox\b_page_mix_collected\vbox{\clf_mixflushrest}% we could avoid this
+        \setbox\b_page_mix_collected\vpack{\clf_mixflushrest}% we could avoid this
         \clf_mixcleanup
         \ifdim\ht\b_page_mix_collected=\zeropoint
             \exitloop
@@ -805,7 +805,7 @@
       % and glue in between and when we're too large we run into issues
       % so mayb best limit correction to one line
       \profilegivenbox\p_profile\b_page_mix_collected
-      \setbox\b_page_mix_collected\vbox{\unvbox\b_page_mix_collected}%
+      \setbox\b_page_mix_collected\vpack{\unvbox\b_page_mix_collected}%
       % tracing
       % \addprofiletobox\b_page_mix_collected
    \fi
diff --git a/tex/context/base/page-mrk.mkiv b/tex/context/base/page-mrk.mkiv
index 0823464fe..0cd615f8a 100644
--- a/tex/context/base/page-mrk.mkiv
+++ b/tex/context/base/page-mrk.mkiv
@@ -56,7 +56,7 @@
 
 \def\page_marks_add_color
   {\setlayoutcomponentattribute{\v!print:\v!color}%
-   \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+   \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
      \uniqueMPgraphic
        {print:color}%
        {w=\the\scratchwidth,h=\the\scratchheight,%
@@ -67,7 +67,7 @@
 
 \def\page_marks_add_marking
   {\setlayoutcomponentattribute{\v!print:\v!marking}%
-   \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+   \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
      \uniqueMPgraphic
        {print:marking}%
        {w=\the\scratchwidth,h=\the\scratchheight,%
@@ -78,7 +78,7 @@
 
 \def\page_marks_add_lines
   {\setlayoutcomponentattribute{\v!print:\v!lines}%
-   \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+   \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
      \uniqueMPgraphic
        {print:lines}%
        {w=\the\scratchwidth,h=\the\scratchheight,%
@@ -90,7 +90,7 @@
 
 \def\page_marks_add_number
   {\setlayoutcomponentattribute{\v!print:\v!number}%
-   \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+   \setbox\scratchbox\hpack \layoutcomponentboxattribute\bgroup
      \useMPgraphic
        {print:number}%
        {w=\the\scratchwidth ,h=\the\scratchheight,%
@@ -101,7 +101,7 @@
    \hskip-\scratchwidth\box\scratchbox}
 
 \def\page_marks_add_page_indeed#1%
-  {\setbox#1\hbox\bgroup
+  {\setbox#1\hpack\bgroup
      \resetvisualizers
      \let\objectoffset\pagecutmarkmargin
     %\infofont
@@ -142,7 +142,7 @@
 
 \installcorenamespace{layoutmarking}
 
-\def\installpagecutmark#1#2%
+\unexpanded\def\installpagecutmark#1#2%
   {\setvalue{\??layoutmarking#1}{#2}}
 
 % \installpagecutmark\v!off
@@ -180,12 +180,13 @@
     \setfalse\c_page_marks_add_more_marking
     \setfalse\c_page_marks_add_more_lines
     \setfalse\c_page_marks_add_more_number
-    \csname\??layoutmarking\layoutparameter\c!marking\endcsname
+    \begincsname\??layoutmarking\layoutparameter\c!marking\endcsname
     \ifconditional\c_page_marks_add_page_lines
       \let\page_marks_add_page\page_marks_add_page_indeed
     \else
       \let\page_marks_add_page\gobbleoneargument
     \fi
+    % we can get a double set of (overlayed) lines .. needs to be redone (too many objects anyway)
     \ifconditional\c_page_marks_add_more_lines
       \let\page_marks_add_more\page_marks_add_more_indeed
     \else\ifconditional\c_page_marks_add_more_color
diff --git a/tex/context/base/page-one.mkiv b/tex/context/base/page-one.mkiv
index 4cf59da2d..ca3d8025a 100644
--- a/tex/context/base/page-one.mkiv
+++ b/tex/context/base/page-one.mkiv
@@ -137,7 +137,7 @@
    %
    % \setbox\b_page_one_contents\vbox \ifconditional\c_notes_bottom_present to \textheight \fi
    %
-   \setbox\b_page_one_contents\vbox to \textheight
+   \setbox\b_page_one_contents\vbox to \textheight % probably no pack
      {\page_otr_command_flush_top_insertions
       % this is messy ... we will provide a more tight area (no big deal as we can
       % do that at the lua end)
@@ -175,13 +175,13 @@
      \else
        \scratchoffset\ht\b_page_one_contents
      \fi
-     \setbox\b_page_one_bottom_notes\hbox
+     \setbox\b_page_one_bottom_notes\hpack
        {\checksinglecolumnfootnotes % why this check? ***
-        \lower\scratchoffset\vbox{\placebottomnotes\par\kern\zeropoint}}% kerns makes notes sit on bottom
+        \lower\scratchoffset\vbox{\placebottomnotes\par\kern\zeropoint}}% kerns makes notes sit on bottom % pack ?
      \smashbox\b_page_one_bottom_notes
      \ht\b_page_one_contents\zeropoint
      \page_one_registered_text_area_b
-       {\vbox to \textheight
+       {\vpack to \textheight
           {\box\b_page_one_contents
            \box\b_page_one_bottom_notes}}%
    \else
@@ -356,9 +356,9 @@
 
 \unexpanded\def\page_one_command_flush_float_box
   {\ifconditional\c_page_floats_center_box \ifdim\wd\floatbox<\hsize
-     \global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}%
+     \global\setbox\floatbox\hpack to \hsize{\hss\box\floatbox\hss}%
    \fi \fi
-   \snaptogrid\hbox{\box\floatbox}} % was copy
+   \snaptogrid\hpack{\box\floatbox}} % was copy
 
 \def\page_one_command_flush_floats_indeed % much in common with OTRSET
   {\ifconditional\c_page_floats_some_waiting
@@ -470,7 +470,7 @@
    \page_one_place_float_here_indeed}
 
 \def\page_one_place_float_side_indeed#1%
-  {\setbox\floatbox\vbox{\box\floatbox}% ? can go
+  {\setbox\floatbox\vpack{\box\floatbox}% ? can go
    \wd\floatbox\floatwidth
    #1{\box\floatbox}%
    \doifinset\v!tall\floatlocationmethod\page_sides_flush_floats_after_par}
diff --git a/tex/context/base/page-otr.lua b/tex/context/base/page-otr.lua
new file mode 100644
index 000000000..307158684
--- /dev/null
+++ b/tex/context/base/page-otr.lua
@@ -0,0 +1,12 @@
+if not modules then modules = { } end modules ['page-otr'] = {
+    version   = 1.001,
+    comment   = "companion to page-otr.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+interfaces.implement {
+    name    = "triggerpagebuilder",
+    actions = tex.triggerbuildpage,
+}
diff --git a/tex/context/base/page-otr.mkvi b/tex/context/base/page-otr.mkvi
index e146d99b7..d1dbaad93 100644
--- a/tex/context/base/page-otr.mkvi
+++ b/tex/context/base/page-otr.mkvi
@@ -19,8 +19,12 @@
 % When issuing two \par\penalty-\plustenthousand's, only the first
 % triggers the otr. Is this an obscure feature or an optimization?
 
+\registerctxluafile{page-otr}{1.001}
+
 \unprotect
 
+\let\triggerpagebuilder\clf_triggerpagebuilder
+
 \def\m!otr{otr} % todo
 
 \installcorenamespace{outputroutine}
@@ -129,7 +133,7 @@
 \unexpanded\def\page_otr_triggered_output_routine_traced
   {\ifcsname\??otrtriggers\the\outputpenalty\endcsname
      \page_otr_message_b{special}%
-     \csname\??otrtriggers\the\outputpenalty\endcsname
+     \csname\??otrtriggers\the\outputpenalty\endcsname % \lastnamedcs can be gone
      \page_otr_message_e{special}%
    \else
      \page_otr_message_b{normal}%
@@ -139,7 +143,8 @@
 
 \unexpanded\def\page_otr_triggered_output_routine_normal
   {\ifcsname\??otrtriggers\the\outputpenalty\endcsname
-     \csname\??otrtriggers\the\outputpenalty\endcsname
+    %\csname\??otrtriggers\the\outputpenalty\endcsname
+     \lastnamedcs
    \else
      \page_otr_command_routine
    \fi}
@@ -220,7 +225,7 @@
 
 \def\page_otr_force_another_page
   {% we should actually remove the dummy line in the otr
-   \hbox to \hsize{}%
+   \hpack to \hsize{}%
    \kern-\topskip
    \nobreak
    \vfill
diff --git a/tex/context/base/page-sel.mkvi b/tex/context/base/page-sel.mkvi
index ee25a37db..93521d4e6 100644
--- a/tex/context/base/page-sel.mkvi
+++ b/tex/context/base/page-sel.mkvi
@@ -272,8 +272,8 @@
         \exitloop
       \fi}}
 
-\setvalue{\??combinepagesalternative\v!horizontal}{\getvalue{\??combinepagesalternative\v!a}}
-\setvalue{\??combinepagesalternative\v!vertical  }{\getvalue{\??combinepagesalternative\v!c}}
+\expandafter\let\csname\??combinepagesalternative\v!horizontal\expandafter\endcsname\csname\??combinepagesalternative\v!a\endcsname
+\expandafter\let\csname\??combinepagesalternative\v!vertical  \expandafter\endcsname\csname\??combinepagesalternative\v!c\endcsname
 
 \setvalue{\??combinepagesalternative\v!b}%
   {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
diff --git a/tex/context/base/page-set.mkiv b/tex/context/base/page-set.mkiv
index 83bdf9a9f..f0a088ea3 100644
--- a/tex/context/base/page-set.mkiv
+++ b/tex/context/base/page-set.mkiv
@@ -1271,10 +1271,10 @@
    %     {\vss\box#2\vss}%
    % \fi
    % and don't change this any more
-%   \doifdefinedelse{\strippedcsname\OTRSETstoreincolumnslot#1}
-%     {\getvalue{\strippedcsname\OTRSETstoreincolumnslot#1}{#2}}
+%   \doifdefinedelse{\csstring\OTRSETstoreincolumnslot#1}
+%     {\getvalue{\csstring\OTRSETstoreincolumnslot#1}{#2}}
 %     {\OTRSETstoreincolumnslotUNKNOWN{#2}}}
-   \executeifdefined{\strippedcsname\OTRSETstoreincolumnslot#1}
+   \executeifdefined{\csstring\OTRSETstoreincolumnslot#1}
      \OTRSETstoreincolumnslotUNKNOWN} % {#2}}
 
 \def\OTRSETstoreincolumnslotUNKNOWN#1%
diff --git a/tex/context/base/page-sid.mkiv b/tex/context/base/page-sid.mkiv
index cbee4da20..2c1c624df 100644
--- a/tex/context/base/page-sid.mkiv
+++ b/tex/context/base/page-sid.mkiv
@@ -258,7 +258,7 @@
    \doloop
      {\iftracesidefloats
         \dontleavehmode
-        \ruledhbox{\m_pages_strut\kern\d_page_sides_width}%
+        \ruledhpack{\m_pages_strut\kern\d_page_sides_width}%
       \else
         \m_pages_strut
       \fi
@@ -456,7 +456,7 @@
 % The compact way:
 
 \def\page_sides_relocate_float#1%
-  {\global\setbox\floatbox\hbox
+  {\global\setbox\floatbox\hpack
      {\ifnum\c_page_sides_float_type=\plusfour
         \kern\d_page_sided_leftshift
       \else\ifnum\c_page_sides_float_type=\plusone
@@ -487,7 +487,7 @@
      \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\setbox\floatbox\hpack{\lower\strutdepth\box\floatbox}%
      \ht\floatbox\scratchdimen
      \dp\floatbox\zeropoint
    \fi
@@ -522,7 +522,7 @@
    \ifnum\c_page_sides_n_of_lines>\zerocount
      \advance\scratchdimen\c_page_sides_n_of_lines\lineheight
    \fi
-   \global\setbox\floatbox\hbox % why extra box
+   \global\setbox\floatbox\hpack % why extra box
      {\vbox
         {\vskip\scratchdimen
          \nointerlineskip
@@ -690,7 +690,7 @@
   {\par
    \begingroup
    \reseteverypar
-   \dontleavehmode\hbox to \zeropoint{\page_sides_anchor\hss\strut}%
+   \dontleavehmode\hpack to \zeropoint{\page_sides_anchor\hss\strut}%
    \vskip-\parskip
    \vskip-\struttotal
    \inhibitblank
@@ -801,7 +801,7 @@
    \divide\scratchcounter \baselineskip
    \advance\scratchcounter \plusone
    \parskip\zeropoint
-   \dorecurse\scratchcounter{\hbox to \hsize{}}%
+   \dorecurse\scratchcounter{\hpack to \hsize{}}%
    \kern-\scratchcounter\baselineskip
    \penalty\zerocount
    \endgroup}
diff --git a/tex/context/base/page-txt.mkvi b/tex/context/base/page-txt.mkvi
index 8be4211bb..401a65dbd 100644
--- a/tex/context/base/page-txt.mkvi
+++ b/tex/context/base/page-txt.mkvi
@@ -283,7 +283,8 @@
    \uselayoutelementstyleandcolor#style#color%
    \csname\??layouttextstrut\layoutelementparameter\c!strut\endcsname
    \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname
-     \csname\??layouttextspecial\m_page_layouts_element_content\endcsname
+    %\csname\??layouttextspecial\m_page_layouts_element_content\endcsname
+     \lastnamedcs
    \else
      \edef\currentlayoutelementwidth{\layoutelementparameter#width}%
      \ifx\currentlayoutelementwidth\empty
@@ -355,8 +356,13 @@
 \to \everybeforeflushedpagefloat
 
 \unexpanded\def\page_layouts_place_text_line#vertical%
-  {\page_layouts_set_element_status#vertical%
-   \csname\??layouttextsline\ifcsname\??layouttextsline\textlinestatus\endcsname\textlinestatus\else\s!unknown\fi\endcsname#vertical}
+  {\page_layouts_set_element_status#vertical\relax
+  %\csname\??layouttextsline\ifcsname\??layouttextsline\textlinestatus\endcsname\textlinestatus\else\s!unknown\fi\endcsname#vertical}
+   \ifcsname\??layouttextsline\textlinestatus\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\page_layouts_place_text_line_unknown
+   \fi#vertical}
 
 \unexpanded\def\doifelselayouttextline#vertical% shown or not
   {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
@@ -407,7 +413,7 @@
    \page_layouts_place_text_line_indeed#vertical#height%
    \egroup}
 
-\setvalue{\??layouttextsline\s!unknown}#vertical#height%
+\def\page_layouts_place_text_line_unknown#vertical#height%
   {\global\settrue\resyncaftertextline
    \begingroup % new
    \page_layouts_reset_element_status#vertical%
@@ -418,6 +424,8 @@
    \page_layouts_place_text_line_indeed#vertical#height%
    \endgroup}
 
+\letvalue{\??layouttextsline\s!unknown}\page_layouts_place_text_line_unknown
+
 %D The following macro has to be called after a page
 %D is flushed.
 
@@ -513,7 +521,7 @@
 \let\page_layouts_place_extra_text_right\relax % historic
 
 \def\page_layouts_place_text_line_right
-  {\hbox
+  {\hpack
      {\ifdim\leftedgewidth>\zeropoint
         \page_layouts_left_edge_element\c!lefttext
       \fi
@@ -534,7 +542,7 @@
       \fi}}
 
 \def\page_layouts_place_text_line_left
-  {\hbox
+  {\hpack
      {\ifdim\leftedgewidth>\zeropoint
         \page_layouts_left_edge_element\c!righttext
       \fi
@@ -807,7 +815,7 @@
    \fi}
 
 \def\page_layouts_place_elements_indeed
-  {\setbox\b_page_layouts_element\vbox
+  {\setbox\b_page_layouts_element\vpack
      {\dontcomplain
       \calculatereducedvsizes
       \swapmargins
@@ -832,7 +840,7 @@
   \box\b_page_layouts_element}
 
 \def\page_insert_body#1#2%
-  {\setbox\b_page_layouts_element\vbox
+  {\setbox\b_page_layouts_element\vpack
      {\offinterlineskip
       \calculatereducedvsizes
       \calculatehsizes
@@ -881,7 +889,7 @@
 % clear up the experimental mess
 
 \def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded
-  {\setbox#1\hbox to \makeupwidth
+  {\setbox#1\hbox to \makeupwidth % maybe \hpack
      {\hss                     % so don't change this
       \setlayoutcomponentattribute{\v!page:\v!text}%
       \vbox \layoutcomponentboxattribute to \textheight
diff --git a/tex/context/base/phys-dim.mkiv b/tex/context/base/phys-dim.mkiv
index d25bef785..fcbb53311 100644
--- a/tex/context/base/phys-dim.mkiv
+++ b/tex/context/base/phys-dim.mkiv
@@ -400,11 +400,15 @@
 \unexpanded\def\installunitsseparator#1#2%
   {\setvalue{\??unitseparator#1}{#2}}
 
+% \unexpanded\def\phys_units_separator
+%   {\edef\currentunitsseparator{\unitparameter\c!separator}%
+%    \csname\??unitseparator
+%      \ifcsname\??unitseparator\currentunitsseparator\endcsname\currentunitsseparator\else\v!normal\fi
+%    \endcsname}
+
 \unexpanded\def\phys_units_separator
-  {\edef\currentunitsseparator{\unitparameter\c!separator}%
-   \csname\??unitseparator
-     \ifcsname\??unitseparator\currentunitsseparator\endcsname\currentunitsseparator\else\v!normal\fi
-   \endcsname}
+  {\edef\currentunitsseparator{\unitparameter\c!separator}% no longer needed
+   \ifcsname\??unitseparator\currentunitsseparator\endcsname\lastnamedcs\else\cdot\fi}
 
 \installunitsseparator\v!normal {\cdot}
 \installunitsseparator\v!big    {\unitsbigspace}
@@ -415,12 +419,17 @@
 \unexpanded\def\installunitsspace#1#2%
   {\setvalue{\??unitspace#1}{#2}}
 
+% \unexpanded\def\phys_units_space
+%   {\unskip % weird, why is unskip needed
+%    \edef\currentunitsspace{\unitparameter\c!space}%
+%    \csname\??unitspace
+%      \ifcsname\??unitspace\currentunitsspace\endcsname\currentunitsspace\else\v!normal\fi
+%    \endcsname}
+
 \unexpanded\def\phys_units_space
   {\unskip % weird, why is unskip needed
    \edef\currentunitsspace{\unitparameter\c!space}%
-   \csname\??unitspace
-     \ifcsname\??unitspace\currentunitsspace\endcsname\currentunitsspace\else\v!normal\fi
-   \endcsname}
+   \ifcsname\??unitspace\currentunitsspace\endcsname\lastnamedcs\else\unitsmediumspace\fi}
 
 \installunitsspace\v!normal {\unitsmediumspace}
 \installunitsspace\v!big    {\unitsbigspace}
diff --git a/tex/context/base/publ-dat.lua b/tex/context/base/publ-dat.lua
index b34a99bc8..0a71b0936 100644
--- a/tex/context/base/publ-dat.lua
+++ b/tex/context/base/publ-dat.lua
@@ -53,7 +53,7 @@ local report_duplicates = logs.reporter("publications","duplicates")
 local allocate          = utilities.storage.allocate
 
 local commands          = commands
-local implement         = interfaces.implement
+local implement         = interfaces and interfaces.implement
 
 publications            = publications or { }
 local publications      = publications
@@ -431,8 +431,7 @@ do
 
     local space     = S(" \t\n\r\f") -- / " "
     local collapsed = space^1/" "
-    ----- csletter  = R("az","AZ")
-    local csletter  = lpegpatterns.csletter
+    local csletter  = lpegpatterns.csletter or R("az","AZ")
 
     ----- command   = P("\\") * Cc("btxcmd{") * (R("az","AZ")^1) * Cc("}")
     ----- command   = P("\\") * (Carg(1) * C(R("az","AZ")^1) / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end)
diff --git a/tex/context/base/publ-imp-apa.lua b/tex/context/base/publ-imp-apa.lua
index 1d894f261..c6fe248ce 100644
--- a/tex/context/base/publ-imp-apa.lua
+++ b/tex/context/base/publ-imp-apa.lua
@@ -31,6 +31,7 @@ local specification = {
         -- Vons, Last, Jrs, First
         --
         author      = "author", -- interpreted as name(s)
+        withauthor  = "author",
         editor      = "author",
         artist      = "author",
         composer    = "author",
@@ -89,6 +90,7 @@ categories.article = {
         "author"
     },
     optional = {
+        "withauthor",
         "year",
         "subtitle", "type", "file",
         "journal", "volume", "number", "pages",
@@ -106,6 +108,7 @@ categories.magazine = {
         "journal",
     },
     optional = {
+        "withauthor",
         "subtitle", "type", "file",
         "number",
         "month", "day",
@@ -127,7 +130,7 @@ categories.periodical = {
         "year",
     },
     optional = {
-        "author",
+        "author", "withauthor",
         "subtitle", "file",
         "series", "volume", "number", "month",
         "organization",
@@ -149,6 +152,7 @@ categories.standard = {
         "doi", "note",
     },
     optional = {
+        "withauthor",
     },
 }
 
@@ -162,6 +166,7 @@ categories.book = {
     },
     required = { "author" },
     optional = {
+        "withauthor",
         "year", "month", "day",
         "subtitle", "type",  "file",
         "editionset", "series",
@@ -183,6 +188,7 @@ categories.inbook = {
         "year" ,
     },
     optional = {
+        "withauthor",
         "subtitle", "type", "file",
         "booktitle",
         -- APA ignores this: "chapter",
@@ -208,6 +214,7 @@ categories.incollection = {
         "year",
     },
     optional = {
+        "withauthor",
         "subtitle", "type", "file",
         "editionset", "series",
         -- APA ignores this: "chapter",
@@ -229,6 +236,7 @@ categories.booklet = {
         "author"
     },
     optional = {
+        "withauthor",
         "publisher",
         "year", "month",
         "subtitle", "type", "file",
@@ -251,6 +259,7 @@ categories.proceedings = {
         "year"
     },
     optional = {
+        "withauthor",
         "publisher",
         "subtitle", "file",
         "editionset", "series",
@@ -266,6 +275,7 @@ categories.inproceedings = {
     sets     = categories.incollection.sets,
     required = categories.incollection.required,
     optional = {
+        "withauthor",
         "subtitle", "type", "file",
         "month",
         "edition", "series",
@@ -290,6 +300,7 @@ categories.thesis = {
         "type"
     },
     optional = {
+        "withauthor",
         "subtitle", "file",
         "month",
         "address",
@@ -306,6 +317,7 @@ categories.mastersthesis = {
         "year"
     },
     optional = {
+        "withauthor",
         "type",
         "subtitle", "file",
         "month",
@@ -331,6 +343,7 @@ categories.techreport = {
         "year"
     },
     optional = {
+        "withauthor",
         "publisher",
         "address",
         "subtitle", "file",
@@ -354,6 +367,7 @@ categories.manual = {
     },
     optional = {
         "author", "publisher",
+        "withauthor",
         "address",
         "subtitle", "file",
         "editionset", "month", "year",
@@ -382,6 +396,7 @@ categories.patent = {
         "type",
         --check this: "language",
         "author", "publisher",
+        "withauthor",
         "title", "subtitle", "file",
         "address",
         "day", "month",
@@ -401,6 +416,7 @@ categories.unpublished = {
         "note"
     },
     optional = {
+        "withauthor",
         "subtitle", "file",
         "year", "month",
         "doi"
@@ -419,7 +435,7 @@ categories.electronic = {
     optional = {
         "subtitle", "type", "file",
         "year", "month",
-        "author",
+        "author", "withauthor",
         "address",
         "organization",
         "howpublished",
@@ -441,6 +457,7 @@ categories.film = {
         "address", "publisher", -- aka studio
     },
     optional = {
+        "withauthor",
         "type",
         "note",
         "doi",
@@ -460,6 +477,7 @@ categories.music = {
         "address", "publisher", -- aka label
     },
     optional = {
+        "withauthor",
         "type",
         "note",
         "doi",
@@ -476,7 +494,7 @@ categories.misc = {
         -- nothing is really important here
     },
     optional = {
-        "author",
+        "author", "withauthor",
         "title", "subtitle", "file",
         "year", "month",
         "howpublished",
@@ -496,6 +514,7 @@ categories.other = {
         "year"
     },
     optional = {
+        "withauthor",
         "subtitle", "file",
         "doi", "note",
     },
@@ -513,6 +532,7 @@ categories.literal = {
         "text"
     },
     optional = {
+        "withauthor",
         "doi", "note"
     },
     virtual = false,
diff --git a/tex/context/base/publ-imp-apa.mkvi b/tex/context/base/publ-imp-apa.mkvi
index 9468b0b0c..1411042c9 100644
--- a/tex/context/base/publ-imp-apa.mkvi
+++ b/tex/context/base/publ-imp-apa.mkvi
@@ -462,6 +462,7 @@
    apa:Volume={Vol.},
    apa:Volumes={Vols.},
    apa:others={et al.},
+   apa:with=with,
    apa:page={p.},
    apa:pages={pp.},
    apa:nd={n.d.},     % no date
@@ -492,6 +493,7 @@
    apa:Volume={Vol.},
    apa:Volumes={Vols.},
    apa:others={et al.},
+   apa:with=met,
    apa:page={p.},
    apa:pages={pp.},
    apa:nd={g.d.}      % geen datum
@@ -522,6 +524,7 @@
    apa:Volume=Volume,
    apa:Volumes=Volumes,
    apa:others={et al.},
+   apa:with=avec,
    apa:page={p.},
    apa:pages={pp.},
    apa:nd={s.d.}      % sans date
@@ -552,6 +555,7 @@
    apa:Volume=Band,        % Bd.
    apa:Volumes={Bände},
    apa:others={et al.},
+   apa:with=mit,
    apa:page={S.},
    apa:pages={S.},
    apa:nd={o.D.},          % ohne Datum (mostly: o.J. / ohne Jahr)
@@ -584,6 +588,7 @@
    apa:Volume={Vol.},  % Volume
    apa:Volumes={Vol.}, % Volumi
    apa:others={et al.},
+   apa:with=con,
    apa:page={p.},
    apa:pages={pp.},
    apa:nd={s.d.},     % senza data
@@ -614,6 +619,7 @@
    apa:Volume={Vol.},   % Volumen
    apa:Volumes={Vols.}, % Volúmenes
    apa:others={et al.},
+   apa:with=con,
    apa:page={p.},
    apa:pages={pp.},
    apa:nd={s.f.},     % sin fecha
@@ -657,7 +663,7 @@
             \texdefinition {\s!btx:\s!cite:inject} {
                 \currentbtxsecond
             }
-        \fi
+            \fi
         \btxflushsuffix
     \fi
    %\btxparameter\c!right
@@ -754,7 +760,6 @@
     \btxstartstyleandcolor[apa:\s!list:title:\currentbtxcategory]
         \begingroup
             \language[\currentbtxlanguage]
-            \tracingall
             \btxusecommand [apa:\s!list:title:\currentbtxcategory] {
                 \btxflush{#title}
                 \btxdoif {sub#title} {
@@ -826,7 +831,7 @@
             } {
                 \btxlabeltext{apa:Editors}
             }
-            \btxrightparenthesisperiod
+            \btxrightparenthesis
         } {
             \doifelse {\btxfoundname{#author}} {producer} {
                 \btxleftparenthesis
@@ -836,7 +841,7 @@
                     \btxlabeltext{apa:Producers}
                 }
                 \btxrightparenthesis
-                \btxdoifelse {director} {
+                \btxdoif {director} {
                     \removeunwantedspaces
                     \btxparameter{\c!separator:names:3}
                     \btxflush{director}
@@ -846,9 +851,7 @@
                     } {
                         \btxlabeltext{apa:Directors}
                     }
-                    \btxrightparenthesisperiod
-                } {
-                    \btxperiod
+                    \btxrightparenthesis
                 }
             } {
                 \doif {\btxfoundname{#author}} {director} {
@@ -858,10 +861,18 @@
                     } {
                         \btxlabeltext{apa:Directors}
                     }
-                    \btxrightparenthesisperiod
+                    \btxrightparenthesis
                 }
             }
         }
+        \btxdoif {withauthor} {
+            \btxleftparenthesis
+            \btxlabeltext{apa:with}
+            \btxspace
+            \btxflush{withauthor}
+            \btxrightparenthesis
+        }
+        \btxperiod
     }
 \stoptexdefinition
 
diff --git a/tex/context/base/publ-ini.mkiv b/tex/context/base/publ-ini.mkiv
index 211c5c00e..782f73e0c 100644
--- a/tex/context/base/publ-ini.mkiv
+++ b/tex/context/base/publ-ini.mkiv
@@ -350,7 +350,7 @@
    \publ_command_yes{#1}}
 
 \unexpanded\def\definebtxcommand#1% {body} #1..#n{body}
-  {\setuvalue{\??btxcommand\strippedcsname#1}}%
+  {\setuvalue{\??btxcommand\csstring#1}}%
 
 % tracing
 
diff --git a/tex/context/base/scrn-fld.mkvi b/tex/context/base/scrn-fld.mkvi
index 9a69bbdc5..b61920de4 100644
--- a/tex/context/base/scrn-fld.mkvi
+++ b/tex/context/base/scrn-fld.mkvi
@@ -746,12 +746,16 @@
 
 % todo: expand #symbols
 
+\installcorenamespace {fieldstack}
+
 \unexpanded\def\definefieldstack
   {\dotripleargument\scrn_fieldstack_define}
 
 \def\scrn_fieldstack_define[#tag][#symbols][#settings]%
-  {\ifcsname scrn_fieldstack:#tag\endcsname \else
-     \setgvalue{scrn_fieldstack:#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}%
+  {\ifcsname \??fieldstack#tag\endcsname
+     % already done
+   \else
+     \setgvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}%
    \fi}
 
 \unexpanded\def\fieldstack
@@ -761,7 +765,7 @@
   {\ifsecondargument
      \scrn_fieldstack_define[#tag][#symbols][#settings]%
    \fi
-   \getvalue{scrn_fieldstack:#tag}}
+   \csname\??fieldstack#tag\endcsname}
 
 \newbox\b_scrn_fieldstack_box
 
diff --git a/tex/context/base/scrp-cjk.lua b/tex/context/base/scrp-cjk.lua
index 0639f5583..1d8191008 100644
--- a/tex/context/base/scrp-cjk.lua
+++ b/tex/context/base/scrp-cjk.lua
@@ -956,7 +956,7 @@ local function process(head,first,last)
                         else -- if head ~= first then
                             if id == glue_code and getsubtype(first) == userskip_code then -- also scriptstatus check?
                                 -- for the moment no distinction possible between space and userskip
-                                local w = getfield(getfield(first,"spec"),"width")
+                                local w = getfield(first,"width")
                                 local s = spacedata[getfont(p)]
                                 if w == s then -- could be option
                                     if trace_details then
diff --git a/tex/context/base/spac-adj.mkiv b/tex/context/base/spac-adj.mkiv
index b8534303d..ad0f92a1f 100644
--- a/tex/context/base/spac-adj.mkiv
+++ b/tex/context/base/spac-adj.mkiv
@@ -45,7 +45,7 @@
   {\dowithnextboxcs\spac_vadjust_faked_finish\vtop}
 
 \def\spac_vadjust_faked_finish
-  {\setbox\nextbox\hbox{\llap{\lower\strutdepth\box\nextbox}}%
+  {\setbox\nextbox\hpack{\llap{\lower\strutdepth\box\nextbox}}%
    \smashedbox\nextbox}
 
 \protect \endinput
diff --git a/tex/context/base/spac-ali.lua b/tex/context/base/spac-ali.lua
index 880da6213..b85751a7c 100644
--- a/tex/context/base/spac-ali.lua
+++ b/tex/context/base/spac-ali.lua
@@ -28,7 +28,7 @@ local getattr          = nuts.getattr
 local setattr          = nuts.setattr
 local getsubtype       = nuts.getsubtype
 
-local hpack_nodes      = nuts.hpack -- nodes.fasthpack not really faster here
+local hpack_nodes      = nuts.hpack
 local linked_nodes     = nuts.linked
 
 local unsetvalue       = attributes.unsetvalue
diff --git a/tex/context/base/spac-ali.mkiv b/tex/context/base/spac-ali.mkiv
index 763d2001a..dbe46b4e0 100644
--- a/tex/context/base/spac-ali.mkiv
+++ b/tex/context/base/spac-ali.mkiv
@@ -514,7 +514,8 @@
    \c_spac_align_state_direction \zerocount % what is default ?
    \c_spac_align_state_page      \zerocount
    \ifcsname\??aligncommand\m_spac_align_asked\endcsname
-     \csname\??aligncommand\m_spac_align_asked\endcsname % not much gain in new method
+    %\csname\??aligncommand\m_spac_align_asked\endcsname % not much gain in new method
+     \lastnamedcs
    \else
      \rawprocesscommacommand[\m_spac_align_asked]\spac_align_collect
    \fi
@@ -681,8 +682,8 @@
 \setvalue{\??aligncommand\v!hz             }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\font_expansion_enable  }}
 \setvalue{\??aligncommand\v!fullhz         }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\font_expansion_enable_k}}
 \setvalue{\??aligncommand\v!nohz           }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\font_expansion_disable }}
-%setvalue{\??aligncommand\v!spacing        }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\enablespacehandling \enablekernhandling }} % not in mkiv
-%setvalue{\??aligncommand\v!nospacing      }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\disablespacehandling\disablekernhandling}} % not in mkiv
+%setvalue{\??aligncommand\v!spacing        }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\normalspacing\zerocount}} % not yet
+%setvalue{\??aligncommand\v!nospacing      }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\normalspacing\plusone}}   % not yet
 \setvalue{\??aligncommand\v!hyphenated     }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\dohyphens}}
 \setvalue{\??aligncommand\v!nothyphenated  }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\nohyphens}}
 
@@ -753,13 +754,15 @@
 
 \def\spac_align_set_ragged_vbox#1%
   {\ifcsname\??alignvertical#1\endcsname
-     \csname\??alignvertical#1\endcsname
+    %\csname\??alignvertical#1\endcsname
+     \lastnamedcs
      \quitcommalist
    \fi}
 
 \def\spac_align_set_ragged_hbox#1%
   {\ifcsname\??alignhorizontal#1\endcsname
-     \csname\??alignhorizontal#1\endcsname
+    %\csname\??alignhorizontal#1\endcsname
+     \lastnamedcs
      \quitcommalist
    \fi}
 
@@ -911,8 +914,11 @@
 \setuvalue{\??alignwrapper\v!right }{\doalignline\hss   \relax}
 \setuvalue{\??alignwrapper\v!max   }{\doalignline\relax \relax}
 
+\def\spac_align_wrapper_middle      {\doalignline\hss   \hss}
+
 \def\spac_align_wrapper_handle#1%
-  {\csname\??alignwrapper\ifcsname\??alignwrapper#1\endcsname#1\else\v!middle\fi\endcsname}
+ %{\csname\??alignwrapper\ifcsname\??alignwrapper#1\endcsname#1\else\v!middle\fi\endcsname}
+  {\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi}
 
 \unexpanded\def\spac_align_wrapper_start[#1]%
   {\spac_align_wrapper_handle{#1}%
@@ -996,7 +1002,12 @@
   {\csname\??alignline#1\endcsname} % no \resetrealignsignal here ?
 
 \def\alignedline#1#2% setting default
-  {\csname\??alignline\ifcsname\??alignline#1\endcsname#1\else#2\fi\endcsname}
+ % {\csname\??alignline\ifcsname\??alignline#1\endcsname#1\else#2\fi\endcsname}
+  {\ifcsname\??alignline#1\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \csname\??alignline#2\expandafter\endcsname
+   \fi}
 
 % beware: \wordright{whatever\kern-\rightskip} should work!
 % so, no funny boxing here
@@ -1074,26 +1085,72 @@
 \letvalue{\??alignsimplereverse\v!flushright}\spac_align_simple_left
 \letvalue{\??alignsimplereverse\v!middle    }\spac_align_simple_middle
 
+% \unexpanded\def\simplealignedbox#1#2%
+%   {\hbox \ifdim#1>\zeropoint to #1
+%      \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+%    \fi}
+
+% \unexpanded\def\simplealignedboxplus#1#2#3%
+%   {\hbox #3 \ifdim#1>\zeropoint to #1
+%      \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+%    \fi}
+
+% \unexpanded\def\simplealignedbox#1#2%
+%   {\hbox \ifdim#1>\zeropoint to #1
+%      \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+%    \fi}
+%
+% \unexpanded\def\simplealignedboxplus#1#2#3%
+%   {\hbox #3 \ifdim#1>\zeropoint to #1
+%      \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+%    \fi}
+
 \unexpanded\def\simplealignedbox#1#2%
   {\hbox \ifdim#1>\zeropoint to #1
-     \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+     \ifcsname\??alignsimple#2\endcsname
+       \doubleexpandafter\lastnamedcs
+     \else
+       \doubleexpandafter\spac_align_simple_left
+     \fi
    \fi}
 
 \unexpanded\def\simplealignedboxplus#1#2#3%
   {\hbox #3 \ifdim#1>\zeropoint to #1
-     \csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\expandafter\endcsname
+     \ifcsname\??alignsimple#2\endcsname
+       \doubleexpandafter\lastnamedcs
+     \else
+       \doubleexpandafter\spac_align_simple_left
+     \fi
    \fi}
 
 \newconditional\alignsimplelefttoright \settrue\alignsimplelefttoright
 
+% \unexpanded\def\simplereversealignedbox#1#2%
+%   {\hbox \ifdim#1>\zeropoint to #1
+%      \csname\??alignsimplereverse\ifcsname\??alignsimplereverse#2\endcsname#2\else\v!left\fi\expandafter\endcsname
+%    \fi}
+%
+% \unexpanded\def\simplereversealignedboxplus#1#2#3%
+%   {\hbox #3 \ifdim#1>\zeropoint to #1
+%      \csname\??alignsimplereverse\ifcsname\??alignsimplereverse#2\endcsname#2\else\v!left\fi\expandafter\endcsname
+%    \fi}
+
 \unexpanded\def\simplereversealignedbox#1#2%
   {\hbox \ifdim#1>\zeropoint to #1
-     \csname\??alignsimplereverse\ifcsname\??alignsimplereverse#2\endcsname#2\else\v!left\fi\expandafter\endcsname
+     \ifcsname\??alignsimplereverse#2\endcsname
+       \doubleexpandafter\lastnamedcs
+     \else
+       \doubleexpandafter\spac_align_simple_left
+     \fi
    \fi}
 
 \unexpanded\def\simplereversealignedboxplus#1#2#3%
   {\hbox #3 \ifdim#1>\zeropoint to #1
-     \csname\??alignsimplereverse\ifcsname\??alignsimplereverse#2\endcsname#2\else\v!left\fi\expandafter\endcsname
+     \ifcsname\??alignsimplereverse#2\endcsname
+       \doubleexpandafter\lastnamedcs
+     \else
+       \doubleexpandafter\spac_align_simple_left
+     \fi
    \fi}
 
 % \installnamespace{alignsets}
diff --git a/tex/context/base/spac-hor.mkiv b/tex/context/base/spac-hor.mkiv
index b677bacdf..8730f81cb 100644
--- a/tex/context/base/spac-hor.mkiv
+++ b/tex/context/base/spac-hor.mkiv
@@ -101,15 +101,42 @@
 \def\spac_indenting_define[#1][#2]% todo: mixes
   {\setevalue{\??indentingpreset#1}{#2}}
 
-\def\spac_indentation_apply_step_one_nested#1%
-  {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_one}
+% \def\spac_indentation_apply_step_one_nested#1%
+%   {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_one}
+%
+% \def\spac_indentation_apply_step_two_nested#1%
+%   {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_two}
+%
+% \def\spac_indentation_apply_step_one#1%
+%   {\ifcsname\??indentingpreset#1\endcsname
+%      \spac_indentation_apply_step_one_nested{#1}%
+%    \else\ifcsname\??indentingmethod#1\endcsname
+%      % case two
+%    \else
+%      \edef\v_spac_indentation_current{#1}% single entry in list
+%      \let\normalindentation\v_spac_indentation_current
+%      \spac_indentation_setup_size
+%    \fi\fi}
+%
+% \def\spac_indentation_apply_step_two#1%
+%   {\ifcsname\??indentingpreset#1\endcsname
+%      \spac_indentation_apply_step_two_nested{#1}%
+%    \else\ifcsname\??indentingmethod#1\endcsname
+%     %\csname\??indentingmethod#1\endcsname
+%      \lastnamedcs
+%    \else
+%      % case one
+%    \fi\fi}
+
+\def\spac_indentation_apply_step_one_nested
+  {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one}
 
-\def\spac_indentation_apply_step_two_nested#1%
-  {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_two}
+\def\spac_indentation_apply_step_two_nested
+  {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_two}
 
 \def\spac_indentation_apply_step_one#1%
   {\ifcsname\??indentingpreset#1\endcsname
-     \spac_indentation_apply_step_one_nested{#1}%
+     \spac_indentation_apply_step_one_nested
    \else\ifcsname\??indentingmethod#1\endcsname
      % case two
    \else
@@ -120,9 +147,10 @@
 
 \def\spac_indentation_apply_step_two#1%
   {\ifcsname\??indentingpreset#1\endcsname
-     \spac_indentation_apply_step_two_nested{#1}%
+     \spac_indentation_apply_step_two_nested
    \else\ifcsname\??indentingmethod#1\endcsname
-     \csname\??indentingmethod#1\endcsname
+    %\csname\??indentingmethod#1\endcsname
+     \lastnamedcs
    \else
      % case one
    \fi\fi}
@@ -275,12 +303,14 @@
 \installcorenamespace{indentnext}
 
 \unexpanded\def\checknextindentation[#1]%
-  {\csname\??indentnext\ifcsname\??indentnext#1\endcsname#1\fi\endcsname}
+ %{\csname\??indentnext\ifcsname\??indentnext#1\endcsname#1\fi\endcsname}
+  {\begincsname\??indentnext#1\endcsname}
 
 \unexpanded\def\useindentnextparameter#1% new, the more efficient variant
   {\edef\p_indentnext{#1\c!indentnext}%
    \ifx\p_indentnext\empty\else
-     \csname\??indentnext\ifcsname\??indentnext\p_indentnext\endcsname\p_indentnext\fi\endcsname
+    %\csname\??indentnext\ifcsname\??indentnext\p_indentnext\endcsname\p_indentnext\fi\endcsname
+     \begincsname\??indentnext\p_indentnext\endcsname
    \fi}
 
 \letvalue{\??indentnext       }\donothing
@@ -460,7 +490,17 @@
 \unexpanded\def\removelastspace{\ifhmode\unskip\fi}
 \unexpanded\def\nospace        {\removelastspace\ignorespaces}
 
-\ifdefined\softhyphen \else \let\softhyphen\- \fi
+\ifdefined\nospaces
+    \unexpanded\def\nospacing{\normalnospaces\plusone}
+    \unexpanded\def\dospacing{\normalnospaces\zerocount}
+\else
+    \unexpanded\def\nospacing{\spaceskip\scaledpoint     \xspaceskip\zeropoint}
+    \unexpanded\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what
+\fi
+
+\ifdefined\softhyphen \else
+    \let\softhyphen\-
+\fi
 
 \cldcontext{"\string\\unexpanded\string\\def\string\\\string\n{\string\\space}"}
 %cldcontext{"\string\\let\string\\\string\n=\string\\space"}
@@ -598,7 +638,8 @@
 
 \unexpanded\def\spac_narrower_method_analyze#1%
   {\ifcsname\??narrowermethod#1\endcsname
-     \csname\??narrowermethod#1\endcsname
+    %\csname\??narrowermethod#1\endcsname
+     \lastnamedcs
    \else
      \global\advance\s_spac_narrower_mid#1\relax
    \fi}
@@ -736,8 +777,11 @@
 \letvalue{\??skipadaptionright\v!no      }\zeropoint
 \letvalue{\??skipadaptionright\empty     }\zeropoint
 
-\unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax}
-\unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax}
+% \unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax}
+% \unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax}
+
+\unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax}
+\unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax}
 
 \unexpanded\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\advance\leftskip \leftskipadaption }
 \unexpanded\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\advance\rightskip\rightskipadaption}
diff --git a/tex/context/base/spac-pag.mkiv b/tex/context/base/spac-pag.mkiv
index 1ecc31d8c..c7d22f0e0 100644
--- a/tex/context/base/spac-pag.mkiv
+++ b/tex/context/base/spac-pag.mkiv
@@ -163,7 +163,7 @@
    \doforcedtrackpagestate{#2}{#3}%
    \edef\m_spac_pagestates_realpage{\pagestaterealpage{#2}{\number#3}}%
    \ifx\m_spac_pagestates_realpage\empty \else
-     \ifnum\m_spac_pagestates_realpage>0\getvalue{\??pagechanges#2:#1}\relax
+     \ifnum\m_spac_pagestates_realpage>0\csname\??pagechanges#2:#1\endcsname\relax
        \pagechangedtrue
      \fi
    \fi
diff --git a/tex/context/base/spac-prf.lua b/tex/context/base/spac-prf.lua
index 687671eff..6b153e15c 100644
--- a/tex/context/base/spac-prf.lua
+++ b/tex/context/base/spac-prf.lua
@@ -178,15 +178,14 @@ local function getprofile(line,step)
                     process(replace)
                 end
             elseif id == glue_code then
-                local spec = getfield(current,"spec")
-                wd = getfield(spec,"width")
+                wd = getfield(current,"width")
                 if glue_sign == 1 then
-                    if getfield(spec,"stretch_order") == glue_order then
-                        wd = wd + getfield(spec,"stretch") * glue_set
+                    if getfield(current,"stretch_order") == glue_order then
+                        wd = wd + getfield(current,"stretch") * glue_set
                     end
                 elseif glue_sign == 2 then
-                    if getfield(spec,"shrink_order") == glue_order then
-                        wd = wd - getfield(spec,"shrink") * glue_set
+                    if getfield(current,"shrink_order") == glue_order then
+                        wd = wd - getfield(current,"shrink") * glue_set
                     end
                 end
                 if getsubtype(current) >= leaders_code then
@@ -295,11 +294,11 @@ local function addstring(height,depth)
     local exheight = hashes.exheights[infofont]
     local httext   = height
     local dptext   = depth
-    local httext   = typesetters.fast_hpack(height,infofont)
-    local dptext   = typesetters.fast_hpack(depth,infofont)
+    local httext   = typesetters.tohpack(height,infofont)
+    local dptext   = typesetters.tohpack(depth,infofont)
     setfield(httext,"shift",- 1.2 * exheight)
     setfield(dptext,"shift",  0.6 * exheight)
-    local text = nuts.fasthpack(
+    local text = nuts.hpack(
         nuts.linked(
             new_kern(-getfield(httext,"width")-emwidth),
             httext,
@@ -671,8 +670,7 @@ local function profilelist(line,mvl)
                     end
                     break
                 elseif id == glue_code then
-                    local spec = getfield(current,"spec")
-                    local wd = getfield(spec,"width")
+                    local wd = getfield(current,"width")
                     if not wd or wd == 0 then
                         -- go on
                     else
@@ -746,8 +744,7 @@ local function profilelist(line,mvl)
                 if top then
                     local subtype = getsubtype(current)
                  -- if subtype == lineskip_code or subtype == baselineskip_code then
-                        local spec = getfield(current,"spec")
-                        local wd   = getfield(spec,"width")
+                        local wd   = getfield(current,"width")
                         if wd > 0 then
                             distance = wd
                             lastglue = current
@@ -852,8 +849,7 @@ function profiling.profilebox(specification)
             local subtype = getsubtype(current)
             if subtype == lineskip_code or subtype == baselineskip_code then
                 if top then
-                    local spec = getfield(current,"spec")
-                    local wd   = getfield(spec,"width")
+                    local wd   = getfield(current,"width")
                     if wd > 0 then
                         distance = wd
                         lastglue = current
diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua
index 7db01325f..6d27a1176 100644
--- a/tex/context/base/spac-ver.lua
+++ b/tex/context/base/spac-ver.lua
@@ -109,7 +109,7 @@ local remove_node         = nuts.remove
 local count_nodes         = nuts.count
 local hpack_node          = nuts.hpack
 local vpack_node          = nuts.vpack
-local writable_spec       = nuts.writable_spec
+----- writable_spec       = nuts.writable_spec
 local nodereference       = nuts.reference
 
 local theprop             = nuts.theprop
@@ -550,13 +550,13 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is
     if offset then
         -- we need to set the attr
         if t then
-            t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width"),getfield(current,"height"),getfield(current,"depth"))
+            t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width") or 0,getfield(current,"height"),getfield(current,"depth"))
         end
         local shifted = hpack_node(getlist(current))
         setfield(shifted,"shift",offset)
         setfield(current,"list",shifted)
         if t then
-            t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width"),getfield(current,"height"),getfield(current,"depth"))
+            t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width") or 0,getfield(current,"height"),getfield(current,"depth"))
         end
         setattr(shifted,a_snapmethod,0)
         setattr(current,a_snapmethod,0)
@@ -593,15 +593,21 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is
     return h, d, ch, cd, lines
 end
 
+-- local function snap_topskip(current,method)
+--     local spec = getfield(current,"spec")
+--     local w = w and getfield(spec,"width") or 0
+--     local wd = w
+--     if getfield(spec,"writable") then
+--         setfield(spec,"width",0)
+--         wd = 0
+--     end
+--     return w, wd
+-- end
+
 local function snap_topskip(current,method)
-    local spec = getfield(current,"spec")
-    local w = getfield(spec,"width")
-    local wd = w
-    if getfield(spec,"writable") then
-        setfield(spec,"width",0)
-        wd = 0
-    end
-    return w, wd
+    local w = getfield(current,"width") or 0
+    setfield(current,"width",0)
+    return w, 0
 end
 
 local categories = allocate {
@@ -844,18 +850,6 @@ local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip
 local topskip_code               = skipcodes.topskip
 local splittopskip_code          = skipcodes.splittopskip
 
--- local function free_glue_node(n)
---     free_node(n)
---     local s = getfield(n,"spec")
---     if s then
---         free_node(s)
---     end
--- end
-
-local free_glue_node = free_node
-local free_glue_spec = function() end
------ free_glue_spec = free_node -- can be enabled in in 0.73 (so for the moment we leak due to old luatex engine issues)
-
 function vspacing.snapbox(n,how)
     local sv = snapmethods[how]
     if sv then
@@ -909,7 +903,7 @@ local w, h, d = 0, 0, 0
 local function forced_skip(head,current,width,where,trace)
     if head == current then
         if getsubtype(head) == baselineskip_code then
-            width = width - getfield(getfield(head,"spec"),"width")
+            width = width - (getfield(head,"width") or 0)
         end
     end
     if width == 0 then
@@ -1055,7 +1049,7 @@ local function check_experimental_overlay(head,current)
         while c and c ~= n do
             local id = getid(c)
             if id == glue_code then
-                skips = skips + getfield(getfield(c,"glue_spec"),"width")
+                skips = skips + (getfield(c,"width") or 0)
             elseif id == kern_code then
                 skips = skips + getfield(c,"kern")
             end
@@ -1188,18 +1182,16 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
 -- end
         end
         if glue_data then
-            local spec = getfield(glue_data,"spec")
             if force_glue then
                 if trace then trace_done("flushed due to " .. why,glue_data) end
-                head = forced_skip(head,current,getfield(spec,"width"),"before",trace)
-                free_glue_node(glue_data)
-            elseif getfield(spec,"writable") then
+                head = forced_skip(head,current,getfield(glue_data,"width") or 0,"before",trace)
+                free_node(glue_data)
+            else
                 if trace then trace_done("flushed due to " .. why,glue_data) end
                 head = insert_node_before(head,current,glue_data)
-            else
-                free_glue_node(glue_data)
             end
         end
+
         if trace then trace_node(current) end
         glue_order, glue_data, force_glue = 0, nil, false
         penalty_order, penalty_data, natural_penalty = 0, nil, nil
@@ -1356,27 +1348,16 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
                         -- todo: prev can be whatsit (latelua)
                         local previous = getprev(current)
                         if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then
-                            local ps = getfield(previous,"spec")
-                            if getfield(ps,"writable") then
-                                local cs = getfield(current,"spec")
-                                if getfield(cs,"writable") and getfield(ps,"stretch_order") == 0 and getfield(ps,"shrink_order") == 0 and getfield(cs,"stretch_order") == 0 and getfield(cs,"shrink_order") == 0 then
-                                    local pw, pp, pm = getfield(ps,"width"), getfield(ps,"stretch"), getfield(ps,"shrink")
-                                    local cw, cp, cm = getfield(cs,"width"), getfield(cs,"stretch"), getfield(cs,"shrink")
-                                 -- ps = writable_spec(previous) -- no writable needed here
-                                 -- ps.width, ps.stretch, ps.shrink = pw + cw, pp + cp, pm + cm
-                                    free_glue_spec(ps)
-                                    setfield(previous,"spec",new_gluespec(pw + cw, pp + cp, pm + cm)) -- else topskip can disappear
-                                    if trace then trace_natural("removed",current) end
-                                    head, current = remove_node(head, current, true)
-                                 -- current = previous
-                                    if trace then trace_natural("collapsed",previous) end
-                                 -- current = getnext(current)
-                                else
-                                    if trace then trace_natural("filler",current) end
-                                    current = getnext(current)
-                                end
+                            if getfield(previous,"stretch_order") == 0 and getfield(previous,"shrink_order") == 0 and
+                               getfield(current, "stretch_order") == 0 and getfield(current, "shrink_order") == 0 then
+                                setfield(previous,"width",  (getfield(previous,"width")   or 0) + (getfield(current,"width")   or 0))
+                                setfield(previous,"stretch",(getfield(previous,"stretch") or 0) + (getfield(current,"stretch") or 0))
+                                setfield(previous,"shrink", (getfield(previous,"shrink")  or 0) + (getfield(current,"shrink")  or 0))
+                                if trace then trace_natural("removed",current) end
+                                head, current = remove_node(head, current, true)
+                                if trace then trace_natural("collapsed",previous) end
                             else
-                                if trace then trace_natural("natural (no prev spec)",current) end
+                                if trace then trace_natural("filler",current) end
                                 current = getnext(current)
                             end
                         else
@@ -1415,16 +1396,16 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
                 elseif glue_order < so then
                     if trace then trace_skip("force",sc,so,sp,current) end
                     glue_order = so
-                    free_glue_node(glue_data)
+                    free_node(glue_data)
                     head, current, glue_data = remove_node(head, current)
                 elseif glue_order == so then
                     -- is now exclusive, maybe support goback as combi, else why a set
                     if sc == largest then
-                        local cs, gs = getfield(current,"spec"), getfield(glue_data,"spec")
-                        local cw, gw = getfield(cs,"width"), getfield(gs,"width")
+                        local cw = getfield(current,"width")   or 0
+                        local gw = getfield(glue_data,"width") or 0
                         if cw > gw then
                             if trace then trace_skip("largest",sc,so,sp,current) end
-                            free_glue_node(glue_data) -- also free spec
+                            free_node(glue_data)
                             head, current, glue_data = remove_node(head,current)
                         else
                             if trace then trace_skip("remove smallest",sc,so,sp,current) end
@@ -1432,26 +1413,24 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
                         end
                     elseif sc == goback then
                         if trace then trace_skip("goback",sc,so,sp,current) end
-                        free_glue_node(glue_data) -- also free spec
+                        free_node(glue_data)
                         head, current, glue_data = remove_node(head,current)
                     elseif sc == force then
                         -- last one counts, some day we can provide an accumulator and largest etc
                         -- but not now
                         if trace then trace_skip("force",sc,so,sp,current) end
-                        free_glue_node(glue_data) -- also free spec
+                        free_node(glue_data)
                         head, current, glue_data = remove_node(head, current)
                     elseif sc == penalty then
                         if trace then trace_skip("penalty",sc,so,sp,current) end
-                        free_glue_node(glue_data) -- also free spec
+                        free_node(glue_data)
                         glue_data = nil
                         head, current = remove_node(head, current, true)
                     elseif sc == add then
                         if trace then trace_skip("add",sc,so,sp,current) end
-                     -- local old, new = glue_data.spec, getfield(current,"spec")
-                        local old, new = writable_spec(glue_data), getfield(current,"spec")
-                        setfield(old,"width",getfield(old,"width") + getfield(new,"width"))
-                        setfield(old,"stretch",getfield(old,"stretch") + getfield(new,"stretch"))
-                        setfield(old,"shrink",getfield(old,"shrink") + getfield(new,"shrink"))
+                        setfield(old,"width",  (getfield(glue_data,"width")   or 0) + (getfield(current,"width")   or 0))
+                        setfield(old,"stretch",(getfield(glue_data,"stretch") or 0) + (getfield(current,"stretch") or 0))
+                        setfield(old,"shrink", (getfield(glue_data,"shrink")  or 0) + (getfield(current,"shrink")  or 0))
                         -- toto: order
                         head, current = remove_node(head, current, true)
                     else
@@ -1470,13 +1449,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
                     local s = getattr(current,a_snapmethod)
                     if s and s ~= 0 then
                         setattr(current,a_snapmethod,0)
-                        local spec = getfield(current,"spec")
-                        if getfield(spec,"writable") then
-                            local spec = writable_spec(current)
-                            setfield(spec,"width",0)
-                            if trace_vsnapping then
-                                report_snapper("lineskip set to zero")
-                            end
+                        setfield(current,"width",0)
+                        if trace_vsnapping then
+                            report_snapper("lineskip set to zero")
                         end
                     else
                         if trace then trace_skip("lineskip",sc,so,sp,current) end
@@ -1492,13 +1467,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
                     local s = getattr(current,a_snapmethod)
                     if s and s ~= 0 then
                         setattr(current,a_snapmethod,0)
-                        local spec = getfield(current,"spec")
-                        if getfield(spec,"writable") then
-                            local spec = writable_spec(current)
-                            setfield(spec,"width",0)
-                            if trace_vsnapping then
-                                report_snapper("baselineskip set to zero")
-                            end
+                        setfield(current,"width",0)
+                        if trace_vsnapping then
+                            report_snapper("baselineskip set to zero")
                         end
                     else
                         if trace then trace_skip("baselineskip",sc,so,sp,current) end
@@ -1515,15 +1486,14 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
                     if trace then trace_natural("ignored parskip",current) end
                     head, current = remove_node(head, current, true)
                 elseif glue_data then
-                    local ps = getfield(current,"spec")
-                    local gs = getfield(glue_data,"spec")
-                    if getfield(ps,"writable") and getfield(gs,"writable") and getfield(ps,"width") > getfield(gs,"width") then
-                        setfield(glue_data,"spec",copy_node(ps))
+                    if (getfield(current,"width") or 0) > (getfield(glue_data,"width") or 0) then
+                        glue_data = current
+                        head, current = remove_node(head, current)
                         if trace then trace_natural("taking parskip",current) end
                     else
+                        head, current = remove_node(head, current, true)
                         if trace then trace_natural("removed parskip",current) end
                     end
-                    head, current = remove_node(head, current, true)
                 else
                     if trace then trace_natural("honored parskip",current) end
                     head, current, glue_data = remove_node(head, current)
@@ -1573,10 +1543,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
                 --
             else -- other glue
                 if snap and trace_vsnapping then
-                    local spec = getfield(current,"spec")
-                    if getfield(spec,"writable") and getfield(spec,"width") ~= 0 then
-                        report_snapper("glue %p of type %a kept",getfield(spec,"width"),skipcodes[subtype])
-                     -- setfield(spec,"width",0)
+                    local w = getfield(current,"width") or 0
+                    if w ~= 0 then
+                        report_snapper("glue %p of type %a kept",w,skipcodes[subtype])
                     end
                 end
                 if trace then trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current) end
@@ -1616,9 +1585,8 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
         if not tail then tail = find_node_tail(head) end
         if trace then trace_done("result",glue_data) end
         if force_glue then
-            local spec = getfield(glue_data,"spec")
-            head, tail = forced_skip(head,tail,getfield(spec,"width"),"after",trace)
-            free_glue_node(glue_data)
+            head, tail = forced_skip(head,tail,getfield(glue_data,"width") or 0,"after",trace)
+            free_node(glue_data)
         else
             head, tail = insert_node_after(head,tail,glue_data)
         end
diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv
index 7620b7b5a..41617bd2b 100644
--- a/tex/context/base/spac-ver.mkiv
+++ b/tex/context/base/spac-ver.mkiv
@@ -132,7 +132,8 @@
 
 \def\spac_linespacing_setup_relative_interlinespace#1%
   {\ifcsname\??interlinespacerelative#1\endcsname
-     \csname\??interlinespacerelative#1\endcsname
+    %\csname\??interlinespacerelative#1\endcsname
+     \lastnamedcs
    \else
      \spac_linespacing_set_specified_relative_interlinespace{#1}%
    \fi}
@@ -370,7 +371,8 @@
 
 \def\spac_whitespace_setup % quick test for no list
   {\ifcsname\??whitespacemethod\v_spac_whitespace_current\endcsname
-     \csname\??whitespacemethod\v_spac_whitespace_current\endcsname
+    %\csname\??whitespacemethod\v_spac_whitespace_current\endcsname
+     \lastnamedcs
    \else
      \expandafter\processcommalist\expandafter[\v_spac_whitespace_current]\spac_whitespace_setup_method % can be raw
    \fi\relax
@@ -418,11 +420,12 @@
 \installwhitespacemethod \v!medium      {\s_spac_whitespace_parskip   \medskipamount}
 \installwhitespacemethod \v!small       {\s_spac_whitespace_parskip   \smallskipamount}
 
-\installwhitespacemethod \s!default     {\spac_whitespace_setup_nop}
+\installwhitespacemethod \s!default     {\spac_whitespace_setup_nop} % also covers none
 
 \def\spac_whitespace_setup_method#1%
   {\ifcsname\??whitespacemethod#1\endcsname
-     \csname\??whitespacemethod#1\endcsname
+    %\csname\??whitespacemethod#1\endcsname
+     \lastnamedcs
    \else
      \s_spac_whitespace_parskip#1\fi
    \relax}
@@ -441,8 +444,8 @@
 % \def\spac_whitespace_setup_method#1%
 %   {\csname\??whitespacemethod\ifcsname\??whitespacemethod#1\endcsname#1\else\s!unknown\endcsname\relax}
 
-\unexpanded\def\nowhitespace{\vspacing[\v!nowhite]}
-\unexpanded\def\whitespace  {\vspacing[\v!white]}
+\unexpanded\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]}
+\unexpanded\def\whitespace  {\directcheckedvspacing\v!white}   % {\vspacing[\v!white]}
 
 \setupwhitespace
   [\v!none]
@@ -463,9 +466,9 @@
    \ifnum\c_spac_packed_level=\plusone \ifvmode
      \begingroup
      \whitespace % not combined
-     \blank[\v!disable]%
+     \directcheckedvspacing\v!disable % \blank[\v!disable]% or \inhibitblank
      \doifelse{#1}\v!blank\settrue\setfalse\c_spac_packed_blank
-     \setupwhitespace[\v!none]%
+     \setupwhitespace[\v!none]% or \forgetparskip
    \fi \fi}
 
 \unexpanded\def\stoppacked
@@ -476,12 +479,12 @@
    \global\advance\c_spac_packed_level\minusone}
 
 \unexpanded\def\startunpacked
-  {\blank
+  {\directdefaultvspacing % \blank
    \begingroup}
 
 \unexpanded\def\stopunpacked
   {\endgroup
-   \blank}
+   \directdefaultvspacing}% \blank}
 
 % \prevdepth crosses pageboundaries!
 %
@@ -506,7 +509,7 @@
 
 \setvalue{\??linesaround\v!blank  }{\blank}
 \letvalue{\??linesaround\empty    }\relax
-\setvalue{\??linesaround\s!unknown}{\blank[\m_spac_lines_around]}
+\setvalue{\??linesaround\s!unknown}{\directcheckedvspacing\m_spac_lines_around} % \blank[\m_spac_lines_around]}
 
 \def\spac_lines_action_around % we used to let this one but it's cleaner this way
   {\csname\??linesaround      % i.e. do it twice
@@ -555,11 +558,11 @@
    \endgroup}
 
 \unexpanded\def\spac_lines_stop_correction_ongrid
-  {\blank[\v!white]%
-   \snaptogrid\hbox{\box\scratchbox}}
+  {\directcheckedvspacing\v!white % \blank[\v!white]%
+   \snaptogrid\hpack{\box\scratchbox}}
 
 \unexpanded\def\spac_lines_stop_correction_normal
-  {\blank[\v!nowhite]%
+  {\directcheckedvspacing\v!nowhite % \blank[\v!nowhite]%
    \ifdim\parskip>\zeropoint
       % too fuzzy otherwise
    \else
@@ -579,7 +582,8 @@
      \fi
    \fi
    \ifdim\pagegoal<\maxdimen
-     \blank[\v!white,\the\d_spac_lines_correction_before]% \blank[\v!white]\dotopbaselinecorrection
+    %\blank[\v!white,\the\d_spac_lines_correction_before]% \blank[\v!white]\dotopbaselinecorrection
+     \directcheckedvspacing{\v!white,\the\d_spac_lines_correction_before}% \blank[\v!white]\dotopbaselinecorrection
    \fi
    \nointerlineskip % new
    \noindent % not \dontleavehmode !
@@ -593,7 +597,8 @@
    \fi
    \box\scratchbox
    \endgraf
-   \blank[\the\d_spac_lines_correction_after]% \dobotbaselinecorrection
+  %\blank[\the\d_spac_lines_correction_after]% \dobotbaselinecorrection
+   \directcheckedvspacing{\the\d_spac_lines_correction_after}% \dobotbaselinecorrection
  % \allowbreak % new, otherwise problems when many in a row
    \prevdepth\strutdp
    \spac_lines_action_around}
@@ -612,8 +617,8 @@
    \flushnextbox
    \stopbaselinecorrection}
 
-\unexpanded\def\verticalstrut  {\vbox{\hsize\zeropoint\forgetall\strut}}
-\unexpanded\def\horizontalstrut{\hbox                          {\strut}}
+\unexpanded\def\verticalstrut  {\vpack{\hsize\zeropoint\forgetall\strut}}
+\unexpanded\def\horizontalstrut{\hpack                          {\strut}}
 
 % Hieronder volgen enkele instellingen en macro's ten behoeve
 % van de interlinie en \strut. De waarden 2.8, 0.07, 0.72 en
@@ -833,7 +838,7 @@
 
 \newbox\strutbox
 
-\setbox\strutbox\hbox{\vrule\s!height8.5pt\s!depth3.5pt\s!width\zeropoint} % just a start
+\setbox\strutbox\hpack{\vrule\s!height8.5pt\s!depth3.5pt\s!width\zeropoint} % just a start
 
 \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
 
@@ -887,7 +892,7 @@
    \dosetstrut}
 
 \unexpanded\def\setcharstrut#1%
-  {\setbox\strutbox\hbox{#1}%
+  {\setbox\strutbox\hbox{#1}% hm, maybe hpack i.e. why apply fonts .. conceptual choice
    \strutht\ht\strutbox
    \strutdp\dp\strutbox
    \dosetstrut}
@@ -938,7 +943,7 @@
    \fi}
 
 \def\spac_struts_set_hide
-  {\setbox\strutbox\hbox
+  {\setbox\strutbox\hpack
      {\vrule
         \s!width \zeropoint
         \s!height\strutht
@@ -947,7 +952,7 @@
 \newconstant\c_strut_visual_mode
 
 \def\spac_struts_set_vide
-  {\setbox\strutbox\hbox  % at some time this extra wrapping was needed
+  {\setbox\strutbox\hpack  % at some time this extra wrapping was needed
      {\spac_struts_vide_hbox to \zeropoint
         {\ifcase\c_strut_visual_mode
            \spac_struts_black
@@ -1061,7 +1066,8 @@
 \def\spac_struts_setup[#1]%
   {\edef\m_strut{#1}%
    \ifcsname\??struts\m_strut\endcsname
-     \csname\??struts\m_strut\endcsname % these are defined later
+    %\csname\??struts\m_strut\endcsname % these are defined later
+     \lastnamedcs
    \else
      \setcharstrut\m_strut
    \fi}
@@ -1069,16 +1075,18 @@
 \unexpanded\def\synchronizestrut#1% no [] parsing, faster for internal
   {\edef\m_strut{#1}%
    \ifcsname\??struts\m_strut\endcsname
-     \csname\??struts\m_strut\endcsname
+    %\csname\??struts\m_strut\endcsname
+     \lastnamedcs
    \else
      \setcharstrut\m_strut
    \fi}
 
 \unexpanded\def\dosynchronizestrut#1% no [] parsing, faster for internal
   {\ifcsname\??struts#1\endcsname
-     \csname\??struts#1\endcsname
+    %\csname\??struts#1\endcsname
+     \lastnamedcs
    \else
-     \setcharstrut\m_strut
+     \setcharstrut{#1}%
    \fi}
 
 \unexpanded\def\showstruts % adapts .. is wrong
@@ -1459,11 +1467,13 @@
 
 \def\spac_grids_snap_value_set#1%
   {%\gridsnappingtrue
-   \ifcsname\??gridsnappers#1\endcsname\csname\??gridsnappers#1\endcsname\fi}
+  %\ifcsname\??gridsnappers#1\endcsname\csname\??gridsnappers#1\endcsname\fi}
+   \begincsname\??gridsnappers#1\endcsname}
 
 \def\spac_grids_snap_value_auto#1%
   {\ifcsname\??gridsnappers#1\endcsname
-     \csname\??gridsnappers#1\endcsname
+    %\csname\??gridsnappers#1\endcsname
+     \lastnamedcs
    \else
      \installsnapvalues\s!dummy{#1}%
      \csname\??gridsnappers\s!dummy\endcsname
@@ -1604,7 +1614,7 @@
    \fi
    \doifelsenothing{#1}{\spac_grids_snap_value_set\v!normal}{\spac_grids_snap_value_set{#1}}%
    \clf_vspacingsnap\nextbox\attribute\snapmethodattribute\relax
-   \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}%
+   \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% pack ?
    \egroup}
 
 \def\spac_grids_check_nop
@@ -1668,6 +1678,7 @@
 \unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
   {\setbox#1\gridboxvbox to #3 % given size
      {\forgetall
+      \resetvisualizers
       \resetteststrut
       \offinterlineskip
       \hsize#2%
@@ -1907,6 +1918,22 @@
 \def\directvspacing#1%
   {\par\clf_vspacing{#1}}
 
+\def\directcheckedvspacing
+  {\ifinpagebody % somewhat weird
+     \expandafter\directvspacing
+   \else\ifconditional\c_spac_packed_blank
+     \doubleexpandafter\directvspacing
+   \else
+     \doubleexpandafter\gobbleoneargument
+   \fi\fi}
+
+\def\directdefaultvspacing
+  {\ifinpagebody % somewhat weird
+     \clf_vspacing{\currentvspacing}%
+   \else\ifconditional\c_spac_packed_blank
+     \clf_vspacing{\currentvspacing}%
+   \fi\fi}
+
 % handy (and faster):
 
 \unexpanded\def\directvpenalty#1%
@@ -1986,7 +2013,7 @@
 \newdimen\d_spac_overlay
 
 \def\spac_overlay_lines
-  {\blank[\v!back,\v!overlay]%
+  {\directcheckedvspacing{\v!back,\v!overlay}% \blank[\v!back,\v!overlay]%
    \nointerlineskip}
 
 % \startitemize[n]
@@ -2087,34 +2114,66 @@
 \unexpanded\def\vspace
   {\dodoubleempty\spac_vspace_inject}
 
-\def\spac_vspace_inject[#1][#2]%
+% \def\spac_vspace_inject[#1][#2]% use \lastnamedcs
+%   {\par
+%    \ifvmode
+%      \removelastskip
+%      \vskip
+%        \csname\??vspace
+%          \ifsecondargument
+%            \ifcsname\??vspace#1:#2\endcsname
+%              #1:#2%
+%            \else\ifcsname\??vspace:#2\endcsname
+%              :#2%
+%            \else
+%              :\s!unknown
+%            \fi\fi
+%          \else\iffirstargument
+%            \ifcsname\??vspace:#1\endcsname
+%              :#1%
+%            \else
+%              :\s!unknown
+%            \fi
+%          \else
+%            \ifcsname\??vspace:\s!default\endcsname
+%              :\s!default
+%            \else
+%              :\s!unknown
+%            \fi
+%          \fi\fi
+%        \endcsname
+%      \relax
+%    \fi}
+
+\def\spac_vspace_unknown
+  {\csname\??vspace:\s!unknown\endcsname}
+
+\def\spac_vspace_inject[#1][#2]% use \lastnamedcs
   {\par
    \ifvmode
      \removelastskip
      \vskip
-       \csname\??vspace
-         \ifsecondargument
-           \ifcsname\??vspace#1:#2\endcsname
-             #1:#2%
-           \else\ifcsname\??vspace:#2\endcsname
-             :#2%
-           \else
-             :\s!unknown
-           \fi\fi
-         \else\iffirstargument
-           \ifcsname\??vspace:#1\endcsname
-             :#1%
-           \else
-             :\s!unknown
-           \fi
+       \ifsecondargument
+         \ifcsname\??vspace#1:#2\endcsname
+           \lastnamedcs
+         \else\ifcsname\??vspace:#2\endcsname
+           \lastnamedcs
          \else
-           \ifcsname\??vspace:\s!default\endcsname
-             :\s!default
-           \else
-             :\s!unknown
-           \fi
+           \spac_vspace_unknown
          \fi\fi
-       \endcsname
+       \else\iffirstargument
+         \ifcsname\??vspace:#1\endcsname
+           \lastnamedcs
+         \else
+           \spac_vspace_unknown
+         \fi
+       \else
+         \ifcsname\??vspace:\s!default\endcsname
+           \lastnamedcs
+         \else
+           \spac_vspace_unknown
+         \fi
+       \fi\fi
      \relax
    \fi}
 
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index a56679347..ae4f2844e 100644
Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
index f2b041597..006b71eb8 100644
Binary files a/tex/context/base/status-lua.pdf and b/tex/context/base/status-lua.pdf differ
diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua
index 9b320c651..3fe9e0d8e 100644
--- a/tex/context/base/status-mkiv.lua
+++ b/tex/context/base/status-mkiv.lua
@@ -2613,12 +2613,6 @@ return {
   },
  },
  lua = {
-  {
-   category = "lua",
-   filename = "anch-pgr",
-   loading  = "anch-pgr",
-   status   = "okay",
-  },
   {
    category = "lua",
    filename = "anch-pos",
@@ -4217,6 +4211,12 @@ return {
    loading  = "pack-rul",
    status   = "okay",
   },
+  {
+   category = "lua",
+   filename = "page-otr",
+   loading  = "page-otr",
+   status   = "okay",
+  },
   {
    category = "lua",
    filename = "page-flt",
diff --git a/tex/context/base/strc-flt.mkvi b/tex/context/base/strc-flt.mkvi
index 02aae2224..a367c5ba7 100644
--- a/tex/context/base/strc-flt.mkvi
+++ b/tex/context/base/strc-flt.mkvi
@@ -385,7 +385,7 @@
        \fi
      \else
        \global\emptyfloatcaptionfalse
-       \setbox\b_strc_floats_caption\hbox{\hskip\leftskip\box\b_strc_floats_caption}%
+       \setbox\b_strc_floats_caption\hpack{\hskip\leftskip\box\b_strc_floats_caption}%
      \fi
    \fi}
 
@@ -888,17 +888,17 @@
    \global\setfalse\usesamefloatnumber % one shot
    % check float box
    \strc_floats_set_natural_dimensions\nextbox
-   \global\setbox\floatbox\vbox{\floatparameter\c!command{\box\nextbox}}%
+   \global\setbox\floatbox\vbox{\floatparameter\c!command{\box\nextbox}}% can be anything so no pack
    \strc_floats_set_natural_dimensions\floatbox
    \ifdim\htdp\floatbox=\zeropoint
      \showmessage\m!floatblocks{11}\empty
-     \global\setbox\floatbox\vbox
+     \global\setbox\floatbox\vpack
        {\dostarttagged\t!floatcontent\empty
         \strc_floats_place_empty_box
         \dostoptagged}%
    \fi
    % deal with lack of caption
-   \global\setbox\floatbox\vbox \floatcaptionattribute
+   \global\setbox\floatbox\vpack \floatcaptionattribute
      {\doifelsemainfloatbody\currentfloatsynchronize\donothing
       \unvbox\floatbox
       \ifnofloatcaption
@@ -1070,7 +1070,7 @@
   {\global\d_page_sides_shift  \zeropoint       % duplicate
    \global\d_page_sides_maximum\zeropoint\relax % duplicate
    \ifdim\d_page_sides_downshift=\zeropoint\else
-     \global\setbox\floatbox\vbox
+     \global\setbox\floatbox\vpack
        {\vskip\d_page_sides_downshift
         \nointerlineskip
         \box\floatbox}%
@@ -1106,13 +1106,13 @@
    \fi}
 
 \def\strc_floats_realign_floatbox_horizontal_one
-  {\global\setbox\floatbox\hbox to \scratchwidth
+  {\global\setbox\floatbox\hpack to \scratchwidth
      {\doifnotinset\v!right\floatlocation\hss
       \box\floatbox
       \doifnotinset\v!left \floatlocation\hss}}
 
 \def\strc_floats_realign_floatbox_horizontal_two
-  {\global\setbox\floatbox\hbox to \scratchwidth
+  {\global\setbox\floatbox\hpack to \scratchwidth
      {\doifnot{\floatparameter\c!location}\v!left \hss
       \box\floatbox
       \doifnot{\floatparameter\c!location}\v!right\hss}}
@@ -1207,7 +1207,7 @@
   {\egroup
    \doifnotinset\v!tall\floatlocation
      {\floattextheight\ifdim\ht\floattext<\floatheight\floatheight\else\ht\floattext\fi}%
-   \setbox\floatbox\vbox to \floattextheight
+   \setbox\floatbox\vpack to \floattextheight
      {\hsize\floatwidth
       \doifelseinset\v!both\floatlocation
         {\doifelseinset\v!low\floatlocation
@@ -1216,7 +1216,7 @@
               {\vfill\box\floatbox\vfill}
               {\box\floatbox\vfill}}}
         {\box\floatbox\vfill}}%
-    \setbox\floattext\vbox to \floattextheight
+    \setbox\floattext\vpack to \floattextheight
      {\hsize\floattextwidth
       \doifelseinset\v!low\floatlocation
         {\vfill
@@ -1230,11 +1230,11 @@
             \box\floattext
             \vfill}}}%
    \doifelseinset\v!right\floatlocation
-     {\setbox\floatbox\hbox to \hsize
+     {\setbox\floatbox\hpack to \hsize
         {\box\floattext
          \hfill
          \box\floatbox}}
-     {\setbox\floatbox\hbox to \hsize
+     {\setbox\floatbox\hpack to \hsize
         {\box\floatbox
          \hfill
          \box\floattext}}%
@@ -1288,7 +1288,7 @@
    \forgetall
    \postponenotes
    \dontcomplain
-   \setbox\b_strc_floats_content\vbox{\borderedfloatbox}%
+   \setbox\b_strc_floats_content\vpack{\borderedfloatbox}%
    \let\strc_floats_align_content\strc_floats_align_content_indeed
    \let\strc_floats_align_caption\strc_floats_align_caption_indeed
    \strc_floats_check_caption_content
@@ -1304,7 +1304,7 @@
        % todo: installable maken, variant/method=auto vs macro
        \strc_floats_prepare_page_caption
       %\page_backgrounds_add_local_to_box\b_strc_floats_content
-       \setbox\b_strc_floats_caption\hbox
+       \setbox\b_strc_floats_caption\hbox % text
          {\floatcaptionparameter\c!command{\box\b_strc_floats_caption}}%
        \moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height
       %\page_backgrounds_add_local_to_box\b_strc_floats_caption
@@ -1319,13 +1319,13 @@
      \doifnotinset\v!margin\floatlocation % brr, really needed! see wm
        {\postcenterfloatbox\d_strc_floats_content}%
    \else
-     \global\setbox\floatbox\vbox
+     \global\setbox\floatbox\vpack
        {\rotate[\c!rotation=\number\c_strc_floats_rotation]{\box\floatbox}}%
    \fi
    \egroup}
 
 \def\strc_floats_prepare_no_caption
-  {\global\setbox\floatbox\vbox % pas op als wd groter dan hsize
+  {\global\setbox\floatbox\vpack % pas op als wd groter dan hsize
      {\ifinsidecolumns\ifdim\wd\b_strc_floats_content>\hsize
         \let\strc_floats_align_content\relax
       \fi\fi
@@ -1424,70 +1424,6 @@
       \fi
       \strc_floats_make_complete_caption}}
 
-% \def\strc_floats_prepare_stack_caption_auto
-%   {\ifx\p_strc_floats_caption_align\empty \else
-%      \doifnotinset\v!middle\p_strc_floats_caption_align{\let\captionovershoot\!!zeropoint}%
-%    \fi
-%    \edef\captionhsize{\the\wd\b_strc_floats_content}%
-%    \ifdim\captionhsize>\hsize
-%      % float is wider than \hsize
-%      \setbox\b_strc_floats_caption\vbox
-%        {\settrialtypesetting
-%         \strc_floats_caption_set_align
-%         \hsize\captionhsize
-%         \notesenabledfalse
-%         \strc_floats_make_complete_caption}%
-%      \ifdim\ht\scratchbox>\lineheight % more lines
-%        \setbox\b_strc_floats_caption\vbox
-%          {\strc_floats_caption_set_align
-%           \hsize\dimexpr\captionhsize-\captionovershoot\relax
-%           \ifdim\hsize<\captionminwidth\relax
-%             \hsize\captionhsize
-%           \fi
-%           \strc_floats_make_complete_caption}%
-%      \else
-%        \setbox\b_strc_floats_caption\vbox
-%          {\strc_floats_caption_set_align
-%           \hsize\captionhsize
-%           \strc_floats_make_complete_caption}%
-%      \fi
-%    \else
-%      % float is smaller of equal to \hsize
-%      \ifdim\captionhsize<\captionminwidth\relax
-%        \scratchdimen\captionminwidth % float smaller than min width
-%        \edef\captionhsize{\the\scratchdimen}%
-%      \fi
-%      \setbox\scratchbox\vbox     % test with overshoot
-%        {\settrialtypesetting
-%         \scratchdimen\dimexpr\captionhsize+\captionovershoot+3\emwidth\relax % 3em is an average word length
-%         \ifdim\scratchdimen<\hsize
-%           \hsize\scratchdimen
-%         \fi
-%         \notesenabledfalse
-%         \strc_floats_make_complete_caption}%
-%      \ifdim\ht\scratchbox>\lineheight
-%        % at least an average word longer than a line
-%        \setbox\b_strc_floats_caption\vbox
-%          {\strc_floats_caption_set_align
-%           \scratchdimen\dimexpr\captionhsize+\captionovershoot\relax
-%           \ifdim\scratchdimen<\hsize
-%             \hsize\scratchdimen
-%           \fi
-%           \strc_floats_make_complete_caption}%
-%      \else\ifx\p_strc_floats_caption_align\empty
-%        \setbox\b_strc_floats_caption\vbox
-%          {\strc_floats_caption_set_align
-%           \hsize\captionhsize
-%           \raggedcenter % overloads
-%           \strc_floats_make_complete_caption}%
-%      \else
-%        \setbox\b_strc_floats_caption\vbox
-%          {\strc_floats_caption_set_align
-%           \hsize\captionhsize
-%           \strc_floats_make_complete_caption}%
-%      \fi\fi
-%    \fi}
-
 \def\strc_floats_prepare_stack_caption_auto
   {\ifx\p_strc_floats_caption_align\empty \else
      \doifnotinset\v!middle\p_strc_floats_caption_align{\let\captionovershoot\!!zeropoint}%
@@ -1563,7 +1499,7 @@
   {\strc_floats_align_content{\box\b_strc_floats_content}}
 
 \def\strc_floats_build_box_next_right#1%
-  {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+  {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % skip, no pack
      {\d_strc_float_temp_height\ht\b_strc_floats_content
       \box\b_strc_floats_content
       \doifnotinset\v!hang{\floatcaptionparameter\c!location}
@@ -1571,7 +1507,7 @@
       \vbox to\d_strc_float_temp_height{#1}}}
 
 \def\strc_floats_build_box_next_left#1%
-  {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+  {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % skip, no pack
      {\d_strc_float_temp_height\ht\b_strc_floats_content
       \vbox to\d_strc_float_temp_height{#1}%
       \doifnotinset\v!hang{\floatcaptionparameter\c!location}
@@ -1585,23 +1521,23 @@
   {\doifelserightpagefloat\strc_floats_build_box_next_left\strc_floats_build_box_next_right}
 
 \def\strc_floats_build_box_next_right_hang#1%
-  {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+  {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi
      {\d_strc_float_temp_height\ht\b_strc_floats_content
       \box\b_strc_floats_content
       \vbox to\d_strc_float_temp_height{#1}}}
 
 \def\strc_floats_build_box_next_left_hang#1%
-  {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+  {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi
      {\d_strc_float_temp_height\ht\b_strc_floats_content
       \vbox to\d_strc_float_temp_height{#1}%
       \box\b_strc_floats_content}}
 
 \def\strc_floats_build_box_next_right_margin_indeed#1#2%
   {\ifconditional\c_strc_floats_par_float
-     \hbox\bgroup
-     \d_strc_float_temp_height\ht\b_strc_floats_content
-     \box\b_strc_floats_content
-     \hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}%
+     \hpack\bgroup
+       \d_strc_float_temp_height\ht\b_strc_floats_content
+       \box\b_strc_floats_content
+       \hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}%
      \egroup
    \else
      \begingroup
@@ -1613,10 +1549,10 @@
 
 \def\strc_floats_build_box_next_left_margin_indeed#1#2%
   {\ifconditional\c_strc_floats_par_float
-     \hbox\bgroup
-     \d_strc_float_temp_height\ht\b_strc_floats_content
-     \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}%
-     \box\b_strc_floats_content
+     \hpack\bgroup
+       \d_strc_float_temp_height\ht\b_strc_floats_content
+       \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}%
+       \box\b_strc_floats_content
      \egroup
    \else
      \begingroup
@@ -1720,14 +1656,14 @@
 \def\strc_floats_build_box_top_stack_normal_content
   {\d_strc_float_temp_width\wd\b_strc_floats_content
    \ifconditional\c_strc_floats_par_float
-     \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
+     \hpack{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
      \strc_floats_between_stack
-     \hbox{\hbox{\box\b_strc_floats_content}}%
+     \hpack{\hbox{\box\b_strc_floats_content}}%
    \else
      \page_otr_command_set_float_hsize
-     \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}
+     \hpack{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}
      \strc_floats_between_stack
-     \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}%
+     \hpack{\strc_floats_align_content{\box\b_strc_floats_content}}%
    \fi}
 
 \def\strc_floats_build_box_bottom_stack_normal_overlay
@@ -1736,14 +1672,14 @@
 \def\strc_floats_build_box_bottom_stack_normal_content
   {\d_strc_float_temp_width\wd\b_strc_floats_content
    \ifconditional\c_strc_floats_par_float
-     \hbox{\hbox{\box\b_strc_floats_content}}%
+     \hpack{\hpack{\box\b_strc_floats_content}}%
      \strc_floats_between_stack
-     \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
+     \hpack{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
    \else
      \page_otr_command_set_float_hsize
-     \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}%
+     \hpack{\strc_floats_align_content{\box\b_strc_floats_content}}%
      \strc_floats_between_stack
-     \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}%
+     \hpack{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}%
    \fi}
 
 \def\strc_floats_build_box_top_stack_normal
@@ -1763,7 +1699,7 @@
       \ifconditional\c_strc_floats_par_float
         \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
         \vss\strc_floats_between_stack
-        \hbox{\box\b_strc_floats_content}%
+        \hpack{\box\b_strc_floats_content}%
       \else
         \page_otr_command_set_float_hsize
         \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
@@ -1778,7 +1714,7 @@
    \setbox\scratchbox\vbox
      {\d_strc_float_temp_width\wd\b_strc_floats_content
       \ifconditional\c_strc_floats_par_float
-        \hbox{\box\b_strc_floats_content}%
+        \hpack{\box\b_strc_floats_content}%
         \vss\strc_floats_between_stack
         \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
       \else
@@ -1792,16 +1728,16 @@
 
 \def\strc_floats_build_box_top_stack_stretch
   {\dp\b_strc_floats_caption\strutdepth
-   \setbox\scratchbox\vbox
+   \setbox\scratchbox\vpack
      {\strc_floats_align_caption{\copy\b_strc_floats_caption}%
       \strc_floats_align_content{\copy\b_strc_floats_content}}%
    \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
-   \vbox to \noflines\lineheight
+   \vbox to \noflines\lineheight % pack ?
      {\d_strc_float_temp_width\wd\b_strc_floats_content
       \ifconditional\c_strc_floats_par_float
         \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
         \vss\strc_floats_between_stack\vss
-        \hbox{\box\b_strc_floats_content}%
+        \hpack{\box\b_strc_floats_content}%
       \else
         \page_otr_command_set_float_hsize
         \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
@@ -1811,14 +1747,14 @@
 
 \def\strc_floats_build_box_bottom_stack_stretch
   {\dp\b_strc_floats_caption\strutdepth
-   \setbox\scratchbox\vbox
+   \setbox\scratchbox\vbox % pack ?
      {\strc_floats_align_content{\copy\b_strc_floats_content  }%
       \strc_floats_align_caption{\copy\b_strc_floats_caption}}%
    \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
    \vbox to \noflines\lineheight
      {\d_strc_float_temp_width\wd\b_strc_floats_content
       \ifconditional\c_strc_floats_par_float
-        \hbox{\box\b_strc_floats_content}%
+        \hpack{\box\b_strc_floats_content}%
         \vss\strc_floats_between_stack\vss
         \strc_floats_locate_side_float{\box\b_strc_floats_caption}
       \else
@@ -1848,15 +1784,25 @@
 \unexpanded\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}}
 
 \def\strc_floats_build_box
-  {\global\setbox\floatbox\vbox
+  {\global\setbox\floatbox\vbox % pack ? probably not
      {\strc_floats_set_local_hsize
       \forgetall
       \let\floatcaptionarrangement\s!default
       \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step
-      \executeifdefined{\??floatbuilder\floatcaptionarrangement}{\getvalue{\??floatbuilder\s!default}}}}
+      \ifcsname\??floatbuilder\floatcaptionarrangement\endcsname
+        \lastnamedcs
+      \else
+        \strc_floats_build_box_default
+      \fi}}
+
+% \def\strc_floats_build_box_step#1%
+%   {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}}
 
 \def\strc_floats_build_box_step#1%
-  {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}}
+  {\ifcsname\??floatbuilder#1\endcsname
+     \def\floatcaptionarrangement{#1}% \let\floatcaptionarrangement\commalistelement
+     \quitcommalist
+   \fi}
 
 \def\strc_floats_locate_text_float
   {\let\next\strc_floats_align_caption
@@ -1930,7 +1876,7 @@
    \setbox\b_strc_floats_content\vbox{\borderedfloatbox}%
   %\page_backgrounds_add_local_to_box\b_strc_floats_content
    \ifnofloatcaption
-     \global\setbox\floatbox\vbox{\box\b_strc_floats_content}%
+     \global\setbox\floatbox\vpack{\box\b_strc_floats_content}%
    \else
      \strc_floats_check_caption_content
      \strc_floats_prepare_side_caption
@@ -1941,30 +1887,6 @@
    \fi
    \egroup}
 
-% \def\strc_floats_prepare_side_caption
-%   {\dostarttagged\t!floatcaption\empty
-%    \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
-%    \doifelse{\floatcaptionparameter\c!width}\v!max
-%      {\setbox\b_strc_floats_caption\vbox
-%         {\strc_floats_caption_set_align
-%          \hsize\wd\b_strc_floats_content
-%          \strc_floats_make_complete_caption}}%
-%      {\doifelse{\floatcaptionparameter\c!width}\v!fit
-%         {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax
-%            \setbox\b_strc_floats_caption\vbox
-%              {\forgetall % needed?
-%               \hsize\wd\b_strc_floats_content
-%               \strc_floats_make_complete_caption}%
-%          \else
-%            \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content
-%              {\hss\hbox{\strc_floats_make_complete_caption}\hss}%
-%          \fi}
-%         {\setbox\b_strc_floats_caption\vbox
-%            {\strc_floats_caption_set_align
-%             \hsize\floatcaptionparameter\c!width % \wd\b_strc_floats_content
-%             \strc_floats_make_complete_caption}}}%
-%    \dostoptagged}
-
 \def\strc_floats_prepare_side_caption
   {\dostarttagged\t!floatcaption\empty
    \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}%
@@ -1993,7 +1915,7 @@
         \hsize\wd\b_strc_floats_content
         \strc_floats_make_complete_caption}%
    \else
-     \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content
+     \setbox\b_strc_floats_caption\hpack to \wd\b_strc_floats_content
        {\hss\hbox{\strc_floats_make_complete_caption}\hss}%
    \fi}
 
@@ -2060,11 +1982,11 @@
      \fi
      \strc_floats_set_local_dimensions
      \global\advance\totalnoffloats\plusone
-     \setbox\floatbox\hbox{\strc_float_save_data\box\floatbox}% still needed? we will do renumbering differently
+     \setbox\floatbox\hpack{\strc_float_save_data\box\floatbox}% still needed? we will do renumbering differently
      \global\floatheight\htdp\floatbox
      \global\floatwidth\wd\floatbox
      \doifnotinset\v!margin\floatlocation % gaat namelijk nog fout
-       {\setbox\floatbox\vbox
+       {\setbox\floatbox\vpack
           {\parindent\zeropoint
            \box\floatbox}}%
      \wd\floatbox\floatwidth
@@ -2304,7 +2226,7 @@
       \else
         \directlocalfloatsparameter\c!inbetween
       \fi
-      \dontleavehmode\hbox{\foundbox\??localfloatstack\recurselevel}% \restorebox...
+      \dontleavehmode\hpack{\foundbox\??localfloatstack\recurselevel}% \restorebox...
       \ifnum\recurselevel=\c_strc_localfloats_n\relax
         \directlocalfloatsparameter\c!after
       \fi}}
diff --git a/tex/context/base/strc-ind.mkiv b/tex/context/base/strc-ind.mkiv
index 0098bff7d..2748fd684 100644
--- a/tex/context/base/strc-ind.mkiv
+++ b/tex/context/base/strc-ind.mkiv
@@ -104,6 +104,12 @@
    \par
    \endgroup}
 
+\unexpanded\def\startindentedtext
+  {\dosingleempty\strc_indentedtexts_start_direct}
+
+\def\strc_indentedtexts_start_direct[#1]%
+  {\strc_indentedtexts_start{#1}\c_strc_indentedtexts_nesting}
+
 \let\stopindentedtext\strc_indentedtexts_stop
 
 \unexpanded\def\strc_indentedtexts_direct#1#2#3\par % no longer clever grabpar trickery
diff --git a/tex/context/base/strc-ini.lua b/tex/context/base/strc-ini.lua
index f736427bb..7a6153096 100644
--- a/tex/context/base/strc-ini.lua
+++ b/tex/context/base/strc-ini.lua
@@ -370,7 +370,6 @@ function sets.get(namespace,block,name,level,default) -- check if name is passed
     if not dn then
         return default
     end
--- inspect(dn)
     local dl = dn[1][level]
     return dl or dn[2] or default
 end
diff --git a/tex/context/base/strc-itm.mkvi b/tex/context/base/strc-itm.mkvi
index 86fc9d9fd..f951920d2 100644
--- a/tex/context/base/strc-itm.mkvi
+++ b/tex/context/base/strc-itm.mkvi
@@ -337,12 +337,12 @@
     \setgvalue{\??itemgroupsetting\currentitemgroup}{\setupcurrentitemgroup[#settings]}}
 
 \def\strc_itemgroups_fetch_continue_state
-  {\getvalue{\??itemgroupoption \currentitemgroup}%
-   \getvalue{\??itemgroupsetting\currentitemgroup}}
+  {\csname\??itemgroupoption \currentitemgroup\endcsname
+   \csname\??itemgroupsetting\currentitemgroup\endcsname}
 
 \def\strc_itemgroups_reset_continue_state
-  {\letgvalue{\??itemgroupoption \currentitemgroup}\relax
-   \letgvalue{\??itemgroupsetting\currentitemgroup}\relax}
+  {\global\expandafter\let\csname\??itemgroupoption \currentitemgroup\endcsname\relax
+   \global\expandafter\let\csname\??itemgroupsetting\currentitemgroup\endcsname\relax}
 
 % These will become keywords. We will also add a feature to keep the while set
 % together.
@@ -388,7 +388,8 @@
         \let\itemgroupfirst\!!plusone
      \fi
      \ifcsname\??itemgroupkeyword\itemgroupsecond\endcsname
-       \csname\??itemgroupkeyword\itemgroupsecond\endcsname
+      %\csname\??itemgroupkeyword\itemgroupsecond\endcsname
+       \lastnamedcs
      \else
        \strc_itemgroups_set_symbol\itemgroupconstantvalue
      \fi
@@ -482,7 +483,8 @@
 
 \def\strc_itemgroups_preset_stage_one_indeed#option%
   {\ifcsname\??itemgroupfirst#option\endcsname
-     \csname\??itemgroupfirst#option\endcsname
+    %\csname\??itemgroupfirst#option\endcsname
+     \lastnamedcs
    \fi}
 
 \ifdefined\dotagsetitemgroup \else \let\dotagsetitemgroup\relax             \fi
@@ -861,10 +863,10 @@
   {\letgvalue{\??itemgrouplocal\currentitemlevel}#symbol}
 
 \def\strc_itemgroups_fetch_global_symbol
-  {\getvalue{\??itemgroupglobal\currentitemlevel}}
+  {\csname\??itemgroupglobal\currentitemlevel\endcsname}
 
 \def\strc_itemgroups_fetch_local_symbol
-  {\getvalue{\??itemgrouplocal\currentitemlevel}}
+  {\csname\??itemgrouplocal\currentitemlevel\endcsname}
 
 \def\strc_itemgroups_setup_symbol_default
   {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}%
@@ -1183,8 +1185,15 @@
      {\dorecurse{0\itemgroupparameter\c!items}{\strc_itemgroups_used_symbol\hss}%
       \unskip}}
 
+% \unexpanded\def\startspecialitemgroupitem[#name]%
+%   {\csname\??itemgroupstart\ifcsname\??itemgroupstart#name\endcsname#name\else\v!item\fi\endcsname}
+
 \unexpanded\def\startspecialitemgroupitem[#name]%
-  {\csname\??itemgroupstart\ifcsname\??itemgroupstart#name\endcsname#name\else\v!item\fi\endcsname}
+  {\ifcsname\??itemgroupstart#name\endcsname
+      \expandafter\lastnamedcs
+    \else
+      \expandafter\strc_itemgroups_start_do_item
+    \fi}
 
 \unexpanded\def\stopspecialitemgroupitem
   {\stopitemgroupitem}
@@ -1422,7 +1431,8 @@
    \ifx\m_strc_itemgroups_text_distance\empty
      %
    \else\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
-     \csname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
+    %\csname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
+     \lastnamedcs
    \else
      \strc_itemgroups_set_text_item_distance_indeed
    \fi\fi}
@@ -1435,9 +1445,12 @@
      {\interwordspace  \!!plus  \emwidth}%
      {\emwidth         \!!plus  \interwordstretch\!!minus\interwordshrink}}
 
+% \unexpanded\def\strc_itemgroups_default_command
+%   {\EveryPar{\ignorespaces}% needed ?
+%    \ignorespaces}
+
 \unexpanded\def\strc_itemgroups_default_command
-  {\EveryPar{\ignorespaces}% needed ?
-   \ignorespaces}
+  {\ignorespaces}
 
 %D Special case:
 
@@ -1533,7 +1546,8 @@
      \advance\c_strc_itemgroups_collected_current\plusone
    \fi
    \ifcsname\??itemgroupstack\number\c_strc_itemgroups_collected_current\endcsname
-     \getvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
+    %\csname\??itemgroupstack\number\c_strc_itemgroups_collected_current\endcsname
+     \lastnamedcs
      \letbeundefined{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
      \advance\c_strc_itemgroups_collected_done\plusone
    \fi
diff --git a/tex/context/base/strc-lnt.mkvi b/tex/context/base/strc-lnt.mkvi
index ee7d5dd88..e7f84ea19 100644
--- a/tex/context/base/strc-lnt.mkvi
+++ b/tex/context/base/strc-lnt.mkvi
@@ -148,7 +148,7 @@
    \let\currentnote\currentnotation
    \letnotationparameter\c!numbercommand\linenotelinenumber% todo: deep hook
    \letnoteparameter    \c!textcommand  \gobbleoneargument % todo: deep hook
-   \getvalue{\??linenote\currentnotation}{#3}%
+   \csname\??linenote\currentnotation\endcsname{#3}%
    \expandafter\glet\csname\??linenotespreviousfrom\currentnotation\endcsname\m_page_lines_current_from
    \expandafter\glet\csname\??linenotespreviousto  \currentnotation\endcsname\m_page_lines_current_to
    \endgroup}
@@ -256,15 +256,15 @@
 \unexpanded\def\tracelinenotes
   {\let\strc_linenotes_traced\strc_linenotes_traced_indeed}
 
+% We predefine one, namely \type {\linenote} cum suis.
+
+\definelinenote[\v!linenote]
+
 %D Use these when not properly nested:
 
 \let\fromlinenote\startlinenote
 \let\tolinenote  \stoplinenote
 
-% We predefine one, namely \type {\linenote} cum suis.
-
-\definelinenote[\v!linenote]
-
 % beware: line numbers are added later on so grouping setups is a bad idea
 %
 % \startbuffer[test]
diff --git a/tex/context/base/strc-lst.mkvi b/tex/context/base/strc-lst.mkvi
index c7fd41daf..90b121399 100644
--- a/tex/context/base/strc-lst.mkvi
+++ b/tex/context/base/strc-lst.mkvi
@@ -277,8 +277,8 @@
 %D a document source but nowadays that is less an issue in the
 %D sense that the extra few lines are neglectable to the rest.
 
-\unexpanded\def\systemsuppliedchapter {\getvalue{\v!chapter}} % obsolete
-\unexpanded\def\systemsuppliedtitle   {\getvalue{\v!title}}   % obsolete
+\unexpanded\def\systemsuppliedchapter {\csname\v!chapter\endcsname} % obsolete
+\unexpanded\def\systemsuppliedtitle   {\csname\v!title  \endcsname} % obsolete
 
 \unexpanded\def\completelist
   {\dodoubleempty\strc_lists_complete}
@@ -477,16 +477,30 @@
 
 \let\dotaglistlocation\relax
 
+\def\strc_lists_entry_process_default
+  {no list method}
+
+% \def\strc_lists_entry_process % assume things to be set up
+%   {\listextraparameter\c!before
+%    \dostarttagged\t!listitem\currentlist
+%    \dotaglistlocation
+%    \csname\??structurelistprocessor
+%      \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\currentlist:\currentlistmethod\else
+%      \ifcsname\??structurelistprocessor\currentlistmethod             \endcsname\currentlistmethod             \else
+%      \ifcsname\??structurelistprocessor\currentlist                   \endcsname\currentlist                   \else
+%                                                                                 \s!default                     \fi\fi\fi
+%    \endcsname
+%    \dostoptagged
+%    \listextraparameter\c!after}
+
 \def\strc_lists_entry_process % assume things to be set up
   {\listextraparameter\c!before
    \dostarttagged\t!listitem\currentlist
    \dotaglistlocation
-   \csname\??structurelistprocessor
-     \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\currentlist:\currentlistmethod\else
-     \ifcsname\??structurelistprocessor\currentlistmethod             \endcsname\currentlistmethod             \else
-     \ifcsname\??structurelistprocessor\currentlist                   \endcsname\currentlist                   \else
-                                                                                \s!default                     \fi\fi\fi
-   \endcsname
+   \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\lastnamedcs\else
+   \ifcsname\??structurelistprocessor\currentlistmethod             \endcsname\lastnamedcs\else
+   \ifcsname\??structurelistprocessor\currentlist                   \endcsname\lastnamedcs\else
+                                                         \strc_lists_entry_process_default\fi\fi\fi
    \dostoptagged
    \listextraparameter\c!after}
 
@@ -502,7 +516,7 @@
 % lists that have a number/title are kind of generic and can share code
 
 \installstructurelistprocessor\s!default
-  {no list method}
+  {\strc_lists_entry_process_default}
 
 \installstructurelistprocessor\s!simple
   {\let\currentlistentrynumber    \structurelistfirst
@@ -567,7 +581,7 @@
 
 \unexpanded\def\strc_lists_symbol_none
   {\strc_lists_assign_dimen\scratchwidth\c!width{1.5\emwidth}%
-   \hbox to \scratchwidth{}}
+   \hpack to \scratchwidth{}}
 
 \unexpanded\def\strc_lists_symbol_one
   {\strut\symbol[bullet]}
@@ -588,22 +602,29 @@
 
 \installcorenamespace{listsymbollabels}
 
+\def\strc_lists_symbol_label_unknown
+  {\leftlabeltext\currentlistlabel
+   \listparameter\c!starter
+   \currentlistentrynumber
+   \listparameter\c!stopper
+   \rightlabeltext\currentlistlabel}
+
 \unexpanded\def\strc_lists_symbol_default
   {\dontleavehmode
    \strut
    \begingroup
    \edef\currentlistlabel{\listparameter\c!label}% can be used in label
-   \csname\??listsymbollabels
-     \ifcsname\??listsymbollabels\currentlistlabel\endcsname\currentlistlabel\else\s!unknown\fi
-   \endcsname
+%    \csname\??listsymbollabels
+%      \ifcsname\??listsymbollabels\currentlistlabel\endcsname\currentlistlabel\else\s!unknown\fi
+%    \endcsname
+   \ifcsname\??listsymbollabels\currentlistlabel\endcsname
+      \lastnamedcs
+   \else
+     \strc_lists_symbol_label_unknown
+   \fi
    \endgroup}
 
-\setvalue{\??listsymbollabels\s!unknown}% use whatever is set
-  {\leftlabeltext\currentlistlabel
-   \listparameter\c!starter
-   \currentlistentrynumber
-   \listparameter\c!stopper
-   \rightlabeltext\currentlistlabel}
+\letvalue{\??listsymbollabels\s!unknown}\strc_lists_symbol_default
 
 \setvalue{\??listsymbollabels}% default (empty)
   {\listparameter\c!starter
@@ -920,7 +941,7 @@
         \listalternativeparameter\c!after
    \else
         \noindent % otherwise annotations are mirrored up
-\typo_injectors_mark_list
+        \typo_injectors_mark_list
         \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
             \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber
         }
@@ -1348,10 +1369,44 @@
      \strc_lists_interaction_check_nop
    \fi}
 
+% \def\strc_lists_interaction_check_yes
+%   {\edef\p_interaction_forward{\listparameter\c!interaction}%
+%    \ifcsname\??listinteractions\p_interaction_forward\endcsname
+%      \expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
+%      \strc_references_get_simple_page_reference{internal(\currentlistentrylocation)}%
+%      \a_strc_lists_reference\currentreferenceattribute
+%    \else
+%      \a_strc_lists_reference\attributeunsetvalue
+%    \fi
+%    \ifnum\a_strc_lists_reference=\attributeunsetvalue
+%       \let\strc_lists_get_reference_attribute\gobbleoneargument
+%       \let\strc_lists_set_reference_attribute\gobbleoneargument
+%       \let\strc_lists_set_style_color        \strc_lists_set_style_color_normal
+%    \else
+%       \let\strc_lists_get_reference_attribute\strc_lists_get_reference_attribute_indeed
+%       \let\strc_lists_set_reference_attribute\strc_lists_set_reference_attribute_indeed
+%       \let\strc_lists_set_style_color        \strc_lists_set_style_color_special
+%    \fi
+%    \edef\p_interaction_backward{\namedheadparameter\currentlist\c!interaction}% \namedheadparameter !
+%    \ifx\p_interaction_backward\v!list
+%      \strc_references_set_simple_page_reference{bck:\currentlistentrylocation}%
+%      \a_strc_lists_destination\currentdestinationattribute
+%    \else
+%      \a_strc_lists_destination\attributeunsetvalue
+%    \fi
+%    \ifnum\a_strc_lists_destination=\attributeunsetvalue
+%       \let\strc_lists_get_destination_attribute\empty
+%       \let\strc_lists_set_destination_attribute\empty
+%    \else
+%       \let\strc_lists_get_destination_attribute\strc_lists_get_destination_attribute_indeed
+%       \let\strc_lists_set_destination_attribute\strc_lists_set_destination_attribute_indeed
+%    \fi}
+
 \def\strc_lists_interaction_check_yes
   {\edef\p_interaction_forward{\listparameter\c!interaction}%
    \ifcsname\??listinteractions\p_interaction_forward\endcsname
-     \expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
+    %\expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
+     \expandafter\let\expandafter\p_interaction_forward\lastnamedcs
      \strc_references_get_simple_page_reference{internal(\currentlistentrylocation)}%
      \a_strc_lists_reference\currentreferenceattribute
    \else
diff --git a/tex/context/base/strc-mar.lua b/tex/context/base/strc-mar.lua
index b7e6ef8c2..8b30e8514 100644
--- a/tex/context/base/strc-mar.lua
+++ b/tex/context/base/strc-mar.lua
@@ -31,7 +31,7 @@ local getlist            = nuts.getlist
 local getattr            = nuts.getattr
 local getbox             = nuts.getbox
 
-local traversenodes      = nuts.traverse
+local traverse_nodes     = nuts.traverse
 
 local nodecodes          = nodes.nodecodes
 local glyph_code         = nodecodes.glyph
@@ -117,7 +117,7 @@ end
 -- identify range
 
 local function sweep(head,first,last)
-    for n in traversenodes(head) do
+    for n in traverse_nodes(head) do
         local id = getid(n)
         if id == glyph_code then
             local a = getattr(n,a_marks)
diff --git a/tex/context/base/strc-mat.mkiv b/tex/context/base/strc-mat.mkiv
index 4435692e1..6bf9b149b 100644
--- a/tex/context/base/strc-mat.mkiv
+++ b/tex/context/base/strc-mat.mkiv
@@ -247,7 +247,7 @@
    \glet\strc_formulas_place_number_nested\strc_formulas_place_number_nested_indeed}
 
 \def\strc_formulas_handle_number % formulas
-  {\strc_formulas_check_reference\c_strc_formulas_number_mode\currentformulareference}
+  {\strc_formulas_check_reference\c_strc_formulas_number_mode\currentformulasreference}
 
 \def\strc_formulas_handle_sub_number_indeed % sub formulas
   {\strc_formulas_check_reference\c_strc_formulas_sub_number_mode\currentsubformulasreference
@@ -629,7 +629,7 @@
    \let\strc_formulas_start_formula\strc_formulas_start_formula_nested
   %\freezedimenmacro\predisplaysizethreshhold
    \strc_formulas_forget_display_skips
-   \getvalue{\e!start\formulaparameter\c!alternative\v!formula}}
+   \csname\e!start\formulaparameter\c!alternative\v!formula\endcsname}
 
 \unexpanded\def\strc_formulas_start_formula_nested#1%
   {\bgroup
@@ -647,7 +647,7 @@
    \strc_formulas_place_number
    \dostoptagged
    \dostarttagged\t!formulacontent\empty
-   \getvalue{\e!stop\formulaparameter\c!alternative\v!formula}%
+   \csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname
    \dostoptagged
    \dostoptagged
    \nonoindentation
@@ -890,7 +890,7 @@
 
 \def\strc_formulas_number_again[#1]%
   {\def\currentformulareference{#1}%
-   \dosinglegroupempty\strc_formulas_number_indeed}
+   \strc_formulas_number_indeed}
 
 \unexpanded\def\placeformula
   {\global\settrue\c_strc_formulas_inside_place
@@ -905,7 +905,7 @@
 \def\strc_formulas_place[#1]%
   {\def\currentplaceformulareference{#1}%
    \let\currentplaceformulasuffix\empty
-   \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop\strc_formulas_place_nop} % [ref]{}
+   \doifelsenextbgroup\strc_formulas_place_yes\strc_formulas_place_nop} % [ref]{}
 
 \def\strc_formulas_place_yes#1%
   {\def\currentplaceformulasuffix{#1}%
diff --git a/tex/context/base/strc-not.mkvi b/tex/context/base/strc-not.mkvi
index 761dec0f5..06d6d502e 100644
--- a/tex/context/base/strc-not.mkvi
+++ b/tex/context/base/strc-not.mkvi
@@ -969,7 +969,8 @@
   {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}}
 
 \unexpanded\def\strc_notes_set_location_step#alternative% the insert related one
-  {\ifcsname\??notelocation#alternative\endcsname\csname\??notelocation#alternative\endcsname\fi}
+ %{\ifcsname\??notelocation#alternative\endcsname\csname\??notelocation#alternative\endcsname\fi}
+  {\begincsname\??notelocation#alternative\endcsname}
 
 \appendtoks
     \strc_notes_set_variants
@@ -1172,8 +1173,8 @@
 \newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used
 \newconditional\c_strc_notes_skip
 
-\unexpanded\def\setnote    [#tag]{\getvalue{#tag}}
-\unexpanded\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\getvalue{#tag}}
+\unexpanded\def\setnote    [#tag]{\csname#tag\endcsname}
+\unexpanded\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\csname#tag\endcsname}
 
 \unexpanded\def\handlenoteinsert#tag#id%
   {\begingroup
@@ -1570,8 +1571,6 @@
         \noteparameter\c!after
       \fi}}
 
-\setvalue{\??notealternative}{\getvalue{\??notealternative\v!none}}
-
 %D A stupid alternative is also provided:
 %D
 %D \starttyping
@@ -1585,6 +1584,9 @@
 \installnotealternative \v!none
   {\flushlocalnotes\currentnote}
 
+\installnotealternative \empty
+  {\flushlocalnotes\currentnote}
+
 \installnotealternative \v!grid % test if n > 0
   {\begingroup
    \setupcurrentnote[\c!location=]%
@@ -1772,7 +1774,7 @@
 %D }
 %D \stoptyping
 
-\def\doifelsenoteonsamepage[#tag]{\clf_doifnoteonsamepageasprevious{#tag}}
+\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}}
 
 \let\doifnoteonsamepageelse\doifelsenoteonsamepage
 
diff --git a/tex/context/base/strc-num.mkiv b/tex/context/base/strc-num.mkiv
index bad4be514..e9eaca11b 100644
--- a/tex/context/base/strc-num.mkiv
+++ b/tex/context/base/strc-num.mkiv
@@ -118,8 +118,8 @@
 \unexpanded\def\prevcounter       {\dodoubleargument\strc_counters_prev_interfaced}
 \unexpanded\def\countersubs       {\dodoubleargument\strc_counters_subs_interfaced}
 
-\unexpanded\def\savecounter       {\dodoubleempty   \strc_counters_save_interfaced}
-\unexpanded\def\restorecounter    {\dodoubleempty   \strc_counters_restore_interfaced}
+\unexpanded\def\savecounter       {\dosingleempty   \strc_counters_save_interfaced}
+\unexpanded\def\restorecounter    {\dosingleempty   \strc_counters_restore_interfaced}
 
 \def\strc_counters_set_interfaced
   {\ifthirdargument
@@ -322,11 +322,11 @@
 \def\nextcountervalue    [#1]{\clf_nextcountervalue    {\namedcounterparameter{#1}\s!name}}
 \def\prevcountervalue    [#1]{\clf_previouscountervalue{\namedcounterparameter{#1}\s!name}}
 
-\let\rawsubcountervalue       \strc_counters_raw_two
-\let\lastsubcountervalue      \strc_counters_last_two
-\let\firstsubcountervalue     \strc_counters_first_two
-\let\nextsubcountervalue      \strc_counters_next_two
-\let\prevsubcountervalue      \strc_counters_prev_two
+\def\rawsubcountervalue  [#1]#2[#3]{\clf_subcountervalue        {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\lastsubcountervalue [#1]#2[#3]{\clf_lastsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\firstsubcountervalue[#1]#2[#3]{\clf_firstsubcountervalue   {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\nextsubcountervalue [#1]#2[#3]{\clf_nextsubcountervalue    {\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
+\def\prevsubcountervalue [#1]#2[#3]{\clf_previoussubcountervalue{\namedcounterparameter{#1}\s!name}\numexpr#3\relax}
 
 % The bypage check needs a multipass reference and therefore we only check for it when we increment
 % and know that some content will be placed. We could also check for spreads.
diff --git a/tex/context/base/strc-ref.mkvi b/tex/context/base/strc-ref.mkvi
index f5d0d1d78..1f2c91404 100644
--- a/tex/context/base/strc-ref.mkvi
+++ b/tex/context/base/strc-ref.mkvi
@@ -438,7 +438,7 @@
   {\ifsecondargument
      \expandafter\strc_references_content_pickup_yes
    \else
-     \expandafter\strc_references_content_pickup_yes
+     \expandafter\strc_references_content_pickup_nop
    \fi}
 
 \def\strc_references_content_pickup_yes[#1][#2]%
@@ -1187,7 +1187,7 @@
 
 \installcorenamespace{referencinginteraction}
 
-\setvalue{\??referencinginteraction\v!all}%
+\def\strc_references_interaction_all
   {\the\leftreferencetoks
    \doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing
    \leftofreference
@@ -1196,6 +1196,8 @@
    \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing
    \the\rightreferencetoks}
 
+\letvalue{\??referencinginteraction\v!all}\strc_references_interaction_all
+
 \setvalue{\??referencinginteraction\v!label}%
   {\leftofreference
    \the\leftreferencetoks
@@ -1210,14 +1212,21 @@
 \setvalue{\??referencinginteraction\v!symbol}%
   {\referencesymbol}
 
+% \def\referencesequence
+%   {\csname\??referencinginteraction
+%      \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
+%        \referencingparameter\c!interaction
+%      \else
+%        \v!all
+%      \fi
+%    \endcsname}
+
 \def\referencesequence
-  {\csname\??referencinginteraction
-     \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
-       \referencingparameter\c!interaction
-     \else
-       \v!all
-     \fi
-   \endcsname}
+  {\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
+     \expandafter\lastnamedcs
+   \else
+     \expandafter\strc_references_interaction_all
+   \fi}
 
 \newtoks\everyresetinatreference
 
@@ -2121,11 +2130,14 @@
 
 \def\referencestructureprefixparameter#kind#name#category#parameter%
   {\ifcsname\??referencingprefix#name:#category#parameter\endcsname
-     \csname\??referencingprefix#name:#category#parameter\endcsname
+    %\csname\??referencingprefix#name:#category#parameter\endcsname
+     \lastnamedcs
    \else\ifcsname\??referencingprefix#kind:#category#parameter\endcsname
-     \csname     \??referencingprefix#kind:#category#parameter\endcsname
+    %\csname     \??referencingprefix#kind:#category#parameter\endcsname
+     \lastnamedcs
    \else\ifcsname\??referencingprefix:#category#parameter\endcsname
-     \csname     \??referencingprefix:#category#parameter\endcsname
+    %\csname     \??referencingprefix:#category#parameter\endcsname
+     \lastnamedcs
    \fi\fi\fi}
 
 \def\currentreferencedefault % for some reason we need to explicitly expand
diff --git a/tex/context/base/strc-ren.mkiv b/tex/context/base/strc-ren.mkiv
index 26b7c75a5..f692d08fd 100644
--- a/tex/context/base/strc-ren.mkiv
+++ b/tex/context/base/strc-ren.mkiv
@@ -486,7 +486,8 @@
      \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor
      \headparameter\c!commandbefore\relax
      \ifcsname\currentheadhash\c!deeptextcommand\endcsname
-       \expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname
+      %\expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname
+       \expandafter\let\expandafter\deepstructuretitlecommand\lastnamedcs
      \fi
      \ifconditional\headisdisplay
        % struts can be nilled with \setnostrut
@@ -506,7 +507,8 @@
   {\begingroup
      \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor
      \ifcsname\currentheadhash\c!deepnumbercommand\endcsname
-       \expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname
+      %\expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname
+       \expandafter\let\expandafter\deepstructurenumbercommand\lastnamedcs
      \fi
      \ifconditional\headisdisplay
        % can be nilled with \setnostrut
diff --git a/tex/context/base/strc-sec.mkiv b/tex/context/base/strc-sec.mkiv
index 64d034ba2..8fae2d133 100644
--- a/tex/context/base/strc-sec.mkiv
+++ b/tex/context/base/strc-sec.mkiv
@@ -671,7 +671,8 @@
 \unexpanded\def\strc_sectioning_initialize_increment
   {\edef\currentheadincrement{\headparameter\c!incrementnumber}%
    \ifcsname\??headincrement\currentheadincrement\endcsname
-     \csname\??headincrement\currentheadincrement\endcsname
+    %\csname\??headincrement\currentheadincrement\endcsname
+     \lastnamedcs
    \else
      \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list
      % \filterheadnumber
diff --git a/tex/context/base/strc-syn.mkiv b/tex/context/base/strc-syn.mkiv
index b206f8069..eb824c439 100644
--- a/tex/context/base/strc-syn.mkiv
+++ b/tex/context/base/strc-syn.mkiv
@@ -281,9 +281,11 @@
    \ifx\currentsynonymtag\empty
      % todo: error message
    \else
+     % this is not that efficient, esp when we load a big list
      \edef\currentsynonymexpansion{\simplelistparameter\c!expansion}%
      \preprocessexpansion\currentsynonymexpansion\m_synonyms_text   \currentsynonymcoding{#4}%
      \preprocessexpansion\currentsynonymexpansion\m_synonyms_meaning\currentsynonymcoding{#5}%
+     %
      \clf_registersynonym
         {\currentsynonym}%
         {synonym}%
diff --git a/tex/context/base/supp-box.mkiv b/tex/context/base/supp-box.mkiv
index 28dc81bff..e32303956 100644
--- a/tex/context/base/supp-box.mkiv
+++ b/tex/context/base/supp-box.mkiv
@@ -281,7 +281,8 @@
 
 \def\syst_boxes_smash_process_option#1%
   {\ifx#1\relax\else
-     \ifcsname\??smashoptions#1\endcsname\csname\??smashoptions#1\endcsname\fi
+    %\csname\??smashoptions#1\endcsname\csname\??smashoptions#1\endcsname\fi
+     \begincsname\??smashoptions#1\endcsname
      \expandafter\syst_boxes_smash_process_option
    \fi}
 
@@ -726,9 +727,9 @@
 %D Some well known friends, but we implement them our own
 %D way. We want the macros to work in both math and text mode.
 
-\def\dodorlap{\hbox to \zeropoint{\box\nextbox\normalhss}\endgroup}
-\def\dodollap{\hbox to \zeropoint{\normalhss\box\nextbox}\endgroup}
-\def\dodoclap{\hbox to \zeropoint{\normalhss\box\nextbox\normalhss}\endgroup}
+\def\dodorlap{\hpack to \zeropoint{\box\nextbox\normalhss}\endgroup}
+\def\dodollap{\hpack to \zeropoint{\normalhss\box\nextbox}\endgroup}
+\def\dodoclap{\hpack to \zeropoint{\normalhss\box\nextbox\normalhss}\endgroup}
 
 \def\dorlap{\begingroup\dowithnextboxcs\dodorlap\hbox}
 \def\dollap{\begingroup\dowithnextboxcs\dodollap\hbox}
@@ -742,8 +743,8 @@
 \unexpanded\def\llap{\mathortext\domathllap\dollap}
 \unexpanded\def\clap{\mathortext\domathclap\doclap}
 
-\def\dodotlap{\vbox to \zeropoint{\normalvss\box\nextbox}\endgroup}
-\def\dodoblap{\vbox to \zeropoint{\box\nextbox\normalvss}\endgroup}
+\def\dodotlap{\vpack to \zeropoint{\normalvss\box\nextbox}\endgroup}
+\def\dodoblap{\vpack to \zeropoint{\box\nextbox\normalvss}\endgroup}
 
 \unexpanded\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox}
 \unexpanded\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox}
@@ -915,7 +916,7 @@
 % We will turn this into a \MKIV\ variant.
 
 \unexpanded\def\insertshapesignal
-  {\hbox to \shapesignal{\strut\hss}% plus \strut
+  {\hpack to \shapesignal{\strut\hss}% plus \strut
    \prevdepth\strutdp} % never \nointerlineskip
 
 \unexpanded\def\restoreshapebox % compensates for the signal
@@ -1263,7 +1264,7 @@
           \fi
           \unvbox\nextbox
           \setbox\nextbox\lastbox
-          \global\setbox1\hbox
+          \global\setbox1\hpack
             {\ifdone
                \unhbox\nextbox\unskip\kern\zeropoint\box\scratchbox
              \else
@@ -1341,7 +1342,7 @@
           {\ifx\clip\undefined
              \box\plusone
            \else\ifdim\wd\plusone>\hsize
-             \lower\strutdepth\hbox{\clip[\c!width=\hsize,\c!height=\lineheight]{\hbox{\raise\strutdepth\box\plusone}}}%
+             \lower\strutdepth\hpack{\clip[\c!width=\hsize,\c!height=\lineheight]{\hpack{\raise\strutdepth\box\plusone}}}%
            \else
              \box\plusone
            \fi\fi
@@ -1375,7 +1376,7 @@
    \clf_applytobox
      method  {char}%
      box     \scratchbox
-     command {\checkedstrippedcsname#2}%
+     command {\csstring#2}%
      nested  true%
    \relax
    \endgroup}
@@ -1388,7 +1389,7 @@
    \clf_applytobox
      method  {word}%
      box     \scratchbox
-     command {\checkedstrippedcsname#2}%
+     command {\csstring#2}%
      nested  true%
    \relax
    \endgroup}
@@ -1400,7 +1401,7 @@
    \dowithnextbox{\clf_applytobox
      method  {char}%
      box     \nextbox
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      nested  true%
    \relax}%
    \hbox}
@@ -1410,7 +1411,7 @@
    \dowithnextbox{\clf_applytobox
      method  {word}%
      box     \nextbox
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      nested  true%
    \relax}%
    \hbox}
@@ -1425,28 +1426,28 @@
 \unexpanded\def\applytosplitstringchar#1#2%
   {\dontleavehmode\clf_processsplit
      data    {#2}%
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      method  {char}%
    \relax}
 
 \unexpanded\def\applytosplitstringword#1#2%
   {\dontleavehmode\clf_processsplit
      data    {#2}%
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      method  {word}%
    \relax}
 
 \unexpanded\def\applytosplitstringline#1#2%
   {\dontleavehmode\clf_processsplit
      data    {#2}%
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      method  {line}%
    \relax}
 
 \unexpanded\def\applytosplitstringcharspaced#1#2%
   {\dontleavehmode\clf_processsplit
      data    {#2}%
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      method  {char}%
      spaced  true%
    \relax}
@@ -1454,7 +1455,7 @@
 \unexpanded\def\applytosplitstringwordspaced#1#2%
   {\dontleavehmode\clf_processsplit
      data    {#2}%
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      method  {word}%
      spaced  true%
    \relax}
@@ -1462,7 +1463,7 @@
 \unexpanded\def\applytosplitstringlinespaced#1#2%
   {\dontleavehmode\clf_processsplit
      data    {#2}%
-     command {\checkedstrippedcsname#1}%
+     command {\csstring#1}%
      method  {line}%
      spaced  true%
    \relax}
@@ -1499,7 +1500,7 @@
    \dowithnextboxcs\syst_boxes_sbox_finish\vbox}
 
 \unexpanded\def\syst_boxes_sbox_finish
-  {\setbox\nextbox\hbox
+  {\setbox\nextbox\hpack
      {\strut
       \dp\nextbox\zeropoint
       \lower\strutdp\box\nextbox}%
@@ -1513,7 +1514,7 @@
 \unexpanded\def\inlinedbox
   {\bgroup
    \dowithnextbox
-     {\setbox\nextbox\hbox
+     {\setbox\nextbox\hpack
         {\lower
            \dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax
            \box\nextbox}%
@@ -1551,7 +1552,7 @@
 
 \def\syst_boxes_topskippedbox_finish
   {\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}%
-   \lower\topskip\hbox{\raise\strutheight\box\nextbox}%
+   \lower\topskip\hpack{\raise\strutheight\box\nextbox}%
    \m_boxes_tmp
    \egroup}
 
@@ -1603,7 +1604,7 @@
 
 \unexpanded\def\centeredbox#1#%   height +/-dimen width +/-dimen
   {\bgroup
-   \setbox0\vbox to \vsize
+   \setbox0\vpack to \vsize
      \bgroup
        \dontcomplain
        \forgetall
@@ -1611,11 +1612,11 @@
        \setbox2\vbox{\hrule\s!height\zeropoint#1}%
        \advance\vsize \ht2
        \advance\hsize \wd0
-       \vbox to \vsize
+       \vpack to \vsize
          \bgroup
            \vskip-\ht2
            \vss
-           \hbox to \hsize
+           \hpack to \hsize
              \bgroup
                \dowithnextbox
                  {\hskip-\wd0
@@ -1671,7 +1672,7 @@
       \ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi
       \setbox\scratchbox\vbox{\hrule\s!height\zeropoint#1}%
       \ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi
-      \vbox to \vsize{\vss\hbox to \hsize{\hss\box\nextbox\hss}\vss}%
+      \vpack to \vsize{\vss\hpack to \hsize{\hss\box\nextbox\hss}\vss}%
       \egroup}%
      \hbox}
 
@@ -1757,7 +1758,7 @@
         \setbox0=\box\rigidcolumnbox
         \doloop
           {\setbox\rigidcolumnbox=\copy0
-           \setbox\scratchbox\hbox to \savedrigidhsize
+           \setbox\scratchbox\hpack to \savedrigidhsize
              {\dorecurse\rigidcolumns
                 {\setbox\scratchbox\vsplit\rigidcolumnbox to \scratchdimen
                    \dp\scratchbox\openstrutdepth
@@ -1772,10 +1773,10 @@
               \hfillneg}%
           \ifvoid\rigidcolumnbox\exitloop\else\advance\scratchdimen\lineheight\fi}%
        \iftightrigidcolumns
-         \setbox\scratchbox\hbox{\raise\dp\scratchbox\box\scratchbox}%
+         \setbox\scratchbox\hpack{\raise\dp\scratchbox\box\scratchbox}%
        \else
          \advance\scratchdimen -\openstrutdepth
-         \setbox\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}%
+         \setbox\scratchbox\hpack{\raise\scratchdimen\box\scratchbox}%
          \dp\scratchbox\openstrutdepth
          \ht\scratchbox\scratchdimen
        \fi
@@ -1949,7 +1950,7 @@
       \ht\hhbox\strutht
       \dp\hhbox\strutdp
       \ifzeropt\hhboxindent\else % \ifdim\hhboxindent=\zeropoint\else
-        \setbox\hhbox\hbox{\kern-\hhboxindent\box\hhbox}%
+        \setbox\hhbox\hpack{\kern-\hhboxindent\box\hhbox}%
         \hhboxindent\zeropoint
       \fi
       \global\lasthhboxwidth\wd\hhbox
@@ -1962,7 +1963,7 @@
    \egroup}
 
 \def\dohboxofvbox
-  {\setbox0\vbox{\unvbox\scratchcounter\global\setbox1\lastbox}%
+  {\setbox0\vpack{\unvbox\scratchcounter\global\setbox1\lastbox}%
    \unhbox1
    \egroup}
 
@@ -2130,17 +2131,17 @@
   {%\removeunwantedspaces % already done
    \scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi
    \ifdim\ht\nextbox>\ht\processbox
-     \setbox\processbox\vbox to \ht\nextbox   {\dp\processbox\zeropoint\vss\box\processbox\vss}%
+     \setbox\processbox\vpack to \ht\nextbox   {\dp\processbox\zeropoint\vss\box\processbox\vss}%
    \else
-     \setbox\nextbox   \vbox to \ht\processbox{\dp\nextbox   \zeropoint\vss\box\nextbox   \vss}%
+     \setbox\nextbox   \vpack to \ht\processbox{\dp\nextbox   \zeropoint\vss\box\nextbox   \vss}%
    \fi
    \dp\nextbox   \scratchdepth
    \dp\processbox\scratchdepth
    \scratchwidth\wd\ifdim\wd\nextbox>\wd\processbox\nextbox\else\processbox\fi
-   \setbox\processbox\hbox to \scratchwidth
-     {\hbox to \scratchwidth{\hss\box\processbox\hss}%
+   \setbox\processbox\hpack to \scratchwidth
+     {\hpack to \scratchwidth{\hss\box\processbox\hss}%
       \kern-\scratchwidth
-      \hbox to \scratchwidth{\hss\box\nextbox   \hss}}}
+      \hpack to \scratchwidth{\hss\box\nextbox   \hss}}}
 
 \unexpanded\def\startoverlay
   {\bgroup
@@ -2226,7 +2227,7 @@
   {\scratchdepth\dimexpr\ht\nextbox+\dp\nextbox-\ht\strutbox\relax
    \ht\nextbox\ht\strutbox
    \dp\nextbox\scratchdepth
-   \setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}%
+   \setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}%
    \ht\nextbox\ht\strutbox
    \dp\nextbox\scratchdepth
    \box\nextbox
@@ -2236,7 +2237,7 @@
   {\scratchheight\dimexpr\ht\nextbox+\dp\nextbox-\dp\strutbox\relax
    \dp\nextbox\dp\strutbox
    \ht\nextbox\scratchheight
-   \setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}%
+   \setbox\nextbox\hpack{\lower\dp\nextbox\box\nextbox}%
    \dp\nextbox\dp\strutbox
    \ht\nextbox\scratchheight
    \box\nextbox
@@ -2247,9 +2248,9 @@
 %D
 %D A few more boxes.
 
-\def\dodolhbox{\hbox to \hsize{\box\nextbox\hss    }}
-\def\dodomhbox{\hbox to \hsize{\hss\box\nextbox\hss}}
-\def\dodorhbox{\hbox to \hsize{\hss\box\nextbox    }}
+\def\dodolhbox{\hpack to \hsize{\box\nextbox\hss    }}
+\def\dodomhbox{\hpack to \hsize{\hss\box\nextbox\hss}}
+\def\dodorhbox{\hpack to \hsize{\hss\box\nextbox    }}
 
 \unexpanded\def\lhbox{\dowithnextboxcs\dodolhbox\hbox}
 \unexpanded\def\mhbox{\dowithnextboxcs\dodomhbox\hbox}
@@ -2315,7 +2316,7 @@
       \dimen0\ht\nextbox
       \ht\nextbox\strutht
       \dp\nextbox\strutdp
-      \hbox{\box\nextbox}
+      \hpack{\box\nextbox}
       \prevdepth\strutdp
       \doloop
         {\advance\dimen0 -\lineheight
@@ -2323,7 +2324,7 @@
            \exitloop
          \else
            \nobreak
-           \hbox{\strut}
+           \hpack{\strut}
          \fi}
       \egroup}
      \vbox}
@@ -2341,7 +2342,7 @@
   {\iftraceboxplacement
      \bgroup
      \scratchdimen2\onepoint
-     \setbox\scratchbox\hbox to \zeropoint
+     \setbox\scratchbox\hpack to \zeropoint
        {\hss
         \vrule
           \s!width \scratchdimen
@@ -2361,14 +2362,14 @@
 \newdimen\boxhdisplacement
 \newdimen\boxvdisplacement
 
-\unexpanded\def\rightbox      {\hbox\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish      \placedbox}
-\unexpanded\def\leftbox       {\hbox\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish       \placedbox}
-\unexpanded\def\topbox        {\hbox\bgroup\dowithnextboxcs\syst_boxes_topbox_finish        \placedbox}
-\unexpanded\def\bottombox     {\hbox\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish     \placedbox}
-\unexpanded\def\lefttopbox    {\hbox\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish    \placedbox}
-\unexpanded\def\righttopbox   {\hbox\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish   \placedbox}
-\unexpanded\def\leftbottombox {\hbox\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox}
-\unexpanded\def\rightbottombox{\hbox\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox}
+\unexpanded\def\rightbox      {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish      \placedbox}
+\unexpanded\def\leftbox       {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish       \placedbox}
+\unexpanded\def\topbox        {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish        \placedbox}
+\unexpanded\def\bottombox     {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish     \placedbox}
+\unexpanded\def\lefttopbox    {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish    \placedbox}
+\unexpanded\def\righttopbox   {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish   \placedbox}
+\unexpanded\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox}
+\unexpanded\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox}
 
 \let\topleftbox    \lefttopbox
 \let\toprightbox   \righttopbox
@@ -2434,10 +2435,10 @@
    \boxcursor\kern\boxhdisplacement\lower\boxvdisplacement\box\nextbox
    \egroup}
 
-\unexpanded\def\middlebox        {\hbox\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish        \placedbox}
-\unexpanded\def\baselinemiddlebox{\hbox\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox}
-\unexpanded\def\baselineleftbox  {\hbox\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish  \placedbox}
-\unexpanded\def\baselinerightbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox}
+\unexpanded\def\middlebox        {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish        \placedbox}
+\unexpanded\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox}
+\unexpanded\def\baselineleftbox  {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish  \placedbox}
+\unexpanded\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox}
 
 \def\syst_boxes_middlebox_finish
   {\global\boxhdisplacement-.5\wd\nextbox
@@ -2476,7 +2477,7 @@
    \dowithnextboxcontent
      {\advance\hsize-#1\advance\hsize-#2\relax
       \advance\vsize-#3\advance\vsize-#4\relax}
-     {\forgetall\vbox to \vsize{\vskip#3\hbox to \hsize{\hskip#1\box\nextbox\hss}\vss}\egroup}
+     {\forgetall\vpack to \vsize{\vskip#3\hpack to \hsize{\hskip#1\box\nextbox\hss}\vss}\egroup}
      \vbox}
 
 %D \macros
@@ -2518,6 +2519,8 @@
 %D \hbox{y:\foundbox{two}{a}} \par
 %D \stoptyping
 
+%D Kind of obsolete:
+
 \installcorenamespace {stackbox}
 \installcorenamespace {stacklst}
 
@@ -2530,7 +2533,7 @@
 \unexpanded\def\initializeboxstack#1%
   {\def\docommand##1{\setstackbox{#1}{##1}{}}%
    \ifcsname\??stacklst#1\endcsname
-     \processcommacommand[\getvalue{\??stacklst#1}]\docommand
+     \expandafter\processcommacommand\expandafter[\lastnamedcs]\docommand
    \fi
    \letgvalueempty{\??stacklst#1}}
 
@@ -2538,28 +2541,32 @@
   {% beware, \setxvalue defines the cs beforehand so we cannot use the
    % test inside the { }
    \ifcsname\??stacklst#1\endcsname
-     \setxvalue{\??stacklst#1}{\csname\??stacklst#1\endcsname,#2}%
+    %\setxvalue{\??stacklst#1}{\csname\??stacklst#1\endcsname,#2}%
+     \expandafter\xdef\csname\??stacklst#1\expandafter\endcsname\expandafter{\lastnamedcs,#2}%
    \else
-     \setxvalue{\??stacklst#1}{#2}%
+     \expandafter\xdef\csname\??stacklst#1\endcsname{#2}%
    \fi
    \setstackbox{#1}{#2}}
 
 \unexpanded\def\restorebox#1#2% unwrapped
   {\ifcsname\??stackbox#1:#2\endcsname
-     \copy\csname\??stackbox#1:#2\endcsname
+    %\copy\csname\??stackbox#1:#2\endcsname
+     \copy\lastnamedcs
    \else
      \emptybox
    \fi}
 
 \unexpanded\def\foundbox#1#2% wrapped
-  {\vbox
+  {\vpack
      {\ifcsname\??stackbox#1:#2\endcsname
-        \copy\csname\??stackbox#1:#2\endcsname
+       %\copy\csname\??stackbox#1:#2\endcsname
+        \copy\lastnamedcs
       \fi}}
 
 \unexpanded\def\doifelsebox#1#2#3#4%
   {\ifcsname\??stackbox#1:#2\endcsname
-     \ifvoid\csname\??stackbox#1:#2\endcsname#4\else#3\fi
+    %\ifvoid\csname\??stackbox#1:#2\endcsname#4\else#3\fi
+     \ifvoid\lastnamedcs#4\else#3\fi
    \else
      #4%
    \fi}
@@ -2665,14 +2672,14 @@
 \def\syst_boxes_lower_indeed{\dowithnextboxcs\syst_boxes_lower_finish}
 
 \def\syst_boxes_raise_finish
-  {\setbox\nextbox\hbox{\raise\scratchdimen\box\nextbox}%
+  {\setbox\nextbox\hpack{\raise\scratchdimen\box\nextbox}%
    \ht\nextbox\strutht
    \dp\nextbox\strutdp
    \box\nextbox
    \egroup}
 
 \def\syst_boxes_lower_finish
-  {\setbox\nextbox\hbox{\lower\scratchdimen\box\nextbox}%
+  {\setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}%
    \ht\nextbox\strutht
    \dp\nextbox\strutdp
    \box\nextbox
@@ -2712,9 +2719,10 @@
 
 \ifdefined\textdir
 
-    \unexpanded\def\naturalhbox{\hbox dir TLT}
-    \unexpanded\def\naturalvbox{\vbox dir TLT}
-   %\unexpanded\def\naturalvtop{\normalvtop dir TLT}
+    \unexpanded\def\naturalhbox {\hbox dir TLT}
+    \unexpanded\def\naturalvbox {\vbox dir TLT}
+    \unexpanded\def\naturalhpack{\hpack dir TLT}
+    \unexpanded\def\naturalvpack{\vpack dir TLT}
 
 \fi
 
@@ -2728,7 +2736,7 @@
    \dowithnextboxcs\syst_boxes_vcenter_finish\vbox}
 
 \def\syst_boxes_vcenter_finish
-  {\hbox{$\normalvcenter{\box\nextbox}$}%
+  {\hpack{$\normalvcenter{\box\nextbox}$}%
    \egroup}
 
 % could be \everymathematics
@@ -2748,7 +2756,7 @@
    \dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox}
 
 \def\syst_boxes_frozenhbox_finish
-  {\hbox{\hbox{\box\nextbox}}%
+  {\hpack{\hpack{\box\nextbox}}%
    \egroup}
 
 %D \macros
@@ -2765,8 +2773,10 @@
 \unexpanded\def\gsetboxllx#1#2{\expandafter\xdef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}}
 \unexpanded\def\gsetboxlly#1#2{\expandafter\xdef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}}
 
-\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\csname\??box_x\number#1\endcsname\else\zeropoint\fi}
-\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\csname\??box_y\number#1\endcsname\else\zeropoint\fi}
+%def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\csname\??box_x\number#1\endcsname\else\zeropoint\fi}
+%def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\csname\??box_y\number#1\endcsname\else\zeropoint\fi}
+\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
 
 \def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence
 \def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence
@@ -2831,7 +2841,7 @@
 \unexpanded\def\minimalhbox#1#%
   {\dowithnextbox
      {\bgroup
-      \setbox\scratchbox\hbox#1{\hss}%
+      \setbox\scratchbox\hpack#1{\hss}%
       \ifdim\wd\nextbox<\wd\scratchbox\wd\nextbox\wd\scratchbox\fi
       \box\nextbox
       \egroup}
diff --git a/tex/context/base/symb-ini.mkiv b/tex/context/base/symb-ini.mkiv
index 40a0af6d6..23879b43a 100644
--- a/tex/context/base/symb-ini.mkiv
+++ b/tex/context/base/symb-ini.mkiv
@@ -72,8 +72,6 @@
      \addvalue{\??symbolset\m_symb_current_set}{#1}%
    \fi}
 
-\letvalue{\??symbolset}\empty
-
 \unexpanded\def\doifelseinsymbolset#1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
 \unexpanded\def\doifinsymbolset    #1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument   \fi}
 \unexpanded\def\doifelsesymbolset    #1{\ifcsname\??symbolset#1\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
@@ -81,7 +79,11 @@
 \let\doifinsymbolsetelse\doifelseinsymbolset
 \let\doifsymbolsetelse  \doifelsesymbolset
 
-\def\symbolset#1{\csname\??symbolset\ifcsname\??symbolset#1\endcsname#1\fi\endcsname} % no [#1], to be used in commalists etc
+\letvalue{\??symbolset}\empty
+
+%def\symbolset#1{\csname\??symbolset\ifcsname\??symbolset#1\endcsname#1\fi\endcsname} % no [#1], to be used in commalists etc
+
+\def\symbolset#1{\begincsname\??symbolset#1\endcsname} % no [#1], to be used in commalists etc
 
 %D Since symbols are used frequently in interactive
 %D documents, we speed up this one. Well, that was history,
@@ -148,7 +150,8 @@
 \letvalue{\??symbol}\firstofoneargument
 
 \def\directsymbol#1#2% no \relax, there can be an argument, see lists
-  {\csname\??symbol\ifcsname\??symbol#1:#2\endcsname#1:#2\fi\endcsname}
+ %{\csname\??symbol\ifcsname\??symbol#1:#2\endcsname#1:#2\fi\endcsname}
+  {\begincsname\??symbol#1:#2\endcsname}
 
 \unexpanded\def\symb_fetch
   {\ifconditional\c_symb_found
diff --git a/tex/context/base/syst-aux.lua b/tex/context/base/syst-aux.lua
index fff9bbb4c..0e7b2c2b6 100644
--- a/tex/context/base/syst-aux.lua
+++ b/tex/context/base/syst-aux.lua
@@ -14,6 +14,8 @@ if not modules then modules = { } end modules ['syst-aux'] = {
 local tonumber = tonumber
 local utfsub = utf.sub
 local P, S, R, C, Cc, Cs, Carg, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg, lpeg.match
+local next = next
+local find  = string.find
 
 local context           = context
 local implement         = interfaces.implement
@@ -21,6 +23,7 @@ local formatters        = string.formatters
 local setcatcode        = tex.setcatcode
 local utf8character     = lpeg.patterns.utf8character
 local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_set  = utilities.parsers.settings_to_set
 local setmacro          = interfaces.setmacro
 
 local pattern           = C(utf8character^-1) * C(P(1)^0)
@@ -227,3 +230,247 @@ implement {
     arguments = "integer",
     actions   = function(n,m) context(accuracy[n](m)) end
 }
+
+-- not faster but just less tracing:
+
+local firstoftwoarguments  = context.firstoftwoarguments
+local secondoftwoarguments = context.secondoftwoarguments
+local firstofoneargument   = context.firstofoneargument
+local gobbleoneargument    = context.gobbleoneargument
+
+local hash = utilities.parsers.hashes.settings_to_set
+
+local function doifelsecommon(a,b)
+    if a == b then
+        setmacro("commalistelement",a)
+        if a == "" then
+            secondoftwoarguments()
+        else
+            firstoftwoarguments()
+        end
+        return
+    end
+    local ba = find(a,",")
+    local bb = find(b,",")
+    if ba and bb then
+        local ha = hash[a]
+        local hb = hash[b]
+     -- local ha = settings_to_set(a)
+     -- local hb = settings_to_set(b)
+        for k in next, ha do
+            if hb[k] then
+                setmacro("commalistelement",k)
+                firstoftwoarguments()
+                return
+            end
+        end
+    elseif ba then
+        if hash[a][b] then
+     -- if settings_to_set(a)[b] then
+            setmacro("commalistelement",b)
+            firstoftwoarguments()
+            return
+        end
+    elseif bb then
+        if hash[b][a] then
+     -- if settings_to_set(b)[a] then
+            setmacro("commalistelement",a)
+            firstoftwoarguments()
+            return
+        end
+    end
+    setmacro("commalistelement","")
+    secondoftwoarguments()
+end
+
+local function doifcommon(a,b)
+    if a == b then
+        setmacro("commalistelement",a)
+        if a == "" then
+            gobbleoneargument()
+        else
+            firstofoneargument()
+        end
+        return
+    end
+    local ba = find(a,",")
+    local bb = find(b,",")
+    if ba and bb then
+        local ha = hash[a]
+        local hb = hash[b]
+     -- local ha = settings_to_set(a)
+     -- local hb = settings_to_set(b)
+        for k in next, ha do
+            if hb[k] then
+                setmacro("commalistelement",k)
+                firstofoneargument()
+                return
+            end
+        end
+    elseif ba then
+        if hash[a][b] then
+     -- if settings_to_set(a)[b] then
+            setmacro("commalistelement",b)
+            firstofoneargument()
+            return
+        end
+    elseif bb then
+        if hash[b][a] then
+     -- if settings_to_set(b)[a] then
+            setmacro("commalistelement",a)
+            firstofoneargument()
+            return
+        end
+    end
+    setmacro("commalistelement","")
+    gobbleoneargument()
+end
+
+local function doifnotcommon(a,b)
+    if a == b then
+        setmacro("commalistelement",a)
+        if a == "" then
+            firstofoneargument()
+        else
+            gobbleoneargument()
+        end
+        return
+    end
+    local ba = find(a,",")
+    local bb = find(b,",")
+    if ba and bb then
+        local ha = hash[a]
+        local hb = hash[b]
+     -- local ha = settings_to_set(a)
+     -- local hb = settings_to_set(b)
+        for k in next, ha do
+            if hb[k] then
+                setmacro("commalistelement",k)
+                gobbleoneargument()
+                return
+            end
+        end
+    elseif ba then
+        if hash[a][b] then
+     -- if settings_to_set(a)[b] then
+            setmacro("commalistelement",b)
+            gobbleoneargument()
+            return
+        end
+    elseif bb then
+        if hash[b][a] then
+     -- if settings_to_set(b)[a] then
+            setmacro("commalistelement",a)
+            gobbleoneargument()
+            return
+        end
+    end
+    setmacro("commalistelement","")
+    firstofoneargument()
+end
+
+local function doifelseinset(a,b)
+    if a == b then
+        setmacro("commalistelement",a)
+        if a == "" then
+            secondoftwoarguments()
+        else
+            firstoftwoarguments()
+        end
+        return
+    end
+    local bb = find(b,",")
+    if bb then
+        if hash[b][a] then
+     -- if settings_to_set(b)[a] then
+            setmacro("commalistelement",a)
+            firstoftwoarguments()
+            return
+        end
+    end
+    setmacro("commalistelement","")
+    secondoftwoarguments()
+end
+
+local function doifinset(a,b)
+    if a == b then
+        setmacro("commalistelement",a)
+        if a == "" then
+            gobbleoneargument()
+        else
+            firstofoneargument()
+        end
+        return
+    end
+    local bb = find(b,",")
+    if bb then
+       if hash[b][a] then
+    -- if settings_to_set(b)[a] then
+            setmacro("commalistelement",a)
+            firstofoneargument()
+            return
+        end
+    end
+    setmacro("commalistelement","")
+    gobbleoneargument()
+end
+
+local function doifnotinset(a,b)
+    if a == b then
+        setmacro("commalistelement",a)
+        if a == "" then
+            firstofoneargument()
+        else
+            gobbleoneargument()
+        end
+        return
+    end
+    local bb = find(b,",")
+    if bb then
+        if hash[b][a] then
+     -- if settings_to_set(b)[a] then
+            setmacro("commalistelement",a)
+            gobbleoneargument()
+            return
+        end
+    end
+    setmacro("commalistelement","")
+    firstofoneargument()
+end
+
+interfaces.implement {
+    name      = "doifelsecommon",
+    actions   = doifelsecommon,
+    arguments = { "string", "string" },
+}
+
+interfaces.implement {
+    name      = "doifcommon",
+    actions   = doifcommon,
+    arguments = { "string", "string" },
+}
+
+interfaces.implement {
+    name      = "doifnotcommon",
+    actions   = doifnotcommon,
+    arguments = { "string", "string" },
+}
+
+interfaces.implement {
+    name      = "doifelseinset",
+    actions   = doifelseinset,
+    arguments = { "string", "string" },
+}
+
+interfaces.implement {
+    name      = "doifinset",
+    actions   = doifinset,
+    arguments = { "string", "string" },
+}
+
+interfaces.implement {
+    name      = "doifnotinset",
+    actions   = doifnotinset,
+    arguments = { "string", "string" },
+}
+
diff --git a/tex/context/base/syst-aux.mkiv b/tex/context/base/syst-aux.mkiv
index dd8d5b3ae..5b7059ea9 100644
--- a/tex/context/base/syst-aux.mkiv
+++ b/tex/context/base/syst-aux.mkiv
@@ -48,15 +48,15 @@
 %D \macros
 %D   {unexpanded}
 %D
-%D Because we use this module only in \MKIV, we have removed the
-%D old protection code.
+%D Because we use this module only in \MKIV, we have removed the old protection
+%D code.
 %D
 %D \starttyping
 %D \unexpanded\def\somecommand{... ... ...}
 %D \stoptyping
 %D
-%D This overloads the \ETEX\ primitive but as we already had an \MKII\
-%D solution we keep the same name for a similar mechanism.
+%D This overloads the \ETEX\ primitive but as we already had an \MKII\ solution we
+%D keep the same name for a similar mechanism.
 
 \let\unexpanded\normalprotected
 
@@ -100,8 +100,7 @@
 %D \macros
 %D   {normalspace}
 %D
-%D There is already \type{\space} but just to be sure we also
-%D provide:
+%D There is already \type{\space} but just to be sure we also provide:
 
 \def\normalspace{ }
 
@@ -109,9 +108,8 @@
 %D   {!!count, !!toks, !!dimen, !!box,
 %D    !!width, !!height, !!depth, !!string, !!done}
 %D
-%D We define some more \COUNTERS\ and \DIMENSIONS. We also
-%D define some shortcuts to the local scatchregisters~0, 2, 4,
-%D 6 and~8.
+%D We define some more \COUNTERS\ and \DIMENSIONS. We also define some shortcuts to
+%D the local scatchregisters~0, 2, 4, 6 and~8.
 
 \newcount\!!counta \newtoks\!!toksa \newdimen\!!dimena \newbox\!!boxa
 \newcount\!!countb \newtoks\!!toksb \newdimen\!!dimenb \newbox\!!boxb
@@ -158,9 +156,8 @@
 %D \macros
 %D   {s!,c!,e!,p!,v!,@@,??}
 %D
-%D To save memory, we use constants (sometimes called
-%D variables). Redefining these constants can have disastrous
-%D results.
+%D To save memory, we use constants (sometimes called variables). Redefining these
+%D constants can have disastrous results.
 
 \def\v!prefix! {v!}
 \def\c!prefix! {c!}
@@ -181,8 +178,9 @@
 
 \def\s!empty   {empty}
 
-%D These are not needed any more now that we have wide screens (and
-%D bytes come cheap).
+%D These are not needed any more now that we have wide screens (and bytes come
+%D cheap).
+
 
 \let\@EA          \singleexpandafter
 \let\@EAEAEA      \doubleexpandafter
@@ -265,19 +263,16 @@
 %D \macros
 %D   {doifnextcharelse}
 %D
-%D When we started using \TEX\ in the late eighties, our
-%D first experiences with programming concerned a simple shell
-%D around \LATEX. The commands probably use most at \PRAGMA,
-%D are the itemizing ones. One of those few shell commands took
-%D care of an optional argument, that enabled us to specify
-%D what kind of item symbol we wanted. Without understanding
-%D anything we were able to locate a \LATEX\ macro that could
-%D be used to inspect the next character.
+%D When we started using \TEX\ in the late eighties, our first experiences with
+%D programming concerned a simple shell around \LATEX. The commands probably use
+%D most at \PRAGMA, are the itemizing ones. One of those few shell commands took
+%D care of an optional argument, that enabled us to specify what kind of item symbol
+%D we wanted. Without understanding anything we were able to locate a \LATEX\ macro
+%D that could be used to inspect the next character.
 %D
-%D It's this macro that the ancester of the next one presented
-%D here. It executes one of two actions, dependant of the next
-%D character. Disturbing spaces and line endings, which are
-%D normally interpreted as spaces too, are skipped.
+%D It's this macro that the ancester of the next one presented here. It executes one
+%D of two actions, dependant of the next character. Disturbing spaces and line
+%D endings, which are normally interpreted as spaces too, are skipped.
 %D
 %D \starttyping
 %D \doifnextcharelse {karakter} {then ...} {else ...}
@@ -309,16 +304,14 @@
      \expandafter\m_syst_action_nop
    \fi}
 
-%D Because we will mostly use this macro for testing if the next
-%D character is \type {[}, we also make a slightly faster variant
-%D as it is not uncommon to have tens of thousands of calls to this
-%D test in a run. Of course it also is more convenient to read a
-%D trace then.
+%D Because we will mostly use this macro for testing if the next character is \type
+%D {[}, we also make a slightly faster variant as it is not uncommon to have tens of
+%D thousands of calls to this test in a run. Of course it also is more convenient to
+%D read a trace then.
 
-% We could make variants without the \if_next_blank_space_token but
-% the overhead is only .1 sec on 3.5 for 10^6 tests and often that
-% branch is not entered anyway. The fast variants with less checking
-% do make a difference however:
+% We could make variants without the \if_next_blank_space_token but the overhead is
+% only .1 sec on 3.5 for 10^6 tests and often that branch is not entered anyway. The
+% fast variants with less checking do make a difference however:
 
 % \testfeature{1000000}{\doifnextoptionalelse       \gobbleoneargument\gobbleoneargument[} % 2.902s
 % \testfeature{1000000}{\doifnextoptionalcselse     \gobbleoneargument\gobbleoneargument[} % 2.590s
@@ -782,132 +775,138 @@
 % !5yes=\doifnotinset{}{}{yes}
 % !6yes=\doifnotinset{aaa}{}{yes}
 
-\def\v_syst_helpers_right_optional_bracket{]}
-
-\def\syst_helpers_do_quit_if_item_in_set_else#1],\relax{\firstoftwoarguments}
-\def\syst_helpers_do_quit_if_item_in_set     #1],\relax{\firstofoneargument}
-\def\syst_helpers_do_quit_if_item_not_in_set #1],\relax{\gobbleoneargument}
-
-\def\syst_helpers_re_do_if_in_set_else{\expandafter\syst_helpers_do_check_if_item_in_set_else\m_syst_string_two,],\relax}
-\def\syst_helpers_re_do_if_in_set     {\expandafter\syst_helpers_do_check_if_item_in_set     \m_syst_string_two,],\relax}
-\def\syst_helpers_re_do_if_not_in_set {\expandafter\syst_helpers_do_check_if_item_not_in_set \m_syst_string_two,],\relax}
+% \def\v_syst_helpers_right_optional_bracket{]}
+%
+% \def\syst_helpers_do_quit_if_item_in_set_else#1],\relax{\firstoftwoarguments}
+% \def\syst_helpers_do_quit_if_item_in_set     #1],\relax{\firstofoneargument}
+% \def\syst_helpers_do_quit_if_item_not_in_set #1],\relax{\gobbleoneargument}
+%
+% \def\syst_helpers_re_do_if_in_set_else{\expandafter\syst_helpers_do_check_if_item_in_set_else\m_syst_string_two,],\relax}
+% \def\syst_helpers_re_do_if_in_set     {\expandafter\syst_helpers_do_check_if_item_in_set     \m_syst_string_two,],\relax}
+% \def\syst_helpers_re_do_if_not_in_set {\expandafter\syst_helpers_do_check_if_item_not_in_set \m_syst_string_two,],\relax}
+%
+% \unexpanded\def\doifelseinset#1% make this two step too
+%   {\edef\m_syst_string_one{#1}%
+%    \ifx\m_syst_string_one\empty
+%      \expandafter\thirdofthreearguments
+%    \else
+%      \expandafter\syst_helpers_do_if_in_set_else
+%    \fi}
+%
+% \let\doifinsetelse\doifelseinset
+%
+% \def\syst_helpers_do_if_in_set_else#1%
+%   {\edef\m_syst_string_two{#1}%
+%    \ifx\m_syst_string_two\empty
+%      \expandafter\secondoftwoarguments
+%    \else
+%      \expandafter\syst_helpers_re_do_if_in_set_else
+%    \fi}
+%
+% \unexpanded\def\doifinset#1%
+%   {\edef\m_syst_string_one{#1}%
+%    \ifx\m_syst_string_one\empty
+%      \expandafter\gobbletwoarguments
+%    \else
+%      \expandafter\syst_helpers_do_if_in_set
+%    \fi}
+%
+% \def\syst_helpers_do_if_in_set#1%
+%   {\edef\m_syst_string_two{#1}%
+%    \ifx\m_syst_string_two\empty
+%      \expandafter\gobbleoneargument
+%    \else
+%      \expandafter\syst_helpers_re_do_if_in_set
+%    \fi}
+%
+% \unexpanded\def\doifnotinset#1%
+%   {\edef\m_syst_string_one{#1}%
+%    \ifx\m_syst_string_one\empty
+%      \expandafter\secondoftwoarguments
+%    \else
+%      \expandafter\syst_helpers_do_if_not_in_set
+%    \fi}
+%
+% \def\syst_helpers_do_if_not_in_set#1%
+%   {\edef\m_syst_string_two{#1}%
+%    \ifx\m_syst_string_two\empty
+%      \expandafter\firstofoneargument
+%    \else
+%      \expandafter\syst_helpers_re_do_if_not_in_set % ...]{true}
+%    \fi}
+%
+% \def\syst_helpers_do_check_if_item_in_set_else#1,#2% #2 eats up preceding space
+%   {\edef\m_syst_string_two{#1}%
+%    \ifx\m_syst_string_two\empty
+%      \expandafter\syst_helpers_do_check_if_item_in_set_else
+%    \else
+%      \expandafter\syst_helpers_do_do_check_if_item_in_set_else
+%    \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_item_in_set_else
+%   {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
+%      \expandafter\thirdofthreearguments
+%    \else
+%      \expandafter\syst_helpers_do_do_do_check_if_item_in_set_else
+%    \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_item_in_set_else
+%   {\ifx\m_syst_string_one\m_syst_string_two
+%      \expandafter\syst_helpers_do_quit_if_item_in_set_else
+%    \else
+%      \expandafter\syst_helpers_do_check_if_item_in_set_else
+%    \fi}
+%
+% \def\syst_helpers_do_check_if_item_in_set#1,#2% #2 eats up preceding space
+%   {\edef\m_syst_string_two{#1}%
+%    \ifx\m_syst_string_two\empty
+%      \expandafter\syst_helpers_do_check_if_item_in_set
+%    \else
+%      \expandafter\syst_helpers_do_do_check_if_item_in_set
+%    \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_item_in_set
+%   {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
+%      \expandafter\gobbletwoarguments
+%    \else
+%      \expandafter\syst_helpers_do_do_do_check_if_item_in_set
+%    \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_item_in_set
+%   {\ifx\m_syst_string_one\m_syst_string_two
+%      \expandafter\syst_helpers_do_quit_if_item_in_set
+%    \else
+%      \expandafter\syst_helpers_do_check_if_item_in_set
+%    \fi}
+%
+% \def\syst_helpers_do_check_if_item_not_in_set#1,#2% #2 eats up preceding space
+%   {\edef\m_syst_string_two{#1}%
+%    \ifx\m_syst_string_two\empty
+%      \expandafter\syst_helpers_do_check_if_item_not_in_set
+%    \else
+%      \expandafter\syst_helpers_do_do_check_if_item_not_in_set
+%    \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_item_not_in_set
+%   {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
+%      \expandafter\secondoftwoarguments
+%    \else
+%      \expandafter\syst_helpers_do_do_do_check_if_item_not_in_set
+%    \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_item_not_in_set
+%   {\ifx\m_syst_string_one\m_syst_string_two
+%      \expandafter\syst_helpers_do_quit_if_item_not_in_set
+%    \else
+%      \expandafter\syst_helpers_do_check_if_item_not_in_set
+%    \fi}
 
-\unexpanded\def\doifelseinset#1% make this two step too
-  {\edef\m_syst_string_one{#1}%
-   \ifx\m_syst_string_one\empty
-     \expandafter\thirdofthreearguments
-   \else
-     \expandafter\syst_helpers_do_if_in_set_else
-   \fi}
+\unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}}
+\unexpanded\def\doifinset    #1#2{\clf_doifinset    {#1}{#2}}
+\unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}}
 
 \let\doifinsetelse\doifelseinset
 
-\def\syst_helpers_do_if_in_set_else#1%
-  {\edef\m_syst_string_two{#1}%
-   \ifx\m_syst_string_two\empty
-     \expandafter\secondoftwoarguments
-   \else
-     \expandafter\syst_helpers_re_do_if_in_set_else
-   \fi}
-
-\unexpanded\def\doifinset#1%
-  {\edef\m_syst_string_one{#1}%
-   \ifx\m_syst_string_one\empty
-     \expandafter\gobbletwoarguments
-   \else
-     \expandafter\syst_helpers_do_if_in_set
-   \fi}
-
-\def\syst_helpers_do_if_in_set#1%
-  {\edef\m_syst_string_two{#1}%
-   \ifx\m_syst_string_two\empty
-     \expandafter\gobbleoneargument
-   \else
-     \expandafter\syst_helpers_re_do_if_in_set
-   \fi}
-
-\unexpanded\def\doifnotinset#1%
-  {\edef\m_syst_string_one{#1}%
-   \ifx\m_syst_string_one\empty
-     \expandafter\secondoftwoarguments
-   \else
-     \expandafter\syst_helpers_do_if_not_in_set
-   \fi}
-
-\def\syst_helpers_do_if_not_in_set#1%
-  {\edef\m_syst_string_two{#1}%
-   \ifx\m_syst_string_two\empty
-     \expandafter\firstofoneargument
-   \else
-     \expandafter\syst_helpers_re_do_if_not_in_set % ...]{true}
-   \fi}
-
-\def\syst_helpers_do_check_if_item_in_set_else#1,#2% #2 eats up preceding space
-  {\edef\m_syst_string_two{#1}%
-   \ifx\m_syst_string_two\empty
-     \expandafter\syst_helpers_do_check_if_item_in_set_else
-   \else
-     \expandafter\syst_helpers_do_do_check_if_item_in_set_else
-   \fi#2}
-
-\def\syst_helpers_do_do_check_if_item_in_set_else
-  {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
-     \expandafter\thirdofthreearguments
-   \else
-     \expandafter\syst_helpers_do_do_do_check_if_item_in_set_else
-   \fi}
-
-\def\syst_helpers_do_do_do_check_if_item_in_set_else
-  {\ifx\m_syst_string_one\m_syst_string_two
-     \expandafter\syst_helpers_do_quit_if_item_in_set_else
-   \else
-     \expandafter\syst_helpers_do_check_if_item_in_set_else
-   \fi}
-
-\def\syst_helpers_do_check_if_item_in_set#1,#2% #2 eats up preceding space
-  {\edef\m_syst_string_two{#1}%
-   \ifx\m_syst_string_two\empty
-     \expandafter\syst_helpers_do_check_if_item_in_set
-   \else
-     \expandafter\syst_helpers_do_do_check_if_item_in_set
-   \fi#2}
-
-\def\syst_helpers_do_do_check_if_item_in_set
-  {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
-     \expandafter\gobbletwoarguments
-   \else
-     \expandafter\syst_helpers_do_do_do_check_if_item_in_set
-   \fi}
-
-\def\syst_helpers_do_do_do_check_if_item_in_set
-  {\ifx\m_syst_string_one\m_syst_string_two
-     \expandafter\syst_helpers_do_quit_if_item_in_set
-   \else
-     \expandafter\syst_helpers_do_check_if_item_in_set
-   \fi}
-
-\def\syst_helpers_do_check_if_item_not_in_set#1,#2% #2 eats up preceding space
-  {\edef\m_syst_string_two{#1}%
-   \ifx\m_syst_string_two\empty
-     \expandafter\syst_helpers_do_check_if_item_not_in_set
-   \else
-     \expandafter\syst_helpers_do_do_check_if_item_not_in_set
-   \fi#2}
-
-\def\syst_helpers_do_do_check_if_item_not_in_set
-  {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
-     \expandafter\secondoftwoarguments
-   \else
-     \expandafter\syst_helpers_do_do_do_check_if_item_not_in_set
-   \fi}
-
-\def\syst_helpers_do_do_do_check_if_item_not_in_set
-  {\ifx\m_syst_string_one\m_syst_string_two
-     \expandafter\syst_helpers_do_quit_if_item_not_in_set
-   \else
-     \expandafter\syst_helpers_do_check_if_item_not_in_set
-   \fi}
-
 %D \macros
 %D   {doifcommon,doifnotcommon,doifcommonelse}
 %D
@@ -936,65 +935,71 @@
 % !9yes=\doifcommonelse{,a,}{,,,a,}{yes}{nop}
 % !9yes=\doifcommonelse{,,a,}{,,,a,}{yes}{nop}
 
-\let\m_syst_common_a\empty
-\let\m_syst_common_b\empty
-\let\m_syst_common_c\empty
-
-\def\syst_helpers_do_quit_if_common_else#1],\relax#2],\relax{\firstoftwoarguments}
-
-\def\syst_helpers_do_check_if_common_else_one#1,#2%
-  {\edef\m_syst_common_c{#1}%
-   \ifx\m_syst_common_c\v_syst_helpers_right_optional_bracket
-     \expandafter\thirdofthreearguments
-   \else
-     \expandafter\syst_helpers_do_common_check
-   \fi#2}
-
-\def\syst_helpers_do_check_if_common_else_two#1,#2% we can do an empty #1 check too
-  {\edef\commalistelement{#1}%
-   \ifx\commalistelement\v_syst_helpers_right_optional_bracket
-     \expandafter\syst_helpers_re_do_check_if_common_else_one
-   \else
-     \expandafter\syst_helpers_do_do_check_if_common_else_two
-   \fi#2}
-
-\def\syst_helpers_do_do_check_if_common_else_two
-  {\ifx\commalistelement\empty
-     \expandafter\syst_helpers_do_check_if_common_else_two
-   \else
-     \expandafter\syst_helpers_do_do_do_check_if_common_else_two
-   \fi}
-
-\def\syst_helpers_do_do_do_check_if_common_else_two
-  {\ifx\m_syst_common_c\commalistelement
-     \expandafter\syst_helpers_do_quit_if_common_else
-   \else
-     \expandafter\syst_helpers_do_check_if_common_else_two
-   \fi}
-
-\def\syst_helpers_re_do_check_if_common_else_one#1{\syst_helpers_do_check_if_common_else_one}
-
-\def\syst_helpers_do_common_check
-  {\expandafter\syst_helpers_do_check_if_common_else_two\m_syst_common_b,],\relax}%
-
-\def\syst_helpers_do_do_do_if_common_else
-  {\expandafter\syst_helpers_do_check_if_common_else_one\m_syst_common_a,],\relax}
+% \let\m_syst_common_a\empty
+% \let\m_syst_common_b\empty
+% \let\m_syst_common_c\empty
+%
+% \def\syst_helpers_do_quit_if_common_else#1],\relax#2],\relax{\firstoftwoarguments}
+%
+% \def\syst_helpers_do_check_if_common_else_one#1,#2% hm, why #2 here and passed at end
+%   {\edef\m_syst_common_c{#1}%
+%    \ifx\m_syst_common_c\v_syst_helpers_right_optional_bracket
+%      \expandafter\thirdofthreearguments
+%    \else
+%      \expandafter\syst_helpers_do_common_check
+%    \fi#2}
+%
+% \def\syst_helpers_do_check_if_common_else_two#1,#2% we can do an empty #1 check too
+%   {\edef\commalistelement{#1}%
+%    \ifx\commalistelement\v_syst_helpers_right_optional_bracket
+%      \expandafter\syst_helpers_re_do_check_if_common_else_one
+%    \else
+%      \expandafter\syst_helpers_do_do_check_if_common_else_two
+%    \fi#2}
+%
+% \def\syst_helpers_do_do_check_if_common_else_two
+%   {\ifx\commalistelement\empty
+%      \expandafter\syst_helpers_do_check_if_common_else_two
+%    \else
+%      \expandafter\syst_helpers_do_do_do_check_if_common_else_two
+%    \fi}
+%
+% \def\syst_helpers_do_do_do_check_if_common_else_two
+%   {\ifx\m_syst_common_c\commalistelement
+%      \expandafter\syst_helpers_do_quit_if_common_else
+%    \else
+%      \expandafter\syst_helpers_do_check_if_common_else_two
+%    \fi}
+%
+% \def\syst_helpers_re_do_check_if_common_else_one#1{\syst_helpers_do_check_if_common_else_one}
+%
+% \def\syst_helpers_do_common_check
+%   {\expandafter\syst_helpers_do_check_if_common_else_two\m_syst_common_b,],\relax}%
+%
+% \def\syst_helpers_do_do_do_if_common_else
+%   {\expandafter\syst_helpers_do_check_if_common_else_one\m_syst_common_a,],\relax}
+%
+% \def\syst_helpers_do_do_if_common_else#1#2#3#4%
+%   {\edef\m_syst_common_a{#3}%
+%    \edef\m_syst_common_b{#4}%
+%    \ifx\m_syst_common_a\empty
+%      \expandafter\secondoftwoarguments
+%    \else\ifx\m_syst_common_b\empty
+%      \expandafter\expandafter\expandafter\secondoftwoarguments
+%    \else
+%      \expandafter\expandafter\expandafter\syst_helpers_do_do_do_if_common_else
+%    \fi\fi
+%    #1#2}
 
-\def\syst_helpers_do_do_if_common_else#1#2#3#4%
-  {\edef\m_syst_common_a{#3}%
-   \edef\m_syst_common_b{#4}%
-   \ifx\m_syst_common_a\empty
-     \expandafter\secondoftwoarguments
-   \else\ifx\m_syst_common_b\empty
-     \expandafter\expandafter\expandafter\secondoftwoarguments
-   \else
-     \expandafter\expandafter\expandafter\syst_helpers_do_do_do_if_common_else
-   \fi\fi
-   #1#2}
+% \unexpanded\def\doifelsecommon{\syst_helpers_do_do_if_common_else\firstoftwoarguments\secondoftwoarguments}
+% \unexpanded\def\doifcommon    {\syst_helpers_do_do_if_common_else\firstofoneargument \gobbleoneargument   }
+% \unexpanded\def\doifnotcommon {\syst_helpers_do_do_if_common_else\gobbleoneargument  \firstofoneargument  }
+%
+% \let\doifcommonelse\doifelsecommon
 
-\unexpanded\def\doifelsecommon{\syst_helpers_do_do_if_common_else\firstoftwoarguments\secondoftwoarguments}
-\unexpanded\def\doifcommon    {\syst_helpers_do_do_if_common_else\firstofoneargument \gobbleoneargument   }
-\unexpanded\def\doifnotcommon {\syst_helpers_do_do_if_common_else\gobbleoneargument  \firstofoneargument  }
+\unexpanded\def\doifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}}
+\unexpanded\def\doifcommon    #1#2{\clf_doifcommon    {#1}{#2}}
+\unexpanded\def\doifnotcommon #1#2{\clf_doifnotcommon {#1}{#2}}
 
 \let\doifcommonelse\doifelsecommon
 
@@ -2723,8 +2728,10 @@
 %D
 %D This expands to \type{\ifsomething}.
 
-\def\strippedcsname
-  {\expandafter\gobbleoneargument\string}
+% \def\strippedcsname
+%   {\expandafter\gobbleoneargument\string}
+
+\let\strippedcsname\csstring
 
 %D \macros
 %D   {complexorsimple,complexorsimpleempty}
@@ -2770,14 +2777,14 @@
 \unexpanded\def\complexorsimple#1%
   {% \relax % prevents lookahead, brrr
    \doifelsenextoptional
-     {\firstargumenttrue \csname\s!complex\strippedcsname#1\endcsname}
-     {\firstargumentfalse\csname\s!simple \strippedcsname#1\endcsname}}
+     {\firstargumenttrue \csname\s!complex\csstring#1\endcsname}
+     {\firstargumentfalse\csname\s!simple \csstring#1\endcsname}}
 
 \unexpanded\def\complexorsimpleempty#1%
   {% \relax % prevents lookahead, brrr
    \doifelsenextoptional
-     {\firstargumenttrue \csname\s!complex\strippedcsname#1\endcsname}
-     {\firstargumentfalse\csname\s!complex\strippedcsname#1\endcsname[]}}
+     {\firstargumenttrue \csname\s!complex\csstring#1\endcsname}
+     {\firstargumentfalse\csname\s!complex\csstring#1\endcsname[]}}
 
 %D \macros
 %D   {definecomplexorsimple,definecomplexorsimpleempty}
@@ -2794,12 +2801,12 @@
 
 \unexpanded\def\definecomplexorsimple#1%
   {\unexpanded\edef#1{\syst_helpers_complex_or_simple
-     \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname
-     \expandafter\noexpand\csname\s!simple \strippedcsname#1\endcsname}}
+     \expandafter\noexpand\csname\s!complex\csstring#1\endcsname
+     \expandafter\noexpand\csname\s!simple \csstring#1\endcsname}}
 
 \unexpanded\def\definecomplexorsimpleempty#1%
   {\unexpanded\edef#1{\syst_helpers_complex_or_simple_empty
-     \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname}}
+     \expandafter\noexpand\csname\s!complex\csstring#1\endcsname}}
 
 %D These commands are called as:
 %D
@@ -3337,7 +3344,9 @@
 
 \egroup
 
-\unexpanded\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace
+% \unexpanded\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace
+
+\unexpanded\def\texdefinition#1{\begincsname#1\endcsname}
 
 % This is a first variant, more might be added:
 
@@ -3461,12 +3470,14 @@
 %D \csname if\strippedcsname\something\endcsname
 %D \stoptyping
 
-\def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
-  {\expandafter\syst_helpers_checked_stripped_csname\string#1}
+% \def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
+%   {\expandafter\syst_helpers_checked_stripped_csname\string#1}
+%
+% \def\syst_helpers_checked_stripped_csname#1%
+%  %{\ifx#1\letterbackslash\else#1\fi}
+%   {\if\noexpand#1\letterbackslash\else#1\fi}
 
-\def\syst_helpers_checked_stripped_csname#1%
- %{\ifx#1\letterbackslash\else#1\fi}
-  {\if\noexpand#1\letterbackslash\else#1\fi}
+\let\checkedstrippedcsname\csstring
 
 %D \macros
 %D   {savenormalmeaning}
@@ -3474,8 +3485,8 @@
 %D We will use this one in:
 
 \unexpanded\def\savenormalmeaning#1%
-  {\ifcsname normal\strippedcsname#1\endcsname \else
-     \expandafter\let\csname normal\strippedcsname#1\endcsname#1%
+  {\ifcsname normal\csstring#1\endcsname \else
+     \expandafter\let\csname normal\csstring#1\endcsname#1%
    \fi}
 
 %D \macros
@@ -3939,18 +3950,15 @@
 %D \macros
 %D   {newevery,everyline,EveryLine,EveryPar}
 %D
-%D Lets skip to something quite different. It's common use
-%D to use \type {\everypar} for special purposes. In \CONTEXT\
-%D we use this primitive for locating sidefloats. This means
-%D that when user assignments to \type {\everypar} can interfere
-%D with those of the package. We therefore introduce
-%D \type {\EveryPar}.
+%D Lets skip to something quite different. It's common use to use \type {\everypar}
+%D for special purposes. In \CONTEXT\ we use this primitive for locating sidefloats.
+%D This means that when user assignments to \type {\everypar} can interfere with
+%D those of the package. We therefore introduce \type {\EveryPar}.
 %D
-%D The same goes for \type {\EveryLine}. Because \TEX\ offers
-%D no \type {\everyline} primitive, we have to call for
-%D \type {\everyline} when we are working on a line by line
-%D basis. Just by calling \type {\EveryPar{}} and
-%D \type {\EveryLine{}} we restore the old situation.
+%D The same goes for \type {\EveryLine}. Because \TEX\ offers no \type {\everyline}
+%D primitive, we have to call for \type {\everyline} when we are working on a line
+%D by line basis. Just by calling \type {\EveryPar{}} and \type {\EveryLine{}} we
+%D restore the old situation.
 
 % \dorecurse{2}{
 %     \expanded{\everypar{before \recurselevel\space}}
@@ -3963,21 +3971,33 @@
 
 \installsystemnamespace{extraevery}
 
+% \unexpanded\def\newevery#1#2%
+%   {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere
+%    \ifx#2\relax\else\ifdefined#2\else
+%      \expandafter\newtoks\csname\??extraevery\csstring#1\endcsname
+%      \def#2{\syst_helpers_every#1}%
+%    \fi\fi}
+%
+% \unexpanded\def\syst_helpers_every#1%
+%   {\expandafter\removetoks\expandafter\the\csname\??extraevery\csstring#1\endcsname\from#1%
+%    \expandafter\appendtoks\expandafter\the\csname\??extraevery\csstring#1\endcsname\to  #1%
+%    \csname\??extraevery\csstring#1\endcsname}
+
 \unexpanded\def\newevery#1#2%
   {\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere
    \ifx#2\relax\else\ifdefined#2\else
-     \expandafter\newtoks\csname\??extraevery\strippedcsname#1\endcsname
-     \def#2{\syst_helpers_every#1}%
+     \expandafter\newtoks\csname\??extraevery\csstring#1\endcsname
+     \edef#2{\syst_helpers_every#1\csname\??extraevery\csstring#1\endcsname}%
    \fi\fi}
 
-\unexpanded\def\syst_helpers_every#1%
-  {\expandafter\removetoks\expandafter\the\csname\??extraevery\strippedcsname#1\endcsname\from#1%
-   \expandafter\appendtoks\expandafter\the\csname\??extraevery\strippedcsname#1\endcsname\to  #1%
-   \csname\??extraevery\strippedcsname#1\endcsname}
+\unexpanded\def\syst_helpers_every#1#2%
+  {\removetoks\the#2\from#1%
+   \appendtoks\the#2\to  #1%
+   #2}
 
 %D This one permits definitions like:
 
-\newevery \everypar  \EveryPar % we get a warning which is ok
+\newevery \everypar  \EveryPar  % we get a warning which is ok
 \newevery \everyline \EveryLine
 
 %D and how about:
@@ -4882,7 +4902,7 @@
 \newtoks\t_syst_helpers_scratch
 \let    \m_syst_helpers_scratch\empty
 
-% no longer \def but \let to target toks
+% no longer \def but \let to target toks .. the space gobbling \relax will go
 
 \unexpanded\def\appendtoks     {\syst_helpers_append_toks      \relax}
 \unexpanded\def\prependtoks    {\syst_helpers_prepend_toks     \relax}
@@ -4897,21 +4917,107 @@
 
 \def\syst_helpers_append_toks#1\to#2%
   {\let\m_syst_helpers_scratch#2%
-   \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}\syst_helpers_append_toks_indeed}
+   \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+   \syst_helpers_append_toks_indeed}
 
 \def\syst_helpers_prepend_toks#1\to#2%
   {\let\m_syst_helpers_scratch#2%
-   \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}\syst_helpers_prepend_toks_indeed}
+   \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+   \syst_helpers_prepend_toks_indeed}
 
 \def\syst_helpers_append_toks_once#1\to#2%
   {\let\m_syst_helpers_scratch#2%
    \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
-   \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch\donothing\syst_helpers_append_toks_indeed}
+   \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+     \donothing
+     \syst_helpers_append_toks_indeed}
 
 \def\syst_helpers_prepend_toks_once#1\to#2%
   {\let\m_syst_helpers_scratch#2%
    \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
-   \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch\donothing\syst_helpers_prepend_toks_indeed}
+   \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+     \donothing
+     \syst_helpers_prepend_toks_indeed}
+
+\ifdefined\toksapp
+
+  % \def\syst_helpers_append_toks#1\to#2%
+  %   {\toksapp#2\expandafter{\gobbleoneargument#1}%
+  %    \ifx\dodoglobal\relax\else
+  %      \global#2#2%
+  %    \fi}
+  %
+  % \def\syst_helpers_prepend_toks#1\to#2%
+  %   {\tokspre#2\expandafter{\gobbleoneargument#1}%
+  %    \ifx\dodoglobal\relax\else
+  %       \global#2#2%
+  %    \fi}
+  %
+  % \def\syst_helpers_append_toks_indeed
+  %   {\toksapp\m_syst_helpers_scratch\t_syst_helpers_scratch
+  %    \ifx\dodoglobal\relax\else
+  %      \global\m_syst_helpers_scratch\m_syst_helpers_scratch
+  %    \fi}
+  %
+  % \def\syst_helpers_prepend_toks_indeed
+  %   {\tokspre\m_syst_helpers_scratch\t_syst_helpers_scratch
+  %    \ifx\dodoglobal\relax\else
+  %      \global\m_syst_helpers_scratch\m_syst_helpers_scratch
+  %    \fi}
+  %
+  % \def\syst_helpers_append_toks_once#1\to#2%
+  %   {\let\m_syst_helpers_scratch#2%
+  %    \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+  %    \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+  %      \donothing
+  %      \syst_helpers_append_toks_indeed}
+  %
+  % \def\syst_helpers_prepend_toks_once#1\to#2%
+  %   {\let\m_syst_helpers_scratch#2%
+  %    \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+  %    \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+  %      \donothing
+  %      \syst_helpers_prepend_toks_indeed}
+
+    \unexpanded\def\appendtoks#1\to#2%
+      {\toksapp#2{#1}%
+       \ifx\dodoglobal\relax\else
+         \global#2#2%
+       \fi}
+
+    \unexpanded\def\prependtoks#1\to#2%
+      {\tokspre#2{#1}%
+       \ifx\dodoglobal\relax\else
+          \global#2#2%
+       \fi}
+
+    \def\syst_helpers_append_toks_indeed
+      {\toksapp\m_syst_helpers_scratch\t_syst_helpers_scratch
+       \ifx\dodoglobal\relax\else
+         \global\m_syst_helpers_scratch\m_syst_helpers_scratch
+       \fi}
+
+    \def\syst_helpers_prepend_toks_indeed
+      {\tokspre\m_syst_helpers_scratch\t_syst_helpers_scratch
+       \ifx\dodoglobal\relax\else
+         \global\m_syst_helpers_scratch\m_syst_helpers_scratch
+       \fi}
+
+    \unexpanded\def\appendtoksonce#1\to#2%
+      {\let\m_syst_helpers_scratch#2%
+       \t_syst_helpers_scratch{#1}%
+       \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+         \donothing
+         \syst_helpers_append_toks_indeed}
+
+    \unexpanded\def\prependtoksonce#1\to#2%
+      {\let\m_syst_helpers_scratch#2%
+       \t_syst_helpers_scratch{#1}%
+       \doifelseintoks\t_syst_helpers_scratch\m_syst_helpers_scratch
+         \donothing
+         \syst_helpers_prepend_toks_indeed}
+
+\fi
 
 %D The test macro:
 
@@ -4941,6 +5047,22 @@
 \unexpanded\def\appendetoks #1\to{\normalexpanded{\appendtoks #1}\to}
 \unexpanded\def\prependetoks#1\to{\normalexpanded{\prependtoks#1}\to}
 
+\ifdefined\toksapp
+
+    \def\appendetoks#1\to#2%
+      {\etoksapp#2{#1}%
+       \ifx\dodoglobal\relax\else
+         \global#2#2%
+       \fi}
+
+    \def\prependetoks#1\to#2%
+      {\etokspre#2{#1}%
+       \ifx\dodoglobal\relax\else
+          \global#2#2%
+       \fi}
+
+\fi
+
 %D Hm.
 
 \unexpanded\def\flushtoks#1% nb: can reassing to #1 again, hence the indirectness
@@ -5353,33 +5475,80 @@
 \installsystemnamespace{localpushedmacro}
 \installsystemnamespace{globalpushedmacro}
 
+% \let\m_syst_helpers_push_macro\empty
+%
+% \unexpanded\def\globalpushmacro#1%
+%   {\xdef\m_syst_helpers_push_macro{\string#1}%
+%    \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \else
+%      \expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+%    \fi
+%    \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \plusone
+%    \global\expandafter\let\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
+%
+% \unexpanded\def\globalpopmacro#1%
+%   {\xdef\m_syst_helpers_push_macro{\string#1}%
+%    \global\expandafter\let\expandafter#1\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
+%    \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \minusone}
+%
+% \unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup
+%   {\xdef\m_syst_helpers_push_macro{\string#1}%
+%    \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \else
+%      \expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+%    \fi
+%    \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \plusone
+%    \global\expandafter\let\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
+%
+% \unexpanded\def\localpopmacro#1%
+%   {\xdef\m_syst_helpers_push_macro{\string#1}%
+%    \expandafter\let\expandafter#1\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
+%    \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \minusone }
+%
+% \let\pushmacro\localpushmacro
+% \let\popmacro \localpopmacro
+%
+% slightly faster but more important: less tracing
+
 \let\m_syst_helpers_push_macro\empty
 
+\newcount\c_syst_helpers_pop_count
+
+\def\syst_helpers_push_macro_new_global
+  {\expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+   \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\plusone}
+
+\def\syst_helpers_push_macro_new_local
+  {\expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+   \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\plusone}
+
 \unexpanded\def\globalpushmacro#1%
-  {\xdef\m_syst_helpers_push_macro{\string#1}%
-   \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \else
-     \expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+  {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+   \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+     \global\advance\lastnamedcs\plusone
+   \else
+     \syst_helpers_push_macro_new_global
    \fi
-   \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \plusone
-   \global\expandafter\let\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
-
-\unexpanded\def\globalpopmacro#1%
-  {\xdef\m_syst_helpers_push_macro{\string#1}%
-   \global\expandafter\let\expandafter#1\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
-   \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \minusone}
+   \global\expandafter\let\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
 
 \unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup
-  {\xdef\m_syst_helpers_push_macro{\string#1}%
-   \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \else
-     \expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+  {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+   \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+     \global\advance\lastnamedcs\plusone
+   \else
+     \syst_helpers_push_macro_new_local
    \fi
-   \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \plusone
-   \global\expandafter\let\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
+   \global\expandafter\let\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
+
+\unexpanded\def\globalpopmacro#1%
+  {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+   \c_syst_helpers_pop_count\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
+   \global\advance\lastnamedcs \minusone
+   \expandafter\let\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname}
 
 \unexpanded\def\localpopmacro#1%
-  {\xdef\m_syst_helpers_push_macro{\string#1}%
-   \expandafter\let\expandafter#1\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
-   \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \minusone }
+  {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+   \c_syst_helpers_pop_count\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
+   \global\advance\lastnamedcs \minusone
+   \expandafter\let\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname}
 
 \let\pushmacro\localpushmacro
 \let\popmacro \localpopmacro
@@ -5754,7 +5923,8 @@
 
 \def\executeifdefined#1% #2 / never change this one again
   {\ifcsname#1\endcsname
-     \csname#1\expandafter\expandafter\expandafter\endcsname\expandafter\gobbleoneargument
+   % \csname#1\expandafter\expandafter\expandafter\endcsname\expandafter\gobbleoneargument
+     \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
    \else
      \expandafter\firstofoneargument
    \fi}
@@ -6461,7 +6631,7 @@
 %D macros mood}.
 
 \def\dofilterfromstr#1#2% max n % no need to be fast
-  {\expandafter \expandafter \expandafter \strippedcsname
+  {\expandafter \expandafter \expandafter \csstring
    \ifcase#1\or \ifcase#2\or
      \firstofoneargument     \else
      \gobbleoneargument      \fi
@@ -6492,7 +6662,7 @@
 \def\filterfromvalue#1#2#3% value max n
   {\expandafter\doubleexpandafter\csname         % we use the fact that an
      \expandafter\ifx\csname#1\endcsname\relax   % undefined cs has become \relax
-       \strippedcsname\gobbleoneargument         % which we then gobble here
+       \csstring\gobbleoneargument               % which we then gobble here
      \else
        \dofilterfromstr{#2}{#3}%
      \fi
@@ -6533,7 +6703,8 @@
   {\the\measured}
 
 \def\measured#1%
-  {\dimexpr\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi\relax}
+ %{\dimexpr\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi\relax}
+  {\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax}
 
 % #2 could be omitted, but we want to support spaces
 %
diff --git a/tex/context/base/syst-ini.mkii b/tex/context/base/syst-ini.mkii
index 124a7282a..7ae5f6c81 100644
--- a/tex/context/base/syst-ini.mkii
+++ b/tex/context/base/syst-ini.mkii
@@ -233,7 +233,6 @@
     \edef\pdfpkresolution        {\pdfvariable pkresolution}        \pdfpkresolution         72
     \edef\pdfinclusioncopyfonts  {\pdfvariable inclusioncopyfonts}  \pdfinclusioncopyfonts    0
     \edef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel} \pdfinclusionerrorlevel   0
-    \edef\pdfreplacefont         {\pdfvariable replacefont}         \pdfreplacefont           0
     \edef\pdfgentounicode        {\pdfvariable gentounicode}        \pdfgentounicode          0
     \edef\pdfpagebox             {\pdfvariable pagebox}             \pdfpagebox               0
     \edef\pdfminorversion        {\pdfvariable minorversion}        \pdfminorversion          4
diff --git a/tex/context/base/syst-ini.mkiv b/tex/context/base/syst-ini.mkiv
index b3193a393..be68fced2 100644
--- a/tex/context/base/syst-ini.mkiv
+++ b/tex/context/base/syst-ini.mkiv
@@ -394,7 +394,6 @@
     \edef\pdfpkresolution        {\pdfvariable pkresolution}        \pdfpkresolution         72
     \edef\pdfinclusioncopyfonts  {\pdfvariable inclusioncopyfonts}  \pdfinclusioncopyfonts    0
     \edef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel} \pdfinclusionerrorlevel   0
-    \edef\pdfreplacefont         {\pdfvariable replacefont}         \pdfreplacefont           0
     \edef\pdfgentounicode        {\pdfvariable gentounicode}        \pdfgentounicode          0
     \edef\pdfpagebox             {\pdfvariable pagebox}             \pdfpagebox               0
     \edef\pdfminorversion        {\pdfvariable minorversion}        \pdfminorversion          4
@@ -931,7 +930,9 @@
 %D
 %D Handy for \ETEX-only usage (avoids making \type {\relax}'s:
 
-\def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi}
+% \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi}
+
+\let\begcsname\begincsname
 
 %D Now come a few macros that might be needed in successive loading. We redefine the
 %D \type {\par} primitive pretty soon so that we get the equivalents right.
@@ -956,7 +957,11 @@
 
 \def\space{ }
 \def\empty{}
-\def\null {\hbox{}}
+%def\null {\hbox{}}
+
+\newbox\syst_nullbox \let\nullbox\syst_nullbox
+
+\normalprotected\def\null{\copy\nullbox}
 
 %D The following two might be overloaded later on but some modules need then
 %D earlier. These functionality is reflected in the name and will not change.
diff --git a/tex/context/base/syst-lua.lua b/tex/context/base/syst-lua.lua
index 1657753ce..422f57a00 100644
--- a/tex/context/base/syst-lua.lua
+++ b/tex/context/base/syst-lua.lua
@@ -113,57 +113,6 @@ function commands.doifelsespaces(str)
     end
 end
 
-local s = lpegtsplitat(",")
-local h = { }
-
-local function doifelsecommon(a,b) -- often the same test
-    local ha = h[a]
-    local hb = h[b]
-    if not ha then
-        ha = lpegmatch(s,a)
-        h[a] = ha
-    end
-    if not hb then
-        hb = lpegmatch(s,b)
-        h[b] = hb
-    end
-    local na = #ha
-    local nb = #hb
-    for i=1,na do
-        for j=1,nb do
-            if ha[i] == hb[j] then
-                ctx_firstoftwoarguments()
-                return
-            end
-        end
-    end
-    ctx_secondoftwoarguments()
-end
-
-local function doifelseinset(a,b)
-    local hb = h[b]
-    if not hb then hb = lpegmatch(s,b) h[b] = hb end
-    for i=1,#hb do
-        if a == hb[i] then
-            ctx_firstoftwoarguments()
-            return
-        end
-    end
-    ctx_secondoftwoarguments()
-end
-
-implement {
-    name      = "doifelsecommon",
-    arguments = two_strings,
-    actions   = doifelsecommon
-}
-
-implement {
-    name      = "doifelseinset",
-    arguments = two_strings,
-    actions   = doifelseinset
-}
-
 local pattern = lpeg.patterns.validdimen
 
 function commands.doifelsedimenstring(str)
diff --git a/tex/context/base/tabl-mis.mkiv b/tex/context/base/tabl-mis.mkiv
index 9a0f13853..aafe270de 100644
--- a/tex/context/base/tabl-mis.mkiv
+++ b/tex/context/base/tabl-mis.mkiv
@@ -273,7 +273,7 @@
    \fi
    \paragraphsparameter\c!bottom
    \egroup % (2)
-   \dontleavehmode\hbox{\raise\strutheight\box\scratchbox}%
+   \dontleavehmode\hpack{\raise\strutheight\box\scratchbox}%
    \endgroup}
 
 \def\typo_paragraphs_separator
diff --git a/tex/context/base/tabl-ntb.mkiv b/tex/context/base/tabl-ntb.mkiv
index fcf8ac312..e42903274 100644
--- a/tex/context/base/tabl-ntb.mkiv
+++ b/tex/context/base/tabl-ntb.mkiv
@@ -290,9 +290,14 @@
 \def\tabl_ntb_let_dis#1{\global\expandafter\let\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
 \def\tabl_ntb_let_aut#1{\global\expandafter\let\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
 
-\def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
-\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
-\def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
+%def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
+%def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
+%def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
+%def\tabl_ntb_get_aut#1{\csname  \??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname}
+
+\def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
+\def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
 \def\tabl_ntb_get_aut#1{\csname  \??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname}
 
 \def\tabl_ntb_tag_pattern#1#2{\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2}
@@ -320,7 +325,8 @@
 
 \def\tabl_ntb_let_ref   #1#2{\expandafter\glet\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
 \def\tabl_ntb_set_ref   #1#2{\expandafter\xdef\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
-\def\tabl_ntb_get_ref   #1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi}
+%def\tabl_ntb_get_ref   #1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi}
+\def\tabl_ntb_get_ref   #1#2{\begincsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
 
 \def\tabl_ntb_set_spn     #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone}
 \def\tabl_ntb_spn_doifelse#1{\ifcase0\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname\relax % could be inlined
@@ -404,8 +410,11 @@
 \installcorenamespace{naturaltablesetupthree}
 \installcorenamespace{naturaltablesetuptwo}
 
-\def\tabl_ntb_setup_three[#1]{\csname\??naturaltablesetupthree\ifcsname\??naturaltablesetupthree#1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
-\def\tabl_ntb_setup_two  [#1]{\csname\??naturaltablesetuptwo  \ifcsname\??naturaltablesetuptwo  #1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+%def\tabl_ntb_setup_three[#1]{\csname\??naturaltablesetupthree\ifcsname\??naturaltablesetupthree#1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+%def\tabl_ntb_setup_two  [#1]{\csname\??naturaltablesetuptwo  \ifcsname\??naturaltablesetuptwo  #1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+
+\def\tabl_ntb_setup_three[#1]{\ifcsname\??naturaltablesetupthree#1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_un\fi[#1]}
+\def\tabl_ntb_setup_two  [#1]{\ifcsname\??naturaltablesetuptwo  #1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_ux\fi[#1]}
 
 \setvalue{\??naturaltablesetupthree    \v!row}[#1]{\tabl_ntb_setup_xy  [\c!y]}
 \setvalue{\??naturaltablesetupthree \v!column}[#1]{\tabl_ntb_setup_xy  [\c!x]}
@@ -435,7 +444,7 @@
      \ifcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
        \def\tabl_ntb_parameters_get[##1]%
          {\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[##1,#2]}}%
-       \getvalue{\??naturaltableset\m_tabl_tbl_level:#1}%
+       \csname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
        \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
      \else
        \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
@@ -506,6 +515,90 @@
 
 \let\tabl_ntb_setup_section\relax
 
+% \unexpanded\def\tabl_ntb_setup_cell#1#2% cell over col over row
+%   {\tabl_ntb_setup_section % already forgotten
+%    \edef\m_tabl_ntb_positive_row{\number#1}%
+%    \edef\m_tabl_ntb_positive_col{\number#2}%
+%    \edef\m_tabl_ntb_negative_row{\the\numexpr-\c_tabl_ntb_maximum_row+#1+\minusone\relax}%
+%    \edef\m_tabl_ntb_negative_col{\the\numexpr-\c_tabl_ntb_maximum_col+#2+\minusone\relax}%
+%    % saves tokens (no speed gain)
+%    \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_tbl_level:}%
+%    % each each
+%    \csname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname
+%    \csname\m_tabl_ntb_prefix\c!y\v!each\endcsname
+%    \csname\m_tabl_ntb_prefix\c!x\v!each\endcsname
+%    % odd even
+%    \csname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+%    \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname
+%    \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+%    % row/col number combinations
+%    \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\fi
+%    \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\fi
+%    \naturaltablelocalparameter\c!extras
+%    \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
+%    \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\fi
+%    \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\fi
+%    \naturaltablelocalparameter\c!extras
+%    \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
+%    % first/last combinations
+%    \ifnum\m_tabl_ntb_positive_row=\plusone
+%      \csname\m_tabl_ntb_prefix\c!y\v!first\endcsname
+%      \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\fi
+%    \fi
+%    \ifnum\m_tabl_ntb_positive_col=\plusone
+%      \csname\m_tabl_ntb_prefix\c!x\v!first\endcsname
+%      \ifcsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\fi
+%    \fi
+%    \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+%      \csname\m_tabl_ntb_prefix\c!y\v!last\endcsname
+%      \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\fi
+%    \fi
+%    \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+%      \csname\m_tabl_ntb_prefix\c!x\v!last\endcsname
+%      \ifcsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\fi
+%    \fi
+%    \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+%      \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname
+%    \fi\fi
+%    \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\plusone
+%      \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname
+%    \fi\fi
+%    \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+%      \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname
+%    \fi\fi
+%    \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+%      \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname
+%    \fi\fi
+%    % special case: two rows and last row : two&first and two&last (round corners)
+%    \ifnum\c_tabl_ntb_maximum_row=\plustwo\relax
+%      \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+%        \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname
+%      \fi\fi
+%      \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+%        \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname
+%      \fi\fi
+%    \fi
+%    \ifnum\tabl_ntb_get_col\m_tabl_ntb_positive_row\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax % top span over whole width
+%      \ifnum\m_tabl_ntb_positive_row=\plusone
+%        \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname
+%      \fi
+%      \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+%        \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname
+%      \fi
+%    \fi
+%    % header things
+%    \ifnum#1>\c_tabl_ntb_n_of_hdnx_lines\else
+%      \ifcsname\m_tabl_ntb_prefix\v!header\v!each     \endcsname\csname\m_tabl_ntb_prefix\v!header\v!each     \endcsname\fi
+%      \ifcsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\fi
+%    \fi
+%    % explicit cells
+%    \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\fi
+%    \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\fi
+%    % local
+%    \ifcsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\fi
+%    % done
+%    \relax}
+
 \unexpanded\def\tabl_ntb_setup_cell#1#2% cell over col over row
   {\tabl_ntb_setup_section % already forgotten
    \edef\m_tabl_ntb_positive_row{\number#1}%
@@ -515,78 +608,78 @@
    % saves tokens (no speed gain)
    \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_tbl_level:}%
    % each each
-   \csname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname
-   \csname\m_tabl_ntb_prefix\c!y\v!each\endcsname
-   \csname\m_tabl_ntb_prefix\c!x\v!each\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!y\v!each\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!x\v!each\endcsname
    % odd even
-   \csname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
-   \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname
-   \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
    % row/col number combinations
-   \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\fi
-   \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\fi
+   \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname
    \naturaltablelocalparameter\c!extras
    \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
-   \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\fi
-   \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\fi
+   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname
    \naturaltablelocalparameter\c!extras
    \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
    % first/last combinations
    \ifnum\m_tabl_ntb_positive_row=\plusone
-     \csname\m_tabl_ntb_prefix\c!y\v!first\endcsname
-     \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\fi
+     \begincsname\m_tabl_ntb_prefix\c!y\v!first\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname
    \fi
    \ifnum\m_tabl_ntb_positive_col=\plusone
-     \csname\m_tabl_ntb_prefix\c!x\v!first\endcsname
-     \ifcsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\fi
+     \begincsname\m_tabl_ntb_prefix\c!x\v!first\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname
    \fi
    \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
-     \csname\m_tabl_ntb_prefix\c!y\v!last\endcsname
-     \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\fi
+     \begincsname\m_tabl_ntb_prefix\c!y\v!last\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname
    \fi
    \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
-     \csname\m_tabl_ntb_prefix\c!x\v!last\endcsname
-     \ifcsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\fi
+     \begincsname\m_tabl_ntb_prefix\c!x\v!last\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname
    \fi
    \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
-     \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname
    \fi\fi
    \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\plusone
-     \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname
    \fi\fi
    \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
-     \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname
    \fi\fi
    \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
-     \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname
+     \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname
    \fi\fi
    % special case: two rows and last row : two&first and two&last (round corners)
    \ifnum\c_tabl_ntb_maximum_row=\plustwo\relax
      \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
-       \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname
+       \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname
      \fi\fi
      \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
-       \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname
+       \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname
      \fi\fi
    \fi
    \ifnum\tabl_ntb_get_col\m_tabl_ntb_positive_row\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax % top span over whole width
      \ifnum\m_tabl_ntb_positive_row=\plusone
-       \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname
+       \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname
      \fi
      \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
-       \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname
+       \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname
      \fi
    \fi
    % header things
    \ifnum#1>\c_tabl_ntb_n_of_hdnx_lines\else
-     \ifcsname\m_tabl_ntb_prefix\v!header\v!each     \endcsname\csname\m_tabl_ntb_prefix\v!header\v!each     \endcsname\fi
-     \ifcsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\fi
+     \begincsname\m_tabl_ntb_prefix\v!header\v!each\endcsname
+     \begincsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname
    \fi
    % explicit cells
-   \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\fi
-   \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\fi
+   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname
+   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname
    % local
-   \ifcsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\fi
+   \begincsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname
    % done
    \relax}
 
@@ -872,16 +965,21 @@
    #2%
    \let\tabl_ntb_setup_section\relax}
 
+% \def\tabl_ntb_preset_parameters% each odd|even level / can be sped up but only once per table
+%   {\ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
+%      \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
+%    \fi
+%    \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname % hm
+%      \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname
+%    \fi
+%    \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname % hm
+%      \csname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname
+%    \fi}
+
 \def\tabl_ntb_preset_parameters% each odd|even level / can be sped up but only once per table
-  {\ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
-     \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
-   \fi
-   \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname % hm
-     \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname
-   \fi
-   \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname % hm
-     \csname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname
-   \fi}
+  {\begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
+   \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname
+   \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname}
 
 \unexpanded\def\bTABLE
   {\dosingleempty\tabl_ntb_table}
@@ -1812,10 +1910,23 @@
 %
 % nilling the background makes a run upto 25% faster
 
+% \def\tabl_ntb_cell_process_a_check_span_one
+%   {\ifautosqueezeTBLspan
+%      \edef\p_width{\naturaltablelocalparameter\c!width}%
+%      \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
+%    \else
+%      \donetrue
+%    \fi
+%    \ifdone % brr, 0
+%      \ifnum\scratchcounter>\plusone
+%        \tabl_ntb_set_spn\c_tabl_ntb_col
+%      \fi
+%    \fi}
+
 \def\tabl_ntb_cell_process_a_check_span_one
   {\ifautosqueezeTBLspan
      \edef\p_width{\naturaltablelocalparameter\c!width}%
-     \csname\??naturaltablesqueeze\ifcsname\??naturaltablesqueeze\p_width\endcsname\p_width\fi\endcsname
+     \ifcsname\??naturaltablesqueeze\p_width\endcsname\lastnamedcs\else\donefalse\fi
    \else
      \donetrue
    \fi
@@ -2090,11 +2201,17 @@
 \let\eTDs\relax
 \let\eTRs\relax
 
+% \unexpanded\def\bTDs[#1]#2\eTDs
+%   {\normalexpanded{\bTD[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTD}
+%
+% \unexpanded\def\bTRs[#1]#2\eTRs
+%   {\normalexpanded{\bTR[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTR}
+
 \unexpanded\def\bTDs[#1]#2\eTDs
-  {\normalexpanded{\bTD[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTD}
+  {\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD}
 
 \unexpanded\def\bTRs[#1]#2\eTRs
-  {\normalexpanded{\bTR[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTR}
+  {\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR}
 
 \protect \endinput
 
diff --git a/tex/context/base/tabl-tab.mkiv b/tex/context/base/tabl-tab.mkiv
index 5add1c684..56ebfe0bd 100644
--- a/tex/context/base/tabl-tab.mkiv
+++ b/tex/context/base/tabl-tab.mkiv
@@ -1043,7 +1043,7 @@
    \!thFinishVCS}
 
 \def\!thFinishVCS
-  {\vbox to\zeropoint{\vss\box\zerocount\vss}}
+  {\vpack to\zeropoint{\vss\box\zerocount\vss}}
 
 \def\dotableRaise
   {\def\!thSign{+}%
diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv
index ae4f03825..598d6d25f 100644
--- a/tex/context/base/tabl-tbl.mkiv
+++ b/tex/context/base/tabl-tbl.mkiv
@@ -262,14 +262,21 @@
      \expandafter\tabl_tabulate_initialize_boxes_step
    \fi}
 
+% \def\tabl_tabulate_initialize_box#1% also used elsewhere
+%   {\ifcsname\??tabulatebox\number#1\endcsname
+%      \tabl_tabulate_initialize_box_yes#1%
+%    \else
+%      \tabl_tabulate_initialize_box_nop#1%
+%    \fi}
 \def\tabl_tabulate_initialize_box#1% also used elsewhere
   {\ifcsname\??tabulatebox\number#1\endcsname
-     \tabl_tabulate_initialize_box_yes#1%
+     \tabl_tabulate_initialize_box_yes
    \else
      \tabl_tabulate_initialize_box_nop#1%
    \fi}
 
-\def\tabl_tabulate_initialize_box_yes#1{\global     \setbox\csname\??tabulatebox\number#1\endcsname\emptybox}
+%def\tabl_tabulate_initialize_box_yes#1{\global     \setbox\csname\??tabulatebox\number#1\endcsname\emptybox}
+\def\tabl_tabulate_initialize_box_yes  {\global     \setbox\lastnamedcs\emptybox}
 \def\tabl_tabulate_initialize_box_nop#1{\expandafter\newbox\csname\??tabulatebox\number#1\endcsname}
 
 \tabl_tabulate_initialize_boxes{16} % not really needed
@@ -420,8 +427,97 @@
 
 \let\tabl_tabulate_hook_g\donothing
 
+% \def\tabl_tabulate_set_preamble_step#1#2% only makes sense for many tabulates
+%   {\normalexpanded{\t_tabl_tabulate_preamble{\the\t_tabl_tabulate_preamble
+%         \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+%         \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+%         \tabl_tabulate_check_local_color\constantemptyargument\m_tabl_tabulate_color\constantnumberargument\c_tabl_tabulate_colorspan
+%         \tabl_tabulate_color_side_right
+%         \aligntab
+%         \tabl_tabulate_column_vrule_inject
+%         \tabl_tabulate_color_side_left
+%         \tabl_tabulate_inject_pre_skip{\the\dimexpr\s_tabl_tabulate_pre}% get rid of plus
+%         \alignmark\alignmark
+%         \aligntab
+%         \tabl_tabulate_color_side_both
+%         \global\c_tabl_tabulate_colorspan\zerocount
+%         \global\c_tabl_tabulate_column\constantnumber\c_tabl_tabulate_columns
+%         \tabl_tabulate_hook_g
+%         \tabl_tabulate_setups_check % unexpandable
+%         \tabl_tabulate_hook_check   % unexpandable
+%         \ifzeropt\d_tabl_tabulate_width
+%             \ifcase\c_tabl_tabulate_modus\else
+%                \settrue\c_tabl_tabulate_automode
+%             \fi
+%         \else
+%             \ifcase\c_tabl_tabulate_modus
+%                 \hbox to
+%             \else
+%                 \hsize
+%             \fi
+%             \the\d_tabl_tabulate_width
+%         \fi
+%         \bgroup
+%             \tabl_tabulate_bbskip
+%             \bgroup % we cannot combine the if because a cell may have only one ##
+%                 \tabl_tabulate_hook_b
+%                 \c_tabl_tabulate_align\constantnumber\c_tabl_tabulate_align % needed in tag passing
+%                 \ifx\m_tabl_tabulate_alignment\empty \else
+%                     \spac_align_use_now{\m_tabl_tabulate_alignment}%
+%                 \fi
+%                 \noexpand\dostarttagged\noexpand\t!tabulatecell\noexpand\empty
+%                 \noexpand\dotagtabulatecell
+%                 \noexpand#1%
+%                 \ifconditional\c_tabl_tabulate_reshape
+%                     \tabl_tabulate_shaped_par_begin
+%                 \fi
+%                 \dotagtabulatesignal  % empty cells .. todo (can be removed as soon as build)
+%                 \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+%                     \the\t_tabl_tabulate_bmath % maybe later? can interfere with char 0
+%                     \the\t_tabl_tabulate_font
+%                     \the\t_tabl_tabulate_settings
+%                     \the\t_tabl_tabulate_before
+%                     \ifx\m_tabl_tabulate_text_color\empty
+%                         \expandafter\gobbleoneargument
+%                     \else
+%                         \expandafter\dofastcoloractivation
+%                     \fi\m_tabl_tabulate_text_color
+%                 \noexpand\fi
+%                 % grouping needs to be outside macros (or expandable), nice test
+%                 % example \NC \string \aligntab \NC which will fail otherwise (mk)
+%                 \bgroup
+%                 \tabl_tabulate_entry_before
+%                 \alignmark\alignmark
+%                 \tabl_tabulate_entry_after
+%                 \egroup
+%                 \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+%                     \the\t_tabl_tabulate_after
+%                     \the\t_tabl_tabulate_emath
+%                 \noexpand\fi
+%                 \ifconditional\c_tabl_tabulate_reshape
+%                     \tabl_tabulate_shaped_par_end
+%                 \fi
+%                 \noexpand#2%
+%                 \tabl_tabulate_hook_e
+%             \egroup
+%         \egroup
+%         \aligntab
+%         \noexpand\dostoptagged
+%         \tabl_tabulate_inject_post_skip{\the\dimexpr\s_tabl_tabulate_post}% get rid of plus
+%         \alignmark\alignmark
+%    }}%
+%    \t_tabl_tabulate_dummy\expandafter{\the\t_tabl_tabulate_dummy\NC}%
+%    \s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\relax
+%    \ifnum\c_tabl_tabulate_columns<\numexpr\c_tabl_tabulate_nofcolumns-\plusone\relax
+%      \s_tabl_tabulate_post\s_tabl_tabulate_pre
+%    \else
+%      \s_tabl_tabulate_post\zeropoint
+%    \fi
+%   %\let\gettabulateexit\dogettabulateexit % still needed ?
+%    \d_tabl_tabulate_width\zeropoint}
+
 \def\tabl_tabulate_set_preamble_step#1#2% only makes sense for many tabulates
-  {\normalexpanded{\t_tabl_tabulate_preamble{\the\t_tabl_tabulate_preamble
+  {\etoksapp\t_tabl_tabulate_preamble{%
         \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
         \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
         \tabl_tabulate_check_local_color\constantemptyargument\m_tabl_tabulate_color\constantnumberargument\c_tabl_tabulate_colorspan
@@ -429,7 +525,6 @@
         \aligntab
         \tabl_tabulate_column_vrule_inject
         \tabl_tabulate_color_side_left
-%         \tabl_tabulate_inject_pre_skip{\the\s_tabl_tabulate_pre}%
         \tabl_tabulate_inject_pre_skip{\the\dimexpr\s_tabl_tabulate_pre}% get rid of plus
         \alignmark\alignmark
         \aligntab
@@ -499,8 +594,8 @@
         \noexpand\dostoptagged
         \tabl_tabulate_inject_post_skip{\the\dimexpr\s_tabl_tabulate_post}% get rid of plus
         \alignmark\alignmark
-   }}%
-   \t_tabl_tabulate_dummy\expandafter{\the\t_tabl_tabulate_dummy\NC}%
+   }%
+   \toksapp\t_tabl_tabulate_dummy{\NC}%
    \s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\relax
    \ifnum\c_tabl_tabulate_columns<\numexpr\c_tabl_tabulate_nofcolumns-\plusone\relax
      \s_tabl_tabulate_post\s_tabl_tabulate_pre
@@ -586,7 +681,8 @@
 
 \def\tabl_tabulate_set_preamble#1%
   {\ifcsname\??tabulatepreamble\string#1\endcsname
-     \expandafter\tabl_tabulate_set_preamble_yes
+    %\expandafter\tabl_tabulate_set_preamble_yes
+     \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
    \else
      \expandafter\tabl_tabulate_set_preamble_nop
    \fi{#1}}
@@ -790,6 +886,21 @@
      \tabl_tabulate_set_width_simple
    \fi}
 
+% \def\tabl_tabulate_set_last_entry#1% rulespec
+%   {\global\let\m_tabl_tabulate_vrule_color\empty
+%    \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
+%    \ifx\currenttabulationtrulespec\empty
+%      \global\d_tabl_tabulate_vrulethickness\zeropoint
+%    \else
+%      \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+%      \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
+%    \fi
+%    \normalexpanded{\t_tabl_tabulate_preamble{\the\t_tabl_tabulate_preamble
+%      \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+%      \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+%      \tabl_tabulate_column_vrule_inject}}%
+%    }
+
 \def\tabl_tabulate_set_last_entry#1% rulespec
   {\global\let\m_tabl_tabulate_vrule_color\empty
    \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
@@ -799,10 +910,10 @@
      \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
      \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
    \fi
-   \normalexpanded{\t_tabl_tabulate_preamble{\the\t_tabl_tabulate_preamble
+   \etoksapp\t_tabl_tabulate_preamble{%
      \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
      \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
-     \tabl_tabulate_column_vrule_inject}}%
+     \tabl_tabulate_column_vrule_inject}%
    }
 
 \let\settabulateentry    \tabl_tabulate_set_entry      % used at the lua end
@@ -830,7 +941,7 @@
    \fi}
 
 \def\tabl_tabulate_check_whitespace
-  {\setbox\scratchbox\vbox
+  {\setbox\scratchbox\vpack
      {\splitdiscards
       \unskip
       \ifdim\lastskip>\d_tabl_tabulate_splitoff_betweenskip
@@ -853,7 +964,7 @@
      \tabl_tabulate_check_whitespace
    \fi
    \tabl_tabulate_color_repeat % needs to end up in a cell
-   \setbox\b_tabl_tabulate\hbox to \wd\b_tabl_tabulate
+   \setbox\b_tabl_tabulate\hpack to \wd\b_tabl_tabulate
      {\hss\tabl_tabulate_hook_yes{\box\b_tabl_tabulate}\hss}%
    \tabl_tabulate_normalize_splitline
    \tabl_tabulate_check_linenumbers
@@ -1054,7 +1165,8 @@
 
 \def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header
   {\ifcsname\??tabulatehead\currenttabulation\endcsname
-     \expandafter\ifx\csname\??tabulatehead\currenttabulation\endcsname\empty
+    %\expandafter\ifx\csname\??tabulatehead\currenttabulation\endcsname\empty
+     \expandafter\ifx\lastnamedcs\empty
        \let\tabl_tabulate_insert_head\empty
      \else
        \let\tabl_tabulate_insert_head\tabl_tabulate_insert_head_content
@@ -1064,6 +1176,7 @@
    \fi
    \ifcsname\??tabulatefoot\currenttabulation\endcsname
      \expandafter\ifx\csname\??tabulatefoot\currenttabulation\endcsname\empty
+    %\expandafter\ifx\lastnamedcs\empty
        \let\tabl_tabulate_insert_foot\empty
      \else
        \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_head_content
@@ -1210,6 +1323,9 @@
    \fi
    \bgroup % settings
    %
+   \t_tabl_tabulate_preamble\emptytoks
+   \t_tabl_tabulate_dummy   \emptytoks
+   %
    \resetcharacteralign
    %
    \edef\p_distance     {\tabulationparameter\c!distance}%
@@ -1426,7 +1542,8 @@
 
 \def\tabl_tabulate_column_rule_separator_step#1%
   {\ifcsname\??tabulateseparator#1\endcsname
-     \csname\??tabulateseparator#1\endcsname
+    %\csname\??tabulateseparator#1\endcsname
+     \lastnamedcs
    \else
      \s_tabl_tabulate_separator#1\relax
    \fi}
@@ -1535,16 +1652,15 @@
    \setxvalue{\??tabulatecolor\the\c_tabl_tabulate_column}{#1}%
   %\attribute\alignbackgroundattribute\plusone
   %\dousecolorparameter{#1}\char\zerocount\strut % hack
-   \hbox \thealignbackgroundcolorattr{#1}{}%
+   \hbox \thealignbackgroundcolorattr{#1}{}% pack ?
    \endgroup}
 
 \def\tabl_tabulate_color_repeat_second % for split off lines
   {\begingroup
    \scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly !
    \ifcsname\??tabulatecolor\the\scratchcounter\endcsname
-    %\expandafter\dousecolorparameter\csname\??tabulatecolor\the\scratchcounter\endcsname
-    %\strut\char\zerocount % hack
-     \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}%
+    %\hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ?
+     \hbox \thealignbackgroundcolorattr{\lastnamedcs}{}% pack ?
    \fi
    \endgroup}
 
@@ -1617,7 +1733,7 @@
 
 \def\tabl_tabulate_flush_indent
   {\ifnum\c_tabl_tabulate_column=\zerocount
-     \hbox to \d_tabl_tabulate_indent
+     \hbox to \d_tabl_tabulate_indent % pack ?
        {% we now have a local hsize, and since we want to
         % register positional info (i.e. real hsizes) we
         % need to reconstitute the original hsize
@@ -2039,6 +2155,166 @@
   {\setlocalhsize
    \hsize\localhsize}
 
+% \def\tabl_tabulate_process
+%   {\c_tabl_tabulate_pass\plusone
+%    \tabl_tabulate_check_full_content
+%    \edef\v_tabl_tabulate_align{\executeifdefined{\??tabulatealigning\p_align}0}%
+%    \s_tabl_tabulate_first.5\d_tabl_tabulate_unit
+%    \s_tabl_tabulate_last\s_tabl_tabulate_first
+%    \s_tabl_tabulate_pre\zeropoint
+%    \s_tabl_tabulate_post\s_tabl_tabulate_first % was: \zeropoint
+%    \global\c_tabl_tabulate_columns\zerocount
+%    \global\c_tabl_tabulate_nofauto\zerocount
+%    \global\c_tabl_tabulate_noflines\zerocount
+%    \c_tabl_tabulate_totalnoflines\zerocount
+%    \c_tabl_tabulate_minusnoflines\zerocount
+%    \global\d_tabl_tabulate_width_p\zeropoint
+%    \global\d_tabl_tabulate_width_w\zeropoint
+%    \global\setfalse\c_tabl_tabulate_equal
+%    \tabl_tabulate_pheight_reset
+%    \tabskip\zeropoint
+%    \ifinsidesplitfloat
+%      \donetrue
+%    \else\ifinsidefloat
+%      \donefalse
+%    \else
+%      \donetrue
+%    \fi\fi
+%    \ifdone
+%      \global\c_tabl_tabulate_repeathead\executeifdefined{\??tabulateheader\tabulationparameter\c!header}\zerocount
+%    \else
+%      \global\c_tabl_tabulate_repeathead\zerocount
+%    \fi
+%    %
+%    \the\t_tabl_tabulate_initializers_first % collect more here
+%    %
+%    \glet\tabl_tabulate_flush_collected\empty
+%    \ifdim\d_tabl_tabulate_margin>\zeropoint
+%      \t_tabl_tabulate_preamble
+%        {\aligntab
+%         \tabl_tabulate_flush_indent
+% % \global\advance\c_tabl_tabulate_noflines\plusone
+%         \strut
+%         \alignmark\alignmark
+%         \tabskip\d_tabl_tabulate_margin
+%         \strut
+%         \aligntab
+%         \alignmark\alignmark
+%         \tabskip\zeropoint}%
+%    \else
+%      \t_tabl_tabulate_preamble
+%        {\aligntab
+%         \tabl_tabulate_flush_indent
+% % \global\advance\c_tabl_tabulate_noflines\plusone
+%         \strut
+%         \alignmark\alignmark
+%         \aligntab
+%         \alignmark\alignmark
+%         \tabskip\zeropoint}%
+%    \fi
+%    \d_tabl_tabulate_width\zeropoint
+%    % these counters are set at the lua end
+%    \c_tabl_tabulate_nofcolumns         \zerocount
+%    \c_tabl_tabulate_has_rule_spec_first\zerocount
+%    \c_tabl_tabulate_has_rule_spec_last \zerocount
+%    \clf_presettabulate{\detokenizedtabulationparameter\c!format}%
+%    %
+%  % \edef\totaltabulatecolumns{\the\numexpr3*\c_tabl_tabulate_columns+\plusfour}%
+%    \d_tabl_tabulate_width\zeropoint
+%    \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
+%    \t_tabl_tabulate_preamble\expandafter{\the\t_tabl_tabulate_preamble
+%      \aligntab\alignmark\alignmark
+%      \global\advance\c_tabl_tabulate_column\plusone % maybe just set it already
+%    }%
+%    \t_tabl_tabulate_dummy\expandafter{\the\t_tabl_tabulate_dummy
+%      \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
+%    }%
+%    \global\c_tabl_tabulate_column\zerocount
+%    \tabl_tabulate_pheight_reset
+%    \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+%    \ifx\p_indenting\v!no
+%      \forgetparindent
+%    \fi
+%    \ifinsidefloat
+%      \d_tabl_tabulate_indent\zeropoint
+%    \else
+%      \tabl_tabulate_set_local_hsize
+%    \fi
+%    \dontcomplain
+%    \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved
+%    \everypar\everytabulatepar
+%    \setbox0\vbox % outside \if because of line counting
+%      {\notesenabledfalse
+%       \d_tabl_tabulate_indent\zeropoint
+%       \settrialtypesetting % very important
+%       \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}%
+%    \ifnum\c_tabl_tabulate_nofauto>\zerocount
+%      % so, even if the natural size is larger, in the final run, we force the calculated width
+%      \d_tabl_tabulate_width\dimexpr\hsize-\wd0-\d_tabl_tabulate_width_p-\d_tabl_tabulate_width_w\relax
+%      \ifnum\c_tabl_tabulate_nofauto>\zerocount
+%        \divide\d_tabl_tabulate_width \c_tabl_tabulate_nofauto\relax
+%      \fi
+%    \fi
+%    \ifconditional\c_tabl_tabulate_split
+%      \splittopskip\strutht
+%      \glet\tabl_tabulate_flush_collected_indeed\empty
+%      \glet\tabl_tabulate_flush_collected\tabl_tabulate_flush_second
+%    \fi
+%    \c_tabl_tabulate_totalnoflines\c_tabl_tabulate_noflines
+%    \c_tabl_tabulate_minusnoflines\numexpr\c_tabl_tabulate_noflines+\minusone\relax
+%    \global\c_tabl_tabulate_noflines\zerocount
+%    %
+%    \c_tabl_tabulate_pass\plustwo % final pass
+%    \the\t_tabl_tabulate_initializers_second % collect more here
+%    %
+%    \ifx\p_line\v!line
+%      \let\HL\HR
+%      \let\tabulateautoline\tabulateautorule
+%      \let\tabulateline\tabulaterule
+%    \fi
+%    %
+%    \ifcase\c_tabl_tabulate_repeathead
+%      \ifinsidesplitfloat
+%         \global\setbox\b_tabl_tabulate\vbox \bgroup
+%       \else
+%         \startframedcontent[\tabulationparameter\c!frame]%
+%       \fi
+%    \else
+%      \global\setbox\b_tabl_tabulate\vbox \bgroup
+%    \fi
+%    %
+%    \dostarttaggedchained\t!tabulate\empty\??tabulation
+%    \dostarttagged\t!tabulaterow\empty
+%    \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
+%    \everycr\expandafter{\the\everycr\dostoptagged\dostarttagged\t!tabulaterow\empty}%
+%    \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
+%    \dostoptagged
+%    \dostoptagged
+%    \ifhmode\par\prevdepth\strutdp\fi % nog eens beter, temporary hack
+%    \ifx\p_distance\v!grid
+%      \vskip-\strutdp % experimental tm-prikkels
+%    \fi
+%    %
+%    \ifcase\c_tabl_tabulate_repeathead
+%      \ifinsidesplitfloat
+%        \egroup % box
+%        \egroup % settings
+%        \tabl_split_box\b_tabl_tabulate
+%      \else
+%        \stopframedcontent
+%        \egroup
+%      \fi
+%    \else
+%      \egroup % box
+%      \egroup % settings
+%      \tabl_split_box\b_tabl_tabulate
+%    \fi
+%    %
+%    \ifinsidefloat \else
+%      \tabulationparameter\c!after
+%    \fi
+%    \egroup} % whole thing
+
 \def\tabl_tabulate_process
   {\c_tabl_tabulate_pass\plusone
    \tabl_tabulate_check_full_content
@@ -2106,11 +2382,11 @@
  % \edef\totaltabulatecolumns{\the\numexpr3*\c_tabl_tabulate_columns+\plusfour}%
    \d_tabl_tabulate_width\zeropoint
    \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
-   \t_tabl_tabulate_preamble\expandafter{\the\t_tabl_tabulate_preamble
+   \toksapp\t_tabl_tabulate_preamble{%
      \aligntab\alignmark\alignmark
      \global\advance\c_tabl_tabulate_column\plusone % maybe just set it already
    }%
-   \t_tabl_tabulate_dummy\expandafter{\the\t_tabl_tabulate_dummy
+   \toksapp\t_tabl_tabulate_dummy{%
      \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
    }%
    \global\c_tabl_tabulate_column\zerocount
@@ -2171,6 +2447,7 @@
    \dostarttagged\t!tabulaterow\empty
    \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
    \everycr\expandafter{\the\everycr\dostoptagged\dostarttagged\t!tabulaterow\empty}%
+%    \toksapp\everycr{\dostoptagged\dostarttagged\t!tabulaterow\empty}%
    \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
    \dostoptagged
    \dostoptagged
diff --git a/tex/context/base/tabl-tsp.mkiv b/tex/context/base/tabl-tsp.mkiv
index eb50eb401..e0c3b9b74 100644
--- a/tex/context/base/tabl-tsp.mkiv
+++ b/tex/context/base/tabl-tsp.mkiv
@@ -305,7 +305,7 @@
    \splittopskip\zeropoint
    \doloop % inner loop
      {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight
-      \setbox\scratchbox\vbox
+      \setbox\scratchbox\vbox % \vpack
         {\unvbox\scratchbox
          \setbox\scratchbox\vbox
            {\splitdiscards
diff --git a/tex/context/base/toks-ini.lua b/tex/context/base/toks-ini.lua
index a6c465d50..b66c24c16 100644
--- a/tex/context/base/toks-ini.lua
+++ b/tex/context/base/toks-ini.lua
@@ -9,6 +9,7 @@ tokens = tokens or { }
 
 local tokens     = tokens
 local newtoken   = newtoken or token
+local tonumber   = tonumber
 local tostring   = tostring
 local utfchar    = utf.char
 local char       = string.char
@@ -69,13 +70,13 @@ local get_next     = newtoken.get_next
 
 local set_macro    = newtoken.set_macro
 
-set_macro = function(k,v,g)
-    if g == "global" then
-        context.setgvalue(k,v or '')
-    else
-        context.setvalue(k,v or '')
-    end
-end
+-- set_macro = function(k,v,g)
+--     if g == "global" then
+--         context.setgvalue(k,v or '')
+--     else
+--         context.setvalue(k,v or '')
+--     end
+-- end
 
 local bits = {
     escape      = 2^ 0,
diff --git a/tex/context/base/trac-inf.lua b/tex/context/base/trac-inf.lua
index 5497e54eb..f4c4e5557 100644
--- a/tex/context/base/trac-inf.lua
+++ b/tex/context/base/trac-inf.lua
@@ -145,13 +145,13 @@ function statistics.show()
         -- so far
      -- collectgarbage("collect")
         register("lua properties",function()
-            local list = status.list()
-            local hashchar = tonumber(list.luatex_hashchars)
+            local hashchar = tonumber(status.luatex_hashchars)
+            local hashtype = status.luatex_hashtype
             local mask = lua.mask or "ascii"
             return format("engine: %s, used memory: %s, hash type: %s, hash chars: min(%s,40), symbol mask: %s (%s)",
                 jit and "luajit" or "lua",
                 statistics.memused(),
-                list.luatex_hashtype or "default",
+                hashtype or "default",
                 hashchar and 2^hashchar or "unknown",
                 mask,
                 mask == "utf" and "τεχ" or "tex")
diff --git a/tex/context/base/trac-log.lua b/tex/context/base/trac-log.lua
index ba8ee8df0..5745460cc 100644
--- a/tex/context/base/trac-log.lua
+++ b/tex/context/base/trac-log.lua
@@ -110,6 +110,10 @@ local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog,
 
 if tex and (tex.jobname or tex.formatname) then
 
+    if texio.setescape then
+        texio.setescape(0)
+    end
+
     local function useluawrites()
 
         -- quick hack, awaiting speedup in engine (8 -> 6.4 sec for --make with console2)
diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua
index 25ec59886..b88981fdd 100644
--- a/tex/context/base/trac-vis.lua
+++ b/tex/context/base/trac-vis.lua
@@ -85,6 +85,7 @@ local getlist             = nuts.getlist
 local getleader           = nuts.getleader
 local getnext             = nuts.getnext
 local getprev             = nuts.getprev
+local getboth             = nuts.getboth
 local getdisc             = nuts.getdisc
 
 local hpack_nodes         = nuts.hpack
@@ -100,8 +101,7 @@ local linked_nodes        = nuts.linked
 
 local effectiveglue       = nuts.effective_glue
 
-local fast_hpack          = nuts.fasthpack
-local fast_hpack_string   = nuts.typesetters.fast_hpack
+local hpack_string        = nuts.typesetters.tohpack
 
 local texgetattribute     = tex.getattribute
 local texsetattribute     = tex.setattribute
@@ -160,38 +160,37 @@ local trace_italic
 local report_visualize = logs.reporter("visualize")
 
 local modes = {
-    hbox       =    1,
-    vbox       =    2,
-    vtop       =    4,
-    kern       =    8,
-    glue       =   16,
-    penalty    =   32,
-    fontkern   =   64,
-    strut      =  128,
-    whatsit    =  256,
-    glyph      =  512,
-    simple     = 1024,
-    simplehbox = 1024 + 1,
-    simplevbox = 1024 + 2,
-    simplevtop = 1024 + 4,
-    user       = 2048,
-    math       = 4096,
-    italic     = 8192,
+    hbox       =     1,
+    vbox       =     2,
+    vtop       =     4,
+    kern       =     8,
+    glue       =    16,
+    penalty    =    32,
+    fontkern   =    64,
+    strut      =   128,
+    whatsit    =   256,
+    glyph      =   512,
+    simple     =  1024,
+    simplehbox =  1024 + 1,
+    simplevbox =  1024 + 2,
+    simplevtop =  1024 + 4,
+    user       =  2048,
+    math       =  4096,
+    italic     =  8192,
+    origin     = 16384,
 }
 
-local modes_makeup = { "hbox", "vbox", "kern", "glue", "penalty" }
-local modes_boxes  = { "hbox", "vbox"  }
-local modes_all    = { "hbox", "vbox", "kern", "glue", "penalty", "fontkern", "whatsit", "glyph", "user", "math" }
-
 local usedfont, exheight, emwidth
-local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic
+local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin
 
 local enabled = false
 local layers  = { }
 
-local preset_boxes  = modes.hbox + modes.vbox
-local preset_makeup = preset_boxes + modes.kern + modes.glue + modes.penalty
-local preset_all    = preset_makeup + modes.fontkern + modes.whatsit + modes.glyph + modes.user + modes.math
+local preset_boxes  = modes.hbox + modes.vbox + modes.origin
+local preset_makeup = preset_boxes
+                    + modes.kern + modes.glue + modes.penalty
+local preset_all    = preset_makeup
+                    + modes.fontkern + modes.whatsit + modes.glyph + modes.user + modes.math
 
 function visualizers.setfont(id)
     usedfont = id or current_font()
@@ -230,6 +229,7 @@ local function enable()
     l_user     = layers.user
     l_math     = layers.math
     l_italic   = layers.italic
+    l_origin   = layers.origin
     nodes.tasks.enableaction("shipouts","nodes.visualizers.handler")
     report_visualize("enabled")
     enabled = true
@@ -325,6 +325,7 @@ local c_glyph      = "trace:o"
 local c_ligature   = "trace:s"
 local c_white      = "trace:w"
 local c_math       = "trace:r"
+local c_origin     = "trace:o"
 
 local c_positive_d = "trace:db"
 local c_negative_d = "trace:dr"
@@ -337,9 +338,10 @@ local c_glyph_d    = "trace:do"
 local c_ligature_d = "trace:ds"
 local c_white_d    = "trace:dw"
 local c_math_d     = "trace:dr"
+local c_origin_d   = "trace:do"
 
 local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed
-    local text = fast_hpack_string(str,usedfont)
+    local text = hpack_string(str,usedfont)
     local size = getfield(text,"width")
     local rule = new_rule(size,2*exheight,exheight/2)
     local kern = new_kern(-size)
@@ -351,17 +353,14 @@ local function sometext(str,layer,color,textcolor,lap) -- we can just paste verb
     end
     local info = linked_nodes(rule,kern,text)
     setlisttransparency(info,c_zero)
-    info = fast_hpack(info)
+    info = new_hlist(info)
     local width = getfield(info,"width")
     if lap then
-        info = fast_hpack(linked_nodes(new_kern(-width),info))
+        info = new_hlist(linked_nodes(new_kern(-width),info))
     end
     if layer then
         setattr(info,a_layer,layer)
     end
-    setfield(info,"width",0)
-    setfield(info,"height",0)
-    setfield(info,"depth",0)
     return info, width
 end
 
@@ -373,7 +372,7 @@ local function fontkern(head,current)
     if info then
         -- print("hit fontkern")
     else
-        local text = fast_hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
+        local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
         local rule = new_rule(emwidth/fraction,6*exheight,2*exheight)
         local list = getlist(text)
         if kern > 0 then
@@ -386,11 +385,8 @@ local function fontkern(head,current)
         setlisttransparency(list,c_text_d)
         settransparency(rule,c_text_d)
         setfield(text,"shift",-5 * exheight)
-        info = fast_hpack(linked_nodes(rule,text))
+        info = new_hlist(linked_nodes(rule,text))
         setattr(info,a_layer,l_fontkern)
-        setfield(info,"width",0)
-        setfield(info,"height",0)
-        setfield(info,"depth",0)
         f_cache[kern] = info
     end
     head = insert_node_before(head,current,copy_list(info))
@@ -479,7 +475,17 @@ end
 
 local b_cache = { }
 
-local function ruledbox(head,current,vertical,layer,what,simple,previous)
+local o_cache = table.setmetatableindex(function(t,size)
+    local rule = new_rule(2*size,size,size)
+    origin = hpack_nodes(rule)
+    setcolor(rule,c_origin_d)
+    settransparency(rule,c_origin_d)
+    setattr(rule,a_layer,l_origin)
+    t[size] = origin
+    return origin
+end)
+
+local function ruledbox(head,current,vertical,layer,what,simple,previous,trace_origin,parent)
     local wd = getfield(current,"width")
     if wd ~= 0 then
         local ht = getfield(current,"height")
@@ -490,6 +496,7 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous)
      -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3
         setboth(current)
         local linewidth = emwidth/fraction
+        local size      = 2*linewidth
         local baseline, baseskip
         if dp ~= 0 and ht ~= 0 then
             if wd > 20*linewidth then
@@ -497,43 +504,37 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous)
                 if not baseline then
                     -- due to an optimized leader color/transparency we need to set the glue node in order
                     -- to trigger this mechanism
-                    local leader = linked_nodes(new_glue(2*linewidth),new_rule(6*linewidth,linewidth,0),new_glue(2*linewidth))
-                 -- setlisttransparency(leader,c_text)
-                    leader = fast_hpack(leader)
-                 -- setlisttransparency(leader,c_text)
+                    local leader = linked_nodes(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size))
+                    leader = hpack_nodes(leader)
                     baseline = new_glue(0)
                     setfield(baseline,"leader",leader)
                     setfield(baseline,"subtype",cleaders_code)
-                    local spec = getfield(baseline,"spec")
-                    setfield(spec,"stretch",65536)
-                    setfield(spec,"stretch_order",2)
+                    setfield(baseline,"stretch",65536)
+                    setfield(baseline,"stretch_order",2)
                     setlisttransparency(baseline,c_text)
                     b_cache.baseline = baseline
                 end
                 baseline = copy_list(baseline)
-                baseline = fast_hpack(baseline,wd-2*linewidth)
-                -- or new hpack node, set head and also:
+                baseline = hpack_nodes(baseline,wd-size)
+                -- or new_hlist, set head and also:
                 -- baseline.width = wd
                 -- baseline.glue_set = wd/65536
                 -- baseline.glue_order = 2
                 -- baseline.glue_sign = 1
                 baseskip = new_kern(-wd+linewidth)
             else
-                baseline = new_rule(wd-2*linewidth,linewidth,0)
-                baseskip = new_kern(-wd+2*linewidth)
+                baseline = new_rule(wd-size,linewidth,0)
+                baseskip = new_kern(-wd+size)
             end
         end
         local this
         if not simple then
             this = b_cache[what]
             if not this then
-                local text = fast_hpack_string(what,usedfont)
+                local text = hpack_string(what,usedfont)
                 this = linked_nodes(new_kern(-getfield(text,"width")),text)
                 setlisttransparency(this,c_text)
-                this = fast_hpack(this)
-                setfield(this,"width",0)
-                setfield(this,"height",0)
-                setfield(this,"depth",0)
+                this = new_hlist(this)
                 b_cache[what] = this
             end
         end
@@ -541,23 +542,68 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous)
         local info = linked_nodes(
             this and copy_list(this) or nil,
             new_rule(linewidth,ht,dp),
-            new_rule(wd-2*linewidth,-dp+linewidth,dp),
+            new_rule(wd-size,-dp+linewidth,dp),
             new_rule(linewidth,ht,dp),
             new_kern(-wd+linewidth),
-            new_rule(wd-2*linewidth,ht,-ht+linewidth)
+            new_rule(wd-size,ht,-ht+linewidth)
         )
         if baseskip then
             info = linked_nodes(info,baseskip,baseline) -- could be in previous linked
         end
         setlisttransparency(info,c_text)
-        info = fast_hpack(info)
-        setfield(info,"width",0)
-        setfield(info,"height",0)
-        setfield(info,"depth",0)
+        info = new_hlist(info)
+        --
         setattr(info,a_layer,layer)
-        local info = linked_nodes(current,new_kern(-wd),info)
-        setfield(current,"shift",0)
-        info = (vertical and new_vlist or new_hlist)(info,wd,ht,dp,shift)
+        if vertical then
+            if shift == 0 then
+                info = linked_nodes(current,info)
+            elseif trace_origin then
+                local size   = 2*size
+                local origin = o_cache[size]
+                origin = copy_list(origin)
+                if getid(parent) == vlist_code then
+                    setfield(origin,"shift",-shift)
+                    info = linked_nodes(current,new_kern(-size),origin,new_kern(-size),info)
+                else
+                    -- todo .. i need an example
+                    info = linked_nodes(current,info)
+                end
+                setfield(current,"shift",0)
+            else
+                info = linked_nodes(current,info)
+                setfield(current,"shift",0)
+            end
+            info = new_vlist(info,wd,ht,dp,shift)
+        else
+            if shift == 0 then
+                info = linked_nodes(current,new_kern(-wd),info)
+            elseif trace_origin then
+                local size   = 2*size
+                local origin = o_cache[size]
+                origin = copy_list(origin)
+                if getid(parent) == vlist_code then
+                    info = linked_nodes(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info)
+                else
+                    setfield(origin,"shift",-shift)
+                    info = linked_nodes(current,new_kern(-wd-size),origin,new_kern(-size),info)
+                end
+                setfield(current,"shift",0)
+            else
+                info = linked_nodes(current,new_kern(-wd),info)
+                setfield(current,"shift",0)
+            end
+            info = new_hlist(info,wd,ht,dp,shift)
+        end
+
+-- how about dir, so maybe just copy the node
+--
+-- local l = getlist(current)
+-- setfield(current,"list",nil)
+-- local c = copy_node(current)
+-- setfield(current,"list",l)
+-- setfield(c,"list",info)
+-- info = c
+
         if next then
             setlink(info,next)
         end
@@ -579,6 +625,13 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous)
     end
 end
 
+local bpfactor =  number.dimenfactors.bp
+
+callback.register("process_rule",function(n,h,v)
+    local p = string.formatters["0 0 %0.6F %0.6F re f"](h*bpfactor,v*bpfactor)
+    pdf.print("direct",p)
+end)
+
 local function ruledglyph(head,current,previous)
     local wd = getfield(current,"width")
  -- local wd = chardata[getfont(current)][getchar(current)].width
@@ -605,21 +658,27 @@ local function ruledglyph(head,current,previous)
             new_kern(-wd+doublelinewidth),
             baseline
         )
+
+-- local rule = new_rule(wd,ht,dp)
+-- setfield(rule,"subtype",4) -- todo
+-- local info = linked_nodes(
+--     rule,
+--     new_kern(-wd),
+--     baseline
+-- )
+
         local char = chardata[getfont(current)][getchar(current)]
-        if char and char.tounicode and #char.tounicode > 4 then -- hack test
+        if char and type(char.unicode) == "table" then -- hackery test
             setlistcolor(info,c_ligature)
             setlisttransparency(info,c_ligature_d)
         else
             setlistcolor(info,c_glyph)
             setlisttransparency(info,c_glyph_d)
         end
-        info = fast_hpack(info)
-        setfield(info,"width",0)
-        setfield(info,"height",0)
-        setfield(info,"depth",0)
+        info = new_hlist(info)
         setattr(info,a_layer,l_glyph)
         local info = linked_nodes(current,new_kern(-wd),info)
-        info = fast_hpack(info)
+        info = hpack_nodes(info)
         setfield(info,"width",wd)
         if next then
             setlink(info,next)
@@ -671,8 +730,6 @@ local tags = {
 -- we sometimes pass previous as we can have issues in math (not watertight for all)
 
 local function ruledglue(head,current,vertical,parent)
-    ----- spec    = getfield(current,"spec")
-    ----- width   = getfield(spec,"width")
     local subtype = getsubtype(current)
     local width   = effectiveglue(current,parent)
     local amount  = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
@@ -797,6 +854,7 @@ local function visualize(head,vertical,forced,parent)
     local trace_user     = false
     local trace_math     = false
     local trace_italic   = false
+    local trace_origin   = false
     local current        = head
     local previous       = nil
     local attr           = unsetvalue
@@ -821,21 +879,23 @@ local function visualize(head,vertical,forced,parent)
                 trace_user     = false
                 trace_math     = false
                 trace_italic   = false
+                trace_origin   = false
             else -- dead slow:
-                trace_hbox     = hasbit(a,   1)
-                trace_vbox     = hasbit(a,   2)
-                trace_vtop     = hasbit(a,   4)
-                trace_kern     = hasbit(a,   8)
-                trace_glue     = hasbit(a,  16)
-                trace_penalty  = hasbit(a,  32)
-                trace_fontkern = hasbit(a,  64)
-                trace_strut    = hasbit(a, 128)
-                trace_whatsit  = hasbit(a, 256)
-                trace_glyph    = hasbit(a, 512)
-                trace_simple   = hasbit(a,1024)
-                trace_user     = hasbit(a,2048)
-                trace_math     = hasbit(a,4096)
-                trace_italic   = hasbit(a,8192)
+                trace_hbox     = hasbit(a,    1)
+                trace_vbox     = hasbit(a,    2)
+                trace_vtop     = hasbit(a,    4)
+                trace_kern     = hasbit(a,    8)
+                trace_glue     = hasbit(a,   16)
+                trace_penalty  = hasbit(a,   32)
+                trace_fontkern = hasbit(a,   64)
+                trace_strut    = hasbit(a,  128)
+                trace_whatsit  = hasbit(a,  256)
+                trace_glyph    = hasbit(a,  512)
+                trace_simple   = hasbit(a, 1024)
+                trace_user     = hasbit(a, 2048)
+                trace_math     = hasbit(a, 4096)
+                trace_italic   = hasbit(a, 8192)
+                trace_origin   = hasbit(a,16384)
             end
             attr = a
         end
@@ -888,7 +948,7 @@ local function visualize(head,vertical,forced,parent)
                 setfield(current,"list",visualize(content,false,nil,current))
             end
             if trace_hbox then
-                head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous)
+                head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent)
             end
         elseif id == vlist_code then
             local content = getlist(current)
@@ -896,9 +956,9 @@ local function visualize(head,vertical,forced,parent)
                 setfield(current,"list",visualize(content,true,nil,current))
             end
             if trace_vtop then
-                head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple,previous)
+                head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple,previous,trace_origin,parent)
             elseif trace_vbox then
-                head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple,previous)
+                head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple,previous,trace_origin,parent)
             end
         elseif id == whatsit_code then
             if trace_whatsit then
@@ -937,14 +997,15 @@ local function cleanup()
     nf,   f_cache   = freed(f_cache)
     nw,   w_cache   = freed(w_cache)
     nb,   b_cache   = freed(b_cache)
+    no,   o_cache   = freed(o_cache)
     ng_v, g_cache_v = freed(g_cache_v)
     ng_h, g_cache_h = freed(g_cache_h)
     np_v, p_cache_v = freed(p_cache_v)
     np_h, p_cache_h = freed(p_cache_h)
     nk_v, k_cache_v = freed(k_cache_v)
     nk_h, k_cache_h = freed(k_cache_h)
- -- report_visualize("cache cleanup: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes",
- --     nf,ng_v+ng_h,np_v+np_h,nk_v+nk_h,nw,nb)
+ -- report_visualize("cache cleanup: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes, %s origins",
+ --     nf,ng_v+ng_h,np_v+np_h,nk_v+nk_h,nw,nb,no)
 end
 
 local function handler(head)
@@ -981,36 +1042,40 @@ function visualizers.box(n)
     end
 end
 
-local last = nil
-local used = nil
-
-local mark = {
-    "trace:1", "trace:2", "trace:3",
-    "trace:4", "trace:5", "trace:6",
-    "trace:7",
-}
-
-local function markfonts(list)
-    for n in traverse_nodes(list) do
-        local id = getid(n)
-        if id == glyph_code then
-            local font = getfont(n)
-            local okay = used[font]
-            if not okay then
-                last = last + 1
-                okay = mark[last]
-                used[font] = okay
+do
+
+    local last = nil
+    local used = nil
+
+    local mark = {
+        "trace:1", "trace:2", "trace:3",
+        "trace:4", "trace:5", "trace:6",
+        "trace:7",
+    }
+
+    local function markfonts(list)
+        for n in traverse_nodes(list) do
+            local id = getid(n)
+            if id == glyph_code then
+                local font = getfont(n)
+                local okay = used[font]
+                if not okay then
+                    last = last + 1
+                    okay = mark[last]
+                    used[font] = okay
+                end
+                setcolor(n,okay)
+            elseif id == hlist_code or id == vlist_code then
+                markfonts(getlist(n))
             end
-            setcolor(n,okay)
-        elseif id == hlist_code or id == vlist_code then
-            markfonts(getlist(n))
         end
     end
-end
 
-function visualizers.markfonts(list)
-    last, used = 0, { }
-    markfonts(type(n) == "number" and getlist(getbox(n)) or n)
+    function visualizers.markfonts(list)
+        last, used = 0, { }
+        markfonts(type(n) == "number" and getlist(getbox(n)) or n)
+    end
+
 end
 
 luatex.registerstopactions(cleanup)
diff --git a/tex/context/base/trac-vis.mkiv b/tex/context/base/trac-vis.mkiv
index 74a2c1ba2..bcf5f210d 100644
--- a/tex/context/base/trac-vis.mkiv
+++ b/tex/context/base/trac-vis.mkiv
@@ -54,11 +54,19 @@
 \let\syst_visualizers_vbox\vbox
 \let\syst_visualizers_vtop\vtop
 
+\let\syst_visualizers_hpack\hpack
+\let\syst_visualizers_vpack\vpack
+\let\syst_visualizers_tpack\tpack
+
 \unexpanded\def\ruledhbox{\syst_visualizers_hbox attr \visualattribute \clf_getvisual{simplehbox} }
 \unexpanded\def\ruledvbox{\syst_visualizers_vbox attr \visualattribute \clf_getvisual{simplevbox} }
 \unexpanded\def\ruledvtop{\syst_visualizers_vtop attr \visualattribute \clf_getvisual{simplevtop} } % special case
 \unexpanded\def\ruledtopv{\syst_visualizers_vtop attr \visualattribute \clf_getvisual{vtop}       }
 
+\unexpanded\def\ruledhpack{\syst_visualizers_hpack attr \visualattribute \clf_getvisual{simplehbox} }
+\unexpanded\def\ruledvpack{\syst_visualizers_vpack attr \visualattribute \clf_getvisual{simplevbox} }
+\unexpanded\def\ruledtpack{\syst_visualizers_tpack attr \visualattribute \clf_getvisual{simplevtop} } % special case
+
 \unexpanded\def\ruledmbox#1{\ruledhbox{\startimath#1\stopimath}}
 
 \appendtoks
@@ -174,6 +182,32 @@
    \unhbox\scratchbox
    \endgroup}
 
+% As demo:
+%
+% \startbuffer
+%     \hbox {\raise1cm\hbox{raised} normal \lower1cm\hbox{lowered}}
+%     \blank
+%     \moveleft1cm\hbox{left}
+%     \blank
+%     \hbox{normal}
+%     \blank
+%     \moveright1cm\hbox{right}
+%     \blank
+% \stopbuffer
+%
+% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer
+%
+% \startbuffer
+%     \moveleft1cm\vbox{left}
+%     \blank
+%     \vbox{normal}
+%     \blank
+%     \moveright1cm\vbox{right}
+%     \blank
+% \stopbuffer
+%
+% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer
+
 %D We keep this one:
 
 \unexpanded\def\dontinterfere
diff --git a/tex/context/base/type-ini.mkvi b/tex/context/base/type-ini.mkvi
index f56c5573d..22fe5ad4d 100644
--- a/tex/context/base/type-ini.mkvi
+++ b/tex/context/base/type-ini.mkvi
@@ -258,9 +258,12 @@
 \def\font_typescripts_synonym_define[#name][#synonym]%
   {\ifsecondargument\setevalue{\??typescriptsynonyms#name}{#synonym}\fi}
 
-\def\truetypescript#name%
+\def\truetypescript#name% recursove so no \lastnamedcs
   {\ifcsname\??typescriptsynonyms#name\endcsname
-     \expandafter\truetypescript\csname\??typescriptsynonyms#name\endcsname\else#name%
+    %\expandafter\truetypescript\csname\??typescriptsynonyms#name\endcsname
+     \expandafter\truetypescript\lastnamedcs
+   \else
+     #name%
    \fi}
 
 % script [serif] [default]         [size]
@@ -417,7 +420,8 @@
 % with testing:
 
 \def\typescriptprefix#name%
-  {\ifcsname\??typescriptprefix#name\endcsname\csname\??typescriptprefix#name\endcsname\else#name\fi}
+ %{\ifcsname\??typescriptprefix#name\endcsname\csname\??typescriptprefix#name\endcsname\else#name\fi}
+  {\ifcsname\??typescriptprefix#name\endcsname\lastnamedcs\else#name\fi}
 
 % defining typefaces:
 %
@@ -555,7 +559,8 @@
    \else\ifx\fontclass\empty
      \setupbodyfont[\s!rm]%
    \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
-     \setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+    %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+     \expandafter\setupbodyfont\expandafter[\lastnamedcs]%
    \else
      \setupbodyfont[\s!rm]%
    \fi \fi \fi
@@ -569,7 +574,8 @@
    \else\ifx\fontclass\empty
      \switchtobodyfont[\s!rm]%
    \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
-     \switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+    %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+     \expandafter\switchtobodyfont\expandafter[\lastnamedcs]%
    \else
      \switchtobodyfont[\s!rm]%
    \fi \fi \fi
@@ -601,7 +607,8 @@
 
 \def\font_typescripts_inherit_check_indeed#name% called often
   {\ifcsname\??typescriptinheritances\fontclass:#name\endcsname
-     \expandafter\let\expandafter\fontclass\csname\??typescriptinheritances\fontclass:#name\endcsname
+    %\expandafter\let\expandafter\fontclass\csname\??typescriptinheritances\fontclass:#name\endcsname
+     \expandafter\let\expandafter\fontclass\lastnamedcs
    \fi}
 
 \let\font_typescripts_inherit_check\gobbleoneargument
@@ -626,7 +633,8 @@
   {\ifx\fontclass\empty
      \let\fontstyle\s!rm
    \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
-     \edef\fontstyle{\csname\??typescriptdefaultstyles\fontclass\endcsname}%
+    %\edef\fontstyle{\csname\??typescriptdefaultstyles\fontclass\endcsname}%
+     \edef\fontstyle{\lastnamedcs}%
    \else
      \let\fontstyle\s!rm
    \fi\fi}
diff --git a/tex/context/base/typo-cln.lua b/tex/context/base/typo-cln.lua
index 6a62bdf9e..bc11f944c 100644
--- a/tex/context/base/typo-cln.lua
+++ b/tex/context/base/typo-cln.lua
@@ -97,7 +97,7 @@ function cleaners.set(n)
             end
             enabled = true
         end
-        texsetattribute(a_cleaner,n)
+        texsetattribute(a_cleaner,tonumber(n))
     end
 end
 
diff --git a/tex/context/base/typo-dha.lua b/tex/context/base/typo-dha.lua
index 4be0d99ea..30984a26c 100644
--- a/tex/context/base/typo-dha.lua
+++ b/tex/context/base/typo-dha.lua
@@ -73,7 +73,6 @@ local end_of_math        = nuts.end_of_math
 local nodepool           = nuts.pool
 
 local nodecodes          = nodes.nodecodes
-local whatcodes          = nodes.whatcodes
 local mathcodes          = nodes.mathcodes
 
 local glyph_code         = nodecodes.glyph
@@ -83,8 +82,8 @@ local kern_code          = nodecodes.kern
 local glue_code          = nodecodes.glue
 local hlist_code         = nodecodes.hlist
 local vlist_code         = nodecodes.vlist
-local dir_code           = nodecodes.dir or whatcodes.dir
-local localpar_code      = nodecodes.localpar or whatcodes.localpar
+local dir_code           = nodecodes.dir
+local localpar_code      = nodecodes.localpar
 
 local new_textdir        = nodepool.textdir
 
@@ -222,7 +221,7 @@ local function process(start)
                                     local fencedir = fences[#fences]
                                     fences[#fences] = nil
                                     if fencedir < 0 then
-                                        setchard(current,mirror)
+                                        setchar(current,mirror)
                                         setprop(current,"direction","r")
                                     else
                                         setprop(current,"direction","l")
diff --git a/tex/context/base/typo-fln.mkiv b/tex/context/base/typo-fln.mkiv
index 38a53bfa9..e883c57d2 100644
--- a/tex/context/base/typo-fln.mkiv
+++ b/tex/context/base/typo-fln.mkiv
@@ -104,7 +104,7 @@
 \unexpanded\def\applytofirstcharacter#1%
   {\begingroup
    \dowithnextbox
-     {\clf_applytofirstcharacter\nextbox{\strippedcsname#1}%
+     {\clf_applytofirstcharacter\nextbox{\csstring#1}%
       \unhbox\nextbox
       \endgroup}%
    \hbox}
diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua
index 45443a86d..dea8af7cb 100644
--- a/tex/context/base/typo-krn.lua
+++ b/tex/context/base/typo-krn.lua
@@ -194,9 +194,8 @@ end
 local function kern_injector(fillup,kern)
     if fillup then
         local g = new_glue(kern)
-        local s = getfield(g,"spec")
-        setfield(s,"stretch",kern)
-        setfield(s,"stretch_order",1)
+        setfield(g,"stretch",kern)
+        setfield(g,"stretch_order",1)
         return g
     else
         return new_kern(kern)
@@ -547,12 +546,11 @@ function kerns.handler(head)
             elseif id == glue_code then
                 local subtype = getsubtype(start)
                 if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then
-                    local s = getfield(start,"spec")
-                    local w = getfield(s,"width")
+                    local w = getfield(start,"width")
                     if w > 0 then
                         local width   = w+gluefactor*w*krn
-                        local stretch = getfield(s,"stretch")
-                        local shrink  = getfield(s,"shrink")
+                        local stretch = getfield(start,"stretch")
+                        local shrink  = getfield(start,"shrink")
                         setfield(start,"spec",spec_injector(fillup,width,stretch*width/w,shrink*width/w))
                         done = true
                     end
diff --git a/tex/context/base/typo-lin.lua b/tex/context/base/typo-lin.lua
index f9761fe64..e5b9b8d7c 100644
--- a/tex/context/base/typo-lin.lua
+++ b/tex/context/base/typo-lin.lua
@@ -180,9 +180,8 @@ local function normalize(line,islocal) -- assumes prestine lines, nothing pre/ap
     if id == glue_code then
         local subtype = getsubtype(head)
         if subtype == leftskip_code then
-            local spec = getfield(head,"spec")
-            leftskip   = head
-            lskip      = getfield(spec,"width")
+            leftskip = head
+            lskip    = getfield(head,"width") or 0
         end
         current = getnext(head)
         id      = getid(current)
@@ -196,9 +195,8 @@ local function normalize(line,islocal) -- assumes prestine lines, nothing pre/ap
     local id      = getid(current)
     if id == glue_code then
         if getsubtype(current) == rightskip_code then
-            local spec = getfield(current,"spec")
             rightskip  = tail
-            rskip      = getfield(spec,"width")
+            rskip      = getfield(current,"width") or 0
             current    = getprev(tail)
             id         = getid(current)
         end
diff --git a/tex/context/base/typo-mar.lua b/tex/context/base/typo-mar.lua
index 7ed4cbe66..ea5f572ba 100644
--- a/tex/context/base/typo-mar.lua
+++ b/tex/context/base/typo-mar.lua
@@ -128,7 +128,7 @@ local tonode             = nuts.tonode
 local tonut              = nuts.tonut
 
 local copy_node_list     = nuts.copy_list
-local hpack_nodes        = nuts.hpack -- nodes.fasthpack not really faster here
+local hpack_nodes        = nuts.hpack
 local traverse_id        = nuts.traverse_id
 local free_node_list     = nuts.flush_list
 local insert_node_after  = nuts.insert_after
diff --git a/tex/context/base/typo-pag.lua b/tex/context/base/typo-pag.lua
index 50b156e1c..355becff6 100644
--- a/tex/context/base/typo-pag.lua
+++ b/tex/context/base/typo-pag.lua
@@ -133,7 +133,7 @@ local function keeptogether(start,a)
                     end
                 elseif id == glue_code then
                     -- hm, breakpoint, maybe turn this into kern
-                    total = total + getfield(getfield(current,"spec"),"width")
+                    total = total + getfield(current,"width")
                     if trace_keeptogether then
                         report_keeptogether("%s, index %s, total %p, threshold %p","glue",a,total,threshold)
                     end
diff --git a/tex/context/base/typo-sus.lua b/tex/context/base/typo-sus.lua
index 0fe8e143a..7dec8cb59 100644
--- a/tex/context/base/typo-sus.lua
+++ b/tex/context/base/typo-sus.lua
@@ -82,7 +82,7 @@ local function special(n)
         elseif id == penalty_code then
             return true
         elseif id == glue_code then
-            local width = getfield(getfield(n,"spec"),"width")
+            local width = getfield(n,"width")
             return width < threshold
         elseif id == hlist_code then
             local width = getfield(n,"width")
@@ -117,7 +117,7 @@ local function mark(head,current,id,color)
     if id == glue_code then
         -- the glue can have stretch and/or shrink so the rule can overlap with the
         -- following glyph .. no big deal as that one then sits on top of the rule
-        local width = getfield(getfield(current,"spec"),"width")
+        local width = getfield(current,"width")
         local rule  = new_rule(width)
         local kern  = new_kern(-width)
         head = insert_before(head,current,rule)
diff --git a/tex/context/base/typo-tal.lua b/tex/context/base/typo-tal.lua
index ad2ad7bd1..2594b7298 100644
--- a/tex/context/base/typo-tal.lua
+++ b/tex/context/base/typo-tal.lua
@@ -260,8 +260,6 @@ function characteralign.handler(originalhead,where)
                 local prev = getprev(current)
                 if next and prev and getid(next) == glyph_code and getid(prev) == glyph_code then -- too much checking
                     local width = fontcharacters[getfont(b_start)][separator or period].width
-                 -- local spec = getfield(current,"spec")
-                 -- free_spec(spec)
                     setfield(current,"spec",new_gluespec(width))
                     setattr(current,a_character,punctuationspace)
                     if a_start then
diff --git a/tex/context/base/typo-wrp.lua b/tex/context/base/typo-wrp.lua
index 07639392f..394e15090 100644
--- a/tex/context/base/typo-wrp.lua
+++ b/tex/context/base/typo-wrp.lua
@@ -19,7 +19,7 @@ local nuts              = nodes.nuts
 local tonut             = nodes.tonut
 local tonode            = nodes.tonode
 
-local findtail          = nuts.tail
+local find_node_tail    = nuts.tail
 local getprev           = nuts.getprev
 local getid             = nuts.getid
 local getsubtype        = nuts.getsubtype
@@ -60,7 +60,7 @@ end
 function wrappers.handler(head)
     local head = tonut(head)
     if head then
-        local tail = findtail(head)
+        local tail = find_node_tail(head)
         local done = false
         head, tail, done = remove_dangling_crlf(head,tail) -- will be action chain
     end
diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua
index a3c1c6f8f..01138f1bb 100644
--- a/tex/context/base/util-prs.lua
+++ b/tex/context/base/util-prs.lua
@@ -24,6 +24,8 @@ local sortedhash        = table.sortedhash
 local sortedkeys        = table.sortedkeys
 local tohash            = table.tohash
 
+local hashes             = { }
+utilities.parsers.hashes = hashes
 -- we share some patterns
 
 local digit       = R("09")
@@ -315,10 +317,17 @@ end
 
 local pattern = Cf(Ct("") * Cg(C((1-S(", "))^1) * S(", ")^0 * Cc(true))^1,rawset)
 
-function utilities.parsers.settings_to_set(str,t)
+function utilities.parsers.settings_to_set(str)
     return str and lpegmatch(pattern,str) or { }
 end
 
+hashes.settings_to_set =  table.setmetatableindex(function(t,k) -- experiment, not public
+    local v = k and lpegmatch(pattern,k) or { }
+    t[k] = v
+    return v
+end)
+
+getmetatable(hashes.settings_to_set).__mode = "kv" -- could be an option (maybe sharing makes sense)
 
 function parsers.simple_hash_to_string(h, separator)
     local t, tn = { }, 0
diff --git a/tex/context/base/xetx-chr.mkii b/tex/context/base/xetx-chr.mkii
index 31f15a0cb..ca9c4aaa4 100644
--- a/tex/context/base/xetx-chr.mkii
+++ b/tex/context/base/xetx-chr.mkii
@@ -1,4 +1,4 @@
-% filename : xetx-chr.tex
+% filename : xetx-chr.mkii
 % comment  : generated by mtxrun --script chars --xtx
 % author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
 % copyright: PRAGMA ADE / ConTeXt Development Team
@@ -15,7 +15,6 @@
 \def\textbar                          {\char"0007C } % VERTICAL LINE: |
 \def\textbraceright                   {\char"0007D } % RIGHT CURLY BRACKET: }
 \def\textasciitilde                   {\char"0007E } % TILDE: ~
-\def\nobreakspace                     {\char"000A0 } % NO-BREAK SPACE:  
 \def\exclamdown                       {\char"000A1 } % INVERTED EXCLAMATION MARK: ¡
 \def\textcent                         {\char"000A2 } % CENT SIGN: ¢
 \def\textsterling                     {\char"000A3 } % POUND SIGN: £
@@ -1068,16 +1067,8 @@
 \def\greekOmegaiotasub                {\char"01FFC } % GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI: ῼ
 \def\greekoxia                        {\char"01FFD } % GREEK OXIA: ´
 \def\greekdasia                       {\char"01FFE } % GREEK DASIA: ῾
-\def\enspace                          {\char"02002 } % EN SPACE:  
-\def\emspace                          {\char"02003 } % EM SPACE:  
-\def\threeperemspace                  {\char"02004 } % THREE-PER-EM SPACE:  
-\def\fourperemspace                   {\char"02005 } % FOUR-PER-EM SPACE:  
-\def\sixperemspace                    {\char"02006 } % SIX-PER-EM SPACE:  
-\def\figurespace                      {\char"02007 } % FIGURE SPACE:  
-\def\punctuationspace                 {\char"02008 } % PUNCTUATION SPACE:  
-\def\thinspace                        {\char"02009 } % THIN SPACE:  
-\def\figurespace                      {\char"0200A } % HAIR SPACE:  
-\def\zerowidthspace                   {\char"0200B } % ZERO WIDTH SPACE: 
+\def\zwnj                             {\char"0200C } % ZERO WIDTH NON-JOINER: 
+\def\zwj                              {\char"0200D } % ZERO WIDTH JOINER: 
 \def\textminus                        {\char"02012 } % FIGURE DASH: ‒
 \def\endash                           {\char"02013 } % EN DASH: –
 \def\emdash                           {\char"02014 } % EM DASH: —
@@ -1092,12 +1083,10 @@
 \def\textddag                         {\char"02021 } % DOUBLE DAGGER: ‡
 \def\textbullet                       {\char"02022 } % BULLET: •
 \def\textellipsis                     {\char"02026 } % HORIZONTAL ELLIPSIS: …
-\def\narrownobreakspace               {\char"0202F } % NARROW NO-BREAK SPACE:  
 \def\perthousand                      {\char"02030 } % PER MILLE SIGN: ‰
 \def\guilsingleleft                   {\char"02039 } % SINGLE LEFT-POINTING ANGLE QUOTATION MARK: ‹
 \def\guilsingleright                  {\char"0203A } % SINGLE RIGHT-POINTING ANGLE QUOTATION MARK: ›
 \def\textfraction                     {\char"02044 } % FRACTION SLASH: ⁄
-\def\medspace                         {\char"0205F } % MEDIUM MATHEMATICAL SPACE:  
 \def\textdong                         {\char"020AB } % DONG SIGN: ₫
 \def\texteuro                         {\char"020AC } % EURO SIGN: €
 \def\textcelsius                      {\char"02103 } % DEGREE CELSIUS: ℃
@@ -1154,14 +1143,11 @@
 \def\romand                           {\char"0217E } % SMALL ROMAN NUMERAL FIVE HUNDRED: ⅾ
 \def\romanm                           {\char"0217F } % SMALL ROMAN NUMERAL ONE THOUSAND: ⅿ
 \def\carriagereturn                   {\char"021B5 } % DOWNWARDS ARROW WITH CORNER LEFTWARDS: ↵
-\def\ideographicspace                 {\char"03000 } % IDEOGRAPHIC SPACE:  
-\def\ideographichalffillspace         {\char"0303F } % IDEOGRAPHIC HALF FILL SPACE: 〿
 \def\ffligature                       {\char"0FB00 } % LATIN SMALL LIGATURE FF: ff
 \def\filigature                       {\char"0FB01 } % LATIN SMALL LIGATURE FI: fi
 \def\flligature                       {\char"0FB02 } % LATIN SMALL LIGATURE FL: fl
 \def\ffiligature                      {\char"0FB03 } % LATIN SMALL LIGATURE FFI: ffi
 \def\fflligature                      {\char"0FB04 } % LATIN SMALL LIGATURE FFL: ffl
 \def\stligature                       {\char"0FB06 } % LATIN SMALL LIGATURE ST: st
-\def\zerowidthnobreakspace            {\char"0FEFF } % ZERO WIDTH NO-BREAK SPACE: 
 
 \endinput
diff --git a/tex/context/base/xetx-cls.mkii b/tex/context/base/xetx-cls.mkii
index 6ce696f71..9142f39e5 100644
--- a/tex/context/base/xetx-cls.mkii
+++ b/tex/context/base/xetx-cls.mkii
@@ -1,4 +1,4 @@
-% filename : xetx-cls.tex
+% filename : xetx-cls.mkii
 % comment  : generated by mtxrun --script chars --xtx
 % author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
 % copyright: PRAGMA ADE / ConTeXt Development Team
@@ -7,29 +7,29 @@
 % some character classes for xetex; seems to be rather hard coded, these numbers
 % and also a mix of several classes; here we do linebreaks
 
-\defineXTXcharinjectionclass[lb:cl]
-\defineXTXcharinjectionclass[lb:ex]
-\defineXTXcharinjectionclass[lb:ns]
 \defineXTXcharinjectionclass[lb:id]
-\defineXTXcharinjectionclass[lb:op]
+\defineXTXcharinjectionclass[lb:cl]
 \defineXTXcharinjectionclass[lb:cm]
 \defineXTXcharinjectionclass[lb:is]
+\defineXTXcharinjectionclass[lb:ex]
+\defineXTXcharinjectionclass[lb:op]
+\defineXTXcharinjectionclass[lb:ns]
 
 \dofastrecurse{"00000}{"00008}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"0000E}{"0001F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00021}{lb:ex}
 \dosetXTXcharacterclass{"00028}{lb:op}
-\dosetXTXcharacterclass{"00029}{lb:cl}
 \dosetXTXcharacterclass{"0002C}{lb:is}
 \dosetXTXcharacterclass{"0002E}{lb:is}
 \dofastrecurse{"0003A}{"0003B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:is}}
 \dosetXTXcharacterclass{"0003F}{lb:ex}
 \dosetXTXcharacterclass{"0005B}{lb:op}
-\dosetXTXcharacterclass{"0005D}{lb:cl}
 \dosetXTXcharacterclass{"0007B}{lb:op}
 \dosetXTXcharacterclass{"0007D}{lb:cl}
 \dofastrecurse{"0007F}{"00084}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00086}{"0009F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"000A1}{lb:op}
+\dosetXTXcharacterclass{"000BF}{lb:op}
 \dofastrecurse{"00300}{"0034E}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00350}{"0035B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00363}{"0036F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
@@ -42,16 +42,16 @@
 \dofastrecurse{"005C4}{"005C5}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"005C6}{lb:ex}
 \dosetXTXcharacterclass{"005C7}{lb:cm}
-\dosetXTXcharacterclass{"0060C}{lb:ex}
-\dosetXTXcharacterclass{"0060D}{lb:is}
-\dofastrecurse{"00610}{"00615}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"0061B}{"0061F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
-\dofastrecurse{"0064B}{"0065E}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dosetXTXcharacterclass{"0066A}{lb:ex}
+\dofastrecurse{"0060C}{"0060D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:is}}
+\dofastrecurse{"00610}{"0061A}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"0061B}{lb:ex}
+\dosetXTXcharacterclass{"0061C}{lb:cm}
+\dofastrecurse{"0061E}{"0061F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
+\dofastrecurse{"0064B}{"0065F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00670}{lb:cm}
 \dosetXTXcharacterclass{"006D4}{lb:ex}
 \dofastrecurse{"006D6}{"006DC}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"006DE}{"006E4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"006DF}{"006E4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"006E7}{"006E8}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"006EA}{"006ED}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00711}{lb:cm}
@@ -60,10 +60,15 @@
 \dofastrecurse{"007EB}{"007F3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"007F8}{lb:is}
 \dosetXTXcharacterclass{"007F9}{lb:ex}
-\dofastrecurse{"00901}{"00903}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dosetXTXcharacterclass{"0093C}{lb:cm}
-\dofastrecurse{"0093E}{"0094D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00951}{"00954}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00816}{"00819}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0081B}{"00823}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00825}{"00827}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00829}{"0082D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00859}{"0085B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"008E3}{"00903}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0093A}{"0093C}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0093E}{"0094F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00951}{"00957}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00962}{"00963}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00981}{"00983}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"009BC}{lb:cm}
@@ -71,27 +76,33 @@
 \dosetXTXcharacterclass{"009D7}{lb:cm}
 \dofastrecurse{"009E2}{"009E3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00A01}{"00A03}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00A3C}{"00A4D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00A3C}{"00A51}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00A70}{"00A71}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00A81}{"00A83}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00A75}{"00A83}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00ABC}{lb:cm}
 \dofastrecurse{"00ABE}{"00ACD}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00AE2}{"00AE3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00B01}{"00B03}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00B3C}{lb:cm}
 \dofastrecurse{"00B3E}{"00B57}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00B62}{"00B63}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00B82}{lb:cm}
-\dofastrecurse{"00BBE}{"00BD7}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00C01}{"00C03}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00BBE}{"00BCD}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"00BD7}{lb:cm}
+\dofastrecurse{"00C00}{"00C03}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00C3E}{"00C56}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00C82}{"00C83}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00C62}{"00C63}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00C81}{"00C83}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00CBC}{lb:cm}
 \dofastrecurse{"00CBE}{"00CD6}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00CE2}{"00CE3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00D02}{"00D03}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00D3E}{"00D57}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00D01}{"00D03}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00D3E}{"00D4D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"00D57}{lb:cm}
+\dofastrecurse{"00D62}{"00D63}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00D82}{"00D83}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00DCA}{"00DF3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00DCA}{"00DDF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00DF2}{"00DF3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00F0D}{"00F11}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
 \dosetXTXcharacterclass{"00F14}{lb:ex}
 \dofastrecurse{"00F18}{"00F19}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
@@ -106,9 +117,9 @@
 \dofastrecurse{"00F71}{"00F7E}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00F80}{"00F84}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"00F86}{"00F87}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"00F90}{"00FBC}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"00F8D}{"00FBC}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"00FC6}{lb:cm}
-\dosetXTXcharacterclass{"0135F}{lb:cm}
+\dofastrecurse{"0135D}{"0135F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"0169B}{lb:op}
 \dosetXTXcharacterclass{"0169C}{lb:cl}
 \dofastrecurse{"01712}{"01714}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
@@ -116,14 +127,26 @@
 \dofastrecurse{"01752}{"01753}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"01772}{"01773}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"017D6}{lb:ns}
+\dofastrecurse{"01802}{"01803}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
+\dofastrecurse{"01808}{"01809}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
 \dofastrecurse{"0180B}{"0180D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"018A9}{lb:cm}
 \dofastrecurse{"01920}{"0193B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"01944}{"01945}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
 \dofastrecurse{"01A17}{"01A1B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"01B00}{"01B04}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"01A7F}{lb:cm}
+\dofastrecurse{"01AB0}{"01B04}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"01B34}{"01B44}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"01B6B}{"01B73}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"01B80}{"01B82}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"01BA1}{"01BAD}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"01BE6}{"01BF3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"01C24}{"01C37}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"01CD0}{"01CD2}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"01CD4}{"01CE8}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"01CED}{lb:cm}
+\dofastrecurse{"01CF2}{"01CF4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"01CF8}{"01CF9}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"01DC0}{"01DFF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"0200C}{"0200F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"0201A}{lb:op}
@@ -134,14 +157,39 @@
 \dosetXTXcharacterclass{"02045}{lb:op}
 \dosetXTXcharacterclass{"02046}{lb:cl}
 \dofastrecurse{"02047}{"02049}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
-\dofastrecurse{"0206A}{"0206F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"02066}{"0206F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"0207D}{lb:op}
 \dosetXTXcharacterclass{"0207E}{lb:cl}
 \dosetXTXcharacterclass{"0208D}{lb:op}
 \dosetXTXcharacterclass{"0208E}{lb:cl}
-\dofastrecurse{"020D0}{"020EF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"020D0}{"020F0}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"02308}{lb:op}
+\dosetXTXcharacterclass{"02309}{lb:cl}
+\dosetXTXcharacterclass{"0230A}{lb:op}
+\dosetXTXcharacterclass{"0230B}{lb:cl}
+\dofastrecurse{"0231A}{"0231B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dosetXTXcharacterclass{"02329}{lb:op}
 \dosetXTXcharacterclass{"0232A}{lb:cl}
+\dofastrecurse{"023F0}{"023F3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"02600}{"02603}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"02614}{"02615}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"02618}{lb:id}
+\dofastrecurse{"0261A}{"0261F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"02639}{"0263B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"02668}{lb:id}
+\dosetXTXcharacterclass{"0267F}{lb:id}
+\dofastrecurse{"026BD}{"026C8}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"026CD}{lb:id}
+\dofastrecurse{"026CF}{"026D1}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"026D3}{"026D4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"026D8}{"026D9}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"026DC}{lb:id}
+\dofastrecurse{"026DF}{"026E1}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"026EA}{lb:id}
+\dofastrecurse{"026F1}{"026F5}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"026F7}{"026FA}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"026FD}{"02704}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"02708}{"0270D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dofastrecurse{"02762}{"02763}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
 \dosetXTXcharacterclass{"02768}{lb:op}
 \dosetXTXcharacterclass{"02769}{lb:cl}
@@ -165,6 +213,10 @@
 \dosetXTXcharacterclass{"027E9}{lb:cl}
 \dosetXTXcharacterclass{"027EA}{lb:op}
 \dosetXTXcharacterclass{"027EB}{lb:cl}
+\dosetXTXcharacterclass{"027EC}{lb:op}
+\dosetXTXcharacterclass{"027ED}{lb:cl}
+\dosetXTXcharacterclass{"027EE}{lb:op}
+\dosetXTXcharacterclass{"027EF}{lb:cl}
 \dosetXTXcharacterclass{"02983}{lb:op}
 \dosetXTXcharacterclass{"02984}{lb:cl}
 \dosetXTXcharacterclass{"02985}{lb:op}
@@ -193,7 +245,23 @@
 \dosetXTXcharacterclass{"029DB}{lb:cl}
 \dosetXTXcharacterclass{"029FC}{lb:op}
 \dosetXTXcharacterclass{"029FD}{lb:cl}
-\dofastrecurse{"02E80}{"03000}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"02CEF}{"02CF1}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"02CF9}{lb:ex}
+\dosetXTXcharacterclass{"02CFE}{lb:ex}
+\dosetXTXcharacterclass{"02D7F}{lb:cm}
+\dofastrecurse{"02DE0}{"02DFF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"02E18}{lb:op}
+\dosetXTXcharacterclass{"02E22}{lb:op}
+\dosetXTXcharacterclass{"02E23}{lb:cl}
+\dosetXTXcharacterclass{"02E24}{lb:op}
+\dosetXTXcharacterclass{"02E25}{lb:cl}
+\dosetXTXcharacterclass{"02E26}{lb:op}
+\dosetXTXcharacterclass{"02E27}{lb:cl}
+\dosetXTXcharacterclass{"02E28}{lb:op}
+\dosetXTXcharacterclass{"02E29}{lb:cl}
+\dosetXTXcharacterclass{"02E2E}{lb:ex}
+\dosetXTXcharacterclass{"02E42}{lb:op}
+\dofastrecurse{"02E80}{"02FFB}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dofastrecurse{"03001}{"03002}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cl}}
 \dofastrecurse{"03003}{"03004}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dosetXTXcharacterclass{"03005}{lb:ns}
@@ -222,71 +290,72 @@
 \dofastrecurse{"0301E}{"0301F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cl}}
 \dofastrecurse{"03020}{"03029}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dofastrecurse{"0302A}{"0302F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"03030}{"0303A}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"03030}{"03034}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"03035}{lb:cm}
+\dofastrecurse{"03036}{"0303A}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dofastrecurse{"0303B}{"0303C}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
 \dofastrecurse{"0303D}{"0303F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dosetXTXcharacterclass{"03041}{lb:ns}
 \dosetXTXcharacterclass{"03042}{lb:id}
-\dosetXTXcharacterclass{"03043}{lb:ns}
 \dosetXTXcharacterclass{"03044}{lb:id}
-\dosetXTXcharacterclass{"03045}{lb:ns}
 \dosetXTXcharacterclass{"03046}{lb:id}
-\dosetXTXcharacterclass{"03047}{lb:ns}
 \dosetXTXcharacterclass{"03048}{lb:id}
-\dosetXTXcharacterclass{"03049}{lb:ns}
 \dofastrecurse{"0304A}{"03062}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dosetXTXcharacterclass{"03063}{lb:ns}
 \dofastrecurse{"03064}{"03082}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dosetXTXcharacterclass{"03083}{lb:ns}
 \dosetXTXcharacterclass{"03084}{lb:id}
-\dosetXTXcharacterclass{"03085}{lb:ns}
 \dosetXTXcharacterclass{"03086}{lb:id}
-\dosetXTXcharacterclass{"03087}{lb:ns}
 \dofastrecurse{"03088}{"0308D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dosetXTXcharacterclass{"0308E}{lb:ns}
 \dofastrecurse{"0308F}{"03094}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dofastrecurse{"03095}{"03096}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
 \dofastrecurse{"03099}{"0309A}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"0309B}{"0309E}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
 \dosetXTXcharacterclass{"0309F}{lb:id}
-\dofastrecurse{"030A0}{"030A1}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
+\dosetXTXcharacterclass{"030A0}{lb:ns}
 \dosetXTXcharacterclass{"030A2}{lb:id}
-\dosetXTXcharacterclass{"030A3}{lb:ns}
 \dosetXTXcharacterclass{"030A4}{lb:id}
-\dosetXTXcharacterclass{"030A5}{lb:ns}
 \dosetXTXcharacterclass{"030A6}{lb:id}
-\dosetXTXcharacterclass{"030A7}{lb:ns}
 \dosetXTXcharacterclass{"030A8}{lb:id}
-\dosetXTXcharacterclass{"030A9}{lb:ns}
 \dofastrecurse{"030AA}{"030C2}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dosetXTXcharacterclass{"030C3}{lb:ns}
 \dofastrecurse{"030C4}{"030E2}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dosetXTXcharacterclass{"030E3}{lb:ns}
 \dosetXTXcharacterclass{"030E4}{lb:id}
-\dosetXTXcharacterclass{"030E5}{lb:ns}
 \dosetXTXcharacterclass{"030E6}{lb:id}
-\dosetXTXcharacterclass{"030E7}{lb:ns}
 \dofastrecurse{"030E8}{"030ED}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dosetXTXcharacterclass{"030EE}{lb:ns}
 \dofastrecurse{"030EF}{"030F4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dofastrecurse{"030F5}{"030F6}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
 \dofastrecurse{"030F7}{"030FA}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dofastrecurse{"030FB}{"030FE}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
-\dofastrecurse{"030FF}{"031CF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dofastrecurse{"031F0}{"031FF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
-\dofastrecurse{"03200}{"03400}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dofastrecurse{"04E00}{"0A014}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"030FB}{lb:ns}
+\dofastrecurse{"030FD}{"030FE}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
+\dofastrecurse{"030FF}{"031E3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"03200}{"03247}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"03250}{"033FF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"0A000}{"0A014}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dosetXTXcharacterclass{"0A015}{lb:ns}
 \dofastrecurse{"0A016}{"0A4C6}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"0A60E}{lb:ex}
+\dofastrecurse{"0A66F}{"0A672}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A674}{"0A67D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A69E}{"0A69F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A6F0}{"0A6F1}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"0A802}{lb:cm}
 \dosetXTXcharacterclass{"0A806}{lb:cm}
 \dosetXTXcharacterclass{"0A80B}{lb:cm}
 \dofastrecurse{"0A823}{"0A827}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"0A876}{"0A877}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
+\dofastrecurse{"0A880}{"0A881}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A8B4}{"0A8C4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A8E0}{"0A8F1}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A926}{"0A92D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A947}{"0A953}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A980}{"0A983}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0A9B3}{"0A9C0}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0AA29}{"0AA36}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"0AA43}{lb:cm}
+\dofastrecurse{"0AA4C}{"0AA4D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0AAEB}{"0AAEF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0AAF5}{"0AAF6}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0ABE3}{"0ABEA}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0ABEC}{"0ABED}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"0F900}{"0FAD9}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dosetXTXcharacterclass{"0FB1E}{lb:cm}
-\dosetXTXcharacterclass{"0FD3E}{lb:op}
-\dosetXTXcharacterclass{"0FD3F}{lb:cl}
+\dosetXTXcharacterclass{"0FD3E}{lb:cl}
+\dosetXTXcharacterclass{"0FD3F}{lb:op}
 \dofastrecurse{"0FE00}{"0FE0F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dosetXTXcharacterclass{"0FE10}{lb:is}
 \dofastrecurse{"0FE11}{"0FE12}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cl}}
@@ -294,7 +363,7 @@
 \dofastrecurse{"0FE15}{"0FE16}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
 \dosetXTXcharacterclass{"0FE17}{lb:op}
 \dosetXTXcharacterclass{"0FE18}{lb:cl}
-\dofastrecurse{"0FE20}{"0FE23}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"0FE20}{"0FE2F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"0FE30}{"0FE34}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dosetXTXcharacterclass{"0FE35}{lb:op}
 \dosetXTXcharacterclass{"0FE36}{lb:cl}
@@ -357,22 +426,86 @@
 \dosetXTXcharacterclass{"0FF62}{lb:op}
 \dofastrecurse{"0FF63}{"0FF64}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cl}}
 \dosetXTXcharacterclass{"0FF65}{lb:ns}
-\dofastrecurse{"0FF67}{"0FF70}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
 \dofastrecurse{"0FF9E}{"0FF9F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
 \dofastrecurse{"0FFE2}{"0FFE4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dofastrecurse{"0FFF9}{"0FFFB}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"101FD}{lb:cm}
+\dosetXTXcharacterclass{"102E0}{lb:cm}
+\dofastrecurse{"10376}{"1037A}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"10A01}{"10A0F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"10A38}{"10A3F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"10AE5}{"10AE6}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"11000}{"11002}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"11038}{"11046}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"1107F}{"11082}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"110B0}{"110BA}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"11100}{"11102}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"11127}{"11134}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"11173}{lb:cm}
+\dofastrecurse{"11180}{"11182}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"111B3}{"111C0}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"111CA}{"111CC}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"1122C}{"11237}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"112DF}{"112EA}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"11300}{"11303}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"1133C}{lb:cm}
+\dofastrecurse{"1133E}{"1134D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"11357}{lb:cm}
+\dofastrecurse{"11362}{"11374}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"114B0}{"114C3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"115AF}{"115C0}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"115C4}{"115C5}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ex}}
+\dofastrecurse{"115DC}{"115DD}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"11630}{"11640}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"116AB}{"116B7}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"13258}{"1325A}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:op}}
+\dofastrecurse{"1325B}{"1325D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cl}}
+\dosetXTXcharacterclass{"13282}{lb:cl}
+\dosetXTXcharacterclass{"13286}{lb:op}
+\dosetXTXcharacterclass{"13287}{lb:cl}
+\dosetXTXcharacterclass{"13288}{lb:op}
+\dosetXTXcharacterclass{"13289}{lb:cl}
+\dosetXTXcharacterclass{"13379}{lb:op}
+\dofastrecurse{"1337A}{"1337B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cl}}
+\dosetXTXcharacterclass{"145CE}{lb:op}
+\dosetXTXcharacterclass{"145CF}{lb:cl}
+\dofastrecurse{"16AF0}{"16AF4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"16B30}{"16B36}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"16F51}{"16F92}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"1B000}{"1B001}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1BC9D}{"1BC9E}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"1BCA0}{"1BCA3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"1D165}{"1D169}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"1D16D}{"1D182}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"1D185}{"1D18B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"1D1AA}{"1D1AD}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 \dofastrecurse{"1D242}{"1D244}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
-\dofastrecurse{"20000}{"2FA1D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1DA00}{"1DA36}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"1DA3B}{"1DA6C}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dosetXTXcharacterclass{"1DA75}{lb:cm}
+\dosetXTXcharacterclass{"1DA84}{lb:cm}
+\dofastrecurse{"1DA9B}{"1DAAF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"1E8D0}{"1E8D6}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
+\dofastrecurse{"1F000}{"1F0F5}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F200}{"1F39B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F39E}{"1F3B4}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F3B7}{"1F3BB}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F3BD}{"1F3FA}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F400}{"1F49F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"1F4A1}{lb:id}
+\dosetXTXcharacterclass{"1F4A3}{lb:id}
+\dofastrecurse{"1F4A5}{"1F4AE}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dosetXTXcharacterclass{"1F4B0}{lb:id}
+\dofastrecurse{"1F4B3}{"1F4FF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F507}{"1F516}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F525}{"1F531}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F54A}{"1F5D3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F5DC}{"1F5F3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F5FA}{"1F64F}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F679}{"1F67B}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:ns}}
+\dofastrecurse{"1F680}{"1F6F3}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
+\dofastrecurse{"1F910}{"2FA1D}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 \dofastrecurse{"E0001}{"E01EF}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:cm}}
 
-\dofastrecurse{"03400}{"04DB5}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dofastrecurse{"04E00}{"09FBB}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
-\dofastrecurse{"20000}{"2A6D6}{1}{\dosetXTXcharacterclass\fastrecursecounter{lb:id}}
 
 \endinput
diff --git a/tex/context/base/xetx-utf.mkii b/tex/context/base/xetx-utf.mkii
index a337c9e76..a157a2d11 100644
--- a/tex/context/base/xetx-utf.mkii
+++ b/tex/context/base/xetx-utf.mkii
@@ -1,4 +1,4 @@
-% filename : xetx-utf.tex
+% filename : xetx-utf.mkii
 % comment  : generated by mtxrun --script chars --xtx
 % author   : Hans Hagen, PRAGMA-ADE, Hasselt NL
 % copyright: PRAGMA ADE / ConTeXt Development Team
@@ -549,9 +549,16 @@
 \setXTXcharcodes "002AD "002AD "002AD % LATIN LETTER BIDENTAL PERCUSSIVE
 \setXTXcharcodes "002AE "002AE "002AE % LATIN SMALL LETTER TURNED H WITH FISHHOOK
 \setXTXcharcodes "002AF "002AF "002AF % LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
+\setXTXcharcodes "00370 "00370 "00370 % GREEK CAPITAL LETTER HETA
+\setXTXcharcodes "00371 "00371 "00371 % GREEK SMALL LETTER HETA
+\setXTXcharcodes "00372 "00372 "00372 % GREEK CAPITAL LETTER ARCHAIC SAMPI
+\setXTXcharcodes "00373 "00373 "00373 % GREEK SMALL LETTER ARCHAIC SAMPI
+\setXTXcharcodes "00376 "00376 "00376 % GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
+\setXTXcharcodes "00377 "00377 "00377 % GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
 \setXTXcharcodes "0037B "0037B "003FD % GREEK SMALL REVERSED LUNATE SIGMA SYMBOL
 \setXTXcharcodes "0037C "0037C "003FE % GREEK SMALL DOTTED LUNATE SIGMA SYMBOL
 \setXTXcharcodes "0037D "0037D "003FF % GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
+\setXTXcharcodes "0037F "0037F "0037F % GREEK CAPITAL LETTER YOT
 \setXTXcharcodes "00386 "003AC "00386 % GREEK CAPITAL LETTER ALPHA WITH TONOS
 \setXTXcharcodes "00388 "003AD "00388 % GREEK CAPITAL LETTER EPSILON WITH TONOS
 \setXTXcharcodes "00389 "003AE "00389 % GREEK CAPITAL LETTER ETA WITH TONOS
@@ -621,6 +628,7 @@
 \setXTXcharcodes "003CC "003CC "0038C % GREEK SMALL LETTER OMICRON WITH TONOS
 \setXTXcharcodes "003CD "003CD "0038E % GREEK SMALL LETTER UPSILON WITH TONOS
 \setXTXcharcodes "003CE "003CE "0038F % GREEK SMALL LETTER OMEGA WITH TONOS
+\setXTXcharcodes "003CF "003CF "003CF % GREEK CAPITAL KAI SYMBOL
 \setXTXcharcodes "003D0 "003D0 "00392 % GREEK BETA SYMBOL
 \setXTXcharcodes "003D1 "003D1 "00398 % GREEK THETA SYMBOL
 \setXTXcharcodes "003D2 "003D2 "003D2 % GREEK UPSILON WITH HOOK SYMBOL
@@ -936,6 +944,34 @@
 \setXTXcharcodes "00511 "00511 "00510 % CYRILLIC SMALL LETTER REVERSED ZE
 \setXTXcharcodes "00512 "00513 "00512 % CYRILLIC CAPITAL LETTER EL WITH HOOK
 \setXTXcharcodes "00513 "00513 "00512 % CYRILLIC SMALL LETTER EL WITH HOOK
+\setXTXcharcodes "00514 "00514 "00514 % CYRILLIC CAPITAL LETTER LHA
+\setXTXcharcodes "00515 "00515 "00515 % CYRILLIC SMALL LETTER LHA
+\setXTXcharcodes "00516 "00516 "00516 % CYRILLIC CAPITAL LETTER RHA
+\setXTXcharcodes "00517 "00517 "00517 % CYRILLIC SMALL LETTER RHA
+\setXTXcharcodes "00518 "00518 "00518 % CYRILLIC CAPITAL LETTER YAE
+\setXTXcharcodes "00519 "00519 "00519 % CYRILLIC SMALL LETTER YAE
+\setXTXcharcodes "0051A "0051A "0051A % CYRILLIC CAPITAL LETTER QA
+\setXTXcharcodes "0051B "0051B "0051B % CYRILLIC SMALL LETTER QA
+\setXTXcharcodes "0051C "0051C "0051C % CYRILLIC CAPITAL LETTER WE
+\setXTXcharcodes "0051D "0051D "0051D % CYRILLIC SMALL LETTER WE
+\setXTXcharcodes "0051E "0051E "0051E % CYRILLIC CAPITAL LETTER ALEUT KA
+\setXTXcharcodes "0051F "0051F "0051F % CYRILLIC SMALL LETTER ALEUT KA
+\setXTXcharcodes "00520 "00520 "00520 % CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
+\setXTXcharcodes "00521 "00521 "00521 % CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK
+\setXTXcharcodes "00522 "00522 "00522 % CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
+\setXTXcharcodes "00523 "00523 "00523 % CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK
+\setXTXcharcodes "00524 "00524 "00524 % CYRILLIC CAPITAL LETTER PE WITH DESCENDER
+\setXTXcharcodes "00525 "00525 "00525 % CYRILLIC SMALL LETTER PE WITH DESCENDER
+\setXTXcharcodes "00526 "00526 "00526 % CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER
+\setXTXcharcodes "00527 "00527 "00527 % CYRILLIC SMALL LETTER SHHA WITH DESCENDER
+\setXTXcharcodes "00528 "00528 "00528 % CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK
+\setXTXcharcodes "00529 "00529 "00529 % CYRILLIC SMALL LETTER EN WITH LEFT HOOK
+\setXTXcharcodes "0052A "0052A "0052A % CYRILLIC CAPITAL LETTER DZZHE
+\setXTXcharcodes "0052B "0052B "0052B % CYRILLIC SMALL LETTER DZZHE
+\setXTXcharcodes "0052C "0052C "0052C % CYRILLIC CAPITAL LETTER DCHE
+\setXTXcharcodes "0052D "0052D "0052D % CYRILLIC SMALL LETTER DCHE
+\setXTXcharcodes "0052E "0052E "0052E % CYRILLIC CAPITAL LETTER EL WITH DESCENDER
+\setXTXcharcodes "0052F "0052F "0052F % CYRILLIC SMALL LETTER EL WITH DESCENDER
 \setXTXcharcodes "00531 "00561 "00531 % ARMENIAN CAPITAL LETTER AYB
 \setXTXcharcodes "00532 "00562 "00532 % ARMENIAN CAPITAL LETTER BEN
 \setXTXcharcodes "00533 "00563 "00533 % ARMENIAN CAPITAL LETTER GIM
@@ -1051,6 +1087,15 @@
 \setXTXcharcodes "010C3 "02D23 "010C3 % GEORGIAN CAPITAL LETTER WE
 \setXTXcharcodes "010C4 "02D24 "010C4 % GEORGIAN CAPITAL LETTER HAR
 \setXTXcharcodes "010C5 "02D25 "010C5 % GEORGIAN CAPITAL LETTER HOE
+\setXTXcharcodes "010C7 "010C7 "010C7 % GEORGIAN CAPITAL LETTER YN
+\setXTXcharcodes "010CD "010CD "010CD % GEORGIAN CAPITAL LETTER AEN
+\setXTXcharcodes "013F5 "013F5 "013F5 % CHEROKEE LETTER MV
+\setXTXcharcodes "013F8 "013F8 "013F8 % CHEROKEE SMALL LETTER YE
+\setXTXcharcodes "013F9 "013F9 "013F9 % CHEROKEE SMALL LETTER YI
+\setXTXcharcodes "013FA "013FA "013FA % CHEROKEE SMALL LETTER YO
+\setXTXcharcodes "013FB "013FB "013FB % CHEROKEE SMALL LETTER YU
+\setXTXcharcodes "013FC "013FC "013FC % CHEROKEE SMALL LETTER YV
+\setXTXcharcodes "013FD "013FD "013FD % CHEROKEE SMALL LETTER MV
 \setXTXcharcodes "01D00 "01D00 "01D00 % LATIN LETTER SMALL CAPITAL A
 \setXTXcharcodes "01D01 "01D01 "01D01 % LATIN LETTER SMALL CAPITAL AE
 \setXTXcharcodes "01D02 "01D02 "01D02 % LATIN SMALL LETTER TURNED AE
@@ -1307,6 +1352,10 @@
 \setXTXcharcodes "01E99 "01E99 "01E99 % LATIN SMALL LETTER Y WITH RING ABOVE
 \setXTXcharcodes "01E9A "01E9A "01E9A % LATIN SMALL LETTER A WITH RIGHT HALF RING
 \setXTXcharcodes "01E9B "01E9B "01E60 % LATIN SMALL LETTER LONG S WITH DOT ABOVE
+\setXTXcharcodes "01E9C "01E9C "01E9C % LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE
+\setXTXcharcodes "01E9D "01E9D "01E9D % LATIN SMALL LETTER LONG S WITH HIGH STROKE
+\setXTXcharcodes "01E9E "01E9E "01E9E % LATIN CAPITAL LETTER SHARP S
+\setXTXcharcodes "01E9F "01E9F "01E9F % LATIN SMALL LETTER DELTA
 \setXTXcharcodes "01EA0 "01EA1 "01EA0 % LATIN CAPITAL LETTER A WITH DOT BELOW
 \setXTXcharcodes "01EA1 "01EA1 "01EA0 % LATIN SMALL LETTER A WITH DOT BELOW
 \setXTXcharcodes "01EA2 "01EA3 "01EA2 % LATIN CAPITAL LETTER A WITH HOOK ABOVE
@@ -1397,6 +1446,12 @@
 \setXTXcharcodes "01EF7 "01EF7 "01EF6 % LATIN SMALL LETTER Y WITH HOOK ABOVE
 \setXTXcharcodes "01EF8 "01EF9 "01EF8 % LATIN CAPITAL LETTER Y WITH TILDE
 \setXTXcharcodes "01EF9 "01EF9 "01EF8 % LATIN SMALL LETTER Y WITH TILDE
+\setXTXcharcodes "01EFA "01EFA "01EFA % LATIN CAPITAL LETTER MIDDLE-WELSH LL
+\setXTXcharcodes "01EFB "01EFB "01EFB % LATIN SMALL LETTER MIDDLE-WELSH LL
+\setXTXcharcodes "01EFC "01EFC "01EFC % LATIN CAPITAL LETTER MIDDLE-WELSH V
+\setXTXcharcodes "01EFD "01EFD "01EFD % LATIN SMALL LETTER MIDDLE-WELSH V
+\setXTXcharcodes "01EFE "01EFE "01EFE % LATIN CAPITAL LETTER Y WITH LOOP
+\setXTXcharcodes "01EFF "01EFF "01EFF % LATIN SMALL LETTER Y WITH LOOP
 \setXTXcharcodes "01F00 "01F00 "01F08 % GREEK SMALL LETTER ALPHA WITH PSILI
 \setXTXcharcodes "01F01 "01F01 "01F09 % GREEK SMALL LETTER ALPHA WITH DASIA
 \setXTXcharcodes "01F02 "01F02 "01F0A % GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA
@@ -1768,10 +1823,24 @@
 \setXTXcharcodes "02C6A "02C6A "02C69 % LATIN SMALL LETTER K WITH DESCENDER
 \setXTXcharcodes "02C6B "02C6C "02C6B % LATIN CAPITAL LETTER Z WITH DESCENDER
 \setXTXcharcodes "02C6C "02C6C "02C6B % LATIN SMALL LETTER Z WITH DESCENDER
+\setXTXcharcodes "02C6D "02C6D "02C6D % LATIN CAPITAL LETTER ALPHA
+\setXTXcharcodes "02C6E "02C6E "02C6E % LATIN CAPITAL LETTER M WITH HOOK
+\setXTXcharcodes "02C6F "02C6F "02C6F % LATIN CAPITAL LETTER TURNED A
+\setXTXcharcodes "02C70 "02C70 "02C70 % LATIN CAPITAL LETTER TURNED ALPHA
+\setXTXcharcodes "02C71 "02C71 "02C71 % LATIN SMALL LETTER V WITH RIGHT HOOK
+\setXTXcharcodes "02C72 "02C72 "02C72 % LATIN CAPITAL LETTER W WITH HOOK
+\setXTXcharcodes "02C73 "02C73 "02C73 % LATIN SMALL LETTER W WITH HOOK
 \setXTXcharcodes "02C74 "02C74 "02C74 % LATIN SMALL LETTER V WITH CURL
 \setXTXcharcodes "02C75 "02C76 "02C75 % LATIN CAPITAL LETTER HALF H
 \setXTXcharcodes "02C76 "02C76 "02C75 % LATIN SMALL LETTER HALF H
 \setXTXcharcodes "02C77 "02C77 "02C77 % LATIN SMALL LETTER TAILLESS PHI
+\setXTXcharcodes "02C78 "02C78 "02C78 % LATIN SMALL LETTER E WITH NOTCH
+\setXTXcharcodes "02C79 "02C79 "02C79 % LATIN SMALL LETTER TURNED R WITH TAIL
+\setXTXcharcodes "02C7A "02C7A "02C7A % LATIN SMALL LETTER O WITH LOW RING INSIDE
+\setXTXcharcodes "02C7B "02C7B "02C7B % LATIN LETTER SMALL CAPITAL TURNED E
+\setXTXcharcodes "02C7C "02C7C "02C7C % LATIN SUBSCRIPT SMALL LETTER J
+\setXTXcharcodes "02C7E "02C7E "02C7E % LATIN CAPITAL LETTER S WITH SWASH TAIL
+\setXTXcharcodes "02C7F "02C7F "02C7F % LATIN CAPITAL LETTER Z WITH SWASH TAIL
 \setXTXcharcodes "02C80 "02C81 "02C80 % COPTIC CAPITAL LETTER ALFA
 \setXTXcharcodes "02C81 "02C81 "02C80 % COPTIC SMALL LETTER ALFA
 \setXTXcharcodes "02C82 "02C83 "02C82 % COPTIC CAPITAL LETTER VIDA
@@ -1873,6 +1942,12 @@
 \setXTXcharcodes "02CE2 "02CE3 "02CE2 % COPTIC CAPITAL LETTER OLD NUBIAN WAU
 \setXTXcharcodes "02CE3 "02CE3 "02CE2 % COPTIC SMALL LETTER OLD NUBIAN WAU
 \setXTXcharcodes "02CE4 "02CE4 "02CE4 % COPTIC SYMBOL KAI
+\setXTXcharcodes "02CEB "02CEB "02CEB % COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI
+\setXTXcharcodes "02CEC "02CEC "02CEC % COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI
+\setXTXcharcodes "02CED "02CED "02CED % COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
+\setXTXcharcodes "02CEE "02CEE "02CEE % COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA
+\setXTXcharcodes "02CF2 "02CF2 "02CF2 % COPTIC CAPITAL LETTER BOHAIRIC KHEI
+\setXTXcharcodes "02CF3 "02CF3 "02CF3 % COPTIC SMALL LETTER BOHAIRIC KHEI
 \setXTXcharcodes "02D00 "02D00 "010A0 % GEORGIAN SMALL LETTER AN
 \setXTXcharcodes "02D01 "02D01 "010A1 % GEORGIAN SMALL LETTER BAN
 \setXTXcharcodes "02D02 "02D02 "010A2 % GEORGIAN SMALL LETTER GAN
@@ -1911,6 +1986,355 @@
 \setXTXcharcodes "02D23 "02D23 "010C3 % GEORGIAN SMALL LETTER WE
 \setXTXcharcodes "02D24 "02D24 "010C4 % GEORGIAN SMALL LETTER HAR
 \setXTXcharcodes "02D25 "02D25 "010C5 % GEORGIAN SMALL LETTER HOE
+\setXTXcharcodes "02D27 "02D27 "02D27 % GEORGIAN SMALL LETTER YN
+\setXTXcharcodes "02D2D "02D2D "02D2D % GEORGIAN SMALL LETTER AEN
+\setXTXcharcodes "0A640 "0A640 "0A640 % CYRILLIC CAPITAL LETTER ZEMLYA
+\setXTXcharcodes "0A641 "0A641 "0A641 % CYRILLIC SMALL LETTER ZEMLYA
+\setXTXcharcodes "0A642 "0A642 "0A642 % CYRILLIC CAPITAL LETTER DZELO
+\setXTXcharcodes "0A643 "0A643 "0A643 % CYRILLIC SMALL LETTER DZELO
+\setXTXcharcodes "0A644 "0A644 "0A644 % CYRILLIC CAPITAL LETTER REVERSED DZE
+\setXTXcharcodes "0A645 "0A645 "0A645 % CYRILLIC SMALL LETTER REVERSED DZE
+\setXTXcharcodes "0A646 "0A646 "0A646 % CYRILLIC CAPITAL LETTER IOTA
+\setXTXcharcodes "0A647 "0A647 "0A647 % CYRILLIC SMALL LETTER IOTA
+\setXTXcharcodes "0A648 "0A648 "0A648 % CYRILLIC CAPITAL LETTER DJERV
+\setXTXcharcodes "0A649 "0A649 "0A649 % CYRILLIC SMALL LETTER DJERV
+\setXTXcharcodes "0A64A "0A64A "0A64A % CYRILLIC CAPITAL LETTER MONOGRAPH UK
+\setXTXcharcodes "0A64B "0A64B "0A64B % CYRILLIC SMALL LETTER MONOGRAPH UK
+\setXTXcharcodes "0A64C "0A64C "0A64C % CYRILLIC CAPITAL LETTER BROAD OMEGA
+\setXTXcharcodes "0A64D "0A64D "0A64D % CYRILLIC SMALL LETTER BROAD OMEGA
+\setXTXcharcodes "0A64E "0A64E "0A64E % CYRILLIC CAPITAL LETTER NEUTRAL YER
+\setXTXcharcodes "0A64F "0A64F "0A64F % CYRILLIC SMALL LETTER NEUTRAL YER
+\setXTXcharcodes "0A650 "0A650 "0A650 % CYRILLIC CAPITAL LETTER YERU WITH BACK YER
+\setXTXcharcodes "0A651 "0A651 "0A651 % CYRILLIC SMALL LETTER YERU WITH BACK YER
+\setXTXcharcodes "0A652 "0A652 "0A652 % CYRILLIC CAPITAL LETTER IOTIFIED YAT
+\setXTXcharcodes "0A653 "0A653 "0A653 % CYRILLIC SMALL LETTER IOTIFIED YAT
+\setXTXcharcodes "0A654 "0A654 "0A654 % CYRILLIC CAPITAL LETTER REVERSED YU
+\setXTXcharcodes "0A655 "0A655 "0A655 % CYRILLIC SMALL LETTER REVERSED YU
+\setXTXcharcodes "0A656 "0A656 "0A656 % CYRILLIC CAPITAL LETTER IOTIFIED A
+\setXTXcharcodes "0A657 "0A657 "0A657 % CYRILLIC SMALL LETTER IOTIFIED A
+\setXTXcharcodes "0A658 "0A658 "0A658 % CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
+\setXTXcharcodes "0A659 "0A659 "0A659 % CYRILLIC SMALL LETTER CLOSED LITTLE YUS
+\setXTXcharcodes "0A65A "0A65A "0A65A % CYRILLIC CAPITAL LETTER BLENDED YUS
+\setXTXcharcodes "0A65B "0A65B "0A65B % CYRILLIC SMALL LETTER BLENDED YUS
+\setXTXcharcodes "0A65C "0A65C "0A65C % CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS
+\setXTXcharcodes "0A65D "0A65D "0A65D % CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS
+\setXTXcharcodes "0A65E "0A65E "0A65E % CYRILLIC CAPITAL LETTER YN
+\setXTXcharcodes "0A65F "0A65F "0A65F % CYRILLIC SMALL LETTER YN
+\setXTXcharcodes "0A660 "0A660 "0A660 % CYRILLIC CAPITAL LETTER REVERSED TSE
+\setXTXcharcodes "0A661 "0A661 "0A661 % CYRILLIC SMALL LETTER REVERSED TSE
+\setXTXcharcodes "0A662 "0A662 "0A662 % CYRILLIC CAPITAL LETTER SOFT DE
+\setXTXcharcodes "0A663 "0A663 "0A663 % CYRILLIC SMALL LETTER SOFT DE
+\setXTXcharcodes "0A664 "0A664 "0A664 % CYRILLIC CAPITAL LETTER SOFT EL
+\setXTXcharcodes "0A665 "0A665 "0A665 % CYRILLIC SMALL LETTER SOFT EL
+\setXTXcharcodes "0A666 "0A666 "0A666 % CYRILLIC CAPITAL LETTER SOFT EM
+\setXTXcharcodes "0A667 "0A667 "0A667 % CYRILLIC SMALL LETTER SOFT EM
+\setXTXcharcodes "0A668 "0A668 "0A668 % CYRILLIC CAPITAL LETTER MONOCULAR O
+\setXTXcharcodes "0A669 "0A669 "0A669 % CYRILLIC SMALL LETTER MONOCULAR O
+\setXTXcharcodes "0A66A "0A66A "0A66A % CYRILLIC CAPITAL LETTER BINOCULAR O
+\setXTXcharcodes "0A66B "0A66B "0A66B % CYRILLIC SMALL LETTER BINOCULAR O
+\setXTXcharcodes "0A66C "0A66C "0A66C % CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
+\setXTXcharcodes "0A66D "0A66D "0A66D % CYRILLIC SMALL LETTER DOUBLE MONOCULAR O
+\setXTXcharcodes "0A680 "0A680 "0A680 % CYRILLIC CAPITAL LETTER DWE
+\setXTXcharcodes "0A681 "0A681 "0A681 % CYRILLIC SMALL LETTER DWE
+\setXTXcharcodes "0A682 "0A682 "0A682 % CYRILLIC CAPITAL LETTER DZWE
+\setXTXcharcodes "0A683 "0A683 "0A683 % CYRILLIC SMALL LETTER DZWE
+\setXTXcharcodes "0A684 "0A684 "0A684 % CYRILLIC CAPITAL LETTER ZHWE
+\setXTXcharcodes "0A685 "0A685 "0A685 % CYRILLIC SMALL LETTER ZHWE
+\setXTXcharcodes "0A686 "0A686 "0A686 % CYRILLIC CAPITAL LETTER CCHE
+\setXTXcharcodes "0A687 "0A687 "0A687 % CYRILLIC SMALL LETTER CCHE
+\setXTXcharcodes "0A688 "0A688 "0A688 % CYRILLIC CAPITAL LETTER DZZE
+\setXTXcharcodes "0A689 "0A689 "0A689 % CYRILLIC SMALL LETTER DZZE
+\setXTXcharcodes "0A68A "0A68A "0A68A % CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
+\setXTXcharcodes "0A68B "0A68B "0A68B % CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK
+\setXTXcharcodes "0A68C "0A68C "0A68C % CYRILLIC CAPITAL LETTER TWE
+\setXTXcharcodes "0A68D "0A68D "0A68D % CYRILLIC SMALL LETTER TWE
+\setXTXcharcodes "0A68E "0A68E "0A68E % CYRILLIC CAPITAL LETTER TSWE
+\setXTXcharcodes "0A68F "0A68F "0A68F % CYRILLIC SMALL LETTER TSWE
+\setXTXcharcodes "0A690 "0A690 "0A690 % CYRILLIC CAPITAL LETTER TSSE
+\setXTXcharcodes "0A691 "0A691 "0A691 % CYRILLIC SMALL LETTER TSSE
+\setXTXcharcodes "0A692 "0A692 "0A692 % CYRILLIC CAPITAL LETTER TCHE
+\setXTXcharcodes "0A693 "0A693 "0A693 % CYRILLIC SMALL LETTER TCHE
+\setXTXcharcodes "0A694 "0A694 "0A694 % CYRILLIC CAPITAL LETTER HWE
+\setXTXcharcodes "0A695 "0A695 "0A695 % CYRILLIC SMALL LETTER HWE
+\setXTXcharcodes "0A696 "0A696 "0A696 % CYRILLIC CAPITAL LETTER SHWE
+\setXTXcharcodes "0A697 "0A697 "0A697 % CYRILLIC SMALL LETTER SHWE
+\setXTXcharcodes "0A698 "0A698 "0A698 % CYRILLIC CAPITAL LETTER DOUBLE O
+\setXTXcharcodes "0A699 "0A699 "0A699 % CYRILLIC SMALL LETTER DOUBLE O
+\setXTXcharcodes "0A69A "0A69A "0A69A % CYRILLIC CAPITAL LETTER CROSSED O
+\setXTXcharcodes "0A69B "0A69B "0A69B % CYRILLIC SMALL LETTER CROSSED O
+\setXTXcharcodes "0A722 "0A722 "0A722 % LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF
+\setXTXcharcodes "0A723 "0A723 "0A723 % LATIN SMALL LETTER EGYPTOLOGICAL ALEF
+\setXTXcharcodes "0A724 "0A724 "0A724 % LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
+\setXTXcharcodes "0A725 "0A725 "0A725 % LATIN SMALL LETTER EGYPTOLOGICAL AIN
+\setXTXcharcodes "0A726 "0A726 "0A726 % LATIN CAPITAL LETTER HENG
+\setXTXcharcodes "0A727 "0A727 "0A727 % LATIN SMALL LETTER HENG
+\setXTXcharcodes "0A728 "0A728 "0A728 % LATIN CAPITAL LETTER TZ
+\setXTXcharcodes "0A729 "0A729 "0A729 % LATIN SMALL LETTER TZ
+\setXTXcharcodes "0A72A "0A72A "0A72A % LATIN CAPITAL LETTER TRESILLO
+\setXTXcharcodes "0A72B "0A72B "0A72B % LATIN SMALL LETTER TRESILLO
+\setXTXcharcodes "0A72C "0A72C "0A72C % LATIN CAPITAL LETTER CUATRILLO
+\setXTXcharcodes "0A72D "0A72D "0A72D % LATIN SMALL LETTER CUATRILLO
+\setXTXcharcodes "0A72E "0A72E "0A72E % LATIN CAPITAL LETTER CUATRILLO WITH COMMA
+\setXTXcharcodes "0A72F "0A72F "0A72F % LATIN SMALL LETTER CUATRILLO WITH COMMA
+\setXTXcharcodes "0A730 "0A730 "0A730 % LATIN LETTER SMALL CAPITAL F
+\setXTXcharcodes "0A731 "0A731 "0A731 % LATIN LETTER SMALL CAPITAL S
+\setXTXcharcodes "0A732 "0A732 "0A732 % LATIN CAPITAL LETTER AA
+\setXTXcharcodes "0A733 "0A733 "0A733 % LATIN SMALL LETTER AA
+\setXTXcharcodes "0A734 "0A734 "0A734 % LATIN CAPITAL LETTER AO
+\setXTXcharcodes "0A735 "0A735 "0A735 % LATIN SMALL LETTER AO
+\setXTXcharcodes "0A736 "0A736 "0A736 % LATIN CAPITAL LETTER AU
+\setXTXcharcodes "0A737 "0A737 "0A737 % LATIN SMALL LETTER AU
+\setXTXcharcodes "0A738 "0A738 "0A738 % LATIN CAPITAL LETTER AV
+\setXTXcharcodes "0A739 "0A739 "0A739 % LATIN SMALL LETTER AV
+\setXTXcharcodes "0A73A "0A73A "0A73A % LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
+\setXTXcharcodes "0A73B "0A73B "0A73B % LATIN SMALL LETTER AV WITH HORIZONTAL BAR
+\setXTXcharcodes "0A73C "0A73C "0A73C % LATIN CAPITAL LETTER AY
+\setXTXcharcodes "0A73D "0A73D "0A73D % LATIN SMALL LETTER AY
+\setXTXcharcodes "0A73E "0A73E "0A73E % LATIN CAPITAL LETTER REVERSED C WITH DOT
+\setXTXcharcodes "0A73F "0A73F "0A73F % LATIN SMALL LETTER REVERSED C WITH DOT
+\setXTXcharcodes "0A740 "0A740 "0A740 % LATIN CAPITAL LETTER K WITH STROKE
+\setXTXcharcodes "0A741 "0A741 "0A741 % LATIN SMALL LETTER K WITH STROKE
+\setXTXcharcodes "0A742 "0A742 "0A742 % LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
+\setXTXcharcodes "0A743 "0A743 "0A743 % LATIN SMALL LETTER K WITH DIAGONAL STROKE
+\setXTXcharcodes "0A744 "0A744 "0A744 % LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE
+\setXTXcharcodes "0A745 "0A745 "0A745 % LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE
+\setXTXcharcodes "0A746 "0A746 "0A746 % LATIN CAPITAL LETTER BROKEN L
+\setXTXcharcodes "0A747 "0A747 "0A747 % LATIN SMALL LETTER BROKEN L
+\setXTXcharcodes "0A748 "0A748 "0A748 % LATIN CAPITAL LETTER L WITH HIGH STROKE
+\setXTXcharcodes "0A749 "0A749 "0A749 % LATIN SMALL LETTER L WITH HIGH STROKE
+\setXTXcharcodes "0A74A "0A74A "0A74A % LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY
+\setXTXcharcodes "0A74B "0A74B "0A74B % LATIN SMALL LETTER O WITH LONG STROKE OVERLAY
+\setXTXcharcodes "0A74C "0A74C "0A74C % LATIN CAPITAL LETTER O WITH LOOP
+\setXTXcharcodes "0A74D "0A74D "0A74D % LATIN SMALL LETTER O WITH LOOP
+\setXTXcharcodes "0A74E "0A74E "0A74E % LATIN CAPITAL LETTER OO
+\setXTXcharcodes "0A74F "0A74F "0A74F % LATIN SMALL LETTER OO
+\setXTXcharcodes "0A750 "0A750 "0A750 % LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER
+\setXTXcharcodes "0A751 "0A751 "0A751 % LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER
+\setXTXcharcodes "0A752 "0A752 "0A752 % LATIN CAPITAL LETTER P WITH FLOURISH
+\setXTXcharcodes "0A753 "0A753 "0A753 % LATIN SMALL LETTER P WITH FLOURISH
+\setXTXcharcodes "0A754 "0A754 "0A754 % LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
+\setXTXcharcodes "0A755 "0A755 "0A755 % LATIN SMALL LETTER P WITH SQUIRREL TAIL
+\setXTXcharcodes "0A756 "0A756 "0A756 % LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER
+\setXTXcharcodes "0A757 "0A757 "0A757 % LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER
+\setXTXcharcodes "0A758 "0A758 "0A758 % LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
+\setXTXcharcodes "0A759 "0A759 "0A759 % LATIN SMALL LETTER Q WITH DIAGONAL STROKE
+\setXTXcharcodes "0A75A "0A75A "0A75A % LATIN CAPITAL LETTER R ROTUNDA
+\setXTXcharcodes "0A75B "0A75B "0A75B % LATIN SMALL LETTER R ROTUNDA
+\setXTXcharcodes "0A75C "0A75C "0A75C % LATIN CAPITAL LETTER RUM ROTUNDA
+\setXTXcharcodes "0A75D "0A75D "0A75D % LATIN SMALL LETTER RUM ROTUNDA
+\setXTXcharcodes "0A75E "0A75E "0A75E % LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
+\setXTXcharcodes "0A75F "0A75F "0A75F % LATIN SMALL LETTER V WITH DIAGONAL STROKE
+\setXTXcharcodes "0A760 "0A760 "0A760 % LATIN CAPITAL LETTER VY
+\setXTXcharcodes "0A761 "0A761 "0A761 % LATIN SMALL LETTER VY
+\setXTXcharcodes "0A762 "0A762 "0A762 % LATIN CAPITAL LETTER VISIGOTHIC Z
+\setXTXcharcodes "0A763 "0A763 "0A763 % LATIN SMALL LETTER VISIGOTHIC Z
+\setXTXcharcodes "0A764 "0A764 "0A764 % LATIN CAPITAL LETTER THORN WITH STROKE
+\setXTXcharcodes "0A765 "0A765 "0A765 % LATIN SMALL LETTER THORN WITH STROKE
+\setXTXcharcodes "0A766 "0A766 "0A766 % LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER
+\setXTXcharcodes "0A767 "0A767 "0A767 % LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER
+\setXTXcharcodes "0A768 "0A768 "0A768 % LATIN CAPITAL LETTER VEND
+\setXTXcharcodes "0A769 "0A769 "0A769 % LATIN SMALL LETTER VEND
+\setXTXcharcodes "0A76A "0A76A "0A76A % LATIN CAPITAL LETTER ET
+\setXTXcharcodes "0A76B "0A76B "0A76B % LATIN SMALL LETTER ET
+\setXTXcharcodes "0A76C "0A76C "0A76C % LATIN CAPITAL LETTER IS
+\setXTXcharcodes "0A76D "0A76D "0A76D % LATIN SMALL LETTER IS
+\setXTXcharcodes "0A76E "0A76E "0A76E % LATIN CAPITAL LETTER CON
+\setXTXcharcodes "0A76F "0A76F "0A76F % LATIN SMALL LETTER CON
+\setXTXcharcodes "0A771 "0A771 "0A771 % LATIN SMALL LETTER DUM
+\setXTXcharcodes "0A772 "0A772 "0A772 % LATIN SMALL LETTER LUM
+\setXTXcharcodes "0A773 "0A773 "0A773 % LATIN SMALL LETTER MUM
+\setXTXcharcodes "0A774 "0A774 "0A774 % LATIN SMALL LETTER NUM
+\setXTXcharcodes "0A775 "0A775 "0A775 % LATIN SMALL LETTER RUM
+\setXTXcharcodes "0A776 "0A776 "0A776 % LATIN LETTER SMALL CAPITAL RUM
+\setXTXcharcodes "0A777 "0A777 "0A777 % LATIN SMALL LETTER TUM
+\setXTXcharcodes "0A778 "0A778 "0A778 % LATIN SMALL LETTER UM
+\setXTXcharcodes "0A779 "0A779 "0A779 % LATIN CAPITAL LETTER INSULAR D
+\setXTXcharcodes "0A77A "0A77A "0A77A % LATIN SMALL LETTER INSULAR D
+\setXTXcharcodes "0A77B "0A77B "0A77B % LATIN CAPITAL LETTER INSULAR F
+\setXTXcharcodes "0A77C "0A77C "0A77C % LATIN SMALL LETTER INSULAR F
+\setXTXcharcodes "0A77D "0A77D "0A77D % LATIN CAPITAL LETTER INSULAR G
+\setXTXcharcodes "0A77E "0A77E "0A77E % LATIN CAPITAL LETTER TURNED INSULAR G
+\setXTXcharcodes "0A77F "0A77F "0A77F % LATIN SMALL LETTER TURNED INSULAR G
+\setXTXcharcodes "0A780 "0A780 "0A780 % LATIN CAPITAL LETTER TURNED L
+\setXTXcharcodes "0A781 "0A781 "0A781 % LATIN SMALL LETTER TURNED L
+\setXTXcharcodes "0A782 "0A782 "0A782 % LATIN CAPITAL LETTER INSULAR R
+\setXTXcharcodes "0A783 "0A783 "0A783 % LATIN SMALL LETTER INSULAR R
+\setXTXcharcodes "0A784 "0A784 "0A784 % LATIN CAPITAL LETTER INSULAR S
+\setXTXcharcodes "0A785 "0A785 "0A785 % LATIN SMALL LETTER INSULAR S
+\setXTXcharcodes "0A786 "0A786 "0A786 % LATIN CAPITAL LETTER INSULAR T
+\setXTXcharcodes "0A787 "0A787 "0A787 % LATIN SMALL LETTER INSULAR T
+\setXTXcharcodes "0A78B "0A78B "0A78B % LATIN CAPITAL LETTER SALTILLO
+\setXTXcharcodes "0A78C "0A78C "0A78C % LATIN SMALL LETTER SALTILLO
+\setXTXcharcodes "0A78D "0A78D "0A78D % LATIN CAPITAL LETTER TURNED H
+\setXTXcharcodes "0A78E "0A78E "0A78E % LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
+\setXTXcharcodes "0A790 "0A790 "0A790 % LATIN CAPITAL LETTER N WITH DESCENDER
+\setXTXcharcodes "0A791 "0A791 "0A791 % LATIN SMALL LETTER N WITH DESCENDER
+\setXTXcharcodes "0A792 "0A792 "0A792 % LATIN CAPITAL LETTER C WITH BAR
+\setXTXcharcodes "0A793 "0A793 "0A793 % LATIN SMALL LETTER C WITH BAR
+\setXTXcharcodes "0A794 "0A794 "0A794 % LATIN SMALL LETTER C WITH PALATAL HOOK
+\setXTXcharcodes "0A795 "0A795 "0A795 % LATIN SMALL LETTER H WITH PALATAL HOOK
+\setXTXcharcodes "0A796 "0A796 "0A796 % LATIN CAPITAL LETTER B WITH FLOURISH
+\setXTXcharcodes "0A797 "0A797 "0A797 % LATIN SMALL LETTER B WITH FLOURISH
+\setXTXcharcodes "0A798 "0A798 "0A798 % LATIN CAPITAL LETTER F WITH STROKE
+\setXTXcharcodes "0A799 "0A799 "0A799 % LATIN SMALL LETTER F WITH STROKE
+\setXTXcharcodes "0A79A "0A79A "0A79A % LATIN CAPITAL LETTER VOLAPUK AE
+\setXTXcharcodes "0A79B "0A79B "0A79B % LATIN SMALL LETTER VOLAPUK AE
+\setXTXcharcodes "0A79C "0A79C "0A79C % LATIN CAPITAL LETTER VOLAPUK OE
+\setXTXcharcodes "0A79D "0A79D "0A79D % LATIN SMALL LETTER VOLAPUK OE
+\setXTXcharcodes "0A79E "0A79E "0A79E % LATIN CAPITAL LETTER VOLAPUK UE
+\setXTXcharcodes "0A79F "0A79F "0A79F % LATIN SMALL LETTER VOLAPUK UE
+\setXTXcharcodes "0A7A0 "0A7A0 "0A7A0 % LATIN CAPITAL LETTER G WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A1 "0A7A1 "0A7A1 % LATIN SMALL LETTER G WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A2 "0A7A2 "0A7A2 % LATIN CAPITAL LETTER K WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A3 "0A7A3 "0A7A3 % LATIN SMALL LETTER K WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A4 "0A7A4 "0A7A4 % LATIN CAPITAL LETTER N WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A5 "0A7A5 "0A7A5 % LATIN SMALL LETTER N WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A6 "0A7A6 "0A7A6 % LATIN CAPITAL LETTER R WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A7 "0A7A7 "0A7A7 % LATIN SMALL LETTER R WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A8 "0A7A8 "0A7A8 % LATIN CAPITAL LETTER S WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7A9 "0A7A9 "0A7A9 % LATIN SMALL LETTER S WITH OBLIQUE STROKE
+\setXTXcharcodes "0A7AA "0A7AA "0A7AA % LATIN CAPITAL LETTER H WITH HOOK
+\setXTXcharcodes "0A7AB "0A7AB "0A7AB % LATIN CAPITAL LETTER REVERSED OPEN E
+\setXTXcharcodes "0A7AC "0A7AC "0A7AC % LATIN CAPITAL LETTER SCRIPT G
+\setXTXcharcodes "0A7AD "0A7AD "0A7AD % LATIN CAPITAL LETTER L WITH BELT
+\setXTXcharcodes "0A7B0 "0A7B0 "0A7B0 % LATIN CAPITAL LETTER TURNED K
+\setXTXcharcodes "0A7B1 "0A7B1 "0A7B1 % LATIN CAPITAL LETTER TURNED T
+\setXTXcharcodes "0A7B2 "0A7B2 "0A7B2 % LATIN CAPITAL LETTER J WITH CROSSED-TAIL
+\setXTXcharcodes "0A7B3 "0A7B3 "0A7B3 % LATIN CAPITAL LETTER CHI
+\setXTXcharcodes "0A7B4 "0A7B4 "0A7B4 % LATIN CAPITAL LETTER BETA
+\setXTXcharcodes "0A7B5 "0A7B5 "0A7B5 % LATIN SMALL LETTER BETA
+\setXTXcharcodes "0A7B6 "0A7B6 "0A7B6 % LATIN CAPITAL LETTER OMEGA
+\setXTXcharcodes "0A7B7 "0A7B7 "0A7B7 % LATIN SMALL LETTER OMEGA
+\setXTXcharcodes "0A7FA "0A7FA "0A7FA % LATIN LETTER SMALL CAPITAL TURNED M
+\setXTXcharcodes "0AB30 "0AB30 "0AB30 % LATIN SMALL LETTER BARRED ALPHA
+\setXTXcharcodes "0AB31 "0AB31 "0AB31 % LATIN SMALL LETTER A REVERSED-SCHWA
+\setXTXcharcodes "0AB32 "0AB32 "0AB32 % LATIN SMALL LETTER BLACKLETTER E
+\setXTXcharcodes "0AB33 "0AB33 "0AB33 % LATIN SMALL LETTER BARRED E
+\setXTXcharcodes "0AB34 "0AB34 "0AB34 % LATIN SMALL LETTER E WITH FLOURISH
+\setXTXcharcodes "0AB35 "0AB35 "0AB35 % LATIN SMALL LETTER LENIS F
+\setXTXcharcodes "0AB36 "0AB36 "0AB36 % LATIN SMALL LETTER SCRIPT G WITH CROSSED-TAIL
+\setXTXcharcodes "0AB37 "0AB37 "0AB37 % LATIN SMALL LETTER L WITH INVERTED LAZY S
+\setXTXcharcodes "0AB38 "0AB38 "0AB38 % LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE
+\setXTXcharcodes "0AB39 "0AB39 "0AB39 % LATIN SMALL LETTER L WITH MIDDLE RING
+\setXTXcharcodes "0AB3A "0AB3A "0AB3A % LATIN SMALL LETTER M WITH CROSSED-TAIL
+\setXTXcharcodes "0AB3B "0AB3B "0AB3B % LATIN SMALL LETTER N WITH CROSSED-TAIL
+\setXTXcharcodes "0AB3C "0AB3C "0AB3C % LATIN SMALL LETTER ENG WITH CROSSED-TAIL
+\setXTXcharcodes "0AB3D "0AB3D "0AB3D % LATIN SMALL LETTER BLACKLETTER O
+\setXTXcharcodes "0AB3E "0AB3E "0AB3E % LATIN SMALL LETTER BLACKLETTER O WITH STROKE
+\setXTXcharcodes "0AB3F "0AB3F "0AB3F % LATIN SMALL LETTER OPEN O WITH STROKE
+\setXTXcharcodes "0AB40 "0AB40 "0AB40 % LATIN SMALL LETTER INVERTED OE
+\setXTXcharcodes "0AB41 "0AB41 "0AB41 % LATIN SMALL LETTER TURNED OE WITH STROKE
+\setXTXcharcodes "0AB42 "0AB42 "0AB42 % LATIN SMALL LETTER TURNED OE WITH HORIZONTAL STROKE
+\setXTXcharcodes "0AB43 "0AB43 "0AB43 % LATIN SMALL LETTER TURNED O OPEN-O
+\setXTXcharcodes "0AB44 "0AB44 "0AB44 % LATIN SMALL LETTER TURNED O OPEN-O WITH STROKE
+\setXTXcharcodes "0AB45 "0AB45 "0AB45 % LATIN SMALL LETTER STIRRUP R
+\setXTXcharcodes "0AB46 "0AB46 "0AB46 % LATIN LETTER SMALL CAPITAL R WITH RIGHT LEG
+\setXTXcharcodes "0AB47 "0AB47 "0AB47 % LATIN SMALL LETTER R WITHOUT HANDLE
+\setXTXcharcodes "0AB48 "0AB48 "0AB48 % LATIN SMALL LETTER DOUBLE R
+\setXTXcharcodes "0AB49 "0AB49 "0AB49 % LATIN SMALL LETTER R WITH CROSSED-TAIL
+\setXTXcharcodes "0AB4A "0AB4A "0AB4A % LATIN SMALL LETTER DOUBLE R WITH CROSSED-TAIL
+\setXTXcharcodes "0AB4B "0AB4B "0AB4B % LATIN SMALL LETTER SCRIPT R
+\setXTXcharcodes "0AB4C "0AB4C "0AB4C % LATIN SMALL LETTER SCRIPT R WITH RING
+\setXTXcharcodes "0AB4D "0AB4D "0AB4D % LATIN SMALL LETTER BASELINE ESH
+\setXTXcharcodes "0AB4E "0AB4E "0AB4E % LATIN SMALL LETTER U WITH SHORT RIGHT LEG
+\setXTXcharcodes "0AB4F "0AB4F "0AB4F % LATIN SMALL LETTER U BAR WITH SHORT RIGHT LEG
+\setXTXcharcodes "0AB50 "0AB50 "0AB50 % LATIN SMALL LETTER UI
+\setXTXcharcodes "0AB51 "0AB51 "0AB51 % LATIN SMALL LETTER TURNED UI
+\setXTXcharcodes "0AB52 "0AB52 "0AB52 % LATIN SMALL LETTER U WITH LEFT HOOK
+\setXTXcharcodes "0AB53 "0AB53 "0AB53 % LATIN SMALL LETTER CHI
+\setXTXcharcodes "0AB54 "0AB54 "0AB54 % LATIN SMALL LETTER CHI WITH LOW RIGHT RING
+\setXTXcharcodes "0AB55 "0AB55 "0AB55 % LATIN SMALL LETTER CHI WITH LOW LEFT SERIF
+\setXTXcharcodes "0AB56 "0AB56 "0AB56 % LATIN SMALL LETTER X WITH LOW RIGHT RING
+\setXTXcharcodes "0AB57 "0AB57 "0AB57 % LATIN SMALL LETTER X WITH LONG LEFT LEG
+\setXTXcharcodes "0AB58 "0AB58 "0AB58 % LATIN SMALL LETTER X WITH LONG LEFT LEG AND LOW RIGHT RING
+\setXTXcharcodes "0AB59 "0AB59 "0AB59 % LATIN SMALL LETTER X WITH LONG LEFT LEG WITH SERIF
+\setXTXcharcodes "0AB5A "0AB5A "0AB5A % LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
+\setXTXcharcodes "0AB60 "0AB60 "0AB60 % LATIN SMALL LETTER SAKHA YAT
+\setXTXcharcodes "0AB61 "0AB61 "0AB61 % LATIN SMALL LETTER IOTIFIED E
+\setXTXcharcodes "0AB62 "0AB62 "0AB62 % LATIN SMALL LETTER OPEN OE
+\setXTXcharcodes "0AB63 "0AB63 "0AB63 % LATIN SMALL LETTER UO
+\setXTXcharcodes "0AB64 "0AB64 "0AB64 % LATIN SMALL LETTER INVERTED ALPHA
+\setXTXcharcodes "0AB65 "0AB65 "0AB65 % GREEK LETTER SMALL CAPITAL OMEGA
+\setXTXcharcodes "0AB70 "0AB70 "0AB70 % CHEROKEE SMALL LETTER A
+\setXTXcharcodes "0AB71 "0AB71 "0AB71 % CHEROKEE SMALL LETTER E
+\setXTXcharcodes "0AB72 "0AB72 "0AB72 % CHEROKEE SMALL LETTER I
+\setXTXcharcodes "0AB73 "0AB73 "0AB73 % CHEROKEE SMALL LETTER O
+\setXTXcharcodes "0AB74 "0AB74 "0AB74 % CHEROKEE SMALL LETTER U
+\setXTXcharcodes "0AB75 "0AB75 "0AB75 % CHEROKEE SMALL LETTER V
+\setXTXcharcodes "0AB76 "0AB76 "0AB76 % CHEROKEE SMALL LETTER GA
+\setXTXcharcodes "0AB77 "0AB77 "0AB77 % CHEROKEE SMALL LETTER KA
+\setXTXcharcodes "0AB78 "0AB78 "0AB78 % CHEROKEE SMALL LETTER GE
+\setXTXcharcodes "0AB79 "0AB79 "0AB79 % CHEROKEE SMALL LETTER GI
+\setXTXcharcodes "0AB7A "0AB7A "0AB7A % CHEROKEE SMALL LETTER GO
+\setXTXcharcodes "0AB7B "0AB7B "0AB7B % CHEROKEE SMALL LETTER GU
+\setXTXcharcodes "0AB7C "0AB7C "0AB7C % CHEROKEE SMALL LETTER GV
+\setXTXcharcodes "0AB7D "0AB7D "0AB7D % CHEROKEE SMALL LETTER HA
+\setXTXcharcodes "0AB7E "0AB7E "0AB7E % CHEROKEE SMALL LETTER HE
+\setXTXcharcodes "0AB7F "0AB7F "0AB7F % CHEROKEE SMALL LETTER HI
+\setXTXcharcodes "0AB80 "0AB80 "0AB80 % CHEROKEE SMALL LETTER HO
+\setXTXcharcodes "0AB81 "0AB81 "0AB81 % CHEROKEE SMALL LETTER HU
+\setXTXcharcodes "0AB82 "0AB82 "0AB82 % CHEROKEE SMALL LETTER HV
+\setXTXcharcodes "0AB83 "0AB83 "0AB83 % CHEROKEE SMALL LETTER LA
+\setXTXcharcodes "0AB84 "0AB84 "0AB84 % CHEROKEE SMALL LETTER LE
+\setXTXcharcodes "0AB85 "0AB85 "0AB85 % CHEROKEE SMALL LETTER LI
+\setXTXcharcodes "0AB86 "0AB86 "0AB86 % CHEROKEE SMALL LETTER LO
+\setXTXcharcodes "0AB87 "0AB87 "0AB87 % CHEROKEE SMALL LETTER LU
+\setXTXcharcodes "0AB88 "0AB88 "0AB88 % CHEROKEE SMALL LETTER LV
+\setXTXcharcodes "0AB89 "0AB89 "0AB89 % CHEROKEE SMALL LETTER MA
+\setXTXcharcodes "0AB8A "0AB8A "0AB8A % CHEROKEE SMALL LETTER ME
+\setXTXcharcodes "0AB8B "0AB8B "0AB8B % CHEROKEE SMALL LETTER MI
+\setXTXcharcodes "0AB8C "0AB8C "0AB8C % CHEROKEE SMALL LETTER MO
+\setXTXcharcodes "0AB8D "0AB8D "0AB8D % CHEROKEE SMALL LETTER MU
+\setXTXcharcodes "0AB8E "0AB8E "0AB8E % CHEROKEE SMALL LETTER NA
+\setXTXcharcodes "0AB8F "0AB8F "0AB8F % CHEROKEE SMALL LETTER HNA
+\setXTXcharcodes "0AB90 "0AB90 "0AB90 % CHEROKEE SMALL LETTER NAH
+\setXTXcharcodes "0AB91 "0AB91 "0AB91 % CHEROKEE SMALL LETTER NE
+\setXTXcharcodes "0AB92 "0AB92 "0AB92 % CHEROKEE SMALL LETTER NI
+\setXTXcharcodes "0AB93 "0AB93 "0AB93 % CHEROKEE SMALL LETTER NO
+\setXTXcharcodes "0AB94 "0AB94 "0AB94 % CHEROKEE SMALL LETTER NU
+\setXTXcharcodes "0AB95 "0AB95 "0AB95 % CHEROKEE SMALL LETTER NV
+\setXTXcharcodes "0AB96 "0AB96 "0AB96 % CHEROKEE SMALL LETTER QUA
+\setXTXcharcodes "0AB97 "0AB97 "0AB97 % CHEROKEE SMALL LETTER QUE
+\setXTXcharcodes "0AB98 "0AB98 "0AB98 % CHEROKEE SMALL LETTER QUI
+\setXTXcharcodes "0AB99 "0AB99 "0AB99 % CHEROKEE SMALL LETTER QUO
+\setXTXcharcodes "0AB9A "0AB9A "0AB9A % CHEROKEE SMALL LETTER QUU
+\setXTXcharcodes "0AB9B "0AB9B "0AB9B % CHEROKEE SMALL LETTER QUV
+\setXTXcharcodes "0AB9C "0AB9C "0AB9C % CHEROKEE SMALL LETTER SA
+\setXTXcharcodes "0AB9D "0AB9D "0AB9D % CHEROKEE SMALL LETTER S
+\setXTXcharcodes "0AB9E "0AB9E "0AB9E % CHEROKEE SMALL LETTER SE
+\setXTXcharcodes "0AB9F "0AB9F "0AB9F % CHEROKEE SMALL LETTER SI
+\setXTXcharcodes "0ABA0 "0ABA0 "0ABA0 % CHEROKEE SMALL LETTER SO
+\setXTXcharcodes "0ABA1 "0ABA1 "0ABA1 % CHEROKEE SMALL LETTER SU
+\setXTXcharcodes "0ABA2 "0ABA2 "0ABA2 % CHEROKEE SMALL LETTER SV
+\setXTXcharcodes "0ABA3 "0ABA3 "0ABA3 % CHEROKEE SMALL LETTER DA
+\setXTXcharcodes "0ABA4 "0ABA4 "0ABA4 % CHEROKEE SMALL LETTER TA
+\setXTXcharcodes "0ABA5 "0ABA5 "0ABA5 % CHEROKEE SMALL LETTER DE
+\setXTXcharcodes "0ABA6 "0ABA6 "0ABA6 % CHEROKEE SMALL LETTER TE
+\setXTXcharcodes "0ABA7 "0ABA7 "0ABA7 % CHEROKEE SMALL LETTER DI
+\setXTXcharcodes "0ABA8 "0ABA8 "0ABA8 % CHEROKEE SMALL LETTER TI
+\setXTXcharcodes "0ABA9 "0ABA9 "0ABA9 % CHEROKEE SMALL LETTER DO
+\setXTXcharcodes "0ABAA "0ABAA "0ABAA % CHEROKEE SMALL LETTER DU
+\setXTXcharcodes "0ABAB "0ABAB "0ABAB % CHEROKEE SMALL LETTER DV
+\setXTXcharcodes "0ABAC "0ABAC "0ABAC % CHEROKEE SMALL LETTER DLA
+\setXTXcharcodes "0ABAD "0ABAD "0ABAD % CHEROKEE SMALL LETTER TLA
+\setXTXcharcodes "0ABAE "0ABAE "0ABAE % CHEROKEE SMALL LETTER TLE
+\setXTXcharcodes "0ABAF "0ABAF "0ABAF % CHEROKEE SMALL LETTER TLI
+\setXTXcharcodes "0ABB0 "0ABB0 "0ABB0 % CHEROKEE SMALL LETTER TLO
+\setXTXcharcodes "0ABB1 "0ABB1 "0ABB1 % CHEROKEE SMALL LETTER TLU
+\setXTXcharcodes "0ABB2 "0ABB2 "0ABB2 % CHEROKEE SMALL LETTER TLV
+\setXTXcharcodes "0ABB3 "0ABB3 "0ABB3 % CHEROKEE SMALL LETTER TSA
+\setXTXcharcodes "0ABB4 "0ABB4 "0ABB4 % CHEROKEE SMALL LETTER TSE
+\setXTXcharcodes "0ABB5 "0ABB5 "0ABB5 % CHEROKEE SMALL LETTER TSI
+\setXTXcharcodes "0ABB6 "0ABB6 "0ABB6 % CHEROKEE SMALL LETTER TSO
+\setXTXcharcodes "0ABB7 "0ABB7 "0ABB7 % CHEROKEE SMALL LETTER TSU
+\setXTXcharcodes "0ABB8 "0ABB8 "0ABB8 % CHEROKEE SMALL LETTER TSV
+\setXTXcharcodes "0ABB9 "0ABB9 "0ABB9 % CHEROKEE SMALL LETTER WA
+\setXTXcharcodes "0ABBA "0ABBA "0ABBA % CHEROKEE SMALL LETTER WE
+\setXTXcharcodes "0ABBB "0ABBB "0ABBB % CHEROKEE SMALL LETTER WI
+\setXTXcharcodes "0ABBC "0ABBC "0ABBC % CHEROKEE SMALL LETTER WO
+\setXTXcharcodes "0ABBD "0ABBD "0ABBD % CHEROKEE SMALL LETTER WU
+\setXTXcharcodes "0ABBE "0ABBE "0ABBE % CHEROKEE SMALL LETTER WV
+\setXTXcharcodes "0ABBF "0ABBF "0ABBF % CHEROKEE SMALL LETTER YA
 \setXTXcharcodes "0FB00 "0FB00 "0FB00 % LATIN SMALL LIGATURE FF
 \setXTXcharcodes "0FB01 "0FB01 "0FB01 % LATIN SMALL LIGATURE FI
 \setXTXcharcodes "0FB02 "0FB02 "0FB02 % LATIN SMALL LIGATURE FL
@@ -1976,10 +2400,6 @@
 \setXTXcharcodes "0FF59 "0FF59 "0FF39 % FULLWIDTH LATIN SMALL LETTER Y
 \setXTXcharcodes "0FF5A "0FF5A "0FF3A % FULLWIDTH LATIN SMALL LETTER Z
 
-\dofastrecurse{"03400}{"04DB5}{1}{\dosetXTXcharcodes\recurselevel\recurselevel\recurselevel}
-\dofastrecurse{"04E00}{"09FBB}{1}{\dosetXTXcharcodes\recurselevel\recurselevel\recurselevel}
-\dofastrecurse{"0AC00}{"0D7A3}{1}{\dosetXTXcharcodes\recurselevel\recurselevel\recurselevel}
-\dofastrecurse{"20000}{"2A6D6}{1}{\dosetXTXcharcodes\recurselevel\recurselevel\recurselevel}
 
 % patch needed for turkish
 
@@ -1988,7 +2408,7 @@
 
 % patch needed for french
 
-% \setXTXcharcodes "0027 "0027 "0027
 \setXTXcharcodes "2019 "2019 "2019
 
+
 \endinput
diff --git a/tex/generic/context/luatex/luatex-basics-nod.lua b/tex/generic/context/luatex/luatex-basics-nod.lua
index 39400a3d0..32d7da00e 100644
--- a/tex/generic/context/luatex/luatex-basics-nod.lua
+++ b/tex/generic/context/luatex/luatex-basics-nod.lua
@@ -51,17 +51,23 @@ nodes              = { }
 nodes.pool         = { }
 nodes.handlers     = { }
 
-local nodecodes    = { } for k,v in next, node.types   () do nodecodes[string.gsub(v,"_","")] = k end
-local whatcodes    = { } for k,v in next, node.whatsits() do whatcodes[string.gsub(v,"_","")] = k end
-local glyphcodes   = { [0] = "character", "glyph", "ligature", "ghost", "left", "right" }
-local disccodes    = { [0] = "discretionary", "explicit", "automatic", "regular", "first", "second" }
-
-for i=0,#glyphcodes do glyphcodes[glyphcodes[i]] = i end
-for i=0,#disccodes  do disccodes [disccodes [i]] = i end
+local nodecodes    = { }
+local glyphcodes   = node.subtypes("glyph")
+local disccodes    = node.subtypes("disc")
+
+for k, v in next, node.types() do
+    v = string.gsub(v,"_","")
+    nodecodes[k] = v
+    nodecodes[v] = k
+end
+for i=0,#glyphcodes do
+    glyphcodes[glyphcodes[i]] = i
+end
+for i=0,#disccodes do
+    disccodes[disccodes[i]] = i
+end
 
 nodes.nodecodes    = nodecodes
-nodes.whatcodes    = whatcodes
-nodes.whatsitcodes = whatcodes
 nodes.glyphcodes   = glyphcodes
 nodes.disccodes    = disccodes
 
@@ -140,7 +146,6 @@ nodes.slide                = node.slide
 nodes.vpack                = node.vpack
 
 nodes.first_glyph          = node.first_glyph
-nodes.first_character      = node.first_character
 nodes.has_glyph            = node.has_glyph or node.first_glyph
 
 nodes.current_attr         = node.current_attr
@@ -178,7 +183,6 @@ nodes.tonut              = tonut
 nuts.tonode              = tonode
 nuts.tonut               = tonut
 
-
 local getfield           = direct.getfield
 local setfield           = direct.setfield
 
@@ -187,7 +191,7 @@ nuts.setfield            = setfield
 nuts.getnext             = direct.getnext
 nuts.getprev             = direct.getprev
 nuts.getid               = direct.getid
-nuts.getattr             = getfield
+nuts.getattr             = direct.get_attribute or direct.has_attribute or getfield
 nuts.setattr             = setfield
 nuts.getfont             = direct.getfont
 nuts.getsubtype          = direct.getsubtype
@@ -206,6 +210,9 @@ nuts.is_node             = direct.is_node
 nuts.end_of_math         = direct.end_of_math
 nuts.traverse            = direct.traverse
 nuts.traverse_id         = direct.traverse_id
+nuts.traverse_char       = direct.traverse_char
+nuts.ligaturing          = direct.ligaturing
+nuts.kerning             = direct.kerning
 
 nuts.getprop             = nuts.getattr
 nuts.setprop             = nuts.setattr
diff --git a/tex/generic/context/luatex/luatex-fonts-def.lua b/tex/generic/context/luatex/luatex-fonts-def.lua
index 0c2f0dbd5..f0941ecdc 100644
--- a/tex/generic/context/luatex/luatex-fonts-def.lua
+++ b/tex/generic/context/luatex/luatex-fonts-def.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['luatex-font-def'] = {
+if not modules then modules = { } end modules ['luatex-fonts-def'] = {
     version   = 1.001,
     comment   = "companion to luatex-*.tex",
     author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/generic/context/luatex/luatex-fonts-inj.lua b/tex/generic/context/luatex/luatex-fonts-inj.lua
deleted file mode 100644
index 36781f72f..000000000
--- a/tex/generic/context/luatex/luatex-fonts-inj.lua
+++ /dev/null
@@ -1,1152 +0,0 @@
-if not modules then modules = { } end modules ['font-inj'] = {
-    version   = 1.001,
-    comment   = "companion to font-lib.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files",
-}
-
--- This property based variant is not faster but looks nicer than the attribute one. We
--- need to use rawget (which is apbout 4 times slower than a direct access but we cannot
--- get/set that one for our purpose! This version does a bit more with discretionaries
--- (and Kai has tested it with his collection of weird fonts.)
-
--- There is some duplicate code here (especially in the the pre/post/replace branches) but
--- we go for speed. We could store a list of glyph and mark nodes when registering but it's
--- cleaner to have an identification pass here. Also, I need to keep tracing in mind so
--- being too clever here is dangerous.
-
--- The subtype test is not needed as there will be no (new) properties set, given that we
--- reset the properties.
-
-if not nodes.properties then return end
-
-local next, rawget = next, rawget
-local utfchar = utf.char
-local fastcopy = table.fastcopy
-
-local trace_injections = false  trackers.register("fonts.injections", function(v) trace_injections = v end)
-
-local report_injections = logs.reporter("fonts","injections")
-
-local attributes, nodes, node = attributes, nodes, node
-
-fonts                    = fonts
-local fontdata           = fonts.hashes.identifiers
-
-nodes.injections         = nodes.injections or { }
-local injections         = nodes.injections
-
-local nodecodes          = nodes.nodecodes
-local glyph_code         = nodecodes.glyph
-local disc_code          = nodecodes.disc
-local kern_code          = nodecodes.kern
-
-local nuts               = nodes.nuts
-local nodepool           = nuts.pool
-
-local newkern            = nodepool.kern
-
-local tonode             = nuts.tonode
-local tonut              = nuts.tonut
-
-local getfield           = nuts.getfield
-local setfield           = nuts.setfield
-local getnext            = nuts.getnext
-local getprev            = nuts.getprev
-local getid              = nuts.getid
-local getfont            = nuts.getfont
-local getsubtype         = nuts.getsubtype
-local getchar            = nuts.getchar
-
-local traverse_id        = nuts.traverse_id
-local insert_node_before = nuts.insert_before
-local insert_node_after  = nuts.insert_after
-local find_tail          = nuts.tail
-
-local properties         = nodes.properties.data
-
-function injections.installnewkern(nk)
-    newkern = nk or newkern
-end
-
-local nofregisteredkerns    = 0
-local nofregisteredpairs    = 0
-local nofregisteredmarks    = 0
-local nofregisteredcursives = 0
------ markanchors           = { } -- one base can have more marks
-local keepregisteredcounts  = false
-
-function injections.keepcounts()
-    keepregisteredcounts = true
-end
-
-function injections.resetcounts()
-    nofregisteredkerns    = 0
-    nofregisteredpairs    = 0
-    nofregisteredmarks    = 0
-    nofregisteredcursives = 0
-    keepregisteredcounts  = false
-end
-
--- We need to make sure that a possible metatable will not kick in unexpectedly.
-
-function injections.reset(n)
-    local p = rawget(properties,n)
-    if p and rawget(p,"injections") then
-        p.injections = nil
-    end
-end
-
-function injections.copy(target,source)
-    local sp = rawget(properties,source)
-    if sp then
-        local tp = rawget(properties,target)
-        local si = rawget(sp,"injections")
-        if si then
-            si = fastcopy(si)
-            if tp then
-                tp.injections = si
-            else
-                propertydata[target] = {
-                    injections = si,
-                }
-            end
-        else
-            if tp then
-                tp.injections = nil
-            end
-        end
-    end
-end
-
-function injections.setligaindex(n,index)
-    local p = rawget(properties,n)
-    if p then
-        local i = rawget(p,"injections")
-        if i then
-            i.ligaindex = index
-        else
-            p.injections = {
-                ligaindex = index
-            }
-        end
-    else
-        properties[n] = {
-            injections = {
-                ligaindex = index
-            }
-        }
-    end
-end
-
-function injections.getligaindex(n,default)
-    local p = rawget(properties,n)
-    if p then
-        local i = rawget(p,"injections")
-        if i then
-            return i.ligaindex or default
-        end
-    end
-    return default
-end
-
-function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -- hm: nuts or nodes
-    local dx =  factor*(exit[1]-entry[1])
-    local dy = -factor*(exit[2]-entry[2])
-    local ws = tfmstart.width
-    local wn = tfmnext.width
-    nofregisteredcursives = nofregisteredcursives + 1
-    if rlmode < 0 then
-        dx = -(dx + wn)
-    else
-        dx = dx - ws
-    end
-    --
-    local p = rawget(properties,start)
-    if p then
-        local i = rawget(p,"injections")
-        if i then
-            i.cursiveanchor = true
-        else
-            p.injections = {
-                cursiveanchor = true,
-            }
-        end
-    else
-        properties[start] = {
-            injections = {
-                cursiveanchor = true,
-            },
-        }
-    end
-    local p = rawget(properties,nxt)
-    if p then
-        local i = rawget(p,"injections")
-        if i then
-            i.cursivex = dx
-            i.cursivey = dy
-        else
-            p.injections = {
-                cursivex = dx,
-                cursivey = dy,
-            }
-        end
-    else
-        properties[nxt] = {
-            injections = {
-                cursivex = dx,
-                cursivey = dy,
-            },
-        }
-    end
-    return dx, dy, nofregisteredcursives
-end
-
-function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2lflag & tfmchr not used
-    local x = factor*spec[1]
-    local y = factor*spec[2]
-    local w = factor*spec[3]
-    local h = factor*spec[4]
-    if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then -- okay?
-        local yoffset   = y - h
-        local leftkern  = x      -- both kerns are set in a pair kern compared
-        local rightkern = w - x  -- to normal kerns where we set only leftkern
-        if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then
-            nofregisteredpairs = nofregisteredpairs + 1
-            if rlmode and rlmode < 0 then
-                leftkern, rightkern = rightkern, leftkern
-            end
-            if not injection then
-                injection = "injections"
-            end
-            local p = rawget(properties,current)
-            if p then
-                local i = rawget(p,injection)
-                if i then
-                    if leftkern ~= 0 then
-                        i.leftkern  = (i.leftkern  or 0) + leftkern
-                    end
-                    if rightkern ~= 0 then
-                        i.rightkern = (i.rightkern or 0) + rightkern
-                    end
-                    if yoffset ~= 0 then
-                        i.yoffset = (i.yoffset or 0) + yoffset
-                    end
-                elseif leftkern ~= 0 or rightkern ~= 0 then
-                    p[injection] = {
-                        leftkern  = leftkern,
-                        rightkern = rightkern,
-                        yoffset   = yoffset,
-                    }
-                else
-                    p[injection] = {
-                        yoffset = yoffset,
-                    }
-                end
-            elseif leftkern ~= 0 or rightkern ~= 0 then
-                properties[current] = {
-                    [injection] = {
-                        leftkern  = leftkern,
-                        rightkern = rightkern,
-                        yoffset   = yoffset,
-                    },
-                }
-            else
-                properties[current] = {
-                    [injection] = {
-                        yoffset = yoffset,
-                    },
-                }
-            end
-            return x, y, w, h, nofregisteredpairs
-         end
-    end
-    return x, y, w, h -- no bound
-end
-
--- This needs checking for rl < 0 but it is unlikely that a r2l script uses kernclasses between
--- glyphs so we're probably safe (KE has a problematic font where marks interfere with rl < 0 in
--- the previous case)
-
-function injections.setkern(current,factor,rlmode,x,injection)
-    local dx = factor * x
-    if dx ~= 0 then
-        nofregisteredkerns = nofregisteredkerns + 1
-        local p = rawget(properties,current)
-        if not injection then
-            injection = "injections"
-        end
-        if p then
-            local i = rawget(p,injection)
-            if i then
-                i.leftkern = dx + (i.leftkern or 0)
-            else
-                p[injection] = {
-                    leftkern = dx,
-                }
-            end
-        else
-            properties[current] = {
-                [injection] = {
-                    leftkern = dx,
-                },
-            }
-        end
-        return dx, nofregisteredkerns
-    else
-        return 0, 0
-    end
-end
-
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
-    local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
-    nofregisteredmarks = nofregisteredmarks + 1
- -- markanchors[nofregisteredmarks] = base
-    if rlmode >= 0 then
-        dx = tfmbase.width - dx -- see later commented ox
-    end
-    local p = rawget(properties,start)
-    -- hm, dejavu serif does a sloppy mark2mark before mark2base
-    if p then
-        local i = rawget(p,"injections")
-        if i then
-            if i.markmark then
-                -- out of order mkmk: yes or no or option
-            else
-                i.markx        = dx
-                i.marky        = dy
-                i.markdir      = rlmode or 0
-                i.markbase     = nofregisteredmarks
-                i.markbasenode = base
-                i.markmark     = mkmk
-            end
-        else
-            p.injections = {
-                markx        = dx,
-                marky        = dy,
-                markdir      = rlmode or 0,
-                markbase     = nofregisteredmarks,
-                markbasenode = base,
-                markmark     = mkmk,
-            }
-        end
-    else
-        properties[start] = {
-            injections = {
-                markx        = dx,
-                marky        = dy,
-                markdir      = rlmode or 0,
-                markbase     = nofregisteredmarks,
-                markbasenode = base,
-                markmark     = mkmk,
-            },
-        }
-    end
-    return dx, dy, nofregisteredmarks
-end
-
-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 showchar(n,nested)
-    local char = getchar(n)
-    report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char)
-end
-
-local function show(n,what,nested,symbol)
-    if n then
-        local p = rawget(properties,n)
-        if p then
-            local i = rawget(p,what)
-            if i then
-                local leftkern  = i.leftkern  or 0
-                local rightkern = i.rightkern or 0
-                local yoffset   = i.yoffset   or 0
-                local markx     = i.markx     or 0
-                local marky     = i.marky     or 0
-                local markdir   = i.markdir   or 0
-                local markbase  = i.markbase  or 0 -- will be markbasenode
-                local cursivex  = i.cursivex  or 0
-                local cursivey  = i.cursivey  or 0
-                local ligaindex = i.ligaindex or 0
-                local margin    = nested and 4 or 2
-                --
-                if rightkern ~= 0 or yoffset ~= 0 then
-                    report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
-                elseif leftkern ~= 0 then
-                    report_injections("%w%s kern: dx %p",margin,symbol,leftkern)
-                end
-                if markx ~= 0 or marky ~= 0 or markbase ~= 0 then
-                    report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no")
-                end
-                if cursivex ~= 0 or cursivey ~= 0 then
-                    report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
-                end
-                if ligaindex ~= 0 then
-                    report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
-                end
-            end
-        end
-    end
-end
-
-local function showsub(n,what,where)
-    report_injections("begin subrun: %s",where)
-    for n in traverse_id(glyph_code,n) do
-        showchar(n,where)
-        show(n,what,where," ")
-    end
-    report_injections("end subrun")
-end
-
-local function trace(head,where)
-    report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered",
-        where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives)
-    local n = head
-    while n do
-        local id = getid(n)
-        if id == glyph_code then
-            showchar(n)
-            show(n,"injections",false," ")
-            show(n,"preinjections",false,"<")
-            show(n,"postinjections",false,">")
-            show(n,"replaceinjections",false,"=")
-        elseif id == disc_code then
-            local pre     = getfield(n,"pre")
-            local post    = getfield(n,"post")
-            local replace = getfield(n,"replace")
-            if pre then
-                showsub(pre,"preinjections","pre")
-            end
-            if post then
-                showsub(post,"postinjections","post")
-            end
-            if replace then
-                showsub(replace,"replaceinjections","replace")
-            end
-        end
-        n = getnext(n)
-    end
-    report_injections("end run")
-end
-
-local function show_result(head)
-    local current  = head
-    local skipping = false
-    while current do
-        local id = getid(current)
-        if id == glyph_code then
-            report_injections("char: %C, width %p, xoffset %p, yoffset %p",
-                getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
-            skipping = false
-        elseif id == kern_code then
-            report_injections("kern: %p",getfield(current,"kern"))
-            skipping = false
-        elseif not skipping then
-            report_injections()
-            skipping = true
-        end
-        current = getnext(current)
-    end
-end
-
-local function collect_glyphs(head,offsets)
-    local glyphs, glyphi, nofglyphs = { }, { }, 0
-    local marks, marki, nofmarks = { }, { }, 0
-    local nf, tm = nil, nil
-    local n = head
-
-    local function identify(n,what)
-        local f = getfont(n)
-        if f ~= nf then
-            nf = f
-            -- other hash in ctx:
-            tm = fontdata[nf].resources
-            if tm then
-                tm = tm.marks
-            end
-        end
-        if tm and tm[getchar(n)] then
-            nofmarks = nofmarks + 1
-            marks[nofmarks] = n
-            marki[nofmarks] = "injections"
-        else
-            nofglyphs = nofglyphs + 1
-            glyphs[nofglyphs] = n
-            glyphi[nofglyphs] = what
-        end
-        if offsets then
-            -- yoffsets can influence curs steps
-            local p = rawget(properties,n)
-            if p then
-                local i = rawget(p,what)
-                if i then
-                    local yoffset = i.yoffset
-                    if yoffset and yoffset ~= 0 then
-                        setfield(n,"yoffset",yoffset)
-                    end
-                end
-            end
-        end
-    end
-
-    while n do -- only needed for relevant fonts
-        local id = getid(n)
-        if id == glyph_code then
-            identify(n,"injections")
-        elseif id == disc_code then
-            local d = getfield(n,"pre")
-            if d then
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        identify(n,"preinjections")
-                    end
-                end
-			end
-            local d = getfield(n,"post")
-            if d then
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        identify(n,"postinjections")
-                    end
-                end
-			end
-            local d = getfield(n,"replace")
-            if d then
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        identify(n,"replaceinjections")
-                    end
-                end
-			end
-        end
-		n = getnext(n)
-    end
-
-    return glyphs, glyphi, nofglyphs, marks, marki, nofmarks
-end
-
-local function inject_marks(marks,marki,nofmarks)
-    for i=1,nofmarks do
-        local n  = marks[i]
-        local pn = rawget(properties,n)
-        if pn then
-            local ni = marki[i]
-            local pn = rawget(pn,ni)
-            if pn then
-                local p = pn.markbasenode
-                if p then
-                    local px = getfield(p,"xoffset")
-                    local ox = 0
-                    local rightkern = nil
-                    local pp = rawget(properties,p)
-                    if pp then
-                        pp = rawget(pp,ni)
-                        if pp then
-                            rightkern = pp.rightkern
-                        end
-                    end
-                    if rightkern then -- x and w ~= 0
-                        if pn.markdir < 0 then
-                            -- kern(w-x) glyph(p) kern(x) mark(n)
-                            ox = px - pn.markx - rightkern
-                         -- report_injections("r2l case 1: %p",ox)
-                        else
-                            -- kern(x) glyph(p) kern(w-x) mark(n)
-                         -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
-                            --
-							-- According to Kai we don't need to handle leftkern here but I'm
-                            -- pretty sure I've run into a case where it was needed so maybe
-	                        -- some day we need something more clever here.
-                            --
-							if false then
-                                -- a mark with kerning
-                                local leftkern = pp.leftkern
-                                if leftkern then
-                                    ox = px - pn.markx - leftkern
-                                else
-                                    ox = px - pn.markx
-                                end
-                            else
-                                ox = px - pn.markx
-                            end
-                        end
-                    else
-                        -- we need to deal with fonts that have marks with width
-                     -- if pn.markdir < 0 then
-                     --     ox = px - pn.markx
-                     --  -- report_injections("r2l case 3: %p",ox)
-                     -- else
-                     --  -- ox = px - getfield(p,"width") + pn.markx
-                            ox = px - pn.markx
-                         -- report_injections("l2r case 3: %p",ox)
-                     -- end
-                        local wn = getfield(n,"width") -- in arial marks have widths
-                        if wn ~= 0 then
-                            -- bad: we should center
-                         -- insert_node_before(head,n,newkern(-wn/2))
-                         -- insert_node_after(head,n,newkern(-wn/2))
-                            pn.leftkern  = -wn/2
-                            pn.rightkern = -wn/2
-                         -- wx[n] = { 0, -wn/2, 0, -wn }
-                        end
-                        -- so far
-                    end
-                    setfield(n,"xoffset",ox)
-                    --
-                    local py = getfield(p,"yoffset")
---                     local oy = 0
---                     if marks[p] then
---                         oy = py + pn.marky
---                     else
---                         oy = getfield(n,"yoffset") + py + pn.marky
---                     end
-                    local oy = getfield(n,"yoffset") + py + pn.marky
-                    setfield(n,"yoffset",oy)
-                else
-                    -- normally this can't happen (only when in trace mode which is a special case anyway)
-                 -- report_injections("missing mark anchor %i",pn.markbase or 0)
-                end
-            end
-        end
-    end
-end
-
-local function inject_cursives(glyphs,glyphi,nofglyphs)
-    local cursiveanchor, lastanchor = nil, nil
-    local minc, maxc, last = 0, 0, nil
-    for i=1,nofglyphs do
-        local n  = glyphs[i]
-        local pn = rawget(properties,n)
-        if pn then
-            pn = rawget(pn,glyphi[i])
-        end
-        if pn then
-            local cursivex = pn.cursivex
-            if cursivex then
-                if cursiveanchor then
-                    if cursivex ~= 0 then
-                        pn.leftkern = (pn.leftkern or 0) + cursivex
-                    end
-                    if lastanchor then
-                        if maxc == 0 then
-                            minc = lastanchor
-                        end
-                        maxc = lastanchor
-                        properties[cursiveanchor].cursivedy = pn.cursivey
-                    end
-                    last = n
-                else
-                    maxc = 0
-                end
-            elseif maxc > 0 then
-                local ny = getfield(n,"yoffset")
-                for i=maxc,minc,-1 do
-                    local ti = glyphs[i]
-                    ny = ny + properties[ti].cursivedy
-                    setfield(ti,"yoffset",ny) -- why not add ?
-                end
-                maxc = 0
-            end
-            if pn.cursiveanchor then
-                cursiveanchor = n
-                lastanchor = i
-            else
-                cursiveanchor = nil
-                lastanchor = nil
-                if maxc > 0 then
-                    local ny = getfield(n,"yoffset")
-                    for i=maxc,minc,-1 do
-                        local ti = glyphs[i]
-                        ny = ny + properties[ti].cursivedy
-                        setfield(ti,"yoffset",ny) -- why not add ?
-                    end
-                    maxc = 0
-                end
-            end
-        elseif maxc > 0 then
-            local ny = getfield(n,"yoffset")
-            for i=maxc,minc,-1 do
-                local ti = glyphs[i]
-                ny = ny + properties[ti].cursivedy
-                setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- ?
-            end
-            maxc = 0
-            cursiveanchor = nil
-            lastanchor = nil
-        end
-     -- if maxc > 0 and not cursiveanchor then
-     --     local ny = getfield(n,"yoffset")
-     --     for i=maxc,minc,-1 do
-     --         local ti = glyphs[i][1]
-     --         ny = ny + properties[ti].cursivedy
-     --         setfield(ti,"yoffset",ny) -- why not add ?
-     --     end
-     --     maxc = 0
-     -- end
-    end
-    if last and maxc > 0 then
-        local ny = getfield(last,"yoffset")
-        for i=maxc,minc,-1 do
-            local ti = glyphs[i]
-            ny = ny + properties[ti].cursivedy
-            setfield(ti,"yoffset",ny) -- why not add ?
-        end
-    end
-end
-
--- G  +D-pre        G
---     D-post+
---    +D-replace+
---
--- G  +D-pre       +D-pre
---     D-post      +D-post
---    +D-replace   +D-replace
-
-local function inject_kerns(head,glist,ilist,length) -- not complete ! compare with inject_kerns_only (but unlikely disc here)
-    for i=1,length do
-        local n  = glist[i]
-        local pn = rawget(properties,n)
-        if pn then
-			local dp = nil
-			local dr = nil
-            local ni = ilist[i]
-            local p  = nil
-			if ni == "injections" then
-				p = getprev(n)
-				if p then
-					local id = getid(p)
-					if id == disc_code then
-						dp = getfield(p,"post")
-						dr = getfield(p,"replace")
-					end
-				end
-			end
-			if dp then
-				local i = rawget(pn,"postinjections")
-				if i then
-					local leftkern = i.leftkern
-					if leftkern and leftkern ~= 0 then
-						local t = find_tail(dp)
-						insert_node_after(dp,t,newkern(leftkern))
-                        setfield(p,"post",dp) -- currently we need to force a tail refresh
-					end
-				end
-			end
-			if dr then
-				local i = rawget(pn,"replaceinjections")
-				if i then
-					local leftkern = i.leftkern
-					if leftkern and leftkern ~= 0 then
-						local t = find_tail(dr)
-						insert_node_after(dr,t,newkern(leftkern))
-                        setfield(p,"replace",dr) -- currently we need to force a tail refresh
-					end
-				end
-			else
-				local i = rawget(pn,ni)
-				if i then
-					local leftkern = i.leftkern
-					if leftkern and leftkern ~= 0 then
-						insert_node_before(head,n,newkern(leftkern)) -- type 0/2
-					end
-					local rightkern = i.rightkern
-					if rightkern and rightkern ~= 0 then
-						insert_node_after(head,n,newkern(rightkern)) -- type 0/2
-					end
-				end
-			end
-        end
-    end
-end
-
-local function inject_everything(head,where)
-    head = tonut(head)
-    if trace_injections then
-        trace(head,"everything")
-    end
-    local glyphs, glyphi, nofglyphs, marks, marki, nofmarks = collect_glyphs(head,nofregisteredpairs > 0)
-    if nofglyphs > 0 then
-        if nofregisteredcursives > 0 then
-            inject_cursives(glyphs,glyphi,nofglyphs)
-        end
-        if nofregisteredmarks > 0 then -- and nofmarks > 0
-            inject_marks(marks,marki,nofmarks)
-        end
-        inject_kerns(head,glyphs,glyphi,nofglyphs)
-    end
-    if nofmarks > 0 then
-        inject_kerns(head,marks,marki,nofmarks)
-	end
-    if keepregisteredcounts then
-        keepregisteredcounts  = false
-    else
-        nofregisteredkerns    = 0
-        nofregisteredpairs    = 0
-        nofregisteredmarks    = 0
-        nofregisteredcursives = 0
-    end
-    return tonode(head), true
-end
-
--- G  +D-pre        G
---     D-post+
---    +D-replace+
---
--- G  +D-pre       +D-pre
---     D-post      +D-post
---    +D-replace   +D-replace
-
-local function inject_kerns_only(head,where)
-    head = tonut(head)
-    if trace_injections then
-        trace(head,"kerns")
-    end
-    local n = head
-    local p = nil -- disc node when non-nil
-    while n do
-        local id = getid(n)
-        if id == glyph_code then
-            if getsubtype(n) < 256 then
-                local pn = rawget(properties,n)
-                if pn then
-                    if p then
-                        local d = getfield(p,"post")
-                        if d then
-                            local i = rawget(pn,"postinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    local t = find_tail(d)
-                                    insert_node_after(d,t,newkern(leftkern))
-                                    setfield(p,"post",d) -- currently we need to force a tail refresh
-                                end
-                            end
-                        end
-                        local d = getfield(p,"replace")
-                        if d then
-                            local i = rawget(pn,"replaceinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    local t = find_tail(d)
-                                    insert_node_after(d,t,newkern(leftkern))
-                                    setfield(p,"replace",d) -- currently we need to force a tail refresh
-                                end
-                            end
-                        else
-                            local i = rawget(pn,"injections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    setfield(p,"replace",newkern(leftkern))
-                                end
-                            end
-                        end
-                    else
-                        -- this is the most common case
-                        local i = rawget(pn,"injections")
-                        if i then
-                            local leftkern = i.leftkern
-                            if leftkern and leftkern ~= 0 then
-                                head = insert_node_before(head,n,newkern(leftkern))
-                            end
-                        end
-                    end
-                end
-            end
-            p = nil
-        elseif id == disc_code then
-            local d = getfield(n,"pre")
-            if d then
-                local h = d
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            local i = rawget(pn,"preinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    h = insert_node_before(h,n,newkern(leftkern))
-                                end
-                            end
-                        end
-                    else
-                        break
-                    end
-                end
-                if h ~= d then
-                    setfield(n,"pre",h)
-                end
-            end
-            local d = getfield(n,"post")
-            if d then
-                local h = d
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            local i = rawget(pn,"postinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    h = insert_node_before(h,n,newkern(leftkern))
-                                end
-                            end
-                        end
-                    else
-                        break
-                    end
-                end
-                if h ~= d then
-                    setfield(n,"post",h)
-                end
-            end
-            local d = getfield(n,"replace")
-            if d then
-                local h = d
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            local i = rawget(pn,"replaceinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    h = insert_node_before(h,n,newkern(leftkern))
-                                end
-                            end
-                        end
-                    else
-                        break
-                    end
-                end
-                if h ~= d then
-                    setfield(n,"replace",h)
-                end
-            end
-            p = n
-        else
-            p = nil
-        end
-        n = getnext(n)
-    end
-    --
-    if keepregisteredcounts then
-        keepregisteredcounts = false
-    else
-        nofregisteredkerns   = 0
-    end
-    return tonode(head), true
-end
-
-local function inject_pairs_only(head,where)
-    head = tonut(head)
-    if trace_injections then
-        trace(head,"pairs")
-    end
-    local n = head
-    local p = nil -- disc node when non-nil
-    while n do
-        local id = getid(n)
-        if id == glyph_code then
-            if getsubtype(n) < 256 then
-                local pn = rawget(properties,n)
-                if pn then
-                    if p then
-                        local d = getfield(p,"post")
-                        if d then
-                            local i = rawget(pn,"postinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    local t = find_tail(d)
-                                    insert_node_after(d,t,newkern(leftkern))
-                                    setfield(p,"post",d) -- currently we need to force a tail refresh
-                                end
-                             -- local rightkern = i.rightkern
-                             -- if rightkern and rightkern ~= 0 then
-                             --     insert_node_after(head,n,newkern(rightkern))
-                             --     n = getnext(n) -- to be checked
-                             -- end
-                            end
-                        end
-                        local d = getfield(p,"replace")
-                        if d then
-                            local i = rawget(pn,"replaceinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    local t = find_tail(d)
-                                    insert_node_after(d,t,newkern(leftkern))
-                                    setfield(p,"replace",d) -- currently we need to force a tail refresh
-                                end
-                             -- local rightkern = i.rightkern
-                             -- if rightkern and rightkern ~= 0 then
-                             --     insert_node_after(head,n,newkern(rightkern))
-                             --     n = getnext(n) -- to be checked
-                             -- end
-                            end
-                        else
-                            local i = rawget(pn,"injections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    setfield(p,"replace",newkern(leftkern))
-                                end
-                             -- local rightkern = i.rightkern
-                             -- if rightkern and rightkern ~= 0 then
-                             --     insert_node_after(head,n,newkern(rightkern))
-                             --     n = getnext(n) -- to be checked
-                             -- end
-                            end
-                        end
-                    else
-                        -- this is the most common case
-                        local i = rawget(pn,"injections")
-                        if i then
-                            local leftkern = i.leftkern
-                            if leftkern and leftkern ~= 0 then
-                                head = insert_node_before(head,n,newkern(leftkern))
-                            end
-                            local rightkern = i.rightkern
-                            if rightkern and rightkern ~= 0 then
-                                insert_node_after(head,n,newkern(rightkern))
-                                n = getnext(n) -- to be checked
-                            end
-                            local yoffset = i.yoffset
-                            if yoffset and yoffset ~= 0 then
-                                setfield(n,"yoffset",yoffset)
-                            end
-                        end
-                    end
-                end
-            end
-            p = nil
-        elseif id == disc_code then
-            local d = getfield(n,"pre")
-            if d then
-                local h = d
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            local i = rawget(pn,"preinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    h = insert_node_before(h,n,newkern(leftkern))
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(head,n,newkern(rightkern))
-                                    n = getnext(n) -- to be checked
-                                end
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                            end
-                        end
-                    else
-                        break
-                    end
-                end
-                if h ~= d then
-                    setfield(n,"pre",h)
-                end
-            end
-            local d = getfield(n,"post")
-            if d then
-                local h = d
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            local i = rawget(pn,"postinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    h = insert_node_before(h,n,newkern(leftkern))
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(head,n,newkern(rightkern))
-                                    n = getnext(n) -- to be checked
-                                end
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                            end
-                        end
-                    else
-                        break
-                    end
-                end
-                if h ~= d then
-                    setfield(n,"post",h)
-                end
-            end
-            local d = getfield(n,"replace")
-            if d then
-                local h = d
-                for n in traverse_id(glyph_code,d) do
-                    if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            local i = rawget(pn,"replaceinjections")
-                            if i then
-                                local leftkern = i.leftkern
-                                if leftkern and leftkern ~= 0 then
-                                    h = insert_node_before(h,n,newkern(leftkern))
-                                end
-                                local rightkern = i.rightkern
-                                if rightkern and rightkern ~= 0 then
-                                    insert_node_after(head,n,newkern(rightkern))
-                                    n = getnext(n) -- to be checked
-                                end
-                                local yoffset = i.yoffset
-                                if yoffset and yoffset ~= 0 then
-                                    setfield(n,"yoffset",yoffset)
-                                end
-                            end
-                        end
-                    else
-                        break
-                    end
-                end
-                if h ~= d then
-                    setfield(n,"replace",h)
-                end
-            end
-            p = n
-        else
-            p = nil
-        end
-        n = getnext(n)
-    end
-    --
-    if keepregisteredcounts then
-        keepregisteredcounts = false
-    else
-        nofregisteredpairs = 0
-        nofregisteredkerns = 0
-    end
-    return tonode(head), true
-end
-
-function injections.handler(head,where)
-    if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
-        return inject_everything(head,where)
-    elseif nofregisteredpairs > 0 then
-        return inject_pairs_only(head,where)
-    elseif nofregisteredkerns > 0 then
-        return inject_kerns_only(head,where)
-    else
-        return head, false
-    end
-end
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index ae366179c..0bc4ee258 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
--- merged file : luatex-fonts-merged.lua
--- parent file : luatex-fonts.lua
--- merge date  : 11/19/15 19:13:15
+-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
+-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
+-- merge date  : 12/17/15 15:57:11
 
 do -- begin closure to overcome local limits and interference
 
@@ -3901,15 +3901,21 @@ end
 nodes={}
 nodes.pool={}
 nodes.handlers={}
-local nodecodes={} for k,v in next,node.types  () do nodecodes[string.gsub(v,"_","")]=k end
-local whatcodes={} for k,v in next,node.whatsits() do whatcodes[string.gsub(v,"_","")]=k end
-local glyphcodes={ [0]="character","glyph","ligature","ghost","left","right" }
-local disccodes={ [0]="discretionary","explicit","automatic","regular","first","second" }
-for i=0,#glyphcodes do glyphcodes[glyphcodes[i]]=i end
-for i=0,#disccodes do disccodes [disccodes [i]]=i end
+local nodecodes={}
+local glyphcodes=node.subtypes("glyph")
+local disccodes=node.subtypes("disc")
+for k,v in next,node.types() do
+  v=string.gsub(v,"_","")
+  nodecodes[k]=v
+  nodecodes[v]=k
+end
+for i=0,#glyphcodes do
+  glyphcodes[glyphcodes[i]]=i
+end
+for i=0,#disccodes do
+  disccodes[disccodes[i]]=i
+end
 nodes.nodecodes=nodecodes
-nodes.whatcodes=whatcodes
-nodes.whatsitcodes=whatcodes
 nodes.glyphcodes=glyphcodes
 nodes.disccodes=disccodes
 local free_node=node.free
@@ -3973,7 +3979,6 @@ nodes.traverse_id=node.traverse_id
 nodes.slide=node.slide
 nodes.vpack=node.vpack
 nodes.first_glyph=node.first_glyph
-nodes.first_character=node.first_character
 nodes.has_glyph=node.has_glyph or node.first_glyph
 nodes.current_attr=node.current_attr
 nodes.do_ligature_n=node.do_ligature_n
@@ -4004,7 +4009,7 @@ nuts.setfield=setfield
 nuts.getnext=direct.getnext
 nuts.getprev=direct.getprev
 nuts.getid=direct.getid
-nuts.getattr=getfield
+nuts.getattr=direct.get_attribute or direct.has_attribute or getfield
 nuts.setattr=setfield
 nuts.getfont=direct.getfont
 nuts.getsubtype=direct.getsubtype
@@ -4022,6 +4027,9 @@ nuts.is_node=direct.is_node
 nuts.end_of_math=direct.end_of_math
 nuts.traverse=direct.traverse
 nuts.traverse_id=direct.traverse_id
+nuts.traverse_char=direct.traverse_char
+nuts.ligaturing=direct.ligaturing
+nuts.kerning=direct.kerning
 nuts.getprop=nuts.getattr
 nuts.setprop=nuts.setattr
 local new_nut=direct.new
@@ -7048,8 +7056,9 @@ local fonts=fonts
 local constructors=fonts.constructors
 local otf=constructors.newhandler("otf")
 local otffeatures=constructors.newfeatures("otf")
-local otftables=otf.tables
 local registerotffeature=otffeatures.register
+local otftables=otf.tables or {}
+otf.tables=otftables
 local allocate=utilities.storage.allocate
 registerotffeature {
   name="features",
@@ -7113,6 +7122,64 @@ registerotffeature {
     node=setscript,
   }
 }
+otftables.featuretypes=allocate {
+  gpos_single="position",
+  gpos_pair="position",
+  gpos_cursive="position",
+  gpos_mark2base="position",
+  gpos_mark2ligature="position",
+  gpos_mark2mark="position",
+  gpos_context="position",
+  gpos_contextchain="position",
+  gsub_single="substitution",
+  gsub_multiple="substitution",
+  gsub_alternate="substitution",
+  gsub_ligature="substitution",
+  gsub_context="substitution",
+  gsub_contextchain="substitution",
+  gsub_reversecontextchain="substitution",
+  gsub_reversesub="substitution",
+}
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+  if featuretype=="position" then
+    local default=scripts.dflt
+    if default then
+      if autoscript=="position" or autoscript==true then
+        return default
+      else
+        report_otf("script feature %s not applied, enable default positioning")
+      end
+    else
+    end
+  elseif featuretype=="substitution" then
+    local default=scripts.dflt
+    if default then
+      if autoscript=="substitution" or autoscript==true then
+        return default
+      end
+    end
+  end
+end
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+  if featuretype=="position" then
+    local default=languages.dflt
+    if default then
+      if autolanguage=="position" or autolanguage==true then
+        return default
+      else
+        report_otf("language feature %s not applied, enable default positioning")
+      end
+    else
+    end
+  elseif featuretype=="substitution" then
+    local default=languages.dflt
+    if default then
+      if autolanguage=="substitution" or autolanguage==true then
+        return default
+      end
+    end
+  end
+end
 
 end -- closure
 
@@ -10224,8 +10291,10 @@ function injections.resetcounts()
 end
 function injections.reset(n)
   local p=rawget(properties,n)
-  if p and rawget(p,"injections") then
-    p.injections=nil
+  if p then
+    p.injections=false 
+  else
+    properties[n]=false 
   end
 end
 function injections.copy(target,source)
@@ -10242,10 +10311,17 @@ function injections.copy(target,source)
           injections=si,
         }
       end
+    elseif tp then
+      tp.injections=false 
     else
-      if tp then
-        tp.injections=nil
-      end
+      properties[target]={ injections={} }
+    end
+  else
+    local tp=rawget(properties,target)
+    if tp then
+      tp.injections=false 
+    else
+      properties[target]=false 
     end
   end
 end
@@ -10480,10 +10556,11 @@ local function show(n,what,nested,symbol)
         local markx=i.markx   or 0
         local marky=i.marky   or 0
         local markdir=i.markdir  or 0
-        local markbase=i.markbase or 0 
+        local markbase=i.markbase or 0
         local cursivex=i.cursivex or 0
         local cursivey=i.cursivey or 0
         local ligaindex=i.ligaindex or 0
+        local cursbase=i.cursiveanchor
         local margin=nested and 4 or 2
         if rightkern~=0 or yoffset~=0 then
           report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
@@ -10494,7 +10571,13 @@ local function show(n,what,nested,symbol)
           report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase~=0 and "yes" or "no")
         end
         if cursivex~=0 or cursivey~=0 then
-          report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+          if cursbase then
+            report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
+          else
+            report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
+          end
+        elseif cursbase then
+          report_injections("%w%s curs: base",margin,symbol)
         end
         if ligaindex~=0 then
           report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
@@ -11177,7 +11260,7 @@ end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['font-otx']={
+if not modules then modules={} end modules ['luatex-fonts-ota']={
   version=1.001,
   comment="companion to font-otf.lua (analysing)",
   author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -11194,7 +11277,6 @@ local initializers=allocate()
 local methods=allocate()
 analyzers.initializers=initializers
 analyzers.methods=methods
-analyzers.useunicodemarks=false
 local a_state=attributes.private('state')
 local nuts=nodes.nuts
 local tonut=nuts.tonut
@@ -11250,6 +11332,7 @@ local features={
 }
 analyzers.states=states
 analyzers.features=features
+analyzers.useunicodemarks=false
 function analyzers.setstate(head,font)
   local useunicodemarks=analyzers.useunicodemarks
   local tfmdata=fontdata[font]
@@ -11263,7 +11346,10 @@ function analyzers.setstate(head,font)
       local char=getchar(current)
       local d=descriptions[char]
       if d then
-        if d.class=="mark" or (useunicodemarks and categories[char]=="mn") then
+        if d.class=="mark" then
+          done=true
+          setprop(current,a_state,s_mark)
+        elseif useunicodemarks and categories[char]=="mn" then
           done=true
           setprop(current,a_state,s_mark)
         elseif n==0 then
@@ -11639,15 +11725,14 @@ local zwj=0x200D
 local wildcard="*"
 local default="dflt"
 local nodecodes=nodes.nodecodes
-local whatcodes=nodes.whatcodes
 local glyphcodes=nodes.glyphcodes
 local disccodes=nodes.disccodes
 local glyph_code=nodecodes.glyph
 local glue_code=nodecodes.glue
 local disc_code=nodecodes.disc
 local math_code=nodecodes.math
-local dir_code=whatcodes.dir
-local localpar_code=whatcodes.localpar
+local dir_code=nodecodes.dir
+local localpar_code=nodecodes.localpar
 local discretionary_code=disccodes.discretionary
 local ligature_code=glyphcodes.ligature
 local privateattribute=attributes.private
@@ -13761,25 +13846,40 @@ otf.chainhandlers={
   normal=normal_handle_contextchain,
   verbose=verbose_handle_contextchain,
 }
+local handle_contextchain=nil
+function chained_contextchain(head,start,stop,...)
+  local steps=currentlookup.steps
+  local nofsteps=currentlookup.nofsteps
+  if nofsteps>1 then
+    reportmoresteps(dataset,sequence)
+  end
+  return handle_contextchain(head,start,...)
+end
 function otf.setcontextchain(method)
   if not method or method=="normal" or not otf.chainhandlers[method] then
-    if handlers.contextchain then 
+    if handle_contextchain then 
       logwarning("installing normal contextchain handler")
     end
-    handlers.contextchain=normal_handle_contextchain
+    handle_contextchain=normal_handle_contextchain
   else
     logwarning("installing contextchain handler %a",method)
     local handler=otf.chainhandlers[method]
-    handlers.contextchain=function(...)
+    handle_contextchain=function(...)
       return handler(currentfont,...) 
     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
+  handlers.gsub_context=handle_contextchain
+  handlers.gsub_contextchain=handle_contextchain
+  handlers.gsub_reversecontextchain=handle_contextchain
+  handlers.gpos_contextchain=handle_contextchain
+  handlers.gpos_context=handle_contextchain
+  handlers.contextchain=handle_contextchain
 end
+chainprocs.gsub_context=chained_contextchain
+chainprocs.gsub_contextchain=chained_contextchain
+chainprocs.gsub_reversecontextchain=chained_contextchain
+chainprocs.gpos_contextchain=chained_contextchain
+chainprocs.gpos_context=chained_contextchain
 otf.setcontextchain()
 local missing={} 
 local function logprocess(...)
@@ -13807,19 +13907,32 @@ setmetatableindex(lookuphashes,function(t,font)
   t[font]=lookuphash
   return lookuphash
 end)
-local autofeatures=fonts.analyzers.features 
-local function initialize(sequence,script,language,enabled)
+local autofeatures=fonts.analyzers.features
+local featuretypes=otf.tables.featuretypes
+local defaultscript=otf.features.checkeddefaultscript
+local defaultlanguage=otf.features.checkeddefaultlanguage
+local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
   local features=sequence.features
   if features then
     local order=sequence.order
     if order then
-      for i=1,#order do 
-        local kind=order[i] 
+      local featuretype=featuretypes[sequence.type or "unknown"]
+      for i=1,#order do
+        local kind=order[i]
         local valid=enabled[kind]
         if valid then
-          local scripts=features[kind] 
-          local languages=scripts[script] or scripts[wildcard]
-          if languages and (languages[language] or languages[wildcard]) then
+          local scripts=features[kind]
+          local languages=scripts and (
+            scripts[script] or
+            scripts[wildcard] or
+            (autoscript and defaultscript(featuretype,autoscript,scripts))
+          )
+          local enabled=languages and (
+            languages[language] or
+            languages[wildcard] or
+            (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+          )
+          if enabled then
             return { valid,autofeatures[kind] or false,sequence,kind }
           end
         end
@@ -13835,6 +13948,8 @@ function otf.dataset(tfmdata,font)
   local language=properties.language or "dflt"
   local script=properties.script  or "dflt"
   local enabled=shared.features
+  local autoscript=enabled and enabled.autoscript
+  local autolanguage=enabled and enabled.autolanguage
   local res=resolved[font]
   if not res then
     res={}
@@ -13852,7 +13967,7 @@ function otf.dataset(tfmdata,font)
     rs[language]=rl
     local sequences=tfmdata.resources.sequences
     for s=1,#sequences do
-      local v=enabled and initialize(sequences[s],script,language,enabled)
+      local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
       if v then
         rl[#rl+1]=v
       end
@@ -14281,6 +14396,40 @@ local function featuresprocessor(head,font,attr)
               end
             elseif id==math_code then
               start=getnext(end_of_math(start))
+            elseif id==dir_code then
+              local dir=getfield(start,"dir")
+              if dir=="+TLT" then
+                topstack=topstack+1
+                dirstack[topstack]=dir
+                rlmode=1
+              elseif dir=="+TRT" then
+                topstack=topstack+1
+                dirstack[topstack]=dir
+                rlmode=-1
+              elseif dir=="-TLT" or dir=="-TRT" then
+                topstack=topstack-1
+                rlmode=dirstack[topstack]=="+TRT" and -1 or 1
+              else
+                rlmode=rlparmode
+              end
+              if trace_directions then
+                report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+              end
+              start=getnext(start)
+            elseif id==localpar_code then
+              local dir=getfield(start,"dir")
+              if dir=="TRT" then
+                rlparmode=-1
+              elseif dir=="TLT" then
+                rlparmode=1
+              else
+                rlparmode=0
+              end
+              rlmode=rlparmode
+              if trace_directions then
+                report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+              end
+              start=getnext(start)
             else
               start=getnext(start)
             end
@@ -14501,6 +14650,40 @@ local function featuresprocessor(head,font,attr)
             end
           elseif id==math_code then
             start=getnext(end_of_math(start))
+          elseif id==dir_code then
+            local dir=getfield(start,"dir")
+            if dir=="+TLT" then
+              topstack=topstack+1
+              dirstack[topstack]=dir
+              rlmode=1
+            elseif dir=="+TRT" then
+              topstack=topstack+1
+              dirstack[topstack]=dir
+              rlmode=-1
+            elseif dir=="-TLT" or dir=="-TRT" then
+              topstack=topstack-1
+              rlmode=dirstack[topstack]=="+TRT" and -1 or 1
+            else
+              rlmode=rlparmode
+            end
+            if trace_directions then
+              report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
+            end
+            start=getnext(start)
+          elseif id==localpar_code then
+            local dir=getfield(start,"dir")
+            if dir=="TRT" then
+              rlparmode=-1
+            elseif dir=="TLT" then
+              rlparmode=1
+            else
+              rlparmode=0
+            end
+            rlmode=rlparmode
+            if trace_directions then
+              report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
+            end
+            start=getnext(start)
           else
             start=getnext(start)
           end
@@ -14636,10 +14819,10 @@ local function split(replacement,original)
   end
   return result
 end
-local valid={
-  coverage={ chainsub=true,chainpos=true,contextsub=true },
+local valid={ 
+  coverage={ chainsub=true,chainpos=true,contextsub=true,contextpos=true },
   reversecoverage={ reversesub=true },
-  glyphs={ chainsub=true,chainpos=true },
+  glyphs={ chainsub=true,chainpos=true,contextsub=true,contextpos=true },
 }
 local function prepare_contextchains(tfmdata)
   local rawdata=tfmdata.shared.rawdata
@@ -15952,7 +16135,7 @@ end -- closure
 
 do -- begin closure to overcome local limits and interference
 
-if not modules then modules={} end modules ['luatex-font-def']={
+if not modules then modules={} end modules ['luatex-fonts-def']={
   version=1.001,
   comment="companion to luatex-*.tex",
   author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/generic/context/luatex/luatex-fonts-ota.lua b/tex/generic/context/luatex/luatex-fonts-ota.lua
index f083fe09e..256ead5a5 100644
--- a/tex/generic/context/luatex/luatex-fonts-ota.lua
+++ b/tex/generic/context/luatex/luatex-fonts-ota.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['font-otx'] = {
+if not modules then modules = { } end modules ['luatex-fonts-ota'] = {
     version   = 1.001,
     comment   = "companion to font-otf.lua (analysing)",
     author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -24,7 +24,6 @@ local methods             = allocate()
 
 analyzers.initializers    = initializers
 analyzers.methods         = methods
-analyzers.useunicodemarks = false
 
 local a_state             = attributes.private('state')
 
@@ -98,8 +97,9 @@ local features = {
     pstf = s_pstf,
 }
 
-analyzers.states   = states
-analyzers.features = features
+analyzers.states          = states
+analyzers.features        = features
+analyzers.useunicodemarks = false
 
 -- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
 -- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
@@ -117,7 +117,10 @@ function analyzers.setstate(head,font)
             local char = getchar(current)
             local d = descriptions[char]
             if d then
-                if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then
+                if d.class == "mark" then
+                    done = true
+                    setprop(current,a_state,s_mark)
+                elseif useunicodemarks and categories[char] == "mn" then
                     done = true
                     setprop(current,a_state,s_mark)
                 elseif n == 0 then
@@ -136,7 +139,9 @@ function analyzers.setstate(head,font)
                 first, last, n = nil, nil, 0
             end
         elseif id == disc_code then
-            -- always in the middle
+            -- always in the middle .. it doesn't make much sense to assign a property
+            -- here ... we might at some point decide to flag the components when present
+            -- but even then it's kind of bogus
             setprop(current,a_state,s_medi)
             last = current
         else -- finish
@@ -213,17 +218,6 @@ registerotffeature {
 
 methods.latn = analyzers.setstate
 
--- This info eventually can go into char-def and we will have a state
--- table for generic then (unicode recognized all states but in practice
--- only has only
---
--- isolated : isol
--- final    : isol_fina
--- medial   : isol_fina_medi_init
---
--- so in practice, without analyzer it's rather useless info which is
--- why having it in char-def makes only sense for special purposes (like)
--- like tracing cq. visualizing.
 
 local tatweel = 0x0640
 local zwnj    = 0x200C
@@ -344,8 +338,6 @@ local medial = { -- isol_fina_medi_init
 
 local arab_warned = { }
 
--- todo: gref
-
 local function warning(current,what)
     local char = getchar(current)
     if not arab_warned[char] then
diff --git a/tex/generic/context/luatex/luatex-fonts-otn.lua b/tex/generic/context/luatex/luatex-fonts-otn.lua
deleted file mode 100644
index 7fafadbc4..000000000
--- a/tex/generic/context/luatex/luatex-fonts-otn.lua
+++ /dev/null
@@ -1,3848 +0,0 @@
-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 a context version which can contain experimental code, but when we
--- have serious patches we also need to change the other two font-otn files
-
--- at some point i might decide to convert the whole list into a table and then
--- run over that instead (but it has some drawbacks as we also need to deal with
--- attributes and such so we need to keep a lot of track - which is why i rejected
--- that method - although it has become a bit easier in the meantime so it might
--- become an alternative (by that time i probably have gone completely lua) .. the
--- usual chicken-egg issues ... maybe mkix as it's no real tex any more then
-
--- preprocessors = { "nodes" }
-
--- anchor class : mark, mkmk, curs, mklg (todo)
--- anchor type  : mark, basechar, baselig, basemark, centry, cexit, max (todo)
-
--- 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.
-
--- 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:
---
--- 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
--- default features (per language, script)
--- handle positions (we need example fonts)
--- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
--- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
--- remove some optimizations (when I have a faster machine)
---
--- beware:
---
--- we do some disc jugling where we need to keep in mind that the
--- pre, post and replace fields can have prev pointers to a nesting
--- node ... i wonder if that is still needed
---
--- not possible:
---
--- \discretionary {alpha-} {betagammadelta}
---   {\discretionary {alphabeta-} {gammadelta}
---      {\discretionary {alphabetagamma-} {delta}
---         {alphabetagammadelta}}}
-
---[[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.
-
-The specification leaves room for interpretation. In case of doubt the microsoft
-implementation is the reference as it is the most complete one. As they deal with
-lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and
-their suggestions help improve the code. I'm aware that not all border cases can be
-taken care of, unless we accept excessive runtime, and even then the interference
-with other mechanisms (like hyphenation) are not trivial.
-
-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
---
--- gsub_single               ok          ok
--- gsub_multiple             ok          ok
--- gsub_alternate            ok          ok
--- gsub_ligature             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          --
---
--- todo: contextpos and contextsub and class stuff
---
--- 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
-
--- We used to have independent hashes for lookups but as the tags are unique
--- we now use only one hash. If needed we can have multiple again but in that
--- case I will probably prefix (i.e. rename) the lookups in the cached font file.
-
--- Todo: make plugin feature that operates on char/glyphnode arrays
-
-local type, next, tonumber = type, next, tonumber
-local random = math.random
-local formatters = string.formatters
-
-local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
-
-local registertracker   = trackers.register
-local registerdirective = directives.register
-
-local fonts = fonts
-local otf   = fonts.handlers.otf
-
-local trace_lookups      = false  registertracker("otf.lookups",      function(v) trace_lookups      = v end)
-local trace_singles      = false  registertracker("otf.singles",      function(v) trace_singles      = v end)
-local trace_multiples    = false  registertracker("otf.multiples",    function(v) trace_multiples    = v end)
-local trace_alternatives = false  registertracker("otf.alternatives", function(v) trace_alternatives = v end)
-local trace_ligatures    = false  registertracker("otf.ligatures",    function(v) trace_ligatures    = v end)
-local trace_contexts     = false  registertracker("otf.contexts",     function(v) trace_contexts     = v end)
-local trace_marks        = false  registertracker("otf.marks",        function(v) trace_marks        = v end)
-local trace_kerns        = false  registertracker("otf.kerns",        function(v) trace_kerns        = v end)
-local trace_cursive      = false  registertracker("otf.cursive",      function(v) trace_cursive      = v end)
-local trace_preparing    = false  registertracker("otf.preparing",    function(v) trace_preparing    = v end)
-local trace_bugs         = false  registertracker("otf.bugs",         function(v) trace_bugs         = v end)
-local trace_details      = false  registertracker("otf.details",      function(v) trace_details      = v end)
-local trace_applied      = false  registertracker("otf.applied",      function(v) trace_applied      = v end)
-local trace_steps        = false  registertracker("otf.steps",        function(v) trace_steps        = v end)
-local trace_skips        = false  registertracker("otf.skips",        function(v) trace_skips        = v end)
-local trace_directions   = false  registertracker("otf.directions",   function(v) trace_directions   = v end)
-
-local trace_kernruns     = false  registertracker("otf.kernruns",     function(v) trace_kernruns     = v end)
-local trace_discruns     = false  registertracker("otf.discruns",     function(v) trace_discruns     = v end)
-local trace_compruns     = false  registertracker("otf.compruns",     function(v) trace_compruns     = v end)
-
-local quit_on_no_replacement = true  -- maybe per font
-local zwnjruns               = true
-
-registerdirective("otf.zwnjruns",                 function(v) zwnjruns = v end)
-registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
-
-local report_direct   = logs.reporter("fonts","otf direct")
-local report_subchain = logs.reporter("fonts","otf subchain")
-local report_chain    = logs.reporter("fonts","otf chain")
-local report_process  = logs.reporter("fonts","otf process")
-local report_prepare  = logs.reporter("fonts","otf prepare")
-local report_warning  = logs.reporter("fonts","otf warning")
-local report_run      = logs.reporter("fonts","otf run")
-
-registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
-registertracker("otf.normal_chain",  function(v) otf.setcontextchain(v and "normal")  end)
-
-registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
-registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
-registertracker("otf.actions","otf.replacements,otf.positions")
-registertracker("otf.injections","nodes.injections")
-
-registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
-
-local nuts               = nodes.nuts
-local tonode             = nuts.tonode
-local tonut              = nuts.tonut
-
-local getfield           = nuts.getfield
-local setfield           = nuts.setfield
-local getnext            = nuts.getnext
-local getprev            = nuts.getprev
-local getid              = nuts.getid
-local getattr            = nuts.getattr
-local setattr            = nuts.setattr
-local getprop            = nuts.getprop
-local setprop            = nuts.setprop
-local getfont            = nuts.getfont
-local getsubtype         = nuts.getsubtype
-local getchar            = nuts.getchar
-
-local insert_node_before = nuts.insert_before
-local insert_node_after  = nuts.insert_after
-local delete_node        = nuts.delete
-local remove_node        = nuts.remove
-local copy_node          = nuts.copy
-local copy_node_list     = nuts.copy_list
-local find_node_tail     = nuts.tail
-local flush_node_list    = nuts.flush_list
-local free_node          = nuts.free
-local end_of_math        = nuts.end_of_math
-local traverse_nodes     = nuts.traverse
-local traverse_id        = nuts.traverse_id
-
-local setmetatableindex  = table.setmetatableindex
-
-local zwnj               = 0x200C
-local zwj                = 0x200D
-local wildcard           = "*"
-local default            = "dflt"
-
-local nodecodes          = nodes.nodecodes
-local whatcodes          = nodes.whatcodes
-local glyphcodes         = nodes.glyphcodes
-local disccodes          = nodes.disccodes
-
-local glyph_code         = nodecodes.glyph
-local glue_code          = nodecodes.glue
-local disc_code          = nodecodes.disc
-local math_code          = nodecodes.math
-
-local dir_code           = whatcodes.dir
-local localpar_code      = whatcodes.localpar
-local discretionary_code = disccodes.discretionary
-local ligature_code      = glyphcodes.ligature
-
-local privateattribute   = attributes.private
-
--- Something is messed up: we have two mark / ligature indices, one at the injection
--- end and one here ... this is based on KE's patches but there is something fishy
--- there as I'm pretty sure that for husayni we need some connection (as it's much
--- more complex than an average font) but I need proper examples of all cases, not
--- of only some.
-
-local a_state            = privateattribute('state')
-local a_cursbase         = privateattribute('cursbase') -- to be checked, probably can go
-
-local injections         = nodes.injections
-local setmark            = injections.setmark
-local setcursive         = injections.setcursive
-local setkern            = injections.setkern
-local setpair            = injections.setpair
-local resetinjection     = injections.reset
-local copyinjection      = injections.copy
-local setligaindex       = injections.setligaindex
-local getligaindex       = injections.getligaindex
-
-local cursonce           = true
-
-local fonthashes         = fonts.hashes
-local fontdata           = fonthashes.identifiers
-
-local otffeatures        = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
-
-local onetimemessage     = fonts.loggers.onetimemessage or function() end
-
-otf.defaultnodealternate = "none" -- first last
-
--- we share some vars here, after all, we have no nested lookups and less code
-
-local tfmdata             = false
-local characters          = false
-local descriptions        = false
-local resources           = false
-local marks               = false
-local currentfont         = false
-local lookuptable         = false
-local anchorlookups       = false
-local lookuptypes         = false
-local lookuptags          = false
-local handlers            = { }
-local rlmode              = 0
-local featurevalue        = false
-
-local sweephead           = { }
-local sweepnode           = nil
-local sweepprev           = nil
-local sweepnext           = nil
-
-local notmatchpre         = { }
-local notmatchpost        = { }
-local notmatchreplace     = { }
-
--- 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
-    report_direct(...)
-end
-
-local function logwarning(...)
-    report_direct(...)
-end
-
-local f_unicode = formatters["%U"]
-local f_uniname = formatters["%U (%s)"]
-local f_unilist = formatters["% t (% t)"]
-
-local function gref(n) -- currently the same as in font-otb
-    if type(n) == "number" then
-        local description = descriptions[n]
-        local name = description and description.name
-        if name then
-            return f_uniname(n,name)
-        else
-            return f_unicode(n)
-        end
-    elseif n then
-        local num, nam = { }, { }
-        for i=1,#n do
-            local ni = n[i]
-            if tonumber(ni) then -- later we will start at 2
-                local di = descriptions[ni]
-                num[i] = f_unicode(ni)
-                nam[i] = di and di.name or "-"
-            end
-        end
-        return f_unilist(num,nam)
-    else
-        return ""
-    end
-end
-
-local function cref(kind,chainname,chainlookupname,lookupname,index) -- not in the mood to alias f_
-    if index then
-        return formatters["feature %a, chain %a, sub %a, lookup %a, index %a"](kind,chainname,chainlookupname,lookuptags[lookupname],index)
-    elseif lookupname then
-        return formatters["feature %a, chain %a, sub %a, lookup %a"](kind,chainname,chainlookupname,lookuptags[lookupname])
-    elseif chainlookupname then
-        return formatters["feature %a, chain %a, sub %a"](kind,lookuptags[chainname],lookuptags[chainlookupname])
-    elseif chainname then
-        return formatters["feature %a, chain %a"](kind,lookuptags[chainname])
-    else
-        return formatters["feature %a"](kind)
-    end
-end
-
-local function pref(kind,lookupname)
-    return formatters["feature %a, lookup %a"](kind,lookuptags[lookupname])
-end
-
--- We can assume that languages that use marks are not hyphenated. We can also assume
--- that at most one discretionary is present.
-
--- We do need components in funny kerning mode but maybe I can better reconstruct then
--- as we do have the font components info available; removing components makes the
--- previous code much simpler. Also, later on copying and freeing becomes easier.
--- However, for arabic we need to keep them around for the sake of mark placement
--- and indices.
-
-local function copy_glyph(g) -- next and prev are untouched !
-    local components = getfield(g,"components")
-    if components then
-        setfield(g,"components",nil)
-        local n = copy_node(g)
-        copyinjection(n,g) -- we need to preserve the lig indices
-        setfield(g,"components",components)
-        return n
-    else
-        local n = copy_node(g)
-        copyinjection(n,g) -- we need to preserve the lig indices
-        return n
-    end
-end
-
-local function flattendisk(head,disc)
-    local replace = getfield(disc,"replace")
-    setfield(disc,"replace",nil)
-    free_node(disc)
-    if head == disc then
-        local next = getnext(disc)
-        if replace then
-            if next then
-                local tail = find_node_tail(replace)
-                setfield(tail,"next",next)
-                setfield(next,"prev",tail)
-            end
-            return replace, replace
-        elseif next then
-            return next, next
-        else
-            return -- maybe warning
-        end
-    else
-        local next = getnext(disc)
-        local prev = getprev(disc)
-        if replace then
-            local tail = find_node_tail(replace)
-            if next then
-                setfield(tail,"next",next)
-                setfield(next,"prev",tail)
-            end
-            setfield(prev,"next",replace)
-            setfield(replace,"prev",prev)
-            return head, replace
-        else
-            if next then
-                setfield(next,"prev",prev)
-            end
-            setfield(prev,"next",next)
-            return head, next
-        end
-    end
-end
-
-local function appenddisc(disc,list)
-    local post    = getfield(disc,"post")
-    local replace = getfield(disc,"replace")
-    local phead   = list
-    local rhead   = copy_node_list(list)
-    local ptail   = find_node_tail(post)
-    local rtail   = find_node_tail(replace)
-    if post then
-        setfield(ptail,"next",phead)
-        setfield(phead,"prev",ptail)
-    else
-        setfield(disc,"post",phead)
-    end
-    if replace then
-        setfield(rtail,"next",rhead)
-        setfield(rhead,"prev",rtail)
-    else
-        setfield(disc,"replace",rhead)
-    end
-end
-
--- start is a mark and we need to keep that one
-
-local function markstoligature(kind,lookupname,head,start,stop,char)
-    if start == stop and getchar(start) == char then
-        return head, start
-    else
-        local prev = getprev(start)
-        local next = getnext(stop)
-        setfield(start,"prev",nil)
-        setfield(stop,"next",nil)
-        local base = copy_glyph(start)
-        if head == start then
-            head = base
-        end
-        resetinjection(base)
-        setfield(base,"char",char)
-        setfield(base,"subtype",ligature_code)
-        setfield(base,"components",start)
-        if prev then
-            setfield(prev,"next",base)
-        end
-        if next then
-            setfield(next,"prev",base)
-        end
-        setfield(base,"next",next)
-        setfield(base,"prev",prev)
-        return head, base
-    end
-end
-
--- The next code is somewhat complicated by the fact that some fonts can have ligatures made
--- from ligatures that themselves have marks. This was identified by Kai in for instance
--- arabtype:  KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
--- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
--- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
--- third component.
-
-local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents)
-    if getid(start) ~= glyph_code then  -- and then get rid of all components
-        return 0
-    elseif getsubtype(start) == ligature_code then
-        local i = 0
-        local components = getfield(start,"components")
-        while components do
-            i = i + getcomponentindex(components)
-            components = getnext(components)
-        end
-        return i
-    elseif not marks[getchar(start)] then
-        return 1
-    else
-        return 0
-    end
-end
-
-local a_noligature = attributes.private("noligature")
-
-local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head
-    if getattr(start,a_noligature) == 1 then
-        -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
-        return head, start
-    end
-    if start == stop and getchar(start) == char then
-        resetinjection(start)
-        setfield(start,"char",char)
-        return head, start
-    end
-    -- needs testing (side effects):
-    local components = getfield(start,"components")
-    if components then
-     -- we get a double free .. needs checking
-     -- flush_node_list(components)
-    end
-    --
-    local prev = getprev(start)
-    local next = getnext(stop)
-    local comp = start
-    setfield(start,"prev",nil)
-    setfield(stop,"next",nil)
-    local base = copy_glyph(start)
-    if start == head then
-        head = base
-    end
-    resetinjection(base)
-    setfield(base,"char",char)
-    setfield(base,"subtype",ligature_code)
-    setfield(base,"components",comp) -- start can have components ... do we need to flush?
-    if prev then
-        setfield(prev,"next",base)
-    end
-    if next then
-        setfield(next,"prev",base)
-    end
-    setfield(base,"prev",prev)
-    setfield(base,"next",next)
-    if not discfound then
-        local deletemarks = markflag ~= "mark"
-        local components = start
-        local baseindex = 0
-        local componentindex = 0
-        local head = base
-        local current = base
-        -- first we loop over the glyphs in start .. stop
-        while start do
-            local char = getchar(start)
-            if not marks[char] then
-                baseindex = baseindex + componentindex
-                componentindex = getcomponentindex(start)
-            elseif not deletemarks then -- quite fishy
-                setligaindex(start,baseindex + getligaindex(start,componentindex))
-                if trace_marks then
-                    logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
-                end
-                local n = copy_node(start)
-                copyinjection(n,start)
-                head, current = insert_node_after(head,current,n) -- unlikely that mark has components
-            elseif trace_marks then
-                logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
-            end
-            start = getnext(start)
-        end
-        -- we can have one accent as part of a lookup and another following
-     -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added)
-        local start = getnext(current)
-        while start and getid(start) == glyph_code do
-            local char = getchar(start)
-            if marks[char] then
-                setligaindex(start,baseindex + getligaindex(start,componentindex))
-                if trace_marks then
-                    logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
-                end
-            else
-                break
-            end
-            start = getnext(start)
-        end
-    else
-        -- discfound ... forget about marks .. probably no scripts that hyphenate and have marks
-        local discprev = getfield(discfound,"prev")
-        local discnext = getfield(discfound,"next")
-        if discprev and discnext then
-            -- we assume normalization in context, and don't care about generic ... especially
-            -- \- can give problems as there we can have a negative char but that won't match
-            -- anyway
-            local pre     = getfield(discfound,"pre")
-            local post    = getfield(discfound,"post")
-            local replace = getfield(discfound,"replace")
-            if not replace then -- todo: signal simple hyphen
-                local prev = getfield(base,"prev")
-                local copied = copy_node_list(comp)
-                setfield(discnext,"prev",nil) -- also blocks funny assignments
-                setfield(discprev,"next",nil) -- also blocks funny assignments
-                if pre then
-                    setfield(discprev,"next",pre)
-                    setfield(pre,"prev",discprev)
-                end
-                pre = comp
-                if post then
-                    local tail = find_node_tail(post)
-                    setfield(tail,"next",discnext)
-                    setfield(discnext,"prev",tail)
-                    setfield(post,"prev",nil)
-                else
-                    post = discnext
-                end
-                setfield(prev,"next",discfound)
-                setfield(discfound,"prev",prev)
-                setfield(discfound,"next",next)
-                setfield(next,"prev",discfound)
-                setfield(base,"next",nil)
-                setfield(base,"prev",nil)
-                setfield(base,"components",copied)
-                setfield(discfound,"pre",pre)
-                setfield(discfound,"post",post)
-                setfield(discfound,"replace",base)
-                setfield(discfound,"subtype",discretionary_code)
-                base = prev -- restart
-            end
-        end
-    end
-    return head, base
-end
-
-local function multiple_glyphs(head,start,multiple,ignoremarks)
-    local nofmultiples = #multiple
-    if nofmultiples > 0 then
-        resetinjection(start)
-        setfield(start,"char",multiple[1])
-        if nofmultiples > 1 then
-            local sn = getnext(start)
-            for k=2,nofmultiples do -- todo: use insert_node
--- untested:
---
--- while ignoremarks and marks[getchar(sn)] then
---     local sn = getnext(sn)
--- end
-                local n = copy_node(start) -- ignore components
-                resetinjection(n)
-                setfield(n,"char",multiple[k])
-                setfield(n,"prev",start)
-                setfield(n,"next",sn)
-                if sn then
-                    setfield(sn,"prev",n)
-                end
-                setfield(start,"next",n)
-                start = n
-            end
-        end
-        return head, start, true
-    else
-        if trace_multiples then
-            logprocess("no multiple for %s",gref(getchar(start)))
-        end
-        return head, start, false
-    end
-end
-
-local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
-    local n = #alternatives
-    if value == "random" then
-        local r = random(1,n)
-        return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r)
-    elseif value == "first" then
-        return alternatives[1], trace_alternatives and formatters["value %a, taking %a"](value,1)
-    elseif value == "last" then
-        return alternatives[n], trace_alternatives and formatters["value %a, taking %a"](value,n)
-    else
-        value = tonumber(value)
-        if type(value) ~= "number" then
-            return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
-        elseif value > n then
-            local defaultalt = otf.defaultnodealternate
-            if defaultalt == "first" then
-                return alternatives[n], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
-            elseif defaultalt == "last" then
-                return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,n)
-            else
-                return false, trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
-            end
-        elseif value == 0 then
-            return getchar(start), trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
-        elseif value < 1 then
-            return alternatives[1], trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
-        else
-            return alternatives[value], trace_alternatives and formatters["value %a, taking %a"](value,value)
-        end
-    end
-end
-
--- handlers
-
-function handlers.gsub_single(head,start,kind,lookupname,replacement)
-    if trace_singles then
-        logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
-    end
-    resetinjection(start)
-    setfield(start,"char",replacement)
-    return head, start, true
-end
-
-function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
-    local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
-    local choice, comment = get_alternative_glyph(start,alternative,value,trace_alternatives)
-    if choice then
-        if trace_alternatives then
-            logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
-        end
-        resetinjection(start)
-        setfield(start,"char",choice)
-    else
-        if trace_alternatives then
-            logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
-        end
-    end
-    return head, start, true
-end
-
-function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
-    if trace_multiples then
-        logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple))
-    end
-    return multiple_glyphs(head,start,multiple,sequence.flags[1])
-end
-
-function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
-    local s, stop = getnext(start), nil
-    local startchar = getchar(start)
-    if marks[startchar] then
-        while s do
-            local id = getid(s)
-            if id == glyph_code and getfont(s) == currentfont and getsubtype(s)<256 then
-                local lg = ligature[getchar(s)]
-                if lg then
-                    stop = s
-                    ligature = lg
-                    s = getnext(s)
-                else
-                    break
-                end
-            else
-                break
-            end
-        end
-        if stop then
-            local lig = ligature.ligature
-            if lig then
-                if trace_ligatures then
-                    local stopchar = getchar(stop)
-                    head, start = markstoligature(kind,lookupname,head,start,stop,lig)
-                    logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
-                else
-                    head, start = markstoligature(kind,lookupname,head,start,stop,lig)
-                end
-                return head, start, true, false
-            else
-                -- ok, goto next lookup
-            end
-        end
-    else
-        local skipmark  = sequence.flags[1]
-        local discfound = false
-        local lastdisc  = nil
-        while s do
-            local id = getid(s)
-            if id == glyph_code and getsubtype(s)<256 then -- not needed
-                if getfont(s) == currentfont then          -- also not needed only when mark
-                    local char = getchar(s)
-                    if skipmark and marks[char] then
-                        s = getnext(s)
-                    else -- ligature is a tree
-                        local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
-                        if lg then
-                            if not discfound and lastdisc then
-                                discfound = lastdisc
-                                lastdisc  = nil
-                            end
-                            stop = s -- needed for fake so outside then
-                            ligature = lg
-                            s = getnext(s)
-                        else
-                            break
-                        end
-                    end
-                else
-                    break
-                end
-            elseif id == disc_code then
-                lastdisc = s
-                s = getnext(s)
-            else
-                break
-            end
-        end
-        local lig = ligature.ligature -- can't we get rid of this .ligature?
-        if lig then
-            if stop then
-                if trace_ligatures then
-                    local stopchar = getchar(stop)
-                    head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
-                    logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
-                else
-                    head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
-                end
-            else
-                -- weird but happens (in some arabic font)
-                resetinjection(start)
-                setfield(start,"char",lig)
-                if trace_ligatures then
-                    logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
-                end
-            end
-            return head, start, true, discfound
-        else
-            -- weird but happens, pseudo ligatures ... just the components
-        end
-    end
-    return head, start, false, discfound
-end
-
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,injection)
-    local startchar = getchar(start)
-    local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection) -- ,characters[startchar])
-    if trace_kerns then
-        logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
-    end
-    return head, start, false
-end
-
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
-    -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
-    -- todo: kerns in components of ligatures
-    local snext = getnext(start)
-    if not snext then
-        return head, start, false
-    else
-        local prev   = start
-        local done   = false
-        local factor = tfmdata.parameters.factor
-        local lookuptype = lookuptypes[lookupname]
-        while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
-            local nextchar = getchar(snext)
-            local krn = kerns[nextchar]
-            if not krn and marks[nextchar] then
-                prev = snext
-                snext = getnext(snext)
-            else
-                if not krn then
-                    -- skip
-                elseif type(krn) == "table" then
-                    if lookuptype == "pair" then -- probably not needed
-                        local a, b = krn[2], krn[3]
-                        if a and #a > 0 then
-                            local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) -- characters[startchar])
-                            if trace_kerns then
-                                local startchar = getchar(start)
-                                logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
-                            end
-                        end
-                        if b and #b > 0 then
-                            local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) -- characters[nextchar])
-                            if trace_kerns then
-                                local startchar = getchar(start)
-                                logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
-                            end
-                        end
-                    else -- wrong ... position has different entries
-                        report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
-                     -- local a, b = krn[2], krn[6]
-                     -- if a and a ~= 0 then
-                     --     local k = setkern(snext,factor,rlmode,a)
-                     --     if trace_kerns then
-                     --         logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),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 = setkern(snext,factor,rlmode,krn,injection)
-                    if trace_kerns then
-                        logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) -- prev?
-                    end
-                    done = true
-                end
-                break
-            end
-        end
-        return head, start, done
-    end
-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(head,start,kind,lookupname,markanchors,sequence)
-    local markchar = getchar(start)
-    if marks[markchar] then
-        local base = getprev(start) -- [glyph] [start=mark]
-        if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-            local basechar = getchar(base)
-            if marks[basechar] then
-                while true do
-                    base = getprev(base)
-                    if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-                        basechar = getchar(base)
-                        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 head, 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 = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
-                                if trace_marks then
-                                    logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
-                                        pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
-                                end
-                                return head, 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
-            elseif trace_bugs then
-            --  logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
-                onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
-            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 head, start, false
-end
-
-function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence)
-    -- check chainpos variant
-    local markchar = getchar(start)
-    if marks[markchar] then
-        local base = getprev(start) -- [glyph] [optional marks] [start=mark]
-        if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-            local basechar = getchar(base)
-            if marks[basechar] then
-                while true do
-                    base = getprev(base)
-                    if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-                        basechar = getchar(base)
-                        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 head, start, false
-                    end
-                end
-            end
-            local index = getligaindex(start)
-            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 = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar]) -- index
-                                        if trace_marks then
-                                            logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
-                                                pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
-                                        end
-                                        return head, start, true
-                                    else
-                                        if trace_bugs then
-                                            logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(kind,lookupname),gref(markchar),gref(basechar),index)
-                                        end
-                                    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
-            elseif trace_bugs then
-            --  logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
-                onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
-            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 head, start, false
-end
-
-function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence)
-    local markchar = getchar(start)
-    if marks[markchar] then
-        local base = getprev(start) -- [glyph] [basemark] [start=mark]
-        local slc = getligaindex(start)
-        if slc then -- a rather messy loop ... needs checking with husayni
-            while base do
-                local blc = getligaindex(base)
-                if blc and blc ~= slc then
-                    base = getprev(base)
-                else
-                    break
-                end
-            end
-        end
-        if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go
-            local basechar = getchar(base)
-            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 = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
-                                    if trace_marks then
-                                        logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
-                                            pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
-                                    end
-                                    return head, 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
-            elseif trace_bugs then
-            --  logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
-                onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
-            end
-        elseif trace_bugs then
-            logwarning("%s: prev node is no mark",pref(kind,lookupname))
-        end
-    elseif trace_bugs then
-        logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
-    end
-    return head, start, false
-end
-
-function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) -- to be checked
-    local alreadydone = cursonce and getprop(start,a_cursbase)
-    if not alreadydone then
-        local done = false
-        local startchar = getchar(start)
-        if marks[startchar] then
-            if trace_cursive then
-                logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
-            end
-        else
-            local nxt = getnext(start)
-            while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do
-                local nextchar = getchar(nxt)
-                if marks[nextchar] then
-                    -- should not happen (maybe warning)
-                    nxt = getnext(nxt)
-                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 = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
-                                            if trace_cursive then
-                                                logprocess("%s: moving %s to %s cursive (%p,%p) 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
-                    elseif trace_bugs then
-                    --  logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
-                        onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
-                    end
-                    break
-                end
-            end
-        end
-        return head, start, done
-    else
-        if trace_cursive and trace_details then
-            logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
-        end
-        return head, start, false
-    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 chainprocs = { }
-
-local function logprocess(...)
-    if trace_steps then
-        registermessage(...)
-    end
-    report_subchain(...)
-end
-
-local logwarning = report_subchain
-
-local function logprocess(...)
-    if trace_steps then
-        registermessage(...)
-    end
-    report_chain(...)
-end
-
-local logwarning = report_chain
-
--- We could share functions but that would lead to extra function calls with many
--- arguments, redundant tests and confusing messages.
-
-function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname)
-    logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
-    return head, 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(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
-    local char = getchar(start)
-    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
-        resetinjection(start)
-        setfield(start,"char",replacement)
-        return head, start, true
-    else
-        return head, 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:
-
-
-xxxabcdexxx [single a->A][multiple b->BCD][ligature cde->E] xxxABCDExxx
-
-
-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 make the code even more messy.
---ldx]]--
-
--- local function delete_till_stop(head,start,stop,ignoremarks) -- keeps start
---     local n = 1
---     if start == stop then
---         -- done
---     elseif ignoremarks then
---         repeat -- start x x m x x stop => start m
---             local next = getnext(start)
---             if not marks[getchar(next)] then
---                 local components = getfield(next,"components")
---                 if components then -- probably not needed
---                     flush_node_list(components)
---                 end
---                 head = delete_node(head,next)
---             end
---             n = n + 1
---         until next == stop
---     else -- start x x x stop => start
---         repeat
---             local next = getnext(start)
---             local components = getfield(next,"components")
---             if components then -- probably not needed
---                 flush_node_list(components)
---             end
---             head = delete_node(head,next)
---             n = n + 1
---         until next == stop
---     end
---     return head, n
--- end
-
---[[ldx--
-Here we replace start by a single variant.
---ldx]]--
-
-function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
-    -- todo: marks ?
-    local current = start
-    local subtables = currentlookup.subtables
-    if #subtables > 1 then
-        logwarning("todo: check if we need to loop over the replacements: % t",subtables)
-    end
-    while current do
-        if getid(current) == glyph_code then
-            local currentchar = getchar(current)
-            local lookupname = subtables[1] -- only 1
-            local replacement = lookuphash[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 or 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
-                    resetinjection(current)
-                    setfield(current,"char",replacement)
-                end
-            end
-            return head, start, true
-        elseif current == stop then
-            break
-        else
-            current = getnext(current)
-        end
-    end
-    return head, start, false
-end
-
---[[ldx--
-Here we replace start by a sequence of new glyphs.
---ldx]]--
-
-function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- -- local head, n = delete_till_stop(head,start,stop)
-    local startchar = getchar(start)
-    local subtables = currentlookup.subtables
-    local lookupname = subtables[1]
-    local replacements = lookuphash[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 or replacement == "" 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
-            return multiple_glyphs(head,start,replacements,currentlookup.flags[1])
-        end
-    end
-    return head, start, false
-end
-
---[[ldx--
-Here we replace start by new glyph. First we delete the rest of the match.
---ldx]]--
-
--- char_1 mark_1 -> char_x mark_1 (ignore marks)
--- char_1 mark_1 -> char_x
-
--- to be checked: do we always have just one glyph?
--- we can also have alternates for marks
--- marks come last anyway
--- are there cases where we need to delete the mark
-
-function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-    local current = start
-    local subtables = currentlookup.subtables
-    local value  = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
-    while current do
-        if getid(current) == glyph_code then -- is this check needed?
-            local currentchar = getchar(current)
-            local lookupname = subtables[1]
-            local alternatives = lookuphash[lookupname]
-            if not alternatives then
-                if trace_bugs then
-                    logwarning("%s: no alternative hit",cref(kind,chainname,chainlookupname,lookupname))
-                end
-            else
-                alternatives = alternatives[currentchar]
-                if alternatives then
-                    local choice, comment = get_alternative_glyph(current,alternatives,value,trace_alternatives)
-                    if choice then
-                        if trace_alternatives then
-                            logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
-                        end
-                        resetinjection(start)
-                        setfield(start,"char",choice)
-                    else
-                        if trace_alternatives then
-                            logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
-                        end
-                    end
-                elseif trace_bugs then
-                    logwarning("%s: no alternative for %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar),comment)
-                end
-            end
-            return head, start, true
-        elseif current == stop then
-            break
-        else
-            current = getnext(current)
-        end
-    end
-    return head, 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(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
-    local startchar = getchar(start)
-    local subtables = currentlookup.subtables
-    local lookupname = subtables[1]
-    local ligatures = lookuphash[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 = getnext(start)
-            local discfound = false
-            local last = stop
-            local nofreplacements = 1
-            local skipmark = currentlookup.flags[1]
-            while s do
-                local id = getid(s)
-                if id == disc_code then
-                    if not discfound then
-                        discfound = s
-                    end
-                    if s == stop then
-                        break -- okay? or before the disc
-                    else
-                        s = getnext(s)
-                    end
-                else
-                    local schar = getchar(s)
-                    if skipmark and marks[schar] then -- marks
-                        s = getnext(s)
-                    else
-                        local lg = ligatures[schar]
-                        if lg then
-                            ligatures, last, nofreplacements = lg, s, nofreplacements + 1
-                            if s == stop then
-                                break
-                            else
-                                s = getnext(s)
-                            end
-                        else
-                            break
-                        end
-                    end
-                end
-            end
-            local l2 = ligatures.ligature
-            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 case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2))
-                    else
-                        logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2))
-                    end
-                end
-                head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
-                return head, start, true, nofreplacements, discfound
-            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(getchar(stop)))
-                end
-            end
-        end
-    end
-    return head, start, false, 0, false
-end
-
-function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
-    -- untested .. needs checking for the new model
-    local startchar = getchar(start)
-    local subtables = currentlookup.subtables
-    local lookupname = subtables[1]
-    local kerns = lookuphash[lookupname]
-    if kerns then
-        kerns = kerns[startchar] -- needed ?
-        if kerns then
-            local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns) -- ,characters[startchar])
-            if trace_kerns then
-                logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
-            end
-        end
-    end
-    return head, start, false
-end
-
-function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
-    local snext = getnext(start)
-    if snext then
-        local startchar = getchar(start)
-        local subtables = currentlookup.subtables
-        local lookupname = subtables[1]
-        local kerns = lookuphash[lookupname]
-        if kerns then
-            kerns = kerns[startchar]
-            if kerns then
-                local lookuptype = lookuptypes[lookupname]
-                local prev, done = start, false
-                local factor = tfmdata.parameters.factor
-                while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
-                    local nextchar = getchar(snext)
-                    local krn = kerns[nextchar]
-                    if not krn and marks[nextchar] then
-                        prev = snext
-                        snext = getnext(snext)
-                    else
-                        if not krn then
-                            -- skip
-                        elseif type(krn) == "table" then
-                            if lookuptype == "pair" then
-                                local a, b = krn[2], krn[3]
-                                if a and #a > 0 then
-                                    local startchar = getchar(start)
-                                    local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a) -- ,characters[startchar])
-                                    if trace_kerns then
-                                        logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
-                                    end
-                                end
-                                if b and #b > 0 then
-                                    local startchar = getchar(start)
-                                    local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b) -- ,characters[nextchar])
-                                    if trace_kerns then
-                                        logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
-                                    end
-                                end
-                            else
-                                report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
-                             -- local a, b = krn[2], krn[6]
-                             -- if a and a ~= 0 then
-                             --     local k = setkern(snext,factor,rlmode,a)
-                             --     if trace_kerns then
-                             --         logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),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 = setkern(snext,factor,rlmode,krn)
-                            if trace_kerns then
-                                logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
-                            end
-                            done = true
-                        end
-                        break
-                    end
-                end
-                return head, start, done
-            end
-        end
-    end
-    return head, start, false
-end
-
-function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-    local markchar = getchar(start)
-    if marks[markchar] then
-        local subtables = currentlookup.subtables
-        local lookupname = subtables[1]
-        local markanchors = lookuphash[lookupname]
-        if markanchors then
-            markanchors = markanchors[markchar]
-        end
-        if markanchors then
-            local base = getprev(start) -- [glyph] [start=mark]
-            if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-                local basechar = getchar(base)
-                if marks[basechar] then
-                    while true do
-                        base = getprev(base)
-                        if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-                            basechar = getchar(base)
-                            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 head, 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 = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
-                                    if trace_marks then
-                                        logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
-                                            cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
-                                    end
-                                    return head, 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 head, start, false
-end
-
-function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-    local markchar = getchar(start)
-    if marks[markchar] then
-        local subtables = currentlookup.subtables
-        local lookupname = subtables[1]
-        local markanchors = lookuphash[lookupname]
-        if markanchors then
-            markanchors = markanchors[markchar]
-        end
-        if markanchors then
-            local base = getprev(start) -- [glyph] [optional marks] [start=mark]
-            if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-                local basechar = getchar(base)
-                if marks[basechar] then
-                    while true do
-                        base = getprev(base)
-                        if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
-                            basechar = getchar(base)
-                            if not marks[basechar] then
-                                break
-                            end
-                        else
-                            if trace_bugs then
-                                logwarning("%s: no base for mark %s",cref(kind,chainname,chainlookupname,lookupname),markchar)
-                            end
-                            return head, start, false
-                        end
-                    end
-                end
-                -- todo: like marks a ligatures hash
-                local index = getligaindex(start)
-                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 = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
-                                        if trace_marks then
-                                            logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
-                                                cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
-                                        end
-                                        return head, 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 head, start, false
-end
-
-function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-    local markchar = getchar(start)
-    if marks[markchar] then
-    --  local markanchors = descriptions[markchar].anchors markanchors = markanchors and markanchors.mark
-        local subtables = currentlookup.subtables
-        local lookupname = subtables[1]
-        local markanchors = lookuphash[lookupname]
-        if markanchors then
-            markanchors = markanchors[markchar]
-        end
-        if markanchors then
-            local base = getprev(start) -- [glyph] [basemark] [start=mark]
-            local slc = getligaindex(start)
-            if slc then -- a rather messy loop ... needs checking with husayni
-                while base do
-                    local blc = getligaindex(base)
-                    if blc and blc ~= slc then
-                        base = getprev(base)
-                    else
-                        break
-                    end
-                end
-            end
-            if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go
-                local basechar = getchar(base)
-                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 = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
-                                    if trace_marks then
-                                        logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
-                                            cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
-                                    end
-                                    return head, 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_bugs then
-        logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
-    end
-    return head, start, false
-end
-
-function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-    local alreadydone = cursonce and getprop(start,a_cursbase)
-    if not alreadydone then
-        local startchar = getchar(start)
-        local subtables = currentlookup.subtables
-        local lookupname = subtables[1]
-        local exitanchors = lookuphash[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 = getnext(start)
-                while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do
-                    local nextchar = getchar(nxt)
-                    if marks[nextchar] then
-                        -- should not happen (maybe warning)
-                        nxt = getnext(nxt)
-                    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 = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
-                                                if trace_cursive then
-                                                    logprocess("%s: moving %s to %s cursive (%p,%p) 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
-                        elseif trace_bugs then
-                        --  logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
-                            onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
-                        end
-                        break
-                    end
-                end
-            end
-            return head, start, done
-        else
-            if trace_cursive and trace_details then
-                logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
-            end
-            return head, start, false
-        end
-    end
-    return head, 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, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
-    else
-        logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
-    end
-end
-
--- A previous version had disc collapsing code in the (single sub) handler plus some
--- checking in the main loop, but that left the pre/post sequences undone. The best
--- solution is to add some checking there and backtrack when a replace/post matches
--- but it takes a bit of work to figure out an efficient way (this is what the sweep*
--- names refer to). I might look into that variant one day again as it can replace
--- some other code too. In that approach we can have a special version for gub and pos
--- which gains some speed. This method does the test and passes info to the handlers
--- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the
--- main loop which also makes code elsewhere simpler (i.e. no need for the other special
--- runners and disc code in ligature building). I also experimented with pushing preceding
--- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards
--- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime).
---
--- In the meantime Kai had moved the code from the single chain into a more general handler
--- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought
--- it in sycn with the other code. Hopefully I didn't introduce errors. Note: this somewhat
--- complex approach is meant for fonts that implement (for instance) ligatures by character
--- replacement which to some extend is not that suitable for hyphenation. I also use some
--- helpers. This method passes some states but reparses the list. There is room for a bit of
--- speed up but that will be done in the context version. (In fact a partial rewrite of all
--- code can bring some more efficientry.)
---
--- I didn't test it with extremes but successive disc nodes still can give issues but in
--- order to handle that we need more complex code which also slows down even more. The main
--- loop variant could deal with that: test, collapse, backtrack.
-
-local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
-
-    if not start then
-        return head, start, false
-    end
-
-    local startishead   = start == head
-    local seq           = ck[3]
-    local f             = ck[4]
-    local l             = ck[5]
-    local s             = #seq
-    local done          = false
-    local sweepnode     = sweepnode
-    local sweeptype     = sweeptype
-    local sweepoverflow = false
-    local checkdisc     = getprev(head) -- hm bad name head
-    local keepdisc      = not sweepnode
-    local lookaheaddisc = nil
-    local backtrackdisc = nil
-    local current       = start
-    local last          = start
-    local prev          = getprev(start)
-
-    -- fishy: so we can overflow and then go on in the sweep?
-
-    local i = f
-    while i <= l do
-        local id = getid(current)
-        if id == glyph_code then
-            i       = i + 1
-            last    = current
-            current = getnext(current)
-        elseif id == disc_code then
-            if keepdisc then
-                keepdisc = false
-                if notmatchpre[current] ~= notmatchreplace[current] then
-                    lookaheaddisc = current
-                end
-                local replace = getfield(current,"replace")
-                while replace and i <= l do
-                    if getid(replace) == glyph_code then
-                        i = i + 1
-                    end
-                    replace = getnext(replace)
-                end
-                last    = current
-                current = getnext(c)
-            else
-                head, current = flattendisk(head,current)
-            end
-        else
-            last    = current
-            current = getnext(current)
-        end
-        if current then
-            -- go on
-        elseif sweepoverflow then
-            -- we already are folling up on sweepnode
-            break
-        elseif sweeptype == "post" or sweeptype == "replace" then
-            current = getnext(sweepnode)
-            if current then
-                sweeptype     = nil
-                sweepoverflow = true
-            else
-                break
-            end
-        end
-    end
-
-    if sweepoverflow then
-        local prev = current and getprev(current)
-        if not current or prev ~= sweepnode then
-            local head = getnext(sweepnode)
-            local tail = nil
-            if prev then
-                tail = prev
-                setfield(current,"prev",sweepnode)
-            else
-                tail = find_node_tail(head)
-            end
-            setfield(sweepnode,"next",current)
-            setfield(head,"prev",nil)
-            setfield(tail,"next",nil)
-            appenddisc(sweepnode,head)
-        end
-    end
-
-    if l < s then
-        local i = l
-        local t = sweeptype == "post" or sweeptype == "replace"
-        while current and i < s do
-            local id = getid(current)
-            if id == glyph_code then
-                i       = i + 1
-                current = getnext(current)
-            elseif id == disc_code then
-                if keepdisc then
-                    keepdisc = false
-                    if notmatchpre[current] ~= notmatchreplace[current] then
-                        lookaheaddisc = current
-                    end
-                    local replace = getfield(c,"replace")
-                    while replace and i < s do
-                        if getid(replace) == glyph_code then
-                            i = i + 1
-                        end
-                        replace = getnext(replace)
-                    end
-                    current = getnext(current)
-                elseif notmatchpre[current] ~= notmatchreplace[current] then
-                    head, current = flattendisk(head,current)
-                else
-                    current = getnext(current) -- HH
-                end
-            else
-                current = getnext(current)
-            end
-            if not current and t then
-                current = getnext(sweepnode)
-                if current then
-                    sweeptype = nil
-                end
-            end
-        end
-    end
-
-    if f > 1 then
-        local current = prev
-        local i       = f
-        local t       = sweeptype == "pre" or sweeptype == "replace"
-        if not current and t and current == checkdisk then
-            current = getprev(sweepnode)
-        end
-        while current and i > 1 do -- missing getprev added / moved outside
-            local id = getid(current)
-            if id == glyph_code then
-                i = i - 1
-            elseif id == disc_code then
-                if keepdisc then
-                    keepdisc = false
-                    if notmatchpost[current] ~= notmatchreplace[current] then
-                        backtrackdisc = current
-                    end
-                    local replace = getfield(current,"replace")
-                    while replace and i > 1 do
-                        if getid(replace) == glyph_code then
-                            i = i - 1
-                        end
-                        replace = getnext(replace)
-                    end
-                elseif notmatchpost[current] ~= notmatchreplace[current] then
-                    head, current = flattendisk(head,current)
-                end
-            end
-            current = getprev(current)
-            if t and current == checkdisk then
-                current = getprev(sweepnode)
-            end
-        end
-    end
-
-    local ok = false
-    if lookaheaddisc then
-
-        local cf            = start
-        local cl            = getprev(lookaheaddisc)
-        local cprev         = getprev(start)
-        local insertedmarks = 0
-
-        while cprev and getid(cf) == glyph_code and getfont(cf) == currentfont and getsubtype(cf) < 256 and marks[getchar(cf)] do
-            insertedmarks = insertedmarks + 1
-            cf            = cprev
-            startishead   = cf == head
-            cprev         = getprev(cprev)
-        end
-
-        setfield(lookaheaddisc,"prev",cprev)
-        if cprev then
-            setfield(cprev,"next",lookaheaddisc)
-        end
-        setfield(cf,"prev",nil)
-        setfield(cl,"next",nil)
-        if startishead then
-            head = lookaheaddisc
-        end
-
-        local replace = getfield(lookaheaddisc,"replace")
-        local pre     = getfield(lookaheaddisc,"pre")
-        local new     = copy_node_list(cf)
-        local cnew = new
-        for i=1,insertedmarks do
-            cnew = getnext(cnew)
-        end
-        local clast = cnew
-        for i=f,l do
-            clast = getnext(clast)
-        end
-        if not notmatchpre[lookaheaddisc] then
-            cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-        end
-        if not notmatchreplace[lookaheaddisc] then
-            new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-        end
-        if pre then
-            setfield(cl,"next",pre)
-            setfield(pre,"prev",cl)
-        end
-        if replace then
-            local tail = find_node_tail(new)
-            setfield(tail,"next",replace)
-            setfield(replace,"prev",tail)
-        end
-        setfield(lookaheaddisc,"pre",cf)      -- also updates tail
-        setfield(lookaheaddisc,"replace",new) -- also updates tail
-
-        start          = getprev(lookaheaddisc)
-        sweephead[cf]  = getnext(clast)
-        sweephead[new] = getnext(last)
-
-    elseif backtrackdisc then
-
-        local cf            = getnext(backtrackdisc)
-        local cl            = start
-        local cnext         = getnext(start)
-        local insertedmarks = 0
-
-        while cnext and getid(cnext) == glyph_code and getfont(cnext) == currentfont and getsubtype(cnext) < 256 and marks[getchar(cnext)] do
-            insertedmarks = insertedmarks + 1
-            cl            = cnext
-            cnext         = getnext(cnext)
-        end
-        if cnext then
-            setfield(cnext,"prev",backtrackdisc)
-        end
-        setfield(backtrackdisc,"next",cnext)
-        setfield(cf,"prev",nil)
-        setfield(cl,"next",nil)
-        local replace = getfield(backtrackdisc,"replace")
-        local post    = getfield(backtrackdisc,"post")
-        local new     = copy_node_list(cf)
-        local cnew    = find_node_tail(new)
-        for i=1,insertedmarks do
-            cnew = getprev(cnew)
-        end
-        local clast = cnew
-        for i=f,l do
-            clast = getnext(clast)
-        end
-        if not notmatchpost[backtrackdisc] then
-            cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-        end
-        if not notmatchreplace[backtrackdisc] then
-            new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-        end
-        if post then
-            local tail = find_node_tail(post)
-            setfield(tail,"next",cf)
-            setfield(cf,"prev",tail)
-        else
-            post = cf
-        end
-        if replace then
-            local tail = find_node_tail(replace)
-            setfield(tail,"next",new)
-            setfield(new,"prev",tail)
-        else
-            replace = new
-        end
-        setfield(backtrackdisc,"post",post)       -- also updates tail
-        setfield(backtrackdisc,"replace",replace) -- also updates tail
-        start              = getprev(backtrackdisc)
-        sweephead[post]    = getnext(clast)
-        sweephead[replace] = getnext(last)
-
-    else
-
-        head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-
-    end
-
-    return head, start, ok
-end
-
-local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
-    local sweepnode    = sweepnode
-    local sweeptype    = sweeptype
-    local diskseen     = false
-    local checkdisc    = getprev(head)
-    local flags        = sequence.flags
-    local done         = false
-    local skipmark     = flags[1]
-    local skipligature = flags[2]
-    local skipbase     = flags[3]
-    local markclass    = sequence.markclass
-    local skipped      = false
-
-    for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu)
-        local match   = true
-        local current = start
-        local last    = start
-        local ck      = contexts[k]
-        local seq     = ck[3]
-        local s       = #seq
-        -- f..l = mid string
-        if s == 1 then
-            -- never happens
-            match = getid(current) == glyph_code and getfont(current) == currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
-        else
-            -- maybe we need a better space check (maybe check for glue or category or combination)
-            -- we cannot optimize for n=2 because there can be disc nodes
-            local f = ck[4]
-            local l = ck[5]
-            -- current match
-            if f == 1 and f == l then -- current only
-                -- already a hit
-             -- match = true
-            else -- before/current/after | before/current | current/after
-                -- no need to test first hit (to be optimized)
-                if f == l then -- new, else last out of sync (f is > 1)
-                 -- match = true
-                else
-                    local discfound = nil
-                    local n = f + 1
-                    last = getnext(last)
-                    while n <= l do
-                        if not last and (sweeptype == "post" or sweeptype == "replace") then
-                            last      = getnext(sweepnode)
-                            sweeptype = nil
-                        end
-                        if last then
-                            local id = getid(last)
-                            if id == glyph_code then
-                                if getfont(last) == currentfont and getsubtype(last)<256 then
-                                    local char = getchar(last)
-                                    local ccd = descriptions[char]
-                                    if ccd then
-                                        local class = ccd.class or "base"
-                                        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 = getnext(last)
-                                        elseif seq[n][char] then
-                                            if n < l then
-                                                last = getnext(last)
-                                            end
-                                            n = n + 1
-                                        else
-                                            if discfound then
-                                                notmatchreplace[discfound] = true
-                                                match = not notmatchpre[discfound]
-                                            else
-                                                match = false
-                                            end
-                                            break
-                                        end
-                                    else
-                                        if discfound then
-                                            notmatchreplace[discfound] = true
-                                            match = not notmatchpre[discfound]
-                                        else
-                                            match = false
-                                        end
-                                        break
-                                    end
-                                else
-                                    if discfound then
-                                        notmatchreplace[discfound] = true
-                                        match = not notmatchpre[discfound]
-                                    else
-                                        match = false
-                                    end
-                                    break
-                                end
-                            elseif id == disc_code then
-                                diskseen              = true
-                                discfound             = last
-                                notmatchpre[last]     = nil
-                                notmatchpost[last]    = true
-                                notmatchreplace[last] = nil
-                                local pre     = getfield(last,"pre")
-                                local replace = getfield(last,"replace")
-                                if pre then
-                                    local n = n
-                                    while pre do
-                                        if seq[n][getchar(pre)] then
-                                            n = n + 1
-                                            pre = getnext(pre)
-                                            if n > l then
-                                                break
-                                            end
-                                        else
-                                            notmatchpre[last] = true
-                                            break
-                                        end
-                                    end
-                                    if n <= l then
-                                        notmatchpre[last] = true
-                                    end
-                                else
-                                    notmatchpre[last] = true
-                                end
-                                if replace then
-                                    -- so far we never entered this branch
-                                    while replace do
-                                        if seq[n][getchar(replace)] then
-                                            n = n + 1
-                                            replace = getnext(replace)
-                                            if n > l then
-                                                break
-                                            end
-                                        else
-                                            notmatchreplace[last] = true
-                                            match = not notmatchpre[last]
-                                            break
-                                        end
-                                    end
-                                    match = not notmatchpre[last]
-                                end
-                                last = getnext(last)
-                            else
-                                match = false
-                                break
-                            end
-                        else
-                            match = false
-                            break
-                        end
-                    end
-                end
-            end
-            -- before
-            if match and f > 1 then
-                local prev = getprev(start)
-                if prev then
-                    if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
-                        prev      = getprev(sweepnode)
-                     -- sweeptype = nil
-                    end
-                    if prev then
-                        local discfound = nil
-                        local n = f - 1
-                        while n >= 1 do
-                            if prev then
-                                local id = getid(prev)
-                                if id == glyph_code then
-                                    if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char
-                                        local char = getchar(prev)
-                                        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
-                                                if discfound then
-                                                    notmatchreplace[discfound] = true
-                                                    match = not notmatchpost[discfound]
-                                                else
-                                                    match = false
-                                                end
-                                                break
-                                            end
-                                        else
-                                            if discfound then
-                                                notmatchreplace[discfound] = true
-                                                match = not notmatchpost[discfound]
-                                            else
-                                                match = false
-                                            end
-                                            break
-                                        end
-                                    else
-                                        if discfound then
-                                            notmatchreplace[discfound] = true
-                                            match = not notmatchpost[discfound]
-                                        else
-                                            match = false
-                                        end
-                                        break
-                                    end
-                                elseif id == disc_code then
-                                    -- the special case: f i where i becomes dottless i ..
-                                    diskseen              = true
-                                    discfound             = prev
-                                    notmatchpre[prev]     = true
-                                    notmatchpost[prev]    = nil
-                                    notmatchreplace[prev] = nil
-                                    local pre     = getfield(prev,"pre")
-                                    local post    = getfield(prev,"post")
-                                    local replace = getfield(prev,"replace")
-                                    if pre ~= start and post ~= start and replace ~= start then
-                                        if post then
-                                            local n = n
-                                            local posttail = find_node_tail(post)
-                                            while posttail do
-                                                if seq[n][getchar(posttail)] then
-                                                    n = n - 1
-                                                    if posttail == post then
-                                                        break
-                                                    else
-                                                        posttail = getprev(posttail)
-                                                        if n < 1 then
-                                                            break
-                                                        end
-                                                    end
-                                                else
-                                                    notmatchpost[prev] = true
-                                                    break
-                                                end
-                                            end
-                                            if n >= 1 then
-                                                notmatchpost[prev] = true
-                                            end
-                                        else
-                                            notmatchpost[prev] = true
-                                        end
-                                        if replace then
-                                            -- we seldom enter this branch (e.g. on brill efficient)
-                                            local replacetail = find_node_tail(replace)
-                                            while replacetail do
-                                                if seq[n][getchar(replacetail)] then
-                                                    n = n - 1
-                                                    if replacetail == replace then
-                                                        break
-                                                    else
-                                                        replacetail = getprev(replacetail)
-                                                        if n < 1 then
-                                                            break
-                                                        end
-                                                    end
-                                                else
-                                                    notmatchreplace[prev] = true
-                                                    match = not notmatchpost[prev]
-                                                    break
-                                                end
-                                            end
-                                            if not match then
-                                                break
-                                            end
-                                        else
-                                            -- skip 'm
-                                        end
-                                    else
-                                        -- skip 'm
-                                    end
-                                elseif seq[n][32] then
-                                    n = n -1
-                                else
-                                    match = false
-                                    break
-                                end
-                                prev = getprev(prev)
-                            elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
-                                n = n - 1
-                            else
-                                match = false
-                                break
-                            end
-                        end
-                    else
-                        match = false
-                    end
-                else
-                    match = false
-                end
-            end
-            -- after
-            if match and s > l then
-                local current = last and getnext(last)
-                if not current then
-                    if sweeptype == "post" or sweeptype == "replace" then
-                        current   = getnext(sweepnode)
-                     -- sweeptype = nil
-                    end
-                end
-                if current then
-                    local discfound = nil
-                    -- 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 = getid(current)
-                            if id == glyph_code then
-                                if getfont(current) == currentfont and getsubtype(current)<256 then -- normal char
-                                    local char = getchar(current)
-                                    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
-                                            if discfound then
-                                                notmatchreplace[discfound] = true
-                                                match = not notmatchpre[discfound]
-                                            else
-                                                match = false
-                                            end
-                                            break
-                                        end
-                                    else
-                                        if discfound then
-                                            notmatchreplace[discfound] = true
-                                            match = not notmatchpre[discfound]
-                                        else
-                                            match = false
-                                        end
-                                        break
-                                    end
-                                else
-                                    if discfound then
-                                        notmatchreplace[discfound] = true
-                                        match = not notmatchpre[discfound]
-                                    else
-                                        match = false
-                                    end
-                                    break
-                                end
-                            elseif id == disc_code then
-                                diskseen                 = true
-                                discfound                = current
-                                notmatchpre[current]     = nil
-                                notmatchpost[current]    = true
-                                notmatchreplace[current] = nil
-                                local pre     = getfield(current,"pre")
-                                local replace = getfield(current,"replace")
-                                if pre then
-                                    local n = n
-                                    while pre do
-                                        if seq[n][getchar(pre)] then
-                                            n = n + 1
-                                            pre = getnext(pre)
-                                            if n > s then
-                                                break
-                                            end
-                                        else
-                                            notmatchpre[current] = true
-                                            break
-                                        end
-                                    end
-                                    if n <= s then
-                                        notmatchpre[current] = true
-                                    end
-                                else
-                                    notmatchpre[current] = true
-                                end
-                                if replace then
-                                    -- so far we never entered this branch
-                                    while replace do
-                                        if seq[n][getchar(replace)] then
-                                            n = n + 1
-                                            replace = getnext(replace)
-                                            if n > s then
-                                                break
-                                            end
-                                        else
-                                            notmatchreplace[current] = true
-                                            match = notmatchpre[current]
-                                            break
-                                        end
-                                    end
-                                    if not match then
-                                        break
-                                    end
-                                else
-                                    -- skip 'm
-                                end
-                            elseif seq[n][32] then -- brrr
-                                n = n + 1
-                            else
-                                match = false
-                                break
-                            end
-                            current = getnext(current)
-                        elseif seq[n][32] then
-                            n = n + 1
-                        else
-                            match = false
-                            break
-                        end
-                    end
-                else
-                    match = false
-                end
-            end
-        end
-        if match then
-            -- can lookups be of a different type ?
-            local diskchain = diskseen or sweepnode
-            if trace_contexts then
-                local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5]
-                local char = getchar(start)
-                if ck[9] then
-                    logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a",
-                        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 %a",
-                        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]
-                    if chainlookup then
-                        local chainproc = chainprocs[chainlookup.type]
-                        if chainproc then
-                            local ok
-                            if diskchain then
-                                head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
-                            else
-                                head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-                            end
-                            if ok then
-                                done = true
-                            end
-                        else
-                            logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
-                        end
-                    else -- shouldn't happen
-                        logprocess("%s is not yet supported",cref(kind,chainname,chainlookupname))
-                    end
-                 else
-                    local i = 1
-                    while start and true do
-                        if skipped then
-                            while true do -- todo: use properties
-                                local char = getchar(start)
-                                local ccd = descriptions[char]
-                                if ccd then
-                                    local class = ccd.class or "base"
-                                    if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
-                                        start = getnext(start)
-                                    else
-                                        break
-                                    end
-                                else
-                                    break
-                                end
-                            end
-                        end
-                        -- see remark in ms standard under : LookupType 5: Contextual Substitution Subtable
-                        local chainlookupname = chainlookups[i]
-                        local chainlookup = lookuptable[chainlookupname]
-                        if not chainlookup then
-                            -- we just advance
-                            i = i + 1
-                        else
-                            local chainproc = chainprocs[chainlookup.type]
-                            if not chainproc then
-                                -- actually an error
-                                logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
-                                i = i + 1
-                            else
-                                local ok, n
-                                if diskchain then
-                                    head, start, ok    = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
-                                else
-                                    head, start, ok, n = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
-                                end
-                                -- messy since last can be changed !
-                                if ok then
-                                    done = true
-                                    if n and n > 1 then
-                                        -- we have a ligature (cf the spec we advance one but we really need to test it
-                                        -- as there are fonts out there that are fuzzy and have too many lookups:
-                                        --
-                                        -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
-                                        --
-                                        if i + n > nofchainlookups then
-                                         -- if trace_contexts then
-                                         --     logprocess("%s: quitting lookups",cref(kind,chainname))
-                                         -- end
-                                            break
-                                        else
-                                            -- we need to carry one
-                                        end
-                                    end
-                                end
-                                i = i + 1
-                            end
-                        end
-                        if i > nofchainlookups or not start then
-                            break
-                        elseif start then
-                            start = getnext(start)
-                        end
-                    end
-                end
-            else
-                local replacements = ck[7]
-                if replacements then
-                    head, start, done = chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements) -- sequence
-                else
-                    done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts
-                    if trace_contexts then
-                        logprocess("%s: skipping match",cref(kind,chainname))
-                    end
-                end
-            end
-            if done then
-                break -- out of contexts (new, needs checking)
-            end
-        end
-    end
-    if diskseen then -- maybe move up so that we can turn checking on/off
-        notmatchpre     = { }
-        notmatchpost    = { }
-        notmatchreplace = { }
-    end
-    return head, 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 %a",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
-    report_process(...)
-end
-
-local logwarning = report_process
-
-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 %a, type %a, font %a, name %a",lookup,typ,currentfont,tfmdata.properties.fullname)
-    end
-end
-
-local resolved = { } -- we only resolve a font,script,language pair once
-
--- todo: pass all these 'locals' in a table
-
-local lookuphashes = { }
-
-setmetatableindex(lookuphashes, function(t,font)
-    local lookuphash = fontdata[font].resources.lookuphash
-    if not lookuphash or not next(lookuphash) then
-        lookuphash = false
-    end
-    t[font] = lookuphash
-    return lookuphash
-end)
-
--- fonts.hashes.lookups = lookuphashes
-
-local autofeatures = fonts.analyzers.features -- was: constants
-
-local function initialize(sequence,script,language,enabled)
-    local features = sequence.features
-    if features then
-        local order = sequence.order
-        if order then
-            for i=1,#order do --
-                local kind  = order[i] --
-                local valid = enabled[kind]
-                if valid then
-                    local scripts = features[kind] --
-                    local languages = scripts[script] or scripts[wildcard]
-                    if languages and (languages[language] or languages[wildcard]) then
-                        return { valid, autofeatures[kind] or false, sequence, kind }
-                    end
-                end
-            end
-        else
-            -- can't happen
-        end
-    end
-    return false
-end
-
-function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
-    local shared     = tfmdata.shared
-    local properties = tfmdata.properties
-    local language   = properties.language or "dflt"
-    local script     = properties.script   or "dflt"
-    local enabled    = shared.features
-    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 = {
-            -- indexed but we can also add specific data by key
-        }
-        rs[language] = rl
-        local sequences = tfmdata.resources.sequences
-        for s=1,#sequences do
-            local v = enabled and initialize(sequences[s],script,language,enabled)
-            if v then
-                rl[#rl+1] = v
-            end
-        end
-    end
-    return rl
-end
-
--- assumptions:
---
--- * languages that use complex disc nodes
-
-local function kernrun(disc,run)
-    --
-    -- we catch 
-    --
-    if trace_kernruns then
-        report_run("kern") -- will be more detailed
-    end
-    --
-    local prev      = getprev(disc) -- todo, keep these in the main loop
-    local next      = getnext(disc) -- todo, keep these in the main loop
-    --
-    local pre       = getfield(disc,"pre")
-    local post      = getfield(disc,"post")
-    local replace   = getfield(disc,"replace")
-    --
-    local prevmarks = prev
-    --
-    -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
-    -- has happened but then it should be in the disc so basically this test indicates an error)
-    --
-    while prevmarks and getid(prevmarks) == glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks) == currentfont and getsubtype(prevmarks) < 256 do
-        prevmarks = getprev(prevmarks)
-    end
-    --
-    if prev and (pre or replace) and not (getid(prev) == glyph_code and getfont(prev) == currentfont and getsubtype(prev)<256) then
-        prev = false
-    end
-    if next and (post or replace) and not (getid(next) == glyph_code and getfont(next) == currentfont and getsubtype(next)<256) then
-        next = false
-    end
-    --
-    if not pre then
-        -- go on
-    elseif prev then
-        local nest = getprev(pre)
-        setfield(pre,"prev",prev)
-        setfield(prev,"next",pre)
-        run(prevmarks,"preinjections")
-        setfield(pre,"prev",nest)
-        setfield(prev,"next",disc)
-    else
-        run(pre,"preinjections")
-    end
-    --
-    if not post then
-        -- go on
-    elseif next then
-        local tail = find_node_tail(post)
-        setfield(tail,"next",next)
-        setfield(next,"prev",tail)
-        run(post,"postinjections",next)
-        setfield(tail,"next",nil)
-        setfield(next,"prev",disc)
-    else
-        run(post,"postinjections")
-    end
-    --
-    if not replace and prev and next then
-        -- this should be already done by discfound
-        setfield(prev,"next",next)
-        setfield(next,"prev",prev)
-        run(prevmarks,"injections",next)
-        setfield(prev,"next",disc)
-        setfield(next,"prev",disc)
-    elseif prev and next then
-        local tail = find_node_tail(replace)
-        local nest = getprev(replace)
-        setfield(replace,"prev",prev)
-        setfield(prev,"next",replace)
-        setfield(tail,"next",next)
-        setfield(next,"prev",tail)
-        run(prevmarks,"replaceinjections",next)
-        setfield(replace,"prev",nest)
-        setfield(prev,"next",disc)
-        setfield(tail,"next",nil)
-        setfield(next,"prev",disc)
-    elseif prev then
-        local nest = getprev(replace)
-        setfield(replace,"prev",prev)
-        setfield(prev,"next",replace)
-        run(prevmarks,"replaceinjections")
-        setfield(replace,"prev",nest)
-        setfield(prev,"next",disc)
-    elseif next then
-        local tail = find_node_tail(replace)
-        setfield(tail,"next",next)
-        setfield(next,"prev",tail)
-        run(replace,"replaceinjections",next)
-        setfield(tail,"next",nil)
-        setfield(next,"prev",disc)
-    else
-        run(replace,"replaceinjections")
-    end
-end
-
--- the if new test might be dangerous as luatex will check / set some tail stuff
--- in a temp node
-
-local function comprun(disc,run)
-    if trace_compruns then
-        report_run("comp: %s",languages.serializediscretionary(disc))
-    end
-    --
-    local pre = getfield(disc,"pre")
-    if pre then
-        sweepnode = disc
-        sweeptype = "pre" -- in alternative code preinjections is used (also used then for proeprties, saves a variable)
-        local new, done = run(pre)
-        if done then
-            setfield(disc,"pre",new)
-        end
-    end
-    --
-    local post = getfield(disc,"post")
-    if post then
-        sweepnode = disc
-        sweeptype = "post"
-        local new, done = run(post)
-        if done then
-            setfield(disc,"post",new)
-        end
-    end
-    --
-    local replace = getfield(disc,"replace")
-    if replace then
-        sweepnode = disc
-        sweeptype = "replace"
-        local new, done = run(replace)
-        if done then
-            setfield(disc,"replace",new)
-        end
-    end
-    sweepnode = nil
-    sweeptype = nil
-end
-
-local function testrun(disc,trun,crun) -- use helper
-    local next = getnext(disc)
-    if next then
-        local replace = getfield(disc,"replace")
-        if replace then
-            local prev = getprev(disc)
-            if prev then
-                -- only look ahead
-                local tail = find_node_tail(replace)
-             -- local nest = getprev(replace)
-                setfield(tail,"next",next)
-                setfield(next,"prev",tail)
-                if trun(replace,next) then
-                    setfield(disc,"replace",nil) -- beware, side effects of nest so first
-                    setfield(prev,"next",replace)
-                    setfield(replace,"prev",prev)
-                    setfield(next,"prev",tail)
-                    setfield(tail,"next",next)
-                    setfield(disc,"prev",nil)
-                    setfield(disc,"next",nil)
-                    flush_node_list(disc)
-                    return replace -- restart
-                else
-                    setfield(tail,"next",nil)
-                    setfield(next,"prev",disc)
-                end
-            else
-                -- weird case
-            end
-        else
-            -- no need
-        end
-    else
-        -- weird case
-    end
-    comprun(disc,crun)
-    return next
-end
-
-local function discrun(disc,drun,krun)
-    local next = getnext(disc)
-    local prev = getprev(disc)
-    if trace_discruns then
-        report_run("disc") -- will be more detailed
-    end
-    if next and prev then
-        setfield(prev,"next",next)
-     -- setfield(next,"prev",prev)
-        drun(prev)
-        setfield(prev,"next",disc)
-     -- setfield(next,"prev",disc)
-    end
-    --
-    local pre = getfield(disc,"pre")
-    if not pre then
-        -- go on
-    elseif prev then
-        local nest = getprev(pre)
-        setfield(pre,"prev",prev)
-        setfield(prev,"next",pre)
-        krun(prev,"preinjections")
-        setfield(pre,"prev",nest)
-        setfield(prev,"next",disc)
-    else
-        krun(pre,"preinjections")
-    end
-    return next
-end
-
--- todo: maybe run lr and rl stretches
-
-local function featuresprocessor(head,font,attr)
-
-    local lookuphash = lookuphashes[font] -- we can also check sequences here
-
-    if not lookuphash then
-        return head, false
-    end
-
-    head = tonut(head)
-
-    if trace_steps then
-        checkstep(head)
-    end
-
-    tfmdata         = fontdata[font]
-    descriptions    = tfmdata.descriptions
-    characters      = tfmdata.characters
-    resources       = tfmdata.resources
-
-    marks           = resources.marks
-    anchorlookups   = resources.lookup_to_anchor
-    lookuptable     = resources.lookups
-    lookuptypes     = resources.lookuptypes
-    lookuptags      = resources.lookuptags
-
-    currentfont     = font
-    rlmode          = 0
-    sweephead       = { }
-
-    local sequences = resources.sequences
-    local done      = false
-    local datasets  = otf.dataset(tfmdata,font,attr)
-
-    local dirstack  = { } -- could move outside function
-
-    -- We could work on sub start-stop ranges instead but I wonder if there is that
-    -- much speed gain (experiments showed that it made not much sense) and we need
-    -- to keep track of directions anyway. Also at some point I want to play with
-    -- font interactions and then we do need the full sweeps.
-
-    -- Keeping track of the headnode is needed for devanagari (I generalized it a bit
-    -- so that multiple cases are also covered.)
-
-    -- We don't goto the next node of a disc node is created so that we can then treat
-    -- the pre, post and replace. It's abit of a hack but works out ok for most cases.
-
-    -- there can be less subtype and attr checking in the comprun etc helpers
-
-    for s=1,#datasets do
-        local dataset      = datasets[s]
-              featurevalue = dataset[1] -- todo: pass to function instead of using a global
-        local attribute    = dataset[2]
-        local sequence     = dataset[3] -- sequences[s] -- also dataset[5]
-        local kind         = dataset[4]
-        ----- chain        = dataset[5] -- sequence.chain or 0
-        local rlparmode    = 0
-        local topstack     = 0
-        local success      = false
-        local typ          = sequence.type
-        local gpossing     = typ == "gpos_single" or typ == "gpos_pair" -- maybe all of them
-        local subtables    = sequence.subtables
-        local handler      = handlers[typ]
-        if typ == "gsub_reversecontextchain" then -- chain < 0
-            -- this is a limited case, no special treatments like 'init' etc
-            -- we need to get rid of this slide! probably no longer needed in latest luatex
-            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 = getid(start)
-                if id == glyph_code then
-                    if getfont(start) == font and getsubtype(start) < 256 then
-                        local a = getattr(start,0)
-                        if a then
-                            a = a == attr
-                        else
-                            a = true
-                        end
-                        if a then
-                            local char = getchar(start)
-                            for i=1,#subtables do
-                                local lookupname = subtables[i]
-                                local lookupcache = lookuphash[lookupname]
-                                if lookupcache then
-                                    local lookupmatch = lookupcache[char]
-                                    if lookupmatch then
-                                        -- todo: disc?
-                                        head, start, success = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
-                                        if success then
-                                            break
-                                        end
-                                    end
-                                else
-                                    report_missing_cache(typ,lookupname)
-                                end
-                            end
-                            if start then start = getprev(start) end
-                        else
-                            start = getprev(start)
-                        end
-                    else
-                        start = getprev(start)
-                    end
-                else
-                    start = getprev(start)
-                end
-            end
-        else
-            local ns = #subtables
-            local start = head -- local ?
-            rlmode = 0 -- to be checked ?
-            if ns == 1 then -- happens often
-                local lookupname  = subtables[1]
-                local lookupcache = lookuphash[lookupname]
-                if not lookupcache then -- also check for empty cache
-                    report_missing_cache(typ,lookupname)
-                else
-
-                    local function c_run(head) -- no need to check for 256 and attr probably also the same
-                        local done  = false
-                        local start = sweephead[head]
-                        if start then
-                            sweephead[head] = nil
-                        else
-                            start = head
-                        end
-                        while start do
-                            local id = getid(start)
-                            if id ~= glyph_code then
-                                -- very unlikely
-                                start = getnext(start)
-                            elseif getfont(start) == font and getsubtype(start) < 256 then
-                                local a = getattr(start,0)
-                                if a then
-                                    a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
-                                else
-                                    a = not attribute or getprop(start,a_state) == attribute
-                                end
-                                if a then
-                                    local lookupmatch = lookupcache[getchar(start)]
-                                    if lookupmatch then
-                                        -- sequence kan weg
-                                        local ok
-                                        head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
-                                        if ok then
-                                            done = true
-                                        end
-                                    end
-                                    if start then start = getnext(start) end
-                                else
-                                    start = getnext(start)
-                                end
-                            else
-                                return head, false
-                            end
-                        end
-                        if done then
-                            success = true -- needed in this subrun?
-                        end
-                        return head, done
-                    end
-
-                    local function t_run(start,stop)
-                        while start ~= stop do
-                            local id = getid(start)
-                            if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
-                                local a = getattr(start,0)
-                                if a then
-                                    a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
-                                else
-                                    a = not attribute or getprop(start,a_state) == attribute
-                                end
-                                if a then
-                                    local lookupmatch = lookupcache[getchar(start)]
-                                    if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
-                                        -- if we need more than ligatures we can outline the code and use functions
-                                        local s = getnext(start)
-                                        local l = nil
-                                        while s do
-                                            local lg = lookupmatch[getchar(s)]
-                                            if lg then
-                                                l = lg
-                                                s = getnext(s)
-                                            else
-                                                break
-                                            end
-                                        end
-                                        if l and l.ligature then
-                                            return true
-                                        end
-                                    end
-                                end
-                                start = getnext(start)
-                            else
-                                break
-                            end
-                        end
-                    end
-
-                    local function d_run(prev) -- we can assume that prev and next are glyphs
-                        local a = getattr(prev,0)
-                        if a then
-                            a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
-                        else
-                            a = not attribute or getprop(prev,a_state) == attribute
-                        end
-                        if a then
-                            local lookupmatch = lookupcache[getchar(prev)]
-                            if lookupmatch then
-                                -- sequence kan weg
-                                local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
-                                if ok then
-                                    done    = true
-                                    success = true
-                                end
-                            end
-                        end
-                    end
-
-                    local function k_run(sub,injection,last)
-                        local a = getattr(sub,0)
-                        if a then
-                            a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
-                        else
-                            a = not attribute or getprop(sub,a_state) == attribute
-                        end
-                        if a then
-                            -- sequence kan weg
-                            for n in traverse_nodes(sub) do -- only gpos
-                                if n == last then
-                                    break
-                                end
-                                local id = getid(n)
-                                if id == glyph_code then
-                                    local lookupmatch = lookupcache[getchar(n)]
-                                    if lookupmatch then
-                                        local h, d, ok = handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
-                                        if ok then
-                                            done    = true
-                                            success = true
-                                        end
-                                    end
-                                else
-                                    -- message
-                                end
-                            end
-                        end
-                    end
-
-                    while start do
-                        local id = getid(start)
-                        if id == glyph_code then
-                            if getfont(start) == font and getsubtype(start) < 256 then -- why a 256 test ...
-                                local a = getattr(start,0)
-                                if a then
-                                    a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
-                                else
-                                    a = not attribute or getprop(start,a_state) == attribute
-                                end
-                                if a then
-                                    local char        = getchar(start)
-                                    local lookupmatch = lookupcache[char]
-                                    if lookupmatch then
-                                        -- sequence kan weg
-                                        local ok
-                                        head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
-                                        if ok then
-                                            success = true
-                                        elseif gpossing and zwnjruns and char == zwnj then
-                                            discrun(start,d_run)
-                                        end
-                                    elseif gpossing and zwnjruns and char == zwnj then
-                                        discrun(start,d_run)
-                                    end
-                                    if start then start = getnext(start) end
-                                else
-                                   start = getnext(start)
-                                end
-                            else
-                                start = getnext(start)
-                            end
-                        elseif id == disc_code then
-                            if gpossing then
-                                kernrun(start,k_run)
-                                start = getnext(start)
-                            elseif typ == "gsub_ligature" then
-                                start = testrun(start,t_run,c_run)
-                            else
-                                comprun(start,c_run)
-                                start = getnext(start)
-                            end
-                        elseif id == math_code then
-                            start = getnext(end_of_math(start))
-                        else
-                            start = getnext(start)
-                        end
-                    end
-                end
-
-            else
-
-                local function c_run(head)
-                    local done  = false
-                    local start = sweephead[head]
-                    if start then
-                        sweephead[head] = nil
-                    else
-                        start = head
-                    end
-                    while start do
-                        local id = getid(start)
-                        if id ~= glyph_code then
-                            -- very unlikely
-                            start = getnext(start)
-                        elseif getfont(start) == font and getsubtype(start) < 256 then
-                            local a = getattr(start,0)
-                            if a then
-                                a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
-                            else
-                                a = not attribute or getprop(start,a_state) == attribute
-                            end
-                            if a then
-                                local char = getchar(start)
-                                for i=1,ns do
-                                    local lookupname = subtables[i]
-                                    local lookupcache = lookuphash[lookupname]
-                                    if lookupcache then
-                                        local lookupmatch = lookupcache[char]
-                                        if lookupmatch then
-                                            -- we could move all code inline but that makes things even more unreadable
-                                            local ok
-                                            head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
-                                            if ok then
-                                                done = true
-                                                break
-                                            elseif not start then
-                                                -- don't ask why ... shouldn't happen
-                                                break
-                                            end
-                                        end
-                                    else
-                                        report_missing_cache(typ,lookupname)
-                                    end
-                                end
-                                if start then start = getnext(start) end
-                            else
-                                start = getnext(start)
-                            end
-                        else
-                            return head, false
-                        end
-                    end
-                    if done then
-                        success = true
-                    end
-                    return head, done
-                end
-
-                local function d_run(prev)
-                    local a = getattr(prev,0)
-                    if a then
-                        a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
-                    else
-                        a = not attribute or getprop(prev,a_state) == attribute
-                    end
-                    if a then
-                        -- brr prev can be disc
-                        local char = getchar(prev)
-                        for i=1,ns do
-                            local lookupname  = subtables[i]
-                            local lookupcache = lookuphash[lookupname]
-                            if lookupcache then
-                                local lookupmatch = lookupcache[char]
-                                if lookupmatch then
-                                    -- we could move all code inline but that makes things even more unreadable
-                                    local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,i)
-                                    if ok then
-                                        done = true
-                                        break
-                                    end
-                                end
-                            else
-                                report_missing_cache(typ,lookupname)
-                            end
-                        end
-                    end
-                end
-
-               local function k_run(sub,injection,last)
-                    local a = getattr(sub,0)
-                    if a then
-                        a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
-                    else
-                        a = not attribute or getprop(sub,a_state) == attribute
-                    end
-                    if a then
-                        for n in traverse_nodes(sub) do -- only gpos
-                            if n == last then
-                                break
-                            end
-                            local id = getid(n)
-                            if id == glyph_code then
-                                local char = getchar(n)
-                                for i=1,ns do
-                                    local lookupname  = subtables[i]
-                                    local lookupcache = lookuphash[lookupname]
-                                    if lookupcache then
-                                        local lookupmatch = lookupcache[char]
-                                        if lookupmatch then
-                                            local h, d, ok = handler(head,n,kind,lookupname,lookupmatch,sequence,lookuphash,i,injection)
-                                            if ok then
-                                                done = true
-                                                break
-                                            end
-                                        end
-                                    else
-                                        report_missing_cache(typ,lookupname)
-                                    end
-                                end
-                            else
-                                -- message
-                            end
-                        end
-                    end
-                end
-
-                local function t_run(start,stop)
-                    while start ~= stop do
-                        local id = getid(start)
-                        if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
-                            local a = getattr(start,0)
-                            if a then
-                                a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
-                            else
-                                a = not attribute or getprop(start,a_state) == attribute
-                            end
-                            if a then
-                                local char = getchar(start)
-                                for i=1,ns do
-                                    local lookupname  = subtables[i]
-                                    local lookupcache = lookuphash[lookupname]
-                                    if lookupcache then
-                                        local lookupmatch = lookupcache[char]
-                                        if lookupmatch then
-                                            -- if we need more than ligatures we can outline the code and use functions
-                                            local s = getnext(start)
-                                            local l = nil
-                                            while s do
-                                                local lg = lookupmatch[getchar(s)]
-                                                if lg then
-                                                    l = lg
-                                                    s = getnext(s)
-                                                else
-                                                    break
-                                                end
-                                            end
-                                            if l and l.ligature then
-                                                return true
-                                            end
-                                        end
-                                    else
-                                        report_missing_cache(typ,lookupname)
-                                    end
-                                end
-                            end
-                            start = getnext(start)
-                        else
-                            break
-                        end
-                    end
-                end
-
-                while start do
-                    local id = getid(start)
-                    if id == glyph_code then
-                        if getfont(start) == font and getsubtype(start) < 256 then
-                            local a = getattr(start,0)
-                            if a then
-                                a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
-                            else
-                                a = not attribute or getprop(start,a_state) == attribute
-                            end
-                            if a then
-                                for i=1,ns do
-                                    local lookupname  = subtables[i]
-                                    local lookupcache = lookuphash[lookupname]
-                                    if lookupcache then
-                                        local char = getchar(start)
-                                        local lookupmatch = lookupcache[char]
-                                        if lookupmatch then
-                                            -- we could move all code inline but that makes things even more unreadable
-                                            local ok
-                                            head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
-                                            if ok then
-                                                success = true
-                                                break
-                                            elseif not start then
-                                                -- don't ask why ... shouldn't happen
-                                                break
-                                            elseif gpossing and zwnjruns and char == zwnj then
-                                                discrun(start,d_run)
-                                            end
-                                        elseif gpossing and zwnjruns and char == zwnj then
-                                            discrun(start,d_run)
-                                        end
-                                    else
-                                        report_missing_cache(typ,lookupname)
-                                    end
-                                end
-                                if start then start = getnext(start) end
-                            else
-                                start = getnext(start)
-                            end
-                        else
-                            start = getnext(start)
-                        end
-                    elseif id == disc_code then
-                        if gpossing then
-                            kernrun(start,k_run)
-                            start = getnext(start)
-                        elseif typ == "gsub_ligature" then
-                            start = testrun(start,t_run,c_run)
-                        else
-                            comprun(start,c_run)
-                            start = getnext(start)
-                        end
-                    elseif id == math_code then
-                        start = getnext(end_of_math(start))
-                    else
-                        start = getnext(start)
-                    end
-                end
-            end
-        end
-        if success then
-            done = true
-        end
-        if trace_steps then -- ?
-            registerstep(head)
-        end
-
-    end
-
-    head = tonode(head)
-
-    return head, done
-end
-
--- this might move to the loader
-
-local function generic(lookupdata,lookupname,unicode,lookuphash)
-    local target = lookuphash[lookupname]
-    if target then
-        target[unicode] = lookupdata
-    else
-        lookuphash[lookupname] = { [unicode] = lookupdata }
-    end
-end
-
-local function ligature(lookupdata,lookupname,unicode,lookuphash)
-    local target = lookuphash[lookupname]
-    if not target then
-        target = { }
-        lookuphash[lookupname] = target
-    end
-    for i=1,#lookupdata do
-        local li = lookupdata[i]
-        local tu = target[li]
-        if not tu then
-            tu = { }
-            target[li] = tu
-        end
-        target = tu
-    end
-    target.ligature = unicode
-end
-
-local function pair(lookupdata,lookupname,unicode,lookuphash)
-    local target = lookuphash[lookupname]
-    if not target then
-        target = { }
-        lookuphash[lookupname] = target
-    end
-    local others = target[unicode]
-    local paired = lookupdata[1]
-    if others then
-        others[paired] = lookupdata
-    else
-        others = { [paired] = lookupdata }
-        target[unicode] = others
-    end
-end
-
-local action = {
-    substitution = generic,
-    multiple     = generic,
-    alternate    = generic,
-    position     = generic,
-    ligature     = ligature,
-    pair         = pair,
-    kern         = pair,
-}
-
-local function prepare_lookups(tfmdata)
-
-    local rawdata          = tfmdata.shared.rawdata
-    local resources        = rawdata.resources
-    local lookuphash       = resources.lookuphash
-    local anchor_to_lookup = resources.anchor_to_lookup
-    local lookup_to_anchor = resources.lookup_to_anchor
-    local lookuptypes      = resources.lookuptypes
-    local characters       = tfmdata.characters
-    local descriptions     = tfmdata.descriptions
-    local duplicates       = resources.duplicates
-
-    -- we cannot free the entries in the descriptions as sometimes we access
-    -- then directly (for instance anchors) ... selectively freeing does save
-    -- much memory as it's only a reference to a table and the slot in the
-    -- description hash is not freed anyway
-
-    -- we can delay this using metatables so that we don't make the hashes for
-    -- features we don't use but then we need to loop over the characters
-    -- many times so we gain nothing
-
-    for unicode, character in next, characters do -- we cannot loop over descriptions !
-
-        local description = descriptions[unicode]
-
-        if description then
-
-            local lookups = description.slookups
-            if lookups then
-                for lookupname, lookupdata in next, lookups do
-                    action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash,duplicates)
-                end
-            end
-
-            local lookups = description.mlookups
-            if lookups then
-                for lookupname, lookuplist in next, lookups do
-                    local lookuptype = lookuptypes[lookupname]
-                    for l=1,#lookuplist do
-                        local lookupdata = lookuplist[l]
-                        action[lookuptype](lookupdata,lookupname,unicode,lookuphash,duplicates)
-                    end
-                end
-            end
-
-            local list = description.kerns
-            if list then
-                for lookup, krn in next, list do  -- ref to glyph, saves lookup
-                    local target = lookuphash[lookup]
-                    if target then
-                        target[unicode] = krn
-                    else
-                        lookuphash[lookup] = { [unicode] = krn }
-                    end
-                end
-            end
-
-            local list = description.anchors
-            if list then
-                for typ, anchors in next, list do -- types
-                    if typ == "mark" or 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 target = lookuphash[lookup]
-                                    if target then
-                                        target[unicode] = anchors
-                                    else
-                                        lookuphash[lookup] = { [unicode] = anchors }
-                                    end
-                                end
-                            end
-                        end
-                    end
-                end
-            end
-
-        end
-
-    end
-
-end
-
--- so far
-
-local function split(replacement,original)
-    local result = { }
-    for i=1,#replacement do
-        result[original[i]] = replacement[i]
-    end
-    return result
-end
-
-local valid = {
-    coverage        = { chainsub = true, chainpos = true, contextsub = true },
-    reversecoverage = { reversesub = true },
-    glyphs          = { chainsub = true, chainpos = true },
-}
-
-local function prepare_contextchains(tfmdata)
-    local rawdata    = tfmdata.shared.rawdata
-    local resources  = rawdata.resources
-    local lookuphash = resources.lookuphash
-    local lookuptags = resources.lookuptags
-    local lookups    = rawdata.lookups
-    if lookups then
-        for lookupname, lookupdata in next, rawdata.lookups do
-            local lookuptype = lookupdata.type
-            if lookuptype then
-                local rules = lookupdata.rules
-                if rules then
-                    local format = lookupdata.format
-                    local validformat = valid[format]
-                    if not validformat then
-                        report_prepare("unsupported format %a",format)
-                    elseif not validformat[lookuptype] then
-                        -- todo: dejavu-serif has one (but i need to see what use it has)
-                        report_prepare("unsupported format %a, lookuptype %a, lookupname %a",format,lookuptype,lookuptags[lookupname])
-                    else
-                        local contexts = lookuphash[lookupname]
-                        if not contexts then
-                            contexts = { }
-                            lookuphash[lookupname] = contexts
-                        end
-                        local t, nt = { }, 0
-                        for nofrules=1,#rules do
-                            local rule         = rules[nofrules]
-                            local current      = rule.current
-                            local before       = rule.before
-                            local after        = rule.after
-                            local replacements = rule.replacements
-                            local sequence     = { }
-                            local nofsequences = 0
-                            -- Eventually we can store start, stop and sequence in the cached file
-                            -- but then less sharing takes place so best not do that without a lot
-                            -- of profiling so let's forget about it.
-                            if before then
-                                for n=1,#before do
-                                    nofsequences = nofsequences + 1
-                                    sequence[nofsequences] = before[n]
-                                end
-                            end
-                            local start = nofsequences + 1
-                            for n=1,#current do
-                                nofsequences = nofsequences + 1
-                                sequence[nofsequences] = current[n]
-                            end
-                            local stop = nofsequences
-                            if after then
-                                for n=1,#after do
-                                    nofsequences = nofsequences + 1
-                                    sequence[nofsequences] = after[n]
-                                end
-                            end
-                            if sequence[1] then
-                                -- Replacements only happen with reverse lookups as they are single only. We
-                                -- could pack them into current (replacement value instead of true) and then
-                                -- use sequence[start] instead but it's somewhat ugly.
-                                nt = nt + 1
-                                t[nt] = { 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
-                else
-                    -- no rules
-                end
-            else
-                report_prepare("missing lookuptype for lookupname %a",lookuptags[lookupname])
-            end
-        end
-    end
-end
-
--- we can consider lookuphash == false (initialized but empty) vs lookuphash == table
-
-local function featuresinitializer(tfmdata,value)
-    if true then -- value then
-        -- beware we need to use the topmost properties table
-        local rawdata    = tfmdata.shared.rawdata
-        local properties = rawdata.properties
-        if not properties.initialized then
-            local starttime = trace_preparing and os.clock()
-            local resources = rawdata.resources
-            resources.lookuphash = resources.lookuphash or { }
-            prepare_contextchains(tfmdata)
-            prepare_lookups(tfmdata)
-            properties.initialized = true
-            if trace_preparing then
-                report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,tfmdata.properties.fullname)
-            end
-        end
-    end
-end
-
-registerotffeature {
-    name         = "features",
-    description  = "features",
-    default      = true,
-    initializers = {
-        position = 1,
-        node     = featuresinitializer,
-    },
-    processors   = {
-        node     = featuresprocessor,
-    }
-}
-
--- This can be used for extra handlers, but should be used with care!
-
-otf.handlers = handlers
diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua
index f18ba35db..2e34fb801 100644
--- a/tex/generic/context/luatex/luatex-fonts.lua
+++ b/tex/generic/context/luatex/luatex-fonts.lua
@@ -215,9 +215,11 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
         loadmodule('font-oti.lua')
         loadmodule('font-otf.lua')
         loadmodule('font-otb.lua')
-        loadmodule('luatex-fonts-inj.lua') -- normally the same as font-inj.lua
+        ----------('luatex-fonts-inj.lua') -- normally the same as font-inj.lua / beware loadmodule is parsed
+        loadmodule('font-inj.lua')
         loadmodule('luatex-fonts-ota.lua')
-        loadmodule('luatex-fonts-otn.lua') -- normally the same as font-otn.lua
+        ----------('luatex-fonts-otn.lua') -- normally the same as font-otn.lua / beware loadmodule is parsed
+        loadmodule('font-otn.lua')
         loadmodule('font-otp.lua')
         loadmodule('luatex-fonts-lua.lua')
         loadmodule('font-def.lua')         -- this code (stripped) might end up in luatex-fonts-def.lua
diff --git a/tex/generic/context/luatex/luatex-languages.lua b/tex/generic/context/luatex/luatex-languages.lua
index 1ea8c1fd1..cecd60c13 100644
--- a/tex/generic/context/luatex/luatex-languages.lua
+++ b/tex/generic/context/luatex/luatex-languages.lua
@@ -16,28 +16,33 @@ function languages.loadpatterns(tag)
     if not loaded[tag] then
         loaded[tag] = 0
         local filename = kpse.find_file("lang-" .. tag .. ".lua")
-        if filename and filename == "" then
-            print("")
+        if not filename or filename == "" then
+            texio.write("")
         else
             local whatever = loadfile(filename)
             if type(whatever) == "function" then
                 whatever = whatever()
                 if type(whatever) == "table" then
+                    texio.write("")
                     local characters = whatever.patterns.characters or ""
                     local patterns = whatever.patterns.data or ""
                     local exceptions = whatever.exceptions.data or ""
-                    local language = lang.new()
                     for b in string.utfvalues(characters) do
+                        -- what about uppercase
+-- lang.sethjcode(b,b)
                         tex.setlccode(b,b)
                     end
+                    local language = lang.new()
                     lang.patterns(language, patterns)
                     lang.hyphenation(language, exceptions)
                     loaded[tag] = lang.id(language)
                 else
-                    print("")
+                    texio.write("")
+                    os.exit()
                 end
             else
-                print("")
+                texio.write("")
+                os.exit()
             end
         end
     end
diff --git a/tex/generic/context/luatex/luatex-languages.tex b/tex/generic/context/luatex/luatex-languages.tex
index 9778da39a..a087b3093 100644
--- a/tex/generic/context/luatex/luatex-languages.tex
+++ b/tex/generic/context/luatex/luatex-languages.tex
@@ -8,6 +8,8 @@
 
 %D Cf. discussion on \CONTEXT\ list:
 
+% \savinghyphcodes1
+
 \directlua {
     dofile(kpse.find_file("luatex-languages.lua","tex"))
 }
diff --git a/tex/generic/context/luatex/luatex-pdf.tex b/tex/generic/context/luatex/luatex-pdf.tex
index 49ca9c2d6..46e36d673 100644
--- a/tex/generic/context/luatex/luatex-pdf.tex
+++ b/tex/generic/context/luatex/luatex-pdf.tex
@@ -122,7 +122,6 @@
     \xdef\pdfpkresolution             {\pdfvariable pkresolution}
     \xdef\pdfinclusioncopyfonts       {\pdfvariable inclusioncopyfonts}
     \xdef\pdfinclusionerrorlevel      {\pdfvariable inclusionerrorlevel}
-    \xdef\pdfreplacefont              {\pdfvariable replacefont}
     \xdef\pdfgentounicode             {\pdfvariable gentounicode}
     \xdef\pdfpagebox                  {\pdfvariable pagebox}
     \xdef\pdfminorversion             {\pdfvariable minorversion}
@@ -155,7 +154,6 @@
     \global\pdfpkresolution         72
     \global\pdfinclusioncopyfonts    0
     \global\pdfinclusionerrorlevel   0
-    \global\pdfreplacefont           0
     \global\pdfgentounicode          0
     \global\pdfpagebox               0
     \global\pdfminorversion          4
-- 
cgit v1.2.3