summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/lpdf-ano.lua
diff options
context:
space:
mode:
authorTaco Hoekwater <taco@elvenkind.com>2009-08-23 11:11:32 +0000
committerTaco Hoekwater <taco@elvenkind.com>2009-08-23 11:11:32 +0000
commit8fc3039c82d48605b5ca8b2eda3f4fdd755681e1 (patch)
tree3cd9bbdd599bc4d1ac0409e167fee2136e4c0ec9 /Master/texmf-dist/tex/context/base/lpdf-ano.lua
parent850fc99b7cd3ae7a20065531fe866ff7bae642ec (diff)
this is context 2009.08.19 17:10
git-svn-id: svn://tug.org/texlive/trunk@14827 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/lpdf-ano.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-ano.lua573
1 files changed, 573 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/lpdf-ano.lua b/Master/texmf-dist/tex/context/base/lpdf-ano.lua
new file mode 100644
index 00000000000..87014365b39
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/lpdf-ano.lua
@@ -0,0 +1,573 @@
+if not modules then modules = { } end modules ['lpdf-ano'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tostring, format, rep = tostring, string.rep, string.format
+local texcount = tex.count
+
+local trace_references = false trackers.register("references.references", function(v) trace_references = v end)
+local trace_destinations = false trackers.register("references.destinations", function(v) trace_destinations = v end)
+local trace_bookmarks = false trackers.register("references.bookmarks", function(v) trace_bookmarks = v end)
+
+local variables = interfaces.variables
+local constants = interfaces.constants
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+jobreferences = jobreferences or { }
+jobreferences.runners = jobreferences.runners or { }
+jobreferences.specials = jobreferences.specials or { }
+jobreferences.handlers = jobreferences.handlers or { }
+jobreferences.executers = jobreferences.executers or { }
+
+local runners = jobreferences.runners
+local specials = jobreferences.specials
+local handlers = jobreferences.handlers
+local executers = jobreferences.executers
+
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfconstant = lpdf.constant
+
+local pdfreserveobj = pdf.reserveobj
+local pdfimmediateobj = pdf.immediateobj
+local pdfpageref = tex.pdfpageref
+
+local pdfannot = nodes.pdfannot
+local pdfdest = nodes.pdfdest
+
+local pdf_uri = pdfconstant("URI")
+local pdf_gotor = pdfconstant("GoToR")
+local pdf_goto = pdfconstant("GoTo")
+local pdf_launch = pdfconstant("Launch")
+local pdf_javascript = pdfconstant("JavaScript")
+local pdf_link = pdfconstant("Link")
+local pdf_n = pdfconstant("N")
+local pdf_t = pdfconstant("T")
+local pdf_border = pdfarray { 0, 0, 0 }
+
+local cache = { }
+
+local function pagedest(n)
+ local pd = cache[n]
+ if not pd then
+ local a = pdfarray {
+ pdfreference(pdfpageref(n)),
+ pdfconstant("Fit")
+ }
+ pd = pdfreference(pdfimmediateobj(tostring(a)))
+ cache[n] = pd
+ end
+ return pd
+end
+
+lpdf.pagedest = pagedest
+
+local function link(url,filename,destination,page,actions)
+ if filename and filename ~= "" then
+ if file.basename(filename) == tex.jobname then
+ return false
+ else
+ filename = file.addsuffix(filename,"pdf")
+ end
+ end
+ if url and url ~= "" then
+ if filename and filename ~= "" then
+ if destination and destination ~= "" then
+ url = file.join(url,filename).."#"..destination
+ else
+ url = file.join(url,filename)
+ end
+ end
+ return pdfdictionary {
+ S = pdf_uri,
+ URI = url,
+ }
+ elseif filename and filename ~= "" then
+ return pdfdictionary {
+ S = pdf_gotor,
+ F = filename,
+ D = destination and destination ~= "" and destination,
+ NewWindow = (actions.newwindow and true) or nil,
+ }
+ elseif destination and destination ~= "" then
+ local realpage, p = texcount.realpageno, tonumber(page)
+ if not p then
+ -- sorry
+ elseif p > realpage then
+ texcount.referencepagestate = 3
+ elseif p < realpage then
+ texcount.referencepagestate = 2
+ else
+ texcount.referencepagestate = 1
+ end
+ return pdfdictionary {
+ S = pdf_goto,
+ D = destination,
+ }
+ elseif page and page ~= "" then
+ local realpage, p = texcount.realpageno, tonumber(page)
+ if p then
+ if p > realpage then
+ texcount.referencepagestate = 3
+ elseif p < realpage then
+ texcount.referencepagestate = 2
+ else
+ texcount.referencepagestate = 1
+ end
+ return pdfdictionary {
+ S = pdf_goto,
+ D = pagedest(p),
+ }
+ else
+ commands.writestatus("references","invalid page reference: %s",page or "?")
+ end
+ end
+ return false
+end
+
+lpdf.link = link
+
+function lpdf.launch(program,parameters)
+ if program and program ~= "" then
+ local d = pdfdictionary {
+ S = pdf_launch,
+ F = program,
+ D = ".",
+ }
+ if parameters and parameters ~= "" then
+ d.P = parameters
+ end
+ return d
+ end
+end
+
+function lpdf.javascript(name,arguments)
+ local script = javascripts.code(name,arguments) -- make into object (hash)
+ if script then
+ return pdfdictionary {
+ S = pdf_javascript,
+ JS = script,
+ }
+ end
+end
+
+local function pdfaction(actions)
+ local nofactions = #actions
+ texcount.referencepagestate = 0 -- goodie, as we do all in the backend, we need to set it here too
+ if nofactions > 0 then
+ local a = actions[1]
+ local action = runners[a.kind]
+ if action then
+ action = action(a,actions)
+ end
+ if action then
+ local first = action
+ for i=2,nofactions do
+ local a = actions[i]
+ local what = runners[a.kind]
+ if what then
+ what = what(a,actions)
+ end
+ if what then
+ action.next = what
+ action = what
+ else
+ -- error
+ return nil
+ end
+ end
+ return first
+ end
+ end
+end
+
+lpdf.pdfaction = pdfaction
+
+function codeinjections.prerollreference(actions)
+ local main = actions and pdfaction(actions)
+ if main then
+ main = pdfdictionary {
+ Subtype = pdf_link,
+ Border = pdf_border,
+ H = (not actions.highlight and pdf_n) or nil,
+ A = main,
+ -- does not work at all in spite of specification
+ -- OC = (actions.layer and lpdf.layerreferences[actions.layer]) or nil,
+ -- OC = backends.pdf.layerreference(actions.layer),
+ }
+ return main("A") -- todo: cache this, maybe weak
+ end
+end
+
+-- local cache = { } -- no real gain in thsi
+--
+-- function codeinjections.prerollreference(actions)
+-- local main = actions and pdfaction(actions)
+-- if main then
+-- main = pdfdictionary {
+-- Subtype = pdf_link,
+-- Border = pdf_border,
+-- H = (not actions.highlight and pdf_n) or nil,
+-- A = main,
+-- }
+-- local cm = cache[main]
+-- if not cm then
+-- cm = "/A ".. tostring(pdfreference(pdfimmediateobj(tostring(main))))
+-- cache[main] = cm
+-- end
+-- return cm
+-- end
+-- end
+
+function nodeinjections.reference(width,height,depth,prerolled)
+ if prerolled then
+ if swapdir then
+ width = - width
+ end
+ if trace_references then
+ logs.report("references","w=%s, h=%s, d=%s, a=%s",width,height,depth,prerolled)
+ end
+ return pdfannot(width,height,depth,prerolled)
+ end
+end
+
+function nodeinjections.destination(width,height,depth,name,view)
+ if swapdir then
+ width = - width
+ end
+ if trace_destinations then
+ logs.report("destinations","w=%s, h=%s, d=%s, n=%s, v=%s",width,height,depth,name,view or "no view")
+ end
+ return pdfdest(width,height,depth,name,view)
+end
+
+-- runners and specials
+
+local method = "internal"
+
+runners["inner"] = function(var,actions)
+ if method == "internal" then
+ local vir = var.i.references
+ local internal = vir and vir.internal
+ if internal then
+ var.inner = "aut:"..internal
+ end
+ end
+ return link(nil,nil,var.inner,var.r,actions)
+end
+
+runners["inner with arguments"] = function(var,actions)
+ return false
+end
+
+runners["outer"] = function(var,actions)
+ return link(nil,var.o,nil,nil,actions) -- var.o ?
+end
+
+runners["outer with inner"] = function(var,actions)
+ -- todo: resolve url/file name
+ return link(nil,var.f,var.inner,var.r,actions)
+end
+
+runners["special outer with operation"] = function(var,actions)
+ return false
+end
+
+runners["special outer"] = function(var,actions)
+ return false
+end
+
+runners["special"] = function(var,actions)
+ local handler = specials[var.special]
+ return handler and handler(var,actions)
+end
+
+runners["outer with inner with arguments"] = function(var,actions)
+ return false
+end
+
+runners["outer with special and operation and arguments"] = function(var,actions)
+ return false
+end
+
+runners["outer with special"] = function(var,actions)
+ return false
+end
+
+runners["outer with special and operation"] = function(var,actions)
+ return false
+end
+
+runners["special operation"] = runners["special"]
+runners["special operation with arguments"] = runners["special"]
+
+function specials.internal(var,actions)
+ local i = tonumber(var.operation)
+ local v = jobreferences.internals[i]
+ if not v then
+ -- error
+ elseif method == "internal" then
+ -- named
+ return link(nil,nil,"aut:"..i,v.references.realpage,actions)
+ else
+ -- page
+ return link(nil,nil,nil,v.references.realpage,actions)
+ end
+end
+
+specials.i = specials.internal
+
+function specials.page(var,actions)
+ local p = jobreferences.pages[var.operation]
+ if type(p) == "function" then
+ p = p()
+ end
+ return link(nil,nil,nil,p or var.operation,actions)
+end
+
+function specials.url(var,actions)
+ local url = var.operation
+ if url then
+ local u = jobreferences.urls[url]
+ if u then
+ local u, f = u[1], u[2]
+ if f and f ~= "" then
+ url = u .. "/" .. f
+ else
+ url = u
+ end
+ end
+ end
+ return link(url,nil,var.arguments,nil,actions)
+end
+
+function specials.file(var,actions)
+ local file = var.operation
+ if file then
+ local f = jobreferences.files[file]
+ if f then
+ file = f[1] or file
+ end
+ end
+ return link(nil,file,var.arguments,nil,actions)
+end
+
+function specials.program(var,content)
+ local program = var.operation
+ if program then
+ local p = jobreferences.programs[program]
+ if p then
+ program = p[1]
+ end
+ end
+ return lpdf.launch(program,var.arguments)
+end
+
+function specials.javascript(var)
+ return lpdf.javascript(var.operation,var.arguments)
+end
+
+specials.JS = specials.javascript
+
+local pdf_named = pdfconstant("Named")
+
+executers.importform = pdfdictionary { S = pdf_named, N = pdfconstant("AcroForm:ImportFDF") }
+executers.exportform = pdfdictionary { S = pdf_named, N = pdfconstant("AcroForm:ExportFDF") }
+executers.first = pdfdictionary { S = pdf_named, N = pdfconstant("FirstPage") }
+executers.previous = pdfdictionary { S = pdf_named, N = pdfconstant("PrevPage") }
+executers.next = pdfdictionary { S = pdf_named, N = pdfconstant("NextPage") }
+executers.last = pdfdictionary { S = pdf_named, N = pdfconstant("LastPage") }
+executers.backward = pdfdictionary { S = pdf_named, N = pdfconstant("GoBack") }
+executers.forward = pdfdictionary { S = pdf_named, N = pdfconstant("GoForward") }
+executers.print = pdfdictionary { S = pdf_named, N = pdfconstant("Print") }
+executers.exit = pdfdictionary { S = pdf_named, N = pdfconstant("Quit") }
+executers.close = pdfdictionary { S = pdf_named, N = pdfconstant("Close") }
+executers.save = pdfdictionary { S = pdf_named, N = pdfconstant("Save") }
+executers.savenamed = pdfdictionary { S = pdf_named, N = pdfconstant("SaveAs") }
+executers.opennamed = pdfdictionary { S = pdf_named, N = pdfconstant("Open") }
+executers.help = pdfdictionary { S = pdf_named, N = pdfconstant("HelpUserGuide") }
+executers.toggle = pdfdictionary { S = pdf_named, N = pdfconstant("FullScreen") }
+executers.search = pdfdictionary { S = pdf_named, N = pdfconstant("Find") }
+executers.searchagain = pdfdictionary { S = pdf_named, N = pdfconstant("FindAgain") }
+executers.gotopage = pdfdictionary { S = pdf_named, N = pdfconstant("GoToPage") }
+executers.query = pdfdictionary { S = pdf_named, N = pdfconstant("AcroSrch:Query") }
+executers.queryagain = pdfdictionary { S = pdf_named, N = pdfconstant("AcroSrch:NextHit") }
+executers.fitwidth = pdfdictionary { S = pdf_named, N = pdfconstant("FitWidth") }
+executers.fitheight = pdfdictionary { S = pdf_named, N = pdfconstant("FitHeight") }
+
+local function fieldset(arguments)
+ -- [\dogetfieldset{#1}]
+ return nil
+end
+
+function executers.resetform(arguments)
+ arguments = (type(arguments) == "table" and arguments) or aux.settings_to_array(arguments)
+ return pdfdictionary {
+ S = pdfconstant("ResetForm"),
+ Field = fieldset(arguments[1])
+ }
+end
+
+local formmethod = "post" -- "get" "post"
+local formformat = "xml" -- "xml" "html" "fdf"
+
+-- bit 3 = html bit 6 = xml bit 4 = get
+
+local flags = {
+ get = {
+ html = 12, fdf = 8, xml = 40,
+ },
+ post = {
+ html = 4, fdf = 0, xml = 32,
+ }
+}
+
+function executers.submitform(arguments)
+ arguments = (type(arguments) == "table" and arguments) or aux.settings_to_array(arguments)
+ local flag = flags[formmethod] or flags.post
+ flag = (flag and (flag[formformat] or flag.xml)) or 32 -- default: post, xml
+ return pdfdictionary {
+ S = pdfconstant("ResetForm"),
+ F = fieldset(arguments[1]),
+ Field = fieldset(arguments[2]),
+ Flags = flag,
+ -- \PDFsubmitfiller
+ }
+end
+
+function executers.hide(arguments)
+ return pdfdictionary {
+ S = pdfconstant("Hide"),
+ H = true,
+ T = arguments,
+ }
+end
+
+function executers.show(arguments)
+ return pdfdictionary {
+ S = pdfconstant("Hide"),
+ H = false,
+ T = arguments,
+ }
+end
+
+local pdf_movie = pdfconstant("Movie")
+local pdf_start = pdfconstant("Start")
+local pdf_stop = pdfconstant("Stop")
+local pdf_resume = pdfconstant("Resume")
+local pdf_pause = pdfconstant("Pause")
+
+local function movie_or_sound(operation,arguments)
+ arguments = (type(arguments) == "table" and arguments) or aux.settings_to_array(arguments)
+ return pdfdictionary {
+ S = pdf_movie,
+ T = format("movie %s",arguments[1] or "noname"),
+ Operation = operation,
+ }
+end
+
+function executers.startmovie (arguments) return movie_or_sound(pdf_start ,arguments) end
+function executers.stopmovie (arguments) return movie_or_sound(pdf_stop ,arguments) end
+function executers.resumemovie(arguments) return movie_or_sound(pdf_resume,arguments) end
+function executers.pausemovie (arguments) return movie_or_sound(pdf_pause ,arguments) end
+
+function executers.startsound (arguments) return movie_or_sound(pdf_start ,arguments) end
+function executers.stopsound (arguments) return movie_or_sound(pdf_stop ,arguments) end
+function executers.resumesound(arguments) return movie_or_sound(pdf_resume,arguments) end
+function executers.pausesound (arguments) return movie_or_sound(pdf_pause ,arguments) end
+
+function specials.action(var)
+ local operation = var.operation
+ if var.operation and operation ~= "" then
+ local e = executers[operation]
+ if type(e) == "table" then
+ return e
+ elseif type(e) == "function" then
+ return e(var.arguments)
+ end
+ end
+end
+
+--~ entry.A = pdfdictionary {
+--~ S = pdfconstant("GoTo"),
+--~ D = ....
+--~ }
+
+local function build(levels,start,parent,method)
+ local startlevel = levels[start][1]
+ local i, n = start, 0
+ local child, entry, m, prev, first, last, f, l
+-- to be tested: i can be nil
+ while i and i <= #levels do
+ local li = levels[i]
+ local level, title, reference, open = li[1], li[2], li[3], li[4]
+ if level == startlevel then
+ if trace_bookmarks then
+ logs.report("bookmark","%3i %s%s %s",realpage,rep(" ",level-1),(open and "+") or "-",title)
+ end
+ local prev = child
+ child = pdfreserveobj()
+ if entry then
+ entry.Next = child and pdfreference(child)
+ pdfimmediateobj(prev,tostring(entry))
+ end
+ entry = pdfdictionary {
+ Title = pdfunicode(title),
+ Parent = parent,
+ Prev = prev and pdfreference(prev),
+ }
+ if method == "internal" then
+ entry.Dest = "aut:" .. reference.internal
+ else -- if method == "page" then
+ entry.Dest = pagedest(reference.realpage)
+ end
+ if not first then first, last = child, child end
+ prev = child
+ last = prev
+ n = n + 1
+ i = i + 1
+ elseif level < startlevel then
+ pdfimmediateobj(child,tostring(entry))
+ return i, n, first, last
+ elseif i < #levels and level > startlevel then
+ i, m, f, l = build(levels,i,pdfreference(child),method)
+ entry.Count = (open and m) or -m
+ if m > 0 then
+ entry.First, entry.Last = pdfreference(f), pdfreference(l)
+ end
+ else
+ -- missing intermediate level but ok
+ i, m, f, l = build(levels,i,pdfreference(child),method)
+ entry.Count = (open and m) or -m
+ if m > 0 then
+ entry.First, entry.Last = pdfreference(f), pdfreference(l)
+ end
+ pdfimmediateobj(child,tostring(entry))
+ return i, n, first, last
+ end
+ end
+ pdfimmediateobj(child,tostring(entry))
+ return nil, n, first, last
+end
+
+function codeinjections.addbookmarks(levels,method)
+ local parent = pdfreserveobj()
+ local _, m, first, last = build(levels,1,pdfreference(parent),method or "internal")
+ local dict = pdfdictionary {
+ Type = pdfconstant("Outlines"),
+ First = pdfreference(first),
+ Last = pdfreference(last),
+ Count = m,
+ }
+ pdfimmediateobj(parent,tostring(dict))
+ lpdf.addtocatalog("Outlines",lpdf.reference(parent))
+end