From 608f6a9dca87c2073c2a74c7eb961ec3077f9f76 Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Tue, 22 Dec 2009 13:15:00 +0100
Subject: beta 2009.12.22 13:15

---
 tex/context/base/attr-ini.lua               |  30 +++--
 tex/context/base/attr-ini.mkiv              |  10 +-
 tex/context/base/colo-ini.mkiv              |   2 +-
 tex/context/base/cont-new.tex               |   2 +-
 tex/context/base/context.tex                |   2 +-
 tex/context/base/core-ctx.lua               |   4 +-
 tex/context/base/core-def.mkiv              |   3 -
 tex/context/base/core-fil.mkiv              |   4 +-
 tex/context/base/core-job.lua               |  29 +++--
 tex/context/base/core-job.mkiv              |  22 +---
 tex/context/base/core-sys.mkiv              |   6 +-
 tex/context/base/core-uti.lua               |   4 +-
 tex/context/base/font-afm.lua               |   4 +-
 tex/context/base/font-chk.lua               |  14 +++
 tex/context/base/font-ext.lua               |  40 +++++++
 tex/context/base/font-ini.mkiv              |  10 +-
 tex/context/base/font-mis.lua               |   2 +-
 tex/context/base/font-otf.lua               |   4 +-
 tex/context/base/font-pat.lua               |  24 ++--
 tex/context/base/font-syn.lua               |  29 +++--
 tex/context/base/font-tfm.lua               |  95 ++++++++--------
 tex/context/base/grph-inc.lua               |  14 ++-
 tex/context/base/grph-inc.mkiv              |   3 -
 tex/context/base/l-os.lua                   |  12 +-
 tex/context/base/lpdf-xmp.lua               |  23 ++--
 tex/context/base/m-graph.mkiv               |   2 +-
 tex/context/base/math-ini.lua               |  16 ++-
 tex/context/base/math-ini.mkiv              |   2 -
 tex/context/base/node-fin.lua               |   2 +-
 tex/context/base/node-ref.lua               |   5 +
 tex/context/base/node-tsk.lua               |   2 +-
 tex/context/base/pack-box.mkii              |  16 +--
 tex/context/base/pack-box.mkiv              |  16 +--
 tex/context/base/s-ptj-01.tex               | 166 +++++++++++++---------------
 tex/context/base/scrn-nav.mkiv              |  12 ++
 tex/context/base/strc-flt.mkiv              |  10 +-
 tex/context/base/supp-fil.mkiv              |  60 +---------
 tex/context/base/supp-ran.lua               |  16 ++-
 tex/context/base/task-ini.lua               |  77 +++++++------
 tex/context/base/trac-log.lua               |   1 +
 tex/context/base/trac-tra.lua               |  36 +++++-
 tex/context/base/typo-brk.lua               |   5 +-
 tex/context/base/typo-brk.mkiv              |   2 +-
 tex/context/base/typo-cap.lua               |   5 +-
 tex/context/base/typo-cap.mkiv              |   4 +-
 tex/context/base/typo-krn.lua               |   2 -
 tex/context/base/typo-krn.mkiv              |   2 +-
 tex/context/base/typo-mir.lua               |  23 ++--
 tex/context/base/typo-mir.mkiv              |  12 +-
 tex/context/base/typo-spa.lua               |   2 -
 tex/context/base/typo-spa.mkiv              |   1 -
 tex/generic/context/luatex-fonts-merged.lua | 101 +++++++++--------
 52 files changed, 547 insertions(+), 443 deletions(-)

(limited to 'tex')

diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua
index 26b050dc4..37615c140 100644
--- a/tex/context/base/attr-ini.lua
+++ b/tex/context/base/attr-ini.lua
@@ -61,7 +61,6 @@ colors.data       = colors.data       or { }
 colors.values     = colors.values     or { }
 colors.registered = colors.registered or { }
 
-colors.enabled    = true
 colors.weightgray = true
 colors.attribute  = attributes.private('color')
 colors.selector   = attributes.private('colormodel')
@@ -255,13 +254,16 @@ shipouts.handle_color = nodes.install_attribute_handler {
     resolver    = function() return colors.main end,
 }
 
+function colors.enable()
+    tasks.enableaction("shipouts","shipouts.handle_color")
+end
+
 -- transparencies
 
 transparencies            = transparencies            or { }
 transparencies.registered = transparencies.registered or { }
 transparencies.data       = transparencies.data       or { }
 transparencies.values     = transparencies.values     or { }
-transparencies.enabled    = false
 transparencies.triggering = true
 transparencies.attribute  = attributes.private('transparency')
 
@@ -341,11 +343,14 @@ shipouts.handle_transparency = nodes.install_attribute_handler {
     processor   = states.process,
 }
 
+function transparencies.enable()
+    tasks.enableaction("shipouts","shipouts.handle_transparency")
+end
+
 --- colorintents: overprint / knockout
 
 colorintents           = colorintents      or { }
 colorintents.data      = colorintents.data or { }
-colorintents.enabled   = false
 colorintents.attribute = attributes.private('colorintent')
 
 colorintents.registered = {
@@ -390,13 +395,14 @@ shipouts.handle_colorintent = nodes.install_attribute_handler {
     processor   = states.process,
 }
 
-local s = shipouts.handle_colorintent
+function colorintents.enable()
+    tasks.enableaction("shipouts","shipouts.handle_colorintent")
+end
 
 --- negative / positive
 
 negatives           = negatives      or { }
 negatives.data      = negatives.data or { }
-negatives.enabled   = false
 negatives.attribute = attributes.private("negative")
 
 negatives.registered = {
@@ -441,13 +447,16 @@ shipouts.handle_negative = nodes.install_attribute_handler {
     processor   = states.process,
 }
 
+function negatives.enable()
+    tasks.enableaction("shipouts","shipouts.handle_negative")
+end
+
 -- effects -- can be optimized (todo: metatables)
 
 effects            = effects            or { }
 effects.data       = effects.data       or { }
 effects.values     = effects.values     or { }
 effects.registered = effects.registered or { }
-effects.enabled    = false
 effects.stamp      = "%s:%s:%s"
 effects.attribute  = attributes.private("effect")
 
@@ -497,6 +506,10 @@ shipouts.handle_effect = nodes.install_attribute_handler {
     processor   = states.process,
 }
 
+function effects.enable()
+    tasks.enableaction("shipouts","shipouts.handle_effect")
+end
+
 -- layers (ugly code, due to no grouping and such); currently we use exclusive layers
 -- but when we need it stacked layers might show up too; the next function based
 -- approach can be replaced by static (metatable driven) resolvers
@@ -506,7 +519,6 @@ viewerlayers.data       = viewerlayers.data       or { }
 viewerlayers.registered = viewerlayers.registered or { }
 viewerlayers.values     = viewerlayers.values     or { }
 viewerlayers.listwise   = viewerlayers.listwise   or { }
-viewerlayers.enabled    = false
 viewerlayers.attribute  = attributes.private("viewerlayer")
 
 storage.register("viewerlayers/registered", viewerlayers.registered, "viewerlayers.registered")
@@ -560,3 +572,7 @@ shipouts.handle_viewerlayer = nodes.install_attribute_handler {
     finalizer   = states.finalize,
     processor   = states.stacked,
 }
+
+function viewerlayers.enable()
+    tasks.enableaction("shipouts","shipouts.handle_viewerlayer")
+end
diff --git a/tex/context/base/attr-ini.mkiv b/tex/context/base/attr-ini.mkiv
index 3d10086f0..b0a56145c 100644
--- a/tex/context/base/attr-ini.mkiv
+++ b/tex/context/base/attr-ini.mkiv
@@ -92,7 +92,7 @@
 \def\sometransparencyswitch#1{\csname(ts:#1)\endcsname}
 
 \def\sometransparencyswitch
-  {\ctxlua{transparencies.enabled=true}%
+  {\ctxlua{transparencies.enable()}%
    \gdef\sometransparencyswitch##1{\csname(ts:##1)\endcsname}%
    \sometransparencyswitch}
 
@@ -105,7 +105,7 @@
   {\setevalue{(os:#1)}{\dosetattribute{colorintent}{\ctxlua{tex.print(colorintents.register('#2'))}}}}
 
 \def\dotriggercolorintent
-  {\ctxlua{colorintents.enabled=true}%
+  {\ctxlua{colorintents.enable()}%
    \gdef\dotriggercolorintent##1{\csname(os:##1)\endcsname}%
    \dotriggercolorintent}
 
@@ -122,7 +122,7 @@
   {\setevalue{(ns:#1)}{\dosetattribute{negative}{\ctxlua{tex.print(negatives.register('#2'))}}}}
 
 \def\dotriggernegative
-  {\ctxlua{negatives.enabled=true}%
+  {\ctxlua{negatives.enable()}%
    \gdef\dotriggernegative##1{\csname(ns:##1)\endcsname}%
    \dotriggernegative}
 
@@ -136,7 +136,7 @@
      {\dosetattribute{effect}{\ctxlua{tex.print(effects.register('#1',#2,\number\dimexpr#3\relax))}}}}
 
 \def\dotriggereffect
-  {\ctxlua{effects.enabled=true}%
+  {\ctxlua{effects.enable()}%
    \gdef\dotriggereffect##1##2##3%
      {\ifcsname(es:##1:##2:\number\dimexpr##3\relax)\endcsname\else\registereffect{##1}{##2}{##3}\fi
       \csname(es:##1:##2:\number\dimexpr##3\relax)\endcsname}%
@@ -163,7 +163,7 @@
 \setevalue{(vl:)}{\global\doresetattribute{viewerlayer}}
 
 \def\dotriggerviewerlayer
-  {\ctxlua{viewerlayers.enabled=true}%
+  {\ctxlua{viewerlayers.enable()}%
    \gdef\dotriggerviewerlayer##1{\csname(vl:##1)\endcsname}%
    \dotriggerviewerlayer}
 
diff --git a/tex/context/base/colo-ini.mkiv b/tex/context/base/colo-ini.mkiv
index 3804c6799..d4d8f7bd8 100644
--- a/tex/context/base/colo-ini.mkiv
+++ b/tex/context/base/colo-ini.mkiv
@@ -773,7 +773,7 @@
 
 \def\doactivatecolor
   {\ifproductionrun
-     \ctxlua{colors.enabled=true transparencies.enabled=true}% not that efficient but at least robust
+     \ctxlua{colors.enable() transparencies.enable()}% not that efficient but at least robust
      \let\doactivatecolor\normaldoactivatecolor
      \expandafter\doactivatecolor
    \else
diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex
index 218980a51..d9f7d7281 100644
--- a/tex/context/base/cont-new.tex
+++ b/tex/context/base/cont-new.tex
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2009.12.18 11:12}
+\newcontextversion{2009.12.22 13:15}
 
 %D This file is loaded at runtime, thereby providing an
 %D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex
index 4290fe723..a5dd4eec6 100644
--- a/tex/context/base/context.tex
+++ b/tex/context/base/context.tex
@@ -20,7 +20,7 @@
 %D your styles an modules.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2009.12.18 11:12}
+\edef\contextversion{2009.12.22 13:15}
 
 %D For those who want to use this:
 
diff --git a/tex/context/base/core-ctx.lua b/tex/context/base/core-ctx.lua
index db85eaf7d..816c8ff57 100644
--- a/tex/context/base/core-ctx.lua
+++ b/tex/context/base/core-ctx.lua
@@ -72,12 +72,12 @@ end
 local processfile       = commands.processfile
 local doifinputfileelse = commands.doifinputfileelse
 
-function commands.processfile(name,depth)
+function commands.processfile(name,maxreadlevel) -- overloaded
     local prepname = found and resolve(name)
     if prepname then
         return processfile(prepname,0)
     end
-    return processfile(name,depth)
+    return processfile(name,maxreadlevel)
 end
 
 function commands.doifinputfileelse(name,depth)
diff --git a/tex/context/base/core-def.mkiv b/tex/context/base/core-def.mkiv
index aab7ff052..04bd7c09e 100644
--- a/tex/context/base/core-def.mkiv
+++ b/tex/context/base/core-def.mkiv
@@ -28,7 +28,6 @@
 
 \appendtoks  \showcontextbanner                    \to \everyjob
 \appendtoks  \initializenewlinechar                \to \everyjob
-\appendtoks  \checksystemcommandmode               \to \everyjob
 \appendtoks  \calculatecurrenttime                 \to \everyjob
 \appendtoks  \loadsystemfiles                      \to \everyjob
 \appendtoks  \loadoptionfile                       \to \everyjob % can load files !
@@ -38,11 +37,9 @@
 \appendtoks  \preloadspecials                      \to \everyjob
 \appendtoks  \checknotes                           \to \everyjob % depends on bodyfont
 \appendtoks  \initializeMPgraphics                 \to \everyjob % after loading system files
-\appendtoks  \reportsystemcommandmode              \to \everyjob
 \appendtoks  \initializemainlanguage               \to \everyjob
 \appendtoks  \MPLIBregister                        \to \everyjob
 \appendtoks  \xmlinitialize                        \to \everyjob
-\appendtoks  \settrue\trackfilenames               \to \everyjob
 \appendtoks  \newbackgroundfalse                   \to \everyjob % global
 \appendtoks  \initializepagecounters               \to \everyjob
 \appendtoks  \directsetup{*runtime:options}        \to \everyjob % we could erase them afterwards % order can change
diff --git a/tex/context/base/core-fil.mkiv b/tex/context/base/core-fil.mkiv
index 90a6bc038..1c7e701c7 100644
--- a/tex/context/base/core-fil.mkiv
+++ b/tex/context/base/core-fil.mkiv
@@ -214,8 +214,8 @@
 \def\moduleparameter     #1#2{\executeifdefined{\??md:#1:#2}\s!empty}
 \def\currentmoduleparameter#1{\executeifdefined{\??md:\currentmodule:#1}\s!empty}
 
-\def\useluamodule  [#1]{\ctxlua{dofile(resolvers.findctxfile("#1",\number\maxreadlevel))}}
-\def\luaenvironment #1 {\ctxlua{dofile(resolvers.findctxfile("#1",\number\maxreadlevel))}}
+\def\useluamodule  [#1]{\ctxlua{dofile(resolvers.findctxfile("#1"))}}
+\def\luaenvironment #1 {\ctxlua{dofile(resolvers.findctxfile("#1"))}}
 
 % \usemodule[newmml]
 % \usemodule[newmml][a=b]
diff --git a/tex/context/base/core-job.lua b/tex/context/base/core-job.lua
index a2ce27ef7..df334573a 100644
--- a/tex/context/base/core-job.lua
+++ b/tex/context/base/core-job.lua
@@ -6,25 +6,30 @@ if not modules then modules = { } end modules ['core-job'] = {
     license   = "see context related readme files"
 }
 
-local texsprint, texprint = tex.sprint, tex.print
+local texsprint, texprint, texwrite = tex.sprint, tex.print, tex.write
 local ctxcatcodes, texcatcodes = tex.ctxcatcodes, tex.texcatcodes
 local lower, format, find, gmatch = string.lower, string.format, string.find, string.gmatch
 local concat = table.concat
 
 -- main code
 
-function resolvers.findctxfile(name,maxreadlevel)
-    local function exists(n)
+resolvers.maxreadlevel = 3
+
+directives.register("resolvers.maxreadlevel", function(v) resolvers.maxreadlevel = tonumber(v) or resolvers.maxreadlevel end)
+
+local function exists(n)
+    if io.exists(n) then
+        return n
+    else
+        n = file.addsuffix(n,'tex')
         if io.exists(n) then
             return n
-        else
-            n = file.addsuffix(n,'tex')
-            if io.exists(n) then
-                return n
-            end
         end
-        return nil
     end
+    return nil
+end
+
+function resolvers.findctxfile(name,maxreadlevel)
     if file.is_qualified_path(name) then
         return name
     else
@@ -34,7 +39,7 @@ function resolvers.findctxfile(name,maxreadlevel)
         if found then
             return found
         else
-            for i=1,maxreadlevel or 0 do
+            for i=1,maxreadlevel or resolvers.maxreadlevel or 0 do
                 n = "../" .. n
                 found = exists(n)
                 if found then
@@ -46,6 +51,10 @@ function resolvers.findctxfile(name,maxreadlevel)
     end
 end
 
+function commands.maxreadlevel()
+    texwrite(resolvers.maxreadlevel)
+end
+
 function commands.processfile(name,maxreadlevel)
     name = resolvers.findctxfile(name,maxreadlevel)
     if name ~= "" then
diff --git a/tex/context/base/core-job.mkiv b/tex/context/base/core-job.mkiv
index 71d4e4d30..131d15578 100644
--- a/tex/context/base/core-job.mkiv
+++ b/tex/context/base/core-job.mkiv
@@ -51,9 +51,9 @@
 \def\processlocalfile#1#2%
   {#1{#2}\donothing{\readfile{#2}\donothing\donothing}}
 
-\def\processfile       #1{\ctxlua{commands.processfile("#1",\number\maxreadlevel)}}
-\def\doifinputfileelse #1{\ctxlua{commands.doifinputfileelse("#1",\number\maxreadlevel)}}
-\def\locatefilepath    #1{\edef\locatedfilepath{\ctxlua{commands.locatefilepath("#1",\number\maxreadlevel)}}}
+\def\processfile       #1{\ctxlua{commands.processfile("#1")}}
+\def\doifinputfileelse #1{\ctxlua{commands.doifinputfileelse("#1")}}
+\def\locatefilepath    #1{\edef\locatedfilepath{\ctxlua{commands.locatefilepath("#1")}}}
 \def\usepath         [#1]{\edef\allinputpaths{\ctxlua{commands.usepath("#1")}}}
 \def\usesubpath      [#1]{\edef\allinputpaths{\ctxlua{commands.usesubpath("#1")}}}
 \def\usezipfile          {\dodoubleempty\dousezipfile}
@@ -302,21 +302,5 @@
 
 % \appendtoks \flushnotes                     \to \everydisplay
 % \appendtoks \adjustsidefloatdisplaylines    \to \everydisplay
-
-\chardef\systemcommandmode\zerocount % 0=unknown 1=disabled 2=enabled
-
-\def\checksystemcommandmode
-  {\ifx\pdfshellescape\undefined \else
-     \chardef\systemcommandmode \ifcase\pdfshellescape \plusone \else \plustwo \fi
-   \fi
-   \global\let\checksystemcommandmode\relax}
-
-\def\reportsystemcommandmode
-  {\ifcase\systemcommandmode
-   \or
-     \writestatus\m!systems{system commands are disabled}%
-   \or
-     \writestatus\m!systems{system commands are enabled}%
-   \fi}
 
 \protect \endinput
diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv
index 16ab62283..c7747d4bb 100644
--- a/tex/context/base/core-sys.mkiv
+++ b/tex/context/base/core-sys.mkiv
@@ -59,10 +59,6 @@
   {\getparameters[\??sv][#1]%
    \the\everysetupsystem}
 
-\appendtoks
-    \setuprandomize[\@@svrandom]%
-\to \everysetupsystem
-
 \appendtoks
     \edef\outputresolution{\@@svresolution}%
 \to \everysetupsystem
@@ -161,7 +157,7 @@
   [\c!directory=,
    \c!n=0, % 0:unknown 1: one run 2: first 3: successive 4: final run
    \c!resolution=600,% in dpi, no unit in mkiv
-   \c!random=,
+   %c!random=, % obsolete here
    \c!file=\jobname,
    \c!inputfile=\outputfilename,
    \c!type=unix, % windows is normally less sensitive to handle
diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua
index a055d8c7e..c20e7b274 100644
--- a/tex/context/base/core-uti.lua
+++ b/tex/context/base/core-uti.lua
@@ -69,8 +69,10 @@ local function initializer()
     local r = jobvariables.collected.randomseed
     if not r then
         r = math.random()
+        math.setrandomseedi(r,"initialize")
+    else
+        math.setrandomseedi(r,"previous run")
     end
-    math.setrandomseedi(r)
     jobvariables.tobesaved.randomseed = r
     for cs, value in next, jobvariables.collected do
         texsprint(ctxcatcodes,format("\\xdef\\%s{%s}",cs,value))
diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua
index 2ba73be26..0e30cc07b 100644
--- a/tex/context/base/font-afm.lua
+++ b/tex/context/base/font-afm.lua
@@ -480,8 +480,8 @@ function afm.copy_to_tfm(data)
             tfm.psname             = tfm.fullname
             tfm.type               = "real"
             tfm.units              = 1000
-            tfm.stretch            = stretch -- nil
-            tfm.slant              = slant -- nil
+            tfm.stretch            = 0
+            tfm.slant              = 0
             tfm.direction          = 0
             tfm.boundarychar_label = 0
             tfm.boundarychar       = 65536
diff --git a/tex/context/base/font-chk.lua b/tex/context/base/font-chk.lua
index 079712bae..32fdf8894 100644
--- a/tex/context/base/font-chk.lua
+++ b/tex/context/base/font-chk.lua
@@ -74,3 +74,17 @@ function checkers.missing(head)
     end
     return head, false
 end
+
+trackers.register("fonts.missing", function(v)
+    tasks.enableaction("processors", "fonts.checkers.missing") -- always on then
+    checkers.enabled = v
+end)
+
+function checkers.enable(delete)
+    tasks.enableaction("processors", "fonts.checkers.missing") -- always on then
+    if delete ~= nil then
+        checkers.delete = delete
+   end
+   checkers.enabled = true
+end
+
diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua
index 66d3b8e78..1b2c8e698 100644
--- a/tex/context/base/font-ext.lua
+++ b/tex/context/base/font-ext.lua
@@ -496,3 +496,43 @@ initializers.node.otf.itlc = initializers.common.itlc
 
 initializers.base.afm.itlc = initializers.common.itlc
 initializers.node.afm.itlc = initializers.common.itlc
+
+-- slanting
+
+table.insert(fonts.triggers,"slant")
+
+function initializers.common.slant(tfmdata,value)
+    if not value then
+        value =  0
+    elseif value >  1 then
+        value =  1
+    elseif value < -1 then
+        value = -1
+    end
+    tfmdata.slant = value
+end
+
+initializers.base.otf.slant = initializers.common.slant
+initializers.node.otf.slant = initializers.common.slant
+
+initializers.base.afm.slant = initializers.common.slant
+initializers.node.afm.slant = initializers.common.slant
+
+table.insert(fonts.triggers,"stretch")
+
+function initializers.common.stretch(tfmdata,value)
+    if not value then
+        value =  0
+    elseif value >  10 then
+        value =  10
+    elseif value < -10 then
+        value = -10
+    end
+    tfmdata.stretch = value
+end
+
+initializers.base.otf.stretch = initializers.common.stretch
+initializers.node.otf.stretch = initializers.common.stretch
+
+initializers.base.afm.stretch = initializers.common.stretch
+initializers.node.afm.stretch = initializers.common.stretch
diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv
index 0b58c9791..96b41084b 100644
--- a/tex/context/base/font-ini.mkiv
+++ b/tex/context/base/font-ini.mkiv
@@ -763,6 +763,12 @@
 
 \let\fontfile\s!unknown
 
+% \definefontfeature[slanted]  [default][slant=.25]
+% \definefontfeature[stretched][default][stretch=2]
+%
+% \start \definedfont[SerifBold*slanted   at 20pt] \ruledhbox{Test!} \stop
+% \start \definedfont[SerifBold*stretched at 20pt] \ruledhbox{Test!} \stop
+
 % \definefontfeature[default]     [liga=yes,texligatures=yes,texquotes=yes]
 % \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn]
 %
@@ -3918,8 +3924,8 @@
 %
 % \setupfonts[check=...]
 
-\def\checkcharactersinfont  {\ctxlua{fonts.checkers.enabled=true}}
-\def\removemissingcharacters{\ctxlua{fonts.checkers.enabled=true fonts.checkers.delete=true}}
+\def\checkcharactersinfont  {\ctxlua{fonts.checkers.enable()}}
+\def\removemissingcharacters{\ctxlua{fonts.checkers.enable(true)}}
 
 %D New commands (not yet interfaced):
 
diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua
index 5faeed2b7..2c809bc3d 100644
--- a/tex/context/base/font-mis.lua
+++ b/tex/context/base/font-mis.lua
@@ -11,7 +11,7 @@ local lower, strip = string.lower, string.strip
 
 fonts.otf = fonts.otf or { }
 
-fonts.otf.version = fonts.otf.version or 2.640
+fonts.otf.version = fonts.otf.version or 2.641
 fonts.otf.pack    = true
 fonts.otf.cache   = containers.define("fonts", "otf", fonts.otf.version, true)
 
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index 2e9562190..8904699a3 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -83,7 +83,7 @@ otf.features.default = otf.features.default or { }
 otf.enhancers        = otf.enhancers        or { }
 otf.glists           = { "gsub", "gpos" }
 
-otf.version          = 2.640 -- beware: also sync font-mis.lua
+otf.version          = 2.641 -- beware: also sync font-mis.lua
 otf.pack             = true  -- beware: also sync font-mis.lua
 otf.syncspace        = true
 otf.notdef           = false
@@ -1531,7 +1531,7 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th
         tfm.cidinfo.registry   = tfm.cidinfo.registry or ""
         tfm.type               = "real"
         tfm.stretch            = 0 -- stretch
-        tfm.slant              = 0 -- slant
+        tfm.slant              = 0 -- data.slant
         tfm.direction          = 0
         tfm.boundarychar_label = 0
         tfm.boundarychar       = 65536
diff --git a/tex/context/base/font-pat.lua b/tex/context/base/font-pat.lua
index e720af79c..e8274c5e7 100644
--- a/tex/context/base/font-pat.lua
+++ b/tex/context/base/font-pat.lua
@@ -105,18 +105,20 @@ local function patch_domh(data,filename,threshold)
             end
             m.DisplayOperatorMinHeight = threshold
         end
-    end
-    for _, g in pairs(data.glyphs) do
-        local name = g.name
-        if find(name,"^integral$") or find(name,"^integral%.vsize") then
-            local width, italic = g.width or 0, g.italic_correction or 0
-            local newwidth = width - italic
-            if trace_loading then
-                logs.report("load otf","patching width of %s: %s (width) - %s (italic) = %s",name,width,italic,newwidth)
-            end
-            g.width = newwidth
+     end
+     if tex.luatexversion < 48 then
+        for _, g in pairs(data.glyphs) do
+           local name = g.name
+           if find(name,"^integral$") or find(name,"^integral%.vsize") then
+              local width, italic = g.width or 0, g.italic_correction or 0
+              local newwidth = width - italic
+              if trace_loading then
+                 logs.report("load otf","patching width of %s: %s (width) - %s (italic) = %s",name,width,italic,newwidth)
+              end
+              g.width = newwidth
+           end
         end
-    end
+     end
 end
 
 patches["cambria"]  = function(data,filename) patch_domh(data,filename,2800) end
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
index e80df71ea..9f84c2637 100644
--- a/tex/context/base/font-syn.lua
+++ b/tex/context/base/font-syn.lua
@@ -13,7 +13,8 @@ local gsub, lower, match, find, lower, upper = string.gsub, string.lower, string
 local find, gmatch = string.find, string.gmatch
 local concat, sort, format = table.concat, table.sort, string.format
 
-local trace_names = false  trackers.register("fonts.names", function(v) trace_names = v end)
+local trace_names    = false  trackers.register("fonts.names",    function(v) trace_names    = v end)
+local trace_warnings = false  trackers.register("fonts.warnings", function(v) trace_warnings = v end)
 
 --[[ldx--
 <p>This module implements a name to filename resolver. Names are resolved
@@ -458,9 +459,9 @@ local function collecthashes()
     return nofmappings, noffallbacks
 end
 
-local function checkduplicate(mapping) -- fails on "Romantik" but that's a border case anyway
+local function checkduplicate(where) -- fails on "Romantik" but that's a border case anyway
     local data = names.data
-    local mapping = data[mapping]
+    local mapping = data[where]
     local specifications, loaded = data.specifications, { }
     if specifications and mapping then
         for _, m in next, mapping do
@@ -487,11 +488,17 @@ local function checkduplicate(mapping) -- fails on "Romantik" but that's a borde
             end
         end
     end
+    local n = 0
     for k, v in table.sortedpairs(loaded) do
-        if #v > 1 then
-            logs.report("fontnames", "double lookup: %s => %s",k,concat(v," | "))
+        local nv = #v
+        if nv > 1 then
+            if trace_warnings then
+                logs.report("fontnames", "double lookup: %s => %s",k,concat(v," | "))
+            end
+            n = n + nv
         end
     end
+    logs.report("fontnames", "%s double lookups in %s",n,where)
 end
 
 local function checkduplicates()
@@ -605,10 +612,10 @@ local function analysefiles()
                         end
                     end
                 end
-                if message and message ~= "" then
+                if trace_warnings and message and message ~= "" then
                     logs.report("fontnames","warning when identifying %s font %s: %s",suffix,completename,message)
                 end
-            else
+            elseif trace_warnings then
                 logs.report("fontnames","error when identifying %s font %s: %s",suffix,completename,message or "unknown")
             end
             done[name] = true
@@ -629,6 +636,9 @@ local function analysefiles()
             logs.report("fontnames", "%s %s files identified, %s hash entries added, runtime %0.3f seconds",nofread,what,nofread-nofskipped,elapsed)
         end
     end
+    if not trace_warnings then
+        logs.report("fontnames", "warnings are disables (tracker 'fonts.warnings')")
+    end
     traverse("tree", function(suffix) -- TEXTREE only
         resolvers.with_files(".*%." .. suffix .. "$", function(method,root,path,name)
             if method == "file" then
@@ -660,7 +670,9 @@ local function rejectclashes() -- just to be sure, so no explicit afm will be fo
         if f then
             local fnd, fnm = used[f], s.filename
             if fnd then
-                logs.report("fontnames", "fontname '%s' clashes, rejecting '%s' in favor of '%s'",f,fnm,fnd)
+                if trace_warnings then
+                    logs.report("fontnames", "fontname '%s' clashes, rejecting '%s' in favor of '%s'",f,fnm,fnd)
+                end
             else
                 used[f], okay[#okay+1] = fnm, s
             end
@@ -700,7 +712,6 @@ function names.identify()
     collecthashes()
     checkduplicates()
  -- sorthashes() -- will be resorted when saved
- --~     logs.report("fontnames", "%s files read, %s normal and %s extra entries added, %s rejected, %s valid",totalread,totalok,added,rejected,totalok+added-rejected)
 end
 
 function names.is_permitted(name)
diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua
index efea9def3..714c89d54 100644
--- a/tex/context/base/font-tfm.lua
+++ b/tex/context/base/font-tfm.lua
@@ -234,6 +234,7 @@ function tfm.do_scale(tfmtable, scaledpoints)
         scaledpoints = (- scaledpoints/1000) * tfmtable.designsize -- already in sp
     end
     local delta = scaledpoints/(tfmtable.units or 1000) -- brr, some open type fonts have 2048
+    local hdelta, vdelta = delta, delta
     local t = { }
     -- unicoded unique descriptions shared cidinfo characters changed parameters indices
     for k,v in next, tfmtable do
@@ -243,6 +244,15 @@ function tfm.do_scale(tfmtable, scaledpoints)
             t[k] = v
         end
     end
+    local stretch = tfmtable.stretch or 0
+    if stretch ~= 0 and stretch ~= 1 then
+        hdelta = hdelta * stretch
+        t.extend = stretch * 1000
+    end
+    local slant = tfmtable.slant or 0
+    if slant ~= 0 then
+        t.slant = t.slant * 1000
+    end
     -- status
     local isvirtual = tfmtable.type == "virtual" or tfmtable.virtualized
     local hasmath = (tfmtable.math_parameters ~= nil and next(tfmtable.math_parameters) ~= nil) or (tfmtable.MathConstants ~= nil and next(tfmtable.MathConstants) ~= nil)
@@ -270,12 +280,12 @@ t.colorscheme = tfmtable.colorscheme
     local tfmp = tfmtable.parameters -- let's check for indexes
     --
     tp.slant         = (tfmp.slant         or tfmp[1] or 0)
-    tp.space         = (tfmp.space         or tfmp[2] or 0)*delta
-    tp.space_stretch = (tfmp.space_stretch or tfmp[3] or 0)*delta
-    tp.space_shrink  = (tfmp.space_shrink  or tfmp[4] or 0)*delta
-    tp.x_height      = (tfmp.x_height      or tfmp[5] or 0)*delta
-    tp.quad          = (tfmp.quad          or tfmp[6] or 0)*delta
-    tp.extra_space   = (tfmp.extra_space   or tfmp[7] or 0)*delta
+    tp.space         = (tfmp.space         or tfmp[2] or 0)*hdelta
+    tp.space_stretch = (tfmp.space_stretch or tfmp[3] or 0)*hdelta
+    tp.space_shrink  = (tfmp.space_shrink  or tfmp[4] or 0)*hdelta
+    tp.x_height      = (tfmp.x_height      or tfmp[5] or 0)*vdelta
+    tp.quad          = (tfmp.quad          or tfmp[6] or 0)*hdelta
+    tp.extra_space   = (tfmp.extra_space   or tfmp[7] or 0)*hdelta
     local protrusionfactor = (tp.quad ~= 0 and 1000/tp.quad) or 0
     local tc = t.characters
     local characters = tfmtable.characters
@@ -292,11 +302,11 @@ t.colorscheme = tfmtable.colorscheme
     local sharedkerns, basekerns = tfm.check_base_kerns(tfmtable)
     -- loop over descriptions (afm and otf have descriptions, tfm not)
     -- there is no need (yet) to assign a value to chr.tonunicode
-    local scaledwidth  = defaultwidth  * delta
-    local scaledheight = defaultheight * delta
-    local scaleddepth  = defaultdepth  * delta
+    local scaledwidth  = defaultwidth  * hdelta
+    local scaledheight = defaultheight * vdelta
+    local scaleddepth  = defaultdepth  * vdelta
     local stackmath = tfmtable.ignore_stack_math ~= true
-local private = fonts.private
+    local private = fonts.private
     for k,v in next, characters do
         local chr, description, index
         if ischanged then
@@ -317,9 +327,9 @@ local private = fonts.private
         local width  = description.width
         local height = description.height
         local depth  = description.depth
-        if width  then width  = delta*width  else width  = scaledwidth  end
-        if height then height = delta*height else height = scaledheight end
-    --  if depth  then depth  = delta*depth  else depth  = scaleddepth  end
+        if width  then width  = hdelta*width  else width  = scaledwidth  end
+        if height then height = vdelta*height else height = scaledheight end
+    --  if depth  then depth  = vdelta*depth  else depth  = scaleddepth  end
         if depth and depth ~= 0 then
             depth = delta*depth
             if nameneeded then
@@ -383,7 +393,7 @@ local private = fonts.private
         if hasitalic then
             local vi = description.italic or v.italic
             if vi and vi ~= 0 then
-                chr.italic = vi*delta
+                chr.italic = vi*hdelta
             end
         end
         -- to be tested
@@ -399,19 +409,19 @@ local private = fonts.private
                     for i=1,#vv do
                         local vvi = vv[i]
                         t[i] = {
-                            ["start"]    = (vvi["start"]   or 0)*delta,
-                            ["end"]      = (vvi["end"]     or 0)*delta,
-                            ["advance"]  = (vvi["advance"] or 0)*delta,
+                            ["start"]    = (vvi["start"]   or 0)*vdelta,
+                            ["end"]      = (vvi["end"]     or 0)*vdelta,
+                            ["advance"]  = (vvi["advance"] or 0)*vdelta,
                             ["extender"] =  vvi["extender"],
                             ["glyph"]    =  vvi["glyph"],
                         }
                     end
                     chr.vert_variants = t
---~ local ic = v.vert_italic_correction
---~ if ic then
---~     chr.italic = ic * delta
---~     print(format("0x%05X -> %s",k,chr.italic))
---~ end
+                --~ local ic = v.vert_italic_correction
+                --~ if ic then
+                --~     chr.italic = ic * hdelta
+                --~     print(format("0x%05X -> %s",k,chr.italic))
+                --~ end
                 else
                     local hv = v.horiz_variants
                     if hv then
@@ -419,9 +429,9 @@ local private = fonts.private
                         for i=1,#hv do
                             local hvi = hv[i]
                             t[i] = {
-                                ["start"]    = (hvi["start"]   or 0)*delta,
-                                ["end"]      = (hvi["end"]     or 0)*delta,
-                                ["advance"]  = (hvi["advance"] or 0)*delta,
+                                ["start"]    = (hvi["start"]   or 0)*hdelta,
+                                ["end"]      = (hvi["end"]     or 0)*hdelta,
+                                ["advance"]  = (hvi["advance"] or 0)*hdelta,
                                 ["extender"] =  hvi["extender"],
                                 ["glyph"]    =  hvi["glyph"],
                             }
@@ -432,31 +442,23 @@ local private = fonts.private
             end
             local vt = description.top_accent
             if vt then
-                chr.top_accent = delta*vt
+                chr.top_accent = vdelta*vt
             end
             if stackmath then
                 local mk = v.mathkerns
                 if mk then
                     local kerns = { }
-                 -- for k, v in next, mk do
-                 --     local kk = { }
-                  --     for i=1,#v do
-                 --         local vi = v[i]
-                 --         kk[i] = { height = delta*vi.height, kern = delta*vi.kern }
-                 --     end
-                 --     kerns[k] = kk
-                 -- end
                     local v = mk.top_right    if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.top_right    = k end
                     local v = mk.top_left     if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.top_left     = k end
                     local v = mk.bottom_left  if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.bottom_left  = k end
                     local v = mk.bottom_right if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.bottom_right = k end
                     chr.mathkern = kerns -- singular
                 end
@@ -469,13 +471,13 @@ local private = fonts.private
                     local base = basekerns[vk] -- hashed by table id, not content
                     if not base then
                         base = {}
-                        for k,v in next, vk do base[k] = v*delta end
+                        for k,v in next, vk do base[k] = v*hdelta end
                         basekerns[vk] = base
                     end
                     chr.kerns = base
                 else
                     local tt = {}
-                    for k,v in next, vk do tt[k] = v*delta end
+                    for k,v in next, vk do tt[k] = v*hdelta end
                     chr.kerns = tt
                 end
             end
@@ -509,8 +511,10 @@ local private = fonts.private
                     for i=1,#vc do
                         local ivc = vc[i]
                         local key = ivc[1]
-                        if key == "right" or key == "down" then
-                            tt[#tt+1] = { key, ivc[2]*delta }
+                        if key == "right" then
+                            tt[#tt+1] = { key, ivc[2]*hdelta }
+                        elseif key == "down" then
+                            tt[#tt+1] = { key, ivc[2]*vdelta }
                         else -- not comment
                             tt[#tt+1] = ivc -- shared since in cache and untouched
                         end
@@ -522,13 +526,12 @@ local private = fonts.private
             end
         end
         tc[k] = chr
---~ if k == 0x222B then
---~     print(t.fontname,table.serialize(chr))
---~ end
     end
     -- t.encodingbytes, t.filename, t.fullname, t.name: elsewhere
     t.size = scaledpoints
     t.factor = delta
+    t.hfactor = hdelta
+    t.vfactor = vdelta
     if t.fonts then
         t.fonts = table.fastcopy(t.fonts) -- maybe we virtualize more afterwards
     end
@@ -536,7 +539,7 @@ local private = fonts.private
      -- mathematics.extras.copy(t) -- can be done elsewhere if needed
         local ma = tfm.mathactions
         for i=1,#ma do
-            ma[i](t,tfmtable,delta)
+            ma[i](t,tfmtable,delta,hdelta,vdelta) -- what delta?
         end
     end
     -- needed for \high cum suis
diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua
index 25adcead5..5d2f1bab7 100644
--- a/tex/context/base/grph-inc.lua
+++ b/tex/context/base/grph-inc.lua
@@ -378,9 +378,19 @@ end
 
 local function locate(request) -- name, format, cache
     local askedname = resolvers.clean_path(request.name)
-    if figures.found[askedname] then
-        return figures.found[askedname]
+    local foundname = figures.found[askedname]
+    if foundname then
+        return foundname
+    end
+    -- protocol check
+    local hashed = url.hashed(askedname)
+    if hashed and hashed.scheme ~= "file" then
+        local foundname = resolvers.findbinfile(askedname)
+        if foundname then
+            askedname = foundname
+        end
     end
+    -- we could use the hashed data instead
     local askedpath= file.is_rootbased_path(askedname)
     local askedbase = file.basename(askedname)
     local askedformat = (request.format ~= "" and request.format ~= "unknown" and request.format) or file.extname(askedname) or ""
diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv
index d18c72e06..d71a03462 100644
--- a/tex/context/base/grph-inc.mkiv
+++ b/tex/context/base/grph-inc.mkiv
@@ -28,14 +28,11 @@
 %D The following registers are used (if only to be downward compatible).
 
 \newbox  \foundexternalfigure
-\newif   \iftraceexternalfigures
 \newif   \ifskipexternalfigures
 \newtoks \everyexternalfigureresets
 \newtoks \everyexternalfigurechecks
 \newtoks \externalfigurepostprocessors
 
-\let\traceexternalfigures  \traceexternalfigurestrue
-
 \def\resetfigurevariables {\the\everyexternalfigureresets}
 \def\checkfigurevariables {\the\everyexternalfigurechecks}
 
diff --git a/tex/context/base/l-os.lua b/tex/context/base/l-os.lua
index 81fb1e2be..b8a5c3d1a 100644
--- a/tex/context/base/l-os.lua
+++ b/tex/context/base/l-os.lua
@@ -6,10 +6,19 @@ if not modules then modules = { } end modules ['l-os'] = {
     license   = "see context related readme files"
 }
 
+-- maybe build io.flush in os.execute
+
 local find, format = string.find, string.format
 local random, ceil = math.random, math.ceil
 
+local execute, spawn, exec, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.flush
+
+function os.execute(...) ioflush() return execute(...) end
+function os.spawn  (...) ioflush() return spawn  (...) end
+function os.exec   (...) ioflush() return exec   (...) end
+
 function os.resultof(command)
+    ioflush() -- else messed up logging
     local handle = io.popen(command,"r")
     if not handle then
     --  print("unknown command '".. command .. "' in os.resultof")
@@ -19,9 +28,6 @@ function os.resultof(command)
     end
 end
 
-if not os.exec  then os.exec  = os.execute end
-if not os.spawn then os.spawn = os.execute end
-
 --~ os.type : windows | unix (new, we already guessed os.platform)
 --~ os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
 
diff --git a/tex/context/base/lpdf-xmp.lua b/tex/context/base/lpdf-xmp.lua
index 03527e823..bd102cbf5 100644
--- a/tex/context/base/lpdf-xmp.lua
+++ b/tex/context/base/lpdf-xmp.lua
@@ -125,19 +125,14 @@ local function flushxmpinfo()
         texio.write_nl("log","")
         texio.write("log","\n% ",(gsub(blob,"[\r\n]","\n%% ")),"\n")
     end
-    --  if true then
-    --      commands.writestatus("system","xmp data not flushed (needs luatex upgrade)")
-    --  else
-    --  lpdf.addtocatalog("Metadata",lpdf.reference(pdf.immediateobj("stream",format(xpacket,packetid,blob),md())))
-        local r = pdf.obj {
-            immediate = true,
-            compresslevel = 0,
-            type = "stream",
-            string = format(xpacket,packetid,blob),
-            attr = md(),
-        }
-        lpdf.addtocatalog("Metadata",lpdf.reference(r))
-    --  end
+    local r = pdf.obj {
+        immediate = true,
+        compresslevel = 0,
+        type = "stream",
+        string = format(xpacket,packetid,blob),
+        attr = md(),
+    }
+    lpdf.addtocatalog("Metadata",lpdf.reference(r))
 
     commands.defrostrandomseed() -- hack
 
@@ -145,7 +140,7 @@ end
 
 --  his will be enabled when we can inhibit compression for a stream at the lua end
 
-lpdf.registerdocumentfinalizer(flushxmpinfo,3)
+lpdf.registerdocumentfinalizer(flushxmpinfo,1)
 
 --~ lpdf.addxmpinfo("creator",         "PRAGMA ADE: Hans Hagen and/or Ton Otten")
 --~ lpdf.addxmpinfo("title",           "oeps")
diff --git a/tex/context/base/m-graph.mkiv b/tex/context/base/m-graph.mkiv
index 39a1271d7..c92234884 100644
--- a/tex/context/base/m-graph.mkiv
+++ b/tex/context/base/m-graph.mkiv
@@ -17,7 +17,7 @@
 
 \startluacode
     local function strip(s)
-        return "\times10^{"..(s:gsub("%+*0*","")).."}"
+        return "\\times10^{"..(s:gsub("%+*0*","")).."}"
     end
     function metapost.format_n(fmt,str)
         fmt = fmt:gsub("@","%%")
diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua
index 9303858b0..add198b21 100644
--- a/tex/context/base/math-ini.lua
+++ b/tex/context/base/math-ini.lua
@@ -302,16 +302,24 @@ end
 
 -- plugins
 
-function mathematics.scaleparameters(t,tfmtable,delta)
+local hvars = table.tohash {
+    --~ "RadicalKernBeforeDegree",
+    --~ "RadicalKernAfterDegree",
+}
+
+function mathematics.scaleparameters(t,tfmtable,delta,hdelta,vdelta)
     local math_parameters = tfmtable.math_parameters
     if math_parameters and next(math_parameters) then
         delta = delta or 1
+        hdelta, vdelta = hdelta or delta, vdelta or delta
         local _, mp = mathematics.dimensions(math_parameters)
         for name, value in next, mp do
-            if name ~= "RadicalDegreeBottomRaisePercent" then
-                mp[name] = delta*value
-            else
+            if name == "RadicalDegreeBottomRaisePercent" then
                 mp[name] = value
+            elseif hvars[name] then
+                mp[name] = hdelta * value
+            else
+                mp[name] = vdelta * value
             end
         end
         t.MathConstants = mp
diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv
index 17b020563..b62f6507d 100644
--- a/tex/context/base/math-ini.mkiv
+++ b/tex/context/base/math-ini.mkiv
@@ -210,8 +210,6 @@
 % $\mathopnolimits{\kern\zeropoint d}x$
 % \stoplines
 
-\newif\iftracemathcollection
-
 % this will be sorted out:
 
 \let\mathcharacter           \getvalue
diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua
index 8ab754bec..9e0538fb5 100644
--- a/tex/context/base/node-fin.lua
+++ b/tex/context/base/node-fin.lua
@@ -75,7 +75,7 @@ end
 
 local function process_attribute(head,plugin) -- head,attribute,enabled,initializer,resolver,processor,finalizer
     local namespace = plugin.namespace
-    if namespace.enabled then
+    if namespace.enabled ~= false then -- this test will go away
         starttiming(attributes)
         local done, used, ok = false, nil, false
         local attribute = namespace.attribute or numbers[plugin.name] -- todo: plugin.attribute
diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua
index 008e44b6b..198a810ff 100644
--- a/tex/context/base/node-ref.lua
+++ b/tex/context/base/node-ref.lua
@@ -526,3 +526,8 @@ statistics.register("interactive elements", function()
         return nil
     end
 end)
+
+function jobreferences.enable_interaction()
+    tasks.enableaction("shipouts","nodes.add_references")
+    tasks.enableaction("shipouts","nodes.add_destinations")
+end
diff --git a/tex/context/base/node-tsk.lua b/tex/context/base/node-tsk.lua
index 4921fe4f6..f0ff6e393 100644
--- a/tex/context/base/node-tsk.lua
+++ b/tex/context/base/node-tsk.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['node-tsk'] = {
     license   = "see context related readme files"
 }
 
-local trace_tasks = false  trackers.register("tasks", function(v) trace_tasks = v end)
+local trace_tasks = false  trackers.register("tasks.creation", function(v) trace_tasks = v end)
 
 tasks         = tasks       or { }
 tasks.data    = tasks.data  or { }
diff --git a/tex/context/base/pack-box.mkii b/tex/context/base/pack-box.mkii
index 1be840552..8adeedb91 100644
--- a/tex/context/base/pack-box.mkii
+++ b/tex/context/base/pack-box.mkii
@@ -751,7 +751,7 @@
 \setvalue{\??ab\??ab \v!line\v!middle}{\baselinemiddlebox}
 \setvalue{\??ab\??ab \v!line\v!right }{\baselinerightbox}
 
-\def\offsetbox
+\unexpanded\def\offsetbox
   {\dodoubleempty\dooffsetbox[]}
 
 % left/right/top/bottomoffset -> dimensions change
@@ -841,8 +841,8 @@
 % \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
 % \input tufte
 
-\def\offset {\dodoubleempty\dooffsetbox [\hbox]} % yes or no
-\def\aligned{\dosingleempty\doalignedbox[\hbox]} % yes or no
+\unexpanded\def\offset {\dodoubleempty\dooffsetbox [\hbox]} % yes or no
+\unexpanded\def\aligned{\dosingleempty\doalignedbox[\hbox]} % yes or no
 
 %\ruledhbox{\offsetbox[x=-1cm,y=-1cm,location=c]
 %  {\framed[width=4cm,height=4cm]{x}}}
@@ -854,9 +854,9 @@
    \hbox to \wd\scratchbox{#1#4#2}%
    \egroup}
 
-\def\ltabbed{\dotabbed\relax\hss}
-\def\rtabbed{\dotabbed\hss  \relax}
-\def\ctabbed{\dotabbed\hss  \hss}      \let\mtabbed\ctabbed
+\unexpanded\def\ltabbed{\dotabbed\relax\hss}
+\unexpanded\def\rtabbed{\dotabbed\hss  \relax}
+\unexpanded\def\ctabbed{\dotabbed\hss  \hss}      \let\mtabbed\ctabbed
 
 % \ltabbed{\romeins{3}}{\romeins{1}} test \endgraf
 % \ltabbed{\romeins{3}}{\romeins{2}} test \endgraf
@@ -903,7 +903,7 @@
 
 % to be documented
 
-\def\phantombox[#1]%
+\unexpanded\def\phantombox[#1]%
   {\hbox\bgroup
    \getparameters
      [\??ol]
@@ -919,7 +919,7 @@
 
 %  \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
 
-\def\backgroundimage#1#2#3% repeat hsize vsize
+\unexpanded\def\backgroundimage#1#2#3% repeat hsize vsize
   {\bgroup
    \forgetall
    \dowithnextbox
diff --git a/tex/context/base/pack-box.mkiv b/tex/context/base/pack-box.mkiv
index a497b1f59..94af540e2 100644
--- a/tex/context/base/pack-box.mkiv
+++ b/tex/context/base/pack-box.mkiv
@@ -741,7 +741,7 @@
 \setvalue{\??ab\??ab \v!line\v!middle}{\baselinemiddlebox}
 \setvalue{\??ab\??ab \v!line\v!right }{\baselinerightbox}
 
-\def\offsetbox
+\unexpanded\def\offsetbox
   {\dodoubleempty\dooffsetbox[]}
 
 % left/right/top/bottomoffset -> dimensions change
@@ -831,8 +831,8 @@
 % \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
 % \input tufte
 
-\def\offset {\dodoubleempty\dooffsetbox [\hbox]} % yes or no
-\def\aligned{\dosingleempty\doalignedbox[\hbox]} % yes or no
+\unexpanded\def\offset {\dodoubleempty\dooffsetbox [\hbox]} % yes or no
+\unexpanded\def\aligned{\dosingleempty\doalignedbox[\hbox]} % yes or no
 
 %\ruledhbox{\offsetbox[x=-1cm,y=-1cm,location=c]
 %  {\framed[width=4cm,height=4cm]{x}}}
@@ -844,9 +844,9 @@
    \hbox to \wd\scratchbox{#1#4#2}%
    \egroup}
 
-\def\ltabbed{\dotabbed\relax\hss}
-\def\rtabbed{\dotabbed\hss  \relax}
-\def\ctabbed{\dotabbed\hss  \hss}      \let\mtabbed\ctabbed
+\unexpanded\def\ltabbed{\dotabbed\relax\hss}
+\unexpanded\def\rtabbed{\dotabbed\hss  \relax}
+\unexpanded\def\ctabbed{\dotabbed\hss  \hss}      \let\mtabbed\ctabbed
 
 % \ltabbed{\romeins{3}}{\romeins{1}} test \endgraf
 % \ltabbed{\romeins{3}}{\romeins{2}} test \endgraf
@@ -893,7 +893,7 @@
 
 % to be documented
 
-\def\phantombox[#1]%
+\unexpanded\def\phantombox[#1]%
   {\hbox\bgroup
    \getparameters
      [\??ol]
@@ -909,7 +909,7 @@
 
 %  \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
 
-\def\backgroundimage#1#2#3% repeat hsize vsize
+\unexpanded\def\backgroundimage#1#2#3% repeat hsize vsize
   {\bgroup
    \forgetall
    \dowithnextbox
diff --git a/tex/context/base/s-ptj-01.tex b/tex/context/base/s-ptj-01.tex
index 188af73bd..9990bf006 100644
--- a/tex/context/base/s-ptj-01.tex
+++ b/tex/context/base/s-ptj-01.tex
@@ -1,29 +1,29 @@
 %D \module
 %D   [      file=s-ptj-01,
-%D        version=2006.11.28,
+%D        version=2009.12.18,
 %D          title=\CONTEXT\ Style File,
 %D       subtitle=PracTeX Journal Style,
 %D         author=Aditya Mahajan,
 %D          email=adityam at umich dot edu,
 %D           date=\currentdate,
-%D      copyright=2006 Aditya Mahajan]
+%D      copyright=2009 Aditya Mahajan]
 %C
 %C This module is part of the \CONTEXT\ macro||package and is
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
 %M % These macros are needed to compile the documentation.
-%M \def\PracTeX{Prac\kern-0.07em\TeX}
-%M \def\PRACTEX{\PracTeX}
-%M \def\TPJ    {The \PRACTEX\ Journal}
-%M \useurl[TPJ][http://www.tug.org/pracjourn/][][\TPJ]
-%M \useurl[texgyre][http://www.gust.org.pl/projects/e-foundry/tex-gyre/]
+%M \def\PracTeX      {Prac\kern-0.07em\TeX}
+%M \def\PRACTEX      {\PracTeX}
+%M \def\pracjourn    {The \PRACTEX\ Journal}
+%M \useurl[pracjourn][http://www.tug.org/pracjourn/][][\pracjourn]
+%M \useurl[texgyre]  [http://www.gust.org.pl/projects/e-foundry/tex-gyre/]
 
 \writestatus  {loading}   {Context Module for the PracTeX Journal}
 
-%D This module is for producing acticles for \from[TPJ]. It merely copies the
+%D This module is for producing acticles for \from[pracjourn]. It merely copies the
 %D layout of the the \LATEX\ class \filename{pracjourn.cls} available from
-%D \TPJ\ website (\url[TPJ]).  This module has a filename synonym
+%D \pracjourn\ website (\url[pracjourn]).  This module has a filename synonym
 %D \filename{pracjourn}. So to use this module, you can write:
 %D \starttyping
 %D \usemodule[pracjourn]
@@ -42,8 +42,8 @@
 
 \unprotect
 
-%D First let's setup the paper size and layout for \TPJ. I am actually not
-%D sure about the \quote{official} layout requirement for \TPJ\ and have
+%D First let's setup the paper size and layout for \pracjourn. I am actually not
+%D sure about the \quote{official} layout requirement for \pracjourn\ and have
 %D reverse engineered the layout from the typeset \LATEX\ examples. If you
 %D feel that anything is wrong here, please let me know.
 
@@ -68,32 +68,16 @@
         footerdistance=.25in,
   ]
 
-%D Next we do the font setup. \TPJ\ uses mathpazo for roman and math faces and
+%D Next we do the font setup. \pracjourn\ uses mathpazo for roman and math faces and
 %D uses latin modern for sans serif and monotype. For the main face, 12pt is
 %D used with a 15.5pt baseline skip. Font protrusion is enabled, but font
-%D expansion is not. We follow these conventions, but use Pagella fonts from
-%D \TEX{gyre} project, and scale latin modern fonts by 1.1 for better
-%D matching. Right now, the \TEX{gyre} fonts are not distributed with
-%D \CONTEXT. They can be downloaded from \url[texgyre]. Most of the numbers
-%D (page numbers, figure numbers, section numbers) are set in oldstyle.
+%D expansion is not. We follow these conventions. \CONTEXT\ uses Pagella fonts
+%D from \TEX{gyre} project, so we use them instead. 
 
 \usetypescript  [serif,sans,mono] [hanging] [pure]
 \setupalign     [hanging]
-
-\usetypescriptfile
-  [type-gyr]
-
-\definetypeface
-  [mainface] [rm] [serif] [palatino] [default] [encoding=texnansi]
-\definetypeface
-  [mainface] [ss] [sans]  [modern]   [default]  [encoding=texnansi, rscale=1.1]
-\definetypeface
-  [mainface] [tt] [mono]  [modern]   [default]  [encoding=texnansi, rscale=1.1]
-\definetypeface
-  [mainface] [mm] [math]  [palatino] [default]  [encoding=texnansi]
-
-\setupbodyfont
-  [mainface,12pt]
+\usetypescript  [palatino][encoding=texnansi]
+\setupbodyfont  [palatino,12pt]
 
 \definefont [titlefont]  [Regular at 20pt]
 \definefont [authorfont] [Regular at 14pt]
@@ -164,11 +148,10 @@
    after={\blank[big]}]
 
 %D Next we define internal frames to take care of the layout of the extra
-%D material in the title. These start with \type|do...| to prevent clash with
-%D user macros. (I do not like writing @ in macro names).
+%D material in the title. 
 
 \defineframed
-  [doinfotitle]
+  [pracjourninfotitle]
   [   frame=off,
       strut=yes,
       width=0.1\textwidth,
@@ -178,7 +161,7 @@
   ]
 
 \defineframed
-  [doinfodetails]
+  [pracjourninfodetails]
   [   frame=off,
       strut=yes,
       width=0.85\textwidth,
@@ -187,27 +170,27 @@
    location=hanging,
   ]
 
-\newif\iftitleskipdone
+\newif\ifpracjourntitleskipdone
 
-\def\doadditionalinfo#1#2
-  {\titleskipdonetrue
+\def\pracjourninfo#1#2%
+  {\pracjourntitleskipdonetrue
     \hbox to \textwidth
    \bgroup
-    \hfill \doinfotitle{#1}
-    \hfill \doinfodetails{#2}
+    \hfill \pracjourninfotitle{#1}
+    \hfill \pracjourninfodetails{#2}
    \egroup\endgraf}
 
 %D Now we take care of the actual layout of the title. Most of this is
 %D heuristic, as I was trying to get the same visual effect as the
 %D \filename{pracjourn.cls} class. If something does not match, please let me
-%D know. The additional information is typeset as
+%D know. The information is typeset as
 %D \starttyping
 %D \hfill <box of .1\textwidth> \hfill <box of .85\textwidth>
 %D \stoptyping
 %D at 11pt size. We also add the title and author information in the \PDF\
 %D metadata.
 
-\startrawsetups [title]
+\startsetups [title]
 % Place the tile and the author
   \title{\getvariable{pracjourn}{title}}
   \blank[medium]
@@ -217,36 +200,42 @@
 % Place the additional information
   \bgroup\switchtobodyfont[11pt]
   \setupindenting[no]
-  \doifdefined{\v!file:::email}
-    {\doadditionalinfo{Email}{\tttf\from[email]\relax}}
-  \doifdefined{\v!file:::website}
-    {\doadditionalinfo{Website}{\from[website]\relax}}
+  \doifurldefinedelse{email}
+    {\pracjourninfo{Email}{\tttf\from[email]\relax}}
+    \empty
+  \doifurldefinedelse{website}
+    {\pracjourninfo{Website}{\from[website]\relax}}
+    \empty
   \doifsomething{\getvariable{pracjourn}{address}}
-    {\doadditionalinfo{Address}{\getvariable{pracjourn}{address}}}
-  \iftitleskipdone  \blank[big] \fi
-  \doadditionalinfo{Abstract}%
-    {\setupindenting[yes]%
-     \setupinterlinespace%
+    {\pracjourninfo{Address}{\getvariable{pracjourn}{address}}}
+  \ifpracjourntitleskipdone  \blank[big] \fi
+  \pracjourninfo{Abstract}
+    {\setupindenting[yes]
+     \setupinterlinespace
      \getbuffer[abstract]
      \endgraf}
   \egroup
   \blank[big]
+  \setups{pracjourndate}
+  % Add information to pdfmetadata
+  \setupinteraction
+    [title={\getvariable{pracjourn}{title}},
+    author={\getvariable{pracjourn}{author}},
+  subtitle={The PracTeX Journal Article}]
+\stopsetups
+  
 % If revision number is present, write it to \filename{_rev.tex}
 % FIXME: Do we need to ensure that the dates and month are two digits?
+\startrawsetups [pracjourndate]
   \doifsomething{\getvariable{pracjourn}{revision}}
   {\expanded{\setvariables[pracjourn:date][y=,m=,d=,\getvariable{pracjourn}{revision}]}
    \immediate\openout \scratchwrite _rev.tex
    \immediate\write   \scratchwrite
    {\getvariable{pracjourn:date}{y}/\getvariable{pracjourn:date}{m}/\getvariable{pracjourn:date}{d}}
    \immediate\closeout\scratchwrite}
-% Add information to pdfmetadata
-  \setupinteraction
-    [title={\getvariable{pracjourn}{title}},
-    author={\getvariable{pracjourn}{author}},
-    subtitle={The PracTeX Journal Article}]
 \stoprawsetups
 
-%D Next we setup the header and footer for the first page. \TPJ\ formats the
+%D Next we setup the header and footer for the first page. \pracjourn\ formats the
 %D header as
 %D \startlines
 %D The PracTeX Journal, year, No. number
@@ -255,32 +244,38 @@
 %D If a copyright notice is present, it is printed right aligned on the bottom
 %D of first page. Otherwise the footer on the first page is empty.
 
-\startlocalsetups [titleheader]
+\startsetups [pracjourntitleheader]
   \framed[frame=off,width=\textwidth,align=normal,location=low]
   {\small\setupinterlinespace
-   \doifelsenothing{\TPJissue}{For submission to \TPJ}{\TPJissue}\endgraf
+   \doifelsenothing{\pracjournissue}
+      {For submission to \pracjourn}
+      {\pracjournissue}
+   \endgraf
    \doifelsenothing{\getvariable{pracjourn}{revision}}
-   {Draft of \currentdate[year,/,mm,/,dd]}
-   {Article revision\space
-     \expanded{\date[\getvariable{pracjourn}{revision}][year,/,mm,/,dd]}}
-    \endgraf}
-\stoplocalsetups
+     {Draft of \currentdate[year,/,mm,/,dd]}
+     {Article revision\space
+      \expanded{\date[\getvariable{pracjourn}{revision}][year,/,mm,/,dd]}}
+   \endgraf}
+\stopsetups
 
-\startlocalsetups [titlefooter]
+\startsetups [pracjourntitlefooter]
   \framed[frame=off,width=\textwidth,align=flushright,location=low]
-  {\small\setupinterlinespace
-  \getvariable{pracjourn}{copyright}\endgraf}
-\stoplocalsetups
+  {\small\setupinterlinespace \getvariable{pracjourn}{copyright}\endgraf}
+\stopsetups
 
-\definetext [titleheader] [header]  [\setups{titleheader}][]
-\definetext [titlefooter] [footer]  [\setups{titlefooter}]
-\setuphead  [title]       [header=titleheader,footer=titlefooter]
+\definetext [pracjourntitleheader] [header]  [\setups{pracjourntitleheader}][]
+\definetext [pracjourntitlefooter] [footer]  [\setups{pracjourntitlefooter}]
+
+\setuphead  
+  [title]           
+  [header=pracjourntitleheader,
+   footer=pracjourntitlefooter]
 
 %D For rest of the pages, page number is printed on the middle of the footer.
 
 \setuppagenumbering [location={footer,middle}, style=mediaeval]
 
-%D Next we setup the formating for the sections.  \TPJ\ wants font sizes of
+%D Next we setup the formating for the sections.  \pracjourn\ wants font sizes of
 %D 17pt, 14pt, and 12pt respectively for section, subsection, and
 %D subsubsection. By default, \tex{tfa} is 1.2, \tex{tfb} is 1.4, so the sizes
 %D come out close to what is required. The section number is typset in
@@ -329,7 +324,7 @@
 
 \def\pracjournfootnote#1{\hbox to 1.5em{#1.}}
 
-%D \TPJ\ uses dash as the first level of itemize and text period as the second
+%D \pracjourn\ uses dash as the first level of itemize and text period as the second
 %D level. The third level is left unspecified.
 
 \definesymbol [1]     [{\symbol[dash]}]
@@ -338,13 +333,6 @@
 \setupitemize [each]  [packed]
 \setupitemize [1]     [packed,autointro]  [margin=1em]
 
-%D We change \type|\type| so that the argument inside \type|\type| is pretty
-%D printed using \TEX's patterns. Another command \type|\normaltype| can be
-%D used if you do not want the original \type|\type|.
-
-\setuptype    [option=TEX]
-\definetype   [normaltype]  [option=none]
-
 %D We enable colors, interaction and bookmarks.
 
 \setupinteraction [state=start,color=darkred,style=normal]
@@ -358,13 +346,13 @@
 \setupwhitespace  [medium]
 \setupblank       [medium]
 
-%D We define logos for \PRACTEX\ and \TPJ. These definitions are copied from
+%D We define logos for \PRACTEX\ and \pracjourn. These definitions are copied from
 %D \filename{pracjourn.cls} and can be accessed by \type|\PracTeX|,
-%D \type|\PRACTEX| and \type|\TPJ|.
+%D \type|\PRACTEX| and \type|\pracjourn|.
 
 \def\PracTeX{Prac\kern-0.07em\TeX}
 \def\PRACTEX{\PracTeX}
-\def\TPJ    {The \PRACTEX\ Journal}
+\def\pracjourn    {The \PRACTEX\ Journal}
 
 %D \filename{pracjourn.cls} provides two macros \type|\ctanfile| and
 %D \type|\ctanloc|. I am not sure what is the advantage of these macors. If
@@ -372,22 +360,22 @@
 %D \CONTEXT. For example
 %D \starttyping
 %D \useURL[pracjourn][http://ctan.org/get?fn=/macros/contrib/latex/pracjourn][][\mono{CTAN:macros/contrib/latex/pracjourn}]
-%D The \LATEX\ style files for \TPJ\ is localed at \from[pracjourn]
+%D The \LATEX\ style files for \pracjourn\ is localed at \from[pracjourn]
 %D \stoptyping
 
 %D For the final version of the paper, the string \quotation{The PracTeX
 %D Journal year, No x} is written on the header. This only happens when the
 %D current directory contains a file \filename{_iss.tex} which contains string
-%D like \quotation{TPJ 2006 No 04, 2006-11-15}. This step is usually taken in
+%D like \quotation{pracjourn 2006 No 04, 2006-11-15}. This step is usually taken in
 %D the final production of the article. If this file is absent, \quotation{For
 %D submission to the PracTeX Journal} is written instead. The next macros are
 %D used to parse this file.
 
-\let\TPJissue\empty
+\let\pracjournissue\empty
 
-\def\parse@iss TPJ #1 No #2, #3-#4-#5\@nil%
+\def\parse@iss pracjourn #1 No #2, #3-#4-#5\@nil%
   {\!!counta#2\relax
-  \edef\TPJissue{\TPJ, #1, No.\,\the\!!counta}}
+  \edef\pracjournissue{\pracjourn, #1, No.\,\the\!!counta}}
 
 %D Read the \filename{_iss.tex} file, if present to determine the current
 %D issue.
diff --git a/tex/context/base/scrn-nav.mkiv b/tex/context/base/scrn-nav.mkiv
index 3eaed3812..cdc862ec0 100644
--- a/tex/context/base/scrn-nav.mkiv
+++ b/tex/context/base/scrn-nav.mkiv
@@ -193,6 +193,18 @@
      \doactivatecolor{#1\c!color}%
    \fi}
 
+%D delayed ...
+
+\def\enableinteractivereferences
+  {\ifproductionrun
+     \ctxlua{jobreferences.enable_interaction()}%
+     \globallet\enableinteractivereferences\relax
+   \fi}
+
+\appendtoks
+    \enableinteractivereferences
+\to \everysetupinteraction
+
 %D More tokens are spend when we want both typeface and color
 %D highlighting.
 
diff --git a/tex/context/base/strc-flt.mkiv b/tex/context/base/strc-flt.mkiv
index 90f8011f6..d826b067e 100644
--- a/tex/context/base/strc-flt.mkiv
+++ b/tex/context/base/strc-flt.mkiv
@@ -699,13 +699,17 @@
         {\global\nofloatnumbertrue}}%
    % this has to change
    \ConvertToConstant\doifelse{#4}{}
+%    \ConvertToConstant\doifelse{\detokenize{#4}}{}
      {\global\emptyfloatcaptiontrue}
      {\global\emptyfloatcaptionfalse}%
+%    \doifinsetelse\v!none{#2}
+%      {\global\nofloatcaptiontrue}
+%      {\ConvertToConstant\doifelse{#4}\v!none
+%         {\global\nofloatcaptiontrue}
+%         {\global\nofloatcaptionfalse}}%
    \doifinsetelse\v!none{#2}
      {\global\nofloatcaptiontrue}
-     {\ConvertToConstant\doifelse{#4}\v!none
-        {\global\nofloatcaptiontrue}
-        {\global\nofloatcaptionfalse}}%
+     {\global\nofloatcaptionfalse}%
    \doif{\floatcaptionparameter\c!number}\v!none % new
     {\global\nofloatcaptiontrue}%
    \ifemptyfloatcaption \ifnofloatnumber
diff --git a/tex/context/base/supp-fil.mkiv b/tex/context/base/supp-fil.mkiv
index bfcefdfa7..7ba71f891 100644
--- a/tex/context/base/supp-fil.mkiv
+++ b/tex/context/base/supp-fil.mkiv
@@ -194,7 +194,7 @@
 \def\inputgivenfile#1{\normalinput"#1"\relax}
 
 %D \macros
-%D   {readfile,ReadFile,maxreadlevel}
+%D   {readfile,ReadFile}
 %D
 %D One cannot be sure if a file exists. When no file can be
 %D found, the \type{\input} primitive gives an error message
@@ -236,13 +236,7 @@
 %D We first present an earlier implementation of
 %D \type{\readfile}. This command backtracks parent
 %D directories, upto a predefined level. Users can change this
-%D level, but we default to~3.
-%D
-%D \starttyping
-%D \def\maxreadlevel {3}
-%D \stoptyping
-%D
-%D This is a pseudo \COUNTER.
+%D level (on the commandline using a directive); we default to~3.
 %D
 %D We use \type{\normalinput} instead of \type{\input}
 %D because we want to be able to redefine the original
@@ -254,20 +248,11 @@
 
 \let \everyreadfile \everybeforereadfile
 
-\newif\iftracefiles
-
-\newcount\readlevel
-
-\def\maxreadlevel{3}
-
-\newconditional\trackfilenames
-\let\trackedfilename\empty
+\def\maxreadlevel{\ctxlua{commands.maxreadlevel()}}
 
 % We need to postpone loading, else we got frozen type-* files and so when
 % a format is generated on a source path.
 
-% tracefiles -> tracker
-
 \def\doreadfile#1#2#3% protocol path filename true false
   {\edef\readfilename{\ctxlua{support.doreadfile("#1","#2","#3")}}%
    \ifx\readfilename\empty
@@ -338,45 +323,6 @@
    \readfile{#1}{#2}{#3}%
    \popcatcodetable}
 
-%D \macros
-%D   {openjobfile,openlocfile,opensysfile,openfixfile}
-%D
-%D The next four alternatives can be used for opening files
-%D for reading on a line||by||line basis. These commands get
-%D an extra argument, the filetag. Explicit closing is done
-%D in the normal way by \type{\closein}.
-
-\def\doopenin#1#2%
-  {\sanitizefilename#2\to\readfilename
-   \checkfilename\readfilename
-   \ifcase\kindoffile
-     \advance\readlevel\plusone
-     \openinputfile{#1}\readfilename
-     \ifeof#1% \relax
-       \ifnum\readlevel>\maxreadlevel % \relax
-       \else
-         \closeinputfile#1% \relax
-         \doopenin{#1}{\pathplusfile\f!parentpath{#2}}%
-       \fi
-     \fi
-   \fi}
-
-\def\openjobin#1#2%
-  {\readlevel\zerocount
-   \doopenin{#1}{\pathplusfile\f!currentpath{#2}}}
-
-\def\opensysin % #1#2%
-  {\readlevel\maxreadlevel
-   \doopenin} % {#1}{#2}}
-
-\def\openlocin#1#2%
-  {\readlevel\maxreadlevel
-   \doopenin{#1}{\pathplusfile\f!currentpath{#2}}}
-
-\def\openfixin#1#2#3%
-  {\readlevel\maxreadlevel
-   \doopenin{#1}{\pathplusfile{#2}{#3}}}
-
 %D \macros
 %D   {doiffileelse,doiflocfileelse}
 %D
diff --git a/tex/context/base/supp-ran.lua b/tex/context/base/supp-ran.lua
index b28b57e9a..0d374541f 100644
--- a/tex/context/base/supp-ran.lua
+++ b/tex/context/base/supp-ran.lua
@@ -11,13 +11,19 @@ if not modules then modules = { } end modules ['supp-ran'] = {
 
 commands = commands or { }
 
-local texwrite, random, randomseed, round, seed, last = tex.write, math.random, math.randomseed, math.round, false, 1
+local random, randomseed, round, seed, last = math.random, math.randomseed, math.round, false, 1
+local texwrite = tex.write
 
-function math.setrandomseedi(n)
+function math.setrandomseedi(n,comment)
     if n <= 1 then
         n = n*1073741823 -- maxcount
     end
-    randomseed(round(n))
+    n = round(n)
+    if false then
+        logs.report("system","setting random seed to %s (%s)",n,comment or "normal")
+    end
+    randomseed(n)
+    last = random(0,1073741823) -- we need an initial value
 end
 
 function commands.getrandomcounta(min,max)
@@ -39,6 +45,8 @@ function commands.getrandomseed(n)
     texwrite(last)
 end
 
+-- maybe stack
+
 function commands.freezerandomseed(n)
     if seed == false then
         seed = last
@@ -50,7 +58,7 @@ end
 
 function commands.defrostrandomseed()
     if seed ~= false then
-        math.setrandomseedi(last)
+        math.setrandomseedi(last,"defrost")
         seed = false
     end
 end
diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua
index 01bcaec0f..4737db9b5 100644
--- a/tex/context/base/task-ini.lua
+++ b/tex/context/base/task-ini.lua
@@ -11,54 +11,67 @@ if not modules then modules = { } end modules ['task-ini'] = {
 --
 -- we can disable more handlers and enable then when really used (*)
 
-tasks.appendaction("processors", "normalizers", "fonts.collections.process")
-tasks.appendaction("processors", "normalizers", "fonts.checkers.missing")                    -- *
+tasks.appendaction("processors", "normalizers", "fonts.collections.process")                 -- todo
+tasks.appendaction("processors", "normalizers", "fonts.checkers.missing")                    -- disabled
 
-tasks.appendaction("processors", "characters",  "chars.handle_mirroring")                    -- *
-tasks.appendaction("processors", "characters",  "chars.handle_casing")                       -- *
-tasks.appendaction("processors", "characters",  "chars.handle_breakpoints")                  -- *
+tasks.appendaction("processors", "characters",  "chars.handle_mirroring")                    -- disabled
+tasks.appendaction("processors", "characters",  "chars.handle_casing")                       -- disabled
+tasks.appendaction("processors", "characters",  "chars.handle_breakpoints")                  -- disabled
 tasks.appendaction("processors", "characters",  "scripts.preprocess")
 
-tasks.appendaction("processors", "words",       "kernel.hyphenation")
-tasks.appendaction("processors", "words",       "languages.words.check")                     -- * disabled
+tasks.appendaction("processors", "words",       "kernel.hyphenation")                        -- always on
+tasks.appendaction("processors", "words",       "languages.words.check")                     -- disabled
 
+tasks.appendaction("processors", "fonts",       "nodes.process_characters")                  -- maybe todo
+tasks.appendaction("processors", "fonts",       "nodes.inject_kerns")                        -- maybe todo
+tasks.appendaction("processors", "fonts",       "nodes.protect_glyphs", nil, "nohead")       -- maybe todo
+tasks.appendaction("processors", "fonts",       "kernel.ligaturing")                         -- always on
+tasks.appendaction("processors", "fonts",       "kernel.kerning")                            -- always on
 
-tasks.appendaction("processors", "fonts",       "nodes.process_characters")
-tasks.appendaction("processors", "fonts",       "nodes.inject_kerns")
-tasks.appendaction("processors", "fonts",       "nodes.protect_glyphs", nil, "nohead")
-tasks.appendaction("processors", "fonts",       "kernel.ligaturing")
-tasks.appendaction("processors", "fonts",       "kernel.kerning")
+tasks.appendaction("processors", "lists",       "lists.handle_spacing")                      -- disabled
+tasks.appendaction("processors", "lists",       "lists.handle_kerning")                      -- disabled
 
-tasks.appendaction("processors", "lists",       "lists.handle_spacing")                      -- * disabled
-tasks.appendaction("processors", "lists",       "lists.handle_kerning")                      -- * disabled
+tasks.appendaction("shipouts",   "normalizers", "nodes.cleanup_page")                        -- maybe todo
+tasks.appendaction("shipouts",   "normalizers", "nodes.add_references")                      -- disabled
+tasks.appendaction("shipouts",   "normalizers", "nodes.add_destinations")                    -- disabled
+tasks.appendaction("shipouts",   "normalizers", "nodes.rules.process")                       -- disabled
+tasks.appendaction("shipouts",   "normalizers", "nodes.shifts.process")                      -- disabled
 
-tasks.appendaction("shipouts",   "normalizers", "nodes.cleanup_page")
-tasks.appendaction("shipouts",   "normalizers", "nodes.add_references")                      -- *
-tasks.appendaction("shipouts",   "normalizers", "nodes.add_destinations")                    -- *
-tasks.appendaction("shipouts",   "normalizers", "nodes.rules.process")                       -- * disabled
-tasks.appendaction("shipouts",   "normalizers", "nodes.shifts.process")                      -- * disabled
+tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_color")                     -- disabled
+tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_transparency")              -- disabled
+tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_colorintent")               -- disabled
+tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_negative")                  -- disabled
+tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_effect")                    -- disabled
+tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_viewerlayer")               -- disabled
 
-tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_color")
-tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_transparency")
-tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_colorintent")               -- *
-tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_negative")                  -- *
-tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_effect")                    -- *
-tasks.appendaction("shipouts",   "finishers",   "shipouts.handle_viewerlayer")               -- *
+tasks.appendaction("math",       "normalizers", "noads.relocate_characters", nil, "nohead")  -- always on
+tasks.appendaction("math",       "normalizers", "noads.resize_characters",   nil, "nohead")  -- always on
+tasks.appendaction("math",       "normalizers", "noads.respace_characters",  nil, "nohead")  -- always on
 
-tasks.appendaction("math",       "normalizers", "noads.relocate_characters", nil, "nohead")
-tasks.appendaction("math",       "normalizers", "noads.resize_characters",   nil, "nohead")
-tasks.appendaction("math",       "normalizers", "noads.respace_characters",  nil, "nohead")
-
-tasks.appendaction("math",       "builders",    "noads.mlist_to_hlist")
+tasks.appendaction("math",       "builders",    "noads.mlist_to_hlist")                      -- always on
 
 -- quite experimental
 
-tasks.appendaction("finalizers", "lists",       "nodes.repackage_graphicvadjust")            -- *
+tasks.appendaction("finalizers", "lists",       "nodes.repackage_graphicvadjust")            -- todo
 
--- speedup: see * -- only kick in when used
+-- speedup: only kick in when used
 
+tasks.disableaction("processors", "fonts.checkers.missing")
+tasks.disableaction("processors", "chars.handle_breakpoints")
+tasks.disableaction("processors", "chars.handle_casing")
+tasks.disableaction("processors", "chars.handle_mirroring")
 tasks.disableaction("processors", "languages.words.check")
 tasks.disableaction("processors", "lists.handle_spacing")
 tasks.disableaction("processors", "lists.handle_kerning")
+
 tasks.disableaction("shipouts",   "nodes.rules.process")
 tasks.disableaction("shipouts",   "nodes.shifts.process")
+tasks.disableaction("shipouts",   "shipouts.handle_color")
+tasks.disableaction("shipouts",   "shipouts.handle_transparency")
+tasks.disableaction("shipouts",   "shipouts.handle_colorintent")
+tasks.disableaction("shipouts",   "shipouts.handle_effect")
+tasks.disableaction("shipouts",   "shipouts.handle_negative")
+tasks.disableaction("shipouts",   "shipouts.handle_viewerlayer")
+
+tasks.disableaction("shipouts",   "nodes.add_references")
+tasks.disableaction("shipouts",   "nodes.add_destinations")
diff --git a/tex/context/base/trac-log.lua b/tex/context/base/trac-log.lua
index b68660a8e..00af9895b 100644
--- a/tex/context/base/trac-log.lua
+++ b/tex/context/base/trac-log.lua
@@ -133,6 +133,7 @@ function logs.tex.stop_page_number()
     else
         logs.report("pages", "flushing page")
     end
+    io.flush()
 end
 
 logs.tex.report_job_stat = statistics.show_job_stat
diff --git a/tex/context/base/trac-tra.lua b/tex/context/base/trac-tra.lua
index e4cbd1e01..128cd63dc 100644
--- a/tex/context/base/trac-tra.lua
+++ b/tex/context/base/trac-tra.lua
@@ -149,20 +149,44 @@ end
 setters      = setters      or { }
 setters.data = setters.data or { }
 
+--~ local function set(t,what,value)
+--~     local data, done = t.data, t.done
+--~     if type(what) == "string" then
+--~         what = aux.settings_to_array(what) -- inefficient but ok
+--~     end
+--~     for i=1,#what do
+--~         local w = what[i]
+--~         for d, f in next, data do
+--~             if done[d] then
+--~                 -- prevent recursion due to wildcards
+--~             elseif find(d,w) then
+--~                 done[d] = true
+--~                 for i=1,#f do
+--~                     f[i](value)
+--~                 end
+--~             end
+--~         end
+--~     end
+--~ end
+
 local function set(t,what,value)
     local data, done = t.data, t.done
     if type(what) == "string" then
-        what = aux.settings_to_array(what) -- inefficient but ok
+        what = aux.settings_to_hash(what) -- inefficient but ok
     end
-    for i=1,#what do
-        local w = what[i]
+    for w, v in next, what do
+        if v == "" then
+            v = value
+        else
+            v = toboolean(v)
+        end
         for d, f in next, data do
             if done[d] then
                 -- prevent recursion due to wildcards
             elseif find(d,w) then
                 done[d] = true
                 for i=1,#f do
-                    f[i](value)
+                    f[i](v)
                 end
             end
         end
@@ -251,7 +275,9 @@ function setters.show(t)
 end
 
 -- we could have used a bit of oo and the trackers:enable syntax but
--- there is already a lot of code around using the singluar tracker
+-- there is already a lot of code around using the singular tracker
+
+-- we could make this into a module
 
 function setters.new(name)
     local t
diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua
index e3d0a8ad8..5cab6a667 100644
--- a/tex/context/base/typo-brk.lua
+++ b/tex/context/base/typo-brk.lua
@@ -28,7 +28,6 @@ local kern    = node.id("kern")
 breakpoints           = breakpoints         or { }
 breakpoints.mapping   = breakpoints.mapping or { }
 breakpoints.methods   = breakpoints.methods or { }
-breakpoints.enabled   = false
 breakpoints.attribute = attributes.private("breakpoint")
 
 storage.register("breakpoints/mapping", breakpoints.mapping, "breakpoints.mapping")
@@ -189,3 +188,7 @@ chars.handle_breakpoints = nodes.install_attribute_handler {
     namespace = breakpoints,
     processor = breakpoints.process,
 }
+
+function breakpoints.enable()
+    tasks.enableaction("processors","chars.handle_breakpoints")
+end
diff --git a/tex/context/base/typo-brk.mkiv b/tex/context/base/typo-brk.mkiv
index 90561fc9e..f53e44810 100644
--- a/tex/context/base/typo-brk.mkiv
+++ b/tex/context/base/typo-brk.mkiv
@@ -52,7 +52,7 @@
    \fi}
 
 \def\setbreakpoints
-  {\ctxlua{breakpoints.enabled=true}%
+  {\ctxlua{breakpoints.enable()}%
    \gdef\setbreakpoints[##1]{\dosetattribute{breakpoint}{\csname\??bp:##1\endcsname}}%
    \setbreakpoints}
 
diff --git a/tex/context/base/typo-cap.lua b/tex/context/base/typo-cap.lua
index 347456171..302953192 100644
--- a/tex/context/base/typo-cap.lua
+++ b/tex/context/base/typo-cap.lua
@@ -23,7 +23,6 @@ local fontdata = fonts.ids
 local chardata = characters.data
 
 cases           = cases or { }
-cases.enabled   = false
 cases.actions   = { }
 cases.attribute = attributes.private("case")
 
@@ -202,3 +201,7 @@ chars.handle_casing = nodes.install_attribute_handler {
     namespace = cases,
     processor = cases.process,
 }
+
+function cases.enable()
+    tasks.enableaction("processors","chars.handle_casing")
+end
diff --git a/tex/context/base/typo-cap.mkiv b/tex/context/base/typo-cap.mkiv
index 45a932200..40885d6c2 100644
--- a/tex/context/base/typo-cap.mkiv
+++ b/tex/context/base/typo-cap.mkiv
@@ -51,8 +51,8 @@
 % test \word{test TEST \TeX} test
 % test \Word{test TEST \TeX} test
 
-\def\setcharactercasing
-  {\ctxlua{cases.enabled=true}%
+\unexpanded\def\setcharactercasing
+  {\ctxlua{cases.enable()}%
    \gdef\setcharactercasing[##1]{\dosetattribute{case}{\number##1}}%
    \setcharactercasing}
 
diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua
index 87e066531..c5a56865a 100644
--- a/tex/context/base/typo-krn.lua
+++ b/tex/context/base/typo-krn.lua
@@ -33,7 +33,6 @@ local chardata = characters.data
 
 kerns           = kerns or { }
 kerns.mapping   = kerns.mapping or { }
-kerns.enabled   = false
 kerns.attribute = attributes.private("kern")
 
 storage.register("kerns/mapping", kerns.mapping, "kerns.mapping")
@@ -220,5 +219,4 @@ lists.handle_kerning = nodes.install_attribute_handler {
 
 function kerns.enable()
     tasks.enableaction("processors","lists.handle_kerning")
-    kerns.enabled = true -- will go
 end
diff --git a/tex/context/base/typo-krn.mkiv b/tex/context/base/typo-krn.mkiv
index e2f10d806..43f65021b 100644
--- a/tex/context/base/typo-krn.mkiv
+++ b/tex/context/base/typo-krn.mkiv
@@ -46,7 +46,7 @@
    \fi}
 
 \def\setcharacterkerning
-  {\ctxlua{kerns.enabled=true}%
+  {\ctxlua{kerns.enable()}%
    \gdef\setcharacterkerning[##1]{\dosetattribute{kern}{\csname\??ck:##1\endcsname}}%
    \setcharacterkerning}
 
diff --git a/tex/context/base/typo-mir.lua b/tex/context/base/typo-mir.lua
index 54b88dfac..6e5d8663c 100644
--- a/tex/context/base/typo-mir.lua
+++ b/tex/context/base/typo-mir.lua
@@ -56,13 +56,12 @@ local chardata = characters.data
 --  elseif d == "ws"  then -- Whitespace
 --  elseif d == "on"  then -- Other Neutrals
 
-mirror         = mirror or { }
-mirror.enabled = false
-mirror.strip   = false
-mirror.attribute = attributes.private("mirror")
+mirroring           = mirroring or { }
+mirroring.strip     = false
+mirroring.attribute = attributes.private("mirroring")
 
 local state   = attributes.private('state')
-local mirrora = attributes.private('mirror')
+local mirrora = attributes.private('mirroring')
 
 local directions = characters.directions -- maybe make a special mirror table
 
@@ -144,7 +143,7 @@ local function force_auto_right_before()
     end
 end
 
-function mirror.process(namespace,attribute,start) -- todo: make faster
+function mirroring.process(namespace,attribute,start) -- todo: make faster
     if not start.next then
         return start, false
     end
@@ -379,7 +378,7 @@ function mirror.process(namespace,attribute,start) -- todo: make faster
         end
         logs.report("bidi","stop log")
     end
-    if done and mirror.strip then
+    if done and mirroring.strip then
         local n = #obsolete
         if n > 0 then
             for i=1,n do
@@ -408,7 +407,11 @@ end
 --~         end
 
 chars.handle_mirroring = nodes.install_attribute_handler {
-    name = "mirror",
-    namespace = mirror,
-    processor = mirror.process,
+    name = "mirroring",
+    namespace = mirroring,
+    processor = mirroring.process,
 }
+
+function mirroring.enable()
+    tasks.enableaction("processors","chars.handle_mirroring")
+end
diff --git a/tex/context/base/typo-mir.mkiv b/tex/context/base/typo-mir.mkiv
index fe9d793e0..7edd207ae 100644
--- a/tex/context/base/typo-mir.mkiv
+++ b/tex/context/base/typo-mir.mkiv
@@ -17,17 +17,17 @@
 
 \registerctxluafile{typo-mir}{1.001}
 
-\definesystemattribute[mirror]
+\definesystemattribute[mirroring]
 
 % experimental mirroring
 
 \def\setcharactermirroring
-  {\ctxlua{mirror.enabled=true}%
-   \gdef\setcharactermirroring[##1]{\dosetattribute{mirror}{\number##1}}%
+  {\ctxlua{mirroring.enable()}%
+   \gdef\setcharactermirroring[##1]{\dosetattribute{mirroring}{\number##1}}%
    \setcharactermirroring}
 
 \def\resetcharactermirroring
-  {\doresetattribute{mirror}}
+  {\doresetattribute{mirroring}}
 
 \newtoks\everysetupdirections
 
@@ -100,9 +100,9 @@
 \def\biditest#1#2#3% font text raw
   {\dontleavehmode\hbox
     {\framed[offset=overlay]{\tttf#2}\quad
-     \ctxlua{mirror.trace = true}%
+     \enabletrackers[nodes.mirroring]%
      \framed[offset=overlay]{#1#3}\quad
-     \ctxlua{mirror.trace = false}
+     \disabletrackers[nodes.mirroring]%
      \tttf\ctxlua{document.split_tokens([[\detokenize{#3}]])}}}
 
 \startbuffer[bidi-sample]
diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua
index d9ded1cfa..117d49914 100644
--- a/tex/context/base/typo-spa.lua
+++ b/tex/context/base/typo-spa.lua
@@ -25,7 +25,6 @@ local fontdata           = fonts.ids
 
 spacings           = spacings         or { }
 spacings.mapping   = spacings.mapping or { }
-spacings.enabled   = false -- will go
 spacings.attribute = attributes.private("spacing")
 
 storage.register("spacings/mapping", spacings.mapping, "spacings.mapping")
@@ -151,7 +150,6 @@ lists.handle_spacing = nodes.install_attribute_handler {
 
 function spacings.enable()
     tasks.enableaction("processors","lists.handle_spacing")
-    spacings.enabled = true -- will go
 end
 
 --~ local data = {
diff --git a/tex/context/base/typo-spa.mkiv b/tex/context/base/typo-spa.mkiv
index 9ff614be9..6bb126351 100644
--- a/tex/context/base/typo-spa.mkiv
+++ b/tex/context/base/typo-spa.mkiv
@@ -43,7 +43,6 @@
    \fi}
 
 \def\setcharacterspacing
-%   {\ctxlua{spacings.enabled=true}%
   {\ctxlua{spacings.enable()}%
    \gdef\setcharacterspacing[##1]{\dosetattribute{spacing}{\csname\??ch:##1\endcsname}}%
    \setcharacterspacing}
diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua
index 959033e31..52c46884c 100644
--- a/tex/generic/context/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts-merged.lua
 -- parent file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts.lua
--- merge date  : 12/18/09 11:16:33
+-- merge date  : 12/22/09 13:19:25
 
 do -- begin closure to overcome local limits and interference
 
@@ -3541,6 +3541,7 @@ function tfm.do_scale(tfmtable, scaledpoints)
         scaledpoints = (- scaledpoints/1000) * tfmtable.designsize -- already in sp
     end
     local delta = scaledpoints/(tfmtable.units or 1000) -- brr, some open type fonts have 2048
+    local hdelta, vdelta = delta, delta
     local t = { }
     -- unicoded unique descriptions shared cidinfo characters changed parameters indices
     for k,v in next, tfmtable do
@@ -3550,6 +3551,15 @@ function tfm.do_scale(tfmtable, scaledpoints)
             t[k] = v
         end
     end
+    local stretch = tfmtable.stretch or 0
+    if stretch ~= 0 and stretch ~= 1 then
+        hdelta = hdelta * stretch
+        t.extend = stretch * 1000
+    end
+    local slant = tfmtable.slant or 0
+    if slant ~= 0 then
+        t.slant = t.slant * 1000
+    end
     -- status
     local isvirtual = tfmtable.type == "virtual" or tfmtable.virtualized
     local hasmath = (tfmtable.math_parameters ~= nil and next(tfmtable.math_parameters) ~= nil) or (tfmtable.MathConstants ~= nil and next(tfmtable.MathConstants) ~= nil)
@@ -3577,12 +3587,12 @@ t.colorscheme = tfmtable.colorscheme
     local tfmp = tfmtable.parameters -- let's check for indexes
     --
     tp.slant         = (tfmp.slant         or tfmp[1] or 0)
-    tp.space         = (tfmp.space         or tfmp[2] or 0)*delta
-    tp.space_stretch = (tfmp.space_stretch or tfmp[3] or 0)*delta
-    tp.space_shrink  = (tfmp.space_shrink  or tfmp[4] or 0)*delta
-    tp.x_height      = (tfmp.x_height      or tfmp[5] or 0)*delta
-    tp.quad          = (tfmp.quad          or tfmp[6] or 0)*delta
-    tp.extra_space   = (tfmp.extra_space   or tfmp[7] or 0)*delta
+    tp.space         = (tfmp.space         or tfmp[2] or 0)*hdelta
+    tp.space_stretch = (tfmp.space_stretch or tfmp[3] or 0)*hdelta
+    tp.space_shrink  = (tfmp.space_shrink  or tfmp[4] or 0)*hdelta
+    tp.x_height      = (tfmp.x_height      or tfmp[5] or 0)*vdelta
+    tp.quad          = (tfmp.quad          or tfmp[6] or 0)*hdelta
+    tp.extra_space   = (tfmp.extra_space   or tfmp[7] or 0)*hdelta
     local protrusionfactor = (tp.quad ~= 0 and 1000/tp.quad) or 0
     local tc = t.characters
     local characters = tfmtable.characters
@@ -3599,11 +3609,11 @@ t.colorscheme = tfmtable.colorscheme
     local sharedkerns, basekerns = tfm.check_base_kerns(tfmtable)
     -- loop over descriptions (afm and otf have descriptions, tfm not)
     -- there is no need (yet) to assign a value to chr.tonunicode
-    local scaledwidth  = defaultwidth  * delta
-    local scaledheight = defaultheight * delta
-    local scaleddepth  = defaultdepth  * delta
+    local scaledwidth  = defaultwidth  * hdelta
+    local scaledheight = defaultheight * vdelta
+    local scaleddepth  = defaultdepth  * vdelta
     local stackmath = tfmtable.ignore_stack_math ~= true
-local private = fonts.private
+    local private = fonts.private
     for k,v in next, characters do
         local chr, description, index
         if ischanged then
@@ -3624,9 +3634,9 @@ local private = fonts.private
         local width  = description.width
         local height = description.height
         local depth  = description.depth
-        if width  then width  = delta*width  else width  = scaledwidth  end
-        if height then height = delta*height else height = scaledheight end
-    --  if depth  then depth  = delta*depth  else depth  = scaleddepth  end
+        if width  then width  = hdelta*width  else width  = scaledwidth  end
+        if height then height = vdelta*height else height = scaledheight end
+    --  if depth  then depth  = vdelta*depth  else depth  = scaleddepth  end
         if depth and depth ~= 0 then
             depth = delta*depth
             if nameneeded then
@@ -3690,7 +3700,7 @@ local private = fonts.private
         if hasitalic then
             local vi = description.italic or v.italic
             if vi and vi ~= 0 then
-                chr.italic = vi*delta
+                chr.italic = vi*hdelta
             end
         end
         -- to be tested
@@ -3706,19 +3716,19 @@ local private = fonts.private
                     for i=1,#vv do
                         local vvi = vv[i]
                         t[i] = {
-                            ["start"]    = (vvi["start"]   or 0)*delta,
-                            ["end"]      = (vvi["end"]     or 0)*delta,
-                            ["advance"]  = (vvi["advance"] or 0)*delta,
+                            ["start"]    = (vvi["start"]   or 0)*vdelta,
+                            ["end"]      = (vvi["end"]     or 0)*vdelta,
+                            ["advance"]  = (vvi["advance"] or 0)*vdelta,
                             ["extender"] =  vvi["extender"],
                             ["glyph"]    =  vvi["glyph"],
                         }
                     end
                     chr.vert_variants = t
---~ local ic = v.vert_italic_correction
---~ if ic then
---~     chr.italic = ic * delta
---~     print(format("0x%05X -> %s",k,chr.italic))
---~ end
+                --~ local ic = v.vert_italic_correction
+                --~ if ic then
+                --~     chr.italic = ic * hdelta
+                --~     print(format("0x%05X -> %s",k,chr.italic))
+                --~ end
                 else
                     local hv = v.horiz_variants
                     if hv then
@@ -3726,9 +3736,9 @@ local private = fonts.private
                         for i=1,#hv do
                             local hvi = hv[i]
                             t[i] = {
-                                ["start"]    = (hvi["start"]   or 0)*delta,
-                                ["end"]      = (hvi["end"]     or 0)*delta,
-                                ["advance"]  = (hvi["advance"] or 0)*delta,
+                                ["start"]    = (hvi["start"]   or 0)*hdelta,
+                                ["end"]      = (hvi["end"]     or 0)*hdelta,
+                                ["advance"]  = (hvi["advance"] or 0)*hdelta,
                                 ["extender"] =  hvi["extender"],
                                 ["glyph"]    =  hvi["glyph"],
                             }
@@ -3739,31 +3749,23 @@ local private = fonts.private
             end
             local vt = description.top_accent
             if vt then
-                chr.top_accent = delta*vt
+                chr.top_accent = vdelta*vt
             end
             if stackmath then
                 local mk = v.mathkerns
                 if mk then
                     local kerns = { }
-                 -- for k, v in next, mk do
-                 --     local kk = { }
-                  --     for i=1,#v do
-                 --         local vi = v[i]
-                 --         kk[i] = { height = delta*vi.height, kern = delta*vi.kern }
-                 --     end
-                 --     kerns[k] = kk
-                 -- end
                     local v = mk.top_right    if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.top_right    = k end
                     local v = mk.top_left     if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.top_left     = k end
                     local v = mk.bottom_left  if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.bottom_left  = k end
                     local v = mk.bottom_right if v then local k = { } for i=1,#v do local vi = v[i]
-                        k[i] = { height = delta*vi.height, kern = delta*vi.kern }
+                        k[i] = { height = vdelta*vi.height, kern = vdelta*vi.kern }
                     end     kerns.bottom_right = k end
                     chr.mathkern = kerns -- singular
                 end
@@ -3776,13 +3778,13 @@ local private = fonts.private
                     local base = basekerns[vk] -- hashed by table id, not content
                     if not base then
                         base = {}
-                        for k,v in next, vk do base[k] = v*delta end
+                        for k,v in next, vk do base[k] = v*hdelta end
                         basekerns[vk] = base
                     end
                     chr.kerns = base
                 else
                     local tt = {}
-                    for k,v in next, vk do tt[k] = v*delta end
+                    for k,v in next, vk do tt[k] = v*hdelta end
                     chr.kerns = tt
                 end
             end
@@ -3816,8 +3818,10 @@ local private = fonts.private
                     for i=1,#vc do
                         local ivc = vc[i]
                         local key = ivc[1]
-                        if key == "right" or key == "down" then
-                            tt[#tt+1] = { key, ivc[2]*delta }
+                        if key == "right" then
+                            tt[#tt+1] = { key, ivc[2]*hdelta }
+                        elseif key == "down" then
+                            tt[#tt+1] = { key, ivc[2]*vdelta }
                         else -- not comment
                             tt[#tt+1] = ivc -- shared since in cache and untouched
                         end
@@ -3829,13 +3833,12 @@ local private = fonts.private
             end
         end
         tc[k] = chr
---~ if k == 0x222B then
---~     print(t.fontname,table.serialize(chr))
---~ end
     end
     -- t.encodingbytes, t.filename, t.fullname, t.name: elsewhere
     t.size = scaledpoints
     t.factor = delta
+    t.hfactor = hdelta
+    t.vfactor = vdelta
     if t.fonts then
         t.fonts = table.fastcopy(t.fonts) -- maybe we virtualize more afterwards
     end
@@ -3843,7 +3846,7 @@ local private = fonts.private
      -- mathematics.extras.copy(t) -- can be done elsewhere if needed
         local ma = tfm.mathactions
         for i=1,#ma do
-            ma[i](t,tfmtable,delta)
+            ma[i](t,tfmtable,delta,hdelta,vdelta) -- what delta?
         end
     end
     -- needed for \high cum suis
@@ -5349,7 +5352,7 @@ otf.features.default = otf.features.default or { }
 otf.enhancers        = otf.enhancers        or { }
 otf.glists           = { "gsub", "gpos" }
 
-otf.version          = 2.640 -- beware: also sync font-mis.lua
+otf.version          = 2.641 -- beware: also sync font-mis.lua
 otf.pack             = true  -- beware: also sync font-mis.lua
 otf.syncspace        = true
 otf.notdef           = false
@@ -6797,7 +6800,7 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th
         tfm.cidinfo.registry   = tfm.cidinfo.registry or ""
         tfm.type               = "real"
         tfm.stretch            = 0 -- stretch
-        tfm.slant              = 0 -- slant
+        tfm.slant              = 0 -- data.slant
         tfm.direction          = 0
         tfm.boundarychar_label = 0
         tfm.boundarychar       = 65536
-- 
cgit v1.2.3