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