From e4e1b848db0d8b091da63f2c95f8350ae7c804c7 Mon Sep 17 00:00:00 2001
From: Context Git Mirror Bot <phg42.2a@gmail.com>
Date: Thu, 9 Oct 2014 00:15:04 +0200
Subject: 2014-10-08 23:34:00

---
 tex/context/base/back-exp.lua                      |   3 +
 tex/context/base/cont-new.mkiv                     |  78 ++++--
 tex/context/base/context-version.pdf               | Bin 4388 -> 4383 bytes
 tex/context/base/context.mkiv                      |   2 +-
 tex/context/base/lpdf-tag.lua                      |  16 +-
 tex/context/base/math-stc.mkvi                     | 277 +++++++++++++--------
 tex/context/base/math-tag.lua                      |   5 +-
 tex/context/base/mult-sys.mkiv                     |   7 +
 tex/context/base/publ-dat.lua                      | 179 ++++++++++---
 tex/context/base/publ-ini.lua                      |  10 +-
 tex/context/base/publ-ini.mkiv                     |  15 ++
 tex/context/base/status-files.pdf                  | Bin 24753 -> 24717 bytes
 tex/context/base/status-lua.pdf                    | Bin 333496 -> 333682 bytes
 tex/context/base/strc-tag.lua                      |  69 ++++-
 tex/context/base/strc-tag.mkiv                     |  17 +-
 tex/generic/context/luatex/luatex-fonts-merged.lua |   2 +-
 16 files changed, 490 insertions(+), 190 deletions(-)

diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua
index 54a53b280..f3064f51e 100644
--- a/tex/context/base/back-exp.lua
+++ b/tex/context/base/back-exp.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['back-exp'] = {
     license   = "see context related readme files"
 }
 
+-- Todo: share properties more with tagged pdf (or thge reverse)
+
 -- Because we run into the 200 local limit we quite some do .. end wrappers .. not always
 -- that nice but it has to be.
 
@@ -1261,6 +1263,7 @@ do
                         local t  = nil
                         local b  = nil
                         -- only accent when top / bot have stretch
+                        -- normally we flush [base under over] which is better for tagged pdf
                         if t1 == "mstackermid" then
                             m = accentchar(d1) -- or m
                             if t2 == "mstackertop" then
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index bd70f3566..5730e9d36 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.10.08 16:51}
+\newcontextversion{2014.10.08 23:31}
 
 %D This file is loaded at runtime, thereby providing an excellent place for
 %D hacks, patches, extensions and new features.
@@ -32,33 +32,59 @@
 %     \inheritmaintextcolor
 % \to \everymargindatacontent
 
-% This is experimental; if this changes we need to adapt the mb-mp
-% style too. It's not in the core yet.
-
-% \def\ActionY{\blank\analyzenofparlines{\inleftmargin{\analyzednofparlines}}}
-% \def\ActionN{\analyzenofparlines{\inleftmargin{\analyzednofparlines}}}
+% This is experimental; if this changes we need to adapt the mb-mp style too. It's
+% not in the core yet.
 %
-% \saveparnumber\ifnum\nofparlines<2 \ActionY\else\ActionN\fi 1.1 nop \crlf
-%                                                             1.2 nop \par
-% \saveparnumber\ifnum\nofparlines<2 \ActionY\else\ActionN\fi 2.1 nop \par
-% \saveparnumber\ifnum\nofparlines<2 \ActionY\else\ActionN\fi 3.1 yes \crlf
-%                                                             3.2 nop \crlf
-%                                                             3.3 nop \par
-% \saveparnumber\ifnum\nofparlines<2 \ActionY\else\ActionN\fi 4.1 nop \crlf
-%                                                             4.2 nop \par
-% \saveparnumber\ifnum\nofparlines<2 \ActionY\else\ActionN\fi 5.1 nop \par
-% \saveparnumber\ifnum\nofparlines<2 \ActionY\else\ActionN\fi 6.1 yes \par
+% \def\ActionY{\blank\inleftmargin{\shownofparlines}}
+% \def\ActionN{\inleftmargin{\shownofparlines}}
 %
-% \saveparnumber\doifelselessparlines {2}\ActionY\ActionN     1.1 nop \crlf
-%                                                             1.2 nop \par
-% \saveparnumber\doifelselessparlines {2}\ActionY\ActionN     2.1 nop \par
-% \saveparnumber\doifelselessparlines {2}\ActionY\ActionN     3.1 yes \crlf
-%                                                             3.2 nop \crlf
-%                                                             3.3 nop \par
-% \saveparnumber\doifelselessparlines {2}\ActionY\ActionN     4.1 nop \crlf
-%                                                             4.2 nop \par
-% \saveparnumber\doifelselessparlines {2}\ActionY\ActionN     5.1 nop \par
-% \saveparnumber\doifelselessparlines {2}\ActionY\ActionN     6.1 yes \par
+% \saveparnumber
+% ...
+% \checknofparlines
+% \ifnum\nofparlines<2
+%   \ActionY
+% \else
+%   \ActionN
+% \fi
+% ...
+
+\newcount\c_typo_par_current
+\newcount\c_typo_par_saved
+\newcount\c_typo_par_lines
+\newcount\c_typo_par_temp
+
+\appendtoks
+    \advance\c_typo_par_current\plusone % local
+   %\llap{\infofont[\the\c_typo_par_saved:\the\c_typo_par_current]\quad}%
+\to \everypar
+
+\unexpanded\def\saveparnumber % the upcoming number
+  {\c_typo_par_saved\c_typo_par_current} % local
+
+\def\savedparnumber  {\number\c_typo_par_saved}
+\def\currentparnumber{\number\c_typo_par_current}
+\def\nofparlines     {\number\c_typo_par_lines}
+
+\unexpanded\def\shownofparlines
+  {\dontleavehmode\hbox\bgroup
+   \infofont[\savedparstate]%
+   \egroup}
+
+\unexpanded\def\checknofparlines
+  {\c_typo_par_temp\numexpr\c_typo_par_saved+\plusone\relax
+   \ifhmode
+     \c_typo_par_lines\zerocount
+     \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space-}%
+   \else\ifnum\c_typo_par_current=\c_typo_par_temp
+     \c_typo_par_lines\prevgraf
+     \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space\number\prevgraf}%
+   \else\ifnum\c_typo_par_temp>\c_typo_par_current
+     \c_typo_par_lines\zerocount
+     \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space-}%
+   \else
+     \c_typo_par_lines\maxdimen
+     \edef\savedparstate{\number\c_typo_par_temp:\number\c_typo_par_current\space+}%
+   \fi\fi\fi}
 
 %D Maybe:
 
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index cfd9a2785..83121d179 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 b10c6885f..4dc1f42a5 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.10.08 16:51}
+\edef\contextversion{2014.10.08 23:31}
 \edef\contextkind   {beta}
 
 %D For those who want to use this:
diff --git a/tex/context/base/lpdf-tag.lua b/tex/context/base/lpdf-tag.lua
index 9b54f39ec..f9ef43818 100644
--- a/tex/context/base/lpdf-tag.lua
+++ b/tex/context/base/lpdf-tag.lua
@@ -191,14 +191,18 @@ local function makeattribute(t)
     end
 end
 
-local function makeelement(fulltag,parent)
+local function makeelement(fulltag,parent,attr)
     local tag, n = lpegmatch(dashsplitter,fulltag)
-    if tag == "ignore" then
+    local tg, detail = lpegmatch(colonsplitter,tag)
+    if tg == "ignore" then
         return false
---     elseif tag == "mstackertop" or tag == "mstackerbot" or tag == "mstackermid"then
---         return true
+    elseif tg == "mstackertop" or tg == "mstackerbot" or tg == "mstackermid"then
+        return true
+    elseif tg == "mstacker" then
+print("get",fulltag)
+        local p = properties[fulltag]
+        tg = p and p.subtype or tg
     end
-    local tg, detail = lpegmatch(colonsplitter,tag)
     local k, r = pdfarray(), pdfreserveobject()
     local a = userproperties[fulltag]
     usedmapping[tg] = true
@@ -343,7 +347,7 @@ function nodeinjections.addtags(head)
         local noftags, tag = #tags, nil
         for j=1,noftags do
             local tag = tags[j]
-            local prv = elements[tag] or makeelement(tag,prev)
+            local prv = elements[tag] or makeelement(tag,prev,attr)
             if prv == false then
                 -- ignore this one
                 prev = false
diff --git a/tex/context/base/math-stc.mkvi b/tex/context/base/math-stc.mkvi
index 349664891..73f2c1a7d 100644
--- a/tex/context/base/math-stc.mkvi
+++ b/tex/context/base/math-stc.mkvi
@@ -16,7 +16,11 @@
 
 \unprotect
 
-%D WARNING: If the code here changes, the export needs to be checked!
+%D WARNING: If the code here changes, the export needs to be checked! Stackers are rather
+%D special because the order in mathml matters, so we flush in [base under over] order. We
+%D also do some analysis at the \TEX\ end (passing the right variant). It's easy in the
+%D export to deal with it but in the pdf stream less trivial as we don't actually analyze
+%D there.
 
 %D At some point the \MKII\ arrow mechanism has been converted to \MKIV, but we kept
 %D most of the logic. We now have a more generic variant dealing with extensibles.
@@ -392,34 +396,50 @@
       \fi
       %
       \math_stackers_normalize_three
-      %
+      % analysis
+      \ifdim\htdp\scratchboxtwo>\zeropoint
+        \ifdim\htdp\scratchboxone>\zeropoint
+          \dosetelementproperty\s!subtype\t!munderover
+        \else
+          \dosetelementproperty\s!subtype\t!munder
+        \fi
+      \else
+        \ifdim\htdp\scratchboxone>\zeropoint
+          \dosetelementproperty\s!subtype\t!mover
+        \else
+          % brrr
+        \fi
+      \fi
+      % base
       \math_stackers_start_tagged_mid
-      \math_stackers_middle\bgroup
-        \box\scratchboxthree
-      \egroup
-      \math_stackers_stop_tagged
-      %
-      \math_stackers_start_tagged_top
-      \ifdim\htdp\scratchboxone>\zeropoint
-        \scratchoffset\scratchvoffset
-        \kern-\scratchwidth
-        \math_stackers_top\bgroup
-          \raise\dimexpr\dp\scratchboxone+\scratchheight+\scratchoffset+\scratchtopoffset\relax
-          \box\scratchboxone
+        \math_stackers_middle\bgroup
+          \box\scratchboxthree
         \egroup
-      \fi
       \math_stackers_stop_tagged
-      %
-      \math_stackers_start_tagged_bot
+      % under
       \ifdim\htdp\scratchboxtwo>\zeropoint
-        \scratchoffset\scratchvoffset
-        \kern-\scratchwidth
-        \math_stackers_bottom\bgroup
-          \lower\dimexpr\ht\scratchboxtwo+\scratchdepth+\scratchoffset+\scratchbottomoffset\relax
-          \box\scratchboxtwo
-        \egroup
+        \math_stackers_start_tagged_bot
+          \scratchoffset\scratchvoffset
+          \kern-\scratchwidth
+          \math_stackers_bottom\bgroup
+            \lower\dimexpr\ht\scratchboxtwo+\scratchdepth+\scratchoffset+\scratchbottomoffset\relax
+            \box\scratchboxtwo
+          \egroup
+        \math_stackers_stop_tagged
+      \fi
+      % over
+      \ifdim\htdp\scratchboxone>\zeropoint
+        \math_stackers_start_tagged_top
+          \scratchoffset\scratchvoffset
+          \kern-\scratchwidth
+          \math_stackers_top\bgroup
+            \raise\dimexpr\dp\scratchboxone+\scratchheight+\scratchoffset+\scratchtopoffset\relax
+            \box\scratchboxone
+          \egroup
+        \math_stackers_stop_tagged
       \fi
-      \math_stackers_stop_tagged}%
+      %
+      }%
   \dostoptagged
   \mathstackersparameter\c!right\relax
   \endgroup}
@@ -478,6 +498,8 @@
 \def\math_class_by_parameter_indeed#1%
   {\csname\??mathclasses\ifcsname\??mathclasses#1\endcsname#1\fi\endcsname}
 
+% 1 0 name n 0 | 0 1 name n 0 | 1 1 name n n
+
 \unexpanded\def\math_stackers_make_double#top#bottom#category#codepoint#codeextra#text%
   {\begingroup
    \edef\currentmathstackers{#category}%
@@ -511,48 +533,98 @@
       \advance\scratchwidth2\scratchhoffset
       %
       \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
-      \setbox\scratchboxthree\hbox
-        to \scratchwidth{\hss\box\scratchboxthree\hss}%
+      \setbox\scratchboxthree\hbox to \scratchwidth{\hss\box\scratchboxthree\hss}%
       %
       \math_stackers_normalize_three
-      %
+      % analysis
+      \ifcase#bottom\relax
+        \ifcase#top\relax
+            \dosetelementproperty\s!subtype\t!munderover
+        \else
+            \dosetelementproperty\s!subtype\t!mover
+        \fi
+      \else
+        \ifcase#top\relax
+            \dosetelementproperty\s!subtype\t!munder
+        \else
+            % brrr
+        \fi
+      \fi
+      % base
       \math_stackers_start_tagged_mid
-      \math_stackers_middle\bgroup
-        \box\scratchboxthree
-      \egroup
+        \math_stackers_middle\bgroup
+          \box\scratchboxthree
+        \egroup
       \math_stackers_stop_tagged
       %
       \ifdim\htdp\scratchboxtwo>\zeropoint
-        \kern-\scratchwidth
-        \math_stackers_start_tagged_top
-        \ifcase#top\else
-          \math_stackers_top\bgroup
-            \raise\dimexpr
-               \scratchheight
-              +\dp\scratchboxtwo % new
-              +\mathstackersparameter\c!distance % was \c!voffset
-            \relax
-            \box\scratchboxtwo
-          \egroup
-        \fi
-        \math_stackers_stop_tagged
-        \scratchunicode#codeextra\relax
-        \math_stackers_start_tagged_bot
-        \ifcase\scratchunicode\else
+%         %
+%         \kern-\scratchwidth
+%         \math_stackers_start_tagged_top
+%           \ifcase#top\else
+%             \math_stackers_top\bgroup
+%               \raise\dimexpr
+%                  \scratchheight
+%                 +\dp\scratchboxtwo % new
+%                 +\mathstackersparameter\c!distance % was \c!voffset
+%               \relax
+%               \box\scratchboxtwo
+%             \egroup
+%           \fi
+%         \math_stackers_stop_tagged
+%         %
+%         \scratchunicode#codeextra\relax
+%         \math_stackers_start_tagged_bot
+%           \ifcase\scratchunicode\else
+%             \kern-\scratchwidth
+%             \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
+%           \fi
+%           \ifcase#bottom\else
+%             \math_stackers_bottom\bgroup
+%               \lower\dimexpr
+%                  \scratchdepth
+%                 +\ht\scratchboxtwo
+%                 +\mathstackersparameter\c!distance % was \c!voffset
+%               \relax
+%               \box\scratchboxtwo
+%             \egroup
+%           \fi
+%         \math_stackers_stop_tagged
+%         %
+        %
+        \ifcase#bottom\else
           \kern-\scratchwidth
-          \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
+          % under
+          \math_stackers_start_tagged_bot
+            \scratchunicode#codeextra\relax
+            \ifcase\scratchunicode\else
+              \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
+            \fi
+            \math_stackers_bottom\bgroup
+              \lower\dimexpr
+                 \scratchdepth
+                +\ht\scratchboxtwo
+                +\mathstackersparameter\c!distance % was \c!voffset
+              \relax
+              \box\scratchboxtwo
+            \egroup
+          \math_stackers_stop_tagged
         \fi
-        \ifcase#bottom\else
-          \math_stackers_bottom\bgroup
-            \lower\dimexpr
-               \scratchdepth
-              +\ht\scratchboxtwo
-              +\mathstackersparameter\c!distance % was \c!voffset
-            \relax
-            \box\scratchboxtwo
-          \egroup
+        \ifcase#top\else
+          \kern-\scratchwidth
+          % over
+          \math_stackers_start_tagged_top
+            \math_stackers_top\bgroup
+              \raise\dimexpr
+                 \scratchheight
+                +\dp\scratchboxtwo % new
+                +\mathstackersparameter\c!distance % was \c!voffset
+              \relax
+              \box\scratchboxtwo
+            \egroup
+          \math_stackers_stop_tagged
         \fi
-        \math_stackers_stop_tagged
+        %
       \fi}%
   \dostoptagged
   \mathstackersparameter\c!right\relax
@@ -670,61 +742,64 @@
       \fi
       %
       \math_stackers_normalize_three
-      %
+      % analysis
+      \dosetelementproperty\s!subtype\t!munderover
+      % base
       \math_stackers_start_tagged_mid
-      \math_stackers_middle\bgroup
-        \box\scratchboxthree
-      \egroup
+        \math_stackers_middle\bgroup
+          \box\scratchboxthree
+        \egroup
       \math_stackers_stop_tagged
       %
+      \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
       \kern-\scratchwidth
       \ifcase#where\relax
-        \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
-        %
-        \math_stackers_start_tagged_top
-        \math_stackers_top\bgroup
-          \raise\dimexpr
-             \scratchheight
-            +\dp\scratchboxone
-            +\mathstackersparameter\c!voffset
-          \relax
-          \box\scratchboxone % toptext
-        \egroup
+        % under
+        \math_stackers_start_tagged_bot
+          \math_stackers_bottom\bgroup
+            \lower\dimexpr
+              \scratchdepth
+             +\ht\scratchboxtwo
+             +\mathstackersparameter\c!distance
+            \relax
+            \box\scratchboxtwo % accent
+          \egroup
         \math_stackers_stop_tagged
         \kern-\scratchwidth
-        \math_stackers_start_tagged_bot
-        \math_stackers_bottom\bgroup
-          \lower\dimexpr
-            \scratchdepth
-           +\ht\scratchboxtwo
-           +\mathstackersparameter\c!distance
-          \relax
-          \box\scratchboxtwo % accent
-        \egroup
+        % over
+        \math_stackers_start_tagged_top
+          \math_stackers_top\bgroup
+            \raise\dimexpr
+               \scratchheight
+              +\dp\scratchboxone
+              +\mathstackersparameter\c!voffset
+            \relax
+            \box\scratchboxone % toptext
+          \egroup
         \math_stackers_stop_tagged
       \else
-        \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
-        %
-        \math_stackers_start_tagged_top
-        \math_stackers_top\bgroup
-          \raise\dimexpr
-             \scratchheight
-            +\dp\scratchboxtwo % new
-            +\mathstackersparameter\c!distance
-          \relax
-          \box\scratchboxtwo % accent
-        \egroup
+        % under
+        \math_stackers_start_tagged_bot
+          \math_stackers_bottom\bgroup
+            \lower\dimexpr
+               \scratchdepth
+              +\ht\scratchboxone
+              +\mathstackersparameter\c!voffset
+            \relax
+            \box\scratchboxone % bottext
+          \egroup
         \math_stackers_stop_tagged
         \kern-\scratchwidth
-        \math_stackers_start_tagged_bot
-        \math_stackers_bottom\bgroup
-          \lower\dimexpr
-             \scratchdepth
-            +\ht\scratchboxone
-            +\mathstackersparameter\c!voffset
-          \relax
-          \box\scratchboxone % bottext
-        \egroup
+        % over
+        \math_stackers_start_tagged_top
+          \math_stackers_top\bgroup
+            \raise\dimexpr
+               \scratchheight
+              +\dp\scratchboxtwo % new
+              +\mathstackersparameter\c!distance
+            \relax
+            \box\scratchboxtwo % accent
+          \egroup
         \math_stackers_stop_tagged
       \fi
       }%
diff --git a/tex/context/base/math-tag.lua b/tex/context/base/math-tag.lua
index 26782bd9c..9617fa182 100644
--- a/tex/context/base/math-tag.lua
+++ b/tex/context/base/math-tag.lua
@@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['math-tag'] = {
 -- use lpeg matchers
 
 local find, match = string.find, string.match
-local insert, remove = table.insert, table.remove
+local insert, remove, concat = table.insert, table.remove, table.concat
 
 local attributes          = attributes
 local nodes               = nodes
@@ -344,7 +344,8 @@ process = function(start) -- we cannot use the processor as we have no finalizer
                                 remove(actionstack)
                             end
                         elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then
-                            setattr(start,a_tagged,start_tagged(tag))
+                            -- looks like it gets processed twice
+                            setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute
                             process(list)
                             stop_tagged()
                         else
diff --git a/tex/context/base/mult-sys.mkiv b/tex/context/base/mult-sys.mkiv
index 8c1bff2bc..9b75f332f 100644
--- a/tex/context/base/mult-sys.mkiv
+++ b/tex/context/base/mult-sys.mkiv
@@ -538,6 +538,13 @@
 \defineinterfacevariable {c} {c}
 \defineinterfacevariable {d} {d}
 
+%D For tagging:
+
+\definesystemconstant {subtype}
+\definesystemconstant {top}
+\definesystemconstant {bottom}
+\definesystemconstant {both}
+
 %D Special purpose variables:
 
 \def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi}
diff --git a/tex/context/base/publ-dat.lua b/tex/context/base/publ-dat.lua
index 20f545d8b..357b381c6 100644
--- a/tex/context/base/publ-dat.lua
+++ b/tex/context/base/publ-dat.lua
@@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['publ-dat'] = {
 
 -- todo: strip the @ in the lpeg instead of on do_definition and do_shortcut
 -- todo: store bibroot and bibrootdt
+-- todo: dataset = datasets[dataset] => current = datasets[dataset]
 
 --[[ldx--
 <p>This is a prelude to integrated bibliography support. This file just loads
@@ -59,6 +60,14 @@ publicationsstats.nofdefinitions = 0
 publicationsstats.nofshortcuts   = 0
 publicationsstats.nofdatasets    = 0
 
+if not publications.usedentries then
+    function publications.usedentries()
+        return { }
+    end
+end
+
+local v_all = interfaces and interfaces.variables.all or "all"
+
 local xmlplaceholder = "<?xml version='1.0' standalone='yes'?>\n<bibtex></bibtex>"
 
 local defaultshortcuts = {
@@ -374,53 +383,59 @@ local cleaner_2 = Cs ( (
 
 local compact = false -- can be a directive but then we also need to deal with newlines ... not now
 
-function publications.converttoxml(dataset,nice) -- we have fields !
-    dataset = datasets[dataset]
-    local luadata = dataset and dataset.luadata
+function publications.converttoxml(dataset,nice,dontstore,usedonly) -- we have fields !
+    current = datasets[dataset]
+    local luadata = current and current.luadata
     if luadata then
         statistics.starttiming(publications)
-        statistics.starttiming(xml)
         --
-        local result, r = { }, 0
+        local result, r, n = { }, 0, 0
+        local usedonly = usedonly and publications.usedentries(dataset)
         --
         r = r + 1 ; result[r] = "<?xml version='1.0' standalone='yes'?>"
         r = r + 1 ; result[r] = "<bibtex>"
         --
         if nice then
             local f_entry_start = formatters[" <entry tag='%s' category='%s' index='%s'>"]
-            local f_entry_stop  = " </entry>"
+            local s_entry_stop  = " </entry>"
             local f_field       = formatters["  <field name='%s'>%s</field>"]
             for tag, entry in sortedhash(luadata) do
-                r = r + 1 ; result[r] = f_entry_start(tag,entry.category,entry.index)
-                for key, value in sortedhash(entry) do
-                    if key ~= "tag" and key ~= "category" and key ~= "index" then
-                        if lpegmatch(cleaner_1,value) then
-                            value = lpegmatch(cleaner_2,value)
-                        end
-                        if value ~= "" then
-                            r = r + 1 ; result[r] = f_field(key,value)
+                if not usedonly or usedonly[tag] then
+                    r = r + 1 ; result[r] = f_entry_start(tag,entry.category,entry.index)
+                    for key, value in sortedhash(entry) do
+                        if key ~= "tag" and key ~= "category" and key ~= "index" then
+                            if lpegmatch(cleaner_1,value) then
+                                value = lpegmatch(cleaner_2,value)
+                            end
+                            if value ~= "" then
+                                r = r + 1 ; result[r] = f_field(key,value)
+                            end
                         end
                     end
+                    r = r + 1 ; result[r] = s_entry_stop
+                    n = n + 1
                 end
-                r = r + 1 ; result[r] = f_entry_stop
             end
         else
             local f_entry_start = formatters["<entry tag='%s' category='%s' index='%s'>"]
-            local f_entry_stop  = "</entry>"
+            local s_entry_stop  = "</entry>"
             local f_field       = formatters["<field name='%s'>%s</field>"]
             for tag, entry in next, luadata do
-                r = r + 1 ; result[r] = f_entry_start(entry.tag,entry.category,entry.index)
-                for key, value in next, entry do
-                    if key ~= "tag" and key ~= "category" and key ~= "index" then
-                        if lpegmatch(cleaner_1,value) then
-                            value = lpegmatch(cleaner_2,value)
-                        end
-                        if value ~= "" then
-                            r = r + 1 ; result[r] = f_field(key,value)
+                if not usedonly or usedonly[tag] then
+                    r = r + 1 ; result[r] = f_entry_start(entry.tag,entry.category,entry.index)
+                    for key, value in next, entry do
+                        if key ~= "tag" and key ~= "category" and key ~= "index" then
+                            if lpegmatch(cleaner_1,value) then
+                                value = lpegmatch(cleaner_2,value)
+                            end
+                            if value ~= "" then
+                                r = r + 1 ; result[r] = f_field(key,value)
+                            end
                         end
                     end
+                    r = r + 1 ; result[r] = s_entry_stop
+                    n = n + 1
                 end
-                r = r + 1 ; result[r] = f_entry_stop
             end
         end
         --
@@ -428,18 +443,23 @@ function publications.converttoxml(dataset,nice) -- we have fields !
         --
         result = concat(result,nice and "\n" or nil)
         --
-        dataset.xmldata = xmlconvert(result, {
-            resolve_entities            = true,
-            resolve_predefined_entities = true, -- in case we have escaped entities
-         -- unify_predefined_entities   = true, -- &#038; -> &amp;
-            utfize_entities             = true,
-        } )
-        --
-        statistics.stoptiming(xml)
-        statistics.stoptiming(publications)
-        if lxml then
-            lxml.register(formatters["btx:%s"](dataset.name),dataset.xmldata)
+        if dontstore then
+            -- indeed
+        else
+            statistics.starttiming(xml)
+            current.xmldata = xmlconvert(result, {
+                resolve_entities            = true,
+                resolve_predefined_entities = true, -- in case we have escaped entities
+             -- unify_predefined_entities   = true, -- &#038; -> &amp;
+                utfize_entities             = true,
+            } )
+            statistics.stoptiming(xml)
+            if lxml then
+                lxml.register(formatters["btx:%s"](current.name),current.xmldata)
+            end
         end
+        statistics.stoptiming(publications)
+        return result, n
     end
 end
 
@@ -657,3 +677,90 @@ function publications.concatstate(i,n)
         return 2
     end
 end
+
+-- savers
+
+local savers = { }
+
+local s_preamble = [[
+% this is an export from context mkiv
+
+@preamble {
+    \ifdefined\btxcmd
+        % we're probably in context
+    \else
+        \def\btxcmd#1{\csname#1\endcsname}
+    \fi
+}
+
+]]
+
+function savers.bib(dataset,filename,usedonly)
+    local current  = datasets[dataset]
+    local luadata  = current.luadata or { }
+    local usedonly = usedonly and publications.usedentries(dataset)
+    local f_start  = formatters["@%s{%s,\n"]
+    local f_field  = formatters["  %s = {%s},\n"]
+    local s_stop   = "}\n\n"
+    local result   = { s_preamble }
+    local n, r = 0, 1
+    for tag, data in sortedhash(luadata) do
+        if not usedonly or usedonly[tag] then
+            r = r + 1 ; result[r] = f_start(data.category or "article",tag)
+            for key, value in sortedhash(data) do
+                r = r + 1 ; result[r] = f_field(key,value)
+            end
+            r = r + 1 ; result[r] = s_stop
+            n = n + 1
+        end
+    end
+    report("%s entries from dataset %a saved in %a",n,dataset,filename)
+    io.savedata(filename,concat(result))
+end
+
+function savers.lua(dataset,filename,usedonly)
+    local current  = datasets[dataset]
+    local luadata  = current.luadata or { }
+    local usedonly = usedonly and publications.usedentries(dataset)
+    if usedonly then
+        local list = { }
+        for k, v in next, luadata do
+            if usedonly[k] then
+                list[k] = v
+            end
+        end
+        luadata = list
+    end
+    report("%s entries from dataset %a saved in %a",table.count(luadata),dataset,filename)
+    table.save(filename,luadata)
+end
+
+function savers.xml(dataset,filename,usedonly)
+    local result, n = publications.converttoxml(dataset,true,true,usedonly)
+    report("%s entries from dataset %a saved in %a",n,dataset,filename)
+    io.savedata(filename,result)
+end
+
+function publications.save(dataset,filename,kind,usedonly)
+    statistics.starttiming(publications)
+    if not kind or kind == "" then
+        kind = file.suffix(filename)
+    end
+    local saver = savers[kind]
+    if saver then
+        usedonly = usedonly ~= v_all
+        saver(dataset,filename,usedonly)
+    else
+        report("unknown format %a for saving %a",kind,dataset)
+    end
+    statistics.stoptiming(publications)
+    return dataset
+end
+
+commands.btxsavedataset = publications.save
+
+-- loaders.bib("test",resolvers.findfile("mkiv-publications.bib","bibtex"))
+--
+-- publications.save("test","e:/tmp/foo.bib")
+-- publications.save("test","e:/tmp/foo.lua")
+-- publications.save("test","e:/tmp/foo.xml")
diff --git a/tex/context/base/publ-ini.lua b/tex/context/base/publ-ini.lua
index 018126573..dae93b000 100644
--- a/tex/context/base/publ-ini.lua
+++ b/tex/context/base/publ-ini.lua
@@ -276,9 +276,9 @@ end
 -- when testing)
 
 local initialized  = false
-local usedentries  = { }
-local citetolist   = { }
-local listtocite   = { }
+local usedentries  = allocate { }
+local citetolist   = allocate { }
+local listtocite   = allocate { }
 local nofcitations = 0
 
 setmetatableindex(usedentries,function(t,k)
@@ -349,6 +349,10 @@ setmetatableindex(usedentries,function(t,k)
     end
 end)
 
+function publications.usedentries(dataset)
+    return usedentries[dataset]
+end
+
 -- match:
 --
 -- [current|previous|following] section
diff --git a/tex/context/base/publ-ini.mkiv b/tex/context/base/publ-ini.mkiv
index 161934384..592071f31 100644
--- a/tex/context/base/publ-ini.mkiv
+++ b/tex/context/base/publ-ini.mkiv
@@ -1119,6 +1119,21 @@
 % \btxexpandedjournal[fbj]
 % \btxabbreviatedjournal[foo journal of bars]
 
+%D Saving data:
+
+\unexpanded\def\savebtxdataset
+  {\dotripleargument\publ_save_dataset}
+
+\unexpanded\def\publ_save_dataset[#1][#2][#3]%
+  {\begingroup
+   \getdummyparameters[\c!criterium=\v!all,\c!alternative=,#3]% % all or used
+   \ctxcommand{btxsavedataset("#1","#2","\dummyparameter\c!alternative","\dummyparameter\c!criterium")}%
+   \endgroup}
+
+% \savebtxdataset[standard][e:/tmp/foo.bib]
+% \savebtxdataset[standard][e:/tmp/foo.lua]
+% \savebtxdataset[standard][e:/tmp/foo.xml]
+
 %D Defaults:
 
 \setbtxdataset
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 427395f63..38da726f3 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 67dc5c4f2..6c9ac5f42 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-tag.lua b/tex/context/base/strc-tag.lua
index ad6117728..2f8e9ff5d 100644
--- a/tex/context/base/strc-tag.lua
+++ b/tex/context/base/strc-tag.lua
@@ -214,6 +214,7 @@ tags.properties = properties
 
 local lasttags = { }
 local userdata = { }
+local nstack   = 0
 
 tags.userdata  = userdata
 
@@ -226,6 +227,27 @@ function tags.setproperty(tag,key,value)
     end
 end
 
+function tags.setaspect(key,value)
+    local tag = chain[nstack]
+    if tag then
+print("set",tag)
+        local p = properties[tag]
+        if p then
+            p[key] = value
+        else
+            properties[tag] = { [key] = value }
+        end
+    end
+end
+
+function tags.copyaspect(old,new)
+    local oldlst = taglist[old]
+    local newlst = taglist[new]
+    local oldtag = oldlst[#oldlst]
+    local newtag = newlst[#newlst]
+    properties[newtag] = properties[oldtag]
+end
+
 function tags.registerdata(data)
     local fulltag = chain[nstack]
     if fulltag then
@@ -244,8 +266,6 @@ function tags.registermetadata(data)
     end
 end
 
-local nstack = 0
-
 function tags.start(tag,specification,props)
     local label, detail, user
     if specification then
@@ -294,14 +314,42 @@ function tags.start(tag,specification,props)
     return t
 end
 
-function tags.restart(completetag)
-    local t = #taglist + 1
+-- function tags.restart(completetag)
+--     if type(completetag) == "number" then
+--         local attribute = completetag
+--         local listentry = taglist[attribute]
+--         local completetag = listentry[#listentry]
+--         nstack = nstack + 1
+--         chain[nstack] = completetag
+--         stack[nstack] = attribute
+--         texattribute[a_tagged] = attribute
+--         return attribute
+--     else
+--         local attribute = #taglist + 1
+--         nstack = nstack + 1
+--         chain[nstack] = completetag
+--         stack[nstack] = attribute
+--         taglist[attribute] = { unpack(chain,1,nstack) }
+--         texattribute[a_tagged] = attribute
+--         return attribute
+--     end
+-- end
+--
+-- more compact:
+
+function tags.restart(attribute)
     nstack = nstack + 1
-    chain[nstack] = completetag
-    stack[nstack] = t
-    taglist[t] = { unpack(chain,1,nstack) }
-    texattribute[a_tagged] = t
-    return t
+    if type(attribute) == "number" then
+        local listentry = taglist[attribute]
+        chain[nstack] = listentry[#listentry]
+    else
+        chain[nstack] = attribute -- a string
+        attribute = #taglist + 1
+        taglist[attribute] = { unpack(chain,1,nstack) }
+    end
+    stack[nstack] = attribute
+    texattribute[a_tagged] = attribute
+    return attribute
 end
 
 function tags.stop()
@@ -311,7 +359,7 @@ function tags.stop()
     local t = stack[nstack]
     if not t then
      -- if trace_tags then
-            report_tags("ignoring end tag, previous chain: %s",nstack > 0 and concat(chain[nstack],"",1,nstack) or "none")
+            report_tags("ignoring end tag, previous chain: %s",nstack > 0 and concat(chain[nstack]," ",1,nstack) or "none")
      -- end
         t = unsetvalue
     end
@@ -398,3 +446,4 @@ end)
 commands.starttag       = tags.start
 commands.stoptag        = tags.stop
 commands.settagproperty = tags.setproperty
+commands.settagaspect   = tags.setaspect
diff --git a/tex/context/base/strc-tag.mkiv b/tex/context/base/strc-tag.mkiv
index 9e850c85e..a79b5f80e 100644
--- a/tex/context/base/strc-tag.mkiv
+++ b/tex/context/base/strc-tag.mkiv
@@ -92,6 +92,10 @@
 \def\t!mathstackermid        {mstackermid}
 \def\t!mathstackerbot        {mstackerbot}
 
+\def\t!munderover            {munderover}             % special cases
+\def\t!munder                {munder}                 % special cases
+\def\t!mover                 {mover}                  % special cases
+
 \def\t!list                  {list}                   % TOC
 \def\t!listitem              {listitem}               % TOCI
 \def\t!listtag               {listtag}                % Lbl
@@ -160,8 +164,11 @@
 \unexpanded\def\setelementbackendtag{\dodoubleargument\strc_tags_set_backend}
 \unexpanded\def\setelementnature    {\dodoubleargument\strc_tags_set_nature}
 
-\def\strc_tags_set_backend[#1][#2]{\ctxcommand{settagproperty("#1","backend","#2")}}
-\def\strc_tags_set_nature [#1][#2]{\ctxcommand{settagproperty("#1","nature", "#2")}}
+\def\strc_tags_set_backend[#1][#2]{\ctxcommand{settagproperty("#1","backend","#2")}} % todo: ignore when no export
+\def\strc_tags_set_nature [#1][#2]{\ctxcommand{settagproperty("#1","nature", "#2")}} % todo: ignore when no export
+
+\unexpanded\def\strc_tags_set_aspect_nop#1#2{}
+\unexpanded\def\strc_tags_set_aspect_yes#1#2{\ctxcommand{settagaspect("#1","#2")}} % todo: ignore when no export
 
 \installcorenamespace{tagging}
 
@@ -204,11 +211,13 @@
 \unexpanded\def\strc_tags_enable_elements
   {\setuplanguage[\s!default][\s!righthyphenchar="AD]% for the moment here
    \let\startelement\strc_tags_element_start_yes
-   \let\stopelement \strc_tags_element_stop_yes}
+   \let\stopelement \strc_tags_element_stop_yes
+   \let\dosetelementproperty\strc_tags_set_aspect_yes}
 
 \unexpanded\def\strc_tags_disable_elements
   {\let\startelement\strc_tags_element_start_nop
-   \let\stopelement \strc_tags_element_stop_nop}
+   \let\stopelement \strc_tags_element_stop_nop
+   \let\dosetelementproperty\strc_tags_set_aspect_nop}
 
 % beware: making these unexpanded spoils tables (noalign problem)
 
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 9fce2bfad..f316e6acf 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  : 10/08/14 16:51:38
+-- merge date  : 10/08/14 23:31:59
 
 do -- begin closure to overcome local limits and interference
 
-- 
cgit v1.2.3