1if not modules then modules = { } end modules ['pack-obj'] = {
2 version = 1.001,
3 comment = "companion to pack-obj.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 context = context
15local codeinjections = backends.codeinjections
16local ctx_doifelse = commands.doifelse
17
18local report = logs.reporter("objects")
19local trace = false trackers.register("objects",function(v) trace = v end)
20
21local nuts = nodes.nuts
22
23local setlink = nuts.setlink
24local getlist = nuts.getlist
25local setbox = nuts.setbox
26
27local new_latelua = nuts.pool.latelua
28
29local settexdimen = tokens.setters.dimen
30
31local getcount = tex.getcount
32
33local implement = interfaces.implement
34local setmacro = interfaces.setmacro
35
36local allocate = utilities.storage.allocate
37
38local collected = allocate()
39local tobesaved = allocate()
40
41local jobobjects = {
42 collected = collected,
43 tobesaved = tobesaved,
44}
45
46job.objects = jobobjects
47
48local function initializer()
49 collected = jobobjects.collected
50 tobesaved = jobobjects.tobesaved
51end
52
53job.register('job.objects.collected', tobesaved, initializer, nil)
54
55local function saveobject(tag,number,page)
56 local data = { number, page }
57 tobesaved[tag] = data
58 collected[tag] = data
59end
60
61local function saveobjectspec(specification)
62 local tag = specification.tag
63 local data = { specification.number, specification.page }
64 tobesaved[tag] = data
65 collected[tag] = data
66end
67
68local function setobject(tag,number,page)
69 collected[tag] = { number, page }
70end
71
72local function getobject(tag)
73 return collected[tag] or tobesaved[tag]
74end
75
76local function getobjectnumber(tag,default)
77 local o = collected[tag] or tobesaved[tag]
78 return o and o[1] or default
79end
80
81local function getobjectpage(tag,default)
82 local o = collected[tag] or tobesaved[tag]
83 return o and o[2] or default
84end
85
86jobobjects.save = saveobject
87jobobjects.set = setobject
88jobobjects.get = getobject
89jobobjects.number = getobjectnumber
90jobobjects.page = getobjectpage
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128local data = table.setmetatableindex("table")
129
130objects = {
131 data = data,
132 n = 0,
133}
134
135local objects = objects
136
137function objects.register(ns,id,b,referenced,offset,mode)
138 local n = objects.n + 1
139 objects.n = n
140 nodes.handlers.finalizebox(b)
141 if mode == 0 then
142
143 data[ns][id] = {
144 codeinjections.registerboxresource(b),
145 offset,
146 referenced or false,
147 mode,
148 }
149 else
150
151 data[ns][id] = {
152 codeinjections.registerboxresource(b,offset),
153 false,
154 referenced,
155 mode,
156 }
157 end
158 if trace then
159 report("registering object %a (n=%i)",id,n)
160 end
161end
162
163function objects.restore(ns,id)
164 local d = data[ns][id]
165 if d then
166 local index = d[1]
167 local offset = d[2]
168 local status = d[3]
169 local mode = d[4]
170 local hbox = codeinjections.restoreboxresource(index)
171 if status then
172 local list = getlist(hbox)
173 local page = new_latelua {
174 action = saveobjectspec,
175 tag = ns .. "::" .. id,
176 number = index,
177 page = getcount("realpageno"),
178 }
179
180 setlink(list,page)
181 end
182 setbox("objectbox",hbox)
183 settexdimen("objectoff",offset or 0)
184 else
185 setbox("objectbox",nil)
186 settexdimen("objectoff",0)
187 end
188 if trace then
189 report("restoring object %a",id)
190 end
191end
192
193function objects.dimensions(index)
194 local d = data[ns][id]
195 if d then
196 return codeinjections.boxresourcedimensions(d[1])
197 else
198 return 0, 0, 0, 0
199 end
200end
201
202function objects.reference(ns,id)
203 local d = data[ns][id]
204 if d then
205 return d[1]
206 else
207 return getobjectnumber(ns .."::" .. id,0)
208 end
209end
210
211function objects.page(ns,id)
212 return getobjectpage(ns .."::" .. id,getcount("realpageno"))
213end
214
215function objects.found(ns,id)
216 return data[ns][id]
217end
218
219implement {
220 name = "registerreferencedobject",
221 arguments = { "string", "string", "integer", true, "dimension", "integer" },
222 actions = objects.register,
223}
224
225implement {
226 name = "registerobject",
227 arguments = { "string", "string", "integer", false, "dimension", "integer" },
228 actions = objects.register,
229}
230
231implement {
232 name = "restoreobject",
233 arguments = "2 strings",
234 actions = objects.restore,
235}
236
237implement {
238 name = "doifelseobject",
239 arguments = "2 strings",
240 actions = function(ns,id)
241 ctx_doifelse(data[ns][id])
242
243 end,
244}
245
246implement {
247 name = "doifelseobjectreference",
248 arguments = "2 strings",
249 actions = function(ns,id)
250
251 ctx_doifelse(objects.reference(ns,id))
252 end,
253}
254
255implement {
256 name = "getobjectreference",
257 arguments = { "string", "string", "csname" },
258 actions = function(ns,id,target)
259 setmacro(target,objects.reference(ns,id),"global")
260 end
261}
262
263implement {
264 name = "getobjectreferencepage",
265 arguments = { "string", "string", "csname" },
266 actions = function(ns,id,target)
267 setmacro(target,objects.page(ns,id),"global")
268 end
269}
270
271implement {
272 name = "getobjectdimensions",
273 arguments = "2 strings",
274 actions = function(ns,id)
275 local object = data[ns][id]
276 local w, h, d, o = 0, 0, 0, 0
277 if object then
278 w, h, d, o = codeinjections.boxresourcedimensions(object[1])
279 end
280 settexdimen("objectwd",w or 0)
281 settexdimen("objectht",h or 0)
282 settexdimen("objectdp",d or 0)
283 settexdimen("objectoff",o or #objects > 2 and object[2] or 0)
284 end
285}
286
287
288
289implement {
290 name = "registerbackendsymbol",
291 arguments = { "string", "integer" },
292 actions = function(...)
293 codeinjections.registersymbol(...)
294 end
295}
296 |