summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/strc-bkm.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/strc-bkm.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/strc-bkm.lua153
1 files changed, 106 insertions, 47 deletions
diff --git a/Master/texmf-dist/tex/context/base/strc-bkm.lua b/Master/texmf-dist/tex/context/base/strc-bkm.lua
index f34d83ec557..6a2cc382775 100644
--- a/Master/texmf-dist/tex/context/base/strc-bkm.lua
+++ b/Master/texmf-dist/tex/context/base/strc-bkm.lua
@@ -9,25 +9,56 @@ if not modules then modules = { } end modules ['strc-bkm'] = {
-- Future version will support adding arbitrary bookmarks with
-- associated complex actions (rather trivial to implement).
+-- this should become proper separated backend code
+
+-- we should hook the placement into everystoptext ... needs checking
+
local format, concat, gsub = string.format, table.concat, string.gsub
-local texsprint, utfvalues = tex.sprint, string.utfvalues
+local utfvalues = string.utfvalues
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local codeinjections = backends.codeinjections
+
+local trace_bookmarks = false trackers.register("references.bookmarks", function(v) trace_bookmarks = v end)
-local ctxcatcodes = tex.ctxcatcodes
+local report_bookmarks = logs.reporter("structure","bookmarks")
-local lists = structure.lists
-local levelmap = structure.sections.levelmap
+local structures = structures
-structure.bookmarks = structure.bookmarks or { }
+structures.bookmarks = structures.bookmarks or { }
-local bookmarks = structure.bookmarks
+local bookmarks = structures.bookmarks
+local sections = structures.sections
+local lists = structures.lists
+
+local levelmap = sections.levelmap
+local variables = interfaces.variables
bookmarks.method = "internal" -- or "page"
-local names, opened = "", ""
+local names, opened, forced, numbered = { }, { }, { }, { }
-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
+function bookmarks.register(settings)
+ local force = settings.force == variables.yes
+ local number = settings.number == variables.yes
+ local allopen = settings.opened == variables.all
+ for k, v in next, settings_to_hash(settings.names or "") do
+ names[k] = true
+ if force then
+ forced[k] = true
+ if allopen then
+ opened[k] = true
+ end
+ end
+ if number then
+ numbered[k] = true
+ end
+ end
+ if not allopen then
+ for k, v in next, settings_to_hash(settings.opened or "") do
+ opened[k] = true
+ end
+ end
end
function bookmarks.overload(name,text)
@@ -61,23 +92,32 @@ end
-- todo: collect specs and collect later i.e. multiple places
+local numberspec = { }
+
+function bookmarks.setup(spec)
+ -- table.merge(numberspec,spec)
+ for k, v in next, spec do
+ numberspec[k] = v
+ end
+end
+
function bookmarks.place()
- if names ~= "" then
- local list = lists.filter(names,"all",nil,lists.collected)
- local lastlevel = 1
+ if next(names) then
+ local list = lists.filtercollected(names,"all",nil,lists.collected,forced)
if #list > 0 then
- local opened, levels = aux.settings_to_set(opened), { }
+ local levels, noflevels, lastlevel = { }, 0, 1
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
+ if not metadata.nolist or forced[name] 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
+ -- We could typeset the title and then convert it.
if not structural then
-- placeholder, todo: bookmarklabel
title = name .. ": " .. (titledata.title or "?")
@@ -85,47 +125,66 @@ function bookmarks.place()
title = titledata.title or "?"
end
end
- levels[#levels+1] = {
+ if numbered[name] then
+ local sectiondata = sections.collected[li.references.section]
+ local numberdata = li.numberdata
+ if sectiondata and numberdata and not numberdata.hidenumber then
+ -- we could typeset the number and convert it
+ title = concat(sections.typesetnumber(sectiondata,"direct",numberspec,sectiondata)) .. " " .. title
+ end
+ end
+ noflevels = noflevels + 1
+ levels[noflevels] = {
lastlevel,
- stripped(title),
+ stripped(title), -- can be replaced by converter
li.references, -- has internal and realpage
allopen or opened[name]
}
end
end
end
- backends.codeinjections.addbookmarks(levels,bookmarks.method)
+ bookmarks.finalize(levels)
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))
+function bookmarks.flatten(levels)
+ -- This function promotes leading structurelements with a higher level
+ -- to the next lower level. Such situations are the result of lack of
+ -- structure: a subject preceding a chapter in a sectionblock. So, the
+ -- following code runs over section blocks as well. (bookmarks-007.tex)
+ local noflevels = #levels
+ if noflevels > 1 then
+ local skip, start, one = false, 1, levels[1]
+ local first, block = one[1], one[3].block
+ for i=2,noflevels do
+ local li = levels[i]
+ local new, newblock = li[1], li[3].block
+ if newblock ~= block then
+ first, block, start, skip = new, newblock, i, false
+ elseif skip then
+ -- go on
+ elseif new > first then
+ skip = true
+ elseif new < first then
+ for j=start,i-1 do
+ local lj = levels[j]
+ local old = lj[1]
+ lj[1] = new
+ if trace_bookmarks then
+ report_bookmarks("promoting entry %s from level %s to %s: %s",j,old,new,lj[2])
+ end
+ end
+ skip = true
+ end
+ end
+ end
+end
+
+function bookmarks.finalize(levels)
+ -- This function can be overloaded by an optional converter
+ -- that uses nodes.toutf on a typeset stream. This is something
+ -- that we will support when the main loop has become a coroutine.
+ codeinjections.addbookmarks(levels,bookmarks.method)
+end