node-rul.lmt /size: 21 Kb    last modification: 2021-10-28 13:51
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
node-rul
'
]
=
{
2
version
=
1
.
001
,
3
optimize
=
true
,
4
comment
=
"
companion to node-rul.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
-- this will go to an auxiliary module
11
-- beware: rules now have a dir field
12
--
13
-- todo: make robust for layers ... order matters
14 15
-- todo: collect successive bit and pieces and combine them
16
--
17
-- path s ; s := shaped(p) ; % p[] has rectangles
18
-- fill s withcolor .5white ;
19
-- draw boundingbox s withcolor yellow;
20 21
local
tonumber
=
tonumber
22 23
local
context
=
context
24
local
attributes
=
attributes
25
local
nodes
=
nodes
26
local
properties
=
nodes
.
properties
.
data
27 28
local
enableaction
=
nodes
.
tasks
.
enableaction
29 30
local
nuts
=
nodes
.
nuts
31
local
tonode
=
nuts
.
tonode
32
local
tonut
=
nuts
.
tonut
33 34
local
setnext
=
nuts
.
setnext
35
local
setprev
=
nuts
.
setprev
36
local
setlink
=
nuts
.
setlink
37
local
getnext
=
nuts
.
getnext
38
local
getprev
=
nuts
.
getprev
39
local
getid
=
nuts
.
getid
40
local
getdirection
=
nuts
.
getdirection
41
local
getattr
=
nuts
.
getattr
42
local
setattr
=
nuts
.
setattr
43
local
setattrs
=
nuts
.
setattrs
44
local
getfont
=
nuts
.
getfont
45
local
getsubtype
=
nuts
.
getsubtype
46
local
getlist
=
nuts
.
getlist
47
local
setwhd
=
nuts
.
setwhd
48
local
setattrlist
=
nuts
.
setattrlist
49
local
setshift
=
nuts
.
setshift
50
local
getwidth
=
nuts
.
getwidth
51
local
setwidth
=
nuts
.
setwidth
52
local
setoffsets
=
nuts
.
setoffsets
53
local
setfield
=
nuts
.
setfield
54
local
getruledata
=
nuts
.
getruledata
55 56
local
isglyph
=
nuts
.
isglyph
57 58
local
flushlist
=
nuts
.
flushlist
59
local
effectiveglue
=
nuts
.
effectiveglue
60
local
insertnodeafter
=
nuts
.
insertafter
61
local
insertnodebefore
=
nuts
.
insertbefore
62
local
find_tail
=
nuts
.
tail
63
local
setglue
=
nuts
.
setglue
64
local
getrangedimensions
=
nuts
.
rangedimensions
65
local
hpack_nodes
=
nuts
.
hpack
66
local
copylist
=
nuts
.
copylist
67 68
local
nextlist
=
nuts
.
traversers
.
list
69
local
nextglue
=
nuts
.
traversers
.
glue
70 71
local
nodecodes
=
nodes
.
nodecodes
72
local
rulecodes
=
nodes
.
rulecodes
73
local
gluecodes
=
nodes
.
gluecodes
74
local
listcodes
=
nodes
.
listcodes
75 76
local
glyph_code
=
nodecodes
.
glyph
77
local
par_code
=
nodecodes
.
par
78
local
dir_code
=
nodecodes
.
dir
79
local
glue_code
=
nodecodes
.
glue
80
local
hlist_code
=
nodecodes
.
hlist
81 82
local
indentlist_code
=
listcodes
.
indent
83
local
linelist_code
=
listcodes
.
line
84 85
local
leftskip_code
=
gluecodes
.
leftskip
86
local
rightskip_code
=
gluecodes
.
rightskip
87
local
parfillleftskip_code
=
gluecodes
.
parfillleftskip
88
local
parfillrightskip_code
=
gluecodes
.
parfillrightskip
89
local
indentskip_code
=
gluecodes
.
indentskip
90 91
local
nodepool
=
nuts
.
pool
92 93
local
new_rule
=
nodepool
.
rule
94
local
new_userrule
=
nodepool
.
userrule
95
local
new_kern
=
nodepool
.
kern
96
local
new_leader
=
nodepool
.
leader
97 98
local
n_tostring
=
nodes
.
idstostring
99
local
n_tosequence
=
nodes
.
tosequence
100 101
local
variables
=
interfaces
.
variables
102
local
implement
=
interfaces
.
implement
103 104
local
privateattributes
=
attributes
.
private
105 106
local
a_ruled
=
privateattributes
(
'
ruled
'
)
107
local
a_runningtext
=
privateattributes
(
'
runningtext
'
)
108
local
a_color
=
privateattributes
(
'
color
'
)
109
local
a_transparency
=
privateattributes
(
'
transparency
'
)
110
local
a_colormodel
=
privateattributes
(
'
colormodel
'
)
111
local
a_linefiller
=
privateattributes
(
"
linefiller
"
)
112
local
a_viewerlayer
=
privateattributes
(
"
viewerlayer
"
)
113 114
local
v_both
=
variables
.
both
115
local
v_left
=
variables
.
left
116
local
v_right
=
variables
.
right
117
local
v_local
=
variables
[
"
local
"
]
118
local
v_yes
=
variables
.
yes
119
local
v_foreground
=
variables
.
foreground
120 121
local
fonthashes
=
fonts
.
hashes
122
local
fontdata
=
fonthashes
.
identifiers
123
local
fontresources
=
fonthashes
.
resources
124 125
local
dimenfactor
=
fonts
.
helpers
.
dimenfactor
126
local
splitdimen
=
number
.
splitdimen
127
local
setmetatableindex
=
table
.
setmetatableindex
128 129
local
runningrule
=
tex
.
magicconstants
.
runningrule
130 131
local
striprange
=
nuts
.
striprange
132
local
processwords
=
nuts
.
processwords
133 134
local
setcoloring
=
nuts
.
colors
.
set
135 136
local
rules
=
nodes
.
rules
or
{
}
137
nodes
.
rules
=
rules
138
rules
.
data
=
rules
.
data
or
{
}
139 140
local
nutrules
=
nuts
.
rules
or
{
}
141
nuts
.
rules
=
nutrules
-- not that many
142 143
storage
.
register
(
"
nodes/rules/data
"
,
rules
.
data
,
"
nodes.rules.data
"
)
144 145
local
data
=
rules
.
data
146 147
-- we implement user rules here as it takes less code this way
148 149
local
function
usernutrule
(
t
,
noattributes
)
150
local
r
=
new_userrule
(
t
.
width
or
0
,
t
.
height
or
0
,
t
.
depth
or
0
)
151
if
noattributes
=
=
false
or
noattributes
=
=
nil
then
152
-- avoid fuzzy ones
153
else
154
setattrlist
(
r
,
true
)
155
end
156
properties
[
r
]
=
t
157
return
r
158
end
159 160
nutrules
.
userrule
=
usernutrule
161 162
local
function
userrule
(
t
,
noattributes
)
163
return
tonode
(
usernutrule
(
t
,
noattributes
)
)
164
end
165 166
rules
.
userrule
=
userrule
167
local
ruleactions
=
{
}
168 169
rules
.
ruleactions
=
ruleactions
170
nutrules
.
ruleactions
=
ruleactions
-- convenient
171 172
local
function
mathaction
(
n
,
h
,
v
,
what
)
173
local
font
=
getruledata
(
n
)
174
local
actions
=
fontresources
[
font
]
.
mathruleactions
175
if
actions
then
176
local
action
=
actions
[
what
]
177
if
action
then
178
action
(
n
,
h
,
v
,
font
)
179
end
180
end
181
end
182 183
local
function
mathradical
(
n
,
h
,
v
)
184
mathaction
(
n
,
h
,
v
,
"
radicalaction
"
)
185
end
186 187
local
function
mathrule
(
n
,
h
,
v
)
188
mathaction
(
n
,
h
,
v
,
"
hruleaction
"
)
189
end
190 191
local
x
192 193
local
function
useraction
(
n
,
h
,
v
)
194
local
p
=
properties
[
n
]
195
if
p
then
196
local
i
=
p
.
type
or
"
draw
"
197
local
a
=
ruleactions
[
i
]
198
if
a
then
199
a
(
p
,
h
,
v
,
i
,
n
)
200
end
201
end
202
end
203 204
local
subtypeactions
=
{
205
[
rulecodes
.
user
]
=
useraction
,
206
[
rulecodes
.
over
]
=
mathrule
,
207
[
rulecodes
.
under
]
=
mathrule
,
208
[
rulecodes
.
fraction
]
=
mathrule
,
209
[
rulecodes
.
radical
]
=
mathradical
,
210
}
211 212
function
rules
.
process
(
n
,
h
,
v
)
213
local
n
=
tonut
(
n
)
-- already a nut
214
local
s
=
getsubtype
(
n
)
215
local
a
=
subtypeactions
[
s
]
216
if
a
then
217
a
(
n
,
h
,
v
)
218
end
219
end
220 221
--
222 223
local
trace_ruled
=
false
trackers
.
register
(
"
nodes.rules
"
,
function
(
v
)
trace_ruled
=
v
end
)
224
local
report_ruled
=
logs
.
reporter
(
"
nodes
"
,
"
rules
"
)
225 226
function
rules
.
define
(
settings
)
227
local
nofdata
=
#
data
+
1
228
data
[
nofdata
]
=
settings
229
local
text
=
settings
.
text
230
if
text
then
231
local
b
=
nuts
.
takebox
(
text
)
232
if
b
then
233
nodepool
.
register
(
b
)
234
settings
.
text
=
getlist
(
b
)
235
else
236
settings
.
text
=
nil
237
end
238
end
239
return
nofdata
240
end
241 242
local
function
flush_ruled
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
-- not that fast but acceptable for this purpose
243
local
font
=
nil
244
local
char
,
id
=
isglyph
(
f
)
245
if
char
then
246
font
=
id
247
elseif
id
=
=
hlist_code
then
248
font
=
getattr
(
f
,
a_runningtext
)
249
end
250
if
not
font
then
251
-- saveguard ... we need to deal with rules and so (math)
252
return
head
253
end
254
local
r
,
m
255
if
strip
then
256
if
trace_ruled
then
257
local
before
=
n_tosequence
(
f
,
l
,
true
)
258
f
,
l
=
striprange
(
f
,
l
)
259
local
after
=
n_tosequence
(
f
,
l
,
true
)
260
report_ruled
(
"
range stripper, before %a, after %a
"
,
before
,
after
)
261
else
262
f
,
l
=
striprange
(
f
,
l
)
263
end
264
end
265
if
not
f
then
266
return
head
267
end
268
local
wd
,
ht
,
dp
=
getrangedimensions
(
parent
,
f
,
getnext
(
l
)
)
269
local
method
=
d
.
method
270
local
empty
=
d
.
empty
=
=
v_yes
271
local
offset
=
d
.
offset
272
local
dy
=
d
.
dy
273
local
order
=
d
.
order
274
local
max
=
d
.
max
275
local
mp
=
d
.
mp
276
local
rulethickness
=
d
.
rulethickness
277
local
unit
=
d
.
unit
278
local
ma
=
d
.
ma
279
local
ca
=
d
.
ca
280
local
ta
=
d
.
ta
281
local
colorspace
=
ma
>
0
and
ma
or
getattr
(
f
,
a_colormodel
)
or
1
282
local
color
=
ca
>
0
and
ca
or
getattr
(
f
,
a_color
)
283
local
transparency
=
ta
>
0
and
ta
or
getattr
(
f
,
a_transparency
)
284
local
foreground
=
order
=
=
v_foreground
285
local
layer
=
getattr
(
f
,
a_viewerlayer
)
286
local
e
=
dimenfactor
(
unit
,
font
)
-- what if no glyph node
287
local
rt
=
tonumber
(
rulethickness
)
288
if
rt
then
289
rulethickness
=
e
*
rulethickness
/
2
290
else
291
local
n
,
u
=
splitdimen
(
rulethickness
)
292
if
n
and
u
then
-- we need to intercept ex and em and % and ...
293
rulethickness
=
n
*
dimenfactor
(
u
,
fontdata
[
font
]
)
/
2
294
else
295
rulethickness
=
1
/
5
296
end
297
end
298
--
299
if
level
>
max
then
300
level
=
max
301
end
302
if
method
=
=
0
then
-- center
303
offset
=
2
*
offset
304
m
=
(
offset
+
(
level
-1
)
*
dy
)
*
e
/
2
+
rulethickness
/
2
305
else
306
m
=
0
307
end
308 309
local
function
inject
(
r
,
wd
,
ht
,
dp
)
310
if
layer
then
311
setattr
(
r
,
a_viewerlayer
,
layer
)
312
end
313
if
empty
then
314
head
=
insertnodebefore
(
head
,
f
,
r
)
315
setlink
(
r
,
getnext
(
l
)
)
316
setprev
(
f
)
317
setnext
(
l
)
318
flushlist
(
f
)
319
else
320
local
k
=
new_kern
(
-
wd
)
321
if
foreground
then
322
insertnodeafter
(
head
,
l
,
k
)
323
insertnodeafter
(
head
,
k
,
r
)
324
l
=
r
325
else
326
head
=
insertnodebefore
(
head
,
f
,
r
)
327
insertnodeafter
(
head
,
r
,
k
)
328
end
329
end
330
if
trace_ruled
then
331
report_ruled
(
"
level %a, width %p, height %p, depth %p, nodes %a, text %a
"
,
332
level
,
wd
,
ht
,
dp
,
n_tostring
(
f
,
l
)
,
n_tosequence
(
f
,
l
,
true
)
)
333
end
334
end
335 336
if
mp
and
mp
~
=
"
"
then
337
local
r
=
usernutrule
{
338
width
=
wd
,
339
height
=
ht
,
340
depth
=
dp
,
341
type
=
"
mp
"
,
342
factor
=
e
,
343
offset
=
offset
,
344
line
=
rulethickness
,
345
data
=
mp
,
346
ma
=
colorspace
,
347
ca
=
color
,
348
ta
=
transparency
,
349
}
350
inject
(
r
,
wd
,
ht
,
dp
)
351
else
352
local
tx
=
d
.
text
353
if
tx
then
354
local
l
=
copylist
(
tx
)
355
if
d
[
"
repeat
"
]
=
=
v_yes
then
356
l
=
new_leader
(
wd
,
l
)
357
setattrlist
(
l
,
tx
)
358
end
359
l
=
hpack_nodes
(
l
,
wd
,
"
exactly
"
)
360
inject
(
l
,
wd
,
ht
,
dp
)
361
else
362
for
i
=
1
,
level
do
363
local
hd
=
(
offset
+
(
i
-1
)
*
dy
)
*
e
-
m
364
local
ht
=
hd
+
rulethickness
365
local
dp
=
-
hd
+
rulethickness
366
inject
(
setcoloring
(
new_rule
(
wd
,
ht
,
dp
)
,
colorspace
,
color
,
transparency
)
,
wd
,
ht
,
dp
)
367
end
368
end
369
end
370
return
head
371
end
372 373
rules
.
handler
=
function
(
head
)
374
return
processwords
(
a_ruled
,
data
,
flush_ruled
,
head
)
375
end
376 377
function
rules
.
enable
(
)
378
enableaction
(
"
shipouts
"
,
"
nodes.rules.handler
"
)
379
end
380 381
local
trace_shifted
=
false
trackers
.
register
(
"
nodes.shifting
"
,
function
(
v
)
trace_shifted
=
v
end
)
382 383
local
report_shifted
=
logs
.
reporter
(
"
nodes
"
,
"
shifting
"
)
384 385
local
a_shifted
=
attributes
.
private
(
'
shifted
'
)
386 387
local
shifts
=
nodes
.
shifts
or
{
}
388
nodes
.
shifts
=
shifts
389
shifts
.
data
=
shifts
.
data
or
{
}
390 391
storage
.
register
(
"
nodes/shifts/data
"
,
shifts
.
data
,
"
nodes.shifts.data
"
)
392 393
local
data
=
shifts
.
data
394 395
function
shifts
.
define
(
settings
)
396
local
nofdata
=
#
data
+
1
397
data
[
nofdata
]
=
settings
398
return
nofdata
399
end
400 401
local
function
flush_shifted
(
head
,
first
,
last
,
data
,
level
,
parent
,
strip
)
-- not that fast but acceptable for this purpose
402
if
true
then
403
first
,
last
=
striprange
(
first
,
last
)
404
end
405
local
prev
=
getprev
(
first
)
406
local
next
=
getnext
(
last
)
407
setprev
(
first
)
408
setnext
(
last
)
409
local
width
,
height
,
depth
=
getrangedimensions
(
parent
,
first
,
next
)
410
local
list
=
hpack_nodes
(
first
,
width
,
"
exactly
"
)
-- we can use a simple pack
411
if
first
=
=
head
then
412
head
=
list
413
end
414
if
prev
then
415
setlink
(
prev
,
list
)
416
end
417
if
next
then
418
setlink
(
list
,
next
)
419
end
420
local
raise
=
data
.
dy
*
dimenfactor
(
data
.
unit
,
fontdata
[
getfont
(
first
)
]
)
421
setshift
(
list
,
raise
)
422
setwhd
(
list
,
width
,
height
,
depth
)
423
if
trace_shifted
then
424
report_shifted
(
"
width %p, nodes %a, text %a
"
,
width
,
n_tostring
(
first
,
last
)
,
n_tosequence
(
first
,
last
,
true
)
)
425
end
426
return
head
427
end
428 429
shifts
.
handler
=
function
(
head
)
430
return
processwords
(
a_shifted
,
data
,
flush_shifted
,
head
)
431
end
432 433
function
shifts
.
enable
(
)
434
enableaction
(
"
shipouts
"
,
"
nodes.shifts.handler
"
)
435
end
436 437
-- linefillers
438 439
local
linefillers
=
nodes
.
linefillers
or
{
}
440
nodes
.
linefillers
=
linefillers
441
linefillers
.
data
=
linefillers
.
data
or
{
}
442 443
storage
.
register
(
"
nodes/linefillers/data
"
,
linefillers
.
data
,
"
nodes.linefillers.data
"
)
444 445
local
data
=
linefillers
.
data
446 447
function
linefillers
.
define
(
settings
)
448
local
nofdata
=
#
data
+
1
449
data
[
nofdata
]
=
settings
450
return
nofdata
451
end
452 453
local
function
linefiller
(
current
,
data
,
width
,
location
)
454
local
height
=
data
.
height
455
local
depth
=
data
.
depth
456
local
mp
=
data
.
mp
457
local
ma
=
data
.
ma
458
local
ca
=
data
.
ca
459
local
ta
=
data
.
ta
460
if
mp
and
mp
~
=
"
"
then
461
return
usernutrule
{
462
width
=
width
,
463
height
=
height
,
464
depth
=
depth
,
465
type
=
"
mp
"
,
466
line
=
data
.
rulethickness
,
467
data
=
mp
,
468
ma
=
ma
,
469
ca
=
ca
,
470
ta
=
ta
,
471
option
=
location
,
472
direction
=
getdirection
(
current
)
,
473
}
474
else
475
return
setcoloring
(
new_rule
(
width
,
height
,
depth
)
,
ma
,
ca
,
ta
)
476
end
477
end
478 479
function
linefillers
.
filler
(
current
,
data
,
width
,
height
,
depth
)
480
if
width
and
width
>
0
then
481
local
height
=
height
or
data
.
height
or
0
482
local
depth
=
depth
or
data
.
depth
or
0
483
if
(
height
+
depth
)
~
=
0
then
484
local
mp
=
data
.
mp
485
local
ma
=
data
.
ma
486
local
ca
=
data
.
ca
487
local
ta
=
data
.
ta
488
if
mp
and
mp
~
=
"
"
then
489
return
usernutrule
{
490
width
=
width
,
491
height
=
height
,
492
depth
=
depth
,
493
type
=
"
mp
"
,
494
line
=
data
.
rulethickness
,
495
data
=
mp
,
496
ma
=
ma
,
497
ca
=
ca
,
498
ta
=
ta
,
499
option
=
location
,
500
direction
=
getdirection
(
current
)
,
501
}
502
else
503
return
setcoloring
(
new_rule
(
width
,
height
,
depth
)
,
ma
,
ca
,
ta
)
504
end
505
end
506
end
507
end
508 509
local
function
getskips
(
list
)
-- this could be a helper
510
local
ls
=
nil
511
local
rs
=
nil
512
local
is
=
nil
513
local
pl
=
nil
514
local
pr
=
nil
515
local
ok
=
false
516
for
n
,
subtype
in
nextglue
,
list
do
517
if
subtype
=
=
rightskip_code
then
518
rs
=
n
519
elseif
subtype
=
=
parfillrightskip_code
then
520
pr
=
n
521
elseif
subtype
=
=
leftskip_code
then
522
ls
=
n
523
elseif
subtype
=
=
indentskip_code
then
524
is
=
n
525
elseif
subtype
=
=
parfillleftskip_code
then
526
pl
=
n
527
end
528
end
529
return
is
,
ls
,
pl
,
pr
,
rs
530
end
531 532
function
linefillers
.
handler
(
head
)
533
-- we have a normalized line ..
534
for
current
,
id
,
subtype
,
list
in
nextlist
,
head
do
535
if
subtype
=
=
linelist_code
and
list
then
536
local
a
=
getattr
(
current
,
a_linefiller
)
537
if
a
then
538
local
class
=
a
%
1000
539
local
data
=
data
[
class
]
540
if
data
then
541
local
location
=
data
.
location
542
local
scope
=
data
.
scope
543
local
distance
=
data
.
distance
544
local
threshold
=
data
.
threshold
545
local
leftlocal
=
false
546
local
rightlocal
=
false
547
--
548
if
scope
=
=
v_right
then
549
leftlocal
=
true
550
elseif
scope
=
=
v_left
then
551
rightlocal
=
true
552
elseif
scope
=
=
v_local
then
553
leftlocal
=
true
554
rightlocal
=
true
555
end
556
--
557
local
is
,
ls
,
pl
,
pr
,
rs
=
getskips
(
list
)
558
if
ls
and
rs
then
559
if
location
=
=
v_left
or
location
=
=
v_both
then
560
local
indentation
=
is
and
getwidth
(
is
)
or
0
561
local
leftfixed
=
ls
and
getwidth
(
ls
)
or
0
562
local
lefttotal
=
ls
and
effectiveglue
(
ls
,
current
)
or
0
563
local
width
=
lefttotal
-
(
leftlocal
and
leftfixed
or
0
)
+
indentation
-
distance
564
if
width
>
threshold
then
565
if
is
then
566
setwidth
(
is
,
0
)
567
end
568
setglue
(
ls
,
leftlocal
and
getwidth
(
ls
)
or
nil
)
569
if
distance
>
0
then
570
insertnodeafter
(
list
,
ls
,
new_kern
(
distance
)
)
571
end
572
insertnodeafter
(
list
,
ls
,
linefiller
(
current
,
data
,
width
,
"
left
"
)
)
573
end
574
end
575
--
576
if
location
=
=
v_right
or
location
=
=
v_both
then
577
local
rightfixed
=
rs
and
getwidth
(
rs
)
or
0
578
local
righttotal
=
rs
and
effectiveglue
(
rs
,
current
)
or
0
579
local
parfixed
=
pr
and
getwidth
(
pr
)
or
0
580
local
partotal
=
pr
and
effectiveglue
(
pr
,
current
)
or
0
581
local
width
=
righttotal
-
(
rightlocal
and
rightfixed
or
0
)
+
partotal
-
distance
582
if
width
>
threshold
then
583
if
pr
then
584
setglue
(
pr
)
585
end
586
setglue
(
rs
,
rightlocal
and
getwidth
(
rs
)
or
nil
)
587
if
distance
>
0
then
588
insertnodebefore
(
list
,
rs
,
new_kern
(
distance
)
)
589
end
590
insertnodebefore
(
list
,
rs
,
linefiller
(
current
,
data
,
width
,
"
right
"
)
)
591
end
592
end
593
else
594
-- error, not a properly normalized line
595
end
596
end
597
end
598
end
599
end
600
return
head
601
end
602 603
local
enable
=
false
604 605
function
linefillers
.
enable
(
)
606
if
not
enable
then
607
-- we could now nil it
608
enableaction
(
"
finalizers
"
,
"
nodes.linefillers.handler
"
)
609
enable
=
true
610
end
611
end
612 613
-- interface
614 615
implement
{
616
name
=
"
definerule
"
,
617
actions
=
{
rules
.
define
,
context
}
,
618
arguments
=
{
619
{
620
{
"
continue
"
}
,
621
{
"
unit
"
}
,
622
{
"
order
"
}
,
623
{
"
method
"
,
"
integer
"
}
,
624
{
"
offset
"
,
"
number
"
}
,
625
{
"
rulethickness
"
}
,
626
{
"
dy
"
,
"
number
"
}
,
627
{
"
max
"
,
"
number
"
}
,
628
{
"
ma
"
,
"
integer
"
}
,
629
{
"
ca
"
,
"
integer
"
}
,
630
{
"
ta
"
,
"
integer
"
}
,
631
{
"
mp
"
}
,
632
{
"
empty
"
}
,
633
{
"
text
"
,
"
integer
"
}
,
634
{
"
repeat
"
}
,
635
}
636
}
637
}
638 639
implement
{
640
name
=
"
enablerules
"
,
641
onlyonce
=
true
,
642
actions
=
rules
.
enable
643
}
644 645
implement
{
646
name
=
"
defineshift
"
,
647
actions
=
{
shifts
.
define
,
context
}
,
648
arguments
=
{
649
{
650
{
"
continue
"
}
,
651
{
"
unit
"
}
,
652
{
"
method
"
,
"
integer
"
}
,
653
{
"
dy
"
,
"
number
"
}
,
654
}
655
}
656
}
657 658
implement
{
659
name
=
"
enableshifts
"
,
660
onlyonce
=
true
,
661
actions
=
shifts
.
enable
662
}
663 664
implement
{
665
name
=
"
definelinefiller
"
,
666
actions
=
{
linefillers
.
define
,
context
}
,
667
arguments
=
{
668
{
669
{
"
method
"
,
"
integer
"
}
,
670
{
"
location
"
,
"
string
"
}
,
671
{
"
scope
"
,
"
string
"
}
,
672
{
"
mp
"
,
"
string
"
}
,
673
{
"
ma
"
,
"
integer
"
}
,
674
{
"
ca
"
,
"
integer
"
}
,
675
{
"
ta
"
,
"
integer
"
}
,
676
{
"
depth
"
,
"
dimension
"
}
,
677
{
"
height
"
,
"
dimension
"
}
,
678
{
"
distance
"
,
"
dimension
"
}
,
679
{
"
threshold
"
,
"
dimension
"
}
,
680
{
"
rulethickness
"
,
"
dimension
"
}
,
681
}
682
}
683
}
684 685
implement
{
686
name
=
"
enablelinefillers
"
,
687
onlyonce
=
true
,
688
actions
=
linefillers
.
enable
689
}
690 691
-- We add a bonus feature here (experiment):
692 693
interfaces
.
implement
{
694
name
=
"
autorule
"
,
695
arguments
=
{
696
{
697
{
"
width
"
,
"
dimension
"
}
,
698
{
"
height
"
,
"
dimension
"
}
,
699
{
"
depth
"
,
"
dimension
"
}
,
700
{
"
xoffset
"
,
"
dimension
"
}
,
701
{
"
yoffset
"
,
"
dimension
"
}
,
702
{
"
left
"
,
"
dimension
"
}
,
703
{
"
right
"
,
"
dimension
"
}
,
704
}
,
705
}
,
706
actions
=
function
(
t
)
707
local
n
=
new_rule
(
708
t
.
width
or
runningrule
,
709
t
.
height
or
runningrule
,
710
t
.
depth
or
runningrule
711
)
712
setattrlist
(
n
,
true
)
713
setoffsets
(
n
,
t
.
xoffset
,
t
.
yoffset
)
-- ,t.left, t.right
714
local
l
=
t
.
left
715
local
r
=
t
.
right
716
if
l
then
717
setfield
(
n
,
"
left
"
,
l
)
718
end
719
if
r
then
720
setfield
(
n
,
"
right
"
,
r
)
721
end
722
context
(
tonode
(
n
)
)
723
end
724
}
725