1if not modules then modules = { } end modules ['spac-ali'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to spac-ali.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 div = math.div
11local format = string.format
12
13local tasks = nodes.tasks
14local enableaction = tasks.enableaction
15
16local nuts = nodes.nuts
17
18local setlist = nuts.setlist
19local setlink = nuts.setlink
20local getdirection = nuts.getdirection
21local takeattr = nuts.takeattr
22local getwidth = nuts.getwidth
23local findtail = nuts.tail
24
25local righttoleft_code = tex.directioncodes.righttoleft
26
27local linelist_code = nodes.listcodes.line
28
29local hpack_nodes = nuts.hpack
30local nextlist = nuts.traversers.list
31
32local new_stretch = nuts.pool.stretch
33
34local a_realign = attributes.private("realign")
35local c_realpageno = tex.iscount("realpageno")
36
37local texsetattribute = tex.setattribute
38local texgetcount = tex.getcount
39
40local isleftpage = layouts.status.isleftpage
41
42typesetters = typesetters or { }
43local alignments = { }
44typesetters.alignments = alignments
45
46local report_realign = logs.reporter("typesetters","margindata")
47local trace_realign = trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
48
49local nofrealigned = 0
50
51
52
53
54
55
56local function handler(head,leftpage,realpageno)
57 for current, id, subtype, list in nextlist, head do
58 if subtype == linelist_code then
59 local a = takeattr(current,a_realign)
60 if a and a > 0 then
61 local pageno = div(a,10)
62 if pageno ~= realpageno then
63 local align = a % 10
64 local action = 0
65 if align == 1 then
66 action = leftpage and 1 or 2
67 elseif align == 2 then
68 action = leftpage and 2 or 1
69 end
70
71 local direction = getdirection(current)
72
73 if direction == righttoleft_code then
74 if action == 1 then
75 action = 2
76 elseif action == 2 then
77 action = 1
78 end
79 end
80
81
82 if action == 1 then
83 local head = list
84 setlink(findtail(list),new_stretch(3))
85 setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
86 if trace_realign then
87 report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
88 end
89 elseif action == 2 then
90 local head = setlink(new_stretch(3),list)
91 setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
92 if trace_realign then
93 report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno)
94 end
95 elseif trace_realign then
96 report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
97 end
98 nofrealigned = nofrealigned + 1
99 end
100 end
101 end
102 handler(list,leftpage,realpageno)
103 end
104 return head
105end
106
107function alignments.handler(head)
108 return handler(head,isleftpage(),texgetcount(c_realpageno))
109end
110
111local enabled = false
112
113function alignments.set(n)
114 if not enabled then
115 enableaction("shipouts","typesetters.alignments.handler")
116 enabled = true
117 if trace_realign then
118 report_realign("enabled")
119 end
120 end
121 texsetattribute(a_realign,texgetcount(c_realpageno) * 10 + n)
122end
123
124interfaces.implement {
125 name = "setrealign",
126 actions = alignments.set,
127 arguments = "integer",
128}
129
130statistics.register("realigning", function()
131 if nofrealigned > 0 then
132 return format("%s processed",nofrealigned)
133 else
134 return nil
135 end
136end)
137 |