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