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