1if not modules then modules = { } end modules ['node-aux'] = {
2 version = 1.001,
3 comment = "companion to node-ini.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
11local type, tostring = type, tostring
12
13local nodes = nodes
14local context = context
15
16local utfvalues = utf.values
17
18local nodecodes = nodes.nodecodes
19
20local glyph_code = nodecodes.glyph
21local hlist_code = nodecodes.hlist
22local vlist_code = nodecodes.vlist
23local attributelist_code = nodecodes.attributelist
24local par_code = nodecodes.par
25
26local nuts = nodes.nuts
27local tonut = nuts.tonut
28local tonode = nuts.tonode
29local vianuts = nuts.vianuts
30
31local getbox = nuts.getbox
32local getnext = nuts.getnext
33local getid = nuts.getid
34local getsubtype = nuts.getsubtype
35local getlist = nuts.getlist
36local getattr = nuts.getattr
37local getboth = nuts.getboth
38local getprev = nuts.getprev
39local getwidth = nuts.getwidth
40local setwidth = nuts.setwidth
41local getboxglue = nuts.getboxglue
42local setboxglue = nuts.setboxglue
43
44local setfield = nuts.setfield
45local setattr = nuts.setattr
46local setlink = nuts.setlink
47local setlist = nuts.setlist
48local setnext = nuts.setnext
49local setprev = nuts.setprev
50local setattrlist = nuts.setattrlist
51
52local traversers = nuts.traversers
53local nextnode = traversers.node
54local nextglyph = traversers.glyph
55
56local flushnode = nuts.flush
57local flushlist = nuts.flushlist
58local hpack_nodes = nuts.hpack
59local unsetattribute = nuts.unsetattribute
60local firstglyph = nuts.firstglyph
61local copy_node = nuts.copy
62local find_tail = nuts.tail
63local getbox = nuts.getbox
64local count = nuts.count
65local isglyph = nuts.isglyph
66
67local nodepool = nuts.pool
68local new_glue = nodepool.glue
69local new_glyph = nodepool.glyph
70
71local unsetvalue = attributes.unsetvalue
72
73local current_font = font.current
74
75local texsetbox = tex.setbox
76
77local report_error = logs.reporter("node-aux:error")
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97local function takebox(id)
98 local box = getbox(id)
99 if box then
100 local list = getlist(box)
101 setlist(box,nil)
102 local copy = copy_node(box)
103 if list then
104 setlist(copy,list)
105 end
106 texsetbox(id,false)
107 return copy
108 end
109end
110
111function nodes.takebox(id)
112 local b = takebox(id)
113 if b then
114 return tonode(b)
115 end
116end
117
118local splitbox = tex.splitbox
119nodes.splitbox = splitbox
120
121function nuts.splitbox(id,height)
122 return tonut(splitbox(id,height))
123end
124
125
126
127
128
129function nuts.takelist(n)
130 local l = getlist(n)
131 setlist(n)
132 flushnode(n)
133 return l
134end
135
136nuts.takebox = takebox
137tex.takebox = nodes.takebox
138
139
140
141local function repackhlist(list,...)
142 local temp, b = hpack_nodes(list,...)
143 list = getlist(temp)
144 setlist(temp)
145 flushnode(temp)
146 return list, b
147end
148
149nuts.repackhlist = repackhlist
150
151function nodes.repackhlist(list,...)
152 local list, b = repackhlist(tonut(list),...)
153 return tonode(list), b
154end
155
156if not nuts.setattributes then
157
158 local function setattributes(head,attr,value)
159 for n, id in nextnode, head do
160 setattr(n,attr,value)
161 if id == hlist_node or id == vlist_node then
162 setattributes(getlist(n),attr,value)
163 end
164 end
165 end
166
167 nuts .setattributes = setattributes
168 nodes.setattributes = vianuts(setattributes)
169
170end
171
172if not nuts.setunsetattributes then
173
174 local function setunsetattributes(head,attr,value)
175 for n, id in nextnode, head do
176 if not getattr(n,attr) then
177 setattr(n,attr,value)
178 end
179 if id == hlist_code or id == vlist_code then
180 setunsetattributes(getlist(n),attr,value)
181 end
182 end
183 end
184
185 nuts .setunsetattributes = setunsetattributes
186 nodes.setunsetattributes = vianuts(setunsetattributes)
187
188end
189
190if not nuts.unsetattributes then
191
192 local function unsetattributes(head,attr)
193 for n, id in nextnode, head do
194 setattr(n,attr,unsetvalue)
195 if id == hlist_code or id == vlist_code then
196 unsetattributes(getlist(n),attr)
197 end
198 end
199 end
200
201 nuts .unsetattributes = unsetattributes
202 nodes.unsetattributes = vianuts(unsetattributes)
203
204end
205
206function nuts.firstcharacter(n,untagged)
207 if untagged then
208 return firstglyph(n)
209 else
210 for g in nextglyph ,n do
211 return g
212 end
213 end
214end
215
216local function firstcharinbox(n)
217 local l = getlist(getbox(n))
218 if l then
219 for g, c in nextglyph, l do
220 return c
221 end
222 end
223 return 0
224end
225
226nuts .firstcharinbox = firstcharinbox
227nodes.firstcharinbox = firstcharinbox
228nodes.firstcharacter = vianuts(firstcharacter)
229
230interfaces.implement {
231 name = "buildtextaccent",
232 arguments = "integer",
233 actions = function(n)
234 local char = firstcharinbox(n)
235 if char > 0 then
236
237 context([[\accent%s\relax]],char)
238 end
239 end
240}
241
242
243
244
245local function tonodes(str,fnt,attr)
246 if not str or str == "" then
247 return
248 end
249 local head, tail, space, fnt, template = nil, nil, nil, nil, nil
250 if not fnt then
251 fnt = current_font()
252 elseif type(fnt) ~= "number" and getid(fnt) == glyph_code then
253 fnt, template = nil, tonut(fnt)
254 end
255 for s in utfvalues(str) do
256 local n
257 if s == 32 then
258 if space then
259 n = copy_node(space)
260 elseif fonts then
261 local parameters = fonts.hashes.identifiers[fnt].parameters
262 space = new_glue(parameters.space,parameters.space_stretch,parameters.space_shrink)
263 n = space
264 end
265 elseif template then
266 n = copy_node(template)
267 setvalue(n,"char",s)
268 else
269 n = new_glyph(fnt,s)
270 end
271 if attr then
272 setattrlist(n,attr)
273 end
274 if head then
275 setlink(tail,n)
276 else
277 head = n
278 end
279 tail = n
280 end
281 return head, tail
282end
283
284nuts.tonodes = tonodes
285
286nodes.tonodes = function(str,fnt,attr)
287 local head, tail = tonodes(str,fnt,attr)
288 return tonode(head), tonode(tail)
289end
290
291local function link(list,currentfont,currentattr,head,tail)
292 for i=1,#list do
293 local n = list[i]
294 if n then
295 local tn = type(n)
296 if tn == "string" then
297 if #tn > 0 then
298 if not currentfont then
299 currentfont = current_font()
300 end
301 local h, t = tonodes(n,currentfont,currentattr)
302 if not h then
303
304 elseif not head then
305 head, tail = h, t
306 else
307 setnext(tail,h)
308 setprev(h,t)
309 tail = t
310 end
311 end
312 elseif tn == "table" then
313 if #tn > 0 then
314 if not currentfont then
315 currentfont = current_font()
316 end
317 head, tail = link(n,currentfont,currentattr,head,tail)
318 end
319 elseif not head then
320 head = n
321 tail = find_tail(n)
322 elseif getid(n) == attributelist_code then
323
324 report_error("weird node type in list at index %s:",i)
325 for i=1,#list do
326 local l = list[i]
327 report_error("%3i: %s %S",i,getid(l) == attributelist_code and "!" or ">",l)
328 end
329 os.exit()
330 else
331 setlink(tail,n)
332 if getnext(n) then
333 tail = find_tail(n)
334 else
335 tail = n
336 end
337 end
338 else
339
340 end
341 end
342 return head, tail
343end
344
345nuts.link = link
346
347nodes.link = function(list,currentfont,currentattr,head,tail)
348 local head, tail = link(list,currentfont,currentattr,tonut(head),tonut(tail))
349 return tonode(head), tonode(tail)
350end
351
352local function locate(start,wantedid,wantedsubtype)
353 for n, id, subtype in nextnode, start do
354 if id == wantedid then
355 if not wantedsubtype or subtype == wantedsubtype then
356 return n
357 end
358 elseif id == hlist_code or id == vlist_code then
359 local found = locate(getlist(n),wantedid,wantedsubtype)
360 if found then
361 return found
362 end
363 end
364 end
365end
366
367nuts.locate = locate
368
369function nodes.locate(start,wantedid,wantedsubtype)
370 local found = locate(tonut(start),wantedid,wantedsubtype)
371 return found and tonode(found)
372end
373
374local function rehpack(n,width)
375 local head = getlist(n)
376 local size = width or getwidth(n)
377 local temp = hpack_nodes(head,size,"exactly")
378 setwidth(n,size)
379 local set, order, sign = getboxglue(temp)
380 setboxglue(n,set,order,sign)
381 setlist(temp)
382 flushnode(temp)
383 return n
384end
385
386nuts.rehpack = rehpack
387
388function nodes.rehpack(n,...)
389 rehpack(tonut(n),...)
390end
391
392do
393
394 local parcodes = nodes.parcodes
395 local hmodepar_code = parcodes.vmode_par
396 local vmodepar_code = parcodes.hmode_par
397
398 local getnest = tex.getnest
399 local getsubtype = nuts.getsubtype
400
401 function nuts.setparproperty(action,...)
402 local tail = tonut(getnest().tail)
403 while tail do
404 if getid(tail) == par_code then
405 local s = getsubtype(tail)
406 if s == hmodepar_code or s == vmodepar_code then
407 return action(tail,...)
408 else
409
410 end
411 end
412 tail = getprev(tail)
413 end
414 end
415
416 local getsubtype = nodes.getsubtype
417
418 function nodes.startofpar(n)
419 local s = getsubtype(n)
420 return s == hmodepar_code or s == vmodepar_code
421 end
422
423end
424
425if not nuts.getnormalizedline then
426
427 local nextnode = traversers.glue
428 local findfail = nuts.tail
429
430 local getid = nuts.getid
431 local getsubtype = nuts.getsubtype
432 local getlist = nuts.getlist
433 local getwidth = nuts.getwidth
434
435 local nodecodes = nodes.nodecodes
436 local skipcodes = nodes.skipcodes
437
438 local hlist_code = nodecodes.hlist
439 local line_code = nodecodes.line
440
441 local leftskip_code = skipcodes.leftskip
442 local rightskip_code = skipcodes.rightskip
443 local lefthangskip_code = skipcodes.lefthangskip
444 local righthangskip_code = skipcodes.righthangskip
445 local indentskip_code = skipcodes.indentskip
446 local parfillskip_code = skipcodes.parfillskip
447
448 nuts.findnode = node.direct.find_node or function(h,t,s)
449 if h then
450 if s then
451 for node, subtype in traversers[t] do
452 if s == subtype then
453 return current
454 end
455 end
456 else
457 for node, subtype in traversers[t] do
458 return current, subtype
459 end
460 end
461 end
462 end
463
464
465 function nuts.getnormalizedline(h)
466 if getid(h) == hlist_code and getsubtype(h) == line_code then
467 local ls, rs = 0, 0
468 local lh, rh = 0, 0
469 local lp, rp = 0, 0
470 local is = 0
471 local h = getlist(h)
472 local t = findtail(h)
473 for n, subtype in nextglue, h do
474 if subtype == leftskip_code then ls = getwidth(n)
475 elseif subtype == rightskip_code then rs = getwidth(n)
476 elseif subtype == lefthangskip_code then lh = getwidth(n)
477 elseif subtype == righthangskip_code then rh = getwidth(n)
478 elseif subtype == indentskip_code then is = getwidth(n)
479 elseif subtype == parfillskip_code then rp = getwidth(n)
480 end
481 end
482 return {
483 leftskip = ls,
484 rightskip = rs,
485 lefthangskip = lh,
486 righthangskip = rh,
487 indent = is,
488 parfillrightskip = rp,
489 parfillleftskip = lp,
490 head = h,
491 tail = t,
492 }
493 end
494 end
495
496end
497 |