strc-pag.lua /size: 13 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
strc-pag
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to strc-pag.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
allocate
,
mark
=
utilities
.
storage
.
allocate
,
utilities
.
storage
.
mark
10 11
local
trace_pages
=
false
trackers
.
register
(
"
structures.pages
"
,
function
(
v
)
trace_pages
=
v
end
)
12 13
local
report_pages
=
logs
.
reporter
(
"
structure
"
,
"
pages
"
)
14 15
local
structures
=
structures
16 17
local
helpers
=
structures
.
helpers
18
local
sections
=
structures
.
sections
19
local
pages
=
structures
.
pages
20
local
sets
=
structures
.
sets
21
local
counters
=
structures
.
counters
22 23
local
counterdata
=
counters
.
data
24 25
local
variables
=
interfaces
.
variables
26
local
context
=
context
27
local
commands
=
commands
28
local
implement
=
interfaces
.
implement
29 30
local
processors
=
typesetters
.
processors
31
local
applyprocessor
=
processors
.
apply
32
local
startapplyprocessor
=
processors
.
startapply
33
local
stopapplyprocessor
=
processors
.
stopapply
34 35
local
texsetcount
=
tex
.
setcount
36
local
texgetcount
=
tex
.
getcount
37 38
local
texconditionals
=
tex
.
conditionals
39 40
local
ctx_convertnumber
=
context
.
convertnumber
41 42
-- storage
43 44
local
collected
,
tobesaved
=
allocate
(
)
,
allocate
(
)
45 46
pages
.
collected
=
collected
47
pages
.
tobesaved
=
tobesaved
48
pages
.
nofpages
=
0
49 50
-- utilitydata.structures.counters.collected.realpage[1]
51 52
local
function
initializer
(
)
53
collected
=
pages
.
collected
54
tobesaved
=
pages
.
tobesaved
55
-- tricky, with pageinjection we can have holes
56
-- pages.nofpages = #collected
57
-- pages.nofpages = table.count(collected) -- could be a helper
58
local
n
=
0
59
for
k
in
next
,
collected
do
60
if
k
>
n
then
61
n
=
k
62
end
63
end
64
pages
.
nofpages
=
n
65
end
66 67
job
.
register
(
'
structures.pages.collected
'
,
tobesaved
,
initializer
)
68 69
local
specification
=
{
}
-- to be checked
70 71
function
pages
.
save
(
prefixdata
,
numberdata
,
extradata
)
72
local
realpage
=
texgetcount
(
"
realpageno
"
)
73
local
userpage
=
texgetcount
(
"
userpageno
"
)
74
if
realpage
>
0
then
75
if
trace_pages
then
76
report_pages
(
"
saving page %s.%s
"
,
realpage
,
userpage
)
77
end
78
local
viewerprefix
=
extradata
.
viewerprefix
79
local
state
=
extradata
.
state
80
local
data
=
{
81
number
=
userpage
,
82
viewerprefix
=
viewerprefix
~
=
"
"
and
viewerprefix
or
nil
,
83
state
=
state
~
=
"
"
and
state
or
nil
,
-- maybe let "start" be default
84
block
=
sections
.
currentblock
(
)
,
85
prefixdata
=
prefixdata
and
helpers
.
simplify
(
prefixdata
)
,
86
numberdata
=
numberdata
and
helpers
.
simplify
(
numberdata
)
,
87
marked
=
pages
.
markedlist
(
realpage
)
,
-- not yet defined
88
}
89
tobesaved
[
realpage
]
=
data
90
if
not
collected
[
realpage
]
then
91
collected
[
realpage
]
=
data
92
end
93
elseif
trace_pages
then
94
report_pages
(
"
not saving page %s.%s
"
,
realpage
,
userpage
)
95
end
96
end
97 98
-- We can set the pagenumber but as it only get incremented in the page
99
-- builder we have to make sure it starts at least at 1.
100 101
function
counters
.
specials
.
userpage
(
)
102
local
r
=
texgetcount
(
"
realpageno
"
)
103
if
r
>
0
then
104
local
t
=
tobesaved
[
r
]
105
if
t
then
106
t
.
number
=
texgetcount
(
"
userpageno
"
)
107
if
trace_pages
then
108
report_pages
(
"
forcing pagenumber of realpage %s to %s
"
,
r
,
t
.
number
)
109
end
110
return
111
end
112
end
113
local
u
=
texgetcount
(
"
userpageno
"
)
114
if
u
=
=
0
then
115
if
trace_pages
then
116
report_pages
(
"
forcing pagenumber of realpage %s to %s (probably a bug)
"
,
r
,
1
)
117
end
118
counters
.
setvalue
(
"
userpage
"
,
1
)
119
texsetcount
(
"
userpageno
"
,
1
)
-- not global ?
120
end
121
end
122 123
-- local f_convert = string.formatters["\\convertnumber{%s}{%s}"]
124
--
125
-- local function convertnumber(str,n)
126
-- return f_convert(str or "numbers",n)
127
-- end
128 129
function
pages
.
number
(
realdata
,
pagespec
)
130
local
userpage
=
realdata
.
number
131
local
block
=
realdata
.
block
or
"
"
-- sections.currentblock()
132
local
numberspec
=
realdata
.
numberdata
133
local
conversionset
=
(
pagespec
and
pagespec
.
conversionset
~
=
"
"
and
pagespec
.
conversionset
)
or
(
numberspec
and
numberspec
.
conversionset
~
=
"
"
and
numberspec
.
conversionset
)
or
"
"
134
local
conversion
=
(
pagespec
and
pagespec
.
conversion
~
=
"
"
and
pagespec
.
conversion
)
or
(
numberspec
and
numberspec
.
conversion
~
=
"
"
and
numberspec
.
conversion
)
or
"
"
135
local
starter
=
(
pagespec
and
pagespec
.
starter
~
=
"
"
and
pagespec
.
starter
)
or
(
numberspec
and
numberspec
.
starter
~
=
"
"
and
numberspec
.
starter
)
or
"
"
136
local
stopper
=
(
pagespec
and
pagespec
.
stopper
~
=
"
"
and
pagespec
.
stopper
)
or
(
numberspec
and
numberspec
.
stopper
~
=
"
"
and
numberspec
.
stopper
)
or
"
"
137
if
starter
~
=
"
"
then
138
applyprocessor
(
starter
)
139
end
140
if
conversion
~
=
"
"
then
141
ctx_convertnumber
(
conversion
,
userpage
)
142
else
143
if
conversionset
=
=
"
"
then
conversionset
=
"
default
"
end
144
local
theconversion
=
sets
.
get
(
"
structure:conversions
"
,
block
,
conversionset
,
1
,
"
numbers
"
)
-- to be checked: 1
145
local
data
=
startapplyprocessor
(
theconversion
)
146
ctx_convertnumber
(
data
or
"
number
"
,
userpage
)
147
stopapplyprocessor
(
)
148
end
149
if
stopper
~
=
"
"
then
150
applyprocessors
(
stopper
)
151
end
152
end
153 154
-- (pagespec.prefix == yes|unset) and (pages.prefix == yes) => prefix
155 156
function
pages
.
analyze
(
entry
,
pagespecification
)
157
-- safeguard
158
if
not
entry
then
159
return
false
,
false
,
"
no entry
"
160
end
161
local
references
=
entry
.
references
162
if
not
references
then
163
return
false
,
false
,
"
no references
"
164
end
165
local
pagedata
=
references
.
pagedata
-- sometimes resolved (external)
166
if
not
pagedata
then
167
local
realpage
=
references
.
realpage
168
if
realpage
then
169
pagedata
=
collected
[
realpage
]
170
else
171
return
false
,
false
,
"
no realpage
"
172
end
173
end
174
if
not
pagedata
then
175
return
false
,
false
,
"
no pagedata
"
176
end
177
local
sectiondata
=
references
.
sectiondata
-- sometimes resolved (external)
178
if
not
sectiondata
then
179
local
section
=
references
.
section
180
if
section
then
181
sectiondata
=
sections
.
collected
[
section
]
182
else
183
return
pagedata
,
false
,
"
no section
"
184
end
185
end
186
if
not
sectiondata
then
187
return
pagedata
,
false
,
"
no sectiondata
"
188
end
189
local
v_no
=
variables
.
no
190
-- local preferences
191
if
pagespecification
and
pagespecification
.
prefix
=
=
v_no
then
192
return
pagedata
,
false
,
"
current spec blocks prefix
"
193
end
194
-- stored preferences
195
-- if entry.prefix == v_no then
196
-- return pagedata, false, "entry blocks prefix"
197
-- end
198
-- stored page state
199
pagespecification
=
pagedata
.
prefixdata
200
if
pagespecification
and
pagespecification
.
prefix
=
=
v_no
then
201
return
pagedata
,
false
,
"
pagedata blocks prefix
"
202
end
203
-- final verdict
204
return
pagedata
,
sectiondata
,
"
okay
"
205
end
206 207
function
helpers
.
page
(
data
,
pagespec
)
208
if
data
then
209
local
pagedata
=
pages
.
analyze
(
data
,
pagespec
)
210
if
pagedata
then
211
pages
.
number
(
pagedata
,
pagespec
)
212
end
213
end
214
end
215 216
function
helpers
.
prefixpage
(
data
,
prefixspec
,
pagespec
)
217
if
data
then
218
local
pagedata
,
prefixdata
,
e
=
pages
.
analyze
(
data
,
pagespec
)
219
if
pagedata
then
220
if
prefixdata
then
221
sections
.
typesetnumber
(
prefixdata
,
"
prefix
"
,
prefixspec
or
false
,
prefixdata
or
false
,
pagedata
.
prefixdata
or
false
)
222
end
223
pages
.
number
(
pagedata
,
pagespec
)
224
end
225
end
226
end
227 228
function
helpers
.
prefixlastpage
(
data
,
prefixspec
,
pagespec
)
229
if
data
then
230
local
r
=
data
.
references
231
local
ls
=
r
.
section
232
local
lr
=
r
.
realpage
233
r
.
section
=
r
.
lastsection
or
r
.
section
234
r
.
realpage
=
r
.
lastrealpage
or
r
.
realpage
235
helpers
.
prefixpage
(
data
,
prefixspec
,
pagespec
)
236
r
.
section
,
r
.
realpage
=
ls
,
lr
237
end
238
end
239 240
--
241 242
function
helpers
.
analyze
(
entry
,
specification
)
243
-- safeguard
244
if
not
entry
then
245
return
false
,
false
,
"
no entry
"
246
end
247
local
yes
=
variables
.
yes
248
local
no
=
variables
.
no
249
-- section data
250
local
references
=
entry
.
references
251
if
not
references
then
252
return
entry
,
false
,
"
no references
"
253
end
254
local
section
=
references
.
section
255
if
not
section
then
256
return
entry
,
false
,
"
no section
"
257
end
258
local
sectiondata
=
sections
.
collected
[
references
.
section
]
259
if
not
sectiondata
then
260
return
entry
,
false
,
"
no section data
"
261
end
262
-- local preferences
263
if
specification
and
specification
.
prefix
=
=
no
then
264
return
entry
,
false
,
"
current spec blocks prefix
"
265
end
266
-- stored preferences (not used)
267
local
prefixdata
=
entry
.
prefixdata
268
if
prefixdata
and
prefixdata
.
prefix
=
=
no
then
269
return
entry
,
false
,
"
entry blocks prefix
"
270
end
271
-- final verdict
272
return
entry
,
sectiondata
,
"
okay
"
273
end
274 275
function
helpers
.
prefix
(
data
,
prefixspec
,
nosuffix
)
276
if
data
then
277
local
_
,
prefixdata
,
status
=
helpers
.
analyze
(
data
,
prefixspec
)
278
if
prefixdata
then
279
if
nosuffix
and
prefixspec
then
280
local
connector
=
prefixspec
.
connector
281
prefixspec
.
connector
=
nil
282
sections
.
typesetnumber
(
prefixdata
,
"
prefix
"
,
prefixspec
or
false
,
data
.
prefixdata
or
false
,
prefixdata
or
false
)
283
prefixspec
.
connector
=
connector
284
else
285
sections
.
typesetnumber
(
prefixdata
,
"
prefix
"
,
prefixspec
or
false
,
data
.
prefixdata
or
false
,
prefixdata
or
false
)
286
end
287
end
288
end
289
end
290 291
function
helpers
.
pageofinternal
(
n
,
prefixspec
,
pagespec
)
292
local
data
=
structures
.
references
.
internals
[
n
]
293
if
not
data
then
294
-- error
295
elseif
prefixspec
then
296
helpers
.
prefixpage
(
data
,
prefixspec
,
pagespec
)
297
else
298
helpers
.
prefix
(
data
,
pagespec
)
299
end
300
end
301 302
function
pages
.
is_odd
(
n
)
303
n
=
n
or
texgetcount
(
"
realpageno
"
)
304
if
texgetcount
(
"
pagenoshift
"
)
%
2
=
=
0
then
305
return
n
%
2
~
=
0
306
else
307
return
n
%
2
=
=
0
308
end
309
end
310 311
function
pages
.
on_right
(
n
)
312
local
pagemode
=
texgetcount
(
"
pageduplexmode
"
)
313
if
pagemode
=
=
2
or
pagemode
=
=
1
then
314
n
=
n
or
texgetcount
(
"
realpageno
"
)
315
if
texgetcount
(
"
pagenoshift
"
)
%
2
=
=
0
then
316
return
n
%
2
~
=
0
317
else
318
return
n
%
2
=
=
0
319
end
320
else
321
return
true
322
end
323
end
324 325
function
pages
.
has_changed
(
)
326
return
texconditionals
.
layouthaschanged
327
end
328 329
function
pages
.
in_body
(
n
)
330
return
texgetcount
(
"
pagebodymode
"
)
>
0
331
end
332 333
function
pages
.
fraction
(
n
)
334
local
lastpage
=
texgetcount
(
"
lastpageno
"
)
-- can be cached
335
return
lastpage
>
1
and
(
texgetcount
(
"
realpageno
"
)
-1
)
/
(
lastpage
-1
)
or
1
336
end
337 338
-- move to strc-pag.lua
339 340
function
counters
.
analyze
(
name
,
counterspecification
)
341
local
cd
=
counterdata
[
name
]
342
-- safeguard
343
if
not
cd
then
344
return
false
,
false
,
"
no counter data
"
345
end
346
-- section data
347
local
sectiondata
=
sections
.
current
(
)
348
if
not
sectiondata
then
349
return
cd
,
false
,
"
not in section
"
350
end
351
local
references
=
sectiondata
.
references
352
if
not
references
then
353
return
cd
,
false
,
"
no references
"
354
end
355
local
section
=
references
.
section
356
if
not
section
then
357
return
cd
,
false
,
"
no section
"
358
end
359
sectiondata
=
sections
.
collected
[
references
.
section
]
360
if
not
sectiondata
then
361
return
cd
,
false
,
"
no section data
"
362
end
363
-- local preferences
364
local
no
=
variables
.
no
365
if
counterspecification
and
counterspecification
.
prefix
=
=
no
then
366
return
cd
,
false
,
"
current spec blocks prefix
"
367
end
368
-- stored preferences (not used)
369
if
cd
.
prefix
=
=
no
then
370
return
cd
,
false
,
"
entry blocks prefix
"
371
end
372
-- sectioning
373
-- if sectiondata.prefix == no then
374
-- return false, false, "sectiondata blocks prefix"
375
-- end
376
-- final verdict
377
return
cd
,
sectiondata
,
"
okay
"
378
end
379 380
function
sections
.
prefixedconverted
(
name
,
prefixspec
,
numberspec
)
381
local
cd
,
prefixdata
,
result
=
counters
.
analyze
(
name
,
prefixspec
)
382
if
cd
then
383
if
prefixdata
then
384
sections
.
typesetnumber
(
prefixdata
,
"
prefix
"
,
prefixspec
or
false
,
cd
or
false
)
385
end
386
counters
.
converted
(
name
,
numberspec
)
387
end
388
end
389 390
--
391 392
implement
{
393
name
=
"
savepagedata
"
,
394
actions
=
pages
.
save
,
395
arguments
=
{
396
{
397
{
"
prefix
"
}
,
398
{
"
separatorset
"
}
,
399
{
"
conversionset
"
}
,
400
{
"
conversion
"
}
,
401
{
"
set
"
}
,
402
{
"
segments
"
}
,
403
{
"
connector
"
}
,
404
}
,
405
{
406
{
"
conversionset
"
}
,
407
{
"
conversion
"
}
,
408
{
"
starter
"
}
,
409
{
"
stopper
"
}
,
410
}
,
411
{
412
{
"
viewerprefix
"
}
,
413
{
"
state
"
}
,
414
}
415
}
416
}
417 418
implement
{
-- weird place
419
name
=
"
prefixedconverted
"
,
420
actions
=
sections
.
prefixedconverted
,
421
arguments
=
{
422
"
string
"
,
423
{
424
{
"
prefix
"
}
,
425
{
"
separatorset
"
}
,
426
{
"
conversionset
"
}
,
427
{
"
conversion
"
}
,
428
{
"
starter
"
}
,
429
{
"
stopper
"
}
,
430
{
"
set
"
}
,
431
{
"
segments
"
}
,
432
{
"
connector
"
}
,
433
}
,
434
{
435
{
"
order
"
}
,
436
{
"
separatorset
"
}
,
437
{
"
conversionset
"
}
,
438
{
"
conversion
"
}
,
439
{
"
starter
"
}
,
440
{
"
stopper
"
}
,
441
{
"
segments
"
}
,
442
{
"
type
"
}
,
443
{
"
criterium
"
}
,
444
}
445
}
446
}
447 448
interfaces
.
implement
{
449
name
=
"
pageofinternal
"
,
450
arguments
=
"
integer
"
,
451
actions
=
helpers
.
pageofinternal
,
452
}
453