1if not modules then modules = { } end modules ['driv-shp'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to driv-ini.mkiv",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10local type, next, rawget, rawset = type, next, rawget, rawset
11
12local setmetatableindex = table.setmetatableindex
13local formatters = string.formatters
14local concat = table.concat
15local keys = table.keys
16local insert = table.insert
17local sortedhash = table.sortedhash
18local find = string.find
19local stripstring = string.strip
20local sequenced = table.sequenced
21local round = math.round
22local nuts = nodes.nuts
23
24local tonut = nodes.tonut
25local tonode = nodes.tonode
26
27local getdirection = nuts.getdirection
28local getlist = nuts.getlist
29local getoffsets = nuts.getoffsets
30local getorientation = nuts.getorientation
31local getanchors = nuts.getanchors
32local getgeometry = nuts.getgeometry
33local getxyscales = nuts.getxyscales
34local getwhd = nuts.getwhd
35local getkern = nuts.getkern
36local getheight = nuts.getheight
37local getdepth = nuts.getdepth
38
39local getnext = nuts.getnext
40local getsubtype = nuts.getsubtype
41local getid = nuts.getid
42local getleader = nuts.getleader
43
44local getshift = nuts.getshift
45local getreplace = nuts.getreplace
46local setreplace = nuts.setreplace
47local getfont = nuts.getfont
48local getxscale = nuts.getxscale
49local getboth = nuts.getboth
50
51local getglyphdimensions = nuts.getglyphdimensions
52local getkerndimension = nuts.getkerndimension
53local getlistdimensions = nuts.getlistdimensions
54local getruledimensions = nuts.getruledimensions
55
56local setdirection = nuts.setdirection
57local setlink = nuts.setlink
58
59local isglyph = nuts.isglyph
60
61local nextnode = nuts.traversers.node
62
63local effectiveglue = nuts.effectiveglue
64local dirdimensions = nuts.dirdimensions
65
66local fonthashes = fonts.hashes
67local fontdata = fonthashes.identifiers
68local characters = fonthashes.characters
69local parameters = fonthashes.parameters
70
71local nodecodes = nodes.nodecodes
72local whatsitcodes = nodes.whatsitcodes
73local gluecodes = nodes.gluecodes
74local subtypes = nodes.subtypes
75
76local directioncodes = tex.directioncodes
77local lefttoright_code = directioncodes.lefttoright
78local righttoleft_code = directioncodes.righttoleft
79
80local glyph_code = nodecodes.glyph
81local kern_code = nodecodes.kern
82local glue_code = nodecodes.glue
83local hlist_code = nodecodes.hlist
84local vlist_code = nodecodes.vlist
85local dir_code = nodecodes.dir
86local disc_code = nodecodes.disc
87local math_code = nodecodes.math
88local rule_code = nodecodes.rule
89local whatsit_code = nodecodes.whatsit
90
91local virtualrule_code = nodes.rulecodes.virtual
92
93local leaders_code = gluecodes.leaders
94local cleaders_code = gluecodes.cleaders
95local xleaders_code = gluecodes.xleaders
96local gleaders_code = gluecodes.gleaders
97
98local spaceskip_code = gluecodes.spaceskip
99local xspaceskip_code = gluecodes.xspaceskip
100
101local getpagedimensions = layouts.getpagedimensions
102
103local drivers = drivers
104
105local report = logs.reporter("drivers")
106
107
108
109
110
111
112local lastfont = nil
113local fontcharacters = nil
114
115local magicconstants = tex.magicconstants
116local maxdimen = magicconstants.maxdimen
117local runningrule = magicconstants.runningrule
118
119local pos_h = 0
120local pos_v = 0
121local pos_r = lefttoright_code
122local shippingmode = "none"
123
124local shipbox_h = 0
125local shipbox_v = 0
126local page_size_h = 0
127local page_size_v = 0
128
129local initialize
130local finalize
131local updatefontstate
132local pushorientation
133local poporientation
134local flushcharacter
135local flushfontchar
136local flushrule
137local flushliteral
138local flushwhatsit
139local flushspace
140
141
142
143function drivers.getpos () return round(pos_h), round(pos_v) end
144function drivers.getrpos() return round(pos_h), round(pos_v), pos_r end
145function drivers.gethpos() return round(pos_h) end
146function drivers.getvpos() return round(pos_v) end
147
148
149
150
151
152local tospace = false directives.register("backends.spaces", function(v) tospace = v end)
153
154local flush_character, flush_space do
155
156 local stack = setmetatableindex("table")
157 local level = 0
158 local nesting = 0
159 local main = 0
160
161
162
163 local default = 16384
164 local refactored = 1000000
165
166 local vfinjectors = fonts.helpers.vfinjectors
167
168
169
170
171
172 local function flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,csx,csy,factor,sx,sy,slant,weight,vfcommands)
173 if nesting > 100 then
174 return
175 elseif nesting == 0 then
176 main = font
177
178
179
180
181
182
183 else
184
185
186
187
188
189
190 end
191
192 nesting = nesting + 1
193
194 local savedlevel = level
195
196 local function push()
197 level = level + 1
198 local s = stack[level]
199 s[1] = pos_h
200 s[2] = pos_v
201 s[3] = pos_r
202 end
203
204 local function pop()
205 if level > 0 then
206 local s = stack[level]
207 pos_h = s[1]
208 pos_v = s[2]
209 pos_r = s[3]
210 level = level - 1
211 end
212 end
213
214
215
216 local saved_h = pos_h
217 local saved_v = pos_v
218 local saved_r = pos_r
219
220 pos_r = lefttoright_code
221
222 local fdata = fontdata[font]
223 local fnt = font
224 local fonts = fdata.fonts
225 local siz = (fdata.parameters.factor or 1)/65536
226
227
228
229
230
231
232
233
234
235
236
237
238
239 local scale = data.scale
240 local xoffset = data.xoffset
241 local yoffset = data.yoffset
242
243 if scale then
244 sx = scale * sx
245 sy = scale * sy
246 end
247
248
249
250 if csx then
251 sx = sx * csx
252 csx = 1
253 end
254 if csy then
255 sy = sy * csy
256 csy = 1
257 end
258
259 if xoffset and xoffset ~= 0 then
260 if factor ~= 0 then
261 xoffset = xoffset + xoffset * factor / refactored
262 end
263 pos_h = pos_h + xoffset * sx
264 end
265
266 if yoffset and yoffset ~= 0 then
267 pos_v = pos_v + yoffset * sy
268 end
269
270
271
272 local function flushchar(fnt,chr,csx,csy)
273 if fnt then
274 local nest = char ~= chr or font ~= fnt
275 if fnt == 0 then
276 fnt = main
277 end
278 if csx then
279 csx = csx * sx
280 else
281 csx = sx
282 end
283 if csy then
284 csy = csy * sy
285 else
286 csy = sy
287 end
288
289
290 return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,csx,csy,slant,weight)
291 else
292 return 0
293 end
294 end
295
296
297
298 for i=1,#vfcommands do
299 local packet = vfcommands[i]
300 if packet then
301 local command = packet[1]
302 if command == "char" then
303 local chr = packet[2]
304 local csx = packet[3]
305 local csy = packet[4] or csx
306 pos_h = pos_h + flushchar(fnt,chr,csx,csy) * sx
307 elseif command == "slot" then
308 local index = packet[2]
309 local chr = packet[3]
310 local csx = packet[4]
311 local csy = packet[5] or csx
312 if index == 0 then
313 pos_h = pos_h + flushchar(font,chr,csx,csy) * sx
314 else
315 local okay = fonts and fonts[index]
316 if okay then
317 local fnt = okay.id
318 if fnt then
319 if fnt == 0 then
320 fnt = font
321 end
322 pos_h = pos_h + flushchar(fnt,chr,csx,csy) * sx
323 end
324 else
325
326 pos_h = pos_h + flushchar(font,chr,csx,csy) * sx
327 end
328 end
329 elseif command == "use" then
330 local index = packet[2]
331 if index then
332 local fnt
333 if index == 0 then
334 fnt = font
335 else
336 local okay = fonts and fonts[index]
337 if okay then
338 fnt = okay.id
339 end
340 end
341 if fnt then
342
343 local d = characters[fnt]
344 if d then
345 for i=3,#packet do
346 local chr = packet[i]
347 local dat = d[chr]
348 if dat then
349 flushfontchar(fnt,chr,dat)
350 end
351 end
352 end
353 end
354 end
355 elseif command == "right" then
356 local h = packet[2]
357 if h ~= 0 then
358 if factor ~= 0 then
359 h = h + h * factor / refactored
360 end
361 pos_h = pos_h + h * sx
362 end
363 elseif command == "left" then
364 local h = packet[2]
365 if h ~= 0 then
366 if factor ~= 0 then
367 h = h + h * factor / refactored
368 end
369 pos_h = pos_h - h * sx
370 end
371 elseif command == "down" then
372 local v = packet[2]
373 if v and v ~= 0 then
374 pos_v = pos_v - v * sy
375 end
376 elseif command == "up" then
377 local v = packet[2]
378 if v and v ~= 0 then
379 pos_v = pos_v + v * sy
380 end
381 elseif command == "offset" then
382 local c = packet[4]
383 if c then
384 local ph = pos_h
385 local pv = pos_v
386 local csx = packet[5]
387 local csy = packet[6] or csx
388 local h = packet[2]
389 local v = packet[3]
390 if h and h ~= 0 then
391 if factor ~= 0 then
392 h = h + h * factor / refactored
393 end
394 pos_h = pos_h + h * sx
395 end
396 if v and v ~= 0 then
397 pos_v = pos_v + v * sy
398 end
399 flushchar(fnt,c,csx,csy)
400 pos_h = ph
401 pos_v = pv
402 end
403 elseif command == "stay" then
404
405 push()
406 flushchar(font,packet[2],1,1)
407 pop()
408 elseif command == "compose" then
409 local ph = pos_h
410 local pv = pos_v
411 local h = packet[2] or 0
412 local v = packet[3] or 0
413 local c = packet[4]
414 if h ~= 0 then
415 if factor ~= 0 then
416 h = h + h * factor / refactored
417 end
418 pos_h = pos_h + h * sx
419 end
420 if v and v ~= 0 then
421 pos_v = pos_v + v * sy
422 end
423 if c then
424 flushchar(fnt,c)
425 pos_h = ph
426 pos_v = pv
427 end
428 elseif command == "push" then
429 push()
430 elseif command == "pop" then
431 pop()
432 elseif command == "frame" then
433
434 local width = packet[2]
435 local height = packet[3]
436 local depth = packet[4]
437 local wd, ht, dp
438 if not current then
439
440 elseif width == true or height == true or depth == true then
441 wd, ht, dp = getwhd(current,true)
442 end
443 if width == true then
444 width = wd or 0
445 elseif not width then
446 width = 0
447 end
448 if height == true then
449 height = ht or 0
450 elseif not height then
451 height = 0
452 end
453 if depth == true then
454 depth = dp or 0
455 elseif not depth then
456 depth = 0
457 end
458 local total = height + depth
459 if width > 0 and total > 0 then
460 if factor ~= 0 then
461 width = width + width * factor / refactored
462 end
463 if width > 0 then
464 local line = packet[5] or default
465 local outline = packet[6]
466 local advance = packet[7]
467 if outline == nil then
468 outline = true
469 end
470 if advance == nil then
471 advance = true
472 end
473 local baseline = outline and packet[8]
474 local color = packet[9]
475 if color then
476 vfinjectors.startcolor(pos_h,pos_v,color)
477 end
478 width = width * sx
479 height = height * sy
480 depth = depth * sy
481 flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline)
482 if color then
483 vfinjectors.stopcolor()
484 end
485 if advance then
486 pos_h = pos_h + width
487 end
488 end
489 end
490 elseif command == "rule" then
491 local size_v = packet[2]
492 local size_h = packet[3]
493 if size_h > 0 and size_v > 0 then
494 if factor ~= 0 then
495 size_h = size_h + size_h * factor / refactored
496 end
497 if size_h > 0 then
498 size_h = size_h * sx
499 size_v = size_v * sy
500 flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v)
501 pos_h = pos_h + size_h
502 end
503 end
504 elseif command == "line" then
505 local wd = packet[2] or 0
506 local ht = packet[3] or 0
507 local dp = packet[4] or 0
508 if wd > 0 and ht ~= 0 and dp ~= 0 then
509 if factor ~= 0 then
510 wd = wd + wd * factor / refactored
511 end
512 if wd > 0 then
513 wd = wd * sx
514 ht = ht * sy
515 dp = dp * sy
516 local color = packet[5]
517 if color then
518 vfinjectors.startcolor(pos_h,pos_v,color)
519 end
520 flushsimplerule(pos_h,pos_v-dp,pos_r,wd,ht+dp)
521 if color then
522 vfinjectors.stopcolor()
523 end
524 pos_h = pos_h + wd
525 end
526 end
527 elseif command == "font" then
528 local index = packet[2]
529 local okay = fonts and fonts[index]
530 if okay then
531 fnt = okay.id or fnt
532 end
533 elseif command == "lua" then
534 local code = packet[2]
535 local kind = type(code)
536 if kind ~= "function" then
537 code = loadstring(code)
538 kind = type(code)
539 end
540 if kind == "function" then
541 code(font,char,pos_h,pos_v,sx,sy)
542 end
543 elseif command == "node" then
544 local h = packet[2]
545 hlist_out(h,getlist(h))
546
547
548
549
550
551
552
553
554
555
556 elseif command == "inspect" then
557 inspect(vfcommands)
558 elseif command == "trace" then
559 report("virtual state: h=%p v=%p d=%i",pos_h,pos_v,pos_r)
560 else
561 local injector = vfinjectors[command]
562 if injector then
563 injector(pos_h,pos_v,packet)
564 end
565 end
566 end
567 end
568
569
570
571 pos_h = saved_h
572 pos_v = saved_v
573 pos_r = saved_r
574
575 if savedlevel ~= level then
576 report("")
577 report("virtual state: stack is corrupt")
578 report("")
579 end
580 level = savedlevel
581
582 nesting = nesting - 1
583
584 end
585
586 local onetimemessage
587
588 flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,csx,csy)
589
590 if font ~= lastfont then
591 lastfont = font
592 fontcharacters = characters[font]
593 updatefontstate(font)
594 end
595
596 local data = fontcharacters[char]
597 if not data then
598 if char > 0 then
599 if not onetimemessage then
600 onetimemessage = fonts.loggers.onetimemessage
601 end
602 onetimemessage(font,char,"missing")
603 end
604 return 0, 0, 0
605 end
606
607 if vfcommands then
608 vfcommands = data.commands
609 end
610 local width, height, depth, naturalwidth, sx, sy, slant, weight
611 if current then
612 width, height, depth, factor, sx, sy, slant, weight = getglyphdimensions(current)
613 else
614 width = data.width or 0
615 height = data.height or 0
616 depth = data.depth or 0
617 naturalwidth = width
618 if not factor then
619 factor = 0
620 end
621 sx = 1
622 sy = 1
623 slant = 0
624 weight = 0
625 end
626 if pos_r == righttoleft_code then
627 pos_h = pos_h - width
628 end
629 if vfcommands then
630 flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,csx,csy,factor,sx,sy,slant,weight,vfcommands)
631 else
632 local orientation = data.orientation
633 if orientation and (orientation == 1 or orientation == 3) then
634
635 pushorientation(orientation,pos_h,pos_v)
636 flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,csx,csy,factor,sx,sy,slant,weight)
637 poporientation(orientation,pos_h,pos_v)
638 else
639 flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,csx,csy,factor,sx,sy,slant,weight)
640 end
641 end
642 return width, height, depth
643 end
644
645 flush_space = function(current,pos_h,pos_v,pos_r)
646 local font = getfont(current)
647 if font == lastfont then
648
649
650
651
652
653
654
655
656 flushspace(font)
657 end
658 end
659
660end
661
662
663
664local function reset_state()
665 pos_h = 0
666 pos_v = 0
667 pos_r = lefttoright_code
668 shipbox_h = 0
669 shipbox_v = 0
670 shippingmode = "none"
671 page_size_h = 0
672 page_size_v = 0
673end
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692local dirstack = { }
693local anchors = { }
694local befores = setmetatableindex("table")
695local afters = setmetatableindex("table")
696local stired = false
697
698local function reset_directions()
699 dirstack = { }
700end
701
702local function reset_anchors()
703 anchors = { }
704end
705
706interfaces.implement {
707 name = "registeranchorbox",
708 public = true,
709 protected = true,
710 arguments = { "integer", "integer", "box" },
711 actions = function(anchor,where,box)
712 box = tonut(box)
713 insert(where < 0 and befores[anchor] or afters[anchor],box)
714 stored = true
715 end
716}
717
718local hlist_out, vlist_out do
719
720 local finalize = nodes.handlers.finalizelist
721 local flushnode = nuts.flushnode
722
723 local function flushstored(current,source,before)
724 local t = before and befores or afters
725 local s = rawget(t,source)
726 if s then
727 for i=1,#s do
728 local si = s[i]
729 if si then
730 local box = si
731 finalize(box)
732 if getid(box) == vlist_code then
733 vlist_out(current,box)
734 else
735 hlist_out(current,box)
736 end
737 flushnode(box)
738 s[i] = false
739 end
740 end
741 rawset(t,source,nil)
742 end
743 end
744
745 local function applyorientation(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
746 local ot = (orientation >> 0) & 0x0F
747 local ay = (orientation >> 4) & 0x0F
748 local ax = (orientation >> 8) & 0x0F
749 if ot == 4 then
750 ot, ay = 0, 1
751 elseif ot == 5 then
752 ot, ay = 0, 2
753 end
754 if ot == 0 or ot == 2 then
755 if ax == 1 then x = x - width
756 elseif ax == 2 then x = x + width
757 elseif ax == 3 then x = x - width/2
758 elseif ax == 4 then x = x + width/2
759 end
760 if ot == 2 then
761 doffset, hoffset = hoffset, doffset
762 end
763 if ay == 1 then y = y - doffset
764 elseif ay == 2 then y = y + hoffset
765 elseif ay == 3 then y = y + (doffset + hoffset)/2 - doffset
766 end
767 elseif ot == 1 or ot == 3 then
768 if ay == 1 then y = y - height
769 elseif ay == 2 then y = y + height
770 elseif ay == 3 then y = y - height/2
771 end
772 if ot == 1 then
773 doffset, hoffset = hoffset, doffset
774 end
775 if ax == 1 then x = x - width
776 elseif ax == 2 then x = x + width
777 elseif ax == 3 then x = x - width/2
778 elseif ax == 4 then x = x + width/2
779 elseif ax == 5 then x = x - hoffset
780 elseif ax == 6 then x = x + doffset
781 end
782 end
783 return ot, x + xoffset, y - yoffset
784 end
785
786 local function applyanchor(anchor,shift,anchor_h,anchor_v,width,height,depth)
787 local h = 0
788 local v = 0
789 local a = anchor & 0x00FF
790 local s = anchor & 0x0F00
791 if a == 0x02 then
792 v = height
793 elseif a == 0x03 then
794 v = - depth
795 elseif a == 0x04 then
796 h = width
797 elseif a == 0x05 then
798 h = width
799 v = height
800 elseif a == 0x06 then
801 h = width
802 v = - depth
803 elseif a == 0x07 then
804 h = width/2
805 elseif a == 0x08 then
806 h = width/2
807 v = height
808 elseif a == 0x09 then
809 h = width/2
810 v = - depth
811 elseif a == 0x0A then
812 h = width/2
813 v = height/2 - depth/2
814 elseif a == 0x0B then
815 h = width/2
816 v = height/2
817 elseif a == 0x0C then
818 h = width/2
819 v = - depth/2
820 elseif a == 0x0D then
821 v = height/2 - depth/2
822 elseif a == 0x0E then
823 h = width
824 v = height/2 - depth/2
825 end
826 if not shift then
827 h = -h
828 v = -v
829 end
830 if s == 0x100 then
831 h = -h
832 elseif s == 0x200 then
833 v = -v
834 elseif s == 0x300 then
835 h = -h
836 v = -v
837 else
838 end
839 anchor_h = anchor_h + h
840 anchor_v = anchor_v + v
841 return anchor_h, anchor_v
842 end
843
844 drivers.applyanchor = applyanchor
845 drivers.applyorientation = applyorientation
846
847
848
849
850
851 local eps <const> = 10
852
853 hlist_out = function(this_box,current)
854 local ref_h = pos_h
855 local ref_v = pos_v
856 local ref_r = pos_r
857 pos_r = getdirection(this_box)
858 local boxwidth,
859 boxheight,
860 boxdepth = getwhd(this_box)
861
862 local cur_h = 0
863
864
865
866
867
868
869
870
871 for current, id, subtype in nextnode, current do
872 if id == glyph_code then
873 local char, font = isglyph(current)
874 local x_offset, y_offset, left, right, raise = getoffsets(current)
875 if x_offset ~= 0 or y_offset ~= 0 then
876 if pos_r == righttoleft_code then
877 pos_h = ref_h - (cur_h + x_offset)
878 else
879 pos_h = ref_h + (cur_h + x_offset)
880 end
881
882 pos_v = ref_v + y_offset
883
884 end
885 pos_v = pos_v + raise
886 pos_h = pos_h - left
887 local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r)
888
889 cur_h = cur_h + wd
890 elseif id == glue_code then
891
892 local gluewidth = effectiveglue(current,this_box,true)
893 if gluewidth ~= 0 then
894 if subtype >= leaders_code then
895 local leader = getleader(current)
896 if leader then
897 local id = getid(leader)
898 if id == rule_code then
899 if gluewidth > 0 then
900 local width, height, depth = getwhd(leader)
901 if height == runningrule then
902 height = boxheight
903 end
904 if depth == runningrule then
905 depth = boxdepth
906 end
907 local total = height + depth
908 if total > 0 then
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929 if pos_r == righttoleft_code then
930 pos_h = pos_h - gluewidth
931 end
932 pos_v = pos_v - depth
933 flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total,getsubtype(leader))
934 end
935 cur_h = cur_h + gluewidth
936 end
937 elseif (id == hlist_code or id == vlist_code or id == glyph_code) and gluewidth > 0 then
938 local width, height, depth = getwhd(leader)
939
940 if width > 0 then
941 gluewidth = gluewidth + eps
942 local edge = cur_h + gluewidth
943 local lx = 0
944 if subtype == gleaders_code then
945 local save_h = cur_h
946 if pos_r == righttoleft_code then
947 cur_h = ref_h - shipbox_h + cur_h
948 cur_h = width * (cur_h / width)
949 cur_h = ref_h - shipbox_h - cur_h
950 else
951 cur_h = ref_h - shipbox_h - cur_h
952 cur_h = width * (cur_h / width)
953 cur_h = ref_h - shipbox_h - cur_h
954 end
955 if cur_h < save_h then
956 cur_h = cur_h + width
957 end
958 local lr = gluewidth % width
959 cur_h = cur_h + lr / 2
960 elseif subtype == leaders_code then
961 local save_h = cur_h
962 cur_h = width * (cur_h / width)
963 if cur_h < save_h then
964 cur_h = cur_h + width
965 end
966 else
967 local lq = gluewidth / width
968 local lr = gluewidth % width
969 if subtype == cleaders_code then
970 cur_h = cur_h + lr / 2
971 else
972 lx = lr / (lq + 1)
973 cur_h = cur_h + (lr - (lq - 1) * lx) / 2
974 end
975 end
976 if id == glyph_code then
977 local char, font = isglyph(leader)
978 local x_offset, y_offset, left, right, raise = getoffsets(leader)
979 local h = ref_h
980 local v = ref_v
981 if x_offset ~= 0 or y_offset ~= 0 then
982 if pos_r == righttoleft_code then
983 h = h - x_offset
984 else
985 h = h + x_offset
986 end
987 v = v + y_offset
988 end
989 v = v + raise
990 h = h - left
991 local basepoint_h = 0
992 if boxdir ~= pos_r then
993 basepoint_h = boxwidth
994 end
995 if pos_r == righttoleft_code then
996 pos_h = h - basepoint_h
997 else
998 pos_h = h + basepoint_h
999 end
1000 while cur_h + width <= edge do
1001 if pos_r == righttoleft_code then
1002 pos_h = h - cur_h
1003 else
1004 pos_h = h + cur_h
1005 end
1006 pos_v = v
1007 flush_character(leader,font,char,false,true,pos_h,pos_v,pos_r)
1008 cur_h = cur_h + width + lx
1009 end
1010 else
1011 local shift = isglyph and 0 or getshift(leader)
1012 local boxdir = getdirection(leader) or lefttoright_code
1013 pushleaderlevel()
1014 while cur_h + width <= edge do
1015
1016 local basepoint_h = 0
1017
1018 if boxdir ~= pos_r then
1019 basepoint_h = boxwidth
1020 end
1021
1022 if pos_r == righttoleft_code then
1023 pos_h = ref_h - (cur_h + basepoint_h)
1024 else
1025 pos_h = ref_h + (cur_h + basepoint_h)
1026 end
1027 pos_v = ref_v - shift
1028
1029 if id == vlist_code then
1030 vlist_out(leader,getlist(leader))
1031 else
1032 hlist_out(leader,getlist(leader))
1033 end
1034 cur_h = cur_h + width + lx
1035 end
1036 popleaderlevel()
1037 end
1038 cur_h = edge - eps
1039 else
1040 cur_h = cur_h + gluewidth
1041 end
1042 else
1043
1044 cur_h = cur_h + gluewidth
1045 end
1046 else
1047 cur_h = cur_h + gluewidth
1048 end
1049 else
1050 if tospace and (subtype == spaceskip_code or subtype == xspaceskip_code) then
1051
1052
1053
1054
1055flush_space(current)
1056 end
1057 cur_h = cur_h + gluewidth
1058 end
1059 end
1060 elseif id == hlist_code or id == vlist_code then
1061
1062
1063
1064
1065
1066 local width, height, depth, shift, list = getlistdimensions(current)
1067 if list then
1068
1069
1070 local geometry, hasoffset, hasorientation, hasanchor, boxdir = getgeometry(current,true)
1071 local anchor, source, target, targetdata, s_anchor, t_anchor
1072 local anc_h, anc_v
1073 local usedorientation = false
1074 if hasanchor then
1075 anchor, source, target, s_anchor, t_anchor = getanchors(current)
1076 end
1077 if hasorientation then
1078 local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current)
1079 local orientation, basepoint_h, basepoint_v = applyorientation(orientation,0,shift,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
1080 if orientation == 1 then
1081 basepoint_h = basepoint_h + doffset
1082 if boxdir == pos_r then
1083 basepoint_v = basepoint_v - height
1084 end
1085 usedorientation = orientation
1086 elseif orientation == 2 then
1087 if boxdir == pos_r then
1088 basepoint_h = basepoint_h + width
1089 end
1090 usedorientation = orientation
1091 elseif orientation == 3 then
1092 basepoint_h = basepoint_h + hoffset
1093 if boxdir ~= pos_r then
1094 basepoint_v = basepoint_v - height
1095 end
1096 usedorientation = orientation
1097 end
1098 if target then
1099 targetdata = anchors[target]
1100 if targetdata then
1101 anc_h = basepoint_h
1102 anc_v = - basepoint_v
1103 goto posdone
1104 end
1105 end
1106 if pos_r == righttoleft_code then
1107 pos_h = ref_h - (cur_h + basepoint_h)
1108 else
1109 pos_h = ref_h + (cur_h + basepoint_h)
1110 end
1111
1112 pos_v = ref_v - basepoint_v
1113 elseif hasoffset then
1114
1115 local xoffset, yoffset = getoffsets(current)
1116 local basepoint_h = boxdir ~= pos_r and width or 0
1117 local basepoint_v = shift
1118 if target then
1119 targetdata = anchors[target]
1120 if targetdata then
1121 anc_h = xoffset + basepoint_h
1122 anc_v = yoffset - basepoint_v
1123 goto posdone
1124 end
1125 end
1126 if pos_r == righttoleft_code then
1127 pos_h = ref_h - (cur_h + basepoint_h + xoffset)
1128 else
1129 pos_h = ref_h + (cur_h + basepoint_h + xoffset)
1130 end
1131 pos_v = ref_v - (basepoint_v - yoffset)
1132 elseif hasanchor then
1133 local basepoint_h = boxdir ~= pos_r and width or 0
1134 local basepoint_v = shift
1135 if target then
1136 targetdata = anchors[target]
1137 if targetdata then
1138 anc_h = basepoint_h
1139 anc_v = - basepoint_v
1140 goto posdone
1141 end
1142 end
1143 if pos_r == righttoleft_code then
1144 pos_h = ref_h - (cur_h + basepoint_h)
1145 else
1146 pos_h = ref_h + (cur_h + basepoint_h)
1147 end
1148 pos_v = ref_v - basepoint_v
1149 else
1150 local basepoint_h = boxdir ~= pos_r and width or 0
1151 local basepoint_v = shift
1152 if pos_r == righttoleft_code then
1153 pos_h = ref_h - (cur_h + basepoint_h)
1154 else
1155 pos_h = ref_h + (cur_h + basepoint_h)
1156 end
1157 pos_v = ref_v - basepoint_v
1158 end
1159 goto process
1160 ::posdone::
1161 if pos_r == righttoleft_code then
1162 pos_h = targetdata[1] - anc_h
1163 else
1164 pos_h = targetdata[1] + anc_h
1165 end
1166 pos_v = targetdata[2] + anc_v
1167 if anchor and anchor > 0 then
1168
1169
1170 pos_h, pos_v = applyanchor(t_anchor,true, pos_h,pos_v,targetdata[3],targetdata[4],targetdata[5])
1171 pos_h, pos_v = applyanchor(s_anchor,false,pos_h,pos_v,width,height,depth)
1172 end
1173 ::process::
1174 if source then
1175 local anchor_h = pos_h
1176 local anchor_v = pos_v
1177 if usedorientation then
1178 if usedorientation == 1 then
1179 anchor_v = anchor_v - (width - height)
1180 elseif usedorientation == 2 then
1181 anchor_v = anchor_v - (depth - height)
1182 elseif usedorientation == 3 then
1183 anchor_v = anchor_v + (height - width)
1184 end
1185 end
1186
1187 anchors[source] = { anchor_h, anchor_v, width, height, depth }
1188 end
1189 if usedorientation then
1190 pushorientation(usedorientation,pos_h,pos_v,pos_r)
1191 end
1192 if source and stored then
1193 flushstored(current,source,true)
1194 end
1195 if id == vlist_code then
1196 vlist_out(current,list)
1197 else
1198 hlist_out(current,list)
1199 end
1200 if source and stored then
1201 flushstored(current,source,false)
1202 end
1203 if usedorientation then
1204 poporientation(usedorientation,pos_h,pos_v,pos_r)
1205 end
1206 end
1207 cur_h = cur_h + width
1208 elseif id == kern_code then
1209
1210 if true then
1211 local kern = getkerndimension(current)
1212 if kern ~= 0 then
1213 cur_h = cur_h + kern
1214 end
1215 else
1216 local kern, factor = getkern(current,true)
1217 if kern ~= 0 then
1218 if factor ~= 0 then
1219 cur_h = cur_h + (1.0 + factor/1000000.0) * kern
1220 else
1221 cur_h = cur_h + kern
1222 end
1223 end
1224 end
1225 elseif id == rule_code then
1226 local width, height, depth, virtual = getruledimensions(current)
1227 if width > 0 then
1228 if height == runningrule then
1229 height = boxheight
1230 end
1231 if depth == runningrule then
1232 depth = boxdepth
1233 end
1234 local total = height + depth
1235 if total > 0 then
1236 local xoffset, yoffset, top, bottom = getoffsets(current)
1237 if pos_r == righttoleft_code then
1238 pos_h = pos_h - width
1239 xoffset = - xoffset
1240 end
1241 if not virtual then
1242 if top ~= 0 then
1243
1244 total = total - top
1245 end
1246 if bottom ~= 0 then
1247 depth = depth - bottom
1248 total = total - bottom
1249 end
1250 end
1251 pos_v = pos_v - depth
1252 flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total,subtype)
1253 end
1254 if not virtual then
1255 cur_h = cur_h + width
1256 end
1257 end
1258 elseif id == math_code then
1259
1260
1261
1262
1263 cur_h = cur_h + effectiveglue(current,this_box,true)
1264
1265 elseif id == dir_code then
1266
1267
1268
1269 local dir, cancel = getdirection(current)
1270 if cancel then
1271 local ds = dirstack[current]
1272 if ds then
1273 ref_h = ds.ref_h
1274 ref_v = ds.ref_v
1275 cur_h = ds.cur_h
1276
1277 else
1278
1279 end
1280 pos_r = dir
1281 else
1282 local width, enddir = dirdimensions(this_box,current)
1283 local new_h = cur_h + width
1284 if dir ~= pos_r then
1285 cur_h = new_h
1286 end
1287
1288 if enddir ~= current then
1289 dirstack[enddir] = {
1290 cur_h = new_h,
1291
1292 ref_h = ref_h,
1293 ref_v = ref_v,
1294 }
1295
1296 setdirection(enddir,pos_r)
1297 end
1298 if pos_r == righttoleft_code then
1299 pos_h = ref_h - cur_h
1300 else
1301 pos_h = ref_h + cur_h
1302 end
1303
1304 pos_v = ref_v
1305
1306 ref_h = pos_h
1307 ref_v = pos_v
1308 cur_h = 0
1309
1310 pos_r = dir
1311 goto synced
1312 end
1313 elseif id == whatsit_code then
1314 flushwhatsit[subtype](current,pos_h,pos_v)
1315 elseif id == disc_code then
1316 local replace, tail = getreplace(current)
1317
1318
1319 if replace then
1320 setlink(tail,getnext(current))
1321 setlink(current,replace)
1322 setreplace(current)
1323 end
1324
1325
1326
1327
1328
1329 else
1330
1331 goto synced
1332 end
1333
1334
1335 if pos_r == righttoleft_code then
1336 pos_h = ref_h - cur_h
1337 else
1338 pos_h = ref_h + cur_h
1339 end
1340
1341 pos_v = ref_v
1342 ::synced::
1343 end
1344 pos_h = ref_h
1345 pos_v = ref_v
1346 pos_r = ref_r
1347 end
1348
1349 vlist_out = function(this_box,current)
1350 local ref_h = pos_h
1351 local ref_v = pos_v
1352 local ref_r = pos_r
1353 pos_r = getdirection(this_box)
1354
1355 local boxwidth,
1356 boxheight,
1357 boxdepth = getwhd(this_box)
1358
1359 local cur_h = 0
1360 local cur_v = - boxheight
1361 local top_edge = cur_v
1362
1363
1364
1365
1366
1367
1368 pos_h = ref_h
1369 pos_v = ref_v - cur_v
1370
1371
1372
1373
1374
1375
1376
1377
1378 for current, id, subtype in nextnode, current do
1379 if id == glue_code then
1380 local glueheight = effectiveglue(current,this_box,true)
1381 if glueheight ~= 0 then
1382 if subtype >= leaders_code then
1383 local leader = getleader(current)
1384 if leader then
1385 local width, height, depth = getwhd(leader)
1386 local total = height + depth
1387 if getid(leader) == rule_code then
1388 depth = 0
1389 total = glueheight
1390 if total > 0 then
1391 if width == runningrule then
1392 width = boxwidth
1393 end
1394 if width > 0 then
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412 if pos_r == righttoleft_code then
1413 cur_h = cur_h - width
1414 end
1415 flushrule(leader,pos_h,pos_v - total,pos_r,width,total,getsubtype(leader))
1416 end
1417 cur_v = cur_v + total
1418 end
1419 elseif total > 0 and glueheight > 0 then
1420 glueheight = glueheight + 10
1421 local edge = cur_v + glueheight
1422 local ly = 0
1423 if subtype == gleaders_code then
1424 save_v = cur_v
1425 cur_v = ref_v - shipbox_v - cur_v
1426 cur_v = total * (cur_v / total)
1427 cur_v = ref_v - shipbox_v - cur_v
1428 if cur_v < save_v then
1429 cur_v = cur_v + total
1430 end
1431 local lr = glueheight % total
1432 cur_v = cur_v + lr / 2
1433 elseif subtype == leaders_code then
1434 save_v = cur_v
1435 cur_v = top_edge + total * ((cur_v - top_edge) // total)
1436 if cur_v < save_v then
1437 cur_v = cur_v + total
1438 end
1439 else
1440 local lq = glueheight / total
1441 local lr = glueheight % total
1442 if subtype == cleaders_code then
1443 cur_v = cur_v + lr / 2
1444 else
1445 ly = lr // (lq + 1)
1446 cur_v = cur_v + (lr - (lq - 1) * ly) / 2
1447 end
1448 end
1449 local shift = getshift(leader)
1450 pushleaderlevel()
1451 while cur_v + total <= edge do
1452
1453 if pos_r == righttoleft_code then
1454 pos_h = ref_h - shift
1455 else
1456 pos_h = ref_h + shift
1457 end
1458 pos_v = ref_v - (cur_v + height)
1459
1460 if getid(leader) == vlist_code then
1461 vlist_out(leader,getlist(leader))
1462 else
1463 hlist_out(leader,getlist(leader))
1464 end
1465 cur_v = cur_v + total + ly
1466 end
1467 popleaderlevel()
1468 cur_v = edge - 10
1469 else
1470 cur_v = cur_v + glueheight
1471 end
1472 end
1473 else
1474 cur_v = cur_v + glueheight
1475 end
1476 end
1477 elseif id == hlist_code or id == vlist_code then
1478
1479
1480
1481
1482
1483 local width, height, depth, shift, list = getlistdimensions(current)
1484 if list then
1485
1486
1487 local geometry, hasoffset, hasorientation, hasanchor, boxdir = getgeometry(current,true)
1488 local anchor, source, target, targetdata, s_anchor, t_anchor
1489 local usedorientation = false
1490 if hasanchor then
1491 anchor, source, target, s_anchor, t_anchor = getanchors(current)
1492 end
1493 if hasorientation then
1494 local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current)
1495 local orientation, basepoint_h, basepoint_v = applyorientation(orientation,shift,height,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
1496 if orientation == 1 then
1497 basepoint_h = basepoint_h + width - height
1498 basepoint_v = basepoint_v - height
1499 usedorientation = orientation
1500 elseif orientation == 2 then
1501 basepoint_h = basepoint_h + width
1502 basepoint_v = basepoint_v + depth - height
1503 usedorientation = orientation
1504 elseif orientation == 3 then
1505 basepoint_h = basepoint_h + height
1506 usedorientation = orientation
1507 end
1508 if target then
1509 targetdata = anchors[target]
1510 if targetdata then
1511 if pos_r == righttoleft_code then
1512 pos_h = targetdata[1] - basepoint_h
1513 else
1514 pos_h = targetdata[1] + basepoint_h
1515 end
1516 pos_v = targetdata[2] - basepoint_v
1517 goto posdone
1518 end
1519 end
1520 if pos_r == righttoleft_code then
1521 pos_h = ref_h - basepoint_h
1522 else
1523 pos_h = ref_h + basepoint_h
1524 end
1525 pos_v = ref_v - (cur_v + basepoint_v)
1526 elseif hasoffset then
1527
1528 local xoffset, yoffset = getoffsets(current)
1529
1530
1531 if boxdir ~= pos_r then
1532 shift = shift + width
1533 end
1534 if target then
1535 targetdata = anchors[target]
1536 if targetdata then
1537 if pos_r == righttoleft_code then
1538 pos_h = targetdata[1] - (shift + xoffset)
1539 else
1540 pos_h = targetdata[1] + (shift + xoffset)
1541 end
1542 pos_v = targetdata[2] - (height - yoffset)
1543 goto posdone
1544 end
1545 end
1546 if pos_r == righttoleft_code then
1547 pos_h = ref_h - (shift + xoffset)
1548 else
1549 pos_h = ref_h + (shift + xoffset)
1550 end
1551 pos_v = ref_v - (cur_v + height - yoffset)
1552 elseif hasanchor then
1553
1554
1555 if boxdir ~= pos_r then
1556 shift = shift + width
1557 end
1558 if target then
1559 local a = anchors[target]
1560 if a then
1561 if pos_r == righttoleft_code then
1562 pos_h = targetdata[1] - shift
1563 else
1564 pos_h = targetdata[1] + shift
1565 end
1566 pos_v = targetdata[2] - height
1567 goto posdone
1568 end
1569 end
1570 if pos_r == righttoleft_code then
1571 pos_h = ref_h - shift
1572 else
1573 pos_h = ref_h + shift
1574 end
1575 pos_v = ref_v - (cur_v + height)
1576 else
1577
1578
1579 if boxdir ~= pos_r then
1580 shift = shift + width
1581 end
1582 if pos_r == righttoleft_code then
1583 pos_h = ref_h - shift
1584 else
1585 pos_h = ref_h + shift
1586 end
1587 pos_v = ref_v - (cur_v + height)
1588 end
1589 goto process
1590 ::posdone::
1591 if anchor and anchor > 0 then
1592
1593
1594 pos_h, pos_v = applyanchor(t_anchor,true, pos_h,pos_v,targetdata[3],targetdata[4],targetdata[5])
1595 pos_h, pos_v = applyanchor(s_anchor,false,pos_h,pos_v,width,height,depth)
1596 end
1597 ::process::
1598 if source then
1599
1600 local anchor_h = pos_h
1601 local anchor_v = pos_v
1602 if usedorientation then
1603 if usedorientation == 1 then
1604 anchor_v = anchor_v - (width - height)
1605 elseif usedorientation == 2 then
1606 anchor_v = anchor_v - (depth - height)
1607 elseif usedorientation == 3 then
1608 anchor_v = anchor_v + (height - width)
1609 end
1610 end
1611 anchors[source] = { anchor_h, anchor_v, width, height, depth }
1612 end
1613 if usedorientation then
1614 pushorientation(usedorientation,pos_h,pos_v,pos_r)
1615 end
1616 if source and stored then
1617 flushstored(current,source,true)
1618 end
1619 if id == vlist_code then
1620 vlist_out(current,list)
1621 else
1622 hlist_out(current,list)
1623 end
1624 if source and stored then
1625 flushstored(current,source,false)
1626 end
1627 if usedorientation then
1628 poporientation(usedorientation,pos_h,pos_v,pos_r)
1629 end
1630 end
1631 cur_v = cur_v + height + depth
1632 elseif id == kern_code then
1633 cur_v = cur_v + getkern(current)
1634 elseif id == rule_code then
1635 local width, height, depth, virtual = getruledimensions(current)
1636 local total = height + depth
1637 if total > 0 then
1638 if width == runningrule then
1639 width = boxwidth
1640 end
1641 if width > 0 then
1642 local xoffset, yoffset, left, right = getoffsets(current)
1643 if not virtual then
1644 if left ~= 0 then
1645 width = width - left
1646 xoffset = left
1647 end
1648 if right ~= 0 then
1649 width = width - right
1650 end
1651 end
1652 if pos_r == righttoleft_code then
1653 xoffset = - xoffset - width
1654 end
1655 flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total,subtype)
1656 end
1657 if not virtual then
1658 cur_v = cur_v + total
1659 end
1660 end
1661 elseif id == whatsit_code then
1662 flushwhatsit[subtype](current,pos_h,pos_v)
1663 else
1664
1665 goto synced
1666 end
1667 if pos_r == righttoleft_code then
1668 pos_h = ref_h - cur_h
1669 else
1670 pos_h = ref_h + cur_h
1671 end
1672 pos_v = ref_v - cur_v
1673 ::synced::
1674 end
1675 pos_h = ref_h
1676 pos_v = ref_v
1677 pos_r = ref_r
1678 end
1679
1680end
1681
1682function drivers.converters.lmtx(driver,box,smode,objnum,specification)
1683
1684 if not driver then
1685 report("error in converter, no driver")
1686 return
1687 end
1688
1689 if box then
1690 box = tonut(box)
1691 else
1692 report("error in converter, no box")
1693 return
1694 end
1695
1696 local actions = driver.actions
1697 local flushers = driver.flushers
1698
1699 initialize = actions.initialize
1700 finalize = actions.finalize
1701
1702 updatefontstate = flushers.updatefontstate
1703
1704 pushorientation = flushers.pushorientation
1705 poporientation = flushers.poporientation
1706
1707 pushleaderlevel = flushers.pushleaderlevel
1708 popleaderlevel = flushers.popleaderlevel
1709
1710 flushcharacter = flushers.character
1711 flushfontchar = flushers.fontchar
1712 flushrule = flushers.rule
1713 flushsimplerule = flushers.simplerule
1714 flushspecialrule = flushers.specialrule
1715 flushliteral = flushers.literal
1716 flushwhatsit = flushers.whatsit
1717 flushspace = flushers.space
1718
1719 reset_directions()
1720 reset_anchors()
1721 reset_state()
1722
1723 shippingmode = smode
1724
1725 local details = nil
1726
1727 local width, height, depth = getwhd(box)
1728
1729 local total = height + depth
1730
1731 if height > maxdimen or depth > maxdimen or width > maxdimen or total > maxdimen then
1732 goto DONE
1733 end
1734
1735 if shippingmode == "page" then
1736
1737
1738
1739 local pagewidth, pageheight = getpagedimensions()
1740
1741 pos_r = lefttoright_code
1742
1743 if pagewidth > 0 then
1744 page_size_h = pagewidth
1745 else
1746 page_size_h = width
1747 end
1748
1749 if page_size_h == 0 then
1750 page_size_h = width
1751 end
1752
1753 if pageheight > 0 then
1754 page_size_v = pageheight
1755 else
1756 page_size_v = total
1757 end
1758
1759 if page_size_v == 0 then
1760 page_size_v = total
1761 end
1762
1763 local refpoint_h = 0
1764 local refpoint_v = page_size_v
1765
1766 pos_h = refpoint_h
1767 pos_v = refpoint_v - height
1768
1769 else
1770
1771 page_size_h = width
1772 page_size_v = total
1773 pos_r = getdirection(box)
1774 pos_v = depth
1775 pos_h = pos_r == righttoleft_code and width or 0
1776
1777 end
1778
1779 shipbox_ref_h = pos_h
1780 shipbox_ref_v = pos_v
1781
1782 details = {
1783 shippingmode = smode,
1784 boundingbox = { 0, 0, page_size_h, page_size_v },
1785 objectnumber = smode ~= "page" and objnum or nil,
1786 pagenumber = smode == "page" and objnum or nil,
1787 specification = specification,
1788 }
1789
1790 initialize(driver,details)
1791
1792 lastfont = nil
1793
1794 if getid(box) == vlist_code then
1795 vlist_out(box,getlist(box))
1796 else
1797 hlist_out(box,getlist(box))
1798 end
1799
1800 ::DONE::
1801
1802 finalize(driver,details)
1803
1804 shippingmode = "none"
1805end
1806
1807
1808
1809do
1810
1811
1812
1813
1814 local properties = nodes.properties.data
1815 local flush = texio.write
1816 local flushline = texio.writenl
1817
1818 local periods = utilities.strings.newrepeater(".")
1819
1820 local f_detail_0 = formatters["%s %s = %s"]
1821 local f_detail_1 = formatters["%i: %s %s = %s"]
1822 local f_detail_2 = formatters["%i:%i: %s %s = %s"]
1823
1824 local function showdetails(n,l,tlp,l1,l2)
1825 local p = properties[tonut(n)]
1826 if p then
1827 for k, v in sortedhash(p) do
1828 local t = type(v)
1829 local p = periods[l+1]
1830 if t == "string" then
1831 if find(v,"[\n\r]") then
1832 v = "\n" .. stripstring(v) .. "\n"
1833 end
1834 elseif t == "number" or t == "boolean" then
1835 v = tostring(v)
1836 elseif t == "table" then
1837 v = sequenced(v)
1838 else
1839 v = "<" .. tostring(v) .. ">"
1840 end
1841 if tlp == 3 then
1842 flushline(f_detail_2(l1,l2,p,k,v))
1843 elseif tlp == 2 then
1844 flushline(f_detail_1(l2,p,k,v))
1845 elseif tlp == 1 then
1846 flushline(f_detail_1(l1,p,k,v))
1847 else
1848 flushline(f_detail_0(p,k,v))
1849 end
1850 end
1851 end
1852 end
1853
1854 local whatsittracers = {
1855 latelua = showdetails,
1856 literal = showdetails,
1857 }
1858
1859 callbacks.register("show_whatsit",function(n,what,l,tlp,l1,l2)
1860 local s = nodes.whatsitcodes[n.subtype]
1861 if what == 1 then
1862 return s or "unknown"
1863
1864 else
1865 local w = whatsittracers[s]
1866 if w then
1867 w(n,l,tlp,l1,l2)
1868 end
1869 end
1870 end,"provide whatsit details")
1871
1872 local names = attributes.names
1873
1874 local a_tagged = attributes.private('tagged')
1875 local taglist = structures.tags.taglist
1876 local details = false
1877
1878 trackers.register("attributes.tags",function(v) details = v end)
1879
1880 callbacks.register("get_attribute",function(k,v)
1881 local detail = nil
1882 if details and k == a_tagged then
1883 detail = taglist[v]
1884 if detail then
1885 detail = detail.taglist
1886 if detail then
1887 detail = detail[#detail]
1888 end
1889 end
1890 end
1891 return names[k], detail
1892 end,"provide verbose attribute name")
1893
1894end
1895 |