1if not modules then modules = { } end modules ['spac-ovl'] = {
2 version = 1.001,
3 comment = "companion to spac-brk.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local next, type, tonumber, tostring = next, type, tonumber, tostring
10
11local settings_to_array = utilities.parsers.settings_to_array
12local settings_to_hash = utilities.parsers.settings_to_hash
13
14local nuts = nodes.nuts
15local tonut = nodes.tonut
16
17local newrule = nuts.pool.virtualrule
18local insertbefore = nuts.insertbefore
19local insertafter = nuts.insertafter
20local hpack_string = nuts.typesetters.tohpack
21local getwidth = nuts.getwidth
22local getid = nuts.getid
23local getprev = nuts.getprev
24local setwhd = nuts.setwhd
25local setoffsets = nuts.setoffsets
26
27local setcolor = nodes.tracers.colors.set
28local settransparency = nodes.tracers.transparencies.set
29
30local texgetnest = tex.getnest
31local texgetcount = tex.getcount
32local texsetcount = tex.setcount
33
34local nodecodes = nodes.nodecodes
35
36local penalty_code <const> = nodecodes.penalty
37local glue_code <const> = nodecodes.glue
38local disc_code <const> = nodecodes.disc
39local kern_code <const> = nodecodes.kern
40local math_code <const> = nodecodes.math
41
42local breakcodes = tex.breakcodes
43
44local report = logs.reporter("linebreaks")
45
46local c_tracinglousiness <const> = tex.iscount("tracinglousiness")
47local c_linebreakchecks <const> = tex.iscount("linebreakchecks")
48
49local width = 65536 / 2
50local height = 9 * 65536
51local depth = 3 * 65536
52local xoffset = 1 * 65536
53local yoffset = -3 * 65536
54
55local serial = false
56local usedfont = false
57local nestlevel = false
58local overload = false
59local order = 0
60local saved = 0
61
62local actions = {
63 [breakcodes.initialize] = function()
64 if texgetnest("ptr") == nestlevel then
65 usedfont = nodes.visualizers.getusedfont()
66 serial = false
67 order = order + 1
68 end
69 end,
70 [breakcodes.start] = function(checks,pass,subpass)
71 if texgetnest("ptr") == nestlevel then
72 if pass == 2 then
73 serial = { }
74 end
75 end
76 end,
77 [breakcodes.report] = function(checks,pass,subpass,currentserial,previousserial,line,kind,class,classes,badness,demerits,breakpoint,short,glue)
78 if serial and breakpoint and texgetnest("ptr") == nestlevel then
79 local s = {
80 serial = currentserial,
81 badness = badness,
82 demerits = demerits,
83 breakpoint = breakpoint,
84 }
85 serial[currentserial] = s
86 local found = overload and overload[currentserial]
87 if found then
88 report("pass %i, overloading serial %i.%i demerits from %i to %i",2,order,currentserial,demerits,found)
89 return found
90 end
91 end
92 return demerits
93 end,
94 [breakcodes.collect] = function()
95 if serial and texgetnest("ptr") == nestlevel and texgetcount(c_tracinglousiness) >= 1 then
96 for currentserial=1,#serial do
97 local data = serial[currentserial]
98 local breakpoint = data.breakpoint
99 local current = tonut(breakpoint)
100 while current do
101 local id = getid(current)
102 if id == penalty_code or id == glue_code or id == kern_code or id == math_code then
103 current = getprev(current)
104 else
105 break
106 end
107 end
108 if current then
109 local rule = newrule(width,height,depth,currentserial)
110 data.rule = rule
111 insertafter(current,current,rule)
112 end
113 end
114 end
115 end,
116 [breakcodes.wrapup] = function()
117 if serial and texgetnest("ptr") == nestlevel then
118 local n = #serial
119 local trace = texgetcount(c_tracinglousiness)
120 if trace >= 2 then
121 report("%i demerits in set %i",n,order)
122 end
123 for currentserial=1,n do
124 local data = serial[currentserial]
125 local demerits = data.demerits
126 if trace >= 1 then
127 local rule = data.rule
128 if rule then
129 local tag = tostring(order).."."..tostring(currentserial)
130 local text = hpack_string(tag,usedfont)
131 local size = getwidth(text)
132 setwhd(text,0,0,0)
133 setoffsets(text,-size-xoffset,yoffset)
134 insertafter(rule,rule,text)
135 end
136 end
137 serial[currentserial] = demerits
138 if trace >= 2 then
139 report("% 4i : %8i",currentserial,demerits)
140 end
141 end
142 overload = false
143 texsetcount("linebreakchecks",saved)
144 end
145 end,
146}
147
148local function action(what,...)
149 local action = actions[what]
150 if action then
151 return action(...)
152 end
153end
154
155local function show(str)
156 nestlevel = texgetnest("ptr")
157 saved = texgetcount("linebreakchecks")
158 if str and str ~= "" then
159 if type(str) == "table" then
160 overload = str
161 else
162 overload = settings_to_hash(str)
163 for k, v in next, overload do
164 overload[tonumber(k)] = tonumber(v) or -1
165 end
166 end
167 else
168 overload = false
169 end
170 texsetcount("linebreakchecks",3)
171end
172
173local function last()
174 return serial or { }
175end
176
177nodes.handlers.linebreakchecks[3] = action
178
179
180
181local context = context
182local scaninteger = tokens.scanners.integer
183
184local function feedback()
185 local l = last()
186 local n = #l
187 if n > 0 then
188 local t = { n }
189 local m = 1
190 for i=1,#l do
191 m = m + 1 ; t[m] = i
192 m = m + 1 ; t[m] = l[i]
193 end
194 context("% t",t)
195 end
196end
197
198interfaces.implement {
199 name = "lousiness",
200 public = true,
201 protected = true,
202 usage = "value",
203 actions = function(what)
204 if what == "value" then
205 feedback()
206 else
207 local n = scaninteger()
208 local t = { }
209 for i=1,n do
210 t[scaninteger()] = scaninteger()
211 end
212 show(t)
213 end
214 end,
215}
216
217interfaces.implement {
218 name = "silliness",
219 public = true,
220 protected = true,
221 usage = "value",
222 actions = function(what)
223 if what == "value" then
224 feedback()
225 else
226 show { [scaninteger()] = 0 }
227 end
228 end,
229}
230 |