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
91local data = table.setmetatableindex("table")
92
93objects = {
94 data = data,
95 n = 0,
96}
97
98local objects = objects
99
100function objects.register(ns,id,b,referenced,offset,mode,delay)
101
102
103 local found = data[ns][id]
104 nodes.handlers.finalizebox(b)
105 if found and delay == 2 then
106 data[ns][id] = {
107 codeinjections.registerboxresource(b,nil,nil,found[1]),
108 offset,
109 referenced or false,
110 mode,
111 }
112 return
113 elseif mode == 0 then
114
115 data[ns][id] = {
116 codeinjections.registerboxresource(b,nil,delay),
117 offset,
118 referenced or false,
119 mode,
120 }
121 else
122
123 data[ns][id] = {
124 codeinjections.registerboxresource(b,offset,delay),
125 false,
126 referenced,
127 mode,
128 }
129 end
130 if trace then
131 report("registering object %a (n=%i)",id,n)
132 end
133end
134
135function objects.restore(ns,id)
136 local d = data[ns][id]
137 if d then
138 local index = d[1]
139 local offset = d[2]
140 local status = d[3]
141 local mode = d[4]
142 local hbox = codeinjections.restoreboxresource(index)
143 if status then
144 local list = getlist(hbox)
145 local page = new_latelua {
146 action = saveobjectspec,
147 tag = ns .. "::" .. id,
148 number = index,
149 page = getcount("realpageno"),
150 }
151
152 setlink(list,page)
153 end
154 setbox("b_pack_objects",hbox)
155 settexdimen("d_pack_objects_offset",offset or 0)
156 else
157 setbox("b_pack_objects",nil)
158 settexdimen("d_pack_objects_offset",0)
159 end
160 if trace then
161 report("restoring object %a",id)
162 end
163end
164
165function objects.dimensions(index)
166 local d = data[ns][id]
167 if d then
168 return codeinjections.boxresourcedimensions(d[1])
169 else
170 return 0, 0, 0, 0
171 end
172end
173
174function objects.reference(ns,id)
175 local d = data[ns][id]
176 if d then
177 return d[1]
178 else
179 return getobjectnumber(ns .."::" .. id,0)
180 end
181end
182
183function objects.page(ns,id)
184 return getobjectpage(ns .."::" .. id,getcount("realpageno"))
185end
186
187function objects.found(ns,id)
188 return data[ns][id]
189end
190
191implement {
192 name = "registerreferencedobject",
193 arguments = { "string", "string", "integer", true, "dimension", "integer", "integer" },
194 actions = objects.register,
195}
196
197implement {
198 name = "registerobject",
199 arguments = { "string", "string", "integer", false, "dimension", "integer", "integer" },
200 actions = objects.register,
201}
202
203implement {
204 name = "restoreobject",
205 arguments = "2 strings",
206 actions = objects.restore,
207}
208
209implement {
210 name = "doifelseobjectfound",
211 arguments = "2 arguments",
212 public = true,
213 protected = true,
214 actions = function(ns,id)
215 ctx_doifelse(data[ns][id])
216
217 end,
218}
219
220implement {
221 name = "doifelseobjectreferencefound",
222 arguments = "2 arguments",
223 public = true,
224 protected = true,
225 actions = function(ns,id)
226
227 ctx_doifelse(objects.reference(ns,id))
228 end,
229}
230
231implement {
232 name = "getobjectreference",
233 arguments = { "argument", "argument", "csname" },
234 public = true,
235 protected = true,
236 actions = function(ns,id,target)
237 setmacro(target,objects.reference(ns,id),"global")
238 end
239}
240
241implement {
242 name = "getobjectreferencepage",
243 arguments = { "argument", "argument", "csname" },
244 public = true,
245 protected = true,
246 actions = function(ns,id,target)
247 setmacro(target,objects.page(ns,id),"global")
248 end
249}
250
251implement {
252 name = "getobjectdimensions",
253 arguments = "2 arguments",
254 public = true,
255 protected = true,
256 actions = function(ns,id)
257 local object = data[ns][id]
258 local w, h, d, o = 0, 0, 0, 0
259 if object then
260 w, h, d, o = codeinjections.boxresourcedimensions(object[1])
261 end
262 settexdimen("d_pack_objects_width", w or 0)
263 settexdimen("d_pack_objects_height",h or 0)
264 settexdimen("d_pack_objects_depth", d or 0)
265 settexdimen("d_pack_objects_offset",o or #objects > 2 and object[2] or 0)
266 end
267}
268
269
270
271implement {
272 name = "registerbackendsymbol",
273 arguments = { "string", "integer" },
274 actions = function(...)
275 codeinjections.registersymbol(...)
276 end
277}
278 |