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
241local function enable(alignmentstoo)
242 if not enabled then
243 enabled = true
244 enableaction("shipouts","nodes.handlers.backgrounds")
245 end
246 if not alignments and alignmentstoo then
247 alignments = true
248 enableaction("vboxbuilders","nodes.handlers.backgroundsvbox")
249 enableaction("mvlbuilders", "nodes.handlers.backgroundspage")
250 end
251end
252
253interfaces.implement {
254 name = "enablebackgroundboxes",
255 onlyonce = true,
256 actions = enable,
257}
258
259interfaces.implement {
260 name = "enablebackgroundalign",
261 onlyonce = true,
262 actions = function()
263 enable(true)
264 end,
265}
266
267interfaces.implement {
268 name = "setbackgroundrowdata",
269 arguments = { "integer", "integer", "dimension" },
270 actions = function(row,box,indent)
271 row = row -1
272 if box == 0 then
273 templates[row] = false
274 else
275 templates[row] = { takebox(box), indent }
276 end
277 end,
278}
279
280interfaces.implement {
281 name = "resetbackgroundrowdata",
282 actions = function()
283 currentrow = 0
284 end,
285}
286 |