summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2021-10-11 00:26:56 +0200
committerContext Git Mirror Bot <phg@phi-gamma.net>2021-10-11 00:26:56 +0200
commitb2db36adbd89b2dba9591da5fc13b4eba57d581e (patch)
treefa1dd5b5b89dc4e56cf3aaf05d45e9b078f51d22 /tex
parent778f381ba6a448ab00d67994a412dd4226d43238 (diff)
downloadcontext-b2db36adbd89b2dba9591da5fc13b4eba57d581e.tar.gz
2021-10-10 23:42:00
Diffstat (limited to 'tex')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/lang-def.mkiv4
-rw-r--r--tex/context/base/mkiv/mtx-context-compare.tex1
-rw-r--r--tex/context/base/mkiv/publ-ini.lua33
-rw-r--r--tex/context/base/mkiv/publ-ini.mkiv4
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin24847 -> 24835 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin253894 -> 253897 bytes
-rw-r--r--tex/context/base/mkxl/cont-new.mkxl2
-rw-r--r--tex/context/base/mkxl/context.mkxl5
-rw-r--r--tex/context/base/mkxl/font-emp.mklx84
-rw-r--r--tex/context/base/mkxl/lang-def.mkxl4
-rw-r--r--tex/context/base/mkxl/publ-ini.mkxl18
-rw-r--r--tex/context/base/mkxl/strc-mar-old.lmt759
-rw-r--r--tex/context/base/mkxl/strc-mar-old.mkxl142
-rw-r--r--tex/context/base/mkxl/strc-mar.lmt822
-rw-r--r--tex/context/base/mkxl/strc-mar.mkxl168
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua2
20 files changed, 1293 insertions, 763 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index d43e2ccf1..6aa453475 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2021.10.08 20:05}
+\newcontextversion{2021.10.10 23:40}
%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/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index 3c7645d53..fff18ed27 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2021.10.08 20:05}
+\edef\contextversion{2021.10.10 23:40}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index c8893eb1e..8bad7dd12 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2021.10.08 20:05}
+\newcontextversion{2021.10.10 23:40}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 89e04f878..3924c7104 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -45,7 +45,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2021.10.08 20:05}
+\edef\contextversion{2021.10.10 23:40}
%D Kind of special:
diff --git a/tex/context/base/mkiv/lang-def.mkiv b/tex/context/base/mkiv/lang-def.mkiv
index 603935097..441d328c8 100644
--- a/tex/context/base/mkiv/lang-def.mkiv
+++ b/tex/context/base/mkiv/lang-def.mkiv
@@ -554,7 +554,7 @@
% Artificial Languages: Esperanto
\installlanguage
- [\s!esperanto]
+ [\s!eo]
[\c!spacing=\v!packed,
\c!leftsentence=\endash,
\c!rightsentence=\endash,
@@ -569,7 +569,7 @@
\s!lefthyphenmin=2,
\s!righthyphenmin=2]
-\installlanguage[\s!eo][\c!default=\s!esperanto]
+\installlanguage[\s!esperanto][\c!default=\s!eo]
% Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian
diff --git a/tex/context/base/mkiv/mtx-context-compare.tex b/tex/context/base/mkiv/mtx-context-compare.tex
index c940270c8..163ea5747 100644
--- a/tex/context/base/mkiv/mtx-context-compare.tex
+++ b/tex/context/base/mkiv/mtx-context-compare.tex
@@ -38,7 +38,6 @@
\stopTEXpage
\stoptexdefinition
-
\startluacode
local report = logs.reporter("compare")
diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua
index 83f0ff9ac..584b23dbf 100644
--- a/tex/context/base/mkiv/publ-ini.lua
+++ b/tex/context/base/mkiv/publ-ini.lua
@@ -2168,18 +2168,18 @@ do
function lists.combiinlist(dataset,tag)
local rendering = renderings[dataset]
- local list = rendering.list
+ -- local list = rendering.list
local toindex = rendering.tagtolistindex
return toindex and toindex[tag]
end
function lists.flushcombi(dataset,tag)
local rendering = renderings[dataset]
- local list = rendering.list
local toindex = rendering.tagtolistindex
local listindex = toindex and toindex[tag]
if listindex then
- local li = list[listindex]
+ local list = rendering.list
+ local li = list[listindex]
if li then
local data = datasets[dataset]
local luadata = data.luadata
@@ -3507,3 +3507,30 @@ do
end
end
+
+do
+
+ -- no caching for now
+
+ interfaces.implement { -- shared with mkiv so no public
+ name = "btxdoifelsecitedone",
+ protected = true,
+ -- public = true,
+ -- arguments = "2 arguments",
+ arguments = "2 strings",
+ actions = function(dataset,tag)
+ -- dataset ignored
+ local list = structures.lists.tobesaved
+ local done = false
+ for i=1,#list do
+ local u = list[i].userdata
+ if u.btxref == tag then
+ done = true
+ break
+ end
+ end
+ ctx_doifelse(done)
+ end
+ }
+
+end
diff --git a/tex/context/base/mkiv/publ-ini.mkiv b/tex/context/base/mkiv/publ-ini.mkiv
index dfed53c73..6e34d3ab5 100644
--- a/tex/context/base/mkiv/publ-ini.mkiv
+++ b/tex/context/base/mkiv/publ-ini.mkiv
@@ -799,9 +799,13 @@
\unexpanded\def\btxdoifelsecombiinlist#1#2%
{\clf_btxdoifelsecombiinlist{#1}{#2}}
+\unexpanded\def\btxdoifelsecitedone#1#2%
+ {\clf_btxdoifelsecitedone{#1}{#2}}
+
\let\btxdoifsameaspreviouscheckedelse\btxdoifelsesameaspreviouschecked
\let\btxdoifsameaspreviouselse \btxdoifelsesameasprevious
\let\btxdoifcombiinlistelse \btxdoifelsecombiinlist
+\let\btxdoifcitedoneelse \btxdoifelsecitedone
\def\publ_place_list_indeed#1#2[#3][#4]%
{\begingroup
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index c251ad6c1..ff8592826 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 50cc0ad29..389d9cfd0 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl
index e81d6cc7b..0a0624c12 100644
--- a/tex/context/base/mkxl/cont-new.mkxl
+++ b/tex/context/base/mkxl/cont-new.mkxl
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2021.10.08 20:05}
+\newcontextversion{2021.10.10 23:40}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl
index a5b9cc7f1..98ed72845 100644
--- a/tex/context/base/mkxl/context.mkxl
+++ b/tex/context/base/mkxl/context.mkxl
@@ -29,7 +29,7 @@
%D {YYYY.MM.DD HH:MM} format.
\immutable\edef\contextformat {\jobname}
-\immutable\edef\contextversion{2021.10.08 20:05}
+\immutable\edef\contextversion{2021.10.10 23:40}
%overloadmode 1 % check frozen / warning
%overloadmode 2 % check frozen / error
@@ -249,8 +249,7 @@
\loadmkxlfile{strc-tag}
\loadmkxlfile{strc-doc}
\loadmkxlfile{strc-num}
-%loadmkxlfile{strc-mar}
-\doiffileelse{strc-mar-new.mkxl}{\loadmkxlfile{strc-mar-new}}{\loadmkxlfile{strc-mar}}
+\loadmkxlfile{strc-mar}
\loadmkxlfile{strc-sbe}
\loadmklxfile{strc-lst}
\loadmkxlfile{strc-sec}
diff --git a/tex/context/base/mkxl/font-emp.mklx b/tex/context/base/mkxl/font-emp.mklx
index 1e30e7012..e99f74afd 100644
--- a/tex/context/base/mkxl/font-emp.mklx
+++ b/tex/context/base/mkxl/font-emp.mklx
@@ -55,28 +55,45 @@
\permanent\protected\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it}
\permanent\protected\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi}
-\permanent\protected\def\normalboldface % public
+\permanent\protected\def\normalboldface % public, upgraded from mkvi / WS
{\relax
+ \ifx\fontalternative\s!tf\bf\orelse
\ifx\fontalternative\s!it\bi\orelse
- \ifx\fontalternative\s!sl\bs\else
+ \ifx\fontalternative\s!sl\bs\orelse
+ \ifx\fontalternative\s!bf \orelse
+ \ifx\fontalternative\s!bi \orelse
+ \ifx\fontalternative\s!bs \else
\bf\fi}
-\permanent\protected\def\normalitalicface % public
+\permanent\protected\def\normalitalicface % public, upgraded from mkvi
{\relax
\ifx\fontalternative\s!tf\it\orelse
- \ifx\fontalternative\s!bf\bi\else
- \tf\fi}
-
-\permanent\protected\def\normalslantedface % public
- {\relax \ifx\fontalternative\s!tf\sl
- \orelse\ifx\fontalternative\s!bf\bs
- \else \tf\fi}
-
-\permanent\protected\def\normaltypeface % public
+ \ifx\fontalternative\s!it \orelse
+ \ifx\fontalternative\s!sl\it\orelse
+ \ifx\fontalternative\s!bf\bi\orelse
+ \ifx\fontalternative\s!bi\bi\orelse
+ \ifx\fontalternative\s!bs\bi\else
+ \it\fi}
+
+\permanent\protected\def\normalslantedface % public, upgraded from mkvi
{\relax
- \ifx\fontalternative\s!bi \it \orelse
- \ifx\fontalternative\s!bs \sl \else
- \tf \fi}
+ \ifx\fontalternative\s!tf\sl\orelse
+ \ifx\fontalternative\s!it\sl\orelse
+ \ifx\fontalternative\s!sl \orelse
+ \ifx\fontalternative\s!bf\bs\orelse
+ \ifx\fontalternative\s!bi\bs\orelse
+ \ifx\fontalternative\s!bs\bs\else
+ \sl\fi}
+
+\permanent\protected\def\normaltypeface % public, upgraded from mkvi
+ {\relax
+ \ifx\fontalternative\s!tf \orelse
+ \ifx\fontalternative\s!it\tf\orelse
+ \ifx\fontalternative\s!sl\tf\orelse
+ \ifx\fontalternative\s!bf \orelse
+ \ifx\fontalternative\s!bi\bf\orelse
+ \ifx\fontalternative\s!bs\bf\else
+ \tf\fi}
\permanent\protected\def\swaptypeface % public
{\relax
@@ -93,6 +110,43 @@
\aliased\let\italicface \normalitalicface % public
\aliased\let\swapface \swaptypeface % public
+%D \startbuffer[demo]
+%D \starttabulate[|l|c|c|c|c|c|c|c|]
+%D \NC \NC \tex{tf} \NC \tex{it} \NC \tex{sl} \NC \tex{bf}
+%D \NC \tex{bi} \NC \tex{bs} \NC \tex{sc} \NC \NR
+%D \NC \NC \tf txt \NC \it txt \NC \sl txt \NC \bf txt
+%D \NC \bi txt \NC \bs txt \NC \sc txt \NC \NR
+%D \NC \tex{typeface} \NC \tf \typeface txt \NC \it \typeface txt \NC \sl \typeface txt \NC \bf \typeface txt
+%D \NC \bi \typeface txt \NC \bs \typeface txt \NC \sc \typeface txt \NC \NR
+%D \NC \tex{boldface} \NC \tf \boldface txt \NC \it \boldface txt \NC \sl \boldface txt \NC \bf \boldface txt
+%D \NC \bi \boldface txt \NC \bs \boldface txt \NC \sc \boldface txt \NC \NR
+%D \NC \tex{slantedface} \NC \tf \slantedface txt \NC \it \slantedface txt \NC \sl \slantedface txt \NC \bf \slantedface txt
+%D \NC \bi \slantedface txt \NC \bs \slantedface txt \NC \sc \slantedface txt \NC \NR
+%D \NC \tex{italicface} \NC \tf \italicface txt \NC \it \italicface txt \NC \sl \italicface txt \NC \bf \italicface txt
+%D \NC \bi \italicface txt \NC \bs \italicface txt \NC \sc \italicface txt \NC \NR
+%D \NC \tex{swapface} \NC \tf \swapface txt \NC \it \swapface txt \NC \sl \swapface txt \NC \bf \swapface txt
+%D \NC \bi \swapface txt \NC \bs \swapface txt \NC \sc \swapface txt \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D {\small \typebuffer[demo]}
+%D
+%D This gives:
+%D
+%D \getbuffer[demo]
+%D
+%D But with:
+%D
+%D \startbuffer
+%D \setupbodyfontenvironment [default] [em=blue] % affects \swapface
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D We get:
+%D
+%D {\getbuffer\getbuffer[demo]}
+
%D To be set with the default body font environment: \type {em} being \type
%D {slanted} or \type {italic}.
diff --git a/tex/context/base/mkxl/lang-def.mkxl b/tex/context/base/mkxl/lang-def.mkxl
index 603935097..441d328c8 100644
--- a/tex/context/base/mkxl/lang-def.mkxl
+++ b/tex/context/base/mkxl/lang-def.mkxl
@@ -554,7 +554,7 @@
% Artificial Languages: Esperanto
\installlanguage
- [\s!esperanto]
+ [\s!eo]
[\c!spacing=\v!packed,
\c!leftsentence=\endash,
\c!rightsentence=\endash,
@@ -569,7 +569,7 @@
\s!lefthyphenmin=2,
\s!righthyphenmin=2]
-\installlanguage[\s!eo][\c!default=\s!esperanto]
+\installlanguage[\s!esperanto][\c!default=\s!eo]
% Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian
diff --git a/tex/context/base/mkxl/publ-ini.mkxl b/tex/context/base/mkxl/publ-ini.mkxl
index 2c52b24e9..f1e60ca43 100644
--- a/tex/context/base/mkxl/publ-ini.mkxl
+++ b/tex/context/base/mkxl/publ-ini.mkxl
@@ -805,9 +805,13 @@
\permanent\protected\def\btxdoifelsecombiinlist#1#2%
{\clf_btxdoifelsecombiinlist{#1}{#2}}
+\permanent\protected\def\btxdoifelsecitedone#1#2%
+ {\clf_btxdoifelsecitedone{#1}{#2}}
+
\aliased\let\btxdoifsameaspreviouscheckedelse\btxdoifelsesameaspreviouschecked
\aliased\let\btxdoifsameaspreviouselse \btxdoifelsesameasprevious
\aliased\let\btxdoifcombiinlistelse \btxdoifelsecombiinlist
+\aliased\let\btxdoifcitedoneelse \btxdoifelsecitedone
\tolerant\def\publ_place_list_indeed#1#2#*[#3]#*[#4]%
{\begingroup
@@ -1303,12 +1307,12 @@
\installcorenamespace{btxinteraction}
-\setvalue{\??btxinteraction\v!number}{\settrue\btxinteractivenumber}
-\setvalue{\??btxinteraction\v!text }{\settrue\btxinteractivetext}
-\setvalue{\??btxinteraction\v!page }{\settrue\btxinteractivepage}
-\setvalue{\??btxinteraction\v!all }{\settrue\btxinteractivenumber
- \settrue\btxinteractivetext
- \settrue\btxinteractivepage}
+\defcsname\??btxinteraction\v!number\endcsname{\settrue\btxinteractivenumber}
+\defcsname\??btxinteraction\v!text \endcsname{\settrue\btxinteractivetext}
+\defcsname\??btxinteraction\v!page \endcsname{\settrue\btxinteractivepage}
+\defcsname\??btxinteraction\v!all \endcsname{\settrue\btxinteractivenumber
+ \settrue\btxinteractivetext
+ \settrue\btxinteractivepage}
% \setupbtx[interaction=page] % or text or number or all
% \setupbtxrendering[pagestate=start]
@@ -1557,7 +1561,7 @@
%D Setup helpers, beware, we need to wrap this .. now we need to know
%D how setups are implemented.
-\setvalue{\??setup:\s!btx:\s!unknown}#1{\inframed{\tttf#1}}
+\defcsname\??setup:\s!btx:\s!unknown\endcsname#1{\inframed{\tttf#1}}
\def\publ_fast_setup_yes#1#2%
{\csname\??setup:\s!btx:%
diff --git a/tex/context/base/mkxl/strc-mar-old.lmt b/tex/context/base/mkxl/strc-mar-old.lmt
new file mode 100644
index 000000000..eb94f9fc3
--- /dev/null
+++ b/tex/context/base/mkxl/strc-mar-old.lmt
@@ -0,0 +1,759 @@
+if not modules then modules = { } end modules ['strc-mar'] = {
+ version = 1.001,
+ comment = "companion to strc-mar.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: cleanup stack (structures.marks.reset(v_all) also does the job)
+-- todo: only commands.* print to tex, native marks return values
+
+local insert, concat = table.insert, table.concat
+local tostring, next, rawget, type = tostring, next, rawget, type
+local lpegmatch = lpeg.match
+
+local context = context
+local commands = commands
+
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local getbox = nuts.getbox
+
+local nextnode = nuts.traversers.node
+
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local whatsit_code = nodecodes.whatsit
+
+local lateluawhatsit_code = whatsitcodes.latelua
+
+local texsetattribute = tex.setattribute
+
+local a_marks = attributes.private("marks")
+
+local trace_set = false trackers.register("marks.set", function(v) trace_set = v end)
+local trace_get = false trackers.register("marks.get", function(v) trace_get = v end)
+local trace_details = false trackers.register("marks.details", function(v) trace_details = v end)
+
+local report_marks = logs.reporter("structure","marks")
+
+local variables = interfaces.variables
+
+local v_first = variables.first
+local v_last = variables.last
+local v_previous = variables.previous
+local v_next = variables.next
+local v_top = variables.top
+local v_bottom = variables.bottom
+local v_current = variables.current
+local v_default = variables.default
+local v_page = variables.page
+local v_all = variables.all
+local v_keep = variables.keep
+
+local v_nocheck_suffix = ":" .. variables.nocheck
+
+local v_first_nocheck = variables.first .. v_nocheck_suffix
+local v_last_nocheck = variables.last .. v_nocheck_suffix
+local v_previous_nocheck = variables.previous .. v_nocheck_suffix
+local v_next_nocheck = variables.next .. v_nocheck_suffix
+local v_top_nocheck = variables.top .. v_nocheck_suffix
+local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix
+
+local structures = structures
+local marks = structures.marks
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local boxes_too = false -- at some point we can also tag boxes or use a zero char
+
+directives.register("marks.boxestoo", function(v) boxes_too = v end)
+
+local data = marks.data or allocate()
+marks.data = data
+
+storage.register("structures/marks/data", marks.data, "structures.marks.data")
+
+local stack, topofstack = { }, 0
+
+local ranges = {
+ [v_page] = {
+ first = 0,
+ last = 0,
+ },
+}
+
+local function resolve(t,k)
+ if k then
+ if trace_set or trace_get then
+ report_marks("undefined mark, name %a",k)
+ end
+ local crap = { autodefined = true } -- maybe set = 0 and reset = 0
+ t[k] = crap
+ return crap
+ else
+ -- weird: k is nil
+ end
+end
+
+setmetatableindex(data, resolve)
+
+function marks.exists(name)
+ return rawget(data,name) ~= nil
+end
+
+-- identify range
+
+local function sweep(head,first,last)
+ for n, id, subtype in nextnode, head do
+ -- we need to handle empty heads so we test for latelua
+ if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then -- brrr
+ local a = getattr(n,a_marks)
+ if not a then
+ -- next
+ elseif first == 0 then
+ first, last = a, a
+ elseif a > last then
+ last = a
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if boxes_too then
+ local a = getattr(n,a_marks)
+ if not a then
+ -- next
+ elseif first == 0 then
+ first, last = a, a
+ elseif a > last then
+ last = a
+ end
+ end
+ local list = getlist(n)
+ if list then
+ first, last = sweep(list,first,last)
+ end
+ end
+ end
+ return first, last
+end
+
+local classes = { }
+
+setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s return s end)
+
+local lasts = { }
+
+function marks.synchronize(class,n,option)
+ local box = getbox(n)
+ if box then
+ local first, last = sweep(getlist(box),0,0)
+ if option == v_keep and first == 0 and last == 0 then
+ if trace_get or trace_set then
+ report_marks("action %a, class %a, box %a","retain at synchronize",class,n)
+ end
+ -- todo: check if still valid first/last in range
+ first = lasts[class] or 0
+ last = first
+ else
+ lasts[class] = last
+ local classlist = classes[class]
+ for i=1,#classlist do
+ local class = classlist[i]
+ local range = ranges[class]
+ if range then
+ range.first = first
+ range.last = last
+ else
+ range = {
+ first = first,
+ last = last,
+ }
+ ranges[class] = range
+ end
+ if trace_get or trace_set then
+ report_marks("action %a, class %a, first %a, last %a","synchronize",class,range.first,range.last)
+ end
+ end
+ end
+ elseif trace_get or trace_set then
+ report_marks("action %s, class %a, box %a","synchronize without content",class,n)
+ end
+end
+
+-- define etc
+
+local function resolve(t,k)
+ if k == "fullchain" then
+ local fullchain = { }
+ local chain = t.chain
+ while chain and chain ~= "" do
+ insert(fullchain,1,chain)
+ chain = data[chain].chain
+ end
+ t[k] = fullchain
+ return fullchain
+ elseif k == "chain" then
+ t[k] = ""
+ return ""
+ elseif k == "reset" or k == "set" then
+ t[k] = 0
+ return 0
+ elseif k == "parent" then
+ t[k] = false
+ return false
+ end
+end
+
+function marks.define(name,settings)
+ if not settings then
+ settings = { }
+ elseif type(settings) == "string" then
+ settings = { parent = settings }
+ end
+ data[name] = settings
+ local parent = settings.parent
+ if parent == nil or parent == "" or parent == name then
+ settings.parent = false
+ else
+ local dp = data[parent]
+ if not dp then
+ settings.parent = false
+ elseif dp.parent then
+ settings.parent = dp.parent
+ end
+ end
+ setmetatableindex(settings, resolve)
+end
+
+for k, v in next, data do
+ setmetatableindex(v,resolve) -- runtime loaded table
+end
+
+local function parentname(name)
+ local dn = data[name]
+ return dn and dn.parent or name
+end
+
+function marks.relate(name,chain)
+ local dn = data[name]
+ if dn and not dn.parent then
+ if chain and chain ~= "" then
+ dn.chain = chain
+ local dc = data[chain]
+ if dc then
+ local children = dc.children
+ if not children then
+ children = { }
+ dc.children = children
+ end
+ children[#children+1] = name
+ end
+ elseif trace_set then
+ report_marks("error: invalid relation, name %a, chain %a",name,chain)
+ end
+ end
+end
+
+local function resetchildren(new,name)
+ local dn = data[name]
+ if dn and not dn.parent then
+ local children = dn.children
+ if children then
+ for i=1,#children do
+ local ci = children[i]
+ new[ci] = false
+ if trace_set then
+ report_marks("action %a, parent %a, child %a","reset",name,ci)
+ end
+ resetchildren(new,ci)
+ end
+ end
+ end
+end
+
+function marks.set(name,value)
+ local dn = data[name]
+ if dn then
+ local child = name
+ local parent = dn.parent
+ if parent then
+ name = parent
+ dn = data[name]
+ end
+ dn.set = topofstack
+ if not dn.reset then
+ dn.reset = 0 -- in case of selfdefined
+ end
+ local top = stack[topofstack]
+ local new = { }
+ if top then
+ for k, v in next, top do
+ local d = data[k]
+ local r = d.reset or 0
+ local s = d.set or 0
+ if r <= topofstack and s < r then
+ new[k] = false
+ else
+ new[k] = v
+ end
+ end
+ end
+ resetchildren(new,name)
+ new[name] = value
+ topofstack = topofstack + 1
+ stack[topofstack] = new
+ if trace_set then
+ if name == child then
+ report_marks("action %a, name %a, index %a, value %a","set",name,topofstack,value)
+ else
+ report_marks("action %a, parent %a, child %a, index %a, value %a","set",parent,child,topofstack,value)
+ end
+ end
+ texsetattribute("global",a_marks,topofstack)
+ end
+end
+
+local function reset(name)
+ if v_all then
+ if trace_set then
+ report_marks("action %a","reset all")
+ end
+ stack = { }
+ for name, dn in next, data do
+ local parent = dn.parent
+ if parent then
+ dn.reset = 0
+ dn.set = 0
+ end
+ end
+ else
+ local dn = data[name]
+ if dn then
+ local parent = dn.parent
+ if parent then
+ name = parent
+ dn = data[name]
+ end
+ if trace_set then
+ report_marks("action %a, name %a, index %a","reset",name,topofstack)
+ end
+ dn.reset = topofstack
+ local children = dn.children
+ if children then
+ for i=1,#children do
+ local ci = children[i]
+ reset(ci)
+ end
+ end
+ end
+ end
+end
+
+marks.reset = reset
+
+function marks.get(n,name,value)
+ local dn = data[name]
+ if dn then
+ name = dn.parent or name
+ local top = stack[n]
+ if top then
+ context(top[name])
+ end
+ end
+end
+
+function marks.show(first,last)
+ if first and last then
+ for k=first,last do
+ local v = stack[k]
+ if v then
+ report_marks("% 4i: %s",k,table.sequenced(v))
+ end
+ end
+ else
+ for k, v in table.sortedpairs(stack) do
+ report_marks("% 4i: %s",k,table.sequenced(v))
+ end
+ end
+end
+
+local function resolve(name,first,last,strict,quitonfalse,notrace)
+ local dn = data[name]
+ if dn then
+ local child = name
+ local parent = dn.parent
+ name = parent or child
+ dn = data[name]
+ local step, method
+ if first > last then
+ step, method = -1, "bottom-up"
+ else
+ step, method = 1, "top-down"
+ end
+ if trace_get and not notrace then
+ report_marks("action %a, strategy %a, name %a, parent %a, strict %a","request",method,child,parent,strict or false)
+ end
+ if trace_details and not notrace then
+ marks.show(first,last)
+ end
+ local r = dn.reset
+ local s = dn.set
+ if first <= last and first <= r then
+ if trace_get and not notrace then
+ report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset first",name,first,last,r,first)
+ end
+ elseif first >= last and last <= r then
+ if trace_get and not notrace then
+ report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset last",name,first,last,r,last)
+ end
+ elseif not stack[first] or not stack[last] then
+ if trace_get and not notrace then
+ -- a previous or next method can give an out of range, which is valid
+ report_marks("error: out of range, name %a, reset %a, index %a",name,r,first)
+ end
+ elseif strict then
+ local top = stack[first]
+ local fullchain = dn.fullchain
+ if not fullchain or #fullchain == 0 then
+ if trace_get and not notrace then
+ report_marks("warning: no full chain, trying again, name %a, first %a, last %a",name,first,last)
+ end
+ return resolve(name,first,last)
+ else
+ if trace_get and not notrace then
+ report_marks("found chain [ % => T ]",fullchain)
+ end
+ local chaindata = { }
+ local chainlength = #fullchain
+ for i=1,chainlength do
+ local cname = fullchain[i]
+ if data[cname].set > 0 then
+ local value = resolve(cname,first,last,false,false,true)
+ if value == "" then
+ if trace_get and not notrace then
+ report_marks("quitting chain, name %a, reset %a, start %a",name,r,first)
+ end
+ return ""
+ else
+ chaindata[i] = value
+ end
+ end
+ end
+ if trace_get and not notrace then
+ report_marks("using chain [ % => T ]",chaindata)
+ end
+ local value, index, found = resolve(name,first,last,false,false,true)
+ if value ~= "" then
+ if trace_get and not notrace then
+ report_marks("following chain [ % => T ]",chaindata)
+ end
+ for i=1,chainlength do
+ local cname = fullchain[i]
+ if data[cname].set > 0 and chaindata[i] ~= found[cname] then
+ if trace_get and not notrace then
+ report_marks("quiting chain, name %a, reset %a, index %a",name,r,first)
+ end
+ return ""
+ end
+ end
+ if trace_get and not notrace then
+ report_marks("found in chain, name %a, reset %a, start %a, index %a, value %a",name,r,first,index,value)
+ end
+ return value, index, found
+ elseif trace_get and not notrace then
+ report_marks("not found, name %a, reset %a",name,r)
+ end
+ end
+ else
+ for i=first,last,step do
+ local current = stack[i]
+ local value = current and current[name]
+ if value == nil then
+ -- search on
+ elseif value == false then
+ if quitonfalse then
+ return ""
+ end
+ elseif value == true then
+ if trace_get and not notrace then
+ report_marks("quitting steps, name %a, reset %a, start %a, index %a",name,r,first,i)
+ end
+ return ""
+ elseif value ~= "" then
+ if trace_get and not notrace then
+ report_marks("found in steps, name %a, reset %a, start %a, index %a, value %a",name,r,first,i,value)
+ end
+ return value, i, current
+ end
+ end
+ if trace_get and not notrace then
+ report_marks("not found in steps, name %a, reset %a",name,r)
+ end
+ end
+ end
+ return ""
+end
+
+-- todo: column:first column:last
+
+local methods = { }
+
+local function doresolve(name,rangename,swap,df,dl,strict)
+ local range = ranges[rangename] or ranges[v_page]
+ local first = range.first
+ local last = range.last
+ if trace_get then
+ report_marks("action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a",
+ "resolving",name,rangename,swap or false,first,last,df,dl,strict or false)
+ end
+ if swap then
+ first, last = last + df, first + dl
+ else
+ first, last = first + df, last + dl
+ end
+ local value, index, found = resolve(name,first,last,strict)
+ -- maybe something more
+ return value, index, found
+end
+
+-- previous : last before sync
+-- next : first after sync
+
+-- top : first in sync
+-- bottom : last in sync
+
+-- first : first not top in sync
+-- last : last not bottom in sync
+
+methods[v_previous] = function(name,range) return doresolve(name,range,false,-1,0,true ) end -- strict
+methods[v_top] = function(name,range) return doresolve(name,range,false, 0,0,true ) end -- strict
+methods[v_bottom] = function(name,range) return doresolve(name,range,true , 0,0,true ) end -- strict
+methods[v_next] = function(name,range) return doresolve(name,range,true , 0,1,true ) end -- strict
+
+methods[v_previous_nocheck] = function(name,range) return doresolve(name,range,false,-1,0,false) end
+methods[v_top_nocheck] = function(name,range) return doresolve(name,range,false, 0,0,false) end
+methods[v_bottom_nocheck] = function(name,range) return doresolve(name,range,true , 0,0,false) end
+methods[v_next_nocheck] = function(name,range) return doresolve(name,range,true , 0,1,false) end
+
+local function do_first(name,range,check)
+ if trace_get then
+ report_marks("action %a, name %a, range %a","resolving first",name,range)
+ end
+ local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
+ if f_found then
+ if trace_get then
+ report_marks("action %a, name %a, range %a","resolving last",name,range)
+ end
+ local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
+ if l_found and l_index > f_index then
+ local name = parentname(name)
+ for i=f_index,l_index,1 do
+ local si = stack[i]
+ local sn = si[name]
+ if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= f_value then
+ if trace_get then
+ report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn)
+ end
+ return sn, i, si
+ end
+ end
+ end
+ end
+ if trace_get then
+ report_marks("resolved, name %a, range %a, using first",name,range)
+ end
+ return f_value, f_index, f_found
+end
+
+local function do_last(name,range,check)
+ if trace_get then
+ report_marks("action %a, name %a, range %a","resolving last",name,range)
+ end
+ local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
+ if l_found then
+ if trace_get then
+ report_marks("action %a, name %a, range %a","resolving first",name,range)
+ end
+ local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
+ if f_found and l_index > f_index then
+ local name = parentname(name)
+ for i=l_index,f_index,-1 do
+ local si = stack[i]
+ local sn = si[name]
+ if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= l_value then
+ if trace_get then
+ report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn)
+ end
+ return sn, i, si
+ end
+ end
+ end
+ end
+ if trace_get then
+ report_marks("resolved, name %a, range %a, using first",name,range)
+ end
+ return l_value, l_index, l_found
+end
+
+methods[v_first ] = function(name,range) return do_first(name,range,true ) end
+methods[v_last ] = function(name,range) return do_last (name,range,true ) end
+methods[v_first_nocheck] = function(name,range) return do_first(name,range,false) end
+methods[v_last_nocheck ] = function(name,range) return do_last (name,range,false) end
+
+methods[v_current] = function(name,range) -- range is ignored here
+ local top = stack[topofstack]
+ return top and top[parentname(name)] or ""
+end
+
+local function fetched(name,range,method)
+ local value = (methods[method] or methods[v_first])(name,range) or ""
+ if not trace_get then
+ -- no report
+ elseif value == "" then
+ report_marks("nothing fetched, name %a, range %a, method %a",name,range,method)
+ else
+ report_marks("marking fetched, name %a, range %a, method %a, value %a",name,range,method,value)
+ end
+ return value or ""
+end
+
+-- can be used at the lua end:
+
+marks.fetched = fetched
+
+-- this will move to a separate runtime modules
+
+marks.tracers = marks.tracers or { }
+
+function marks.tracers.showtable()
+ context.starttabulate { "|l|l|l|lp|lp|" }
+ context.tabulaterowbold("name","parent","chain","children","fullchain")
+ context.ML()
+ for k, v in table.sortedpairs(data) do
+ local parent = v.parent or ""
+ local chain = v.chain or ""
+ local children = v.children or { }
+ local fullchain = v.fullchain or { }
+ table.sort(children) -- in-place but harmless
+ context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," "))
+ end
+ context.stoptabulate()
+end
+
+-- pushing to context:
+
+-- local separator = context.nested.markingseparator
+-- local command = context.nested.markingcommand
+-- local ctxconcat = context.concat
+
+-- local function fetchonemark(name,range,method)
+-- context(command(name,fetched(name,range,method)))
+-- end
+
+-- local function fetchtwomarks(name,range)
+-- ctxconcat( {
+-- command(name,fetched(name,range,v_first)),
+-- command(name,fetched(name,range,v_last)),
+-- }, separator(name))
+-- end
+
+-- local function fetchallmarks(name,range)
+-- ctxconcat( {
+-- command(name,fetched(name,range,v_previous)),
+-- command(name,fetched(name,range,v_first)),
+-- command(name,fetched(name,range,v_last)),
+-- }, separator(name))
+-- end
+
+ local ctx_separator = context.markingseparator
+ local ctx_command = context.markingcommand
+
+ local function fetchonemark(name,range,method)
+ ctx_command(name,fetched(name,range,method))
+ end
+
+ local function fetchtwomarks(name,range)
+ ctx_command(name,fetched(name,range,v_first))
+ ctx_separator(name)
+ ctx_command(name,fetched(name,range,v_last))
+ end
+
+ local function fetchallmarks(name,range)
+ ctx_command(name,fetched(name,range,v_previous))
+ ctx_separator(name)
+ ctx_command(name,fetched(name,range,v_first))
+ ctx_separator(name)
+ ctx_command(name,fetched(name,range,v_last))
+ end
+
+function marks.fetch(name,range,method) -- chapter page first | chapter column:1 first
+ if trace_get then
+ report_marks("marking requested, name %a, range %a, method %a",name,range,method)
+ end
+ if method == "" or method == v_default then
+ fetchonemark(name,range,v_first)
+ elseif method == v_both then
+ fetchtwomarks(name,range)
+ elseif method == v_all then
+ fetchallmarks(name,range)
+ else
+ fetchonemark(name,range,method)
+ end
+end
+
+function marks.fetchonemark (name,range,method) fetchonemark (name,range,method) end
+function marks.fetchtwomarks(name,range) fetchtwomarks(name,range ) end
+function marks.fetchallmarks(name,range) fetchallmarks(name,range ) end
+
+-- here we have a few helpers .. will become commands.*
+
+local pattern = lpeg.afterprefix("li::")
+
+function marks.title(tag,n)
+ local listindex = lpegmatch(pattern,n)
+ if listindex then
+ commands.savedlisttitle(tag,listindex,"marking")
+ else
+ context(n)
+ end
+end
+
+function marks.number(tag,n) -- no spec
+ local listindex = lpegmatch(pattern,n)
+ if listindex then
+ commands.savedlistnumber(tag,listindex)
+ else
+ -- no prefix (as it is the prefix)
+ context(n)
+ end
+end
+
+-- interface
+
+implement { name = "markingtitle", actions = marks.title, arguments = "2 strings" }
+implement { name = "markingnumber", actions = marks.number, arguments = "2 strings" }
+
+implement { name = "definemarking", actions = marks.define, arguments = "2 strings" }
+implement { name = "relatemarking", actions = marks.relate, arguments = "2 strings" }
+implement { name = "setmarking", actions = marks.set, arguments = "2 strings" }
+implement { name = "resetmarking", actions = marks.reset, arguments = "string" }
+implement { name = "synchronizemarking", actions = marks.synchronize, arguments = { "string", "integer", "string" } }
+implement { name = "getmarking", actions = marks.fetch, arguments = "3 strings" }
+implement { name = "fetchonemark", actions = marks.fetchonemark, arguments = "3 strings" }
+implement { name = "fetchtwomarks", actions = marks.fetchtwomarks, arguments = "2 strings" }
+implement { name = "fetchallmarks", actions = marks.fetchallmarks, arguments = "2 strings" }
+
+implement { name = "doifelsemarking", actions = { marks.exists, commands.doifelse }, arguments = "string" }
diff --git a/tex/context/base/mkxl/strc-mar-old.mkxl b/tex/context/base/mkxl/strc-mar-old.mkxl
new file mode 100644
index 000000000..b2c421dbf
--- /dev/null
+++ b/tex/context/base/mkxl/strc-mar-old.mkxl
@@ -0,0 +1,142 @@
+%D \module
+%D [ file=strc-mar,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Markings,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Markings}
+
+\registerctxluafile{strc-mar-old}{autosuffix}
+
+\unprotect
+
+%D Synchronizing marks is a rather tricky and messy business. When setting a mark, a
+%D node is added to the list in order for to \TEX\ be able to figure out the 3
+%D current marks when a page is made (last mark on previous page, first on current
+%D page, last on current page; in \LUATEX\ we might at one point have the first on
+%D the next page as well).
+%D
+%D Resetting a mark is not easy. An empty one will not erase the last one on the
+%D previous page for instance. In \LUATEX\ we can clear a marks state register with
+%D \type {\clearmarks} but since this is an immediate operation it might have
+%D unwanted side effects when \TEX\ has collected several pages of text and
+%D finishing off these pages uses marks.
+%D
+%D In \MKIV\ we provide an alternative model that permits some more control over the
+%D way marks are used. It is not entirely compatible with \MKII\ or previous \MKIV\
+%D implementations but in practice this is not a real problem. It's also easier now
+%D to extend this mechanism.
+
+% first last previous next top bottom [:nocheck]
+% current
+% default page all keep
+
+\definesystemattribute [marks] [global]
+
+\installcorenamespace{marking}
+
+\installcommandhandler \??marking {marking} \??marking
+
+\newconditional\inhibitgetmarking % will become private
+\newconditional\inhibitsetmarking % will become private
+
+\newtoks \everymarking
+
+\appendtoks
+ \clf_definemarking{\currentmarking}{\currentmarkingparent}%
+\to \everydefinemarking
+
+\permanent\protected\tolerant\def\relatemarking [#1]#*[#2]{\clf_relatemarking{#1}{#2}}
+\permanent\protected\tolerant\def\resetmarking [#1]{\clf_resetmarking{#1}}
+\permanent\protected\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi}
+\permanent \def\doifelsemarking #1{\clf_doifelsemarking{#1}} % no \noexpanded
+
+\aliased\let\clearmarking\resetmarking % different in the new situation
+
+\def\strc_markings_synchronize#1#2#3{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} % called in page-ini
+
+\permanent\protected\tolerant\def\setmarking[#1]#:#2%
+ {\ifconditional\inhibitsetmarking\else
+ \doifelse{\namedmarkingparameter{#1}\c!expansion}\v!yes
+ {\clf_setmarking{#1}{#2}}%
+ {\clf_setmarking{#1}{\detokenize{#2}}}%
+ \fi}
+
+\aliased\let\marking \setmarking
+\aliased\let\doifmarkingelse\doifelsemarking
+
+% defaults
+
+\setupmarking
+ [\c!expansion=\v!no,
+ \c!separator=\space\emdash\space,
+ \c!filtercommand=\firstofoneargument,
+ \c!state=\v!start]
+
+% fetching, regular interface
+
+\permanent\protected\def\getmarking
+ {\ifconditional\inhibitgetmarking
+ \expandafter\strc_markings_get_nop
+ \else
+ \expandafter\strc_markings_get_yes
+ \fi}
+
+\tolerant\def\strc_markings_get_nop[#-]#*[#-]#*[#-]%
+ {}
+
+\tolerant\def\strc_markings_get_yes[#1]#*[#2]#*[#3]%
+ {\ifcstok{\namedmarkingparameter{#1}\c!state}\v!start
+ \begingroup
+ \setsystemmode\v!marking
+ \the\everymarking
+ \ifparameter#3\or
+ \clf_getmarking{#1}{#2}{#3}%
+ \else
+ \clf_getmarking{#1}{\v!page}{#2}%
+ \fi
+ \endgroup
+ \fi}
+
+% the fetchers are fully expandable: [name][method]
+
+\permanent\tolerant\def\fetchonemark[#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{\v!page}{#2}\fi}
+\permanent\tolerant\def\fetchtwomarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{\v!page}\fi}
+\permanent\tolerant\def\fetchallmarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{\v!page}\fi}
+
+\aliased\let\fetchmark\fetchonemark
+
+% also fully expandable but here we have: [name][range][method]
+
+\permanent\tolerant\def\fetchonemarking[#1]#*[#2]#*[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{#2}{#3}\fi}
+\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{#2}\fi}
+\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{#2}\fi}
+
+\aliased\let\fetchmarking\fetchonemarking
+
+\permanent\def\markingseparator#1{\namedmarkingparameter{#1}\c!separator}
+\permanent\def\markingcommand #1{\namedmarkingparameter{#1}\c!filtercommand}
+
+%D Experimental:
+%D
+%D \starttyping
+%D \definemarking[boxmark]
+%D
+%D \setbox0\ruledvbox{
+%D \marking[boxmark]{tufte} \input tufte \par
+%D \marking[boxmark]{ward} \input ward \par
+%D }
+%D
+%D \synchronizemarking[zerobox][0] \box0
+%D
+%D marks: (\getmarking[boxmark][zerobox][first],\getmarking[boxmark][zerobox][last])
+%D \stoptyping
+
+\protect \endinput
diff --git a/tex/context/base/mkxl/strc-mar.lmt b/tex/context/base/mkxl/strc-mar.lmt
index eb94f9fc3..e5266daf0 100644
--- a/tex/context/base/mkxl/strc-mar.lmt
+++ b/tex/context/base/mkxl/strc-mar.lmt
@@ -6,719 +6,143 @@ if not modules then modules = { } end modules ['strc-mar'] = {
license = "see context related readme files"
}
--- todo: cleanup stack (structures.marks.reset(v_all) also does the job)
--- todo: only commands.* print to tex, native marks return values
-
-local insert, concat = table.insert, table.concat
-local tostring, next, rawget, type = tostring, next, rawget, type
local lpegmatch = lpeg.match
-
-local context = context
-local commands = commands
-
-local implement = interfaces.implement
-
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
-
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getattr = nuts.getattr
-local getbox = nuts.getbox
-
-local nextnode = nuts.traversers.node
-
-local nodecodes = nodes.nodecodes
-local whatsitcodes = nodes.whatsitcodes
-
-local glyph_code = nodecodes.glyph
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local whatsit_code = nodecodes.whatsit
-
-local lateluawhatsit_code = whatsitcodes.latelua
-
-local texsetattribute = tex.setattribute
-
-local a_marks = attributes.private("marks")
-
-local trace_set = false trackers.register("marks.set", function(v) trace_set = v end)
-local trace_get = false trackers.register("marks.get", function(v) trace_get = v end)
-local trace_details = false trackers.register("marks.details", function(v) trace_details = v end)
-
-local report_marks = logs.reporter("structure","marks")
-
-local variables = interfaces.variables
-
-local v_first = variables.first
-local v_last = variables.last
-local v_previous = variables.previous
-local v_next = variables.next
-local v_top = variables.top
-local v_bottom = variables.bottom
-local v_current = variables.current
-local v_default = variables.default
-local v_page = variables.page
-local v_all = variables.all
-local v_keep = variables.keep
-
-local v_nocheck_suffix = ":" .. variables.nocheck
-
-local v_first_nocheck = variables.first .. v_nocheck_suffix
-local v_last_nocheck = variables.last .. v_nocheck_suffix
-local v_previous_nocheck = variables.previous .. v_nocheck_suffix
-local v_next_nocheck = variables.next .. v_nocheck_suffix
-local v_top_nocheck = variables.top .. v_nocheck_suffix
-local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix
-
-local structures = structures
-local marks = structures.marks
-
-local settings_to_array = utilities.parsers.settings_to_array
-
-local boxes_too = false -- at some point we can also tag boxes or use a zero char
-
-directives.register("marks.boxestoo", function(v) boxes_too = v end)
-
-local data = marks.data or allocate()
-marks.data = data
-
-storage.register("structures/marks/data", marks.data, "structures.marks.data")
-
-local stack, topofstack = { }, 0
-
-local ranges = {
- [v_page] = {
- first = 0,
- last = 0,
- },
-}
-
-local function resolve(t,k)
- if k then
- if trace_set or trace_get then
- report_marks("undefined mark, name %a",k)
- end
- local crap = { autodefined = true } -- maybe set = 0 and reset = 0
- t[k] = crap
- return crap
- else
- -- weird: k is nil
- end
-end
-
-setmetatableindex(data, resolve)
-
-function marks.exists(name)
- return rawget(data,name) ~= nil
-end
-
--- identify range
-
-local function sweep(head,first,last)
- for n, id, subtype in nextnode, head do
- -- we need to handle empty heads so we test for latelua
- if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then -- brrr
- local a = getattr(n,a_marks)
- if not a then
- -- next
- elseif first == 0 then
- first, last = a, a
- elseif a > last then
- last = a
- end
- elseif id == hlist_code or id == vlist_code then
- if boxes_too then
- local a = getattr(n,a_marks)
- if not a then
- -- next
- elseif first == 0 then
- first, last = a, a
- elseif a > last then
- last = a
- end
- end
- local list = getlist(n)
+local setmetatableindex = table.setmetatableindex
+
+local context = context
+
+local implement = interfaces.implement
+local variables = interfaces.variables
+
+local v_first = variables.first
+local v_last = variables.last
+local v_previous = variables.previous
+local v_next = variables.next
+local v_column = variables.column
+
+local nuts = nodes.nuts
+local nextmark = nuts.traversers.mark
+local getbox = nuts.getbox
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getindex = nuts.getindex
+local getdata = nuts.getdata
+----- setmark_code = nodes.markcodes.set
+local flushmark_code = nodes.markcodes.flush
+local hlist_code = nodes.nodecodes.hlist
+local vlist_code = nodes.nodecodes.vlist
+
+local marks = { }
+structures.marks = marks
+
+local markdata = setmetatableindex("table")
+local pattern = lpeg.splitat(":")
+
+implement {
+ name = "synchronizemarking",
+ arguments = { "string", "integer", "integer" },
+ actions = function(category,index,boxnumber)
+ local new = setmetatableindex("table")
+ local box = getbox(boxnumber)
+ while box and getid(box) == hlist_code do
+ box = getlist(box)
+ end
+ if box and getid(box) == vlist_code then
+ local list = getlist(box)
if list then
- first, last = sweep(list,first,last)
- end
- end
- end
- return first, last
-end
-
-local classes = { }
-
-setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s return s end)
-
-local lasts = { }
-
-function marks.synchronize(class,n,option)
- local box = getbox(n)
- if box then
- local first, last = sweep(getlist(box),0,0)
- if option == v_keep and first == 0 and last == 0 then
- if trace_get or trace_set then
- report_marks("action %a, class %a, box %a","retain at synchronize",class,n)
- end
- -- todo: check if still valid first/last in range
- first = lasts[class] or 0
- last = first
- else
- lasts[class] = last
- local classlist = classes[class]
- for i=1,#classlist do
- local class = classlist[i]
- local range = ranges[class]
- if range then
- range.first = first
- range.last = last
- else
- range = {
- first = first,
- last = last,
- }
- ranges[class] = range
- end
- if trace_get or trace_set then
- report_marks("action %a, class %a, first %a, last %a","synchronize",class,range.first,range.last)
- end
- end
- end
- elseif trace_get or trace_set then
- report_marks("action %s, class %a, box %a","synchronize without content",class,n)
- end
-end
-
--- define etc
-
-local function resolve(t,k)
- if k == "fullchain" then
- local fullchain = { }
- local chain = t.chain
- while chain and chain ~= "" do
- insert(fullchain,1,chain)
- chain = data[chain].chain
- end
- t[k] = fullchain
- return fullchain
- elseif k == "chain" then
- t[k] = ""
- return ""
- elseif k == "reset" or k == "set" then
- t[k] = 0
- return 0
- elseif k == "parent" then
- t[k] = false
- return false
- end
-end
-
-function marks.define(name,settings)
- if not settings then
- settings = { }
- elseif type(settings) == "string" then
- settings = { parent = settings }
- end
- data[name] = settings
- local parent = settings.parent
- if parent == nil or parent == "" or parent == name then
- settings.parent = false
- else
- local dp = data[parent]
- if not dp then
- settings.parent = false
- elseif dp.parent then
- settings.parent = dp.parent
- end
- end
- setmetatableindex(settings, resolve)
-end
-
-for k, v in next, data do
- setmetatableindex(v,resolve) -- runtime loaded table
-end
-
-local function parentname(name)
- local dn = data[name]
- return dn and dn.parent or name
-end
-
-function marks.relate(name,chain)
- local dn = data[name]
- if dn and not dn.parent then
- if chain and chain ~= "" then
- dn.chain = chain
- local dc = data[chain]
- if dc then
- local children = dc.children
- if not children then
- children = { }
- dc.children = children
- end
- children[#children+1] = name
- end
- elseif trace_set then
- report_marks("error: invalid relation, name %a, chain %a",name,chain)
- end
- end
-end
-
-local function resetchildren(new,name)
- local dn = data[name]
- if dn and not dn.parent then
- local children = dn.children
- if children then
- for i=1,#children do
- local ci = children[i]
- new[ci] = false
- if trace_set then
- report_marks("action %a, parent %a, child %a","reset",name,ci)
- end
- resetchildren(new,ci)
- end
- end
- end
-end
-
-function marks.set(name,value)
- local dn = data[name]
- if dn then
- local child = name
- local parent = dn.parent
- if parent then
- name = parent
- dn = data[name]
- end
- dn.set = topofstack
- if not dn.reset then
- dn.reset = 0 -- in case of selfdefined
- end
- local top = stack[topofstack]
- local new = { }
- if top then
- for k, v in next, top do
- local d = data[k]
- local r = d.reset or 0
- local s = d.set or 0
- if r <= topofstack and s < r then
- new[k] = false
- else
- new[k] = v
- end
- end
- end
- resetchildren(new,name)
- new[name] = value
- topofstack = topofstack + 1
- stack[topofstack] = new
- if trace_set then
- if name == child then
- report_marks("action %a, name %a, index %a, value %a","set",name,topofstack,value)
- else
- report_marks("action %a, parent %a, child %a, index %a, value %a","set",parent,child,topofstack,value)
- end
- end
- texsetattribute("global",a_marks,topofstack)
- end
-end
-
-local function reset(name)
- if v_all then
- if trace_set then
- report_marks("action %a","reset all")
- end
- stack = { }
- for name, dn in next, data do
- local parent = dn.parent
- if parent then
- dn.reset = 0
- dn.set = 0
- end
- end
- else
- local dn = data[name]
- if dn then
- local parent = dn.parent
- if parent then
- name = parent
- dn = data[name]
- end
- if trace_set then
- report_marks("action %a, name %a, index %a","reset",name,topofstack)
- end
- dn.reset = topofstack
- local children = dn.children
- if children then
- for i=1,#children do
- local ci = children[i]
- reset(ci)
- end
- end
- end
- end
-end
-
-marks.reset = reset
-
-function marks.get(n,name,value)
- local dn = data[name]
- if dn then
- name = dn.parent or name
- local top = stack[n]
- if top then
- context(top[name])
- end
- end
-end
-
-function marks.show(first,last)
- if first and last then
- for k=first,last do
- local v = stack[k]
- if v then
- report_marks("% 4i: %s",k,table.sequenced(v))
- end
- end
- else
- for k, v in table.sortedpairs(stack) do
- report_marks("% 4i: %s",k,table.sequenced(v))
- end
- end
-end
-
-local function resolve(name,first,last,strict,quitonfalse,notrace)
- local dn = data[name]
- if dn then
- local child = name
- local parent = dn.parent
- name = parent or child
- dn = data[name]
- local step, method
- if first > last then
- step, method = -1, "bottom-up"
- else
- step, method = 1, "top-down"
- end
- if trace_get and not notrace then
- report_marks("action %a, strategy %a, name %a, parent %a, strict %a","request",method,child,parent,strict or false)
- end
- if trace_details and not notrace then
- marks.show(first,last)
- end
- local r = dn.reset
- local s = dn.set
- if first <= last and first <= r then
- if trace_get and not notrace then
- report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset first",name,first,last,r,first)
- end
- elseif first >= last and last <= r then
- if trace_get and not notrace then
- report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset last",name,first,last,r,last)
- end
- elseif not stack[first] or not stack[last] then
- if trace_get and not notrace then
- -- a previous or next method can give an out of range, which is valid
- report_marks("error: out of range, name %a, reset %a, index %a",name,r,first)
- end
- elseif strict then
- local top = stack[first]
- local fullchain = dn.fullchain
- if not fullchain or #fullchain == 0 then
- if trace_get and not notrace then
- report_marks("warning: no full chain, trying again, name %a, first %a, last %a",name,first,last)
- end
- return resolve(name,first,last)
- else
- if trace_get and not notrace then
- report_marks("found chain [ % => T ]",fullchain)
- end
- local chaindata = { }
- local chainlength = #fullchain
- for i=1,chainlength do
- local cname = fullchain[i]
- if data[cname].set > 0 then
- local value = resolve(cname,first,last,false,false,true)
- if value == "" then
- if trace_get and not notrace then
- report_marks("quitting chain, name %a, reset %a, start %a",name,r,first)
- end
- return ""
- else
- chaindata[i] = value
+ for n, subtype in nextmark, list do
+ local class = getindex(n)
+ local entry = new[class]
+ if subtype == flushmark_code then
+ entry.first = false
+ entry.last = false
+ else
+ if not entry.first then
+ entry.first = n
end
+ entry.last = n
end
end
- if trace_get and not notrace then
- report_marks("using chain [ % => T ]",chaindata)
- end
- local value, index, found = resolve(name,first,last,false,false,true)
- if value ~= "" then
- if trace_get and not notrace then
- report_marks("following chain [ % => T ]",chaindata)
- end
- for i=1,chainlength do
- local cname = fullchain[i]
- if data[cname].set > 0 and chaindata[i] ~= found[cname] then
- if trace_get and not notrace then
- report_marks("quiting chain, name %a, reset %a, index %a",name,r,first)
- end
- return ""
- end
+ for class, entry in next, new do
+ local first = entry.first
+ local last = entry.last
+ if last and first ~= last then
+ entry.last = getdata(last,true)
end
- if trace_get and not notrace then
- report_marks("found in chain, name %a, reset %a, start %a, index %a, value %a",name,r,first,index,value)
+ if first then
+ entry.first = getdata(first,true)
end
- return value, index, found
- elseif trace_get and not notrace then
- report_marks("not found, name %a, reset %a",name,r)
end
+ else
+ -- wipe empty columns
end
else
- for i=first,last,step do
- local current = stack[i]
- local value = current and current[name]
- if value == nil then
- -- search on
- elseif value == false then
- if quitonfalse then
- return ""
- end
- elseif value == true then
- if trace_get and not notrace then
- report_marks("quitting steps, name %a, reset %a, start %a, index %a",name,r,first,i)
- end
- return ""
- elseif value ~= "" then
- if trace_get and not notrace then
- report_marks("found in steps, name %a, reset %a, start %a, index %a, value %a",name,r,first,i,value)
- end
- return value, i, current
- end
- end
- if trace_get and not notrace then
- report_marks("not found in steps, name %a, reset %a",name,r)
- end
- end
- end
- return ""
-end
-
--- todo: column:first column:last
-
-local methods = { }
-
-local function doresolve(name,rangename,swap,df,dl,strict)
- local range = ranges[rangename] or ranges[v_page]
- local first = range.first
- local last = range.last
- if trace_get then
- report_marks("action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a",
- "resolving",name,rangename,swap or false,first,last,df,dl,strict or false)
- end
- if swap then
- first, last = last + df, first + dl
- else
- first, last = first + df, last + dl
- end
- local value, index, found = resolve(name,first,last,strict)
- -- maybe something more
- return value, index, found
-end
-
--- previous : last before sync
--- next : first after sync
-
--- top : first in sync
--- bottom : last in sync
-
--- first : first not top in sync
--- last : last not bottom in sync
-
-methods[v_previous] = function(name,range) return doresolve(name,range,false,-1,0,true ) end -- strict
-methods[v_top] = function(name,range) return doresolve(name,range,false, 0,0,true ) end -- strict
-methods[v_bottom] = function(name,range) return doresolve(name,range,true , 0,0,true ) end -- strict
-methods[v_next] = function(name,range) return doresolve(name,range,true , 0,1,true ) end -- strict
-
-methods[v_previous_nocheck] = function(name,range) return doresolve(name,range,false,-1,0,false) end
-methods[v_top_nocheck] = function(name,range) return doresolve(name,range,false, 0,0,false) end
-methods[v_bottom_nocheck] = function(name,range) return doresolve(name,range,true , 0,0,false) end
-methods[v_next_nocheck] = function(name,range) return doresolve(name,range,true , 0,1,false) end
-
-local function do_first(name,range,check)
- if trace_get then
- report_marks("action %a, name %a, range %a","resolving first",name,range)
- end
- local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
- if f_found then
- if trace_get then
- report_marks("action %a, name %a, range %a","resolving last",name,range)
- end
- local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
- if l_found and l_index > f_index then
- local name = parentname(name)
- for i=f_index,l_index,1 do
- local si = stack[i]
- local sn = si[name]
- if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= f_value then
- if trace_get then
- report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn)
+ -- wipe empty columns
+ end
+ local m = markdata[category]
+ if m then
+ local entry = m[index]
+ if entry then
+ local prev = index == 1 and m[#m] or m[index-1]
+ for class, data in next, entry do
+ local pcls = prev[class]
+ local last = pcls and pcls.last
+ if last then
+ local ncls = new[class]
+ ncls.previous = last
+ if not ncls.first then
+ ncls.first = last
+ end
+ if not ncls.last then
+ ncls.last = ncls.first
+ end
end
- return sn, i, si
end
end
+ m[index] = new
+ else
+ new.previous = ""
+ markdata[category] = { [index] = new }
end
- end
- if trace_get then
- report_marks("resolved, name %a, range %a, using first",name,range)
- end
- return f_value, f_index, f_found
-end
+ -- inspect(data)
+ end,
+}
-local function do_last(name,range,check)
- if trace_get then
- report_marks("action %a, name %a, range %a","resolving last",name,range)
- end
- local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
- if l_found then
- if trace_get then
- report_marks("action %a, name %a, range %a","resolving first",name,range)
- end
- local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
- if f_found and l_index > f_index then
- local name = parentname(name)
- for i=l_index,f_index,-1 do
- local si = stack[i]
- local sn = si[name]
- if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= l_value then
- if trace_get then
- report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn)
+implement {
+ name = "getsynchronizedmarking",
+ arguments = { "integer", "string", "string" },
+ actions = function(class,category,what)
+ local category, n = lpegmatch(pattern,category)
+ local useddata = markdata[category]
+ if useddata then
+ local index = tonumber(n) or 1
+ local data = useddata[index]
+ if data then
+ local entry = data[class]
+ if entry then
+ if what == v_first then
+ context(entry.first or "")
+ elseif what == v_last then
+ context(entry.last or "")
+ elseif what == v_previous then
+ context(entry.previous or "")
+ elseif what == v_next then
+ -- context(entry.next or "") -- will be done when i need it, unreliable anyway
end
- return sn, i, si
end
end
end
end
- if trace_get then
- report_marks("resolved, name %a, range %a, using first",name,range)
- end
- return l_value, l_index, l_found
-end
-
-methods[v_first ] = function(name,range) return do_first(name,range,true ) end
-methods[v_last ] = function(name,range) return do_last (name,range,true ) end
-methods[v_first_nocheck] = function(name,range) return do_first(name,range,false) end
-methods[v_last_nocheck ] = function(name,range) return do_last (name,range,false) end
-
-methods[v_current] = function(name,range) -- range is ignored here
- local top = stack[topofstack]
- return top and top[parentname(name)] or ""
-end
-
-local function fetched(name,range,method)
- local value = (methods[method] or methods[v_first])(name,range) or ""
- if not trace_get then
- -- no report
- elseif value == "" then
- report_marks("nothing fetched, name %a, range %a, method %a",name,range,method)
- else
- report_marks("marking fetched, name %a, range %a, method %a, value %a",name,range,method,value)
- end
- return value or ""
-end
-
--- can be used at the lua end:
-
-marks.fetched = fetched
-
--- this will move to a separate runtime modules
-
-marks.tracers = marks.tracers or { }
-
-function marks.tracers.showtable()
- context.starttabulate { "|l|l|l|lp|lp|" }
- context.tabulaterowbold("name","parent","chain","children","fullchain")
- context.ML()
- for k, v in table.sortedpairs(data) do
- local parent = v.parent or ""
- local chain = v.chain or ""
- local children = v.children or { }
- local fullchain = v.fullchain or { }
- table.sort(children) -- in-place but harmless
- context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," "))
- end
- context.stoptabulate()
-end
-
--- pushing to context:
-
--- local separator = context.nested.markingseparator
--- local command = context.nested.markingcommand
--- local ctxconcat = context.concat
-
--- local function fetchonemark(name,range,method)
--- context(command(name,fetched(name,range,method)))
--- end
-
--- local function fetchtwomarks(name,range)
--- ctxconcat( {
--- command(name,fetched(name,range,v_first)),
--- command(name,fetched(name,range,v_last)),
--- }, separator(name))
--- end
-
--- local function fetchallmarks(name,range)
--- ctxconcat( {
--- command(name,fetched(name,range,v_previous)),
--- command(name,fetched(name,range,v_first)),
--- command(name,fetched(name,range,v_last)),
--- }, separator(name))
--- end
-
- local ctx_separator = context.markingseparator
- local ctx_command = context.markingcommand
-
- local function fetchonemark(name,range,method)
- ctx_command(name,fetched(name,range,method))
- end
-
- local function fetchtwomarks(name,range)
- ctx_command(name,fetched(name,range,v_first))
- ctx_separator(name)
- ctx_command(name,fetched(name,range,v_last))
- end
-
- local function fetchallmarks(name,range)
- ctx_command(name,fetched(name,range,v_previous))
- ctx_separator(name)
- ctx_command(name,fetched(name,range,v_first))
- ctx_separator(name)
- ctx_command(name,fetched(name,range,v_last))
- end
+}
-function marks.fetch(name,range,method) -- chapter page first | chapter column:1 first
- if trace_get then
- report_marks("marking requested, name %a, range %a, method %a",name,range,method)
- end
- if method == "" or method == v_default then
- fetchonemark(name,range,v_first)
- elseif method == v_both then
- fetchtwomarks(name,range)
- elseif method == v_all then
- fetchallmarks(name,range)
- else
- fetchonemark(name,range,method)
+implement {
+ name = "resetsynchronizedmarking",
+ arguments = "argument",
+ actions = function(category)
+ local category, n = lpegmatch(pattern,category)
+ markdata[category] = nil
end
-end
-
-function marks.fetchonemark (name,range,method) fetchonemark (name,range,method) end
-function marks.fetchtwomarks(name,range) fetchtwomarks(name,range ) end
-function marks.fetchallmarks(name,range) fetchallmarks(name,range ) end
-
--- here we have a few helpers .. will become commands.*
+}
local pattern = lpeg.afterprefix("li::")
@@ -743,17 +167,5 @@ end
-- interface
-implement { name = "markingtitle", actions = marks.title, arguments = "2 strings" }
-implement { name = "markingnumber", actions = marks.number, arguments = "2 strings" }
-
-implement { name = "definemarking", actions = marks.define, arguments = "2 strings" }
-implement { name = "relatemarking", actions = marks.relate, arguments = "2 strings" }
-implement { name = "setmarking", actions = marks.set, arguments = "2 strings" }
-implement { name = "resetmarking", actions = marks.reset, arguments = "string" }
-implement { name = "synchronizemarking", actions = marks.synchronize, arguments = { "string", "integer", "string" } }
-implement { name = "getmarking", actions = marks.fetch, arguments = "3 strings" }
-implement { name = "fetchonemark", actions = marks.fetchonemark, arguments = "3 strings" }
-implement { name = "fetchtwomarks", actions = marks.fetchtwomarks, arguments = "2 strings" }
-implement { name = "fetchallmarks", actions = marks.fetchallmarks, arguments = "2 strings" }
-
-implement { name = "doifelsemarking", actions = { marks.exists, commands.doifelse }, arguments = "string" }
+implement { name = "markingtitle", actions = marks.title, arguments = "2 strings" }
+implement { name = "markingnumber", actions = marks.number,arguments = "2 strings" }
diff --git a/tex/context/base/mkxl/strc-mar.mkxl b/tex/context/base/mkxl/strc-mar.mkxl
index fcce83173..a0767e609 100644
--- a/tex/context/base/mkxl/strc-mar.mkxl
+++ b/tex/context/base/mkxl/strc-mar.mkxl
@@ -34,13 +34,31 @@
%D implementations but in practice this is not a real problem. It's also easier now
%D to extend this mechanism.
-% first last previous next top bottom [:nocheck]
+%D In \LUAMETATEX\ we have extended the marks mechanism with a few handy options.
+%D First of all we have automigration built in for inserts and marks (so we no
+%D longer need to do that in \LUA) and marks can be properly flushed.
+
+% \ifdefined\automigrationmode \automigrationmode0 \fi
+% \starttext
+% \dorecurse{10}{
+% \dontleavehmode\setbox0\hbox{SAMPLE #1}\box0
+% \marks\foomark{sample #1}%
+% \samplefile{tufte}\par
+% }%
+% \stoptext
+
% current
+
+% column:n | n | column | etc ... now only column:n
+
% default page all keep
-\definesystemattribute [marks] [global]
+%definesystemattribute [marks] [global]
\installcorenamespace{marking}
+\installcorenamespace{markingclass}
+\installcorenamespace{markingsyncs}
+\installcorenamespace{markingfilter}
\installcommandhandler \??marking {marking} \??marking
@@ -49,24 +67,70 @@
\newtoks \everymarking
+% \clf_definemarking{\currentmarking}{\currentmarkingparent}%
+
\appendtoks
- \clf_definemarking{\currentmarking}{\currentmarkingparent}%
+ \ifcsname\??markingclass\currentmarking\endcsname\else
+ \ifempty\currentmarkingparent
+ \expandafter\newmarks\csname\??markingclass\currentmarking\endcsname
+ \expandafter\newtoks \csname\??markingsyncs\currentmarking\endcsname
+ \else
+ \expandafter\letcsname\??markingclass\currentmarking\expandafter\endcsname\csname\??markingclass\currentmarkingparent\endcsname
+ \expandafter\letcsname\??markingsyncs\currentmarking\expandafter\endcsname\csname\??markingsyncs\currentmarkingparent\endcsname
+ \fi
+ \fi
\to \everydefinemarking
-\permanent\protected\tolerant\def\relatemarking [#1]#*[#2]{\clf_relatemarking{#1}{#2}}
-\permanent\protected\tolerant\def\resetmarking [#1]{\clf_resetmarking{#1}}
-\permanent\protected\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi}
-\permanent \def\doifelsemarking #1{\clf_doifelsemarking{#1}} % no \noexpanded
+\permanent\protected\tolerant\def\relatemarking[#1]#*[#2]%
+ {\ifarguments\or\else
+ \xtoksapp\csname\??markingsyncs#2\endcsname{%
+ \flushmarks\csname\??markingclass#1\endcsname
+ \noexpand\the\begincsname\??markingsyncs#1\endcsname
+ }%
+ \fi}
+
+\permanent\protected\tolerant\def\clearmarking[#1]%
+ {\ifarguments\else
+ \begingroup
+ \clearmarks\csname\??markingclass#1\endcsname
+ \enforced\let\flushmarks\clearmarks
+ \the\csname\??markingsyncs#1\endcsname
+ \endgroup
+ \fi}
+
+\permanent\protected\tolerant\def\resetmarking[#1]%
+ {\ifarguments\else
+ % probably best: \dontleavehmode
+ \the\csname\??markingsyncs#1\endcsname
+ \fi}
-\aliased\let\clearmarking\resetmarking % different in the new situation
+\permanent\protected\tolerant\def\resetsynchronizemarking[#1]%
+ {\clf_resetsynchronizemarking{#1}}
-\def\strc_markings_synchronize#1#2#3{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} % called in page-ini
+\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]% #3: options
+ {\clf_synchronizemarking{#1}\plusone\numexpr#2\relax}
+
+\def\strc_markings_synchronize#1#2#3% category n box
+ {\ifvoid#3\orelse\ifcstok{#1}\v!page\else
+ \clf_synchronizemarking{#1}\numexpr#2\relax\numexpr#3\relax
+ \fi}
+
+\permanent\def\doifelsemarking#1%
+ {\ifcondition\ifcommandhandler\??marking{#1}%
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
\permanent\protected\tolerant\def\setmarking[#1]#:#2%
- {\ifconditional\inhibitsetmarking\else
- \doifelse{\namedmarkingparameter{#1}\c!expansion}\v!yes
- {\clf_setmarking{#1}{#2}}%
- {\clf_setmarking{#1}{\detokenize{#2}}}%
+ {\ifarguments\orelse\ifconditional\inhibitsetmarking\else
+ % probably best: \dontleavehmode
+ \the\csname\??markingsyncs#1\endcsname
+ \ifcstok{\namedmarkingparameter{#1}\c!expansion}\v!yes
+ \marks\csname\??markingclass#1\endcsname{#2}%
+ \else
+ \marks\csname\??markingclass#1\endcsname{\detokenize{#2}}%
+ \fi
\fi}
\aliased\let\marking \setmarking
@@ -111,19 +175,85 @@
\endgroup
\fi}
+% previous : last before sync next : first after sync
+% top : first in sync bottom : last in sync
+% first|default : first not top in sync last : last not bottom in sync
+
+% current
+
+\defcsname\??markingfilter\v!previous\endcsname#1{\topmarks \csname\??markingclass#1\endcsname}
+\defcsname\??markingfilter\v!next \endcsname#1{\botmarks \csname\??markingclass#1\endcsname}
+
+%defcsname\??markingfilter\v!top \endcsname#1{\topmarks \csname\??markingclass#1\endcsname}
+\defcsname\??markingfilter\v!top \endcsname#1{\firstmarks \csname\??markingclass#1\endcsname}
+\defcsname\??markingfilter\v!bottom \endcsname#1{\botmarks \csname\??markingclass#1\endcsname}
+
+\defcsname\??markingfilter\v!first \endcsname#1{\firstmarks \csname\??markingclass#1\endcsname}
+\defcsname\??markingfilter\v!last \endcsname#1{\botmarks \csname\??markingclass#1\endcsname}
+
+\defcsname\??markingfilter\v!current \endcsname#1{\currentmarks\csname\??markingclass#1\endcsname}
+
+\letcsname\??markingfilter\v!default\expandafter\endcsname
+ \csname\??markingfilter\v!first \endcsname
+
% the fetchers are fully expandable: [name][method]
-\permanent\tolerant\def\fetchonemark[#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{\v!page}{#2}\fi}
-\permanent\tolerant\def\fetchtwomarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{\v!page}\fi}
-\permanent\tolerant\def\fetchallmarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{\v!page}\fi}
+\def\strc_markings_fetch_one#1#2#3%
+ {\ifparameter#1\or
+ \ifconditional\inhibitgetmarking\else
+ \ifcstok{#2}\v!page
+ \markingcommand{#1}{\begincsname\??markingfilter#3\endcsname{#1}}%
+ \else
+ \markingcommand{#1}{\clf_getsynchronizedmarking{#1}{#2}}%
+ \fi
+ \fi
+ \fi}
+
+\def\strc_markings_fetch_two#1#2%
+ {\ifparameter#1\or
+ \ifconditional\inhibitgetmarking\else
+ \ifcstok{#2}\v!page
+ \markingcommand{#1}{\begincsname\??markingfilter\v!first\endcsname{#1}}%
+ \markingseparator{#1}%
+ \markingcommand{#1}{\begincsname\??markingfilter\v!last\endcsname{#1}}%
+ \else
+ \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!first}%
+ \markingseparator{#1}%
+ \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!last}%
+ \fi
+ \fi
+ \fi}
+
+\def\strc_markings_fetch_all#1#2%
+ {\ifparameter#1\or
+ \ifconditional\inhibitgetmarking\else
+ \ifcstok{#2}\v!page
+ \markingcommand{#1}{\begincsname\??markingfilter\v!previous\endcsname{#1}}%
+ \markingseparator{#1}%
+ \markingcommand{#1}{\begincsname\??markingfilter\v!first\endcsname{#1}}%
+ \markingseparator{#1}%
+ \markingcommand{#1}{\begincsname\??markingfilter\v!last\endcsname{#1}}%
+ \else
+ %\markingcommand{#1}{\begincsname\??markclass:\v!previous\endcsname{#1}}%
+ %\markingseparator{#1}%
+ \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!first}%
+ \markingseparator{#1}%
+ \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!last}%
+ \fi
+ \fi
+ \fi}
+
+\permanent\tolerant\def\fetchonemark [#1]#*[#2]{\strc_markings_fetch_one{#1}\v!page{#2}}
+\permanent\tolerant\def\fetchtwomarks [#1]{\strc_markings_fetch_two{#1}\v!page}
+\permanent\tolerant\def\fetchallmarks [#1]{\strc_markings_fetch_all{#1}\v!page}
\aliased\let\fetchmark\fetchonemark
% also fully expandable but here we have: [name][range][method]
-\permanent\tolerant\def\fetchonemarking[#1]#*[#2]#*[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{#2}{#3}\fi}
-\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{#2}\fi}
-\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{#2}\fi}
+\permanent\tolerant\def\fetchonemarking [#1]#*[#2]#*[#3]{\strc_markings_fetch_one{#1}{#2}{#3}}
+\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\strc_markings_fetch_two{#1}{#2}}
+\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\strc_markings_fetch_all{#1}{#2}}
\aliased\let\fetchmarking\fetchonemarking
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 02f89ada1..72164b777 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 : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 2021-10-08 20:05
+-- merge date : 2021-10-10 23:40
do -- begin closure to overcome local limits and interference