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
17local nodepool = nuts.pool
18
19local tonode = nuts.tonode
20local tonut = nuts.tonut
21
22local getnext = nuts.getnext
23local getprev = nuts.getprev
24local getid = nuts.getid
25local getlist = nuts.getlist
26local setlist = nuts.setlist
27local setlink = nuts.setlink
28local getdirection = nuts.getdirection
29local takeattr = nuts.takeattr
30local getsubtype = nuts.getsubtype
31local getwidth = nuts.getwidth
32local findtail = nuts.tail
33
34local righttoleft_code = nodes.dirvalues.righttoleft
35
36local hpack_nodes = nuts.hpack
37
38local unsetvalue = attributes.unsetvalue
39
40local nodecodes = nodes.nodecodes
41local listcodes = nodes.listcodes
42
43local hlist_code = nodecodes.hlist
44local vlist_code = nodecodes.vlist
45
46local linelist_code = listcodes.line
47
48local new_stretch = nodepool.stretch
49
50local a_realign = attributes.private("realign")
51
52local texsetattribute = tex.setattribute
53local texgetcount = tex.getcount
54
55local isleftpage = layouts.status.isleftpage
56
57typesetters = typesetters or { }
58local alignments = { }
59typesetters.alignments = alignments
60
61local report_realign = logs.reporter("typesetters","margindata")
62local trace_realign = trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
63
64local nofrealigned = 0
65
66
67
68
69
70
71local function handler(head,leftpage,realpageno)
72 local current = head
73 while current do
74 local id = getid(current)
75 if id == hlist_code then
76 if getsubtype(current) == linelist_code then
77 local a = takeattr(current,a_realign)
78 if not a or a == 0 then
79
80 else
81 local align = a % 10
82 local pageno = div(a,10)
83 if pageno == realpageno then
84
85 else
86 local action = 0
87 if align == 1 then
88 action = leftpage and 1 or 2
89 elseif align == 2 then
90 action = leftpage and 2 or 1
91 end
92
93 local direction = getdirection(current)
94
95 if direction == righttoleft_code then
96 if action == 1 then
97 action = 2
98 elseif action == 2 then
99 action = 1
100 end
101 end
102
103 if action == 1 then
104 local head = getlist(current)
105 setlink(findtail(head),new_stretch(3))
106 setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
107 if trace_realign then
108 report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
109 end
110 elseif action == 2 then
111 local list = getlist(current)
112 local head = setlink(new_stretch(3),list)
113 setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
114 if trace_realign then
115 report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno)
116 end
117 elseif trace_realign then
118 report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
119 end
120 nofrealigned = nofrealigned + 1
121 end
122 end
123 end
124 handler(getlist(current),leftpage,realpageno)
125 elseif id == vlist_code then
126 handler(getlist(current),leftpage,realpageno)
127 end
128 current = getnext(current)
129 end
130 return head
131end
132
133function alignments.handler(head)
134 return handler(head,isleftpage(),texgetcount("realpageno"))
135end
136
137local enabled = false
138
139function alignments.set(n)
140 if not enabled then
141 enableaction("shipouts","typesetters.alignments.handler")
142 enabled = true
143 if trace_realign then
144 report_realign("enabled")
145 end
146 end
147 texsetattribute(a_realign,texgetcount("realpageno") * 10 + n)
148end
149
150interfaces.implement {
151 name = "setrealign",
152 actions = alignments.set,
153 arguments = "integer",
154}
155
156statistics.register("realigning", function()
157 if nofrealigned > 0 then
158 return format("%s processed",nofrealigned)
159 else
160 return nil
161 end
162end)
163 |