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