strc-mar.lmt /size: 5536 b    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['strc-mar'] = {
2    version   = 1.001,
3    comment   = "companion to strc-mar.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local lpegmatch = lpeg.match
10local setmetatableindex = table.setmetatableindex
11
12local context        = context
13
14local implement      = interfaces.implement
15local variables      = interfaces.variables
16
17local v_first        = variables.first
18local v_last         = variables.last
19local v_previous     = variables.previous
20local v_next         = variables.next
21local v_column       = variables.column
22
23local nuts           = nodes.nuts
24local nextmark       = nuts.traversers.mark
25local getbox         = nuts.getbox
26local getid          = nuts.getid
27local getlist        = nuts.getlist
28local getindex       = nuts.getindex
29local getdata        = nuts.getdata
30----- setmark_code   = nodes.markcodes.set
31local flushmark_code = nodes.markcodes.flush
32local hlist_code     = nodes.nodecodes.hlist
33local vlist_code     = nodes.nodecodes.vlist
34
35local marks      = { }
36structures.marks = marks
37
38local markdata = setmetatableindex("table")
39local pattern  = lpeg.splitat(":")
40
41implement {
42    name      = "synchronizemarking",
43    arguments =  { "string", "integer", "integer" },
44    actions   = function(category,index,boxnumber)
45        local new = setmetatableindex("table")
46        local box = getbox(boxnumber)
47        while box and getid(box) == hlist_code do
48            box = getlist(box)
49        end
50        if box and getid(box) == vlist_code then
51            local list = getlist(box)
52            if list then
53                for n, subtype in nextmark, list do
54                    local class = getindex(n)
55                    local entry = new[class]
56                    if subtype == flushmark_code then
57                        entry.first = false
58                        entry.last  = false
59                    else
60                        if not entry.first then
61                            entry.first = n
62                        end
63                        entry.last = n
64                    end
65                end
66                for class, entry in next, new do
67                    local first = entry.first
68                    local last  = entry.last
69                    if last and first ~= last then
70                        entry.last = getdata(last,true)
71                    end
72                    if first then
73                        entry.first = getdata(first,true)
74                    end
75                end
76            else
77                -- wipe empty columns
78            end
79        else
80            -- wipe empty columns
81        end
82        local m = markdata[category]
83        if m then
84            local entry = m[index]
85            if entry then
86                local prev = index == 1 and m[#m] or m[index-1]
87                for class, data in next, entry do
88                    local pcls = prev[class]
89                    local last = pcls and pcls.last
90                    if last then
91                        local ncls = new[class]
92                        ncls.previous = last
93                        if not ncls.first then
94                            ncls.first = last
95                        end
96                        if not ncls.last then
97                            ncls.last = ncls.first
98                        end
99                    end
100                end
101            end
102            m[index] = new
103        else
104            new.previous = ""
105            markdata[category] = { [index] = new }
106        end
107     -- inspect(data)
108    end,
109}
110
111implement {
112    name      = "getsynchronizemarking",
113    arguments = { "integer", "string", "string" },
114    actions   = function(class,category,what)
115        local category, n = lpegmatch(pattern,category)
116        local useddata = markdata[category]
117        if useddata then
118            local index = tonumber(n) or 1
119            local data  = useddata[index]
120            if data then
121                local entry = data[class]
122                if entry then
123                    if what == v_first then
124                        context(entry.first or "")
125                    elseif what == v_last then
126                        context(entry.last or "")
127                    elseif what == v_previous then
128                        context(entry.previous or "")
129                    elseif what == v_next then
130                     -- context(entry.next or "") -- will be done when i need it, unreliable anyway
131                    end
132                end
133            end
134        end
135    end
136}
137
138implement {
139    name      = "resetsynchronizemarking",
140    arguments = "argument",
141    actions   = function(category)
142        local category, n = lpegmatch(pattern,category)
143        markdata[category] = nil
144    end
145}
146
147local pattern = lpeg.afterprefix("li::")
148
149function marks.title(tag,n)
150    local listindex = lpegmatch(pattern,n)
151    if listindex then
152        commands.savedlisttitle(tag,listindex,"marking")
153    else
154        context(n)
155    end
156end
157
158function marks.number(tag,n) -- no spec
159    local listindex = lpegmatch(pattern,n)
160    if listindex then
161        commands.savedlistnumber(tag,listindex)
162    else
163        -- no prefix (as it is the prefix)
164        context(n)
165    end
166end
167
168-- interface
169
170implement { name = "markingtitle",  actions = marks.title, arguments = "2 strings" }
171implement { name = "markingnumber", actions = marks.number,arguments = "2 strings" }
172