spac-ver.lua /size: 87 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
spac-ver
'
]
=
{
2
version
=
1
.
001
,
3
optimize
=
true
,
4
comment
=
"
companion to spac-ver.mkiv
"
,
5
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
6
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
7
license
=
"
see context related readme files
"
8
}
9 10
-- we also need to call the spacer for inserts!
11 12
-- somehow lists still don't always have proper prev nodes so i need to
13
-- check all of the luatex code some day .. maybe i should replece the
14
-- whole mvl handler by lua code .. why not
15 16
-- todo: use lua nodes with lua data (>0.79)
17
-- see ** can go when 0.79
18 19
-- needs to be redone, too many calls and tests now ... still within some
20
-- luatex limitations
21 22
-- this code dates from the beginning and is kind of experimental; it
23
-- will be optimized and improved soon .. it's way too complex now but
24
-- dates from less possibilities
25
--
26
-- the collapser will be redone with user nodes; also, we might get make
27
-- parskip into an attribute and appy it explicitly thereby getting rid
28
-- of automated injections; eventually i want to get rid of the currently
29
-- still needed tex -> lua -> tex > lua chain (needed because we can have
30
-- expandable settings at the tex end
31 32
-- todo: strip baselineskip around display math
33 34
local
next
,
type
,
tonumber
=
next
,
type
,
tonumber
35
local
gmatch
,
concat
=
string
.
gmatch
,
table
.
concat
36
local
ceil
,
floor
=
math
.
ceil
,
math
.
floor
37
local
lpegmatch
=
lpeg
.
match
38
local
unpack
=
unpack
or
table
.
unpack
39
local
allocate
=
utilities
.
storage
.
allocate
40
local
todimen
=
string
.
todimen
41
local
formatters
=
string
.
formatters
42
local
abs
=
math
.
abs
43 44
local
nodes
=
nodes
45
local
trackers
=
trackers
46
local
attributes
=
attributes
47
local
context
=
context
48
local
tex
=
tex
49 50
local
texlists
=
tex
.
lists
51
local
texget
=
tex
.
get
52
local
texgetcount
=
tex
.
getcount
53
local
texgetdimen
=
tex
.
getdimen
54
local
texset
=
tex
.
set
55
local
texsetdimen
=
tex
.
setdimen
56
local
texsetcount
=
tex
.
setcount
57
local
texnest
=
tex
.
nest
58
local
texgetbox
=
tex
.
getbox
59 60
local
buildpage
=
tex
.
triggerbuildpage
61 62
local
variables
=
interfaces
.
variables
63
local
implement
=
interfaces
.
implement
64 65
local
v_local
=
variables
[
"
local
"
]
66
local
v_global
=
variables
[
"
global
"
]
67
local
v_box
=
variables
.
box
68
----- v_page = variables.page -- reserved for future use
69
local
v_split
=
variables
.
split
70
local
v_min
=
variables
.
min
71
local
v_max
=
variables
.
max
72
local
v_none
=
variables
.
none
73
local
v_line
=
variables
.
line
74
local
v_noheight
=
variables
.
noheight
75
local
v_nodepth
=
variables
.
nodepth
76
local
v_line
=
variables
.
line
77
local
v_halfline
=
variables
.
halfline
78
local
v_line_m
=
"
-
"
.
.
v_line
79
local
v_halfline_m
=
"
-
"
.
.
v_halfline
80
local
v_first
=
variables
.
first
81
local
v_last
=
variables
.
last
82
local
v_top
=
variables
.
top
83
local
v_bottom
=
variables
.
bottom
84
local
v_minheight
=
variables
.
minheight
85
local
v_maxheight
=
variables
.
maxheight
86
local
v_mindepth
=
variables
.
mindepth
87
local
v_maxdepth
=
variables
.
maxdepth
88
local
v_offset
=
variables
.
offset
89
local
v_strut
=
variables
.
strut
90 91
local
v_hfraction
=
variables
.
hfraction
92
local
v_dfraction
=
variables
.
dfraction
93
local
v_bfraction
=
variables
.
bfraction
94
local
v_tlines
=
variables
.
tlines
95
local
v_blines
=
variables
.
blines
96 97
-- vertical space handler
98 99
local
trace_vbox_vspacing
=
false
trackers
.
register
(
"
vspacing.vbox
"
,
function
(
v
)
trace_vbox_vspacing
=
v
end
)
100
local
trace_page_vspacing
=
false
trackers
.
register
(
"
vspacing.page
"
,
function
(
v
)
trace_page_vspacing
=
v
end
)
101
local
trace_page_builder
=
false
trackers
.
register
(
"
builders.page
"
,
function
(
v
)
trace_page_builder
=
v
end
)
102
local
trace_collect_vspacing
=
false
trackers
.
register
(
"
vspacing.collect
"
,
function
(
v
)
trace_collect_vspacing
=
v
end
)
103
local
trace_vspacing
=
false
trackers
.
register
(
"
vspacing.spacing
"
,
function
(
v
)
trace_vspacing
=
v
end
)
104
local
trace_vsnapping
=
false
trackers
.
register
(
"
vspacing.snapping
"
,
function
(
v
)
trace_vsnapping
=
v
end
)
105
local
trace_specials
=
false
trackers
.
register
(
"
vspacing.specials
"
,
function
(
v
)
trace_specials
=
v
end
)
106 107
local
remove_math_skips
=
true
directives
.
register
(
"
vspacing.removemathskips
"
,
function
(
v
)
remnove_math_skips
=
v
end
)
108 109
local
report_vspacing
=
logs
.
reporter
(
"
vspacing
"
,
"
spacing
"
)
110
local
report_collapser
=
logs
.
reporter
(
"
vspacing
"
,
"
collapsing
"
)
111
local
report_snapper
=
logs
.
reporter
(
"
vspacing
"
,
"
snapping
"
)
112
local
report_specials
=
logs
.
reporter
(
"
vspacing
"
,
"
specials
"
)
113 114
local
a_skipcategory
=
attributes
.
private
(
'
skipcategory
'
)
115
local
a_skippenalty
=
attributes
.
private
(
'
skippenalty
'
)
116
local
a_skiporder
=
attributes
.
private
(
'
skiporder
'
)
117
local
a_snapmethod
=
attributes
.
private
(
'
snapmethod
'
)
118
local
a_snapvbox
=
attributes
.
private
(
'
snapvbox
'
)
119 120
local
nuts
=
nodes
.
nuts
121
local
tonut
=
nuts
.
tonut
122
local
tonode
=
nuts
.
tonode
123 124
local
getnext
=
nuts
.
getnext
125
local
setlink
=
nuts
.
setlink
126
local
getprev
=
nuts
.
getprev
127
local
getid
=
nuts
.
getid
128
local
getlist
=
nuts
.
getlist
129
local
setlist
=
nuts
.
setlist
130
local
getattr
=
nuts
.
getattr
131
local
setattr
=
nuts
.
setattr
132
local
getsubtype
=
nuts
.
getsubtype
133
local
getbox
=
nuts
.
getbox
134
local
getwhd
=
nuts
.
getwhd
135
local
setwhd
=
nuts
.
setwhd
136
local
getprop
=
nuts
.
getprop
137
local
setprop
=
nuts
.
setprop
138
local
getglue
=
nuts
.
getglue
139
local
setglue
=
nuts
.
setglue
140
local
getkern
=
nuts
.
getkern
141
local
getpenalty
=
nuts
.
getpenalty
142
local
setshift
=
nuts
.
setshift
143
local
setwidth
=
nuts
.
setwidth
144
local
getwidth
=
nuts
.
getwidth
145
local
setheight
=
nuts
.
setheight
146
local
getheight
=
nuts
.
getheight
147
local
setdepth
=
nuts
.
setdepth
148
local
getdepth
=
nuts
.
getdepth
149 150
local
find_node_tail
=
nuts
.
tail
151
local
flushnode
=
nuts
.
flushnode
152
local
insertnodeafter
=
nuts
.
insertafter
153
local
insertnodebefore
=
nuts
.
insertbefore
154
local
remove_node
=
nuts
.
remove
155
local
count_nodes
=
nuts
.
countall
156
local
hpack_node
=
nuts
.
hpack
157
local
vpack_node
=
nuts
.
vpack
158 159
local
startofpar
=
nuts
.
startofpar
160 161
local
nextnode
=
nuts
.
traversers
.
node
162
local
nexthlist
=
nuts
.
traversers
.
hlist
163 164
local
nodereference
=
nuts
.
reference
165 166
local
theprop
=
nuts
.
theprop
167 168
local
listtoutf
=
nodes
.
listtoutf
169
local
nodeidstostring
=
nodes
.
idstostring
170 171
local
nodepool
=
nuts
.
pool
172 173
local
new_penalty
=
nodepool
.
penalty
174
local
new_kern
=
nodepool
.
kern
175
----- new_glue = nodepool.glue
176
local
new_rule
=
nodepool
.
rule
177 178
local
nodecodes
=
nodes
.
nodecodes
179
local
gluecodes
=
nodes
.
gluecodes
180
----- penaltycodes = nodes.penaltycodes
181
----- listcodes = nodes.listcodes
182 183
local
penalty_code
=
nodecodes
.
penalty
184
local
kern_code
=
nodecodes
.
kern
185
local
glue_code
=
nodecodes
.
glue
186
local
hlist_code
=
nodecodes
.
hlist
187
local
vlist_code
=
nodecodes
.
vlist
188
local
rule_code
=
nodecodes
.
rule
189
local
par_code
=
nodecodes
.
par
190 191
local
userskip_code
=
gluecodes
.
userskip
192
local
lineskip_code
=
gluecodes
.
lineskip
193
local
baselineskip_code
=
gluecodes
.
baselineskip
194
local
parskip_code
=
gluecodes
.
parskip
195
local
topskip_code
=
gluecodes
.
topskip
196
local
splittopskip_code
=
gluecodes
.
splittopskip
197 198
local
linelist_code
=
nodes
.
listcodes
.
line
199 200
local
abovedisplayskip_code
=
gluecodes
.
abovedisplayskip
201
local
belowdisplayskip_code
=
gluecodes
.
belowdisplayskip
202
local
abovedisplayshortskip_code
=
gluecodes
.
abovedisplayshortskip
203
local
belowdisplayshortskip_code
=
gluecodes
.
belowdisplayshortskip
204 205
local
properties
=
nodes
.
properties
.
data
206 207
local
vspacing
=
builders
.
vspacing
or
{
}
208
builders
.
vspacing
=
vspacing
209 210
local
vspacingdata
=
vspacing
.
data
or
{
}
211
vspacing
.
data
=
vspacingdata
212 213
local
snapmethods
=
vspacingdata
.
snapmethods
or
{
}
214
vspacingdata
.
snapmethods
=
snapmethods
215 216
storage
.
register
(
"
builders/vspacing/data/snapmethods
"
,
snapmethods
,
"
builders.vspacing.data.snapmethods
"
)
217 218
do
219 220
local
default
=
{
221
[
v_maxheight
]
=
true
,
222
[
v_maxdepth
]
=
true
,
223
[
v_strut
]
=
true
,
224
[
v_hfraction
]
=
1
,
225
[
v_dfraction
]
=
1
,
226
[
v_bfraction
]
=
0
.
25
,
227
}
228 229
local
fractions
=
{
230
[
v_minheight
]
=
v_hfraction
,
[
v_maxheight
]
=
v_hfraction
,
231
[
v_mindepth
]
=
v_dfraction
,
[
v_maxdepth
]
=
v_dfraction
,
232
[
v_box
]
=
v_bfraction
,
233
[
v_top
]
=
v_tlines
,
[
v_bottom
]
=
v_blines
,
234
}
235 236
local
values
=
{
237
offset
=
"
offset
"
238
}
239 240
local
colonsplitter
=
lpeg
.
splitat
(
"
:
"
)
241 242
local
function
listtohash
(
str
)
243
local
t
=
{
}
244
for
s
in
gmatch
(
str
,
"
[^, ]+
"
)
do
245
local
key
,
detail
=
lpegmatch
(
colonsplitter
,
s
)
246
local
v
=
variables
[
key
]
247
if
v
then
248
t
[
v
]
=
true
249
if
detail
then
250
local
k
=
fractions
[
key
]
251
if
k
then
252
detail
=
tonumber
(
"
0
"
.
.
detail
)
253
if
detail
then
254
t
[
k
]
=
detail
255
end
256
else
257
k
=
values
[
key
]
258
if
k
then
259
detail
=
todimen
(
detail
)
260
if
detail
then
261
t
[
k
]
=
detail
262
end
263
end
264
end
265
end
266
else
267
detail
=
tonumber
(
"
0
"
.
.
key
)
268
if
detail
then
269
t
[
v_hfraction
]
=
detail
270
t
[
v_dfraction
]
=
detail
271
end
272
end
273
end
274
if
next
(
t
)
then
275
t
[
v_hfraction
]
=
t
[
v_hfraction
]
or
1
276
t
[
v_dfraction
]
=
t
[
v_dfraction
]
or
1
277
return
t
278
else
279
return
default
280
end
281
end
282 283
function
vspacing
.
definesnapmethod
(
name
,
method
)
284
local
n
=
#
snapmethods
+
1
285
local
t
=
listtohash
(
method
)
286
snapmethods
[
n
]
=
t
287
t
.
name
=
name
-- not interfaced
288
t
.
specification
=
method
-- not interfaced
289
context
(
n
)
290
end
291 292
end
293 294
local
function
validvbox
(
parentid
,
list
)
295
if
parentid
=
=
hlist_code
then
296
local
id
=
getid
(
list
)
297
if
id
=
=
par_code
and
startofpar
(
list
)
then
298
list
=
getnext
(
list
)
299
if
not
next
then
300
return
nil
301
end
302
end
303
local
done
=
nil
304
for
n
,
id
in
nextnode
,
list
do
305
if
id
=
=
vlist_code
or
id
=
=
hlist_code
then
306
if
done
then
307
return
nil
308
else
309
done
=
n
310
end
311
elseif
id
=
=
glue_code
or
id
=
=
penalty_code
then
312
-- go on
313
else
314
return
nil
-- whatever
315
end
316
end
317
if
done
then
318
local
id
=
getid
(
done
)
319
if
id
=
=
hlist_code
then
320
return
validvbox
(
id
,
getlist
(
done
)
)
321
end
322
end
323
return
done
-- only one vbox
324
end
325
end
326 327
-- we can use a property
328 329
local
function
already_done
(
parentid
,
list
,
a_snapmethod
)
-- todo: done when only boxes and all snapped
330
-- problem: any snapped vbox ends up in a line
331
if
list
and
parentid
=
=
hlist_code
then
332
local
id
=
getid
(
list
)
333
if
id
=
=
par_code
and
startofpar
(
list
)
then
334
list
=
getnext
(
list
)
335
if
not
list
then
336
return
false
337
end
338
end
339
for
n
,
id
in
nextnode
,
list
do
340
if
id
=
=
hlist_code
or
id
=
=
vlist_code
then
341
-- local a = getattr(n,a_snapmethod)
342
-- if not a then
343
-- -- return true -- not snapped at all
344
-- elseif a == 0 then
345
-- return true -- already snapped
346
-- end
347
local
p
=
getprop
(
n
,
"
snapper
"
)
348
if
p
then
349
return
p
350
end
351
elseif
id
=
=
glue_code
or
id
=
=
penalty_code
then
-- or id == kern_code then
352
-- go on
353
else
354
return
false
-- whatever
355
end
356
end
357
end
358
return
false
359
end
360 361
-- quite tricky: ceil(-something) => -0
362 363
local
function
ceiled
(
n
)
364
if
n
<
0
or
n
<
0
.
01
then
365
return
0
366
else
367
return
ceil
(
n
)
368
end
369
end
370 371
local
function
floored
(
n
)
372
if
n
<
0
or
n
<
0
.
01
then
373
return
0
374
else
375
return
floor
(
n
)
376
end
377
end
378 379
-- check variables.none etc
380 381
local
function
fixedprofile
(
current
)
382
local
profiling
=
builders
.
profiling
383
return
profiling
and
profiling
.
fixedprofile
(
current
)
384
end
385 386
-- local function onlyoneentry(t)
387
-- local n = 1
388
-- for k, v in next, t do
389
-- if n > 1 then
390
-- return false
391
-- end
392
-- n = n + 1
393
-- end
394
-- return true
395
-- end
396 397
local
function
snap_hlist
(
where
,
current
,
method
,
height
,
depth
)
-- method[v_strut] is default
398
if
fixedprofile
(
current
)
then
399
return
400
end
401
local
list
=
getlist
(
current
)
402
local
t
=
trace_vsnapping
and
{
}
403
if
t
then
404
t
[
#
t
+
1
]
=
formatters
[
"
list content: %s
"
]
(
listtoutf
(
list
)
)
405
t
[
#
t
+
1
]
=
formatters
[
"
snap method: %s
"
]
(
method
.
name
)
-- not interfaced
406
t
[
#
t
+
1
]
=
formatters
[
"
specification: %s
"
]
(
method
.
specification
)
-- not interfaced
407
end
408
local
snapht
,
snapdp
409
if
method
[
v_local
]
then
410
-- snapping is done immediately here
411
snapht
=
texgetdimen
(
"
bodyfontstrutheight
"
)
412
snapdp
=
texgetdimen
(
"
bodyfontstrutdepth
"
)
413
if
t
then
414
t
[
#
t
+
1
]
=
formatters
[
"
local: snapht %p snapdp %p
"
]
(
snapht
,
snapdp
)
415
end
416
elseif
method
[
v_global
]
then
417
snapht
=
texgetdimen
(
"
globalbodyfontstrutheight
"
)
418
snapdp
=
texgetdimen
(
"
globalbodyfontstrutdepth
"
)
419
if
t
then
420
t
[
#
t
+
1
]
=
formatters
[
"
global: snapht %p snapdp %p
"
]
(
snapht
,
snapdp
)
421
end
422
else
423
-- maybe autolocal
424
-- snapping might happen later in the otr
425
snapht
=
texgetdimen
(
"
globalbodyfontstrutheight
"
)
426
snapdp
=
texgetdimen
(
"
globalbodyfontstrutdepth
"
)
427
local
lsnapht
=
texgetdimen
(
"
bodyfontstrutheight
"
)
428
local
lsnapdp
=
texgetdimen
(
"
bodyfontstrutdepth
"
)
429
if
snapht
~
=
lsnapht
and
snapdp
~
=
lsnapdp
then
430
snapht
,
snapdp
=
lsnapht
,
lsnapdp
431
end
432
if
t
then
433
t
[
#
t
+
1
]
=
formatters
[
"
auto: snapht %p snapdp %p
"
]
(
snapht
,
snapdp
)
434
end
435
end
436 437
local
wd
,
ht
,
dp
=
getwhd
(
current
)
438 439
local
h
=
(
method
[
v_noheight
]
and
0
)
or
height
or
ht
440
local
d
=
(
method
[
v_nodepth
]
and
0
)
or
depth
or
dp
441
local
hr
=
method
[
v_hfraction
]
or
1
442
local
dr
=
method
[
v_dfraction
]
or
1
443
local
br
=
method
[
v_bfraction
]
or
0
444
local
ch
=
h
445
local
cd
=
d
446
local
tlines
=
method
[
v_tlines
]
or
1
447
local
blines
=
method
[
v_blines
]
or
1
448
local
done
=
false
449
local
plusht
=
snapht
450
local
plusdp
=
snapdp
451
local
snaphtdp
=
snapht
+
snapdp
452
local
extra
=
0
453 454
if
t
then
455
t
[
#
t
+
1
]
=
formatters
[
"
hlist: wd %p ht %p (used %p) dp %p (used %p)
"
]
(
wd
,
ht
,
h
,
dp
,
d
)
456
t
[
#
t
+
1
]
=
formatters
[
"
fractions: hfraction %s dfraction %s bfraction %s tlines %s blines %s
"
]
(
hr
,
dr
,
br
,
tlines
,
blines
)
457
end
458 459
if
method
[
v_box
]
then
460
local
br
=
1
-
br
461
if
br
<
0
then
462
br
=
0
463
elseif
br
>
1
then
464
br
=
1
465
end
466
local
n
=
ceiled
(
(
h
+
d
-
br
*
snapht
-
br
*
snapdp
)
/
snaphtdp
)
467
local
x
=
n
*
snaphtdp
-
h
-
d
468
plusht
=
h
+
x
/
2
469
plusdp
=
d
+
x
/
2
470
if
t
then
471
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_box
,
plusht
,
plusdp
)
472
end
473
elseif
method
[
v_max
]
then
474
local
n
=
ceiled
(
(
h
+
d
)
/
snaphtdp
)
475
local
x
=
n
*
snaphtdp
-
h
-
d
476
plusht
=
h
+
x
/
2
477
plusdp
=
d
+
x
/
2
478
if
t
then
479
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_max
,
plusht
,
plusdp
)
480
end
481
elseif
method
[
v_min
]
then
482
-- we catch a lone min
483
if
method
.
specification
~
=
v_min
then
484
local
n
=
floored
(
(
h
+
d
)
/
snaphtdp
)
485
local
x
=
n
*
snaphtdp
-
h
-
d
486
plusht
=
h
+
x
/
2
487
plusdp
=
d
+
x
/
2
488
if
plusht
<
0
then
489
plusht
=
0
490
end
491
if
plusdp
<
0
then
492
plusdp
=
0
493
end
494
end
495
if
t
then
496
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_min
,
plusht
,
plusdp
)
497
end
498
elseif
method
[
v_none
]
then
499
plusht
,
plusdp
=
0
,
0
500
if
t
then
501
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_none
,
0
,
0
)
502
end
503
end
504
-- for now, we actually need to tag a box and then check at several points if something ended up
505
-- at the top of a page
506
if
method
[
v_halfline
]
then
-- extra halfline
507
extra
=
snaphtdp
/
2
508
plusht
=
plusht
+
extra
509
plusdp
=
plusdp
+
extra
510
if
t
then
511
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_halfline
,
plusht
,
plusdp
)
512
end
513
end
514
if
method
[
v_line
]
then
-- extra line
515
extra
=
snaphtdp
516
plusht
=
plusht
+
extra
517
plusdp
=
plusdp
+
extra
518
if
t
then
519
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_line
,
plusht
,
plusdp
)
520
end
521
end
522
if
method
[
v_halfline_m
]
then
-- extra halfline
523
extra
=
-
snaphtdp
/
2
524
plusht
=
plusht
+
extra
525
plusdp
=
plusdp
+
extra
526
if
t
then
527
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_halfline_m
,
plusht
,
plusdp
)
528
end
529
end
530
if
method
[
v_line_m
]
then
-- extra line
531
extra
=
-
snaphtdp
532
plusht
=
plusht
+
extra
533
plusdp
=
plusdp
+
extra
534
if
t
then
535
t
[
#
t
+
1
]
=
formatters
[
"
%s: plusht %p plusdp %p
"
]
(
v_line_m
,
plusht
,
plusdp
)
536
end
537
end
538
if
method
[
v_first
]
then
539
local
thebox
=
current
540
local
id
=
getid
(
thebox
)
541
if
id
=
=
hlist_code
then
542
thebox
=
validvbox
(
id
,
getlist
(
thebox
)
)
543
id
=
thebox
and
getid
(
thebox
)
544
end
545
if
thebox
and
id
=
=
vlist_code
then
546
local
list
=
getlist
(
thebox
)
547
local
lw
,
lh
,
ld
548
for
n
in
nexthlist
,
list
do
549
lw
,
lh
,
ld
=
getwhd
(
n
)
550
break
551
end
552
if
lh
then
553
local
wd
,
ht
,
dp
=
getwhd
(
thebox
)
554
if
t
then
555
t
[
#
t
+
1
]
=
formatters
[
"
first line: height %p depth %p
"
]
(
lh
,
ld
)
556
t
[
#
t
+
1
]
=
formatters
[
"
dimensions: height %p depth %p
"
]
(
ht
,
dp
)
557
end
558
local
delta
=
h
-
lh
559
ch
,
cd
=
lh
,
delta
+
d
560
h
,
d
=
ch
,
cd
561
local
shifted
=
hpack_node
(
getlist
(
current
)
)
562
setshift
(
shifted
,
delta
)
563
setlist
(
current
,
shifted
)
564
done
=
true
565
if
t
then
566
t
[
#
t
+
1
]
=
formatters
[
"
first: height %p depth %p shift %p
"
]
(
ch
,
cd
,
delta
)
567
end
568
elseif
t
then
569
t
[
#
t
+
1
]
=
"
first: not done, no content
"
570
end
571
elseif
t
then
572
t
[
#
t
+
1
]
=
"
first: not done, no vbox
"
573
end
574
elseif
method
[
v_last
]
then
575
local
thebox
=
current
576
local
id
=
getid
(
thebox
)
577
if
id
=
=
hlist_code
then
578
thebox
=
validvbox
(
id
,
getlist
(
thebox
)
)
579
id
=
thebox
and
getid
(
thebox
)
580
end
581
if
thebox
and
id
=
=
vlist_code
then
582
local
list
=
getlist
(
thebox
)
583
local
lw
,
lh
,
ld
584
for
n
in
nexthlist
,
list
do
585
lw
,
lh
,
ld
=
getwhd
(
n
)
586
end
587
if
lh
then
588
local
wd
,
ht
,
dp
=
getwhd
(
thebox
)
589
if
t
then
590
t
[
#
t
+
1
]
=
formatters
[
"
last line: height %p depth %p
"
]
(
lh
,
ld
)
591
t
[
#
t
+
1
]
=
formatters
[
"
dimensions: height %p depth %p
"
]
(
ht
,
dp
)
592
end
593
local
delta
=
d
-
ld
594
cd
,
ch
=
ld
,
delta
+
h
595
h
,
d
=
ch
,
cd
596
local
shifted
=
hpack_node
(
getlist
(
current
)
)
597
setshift
(
shifted
,
delta
)
598
setlist
(
current
,
shifted
)
599
done
=
true
600
if
t
then
601
t
[
#
t
+
1
]
=
formatters
[
"
last: height %p depth %p shift %p
"
]
(
ch
,
cd
,
delta
)
602
end
603
elseif
t
then
604
t
[
#
t
+
1
]
=
"
last: not done, no content
"
605
end
606
elseif
t
then
607
t
[
#
t
+
1
]
=
"
last: not done, no vbox
"
608
end
609
end
610
if
method
[
v_minheight
]
then
611
ch
=
floored
(
(
h
-
hr
*
snapht
)
/
snaphtdp
)
*
snaphtdp
+
plusht
612
if
t
then
613
t
[
#
t
+
1
]
=
formatters
[
"
minheight: %p
"
]
(
ch
)
614
end
615
elseif
method
[
v_maxheight
]
then
616
ch
=
ceiled
(
(
h
-
hr
*
snapht
)
/
snaphtdp
)
*
snaphtdp
+
plusht
617
if
t
then
618
t
[
#
t
+
1
]
=
formatters
[
"
maxheight: %p
"
]
(
ch
)
619
end
620
else
621
ch
=
plusht
622
if
t
then
623
t
[
#
t
+
1
]
=
formatters
[
"
set height: %p
"
]
(
ch
)
624
end
625
end
626
if
method
[
v_mindepth
]
then
627
cd
=
floored
(
(
d
-
dr
*
snapdp
)
/
snaphtdp
)
*
snaphtdp
+
plusdp
628
if
t
then
629
t
[
#
t
+
1
]
=
formatters
[
"
mindepth: %p
"
]
(
cd
)
630
end
631
elseif
method
[
v_maxdepth
]
then
632
cd
=
ceiled
(
(
d
-
dr
*
snapdp
)
/
snaphtdp
)
*
snaphtdp
+
plusdp
633
if
t
then
634
t
[
#
t
+
1
]
=
formatters
[
"
maxdepth: %p
"
]
(
cd
)
635
end
636
else
637
cd
=
plusdp
638
if
t
then
639
t
[
#
t
+
1
]
=
formatters
[
"
set depth: %p
"
]
(
cd
)
640
end
641
end
642
if
method
[
v_top
]
then
643
ch
=
ch
+
tlines
*
snaphtdp
644
if
t
then
645
t
[
#
t
+
1
]
=
formatters
[
"
top height: %p
"
]
(
ch
)
646
end
647
end
648
if
method
[
v_bottom
]
then
649
cd
=
cd
+
blines
*
snaphtdp
650
if
t
then
651
t
[
#
t
+
1
]
=
formatters
[
"
bottom depth: %p
"
]
(
cd
)
652
end
653
end
654
local
offset
=
method
[
v_offset
]
655
if
offset
then
656
-- we need to set the attr
657
if
t
then
658
local
wd
,
ht
,
dp
=
getwhd
(
current
)
659
t
[
#
t
+
1
]
=
formatters
[
"
before offset: %p (width %p height %p depth %p)
"
]
(
offset
,
wd
,
ht
,
dp
)
660
end
661
local
shifted
=
hpack_node
(
getlist
(
current
)
)
662
setshift
(
shifted
,
offset
)
663
setlist
(
current
,
shifted
)
664
if
t
then
665
local
wd
,
ht
,
dp
=
getwhd
(
current
)
666
t
[
#
t
+
1
]
=
formatters
[
"
after offset: %p (width %p height %p depth %p)
"
]
(
offset
,
wd
,
ht
,
dp
)
667
end
668
setattr
(
shifted
,
a_snapmethod
,
0
)
669
setattr
(
current
,
a_snapmethod
,
0
)
670
end
671
if
not
height
then
672
setheight
(
current
,
ch
)
673
if
t
then
674
t
[
#
t
+
1
]
=
formatters
[
"
forced height: %p
"
]
(
ch
)
675
end
676
end
677
if
not
depth
then
678
setdepth
(
current
,
cd
)
679
if
t
then
680
t
[
#
t
+
1
]
=
formatters
[
"
forced depth: %p
"
]
(
cd
)
681
end
682
end
683
local
lines
=
(
ch
+
cd
)
/
snaphtdp
684
if
t
then
685
local
original
=
(
h
+
d
)
/
snaphtdp
686
local
whatever
=
(
ch
+
cd
)
/
(
texgetdimen
(
"
globalbodyfontstrutheight
"
)
+
texgetdimen
(
"
globalbodyfontstrutdepth
"
)
)
687
t
[
#
t
+
1
]
=
formatters
[
"
final lines : %p -> %p (%p)
"
]
(
original
,
lines
,
whatever
)
688
t
[
#
t
+
1
]
=
formatters
[
"
final height: %p -> %p
"
]
(
h
,
ch
)
689
t
[
#
t
+
1
]
=
formatters
[
"
final depth : %p -> %p
"
]
(
d
,
cd
)
690
end
691
-- todo:
692
--
693
-- if h < 0 or d < 0 then
694
-- h = 0
695
-- d = 0
696
-- end
697
if
t
then
698
report_snapper
(
"
trace: %s type %s\n\t%\n\tt
"
,
where
,
nodecodes
[
getid
(
current
)
]
,
t
)
699
end
700
if
not
method
[
v_split
]
then
701
-- so extra will not be compensated at the top of a page
702
extra
=
0
703
end
704
return
h
,
d
,
ch
,
cd
,
lines
,
extra
705
end
706 707
local
function
snap_topskip
(
current
,
method
)
708
local
w
=
getwidth
(
current
)
709
setwidth
(
current
,
0
)
710
return
w
,
0
711
end
712 713
local
categories
=
{
[
0
]
=
714
"
discard
"
,
715
"
largest
"
,
716
"
force
"
,
717
"
penalty
"
,
718
"
add
"
,
719
"
disable
"
,
720
"
nowhite
"
,
721
"
goback
"
,
722
"
packed
"
,
723
"
overlay
"
,
724
"
enable
"
,
725
"
notopskip
"
,
726
}
727 728
categories
=
allocate
(
table
.
swapped
(
categories
,
categories
)
)
729
vspacing
.
categories
=
categories
730 731
function
vspacing
.
tocategories
(
str
)
732
local
t
=
{
}
733
for
s
in
gmatch
(
str
,
"
[^, ]
"
)
do
-- use lpeg instead
734
local
n
=
tonumber
(
s
)
735
if
n
then
736
t
[
categories
[
n
]
]
=
true
737
else
738
t
[
b
]
=
true
739
end
740
end
741
return
t
742
end
743 744
function
vspacing
.
tocategory
(
str
)
-- can be optimized
745
if
type
(
str
)
=
=
"
string
"
then
746
return
set
.
tonumber
(
vspacing
.
tocategories
(
str
)
)
747
else
748
return
set
.
tonumber
(
{
[
categories
[
str
]
]
=
true
}
)
749
end
750
end
751 752
vspacingdata
.
map
=
vspacingdata
.
map
or
{
}
-- allocate ?
753
vspacingdata
.
skip
=
vspacingdata
.
skip
or
{
}
-- allocate ?
754 755
storage
.
register
(
"
builders/vspacing/data/map
"
,
vspacingdata
.
map
,
"
builders.vspacing.data.map
"
)
756
storage
.
register
(
"
builders/vspacing/data/skip
"
,
vspacingdata
.
skip
,
"
builders.vspacing.data.skip
"
)
757 758
do
-- todo: interface.variables and properties
759 760
local
P
,
C
,
R
,
S
,
Cc
,
Cs
=
lpeg
.
P
,
lpeg
.
C
,
lpeg
.
R
,
lpeg
.
S
,
lpeg
.
Cc
,
lpeg
.
Cs
761 762
vspacing
.
fixed
=
false
763 764
local
map
=
vspacingdata
.
map
765
local
skip
=
vspacingdata
.
skip
766 767
local
sign
=
S
(
"
+-
"
)
^
0
768
local
multiplier
=
C
(
sign
*
R
(
"
09
"
)
^
1
)
*
P
(
"
*
"
)
769
local
singlefier
=
Cs
(
sign
*
Cc
(
1
)
)
770
local
separator
=
S
(
"
,
"
)
771
local
category
=
P
(
"
:
"
)
*
C
(
(
1
-
separator
)
^
1
)
772
local
keyword
=
C
(
(
1
-
category
-
separator
)
^
1
)
773
local
splitter
=
(
multiplier
+
Cc
(
1
)
)
*
keyword
*
(
category
+
Cc
(
false
)
)
774 775
local
k_fixed
=
variables
.
fixed
776
local
k_flexible
=
variables
.
flexible
777
local
k_category
=
"
category
"
778
local
k_penalty
=
"
penalty
"
779
local
k_order
=
"
order
"
780 781
-- This will change: just node.write and we can store the values in skips which
782
-- then obeys grouping .. but .. we miss the amounts then as they live at the tex
783
-- end so we then also need to change that bit ... it would be interesting if we
784
-- could store in properties
785 786
local
ctx_fixedblankskip
=
context
.
fixedblankskip
787
local
ctx_flexibleblankskip
=
context
.
flexibleblankskip
788
local
ctx_setblankcategory
=
context
.
setblankcategory
789
local
ctx_setblankorder
=
context
.
setblankorder
790
local
ctx_setblankpenalty
=
context
.
setblankpenalty
791
----- ctx_setblankhandling = context.setblankhandling
792
local
ctx_flushblankhandling
=
context
.
flushblankhandling
793
local
ctx_addpredefinedblankskip
=
context
.
addpredefinedblankskip
794
local
ctx_addaskedblankskip
=
context
.
addaskedblankskip
795
local
ctx_setblankpacked
=
context
.
setblankpacked
796 797
local
ctx_pushlogger
=
context
.
pushlogger
798
local
ctx_startblankhandling
=
context
.
startblankhandling
799
local
ctx_stopblankhandling
=
context
.
stopblankhandling
800
local
ctx_poplogger
=
context
.
poplogger
801 802
local
pattern
=
nil
803 804
local
packed
=
categories
.
packed
805 806
local
function
handler
(
amount
,
keyword
,
detail
)
807
if
not
keyword
then
808
report_vspacing
(
"
unknown directive %a
"
,
s
)
809
else
810
local
mk
=
map
[
keyword
]
811
if
mk
then
812
lpegmatch
(
pattern
,
mk
)
813
elseif
keyword
=
=
k_fixed
then
814
ctx_fixedblankskip
(
)
815
elseif
keyword
=
=
k_flexible
then
816
ctx_flexibleblankskip
(
)
817
elseif
keyword
=
=
k_category
then
818
local
category
=
tonumber
(
detail
)
819
if
category
=
=
packed
then
820
ctx_setblankpacked
(
)
821
elseif
category
then
822
ctx_setblankcategory
(
category
)
823
ctx_flushblankhandling
(
)
824
end
825
elseif
keyword
=
=
k_order
and
detail
then
826
local
order
=
tonumber
(
detail
)
827
if
order
then
828
ctx_setblankorder
(
order
)
829
end
830
elseif
keyword
=
=
k_penalty
and
detail
then
831
local
penalty
=
tonumber
(
detail
)
832
if
penalty
then
833
ctx_setblankpenalty
(
penalty
)
834
end
835
else
836
amount
=
tonumber
(
amount
)
or
1
837
local
sk
=
skip
[
keyword
]
838
if
sk
then
839
ctx_addpredefinedblankskip
(
amount
,
keyword
)
840
else
-- no check
841
ctx_addaskedblankskip
(
amount
,
keyword
)
842
end
843
end
844
end
845
end
846 847
local
splitter
=
(
(
multiplier
+
singlefier
)
*
keyword
*
(
category
+
Cc
(
false
)
)
)
/
handler
848
pattern
=
(
splitter
+
separator
^
1
)
^
0
849 850
function
vspacing
.
analyze
(
str
)
851
if
trace_vspacing
then
852
ctx_pushlogger
(
report_vspacing
)
853
ctx_startblankhandling
(
)
854
lpegmatch
(
pattern
,
str
)
855
ctx_stopblankhandling
(
)
856
ctx_poplogger
(
)
857
else
858
ctx_startblankhandling
(
)
859
lpegmatch
(
pattern
,
str
)
860
ctx_stopblankhandling
(
)
861
end
862
end
863 864
--
865 866
function
vspacing
.
setmap
(
from
,
to
)
867
map
[
from
]
=
to
868
end
869 870
function
vspacing
.
setskip
(
key
,
value
,
grid
)
871
if
value
~
=
"
"
then
872
if
grid
=
=
"
"
then
grid
=
value
end
873
skip
[
key
]
=
{
value
,
grid
}
874
end
875
end
876 877
end
878 879
-- implementation
880 881
local
trace_list
,
tracing_info
,
before
,
after
=
{
}
,
false
,
"
"
,
"
"
882 883
local
function
nodes_to_string
(
head
)
884
local
current
=
head
885
local
t
=
{
}
886
while
current
do
887
local
id
=
getid
(
current
)
888
local
ty
=
nodecodes
[
id
]
889
if
id
=
=
penalty_code
then
890
t
[
#
t
+
1
]
=
formatters
[
"
%s:%s
"
]
(
ty
,
getpenalty
(
current
)
)
891
elseif
id
=
=
glue_code
then
892
t
[
#
t
+
1
]
=
formatters
[
"
%s:%s:%p
"
]
(
ty
,
gluecodes
[
getsubtype
(
current
)
]
,
getwidth
(
current
)
)
893
elseif
id
=
=
kern_code
then
894
t
[
#
t
+
1
]
=
formatters
[
"
%s:%p
"
]
(
ty
,
getkern
(
current
)
)
895
else
896
t
[
#
t
+
1
]
=
ty
897
end
898
current
=
getnext
(
current
)
899
end
900
return
concat
(
t
,
"
+
"
)
901
end
902 903
local
function
reset_tracing
(
head
)
904
trace_list
,
tracing_info
,
before
,
after
=
{
}
,
false
,
nodes_to_string
(
head
)
,
"
"
905
end
906 907
local
function
trace_skip
(
str
,
sc
,
so
,
sp
,
data
)
908
trace_list
[
#
trace_list
+
1
]
=
{
"
skip
"
,
formatters
[
"
%s | %p | category %s | order %s | penalty %s
"
]
(
str
,
getwidth
(
data
)
,
sc
or
"
-
"
,
so
or
"
-
"
,
sp
or
"
-
"
)
}
909
tracing_info
=
true
910
end
911 912
local
function
trace_natural
(
str
,
data
)
913
trace_list
[
#
trace_list
+
1
]
=
{
"
skip
"
,
formatters
[
"
%s | %p
"
]
(
str
,
getwidth
(
data
)
)
}
914
tracing_info
=
true
915
end
916 917
local
function
trace_info
(
message
,
where
,
what
)
918
trace_list
[
#
trace_list
+
1
]
=
{
"
info
"
,
formatters
[
"
%s: %s/%s
"
]
(
message
,
where
,
what
)
}
919
end
920 921
local
function
trace_node
(
what
)
922
local
nt
=
nodecodes
[
getid
(
what
)
]
923
local
tl
=
trace_list
[
#
trace_list
]
924
if
tl
and
tl
[
1
]
=
=
"
node
"
then
925
trace_list
[
#
trace_list
]
=
{
"
node
"
,
formatters
[
"
%s + %s
"
]
(
tl
[
2
]
,
nt
)
}
926
else
927
trace_list
[
#
trace_list
+
1
]
=
{
"
node
"
,
nt
}
928
end
929
end
930 931
local
function
trace_done
(
str
,
data
)
932
if
getid
(
data
)
=
=
penalty_code
then
933
trace_list
[
#
trace_list
+
1
]
=
{
"
penalty
"
,
formatters
[
"
%s | %s
"
]
(
str
,
getpenalty
(
data
)
)
}
934
else
935
trace_list
[
#
trace_list
+
1
]
=
{
"
glue
"
,
formatters
[
"
%s | %p
"
]
(
str
,
getwidth
(
data
)
)
}
936
end
937
tracing_info
=
true
938
end
939 940
local
function
show_tracing
(
head
)
941
if
tracing_info
then
942
after
=
nodes_to_string
(
head
)
943
for
i
=
1
,
#
trace_list
do
944
local
tag
,
text
=
unpack
(
trace_list
[
i
]
)
945
if
tag
=
=
"
info
"
then
946
report_collapser
(
text
)
947
else
948
report_collapser
(
"
%s: %s
"
,
tag
,
text
)
949
end
950
end
951
report_collapser
(
"
before: %s
"
,
before
)
952
report_collapser
(
"
after : %s
"
,
after
)
953
end
954
end
955 956
-- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display
957 958
function
vspacing
.
snapbox
(
n
,
how
)
959
local
sv
=
snapmethods
[
how
]
960
if
sv
then
961
local
box
=
getbox
(
n
)
962
local
list
=
getlist
(
box
)
963
if
list
then
964
local
s
=
getattr
(
list
,
a_snapmethod
)
965
if
s
=
=
0
then
966
if
trace_vsnapping
then
967
-- report_snapper("box list not snapped, already done")
968
end
969
else
970
local
wd
,
ht
,
dp
=
getwhd
(
box
)
971
if
false
then
-- todo: already_done
972
-- assume that the box is already snapped
973
if
trace_vsnapping
then
974
report_snapper
(
"
box list already snapped at (%p,%p): %s
"
,
975
ht
,
dp
,
listtoutf
(
list
)
)
976
end
977
else
978
local
h
,
d
,
ch
,
cd
,
lines
,
extra
=
snap_hlist
(
"
box
"
,
box
,
sv
,
ht
,
dp
)
979
setprop
(
box
,
"
snapper
"
,
{
980
ht
=
h
,
981
dp
=
d
,
982
ch
=
ch
,
983
cd
=
cd
,
984
extra
=
extra
,
985
current
=
current
,
986
}
)
987
setwhd
(
box
,
wd
,
ch
,
cd
)
988
if
trace_vsnapping
then
989
report_snapper
(
"
box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s
"
,
990
h
,
d
,
ch
,
cd
,
sv
.
name
,
sv
.
specification
,
"
direct
"
,
lines
,
listtoutf
(
list
)
)
991
end
992
setattr
(
box
,
a_snapmethod
,
0
)
--
993
setattr
(
list
,
a_snapmethod
,
0
)
-- yes or no
994
end
995
end
996
end
997
end
998
end
999 1000
-- I need to figure out how to deal with the prevdepth that crosses pages. In fact,
1001
-- prevdepth is often quite interfering (even over a next paragraph) so I need to
1002
-- figure out a trick. Maybe use something other than a rule. If we visualize we'll
1003
-- see the baselineskip in action:
1004
--
1005
-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page
1006
-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page
1007
-- \blank[force,5*big] { \baselineskip5cm xxxxxxxxx \par } \page
1008 1009
-- We can register and copy the rule instead.
1010 1011
do
1012 1013
local
w
,
h
,
d
=
0
,
0
,
0
1014
----- w, h, d = 100*65536, 65536, 65536
1015 1016
local
function
forced_skip
(
head
,
current
,
width
,
where
,
trace
)
-- looks old ... we have other tricks now
1017
if
head
=
=
current
then
1018
if
getsubtype
(
head
)
=
=
baselineskip_code
then
1019
width
=
width
-
getwidth
(
head
)
1020
end
1021
end
1022
if
width
=
=
0
then
1023
-- do nothing
1024
elseif
where
=
=
"
after
"
then
1025
head
,
current
=
insertnodeafter
(
head
,
current
,
new_rule
(
w
,
h
,
d
)
)
1026
head
,
current
=
insertnodeafter
(
head
,
current
,
new_kern
(
width
)
)
1027
head
,
current
=
insertnodeafter
(
head
,
current
,
new_rule
(
w
,
h
,
d
)
)
1028
else
1029
local
c
=
current
1030
head
,
current
=
insertnodebefore
(
head
,
current
,
new_rule
(
w
,
h
,
d
)
)
1031
head
,
current
=
insertnodebefore
(
head
,
current
,
new_kern
(
width
)
)
1032
head
,
current
=
insertnodebefore
(
head
,
current
,
new_rule
(
w
,
h
,
d
)
)
1033
current
=
c
1034
end
1035
if
trace
then
1036
report_vspacing
(
"
inserting forced skip of %p
"
,
width
)
1037
end
1038
return
head
,
current
1039
end
1040 1041
-- penalty only works well when before skip
1042 1043
local
discard
=
categories
.
discard
1044
local
largest
=
categories
.
largest
1045
local
force
=
categories
.
force
1046
local
penalty
=
categories
.
penalty
1047
local
add
=
categories
.
add
1048
local
disable
=
categories
.
disable
1049
local
nowhite
=
categories
.
nowhite
1050
local
goback
=
categories
.
goback
1051
local
packed
=
categories
.
packed
1052
local
overlay
=
categories
.
overlay
1053
local
enable
=
categories
.
enable
1054
local
notopskip
=
categories
.
notopskip
1055 1056
-- [whatsits][hlist][glue][glue][penalty]
1057 1058
local
special_penalty_min
=
32250
1059
local
special_penalty_max
=
35000
1060
local
special_penalty_xxx
=
0
1061 1062
-- this is rather messy and complex: we want to make sure that successive
1063
-- header don't break but also make sure that we have at least a decent
1064
-- break when we have succesive ones (often when testing)
1065 1066
-- todo: mark headers as such so that we can recognize them
1067 1068
local
specialmethods
=
{
}
1069
local
specialmethod
=
1
1070 1071
specialmethods
[
1
]
=
function
(
pagehead
,
pagetail
,
start
,
penalty
)
1072
--
1073
if
not
pagehead
or
penalty
<
special_penalty_min
or
penalty
>
special_penalty_max
then
1074
return
1075
end
1076
local
current
=
pagetail
1077
--
1078
-- nodes.showsimplelist(pagehead,0)
1079
--
1080
if
trace_specials
then
1081
report_specials
(
"
checking penalty %a
"
,
penalty
)
1082
end
1083
while
current
do
1084
local
id
=
getid
(
current
)
1085
if
id
=
=
penalty_code
then
1086
local
p
=
properties
[
current
]
1087
if
p
then
1088
local
p
=
p
.
special_penalty
1089
if
not
p
then
1090
if
trace_specials
then
1091
report_specials
(
"
regular penalty, continue
"
)
1092
end
1093
elseif
p
=
=
penalty
then
1094
if
trace_specials
then
1095
report_specials
(
"
context penalty %a, same level, overloading
"
,
p
)
1096
end
1097
return
special_penalty_xxx
1098
elseif
p
>
special_penalty_min
and
p
<
special_penalty_max
then
1099
if
penalty
<
p
then
1100
if
trace_specials
then
1101
report_specials
(
"
context penalty %a, lower level, overloading
"
,
p
)
1102
end
1103
return
special_penalty_xxx
1104
else
1105
if
trace_specials
then
1106
report_specials
(
"
context penalty %a, higher level, quitting
"
,
p
)
1107
end
1108
return
1109
end
1110
elseif
trace_specials
then
1111
report_specials
(
"
context penalty %a, higher level, continue
"
,
p
)
1112
end
1113
else
1114
local
p
=
getpenalty
(
current
)
1115
if
p
<
10000
then
1116
-- assume some other mechanism kicks in so we seem to have content
1117
if
trace_specials
then
1118
report_specials
(
"
regular penalty %a, quitting
"
,
p
)
1119
end
1120
break
1121
else
1122
if
trace_specials
then
1123
report_specials
(
"
regular penalty %a, continue
"
,
p
)
1124
end
1125
end
1126
end
1127
end
1128
current
=
getprev
(
current
)
1129
end
1130
-- none found, so no reson to be special
1131
if
trace_specials
then
1132
if
pagetail
then
1133
report_specials
(
"
context penalty, discarding, nothing special
"
)
1134
else
1135
report_specials
(
"
context penalty, discarding, nothing preceding
"
)
1136
end
1137
end
1138
return
special_penalty_xxx
1139
end
1140 1141
-- This will be replaced after 0.80+ when we have a more robust look-back and
1142
-- can look at the bigger picture.
1143 1144
-- todo: look back and when a special is there before a list is seen penalty keep ut
1145 1146
-- we now look back a lot, way too often
1147 1148
-- userskip
1149
-- lineskip
1150
-- baselineskip
1151
-- parskip
1152
-- abovedisplayskip
1153
-- belowdisplayskip
1154
-- abovedisplayshortskip
1155
-- belowdisplayshortskip
1156
-- topskip
1157
-- splittopskip
1158 1159
-- we could inject a vadjust to force a recalculation .. a mess
1160
--
1161
-- So, the next is far from robust and okay but for the moment this overlaying
1162
-- has to do. Always test this with the examples in spac-ver.mkvi!
1163 1164
local
function
check_experimental_overlay
(
head
,
current
)
1165
local
p
=
nil
1166
local
c
=
current
1167
local
n
=
nil
1168
local
function
overlay
(
p
,
n
,
mvl
)
1169
local
p_wd
,
p_ht
,
p_dp
=
getwhd
(
p
)
1170
local
n_wd
,
n_ht
,
n_dp
=
getwhd
(
n
)
1171
local
skips
=
0
1172
--
1173
-- We deal with this at the tex end .. we don't see spacing .. enabling this code
1174
-- is probably harmless but then we need to test it.
1175
--
1176
-- we could calculate this before we call
1177
--
1178
-- problem: prev list and next list can be unconnected
1179
--
1180
local
c
=
getnext
(
p
)
1181
local
l
=
c
1182
while
c
and
c
~
=
n
do
1183
local
id
=
getid
(
c
)
1184
if
id
=
=
glue_code
then
1185
skips
=
skips
+
getwidth
(
c
)
1186
elseif
id
=
=
kern_code
then
1187
skips
=
skips
+
getkern
(
c
)
1188
end
1189
l
=
c
1190
c
=
getnext
(
c
)
1191
end
1192
local
c
=
getprev
(
n
)
1193
while
c
and
c
~
=
n
and
c
~
=
l
do
1194
local
id
=
getid
(
c
)
1195
if
id
=
=
glue_code
then
1196
skips
=
skips
+
getwidth
(
c
)
1197
elseif
id
=
=
kern_code
then
1198
skips
=
skips
+
getkern
(
c
)
1199
end
1200
c
=
getprev
(
c
)
1201
end
1202
--
1203
local
delta
=
n_ht
+
skips
+
p_dp
1204
texsetdimen
(
"
global
"
,
"
d_spac_overlay
"
,
-
delta
)
-- for tracing
1205
-- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak
1206
local
k
=
new_kern
(
-
delta
)
1207
head
=
insertnodebefore
(
head
,
n
,
k
)
1208
if
n_ht
>
p_ht
then
1209
local
k
=
new_kern
(
n_ht
-
p_ht
)
1210
head
=
insertnodebefore
(
head
,
p
,
k
)
1211
end
1212
if
trace_vspacing
then
1213
report_vspacing
(
"
overlaying, prev height: %p, prev depth: %p, next height: %p, skips: %p, move up: %p
"
,
p_ht
,
p_dp
,
n_ht
,
skips
,
delta
)
1214
end
1215
return
remove_node
(
head
,
current
,
true
)
1216
end
1217 1218
-- goto next line
1219
while
c
do
1220
local
id
=
getid
(
c
)
1221
if
id
=
=
glue_code
or
id
=
=
penalty_code
or
id
=
=
kern_code
then
1222
-- skip (actually, remove)
1223
c
=
getnext
(
c
)
1224
elseif
id
=
=
hlist_code
then
1225
n
=
c
1226
break
1227
else
1228
break
1229
end
1230
end
1231
if
n
then
1232
-- we have a next line, goto prev line
1233
c
=
current
1234
while
c
do
1235
local
id
=
getid
(
c
)
1236
if
id
=
=
glue_code
or
id
=
=
penalty_code
then
-- kern ?
1237
c
=
getprev
(
c
)
1238
elseif
id
=
=
hlist_code
then
1239
p
=
c
1240
break
1241
else
1242
break
1243
end
1244
end
1245
if
not
p
then
1246
if
a_snapmethod
=
=
a_snapvbox
then
1247
-- quit, we're not on the mvl
1248
else
1249
-- inefficient when we're at the end of a page
1250
local
c
=
tonut
(
texlists
.
page_head
)
1251
while
c
and
c
~
=
n
do
1252
local
id
=
getid
(
c
)
1253
if
id
=
=
hlist_code
then
1254
p
=
c
1255
end
1256
c
=
getnext
(
c
)
1257
end
1258
if
p
and
p
~
=
n
then
1259
return
overlay
(
p
,
n
,
true
)
1260
end
1261
end
1262
elseif
p
~
=
n
then
1263
return
overlay
(
p
,
n
,
false
)
1264
end
1265
end
1266
-- in fact, we could try again later ... so then no remove (a few tries)
1267
return
remove_node
(
head
,
current
,
true
)
1268
end
1269 1270
local
function
collapser
(
head
,
where
,
what
,
trace
,
snap
,
a_snapmethod
)
-- maybe also pass tail
1271
if
trace
then
1272
reset_tracing
(
head
)
1273
end
1274
local
current
=
head
1275
local
oldhead
=
head
1276
local
glue_order
=
0
1277
local
glue_data
1278
local
force_glue
=
false
1279
local
penalty_order
=
0
1280
local
penalty_data
1281
local
natural_penalty
1282
local
special_penalty
1283
local
parskip
1284
local
ignore_parskip
=
false
1285
local
ignore_following
=
false
1286
local
ignore_whitespace
=
false
1287
local
keep_together
=
false
1288
local
lastsnap
1289
local
pagehead
1290
local
pagetail
1291
--
1292
-- todo: keep_together: between headers
1293
--
1294
local
function
getpagelist
(
)
1295
if
not
pagehead
then
1296
pagehead
=
texlists
.
page_head
1297
if
pagehead
then
1298
pagehead
=
tonut
(
pagehead
)
1299
pagetail
=
find_node_tail
(
pagehead
)
-- no texlists.page_tail yet-- no texlists.page_tail yet
1300
end
1301
end
1302
end
1303
--
1304
local
function
compensate
(
n
)
1305
local
g
=
0
1306
while
n
and
getid
(
n
)
=
=
glue_code
do
1307
g
=
g
+
getwidth
(
n
)
1308
n
=
getnext
(
n
)
1309
end
1310
if
n
then
1311
local
p
=
getprop
(
n
,
"
snapper
"
)
1312
if
p
then
1313
local
extra
=
p
.
extra
1314
if
extra
and
extra
<
0
then
-- hm, extra can be unset ... needs checking
1315
local
h
=
p
.
ch
-- getheight(n)
1316
-- maybe an extra check
1317
-- if h - extra < g then
1318
setheight
(
n
,
h
-2
*
extra
)
1319
p
.
extra
=
0
1320
if
trace_vsnapping
then
1321
report_snapper
(
"
removed extra space at top: %p
"
,
extra
)
1322
end
1323
-- end
1324
end
1325
end
1326
return
n
1327
end
1328
end
1329
--
1330
local
function
removetopsnap
(
)
1331
getpagelist
(
)
1332
if
pagehead
then
1333
local
n
=
pagehead
and
compensate
(
pagehead
)
1334
if
n
and
n
~
=
pagetail
then
1335
local
p
=
getprop
(
pagetail
,
"
snapper
"
)
1336
if
p
then
1337
local
e
=
p
.
extra
1338
if
e
and
e
<
0
then
1339
local
t
=
texget
(
"
pagetotal
"
)
1340
if
t
>
0
then
1341
local
g
=
texget
(
"
pagegoal
"
)
-- 1073741823 is signal
1342
local
d
=
g
-
t
1343
if
d
<
-
e
then
1344
local
penalty
=
new_penalty
(
1000000
)
1345
setlink
(
penalty
,
head
)
1346
head
=
penalty
1347
report_snapper
(
"
force pagebreak due to extra space at bottom: %p
"
,
e
)
1348
end
1349
end
1350
end
1351
end
1352
end
1353
elseif
head
then
1354
compensate
(
head
)
1355
end
1356
end
1357
--
1358
local
function
getavailable
(
)
1359
getpagelist
(
)
1360
if
pagehead
then
1361
local
t
=
texget
(
"
pagetotal
"
)
1362
if
t
>
0
then
1363
local
g
=
texget
(
"
pagegoal
"
)
1364
return
g
-
t
1365
end
1366
end
1367
return
false
1368
end
1369
--
1370
local
function
flush
(
why
)
1371
if
penalty_data
then
1372
local
p
=
new_penalty
(
penalty_data
)
1373
if
trace
then
1374
trace_done
(
"
flushed due to
"
.
.
why
,
p
)
1375
end
1376
if
penalty_data
>
=
10000
then
-- or whatever threshold?
1377
local
prev
=
getprev
(
current
)
1378
if
getid
(
prev
)
=
=
glue_code
then
-- maybe go back more, or maybe even push back before any glue
1379
-- tricky case: spacing/grid-007.tex: glue penalty glue
1380
head
=
insertnodebefore
(
head
,
prev
,
p
)
1381
else
1382
head
=
insertnodebefore
(
head
,
current
,
p
)
1383
end
1384
else
1385
head
=
insertnodebefore
(
head
,
current
,
p
)
1386
end
1387
-- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then
1388
local
props
=
properties
[
p
]
1389
if
props
then
1390
props
.
special_penalty
=
special_penalty
or
penalty_data
1391
else
1392
properties
[
p
]
=
{
1393
special_penalty
=
special_penalty
or
penalty_data
1394
}
1395
end
1396
-- end
1397
end
1398
if
glue_data
then
1399
if
force_glue
then
1400
if
trace
then
1401
trace_done
(
"
flushed due to forced
"
.
.
why
,
glue_data
)
1402
end
1403
head
=
forced_skip
(
head
,
current
,
getwidth
(
glue_data
,
width
)
,
"
before
"
,
trace
)
1404
flushnode
(
glue_data
)
1405
else
1406
local
width
,
stretch
,
shrink
=
getglue
(
glue_data
)
1407
if
width
~
=
0
then
1408
if
trace
then
1409
trace_done
(
"
flushed due to non zero
"
.
.
why
,
glue_data
)
1410
end
1411
head
=
insertnodebefore
(
head
,
current
,
glue_data
)
1412
elseif
stretch
~
=
0
or
shrink
~
=
0
then
1413
if
trace
then
1414
trace_done
(
"
flushed due to stretch/shrink in
"
.
.
why
,
glue_data
)
1415
end
1416
head
=
insertnodebefore
(
head
,
current
,
glue_data
)
1417
else
1418
-- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w)
1419
flushnode
(
glue_data
)
1420
end
1421
end
1422
end
1423 1424
if
trace
then
1425
trace_node
(
current
)
1426
end
1427
glue_order
,
glue_data
,
force_glue
=
0
,
nil
,
false
1428
penalty_order
,
penalty_data
,
natural_penalty
=
0
,
nil
,
nil
1429
parskip
,
ignore_parskip
,
ignore_following
,
ignore_whitespace
=
nil
,
false
,
false
,
false
1430
end
1431
--
1432
if
trace_vsnapping
then
1433
report_snapper
(
"
global ht/dp = %p/%p, local ht/dp = %p/%p
"
,
1434
texgetdimen
(
"
globalbodyfontstrutheight
"
)
,
1435
texgetdimen
(
"
globalbodyfontstrutdepth
"
)
,
1436
texgetdimen
(
"
bodyfontstrutheight
"
)
,
1437
texgetdimen
(
"
bodyfontstrutdepth
"
)
1438
)
1439
end
1440
if
trace
then
1441
trace_info
(
"
start analyzing
"
,
where
,
what
)
1442
end
1443
if
snap
and
where
=
=
"
page
"
then
1444
removetopsnap
(
)
1445
end
1446
while
current
do
1447
local
id
=
getid
(
current
)
1448
if
id
=
=
hlist_code
or
id
=
=
vlist_code
then
1449
-- needs checking, why so many calls
1450
if
snap
then
1451
lastsnap
=
nil
1452
local
list
=
getlist
(
current
)
1453
local
s
=
getattr
(
current
,
a_snapmethod
)
1454
if
not
s
then
1455
-- if trace_vsnapping then
1456
-- report_snapper("mvl list not snapped")
1457
-- end
1458
elseif
s
=
=
0
then
1459
if
trace_vsnapping
then
1460
report_snapper
(
"
mvl %a not snapped, already done: %s
"
,
nodecodes
[
id
]
,
listtoutf
(
list
)
)
1461
end
1462
else
1463
local
sv
=
snapmethods
[
s
]
1464
if
sv
then
1465
-- check if already snapped
1466
local
done
=
list
and
already_done
(
id
,
list
,
a_snapmethod
)
1467
if
done
then
1468
-- assume that the box is already snapped
1469
if
trace_vsnapping
then
1470
local
w
,
h
,
d
=
getwhd
(
current
)
1471
report_snapper
(
"
mvl list already snapped at (%p,%p): %s
"
,
h
,
d
,
listtoutf
(
list
)
)
1472
end
1473
else
1474
local
h
,
d
,
ch
,
cd
,
lines
,
extra
=
snap_hlist
(
"
mvl
"
,
current
,
sv
,
false
,
false
)
1475
lastsnap
=
{
1476
ht
=
h
,
1477
dp
=
d
,
1478
ch
=
ch
,
1479
cd
=
cd
,
1480
extra
=
extra
,
1481
current
=
current
,
1482
}
1483
setprop
(
current
,
"
snapper
"
,
lastsnap
)
1484
if
trace_vsnapping
then
1485
report_snapper
(
"
mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s
"
,
1486
nodecodes
[
id
]
,
h
,
d
,
ch
,
cd
,
sv
.
name
,
sv
.
specification
,
where
,
lines
,
listtoutf
(
list
)
)
1487
end
1488
end
1489
elseif
trace_vsnapping
then
1490
report_snapper
(
"
mvl %a not snapped due to unknown snap specification: %s
"
,
nodecodes
[
id
]
,
listtoutf
(
list
)
)
1491
end
1492
setattr
(
current
,
a_snapmethod
,
0
)
1493
end
1494
else
1495
--
1496
end
1497
-- tex.prevdepth = 0
1498
flush
(
"
list
"
)
1499
current
=
getnext
(
current
)
1500
elseif
id
=
=
penalty_code
then
1501
-- natural_penalty = getpenalty(current)
1502
-- if trace then
1503
-- trace_done("removed penalty",current)
1504
-- end
1505
-- head, current = remove_node(head,current,true)
1506
current
=
getnext
(
current
)
1507
elseif
id
=
=
kern_code
then
1508
if
snap
and
trace_vsnapping
and
getkern
(
current
)
~
=
0
then
1509
report_snapper
(
"
kern of %p kept
"
,
getkern
(
current
)
)
1510
end
1511
flush
(
"
kern
"
)
1512
current
=
getnext
(
current
)
1513
elseif
id
=
=
glue_code
then
1514
local
subtype
=
getsubtype
(
current
)
1515
if
subtype
=
=
userskip_code
then
1516
local
sc
=
getattr
(
current
,
a_skipcategory
)
-- has no default, no unset (yet)
1517
local
so
=
getattr
(
current
,
a_skiporder
)
or
1
-- has 1 default, no unset (yet)
1518
local
sp
=
getattr
(
current
,
a_skippenalty
)
-- has no default, no unset (yet)
1519
if
sp
and
sc
=
=
penalty
then
1520
if
where
=
=
"
page
"
then
1521
getpagelist
(
)
1522
local
p
=
specialmethods
[
specialmethod
]
(
pagehead
,
pagetail
,
current
,
sp
)
1523
if
p
then
1524
-- todo: other tracer
1525
--
1526
-- if trace then
1527
-- trace_skip("previous special penalty %a is changed to %a using method %a",sp,p,specialmethod)
1528
-- end
1529
special_penalty
=
sp
1530
sp
=
p
1531
end
1532
end
1533
if
not
penalty_data
then
1534
penalty_data
=
sp
1535
elseif
penalty_order
<
so
then
1536
penalty_order
,
penalty_data
=
so
,
sp
1537
elseif
penalty_order
=
=
so
and
sp
>
penalty_data
then
1538
penalty_data
=
sp
1539
end
1540
if
trace
then
1541
trace_skip
(
"
penalty in skip
"
,
sc
,
so
,
sp
,
current
)
1542
end
1543
head
,
current
=
remove_node
(
head
,
current
,
true
)
1544
elseif
not
sc
then
-- if not sc then
1545
if
glue_data
then
1546
if
trace
then
1547
trace_done
(
"
flush
"
,
glue_data
)
1548
end
1549
head
=
insertnodebefore
(
head
,
current
,
glue_data
)
1550
if
trace
then
1551
trace_natural
(
"
natural
"
,
current
)
1552
end
1553
current
=
getnext
(
current
)
1554
else
1555
-- not look back across head
1556
-- todo: prev can be whatsit (latelua)
1557
local
previous
=
getprev
(
current
)
1558
if
previous
and
getid
(
previous
)
=
=
glue_code
and
getsubtype
(
previous
)
=
=
userskip_code
then
1559
local
pwidth
,
pstretch
,
pshrink
,
pstretch_order
,
pshrink_order
=
getglue
(
previous
)
1560
local
cwidth
,
cstretch
,
cshrink
,
cstretch_order
,
cshrink_order
=
getglue
(
current
)
1561
if
pstretch_order
=
=
0
and
pshrink_order
=
=
0
and
cstretch_order
=
=
0
and
cshrink_order
=
=
0
then
1562
setglue
(
previous
,
pwidth
+
cwidth
,
pstretch
+
cstretch
,
pshrink
+
cshrink
)
1563
if
trace
then
1564
trace_natural
(
"
removed
"
,
current
)
1565
end
1566
head
,
current
=
remove_node
(
head
,
current
,
true
)
1567
if
trace
then
1568
trace_natural
(
"
collapsed
"
,
previous
)
1569
end
1570
else
1571
if
trace
then
1572
trace_natural
(
"
filler
"
,
current
)
1573
end
1574
current
=
getnext
(
current
)
1575
end
1576
else
1577
if
trace
then
1578
trace_natural
(
"
natural (no prev)
"
,
current
)
1579
end
1580
current
=
getnext
(
current
)
1581
end
1582
end
1583
glue_order
,
glue_data
=
0
,
nil
1584
elseif
sc
=
=
disable
or
sc
=
=
enable
then
1585
local
next
=
getnext
(
current
)
1586
if
next
then
1587
ignore_following
=
sc
=
=
disable
1588
if
trace
then
1589
trace_skip
(
sc
=
=
disable
and
"
disable
"
or
"
enable
"
,
sc
,
so
,
sp
,
current
)
1590
end
1591
head
,
current
=
remove_node
(
head
,
current
,
true
)
1592
else
1593
current
=
next
1594
end
1595
elseif
sc
=
=
packed
then
1596
if
trace
then
1597
trace_skip
(
"
packed
"
,
sc
,
so
,
sp
,
current
)
1598
end
1599
-- can't happen !
1600
head
,
current
=
remove_node
(
head
,
current
,
true
)
1601
elseif
sc
=
=
nowhite
then
1602
local
next
=
getnext
(
current
)
1603
if
next
then
1604
ignore_whitespace
=
true
1605
head
,
current
=
remove_node
(
head
,
current
,
true
)
1606
else
1607
current
=
next
1608
end
1609
elseif
sc
=
=
discard
then
1610
if
trace
then
1611
trace_skip
(
"
discard
"
,
sc
,
so
,
sp
,
current
)
1612
end
1613
head
,
current
=
remove_node
(
head
,
current
,
true
)
1614
elseif
sc
=
=
overlay
then
1615
-- todo (overlay following line over previous
1616
if
trace
then
1617
trace_skip
(
"
overlay
"
,
sc
,
so
,
sp
,
current
)
1618
end
1619
-- beware: head can actually be after the affected nodes as
1620
-- we look back ... some day head will the real head
1621
head
,
current
=
check_experimental_overlay
(
head
,
current
,
a_snapmethod
)
1622
elseif
ignore_following
then
1623
if
trace
then
1624
trace_skip
(
"
disabled
"
,
sc
,
so
,
sp
,
current
)
1625
end
1626
head
,
current
=
remove_node
(
head
,
current
,
true
)
1627
elseif
not
glue_data
then
1628
if
trace
then
1629
trace_skip
(
"
assign
"
,
sc
,
so
,
sp
,
current
)
1630
end
1631
glue_order
=
so
1632
head
,
current
,
glue_data
=
remove_node
(
head
,
current
)
1633
elseif
glue_order
<
so
then
1634
if
trace
then
1635
trace_skip
(
"
force
"
,
sc
,
so
,
sp
,
current
)
1636
end
1637
glue_order
=
so
1638
flushnode
(
glue_data
)
1639
head
,
current
,
glue_data
=
remove_node
(
head
,
current
)
1640
elseif
glue_order
=
=
so
then
1641
-- is now exclusive, maybe support goback as combi, else why a set
1642
if
sc
=
=
largest
then
1643
local
cw
=
getwidth
(
current
)
1644
local
gw
=
getwidth
(
glue_data
)
1645
if
cw
>
gw
then
1646
if
trace
then
1647
trace_skip
(
"
largest
"
,
sc
,
so
,
sp
,
current
)
1648
end
1649
flushnode
(
glue_data
)
1650
head
,
current
,
glue_data
=
remove_node
(
head
,
current
)
1651
else
1652
if
trace
then
1653
trace_skip
(
"
remove smallest
"
,
sc
,
so
,
sp
,
current
)
1654
end
1655
head
,
current
=
remove_node
(
head
,
current
,
true
)
1656
end
1657
elseif
sc
=
=
goback
then
1658
if
trace
then
1659
trace_skip
(
"
goback
"
,
sc
,
so
,
sp
,
current
)
1660
end
1661
flushnode
(
glue_data
)
1662
head
,
current
,
glue_data
=
remove_node
(
head
,
current
)
1663
elseif
sc
=
=
force
then
1664
-- last one counts, some day we can provide an accumulator and largest etc
1665
-- but not now
1666
if
trace
then
1667
trace_skip
(
"
force
"
,
sc
,
so
,
sp
,
current
)
1668
end
1669
flushnode
(
glue_data
)
1670
head
,
current
,
glue_data
=
remove_node
(
head
,
current
)
1671
elseif
sc
=
=
penalty
then
1672
if
trace
then
1673
trace_skip
(
"
penalty
"
,
sc
,
so
,
sp
,
current
)
1674
end
1675
flushnode
(
glue_data
)
1676
glue_data
=
nil
1677
head
,
current
=
remove_node
(
head
,
current
,
true
)
1678
elseif
sc
=
=
add
then
1679
if
trace
then
1680
trace_skip
(
"
add
"
,
sc
,
so
,
sp
,
current
)
1681
end
1682
local
cwidth
,
cstretch
,
cshrink
=
getglue
(
current
)
1683
local
gwidth
,
gstretch
,
gshrink
=
getglue
(
glue_data
)
1684
setglue
(
glue_data
,
gwidth
+
cwidth
,
gstretch
+
cstretch
,
gshrink
+
cshrink
)
1685
-- toto: order
1686
head
,
current
=
remove_node
(
head
,
current
,
true
)
1687
else
1688
if
trace
then
1689
trace_skip
(
"
unknown
"
,
sc
,
so
,
sp
,
current
)
1690
end
1691
head
,
current
=
remove_node
(
head
,
current
,
true
)
1692
end
1693
else
1694
if
trace
then
1695
trace_skip
(
"
unknown
"
,
sc
,
so
,
sp
,
current
)
1696
end
1697
head
,
current
=
remove_node
(
head
,
current
,
true
)
1698
end
1699
if
sc
=
=
force
then
1700
force_glue
=
true
1701
end
1702
elseif
subtype
=
=
lineskip_code
then
1703
if
snap
then
1704
local
s
=
getattr
(
current
,
a_snapmethod
)
1705
if
s
and
s
~
=
0
then
1706
setattr
(
current
,
a_snapmethod
,
0
)
1707
setwidth
(
current
,
0
)
1708
if
trace_vsnapping
then
1709
report_snapper
(
"
lineskip set to zero
"
)
1710
end
1711
else
1712
if
trace
then
1713
trace_skip
(
"
lineskip
"
,
sc
,
so
,
sp
,
current
)
1714
end
1715
flush
(
"
lineskip
"
)
1716
end
1717
else
1718
if
trace
then
1719
trace_skip
(
"
lineskip
"
,
sc
,
so
,
sp
,
current
)
1720
end
1721
flush
(
"
lineskip
"
)
1722
end
1723
current
=
getnext
(
current
)
1724
elseif
subtype
=
=
baselineskip_code
then
1725
if
snap
then
1726
local
s
=
getattr
(
current
,
a_snapmethod
)
1727
if
s
and
s
~
=
0
then
1728
setattr
(
current
,
a_snapmethod
,
0
)
1729
setwidth
(
current
,
0
)
1730
if
trace_vsnapping
then
1731
report_snapper
(
"
baselineskip set to zero
"
)
1732
end
1733
else
1734
if
trace
then
1735
trace_skip
(
"
baselineskip
"
,
sc
,
so
,
sp
,
current
)
1736
end
1737
flush
(
"
baselineskip
"
)
1738
end
1739
else
1740
if
trace
then
1741
trace_skip
(
"
baselineskip
"
,
sc
,
so
,
sp
,
current
)
1742
end
1743
flush
(
"
baselineskip
"
)
1744
end
1745
current
=
getnext
(
current
)
1746
elseif
subtype
=
=
parskip_code
then
1747
-- parskip always comes later
1748
if
ignore_whitespace
then
1749
if
trace
then
1750
trace_natural
(
"
ignored parskip
"
,
current
)
1751
end
1752
head
,
current
=
remove_node
(
head
,
current
,
true
)
1753
elseif
glue_data
then
1754
local
w
=
getwidth
(
current
)
1755
if
(
w
~
=
0
)
and
(
w
>
getwidth
(
glue_data
)
)
then
1756
glue_data
=
current
1757
if
trace
then
1758
trace_natural
(
"
taking parskip
"
,
current
)
1759
end
1760
head
,
current
=
remove_node
(
head
,
current
)
1761
else
1762
if
trace
then
1763
trace_natural
(
"
removed parskip
"
,
current
)
1764
end
1765
head
,
current
=
remove_node
(
head
,
current
,
true
)
1766
end
1767
else
1768
if
trace
then
1769
trace_natural
(
"
honored parskip
"
,
current
)
1770
end
1771
head
,
current
,
glue_data
=
remove_node
(
head
,
current
)
1772
end
1773
elseif
subtype
=
=
topskip_code
or
subtype
=
=
splittopskip_code
then
1774
local
next
=
getnext
(
current
)
1775
if
next
and
getattr
(
next
,
a_skipcategory
)
=
=
notopskip
then
1776
nuts
.
setglue
(
current
)
-- zero
1777
end
1778
if
snap
then
1779
local
s
=
getattr
(
current
,
a_snapmethod
)
1780
if
s
and
s
~
=
0
then
1781
setattr
(
current
,
a_snapmethod
,
0
)
1782
local
sv
=
snapmethods
[
s
]
1783
local
w
,
cw
=
snap_topskip
(
current
,
sv
)
1784
if
trace_vsnapping
then
1785
report_snapper
(
"
topskip snapped from %p to %p for %a
"
,
w
,
cw
,
where
)
1786
end
1787
else
1788
if
trace
then
1789
trace_skip
(
"
topskip
"
,
sc
,
so
,
sp
,
current
)
1790
end
1791
flush
(
"
topskip
"
)
1792
end
1793
else
1794
if
trace
then
1795
trace_skip
(
"
topskip
"
,
sc
,
so
,
sp
,
current
)
1796
end
1797
flush
(
"
topskip
"
)
1798
end
1799
current
=
getnext
(
current
)
1800
elseif
subtype
=
=
abovedisplayskip_code
and
remove_math_skips
then
1801
--
1802
if
trace
then
1803
trace_skip
(
"
above display skip (normal)
"
,
sc
,
so
,
sp
,
current
)
1804
end
1805
flush
(
"
above display skip (normal)
"
)
1806
current
=
getnext
(
current
)
1807
--
1808
elseif
subtype
=
=
belowdisplayskip_code
and
remove_math_skips
then
1809
--
1810
if
trace
then
1811
trace_skip
(
"
below display skip (normal)
"
,
sc
,
so
,
sp
,
current
)
1812
end
1813
flush
(
"
below display skip (normal)
"
)
1814
current
=
getnext
(
current
)
1815
--
1816
elseif
subtype
=
=
abovedisplayshortskip_code
and
remove_math_skips
then
1817
--
1818
if
trace
then
1819
trace_skip
(
"
above display skip (short)
"
,
sc
,
so
,
sp
,
current
)
1820
end
1821
flush
(
"
above display skip (short)
"
)
1822
current
=
getnext
(
current
)
1823
--
1824
elseif
subtype
=
=
belowdisplayshortskip_code
and
remove_math_skips
then
1825
--
1826
if
trace
then
1827
trace_skip
(
"
below display skip (short)
"
,
sc
,
so
,
sp
,
current
)
1828
end
1829
flush
(
"
below display skip (short)
"
)
1830
current
=
getnext
(
current
)
1831
--
1832
else
-- other glue
1833
if
snap
and
trace_vsnapping
then
1834
local
w
=
getwidth
(
current
)
1835
if
w
~
=
0
then
1836
report_snapper
(
"
glue %p of type %a kept
"
,
w
,
gluecodes
[
subtype
]
)
1837
end
1838
end
1839
if
trace
then
1840
trace_skip
(
formatters
[
"
glue of type %a
"
]
(
subtype
)
,
sc
,
so
,
sp
,
current
)
1841
end
1842
flush
(
"
some glue
"
)
1843
current
=
getnext
(
current
)
1844
end
1845
else
1846
flush
(
formatters
[
"
node with id %a
"
]
(
id
)
)
1847
current
=
getnext
(
current
)
1848
end
1849
end
1850
if
trace
then
1851
trace_info
(
"
stop analyzing
"
,
where
,
what
)
1852
end
1853
-- if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then
1854
-- penalty_data = natural_penalty
1855
-- end
1856
if
trace
and
(
glue_data
or
penalty_data
)
then
1857
trace_info
(
"
start flushing
"
,
where
,
what
)
1858
end
1859
local
tail
1860
if
penalty_data
then
1861
tail
=
find_node_tail
(
head
)
1862
local
p
=
new_penalty
(
penalty_data
)
1863
if
trace
then
1864
trace_done
(
"
result
"
,
p
)
1865
end
1866
setlink
(
tail
,
p
)
1867
-- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then
1868
local
props
=
properties
[
p
]
1869
if
props
then
1870
props
.
special_penalty
=
special_penalty
or
penalty_data
1871
else
1872
properties
[
p
]
=
{
1873
special_penalty
=
special_penalty
or
penalty_data
1874
}
1875
end
1876
-- end
1877
end
1878
if
glue_data
then
1879
if
not
tail
then
tail
=
find_node_tail
(
head
)
end
1880
if
trace
then
1881
trace_done
(
"
result
"
,
glue_data
)
1882
end
1883
if
force_glue
then
1884
head
,
tail
=
forced_skip
(
head
,
tail
,
getwidth
(
glue_data
)
,
"
after
"
,
trace
)
1885
flushnode
(
glue_data
)
1886
glue_data
=
nil
1887
elseif
tail
then
1888
setlink
(
tail
,
glue_data
)
1889
else
1890
head
=
glue_data
1891
end
1892
texnest
[
texnest
.
ptr
]
.
prevdepth
=
0
-- appending to the list bypasses tex's prevdepth handler
1893
end
1894
if
trace
then
1895
if
glue_data
or
penalty_data
then
1896
trace_info
(
"
stop flushing
"
,
where
,
what
)
1897
end
1898
show_tracing
(
head
)
1899
if
oldhead
~
=
head
then
1900
trace_info
(
"
head has been changed from %a to %a
"
,
nodecodes
[
getid
(
oldhead
)
]
,
nodecodes
[
getid
(
head
)
]
)
1901
end
1902
end
1903
return
head
1904
end
1905 1906
local
stackhead
,
stacktail
,
stackhack
=
nil
,
nil
,
false
1907 1908
local
function
report
(
message
,
where
,
lst
)
1909
if
lst
and
where
then
1910
report_vspacing
(
message
,
where
,
count_nodes
(
lst
,
true
)
,
nodeidstostring
(
lst
)
)
1911
else
1912
report_vspacing
(
message
,
count_nodes
(
lst
,
true
)
,
nodeidstostring
(
lst
)
)
1913
end
1914
end
1915 1916
-- ugly code: we get partial lists (check if this stack is still okay) ... and we run
1917
-- into temp nodes (sigh)
1918 1919
local
forceflush
=
false
1920 1921
function
vspacing
.
pagehandler
(
newhead
,
where
)
1922
if
newhead
then
1923
local
newtail
=
find_node_tail
(
newhead
)
-- best pass that tail, known anyway
1924
local
flush
=
false
1925
stackhack
=
true
-- todo: only when grid snapping once enabled
1926
-- todo: fast check if head = tail
1927
for
n
,
id
,
subtype
in
nextnode
,
newhead
do
-- we could just look for glue nodes
1928
if
id
~
=
glue_code
then
1929
flush
=
true
1930
elseif
subtype
=
=
userskip_code
then
1931
if
getattr
(
n
,
a_skipcategory
)
then
1932
stackhack
=
true
1933
else
1934
flush
=
true
1935
end
1936
elseif
subtype
=
=
parskip_code
then
1937
-- if where == new_graf then ... end
1938
if
texgetcount
(
"
c_spac_vspacing_ignore_parskip
"
)
>
0
then
1939
-- texsetcount("c_spac_vspacing_ignore_parskip",0)
1940
setglue
(
n
)
1941
-- maybe removenode
1942
end
1943
end
1944
end
1945
texsetcount
(
"
c_spac_vspacing_ignore_parskip
"
,
0
)
1946 1947
if
forceflush
then
1948
forceflush
=
false
1949
flush
=
true
1950
end
1951 1952
if
flush
then
1953
if
stackhead
then
1954
if
trace_collect_vspacing
then
report
(
"
%s > appending %s nodes to stack (final): %s
"
,
where
,
newhead
)
end
1955
setlink
(
stacktail
,
newhead
)
1956
newhead
=
stackhead
1957
stackhead
=
nil
1958
stacktail
=
nil
1959
end
1960
if
stackhack
then
1961
stackhack
=
false
1962
if
trace_collect_vspacing
then
report
(
"
%s > processing %s nodes: %s
"
,
where
,
newhead
)
end
1963
newhead
=
collapser
(
newhead
,
"
page
"
,
where
,
trace_page_vspacing
,
true
,
a_snapmethod
)
1964
else
1965
if
trace_collect_vspacing
then
report
(
"
%s > flushing %s nodes: %s
"
,
where
,
newhead
)
end
1966
end
1967
return
newhead
1968
else
1969
if
stackhead
then
1970
if
trace_collect_vspacing
then
report
(
"
%s > appending %s nodes to stack (intermediate): %s
"
,
where
,
newhead
)
end
1971
setlink
(
stacktail
,
newhead
)
1972
else
1973
if
trace_collect_vspacing
then
report
(
"
%s > storing %s nodes in stack (initial): %s
"
,
where
,
newhead
)
end
1974
stackhead
=
newhead
1975
end
1976
stacktail
=
newtail
1977
end
1978
end
1979
return
nil
1980
end
1981 1982
function
vspacing
.
pageoverflow
(
)
1983
local
h
=
0
1984
if
stackhead
then
1985
for
n
,
id
in
nextnode
,
stackhead
do
1986
if
id
=
=
glue_code
then
1987
h
=
h
+
getwidth
(
n
)
1988
elseif
id
=
=
kern_code
then
1989
h
=
h
+
getkern
(
n
)
1990
end
1991
end
1992
end
1993
return
h
1994
end
1995 1996
function
vspacing
.
forcepageflush
(
)
1997
forceflush
=
true
1998
end
1999 2000
local
ignore
=
table
.
tohash
{
2001
"
split_keep
"
,
2002
"
split_off
"
,
2003
-- "vbox",
2004
}
2005 2006
function
vspacing
.
vboxhandler
(
head
,
where
)
2007
if
head
and
not
ignore
[
where
]
and
getnext
(
head
)
then
2008
if
getnext
(
head
)
then
-- what if a one liner and snapping?
2009
head
=
collapser
(
head
,
"
vbox
"
,
where
,
trace_vbox_vspacing
,
true
,
a_snapvbox
)
-- todo: local snapper
2010
return
head
2011
end
2012
end
2013
return
head
2014
end
2015 2016
function
vspacing
.
collapsevbox
(
n
,
aslist
)
-- for boxes but using global a_snapmethod
2017
local
box
=
getbox
(
n
)
2018
if
box
then
2019
local
list
=
getlist
(
box
)
2020
if
list
then
2021
list
=
collapser
(
list
,
"
snapper
"
,
"
vbox
"
,
trace_vbox_vspacing
,
true
,
a_snapmethod
)
2022
if
aslist
then
2023
setlist
(
box
,
list
)
-- beware, dimensions of box are wrong now
2024
else
2025
setlist
(
box
,
vpack_node
(
list
)
)
2026
end
2027
end
2028
end
2029
end
2030 2031
end
2032 2033
-- This one is needed to prevent bleeding of prevdepth to the next page
2034
-- which doesn't work well with forced skips. I'm not that sure if the
2035
-- following is a good way out.
2036 2037
do
2038 2039
local
outer
=
texnest
[
0
]
2040 2041
local
enabled
=
true
2042
local
trace
=
false
2043
local
report
=
logs
.
reporter
(
"
vspacing
"
)
2044 2045
trackers
.
register
(
"
vspacing.synchronizepage
"
,
function
(
v
)
2046
trace
=
v
2047
end
)
2048 2049
directives
.
register
(
"
vspacing.synchronizepage
"
,
function
(
v
)
2050
enabled
=
v
2051
end
)
2052 2053
local
ignoredepth
=
-65536000
2054 2055
-- A previous version analyzed the number of lines moved to the next page in
2056
-- synchronizepage because prevgraf is unreliable in that case. However, we cannot
2057
-- tweak that parameter because it is also used in postlinebreak and hangafter, so
2058
-- there is a danger for interference. Therefore we now do it dynamically.
2059 2060
-- We can also support other lists but there prevgraf probably is ok.
2061 2062
function
vspacing
.
getnofpreviouslines
(
head
)
2063
if
enabled
then
2064
if
not
thead
then
2065
head
=
texlists
.
page_head
2066
end
2067
local
noflines
=
0
2068
if
head
then
2069
local
tail
=
find_node_tail
(
tonut
(
head
)
)
2070
while
tail
do
2071
local
id
=
getid
(
tail
)
2072
if
id
=
=
hlist_code
then
2073
if
getsubtype
(
tail
)
=
=
linelist_code
then
2074
noflines
=
noflines
+
1
2075
else
2076
break
2077
end
2078
elseif
id
=
=
vlist_code
then
2079
break
2080
elseif
id
=
=
glue_code
then
2081
local
subtype
=
getsubtype
(
tail
)
2082
if
subtype
=
=
baselineskip_code
or
subtype
=
=
lineskip_code
then
2083
-- we're ok
2084
elseif
subtype
=
=
parskip_code
then
2085
if
getwidth
(
tail
)
>
0
then
2086
break
2087
else
2088
-- we assume we're ok
2089
end
2090
end
2091
elseif
id
=
=
penalty_code
then
2092
-- we're probably ok
2093
elseif
id
=
=
rule_code
or
id
=
=
kern_code
then
2094
break
2095
else
2096
-- ins, mark, boundary, whatsit
2097
end
2098
tail
=
getprev
(
tail
)
2099
end
2100
end
2101
return
noflines
2102
end
2103
end
2104 2105
interfaces
.
implement
{
2106
name
=
"
getnofpreviouslines
"
,
2107
public
=
true
,
2108
actions
=
vspacing
.
getnofpreviouslines
,
2109
}
2110 2111
function
vspacing
.
synchronizepage
(
)
2112
if
enabled
then
2113
if
trace
then
2114
local
newdepth
=
outer
.
prevdepth
2115
local
olddepth
=
newdepth
2116
if
not
texlists
.
page_head
then
2117
newdepth
=
ignoredepth
2118
texset
(
"
prevdepth
"
,
ignoredepth
)
2119
outer
.
prevdepth
=
ignoredepth
2120
end
2121
report
(
"
page %i, prevdepth %p => %p
"
,
texgetcount
(
"
realpageno
"
)
,
olddepth
,
newdepth
)
2122
-- report("list %s",nodes.idsandsubtypes(head))
2123
else
2124
if
not
texlists
.
page_head
then
2125
texset
(
"
prevdepth
"
,
ignoredepth
)
2126
outer
.
prevdepth
=
ignoredepth
2127
end
2128
end
2129
end
2130
end
2131 2132
local
trace
=
false
2133
local
last
=
nil
2134
local
vmode_code
=
tex
.
modelevels
.
vertical
2135
local
temp_code
=
nodecodes
.
temp
2136
local
texgetnest
=
tex
.
getnest
2137
local
texgetlist
=
tex
.
getlist
2138
local
getnodetail
=
nodes
.
tail
2139 2140
trackers
.
register
(
"
vspacing.forcestrutdepth
"
,
function
(
v
)
trace
=
v
end
)
2141 2142
-- abs : negative is inner
2143 2144
function
vspacing
.
checkstrutdepth
(
depth
)
2145
local
nest
=
texgetnest
(
)
2146
if
abs
(
nest
.
mode
)
=
=
vmode_code
and
nest
.
head
then
2147
local
tail
=
nest
.
tail
2148
local
id
=
tail
.
id
2149
if
id
=
=
hlist_code
then
2150
if
tail
.
depth
<
depth
then
2151
tail
.
depth
=
depth
2152
end
2153
nest
.
prevdepth
=
depth
2154
elseif
id
=
=
temp_code
and
texgetnest
(
"
ptr
"
)
=
=
0
then
2155
local
head
=
texgetlist
(
"
page_head
"
)
2156
if
head
then
2157
tail
=
getnodetail
(
head
)
2158
if
tail
and
tail
.
id
=
=
hlist_code
then
2159
if
tail
.
depth
<
depth
then
2160
tail
.
depth
=
depth
2161
end
2162
nest
.
prevdepth
=
depth
2163
-- only works in lmtx
2164
texset
(
"
pagedepth
"
,
depth
)
2165
end
2166
end
2167
end
2168
end
2169
end
2170 2171
interfaces
.
implement
{
2172
name
=
"
checkstrutdepth
"
,
2173
arguments
=
"
dimension
"
,
2174
actions
=
vspacing
.
checkstrutdepth
,
2175
}
2176 2177
function
vspacing
.
forcestrutdepth
(
n
,
depth
,
trace_mode
,
plus
)
2178
local
box
=
texgetbox
(
n
)
2179
if
box
then
2180
box
=
tonut
(
box
)
2181
local
head
=
getlist
(
box
)
2182
if
head
then
2183
local
tail
=
find_node_tail
(
head
)
2184
if
tail
then
2185
if
getid
(
tail
)
=
=
hlist_code
then
2186
local
dp
=
getdepth
(
tail
)
2187
if
dp
<
depth
then
2188
setdepth
(
tail
,
depth
)
2189
outer
.
prevdepth
=
depth
2190
if
trace
or
trace_mode
>
0
then
2191
nuts
.
setvisual
(
tail
,
"
depth
"
)
2192
end
2193
end
2194
end
2195
last
=
nil
2196
if
plus
then
2197
-- penalty / skip ...
2198
local
height
=
0
2199
local
sofar
=
0
2200
local
same
=
false
2201
local
seen
=
false
2202
local
list
=
{
}
2203
last
=
nil
2204
while
tail
do
2205
local
id
=
getid
(
tail
)
2206
if
id
=
=
hlist_code
or
id
=
=
vlist_code
then
2207
local
w
,
h
,
d
=
getwhd
(
tail
)
2208
height
=
height
+
h
+
d
+
sofar
2209
sofar
=
0
2210
last
=
tail
2211
elseif
id
=
=
kern_code
then
2212
sofar
=
sofar
+
getkern
(
tail
)
2213
elseif
id
=
=
glue_code
then
2214
if
seen
then
2215
sofar
=
sofar
+
getwidth
(
tail
)
2216
seen
=
false
2217
else
2218
break
2219
end
2220
elseif
id
=
=
penalty_code
then
2221
local
p
=
getpenalty
(
tail
)
2222
if
p
>
=
10000
then
2223
same
=
true
2224
seen
=
true
2225
else
2226
break
2227
end
2228
else
2229
break
2230
end
2231
tail
=
getprev
(
tail
)
2232
end
2233
texsetdimen
(
"
global
"
,
"
d_spac_prevcontent
"
,
same
and
height
or
0
)
2234
end
2235
end
2236
end
2237
end
2238
end
2239 2240
function
vspacing
.
pushatsame
(
)
2241
-- needs better checking !
2242
if
last
then
-- setsplit
2243
nuts
.
setnext
(
getprev
(
last
)
)
2244
nuts
.
setprev
(
last
)
2245
end
2246
end
2247 2248
function
vspacing
.
popatsame
(
)
2249
-- needs better checking !
2250
nuts
.
write
(
last
)
2251
end
2252 2253
end
2254 2255
-- interface
2256 2257
do
2258 2259
implement
{
2260
name
=
"
vspacing
"
,
2261
actions
=
vspacing
.
analyze
,
2262
scope
=
"
private
"
,
2263
arguments
=
"
string
"
2264
}
2265 2266
implement
{
2267
name
=
"
synchronizepage
"
,
2268
actions
=
vspacing
.
synchronizepage
,
2269
scope
=
"
private
"
2270
}
2271 2272
implement
{
2273
name
=
"
forcestrutdepth
"
,
2274
arguments
=
{
"
integer
"
,
"
dimension
"
,
"
integer
"
}
,
2275
actions
=
vspacing
.
forcestrutdepth
,
2276
scope
=
"
private
"
2277
}
2278 2279
implement
{
2280
name
=
"
forcestrutdepthplus
"
,
2281
arguments
=
{
"
integer
"
,
"
dimension
"
,
"
integer
"
,
true
}
,
2282
actions
=
vspacing
.
forcestrutdepth
,
2283
scope
=
"
private
"
2284
}
2285 2286
implement
{
2287
name
=
"
pushatsame
"
,
2288
actions
=
vspacing
.
pushatsame
,
2289
scope
=
"
private
"
2290
}
2291 2292
implement
{
2293
name
=
"
popatsame
"
,
2294
actions
=
vspacing
.
popatsame
,
2295
scope
=
"
private
"
2296
}
2297 2298
implement
{
2299
name
=
"
vspacingsetamount
"
,
2300
actions
=
vspacing
.
setskip
,
2301
scope
=
"
private
"
,
2302
arguments
=
"
string
"
,
2303
}
2304 2305
implement
{
2306
name
=
"
vspacingdefine
"
,
2307
actions
=
vspacing
.
setmap
,
2308
scope
=
"
private
"
,
2309
arguments
=
"
2 strings
"
,
2310
}
2311 2312
implement
{
2313
name
=
"
vspacingcollapse
"
,
2314
actions
=
vspacing
.
collapsevbox
,
2315
scope
=
"
private
"
,
2316
arguments
=
"
integer
"
2317
}
2318 2319
implement
{
2320
name
=
"
vspacingcollapseonly
"
,
2321
actions
=
vspacing
.
collapsevbox
,
2322
scope
=
"
private
"
,
2323
arguments
=
{
"
integer
"
,
true
}
2324
}
2325 2326
implement
{
2327
name
=
"
vspacingsnap
"
,
2328
actions
=
vspacing
.
snapbox
,
2329
scope
=
"
private
"
,
2330
arguments
=
{
"
integer
"
,
"
integer
"
}
2331
}
2332 2333
implement
{
2334
name
=
"
definesnapmethod
"
,
2335
actions
=
vspacing
.
definesnapmethod
,
2336
scope
=
"
private
"
,
2337
arguments
=
"
2 strings
"
,
2338
}
2339 2340
-- local remove_node = nodes.remove
2341
-- local find_node_tail = nodes.tail
2342
--
2343
-- interfaces.implement {
2344
-- name = "fakenextstrutline",
2345
-- actions = function()
2346
-- local head = texlists.page_head
2347
-- if head then
2348
-- local head = remove_node(head,find_node_tail(head),true)
2349
-- texlists.page_head = head
2350
-- buildpage()
2351
-- end
2352
-- end
2353
-- }
2354 2355
implement
{
2356
name
=
"
removelastline
"
,
2357
actions
=
function
(
)
2358
local
head
=
texlists
.
page_head
2359
if
head
then
2360
local
tail
=
find_node_tail
(
head
)
2361
if
tail
then
2362
-- maybe check for hlist subtype 1
2363
local
head
=
remove_node
(
head
,
tail
,
true
)
2364
texlists
.
page_head
=
head
2365
buildpage
(
)
2366
end
2367
end
2368
end
2369
}
2370 2371
implement
{
2372
name
=
"
showpagelist
"
,
-- will improve
2373
actions
=
function
(
)
2374
local
head
=
texlists
.
page_head
2375
if
head
then
2376
print
(
"
start
"
)
2377
while
head
do
2378
print
(
"
"
.
.
tostring
(
head
)
)
2379
head
=
head
.
next
2380
end
2381
end
2382
end
2383
}
2384 2385
implement
{
2386
name
=
"
pageoverflow
"
,
2387
actions
=
{
vspacing
.
pageoverflow
,
context
}
2388
}
2389 2390
implement
{
2391
name
=
"
forcepageflush
"
,
2392
actions
=
vspacing
.
forcepageflush
2393
}
2394 2395
end
2396