1if not modules then modules = { } end modules ['node-bck'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to node-bck.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
10
11
12
13
14
15
16local attributes, nodes, node = attributes, nodes, node
17
18local enableaction = nodes.tasks.enableaction
19
20local nodecodes = nodes.nodecodes
21local listcodes = nodes.listcodes
22
23local hlist_code <const> = nodecodes.hlist
24local vlist_code <const> = nodecodes.vlist
25
26local alignmentlist_code <const> = listcodes.alignment
27local celllist_code <const> = listcodes.cell
28
29local nuts = nodes.nuts
30local nodepool = nuts.pool
31
32local getnext = nuts.getnext
33local getprev = nuts.getprev
34local getid = nuts.getid
35local getlist = nuts.getlist
36local getattr = nuts.getattr
37local getsubtype = nuts.getsubtype
38local getwhd = nuts.getwhd
39local getwidth = nuts.getwidth
40local getprop = nuts.getprop
41
42local setattr = nuts.setattr
43local setlink = nuts.setlink
44local setlist = nuts.setlist
45local setattributelist = nuts.setattributelist
46local setprop = nuts.setprop
47
48local takebox = nuts.takebox
49
50local nextnode = nuts.traversers.node
51local nexthlist = nuts.traversers.hlist
52local nextlist = nuts.traversers.list
53
54local flushnodelist = nuts.flushlist
55local flushnode = nuts.flush
56
57local new_rule = nodepool.rule
58local new_kern = nodepool.kern
59local new_hlist = nodepool.hlist
60
61local privateattributes = attributes.private
62
63local getvalue = attributes.getvalue
64local hasvalues = attributes.hasvalues
65
66local linefillers = nodes.linefillers
67
68local a_background <const> = privateattributes("background")
69local a_alignbackground <const> = privateattributes("alignbackground")
70local a_linefiller <const> = privateattributes("linefiller")
71
72local unsetvalue <const> = attributes.unsetvalue
73
74local trace_alignment = false
75local report_alignment = logs.reporter("backgrounds","alignment")
76
77trackers.register("backgrounds.alignments",function(v) trace_alignment = v end)
78
79
80
81
82
83
84
85
86
87
88local overshoot = math.floor(65781/5)
89
90local function colored_a(current,list,template,id)
91 local width, height, depth = getwhd(current)
92 local total = height + depth
93 if width > 0 and total > 0 then
94 local rule = nil
95
96 local a = getattr(template,a_linefiller)
97 if a then
98 local d = getvalue(a_linefiller,a)
99 if d then
100 rule = linefillers.filler(template,d,width,height,depth)
101 end
102 end
103
104 if not rule then
105 rule = new_rule(width,height,depth)
106 setattributelist(rule,template)
107 end
108 local back = new_kern(-((id == vlist_code and total) or width))
109 return setlink(rule,back,list)
110 end
111end
112
113local function colored_b(current,list,template,id,indent)
114 local width, height, depth = getwhd(current)
115 local total = height + depth
116 if width > 0 and total > 0 then
117 local fore = (indent ~= 0) and new_kern(indent)
118 local rule = nil
119
120 local a = getattr(template,a_linefiller)
121 if a then
122 local d = getvalue(a_linefiller,a)
123 if d then
124 rule = linefillers.filler(template,d,width-indent,height,depth)
125 end
126 end
127
128 if not rule then
129 rule = new_rule(width-indent,height+overshoot,depth+overshoot)
130 setattributelist(rule,template)
131 end
132 if overshoot == 0 then
133 local back = new_kern(-((id == vlist_code and total) or width))
134 return setlink(fore,rule,back,list)
135 else
136 rule = new_hlist(rule)
137 return setlink(fore,rule,list)
138 end
139 end
140end
141
142local templates = { }
143local currentrow = 0
144local enabled = false
145local alignments = false
146
147
148
149local function add_alignbackgrounds(head,list)
150 for current, id, subtype, list in nextlist, list do
151 if list and id == hlist_code and subtype == celllist_code then
152 for template in nexthlist, list do
153 local background = getattr(template,a_alignbackground)
154 if background then
155 local list = colored_a(current,list,template,id)
156 if list then
157 setlist(current,list)
158 end
159
160 setattr(template,a_alignbackground,unsetvalue)
161 end
162 break
163 end
164 end
165 end
166
167 local template = getprop(head,"alignmentchecked")
168 if template then
169 list = colored_b(head,list,template[1],hlist_code,template[2])
170 flushnodelist(template[1])
171 templates[currentrow] = false
172 return list
173 end
174end
175
176local function add_backgrounds(head,id,list)
177 if list then
178 for current, id, subtype, list in nextlist, list do
179 if list then
180 if alignments and subtype == alignmentlist_code then
181 local l = add_alignbackgrounds(current,list)
182 if l then
183 list = l
184 setlist(current,list)
185 end
186 end
187 local l = add_backgrounds(current,id,list)
188 if l then
189 list = l
190 setlist(current,l)
191 end
192 end
193 end
194 end
195 if id == hlist_code or id == vlist_code then
196 local background = getattr(head,a_background)
197 if background then
198 list = colored_a(head,list,head,id)
199
200 setattr(head,a_background,unsetvalue)
201 return list
202 end
203 end
204end
205
206function nodes.handlers.backgrounds(head)
207 add_backgrounds(head,getid(head),getlist(head))
208 return head
209end
210
211function nodes.handlers.backgroundspage(head,where)
212 if head and where == "alignment" then
213 for n in nexthlist, head do
214 local p = getprop(n,"alignmentchecked")
215 if not p and getsubtype(n) == alignmentlist_code then
216 currentrow = currentrow + 1
217 local template = templates[currentrow]
218 if trace_alignment then
219 report_alignment("%03i %s %s",currentrow,"page",template and "+" or "-")
220 end
221 setprop(n,"alignmentchecked",template)
222 end
223 end
224 end
225 return head
226end
227
228function nodes.handlers.backgroundsvbox(head,where)
229 if head and where == "vbox" then
230 local list = getlist(head)
231 if list then
232 for n in nexthlist, list do
233 local p = getprop(n,"alignmentchecked")
234 if not p and getsubtype(n) == alignmentlist_code then
235 currentrow = currentrow + 1
236 local template = templates[currentrow]
237 if trace_alignment then
238 report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-")
239 end
240 setprop(n,"alignmentchecked",template)
241 end
242 end
243 end
244 end
245 return head
246end
247
248local function enable(alignmentstoo)
249 if not enabled then
250 enabled = true
251 enableaction("shipouts","nodes.handlers.backgrounds")
252 end
253 if not alignments and alignmentstoo then
254 alignments = true
255 enableaction("vboxbuilders","nodes.handlers.backgroundsvbox")
256 enableaction("mvlbuilders", "nodes.handlers.backgroundspage")
257 end
258end
259
260interfaces.implement {
261 name = "enablebackgroundboxes",
262 onlyonce = true,
263 actions = enable,
264}
265
266interfaces.implement {
267 name = "enablebackgroundalign",
268 onlyonce = true,
269 actions = function()
270 enable(true)
271 end,
272}
273
274interfaces.implement {
275 name = "setbackgroundrowdata",
276 arguments = { "integer", "integer", "dimension" },
277 actions = function(row,box,indent)
278 row = row -1
279 if box == 0 then
280 templates[row] = false
281 else
282 templates[row] = { takebox(box), indent }
283 end
284 end,
285}
286
287interfaces.implement {
288 name = "resetbackgroundrowdata",
289 actions = function()
290 currentrow = 0
291 end,
292}
293 |