From d21bf0b75f6e7def14293497c057e6d9267bc8a5 Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Sun, 15 Jun 2014 15:54:00 +0200
Subject: beta 2014.06.15 15:54

---
 tex/context/base/cont-new.mkiv                     |   2 +-
 tex/context/base/context-version.pdf               | Bin 4348 -> 4350 bytes
 tex/context/base/context.mkiv                      |   2 +-
 tex/context/base/lpdf-ano.lua                      |   6 +
 tex/context/base/page-lay.mkiv                     |  15 +-
 tex/context/base/publ-imp-cite.mkiv                |   4 -
 tex/context/base/publ-ini.lua                      | 357 ++++++++++++---------
 tex/context/base/publ-ini.mkiv                     | 141 ++++----
 tex/context/base/status-files.pdf                  | Bin 24902 -> 24867 bytes
 tex/context/base/status-lua.pdf                    | Bin 246856 -> 247262 bytes
 tex/context/base/strc-ref.mkvi                     |  21 ++
 tex/context/sample/samples.tex                     |   1 +
 tex/generic/context/luatex/luatex-fonts-merged.lua |   2 +-
 13 files changed, 324 insertions(+), 227 deletions(-)

(limited to 'tex')

diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index cca80bc32..2daba177b 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{2014.06.13 01:11}
+\newcontextversion{2014.06.15 15:54}
 
 %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 d2dea43e7..3d9a12dea 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 c8ebab07e..816e5a6d2 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -28,7 +28,7 @@
 %D up and the dependencies are more consistent.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2014.06.13 01:11}
+\edef\contextversion{2014.06.15 15:54}
 \edef\contextkind   {beta}
 
 %D For those who want to use this:
diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua
index ab3a74053..14359e2c7 100644
--- a/tex/context/base/lpdf-ano.lua
+++ b/tex/context/base/lpdf-ano.lua
@@ -157,6 +157,9 @@ local pagereferences   = allocate() -- annots are cached themselves
 
 setmetatableindex(pagedestinations, function(t,k)
     k = tonumber(k)
+    if not k or k <= 0 then
+        return pdfnull()
+    end
     local v = rawget(t,k)
     if v then
      -- report_reference("page number expected, got %s: %a",type(k),k)
@@ -172,6 +175,9 @@ end)
 
 setmetatableindex(pagereferences,function(t,k)
     k = tonumber(k)
+    if not k or k <= 0 then
+        return nil
+    end
     local v = rawget(t,k)
     if v then
         return v
diff --git a/tex/context/base/page-lay.mkiv b/tex/context/base/page-lay.mkiv
index 19f237242..ccb60f1e8 100644
--- a/tex/context/base/page-lay.mkiv
+++ b/tex/context/base/page-lay.mkiv
@@ -1505,15 +1505,18 @@
 %   [ \c!width=\paperwidth,
 %    \c!height=\paperheight]
 
+\setuppapersize
+  [\c!distance=1.5cm] % offset is already taken
+
 \definepapersize
   [oversized]
-  [ \c!width=\dimexpr\paperwidth +1.5cm\relax,
-   \c!height=\dimexpr\paperheight+1.5cm\relax]
+  [ \c!width=\dimexpr\paperwidth +\layouttargetparameter\c!distance\relax,
+   \c!height=\dimexpr\paperheight+\layouttargetparameter\c!distance\relax]
 
 \definepapersize
   [undersized]
-  [ \c!width=\dimexpr\paperwidth -1.5cm\relax,
-   \c!height=\dimexpr\paperheight-1.5cm\relax]
+  [ \c!width=\dimexpr\paperwidth -\layouttargetparameter\c!distance\relax,
+   \c!height=\dimexpr\paperheight-\layouttargetparameter\c!distance\relax]
 
 \definepapersize
   [doublesized]
@@ -1522,8 +1525,8 @@
 
 \definepapersize
   [doubleoversized]
-  [ \c!width=\dimexpr \paperheight+1.5cm\relax,
-   \c!height=\dimexpr2\paperwidth +1.5cm\relax]
+  [ \c!width=\dimexpr \paperheight+\layouttargetparameter\c!distance\relax,
+   \c!height=\dimexpr2\paperwidth +\layouttargetparameter\c!distance\relax]
 
 % \setuppapersize
 %   [A4][A4]
diff --git a/tex/context/base/publ-imp-cite.mkiv b/tex/context/base/publ-imp-cite.mkiv
index d758675fa..e0b284624 100644
--- a/tex/context/base/publ-imp-cite.mkiv
+++ b/tex/context/base/publ-imp-cite.mkiv
@@ -69,7 +69,6 @@
         \directsetup{\s!btx:\s!cite:\s!unknown}
     \else\ifconditional\btxinteractive
         \goto {
-            \btxcitereference
             \currentbtxfirst
             \ifx\currentbtxsecond\empty \else
                 \btxcitevariantparameter\v!inbetween
@@ -93,7 +92,6 @@
         \directsetup{\s!btx:\s!cite:missing}
     \else\ifconditional\btxinteractive
         \goto {
-            \btxcitereference
             \currentbtxfirst
             \ifx\currentbtxsecond\empty \else
                 \btxcitevariantparameter\c!range
@@ -115,7 +113,6 @@
     \directsetup{\s!btx:\s!cite:concat}
     \ifconditional\btxinteractive
         \goto {
-            \btxcitereference
             \directsetup{\s!btx:\s!cite:render:\currentbtxcitevariant}
         } [
             \s!internal(\currentbtxinternal)
@@ -224,7 +221,6 @@
         \directsetup{\s!btx:\s!cite:\s!unknown}
     \else\ifconditional\btxinteractive
         \goto {
-            \btxcitereference
             \hyphenatedurl{\currentbtxfirst}
         } [
             url(\currentbtxfirst)
diff --git a/tex/context/base/publ-ini.lua b/tex/context/base/publ-ini.lua
index 0cfda11a2..f6567402d 100644
--- a/tex/context/base/publ-ini.lua
+++ b/tex/context/base/publ-ini.lua
@@ -18,7 +18,7 @@ local settings_to_array, settings_to_set = utilities.parsers.settings_to_array,
 local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash
 local setmetatableindex = table.setmetatableindex
 local lpegmatch = lpeg.match
-local P, C, Ct, R = lpeg.P, lpeg.C, lpeg.Ct, lpeg.R
+local P, C, Ct, R, Carg = lpeg.P, lpeg.C, lpeg.Ct, lpeg.R, lpeg.Carg
 
 local report           = logs.reporter("publications")
 local report_cite      = logs.reporter("publications","cite")
@@ -107,6 +107,8 @@ local ctx_btxcitesetup            = context.btxcitesetup
 local ctx_btxsetfirst             = context.btxsetfirst
 local ctx_btxsetsecond            = context.btxsetsecond
 local ctx_btxsetinternal          = context.btxsetinternal
+local ctx_btxsetbacklink          = context.btxsetbacklink
+local ctx_btxsetbacktrace         = context.btxsetbacktrace
 local ctx_btxsetconcat            = context.btxsetconcat
 local ctx_btxstartsubcite         = context.btxstartsubcite
 local ctx_btxstopsubcite          = context.btxstopsubcite
@@ -209,7 +211,7 @@ local function finalizer()
         local used   = { }
         for i=1,#sources do
             local source = sources[i]
---             if loaded[source.filename] ~= "previous" then
+         -- if loaded[source.filename] ~= "previous" then -- needs checking
             if loaded[source.filename] ~= "previous" or loaded[source.filename] == "current" then
                 used[#used+1] = source
             end
@@ -250,47 +252,59 @@ if not publications.authors then
     initializer() -- for now, runtime loaded
 end
 
-local usedentries = { }
-local initialized = false
-
---  {
---   ["metadata"]=1,
---   ["references"]={
---    ["block"]="bodypart",
---    ["internal"]=2,
---    ["realpage"]=1,
---    ["section"]=0,
---   },
---   ["userdata"]={
---    ["btxref"]="Cleveland1985",
---    ["btxset"]="standard",
---   },
---  },
+local initialized  = false
+local usedentries  = { }
+local citetolist   = { }
+local listtocite   = { }
+local nofcitations = 0
 
 setmetatableindex(usedentries,function(t,k)
     if not initialized then
         usedentries = { }
+        citetolist  = { }
+        listtocite  = { }
         local internals = structures.references.internals
+        local p_collect = (C(R("09")^1) * Carg(1) / function(s,entry) listtocite[tonumber(s)] = entry end + P(1))^0
         for i=1,#internals do
             local entry = internals[i]
             if entry then
                 local metadata = entry.metadata
-                if metadata and metadata.kind == "full" then
-                    local userdata = entry.userdata
-                    if userdata then
-                        local set = userdata.btxset
-                        if set then
-                            local tag = userdata.btxref
-                            local s = usedentries[set]
-                            if s then
-                                local u = s[tag]
-                                if u then
-                                    u[#u+1] = entry
+                if metadata then
+                    local kind = metadata.kind
+                    if kind == "full" then
+                        local userdata = entry.userdata
+                        if userdata then
+                            local set = userdata.btxset
+                            if set then
+                                local tag = userdata.btxref
+                                local s = usedentries[set]
+                                if s then
+                                    local u = s[tag]
+                                    if u then
+                                        u[#u+1] = entry
+                                    else
+                                        s[tag] = { entry }
+                                    end
                                 else
-                                    s[tag] = { entry }
+                                    usedentries[set] = { [tag] = { entry } }
+                                end
+                                local bck = userdata.btxbck
+                                if bck then
+                                    lpegmatch(p_collect,bck,1,entry) -- for s in string.gmatch(bck,"[^ ]+") do listtocite[tonumber(s)] = entry end
+                                else
+                                    local int = userdata.btxint
+                                    if int then
+                                        listtocite[tonumber(int)] = entry
+                                    end
                                 end
-                            else
-                                usedentries[set] = { [tag] = { entry } }
+                            end
+                        end
+                    elseif kind == "userdata" then
+                        local userdata = entry.userdata
+                        if userdata then
+                            local int = userdata.btxint
+                            if int then
+                                citetolist[tonumber(int)] = entry
                             end
                         end
                     end
@@ -298,7 +312,6 @@ setmetatableindex(usedentries,function(t,k)
             else
                 -- weird
             end
-         -- table.save("temp.lua",usedentries)
         end
         return usedentries[k]
     end
@@ -316,7 +329,7 @@ end)
 local reported = { }
 local finder   = publications.finder
 
-local function findallused(dataset,reference,block,section)
+local function findallused(dataset,reference,internal)
     local finder = publications.finder -- for the moment, not yes in all betas
     local find   = finder and finder(reference)
     local tags   = not find and settings_to_array(reference)
@@ -333,8 +346,34 @@ local function findallused(dataset,reference,block,section)
                 if #entry == 1 then
                     entry = entry[1]
                 else
-                    -- find best match (todo)
-                    entry = entry[1] -- for now
+                    -- same block and section
+                    local done = false
+                    if internal and internal > 0 then
+                        -- first following in list
+                        for i=1,#entry do
+                            local e = entry[i]
+                            if e.references.internal > internal then
+                                done = e
+                                break
+                            end
+                        end
+                        if not done then
+                            -- last preceding in list
+                            for i=1,#entry do
+                                local e = entry[i]
+                                if e.references.internal > internal then
+                                    break
+                                else
+                                    done = e
+                                end
+                            end
+                        end
+                    end
+                    if done then
+                        entry = done
+                    else
+                        entry = entry[1]
+                    end
                 end
                 okay[#okay+1] = entry
             end
@@ -342,7 +381,7 @@ local function findallused(dataset,reference,block,section)
         end
         if find then
             tags = { }
-            for tag, entry in next, valid do
+            for tag, entry in sortedhash(valid) do
                 local found = find(entry)
                 if found then
                     register(tag)
@@ -363,7 +402,7 @@ local function findallused(dataset,reference,block,section)
     else
         if find then
             tags = { }
-            for tag, entry in next, valid do
+            for tag, entry in sortedhash(valid) do
                 local found = find(entry)
                 if found then
                     todo[tag] = true
@@ -402,11 +441,11 @@ local function flushcollected(reference,flush,nofcollected)
     end
 end
 
-local function markcite(dataset,tag)
+local function markcite(dataset,tag,internal)
     if trace_cite then
-        report_cite("mark, dataset: %s, tag: %s",dataset,tag)
+        report_cite("mark, dataset: %s, tag: %s, internal: %s",dataset,tag,internal)
     end
-    ctx_btxdomarkcitation(dataset,tag)
+    ctx_btxdomarkcitation(dataset,tag,internal or 0)
 end
 
 local function flushmarked(dataset,list,todo)
@@ -414,7 +453,7 @@ local function flushmarked(dataset,list,todo)
         for i=1,#list do
             local tag = list[i]
             if todo[tag] then
-                markcite(dataset,tag)
+                markcite(dataset,tag,0)
             end
         end
     end
@@ -871,32 +910,36 @@ function lists.collectentries(specification)
     local list    = rendering.list
     local done    = rendering.done
     local alldone = rendering.alldone
-    if method == v_local then
+    local traced  = { }
+    if method == v_local or method == v_global then
+        local anyway = method == v_local
         for listindex=1,#result do
             local r = result[listindex]
             local u = r.userdata
             if u and u.btxset == dataset then
                 local tag = u.btxref
-                if tag and done[tag] ~= section then
-                    if not keyword or validkeyword(dataset,tag,keyword) then
-                        done[tag]     = section
-                        alldone[tag]  = true
-                        list[#list+1] = { tag, listindex }
-                    end
-                end
-            end
-        end
-    elseif method == v_global then
-        for listindex=1,#result do
-            local r = result[listindex]
-            local u = r.userdata
-            if u and u.btxset == dataset then
-                local tag = u.btxref
-                if tag and not alldone[tag] and done[tag] ~= section then
-                    if not keyword or validkeyword(dataset,tag,keyword) then
-                        done[tag]     = section
-                        alldone[tag]  = true
-                        list[#list+1] = { tag, listindex }
+                if tag then
+                    if traced then
+                        if not keyword or validkeyword(dataset,tag,keyword) then
+                            done[tag]     = section
+                            alldone[tag]  = true
+                            local l = traced[tag]
+                            if l then
+                                l[#l+1] = u.btxint
+                            else
+                                local l = { tag, listindex, u.btxint }
+                                list[#list+1] = l
+                                traced[tag] = l
+                            end
+                        end
+                    else
+                        if done[tag] ~= section then
+                            if not keyword or validkeyword(dataset,tag,keyword) then
+                                done[tag]     = section
+                                alldone[tag]  = true
+                                list[#list+1] = { tag, listindex, u.btxint }
+                            end
+                        end
                     end
                 end
             end
@@ -909,10 +952,8 @@ function lists.collectentries(specification)
             local u = r.userdata
             if u and u.btxset == dataset then
                 local tag = u.btxref
-                if tag then
-                    if not keyword or validkeyword(dataset,tag,keyword) then
-                        list[#list+1] = { tag, listindex }
-                    end
+                if tag and (not keyword or validkeyword(dataset,tag,keyword)) then
+                    list[#list+1] = { tag, listindex, u.btxint }
                 end
             end
         end
@@ -999,7 +1040,8 @@ function lists.flushentries(dataset,sortvariant)
  -- local details = datasets[dataset].details
     for i=1,#list do
      -- we can pass i here too ... more efficient to avoid the setvalue
-        local tag = list[i][1]
+        local li = list[i]
+        local tag = li[1]
         local entry = luadata[tag]
         if entry then
             ctx_btxsetindex(i)
@@ -1009,11 +1051,22 @@ function lists.flushentries(dataset,sortvariant)
             end
             ctx_btxsetcategory(entry.category or "unknown")
             ctx_btxsettag(tag)
-            ctx_btxhandlelistentry()
             local language = entry.language
             if language then
                 ctx_btxsetlanguage(language)
             end
+            local bl = li[3]
+            if bl and bl ~= "" then
+                ctx_btxsetbacklink(bl)
+                ctx_btxsetbacktrace(concat(li," ",3))
+                local uc = citetolist[tonumber(bl)]
+                if uc then
+                    ctx_btxsetinternal(uc.references.internal or "")
+                end
+            else
+                -- nothing
+            end
+            ctx_btxhandlelistentry()
         end
      end
 end
@@ -1046,35 +1099,34 @@ function lists.doifalreadyplaced(dataset,tag)
     commands.doifelse(renderings[dataset].used[tag])
 end
 
-local function compare(a,b)
-    local aa, bb = a and a[3], b and b[3]
-    return aa and bb and aa < bb
-end
-
-local f_citereference = formatters["btx:cite:%s"]
-local f_listreference = formatters["btx:list:%s"]
-
-local nofcite = 0
-local noflist = 0
-
-function commands.btxcitereference(internal)
-    nofcite = nofcite + 1
-    local ref = f_citereference(nofcite)
-    if trace_references then
-        report_reference("cite: %s",ref)
-    end
-    ctx_btxsetcitereference(ref,internal)
-end
-
-function commands.btxlistreference(dataset,block,tag,data)
-    noflist = noflist + 1
-    local ref = f_listreference(noflist)
-    if trace_references then
-        report_reference("list: %s",ref)
-    end
-    ctx_btxsetlistreference(dataset,tag,ref,data)
-end
+-- local function compare(a,b)
+--     local aa, bb = a and a[3], b and b[3]
+--     return aa and bb and aa < bb
+-- end
 
+-- local f_citereference = formatters["btx:cite:%s"]
+-- local f_listreference = formatters["btx:list:%s"]
+--
+-- local nofcite = 0
+-- local noflist = 0
+--
+-- function commands.btxcitereference(internal)
+--     nofcite = nofcite + 1
+--     local ref = f_citereference(nofcite)
+--     if trace_references then
+--         report_reference("cite: %s",ref)
+--     end
+--     ctx_btxsetcitereference(ref,internal) -- second goes away
+-- end
+--
+-- function commands.btxlistreference(dataset,tag,data)
+--     noflist = noflist + 1
+--     local ref = f_listreference(noflist)
+--     if trace_references then
+--         report_reference("list: %s",ref)
+--     end
+--     ctx_btxsetlistreference(dataset,tag,ref,data)
+-- end
 
 commands.btxsetlistmethod           = lists.setmethod
 commands.btxresolvelistreference    = lists.resolve
@@ -1130,11 +1182,12 @@ function commands.btxhandlecite(specification)
         return
     end
     --
-    local dataset   = specification.dataset or ""
-    local mark      = specification.markentry ~= false
-    local variant   = specification.variant or "num"
-    local sorttype  = specification.sorttype
-    local compress  = specification.compress == v_yes
+    local dataset  = specification.dataset or "" -- standard
+    local mark     = specification.markentry ~= false
+    local variant  = specification.variant or "num"
+    local sorttype = specification.sorttype
+    local compress = specification.compress == v_yes
+    local internal = specification.internal or 0
     --
     local prefix, rest = lpegmatch(prefixsplitter,tag)
     if rest then
@@ -1147,7 +1200,7 @@ function commands.btxhandlecite(specification)
         report_cite("inject, dataset: %s, tag: %s, variant: %s, compressed",dataset or "-",rest,variant)
     end
     ctx_setvalue("currentbtxdataset",dataset)
-    action(dataset,rest,mark,compress,variant)
+    action(dataset,rest,mark,compress,variant,internal) -- maybe pass a table
 end
 
 function commands.btxhandlenocite(specification)
@@ -1172,7 +1225,7 @@ function commands.btxhandlenocite(specification)
         report_cite("mark, dataset: %s, tags: % | t",dataset or "-",tags)
     end
     for i=1,#tags do
-        markcite(dataset,tags[i])
+        markcite(dataset,tags[i],0)
     end
 end
 
@@ -1282,9 +1335,9 @@ local f_missing  = formatters["<%s>"]
 
 -- maybe also sparse (e.g. pages)
 
-local function processcite(dataset,reference,mark,compress,setup,getter,setter,compressor)
+local function processcite(dataset,reference,mark,compress,setup,internal,getter,setter,compressor)
     reference = publications.parenttag(dataset,reference)
-    local found, todo, list = findallused(dataset,reference)
+    local found, todo, list = findallused(dataset,reference,internal)
     if found and setup then
         local source = { }
         local badkey = false
@@ -1311,6 +1364,7 @@ local function processcite(dataset,reference,mark,compress,setup,getter,setter,c
         if compress and not badkey then
             local target  = (compressor or compresslist)(source)
             local function flush(i,state)
+                nofcitations = nofcitations + 1
                 local entry = target[i]
                 local first = entry.first
                 if first then
@@ -1318,15 +1372,14 @@ local function processcite(dataset,reference,mark,compress,setup,getter,setter,c
                     if mark then
                         for i=1,#tags do
                             local tag = tags[i]
-                            markcite(dataset,tag)
+                            markcite(dataset,tag,nofcitations)
                             todo[tag] = false
                         end
                     end
                     ctx_btxsettag(tags[1])
-                    local internal = first.internal
-                    if internal then
-                        ctx_btxsetinternal(internal)
-                    end
+                    ctx_btxsetbacklink(nofcitations)
+                    local bl = listtocite[nofcitations]
+                    ctx_btxsetinternal(bl and bl.references.internal or 0)
                     local language = first.language
                     if language then
                         ctx_btxsetlanguage(language)
@@ -1337,14 +1390,13 @@ local function processcite(dataset,reference,mark,compress,setup,getter,setter,c
                 else
                     local tag = entry.tag
                     if mark then
-                        markcite(dataset,tag)
+                        markcite(dataset,tag,nofcitations)
                         todo[tag] = false
                     end
                     ctx_btxsettag(tag)
-                    local internal = entry.internal
-                    if internal then
-                        ctx_btxsetinternal(internal)
-                    end
+                    ctx_btxsetbacklink(nofcitations)
+                    local bl = listtocite[nofcitations]
+                    ctx_btxsetinternal(bl and bl.references.internal or 0)
                     local language = entry.language
                     if language then
                         ctx_btxsetlanguage(language)
@@ -1359,17 +1411,17 @@ local function processcite(dataset,reference,mark,compress,setup,getter,setter,c
             flushcollected(reference,flush,#target)
         else
             local function flush(i,state)
+                nofcitations = nofcitations + 1
                 local entry = source[i]
                 local tag   = entry.tag
                 if mark then
-                    markcite(dataset,tag)
+                    markcite(dataset,tag,nofcitations)
                     todo[tag] = false
                 end
                 ctx_btxsettag(tag)
-                local internal = entry.internal
-                if internal then
-                    ctx_btxsetinternal(internal)
-                end
+                ctx_btxsetbacklink(nofcitations)
+                local bl = listtocite[nofcitations]
+                ctx_btxsetinternal(bl and bl.references.internal or 0)
                 local language = entry.language
                 if language then
                     ctx_btxsetlanguage(language)
@@ -1430,8 +1482,8 @@ setmetatableindex(citevariants,function(t,k)
     return v
 end)
 
-function citevariants.default(dataset,reference,mark,compress,variant,setup)
-    processcite(dataset,reference,mark,compress,setup or variant,setters[variant],getters[variant])
+function citevariants.default(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,variant,internal,setters[variant],getters[variant])
 end
 
 -- short
@@ -1458,8 +1510,8 @@ local function getter(first,last) -- last not used
     end
 end
 
-function citevariants.short(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,false,"short",setter,getter)
+function citevariants.short(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,false,"short",internal,setter,getter)
 end
 
 -- pages (no compress)
@@ -1486,14 +1538,15 @@ local function getter(first,last)
     end
 end
 
-function citevariants.page(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"page",setter,getter)
+function citevariants.page(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"page",internal,setter,getter)
 end
 
 -- num
 
 local function setter(dataset,tag,entry,internal)
-    local text = entry.entries.text
+    local entries = entry.entries
+    local text = entries and entries.text or "?"
     return {
         dataset  = dataset,
         tag      = tag,
@@ -1507,8 +1560,8 @@ local function getter(first,last)
     return simplegetter(first,last,"num")
 end
 
-function citevariants.num(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"num",setter,getter)
+function citevariants.num(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"num",internal,setter,getter)
 end
 
 -- year
@@ -1529,8 +1582,8 @@ local function getter(first,last)
     return simplegetter(first,last,"year")
 end
 
-function citevariants.year(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"year",setter,getter)
+function citevariants.year(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"year",internal,setter,getter)
 end
 
 -- index | serial
@@ -1550,12 +1603,12 @@ local function getter(first,last)
     return simplegetter(first,last,"index")
 end
 
-function citevariants.index(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"index",setter,getter)
+function citevariants.index(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"index",internal,setter,getter)
 end
 
-function citevariants.serial(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"serial",setter,getter)
+function citevariants.serial(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"serial",internal,setter,getter)
 end
 
 -- category | type
@@ -1573,12 +1626,12 @@ local function getter(first,last)
     return simplegetter(first,last,"category")
 end
 
-function citevariants.category(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"category",setter,getter)
+function citevariants.category(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"category",internal,setter,getter)
 end
 
-function citevariants.type(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"type",setter,getter)
+function citevariants.type(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"type",internal,setter,getter)
 end
 
 -- key | tag
@@ -1596,12 +1649,12 @@ local function getter(first,last)
     return true
 end
 
-function citevariants.key(dataset,reference,mark,compress) return
-    processcite(dataset,reference,mark,compress,"key",setter,getter)
+function citevariants.key(dataset,reference,mark,compress,variant,internal)
+    return processcite(dataset,reference,mark,compress,"key",internal,setter,getter)
 end
 
-function citevariants.tag(dataset,reference,mark,compress) return
-    processcite(dataset,reference,mark,compress,"tag",setter,getter)
+function citevariants.tag(dataset,reference,mark,compress,variant,internal)
+    return processcite(dataset,reference,mark,compress,"tag",internal,setter,getter)
 end
 
 -- author
@@ -1620,8 +1673,8 @@ local function getter(first,last)
     return true
 end
 
-function citevariants.author(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,false,"author",setter,getter)
+function citevariants.author(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,false,"author",internal,setter,getter)
 end
 
 -- todo : sort
@@ -1749,8 +1802,8 @@ local function compressor(found)
     return authorcompressor(found,"num")
 end
 
-function citevariants.authornum(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"authornum",setter,getter,compressor)
+function citevariants.authornum(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"authornum",internal,setter,getter,compressor)
 end
 
 -- authoryear | authoryears
@@ -1777,8 +1830,8 @@ local function compressor(found)
     return authorcompressor(found,"year")
 end
 
-function citevariants.authoryear(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"authoryear",setter,getter,compressor)
+function citevariants.authoryear(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"authoryear",internal,setter,getter,compressor)
 end
 
 local function getter(first,last)
@@ -1786,8 +1839,8 @@ local function getter(first,last)
     return true
 end
 
-function citevariants.authoryears(dataset,reference,mark,compress)
-    processcite(dataset,reference,mark,compress,"authoryears",setter,getter,compressor)
+function citevariants.authoryears(dataset,reference,mark,compress,variant,internal)
+    processcite(dataset,reference,mark,compress,"authoryears",internal,setter,getter,compressor)
 end
 
 -- List variants
diff --git a/tex/context/base/publ-ini.mkiv b/tex/context/base/publ-ini.mkiv
index 107e23122..f70628bad 100644
--- a/tex/context/base/publ-ini.mkiv
+++ b/tex/context/base/publ-ini.mkiv
@@ -55,6 +55,11 @@
 \def\v!btxlist      {btxlist}
 \def\v!btxrendering {btxrendering}
 
+\def\s!btxset       {btxset}
+\def\s!btxref       {btxref}
+\def\s!btxint       {btxint}
+\def\s!btxbck       {btxbck}
+
 \definelabelclass[btxlabel][2]
 
 % a dedicated construction mechanism
@@ -97,7 +102,6 @@
 
 \unexpanded\setvalue{\??constructiontexthandler\v!btxlist}%
   {\begingroup
-   \xdef\btxcurrentlistinternal{\the\numexpr\locationcount+\plusone)}% \nextinternalreference
    \directsetup{\v!btxrendering:\v!number:\constructionparameter\c!number}%
    \endgroup}
 
@@ -112,7 +116,7 @@
    \iflocation
      \goto
        {\publ_list_number_normal}%
-       [\s!internal(\btxcurrentlistinternal)]%
+       [\s!internal(\currentbtxinternal)]%
    \else
      \publ_list_number_normal
    \fi
@@ -124,8 +128,6 @@
    \btx_list_reference_inject
    \relax}
 
-\let\btxcurrentlistinternal\relax
-
 % todo: low level builder commands without using the constructor
 
 % construction
@@ -203,7 +205,6 @@
 \installcorenamespace {btxnumbering}
 \installcorenamespace {btxrenderingdefinition}
 
-
 \installcommandhandler \??btxdataset     {btxdataset}     \??btxdataset
 \installcommandhandler \??btxlistvariant {btxlistvariant} \??btxlistvariant
 \installcommandhandler \??btxcitevariant {btxcitevariant} \??btxcitevariant
@@ -287,6 +288,15 @@
 \unexpanded\def\definebtxcommand#1% {body} #1..#n{body}
   {\setuvalue{\??btxcommand\strippedcsname#1}}%
 
+% tracing
+
+\installtextracker
+  {publications.crosslinks}
+  {\let\btx_trace_list_cross\strc_references_tracer}
+  {\let\btx_trace_list_cross\gobbletwoarguments}
+
+\let\btx_trace_list_cross\gobbletwoarguments
+
 % access
 
 \let\currentbtxtag    \empty
@@ -298,7 +308,8 @@
 \unexpanded\def\setbtxentry[#1]%
   {\edef\currentbtxtag{\ctxcommand{setbtxentry("\currentbtxdataset","#1")}}}
 
-\setbtxdataset[\v!standard]
+\setbtxdataset
+  [\v!standard]
 
 % \let\btxsetdataset\setbtxdataset
 % \let\btxsetentry  \setbtxentry
@@ -366,8 +377,8 @@
 %newdimen\d_publ_number_distance
 
 \ifdefined\btxblock       \else \newcount\btxblock       \fi \btxblock\plusone
-\ifdefined\btxlistcounter \else \newcount\btxlistcounter \fi
-\ifdefined\btxcitecounter \else \newcount\btxcitecounter \fi
+\ifdefined\btxlistcounter \else \newcount\btxlistcounter \fi % maintaned here, maybe in lua too?
+\ifdefined\btxcitecounter \else \newcount\btxcitecounter \fi % maybe pass this to lua
 
 \newtoks \everysetupbtxlistplacement % name will change
 \newtoks \everysetupbtxciteplacement % name will change
@@ -524,20 +535,34 @@
 \def\publ_place_list_entry_register
   {\ctxcommand{btxregisterlistentry("\currentbtxdataset","\currentbtxtag")}}
 
+\unexpanded\def\btxchecklistentry#1% called at the lua end
+  {\begingroup
+   \edef\currentbtxtag{#1}%
+   \ifx\currentbtxcriterium\v!all % move this check to lua ... easier to test there anyway
+     \publ_check_list_entry
+   \else
+     \ctxcommand{btxdoifelselistentryplaced("\currentbtxdataset","\currentbtxtag")}\donothing\publ_check_list_entry
+   \fi
+   \endgroup}
+
 \unexpanded\def\btxlistreset
-  {\let\currentbtxindex   \!!zerocount
-   \let\currentbtxcombis  \empty
-   \let\currentbtxcategory\empty
-   \let\currentbtxinternal\empty
-   \let\currentbtxlanguage\empty
-   \let\currentbtxtag     \empty}
-
-\unexpanded\def\btxsetindex   {\def\currentbtxindex}
-\unexpanded\def\btxsetcombis  {\def\currentbtxcombis}
-\unexpanded\def\btxsetcategory{\def\currentbtxcategory}
-\unexpanded\def\btxsetinternal{\def\currentbtxinternal}
-%unexpanded\def\btxsetlanguage{\def\currentbtxlanguage}
-\unexpanded\def\btxsettag     {\def\currentbtxtag}
+  {\let\currentbtxindex    \!!zerocount
+   \let\currentbtxcombis   \empty
+   \let\currentbtxcategory \empty
+   \let\currentbtxinternal \empty
+   \let\currentbtxbacklink \empty
+   \let\currentbtxbacktrace\empty
+   \let\currentbtxlanguage \empty
+   \let\currentbtxtag      \empty}
+
+\unexpanded\def\btxsetindex    {\def\currentbtxindex}
+\unexpanded\def\btxsetcombis   {\def\currentbtxcombis}
+\unexpanded\def\btxsetcategory {\def\currentbtxcategory}
+\unexpanded\def\btxsetinternal {\def\currentbtxinternal}
+\unexpanded\def\btxsetbacklink {\def\currentbtxbacklink}
+\unexpanded\def\btxsetbacktrace{\def\currentbtxbacktrace}
+%unexpanded\def\btxsetlanguage {\def\currentbtxlanguage}
+\unexpanded\def\btxsettag      {\def\currentbtxtag}
 
 \unexpanded\def\btxsetlanguage#1%
   {\def\currentbtxlanguage{#1}%
@@ -569,47 +594,44 @@
      \btx_entry_inject
    \stopbtxlistentry}
 
-\unexpanded\def\btxchecklistentry#1% called at the lua end
-  {\begingroup
-   \edef\currentbtxtag{#1}%
-   \ifx\currentbtxcriterium\v!all % move this check to lua ... easier to test there anyway
-     \publ_check_list_entry
-   \else
-     \ctxcommand{btxdoifelselistentryplaced("\currentbtxdataset","\currentbtxtag")}\donothing\publ_check_list_entry
-   \fi
-   \endgroup}
-
 \unexpanded\def\publ_check_list_entry
   {\global\advance\btxlistcounter\plusone
    % todo, switch to font
    \hbox{\btx_reference_checked}%
    \par}
 
-\unexpanded\def\btx_list_reference_inject % we can use a faster \reference
+\unexpanded\def\btx_reference_checked
+  {\dontleavehmode\hbox\bgroup
+     \btx_list_reference_inject_indeed
+   \egroup}
+
+\newcount\c_btx_list_reference
+
+\unexpanded\def\btx_list_reference_inject
   {\dontleavehmode\begingroup % no box
      \iftrialtypesetting\else
-       \ctxcommand{btxlistreference("\currentbtxdataset","\currentbtxblock","\currentbtxtag","\number\btxlistcounter")}%
+       \btx_list_reference_inject_now
      \fi
-     \btx_list_reference_inject_indeed
+     \btx_list_reference_inject_indeed % needs checking ... still needed?
    \endgroup}
 
-\unexpanded\def\btx_reference_checked
-  {\dontleavehmode\hbox\bgroup
-     \btx_list_reference_inject_indeed
-   \egroup}
+\def\btx_list_reference_inject_now
+  {\btx_trace_list_cross\empty\currentbtxbacktrace
+   \global\advance\c_btx_list_reference\plusone
+   \strc_references_direct_full_user
+      {\s!btxset="\currentbtxdataset",\s!btxref="\currentbtxtag",\ifx\currentbtxbacklink\currentbtxbacktrace\s!btxint=\currentbtxbacklink\else\s!btxbck="\currentbtxbacktrace"\fi}%
+      {\s!btx::\v!list::\number\c_btx_list_reference}%
+      {\number\btxlistcounter}}
 
 \unexpanded\def\btx_cite_reference_inject % todo: wrap whole content?
   {\dontleavehmode\begingroup % no box
-     \iftrialtypesetting\else
-%        \ifx\currentbtxinternal\empty\else
- %        \global\advance\btxcitecounter\plusone
-         \ctxcommand{btxcitereference(\number\currentbtxinternal)}%
-%        \fi
+     \iftrialtypesetting \else
+       \btx_trace_list_cross\currentbtxbacklink\empty
      \fi
-    % \btx_list_reference_inject_indeed
    \endgroup}
 
-\let\btxcitereference\btx_cite_reference_inject
+% \let\btxcitereference\btx_cite_reference_inject
+\let\btxcitereference\relax
 
 \setuvalue{\??btxnumbering\v!short  }{\btxlistvariant{short}} % these will be setups
 \setuvalue{\??btxnumbering\v!bib    }{\btxlistvariant{num}}   % these will be setups
@@ -762,14 +784,14 @@
 
 \unexpanded\def\btxdomarkcitation % called from lua end
   {\iftrialtypesetting
-     \expandafter\gobbletwoarguments
+     \expandafter\gobblethreearguments
    \else
      \expandafter\publ_cite_mark_citation
    \fi}
 
-\def\publ_cite_mark_citation#1#2% called from lua end
+\def\publ_cite_mark_citation#1#2#3% called from lua end
   {\dontleavehmode
-   \writedatatolist[btx][btxset=#1,btxref=#2]}  % \c!location=\v!here
+   \normalexpanded{\writedatatolist[\s!btx][\s!btxset=#1,\s!btxref=#2,\s!btxint=\number#3]}}  % \c!location=\v!here
 
 %D \macros{cite,nocite,citation,nocitation,usecitation}
 %D
@@ -923,17 +945,20 @@
 \newconstant\currentbtxconcat
 
 \unexpanded\def\btxcitereset
-  {\let\currentbtxfirst   \empty
-   \let\currentbtxsecond  \empty
-   \let\currentbtxinternal\empty
-   \let\currentbtxlanguage\empty
-   \let\currentbtxtag     \empty
+  {\let\currentbtxfirst    \empty
+   \let\currentbtxsecond   \empty
+   \let\currentbtxinternal \empty
+   \let\currentbtxbacklink \empty
+   \let\currentbtxbacktrace\empty
+   \let\currentbtxlanguage \empty
+   \let\currentbtxtag      \empty
    \setconstant\currentbtxconcat\zerocount}
 
 \btxcitereset
 
 \unexpanded\def\btxcitesetup#1%
-  {\directsetup{btx:cite:#1}%
+  {\btx_cite_reference_inject
+   \directsetup{btx:cite:#1}%
    \btxcitereset}
 
 \unexpanded\def\btxsetfirst   {\def\currentbtxfirst}
@@ -943,14 +968,6 @@
 %unexpanded\def\btxsetlanguage{\def\currentbtxlanguage}
 \unexpanded\def\btxsetconcat#1{\setconstant\currentbtxconcat#1\relax}
 
-\unexpanded\def\btxsetlistreference#1#2% #3#4%
-  {\strc_references_direct_full_user{btxset="#1",btxref="#2"}}
-
-\unexpanded\def\btxsetcitereference#1#2%
-  {\ifx\currentbtxinternal\empty \else
-     \strc_references_direct_full_user{btxint=#2}{#1}\empty
-   \fi}
-
 \unexpanded\def\btxstartsubcite#1%
   {\bgroup
    \btxcitereset
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 90dcf1e59..3a2a70a01 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 ab35fb8a4..1c9f6bd8d 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-ref.mkvi b/tex/context/base/strc-ref.mkvi
index 91bcb6193..7d9c1c526 100644
--- a/tex/context/base/strc-ref.mkvi
+++ b/tex/context/base/strc-ref.mkvi
@@ -1920,6 +1920,27 @@
 %D \stopinteractionmenu
 %D \stoptyping
 
+%D Tracing:
+
+\unexpanded\def\strc_references_tracer#1#2% \csleft csright
+  {\hbox to \zeropoint \bgroup
+     \hss
+     \infofont
+     \darkblue
+     \ifx#1\empty\else
+         \raise\strutht \hbox \s!to \zeropoint \bgroup
+           \hss#1\hskip.2\emwidth
+         \egroup
+     \fi
+     \vrule \s!height 1.5\strutht \s!depth \strutdp \s!width .1\emwidth
+     \ifx#2\empty\else
+       \raise\strutht \hbox \s!to \zeropoint \bgroup
+         \hskip.2\emwidth#2\hss
+       \egroup
+     \fi
+     \hss
+   \egroup}%
+
 \protect \endinput
 
 % tricky:
diff --git a/tex/context/sample/samples.tex b/tex/context/sample/samples.tex
index d8640055a..6e217a592 100644
--- a/tex/context/sample/samples.tex
+++ b/tex/context/sample/samples.tex
@@ -42,6 +42,7 @@ used in testing bibliographic references and citations.
                                                      University of California Press, 2007, p.199 \NC \NR
 \NC carrol.tex         \NC Sean B. Carrol        \NC The Making of the Fittest, \endgraf
                                                      Quercus, London, 2006 \NC \NR
+%NC jojomayer.tex      \NC Jojo Mayer            \NC Between Zero & One, www.youtube.com/watch?v=mSj298iBjBY \NC \NR
 %NC schwarzenegger.tex \NC Arnold Schwarzenegger \NC Several place on the World Wide Web. \NC \NR
 \stoptabulate
 
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index f31c800c7..3f24c9795 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  : 06/13/14 01:11:28
+-- merge date  : 06/15/14 15:54:28
 
 do -- begin closure to overcome local limits and interference
 
-- 
cgit v1.2.3