From c77671a43d94378e828762b50b94b2adebcafe32 Mon Sep 17 00:00:00 2001
From: Context Git Mirror Bot <phg42.2a@gmail.com>
Date: Thu, 21 May 2015 14:15:04 +0200
Subject: 2015-05-21 13:41:00

---
 tex/context/base/cont-new.mkiv                     |   2 +-
 tex/context/base/context-version.pdf               | Bin 4182 -> 4178 bytes
 tex/context/base/context.mkiv                      |   5 +-
 tex/context/base/core-con.lua                      |   2 +-
 tex/context/base/core-sys.mkiv                     |  19 +-
 tex/context/base/font-mis.lua                      |   2 +-
 tex/context/base/font-otf.lua                      | 312 ++++++++++++---------
 tex/context/base/lpdf-epd.lua                      |   2 +-
 tex/context/base/lxml-tab.lua                      |   9 +
 tex/context/base/math-fen.mkiv                     |   4 +
 tex/context/base/math-ini.mkiv                     |  14 +-
 tex/context/base/mult-ini.lua                      |  11 +
 tex/context/base/mult-ini.mkiv                     |   1 +
 tex/context/base/mult-low.lua                      |   1 +
 tex/context/base/mult-prm.lua                      |   1 +
 tex/context/base/pack-rul.mkiv                     |   2 +-
 tex/context/base/page-mrk.mkiv                     |   2 +
 tex/context/base/phys-dim.lua                      |  25 +-
 tex/context/base/phys-dim.mkiv                     |  27 +-
 tex/context/base/publ-dat.lua                      |   1 +
 tex/context/base/publ-imp-apa.mkvi                 | 111 +++++---
 tex/context/base/publ-imp-aps.mkvi                 |  83 ++++--
 tex/context/base/publ-imp-default.mkvi             |  59 +++-
 tex/context/base/publ-imp-list.mkvi                |  22 +-
 tex/context/base/publ-ini.lua                      | 173 +++++++-----
 tex/context/base/publ-ini.mkiv                     | 110 +++++---
 tex/context/base/publ-reg.lua                      |  52 +++-
 tex/context/base/publ-tra.lua                      |  24 ++
 tex/context/base/publ-tra.mkiv                     |   4 +
 tex/context/base/status-files.pdf                  | Bin 24470 -> 24514 bytes
 tex/context/base/status-lua.pdf                    | Bin 251173 -> 251206 bytes
 tex/context/base/strc-mat.mkiv                     |  32 ++-
 tex/context/base/syst-ini.mkiv                     |   4 +
 tex/context/base/trac-vis.lua                      |  30 +-
 tex/context/base/trac-vis.mkiv                     |   2 +-
 tex/context/base/typo-itc.lua                      |  10 +-
 tex/context/base/typo-sus.lua                      |   7 +
 tex/context/base/util-str.lua                      |   2 +-
 tex/context/base/x-asciimath.lua                   |  30 +-
 tex/context/base/x-asciimath.mkiv                  |  16 +-
 tex/generic/context/luatex/luatex-fonts-merged.lua | 244 +++++++++-------
 41 files changed, 975 insertions(+), 482 deletions(-)

(limited to 'tex')

diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index 6cf0725e6..95a707514 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2015.05.15 11:42}
+\newcontextversion{2015.05.21 13:39}
 
 %D This file is loaded at runtime, thereby providing an excellent place for
 %D hacks, patches, extensions and new features.
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 2c40d33ca..63deabdbb 100644
Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index da357ca9a..029516ce4 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -39,7 +39,7 @@
 %D up and the dependencies are more consistent.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2015.05.15 11:42}
+\edef\contextversion{2015.05.21 13:39}
 \edef\contextkind   {beta}
 
 %D For those who want to use this:
@@ -483,7 +483,7 @@
 \loadmarkfile{math-dis}
 %loadmarkfile{math-lan}
 
-\loadmarkfile{phys-dim}
+%loadmarkfile{phys-dim} % moved to after typo-scr
 
 \loadmarkfile{strc-mat}
 
@@ -491,6 +491,7 @@
 \loadmarkfile{chem-str}
 
 \loadmarkfile{typo-scr}
+\loadmarkfile{phys-dim}
 
 \loadmarkfile{node-rul}
 \loadmkvifile{font-sol} % font solutions
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua
index be462e1d2..37942ae71 100644
--- a/tex/context/base/core-con.lua
+++ b/tex/context/base/core-con.lua
@@ -807,7 +807,7 @@ end
 implement {
     name      = "ordinal",
     actions   = ctxordinal,
-    arguments = { "string", "string" }
+    arguments = { "integer", "string" }
 }
 
 -- verbose numbers
diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv
index 27bbec0b1..1358f4cce 100644
--- a/tex/context/base/core-sys.mkiv
+++ b/tex/context/base/core-sys.mkiv
@@ -208,27 +208,32 @@
 \to \everydefinestartstop
 
 \unexpanded\def\syst_startstop_start#1%
-  {\namedstartstopparameter{#1}\c!before
+  {\namedstartstopparameter{#1}\c!before\relax
    \bgroup
    \def\currentstartstop{#1}%
-   \startstopparameter\c!commands
+   % we will keep this for a while:
+   \startstopparameter\c!commands\relax % obsolete
+   % this is the new method:
+   \usesetupsparameter\startstopparameter\relax % only in the display version
    \dostarttagged\t!construct\currentstartstop
    \usestartstopstyleandcolor\c!style\c!color}
 
 \unexpanded\def\syst_startstop_stop#1%
   {\dostoptagged
    \egroup
-   \namedstartstopparameter{#1}\c!after}
+   \namedstartstopparameter{#1}\c!after\relax}
 
 \unexpanded\def\syst_startstop_indeed#1%
   {\groupedcommand
      {\def\currentstartstop{#1}%
-      \startstopparameter\c!commands % will become setups
+      \startstopparameter\c!commands\relax % better: setups so that will show op soon
       \dostarttagged\t!construct\currentstartstop
-      \usestartstopstyleandcolor\c!style\c!color}
-     {\def\currentstartstop{#1}%
+      \usestartstopstyleandcolor\c!style\c!color
+      \startstopparameter\c!left\relax}
+     {\def\currentstartstop{#1}% safeguard, nto really needed
+      \startstopparameter\c!right\relax
       \dostoptagged
-      \startstopparameter\c!inbetween}}
+      \startstopparameter\c!inbetween\relax}}
 
 % \definestartstop[tracing][\c!style=\tt]
 
diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua
index 0ec95ee1b..c7fb1da1b 100644
--- a/tex/context/base/font-mis.lua
+++ b/tex/context/base/font-mis.lua
@@ -22,7 +22,7 @@ local handlers = fonts.handlers
 handlers.otf   = handlers.otf or { }
 local otf      = handlers.otf
 
-otf.version    = otf.version or 2.803
+otf.version    = otf.version or 2.810
 otf.cache      = otf.cache   or containers.define("fonts", "otf", otf.version, true)
 
 local fontloader    = fontloader
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index 85eebaaeb..dab7137f8 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -36,6 +36,7 @@ local elapsedtime        = statistics.elapsedtime
 local findbinfile        = resolvers.findbinfile
 
 local trace_private      = false  registertracker("otf.private",        function(v) trace_private   = v end)
+local trace_subfonts     = false  registertracker("otf.subfonts",       function(v) trace_subfonts  = v end)
 local trace_loading      = false  registertracker("otf.loading",        function(v) trace_loading   = v end)
 local trace_features     = false  registertracker("otf.features",       function(v) trace_features  = v end)
 local trace_dynamics     = false  registertracker("otf.dynamics",       function(v) trace_dynamics  = v end)
@@ -53,7 +54,7 @@ local otf                = fonts.handlers.otf
 
 otf.glists               = { "gsub", "gpos" }
 
-otf.version              = 2.803 -- beware: also sync font-mis.lua
+otf.version              = 2.810 -- beware: also sync font-mis.lua
 otf.cache                = containers.define("fonts", "otf", otf.version, true)
 
 local hashes             = fonts.hashes
@@ -699,6 +700,7 @@ end
 -- not setting hasitalics and class (when nil) during table cronstruction can save some mem
 
 actions["prepare glyphs"] = function(data,filename,raw)
+    local tableversion = tonumber(raw.table_version) or 0
     local rawglyphs    = raw.glyphs
     local rawsubfonts  = raw.subfonts
     local rawcidinfo   = raw.cidinfo
@@ -722,81 +724,110 @@ actions["prepare glyphs"] = function(data,filename,raw)
             local cidmap = fonts.cid.getmap(rawcidinfo)
             if cidmap then
                 rawcidinfo.usedname = cidmap.usedname
-                local nofnames, nofunicodes = 0, 0
-                local cidunicodes, cidnames = cidmap.unicodes, cidmap.names
+                local nofnames    = 0
+                local nofunicodes = 0
+                local cidunicodes = cidmap.unicodes
+                local cidnames    = cidmap.names
+                local cidtotal    = 0
+                local unique      = trace_subfonts and { }
                 for cidindex=1,#rawsubfonts do
                     local subfont   = rawsubfonts[cidindex]
                     local cidglyphs = subfont.glyphs
                     if includesubfonts then
                         metadata.subfonts[cidindex] = somecopy(subfont)
                     end
-                    -- we have delayed loading so we cannot use next
-                    for index=0,subfont.glyphcnt-1 do -- we could take the previous glyphcnt instead of 0
-                        local glyph = cidglyphs[index]
-                        if glyph then
-                            local unicode = glyph.unicode
-                            if     unicode >= 0x00E000 and unicode <= 0x00F8FF then
-                                unicode = -1
-                            elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFD then
-                                unicode = -1
-                            elseif unicode >= 0x100000 and unicode <= 0x10FFFD then
-                                unicode = -1
-                            end
-                            local name = glyph.name or cidnames[index]
-                            if not unicode or unicode == -1 then -- or unicode >= criterium then
-                                unicode = cidunicodes[index]
-                            end
-                            if unicode and descriptions[unicode] then
-                                if trace_private then
-                                    report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+                    local cidcnt, cidmin, cidmax
+                    if tableversion > 0.3 then
+                        -- we have delayed loading so we cannot use next
+                        cidcnt = subfont.glyphcnt
+                        cidmin = subfont.glyphmin
+                        cidmax = subfont.glyphmax
+                    else
+                        cidcnt = subfont.glyphcnt
+                        cidmin = 0
+                        cidmax = cidcnt - 1
+                    end
+                    if trace_subfonts then
+                        local cidtot = cidmax - cidmin + 1
+                        cidtotal = cidtotal + cidtot
+                        report_otf("subfont: %i, min: %i, max: %i, cnt: %i, n: %i",cidindex,cidmin,cidmax,cidtot,cidcnt)
+                    end
+                    if cidcnt > 0 then
+                        for cidslot=cidmin,cidmax do
+                            local glyph = cidglyphs[cidslot]
+                            if glyph then
+                                local index = tableversion > 0.3 and glyph.orig_pos or cidslot
+                                if trace_subfonts then
+                                    unique[index] = true
                                 end
-                                unicode = -1
-                            end
-                            if not unicode or unicode == -1 then -- or unicode >= criterium then
-                                if not name then
-                                    name = format("u%06X.ctx",private)
+                                local unicode = glyph.unicode
+                                if     unicode >= 0x00E000 and unicode <= 0x00F8FF then
+                                    unicode = -1
+                                elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFD then
+                                    unicode = -1
+                                elseif unicode >= 0x100000 and unicode <= 0x10FFFD then
+                                    unicode = -1
                                 end
-                                unicode = private
-                                unicodes[name] = private
-                                if trace_private then
-                                    report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+                                local name = glyph.name or cidnames[index]
+                                if not unicode or unicode == -1 then -- or unicode >= criterium then
+                                    unicode = cidunicodes[index]
                                 end
-                                private = private + 1
-                                nofnames = nofnames + 1
-                            else
-                             -- if unicode > criterium then
-                             --     local taken = descriptions[unicode]
-                             --     if taken then
-                             --         private = private + 1
-                             --         descriptions[private] = taken
-                             --         unicodes[taken.name] = private
-                             --         indices[taken.index] = private
-                             --         if trace_private then
-                             --             report_otf("slot %U is moved to %U due to private in font",unicode)
-                             --         end
-                             --     end
-                             -- end
-                                if not name then
-                                    name = format("u%06X.ctx",unicode)
+                                if unicode and descriptions[unicode] then
+                                    if trace_private then
+                                        report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+                                    end
+                                    unicode = -1
                                 end
-                                unicodes[name] = unicode
-                                nofunicodes = nofunicodes + 1
+                                if not unicode or unicode == -1 then -- or unicode >= criterium then
+                                    if not name then
+                                        name = format("u%06X.ctx",private)
+                                    end
+                                    unicode = private
+                                    unicodes[name] = private
+                                    if trace_private then
+                                        report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+                                    end
+                                    private = private + 1
+                                    nofnames = nofnames + 1
+                                else
+                                 -- if unicode > criterium then
+                                 --     local taken = descriptions[unicode]
+                                 --     if taken then
+                                 --         private = private + 1
+                                 --         descriptions[private] = taken
+                                 --         unicodes[taken.name] = private
+                                 --         indices[taken.index] = private
+                                 --         if trace_private then
+                                 --             report_otf("slot %U is moved to %U due to private in font",unicode)
+                                 --         end
+                                 --     end
+                                 -- end
+                                    if not name then
+                                        name = format("u%06X.ctx",unicode)
+                                    end
+                                    unicodes[name] = unicode
+                                    nofunicodes = nofunicodes + 1
+                                end
+                                indices[index] = unicode -- each index is unique (at least now)
+                                local description = {
+                                 -- width       = glyph.width,
+                                    boundingbox = glyph.boundingbox,
+                                 -- name        = glyph.name or name or "unknown", -- uniXXXX
+                                    name        = name or "unknown", -- uniXXXX
+                                    cidindex    = cidindex,
+                                    index       = cidslot,
+                                    glyph       = glyph,
+                                }
+                                descriptions[unicode] = description
                             end
-                            indices[index] = unicode -- each index is unique (at least now)
-                            local description = {
-                             -- width       = glyph.width,
-                                boundingbox = glyph.boundingbox,
-                                name        = glyph.name or name or "unknown", -- uniXXXX
-                                cidindex    = cidindex,
-                                index       = index,
-                                glyph       = glyph,
-                            }
-                            descriptions[unicode] = description
-                        else
-                         -- report_otf("potential problem: glyph %U is used but empty",index)
                         end
+                    else
+                        report_otf("potential problem: no glyphs found in subfont %i",cidindex)
                     end
                 end
+                if trace_subfonts then
+                    report_otf("nofglyphs: %i, unique: %i",cidtotal,table.count(unique))
+                end
                 if trace_loading then
                     report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
                 end
@@ -809,87 +840,95 @@ actions["prepare glyphs"] = function(data,filename,raw)
 
     else
 
-        for index=0,raw.glyphcnt-1 do -- not raw.glyphmax-1 (as that will crash)
-            local glyph = rawglyphs[index]
-            if glyph then
-                local unicode = glyph.unicode
-                local name    = glyph.name
-                if not unicode or unicode == -1 then -- or unicode >= criterium then
-                    unicode = private
-                    unicodes[name] = private
-                    if trace_private then
-                        report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
-                    end
-                    private = private + 1
-                else
-                    -- We have a font that uses and exposes the private area. As this is rather unreliable it's
-                    -- advised no to trust slots here (better use glyphnames). Anyway, we need a double check:
-                    -- we need to move already moved entries and we also need to bump the next private to after
-                    -- the (currently) last slot. This could leave us with a hole but we have holes anyway.
-                    if unicode > criterium then
-                        -- \definedfont[file:HANBatang-LVT.ttf] \fontchar{uF0135} \char"F0135
-                        local taken = descriptions[unicode]
-                        if taken then
-                            if unicode >= private then
-                                private = unicode + 1 -- restart private (so we can have mixed now)
+        local cnt = raw.glyphcnt or 0
+        local min = tableversion > 0.3 and raw.glyphmin or 0
+        local max = tableversion > 0.3 and raw.glyphmax or (raw.glyphcnt - 1)
+        if cnt > 0 then
+--             for index=0,cnt-1 do
+            for index=min,max do
+                local glyph = rawglyphs[index]
+                if glyph then
+                    local unicode = glyph.unicode
+                    local name    = glyph.name
+                    if not unicode or unicode == -1 then -- or unicode >= criterium then
+                        unicode = private
+                        unicodes[name] = private
+                        if trace_private then
+                            report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+                        end
+                        private = private + 1
+                    else
+                        -- We have a font that uses and exposes the private area. As this is rather unreliable it's
+                        -- advised no to trust slots here (better use glyphnames). Anyway, we need a double check:
+                        -- we need to move already moved entries and we also need to bump the next private to after
+                        -- the (currently) last slot. This could leave us with a hole but we have holes anyway.
+                        if unicode > criterium then
+                            -- \definedfont[file:HANBatang-LVT.ttf] \fontchar{uF0135} \char"F0135
+                            local taken = descriptions[unicode]
+                            if taken then
+                                if unicode >= private then
+                                    private = unicode + 1 -- restart private (so we can have mixed now)
+                                else
+                                    private = private + 1 -- move on
+                                end
+                                descriptions[private] = taken
+                                unicodes[taken.name] = private
+                                indices[taken.index] = private
+                                if trace_private then
+                                    report_otf("slot %U is moved to %U due to private in font",unicode)
+                                end
                             else
-                                private = private + 1 -- move on
-                            end
-                            descriptions[private] = taken
-                            unicodes[taken.name] = private
-                            indices[taken.index] = private
-                            if trace_private then
-                                report_otf("slot %U is moved to %U due to private in font",unicode)
-                            end
-                        else
-                            if unicode >= private then
-                                private = unicode + 1 -- restart (so we can have mixed now)
+                                if unicode >= private then
+                                    private = unicode + 1 -- restart (so we can have mixed now)
+                                end
                             end
                         end
+                        unicodes[name] = unicode
                     end
-                    unicodes[name] = unicode
-                end
-                indices[index] = unicode
-             -- if not name then
-             --     name = format("u%06X",unicode) -- u%06X.ctx
-             -- end
-                descriptions[unicode] = {
-                 -- width       = glyph.width,
-                    boundingbox = glyph.boundingbox,
-                    name        = name,
-                    index       = index,
-                    glyph       = glyph,
-                }
-                local altuni = glyph.altuni
-                if altuni then
-                 -- local d
-                    for i=1,#altuni do
-                        local a = altuni[i]
-                        local u = a.unicode
-                        local v = a.variant
-                        if v then
-                            -- tricky: no addition to d? needs checking but in practice such dups are either very simple
-                            -- shapes or e.g cjk with not that many features
-                            local vv = variants[v]
-                            if vv then
-                                vv[u] = unicode
-                            else -- xits-math has some:
-                                vv = { [u] = unicode }
-                                variants[v] = vv
+                    indices[index] = unicode
+                 -- if not name then
+                 --     name = format("u%06X",unicode) -- u%06X.ctx
+                 -- end
+                    descriptions[unicode] = {
+                     -- width       = glyph.width,
+                        boundingbox = glyph.boundingbox,
+                        name        = name,
+                        index       = index,
+                        glyph       = glyph,
+                    }
+                    local altuni = glyph.altuni
+                    if altuni then
+                     -- local d
+                        for i=1,#altuni do
+                            local a = altuni[i]
+                            local u = a.unicode
+                            local v = a.variant
+                            if v then
+                                -- tricky: no addition to d? needs checking but in practice such dups are either very simple
+                                -- shapes or e.g cjk with not that many features
+                                local vv = variants[v]
+                                if vv then
+                                    vv[u] = unicode
+                                else -- xits-math has some:
+                                    vv = { [u] = unicode }
+                                    variants[v] = vv
+                                end
+                         -- elseif d then
+                         --     d[#d+1] = u
+                         -- else
+                         --     d = { u }
                             end
-                     -- elseif d then
-                     --     d[#d+1] = u
-                     -- else
-                     --     d = { u }
                         end
+                     -- if d then
+                     --     duplicates[unicode] = d -- is this needed ?
+                     -- end
                     end
-                 -- if d then
-                 --     duplicates[unicode] = d -- is this needed ?
-                 -- end
+                else
+                    report_otf("potential problem: glyph %U is used but empty",index)
                 end
-            else
-                report_otf("potential problem: glyph %U is used but empty",index)
             end
+        else
+            report_otf("potential problem: no glyphs found")
         end
 
     end
@@ -974,8 +1013,8 @@ actions["check encoding"] = function(data,filename,raw)
     end
 
     if mapdata then
-        mapdata.map     = { } -- clear some memory
-        mapdata.backmap = { } -- clear some memory
+        mapdata.map     = { } -- clear some memory (virtual and created each time anyway)
+        mapdata.backmap = { } -- clear some memory (virtual and created each time anyway)
     end
 end
 
@@ -991,7 +1030,6 @@ actions["add duplicates"] = function(data,filename,raw)
     local unicodes     = resources.unicodes -- name to unicode
     local indices      = resources.indices  -- index to unicodes
     local duplicates   = resources.duplicates
-
     for unicode, d in next, duplicates do
         local nofduplicates = #d
         if nofduplicates > 4 then
diff --git a/tex/context/base/lpdf-epd.lua b/tex/context/base/lpdf-epd.lua
index 1dc20bc26..d6a0f00bc 100644
--- a/tex/context/base/lpdf-epd.lua
+++ b/tex/context/base/lpdf-epd.lua
@@ -538,7 +538,7 @@ function lpdf_epdf.load(filename)
             --
             local Catalog          = some_dictionary(__xref__:getCatalog():getDict(),document)
             local Info             = some_dictionary(__xref__:getDocInfo():getDict(),document)
-			--
+            --
             document.Catalog       = Catalog
             document.Info          = Info
             -- a few handy helper tables
diff --git a/tex/context/base/lxml-tab.lua b/tex/context/base/lxml-tab.lua
index 47e2cac61..510ba1bd4 100644
--- a/tex/context/base/lxml-tab.lua
+++ b/tex/context/base/lxml-tab.lua
@@ -264,8 +264,17 @@ end
 --     end
 -- end
 
+local spaceonly = lpegpatterns.whitespace^0 * P(-1)
+
 local function add_text(text)
     local n = #dt
+--
+-- will be an option: dataonly
+--
+-- if #text == 0 or lpegmatch(spaceonly,text) then
+--     return
+-- end
+--
     if cleanup and #text > 0 then
         if n > 0 then
             local s = dt[n]
diff --git a/tex/context/base/math-fen.mkiv b/tex/context/base/math-fen.mkiv
index b2f64890c..9570eac83 100644
--- a/tex/context/base/math-fen.mkiv
+++ b/tex/context/base/math-fen.mkiv
@@ -303,6 +303,10 @@
 % \installmathfencepair { \Lbrace          } \Rbrace
 % \installmathfencepair } \Rbracemirrored  { \Lbracemirrored
 
+\appendtoks
+    \ignorediscretionaries % so $\mtext{a|b}$ works, this is ok because it's an \hbox
+\to \everymathematics
+
 % todo paren parent
 
 \let\lbrack\lbracket
diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv
index 79c9a6204..9627b153f 100644
--- a/tex/context/base/math-ini.mkiv
+++ b/tex/context/base/math-ini.mkiv
@@ -842,13 +842,6 @@
 
 % \activatemathcharacter\primeasciicode
 
-% not needed:
-%
-% \activatemathcharacter\barasciicode
-% \appendtoks
-%     \let |\letterbar
-% \to \everymathematics
-
 % not used:
 %
 % \mathcode\spaceasciicode\activemathcharcode
@@ -2257,6 +2250,13 @@
    \math_inline_openup_stop
    \endgroup}
 
+% Also handy, especially for units:
+%
+% 0x002B=plus 0x2212=minus 0x2013=endash
+
+\unexpanded\def\mathplus {+}
+\unexpanded\def\mathminus{\ifmmode –\else\iffontchar\font`−−\else –\fi\fi}
+
 \protect \endinput
 
 % % not used (yet)
diff --git a/tex/context/base/mult-ini.lua b/tex/context/base/mult-ini.lua
index bd3b1d38b..c7ba52b3b 100644
--- a/tex/context/base/mult-ini.lua
+++ b/tex/context/base/mult-ini.lua
@@ -295,6 +295,10 @@ function interfaces.writestatus(category,message)
     reporters[category](message) -- could also be a setmetatablecall
 end
 
+function interfaces.message(str)
+    texio.write(str) -- overloaded
+end
+
 implement { name = "registernamespace",    actions = interfaces.registernamespace, arguments = { "integer", "string" } }
 implement { name = "setinterfaceconstant", actions = interfaces.setconstant,       arguments = { "string", "string" } }
 implement { name = "setinterfacevariable", actions = interfaces.setvariable,       arguments = { "string", "string" } }
@@ -322,6 +326,13 @@ implement {
     arguments = { "string", "string" },
 }
 
+implement {
+    name      = "message",
+    overload  = true,
+    actions   = interfaces.message,
+    arguments = "string",
+}
+
 local function showassignerror(namespace,key,line)
     local ns, instance = match(namespace,"^(%d+)[^%a]+(%a*)")
     if ns then
diff --git a/tex/context/base/mult-ini.mkiv b/tex/context/base/mult-ini.mkiv
index 1dd5a696a..a517aa3e9 100644
--- a/tex/context/base/mult-ini.mkiv
+++ b/tex/context/base/mult-ini.mkiv
@@ -385,6 +385,7 @@
 \unexpanded\def\doifelsemessage  #1#2{\clf_doifelsemessage{#1}{#2}}
 \unexpanded\def\showmessage    #1#2#3{\clf_showmessage{#1}{#2}{#3}}
 \unexpanded\def\writestatus      #1#2{\clf_writestatus{#1}{#2}}
+\unexpanded\def\message              {\clf_message}
 
 \let\doifmessageelse\doifelsemessage
 
diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua
index 9a05e59d9..5396ec723 100644
--- a/tex/context/base/mult-low.lua
+++ b/tex/context/base/mult-low.lua
@@ -266,6 +266,7 @@ return {
         "singleexpandafter", "doubleexpandafter", "tripleexpandafter",
         --
         "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces",
+        "removepunctuation",
         --
         "wait", "writestatus", "define", "defineexpandable", "redefine",
         --
diff --git a/tex/context/base/mult-prm.lua b/tex/context/base/mult-prm.lua
index 3b4d84356..9d6fc7810 100644
--- a/tex/context/base/mult-prm.lua
+++ b/tex/context/base/mult-prm.lua
@@ -254,6 +254,7 @@ return {
   "suppresslongerror",
   "suppressoutererror",
   "suppressmathparerror",
+  "matheqnogapstep",
   "synctex",
  },
  ["omega"]={
diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv
index 5f72a1113..0fecf792c 100644
--- a/tex/context/base/pack-rul.mkiv
+++ b/tex/context/base/pack-rul.mkiv
@@ -649,7 +649,7 @@
 %D
 %D We predefine two already familiar backgrounds:
 
-\letvalue{\??overlaybuiltin\v!screen    }\pack_framed_background_box_gray
+%letvalue{\??overlaybuiltin\v!screen    }\pack_framed_background_box_gray
 \letvalue{\??overlaybuiltin\v!color     }\pack_framed_background_box_color
 \letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox]
 
diff --git a/tex/context/base/page-mrk.mkiv b/tex/context/base/page-mrk.mkiv
index 6d0a5af94..0823464fe 100644
--- a/tex/context/base/page-mrk.mkiv
+++ b/tex/context/base/page-mrk.mkiv
@@ -102,6 +102,7 @@
 
 \def\page_marks_add_page_indeed#1%
   {\setbox#1\hbox\bgroup
+     \resetvisualizers
      \let\objectoffset\pagecutmarkmargin
     %\infofont
      \scratchwidth \wd#1%
@@ -115,6 +116,7 @@
 
 \def\page_marks_add_more_indeed#1%
   {\setbox#1\hbox\bgroup
+     \resetvisualizers
      \let\objectoffset\pagecutmarkmargin
      \infofont
      \scratchwidth \wd#1% these can move out
diff --git a/tex/context/base/phys-dim.lua b/tex/context/base/phys-dim.lua
index 7430b62d7..71c9b0bd4 100644
--- a/tex/context/base/phys-dim.lua
+++ b/tex/context/base/phys-dim.lua
@@ -43,6 +43,7 @@ local rawset, next = rawset, next
 local V, P, S, R, C, Cc, Cs, matchlpeg = lpeg.V, lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.match
 local format, lower = string.format, string.lower
 local appendlpeg = lpeg.append
+local utfchartabletopattern = lpeg.utfchartabletopattern
 local mergetable, mergedtable, keys, loweredkeys = table.merge, table.merged, table.keys, table.loweredkeys
 local setmetatablenewindex = table.setmetatablenewindex
 local utfchar = utf.char
@@ -663,11 +664,11 @@ labels.suffixes = allocate {
     square     = { labels = { en = [[2]]  } },
     cubic      = { labels = { en = [[3]]  } },
     quadratic  = { labels = { en = [[4]]  } },
-    inverse    = { labels = { en = [[-1]] } },
-    ilinear    = { labels = { en = [[-1]] } },
-    isquare    = { labels = { en = [[-2]] } },
-    icubic     = { labels = { en = [[-3]] } },
-    iquadratic = { labels = { en = [[-4]]  } },
+    inverse    = { labels = { en = [[\mathminus1]] } },
+    ilinear    = { labels = { en = [[\mathminus1]] } },
+    isquare    = { labels = { en = [[\mathminus2]] } },
+    icubic     = { labels = { en = [[\mathminus3]] } },
+    iquadratic = { labels = { en = [[\mathminus4]] } },
 }
 
 local function dimpus(p,u,s)
@@ -774,6 +775,20 @@ local function update_parsers() -- todo: don't remap utf sequences
     local p_short_operator = appendlpeg(short_operators)
     local p_short_suffix   = appendlpeg(short_suffixes)
 
+    -- more efficient but needs testing
+
+--     local p_long_prefix    = utfchartabletopattern(all_long_prefixes)  / all_long_prefixes
+--     local p_long_unit      = utfchartabletopattern(all_long_units)     / all_long_units
+--     local p_long_operator  = utfchartabletopattern(all_long_operators) / all_long_operators
+--     local p_long_suffix    = utfchartabletopattern(all_long_suffixes)  / all_long_suffixes
+--     local p_symbol         = utfchartabletopattern(all_symbol_units)   / all_symbol_units
+--     local p_packaged       = utfchartabletopattern(all_packaged_units) / all_packaged_units
+
+--     local p_short_prefix   = utfchartabletopattern(short_prefixes)     / short_prefixes
+--     local p_short_unit     = utfchartabletopattern(short_units)        / short_units
+--     local p_short_operator = utfchartabletopattern(short_operators)    / short_operators
+--     local p_short_suffix   = utfchartabletopattern(short_suffixes)     / short_suffixes
+
     -- we can can cleanup some space issues here (todo)
 
     local unitparser = P { "unit",
diff --git a/tex/context/base/phys-dim.mkiv b/tex/context/base/phys-dim.mkiv
index 232edc2fc..b1bcb40c9 100644
--- a/tex/context/base/phys-dim.mkiv
+++ b/tex/context/base/phys-dim.mkiv
@@ -156,7 +156,7 @@
   {\ifmmode
      \expandafter\normalsuperscript
    \else
-     \expandafter\high
+     \expandafter\unitshigh
    \fi}
 
 % we could use a symbolset but how many symbols are there ?
@@ -170,17 +170,21 @@
 % \definesymbol[units][times][\cdots]
 % \definesymbol[units][times][\ifmmode\cdot\else\kern.2\emwidth\cdot\kern.2\emwidth\fi]
 
-\def\digitstimessymbol{\times}
-% \def\digitstimessymbol{\cdot}
-% \def\digitstimessymbol{\ifmmode\cdot\else\kern.2\emwidth\cdot\kern.2\emwidth\fi}
+\unexpanded\def\digitstextbinop#1% assumes preceding
+  {\fourperemspace\nobreak\times\fourperemspace}
+
+%def\digitstimessymbol{\ifmmode\cdot\else\digitstextbinop\cdot\fi}
+\def\digitstimessymbol{\ifmmode\times\else\digitstextbinop\times\fi}
 
 \unexpanded\def\digitszeropadding   {\hphantom{0}}
 \unexpanded\def\digitsnegative      {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}}
 \unexpanded\def\digitspositive      {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}}
 \unexpanded\def\digitsnegative      {\phys_digits_normalized{0}{\mathematics{\negative}}}
 \unexpanded\def\digitspositive      {\phys_digits_normalized{0}{\mathematics{\positive}}}
-\unexpanded\def\digitsminus         {\phys_digits_normalized{0}{\mathematics{-}}}
-\unexpanded\def\digitsplus          {\phys_digits_normalized{0}{\mathematics{+}}}
+%unexpanded\def\digitsminus         {\phys_digits_normalized{0}{\mathematics{-}}}
+%unexpanded\def\digitsplus          {\phys_digits_normalized{0}{\mathematics{+}}}
+\unexpanded\def\digitsminus         {\phys_digits_normalized{0}{\mathminus}}
+\unexpanded\def\digitsplus          {\phys_digits_normalized{0}{\mathplus }}
 \unexpanded\def\digitsspace         {\hphantom{0}}
 \unexpanded\def\digitsseparatorspace{\hphantom{.}}
 \unexpanded\def\digitssignspace     {\hphantom{\digitsminus}}
@@ -370,6 +374,9 @@
   %\c!space=...,                 % (maybe) small medium big
   ]
 
+\definehigh[unitshigh][\c!style=\txx]
+\definelow [unitslow] [\c!style=\txx]
+
 \let\setupunits\setupunit
 
 \newconstant   \c_phys_units_mode   % 0=text 1=math 2=textinmath 3=mathintext
@@ -615,22 +622,22 @@
 
 \def\unitsraise
   {\ifcase\c_phys_units_mode
-     \expandafter\high
+     \expandafter\unitshigh
    \or
      \expandafter\normalsuperscript
    \or
-     \expandafter\high
+     \expandafter\unitshigh
    \or
      \expandafter\normalsuperscript
    \fi}
 
 \def\unitslower
   {\ifcase\c_phys_units_mode
-     \expandafter\low
+     \expandafter\unitslow
    \or
      \expandafter\normalsubscript
    \or
-     \expandafter\low
+     \expandafter\unitslow
    \or
      \expandafter\normalsubscript
    \fi}
diff --git a/tex/context/base/publ-dat.lua b/tex/context/base/publ-dat.lua
index 36ba15000..e9cf22604 100644
--- a/tex/context/base/publ-dat.lua
+++ b/tex/context/base/publ-dat.lua
@@ -383,6 +383,7 @@ function publications.new(name)
         userdata   = { },
         used       = { },
         commands   = { }, -- for statistical purposes
+        citestate  = { },
         status     = {
             resources = false,
             userdata  = false,
diff --git a/tex/context/base/publ-imp-apa.mkvi b/tex/context/base/publ-imp-apa.mkvi
index cf35a4b80..85e0ebd5f 100644
--- a/tex/context/base/publ-imp-apa.mkvi
+++ b/tex/context/base/publ-imp-apa.mkvi
@@ -33,7 +33,7 @@
   [apa]
   [\c!default=default,
    \c!specification=apa,
-   \c!otherstext={\space\btxlabeltext{apa:others}},
+   \c!otherstext={\btxspace\btxlabeltext{apa:others}},
    %c!journalconversion=\v!normal,
    \c!monthconversion=\v!month]
 
@@ -57,14 +57,14 @@
 \definebtx
   [apa:\s!list]
   [apa]
-  [\c!otherstext={,\nobreakspace\textellipsis\space},
+  [\c!otherstext={\btxcomma\btxnobreakspace\textellipsis\space},
    \c!etallimit=7,
    \c!etaldisplay=6,
    \c!etaloption=last,
    \c!authorconversion=invertedshort,
-   \c!separator:names:2={,\space}, % aka namesep - in this namespace
-   \c!separator:names:3={,\nobreakspace\textampersand\space}, % comma separated list
-   \c!separator:names:4={\nobreakspace\textampersand\space}] % last of two, no comma!
+   \c!separator:names:2={\btxcomma}, % aka namesep - in this namespace
+   \c!separator:names:3={\btxcomma\btxnobreakspace\textampersand\space}, % comma separated list
+   \c!separator:names:4={\btxnobreakspace\textampersand\space}] % last of two, no comma!
 
 % First, we define a namespace for a few special fields
 
@@ -91,9 +91,9 @@
 \definebtx
   [apa:\s!list:\s!page]
   [apa:\s!list]
-  [\c!separator:2={,\space},
-   \c!separator:3={,\space\btxlabeltext{apa:and}\space},
-   \c!separator:4={\space\btxlabeltext{apa:and}\space},
+  [\c!separator:2={\btxcomma},
+   \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space},
+   \c!separator:4={\btxspace\btxlabeltext{apa:and}\space},
    \c!left={\btxleftparenthesis},
    \c!right={\btxrightparenthesis},
    \c!command={\wordright}]
@@ -101,22 +101,28 @@
 \definebtx
   [apa:\s!list:numbering]
   [apa:\s!list]
+  [\c!right={\btxspace}]
+
+\definebtx
+  [apa:\s!list:numbering:default]
+  [apa:\s!list:numbering]
 
 \definebtx
   [apa:\s!list:numbering:num]
   [apa:\s!list:numbering]
-  [\c!stopper={.},
-   \c!right={\space}]
+  [\c!stopper={.}]
 
 \definebtx
   [apa:\s!list:numbering:short]
-  [apa:\s!list:numbering:num]
-  [\c!stopper=]
+  [apa:\s!list:numbering]
 
 \definebtx
   [apa:\s!list:numbering:tag]
-  [apa:\s!list:numbering:num]
-  [\c!stopper=]
+  [apa:\s!list:numbering]
+
+\definebtx
+  [apa:\s!list:numbering:index]
+  [apa:\s!list:numbering]
 
 % Next, we define a namespace for each category
 
@@ -259,15 +265,40 @@
   [apa:\s!cite]
   [apa]
   [\c!alternative=authoryear,
-   \c!otherstext={,\space\btxlabeltext{apa:others}},
+   \c!otherstext={\btxcomma\btxlabeltext{apa:others}},
    \c!etallimit=5,
    \c!etaldisplay=1, % TODO: when 2-4, show all first time, etaldisplay subsequently...
    \c!authorconversion=\v!name,
    \c!sorttype=normal,
    \c!compress=\v!yes, % note that cite sorts only work with compress=yes.
-   \c!separator:names:2={,\space},
-   \c!separator:names:3={,\space\btxlabeltext{apa:and}\space}, % not \textampersand
-   \c!separator:names:4={\space\btxlabeltext{apa:and}\space}] % not \textampersand
+   \c!separator:names:2={\btxcomma},
+   \c!separator:names:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+   \c!separator:names:4={\btxspace\btxlabeltext{apa:and}\space}] % not \textampersand
+
+\definebtx
+  [apa:\s!cite:name]
+  [apa:\s!cite]
+  [\c!authorconversion=\v!name]
+
+\definebtx
+  [apa:\s!cite:inverted]
+  [apa:\s!cite]
+  [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+  [apa:\s!cite:invertedshort]
+  [apa:\s!cite]
+  [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+  [apa:\s!cite:normalshort]
+  [apa:\s!cite]
+  [\c!authorconversion=\v!normalshort]
+
+\definebtx
+  [apa:\s!cite:normal]
+  [apa:\s!cite]
+  [\c!authorconversion=\v!normal]
 
 \definebtx
   [apa:\s!cite:author]
@@ -278,7 +309,7 @@
   [apa:\s!cite:author]
   [\c!left={(},
    \c!right={)},
-   \c!inbetween={,\space}]
+   \c!inbetween={\btxcomma}]
 
 \definebtx
   [apa:\s!cite:default]
@@ -289,7 +320,7 @@
   [apa:\s!cite:authoryear]
   [\c!left=,
    \c!right=,
-   \c!inbetween={\space}]
+   \c!inbetween={\btxspace}]
 
 \definebtx
   [apa:\s!cite:authornum]
@@ -300,7 +331,7 @@
 \definebtx
   [apa:\s!cite:author:num] % todo
   [apa:\s!cite:authornum]
-  [\c!left={\space[},
+  [\c!left={\btxspace[},
    \c!right={]}]
 
 \definebtx
@@ -311,22 +342,22 @@
   [apa:\s!cite:author:years] % todo
   [apa:\s!cite:authoryears]
   [\c!inbetween=,
-   \c!left={\space(},
+   \c!left={\btxspace(},
    \c!right={)}]
 
 \definebtx
   [apa:\s!cite:year]
   [apa:\s!cite]
-  [\c!separator:2={,\space}, % :0 and :1 - between items of a list
-   \c!separator:3={,\space\btxlabeltext{apa:and}\space}, % not \textampersand
-   \c!separator:4={\space\btxlabeltext{apa:and}\space}] % not \textampersand
+  [\c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+   \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+   \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}] % not \textampersand
 
 \definebtx
   [apa:\s!cite:title]
   [apa:\s!cite]
-  [\c!separator:2={,\space}, % :0 and :1 - between items of a list
-   \c!separator:3={,\space\btxlabeltext{apa:and}\space}, % not \textampersand
-   \c!separator:4={\space\btxlabeltext{apa:and}\space}, % not \textampersand
+  [\c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+   \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+   \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}, % not \textampersand
    \c!command={\language[\currentbtxlanguage]}, % BAH
    \c!sorttype=none,
    \c!style=\v!italic]
@@ -353,9 +384,9 @@
   [apa:\s!cite]
   [\c!left=,
    \c!right=,
-   \c!separator:2={,\space}, % :0 and :1 - between items of a list
-   \c!separator:3={,\space\btxlabeltext{apa:and}\space}, % not \textampersand
-   \c!separator:4={\space\btxlabeltext{apa:and}\space}] % not \textampersand
+   \c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+   \c!separator:3={\btxcomma\btxlabeltext{apa:and}\space}, % not \textampersand
+   \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}] % not \textampersand
 
 \definebtx
   [apa:\s!cite:pages]
@@ -399,17 +430,17 @@
   [apa:\s!cite:num]
   [\c!left={Ref.\nbsp},
    \c!right=,
-   \c!separator:2={,\space},
-   \c!separator:3={\space\btxlabeltext{apa:and}\space},
-   \c!separator:4={\space\btxlabeltext{apa:and}\space}]
+   \c!separator:2={\btxcomma},
+   \c!separator:3={\btxspace\btxlabeltext{apa:and}\space},
+   \c!separator:4={\btxspace\btxlabeltext{apa:and}\space}]
 
 \definebtx
   [apa:\s!cite:entry]
   [apa:\s!cite]
   [\c!left=,
    \c!right=,
-   \c!inbetween={\space},
-   \c!separator:2={;\space},
+   \c!inbetween={\btxspace},
+   \c!separator:2={\btxsemicolon},
    \c!separator:3=\btxparameter{\c!separator:2},
    \c!separator:4=\btxparameter{\c!separator:2}]
 
@@ -772,7 +803,13 @@
         \btxflush{year}
         \btxflushsuffix
     } {
-        \btxlabeltext{apa:nd}
+        \fastsetup{btx:apa:nd}
+        % Hans: the following won't work but should.
+        \btxdoif {suffix} {
+            \btxspace
+            \btxflushsuffix
+            % Hans: similarly, why can't \btxflush{suffix} be made to work?
+        }
     }
 \stoptexdefinition
 
diff --git a/tex/context/base/publ-imp-aps.mkvi b/tex/context/base/publ-imp-aps.mkvi
index 9772fbb87..71b0dc185 100644
--- a/tex/context/base/publ-imp-aps.mkvi
+++ b/tex/context/base/publ-imp-aps.mkvi
@@ -33,15 +33,15 @@
   [aps]
   [\c!default=default,
    \c!specification=aps,
-   \c!otherstext={\space{\it\btxlabeltext{aps:others}}},
+   \c!otherstext={\btxspace{\it\btxlabeltext{aps:others}}},
    \c!etallimit=10,
    \c!etaldisplay=\btxparameter\c!etallimit,
    %c!journalconversion=\v!normal,
    \c!monthconversion=\v!month,
    \c!title=\v!yes,
-   \c!separator:names:2={,\space},
-   \c!separator:names:3={,\space\btxlabeltext{aps:and}\space}, % not \textampersand
-   \c!separator:names:4= {\space\btxlabeltext{aps:and}\space}] % not \textampersand
+   \c!separator:names:2={\btxcomma},
+   \c!separator:names:3={\btxcomma\btxlabeltext{aps:and}\space},
+   \c!separator:names:4={\btxspace\btxlabeltext{aps:and}\space}]
 
 % First, define and set list and rendering parameters
 
@@ -83,9 +83,9 @@
 \definebtx
   [aps:\s!list:\s!page]
   [aps:\s!list]
-  [\c!separator:2={,\space},
-   \c!separator:3={,\space\btxlabeltext{aps:and}\space},
-   \c!separator:4={\space\btxlabeltext{aps:and}\space},
+  [\c!separator:2={\btxcomma},
+   \c!separator:3={\btxcomma\btxlabeltext{aps:and}\space},
+   \c!separator:4={\btxspace\btxlabeltext{aps:and}\space},
    \c!left={\btxleftparenthesis},
    \c!right={\btxrightparenthesis},
    \c!command={\wordright}]
@@ -93,20 +93,28 @@
 \definebtx
   [aps:\s!list:numbering]
   [aps:\s!list]
+  [left={[},
+   right={]}]
+
+\definebtx
+  [aps:\s!list:numbering:default]
+  [aps:\s!list:numbering]
 
 \definebtx
   [aps:\s!list:numbering:num]
   [aps:\s!list:numbering]
-  [left={[},
-   right={]}]
 
 \definebtx
   [aps:\s!list:numbering:short]
-  [aps:\s!list:numbering:num]
+  [aps:\s!list:numbering]
 
 \definebtx
   [aps:\s!list:numbering:tag]
-  [aps:\s!list:numbering:num]
+  [aps:\s!list:numbering]
+
+\definebtx
+  [aps:\s!list:numbering:index]
+  [aps:\s!list:numbering]
 
 %D In order to be able to get journals expanded (or normalized or abbreviated) you need
 %D to load a list:
@@ -239,10 +247,36 @@
 \definebtx
   [aps:\s!cite]
   [aps]
-  [\c!authorconversion=\v!name,
+  [\c!alternative=num,
+   \c!authorconversion=\v!name,
    \c!compress=\v!yes,
    \c!sorttype=normal]
 
+\definebtx
+  [aps:\s!cite:name]
+  [aps:\s!cite]
+  [\c!authorconversion=\v!name]
+
+\definebtx
+  [aps:\s!cite:inverted]
+  [aps:\s!cite]
+  [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+  [aps:\s!cite:invertedshort]
+  [aps:\s!cite]
+  [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+  [aps:\s!cite:normalshort]
+  [aps:\s!cite]
+  [\c!authorconversion=\v!normalshort]
+
+\definebtx
+  [aps:\s!cite:normal]
+  [aps:\s!cite]
+  [\c!authorconversion=\v!normal]
+
 \definebtx
   [aps:\s!cite:author]
   [aps:\s!cite]
@@ -252,14 +286,14 @@
   [aps:\s!cite:author]
   [\c!left={(},
    \c!right={)},
-   \c!inbetween={,\space}]
+   \c!inbetween={\btxcomma}]
 
 \definebtx
   [aps:\s!cite:authoryears]
   [aps:\s!cite:authoryear]
   [\c!left=,
    \c!right=,
-   \c!inbetween={\space}]
+   \c!inbetween={\btxspace}]
 
 \definebtx
   [aps:\s!cite:authornum]
@@ -270,7 +304,7 @@
 \definebtx
   [aps:\s!cite:author:num] % todo
   [aps:\s!cite:authornum]
-  [\c!left={\space[},
+  [\c!left={\btxspace[},
    \c!right={]}]
 
 \definebtx
@@ -283,7 +317,7 @@
   [aps:\s!cite:author:years] % todo
   [aps:\s!cite:authoryears]
   [\c!inbetween=,
-   \c!left={\space(},
+   \c!left={\btxspace(},
    \c!right={)}]
 
 \definebtx
@@ -318,9 +352,9 @@
   [aps:\s!cite]
   [\c!left=,
    \c!right=,
-   \c!separator:2={,\space}, % :0 and :1 - between items of a list
-   \c!separator:3={,\space\btxlabeltext{aps:and}\space}, % not \textampersand
-   \c!separator:4= {\space\btxlabeltext{aps:and}\space}] % not \textampersand
+   \c!separator:2={\btxcomma}, % :0 and :1 - between items of a list
+   \c!separator:3={\btxcomma\btxlabeltext{aps:and}\space},
+   \c!separator:4={\btxspace\btxlabeltext{aps:and}\space}]
 
 \definebtx
   [aps:\s!cite:pages]
@@ -373,17 +407,17 @@
   [aps:\s!cite:num]
   [\c!left={Ref.\nbsp},
    \c!command=,
-   \c!separator:2={,\space},
-   \c!separator:3={\space\btxlabeltext{aps:and}\space},
-   \c!separator:4={\space\btxlabeltext{aps:and}\space}]
+   \c!separator:2={\btxcomma},
+   \c!separator:3={\btxspace\btxlabeltext{aps:and}\space},
+   \c!separator:4={\btxspace\btxlabeltext{aps:and}\space}]
 
 \definebtx
   [aps:\s!cite:entry]
   [aps:\s!cite]
   [\c!left=,
    \c!right=,
-   \c!inbetween={\space},
-   \c!separator:2={;\space},
+   \c!inbetween={\btxspace},
+   \c!separator:2={\btxsemicolon},
    \c!separator:3=\btxparameter{\c!separator:2},
    \c!separator:4=\btxparameter{\c!separator:2}]
 
@@ -808,7 +842,6 @@
     \else
         #text
     \fi
-
 \stoptexdefinition
 
 % Then setups, by category
diff --git a/tex/context/base/publ-imp-default.mkvi b/tex/context/base/publ-imp-default.mkvi
index 73520c7ff..6a15712ad 100644
--- a/tex/context/base/publ-imp-default.mkvi
+++ b/tex/context/base/publ-imp-default.mkvi
@@ -26,12 +26,12 @@
 \definebtx
   [\s!default]
   [\c!default=, % we do not want to fall|-|back on ourself.
-   \c!otherstext={\space\btxlabeltext{default:others}},
+   \c!otherstext={\btxspace\btxlabeltext{default:others}},
    %c!journalconversion=\v!normal,
    \c!monthconversion=\v!number,
-   \c!separator:names:2={,\space},
-   \c!separator:names:3={\space\btxlabeltext{default:and}\space},
-   \c!separator:names:4={\space\btxlabeltext{default:and}\space}]
+   \c!separator:names:2={\btxcomma},
+   \c!separator:names:3={\btxspace\btxlabeltext{default:and}\space},
+   \c!separator:names:4={\btxspace\btxlabeltext{default:and}\space}]
 
 \definebtx
   [\s!default:\s!list]
@@ -46,14 +46,39 @@
    \c!sorttype=normal,
    \c!authorconversion=\v!name]
 
+\definebtx
+  [\s!default:\s!cite:name]
+  [\s!default:\s!cite]
+  [\c!authorconversion=\v!name]
+
+\definebtx
+  [\s!default:\s!cite:inverted]
+  [\s!default:\s!cite]
+  [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+  [\s!default:\s!cite:invertedshort]
+  [\s!default:\s!cite]
+  [\c!authorconversion=\v!invertedshort]
+
+\definebtx
+  [\s!default:\s!cite:normalshort]
+  [\s!default:\s!cite]
+  [\c!authorconversion=\v!normalshort]
+
+\definebtx
+  [\s!default:\s!cite:normal]
+  [\s!default:\s!cite]
+  [\c!authorconversion=\v!normal]
+
 % List variants, some having specific settings:
 
 \definebtx
   [\s!default:\s!list:\s!page]
   [\s!default:\s!list]
-  [\c!separator:2={,\space},
-   \c!separator:3={,\space\btxlabeltext{default:and}\space},
-   \c!separator:4={\space\btxlabeltext{default:and}\space},
+  [\c!separator:2={\btxcomma},
+   \c!separator:3={\btxcomma\btxlabeltext{default:and}\space},
+   \c!separator:4={\btxspace\btxlabeltext{default:and}\space},
    \c!left={\btxleftparenthesis},
    \c!right={\btxrightparenthesis}]
 
@@ -61,6 +86,10 @@
   [\s!default:\s!list:numbering]
   [\s!default:\s!list]
 
+\definebtx
+  [\s!default:\s!list:numbering:default]
+  [\s!default:\s!list:numbering]
+
 \definebtx
   [\s!default:\s!list:numbering:num]
   [\s!default:\s!list:numbering]
@@ -73,6 +102,10 @@
   [\s!default:\s!list:numbering:tag]
   [\s!default:\s!list:numbering:num]
 
+\definebtx
+  [\s!default:\s!list:numbering:index]
+  [\s!default:\s!list:numbering:num]
+
 \definebtx
   [\s!default:\s!list:author]
   [\s!default:\s!list]
@@ -131,7 +164,7 @@
   [\s!default:\s!cite:author]
   [\c!left={(},
    \c!right={)},
-   \c!inbetween={,\space}]
+   \c!inbetween={\btxcomma}]
 
 \definebtx
   [\s!default:\s!cite:authoryears]
@@ -140,7 +173,7 @@
 \definebtx
   [\s!default:\s!cite:author:num] % todo
   [\s!default:\s!cite:authornum]
-  [\c!left={\space[},
+  [\c!left={\btxleftbracket},
    \c!right={]}]
 
 \definebtx
@@ -153,7 +186,7 @@
   [\s!default:\s!cite:author:years] % todo
   [\s!default:\s!cite:authoryears]
   [\c!inbetween=,
-   \c!left={\space(},
+   \c!left={\btxleftparenthesis},
    \c!right={)}]
 
 \definebtx
@@ -232,9 +265,9 @@
   [\s!default:\s!cite:num]
   [\c!left=, % in apa: {Ref.\nbsp} or so
    \c!right=,
-   \c!separator:2={,\space},
-   \c!separator:3={,\space\btxlabeltext{default:and}\space},
-   \c!separator:4= {\space\btxlabeltext{default:and}\space}]
+   \c!separator:2={\btxcomma},
+   \c!separator:3={\btxcomma\btxlabeltext{default:and}\space},
+   \c!separator:4={\btxspace\btxlabeltext{default:and}\space}]
 
 \definebtx
   [\s!default:\s!cite:entry]
diff --git a/tex/context/base/publ-imp-list.mkvi b/tex/context/base/publ-imp-list.mkvi
index d34e4bc24..23256de33 100644
--- a/tex/context/base/publ-imp-list.mkvi
+++ b/tex/context/base/publ-imp-list.mkvi
@@ -50,6 +50,16 @@
     }
 \stopsetups
 
+% Hans: can the following setups be condensed to one using some variable?
+
+\startsetups[\s!btx:\s!list:\s!numbering:default]
+    \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:default]
+        \btxusecommand[\currentbtxspecification:\s!list:\s!numbering:default] {
+            \fastsetup{\s!btx:\s!list:\s!numbering}
+        }
+    \btxstopstyleandcolor
+\stopsetups
+
 \startsetups[\s!btx:\s!list:\s!numbering:num]
     \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:num]
         \btxusecommand[\currentbtxspecification:\s!list:\s!numbering:num] {
@@ -58,10 +68,6 @@
     \btxstopstyleandcolor
 \stopsetups
 
-\startsetups[\s!btx:\s!list:\s!numbering:\v!yes]
-    \fastsetup{\s!btx:\s!list:\s!numbering:num}
-\stopsetups
-
 \startsetups[\s!btx:\s!list:\s!numbering:short]
     \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:short]
         \btxusecommand [\currentbtxspecification:\s!list:\s!numbering:short] {
@@ -79,4 +85,12 @@
     \btxstopstyleandcolor
 \stopsetups
 
+\startsetups[\s!btx:\s!list:\s!numbering:index]
+    \btxstartstyleandcolor [\currentbtxspecification:\s!list:\s!numbering:index]
+        \btxusecommand [\currentbtxspecification:\s!list:\s!numbering:index] {
+            \fastsetup{\s!btx:\s!list:\s!numbering}
+        }
+    \btxstopstyleandcolor
+\stopsetups
+
 \protect
diff --git a/tex/context/base/publ-ini.lua b/tex/context/base/publ-ini.lua
index 4f7dd4413..3791bd532 100644
--- a/tex/context/base/publ-ini.lua
+++ b/tex/context/base/publ-ini.lua
@@ -72,6 +72,9 @@ local v_yes              = variables.yes
 local v_no               = variables.no
 local v_all              = variables.all
 local v_always           = variables.always
+local v_hidden           = variables.hidden
+local v_list             = variables.list
+local v_text             = variables.text
 local v_doublesided      = variables.doublesided
 local v_default          = variables.default
 local v_dataset          = variables.dataset
@@ -163,6 +166,8 @@ local ctx_btxsetnoflistentries    = context.btxsetnoflistentries
 local ctx_btxsetcurrentlistentry  = context.btxsetcurrentlistentry
 local ctx_btxsetcurrentlistindex  = context.btxsetcurrentlistindex
 
+local trialtypesetting            = context.trialtypesetting
+
 languages.data                    = languages.data       or { }
 local data                        = languages.data
 
@@ -479,7 +484,7 @@ local findallused do
     local reported = { }
     local finder   = publications.finder
 
-    findallused = function(dataset,reference,internal)
+    findallused = function(dataset,reference,internal,forcethem)
         local current  = datasets[dataset]
         local finder   = publications.finder -- for the moment, not yet in all betas
         local find     = finder and finder(current,reference)
@@ -490,10 +495,20 @@ local findallused do
         local luadata  = current.luadata
         local details  = current.details
         local ordered  = current.ordered
-        if set then
+        if allused then
             local registered = { }
             local function register(tag)
-                local entry = allused[tag]
+                local entry = forcethem and luadata[tag]
+                if entry then
+                    if registered[tag] then
+                        return
+                    end
+                    okay[#okay+1] = entry
+                 -- todo[tag] = true
+                    registered[tag] = true
+                    return tag
+                end
+                entry = allused[tag]
                 if not entry then
                     local parent = details[tag].parent
                     if parent then
@@ -632,7 +647,15 @@ end
 
 local concatstate = publications.concatstate
 
-local tobemarked = nil
+-- hidden : mark for list, don't show in text
+-- list   : mark for list, show in text only when in list
+-- text   : not to list, show in text
+-- always : mark for list, show in text
+
+local marked_todo    = false -- keeps track or not yet flushed
+local marked_dataset = false
+local marked_list    = false -- the sequential list (we flush in order, not by unordered hash)
+local marked_method  = false
 
 local function marknocite(dataset,tag,nofcitations,setup)
     ctx_btxstartcite()
@@ -647,10 +670,10 @@ local function marknocite(dataset,tag,nofcitations,setup)
 end
 
 local function markcite(dataset,tag,flush)
-    if not tobemarked then
+    if not marked_todo then
         return 0
     end
-    local citation = tobemarked[tag]
+    local citation = marked_todo[tag]
     if not citation then
         return 0
     end
@@ -662,39 +685,35 @@ local function markcite(dataset,tag,flush)
         if flush then
             marknocite(dataset,tag,nofcitations,"nocite")
         end
-        tobemarked[tag] = nofcitations
+        marked_todo[tag] = nofcitations -- signal that it's marked
         return nofcitations
     else
         return citation
     end
 end
 
-local marked_dataset = nil
-local marked_list    = nil
-
-local function flushmarked(dataset,list,todo)
-    marked_dataset = dataset
-    marked_list    = list
-end
-
 local function btxflushmarked()
-    if marked_list and tobemarked then
+    if marked_list and marked_todo then
         for i=1,#marked_list do
             -- keep order
             local tag = marked_list[i]
-            local tbm = tobemarked[tag]
+            local tbm = marked_todo[tag]
             if tbm == true or not tbm then
                 nofcitations = nofcitations + 1
-                marknocite(marked_dataset,tag,nofcitations,tbm and "nocite" or "invalid")
+                local setup = (tbm or marked_method == v_always) and "nocite" or "invalid"
+                marknocite(marked_dataset,tag,nofcitations,setup)
                 if trace_cite then
-                    report_cite("mark, dataset: %s, tag: %s, number: %s, state: %s",marked_dataset,tag,nofcitations,tbm and "unset" or "invalid")
+                    report_cite("mark, dataset: %s, tag: %s, number: %s, setup: %s",marked_dataset,tag,nofcitations,setup)
                 end
+            else
+                -- a number signaling being marked
             end
         end
     end
-    tobemarked     = nil
-    marked_dataset = nil
-    marked_list    = nil
+    marked_todo    = false
+    marked_dataset = false
+    marked_list    = false
+    marked_method  = false
 end
 
 implement { name = "btxflushmarked", actions = btxflushmarked }
@@ -2286,14 +2305,17 @@ do
     end
 
     local function btxhandlenocite(specification)
+        if trialtypesetting() then
+            return
+        end
         local dataset   = specification.dataset or v_default
         local reference = specification.reference
         if not reference or reference == "" then
             return
         end
         --
-        local markentry = specification.markentry ~= false
-        local internal  = specification.internal or ""
+        local method   = specification.method
+        local internal = specification.internal or ""
         --
         local prefix, rest = lpegmatch(prefixsplitter,reference)
         if rest then
@@ -2309,10 +2331,14 @@ do
         --
         local found, todo, list = findallused(dataset,reference,internal)
         --
-        tobemarked = markentry and todo
-        if found and tobemarked then
-            flushmarked(dataset,list)
-            btxflushmarked() -- here (could also be done in caller)
+        if todo then
+            marked_todo    = todo
+            marked_dataset = dataset
+            marked_list    = list
+            marked_method  = method
+         -- btxflushmarked() -- here (could also be done in caller)
+        else
+            marked_todo = false
         end
     end
 
@@ -2323,7 +2349,7 @@ do
             {
                 { "dataset" },
                 { "reference" },
-                { "markentry", "boolean" },
+                { "method" },
                 { "variant" },
                 { "sorttype" },
                 { "compress" },
@@ -2342,9 +2368,9 @@ do
         actions   = btxhandlenocite,
         arguments = {
             {
-               { "dataset" },
-               { "reference" },
-               { "markentry", "boolean" },
+                { "dataset" },
+                { "reference" },
+                { "method" },
             }
         }
     }
@@ -2470,11 +2496,11 @@ do
         local getter     = specification.getter
         local setter     = specification.setter
         local compressor = specification.compressor
+        local method     = specification.method
         --
         local reference  = publications.parenttag(dataset,reference)
         --
-        local found, todo, list = findallused(dataset,reference,internal)
-        tobemarked = specification.markentry and todo
+        local found, todo, list = findallused(dataset,reference,internal,method == v_text or method == v_always) -- also when not in list
         --
         if not found or #found == 0 then
             report("no entry %a found in dataset %a",reference,dataset)
@@ -2487,23 +2513,26 @@ do
             local source  = { }
             local luadata = datasets[dataset].luadata
             for i=1,#found do
-                local entry = found[i]
--- inspect(entry)
-                local tag   = entry.userdata.btxref
-                local ldata = luadata[tag]
-                local data  = {
-                    internal  = entry.references.internal,
-                    language  = ldata.language,
-                    dataset   = dataset,
-                    tag       = tag,
-                 -- combis    = entry.userdata.btxcom,
-                 -- luadata   = ldata,
-                }
-                setter(data,dataset,tag,entry)
-                if type(data) == "table" then
-                    source[#source+1] = data
-                else
-                    report("error in cite rendering %a",setup or "?")
+                local entry      = found[i]
+                local userdata   = entry.userdata
+                local references = entry.references
+                local tag        = userdata and userdata.btxref or entry.tag -- no need for userdata
+                if tag then
+                    local ldata = luadata[tag]
+                    local data  = {
+                        internal  = references and references.internal,
+                        language  = ldata.language,
+                        dataset   = dataset,
+                        tag       = tag,
+                     -- combis    = entry.userdata.btxcom,
+                     -- luadata   = ldata,
+                    }
+                    setter(data,dataset,tag,entry)
+                    if type(data) == "table" then
+                        source[#source+1] = data
+                    else
+                        report("error in cite rendering %a",setup or "?")
+                    end
                 end
             end
 
@@ -2530,14 +2559,16 @@ do
                 if before    then local text = before   [i] ; if text and text ~= "" then ctx_btxsetbefore   (text) end end
                 if after     then local text = after    [i] ; if text and text ~= "" then ctx_btxsetafter    (text) end end
                 --
-                ctx_btxsetbacklink(currentcitation)
-                local bl = listtocite[currentcitation]
-                if bl then
-                    -- we refer to a coming list entry
-                    ctx_btxsetinternal(bl.references.internal or "")
-                else
-                    -- we refer to a previous list entry
-                    ctx_btxsetinternal(entry.internal or "")
+                if method ~= v_text then
+                    ctx_btxsetbacklink(currentcitation)
+                    local bl = listtocite[currentcitation]
+                    if bl then
+                        -- we refer to a coming list entry
+                        ctx_btxsetinternal(bl.references.internal or "")
+                    else
+                        -- we refer to a previous list entry
+                        ctx_btxsetinternal(entry.internal or "")
+                    end
                 end
                 local language = entry.language
                 if language then
@@ -2591,9 +2622,16 @@ do
                 end
             end
         end
-        if tobemarked then
-            flushmarked(dataset,list)
-            btxflushmarked() -- here (could also be done in caller)
+        if trialtypesetting() then
+            marked_todo = false
+        elseif method ~= v_text then
+            marked_todo    = todo
+            marked_dataset = dataset
+            marked_list    = list
+            marked_method  = method
+         -- btxflushmarked() -- here (could also be done in caller)
+        else
+            marked_todo = false
         end
     end
 
@@ -3202,7 +3240,16 @@ do
         ctx_btxnumberingsetup(variant or "num")
     end
 
-    listvariants[v_yes] = listvariants.num
+ -- listvariants[v_yes] = listvariants.num
+
+    function listvariants.index(dataset,block,tag,variant,listindex)
+        local index = getdetail(dataset,tag,"index")
+        ctx_btxsetfirst(index or "?")
+        if trace_detail then
+            report("expanding %a list setup %a","index",variant)
+        end
+        ctx_btxnumberingsetup(variant or "index")
+    end
 
     function listvariants.tag(dataset,block,tag,variant,listindex)
         ctx_btxsetfirst(tag)
diff --git a/tex/context/base/publ-ini.mkiv b/tex/context/base/publ-ini.mkiv
index 2d55832f9..fd9e4ad97 100644
--- a/tex/context/base/publ-ini.mkiv
+++ b/tex/context/base/publ-ini.mkiv
@@ -1203,6 +1203,13 @@
 
 % these need to be sort of protected:
 
+% methods:
+%
+% hidden : mark for list, don't show in text
+% list   : mark for list, show in text only when in list
+% text   : not to list, show in text
+% always : mark for list, show in text
+
 \let\p_publ_cite_before   \empty
 \let\p_publ_cite_after    \empty
 \let\p_publ_cite_lefttext \empty
@@ -1279,6 +1286,7 @@
 \newconditional\btxcitecompress
 
 \let\currentbtxreference\empty
+\let\currentbtxcitemethod\v!hidden
 
 \def\publ_cite_variant
   {\begingroup
@@ -1295,7 +1303,7 @@
   {\clf_btxhandlecite
      dataset          {\currentbtxdataset}%
      reference        {\currentbtxreference}%
-     markentry        \iftrialtypesetting\s!false\else\s!true\fi\space
+     method           {\currentbtxcitemethod}%
      variant          {\currentbtxcitealternative}%
      sorttype         {\btxparameter\c!sorttype}%
      compress         {\btxparameter\c!compress}%
@@ -1306,7 +1314,9 @@
      before           {\p_publ_cite_before}%
      after            {\p_publ_cite_after}%
    \relax
-   \clf_btxflushmarked} % maybe: \iftrialtypesetting\else ... \fi
+   \iftrialtypesetting\else
+     \clf_btxflushmarked
+   \fi}
 
 \let\dobtxcitevariantblob\publ_cite_handle_variant_blob % command can use it via lua
 
@@ -1320,9 +1330,23 @@
    \btxparameter\c!right
    \endgroup}
 
-\unexpanded\def\btxcitation
+\unexpanded\def\btxlistcitation
+  {\dontleavehmode
+   \begingroup
+   \let\currentbtxcitemethod\v!list
+   \dodoubleempty\publ_citation}
+
+\unexpanded\def\btxtextcitation
+  {\dontleavehmode
+   \begingroup
+   \let\btxcitereference\relax % a bit of a hack but ok
+   \let\currentbtxcitemethod\v!text
+   \dodoubleempty\publ_citation}
+
+\unexpanded\def\btxalwayscitation
   {\dontleavehmode
    \begingroup
+   \let\currentbtxcitemethod\v!always
    \dodoubleempty\publ_citation}
 
 \def\publ_citation[#1][#2]% could be made more efficient but not now
@@ -1332,19 +1356,20 @@
      \publ_cite_tags_indeed{#1}%
    \fi}
 
-\unexpanded\def\btxnocitation
-  {\dosingleempty\publ_cite_no}
+\unexpanded\def\btxhiddencitation
+  {\dosingleempty\publ_cite_hidden}
 
-\unexpanded\def\publ_cite_no[#1]%
+\unexpanded\def\publ_cite_hidden[#1]%
   {\iftrialtypesetting \else
      \begingroup
+     \let\currentbtxcitemethod\v!hidden
      \edef\currentbtxreference{#1}%
      \clf_btxhandlenocite
+       method    {\currentbtxcitemethod}%
        dataset   {\currentbtxdataset}%
        reference {\currentbtxreference}%
-       markentry true%
      \relax
-   % \clf_btxflushmarked
+     \clf_btxflushmarked
      \endgroup
    \fi}
 
@@ -1353,16 +1378,27 @@
 
 %D Compatibility:
 
-\let\cite      \btxcitation
-\let\citation  \btxcitation
-\let\nocite    \btxnocitation
-\let\nocitation\btxnocitation
+\let\hiddencitation\btxhiddencitation  \let\hiddencite\hiddencitation
+\let\listcitation  \btxlistcitation    \let\listcite  \listcitation
+\let\textcitation  \btxtextcitation    \let\textcite  \textcitation
+\let\alwayscitation\btxalwayscitation  \let\alwayscite\alwayscitation
+
+\unexpanded\def\citation  {\doifelsenextoptionalcs\btxlistcitation  \btxdirectlistcite}
+\unexpanded\def\nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite}
+
+\let\citation  \listcitation \let\cite  \citation
+\let\nocitation\nocitation   \let\nocite\nocitation
 
-\unexpanded\def\cite  {\doifelsenextoptionalcs\btxcitation  \btxdirectcite}
-\unexpanded\def\nocite{\doifelsenextoptionalcs\btxnocitation\btxdirectnocite}
+\unexpanded\def\publ_entry_citation  {\doifelsenextoptionalcs\btxlistcitation  \btxdirectlistcite}
+\unexpanded\def\publ_entry_nocitation{\doifelsenextoptionalcs\btxhiddencitation\btxdirecthiddencite}
+
+\appendtoks
+    \let\cite  \publ_entry_citation
+    \let\nocite\publ_entry_nocitation
+\to \everybtxlistrendering
 
-\unexpanded\def\btxdirectcite  #1{\btxcitation  [#1]\relax} % no optional arguments
-\unexpanded\def\btxdirectnocite#1{\btxnocitation[#1]\relax} % no optional arguments
+\unexpanded\def\btxdirectlistcite  #1{\btxlistcitation  [#1]\relax} % no optional arguments
+\unexpanded\def\btxdirecthiddencite#1{\btxhiddencitation[#1]\relax} % no optional arguments
 
 %D Setup helpers, beware, we need to wrap this .. now we need to know
 %D how setups are implemented.
@@ -1658,7 +1694,7 @@
     \clf_btxtoregister{\currentbtxdataset}{\currentbtxtag}%
 \to \t_btx_reference_inject
 
-\unexpanded\def\btxindexedauthor#1#2#3#4#5#6% alternative von last first junior
+\unexpanded\def\btxindexedauthor#1#2#3#4#5#6% alternative von last initials first junior
   {\begingroup
    \def\currentbtxcitealternative{#1}%
    \ifx\currentbtxcitealternative\empty
@@ -1675,6 +1711,16 @@
    \fastsetup{\s!btx:\s!cite:\s!author:\currentbtxcitealternative}%
    \endgroup}
 
+\unexpanded\def\btxregisterauthor
+  {\doifelsenextoptionalcs\publ_register_author_yes\publ_register_author_nop}
+
+\def\publ_register_author_yes[#1]#2%
+  {\clf_btxauthortoregister{#1}{#2}\relax}
+
+\def\publ_register_author_nop#1%
+  {\clf_btxauthortoregister{\currentbtxdataset}{#1}\relax}
+
+
 %D We hook some setters in the definition sets:
 
 % \installdefinitionsetmember \??btx {btxspecification} \??btxcitevariant {btxcitevariant}
@@ -1739,9 +1785,10 @@
    \c!refcommand=authoryears,  % todo
    \c!numbering=\v!yes,
   %\c!saveinlist=\v!no, % maybe for before/after
+   \c!pagestate=\v!stop,
    \c!textstate=\v!start,
    \c!width=\v!auto,
-   \c!separator={;\space},
+   \c!separator={\btxsemicolon},
    \c!distance=1.5\emwidth]
 
 % Quite some interpunction and labels are the same of at least consistent within
@@ -1750,30 +1797,29 @@
 
 \setupbtx
   [\c!interaction=\v!start,
-   \c!alternative=num, % default cite form
-   \c!inbetween=\space,
+   \c!alternative=num, % default cite form, normally defined in the cite namespace
+   \c!inbetween=\btxspace,
    \c!range=\endash,   % separator:range?
    \c!compress=\v!yes, % was no?
    \c!authorconversion=normal,
    \c!sorttype=normal, % normal, reverse or none
    \c!etallimit=3,
    \c!etaldisplay=\btxparameter\c!etallimit,
-   \c!otherstext={\space et al.},
-   \c!separator:firstnames={\space},
-   \c!separator:juniors={\space},
-   \c!separator:vons={\space},
-   \c!separator:initials={\space},
+   \c!otherstext={\btxspace et al.},
+   \c!separator:firstnames={\btxspace},
+   \c!separator:juniors={\btxspace},
+   \c!separator:vons={\btxspace},
+   \c!separator:initials={\btxspace},
    \c!stopper:initials={.},
-  %\c!surnamesep={,\space}, % is this used anywhere?
-   \c!separator:invertedinitials={,\space},
-   \c!separator:invertedfirstnames={,\space},
-   \c!separator:names:2={,\space}, % separates multiple names
+  %\c!surnamesep={\btxcomma}, % is this used anywhere?
+   \c!separator:invertedinitials={\btxcomma},
+   \c!separator:invertedfirstnames={\btxcomma},
+   \c!separator:names:2={\btxcomma}, % separates multiple names
    \c!separator:names:3=\btxparameter{\c!separator:2}, % before last name in a list
    \c!separator:names:4=\btxparameter{\c!separator:2}, % between only two names
-   \c!separator:2={;\space}, % aka pubsep - separates multiple objects
+   \c!separator:2={\btxsemicolon}, % aka pubsep - separates multiple objects
    \c!separator:3=\btxparameter{separator:2}, % before last object in a list
-   \c!separator:4=\btxparameter{separator:2}, % between only two objects
-   \c!pagestate=\v!stop]
+   \c!separator:4=\btxparameter{separator:2}] % between only two objects
 
 % Do we want these in the format? Loading them delayed is somewhat messy.
 
diff --git a/tex/context/base/publ-reg.lua b/tex/context/base/publ-reg.lua
index 39469e510..3f276b49a 100644
--- a/tex/context/base/publ-reg.lua
+++ b/tex/context/base/publ-reg.lua
@@ -153,6 +153,9 @@ local shorts = {
 }
 
 function flushers.author(step,field,value)
+    if type(value) == "string" then
+        value = publications.authorcache[value]
+    end
     if type(value) == "table" and #value > 0 then
         local register    = step.register
         local processor   = step.processor
@@ -160,7 +163,7 @@ function flushers.author(step,field,value)
         for i=1,#value do
             local a = value[i]
             local k = writers[field] { a }
-            local e = f_author(alternative,components(a,short))
+            local e = f_author(alternative,components(a))
             ctx_dosetfastregisterentry(register,e,k,processor or "","")
         end
     end
@@ -175,3 +178,50 @@ function flushers.keyword(step,field,value)
         end
     end
 end
+
+-- publications.registerflushers = flushers
+
+local function btxtoregister(dataset,tag)
+    local current = datasets[dataset]
+    for i=1,#sequence do
+        local step = sequence[i]
+        local dset = step.dataset
+        if dset == v_all or dset == dataset then
+            local done = step.done
+            if not done[tag] then
+                local value, field, kind = getcasted(current,tag,step.field,specifications[step.specification])
+                if value then
+                    flushers[kind](step,field,value)
+                end
+                done[tag] = true
+            end
+        end
+    end
+end
+
+local function authortoregister(dataset,hash)
+    local author = publications.authorcache[hash]
+    if author then
+        local current = datasets[dataset]
+        for i=1,#sequence do
+            local step = sequence[i]
+            local dset = step.dataset
+            if dset == v_all or dset == dataset then
+                local register    = step.register
+                local processor   = step.processor
+                local alternative = shorts[step.alternative or "invertedshort"] or "invertedshort"
+                local k = writers.author { author }
+                local e = f_author(alternative,components(author,short))
+                ctx_dosetfastregisterentry(register,e,k,processor or "","")
+            end
+        end
+    end
+end
+
+publications.authortoregister = authortoregister
+
+implement {
+    name      = "btxauthortoregister",
+    actions   = authortoregister,
+    arguments = { "string", "string" }
+}
diff --git a/tex/context/base/publ-tra.lua b/tex/context/base/publ-tra.lua
index b90455aed..4b03307ac 100644
--- a/tex/context/base/publ-tra.lua
+++ b/tex/context/base/publ-tra.lua
@@ -471,10 +471,34 @@ function tracers.showvariants(dataset,pages)
     end
 end
 
+function tracers.showhashedauthors(dataset,pages)
+    local components = publications.components.author
+    ctx_starttabulate { "|T|T|T|T|T|T|" }
+    ctx_NC() ctx_bold("hash")
+    ctx_NC() ctx_bold("vons")
+    ctx_NC() ctx_bold("surnames")
+    ctx_NC() ctx_bold("initials")
+    ctx_NC() ctx_bold("firstnames")
+    ctx_NC() ctx_bold("juniors")
+    ctx_NC() ctx_NR() ctx_HL()
+    for hash, data in sortedhash(publications.authorcache) do
+        local vons, surnames, initials, firstnames, juniors = components(data)
+        ctx_NC() context(hash)
+        ctx_NC() context(vons)
+        ctx_NC() context(surnames)
+        ctx_NC() context(initials)
+        ctx_NC() context(firstnames)
+        ctx_NC() context(juniors)
+        ctx_NC() ctx_NR()
+    end
+    ctx_stoptabulate()
+end
+
 commands.showbtxdatasetfields       = tracers.showdatasetfields
 commands.showbtxdatasetcompleteness = tracers.showdatasetcompleteness
 commands.showbtxfields              = tracers.showfields
 commands.showbtxtables              = tracers.showtables
 commands.showbtxdatasetauthors      = tracers.showdatasetauthors
+commands.showbtxhashedauthors       = tracers.showhashedauthors
 commands.showbtxentry               = tracers.showentry
 commands.showbtxvariants            = tracers.showvariants
diff --git a/tex/context/base/publ-tra.mkiv b/tex/context/base/publ-tra.mkiv
index 2f86a5624..6ef86ca59 100644
--- a/tex/context/base/publ-tra.mkiv
+++ b/tex/context/base/publ-tra.mkiv
@@ -23,6 +23,7 @@
 \unexpanded\def\showbtxdatasetfields      {\dosingleempty\publ_show_dataset_fields}
 \unexpanded\def\showbtxdatasetcompleteness{\dosingleempty\publ_show_dataset_completeness}
 \unexpanded\def\showbtxdatasetauthors     {\dosingleempty\publ_show_dataset_authors}
+\unexpanded\def\showbtxhashedauthors      {\dosingleempty\publ_show_hashed_authors}
 \unexpanded\def\showbtxfields             {\dosingleempty\publ_show_fields}
 \unexpanded\def\showbtxtables             {\dosingleempty\publ_show_tables}
 
@@ -69,6 +70,9 @@
    \ctxcommand{showbtxtables{}}%
    \endgroup}
 
+\def\publ_show_hashed_authors[#1]%
+  {\ctxcommand{showbtxhashedauthors{}}}
+
 \protect
 
 \continueifinputfile{publ-tra.mkiv}
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 0444f2f91..828eca6c8 100644
Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
index 96ab490b7..91d2fdb2c 100644
Binary files a/tex/context/base/status-lua.pdf and b/tex/context/base/status-lua.pdf differ
diff --git a/tex/context/base/strc-mat.mkiv b/tex/context/base/strc-mat.mkiv
index 22fa54889..225531fa8 100644
--- a/tex/context/base/strc-mat.mkiv
+++ b/tex/context/base/strc-mat.mkiv
@@ -45,7 +45,16 @@
    \c!indentnext=\v!no,
    \c!alternative=\s!default,
    \c!strut=\v!no,
-   \c!distance=\emwidth]
+   \c!distance=2\emwidth]
+
+\ifdefined\matheqnogapstep
+    % we're ok, now we have that quad in the distance which is
+    % more consistent and not depending on the text font in math
+    \matheqnogapstep\zerocount
+\else
+    % we will keep this for a while
+    \setupformulas[\c!distance=\emwidth]
+\fi
 
 \setupsubformulas % subformulas could be last in chain
   [\c!indentnext=\formulaparameter\c!indentnext]
@@ -228,18 +237,27 @@
 %       nested:     \number\c_strc_formulas_nested_number_mode]}}
 
 \unexpanded\def\placecurrentformulanumber
-  {\rm % nodig ?
-   \doif{\formulaparameter\c!location}\v!right{\hskip\formulaparameter\c!distance}%
+  {\begingroup
+   \rm % determines the distance and main font
+   \edef\p_location{\formulaparameter\c!location}%
+   \ifx\p_location\v!right
+      \hskip\formulaparameter\c!distance
+   \fi
+   \begingroup
+   \useformulastyleandcolor\c!numberstyle\c!numbercolor
    \formulaparameter\c!numbercommand
-     {\useformulastyleandcolor\c!numberstyle\c!numbercolor
-      \strut
+     {\strut
       \formulaparameter\c!left
       \namedtaggedlabeltexts
         \t!formulalabel \v!formula
         \t!formulanumber\v!formula
         {\ignorespaces\strc_formulas_place_current_number\removeunwantedspaces}%
       \formulaparameter\c!right}%
-   \doif{\formulaparameter\c!location}\v!left{\hskip\formulaparameter\c!distance}}
+   \endgroup
+   \ifx\p_location\v!left
+     \hskip\formulaparameter\c!distance
+   \fi
+   \endgroup}
 
 \unexpanded\def\strc_formulas_place_current_number
   {\strc_formulas_handle_current_references
@@ -433,6 +451,8 @@
 %D
 %D Otherwise we get a missing \type {$$} error reported.
 
+\let\reqno\eqno
+
 \unexpanded\def\resetdisplaymatheq % when used?
   {\let\normalleqno\gobbleoneargument \let\leqno\gobbleoneargument
    \let\normalreqno\gobbleoneargument \let\eqno \gobbleoneargument
diff --git a/tex/context/base/syst-ini.mkiv b/tex/context/base/syst-ini.mkiv
index 8631aed90..dc5fddb63 100644
--- a/tex/context/base/syst-ini.mkiv
+++ b/tex/context/base/syst-ini.mkiv
@@ -1095,6 +1095,10 @@
 \suppressoutererror   \plusone
 \suppressmathparerror \plusone
 
+\ifdefined\matheqnogapstep % for now
+    \matheqnogapstep  \zerocount
+\fi
+
 %D While cleaning this code up a bit I was listening to Heather Nova's \CD\ Redbird.
 %D The first song on that \CD\ ends with a few lines suitable for ending this
 %D initialization module:
diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua
index a20e42d1a..b54182798 100644
--- a/tex/context/base/trac-vis.lua
+++ b/tex/context/base/trac-vis.lua
@@ -471,8 +471,10 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous)
     if wd ~= 0 then
         local ht = getfield(current,"height")
         local dp = getfield(current,"depth")
+        local shift = getfield(current,"shift")
         local next = getnext(current)
-        local prev = previous -- getprev(current) ... prev can be wrong in math mode < 0.78.3
+        local prev = previous
+     -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3
         setfield(current,"next",nil)
         setfield(current,"prev",nil)
         local linewidth = emwidth/fraction
@@ -533,7 +535,22 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous)
             new_rule(wd-2*linewidth,ht,-ht+linewidth)
         )
         if baseskip then
-            info = linked_nodes(info,baseskip,baseline)
+            info = linked_nodes(info,baseskip,baseline) -- could be in previous linked
+        end
+        local shft
+        if shift == 0 then
+            shift = nil
+        else
+            local sh = shift > 0 and   shift or 0
+            local sd = shift < 0 and - shift or 0
+            shft = fast_hpack(new_rule(2*emwidth/fraction,sh,sd))
+            setfield(shft,"width",0)
+            if sh > 0 then
+                setfield(shft,"height",0)
+            end
+            if sd > 0 then
+                setfield(shft,"depth",0)
+            end
         end
         setlisttransparency(info,c_text)
         info = fast_hpack(info)
@@ -541,11 +558,18 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous)
         setfield(info,"height",0)
         setfield(info,"depth",0)
         setattr(info,a_layer,layer)
-        local info = linked_nodes(current,new_kern(-wd),info)
+        local info = linked_nodes(shft,current,new_kern(-wd),info)
         info = fast_hpack(info,wd)
         if vertical then
             info = vpack_nodes(info)
         end
+        if shift then
+            setfield(current,"shift",0)
+            setfield(info,"width",wd)
+            setfield(info,"height",ht)
+            setfield(info,"depth",dp)
+            setfield(info,"shift",shift)
+        end
         if next then
             setfield(info,"next",next)
             setfield(next,"prev",info)
diff --git a/tex/context/base/trac-vis.mkiv b/tex/context/base/trac-vis.mkiv
index 6ee8a6b8d..74a2c1ba2 100644
--- a/tex/context/base/trac-vis.mkiv
+++ b/tex/context/base/trac-vis.mkiv
@@ -22,7 +22,7 @@
 %D
 %D Control over what gets visualized happens with the tracker command:
 %D
-%D \enabletrackers[visualizer.*]
+%D \enabletrackers[visualizers.*]
 %D
 %D Possible values are: \type {fontkern}, \type {kern}, \type {glue}, \type
 %D {penalty}, \type {hbox}, \type {vbox}, \type {all}, \type {reset}, \type
diff --git a/tex/context/base/typo-itc.lua b/tex/context/base/typo-itc.lua
index e4873f606..d3a31fad1 100644
--- a/tex/context/base/typo-itc.lua
+++ b/tex/context/base/typo-itc.lua
@@ -133,14 +133,6 @@ end
 --     return with_attributes(new_correction_kern(kern),n)
 -- end
 
-local function correction_glue(glue,n)
-    local g = new_correction_glue(glue)
-    if n then
-        setfield(g,"attr",getfield(n,"attr"))
-    end
-    return g
-end
-
 local function correction_kern(kern,n)
     local k = new_correction_kern(kern)
     if n then
@@ -152,7 +144,7 @@ local function correction_kern(kern,n)
     return k
 end
 
-local function correction_glue(n,glue)
+local function correction_glue(glue,n)
     local g = new_correction_glue(glue)
     if n then
         local a = getfield(n,"attr")
diff --git a/tex/context/base/typo-sus.lua b/tex/context/base/typo-sus.lua
index 9eef6196b..0fe8e143a 100644
--- a/tex/context/base/typo-sus.lua
+++ b/tex/context/base/typo-sus.lua
@@ -20,6 +20,11 @@ local closequote = {
     pf = true,
 }
 
+local weird = {
+    lm = true,
+    no = true,
+}
+
 local categories      = characters.categories
 
 local nodecodes       = nodes.nodecodes
@@ -187,6 +192,8 @@ function typesetters.marksuspects(head)
                     if prev and pid == glue_code then
                         done = 1 -- darkred
                     end
+                elseif weird[code] then
+                    done = 2 -- darkgreen
                 else
                     local prev, pid = goback(current)
                     if prev then
diff --git a/tex/context/base/util-str.lua b/tex/context/base/util-str.lua
index de4a87e9f..c2139b155 100644
--- a/tex/context/base/util-str.lua
+++ b/tex/context/base/util-str.lua
@@ -1118,7 +1118,7 @@ function string.optionalquoted(str)
     return lpegmatch(pattern,str) or str
 end
 
-local pattern = Cs((newline / os.newline + 1)^0)
+local pattern = Cs((newline / (os.newline or "\r") + 1)^0)
 
 function string.replacenewlines(str)
     return lpegmatch(pattern,str)
diff --git a/tex/context/base/x-asciimath.lua b/tex/context/base/x-asciimath.lua
index efa6a7736..52664f0d3 100644
--- a/tex/context/base/x-asciimath.lua
+++ b/tex/context/base/x-asciimath.lua
@@ -711,9 +711,11 @@ local reserved = {
 for k, v in next, characters.data do
     local name = v.mathname
     if name and not reserved[name] then
-        reserved[name] = { true, utfchar(k) }
+        local char = { true, utfchar(k) }
+        reserved[        name] = char
+     -- reserved["\\" .. name] = char
     end
-    local spec = v.mathspec
+ -- local spec = v.mathspec
  -- if spec then
  --     for i=1,#spec do
  --         local name = spec[i].name
@@ -957,8 +959,10 @@ for k, v in sortedhash(reserved) do
             k_reserved_different[#k_reserved_different+1] = k
         end
     end
-    if not find(k,"[^[a-zA-Z]+$]") then
-        k_unicode["\\"..k] = k -- dirty trick, no real unicode
+    if find(k,"^[a-zA-Z]+$") then
+        k_unicode["\\"..k] = replacement
+    else
+        k_unicode["\\"..k] = k  -- dirty trick, no real unicode (still needed ?)
     end
     if not find(k,"[^a-zA-Z]") then
         k_reserved_words[#k_reserved_words+1] = k
@@ -970,9 +974,8 @@ local p_reserved =
     lpeg.utfchartabletopattern(k_reserved_different) / k_commands
 
 local p_unicode =
-    lpeg.utfchartabletopattern(table.keys(k_unicode)) / k_unicode
-
--- inspect(k_reserved_different)
+--     lpeg.utfchartabletopattern(table.keys(k_unicode)) / k_unicode
+    lpeg.utfchartabletopattern(k_unicode) / k_unicode
 
 local p_texescape = patterns.texescape
 
@@ -1817,7 +1820,7 @@ local uncrapped = {
     ["_"] = "\\underline{\\enspace}",
 }
 
-local function convert(str)
+local function convert(str,nowrap)
     if #str > 0 then
         local unicoded = lpegmatch(u_parser,str) or str
         if lpegmatch(p_onechar,unicoded) then
@@ -1834,6 +1837,8 @@ local function convert(str)
                 if message then
                     report_asciimath("%s: %s : %s",message,str,texcoded)
                     ctx_type(formatters["<%s>"](message))
+                elseif nowrap then
+                     context(texcoded)
                 else
                     ctx_mathematics(texcoded)
                 end
@@ -1855,6 +1860,7 @@ if not context then
 --     report_asciimath(cleanedup([[a "α" b]]))
 --     report_asciimath(cleanedup([[//4]]))
 
+convert("leq\\leq")
 -- convert([[\^{1/5}log]])
 -- convert("sqrt")
 -- convert("^")
@@ -1936,11 +1942,17 @@ if not context then
 end
 
 interfaces.implement {
-    name      = "asciimath", -- module_asciimath_convert
+    name      = "asciimath",
     actions   = convert,
     arguments = "string"
 }
 
+interfaces.implement {
+    name      = "justasciimath",
+    actions   = convert,
+    arguments = { "string", true },
+}
+
 local ctx_typebuffer  = context.typebuffer
 local ctx_mathematics = context.mathematics
 local ctx_color       = context.color
diff --git a/tex/context/base/x-asciimath.mkiv b/tex/context/base/x-asciimath.mkiv
index cc98b54ac..1d62fb93d 100644
--- a/tex/context/base/x-asciimath.mkiv
+++ b/tex/context/base/x-asciimath.mkiv
@@ -156,8 +156,20 @@
     }}%
 \to \everysetupasciimath
 
-\unexpanded\def\asciimath#1%
-  {\clf_asciimath{\detokenize\expandafter{\normalexpanded{#1}}}}
+\newtoks\everyascimath
+
+% \appendtoks
+%     \ignorediscretionaries
+% \to \everyasciimath
+
+\unexpanded\def\asciimath
+  {\doifnextoptionalelse\asciimath_yes\asciimath_nop}
+
+\def\asciimath_yes[#1]#2%
+  {\mathematics[#1]{\clf_justasciimath{\detokenize\expandafter{\normalexpanded{#2}}}}}
+
+\def\asciimath_nop#1%
+  {\mathematics{\clf_justasciimath{\detokenize\expandafter{\normalexpanded{#1}}}}}
 
 \unexpanded\def\ctxmoduleasciimath#1%
   {\ctxlua{moduledata.asciimath.#1}}
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index afd01aae2..a3112d206 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : luatex-fonts-merged.lua
 -- parent file : luatex-fonts.lua
--- merge date  : 05/15/15 11:42:33
+-- merge date  : 05/21/15 13:39:28
 
 do -- begin closure to overcome local limits and interference
 
@@ -3442,7 +3442,7 @@ local pattern=Cs(dquote*(equote-P(-2))^0*dquote)
 function string.optionalquoted(str)
   return lpegmatch(pattern,str) or str
 end
-local pattern=Cs((newline/os.newline+1)^0)
+local pattern=Cs((newline/(os.newline or "\r")+1)^0)
 function string.replacenewlines(str)
   return lpegmatch(pattern,str)
 end
@@ -7163,6 +7163,7 @@ local stoptiming=statistics.stoptiming
 local elapsedtime=statistics.elapsedtime
 local findbinfile=resolvers.findbinfile
 local trace_private=false registertracker("otf.private",function(v) trace_private=v end)
+local trace_subfonts=false registertracker("otf.subfonts",function(v) trace_subfonts=v end)
 local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end)
 local trace_features=false registertracker("otf.features",function(v) trace_features=v end)
 local trace_dynamics=false registertracker("otf.dynamics",function(v) trace_dynamics=v end)
@@ -7175,7 +7176,7 @@ local report_otf=logs.reporter("fonts","otf loading")
 local fonts=fonts
 local otf=fonts.handlers.otf
 otf.glists={ "gsub","gpos" }
-otf.version=2.803 
+otf.version=2.810 
 otf.cache=containers.define("fonts","otf",otf.version,true)
 local hashes=fonts.hashes
 local definers=fonts.definers
@@ -7708,6 +7709,7 @@ local function somecopy(old)
   end
 end
 actions["prepare glyphs"]=function(data,filename,raw)
+  local tableversion=tonumber(raw.table_version) or 0
   local rawglyphs=raw.glyphs
   local rawsubfonts=raw.subfonts
   local rawcidinfo=raw.cidinfo
@@ -7728,66 +7730,95 @@ actions["prepare glyphs"]=function(data,filename,raw)
       local cidmap=fonts.cid.getmap(rawcidinfo)
       if cidmap then
         rawcidinfo.usedname=cidmap.usedname
-        local nofnames,nofunicodes=0,0
-        local cidunicodes,cidnames=cidmap.unicodes,cidmap.names
+        local nofnames=0
+        local nofunicodes=0
+        local cidunicodes=cidmap.unicodes
+        local cidnames=cidmap.names
+        local cidtotal=0
+        local unique=trace_subfonts and {}
         for cidindex=1,#rawsubfonts do
           local subfont=rawsubfonts[cidindex]
           local cidglyphs=subfont.glyphs
           if includesubfonts then
             metadata.subfonts[cidindex]=somecopy(subfont)
           end
-          for index=0,subfont.glyphcnt-1 do 
-            local glyph=cidglyphs[index]
-            if glyph then
-              local unicode=glyph.unicode
-              if   unicode>=0x00E000 and unicode<=0x00F8FF then
-                unicode=-1
-              elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
-                unicode=-1
-              elseif unicode>=0x100000 and unicode<=0x10FFFD then
-                unicode=-1
-              end
-              local name=glyph.name or cidnames[index]
-              if not unicode or unicode==-1 then 
-                unicode=cidunicodes[index]
-              end
-              if unicode and descriptions[unicode] then
-                if trace_private then
-                  report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+          local cidcnt,cidmin,cidmax
+          if tableversion>0.3 then
+            cidcnt=subfont.glyphcnt
+            cidmin=subfont.glyphmin
+            cidmax=subfont.glyphmax
+          else
+            cidcnt=subfont.glyphcnt
+            cidmin=0
+            cidmax=cidcnt-1
+          end
+          if trace_subfonts then
+            local cidtot=cidmax-cidmin+1
+            cidtotal=cidtotal+cidtot
+            report_otf("subfont: %i, min: %i, max: %i, cnt: %i, n: %i",cidindex,cidmin,cidmax,cidtot,cidcnt)
+          end
+          if cidcnt>0 then
+            for cidslot=cidmin,cidmax do
+              local glyph=cidglyphs[cidslot]
+              if glyph then
+                local index=tableversion>0.3 and glyph.orig_pos or cidslot
+                if trace_subfonts then
+                  unique[index]=true
                 end
-                unicode=-1
-              end
-              if not unicode or unicode==-1 then 
-                if not name then
-                  name=format("u%06X.ctx",private)
+                local unicode=glyph.unicode
+                if   unicode>=0x00E000 and unicode<=0x00F8FF then
+                  unicode=-1
+                elseif unicode>=0x0F0000 and unicode<=0x0FFFFD then
+                  unicode=-1
+                elseif unicode>=0x100000 and unicode<=0x10FFFD then
+                  unicode=-1
                 end
-                unicode=private
-                unicodes[name]=private
-                if trace_private then
-                  report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+                local name=glyph.name or cidnames[index]
+                if not unicode or unicode==-1 then 
+                  unicode=cidunicodes[index]
                 end
-                private=private+1
-                nofnames=nofnames+1
-              else
-                if not name then
-                  name=format("u%06X.ctx",unicode)
+                if unicode and descriptions[unicode] then
+                  if trace_private then
+                    report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
+                  end
+                  unicode=-1
                 end
-                unicodes[name]=unicode
-                nofunicodes=nofunicodes+1
-              end
-              indices[index]=unicode 
-              local description={
-                boundingbox=glyph.boundingbox,
-                name=glyph.name or name or "unknown",
-                cidindex=cidindex,
-                index=index,
-                glyph=glyph,
-              }
-              descriptions[unicode]=description
-            else
+                if not unicode or unicode==-1 then 
+                  if not name then
+                    name=format("u%06X.ctx",private)
+                  end
+                  unicode=private
+                  unicodes[name]=private
+                  if trace_private then
+                    report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+                  end
+                  private=private+1
+                  nofnames=nofnames+1
+                else
+                  if not name then
+                    name=format("u%06X.ctx",unicode)
+                  end
+                  unicodes[name]=unicode
+                  nofunicodes=nofunicodes+1
+                end
+                indices[index]=unicode 
+                local description={
+                  boundingbox=glyph.boundingbox,
+                  name=name or "unknown",
+                  cidindex=cidindex,
+                  index=cidslot,
+                  glyph=glyph,
+                }
+                descriptions[unicode]=description
+              end
             end
+          else
+            report_otf("potential problem: no glyphs found in subfont %i",cidindex)
           end
         end
+        if trace_subfonts then
+          report_otf("nofglyphs: %i, unique: %i",cidtotal,table.count(unique))
+        end
         if trace_loading then
           report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes,nofnames,nofunicodes+nofnames)
         end
@@ -7798,68 +7829,75 @@ actions["prepare glyphs"]=function(data,filename,raw)
       report_otf("font %a has no glyphs",filename)
     end
   else
-    for index=0,raw.glyphcnt-1 do 
-      local glyph=rawglyphs[index]
-      if glyph then
-        local unicode=glyph.unicode
-        local name=glyph.name
-        if not unicode or unicode==-1 then 
-          unicode=private
-          unicodes[name]=private
-          if trace_private then
-            report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
-          end
-          private=private+1
-        else
-          if unicode>criterium then
-            local taken=descriptions[unicode]
-            if taken then
-              if unicode>=private then
-                private=unicode+1 
+    local cnt=raw.glyphcnt or 0
+    local min=tableversion>0.3 and raw.glyphmin or 0
+    local max=tableversion>0.3 and raw.glyphmax or (raw.glyphcnt-1)
+    if cnt>0 then
+      for index=min,max do
+        local glyph=rawglyphs[index]
+        if glyph then
+          local unicode=glyph.unicode
+          local name=glyph.name
+          if not unicode or unicode==-1 then 
+            unicode=private
+            unicodes[name]=private
+            if trace_private then
+              report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
+            end
+            private=private+1
+          else
+            if unicode>criterium then
+              local taken=descriptions[unicode]
+              if taken then
+                if unicode>=private then
+                  private=unicode+1 
+                else
+                  private=private+1 
+                end
+                descriptions[private]=taken
+                unicodes[taken.name]=private
+                indices[taken.index]=private
+                if trace_private then
+                  report_otf("slot %U is moved to %U due to private in font",unicode)
+                end
               else
-                private=private+1 
-              end
-              descriptions[private]=taken
-              unicodes[taken.name]=private
-              indices[taken.index]=private
-              if trace_private then
-                report_otf("slot %U is moved to %U due to private in font",unicode)
-              end
-            else
-              if unicode>=private then
-                private=unicode+1 
+                if unicode>=private then
+                  private=unicode+1 
+                end
               end
             end
+            unicodes[name]=unicode
           end
-          unicodes[name]=unicode
-        end
-        indices[index]=unicode
-        descriptions[unicode]={
-          boundingbox=glyph.boundingbox,
-          name=name,
-          index=index,
-          glyph=glyph,
-        }
-        local altuni=glyph.altuni
-        if altuni then
-          for i=1,#altuni do
-            local a=altuni[i]
-            local u=a.unicode
-            local v=a.variant
-            if v then
-              local vv=variants[v]
-              if vv then
-                vv[u]=unicode
-              else 
-                vv={ [u]=unicode }
-                variants[v]=vv
+          indices[index]=unicode
+          descriptions[unicode]={
+            boundingbox=glyph.boundingbox,
+            name=name,
+            index=index,
+            glyph=glyph,
+          }
+          local altuni=glyph.altuni
+          if altuni then
+            for i=1,#altuni do
+              local a=altuni[i]
+              local u=a.unicode
+              local v=a.variant
+              if v then
+                local vv=variants[v]
+                if vv then
+                  vv[u]=unicode
+                else 
+                  vv={ [u]=unicode }
+                  variants[v]=vv
+                end
               end
             end
           end
+        else
+          report_otf("potential problem: glyph %U is used but empty",index)
         end
-      else
-        report_otf("potential problem: glyph %U is used but empty",index)
       end
+    else
+      report_otf("potential problem: no glyphs found")
     end
   end
   resources.private=private
-- 
cgit v1.2.3