summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/strc-pag.lua
blob: 460d4ff008e055525c0d8258789c3f1f6406c14a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
if not modules then modules = { } end modules ['strc-pag'] = {
    version   = 1.001,
    comment   = "companion to strc-pag.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local texcount, format = tex.count, string.format

local allocate, mark = utilities.storage.allocate, utilities.storage.mark

local trace_pages         = false  trackers.register("structures.pages", function(v) trace_pages = v end)

local report_pages        = logs.reporter("structure","pages")

local structures          = structures

local helpers             = structures.helpers
local sections            = structures.sections
local pages               = structures.pages
local sets                = structures.sets
local counters            = structures.counters

local counterdata         = counters.data

local variables           = interfaces.variables
local context             = context

local processors          = typesetters.processors
local applyprocessor      = processors.apply
local startapplyprocessor = processors.startapply
local stopapplyprocessor  = processors.stopapply

-- storage

local collected, tobesaved = allocate(), allocate()

pages.collected = collected
pages.tobesaved = tobesaved

local function initializer()
    collected = pages.collected
    tobesaved = pages.tobesaved
end

job.register('structures.pages.collected', tobesaved, initializer)

local specification = { } -- to be checked

function pages.save(prefixdata,numberdata)
    local realpage, userpage = texcount.realpageno, texcount.userpageno
    if realpage > 0 then
        if trace_pages then
            report_pages("saving page %s.%s",realpage,userpage)
        end
        local data = {
            number     = userpage,
            block      = sections.currentblock(),
            prefixdata = prefixdata and helpers.simplify(prefixdata),
            numberdata = numberdata and helpers.simplify(numberdata),
        }
        tobesaved[realpage] = data
        if not collected[realpage] then
            collected[realpage] = data
        end
    elseif trace_pages then
        report_pages("not saving page %s.%s",realpage,userpage)
    end
end

function counters.specials.userpage()
    local r = texcount.realpageno
    if r > 0 then
        local t = tobesaved[r]
        if t then
            t.number = texcount.userpageno
            if trace_pages then
                report_pages("forcing pagenumber of realpage %s to %s",r,t.number)
            end
        end
    end
end

local function convertnumber(str,n)
    return format("\\convertnumber{%s}{%s}",str or "numbers",n)
end

function pages.number(realdata,pagespec)
    local userpage, block = realdata.number, realdata.block or "" -- sections.currentblock()
    local numberspec = realdata.numberdata
    local conversionset = (pagespec and pagespec.conversionset ~= "" and pagespec.conversionset) or (numberspec and numberspec.conversionset ~= "" and numberspec.conversionset) or ""
    local conversion    = (pagespec and pagespec.conversion    ~= "" and pagespec.conversion   ) or (numberspec and numberspec.conversion    ~= "" and numberspec.conversion   ) or ""
    local starter       = (pagespec and pagespec.starter       ~= "" and pagespec.starter      ) or (numberspec and numberspec.starter       ~= "" and numberspec.starter      ) or ""
    local stopper       = (pagespec and pagespec.stopper       ~= "" and pagespec.stopper      ) or (numberspec and numberspec.stopper       ~= "" and numberspec.stopper      ) or ""
    if starter ~= "" then
        applyprocessor(starter)
    end
    if conversion ~= "" then
        context.convertnumber(conversion,userpage)
    else
        if conversionset == "" then conversionset = "default" end
        local theconversion = sets.get("structure:conversions",block,conversionset,1,"numbers") -- to be checked: 1
        local data = startapplyprocessor(theconversion)
        context.convertnumber(data or "number",userpage)
        stopapplyprocessor()
    end
    if stopper ~= "" then
        applyprocessors(stopper)
    end
end

-- (pagespec.prefix == yes|unset) and (pages.prefix == yes) => prefix

function pages.analyze(entry,pagespecification)
    -- safeguard
    if not entry then
        return false, false, "no entry"
    end
    local references = entry.references
    if not references then
        return false, false, "no references"
    end
    local pagedata = references.pagedata -- sometimes resolved (external)
    if not pagedata then
        local realpage = references.realpage
        if realpage then
            pagedata = collected[realpage]
        else
            return false, false, "no realpage"
        end
    end
    if not pagedata then
        return false, false, "no pagedata"
    end
    local sectiondata = references.sectiondata -- sometimes resolved (external)
    if not sectiondata then
        local section = references.section
        if section then
            sectiondata = sections.collected[section]
        else
            return pagedata, false, "no section"
        end
    end
    if not sectiondata then
        return pagedata, false, "no sectiondata"
    end
    local no = variables.no
    -- local preferences
    if pagespecification and pagespecification.prefix == no then
        return pagedata, false, "current spec blocks prefix"
    end
    -- stored preferences
 -- if entry.prefix == no then
 --     return pagedata, false, "entry blocks prefix"
 -- end
    -- stored page state
    pagespecification = pagedata.prefixdata
    if pagespecification and pagespecification.prefix == no then
        return pagedata, false, "pagedata blocks prefix"
    end
    -- final verdict
    return pagedata, sectiondata, "okay"
end

function helpers.page(data,pagespec)
    if data then
        local pagedata = pages.analyze(data,pagespec)
        if pagedata then
            pages.number(pagedata,pagespec)
        end
    end
end

function helpers.prefixpage(data,prefixspec,pagespec)
    if data then
        local pagedata, prefixdata, e = pages.analyze(data,pagespec)
        if pagedata then
            if prefixdata then
                sections.typesetnumber(prefixdata,"prefix",prefixspec or false,prefixdata or false,pagedata.prefixdata or false)
            end
            pages.number(pagedata,pagespec)
        end
    end
end

function helpers.prefixlastpage(data,prefixspec,pagespec)
    if data then
        local r = data.references
        local ls, lr = r.section, r.realpage
        r.section, r.realpage = r.lastsection or r.section, r.lastrealpage or r.realpage
        helpers.prefixpage(data,prefixspec,pagespec)
        r.section, r.realpage = ls, lr
    end
end

--

function helpers.analyze(entry,specification)
    -- safeguard
    if not entry then
        return false, false, "no entry"
    end
    local yes, no = variables.yes, variables.no
    -- section data
    local references = entry.references
    if not references then
        return entry, false, "no references"
    end
    local section = references.section
    if not section then
        return entry, false, "no section"
    end
    local sectiondata = sections.collected[references.section]
    if not sectiondata then
        return entry, false, "no section data"
    end
    -- local preferences
    if specification and specification.prefix == no then
        return entry, false, "current spec blocks prefix"
    end
    -- stored preferences (not used)
    local prefixdata = entry.prefixdata
    if prefixdata and prefixdata.prefix == no then
        return entry, false, "entry blocks prefix"
    end
    -- final verdict
    return entry, sectiondata, "okay"
end

function helpers.prefix(data,prefixspec)
    if data then
        local _, prefixdata, status = helpers.analyze(data,prefixspec)
        if prefixdata then
            sections.typesetnumber(prefixdata,"prefix",prefixspec or false,data.prefixdata or false,prefixdata or false)
        end
    end
end

function pages.is_odd(n)
    n = n or texcount.realpageno
    if texcount.pagenoshift % 2 == 0 then
        return n % 2 == 0
    else
        return n % 2 ~= 0
    end
end

-- move to strc-pag.lua

function counters.analyze(name,counterspecification)
    local cd = counterdata[name]
    -- safeguard
    if not cd then
        return false, false, "no counter data"
    end
    -- section data
    local sectiondata = sections.current()
    if not sectiondata then
        return cd, false, "not in section"
    end
    local references = sectiondata.references
    if not references then
        return cd, false, "no references"
    end
    local section = references.section
    if not section then
        return cd, false, "no section"
    end
    sectiondata = sections.collected[references.section]
    if not sectiondata then
        return cd, false, "no section data"
    end
    -- local preferences
    local no = variables.no
    if counterspecification and counterspecification.prefix == no then
        return cd, false, "current spec blocks prefix"
    end
    -- stored preferences (not used)
    if cd.prefix == no then
        return cd, false, "entry blocks prefix"
    end
    -- sectioning
    -- if sectiondata.prefix == no then
    --     return false, false, "sectiondata blocks prefix"
    -- end
    -- final verdict
    return cd, sectiondata, "okay"
end

function sections.prefixedconverted(name,prefixspec,numberspec)
    local cd, prefixdata, result = counters.analyze(name,prefixspec)
    if cd then
        if prefixdata then
            sections.typesetnumber(prefixdata,"prefix",prefixspec or false,cd or false)
        end
        counters.converted(name,numberspec)
    end
end