summaryrefslogtreecommitdiff
path: root/tex/context/base/strc-bkm.lua
blob: f34d83ec5577ae48814a0adcc2ba94120466036e (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
if not modules then modules = { } end modules ['strc-bkm'] = {
    version   = 0.200,
    comment   = "companion to strc-bkm.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- Future version will support adding arbitrary bookmarks with
-- associated complex actions (rather trivial to implement).

local format, concat, gsub = string.format, table.concat, string.gsub
local texsprint, utfvalues = tex.sprint, string.utfvalues

local ctxcatcodes = tex.ctxcatcodes

local lists    = structure.lists
local levelmap = structure.sections.levelmap

structure.bookmarks = structure.bookmarks or { }

local bookmarks = structure.bookmarks

bookmarks.method = "internal" -- or "page"

local names, opened = "", ""

function bookmarks.register(n,o)
    if names  == "" then names  = n else names  = names  .. "," .. n end
    if opened == "" then opened = o else opened = opened .. "," .. o end
end

function bookmarks.overload(name,text)
    local l, ls = lists.tobesaved, nil
    if #l == 0 then
        -- no entries
    elseif name == "" then
        ls = l[#l]
    else
        for i=#l,0,-1 do
            local li = l[i]
            local metadata = li.metadata
            if metadata and not metadata.nolist and metadata.name == name then
                ls = li
                break
            end
        end
    end
    if ls then
        ls.titledata.bookmark = text
    end
end

local function stripped(str) -- kind of generic
    str = gsub(str,"\\([A-Z]+)","%1")            -- \LOGO
    str = gsub(str,"\\ "," ")                    -- \
    str = gsub(str,"\\([A-Za-z]+) *{(.-)}","%1") -- \bla{...}
    str = gsub(str," +"," ")                     -- spaces
    return str
end

-- todo: collect specs and collect later i.e. multiple places

function bookmarks.place()
    if names ~= "" then
        local list = lists.filter(names,"all",nil,lists.collected)
        local lastlevel = 1
        if #list > 0 then
            local opened, levels = aux.settings_to_set(opened), { }
            for i=1,#list do
                local li = list[i]
                local metadata = li.metadata
                local name = metadata.name
                if not metadata.nolist then -- and levelmap[name] then
                    local titledata = li.titledata
                    if titledata then
                        local structural = levelmap[name]
                        lastlevel = structural or lastlevel
                        local title = titledata.bookmark
                        if not title or title == "" then
                            if not structural then
                                -- placeholder, todo: bookmarklabel
                                title = name .. ": " .. (titledata.title or "?")
                            else
                                title = titledata.title or "?"
                            end
                        end
                        levels[#levels+1] = {
                            lastlevel,
                            stripped(title),
                            li.references, -- has internal and realpage
                            allopen or opened[name]
                        }
                    end
                end
            end
            backends.codeinjections.addbookmarks(levels,bookmarks.method)
        end
        function bookmarks.place() end -- prevent second run
    end
end

lpdf.registerdocumentfinalizer(function() structure.bookmarks.place() end,1)

-- bkm
--~ function nodes.toutf(list)
--~     local t= { }
--~     for n in node.traverse(list) do
--~         local id = n.id
--~         if id == node.id("glyph") then
--~             local c = n.char
--~             local f = fonts.ids[n.font]
--~             if f then
--~                 local u = f.characters[c].tounicode
--~                 if u then
--~                     for s in string.gmatch(u,"..") do
--~                         t[#t+1] = utf.char(tonumber(s,16))
--~                     end
--~                 else
--~                     t[#t+1] = utf.char(c)
--~                 end
--~             else
--~                 t[#t+1] = utf.char(c)
--~             end
--~         elseif id == node.id("glue") then
--~             t[#t+1] = " "
--~         end
--~     end
--~     return table.concat(t,"")
--~ end
--~ print(nodes.toutf(tex.box[999].list))