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
13
14local tonumber, tostring, type = tonumber, tostring, type
15
16local context = context
17local commands = commands
18local ctx_latelua = context.latelua
19
20local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end)
21local trace_pagestates = false trackers.register("job.pagestates", function(v) trace_pagestates = v end)
22
23local report_dataset = logs.reporter("dataset")
24local report_pagestate = logs.reporter("pagestate")
25
26local allocate = utilities.storage.allocate
27local settings_to_hash = utilities.parsers.settings_to_hash
28
29local texgetcount = tex.getcount
30local texsetcount = tex.setcount
31
32local formatters = string.formatters
33
34local v_yes = interfaces.variables.yes
35
36local new_latelua = nodes.pool.latelua
37
38local implement = interfaces.implement
39local getnamespace = interfaces.getnamespace
40
41local collected = allocate()
42local tobesaved = allocate()
43
44local datasets = {
45 collected = collected,
46 tobesaved = tobesaved,
47}
48
49job.datasets = datasets
50
51local function initializer()
52 collected = datasets.collected
53 tobesaved = datasets.tobesaved
54end
55
56job.register('job.datasets.collected', tobesaved, initializer, nil)
57
58local sets = { }
59
60table.setmetatableindex(tobesaved, function(t,k)
61 local v = { }
62 t[k] = v
63 return v
64end)
65
66table.setmetatableindex(sets, function(t,k)
67 local v = {
68 index = 0,
69 order = 0,
70 }
71 t[k] = v
72 return v
73end)
74
75local function setdata(settings)
76 local name = settings.name
77 local tag = settings.tag
78 local data = settings.data
79 local list = tobesaved[name]
80 if settings.convert and type(data) == "string" then
81 data = settings_to_hash(data)
82 end
83 if type(data) ~= "table" then
84 data = { data = data }
85 end
86 if not tag then
87 tag = #list + 1
88 else
89 tag = tonumber(tag) or tag
90 end
91 list[tag] = data
92 if settings.delay == v_yes then
93 local set = sets[name]
94 local index = set.index + 1
95 set.index = index
96 data.index = index
97 data.order = index
98 data.realpage = texgetcount("realpageno")
99 if trace_datasets then
100 report_dataset("action %a, name %a, tag %a, index %a","assign delayed",name,tag,index)
101 end
102 elseif trace_datasets then
103 report_dataset("action %a, name %a, tag %a","assign immediate",name,tag)
104 end
105 return name, tag, data
106end
107
108datasets.setdata = setdata
109
110function datasets.extend(name,tag)
111 if type(name) == "table" then
112 name, tag = name.name, name.tag
113 end
114 local set = sets[name]
115 local order = set.order + 1
116 local realpage = texgetcount("realpageno")
117 set.order = order
118 local t = tobesaved[name][tag]
119 t.realpage = realpage
120 t.order = order
121 if trace_datasets then
122 report_dataset("action %a, name %a, tag %a, page %a, index %a","flush by order",name,tag,t.index or 0,order,realpage)
123 end
124end
125
126function datasets.getdata(name,tag,key,default)
127 local t = collected[name]
128 if t == nil then
129 if trace_datasets then
130 report_dataset("error: unknown dataset, name %a",name)
131 end
132 elseif type(t) ~= "table" then
133 return t
134 else
135 t = t[tag] or t[tonumber(tag)]
136 if not t then
137 if trace_datasets then
138 report_dataset("error: unknown dataset, name %a, tag %a",name,tag)
139 end
140 elseif key then
141 return t[key] or default
142 else
143 return t
144 end
145 end
146 return default
147end
148
149local function setdataset(settings)
150 settings.convert = true
151 local name, tag = setdata(settings)
152 if settings.delay ~= v_yes then
153
154 else
155 context(new_latelua { action = job.datasets.extend, name = name, tag = tag })
156 end
157end
158
159local function datasetvariable(name,tag,key)
160 local t = collected[name]
161 if t == nil then
162 if trace_datasets then
163 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name)
164 end
165 elseif type(t) ~= "table" then
166 context(tostring(t))
167 else
168 t = t and (t[tag] or t[tonumber(tag)])
169 if not t then
170 if trace_datasets then
171 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
172 end
173 elseif type(t) == "table" then
174 local s = t[key]
175 if type(s) ~= "table" then
176 context(tostring(s))
177 elseif trace_datasets then
178 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
179 end
180 end
181 end
182end
183
184implement {
185 name = "setdataset",
186 actions = setdataset,
187 arguments = {
188 {
189 { "name" },
190 { "tag" },
191 { "delay" },
192 { "data" },
193 }
194 }
195}
196
197implement {
198 name = "datasetvariable",
199 actions = datasetvariable,
200 arguments = "3 strings",
201}
202
203
206
207local collected = allocate()
208local tobesaved = allocate()
209
210local pagestates = {
211 collected = collected,
212 tobesaved = tobesaved,
213}
214
215job.pagestates = pagestates
216
217local function initializer()
218 collected = pagestates.collected
219 tobesaved = pagestates.tobesaved
220end
221
222job.register('job.pagestates.collected', tobesaved, initializer, nil)
223
224table.setmetatableindex(tobesaved, function(t,k)
225 local v = { }
226 t[k] = v
227 return v
228end)
229
230local function setstate(settings)
231 local name = settings.name
232 local tag = settings.tag
233 local list = tobesaved[name]
234 if not tag then
235 tag = #list + 1
236 else
237 tag = tonumber(tag) or tag
238 end
239 local realpage = texgetcount("realpageno")
240 local data = realpage
241 list[tag] = data
242 if trace_pagestates then
243 report_pagestate("action %a, name %a, tag %a, preset %a","set",name,tag,realpage)
244 end
245 return name, tag, data
246end
247
248local function extend(name,tag)
249 local realpage = texgetcount("realpageno")
250 if trace_pagestates then
251 report_pagestate("action %a, name %a, tag %a, preset %a","synchronize",name,tag,realpage)
252 end
253 tobesaved[name][tag] = realpage
254end
255
256local function realpage(name,tag,default)
257 local t = collected[name]
258 if t then
259 t = t[tag] or t[tonumber(tag)]
260 if t then
261 return tonumber(t or default)
262 elseif trace_pagestates then
263 report_pagestate("error: unknown dataset, name %a, tag %a",name,tag)
264 end
265 elseif trace_pagestates then
266 report_pagestate("error: unknown dataset, name %a, tag %a",name)
267 end
268 return default
269end
270
271local function realpageorder(name,tag)
272 local t = collected[name]
273 if t then
274 local p = t[tag]
275 if p then
276 local n = 1
277 for i=tag-1,1,-1 do
278 if t[i] == p then
279 n = n +1
280 end
281 end
282 return n
283 end
284 end
285 return 0
286end
287
288pagestates.setstate = setstate
289pagestates.extend = extend
290pagestates.realpage = realpage
291pagestates.realpageorder = realpageorder
292
293function pagestates.countervalue(name)
294 return name and texgetcount(getnamespace("pagestatecounter") .. name) or 0
295end
296
297local function setpagestate(settings)
298 local name, tag = setstate(settings)
299
300 ctx_latelua(function() extend(name,tag) end)
301end
302
303local function setpagestaterealpageno(name,tag)
304 local t = collected[name]
305 t = t and (t[tag] or t[tonumber(tag)])
306 texsetcount("realpagestateno",t or texgetcount("realpageno"))
307end
308
309implement {
310 name = "setpagestate",
311 actions = setpagestate,
312 arguments = {
313 {
314 { "name" },
315 { "tag" },
316 { "delay" },
317 }
318 }
319}
320
321implement {
322 name = "pagestaterealpage",
323 actions = { realpage, context },
324 arguments = "2 strings",
325}
326
327implement {
328 name = "setpagestaterealpageno",
329 actions = setpagestaterealpageno,
330 arguments = "2 strings",
331}
332
333implement {
334 name = "pagestaterealpageorder",
335 actions = { realpageorder, context },
336 arguments = { "string", "integer" }
337}
338 |