From 9671aae0a69df33d2a832de35eab0f143fc3b55b Mon Sep 17 00:00:00 2001
From: Marius <mariausol@gmail.com>
Date: Mon, 14 Nov 2011 01:00:14 +0200
Subject: beta 2011.11.13 23:53

---
 tex/context/base/back-exp.lua                      | 143 ++++++----
 tex/context/base/cont-new.mkii                     |   2 +-
 tex/context/base/cont-new.mkiv                     |   2 +-
 tex/context/base/context-version.pdf               | Bin 4116 -> 4118 bytes
 tex/context/base/context-version.png               | Bin 106126 -> 106240 bytes
 tex/context/base/context.mkii                      |   2 +-
 tex/context/base/context.mkiv                      |   2 +-
 tex/context/base/core-env.mkiv                     |   2 +-
 tex/context/base/font-otn.lua                      |  50 ++--
 tex/context/base/math-vfu.lua                      |  18 +-
 tex/context/base/status-files.pdf                  | Bin 24101 -> 24150 bytes
 tex/context/base/status-lua.pdf                    | Bin 168949 -> 168961 bytes
 tex/context/base/syst-aux.mkiv                     |  32 ++-
 tex/context/base/tabl-tab.mkiv                     |  15 +-
 tex/context/base/tabl-tbl.mkiv                     |  23 +-
 tex/context/base/typo-mar.lua                      | 308 +++++++++++++--------
 tex/context/base/typo-pag.lua                      |  17 +-
 tex/context/fonts/lm-math.lfg                      |   4 +-
 tex/context/fonts/px-math.lfg                      |   1 +
 tex/context/fonts/tx-math.lfg                      |   1 +
 tex/generic/context/luatex/luatex-fonts-merged.lua |  52 ++--
 21 files changed, 412 insertions(+), 262 deletions(-)

(limited to 'tex')

diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua
index d7a50da3a..98d87b1ee 100644
--- a/tex/context/base/back-exp.lua
+++ b/tex/context/base/back-exp.lua
@@ -26,6 +26,7 @@ local insert, remove = table.insert, table.remove
 local topoints = number.topoints
 local utfvalues = string.utfvalues
 local fromunicode16 = fonts.mappings.fromunicode16
+local sortedhash = table.sortedhash
 
 local trace_export  = false  trackers.register  ("export.trace",         function(v) trace_export  = v end)
 local trace_spacing = false  trackers.register  ("export.trace.spacing", function(v) trace_spacing = v end)
@@ -251,7 +252,8 @@ local function hashlistdata()
         local ci = c[i]
         local tag = ci.references.tag
         if tag then
-            listdata[ci.metadata.kind .. ":" .. ci.metadata.name .. "-" .. tag] = ci
+            local m = ci.metadata
+            listdata[m.kind .. ":" .. m.name .. "-" .. tag] = ci
         end
     end
 end
@@ -346,10 +348,12 @@ local function allusedstyles(xmlfile)
     --
     result[#result+1] = format(documenttemplate,bodyfont,width,align,hyphen)
     --
-    for element, details in table.sortedpairs(usedstyles) do
-        for detail, data in table.sortedpairs(details) do
-            local s = xml.css.fontspecification(data.style)
-            local c = xml.css.colorspecification(data.color)
+    local colorspecification = xml.css.fontspecification
+    local fontspecification = xml.css.fontspecification
+    for element, details in sortedhash(usedstyles) do
+        for detail, data in sortedhash(details) do
+            local s = fontspecification(data.style)
+            local c = colorspecification(data.color)
             result[#result+1] = format(styletemplate,element,detail,
                 s.style   or "inherit",
                 s.variant or "inherit",
@@ -375,8 +379,8 @@ local imagetemplate = [[
 
 local function allusedimages(xmlfile)
     local result = { format("/* images for file %s */",xmlfile) }
-    for element, details in table.sortedpairs(usedimages) do
-        for detail, data in table.sortedpairs(details) do
+    for element, details in sortedhash(usedimages) do
+        for detail, data in sortedhash(details) do
             local name = data.name
             if file.extname(name) == "pdf" then
                 -- temp hack .. we will have a remapper
@@ -446,12 +450,13 @@ local function checkdocument(root)
     if data then
         for i=1,#data do
             local di = data[i]
-            if type(di) == "table" then
-                if di.tg == "ignore" then
-                    di.element = ""
-                else
-                    checkdocument(di)
-                end
+            if di.content then
+                -- ok
+            elseif di.tg == "ignore" then
+                di.element = ""
+                checkdocument(di)
+            else
+                -- can't happen
             end
         end
     end
@@ -742,8 +747,11 @@ function extras.link(result,element,detail,n,fulltag,di)
         if data then
             for i=1,#data do
                 local di = data[i]
-                if di and extras.link(result,element,detail,n,di.fulltag,di) then
-                    return true
+                if di then
+                    local fulltag = di.fulltag
+                    if fulltag and extras.link(result,element,detail,n,fulltag,di) then
+                        return true
+                    end
                 end
             end
         end
@@ -817,16 +825,19 @@ local function checkmath(root) -- we can provide utf.toentities as an option
         if roottg == "msubsup" then
             local nucleus, superscript, subscript
             for i=1,ndata do
-                if type(data[i]) == "table" then
-                    if not nucleus then
-                        nucleus = i
-                    elseif not superscript then
-                        superscript = i
-                    elseif not subscript then
-                        subscript = i
-                    else
-                        -- error
-                    end
+                local di = data[i]
+                if not di then
+                    -- weird
+                elseif di.content then
+                    -- text
+                elseif not nucleus then
+                    nucleus = i
+                elseif not superscript then
+                    superscript = i
+                elseif not subscript then
+                    subscript = i
+                else
+                    -- error
                 end
             end
             if superscript and subscript then
@@ -841,7 +852,12 @@ local function checkmath(root) -- we can provide utf.toentities as an option
             root.attributes = attributes
             for i=1,ndata do
                 local di = data[i]
-                if type(di) == "table" then
+                if not di then
+                    -- weird
+                elseif di.content then
+                    n = n + 1
+                    new[n] = di
+                else
                     local tg = di.tg
                     if tg == "mleft" then
                         attributes.left   = tostring(di.data[1].data[1])
@@ -854,9 +870,6 @@ local function checkmath(root) -- we can provide utf.toentities as an option
                         di.__i__ = n
                         new[n] = di
                     end
-                else
-                    n = n + 1
-                    new[n] = di
                 end
             end
             root.data = new
@@ -866,8 +879,10 @@ local function checkmath(root) -- we can provide utf.toentities as an option
             return
         elseif ndata == 1 then
             local d = data[1]
-            if type(d) ~= "table" then
-                return -- can be string or false
+            if not d then
+                return
+            elseif d.content then
+                return
             elseif #root.data == 1 then
                 local tg = d.tg
                 if automathrows and roottg == "mrow" then
@@ -887,7 +902,7 @@ local function checkmath(root) -- we can provide utf.toentities as an option
         local i = 1
         while i <= ndata do                   -- -- -- TOO MUCH NESTED CHECKING -- -- --
             local di = data[i]
-            if di and type(di) == "table" then
+            if di and not di.content then
                 local tg = di.tg
                 local detail = di.detail
                 if tg == "math" then
@@ -1014,34 +1029,43 @@ local function checkmath(root) -- we can provide utf.toentities as an option
 end
 
 function stripmath(di)
-    local tg = di.tg
-    if tg == "mtext" or tg == "ms" then
+    if not di then
+        --
+    elseif di.content then
         return di
     else
-        local data = di.data
-        local ndata = #data
-        local n = 0
-        for i=1,ndata do
-            local di = data[i]
-            if type(di) == "table" then
-                di = stripmath(di)
+        local tg = di.tg
+        if tg == "mtext" or tg == "ms" then
+            return di
+        else
+            local data = di.data
+            local ndata = #data
+            local n = 0
+            for i=1,ndata do
+                local di = data[i]
+                if di and not di.content then
+                    di = stripmath(di)
+                end
+                if di then
+                    local content = di.content
+                    if not content then
+                        n = n + 1
+                        di.__i__ = n
+                        data[n] = di
+                    elseif content == " " or content == "" then
+                        -- skip
+                    else
+                        n = n + 1
+                        data[n] = di
+                    end
+                end
             end
-            if not di or di == " " or di == "" then
-                -- skip
-            elseif type(di) == "table" then
-                n = n + 1
-                di.__i__ = n
-                data[n] = di
-            else
-                n = n + 1
-                data[n] = di
+            for i=ndata,n+1,-1 do
+                data[i] = nil
+            end
+            if #data > 0 then
+                return di
             end
-        end
-        for i=ndata,n+1,-1 do
-            data[i] = nil
-        end
-        if #data > 0 then
-            return di
         end
     end
 end
@@ -1066,8 +1090,8 @@ end
 
 local a, z, A, Z = 0x61, 0x7A, 0x41, 0x5A
 
-function extras.mi(result,element,detail,n,fulltag,di)
-    local str = di.data[1]
+function extras.mi(result,element,detail,n,fulltag,di) -- check with content
+    local str = di.data[1].content
     if str and sub(str,1,1) ~= "&" then -- hack but good enough (maybe gsub op eerste)
         for v in utfvalues(str) do
             if (v >= a and v <= z) or (v >= A and v <= Z) then
@@ -1176,7 +1200,8 @@ function extras.tabulate(result,element,detail,n,fulltag,di)
             local content = false
             for i=1,#did do
                 local d = did[i].data
-                if d and #d > 0 then
+                local c = d and c.content
+                if c and #c > 0 then
                     content = true
                     break
                 end
diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii
index fdf1f849c..76b686c97 100644
--- a/tex/context/base/cont-new.mkii
+++ b/tex/context/base/cont-new.mkii
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2011.11.12 12:34}
+\newcontextversion{2011.11.13 23:53}
 
 %D This file is loaded at runtime, thereby providing an
 %D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index eb9b9b681..94ef37a12 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{2011.11.12 12:34}
+\newcontextversion{2011.11.13 23:53}
 
 %D This file is loaded at runtime, thereby providing an
 %D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 3f89f3a03..e628eca52 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-version.png b/tex/context/base/context-version.png
index 6ed66c29c..0fc57d8f7 100644
Binary files a/tex/context/base/context-version.png and b/tex/context/base/context-version.png differ
diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii
index 013e99747..90a1b6eba 100644
--- a/tex/context/base/context.mkii
+++ b/tex/context/base/context.mkii
@@ -20,7 +20,7 @@
 %D your styles an modules.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2011.11.12 12:34}
+\edef\contextversion{2011.11.13 23:53}
 
 %D For those who want to use this:
 
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index 6d07af3f8..0fd348853 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -20,7 +20,7 @@
 %D your styles an modules.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2011.11.12 12:34}
+\edef\contextversion{2011.11.13 23:53}
 
 %D For those who want to use this:
 
diff --git a/tex/context/base/core-env.mkiv b/tex/context/base/core-env.mkiv
index b095008b5..e81f1e6b3 100644
--- a/tex/context/base/core-env.mkiv
+++ b/tex/context/base/core-env.mkiv
@@ -223,7 +223,7 @@
    \expandafter\edef\csname\@mode@:\systemmodeprefix#1\endcsname{\number\csname\@mode@\systemmodeprefix#1\endcsname}%
    \expandafter\pushmacro\csname\@mode@:\systemmodeprefix#1\endcsname}
 
-\def\resetsystemmode#1%
+\def\popsystemmode#1%
   {\ifcsname\@mode@:\systemmodeprefix#1\endcsname
      \expandafter\popmacro\csname\@mode@:\systemmodeprefix#1\endcsname
      \csname\@mode@\systemmodeprefix#1\endcsname\csname\@mode@:\systemmodeprefix#1\endcsname\relax
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index e11e8d917..12ea97561 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -420,11 +420,11 @@ function handlers.gsub_single(start,kind,lookupname,replacement)
     return start, true
 end
 
-local function set_alternative_glyph(start,alternatives,kind,chainname,chainlookupname,lookupname) -- chainname and chainlookupname optional
+local function get_alternative_glyph(start,alternatives,value)
     -- needs checking: (global value, brrr)
-    local value  = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
     local choice = nil
     local n      = #alternatives
+    local char   = start.char
     --
     if value == "random" then
         local r = random(1,n)
@@ -447,30 +447,14 @@ local function set_alternative_glyph(start,alternatives,kind,chainname,chainlook
                 value, choice = format("no %s variants, ignoring",value), false
             end
         elseif value == 0 then
-            value, choice = format("choice %s (no change)",value), start.char
+            value, choice = format("choice %s (no change)",value), char
         elseif value < 1 then
             value, choice = format("no %s variants, taking %s",value,1), alternatives[1]
         else
             value, choice = format("choice %s",value), alternatives[value]
         end
     end
-    if trace_alternatives then
-        if choice then
-            logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index)
-        else
-            logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char))
-        end
-    end
-    if choice then
-        start.char = choice
-        if trace_alternatives then
-            logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index)
-        end
-    else
-        if trace_alternatives then
-            logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char))
-        end
-    end
+    return choice
 end
 
 local function multiple_glyphs(start,multiple) -- marks ?
@@ -501,7 +485,18 @@ local function multiple_glyphs(start,multiple) -- marks ?
 end
 
 function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence)
-    set_alternative_glyph(start,alternative,kind,lookupname)
+    local value  = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
+    local choice = get_alternative_glyph(start,alternative,value)
+    if choice then
+        if trace_alternatives then
+            logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice)
+        end
+        start.char = choice
+    else
+        if trace_alternatives then
+            logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char))
+        end
+    end
     return start, true
 end
 
@@ -1102,6 +1097,7 @@ chainmores.gsub_multiple = chainprocs.gsub_multiple
 function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
     local current = start
     local subtables = currentlookup.subtables
+    local value  = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
     while current do
         if current.id == glyph_code then -- is this check needed?
             local currentchar = current.char
@@ -1114,7 +1110,17 @@ function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,look
             else
                 alternatives = alternatives[currentchar]
                 if alternatives then
-                    set_alternative_glyph(current,alternatives,kind,chainname,chainlookupname,lookupname)
+                    local choice = get_alternative_glyph(current,alternatives,value)
+                    if choice then
+                        if trace_alternatives then
+                            logprocess("%s: replacing %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),gref(char),gref(choice),choice)
+                        end
+                        start.char = choice
+                    else
+                        if trace_alternatives then
+                            logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),tostring(value),gref(char))
+                        end
+                    end
                 elseif trace_bugs then
                     logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar))
                 end
diff --git a/tex/context/base/math-vfu.lua b/tex/context/base/math-vfu.lua
index dff7e84fa..c3f234166 100644
--- a/tex/context/base/math-vfu.lua
+++ b/tex/context/base/math-vfu.lua
@@ -421,7 +421,7 @@ end)
 function vfmath.define(specification,set,goodies)
     local name = specification.name -- symbolic name
     local size = specification.size -- given size
-    local loaded, fontlist, main = { }, { }, nil
+    local loaded, fontlist, names, main = { }, { }, { }, nil
     local start = (trace_virtual or trace_timings) and os.clock()
     local okset, n = { }, 0
     for s=1,#set do
@@ -438,7 +438,17 @@ function vfmath.define(specification,set,goodies)
             if ss.main then
                 main = s
             end
-            local f, id = fonts.constructors.readanddefine(ssname,size)
+            local alreadyloaded = names[ssname] -- for px we load one twice (saves .04 sec)
+            local f, id
+            if alreadyloaded then
+                f, id = alreadyloaded.f, alreadyloaded.id
+                if trace_virtual then
+                    report_virtual("loading font %s subfont %s with name %s is reused",name,s,ssname)
+                end
+            else
+                f, id = fonts.constructors.readanddefine(ssname,size)
+                names[ssname] = { f = f, id = id }
+            end
             if not f or id == 0 then
                 report_virtual("loading font %s subfont %s with name %s at %s is skipped, not found",name,s,ssname,size)
             else
@@ -446,7 +456,9 @@ function vfmath.define(specification,set,goodies)
                 okset[n] = ss
                 loaded[n] = f
                 fontlist[n] = { id = id, size = size }
-                if not shared[s] then shared[n] = { } end
+                if not shared[s] then
+                    shared[n] = { }
+                end
                 if trace_virtual then
                     report_virtual("loading font %s subfont %s with name %s at %s as id %s using encoding %s",name,s,ssname,size,id,ss.vector or "none")
                 end
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index f355d9406..d24a42400 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 46b8d7014..307c92c4f 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/syst-aux.mkiv b/tex/context/base/syst-aux.mkiv
index 3a9424098..0438480df 100644
--- a/tex/context/base/syst-aux.mkiv
+++ b/tex/context/base/syst-aux.mkiv
@@ -168,12 +168,14 @@
 
 \let\@@expanded\empty % always long and global (less restores)
 
-\def\expanded#1%
+\unexpanded\def\expanded#1%
   {\xdef\@@expanded{\noexpand#1}\@@expanded}
 
-\def\startexpanded#1\stopexpanded % see x-fo for example
+\unexpanded\def\startexpanded#1\stopexpanded % see x-fo for example
   {\xdef\@@expanded{#1}\@@expanded}
 
+\let\stopexpanded\relax
+
 %D Recent \TEX's have a primitive \expanded
 
 % not yet as we need to adapt ##'s in calls
@@ -3396,7 +3398,7 @@
 \def\@@irecurse{@@ir@@} % ecurse} % stepper
 \def\@@arecurse{@@ar@@} % ecurse} % action
 
-\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
   {\global\advance\outerrecurse \plusone
    \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname{#4}%
    \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
@@ -4420,7 +4422,7 @@
   {\def\dodogotopar{#1}%
    \redogotopar\par}
 
-\def\GetPar
+\unexpanded\def\GetPar
   {\expanded
      {\dowithpar
         {\the\BeforePar
@@ -4429,7 +4431,7 @@
          \BeforePar\emptytoks
          \AfterPar\emptytoks}}}
 
-\def\GotoPar
+\unexpanded\def\GotoPar
   {\expanded
      {\dogotopar
         {\the\BeforePar
@@ -4468,7 +4470,7 @@
 %D   ... \par
 %D \stoptyping
 
-\def\dowithpargument#1%
+\unexpanded\def\dowithpargument#1%
   {\def\nextpar##1 \par{#1{##1}}%
    \def\nextarg##1{#1{##1}}%
    \doifnextbgroupelse\nextarg{\doifnextcharelse\par{#1{}}\nextpar}}
@@ -4495,7 +4497,7 @@
 %D   ...
 %D \stoptyping
 
-\def\dowithwargument#1%
+\unexpanded\def\dowithwargument#1%
   {\def\nextwar##1 {#1{##1}}%
    \def\nextarg##1{#1{##1}}%
    \doifnextbgroupelse\nextarg\nextwar}
@@ -4626,10 +4628,10 @@
 
 \newtoks\@@scratchtoks
 
-\def\appendtoks     {\doappendtoks     \relax}
-\def\prependtoks    {\doprependtoks    \relax}
-\def\appendtoksonce {\doappendtoksonce \relax}
-\def\prependtoksonce{\doprependtoksonce\relax}
+\unexpanded\def\appendtoks     {\doappendtoks     \relax}
+\unexpanded\def\prependtoks    {\doprependtoks    \relax}
+\unexpanded\def\appendtoksonce {\doappendtoksonce \relax}
+\unexpanded\def\prependtoksonce{\doprependtoksonce\relax}
 
 \def\dodoappendtoks
   {\dodoglobal\@@toks\doubleexpandafter{\expandafter\the\expandafter\@@toks\the\@@scratchtoks}}
@@ -4657,7 +4659,7 @@
 
 %D The test macro:
 
-\def\doifintokselse#1#2% #1 en #2 zijn toks
+\unexpanded\def\doifintokselse#1#2% #1 en #2 zijn toks
   {\edef\asciia{\detokenize\expandafter{\the#1}}%
    \edef\asciib{\detokenize\expandafter{\the#2}}%
    \doifstringinstringelse\asciia\asciib}
@@ -4670,7 +4672,7 @@
 % {\scratchtoks{xaa} \removetoks x\from\scratchtoks [\the\scratchtoks]}
 % {\scratchtoks{a\relax b} \removetoks \relax\from\scratchtoks [\showthe\scratchtoks]}
 
-\def\removetoks#1\from#2%
+\unexpanded\def\removetoks#1\from#2%
   {\def\doremovetoks##1#1##2\empty\empty\empty##3\\%
      {\def\!!stringa{##3}%
       \ifx\!!stringa\empty#2{##1}\else#2{##1##2}\fi}%
@@ -4678,8 +4680,8 @@
 
 %D Also:
 
-\def\appendetoks #1\to{\normalexpanded{\noexpand\appendtoks #1}\to}
-\def\prependetoks#1\to{\normalexpanded{\noexpand\prependtoks#1}\to}
+\unexpanded\def\appendetoks #1\to{\normalexpanded{\noexpand\appendtoks #1}\to}
+\unexpanded\def\prependetoks#1\to{\normalexpanded{\noexpand\prependtoks#1}\to}
 
 %D Hm.
 
diff --git a/tex/context/base/tabl-tab.mkiv b/tex/context/base/tabl-tab.mkiv
index 6590c6625..d7e842a62 100644
--- a/tex/context/base/tabl-tab.mkiv
+++ b/tex/context/base/tabl-tab.mkiv
@@ -893,7 +893,7 @@
 
 \def\@VLd{.125em}
 
-\def\do!ttInsertVrule % will be merged in 2005
+\def\do!ttInsertVrule
   {\vrule\!!width
      \ifnum\!tgCode=\plusone
        \ifx\!tgValue\empty
@@ -983,6 +983,9 @@
 \def\donormaltableshortrule % was: \!ttShortHrule
   {\omit
    \!ttGetHalfRuleThickness
+   \ifx\tablecurrenthrulecolor\empty\else
+     \switchtocolor[\tablecurrenthrulecolor]% see *DL*
+   \fi
    \leaders\hrule\!!height\scratchdimen\!!depth\scratchdimen\hfill
    \emptyhbox
    \ignorespaces}
@@ -2055,9 +2058,9 @@
 
 \unexpanded\def\dotableDL
   {\dochecktabledivision
-   \dosingleempty\dotableDL}
+   \dosingleempty\dodotableDL}
 
-\def\dotableDL[#1]%
+\def\dodotableDL[#1]%
   {\ifnum\tableactionstate=\tablerulestate
      \writestatus\m!TABLE{skipping \string\DL}%
    \else
@@ -2072,9 +2075,9 @@
      \iffirstargument
        \global\let\tablecurrenthrulecolor\empty
        \rawprocesscommalist[#1]\dotabledrulecommand
-       \ifx\tablecurrenthrulecolor\empty\else
-         \switchtocolor[\tablecurrenthrulecolor]%
-       \fi
+     % \ifx\tablecurrenthrulecolor\empty\else
+     %   \switchtocolor[\tablecurrenthrulecolor]% see *DL*
+     % \fi
      \fi
      \ifcase\tabledrulespan
        \global\advance\currenttablecolumn \plusone
diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv
index c7b5e7b1b..99d507cf3 100644
--- a/tex/context/base/tabl-tbl.mkiv
+++ b/tex/context/base/tabl-tbl.mkiv
@@ -790,6 +790,8 @@
 % \starttabulate[preamble]
 % \starttabulate -> \starttabulate[|l|p|]
 
+% todo: commandhandler
+
 \def\definetabulate
   {\dotripleempty\dodefinetabulate}
 
@@ -875,7 +877,8 @@
   {\csname\e!start#1::\ifcsname\e!start#1::#2\endcsname#2\fi\endcsname}
 
 \setuvalue{\e!start\v!tabulate}%
-  {\bgroup\dodoubleempty\donormalstarttabulate}
+  {\bgroup % whole thing
+   \dodoubleempty\donormalstarttabulate}
 
 \def\doinhibitnestedtabulate
  {\setuvalue{\e!start\v!tabulate}%
@@ -920,7 +923,7 @@
      \whitespace
      \tabulateparameter\c!before
    \fi
-   \bgroup
+   \bgroup % settings
    \resetcharacteralign
    % todo: spacing around tabulate when bodyfont is set
    % expansion en test needed ?
@@ -1710,12 +1713,12 @@
    %
    \ifcase\tabulaterepeathead
      \ifinsidesplitfloat
-       \setbox\tabulatebox\vbox \bgroup
+       \global\setbox\tabulatebox\vbox \bgroup
       \else
         \startframedcontent[\tabulateparameter\c!frame]%
       \fi
    \else
-     \setbox\tabulatebox\vbox \bgroup
+     \global\setbox\tabulatebox\vbox \bgroup
    \fi
    %
    \dostarttagged\t!tabulate\empty
@@ -1729,19 +1732,23 @@
    %
    \ifcase\tabulaterepeathead
      \ifinsidesplitfloat
-       \egroup \splittabulatebox\tabulatebox
+       \egroup % box
+       \egroup % settings
+       \splittabulatebox\tabulatebox
      \else
        \stopframedcontent
+       \egroup
      \fi
    \else
-     \egroup \splittabulatebox\tabulatebox
+     \egroup % box
+     \egroup % settings
+     \splittabulatebox\tabulatebox
    \fi
    %
-   \egroup
    \ifinsidefloat \else
      \tabulateparameter\c!after
    \fi
-   \egroup}
+   \egroup} % whole thing
 
 % \egroup
 
diff --git a/tex/context/base/typo-mar.lua b/tex/context/base/typo-mar.lua
index 6e941bac0..4d9043424 100644
--- a/tex/context/base/typo-mar.lua
+++ b/tex/context/base/typo-mar.lua
@@ -31,7 +31,7 @@ if not modules then modules = { } end modules ['typo-mar'] = {
 --     whatever[tag] = nil
 -- end
 --
--- function anchors.startmove(tag,how)
+-- function anchors.startmove(tag,how) -- save/restore nodes but they don't support moves
 --     local w = whatever[tag]
 --     if not w then
 --         -- error
@@ -84,93 +84,103 @@ local trace_marginstack = false  trackers.register("typesetters.margindata.stack
 
 local report_margindata = logs.reporter("typesetters","margindata")
 
-local tasks            = nodes.tasks
-local prependaction    = tasks.prependaction
-local disableaction    = tasks.disableaction
-local enableaction     = tasks.enableaction
-
-local variables        = interfaces.variables
-
-local conditionals     = tex.conditionals
-
-local v_top            = variables.top
-local v_depth          = variables.depth
-local v_local          = variables["local"]
-local v_global         = variables["global"]
-local v_left           = variables.left
-local v_right          = variables.right
-local v_flushleft      = variables.flushleft
-local v_flushright     = variables.flushright
-local v_inner          = variables.inner
-local v_outer          = variables.outer
-local v_margin         = variables.margin
-local v_edge           = variables.edge
-local v_default        = variables.default
-local v_normal         = variables.normal
-local v_yes            = variables.yes
-local v_first          = variables.first
-
-local has_attribute    = node.has_attribute
-local set_attribute    = node.set_attribute
-local unset_attribute  = node.unset_attribute
-local copy_node_list   = node.copy_list
-local slide_nodes      = node.slide
-local hpack_nodes      = node.hpack -- nodes.fasthpack not really faster here
-local traverse_id      = node.traverse_id
-local free_node_list   = node.flush_list
-local insert_node_after= node.insert_after
-
-local link_nodes       = nodes.link
-
-local nodecodes        = nodes.nodecodes
-local listcodes        = nodes.listcodes
-local gluecodes        = nodes.gluecodes
-local whatsitcodes     = nodes.whatsitcodes
-
-local hlist_code       = nodecodes.hlist
-local vlist_code       = nodecodes.vlist
-local glue_code        = nodecodes.glue
-local kern_code        = nodecodes.kern
-local penalty_code     = nodecodes.penalty
-local whatsit_code     = nodecodes.whatsit
-local line_code        = listcodes.line
-local leftskip_code    = gluecodes.leftskip
-local rightskip_code   = gluecodes.rightskip
-local userdefined_code = whatsitcodes.userdefined
-
-local dir_code         = whatsitcodes.dir
-local localpar_code    = whatsitcodes.localpar
-
-local nodepool         = nodes.pool
-
-local new_kern         = nodepool.kern
-local new_penalty      = nodepool.penalty
-local new_stretch      = nodepool.stretch
-local new_usernumber   = nodepool.usernumber
-local new_latelua      = nodepool.latelua
-
-local texcount         = tex.count
-local texdimen         = tex.dimen
-local texbox           = tex.box
-
-local isleftpage       = layouts.status.isleftpage
-local registertogether = builders.paragraphs.registertogether
-
-local a_margindata     = attributes.private("margindata")
-
-local inline_mark      = nodepool.userids["margins.inline"]
-
-local margins          =  { }
-typesetters.margins    = margins
-
-local locations        = { v_left, v_right, v_inner, v_outer } -- order might change
-local categories       = { }
-local displaystore     = { } -- [category][location][scope]
-local inlinestore      = { } -- [number]
-local nofsaved         = 0
-local nofstored        = 0
-local nofinlined       = 0
-local nofdelayed       = 0
+local tasks              = nodes.tasks
+local prependaction      = tasks.prependaction
+local disableaction      = tasks.disableaction
+local enableaction       = tasks.enableaction
+
+local variables          = interfaces.variables
+
+local conditionals       = tex.conditionals
+
+local v_top              = variables.top
+local v_depth            = variables.depth
+local v_local            = variables["local"]
+local v_global           = variables["global"]
+local v_left             = variables.left
+local v_right            = variables.right
+local v_flushleft        = variables.flushleft
+local v_flushright       = variables.flushright
+local v_inner            = variables.inner
+local v_outer            = variables.outer
+local v_margin           = variables.margin
+local v_edge             = variables.edge
+local v_default          = variables.default
+local v_normal           = variables.normal
+local v_yes              = variables.yes
+local v_continue         = variables.continue
+local v_first            = variables.first
+
+local has_attribute      = node.has_attribute
+local set_attribute      = node.set_attribute
+local unset_attribute    = node.unset_attribute
+local copy_node_list     = node.copy_list
+local slide_nodes        = node.slide
+local hpack_nodes        = node.hpack -- nodes.fasthpack not really faster here
+local traverse_id        = node.traverse_id
+local free_node_list     = node.flush_list
+local insert_node_after  = node.insert_after
+local insert_node_before = node.insert_before
+
+local link_nodes         = nodes.link
+
+local nodecodes          = nodes.nodecodes
+local listcodes          = nodes.listcodes
+local gluecodes          = nodes.gluecodes
+local whatsitcodes       = nodes.whatsitcodes
+
+local hlist_code         = nodecodes.hlist
+local vlist_code         = nodecodes.vlist
+local glue_code          = nodecodes.glue
+local kern_code          = nodecodes.kern
+local penalty_code       = nodecodes.penalty
+local whatsit_code       = nodecodes.whatsit
+local line_code          = listcodes.line
+local leftskip_code      = gluecodes.leftskip
+local rightskip_code     = gluecodes.rightskip
+local userdefined_code   = whatsitcodes.userdefined
+
+local dir_code           = whatsitcodes.dir
+local localpar_code      = whatsitcodes.localpar
+
+local nodepool           = nodes.pool
+
+local new_kern           = nodepool.kern
+local new_glue           = nodepool.glue
+local new_penalty        = nodepool.penalty
+local new_stretch        = nodepool.stretch
+local new_usernumber     = nodepool.usernumber
+local new_latelua        = nodepool.latelua
+
+local texcount           = tex.count
+local texdimen           = tex.dimen
+local texbox             = tex.box
+
+local points             = number.points
+
+local isleftpage         = layouts.status.isleftpage
+local registertogether   = builders.paragraphs.registertogether
+
+local jobpositions       = job.positions
+local getposition        = jobpositions.position
+
+local a_margindata       = attributes.private("margindata")
+
+local inline_mark        = nodepool.userids["margins.inline"]
+
+local margins            =  { }
+typesetters.margins      = margins
+
+local locations          = { v_left, v_right, v_inner, v_outer } -- order might change
+local categories         = { }
+local displaystore       = { } -- [category][location][scope]
+local inlinestore        = { } -- [number]
+local nofsaved           = 0
+local nofstored          = 0
+local nofinlined         = 0
+local nofdelayed         = 0
+local h_anchors          = 0
+local v_anchors          = 0
 
 local mt1 = {
     __index = function(t,location)
@@ -339,7 +349,7 @@ end
 -- When the prototype inner/outer code that was part of this proved to be
 -- okay it was moved elsewhere.
 
-local status, nofstatus, anchors = { }, 0, 0
+local status, nofstatus = { }, 0
 
 local function realign(current,candidate)
     local location      = candidate.location
@@ -396,15 +406,15 @@ local function realign(current,candidate)
     current.width = 0
 
     if candidate.inline then -- this mess is needed for alignments (combinations)
-        anchors = anchors + 1
-        local anchor = new_latelua(format("_plib_.setraw('_md_:%s',pdf.h)",anchors))
-        local blob_x = job.positions.v("_md_:"..anchors) or 0
-        local text_x = job.positions.x("text:"..tex.count.realpageno) or 0
+        h_anchors = h_anchors + 1
+        local anchor = new_latelua(format("_plib_.setraw('_mh_:%s',pdf.h)",h_anchors))
+        local blob_x = jobpositions.v("_mh_:"..h_anchors) or 0
+        local text_x = jobpositions.x("text:"..texcount.realpageno) or 0
         local move_x = text_x - blob_x
         delta = delta - move_x
         current.list = hpack_nodes(link_nodes(anchor,new_kern(-delta),current.list,new_kern(delta)))
         if trace_margindata then
-            report_margindata("realigned: %s, location: %s, margin: %s, move: %s",candidate.n,location,margin,number.points(move_x))
+            report_margindata("realigned: %s, location: %s, margin: %s, move: %s",candidate.n,location,margin,points(move_x))
         end
     else
         current.list = hpack_nodes(link_nodes(new_kern(-delta),current.list,new_kern(delta)))
@@ -412,7 +422,6 @@ local function realign(current,candidate)
             report_margindata("realigned: %s, location: %s, margin: %s",candidate.n,location,margin)
         end
     end
-
     current.width = 0
 end
 
@@ -424,15 +433,62 @@ local function realigned(current,a)
     return true
 end
 
+-- Stacking is done in two ways: the v_yes option stacks per paragraph (or line,
+-- depending on what gets by) and mostly concerns margin data dat got ste at more or
+-- less the same time. The v_continue option uses position tracking and works on
+-- larger range. However, crossing pages is not part of it. Anyway, when you have
+-- such messed up margin data you'd better think twice.
+--
+-- The stacked table keeps track (per location) of the offsets (the v_yes case). This
+-- table gets saved when the v_continue case is active. We use a special variant
+-- of position tracking, after all we only need the page number and vertical position.
+
 local stacked = { }
+local cache = { }
 
 local function resetstacked()
-    for i=1,#locations do
-        stacked[locations[i]] = false
-    end
+--     for i=1,#locations do
+--         stacked[locations[i]] = false
+--     end
+    stacked = { }
+end
+
+-- resetstacked()
+
+function margins.ha(tag)
+    local p = cache[tag]
+    p.r = texcount.realpageno
+    p.y = pdf.v
+    _plib_.setraw('_mv_:'..tag,p)
+    cache[tag] = nil
+end
+
+local function markovershoot(current)
+    h_anchors = h_anchors + 1
+    cache[h_anchors] = stacked
+    local anchor = new_latelua(format("typesetters.margins.ha(%s)",h_anchors)) -- todo: alleen als offset > line
+    current.list = hpack_nodes(link_nodes(anchor,current.list))
 end
 
-resetstacked()
+local function getovershoot(location)
+    local previous = '_mv_:' .. h_anchors
+    local current  = '_mv_:' .. (h_anchors + 1)
+    local p = jobpositions.v(previous)
+    local c = jobpositions.v(current)
+    if p and c and p.r and p.r == c.r then
+        local distance = p.y - c.y
+        local offset = p[location] or 0
+        local overshoot = offset - distance
+        if trace_marginstack then
+            report_margindata("location: %s, distance: %s, offset: %s, overshoot: %s",
+                location,points(distance),points(offset),points(overshoot))
+        end
+        if overshoot > 0 then
+            return overshoot
+        end
+    end
+    return 0
+end
 
 local function inject(parent,head,candidate)
     local box          = candidate.box
@@ -447,7 +503,7 @@ local function inject(parent,head,candidate)
     local line         = candidate.line
     local baseline     = candidate.baseline
     local offset       = stacked[location]
-    local firstonstack = offset == false
+    local firstonstack = offset == false or offset == nil
     nofstatus          = nofstatus  + 1
     nofdelayed         = nofdelayed + 1
     status[nofstatus]  = candidate
@@ -473,6 +529,9 @@ local function inject(parent,head,candidate)
     if stack == v_yes then
         offset = offset + candidate.dy
         shift = shift + offset
+    elseif stack == v_continue then
+        offset = offset + candidate.dy + getovershoot(location)
+        shift = shift + offset
     end
     -- -- --
     -- Maybe we also need to patch offset when we apply methods, but how ...
@@ -537,21 +596,25 @@ local function inject(parent,head,candidate)
     -- we need to add line etc to offset as well
     offset = offset + depth
     local room = {
-        height = height,
-        depth  = offset,
-        slack  = candidate.bottomspace, -- todo: 'depth' => strutdepth
+        height     = height,
+        depth      = offset,
+        slack      = candidate.bottomspace, -- todo: 'depth' => strutdepth
+        lineheight = candidate.lineheight, -- only for tracing
     }
-offset = offset + height
+    offset = offset + height
     stacked[location] = offset
     -- todo: if no real depth then zero
     if trace_margindata then
         report_margindata("status, offset: %s",offset)
     end
-    return head, room
+    return head, room, stack == v_continue
 end
 
-local function flushinline(parent,head,done)
+local function flushinline(parent,head)
     local current = head
+    local done = false
+    local continue = false
+    local room, don, con
     while current and nofinlined > 0 do
         local id = current.id
         if id == whatsit_code then
@@ -561,24 +624,28 @@ local function flushinline(parent,head,done)
                 if candidate then -- no vpack, as we want to realign
                     inlinestore[n] = nil
                     nofinlined = nofinlined - 1
-                    head = inject(parent,head,candidate) -- maybe return applied offset
+                    head, room, con = inject(parent,head,candidate) -- maybe return applied offset
+                    continue = continue or con
                     done = true
                     nofstored = nofstored - 1
                 end
             end
         elseif id == hlist_code or id == vlist_code then
             -- optional (but sometimes needed)
-            current.list, done = flushinline(current,current.list,done)
+            current.list, don, con = flushinline(current,current.list)
+            continue = continue or con
+            done = done or don
         end
         current = current.next
     end
-    return head, done
+    return head, done, continue
 end
 
 local function flushed(scope,parent) -- current is hlist
-    local done = false
     local head = parent.list
-    local room
+    local done = false
+    local continue = false
+    local room, con, don
     for c=1,#categories do
         local category = categories[c]
         for l=1,#locations do
@@ -587,8 +654,9 @@ local function flushed(scope,parent) -- current is hlist
             while true do
                 local candidate = remove(store,1) -- brr, local stores are sparse
                 if candidate then -- no vpack, as we want to realign
-                    head, room = inject(parent,head,candidate) -- maybe return applied offset
+                    head, room, con = inject(parent,head,candidate)
                     done = true
+                    continue = continue or con
                     nofstored = nofstored - 1
                     registertogether(parent,room)
                 else
@@ -601,13 +669,15 @@ local function flushed(scope,parent) -- current is hlist
         if done then
             parent.list = head
         end
-        head, done = flushinline(parent,head,false)
+        head, don, con = flushinline(parent,head)
+        continue = continue or con
+        done = done or don
     end
     if done then
         parent.list = hpack_nodes(head,parent.width,"exactly")
-        resetstacked()
+     -- resetstacked()
     end
-    return done
+    return done, continue
 end
 
 -- only when group   : vbox|vmode_par
@@ -623,8 +693,12 @@ local function handler(scope,head,group)
         while current do
             local id = current.id
             if (id == vlist_code or id == hlist_code) and not has_attribute(current,a_margindata) then
-                if flushed(scope,current) then
+                local don, continue = flushed(scope,current)
+                if don then
                     set_attribute(current,a_margindata,0) -- signal to prevent duplicate processing
+                    if continue then
+                        markovershoot(current)
+                    end
                     if nofstored <= 0 then
                         break
                     end
@@ -634,7 +708,7 @@ local function handler(scope,head,group)
             current = current.next
         end
      -- if done then
-     --     resetstacked()
+        resetstacked() -- why doesn't done work ok here?
      -- end
         return head, done
     else
diff --git a/tex/context/base/typo-pag.lua b/tex/context/base/typo-pag.lua
index 92c8e2c62..482a3a9f8 100644
--- a/tex/context/base/typo-pag.lua
+++ b/tex/context/base/typo-pag.lua
@@ -24,13 +24,15 @@ local points              = number.points
 
 local a_keeptogether      = attributes.private("keeptogether")
 
-local trace_keeptogether  = false  trackers.register("parbuilders.keeptogether", function(v) trace_keeptogether  = v end)
+local trace_keeptogether  = false
 local report_keeptogether = logs.reporter("parbuilders","keeptogether")
 
 local cache               = { }
 local last                = 0
 local enabled             = false
 
+trackers.register("parbuilders.keeptogether", function(v) trace_keeptogether  = v end)
+
 -- todo: also support lines = 3 etc (e.g. dropped caps) but how to set that
 -- when no hlists are there ? ... maybe the local_par
 
@@ -71,8 +73,17 @@ function builders.paragraphs.registertogether(line,specification) -- might chang
         local a = a or last
         local c = cache[a]
         if trace_keeptogether then
-            report_keeptogether("registered, index: %s, height: %s, depth: %s, slack: %s",
-                a,points(c.height),points(c.depth),points(c.slack))
+            local noflines = specification.lineheight
+            local height = c.height
+            local depth = c.depth
+            local slack = c.slack
+            if not noflines or noflines == 0 then
+                noflines = "unknown"
+            else
+                noflines = math.round((height + depth - slack) / noflines)
+            end
+            report_keeptogether("registered, index: %s, height: %s, depth: %s, slack: %s, noflines: %s",
+                a,points(height),points(depth),points(slack),noflines)
         end
     end
 end
diff --git a/tex/context/fonts/lm-math.lfg b/tex/context/fonts/lm-math.lfg
index e6b64c638..a2c095bc2 100644
--- a/tex/context/fonts/lm-math.lfg
+++ b/tex/context/fonts/lm-math.lfg
@@ -1,3 +1,5 @@
+-- we could consider taking more from 'tex-mr-missing'
+
 -- This patch code is moved from font-pat.lua to this goodies
 -- files as it does not belong in the core code.
 
@@ -188,7 +190,7 @@ local ten = {
 
 local twelve = {
     { name = "lmroman12-regular.otf", features = "virtualmath", main = true },
-    { name = "rm-lmr12.tfm", vector = "tex-mr-missing" } ,
+    { name = "rm-lmr12.tfm", vector = "tex-mr-missing" },
     { name = "lmmi12.tfm", vector = "tex-mi", skewchar=0x7F },
     { name = "lmmi12.tfm", vector = "tex-it", skewchar=0x7F },
     { name = "lmsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } ,
diff --git a/tex/context/fonts/px-math.lfg b/tex/context/fonts/px-math.lfg
index 1d18bad36..afb0270a2 100644
--- a/tex/context/fonts/px-math.lfg
+++ b/tex/context/fonts/px-math.lfg
@@ -11,6 +11,7 @@ return {
         virtuals = {
             ["px-math"] = {
                 { name = "texgyrepagella-regular.otf", features = "virtualmath", main = true },
+                { name = "texgyrepagella-regular.otf", features = "virtualmath", vector = "tex-mr-missing" } ,
                 { name = "rpxr.tfm", vector = "tex-mr" } ,
                 { name = "rpxmi.tfm", vector = "tex-mi", skewchar=0x7F },
                 { name = "rpxpplri.tfm", vector = "tex-it", skewchar=0x7F },
diff --git a/tex/context/fonts/tx-math.lfg b/tex/context/fonts/tx-math.lfg
index 8423aaaf4..2ad173486 100644
--- a/tex/context/fonts/tx-math.lfg
+++ b/tex/context/fonts/tx-math.lfg
@@ -11,6 +11,7 @@ return {
         virtuals = {
             ["tx-math"] = {
                 { name = "texgyretermes-regular.otf", features = "virtualmath", main = true },
+                { name = "texgyretermes-regular.otf", features = "virtualmath", vector = "tex-mr-missing" },
                 { name = "rtxr.tfm", vector = "tex-mr" } ,
                 { name = "rtxptmri.tfm", vector = "tex-it", skewchar=0x7F },
                 { name = "rtxmi.tfm", vector = "tex-mi", skewchar=0x7F },
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 928b9c2d5..8a951089c 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : luatex-fonts-merged.lua
 -- parent file : luatex-fonts.lua
--- merge date  : 11/12/11 12:34:20
+-- merge date  : 11/13/11 23:53:45
 
 do -- begin closure to overcome local limits and interference
 
@@ -8892,11 +8892,11 @@ function handlers.gsub_single(start,kind,lookupname,replacement)
     return start, true
 end
 
-local function set_alternative_glyph(start,alternatives,kind,chainname,chainlookupname,lookupname) -- chainname and chainlookupname optional
+local function get_alternative_glyph(start,alternatives,value)
     -- needs checking: (global value, brrr)
-    local value  = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
     local choice = nil
     local n      = #alternatives
+    local char   = start.char
     --
     if value == "random" then
         local r = random(1,n)
@@ -8919,30 +8919,14 @@ local function set_alternative_glyph(start,alternatives,kind,chainname,chainlook
                 value, choice = format("no %s variants, ignoring",value), false
             end
         elseif value == 0 then
-            value, choice = format("choice %s (no change)",value), start.char
+            value, choice = format("choice %s (no change)",value), char
         elseif value < 1 then
             value, choice = format("no %s variants, taking %s",value,1), alternatives[1]
         else
             value, choice = format("choice %s",value), alternatives[value]
         end
     end
-    if trace_alternatives then
-        if choice then
-            logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index)
-        else
-            logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char))
-        end
-    end
-    if choice then
-        start.char = choice
-        if trace_alternatives then
-            logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index)
-        end
-    else
-        if trace_alternatives then
-            logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char))
-        end
-    end
+    return choice
 end
 
 local function multiple_glyphs(start,multiple) -- marks ?
@@ -8973,7 +8957,18 @@ local function multiple_glyphs(start,multiple) -- marks ?
 end
 
 function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence)
-    set_alternative_glyph(start,alternative,kind,lookupname)
+    local value  = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
+    local choice = get_alternative_glyph(start,alternative,value)
+    if choice then
+        if trace_alternatives then
+            logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice)
+        end
+        start.char = choice
+    else
+        if trace_alternatives then
+            logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char))
+        end
+    end
     return start, true
 end
 
@@ -9574,6 +9569,7 @@ chainmores.gsub_multiple = chainprocs.gsub_multiple
 function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
     local current = start
     local subtables = currentlookup.subtables
+    local value  = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
     while current do
         if current.id == glyph_code then -- is this check needed?
             local currentchar = current.char
@@ -9586,7 +9582,17 @@ function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,look
             else
                 alternatives = alternatives[currentchar]
                 if alternatives then
-                    set_alternative_glyph(current,alternatives,kind,chainname,chainlookupname,lookupname)
+                    local choice = get_alternative_glyph(current,alternatives,value)
+                    if choice then
+                        if trace_alternatives then
+                            logprocess("%s: replacing %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),gref(char),gref(choice),choice)
+                        end
+                        start.char = choice
+                    else
+                        if trace_alternatives then
+                            logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),tostring(value),gref(char))
+                        end
+                    end
                 elseif trace_bugs then
                     logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar))
                 end
-- 
cgit v1.2.3