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 setlink ( list , page )
180 end
181 setbox ( " objectbox " , hbox )
182 settexdimen ( " objectoff " , offset or 0 )
183 else
184 setbox ( " objectbox " , nil )
185 settexdimen ( " objectoff " , 0 )
186 end
187 if trace then
188 report ( " restoring object %a " , id )
189 end
190end
191
192function objects . dimensions ( index )
193 local d = data [ ns ] [ id ]
194 if d then
195 return codeinjections . boxresourcedimensions ( d [ 1 ] )
196 else
197 return 0 , 0 , 0 , 0
198 end
199end
200
201function objects . reference ( ns , id )
202 local d = data [ ns ] [ id ]
203 if d then
204 return d [ 1 ]
205 else
206 return getobjectnumber ( ns . . " :: " . . id , 0 )
207 end
208end
209
210function objects . page ( ns , id )
211 return getobjectpage ( ns . . " :: " . . id , getcount ( " realpageno " ) )
212end
213
214function objects . found ( ns , id )
215 return data [ ns ] [ id ]
216end
217
218implement {
219 name = " registerreferencedobject " ,
220 arguments = { " string " , " string " , " integer " , true , " dimension " , " integer " } ,
221 actions = objects . register ,
222}
223
224implement {
225 name = " registerobject " ,
226 arguments = { " string " , " string " , " integer " , false , " dimension " , " integer " } ,
227 actions = objects . register ,
228}
229
230implement {
231 name = " restoreobject " ,
232 arguments = " 2 strings " ,
233 actions = objects . restore ,
234}
235
236implement {
237 name = " doifelseobject " ,
238 arguments = " 2 strings " ,
239 actions = function ( ns , id )
240 ctx_doifelse ( data [ ns ] [ id ] )
241
242 end ,
243}
244
245implement {
246 name = " doifelseobjectreference " ,
247 arguments = " 2 strings " ,
248 actions = function ( ns , id )
249
250 ctx_doifelse ( objects . reference ( ns , id ) )
251 end ,
252}
253
254implement {
255 name = " getobjectreference " ,
256 arguments = { " string " , " string " , " csname " } ,
257 actions = function ( ns , id , target )
258 setmacro ( target , objects . reference ( ns , id ) , " global " )
259 end
260}
261
262implement {
263 name = " getobjectreferencepage " ,
264 arguments = { " string " , " string " , " csname " } ,
265 actions = function ( ns , id , target )
266 setmacro ( target , objects . page ( ns , id ) , " global " )
267 end
268}
269
270implement {
271 name = " getobjectdimensions " ,
272 arguments = " 2 strings " ,
273 actions = function ( ns , id )
274 local object = data [ ns ] [ id ]
275 local w , h , d , o = 0 , 0 , 0 , 0
276 if object then
277 w , h , d , o = codeinjections . boxresourcedimensions ( object [ 1 ] )
278 end
279 settexdimen ( " objectwd " , w or 0 )
280 settexdimen ( " objectht " , h or 0 )
281 settexdimen ( " objectdp " , d or 0 )
282 settexdimen ( " objectoff " , o or # objects > 2 and object [ 2 ] or 0 )
283 end
284}
285
286
287
288implement {
289 name = " registerbackendsymbol " ,
290 arguments = { " string " , " integer " } ,
291 actions = function ( ... )
292 codeinjections . registersymbol ( ... )
293 end
294}
295 |