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