summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkxl/pack-obj.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkxl/pack-obj.lmt')
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/pack-obj.lmt305
1 files changed, 305 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkxl/pack-obj.lmt b/Master/texmf-dist/tex/context/base/mkxl/pack-obj.lmt
new file mode 100644
index 00000000000..f021339b472
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/pack-obj.lmt
@@ -0,0 +1,305 @@
+if not modules then modules = { } end modules ['pack-obj'] = {
+ version = 1.001,
+ comment = "companion to pack-obj.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>We save object references in the main utility table. jobobjects are
+reusable components.</p>
+--ldx]]--
+
+local context = context
+local codeinjections = backends.codeinjections
+local ctx_doifelse = commands.doifelse
+
+local report = logs.reporter("objects")
+local trace = false trackers.register("objects",function(v) trace = v end)
+
+local nuts = nodes.nuts
+
+local setlink = nuts.setlink
+local getlist = nuts.getlist
+local setbox = nuts.setbox
+
+local new_latelua = nuts.pool.latelua
+
+local settexdimen = tokens.setters.dimen
+
+local getcount = tex.getcount
+
+local implement = interfaces.implement
+local setmacro = interfaces.setmacro
+
+local allocate = utilities.storage.allocate
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local jobobjects = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.objects = jobobjects
+
+local function initializer()
+ collected = jobobjects.collected
+ tobesaved = jobobjects.tobesaved
+end
+
+job.register('job.objects.collected', tobesaved, initializer, nil)
+
+local function saveobject(tag,number,page)
+ local data = { number, page }
+ tobesaved[tag] = data
+ collected[tag] = data
+end
+
+local function saveobjectspec(specification)
+ local tag = specification.tag
+ local data = { specification.number, specification.page }
+ tobesaved[tag] = data
+ collected[tag] = data
+end
+
+local function setobject(tag,number,page)
+ collected[tag] = { number, page }
+end
+
+local function getobject(tag)
+ return collected[tag] or tobesaved[tag]
+end
+
+local function getobjectnumber(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ return o and o[1] or default
+end
+
+local function getobjectpage(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ return o and o[2] or default
+end
+
+jobobjects.save = saveobject
+jobobjects.set = setobject
+jobobjects.get = getobject
+jobobjects.number = getobjectnumber
+jobobjects.page = getobjectpage
+
+-- implement {
+-- name = "saveobject",
+-- actions = saveobject
+-- }
+--
+-- implement {
+-- name = "setobject",
+-- actions = setobject,
+-- arguments = { "string", "integer", "integer" }
+-- }
+--
+-- implement {
+-- name = "objectnumber",
+-- actions = { getobjectnumber, context },
+-- arguments = "2 strings",
+-- }
+--
+-- implement {
+-- name = "objectpage",
+-- actions = { getobjectpage, context },
+-- arguments = "2 strings",
+-- }
+--
+-- implement {
+-- name = "doifelseobjectreferencefound",
+-- actions = { getobject, commands.doifelse },
+-- arguments = "string"
+-- }
+
+-- if false then
+-- -- we can flush the inline ref ourselves now if we want
+-- local flush = new_latelua("pdf.flushxform("..index..")")
+-- flush.next = list
+-- next.prev = flush
+-- end
+
+local data = table.setmetatableindex("table")
+
+objects = {
+ data = data,
+ n = 0,
+}
+
+local objects = objects
+
+function objects.register(ns,id,b,referenced,offset,mode)
+ local n = objects.n + 1
+ objects.n = n
+ nodes.handlers.finalizebox(b)
+ if mode == 0 then
+ -- tex
+ data[ns][id] = {
+ codeinjections.registerboxresource(b), -- a box number
+ offset,
+ referenced or false,
+ mode,
+ }
+ else
+ -- box (backend)
+ data[ns][id] = {
+ codeinjections.registerboxresource(b,offset), -- a box number
+ false,
+ referenced,
+ mode,
+ }
+ end
+ if trace then
+ report("registering object %a (n=%i)",id,n)
+ end
+end
+
+function objects.restore(ns,id) -- why not just pass a box number here too (ok, we also set offset)
+ local d = data[ns][id]
+ if d then
+ local index = d[1]
+ local offset = d[2]
+ local status = d[3]
+ local mode = d[4]
+ local hbox = codeinjections.restoreboxresource(index) -- a nut !
+ if status then
+ local list = getlist(hbox)
+ local page = new_latelua {
+ action = saveobjectspec,
+ tag = ns .. "::" .. id,
+ number = index,
+ page = getcount("realpageno"),
+ }
+ -- list is a rule
+ setlink(list,page)
+ end
+ setbox("objectbox",hbox)
+ settexdimen("objectoff",offset or 0)
+ else
+ setbox("objectbox",nil)
+ settexdimen("objectoff",0) -- for good old times
+ end
+ if trace then
+ report("restoring object %a",id)
+ end
+end
+
+function objects.dimensions(index)
+ local d = data[ns][id]
+ if d then
+ return codeinjections.boxresourcedimensions(d[1])
+ else
+ return 0, 0, 0, 0
+ end
+end
+
+function objects.reference(ns,id)
+ local d = data[ns][id]
+ if d then
+ return d[1]
+ else
+ return getobjectnumber(ns .."::" .. id,0)
+ end
+end
+
+function objects.page(ns,id)
+ return getobjectpage(ns .."::" .. id,getcount("realpageno"))
+end
+
+function objects.found(ns,id)
+ return data[ns][id]
+end
+
+implement {
+ name = "registerreferencedobject",
+ arguments = { "string", "string", "integer", true, "dimension", "integer" },
+ actions = objects.register,
+}
+
+implement {
+ name = "registerobject",
+ arguments = { "string", "string", "integer", false, "dimension", "integer" },
+ actions = objects.register,
+}
+
+implement {
+ name = "restoreobject",
+ arguments = "2 strings",
+ actions = objects.restore,
+}
+
+implement {
+ name = "doifelseobjectfound",
+ arguments = "2 arguments",
+ public = true,
+ protected = true,
+ actions = function(ns,id)
+ ctx_doifelse(data[ns][id])
+ -- ctx_doifelse(objects.reference(ns,id))
+ end,
+}
+
+implement {
+ name = "doifelseobjectreferencefound",
+ arguments = "2 arguments",
+ public = true,
+ protected = true,
+ actions = function(ns,id)
+ -- ctx_doifelse(data[ns][id])
+ ctx_doifelse(objects.reference(ns,id))
+ end,
+}
+
+implement {
+ name = "getobjectreference",
+ arguments = { "argument", "argument", "csname" },
+ public = true,
+ protected = true,
+ actions = function(ns,id,target)
+ setmacro(target,objects.reference(ns,id),"global")
+ end
+}
+
+implement {
+ name = "getobjectreferencepage",
+ arguments = { "argument", "argument", "csname" },
+ public = true,
+ protected = true,
+ actions = function(ns,id,target)
+ setmacro(target,objects.page(ns,id),"global")
+ end
+}
+
+implement {
+ name = "getobjectdimensions",
+ arguments = "2 arguments",
+ public = true,
+ protected = true,
+ actions = function(ns,id)
+ local object = data[ns][id]
+ local w, h, d, o = 0, 0, 0, 0
+ if object then
+ w, h, d, o = codeinjections.boxresourcedimensions(object[1])
+ end
+ settexdimen("objectwd",w or 0)
+ settexdimen("objectht",h or 0)
+ settexdimen("objectdp",d or 0)
+ settexdimen("objectoff",o or #objects > 2 and object[2] or 0)
+ end
+}
+
+-- for the moment here:
+
+implement {
+ name = "registerbackendsymbol",
+ arguments = { "string", "integer" },
+ actions = function(...)
+ codeinjections.registersymbol(...)
+ end
+}