core-pag.lmt /size: 4243 b    last modification: 2024-01-16 10:22
1if not modules then modules = { } end modules ['core-dat'] = {
2    version   = 1.001,
3    comment   = "companion to core-dat.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
9-- This module provides a (multipass) container for arbitrary data. It replaces the
10-- twopass data mechanism.
11
12local tonumber = tonumber
13
14local context           = context
15local ctx_latelua       = context.latelua
16
17local trace_pagestates  = false  trackers.register("job.pagestates", function(v) trace_pagestates = v end)
18
19local report_pagestate  = logs.reporter("pagestate")
20
21local allocate          = utilities.storage.allocate
22
23local texgetcount       = tex.getcount
24local texsetcount       = tex.setcount
25
26local new_latelua       = nodes.pool.latelua
27
28local implement         = interfaces.implement
29local getnamespace      = interfaces.getnamespace
30
31local c_realpageno      = tex.iscount("realpageno")
32local c_realpagestateno = tex.iscount("realpagestateno")
33
34local collected = allocate()
35local tobesaved = allocate()
36
37local pagestates = {
38    collected = collected,
39    tobesaved = tobesaved,
40}
41
42job.pagestates = pagestates
43
44local function initializer()
45    collected = pagestates.collected
46    tobesaved = pagestates.tobesaved
47end
48
49job.register("job.pagestates.collected", tobesaved, initializer, nil)
50
51table.setmetatableindex(tobesaved, "table")
52
53local function setstate(settings)
54    local name = settings.name
55    local tag  = settings.tag
56    local list = tobesaved[name]
57    if not tag then
58        tag = #list + 1
59    else
60        tag = tonumber(tag) or tag -- autonumber saves keys
61    end
62    local realpage = texgetcount(c_realpageno)
63    local data = realpage
64    list[tag] = data
65    if trace_pagestates then
66        report_pagestate("action %a, name %a, tag %a, preset %a","set",name,tag,realpage)
67    end
68    return name, tag, data
69end
70
71local function extend(name,tag)
72    local realpage = texgetcount(c_realpageno)
73    if trace_pagestates then
74        report_pagestate("action %a, name %a, tag %a, preset %a","synchronize",name,tag,realpage)
75    end
76    tobesaved[name][tag] = realpage
77end
78
79local function realpage(name,tag,default)
80    local t = collected[name]
81    if t then
82        t = t[tag] or t[tonumber(tag)]
83        if t then
84            return tonumber(t or default)
85        elseif trace_pagestates then
86            report_pagestate("error: unknown dataset, name %a, tag %a",name,tag)
87        end
88    elseif trace_pagestates then
89        report_pagestate("error: unknown dataset, name %a, tag %a",name) -- nil
90    end
91    return default
92end
93
94local function realpageorder(name,tag)
95    local t = collected[name]
96    if t then
97        local p = t[tag]
98        if p then
99            local n = 1
100            for i=tag-1,1,-1 do
101                if t[i] == p then
102                    n = n  +1
103                end
104            end
105            return n
106        end
107    end
108    return 0
109end
110
111pagestates.setstate      = setstate
112pagestates.extend        = extend
113pagestates.realpage      = realpage
114pagestates.realpageorder = realpageorder
115
116function pagestates.countervalue(name)
117    return name and texgetcount(getnamespace("pagestatecounter") .. name) or 0
118end
119
120local function setpagestate(settings)
121    local name, tag = setstate(settings)
122 -- context(new_latelua(function() extend(name,tag) end))
123    ctx_latelua(function() extend(name,tag) end)
124end
125
126local function setpagestaterealpageno(name,tag)
127    local t = collected[name]
128    t = t and (t[tag] or t[tonumber(tag)])
129    texsetcount("realpagestateno",t or texgetcount(c_realpageno))
130end
131
132implement {
133    name      = "setpagestate",
134    actions   = setpagestate,
135    arguments = {
136        {
137            { "name" },
138            { "tag" },
139            { "delay" },
140        }
141    }
142}
143
144implement {
145    name      = "pagestaterealpage",
146    actions   = { realpage, context },
147    arguments = "2 strings",
148}
149
150implement {
151    name      = "setpagestaterealpageno",
152    actions   = setpagestaterealpageno,
153    arguments = "2 strings",
154}
155
156implement {
157    name      = "pagestaterealpageorder",
158    actions   = { realpageorder, context },
159    arguments = { "string", "integer" }
160}
161