1if not modules then modules = { } end modules ['typo-lbx'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to typo-lbx.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 context = context
11
12local tostring = tostring
13
14local nuts = nodes.nuts
15local tonut = nodes.tonut
16local tonode = nodes.tonode
17
18local left_box_code <const> = nodes.listcodes.left
19local right_box_code <const> = nodes.listcodes.right
20local local_box_code <const> = nodes.listcodes["local"]
21local hlist_code <const> = nodes.nodecodes.hlist
22
23
24
25local getlist = nuts.getlist
26local getprev = nuts.getprev
27local getnext = nuts.getnext
28local getattribute = nuts.getattribute
29local gettail = nuts.tail
30local getwidth = nuts.getwidth
31local getboth = nuts.getboth
32local getindex = nuts.getindex
33local setlist = nuts.setlist
34local flushlist = nuts.flushlist
35local takebox = nuts.takebox
36local setbox = nuts.setbox
37local copynode = nuts.copynode
38local rangedimensions = nuts.rangedimensions
39local traverse_list = nuts.traversers.list
40
41
42
43
44local expandmacro = token.expandmacro
45
46local dimension_value <const> = tokens.values.dimension
47local integer_value <const> = tokens.values.integer
48
49local implement = interfaces.implement
50
51typesetters = typesetters or { }
52local typesetters = typesetters
53
54typesetters.localboxes = typesetters.localboxes or { }
55local localboxes = typesetters.localboxes
56
57local a_localboxesmark <const> = attributes.private("localboxesmark")
58
59local starttiming = statistics.starttiming
60local stoptiming = statistics.stoptiming
61
62do
63 local lb_found = nil
64 local lb_index = 0
65 local lb_linenumber = 0
66 local lb_linewidth = 0
67 local lb_localwidth = 0
68 local lb_progress = 0
69 local lb_leftoffset = 0
70 local lb_rightoffset = 0
71 local lb_leftskip = 0
72 local lb_rightskip = 0
73 local lb_lefthang = 0
74 local lb_righthang = 0
75 local lb_indent = 0
76 local lb_parfillleftskip = 0
77 local lb_parfillrightskip = 0
78 local lb_parinitleftskip = 0
79 local lb_parinitrightskip = 0
80 local lb_overshoot = 0
81
82 implement { name = "localboxindex", public = true, usage = "value", actions = function() return integer_value, lb_index end }
83 implement { name = "localboxlinenumber", public = true, usage = "value", actions = function() return integer_value, lb_linenumber end }
84 implement { name = "localboxlinewidth", public = true, usage = "value", actions = function() return dimension_value, lb_linewidth end }
85 implement { name = "localboxlocalwidth", public = true, usage = "value", actions = function() return dimension_value, lb_localwidth end }
86 implement { name = "localboxprogress", public = true, usage = "value", actions = function() return dimension_value, lb_progress end }
87 implement { name = "localboxleftoffset", public = true, usage = "value", actions = function() return dimension_value, lb_leftoffset end }
88 implement { name = "localboxrightoffset", public = true, usage = "value", actions = function() return dimension_value, lb_rightoffset end }
89 implement { name = "localboxleftskip", public = true, usage = "value", actions = function() return dimension_value, lb_leftskip end }
90 implement { name = "localboxrightskip", public = true, usage = "value", actions = function() return dimension_value, lb_rightskip end }
91 implement { name = "localboxlefthang", public = true, usage = "value", actions = function() return dimension_value, lb_lefthang end }
92 implement { name = "localboxrighthang", public = true, usage = "value", actions = function() return dimension_value, lb_righthang end }
93 implement { name = "localboxindent", public = true, usage = "value", actions = function() return dimension_value, lb_indent end }
94 implement { name = "localboxparfillleftskip", public = true, usage = "value", actions = function() return dimension_value, lb_parfillleftskip end }
95 implement { name = "localboxparfillrightskip", public = true, usage = "value", actions = function() return dimension_value, lb_parfillrightskip end }
96 implement { name = "localboxparinitleftskip", public = true, usage = "value", actions = function() return dimension_value, lb_parinitleftskip end }
97 implement { name = "localboxparinitrightskip", public = true, usage = "value", actions = function() return dimension_value, lb_parinitrightskip end }
98 implement { name = "localboxovershoot", public = true, usage = "value", actions = function() return dimension_value, lb_overshoot end }
99
100 local cache = table.setmetatableindex(function(t,k)
101 local v = { n = 0, m = 0 }
102 t[k] = v
103 return v
104 end)
105
106
107
108
109 implement {
110 name = "localboxmarkonce",
111 public = true,
112 arguments = "integer",
113 actions = function(attr)
114 local c = cache[attr]
115 local n = c.n
116
117
118
119
120
121
122
123 n = n + 1
124
125 c[n] = true
126 c.n = n
127 context(n)
128 end
129 }
130
131 local function action(current)
132 local list = getlist(current)
133 if list then
134 local attr = getattribute(list,a_localboxesmark) or 0
135 local cach = attr and cache[lb_index]
136 local once = cach and cach[attr]
137 if once == false then
138 setlist(current)
139 flushlist(list)
140 else
141 setlist(current)
142 local head = copynode(current)
143 setlist(head,list)
144 setbox("localboxcontentbox",head)
145 expandmacro("localboxcommand")
146 local box = takebox("localboxcontentbox")
147 setlist(current,box)
148 if once and cach[attr] == true then
149 cach[attr] = false
150 cach.m = cach.m + 1
151 end
152 end
153 end
154 end
155
156
157
158
159 local function processleftbox(box)
160 local list = getlist(box)
161 for current, id, subtype in traverse_list, list do
162 if subtype == local_box_code and getwidth(current) == 0 then
163 local index = getindex(current)
164 if index then
165 lb_found = current
166 lb_index = index
167 lb_progress = rangedimensions(box,list,current)
168 action(current)
169 end
170 end
171 end
172 end
173
174 local function processrightbox(box)
175 local list = getlist(box)
176 for current, id, subtype in traverse_list, list do
177 if subtype == local_box_code and getwidth(current) == 0 then
178 local index = getindex(current)
179 if index then
180 lb_found = current
181 lb_index = index
182 lb_progress = rangedimensions(box,list,current)
183 action(current)
184 end
185 end
186 end
187 end
188
189 local function processmiddlebox(box,line)
190 local list = getlist(box)
191 for current, id, subtype in traverse_list, list do
192 if subtype == local_box_code and getwidth(current) == 0 then
193 local index = getindex(current)
194 if index then
195 lb_found = current
196 lb_index = index
197 lb_progress = rangedimensions(line,getlist(line),box)
198 action(current)
199 end
200 end
201 end
202 end
203
204 local function processlocalboxes(line,leftbox,rightbox,middlebox,linenumber,leftskip,rightskip,lefthang,righthang,indent,parinitleftskip,parinitrightskip,parfillleftskip,parfillrightskip,overshoot)
205
206 lb_found = nil
207 lb_index = 0
208 lb_linenumber = linenumber
209 lb_progress = 0
210 lb_leftskip = leftskip
211 lb_rightskip = rightskip
212 lb_lefthang = lefthang
213 lb_righthang = righthang
214 lb_indent = indent
215 lb_parfillleftskip = parfillleftskip
216 lb_parfillrightskip = parfillrightskip
217 lb_parinitleftskip = parinitleftskip
218 lb_parinitrightskip = parinitrightskip
219 lb_overshoot = overshoot
220 lb_linewidth = getwidth(line)
221
222 lb_leftoffset = leftskip + lefthang + parfillleftskip + parinitleftskip + indent
223 lb_rightoffset = rightskip + righthang + parfillrightskip + parinitrightskip - overshoot
224
225 if leftbox then
226 lb_localwidth = getwidth(leftbox)
227 processleftbox(leftbox)
228 end
229 if middlebox then
230 lb_localwidth = getwidth(middlebox)
231 processmiddlebox(middlebox,line)
232 end
233 if rightbox then
234 lb_localwidth = getwidth(rightbox)
235 processrightbox(rightbox)
236 end
237 end
238
239 typesetters.localboxes.handler = processlocalboxes
240
241end
242
243local localboxactions = nodes.tasks.actions("localboxes")
244
245function builders.local_box_filter(...)
246 starttiming(builders)
247 localboxactions(...)
248 stoptiming(builders)
249end
250
251callbacks.register("local_box_filter", builders.local_box_filter, "process local boxes")
252 |