1if not modules then modules = { } end modules ['trac-bld'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to trac-bld.mkxl",
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 nuts = nodes.nuts
11local tonut = nodes.tonut
12
13local insertafter = nuts.insertafter
14local hpack_string = nuts.typesetters.tohpack
15local hpack = nuts.hpack
16local getheight = nuts.getheight
17local getid = nuts.getid
18local setwhd = nuts.setwhd
19local setoffsets = nuts.setoffsets
20local setlink = nuts.setlink
21
22local newrule = nuts.pool.virtualrule
23
24local nodecodes = nodes.nodecodes
25
26local hlist_code = nodecodes.hlist
27local vlist_code = nodecodes.vlist
28local rule_code = nodecodes.rule
29
30local setcolor = nodes.tracers.colors.set
31
32local buildcodes = tex.buildcodes
33
34local ejectpenalty = tex.magicconstants.eject_penalty
35
36local report = logs.reporter("build")
37
38local xoffset = 4 * 65536
39local yoffset = 1 * 65536
40local usedfont = false
41
42local f_status_y = string.formatters["%i : badness=%i costs=%i height=%p depth=%p stretch=%p shrink=%p hasfil=%l"]
43local f_status_n = string.formatters["%i"]
44
45local variables = interfaces.variables
46local v_after = variables.after
47local v_before = variables.before
48local v_reset = variables.reset
49local v_yes = variables.yes
50local v_all = variables.all
51
52local done = { }
53local last = false
54local count = 0
55local forced = { }
56local ignored = { }
57local detail = false
58local enabled = false
59local ejecting = false
60
61
62
63local function checkedforce(moveon,fireup,penalty)
64 local how = forced[count]
65 ejecting = fireup and penalty == ejectpenalty
66 if how == v_after then
67 report("forcing pagebreak %s %i",how,count)
68 forced[count] = nil
69 ignored[count] = true
70
71 return true, true
72 elseif how == v_before then
73 report("forcing pagebreak %s %i",how,count)
74 forced[count] = nil
75 ignored[count] = true
76 return false, true
77 else
78 return moveon, fireup
79 end
80end
81
82local function check(current,moveon,fireup,badness,costs,penalty)
83 if last then
84 count = count + 1
85 end
86 return checkedforce(moveon,fireup,penalty)
87end
88
89local forceactions = {
90 [buildcodes.step] = step,
91 [buildcodes.check] = check,
92}
93
94local function handleforce(what,...)
95 local action = forceactions[what]
96 if action then
97 return action(...)
98 end
99end
100
101local function disableforce()
102 count = 0
103 forced = { }
104 ignored = { }
105 if enabled and not trace then
106 callback.register("show_build")
107 end
108 enabled = false
109end
110
111local function enableforce()
112 if not enabled and not trace then
113 callback.register("show_build",handleforce)
114 end
115 enabled = true
116end
117
118interfaces.implement {
119 name = "registerforcedbreak",
120 public = true,
121 protected = true,
122 arguments = "2 optionals",
123 actions = function(where,how)
124 if where == v_reset then
125 disableforce()
126 else
127 for n in string.gmatch(where,"%d+") do
128 forced[tonumber(n)] = how
129 end
130 enableforce()
131 end
132 end
133}
134
135interfaces.implement {
136 name = "resetforcedbreak",
137 public = true,
138 protected = true,
139 actions = disableforce,
140}
141
142
143
144local function initialize()
145 usedfont = nodes.visualizers.getusedfont()
146end
147
148local function step(current)
149 current = tonut(current)
150 local id = getid(current)
151 if id == hlist_code or id == vlist_code or id == rule_code then
152 last = current
153 end
154end
155
156local function check(current,moveon,fireup,badness,costs,penalty)
157 if last then
158 count = count + 1
159 done[#done+1] = {
160 count = count,
161 line = last,
162 badness = badness,
163 penalty = penalty,
164 costs = costs,
165 height = 0,
166 depth = 0,
167 stretch = 0,
168 shrink = 0,
169 hasfil = false,
170 }
171 end
172 return checkedforce(moveon,fireup,penalty)
173end
174
175
176
177
178
179
180
181
182
183
184
185local function move(current,height,depth,stretch,shrink,hasfil)
186 local d = done[#done]
187 if d then
188 d.height = height
189 d.depth = depth
190 d.stretch = stretch
191 d.shrink = shrink
192 d.hasfil = hasfil
193 end
194end
195
196
197
198
199
200
201
202local showactions = {
203 [buildcodes.initialize] = initialize,
204 [buildcodes.step] = step,
205 [buildcodes.check] = check,
206
207 [buildcodes.move] = move,
208
209
210}
211
212interfaces.implement {
213 name = "build_page_before_shipout",
214 actions = function()
215 if trace then
216 done[#done] = nil
217 if #done > 0 then
218 for i=1,#done do
219 local data = done[i]
220 local line = data.line
221 local count = data.count
222 if not ignored[count] then
223 local badness = data.badness
224 if detail and badness then
225 data = f_status_y(count,badness,data.costs,data.height,data.depth,data.stretch,data.shrink,data.hasfil)
226 else
227 data = f_status_n(count)
228 end
229 local text = hpack_string(data,usedfont)
230 local height = getheight(text)
231 local rule = newrule(height,height,0)
232 setcolor(rule,"trace:db")
233 setoffsets(rule,-(height+xoffset),0)
234 text = hpack(setlink(rule,text))
235 setwhd(text,0,0,0)
236 setoffsets(text,0,-(height+yoffset))
237 insertafter(line,line,text)
238 end
239 end
240 if ejecting then
241 count = 0
242 done = { }
243 end
244 end
245 end
246 end
247}
248
249interfaces.implement {
250 name = "build_page_after_shipout",
251 actions = function()
252 if trace then
253 done = { }
254 end
255 last = false
256 end
257}
258
259local function build_page_setup(v)
260 if v == "all" or v == v_all then
261 trace = true
262 detail = true
263 elseif v == true or v == "yes" or v == v_yes then
264 trace = true
265 detail = false
266 else
267 trace = false
268 detail = false
269 end
270 if trace then
271 callback.register("show_build", function(what,...)
272 local action = showactions[what]
273 if action then
274 return action(...)
275 end
276 end)
277 elseif not enabled then
278 callback.register("show_build")
279 end
280end
281
282interfaces.implement {
283 name = "build_page_setup",
284 arguments = "string",
285 actions = build_page_setup,
286}
287
288trackers.register("builders.page.show", build_page_setup)
289 |