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