strc-not.lua /size: 14 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
strc-not
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to strc-not.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
local
format
=
string
.
format
10
local
next
=
next
11 12
local
trace_notes
=
false
trackers
.
register
(
"
structures.notes
"
,
function
(
v
)
trace_notes
=
v
end
)
13
local
trace_references
=
false
trackers
.
register
(
"
structures.notes.references
"
,
function
(
v
)
trace_references
=
v
end
)
14 15
local
report_notes
=
logs
.
reporter
(
"
structure
"
,
"
notes
"
)
16 17
local
structures
=
structures
18
local
helpers
=
structures
.
helpers
19
local
lists
=
structures
.
lists
20
local
sections
=
structures
.
sections
21
local
counters
=
structures
.
counters
22
local
notes
=
structures
.
notes
23
local
references
=
structures
.
references
24
local
counterspecials
=
counters
.
specials
25 26
local
texgetcount
=
tex
.
getcount
27
local
texgetbox
=
tex
.
getbox
28 29
-- todo: allocate
30 31
notes
.
states
=
notes
.
states
or
{
}
32
lists
.
enhancers
=
lists
.
enhancers
or
{
}
33
notes
.
numbers
=
notes
.
numbers
or
{
}
34 35
storage
.
register
(
"
structures/notes/states
"
,
notes
.
states
,
"
structures.notes.states
"
)
36
storage
.
register
(
"
structures/notes/numbers
"
,
notes
.
numbers
,
"
structures.notes.numbers
"
)
37 38
local
notestates
=
notes
.
states
39
local
notedata
=
table
.
setmetatableindex
(
"
table
"
)
40 41
local
variables
=
interfaces
.
variables
42
local
context
=
context
43
local
commands
=
commands
44 45
local
implement
=
interfaces
.
implement
46 47
-- state: store, insert, postpone
48 49
local
function
store
(
tag
,
n
)
50
-- somewhat weird but this is a cheap hook spot
51
if
not
counterspecials
[
tag
]
then
52
counterspecials
[
tag
]
=
function
(
tag
)
53
context
.
doresetlinenotecompression
(
tag
)
-- maybe flag that controls it
54
end
55
end
56
--
57
local
nd
=
notedata
[
tag
]
58
local
nnd
=
#
nd
+
1
59
nd
[
nnd
]
=
n
60
local
state
=
notestates
[
tag
]
61
if
not
state
then
62
report_notes
(
"
unknown state for %a
"
,
tag
)
63
elseif
state
.
kind
~
=
"
insert
"
then
64
if
trace_notes
then
65
report_notes
(
"
storing %a with state %a as %a
"
,
tag
,
state
.
kind
,
nnd
)
66
end
67
state
.
start
=
state
.
start
or
nnd
68
end
69
return
nnd
70
end
71 72
notes
.
store
=
store
73 74
implement
{
75
name
=
"
storenote
"
,
76
actions
=
{
store
,
context
}
,
77
arguments
=
{
"
string
"
,
"
integer
"
}
78
}
79 80
local
function
get
(
tag
,
n
)
-- tricky ... only works when defined
81
local
nd
=
notedata
[
tag
]
82
if
not
n
then
83
n
=
#
nd
84
end
85
nd
=
nd
[
n
]
86
if
nd
then
87
if
trace_notes
then
88
report_notes
(
"
getting note %a of %a with listindex %a
"
,
n
,
tag
,
nd
)
89
end
90
-- is this right?
91
local
newdata
=
lists
.
cached
[
nd
]
92
return
newdata
93
end
94
end
95 96
local
function
getn
(
tag
)
97
return
#
notedata
[
tag
]
98
end
99 100
notes
.
get
=
get
101
notes
.
getn
=
getn
102 103
-- we could make a special enhancer
104 105
local
function
listindex
(
tag
,
n
)
106
local
ndt
=
notedata
[
tag
]
107
return
ndt
and
ndt
[
n
]
108
end
109 110
notes
.
listindex
=
listindex
111 112
implement
{
113
name
=
"
notelistindex
"
,
114
actions
=
{
listindex
,
context
}
,
115
arguments
=
{
"
string
"
,
"
integer
"
}
116
}
117 118
local
function
setstate
(
tag
,
newkind
)
119
local
state
=
notestates
[
tag
]
120
if
trace_notes
then
121
report_notes
(
"
setting state of %a from %s to %s
"
,
tag
,
(
state
and
state
.
kind
)
or
"
unset
"
,
newkind
)
122
end
123
if
not
state
then
124
state
=
{
125
kind
=
newkind
126
}
127
notestates
[
tag
]
=
state
128
elseif
newkind
=
=
"
insert
"
then
129
if
not
state
.
start
then
130
state
.
kind
=
newkind
131
end
132
else
133
-- if newkind == "postpone" and state.kind == "store" then
134
-- else
135
state
.
kind
=
newkind
136
-- end
137
end
138
-- state.start can already be set and will be set when an entry is added or flushed
139
return
state
140
end
141 142
local
function
getstate
(
tag
)
143
local
state
=
notestates
[
tag
]
144
return
state
and
state
.
kind
or
"
unknown
"
145
end
146 147
notes
.
setstate
=
setstate
148
notes
.
getstate
=
getstate
149 150 151 152
implement
{
153
name
=
"
setnotestate
"
,
154
actions
=
setstate
,
155
arguments
=
"
2 strings
"
,
156
}
157 158
implement
{
159
name
=
"
getnotestate
"
,
160
actions
=
{
getstate
,
context
}
,
161
arguments
=
"
string
"
162
}
163 164
function
notes
.
define
(
tag
,
kind
,
number
)
165
local
state
=
setstate
(
tag
,
kind
)
166
notes
.
numbers
[
number
]
=
state
167
state
.
number
=
number
168
end
169 170
implement
{
171
name
=
"
definenote
"
,
172
actions
=
notes
.
define
,
173
arguments
=
{
"
string
"
,
"
string
"
,
"
integer
"
}
174
}
175 176
function
notes
.
save
(
tag
,
newkind
)
177
local
state
=
notestates
[
tag
]
178
if
state
and
not
state
.
saved
then
179
if
trace_notes
then
180
report_notes
(
"
saving state of %a, old: %a, new %a
"
,
tag
,
state
.
kind
,
newkind
or
state
.
kind
)
181
end
182
state
.
saveddata
=
notedata
[
tag
]
183
state
.
savedkind
=
state
.
kind
184
state
.
kind
=
newkind
or
state
.
kind
185
state
.
saved
=
true
186
notedata
[
tag
]
=
{
}
187
end
188
end
189 190
function
notes
.
restore
(
tag
,
forcedstate
)
191
local
state
=
notestates
[
tag
]
192
if
state
and
state
.
saved
then
193
if
trace_notes
then
194
report_notes
(
"
restoring state of %a, old: %a, new: %a
"
,
tag
,
state
.
kind
,
state
.
savedkind
)
195
end
196
notedata
[
tag
]
=
state
.
saveddata
197
state
.
kind
=
forcedstate
or
state
.
savedkind
198
state
.
saveddata
=
nil
199
state
.
saved
=
false
200
end
201
end
202 203
implement
{
name
=
"
savenote
"
,
actions
=
notes
.
save
,
arguments
=
"
2 strings
"
}
204
implement
{
name
=
"
restorenote
"
,
actions
=
notes
.
restore
,
arguments
=
"
2 strings
"
}
205 206
local
function
hascontent
(
tag
)
207
local
ok
=
notestates
[
tag
]
208
if
ok
then
209
if
ok
.
kind
=
=
"
insert
"
then
210
ok
=
texgetbox
(
ok
.
number
)
211
if
ok
then
212
ok
=
tbs
.
list
213
ok
=
lst
and
lst
.
next
214
end
215
else
216
ok
=
ok
.
start
217
end
218
end
219
return
ok
and
true
or
false
220
end
221 222
notes
.
hascontent
=
hascontent
223 224
implement
{
225
name
=
"
doifnotecontent
"
,
226
actions
=
{
hascontent
,
commands
.
doif
}
,
227
arguments
=
"
string
"
,
228
}
229 230
local
function
internal
(
tag
,
n
)
231
local
nd
=
get
(
tag
,
n
)
232
if
nd
then
233
local
r
=
nd
.
references
234
if
r
then
235
local
i
=
r
.
internal
236
return
i
and
references
.
internals
[
i
]
-- dependency on references
237
end
238
end
239
return
nil
240
end
241 242
local
function
ordered
(
kind
,
name
,
n
)
243
local
o
=
lists
.
ordered
[
kind
]
244
o
=
o
and
o
[
name
]
245
return
o
and
o
[
n
]
246
end
247 248
notes
.
internal
=
internal
249
notes
.
ordered
=
ordered
250 251
-- local function onsamepageasprevious(tag)
252
-- local same = false
253
-- local n = getn(tag,n)
254
-- local current = get(tag,n)
255
-- local previous = get(tag,n-1)
256
-- if current and previous then
257
-- local cr = current.references
258
-- local pr = previous.references
259
-- same = cr and pr and cr.realpage == pr.realpage
260
-- end
261
-- return same and true or false
262
-- end
263 264
local
function
onsamepageasprevious
(
tag
)
265
local
n
=
getn
(
tag
,
n
)
266
local
current
=
get
(
tag
,
n
)
267
if
not
current
then
268
return
false
269
end
270
local
cr
=
current
.
references
271
if
not
cr
then
272
return
false
273
end
274
local
previous
=
get
(
tag
,
n
-1
)
275
if
not
previous
then
276
return
false
277
end
278
local
pr
=
previous
.
references
279
if
not
pr
then
280
return
false
281
end
282
return
cr
.
realpage
=
=
pr
.
realpage
283
end
284 285
notes
.
doifonsamepageasprevious
=
onsamepageasprevious
286 287
implement
{
288
name
=
"
doifnoteonsamepageasprevious
"
,
289
actions
=
{
onsamepageasprevious
,
commands
.
doifelse
}
,
290
arguments
=
"
string
"
,
291
}
292 293
function
notes
.
checkpagechange
(
tag
)
-- called before increment !
294
local
nd
=
notedata
[
tag
]
-- can be unset at first entry
295
if
nd
then
296
local
current
=
ordered
(
"
note
"
,
tag
,
#
nd
)
297
local
nextone
=
ordered
(
"
note
"
,
tag
,
#
nd
+
1
)
298
if
nextone
then
299
-- we can use data from the previous pass
300
if
nextone
.
pagenumber
.
number
>
current
.
pagenumber
.
number
then
301
counters
.
reset
(
tag
)
302
end
303
elseif
current
then
304
-- we need to locate the next one, best guess
305
if
texgetcount
(
"
realpageno
"
)
>
current
.
pagenumber
.
number
then
306
counters
.
reset
(
tag
)
307
end
308
end
309
end
310
end
311 312
function
notes
.
postpone
(
)
313
if
trace_notes
then
314
report_notes
(
"
postponing all insert notes
"
)
315
end
316
for
tag
,
state
in
next
,
notestates
do
317
if
state
.
kind
~
=
"
store
"
then
318
setstate
(
tag
,
"
postpone
"
)
319
end
320
end
321
end
322 323
implement
{
324
name
=
"
postponenotes
"
,
325
actions
=
notes
.
postpone
326
}
327 328
local
function
getinternal
(
tag
,
n
)
329
local
li
=
internal
(
tag
,
n
)
330
if
li
then
331
local
references
=
li
.
references
332
if
references
then
333
return
references
.
internal
or
0
334
end
335
end
336
return
0
337
end
338 339
local
function
getdeltapage
(
tag
,
n
)
340
-- 0:unknown 1:textbefore, 2:textafter, 3:samepage
341
local
li
=
internal
(
tag
,
n
)
342
if
li
then
343
local
references
=
li
.
references
344
if
references
then
345
-- local symb = structures.references.collected[""]["symb:"..tag..":"..n]
346
local
rymb
=
structures
.
references
.
collected
[
"
"
]
347
local
symb
=
rymb
and
rymb
[
"
*
"
.
.
(
references
.
internal
or
0
)
]
348
local
notepage
=
references
.
realpage
or
0
349
local
symbolpage
=
symb
and
symb
.
references
.
realpage
or
-1
350
if
trace_references
then
351
report_notes
(
"
note number %a of %a points from page %a to page %a
"
,
n
,
tag
,
symbolpage
,
notepage
)
352
end
353
if
notepage
<
symbolpage
then
354
return
3
-- after
355
elseif
notepage
>
symbolpage
then
356
return
2
-- before
357
elseif
notepage
>
0
then
358
return
1
-- same
359
end
360
else
361
-- might be a note that is not flushed due to to deep
362
-- nesting in a vbox
363
end
364
end
365
return
0
366
end
367 368
notes
.
getinternal
=
getinternal
369
notes
.
getdeltapage
=
getdeltapage
370 371
implement
{
name
=
"
noteinternal
"
,
actions
=
{
getinternal
,
context
}
,
arguments
=
{
"
string
"
,
"
integer
"
}
}
372
implement
{
name
=
"
notedeltapage
"
,
actions
=
{
getdeltapage
,
context
}
,
arguments
=
{
"
string
"
,
"
integer
"
}
}
373 374
local
function
flushnotes
(
tag
,
whatkind
,
how
)
-- store and postpone
375
local
state
=
notestates
[
tag
]
376
local
kind
=
state
.
kind
377
if
kind
=
=
whatkind
then
378
local
nd
=
notedata
[
tag
]
379
local
ns
=
state
.
start
-- first index
380
if
kind
=
=
"
postpone
"
then
381
if
nd
and
ns
then
382
if
trace_notes
then
383
report_notes
(
"
flushing state %a of %a from %a to %a
"
,
whatkind
,
tag
,
ns
,
#
nd
)
384
end
385
for
i
=
ns
,
#
nd
do
386
context
.
handlenoteinsert
(
tag
,
i
)
387
end
388
end
389
state
.
start
=
nil
390
state
.
kind
=
"
insert
"
391
elseif
kind
=
=
"
store
"
then
392
if
nd
and
ns
then
393
if
trace_notes
then
394
report_notes
(
"
flushing state %a of %a from %a to %a
"
,
whatkind
,
tag
,
ns
,
#
nd
)
395
end
396
-- todo: as registers: start, stop, inbetween
397
for
i
=
ns
,
#
nd
do
398
-- tricky : trialtypesetting
399
if
how
=
=
variables
.
page
then
400
local
rp
=
get
(
tag
,
i
)
401
rp
=
rp
and
rp
.
references
402
rp
=
rp
and
rp
.
symbolpage
or
0
403
if
rp
>
texgetcount
(
"
realpageno
"
)
then
404
state
.
start
=
i
405
return
406
end
407
end
408
if
i
>
ns
then
409
context
.
betweennoteitself
(
tag
)
410
end
411
context
.
handlenoteitself
(
tag
,
i
)
412
end
413
end
414
state
.
start
=
nil
415
elseif
kind
=
=
"
reset
"
then
416
if
nd
and
ns
then
417
if
trace_notes
then
418
report_notes
(
"
flushing state %a of %a from %a to %a
"
,
whatkind
,
tag
,
ns
,
#
nd
)
419
end
420
end
421
state
.
start
=
nil
422
elseif
trace_notes
then
423
report_notes
(
"
not flushing state %a of %a
"
,
whatkind
,
tag
)
424
end
425
elseif
trace_notes
then
426
report_notes
(
"
not flushing state %a of %a
"
,
whatkind
,
tag
)
427
end
428
end
429 430
local
function
flushpostponednotes
(
)
431
if
trace_notes
then
432
report_notes
(
"
flushing all postponed notes
"
)
433
end
434
for
tag
,
_
in
next
,
notestates
do
435
flushnotes
(
tag
,
"
postpone
"
)
436
end
437
end
438 439
implement
{
440
name
=
"
flushpostponednotes
"
,
441
actions
=
flushpostponednotes
442
}
443 444
implement
{
445
name
=
"
flushnotes
"
,
446
actions
=
flushnotes
,
447
arguments
=
"
3 strings
"
,
448
}
449 450
function
notes
.
resetpostponed
(
)
451
if
trace_notes
then
452
report_notes
(
"
resetting all postponed notes
"
)
453
end
454
for
tag
,
state
in
next
,
notestates
do
455
if
state
.
kind
=
=
"
postpone
"
then
456
state
.
start
=
nil
457
state
.
kind
=
"
insert
"
458
end
459
end
460
end
461 462
implement
{
463
name
=
"
notetitle
"
,
464
actions
=
function
(
tag
,
n
)
lists
.
savedlisttitle
(
tag
,
notedata
[
tag
]
[
n
]
)
end
,
465
arguments
=
{
"
string
"
,
"
integer
"
}
466
}
467 468
implement
{
469
name
=
"
noteprefixednumber
"
,
470
actions
=
function
(
tag
,
n
)
lists
.
savedlistprefixednumber
(
tag
,
notedata
[
tag
]
[
n
]
)
end
,
471
arguments
=
{
"
string
"
,
"
integer
"
}
472
}
473 474
function
notes
.
internalid
(
tag
,
n
)
475
local
nd
=
get
(
tag
,
n
)
476
if
nd
then
477
local
r
=
nd
.
references
478
return
r
.
internal
479
end
480
end
481 482
-- for the moment here but better in some builder modules
483 484
-- gets register "n" and location "i" (where 1 is before)
485 486
-- this is an experiment, we will make a more general handler instead
487
-- of the current note one
488 489
local
report_insert
=
logs
.
reporter
(
"
pagebuilder
"
,
"
insert
"
)
490
local
trace_insert
=
false
trackers
.
register
(
"
pagebuilder.insert
"
,
function
(
v
)
trace_insert
=
v
end
)
491 492
local
texgetglue
=
tex
.
getglue
493
local
texsetglue
=
tex
.
setglue
494 495
local
function
check_spacing
(
n
,
i
)
496
-- we can also check for tex.insertheights > 0 (instead of i > 1)
497
local
gn
,
pn
,
mn
=
texgetglue
(
n
)
498
local
gi
,
pi
,
mi
=
texgetglue
(
i
>
1
and
"
s_strc_notes_inbetween
"
or
"
s_strc_notes_before
"
)
499
local
gt
,
pt
,
mt
=
gn
+
gi
,
pn
+
pi
,
mn
+
mi
500
if
trace_insert
then
501
report_insert
(
"
%s %i: %p plus %p minus %p
"
,
"
always
"
,
n
,
gn
,
pn
,
mn
)
502
report_insert
(
"
%s %i: %p plus %p minus %p
"
,
i
>
1
and
"
inbetween
"
or
"
before
"
,
n
,
gi
,
pi
,
mi
)
503
report_insert
(
"
%s %i: %p plus %p minus %p
"
,
"
effective
"
,
n
,
gt
,
pt
,
mt
)
504
end
505
return
gt
,
pt
,
mt
506
end
507 508
notes
.
check_spacing
=
check_spacing
509 510
callback
.
register
(
"
build_page_insert
"
,
function
(
n
,
i
)
511
local
state
=
notes
.
numbers
[
n
]
512
if
state
then
513
-- only notes, kind of hardcoded .. bah
514
local
gt
,
pt
,
mt
=
check_spacing
(
n
,
i
)
515
texsetglue
(
0
,
gt
,
pt
,
mt
)
-- for the moment we use skip register 0
516
return
0
517
else
518
return
n
519
end
520
end
)
521